<svelte:options
  customElement={{
    tag: 'm-quantityselector',
    props: {
      isinvalid: { reflect: true, type: 'Boolean', attribute: 'isinvalid' },
      disabled: { reflect: true, type: 'Boolean', attribute: 'disabled' },
      readonly: { reflect: true, type: 'Boolean', attribute: 'readonly' },
    },
    extend: customElementForwardEvents,
  }}
/>

<script lang="ts">
  import { customElementForwardEvents } from '../../utils';
  import { More24, Less24 } from '@mozaic-ds/icons-svelte';
  /**
   * A quantity selector is an input component that allows users to increment or decrement a numeric value, typically using plus (+) and minus (−) buttons. It provides a simple and efficient way to adjust quantities without manual typing, ensuring controlled input. This component is commonly used in e-commerce, inventory management, and settings where users need to specify amounts.
   */
  interface Props {
    [key: string]: any;
    /**
     * A unique identifier for the quantity selector element, used to associate the label with the form element.
     */
    id: string;
    /**
     * The name attribute for the quantity selector element, typically used for form submission.
     */
    name?: string;
    /**
     * The current value of the quantity selector field.
     */
    value?: number;
    /**
     * If `true`, applies an invalid state to the quantity selector.
     */
    isinvalid?: boolean;
    /**
     * If `true`, disables the quantity selector, making it non-interactive.
     */
    disabled?: boolean;
    /**
     * Determines the size of the quantity selector.
     */
    size?: 's' | 'm';
    /**
     * Minimum acceptable value for the quantity selector.
     */
    min?: number;
    /**
     * Maximum acceptable value for the quantity selector.
     */
    max?: number;
    /**
     * Determines how much the value will change per click when the quantity is increased or decreased.
     */
    step?: number;
    /**
     * If `true`, the quantity selector is read-only (cannot be edited).
     */
    readonly?: boolean;
    /**
     * The label text for the increment button.
     */
    incrementlabel?: string;
    /**
     * The label text for the decrement button.
     */
    decrementlabel?: string;
  }

  let {
    id,
    value = $bindable(1),
    min = 1,
    max = 100,
    step = 1,
    size = 'm',
    disabled,
    isinvalid = false,
    name = 'quantity-selector-input',
    readonly,
    decrementlabel = 'Decrement',
    incrementlabel = 'Increment',
    class: className,
    ...attrs
  }: Props = $props();

  const onValue = (): void => {
    const numericValue = Number(value);
    if (numericValue > max) {
      value = max;
    } else if (numericValue < min) {
      value = min;
    } else {
      value = numericValue;
    }
  };

  const onIncrement = (): void => {
    const numericValue = Number(value);
    const numericStep = Number(step);

    if (numericValue + numericStep <= max) {
      value = numericValue + numericStep;
    } else {
      value = max;
    }
  };

  const onDecrement = (): void => {
    const numericValue = Number(value);
    const numericStep = Number(step);

    if (numericValue - numericStep >= min) {
      value = numericValue - numericStep;
    } else {
      value = min;
    }
  };
</script>

<div
  class={[
    'mc-quantity-selector',
    `mc-quantity-selector--${size}`,
    isinvalid && 'is-invalid',
    className,
  ]}
>
  <input
    type="number"
    {id}
    {name}
    bind:value
    oninput={onValue}
    class="mc-quantity-selector__control"
    aria-valuemin={min}
    aria-valuemax={max}
    aria-valuenow={value}
    aria-invalid={`${isinvalid}`}
    {readonly}
    {disabled}
    {...attrs}
  />
  <button
    type="button"
    aria-controls={id}
    class="mc-quantity-selector__button mc-quantity-selector__button--increase"
    tabindex="-1"
    disabled={value === max || disabled}
    onclick={onIncrement}
  >
    <span class="mc-quantity-selector__icon">
      <More24 />
    </span>
    <span class="mc-quantity-selector__label">{incrementlabel}</span>
  </button>
  <button
    type="button"
    aria-controls={id}
    class="mc-quantity-selector__button mc-quantity-selector__button--decrease"
    tabindex="-1"
    disabled={value === min || disabled}
    onclick={onDecrement}
  >
    <span class="mc-quantity-selector__icon">
      <Less24 />
    </span>
    <span class="mc-quantity-selector__label">{decrementlabel}</span>
  </button>
</div>

<style>/**
 * Do not edit directly, this file was auto-generated.
 */
.mc-quantity-selector {
  background-color: var(--forms-color-background-default, #ffffff);
  border: var(--border-width-s, 0.0625rem) solid var(--forms-color-border-default, #666666);
  border-radius: var(--forms-border-radius, 0.25rem);
  transition: all ease 200ms;
  color: var(--forms-color-text-default, #000000);
  display: block;
  width: 100%;
  height: 3rem;
  display: flex;
  gap: 0.25rem;
  padding: 0.1875rem;
  position: relative;
  border-radius: var(--border-radius-s, 0.25rem);
  box-sizing: border-box;
}
.mc-quantity-selector__control {
  background-color: transparent;
  border-width: 0;
  color: inherit;
  font-family: inherit;
  outline: none;
}
.mc-quantity-selector__control[type=number] {
  /* For Blink & WebKit rendering engines */
}
.mc-quantity-selector__control[type=number]::-webkit-inner-spin-button, .mc-quantity-selector__control[type=number]::-webkit-outer-spin-button {
  appearance: none;
  margin: 0;
}
.mc-quantity-selector__control[type=number] {
  /* For Gecko rendering engine */
  appearance: textfield;
}
.mc-quantity-selector__control[type=search]::-webkit-search-decoration, .mc-quantity-selector__control[type=search]::-webkit-search-cancel-button {
  appearance: none;
}
.mc-quantity-selector__control {
  padding: 0;
  font-size: inherit;
  font-size: var(--font-size-150, 1rem);
  line-height: var(--line-height-m, 1.5);
  font-weight: var(--font-weight-semi-bold, 600);
  cursor: inherit;
  text-align: center;
  flex-grow: 1;
}
.mc-quantity-selector__control::placeholder {
  color: var(--forms-color-placeholder, #666666);
}
.mc-quantity-selector__button {
  background-color: transparent;
  border-width: 0;
  color: initial;
  font-family: inherit;
  outline: none;
  appearance: none;
  cursor: pointer;
  padding: 0;
  height: 2.5rem;
  width: 2.5rem;
  border-radius: var(--border-radius-full, 100%);
  color: var(--quantity-selector-color-button-text-default, #000000);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.mc-quantity-selector__button:disabled {
  color: var(--quantity-selector-color-button-text-disabled, #b3b3b3);
  cursor: not-allowed;
}
.mc-quantity-selector__button:hover:not(:disabled) {
  background-color: var(--quantity-selector-color-button-background-hover, rgba(0, 0, 0, 0.05));
}
.mc-quantity-selector__button--decrease {
  order: -1;
}
.mc-quantity-selector__icon {
  height: 1.5rem;
  width: 1.5rem;
  fill: currentcolor;
}
.mc-quantity-selector__label {
  clip-path: inset(100%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  padding: 0;
  width: 1px;
}
.mc-quantity-selector::after {
  transition: box-shadow 200ms ease;
  content: "";
  position: absolute;
  inset: -0.125rem var(--inset-x, 3rem);
  pointer-events: none;
  display: block;
  border-radius: var(--border-radius-s, 0.25rem);
}
.mc-quantity-selector:hover:not(:focus-within) {
  border-color: var(--forms-color-border-hover, #4d4d4d);
  box-shadow: 0 0 0 var(--border-width-s, 0.0625rem) var(--forms-color-border-hover, #4d4d4d);
}
.mc-quantity-selector:has(input:disabled) {
  background-color: var(--forms-color-background-disabled, #d9d9d9);
  cursor: not-allowed;
  border-color: transparent;
  box-shadow: none;
  color: var(--forms-color-text-disabled, #737373);
  pointer-events: none;
}
.mc-quantity-selector:has(input:disabled) .mc-quantity-selector__button:disabled {
  color: var(--forms-color-icon-disabled, #737373);
}
.mc-quantity-selector:has(input[readonly]) {
  border-color: var(--forms-color-border-read-only, #cccccc);
  pointer-events: none;
}
.mc-quantity-selector:has(input[readonly]) .mc-quantity-selector__control[readonly] {
  text-align: left;
  padding-left: 0.5rem;
}
.mc-quantity-selector:has(input:focus)::after {
  box-shadow: 0 0 0 0.125rem var(--focus-color-mid, var(--focus-color-outline-mid, #ffffff)), 0 0 0 0.25rem var(--focus-color-outer, var(--focus-color-outline-outer, #000000));
  outline: 0.125rem solid transparent;
  outline-offset: 0.125rem;
}
.mc-quantity-selector--s {
  --inset-x: 2rem;
  height: 2rem;
}
.mc-quantity-selector--s .mc-quantity-selector__button {
  height: 1.5rem;
  width: 1.5rem;
}
.mc-quantity-selector--s .mc-quantity-selector__icon {
  height: 1.25rem;
  width: 1.25rem;
}
.mc-quantity-selector.is-invalid {
  border-color: var(--forms-color-border-invalid, #ea302d);
  box-shadow: 0 0 0 var(--border-width-s, 0.0625rem) var(--forms-color-border-invalid, #ea302d);
}
.mc-quantity-selector.is-invalid:hover:not(:focus-within) {
  border-color: var(--forms-color-border-invalid-hover, #c61112);
  box-shadow: 0 0 0 var(--border-width-s, 0.0625rem) var(--forms-color-border-invalid-hover, #c61112);
}
.mc-quantity-selector * {
  box-sizing: border-box;
}</style>
