{"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;iCAMuB,2BAA2B,KAAG,MAAM;AAJ5D;;;GAGG;AACH,wBA6GI","file":"focus-plugin.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 { 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 =>\n  (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"]}