@keenthemes/ktui 1.0.7 → 1.0.9
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/dist/ktui.js +16038 -17101
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/lib/cjs/components/accordion/accordion.js +20 -11
- package/lib/cjs/components/accordion/accordion.js.map +1 -1
- package/lib/cjs/components/accordion/index.js +4 -0
- package/lib/cjs/components/accordion/index.js.map +1 -1
- package/lib/cjs/components/accordion/types.js +4 -0
- package/lib/cjs/components/accordion/types.js.map +1 -1
- package/lib/cjs/components/collapse/collapse.js +13 -7
- package/lib/cjs/components/collapse/collapse.js.map +1 -1
- package/lib/cjs/components/collapse/index.js +4 -0
- package/lib/cjs/components/collapse/index.js.map +1 -1
- package/lib/cjs/components/collapse/types.js +4 -0
- package/lib/cjs/components/collapse/types.js.map +1 -1
- package/lib/cjs/components/component.js +12 -41
- package/lib/cjs/components/component.js.map +1 -1
- package/lib/cjs/components/constants.js +4 -0
- package/lib/cjs/components/constants.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-checkbox.js +217 -0
- package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-sort.js +91 -0
- package/lib/cjs/components/datatable/datatable-sort.js.map +1 -0
- package/lib/cjs/components/datatable/datatable.js +294 -349
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/datatable/index.js +4 -0
- package/lib/cjs/components/datatable/index.js.map +1 -1
- package/lib/cjs/components/datatable/types.js +4 -0
- package/lib/cjs/components/datatable/types.js.map +1 -1
- package/lib/cjs/components/datepicker/calendar.js +1061 -0
- package/lib/cjs/components/datepicker/calendar.js.map +1 -0
- package/lib/cjs/components/datepicker/config.js +332 -0
- package/lib/cjs/components/datepicker/config.js.map +1 -0
- package/lib/cjs/components/datepicker/datepicker.js +949 -0
- package/lib/cjs/components/datepicker/datepicker.js.map +1 -0
- package/lib/cjs/components/datepicker/dropdown.js +635 -0
- package/lib/cjs/components/datepicker/dropdown.js.map +1 -0
- package/lib/cjs/components/datepicker/events.js +129 -0
- package/lib/cjs/components/datepicker/events.js.map +1 -0
- package/lib/cjs/components/datepicker/index.js +13 -0
- package/lib/cjs/components/datepicker/index.js.map +1 -0
- package/lib/cjs/components/datepicker/keyboard.js +536 -0
- package/lib/cjs/components/datepicker/keyboard.js.map +1 -0
- package/lib/cjs/components/datepicker/locales.js +78 -0
- package/lib/cjs/components/datepicker/locales.js.map +1 -0
- package/lib/cjs/components/datepicker/templates.js +403 -0
- package/lib/cjs/components/datepicker/templates.js.map +1 -0
- package/lib/cjs/components/datepicker/types.js +23 -0
- package/lib/cjs/components/datepicker/types.js.map +1 -0
- package/lib/cjs/components/datepicker/utils.js +524 -0
- package/lib/cjs/components/datepicker/utils.js.map +1 -0
- package/lib/cjs/components/dismiss/dismiss.js +10 -6
- package/lib/cjs/components/dismiss/dismiss.js.map +1 -1
- package/lib/cjs/components/dismiss/index.js +4 -0
- package/lib/cjs/components/dismiss/index.js.map +1 -1
- package/lib/cjs/components/dismiss/types.js +4 -0
- package/lib/cjs/components/dismiss/types.js.map +1 -1
- package/lib/cjs/components/drawer/drawer.js +54 -28
- package/lib/cjs/components/drawer/drawer.js.map +1 -1
- package/lib/cjs/components/drawer/index.js +4 -0
- package/lib/cjs/components/drawer/index.js.map +1 -1
- package/lib/cjs/components/drawer/types.js +4 -0
- package/lib/cjs/components/drawer/types.js.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.js +145 -115
- package/lib/cjs/components/dropdown/dropdown.js.map +1 -1
- package/lib/cjs/components/dropdown/index.js +4 -0
- package/lib/cjs/components/dropdown/index.js.map +1 -1
- package/lib/cjs/components/dropdown/types.js +4 -0
- package/lib/cjs/components/dropdown/types.js.map +1 -1
- package/lib/cjs/components/image-input/image-input.js +21 -16
- package/lib/cjs/components/image-input/image-input.js.map +1 -1
- package/lib/cjs/components/image-input/index.js +4 -0
- package/lib/cjs/components/image-input/index.js.map +1 -1
- package/lib/cjs/components/image-input/types.js +4 -0
- package/lib/cjs/components/image-input/types.js.map +1 -1
- package/lib/cjs/components/modal/index.js +4 -0
- package/lib/cjs/components/modal/index.js.map +1 -1
- package/lib/cjs/components/modal/modal.js +26 -19
- package/lib/cjs/components/modal/modal.js.map +1 -1
- package/lib/cjs/components/modal/types.js +4 -0
- package/lib/cjs/components/modal/types.js.map +1 -1
- package/lib/cjs/components/reparent/index.js +4 -0
- package/lib/cjs/components/reparent/index.js.map +1 -1
- package/lib/cjs/components/reparent/reparent.js +13 -5
- package/lib/cjs/components/reparent/reparent.js.map +1 -1
- package/lib/cjs/components/reparent/types.js +4 -0
- package/lib/cjs/components/reparent/types.js.map +1 -1
- package/lib/cjs/components/scrollable/index.js +4 -0
- package/lib/cjs/components/scrollable/index.js.map +1 -1
- package/lib/cjs/components/scrollable/scrollable.js +17 -10
- package/lib/cjs/components/scrollable/scrollable.js.map +1 -1
- package/lib/cjs/components/scrollable/types.js +4 -0
- package/lib/cjs/components/scrollable/types.js.map +1 -1
- package/lib/cjs/components/scrollspy/index.js +4 -0
- package/lib/cjs/components/scrollspy/index.js.map +1 -1
- package/lib/cjs/components/scrollspy/scrollspy.js +28 -17
- package/lib/cjs/components/scrollspy/scrollspy.js.map +1 -1
- package/lib/cjs/components/scrollspy/types.js +4 -0
- package/lib/cjs/components/scrollspy/types.js.map +1 -1
- package/lib/cjs/components/scrollto/index.js +4 -0
- package/lib/cjs/components/scrollto/index.js.map +1 -1
- package/lib/cjs/components/scrollto/scrollto.js +14 -8
- package/lib/cjs/components/scrollto/scrollto.js.map +1 -1
- package/lib/cjs/components/scrollto/types.js +4 -0
- package/lib/cjs/components/scrollto/types.js.map +1 -1
- package/lib/cjs/components/select/combobox.js +237 -0
- package/lib/cjs/components/select/combobox.js.map +1 -0
- package/lib/cjs/components/select/config.js +226 -0
- package/lib/cjs/components/select/config.js.map +1 -0
- package/lib/cjs/components/select/dropdown.js +429 -0
- package/lib/cjs/components/select/dropdown.js.map +1 -0
- package/lib/cjs/components/select/index.js +24 -0
- package/lib/cjs/components/select/index.js.map +1 -0
- package/lib/cjs/components/select/option.js +53 -0
- package/lib/cjs/components/select/option.js.map +1 -0
- package/lib/cjs/components/select/remote.js +414 -0
- package/lib/cjs/components/select/remote.js.map +1 -0
- package/lib/cjs/components/select/search.js +339 -0
- package/lib/cjs/components/select/search.js.map +1 -0
- package/lib/cjs/components/select/select.js +1538 -0
- package/lib/cjs/components/select/select.js.map +1 -0
- package/lib/cjs/components/select/tags.js +110 -0
- package/lib/cjs/components/select/tags.js.map +1 -0
- package/lib/cjs/components/select/templates.js +337 -0
- package/lib/cjs/components/select/templates.js.map +1 -0
- package/lib/cjs/components/select/types.js +19 -0
- package/lib/cjs/components/select/types.js.map +1 -0
- package/lib/cjs/components/select/utils.js +606 -0
- package/lib/cjs/components/select/utils.js.map +1 -0
- package/lib/cjs/components/stepper/index.js +4 -0
- package/lib/cjs/components/stepper/index.js.map +1 -1
- package/lib/cjs/components/stepper/stepper.js +20 -13
- package/lib/cjs/components/stepper/stepper.js.map +1 -1
- package/lib/cjs/components/stepper/types.js +4 -0
- package/lib/cjs/components/stepper/types.js.map +1 -1
- package/lib/cjs/components/sticky/index.js +4 -0
- package/lib/cjs/components/sticky/index.js.map +1 -1
- package/lib/cjs/components/sticky/sticky.js +60 -38
- package/lib/cjs/components/sticky/sticky.js.map +1 -1
- package/lib/cjs/components/sticky/types.js +4 -0
- package/lib/cjs/components/sticky/types.js.map +1 -1
- package/lib/cjs/components/tabs/index.js +4 -0
- package/lib/cjs/components/tabs/index.js.map +1 -1
- package/lib/cjs/components/tabs/tabs.js +34 -24
- package/lib/cjs/components/tabs/tabs.js.map +1 -1
- package/lib/cjs/components/tabs/types.js +4 -0
- package/lib/cjs/components/tabs/types.js.map +1 -1
- package/lib/cjs/components/theme-switch/index.js +10 -0
- package/lib/cjs/components/theme-switch/index.js.map +1 -0
- package/lib/cjs/components/theme-switch/theme-switch.js +143 -0
- package/lib/cjs/components/theme-switch/theme-switch.js.map +1 -0
- package/lib/cjs/components/theme-switch/types.js +7 -0
- package/lib/cjs/components/theme-switch/types.js.map +1 -0
- package/lib/cjs/components/toggle/index.js +4 -0
- package/lib/cjs/components/toggle/index.js.map +1 -1
- package/lib/cjs/components/toggle/toggle.js +11 -7
- package/lib/cjs/components/toggle/toggle.js.map +1 -1
- package/lib/cjs/components/toggle/types.js +4 -0
- package/lib/cjs/components/toggle/types.js.map +1 -1
- package/lib/cjs/components/toggle-password/index.js +4 -0
- package/lib/cjs/components/toggle-password/index.js.map +1 -1
- package/lib/cjs/components/toggle-password/toggle-password.js +12 -7
- package/lib/cjs/components/toggle-password/toggle-password.js.map +1 -1
- package/lib/cjs/components/toggle-password/types.js +4 -0
- package/lib/cjs/components/toggle-password/types.js.map +1 -1
- package/lib/cjs/components/tooltip/index.js +4 -0
- package/lib/cjs/components/tooltip/index.js.map +1 -1
- package/lib/cjs/components/tooltip/tooltip.js +51 -21
- package/lib/cjs/components/tooltip/tooltip.js.map +1 -1
- package/lib/cjs/components/tooltip/types.js +4 -0
- package/lib/cjs/components/tooltip/types.js.map +1 -1
- package/lib/cjs/helpers/data.js +5 -1
- package/lib/cjs/helpers/data.js.map +1 -1
- package/lib/cjs/helpers/dom.js +34 -29
- package/lib/cjs/helpers/dom.js.map +1 -1
- package/lib/cjs/helpers/event-handler.js +5 -1
- package/lib/cjs/helpers/event-handler.js.map +1 -1
- package/lib/cjs/helpers/utils.js +65 -11
- package/lib/cjs/helpers/utils.js.map +1 -1
- package/lib/cjs/index.js +18 -22
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/types.js +4 -0
- package/lib/cjs/types.js.map +1 -1
- package/lib/esm/components/accordion/accordion.js +20 -11
- package/lib/esm/components/accordion/accordion.js.map +1 -1
- package/lib/esm/components/accordion/index.js +4 -0
- package/lib/esm/components/accordion/index.js.map +1 -1
- package/lib/esm/components/accordion/types.js +4 -0
- package/lib/esm/components/accordion/types.js.map +1 -1
- package/lib/esm/components/collapse/collapse.js +13 -7
- package/lib/esm/components/collapse/collapse.js.map +1 -1
- package/lib/esm/components/collapse/index.js +4 -0
- package/lib/esm/components/collapse/index.js.map +1 -1
- package/lib/esm/components/collapse/types.js +4 -0
- package/lib/esm/components/collapse/types.js.map +1 -1
- package/lib/esm/components/component.js +12 -41
- package/lib/esm/components/component.js.map +1 -1
- package/lib/esm/components/constants.js +4 -0
- package/lib/esm/components/constants.js.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.js +214 -0
- package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -0
- package/lib/esm/components/datatable/datatable-sort.js +88 -0
- package/lib/esm/components/datatable/datatable-sort.js.map +1 -0
- package/lib/esm/components/datatable/datatable.js +294 -349
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/datatable/index.js +4 -0
- package/lib/esm/components/datatable/index.js.map +1 -1
- package/lib/esm/components/datatable/types.js +4 -0
- package/lib/esm/components/datatable/types.js.map +1 -1
- package/lib/esm/components/datepicker/calendar.js +1058 -0
- package/lib/esm/components/datepicker/calendar.js.map +1 -0
- package/lib/esm/components/datepicker/config.js +329 -0
- package/lib/esm/components/datepicker/config.js.map +1 -0
- package/lib/esm/components/datepicker/datepicker.js +946 -0
- package/lib/esm/components/datepicker/datepicker.js.map +1 -0
- package/lib/esm/components/datepicker/dropdown.js +632 -0
- package/lib/esm/components/datepicker/dropdown.js.map +1 -0
- package/lib/esm/components/datepicker/events.js +126 -0
- package/lib/esm/components/datepicker/events.js.map +1 -0
- package/lib/esm/components/datepicker/index.js +9 -0
- package/lib/esm/components/datepicker/index.js.map +1 -0
- package/lib/esm/components/datepicker/keyboard.js +533 -0
- package/lib/esm/components/datepicker/keyboard.js.map +1 -0
- package/lib/esm/components/datepicker/locales.js +74 -0
- package/lib/esm/components/datepicker/locales.js.map +1 -0
- package/lib/esm/components/datepicker/templates.js +390 -0
- package/lib/esm/components/datepicker/templates.js.map +1 -0
- package/lib/esm/components/datepicker/types.js +20 -0
- package/lib/esm/components/datepicker/types.js.map +1 -0
- package/lib/esm/components/datepicker/utils.js +508 -0
- package/lib/esm/components/datepicker/utils.js.map +1 -0
- package/lib/esm/components/dismiss/dismiss.js +10 -6
- package/lib/esm/components/dismiss/dismiss.js.map +1 -1
- package/lib/esm/components/dismiss/index.js +4 -0
- package/lib/esm/components/dismiss/index.js.map +1 -1
- package/lib/esm/components/dismiss/types.js +4 -0
- package/lib/esm/components/dismiss/types.js.map +1 -1
- package/lib/esm/components/drawer/drawer.js +54 -28
- package/lib/esm/components/drawer/drawer.js.map +1 -1
- package/lib/esm/components/drawer/index.js +4 -0
- package/lib/esm/components/drawer/index.js.map +1 -1
- package/lib/esm/components/drawer/types.js +4 -0
- package/lib/esm/components/drawer/types.js.map +1 -1
- package/lib/esm/components/dropdown/dropdown.js +146 -116
- package/lib/esm/components/dropdown/dropdown.js.map +1 -1
- package/lib/esm/components/dropdown/index.js +4 -0
- package/lib/esm/components/dropdown/index.js.map +1 -1
- package/lib/esm/components/dropdown/types.js +4 -0
- package/lib/esm/components/dropdown/types.js.map +1 -1
- package/lib/esm/components/image-input/image-input.js +21 -16
- package/lib/esm/components/image-input/image-input.js.map +1 -1
- package/lib/esm/components/image-input/index.js +4 -0
- package/lib/esm/components/image-input/index.js.map +1 -1
- package/lib/esm/components/image-input/types.js +4 -0
- package/lib/esm/components/image-input/types.js.map +1 -1
- package/lib/esm/components/modal/index.js +4 -0
- package/lib/esm/components/modal/index.js.map +1 -1
- package/lib/esm/components/modal/modal.js +26 -19
- package/lib/esm/components/modal/modal.js.map +1 -1
- package/lib/esm/components/modal/types.js +4 -0
- package/lib/esm/components/modal/types.js.map +1 -1
- package/lib/esm/components/reparent/index.js +4 -0
- package/lib/esm/components/reparent/index.js.map +1 -1
- package/lib/esm/components/reparent/reparent.js +13 -5
- package/lib/esm/components/reparent/reparent.js.map +1 -1
- package/lib/esm/components/reparent/types.js +4 -0
- package/lib/esm/components/reparent/types.js.map +1 -1
- package/lib/esm/components/scrollable/index.js +4 -0
- package/lib/esm/components/scrollable/index.js.map +1 -1
- package/lib/esm/components/scrollable/scrollable.js +17 -10
- package/lib/esm/components/scrollable/scrollable.js.map +1 -1
- package/lib/esm/components/scrollable/types.js +4 -0
- package/lib/esm/components/scrollable/types.js.map +1 -1
- package/lib/esm/components/scrollspy/index.js +4 -0
- package/lib/esm/components/scrollspy/index.js.map +1 -1
- package/lib/esm/components/scrollspy/scrollspy.js +28 -17
- package/lib/esm/components/scrollspy/scrollspy.js.map +1 -1
- package/lib/esm/components/scrollspy/types.js +4 -0
- package/lib/esm/components/scrollspy/types.js.map +1 -1
- package/lib/esm/components/scrollto/index.js +4 -0
- package/lib/esm/components/scrollto/index.js.map +1 -1
- package/lib/esm/components/scrollto/scrollto.js +14 -8
- package/lib/esm/components/scrollto/scrollto.js.map +1 -1
- package/lib/esm/components/scrollto/types.js +4 -0
- package/lib/esm/components/scrollto/types.js.map +1 -1
- package/lib/esm/components/select/combobox.js +234 -0
- package/lib/esm/components/select/combobox.js.map +1 -0
- package/lib/esm/components/select/config.js +223 -0
- package/lib/esm/components/select/config.js.map +1 -0
- package/lib/esm/components/select/dropdown.js +426 -0
- package/lib/esm/components/select/dropdown.js.map +1 -0
- package/lib/esm/components/select/index.js +12 -0
- package/lib/esm/components/select/index.js.map +1 -0
- package/lib/esm/components/select/option.js +50 -0
- package/lib/esm/components/select/option.js.map +1 -0
- package/lib/esm/components/select/remote.js +411 -0
- package/lib/esm/components/select/remote.js.map +1 -0
- package/lib/esm/components/select/search.js +336 -0
- package/lib/esm/components/select/search.js.map +1 -0
- package/lib/esm/components/select/select.js +1535 -0
- package/lib/esm/components/select/select.js.map +1 -0
- package/lib/esm/components/select/tags.js +107 -0
- package/lib/esm/components/select/tags.js.map +1 -0
- package/lib/esm/components/select/templates.js +332 -0
- package/lib/esm/components/select/templates.js.map +1 -0
- package/lib/esm/components/select/types.js +16 -0
- package/lib/esm/components/select/types.js.map +1 -0
- package/lib/esm/components/select/utils.js +598 -0
- package/lib/esm/components/select/utils.js.map +1 -0
- package/lib/esm/components/stepper/index.js +4 -0
- package/lib/esm/components/stepper/index.js.map +1 -1
- package/lib/esm/components/stepper/stepper.js +20 -13
- package/lib/esm/components/stepper/stepper.js.map +1 -1
- package/lib/esm/components/stepper/types.js +4 -0
- package/lib/esm/components/stepper/types.js.map +1 -1
- package/lib/esm/components/sticky/index.js +4 -0
- package/lib/esm/components/sticky/index.js.map +1 -1
- package/lib/esm/components/sticky/sticky.js +60 -38
- package/lib/esm/components/sticky/sticky.js.map +1 -1
- package/lib/esm/components/sticky/types.js +4 -0
- package/lib/esm/components/sticky/types.js.map +1 -1
- package/lib/esm/components/tabs/index.js +4 -0
- package/lib/esm/components/tabs/index.js.map +1 -1
- package/lib/esm/components/tabs/tabs.js +34 -24
- package/lib/esm/components/tabs/tabs.js.map +1 -1
- package/lib/esm/components/tabs/types.js +4 -0
- package/lib/esm/components/tabs/types.js.map +1 -1
- package/lib/esm/components/theme-switch/index.js +6 -0
- package/lib/esm/components/theme-switch/index.js.map +1 -0
- package/lib/esm/components/theme-switch/theme-switch.js +140 -0
- package/lib/esm/components/theme-switch/theme-switch.js.map +1 -0
- package/lib/esm/components/theme-switch/types.js +6 -0
- package/lib/esm/components/theme-switch/types.js.map +1 -0
- package/lib/esm/components/toggle/index.js +4 -0
- package/lib/esm/components/toggle/index.js.map +1 -1
- package/lib/esm/components/toggle/toggle.js +11 -7
- package/lib/esm/components/toggle/toggle.js.map +1 -1
- package/lib/esm/components/toggle/types.js +4 -0
- package/lib/esm/components/toggle/types.js.map +1 -1
- package/lib/esm/components/toggle-password/index.js +4 -0
- package/lib/esm/components/toggle-password/index.js.map +1 -1
- package/lib/esm/components/toggle-password/toggle-password.js +12 -7
- package/lib/esm/components/toggle-password/toggle-password.js.map +1 -1
- package/lib/esm/components/toggle-password/types.js +4 -0
- package/lib/esm/components/toggle-password/types.js.map +1 -1
- package/lib/esm/components/tooltip/index.js +4 -0
- package/lib/esm/components/tooltip/index.js.map +1 -1
- package/lib/esm/components/tooltip/tooltip.js +52 -22
- package/lib/esm/components/tooltip/tooltip.js.map +1 -1
- package/lib/esm/components/tooltip/types.js +4 -0
- package/lib/esm/components/tooltip/types.js.map +1 -1
- package/lib/esm/helpers/data.js +5 -1
- package/lib/esm/helpers/data.js.map +1 -1
- package/lib/esm/helpers/dom.js +34 -29
- package/lib/esm/helpers/dom.js.map +1 -1
- package/lib/esm/helpers/event-handler.js +5 -1
- package/lib/esm/helpers/event-handler.js.map +1 -1
- package/lib/esm/helpers/utils.js +65 -11
- package/lib/esm/helpers/utils.js.map +1 -1
- package/lib/esm/index.js +14 -16
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/types.js +4 -0
- package/lib/esm/types.js.map +1 -1
- package/package.json +16 -8
- package/src/components/accordion/accordion-menu.css +1 -2
- package/src/components/accordion/accordion.css +1 -1
- package/src/components/accordion/accordion.ts +1 -1
- package/src/components/accordion/index.ts +1 -1
- package/src/components/accordion/types.ts +1 -1
- package/src/components/alert/alert.css +1 -1
- package/src/components/avatar/avatar.css +1 -1
- package/src/components/badge/badge.css +1 -1
- package/src/components/breadcrumb/breadcrumb.css +1 -1
- package/src/components/btn/btn.css +1 -1
- package/src/components/card/card.css +1 -1
- package/src/components/checkbox/checkbox.css +1 -1
- package/src/components/collapse/collapse.css +1 -1
- package/src/components/collapse/collapse.ts +1 -1
- package/src/components/collapse/index.ts +1 -1
- package/src/components/collapse/types.ts +1 -1
- package/src/components/component.ts +1 -1
- package/src/components/constants.ts +1 -1
- package/src/components/datatable/datatable-checkbox.ts +1 -1
- package/src/components/datatable/datatable-sort.ts +1 -1
- package/src/components/datatable/datatable.css +1 -1
- package/src/components/datatable/datatable.ts +38 -2
- package/src/components/datatable/index.ts +1 -1
- package/src/components/datatable/types.ts +1 -1
- package/src/components/datepicker/calendar.ts +1 -1
- package/src/components/datepicker/config.ts +1 -1
- package/src/components/datepicker/datepicker.css +1 -1
- package/src/components/datepicker/datepicker.ts +1 -1
- package/src/components/datepicker/dropdown.ts +1 -1
- package/src/components/datepicker/events.ts +1 -1
- package/src/components/datepicker/index.ts +1 -1
- package/src/components/datepicker/keyboard.ts +1 -1
- package/src/components/datepicker/locales.ts +1 -1
- package/src/components/datepicker/templates.ts +1 -1
- package/src/components/datepicker/types.ts +1 -1
- package/src/components/datepicker/utils.ts +1 -1
- package/src/components/dismiss/dismiss.css +1 -1
- package/src/components/dismiss/dismiss.ts +1 -1
- package/src/components/dismiss/index.ts +1 -1
- package/src/components/dismiss/types.ts +1 -1
- package/src/components/drawer/drawer.css +1 -1
- package/src/components/drawer/drawer.ts +1 -1
- package/src/components/drawer/index.ts +1 -1
- package/src/components/drawer/types.ts +1 -1
- package/src/components/dropdown/dropdown-menu.css +1 -1
- package/src/components/dropdown/dropdown.css +1 -1
- package/src/components/dropdown/dropdown.ts +1 -1
- package/src/components/dropdown/index.ts +1 -1
- package/src/components/dropdown/types.ts +1 -1
- package/src/components/form/form.css +1 -1
- package/src/components/image-input/image-input.css +1 -1
- package/src/components/image-input/image-input.ts +1 -1
- package/src/components/image-input/index.ts +1 -1
- package/src/components/image-input/types.ts +1 -1
- package/src/components/input/input-group.css +8 -5
- package/src/components/input/input.css +1 -1
- package/src/components/kbd/kbd.css +1 -1
- package/src/components/label/label.css +1 -1
- package/src/components/link/link.css +1 -1
- package/src/components/modal/index.ts +1 -1
- package/src/components/modal/modal.css +1 -1
- package/src/components/modal/modal.ts +1 -1
- package/src/components/modal/types.ts +1 -1
- package/src/components/pagination/pagination.css +1 -1
- package/src/components/popover/popover.css +1 -1
- package/src/components/progress/progress.css +2 -2
- package/src/components/radio/radio.css +1 -1
- package/src/components/reparent/index.ts +1 -1
- package/src/components/reparent/reparent.ts +1 -1
- package/src/components/reparent/types.ts +1 -1
- package/src/components/scrollable/index.ts +1 -1
- package/src/components/scrollable/scrollable.css +1 -1
- package/src/components/scrollable/scrollable.ts +1 -1
- package/src/components/scrollable/types.ts +1 -1
- package/src/components/scrollspy/index.ts +1 -1
- package/src/components/scrollspy/scrollspy.css +1 -1
- package/src/components/scrollspy/scrollspy.ts +1 -1
- package/src/components/scrollspy/types.ts +1 -1
- package/src/components/scrollto/index.ts +1 -1
- package/src/components/scrollto/scrollto.ts +1 -1
- package/src/components/scrollto/types.ts +1 -1
- package/src/components/select/combobox.ts +1 -1
- package/src/components/select/config.ts +1 -1
- package/src/components/select/dropdown.ts +1 -1
- package/src/components/select/index.ts +1 -1
- package/src/components/select/option.ts +1 -1
- package/src/components/select/remote.ts +1 -1
- package/src/components/select/search.ts +1 -1
- package/src/components/select/select.css +1 -1
- package/src/components/select/select.ts +1 -1
- package/src/components/select/tags.ts +1 -1
- package/src/components/select/templates.ts +1 -1
- package/src/components/select/types.ts +1 -1
- package/src/components/select/utils.ts +1 -1
- package/src/components/select/variants.css +1 -1
- package/src/components/separator/separator.css +1 -1
- package/src/components/skeleton/skeleton.css +1 -1
- package/src/components/stepper/index.ts +1 -1
- package/src/components/stepper/stepper.css +1 -1
- package/src/components/stepper/stepper.ts +1 -1
- package/src/components/stepper/types.ts +1 -1
- package/src/components/sticky/index.ts +1 -1
- package/src/components/sticky/sticky.css +1 -1
- package/src/components/sticky/sticky.ts +1 -1
- package/src/components/sticky/types.ts +1 -1
- package/src/components/switch/switch.css +1 -1
- package/src/components/table/table.css +2 -2
- package/src/components/tabs/index.ts +1 -1
- package/src/components/tabs/tabs.css +1 -1
- package/src/components/tabs/tabs.ts +1 -1
- package/src/components/tabs/types.ts +1 -1
- package/src/components/textarea/textarea.css +1 -1
- package/src/components/theme-switch/index.ts +1 -1
- package/src/components/theme-switch/theme-switch.css +1 -1
- package/src/components/theme-switch/theme-switch.ts +1 -1
- package/src/components/theme-switch/types.ts +1 -1
- package/src/components/toggle/index.ts +1 -1
- package/src/components/toggle/toggle.css +1 -1
- package/src/components/toggle/toggle.ts +1 -1
- package/src/components/toggle/types.ts +1 -1
- package/src/components/toggle-group/toggle-group.css +1 -1
- package/src/components/toggle-password/index.ts +1 -1
- package/src/components/toggle-password/toggle-password.css +1 -1
- package/src/components/toggle-password/toggle-password.ts +1 -1
- package/src/components/toggle-password/types.ts +1 -1
- package/src/components/tooltip/index.ts +1 -1
- package/src/components/tooltip/tooltip.css +1 -1
- package/src/components/tooltip/tooltip.ts +1 -1
- package/src/components/tooltip/types.ts +1 -1
- package/src/helpers/data.ts +1 -1
- package/src/helpers/dom.ts +1 -1
- package/src/helpers/event-handler.ts +1 -1
- package/src/helpers/utils.ts +1 -1
- package/src/index.ts +1 -1
- package/src/types.ts +1 -1
|
@@ -0,0 +1,1535 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
|
|
3
|
+
* Copyright 2025 by Keenthemes Inc
|
|
4
|
+
*/
|
|
5
|
+
var __extends = (this && this.__extends) || (function () {
|
|
6
|
+
var extendStatics = function (d, b) {
|
|
7
|
+
extendStatics = Object.setPrototypeOf ||
|
|
8
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
9
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
10
|
+
return extendStatics(d, b);
|
|
11
|
+
};
|
|
12
|
+
return function (d, b) {
|
|
13
|
+
if (typeof b !== "function" && b !== null)
|
|
14
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
15
|
+
extendStatics(d, b);
|
|
16
|
+
function __() { this.constructor = d; }
|
|
17
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
18
|
+
};
|
|
19
|
+
})();
|
|
20
|
+
var __assign = (this && this.__assign) || function () {
|
|
21
|
+
__assign = Object.assign || function(t) {
|
|
22
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
23
|
+
s = arguments[i];
|
|
24
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
25
|
+
t[p] = s[p];
|
|
26
|
+
}
|
|
27
|
+
return t;
|
|
28
|
+
};
|
|
29
|
+
return __assign.apply(this, arguments);
|
|
30
|
+
};
|
|
31
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
32
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
33
|
+
if (ar || !(i in from)) {
|
|
34
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
35
|
+
ar[i] = from[i];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
39
|
+
};
|
|
40
|
+
import KTData from '../../helpers/data';
|
|
41
|
+
import KTDom from '../../helpers/dom';
|
|
42
|
+
import KTComponent from '../component';
|
|
43
|
+
import { KTSelectState, } from './config';
|
|
44
|
+
import { KTSelectOption } from './option';
|
|
45
|
+
import { KTSelectRemote } from './remote';
|
|
46
|
+
import { KTSelectSearch } from './search';
|
|
47
|
+
import { defaultTemplates } from './templates';
|
|
48
|
+
import { KTSelectCombobox } from './combobox';
|
|
49
|
+
import { KTSelectDropdown } from './dropdown';
|
|
50
|
+
import { handleDropdownKeyNavigation, filterOptions, FocusManager, EventManager, } from './utils';
|
|
51
|
+
import { KTSelectTags } from './tags';
|
|
52
|
+
import { SelectMode } from './types';
|
|
53
|
+
var KTSelect = /** @class */ (function (_super) {
|
|
54
|
+
__extends(KTSelect, _super);
|
|
55
|
+
/**
|
|
56
|
+
* Constructor: Initializes the select component
|
|
57
|
+
*/
|
|
58
|
+
function KTSelect(element, config) {
|
|
59
|
+
var _this = _super.call(this) || this;
|
|
60
|
+
// Core properties
|
|
61
|
+
_this._name = 'select';
|
|
62
|
+
_this._dataOptionPrefix = 'kt-'; // Use 'kt-' prefix to support data-kt-select-option attributes
|
|
63
|
+
// State
|
|
64
|
+
_this._dropdownIsOpen = false;
|
|
65
|
+
_this._comboboxModule = null;
|
|
66
|
+
_this._tagsModule = null;
|
|
67
|
+
_this._dropdownModule = null;
|
|
68
|
+
_this._loadMoreIndicator = null;
|
|
69
|
+
// Search debounce timeout
|
|
70
|
+
_this._searchDebounceTimeout = null;
|
|
71
|
+
// Store original options HTML for restoring after search
|
|
72
|
+
_this._originalOptionsHtml = null;
|
|
73
|
+
if (KTData.has(element, _this._name)) {
|
|
74
|
+
return _this;
|
|
75
|
+
}
|
|
76
|
+
_this._init(element);
|
|
77
|
+
_this._buildConfig(config);
|
|
78
|
+
_this._state = new KTSelectState(_this._config);
|
|
79
|
+
_this._config = _this._state.getConfig();
|
|
80
|
+
element.instance = _this;
|
|
81
|
+
// Initialize event manager
|
|
82
|
+
_this._eventManager = new EventManager();
|
|
83
|
+
// Initialize remote module if remote data is enabled
|
|
84
|
+
if (_this._config.remote) {
|
|
85
|
+
_this._remoteModule = new KTSelectRemote(_this._config, _this._element);
|
|
86
|
+
_this._initializeRemoteData();
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
_this._state
|
|
90
|
+
.setItems()
|
|
91
|
+
.then(function () {
|
|
92
|
+
if (_this._config.debug)
|
|
93
|
+
console.log('Setting up component after remote data is loaded');
|
|
94
|
+
_this._setupComponent();
|
|
95
|
+
})
|
|
96
|
+
.catch(function (error) {
|
|
97
|
+
console.error('Error setting items:', error);
|
|
98
|
+
// Handle the error, e.g., display an error message to the user
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return _this;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Initialize remote data fetching
|
|
105
|
+
*/
|
|
106
|
+
KTSelect.prototype._initializeRemoteData = function () {
|
|
107
|
+
var _this = this;
|
|
108
|
+
if (!this._remoteModule || !this._config.remote)
|
|
109
|
+
return;
|
|
110
|
+
if (this._config.debug)
|
|
111
|
+
console.log('Initializing remote data with URL:', this._config.dataUrl);
|
|
112
|
+
// Show loading state
|
|
113
|
+
this._renderLoadingState();
|
|
114
|
+
// Fetch remote data
|
|
115
|
+
this._remoteModule
|
|
116
|
+
.fetchData()
|
|
117
|
+
.then(function (items) {
|
|
118
|
+
if (_this._config.debug)
|
|
119
|
+
console.log('Remote data fetched:', items);
|
|
120
|
+
// Remove placeholder/loading options before setting new items
|
|
121
|
+
_this._clearExistingOptions();
|
|
122
|
+
// Update state with fetched items
|
|
123
|
+
_this._state
|
|
124
|
+
.setItems(items)
|
|
125
|
+
.then(function () {
|
|
126
|
+
// Generate options from the fetched data
|
|
127
|
+
_this._generateOptionsHtml(_this._element);
|
|
128
|
+
if (_this._config.debug)
|
|
129
|
+
console.log('Generating options HTML from remote data');
|
|
130
|
+
_this._setupComponent();
|
|
131
|
+
// Add pagination "Load More" button if needed
|
|
132
|
+
if (_this._config.pagination && _this._remoteModule.hasMorePages()) {
|
|
133
|
+
_this._addLoadMoreButton();
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
.catch(function (error) {
|
|
137
|
+
console.error('Error setting items:', error);
|
|
138
|
+
_this._renderErrorState(error.message || 'Failed to load data');
|
|
139
|
+
});
|
|
140
|
+
})
|
|
141
|
+
.catch(function (error) {
|
|
142
|
+
console.error('Error fetching remote data:', error);
|
|
143
|
+
_this._renderErrorState(_this._remoteModule.getErrorMessage() || 'Failed to load data');
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Clear existing options from the select element
|
|
148
|
+
*/
|
|
149
|
+
KTSelect.prototype._clearExistingOptions = function () {
|
|
150
|
+
// Keep only the empty/placeholder option and remove the rest
|
|
151
|
+
var options = Array.from(this._element.querySelectorAll('option:not([value=""])'));
|
|
152
|
+
options.forEach(function (option) { return option.remove(); });
|
|
153
|
+
// Ensure we have at least an empty option
|
|
154
|
+
if (this._element.querySelectorAll('option').length === 0) {
|
|
155
|
+
var emptyOption = defaultTemplates.emptyOption(__assign(__assign({}, this._config), { placeholder: this._config.placeholder }));
|
|
156
|
+
this._element.appendChild(emptyOption);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Helper to show a dropdown message (error, loading, noResults)
|
|
161
|
+
*/
|
|
162
|
+
KTSelect.prototype._showDropdownMessage = function (type, message) {
|
|
163
|
+
if (!this._dropdownContentElement)
|
|
164
|
+
return;
|
|
165
|
+
var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
|
|
166
|
+
if (!optionsContainer)
|
|
167
|
+
return;
|
|
168
|
+
switch (type) {
|
|
169
|
+
case 'error':
|
|
170
|
+
optionsContainer.innerHTML = defaultTemplates.error(__assign(__assign({}, this._config), { errorMessage: message }));
|
|
171
|
+
break;
|
|
172
|
+
case 'loading':
|
|
173
|
+
optionsContainer.innerHTML = defaultTemplates.loading(this._config, message || 'Loading...').outerHTML;
|
|
174
|
+
break;
|
|
175
|
+
case 'noResults':
|
|
176
|
+
optionsContainer.innerHTML = '';
|
|
177
|
+
optionsContainer.appendChild(defaultTemplates.noResults(this._config));
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Render loading state in dropdown
|
|
183
|
+
*/
|
|
184
|
+
KTSelect.prototype._renderLoadingState = function () {
|
|
185
|
+
if (this._element.querySelectorAll('option').length <= 1) {
|
|
186
|
+
var existingLoadingOptions = this._element.querySelectorAll('option[disabled][selected][value=""]');
|
|
187
|
+
existingLoadingOptions.forEach(function (option) { return option.remove(); });
|
|
188
|
+
this._showDropdownMessage('loading', 'Loading options...');
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* Render error state
|
|
193
|
+
* @param message Error message
|
|
194
|
+
*/
|
|
195
|
+
KTSelect.prototype._renderErrorState = function (message) {
|
|
196
|
+
// Create error option if the select is empty
|
|
197
|
+
if (this._element.querySelectorAll('option').length <= 1) {
|
|
198
|
+
var loadingOptions = this._element.querySelectorAll('option[disabled]:not([value])');
|
|
199
|
+
loadingOptions.forEach(function (option) { return option.remove(); });
|
|
200
|
+
// Use template function for error option instead of hardcoded element
|
|
201
|
+
var errorOption = defaultTemplates.errorOption(__assign(__assign({}, this._config), { errorMessage: message }));
|
|
202
|
+
this._element.appendChild(errorOption);
|
|
203
|
+
}
|
|
204
|
+
// If dropdown is already created, show error message there
|
|
205
|
+
this._showDropdownMessage('error', message);
|
|
206
|
+
if (!this._wrapperElement) {
|
|
207
|
+
if (this._config.debug)
|
|
208
|
+
console.log('Setting up component after error');
|
|
209
|
+
this._setupComponent();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Add "Load More" button for pagination
|
|
214
|
+
*/
|
|
215
|
+
KTSelect.prototype._addLoadMoreButton = function () {
|
|
216
|
+
if (!this._dropdownContentElement || !this._config.pagination)
|
|
217
|
+
return;
|
|
218
|
+
// Remove existing button if any
|
|
219
|
+
if (this._loadMoreIndicator) {
|
|
220
|
+
this._loadMoreIndicator.remove();
|
|
221
|
+
this._loadMoreIndicator = null;
|
|
222
|
+
}
|
|
223
|
+
// Create load more button using template
|
|
224
|
+
this._loadMoreIndicator = defaultTemplates.loadMore(this._config);
|
|
225
|
+
// Add to dropdown
|
|
226
|
+
var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
|
|
227
|
+
if (optionsContainer) {
|
|
228
|
+
optionsContainer.appendChild(this._loadMoreIndicator);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
this._dropdownContentElement.appendChild(this._loadMoreIndicator);
|
|
232
|
+
}
|
|
233
|
+
// Add event listener
|
|
234
|
+
this._loadMoreIndicator.addEventListener('click', this._handleLoadMore.bind(this));
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* Handle load more button click
|
|
238
|
+
*/
|
|
239
|
+
KTSelect.prototype._handleLoadMore = function () {
|
|
240
|
+
var _this = this;
|
|
241
|
+
if (!this._remoteModule || !this._config.pagination)
|
|
242
|
+
return;
|
|
243
|
+
// Show loading state
|
|
244
|
+
if (this._loadMoreIndicator) {
|
|
245
|
+
this._loadMoreIndicator.textContent = 'Loading...';
|
|
246
|
+
}
|
|
247
|
+
// Fetch next page
|
|
248
|
+
this._remoteModule
|
|
249
|
+
.loadNextPage()
|
|
250
|
+
.then(function (newItems) {
|
|
251
|
+
// Get existing items
|
|
252
|
+
var existingItems = _this._state.getItems();
|
|
253
|
+
// Combine new items with existing items
|
|
254
|
+
_this._state
|
|
255
|
+
.setItems(__spreadArray(__spreadArray([], existingItems, true), newItems, true))
|
|
256
|
+
.then(function () {
|
|
257
|
+
// Update options in the dropdown
|
|
258
|
+
_this._updateOptionsInDropdown(newItems);
|
|
259
|
+
// Check if there are more pages
|
|
260
|
+
if (_this._remoteModule.hasMorePages()) {
|
|
261
|
+
// Reset load more button
|
|
262
|
+
if (_this._loadMoreIndicator) {
|
|
263
|
+
_this._loadMoreIndicator.textContent =
|
|
264
|
+
_this._config.loadMoreText || 'Load more...';
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
// Remove load more button if no more pages
|
|
269
|
+
if (_this._loadMoreIndicator) {
|
|
270
|
+
_this._loadMoreIndicator.remove();
|
|
271
|
+
_this._loadMoreIndicator = null;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
})
|
|
275
|
+
.catch(function (error) {
|
|
276
|
+
console.error('Error updating items:', error);
|
|
277
|
+
// Reset load more button
|
|
278
|
+
if (_this._loadMoreIndicator) {
|
|
279
|
+
_this._loadMoreIndicator.textContent = 'Error loading more items';
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
})
|
|
283
|
+
.catch(function (error) {
|
|
284
|
+
console.error('Error loading more items:', error);
|
|
285
|
+
// Reset load more button
|
|
286
|
+
if (_this._loadMoreIndicator) {
|
|
287
|
+
_this._loadMoreIndicator.textContent = 'Error loading more items';
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
/**
|
|
292
|
+
* Update options in the dropdown
|
|
293
|
+
* @param newItems New items to add to the dropdown
|
|
294
|
+
*/
|
|
295
|
+
KTSelect.prototype._updateOptionsInDropdown = function (newItems) {
|
|
296
|
+
var _this = this;
|
|
297
|
+
if (!this._dropdownContentElement || !newItems.length)
|
|
298
|
+
return;
|
|
299
|
+
var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
|
|
300
|
+
if (!optionsContainer)
|
|
301
|
+
return;
|
|
302
|
+
// Get the load more button
|
|
303
|
+
var loadMoreButton = optionsContainer.querySelector('[data-kt-select-load-more]');
|
|
304
|
+
// Process each new item
|
|
305
|
+
newItems.forEach(function (item) {
|
|
306
|
+
// Create option for the original select
|
|
307
|
+
var selectOption = defaultTemplates.emptyOption(__assign(__assign({}, _this._config), { placeholder: item.title || 'Unnamed option' }));
|
|
308
|
+
selectOption.value = item.id || '';
|
|
309
|
+
// Add description and icon attributes if available and valid
|
|
310
|
+
if (item.description &&
|
|
311
|
+
item.description !== 'null' &&
|
|
312
|
+
item.description !== 'undefined') {
|
|
313
|
+
selectOption.setAttribute('data-kt-select-option-description', item.description);
|
|
314
|
+
}
|
|
315
|
+
if (item.icon && item.icon !== 'null' && item.icon !== 'undefined') {
|
|
316
|
+
selectOption.setAttribute('data-kt-select-option-icon', item.icon);
|
|
317
|
+
}
|
|
318
|
+
// Add the option to the original select element
|
|
319
|
+
_this._element.appendChild(selectOption);
|
|
320
|
+
// Create option element for the dropdown using the KTSelectOption class
|
|
321
|
+
// This ensures consistent option rendering
|
|
322
|
+
var ktOption = new KTSelectOption(selectOption, _this._config);
|
|
323
|
+
var renderedOption = ktOption.render();
|
|
324
|
+
// Add to dropdown container
|
|
325
|
+
if (loadMoreButton) {
|
|
326
|
+
// Insert before the load more button
|
|
327
|
+
optionsContainer.insertBefore(renderedOption, loadMoreButton);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
// Append to the end
|
|
331
|
+
optionsContainer.appendChild(renderedOption);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
// Update options NodeList to include the new options
|
|
335
|
+
this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
|
|
336
|
+
if (this._config.debug)
|
|
337
|
+
console.log("Added ".concat(newItems.length, " more options to dropdown"));
|
|
338
|
+
};
|
|
339
|
+
/**
|
|
340
|
+
* ========================================================================
|
|
341
|
+
* INITIALIZATION METHODS
|
|
342
|
+
* ========================================================================
|
|
343
|
+
*/
|
|
344
|
+
/**
|
|
345
|
+
* Set up the component after everything is initialized
|
|
346
|
+
*/
|
|
347
|
+
KTSelect.prototype._setupComponent = function () {
|
|
348
|
+
// Setup HTML structure
|
|
349
|
+
this._createHtmlStructure();
|
|
350
|
+
this._setupElementReferences();
|
|
351
|
+
this._initZIndex();
|
|
352
|
+
// Initialize options
|
|
353
|
+
this._initializeOptionsHtml();
|
|
354
|
+
this._preSelectOptions(this._element);
|
|
355
|
+
// Apply disabled state if needed
|
|
356
|
+
this._applyInitialDisabledState();
|
|
357
|
+
// Initialize search if enabled
|
|
358
|
+
if (this._config.enableSearch) {
|
|
359
|
+
this._initializeSearchModule();
|
|
360
|
+
}
|
|
361
|
+
// Initialize combobox if enabled
|
|
362
|
+
if (this._config.mode === SelectMode.COMBOBOX) {
|
|
363
|
+
this._comboboxModule = new KTSelectCombobox(this);
|
|
364
|
+
}
|
|
365
|
+
// Initialize tags if enabled
|
|
366
|
+
if (this._config.mode === SelectMode.TAGS) {
|
|
367
|
+
this._tagsModule = new KTSelectTags(this);
|
|
368
|
+
}
|
|
369
|
+
// Initialize focus manager after dropdown element is created
|
|
370
|
+
this._focusManager = new FocusManager(this._dropdownContentElement, '[data-kt-select-option]', this._config);
|
|
371
|
+
// Initialize dropdown module after all elements are created
|
|
372
|
+
this._dropdownModule = new KTSelectDropdown(this._wrapperElement, this._displayElement, this._dropdownContentElement, this._config);
|
|
373
|
+
// Update display and set ARIA attributes
|
|
374
|
+
this._updateDisplayAndAriaAttributes();
|
|
375
|
+
this.updateSelectedOptionDisplay();
|
|
376
|
+
this._setAriaAttributes();
|
|
377
|
+
// Attach event listeners after all modules are initialized
|
|
378
|
+
this._attachEventListeners();
|
|
379
|
+
};
|
|
380
|
+
/**
|
|
381
|
+
* Initialize options HTML from data
|
|
382
|
+
*/
|
|
383
|
+
KTSelect.prototype._initializeOptionsHtml = function () {
|
|
384
|
+
this._generateOptionsHtml(this._element);
|
|
385
|
+
};
|
|
386
|
+
/**
|
|
387
|
+
* Creates the HTML structure for the select component
|
|
388
|
+
*/
|
|
389
|
+
KTSelect.prototype._createHtmlStructure = function () {
|
|
390
|
+
var _this = this;
|
|
391
|
+
var options = Array.from(this._element.querySelectorAll('option'));
|
|
392
|
+
// Create wrapper and display elements
|
|
393
|
+
var wrapperElement = defaultTemplates.main(this._config);
|
|
394
|
+
var displayElement = defaultTemplates.display(this._config);
|
|
395
|
+
// Add the display element to the wrapper
|
|
396
|
+
wrapperElement.appendChild(displayElement);
|
|
397
|
+
// Create an empty dropdown first (without options) using template
|
|
398
|
+
var dropdownElement = defaultTemplates.dropdownContent(__assign(__assign({}, this._config), { zindex: this._config.dropdownZindex }));
|
|
399
|
+
// Add search input if needed
|
|
400
|
+
var isCombobox = this._config.mode === SelectMode.COMBOBOX;
|
|
401
|
+
var hasSearch = this._config.enableSearch && !isCombobox;
|
|
402
|
+
if (hasSearch) {
|
|
403
|
+
var searchElement = defaultTemplates.search(this._config);
|
|
404
|
+
dropdownElement.appendChild(searchElement);
|
|
405
|
+
}
|
|
406
|
+
// Create options container using template
|
|
407
|
+
var optionsContainer = defaultTemplates.optionsContainer(this._config);
|
|
408
|
+
// Add each option directly to the container
|
|
409
|
+
options.forEach(function (optionElement) {
|
|
410
|
+
// Skip empty placeholder options (only if BOTH value AND text are empty)
|
|
411
|
+
// This allows options with empty value but visible text to display in dropdown
|
|
412
|
+
if (optionElement.value === '' &&
|
|
413
|
+
optionElement.textContent.trim() === '') {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
// Create new KTSelectOption instance for each option
|
|
417
|
+
var selectOption = new KTSelectOption(optionElement, _this._config);
|
|
418
|
+
var renderedOption = selectOption.render();
|
|
419
|
+
// Append directly to options container
|
|
420
|
+
optionsContainer.appendChild(renderedOption);
|
|
421
|
+
});
|
|
422
|
+
// Add options container to dropdown
|
|
423
|
+
dropdownElement.appendChild(optionsContainer);
|
|
424
|
+
// Add dropdown to wrapper
|
|
425
|
+
wrapperElement.appendChild(dropdownElement);
|
|
426
|
+
// Insert after the original element
|
|
427
|
+
this._element.after(wrapperElement);
|
|
428
|
+
this._element.style.display = 'none';
|
|
429
|
+
};
|
|
430
|
+
/**
|
|
431
|
+
* Setup all element references after DOM is created
|
|
432
|
+
*/
|
|
433
|
+
KTSelect.prototype._setupElementReferences = function () {
|
|
434
|
+
this._wrapperElement = this._element.nextElementSibling;
|
|
435
|
+
// Get display element
|
|
436
|
+
this._displayElement = this._wrapperElement.querySelector("[data-kt-select-display]");
|
|
437
|
+
// Get dropdown content element - this is critical for dropdown functionality
|
|
438
|
+
this._dropdownContentElement = this._wrapperElement.querySelector("[data-kt-select-dropdown-content]");
|
|
439
|
+
if (!this._dropdownContentElement) {
|
|
440
|
+
console.error('Dropdown content element not found', this._wrapperElement);
|
|
441
|
+
}
|
|
442
|
+
// Get search input element - this is used for the search functionality
|
|
443
|
+
// First check if it's in dropdown, then check if it's in display (for combobox)
|
|
444
|
+
this._searchInputElement = this._dropdownContentElement.querySelector("[data-kt-select-search]");
|
|
445
|
+
// If not found in dropdown, check if it's the display element itself (for combobox)
|
|
446
|
+
if (!this._searchInputElement &&
|
|
447
|
+
this._config.mode === SelectMode.COMBOBOX) {
|
|
448
|
+
this._searchInputElement = this._displayElement;
|
|
449
|
+
}
|
|
450
|
+
if (this._config.debug)
|
|
451
|
+
console.log('Search input found:', this._searchInputElement ? 'Yes' : 'No', 'Mode:', this._config.mode, 'EnableSearch:', this._config.enableSearch);
|
|
452
|
+
this._valueDisplayElement = this._wrapperElement.querySelector("[data-kt-select-value]");
|
|
453
|
+
this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
|
|
454
|
+
};
|
|
455
|
+
/**
|
|
456
|
+
* Attach all event listeners to elements
|
|
457
|
+
*/
|
|
458
|
+
KTSelect.prototype._attachEventListeners = function () {
|
|
459
|
+
// Document level event listeners
|
|
460
|
+
document.addEventListener('click', this._handleDocumentClick.bind(this));
|
|
461
|
+
document.addEventListener('keydown', this._handleEscKey.bind(this));
|
|
462
|
+
// Dropdown option click events
|
|
463
|
+
this._eventManager.addListener(this._dropdownContentElement, 'click', this._handleDropdownOptionClick.bind(this));
|
|
464
|
+
// Only attach click handler to display element
|
|
465
|
+
this._eventManager.addListener(this._displayElement, 'click', this._handleDropdownClick.bind(this));
|
|
466
|
+
// Only attach keyboard navigation to display element if NOT in combobox mode
|
|
467
|
+
// This prevents conflicts with the combobox module's keyboard handler
|
|
468
|
+
if (this._config.mode !== SelectMode.COMBOBOX) {
|
|
469
|
+
if (this._config.debug)
|
|
470
|
+
console.log('Attaching keyboard navigation to display element (non-combobox mode)');
|
|
471
|
+
this._eventManager.addListener(this._displayElement, 'keydown', this._handleDropdownKeyDown.bind(this));
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
/**
|
|
475
|
+
* Initialize search module if search is enabled
|
|
476
|
+
*/
|
|
477
|
+
KTSelect.prototype._initializeSearchModule = function () {
|
|
478
|
+
if (this._config.enableSearch) {
|
|
479
|
+
this._searchModule = new KTSelectSearch(this);
|
|
480
|
+
this._searchModule.init();
|
|
481
|
+
// If remote search is enabled, add event listener for search input
|
|
482
|
+
if (this._config.remote &&
|
|
483
|
+
this._config.searchParam &&
|
|
484
|
+
this._searchInputElement) {
|
|
485
|
+
this._searchInputElement.addEventListener('input', this._handleRemoteSearch.bind(this));
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
/**
|
|
490
|
+
* Apply ARIA attributes and update display
|
|
491
|
+
*/
|
|
492
|
+
KTSelect.prototype._updateDisplayAndAriaAttributes = function () {
|
|
493
|
+
this.updateSelectedOptionDisplay();
|
|
494
|
+
this._setAriaAttributes();
|
|
495
|
+
};
|
|
496
|
+
/**
|
|
497
|
+
* Apply initial disabled state if configured
|
|
498
|
+
*/
|
|
499
|
+
KTSelect.prototype._applyInitialDisabledState = function () {
|
|
500
|
+
if (this._config.disabled) {
|
|
501
|
+
this.getElement().classList.add('disabled');
|
|
502
|
+
this.getElement().setAttribute('disabled', 'disabled');
|
|
503
|
+
this._wrapperElement.classList.add('disabled');
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
/**
|
|
507
|
+
* Generate options HTML from data items
|
|
508
|
+
*/
|
|
509
|
+
KTSelect.prototype._generateOptionsHtml = function (element) {
|
|
510
|
+
var _this = this;
|
|
511
|
+
var items = this._state.getItems() || [];
|
|
512
|
+
if (this._config.debug)
|
|
513
|
+
console.log("Generating options HTML from ".concat(items.length, " items"));
|
|
514
|
+
// Only modify options if we have items to replace them with
|
|
515
|
+
if (items && items.length > 0) {
|
|
516
|
+
// Clear existing options except the first empty one
|
|
517
|
+
var options = element.querySelectorAll('option:not(:first-child)');
|
|
518
|
+
options.forEach(function (option) { return option.remove(); });
|
|
519
|
+
// Generate options from data
|
|
520
|
+
items.forEach(function (item) {
|
|
521
|
+
var optionElement = document.createElement('option');
|
|
522
|
+
// Get value - use item.id directly if available, otherwise try dataValueField
|
|
523
|
+
var value = '';
|
|
524
|
+
if (item.id !== undefined) {
|
|
525
|
+
value = String(item.id);
|
|
526
|
+
}
|
|
527
|
+
else if (_this._config.dataValueField) {
|
|
528
|
+
var extractedValue = _this._getValueByKey(item, _this._config.dataValueField);
|
|
529
|
+
value = extractedValue !== null ? String(extractedValue) : '';
|
|
530
|
+
}
|
|
531
|
+
// Get label - use item.title directly if available, otherwise try dataFieldText
|
|
532
|
+
var label = '';
|
|
533
|
+
if (item.title !== undefined) {
|
|
534
|
+
label = String(item.title);
|
|
535
|
+
}
|
|
536
|
+
else if (_this._config.dataFieldText) {
|
|
537
|
+
var extractedLabel = _this._getValueByKey(item, _this._config.dataFieldText);
|
|
538
|
+
label =
|
|
539
|
+
extractedLabel !== null ? String(extractedLabel) : 'Unnamed option';
|
|
540
|
+
}
|
|
541
|
+
// Get description - skip if null, undefined, or "null" string
|
|
542
|
+
var description = null;
|
|
543
|
+
if (item.description !== undefined &&
|
|
544
|
+
item.description !== null &&
|
|
545
|
+
String(item.description) !== 'null' &&
|
|
546
|
+
String(item.description) !== 'undefined') {
|
|
547
|
+
description = String(item.description);
|
|
548
|
+
}
|
|
549
|
+
else if (_this._config.dataFieldDescription) {
|
|
550
|
+
var extractedDesc = _this._getValueByKey(item, _this._config.dataFieldDescription);
|
|
551
|
+
if (extractedDesc !== null &&
|
|
552
|
+
extractedDesc !== undefined &&
|
|
553
|
+
String(extractedDesc) !== 'null' &&
|
|
554
|
+
String(extractedDesc) !== 'undefined') {
|
|
555
|
+
description = String(extractedDesc);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
// Get icon - skip if null, undefined, or "null" string
|
|
559
|
+
var icon = null;
|
|
560
|
+
if (item.icon !== undefined &&
|
|
561
|
+
item.icon !== null &&
|
|
562
|
+
String(item.icon) !== 'null' &&
|
|
563
|
+
String(item.icon) !== 'undefined') {
|
|
564
|
+
icon = String(item.icon);
|
|
565
|
+
}
|
|
566
|
+
else if (_this._config.dataFieldIcon) {
|
|
567
|
+
var extractedIcon = _this._getValueByKey(item, _this._config.dataFieldIcon);
|
|
568
|
+
if (extractedIcon !== null &&
|
|
569
|
+
extractedIcon !== undefined &&
|
|
570
|
+
String(extractedIcon) !== 'null' &&
|
|
571
|
+
String(extractedIcon) !== 'undefined') {
|
|
572
|
+
icon = String(extractedIcon);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
// Log the extracted values for debugging
|
|
576
|
+
if (_this._config.debug)
|
|
577
|
+
console.log("Option: value=".concat(value, ", label=").concat(label, ", desc=").concat(description ? description : 'none', ", icon=").concat(icon ? icon : 'none'));
|
|
578
|
+
// Set option attributes
|
|
579
|
+
optionElement.value = value;
|
|
580
|
+
optionElement.textContent = label || 'Unnamed option';
|
|
581
|
+
if (description) {
|
|
582
|
+
optionElement.setAttribute('data-kt-select-option-description', description);
|
|
583
|
+
}
|
|
584
|
+
if (icon) {
|
|
585
|
+
optionElement.setAttribute('data-kt-select-option-icon', icon);
|
|
586
|
+
}
|
|
587
|
+
if (item.selected) {
|
|
588
|
+
optionElement.setAttribute('selected', 'selected');
|
|
589
|
+
}
|
|
590
|
+
element.appendChild(optionElement);
|
|
591
|
+
});
|
|
592
|
+
if (this._config.debug)
|
|
593
|
+
console.log("Added ".concat(items.length, " options to select element"));
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
if (this._config.debug)
|
|
597
|
+
console.log('No items to generate options from');
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
/**
|
|
601
|
+
* Extract nested property value from object using dot notation
|
|
602
|
+
*/
|
|
603
|
+
KTSelect.prototype._getValueByKey = function (obj, key) {
|
|
604
|
+
if (!key || !obj)
|
|
605
|
+
return null;
|
|
606
|
+
// Use reduce to walk through the object by splitting the key on dots
|
|
607
|
+
var result = key
|
|
608
|
+
.split('.')
|
|
609
|
+
.reduce(function (o, k) { return (o && o[k] !== undefined ? o[k] : null); }, obj);
|
|
610
|
+
if (this._config.debug)
|
|
611
|
+
console.log("Extracting [".concat(key, "] from object => ").concat(result !== null ? JSON.stringify(result) : 'null'));
|
|
612
|
+
return result;
|
|
613
|
+
};
|
|
614
|
+
/**
|
|
615
|
+
* Pre-select options that have the selected attribute
|
|
616
|
+
*/
|
|
617
|
+
KTSelect.prototype._preSelectOptions = function (element) {
|
|
618
|
+
var _this = this;
|
|
619
|
+
// Handle options with selected attribute
|
|
620
|
+
Array.from(element.querySelectorAll('option[selected]')).forEach(function (option) {
|
|
621
|
+
var value = option.value;
|
|
622
|
+
_this._selectOption(value);
|
|
623
|
+
});
|
|
624
|
+
// Handle data-kt-select-pre-selected attribute for React compatibility
|
|
625
|
+
var preSelectedValues = element.getAttribute('data-kt-select-pre-selected');
|
|
626
|
+
if (preSelectedValues) {
|
|
627
|
+
var values = preSelectedValues.split(',').map(function (v) { return v.trim(); });
|
|
628
|
+
values.forEach(function (value) {
|
|
629
|
+
if (value) {
|
|
630
|
+
_this._selectOption(value);
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
/**
|
|
636
|
+
* Set appropriate z-index for dropdown
|
|
637
|
+
*/
|
|
638
|
+
KTSelect.prototype._initZIndex = function () {
|
|
639
|
+
var zindex = this._config.dropdownZindex;
|
|
640
|
+
if (parseInt(KTDom.getCssProp(this._dropdownContentElement, 'z-index')) >
|
|
641
|
+
zindex) {
|
|
642
|
+
zindex = parseInt(KTDom.getCssProp(this._dropdownContentElement, 'z-index'));
|
|
643
|
+
}
|
|
644
|
+
if (KTDom.getHighestZindex(this._wrapperElement) > zindex) {
|
|
645
|
+
zindex = KTDom.getHighestZindex(this._wrapperElement) + 1;
|
|
646
|
+
}
|
|
647
|
+
this._dropdownContentElement.style.zIndex = String(zindex);
|
|
648
|
+
};
|
|
649
|
+
/**
|
|
650
|
+
* ========================================================================
|
|
651
|
+
* DROPDOWN MANAGEMENT
|
|
652
|
+
* ========================================================================
|
|
653
|
+
*/
|
|
654
|
+
/**
|
|
655
|
+
* Toggle dropdown visibility
|
|
656
|
+
*/
|
|
657
|
+
KTSelect.prototype.toggleDropdown = function () {
|
|
658
|
+
if (this._config.debug)
|
|
659
|
+
console.log('toggleDropdown called');
|
|
660
|
+
if (this._dropdownModule) {
|
|
661
|
+
// Always use the dropdown module's state to determine whether to open or close
|
|
662
|
+
if (this._dropdownModule.isOpen()) {
|
|
663
|
+
if (this._config.debug)
|
|
664
|
+
console.log('Dropdown is open, closing...');
|
|
665
|
+
this.closeDropdown();
|
|
666
|
+
}
|
|
667
|
+
else {
|
|
668
|
+
if (this._config.debug)
|
|
669
|
+
console.log('Dropdown is closed, opening...');
|
|
670
|
+
this.openDropdown();
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
/**
|
|
675
|
+
* Open the dropdown
|
|
676
|
+
*/
|
|
677
|
+
KTSelect.prototype.openDropdown = function () {
|
|
678
|
+
var _this = this;
|
|
679
|
+
if (this._config.debug)
|
|
680
|
+
console.log('openDropdown called, dropdownModule exists:', !!this._dropdownModule);
|
|
681
|
+
if (!this._dropdownModule) {
|
|
682
|
+
if (this._config.debug)
|
|
683
|
+
console.log('Early return from openDropdown - module missing');
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
// Don't open dropdown if the select is disabled
|
|
687
|
+
if (this._config.disabled) {
|
|
688
|
+
if (this._config.debug)
|
|
689
|
+
console.log('Early return from openDropdown - select is disabled');
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
if (this._config.debug)
|
|
693
|
+
console.log('Opening dropdown via dropdownModule...');
|
|
694
|
+
// Set our internal flag to match what we're doing
|
|
695
|
+
this._dropdownIsOpen = true;
|
|
696
|
+
// Open the dropdown via the module
|
|
697
|
+
this._dropdownModule.open();
|
|
698
|
+
// Dispatch custom event
|
|
699
|
+
this._dispatchEvent('show');
|
|
700
|
+
this._fireEvent('show');
|
|
701
|
+
// Focus search input if configured and exists
|
|
702
|
+
if (this._config.enableSearch &&
|
|
703
|
+
this._config.searchAutofocus &&
|
|
704
|
+
this._searchInputElement) {
|
|
705
|
+
setTimeout(function () {
|
|
706
|
+
_this._searchInputElement.focus();
|
|
707
|
+
}, 50);
|
|
708
|
+
}
|
|
709
|
+
// Update ARIA states
|
|
710
|
+
this._setAriaAttributes();
|
|
711
|
+
// Focus the first selected option or first option if nothing selected
|
|
712
|
+
this._focusSelectedOption();
|
|
713
|
+
};
|
|
714
|
+
/**
|
|
715
|
+
* Close the dropdown
|
|
716
|
+
*/
|
|
717
|
+
KTSelect.prototype.closeDropdown = function () {
|
|
718
|
+
if (this._config.debug)
|
|
719
|
+
console.log('closeDropdown called, dropdownModule exists:', !!this._dropdownModule);
|
|
720
|
+
// Only check if dropdown module exists, not dropdownIsOpen flag
|
|
721
|
+
if (!this._dropdownModule) {
|
|
722
|
+
if (this._config.debug)
|
|
723
|
+
console.log('Early return from closeDropdown - module missing');
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
// Always close by delegating to the dropdown module, which is the source of truth
|
|
727
|
+
if (this._config.debug)
|
|
728
|
+
console.log('Closing dropdown via dropdownModule...');
|
|
729
|
+
// Clear search input and highlights if the dropdown is closing
|
|
730
|
+
if (this._searchModule && this._searchInputElement) {
|
|
731
|
+
// Clear search input if configured to do so
|
|
732
|
+
if (this._config.clearSearchOnClose) {
|
|
733
|
+
this._searchInputElement.value = '';
|
|
734
|
+
}
|
|
735
|
+
// Always clear the highlights when dropdown closes
|
|
736
|
+
this._searchModule.clearSearchHighlights();
|
|
737
|
+
}
|
|
738
|
+
// Set our internal flag to match what we're doing
|
|
739
|
+
this._dropdownIsOpen = false;
|
|
740
|
+
// Call the dropdown module's close method
|
|
741
|
+
this._dropdownModule.close();
|
|
742
|
+
// Reset all focus states
|
|
743
|
+
if (this._focusManager) {
|
|
744
|
+
this._focusManager.resetFocus();
|
|
745
|
+
}
|
|
746
|
+
// Dispatch custom events
|
|
747
|
+
this._dispatchEvent('close');
|
|
748
|
+
this._fireEvent('close');
|
|
749
|
+
// Update ARIA states
|
|
750
|
+
this._setAriaAttributes();
|
|
751
|
+
if (this._config.debug)
|
|
752
|
+
console.log('closeDropdown complete');
|
|
753
|
+
};
|
|
754
|
+
/**
|
|
755
|
+
* Update dropdown position
|
|
756
|
+
*/
|
|
757
|
+
KTSelect.prototype.updateDropdownPosition = function () {
|
|
758
|
+
if (this._dropdownModule) {
|
|
759
|
+
this._dropdownModule.updatePosition();
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
/**
|
|
763
|
+
* Focus on the first selected option if any exists in the dropdown
|
|
764
|
+
*/
|
|
765
|
+
KTSelect.prototype._focusSelectedOption = function () {
|
|
766
|
+
// Get selected options
|
|
767
|
+
var selectedOptions = this.getSelectedOptions();
|
|
768
|
+
if (selectedOptions.length === 0)
|
|
769
|
+
return;
|
|
770
|
+
// Get the first selected option element
|
|
771
|
+
var firstSelectedValue = selectedOptions[0];
|
|
772
|
+
// Use the FocusManager to focus on the option
|
|
773
|
+
this._focusManager.focusOptionByValue(firstSelectedValue);
|
|
774
|
+
};
|
|
775
|
+
/**
|
|
776
|
+
* ========================================================================
|
|
777
|
+
* SELECTION MANAGEMENT
|
|
778
|
+
* ========================================================================
|
|
779
|
+
*/
|
|
780
|
+
/**
|
|
781
|
+
* Select an option by value
|
|
782
|
+
*/
|
|
783
|
+
KTSelect.prototype._selectOption = function (value) {
|
|
784
|
+
// Get current selection state
|
|
785
|
+
var isSelected = this._state.isSelected(value);
|
|
786
|
+
// Toggle selection in state
|
|
787
|
+
if (this._config.multiple) {
|
|
788
|
+
// Toggle in multiple mode
|
|
789
|
+
this._state.toggleSelectedOptions(value);
|
|
790
|
+
}
|
|
791
|
+
else {
|
|
792
|
+
// Set as only selection in single mode
|
|
793
|
+
this._state.setSelectedOptions(value);
|
|
794
|
+
}
|
|
795
|
+
// Update the original select element's option selected state
|
|
796
|
+
var optionEl = Array.from(this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
|
|
797
|
+
if (optionEl) {
|
|
798
|
+
if (this._config.multiple) {
|
|
799
|
+
// Toggle the selection for multiple select
|
|
800
|
+
optionEl.selected = !isSelected;
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
// Set as only selection for single select
|
|
804
|
+
Array.from(this._element.querySelectorAll('option')).forEach(function (opt) {
|
|
805
|
+
opt.selected = opt.value === value;
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
// Update the visual display of selected options
|
|
810
|
+
this.updateSelectedOptionDisplay();
|
|
811
|
+
// Update option classes without re-rendering the dropdown content
|
|
812
|
+
this._updateSelectedOptionClass();
|
|
813
|
+
// Dispatch standard and custom change events
|
|
814
|
+
this._dispatchEvent('change', {
|
|
815
|
+
value: value,
|
|
816
|
+
selected: !isSelected,
|
|
817
|
+
selectedOptions: this.getSelectedOptions(),
|
|
818
|
+
});
|
|
819
|
+
this._fireEvent('change', {
|
|
820
|
+
value: value,
|
|
821
|
+
selected: !isSelected,
|
|
822
|
+
selectedOptions: this.getSelectedOptions(),
|
|
823
|
+
});
|
|
824
|
+
};
|
|
825
|
+
/**
|
|
826
|
+
* Update selected option display value
|
|
827
|
+
*/
|
|
828
|
+
KTSelect.prototype.updateSelectedOptionDisplay = function () {
|
|
829
|
+
var _this = this;
|
|
830
|
+
var selectedOptions = this.getSelectedOptions();
|
|
831
|
+
if (this._config.renderSelected) {
|
|
832
|
+
// Use the custom renderSelected function if provided
|
|
833
|
+
this._updateValueDisplay(this._config.renderSelected(selectedOptions));
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
if (selectedOptions.length === 0) {
|
|
837
|
+
if (this._config.mode !== SelectMode.COMBOBOX) {
|
|
838
|
+
this._updateValueDisplay(this._config.placeholder); // Use innerHTML for placeholder
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
else if (this._config.multiple) {
|
|
842
|
+
if (this._config.mode === SelectMode.TAGS) {
|
|
843
|
+
// Use the tags module to render selected options as tags
|
|
844
|
+
if (this._tagsModule) {
|
|
845
|
+
this._tagsModule.updateTagsDisplay(selectedOptions);
|
|
846
|
+
}
|
|
847
|
+
else {
|
|
848
|
+
// Fallback if tags module not initialized for some reason
|
|
849
|
+
this._updateValueDisplay(selectedOptions.join(', '));
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
// Render as comma-separated values
|
|
854
|
+
var displayText = selectedOptions
|
|
855
|
+
.map(function (option) { return _this._getOptionInnerHtml(option) || ''; })
|
|
856
|
+
.join(', ');
|
|
857
|
+
this._updateValueDisplay(displayText);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
else {
|
|
861
|
+
var selectedOption = selectedOptions[0];
|
|
862
|
+
if (selectedOption) {
|
|
863
|
+
var selectedText = this._getOptionInnerHtml(selectedOption);
|
|
864
|
+
this._updateValueDisplay(selectedText);
|
|
865
|
+
// Update combobox input value if in combobox mode
|
|
866
|
+
if (this._config.mode === SelectMode.COMBOBOX &&
|
|
867
|
+
this._comboboxModule) {
|
|
868
|
+
this._comboboxModule.updateSelectedValue(selectedText);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
else {
|
|
872
|
+
this._updateValueDisplay(this._config.placeholder);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
// Update any debug display boxes if they exist
|
|
877
|
+
this._updateDebugDisplays();
|
|
878
|
+
};
|
|
879
|
+
/**
|
|
880
|
+
* Update the value display element
|
|
881
|
+
*/
|
|
882
|
+
KTSelect.prototype._updateValueDisplay = function (value) {
|
|
883
|
+
if (this._config.mode === SelectMode.COMBOBOX) {
|
|
884
|
+
// For combobox, we only update the hidden value element, not the input
|
|
885
|
+
// The combobox module will handle updating the input value
|
|
886
|
+
if (!this._comboboxModule) {
|
|
887
|
+
this._valueDisplayElement.value = value;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
else {
|
|
891
|
+
this._valueDisplayElement.innerHTML = value;
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
/**
|
|
895
|
+
* Update debug displays if present
|
|
896
|
+
*/
|
|
897
|
+
KTSelect.prototype._updateDebugDisplays = function () {
|
|
898
|
+
// Check if we're in a test environment with debug boxes
|
|
899
|
+
var selectId = this.getElement().id;
|
|
900
|
+
if (selectId) {
|
|
901
|
+
var debugElement = document.getElementById("".concat(selectId, "-value"));
|
|
902
|
+
if (debugElement) {
|
|
903
|
+
var selectedOptions = this.getSelectedOptions();
|
|
904
|
+
// Format display based on selection mode
|
|
905
|
+
if (this._config.multiple) {
|
|
906
|
+
// For multiple selection, show comma-separated list
|
|
907
|
+
debugElement.textContent =
|
|
908
|
+
selectedOptions.length > 0 ? selectedOptions.join(', ') : 'None';
|
|
909
|
+
}
|
|
910
|
+
else {
|
|
911
|
+
// For single selection, show just the one value
|
|
912
|
+
debugElement.textContent =
|
|
913
|
+
selectedOptions.length > 0 ? selectedOptions[0] : 'None';
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
/**
|
|
919
|
+
* Get option inner HTML content by option value
|
|
920
|
+
*/
|
|
921
|
+
KTSelect.prototype._getOptionInnerHtml = function (optionValue) {
|
|
922
|
+
var option = Array.from(this._options).find(function (opt) { return opt.dataset.value === optionValue; });
|
|
923
|
+
if (this._config.mode == SelectMode.COMBOBOX) {
|
|
924
|
+
return option.textContent;
|
|
925
|
+
}
|
|
926
|
+
return option.innerHTML; // Get the entire HTML content of the option
|
|
927
|
+
};
|
|
928
|
+
/**
|
|
929
|
+
* Update CSS classes for selected options
|
|
930
|
+
*/
|
|
931
|
+
KTSelect.prototype._updateSelectedOptionClass = function () {
|
|
932
|
+
var allOptions = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
|
|
933
|
+
var selectedValues = this._state.getSelectedOptions();
|
|
934
|
+
var maxReached = typeof this._config.maxSelections === 'number' &&
|
|
935
|
+
selectedValues.length >= this._config.maxSelections;
|
|
936
|
+
if (this._config.debug)
|
|
937
|
+
console.log('Updating selected classes for options, selected values:', selectedValues);
|
|
938
|
+
allOptions.forEach(function (option) {
|
|
939
|
+
var optionValue = option.getAttribute('data-value');
|
|
940
|
+
if (!optionValue)
|
|
941
|
+
return;
|
|
942
|
+
var isSelected = selectedValues.includes(optionValue);
|
|
943
|
+
if (isSelected) {
|
|
944
|
+
option.classList.add('selected');
|
|
945
|
+
option.setAttribute('aria-selected', 'true');
|
|
946
|
+
option.classList.remove('hidden');
|
|
947
|
+
option.classList.remove('disabled');
|
|
948
|
+
option.removeAttribute('aria-disabled');
|
|
949
|
+
}
|
|
950
|
+
else {
|
|
951
|
+
option.classList.remove('selected');
|
|
952
|
+
option.setAttribute('aria-selected', 'false');
|
|
953
|
+
if (maxReached) {
|
|
954
|
+
option.classList.add('disabled');
|
|
955
|
+
option.setAttribute('aria-disabled', 'true');
|
|
956
|
+
}
|
|
957
|
+
else {
|
|
958
|
+
option.classList.remove('disabled');
|
|
959
|
+
option.removeAttribute('aria-disabled');
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
};
|
|
964
|
+
/**
|
|
965
|
+
* Clear all selected options
|
|
966
|
+
*/
|
|
967
|
+
KTSelect.prototype.clearSelection = function () {
|
|
968
|
+
// Clear the current selection
|
|
969
|
+
this._state.setSelectedOptions([]);
|
|
970
|
+
this.updateSelectedOptionDisplay();
|
|
971
|
+
this._updateSelectedOptionClass();
|
|
972
|
+
// For combobox, also clear the input value
|
|
973
|
+
if (this._config.mode === SelectMode.COMBOBOX) {
|
|
974
|
+
if (this._searchInputElement) {
|
|
975
|
+
this._searchInputElement.value = '';
|
|
976
|
+
}
|
|
977
|
+
// If combobox has a clear button, hide it
|
|
978
|
+
if (this._comboboxModule) {
|
|
979
|
+
// The combobox module will handle hiding the clear button
|
|
980
|
+
this._comboboxModule.resetInputValueToSelection();
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
// Dispatch change event
|
|
984
|
+
this._dispatchEvent('change');
|
|
985
|
+
this._fireEvent('change');
|
|
986
|
+
};
|
|
987
|
+
/**
|
|
988
|
+
* Set selected options programmatically
|
|
989
|
+
*/
|
|
990
|
+
KTSelect.prototype.setSelectedOptions = function (options) {
|
|
991
|
+
var values = Array.from(options).map(function (option) { return option.value; });
|
|
992
|
+
this._state.setSelectedOptions(values);
|
|
993
|
+
};
|
|
994
|
+
/**
|
|
995
|
+
* ========================================================================
|
|
996
|
+
* KEYBOARD NAVIGATION
|
|
997
|
+
* ========================================================================
|
|
998
|
+
*/
|
|
999
|
+
/**
|
|
1000
|
+
* Handle dropdown key down events for keyboard navigation
|
|
1001
|
+
* Only used for standard (non-combobox) dropdowns
|
|
1002
|
+
*/
|
|
1003
|
+
KTSelect.prototype._handleDropdownKeyDown = function (event) {
|
|
1004
|
+
// Log event for debugging
|
|
1005
|
+
if (this._config.debug)
|
|
1006
|
+
console.log('Standard dropdown keydown:', event.key);
|
|
1007
|
+
// Use the shared handler
|
|
1008
|
+
handleDropdownKeyNavigation(event, this, {
|
|
1009
|
+
multiple: this._config.multiple,
|
|
1010
|
+
closeOnSelect: this._config.closeOnSelect,
|
|
1011
|
+
});
|
|
1012
|
+
};
|
|
1013
|
+
/**
|
|
1014
|
+
* Focus next option in dropdown
|
|
1015
|
+
*/
|
|
1016
|
+
KTSelect.prototype._focusNextOption = function () {
|
|
1017
|
+
return this._focusManager.focusNext();
|
|
1018
|
+
};
|
|
1019
|
+
/**
|
|
1020
|
+
* Focus previous option in dropdown
|
|
1021
|
+
*/
|
|
1022
|
+
KTSelect.prototype._focusPreviousOption = function () {
|
|
1023
|
+
return this._focusManager.focusPrevious();
|
|
1024
|
+
};
|
|
1025
|
+
/**
|
|
1026
|
+
* Apply hover/focus state to focused option
|
|
1027
|
+
*/
|
|
1028
|
+
KTSelect.prototype._hoverFocusedOption = function (option) {
|
|
1029
|
+
this._focusManager.applyFocus(option);
|
|
1030
|
+
};
|
|
1031
|
+
/**
|
|
1032
|
+
* Scroll option into view when navigating
|
|
1033
|
+
*/
|
|
1034
|
+
KTSelect.prototype._scrollOptionIntoView = function (option) {
|
|
1035
|
+
this._focusManager.scrollIntoView(option);
|
|
1036
|
+
};
|
|
1037
|
+
/**
|
|
1038
|
+
* Select the currently focused option
|
|
1039
|
+
*/
|
|
1040
|
+
KTSelect.prototype.selectFocusedOption = function () {
|
|
1041
|
+
var _a, _b;
|
|
1042
|
+
var focusedOption = this._focusManager.getFocusedOption();
|
|
1043
|
+
if (focusedOption) {
|
|
1044
|
+
var selectedValue = focusedOption.dataset.value;
|
|
1045
|
+
// Extract just the title text, not including description
|
|
1046
|
+
var selectedText = '';
|
|
1047
|
+
var titleElement = focusedOption.querySelector('[data-kt-option-title]');
|
|
1048
|
+
if (titleElement) {
|
|
1049
|
+
// If it has a structured content with title element
|
|
1050
|
+
selectedText = ((_a = titleElement.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
1051
|
+
}
|
|
1052
|
+
else {
|
|
1053
|
+
// Fallback to the whole text content
|
|
1054
|
+
selectedText = ((_b = focusedOption.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || '';
|
|
1055
|
+
}
|
|
1056
|
+
// First trigger the selection to ensure state is updated properly
|
|
1057
|
+
if (selectedValue) {
|
|
1058
|
+
this._selectOption(selectedValue);
|
|
1059
|
+
}
|
|
1060
|
+
// For combobox mode, update input value AFTER selection to ensure consistency
|
|
1061
|
+
if (this._config.mode === SelectMode.COMBOBOX && this._comboboxModule) {
|
|
1062
|
+
this._comboboxModule.updateSelectedValue(selectedText);
|
|
1063
|
+
// Also directly update the input value for immediate visual feedback
|
|
1064
|
+
if (this._searchInputElement) {
|
|
1065
|
+
this._searchInputElement.value = selectedText;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
1070
|
+
/**
|
|
1071
|
+
* ========================================================================
|
|
1072
|
+
* COMBOBOX SPECIFIC METHODS
|
|
1073
|
+
* ========================================================================
|
|
1074
|
+
*/
|
|
1075
|
+
/**
|
|
1076
|
+
* Handle combobox input events
|
|
1077
|
+
*/
|
|
1078
|
+
KTSelect.prototype._handleComboboxInput = function (event) {
|
|
1079
|
+
if (this._comboboxModule) {
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
var inputElement = event.target;
|
|
1083
|
+
var query = inputElement.value.toLowerCase();
|
|
1084
|
+
// If dropdown isn't open, open it when user starts typing
|
|
1085
|
+
if (!this._dropdownIsOpen) {
|
|
1086
|
+
this.openDropdown();
|
|
1087
|
+
}
|
|
1088
|
+
// Filter options based on input
|
|
1089
|
+
this._filterOptionsForCombobox(query);
|
|
1090
|
+
};
|
|
1091
|
+
/**
|
|
1092
|
+
* Filter options for combobox based on input query
|
|
1093
|
+
* Uses the shared filterOptions function
|
|
1094
|
+
*/
|
|
1095
|
+
KTSelect.prototype._filterOptionsForCombobox = function (query) {
|
|
1096
|
+
var options = Array.from(this._dropdownContentElement.querySelectorAll('[data-kt-select-option]'));
|
|
1097
|
+
filterOptions(options, query, this._config, this._dropdownContentElement);
|
|
1098
|
+
};
|
|
1099
|
+
/**
|
|
1100
|
+
* ========================================================================
|
|
1101
|
+
* EVENT HANDLERS
|
|
1102
|
+
* ========================================================================
|
|
1103
|
+
*/
|
|
1104
|
+
/**
|
|
1105
|
+
* Handle display element click
|
|
1106
|
+
*/
|
|
1107
|
+
KTSelect.prototype._handleDropdownClick = function (event) {
|
|
1108
|
+
if (this._config.debug)
|
|
1109
|
+
console.log('Display element clicked', event.target);
|
|
1110
|
+
event.preventDefault();
|
|
1111
|
+
event.stopPropagation(); // Prevent event bubbling
|
|
1112
|
+
this.toggleDropdown();
|
|
1113
|
+
};
|
|
1114
|
+
/**
|
|
1115
|
+
* Handle click within the dropdown
|
|
1116
|
+
*/
|
|
1117
|
+
KTSelect.prototype._handleDropdownOptionClick = function (event) {
|
|
1118
|
+
var optionElement = event.target.closest("[data-kt-select-option]");
|
|
1119
|
+
// If an option is clicked, handle the option click
|
|
1120
|
+
if (optionElement) {
|
|
1121
|
+
this._handleOptionClick(event);
|
|
1122
|
+
}
|
|
1123
|
+
};
|
|
1124
|
+
/**
|
|
1125
|
+
* Handle clicking on an option in the dropdown
|
|
1126
|
+
*/
|
|
1127
|
+
KTSelect.prototype._handleOptionClick = function (event) {
|
|
1128
|
+
if (this._config.debug)
|
|
1129
|
+
console.log('_handleOptionClick called', event.target);
|
|
1130
|
+
event.preventDefault();
|
|
1131
|
+
event.stopPropagation();
|
|
1132
|
+
// Find the clicked option element
|
|
1133
|
+
var clickedOption = event.target.closest("[data-kt-select-option]");
|
|
1134
|
+
if (!clickedOption) {
|
|
1135
|
+
if (this._config.debug)
|
|
1136
|
+
console.log('No clicked option found');
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
// Check if the option is disabled
|
|
1140
|
+
if (clickedOption.getAttribute('aria-disabled') === 'true') {
|
|
1141
|
+
if (this._config.debug)
|
|
1142
|
+
console.log('Option is disabled, ignoring click');
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
// Use dataset.value to get the option value
|
|
1146
|
+
var optionValue = clickedOption.dataset.value;
|
|
1147
|
+
if (optionValue === undefined) {
|
|
1148
|
+
if (this._config.debug)
|
|
1149
|
+
console.log('Option value is undefined');
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
if (this._config.debug)
|
|
1153
|
+
console.log('Option clicked:', optionValue);
|
|
1154
|
+
// Use toggleSelection instead of _selectOption to prevent re-rendering
|
|
1155
|
+
this.toggleSelection(optionValue);
|
|
1156
|
+
};
|
|
1157
|
+
/**
|
|
1158
|
+
* Handle document click for closing dropdown
|
|
1159
|
+
*/
|
|
1160
|
+
KTSelect.prototype._handleDocumentClick = function (event) {
|
|
1161
|
+
var targetElement = event.target;
|
|
1162
|
+
// Check if the click is outside the dropdown and the display element
|
|
1163
|
+
if (!this._wrapperElement.contains(targetElement)) {
|
|
1164
|
+
this.closeDropdown();
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
/**
|
|
1168
|
+
* Handle escape key press
|
|
1169
|
+
*/
|
|
1170
|
+
KTSelect.prototype._handleEscKey = function (event) {
|
|
1171
|
+
if (event.key === 'Escape' && this._dropdownIsOpen) {
|
|
1172
|
+
this.closeDropdown();
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
/**
|
|
1176
|
+
* ========================================================================
|
|
1177
|
+
* ACCESSIBILITY METHODS
|
|
1178
|
+
* ========================================================================
|
|
1179
|
+
*/
|
|
1180
|
+
/**
|
|
1181
|
+
* Set ARIA attributes for accessibility
|
|
1182
|
+
*/
|
|
1183
|
+
KTSelect.prototype._setAriaAttributes = function () {
|
|
1184
|
+
this._displayElement.setAttribute('aria-expanded', this._dropdownIsOpen.toString());
|
|
1185
|
+
};
|
|
1186
|
+
/**
|
|
1187
|
+
* Handle focus events
|
|
1188
|
+
*/
|
|
1189
|
+
KTSelect.prototype._handleFocus = function () {
|
|
1190
|
+
// Implementation pending
|
|
1191
|
+
};
|
|
1192
|
+
/**
|
|
1193
|
+
* Handle blur events
|
|
1194
|
+
*/
|
|
1195
|
+
KTSelect.prototype._handleBlur = function () {
|
|
1196
|
+
// Implementation pending
|
|
1197
|
+
};
|
|
1198
|
+
/**
|
|
1199
|
+
* ========================================================================
|
|
1200
|
+
* PUBLIC API
|
|
1201
|
+
* ========================================================================
|
|
1202
|
+
*/
|
|
1203
|
+
/**
|
|
1204
|
+
* Get the search input element
|
|
1205
|
+
*/
|
|
1206
|
+
KTSelect.prototype.getSearchInput = function () {
|
|
1207
|
+
return this._searchInputElement;
|
|
1208
|
+
};
|
|
1209
|
+
/**
|
|
1210
|
+
* Get selected options
|
|
1211
|
+
*/
|
|
1212
|
+
KTSelect.prototype.getSelectedOptions = function () {
|
|
1213
|
+
return this._state.getSelectedOptions();
|
|
1214
|
+
};
|
|
1215
|
+
/**
|
|
1216
|
+
* Get configuration
|
|
1217
|
+
*/
|
|
1218
|
+
KTSelect.prototype.getConfig = function () {
|
|
1219
|
+
return this._config;
|
|
1220
|
+
};
|
|
1221
|
+
/**
|
|
1222
|
+
* Get option elements
|
|
1223
|
+
*/
|
|
1224
|
+
KTSelect.prototype.getOptionsElement = function () {
|
|
1225
|
+
return this._options;
|
|
1226
|
+
};
|
|
1227
|
+
/**
|
|
1228
|
+
* Get dropdown element
|
|
1229
|
+
*/
|
|
1230
|
+
KTSelect.prototype.getDropdownElement = function () {
|
|
1231
|
+
return this._dropdownContentElement;
|
|
1232
|
+
};
|
|
1233
|
+
/**
|
|
1234
|
+
* Get value display element
|
|
1235
|
+
*/
|
|
1236
|
+
KTSelect.prototype.getValueDisplayElement = function () {
|
|
1237
|
+
return this._valueDisplayElement;
|
|
1238
|
+
};
|
|
1239
|
+
/**
|
|
1240
|
+
* Show all options in the dropdown
|
|
1241
|
+
*/
|
|
1242
|
+
KTSelect.prototype.showAllOptions = function () {
|
|
1243
|
+
// Get all options in the dropdown
|
|
1244
|
+
var options = Array.from(this._wrapperElement.querySelectorAll("[data-kt-select-option]"));
|
|
1245
|
+
// Show all options by removing the hidden class and any inline styles
|
|
1246
|
+
options.forEach(function (option) {
|
|
1247
|
+
// Remove hidden class
|
|
1248
|
+
option.classList.remove('hidden');
|
|
1249
|
+
// Clean up any existing inline styles for backward compatibility
|
|
1250
|
+
if (option.hasAttribute('style')) {
|
|
1251
|
+
var styleAttr = option.getAttribute('style');
|
|
1252
|
+
if (styleAttr.includes('display:')) {
|
|
1253
|
+
// If style only contains display property, remove the entire attribute
|
|
1254
|
+
if (styleAttr.trim() === 'display: none;' ||
|
|
1255
|
+
styleAttr.trim() === 'display: block;') {
|
|
1256
|
+
option.removeAttribute('style');
|
|
1257
|
+
}
|
|
1258
|
+
else {
|
|
1259
|
+
// Otherwise, remove just the display property
|
|
1260
|
+
option.setAttribute('style', styleAttr.replace(/display:\s*[^;]+;?/gi, '').trim());
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1265
|
+
// If search input exists, clear it
|
|
1266
|
+
if (this._searchInputElement && this._config.mode !== SelectMode.COMBOBOX) {
|
|
1267
|
+
this._searchInputElement.value = '';
|
|
1268
|
+
// If we have a search module, clear any search filtering
|
|
1269
|
+
if (this._searchModule) {
|
|
1270
|
+
this._searchModule.clearSearchHighlights();
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
};
|
|
1274
|
+
/**
|
|
1275
|
+
* Toggle multi-select functionality
|
|
1276
|
+
*/
|
|
1277
|
+
KTSelect.prototype.enableMultiSelect = function () {
|
|
1278
|
+
this._state.modifyConfig({ multiple: true });
|
|
1279
|
+
};
|
|
1280
|
+
/**
|
|
1281
|
+
* Disable multi-select functionality
|
|
1282
|
+
*/
|
|
1283
|
+
KTSelect.prototype.disableMultiSelect = function () {
|
|
1284
|
+
this._state.modifyConfig({ multiple: false });
|
|
1285
|
+
};
|
|
1286
|
+
/**
|
|
1287
|
+
* Toggle the selection of an option
|
|
1288
|
+
*/
|
|
1289
|
+
KTSelect.prototype.toggleSelection = function (value) {
|
|
1290
|
+
// Get current selection state
|
|
1291
|
+
var isSelected = this._state.isSelected(value);
|
|
1292
|
+
if (this._config.debug)
|
|
1293
|
+
console.log("toggleSelection called for value: ".concat(value, ", isSelected: ").concat(isSelected, ", multiple: ").concat(this._config.multiple, ", closeOnSelect: ").concat(this._config.closeOnSelect));
|
|
1294
|
+
// If already selected in single select mode, do nothing (can't deselect in single select)
|
|
1295
|
+
if (isSelected && !this._config.multiple) {
|
|
1296
|
+
if (this._config.debug)
|
|
1297
|
+
console.log('Early return from toggleSelection - already selected in single select mode');
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
if (this._config.debug)
|
|
1301
|
+
console.log("Toggling selection for option: ".concat(value, ", currently selected: ").concat(isSelected));
|
|
1302
|
+
// Ensure any search highlights are cleared when selection changes
|
|
1303
|
+
if (this._searchModule) {
|
|
1304
|
+
this._searchModule.clearSearchHighlights();
|
|
1305
|
+
}
|
|
1306
|
+
// Toggle the selection in the state
|
|
1307
|
+
this._state.toggleSelectedOptions(value);
|
|
1308
|
+
// Update the original select element's option selected state
|
|
1309
|
+
var optionEl = Array.from(this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
|
|
1310
|
+
if (optionEl) {
|
|
1311
|
+
// For multiple select, toggle the 'selected' attribute
|
|
1312
|
+
if (this._config.multiple) {
|
|
1313
|
+
optionEl.selected = !isSelected;
|
|
1314
|
+
}
|
|
1315
|
+
else {
|
|
1316
|
+
// For single select, deselect all other options and select this one
|
|
1317
|
+
Array.from(this._element.querySelectorAll('option')).forEach(function (opt) {
|
|
1318
|
+
opt.selected = opt.value === value;
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
// Update the display element value
|
|
1323
|
+
this.updateSelectedOptionDisplay();
|
|
1324
|
+
// Update option classes without re-rendering the dropdown content
|
|
1325
|
+
this._updateSelectedOptionClass();
|
|
1326
|
+
// For single select mode, always close the dropdown after selection
|
|
1327
|
+
// For multiple select mode, only close if closeOnSelect is true
|
|
1328
|
+
if (!this._config.multiple) {
|
|
1329
|
+
if (this._config.debug)
|
|
1330
|
+
console.log('About to call closeDropdown() for single select mode - always close after selection');
|
|
1331
|
+
this.closeDropdown();
|
|
1332
|
+
}
|
|
1333
|
+
else if (this._config.closeOnSelect) {
|
|
1334
|
+
if (this._config.debug)
|
|
1335
|
+
console.log('About to call closeDropdown() for multiple select with closeOnSelect:true');
|
|
1336
|
+
this.closeDropdown();
|
|
1337
|
+
}
|
|
1338
|
+
// Dispatch custom change event with additional data
|
|
1339
|
+
this._dispatchEvent('change', {
|
|
1340
|
+
value: value,
|
|
1341
|
+
selected: !isSelected,
|
|
1342
|
+
selectedOptions: this.getSelectedOptions(),
|
|
1343
|
+
});
|
|
1344
|
+
this._fireEvent('change', {
|
|
1345
|
+
value: value,
|
|
1346
|
+
selected: !isSelected,
|
|
1347
|
+
selectedOptions: this.getSelectedOptions(),
|
|
1348
|
+
});
|
|
1349
|
+
};
|
|
1350
|
+
/**
|
|
1351
|
+
* Clean up all resources when the component is destroyed
|
|
1352
|
+
* This overrides the parent dispose method
|
|
1353
|
+
*/
|
|
1354
|
+
KTSelect.prototype.dispose = function () {
|
|
1355
|
+
// Clean up event listeners
|
|
1356
|
+
this._eventManager.removeAllListeners(null);
|
|
1357
|
+
// Dispose modules
|
|
1358
|
+
if (this._dropdownModule) {
|
|
1359
|
+
this._dropdownModule.dispose();
|
|
1360
|
+
}
|
|
1361
|
+
if (this._comboboxModule) {
|
|
1362
|
+
if (typeof this._comboboxModule.destroy === 'function') {
|
|
1363
|
+
this._comboboxModule.destroy();
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
if (this._tagsModule) {
|
|
1367
|
+
if (typeof this._tagsModule.destroy === 'function') {
|
|
1368
|
+
this._tagsModule.destroy();
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
if (this._searchModule) {
|
|
1372
|
+
if (typeof this._searchModule.destroy === 'function') {
|
|
1373
|
+
this._searchModule.destroy();
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
// Remove DOM elements
|
|
1377
|
+
if (this._wrapperElement && this._wrapperElement.parentNode) {
|
|
1378
|
+
this._wrapperElement.parentNode.removeChild(this._wrapperElement);
|
|
1379
|
+
}
|
|
1380
|
+
// Call parent dispose to clean up data
|
|
1381
|
+
_super.prototype.dispose.call(this);
|
|
1382
|
+
};
|
|
1383
|
+
/**
|
|
1384
|
+
* Create instances of KTSelect for all matching elements
|
|
1385
|
+
*/
|
|
1386
|
+
KTSelect.createInstances = function () {
|
|
1387
|
+
var _this = this;
|
|
1388
|
+
var elements = document.querySelectorAll('[data-kt-select]');
|
|
1389
|
+
elements.forEach(function (element) {
|
|
1390
|
+
if (element.hasAttribute('data-kt-select') &&
|
|
1391
|
+
!element.classList.contains('data-kt-select-initialized')) {
|
|
1392
|
+
var instance = new KTSelect(element);
|
|
1393
|
+
_this._instances.set(element, instance);
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
};
|
|
1397
|
+
/**
|
|
1398
|
+
* Initialize all KTSelect instances
|
|
1399
|
+
*/
|
|
1400
|
+
KTSelect.init = function () {
|
|
1401
|
+
KTSelect.createInstances();
|
|
1402
|
+
};
|
|
1403
|
+
/**
|
|
1404
|
+
* Handle remote search
|
|
1405
|
+
* @param event Input event
|
|
1406
|
+
*/
|
|
1407
|
+
KTSelect.prototype._handleRemoteSearch = function (event) {
|
|
1408
|
+
var _this = this;
|
|
1409
|
+
if (!this._remoteModule ||
|
|
1410
|
+
!this._config.remote ||
|
|
1411
|
+
!this._config.searchParam)
|
|
1412
|
+
return;
|
|
1413
|
+
var query = event.target.value;
|
|
1414
|
+
// Check if the query is long enough
|
|
1415
|
+
if (query.length < (this._config.searchMinLength || 0)) {
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
// Debounce the search
|
|
1419
|
+
if (this._searchDebounceTimeout) {
|
|
1420
|
+
clearTimeout(this._searchDebounceTimeout);
|
|
1421
|
+
}
|
|
1422
|
+
this._searchDebounceTimeout = window.setTimeout(function () {
|
|
1423
|
+
// Show loading state
|
|
1424
|
+
_this._renderSearchLoadingState();
|
|
1425
|
+
// Fetch remote data with search query
|
|
1426
|
+
_this._remoteModule
|
|
1427
|
+
.fetchData(query)
|
|
1428
|
+
.then(function (items) {
|
|
1429
|
+
// Update state with fetched items
|
|
1430
|
+
_this._state
|
|
1431
|
+
.setItems(items)
|
|
1432
|
+
.then(function () {
|
|
1433
|
+
// Update options in the dropdown
|
|
1434
|
+
_this._updateSearchResults(items);
|
|
1435
|
+
// Refresh the search module's option cache if search is enabled
|
|
1436
|
+
if (_this._searchModule && _this._config.enableSearch) {
|
|
1437
|
+
_this._searchModule.refreshOptionCache();
|
|
1438
|
+
}
|
|
1439
|
+
})
|
|
1440
|
+
.catch(function (error) {
|
|
1441
|
+
console.error('Error updating search results:', error);
|
|
1442
|
+
_this._renderSearchErrorState(error.message || 'Failed to load search results');
|
|
1443
|
+
});
|
|
1444
|
+
})
|
|
1445
|
+
.catch(function (error) {
|
|
1446
|
+
console.error('Error fetching search results:', error);
|
|
1447
|
+
_this._renderSearchErrorState(_this._remoteModule.getErrorMessage() ||
|
|
1448
|
+
'Failed to load search results');
|
|
1449
|
+
});
|
|
1450
|
+
}, this._config.searchDebounce || 300);
|
|
1451
|
+
};
|
|
1452
|
+
/**
|
|
1453
|
+
* Render loading state for search
|
|
1454
|
+
*/
|
|
1455
|
+
KTSelect.prototype._renderSearchLoadingState = function () {
|
|
1456
|
+
if (!this._originalOptionsHtml && this._dropdownContentElement) {
|
|
1457
|
+
var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
|
|
1458
|
+
if (optionsContainer) {
|
|
1459
|
+
this._originalOptionsHtml = optionsContainer.innerHTML;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
this._showDropdownMessage('loading', 'Searching...');
|
|
1463
|
+
};
|
|
1464
|
+
/**
|
|
1465
|
+
* Render error state for search
|
|
1466
|
+
* @param message Error message
|
|
1467
|
+
*/
|
|
1468
|
+
KTSelect.prototype._renderSearchErrorState = function (message) {
|
|
1469
|
+
this._showDropdownMessage('error', message);
|
|
1470
|
+
};
|
|
1471
|
+
/**
|
|
1472
|
+
* Update search results in the dropdown
|
|
1473
|
+
* @param items Search result items
|
|
1474
|
+
*/
|
|
1475
|
+
KTSelect.prototype._updateSearchResults = function (items) {
|
|
1476
|
+
var _this = this;
|
|
1477
|
+
if (!this._dropdownContentElement)
|
|
1478
|
+
return;
|
|
1479
|
+
var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
|
|
1480
|
+
if (!optionsContainer)
|
|
1481
|
+
return;
|
|
1482
|
+
// Clear current options
|
|
1483
|
+
optionsContainer.innerHTML = '';
|
|
1484
|
+
if (items.length === 0) {
|
|
1485
|
+
// Show no results message using template for consistency and customization
|
|
1486
|
+
var noResultsElement = defaultTemplates.noResults(this._config);
|
|
1487
|
+
optionsContainer.appendChild(noResultsElement);
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
// Process each item individually to create options
|
|
1491
|
+
items.forEach(function (item) {
|
|
1492
|
+
// Create option for the original select
|
|
1493
|
+
var selectOption = defaultTemplates.emptyOption(__assign(__assign({}, _this._config), { placeholder: item.title }));
|
|
1494
|
+
selectOption.value = item.id;
|
|
1495
|
+
if (item.description) {
|
|
1496
|
+
selectOption.setAttribute('data-kt-select-option-description', item.description);
|
|
1497
|
+
}
|
|
1498
|
+
if (item.icon) {
|
|
1499
|
+
selectOption.setAttribute('data-kt-select-option-icon', item.icon);
|
|
1500
|
+
}
|
|
1501
|
+
// Create option element for the dropdown
|
|
1502
|
+
var ktOption = new KTSelectOption(selectOption, _this._config);
|
|
1503
|
+
var renderedOption = ktOption.render();
|
|
1504
|
+
// Add to dropdown container
|
|
1505
|
+
optionsContainer.appendChild(renderedOption);
|
|
1506
|
+
});
|
|
1507
|
+
// Add pagination "Load More" button if needed
|
|
1508
|
+
if (this._config.pagination && this._remoteModule.hasMorePages()) {
|
|
1509
|
+
this._addLoadMoreButton();
|
|
1510
|
+
}
|
|
1511
|
+
// Update options NodeList
|
|
1512
|
+
this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
|
|
1513
|
+
};
|
|
1514
|
+
/**
|
|
1515
|
+
* Filter options by query
|
|
1516
|
+
*/
|
|
1517
|
+
KTSelect.prototype.filterOptions = function (query) {
|
|
1518
|
+
this._filterOptionsForCombobox(query);
|
|
1519
|
+
};
|
|
1520
|
+
/**
|
|
1521
|
+
* Check if dropdown is open
|
|
1522
|
+
*/
|
|
1523
|
+
KTSelect.prototype.isDropdownOpen = function () {
|
|
1524
|
+
return this._dropdownIsOpen;
|
|
1525
|
+
};
|
|
1526
|
+
/**
|
|
1527
|
+
* ========================================================================
|
|
1528
|
+
* STATIC METHODS
|
|
1529
|
+
* ========================================================================
|
|
1530
|
+
*/
|
|
1531
|
+
KTSelect._instances = new Map();
|
|
1532
|
+
return KTSelect;
|
|
1533
|
+
}(KTComponent));
|
|
1534
|
+
export { KTSelect };
|
|
1535
|
+
//# sourceMappingURL=select.js.map
|