function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }

function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

import PropTypes from "prop-types";

/*
 * SPDX-License-Identifier: Apache-2.0
 *
 * The OpenSearch Contributors require contributions made to
 * this file be licensed under the Apache-2.0 license or a
 * compatible open source license.
 *
 * Modifications Copyright OpenSearch Contributors. See
 * GitHub history for details.
 */

/*
 * Licensed to Elasticsearch B.V. under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch B.V. licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import React, { cloneElement, useEffect, useMemo, useRef, useState } from 'react';
import classNames from 'classnames';
import chroma from 'chroma-js';
import { EuiScreenReaderOnly } from '../accessibility';
import { EuiColorPickerSwatch } from './color_picker_swatch';
import { EuiFocusTrap } from '../focus_trap';
import { EuiFlexGroup, EuiFlexItem } from '../flex';
import { EuiFieldText, EuiFormControlLayout, EuiFormRow, EuiRange } from '../form';
import { EuiI18n } from '../i18n';
import { EuiPopover } from '../popover';
import { EuiSpacer } from '../spacer';
import { VISUALIZATION_COLORS, keys } from '../../services';
import { EuiHue } from './hue';
import { EuiSaturation } from './saturation';
import { getChromaColor, parseColor, HEX_FALLBACK, HSV_FALLBACK, RGB_FALLBACK, RGB_JOIN } from './utils';

function isKeyboardEvent(event) {
  return _typeof(event) === 'object' && 'key' in event;
}

var getOutput = function getOutput(text) {
  var showAlpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  var color = getChromaColor(text, true);
  var isValid = true;

  if (!showAlpha && color !== null) {
    isValid = color.alpha() === 1;
  } // Note that if a consumer has disallowed opacity,
  // we still return the color with an alpha channel, but mark it as invalid


  return color ? {
    rgba: color.rgba(),
    hex: color.hex(),
    isValid: isValid
  } : {
    rgba: RGB_FALLBACK,
    hex: HEX_FALLBACK,
    isValid: false
  };
};

var getHsv = function getHsv(hsv) {
  var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  // Chroma's passthrough (RGB) parsing determines that black/white/gray are hue-less and returns `NaN`
  // For our purposes we can process `NaN` as `0` if necessary
  if (!hsv) return HSV_FALLBACK;
  var hue = isNaN(hsv[0]) ? fallback : hsv[0];
  return [hue, hsv[1], hsv[2]];
};

export var EuiColorPicker = function EuiColorPicker(_ref) {
  var _ref8;

  var button = _ref.button,
      className = _ref.className,
      color = _ref.color,
      _ref$compressed = _ref.compressed,
      compressed = _ref$compressed === void 0 ? false : _ref$compressed,
      disabled = _ref.disabled,
      _ref$display = _ref.display,
      display = _ref$display === void 0 ? 'default' : _ref$display,
      _ref$fullWidth = _ref.fullWidth,
      fullWidth = _ref$fullWidth === void 0 ? false : _ref$fullWidth,
      id = _ref.id,
      isInvalid = _ref.isInvalid,
      _ref$mode = _ref.mode,
      mode = _ref$mode === void 0 ? 'default' : _ref$mode,
      onBlur = _ref.onBlur,
      onChange = _ref.onChange,
      onFocus = _ref.onFocus,
      _ref$readOnly = _ref.readOnly,
      readOnly = _ref$readOnly === void 0 ? false : _ref$readOnly,
      _ref$swatches = _ref.swatches,
      swatches = _ref$swatches === void 0 ? VISUALIZATION_COLORS : _ref$swatches,
      popoverZIndex = _ref.popoverZIndex,
      prepend = _ref.prepend,
      append = _ref.append,
      _ref$showAlpha = _ref.showAlpha,
      showAlpha = _ref$showAlpha === void 0 ? false : _ref$showAlpha,
      format = _ref.format,
      _ref$secondaryInputDi = _ref.secondaryInputDisplay,
      secondaryInputDisplay = _ref$secondaryInputDi === void 0 ? 'none' : _ref$secondaryInputDi,
      _ref$isClearable = _ref.isClearable,
      isClearable = _ref$isClearable === void 0 ? false : _ref$isClearable,
      placeholder = _ref.placeholder,
      dataTestSubj = _ref['data-test-subj'];
  var preferredFormat = useMemo(function () {
    if (format) return format;
    var parsed = parseColor(color);
    return parsed != null && _typeof(parsed) === 'object' ? 'rgba' : 'hex';
  }, [color, format]);
  var chromaColor = useMemo(function () {
    return getChromaColor(color, showAlpha);
  }, [color, showAlpha]);

  var _useState = useState('100'),
      _useState2 = _slicedToArray(_useState, 2),
      alphaRangeValue = _useState2[0],
      setAlphaRangeValue = _useState2[1];

  var alphaChannel = useMemo(function () {
    return chromaColor ? chromaColor.alpha() : 1;
  }, [chromaColor]);
  useEffect(function () {
    var percent = (alphaChannel * 100).toFixed();
    setAlphaRangeValue(percent);
  }, [alphaChannel]);

  var _useState3 = useState(false),
      _useState4 = _slicedToArray(_useState3, 2),
      isColorSelectorShown = _useState4[0],
      setIsColorSelectorShown = _useState4[1];

  var _useState5 = useState(null),
      _useState6 = _slicedToArray(_useState5, 2),
      inputRef = _useState6[0],
      setInputRef = _useState6[1]; // Ideally this is uses `useRef`, but `EuiFieldText` isn't ready for that


  var _useState7 = useState(false),
      _useState8 = _slicedToArray(_useState7, 2),
      popoverShouldOwnFocus = _useState8[0],
      setPopoverShouldOwnFocus = _useState8[1];

  var prevColor = useRef(chromaColor ? chromaColor.rgba().join() : null);

  var _useState9 = useState(chromaColor ? getHsv(chromaColor.hsv()) : HSV_FALLBACK),
      _useState10 = _slicedToArray(_useState9, 2),
      colorAsHsv = _useState10[0],
      setColorAsHsv = _useState10[1];

  var usableHsv = useMemo(function () {
    if (chromaColor && chromaColor.rgba().join() !== prevColor.current) {
      var _chromaColor$hsv = chromaColor.hsv(),
          _chromaColor$hsv2 = _slicedToArray(_chromaColor$hsv, 3),
          h = _chromaColor$hsv2[0],
          s = _chromaColor$hsv2[1],
          v = _chromaColor$hsv2[2];

      var hue = isNaN(h) ? colorAsHsv[0] : h;
      return [hue, s, v];
    }

    return colorAsHsv;
  }, [chromaColor, colorAsHsv]);
  var satruationRef = useRef(null);
  var swatchRef = useRef(null);
  var testSubjAnchor = classNames('euiColorPickerAnchor', dataTestSubj);

  var updateColorAsHsv = function updateColorAsHsv(_ref2) {
    var _ref3 = _slicedToArray(_ref2, 3),
        h = _ref3[0],
        s = _ref3[1],
        v = _ref3[2];

    setColorAsHsv(getHsv([h, s, v], usableHsv[0]));
  };

  var classes = classNames('euiColorPicker', className);
  var popoverClass = 'euiColorPicker__popoverAnchor';
  var panelClasses = classNames('euiColorPicker__popoverPanel', {
    'euiColorPicker__popoverPanel--pickerOnly': mode === 'picker' && secondaryInputDisplay !== 'bottom',
    'euiColorPicker__popoverPanel--customButton': button
  });
  var swatchClass = 'euiColorPicker__swatchSelect';
  var inputClasses = classNames('euiColorPicker__input', {
    'euiColorPicker__input--inGroup': prepend || append
  });

  var handleOnChange = function handleOnChange(text) {
    var output = getOutput(text, showAlpha);

    if (output.isValid) {
      prevColor.current = output.rgba.join();
    }

    onChange(text, output);
  };

  var handleOnBlur = function handleOnBlur() {
    // `onBlur` also gets called when the popover is closing
    // so prevent a second `onBlur` if the popover is open
    if (!isColorSelectorShown && onBlur) {
      onBlur();
    }
  };

  var closeColorSelector = function closeColorSelector() {
    var shouldDelay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

    if (onBlur) {
      onBlur();
    }

    if (shouldDelay) {
      setTimeout(function () {
        return setIsColorSelectorShown(false);
      });
    } else {
      setIsColorSelectorShown(false);
    }
  };

  var showColorSelector = function showColorSelector() {
    var shouldFocusInside = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
    if (isColorSelectorShown || readOnly) return;

    if (onFocus) {
      onFocus();
    }

    setPopoverShouldOwnFocus(shouldFocusInside);
    setIsColorSelectorShown(true);
  };

  var handleToggle = function handleToggle() {
    if (isColorSelectorShown) {
      closeColorSelector();
    } else {
      showColorSelector(true);
    }
  };

  var handleFinalSelection = function handleFinalSelection() {
    // When the trigger is an input, focus the input so you can adjust
    if (inputRef) {
      inputRef.focus();
    }

    closeColorSelector(true);
  };

  var handleOnKeyDown = function handleOnKeyDown(event) {
    if (event.key === keys.ENTER) {
      if (isColorSelectorShown) {
        handleFinalSelection();
      } else {
        showColorSelector();
      }
    }
  };

  var handleInputActivity = function handleInputActivity(event) {
    if (isKeyboardEvent(event)) {
      if (event.key === keys.ENTER) {
        event.preventDefault();
        handleToggle();
      }
    } else {
      showColorSelector();
    }
  };

  var handleToggleOnKeyDown = function handleToggleOnKeyDown(event) {
    if (event.key === keys.ARROW_DOWN) {
      event.preventDefault();

      if (isColorSelectorShown) {
        var nextFocusEl = mode !== 'swatch' ? satruationRef : swatchRef;

        if (nextFocusEl.current) {
          nextFocusEl.current.focus();
        }
      } else {
        showColorSelector(true);
      }
    }
  };

  var handleColorInput = function handleColorInput(event) {
    handleOnChange(event.target.value);
    var newColor = getChromaColor(event.target.value, showAlpha);

    if (newColor) {
      updateColorAsHsv(newColor.hsv());
    }
  };

  var handleClearInput = function handleClearInput() {
    handleOnChange('');

    if (secondaryInputDisplay === 'none' && isColorSelectorShown) {
      closeColorSelector();
    }
  };

  var updateWithHsv = function updateWithHsv(hsv) {
    var color = chroma.hsv.apply(chroma, _toConsumableArray(hsv)).alpha(alphaChannel);
    var formatted;

    if (preferredFormat === 'rgba') {
      formatted = alphaChannel < 1 ? color.rgba().join(RGB_JOIN) : color.rgb().join(RGB_JOIN);
    } else {
      formatted = color.hex();
    }

    handleOnChange(formatted);
    updateColorAsHsv(hsv);
  };

  var handleColorSelection = function handleColorSelection(color) {
    var _usableHsv = _slicedToArray(usableHsv, 1),
        h = _usableHsv[0];

    var _color = _slicedToArray(color, 3),
        s = _color[1],
        v = _color[2];

    var newHsv = [h, s, v];
    updateWithHsv(newHsv);
  };

  var handleHueSelection = function handleHueSelection(hue) {
    var _usableHsv2 = _slicedToArray(usableHsv, 3),
        s = _usableHsv2[1],
        v = _usableHsv2[2];

    var newHsv = [hue, s, v];
    updateWithHsv(newHsv);
  };

  var handleSwatchSelection = function handleSwatchSelection(color) {
    var newColor = getChromaColor(color, showAlpha);
    handleOnChange(color);

    if (newColor) {
      updateColorAsHsv(newColor.hsv());
    }

    handleFinalSelection();
  };

  var handleAlphaSelection = function handleAlphaSelection(e, isValid) {
    var target = e.target;
    setAlphaRangeValue(target.value || '');

    if (isValid) {
      var alpha = parseInt(target.value, 10) / 100;
      var newColor = chromaColor ? chromaColor.alpha(alpha) : null;
      var hex = newColor ? newColor.hex() : HEX_FALLBACK;
      var rgba = newColor ? newColor.rgba() : RGB_FALLBACK;

      var _text;

      if (preferredFormat === 'rgba') {
        _text = alpha < 1 ? rgba.join(RGB_JOIN) : rgba.slice(0, 3).join(RGB_JOIN);
      } else {
        _text = hex;
      }

      onChange(_text, {
        hex: hex,
        rgba: rgba,
        isValid: !!newColor
      });
    }
  };

  var inlineInput = secondaryInputDisplay !== 'none' && /*#__PURE__*/React.createElement(EuiI18n, {
    tokens: ['euiColorPicker.colorLabel', 'euiColorPicker.colorErrorMessage', 'euiColorPicker.transparent'],
    defaults: ['Color value', 'Invalid color value', 'Transparent']
  }, function (_ref4) {
    var _ref5 = _slicedToArray(_ref4, 3),
        colorLabel = _ref5[0],
        colorErrorMessage = _ref5[1],
        transparent = _ref5[2];

    return /*#__PURE__*/React.createElement(EuiFormRow, {
      display: "rowCompressed",
      isInvalid: isInvalid,
      error: isInvalid ? colorErrorMessage : null
    }, /*#__PURE__*/React.createElement(EuiFormControlLayout, {
      clear: isClearable && color && !readOnly && !disabled ? {
        onClick: handleClearInput
      } : undefined,
      readOnly: readOnly,
      compressed: compressed
    }, /*#__PURE__*/React.createElement(EuiFieldText, {
      compressed: true,
      value: color ? color.toUpperCase() : HEX_FALLBACK,
      placeholder: !color ? placeholder || transparent : undefined,
      onChange: handleColorInput,
      isInvalid: isInvalid,
      disabled: disabled,
      readOnly: readOnly,
      "aria-label": colorLabel,
      autoComplete: "off",
      "data-test-subj": "euiColorPickerInput_".concat(secondaryInputDisplay)
    })));
  });
  var showSecondaryInputOnly = mode === 'secondaryInput';
  var showPicker = mode !== 'swatch' && !showSecondaryInputOnly;
  var showSwatches = mode !== 'picker' && !showSecondaryInputOnly;
  var composite = /*#__PURE__*/React.createElement(React.Fragment, null, secondaryInputDisplay === 'top' && /*#__PURE__*/React.createElement(React.Fragment, null, inlineInput, /*#__PURE__*/React.createElement(EuiSpacer, {
    size: "s"
  })), showPicker && /*#__PURE__*/React.createElement("div", {
    onKeyDown: handleOnKeyDown
  }, /*#__PURE__*/React.createElement(EuiSaturation, {
    id: id,
    color: usableHsv,
    hex: chromaColor ? chromaColor.hex() : undefined,
    onChange: handleColorSelection,
    ref: satruationRef
  }), /*#__PURE__*/React.createElement(EuiHue, {
    id: id,
    hue: usableHsv[0],
    hex: chromaColor ? chromaColor.hex() : undefined,
    onChange: handleHueSelection
  })), showSwatches && /*#__PURE__*/React.createElement(EuiFlexGroup, {
    wrap: true,
    responsive: false,
    gutterSize: "s",
    role: "listbox"
  }, swatches.map(function (swatch, index) {
    return /*#__PURE__*/React.createElement(EuiFlexItem, {
      grow: false,
      key: swatch
    }, /*#__PURE__*/React.createElement(EuiI18n, {
      token: "euiColorPicker.swatchAriaLabel",
      values: {
        swatch: swatch
      },
      default: "Select {swatch} as the color"
    }, function (swatchAriaLabel) {
      return /*#__PURE__*/React.createElement(EuiColorPickerSwatch, {
        className: swatchClass,
        color: swatch,
        onClick: function onClick() {
          return handleSwatchSelection(swatch);
        },
        "aria-label": swatchAriaLabel,
        role: "option",
        ref: index === 0 ? swatchRef : undefined
      });
    }));
  })), secondaryInputDisplay === 'bottom' && /*#__PURE__*/React.createElement(React.Fragment, null, mode !== 'picker' && /*#__PURE__*/React.createElement(EuiSpacer, {
    size: "s"
  }), inlineInput), showAlpha && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EuiSpacer, {
    size: "s"
  }), /*#__PURE__*/React.createElement(EuiI18n, {
    token: "euiColorPicker.alphaLabel",
    default: "Alpha channel (opacity) value"
  }, function (alphaLabel) {
    return /*#__PURE__*/React.createElement(EuiRange, {
      className: "euiColorPicker__alphaRange",
      "data-test-subj": "euiColorPickerAlpha",
      compressed: true,
      showInput: true,
      max: 100,
      min: 0,
      value: alphaRangeValue,
      append: "%",
      onChange: handleAlphaSelection,
      "aria-label": alphaLabel
    });
  })));
  var buttonOrInput;

  if (button) {
    buttonOrInput = /*#__PURE__*/cloneElement(button, {
      onClick: handleToggle,
      id: id,
      disabled: disabled,
      'data-test-subj': testSubjAnchor
    });
  } else {
    var colorStyle = chromaColor ? chromaColor.css() : undefined;
    buttonOrInput = /*#__PURE__*/React.createElement(EuiFormControlLayout, {
      icon: !readOnly ? {
        type: 'arrowDown',
        side: 'right'
      } : undefined,
      clear: isClearable && color && !readOnly && !disabled ? {
        onClick: handleClearInput
      } : undefined,
      readOnly: readOnly,
      fullWidth: fullWidth,
      compressed: compressed,
      onKeyDown: handleToggleOnKeyDown,
      prepend: prepend,
      append: append
    }, /*#__PURE__*/React.createElement("div", {
      // Used to pass the chosen color through to form layout SVG using currentColor
      style: {
        color: colorStyle
      }
    }, /*#__PURE__*/React.createElement(EuiI18n, {
      tokens: ['euiColorPicker.openLabel', 'euiColorPicker.closeLabel', 'euiColorPicker.transparent'],
      defaults: ['Press the escape key to close the popover', 'Press the down key to open a popover containing color options', 'Transparent']
    }, function (_ref6) {
      var _ref7 = _slicedToArray(_ref6, 3),
          openLabel = _ref7[0],
          closeLabel = _ref7[1],
          transparent = _ref7[2];

      return /*#__PURE__*/React.createElement(EuiFieldText, {
        className: inputClasses,
        onClick: handleInputActivity,
        onKeyDown: handleInputActivity,
        onBlur: handleOnBlur,
        value: color ? color.toUpperCase() : HEX_FALLBACK,
        placeholder: !color ? placeholder || transparent : undefined,
        id: id,
        onChange: handleColorInput,
        icon: chromaColor ? 'swatchInput' : 'stopSlash',
        inputRef: setInputRef,
        isInvalid: isInvalid,
        compressed: compressed,
        disabled: disabled,
        readOnly: readOnly,
        fullWidth: fullWidth,
        autoComplete: "off",
        "data-test-subj": testSubjAnchor,
        "aria-label": isColorSelectorShown ? openLabel : closeLabel
      });
    })));
  }

  return display === 'inline' ? /*#__PURE__*/React.createElement("div", {
    className: classes
  }, composite) : /*#__PURE__*/React.createElement(EuiPopover, {
    ownFocus: popoverShouldOwnFocus,
    initialFocus: (_ref8 = mode !== 'swatch' ? satruationRef.current : swatchRef.current) !== null && _ref8 !== void 0 ? _ref8 : undefined,
    button: buttonOrInput,
    isOpen: isColorSelectorShown,
    closePopover: handleFinalSelection,
    zIndex: popoverZIndex,
    className: popoverClass,
    panelClassName: panelClasses,
    display: button ? 'inlineBlock' : 'block',
    attachToAnchor: button ? false : true,
    anchorPosition: "downLeft",
    panelPaddingSize: "s"
  }, /*#__PURE__*/React.createElement("div", {
    className: classes,
    "data-test-subj": "euiColorPickerPopover"
  }, /*#__PURE__*/React.createElement(EuiFocusTrap, {
    clickOutsideDisables: true
  }, /*#__PURE__*/React.createElement(EuiScreenReaderOnly, null, /*#__PURE__*/React.createElement("p", {
    "aria-live": "polite"
  }, /*#__PURE__*/React.createElement(EuiI18n, {
    token: "euiColorPicker.screenReaderAnnouncement",
    default: "A popup with a range of selectable colors opened. Tab forward to cycle through colors choices or press escape to close this popup."
  }))), composite)));
};
EuiColorPicker.propTypes = {
  /**
     *  Custom element to use instead of text input
     */
  button: PropTypes.element,

  /**
     *  Use the compressed style for EuiFieldText
     */
  compressed: PropTypes.bool,
  display: PropTypes.oneOf(["default", "inline"]),
  disabled: PropTypes.bool,
  fullWidth: PropTypes.bool,
  id: PropTypes.string,

  /**
     *  Custom validation flag
     */
  isInvalid: PropTypes.bool,

  /**
     * Choose between swatches with gradient picker (default), swatches only, gradient picker only, or secondary input only.
     */
  mode: PropTypes.oneOf(["default", "swatch", "picker", "secondaryInput"]),

  /**
     *  Custom z-index for the popover
     */
  popoverZIndex: PropTypes.number,
  readOnly: PropTypes.bool,

  /**
     *  Array of hex strings (3 or 6 character) to use as swatch options. Defaults to EUI visualization colors
     */
  swatches: PropTypes.arrayOf(PropTypes.string.isRequired),

  /**
     * Creates an input group with element(s) coming before input. It only shows when the `display` is set to `default`.
     * `string` | `ReactElement` or an array of these
     */
  prepend: PropTypes.any,

  /**
     * Creates an input group with element(s) coming after input. It only shows when the `display` is set to `default`.
     * `string` | `ReactElement` or an array of these
     */
  append: PropTypes.any,

  /**
     * Whether to render the alpha channel (opacity) value range slider.
     */
  showAlpha: PropTypes.bool,

  /**
     * Will format the text input in the provided format when possible (hue and saturation selection)
     * Exceptions: Manual text input and swatches will display as-authored
     * Default is to display the last format entered by the user
     */
  format: PropTypes.oneOf(["hex", "rgba"]),

  /**
     * Placement option for a secondary color value input.
     */
  secondaryInputDisplay: PropTypes.oneOf(["top", "bottom", "none"]),

  /**
     * Add a button to the primary input to clear its value.
     */
  isClearable: PropTypes.bool,

  /**
     * Text to replace the default 'Transparent' placeholder for unset color values.
     */
  placeholder: PropTypes.string,
  className: PropTypes.string,
  "aria-label": PropTypes.string,
  "data-test-subj": PropTypes.string,

  /**
     * hex (string)
     * RGB (as comma separated string)
     * RGBa (as comma separated string)
     * Empty string will register as 'transparent'
     */
  color: PropTypes.oneOfType([PropTypes.string.isRequired, PropTypes.oneOf([null])]),
  onBlur: PropTypes.func,

  /**
     * text (string, as entered or selected)
     * hex (8-digit hex if alpha < 1, otherwise 6-digit hex)
     * RGBa (as array; values of NaN if color is invalid)
     * isValid (boolean signifying if the input text is a valid color)
     */
  onChange: PropTypes.func.isRequired,
  onFocus: PropTypes.func
};