@keenthemes/ktui 1.2.1 → 1.2.2
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 +2858 -1515
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +23 -0
- package/lib/cjs/components/carousel/carousel.d.ts +102 -0
- package/lib/cjs/components/carousel/carousel.d.ts.map +1 -0
- package/lib/cjs/components/carousel/carousel.js +769 -0
- package/lib/cjs/components/carousel/carousel.js.map +1 -0
- package/lib/cjs/components/carousel/index.d.ts +7 -0
- package/lib/cjs/components/carousel/index.d.ts.map +1 -0
- package/lib/cjs/components/carousel/index.js +10 -0
- package/lib/cjs/components/carousel/index.js.map +1 -0
- package/lib/cjs/components/carousel/types.d.ts +36 -0
- package/lib/cjs/components/carousel/types.d.ts.map +1 -0
- package/lib/cjs/components/carousel/types.js +7 -0
- package/lib/cjs/components/carousel/types.js.map +1 -0
- package/lib/cjs/components/component.d.ts +3 -3
- package/lib/cjs/components/component.d.ts.map +1 -1
- package/lib/cjs/components/component.js +9 -1
- package/lib/cjs/components/component.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-checkbox.d.ts +1 -1
- package/lib/cjs/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-checkbox.js +1 -1
- package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-sort.d.ts +1 -1
- package/lib/cjs/components/datatable/datatable-sort.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-sort.js.map +1 -1
- package/lib/cjs/components/datatable/datatable.d.ts +2 -0
- package/lib/cjs/components/datatable/datatable.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +29 -16
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/datatable/types.d.ts +2 -1
- package/lib/cjs/components/datatable/types.d.ts.map +1 -1
- package/lib/cjs/components/drawer/drawer.d.ts.map +1 -1
- package/lib/cjs/components/drawer/drawer.js +3 -16
- package/lib/cjs/components/drawer/drawer.js.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.d.ts +1 -1
- package/lib/cjs/components/dropdown/dropdown.d.ts.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.js +2 -3
- package/lib/cjs/components/dropdown/dropdown.js.map +1 -1
- package/lib/cjs/components/pin-input/index.d.ts +3 -0
- package/lib/cjs/components/pin-input/index.d.ts.map +1 -0
- package/lib/cjs/components/pin-input/index.js +6 -0
- package/lib/cjs/components/pin-input/index.js.map +1 -0
- package/lib/cjs/components/pin-input/pin-input.d.ts +56 -0
- package/lib/cjs/components/pin-input/pin-input.d.ts.map +1 -0
- package/lib/cjs/components/pin-input/pin-input.js +455 -0
- package/lib/cjs/components/pin-input/pin-input.js.map +1 -0
- package/lib/cjs/components/pin-input/types.d.ts +41 -0
- package/lib/cjs/components/pin-input/types.d.ts.map +1 -0
- package/lib/cjs/components/pin-input/types.js +6 -0
- package/lib/cjs/components/pin-input/types.js.map +1 -0
- package/lib/cjs/components/rating/rating.d.ts.map +1 -1
- package/lib/cjs/components/rating/rating.js.map +1 -1
- package/lib/cjs/components/select/combobox.d.ts.map +1 -1
- package/lib/cjs/components/select/combobox.js +25 -15
- package/lib/cjs/components/select/combobox.js.map +1 -1
- package/lib/cjs/components/select/config.d.ts +2 -2
- package/lib/cjs/components/select/config.d.ts.map +1 -1
- package/lib/cjs/components/select/config.js +10 -9
- package/lib/cjs/components/select/config.js.map +1 -1
- package/lib/cjs/components/select/dropdown.js.map +1 -1
- package/lib/cjs/components/select/option.d.ts +2 -1
- package/lib/cjs/components/select/option.d.ts.map +1 -1
- package/lib/cjs/components/select/option.js +9 -3
- package/lib/cjs/components/select/option.js.map +1 -1
- package/lib/cjs/components/select/remote.d.ts +1 -0
- package/lib/cjs/components/select/remote.d.ts.map +1 -1
- package/lib/cjs/components/select/remote.js +21 -14
- package/lib/cjs/components/select/remote.js.map +1 -1
- package/lib/cjs/components/select/search.d.ts +1 -1
- package/lib/cjs/components/select/search.d.ts.map +1 -1
- package/lib/cjs/components/select/search.js +34 -25
- package/lib/cjs/components/select/search.js.map +1 -1
- package/lib/cjs/components/select/select.d.ts +5 -3
- package/lib/cjs/components/select/select.d.ts.map +1 -1
- package/lib/cjs/components/select/select.js +31 -31
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/cjs/components/select/tags.d.ts.map +1 -1
- package/lib/cjs/components/select/tags.js +22 -13
- package/lib/cjs/components/select/tags.js.map +1 -1
- package/lib/cjs/components/select/templates.d.ts.map +1 -1
- package/lib/cjs/components/select/templates.js +4 -4
- package/lib/cjs/components/select/templates.js.map +1 -1
- package/lib/cjs/components/select/types.d.ts +1 -1
- package/lib/cjs/components/select/types.d.ts.map +1 -1
- package/lib/cjs/components/select/utils.d.ts +4 -4
- package/lib/cjs/components/select/utils.d.ts.map +1 -1
- package/lib/cjs/components/select/utils.js +2 -3
- package/lib/cjs/components/select/utils.js.map +1 -1
- package/lib/cjs/components/sticky/sticky.d.ts +1 -1
- package/lib/cjs/components/sticky/sticky.d.ts.map +1 -1
- package/lib/cjs/components/sticky/sticky.js +13 -13
- package/lib/cjs/components/sticky/sticky.js.map +1 -1
- package/lib/cjs/components/toast/toast.d.ts.map +1 -1
- package/lib/cjs/components/toast/toast.js +17 -9
- package/lib/cjs/components/toast/toast.js.map +1 -1
- package/lib/cjs/components/toast/types.d.ts +3 -0
- package/lib/cjs/components/toast/types.d.ts.map +1 -1
- package/lib/cjs/components/toggle-password/toggle-password.d.ts.map +1 -1
- package/lib/cjs/components/toggle-password/toggle-password.js.map +1 -1
- package/lib/cjs/helpers/dom.d.ts +4 -4
- package/lib/cjs/helpers/dom.d.ts.map +1 -1
- package/lib/cjs/helpers/dom.js +8 -10
- package/lib/cjs/helpers/dom.js.map +1 -1
- package/lib/cjs/helpers/event-handler.d.ts +1 -1
- package/lib/cjs/helpers/event-handler.d.ts.map +1 -1
- package/lib/cjs/helpers/event-handler.js +3 -1
- package/lib/cjs/helpers/event-handler.js.map +1 -1
- package/lib/cjs/helpers/utils.d.ts +1 -1
- package/lib/cjs/helpers/utils.d.ts.map +1 -1
- package/lib/cjs/helpers/utils.js +4 -1
- package/lib/cjs/helpers/utils.js.map +1 -1
- package/lib/cjs/index.d.ts +8 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +9 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/types.d.ts +1 -1
- package/lib/cjs/types.d.ts.map +1 -1
- package/lib/esm/components/carousel/carousel.d.ts +102 -0
- package/lib/esm/components/carousel/carousel.d.ts.map +1 -0
- package/lib/esm/components/carousel/carousel.js +766 -0
- package/lib/esm/components/carousel/carousel.js.map +1 -0
- package/lib/esm/components/carousel/index.d.ts +7 -0
- package/lib/esm/components/carousel/index.d.ts.map +1 -0
- package/lib/esm/components/carousel/index.js +6 -0
- package/lib/esm/components/carousel/index.js.map +1 -0
- package/lib/esm/components/carousel/types.d.ts +36 -0
- package/lib/esm/components/carousel/types.d.ts.map +1 -0
- package/lib/esm/components/carousel/types.js +6 -0
- package/lib/esm/components/carousel/types.js.map +1 -0
- package/lib/esm/components/component.d.ts +3 -3
- package/lib/esm/components/component.d.ts.map +1 -1
- package/lib/esm/components/component.js +9 -1
- package/lib/esm/components/component.js.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.d.ts +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.js +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/esm/components/datatable/datatable-sort.d.ts +1 -1
- package/lib/esm/components/datatable/datatable-sort.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-sort.js.map +1 -1
- package/lib/esm/components/datatable/datatable.d.ts +2 -0
- package/lib/esm/components/datatable/datatable.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable.js +29 -16
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/datatable/types.d.ts +2 -1
- package/lib/esm/components/datatable/types.d.ts.map +1 -1
- package/lib/esm/components/drawer/drawer.d.ts.map +1 -1
- package/lib/esm/components/drawer/drawer.js +3 -16
- package/lib/esm/components/drawer/drawer.js.map +1 -1
- package/lib/esm/components/dropdown/dropdown.d.ts +1 -1
- package/lib/esm/components/dropdown/dropdown.d.ts.map +1 -1
- package/lib/esm/components/dropdown/dropdown.js +2 -3
- package/lib/esm/components/dropdown/dropdown.js.map +1 -1
- package/lib/esm/components/pin-input/index.d.ts +3 -0
- package/lib/esm/components/pin-input/index.d.ts.map +1 -0
- package/lib/esm/components/pin-input/index.js +2 -0
- package/lib/esm/components/pin-input/index.js.map +1 -0
- package/lib/esm/components/pin-input/pin-input.d.ts +56 -0
- package/lib/esm/components/pin-input/pin-input.d.ts.map +1 -0
- package/lib/esm/components/pin-input/pin-input.js +452 -0
- package/lib/esm/components/pin-input/pin-input.js.map +1 -0
- package/lib/esm/components/pin-input/types.d.ts +41 -0
- package/lib/esm/components/pin-input/types.d.ts.map +1 -0
- package/lib/esm/components/pin-input/types.js +5 -0
- package/lib/esm/components/pin-input/types.js.map +1 -0
- package/lib/esm/components/rating/rating.d.ts.map +1 -1
- package/lib/esm/components/rating/rating.js.map +1 -1
- package/lib/esm/components/select/combobox.d.ts.map +1 -1
- package/lib/esm/components/select/combobox.js +25 -15
- package/lib/esm/components/select/combobox.js.map +1 -1
- package/lib/esm/components/select/config.d.ts +2 -2
- package/lib/esm/components/select/config.d.ts.map +1 -1
- package/lib/esm/components/select/config.js +10 -9
- package/lib/esm/components/select/config.js.map +1 -1
- package/lib/esm/components/select/dropdown.js.map +1 -1
- package/lib/esm/components/select/option.d.ts +2 -1
- package/lib/esm/components/select/option.d.ts.map +1 -1
- package/lib/esm/components/select/option.js +9 -3
- package/lib/esm/components/select/option.js.map +1 -1
- package/lib/esm/components/select/remote.d.ts +1 -0
- package/lib/esm/components/select/remote.d.ts.map +1 -1
- package/lib/esm/components/select/remote.js +21 -14
- package/lib/esm/components/select/remote.js.map +1 -1
- package/lib/esm/components/select/search.d.ts +1 -1
- package/lib/esm/components/select/search.d.ts.map +1 -1
- package/lib/esm/components/select/search.js +34 -25
- package/lib/esm/components/select/search.js.map +1 -1
- package/lib/esm/components/select/select.d.ts +5 -3
- package/lib/esm/components/select/select.d.ts.map +1 -1
- package/lib/esm/components/select/select.js +31 -31
- package/lib/esm/components/select/select.js.map +1 -1
- package/lib/esm/components/select/tags.d.ts.map +1 -1
- package/lib/esm/components/select/tags.js +22 -13
- package/lib/esm/components/select/tags.js.map +1 -1
- package/lib/esm/components/select/templates.d.ts.map +1 -1
- package/lib/esm/components/select/templates.js +4 -4
- package/lib/esm/components/select/templates.js.map +1 -1
- package/lib/esm/components/select/types.d.ts +1 -1
- package/lib/esm/components/select/types.d.ts.map +1 -1
- package/lib/esm/components/select/utils.d.ts +4 -4
- package/lib/esm/components/select/utils.d.ts.map +1 -1
- package/lib/esm/components/select/utils.js +2 -3
- package/lib/esm/components/select/utils.js.map +1 -1
- package/lib/esm/components/sticky/sticky.d.ts +1 -1
- package/lib/esm/components/sticky/sticky.d.ts.map +1 -1
- package/lib/esm/components/sticky/sticky.js +13 -13
- package/lib/esm/components/sticky/sticky.js.map +1 -1
- package/lib/esm/components/toast/toast.d.ts.map +1 -1
- package/lib/esm/components/toast/toast.js +17 -9
- package/lib/esm/components/toast/toast.js.map +1 -1
- package/lib/esm/components/toast/types.d.ts +3 -0
- package/lib/esm/components/toast/types.d.ts.map +1 -1
- package/lib/esm/components/toggle-password/toggle-password.d.ts.map +1 -1
- package/lib/esm/components/toggle-password/toggle-password.js.map +1 -1
- package/lib/esm/helpers/dom.d.ts +4 -4
- package/lib/esm/helpers/dom.d.ts.map +1 -1
- package/lib/esm/helpers/dom.js +8 -10
- package/lib/esm/helpers/dom.js.map +1 -1
- package/lib/esm/helpers/event-handler.d.ts +1 -1
- package/lib/esm/helpers/event-handler.d.ts.map +1 -1
- package/lib/esm/helpers/event-handler.js +3 -1
- package/lib/esm/helpers/event-handler.js.map +1 -1
- package/lib/esm/helpers/utils.d.ts +1 -1
- package/lib/esm/helpers/utils.d.ts.map +1 -1
- package/lib/esm/helpers/utils.js +4 -1
- package/lib/esm/helpers/utils.js.map +1 -1
- package/lib/esm/index.d.ts +8 -0
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +6 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/types.d.ts +1 -1
- package/lib/esm/types.d.ts.map +1 -1
- package/package.json +5 -2
- package/src/components/carousel/__tests__/carousel.test.ts +326 -0
- package/src/components/carousel/carousel.css +42 -0
- package/src/components/carousel/carousel.ts +847 -0
- package/src/components/carousel/index.ts +11 -0
- package/src/components/carousel/types.ts +38 -0
- package/src/components/clipboard/__tests__/clipboard.test.ts +4 -4
- package/src/components/component.ts +15 -5
- package/src/components/datatable/__tests__/currency-sort.test.ts +4 -3
- package/src/components/datatable/__tests__/pagination-reset.test.ts +7 -4
- package/src/components/datatable/__tests__/setup.ts +1 -1
- package/src/components/datatable/datatable-checkbox.ts +6 -4
- package/src/components/datatable/datatable-sort.ts +27 -7
- package/src/components/datatable/datatable.ts +64 -37
- package/src/components/datatable/types.ts +3 -1
- package/src/components/drawer/drawer.ts +3 -18
- package/src/components/dropdown/dropdown.ts +2 -3
- package/src/components/pin-input/__tests__/pin-input.test.ts +928 -0
- package/src/components/pin-input/index.ts +6 -0
- package/src/components/pin-input/pin-input.ts +499 -0
- package/src/components/pin-input/types.ts +45 -0
- package/src/components/rating/rating.ts +0 -1
- package/src/components/repeater/__tests__/repeater.test.ts +5 -5
- package/src/components/select/__tests__/ux-behaviors.test.ts +4 -3
- package/src/components/select/combobox.ts +23 -16
- package/src/components/select/config.ts +15 -14
- package/src/components/select/dropdown.ts +1 -1
- package/src/components/select/option.ts +14 -4
- package/src/components/select/remote.ts +68 -56
- package/src/components/select/search.ts +30 -27
- package/src/components/select/select.ts +41 -37
- package/src/components/select/tags.ts +14 -8
- package/src/components/select/templates.ts +11 -6
- package/src/components/select/types.ts +1 -1
- package/src/components/select/utils.ts +7 -9
- package/src/components/sticky/sticky.ts +2 -2
- package/src/components/toast/toast.ts +34 -21
- package/src/components/toast/types.ts +5 -1
- package/src/components/toggle-password/toggle-password.ts +0 -1
- package/src/helpers/dom.ts +14 -17
- package/src/helpers/event-handler.ts +5 -6
- package/src/helpers/utils.ts +5 -2
- package/src/index.ts +18 -0
- package/src/types.ts +1 -1
- package/styles.css +1 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { KTSelectConfigInterface } from './config';
|
|
7
7
|
import { KTSelect } from './select';
|
|
8
|
-
import { filterOptions,
|
|
8
|
+
import { filterOptions, FocusManager } from './utils';
|
|
9
9
|
import { defaultTemplates } from './templates';
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -14,7 +14,7 @@ import { defaultTemplates } from './templates';
|
|
|
14
14
|
export class KTSelectCombobox {
|
|
15
15
|
private _select: KTSelect;
|
|
16
16
|
private _config: KTSelectConfigInterface;
|
|
17
|
-
private _searchInputElement: HTMLInputElement;
|
|
17
|
+
private _searchInputElement: HTMLInputElement | null;
|
|
18
18
|
private _clearButtonElement: HTMLElement | null;
|
|
19
19
|
private _boundInputHandler: (event: Event) => void;
|
|
20
20
|
private _boundClearHandler: (event: MouseEvent) => void;
|
|
@@ -41,16 +41,18 @@ export class KTSelectCombobox {
|
|
|
41
41
|
|
|
42
42
|
this._attachEventListeners();
|
|
43
43
|
|
|
44
|
-
this._select.getElement()
|
|
44
|
+
this._select.getElement()?.addEventListener('dropdown.close', () => {
|
|
45
45
|
// When dropdown closes, if not multi-select and not using displayTemplate,
|
|
46
46
|
// ensure input shows the selected value or placeholder.
|
|
47
47
|
if (!this._config.multiple && !this._config.displayTemplate) {
|
|
48
48
|
this.updateDisplay(this._select.getSelectedOptions());
|
|
49
49
|
} else {
|
|
50
50
|
// For tags or displayTemplate, the input should be clear for typing.
|
|
51
|
-
this._searchInputElement
|
|
51
|
+
if (this._searchInputElement) {
|
|
52
|
+
this._searchInputElement.value = '';
|
|
53
|
+
}
|
|
52
54
|
}
|
|
53
|
-
this._toggleClearButtonVisibility(this._searchInputElement
|
|
55
|
+
this._toggleClearButtonVisibility(this._searchInputElement?.value ?? '');
|
|
54
56
|
// this._select.showAllOptions(); // showAllOptions might be too broad, filtering is managed by typing.
|
|
55
57
|
});
|
|
56
58
|
}
|
|
@@ -102,7 +104,7 @@ export class KTSelectCombobox {
|
|
|
102
104
|
|
|
103
105
|
this._toggleClearButtonVisibility(query);
|
|
104
106
|
|
|
105
|
-
if (!
|
|
107
|
+
if (!this._select.isDropdownOpen()) {
|
|
106
108
|
// Use public getter
|
|
107
109
|
this._select.openDropdown();
|
|
108
110
|
}
|
|
@@ -125,6 +127,7 @@ export class KTSelectCombobox {
|
|
|
125
127
|
private _handleClearButtonClick(event: MouseEvent): void {
|
|
126
128
|
event.preventDefault();
|
|
127
129
|
event.stopPropagation();
|
|
130
|
+
if (!this._searchInputElement) return;
|
|
128
131
|
|
|
129
132
|
this._searchInputElement.value = '';
|
|
130
133
|
this._toggleClearButtonVisibility('');
|
|
@@ -134,7 +137,7 @@ export class KTSelectCombobox {
|
|
|
134
137
|
this._select.clearSelection(); // This will also trigger updateSelectedOptionDisplay
|
|
135
138
|
this._select.showAllOptions(); // Show all options after clearing
|
|
136
139
|
this._select.openDropdown();
|
|
137
|
-
this._searchInputElement
|
|
140
|
+
this._searchInputElement?.focus();
|
|
138
141
|
}
|
|
139
142
|
|
|
140
143
|
/**
|
|
@@ -170,7 +173,10 @@ export class KTSelectCombobox {
|
|
|
170
173
|
// or the main FocusManager should adjust focus if needed.
|
|
171
174
|
// For combobox, this filtering is the primary search mechanism.
|
|
172
175
|
// We might need to tell select's focus manager to focus first option.
|
|
173
|
-
|
|
176
|
+
const focusManager = (
|
|
177
|
+
this._select as unknown as { _focusManager?: FocusManager }
|
|
178
|
+
)._focusManager;
|
|
179
|
+
focusManager?.focusFirst();
|
|
174
180
|
}
|
|
175
181
|
|
|
176
182
|
/**
|
|
@@ -185,17 +191,18 @@ export class KTSelectCombobox {
|
|
|
185
191
|
}
|
|
186
192
|
|
|
187
193
|
if (this._config.tags && this._valuesContainerElement) {
|
|
194
|
+
const valuesContainer = this._valuesContainerElement;
|
|
195
|
+
const selectElement = this._select.getElement();
|
|
196
|
+
if (!selectElement) return;
|
|
188
197
|
// Combobox + Tags
|
|
189
198
|
selectedOptions.forEach((value) => {
|
|
190
199
|
// Ensure value is properly escaped for querySelector
|
|
191
|
-
const optionElement =
|
|
192
|
-
.
|
|
193
|
-
|
|
194
|
-
`option[value="${CSS.escape(value)}"]`,
|
|
195
|
-
) as HTMLOptionElement;
|
|
200
|
+
const optionElement = selectElement.querySelector(
|
|
201
|
+
`option[value="${CSS.escape(value)}"]`,
|
|
202
|
+
) as HTMLOptionElement;
|
|
196
203
|
if (optionElement) {
|
|
197
204
|
const tagElement = defaultTemplates.tag(optionElement, this._config);
|
|
198
|
-
|
|
205
|
+
valuesContainer.appendChild(tagElement);
|
|
199
206
|
}
|
|
200
207
|
});
|
|
201
208
|
this._searchInputElement.value = ''; // Input field is for typing new searches
|
|
@@ -219,7 +226,7 @@ export class KTSelectCombobox {
|
|
|
219
226
|
.map((value) => {
|
|
220
227
|
const optionEl = this._select
|
|
221
228
|
.getElement()
|
|
222
|
-
|
|
229
|
+
?.querySelector(`option[value="${CSS.escape(value)}"]`);
|
|
223
230
|
return optionEl ? optionEl.textContent : '';
|
|
224
231
|
})
|
|
225
232
|
.join(', '); // Basic comma separation
|
|
@@ -233,7 +240,7 @@ export class KTSelectCombobox {
|
|
|
233
240
|
const selectedValue = selectedOptions[0];
|
|
234
241
|
const optionElement = this._select
|
|
235
242
|
.getElement()
|
|
236
|
-
|
|
243
|
+
?.querySelector(`option[value="${CSS.escape(selectedValue)}"]`);
|
|
237
244
|
this._searchInputElement.value = optionElement
|
|
238
245
|
? optionElement.textContent || ''
|
|
239
246
|
: '';
|
|
@@ -15,17 +15,17 @@ export const DefaultConfig: KTSelectConfigInterface = {
|
|
|
15
15
|
// Data Handling
|
|
16
16
|
items: [], // Static list of options
|
|
17
17
|
isLoading: false, // Indicates if options are being loaded asynchronously
|
|
18
|
-
onFetch:
|
|
18
|
+
onFetch: undefined, // Callback function to fetch options asynchronously
|
|
19
19
|
|
|
20
20
|
// Remote Data Configuration
|
|
21
21
|
remote: false, // Enable/disable remote data fetching
|
|
22
|
-
dataUrl:
|
|
23
|
-
apiDataProperty:
|
|
22
|
+
dataUrl: undefined, // URL to fetch options from
|
|
23
|
+
apiDataProperty: undefined, // Property in the response object that contains the options
|
|
24
24
|
remoteErrorMessage: 'Failed to load data', // Error message to display if remote data fetch fails
|
|
25
25
|
|
|
26
26
|
// Field Mapping
|
|
27
|
-
dataValueField:
|
|
28
|
-
dataFieldText:
|
|
27
|
+
dataValueField: undefined, // Property in the option object that contains the value (default: 'id')
|
|
28
|
+
dataFieldText: undefined, // Property in the option object that contains the text (default: 'title')
|
|
29
29
|
|
|
30
30
|
// Search Configuration
|
|
31
31
|
searchParam: '', // Query parameter for API search requests
|
|
@@ -60,7 +60,7 @@ export const DefaultConfig: KTSelectConfigInterface = {
|
|
|
60
60
|
clearAllText: 'Clear all', // Text for the "Clear All" option (if implemented)
|
|
61
61
|
enableSelectAll: false, // Enable/disable "Select All" button for multi-select
|
|
62
62
|
showSelectedCount: true, // Show the number of selected options in multi-select mode
|
|
63
|
-
renderSelected:
|
|
63
|
+
renderSelected: undefined, // Custom function to render the selected value(s) in the display area
|
|
64
64
|
|
|
65
65
|
// Accessibility & Usability
|
|
66
66
|
label: 'Select an option', // Label for the select component (for screen readers)
|
|
@@ -69,10 +69,10 @@ export const DefaultConfig: KTSelectConfigInterface = {
|
|
|
69
69
|
// Dropdown Configuration
|
|
70
70
|
dropdownZindex: 105, // Initial z-index value for the dropdown
|
|
71
71
|
dropdownContainer: null, // Container element for the dropdown
|
|
72
|
-
dropdownPlacement:
|
|
72
|
+
dropdownPlacement: undefined,
|
|
73
73
|
dropdownFlip: false,
|
|
74
74
|
dropdownPreventOverflow: false,
|
|
75
|
-
dropdownStrategy:
|
|
75
|
+
dropdownStrategy: undefined,
|
|
76
76
|
dropdownWidth: null, // Custom width for dropdown (e.g., '300px'), null to match toggle element width
|
|
77
77
|
closeOnOtherOpen: true, // Close other open dropdowns when this one opens
|
|
78
78
|
dispatchGlobalEvents: true, // Dispatch events on document for global listeners (jQuery compatibility)
|
|
@@ -112,7 +112,7 @@ export interface KTSelectConfigInterface {
|
|
|
112
112
|
clearAllText?: string;
|
|
113
113
|
enableSelectAll?: boolean;
|
|
114
114
|
showSelectedCount?: boolean;
|
|
115
|
-
renderSelected?: (selectedOptions:
|
|
115
|
+
renderSelected?: (selectedOptions: string[]) => string;
|
|
116
116
|
|
|
117
117
|
// Accessibility & Usability
|
|
118
118
|
label?: string;
|
|
@@ -201,16 +201,17 @@ export class KTSelectState {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
private _initDefaultConfig(
|
|
204
|
-
config
|
|
204
|
+
config?: KTSelectConfigInterface,
|
|
205
205
|
): KTSelectConfigInterface {
|
|
206
|
+
const resolvedConfig: Partial<KTSelectConfigInterface> = config ?? {};
|
|
206
207
|
return {
|
|
207
208
|
...DefaultConfig,
|
|
208
|
-
...
|
|
209
|
-
...
|
|
210
|
-
};
|
|
209
|
+
...resolvedConfig,
|
|
210
|
+
...resolvedConfig.config,
|
|
211
|
+
} as KTSelectConfigInterface;
|
|
211
212
|
}
|
|
212
213
|
|
|
213
|
-
public setItems(items?:
|
|
214
|
+
public setItems(items?: KTSelectOption[], query?: string): Promise<void> {
|
|
214
215
|
return new Promise<void>((resolve, reject) => {
|
|
215
216
|
if (items) {
|
|
216
217
|
this._config.items = items;
|
|
@@ -127,7 +127,7 @@ export class KTSelectDropdown extends KTComponent {
|
|
|
127
127
|
/**
|
|
128
128
|
* Handle clicks outside the dropdown
|
|
129
129
|
*/
|
|
130
|
-
private _handleOutsideClick(event:
|
|
130
|
+
private _handleOutsideClick(event: Event): void {
|
|
131
131
|
if (!this._isOpen) return;
|
|
132
132
|
|
|
133
133
|
const target = event.target as HTMLElement;
|
|
@@ -13,16 +13,26 @@ export class KTSelectOption extends KTComponent {
|
|
|
13
13
|
protected override readonly _config: KTSelectConfigInterface; // Holds option-specific data from data-kt-*
|
|
14
14
|
private _globalConfig: KTSelectConfigInterface; // Main select's config
|
|
15
15
|
|
|
16
|
+
private _elementWithInstance(): HTMLElement & { instance?: KTSelectOption } {
|
|
17
|
+
return this._element as HTMLElement & { instance?: KTSelectOption };
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
constructor(element: HTMLElement, config?: KTSelectConfigInterface) {
|
|
17
21
|
super();
|
|
18
22
|
|
|
19
23
|
// Always initialize a new option instance
|
|
20
24
|
this._init(element);
|
|
21
|
-
this._globalConfig = config;
|
|
25
|
+
this._globalConfig = (config ?? {}) as KTSelectConfigInterface;
|
|
22
26
|
this._buildConfig();
|
|
23
27
|
|
|
24
28
|
// Clean the config
|
|
25
|
-
|
|
29
|
+
const configRecord = this._config as unknown as Record<
|
|
30
|
+
string,
|
|
31
|
+
KTSelectConfigInterface
|
|
32
|
+
>;
|
|
33
|
+
this._config =
|
|
34
|
+
(configRecord[''] as KTSelectConfigInterface) ||
|
|
35
|
+
({} as KTSelectConfigInterface);
|
|
26
36
|
|
|
27
37
|
// Add the option config to the global config
|
|
28
38
|
// Ensure optionsConfig is initialized
|
|
@@ -42,7 +52,7 @@ export class KTSelectOption extends KTComponent {
|
|
|
42
52
|
|
|
43
53
|
// Don't store in KTData to avoid Singleton pattern issues
|
|
44
54
|
// Each option should be a unique instance
|
|
45
|
-
(
|
|
55
|
+
this._elementWithInstance().instance = this;
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
public get id(): string {
|
|
@@ -61,7 +71,7 @@ export class KTSelectOption extends KTComponent {
|
|
|
61
71
|
* Gathers all necessary data for rendering this option,
|
|
62
72
|
* including standard HTML attributes and custom data-kt-* attributes.
|
|
63
73
|
*/
|
|
64
|
-
public getOptionDataForTemplate(): Record<string,
|
|
74
|
+
public getOptionDataForTemplate(): Record<string, unknown> {
|
|
65
75
|
const el = this.getHTMLOptionElement();
|
|
66
76
|
const text = el.textContent || '';
|
|
67
77
|
return {
|
|
@@ -22,6 +22,10 @@ export class KTSelectRemote {
|
|
|
22
22
|
private _lastQuery: string = '';
|
|
23
23
|
private _element: HTMLElement | null = null;
|
|
24
24
|
|
|
25
|
+
private _isRecord(value: unknown): value is Record<string, unknown> {
|
|
26
|
+
return typeof value === 'object' && value !== null;
|
|
27
|
+
}
|
|
28
|
+
|
|
25
29
|
/**
|
|
26
30
|
* Constructor
|
|
27
31
|
* @param config KTSelect configuration
|
|
@@ -54,13 +58,13 @@ export class KTSelectRemote {
|
|
|
54
58
|
this._dispatchEvent('remoteSearchStart');
|
|
55
59
|
|
|
56
60
|
return fetch(url)
|
|
57
|
-
.then((response: Response): Promise<
|
|
61
|
+
.then((response: Response): Promise<unknown> => {
|
|
58
62
|
if (!response.ok) {
|
|
59
63
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
60
64
|
}
|
|
61
65
|
return response.json();
|
|
62
66
|
})
|
|
63
|
-
.then((data:
|
|
67
|
+
.then((data: unknown): KTSelectOptionData[] => {
|
|
64
68
|
// Process the data
|
|
65
69
|
return this._processData(data);
|
|
66
70
|
})
|
|
@@ -144,25 +148,30 @@ export class KTSelectRemote {
|
|
|
144
148
|
* @param data API response data
|
|
145
149
|
* @returns Array of KTSelectOptionData
|
|
146
150
|
*/
|
|
147
|
-
private _processData(data:
|
|
151
|
+
private _processData(data: unknown): KTSelectOptionData[] {
|
|
148
152
|
try {
|
|
149
|
-
let processedData = data;
|
|
153
|
+
let processedData: unknown = data;
|
|
154
|
+
const dataRecord = this._isRecord(data) ? data : null;
|
|
150
155
|
|
|
151
156
|
// Extract data from the API property if specified
|
|
152
|
-
if (
|
|
157
|
+
if (
|
|
158
|
+
this._config.apiDataProperty &&
|
|
159
|
+
dataRecord &&
|
|
160
|
+
this._config.apiDataProperty in dataRecord
|
|
161
|
+
) {
|
|
153
162
|
// If pagination metadata is available, extract it
|
|
154
163
|
if (this._config.pagination) {
|
|
155
|
-
if (
|
|
156
|
-
this._totalPages =
|
|
164
|
+
if (typeof dataRecord.total_pages === 'number') {
|
|
165
|
+
this._totalPages = dataRecord.total_pages;
|
|
157
166
|
}
|
|
158
|
-
if (
|
|
167
|
+
if (typeof dataRecord.total === 'number') {
|
|
159
168
|
this._totalPages = Math.ceil(
|
|
160
|
-
|
|
169
|
+
dataRecord.total / (this._config.paginationLimit || 10),
|
|
161
170
|
);
|
|
162
171
|
}
|
|
163
172
|
}
|
|
164
173
|
|
|
165
|
-
processedData =
|
|
174
|
+
processedData = dataRecord[this._config.apiDataProperty];
|
|
166
175
|
}
|
|
167
176
|
|
|
168
177
|
// Ensure data is an array
|
|
@@ -172,46 +181,48 @@ export class KTSelectRemote {
|
|
|
172
181
|
}
|
|
173
182
|
|
|
174
183
|
// Map data to KTSelectOptionData format
|
|
175
|
-
const mappedData = processedData.map(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
184
|
+
const mappedData = processedData.map(
|
|
185
|
+
(item: unknown): KTSelectOptionData => {
|
|
186
|
+
const mappedItem = this._mapItemToOption(item);
|
|
187
|
+
|
|
188
|
+
// Add logging to trace data path extraction
|
|
189
|
+
if (
|
|
190
|
+
this._config.dataValueField &&
|
|
191
|
+
this._config.dataValueField.includes('.')
|
|
192
|
+
) {
|
|
193
|
+
// For nested paths, verify extraction worked
|
|
194
|
+
const parts = this._config.dataValueField.split('.');
|
|
195
|
+
let nestedValue: unknown = item;
|
|
196
|
+
|
|
197
|
+
// Try to navigate to the value manually for verification
|
|
198
|
+
for (const part of parts) {
|
|
199
|
+
if (
|
|
200
|
+
nestedValue &&
|
|
201
|
+
typeof nestedValue === 'object' &&
|
|
202
|
+
part in nestedValue
|
|
203
|
+
) {
|
|
204
|
+
nestedValue = (nestedValue as Record<string, unknown>)[part];
|
|
205
|
+
} else {
|
|
206
|
+
nestedValue = null;
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
198
209
|
}
|
|
199
|
-
}
|
|
200
210
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
211
|
+
// If we found a value, verify it matches what was extracted
|
|
212
|
+
if (nestedValue !== null && nestedValue !== undefined) {
|
|
213
|
+
const expectedValue = String(nestedValue);
|
|
204
214
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
215
|
+
if (mappedItem.id !== expectedValue && expectedValue) {
|
|
216
|
+
console.warn(
|
|
217
|
+
`Value mismatch! Path: ${this._config.dataValueField}, Expected: ${expectedValue}, Got: ${mappedItem.id}`,
|
|
218
|
+
);
|
|
219
|
+
}
|
|
209
220
|
}
|
|
210
221
|
}
|
|
211
|
-
}
|
|
212
222
|
|
|
213
|
-
|
|
214
|
-
|
|
223
|
+
return mappedItem;
|
|
224
|
+
},
|
|
225
|
+
);
|
|
215
226
|
|
|
216
227
|
return mappedData;
|
|
217
228
|
} catch (error) {
|
|
@@ -227,19 +238,19 @@ export class KTSelectRemote {
|
|
|
227
238
|
* @param item Data item from API
|
|
228
239
|
* @returns KTSelectOptionData object
|
|
229
240
|
*/
|
|
230
|
-
private _mapItemToOption(item:
|
|
241
|
+
private _mapItemToOption(item: unknown): KTSelectOptionData {
|
|
231
242
|
// Get the field mapping from config with fallbacks for common field names
|
|
232
243
|
const valueField = this._config.dataValueField || 'id';
|
|
233
244
|
const labelField = this._config.dataFieldText || 'title';
|
|
234
245
|
|
|
235
246
|
// Extract values using improved getValue function
|
|
236
|
-
const getValue = (obj:
|
|
247
|
+
const getValue = (obj: unknown, path: string): unknown => {
|
|
237
248
|
if (!path || !obj) return null;
|
|
238
249
|
|
|
239
250
|
try {
|
|
240
251
|
// Handle dot notation to access nested properties
|
|
241
252
|
const parts = path.split('.');
|
|
242
|
-
let result = obj;
|
|
253
|
+
let result: unknown = obj;
|
|
243
254
|
|
|
244
255
|
for (const part of parts) {
|
|
245
256
|
if (
|
|
@@ -249,7 +260,7 @@ export class KTSelectRemote {
|
|
|
249
260
|
) {
|
|
250
261
|
return null;
|
|
251
262
|
}
|
|
252
|
-
result = result[part];
|
|
263
|
+
result = (result as Record<string, unknown>)[part];
|
|
253
264
|
}
|
|
254
265
|
|
|
255
266
|
return result;
|
|
@@ -261,12 +272,13 @@ export class KTSelectRemote {
|
|
|
261
272
|
|
|
262
273
|
// Get ID and ensure it's a string
|
|
263
274
|
let id = getValue(item, valueField);
|
|
275
|
+
const itemRecord = this._isRecord(item) ? item : {};
|
|
264
276
|
if (id === null || id === undefined) {
|
|
265
277
|
// Try common fallback fields for ID
|
|
266
278
|
const fallbackFields = ['id', 'value', 'key', 'pk'];
|
|
267
279
|
for (const field of fallbackFields) {
|
|
268
|
-
if (
|
|
269
|
-
id = String(
|
|
280
|
+
if (itemRecord[field] !== null && itemRecord[field] !== undefined) {
|
|
281
|
+
id = String(itemRecord[field]);
|
|
270
282
|
break;
|
|
271
283
|
}
|
|
272
284
|
}
|
|
@@ -292,8 +304,8 @@ export class KTSelectRemote {
|
|
|
292
304
|
'description',
|
|
293
305
|
];
|
|
294
306
|
for (const field of fallbackFields) {
|
|
295
|
-
if (
|
|
296
|
-
title = String(
|
|
307
|
+
if (itemRecord[field] !== null && itemRecord[field] !== undefined) {
|
|
308
|
+
title = String(itemRecord[field]);
|
|
297
309
|
break;
|
|
298
310
|
}
|
|
299
311
|
}
|
|
@@ -308,10 +320,10 @@ export class KTSelectRemote {
|
|
|
308
320
|
|
|
309
321
|
// Create the option object with consistent structure
|
|
310
322
|
const result: KTSelectOptionData = {
|
|
311
|
-
id: id,
|
|
312
|
-
title: title,
|
|
313
|
-
selected: Boolean(
|
|
314
|
-
disabled: Boolean(
|
|
323
|
+
id: String(id),
|
|
324
|
+
title: String(title),
|
|
325
|
+
selected: Boolean(itemRecord.selected),
|
|
326
|
+
disabled: Boolean(itemRecord.disabled),
|
|
315
327
|
};
|
|
316
328
|
|
|
317
329
|
return result;
|
|
@@ -10,7 +10,7 @@ import { filterOptions, FocusManager, EventManager } from './utils';
|
|
|
10
10
|
|
|
11
11
|
export class KTSelectSearch {
|
|
12
12
|
private _select: KTSelect;
|
|
13
|
-
private _searchInput: HTMLInputElement;
|
|
13
|
+
private _searchInput: HTMLInputElement | null;
|
|
14
14
|
private _noResultsElement: HTMLElement | null = null;
|
|
15
15
|
private _originalOptionContents = new Map<string, string>();
|
|
16
16
|
private _eventManager: EventManager;
|
|
@@ -18,7 +18,7 @@ export class KTSelectSearch {
|
|
|
18
18
|
private _config: KTSelectConfigInterface;
|
|
19
19
|
|
|
20
20
|
// Public handler for search input (made public for event binding)
|
|
21
|
-
public handleSearchInput: (
|
|
21
|
+
public handleSearchInput: (event: Event) => void;
|
|
22
22
|
|
|
23
23
|
constructor(select: KTSelect) {
|
|
24
24
|
this._select = select;
|
|
@@ -60,7 +60,7 @@ export class KTSelectSearch {
|
|
|
60
60
|
this._eventManager.addListener(this._searchInput, 'blur', () => {
|
|
61
61
|
// Small delay to prevent race conditions with selection
|
|
62
62
|
setTimeout(() => {
|
|
63
|
-
if (!this._searchInput
|
|
63
|
+
if (!this._searchInput?.value) {
|
|
64
64
|
this._resetAllOptions();
|
|
65
65
|
this.clearSearch();
|
|
66
66
|
}
|
|
@@ -74,12 +74,12 @@ export class KTSelectSearch {
|
|
|
74
74
|
) {
|
|
75
75
|
this._select
|
|
76
76
|
.getElement()
|
|
77
|
-
|
|
77
|
+
?.addEventListener('remoteSearchStart', () => {
|
|
78
78
|
// Reset focused option when remote search starts
|
|
79
79
|
this._focusManager.resetFocus();
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
this._select.getElement()
|
|
82
|
+
this._select.getElement()?.addEventListener('remoteSearchEnd', () => {
|
|
83
83
|
// After remote search completes, refresh our option cache
|
|
84
84
|
this.refreshOptionCache();
|
|
85
85
|
});
|
|
@@ -88,7 +88,7 @@ export class KTSelectSearch {
|
|
|
88
88
|
// Listen for dropdown close to reset options - ATTACH TO WRAPPER
|
|
89
89
|
this._select
|
|
90
90
|
.getWrapperElement()
|
|
91
|
-
|
|
91
|
+
?.addEventListener('dropdown.close', () => {
|
|
92
92
|
this._focusManager.resetFocus();
|
|
93
93
|
const config = this._select.getConfig();
|
|
94
94
|
|
|
@@ -98,7 +98,9 @@ export class KTSelectSearch {
|
|
|
98
98
|
// Respect clearSearchOnClose config option
|
|
99
99
|
if (config.clearSearchOnClose) {
|
|
100
100
|
// Clear the search input field
|
|
101
|
-
this._searchInput
|
|
101
|
+
if (this._searchInput) {
|
|
102
|
+
this._searchInput.value = '';
|
|
103
|
+
}
|
|
102
104
|
// Reset all options to their original state
|
|
103
105
|
this._resetAllOptions();
|
|
104
106
|
// Clear any "no results" message
|
|
@@ -116,7 +118,7 @@ export class KTSelectSearch {
|
|
|
116
118
|
});
|
|
117
119
|
|
|
118
120
|
// Clear highlights when an option is selected - ATTACH TO ORIGINAL SELECT (standard 'change' event)
|
|
119
|
-
this._select.getElement()
|
|
121
|
+
this._select.getElement()?.addEventListener('change', () => {
|
|
120
122
|
this.clearSearch();
|
|
121
123
|
|
|
122
124
|
// Close dropdown only for single select mode, and only if closeOnEnter is not false
|
|
@@ -131,7 +133,7 @@ export class KTSelectSearch {
|
|
|
131
133
|
// Consolidated 'dropdown.show' event listener - ATTACH TO WRAPPER
|
|
132
134
|
this._select
|
|
133
135
|
.getWrapperElement()
|
|
134
|
-
|
|
136
|
+
?.addEventListener('dropdown.show', () => {
|
|
135
137
|
this._focusManager.resetFocus(); // Always clear previous focus state
|
|
136
138
|
|
|
137
139
|
if (this._searchInput?.value) {
|
|
@@ -205,7 +207,7 @@ export class KTSelectSearch {
|
|
|
205
207
|
if (attempt < maxAttempts) {
|
|
206
208
|
this._focusSearchInputWithRetry(attempt + 1);
|
|
207
209
|
}
|
|
208
|
-
} catch
|
|
210
|
+
} catch {
|
|
209
211
|
// Focus failed with error, retry if we haven't exceeded max attempts
|
|
210
212
|
if (attempt < maxAttempts) {
|
|
211
213
|
this._focusSearchInputWithRetry(attempt + 1);
|
|
@@ -223,25 +225,26 @@ export class KTSelectSearch {
|
|
|
223
225
|
/**
|
|
224
226
|
* Handles keydown events on the search input for navigation and actions.
|
|
225
227
|
*/
|
|
226
|
-
private _handleSearchKeyDown(event:
|
|
227
|
-
const
|
|
228
|
+
private _handleSearchKeyDown(event: Event): void {
|
|
229
|
+
const keyEvent = event as KeyboardEvent;
|
|
230
|
+
const key = keyEvent.key;
|
|
228
231
|
|
|
229
232
|
switch (key) {
|
|
230
233
|
case ' ': // Spacebar
|
|
231
234
|
// Do nothing, allow space to be typed into the input
|
|
232
235
|
// Stop propagation to prevent parent handlers from processing this event
|
|
233
|
-
|
|
236
|
+
keyEvent.stopPropagation();
|
|
234
237
|
break;
|
|
235
238
|
case 'ArrowDown':
|
|
236
|
-
|
|
239
|
+
keyEvent.preventDefault();
|
|
237
240
|
this._focusManager.focusNext();
|
|
238
241
|
break;
|
|
239
242
|
case 'ArrowUp':
|
|
240
|
-
|
|
243
|
+
keyEvent.preventDefault();
|
|
241
244
|
this._focusManager.focusPrevious();
|
|
242
245
|
break;
|
|
243
|
-
case 'Enter':
|
|
244
|
-
|
|
246
|
+
case 'Enter': {
|
|
247
|
+
keyEvent.preventDefault();
|
|
245
248
|
// Use currently focused option (from arrow keys); only fall back to first if none focused
|
|
246
249
|
const optionToSelect =
|
|
247
250
|
this._focusManager.getFocusedOption() ??
|
|
@@ -272,9 +275,12 @@ export class KTSelectSearch {
|
|
|
272
275
|
}
|
|
273
276
|
}
|
|
274
277
|
break;
|
|
278
|
+
}
|
|
275
279
|
case 'Escape':
|
|
276
|
-
|
|
277
|
-
this._searchInput
|
|
280
|
+
keyEvent.preventDefault();
|
|
281
|
+
if (this._searchInput) {
|
|
282
|
+
this._searchInput.value = '';
|
|
283
|
+
}
|
|
278
284
|
this.clearSearch();
|
|
279
285
|
this._resetAllOptions();
|
|
280
286
|
this._clearNoResultsMessage();
|
|
@@ -342,8 +348,9 @@ export class KTSelectSearch {
|
|
|
342
348
|
|
|
343
349
|
// For remote search, KTSelect component handles it.
|
|
344
350
|
// KTSelect will call refreshAfterSearch on this module when remote data is updated.
|
|
351
|
+
const minLength = config.searchMinLength ?? 0;
|
|
345
352
|
if (config.remote && config.searchParam) {
|
|
346
|
-
if (query.length <
|
|
353
|
+
if (query.length < minLength) {
|
|
347
354
|
this._resetAllOptions();
|
|
348
355
|
this._clearNoResultsMessage();
|
|
349
356
|
this._focusManager.focusFirst(); // Focus first if query too short
|
|
@@ -352,7 +359,7 @@ export class KTSelectSearch {
|
|
|
352
359
|
}
|
|
353
360
|
|
|
354
361
|
// For local search
|
|
355
|
-
if (query.length >=
|
|
362
|
+
if (query.length >= minLength) {
|
|
356
363
|
this._filterOptions(query);
|
|
357
364
|
this._focusManager.focusFirst(); // Focus first visible option after local filtering
|
|
358
365
|
} else {
|
|
@@ -377,12 +384,8 @@ export class KTSelectSearch {
|
|
|
377
384
|
// Restore original content before filtering, so highlighting is applied fresh.
|
|
378
385
|
this._restoreOptionContentsBeforeFilter();
|
|
379
386
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
query,
|
|
383
|
-
config,
|
|
384
|
-
dropdownElement,
|
|
385
|
-
(count) => this._handleNoResults(count),
|
|
387
|
+
filterOptions(options, query, config, dropdownElement, (count) =>
|
|
388
|
+
this._handleNoResults(count),
|
|
386
389
|
);
|
|
387
390
|
|
|
388
391
|
this._select.updateSelectAllButtonState();
|