@keenthemes/ktui 1.1.1 → 1.1.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/dist/ktui.js +674 -225
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +13 -1
- package/lib/cjs/components/component.js +22 -0
- package/lib/cjs/components/component.js.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +7 -1
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/drawer/drawer.js +255 -9
- package/lib/cjs/components/drawer/drawer.js.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.js +55 -8
- package/lib/cjs/components/dropdown/dropdown.js.map +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 +93 -22
- package/lib/cjs/components/select/search.js.map +1 -1
- package/lib/cjs/components/select/select.js +180 -114
- 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/cjs/components/sticky/sticky.js +44 -5
- package/lib/cjs/components/sticky/sticky.js.map +1 -1
- package/lib/cjs/helpers/data.js +8 -0
- package/lib/cjs/helpers/data.js.map +1 -1
- package/lib/cjs/helpers/event-handler.js +6 -5
- package/lib/cjs/helpers/event-handler.js.map +1 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/components/component.js +22 -0
- package/lib/esm/components/component.js.map +1 -1
- package/lib/esm/components/datatable/datatable.js +7 -1
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/drawer/drawer.js +255 -9
- package/lib/esm/components/drawer/drawer.js.map +1 -1
- package/lib/esm/components/dropdown/dropdown.js +55 -8
- package/lib/esm/components/dropdown/dropdown.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 +93 -22
- package/lib/esm/components/select/search.js.map +1 -1
- package/lib/esm/components/select/select.js +180 -114
- 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/lib/esm/components/sticky/sticky.js +44 -5
- package/lib/esm/components/sticky/sticky.js.map +1 -1
- package/lib/esm/helpers/data.js +8 -0
- package/lib/esm/helpers/data.js.map +1 -1
- package/lib/esm/helpers/event-handler.js +6 -5
- package/lib/esm/helpers/event-handler.js.map +1 -1
- package/lib/esm/index.js.map +1 -1
- package/package.json +6 -4
- package/src/components/component.ts +26 -0
- package/src/components/datatable/__tests__/race-conditions.test.ts +7 -7
- package/src/components/datatable/datatable.ts +8 -1
- package/src/components/drawer/drawer.ts +266 -10
- package/src/components/dropdown/dropdown.ts +63 -8
- package/src/components/select/__tests__/ux-behaviors.test.ts +997 -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 +97 -24
- package/src/components/select/select.css +5 -1
- package/src/components/select/select.ts +211 -153
- package/src/components/select/tags.ts +0 -1
- package/src/components/sticky/sticky.ts +55 -5
- package/src/helpers/data.ts +10 -0
- package/src/helpers/event-handler.ts +7 -6
- package/src/index.ts +2 -0
|
@@ -98,8 +98,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
98
98
|
_this._state
|
|
99
99
|
.setItems()
|
|
100
100
|
.then(function () {
|
|
101
|
-
if (_this._config.debug)
|
|
102
|
-
console.log('Setting up component after remote data is loaded');
|
|
103
101
|
_this._setupComponent();
|
|
104
102
|
})
|
|
105
103
|
.catch(function (error) {
|
|
@@ -134,6 +132,41 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
134
132
|
// Cast to writable to allow assignment (config is readonly but needs initialization)
|
|
135
133
|
this._config = __assign(__assign(__assign(__assign(__assign({}, this._defaultConfig), KTSelect.globalConfig), this._getGlobalConfig()), dom_1.default.getDataAttributes(this._element, this._dataOptionPrefix + this._name)), config);
|
|
136
134
|
};
|
|
135
|
+
/**
|
|
136
|
+
* Override _dispatchEvent to also dispatch on document for global listeners (jQuery compatibility)
|
|
137
|
+
*/
|
|
138
|
+
KTSelect.prototype._dispatchEvent = function (eventType, payload) {
|
|
139
|
+
if (payload === void 0) { payload = null; }
|
|
140
|
+
// Call parent method to dispatch on element (existing behavior)
|
|
141
|
+
_super.prototype._dispatchEvent.call(this, eventType, payload);
|
|
142
|
+
// Also dispatch on document if configured
|
|
143
|
+
var dispatchGlobalEvents = this._config.dispatchGlobalEvents !== false; // Default to true
|
|
144
|
+
if (dispatchGlobalEvents) {
|
|
145
|
+
// Create event detail structure
|
|
146
|
+
var eventDetail = {
|
|
147
|
+
payload: payload,
|
|
148
|
+
instance: this, // Include component instance reference
|
|
149
|
+
element: this._element, // Include element reference
|
|
150
|
+
};
|
|
151
|
+
// Dispatch non-namespaced event on document (for jQuery compatibility: $(document).on('show', ...))
|
|
152
|
+
var nonNamespacedEvent = new CustomEvent(eventType, {
|
|
153
|
+
detail: eventDetail,
|
|
154
|
+
bubbles: true,
|
|
155
|
+
cancelable: true,
|
|
156
|
+
composed: true, // Allow event to cross shadow DOM boundaries
|
|
157
|
+
});
|
|
158
|
+
document.dispatchEvent(nonNamespacedEvent);
|
|
159
|
+
// Also dispatch namespaced event on document (for namespaced listeners: $(document).on('kt-select:show', ...))
|
|
160
|
+
var namespacedEventType = "kt-select:".concat(eventType);
|
|
161
|
+
var namespacedEvent = new CustomEvent(namespacedEventType, {
|
|
162
|
+
detail: eventDetail,
|
|
163
|
+
bubbles: true,
|
|
164
|
+
cancelable: true,
|
|
165
|
+
composed: true, // Allow event to cross shadow DOM boundaries
|
|
166
|
+
});
|
|
167
|
+
document.dispatchEvent(namespacedEvent);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
137
170
|
/**
|
|
138
171
|
* Initialize remote data fetching
|
|
139
172
|
*/
|
|
@@ -141,8 +174,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
141
174
|
var _this = this;
|
|
142
175
|
if (!this._remoteModule || !this._config.remote)
|
|
143
176
|
return;
|
|
144
|
-
if (this._config.debug)
|
|
145
|
-
console.log('Initializing remote data with URL:', this._config.dataUrl);
|
|
146
177
|
// For remote data, we need to create the HTML structure first
|
|
147
178
|
// so that the component can be properly initialized
|
|
148
179
|
this._createHtmlStructure();
|
|
@@ -153,8 +184,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
153
184
|
this._remoteModule
|
|
154
185
|
.fetchData()
|
|
155
186
|
.then(function (items) {
|
|
156
|
-
if (_this._config.debug)
|
|
157
|
-
console.log('Remote data fetched:', items);
|
|
158
187
|
// Remove placeholder/loading options before setting new items
|
|
159
188
|
_this._clearExistingOptions();
|
|
160
189
|
// Update state with fetched items
|
|
@@ -163,8 +192,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
163
192
|
.then(function () {
|
|
164
193
|
// Generate options from the fetched data
|
|
165
194
|
_this._generateOptionsHtml(_this._element);
|
|
166
|
-
if (_this._config.debug)
|
|
167
|
-
console.log('Generating options HTML from remote data');
|
|
168
195
|
// Update the dropdown to show the new options
|
|
169
196
|
_this._updateDropdownWithNewOptions();
|
|
170
197
|
// Complete the component setup with the fetched data
|
|
@@ -192,9 +219,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
192
219
|
var selectedOptions = Array.from(this._element.querySelectorAll('option[selected]:not([value=""])'));
|
|
193
220
|
if (selectedOptions.length > 0) {
|
|
194
221
|
this._preSelectedValues = selectedOptions.map(function (opt) { return opt.value; });
|
|
195
|
-
if (this._config.debug) {
|
|
196
|
-
console.log('Captured pre-selected values before clearing:', this._preSelectedValues);
|
|
197
|
-
}
|
|
198
222
|
}
|
|
199
223
|
// Keep only the empty/placeholder option and remove the rest
|
|
200
224
|
var options = Array.from(this._element.querySelectorAll('option:not([value=""])'));
|
|
@@ -253,9 +277,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
253
277
|
optionsContainer.appendChild(fragment);
|
|
254
278
|
// Update options NodeList
|
|
255
279
|
this._options = this._dropdownContentElement.querySelectorAll('[data-kt-select-option]');
|
|
256
|
-
if (this._config.debug) {
|
|
257
|
-
console.log("Rendered ".concat(optionsData.length, " options in dropdown"));
|
|
258
|
-
}
|
|
259
280
|
};
|
|
260
281
|
/**
|
|
261
282
|
* Update dropdown with new options from the original select element
|
|
@@ -280,9 +301,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
280
301
|
}
|
|
281
302
|
// Apply pre-selected values captured before remote data was loaded
|
|
282
303
|
if (this._preSelectedValues.length > 0) {
|
|
283
|
-
if (this._config.debug) {
|
|
284
|
-
console.log('Applying pre-selected values after remote data loaded:', this._preSelectedValues);
|
|
285
|
-
}
|
|
286
304
|
// Get all available option values from the loaded remote data
|
|
287
305
|
var availableValues_1 = Array.from(this._element.querySelectorAll('option')).map(function (opt) { return opt.value; });
|
|
288
306
|
// Filter pre-selected values to only those that exist in remote data
|
|
@@ -294,9 +312,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
294
312
|
var valuesToSelect = this._config.multiple
|
|
295
313
|
? validPreSelectedValues
|
|
296
314
|
: [validPreSelectedValues[0]];
|
|
297
|
-
if (this._config.debug) {
|
|
298
|
-
console.log('Selecting matched values:', valuesToSelect);
|
|
299
|
-
}
|
|
300
315
|
// Get any existing selections from _preSelectOptions (e.g., data-kt-select-pre-selected)
|
|
301
316
|
var existingSelections = this._state.getSelectedOptions();
|
|
302
317
|
// Merge existing selections with native pre-selected values (no duplicates)
|
|
@@ -313,9 +328,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
313
328
|
this.updateSelectedOptionDisplay();
|
|
314
329
|
this._updateSelectedOptionClass();
|
|
315
330
|
}
|
|
316
|
-
else if (this._config.debug) {
|
|
317
|
-
console.log('None of the pre-selected values matched remote data:', this._preSelectedValues);
|
|
318
|
-
}
|
|
319
331
|
// Clear the pre-selected values array after processing
|
|
320
332
|
this._preSelectedValues = [];
|
|
321
333
|
}
|
|
@@ -390,8 +402,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
390
402
|
// If dropdown is already created, show error message there
|
|
391
403
|
this._showDropdownMessage('error', message);
|
|
392
404
|
if (!this._wrapperElement) {
|
|
393
|
-
if (this._config.debug)
|
|
394
|
-
console.log('Setting up component after error');
|
|
395
405
|
this._setupComponent();
|
|
396
406
|
}
|
|
397
407
|
};
|
|
@@ -503,8 +513,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
503
513
|
});
|
|
504
514
|
// Update options NodeList to include the new options
|
|
505
515
|
this._options = this._dropdownContentElement.querySelectorAll("[data-kt-select-option]");
|
|
506
|
-
if (this._config.debug)
|
|
507
|
-
console.log("Added ".concat(newItems.length, " more options to dropdown"));
|
|
508
516
|
};
|
|
509
517
|
/**
|
|
510
518
|
* ========================================================================
|
|
@@ -643,10 +651,18 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
643
651
|
return;
|
|
644
652
|
}
|
|
645
653
|
// Get search input element - this is used for the search functionality
|
|
646
|
-
|
|
647
|
-
|
|
654
|
+
// First try to find the actual input element (not the wrapper div)
|
|
655
|
+
this._searchInputElement = this._dropdownContentElement.querySelector("input[data-kt-select-search]");
|
|
656
|
+
// If not found, try the wrapper selector (for backward compatibility)
|
|
657
|
+
if (!this._searchInputElement) {
|
|
658
|
+
var searchWrapper = this._dropdownContentElement.querySelector("[data-kt-select-search]");
|
|
659
|
+
if (searchWrapper) {
|
|
660
|
+
this._searchInputElement = searchWrapper.querySelector('input');
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
// If still not found in dropdown, check if it's the display element itself (combobox mode)
|
|
648
664
|
if (!this._searchInputElement) {
|
|
649
|
-
this._searchInputElement = this._displayElement;
|
|
665
|
+
this._searchInputElement = this._displayElement.querySelector('input[data-kt-select-search]');
|
|
650
666
|
}
|
|
651
667
|
this._selectAllButton = this._wrapperElement.querySelector('[data-kt-select-select-all]');
|
|
652
668
|
// Cache the options container for performance
|
|
@@ -712,8 +728,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
712
728
|
KTSelect.prototype._generateOptionsHtml = function (element) {
|
|
713
729
|
var _this = this;
|
|
714
730
|
var items = this._state.getItems() || [];
|
|
715
|
-
if (this._config.debug)
|
|
716
|
-
console.log("Generating options HTML from ".concat(items.length, " items"));
|
|
717
731
|
// Only modify options if we have items to replace them with
|
|
718
732
|
if (items && items.length > 0) {
|
|
719
733
|
// Clear existing options except the first empty one
|
|
@@ -741,9 +755,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
741
755
|
label =
|
|
742
756
|
extractedLabel !== null ? String(extractedLabel) : 'Unnamed option';
|
|
743
757
|
}
|
|
744
|
-
// Log the extracted values for debugging
|
|
745
|
-
if (_this._config.debug)
|
|
746
|
-
console.log("Option: value=".concat(value, ", label=").concat(label));
|
|
747
758
|
// Set option attributes
|
|
748
759
|
optionElement.value = value;
|
|
749
760
|
optionElement.textContent = label || 'Unnamed option';
|
|
@@ -752,12 +763,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
752
763
|
}
|
|
753
764
|
element.appendChild(optionElement);
|
|
754
765
|
});
|
|
755
|
-
if (this._config.debug)
|
|
756
|
-
console.log("Added ".concat(items.length, " options to select element"));
|
|
757
|
-
}
|
|
758
|
-
else {
|
|
759
|
-
if (this._config.debug)
|
|
760
|
-
console.log('No items to generate options from');
|
|
761
766
|
}
|
|
762
767
|
};
|
|
763
768
|
/**
|
|
@@ -770,8 +775,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
770
775
|
var result = key
|
|
771
776
|
.split('.')
|
|
772
777
|
.reduce(function (o, k) { return (o && o[k] !== undefined ? o[k] : null); }, obj);
|
|
773
|
-
if (this._config.debug)
|
|
774
|
-
console.log("Extracting [".concat(key, "] from object => ").concat(result !== null ? JSON.stringify(result) : 'null'));
|
|
775
778
|
return result;
|
|
776
779
|
};
|
|
777
780
|
/**
|
|
@@ -804,55 +807,79 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
804
807
|
* Open the dropdown
|
|
805
808
|
*/
|
|
806
809
|
KTSelect.prototype.openDropdown = function () {
|
|
810
|
+
var _this = this;
|
|
807
811
|
if (this._config.disabled) {
|
|
808
|
-
if (this._config.debug)
|
|
809
|
-
console.log('openDropdown: select is disabled, not opening');
|
|
810
812
|
return;
|
|
811
813
|
}
|
|
812
|
-
if (this._config.debug)
|
|
813
|
-
console.log('openDropdown called, dropdownModule exists:', !!this._dropdownModule);
|
|
814
814
|
if (!this._dropdownModule) {
|
|
815
|
-
if (this._config.debug)
|
|
816
|
-
console.log('Early return from openDropdown - module missing');
|
|
817
815
|
return;
|
|
818
816
|
}
|
|
819
817
|
// Don't open dropdown if the select is disabled
|
|
820
818
|
if (this._config.disabled) {
|
|
821
|
-
if (this._config.debug)
|
|
822
|
-
console.log('Early return from openDropdown - select is disabled');
|
|
823
819
|
return;
|
|
824
820
|
}
|
|
825
|
-
if
|
|
826
|
-
|
|
821
|
+
// Global dropdown management: close other open dropdowns if configured
|
|
822
|
+
var closeOnOtherOpen = this._config.closeOnOtherOpen !== false; // Default to true
|
|
823
|
+
if (closeOnOtherOpen) {
|
|
824
|
+
// Close all other open dropdowns
|
|
825
|
+
var otherSelectsToClose_1 = [];
|
|
826
|
+
KTSelect.openDropdowns.forEach(function (otherSelect) {
|
|
827
|
+
var isOther = otherSelect !== _this;
|
|
828
|
+
var isOpen = otherSelect._dropdownIsOpen;
|
|
829
|
+
if (isOther && isOpen) {
|
|
830
|
+
otherSelectsToClose_1.push(otherSelect);
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
otherSelectsToClose_1.forEach(function (otherSelect) {
|
|
834
|
+
otherSelect.closeDropdown();
|
|
835
|
+
});
|
|
836
|
+
}
|
|
827
837
|
// Set our internal flag to match what we're doing
|
|
828
838
|
this._dropdownIsOpen = true;
|
|
839
|
+
// Add to registry
|
|
840
|
+
KTSelect.openDropdowns.add(this);
|
|
829
841
|
// Open the dropdown via the module
|
|
830
842
|
this._dropdownModule.open();
|
|
831
|
-
// Dispatch custom
|
|
843
|
+
// Dispatch custom events
|
|
832
844
|
this._dispatchEvent('show');
|
|
833
845
|
this._fireEvent('show');
|
|
846
|
+
// Dispatch dropdown.show event on wrapper for search module
|
|
847
|
+
var dropdownShowEvent = new CustomEvent('dropdown.show', {
|
|
848
|
+
bubbles: true,
|
|
849
|
+
cancelable: true,
|
|
850
|
+
});
|
|
851
|
+
this._wrapperElement.dispatchEvent(dropdownShowEvent);
|
|
834
852
|
// Update ARIA states
|
|
835
853
|
this._setAriaAttributes();
|
|
836
854
|
// Update select all button state
|
|
837
855
|
this.updateSelectAllButtonState();
|
|
838
856
|
// Focus the first selected option or first option if nothing selected
|
|
839
|
-
this
|
|
857
|
+
// BUT: Skip this if search autofocus is enabled, as we want search input to get focus
|
|
858
|
+
if (!(this._config.enableSearch && this._config.searchAutofocus)) {
|
|
859
|
+
this._focusSelectedOption();
|
|
860
|
+
}
|
|
861
|
+
// Dispatch dropdown.show event on the wrapper element for search module
|
|
862
|
+
// Use requestAnimationFrame to ensure dropdown is visible and transition has started
|
|
863
|
+
requestAnimationFrame(function () {
|
|
864
|
+
requestAnimationFrame(function () {
|
|
865
|
+
if (_this._wrapperElement) {
|
|
866
|
+
var dropdownShowEvent_1 = new CustomEvent('dropdown.show', {
|
|
867
|
+
bubbles: true,
|
|
868
|
+
cancelable: true,
|
|
869
|
+
});
|
|
870
|
+
_this._wrapperElement.dispatchEvent(dropdownShowEvent_1);
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
});
|
|
840
874
|
};
|
|
841
875
|
/**
|
|
842
876
|
* Close the dropdown
|
|
843
877
|
*/
|
|
844
878
|
KTSelect.prototype.closeDropdown = function () {
|
|
845
|
-
if (this._config.debug)
|
|
846
|
-
console.log('closeDropdown called, dropdownModule exists:', !!this._dropdownModule);
|
|
847
879
|
// Only check if dropdown module exists, not dropdownIsOpen flag
|
|
848
880
|
if (!this._dropdownModule) {
|
|
849
|
-
if (this._config.debug)
|
|
850
|
-
console.log('Early return from closeDropdown - module missing');
|
|
851
881
|
return;
|
|
852
882
|
}
|
|
853
|
-
// Always close by delegating to the dropdown module, which is the source of truth
|
|
854
|
-
if (this._config.debug)
|
|
855
|
-
console.log('Closing dropdown via dropdownModule...');
|
|
856
883
|
// Clear search input if the dropdown is closing
|
|
857
884
|
if (this._searchModule && this._searchInputElement) {
|
|
858
885
|
// Clear search input if configured to do so
|
|
@@ -864,19 +891,25 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
864
891
|
}
|
|
865
892
|
// Set our internal flag to match what we're doing
|
|
866
893
|
this._dropdownIsOpen = false;
|
|
894
|
+
// Remove from registry
|
|
895
|
+
KTSelect.openDropdowns.delete(this);
|
|
867
896
|
// Call the dropdown module's close method
|
|
868
897
|
this._dropdownModule.close();
|
|
869
898
|
// Reset all focus states
|
|
870
899
|
if (this._focusManager) {
|
|
871
900
|
this._focusManager.resetFocus();
|
|
872
901
|
}
|
|
873
|
-
// Dispatch custom events
|
|
902
|
+
// Dispatch custom events on the select element
|
|
874
903
|
this._dispatchEvent('close');
|
|
875
904
|
this._fireEvent('close');
|
|
905
|
+
// Dispatch dropdown.close event on wrapper for search module
|
|
906
|
+
var dropdownCloseEvent = new CustomEvent('dropdown.close', {
|
|
907
|
+
bubbles: true,
|
|
908
|
+
cancelable: true,
|
|
909
|
+
});
|
|
910
|
+
this._wrapperElement.dispatchEvent(dropdownCloseEvent);
|
|
876
911
|
// Update ARIA states
|
|
877
912
|
this._setAriaAttributes();
|
|
878
|
-
if (this._config.debug)
|
|
879
|
-
console.log('closeDropdown complete');
|
|
880
913
|
};
|
|
881
914
|
/**
|
|
882
915
|
* Update dropdown position
|
|
@@ -913,8 +946,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
913
946
|
KTSelect.prototype._selectOption = function (value) {
|
|
914
947
|
// Prevent selection if the option is disabled (in dropdown or original select)
|
|
915
948
|
if (this._isOptionDisabled(value)) {
|
|
916
|
-
if (this._config.debug)
|
|
917
|
-
console.log('_selectOption: Option is disabled, ignoring selection');
|
|
918
949
|
return;
|
|
919
950
|
}
|
|
920
951
|
// Get current selection state
|
|
@@ -1043,8 +1074,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1043
1074
|
var selectedValues = this._state.getSelectedOptions();
|
|
1044
1075
|
var maxReached = typeof this._config.maxSelections === 'number' &&
|
|
1045
1076
|
selectedValues.length >= this._config.maxSelections;
|
|
1046
|
-
if (this._config.debug)
|
|
1047
|
-
console.log('Updating selected classes for options, selected values:', selectedValues);
|
|
1048
1077
|
allOptions.forEach(function (option) {
|
|
1049
1078
|
var optionValue = option.getAttribute('data-value');
|
|
1050
1079
|
if (!optionValue)
|
|
@@ -1094,6 +1123,55 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1094
1123
|
this._dispatchEvent('change');
|
|
1095
1124
|
this._fireEvent('change');
|
|
1096
1125
|
};
|
|
1126
|
+
/**
|
|
1127
|
+
* Deselect a specific option by value
|
|
1128
|
+
* @param value The value of the option to deselect
|
|
1129
|
+
* @public
|
|
1130
|
+
*/
|
|
1131
|
+
KTSelect.prototype.deselectOption = function (value) {
|
|
1132
|
+
// Check if the option is currently selected
|
|
1133
|
+
if (!this._state.isSelected(value)) {
|
|
1134
|
+
return; // Already deselected
|
|
1135
|
+
}
|
|
1136
|
+
// For single-select mode, check if clearing is allowed
|
|
1137
|
+
if (!this._config.multiple && !this._config.allowClear) {
|
|
1138
|
+
return; // Cannot deselect in single-select mode unless allowClear is true
|
|
1139
|
+
}
|
|
1140
|
+
// Remove from selected options
|
|
1141
|
+
if (this._config.multiple) {
|
|
1142
|
+
// For multiple select, just toggle it off
|
|
1143
|
+
this._state.toggleSelectedOptions(value);
|
|
1144
|
+
}
|
|
1145
|
+
else {
|
|
1146
|
+
// For single select, clear all selections
|
|
1147
|
+
this._state.setSelectedOptions([]);
|
|
1148
|
+
}
|
|
1149
|
+
// Update the native select element
|
|
1150
|
+
var optionEl = Array.from(this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
|
|
1151
|
+
if (optionEl) {
|
|
1152
|
+
optionEl.selected = false;
|
|
1153
|
+
}
|
|
1154
|
+
// For single select, clear the native select value
|
|
1155
|
+
if (!this._config.multiple) {
|
|
1156
|
+
this._element.value = '';
|
|
1157
|
+
}
|
|
1158
|
+
// Update the display
|
|
1159
|
+
this.updateSelectedOptionDisplay();
|
|
1160
|
+
this._updateSelectedOptionClass();
|
|
1161
|
+
// Update select all button state
|
|
1162
|
+
this.updateSelectAllButtonState();
|
|
1163
|
+
// Dispatch change event
|
|
1164
|
+
this._dispatchEvent('change', {
|
|
1165
|
+
value: value,
|
|
1166
|
+
selected: false,
|
|
1167
|
+
selectedOptions: this.getSelectedOptions(),
|
|
1168
|
+
});
|
|
1169
|
+
this._fireEvent('change', {
|
|
1170
|
+
value: value,
|
|
1171
|
+
selected: false,
|
|
1172
|
+
selectedOptions: this.getSelectedOptions(),
|
|
1173
|
+
});
|
|
1174
|
+
};
|
|
1097
1175
|
/**
|
|
1098
1176
|
* Set selected options programmatically
|
|
1099
1177
|
*/
|
|
@@ -1145,36 +1223,24 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1145
1223
|
* Handle clicking on an option in the dropdown
|
|
1146
1224
|
*/
|
|
1147
1225
|
KTSelect.prototype._handleOptionClick = function (event) {
|
|
1148
|
-
if (this._config.debug)
|
|
1149
|
-
console.log('_handleOptionClick called', event.target);
|
|
1150
1226
|
event.preventDefault();
|
|
1151
1227
|
event.stopPropagation();
|
|
1152
1228
|
// Find the clicked option element
|
|
1153
1229
|
var clickedOption = event.target.closest("[data-kt-select-option]");
|
|
1154
1230
|
if (!clickedOption) {
|
|
1155
|
-
if (this._config.debug)
|
|
1156
|
-
console.log('No clicked option found');
|
|
1157
1231
|
return;
|
|
1158
1232
|
}
|
|
1159
1233
|
// Check if the option is disabled
|
|
1160
1234
|
if (clickedOption.getAttribute('aria-disabled') === 'true') {
|
|
1161
|
-
if (this._config.debug)
|
|
1162
|
-
console.log('Option is disabled, ignoring click');
|
|
1163
1235
|
return;
|
|
1164
1236
|
}
|
|
1165
1237
|
// Use dataset.value to get the option value
|
|
1166
1238
|
var optionValue = clickedOption.dataset.value;
|
|
1167
1239
|
if (optionValue === undefined) {
|
|
1168
|
-
if (this._config.debug)
|
|
1169
|
-
console.log('Option value is undefined');
|
|
1170
1240
|
return;
|
|
1171
1241
|
}
|
|
1172
|
-
if (this._config.debug)
|
|
1173
|
-
console.log('Option clicked:', optionValue);
|
|
1174
1242
|
// If in single-select mode and the clicked option is already selected, just close the dropdown.
|
|
1175
1243
|
if (!this._config.multiple && this._state.isSelected(optionValue)) {
|
|
1176
|
-
if (this._config.debug)
|
|
1177
|
-
console.log('Single select mode: clicked already selected option. Closing dropdown.');
|
|
1178
1244
|
this.closeDropdown();
|
|
1179
1245
|
return;
|
|
1180
1246
|
}
|
|
@@ -1303,22 +1369,19 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1303
1369
|
KTSelect.prototype.toggleSelection = function (value) {
|
|
1304
1370
|
// Prevent selection if the option is disabled (in dropdown or original select)
|
|
1305
1371
|
if (this._isOptionDisabled(value)) {
|
|
1306
|
-
if (this._config.debug)
|
|
1307
|
-
console.log('toggleSelection: Option is disabled, ignoring selection');
|
|
1308
1372
|
return;
|
|
1309
1373
|
}
|
|
1310
1374
|
// Get current selection state
|
|
1311
1375
|
var isSelected = this._state.isSelected(value);
|
|
1312
|
-
if
|
|
1313
|
-
console.log("toggleSelection called for value: ".concat(value, ", isSelected: ").concat(isSelected, ", multiple: ").concat(this._config.multiple));
|
|
1314
|
-
// If already selected in single select mode, do nothing (can't deselect in single select)
|
|
1376
|
+
// If already selected in single select mode, allow deselecting only if allowClear is true
|
|
1315
1377
|
if (isSelected && !this._config.multiple) {
|
|
1316
|
-
if (this._config.
|
|
1317
|
-
|
|
1318
|
-
|
|
1378
|
+
if (this._config.allowClear) {
|
|
1379
|
+
// Use the deselectOption method to handle clearing
|
|
1380
|
+
this.deselectOption(value);
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
return; // Can't deselect in single select mode when allowClear is false
|
|
1319
1384
|
}
|
|
1320
|
-
if (this._config.debug)
|
|
1321
|
-
console.log("Toggling selection for option: ".concat(value, ", currently selected: ").concat(isSelected));
|
|
1322
1385
|
// Ensure any search input is cleared when selection changes
|
|
1323
1386
|
if (this._searchModule) {
|
|
1324
1387
|
this._searchModule.clearSearch();
|
|
@@ -1343,16 +1406,21 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1343
1406
|
this.updateSelectedOptionDisplay();
|
|
1344
1407
|
// Update option classes without re-rendering the dropdown content
|
|
1345
1408
|
this._updateSelectedOptionClass();
|
|
1346
|
-
// For single select mode,
|
|
1409
|
+
// For single select mode, close the dropdown after selection unless closeOnEnter is false
|
|
1347
1410
|
// For multiple select mode, keep the dropdown open to allow multiple selections
|
|
1348
1411
|
if (!this._config.multiple) {
|
|
1349
|
-
if
|
|
1350
|
-
|
|
1351
|
-
|
|
1412
|
+
// Check if we should close based on closeOnEnter config
|
|
1413
|
+
// closeOnEnter only applies to Enter key selections, but for backward compatibility,
|
|
1414
|
+
// we'll respect it for all selections when explicitly set to false
|
|
1415
|
+
var shouldClose = this._config.closeOnEnter !== false; // Default to true
|
|
1416
|
+
if (shouldClose) {
|
|
1417
|
+
this.closeDropdown();
|
|
1418
|
+
}
|
|
1419
|
+
else {
|
|
1420
|
+
this.updateSelectAllButtonState();
|
|
1421
|
+
}
|
|
1352
1422
|
}
|
|
1353
1423
|
else {
|
|
1354
|
-
if (this._config.debug)
|
|
1355
|
-
console.log('Multiple select mode - keeping dropdown open for additional selections');
|
|
1356
1424
|
// Don't close dropdown in multiple select mode to allow multiple selections
|
|
1357
1425
|
this.updateSelectAllButtonState();
|
|
1358
1426
|
}
|
|
@@ -1484,9 +1552,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1484
1552
|
var validSelections = currentlySelected.filter(function (value) {
|
|
1485
1553
|
return availableValues.includes(value);
|
|
1486
1554
|
});
|
|
1487
|
-
if (_this._config.debug && currentlySelected.length > 0) {
|
|
1488
|
-
console.log('update(): Preserving selections that exist in new data:', validSelections);
|
|
1489
|
-
}
|
|
1490
1555
|
// Add new options from remote data and restore selection state
|
|
1491
1556
|
items.forEach(function (item) {
|
|
1492
1557
|
var option = document.createElement('option');
|
|
@@ -1569,9 +1634,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1569
1634
|
var validSelections = currentlySelected.filter(function (value) {
|
|
1570
1635
|
return availableValues.includes(value);
|
|
1571
1636
|
});
|
|
1572
|
-
if (_this._config.debug && currentlySelected.length > 0) {
|
|
1573
|
-
console.log('reload(): Preserving selections that exist in new data:', validSelections);
|
|
1574
|
-
}
|
|
1575
1637
|
// Mark preserved selections on new options
|
|
1576
1638
|
validSelections.forEach(function (value) {
|
|
1577
1639
|
var option = Array.from(_this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
|
|
@@ -1635,9 +1697,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1635
1697
|
var validSelections = currentlySelected.filter(function (value) {
|
|
1636
1698
|
return availableValues.includes(value);
|
|
1637
1699
|
});
|
|
1638
|
-
if (_this._config.debug && currentlySelected.length > 0) {
|
|
1639
|
-
console.log('refresh(): Preserving selections that exist in new data:', validSelections);
|
|
1640
|
-
}
|
|
1641
1700
|
// Add new options and restore selection state
|
|
1642
1701
|
items.forEach(function (item) {
|
|
1643
1702
|
var option = document.createElement('option');
|
|
@@ -1816,9 +1875,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1816
1875
|
this._searchModule.refreshAfterSearch();
|
|
1817
1876
|
}
|
|
1818
1877
|
this.updateSelectAllButtonState();
|
|
1819
|
-
if (this._config.debug) {
|
|
1820
|
-
console.log('Restored original options after search clear');
|
|
1821
|
-
}
|
|
1822
1878
|
};
|
|
1823
1879
|
/**
|
|
1824
1880
|
* Update search results in the dropdown
|
|
@@ -1869,9 +1925,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1869
1925
|
}
|
|
1870
1926
|
_this._element.appendChild(optionElement);
|
|
1871
1927
|
});
|
|
1872
|
-
if (this._config.debug) {
|
|
1873
|
-
console.log("Updated original select with ".concat(items.length, " search results"));
|
|
1874
|
-
}
|
|
1875
1928
|
};
|
|
1876
1929
|
/**
|
|
1877
1930
|
* Check if dropdown is open
|
|
@@ -1996,8 +2049,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
1996
2049
|
if (val !== undefined &&
|
|
1997
2050
|
!this._config.multiple &&
|
|
1998
2051
|
this._state.isSelected(val)) {
|
|
1999
|
-
if (this._config.debug)
|
|
2000
|
-
console.log('Enter on already selected item in single-select mode. Closing.');
|
|
2001
2052
|
this.closeDropdown();
|
|
2002
2053
|
event.preventDefault();
|
|
2003
2054
|
break;
|
|
@@ -2181,8 +2232,23 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
2181
2232
|
? this._config.clearAllText
|
|
2182
2233
|
: this._config.selectAllText;
|
|
2183
2234
|
};
|
|
2235
|
+
/**
|
|
2236
|
+
* Destroy the component and clean up resources
|
|
2237
|
+
*/
|
|
2238
|
+
KTSelect.prototype.destroy = function () {
|
|
2239
|
+
// Remove from global dropdown registry
|
|
2240
|
+
KTSelect.openDropdowns.delete(this);
|
|
2241
|
+
// Close dropdown if open
|
|
2242
|
+
if (this._dropdownIsOpen) {
|
|
2243
|
+
this.closeDropdown();
|
|
2244
|
+
}
|
|
2245
|
+
// Call parent dispose method
|
|
2246
|
+
_super.prototype.dispose.call(this);
|
|
2247
|
+
};
|
|
2184
2248
|
// Static global configuration
|
|
2185
2249
|
KTSelect.globalConfig = {};
|
|
2250
|
+
// Static registry for tracking open dropdowns (global dropdown management)
|
|
2251
|
+
KTSelect.openDropdowns = new Set();
|
|
2186
2252
|
return KTSelect;
|
|
2187
2253
|
}(component_1.default));
|
|
2188
2254
|
exports.KTSelect = KTSelect;
|