@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.
Files changed (81) hide show
  1. package/dist/ktui.js +674 -225
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +13 -1
  5. package/lib/cjs/components/component.js +22 -0
  6. package/lib/cjs/components/component.js.map +1 -1
  7. package/lib/cjs/components/datatable/datatable.js +7 -1
  8. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  9. package/lib/cjs/components/drawer/drawer.js +255 -9
  10. package/lib/cjs/components/drawer/drawer.js.map +1 -1
  11. package/lib/cjs/components/dropdown/dropdown.js +55 -8
  12. package/lib/cjs/components/dropdown/dropdown.js.map +1 -1
  13. package/lib/cjs/components/select/combobox.js +0 -2
  14. package/lib/cjs/components/select/combobox.js.map +1 -1
  15. package/lib/cjs/components/select/config.js +4 -1
  16. package/lib/cjs/components/select/config.js.map +1 -1
  17. package/lib/cjs/components/select/dropdown.js +0 -16
  18. package/lib/cjs/components/select/dropdown.js.map +1 -1
  19. package/lib/cjs/components/select/remote.js +0 -40
  20. package/lib/cjs/components/select/remote.js.map +1 -1
  21. package/lib/cjs/components/select/search.js +93 -22
  22. package/lib/cjs/components/select/search.js.map +1 -1
  23. package/lib/cjs/components/select/select.js +180 -114
  24. package/lib/cjs/components/select/select.js.map +1 -1
  25. package/lib/cjs/components/select/tags.js +0 -2
  26. package/lib/cjs/components/select/tags.js.map +1 -1
  27. package/lib/cjs/components/sticky/sticky.js +44 -5
  28. package/lib/cjs/components/sticky/sticky.js.map +1 -1
  29. package/lib/cjs/helpers/data.js +8 -0
  30. package/lib/cjs/helpers/data.js.map +1 -1
  31. package/lib/cjs/helpers/event-handler.js +6 -5
  32. package/lib/cjs/helpers/event-handler.js.map +1 -1
  33. package/lib/cjs/index.js.map +1 -1
  34. package/lib/esm/components/component.js +22 -0
  35. package/lib/esm/components/component.js.map +1 -1
  36. package/lib/esm/components/datatable/datatable.js +7 -1
  37. package/lib/esm/components/datatable/datatable.js.map +1 -1
  38. package/lib/esm/components/drawer/drawer.js +255 -9
  39. package/lib/esm/components/drawer/drawer.js.map +1 -1
  40. package/lib/esm/components/dropdown/dropdown.js +55 -8
  41. package/lib/esm/components/dropdown/dropdown.js.map +1 -1
  42. package/lib/esm/components/select/combobox.js +0 -2
  43. package/lib/esm/components/select/combobox.js.map +1 -1
  44. package/lib/esm/components/select/config.js +4 -1
  45. package/lib/esm/components/select/config.js.map +1 -1
  46. package/lib/esm/components/select/dropdown.js +0 -16
  47. package/lib/esm/components/select/dropdown.js.map +1 -1
  48. package/lib/esm/components/select/remote.js +0 -40
  49. package/lib/esm/components/select/remote.js.map +1 -1
  50. package/lib/esm/components/select/search.js +93 -22
  51. package/lib/esm/components/select/search.js.map +1 -1
  52. package/lib/esm/components/select/select.js +180 -114
  53. package/lib/esm/components/select/select.js.map +1 -1
  54. package/lib/esm/components/select/tags.js +0 -2
  55. package/lib/esm/components/select/tags.js.map +1 -1
  56. package/lib/esm/components/sticky/sticky.js +44 -5
  57. package/lib/esm/components/sticky/sticky.js.map +1 -1
  58. package/lib/esm/helpers/data.js +8 -0
  59. package/lib/esm/helpers/data.js.map +1 -1
  60. package/lib/esm/helpers/event-handler.js +6 -5
  61. package/lib/esm/helpers/event-handler.js.map +1 -1
  62. package/lib/esm/index.js.map +1 -1
  63. package/package.json +6 -4
  64. package/src/components/component.ts +26 -0
  65. package/src/components/datatable/__tests__/race-conditions.test.ts +7 -7
  66. package/src/components/datatable/datatable.ts +8 -1
  67. package/src/components/drawer/drawer.ts +266 -10
  68. package/src/components/dropdown/dropdown.ts +63 -8
  69. package/src/components/select/__tests__/ux-behaviors.test.ts +997 -0
  70. package/src/components/select/combobox.ts +0 -1
  71. package/src/components/select/config.ts +7 -1
  72. package/src/components/select/dropdown.ts +0 -24
  73. package/src/components/select/remote.ts +0 -49
  74. package/src/components/select/search.ts +97 -24
  75. package/src/components/select/select.css +5 -1
  76. package/src/components/select/select.ts +211 -153
  77. package/src/components/select/tags.ts +0 -1
  78. package/src/components/sticky/sticky.ts +55 -5
  79. package/src/helpers/data.ts +10 -0
  80. package/src/helpers/event-handler.ts +7 -6
  81. 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
- this._searchInputElement = this._dropdownContentElement.querySelector("[data-kt-select-search]");
647
- // If not found in dropdown, check if it's the display element itself
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 (this._config.debug)
826
- console.log('Opening dropdown via dropdownModule...');
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 event
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._focusSelectedOption();
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 (this._config.debug)
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.debug)
1317
- console.log('Early return from toggleSelection - already selected in single select mode');
1318
- return;
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, always close the dropdown after selection
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 (this._config.debug)
1350
- console.log('About to call closeDropdown() for single select mode - always close after selection');
1351
- this.closeDropdown();
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;