/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { c as customElement } from "../../chunks/runtime.js";
import { keyed } from "lit/directives/keyed.js";
import Color from "color";
import { css, html } from "lit";
import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina";
import { createRef, ref } from "lit/directives/ref.js";
import { n as normalizeHex, b as hexify, i as isValidHex, s as isLonghandHex, u as isShorthandHex, v as rgbToHex, o as opacityToAlpha, m as alphaToOpacity, O as OPACITY_LIMITS, w as hexChar } from "../../chunks/utils.js";
import { u as useSetFocus } from "../../chunks/useSetFocus.js";
const CSS = {
  container: "container",
  hexInput: "hex-input",
  opacityInput: "opacity-input"
};
const styles = css`:host{display:block}.container{display:flex;inline-size:100%;flex-wrap:nowrap;align-items:center}.hex-input{--calcite-input-text-background-color: var(--calcite-color-picker-input-background-color);--calcite-input-text-border-color: var(--calcite-color-picker-input-border-color);--calcite-input-text-text-color: var(--calcite-color-picker-input-text-color);--calcite-input-prefix-text-color: var(--calcite-color-picker-input-prefix-text-color)}.opacity-input{--calcite-input-number-background-color: var(--calcite-color-picker-input-background-color);--calcite-input-number-border-color: var(--calcite-color-picker-input-border-color);--calcite-input-number-text-color: var(--calcite-color-picker-input-text-color);--calcite-input-suffix-text-color: var(--calcite-color-picker-input-suffix-text-color)}.hex-input{flex-grow:1;text-transform:uppercase}.opacity-input{inline-size:100px;margin-inline-start:-1px}:host([hidden]){display:none}[hidden]{display:none}`;
const DEFAULT_COLOR = Color();
class ColorPickerHexInput extends LitElement {
  constructor() {
    super(...arguments);
    this.hexInputRef = createRef();
    this.opacityInputRef = createRef();
    this.focusSetter = useSetFocus()(this);
    this.internalColor = DEFAULT_COLOR;
    this.alphaChannel = false;
    this.allowEmpty = false;
    this.hexLabel = "Hex";
    this.scale = "m";
    this.value = normalizeHex(hexify(DEFAULT_COLOR, this.alphaChannel), this.alphaChannel, true);
    this.calciteColorPickerHexInputChange = createEvent({ cancelable: false });
  }
  static {
    this.properties = { internalColor: [16, {}, { state: true }], alphaChannel: [5, {}, { type: Boolean }], allowEmpty: [5, {}, { type: Boolean }], hexLabel: 1, messages: [0, {}, { attribute: false }], numberingSystem: 1, scale: [3, {}, { reflect: true }], value: [3, {}, { reflect: true }] };
  }
  static {
    this.styles = styles;
  }
  async setFocus(options) {
    return this.focusSetter(() => this.hexInputRef.value, options);
  }
  connectedCallback() {
    super.connectedCallback();
    this.previousDefinedValue = this.value;
    const { allowEmpty, alphaChannel, value } = this;
    if (value) {
      const normalized = normalizeHex(value, alphaChannel);
      if (isValidHex(normalized, alphaChannel)) {
        this.internalSetValue(normalized, normalized, false);
      }
      return;
    }
    if (allowEmpty) {
      this.internalSetValue(void 0, void 0, false);
    }
  }
  willUpdate(changes) {
    if (changes.has("value") && (this.hasUpdated || this.value !== normalizeHex(hexify(DEFAULT_COLOR, this.alphaChannel), this.alphaChannel, true))) {
      this.internalSetValue(this.value, changes.get("value"), false);
    }
  }
  onHexInputBlur() {
    const node = this.hexInputRef.value;
    const inputValue = node.value;
    const hex = `#${inputValue}`;
    const { allowEmpty, internalColor } = this;
    const willClearValue = allowEmpty && !inputValue;
    const isLonghand = isLonghandHex(hex);
    const anyShorthand = isShorthandHex(hex, true) || isShorthandHex(hex, false);
    if (anyShorthand) {
      this.onHexInputChange();
    }
    if (willClearValue || isValidHex(hex) && isLonghand) {
      return;
    }
    node.value = allowEmpty && !internalColor ? "" : this.formatHexForInternalInput(rgbToHex(
      // always display hex input in RRGGBB format
      internalColor.object()
    ));
  }
  onOpacityInputBlur() {
    const node = this.opacityInputRef.value;
    const inputValue = node.value;
    const { allowEmpty, internalColor } = this;
    const willClearValue = allowEmpty && !inputValue;
    if (willClearValue) {
      return;
    }
    node.value = allowEmpty && !internalColor ? "" : this.formatOpacityForInternalInput(internalColor);
  }
  onOpacityInputInput() {
    this.onOpacityInputChange();
  }
  onHexInputChange() {
    const nodeValue = this.hexInputRef.value.value;
    let value = nodeValue;
    if (value) {
      const normalized = normalizeHex(value, false);
      const preserveExistingAlpha = isValidHex(normalized) && this.alphaChannel;
      if (preserveExistingAlpha && this.internalColor) {
        const alphaHex = normalizeHex(this.internalColor.hexa(), true).slice(-2);
        value = `${normalized + alphaHex}`;
      }
    }
    this.internalSetValue(value, this.value);
  }
  onOpacityInputChange() {
    const node = this.opacityInputRef.value;
    let value;
    if (!node.value) {
      value = node.value;
    } else {
      const alpha = opacityToAlpha(Number(node.value));
      value = this.internalColor?.alpha(alpha).hexa();
    }
    this.internalSetValue(value, this.value);
  }
  onInputFocus(event) {
    const focusTarget = event.type === "calciteInternalInputTextFocus" ? this.hexInputRef : this.opacityInputRef;
    focusTarget.value.selectText();
  }
  onHexInputInput() {
    const hexInputValue = `#${this.hexInputRef.value.value}`;
    const oldValue = this.value;
    if (isValidHex(hexInputValue, this.alphaChannel) && isLonghandHex(hexInputValue, this.alphaChannel)) {
      this.internalSetValue(hexInputValue, oldValue);
    }
  }
  onInputKeyDown(event) {
    const { altKey, ctrlKey, metaKey, shiftKey } = event;
    const { alphaChannel, hexInputRef, internalColor, value } = this;
    const { key } = event;
    const composedPath = event.composedPath();
    if (key === "Tab" && isShorthandHex(value, this.alphaChannel) || key === "Enter") {
      if (composedPath.includes(hexInputRef.value)) {
        this.onHexInputChange();
      } else {
        this.onOpacityInputChange();
      }
      if (key === "Enter") {
        event.preventDefault();
      }
      return;
    }
    const isNudgeKey = key === "ArrowDown" || key === "ArrowUp";
    const oldValue = this.value;
    if (isNudgeKey) {
      if (!value) {
        this.internalSetValue(this.previousDefinedValue, oldValue);
        event.preventDefault();
        return;
      }
      const direction = key === "ArrowUp" ? 1 : -1;
      const bump = shiftKey ? 10 : 1;
      this.internalSetValue(hexify(this.nudgeRGBChannels(internalColor, bump * direction, composedPath.includes(hexInputRef.value) ? "rgb" : "a"), alphaChannel), oldValue);
      event.preventDefault();
      return;
    }
    const withModifiers = altKey || ctrlKey || metaKey;
    const singleChar = key.length === 1;
    const validHexChar = hexChar.test(key);
    if (singleChar && !withModifiers && !validHexChar) {
      event.preventDefault();
    }
  }
  onHexInputPaste(event) {
    const hex = event.clipboardData?.getData("text");
    if (isValidHex(hex, this.alphaChannel) && isLonghandHex(hex, this.alphaChannel)) {
      event.preventDefault();
      this.hexInputRef.value.value = hex.slice(1);
      this.internalSetValue(hex, this.value);
    }
  }
  internalSetValue(value, oldValue, emit = true) {
    if (value) {
      const { alphaChannel } = this;
      const normalized = normalizeHex(value, alphaChannel, alphaChannel);
      if (isValidHex(normalized, alphaChannel)) {
        const { internalColor: currentColor } = this;
        const nextColor = Color(normalized);
        const normalizedLonghand = normalizeHex(hexify(nextColor, alphaChannel), alphaChannel);
        const changed = !currentColor || normalizedLonghand !== normalizeHex(hexify(currentColor, alphaChannel), alphaChannel);
        this.internalColor = nextColor;
        this.previousDefinedValue = normalizedLonghand;
        this.value = normalizedLonghand;
        if (changed && emit) {
          this.calciteColorPickerHexInputChange.emit();
        }
        return;
      }
    } else if (this.allowEmpty) {
      this.internalColor = void 0;
      this.value = void 0;
      if (emit) {
        this.calciteColorPickerHexInputChange.emit();
      }
      return;
    }
    this.value = oldValue;
  }
  formatHexForInternalInput(hex) {
    return hex ? hex.replace("#", "").slice(0, 6) : "";
  }
  formatOpacityForInternalInput(color) {
    return color ? `${alphaToOpacity(color.alpha())}` : "";
  }
  nudgeRGBChannels(color, amount, context) {
    let nudgedChannels;
    const channels = color.array();
    const rgbChannels = channels.slice(0, 3);
    if (context === "rgb") {
      const nudgedRGBChannels = rgbChannels.map((channel) => channel + amount);
      nudgedChannels = [
        ...nudgedRGBChannels,
        this.alphaChannel ? channels[3] : void 0
      ];
    } else {
      const nudgedAlpha = opacityToAlpha(alphaToOpacity(color.alpha()) + amount);
      nudgedChannels = [...rgbChannels, nudgedAlpha];
    }
    return Color(nudgedChannels);
  }
  render() {
    const { alphaChannel, hexLabel, internalColor, messages, scale, value } = this;
    const hexInputValue = this.formatHexForInternalInput(value);
    const opacityInputValue = this.formatOpacityForInternalInput(internalColor);
    const inputScale = scale === "l" ? "m" : "s";
    return html`<div class=${safeClassMap(CSS.container)}><calcite-input-text class=${safeClassMap(CSS.hexInput)} .label=${messages?.hex || hexLabel} .maxLength=${this.alphaChannel ? 8 : 6} @calciteInputTextChange=${this.onHexInputChange} @calciteInputTextInput=${this.onHexInputInput} @calciteInternalInputTextBlur=${this.onHexInputBlur} @calciteInternalInputTextFocus=${this.onInputFocus} @keydown=${this.onInputKeyDown} @paste=${this.onHexInputPaste} prefix-text=# .scale=${inputScale} .value=${hexInputValue} ${ref(this.hexInputRef)}></calcite-input-text>${alphaChannel ? keyed("opacity-input", html`<calcite-input-number class=${safeClassMap(CSS.opacityInput)} .label=${messages?.opacity} .max=${OPACITY_LIMITS.max} max-length=3 .min=${OPACITY_LIMITS.min} number-button-type=none .numberingSystem=${this.numberingSystem} @calciteInputNumberInput=${this.onOpacityInputInput} @calciteInternalInputNumberBlur=${this.onOpacityInputBlur} @calciteInternalInputNumberFocus=${this.onInputFocus} @keydown=${this.onInputKeyDown} .scale=${inputScale} suffix-text=% .value=${opacityInputValue} ${ref(this.opacityInputRef)}></calcite-input-number>`) : null}</div>`;
  }
}
customElement("calcite-color-picker-hex-input", ColorPickerHexInput);
export {
  ColorPickerHexInput
};
