@keenthemes/ktui 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +88 -0
- package/LICENSE.md +21 -0
- package/README.md +124 -0
- package/dist/ktui.js +19201 -0
- package/dist/ktui.min.js +2 -0
- package/dist/ktui.min.js.map +1 -0
- package/lib/cjs/components/accordion/accordion.js +168 -0
- package/lib/cjs/components/accordion/accordion.js.map +1 -0
- package/lib/cjs/components/accordion/index.js +6 -0
- package/lib/cjs/components/accordion/index.js.map +1 -0
- package/lib/cjs/components/accordion/types.js +3 -0
- package/lib/cjs/components/accordion/types.js.map +1 -0
- package/lib/cjs/components/collapse/collapse.js +169 -0
- package/lib/cjs/components/collapse/collapse.js.map +1 -0
- package/lib/cjs/components/collapse/index.js +6 -0
- package/lib/cjs/components/collapse/index.js.map +1 -0
- package/lib/cjs/components/collapse/types.js +3 -0
- package/lib/cjs/components/collapse/types.js.map +1 -0
- package/lib/cjs/components/component.js +135 -0
- package/lib/cjs/components/component.js.map +1 -0
- package/lib/cjs/components/config.js +26 -0
- package/lib/cjs/components/config.js.map +1 -0
- package/lib/cjs/components/config.umd.js +23 -0
- package/lib/cjs/components/config.umd.js.map +1 -0
- package/lib/cjs/components/constants.js +15 -0
- package/lib/cjs/components/constants.js.map +1 -0
- package/lib/cjs/components/datatable/datatable.js +1464 -0
- package/lib/cjs/components/datatable/datatable.js.map +1 -0
- package/lib/cjs/components/datatable/index.js +6 -0
- package/lib/cjs/components/datatable/index.js.map +1 -0
- package/lib/cjs/components/datatable/types.js +3 -0
- package/lib/cjs/components/datatable/types.js.map +1 -0
- package/lib/cjs/components/dismiss/dismiss.js +131 -0
- package/lib/cjs/components/dismiss/dismiss.js.map +1 -0
- package/lib/cjs/components/dismiss/index.js +6 -0
- package/lib/cjs/components/dismiss/index.js.map +1 -0
- package/lib/cjs/components/dismiss/types.js +3 -0
- package/lib/cjs/components/dismiss/types.js.map +1 -0
- package/lib/cjs/components/drawer/drawer.js +347 -0
- package/lib/cjs/components/drawer/drawer.js.map +1 -0
- package/lib/cjs/components/drawer/index.js +6 -0
- package/lib/cjs/components/drawer/index.js.map +1 -0
- package/lib/cjs/components/drawer/types.js +3 -0
- package/lib/cjs/components/drawer/types.js.map +1 -0
- package/lib/cjs/components/dropdown/dropdown.js +403 -0
- package/lib/cjs/components/dropdown/dropdown.js.map +1 -0
- package/lib/cjs/components/dropdown/index.js +6 -0
- package/lib/cjs/components/dropdown/index.js.map +1 -0
- package/lib/cjs/components/dropdown/types.js +3 -0
- package/lib/cjs/components/dropdown/types.js.map +1 -0
- package/lib/cjs/components/image-input/image-input.js +191 -0
- package/lib/cjs/components/image-input/image-input.js.map +1 -0
- package/lib/cjs/components/image-input/index.js +6 -0
- package/lib/cjs/components/image-input/index.js.map +1 -0
- package/lib/cjs/components/image-input/types.js +3 -0
- package/lib/cjs/components/image-input/types.js.map +1 -0
- package/lib/cjs/components/menu/index.js +6 -0
- package/lib/cjs/components/menu/index.js.map +1 -0
- package/lib/cjs/components/menu/menu.js +1021 -0
- package/lib/cjs/components/menu/menu.js.map +1 -0
- package/lib/cjs/components/menu/types.js +3 -0
- package/lib/cjs/components/menu/types.js.map +1 -0
- package/lib/cjs/components/modal/index.js +6 -0
- package/lib/cjs/components/modal/index.js.map +1 -0
- package/lib/cjs/components/modal/modal.js +316 -0
- package/lib/cjs/components/modal/modal.js.map +1 -0
- package/lib/cjs/components/modal/types.js +3 -0
- package/lib/cjs/components/modal/types.js.map +1 -0
- package/lib/cjs/components/reparent/index.js +6 -0
- package/lib/cjs/components/reparent/index.js.map +1 -0
- package/lib/cjs/components/reparent/reparent.js +93 -0
- package/lib/cjs/components/reparent/reparent.js.map +1 -0
- package/lib/cjs/components/reparent/types.js +3 -0
- package/lib/cjs/components/reparent/types.js.map +1 -0
- package/lib/cjs/components/scrollable/index.js +6 -0
- package/lib/cjs/components/scrollable/index.js.map +1 -0
- package/lib/cjs/components/scrollable/scrollable.js +259 -0
- package/lib/cjs/components/scrollable/scrollable.js.map +1 -0
- package/lib/cjs/components/scrollable/types.js +3 -0
- package/lib/cjs/components/scrollable/types.js.map +1 -0
- package/lib/cjs/components/scrollspy/index.js +6 -0
- package/lib/cjs/components/scrollspy/index.js.map +1 -0
- package/lib/cjs/components/scrollspy/scrollspy.js +174 -0
- package/lib/cjs/components/scrollspy/scrollspy.js.map +1 -0
- package/lib/cjs/components/scrollspy/types.js +3 -0
- package/lib/cjs/components/scrollspy/types.js.map +1 -0
- package/lib/cjs/components/scrollto/index.js +6 -0
- package/lib/cjs/components/scrollto/index.js.map +1 -0
- package/lib/cjs/components/scrollto/scrollto.js +103 -0
- package/lib/cjs/components/scrollto/scrollto.js.map +1 -0
- package/lib/cjs/components/scrollto/types.js +3 -0
- package/lib/cjs/components/scrollto/types.js.map +1 -0
- package/lib/cjs/components/stepper/index.js +6 -0
- package/lib/cjs/components/stepper/index.js.map +1 -0
- package/lib/cjs/components/stepper/stepper.js +258 -0
- package/lib/cjs/components/stepper/stepper.js.map +1 -0
- package/lib/cjs/components/stepper/types.js +3 -0
- package/lib/cjs/components/stepper/types.js.map +1 -0
- package/lib/cjs/components/sticky/index.js +6 -0
- package/lib/cjs/components/sticky/index.js.map +1 -0
- package/lib/cjs/components/sticky/sticky.js +297 -0
- package/lib/cjs/components/sticky/sticky.js.map +1 -0
- package/lib/cjs/components/sticky/types.js +3 -0
- package/lib/cjs/components/sticky/types.js.map +1 -0
- package/lib/cjs/components/tabs/index.js +6 -0
- package/lib/cjs/components/tabs/index.js.map +1 -0
- package/lib/cjs/components/tabs/tabs.js +146 -0
- package/lib/cjs/components/tabs/tabs.js.map +1 -0
- package/lib/cjs/components/tabs/types.js +3 -0
- package/lib/cjs/components/tabs/types.js.map +1 -0
- package/lib/cjs/components/theme/index.js +6 -0
- package/lib/cjs/components/theme/index.js.map +1 -0
- package/lib/cjs/components/theme/theme.js +147 -0
- package/lib/cjs/components/theme/theme.js.map +1 -0
- package/lib/cjs/components/theme/types.js +3 -0
- package/lib/cjs/components/theme/types.js.map +1 -0
- package/lib/cjs/components/toggle/index.js +6 -0
- package/lib/cjs/components/toggle/index.js.map +1 -0
- package/lib/cjs/components/toggle/toggle.js +139 -0
- package/lib/cjs/components/toggle/toggle.js.map +1 -0
- package/lib/cjs/components/toggle/types.js +3 -0
- package/lib/cjs/components/toggle/types.js.map +1 -0
- package/lib/cjs/components/toggle-password/index.js +6 -0
- package/lib/cjs/components/toggle-password/index.js.map +1 -0
- package/lib/cjs/components/toggle-password/toggle-password.js +131 -0
- package/lib/cjs/components/toggle-password/toggle-password.js.map +1 -0
- package/lib/cjs/components/toggle-password/types.js +3 -0
- package/lib/cjs/components/toggle-password/types.js.map +1 -0
- package/lib/cjs/components/tooltip/index.js +6 -0
- package/lib/cjs/components/tooltip/index.js.map +1 -0
- package/lib/cjs/components/tooltip/tooltip.js +271 -0
- package/lib/cjs/components/tooltip/tooltip.js.map +1 -0
- package/lib/cjs/components/tooltip/types.js +3 -0
- package/lib/cjs/components/tooltip/types.js.map +1 -0
- package/lib/cjs/helpers/data.js +33 -0
- package/lib/cjs/helpers/data.js.map +1 -0
- package/lib/cjs/helpers/dom.js +297 -0
- package/lib/cjs/helpers/dom.js.map +1 -0
- package/lib/cjs/helpers/event-handler.js +36 -0
- package/lib/cjs/helpers/event-handler.js.map +1 -0
- package/lib/cjs/helpers/utils.js +94 -0
- package/lib/cjs/helpers/utils.js.map +1 -0
- package/lib/cjs/index.js +105 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/types.js +3 -0
- package/lib/cjs/types.js.map +1 -0
- package/lib/esm/components/accordion/accordion.js +165 -0
- package/lib/esm/components/accordion/accordion.js.map +1 -0
- package/lib/esm/components/accordion/index.js +2 -0
- package/lib/esm/components/accordion/index.js.map +1 -0
- package/lib/esm/components/accordion/types.js +2 -0
- package/lib/esm/components/accordion/types.js.map +1 -0
- package/lib/esm/components/collapse/collapse.js +166 -0
- package/lib/esm/components/collapse/collapse.js.map +1 -0
- package/lib/esm/components/collapse/index.js +2 -0
- package/lib/esm/components/collapse/index.js.map +1 -0
- package/lib/esm/components/collapse/types.js +2 -0
- package/lib/esm/components/collapse/types.js.map +1 -0
- package/lib/esm/components/component.js +133 -0
- package/lib/esm/components/component.js.map +1 -0
- package/lib/esm/components/config.js +24 -0
- package/lib/esm/components/config.js.map +1 -0
- package/lib/esm/components/config.umd.js +23 -0
- package/lib/esm/components/config.umd.js.map +1 -0
- package/lib/esm/components/constants.js +12 -0
- package/lib/esm/components/constants.js.map +1 -0
- package/lib/esm/components/datatable/datatable.js +1461 -0
- package/lib/esm/components/datatable/datatable.js.map +1 -0
- package/lib/esm/components/datatable/index.js +2 -0
- package/lib/esm/components/datatable/index.js.map +1 -0
- package/lib/esm/components/datatable/types.js +2 -0
- package/lib/esm/components/datatable/types.js.map +1 -0
- package/lib/esm/components/dismiss/dismiss.js +128 -0
- package/lib/esm/components/dismiss/dismiss.js.map +1 -0
- package/lib/esm/components/dismiss/index.js +2 -0
- package/lib/esm/components/dismiss/index.js.map +1 -0
- package/lib/esm/components/dismiss/types.js +2 -0
- package/lib/esm/components/dismiss/types.js.map +1 -0
- package/lib/esm/components/drawer/drawer.js +344 -0
- package/lib/esm/components/drawer/drawer.js.map +1 -0
- package/lib/esm/components/drawer/index.js +2 -0
- package/lib/esm/components/drawer/index.js.map +1 -0
- package/lib/esm/components/drawer/types.js +2 -0
- package/lib/esm/components/drawer/types.js.map +1 -0
- package/lib/esm/components/dropdown/dropdown.js +400 -0
- package/lib/esm/components/dropdown/dropdown.js.map +1 -0
- package/lib/esm/components/dropdown/index.js +2 -0
- package/lib/esm/components/dropdown/index.js.map +1 -0
- package/lib/esm/components/dropdown/types.js +2 -0
- package/lib/esm/components/dropdown/types.js.map +1 -0
- package/lib/esm/components/image-input/image-input.js +188 -0
- package/lib/esm/components/image-input/image-input.js.map +1 -0
- package/lib/esm/components/image-input/index.js +2 -0
- package/lib/esm/components/image-input/index.js.map +1 -0
- package/lib/esm/components/image-input/types.js +2 -0
- package/lib/esm/components/image-input/types.js.map +1 -0
- package/lib/esm/components/menu/index.js +2 -0
- package/lib/esm/components/menu/index.js.map +1 -0
- package/lib/esm/components/menu/menu.js +1018 -0
- package/lib/esm/components/menu/menu.js.map +1 -0
- package/lib/esm/components/menu/types.js +2 -0
- package/lib/esm/components/menu/types.js.map +1 -0
- package/lib/esm/components/modal/index.js +2 -0
- package/lib/esm/components/modal/index.js.map +1 -0
- package/lib/esm/components/modal/modal.js +313 -0
- package/lib/esm/components/modal/modal.js.map +1 -0
- package/lib/esm/components/modal/types.js +2 -0
- package/lib/esm/components/modal/types.js.map +1 -0
- package/lib/esm/components/reparent/index.js +2 -0
- package/lib/esm/components/reparent/index.js.map +1 -0
- package/lib/esm/components/reparent/reparent.js +90 -0
- package/lib/esm/components/reparent/reparent.js.map +1 -0
- package/lib/esm/components/reparent/types.js +2 -0
- package/lib/esm/components/reparent/types.js.map +1 -0
- package/lib/esm/components/scrollable/index.js +2 -0
- package/lib/esm/components/scrollable/index.js.map +1 -0
- package/lib/esm/components/scrollable/scrollable.js +256 -0
- package/lib/esm/components/scrollable/scrollable.js.map +1 -0
- package/lib/esm/components/scrollable/types.js +2 -0
- package/lib/esm/components/scrollable/types.js.map +1 -0
- package/lib/esm/components/scrollspy/index.js +2 -0
- package/lib/esm/components/scrollspy/index.js.map +1 -0
- package/lib/esm/components/scrollspy/scrollspy.js +171 -0
- package/lib/esm/components/scrollspy/scrollspy.js.map +1 -0
- package/lib/esm/components/scrollspy/types.js +2 -0
- package/lib/esm/components/scrollspy/types.js.map +1 -0
- package/lib/esm/components/scrollto/index.js +2 -0
- package/lib/esm/components/scrollto/index.js.map +1 -0
- package/lib/esm/components/scrollto/scrollto.js +100 -0
- package/lib/esm/components/scrollto/scrollto.js.map +1 -0
- package/lib/esm/components/scrollto/types.js +2 -0
- package/lib/esm/components/scrollto/types.js.map +1 -0
- package/lib/esm/components/stepper/index.js +2 -0
- package/lib/esm/components/stepper/index.js.map +1 -0
- package/lib/esm/components/stepper/stepper.js +255 -0
- package/lib/esm/components/stepper/stepper.js.map +1 -0
- package/lib/esm/components/stepper/types.js +2 -0
- package/lib/esm/components/stepper/types.js.map +1 -0
- package/lib/esm/components/sticky/index.js +2 -0
- package/lib/esm/components/sticky/index.js.map +1 -0
- package/lib/esm/components/sticky/sticky.js +294 -0
- package/lib/esm/components/sticky/sticky.js.map +1 -0
- package/lib/esm/components/sticky/types.js +2 -0
- package/lib/esm/components/sticky/types.js.map +1 -0
- package/lib/esm/components/tabs/index.js +2 -0
- package/lib/esm/components/tabs/index.js.map +1 -0
- package/lib/esm/components/tabs/tabs.js +143 -0
- package/lib/esm/components/tabs/tabs.js.map +1 -0
- package/lib/esm/components/tabs/types.js +2 -0
- package/lib/esm/components/tabs/types.js.map +1 -0
- package/lib/esm/components/theme/index.js +2 -0
- package/lib/esm/components/theme/index.js.map +1 -0
- package/lib/esm/components/theme/theme.js +144 -0
- package/lib/esm/components/theme/theme.js.map +1 -0
- package/lib/esm/components/theme/types.js +2 -0
- package/lib/esm/components/theme/types.js.map +1 -0
- package/lib/esm/components/toggle/index.js +2 -0
- package/lib/esm/components/toggle/index.js.map +1 -0
- package/lib/esm/components/toggle/toggle.js +136 -0
- package/lib/esm/components/toggle/toggle.js.map +1 -0
- package/lib/esm/components/toggle/types.js +2 -0
- package/lib/esm/components/toggle/types.js.map +1 -0
- package/lib/esm/components/toggle-password/index.js +2 -0
- package/lib/esm/components/toggle-password/index.js.map +1 -0
- package/lib/esm/components/toggle-password/toggle-password.js +128 -0
- package/lib/esm/components/toggle-password/toggle-password.js.map +1 -0
- package/lib/esm/components/toggle-password/types.js +2 -0
- package/lib/esm/components/toggle-password/types.js.map +1 -0
- package/lib/esm/components/tooltip/index.js +2 -0
- package/lib/esm/components/tooltip/index.js.map +1 -0
- package/lib/esm/components/tooltip/tooltip.js +268 -0
- package/lib/esm/components/tooltip/tooltip.js.map +1 -0
- package/lib/esm/components/tooltip/types.js +2 -0
- package/lib/esm/components/tooltip/types.js.map +1 -0
- package/lib/esm/helpers/data.js +31 -0
- package/lib/esm/helpers/data.js.map +1 -0
- package/lib/esm/helpers/dom.js +295 -0
- package/lib/esm/helpers/dom.js.map +1 -0
- package/lib/esm/helpers/event-handler.js +34 -0
- package/lib/esm/helpers/event-handler.js.map +1 -0
- package/lib/esm/helpers/utils.js +92 -0
- package/lib/esm/helpers/utils.js.map +1 -0
- package/lib/esm/index.js +79 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/types.js +2 -0
- package/lib/esm/types.js.map +1 -0
- package/package.json +85 -0
- package/prettier.config.js +9 -0
- package/src/components/accordion/accordion-menu.css +51 -0
- package/src/components/accordion/accordion.css +86 -0
- package/src/components/accordion/accordion.ts +221 -0
- package/src/components/accordion/index.ts +7 -0
- package/src/components/accordion/types.ts +16 -0
- package/src/components/alert/alert.css +282 -0
- package/src/components/avatar/avatar.css +46 -0
- package/src/components/badge/badge.css +176 -0
- package/src/components/breadcrumb/breadcrumb.css +38 -0
- package/src/components/btn/btn.css +227 -0
- package/src/components/card/card.css +158 -0
- package/src/components/checkbox/checkbox.css +74 -0
- package/src/components/collapse/collapse.css +14 -0
- package/src/components/collapse/collapse.ts +200 -0
- package/src/components/collapse/index.ts +7 -0
- package/src/components/collapse/types.ts +16 -0
- package/src/components/component.ts +132 -0
- package/src/components/constants.ts +16 -0
- package/src/components/datatable/datatable-checkbox.ts +236 -0
- package/src/components/datatable/datatable-sort.ts +154 -0
- package/src/components/datatable/datatable.css +110 -0
- package/src/components/datatable/datatable.ts +1657 -0
- package/src/components/datatable/index.ts +19 -0
- package/src/components/datatable/types.ts +203 -0
- package/src/components/datepicker/calendar.ts +1397 -0
- package/src/components/datepicker/config.ts +368 -0
- package/src/components/datepicker/datepicker.css +7 -0
- package/src/components/datepicker/datepicker.ts +1287 -0
- package/src/components/datepicker/dropdown.ts +757 -0
- package/src/components/datepicker/events.ts +149 -0
- package/src/components/datepicker/index.ts +10 -0
- package/src/components/datepicker/keyboard.ts +646 -0
- package/src/components/datepicker/locales.ts +80 -0
- package/src/components/datepicker/templates.ts +792 -0
- package/src/components/datepicker/types.ts +154 -0
- package/src/components/datepicker/utils.ts +631 -0
- package/src/components/dismiss/dismiss.css +10 -0
- package/src/components/dismiss/dismiss.ts +152 -0
- package/src/components/dismiss/index.ts +7 -0
- package/src/components/dismiss/types.ts +17 -0
- package/src/components/drawer/drawer.css +97 -0
- package/src/components/drawer/drawer.ts +437 -0
- package/src/components/drawer/index.ts +7 -0
- package/src/components/drawer/types.ts +25 -0
- package/src/components/dropdown/dropdown-menu.css +56 -0
- package/src/components/dropdown/dropdown.css +46 -0
- package/src/components/dropdown/dropdown.ts +549 -0
- package/src/components/dropdown/index.ts +7 -0
- package/src/components/dropdown/types.ts +28 -0
- package/src/components/form/form.css +54 -0
- package/src/components/image-input/image-input.css +56 -0
- package/src/components/image-input/image-input.ts +249 -0
- package/src/components/image-input/index.ts +10 -0
- package/src/components/image-input/types.ts +12 -0
- package/src/components/input/input-group.css +42 -0
- package/src/components/input/input.css +136 -0
- package/src/components/kbd/kbd.css +30 -0
- package/src/components/label/label.css +20 -0
- package/src/components/link/link.css +81 -0
- package/src/components/modal/index.ts +7 -0
- package/src/components/modal/modal.css +73 -0
- package/src/components/modal/modal.ts +382 -0
- package/src/components/modal/types.ts +21 -0
- package/src/components/pagination/pagination.css +26 -0
- package/src/components/popover/popover.css +22 -0
- package/src/components/progress/progress.css +51 -0
- package/src/components/radio/radio.css +51 -0
- package/src/components/reparent/index.ts +7 -0
- package/src/components/reparent/reparent.ts +109 -0
- package/src/components/reparent/types.ts +15 -0
- package/src/components/scrollable/index.ts +10 -0
- package/src/components/scrollable/scrollable.css +29 -0
- package/src/components/scrollable/scrollable.ts +297 -0
- package/src/components/scrollable/types.ts +16 -0
- package/src/components/scrollspy/index.ts +7 -0
- package/src/components/scrollspy/scrollspy.css +13 -0
- package/src/components/scrollspy/scrollspy.ts +224 -0
- package/src/components/scrollspy/types.ts +15 -0
- package/src/components/scrollto/index.ts +7 -0
- package/src/components/scrollto/scrollto.ts +127 -0
- package/src/components/scrollto/types.ts +15 -0
- package/src/components/select/combobox.ts +305 -0
- package/src/components/select/config.ts +324 -0
- package/src/components/select/dropdown.ts +510 -0
- package/src/components/select/index.ts +13 -0
- package/src/components/select/option.ts +43 -0
- package/src/components/select/remote.ts +477 -0
- package/src/components/select/search.ts +430 -0
- package/src/components/select/select.css +105 -0
- package/src/components/select/select.ts +1916 -0
- package/src/components/select/tags.ts +123 -0
- package/src/components/select/templates.ts +531 -0
- package/src/components/select/types.ts +36 -0
- package/src/components/select/utils.ts +747 -0
- package/src/components/select/variants.css +5 -0
- package/src/components/separator/separator.css +14 -0
- package/src/components/skeleton/skeleton.css +10 -0
- package/src/components/stepper/index.ts +7 -0
- package/src/components/stepper/stepper.css +49 -0
- package/src/components/stepper/stepper.ts +308 -0
- package/src/components/stepper/types.ts +13 -0
- package/src/components/sticky/index.ts +7 -0
- package/src/components/sticky/sticky.css +22 -0
- package/src/components/sticky/sticky.ts +381 -0
- package/src/components/sticky/types.ts +23 -0
- package/src/components/switch/switch.css +110 -0
- package/src/components/table/table.css +168 -0
- package/src/components/tabs/index.ts +7 -0
- package/src/components/tabs/tabs.css +40 -0
- package/src/components/tabs/tabs.ts +190 -0
- package/src/components/tabs/types.ts +13 -0
- package/src/components/textarea/textarea.css +35 -0
- package/src/components/theme-switch/index.ts +10 -0
- package/src/components/theme-switch/theme-switch.css +22 -0
- package/src/components/theme-switch/theme-switch.ts +176 -0
- package/src/components/theme-switch/types.ts +15 -0
- package/src/components/toggle/index.ts +7 -0
- package/src/components/toggle/toggle.css +13 -0
- package/src/components/toggle/toggle.ts +173 -0
- package/src/components/toggle/types.ts +18 -0
- package/src/components/toggle-group/toggle-group.css +55 -0
- package/src/components/toggle-password/index.ts +10 -0
- package/src/components/toggle-password/toggle-password.css +13 -0
- package/src/components/toggle-password/toggle-password.ts +159 -0
- package/src/components/toggle-password/types.ts +13 -0
- package/src/components/tooltip/index.ts +7 -0
- package/src/components/tooltip/tooltip.css +18 -0
- package/src/components/tooltip/tooltip.ts +361 -0
- package/src/components/tooltip/types.ts +28 -0
- package/src/helpers/data.ts +46 -0
- package/src/helpers/dom.ts +405 -0
- package/src/helpers/event-handler.ts +61 -0
- package/src/helpers/utils.ts +183 -0
- package/src/index.ts +113 -0
- package/src/types.ts +23 -0
- package/styles.css +48 -0
- package/tsconfig.json +17 -0
- package/webpack.config.js +113 -0
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
|
|
3
|
+
* Copyright 2025 by Keenthemes Inc
|
|
4
|
+
* @version: 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
Instance as PopperInstance,
|
|
8
|
+
createPopper,
|
|
9
|
+
Placement,
|
|
10
|
+
} from '@popperjs/core';
|
|
11
|
+
import KTDom from '../../helpers/dom';
|
|
12
|
+
import KTData from '../../helpers/data';
|
|
13
|
+
import KTComponent from '../component';
|
|
14
|
+
import { KTDatepickerConfigInterface } from './types';
|
|
15
|
+
import { KTDatepickerStateManager } from './config';
|
|
16
|
+
import { KTDatepickerEvents } from './types';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Class to manage focus within the dropdown
|
|
20
|
+
*/
|
|
21
|
+
class FocusManager {
|
|
22
|
+
private _element: HTMLElement;
|
|
23
|
+
private _focusableSelector: string =
|
|
24
|
+
'button:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
25
|
+
|
|
26
|
+
constructor(element: HTMLElement) {
|
|
27
|
+
this._element = element;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get all visible focusable options
|
|
32
|
+
*/
|
|
33
|
+
public getVisibleOptions(): HTMLElement[] {
|
|
34
|
+
return Array.from(
|
|
35
|
+
this._element.querySelectorAll(this._focusableSelector),
|
|
36
|
+
).filter((el) => {
|
|
37
|
+
const element = el as HTMLElement;
|
|
38
|
+
return element.offsetParent !== null; // Only visible elements
|
|
39
|
+
}) as HTMLElement[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Apply focus to an element
|
|
44
|
+
*/
|
|
45
|
+
public applyFocus(element: HTMLElement): void {
|
|
46
|
+
if (element && typeof element.focus === 'function') {
|
|
47
|
+
element.focus();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Focus next element
|
|
53
|
+
*/
|
|
54
|
+
public focusNext(): void {
|
|
55
|
+
const options = this.getVisibleOptions();
|
|
56
|
+
const currentFocused = document.activeElement;
|
|
57
|
+
|
|
58
|
+
let nextIndex = 0;
|
|
59
|
+
if (currentFocused) {
|
|
60
|
+
const currentIndex = options.indexOf(currentFocused as HTMLElement);
|
|
61
|
+
nextIndex = currentIndex >= 0 ? (currentIndex + 1) % options.length : 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (options.length > 0) {
|
|
65
|
+
this.applyFocus(options[nextIndex]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Focus previous element
|
|
71
|
+
*/
|
|
72
|
+
public focusPrevious(): void {
|
|
73
|
+
const options = this.getVisibleOptions();
|
|
74
|
+
const currentFocused = document.activeElement;
|
|
75
|
+
|
|
76
|
+
let prevIndex = options.length - 1;
|
|
77
|
+
if (currentFocused) {
|
|
78
|
+
const currentIndex = options.indexOf(currentFocused as HTMLElement);
|
|
79
|
+
prevIndex =
|
|
80
|
+
currentIndex >= 0
|
|
81
|
+
? (currentIndex - 1 + options.length) % options.length
|
|
82
|
+
: prevIndex;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (options.length > 0) {
|
|
86
|
+
this.applyFocus(options[prevIndex]);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Scroll element into view
|
|
92
|
+
*/
|
|
93
|
+
public scrollIntoView(element: HTMLElement): void {
|
|
94
|
+
if (element && typeof element.scrollIntoView === 'function') {
|
|
95
|
+
element.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Clean up resources
|
|
101
|
+
*/
|
|
102
|
+
public dispose(): void {
|
|
103
|
+
// Nothing to clean up yet
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Class to manage event listeners
|
|
109
|
+
*/
|
|
110
|
+
class EventManager {
|
|
111
|
+
private _listeners: Map<HTMLElement, Map<string, Function[]>> = new Map();
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Add event listener and track it
|
|
115
|
+
*/
|
|
116
|
+
public addListener(
|
|
117
|
+
element: HTMLElement,
|
|
118
|
+
eventType: string,
|
|
119
|
+
handler: Function,
|
|
120
|
+
): void {
|
|
121
|
+
if (!this._listeners.has(element)) {
|
|
122
|
+
this._listeners.set(element, new Map());
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const elementListeners = this._listeners.get(element)!;
|
|
126
|
+
if (!elementListeners.has(eventType)) {
|
|
127
|
+
elementListeners.set(eventType, []);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const handlers = elementListeners.get(eventType)!;
|
|
131
|
+
element.addEventListener(eventType, handler as EventListener);
|
|
132
|
+
handlers.push(handler);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Remove all listeners for an element
|
|
137
|
+
*/
|
|
138
|
+
public removeAllListeners(element: HTMLElement): void {
|
|
139
|
+
if (this._listeners.has(element)) {
|
|
140
|
+
const elementListeners = this._listeners.get(element)!;
|
|
141
|
+
|
|
142
|
+
elementListeners.forEach((handlers, eventType) => {
|
|
143
|
+
handlers.forEach((handler) => {
|
|
144
|
+
element.removeEventListener(eventType, handler as EventListener);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
this._listeners.delete(element);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Focus trap class to manage keyboard focus within the dropdown
|
|
155
|
+
*/
|
|
156
|
+
class FocusTrap {
|
|
157
|
+
private _element: HTMLElement;
|
|
158
|
+
private _focusableElements: HTMLElement[] = [];
|
|
159
|
+
private _firstFocusableElement: HTMLElement | null = null;
|
|
160
|
+
private _lastFocusableElement: HTMLElement | null = null;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Constructor
|
|
164
|
+
*
|
|
165
|
+
* @param element - Element to trap focus within
|
|
166
|
+
*/
|
|
167
|
+
constructor(element: HTMLElement) {
|
|
168
|
+
this._element = element;
|
|
169
|
+
this._update();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Update the focusable elements
|
|
174
|
+
*/
|
|
175
|
+
public update(): void {
|
|
176
|
+
this._update();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Update the list of focusable elements
|
|
181
|
+
*/
|
|
182
|
+
private _update(): void {
|
|
183
|
+
// Get all focusable elements
|
|
184
|
+
const focusableElements = this._element.querySelectorAll(
|
|
185
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// Convert to array and filter out disabled elements
|
|
189
|
+
this._focusableElements = Array.from(focusableElements).filter(
|
|
190
|
+
(el) => !el.hasAttribute('disabled'),
|
|
191
|
+
) as HTMLElement[];
|
|
192
|
+
|
|
193
|
+
// Get first and last focusable elements
|
|
194
|
+
this._firstFocusableElement = this._focusableElements[0] || null;
|
|
195
|
+
this._lastFocusableElement =
|
|
196
|
+
this._focusableElements[this._focusableElements.length - 1] || null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Handle tab key press to trap focus
|
|
201
|
+
*
|
|
202
|
+
* @param event - Keyboard event
|
|
203
|
+
*/
|
|
204
|
+
public handleTab(event: KeyboardEvent): void {
|
|
205
|
+
// If no focusable elements, do nothing
|
|
206
|
+
if (!this._firstFocusableElement || !this._lastFocusableElement) {
|
|
207
|
+
event.preventDefault();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const isTabPressed = event.key === 'Tab' || event.keyCode === 9;
|
|
212
|
+
|
|
213
|
+
if (!isTabPressed) return;
|
|
214
|
+
|
|
215
|
+
// Handle Shift+Tab to focus last element when on first
|
|
216
|
+
if (event.shiftKey) {
|
|
217
|
+
if (document.activeElement === this._firstFocusableElement) {
|
|
218
|
+
this._lastFocusableElement.focus();
|
|
219
|
+
event.preventDefault();
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
// Handle Tab to focus first element when on last
|
|
223
|
+
if (document.activeElement === this._lastFocusableElement) {
|
|
224
|
+
this._firstFocusableElement.focus();
|
|
225
|
+
event.preventDefault();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Focus the first interactive element
|
|
232
|
+
*/
|
|
233
|
+
public focusFirstElement(): void {
|
|
234
|
+
if (this._firstFocusableElement) {
|
|
235
|
+
this._firstFocusableElement.focus();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* KTDatepickerDropdown
|
|
242
|
+
*
|
|
243
|
+
* A specialized dropdown implementation for the KTDatepicker component.
|
|
244
|
+
* This module handles the dropdown functionality for the datepicker component,
|
|
245
|
+
* including positioning, showing/hiding, and keyboard navigation.
|
|
246
|
+
*/
|
|
247
|
+
export class KTDatepickerDropdown extends KTComponent {
|
|
248
|
+
protected override readonly _name: string = 'datepicker-dropdown';
|
|
249
|
+
protected override readonly _config: KTDatepickerConfigInterface;
|
|
250
|
+
|
|
251
|
+
// DOM Elements
|
|
252
|
+
protected _element: HTMLElement;
|
|
253
|
+
private _toggleElement: HTMLElement;
|
|
254
|
+
private _dropdownElement: HTMLElement;
|
|
255
|
+
|
|
256
|
+
// State
|
|
257
|
+
private _isOpen: boolean = false;
|
|
258
|
+
private _isTransitioning: boolean = false;
|
|
259
|
+
private _popperInstance: PopperInstance | null = null;
|
|
260
|
+
private _eventManager: EventManager;
|
|
261
|
+
private _focusManager: FocusManager;
|
|
262
|
+
private _focusTrap: FocusTrap | null = null;
|
|
263
|
+
private _activeElement: Element | null = null;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Constructor
|
|
267
|
+
* @param element The parent element (datepicker wrapper)
|
|
268
|
+
* @param toggleElement The element that triggers the dropdown
|
|
269
|
+
* @param dropdownElement The dropdown content element
|
|
270
|
+
* @param config The configuration options
|
|
271
|
+
*/
|
|
272
|
+
constructor(
|
|
273
|
+
element: HTMLElement,
|
|
274
|
+
toggleElement: HTMLElement,
|
|
275
|
+
dropdownElement: HTMLElement,
|
|
276
|
+
config: KTDatepickerConfigInterface,
|
|
277
|
+
) {
|
|
278
|
+
super();
|
|
279
|
+
|
|
280
|
+
this._element = element;
|
|
281
|
+
this._toggleElement = toggleElement;
|
|
282
|
+
this._dropdownElement = dropdownElement;
|
|
283
|
+
this._config = config;
|
|
284
|
+
this._eventManager = new EventManager();
|
|
285
|
+
this._focusManager = new FocusManager(dropdownElement);
|
|
286
|
+
|
|
287
|
+
this._setupEventListeners();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Set up event listeners for the dropdown
|
|
292
|
+
*/
|
|
293
|
+
private _setupEventListeners(): void {
|
|
294
|
+
// Toggle click
|
|
295
|
+
this._eventManager.addListener(
|
|
296
|
+
this._toggleElement,
|
|
297
|
+
'click',
|
|
298
|
+
this._handleToggleClick.bind(this),
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
// Keyboard navigation
|
|
302
|
+
this._eventManager.addListener(
|
|
303
|
+
this._element,
|
|
304
|
+
'keydown',
|
|
305
|
+
this._handleKeyDown.bind(this),
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
// Close on outside click
|
|
309
|
+
this._eventManager.addListener(
|
|
310
|
+
document as unknown as HTMLElement,
|
|
311
|
+
'click',
|
|
312
|
+
this._handleOutsideClick.bind(this),
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Handle toggle element click
|
|
318
|
+
*/
|
|
319
|
+
private _handleToggleClick(event: Event): void {
|
|
320
|
+
event.preventDefault();
|
|
321
|
+
event.stopPropagation();
|
|
322
|
+
|
|
323
|
+
this.toggle();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Handle keyboard events
|
|
328
|
+
*/
|
|
329
|
+
private _handleKeyDown(event: KeyboardEvent): void {
|
|
330
|
+
if (!this._isOpen) return;
|
|
331
|
+
|
|
332
|
+
switch (event.key) {
|
|
333
|
+
case 'Escape':
|
|
334
|
+
event.preventDefault();
|
|
335
|
+
this.close();
|
|
336
|
+
this._toggleElement.focus();
|
|
337
|
+
break;
|
|
338
|
+
case 'ArrowDown':
|
|
339
|
+
event.preventDefault();
|
|
340
|
+
this._focusManager.focusNext();
|
|
341
|
+
break;
|
|
342
|
+
case 'ArrowUp':
|
|
343
|
+
event.preventDefault();
|
|
344
|
+
this._focusManager.focusPrevious();
|
|
345
|
+
break;
|
|
346
|
+
case 'Home':
|
|
347
|
+
event.preventDefault();
|
|
348
|
+
// Focus first visible option
|
|
349
|
+
const firstOption = this._focusManager.getVisibleOptions()[0];
|
|
350
|
+
if (firstOption) {
|
|
351
|
+
this._focusManager.applyFocus(firstOption);
|
|
352
|
+
this._focusManager.scrollIntoView(firstOption);
|
|
353
|
+
}
|
|
354
|
+
break;
|
|
355
|
+
case 'End':
|
|
356
|
+
event.preventDefault();
|
|
357
|
+
// Focus last visible option
|
|
358
|
+
const visibleOptions = this._focusManager.getVisibleOptions();
|
|
359
|
+
const lastOption = visibleOptions[visibleOptions.length - 1];
|
|
360
|
+
if (lastOption) {
|
|
361
|
+
this._focusManager.applyFocus(lastOption);
|
|
362
|
+
this._focusManager.scrollIntoView(lastOption);
|
|
363
|
+
}
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Handle clicks outside the dropdown
|
|
370
|
+
*/
|
|
371
|
+
private _handleOutsideClick(event: MouseEvent): void {
|
|
372
|
+
if (!this._isOpen) return;
|
|
373
|
+
|
|
374
|
+
const target = event.target as HTMLElement;
|
|
375
|
+
|
|
376
|
+
if (
|
|
377
|
+
!this._element.contains(target) &&
|
|
378
|
+
!this._dropdownElement.contains(target)
|
|
379
|
+
) {
|
|
380
|
+
// Before closing, check if a range selection is in progress
|
|
381
|
+
const datepickerElement = this._element.closest('[data-kt-datepicker]');
|
|
382
|
+
if (datepickerElement) {
|
|
383
|
+
// Get the state manager through the calendar instance or directly
|
|
384
|
+
const stateManager = (datepickerElement as any).instance?._state;
|
|
385
|
+
|
|
386
|
+
if (stateManager) {
|
|
387
|
+
const state = stateManager.getState();
|
|
388
|
+
const config = stateManager.getConfig();
|
|
389
|
+
|
|
390
|
+
// If we're in range mode and range selection is in progress, don't close
|
|
391
|
+
if (config.range && state.isRangeSelectionInProgress) {
|
|
392
|
+
console.log(
|
|
393
|
+
'Outside click detected but range selection in progress - keeping dropdown open',
|
|
394
|
+
);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
this.close();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Set width of dropdown based on toggle element
|
|
406
|
+
*/
|
|
407
|
+
private _setDropdownWidth(): void {
|
|
408
|
+
if (!this._dropdownElement || !this._toggleElement) return;
|
|
409
|
+
|
|
410
|
+
// Get the datepicker configuration
|
|
411
|
+
const datepickerElement = this._element.closest('[data-kt-datepicker]');
|
|
412
|
+
let visibleMonths = 1;
|
|
413
|
+
|
|
414
|
+
if (datepickerElement) {
|
|
415
|
+
// Get visible months from config
|
|
416
|
+
const instance = (datepickerElement as any).instance;
|
|
417
|
+
if (instance && instance._config) {
|
|
418
|
+
visibleMonths = instance._config.visibleMonths || 1;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Calculate appropriate width based on number of visible months
|
|
423
|
+
if (visibleMonths > 1) {
|
|
424
|
+
// For multiple months, calculate a fixed width per month plus padding and gaps
|
|
425
|
+
const monthWidth = 280; // Fixed width for each month
|
|
426
|
+
const padding = 24; // Left/right padding (p-3 = 0.75rem × 2 × 16px = 24px)
|
|
427
|
+
const spacing = 16 * (visibleMonths - 1); // Gap between months (gap-4 = 1rem × 16px)
|
|
428
|
+
|
|
429
|
+
// Limit to showing max 3 months at once for UX (user can scroll to see more)
|
|
430
|
+
const visibleWidth = Math.min(visibleMonths, 3);
|
|
431
|
+
|
|
432
|
+
const totalWidth = monthWidth * visibleWidth + spacing + padding;
|
|
433
|
+
|
|
434
|
+
// Set fixed width for the dropdown
|
|
435
|
+
this._dropdownElement.style.width = `${totalWidth}px`;
|
|
436
|
+
this._dropdownElement.style.minWidth = `${totalWidth}px`;
|
|
437
|
+
} else {
|
|
438
|
+
// For single month, use a fixed width that works well for most calendars
|
|
439
|
+
this._dropdownElement.style.width = '332px'; // 280px calendar width + 24px padding + border
|
|
440
|
+
this._dropdownElement.style.minWidth = '332px';
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Initialize the Popper instance for dropdown positioning
|
|
446
|
+
*/
|
|
447
|
+
private _initPopper(): void {
|
|
448
|
+
// Destroy existing popper instance if it exists
|
|
449
|
+
this._destroyPopper();
|
|
450
|
+
|
|
451
|
+
// Default offset
|
|
452
|
+
const offsetValue = '0, 5';
|
|
453
|
+
|
|
454
|
+
// Get configuration options
|
|
455
|
+
const placement = 'bottom-start';
|
|
456
|
+
const strategy = 'absolute';
|
|
457
|
+
const preventOverflow = true;
|
|
458
|
+
const flip = true;
|
|
459
|
+
|
|
460
|
+
// Create new popper instance
|
|
461
|
+
this._popperInstance = createPopper(
|
|
462
|
+
this._toggleElement,
|
|
463
|
+
this._dropdownElement,
|
|
464
|
+
{
|
|
465
|
+
placement: placement as Placement,
|
|
466
|
+
strategy: strategy as 'fixed' | 'absolute',
|
|
467
|
+
modifiers: [
|
|
468
|
+
{
|
|
469
|
+
name: 'offset',
|
|
470
|
+
options: {
|
|
471
|
+
offset: this._parseOffset(offsetValue),
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
name: 'preventOverflow',
|
|
476
|
+
options: {
|
|
477
|
+
boundary: 'viewport',
|
|
478
|
+
altAxis: preventOverflow,
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
name: 'flip',
|
|
483
|
+
options: {
|
|
484
|
+
enabled: flip,
|
|
485
|
+
fallbackPlacements: ['top-start', 'bottom-end', 'top-end'],
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
},
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Parse offset string into an array of numbers
|
|
495
|
+
*/
|
|
496
|
+
private _parseOffset(offset: string): number[] {
|
|
497
|
+
return offset.split(',').map((value) => parseInt(value.trim(), 10));
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Destroy the Popper instance
|
|
502
|
+
*/
|
|
503
|
+
private _destroyPopper(): void {
|
|
504
|
+
if (this._popperInstance) {
|
|
505
|
+
this._popperInstance.destroy();
|
|
506
|
+
this._popperInstance = null;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Update dropdown position
|
|
512
|
+
*/
|
|
513
|
+
public updatePosition(): void {
|
|
514
|
+
// Look for the display element rather than using the input directly
|
|
515
|
+
const displayElement = this._element.querySelector(
|
|
516
|
+
'[data-kt-datepicker-display]',
|
|
517
|
+
) as HTMLElement;
|
|
518
|
+
const triggerElement = displayElement || this._toggleElement;
|
|
519
|
+
|
|
520
|
+
if (!triggerElement || !this._dropdownElement) return;
|
|
521
|
+
|
|
522
|
+
// Reset position styles
|
|
523
|
+
this._dropdownElement.style.top = '';
|
|
524
|
+
this._dropdownElement.style.bottom = '';
|
|
525
|
+
this._dropdownElement.style.left = '';
|
|
526
|
+
this._dropdownElement.style.right = '';
|
|
527
|
+
|
|
528
|
+
// Set width before positioning
|
|
529
|
+
this._setDropdownWidth();
|
|
530
|
+
|
|
531
|
+
// Get position information
|
|
532
|
+
const triggerRect = triggerElement.getBoundingClientRect();
|
|
533
|
+
const containerRect = this._element.getBoundingClientRect();
|
|
534
|
+
const dropdownRect = this._dropdownElement.getBoundingClientRect();
|
|
535
|
+
const viewportHeight = window.innerHeight;
|
|
536
|
+
const viewportWidth = window.innerWidth;
|
|
537
|
+
|
|
538
|
+
// Calculate available space below and above the trigger
|
|
539
|
+
const spaceBelow = viewportHeight - triggerRect.bottom;
|
|
540
|
+
const spaceAbove = triggerRect.top;
|
|
541
|
+
|
|
542
|
+
// Calculate if dropdown would overflow horizontally
|
|
543
|
+
const overflowRight = triggerRect.left + dropdownRect.width > viewportWidth;
|
|
544
|
+
|
|
545
|
+
// Position dropdown
|
|
546
|
+
this._dropdownElement.style.position = 'absolute';
|
|
547
|
+
|
|
548
|
+
// Determine vertical position
|
|
549
|
+
if (spaceBelow >= dropdownRect.height || spaceBelow >= spaceAbove) {
|
|
550
|
+
// Position below the trigger
|
|
551
|
+
this._dropdownElement.style.top = `${triggerRect.height + 5}px`;
|
|
552
|
+
} else {
|
|
553
|
+
// Position above the trigger
|
|
554
|
+
this._dropdownElement.style.bottom = `${triggerRect.height + 5}px`;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Determine horizontal position - handle potential overflow
|
|
558
|
+
if (overflowRight) {
|
|
559
|
+
// Align with right edge of trigger to prevent overflow
|
|
560
|
+
const rightOffset = Math.max(0, dropdownRect.width - triggerRect.width);
|
|
561
|
+
this._dropdownElement.style.right = `0px`;
|
|
562
|
+
} else {
|
|
563
|
+
// Align with left edge of trigger
|
|
564
|
+
this._dropdownElement.style.left = `0px`;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Toggle the dropdown
|
|
570
|
+
*/
|
|
571
|
+
public toggle(): void {
|
|
572
|
+
if (this._isOpen) {
|
|
573
|
+
this.close();
|
|
574
|
+
} else {
|
|
575
|
+
this.open();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Open the dropdown
|
|
581
|
+
*/
|
|
582
|
+
public open(): void {
|
|
583
|
+
if (this._isOpen || this._isTransitioning) return;
|
|
584
|
+
|
|
585
|
+
// Fire before show event
|
|
586
|
+
const beforeShowEvent = new CustomEvent('kt.datepicker.dropdown.show', {
|
|
587
|
+
bubbles: true,
|
|
588
|
+
cancelable: true,
|
|
589
|
+
});
|
|
590
|
+
this._element.dispatchEvent(beforeShowEvent);
|
|
591
|
+
|
|
592
|
+
if (beforeShowEvent.defaultPrevented) return;
|
|
593
|
+
|
|
594
|
+
// Begin opening transition
|
|
595
|
+
this._isTransitioning = true;
|
|
596
|
+
|
|
597
|
+
// Set dropdown visibility
|
|
598
|
+
this._dropdownElement.classList.remove('hidden');
|
|
599
|
+
this._dropdownElement.setAttribute('aria-hidden', 'false');
|
|
600
|
+
|
|
601
|
+
// Set dropdown width
|
|
602
|
+
this._setDropdownWidth();
|
|
603
|
+
|
|
604
|
+
// Make sure the element is visible for transitioning
|
|
605
|
+
KTDom.reflow(this._dropdownElement);
|
|
606
|
+
|
|
607
|
+
// Apply z-index
|
|
608
|
+
this._dropdownElement.style.zIndex = '1000';
|
|
609
|
+
|
|
610
|
+
// Initialize popper for positioning
|
|
611
|
+
this._initPopper();
|
|
612
|
+
|
|
613
|
+
// Add active classes
|
|
614
|
+
this._toggleElement.classList.add('ring', 'ring-blue-300');
|
|
615
|
+
this._toggleElement.setAttribute('aria-expanded', 'true');
|
|
616
|
+
|
|
617
|
+
// Start transition
|
|
618
|
+
this._dropdownElement.classList.remove('opacity-0', 'translate-y-2');
|
|
619
|
+
this._dropdownElement.classList.add('opacity-100', 'translate-y-0');
|
|
620
|
+
|
|
621
|
+
// Handle transition end
|
|
622
|
+
KTDom.transitionEnd(this._dropdownElement, () => {
|
|
623
|
+
this._isTransitioning = false;
|
|
624
|
+
this._isOpen = true;
|
|
625
|
+
|
|
626
|
+
// Focus the first interactive element
|
|
627
|
+
this._focusFirstInteractiveElement();
|
|
628
|
+
|
|
629
|
+
// Fire after show event
|
|
630
|
+
const afterShowEvent = new CustomEvent('kt.datepicker.dropdown.shown', {
|
|
631
|
+
bubbles: true,
|
|
632
|
+
});
|
|
633
|
+
this._element.dispatchEvent(afterShowEvent);
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Focus the first interactive element in the dropdown
|
|
639
|
+
*/
|
|
640
|
+
private _focusFirstInteractiveElement(): void {
|
|
641
|
+
// Priority of elements to focus:
|
|
642
|
+
// 1. A "Today" button if available
|
|
643
|
+
// 2. The first day in the current month
|
|
644
|
+
// 3. Any other focusable element
|
|
645
|
+
|
|
646
|
+
// Find the Today button using standard DOM selectors
|
|
647
|
+
let todayBtn: HTMLElement | null = null;
|
|
648
|
+
const buttons = this._dropdownElement.querySelectorAll('button');
|
|
649
|
+
for (let i = 0; i < buttons.length; i++) {
|
|
650
|
+
if (buttons[i].textContent && buttons[i].textContent.trim() === 'Today') {
|
|
651
|
+
todayBtn = buttons[i] as HTMLElement;
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (todayBtn) {
|
|
657
|
+
todayBtn.focus();
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
const currentMonthDay = this._dropdownElement.querySelector(
|
|
662
|
+
'button[data-date]:not(.text-gray-400)',
|
|
663
|
+
) as HTMLElement;
|
|
664
|
+
if (currentMonthDay) {
|
|
665
|
+
currentMonthDay.focus();
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const firstOption = this._focusManager.getVisibleOptions()[0];
|
|
670
|
+
if (firstOption) {
|
|
671
|
+
this._focusManager.applyFocus(firstOption);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Close the dropdown
|
|
677
|
+
*/
|
|
678
|
+
public close(): void {
|
|
679
|
+
if (!this._isOpen || this._isTransitioning) return;
|
|
680
|
+
|
|
681
|
+
// Fire before hide event
|
|
682
|
+
const beforeHideEvent = new CustomEvent('kt.datepicker.dropdown.hide', {
|
|
683
|
+
bubbles: true,
|
|
684
|
+
cancelable: true,
|
|
685
|
+
});
|
|
686
|
+
this._element.dispatchEvent(beforeHideEvent);
|
|
687
|
+
|
|
688
|
+
if (beforeHideEvent.defaultPrevented) return;
|
|
689
|
+
|
|
690
|
+
// Begin closing transition
|
|
691
|
+
this._isTransitioning = true;
|
|
692
|
+
|
|
693
|
+
// Start transition
|
|
694
|
+
this._dropdownElement.classList.add('opacity-0', 'translate-y-2');
|
|
695
|
+
this._dropdownElement.classList.remove('opacity-100', 'translate-y-0');
|
|
696
|
+
|
|
697
|
+
// Handle transition end
|
|
698
|
+
KTDom.transitionEnd(this._dropdownElement, () => {
|
|
699
|
+
// Remove active classes
|
|
700
|
+
this._dropdownElement.classList.add('hidden');
|
|
701
|
+
this._dropdownElement.setAttribute('aria-hidden', 'true');
|
|
702
|
+
|
|
703
|
+
// Reset styles
|
|
704
|
+
this._dropdownElement.style.opacity = '';
|
|
705
|
+
this._dropdownElement.style.transform = '';
|
|
706
|
+
this._dropdownElement.style.zIndex = '';
|
|
707
|
+
|
|
708
|
+
// Destroy popper
|
|
709
|
+
this._destroyPopper();
|
|
710
|
+
|
|
711
|
+
// Update state
|
|
712
|
+
this._isTransitioning = false;
|
|
713
|
+
this._isOpen = false;
|
|
714
|
+
|
|
715
|
+
// Fire after hide event
|
|
716
|
+
const afterHideEvent = new CustomEvent('kt.datepicker.dropdown.hidden', {
|
|
717
|
+
bubbles: true,
|
|
718
|
+
});
|
|
719
|
+
this._element.dispatchEvent(afterHideEvent);
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* Check if dropdown is open
|
|
725
|
+
*/
|
|
726
|
+
public isOpen(): boolean {
|
|
727
|
+
return this._isOpen;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Clean up component
|
|
732
|
+
*/
|
|
733
|
+
public override dispose(): void {
|
|
734
|
+
// Destroy popper
|
|
735
|
+
this._destroyPopper();
|
|
736
|
+
|
|
737
|
+
// Remove event listeners
|
|
738
|
+
this._eventManager.removeAllListeners(this._element);
|
|
739
|
+
this._eventManager.removeAllListeners(this._toggleElement);
|
|
740
|
+
this._eventManager.removeAllListeners(document as unknown as HTMLElement);
|
|
741
|
+
|
|
742
|
+
// Clean up focus manager
|
|
743
|
+
if (
|
|
744
|
+
this._focusManager &&
|
|
745
|
+
typeof this._focusManager.dispose === 'function'
|
|
746
|
+
) {
|
|
747
|
+
this._focusManager.dispose();
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Clean up state
|
|
751
|
+
this._isOpen = false;
|
|
752
|
+
this._isTransitioning = false;
|
|
753
|
+
|
|
754
|
+
// Remove data reference
|
|
755
|
+
KTData.remove(this._element, this._name);
|
|
756
|
+
}
|
|
757
|
+
}
|