( family: string, enabled = true, options?: ObserverOptions, )
| 97 | }; |
| 98 | |
| 99 | export const useFontStatus = ( |
| 100 | family: string, |
| 101 | enabled = true, |
| 102 | options?: ObserverOptions, |
| 103 | ): FontStatus => { |
| 104 | const fontFaces = useMemo<FontFace[]>(() => { |
| 105 | if (!options?.weights || options.weights.length === 0) { |
| 106 | return [{ family, style: options?.style ?? 'normal' }]; |
| 107 | } |
| 108 | |
| 109 | return options.weights.map((weight) => ({ |
| 110 | family, |
| 111 | weight, |
| 112 | style: options.style ?? 'normal', |
| 113 | })); |
| 114 | }, [family, options?.weights, options?.style]); |
| 115 | |
| 116 | const cacheKey = useMemo(() => JSON.stringify(fontFaces), [fontFaces]); |
| 117 | |
| 118 | // Load the font on mount or when font faces change. |
| 119 | useEffect(() => { |
| 120 | // Skip font loading during SSR or if the hook is not enabled. |
| 121 | if (!isClient || !enabled) { |
| 122 | return; |
| 123 | } |
| 124 | |
| 125 | triggerFontLoad(cacheKey, fontFaces); |
| 126 | }, [cacheKey, fontFaces, enabled]); |
| 127 | |
| 128 | const status = useSyncExternalStore( |
| 129 | (callback) => { |
| 130 | if (!subscribers.has(cacheKey)) { |
| 131 | subscribers.set(cacheKey, new Set()); |
| 132 | } |
| 133 | |
| 134 | // biome-ignore lint/style/noNonNullAssertion: We check existence with .has(). |
| 135 | const specificSubscribers = subscribers.get(cacheKey)!; |
| 136 | |
| 137 | specificSubscribers.add(callback); |
| 138 | |
| 139 | return () => { |
| 140 | specificSubscribers.delete(callback); |
| 141 | |
| 142 | // Clean up if no subscribers left. |
| 143 | if (specificSubscribers.size === 0) { |
| 144 | subscribers.delete(cacheKey); |
| 145 | } |
| 146 | }; |
| 147 | }, |
| 148 | () => fontStatusCache.get(cacheKey), // Client snapshot. |
| 149 | () => undefined, // Server snapshot should always be undefined (no fonts loaded on server). |
| 150 | ); |
| 151 | |
| 152 | // If not enabled, the font is neither loading nor loaded yet. |
| 153 | if (!enabled) { |
| 154 | return undefined; |
| 155 | } |
| 156 |
no test coverage detected