@keenthemes/ktui 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +88 -0
- package/LICENSE.md +21 -0
- package/README.md +124 -0
- package/dist/ktui.js +19201 -0
- package/dist/ktui.min.js +2 -0
- package/dist/ktui.min.js.map +1 -0
- package/lib/cjs/components/accordion/accordion.js +168 -0
- package/lib/cjs/components/accordion/accordion.js.map +1 -0
- package/lib/cjs/components/accordion/index.js +6 -0
- package/lib/cjs/components/accordion/index.js.map +1 -0
- package/lib/cjs/components/accordion/types.js +3 -0
- package/lib/cjs/components/accordion/types.js.map +1 -0
- package/lib/cjs/components/collapse/collapse.js +169 -0
- package/lib/cjs/components/collapse/collapse.js.map +1 -0
- package/lib/cjs/components/collapse/index.js +6 -0
- package/lib/cjs/components/collapse/index.js.map +1 -0
- package/lib/cjs/components/collapse/types.js +3 -0
- package/lib/cjs/components/collapse/types.js.map +1 -0
- package/lib/cjs/components/component.js +135 -0
- package/lib/cjs/components/component.js.map +1 -0
- package/lib/cjs/components/config.js +26 -0
- package/lib/cjs/components/config.js.map +1 -0
- package/lib/cjs/components/config.umd.js +23 -0
- package/lib/cjs/components/config.umd.js.map +1 -0
- package/lib/cjs/components/constants.js +15 -0
- package/lib/cjs/components/constants.js.map +1 -0
- package/lib/cjs/components/datatable/datatable.js +1464 -0
- package/lib/cjs/components/datatable/datatable.js.map +1 -0
- package/lib/cjs/components/datatable/index.js +6 -0
- package/lib/cjs/components/datatable/index.js.map +1 -0
- package/lib/cjs/components/datatable/types.js +3 -0
- package/lib/cjs/components/datatable/types.js.map +1 -0
- package/lib/cjs/components/dismiss/dismiss.js +131 -0
- package/lib/cjs/components/dismiss/dismiss.js.map +1 -0
- package/lib/cjs/components/dismiss/index.js +6 -0
- package/lib/cjs/components/dismiss/index.js.map +1 -0
- package/lib/cjs/components/dismiss/types.js +3 -0
- package/lib/cjs/components/dismiss/types.js.map +1 -0
- package/lib/cjs/components/drawer/drawer.js +347 -0
- package/lib/cjs/components/drawer/drawer.js.map +1 -0
- package/lib/cjs/components/drawer/index.js +6 -0
- package/lib/cjs/components/drawer/index.js.map +1 -0
- package/lib/cjs/components/drawer/types.js +3 -0
- package/lib/cjs/components/drawer/types.js.map +1 -0
- package/lib/cjs/components/dropdown/dropdown.js +403 -0
- package/lib/cjs/components/dropdown/dropdown.js.map +1 -0
- package/lib/cjs/components/dropdown/index.js +6 -0
- package/lib/cjs/components/dropdown/index.js.map +1 -0
- package/lib/cjs/components/dropdown/types.js +3 -0
- package/lib/cjs/components/dropdown/types.js.map +1 -0
- package/lib/cjs/components/image-input/image-input.js +191 -0
- package/lib/cjs/components/image-input/image-input.js.map +1 -0
- package/lib/cjs/components/image-input/index.js +6 -0
- package/lib/cjs/components/image-input/index.js.map +1 -0
- package/lib/cjs/components/image-input/types.js +3 -0
- package/lib/cjs/components/image-input/types.js.map +1 -0
- package/lib/cjs/components/menu/index.js +6 -0
- package/lib/cjs/components/menu/index.js.map +1 -0
- package/lib/cjs/components/menu/menu.js +1021 -0
- package/lib/cjs/components/menu/menu.js.map +1 -0
- package/lib/cjs/components/menu/types.js +3 -0
- package/lib/cjs/components/menu/types.js.map +1 -0
- package/lib/cjs/components/modal/index.js +6 -0
- package/lib/cjs/components/modal/index.js.map +1 -0
- package/lib/cjs/components/modal/modal.js +316 -0
- package/lib/cjs/components/modal/modal.js.map +1 -0
- package/lib/cjs/components/modal/types.js +3 -0
- package/lib/cjs/components/modal/types.js.map +1 -0
- package/lib/cjs/components/reparent/index.js +6 -0
- package/lib/cjs/components/reparent/index.js.map +1 -0
- package/lib/cjs/components/reparent/reparent.js +93 -0
- package/lib/cjs/components/reparent/reparent.js.map +1 -0
- package/lib/cjs/components/reparent/types.js +3 -0
- package/lib/cjs/components/reparent/types.js.map +1 -0
- package/lib/cjs/components/scrollable/index.js +6 -0
- package/lib/cjs/components/scrollable/index.js.map +1 -0
- package/lib/cjs/components/scrollable/scrollable.js +259 -0
- package/lib/cjs/components/scrollable/scrollable.js.map +1 -0
- package/lib/cjs/components/scrollable/types.js +3 -0
- package/lib/cjs/components/scrollable/types.js.map +1 -0
- package/lib/cjs/components/scrollspy/index.js +6 -0
- package/lib/cjs/components/scrollspy/index.js.map +1 -0
- package/lib/cjs/components/scrollspy/scrollspy.js +174 -0
- package/lib/cjs/components/scrollspy/scrollspy.js.map +1 -0
- package/lib/cjs/components/scrollspy/types.js +3 -0
- package/lib/cjs/components/scrollspy/types.js.map +1 -0
- package/lib/cjs/components/scrollto/index.js +6 -0
- package/lib/cjs/components/scrollto/index.js.map +1 -0
- package/lib/cjs/components/scrollto/scrollto.js +103 -0
- package/lib/cjs/components/scrollto/scrollto.js.map +1 -0
- package/lib/cjs/components/scrollto/types.js +3 -0
- package/lib/cjs/components/scrollto/types.js.map +1 -0
- package/lib/cjs/components/stepper/index.js +6 -0
- package/lib/cjs/components/stepper/index.js.map +1 -0
- package/lib/cjs/components/stepper/stepper.js +258 -0
- package/lib/cjs/components/stepper/stepper.js.map +1 -0
- package/lib/cjs/components/stepper/types.js +3 -0
- package/lib/cjs/components/stepper/types.js.map +1 -0
- package/lib/cjs/components/sticky/index.js +6 -0
- package/lib/cjs/components/sticky/index.js.map +1 -0
- package/lib/cjs/components/sticky/sticky.js +297 -0
- package/lib/cjs/components/sticky/sticky.js.map +1 -0
- package/lib/cjs/components/sticky/types.js +3 -0
- package/lib/cjs/components/sticky/types.js.map +1 -0
- package/lib/cjs/components/tabs/index.js +6 -0
- package/lib/cjs/components/tabs/index.js.map +1 -0
- package/lib/cjs/components/tabs/tabs.js +146 -0
- package/lib/cjs/components/tabs/tabs.js.map +1 -0
- package/lib/cjs/components/tabs/types.js +3 -0
- package/lib/cjs/components/tabs/types.js.map +1 -0
- package/lib/cjs/components/theme/index.js +6 -0
- package/lib/cjs/components/theme/index.js.map +1 -0
- package/lib/cjs/components/theme/theme.js +147 -0
- package/lib/cjs/components/theme/theme.js.map +1 -0
- package/lib/cjs/components/theme/types.js +3 -0
- package/lib/cjs/components/theme/types.js.map +1 -0
- package/lib/cjs/components/toggle/index.js +6 -0
- package/lib/cjs/components/toggle/index.js.map +1 -0
- package/lib/cjs/components/toggle/toggle.js +139 -0
- package/lib/cjs/components/toggle/toggle.js.map +1 -0
- package/lib/cjs/components/toggle/types.js +3 -0
- package/lib/cjs/components/toggle/types.js.map +1 -0
- package/lib/cjs/components/toggle-password/index.js +6 -0
- package/lib/cjs/components/toggle-password/index.js.map +1 -0
- package/lib/cjs/components/toggle-password/toggle-password.js +131 -0
- package/lib/cjs/components/toggle-password/toggle-password.js.map +1 -0
- package/lib/cjs/components/toggle-password/types.js +3 -0
- package/lib/cjs/components/toggle-password/types.js.map +1 -0
- package/lib/cjs/components/tooltip/index.js +6 -0
- package/lib/cjs/components/tooltip/index.js.map +1 -0
- package/lib/cjs/components/tooltip/tooltip.js +271 -0
- package/lib/cjs/components/tooltip/tooltip.js.map +1 -0
- package/lib/cjs/components/tooltip/types.js +3 -0
- package/lib/cjs/components/tooltip/types.js.map +1 -0
- package/lib/cjs/helpers/data.js +33 -0
- package/lib/cjs/helpers/data.js.map +1 -0
- package/lib/cjs/helpers/dom.js +297 -0
- package/lib/cjs/helpers/dom.js.map +1 -0
- package/lib/cjs/helpers/event-handler.js +36 -0
- package/lib/cjs/helpers/event-handler.js.map +1 -0
- package/lib/cjs/helpers/utils.js +94 -0
- package/lib/cjs/helpers/utils.js.map +1 -0
- package/lib/cjs/index.js +105 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/types.js +3 -0
- package/lib/cjs/types.js.map +1 -0
- package/lib/esm/components/accordion/accordion.js +165 -0
- package/lib/esm/components/accordion/accordion.js.map +1 -0
- package/lib/esm/components/accordion/index.js +2 -0
- package/lib/esm/components/accordion/index.js.map +1 -0
- package/lib/esm/components/accordion/types.js +2 -0
- package/lib/esm/components/accordion/types.js.map +1 -0
- package/lib/esm/components/collapse/collapse.js +166 -0
- package/lib/esm/components/collapse/collapse.js.map +1 -0
- package/lib/esm/components/collapse/index.js +2 -0
- package/lib/esm/components/collapse/index.js.map +1 -0
- package/lib/esm/components/collapse/types.js +2 -0
- package/lib/esm/components/collapse/types.js.map +1 -0
- package/lib/esm/components/component.js +133 -0
- package/lib/esm/components/component.js.map +1 -0
- package/lib/esm/components/config.js +24 -0
- package/lib/esm/components/config.js.map +1 -0
- package/lib/esm/components/config.umd.js +23 -0
- package/lib/esm/components/config.umd.js.map +1 -0
- package/lib/esm/components/constants.js +12 -0
- package/lib/esm/components/constants.js.map +1 -0
- package/lib/esm/components/datatable/datatable.js +1461 -0
- package/lib/esm/components/datatable/datatable.js.map +1 -0
- package/lib/esm/components/datatable/index.js +2 -0
- package/lib/esm/components/datatable/index.js.map +1 -0
- package/lib/esm/components/datatable/types.js +2 -0
- package/lib/esm/components/datatable/types.js.map +1 -0
- package/lib/esm/components/dismiss/dismiss.js +128 -0
- package/lib/esm/components/dismiss/dismiss.js.map +1 -0
- package/lib/esm/components/dismiss/index.js +2 -0
- package/lib/esm/components/dismiss/index.js.map +1 -0
- package/lib/esm/components/dismiss/types.js +2 -0
- package/lib/esm/components/dismiss/types.js.map +1 -0
- package/lib/esm/components/drawer/drawer.js +344 -0
- package/lib/esm/components/drawer/drawer.js.map +1 -0
- package/lib/esm/components/drawer/index.js +2 -0
- package/lib/esm/components/drawer/index.js.map +1 -0
- package/lib/esm/components/drawer/types.js +2 -0
- package/lib/esm/components/drawer/types.js.map +1 -0
- package/lib/esm/components/dropdown/dropdown.js +400 -0
- package/lib/esm/components/dropdown/dropdown.js.map +1 -0
- package/lib/esm/components/dropdown/index.js +2 -0
- package/lib/esm/components/dropdown/index.js.map +1 -0
- package/lib/esm/components/dropdown/types.js +2 -0
- package/lib/esm/components/dropdown/types.js.map +1 -0
- package/lib/esm/components/image-input/image-input.js +188 -0
- package/lib/esm/components/image-input/image-input.js.map +1 -0
- package/lib/esm/components/image-input/index.js +2 -0
- package/lib/esm/components/image-input/index.js.map +1 -0
- package/lib/esm/components/image-input/types.js +2 -0
- package/lib/esm/components/image-input/types.js.map +1 -0
- package/lib/esm/components/menu/index.js +2 -0
- package/lib/esm/components/menu/index.js.map +1 -0
- package/lib/esm/components/menu/menu.js +1018 -0
- package/lib/esm/components/menu/menu.js.map +1 -0
- package/lib/esm/components/menu/types.js +2 -0
- package/lib/esm/components/menu/types.js.map +1 -0
- package/lib/esm/components/modal/index.js +2 -0
- package/lib/esm/components/modal/index.js.map +1 -0
- package/lib/esm/components/modal/modal.js +313 -0
- package/lib/esm/components/modal/modal.js.map +1 -0
- package/lib/esm/components/modal/types.js +2 -0
- package/lib/esm/components/modal/types.js.map +1 -0
- package/lib/esm/components/reparent/index.js +2 -0
- package/lib/esm/components/reparent/index.js.map +1 -0
- package/lib/esm/components/reparent/reparent.js +90 -0
- package/lib/esm/components/reparent/reparent.js.map +1 -0
- package/lib/esm/components/reparent/types.js +2 -0
- package/lib/esm/components/reparent/types.js.map +1 -0
- package/lib/esm/components/scrollable/index.js +2 -0
- package/lib/esm/components/scrollable/index.js.map +1 -0
- package/lib/esm/components/scrollable/scrollable.js +256 -0
- package/lib/esm/components/scrollable/scrollable.js.map +1 -0
- package/lib/esm/components/scrollable/types.js +2 -0
- package/lib/esm/components/scrollable/types.js.map +1 -0
- package/lib/esm/components/scrollspy/index.js +2 -0
- package/lib/esm/components/scrollspy/index.js.map +1 -0
- package/lib/esm/components/scrollspy/scrollspy.js +171 -0
- package/lib/esm/components/scrollspy/scrollspy.js.map +1 -0
- package/lib/esm/components/scrollspy/types.js +2 -0
- package/lib/esm/components/scrollspy/types.js.map +1 -0
- package/lib/esm/components/scrollto/index.js +2 -0
- package/lib/esm/components/scrollto/index.js.map +1 -0
- package/lib/esm/components/scrollto/scrollto.js +100 -0
- package/lib/esm/components/scrollto/scrollto.js.map +1 -0
- package/lib/esm/components/scrollto/types.js +2 -0
- package/lib/esm/components/scrollto/types.js.map +1 -0
- package/lib/esm/components/stepper/index.js +2 -0
- package/lib/esm/components/stepper/index.js.map +1 -0
- package/lib/esm/components/stepper/stepper.js +255 -0
- package/lib/esm/components/stepper/stepper.js.map +1 -0
- package/lib/esm/components/stepper/types.js +2 -0
- package/lib/esm/components/stepper/types.js.map +1 -0
- package/lib/esm/components/sticky/index.js +2 -0
- package/lib/esm/components/sticky/index.js.map +1 -0
- package/lib/esm/components/sticky/sticky.js +294 -0
- package/lib/esm/components/sticky/sticky.js.map +1 -0
- package/lib/esm/components/sticky/types.js +2 -0
- package/lib/esm/components/sticky/types.js.map +1 -0
- package/lib/esm/components/tabs/index.js +2 -0
- package/lib/esm/components/tabs/index.js.map +1 -0
- package/lib/esm/components/tabs/tabs.js +143 -0
- package/lib/esm/components/tabs/tabs.js.map +1 -0
- package/lib/esm/components/tabs/types.js +2 -0
- package/lib/esm/components/tabs/types.js.map +1 -0
- package/lib/esm/components/theme/index.js +2 -0
- package/lib/esm/components/theme/index.js.map +1 -0
- package/lib/esm/components/theme/theme.js +144 -0
- package/lib/esm/components/theme/theme.js.map +1 -0
- package/lib/esm/components/theme/types.js +2 -0
- package/lib/esm/components/theme/types.js.map +1 -0
- package/lib/esm/components/toggle/index.js +2 -0
- package/lib/esm/components/toggle/index.js.map +1 -0
- package/lib/esm/components/toggle/toggle.js +136 -0
- package/lib/esm/components/toggle/toggle.js.map +1 -0
- package/lib/esm/components/toggle/types.js +2 -0
- package/lib/esm/components/toggle/types.js.map +1 -0
- package/lib/esm/components/toggle-password/index.js +2 -0
- package/lib/esm/components/toggle-password/index.js.map +1 -0
- package/lib/esm/components/toggle-password/toggle-password.js +128 -0
- package/lib/esm/components/toggle-password/toggle-password.js.map +1 -0
- package/lib/esm/components/toggle-password/types.js +2 -0
- package/lib/esm/components/toggle-password/types.js.map +1 -0
- package/lib/esm/components/tooltip/index.js +2 -0
- package/lib/esm/components/tooltip/index.js.map +1 -0
- package/lib/esm/components/tooltip/tooltip.js +268 -0
- package/lib/esm/components/tooltip/tooltip.js.map +1 -0
- package/lib/esm/components/tooltip/types.js +2 -0
- package/lib/esm/components/tooltip/types.js.map +1 -0
- package/lib/esm/helpers/data.js +31 -0
- package/lib/esm/helpers/data.js.map +1 -0
- package/lib/esm/helpers/dom.js +295 -0
- package/lib/esm/helpers/dom.js.map +1 -0
- package/lib/esm/helpers/event-handler.js +34 -0
- package/lib/esm/helpers/event-handler.js.map +1 -0
- package/lib/esm/helpers/utils.js +92 -0
- package/lib/esm/helpers/utils.js.map +1 -0
- package/lib/esm/index.js +79 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/types.js +2 -0
- package/lib/esm/types.js.map +1 -0
- package/package.json +85 -0
- package/prettier.config.js +9 -0
- package/src/components/accordion/accordion-menu.css +51 -0
- package/src/components/accordion/accordion.css +86 -0
- package/src/components/accordion/accordion.ts +221 -0
- package/src/components/accordion/index.ts +7 -0
- package/src/components/accordion/types.ts +16 -0
- package/src/components/alert/alert.css +282 -0
- package/src/components/avatar/avatar.css +46 -0
- package/src/components/badge/badge.css +176 -0
- package/src/components/breadcrumb/breadcrumb.css +38 -0
- package/src/components/btn/btn.css +227 -0
- package/src/components/card/card.css +158 -0
- package/src/components/checkbox/checkbox.css +74 -0
- package/src/components/collapse/collapse.css +14 -0
- package/src/components/collapse/collapse.ts +200 -0
- package/src/components/collapse/index.ts +7 -0
- package/src/components/collapse/types.ts +16 -0
- package/src/components/component.ts +132 -0
- package/src/components/constants.ts +16 -0
- package/src/components/datatable/datatable-checkbox.ts +236 -0
- package/src/components/datatable/datatable-sort.ts +154 -0
- package/src/components/datatable/datatable.css +110 -0
- package/src/components/datatable/datatable.ts +1657 -0
- package/src/components/datatable/index.ts +19 -0
- package/src/components/datatable/types.ts +203 -0
- package/src/components/datepicker/calendar.ts +1397 -0
- package/src/components/datepicker/config.ts +368 -0
- package/src/components/datepicker/datepicker.css +7 -0
- package/src/components/datepicker/datepicker.ts +1287 -0
- package/src/components/datepicker/dropdown.ts +757 -0
- package/src/components/datepicker/events.ts +149 -0
- package/src/components/datepicker/index.ts +10 -0
- package/src/components/datepicker/keyboard.ts +646 -0
- package/src/components/datepicker/locales.ts +80 -0
- package/src/components/datepicker/templates.ts +792 -0
- package/src/components/datepicker/types.ts +154 -0
- package/src/components/datepicker/utils.ts +631 -0
- package/src/components/dismiss/dismiss.css +10 -0
- package/src/components/dismiss/dismiss.ts +152 -0
- package/src/components/dismiss/index.ts +7 -0
- package/src/components/dismiss/types.ts +17 -0
- package/src/components/drawer/drawer.css +97 -0
- package/src/components/drawer/drawer.ts +437 -0
- package/src/components/drawer/index.ts +7 -0
- package/src/components/drawer/types.ts +25 -0
- package/src/components/dropdown/dropdown-menu.css +56 -0
- package/src/components/dropdown/dropdown.css +46 -0
- package/src/components/dropdown/dropdown.ts +549 -0
- package/src/components/dropdown/index.ts +7 -0
- package/src/components/dropdown/types.ts +28 -0
- package/src/components/form/form.css +54 -0
- package/src/components/image-input/image-input.css +56 -0
- package/src/components/image-input/image-input.ts +249 -0
- package/src/components/image-input/index.ts +10 -0
- package/src/components/image-input/types.ts +12 -0
- package/src/components/input/input-group.css +42 -0
- package/src/components/input/input.css +136 -0
- package/src/components/kbd/kbd.css +30 -0
- package/src/components/label/label.css +20 -0
- package/src/components/link/link.css +81 -0
- package/src/components/modal/index.ts +7 -0
- package/src/components/modal/modal.css +73 -0
- package/src/components/modal/modal.ts +382 -0
- package/src/components/modal/types.ts +21 -0
- package/src/components/pagination/pagination.css +26 -0
- package/src/components/popover/popover.css +22 -0
- package/src/components/progress/progress.css +51 -0
- package/src/components/radio/radio.css +51 -0
- package/src/components/reparent/index.ts +7 -0
- package/src/components/reparent/reparent.ts +109 -0
- package/src/components/reparent/types.ts +15 -0
- package/src/components/scrollable/index.ts +10 -0
- package/src/components/scrollable/scrollable.css +29 -0
- package/src/components/scrollable/scrollable.ts +297 -0
- package/src/components/scrollable/types.ts +16 -0
- package/src/components/scrollspy/index.ts +7 -0
- package/src/components/scrollspy/scrollspy.css +13 -0
- package/src/components/scrollspy/scrollspy.ts +224 -0
- package/src/components/scrollspy/types.ts +15 -0
- package/src/components/scrollto/index.ts +7 -0
- package/src/components/scrollto/scrollto.ts +127 -0
- package/src/components/scrollto/types.ts +15 -0
- package/src/components/select/combobox.ts +305 -0
- package/src/components/select/config.ts +324 -0
- package/src/components/select/dropdown.ts +510 -0
- package/src/components/select/index.ts +13 -0
- package/src/components/select/option.ts +43 -0
- package/src/components/select/remote.ts +477 -0
- package/src/components/select/search.ts +430 -0
- package/src/components/select/select.css +105 -0
- package/src/components/select/select.ts +1916 -0
- package/src/components/select/tags.ts +123 -0
- package/src/components/select/templates.ts +531 -0
- package/src/components/select/types.ts +36 -0
- package/src/components/select/utils.ts +747 -0
- package/src/components/select/variants.css +5 -0
- package/src/components/separator/separator.css +14 -0
- package/src/components/skeleton/skeleton.css +10 -0
- package/src/components/stepper/index.ts +7 -0
- package/src/components/stepper/stepper.css +49 -0
- package/src/components/stepper/stepper.ts +308 -0
- package/src/components/stepper/types.ts +13 -0
- package/src/components/sticky/index.ts +7 -0
- package/src/components/sticky/sticky.css +22 -0
- package/src/components/sticky/sticky.ts +381 -0
- package/src/components/sticky/types.ts +23 -0
- package/src/components/switch/switch.css +110 -0
- package/src/components/table/table.css +168 -0
- package/src/components/tabs/index.ts +7 -0
- package/src/components/tabs/tabs.css +40 -0
- package/src/components/tabs/tabs.ts +190 -0
- package/src/components/tabs/types.ts +13 -0
- package/src/components/textarea/textarea.css +35 -0
- package/src/components/theme-switch/index.ts +10 -0
- package/src/components/theme-switch/theme-switch.css +22 -0
- package/src/components/theme-switch/theme-switch.ts +176 -0
- package/src/components/theme-switch/types.ts +15 -0
- package/src/components/toggle/index.ts +7 -0
- package/src/components/toggle/toggle.css +13 -0
- package/src/components/toggle/toggle.ts +173 -0
- package/src/components/toggle/types.ts +18 -0
- package/src/components/toggle-group/toggle-group.css +55 -0
- package/src/components/toggle-password/index.ts +10 -0
- package/src/components/toggle-password/toggle-password.css +13 -0
- package/src/components/toggle-password/toggle-password.ts +159 -0
- package/src/components/toggle-password/types.ts +13 -0
- package/src/components/tooltip/index.ts +7 -0
- package/src/components/tooltip/tooltip.css +18 -0
- package/src/components/tooltip/tooltip.ts +361 -0
- package/src/components/tooltip/types.ts +28 -0
- package/src/helpers/data.ts +46 -0
- package/src/helpers/dom.ts +405 -0
- package/src/helpers/event-handler.ts +61 -0
- package/src/helpers/utils.ts +183 -0
- package/src/index.ts +113 -0
- package/src/types.ts +23 -0
- package/styles.css +48 -0
- package/tsconfig.json +17 -0
- package/webpack.config.js +113 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
|
|
3
|
+
* Copyright 2025 by Keenthemes Inc
|
|
4
|
+
* @version: 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import { KTSelectConfigInterface } from './config';
|
|
7
|
+
import { KTSelect } from './select';
|
|
8
|
+
import { defaultTemplates } from './templates';
|
|
9
|
+
import { EventManager } from './utils';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* KTSelectTags - Handles tags-specific functionality for KTSelect
|
|
13
|
+
*/
|
|
14
|
+
export class KTSelectTags {
|
|
15
|
+
private _select: KTSelect;
|
|
16
|
+
private _config: KTSelectConfigInterface;
|
|
17
|
+
private _valueDisplayElement: HTMLElement;
|
|
18
|
+
private _eventManager: EventManager;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Constructor: Initializes the tags component
|
|
22
|
+
*/
|
|
23
|
+
constructor(select: KTSelect) {
|
|
24
|
+
this._select = select;
|
|
25
|
+
this._config = select.getConfig();
|
|
26
|
+
this._valueDisplayElement = select.getValueDisplayElement();
|
|
27
|
+
this._eventManager = new EventManager();
|
|
28
|
+
|
|
29
|
+
if (this._config.debug) console.log('KTSelectTags initialized');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Update selected tags display
|
|
34
|
+
* Renders selected options as tags in the display element
|
|
35
|
+
*/
|
|
36
|
+
public updateTagsDisplay(selectedOptions: string[]): void {
|
|
37
|
+
// Clear existing content
|
|
38
|
+
this._valueDisplayElement.innerHTML = '';
|
|
39
|
+
|
|
40
|
+
// If no options selected, show placeholder
|
|
41
|
+
if (selectedOptions.length === 0) {
|
|
42
|
+
this._valueDisplayElement.textContent = this._config.placeholder || '';
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Create and append a tag element for each selected option
|
|
47
|
+
selectedOptions.forEach((optionValue) => {
|
|
48
|
+
const tagElement = this._createTagElement(optionValue);
|
|
49
|
+
this._valueDisplayElement.appendChild(tagElement);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Create tag element for a selected option
|
|
55
|
+
*/
|
|
56
|
+
private _createTagElement(optionValue: string): HTMLElement {
|
|
57
|
+
const optionLabel = this._getOptionLabel(optionValue);
|
|
58
|
+
// Create a mock option object to pass to the tag template
|
|
59
|
+
const mockOption = {
|
|
60
|
+
id: optionValue,
|
|
61
|
+
title: optionLabel,
|
|
62
|
+
selected: true,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Use the tag template
|
|
66
|
+
const tag = defaultTemplates.tag(mockOption, this._config);
|
|
67
|
+
|
|
68
|
+
// Add event listener to the close button
|
|
69
|
+
const closeButton = tag.querySelector(
|
|
70
|
+
`[data-kt-select-remove-button]`,
|
|
71
|
+
) as HTMLElement;
|
|
72
|
+
|
|
73
|
+
if (closeButton) {
|
|
74
|
+
this._eventManager.addListener(closeButton, 'click', (event: Event) => {
|
|
75
|
+
event.stopPropagation();
|
|
76
|
+
this._removeTag(optionValue);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return tag;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get the label/text for an option by its value
|
|
85
|
+
*/
|
|
86
|
+
private _getOptionLabel(optionValue: string): string {
|
|
87
|
+
// First look for an option element in the dropdown with matching value
|
|
88
|
+
const optionElements = this._select.getOptionsElement();
|
|
89
|
+
for (const option of Array.from(optionElements)) {
|
|
90
|
+
if ((option as HTMLElement).dataset.value === optionValue) {
|
|
91
|
+
return (option as HTMLElement).textContent?.trim() || optionValue;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// If not found in dropdown, look in original select element
|
|
96
|
+
const originalOptions = this._select
|
|
97
|
+
.getElement()
|
|
98
|
+
.querySelectorAll('option');
|
|
99
|
+
for (const option of Array.from(originalOptions)) {
|
|
100
|
+
if ((option as HTMLOptionElement).value === optionValue) {
|
|
101
|
+
return (option as HTMLOptionElement).textContent?.trim() || optionValue;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// If still not found, return the value itself
|
|
106
|
+
return optionValue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Remove a tag and its selection
|
|
111
|
+
*/
|
|
112
|
+
private _removeTag(optionValue: string): void {
|
|
113
|
+
// Delegate to the select component to handle state changes
|
|
114
|
+
this._select.toggleSelection(optionValue);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Clean up resources used by this module
|
|
119
|
+
*/
|
|
120
|
+
public destroy(): void {
|
|
121
|
+
this._eventManager.removeAllListeners(null);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
|
|
3
|
+
* Copyright 2025 by Keenthemes Inc
|
|
4
|
+
* @version: 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import { KTSelectConfigInterface, KTSelectOption } from './config';
|
|
7
|
+
import { SelectMode } from './types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Default HTML string templates for KTSelect. All UI structure is defined here.
|
|
11
|
+
* Users can override any template by providing a matching key in the config.templates object.
|
|
12
|
+
*/
|
|
13
|
+
const defaultTemplateStrings = {
|
|
14
|
+
dropdownContent: `<div data-kt-select-dropdown-content class="kt-select-dropdown hidden" style="z-index: {{zindex}};">{{content}}</div>`,
|
|
15
|
+
optionsContainer: `<ul role="listbox" aria-label="{{label}}" data-kt-select-options-container style="max-height: {{height}}px; overflow-y: auto;">{{options}}</ul>`,
|
|
16
|
+
emptyOption: `<option value="">{{placeholder}}</option>`,
|
|
17
|
+
errorOption: `<option value="" disabled selected>{{errorMessage}}</option>`, // Template for error <option>
|
|
18
|
+
|
|
19
|
+
loadMore: `<li class="py-2 px-4 text-center text-gray-600 cursor-pointer hover:bg-gray-100" data-kt-select-load-more>{{loadMoreText}}</li>`,
|
|
20
|
+
dropdown: `<div data-kt-select-dropdown-content class="absolute z-10 w-full mt-2 bg-white border border-gray-200 rounded-md shadow-md">
|
|
21
|
+
{{search}}
|
|
22
|
+
<ul role="listbox" aria-label="{{label}}" data-kt-select-options-container style="max-height: {{height}}px; overflow-y: auto;">
|
|
23
|
+
{{options}}
|
|
24
|
+
</ul>
|
|
25
|
+
</div>`,
|
|
26
|
+
error: `<li class="px-3 py-2 text-red-500" role="alert">{{errorMessage}}</li>`,
|
|
27
|
+
|
|
28
|
+
highlight: `<span class="highlight">{{text}}</span>`,
|
|
29
|
+
main: `<div data-kt-select-wrapper class="relative" data-kt-select-mode="{{mode}}"></div>`,
|
|
30
|
+
displayCombobox: `<div class="relative flex items-center w-full">
|
|
31
|
+
<input data-kt-select-search data-kt-select-display data-kt-select-value type="text" class="flex-1 w-full items-center justify-between px-3 py-2 border border-gray-300 rounded-md cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-200 focus:border-blue-400" placeholder="{{placeholder}}" role="searchbox" aria-label="{{label}}" {{disabled}} />
|
|
32
|
+
<button type="button" data-kt-select-clear-button class="absolute right-3 hidden text-gray-400 hover:text-gray-600" aria-label="Clear selection">
|
|
33
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
34
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
35
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
36
|
+
</svg>
|
|
37
|
+
</button>
|
|
38
|
+
</div>`,
|
|
39
|
+
|
|
40
|
+
icon: `<span class="option-icon mr-2"><img src="{{icon}}" class="rounded-full w-6 h-6" /></span>`,
|
|
41
|
+
description: `<div class="option-description text-sm text-gray-500">{{description}}</div>`,
|
|
42
|
+
|
|
43
|
+
display: `<div data-kt-select-display class="flex items-center justify-between px-3 py-2 border border-gray-300 rounded-md cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-200 focus:border-blue-400" tabindex="{{tabindex}}" role="button" aria-haspopup="listbox" aria-expanded="false" aria-label="{{label}}" {{disabled}}>
|
|
44
|
+
<span data-kt-select-value>{{placeholder}}</span>
|
|
45
|
+
<span data-kt-select-arrow class="ml-2">
|
|
46
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
47
|
+
<polyline points="6 9 12 15 18 9"></polyline>
|
|
48
|
+
</svg>
|
|
49
|
+
</span>
|
|
50
|
+
</div>`,
|
|
51
|
+
option: `<li data-kt-select-option data-value="{{value}}" class="px-3 py-2 cursor-pointer hover:bg-gray-100 flex items-center{{selectedClass}}{{disabledClass}}" role="option" {{selected}} {{disabled}}>{{icon}}<div class="option-content"><div class="option-title" data-kt-option-title>{{text}}</div>{{description}}</div></li>`,
|
|
52
|
+
|
|
53
|
+
optionGroup: `<li role="group" aria-label="{{label}}" class="py-1"><div class="px-3 py-1 text-xs font-semibold text-gray-500 uppercase">{{label}}</div><ul>{{optionsHtml}}</ul></li>`,
|
|
54
|
+
search: `<div class="px-3 py-2 border-b border-gray-200"><input type="text" data-kt-select-search placeholder="{{searchPlaceholder}}" class="w-full border-none focus:outline-none text-sm" role="searchbox" aria-label="{{searchPlaceholder}}"/></div>`,
|
|
55
|
+
noResults: `<li class="px-3 py-2 text-gray-500" role="status">{{searchNotFoundText}}</li>`,
|
|
56
|
+
loading: `<li class="px-3 py-2 text-gray-500 italic" role="status" aria-live="polite">{{loadingMessage}}</li>`,
|
|
57
|
+
tag: `<div data-kt-select-tag class="inline-flex items-center bg-blue-50 border border-blue-100 rounded px-2 py-1 text-sm mr-1 mb-1"><span>{{title}}</span><span data-kt-select-remove-button data-value="{{id}}" class="ml-1 text-blue-400 hover:text-blue-600 cursor-pointer" role="button" aria-label="Remove {{safeTitle}}" tabindex="0"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></span></div>`,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Template interface for KTSelect component
|
|
62
|
+
* Each method returns an HTML string or HTMLElement
|
|
63
|
+
*/
|
|
64
|
+
export interface KTSelectTemplateInterface {
|
|
65
|
+
/**
|
|
66
|
+
* Renders the dropdown content container
|
|
67
|
+
*/
|
|
68
|
+
dropdownContent: (
|
|
69
|
+
config: KTSelectConfigInterface & { zindex?: number; content?: string },
|
|
70
|
+
) => HTMLElement;
|
|
71
|
+
/**
|
|
72
|
+
* Renders the options container
|
|
73
|
+
*/
|
|
74
|
+
optionsContainer: (
|
|
75
|
+
config: KTSelectConfigInterface & { options?: string },
|
|
76
|
+
) => HTMLElement;
|
|
77
|
+
/**
|
|
78
|
+
* Renders an empty <option> for native select
|
|
79
|
+
*/
|
|
80
|
+
emptyOption: (
|
|
81
|
+
config: KTSelectConfigInterface & { placeholder?: string },
|
|
82
|
+
) => HTMLOptionElement;
|
|
83
|
+
/**
|
|
84
|
+
* Renders an error <option> for the native select
|
|
85
|
+
*/
|
|
86
|
+
errorOption: (
|
|
87
|
+
config: KTSelectConfigInterface & { errorMessage: string },
|
|
88
|
+
) => HTMLElement;
|
|
89
|
+
/**
|
|
90
|
+
* Renders the load more button for pagination
|
|
91
|
+
*/
|
|
92
|
+
loadMore: (config: KTSelectConfigInterface) => HTMLElement;
|
|
93
|
+
/**
|
|
94
|
+
* Renders an error message in the dropdown
|
|
95
|
+
*/
|
|
96
|
+
error: (config: KTSelectConfigInterface & { errorMessage: string }) => string;
|
|
97
|
+
|
|
98
|
+
highlight: (config: KTSelectConfigInterface, text: string) => HTMLElement;
|
|
99
|
+
|
|
100
|
+
// Main components
|
|
101
|
+
main: (config: KTSelectConfigInterface) => HTMLElement;
|
|
102
|
+
display: (config: KTSelectConfigInterface) => HTMLElement;
|
|
103
|
+
dropdown: (
|
|
104
|
+
config: KTSelectConfigInterface,
|
|
105
|
+
optionsHtml: string,
|
|
106
|
+
) => HTMLElement;
|
|
107
|
+
|
|
108
|
+
// Icon rendering
|
|
109
|
+
icon: (icon: string, config: KTSelectConfigInterface) => HTMLElement;
|
|
110
|
+
description: (
|
|
111
|
+
description: string,
|
|
112
|
+
config: KTSelectConfigInterface,
|
|
113
|
+
) => HTMLElement;
|
|
114
|
+
|
|
115
|
+
// Option rendering
|
|
116
|
+
option: (
|
|
117
|
+
option: KTSelectOption | HTMLOptionElement,
|
|
118
|
+
config: KTSelectConfigInterface,
|
|
119
|
+
) => HTMLElement;
|
|
120
|
+
optionGroup: (
|
|
121
|
+
label: string,
|
|
122
|
+
optionsHtml: string,
|
|
123
|
+
config: KTSelectConfigInterface,
|
|
124
|
+
) => HTMLElement;
|
|
125
|
+
|
|
126
|
+
// Search and empty states
|
|
127
|
+
search: (config: KTSelectConfigInterface) => HTMLElement;
|
|
128
|
+
noResults: (config: KTSelectConfigInterface) => HTMLElement;
|
|
129
|
+
loading: (
|
|
130
|
+
config: KTSelectConfigInterface,
|
|
131
|
+
loadingMessage: string,
|
|
132
|
+
) => HTMLElement;
|
|
133
|
+
|
|
134
|
+
// Multi-select
|
|
135
|
+
tag: (option: KTSelectOption, config: KTSelectConfigInterface) => HTMLElement;
|
|
136
|
+
selectedDisplay: (
|
|
137
|
+
selectedOptions: KTSelectOption[],
|
|
138
|
+
config: KTSelectConfigInterface,
|
|
139
|
+
) => string;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Default templates for KTSelect component
|
|
144
|
+
*/
|
|
145
|
+
function stringToElement(html: string): HTMLElement {
|
|
146
|
+
const template = document.createElement('template');
|
|
147
|
+
template.innerHTML = html.trim();
|
|
148
|
+
return template.content.firstElementChild as HTMLElement;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* User-supplied template overrides. Use setTemplateStrings() to add or update.
|
|
153
|
+
*/
|
|
154
|
+
let userTemplateStrings: Partial<typeof defaultTemplateStrings> = {};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Register or update user template overrides.
|
|
158
|
+
* @param templates Partial template object to merge with defaults.
|
|
159
|
+
*/
|
|
160
|
+
export function setTemplateStrings(
|
|
161
|
+
templates: Partial<typeof defaultTemplateStrings>,
|
|
162
|
+
): void {
|
|
163
|
+
userTemplateStrings = { ...userTemplateStrings, ...templates };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get the complete template set, merging defaults, user overrides, and config templates.
|
|
168
|
+
* @param config Optional config object with a "templates" property.
|
|
169
|
+
*/
|
|
170
|
+
export function getTemplateStrings(
|
|
171
|
+
config?: KTSelectConfigInterface,
|
|
172
|
+
): typeof defaultTemplateStrings {
|
|
173
|
+
const templates =
|
|
174
|
+
config && typeof config === 'object' && 'templates' in config
|
|
175
|
+
? (config as any).templates
|
|
176
|
+
: undefined;
|
|
177
|
+
if (templates) {
|
|
178
|
+
return { ...defaultTemplateStrings, ...userTemplateStrings, ...templates };
|
|
179
|
+
}
|
|
180
|
+
return { ...defaultTemplateStrings, ...userTemplateStrings };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Default templates for KTSelect component
|
|
185
|
+
*/
|
|
186
|
+
export const defaultTemplates: KTSelectTemplateInterface = {
|
|
187
|
+
/**
|
|
188
|
+
* Renders a highlighted text
|
|
189
|
+
*/
|
|
190
|
+
highlight: (config: KTSelectConfigInterface, text: string) => {
|
|
191
|
+
const template = getTemplateStrings(config).highlight;
|
|
192
|
+
const html = template.replace('{{text}}', text);
|
|
193
|
+
return stringToElement(html);
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Renders the dropdown content
|
|
198
|
+
*/
|
|
199
|
+
dropdownContent: (
|
|
200
|
+
config: KTSelectConfigInterface & { zindex?: number; content?: string },
|
|
201
|
+
) => {
|
|
202
|
+
const template = getTemplateStrings(config).dropdownContent;
|
|
203
|
+
const html = template
|
|
204
|
+
.replace('{{zindex}}', config.zindex ? String(config.zindex) : '')
|
|
205
|
+
.replace('{{content}}', config.content || '');
|
|
206
|
+
return stringToElement(html);
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Renders the options container for the dropdown
|
|
211
|
+
*/
|
|
212
|
+
optionsContainer: (
|
|
213
|
+
config: KTSelectConfigInterface & { options?: string },
|
|
214
|
+
) => {
|
|
215
|
+
const template = getTemplateStrings(config).optionsContainer;
|
|
216
|
+
const html = template
|
|
217
|
+
.replace('{{label}}', config.label || 'Options')
|
|
218
|
+
.replace('{{height}}', config.height ? String(config.height) : '250')
|
|
219
|
+
.replace('{{options}}', config.options || '');
|
|
220
|
+
return stringToElement(html);
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Renders an empty option in the dropdown
|
|
225
|
+
*/
|
|
226
|
+
emptyOption: (config: KTSelectConfigInterface & { placeholder?: string }) => {
|
|
227
|
+
const template = getTemplateStrings(config).emptyOption;
|
|
228
|
+
const html = template.replace(
|
|
229
|
+
'{{placeholder}}',
|
|
230
|
+
config.placeholder || 'Select...',
|
|
231
|
+
);
|
|
232
|
+
return stringToElement(html) as HTMLOptionElement;
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Renders an error option in the dropdown
|
|
237
|
+
*/
|
|
238
|
+
errorOption: (config: KTSelectConfigInterface & { errorMessage: string }) => {
|
|
239
|
+
const template = getTemplateStrings(config).errorOption;
|
|
240
|
+
const html = template.replace(
|
|
241
|
+
'{{errorMessage}}',
|
|
242
|
+
config.errorMessage || 'An error occurred',
|
|
243
|
+
);
|
|
244
|
+
return stringToElement(html);
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Renders the load more button for pagination
|
|
249
|
+
*/
|
|
250
|
+
loadMore: (config: KTSelectConfigInterface): HTMLElement => {
|
|
251
|
+
let html = getTemplateStrings(config).loadMore.replace(
|
|
252
|
+
'{{loadMoreText}}',
|
|
253
|
+
config.loadMoreText || 'Load more...',
|
|
254
|
+
);
|
|
255
|
+
return stringToElement(html);
|
|
256
|
+
},
|
|
257
|
+
/**
|
|
258
|
+
* Renders an error message in the dropdown
|
|
259
|
+
*/
|
|
260
|
+
error: (
|
|
261
|
+
config: KTSelectConfigInterface & { errorMessage: string },
|
|
262
|
+
): string => {
|
|
263
|
+
const template = getTemplateStrings(config).error;
|
|
264
|
+
return template.replace(
|
|
265
|
+
'{{errorMessage}}',
|
|
266
|
+
config.errorMessage || 'An error occurred',
|
|
267
|
+
);
|
|
268
|
+
},
|
|
269
|
+
/**
|
|
270
|
+
* Renders the main container for the select component
|
|
271
|
+
*/
|
|
272
|
+
main: (config: KTSelectConfigInterface): HTMLElement => {
|
|
273
|
+
const html = getTemplateStrings(config).main.replace(
|
|
274
|
+
'{{mode}}',
|
|
275
|
+
config.mode || '',
|
|
276
|
+
);
|
|
277
|
+
return stringToElement(html);
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Renders the display element (trigger) for the select
|
|
282
|
+
*/
|
|
283
|
+
display: (config: KTSelectConfigInterface): HTMLElement => {
|
|
284
|
+
const isCombobox = config.mode === SelectMode.COMBOBOX;
|
|
285
|
+
if (isCombobox) {
|
|
286
|
+
let html = getTemplateStrings(config)
|
|
287
|
+
.displayCombobox.replace(
|
|
288
|
+
/{{placeholder}}/g,
|
|
289
|
+
config.placeholder || 'Select...',
|
|
290
|
+
)
|
|
291
|
+
.replace(
|
|
292
|
+
/{{label}}/g,
|
|
293
|
+
config.label || config.placeholder || 'Select...',
|
|
294
|
+
)
|
|
295
|
+
.replace('{{disabled}}', config.disabled ? 'disabled' : '');
|
|
296
|
+
return stringToElement(html);
|
|
297
|
+
}
|
|
298
|
+
let html = getTemplateStrings(config)
|
|
299
|
+
.display.replace('{{tabindex}}', config.disabled ? '-1' : '0')
|
|
300
|
+
.replace('{{label}}', config.label || config.placeholder || 'Select...')
|
|
301
|
+
.replace('{{disabled}}', config.disabled ? 'aria-disabled="true"' : '')
|
|
302
|
+
.replace('{{placeholder}}', config.placeholder || 'Select...');
|
|
303
|
+
return stringToElement(html);
|
|
304
|
+
},
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Renders the dropdown content container
|
|
308
|
+
*/
|
|
309
|
+
dropdown: (
|
|
310
|
+
config: KTSelectConfigInterface,
|
|
311
|
+
optionsHtml: string,
|
|
312
|
+
): HTMLElement => {
|
|
313
|
+
const isCombobox = config.mode === SelectMode.COMBOBOX;
|
|
314
|
+
const hasSearch = config.enableSearch && !isCombobox;
|
|
315
|
+
const template = getTemplateStrings(config).dropdown;
|
|
316
|
+
let searchHtml = '';
|
|
317
|
+
if (hasSearch) {
|
|
318
|
+
const searchElement = defaultTemplates.search(config);
|
|
319
|
+
searchHtml = searchElement.outerHTML;
|
|
320
|
+
}
|
|
321
|
+
const html = template
|
|
322
|
+
.replace('{{search}}', searchHtml)
|
|
323
|
+
.replace('{{options}}', optionsHtml)
|
|
324
|
+
.replace('{{label}}', config.label || 'Options')
|
|
325
|
+
.replace('{{height}}', config.height ? String(config.height) : '250');
|
|
326
|
+
return stringToElement(html);
|
|
327
|
+
},
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Renders a single option
|
|
331
|
+
*/
|
|
332
|
+
option: (
|
|
333
|
+
option: KTSelectOption | HTMLOptionElement,
|
|
334
|
+
config: KTSelectConfigInterface & { templates: KTSelectTemplateInterface },
|
|
335
|
+
): HTMLElement => {
|
|
336
|
+
const isHtmlOption = option instanceof HTMLOptionElement;
|
|
337
|
+
|
|
338
|
+
const value = isHtmlOption ? option.value : (option as KTSelectOption).id;
|
|
339
|
+
const text = isHtmlOption ? option.text : (option as KTSelectOption).title;
|
|
340
|
+
const disabled = isHtmlOption
|
|
341
|
+
? option.disabled
|
|
342
|
+
: (option as any).disabled === true;
|
|
343
|
+
const selected = isHtmlOption
|
|
344
|
+
? option.selected
|
|
345
|
+
: !!(option as KTSelectOption).selected;
|
|
346
|
+
|
|
347
|
+
// Prefer data-kt-select-option (JSON) if present
|
|
348
|
+
let description: string | undefined;
|
|
349
|
+
let icon: string | undefined;
|
|
350
|
+
if (isHtmlOption) {
|
|
351
|
+
const json = option.getAttribute('data-kt-select-option');
|
|
352
|
+
if (json) {
|
|
353
|
+
try {
|
|
354
|
+
const optionData = JSON.parse(json);
|
|
355
|
+
description = optionData?.description;
|
|
356
|
+
icon = optionData?.icon;
|
|
357
|
+
} catch (e) {
|
|
358
|
+
// fallback to legacy attributes if JSON is invalid
|
|
359
|
+
description =
|
|
360
|
+
option.getAttribute('data-kt-select-option-description') ||
|
|
361
|
+
undefined;
|
|
362
|
+
icon = option.getAttribute('data-kt-select-option-icon') || undefined;
|
|
363
|
+
}
|
|
364
|
+
} else {
|
|
365
|
+
description =
|
|
366
|
+
option.getAttribute('data-kt-select-option-description') || undefined;
|
|
367
|
+
icon = option.getAttribute('data-kt-select-option-icon') || undefined;
|
|
368
|
+
}
|
|
369
|
+
} else {
|
|
370
|
+
description = (option as KTSelectOption).description;
|
|
371
|
+
icon = (option as KTSelectOption).icon;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Build option element with proper accessibility attributes
|
|
375
|
+
const selectedClass = selected ? ' selected' : '';
|
|
376
|
+
const disabledClass = disabled ? ' disabled' : '';
|
|
377
|
+
let html = getTemplateStrings(config)
|
|
378
|
+
.option.replace('{{value}}', value)
|
|
379
|
+
.replace('{{selectedClass}}', selectedClass)
|
|
380
|
+
.replace('{{disabledClass}}', disabledClass)
|
|
381
|
+
.replace(
|
|
382
|
+
'{{selected}}',
|
|
383
|
+
selected ? 'aria-selected="true"' : 'aria-selected="false"',
|
|
384
|
+
)
|
|
385
|
+
.replace('{{disabled}}', disabled ? 'aria-disabled="true"' : '')
|
|
386
|
+
.replace(
|
|
387
|
+
/{{icon}}/g,
|
|
388
|
+
icon ? defaultTemplates.icon(icon, config).outerHTML : '',
|
|
389
|
+
)
|
|
390
|
+
.replace('{{text}}', text)
|
|
391
|
+
.replace(
|
|
392
|
+
/{{description}}/g,
|
|
393
|
+
description
|
|
394
|
+
? defaultTemplates.description(description, config).outerHTML
|
|
395
|
+
: '',
|
|
396
|
+
);
|
|
397
|
+
return stringToElement(html);
|
|
398
|
+
},
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Renders an icon
|
|
402
|
+
*/
|
|
403
|
+
icon: (icon: string, config: KTSelectConfigInterface): HTMLElement => {
|
|
404
|
+
const html = getTemplateStrings(config).icon.replace('{{icon}}', icon);
|
|
405
|
+
return stringToElement(html);
|
|
406
|
+
},
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Renders a description
|
|
410
|
+
*/
|
|
411
|
+
description: (
|
|
412
|
+
description: string,
|
|
413
|
+
config: KTSelectConfigInterface,
|
|
414
|
+
): HTMLElement => {
|
|
415
|
+
const html = getTemplateStrings(config).description.replace(
|
|
416
|
+
'{{description}}',
|
|
417
|
+
description,
|
|
418
|
+
);
|
|
419
|
+
return stringToElement(html);
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Renders an option group with header
|
|
424
|
+
*/
|
|
425
|
+
optionGroup: (
|
|
426
|
+
label: string,
|
|
427
|
+
optionsHtml: string,
|
|
428
|
+
config: KTSelectConfigInterface,
|
|
429
|
+
): HTMLElement => {
|
|
430
|
+
let html = getTemplateStrings(config)
|
|
431
|
+
.optionGroup.replace(/{{label}}/g, label)
|
|
432
|
+
.replace('{{optionsHtml}}', optionsHtml);
|
|
433
|
+
return stringToElement(html);
|
|
434
|
+
},
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Renders the search input
|
|
438
|
+
*/
|
|
439
|
+
search: (config: KTSelectConfigInterface): HTMLElement => {
|
|
440
|
+
let html = getTemplateStrings(config).search.replace(
|
|
441
|
+
'{{searchPlaceholder}}',
|
|
442
|
+
config.searchPlaceholder || 'Search...',
|
|
443
|
+
);
|
|
444
|
+
return stringToElement(html);
|
|
445
|
+
},
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Renders the no results message
|
|
449
|
+
*/
|
|
450
|
+
noResults: (config: KTSelectConfigInterface): HTMLElement => {
|
|
451
|
+
let html = getTemplateStrings(config).noResults.replace(
|
|
452
|
+
'{{searchNotFoundText}}',
|
|
453
|
+
config.searchNotFoundText || 'No results found',
|
|
454
|
+
);
|
|
455
|
+
return stringToElement(html);
|
|
456
|
+
},
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Renders the loading state
|
|
460
|
+
*/
|
|
461
|
+
loading: (
|
|
462
|
+
config: KTSelectConfigInterface,
|
|
463
|
+
loadingMessage: string,
|
|
464
|
+
): HTMLElement => {
|
|
465
|
+
let html = getTemplateStrings(config).loading.replace(
|
|
466
|
+
'{{loadingMessage}}',
|
|
467
|
+
loadingMessage || 'Loading options...',
|
|
468
|
+
);
|
|
469
|
+
return stringToElement(html);
|
|
470
|
+
},
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Renders a tag for multi-select
|
|
474
|
+
*/
|
|
475
|
+
tag: (
|
|
476
|
+
option: KTSelectOption,
|
|
477
|
+
config: KTSelectConfigInterface,
|
|
478
|
+
): HTMLElement => {
|
|
479
|
+
// Escape HTML characters for aria-label to prevent HTML injection
|
|
480
|
+
const escapeHTML = (str: string) => {
|
|
481
|
+
return str.replace(/[&<>"']/g, (match) => {
|
|
482
|
+
const escapeMap: Record<string, string> = {
|
|
483
|
+
'&': '&',
|
|
484
|
+
'<': '<',
|
|
485
|
+
'>': '>',
|
|
486
|
+
'"': '"',
|
|
487
|
+
"'": ''',
|
|
488
|
+
};
|
|
489
|
+
return escapeMap[match];
|
|
490
|
+
});
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
// Ensure we have plain text for the aria-label
|
|
494
|
+
const safeTitle = escapeHTML(option.title);
|
|
495
|
+
let html = getTemplateStrings(config)
|
|
496
|
+
.tag.replace('{{title}}', option.title)
|
|
497
|
+
.replace('{{id}}', option.id)
|
|
498
|
+
.replace('{{safeTitle}}', safeTitle);
|
|
499
|
+
return stringToElement(html);
|
|
500
|
+
},
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Formats the display of selected values
|
|
504
|
+
*/
|
|
505
|
+
selectedDisplay: (
|
|
506
|
+
selectedOptions: KTSelectOption[],
|
|
507
|
+
config: KTSelectConfigInterface,
|
|
508
|
+
): string => {
|
|
509
|
+
if (!selectedOptions || selectedOptions.length === 0) {
|
|
510
|
+
return config.placeholder || 'Select...';
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (config.multiple) {
|
|
514
|
+
if (
|
|
515
|
+
config.renderSelected &&
|
|
516
|
+
typeof config.renderSelected === 'function'
|
|
517
|
+
) {
|
|
518
|
+
return config.renderSelected(selectedOptions);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (config.showSelectedCount) {
|
|
522
|
+
const count = selectedOptions.length;
|
|
523
|
+
return `${count} ${count === 1 ? 'item' : 'items'} selected`;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return selectedOptions.map((option) => option.title).join(', ');
|
|
527
|
+
} else {
|
|
528
|
+
return selectedOptions[0].title;
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
|
|
3
|
+
* Copyright 2025 by Keenthemes Inc
|
|
4
|
+
* @version: 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Common type interfaces for the KTSelect component
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Select mode options
|
|
12
|
+
*/
|
|
13
|
+
export enum SelectMode {
|
|
14
|
+
TAGS = 'tags',
|
|
15
|
+
COMBOBOX = 'combobox',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface KTSelectOption {
|
|
19
|
+
id: string;
|
|
20
|
+
title: string;
|
|
21
|
+
selected?: boolean;
|
|
22
|
+
description?: string;
|
|
23
|
+
icon?: string;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface KTSelectOptionData {
|
|
28
|
+
[key: string]: any;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface KTSelectState {
|
|
32
|
+
getSelectedOptions(): string[];
|
|
33
|
+
setSelectedOptions(value: string | string[]): void;
|
|
34
|
+
toggleSelectedOptions(value: string): void;
|
|
35
|
+
isSelected(value: string): boolean;
|
|
36
|
+
}
|