/**
 * WordPress dependencies
 */
import { useCallback, useMemo, useState } from '@wordpress/element';

/**
 * Internal dependencies
 */
import * as styles from '../styles';
import { parseQuantityAndUnitFromRawValue } from '../../unit-control/utils';
import { useContextSystem } from '../../context';
import { useCx } from '../../utils/hooks/use-cx';
import { maybeWarnDeprecated36pxSize } from '../../utils/deprecated-36px-size';

// If either width or color are defined, the border is considered valid
// and a border style can be set as well.
const isValidBorder = border => {
  const hasWidth = border?.width !== undefined && border.width !== '';
  const hasColor = border?.color !== undefined;
  return hasWidth || hasColor;
};
export function useBorderControl(props) {
  const {
    className,
    colors = [],
    isCompact,
    onChange,
    enableAlpha = true,
    enableStyle = true,
    shouldSanitizeBorder = true,
    size = 'default',
    value: border,
    width,
    __experimentalIsRenderedInSidebar = false,
    __next40pxDefaultSize,
    __shouldNotWarnDeprecated36pxSize,
    ...otherProps
  } = useContextSystem(props, 'BorderControl');
  maybeWarnDeprecated36pxSize({
    componentName: 'BorderControl',
    __next40pxDefaultSize,
    size,
    __shouldNotWarnDeprecated36pxSize
  });
  const computedSize = size === 'default' && __next40pxDefaultSize ? '__unstable-large' : size;
  const [widthValue, originalWidthUnit] = parseQuantityAndUnitFromRawValue(border?.width);
  const widthUnit = originalWidthUnit || 'px';
  const hadPreviousZeroWidth = widthValue === 0;
  const [colorSelection, setColorSelection] = useState();
  const [styleSelection, setStyleSelection] = useState();
  const isStyleSettable = shouldSanitizeBorder ? isValidBorder(border) : true;
  const onBorderChange = useCallback(newBorder => {
    if (shouldSanitizeBorder && !isValidBorder(newBorder)) {
      onChange(undefined);
      return;
    }
    onChange(newBorder);
  }, [onChange, shouldSanitizeBorder]);
  const onWidthChange = useCallback(newWidth => {
    const newWidthValue = newWidth === '' ? undefined : newWidth;
    const [parsedValue] = parseQuantityAndUnitFromRawValue(newWidth);
    const hasZeroWidth = parsedValue === 0;
    const updatedBorder = {
      ...border,
      width: newWidthValue
    };

    // Setting the border width explicitly to zero will also set the
    // border style to `none` and clear the border color.
    if (hasZeroWidth && !hadPreviousZeroWidth) {
      // Before clearing the color and style selections, keep track of
      // the current selections so they can be restored when the width
      // changes to a non-zero value.
      setColorSelection(border?.color);
      setStyleSelection(border?.style);

      // Clear the color and style border properties.
      updatedBorder.color = undefined;
      updatedBorder.style = 'none';
    }

    // Selection has changed from zero border width to non-zero width.
    if (!hasZeroWidth && hadPreviousZeroWidth) {
      // Restore previous border color and style selections if width
      // is now not zero.
      if (updatedBorder.color === undefined) {
        updatedBorder.color = colorSelection;
      }
      if (updatedBorder.style === 'none') {
        updatedBorder.style = styleSelection;
      }
    }
    onBorderChange(updatedBorder);
  }, [border, hadPreviousZeroWidth, colorSelection, styleSelection, onBorderChange]);
  const onSliderChange = useCallback(value => {
    onWidthChange(`${value}${widthUnit}`);
  }, [onWidthChange, widthUnit]);

  // Generate class names.
  const cx = useCx();
  const classes = useMemo(() => {
    return cx(styles.borderControl, className);
  }, [className, cx]);
  let wrapperWidth = width;
  if (isCompact) {
    // Widths below represent the minimum usable width for compact controls.
    // Taller controls contain greater internal padding, thus greater width.
    wrapperWidth = size === '__unstable-large' ? '116px' : '90px';
  }
  const innerWrapperClassName = useMemo(() => {
    const widthStyle = !!wrapperWidth && styles.wrapperWidth;
    const heightStyle = styles.wrapperHeight(computedSize);
    return cx(styles.innerWrapper(), widthStyle, heightStyle);
  }, [wrapperWidth, cx, computedSize]);
  const sliderClassName = useMemo(() => {
    return cx(styles.borderSlider());
  }, [cx]);
  return {
    ...otherProps,
    className: classes,
    colors,
    enableAlpha,
    enableStyle,
    innerWrapperClassName,
    inputWidth: wrapperWidth,
    isStyleSettable,
    onBorderChange,
    onSliderChange,
    onWidthChange,
    previousStyleSelection: styleSelection,
    sliderClassName,
    value: border,
    widthUnit,
    widthValue,
    size: computedSize,
    __experimentalIsRenderedInSidebar,
    __next40pxDefaultSize
  };
}
//# sourceMappingURL=hook.js.map