"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = ColorPanel;
exports.useHasBackgroundColorPanel = useHasBackgroundColorPanel;
exports.useHasButtonPanel = useHasButtonPanel;
exports.useHasCaptionPanel = useHasCaptionPanel;
exports.useHasColorPanel = useHasColorPanel;
exports.useHasHeadingPanel = useHasHeadingPanel;
exports.useHasLinkPanel = useHasLinkPanel;
exports.useHasTextPanel = useHasTextPanel;
var _clsx = _interopRequireDefault(require("clsx"));
var _components = require("@wordpress/components");
var _element = require("@wordpress/element");
var _i18n = require("@wordpress/i18n");
var _control = _interopRequireDefault(require("../colors-gradients/control"));
var _hooks = require("./hooks");
var _utils = require("./utils");
var _object = require("../../utils/object");
var _lockUnlock = require("../../lock-unlock");
var _jsxRuntime = require("react/jsx-runtime");
/**
 * External dependencies
 */

/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

function useHasColorPanel(settings) {
  const hasTextPanel = useHasTextPanel(settings);
  const hasBackgroundPanel = useHasBackgroundColorPanel(settings);
  const hasLinkPanel = useHasLinkPanel(settings);
  const hasHeadingPanel = useHasHeadingPanel(settings);
  const hasButtonPanel = useHasButtonPanel(settings);
  const hasCaptionPanel = useHasCaptionPanel(settings);
  return hasTextPanel || hasBackgroundPanel || hasLinkPanel || hasHeadingPanel || hasButtonPanel || hasCaptionPanel;
}
function useHasTextPanel(settings) {
  const colors = (0, _hooks.useColorsPerOrigin)(settings);
  return settings?.color?.text && (colors?.length > 0 || settings?.color?.custom);
}
function useHasLinkPanel(settings) {
  const colors = (0, _hooks.useColorsPerOrigin)(settings);
  return settings?.color?.link && (colors?.length > 0 || settings?.color?.custom);
}
function useHasCaptionPanel(settings) {
  const colors = (0, _hooks.useColorsPerOrigin)(settings);
  return settings?.color?.caption && (colors?.length > 0 || settings?.color?.custom);
}
function useHasHeadingPanel(settings) {
  const colors = (0, _hooks.useColorsPerOrigin)(settings);
  const gradients = (0, _hooks.useGradientsPerOrigin)(settings);
  return settings?.color?.heading && (colors?.length > 0 || settings?.color?.custom || gradients?.length > 0 || settings?.color?.customGradient);
}
function useHasButtonPanel(settings) {
  const colors = (0, _hooks.useColorsPerOrigin)(settings);
  const gradients = (0, _hooks.useGradientsPerOrigin)(settings);
  return settings?.color?.button && (colors?.length > 0 || settings?.color?.custom || gradients?.length > 0 || settings?.color?.customGradient);
}
function useHasBackgroundColorPanel(settings) {
  const colors = (0, _hooks.useColorsPerOrigin)(settings);
  const gradients = (0, _hooks.useGradientsPerOrigin)(settings);
  return settings?.color?.background && (colors?.length > 0 || settings?.color?.custom || gradients?.length > 0 || settings?.color?.customGradient);
}
function ColorToolsPanel({
  resetAllFilter,
  onChange,
  value,
  panelId,
  children
}) {
  const dropdownMenuProps = (0, _utils.useToolsPanelDropdownMenuProps)();
  const resetAll = () => {
    const updatedValue = resetAllFilter(value);
    onChange(updatedValue);
  };
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanel, {
    label: (0, _i18n.__)('Elements'),
    resetAll: resetAll,
    panelId: panelId,
    hasInnerWrapper: true,
    headingLevel: 3,
    className: "color-block-support-panel",
    __experimentalFirstVisibleItemClass: "first",
    __experimentalLastVisibleItemClass: "last",
    dropdownMenuProps: dropdownMenuProps,
    children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
      className: "color-block-support-panel__inner-wrapper",
      children: children
    })
  });
}
const DEFAULT_CONTROLS = {
  text: true,
  background: true,
  link: true,
  heading: true,
  button: true,
  caption: true
};
const popoverProps = {
  placement: 'left-start',
  offset: 36,
  shift: true
};
const {
  Tabs
} = (0, _lockUnlock.unlock)(_components.privateApis);
const LabeledColorIndicators = ({
  indicators,
  label
}) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalHStack, {
  justify: "flex-start",
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalZStack, {
    isLayered: false,
    offset: -8,
    children: indicators.map((indicator, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Flex, {
      expanded: false,
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ColorIndicator, {
        colorValue: indicator
      })
    }, index))
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.FlexItem, {
    className: "block-editor-panel-color-gradient-settings__color-name",
    children: label
  })]
});
function ColorPanelTab({
  isGradient,
  inheritedValue,
  userValue,
  setValue,
  colorGradientControlSettings
}) {
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_control.default, {
    ...colorGradientControlSettings,
    showTitle: false,
    enableAlpha: true,
    __experimentalIsRenderedInSidebar: true,
    colorValue: isGradient ? undefined : inheritedValue,
    gradientValue: isGradient ? inheritedValue : undefined,
    onColorChange: isGradient ? undefined : setValue,
    onGradientChange: isGradient ? setValue : undefined,
    clearable: inheritedValue === userValue,
    headingLevel: 3
  });
}
function ColorPanelDropdown({
  label,
  hasValue,
  resetValue,
  isShownByDefault,
  indicators,
  tabs,
  colorGradientControlSettings,
  panelId
}) {
  var _tabs$;
  const currentTab = tabs.find(tab => tab.userValue !== undefined);
  const {
    key: firstTabKey,
    ...firstTab
  } = (_tabs$ = tabs[0]) !== null && _tabs$ !== void 0 ? _tabs$ : {};
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, {
    className: "block-editor-tools-panel-color-gradient-settings__item",
    hasValue: hasValue,
    label: label,
    onDeselect: resetValue,
    isShownByDefault: isShownByDefault,
    panelId: panelId,
    children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Dropdown, {
      popoverProps: popoverProps,
      className: "block-editor-tools-panel-color-gradient-settings__dropdown",
      renderToggle: ({
        onToggle,
        isOpen
      }) => {
        const toggleProps = {
          onClick: onToggle,
          className: (0, _clsx.default)('block-editor-panel-color-gradient-settings__dropdown', {
            'is-open': isOpen
          }),
          'aria-expanded': isOpen
        };
        return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
          __next40pxDefaultSize: true,
          ...toggleProps,
          children: /*#__PURE__*/(0, _jsxRuntime.jsx)(LabeledColorIndicators, {
            indicators: indicators,
            label: label
          })
        });
      },
      renderContent: () => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalDropdownContentWrapper, {
        paddingSize: "none",
        children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
          className: "block-editor-panel-color-gradient-settings__dropdown-content",
          children: [tabs.length === 1 && /*#__PURE__*/(0, _jsxRuntime.jsx)(ColorPanelTab, {
            ...firstTab,
            colorGradientControlSettings: colorGradientControlSettings
          }, firstTabKey), tabs.length > 1 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(Tabs, {
            defaultTabId: currentTab?.key,
            children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Tabs.TabList, {
              children: tabs.map(tab => /*#__PURE__*/(0, _jsxRuntime.jsx)(Tabs.Tab, {
                tabId: tab.key,
                children: tab.label
              }, tab.key))
            }), tabs.map(tab => {
              const {
                key: tabKey,
                ...restTabProps
              } = tab;
              return /*#__PURE__*/(0, _jsxRuntime.jsx)(Tabs.TabPanel, {
                tabId: tabKey,
                focusable: false,
                children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ColorPanelTab, {
                  ...restTabProps,
                  colorGradientControlSettings: colorGradientControlSettings
                }, tabKey)
              }, tabKey);
            })]
          })]
        })
      })
    })
  });
}
function ColorPanel({
  as: Wrapper = ColorToolsPanel,
  value,
  onChange,
  inheritedValue = value,
  settings,
  panelId,
  defaultControls = DEFAULT_CONTROLS,
  children
}) {
  const colors = (0, _hooks.useColorsPerOrigin)(settings);
  const gradients = (0, _hooks.useGradientsPerOrigin)(settings);
  const areCustomSolidsEnabled = settings?.color?.custom;
  const areCustomGradientsEnabled = settings?.color?.customGradient;
  const hasSolidColors = colors.length > 0 || areCustomSolidsEnabled;
  const hasGradientColors = gradients.length > 0 || areCustomGradientsEnabled;
  const decodeValue = rawValue => (0, _utils.getValueFromVariable)({
    settings
  }, '', rawValue);
  const encodeColorValue = colorValue => {
    const allColors = colors.flatMap(({
      colors: originColors
    }) => originColors);
    const colorObject = allColors.find(({
      color
    }) => color === colorValue);
    return colorObject ? 'var:preset|color|' + colorObject.slug : colorValue;
  };
  const encodeGradientValue = gradientValue => {
    const allGradients = gradients.flatMap(({
      gradients: originGradients
    }) => originGradients);
    const gradientObject = allGradients.find(({
      gradient
    }) => gradient === gradientValue);
    return gradientObject ? 'var:preset|gradient|' + gradientObject.slug : gradientValue;
  };

  // BackgroundColor
  const showBackgroundPanel = useHasBackgroundColorPanel(settings);
  const backgroundColor = decodeValue(inheritedValue?.color?.background);
  const userBackgroundColor = decodeValue(value?.color?.background);
  const gradient = decodeValue(inheritedValue?.color?.gradient);
  const userGradient = decodeValue(value?.color?.gradient);
  const hasBackground = () => !!userBackgroundColor || !!userGradient;
  const setBackgroundColor = newColor => {
    const newValue = (0, _object.setImmutably)(value, ['color', 'background'], encodeColorValue(newColor));
    newValue.color.gradient = undefined;
    onChange(newValue);
  };
  const setGradient = newGradient => {
    const newValue = (0, _object.setImmutably)(value, ['color', 'gradient'], encodeGradientValue(newGradient));
    newValue.color.background = undefined;
    onChange(newValue);
  };
  const resetBackground = () => {
    const newValue = (0, _object.setImmutably)(value, ['color', 'background'], undefined);
    newValue.color.gradient = undefined;
    onChange(newValue);
  };

  // Links
  const showLinkPanel = useHasLinkPanel(settings);
  const linkColor = decodeValue(inheritedValue?.elements?.link?.color?.text);
  const userLinkColor = decodeValue(value?.elements?.link?.color?.text);
  const setLinkColor = newColor => {
    onChange((0, _object.setImmutably)(value, ['elements', 'link', 'color', 'text'], encodeColorValue(newColor)));
  };
  const hoverLinkColor = decodeValue(inheritedValue?.elements?.link?.[':hover']?.color?.text);
  const userHoverLinkColor = decodeValue(value?.elements?.link?.[':hover']?.color?.text);
  const setHoverLinkColor = newColor => {
    onChange((0, _object.setImmutably)(value, ['elements', 'link', ':hover', 'color', 'text'], encodeColorValue(newColor)));
  };
  const hasLink = () => !!userLinkColor || !!userHoverLinkColor;
  const resetLink = () => {
    let newValue = (0, _object.setImmutably)(value, ['elements', 'link', ':hover', 'color', 'text'], undefined);
    newValue = (0, _object.setImmutably)(newValue, ['elements', 'link', 'color', 'text'], undefined);
    onChange(newValue);
  };

  // Text Color
  const showTextPanel = useHasTextPanel(settings);
  const textColor = decodeValue(inheritedValue?.color?.text);
  const userTextColor = decodeValue(value?.color?.text);
  const hasTextColor = () => !!userTextColor;
  const setTextColor = newColor => {
    let changedObject = (0, _object.setImmutably)(value, ['color', 'text'], encodeColorValue(newColor));
    if (textColor === linkColor) {
      changedObject = (0, _object.setImmutably)(changedObject, ['elements', 'link', 'color', 'text'], encodeColorValue(newColor));
    }
    onChange(changedObject);
  };
  const resetTextColor = () => setTextColor(undefined);

  // Elements
  const elements = [{
    name: 'caption',
    label: (0, _i18n.__)('Captions'),
    showPanel: useHasCaptionPanel(settings)
  }, {
    name: 'button',
    label: (0, _i18n.__)('Button'),
    showPanel: useHasButtonPanel(settings)
  }, {
    name: 'heading',
    label: (0, _i18n.__)('Heading'),
    showPanel: useHasHeadingPanel(settings)
  }, {
    name: 'h1',
    label: (0, _i18n.__)('H1'),
    showPanel: useHasHeadingPanel(settings)
  }, {
    name: 'h2',
    label: (0, _i18n.__)('H2'),
    showPanel: useHasHeadingPanel(settings)
  }, {
    name: 'h3',
    label: (0, _i18n.__)('H3'),
    showPanel: useHasHeadingPanel(settings)
  }, {
    name: 'h4',
    label: (0, _i18n.__)('H4'),
    showPanel: useHasHeadingPanel(settings)
  }, {
    name: 'h5',
    label: (0, _i18n.__)('H5'),
    showPanel: useHasHeadingPanel(settings)
  }, {
    name: 'h6',
    label: (0, _i18n.__)('H6'),
    showPanel: useHasHeadingPanel(settings)
  }];
  const resetAllFilter = (0, _element.useCallback)(previousValue => {
    return {
      ...previousValue,
      color: undefined,
      elements: {
        ...previousValue?.elements,
        link: {
          ...previousValue?.elements?.link,
          color: undefined,
          ':hover': {
            color: undefined
          }
        },
        ...elements.reduce((acc, element) => {
          return {
            ...acc,
            [element.name]: {
              ...previousValue?.elements?.[element.name],
              color: undefined
            }
          };
        }, {})
      }
    };
  }, []);
  const items = [showTextPanel && {
    key: 'text',
    label: (0, _i18n.__)('Text'),
    hasValue: hasTextColor,
    resetValue: resetTextColor,
    isShownByDefault: defaultControls.text,
    indicators: [textColor],
    tabs: [{
      key: 'text',
      label: (0, _i18n.__)('Text'),
      inheritedValue: textColor,
      setValue: setTextColor,
      userValue: userTextColor
    }]
  }, showBackgroundPanel && {
    key: 'background',
    label: (0, _i18n.__)('Background'),
    hasValue: hasBackground,
    resetValue: resetBackground,
    isShownByDefault: defaultControls.background,
    indicators: [gradient !== null && gradient !== void 0 ? gradient : backgroundColor],
    tabs: [hasSolidColors && {
      key: 'background',
      label: (0, _i18n.__)('Color'),
      inheritedValue: backgroundColor,
      setValue: setBackgroundColor,
      userValue: userBackgroundColor
    }, hasGradientColors && {
      key: 'gradient',
      label: (0, _i18n.__)('Gradient'),
      inheritedValue: gradient,
      setValue: setGradient,
      userValue: userGradient,
      isGradient: true
    }].filter(Boolean)
  }, showLinkPanel && {
    key: 'link',
    label: (0, _i18n.__)('Link'),
    hasValue: hasLink,
    resetValue: resetLink,
    isShownByDefault: defaultControls.link,
    indicators: [linkColor, hoverLinkColor],
    tabs: [{
      key: 'link',
      label: (0, _i18n.__)('Default'),
      inheritedValue: linkColor,
      setValue: setLinkColor,
      userValue: userLinkColor
    }, {
      key: 'hover',
      label: (0, _i18n.__)('Hover'),
      inheritedValue: hoverLinkColor,
      setValue: setHoverLinkColor,
      userValue: userHoverLinkColor
    }]
  }].filter(Boolean);
  elements.forEach(({
    name,
    label,
    showPanel
  }) => {
    if (!showPanel) {
      return;
    }
    const elementBackgroundColor = decodeValue(inheritedValue?.elements?.[name]?.color?.background);
    const elementGradient = decodeValue(inheritedValue?.elements?.[name]?.color?.gradient);
    const elementTextColor = decodeValue(inheritedValue?.elements?.[name]?.color?.text);
    const elementBackgroundUserColor = decodeValue(value?.elements?.[name]?.color?.background);
    const elementGradientUserColor = decodeValue(value?.elements?.[name]?.color?.gradient);
    const elementTextUserColor = decodeValue(value?.elements?.[name]?.color?.text);
    const hasElement = () => !!(elementTextUserColor || elementBackgroundUserColor || elementGradientUserColor);
    const resetElement = () => {
      const newValue = (0, _object.setImmutably)(value, ['elements', name, 'color', 'background'], undefined);
      newValue.elements[name].color.gradient = undefined;
      newValue.elements[name].color.text = undefined;
      onChange(newValue);
    };
    const setElementTextColor = newTextColor => {
      onChange((0, _object.setImmutably)(value, ['elements', name, 'color', 'text'], encodeColorValue(newTextColor)));
    };
    const setElementBackgroundColor = newBackgroundColor => {
      const newValue = (0, _object.setImmutably)(value, ['elements', name, 'color', 'background'], encodeColorValue(newBackgroundColor));
      newValue.elements[name].color.gradient = undefined;
      onChange(newValue);
    };
    const setElementGradient = newGradient => {
      const newValue = (0, _object.setImmutably)(value, ['elements', name, 'color', 'gradient'], encodeGradientValue(newGradient));
      newValue.elements[name].color.background = undefined;
      onChange(newValue);
    };
    const supportsTextColor = true;
    // Background color is not supported for `caption`
    // as there isn't yet a way to set padding for the element.
    const supportsBackground = name !== 'caption';
    items.push({
      key: name,
      label,
      hasValue: hasElement,
      resetValue: resetElement,
      isShownByDefault: defaultControls[name],
      indicators: supportsTextColor && supportsBackground ? [elementTextColor, elementGradient !== null && elementGradient !== void 0 ? elementGradient : elementBackgroundColor] : [supportsTextColor ? elementTextColor : elementGradient !== null && elementGradient !== void 0 ? elementGradient : elementBackgroundColor],
      tabs: [hasSolidColors && supportsTextColor && {
        key: 'text',
        label: (0, _i18n.__)('Text'),
        inheritedValue: elementTextColor,
        setValue: setElementTextColor,
        userValue: elementTextUserColor
      }, hasSolidColors && supportsBackground && {
        key: 'background',
        label: (0, _i18n.__)('Background'),
        inheritedValue: elementBackgroundColor,
        setValue: setElementBackgroundColor,
        userValue: elementBackgroundUserColor
      }, hasGradientColors && supportsBackground && {
        key: 'gradient',
        label: (0, _i18n.__)('Gradient'),
        inheritedValue: elementGradient,
        setValue: setElementGradient,
        userValue: elementGradientUserColor,
        isGradient: true
      }].filter(Boolean)
    });
  });
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Wrapper, {
    resetAllFilter: resetAllFilter,
    value: value,
    onChange: onChange,
    panelId: panelId,
    children: [items.map(item => {
      const {
        key,
        ...restItem
      } = item;
      return /*#__PURE__*/(0, _jsxRuntime.jsx)(ColorPanelDropdown, {
        ...restItem,
        colorGradientControlSettings: {
          colors,
          disableCustomColors: !areCustomSolidsEnabled,
          gradients,
          disableCustomGradients: !areCustomGradientsEnabled
        },
        panelId: panelId
      }, key);
    }), children]
  });
}
//# sourceMappingURL=color-panel.js.map