import Select from "react-select"; import { __ } from "@wordpress/i18n"; import { Button, Flex, Popover, Tooltip } from "@wordpress/components"; import { Fragment, useEffect, useRef, useState } from "@wordpress/element"; import ComponentsTopSection from "../componentsTopControl/ComponentsTopSection.js"; import "../typography/editor.scss"; import SelectField from "../selectField/selectField.js"; import { fontWeightMap, getFontWeightList, textCaseOptions, textDecorationOptions } from "../typography/utility.js"; import InputControl from "../inputControl/inputControl.js"; import { useDeviceType } from "../../controls/controls.js"; import { BorderIcon } from "../../icons/icons.js"; import { useSelect } from "@wordpress/data"; import useGoogleFonts from "../../hooks/useGoogleFontApi.js"; const GlobalTypography = ({ attributes, typographyLabel = "Typography", typoItem, onChangeAttr, deleteAction }) => { const fontFamilies = useSelect((select) => { const settings = select("core/editor")?.getEditorSettings(); return settings?.__experimentalFeatures?.typography?.fontFamilies || []; }, []); const [systemFonts, setSystemFonts] = useState([]); const [allFonts, setAllFonts] = useState([]); const [fontLists, setFontLists] = useState([]); const [fontInfo, setFontInfo] = useState(typoItem); const { wordSpacing } = attributes; const deviceType = useDeviceType(); const typographyBtnRef = useRef(null); const [isVisible, setIsVisible] = useState(false); const toggleVisible = () => { setIsVisible((state) => !state); if (isVisible) { onChangeAttr(fontInfo); } }; const { googleFonts } = useGoogleFonts(); useEffect(() => { if (allFonts.length === 0 && googleFonts.length > 0) { let wpFonts = []; if (fontFamilies) { const customFonts = fontFamilies.custom || []; const themeFonts = fontFamilies.theme || []; const _systemFonts = [...customFonts, ...themeFonts]; wpFonts = _systemFonts?.map((f) => { const variants = f?.fontFace?.map((v) => v.fontWeight); return { label: f.name, value: f.fontFamily, type: "system", font: { family: f.fontFamily, variants: variants?.length > 0 ? variants[0]?.split(" ") : ["300", "400", "500", "600", "700", "800"], }, }; }); } const grouped = [ ...(wpFonts.length > 0 ? [{ label: "System Fonts", options: wpFonts }] : []), { label: "Google Fonts", options: googleFonts.filter((font, i) => i < 50 && font), }, ]; setSystemFonts(wpFonts); setAllFonts([...wpFonts, ...googleFonts]); setFontLists(grouped); } }, [googleFonts, fontFamilies]); const fontSearch = (inputValue) => { if (!inputValue) { setFontLists([ ...(systemFonts.length > 0 ? [ { label: "System Fonts", options: systemFonts, }, ] : []), { label: "Google Fonts", options: googleFonts.filter((font, i) => i < 50 && font), }, ]); return; } const searchedFonts = allFonts .filter((font) => font.label.toLowerCase().includes(inputValue.toLowerCase())) .slice(0, 30); setFontLists([ { label: "Search Result", options: searchedFonts, }, ]); }; // default and active family options. const defaultFamilyOption = { label: "Default", value: "", font: { variants: ["regular"] }, }; const activeFontFamily = fontInfo.typography.family === "" ? defaultFamilyOption : { label: allFonts?.find((font) => font.value === fontInfo.typography.family)?.label || fontInfo.typography.family, value: fontInfo.typography?.family, font: fontInfo.typography.font, }; useEffect(() => { const clickOutSite = (e) => { const target = e.target.closest(".sp-smart-post-typography-fonts"); const buttonTarget = e.target.closest(`.sp-smart-post-typography-btn button.button-${fontInfo?.slug}`); const familyTarget = e.target.closest(".css-1nmdiq5-menu"); if (!target && isVisible && !buttonTarget && !familyTarget) { setIsVisible(false); onChangeAttr(fontInfo); } }; window.addEventListener("click", clickOutSite); return () => window.removeEventListener("click", clickOutSite); }); const allFamilyList = [defaultFamilyOption, ...fontLists]; const isAvailableOnList = allFamilyList?.find((font) => font.value === activeFontFamily.value); const fontFamilySelectOptions = isAvailableOnList ? allFamilyList : [defaultFamilyOption, activeFontFamily, ...fontLists]; // Set Font Family Function. const selectFontFamily = (newValue) => { const newData = { ...fontInfo, typography: { ...fontInfo.typography, family: newValue.value, type: "system" === newValue.type ? "system" : "google", font: newValue.font, fontWeight: "400", }, }; setFontInfo(newData); }; // Set font weight and font style function. const onChangeFontWeight = (fontWeight) => { const arrayOfStyles = fontWeightMap[fontWeight]?.split(" "); const style = fontWeightMap[fontWeight].includes("italic") ? "italic" : "normal"; let weight = arrayOfStyles[arrayOfStyles.length - 1]; weight = "italic" === style && "400" === weight ? "italic" : weight; const newData = { ...fontInfo, typography: { ...fontInfo.typography, fontWeight: weight, style: style, }, }; setFontInfo(newData); }; // Set font line height function. const onChangeLineHeight = (newValue) => { const newData = { ...fontInfo, lineHeight: { ...fontInfo.lineHeight, device: { ...fontInfo.lineHeight.device, [deviceType]: newValue, }, }, }; setFontInfo(newData); }; // Set letter spacing function. const letterSpacing = (newValue) => { const newData = { ...fontInfo, letterSpacing: { ...fontInfo.letterSpacing, device: { ...fontInfo.letterSpacing.device, [deviceType]: newValue, }, }, }; setFontInfo(newData); }; // Set word spacing function. const wordSpacingFn = (newValue) => { const newData = { ...fontInfo, wordSpacing: { ...fontInfo.wordSpacing, device: { ...fontInfo.wordSpacing.device, [deviceType]: newValue, }, }, }; setFontInfo(newData); }; // Set font size function. const onChangeFontSize = (newValue) => { const newData = { ...fontInfo, fontSize: { ...fontInfo.fontSize, device: { ...fontInfo.fontSize.device, [deviceType]: newValue, }, }, }; setFontInfo(newData); }; // Set unit function. const unitChange = (newUnit, key) => { const newData = { ...fontInfo, [key]: { ...fontInfo[key], unit: { ...fontInfo[key].unit, [newUnit.deviceType]: newUnit.unit, }, }, }; setFontInfo(newData); }; // Reset function. // const onReset = ( defaultValue, key ) => { // const newData = { // ...fontInfo, // [key]: { // ...fontInfo[key], // "unit": { // ...fontInfo.fontSize.unit, // "Desktop": defaultValue.unit, // }, // "device": { // ...fontInfo.fontSize.device, // "Desktop": defaultValue.value, // }, // }, // }; // setFontInfo( newData ); // }; // Set text style function. const onChangeTextStyles = (key, value) => { const newValue = fontInfo?.typography[key] === value ? "" : value; const newData = { ...fontInfo, typography: { ...fontInfo.typography, [key]: newValue }, }; setFontInfo(newData); }; // Title text change const onChangeFontTitle = (e) => { const newData = { ...fontInfo, title: e.target.value }; setFontInfo(newData); }; // Update fontSize and lineHeight const onChangeSizes = (newValue, index, key) => { const newSizes = fontInfo?.sizes?.map((size, i) => i === index ? { ...size, [key]: { ...size[key], device: { ...size[key]?.device, [deviceType]: newValue, }, }, } : size ); const newData = { ...fontInfo, sizes: newSizes }; setFontInfo(newData); }; const onChangeSizesUnit = (newValue, index, key) => { const newSizes = fontInfo?.sizes?.map((size, i) => i === index ? { ...size, [key]: { ...size[key], unit: { ...size[key]?.unit, [deviceType]: newValue?.unit, }, }, } : size ); const newData = { ...fontInfo, sizes: newSizes }; setFontInfo(newData); }; return ( <>
{typographyLabel}