// packages/block-editor/src/components/global-styles/typography-panel.js
import {
  FontSizePicker,
  __experimentalNumberControl as NumberControl,
  __experimentalToolsPanel as ToolsPanel,
  __experimentalToolsPanelItem as ToolsPanelItem,
  Notice
} from "@wordpress/components";
import { __ } from "@wordpress/i18n";
import { useCallback, useMemo, useEffect } from "@wordpress/element";
import { getValueFromVariable } from "@wordpress/global-styles-engine";
import FontFamilyControl from "../font-family";
import FontAppearanceControl from "../font-appearance-control";
import LineHeightControl from "../line-height-control";
import LetterSpacingControl from "../letter-spacing-control";
import TextAlignmentControl from "../text-alignment-control";
import TextTransformControl from "../text-transform-control";
import TextDecorationControl from "../text-decoration-control";
import WritingModeControl from "../writing-mode-control";
import { useToolsPanelDropdownMenuProps } from "./utils";
import { setImmutably } from "../../utils/object";
import {
  getMergedFontFamiliesAndFontFamilyFaces,
  findNearestStyleAndWeight
} from "./typography-utils";
import { jsx, jsxs } from "react/jsx-runtime";
var MIN_TEXT_COLUMNS = 1;
var MAX_TEXT_COLUMNS = 6;
function useHasTypographyPanel(settings) {
  const hasFontFamily = useHasFontFamilyControl(settings);
  const hasLineHeight = useHasLineHeightControl(settings);
  const hasFontAppearance = useHasAppearanceControl(settings);
  const hasLetterSpacing = useHasLetterSpacingControl(settings);
  const hasTextAlign = useHasTextAlignmentControl(settings);
  const hasTextTransform = useHasTextTransformControl(settings);
  const hasTextDecoration = useHasTextDecorationControl(settings);
  const hasWritingMode = useHasWritingModeControl(settings);
  const hasTextColumns = useHasTextColumnsControl(settings);
  const hasFontSize = useHasFontSizeControl(settings);
  return hasFontFamily || hasLineHeight || hasFontAppearance || hasLetterSpacing || hasTextAlign || hasTextTransform || hasFontSize || hasTextDecoration || hasWritingMode || hasTextColumns;
}
function useHasFontSizeControl(settings) {
  return settings?.typography?.defaultFontSizes !== false && settings?.typography?.fontSizes?.default?.length || settings?.typography?.fontSizes?.theme?.length || settings?.typography?.fontSizes?.custom?.length || settings?.typography?.customFontSize;
}
function useHasFontFamilyControl(settings) {
  return ["default", "theme", "custom"].some(
    (key) => settings?.typography?.fontFamilies?.[key]?.length
  );
}
function useHasLineHeightControl(settings) {
  return settings?.typography?.lineHeight;
}
function useHasAppearanceControl(settings) {
  return settings?.typography?.fontStyle || settings?.typography?.fontWeight;
}
function useAppearanceControlLabel(settings) {
  if (!settings?.typography?.fontStyle) {
    return __("Font weight");
  }
  if (!settings?.typography?.fontWeight) {
    return __("Font style");
  }
  return __("Appearance");
}
function useHasLetterSpacingControl(settings) {
  return settings?.typography?.letterSpacing;
}
function useHasTextTransformControl(settings) {
  return settings?.typography?.textTransform;
}
function useHasTextAlignmentControl(settings) {
  return settings?.typography?.textAlign;
}
function useHasTextDecorationControl(settings) {
  return settings?.typography?.textDecoration;
}
function useHasWritingModeControl(settings) {
  return settings?.typography?.writingMode;
}
function useHasTextColumnsControl(settings) {
  return settings?.typography?.textColumns;
}
function getMergedFontSizes(settings) {
  const fontSizes = settings?.typography?.fontSizes;
  const defaultFontSizesEnabled = !!settings?.typography?.defaultFontSizes;
  return [
    ...fontSizes?.custom ?? [],
    ...fontSizes?.theme ?? [],
    ...defaultFontSizesEnabled ? fontSizes?.default ?? [] : []
  ];
}
function TypographyToolsPanel({
  resetAllFilter,
  onChange,
  value,
  panelId,
  children
}) {
  const dropdownMenuProps = useToolsPanelDropdownMenuProps();
  const resetAll = () => {
    const updatedValue = resetAllFilter(value);
    onChange(updatedValue);
  };
  return /* @__PURE__ */ jsx(
    ToolsPanel,
    {
      label: __("Typography"),
      resetAll,
      panelId,
      dropdownMenuProps,
      children
    }
  );
}
var DEFAULT_CONTROLS = {
  fontFamily: true,
  fontSize: true,
  fontAppearance: true,
  lineHeight: true,
  letterSpacing: true,
  textAlign: true,
  textTransform: true,
  textDecoration: true,
  writingMode: true,
  textColumns: true
};
function TypographyPanel({
  as: Wrapper = TypographyToolsPanel,
  value,
  onChange,
  inheritedValue = value,
  settings,
  panelId,
  defaultControls = DEFAULT_CONTROLS,
  fitText = false
}) {
  const decodeValue = (rawValue) => getValueFromVariable({ settings }, "", rawValue);
  const hasFontFamilyEnabled = useHasFontFamilyControl(settings);
  const fontFamily = decodeValue(inheritedValue?.typography?.fontFamily);
  const { fontFamilies, fontFamilyFaces } = useMemo(() => {
    return getMergedFontFamiliesAndFontFamilyFaces(settings, fontFamily);
  }, [settings, fontFamily]);
  const setFontFamily = (newValue) => {
    const slug = fontFamilies?.find(
      ({ fontFamily: f }) => f === newValue
    )?.slug;
    onChange(
      setImmutably(
        value,
        ["typography", "fontFamily"],
        slug ? `var:preset|font-family|${slug}` : newValue || void 0
      )
    );
  };
  const hasFontFamily = () => !!value?.typography?.fontFamily;
  const resetFontFamily = () => setFontFamily(void 0);
  const hasFontSizeEnabled = useHasFontSizeControl(settings);
  const disableCustomFontSizes = !settings?.typography?.customFontSize;
  const mergedFontSizes = getMergedFontSizes(settings);
  const fontSize = decodeValue(inheritedValue?.typography?.fontSize);
  const currentFontSizeSlug = (() => {
    const rawValue = inheritedValue?.typography?.fontSize;
    if (!rawValue || typeof rawValue !== "string") {
      return void 0;
    }
    if (rawValue.startsWith("var:preset|font-size|")) {
      return rawValue.replace("var:preset|font-size|", "");
    }
    const cssVarMatch = rawValue.match(
      /^var\(--wp--preset--font-size--([^)]+)\)$/
    );
    if (cssVarMatch) {
      return cssVarMatch[1];
    }
    return void 0;
  })();
  const setFontSize = (newValue, metadata) => {
    const actualValue = !!metadata?.slug ? `var:preset|font-size|${metadata?.slug}` : newValue;
    onChange(
      setImmutably(
        value,
        ["typography", "fontSize"],
        actualValue || void 0
      )
    );
  };
  const hasFontSize = () => !!value?.typography?.fontSize;
  const resetFontSize = () => setFontSize(void 0);
  const hasAppearanceControl = useHasAppearanceControl(settings);
  const appearanceControlLabel = useAppearanceControlLabel(settings);
  const hasFontStyles = settings?.typography?.fontStyle;
  const hasFontWeights = settings?.typography?.fontWeight;
  const fontStyle = decodeValue(inheritedValue?.typography?.fontStyle);
  const fontWeight = decodeValue(inheritedValue?.typography?.fontWeight);
  const { nearestFontStyle, nearestFontWeight } = findNearestStyleAndWeight(
    fontFamilyFaces,
    fontStyle,
    fontWeight
  );
  const setFontAppearance = useCallback(
    ({ fontStyle: newFontStyle, fontWeight: newFontWeight }) => {
      if (newFontStyle !== fontStyle || newFontWeight !== fontWeight) {
        onChange({
          ...value,
          typography: {
            ...value?.typography,
            fontStyle: newFontStyle || void 0,
            fontWeight: newFontWeight || void 0
          }
        });
      }
    },
    [fontStyle, fontWeight, onChange, value]
  );
  const hasFontAppearance = () => !!value?.typography?.fontStyle || !!value?.typography?.fontWeight;
  const resetFontAppearance = useCallback(() => {
    setFontAppearance({});
  }, [setFontAppearance]);
  useEffect(() => {
    if (nearestFontStyle && nearestFontWeight) {
      setFontAppearance({
        fontStyle: nearestFontStyle,
        fontWeight: nearestFontWeight
      });
    } else {
      resetFontAppearance();
    }
  }, [
    nearestFontStyle,
    nearestFontWeight,
    resetFontAppearance,
    setFontAppearance
  ]);
  const hasLineHeightEnabled = useHasLineHeightControl(settings);
  const lineHeight = decodeValue(inheritedValue?.typography?.lineHeight);
  const setLineHeight = (newValue) => {
    onChange(
      setImmutably(
        value,
        ["typography", "lineHeight"],
        newValue || void 0
      )
    );
  };
  const hasLineHeight = () => value?.typography?.lineHeight !== void 0;
  const resetLineHeight = () => setLineHeight(void 0);
  const hasLetterSpacingControl = useHasLetterSpacingControl(settings);
  const letterSpacing = decodeValue(
    inheritedValue?.typography?.letterSpacing
  );
  const setLetterSpacing = (newValue) => {
    onChange(
      setImmutably(
        value,
        ["typography", "letterSpacing"],
        newValue || void 0
      )
    );
  };
  const hasLetterSpacing = () => !!value?.typography?.letterSpacing;
  const resetLetterSpacing = () => setLetterSpacing(void 0);
  const hasTextColumnsControl = useHasTextColumnsControl(settings);
  const textColumns = decodeValue(inheritedValue?.typography?.textColumns);
  const setTextColumns = (newValue) => {
    onChange(
      setImmutably(
        value,
        ["typography", "textColumns"],
        newValue || void 0
      )
    );
  };
  const hasTextColumns = () => !!value?.typography?.textColumns;
  const resetTextColumns = () => setTextColumns(void 0);
  const hasTextTransformControl = useHasTextTransformControl(settings);
  const textTransform = decodeValue(
    inheritedValue?.typography?.textTransform
  );
  const setTextTransform = (newValue) => {
    onChange(
      setImmutably(
        value,
        ["typography", "textTransform"],
        newValue || void 0
      )
    );
  };
  const hasTextTransform = () => !!value?.typography?.textTransform;
  const resetTextTransform = () => setTextTransform(void 0);
  const hasTextDecorationControl = useHasTextDecorationControl(settings);
  const textDecoration = decodeValue(
    inheritedValue?.typography?.textDecoration
  );
  const setTextDecoration = (newValue) => {
    onChange(
      setImmutably(
        value,
        ["typography", "textDecoration"],
        newValue || void 0
      )
    );
  };
  const hasTextDecoration = () => !!value?.typography?.textDecoration;
  const resetTextDecoration = () => setTextDecoration(void 0);
  const hasWritingModeControl = useHasWritingModeControl(settings);
  const writingMode = decodeValue(inheritedValue?.typography?.writingMode);
  const setWritingMode = (newValue) => {
    onChange(
      setImmutably(
        value,
        ["typography", "writingMode"],
        newValue || void 0
      )
    );
  };
  const hasWritingMode = () => !!value?.typography?.writingMode;
  const resetWritingMode = () => setWritingMode(void 0);
  const hasTextAlignmentControl = useHasTextAlignmentControl(settings);
  const textAlign = decodeValue(inheritedValue?.typography?.textAlign);
  const setTextAlign = (newValue) => {
    onChange(
      setImmutably(
        value,
        ["typography", "textAlign"],
        newValue || void 0
      )
    );
  };
  const hasTextAlign = () => !!value?.typography?.textAlign;
  const resetTextAlign = () => setTextAlign(void 0);
  const resetAllFilter = useCallback((previousValue) => {
    return {
      ...previousValue,
      typography: {}
    };
  }, []);
  return /* @__PURE__ */ jsxs(
    Wrapper,
    {
      resetAllFilter,
      value,
      onChange,
      panelId,
      children: [
        hasFontFamilyEnabled && /* @__PURE__ */ jsx(
          ToolsPanelItem,
          {
            label: __("Font"),
            hasValue: hasFontFamily,
            onDeselect: resetFontFamily,
            isShownByDefault: defaultControls.fontFamily,
            panelId,
            children: /* @__PURE__ */ jsx(
              FontFamilyControl,
              {
                fontFamilies,
                value: fontFamily,
                onChange: setFontFamily,
                size: "__unstable-large"
              }
            )
          }
        ),
        hasFontSizeEnabled && !fitText && /* @__PURE__ */ jsx(
          ToolsPanelItem,
          {
            label: __("Size"),
            hasValue: hasFontSize,
            onDeselect: resetFontSize,
            isShownByDefault: defaultControls.fontSize,
            panelId,
            children: /* @__PURE__ */ jsx(
              FontSizePicker,
              {
                value: currentFontSizeSlug || fontSize,
                valueMode: currentFontSizeSlug ? "slug" : "literal",
                onChange: setFontSize,
                fontSizes: mergedFontSizes,
                disableCustomFontSizes,
                withReset: false,
                withSlider: true,
                size: "__unstable-large"
              }
            )
          }
        ),
        hasAppearanceControl && /* @__PURE__ */ jsx(
          ToolsPanelItem,
          {
            className: "single-column",
            label: appearanceControlLabel,
            hasValue: hasFontAppearance,
            onDeselect: resetFontAppearance,
            isShownByDefault: defaultControls.fontAppearance,
            panelId,
            children: /* @__PURE__ */ jsx(
              FontAppearanceControl,
              {
                value: {
                  fontStyle,
                  fontWeight
                },
                onChange: setFontAppearance,
                hasFontStyles,
                hasFontWeights,
                fontFamilyFaces,
                size: "__unstable-large"
              }
            )
          }
        ),
        hasLineHeightEnabled && /* @__PURE__ */ jsx(
          ToolsPanelItem,
          {
            className: "single-column",
            label: __("Line height"),
            hasValue: hasLineHeight,
            onDeselect: resetLineHeight,
            isShownByDefault: defaultControls.lineHeight,
            panelId,
            children: /* @__PURE__ */ jsx(
              LineHeightControl,
              {
                __unstableInputWidth: "auto",
                value: lineHeight,
                onChange: setLineHeight,
                size: "__unstable-large"
              }
            )
          }
        ),
        hasLetterSpacingControl && /* @__PURE__ */ jsx(
          ToolsPanelItem,
          {
            className: "single-column",
            label: __("Letter spacing"),
            hasValue: hasLetterSpacing,
            onDeselect: resetLetterSpacing,
            isShownByDefault: defaultControls.letterSpacing,
            panelId,
            children: /* @__PURE__ */ jsx(
              LetterSpacingControl,
              {
                value: letterSpacing,
                onChange: setLetterSpacing,
                size: "__unstable-large",
                __unstableInputWidth: "auto"
              }
            )
          }
        ),
        hasTextColumnsControl && /* @__PURE__ */ jsx(
          ToolsPanelItem,
          {
            className: "single-column",
            label: __("Columns"),
            hasValue: hasTextColumns,
            onDeselect: resetTextColumns,
            isShownByDefault: defaultControls.textColumns,
            panelId,
            children: /* @__PURE__ */ jsx(
              NumberControl,
              {
                label: __("Columns"),
                max: MAX_TEXT_COLUMNS,
                min: MIN_TEXT_COLUMNS,
                onChange: setTextColumns,
                size: "__unstable-large",
                spinControls: "custom",
                value: textColumns,
                initialPosition: 1
              }
            )
          }
        ),
        hasTextDecorationControl && /* @__PURE__ */ jsx(
          ToolsPanelItem,
          {
            className: "single-column",
            label: __("Decoration"),
            hasValue: hasTextDecoration,
            onDeselect: resetTextDecoration,
            isShownByDefault: defaultControls.textDecoration,
            panelId,
            children: /* @__PURE__ */ jsx(
              TextDecorationControl,
              {
                value: textDecoration,
                onChange: setTextDecoration,
                size: "__unstable-large",
                __unstableInputWidth: "auto"
              }
            )
          }
        ),
        hasWritingModeControl && /* @__PURE__ */ jsx(
          ToolsPanelItem,
          {
            className: "single-column",
            label: __("Orientation"),
            hasValue: hasWritingMode,
            onDeselect: resetWritingMode,
            isShownByDefault: defaultControls.writingMode,
            panelId,
            children: /* @__PURE__ */ jsx(
              WritingModeControl,
              {
                value: writingMode,
                onChange: setWritingMode,
                size: "__unstable-large",
                __nextHasNoMarginBottom: true
              }
            )
          }
        ),
        hasTextTransformControl && /* @__PURE__ */ jsx(
          ToolsPanelItem,
          {
            label: __("Letter case"),
            hasValue: hasTextTransform,
            onDeselect: resetTextTransform,
            isShownByDefault: defaultControls.textTransform,
            panelId,
            children: /* @__PURE__ */ jsx(
              TextTransformControl,
              {
                value: textTransform,
                onChange: setTextTransform,
                showNone: true,
                isBlock: true,
                size: "__unstable-large",
                __nextHasNoMarginBottom: true
              }
            )
          }
        ),
        hasTextAlignmentControl && /* @__PURE__ */ jsxs(
          ToolsPanelItem,
          {
            label: __("Text alignment"),
            hasValue: hasTextAlign,
            onDeselect: resetTextAlign,
            isShownByDefault: defaultControls.textAlign,
            panelId,
            children: [
              /* @__PURE__ */ jsx(
                TextAlignmentControl,
                {
                  value: textAlign,
                  onChange: setTextAlign,
                  options: ["left", "center", "right", "justify"],
                  size: "__unstable-large",
                  __nextHasNoMarginBottom: true
                }
              ),
              textAlign === "justify" && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Notice, { status: "warning", isDismissible: false, children: __(
                "Justified text can reduce readability. For better accessibility, use left-aligned text instead."
              ) }) })
            ]
          }
        )
      ]
    }
  );
}
export {
  TypographyPanel as default,
  useHasTypographyPanel
};
//# sourceMappingURL=typography-panel.js.map
