{"version":3,"sources":["components/date-picker/date-picker.ts"],"names":[],"mappings":"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","file":"date-picker.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 { html, property, query, customElement, LitElement } from 'lit-element';\nimport flatpickr from 'flatpickr';\nimport { Instance as FlatpickrInstance } from 'flatpickr/dist/types/instance';\nimport { Locale as FlatpickrLocale } from 'flatpickr/dist/types/locale';\nimport { Options as FlatpickrOptions, Plugin as FlatpickrPlugin } from 'flatpickr/dist/types/options';\nimport settings from 'carbon-components/es/globals/js/settings';\nimport FormMixin from '../../globals/mixins/form';\nimport HostListenerMixin from '../../globals/mixins/host-listener';\nimport HostListener from '../../globals/decorators/host-listener';\nimport { getISODateString, parseISODateString } from './iso-date';\nimport BXDatePickerInput from './date-picker-input';\nimport appendToPlugin from './append-to-plugin';\nimport cssClassPlugin from './css-class-plugin';\nimport fixEventsPlugin from './fix-events-plugin';\nimport focusPlugin from './focus-plugin';\nimport iconPlugin from './icon-plugin';\nimport monthSelectPlugin from './month-select-plugin';\nimport rangePlugin from './range-plugin';\nimport shadowDOMEventPlugin from './shadow-dom-events-plugin';\nimport stateHandshakePlugin from './state-handshake-plugin';\nimport styles from './date-picker.scss';\n\nconst { prefix } = settings;\n\n/**\n * Date picker modes.\n */\nenum DATE_PICKER_MODE {\n  /**\n   * Simple mode, without calendar dropdown.\n   */\n  SIMPLE = 'simple',\n\n  /**\n   * Single date mode.\n   */\n  SINGLE = 'single',\n\n  /**\n   * Range mode.\n   */\n  RANGE = 'range',\n}\n\n/**\n * Date picker.\n * @element bx-date-picker\n * @fires bx-date-picker-changed - The custom event fired on this element when Flatpickr updates its value.\n */\n@customElement(`${prefix}-date-picker`)\nclass BXDatePicker extends HostListenerMixin(FormMixin(LitElement)) {\n  /**\n   * The slotted `<bx-date-input kind=\"from\">`.\n   */\n  private _dateInteractNode: BXDatePickerInput | null = null;\n\n  /**\n   * The element to put calendar dropdown in.\n   */\n  @query('#floating-menu-container')\n  private _floatingMenuContainerNode!: HTMLDivElement;\n\n  /**\n   * The internal placeholder for the `value` property.\n   */\n  private _value!: string;\n\n  /**\n   * @returns The effective date picker mode, determined by the child `<bx-date-picker-input>`.\n   */\n  private get _mode() {\n    const { selectorInputFrom, selectorInputTo } = this.constructor as typeof BXDatePicker;\n    if (this.querySelector(selectorInputTo)) {\n      return DATE_PICKER_MODE.RANGE;\n    }\n    if (this.querySelector(selectorInputFrom)) {\n      return DATE_PICKER_MODE.SINGLE;\n    }\n    return DATE_PICKER_MODE.SIMPLE;\n  }\n\n  /**\n   * @returns The Flatpickr plugins to use.\n   */\n  private get _datePickerPlugins(): FlatpickrPlugin[] {\n    const {\n      classCalendarContainer,\n      classMonth,\n      classWeekdays,\n      classDays,\n      classWeekday,\n      classDay,\n      classNoBorder,\n      selectorInputFrom,\n      selectorInputTo,\n      _selectorFlatpickrMonthYearContainer: selectorFlatpickrMonthYearContainer,\n      _selectorFlatpickrYearContainer: selectorFlatpickrYearContainer,\n      _selectorFlatpickrCurrentMonth: selectorFlatpickrCurrentMonth,\n      _selectorFlatpickrMonth: selectorFlatpickrMonth,\n      _selectorFlatpickrWeekdays: selectorFlatpickrWeekdays,\n      _selectorFlatpickrDays: selectorFlatpickrDays,\n      _selectorFlatpickrWeekday: selectorFlatpickrWeekday,\n      _selectorFlatpickrDay: selectorFlatpickrDay,\n      _classFlatpickrCurrentMonth: classFlatpickrCurrentMonth,\n      _classFlatpickrToday: classFlatpickrToday,\n    } = this.constructor as typeof BXDatePicker;\n    const { _floatingMenuContainerNode: floatingMenuContainerNode, _mode: mode } = this;\n    const inputFrom = this.querySelector(selectorInputFrom);\n    const inputTo = this.querySelector(selectorInputTo);\n    const plugins = [\n      appendToPlugin({ appendTo: floatingMenuContainerNode }),\n      cssClassPlugin({\n        classCalendarContainer,\n        classMonth,\n        classWeekdays,\n        classDays,\n        classWeekday,\n        classDay,\n        classNoBorder,\n        selectorFlatpickrMonth,\n        selectorFlatpickrWeekdays,\n        selectorFlatpickrDays,\n        selectorFlatpickrWeekday,\n        selectorFlatpickrDay,\n        classFlatpickrToday,\n      }),\n      fixEventsPlugin({ inputFrom: inputFrom as BXDatePickerInput, inputTo: inputTo as BXDatePickerInput }),\n      focusPlugin({ inputFrom: inputFrom as BXDatePickerInput, inputTo: inputTo as BXDatePickerInput }),\n      iconPlugin(),\n      monthSelectPlugin({\n        selectorFlatpickrMonthYearContainer,\n        selectorFlatpickrYearContainer,\n        selectorFlatpickrCurrentMonth,\n        classFlatpickrCurrentMonth,\n      }),\n      shadowDOMEventPlugin(),\n      stateHandshakePlugin(this),\n    ];\n    if (mode === DATE_PICKER_MODE.RANGE) {\n      // Flatpickr runs event handlers of last registered plugins first.\n      // Ensures `onValueUpdate` of `rangePlugin` runs first\n      // given Flatpickr puts `01/01/1970 to 01/02/1970` to from date\n      // where `rangePlugin` overrides it to separate them to from/to dates.\n      // We want to ensure our handler of `onValueUpdate` (notably one in `<bx-date-picker-input>`)\n      // gets the `<input>` value set by `rangePlugin` instead of Flatpickr core.\n      plugins.push(rangePlugin({ input: inputTo as HTMLInputElement }));\n    }\n    return plugins;\n  }\n\n  /**\n   * @returns The options to instantiate Flatpickr with.\n   */\n  private get _datePickerOptions(): FlatpickrOptions {\n    const {\n      locale = (this.constructor as typeof BXDatePicker).defaultLocale,\n      enabledRange,\n      _dateInteractNode: dateInteractNode,\n      _datePickerPlugins: plugins,\n      _handleFlatpickrError: handleFlatpickrError,\n    } = this;\n    // We use `<bx-date-picker-input>` to communicate values/events with Flatpickr,\n    // but want to use `<input>` in shadow DOM to base the calendar dropdown's position on\n    const { input: positionElement } = dateInteractNode!;\n    const [minDate = undefined, maxDate = undefined] = !enabledRange ? [] : enabledRange.split('/');\n    return {\n      allowInput: true,\n      dateFormat: this.dateFormat ?? (this.constructor as typeof BXDatePicker).defaultDateFormat,\n      disableMobile: true,\n      errorHandler: handleFlatpickrError,\n      locale,\n      maxDate,\n      minDate,\n      positionElement,\n      plugins,\n    };\n  }\n\n  /**\n   * Handles `${prefix}-date-picker-changed` event on this element.\n   */\n  @HostListener('eventChange')\n  // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to\n  private _handleChange = ({ detail }: CustomEvent) => {\n    this._value = detail.selectedDates.map(date => getISODateString(date)).join('/');\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, value);\n    }\n  }\n\n  /**\n   * Handles `slotchange` event in the `<slot>`.\n   */\n  private _handleSlotChange({ target }: Event) {\n    const { _dateInteractNode: oldDateInteractNode } = this;\n    const dateInteractNode = (target as HTMLSlotElement)\n      .assignedNodes()\n      .find(\n        node =>\n          node.nodeType === Node.ELEMENT_NODE &&\n          (node as HTMLElement).matches((this.constructor as typeof BXDatePicker).selectorInputFrom)\n      );\n    if (oldDateInteractNode !== dateInteractNode) {\n      this._dateInteractNode = dateInteractNode as BXDatePickerInput;\n      this._instantiateDatePicker();\n    }\n  }\n\n  /**\n   * Fires a custom event to notify an error in Flatpickr.\n   */\n  private _handleFlatpickrError = (error: Error) => {\n    this.dispatchEvent(\n      new CustomEvent((this.constructor as typeof BXDatePicker).eventFlatpickrError, {\n        bubbles: true,\n        cancelable: false,\n        composed: true,\n        detail: {\n          error,\n        },\n      })\n    );\n  };\n\n  /**\n   * Instantiates Flatpickr.\n   * @returns The Flatpickr instance.\n   */\n  private _instantiateDatePicker() {\n    this._releaseDatePicker();\n    const { _dateInteractNode: dateInteractNode } = this;\n    // `this._dateInteractNode` won't be there unless there is a slotted `<bx-date-input type=\"from\">`,\n    // which means Flatpickr will never be instantiated in \"simple\" mode.\n    if (dateInteractNode && dateInteractNode.input) {\n      this.calendar = flatpickr(dateInteractNode as any, this._datePickerOptions);\n    }\n    return this.calendar;\n  }\n\n  /**\n   * Releases Flatpickr instances.\n   */\n  private _releaseDatePicker() {\n    if (this.calendar) {\n      this.calendar.destroy();\n      this.calendar = null;\n    }\n    return this.calendar;\n  }\n\n  /**\n   * The Flatpickr instance.\n   */\n  calendar: FlatpickrInstance | null = null;\n\n  /**\n   * The date format to let Flatpickr use.\n   */\n  @property({ attribute: 'date-format' })\n  dateFormat!: string;\n\n  /**\n   * Controls the disabled state of the input\n   */\n  @property({ type: Boolean, reflect: true })\n  disabled = false;\n\n  /**\n   * The localization data.\n   */\n  @property({ attribute: false })\n  locale!: FlatpickrLocale;\n\n  /**\n   * The date range that a user can pick in calendar dropdown.\n   */\n  @property({ attribute: 'enabled-range' })\n  enabledRange!: string;\n\n  /**\n   * Name for the input in the `FormData`\n   */\n  @property()\n  name = '';\n\n  /**\n   * `true` if the date picker should be open.\n   */\n  @property({ type: Boolean, reflect: true })\n  open = false;\n\n  /**\n   * The date(s) in ISO8601 format (date portion only), for range mode, '/' is used for separate start/end dates.\n   */\n  @property()\n  get value() {\n    return this._value;\n  }\n\n  set value(value: string) {\n    const { _value: oldValue } = this;\n    this._value = value;\n    this.requestUpdate('value', oldValue);\n  }\n\n  connectedCallback() {\n    super.connectedCallback();\n    this._instantiateDatePicker();\n  }\n\n  disconnectedCallback() {\n    this._releaseDatePicker();\n    super.disconnectedCallback();\n  }\n\n  updated(changedProperties) {\n    const { calendar, disabled, open } = this;\n    const { selectorInputFrom, selectorInputTo } = this.constructor as typeof BXDatePicker;\n    const inputFrom = this.querySelector(selectorInputFrom) as BXDatePickerInput;\n    const inputTo = this.querySelector(selectorInputTo) as BXDatePickerInput;\n    if (calendar && changedProperties.has('dateFormat')) {\n      const { dateFormat } = this;\n      calendar.set({ dateFormat });\n    }\n    if (changedProperties.has('enabledRange')) {\n      const { enabledRange } = this;\n      const dates = enabledRange.split('/').map(item => (!item ? undefined : parseISODateString(item))); // Allows empty start/end\n      if (dates.some(item => Boolean(item && isNaN(Number(item))))) {\n        // Allows empty start/end\n        throw new Error(`Wrong date format found in \\`enabledRange\\` property: ${enabledRange}`);\n      }\n      const [minDate, maxDate] = dates;\n      if (minDate && maxDate && minDate > maxDate) {\n        throw new Error(\n          `In \\`enabledRange\\` property, the end date shouldn't be smaller than the start date. You have: ${enabledRange}`\n        );\n      }\n      if (calendar) {\n        calendar.set({ minDate, maxDate });\n      }\n    }\n    if (changedProperties.has('open') && calendar) {\n      if (open) {\n        calendar.open();\n      } else {\n        calendar.close();\n      }\n    }\n    if (changedProperties.has('disabled')) {\n      [inputFrom, inputTo].forEach(input => {\n        if (input) {\n          input.disabled = disabled;\n        }\n      });\n    }\n    if (changedProperties.has('value')) {\n      const { value } = this;\n      const dates = value\n        .split('/')\n        .filter(Boolean)\n        .map(item => parseISODateString(item));\n      if (dates.some(item => isNaN(Number(item)))) {\n        throw new Error(`Wrong date format found in \\`value\\` property: ${value}`);\n      }\n      const [startDate, endDate] = dates;\n      if (startDate && endDate && startDate > endDate) {\n        throw new Error(`In \\`value\\` property, the end date shouldn't be smaller than the start date. You have: ${value}`);\n      }\n      if (calendar) {\n        calendar.setDate(dates);\n        [inputFrom, inputTo].forEach((input, i) => {\n          if (input) {\n            input.value = !dates[i] ? '' : calendar.formatDate(new Date(dates[i]), calendar.config.dateFormat);\n          }\n        });\n      }\n    }\n  }\n\n  render() {\n    const { _handleSlotChange: handleSlotChange } = this;\n    return html`\n      <a class=\"${prefix}--visually-hidden\" href=\"javascript:void 0\" role=\"navigation\"></a>\n      <slot @slotchange=\"${handleSlotChange}\"></slot>\n      <div id=\"floating-menu-container\"></div>\n      <a class=\"${prefix}--visually-hidden\" href=\"javascript:void 0\" role=\"navigation\"></a>\n    `;\n  }\n\n  /**\n   * The CSS selector for Flatpickr's month/year portion.\n   */\n  private static _selectorFlatpickrMonthYearContainer = '.flatpickr-current-month';\n\n  /**\n   * The CSS selector for Flatpickr's year portion.\n   */\n  private static _selectorFlatpickrYearContainer = '.numInputWrapper';\n\n  /**\n   * The CSS selector for the inner element of Flatpickr's month portion.\n   */\n  private static _selectorFlatpickrCurrentMonth = '.cur-month';\n\n  /**\n   * The CSS selector for Flatpickr's month navigator.\n   */\n  private static _selectorFlatpickrMonth = '.flatpickr-month';\n\n  /**\n   * The CSS selector for Flatpickr's container of the weekdays.\n   */\n  private static _selectorFlatpickrWeekdays = '.flatpickr-weekdays';\n\n  /**\n   * The CSS selector for Flatpickr's container of the days.\n   */\n  private static _selectorFlatpickrDays = '.flatpickr-days';\n\n  /**\n   * The CSS selector applied to Flatpickr's each weekdays.\n   */\n  private static _selectorFlatpickrWeekday = '.flatpickr-weekday';\n\n  /**\n   * The CSS selector applied to Flatpickr's each days.\n   */\n  private static _selectorFlatpickrDay = '.flatpickr-day';\n\n  /**\n   * The CSS class for the inner element of Flatpickr's month portion.\n   */\n  private static _classFlatpickrCurrentMonth = 'cur-month';\n\n  /**\n   * The CSS class applied to Flatpickr's \"today\" highlight.\n   */\n  private static _classFlatpickrToday = 'today';\n\n  /**\n   * The CSS class for the calendar dropdown.\n   */\n  static get classCalendarContainer() {\n    return `${prefix}--date-picker__calendar`;\n  }\n\n  /**\n   * The CSS class for the month navigator.\n   */\n  static get classMonth() {\n    return `${prefix}--date-picker__month`;\n  }\n\n  /**\n   * The CSS class for the container of the weekdays.\n   */\n  static get classWeekdays() {\n    return `${prefix}--date-picker__weekdays`;\n  }\n\n  /**\n   * The CSS class for the container of the days.\n   */\n  static get classDays() {\n    return `${prefix}--date-picker__days`;\n  }\n\n  /**\n   * The CSS class applied to each weekdays.\n   */\n  static get classWeekday() {\n    return `${prefix}--date-picker__weekday`;\n  }\n\n  /**\n   * The CSS class applied to each days.\n   */\n  static get classDay() {\n    return `${prefix}--date-picker__day`;\n  }\n\n  /**\n   * The CSS class applied to the \"today\" highlight if there are any dates selected.\n   */\n  static classNoBorder = 'no-border';\n\n  /**\n   * The default date format.\n   */\n  static defaultDateFormat = 'm/d/Y';\n\n  /**\n   * The default localization data.\n   */\n  static defaultLocale = flatpickr.l10ns.default;\n\n  /**\n   * A selector that will return the `<input>` to enter starting date.\n   */\n  static get selectorInputFrom() {\n    return `${prefix}-date-picker-input[kind=\"single\"],${prefix}-date-picker-input[kind=\"from\"]`;\n  }\n\n  /**\n   * A selector that will return the `<input>` to enter end date.\n   */\n  static get selectorInputTo() {\n    return `${prefix}-date-picker-input[kind=\"to\"]`;\n  }\n\n  /**\n   * The name of the custom event when Flatpickr throws an error.\n   */\n  static get eventFlatpickrError() {\n    return `${prefix}-date-picker-flatpickr-error`;\n  }\n\n  /**\n   * The name of the custom event fired on this element when Flatpickr updates its value.\n   */\n  static get eventChange() {\n    return `${prefix}-date-picker-changed`;\n  }\n\n  static styles = styles;\n}\n\nexport default BXDatePicker;\n"]}