@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,1287 @@
|
|
|
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 KTComponent from '../component';
|
|
7
|
+
import { KTDatepickerCalendar } from './calendar';
|
|
8
|
+
import { KTDatepickerStateManager } from './config';
|
|
9
|
+
import { KTDatepickerKeyboard } from './keyboard';
|
|
10
|
+
import { DateRangeInterface, KTDatepickerConfigInterface } from './types';
|
|
11
|
+
import { formatDate, parseDate, isValidDate, isDateDisabled } from './utils';
|
|
12
|
+
import {
|
|
13
|
+
datepickerContainerTemplate,
|
|
14
|
+
inputWrapperTemplate,
|
|
15
|
+
segmentedDateInputTemplate,
|
|
16
|
+
segmentedDateRangeInputTemplate,
|
|
17
|
+
placeholderTemplate,
|
|
18
|
+
} from './templates';
|
|
19
|
+
import { KTDatepickerEventManager, KTDatepickerEventName } from './events';
|
|
20
|
+
|
|
21
|
+
// Helper function to replace stringToElement
|
|
22
|
+
function createElement(html: string): HTMLElement {
|
|
23
|
+
const template = document.createElement('template');
|
|
24
|
+
template.innerHTML = html.trim();
|
|
25
|
+
return template.content.firstChild as HTMLElement;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* KTDatepicker - Main datepicker component class
|
|
30
|
+
* Manages the datepicker functionality and integration with input elements
|
|
31
|
+
*/
|
|
32
|
+
export class KTDatepicker extends KTComponent {
|
|
33
|
+
protected override readonly _name: string = 'datepicker';
|
|
34
|
+
protected override readonly _config: KTDatepickerConfigInterface;
|
|
35
|
+
|
|
36
|
+
private _state: KTDatepickerStateManager;
|
|
37
|
+
private _calendar: KTDatepickerCalendar;
|
|
38
|
+
private _keyboard: KTDatepickerKeyboard;
|
|
39
|
+
private _eventManager: KTDatepickerEventManager;
|
|
40
|
+
|
|
41
|
+
private _dateInputElement: HTMLInputElement | null = null;
|
|
42
|
+
private _startDateInputElement: HTMLInputElement | null = null;
|
|
43
|
+
private _endDateInputElement: HTMLInputElement | null = null;
|
|
44
|
+
private _displayElement: HTMLElement | null = null;
|
|
45
|
+
private _useSegmentedDisplay = false;
|
|
46
|
+
private _displayWrapper: HTMLElement | null = null;
|
|
47
|
+
private _displayText: HTMLElement | null = null;
|
|
48
|
+
|
|
49
|
+
private _currentDate: Date | null = null;
|
|
50
|
+
private _currentRange: DateRangeInterface | null = null;
|
|
51
|
+
private _segmentFocused:
|
|
52
|
+
| 'day'
|
|
53
|
+
| 'month'
|
|
54
|
+
| 'year'
|
|
55
|
+
| 'start-day'
|
|
56
|
+
| 'start-month'
|
|
57
|
+
| 'start-year'
|
|
58
|
+
| 'end-day'
|
|
59
|
+
| 'end-month'
|
|
60
|
+
| 'end-year'
|
|
61
|
+
| null = null;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Constructor for the KTDatepicker class.
|
|
65
|
+
*/
|
|
66
|
+
constructor(element: HTMLElement, config?: KTDatepickerConfigInterface) {
|
|
67
|
+
super();
|
|
68
|
+
|
|
69
|
+
// Check if the element already has a datepicker instance attached to it
|
|
70
|
+
if (element.getAttribute('data-kt-datepicker-initialized') === 'true') {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Initialize the datepicker with the provided element
|
|
75
|
+
this._init(element);
|
|
76
|
+
|
|
77
|
+
// Build the configuration object by merging the default config with the provided config
|
|
78
|
+
this._buildConfig(config);
|
|
79
|
+
|
|
80
|
+
// Store the instance of the datepicker directly on the element
|
|
81
|
+
(element as any).instance = this;
|
|
82
|
+
|
|
83
|
+
// Ensure the element is focusable
|
|
84
|
+
this._element.setAttribute('tabindex', '0');
|
|
85
|
+
this._element.classList.add(
|
|
86
|
+
'kt-datepicker',
|
|
87
|
+
'relative',
|
|
88
|
+
'focus:outline-none',
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Mark as initialized
|
|
92
|
+
this._element.setAttribute('data-kt-datepicker-initialized', 'true');
|
|
93
|
+
|
|
94
|
+
// Find input elements
|
|
95
|
+
this._initializeInputElements();
|
|
96
|
+
|
|
97
|
+
// Create display element if needed
|
|
98
|
+
this._createDisplayElement();
|
|
99
|
+
|
|
100
|
+
// Create state manager first
|
|
101
|
+
this._state = new KTDatepickerStateManager(this._element, this._config);
|
|
102
|
+
this._config = this._state.getConfig();
|
|
103
|
+
|
|
104
|
+
// Initialize the calendar and keyboard after creating the state manager
|
|
105
|
+
this._calendar = new KTDatepickerCalendar(this._element, this._state);
|
|
106
|
+
this._keyboard = new KTDatepickerKeyboard(this._element, this._state);
|
|
107
|
+
|
|
108
|
+
// Initialize event manager
|
|
109
|
+
this._eventManager = this._state.getEventManager();
|
|
110
|
+
|
|
111
|
+
// Set up event listeners
|
|
112
|
+
this._setupEventListeners();
|
|
113
|
+
|
|
114
|
+
// Initialize with any default values
|
|
115
|
+
this._initializeDefaultValues();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Initialize input elements
|
|
120
|
+
*/
|
|
121
|
+
private _initializeInputElements(): void {
|
|
122
|
+
// Get main input element - will be hidden
|
|
123
|
+
this._dateInputElement = this._element.querySelector(
|
|
124
|
+
'[data-kt-datepicker-input]',
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Hide the input element and make it only for data storage
|
|
128
|
+
if (this._dateInputElement) {
|
|
129
|
+
this._dateInputElement.classList.add('hidden', 'sr-only');
|
|
130
|
+
this._dateInputElement.setAttribute('aria-hidden', 'true');
|
|
131
|
+
this._dateInputElement.tabIndex = -1;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Get range input elements if applicable
|
|
135
|
+
this._startDateInputElement = this._element.querySelector(
|
|
136
|
+
'[data-kt-datepicker-start]',
|
|
137
|
+
);
|
|
138
|
+
this._endDateInputElement = this._element.querySelector(
|
|
139
|
+
'[data-kt-datepicker-end]',
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// Get display element if exists
|
|
143
|
+
this._displayElement = this._element.querySelector(
|
|
144
|
+
'[data-kt-datepicker-display]',
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
// Check if we should use segmented display
|
|
148
|
+
this._useSegmentedDisplay =
|
|
149
|
+
this._element.hasAttribute('data-kt-datepicker-segmented') ||
|
|
150
|
+
this._element.hasAttribute('data-kt-datepicker-segmented-input');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Create display element for datepicker
|
|
155
|
+
*/
|
|
156
|
+
private _createDisplayElement(): void {
|
|
157
|
+
// Skip if already created
|
|
158
|
+
if (this._displayElement) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Get format from config or use default
|
|
163
|
+
const format = this._config.format || 'mm/dd/yyyy';
|
|
164
|
+
const placeholder =
|
|
165
|
+
this._dateInputElement?.getAttribute('placeholder') || format;
|
|
166
|
+
|
|
167
|
+
// Create wrapper for display element
|
|
168
|
+
this._displayWrapper = document.createElement('div');
|
|
169
|
+
this._displayWrapper.className =
|
|
170
|
+
'kt-datepicker-display-wrapper kt-datepicker-display-segment';
|
|
171
|
+
this._displayWrapper.setAttribute('role', 'combobox');
|
|
172
|
+
this._displayWrapper.setAttribute('aria-haspopup', 'dialog');
|
|
173
|
+
this._displayWrapper.setAttribute('aria-expanded', 'false');
|
|
174
|
+
this._element.appendChild(this._displayWrapper);
|
|
175
|
+
|
|
176
|
+
if (this._useSegmentedDisplay) {
|
|
177
|
+
// Create segmented display for better date part selection
|
|
178
|
+
const displayContainer = document.createElement('div');
|
|
179
|
+
displayContainer.className = 'kt-datepicker-display-element';
|
|
180
|
+
displayContainer.setAttribute('tabindex', '0');
|
|
181
|
+
displayContainer.setAttribute('role', 'textbox');
|
|
182
|
+
displayContainer.setAttribute('aria-label', placeholder);
|
|
183
|
+
displayContainer.setAttribute('data-kt-datepicker-display', '');
|
|
184
|
+
|
|
185
|
+
// Add segmented template based on range mode
|
|
186
|
+
if (this._config.range) {
|
|
187
|
+
displayContainer.innerHTML = segmentedDateRangeInputTemplate(
|
|
188
|
+
this._config.format || 'mm/dd/yyyy',
|
|
189
|
+
);
|
|
190
|
+
} else {
|
|
191
|
+
displayContainer.innerHTML = segmentedDateInputTemplate(
|
|
192
|
+
this._config.format || 'mm/dd/yyyy',
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
this._displayElement = displayContainer;
|
|
197
|
+
this._displayWrapper.appendChild(this._displayElement);
|
|
198
|
+
|
|
199
|
+
// Add click handlers for segments
|
|
200
|
+
const segments = this._displayElement.querySelectorAll('[data-segment]');
|
|
201
|
+
segments.forEach((segment) => {
|
|
202
|
+
segment.addEventListener('click', (e) => {
|
|
203
|
+
e.stopPropagation();
|
|
204
|
+
const segmentType = segment.getAttribute('data-segment');
|
|
205
|
+
this._handleSegmentClick(segmentType);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
} else {
|
|
209
|
+
// Create simple display element
|
|
210
|
+
this._displayElement = document.createElement('div');
|
|
211
|
+
this._displayElement.className = 'kt-datepicker-display-element';
|
|
212
|
+
this._displayElement.setAttribute('tabindex', '0');
|
|
213
|
+
this._displayElement.setAttribute('role', 'textbox');
|
|
214
|
+
this._displayElement.setAttribute('aria-label', placeholder);
|
|
215
|
+
this._displayElement.setAttribute('data-placeholder', placeholder);
|
|
216
|
+
this._displayElement.setAttribute('data-kt-datepicker-display', '');
|
|
217
|
+
|
|
218
|
+
// Create display text element
|
|
219
|
+
this._displayText = document.createElement('span');
|
|
220
|
+
this._displayText.className = 'kt-datepicker-display-text';
|
|
221
|
+
this._displayText.textContent = placeholder;
|
|
222
|
+
this._displayText.classList.add('text-gray-400');
|
|
223
|
+
|
|
224
|
+
this._displayElement.appendChild(this._displayText);
|
|
225
|
+
this._displayWrapper.appendChild(this._displayElement);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Add click event to display element
|
|
229
|
+
this._displayElement.addEventListener('click', (e) => {
|
|
230
|
+
e.preventDefault();
|
|
231
|
+
if (!this._state.getState().isOpen) {
|
|
232
|
+
this._state.setOpen(true);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Enhanced keyboard event handling for display element
|
|
237
|
+
this._displayElement.addEventListener('keydown', (e) => {
|
|
238
|
+
if (e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown') {
|
|
239
|
+
e.preventDefault();
|
|
240
|
+
e.stopPropagation();
|
|
241
|
+
|
|
242
|
+
// If not already open, open the dropdown
|
|
243
|
+
if (!this._state.getState().isOpen) {
|
|
244
|
+
this._state.setOpen(true);
|
|
245
|
+
|
|
246
|
+
// Dispatch a custom event to notify about the keyboard open
|
|
247
|
+
this._eventManager.dispatchKeyboardOpenEvent();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Handle segment click to focus and open appropriate view
|
|
255
|
+
*
|
|
256
|
+
* @param segmentType - Type of segment clicked
|
|
257
|
+
*/
|
|
258
|
+
private _handleSegmentClick(segmentType: string | null): void {
|
|
259
|
+
if (!segmentType) return;
|
|
260
|
+
|
|
261
|
+
// Store the focused segment
|
|
262
|
+
this._segmentFocused = segmentType as any;
|
|
263
|
+
|
|
264
|
+
// Remove highlight from all segments
|
|
265
|
+
this._removeSegmentHighlights();
|
|
266
|
+
|
|
267
|
+
// Add highlight to clicked segment
|
|
268
|
+
if (this._displayElement) {
|
|
269
|
+
const segment = this._displayElement.querySelector(
|
|
270
|
+
`[data-segment="${segmentType}"]`,
|
|
271
|
+
);
|
|
272
|
+
if (segment) {
|
|
273
|
+
segment.classList.add('kt-datepicker-segment-focused');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Set the appropriate view mode based on segment type
|
|
278
|
+
if (segmentType.includes('day')) {
|
|
279
|
+
// Day segment - open in days view (default)
|
|
280
|
+
this._state.setViewMode('days');
|
|
281
|
+
this._state.setOpen(true);
|
|
282
|
+
} else if (segmentType.includes('month')) {
|
|
283
|
+
// Month segment - open in months view
|
|
284
|
+
this._state.setViewMode('months');
|
|
285
|
+
this._state.setOpen(true);
|
|
286
|
+
} else if (segmentType.includes('year')) {
|
|
287
|
+
// Year segment - open in years view
|
|
288
|
+
this._state.setViewMode('years');
|
|
289
|
+
this._state.setOpen(true);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Set up event listeners
|
|
295
|
+
*/
|
|
296
|
+
private _setupEventListeners(): void {
|
|
297
|
+
// Listen for state changes
|
|
298
|
+
this._eventManager.addEventListener(
|
|
299
|
+
KTDatepickerEventName.STATE_CHANGE,
|
|
300
|
+
(e: CustomEvent) => {
|
|
301
|
+
const { state } = e.detail;
|
|
302
|
+
|
|
303
|
+
// Update ARIA attributes based on open state
|
|
304
|
+
if (this._displayWrapper) {
|
|
305
|
+
this._displayWrapper.setAttribute(
|
|
306
|
+
'aria-expanded',
|
|
307
|
+
state.isOpen.toString(),
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Update display when closing
|
|
312
|
+
if (!state.isOpen && state.prevIsOpen) {
|
|
313
|
+
this._syncDisplayWithSelectedDate();
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
// Set up change event listener to update input values
|
|
319
|
+
this._eventManager.addEventListener(
|
|
320
|
+
KTDatepickerEventName.DATE_CHANGE,
|
|
321
|
+
this._handleDateChange.bind(this),
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
// Add keyboard events to the root element
|
|
325
|
+
this._element.addEventListener('keydown', (e) => {
|
|
326
|
+
if (e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown') {
|
|
327
|
+
const state = this._state.getState();
|
|
328
|
+
if (!state.isOpen) {
|
|
329
|
+
e.preventDefault();
|
|
330
|
+
this._state.setOpen(true);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Add keyboard navigation for segments
|
|
336
|
+
if (this._displayElement && this._useSegmentedDisplay) {
|
|
337
|
+
this._displayElement.addEventListener(
|
|
338
|
+
'keydown',
|
|
339
|
+
this._handleSegmentKeydown.bind(this),
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Handle keyboard navigation between segments
|
|
346
|
+
*
|
|
347
|
+
* @param e - Keyboard event
|
|
348
|
+
*/
|
|
349
|
+
private _handleSegmentKeydown(e: KeyboardEvent): void {
|
|
350
|
+
// Only handle if we have a focused segment
|
|
351
|
+
if (!this._segmentFocused) return;
|
|
352
|
+
|
|
353
|
+
const target = e.target as HTMLElement;
|
|
354
|
+
const segmentType = target.getAttribute('data-segment');
|
|
355
|
+
if (!segmentType) return;
|
|
356
|
+
|
|
357
|
+
// Handle keyboard navigation
|
|
358
|
+
switch (e.key) {
|
|
359
|
+
case 'ArrowLeft':
|
|
360
|
+
e.preventDefault();
|
|
361
|
+
this._navigateSegments('prev', segmentType);
|
|
362
|
+
break;
|
|
363
|
+
case 'ArrowRight':
|
|
364
|
+
e.preventDefault();
|
|
365
|
+
this._navigateSegments('next', segmentType);
|
|
366
|
+
break;
|
|
367
|
+
case 'Tab':
|
|
368
|
+
// Let default tab behavior work, but update focus segment when tabbing
|
|
369
|
+
this._segmentFocused = segmentType as any;
|
|
370
|
+
// Remove highlight from all segments
|
|
371
|
+
this._removeSegmentHighlights();
|
|
372
|
+
// Add highlight to current segment
|
|
373
|
+
target.classList.add('segment-focused');
|
|
374
|
+
break;
|
|
375
|
+
case 'Enter':
|
|
376
|
+
case ' ':
|
|
377
|
+
e.preventDefault();
|
|
378
|
+
this._handleSegmentClick(segmentType);
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Navigate between segments with keyboard
|
|
385
|
+
*
|
|
386
|
+
* @param direction - 'prev' or 'next'
|
|
387
|
+
* @param currentSegment - Current segment identifier
|
|
388
|
+
*/
|
|
389
|
+
private _navigateSegments(
|
|
390
|
+
direction: 'prev' | 'next',
|
|
391
|
+
currentSegment: string,
|
|
392
|
+
): void {
|
|
393
|
+
if (!this._displayElement) return;
|
|
394
|
+
|
|
395
|
+
// Define segment order
|
|
396
|
+
let segments: string[];
|
|
397
|
+
if (this._config.range) {
|
|
398
|
+
segments = [
|
|
399
|
+
'start-month',
|
|
400
|
+
'start-day',
|
|
401
|
+
'start-year',
|
|
402
|
+
'end-month',
|
|
403
|
+
'end-day',
|
|
404
|
+
'end-year',
|
|
405
|
+
];
|
|
406
|
+
} else {
|
|
407
|
+
segments = ['month', 'day', 'year'];
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Find current index
|
|
411
|
+
const currentIndex = segments.indexOf(currentSegment);
|
|
412
|
+
if (currentIndex === -1) return;
|
|
413
|
+
|
|
414
|
+
// Calculate new index
|
|
415
|
+
let newIndex;
|
|
416
|
+
if (direction === 'prev') {
|
|
417
|
+
newIndex = currentIndex === 0 ? segments.length - 1 : currentIndex - 1;
|
|
418
|
+
} else {
|
|
419
|
+
newIndex = currentIndex === segments.length - 1 ? 0 : currentIndex + 1;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Find new segment element
|
|
423
|
+
const newSegment = this._displayElement.querySelector(
|
|
424
|
+
`[data-segment="${segments[newIndex]}"]`,
|
|
425
|
+
) as HTMLElement;
|
|
426
|
+
if (!newSegment) return;
|
|
427
|
+
|
|
428
|
+
// Update focus
|
|
429
|
+
newSegment.focus();
|
|
430
|
+
this._segmentFocused = segments[newIndex] as any;
|
|
431
|
+
|
|
432
|
+
// Remove highlight from all segments
|
|
433
|
+
this._removeSegmentHighlights();
|
|
434
|
+
|
|
435
|
+
// Add highlight to new segment
|
|
436
|
+
newSegment.classList.add('segment-focused');
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Remove highlight from all segments
|
|
441
|
+
*/
|
|
442
|
+
private _removeSegmentHighlights(): void {
|
|
443
|
+
if (!this._displayElement) return;
|
|
444
|
+
|
|
445
|
+
const segments = this._displayElement.querySelectorAll('.segment-part');
|
|
446
|
+
segments.forEach((segment) => {
|
|
447
|
+
segment.classList.remove('segment-focused');
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Sync display element with the selected date
|
|
453
|
+
*/
|
|
454
|
+
private _syncDisplayWithSelectedDate(): void {
|
|
455
|
+
if (!this._displayElement) return;
|
|
456
|
+
|
|
457
|
+
const state = this._state.getState();
|
|
458
|
+
const selectedDate = state.selectedDate;
|
|
459
|
+
const selectedDateRange = state.selectedDateRange;
|
|
460
|
+
|
|
461
|
+
if (this._useSegmentedDisplay) {
|
|
462
|
+
// Update segmented display elements
|
|
463
|
+
if (selectedDate) {
|
|
464
|
+
// Single date
|
|
465
|
+
const daySegment = this._displayElement.querySelector(
|
|
466
|
+
'[data-segment="day"]',
|
|
467
|
+
);
|
|
468
|
+
const monthSegment = this._displayElement.querySelector(
|
|
469
|
+
'[data-segment="month"]',
|
|
470
|
+
);
|
|
471
|
+
const yearSegment = this._displayElement.querySelector(
|
|
472
|
+
'[data-segment="year"]',
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
if (daySegment) {
|
|
476
|
+
daySegment.textContent = selectedDate
|
|
477
|
+
.getDate()
|
|
478
|
+
.toString()
|
|
479
|
+
.padStart(2, '0');
|
|
480
|
+
}
|
|
481
|
+
if (monthSegment) {
|
|
482
|
+
monthSegment.textContent = (selectedDate.getMonth() + 1)
|
|
483
|
+
.toString()
|
|
484
|
+
.padStart(2, '0');
|
|
485
|
+
}
|
|
486
|
+
if (yearSegment) {
|
|
487
|
+
yearSegment.textContent = selectedDate.getFullYear().toString();
|
|
488
|
+
}
|
|
489
|
+
} else if (selectedDateRange && selectedDateRange.startDate) {
|
|
490
|
+
// Range selection
|
|
491
|
+
const startDay = this._displayElement.querySelector(
|
|
492
|
+
'[data-segment="start-day"]',
|
|
493
|
+
);
|
|
494
|
+
const startMonth = this._displayElement.querySelector(
|
|
495
|
+
'[data-segment="start-month"]',
|
|
496
|
+
);
|
|
497
|
+
const startYear = this._displayElement.querySelector(
|
|
498
|
+
'[data-segment="start-year"]',
|
|
499
|
+
);
|
|
500
|
+
|
|
501
|
+
if (startDay) {
|
|
502
|
+
startDay.textContent = selectedDateRange.startDate
|
|
503
|
+
.getDate()
|
|
504
|
+
.toString()
|
|
505
|
+
.padStart(2, '0');
|
|
506
|
+
}
|
|
507
|
+
if (startMonth) {
|
|
508
|
+
startMonth.textContent = (selectedDateRange.startDate.getMonth() + 1)
|
|
509
|
+
.toString()
|
|
510
|
+
.padStart(2, '0');
|
|
511
|
+
}
|
|
512
|
+
if (startYear) {
|
|
513
|
+
startYear.textContent = selectedDateRange.startDate
|
|
514
|
+
.getFullYear()
|
|
515
|
+
.toString();
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
if (selectedDateRange.endDate) {
|
|
519
|
+
const endDay = this._displayElement.querySelector(
|
|
520
|
+
'[data-segment="end-day"]',
|
|
521
|
+
);
|
|
522
|
+
const endMonth = this._displayElement.querySelector(
|
|
523
|
+
'[data-segment="end-month"]',
|
|
524
|
+
);
|
|
525
|
+
const endYear = this._displayElement.querySelector(
|
|
526
|
+
'[data-segment="end-year"]',
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
if (endDay) {
|
|
530
|
+
endDay.textContent = selectedDateRange.endDate
|
|
531
|
+
.getDate()
|
|
532
|
+
.toString()
|
|
533
|
+
.padStart(2, '0');
|
|
534
|
+
}
|
|
535
|
+
if (endMonth) {
|
|
536
|
+
endMonth.textContent = (selectedDateRange.endDate.getMonth() + 1)
|
|
537
|
+
.toString()
|
|
538
|
+
.padStart(2, '0');
|
|
539
|
+
}
|
|
540
|
+
if (endYear) {
|
|
541
|
+
endYear.textContent = selectedDateRange.endDate
|
|
542
|
+
.getFullYear()
|
|
543
|
+
.toString();
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
} else if (this._displayText) {
|
|
548
|
+
// Simple display
|
|
549
|
+
if (selectedDate) {
|
|
550
|
+
// Clear placeholder styling
|
|
551
|
+
this._displayText.classList.remove('placeholder');
|
|
552
|
+
|
|
553
|
+
// Format date(s) based on config
|
|
554
|
+
if (
|
|
555
|
+
this._config.range &&
|
|
556
|
+
selectedDateRange &&
|
|
557
|
+
selectedDateRange.startDate &&
|
|
558
|
+
selectedDateRange.endDate
|
|
559
|
+
) {
|
|
560
|
+
this._displayText.textContent = `${formatDate(
|
|
561
|
+
selectedDateRange.startDate,
|
|
562
|
+
this._config.format,
|
|
563
|
+
this._config,
|
|
564
|
+
)} - ${formatDate(
|
|
565
|
+
selectedDateRange.endDate,
|
|
566
|
+
this._config.format,
|
|
567
|
+
this._config,
|
|
568
|
+
)}`;
|
|
569
|
+
} else {
|
|
570
|
+
this._displayText.textContent = formatDate(
|
|
571
|
+
selectedDate,
|
|
572
|
+
this._config.format,
|
|
573
|
+
this._config,
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
} else {
|
|
577
|
+
// No date selected, show format as placeholder
|
|
578
|
+
const placeholder =
|
|
579
|
+
this._displayElement?.getAttribute('data-placeholder') ||
|
|
580
|
+
this._config.format;
|
|
581
|
+
this._displayText.textContent = placeholder;
|
|
582
|
+
this._displayText.classList.add('placeholder');
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Handle date change events
|
|
589
|
+
*
|
|
590
|
+
* @param e - Custom event with date change details
|
|
591
|
+
*/
|
|
592
|
+
private _handleDateChange(e: CustomEvent): void {
|
|
593
|
+
const detail = e.detail?.payload;
|
|
594
|
+
if (!detail) return;
|
|
595
|
+
|
|
596
|
+
// Handle single date selection
|
|
597
|
+
if (detail.selectedDate) {
|
|
598
|
+
const formattedDate = formatDate(
|
|
599
|
+
detail.selectedDate,
|
|
600
|
+
this._config.format,
|
|
601
|
+
this._config,
|
|
602
|
+
);
|
|
603
|
+
|
|
604
|
+
// Update hidden input value
|
|
605
|
+
if (this._dateInputElement) {
|
|
606
|
+
this._dateInputElement.value = formattedDate;
|
|
607
|
+
// Dispatch change event on input to trigger form validation
|
|
608
|
+
this._dateInputElement.dispatchEvent(
|
|
609
|
+
new Event('change', { bubbles: true }),
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Update display element
|
|
614
|
+
this._updateDisplayElement(detail.selectedDate);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Handle date range selection
|
|
618
|
+
if (detail.selectedDateRange && this._config.range) {
|
|
619
|
+
const { startDate, endDate } = detail.selectedDateRange;
|
|
620
|
+
|
|
621
|
+
// Format the range for the hidden input
|
|
622
|
+
if (this._dateInputElement) {
|
|
623
|
+
let displayValue = '';
|
|
624
|
+
|
|
625
|
+
if (startDate) {
|
|
626
|
+
displayValue = formatDate(
|
|
627
|
+
startDate,
|
|
628
|
+
this._config.format,
|
|
629
|
+
this._config,
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
if (endDate) {
|
|
633
|
+
const endFormatted = formatDate(
|
|
634
|
+
endDate,
|
|
635
|
+
this._config.format,
|
|
636
|
+
this._config,
|
|
637
|
+
);
|
|
638
|
+
displayValue += `${this._config.rangeSeparator}${endFormatted}`;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
this._dateInputElement.value = displayValue;
|
|
643
|
+
// Dispatch change event on input
|
|
644
|
+
this._dateInputElement.dispatchEvent(
|
|
645
|
+
new Event('change', { bubbles: true }),
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// Update individual start/end inputs if they exist
|
|
650
|
+
if (this._startDateInputElement && startDate) {
|
|
651
|
+
this._startDateInputElement.value = formatDate(
|
|
652
|
+
startDate,
|
|
653
|
+
this._config.format,
|
|
654
|
+
this._config,
|
|
655
|
+
);
|
|
656
|
+
this._startDateInputElement.dispatchEvent(
|
|
657
|
+
new Event('change', { bubbles: true }),
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (this._endDateInputElement && endDate) {
|
|
662
|
+
this._endDateInputElement.value = formatDate(
|
|
663
|
+
endDate,
|
|
664
|
+
this._config.format,
|
|
665
|
+
this._config,
|
|
666
|
+
);
|
|
667
|
+
this._endDateInputElement.dispatchEvent(
|
|
668
|
+
new Event('change', { bubbles: true }),
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Update display element for range
|
|
673
|
+
this._updateRangeDisplayElement(startDate, endDate);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Update the display element for a single date
|
|
679
|
+
*
|
|
680
|
+
* @param date - The date to display
|
|
681
|
+
*/
|
|
682
|
+
private _updateDisplayElement(date: Date | null): void {
|
|
683
|
+
if (!this._displayElement) return;
|
|
684
|
+
|
|
685
|
+
if (!date) {
|
|
686
|
+
// If no date, show placeholder
|
|
687
|
+
const placeholder =
|
|
688
|
+
this._dateInputElement?.getAttribute('placeholder') || 'Select date';
|
|
689
|
+
this._displayElement.innerHTML = placeholderTemplate(placeholder);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if (this._useSegmentedDisplay) {
|
|
694
|
+
// Update segmented display
|
|
695
|
+
const day = date.getDate();
|
|
696
|
+
const month = date.getMonth() + 1;
|
|
697
|
+
const year = date.getFullYear();
|
|
698
|
+
|
|
699
|
+
const daySegment = this._displayElement.querySelector(
|
|
700
|
+
'[data-segment="day"]',
|
|
701
|
+
);
|
|
702
|
+
const monthSegment = this._displayElement.querySelector(
|
|
703
|
+
'[data-segment="month"]',
|
|
704
|
+
);
|
|
705
|
+
const yearSegment = this._displayElement.querySelector(
|
|
706
|
+
'[data-segment="year"]',
|
|
707
|
+
);
|
|
708
|
+
|
|
709
|
+
if (daySegment) daySegment.textContent = day < 10 ? `0${day}` : `${day}`;
|
|
710
|
+
if (monthSegment)
|
|
711
|
+
monthSegment.textContent = month < 10 ? `0${month}` : `${month}`;
|
|
712
|
+
if (yearSegment) yearSegment.textContent = `${year}`;
|
|
713
|
+
} else {
|
|
714
|
+
// Simple display
|
|
715
|
+
this._displayElement.textContent = formatDate(
|
|
716
|
+
date,
|
|
717
|
+
this._config.format,
|
|
718
|
+
this._config,
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* Update the display element for a date range
|
|
725
|
+
*
|
|
726
|
+
* @param startDate - The start date of the range
|
|
727
|
+
* @param endDate - The end date of the range
|
|
728
|
+
*/
|
|
729
|
+
private _updateRangeDisplayElement(
|
|
730
|
+
startDate: Date | null,
|
|
731
|
+
endDate: Date | null,
|
|
732
|
+
): void {
|
|
733
|
+
if (!this._displayElement) return;
|
|
734
|
+
|
|
735
|
+
if (!startDate) {
|
|
736
|
+
// If no date, show placeholder
|
|
737
|
+
const placeholder =
|
|
738
|
+
this._dateInputElement?.getAttribute('placeholder') ||
|
|
739
|
+
'Select date range';
|
|
740
|
+
this._displayElement.innerHTML = placeholderTemplate(placeholder);
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if (this._useSegmentedDisplay) {
|
|
745
|
+
// Update segmented range display
|
|
746
|
+
// Start date segments
|
|
747
|
+
const startDay = this._displayElement.querySelector(
|
|
748
|
+
'[data-segment="start-day"]',
|
|
749
|
+
);
|
|
750
|
+
const startMonth = this._displayElement.querySelector(
|
|
751
|
+
'[data-segment="start-month"]',
|
|
752
|
+
);
|
|
753
|
+
const startYear = this._displayElement.querySelector(
|
|
754
|
+
'[data-segment="start-year"]',
|
|
755
|
+
);
|
|
756
|
+
|
|
757
|
+
if (startDay)
|
|
758
|
+
startDay.textContent =
|
|
759
|
+
startDate.getDate() < 10
|
|
760
|
+
? `0${startDate.getDate()}`
|
|
761
|
+
: `${startDate.getDate()}`;
|
|
762
|
+
if (startMonth)
|
|
763
|
+
startMonth.textContent =
|
|
764
|
+
startDate.getMonth() + 1 < 10
|
|
765
|
+
? `0${startDate.getMonth() + 1}`
|
|
766
|
+
: `${startDate.getMonth() + 1}`;
|
|
767
|
+
if (startYear) startYear.textContent = `${startDate.getFullYear()}`;
|
|
768
|
+
|
|
769
|
+
// End date segments
|
|
770
|
+
if (endDate) {
|
|
771
|
+
const endDay = this._displayElement.querySelector(
|
|
772
|
+
'[data-segment="end-day"]',
|
|
773
|
+
);
|
|
774
|
+
const endMonth = this._displayElement.querySelector(
|
|
775
|
+
'[data-segment="end-month"]',
|
|
776
|
+
);
|
|
777
|
+
const endYear = this._displayElement.querySelector(
|
|
778
|
+
'[data-segment="end-year"]',
|
|
779
|
+
);
|
|
780
|
+
|
|
781
|
+
if (endDay)
|
|
782
|
+
endDay.textContent =
|
|
783
|
+
endDate.getDate() < 10
|
|
784
|
+
? `0${endDate.getDate()}`
|
|
785
|
+
: `${endDate.getDate()}`;
|
|
786
|
+
if (endMonth)
|
|
787
|
+
endMonth.textContent =
|
|
788
|
+
endDate.getMonth() + 1 < 10
|
|
789
|
+
? `0${endDate.getMonth() + 1}`
|
|
790
|
+
: `${endDate.getMonth() + 1}`;
|
|
791
|
+
if (endYear) endYear.textContent = `${endDate.getFullYear()}`;
|
|
792
|
+
}
|
|
793
|
+
} else {
|
|
794
|
+
// Simple display
|
|
795
|
+
let displayText = formatDate(
|
|
796
|
+
startDate,
|
|
797
|
+
this._config.format,
|
|
798
|
+
this._config,
|
|
799
|
+
);
|
|
800
|
+
|
|
801
|
+
if (endDate) {
|
|
802
|
+
const endFormatted = formatDate(
|
|
803
|
+
endDate,
|
|
804
|
+
this._config.format,
|
|
805
|
+
this._config,
|
|
806
|
+
);
|
|
807
|
+
displayText += `${this._config.rangeSeparator}${endFormatted}`;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
this._displayElement.textContent = displayText;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Handle input change events
|
|
816
|
+
*
|
|
817
|
+
* @param e - Input change event
|
|
818
|
+
*/
|
|
819
|
+
private _handleInputChange(e: Event): void {
|
|
820
|
+
const input = e.target as HTMLInputElement;
|
|
821
|
+
const inputValue = input.value.trim();
|
|
822
|
+
|
|
823
|
+
if (!inputValue) {
|
|
824
|
+
// Clear selection if input is empty
|
|
825
|
+
this._state.setSelectedDate(null);
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (this._config.range) {
|
|
830
|
+
// Handle range input
|
|
831
|
+
const rangeParts = inputValue.split(this._config.rangeSeparator);
|
|
832
|
+
|
|
833
|
+
if (rangeParts.length === 2) {
|
|
834
|
+
const startDate = parseDate(
|
|
835
|
+
rangeParts[0].trim(),
|
|
836
|
+
this._config.format,
|
|
837
|
+
this._config,
|
|
838
|
+
);
|
|
839
|
+
const endDate = parseDate(
|
|
840
|
+
rangeParts[1].trim(),
|
|
841
|
+
this._config.format,
|
|
842
|
+
this._config,
|
|
843
|
+
);
|
|
844
|
+
|
|
845
|
+
// Validate dates are within min/max constraints
|
|
846
|
+
if (startDate && isDateDisabled(startDate, this._config)) {
|
|
847
|
+
console.log(
|
|
848
|
+
'Start date from input is outside allowed range:',
|
|
849
|
+
startDate.toISOString(),
|
|
850
|
+
);
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
if (endDate && isDateDisabled(endDate, this._config)) {
|
|
855
|
+
console.log(
|
|
856
|
+
'End date from input is outside allowed range:',
|
|
857
|
+
endDate.toISOString(),
|
|
858
|
+
);
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
if (startDate && endDate) {
|
|
863
|
+
this.setDateRange(startDate, endDate);
|
|
864
|
+
}
|
|
865
|
+
} else if (rangeParts.length === 1) {
|
|
866
|
+
const singleDate = parseDate(
|
|
867
|
+
rangeParts[0].trim(),
|
|
868
|
+
this._config.format,
|
|
869
|
+
this._config,
|
|
870
|
+
);
|
|
871
|
+
|
|
872
|
+
// Validate date is within min/max constraints
|
|
873
|
+
if (singleDate && isDateDisabled(singleDate, this._config)) {
|
|
874
|
+
console.log(
|
|
875
|
+
'Date from input is outside allowed range:',
|
|
876
|
+
singleDate.toISOString(),
|
|
877
|
+
);
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
if (singleDate) {
|
|
882
|
+
this.setDateRange(singleDate, null);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
} else {
|
|
886
|
+
// Handle single date input
|
|
887
|
+
const parsedDate = parseDate(
|
|
888
|
+
inputValue,
|
|
889
|
+
this._config.format,
|
|
890
|
+
this._config,
|
|
891
|
+
);
|
|
892
|
+
|
|
893
|
+
// Validate date is within min/max constraints
|
|
894
|
+
if (parsedDate && isDateDisabled(parsedDate, this._config)) {
|
|
895
|
+
console.log(
|
|
896
|
+
'Date from input is outside allowed range:',
|
|
897
|
+
parsedDate.toISOString(),
|
|
898
|
+
);
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if (parsedDate) {
|
|
903
|
+
this.setDate(parsedDate);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* Initialize with default values from input
|
|
910
|
+
*/
|
|
911
|
+
private _initializeDefaultValues(): void {
|
|
912
|
+
// Set min and max dates from attributes if they exist
|
|
913
|
+
const minDateAttr = this._element.getAttribute(
|
|
914
|
+
'data-kt-datepicker-min-date',
|
|
915
|
+
);
|
|
916
|
+
const maxDateAttr = this._element.getAttribute(
|
|
917
|
+
'data-kt-datepicker-max-date',
|
|
918
|
+
);
|
|
919
|
+
|
|
920
|
+
if (minDateAttr) {
|
|
921
|
+
const minDate = parseDate(minDateAttr, this._config.format, this._config);
|
|
922
|
+
if (minDate) {
|
|
923
|
+
this.setMinDate(minDate);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
if (maxDateAttr) {
|
|
928
|
+
const maxDate = parseDate(maxDateAttr, this._config.format, this._config);
|
|
929
|
+
if (maxDate) {
|
|
930
|
+
this.setMaxDate(maxDate);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// Check for default value in main input
|
|
935
|
+
if (this._dateInputElement && this._dateInputElement.value) {
|
|
936
|
+
this._handleInputChange({
|
|
937
|
+
target: this._dateInputElement,
|
|
938
|
+
} as unknown as Event);
|
|
939
|
+
}
|
|
940
|
+
// Check for default values in range inputs
|
|
941
|
+
else if (
|
|
942
|
+
this._config.range &&
|
|
943
|
+
this._startDateInputElement &&
|
|
944
|
+
this._startDateInputElement.value
|
|
945
|
+
) {
|
|
946
|
+
const startDate = parseDate(
|
|
947
|
+
this._startDateInputElement.value,
|
|
948
|
+
this._config.format,
|
|
949
|
+
this._config,
|
|
950
|
+
);
|
|
951
|
+
let endDate = null;
|
|
952
|
+
|
|
953
|
+
if (this._endDateInputElement && this._endDateInputElement.value) {
|
|
954
|
+
endDate = parseDate(
|
|
955
|
+
this._endDateInputElement.value,
|
|
956
|
+
this._config.format,
|
|
957
|
+
this._config,
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
if (startDate) {
|
|
962
|
+
this.setDateRange(startDate, endDate);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* ========================================================================
|
|
969
|
+
* Public API
|
|
970
|
+
* ========================================================================
|
|
971
|
+
*/
|
|
972
|
+
|
|
973
|
+
/**
|
|
974
|
+
* Get the currently selected date
|
|
975
|
+
*
|
|
976
|
+
* @returns Selected date, null if no selection, or date range object
|
|
977
|
+
*/
|
|
978
|
+
public getDate(): Date | null | DateRangeInterface {
|
|
979
|
+
const state = this._state.getState();
|
|
980
|
+
const config = this._state.getConfig();
|
|
981
|
+
|
|
982
|
+
if (config.range) {
|
|
983
|
+
return state.selectedDateRange || { startDate: null, endDate: null };
|
|
984
|
+
} else {
|
|
985
|
+
return state.selectedDate;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* Set the selected date
|
|
991
|
+
*
|
|
992
|
+
* @param date - Date to select or null to clear selection
|
|
993
|
+
*/
|
|
994
|
+
public setDate(date: Date | null): void {
|
|
995
|
+
// Skip if the date is disabled (outside min/max range)
|
|
996
|
+
if (date && isDateDisabled(date, this._config)) {
|
|
997
|
+
console.log(
|
|
998
|
+
'Date is disabled in setDate, ignoring selection:',
|
|
999
|
+
date.toISOString(),
|
|
1000
|
+
);
|
|
1001
|
+
return;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
this._state.setSelectedDate(date);
|
|
1005
|
+
|
|
1006
|
+
if (date) {
|
|
1007
|
+
this._state.setCurrentDate(date);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// Update the display
|
|
1011
|
+
this._updateDisplayElement(date);
|
|
1012
|
+
|
|
1013
|
+
// Update hidden input
|
|
1014
|
+
if (this._dateInputElement && date) {
|
|
1015
|
+
this._dateInputElement.value = formatDate(
|
|
1016
|
+
date,
|
|
1017
|
+
this._config.format,
|
|
1018
|
+
this._config,
|
|
1019
|
+
);
|
|
1020
|
+
this._dateInputElement.dispatchEvent(
|
|
1021
|
+
new Event('change', { bubbles: true }),
|
|
1022
|
+
);
|
|
1023
|
+
} else if (this._dateInputElement) {
|
|
1024
|
+
this._dateInputElement.value = '';
|
|
1025
|
+
this._dateInputElement.dispatchEvent(
|
|
1026
|
+
new Event('change', { bubbles: true }),
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Get the currently selected date range
|
|
1033
|
+
*
|
|
1034
|
+
* @returns Selected date range or null if no selection
|
|
1035
|
+
*/
|
|
1036
|
+
public getDateRange(): DateRangeInterface | null {
|
|
1037
|
+
const state = this._state.getState();
|
|
1038
|
+
return state.selectedDateRange;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Set the selected date range
|
|
1043
|
+
*
|
|
1044
|
+
* @param start - Start date of the range
|
|
1045
|
+
* @param end - End date of the range
|
|
1046
|
+
*/
|
|
1047
|
+
public setDateRange(start: Date | null, end: Date | null): void {
|
|
1048
|
+
const state = this._state.getState();
|
|
1049
|
+
|
|
1050
|
+
// Ensure we're in range mode
|
|
1051
|
+
if (!this._config.range) {
|
|
1052
|
+
console.warn('Cannot set date range when range mode is disabled');
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
// Validate start and end dates are within min/max range
|
|
1057
|
+
if (start && isDateDisabled(start, this._config)) {
|
|
1058
|
+
console.log(
|
|
1059
|
+
'Start date is disabled in setDateRange, ignoring selection:',
|
|
1060
|
+
start.toISOString(),
|
|
1061
|
+
);
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
if (end && isDateDisabled(end, this._config)) {
|
|
1066
|
+
console.log(
|
|
1067
|
+
'End date is disabled in setDateRange, ignoring selection:',
|
|
1068
|
+
end.toISOString(),
|
|
1069
|
+
);
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
// Reset range selection state
|
|
1074
|
+
this._state.getState().isRangeSelectionStart = true;
|
|
1075
|
+
|
|
1076
|
+
// Set start date
|
|
1077
|
+
if (start) {
|
|
1078
|
+
if (!state.selectedDateRange) {
|
|
1079
|
+
state.selectedDateRange = { startDate: null, endDate: null };
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
state.selectedDateRange.startDate = start;
|
|
1083
|
+
this._state.setCurrentDate(start);
|
|
1084
|
+
|
|
1085
|
+
// Set end date if provided
|
|
1086
|
+
if (end) {
|
|
1087
|
+
state.selectedDateRange.endDate = end;
|
|
1088
|
+
} else {
|
|
1089
|
+
state.selectedDateRange.endDate = null;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
// Update display element
|
|
1093
|
+
this._updateRangeDisplayElement(start, end);
|
|
1094
|
+
|
|
1095
|
+
// Update hidden inputs
|
|
1096
|
+
if (this._dateInputElement) {
|
|
1097
|
+
let inputValue = formatDate(start, this._config.format, this._config);
|
|
1098
|
+
if (end) {
|
|
1099
|
+
inputValue += `${this._config.rangeSeparator}${formatDate(
|
|
1100
|
+
end,
|
|
1101
|
+
this._config.format,
|
|
1102
|
+
this._config,
|
|
1103
|
+
)}`;
|
|
1104
|
+
}
|
|
1105
|
+
this._dateInputElement.value = inputValue;
|
|
1106
|
+
this._dateInputElement.dispatchEvent(
|
|
1107
|
+
new Event('change', { bubbles: true }),
|
|
1108
|
+
);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
if (this._startDateInputElement) {
|
|
1112
|
+
this._startDateInputElement.value = formatDate(
|
|
1113
|
+
start,
|
|
1114
|
+
this._config.format,
|
|
1115
|
+
this._config,
|
|
1116
|
+
);
|
|
1117
|
+
this._startDateInputElement.dispatchEvent(
|
|
1118
|
+
new Event('change', { bubbles: true }),
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
if (this._endDateInputElement && end) {
|
|
1123
|
+
this._endDateInputElement.value = formatDate(
|
|
1124
|
+
end,
|
|
1125
|
+
this._config.format,
|
|
1126
|
+
this._config,
|
|
1127
|
+
);
|
|
1128
|
+
this._endDateInputElement.dispatchEvent(
|
|
1129
|
+
new Event('change', { bubbles: true }),
|
|
1130
|
+
);
|
|
1131
|
+
} else if (this._endDateInputElement) {
|
|
1132
|
+
this._endDateInputElement.value = '';
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// Dispatch change event
|
|
1136
|
+
this._eventManager.dispatchEvent(KTDatepickerEventName.DATE_CHANGE, {
|
|
1137
|
+
selectedDateRange: state.selectedDateRange,
|
|
1138
|
+
});
|
|
1139
|
+
} else {
|
|
1140
|
+
// Clear selection
|
|
1141
|
+
this._state.getState().selectedDateRange = null;
|
|
1142
|
+
|
|
1143
|
+
// Clear display
|
|
1144
|
+
if (this._displayElement) {
|
|
1145
|
+
const placeholder =
|
|
1146
|
+
this._dateInputElement?.getAttribute('placeholder') ||
|
|
1147
|
+
'Select date range';
|
|
1148
|
+
this._displayElement.innerHTML = placeholderTemplate(placeholder);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
// Clear inputs
|
|
1152
|
+
if (this._dateInputElement) {
|
|
1153
|
+
this._dateInputElement.value = '';
|
|
1154
|
+
this._dateInputElement.dispatchEvent(
|
|
1155
|
+
new Event('change', { bubbles: true }),
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
if (this._startDateInputElement) {
|
|
1160
|
+
this._startDateInputElement.value = '';
|
|
1161
|
+
this._startDateInputElement.dispatchEvent(
|
|
1162
|
+
new Event('change', { bubbles: true }),
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
if (this._endDateInputElement) {
|
|
1167
|
+
this._endDateInputElement.value = '';
|
|
1168
|
+
this._endDateInputElement.dispatchEvent(
|
|
1169
|
+
new Event('change', { bubbles: true }),
|
|
1170
|
+
);
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
this._eventManager.dispatchEvent(KTDatepickerEventName.DATE_CHANGE, {
|
|
1174
|
+
selectedDateRange: null,
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* Set the minimum selectable date
|
|
1181
|
+
*
|
|
1182
|
+
* @param minDate - Minimum date or null to remove constraint
|
|
1183
|
+
*/
|
|
1184
|
+
public setMinDate(minDate: Date | null): void {
|
|
1185
|
+
this._config.minDate = minDate;
|
|
1186
|
+
|
|
1187
|
+
// Refresh calendar view to apply new constraints
|
|
1188
|
+
this._eventManager.dispatchEvent(KTDatepickerEventName.UPDATE);
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
/**
|
|
1192
|
+
* Set the maximum selectable date
|
|
1193
|
+
*
|
|
1194
|
+
* @param maxDate - Maximum date or null to remove constraint
|
|
1195
|
+
*/
|
|
1196
|
+
public setMaxDate(maxDate: Date | null): void {
|
|
1197
|
+
this._config.maxDate = maxDate;
|
|
1198
|
+
|
|
1199
|
+
// Refresh calendar view to apply new constraints
|
|
1200
|
+
this._eventManager.dispatchEvent(KTDatepickerEventName.UPDATE);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
/**
|
|
1204
|
+
* Update the datepicker (refresh view)
|
|
1205
|
+
*/
|
|
1206
|
+
public update(): void {
|
|
1207
|
+
// Trigger calendar update through events
|
|
1208
|
+
this._eventManager.dispatchEvent(KTDatepickerEventName.UPDATE);
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
/**
|
|
1212
|
+
* Destroy the datepicker instance and clean up
|
|
1213
|
+
*/
|
|
1214
|
+
public destroy(): void {
|
|
1215
|
+
// Remove event listeners
|
|
1216
|
+
this._eventManager.removeEventListener(
|
|
1217
|
+
KTDatepickerEventName.DATE_CHANGE,
|
|
1218
|
+
this._handleDateChange.bind(this),
|
|
1219
|
+
);
|
|
1220
|
+
|
|
1221
|
+
if (this._dateInputElement) {
|
|
1222
|
+
this._dateInputElement.removeEventListener(
|
|
1223
|
+
'change',
|
|
1224
|
+
this._handleInputChange.bind(this),
|
|
1225
|
+
);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
if (this._displayElement) {
|
|
1229
|
+
this._displayElement.remove();
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
// Remove instance from element
|
|
1233
|
+
this._element.removeAttribute('data-kt-datepicker-initialized');
|
|
1234
|
+
delete (this._element as any).instance;
|
|
1235
|
+
|
|
1236
|
+
// Remove initialized class
|
|
1237
|
+
this._element.classList.remove('relative');
|
|
1238
|
+
|
|
1239
|
+
// Remove from instances map
|
|
1240
|
+
KTDatepicker._instances.delete(this._element);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
/**
|
|
1244
|
+
* Dispatch a custom event
|
|
1245
|
+
*
|
|
1246
|
+
* @param eventName - Name of the event
|
|
1247
|
+
* @param payload - Optional event payload
|
|
1248
|
+
*/
|
|
1249
|
+
protected _dispatchEvent(eventName: string, payload?: any): void {
|
|
1250
|
+
this._eventManager.dispatchEvent(eventName, payload);
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
/**
|
|
1254
|
+
* ========================================================================
|
|
1255
|
+
* Static instances
|
|
1256
|
+
* ========================================================================
|
|
1257
|
+
*/
|
|
1258
|
+
|
|
1259
|
+
private static readonly _instances = new Map<HTMLElement, KTDatepicker>();
|
|
1260
|
+
|
|
1261
|
+
/**
|
|
1262
|
+
* Create instances for all datepicker elements on the page
|
|
1263
|
+
*/
|
|
1264
|
+
public static createInstances(): void {
|
|
1265
|
+
const elements = document.querySelectorAll<HTMLElement>(
|
|
1266
|
+
'[data-kt-datepicker]',
|
|
1267
|
+
);
|
|
1268
|
+
|
|
1269
|
+
elements.forEach((element) => {
|
|
1270
|
+
if (
|
|
1271
|
+
element.hasAttribute('data-kt-datepicker') &&
|
|
1272
|
+
!element.getAttribute('data-kt-datepicker-initialized')
|
|
1273
|
+
) {
|
|
1274
|
+
// Create instance
|
|
1275
|
+
const instance = new KTDatepicker(element);
|
|
1276
|
+
this._instances.set(element, instance);
|
|
1277
|
+
}
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* Initialize all datepickers on the page
|
|
1283
|
+
*/
|
|
1284
|
+
public static init(): void {
|
|
1285
|
+
KTDatepicker.createInstances();
|
|
1286
|
+
}
|
|
1287
|
+
}
|