{"version":3,"sources":["components/slider/slider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAwC,UAAU,EAAE,MAAM,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8B/E;;;;;;;GAOG;AACH,cACM,QAAS,SAAQ,aAAoD;IACzE;;OAEG;IACH,OAAO,CAAC,IAAI,CAAS;IAErB;;OAEG;IACH,OAAO,CAAC,IAAI,CAAO;IAEnB;;OAEG;IACH,OAAO,CAAC,KAAK,CAAO;IAEpB;;OAEG;IACH,OAAO,CAAC,UAAU,CAAO;IAEzB;;OAEG;IACH,OAAO,CAAC,+BAA+B,CAA+D;IAEtG;;OAEG;IACH,OAAO,CAAC,SAAS,CAAS;IAE1B;;;OAGG;IACH,OAAO,KAAK,KAAK,GAIhB;IAED,OAAO,KAAK,KAAK,QAIhB;IAED;;OAEG;IAEH,OAAO,CAAC,UAAU,CAAkB;IAEpC;;OAEG;IAEH,OAAO,CAAC,UAAU,CAAkB;IAEpC;;OAEG;IACH,iBAAiB;IAIjB,eAAe,CAAC,KAAK,EAAE,KAAK;IAQ5B;;OAEG;IACH,OAAO,CAAC,cAAc;IA0BtB;;OAEG;IACH,OAAO,CAAC,UAAU;IAKlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAmBpB;;;OAGG;IAGH,OAAO,CAAC,kBAAkB,CAKxB;IAEF;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAoB9B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAcd;IAEF;;OAEG;IAGH,OAAO,CAAC,kBAAkB,CAaxB;IAEF;;OAEG;IAEH,QAAQ,UAAS;IAEjB;;;OAGG;IAEH,aAAa;aAAoB,MAAM;iBAAW;IAElD;;;OAGG;IAEH,aAAa;aAAoB,MAAM;iBAAW;IAElD;;OAEG;IAEH,SAAS,SAAM;IAEf;;OAEG;IACH,IACI,GAAG,WAEN;IAED,IAAI,GAAG,CAAC,KAAK,QAAA,EAIZ;IAED;;OAEG;IACH,IACI,GAAG,WAEN;IAED,IAAI,GAAG,CAAC,KAAK,QAAA,EAIZ;IAED;;OAEG;IAEH,IAAI,EAAG,MAAM,CAAC;IAEd;;OAEG;IACH,IACI,IAAI,WAEP;IAED,IAAI,IAAI,CAAC,KAAK,QAAA,EAIb;IAED;;;OAGG;IACH,IACI,SAAS,WAEZ;IAED,IAAI,SAAS,CAAC,KAAK,QAAA,EAIlB;IAED;;OAEG;IAEH,KAAK,SAAM;IAEX,gBAAgB;IAOhB,iBAAiB;IAOjB,oBAAoB;IAQpB,YAAY,CAAC,iBAAiB,KAAA;IAoB9B,MAAM;IAsEN;;OAEG;IACH,MAAM,KAAK,aAAa,WAEvB;IAED;;OAEG;IACH,MAAM,KAAK,WAAW,WAErB;IAED;;OAEG;IACH,MAAM,KAAK,gBAAgB,WAE1B;IAED,MAAM,CAAC,MAAM,MAAU;CACxB;AAED,eAAe,QAAQ,CAAC","file":"slider.d.ts","sourcesContent":["/**\n * @license\n *\n * Copyright IBM Corp. 2019, 2021\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { classMap } from 'lit-html/directives/class-map';\nimport throttle from 'lodash-es/throttle';\nimport { html, property, query, customElement, LitElement } from 'lit-element';\nimport settings from 'carbon-components/es/globals/js/settings';\nimport FocusMixin from '../../globals/mixins/focus';\nimport FormMixin from '../../globals/mixins/form';\nimport HostListenerMixin from '../../globals/mixins/host-listener';\nimport HostListener from '../../globals/decorators/host-listener';\nimport ifNonEmpty from '../../globals/directives/if-non-empty';\nimport BXSliderInput from './slider-input';\nimport styles from './slider.scss';\n\nconst { prefix } = settings;\n\ninterface Cancelable {\n  cancel(): void;\n}\n\n/**\n * The direction to move the thumb, associated with key symbols.\n */\nconst THUMB_DIRECTION = {\n  Left: -1,\n  ArrowLeft: -1,\n  Up: -1,\n  ArrowUp: -1,\n  Right: 1,\n  ArrowRight: 1,\n  Down: 1,\n  ArrowDown: 1,\n};\n\n/**\n * Slider.\n * @element bx-slider\n * @slot label-text - The label text.\n * @slot max-text - The text for maximum value.\n * @slot min-text - The text for minimum value.\n * @fires bx-slider-changed - The custom event fired after the value is changed by user gesture.\n */\n@customElement(`${prefix}-slider`)\nclass BXSlider extends HostListenerMixin(FormMixin(FocusMixin(LitElement))) {\n  /**\n   * The internal value of `max` property.\n   */\n  private _max = '100';\n\n  /**\n   * The internal value of `min` property.\n   */\n  private _min = '0';\n\n  /**\n   * The internal value of `step` property.\n   */\n  private _step = '1';\n\n  /**\n   * The internal value of `stepRatio` property.\n   */\n  private _stepRatio = '4';\n\n  /**\n   * The handle for the throttled listener of `pointermove` event.\n   */\n  private _throttledHandlePointermoveImpl: (((event: PointerEvent) => void) & Cancelable) | null = null;\n\n  /**\n   * `true` if dragging of thumb is in progress.\n   */\n  private _dragging = false;\n\n  /**\n   * The rate of the thumb position in the track.\n   * When we try to set a new value, we adjust the value considering `step` property.\n   */\n  private get _rate() {\n    const { max, min, value } = this;\n    // Copes with out-of-range value coming programmatically or from `<bx-slider-input>`\n    return (Math.min(Number(max), Math.max(Number(min), value)) - Number(min)) / (Number(max) - Number(min));\n  }\n\n  private set _rate(rate: number) {\n    const { max, min, step } = this;\n    this.value =\n      Number(min) + Math.round(((Number(max) - Number(min)) * Math.min(1, Math.max(0, rate))) / Number(step)) * Number(step);\n  }\n\n  /**\n   * The DOM element of the thumb.\n   */\n  @query('#thumb')\n  private _thumbNode!: HTMLDivElement;\n\n  /**\n   * The DOM element of the track.\n   */\n  @query('#track')\n  private _trackNode!: HTMLDivElement;\n\n  /**\n   * Handles `click` event on the `<label>` to focus on the thumb.\n   */\n  _handleClickLabel() {\n    this._thumbNode?.focus();\n  }\n\n  _handleFormdata(event: Event) {\n    const { formData } = event as any; // TODO: Wait for `FormDataEvent` being available in `lib.dom.d.ts`\n    const { disabled, name, value } = this;\n    if (!disabled) {\n      formData.append(name, String(value));\n    }\n  }\n\n  /**\n   * Handles `keydown` event on the thumb to increase/decrease the value.\n   */\n  private _handleKeydown({ key, shiftKey }: KeyboardEvent) {\n    if (!this.disabled) {\n      if (key in THUMB_DIRECTION) {\n        const { max: rawMax, min: rawMin, step: rawStep, stepRatio: rawStepRatio, value } = this;\n        const max = Number(rawMax);\n        const min = Number(rawMin);\n        const step = Number(rawStep);\n        const stepRatio = Number(rawStepRatio);\n        const diff = (!shiftKey ? step : (max - min) / stepRatio) * THUMB_DIRECTION[key];\n        const stepCount = (value + diff) / step;\n        // Snaps to next\n        this.value = Math.min(max, Math.max(min, (diff >= 0 ? Math.floor(stepCount) : Math.ceil(stepCount)) * step));\n        this.dispatchEvent(\n          new CustomEvent((this.constructor as typeof BXSlider).eventChange, {\n            bubbles: true,\n            composed: true,\n            detail: {\n              value: this.value,\n              intermediate: false,\n            },\n          })\n        );\n      }\n    }\n  }\n\n  /**\n   * Handles `pointerdown` event on the thumb to start dragging.\n   */\n  private _startDrag() {\n    this._dragging = true;\n    this._thumbNode.style.touchAction = 'none';\n  }\n\n  /**\n   * Handles `pointerdown` event on the track to update the thumb position and the value as necessary.\n   */\n  private _handleClick(event: PointerEvent) {\n    if (!this.disabled) {\n      const { _trackNode: trackNode } = this;\n      const isRtl = trackNode.ownerDocument!.defaultView!.getComputedStyle(trackNode).getPropertyValue('direction') === 'rtl';\n      const thumbPosition = event.clientX;\n      const { left: trackLeft, width: trackWidth } = trackNode.getBoundingClientRect();\n      this._rate = (isRtl ? trackLeft + trackWidth - thumbPosition : thumbPosition - trackLeft) / trackWidth;\n      this.dispatchEvent(\n        new CustomEvent((this.constructor as typeof BXSlider).eventChange, {\n          bubbles: true,\n          composed: true,\n          detail: {\n            value: this.value,\n          },\n        })\n      );\n    }\n  }\n\n  /**\n   * Handles `pointermove` to update the thumb position and the value as necessary.\n   * @param event The event.\n   */\n  @HostListener('document:pointermove')\n  // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to\n  private _handlePointermove = (event: PointerEvent) => {\n    const { disabled, _dragging: dragging } = this;\n    if (!disabled && dragging) {\n      this._throttledHandlePointermoveImpl!(event);\n    }\n  };\n\n  /**\n   * Updates thumb position and value upon user's `pointermove` gesture.\n   * @param event The event.\n   */\n  private _handlePointermoveImpl(event: PointerEvent) {\n    const { disabled, _dragging: dragging, _trackNode: trackNode } = this;\n    if (!disabled && dragging) {\n      const isRtl = trackNode.ownerDocument!.defaultView!.getComputedStyle(trackNode).getPropertyValue('direction') === 'rtl';\n      const thumbPosition = event.clientX;\n      const { left: trackLeft, width: trackWidth } = this._trackNode.getBoundingClientRect();\n      this._rate = (isRtl ? trackLeft + trackWidth - thumbPosition : thumbPosition - trackLeft) / trackWidth;\n      this.dispatchEvent(\n        new CustomEvent((this.constructor as typeof BXSlider).eventChange, {\n          bubbles: true,\n          composed: true,\n          detail: {\n            value: this.value,\n            intermediate: true,\n          },\n        })\n      );\n    }\n  }\n\n  /**\n   * Handles `pointerup` and `pointerleave` event to finishing dragging.\n   */\n  private _endDrag = () => {\n    if (this._dragging) {\n      this.dispatchEvent(\n        new CustomEvent((this.constructor as typeof BXSlider).eventChange, {\n          bubbles: true,\n          composed: true,\n          detail: {\n            value: this.value,\n          },\n        })\n      );\n      this._dragging = false;\n      this._thumbNode.style.touchAction = '';\n    }\n  };\n\n  /**\n   * Handles `${prefix}-slider-input-changed` event to update the value.\n   */\n  @HostListener('eventChangeInput')\n  // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to\n  private _handleChangeInput = ({ detail }: CustomEvent) => {\n    const { intermediate, value } = detail;\n    this.value = value;\n    this.dispatchEvent(\n      new CustomEvent((this.constructor as typeof BXSlider).eventChange, {\n        bubbles: true,\n        composed: true,\n        detail: {\n          value,\n          intermediate,\n        },\n      })\n    );\n  };\n\n  /**\n   * `true` if the check box should be disabled.\n   */\n  @property({ type: Boolean, reflect: true })\n  disabled = false;\n\n  /**\n   * The formatter for the text for maximum value.\n   * Should be changed upon the locale the UI is rendered with.\n   */\n  @property({ attribute: false })\n  formatMaxText = ({ max }: { max: string }) => max;\n\n  /**\n   * The formatter for the text for minimum value.\n   * Should be changed upon the locale the UI is rendered with.\n   */\n  @property({ attribute: false })\n  formatMinText = ({ min }: { min: string }) => min;\n\n  /**\n   * The label text.\n   */\n  @property({ attribute: 'label-text' })\n  labelText = '';\n\n  /**\n   * The maximum value.\n   */\n  @property({ type: Number, reflect: true })\n  get max() {\n    return this._max.toString();\n  }\n\n  set max(value) {\n    const { max: oldMax } = this;\n    this._max = value;\n    this.requestUpdate('max', oldMax);\n  }\n\n  /**\n   * The minimum value.\n   */\n  @property({ type: Number, reflect: true })\n  get min() {\n    return this._min.toString();\n  }\n\n  set min(value) {\n    const { min: oldMin } = this;\n    this._min = value;\n    this.requestUpdate('min', oldMin);\n  }\n\n  /**\n   * The form name.\n   */\n  @property()\n  name!: string;\n\n  /**\n   * The snapping step of the value.\n   */\n  @property({ type: Number, reflect: true })\n  get step() {\n    return this._step.toString();\n  }\n\n  set step(value) {\n    const { step: oldStep } = this;\n    this._step = value;\n    this.requestUpdate('step', oldStep);\n  }\n\n  /**\n   * A value determining how much the value should increase/decrease by Shift+arrow keys,\n   * which will be `(max - min) / stepRatio`.\n   */\n  @property({ type: Number, reflect: true, attribute: 'step-ratio' })\n  get stepRatio() {\n    return this._stepRatio.toString();\n  }\n\n  set stepRatio(value) {\n    const { stepRatio: oldStepRatio } = this;\n    this._stepRatio = value;\n    this.requestUpdate('stepRatio', oldStepRatio);\n  }\n\n  /**\n   * The value.\n   */\n  @property({ type: Number })\n  value = 50;\n\n  createRenderRoot() {\n    return this.attachShadow({\n      mode: 'open',\n      delegatesFocus: Number((/Safari\\/(\\d+)/.exec(navigator.userAgent) ?? ['', 0])[1]) <= 537,\n    });\n  }\n\n  connectedCallback() {\n    super.connectedCallback();\n    if (!this._throttledHandlePointermoveImpl) {\n      this._throttledHandlePointermoveImpl = throttle(this._handlePointermoveImpl, 10);\n    }\n  }\n\n  disconnectedCallback() {\n    if (this._throttledHandlePointermoveImpl) {\n      this._throttledHandlePointermoveImpl.cancel();\n      this._throttledHandlePointermoveImpl = null;\n    }\n    super.disconnectedCallback();\n  }\n\n  shouldUpdate(changedProperties) {\n    const input = this.querySelector((this.constructor as typeof BXSlider).selectorInput) as BXSliderInput;\n    if (changedProperties.has('disabled')) {\n      if (input) {\n        input.disabled = this.disabled;\n      }\n      if (this.disabled) {\n        this._dragging = false;\n      }\n    }\n    if (input) {\n      ['max', 'min', 'step', 'value'].forEach(name => {\n        if (changedProperties.has(name)) {\n          input[name] = this[name];\n        }\n      });\n    }\n    return true;\n  }\n\n  render() {\n    const {\n      disabled,\n      formatMaxText,\n      formatMinText,\n      labelText,\n      max,\n      min,\n      name,\n      value,\n      _rate: rate,\n      _handleClickLabel: handleClickLabel,\n      _handleKeydown: handleKeydown,\n      _handleClick: handleClick,\n      _startDrag: startDrag,\n      _endDrag: endDrag,\n    } = this;\n    const labelClasses = classMap({\n      [`${prefix}--label`]: true,\n      [`${prefix}--label--disabled`]: disabled,\n    });\n    const sliderClasses = classMap({\n      [`${prefix}--slider`]: true,\n      [`${prefix}--slider--disabled`]: disabled,\n    });\n    return html`\n      <label class=\"${labelClasses}\" @click=\"${handleClickLabel}\">\n        <slot name=\"label-text\">${labelText}</slot>\n      </label>\n      <div class=\"${prefix}--slider-container\">\n        <span class=\"${prefix}--slider__range-label\">\n          <slot name=\"min-text\">${formatMinText({ min })}</slot>\n        </span>\n        <div\n          @keydown=\"${handleKeydown}\"\n          @click=\"${handleClick}\"\n          @pointerup=\"${endDrag}\"\n          @pointerleave=\"${endDrag}\"\n          class=\"${sliderClasses}\"\n          role=\"presentation\">\n          <div\n            id=\"thumb\"\n            class=\"${prefix}--slider__thumb\"\n            role=\"slider\"\n            tabindex=\"0\"\n            aria-valuemax=\"${max}\"\n            aria-valuemin=\"${min}\"\n            aria-valuenow=\"${value}\"\n            style=\"left: ${rate * 100}%\"\n            @pointerdown=\"${startDrag}\"></div>\n          <div id=\"track\" class=\"${prefix}--slider__track\"></div>\n          <div class=\"${prefix}-ce--slider__filled-track-container\">\n            <div class=\"${prefix}--slider__filled-track\" style=\"transform: translate(0%, -50%) scaleX(${rate})\"></div>\n          </div>\n          <input\n            class=\"${prefix}--slider__input\"\n            type=\"hidden\"\n            name=\"${ifNonEmpty(name)}\"\n            .value=\"${value}\"\n            min=\"${ifNonEmpty(min)}\"\n            max=\"${ifNonEmpty(max)}\" />\n        </div>\n        <span class=\"${prefix}--slider__range-label\">\n          <slot name=\"max-text\">${formatMaxText({ max })}</slot>\n        </span>\n        <slot></slot>\n      </div>\n    `;\n  }\n\n  /**\n   * A selector that will return the `<input>` box got entering the value directly.\n   */\n  static get selectorInput() {\n    return `${prefix}-slider-input`;\n  }\n\n  /**\n   * The name of the custom event fired after the value is changed by user gesture.\n   */\n  static get eventChange() {\n    return `${prefix}-slider-changed`;\n  }\n\n  /**\n   * The name of the custom event fired after the value is changed in `<bx-slider-input>` by user gesture.\n   */\n  static get eventChangeInput() {\n    return `${prefix}-slider-input-changed`;\n  }\n\n  static styles = styles;\n}\n\nexport default BXSlider;\n"]}