import { useRef, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useTranslation } from "react-i18next"; import Head from "next/head"; import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; import IconButton from "@mui/material/IconButton"; import AddIcon from "@mui/icons-material/Add"; import { fonts as initialFonts, Font } from "./fonts"; import { setFont, setIsVariable } from "./labSlice"; import { RootState } from "./reducers"; import { LabState } from "./labSlice"; import { SelectButton } from "../../components/SelectButton"; import { addStyle } from "../../lib/utils"; let idNum = 0; export const generateId = () => `c${++idNum}`; export const fileTypes: { [key: string]: string; } = { ttf: "truetype", woff: "woff", woff2: "woff2", otf: "opentype", } as const; // TODO: add a feature for uploading custom fonts export function FontPanel() { const { t } = useTranslation(undefined, {keyPrefix: 'lab'}); const dispatch = useDispatch(); const [fonts, setFonts] = useState>(initialFonts); const labState: LabState = useSelector( (state: RootState) => state.labReducer, (prev, next) => prev.font === next.font, ); const { font: selectedFont } = labState; const inputFontFile = useRef(null); const handleInputFontFileChange = ( e: React.ChangeEvent, ) => { let file: globalThis.File | null = null; if (e.target !== null && e.target.files !== null && e.target.files.length) { file = e.target.files[0]; } if (!file) { return; } const url = window.URL.createObjectURL(file); const familyParts = file.name.split("."); familyParts.splice(-1, 0, generateId()); const family = familyParts.join("-"); const fileExt = String(file.name.split(".").pop()); const fileType = fileTypes[fileExt]; if (Object.keys(fileTypes).indexOf(fileExt) === -1) { alert("Wrong file type!"); return; } addStyle(` @font-face { font-family: '${family}'; src: url('${url}') format("${fileType}"); font-weight: 400; font-style: normal; } `); const font = { family: family, cssFamily: family, cssURL: "", isVariable: false, }; setFonts([font, ...fonts]); dispatch(setFont(font)); }; return ( <> { if (inputFontFile.current !== null) { inputFontFile.current.click(); } }} size="large" title="Add a font" > {fonts.map((font) => ( { dispatch(setFont(font)); dispatch(setIsVariable(font.isVariable)); }} sx={{ whiteSpace: "nowrap", minWidth: "max-content", px: 2, }} > {t(font.family)} ))} result + `.${type},`, "", )} /> ); }