@keenthemes/ktui 1.1.1 → 1.1.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 +182 -190
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +1 -1
- package/lib/cjs/components/select/combobox.js +0 -2
- package/lib/cjs/components/select/combobox.js.map +1 -1
- package/lib/cjs/components/select/config.js +4 -1
- package/lib/cjs/components/select/config.js.map +1 -1
- package/lib/cjs/components/select/dropdown.js +0 -16
- package/lib/cjs/components/select/dropdown.js.map +1 -1
- package/lib/cjs/components/select/remote.js +0 -40
- package/lib/cjs/components/select/remote.js.map +1 -1
- package/lib/cjs/components/select/search.js +80 -19
- package/lib/cjs/components/select/search.js.map +1 -1
- package/lib/cjs/components/select/select.js +98 -110
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/cjs/components/select/tags.js +0 -2
- package/lib/cjs/components/select/tags.js.map +1 -1
- package/lib/esm/components/select/combobox.js +0 -2
- package/lib/esm/components/select/combobox.js.map +1 -1
- package/lib/esm/components/select/config.js +4 -1
- package/lib/esm/components/select/config.js.map +1 -1
- package/lib/esm/components/select/dropdown.js +0 -16
- package/lib/esm/components/select/dropdown.js.map +1 -1
- package/lib/esm/components/select/remote.js +0 -40
- package/lib/esm/components/select/remote.js.map +1 -1
- package/lib/esm/components/select/search.js +80 -19
- package/lib/esm/components/select/search.js.map +1 -1
- package/lib/esm/components/select/select.js +98 -110
- package/lib/esm/components/select/select.js.map +1 -1
- package/lib/esm/components/select/tags.js +0 -2
- package/lib/esm/components/select/tags.js.map +1 -1
- package/package.json +3 -3
- package/src/components/datatable/__tests__/race-conditions.test.ts +5 -5
- package/src/components/select/__tests__/ux-behaviors.test.ts +619 -0
- package/src/components/select/combobox.ts +0 -1
- package/src/components/select/config.ts +7 -1
- package/src/components/select/dropdown.ts +0 -24
- package/src/components/select/remote.ts +0 -49
- package/src/components/select/search.ts +85 -21
- package/src/components/select/select.ts +118 -149
- package/src/components/select/tags.ts +0 -1
|
@@ -35,6 +35,9 @@ export class KTSelect extends KTComponent {
|
|
|
35
35
|
// Static global configuration
|
|
36
36
|
private static globalConfig: Partial<KTSelectConfigInterface> = {};
|
|
37
37
|
|
|
38
|
+
// Static registry for tracking open dropdowns (global dropdown management)
|
|
39
|
+
private static openDropdowns: Set<KTSelect> = new Set();
|
|
40
|
+
|
|
38
41
|
// DOM elements
|
|
39
42
|
private _wrapperElement: HTMLElement;
|
|
40
43
|
private _displayElement: HTMLElement;
|
|
@@ -91,8 +94,6 @@ export class KTSelect extends KTComponent {
|
|
|
91
94
|
this._state
|
|
92
95
|
.setItems()
|
|
93
96
|
.then(() => {
|
|
94
|
-
if (this._config.debug)
|
|
95
|
-
console.log('Setting up component after remote data is loaded');
|
|
96
97
|
this._setupComponent();
|
|
97
98
|
})
|
|
98
99
|
.catch((error) => {
|
|
@@ -137,14 +138,43 @@ export class KTSelect extends KTComponent {
|
|
|
137
138
|
} as KTSelectConfigInterface;
|
|
138
139
|
}
|
|
139
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Override _dispatchEvent to also dispatch on document for global listeners (jQuery compatibility)
|
|
143
|
+
*/
|
|
144
|
+
protected override _dispatchEvent(eventType: string, payload: object = null): void {
|
|
145
|
+
// Call parent method to dispatch on element (existing behavior)
|
|
146
|
+
super._dispatchEvent(eventType, payload);
|
|
147
|
+
|
|
148
|
+
// Also dispatch on document if configured
|
|
149
|
+
const dispatchGlobalEvents =
|
|
150
|
+
this._config.dispatchGlobalEvents !== false; // Default to true
|
|
151
|
+
if (dispatchGlobalEvents) {
|
|
152
|
+
// Create namespaced event name for document dispatch
|
|
153
|
+
const namespacedEventType = `kt-select:${eventType}`;
|
|
154
|
+
|
|
155
|
+
// Create event with same detail structure
|
|
156
|
+
const globalEvent = new CustomEvent(namespacedEventType, {
|
|
157
|
+
detail: {
|
|
158
|
+
payload,
|
|
159
|
+
instance: this, // Include component instance reference
|
|
160
|
+
element: this._element, // Include element reference
|
|
161
|
+
},
|
|
162
|
+
bubbles: true,
|
|
163
|
+
cancelable: true,
|
|
164
|
+
composed: true, // Allow event to cross shadow DOM boundaries
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Dispatch on document
|
|
168
|
+
document.dispatchEvent(globalEvent);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
140
172
|
/**
|
|
141
173
|
* Initialize remote data fetching
|
|
142
174
|
*/
|
|
143
175
|
private _initializeRemoteData() {
|
|
144
176
|
if (!this._remoteModule || !this._config.remote) return;
|
|
145
177
|
|
|
146
|
-
if (this._config.debug)
|
|
147
|
-
console.log('Initializing remote data with URL:', this._config.dataUrl);
|
|
148
178
|
|
|
149
179
|
// For remote data, we need to create the HTML structure first
|
|
150
180
|
// so that the component can be properly initialized
|
|
@@ -158,7 +188,6 @@ export class KTSelect extends KTComponent {
|
|
|
158
188
|
this._remoteModule
|
|
159
189
|
.fetchData()
|
|
160
190
|
.then((items) => {
|
|
161
|
-
if (this._config.debug) console.log('Remote data fetched:', items);
|
|
162
191
|
|
|
163
192
|
// Remove placeholder/loading options before setting new items
|
|
164
193
|
this._clearExistingOptions();
|
|
@@ -170,8 +199,6 @@ export class KTSelect extends KTComponent {
|
|
|
170
199
|
// Generate options from the fetched data
|
|
171
200
|
this._generateOptionsHtml(this._element);
|
|
172
201
|
|
|
173
|
-
if (this._config.debug)
|
|
174
|
-
console.log('Generating options HTML from remote data');
|
|
175
202
|
|
|
176
203
|
// Update the dropdown to show the new options
|
|
177
204
|
this._updateDropdownWithNewOptions();
|
|
@@ -208,12 +235,6 @@ export class KTSelect extends KTComponent {
|
|
|
208
235
|
|
|
209
236
|
if (selectedOptions.length > 0) {
|
|
210
237
|
this._preSelectedValues = selectedOptions.map((opt) => opt.value);
|
|
211
|
-
if (this._config.debug) {
|
|
212
|
-
console.log(
|
|
213
|
-
'Captured pre-selected values before clearing:',
|
|
214
|
-
this._preSelectedValues,
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
238
|
}
|
|
218
239
|
|
|
219
240
|
// Keep only the empty/placeholder option and remove the rest
|
|
@@ -288,9 +309,6 @@ export class KTSelect extends KTComponent {
|
|
|
288
309
|
'[data-kt-select-option]',
|
|
289
310
|
) as NodeListOf<HTMLElement>;
|
|
290
311
|
|
|
291
|
-
if (this._config.debug) {
|
|
292
|
-
console.log(`Rendered ${optionsData.length} options in dropdown`);
|
|
293
|
-
}
|
|
294
312
|
}
|
|
295
313
|
|
|
296
314
|
/**
|
|
@@ -322,12 +340,6 @@ export class KTSelect extends KTComponent {
|
|
|
322
340
|
|
|
323
341
|
// Apply pre-selected values captured before remote data was loaded
|
|
324
342
|
if (this._preSelectedValues.length > 0) {
|
|
325
|
-
if (this._config.debug) {
|
|
326
|
-
console.log(
|
|
327
|
-
'Applying pre-selected values after remote data loaded:',
|
|
328
|
-
this._preSelectedValues,
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
343
|
|
|
332
344
|
// Get all available option values from the loaded remote data
|
|
333
345
|
const availableValues = Array.from(
|
|
@@ -345,9 +357,6 @@ export class KTSelect extends KTComponent {
|
|
|
345
357
|
? validPreSelectedValues
|
|
346
358
|
: [validPreSelectedValues[0]];
|
|
347
359
|
|
|
348
|
-
if (this._config.debug) {
|
|
349
|
-
console.log('Selecting matched values:', valuesToSelect);
|
|
350
|
-
}
|
|
351
360
|
|
|
352
361
|
// Get any existing selections from _preSelectOptions (e.g., data-kt-select-pre-selected)
|
|
353
362
|
const existingSelections = this._state.getSelectedOptions();
|
|
@@ -370,11 +379,6 @@ export class KTSelect extends KTComponent {
|
|
|
370
379
|
// Update the visual display
|
|
371
380
|
this.updateSelectedOptionDisplay();
|
|
372
381
|
this._updateSelectedOptionClass();
|
|
373
|
-
} else if (this._config.debug) {
|
|
374
|
-
console.log(
|
|
375
|
-
'None of the pre-selected values matched remote data:',
|
|
376
|
-
this._preSelectedValues,
|
|
377
|
-
);
|
|
378
382
|
}
|
|
379
383
|
|
|
380
384
|
// Clear the pre-selected values array after processing
|
|
@@ -492,7 +496,6 @@ export class KTSelect extends KTComponent {
|
|
|
492
496
|
this._showDropdownMessage('error', message);
|
|
493
497
|
|
|
494
498
|
if (!this._wrapperElement) {
|
|
495
|
-
if (this._config.debug) console.log('Setting up component after error');
|
|
496
499
|
this._setupComponent();
|
|
497
500
|
}
|
|
498
501
|
}
|
|
@@ -626,8 +629,6 @@ export class KTSelect extends KTComponent {
|
|
|
626
629
|
`[data-kt-select-option]`,
|
|
627
630
|
) as NodeListOf<HTMLElement>;
|
|
628
631
|
|
|
629
|
-
if (this._config.debug)
|
|
630
|
-
console.log(`Added ${newItems.length} more options to dropdown`);
|
|
631
632
|
}
|
|
632
633
|
|
|
633
634
|
/**
|
|
@@ -831,13 +832,28 @@ export class KTSelect extends KTComponent {
|
|
|
831
832
|
}
|
|
832
833
|
|
|
833
834
|
// Get search input element - this is used for the search functionality
|
|
835
|
+
// First try to find the actual input element (not the wrapper div)
|
|
834
836
|
this._searchInputElement = this._dropdownContentElement.querySelector(
|
|
835
|
-
`[data-kt-select-search]`,
|
|
837
|
+
`input[data-kt-select-search]`,
|
|
836
838
|
) as HTMLInputElement;
|
|
837
839
|
|
|
838
|
-
// If not found
|
|
840
|
+
// If not found, try the wrapper selector (for backward compatibility)
|
|
839
841
|
if (!this._searchInputElement) {
|
|
840
|
-
|
|
842
|
+
const searchWrapper = this._dropdownContentElement.querySelector(
|
|
843
|
+
`[data-kt-select-search]`,
|
|
844
|
+
) as HTMLElement;
|
|
845
|
+
if (searchWrapper) {
|
|
846
|
+
this._searchInputElement = searchWrapper.querySelector(
|
|
847
|
+
'input',
|
|
848
|
+
) as HTMLInputElement;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// If still not found in dropdown, check if it's the display element itself (combobox mode)
|
|
853
|
+
if (!this._searchInputElement) {
|
|
854
|
+
this._searchInputElement = this._displayElement.querySelector(
|
|
855
|
+
'input[data-kt-select-search]',
|
|
856
|
+
) as HTMLInputElement;
|
|
841
857
|
}
|
|
842
858
|
|
|
843
859
|
this._selectAllButton = this._wrapperElement.querySelector(
|
|
@@ -937,8 +953,6 @@ export class KTSelect extends KTComponent {
|
|
|
937
953
|
private _generateOptionsHtml(element: HTMLElement) {
|
|
938
954
|
const items = this._state.getItems() || [];
|
|
939
955
|
|
|
940
|
-
if (this._config.debug)
|
|
941
|
-
console.log(`Generating options HTML from ${items.length} items`);
|
|
942
956
|
|
|
943
957
|
// Only modify options if we have items to replace them with
|
|
944
958
|
if (items && items.length > 0) {
|
|
@@ -975,9 +989,6 @@ export class KTSelect extends KTComponent {
|
|
|
975
989
|
extractedLabel !== null ? String(extractedLabel) : 'Unnamed option';
|
|
976
990
|
}
|
|
977
991
|
|
|
978
|
-
// Log the extracted values for debugging
|
|
979
|
-
if (this._config.debug)
|
|
980
|
-
console.log(`Option: value=${value}, label=${label}`);
|
|
981
992
|
|
|
982
993
|
// Set option attributes
|
|
983
994
|
optionElement.value = value;
|
|
@@ -990,10 +1001,6 @@ export class KTSelect extends KTComponent {
|
|
|
990
1001
|
element.appendChild(optionElement);
|
|
991
1002
|
});
|
|
992
1003
|
|
|
993
|
-
if (this._config.debug)
|
|
994
|
-
console.log(`Added ${items.length} options to select element`);
|
|
995
|
-
} else {
|
|
996
|
-
if (this._config.debug) console.log('No items to generate options from');
|
|
997
1004
|
}
|
|
998
1005
|
}
|
|
999
1006
|
|
|
@@ -1008,10 +1015,6 @@ export class KTSelect extends KTComponent {
|
|
|
1008
1015
|
.split('.')
|
|
1009
1016
|
.reduce((o, k) => (o && o[k] !== undefined ? o[k] : null), obj);
|
|
1010
1017
|
|
|
1011
|
-
if (this._config.debug)
|
|
1012
|
-
console.log(
|
|
1013
|
-
`Extracting [${key}] from object => ${result !== null ? JSON.stringify(result) : 'null'}`,
|
|
1014
|
-
);
|
|
1015
1018
|
return result;
|
|
1016
1019
|
}
|
|
1017
1020
|
|
|
@@ -1052,42 +1055,57 @@ export class KTSelect extends KTComponent {
|
|
|
1052
1055
|
*/
|
|
1053
1056
|
public openDropdown() {
|
|
1054
1057
|
if (this._config.disabled) {
|
|
1055
|
-
if (this._config.debug)
|
|
1056
|
-
console.log('openDropdown: select is disabled, not opening');
|
|
1057
1058
|
return;
|
|
1058
1059
|
}
|
|
1059
|
-
if (this._config.debug)
|
|
1060
|
-
console.log(
|
|
1061
|
-
'openDropdown called, dropdownModule exists:',
|
|
1062
|
-
!!this._dropdownModule,
|
|
1063
|
-
);
|
|
1064
1060
|
|
|
1065
1061
|
if (!this._dropdownModule) {
|
|
1066
|
-
if (this._config.debug)
|
|
1067
|
-
console.log('Early return from openDropdown - module missing');
|
|
1068
1062
|
return;
|
|
1069
1063
|
}
|
|
1070
1064
|
|
|
1071
1065
|
// Don't open dropdown if the select is disabled
|
|
1072
1066
|
if (this._config.disabled) {
|
|
1073
|
-
if (this._config.debug)
|
|
1074
|
-
console.log('Early return from openDropdown - select is disabled');
|
|
1075
1067
|
return;
|
|
1076
1068
|
}
|
|
1077
1069
|
|
|
1078
|
-
if
|
|
1079
|
-
|
|
1070
|
+
// Global dropdown management: close other open dropdowns if configured
|
|
1071
|
+
const closeOnOtherOpen =
|
|
1072
|
+
this._config.closeOnOtherOpen !== false; // Default to true
|
|
1073
|
+
if (closeOnOtherOpen) {
|
|
1074
|
+
// Close all other open dropdowns
|
|
1075
|
+
const otherSelectsToClose: KTSelect[] = [];
|
|
1076
|
+
KTSelect.openDropdowns.forEach((otherSelect) => {
|
|
1077
|
+
const isOther = otherSelect !== this;
|
|
1078
|
+
const isOpen = otherSelect._dropdownIsOpen;
|
|
1079
|
+
if (isOther && isOpen) {
|
|
1080
|
+
otherSelectsToClose.push(otherSelect);
|
|
1081
|
+
}
|
|
1082
|
+
});
|
|
1083
|
+
otherSelectsToClose.forEach((otherSelect) => {
|
|
1084
|
+
otherSelect.closeDropdown();
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1080
1088
|
|
|
1081
1089
|
// Set our internal flag to match what we're doing
|
|
1082
1090
|
this._dropdownIsOpen = true;
|
|
1083
1091
|
|
|
1092
|
+
// Add to registry
|
|
1093
|
+
KTSelect.openDropdowns.add(this);
|
|
1094
|
+
|
|
1084
1095
|
// Open the dropdown via the module
|
|
1085
1096
|
this._dropdownModule.open();
|
|
1086
1097
|
|
|
1087
|
-
// Dispatch custom
|
|
1098
|
+
// Dispatch custom events
|
|
1088
1099
|
this._dispatchEvent('show');
|
|
1089
1100
|
this._fireEvent('show');
|
|
1090
1101
|
|
|
1102
|
+
// Dispatch dropdown.show event on wrapper for search module
|
|
1103
|
+
const dropdownShowEvent = new CustomEvent('dropdown.show', {
|
|
1104
|
+
bubbles: true,
|
|
1105
|
+
cancelable: true,
|
|
1106
|
+
});
|
|
1107
|
+
this._wrapperElement.dispatchEvent(dropdownShowEvent);
|
|
1108
|
+
|
|
1091
1109
|
// Update ARIA states
|
|
1092
1110
|
this._setAriaAttributes();
|
|
1093
1111
|
|
|
@@ -1102,23 +1120,11 @@ export class KTSelect extends KTComponent {
|
|
|
1102
1120
|
* Close the dropdown
|
|
1103
1121
|
*/
|
|
1104
1122
|
public closeDropdown() {
|
|
1105
|
-
if (this._config.debug)
|
|
1106
|
-
console.log(
|
|
1107
|
-
'closeDropdown called, dropdownModule exists:',
|
|
1108
|
-
!!this._dropdownModule,
|
|
1109
|
-
);
|
|
1110
|
-
|
|
1111
1123
|
// Only check if dropdown module exists, not dropdownIsOpen flag
|
|
1112
1124
|
if (!this._dropdownModule) {
|
|
1113
|
-
if (this._config.debug)
|
|
1114
|
-
console.log('Early return from closeDropdown - module missing');
|
|
1115
1125
|
return;
|
|
1116
1126
|
}
|
|
1117
1127
|
|
|
1118
|
-
// Always close by delegating to the dropdown module, which is the source of truth
|
|
1119
|
-
if (this._config.debug)
|
|
1120
|
-
console.log('Closing dropdown via dropdownModule...');
|
|
1121
|
-
|
|
1122
1128
|
// Clear search input if the dropdown is closing
|
|
1123
1129
|
if (this._searchModule && this._searchInputElement) {
|
|
1124
1130
|
// Clear search input if configured to do so
|
|
@@ -1133,6 +1139,9 @@ export class KTSelect extends KTComponent {
|
|
|
1133
1139
|
// Set our internal flag to match what we're doing
|
|
1134
1140
|
this._dropdownIsOpen = false;
|
|
1135
1141
|
|
|
1142
|
+
// Remove from registry
|
|
1143
|
+
KTSelect.openDropdowns.delete(this);
|
|
1144
|
+
|
|
1136
1145
|
// Call the dropdown module's close method
|
|
1137
1146
|
this._dropdownModule.close();
|
|
1138
1147
|
|
|
@@ -1145,9 +1154,15 @@ export class KTSelect extends KTComponent {
|
|
|
1145
1154
|
this._dispatchEvent('close');
|
|
1146
1155
|
this._fireEvent('close');
|
|
1147
1156
|
|
|
1157
|
+
// Dispatch dropdown.close event on wrapper for search module
|
|
1158
|
+
const dropdownCloseEvent = new CustomEvent('dropdown.close', {
|
|
1159
|
+
bubbles: true,
|
|
1160
|
+
cancelable: true,
|
|
1161
|
+
});
|
|
1162
|
+
this._wrapperElement.dispatchEvent(dropdownCloseEvent);
|
|
1163
|
+
|
|
1148
1164
|
// Update ARIA states
|
|
1149
1165
|
this._setAriaAttributes();
|
|
1150
|
-
if (this._config.debug) console.log('closeDropdown complete');
|
|
1151
1166
|
}
|
|
1152
1167
|
|
|
1153
1168
|
/**
|
|
@@ -1187,8 +1202,6 @@ export class KTSelect extends KTComponent {
|
|
|
1187
1202
|
private _selectOption(value: string) {
|
|
1188
1203
|
// Prevent selection if the option is disabled (in dropdown or original select)
|
|
1189
1204
|
if (this._isOptionDisabled(value)) {
|
|
1190
|
-
if (this._config.debug)
|
|
1191
|
-
console.log('_selectOption: Option is disabled, ignoring selection');
|
|
1192
1205
|
return;
|
|
1193
1206
|
}
|
|
1194
1207
|
|
|
@@ -1338,11 +1351,6 @@ export class KTSelect extends KTComponent {
|
|
|
1338
1351
|
typeof this._config.maxSelections === 'number' &&
|
|
1339
1352
|
selectedValues.length >= this._config.maxSelections;
|
|
1340
1353
|
|
|
1341
|
-
if (this._config.debug)
|
|
1342
|
-
console.log(
|
|
1343
|
-
'Updating selected classes for options, selected values:',
|
|
1344
|
-
selectedValues,
|
|
1345
|
-
);
|
|
1346
1354
|
|
|
1347
1355
|
allOptions.forEach((option) => {
|
|
1348
1356
|
const optionValue = option.getAttribute('data-value');
|
|
@@ -1462,8 +1470,6 @@ export class KTSelect extends KTComponent {
|
|
|
1462
1470
|
* Handle clicking on an option in the dropdown
|
|
1463
1471
|
*/
|
|
1464
1472
|
private _handleOptionClick(event: Event) {
|
|
1465
|
-
if (this._config.debug)
|
|
1466
|
-
console.log('_handleOptionClick called', event.target);
|
|
1467
1473
|
event.preventDefault();
|
|
1468
1474
|
event.stopPropagation();
|
|
1469
1475
|
|
|
@@ -1473,31 +1479,22 @@ export class KTSelect extends KTComponent {
|
|
|
1473
1479
|
) as HTMLElement;
|
|
1474
1480
|
|
|
1475
1481
|
if (!clickedOption) {
|
|
1476
|
-
if (this._config.debug) console.log('No clicked option found');
|
|
1477
1482
|
return;
|
|
1478
1483
|
}
|
|
1479
1484
|
|
|
1480
1485
|
// Check if the option is disabled
|
|
1481
1486
|
if (clickedOption.getAttribute('aria-disabled') === 'true') {
|
|
1482
|
-
if (this._config.debug) console.log('Option is disabled, ignoring click');
|
|
1483
1487
|
return;
|
|
1484
1488
|
}
|
|
1485
1489
|
|
|
1486
1490
|
// Use dataset.value to get the option value
|
|
1487
1491
|
const optionValue = clickedOption.dataset.value;
|
|
1488
1492
|
if (optionValue === undefined) {
|
|
1489
|
-
if (this._config.debug) console.log('Option value is undefined');
|
|
1490
1493
|
return;
|
|
1491
1494
|
}
|
|
1492
1495
|
|
|
1493
|
-
if (this._config.debug) console.log('Option clicked:', optionValue);
|
|
1494
|
-
|
|
1495
1496
|
// If in single-select mode and the clicked option is already selected, just close the dropdown.
|
|
1496
1497
|
if (!this._config.multiple && this._state.isSelected(optionValue)) {
|
|
1497
|
-
if (this._config.debug)
|
|
1498
|
-
console.log(
|
|
1499
|
-
'Single select mode: clicked already selected option. Closing dropdown.',
|
|
1500
|
-
);
|
|
1501
1498
|
this.closeDropdown();
|
|
1502
1499
|
return;
|
|
1503
1500
|
}
|
|
@@ -1654,32 +1651,17 @@ export class KTSelect extends KTComponent {
|
|
|
1654
1651
|
public toggleSelection(value: string): void {
|
|
1655
1652
|
// Prevent selection if the option is disabled (in dropdown or original select)
|
|
1656
1653
|
if (this._isOptionDisabled(value)) {
|
|
1657
|
-
if (this._config.debug)
|
|
1658
|
-
console.log('toggleSelection: Option is disabled, ignoring selection');
|
|
1659
1654
|
return;
|
|
1660
1655
|
}
|
|
1661
1656
|
|
|
1662
1657
|
// Get current selection state
|
|
1663
1658
|
const isSelected = this._state.isSelected(value);
|
|
1664
|
-
if (this._config.debug)
|
|
1665
|
-
console.log(
|
|
1666
|
-
`toggleSelection called for value: ${value}, isSelected: ${isSelected}, multiple: ${this._config.multiple}`,
|
|
1667
|
-
);
|
|
1668
1659
|
|
|
1669
1660
|
// If already selected in single select mode, do nothing (can't deselect in single select)
|
|
1670
1661
|
if (isSelected && !this._config.multiple) {
|
|
1671
|
-
if (this._config.debug)
|
|
1672
|
-
console.log(
|
|
1673
|
-
'Early return from toggleSelection - already selected in single select mode',
|
|
1674
|
-
);
|
|
1675
1662
|
return;
|
|
1676
1663
|
}
|
|
1677
1664
|
|
|
1678
|
-
if (this._config.debug)
|
|
1679
|
-
console.log(
|
|
1680
|
-
`Toggling selection for option: ${value}, currently selected: ${isSelected}`,
|
|
1681
|
-
);
|
|
1682
|
-
|
|
1683
1665
|
// Ensure any search input is cleared when selection changes
|
|
1684
1666
|
if (this._searchModule) {
|
|
1685
1667
|
this._searchModule.clearSearch();
|
|
@@ -1711,19 +1693,20 @@ export class KTSelect extends KTComponent {
|
|
|
1711
1693
|
// Update option classes without re-rendering the dropdown content
|
|
1712
1694
|
this._updateSelectedOptionClass();
|
|
1713
1695
|
|
|
1714
|
-
// For single select mode,
|
|
1696
|
+
// For single select mode, close the dropdown after selection unless closeOnEnter is false
|
|
1715
1697
|
// For multiple select mode, keep the dropdown open to allow multiple selections
|
|
1716
1698
|
if (!this._config.multiple) {
|
|
1717
|
-
if
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1699
|
+
// Check if we should close based on closeOnEnter config
|
|
1700
|
+
// closeOnEnter only applies to Enter key selections, but for backward compatibility,
|
|
1701
|
+
// we'll respect it for all selections when explicitly set to false
|
|
1702
|
+
const shouldClose =
|
|
1703
|
+
this._config.closeOnEnter !== false; // Default to true
|
|
1704
|
+
if (shouldClose) {
|
|
1705
|
+
this.closeDropdown();
|
|
1706
|
+
} else {
|
|
1707
|
+
this.updateSelectAllButtonState();
|
|
1708
|
+
}
|
|
1722
1709
|
} else {
|
|
1723
|
-
if (this._config.debug)
|
|
1724
|
-
console.log(
|
|
1725
|
-
'Multiple select mode - keeping dropdown open for additional selections',
|
|
1726
|
-
);
|
|
1727
1710
|
// Don't close dropdown in multiple select mode to allow multiple selections
|
|
1728
1711
|
this.updateSelectAllButtonState();
|
|
1729
1712
|
}
|
|
@@ -1879,12 +1862,6 @@ export class KTSelect extends KTComponent {
|
|
|
1879
1862
|
availableValues.includes(value),
|
|
1880
1863
|
);
|
|
1881
1864
|
|
|
1882
|
-
if (this._config.debug && currentlySelected.length > 0) {
|
|
1883
|
-
console.log(
|
|
1884
|
-
'update(): Preserving selections that exist in new data:',
|
|
1885
|
-
validSelections,
|
|
1886
|
-
);
|
|
1887
|
-
}
|
|
1888
1865
|
|
|
1889
1866
|
// Add new options from remote data and restore selection state
|
|
1890
1867
|
items.forEach((item) => {
|
|
@@ -1980,12 +1957,6 @@ export class KTSelect extends KTComponent {
|
|
|
1980
1957
|
availableValues.includes(value),
|
|
1981
1958
|
);
|
|
1982
1959
|
|
|
1983
|
-
if (this._config.debug && currentlySelected.length > 0) {
|
|
1984
|
-
console.log(
|
|
1985
|
-
'reload(): Preserving selections that exist in new data:',
|
|
1986
|
-
validSelections,
|
|
1987
|
-
);
|
|
1988
|
-
}
|
|
1989
1960
|
|
|
1990
1961
|
// Mark preserved selections on new options
|
|
1991
1962
|
validSelections.forEach((value) => {
|
|
@@ -2063,12 +2034,6 @@ export class KTSelect extends KTComponent {
|
|
|
2063
2034
|
availableValues.includes(value),
|
|
2064
2035
|
);
|
|
2065
2036
|
|
|
2066
|
-
if (this._config.debug && currentlySelected.length > 0) {
|
|
2067
|
-
console.log(
|
|
2068
|
-
'refresh(): Preserving selections that exist in new data:',
|
|
2069
|
-
validSelections,
|
|
2070
|
-
);
|
|
2071
|
-
}
|
|
2072
2037
|
|
|
2073
2038
|
// Add new options and restore selection state
|
|
2074
2039
|
items.forEach((item) => {
|
|
@@ -2296,9 +2261,6 @@ export class KTSelect extends KTComponent {
|
|
|
2296
2261
|
}
|
|
2297
2262
|
this.updateSelectAllButtonState();
|
|
2298
2263
|
|
|
2299
|
-
if (this._config.debug) {
|
|
2300
|
-
console.log('Restored original options after search clear');
|
|
2301
|
-
}
|
|
2302
2264
|
}
|
|
2303
2265
|
|
|
2304
2266
|
/**
|
|
@@ -2358,11 +2320,6 @@ export class KTSelect extends KTComponent {
|
|
|
2358
2320
|
this._element.appendChild(optionElement);
|
|
2359
2321
|
});
|
|
2360
2322
|
|
|
2361
|
-
if (this._config.debug) {
|
|
2362
|
-
console.log(
|
|
2363
|
-
`Updated original select with ${items.length} search results`,
|
|
2364
|
-
);
|
|
2365
|
-
}
|
|
2366
2323
|
}
|
|
2367
2324
|
|
|
2368
2325
|
/**
|
|
@@ -2502,10 +2459,6 @@ export class KTSelect extends KTComponent {
|
|
|
2502
2459
|
!this._config.multiple &&
|
|
2503
2460
|
this._state.isSelected(val)
|
|
2504
2461
|
) {
|
|
2505
|
-
if (this._config.debug)
|
|
2506
|
-
console.log(
|
|
2507
|
-
'Enter on already selected item in single-select mode. Closing.',
|
|
2508
|
-
);
|
|
2509
2462
|
this.closeDropdown();
|
|
2510
2463
|
event.preventDefault();
|
|
2511
2464
|
break;
|
|
@@ -2728,4 +2681,20 @@ export class KTSelect extends KTComponent {
|
|
|
2728
2681
|
? this._config.clearAllText
|
|
2729
2682
|
: this._config.selectAllText;
|
|
2730
2683
|
}
|
|
2684
|
+
|
|
2685
|
+
/**
|
|
2686
|
+
* Destroy the component and clean up resources
|
|
2687
|
+
*/
|
|
2688
|
+
public destroy(): void {
|
|
2689
|
+
// Remove from global dropdown registry
|
|
2690
|
+
KTSelect.openDropdowns.delete(this);
|
|
2691
|
+
|
|
2692
|
+
// Close dropdown if open
|
|
2693
|
+
if (this._dropdownIsOpen) {
|
|
2694
|
+
this.closeDropdown();
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
// Call parent dispose method
|
|
2698
|
+
super.dispose();
|
|
2699
|
+
}
|
|
2731
2700
|
}
|