/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { c as customElement } from "../../chunks/runtime.js";
import { live } from "lit/directives/live.js";
import { html, css } from "lit";
import { safeClassMap, LitElement, createEvent, stringOrBoolean, nothing, safeStyleMap } from "@arcgis/lumina";
import { g as guid } from "../../chunks/guid.js";
import { c as connectLabel, d as disconnectLabel, g as getLabelText } from "../../chunks/label.js";
import { I as InternalLabel } from "../../chunks/InternalLabel.js";
import { V as Validation } from "../../chunks/Validation.js";
import { u as useT9n } from "../../chunks/useT9n.js";
import { u as useSetFocus } from "../../chunks/useSetFocus.js";
import { u as useInteractive } from "../../chunks/useInteractive.js";
import { u as useForm } from "../../chunks/useForm.js";
const StarIcon = ({ full, scale, partial }) => html`<calcite-icon class=${safeClassMap(partial ? void 0 : "icon")} .icon=${full ? "star-f" : "star"} .scale=${scale}></calcite-icon>`;
const CSS = {
  fieldSet: "fieldset",
  star: "star",
  fraction: "fraction",
  numberAverage: "number--average",
  numberCount: "number--count",
  wrapper: "wrapper",
  visuallyHidden: "visually-hidden"
};
const idPrefix = "calcite-ratings";
const IDS = {
  validationMessage: "validationMessage",
  host: (id) => `${idPrefix}-${id}`
};
const styles = css`:host([disabled]){cursor:default;-webkit-user-select:none;user-select:none;opacity:var(--calcite-opacity-disabled)}:host([read-only]) *,:host([disabled]) *,:host([read-only]) ::slotted(*),:host([disabled]) ::slotted(*){pointer-events:none}:host{position:relative;display:flex;align-items:center;inline-size:fit-content}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}.interaction-container{display:contents}:host([scale=s]){block-size:1.5rem;--calcite-internal-rating-spacing: .25rem}:host([scale=m]){block-size:2rem;--calcite-internal-rating-spacing: .5rem}:host([scale=l]){block-size:2.75rem;--calcite-internal-rating-spacing: .75rem}.fieldset{margin:0;display:flex;border-width:0;padding:0;align-items:center;gap:var(--calcite-rating-spacing, var(--calcite-internal-rating-spacing))}.wrapper{display:inline-block}.star{transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out;position:relative;display:flex;flex-direction:column;cursor:pointer;color:var(--calcite-rating-color, var(--calcite-color-border-input))}.star:hover{color:var(--calcite-rating-color-hover, var(--calcite-color-brand-hover))}.star:active{color:var(--calcite-rating-color-press, var(--calcite-color-brand-press))}.star:focus{outline:var(--calcite-border-width-md) solid var(--calcite-color-focus, var(--calcite-ui-focus-color, var(--calcite-color-brand)));outline-offset:calc(var(--calcite-spacing-base) * calc(1 - (2*clamp(0,var(--calcite-offset-invert-focus),1))))}.average,.fraction{color:var(--calcite-rating-average-color, var(--calcite-color-status-warning))}.hovered,.selected{color:var(--calcite-rating-color, var(--calcite-color-brand))}.fraction{transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out;position:absolute;pointer-events:none;inset-block-start:0;overflow:hidden;inset-inline-start:0}calcite-chip{pointer-events:none;cursor:default}.number--average{font-weight:700;color:var(--calcite-rating-average-text-color)}.number--count{color:var(--calcite-rating-count-text-color, var(--calcite-color-text-2));font-style:italic}.number--count:not(:first-child){margin-inline-start:var(--calcite-rating-spacing, var(--calcite-internal-rating-spacing))}.visually-hidden{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.internal-label-alignment--center{align-items:center}.internal-label-alignment--end{align-items:end}.internal-label--container{display:flex;justify-content:space-between;color:var(--calcite-color-text-1)}.internal-label-required--indicator{font-weight:var(--calcite-font-weight-medium);color:var(--calcite-color-status-danger);padding-inline:var(--calcite-spacing-base)}.internal-label-required--indicator:hover{cursor:help}.internal-label--text{line-height:1}:host([scale=s]) .internal-label-spacing--bottom{margin-block-end:var(--calcite-spacing-xxs)}:host([scale=s]) .internal-label-spacing-inline--end{margin-inline-end:var(--calcite-spacing-sm)}:host([scale=s]) .internal-label-spacing-inline--start{margin-inline-start:var(--calcite-spacing-sm)}:host([scale=s]) .internal-label--text{font-size:var(--calcite-font-size--2)}:host([scale=m]) .internal-label-spacing--bottom{margin-block-end:var(--calcite-spacing-sm)}:host([scale=m]) .internal-label-spacing-inline--end{margin-inline-end:var(--calcite-spacing-sm)}:host([scale=m]) .internal-label-spacing-inline--start{margin-inline-start:var(--calcite-spacing-sm)}:host([scale=m]) .internal-label--text{font-size:var(--calcite-font-size--1)}:host([scale=l]) .internal-label-spacing--bottom{margin-block-end:var(--calcite-spacing-sm)}:host([scale=l]) .internal-label-spacing-inline--end{margin-inline-end:var(--calcite-spacing-md)}:host([scale=l]) .internal-label-spacing-inline--start{margin-inline-start:var(--calcite-spacing-md)}:host([scale=l]) .internal-label--text{font-size:var(--calcite-font-size-0)}.validation-container{display:flex;flex-direction:column;align-items:flex-start;align-self:stretch}:host([scale=m]) .validation-container,:host([scale=l]) .validation-container{padding-block-start:.5rem}:host([scale=s]) .validation-container{padding-block-start:.25rem}::slotted(input[slot=hidden-form-input]){margin:0!important;opacity:0!important;outline:none!important;padding:0!important;position:absolute!important;inset:0!important;transform:none!important;-webkit-appearance:none!important;z-index:-1!important}:host([hidden]){display:none}[hidden]{display:none}`;
class Rating extends LitElement {
  constructor() {
    super();
    this.emit = false;
    this.formSupport = useForm({
      inputType: "number",
      getValue: () => {
        return this.value === 0 ? "" : this.value;
      }
    })(this);
    this.guid = IDS.host(guid());
    this.isKeyboardInteraction = true;
    this.labelElements = [];
    this.max = 5;
    this._value = 0;
    this.messages = useT9n({ blocking: true });
    this.focusSetter = useSetFocus()(this);
    this.interactiveContainer = useInteractive(this);
    this.disabled = false;
    this.readOnly = false;
    this.required = false;
    this.scale = "m";
    this.showChip = false;
    this.status = "idle";
    this.calciteRatingChange = createEvent({ cancelable: false });
    this.listen("keydown", this.handleHostKeyDown);
    this.listen("pointerout", this.handleRatingPointerOut);
    this.listen("pointerover", this.handleRatingPointerOver);
  }
  static {
    this.properties = { hoverValue: [16, {}, { state: true }], average: [11, {}, { reflect: true, type: Number }], count: [11, {}, { reflect: true, type: Number }], disabled: [7, {}, { reflect: true, type: Boolean }], form: [3, {}, { reflect: true }], labelText: 1, messageOverrides: [0, {}, { attribute: false }], name: [3, {}, { reflect: true }], readOnly: [7, {}, { reflect: true, type: Boolean }], required: [7, {}, { reflect: true, type: Boolean }], scale: [3, {}, { reflect: true }], showChip: [7, {}, { reflect: true, type: Boolean }], status: [3, {}, { reflect: true }], validationIcon: [3, { converter: stringOrBoolean, type: String }, { reflect: true }], validationMessage: 1, validity: [32, {}, { readOnly: true, attribute: false }], value: [11, {}, { reflect: true, type: Number }] };
  }
  static {
    this.formAssociated = true;
  }
  static {
    this.styles = styles;
  }
  get value() {
    return this._value;
  }
  set value(value) {
    const oldValue = this._value;
    if (value !== oldValue) {
      this._value = value;
      if (this.hasUpdated) {
        this.handleValueUpdate(value);
      }
    }
  }
  async setFocus(options) {
    return this.focusSetter(() => this.el, options);
  }
  connectedCallback() {
    super.connectedCallback();
    connectLabel(this);
  }
  async load() {
    this.requestUpdate("value");
  }
  willUpdate() {
    this.starsMap = Array.from({ length: this.max }, (_, i) => {
      const value = i + 1;
      const hoverValue = this.hoverValue ?? 0;
      const hasHoverValue = hoverValue > 0;
      const hasAverage = this.average != null;
      const averageValue = this.average ?? 0;
      const average = !hasHoverValue && hasAverage && !this.value && value <= averageValue;
      const checked = value === this.value;
      const fraction = hasAverage ? averageValue + 1 - value : 0;
      const hovered = hasHoverValue && value <= hoverValue;
      const id = `${this.guid}-${value}`;
      const partial = !hasHoverValue && !this.value && hasAverage && !hovered && fraction > 0 && fraction < 1;
      const selected = this.value >= value;
      const tabIndex = this.getTabIndex(value);
      return {
        average,
        checked,
        fraction,
        hovered,
        id,
        partial,
        selected,
        value,
        tabIndex
      };
    });
  }
  loaded() {
    this.labelElements = Array.from(this.renderRoot.querySelectorAll("label"));
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    disconnectLabel(this);
  }
  handleValueUpdate(newValue) {
    this.hoverValue = newValue;
    if (this.emit) {
      this.calciteRatingChange.emit();
    }
    this.emit = false;
  }
  onLabelClick() {
    this.setFocus();
  }
  handleRatingPointerOver() {
    this.isKeyboardInteraction = false;
  }
  handleRatingPointerOut() {
    this.isKeyboardInteraction = true;
    this.hoverValue = void 0;
  }
  handleHostKeyDown() {
    this.isKeyboardInteraction = true;
  }
  handleLabelKeyDown(event) {
    const inputValue = this.getValueFromLabelEvent(event);
    const key = event.key;
    const numberKey = key == " " ? NaN : Number(key);
    this.emit = true;
    if (isNaN(numberKey)) {
      switch (key) {
        case "Enter":
        case " ":
          this.value = !this.required && this.value === inputValue ? 0 : inputValue;
          break;
        case "ArrowLeft":
          this.value = this.getPreviousRatingValue(inputValue);
          this.updateFocus();
          event.preventDefault();
          break;
        case "ArrowRight":
          this.value = this.getNextRatingValue(inputValue);
          this.updateFocus();
          event.preventDefault();
          break;
        case "Tab":
          this.hoverValue = void 0;
          break;
      }
    } else {
      if (!this.required && numberKey >= 0 && numberKey <= this.max) {
        this.value = numberKey;
      } else if (this.required && numberKey > 0 && numberKey <= this.max) {
        this.value = numberKey;
      }
      this.updateFocus();
    }
  }
  handleInputChange(event) {
    if (this.isKeyboardInteraction === true) {
      const inputVal = Number(event.target.value);
      this.hoverValue = inputVal;
      this.value = inputVal;
    }
  }
  handleLabelPointerOver(event) {
    this.hoverValue = this.getValueFromLabelEvent(event);
  }
  handleLabelPointerDown(event) {
    const target = event.currentTarget;
    const inputValue = this.getValueFromLabelEvent(event);
    this.hoverValue = inputValue;
    this.emit = true;
    this.value = !this.required && this.value === inputValue ? 0 : inputValue;
    target.focus();
  }
  handleLabelClick(event) {
    event.preventDefault();
  }
  handleLabelFocus(event) {
    const inputValue = this.getValueFromLabelEvent(event);
    this.hoverValue = inputValue;
  }
  updateFocus() {
    this.hoverValue = this.value;
    this.labelElements[this.value - 1]?.focus();
  }
  getTabIndex(value) {
    if (this.readOnly || this.value !== value && (this.value || value !== 1)) {
      return -1;
    }
    return 0;
  }
  getValueFromLabelEvent(event) {
    const target = event.currentTarget;
    return Number(target.getAttribute("data-value"));
  }
  getNextRatingValue(currentValue) {
    return currentValue === 5 ? 1 : currentValue + 1;
  }
  getPreviousRatingValue(currentValue) {
    return currentValue === 1 ? 5 : currentValue - 1;
  }
  render() {
    const countString = this.count?.toString();
    return this.interactiveContainer({ disabled: this.disabled, children: html`<span class=${safeClassMap(CSS.wrapper)}>${this.labelText && InternalLabel({ labelText: this.labelText, onClick: this.onLabelClick, required: this.required, tooltipText: this.messages.required }) || ""}<fieldset class=${safeClassMap(CSS.fieldSet)} .disabled=${this.disabled}><legend class=${safeClassMap(CSS.visuallyHidden)}>${this.messages.rating}</legend>${this.starsMap.map(({ average, checked, fraction, hovered, id, partial, selected, value, tabIndex }) => {
      return html`<label class=${safeClassMap({
        [CSS.star]: true,
        selected,
        hovered,
        average,
        partial
      })} data-value=${value ?? nothing} for=${id ?? nothing} @click=${this.handleLabelClick} @focus=${this.handleLabelFocus} @keydown=${this.handleLabelKeyDown} @pointerdown=${this.handleLabelPointerDown} @pointerover=${this.handleLabelPointerOver} tabindex=${tabIndex ?? nothing}><input aria-errormessage=${IDS.validationMessage} .ariaInvalid=${this.status === "invalid"} .ariaLabel=${getLabelText(this)} .ariaRequired=${this.required} .checked=${checked} class=${safeClassMap(CSS.visuallyHidden)} .disabled=${this.disabled || this.readOnly} id=${id ?? nothing} name=${this.guid ?? nothing} @change=${this.handleInputChange} tabindex=-1 type=radio .value=${live(value ?? "")}>${StarIcon({ full: selected || average || hovered, scale: this.scale })}${partial && html`<div class=${safeClassMap(CSS.fraction)} style=${safeStyleMap({ width: `${fraction * 100}%` })}>${StarIcon({ full: true, partial: true, scale: this.scale })}</div>` || ""}<span class=${safeClassMap(CSS.visuallyHidden)}>${this.messages.stars.replace("{num}", `${value}`)}</span></label>`;
    })}${(this.count || this.average) && this.showChip ? html`<calcite-chip .label=${countString} .scale=${this.scale} .value=${countString}>${!!this.average && html`<span class=${safeClassMap(CSS.numberAverage)}>${this.average.toString()}</span>` || ""}${!!this.count && html`<span class=${safeClassMap(CSS.numberCount)}>(${countString})</span>` || ""}</calcite-chip>` : null}</fieldset>${this.validationMessage && this.status === "invalid" ? Validation({ icon: this.validationIcon, id: IDS.validationMessage, message: this.validationMessage, scale: this.scale, status: this.status }) : null}</span>` });
  }
}
customElement("calcite-rating", Rating);
export {
  Rating
};
