{"version":3,"sources":["components/date-picker/focus-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEtD,OAAO,MAAM,MAAM,+BAA+B,CAAC;AACnD,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,SAAS,EAAE,iBAAiB,CAAC;IAE7B;;OAEG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,oCAAqC,SAAQ,iBAAiB;IAC7E;;OAEG;IACH,+BAA+B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhD;;OAEG;IACH,sCAAsC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvD;;OAEG;IACH,oCAAoC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAErD;;OAEG;IACH,oCAAoC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAErD;;OAEG;IACH,kCAAkC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnD;;OAEG;IACH,eAAe,CAAC,EAAE,gBAAgB,CAAC;CACpC;;AAED;;;GAGG;AACH,wBA4GE","file":"focus-plugin.d.ts","sourcesContent":["/**\n * @license\n *\n * Copyright IBM Corp. 2019\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 { Instance as FlatpickrInstance } from 'flatpickr/dist/types/instance';\nimport { Plugin } from 'flatpickr/dist/types/options';\nimport on from 'carbon-components/es/globals/js/misc/on';\nimport Handle from '../../globals/internal/handle';\nimport BXDatePickerInput from './date-picker-input';\n\n/**\n * The configuration for the Flatpickr plugin to set CSS classes specific to this design system.\n */\nexport interface DatePickerFocusPluginConfig {\n  /**\n   * The input box to enter starting date.\n   */\n  inputFrom: BXDatePickerInput;\n\n  /**\n   * The input box to enter end date.\n   */\n  inputTo?: BXDatePickerInput;\n}\n\n/**\n * `FlatpickrInstance` with additional properties used for `carbonFlatpickrFocusPlugin`.\n */\nexport interface ExtendedFlatpickrInstanceFocusPlugin extends FlatpickrInstance {\n  /**\n   * The handle for `blur` event handler in calendar dropdown.\n   */\n  _hBXCEDatePickerFocusPluginBlur?: Handle | null;\n\n  /**\n   * The handle for `keydown` event handler in the `<input>` for the starting date.\n   */\n  _hBXCEDatePickerFocusPluginKeydownFrom?: Handle | null;\n\n  /**\n   * The handle for `keydown` event handler in the `<input>` for the end date.\n   */\n  _hBXCEDatePickerFocusPluginKeydownTo?: Handle | null;\n\n  /**\n   * The handle for `focus` event handler in the `<input>` for the starting date.\n   */\n  _hBXCEDatePickerFocusPluginFocusFrom?: Handle | null;\n\n  /**\n   * The handle for `focus` event handler in the `<input>` for the end date.\n   */\n  _hBXCEDatePickerFocusPluginFocusTo?: Handle | null;\n\n  /**\n   * Lastly focused `<input>` for starting/end date.\n   */\n  _lastFocusInput?: HTMLInputElement;\n}\n\n/**\n * @param config Plugin configuration.\n * @returns A Flatpickr plugin to manage focus to align with the UX pattern in our design system.\n */\nexport default (config: DatePickerFocusPluginConfig): Plugin => (fp: ExtendedFlatpickrInstanceFocusPlugin) => {\n  /**\n   * Focuses on calendar dropdown.\n   */\n  const focusCalendar = () => {\n    const { calendarContainer, selectedDateElem, todayDateElem } = fp;\n    (selectedDateElem || todayDateElem || calendarContainer).focus();\n  };\n\n  /**\n   * Handles `blur` event to move the focus back to the `<input>`.\n   */\n  const handleBlur = ({ target, relatedTarget }: FocusEvent) => {\n    // Obtains `beingUpdated` up-front because it'll be flushed out shortly\n    const { calendarContainer, isOpen } = fp;\n    if (isOpen && calendarContainer.contains(target as Node) && !calendarContainer.contains(relatedTarget as Node)) {\n      Promise.resolve().then(() => {\n        const rootNode = (target as Node).getRootNode();\n        // This `blur` event handler can be called from Flatpickr's code cleaning up calenar dropdown's DOM,\n        // and changing focus in such condition causes removing an orphaned DOM node,\n        // because Flatpickr redraws the calendar dropdown when the `<input>` gets focus.\n        if (rootNode.nodeType === Node.DOCUMENT_NODE || rootNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n          if (fp._lastFocusInput === config.inputTo) {\n            config.inputTo!.focus();\n          } else {\n            config.inputFrom.focus();\n          }\n          // Closing after moving focus. Reversing the order will cause re-opening calendar dropdown upon focusing\n          fp.close();\n        }\n      });\n    }\n  };\n\n  /**\n   * Handles `keydown` event to move focus on calendar dropdown.\n   */\n  const handleInputKeydown = (event: KeyboardEvent) => {\n    const { key } = event;\n    if (key === 'ArrowDown' || key === 'Down' || key === 'Enter') {\n      event.preventDefault();\n      fp.open();\n      if (key !== 'Enter') {\n        focusCalendar();\n      } else {\n        // Hitting Enter key blurs the `<input>`, causing any element to lose focus\n        setTimeout(focusCalendar, 0);\n      }\n    }\n  };\n\n  /**\n   * Handles `focus` event on `<input>` for starting/end date to track the lastly focused one.\n   */\n  const handleInputFocus = ({ target }: FocusEvent) => {\n    fp._lastFocusInput = target as HTMLInputElement;\n  };\n\n  /**\n   * Releases event listeners used in this Flatpickr plugin.\n   */\n  const release = () => {\n    if (fp._hBXCEDatePickerFocusPluginBlur) {\n      fp._hBXCEDatePickerFocusPluginBlur = fp._hBXCEDatePickerFocusPluginBlur.release();\n    }\n    if (fp._hBXCEDatePickerFocusPluginFocusTo) {\n      fp._hBXCEDatePickerFocusPluginFocusTo = fp._hBXCEDatePickerFocusPluginFocusTo.release();\n    }\n    if (fp._hBXCEDatePickerFocusPluginFocusFrom) {\n      fp._hBXCEDatePickerFocusPluginFocusFrom = fp._hBXCEDatePickerFocusPluginFocusFrom.release();\n    }\n    if (fp._hBXCEDatePickerFocusPluginKeydownTo) {\n      fp._hBXCEDatePickerFocusPluginKeydownTo = fp._hBXCEDatePickerFocusPluginKeydownTo.release();\n    }\n    if (fp._hBXCEDatePickerFocusPluginKeydownFrom) {\n      fp._hBXCEDatePickerFocusPluginKeydownFrom = fp._hBXCEDatePickerFocusPluginKeydownFrom.release();\n    }\n  };\n\n  /**\n   * Sets up event listeners used for this Flatpickr plugin.\n   */\n  const init = () => {\n    release();\n    const { inputFrom, inputTo } = config;\n    fp._hBXCEDatePickerFocusPluginBlur = on(fp.calendarContainer, 'blur', handleBlur, true);\n    fp._hBXCEDatePickerFocusPluginKeydownFrom = on(inputFrom, 'keydown', handleInputKeydown);\n    if (inputTo) {\n      fp._hBXCEDatePickerFocusPluginKeydownTo = on(inputTo, 'keydown', handleInputKeydown);\n    }\n    fp._hBXCEDatePickerFocusPluginFocusFrom = on(inputFrom, 'focus', handleInputFocus);\n    if (inputTo) {\n      fp._hBXCEDatePickerFocusPluginFocusTo = on(inputTo, 'focus', handleInputFocus);\n    }\n  };\n\n  /**\n   * Registers this Flatpickr plugin.\n   * @param calendar The Flatpickr instance.\n   */\n  const register = () => {\n    fp.loadedPlugins.push('carbonFlatpickrFocusPlugin');\n  };\n\n  return {\n    onReady: [register, init],\n    onDestroy: release,\n  };\n};\n"]}