Created
April 16, 2024 08:13
-
-
Save steveruizok/d1bf4f05321fc127fec8a2015c4207d8 to your computer and use it in GitHub Desktop.
tldraw preload fonts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useState } from 'react' | |
export type TLTypeFace = { | |
url: string | |
display?: any // FontDisplay | |
featureSettings?: string | |
stretch?: string | |
style?: string | |
unicodeRange?: string | |
variant?: string | |
weight?: string | |
format?: string | |
} | |
export async function preloadFont(id: string, font: TLTypeFace) { | |
const { | |
url, | |
style = 'normal', | |
weight = '500', | |
display, | |
featureSettings, | |
stretch, | |
unicodeRange, | |
variant, | |
format, | |
} = font | |
const descriptors: FontFaceDescriptors = { | |
style, | |
weight, | |
display, | |
featureSettings, | |
stretch, | |
unicodeRange, | |
// @ts-expect-error why is this here | |
variant, | |
} | |
const fontInstance = new FontFace(id, `url(${url})`, descriptors) | |
await fontInstance.load() | |
document.fonts.add(fontInstance) | |
// @ts-expect-error | |
fontInstance.$$_url = url | |
// @ts-expect-error | |
fontInstance.$$_fontface = ` | |
@font-face { | |
font-family: ${fontInstance.family}; | |
font-stretch: ${fontInstance.stretch}; | |
font-weight: ${fontInstance.weight}; | |
font-style: ${fontInstance.style}; | |
src: url("${url}") format("${format}") | |
}` | |
return fontInstance | |
} | |
enum PreloadStatus { | |
SUCCESS, | |
FAILED, | |
WAITING, | |
} | |
const usePreloadFont = (id: string, font: TLTypeFace): PreloadStatus => { | |
const [state, setState] = useState<PreloadStatus>(PreloadStatus.WAITING) | |
useEffect(() => { | |
let cancelled = false | |
setState(PreloadStatus.WAITING) | |
preloadFont(id, font) | |
.then(() => { | |
if (cancelled) return | |
setState(PreloadStatus.SUCCESS) | |
}) | |
.catch((err: any) => { | |
if (cancelled) return | |
console.error(err) | |
setState(PreloadStatus.FAILED) | |
}) | |
return () => { | |
cancelled = true | |
} | |
}, [id, font]) | |
return state | |
} | |
const TYPEFACES = { | |
draw: { | |
url: `https://www.yourhost.com/Shantell_Sans-Tldrawish.woff2`, | |
format: 'woff2', | |
}, | |
serif: { | |
url: `https://www.yourhost.com/IBMPlexSerif-Medium.woff2`, | |
format: 'woff2', | |
}, | |
sansSerif: { | |
url: `https://www.yourhost.com/IBMPlexSans-Medium.woff2`, | |
format: 'woff2', | |
}, | |
monospace: { | |
url: `https://www.yourhost.com/IBMPlexMono-Medium.woff2`, | |
format: 'woff2', | |
}, | |
} | |
export function usePreloadAssets() { | |
const results = [ | |
usePreloadFont('tldraw_draw', TYPEFACES.draw), | |
usePreloadFont('tldraw_serif', TYPEFACES.serif), | |
usePreloadFont('tldraw_sans', TYPEFACES.sansSerif), | |
usePreloadFont('tldraw_mono', TYPEFACES.monospace), | |
] | |
return { | |
// If any of the results have errored, then preloading has failed | |
error: results.some((result) => result === PreloadStatus.FAILED), | |
// If any of the results are waiting, then we're not done yet | |
done: !results.some((result) => result === PreloadStatus.WAITING), | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment