import Select, { components } from "react-select"; import { __ } from "@wordpress/i18n"; import { Button, Popover, RangeControl, Flex, Tooltip } from "@wordpress/components"; import { useEffect, useRef, useState } from "@wordpress/element"; import SPRangeControl from "../rangeControl/rangeControl.js"; import ComponentsTopSection from "../componentsTopControl/ComponentsTopSection.js"; import { EditIcon } from "./svgIcon.js"; import "./editor.scss"; import SelectField from "../selectField/selectField.js"; import { fontWeightMap, getFontSizePresets, getFontWeightList, getGlobalTypoPresets, textCaseOptions, textDecorationOptions, } from "./utility.js"; import InputControl from "../inputControl/inputControl.js"; import { useDeviceType } from "../../controls/controls.js"; import Divider from "../divider/divider.js"; import classNames from "classnames"; import { BorderIcon, GlobalIcon } from "../../icons/icons.js"; import { dispatch, useSelect, select } from "@wordpress/data"; import useGoogleFonts from "../../hooks/useGoogleFontApi.js"; const TypographyNew = ({ setAttributes, attributes, fontSizeDefault = { unit: "px", value: 16 }, lineDefaultValue = "", typographyLabel = "Typography", fontSizePresetType = "body", onStateUpdate = false, }) => { 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 { family, familyKey, fontSize, fontSizeKey, lineHeight, lineHeightKey, fontSpacing, fontSpacingKey, wordSpacing, wordSpacingKey, globalTypo, globalTypoKey, } = attributes; const deviceType = useDeviceType(); const fontSizePresets = getFontSizePresets(fontSizePresetType); const globalTypoOptions = !onStateUpdate ? getGlobalTypoPresets() : {}; const [isVisible, setIsVisible] = useState(false); const [isCustomFontSize, setIsCustomFontSize] = useState( (!fontSizePresets?.find((preset) => preset?.value === fontSize?.device?.[deviceType]) && fontSize?.device?.[deviceType] !== "") || false ); const typoBtnRef = useRef(null); const openPluginSidebar = () => { const sidebarName = "smart-post-show-pro-global-settings/sidebar"; if (select("core/edit-site")) { dispatch("core/edit-site").openGeneralSidebar(sidebarName); } else if (select("core/edit-post")) { dispatch("core/edit-post").openGeneralSidebar(sidebarName); } else if (select("core/customize-widgets")) { dispatch("core/customize-widgets").openGeneralSidebar(sidebarName); } else { console.log("Could not determine current editor type"); } }; const toggleVisible = () => { setIsVisible((state) => !state); }; const { googleFonts } = useGoogleFonts(); const rendKey = () => { return Math.random().toString(36).substring(2, 9); }; 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); let variantsArray = []; if (variants?.length > 0) { variantsArray = variants?.length === 1 ? variants[0]?.split(" ") : variants; } else { variantsArray = ["300", "400", "500", "600", "700", "800"]; } return { label: f.name, value: f.fontFamily, font: { family: f.fontFamily, variants: variantsArray, }, }; }); } 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, allFonts]); 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, }, ]); }; const typoBtnActiveClass = `.sp-${rendKey()}`; useEffect(() => { const clickOutSite = (e) => { const target = e.target.closest(".sp-smart-post-typography-fonts"); const buttonTarget = e.target.closest(`.sp-smart-post-typography-trigger button${typoBtnActiveClass}`); const familyTarget = e.target.closest(".css-1nmdiq5-menu"); if (!target && isVisible && !buttonTarget && !familyTarget && !typoBtnRef.current?.contains(e.target)) { setIsVisible(false); } }; window.addEventListener("click", clickOutSite); return () => window.removeEventListener("click", clickOutSite); }); // default and active family options. const defaultFamilyOption = { label: "Default", value: "Default", font: { family: "Default", variants: ["300", "400", "500", "600", "700", "800"], }, }; const activeFontFamily = family.typography.family === "" ? defaultFamilyOption : { label: allFonts?.find((font) => font.value === family.typography.family)?.label || family.typography.family, value: family.googleFont?.family, font: family.googleFont, }; const allFamilyList = [defaultFamilyOption, ...fontLists]; const isAvailableOnList = allFamilyList?.find((font) => font.value === activeFontFamily.value); const fontFamilySelectOptions = isAvailableOnList ? allFamilyList : [defaultFamilyOption, activeFontFamily, ...fontLists]; // font family. const { fontWeight, style } = family.typography; const onChangeFontStyle = (fontStyle) => { const arrayOfStyles = fontWeightMap[fontStyle]?.split(" "); const _style = fontWeightMap[fontStyle].includes("italic") ? "italic" : ""; const _fontWeight = arrayOfStyles[arrayOfStyles?.length - 1]; if (onStateUpdate) { onStateUpdate(familyKey, { ...family, typography: { ...family.typography, fontWeight: _fontWeight, style: _style, }, }); return; } setAttributes({ [familyKey]: { ...family, typography: { ...family.typography, fontWeight: _fontWeight, style: _style, }, }, }); }; const onChangeFontSize = (newValue) => { setAttributes({ [fontSizeKey]: { ...fontSize, device: { ...fontSize?.device, [deviceType]: newValue.value, }, unit: { ...fontSize.unit, [deviceType]: fontSize?.unit?.[deviceType] ? fontSize?.unit?.[deviceType] : fontSizeDefault.unit, }, }, }); }; const onChangeTextStyles = (key, value) => { const newValue = family?.typography[key] === value ? "" : value; if (onStateUpdate) { onStateUpdate(familyKey, { ...family, typography: { ...family.typography, [key]: newValue, }, }); return; } setAttributes({ [familyKey]: { ...family, typography: { ...family.typography, [key]: newValue, }, }, }); }; const onChangeLineHeight = (newValue) => { if (onStateUpdate) { onStateUpdate(lineHeightKey, { ...lineHeight, value: newValue?.value }); } else { setAttributes({ [lineHeightKey]: { ...lineHeight, device: { ...lineHeight.device, [newValue.deviceType]: newValue?.value }, }, }); } }; const onGlobalTypoChange = (value) => { // reset typography setAttributes({ [globalTypoKey]: value, [fontSizeKey]: { ...fontSize, device: { Desktop: value.fontSize, Tablet: value.fontSize, Mobile: value.fontSize, }, unit: { Desktop: "", Tablet: "", Mobile: "", }, }, [lineHeightKey]: { ...lineHeight, device: { Desktop: value.lineHeight, Tablet: value.lineHeight, Mobile: value.lineHeight, }, unit: { Desktop: "", Tablet: "", Mobile: "", }, }, [familyKey]: { ...family, typography: { ...family.typography, family: "", fontWeight: "", style: "", transform: "", decoration: "", }, }, [fontSpacingKey]: { ...fontSpacing, device: { Desktop: 0, Tablet: 0, Mobile: 0, }, }, [wordSpacingKey]: { ...wordSpacing, device: { Desktop: 0, Tablet: 0, Mobile: 0, }, }, }); }; const activeGlobalTypo = globalTypo?.length === 0 ? { label: "Default", value: "" } : globalTypo; return (
{typographyLabel}