@keenthemes/ktui 1.0.10 → 1.0.12

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 (139) hide show
  1. package/README.md +2 -2
  2. package/dist/ktui.js +1283 -1100
  3. package/dist/ktui.min.js +1 -1
  4. package/dist/ktui.min.js.map +1 -1
  5. package/examples/select/basic-usage.html +43 -0
  6. package/examples/select/combobox-icons.html +58 -0
  7. package/examples/select/combobox.html +46 -0
  8. package/examples/select/description.html +69 -0
  9. package/examples/select/disable-option.html +43 -0
  10. package/examples/select/disable-select.html +34 -0
  11. package/examples/select/icon-description.html +56 -0
  12. package/examples/select/icon-multiple.html +58 -0
  13. package/examples/select/icon.html +58 -0
  14. package/examples/select/max-selection.html +39 -0
  15. package/examples/select/modal.html +70 -0
  16. package/examples/select/multiple.html +42 -0
  17. package/examples/select/placeholder.html +43 -0
  18. package/examples/select/remote-data.html +32 -0
  19. package/examples/select/search.html +49 -0
  20. package/examples/select/tags-icons.html +58 -0
  21. package/examples/select/tags-selected.html +59 -0
  22. package/examples/select/tags.html +58 -0
  23. package/examples/select/template-customization.html +65 -0
  24. package/examples/select/test.html +94 -0
  25. package/examples/toast/example.html +427 -0
  26. package/lib/cjs/components/component.js +1 -1
  27. package/lib/cjs/components/component.js.map +1 -1
  28. package/lib/cjs/components/datatable/datatable.js +22 -6
  29. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  30. package/lib/cjs/components/modal/modal.js +0 -4
  31. package/lib/cjs/components/modal/modal.js.map +1 -1
  32. package/lib/cjs/components/select/combobox.js +38 -120
  33. package/lib/cjs/components/select/combobox.js.map +1 -1
  34. package/lib/cjs/components/select/config.js +4 -16
  35. package/lib/cjs/components/select/config.js.map +1 -1
  36. package/lib/cjs/components/select/dropdown.js +10 -49
  37. package/lib/cjs/components/select/dropdown.js.map +1 -1
  38. package/lib/cjs/components/select/index.js +2 -1
  39. package/lib/cjs/components/select/index.js.map +1 -1
  40. package/lib/cjs/components/select/option.js +21 -4
  41. package/lib/cjs/components/select/option.js.map +1 -1
  42. package/lib/cjs/components/select/remote.js +1 -37
  43. package/lib/cjs/components/select/remote.js.map +1 -1
  44. package/lib/cjs/components/select/search.js +11 -41
  45. package/lib/cjs/components/select/search.js.map +1 -1
  46. package/lib/cjs/components/select/select.js +213 -326
  47. package/lib/cjs/components/select/select.js.map +1 -1
  48. package/lib/cjs/components/select/tags.js +39 -31
  49. package/lib/cjs/components/select/tags.js.map +1 -1
  50. package/lib/cjs/components/select/templates.js +120 -179
  51. package/lib/cjs/components/select/templates.js.map +1 -1
  52. package/lib/cjs/components/select/types.js +0 -12
  53. package/lib/cjs/components/select/types.js.map +1 -1
  54. package/lib/cjs/components/select/utils.js +204 -257
  55. package/lib/cjs/components/select/utils.js.map +1 -1
  56. package/lib/cjs/components/toast/index.js +10 -0
  57. package/lib/cjs/components/toast/index.js.map +1 -0
  58. package/lib/cjs/components/toast/toast.js +543 -0
  59. package/lib/cjs/components/toast/toast.js.map +1 -0
  60. package/lib/cjs/components/toast/types.js +7 -0
  61. package/lib/cjs/components/toast/types.js.map +1 -0
  62. package/lib/cjs/helpers/dom.js +24 -0
  63. package/lib/cjs/helpers/dom.js.map +1 -1
  64. package/lib/cjs/index.js +5 -1
  65. package/lib/cjs/index.js.map +1 -1
  66. package/lib/esm/components/component.js +1 -1
  67. package/lib/esm/components/component.js.map +1 -1
  68. package/lib/esm/components/datatable/datatable.js +22 -6
  69. package/lib/esm/components/datatable/datatable.js.map +1 -1
  70. package/lib/esm/components/modal/modal.js +0 -4
  71. package/lib/esm/components/modal/modal.js.map +1 -1
  72. package/lib/esm/components/select/combobox.js +39 -121
  73. package/lib/esm/components/select/combobox.js.map +1 -1
  74. package/lib/esm/components/select/config.js +3 -15
  75. package/lib/esm/components/select/config.js.map +1 -1
  76. package/lib/esm/components/select/dropdown.js +10 -49
  77. package/lib/esm/components/select/dropdown.js.map +1 -1
  78. package/lib/esm/components/select/index.js +1 -1
  79. package/lib/esm/components/select/index.js.map +1 -1
  80. package/lib/esm/components/select/option.js +21 -4
  81. package/lib/esm/components/select/option.js.map +1 -1
  82. package/lib/esm/components/select/remote.js +1 -37
  83. package/lib/esm/components/select/remote.js.map +1 -1
  84. package/lib/esm/components/select/search.js +12 -42
  85. package/lib/esm/components/select/search.js.map +1 -1
  86. package/lib/esm/components/select/select.js +214 -327
  87. package/lib/esm/components/select/select.js.map +1 -1
  88. package/lib/esm/components/select/tags.js +39 -31
  89. package/lib/esm/components/select/tags.js.map +1 -1
  90. package/lib/esm/components/select/templates.js +119 -178
  91. package/lib/esm/components/select/templates.js.map +1 -1
  92. package/lib/esm/components/select/types.js +1 -11
  93. package/lib/esm/components/select/types.js.map +1 -1
  94. package/lib/esm/components/select/utils.js +201 -255
  95. package/lib/esm/components/select/utils.js.map +1 -1
  96. package/lib/esm/components/toast/index.js +6 -0
  97. package/lib/esm/components/toast/index.js.map +1 -0
  98. package/lib/esm/components/toast/toast.js +540 -0
  99. package/lib/esm/components/toast/toast.js.map +1 -0
  100. package/lib/esm/components/toast/types.js +6 -0
  101. package/lib/esm/components/toast/types.js.map +1 -0
  102. package/lib/esm/helpers/dom.js +24 -0
  103. package/lib/esm/helpers/dom.js.map +1 -1
  104. package/lib/esm/index.js +3 -0
  105. package/lib/esm/index.js.map +1 -1
  106. package/package.json +8 -6
  107. package/src/components/alert/alert.css +20 -2
  108. package/src/components/badge/badge.css +5 -0
  109. package/src/components/component.ts +4 -0
  110. package/src/components/datatable/datatable.ts +24 -16
  111. package/src/components/drawer/drawer.css +1 -1
  112. package/src/components/input/input.css +3 -1
  113. package/src/components/link/link.css +2 -2
  114. package/src/components/modal/modal.css +18 -2
  115. package/src/components/modal/modal.ts +0 -5
  116. package/src/components/select/combobox.ts +42 -149
  117. package/src/components/select/config.ts +38 -33
  118. package/src/components/select/dropdown.ts +8 -55
  119. package/src/components/select/index.ts +1 -1
  120. package/src/components/select/option.ts +28 -7
  121. package/src/components/select/remote.ts +2 -42
  122. package/src/components/select/search.ts +14 -54
  123. package/src/components/select/select.css +49 -0
  124. package/src/components/select/select.ts +231 -437
  125. package/src/components/select/tags.ts +40 -37
  126. package/src/components/select/templates.ts +166 -303
  127. package/src/components/select/types.ts +0 -10
  128. package/src/components/select/utils.ts +214 -304
  129. package/src/components/table/table.css +1 -1
  130. package/src/components/textarea/textarea.css +2 -1
  131. package/src/components/toast/index.ts +7 -0
  132. package/src/components/toast/toast.css +60 -0
  133. package/src/components/toast/toast.ts +605 -0
  134. package/src/components/toast/types.ts +169 -0
  135. package/src/helpers/dom.ts +30 -0
  136. package/src/index.ts +4 -0
  137. package/styles/main.css +3 -0
  138. package/styles/vars.css +138 -0
  139. package/styles.css +1 -0
@@ -52,7 +52,6 @@ var combobox_1 = require("./combobox");
52
52
  var dropdown_1 = require("./dropdown");
53
53
  var utils_1 = require("./utils");
54
54
  var tags_1 = require("./tags");
55
- var types_1 = require("./types");
56
55
  var KTSelect = /** @class */ (function (_super) {
57
56
  __extends(KTSelect, _super);
58
57
  /**
@@ -69,6 +68,7 @@ var KTSelect = /** @class */ (function (_super) {
69
68
  _this._tagsModule = null;
70
69
  _this._dropdownModule = null;
71
70
  _this._loadMoreIndicator = null;
71
+ _this._typeToSearchBuffer = new utils_1.TypeToSearchBuffer();
72
72
  // Search debounce timeout
73
73
  _this._searchDebounceTimeout = null;
74
74
  // Store original options HTML for restoring after search
@@ -153,11 +153,6 @@ var KTSelect = /** @class */ (function (_super) {
153
153
  // Keep only the empty/placeholder option and remove the rest
154
154
  var options = Array.from(this._element.querySelectorAll('option:not([value=""])'));
155
155
  options.forEach(function (option) { return option.remove(); });
156
- // Ensure we have at least an empty option
157
- if (this._element.querySelectorAll('option').length === 0) {
158
- var emptyOption = templates_1.defaultTemplates.emptyOption(__assign(__assign({}, this._config), { placeholder: this._config.placeholder }));
159
- this._element.appendChild(emptyOption);
160
- }
161
156
  };
162
157
  /**
163
158
  * Helper to show a dropdown message (error, loading, noResults)
@@ -165,7 +160,7 @@ var KTSelect = /** @class */ (function (_super) {
165
160
  KTSelect.prototype._showDropdownMessage = function (type, message) {
166
161
  if (!this._dropdownContentElement)
167
162
  return;
168
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
163
+ var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
169
164
  if (!optionsContainer)
170
165
  return;
171
166
  switch (type) {
@@ -175,9 +170,9 @@ var KTSelect = /** @class */ (function (_super) {
175
170
  case 'loading':
176
171
  optionsContainer.innerHTML = templates_1.defaultTemplates.loading(this._config, message || 'Loading...').outerHTML;
177
172
  break;
178
- case 'noResults':
173
+ case 'empty':
179
174
  optionsContainer.innerHTML = '';
180
- optionsContainer.appendChild(templates_1.defaultTemplates.noResults(this._config));
175
+ optionsContainer.appendChild(templates_1.defaultTemplates.empty(this._config));
181
176
  break;
182
177
  }
183
178
  };
@@ -196,14 +191,6 @@ var KTSelect = /** @class */ (function (_super) {
196
191
  * @param message Error message
197
192
  */
198
193
  KTSelect.prototype._renderErrorState = function (message) {
199
- // Create error option if the select is empty
200
- if (this._element.querySelectorAll('option').length <= 1) {
201
- var loadingOptions = this._element.querySelectorAll('option[disabled]:not([value])');
202
- loadingOptions.forEach(function (option) { return option.remove(); });
203
- // Use template function for error option instead of hardcoded element
204
- var errorOption = templates_1.defaultTemplates.errorOption(__assign(__assign({}, this._config), { errorMessage: message }));
205
- this._element.appendChild(errorOption);
206
- }
207
194
  // If dropdown is already created, show error message there
208
195
  this._showDropdownMessage('error', message);
209
196
  if (!this._wrapperElement) {
@@ -226,7 +213,7 @@ var KTSelect = /** @class */ (function (_super) {
226
213
  // Create load more button using template
227
214
  this._loadMoreIndicator = templates_1.defaultTemplates.loadMore(this._config);
228
215
  // Add to dropdown
229
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
216
+ var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
230
217
  if (optionsContainer) {
231
218
  optionsContainer.appendChild(this._loadMoreIndicator);
232
219
  }
@@ -296,42 +283,26 @@ var KTSelect = /** @class */ (function (_super) {
296
283
  * @param newItems New items to add to the dropdown
297
284
  */
298
285
  KTSelect.prototype._updateOptionsInDropdown = function (newItems) {
299
- var _this = this;
300
286
  if (!this._dropdownContentElement || !newItems.length)
301
287
  return;
302
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
288
+ var optionsContainer = this._dropdownContentElement.querySelector("[data-kt-select-options]");
303
289
  if (!optionsContainer)
304
290
  return;
305
291
  // Get the load more button
306
- var loadMoreButton = optionsContainer.querySelector('[data-kt-select-load-more]');
292
+ var loadMoreButton = optionsContainer.querySelector("[data-kt-select-load-more]");
307
293
  // Process each new item
308
294
  newItems.forEach(function (item) {
309
295
  // Create option for the original select
310
- var selectOption = templates_1.defaultTemplates.emptyOption(__assign(__assign({}, _this._config), { placeholder: item.title || 'Unnamed option' }));
296
+ var selectOption = document.createElement('option');
311
297
  selectOption.value = item.id || '';
312
- // Add description and icon attributes if available and valid
313
- if (item.description &&
314
- item.description !== 'null' &&
315
- item.description !== 'undefined') {
316
- selectOption.setAttribute('data-kt-select-option-description', item.description);
317
- }
318
- if (item.icon && item.icon !== 'null' && item.icon !== 'undefined') {
319
- selectOption.setAttribute('data-kt-select-option-icon', item.icon);
320
- }
321
- // Add the option to the original select element
322
- _this._element.appendChild(selectOption);
323
- // Create option element for the dropdown using the KTSelectOption class
324
- // This ensures consistent option rendering
325
- var ktOption = new option_1.KTSelectOption(selectOption, _this._config);
326
- var renderedOption = ktOption.render();
327
298
  // Add to dropdown container
328
299
  if (loadMoreButton) {
329
300
  // Insert before the load more button
330
- optionsContainer.insertBefore(renderedOption, loadMoreButton);
301
+ optionsContainer.insertBefore(selectOption, loadMoreButton);
331
302
  }
332
303
  else {
333
304
  // Append to the end
334
- optionsContainer.appendChild(renderedOption);
305
+ optionsContainer.appendChild(selectOption);
335
306
  }
336
307
  });
337
308
  // Update options NodeList to include the new options
@@ -353,7 +324,7 @@ var KTSelect = /** @class */ (function (_super) {
353
324
  this._setupElementReferences();
354
325
  this._initZIndex();
355
326
  // Initialize options
356
- this._initializeOptionsHtml();
327
+ // this._initializeOptionsHtml();
357
328
  this._preSelectOptions(this._element);
358
329
  // Apply disabled state if needed
359
330
  this._applyInitialDisabledState();
@@ -362,11 +333,11 @@ var KTSelect = /** @class */ (function (_super) {
362
333
  this._initializeSearchModule();
363
334
  }
364
335
  // Initialize combobox if enabled
365
- if (this._config.mode === types_1.SelectMode.COMBOBOX) {
336
+ if (this._config.combobox) {
366
337
  this._comboboxModule = new combobox_1.KTSelectCombobox(this);
367
338
  }
368
339
  // Initialize tags if enabled
369
- if (this._config.mode === types_1.SelectMode.TAGS) {
340
+ if (this._config.tags) {
370
341
  this._tagsModule = new tags_1.KTSelectTags(this);
371
342
  }
372
343
  // Initialize focus manager after dropdown element is created
@@ -383,31 +354,37 @@ var KTSelect = /** @class */ (function (_super) {
383
354
  /**
384
355
  * Initialize options HTML from data
385
356
  */
386
- KTSelect.prototype._initializeOptionsHtml = function () {
387
- this._generateOptionsHtml(this._element);
388
- };
357
+ // private _initializeOptionsHtml() {
358
+ // this._generateOptionsHtml(this._element);
359
+ // }
389
360
  /**
390
361
  * Creates the HTML structure for the select component
391
362
  */
392
363
  KTSelect.prototype._createHtmlStructure = function () {
364
+ var _a;
393
365
  var _this = this;
394
366
  var options = Array.from(this._element.querySelectorAll('option'));
395
367
  // Create wrapper and display elements
396
- var wrapperElement = templates_1.defaultTemplates.main(this._config);
368
+ var wrapperElement = templates_1.defaultTemplates.wrapper(this._config);
397
369
  var displayElement = templates_1.defaultTemplates.display(this._config);
398
370
  // Add the display element to the wrapper
399
371
  wrapperElement.appendChild(displayElement);
372
+ // Move classes from original select to display element
373
+ if (this._element.classList.length > 0) {
374
+ (_a = displayElement.classList).add.apply(_a, Array.from(this._element.classList));
375
+ this._element.className = '';
376
+ }
400
377
  // Create an empty dropdown first (without options) using template
401
- var dropdownElement = templates_1.defaultTemplates.dropdownContent(__assign(__assign({}, this._config), { zindex: this._config.dropdownZindex }));
378
+ var dropdownElement = templates_1.defaultTemplates.dropdown(__assign(__assign({}, this._config), { zindex: this._config.dropdownZindex }));
402
379
  // Add search input if needed
403
- var isCombobox = this._config.mode === types_1.SelectMode.COMBOBOX;
404
- var hasSearch = this._config.enableSearch && !isCombobox;
405
- if (hasSearch) {
380
+ if (this._config.enableSearch) {
406
381
  var searchElement = templates_1.defaultTemplates.search(this._config);
407
382
  dropdownElement.appendChild(searchElement);
408
383
  }
409
384
  // Create options container using template
410
- var optionsContainer = templates_1.defaultTemplates.optionsContainer(this._config);
385
+ var optionsContainer = templates_1.defaultTemplates.options(this._config);
386
+ // Clear the options container
387
+ optionsContainer.innerHTML = '';
411
388
  // Add each option directly to the container
412
389
  options.forEach(function (optionElement) {
413
390
  // Skip empty placeholder options (only if BOTH value AND text are empty)
@@ -438,20 +415,17 @@ var KTSelect = /** @class */ (function (_super) {
438
415
  // Get display element
439
416
  this._displayElement = this._wrapperElement.querySelector("[data-kt-select-display]");
440
417
  // Get dropdown content element - this is critical for dropdown functionality
441
- this._dropdownContentElement = this._wrapperElement.querySelector("[data-kt-select-dropdown-content]");
418
+ this._dropdownContentElement = this._wrapperElement.querySelector("[data-kt-select-dropdown]");
442
419
  if (!this._dropdownContentElement) {
420
+ console.log(this._element);
443
421
  console.error('Dropdown content element not found', this._wrapperElement);
444
422
  }
445
423
  // Get search input element - this is used for the search functionality
446
- // First check if it's in dropdown, then check if it's in display (for combobox)
447
424
  this._searchInputElement = this._dropdownContentElement.querySelector("[data-kt-select-search]");
448
- // If not found in dropdown, check if it's the display element itself (for combobox)
449
- if (!this._searchInputElement &&
450
- this._config.mode === types_1.SelectMode.COMBOBOX) {
425
+ // If not found in dropdown, check if it's the display element itself
426
+ if (!this._searchInputElement) {
451
427
  this._searchInputElement = this._displayElement;
452
428
  }
453
- if (this._config.debug)
454
- console.log('Search input found:', this._searchInputElement ? 'Yes' : 'No', 'Mode:', this._config.mode, 'EnableSearch:', this._config.enableSearch);
455
429
  this._valueDisplayElement = this._wrapperElement.querySelector("[data-kt-select-value]");
456
430
  this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
457
431
  };
@@ -461,17 +435,18 @@ var KTSelect = /** @class */ (function (_super) {
461
435
  KTSelect.prototype._attachEventListeners = function () {
462
436
  // Document level event listeners
463
437
  document.addEventListener('click', this._handleDocumentClick.bind(this));
464
- document.addEventListener('keydown', this._handleEscKey.bind(this));
465
438
  // Dropdown option click events
466
439
  this._eventManager.addListener(this._dropdownContentElement, 'click', this._handleDropdownOptionClick.bind(this));
467
440
  // Only attach click handler to display element
468
- this._eventManager.addListener(this._displayElement, 'click', this._handleDropdownClick.bind(this));
469
- // Only attach keyboard navigation to display element if NOT in combobox mode
470
- // This prevents conflicts with the combobox module's keyboard handler
471
- if (this._config.mode !== types_1.SelectMode.COMBOBOX) {
472
- if (this._config.debug)
473
- console.log('Attaching keyboard navigation to display element (non-combobox mode)');
474
- this._eventManager.addListener(this._displayElement, 'keydown', this._handleDropdownKeyDown.bind(this));
441
+ // this._eventManager.addListener(
442
+ // this._wrapperElement,
443
+ // 'click',
444
+ // this._handleDropdownClick.bind(this),
445
+ // );
446
+ // Attach centralized keyboard handler
447
+ var keyboardTarget = this._searchInputElement || this._wrapperElement;
448
+ if (keyboardTarget) {
449
+ keyboardTarget.addEventListener('keydown', this._handleKeyboardEvent.bind(this));
475
450
  }
476
451
  };
477
452
  /**
@@ -541,52 +516,12 @@ var KTSelect = /** @class */ (function (_super) {
541
516
  label =
542
517
  extractedLabel !== null ? String(extractedLabel) : 'Unnamed option';
543
518
  }
544
- // Get description - skip if null, undefined, or "null" string
545
- var description = null;
546
- if (item.description !== undefined &&
547
- item.description !== null &&
548
- String(item.description) !== 'null' &&
549
- String(item.description) !== 'undefined') {
550
- description = String(item.description);
551
- }
552
- else if (_this._config.dataFieldDescription) {
553
- var extractedDesc = _this._getValueByKey(item, _this._config.dataFieldDescription);
554
- if (extractedDesc !== null &&
555
- extractedDesc !== undefined &&
556
- String(extractedDesc) !== 'null' &&
557
- String(extractedDesc) !== 'undefined') {
558
- description = String(extractedDesc);
559
- }
560
- }
561
- // Get icon - skip if null, undefined, or "null" string
562
- var icon = null;
563
- if (item.icon !== undefined &&
564
- item.icon !== null &&
565
- String(item.icon) !== 'null' &&
566
- String(item.icon) !== 'undefined') {
567
- icon = String(item.icon);
568
- }
569
- else if (_this._config.dataFieldIcon) {
570
- var extractedIcon = _this._getValueByKey(item, _this._config.dataFieldIcon);
571
- if (extractedIcon !== null &&
572
- extractedIcon !== undefined &&
573
- String(extractedIcon) !== 'null' &&
574
- String(extractedIcon) !== 'undefined') {
575
- icon = String(extractedIcon);
576
- }
577
- }
578
519
  // Log the extracted values for debugging
579
520
  if (_this._config.debug)
580
- console.log("Option: value=".concat(value, ", label=").concat(label, ", desc=").concat(description ? description : 'none', ", icon=").concat(icon ? icon : 'none'));
521
+ console.log("Option: value=".concat(value, ", label=").concat(label));
581
522
  // Set option attributes
582
523
  optionElement.value = value;
583
524
  optionElement.textContent = label || 'Unnamed option';
584
- if (description) {
585
- optionElement.setAttribute('data-kt-select-option-description', description);
586
- }
587
- if (icon) {
588
- optionElement.setAttribute('data-kt-select-option-icon', icon);
589
- }
590
525
  if (item.selected) {
591
526
  optionElement.setAttribute('selected', 'selected');
592
527
  }
@@ -656,8 +591,14 @@ var KTSelect = /** @class */ (function (_super) {
656
591
  */
657
592
  /**
658
593
  * Toggle dropdown visibility
594
+ * @deprecated
659
595
  */
660
596
  KTSelect.prototype.toggleDropdown = function () {
597
+ if (this._config.disabled) {
598
+ if (this._config.debug)
599
+ console.log('toggleDropdown: select is disabled, not opening');
600
+ return;
601
+ }
661
602
  if (this._config.debug)
662
603
  console.log('toggleDropdown called');
663
604
  if (this._dropdownModule) {
@@ -679,6 +620,11 @@ var KTSelect = /** @class */ (function (_super) {
679
620
  */
680
621
  KTSelect.prototype.openDropdown = function () {
681
622
  var _this = this;
623
+ if (this._config.disabled) {
624
+ if (this._config.debug)
625
+ console.log('openDropdown: select is disabled, not opening');
626
+ return;
627
+ }
682
628
  if (this._config.debug)
683
629
  console.log('openDropdown called, dropdownModule exists:', !!this._dropdownModule);
684
630
  if (!this._dropdownModule) {
@@ -784,6 +730,12 @@ var KTSelect = /** @class */ (function (_super) {
784
730
  * Select an option by value
785
731
  */
786
732
  KTSelect.prototype._selectOption = function (value) {
733
+ // Prevent selection if the option is disabled (in dropdown or original select)
734
+ if (this._isOptionDisabled(value)) {
735
+ if (this._config.debug)
736
+ console.log('_selectOption: Option is disabled, ignoring selection');
737
+ return;
738
+ }
787
739
  // Get current selection state
788
740
  var isSelected = this._state.isSelected(value);
789
741
  // Toggle selection in state
@@ -829,104 +781,34 @@ var KTSelect = /** @class */ (function (_super) {
829
781
  * Update selected option display value
830
782
  */
831
783
  KTSelect.prototype.updateSelectedOptionDisplay = function () {
832
- var _this = this;
833
784
  var selectedOptions = this.getSelectedOptions();
834
- if (this._config.renderSelected) {
785
+ // Tag mode: render tags if enabled
786
+ if (this._config.tags && this._tagsModule) {
787
+ this._tagsModule.updateTagsDisplay(selectedOptions);
788
+ return;
789
+ }
790
+ if (typeof this._config.renderSelected === 'function') {
835
791
  // Use the custom renderSelected function if provided
836
- this._updateValueDisplay(this._config.renderSelected(selectedOptions));
792
+ this._valueDisplayElement.innerHTML = this._config.renderSelected(selectedOptions);
837
793
  }
838
794
  else {
839
795
  if (selectedOptions.length === 0) {
840
- if (this._config.mode !== types_1.SelectMode.COMBOBOX) {
841
- this._updateValueDisplay(this._config.placeholder); // Use innerHTML for placeholder
842
- }
843
- }
844
- else if (this._config.multiple) {
845
- if (this._config.mode === types_1.SelectMode.TAGS) {
846
- // Use the tags module to render selected options as tags
847
- if (this._tagsModule) {
848
- this._tagsModule.updateTagsDisplay(selectedOptions);
849
- }
850
- else {
851
- // Fallback if tags module not initialized for some reason
852
- this._updateValueDisplay(selectedOptions.join(', '));
853
- }
854
- }
855
- else {
856
- // Render as comma-separated values
857
- var displayText = selectedOptions
858
- .map(function (option) { return _this._getOptionInnerHtml(option) || ''; })
859
- .join(', ');
860
- this._updateValueDisplay(displayText);
861
- }
796
+ var placeholder = templates_1.defaultTemplates.placeholder(this._config);
797
+ this._valueDisplayElement.replaceChildren(placeholder);
862
798
  }
863
799
  else {
864
- var selectedOption = selectedOptions[0];
865
- if (selectedOption) {
866
- var selectedText = this._getOptionInnerHtml(selectedOption);
867
- this._updateValueDisplay(selectedText);
868
- // Update combobox input value if in combobox mode
869
- if (this._config.mode === types_1.SelectMode.COMBOBOX &&
870
- this._comboboxModule) {
871
- this._comboboxModule.updateSelectedValue(selectedText);
872
- }
800
+ var content = '';
801
+ if (this._config.displayTemplate) {
802
+ var selectedValues = this.getSelectedOptions();
803
+ content = this.renderDisplayTemplateForSelected(selectedValues);
873
804
  }
874
805
  else {
875
- this._updateValueDisplay(this._config.placeholder);
806
+ // If no displayTemplate is provided, use the default comma-separated list of selected options
807
+ content = this.getSelectedOptionsText();
876
808
  }
809
+ this._valueDisplayElement.innerHTML = content;
877
810
  }
878
811
  }
879
- // Update any debug display boxes if they exist
880
- this._updateDebugDisplays();
881
- };
882
- /**
883
- * Update the value display element
884
- */
885
- KTSelect.prototype._updateValueDisplay = function (value) {
886
- if (this._config.mode === types_1.SelectMode.COMBOBOX) {
887
- // For combobox, we only update the hidden value element, not the input
888
- // The combobox module will handle updating the input value
889
- if (!this._comboboxModule) {
890
- this._valueDisplayElement.value = value;
891
- }
892
- }
893
- else {
894
- this._valueDisplayElement.innerHTML = value;
895
- }
896
- };
897
- /**
898
- * Update debug displays if present
899
- */
900
- KTSelect.prototype._updateDebugDisplays = function () {
901
- // Check if we're in a test environment with debug boxes
902
- var selectId = this.getElement().id;
903
- if (selectId) {
904
- var debugElement = document.getElementById("".concat(selectId, "-value"));
905
- if (debugElement) {
906
- var selectedOptions = this.getSelectedOptions();
907
- // Format display based on selection mode
908
- if (this._config.multiple) {
909
- // For multiple selection, show comma-separated list
910
- debugElement.textContent =
911
- selectedOptions.length > 0 ? selectedOptions.join(', ') : 'None';
912
- }
913
- else {
914
- // For single selection, show just the one value
915
- debugElement.textContent =
916
- selectedOptions.length > 0 ? selectedOptions[0] : 'None';
917
- }
918
- }
919
- }
920
- };
921
- /**
922
- * Get option inner HTML content by option value
923
- */
924
- KTSelect.prototype._getOptionInnerHtml = function (optionValue) {
925
- var option = Array.from(this._options).find(function (opt) { return opt.dataset.value === optionValue; });
926
- if (this._config.mode == types_1.SelectMode.COMBOBOX) {
927
- return option.textContent;
928
- }
929
- return option.innerHTML; // Get the entire HTML content of the option
930
812
  };
931
813
  /**
932
814
  * Update CSS classes for selected options
@@ -972,17 +854,6 @@ var KTSelect = /** @class */ (function (_super) {
972
854
  this._state.setSelectedOptions([]);
973
855
  this.updateSelectedOptionDisplay();
974
856
  this._updateSelectedOptionClass();
975
- // For combobox, also clear the input value
976
- if (this._config.mode === types_1.SelectMode.COMBOBOX) {
977
- if (this._searchInputElement) {
978
- this._searchInputElement.value = '';
979
- }
980
- // If combobox has a clear button, hide it
981
- if (this._comboboxModule) {
982
- // The combobox module will handle hiding the clear button
983
- this._comboboxModule.resetInputValueToSelection();
984
- }
985
- }
986
857
  // Dispatch change event
987
858
  this._dispatchEvent('change');
988
859
  this._fireEvent('change');
@@ -994,49 +865,6 @@ var KTSelect = /** @class */ (function (_super) {
994
865
  var values = Array.from(options).map(function (option) { return option.value; });
995
866
  this._state.setSelectedOptions(values);
996
867
  };
997
- /**
998
- * ========================================================================
999
- * KEYBOARD NAVIGATION
1000
- * ========================================================================
1001
- */
1002
- /**
1003
- * Handle dropdown key down events for keyboard navigation
1004
- * Only used for standard (non-combobox) dropdowns
1005
- */
1006
- KTSelect.prototype._handleDropdownKeyDown = function (event) {
1007
- // Log event for debugging
1008
- if (this._config.debug)
1009
- console.log('Standard dropdown keydown:', event.key);
1010
- // Use the shared handler
1011
- (0, utils_1.handleDropdownKeyNavigation)(event, this, {
1012
- multiple: this._config.multiple,
1013
- closeOnSelect: this._config.closeOnSelect,
1014
- });
1015
- };
1016
- /**
1017
- * Focus next option in dropdown
1018
- */
1019
- KTSelect.prototype._focusNextOption = function () {
1020
- return this._focusManager.focusNext();
1021
- };
1022
- /**
1023
- * Focus previous option in dropdown
1024
- */
1025
- KTSelect.prototype._focusPreviousOption = function () {
1026
- return this._focusManager.focusPrevious();
1027
- };
1028
- /**
1029
- * Apply hover/focus state to focused option
1030
- */
1031
- KTSelect.prototype._hoverFocusedOption = function (option) {
1032
- this._focusManager.applyFocus(option);
1033
- };
1034
- /**
1035
- * Scroll option into view when navigating
1036
- */
1037
- KTSelect.prototype._scrollOptionIntoView = function (option) {
1038
- this._focusManager.scrollIntoView(option);
1039
- };
1040
868
  /**
1041
869
  * Select the currently focused option
1042
870
  */
@@ -1060,44 +888,7 @@ var KTSelect = /** @class */ (function (_super) {
1060
888
  if (selectedValue) {
1061
889
  this._selectOption(selectedValue);
1062
890
  }
1063
- // For combobox mode, update input value AFTER selection to ensure consistency
1064
- if (this._config.mode === types_1.SelectMode.COMBOBOX && this._comboboxModule) {
1065
- this._comboboxModule.updateSelectedValue(selectedText);
1066
- // Also directly update the input value for immediate visual feedback
1067
- if (this._searchInputElement) {
1068
- this._searchInputElement.value = selectedText;
1069
- }
1070
- }
1071
- }
1072
- };
1073
- /**
1074
- * ========================================================================
1075
- * COMBOBOX SPECIFIC METHODS
1076
- * ========================================================================
1077
- */
1078
- /**
1079
- * Handle combobox input events
1080
- */
1081
- KTSelect.prototype._handleComboboxInput = function (event) {
1082
- if (this._comboboxModule) {
1083
- return;
1084
- }
1085
- var inputElement = event.target;
1086
- var query = inputElement.value.toLowerCase();
1087
- // If dropdown isn't open, open it when user starts typing
1088
- if (!this._dropdownIsOpen) {
1089
- this.openDropdown();
1090
891
  }
1091
- // Filter options based on input
1092
- this._filterOptionsForCombobox(query);
1093
- };
1094
- /**
1095
- * Filter options for combobox based on input query
1096
- * Uses the shared filterOptions function
1097
- */
1098
- KTSelect.prototype._filterOptionsForCombobox = function (query) {
1099
- var options = Array.from(this._dropdownContentElement.querySelectorAll('[data-kt-select-option]'));
1100
- (0, utils_1.filterOptions)(options, query, this._config, this._dropdownContentElement);
1101
892
  };
1102
893
  /**
1103
894
  * ========================================================================
@@ -1106,6 +897,7 @@ var KTSelect = /** @class */ (function (_super) {
1106
897
  */
1107
898
  /**
1108
899
  * Handle display element click
900
+ * @deprecated
1109
901
  */
1110
902
  KTSelect.prototype._handleDropdownClick = function (event) {
1111
903
  if (this._config.debug)
@@ -1167,14 +959,6 @@ var KTSelect = /** @class */ (function (_super) {
1167
959
  this.closeDropdown();
1168
960
  }
1169
961
  };
1170
- /**
1171
- * Handle escape key press
1172
- */
1173
- KTSelect.prototype._handleEscKey = function (event) {
1174
- if (event.key === 'Escape' && this._dropdownIsOpen) {
1175
- this.closeDropdown();
1176
- }
1177
- };
1178
962
  /**
1179
963
  * ========================================================================
1180
964
  * ACCESSIBILITY METHODS
@@ -1186,18 +970,6 @@ var KTSelect = /** @class */ (function (_super) {
1186
970
  KTSelect.prototype._setAriaAttributes = function () {
1187
971
  this._displayElement.setAttribute('aria-expanded', this._dropdownIsOpen.toString());
1188
972
  };
1189
- /**
1190
- * Handle focus events
1191
- */
1192
- KTSelect.prototype._handleFocus = function () {
1193
- // Implementation pending
1194
- };
1195
- /**
1196
- * Handle blur events
1197
- */
1198
- KTSelect.prototype._handleBlur = function () {
1199
- // Implementation pending
1200
- };
1201
973
  /**
1202
974
  * ========================================================================
1203
975
  * PUBLIC API
@@ -1266,7 +1038,7 @@ var KTSelect = /** @class */ (function (_super) {
1266
1038
  }
1267
1039
  });
1268
1040
  // If search input exists, clear it
1269
- if (this._searchInputElement && this._config.mode !== types_1.SelectMode.COMBOBOX) {
1041
+ if (this._searchInputElement) {
1270
1042
  this._searchInputElement.value = '';
1271
1043
  // If we have a search module, clear any search filtering
1272
1044
  if (this._searchModule) {
@@ -1290,6 +1062,12 @@ var KTSelect = /** @class */ (function (_super) {
1290
1062
  * Toggle the selection of an option
1291
1063
  */
1292
1064
  KTSelect.prototype.toggleSelection = function (value) {
1065
+ // Prevent selection if the option is disabled (in dropdown or original select)
1066
+ if (this._isOptionDisabled(value)) {
1067
+ if (this._config.debug)
1068
+ console.log('toggleSelection: Option is disabled, ignoring selection');
1069
+ return;
1070
+ }
1293
1071
  // Get current selection state
1294
1072
  var isSelected = this._state.isSelected(value);
1295
1073
  if (this._config.debug)
@@ -1457,7 +1235,7 @@ var KTSelect = /** @class */ (function (_super) {
1457
1235
  */
1458
1236
  KTSelect.prototype._renderSearchLoadingState = function () {
1459
1237
  if (!this._originalOptionsHtml && this._dropdownContentElement) {
1460
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
1238
+ var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
1461
1239
  if (optionsContainer) {
1462
1240
  this._originalOptionsHtml = optionsContainer.innerHTML;
1463
1241
  }
@@ -1476,36 +1254,26 @@ var KTSelect = /** @class */ (function (_super) {
1476
1254
  * @param items Search result items
1477
1255
  */
1478
1256
  KTSelect.prototype._updateSearchResults = function (items) {
1479
- var _this = this;
1480
1257
  if (!this._dropdownContentElement)
1481
1258
  return;
1482
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
1259
+ var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
1483
1260
  if (!optionsContainer)
1484
1261
  return;
1485
1262
  // Clear current options
1486
1263
  optionsContainer.innerHTML = '';
1487
1264
  if (items.length === 0) {
1488
1265
  // Show no results message using template for consistency and customization
1489
- var noResultsElement = templates_1.defaultTemplates.noResults(this._config);
1266
+ var noResultsElement = templates_1.defaultTemplates.empty(this._config);
1490
1267
  optionsContainer.appendChild(noResultsElement);
1491
1268
  return;
1492
1269
  }
1493
1270
  // Process each item individually to create options
1494
1271
  items.forEach(function (item) {
1495
1272
  // Create option for the original select
1496
- var selectOption = templates_1.defaultTemplates.emptyOption(__assign(__assign({}, _this._config), { placeholder: item.title }));
1273
+ var selectOption = document.createElement('option');
1497
1274
  selectOption.value = item.id;
1498
- if (item.description) {
1499
- selectOption.setAttribute('data-kt-select-option-description', item.description);
1500
- }
1501
- if (item.icon) {
1502
- selectOption.setAttribute('data-kt-select-option-icon', item.icon);
1503
- }
1504
- // Create option element for the dropdown
1505
- var ktOption = new option_1.KTSelectOption(selectOption, _this._config);
1506
- var renderedOption = ktOption.render();
1507
1275
  // Add to dropdown container
1508
- optionsContainer.appendChild(renderedOption);
1276
+ optionsContainer.appendChild(selectOption);
1509
1277
  });
1510
1278
  // Add pagination "Load More" button if needed
1511
1279
  if (this._config.pagination && this._remoteModule.hasMorePages()) {
@@ -1514,18 +1282,137 @@ var KTSelect = /** @class */ (function (_super) {
1514
1282
  // Update options NodeList
1515
1283
  this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
1516
1284
  };
1517
- /**
1518
- * Filter options by query
1519
- */
1520
- KTSelect.prototype.filterOptions = function (query) {
1521
- this._filterOptionsForCombobox(query);
1522
- };
1523
1285
  /**
1524
1286
  * Check if dropdown is open
1525
1287
  */
1526
1288
  KTSelect.prototype.isDropdownOpen = function () {
1527
1289
  return this._dropdownIsOpen;
1528
1290
  };
1291
+ KTSelect.prototype.getSelectedOptionsText = function () {
1292
+ var _this = this;
1293
+ var selectedValues = this.getSelectedOptions();
1294
+ var displaySeparator = this._config.displaySeparator || ', ';
1295
+ var texts = selectedValues.map(function (value) {
1296
+ var option = Array.from(_this._options).find(function (opt) { return opt.getAttribute('data-value') === value; });
1297
+ return (option === null || option === void 0 ? void 0 : option.getAttribute('data-text')) || '';
1298
+ }).filter(Boolean);
1299
+ return texts.join(displaySeparator);
1300
+ };
1301
+ /**
1302
+ * Check if an option is disabled (either in dropdown or original select)
1303
+ */
1304
+ KTSelect.prototype._isOptionDisabled = function (value) {
1305
+ var dropdownOption = Array.from(this._options).find(function (opt) { return opt.getAttribute('data-value') === value; });
1306
+ var isDropdownDisabled = dropdownOption && (dropdownOption.classList.contains('disabled') || dropdownOption.getAttribute('aria-disabled') === 'true');
1307
+ var selectOption = Array.from(this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
1308
+ var isNativeDisabled = selectOption && selectOption.disabled;
1309
+ return Boolean(isDropdownDisabled || isNativeDisabled);
1310
+ };
1311
+ /**
1312
+ * Centralized keyboard event handler for all select modes
1313
+ */
1314
+ KTSelect.prototype._handleKeyboardEvent = function (event) {
1315
+ var isOpen = this._dropdownIsOpen;
1316
+ var config = this._config;
1317
+ var focusManager = this._focusManager;
1318
+ var buffer = this._typeToSearchBuffer;
1319
+ // Ignore modifier keys
1320
+ if (event.altKey || event.ctrlKey || event.metaKey)
1321
+ return;
1322
+ // Type-to-search: only for single char keys
1323
+ if (event.key.length === 1 && !event.repeat && !event.key.match(/\s/)) {
1324
+ buffer.push(event.key);
1325
+ var str = buffer.getBuffer();
1326
+ focusManager.focusByString(str);
1327
+ return;
1328
+ }
1329
+ switch (event.key) {
1330
+ case 'ArrowDown':
1331
+ event.preventDefault();
1332
+ if (!isOpen) {
1333
+ this.openDropdown();
1334
+ }
1335
+ else {
1336
+ focusManager.focusNext();
1337
+ }
1338
+ break;
1339
+ case 'ArrowUp':
1340
+ event.preventDefault();
1341
+ if (!isOpen) {
1342
+ this.openDropdown();
1343
+ }
1344
+ else {
1345
+ focusManager.focusPrevious();
1346
+ }
1347
+ break;
1348
+ case 'Home':
1349
+ event.preventDefault();
1350
+ if (isOpen)
1351
+ focusManager.focusFirst();
1352
+ break;
1353
+ case 'End':
1354
+ event.preventDefault();
1355
+ if (isOpen)
1356
+ focusManager.focusLast();
1357
+ break;
1358
+ case 'Enter':
1359
+ case ' ': // Space
1360
+ if (isOpen) {
1361
+ var focused = focusManager.getFocusedOption();
1362
+ if (focused) {
1363
+ var value = focused.dataset.value;
1364
+ if (value) {
1365
+ this.toggleSelection(value);
1366
+ if (!config.multiple && config.closeOnSelect) {
1367
+ this.closeDropdown();
1368
+ }
1369
+ }
1370
+ }
1371
+ // Prevent form submit
1372
+ event.preventDefault();
1373
+ }
1374
+ else {
1375
+ this.openDropdown();
1376
+ }
1377
+ break;
1378
+ case 'Escape':
1379
+ if (isOpen) {
1380
+ this.closeDropdown();
1381
+ event.target.blur();
1382
+ }
1383
+ break;
1384
+ case 'Tab':
1385
+ // Let Tab propagate for normal focus movement
1386
+ break;
1387
+ default:
1388
+ break;
1389
+ }
1390
+ };
1391
+ KTSelect.prototype.renderDisplayTemplateForSelected = function (selectedValues) {
1392
+ var _this = this;
1393
+ var optionsConfig = this._config.optionsConfig || {};
1394
+ var displaySeparator = this._config.displaySeparator || ', ';
1395
+ var contentArray = Array.from(new Set(selectedValues.map(function (value) {
1396
+ var option = Array.from(_this._options).find(function (opt) { return opt.getAttribute('data-value') === value; });
1397
+ if (!option)
1398
+ return '';
1399
+ var displayTemplate = _this._config.displayTemplate;
1400
+ var text = option.getAttribute('data-text') || '';
1401
+ // Replace all {{varname}} in option.innerHTML with values from _config
1402
+ Object.entries(optionsConfig[value] || {}).forEach(function (_a) {
1403
+ var key = _a[0], val = _a[1];
1404
+ if (["string", "number", "boolean"].includes(typeof val)) {
1405
+ displayTemplate = displayTemplate.replace(new RegExp("{{".concat(key, "}}"), 'g'), String(val));
1406
+ }
1407
+ });
1408
+ return (0, utils_1.renderTemplateString)(displayTemplate, {
1409
+ selectedCount: selectedValues.length || 0,
1410
+ selectedTexts: _this.getSelectedOptionsText() || '',
1411
+ text: text,
1412
+ });
1413
+ }).filter(Boolean)));
1414
+ return contentArray.join(displaySeparator);
1415
+ };
1529
1416
  /**
1530
1417
  * ========================================================================
1531
1418
  * STATIC METHODS