@keenthemes/ktui 1.0.11 → 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 (129) hide show
  1. package/dist/ktui.js +1283 -1096
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/examples/select/basic-usage.html +43 -0
  5. package/examples/select/combobox-icons.html +58 -0
  6. package/examples/select/combobox.html +46 -0
  7. package/examples/select/description.html +69 -0
  8. package/examples/select/disable-option.html +43 -0
  9. package/examples/select/disable-select.html +34 -0
  10. package/examples/select/icon-description.html +56 -0
  11. package/examples/select/icon-multiple.html +58 -0
  12. package/examples/select/icon.html +58 -0
  13. package/examples/select/max-selection.html +39 -0
  14. package/examples/select/modal.html +70 -0
  15. package/examples/select/multiple.html +42 -0
  16. package/examples/select/placeholder.html +43 -0
  17. package/examples/select/remote-data.html +32 -0
  18. package/examples/select/search.html +49 -0
  19. package/examples/select/tags-icons.html +58 -0
  20. package/examples/select/tags-selected.html +59 -0
  21. package/examples/select/tags.html +58 -0
  22. package/examples/select/template-customization.html +65 -0
  23. package/examples/select/test.html +94 -0
  24. package/examples/toast/example.html +427 -0
  25. package/lib/cjs/components/component.js +1 -1
  26. package/lib/cjs/components/component.js.map +1 -1
  27. package/lib/cjs/components/datatable/datatable.js +22 -6
  28. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  29. package/lib/cjs/components/select/combobox.js +38 -120
  30. package/lib/cjs/components/select/combobox.js.map +1 -1
  31. package/lib/cjs/components/select/config.js +4 -16
  32. package/lib/cjs/components/select/config.js.map +1 -1
  33. package/lib/cjs/components/select/dropdown.js +10 -49
  34. package/lib/cjs/components/select/dropdown.js.map +1 -1
  35. package/lib/cjs/components/select/index.js +2 -1
  36. package/lib/cjs/components/select/index.js.map +1 -1
  37. package/lib/cjs/components/select/option.js +21 -4
  38. package/lib/cjs/components/select/option.js.map +1 -1
  39. package/lib/cjs/components/select/remote.js +1 -37
  40. package/lib/cjs/components/select/remote.js.map +1 -1
  41. package/lib/cjs/components/select/search.js +11 -41
  42. package/lib/cjs/components/select/search.js.map +1 -1
  43. package/lib/cjs/components/select/select.js +213 -326
  44. package/lib/cjs/components/select/select.js.map +1 -1
  45. package/lib/cjs/components/select/tags.js +39 -31
  46. package/lib/cjs/components/select/tags.js.map +1 -1
  47. package/lib/cjs/components/select/templates.js +120 -179
  48. package/lib/cjs/components/select/templates.js.map +1 -1
  49. package/lib/cjs/components/select/types.js +0 -12
  50. package/lib/cjs/components/select/types.js.map +1 -1
  51. package/lib/cjs/components/select/utils.js +204 -257
  52. package/lib/cjs/components/select/utils.js.map +1 -1
  53. package/lib/cjs/components/toast/index.js +10 -0
  54. package/lib/cjs/components/toast/index.js.map +1 -0
  55. package/lib/cjs/components/toast/toast.js +543 -0
  56. package/lib/cjs/components/toast/toast.js.map +1 -0
  57. package/lib/cjs/components/toast/types.js +7 -0
  58. package/lib/cjs/components/toast/types.js.map +1 -0
  59. package/lib/cjs/helpers/dom.js +24 -0
  60. package/lib/cjs/helpers/dom.js.map +1 -1
  61. package/lib/cjs/index.js +5 -1
  62. package/lib/cjs/index.js.map +1 -1
  63. package/lib/esm/components/component.js +1 -1
  64. package/lib/esm/components/component.js.map +1 -1
  65. package/lib/esm/components/datatable/datatable.js +22 -6
  66. package/lib/esm/components/datatable/datatable.js.map +1 -1
  67. package/lib/esm/components/select/combobox.js +39 -121
  68. package/lib/esm/components/select/combobox.js.map +1 -1
  69. package/lib/esm/components/select/config.js +3 -15
  70. package/lib/esm/components/select/config.js.map +1 -1
  71. package/lib/esm/components/select/dropdown.js +10 -49
  72. package/lib/esm/components/select/dropdown.js.map +1 -1
  73. package/lib/esm/components/select/index.js +1 -1
  74. package/lib/esm/components/select/index.js.map +1 -1
  75. package/lib/esm/components/select/option.js +21 -4
  76. package/lib/esm/components/select/option.js.map +1 -1
  77. package/lib/esm/components/select/remote.js +1 -37
  78. package/lib/esm/components/select/remote.js.map +1 -1
  79. package/lib/esm/components/select/search.js +12 -42
  80. package/lib/esm/components/select/search.js.map +1 -1
  81. package/lib/esm/components/select/select.js +214 -327
  82. package/lib/esm/components/select/select.js.map +1 -1
  83. package/lib/esm/components/select/tags.js +39 -31
  84. package/lib/esm/components/select/tags.js.map +1 -1
  85. package/lib/esm/components/select/templates.js +119 -178
  86. package/lib/esm/components/select/templates.js.map +1 -1
  87. package/lib/esm/components/select/types.js +1 -11
  88. package/lib/esm/components/select/types.js.map +1 -1
  89. package/lib/esm/components/select/utils.js +201 -255
  90. package/lib/esm/components/select/utils.js.map +1 -1
  91. package/lib/esm/components/toast/index.js +6 -0
  92. package/lib/esm/components/toast/index.js.map +1 -0
  93. package/lib/esm/components/toast/toast.js +540 -0
  94. package/lib/esm/components/toast/toast.js.map +1 -0
  95. package/lib/esm/components/toast/types.js +6 -0
  96. package/lib/esm/components/toast/types.js.map +1 -0
  97. package/lib/esm/helpers/dom.js +24 -0
  98. package/lib/esm/helpers/dom.js.map +1 -1
  99. package/lib/esm/index.js +3 -0
  100. package/lib/esm/index.js.map +1 -1
  101. package/package.json +8 -6
  102. package/src/components/alert/alert.css +15 -2
  103. package/src/components/component.ts +4 -0
  104. package/src/components/datatable/datatable.ts +24 -16
  105. package/src/components/input/input.css +3 -1
  106. package/src/components/link/link.css +2 -2
  107. package/src/components/select/combobox.ts +42 -149
  108. package/src/components/select/config.ts +38 -33
  109. package/src/components/select/dropdown.ts +8 -55
  110. package/src/components/select/index.ts +1 -1
  111. package/src/components/select/option.ts +28 -7
  112. package/src/components/select/remote.ts +2 -42
  113. package/src/components/select/search.ts +14 -54
  114. package/src/components/select/select.css +49 -0
  115. package/src/components/select/select.ts +231 -437
  116. package/src/components/select/tags.ts +40 -37
  117. package/src/components/select/templates.ts +166 -303
  118. package/src/components/select/types.ts +0 -10
  119. package/src/components/select/utils.ts +214 -304
  120. package/src/components/textarea/textarea.css +2 -1
  121. package/src/components/toast/index.ts +7 -0
  122. package/src/components/toast/toast.css +60 -0
  123. package/src/components/toast/toast.ts +605 -0
  124. package/src/components/toast/types.ts +169 -0
  125. package/src/helpers/dom.ts +30 -0
  126. package/src/index.ts +4 -0
  127. package/styles/main.css +3 -0
  128. package/styles/vars.css +138 -0
  129. package/styles.css +1 -0
package/dist/ktui.js CHANGED
@@ -21,7 +21,7 @@ return /******/ (function() { // webpackBootstrap
21
21
  * Copyright 2025 by Keenthemes Inc
22
22
  */
23
23
  Object.defineProperty(exports, "__esModule", ({ value: true }));
24
- exports.EventManager = exports.FocusManager = exports.filterOptions = exports.KTSelectDropdown = exports.KTSelectTags = exports.KTSelectSearch = exports.KTSelectCombobox = exports.KTSelectRemote = exports.KTSelect = void 0;
24
+ exports.TypeToSearchBuffer = exports.EventManager = exports.FocusManager = exports.filterOptions = exports.KTSelectDropdown = exports.KTSelectTags = exports.KTSelectSearch = exports.KTSelectCombobox = exports.KTSelectRemote = exports.KTSelect = void 0;
25
25
  var select_1 = __webpack_require__(8016);
26
26
  Object.defineProperty(exports, "KTSelect", ({ enumerable: true, get: function () { return select_1.KTSelect; } }));
27
27
  var remote_1 = __webpack_require__(3710);
@@ -38,6 +38,7 @@ var utils_1 = __webpack_require__(9011);
38
38
  Object.defineProperty(exports, "filterOptions", ({ enumerable: true, get: function () { return utils_1.filterOptions; } }));
39
39
  Object.defineProperty(exports, "FocusManager", ({ enumerable: true, get: function () { return utils_1.FocusManager; } }));
40
40
  Object.defineProperty(exports, "EventManager", ({ enumerable: true, get: function () { return utils_1.EventManager; } }));
41
+ Object.defineProperty(exports, "TypeToSearchBuffer", ({ enumerable: true, get: function () { return utils_1.TypeToSearchBuffer; } }));
41
42
 
42
43
 
43
44
  /***/ }),
@@ -2452,7 +2453,7 @@ var KTComponent = /** @class */ (function () {
2452
2453
  if (config === void 0) { config = {}; }
2453
2454
  if (!this._element)
2454
2455
  return;
2455
- this._config = __assign(__assign(__assign(__assign({}, this._defaultConfig), this._getGlobalConfig()), dom_1.default.getDataAttributes(this._element, this._dataOptionPrefix + this._name)), config);
2456
+ this._config = __assign(__assign(__assign(__assign(__assign({}, this._defaultConfig), this._getGlobalConfig()), dom_1.default.getDataAttributes(this._element, this._dataOptionPrefix + this._name)), dom_1.default.getDataAttributesByJson(this._element, this._dataOptionPrefix + this._name + '-config')), config);
2456
2457
  };
2457
2458
  KTComponent.prototype.dispose = function () {
2458
2459
  if (!this._element)
@@ -3266,10 +3267,8 @@ var KTSelectRemote = /** @class */ (function () {
3266
3267
  // Get the field mapping from config with fallbacks for common field names
3267
3268
  var valueField = this._config.dataValueField || 'id';
3268
3269
  var labelField = this._config.dataFieldText || 'title';
3269
- var descriptionField = this._config.dataFieldDescription || 'description';
3270
- var iconField = this._config.dataFieldIcon || 'icon';
3271
3270
  if (this._config.debug)
3272
- console.log("Mapping fields: value=".concat(valueField, ", label=").concat(labelField, ", description=").concat(descriptionField, ", icon=").concat(iconField));
3271
+ console.log("Mapping fields: value=".concat(valueField, ", label=").concat(labelField));
3273
3272
  if (this._config.debug)
3274
3273
  console.log('Item data:', JSON.stringify(item).substring(0, 200) + '...'); // Trimmed for readability
3275
3274
  // Extract values using dot notation if needed
@@ -3360,44 +3359,10 @@ var KTSelectRemote = /** @class */ (function () {
3360
3359
  if (this._config.debug)
3361
3360
  console.log('After fallback checks, title:', title);
3362
3361
  }
3363
- // Get description - make sure we don't pass null, undefined, or "null" string values
3364
- var description = getValue(item, descriptionField);
3365
- if (description === null ||
3366
- description === undefined ||
3367
- String(description) === 'null' ||
3368
- String(description) === 'undefined') {
3369
- description = null;
3370
- }
3371
- else {
3372
- description = String(description);
3373
- }
3374
- if (this._config.debug)
3375
- console.log("Description field [".concat(descriptionField, "]:"), description);
3376
- // Try to get an icon - make sure we don't pass null, undefined, or "null" string values
3377
- var icon = getValue(item, iconField);
3378
- if (icon === null ||
3379
- icon === undefined ||
3380
- String(icon) === 'null' ||
3381
- String(icon) === 'undefined') {
3382
- icon = null;
3383
- }
3384
- else {
3385
- icon = String(icon);
3386
- }
3387
- if (this._config.debug)
3388
- console.log("Icon field [".concat(iconField, "]:"), icon);
3389
- // If ID is null, use the title as fallback
3390
- if (id === null || id === '') {
3391
- id = title;
3392
- if (this._config.debug)
3393
- console.log("Using title as fallback for ID: ".concat(id));
3394
- }
3395
3362
  // Create the option object with non-empty values
3396
3363
  var result = {
3397
3364
  id: id || title || 'id-' + Math.random().toString(36).substr(2, 9), // Ensure we always have an ID
3398
3365
  title: title || 'Unnamed option',
3399
- description: description,
3400
- icon: icon,
3401
3366
  };
3402
3367
  if (this._config.debug)
3403
3368
  console.log('Final mapped item:', JSON.stringify(result));
@@ -5702,6 +5667,11 @@ var KTSelectOption = /** @class */ (function (_super) {
5702
5667
  _this._init(element);
5703
5668
  _this._buildConfig();
5704
5669
  _this._globalConfig = config;
5670
+ // Clean the config
5671
+ _this._config = _this._config[''] || {};
5672
+ // Add the option config to the global config
5673
+ _this._globalConfig.optionsConfig = _this._globalConfig.optionsConfig || {};
5674
+ _this._globalConfig.optionsConfig[element.value] = _this._config;
5705
5675
  // Don't store in KTData to avoid Singleton pattern issues
5706
5676
  // Each option should be a unique instance
5707
5677
  element.instance = _this;
@@ -5711,11 +5681,23 @@ var KTSelectOption = /** @class */ (function (_super) {
5711
5681
  return this._element;
5712
5682
  };
5713
5683
  KTSelectOption.prototype.render = function () {
5684
+ var _this = this;
5714
5685
  var optionElement = this.getHTMLOptionElement();
5715
- // Use the global config if available, or create a minimal valid config
5716
- var config = this._globalConfig || { height: 250 };
5717
- // Create a new option element every time
5718
- return templates_1.defaultTemplates.option(optionElement, config);
5686
+ // Get the original template
5687
+ var originalTemplate = this._globalConfig.optionTemplate;
5688
+ if (this._globalConfig.optionTemplate) {
5689
+ // Replace all {{varname}} in option.innerHTML with values from _config
5690
+ Object.entries(this._config || {}).forEach(function (_a) {
5691
+ var key = _a[0], value = _a[1];
5692
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
5693
+ _this._globalConfig.optionTemplate = _this._globalConfig.optionTemplate.replace(new RegExp("{{".concat(key, "}}"), 'g'), String(value));
5694
+ }
5695
+ });
5696
+ }
5697
+ var template = templates_1.defaultTemplates.option(optionElement, this._globalConfig);
5698
+ // Restore the original template
5699
+ this._globalConfig.optionTemplate = originalTemplate;
5700
+ return template;
5719
5701
  };
5720
5702
  return KTSelectOption;
5721
5703
  }(component_1.default));
@@ -6538,6 +6520,8 @@ var utils_1 = __webpack_require__(9011);
6538
6520
  */
6539
6521
  var KTSelectCombobox = /** @class */ (function () {
6540
6522
  function KTSelectCombobox(select) {
6523
+ var _this = this;
6524
+ var _a;
6541
6525
  this._select = select;
6542
6526
  this._config = select.getConfig();
6543
6527
  // Get the display element (could be the input directly or a parent div)
@@ -6547,17 +6531,36 @@ var KTSelectCombobox = /** @class */ (function () {
6547
6531
  displayElement.tagName === 'INPUT'
6548
6532
  ? displayElement
6549
6533
  : displayElement.querySelector('input[data-kt-select-search]');
6550
- // Find the clear button
6551
- this._clearButtonElement =
6552
- displayElement.tagName === 'DIV'
6553
- ? displayElement.querySelector('[data-kt-select-clear-button]')
6554
- : null;
6534
+ // Find the clear button robustly
6535
+ var clearButtonContainer = null;
6536
+ if (displayElement.tagName === 'DIV') {
6537
+ clearButtonContainer = displayElement;
6538
+ }
6539
+ else if (displayElement.tagName === 'INPUT') {
6540
+ clearButtonContainer = displayElement.parentElement;
6541
+ }
6542
+ this._clearButtonElement = clearButtonContainer
6543
+ ? clearButtonContainer.querySelector('[data-kt-select-clear-button]')
6544
+ : null;
6545
+ this._valuesContainerElement = (_a = displayElement === null || displayElement === void 0 ? void 0 : displayElement.closest('[data-kt-select-combobox]')) === null || _a === void 0 ? void 0 : _a.querySelector('[data-kt-select-combobox-values]');
6555
6546
  // Create bound handler references to allow proper cleanup
6556
- this._boundKeyNavHandler = this._handleComboboxKeyNav.bind(this);
6557
6547
  this._boundInputHandler = this._handleComboboxInput.bind(this);
6558
6548
  this._boundClearHandler = this._handleClearButtonClick.bind(this);
6559
6549
  // Attach event listeners
6560
6550
  this._attachEventListeners();
6551
+ // Reset combobox search state when dropdown closes
6552
+ this._select.getElement().addEventListener('dropdown.close', function () {
6553
+ _this._searchInputElement.value = '';
6554
+ // this._toggleClearButtonVisibility('');
6555
+ _this._select.showAllOptions();
6556
+ });
6557
+ // When selection changes, update the input value to the selected option's text
6558
+ // this._select.getElement().addEventListener('change', () => {
6559
+ // // Only update the input value, do not reset the filter or show all options
6560
+ // const selectedValues = this._select.getSelectedOptions();
6561
+ // const content = this._select.renderDisplayTemplateForSelected(selectedValues);
6562
+ // this._valuesContainerElement?.append(stringToElement(content));
6563
+ // });
6561
6564
  if (this._config.debug)
6562
6565
  console.log('KTSelectCombobox initialized');
6563
6566
  }
@@ -6569,8 +6572,6 @@ var KTSelectCombobox = /** @class */ (function () {
6569
6572
  this._removeEventListeners();
6570
6573
  // Add input event handler to filter options as user types
6571
6574
  this._searchInputElement.addEventListener('input', this._boundInputHandler);
6572
- // Add keyboard navigation for the combobox
6573
- this._searchInputElement.addEventListener('keydown', this._boundKeyNavHandler);
6574
6575
  // Add clear button click event listener
6575
6576
  if (this._clearButtonElement) {
6576
6577
  this._clearButtonElement.addEventListener('click', this._boundClearHandler);
@@ -6584,7 +6585,6 @@ var KTSelectCombobox = /** @class */ (function () {
6584
6585
  KTSelectCombobox.prototype._removeEventListeners = function () {
6585
6586
  if (this._searchInputElement) {
6586
6587
  this._searchInputElement.removeEventListener('input', this._boundInputHandler);
6587
- this._searchInputElement.removeEventListener('keydown', this._boundKeyNavHandler);
6588
6588
  }
6589
6589
  if (this._clearButtonElement) {
6590
6590
  this._clearButtonElement.removeEventListener('click', this._boundClearHandler);
@@ -6599,7 +6599,7 @@ var KTSelectCombobox = /** @class */ (function () {
6599
6599
  if (this._config.debug)
6600
6600
  console.log('Combobox input event, query:', query);
6601
6601
  // Toggle clear button visibility based on input value
6602
- this._toggleClearButtonVisibility(query);
6602
+ // this._toggleClearButtonVisibility(query);
6603
6603
  // If dropdown isn't open, open it when user starts typing
6604
6604
  if (!this._select._dropdownIsOpen) {
6605
6605
  this._select.openDropdown();
@@ -6616,12 +6616,16 @@ var KTSelectCombobox = /** @class */ (function () {
6616
6616
  // Clear the input
6617
6617
  this._searchInputElement.value = '';
6618
6618
  // Hide the clear button
6619
- this._toggleClearButtonVisibility('');
6619
+ // this._toggleClearButtonVisibility('');
6620
6620
  // Show all options and open dropdown
6621
6621
  this._select.showAllOptions();
6622
6622
  this._select.openDropdown();
6623
6623
  // Clear the current selection
6624
6624
  this._select.clearSelection();
6625
+ // Clear the combobox values container if present (for displayTemplate)
6626
+ if (this._valuesContainerElement) {
6627
+ this._valuesContainerElement.innerHTML = '';
6628
+ }
6625
6629
  // Focus on the input
6626
6630
  this._searchInputElement.focus();
6627
6631
  };
@@ -6642,115 +6646,11 @@ var KTSelectCombobox = /** @class */ (function () {
6642
6646
  * Filter options for combobox based on input query
6643
6647
  */
6644
6648
  KTSelectCombobox.prototype._filterOptionsForCombobox = function (query) {
6645
- // Access the private method through type assertion
6646
- this._select._filterOptionsForCombobox(query);
6647
- };
6648
- /**
6649
- * Handle keyboard navigation in combobox mode
6650
- */
6651
- KTSelectCombobox.prototype._handleComboboxKeyNav = function (event) {
6652
- if (this._config.debug)
6653
- console.log('Combobox keydown event:', event.key);
6654
- // Prevent event propagation to stop bubbling to other handlers
6655
- event.stopPropagation();
6656
- // Handle clear with Escape when dropdown is closed
6657
- if (event.key === 'Escape' &&
6658
- !this._select._dropdownIsOpen &&
6659
- this._searchInputElement.value !== '') {
6660
- event.preventDefault();
6661
- this._searchInputElement.value = '';
6662
- this._toggleClearButtonVisibility('');
6663
- this._select.clearSelection();
6664
- return;
6665
- }
6666
- // Handle dropdown visibility with special keys
6667
- if (!this._select._dropdownIsOpen &&
6668
- (event.key === 'ArrowDown' ||
6669
- event.key === 'ArrowUp' ||
6670
- event.key === 'Enter')) {
6671
- if (this._config.debug)
6672
- console.log('Opening dropdown from keyboard in combobox');
6673
- this._select.openDropdown();
6674
- event.preventDefault();
6675
- // If it's arrow keys, also move focus
6676
- if (event.key === 'ArrowDown') {
6677
- this._select._focusNextOption();
6678
- }
6679
- else if (event.key === 'ArrowUp') {
6680
- this._select._focusPreviousOption();
6681
- }
6682
- return;
6683
- }
6684
- // Use the shared keyboard navigation handler
6685
- (0, utils_1.handleDropdownKeyNavigation)(event, this._select, {
6686
- multiple: this._config.multiple,
6687
- closeOnSelect: this._config.closeOnSelect,
6688
- });
6689
- };
6690
- /**
6691
- * Update the combobox input value when an option is selected
6692
- */
6693
- KTSelectCombobox.prototype.updateSelectedValue = function (selectedText) {
6694
- if (this._searchInputElement) {
6695
- // Extract just the text content if it contains HTML
6696
- var cleanText = selectedText;
6697
- // If the text might contain HTML (when description is present)
6698
- if (selectedText.includes('<') || selectedText.includes('>')) {
6699
- // Create a temporary element to extract just the text
6700
- var tempDiv = document.createElement('div');
6701
- tempDiv.innerHTML = selectedText;
6702
- // Find and use only the option-title text if available
6703
- var titleElement = tempDiv.querySelector('[data-kt-option-title]');
6704
- if (titleElement) {
6705
- cleanText = titleElement.textContent || selectedText;
6706
- }
6707
- else {
6708
- // Fallback to all text content if option-title not found
6709
- cleanText = tempDiv.textContent || selectedText;
6710
- }
6711
- }
6712
- // Set the input value directly for immediate feedback
6713
- this._searchInputElement.value = cleanText;
6714
- // Show the clear button if there's a value
6715
- this._toggleClearButtonVisibility(cleanText);
6716
- // Trigger an input event to ensure any input-based listeners are notified
6717
- var inputEvent = new Event('input', { bubbles: true });
6718
- this._searchInputElement.dispatchEvent(inputEvent);
6719
- if (this._config.debug)
6720
- console.log('Combobox value updated to:', cleanText);
6721
- }
6722
- };
6723
- /**
6724
- * Reset the input value to match the current selection
6725
- * This can be called to sync the input with the current state
6726
- */
6727
- KTSelectCombobox.prototype.resetInputValueToSelection = function () {
6728
- var _a, _b;
6729
- var selectedOptions = this._select.getSelectedOptions();
6730
- if (selectedOptions.length > 0) {
6731
- var selectedOption = Array.from(this._select.getOptionsElement()).find(function (opt) { return opt.dataset.value === selectedOptions[0]; });
6732
- if (selectedOption) {
6733
- // Find the option-title element to get just the title text
6734
- var titleElement = selectedOption.querySelector('[data-kt-option-title]');
6735
- var selectedText = '';
6736
- if (titleElement) {
6737
- // If it has a structured content with a title element
6738
- selectedText = ((_a = titleElement.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '';
6739
- }
6740
- else {
6741
- // Fallback to the whole text content
6742
- selectedText = ((_b = selectedOption.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || '';
6743
- }
6744
- this.updateSelectedValue(selectedText);
6745
- }
6746
- }
6747
- else {
6748
- // No selection, clear the input
6749
- if (this._searchInputElement) {
6750
- this._searchInputElement.value = '';
6751
- this._toggleClearButtonVisibility('');
6752
- }
6753
- }
6649
+ // Use the same filter logic as KTSelectSearch
6650
+ var options = Array.from(this._select.getOptionsElement());
6651
+ var config = this._select.getConfig();
6652
+ var dropdownElement = this._select.getDropdownElement();
6653
+ (0, utils_1.filterOptions)(options, query, config, dropdownElement);
6754
6654
  };
6755
6655
  /**
6756
6656
  * Destroy the combobox component and clean up event listeners
@@ -7169,6 +7069,22 @@ var stepper_1 = __webpack_require__(770);
7169
7069
  Object.defineProperty(exports, "KTStepper", ({ enumerable: true, get: function () { return stepper_1.KTStepper; } }));
7170
7070
 
7171
7071
 
7072
+ /***/ }),
7073
+
7074
+ /***/ 6265:
7075
+ /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
7076
+
7077
+
7078
+ /**
7079
+ * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
7080
+ * Copyright 2025 by Keenthemes Inc
7081
+ */
7082
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
7083
+ exports.KTToast = void 0;
7084
+ var toast_1 = __webpack_require__(8834);
7085
+ Object.defineProperty(exports, "KTToast", ({ enumerable: true, get: function () { return toast_1.KTToast; } }));
7086
+
7087
+
7172
7088
  /***/ }),
7173
7089
 
7174
7090
  /***/ 6292:
@@ -7627,6 +7543,7 @@ var KTDataTable = /** @class */ (function (_super) {
7627
7543
  _this._originalTdClasses = []; // Store original td classes as a 2D array [row][col]
7628
7544
  _this._originalThClasses = []; // Store original th classes
7629
7545
  _this._data = [];
7546
+ _this._isFetching = false;
7630
7547
  if (data_1.default.has(element, _this._name))
7631
7548
  return _this;
7632
7549
  _this._defaultConfig = _this._initDefaultConfig(config);
@@ -7930,11 +7847,21 @@ var KTDataTable = /** @class */ (function (_super) {
7930
7847
  KTDataTable.prototype._updateData = function () {
7931
7848
  return __awaiter(this, void 0, void 0, function () {
7932
7849
  return __generator(this, function (_a) {
7933
- this._showSpinner(); // Show spinner before fetching data
7934
- // Fetch data from the DOM and initialize the checkbox plugin
7935
- return [2 /*return*/, typeof this._config.apiEndpoint === 'undefined'
7936
- ? this._fetchDataFromLocal().then(this._finalize.bind(this))
7937
- : this._fetchDataFromServer().then(this._finalize.bind(this))];
7850
+ if (this._isFetching)
7851
+ return [2 /*return*/]; // Prevent duplicate fetches
7852
+ this._isFetching = true;
7853
+ try {
7854
+ this._showSpinner(); // Show spinner before fetching data
7855
+ // Fetch data from the DOM and initialize the checkbox plugin
7856
+ return [2 /*return*/, typeof this._config.apiEndpoint === 'undefined'
7857
+ ? this._fetchDataFromLocal().then(this._finalize.bind(this))
7858
+ : this._fetchDataFromServer().then(this._finalize.bind(this))];
7859
+ }
7860
+ finally {
7861
+ this._isFetching = false;
7862
+ }
7863
+ // removed by dead control flow
7864
+ {}
7938
7865
  });
7939
7866
  });
7940
7867
  };
@@ -8374,7 +8301,13 @@ var KTDataTable = /** @class */ (function (_super) {
8374
8301
  td.className = _this._originalTdClasses[rowIndex][colIndex];
8375
8302
  }
8376
8303
  if (typeof columnDef.render === 'function') {
8377
- td.innerHTML = columnDef.render.call(_this, item[key], item, _this);
8304
+ var result = columnDef.render.call(_this, item[key], item, _this);
8305
+ if (result instanceof HTMLElement || result instanceof DocumentFragment) {
8306
+ td.appendChild(result);
8307
+ }
8308
+ else if (typeof result === 'string') {
8309
+ td.innerHTML = result;
8310
+ }
8378
8311
  }
8379
8312
  else {
8380
8313
  td.textContent = item[key];
@@ -9317,8 +9250,6 @@ var KTSelectDropdown = /** @class */ (function (_super) {
9317
9250
  KTSelectDropdown.prototype._setupEventListeners = function () {
9318
9251
  // Toggle click
9319
9252
  this._eventManager.addListener(this._toggleElement, 'click', this._handleToggleClick.bind(this));
9320
- // Keyboard navigation
9321
- this._eventManager.addListener(this._element, 'keydown', this._handleKeyDown.bind(this));
9322
9253
  // Close on outside click
9323
9254
  this._eventManager.addListener(document, 'click', this._handleOutsideClick.bind(this));
9324
9255
  };
@@ -9330,47 +9261,6 @@ var KTSelectDropdown = /** @class */ (function (_super) {
9330
9261
  event.stopPropagation();
9331
9262
  this.toggle();
9332
9263
  };
9333
- /**
9334
- * Handle keyboard events
9335
- */
9336
- KTSelectDropdown.prototype._handleKeyDown = function (event) {
9337
- if (!this._isOpen)
9338
- return;
9339
- switch (event.key) {
9340
- case 'Escape':
9341
- event.preventDefault();
9342
- this.close();
9343
- this._toggleElement.focus();
9344
- break;
9345
- case 'ArrowDown':
9346
- event.preventDefault();
9347
- this._focusManager.focusNext();
9348
- break;
9349
- case 'ArrowUp':
9350
- event.preventDefault();
9351
- this._focusManager.focusPrevious();
9352
- break;
9353
- case 'Home':
9354
- event.preventDefault();
9355
- // Focus first visible option
9356
- var firstOption = this._focusManager.getVisibleOptions()[0];
9357
- if (firstOption) {
9358
- this._focusManager.applyFocus(firstOption);
9359
- this._focusManager.scrollIntoView(firstOption);
9360
- }
9361
- break;
9362
- case 'End':
9363
- event.preventDefault();
9364
- // Focus last visible option
9365
- var visibleOptions = this._focusManager.getVisibleOptions();
9366
- var lastOption = visibleOptions[visibleOptions.length - 1];
9367
- if (lastOption) {
9368
- this._focusManager.applyFocus(lastOption);
9369
- this._focusManager.scrollIntoView(lastOption);
9370
- }
9371
- break;
9372
- }
9373
- };
9374
9264
  /**
9375
9265
  * Handle clicks outside the dropdown
9376
9266
  */
@@ -9486,6 +9376,11 @@ var KTSelectDropdown = /** @class */ (function (_super) {
9486
9376
  * Toggle the dropdown
9487
9377
  */
9488
9378
  KTSelectDropdown.prototype.toggle = function () {
9379
+ if (this._config.disabled) {
9380
+ if (this._config.debug)
9381
+ console.log('KTSelectDropdown.toggle: select is disabled, not toggling');
9382
+ return;
9383
+ }
9489
9384
  if (this._config.debug)
9490
9385
  console.log('KTSelectDropdown.toggle called - isOpen:', this._isOpen);
9491
9386
  if (this._isTransitioning) {
@@ -9505,6 +9400,11 @@ var KTSelectDropdown = /** @class */ (function (_super) {
9505
9400
  */
9506
9401
  KTSelectDropdown.prototype.open = function () {
9507
9402
  var _this = this;
9403
+ if (this._config.disabled) {
9404
+ if (this._config.debug)
9405
+ console.log('KTSelectDropdown.open: select is disabled, not opening');
9406
+ return;
9407
+ }
9508
9408
  if (this._isOpen || this._isTransitioning)
9509
9409
  return;
9510
9410
  // Fire before show event
@@ -9554,12 +9454,6 @@ var KTSelectDropdown = /** @class */ (function (_super) {
9554
9454
  if (searchInput) {
9555
9455
  searchInput.focus();
9556
9456
  }
9557
- else {
9558
- _this._focusFirstOption();
9559
- }
9560
- }
9561
- else {
9562
- _this._focusFirstOption();
9563
9457
  }
9564
9458
  // Fire after show event
9565
9459
  var afterShowEvent = new CustomEvent('kt.select.dropdown.shown', {
@@ -10003,7 +9897,6 @@ var KTSelectSearch = /** @class */ (function () {
10003
9897
  this._searchInput = select.getSearchInput();
10004
9898
  this._eventManager = new utils_1.EventManager();
10005
9899
  this._focusManager = new utils_1.FocusManager(this._select.getDropdownElement(), '[data-kt-select-option]', select.getConfig());
10006
- this._boundKeyNavHandler = this._handleKeyboardNavigation.bind(this);
10007
9900
  this.handleSearchInput = this._handleSearchInput.bind(this);
10008
9901
  this._config = select.getConfig();
10009
9902
  this._cacheOriginalOptionContents();
@@ -10043,21 +9936,13 @@ var KTSelectSearch = /** @class */ (function () {
10043
9936
  _this.refreshOptionCache();
10044
9937
  });
10045
9938
  }
10046
- // Add keyboard navigation for search results
10047
- // This is stopping event propagation to prevent conflicts
10048
- this._eventManager.addListener(this._searchInput, 'keydown', this._boundKeyNavHandler);
10049
9939
  // Listen for dropdown close to reset options if search is empty
10050
9940
  this._select.getElement().addEventListener('dropdown.close', function () {
10051
9941
  _this._focusManager.resetFocus();
10052
- // Always clear highlights when dropdown closes
10053
9942
  _this.clearSearchHighlights();
10054
- if (!_this._searchInput.value) {
10055
- _this._resetAllOptions();
10056
- }
10057
- // Clear the search input when dropdown closes if configured
10058
- if (_this._select.getConfig().clearSearchOnClose) {
10059
- _this._searchInput.value = '';
10060
- }
9943
+ _this._searchInput.value = '';
9944
+ _this._resetAllOptions();
9945
+ _this._clearNoResultsMessage();
10061
9946
  });
10062
9947
  // Clear highlights when an option is selected
10063
9948
  this._select.getElement().addEventListener('change', function () {
@@ -10097,33 +9982,6 @@ var KTSelectSearch = /** @class */ (function () {
10097
9982
  this._eventManager.removeAllListeners(this._searchInput);
10098
9983
  }
10099
9984
  };
10100
- /**
10101
- * Handle keyboard navigation for search results
10102
- */
10103
- KTSelectSearch.prototype._handleKeyboardNavigation = function (event) {
10104
- var _this = this;
10105
- // Stop propagation to prevent multiple handlers from firing
10106
- event.stopPropagation();
10107
- if (this._config.debug)
10108
- console.log('Search module keydown:', event.key);
10109
- var visibleOptions = this._focusManager.getVisibleOptions();
10110
- if (visibleOptions.length === 0)
10111
- return;
10112
- // Use the shared keyboard navigation handler with custom callbacks
10113
- (0, utils_1.handleDropdownKeyNavigation)(event, this._select, {
10114
- multiple: this._select.getConfig().multiple,
10115
- closeOnSelect: this._select.getConfig().closeOnSelect,
10116
- }, {
10117
- onArrowDown: function () { return _this._focusManager.focusNext(); },
10118
- onArrowUp: function () { return _this._focusManager.focusPrevious(); },
10119
- onEnter: function () { return _this._selectFocusedOption(); },
10120
- onClose: function () {
10121
- if (event.key === 'Escape') {
10122
- _this.clearSearchHighlights();
10123
- }
10124
- },
10125
- });
10126
- };
10127
9985
  /**
10128
9986
  * Select the currently focused option
10129
9987
  */
@@ -10253,9 +10111,9 @@ var KTSelectSearch = /** @class */ (function () {
10253
10111
  KTSelectSearch.prototype._showNoResultsMessage = function () {
10254
10112
  this._clearNoResultsMessage();
10255
10113
  var config = this._select.getConfig();
10256
- this._noResultsElement = templates_1.defaultTemplates.noResults(config);
10114
+ this._noResultsElement = templates_1.defaultTemplates.empty(config);
10257
10115
  var dropdownElement = this._select.getDropdownElement();
10258
- var optionsContainer = dropdownElement.querySelector('[data-kt-select-options-container]');
10116
+ var optionsContainer = dropdownElement.querySelector('[data-kt-select-options]');
10259
10117
  if (optionsContainer) {
10260
10118
  optionsContainer.appendChild(this._noResultsElement);
10261
10119
  }
@@ -10291,6 +10149,12 @@ var KTSelectSearch = /** @class */ (function () {
10291
10149
  */
10292
10150
  KTSelectSearch.prototype._clearDisplayHighlights = function () {
10293
10151
  // Implementation for clearing display highlights
10152
+ var options = Array.from(this._select.getOptionsElement());
10153
+ options.forEach(function (option) {
10154
+ if (option.dataset && !option.dataset.originalText) {
10155
+ option.dataset.originalText = option.innerHTML;
10156
+ }
10157
+ });
10294
10158
  };
10295
10159
  /**
10296
10160
  * This ensures that search highlighting works correctly with new options
@@ -11424,7 +11288,6 @@ var combobox_1 = __webpack_require__(5539);
11424
11288
  var dropdown_1 = __webpack_require__(7125);
11425
11289
  var utils_1 = __webpack_require__(9011);
11426
11290
  var tags_1 = __webpack_require__(8797);
11427
- var types_1 = __webpack_require__(8135);
11428
11291
  var KTSelect = /** @class */ (function (_super) {
11429
11292
  __extends(KTSelect, _super);
11430
11293
  /**
@@ -11441,6 +11304,7 @@ var KTSelect = /** @class */ (function (_super) {
11441
11304
  _this._tagsModule = null;
11442
11305
  _this._dropdownModule = null;
11443
11306
  _this._loadMoreIndicator = null;
11307
+ _this._typeToSearchBuffer = new utils_1.TypeToSearchBuffer();
11444
11308
  // Search debounce timeout
11445
11309
  _this._searchDebounceTimeout = null;
11446
11310
  // Store original options HTML for restoring after search
@@ -11525,11 +11389,6 @@ var KTSelect = /** @class */ (function (_super) {
11525
11389
  // Keep only the empty/placeholder option and remove the rest
11526
11390
  var options = Array.from(this._element.querySelectorAll('option:not([value=""])'));
11527
11391
  options.forEach(function (option) { return option.remove(); });
11528
- // Ensure we have at least an empty option
11529
- if (this._element.querySelectorAll('option').length === 0) {
11530
- var emptyOption = templates_1.defaultTemplates.emptyOption(__assign(__assign({}, this._config), { placeholder: this._config.placeholder }));
11531
- this._element.appendChild(emptyOption);
11532
- }
11533
11392
  };
11534
11393
  /**
11535
11394
  * Helper to show a dropdown message (error, loading, noResults)
@@ -11537,7 +11396,7 @@ var KTSelect = /** @class */ (function (_super) {
11537
11396
  KTSelect.prototype._showDropdownMessage = function (type, message) {
11538
11397
  if (!this._dropdownContentElement)
11539
11398
  return;
11540
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
11399
+ var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
11541
11400
  if (!optionsContainer)
11542
11401
  return;
11543
11402
  switch (type) {
@@ -11547,9 +11406,9 @@ var KTSelect = /** @class */ (function (_super) {
11547
11406
  case 'loading':
11548
11407
  optionsContainer.innerHTML = templates_1.defaultTemplates.loading(this._config, message || 'Loading...').outerHTML;
11549
11408
  break;
11550
- case 'noResults':
11409
+ case 'empty':
11551
11410
  optionsContainer.innerHTML = '';
11552
- optionsContainer.appendChild(templates_1.defaultTemplates.noResults(this._config));
11411
+ optionsContainer.appendChild(templates_1.defaultTemplates.empty(this._config));
11553
11412
  break;
11554
11413
  }
11555
11414
  };
@@ -11568,14 +11427,6 @@ var KTSelect = /** @class */ (function (_super) {
11568
11427
  * @param message Error message
11569
11428
  */
11570
11429
  KTSelect.prototype._renderErrorState = function (message) {
11571
- // Create error option if the select is empty
11572
- if (this._element.querySelectorAll('option').length <= 1) {
11573
- var loadingOptions = this._element.querySelectorAll('option[disabled]:not([value])');
11574
- loadingOptions.forEach(function (option) { return option.remove(); });
11575
- // Use template function for error option instead of hardcoded element
11576
- var errorOption = templates_1.defaultTemplates.errorOption(__assign(__assign({}, this._config), { errorMessage: message }));
11577
- this._element.appendChild(errorOption);
11578
- }
11579
11430
  // If dropdown is already created, show error message there
11580
11431
  this._showDropdownMessage('error', message);
11581
11432
  if (!this._wrapperElement) {
@@ -11598,7 +11449,7 @@ var KTSelect = /** @class */ (function (_super) {
11598
11449
  // Create load more button using template
11599
11450
  this._loadMoreIndicator = templates_1.defaultTemplates.loadMore(this._config);
11600
11451
  // Add to dropdown
11601
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
11452
+ var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
11602
11453
  if (optionsContainer) {
11603
11454
  optionsContainer.appendChild(this._loadMoreIndicator);
11604
11455
  }
@@ -11668,42 +11519,26 @@ var KTSelect = /** @class */ (function (_super) {
11668
11519
  * @param newItems New items to add to the dropdown
11669
11520
  */
11670
11521
  KTSelect.prototype._updateOptionsInDropdown = function (newItems) {
11671
- var _this = this;
11672
11522
  if (!this._dropdownContentElement || !newItems.length)
11673
11523
  return;
11674
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
11524
+ var optionsContainer = this._dropdownContentElement.querySelector("[data-kt-select-options]");
11675
11525
  if (!optionsContainer)
11676
11526
  return;
11677
11527
  // Get the load more button
11678
- var loadMoreButton = optionsContainer.querySelector('[data-kt-select-load-more]');
11528
+ var loadMoreButton = optionsContainer.querySelector("[data-kt-select-load-more]");
11679
11529
  // Process each new item
11680
11530
  newItems.forEach(function (item) {
11681
11531
  // Create option for the original select
11682
- var selectOption = templates_1.defaultTemplates.emptyOption(__assign(__assign({}, _this._config), { placeholder: item.title || 'Unnamed option' }));
11532
+ var selectOption = document.createElement('option');
11683
11533
  selectOption.value = item.id || '';
11684
- // Add description and icon attributes if available and valid
11685
- if (item.description &&
11686
- item.description !== 'null' &&
11687
- item.description !== 'undefined') {
11688
- selectOption.setAttribute('data-kt-select-option-description', item.description);
11689
- }
11690
- if (item.icon && item.icon !== 'null' && item.icon !== 'undefined') {
11691
- selectOption.setAttribute('data-kt-select-option-icon', item.icon);
11692
- }
11693
- // Add the option to the original select element
11694
- _this._element.appendChild(selectOption);
11695
- // Create option element for the dropdown using the KTSelectOption class
11696
- // This ensures consistent option rendering
11697
- var ktOption = new option_1.KTSelectOption(selectOption, _this._config);
11698
- var renderedOption = ktOption.render();
11699
11534
  // Add to dropdown container
11700
11535
  if (loadMoreButton) {
11701
11536
  // Insert before the load more button
11702
- optionsContainer.insertBefore(renderedOption, loadMoreButton);
11537
+ optionsContainer.insertBefore(selectOption, loadMoreButton);
11703
11538
  }
11704
11539
  else {
11705
11540
  // Append to the end
11706
- optionsContainer.appendChild(renderedOption);
11541
+ optionsContainer.appendChild(selectOption);
11707
11542
  }
11708
11543
  });
11709
11544
  // Update options NodeList to include the new options
@@ -11725,7 +11560,7 @@ var KTSelect = /** @class */ (function (_super) {
11725
11560
  this._setupElementReferences();
11726
11561
  this._initZIndex();
11727
11562
  // Initialize options
11728
- this._initializeOptionsHtml();
11563
+ // this._initializeOptionsHtml();
11729
11564
  this._preSelectOptions(this._element);
11730
11565
  // Apply disabled state if needed
11731
11566
  this._applyInitialDisabledState();
@@ -11734,11 +11569,11 @@ var KTSelect = /** @class */ (function (_super) {
11734
11569
  this._initializeSearchModule();
11735
11570
  }
11736
11571
  // Initialize combobox if enabled
11737
- if (this._config.mode === types_1.SelectMode.COMBOBOX) {
11572
+ if (this._config.combobox) {
11738
11573
  this._comboboxModule = new combobox_1.KTSelectCombobox(this);
11739
11574
  }
11740
11575
  // Initialize tags if enabled
11741
- if (this._config.mode === types_1.SelectMode.TAGS) {
11576
+ if (this._config.tags) {
11742
11577
  this._tagsModule = new tags_1.KTSelectTags(this);
11743
11578
  }
11744
11579
  // Initialize focus manager after dropdown element is created
@@ -11755,31 +11590,37 @@ var KTSelect = /** @class */ (function (_super) {
11755
11590
  /**
11756
11591
  * Initialize options HTML from data
11757
11592
  */
11758
- KTSelect.prototype._initializeOptionsHtml = function () {
11759
- this._generateOptionsHtml(this._element);
11760
- };
11593
+ // private _initializeOptionsHtml() {
11594
+ // this._generateOptionsHtml(this._element);
11595
+ // }
11761
11596
  /**
11762
11597
  * Creates the HTML structure for the select component
11763
11598
  */
11764
11599
  KTSelect.prototype._createHtmlStructure = function () {
11600
+ var _a;
11765
11601
  var _this = this;
11766
11602
  var options = Array.from(this._element.querySelectorAll('option'));
11767
11603
  // Create wrapper and display elements
11768
- var wrapperElement = templates_1.defaultTemplates.main(this._config);
11604
+ var wrapperElement = templates_1.defaultTemplates.wrapper(this._config);
11769
11605
  var displayElement = templates_1.defaultTemplates.display(this._config);
11770
11606
  // Add the display element to the wrapper
11771
11607
  wrapperElement.appendChild(displayElement);
11608
+ // Move classes from original select to display element
11609
+ if (this._element.classList.length > 0) {
11610
+ (_a = displayElement.classList).add.apply(_a, Array.from(this._element.classList));
11611
+ this._element.className = '';
11612
+ }
11772
11613
  // Create an empty dropdown first (without options) using template
11773
- var dropdownElement = templates_1.defaultTemplates.dropdownContent(__assign(__assign({}, this._config), { zindex: this._config.dropdownZindex }));
11614
+ var dropdownElement = templates_1.defaultTemplates.dropdown(__assign(__assign({}, this._config), { zindex: this._config.dropdownZindex }));
11774
11615
  // Add search input if needed
11775
- var isCombobox = this._config.mode === types_1.SelectMode.COMBOBOX;
11776
- var hasSearch = this._config.enableSearch && !isCombobox;
11777
- if (hasSearch) {
11616
+ if (this._config.enableSearch) {
11778
11617
  var searchElement = templates_1.defaultTemplates.search(this._config);
11779
11618
  dropdownElement.appendChild(searchElement);
11780
11619
  }
11781
11620
  // Create options container using template
11782
- var optionsContainer = templates_1.defaultTemplates.optionsContainer(this._config);
11621
+ var optionsContainer = templates_1.defaultTemplates.options(this._config);
11622
+ // Clear the options container
11623
+ optionsContainer.innerHTML = '';
11783
11624
  // Add each option directly to the container
11784
11625
  options.forEach(function (optionElement) {
11785
11626
  // Skip empty placeholder options (only if BOTH value AND text are empty)
@@ -11810,20 +11651,17 @@ var KTSelect = /** @class */ (function (_super) {
11810
11651
  // Get display element
11811
11652
  this._displayElement = this._wrapperElement.querySelector("[data-kt-select-display]");
11812
11653
  // Get dropdown content element - this is critical for dropdown functionality
11813
- this._dropdownContentElement = this._wrapperElement.querySelector("[data-kt-select-dropdown-content]");
11654
+ this._dropdownContentElement = this._wrapperElement.querySelector("[data-kt-select-dropdown]");
11814
11655
  if (!this._dropdownContentElement) {
11656
+ console.log(this._element);
11815
11657
  console.error('Dropdown content element not found', this._wrapperElement);
11816
11658
  }
11817
11659
  // Get search input element - this is used for the search functionality
11818
- // First check if it's in dropdown, then check if it's in display (for combobox)
11819
11660
  this._searchInputElement = this._dropdownContentElement.querySelector("[data-kt-select-search]");
11820
- // If not found in dropdown, check if it's the display element itself (for combobox)
11821
- if (!this._searchInputElement &&
11822
- this._config.mode === types_1.SelectMode.COMBOBOX) {
11661
+ // If not found in dropdown, check if it's the display element itself
11662
+ if (!this._searchInputElement) {
11823
11663
  this._searchInputElement = this._displayElement;
11824
11664
  }
11825
- if (this._config.debug)
11826
- console.log('Search input found:', this._searchInputElement ? 'Yes' : 'No', 'Mode:', this._config.mode, 'EnableSearch:', this._config.enableSearch);
11827
11665
  this._valueDisplayElement = this._wrapperElement.querySelector("[data-kt-select-value]");
11828
11666
  this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
11829
11667
  };
@@ -11833,17 +11671,18 @@ var KTSelect = /** @class */ (function (_super) {
11833
11671
  KTSelect.prototype._attachEventListeners = function () {
11834
11672
  // Document level event listeners
11835
11673
  document.addEventListener('click', this._handleDocumentClick.bind(this));
11836
- document.addEventListener('keydown', this._handleEscKey.bind(this));
11837
11674
  // Dropdown option click events
11838
11675
  this._eventManager.addListener(this._dropdownContentElement, 'click', this._handleDropdownOptionClick.bind(this));
11839
11676
  // Only attach click handler to display element
11840
- this._eventManager.addListener(this._displayElement, 'click', this._handleDropdownClick.bind(this));
11841
- // Only attach keyboard navigation to display element if NOT in combobox mode
11842
- // This prevents conflicts with the combobox module's keyboard handler
11843
- if (this._config.mode !== types_1.SelectMode.COMBOBOX) {
11844
- if (this._config.debug)
11845
- console.log('Attaching keyboard navigation to display element (non-combobox mode)');
11846
- this._eventManager.addListener(this._displayElement, 'keydown', this._handleDropdownKeyDown.bind(this));
11677
+ // this._eventManager.addListener(
11678
+ // this._wrapperElement,
11679
+ // 'click',
11680
+ // this._handleDropdownClick.bind(this),
11681
+ // );
11682
+ // Attach centralized keyboard handler
11683
+ var keyboardTarget = this._searchInputElement || this._wrapperElement;
11684
+ if (keyboardTarget) {
11685
+ keyboardTarget.addEventListener('keydown', this._handleKeyboardEvent.bind(this));
11847
11686
  }
11848
11687
  };
11849
11688
  /**
@@ -11913,52 +11752,12 @@ var KTSelect = /** @class */ (function (_super) {
11913
11752
  label =
11914
11753
  extractedLabel !== null ? String(extractedLabel) : 'Unnamed option';
11915
11754
  }
11916
- // Get description - skip if null, undefined, or "null" string
11917
- var description = null;
11918
- if (item.description !== undefined &&
11919
- item.description !== null &&
11920
- String(item.description) !== 'null' &&
11921
- String(item.description) !== 'undefined') {
11922
- description = String(item.description);
11923
- }
11924
- else if (_this._config.dataFieldDescription) {
11925
- var extractedDesc = _this._getValueByKey(item, _this._config.dataFieldDescription);
11926
- if (extractedDesc !== null &&
11927
- extractedDesc !== undefined &&
11928
- String(extractedDesc) !== 'null' &&
11929
- String(extractedDesc) !== 'undefined') {
11930
- description = String(extractedDesc);
11931
- }
11932
- }
11933
- // Get icon - skip if null, undefined, or "null" string
11934
- var icon = null;
11935
- if (item.icon !== undefined &&
11936
- item.icon !== null &&
11937
- String(item.icon) !== 'null' &&
11938
- String(item.icon) !== 'undefined') {
11939
- icon = String(item.icon);
11940
- }
11941
- else if (_this._config.dataFieldIcon) {
11942
- var extractedIcon = _this._getValueByKey(item, _this._config.dataFieldIcon);
11943
- if (extractedIcon !== null &&
11944
- extractedIcon !== undefined &&
11945
- String(extractedIcon) !== 'null' &&
11946
- String(extractedIcon) !== 'undefined') {
11947
- icon = String(extractedIcon);
11948
- }
11949
- }
11950
11755
  // Log the extracted values for debugging
11951
11756
  if (_this._config.debug)
11952
- console.log("Option: value=".concat(value, ", label=").concat(label, ", desc=").concat(description ? description : 'none', ", icon=").concat(icon ? icon : 'none'));
11757
+ console.log("Option: value=".concat(value, ", label=").concat(label));
11953
11758
  // Set option attributes
11954
11759
  optionElement.value = value;
11955
11760
  optionElement.textContent = label || 'Unnamed option';
11956
- if (description) {
11957
- optionElement.setAttribute('data-kt-select-option-description', description);
11958
- }
11959
- if (icon) {
11960
- optionElement.setAttribute('data-kt-select-option-icon', icon);
11961
- }
11962
11761
  if (item.selected) {
11963
11762
  optionElement.setAttribute('selected', 'selected');
11964
11763
  }
@@ -12028,8 +11827,14 @@ var KTSelect = /** @class */ (function (_super) {
12028
11827
  */
12029
11828
  /**
12030
11829
  * Toggle dropdown visibility
11830
+ * @deprecated
12031
11831
  */
12032
11832
  KTSelect.prototype.toggleDropdown = function () {
11833
+ if (this._config.disabled) {
11834
+ if (this._config.debug)
11835
+ console.log('toggleDropdown: select is disabled, not opening');
11836
+ return;
11837
+ }
12033
11838
  if (this._config.debug)
12034
11839
  console.log('toggleDropdown called');
12035
11840
  if (this._dropdownModule) {
@@ -12051,6 +11856,11 @@ var KTSelect = /** @class */ (function (_super) {
12051
11856
  */
12052
11857
  KTSelect.prototype.openDropdown = function () {
12053
11858
  var _this = this;
11859
+ if (this._config.disabled) {
11860
+ if (this._config.debug)
11861
+ console.log('openDropdown: select is disabled, not opening');
11862
+ return;
11863
+ }
12054
11864
  if (this._config.debug)
12055
11865
  console.log('openDropdown called, dropdownModule exists:', !!this._dropdownModule);
12056
11866
  if (!this._dropdownModule) {
@@ -12156,6 +11966,12 @@ var KTSelect = /** @class */ (function (_super) {
12156
11966
  * Select an option by value
12157
11967
  */
12158
11968
  KTSelect.prototype._selectOption = function (value) {
11969
+ // Prevent selection if the option is disabled (in dropdown or original select)
11970
+ if (this._isOptionDisabled(value)) {
11971
+ if (this._config.debug)
11972
+ console.log('_selectOption: Option is disabled, ignoring selection');
11973
+ return;
11974
+ }
12159
11975
  // Get current selection state
12160
11976
  var isSelected = this._state.isSelected(value);
12161
11977
  // Toggle selection in state
@@ -12201,105 +12017,35 @@ var KTSelect = /** @class */ (function (_super) {
12201
12017
  * Update selected option display value
12202
12018
  */
12203
12019
  KTSelect.prototype.updateSelectedOptionDisplay = function () {
12204
- var _this = this;
12205
12020
  var selectedOptions = this.getSelectedOptions();
12206
- if (this._config.renderSelected) {
12021
+ // Tag mode: render tags if enabled
12022
+ if (this._config.tags && this._tagsModule) {
12023
+ this._tagsModule.updateTagsDisplay(selectedOptions);
12024
+ return;
12025
+ }
12026
+ if (typeof this._config.renderSelected === 'function') {
12207
12027
  // Use the custom renderSelected function if provided
12208
- this._updateValueDisplay(this._config.renderSelected(selectedOptions));
12028
+ this._valueDisplayElement.innerHTML = this._config.renderSelected(selectedOptions);
12209
12029
  }
12210
12030
  else {
12211
12031
  if (selectedOptions.length === 0) {
12212
- if (this._config.mode !== types_1.SelectMode.COMBOBOX) {
12213
- this._updateValueDisplay(this._config.placeholder); // Use innerHTML for placeholder
12214
- }
12215
- }
12216
- else if (this._config.multiple) {
12217
- if (this._config.mode === types_1.SelectMode.TAGS) {
12218
- // Use the tags module to render selected options as tags
12219
- if (this._tagsModule) {
12220
- this._tagsModule.updateTagsDisplay(selectedOptions);
12221
- }
12222
- else {
12223
- // Fallback if tags module not initialized for some reason
12224
- this._updateValueDisplay(selectedOptions.join(', '));
12225
- }
12226
- }
12227
- else {
12228
- // Render as comma-separated values
12229
- var displayText = selectedOptions
12230
- .map(function (option) { return _this._getOptionInnerHtml(option) || ''; })
12231
- .join(', ');
12232
- this._updateValueDisplay(displayText);
12233
- }
12032
+ var placeholder = templates_1.defaultTemplates.placeholder(this._config);
12033
+ this._valueDisplayElement.replaceChildren(placeholder);
12234
12034
  }
12235
12035
  else {
12236
- var selectedOption = selectedOptions[0];
12237
- if (selectedOption) {
12238
- var selectedText = this._getOptionInnerHtml(selectedOption);
12239
- this._updateValueDisplay(selectedText);
12240
- // Update combobox input value if in combobox mode
12241
- if (this._config.mode === types_1.SelectMode.COMBOBOX &&
12242
- this._comboboxModule) {
12243
- this._comboboxModule.updateSelectedValue(selectedText);
12244
- }
12245
- }
12246
- else {
12247
- this._updateValueDisplay(this._config.placeholder);
12248
- }
12249
- }
12250
- }
12251
- // Update any debug display boxes if they exist
12252
- this._updateDebugDisplays();
12253
- };
12254
- /**
12255
- * Update the value display element
12256
- */
12257
- KTSelect.prototype._updateValueDisplay = function (value) {
12258
- if (this._config.mode === types_1.SelectMode.COMBOBOX) {
12259
- // For combobox, we only update the hidden value element, not the input
12260
- // The combobox module will handle updating the input value
12261
- if (!this._comboboxModule) {
12262
- this._valueDisplayElement.value = value;
12263
- }
12264
- }
12265
- else {
12266
- this._valueDisplayElement.innerHTML = value;
12267
- }
12268
- };
12269
- /**
12270
- * Update debug displays if present
12271
- */
12272
- KTSelect.prototype._updateDebugDisplays = function () {
12273
- // Check if we're in a test environment with debug boxes
12274
- var selectId = this.getElement().id;
12275
- if (selectId) {
12276
- var debugElement = document.getElementById("".concat(selectId, "-value"));
12277
- if (debugElement) {
12278
- var selectedOptions = this.getSelectedOptions();
12279
- // Format display based on selection mode
12280
- if (this._config.multiple) {
12281
- // For multiple selection, show comma-separated list
12282
- debugElement.textContent =
12283
- selectedOptions.length > 0 ? selectedOptions.join(', ') : 'None';
12036
+ var content = '';
12037
+ if (this._config.displayTemplate) {
12038
+ var selectedValues = this.getSelectedOptions();
12039
+ content = this.renderDisplayTemplateForSelected(selectedValues);
12284
12040
  }
12285
12041
  else {
12286
- // For single selection, show just the one value
12287
- debugElement.textContent =
12288
- selectedOptions.length > 0 ? selectedOptions[0] : 'None';
12042
+ // If no displayTemplate is provided, use the default comma-separated list of selected options
12043
+ content = this.getSelectedOptionsText();
12289
12044
  }
12045
+ this._valueDisplayElement.innerHTML = content;
12290
12046
  }
12291
12047
  }
12292
12048
  };
12293
- /**
12294
- * Get option inner HTML content by option value
12295
- */
12296
- KTSelect.prototype._getOptionInnerHtml = function (optionValue) {
12297
- var option = Array.from(this._options).find(function (opt) { return opt.dataset.value === optionValue; });
12298
- if (this._config.mode == types_1.SelectMode.COMBOBOX) {
12299
- return option.textContent;
12300
- }
12301
- return option.innerHTML; // Get the entire HTML content of the option
12302
- };
12303
12049
  /**
12304
12050
  * Update CSS classes for selected options
12305
12051
  */
@@ -12344,17 +12090,6 @@ var KTSelect = /** @class */ (function (_super) {
12344
12090
  this._state.setSelectedOptions([]);
12345
12091
  this.updateSelectedOptionDisplay();
12346
12092
  this._updateSelectedOptionClass();
12347
- // For combobox, also clear the input value
12348
- if (this._config.mode === types_1.SelectMode.COMBOBOX) {
12349
- if (this._searchInputElement) {
12350
- this._searchInputElement.value = '';
12351
- }
12352
- // If combobox has a clear button, hide it
12353
- if (this._comboboxModule) {
12354
- // The combobox module will handle hiding the clear button
12355
- this._comboboxModule.resetInputValueToSelection();
12356
- }
12357
- }
12358
12093
  // Dispatch change event
12359
12094
  this._dispatchEvent('change');
12360
12095
  this._fireEvent('change');
@@ -12366,49 +12101,6 @@ var KTSelect = /** @class */ (function (_super) {
12366
12101
  var values = Array.from(options).map(function (option) { return option.value; });
12367
12102
  this._state.setSelectedOptions(values);
12368
12103
  };
12369
- /**
12370
- * ========================================================================
12371
- * KEYBOARD NAVIGATION
12372
- * ========================================================================
12373
- */
12374
- /**
12375
- * Handle dropdown key down events for keyboard navigation
12376
- * Only used for standard (non-combobox) dropdowns
12377
- */
12378
- KTSelect.prototype._handleDropdownKeyDown = function (event) {
12379
- // Log event for debugging
12380
- if (this._config.debug)
12381
- console.log('Standard dropdown keydown:', event.key);
12382
- // Use the shared handler
12383
- (0, utils_1.handleDropdownKeyNavigation)(event, this, {
12384
- multiple: this._config.multiple,
12385
- closeOnSelect: this._config.closeOnSelect,
12386
- });
12387
- };
12388
- /**
12389
- * Focus next option in dropdown
12390
- */
12391
- KTSelect.prototype._focusNextOption = function () {
12392
- return this._focusManager.focusNext();
12393
- };
12394
- /**
12395
- * Focus previous option in dropdown
12396
- */
12397
- KTSelect.prototype._focusPreviousOption = function () {
12398
- return this._focusManager.focusPrevious();
12399
- };
12400
- /**
12401
- * Apply hover/focus state to focused option
12402
- */
12403
- KTSelect.prototype._hoverFocusedOption = function (option) {
12404
- this._focusManager.applyFocus(option);
12405
- };
12406
- /**
12407
- * Scroll option into view when navigating
12408
- */
12409
- KTSelect.prototype._scrollOptionIntoView = function (option) {
12410
- this._focusManager.scrollIntoView(option);
12411
- };
12412
12104
  /**
12413
12105
  * Select the currently focused option
12414
12106
  */
@@ -12432,52 +12124,16 @@ var KTSelect = /** @class */ (function (_super) {
12432
12124
  if (selectedValue) {
12433
12125
  this._selectOption(selectedValue);
12434
12126
  }
12435
- // For combobox mode, update input value AFTER selection to ensure consistency
12436
- if (this._config.mode === types_1.SelectMode.COMBOBOX && this._comboboxModule) {
12437
- this._comboboxModule.updateSelectedValue(selectedText);
12438
- // Also directly update the input value for immediate visual feedback
12439
- if (this._searchInputElement) {
12440
- this._searchInputElement.value = selectedText;
12441
- }
12442
- }
12443
12127
  }
12444
12128
  };
12445
12129
  /**
12446
12130
  * ========================================================================
12447
- * COMBOBOX SPECIFIC METHODS
12131
+ * EVENT HANDLERS
12448
12132
  * ========================================================================
12449
12133
  */
12450
12134
  /**
12451
- * Handle combobox input events
12452
- */
12453
- KTSelect.prototype._handleComboboxInput = function (event) {
12454
- if (this._comboboxModule) {
12455
- return;
12456
- }
12457
- var inputElement = event.target;
12458
- var query = inputElement.value.toLowerCase();
12459
- // If dropdown isn't open, open it when user starts typing
12460
- if (!this._dropdownIsOpen) {
12461
- this.openDropdown();
12462
- }
12463
- // Filter options based on input
12464
- this._filterOptionsForCombobox(query);
12465
- };
12466
- /**
12467
- * Filter options for combobox based on input query
12468
- * Uses the shared filterOptions function
12469
- */
12470
- KTSelect.prototype._filterOptionsForCombobox = function (query) {
12471
- var options = Array.from(this._dropdownContentElement.querySelectorAll('[data-kt-select-option]'));
12472
- (0, utils_1.filterOptions)(options, query, this._config, this._dropdownContentElement);
12473
- };
12474
- /**
12475
- * ========================================================================
12476
- * EVENT HANDLERS
12477
- * ========================================================================
12478
- */
12479
- /**
12480
- * Handle display element click
12135
+ * Handle display element click
12136
+ * @deprecated
12481
12137
  */
12482
12138
  KTSelect.prototype._handleDropdownClick = function (event) {
12483
12139
  if (this._config.debug)
@@ -12539,14 +12195,6 @@ var KTSelect = /** @class */ (function (_super) {
12539
12195
  this.closeDropdown();
12540
12196
  }
12541
12197
  };
12542
- /**
12543
- * Handle escape key press
12544
- */
12545
- KTSelect.prototype._handleEscKey = function (event) {
12546
- if (event.key === 'Escape' && this._dropdownIsOpen) {
12547
- this.closeDropdown();
12548
- }
12549
- };
12550
12198
  /**
12551
12199
  * ========================================================================
12552
12200
  * ACCESSIBILITY METHODS
@@ -12558,18 +12206,6 @@ var KTSelect = /** @class */ (function (_super) {
12558
12206
  KTSelect.prototype._setAriaAttributes = function () {
12559
12207
  this._displayElement.setAttribute('aria-expanded', this._dropdownIsOpen.toString());
12560
12208
  };
12561
- /**
12562
- * Handle focus events
12563
- */
12564
- KTSelect.prototype._handleFocus = function () {
12565
- // Implementation pending
12566
- };
12567
- /**
12568
- * Handle blur events
12569
- */
12570
- KTSelect.prototype._handleBlur = function () {
12571
- // Implementation pending
12572
- };
12573
12209
  /**
12574
12210
  * ========================================================================
12575
12211
  * PUBLIC API
@@ -12638,7 +12274,7 @@ var KTSelect = /** @class */ (function (_super) {
12638
12274
  }
12639
12275
  });
12640
12276
  // If search input exists, clear it
12641
- if (this._searchInputElement && this._config.mode !== types_1.SelectMode.COMBOBOX) {
12277
+ if (this._searchInputElement) {
12642
12278
  this._searchInputElement.value = '';
12643
12279
  // If we have a search module, clear any search filtering
12644
12280
  if (this._searchModule) {
@@ -12662,6 +12298,12 @@ var KTSelect = /** @class */ (function (_super) {
12662
12298
  * Toggle the selection of an option
12663
12299
  */
12664
12300
  KTSelect.prototype.toggleSelection = function (value) {
12301
+ // Prevent selection if the option is disabled (in dropdown or original select)
12302
+ if (this._isOptionDisabled(value)) {
12303
+ if (this._config.debug)
12304
+ console.log('toggleSelection: Option is disabled, ignoring selection');
12305
+ return;
12306
+ }
12665
12307
  // Get current selection state
12666
12308
  var isSelected = this._state.isSelected(value);
12667
12309
  if (this._config.debug)
@@ -12829,7 +12471,7 @@ var KTSelect = /** @class */ (function (_super) {
12829
12471
  */
12830
12472
  KTSelect.prototype._renderSearchLoadingState = function () {
12831
12473
  if (!this._originalOptionsHtml && this._dropdownContentElement) {
12832
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
12474
+ var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
12833
12475
  if (optionsContainer) {
12834
12476
  this._originalOptionsHtml = optionsContainer.innerHTML;
12835
12477
  }
@@ -12848,36 +12490,26 @@ var KTSelect = /** @class */ (function (_super) {
12848
12490
  * @param items Search result items
12849
12491
  */
12850
12492
  KTSelect.prototype._updateSearchResults = function (items) {
12851
- var _this = this;
12852
12493
  if (!this._dropdownContentElement)
12853
12494
  return;
12854
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options-container]');
12495
+ var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
12855
12496
  if (!optionsContainer)
12856
12497
  return;
12857
12498
  // Clear current options
12858
12499
  optionsContainer.innerHTML = '';
12859
12500
  if (items.length === 0) {
12860
12501
  // Show no results message using template for consistency and customization
12861
- var noResultsElement = templates_1.defaultTemplates.noResults(this._config);
12502
+ var noResultsElement = templates_1.defaultTemplates.empty(this._config);
12862
12503
  optionsContainer.appendChild(noResultsElement);
12863
12504
  return;
12864
12505
  }
12865
12506
  // Process each item individually to create options
12866
12507
  items.forEach(function (item) {
12867
12508
  // Create option for the original select
12868
- var selectOption = templates_1.defaultTemplates.emptyOption(__assign(__assign({}, _this._config), { placeholder: item.title }));
12509
+ var selectOption = document.createElement('option');
12869
12510
  selectOption.value = item.id;
12870
- if (item.description) {
12871
- selectOption.setAttribute('data-kt-select-option-description', item.description);
12872
- }
12873
- if (item.icon) {
12874
- selectOption.setAttribute('data-kt-select-option-icon', item.icon);
12875
- }
12876
- // Create option element for the dropdown
12877
- var ktOption = new option_1.KTSelectOption(selectOption, _this._config);
12878
- var renderedOption = ktOption.render();
12879
12511
  // Add to dropdown container
12880
- optionsContainer.appendChild(renderedOption);
12512
+ optionsContainer.appendChild(selectOption);
12881
12513
  });
12882
12514
  // Add pagination "Load More" button if needed
12883
12515
  if (this._config.pagination && this._remoteModule.hasMorePages()) {
@@ -12886,18 +12518,137 @@ var KTSelect = /** @class */ (function (_super) {
12886
12518
  // Update options NodeList
12887
12519
  this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
12888
12520
  };
12889
- /**
12890
- * Filter options by query
12891
- */
12892
- KTSelect.prototype.filterOptions = function (query) {
12893
- this._filterOptionsForCombobox(query);
12894
- };
12895
12521
  /**
12896
12522
  * Check if dropdown is open
12897
12523
  */
12898
12524
  KTSelect.prototype.isDropdownOpen = function () {
12899
12525
  return this._dropdownIsOpen;
12900
12526
  };
12527
+ KTSelect.prototype.getSelectedOptionsText = function () {
12528
+ var _this = this;
12529
+ var selectedValues = this.getSelectedOptions();
12530
+ var displaySeparator = this._config.displaySeparator || ', ';
12531
+ var texts = selectedValues.map(function (value) {
12532
+ var option = Array.from(_this._options).find(function (opt) { return opt.getAttribute('data-value') === value; });
12533
+ return (option === null || option === void 0 ? void 0 : option.getAttribute('data-text')) || '';
12534
+ }).filter(Boolean);
12535
+ return texts.join(displaySeparator);
12536
+ };
12537
+ /**
12538
+ * Check if an option is disabled (either in dropdown or original select)
12539
+ */
12540
+ KTSelect.prototype._isOptionDisabled = function (value) {
12541
+ var dropdownOption = Array.from(this._options).find(function (opt) { return opt.getAttribute('data-value') === value; });
12542
+ var isDropdownDisabled = dropdownOption && (dropdownOption.classList.contains('disabled') || dropdownOption.getAttribute('aria-disabled') === 'true');
12543
+ var selectOption = Array.from(this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
12544
+ var isNativeDisabled = selectOption && selectOption.disabled;
12545
+ return Boolean(isDropdownDisabled || isNativeDisabled);
12546
+ };
12547
+ /**
12548
+ * Centralized keyboard event handler for all select modes
12549
+ */
12550
+ KTSelect.prototype._handleKeyboardEvent = function (event) {
12551
+ var isOpen = this._dropdownIsOpen;
12552
+ var config = this._config;
12553
+ var focusManager = this._focusManager;
12554
+ var buffer = this._typeToSearchBuffer;
12555
+ // Ignore modifier keys
12556
+ if (event.altKey || event.ctrlKey || event.metaKey)
12557
+ return;
12558
+ // Type-to-search: only for single char keys
12559
+ if (event.key.length === 1 && !event.repeat && !event.key.match(/\s/)) {
12560
+ buffer.push(event.key);
12561
+ var str = buffer.getBuffer();
12562
+ focusManager.focusByString(str);
12563
+ return;
12564
+ }
12565
+ switch (event.key) {
12566
+ case 'ArrowDown':
12567
+ event.preventDefault();
12568
+ if (!isOpen) {
12569
+ this.openDropdown();
12570
+ }
12571
+ else {
12572
+ focusManager.focusNext();
12573
+ }
12574
+ break;
12575
+ case 'ArrowUp':
12576
+ event.preventDefault();
12577
+ if (!isOpen) {
12578
+ this.openDropdown();
12579
+ }
12580
+ else {
12581
+ focusManager.focusPrevious();
12582
+ }
12583
+ break;
12584
+ case 'Home':
12585
+ event.preventDefault();
12586
+ if (isOpen)
12587
+ focusManager.focusFirst();
12588
+ break;
12589
+ case 'End':
12590
+ event.preventDefault();
12591
+ if (isOpen)
12592
+ focusManager.focusLast();
12593
+ break;
12594
+ case 'Enter':
12595
+ case ' ': // Space
12596
+ if (isOpen) {
12597
+ var focused = focusManager.getFocusedOption();
12598
+ if (focused) {
12599
+ var value = focused.dataset.value;
12600
+ if (value) {
12601
+ this.toggleSelection(value);
12602
+ if (!config.multiple && config.closeOnSelect) {
12603
+ this.closeDropdown();
12604
+ }
12605
+ }
12606
+ }
12607
+ // Prevent form submit
12608
+ event.preventDefault();
12609
+ }
12610
+ else {
12611
+ this.openDropdown();
12612
+ }
12613
+ break;
12614
+ case 'Escape':
12615
+ if (isOpen) {
12616
+ this.closeDropdown();
12617
+ event.target.blur();
12618
+ }
12619
+ break;
12620
+ case 'Tab':
12621
+ // Let Tab propagate for normal focus movement
12622
+ break;
12623
+ default:
12624
+ break;
12625
+ }
12626
+ };
12627
+ KTSelect.prototype.renderDisplayTemplateForSelected = function (selectedValues) {
12628
+ var _this = this;
12629
+ var optionsConfig = this._config.optionsConfig || {};
12630
+ var displaySeparator = this._config.displaySeparator || ', ';
12631
+ var contentArray = Array.from(new Set(selectedValues.map(function (value) {
12632
+ var option = Array.from(_this._options).find(function (opt) { return opt.getAttribute('data-value') === value; });
12633
+ if (!option)
12634
+ return '';
12635
+ var displayTemplate = _this._config.displayTemplate;
12636
+ var text = option.getAttribute('data-text') || '';
12637
+ // Replace all {{varname}} in option.innerHTML with values from _config
12638
+ Object.entries(optionsConfig[value] || {}).forEach(function (_a) {
12639
+ var key = _a[0], val = _a[1];
12640
+ if (["string", "number", "boolean"].includes(typeof val)) {
12641
+ displayTemplate = displayTemplate.replace(new RegExp("{{".concat(key, "}}"), 'g'), String(val));
12642
+ }
12643
+ });
12644
+ return (0, utils_1.renderTemplateString)(displayTemplate, {
12645
+ selectedCount: selectedValues.length || 0,
12646
+ selectedTexts: _this.getSelectedOptionsText() || '',
12647
+ text: text,
12648
+ });
12649
+ }).filter(Boolean)));
12650
+ return contentArray.join(displaySeparator);
12651
+ };
12901
12652
  /**
12902
12653
  * ========================================================================
12903
12654
  * STATIC METHODS
@@ -12925,31 +12676,6 @@ var tooltip_1 = __webpack_require__(1850);
12925
12676
  Object.defineProperty(exports, "KTTooltip", ({ enumerable: true, get: function () { return tooltip_1.KTTooltip; } }));
12926
12677
 
12927
12678
 
12928
- /***/ }),
12929
-
12930
- /***/ 8135:
12931
- /***/ (function(__unused_webpack_module, exports) {
12932
-
12933
-
12934
- /**
12935
- * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
12936
- * Copyright 2025 by Keenthemes Inc
12937
- */
12938
- Object.defineProperty(exports, "__esModule", ({ value: true }));
12939
- exports.SelectMode = void 0;
12940
- /**
12941
- * Common type interfaces for the KTSelect component
12942
- */
12943
- /**
12944
- * Select mode options
12945
- */
12946
- var SelectMode;
12947
- (function (SelectMode) {
12948
- SelectMode["TAGS"] = "tags";
12949
- SelectMode["COMBOBOX"] = "combobox";
12950
- })(SelectMode || (exports.SelectMode = SelectMode = {}));
12951
-
12952
-
12953
12679
  /***/ }),
12954
12680
 
12955
12681
  /***/ 8151:
@@ -13503,7 +13229,7 @@ exports.KTDatepickerKeyboard = KTDatepickerKeyboard;
13503
13229
  * Copyright 2025 by Keenthemes Inc
13504
13230
  */
13505
13231
  Object.defineProperty(exports, "__esModule", ({ value: true }));
13506
- exports.KTSelect = exports.KTDatepicker = exports.KTDataTable = exports.KTTogglePassword = exports.KTImageInput = exports.KTThemeSwitch = exports.KTStepper = exports.KTTooltip = exports.KTToggle = exports.KTReparent = exports.KTSticky = exports.KTScrollto = exports.KTScrollable = exports.KTScrollspy = exports.KTAccordion = exports.KTTabs = exports.KTDismiss = exports.KTCollapse = exports.KTDrawer = exports.KTModal = exports.KTDropdown = void 0;
13232
+ exports.KTToast = exports.KTSelect = exports.KTDatepicker = exports.KTDataTable = exports.KTTogglePassword = exports.KTImageInput = exports.KTThemeSwitch = exports.KTStepper = exports.KTTooltip = exports.KTToggle = exports.KTReparent = exports.KTSticky = exports.KTScrollto = exports.KTScrollable = exports.KTScrollspy = exports.KTAccordion = exports.KTTabs = exports.KTDismiss = exports.KTCollapse = exports.KTDrawer = exports.KTModal = exports.KTDropdown = void 0;
13507
13233
  var dom_1 = __webpack_require__(9010);
13508
13234
  var dropdown_1 = __webpack_require__(5071);
13509
13235
  var modal_1 = __webpack_require__(3395);
@@ -13526,6 +13252,7 @@ var toggle_password_1 = __webpack_require__(2232);
13526
13252
  var datatable_1 = __webpack_require__(2626);
13527
13253
  var datepicker_1 = __webpack_require__(5116);
13528
13254
  var select_1 = __webpack_require__(494);
13255
+ var toast_1 = __webpack_require__(6265);
13529
13256
  var dropdown_2 = __webpack_require__(5071);
13530
13257
  Object.defineProperty(exports, "KTDropdown", ({ enumerable: true, get: function () { return dropdown_2.KTDropdown; } }));
13531
13258
  var modal_2 = __webpack_require__(3395);
@@ -13568,6 +13295,8 @@ var datepicker_2 = __webpack_require__(5116);
13568
13295
  Object.defineProperty(exports, "KTDatepicker", ({ enumerable: true, get: function () { return datepicker_2.KTDatepicker; } }));
13569
13296
  var select_2 = __webpack_require__(494);
13570
13297
  Object.defineProperty(exports, "KTSelect", ({ enumerable: true, get: function () { return select_2.KTSelect; } }));
13298
+ var toast_2 = __webpack_require__(6265);
13299
+ Object.defineProperty(exports, "KTToast", ({ enumerable: true, get: function () { return toast_2.KTToast; } }));
13571
13300
  var KTComponents = {
13572
13301
  init: function () {
13573
13302
  dropdown_1.KTDropdown.init();
@@ -13591,6 +13320,7 @@ var KTComponents = {
13591
13320
  datatable_1.KTDataTable.init();
13592
13321
  datepicker_1.KTDatepicker.init();
13593
13322
  select_1.KTSelect.init();
13323
+ toast_1.KTToast.init();
13594
13324
  },
13595
13325
  };
13596
13326
  exports["default"] = KTComponents;
@@ -14789,43 +14519,51 @@ var KTSelectTags = /** @class */ (function () {
14789
14519
  */
14790
14520
  KTSelectTags.prototype.updateTagsDisplay = function (selectedOptions) {
14791
14521
  var _this = this;
14792
- // Clear existing content
14793
- this._valueDisplayElement.innerHTML = '';
14794
- // If no options selected, show placeholder
14522
+ // Remove any existing tag elements
14523
+ var wrapper = this._valueDisplayElement.parentElement;
14524
+ if (!wrapper)
14525
+ return;
14526
+ // Remove all previous tags
14527
+ Array.from(wrapper.querySelectorAll('[data-kt-select-tag]')).forEach(function (tag) { return tag.remove(); });
14528
+ // If no options selected, do nothing (let display show placeholder)
14795
14529
  if (selectedOptions.length === 0) {
14796
- this._valueDisplayElement.textContent = this._config.placeholder || '';
14797
14530
  return;
14798
14531
  }
14799
- // Create and append a tag element for each selected option
14532
+ // Insert each tag before the display element
14800
14533
  selectedOptions.forEach(function (optionValue) {
14801
- var tagElement = _this._createTagElement(optionValue);
14802
- _this._valueDisplayElement.appendChild(tagElement);
14534
+ // Find the original option element (in dropdown or select)
14535
+ var optionElement = null;
14536
+ var optionElements = _this._select.getOptionsElement();
14537
+ for (var _i = 0, _a = Array.from(optionElements); _i < _a.length; _i++) {
14538
+ var opt = _a[_i];
14539
+ if (opt.dataset.value === optionValue) {
14540
+ optionElement = opt;
14541
+ break;
14542
+ }
14543
+ }
14544
+ if (!optionElement) {
14545
+ var originalOptions = _this._select.getElement().querySelectorAll('option');
14546
+ for (var _b = 0, _c = Array.from(originalOptions); _b < _c.length; _b++) {
14547
+ var opt = _c[_b];
14548
+ if (opt.value === optionValue) {
14549
+ optionElement = opt;
14550
+ break;
14551
+ }
14552
+ }
14553
+ }
14554
+ var tag = templates_1.defaultTemplates.tag(optionElement, _this._config);
14555
+ // Add event listener to the close button
14556
+ var closeButton = tag.querySelector('[data-kt-select-remove-button]');
14557
+ if (closeButton) {
14558
+ _this._eventManager.addListener(closeButton, 'click', function (event) {
14559
+ event.stopPropagation();
14560
+ _this._removeTag(optionValue);
14561
+ });
14562
+ }
14563
+ // Insert tag before the display element
14564
+ wrapper.insertBefore(tag, _this._valueDisplayElement);
14803
14565
  });
14804
14566
  };
14805
- /**
14806
- * Create tag element for a selected option
14807
- */
14808
- KTSelectTags.prototype._createTagElement = function (optionValue) {
14809
- var _this = this;
14810
- var optionLabel = this._getOptionLabel(optionValue);
14811
- // Create a mock option object to pass to the tag template
14812
- var mockOption = {
14813
- id: optionValue,
14814
- title: optionLabel,
14815
- selected: true,
14816
- };
14817
- // Use the tag template
14818
- var tag = templates_1.defaultTemplates.tag(mockOption, this._config);
14819
- // Add event listener to the close button
14820
- var closeButton = tag.querySelector("[data-kt-select-remove-button]");
14821
- if (closeButton) {
14822
- this._eventManager.addListener(closeButton, 'click', function (event) {
14823
- event.stopPropagation();
14824
- _this._removeTag(optionValue);
14825
- });
14826
- }
14827
- return tag;
14828
- };
14829
14567
  /**
14830
14568
  * Get the label/text for an option by its value
14831
14569
  */
@@ -14870,6 +14608,555 @@ var KTSelectTags = /** @class */ (function () {
14870
14608
  exports.KTSelectTags = KTSelectTags;
14871
14609
 
14872
14610
 
14611
+ /***/ }),
14612
+
14613
+ /***/ 8834:
14614
+ /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
14615
+
14616
+
14617
+ /**
14618
+ * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
14619
+ * Copyright 2025 by Keenthemes Inc
14620
+ */
14621
+ var __extends = (this && this.__extends) || (function () {
14622
+ var extendStatics = function (d, b) {
14623
+ extendStatics = Object.setPrototypeOf ||
14624
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
14625
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
14626
+ return extendStatics(d, b);
14627
+ };
14628
+ return function (d, b) {
14629
+ if (typeof b !== "function" && b !== null)
14630
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
14631
+ extendStatics(d, b);
14632
+ function __() { this.constructor = d; }
14633
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
14634
+ };
14635
+ })();
14636
+ var __assign = (this && this.__assign) || function () {
14637
+ __assign = Object.assign || function(t) {
14638
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
14639
+ s = arguments[i];
14640
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
14641
+ t[p] = s[p];
14642
+ }
14643
+ return t;
14644
+ };
14645
+ return __assign.apply(this, arguments);
14646
+ };
14647
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
14648
+ exports.KTToast = void 0;
14649
+ var component_1 = __webpack_require__(2658);
14650
+ var data_1 = __webpack_require__(8716);
14651
+ var DEFAULT_CONFIG = {
14652
+ position: 'top-end',
14653
+ duration: 4000,
14654
+ className: '',
14655
+ maxToasts: 5,
14656
+ offset: 15,
14657
+ gap: 10,
14658
+ };
14659
+ var DEFAULT_TOAST_OPTIONS = {
14660
+ appearance: 'solid',
14661
+ progress: false,
14662
+ size: 'md',
14663
+ action: false,
14664
+ cancel: false,
14665
+ dismiss: true,
14666
+ };
14667
+ var KTToast = /** @class */ (function (_super) {
14668
+ __extends(KTToast, _super);
14669
+ /**
14670
+ * Creates a new KTToast instance for a specific element (not commonly used; most use static API).
14671
+ * @param element The target HTML element.
14672
+ * @param config Optional toast config for this instance.
14673
+ */
14674
+ function KTToast(element, config) {
14675
+ var _this = _super.call(this) || this;
14676
+ _this._name = 'toast';
14677
+ _this._defaultConfig = DEFAULT_CONFIG;
14678
+ _this._config = DEFAULT_CONFIG;
14679
+ _this._defaultToastOptions = DEFAULT_TOAST_OPTIONS;
14680
+ if (data_1.default.has(element, _this._name))
14681
+ return _this;
14682
+ _this._init(element);
14683
+ _this._buildConfig(config);
14684
+ data_1.default.set(element, _this._name, _this);
14685
+ return _this;
14686
+ }
14687
+ /**
14688
+ * Generates the HTML content for a toast based on the provided options.
14689
+ * @param options Toast options (message, icon, actions, etc).
14690
+ * @returns The toast's HTML markup as a string.
14691
+ */
14692
+ KTToast.getContent = function (options) {
14693
+ var classNames = __assign(__assign({}, (this.globalConfig.classNames || {})), ((options === null || options === void 0 ? void 0 : options.classNames) || {}));
14694
+ if (options === null || options === void 0 ? void 0 : options.content) {
14695
+ if (typeof options.content === 'string') {
14696
+ return options.content;
14697
+ }
14698
+ else if (typeof options.content === 'function') {
14699
+ var node = options.content();
14700
+ if (node instanceof HTMLElement) {
14701
+ return node.outerHTML;
14702
+ }
14703
+ }
14704
+ else if (options.content instanceof HTMLElement) {
14705
+ return options.content.outerHTML;
14706
+ }
14707
+ }
14708
+ var template = '';
14709
+ if (options === null || options === void 0 ? void 0 : options.icon) {
14710
+ template +=
14711
+ '<div class="kt-alert-icon ' +
14712
+ (classNames.icon || '') +
14713
+ '">' +
14714
+ options.icon +
14715
+ '</div>';
14716
+ }
14717
+ if (options === null || options === void 0 ? void 0 : options.message) {
14718
+ template +=
14719
+ '<div class="kt-alert-title ' +
14720
+ (classNames.message || '') +
14721
+ '">' +
14722
+ options.message +
14723
+ '</div>';
14724
+ }
14725
+ if ((options === null || options === void 0 ? void 0 : options.action) !== false ||
14726
+ (options === null || options === void 0 ? void 0 : options.dismiss) !== false ||
14727
+ (options === null || options === void 0 ? void 0 : options.cancel) !== false) {
14728
+ template +=
14729
+ '<div class="kt-alert-toolbar ' + (classNames.toolbar || '') + '">';
14730
+ template +=
14731
+ '<div class="kt-alert-actions ' + (classNames.actions || '') + '">';
14732
+ if ((options === null || options === void 0 ? void 0 : options.action) && typeof options.action === 'object') {
14733
+ template +=
14734
+ '<button data-kt-toast-action="true" class="' +
14735
+ (options.action.className || '') +
14736
+ '">' +
14737
+ options.action.label +
14738
+ '</button>';
14739
+ }
14740
+ if ((options === null || options === void 0 ? void 0 : options.cancel) && typeof options.cancel === 'object') {
14741
+ template +=
14742
+ '<button data-kt-toast-cancel="true" class="' +
14743
+ (options.cancel.className || '') +
14744
+ '">' +
14745
+ options.cancel.label +
14746
+ '</button>';
14747
+ }
14748
+ if ((options === null || options === void 0 ? void 0 : options.dismiss) !== false) {
14749
+ template +=
14750
+ '<button data-kt-toast-dismiss="true" class="kt-alert-close"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button>';
14751
+ }
14752
+ template += '</div>';
14753
+ template += '</div>';
14754
+ }
14755
+ template += '</div>';
14756
+ return template;
14757
+ };
14758
+ /**
14759
+ * Update all toasts in the container with smooth animation.
14760
+ *
14761
+ * @param container The toast container element.
14762
+ * @param offset Optional offset from the edge.
14763
+ */
14764
+ KTToast.update = function (container, offset) {
14765
+ var _this = this;
14766
+ var _a;
14767
+ if (!container)
14768
+ return;
14769
+ offset =
14770
+ typeof offset === 'number' ? offset : ((_a = this.globalConfig.offset) !== null && _a !== void 0 ? _a : 15);
14771
+ requestAnimationFrame(function () {
14772
+ var _a;
14773
+ var gap = (_a = _this.globalConfig.gap) !== null && _a !== void 0 ? _a : 8;
14774
+ // Group toasts by alignment (top/bottom)
14775
+ var positionGroups = {
14776
+ top: [],
14777
+ bottom: [],
14778
+ };
14779
+ var toasts = Array.from(container.children);
14780
+ toasts.forEach(function (toast) {
14781
+ if (toast.classList.contains('kt-toast-top-end') ||
14782
+ toast.classList.contains('kt-toast-top-center') ||
14783
+ toast.classList.contains('kt-toast-top-start')) {
14784
+ positionGroups.top.push(toast);
14785
+ }
14786
+ else {
14787
+ positionGroups.bottom.push(toast);
14788
+ }
14789
+ });
14790
+ // Stack top toasts from the top down
14791
+ var currentOffset = offset;
14792
+ positionGroups.top.forEach(function (toast) {
14793
+ toast.style.top = "".concat(currentOffset, "px");
14794
+ toast.style.bottom = '';
14795
+ toast.style.transition =
14796
+ 'top 0.28s cubic-bezier(.4,0,.2,1), opacity 0.28s cubic-bezier(.4,0,.2,1)';
14797
+ currentOffset += toast.offsetHeight + gap;
14798
+ if (toast.classList.contains('kt-toast-top-start')) {
14799
+ toast.style.insetInlineStart = "".concat(offset, "px");
14800
+ }
14801
+ if (toast.classList.contains('kt-toast-top-end')) {
14802
+ toast.style.insetInlineEnd = "".concat(offset, "px");
14803
+ }
14804
+ });
14805
+ // Stack bottom toasts from the bottom up
14806
+ currentOffset = offset;
14807
+ for (var i = positionGroups.bottom.length - 1; i >= 0; i--) {
14808
+ var toast = positionGroups.bottom[i];
14809
+ toast.style.bottom = "".concat(currentOffset, "px");
14810
+ toast.style.top = '';
14811
+ toast.style.transition =
14812
+ 'bottom 0.28s cubic-bezier(.4,0,.2,1), opacity 0.28s cubic-bezier(.4,0,.2,1)';
14813
+ currentOffset += toast.offsetHeight + gap;
14814
+ if (toast.classList.contains('kt-toast-bottom-start')) {
14815
+ toast.style.insetInlineStart = "".concat(offset, "px");
14816
+ }
14817
+ if (toast.classList.contains('kt-toast-bottom-end')) {
14818
+ toast.style.insetInlineEnd = "".concat(offset, "px");
14819
+ }
14820
+ }
14821
+ });
14822
+ };
14823
+ /**
14824
+ * Set global toast configuration options.
14825
+ * @param options Partial toast config to merge with global config.
14826
+ */
14827
+ KTToast.config = function (options) {
14828
+ this.globalConfig = __assign(__assign({}, this.globalConfig), options);
14829
+ };
14830
+ /**
14831
+ * Show a toast notification.
14832
+ * @param inputOptions Toast options (message, duration, variant, etc).
14833
+ * @returns Toast instance with dismiss method, or undefined if invalid input.
14834
+ */
14835
+ KTToast.show = function (inputOptions) {
14836
+ var _a, _b, _c, _d;
14837
+ var options = __assign(__assign({}, DEFAULT_TOAST_OPTIONS), inputOptions);
14838
+ if (!options || (!options.message && !options.content)) {
14839
+ return undefined;
14840
+ }
14841
+ // Always resolve the id once and use it everywhere
14842
+ var id = "kt-toast-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 8));
14843
+ var position = options.position || this.globalConfig.position || 'top-end';
14844
+ var classNames = __assign(__assign({}, (this.globalConfig.classNames || {})), (options.classNames || {}));
14845
+ var container = this.containerMap.get(position);
14846
+ if (!container) {
14847
+ container = document.createElement('div');
14848
+ var classNames_1 = __assign(__assign({}, (this.globalConfig.classNames || {})), (options.classNames || {}));
14849
+ // Fallback to default hardcoded classes if not provided in options or globalConfig
14850
+ container.className =
14851
+ classNames_1.container || "kt-toast-container ".concat(position);
14852
+ document.body.appendChild(container);
14853
+ this.containerMap.set(position, container);
14854
+ }
14855
+ // Enforce maxToasts
14856
+ if (container.children.length >=
14857
+ (this.globalConfig.maxToasts || DEFAULT_CONFIG.maxToasts)) {
14858
+ var firstToast_1 = container.firstElementChild;
14859
+ if (firstToast_1) {
14860
+ firstToast_1.classList.add('kt-toast-closing');
14861
+ firstToast_1.addEventListener('animationend', function () {
14862
+ firstToast_1.remove();
14863
+ });
14864
+ }
14865
+ }
14866
+ // Create toast element
14867
+ var variantMap = {
14868
+ info: 'kt-alert-info',
14869
+ success: 'kt-alert-success',
14870
+ error: 'kt-alert-error',
14871
+ warning: 'kt-alert-warning',
14872
+ primary: 'kt-alert-primary',
14873
+ secondary: 'kt-alert-secondary',
14874
+ destructive: 'kt-alert-destructive',
14875
+ mono: 'kt-alert-mono',
14876
+ };
14877
+ var appearanceMap = {
14878
+ solid: 'kt-alert-solid',
14879
+ outline: 'kt-alert-outline',
14880
+ light: 'kt-alert-light',
14881
+ };
14882
+ var sizeMap = {
14883
+ sm: 'kt-alert-sm',
14884
+ md: 'kt-alert-md',
14885
+ lg: 'kt-alert-lg',
14886
+ };
14887
+ var toast = document.createElement('div');
14888
+ toast.className = "kt-toast kt-alert ".concat(variantMap[options.variant] || '', " ").concat(appearanceMap[options.appearance] || '', " ").concat(sizeMap[options.size] || '', " ").concat(options.className || '', " ").concat(classNames.toast || '');
14889
+ // ARIA support
14890
+ toast.setAttribute('role', options.role || 'status');
14891
+ toast.setAttribute('aria-live', 'polite');
14892
+ toast.setAttribute('aria-atomic', 'true');
14893
+ toast.setAttribute('tabindex', '0');
14894
+ // Always resolve the id once and use it everywhere
14895
+ // Always resolve id ONCE at the top, use everywhere
14896
+ // (Move this up to replace the previous const id = ... assignment)
14897
+ // Populate content via getContent
14898
+ var contentHtml = KTToast.getContent(options);
14899
+ toast.innerHTML = contentHtml;
14900
+ // Assign event handlers to buttons by data attribute
14901
+ var actionBtn = toast.querySelector('[data-kt-toast-action]');
14902
+ if (actionBtn &&
14903
+ options.action &&
14904
+ typeof options.action === 'object' &&
14905
+ options.action.onClick) {
14906
+ actionBtn.addEventListener('click', function (e) {
14907
+ e.stopPropagation();
14908
+ if (typeof options.action === 'object' && options.action.onClick) {
14909
+ options.action.onClick(id);
14910
+ KTToast.close(id);
14911
+ }
14912
+ });
14913
+ }
14914
+ var cancelBtn = toast.querySelector('[data-kt-toast-cancel]');
14915
+ if (cancelBtn && options.cancel && typeof options.cancel === 'object') {
14916
+ cancelBtn.addEventListener('click', function (e) {
14917
+ e.stopPropagation();
14918
+ if (typeof options.cancel === 'object' && options.cancel.onClick) {
14919
+ options.cancel.onClick(id);
14920
+ KTToast.close(id);
14921
+ }
14922
+ });
14923
+ }
14924
+ // Dismiss button handler
14925
+ var dismissBtn = toast.querySelector('[data-kt-toast-dismiss]');
14926
+ if (dismissBtn && options.dismiss !== false) {
14927
+ dismissBtn.addEventListener('click', function (e) {
14928
+ e.stopPropagation();
14929
+ KTToast.close(id);
14930
+ });
14931
+ }
14932
+ // If modal-like, set aria-modal
14933
+ if (options.important)
14934
+ toast.setAttribute('aria-modal', 'true');
14935
+ toast.style.pointerEvents = 'auto';
14936
+ // Progress line
14937
+ var duration = options.important
14938
+ ? null
14939
+ : ((_b = (_a = options.duration) !== null && _a !== void 0 ? _a : this.globalConfig.duration) !== null && _b !== void 0 ? _b : DEFAULT_CONFIG.duration);
14940
+ if (duration && options.progress) {
14941
+ var progress = document.createElement('div');
14942
+ progress.className = 'kt-toast-progress ' + (classNames.progress || '');
14943
+ progress.style.animationDuration = duration + 'ms';
14944
+ progress.setAttribute('data-kt-toast-progress', 'true');
14945
+ toast.appendChild(progress);
14946
+ }
14947
+ // Assign direction class to the toast itself, not the container
14948
+ var directionClassMap = {
14949
+ 'top-end': 'kt-toast-top-end',
14950
+ 'top-center': 'kt-toast-top-center',
14951
+ 'top-start': 'kt-toast-top-start',
14952
+ 'bottom-end': 'kt-toast-bottom-end',
14953
+ 'bottom-center': 'kt-toast-bottom-center',
14954
+ 'bottom-start': 'kt-toast-bottom-start',
14955
+ };
14956
+ Object.values(directionClassMap).forEach(function (cls) {
14957
+ return toast.classList.remove(cls);
14958
+ });
14959
+ var dirClass = directionClassMap[position] || 'kt-toast-top-end';
14960
+ toast.classList.add(dirClass);
14961
+ // Enforce maxToasts: remove oldest if needed
14962
+ var maxToasts = (_d = (_c = options.maxToasts) !== null && _c !== void 0 ? _c : this.globalConfig.maxToasts) !== null && _d !== void 0 ? _d : DEFAULT_CONFIG.maxToasts;
14963
+ var currentToasts = Array.from(container.children);
14964
+ if (currentToasts.length >= maxToasts && currentToasts.length > 0) {
14965
+ var oldestToast = currentToasts[currentToasts.length - 1];
14966
+ var oldestId = oldestToast.getAttribute('data-kt-toast-id');
14967
+ if (oldestId) {
14968
+ KTToast.close(oldestId);
14969
+ }
14970
+ else {
14971
+ oldestToast.remove();
14972
+ }
14973
+ }
14974
+ // Insert toast at the top
14975
+ container.insertBefore(toast, container.firstChild);
14976
+ KTToast.update(container);
14977
+ // Play beep if requested
14978
+ if (options.beep) {
14979
+ try {
14980
+ // Use Web Audio API for a short beep
14981
+ var ctx_1 = new (window.AudioContext ||
14982
+ window.webkitAudioContext)();
14983
+ var o_1 = ctx_1.createOscillator();
14984
+ var g = ctx_1.createGain();
14985
+ o_1.type = 'sine';
14986
+ o_1.frequency.value = 880;
14987
+ g.gain.value = 0.09;
14988
+ o_1.connect(g);
14989
+ g.connect(ctx_1.destination);
14990
+ o_1.start();
14991
+ setTimeout(function () {
14992
+ o_1.stop();
14993
+ ctx_1.close();
14994
+ }, 120);
14995
+ }
14996
+ catch (e) {
14997
+ /* ignore */
14998
+ }
14999
+ }
15000
+ KTToast._fireEventOnElement(toast, 'show', { id: id });
15001
+ KTToast._dispatchEventOnElement(toast, 'show', { id: id });
15002
+ var instance = { id: id, element: toast, timeoutId: 0 };
15003
+ KTToast.toasts.set(id, instance);
15004
+ // Auto-dismiss
15005
+ var timeoutId = undefined;
15006
+ var remaining = duration;
15007
+ var startTime;
15008
+ var paused = false;
15009
+ var progressEl = null;
15010
+ if (duration) {
15011
+ var startTimer_1 = function (ms) {
15012
+ startTime = Date.now();
15013
+ timeoutId = window.setTimeout(function () {
15014
+ var _a;
15015
+ (_a = options.onAutoClose) === null || _a === void 0 ? void 0 : _a.call(options, id);
15016
+ KTToast.close(id);
15017
+ }, ms);
15018
+ instance.timeoutId = timeoutId;
15019
+ };
15020
+ startTimer_1(duration);
15021
+ if (options.pauseOnHover) {
15022
+ progressEl = toast.querySelector('[data-kt-toast-progress]');
15023
+ var progressPausedAt_1 = 0;
15024
+ var pause = function () {
15025
+ if (!paused && timeoutId) {
15026
+ paused = true;
15027
+ window.clearTimeout(timeoutId);
15028
+ if (startTime) {
15029
+ remaining -= Date.now() - startTime;
15030
+ }
15031
+ // Pause progress bar
15032
+ if (progressEl) {
15033
+ var computedStyle = window.getComputedStyle(progressEl);
15034
+ var matrix = computedStyle.transform;
15035
+ var scaleX = 1;
15036
+ if (matrix && matrix !== 'none') {
15037
+ var values = matrix.match(/matrix\(([^)]+)\)/);
15038
+ if (values && values[1]) {
15039
+ scaleX = parseFloat(values[1].split(',')[0]);
15040
+ }
15041
+ }
15042
+ progressPausedAt_1 = scaleX;
15043
+ progressEl.style.animation = 'none';
15044
+ progressEl.style.transition = 'none';
15045
+ progressEl.style.transform = "scaleX(".concat(scaleX, ")");
15046
+ }
15047
+ }
15048
+ };
15049
+ var resume = function () {
15050
+ if (paused && remaining > 0) {
15051
+ paused = false;
15052
+ startTimer_1(remaining);
15053
+ // Resume progress bar
15054
+ if (progressEl) {
15055
+ progressEl.style.transition = 'transform 0ms';
15056
+ progressEl.style.transform = "scaleX(".concat(progressPausedAt_1, ")");
15057
+ progressEl.offsetHeight; // force reflow
15058
+ progressEl.style.transition = "transform ".concat(remaining, "ms linear");
15059
+ progressEl.style.transform = 'scaleX(0)';
15060
+ }
15061
+ }
15062
+ };
15063
+ toast.addEventListener('mouseenter', pause);
15064
+ toast.addEventListener('mouseleave', resume);
15065
+ }
15066
+ }
15067
+ KTToast._fireEventOnElement(toast, 'shown', { id: id });
15068
+ KTToast._dispatchEventOnElement(toast, 'shown', { id: id });
15069
+ return __assign(__assign({}, instance), { dismiss: function () { return KTToast.close(id); } });
15070
+ };
15071
+ /**
15072
+ * Close and remove all active toasts.
15073
+ */
15074
+ KTToast.clearAll = function () {
15075
+ for (var _i = 0, _a = Array.from(this.toasts.keys()); _i < _a.length; _i++) {
15076
+ var id = _a[_i];
15077
+ console.log('clearAll:', id);
15078
+ this.close(id);
15079
+ }
15080
+ };
15081
+ /**
15082
+ * Close a toast by ID or instance.
15083
+ * @param idOrInstance Toast ID string or KTToastInstance.
15084
+ */
15085
+ KTToast.close = function (idOrInstance) {
15086
+ var inst;
15087
+ var id;
15088
+ if (!idOrInstance)
15089
+ return;
15090
+ if (typeof idOrInstance === 'string') {
15091
+ id = idOrInstance;
15092
+ inst = this.toasts.get(id);
15093
+ }
15094
+ else if (typeof idOrInstance === 'object' && idOrInstance.id) {
15095
+ id = idOrInstance.id;
15096
+ inst = idOrInstance;
15097
+ }
15098
+ if (!inst || !id)
15099
+ return;
15100
+ if (inst._closing)
15101
+ return; // Prevent double-close
15102
+ inst._closing = true;
15103
+ clearTimeout(inst.timeoutId);
15104
+ KTToast._fireEventOnElement(inst.element, 'hide', { id: id });
15105
+ KTToast._dispatchEventOnElement(inst.element, 'hide', { id: id });
15106
+ // Remove progress bar instantly if present
15107
+ var progressEl = inst.element.querySelector('[data-kt-toast-progress]');
15108
+ if (progressEl)
15109
+ progressEl.remove();
15110
+ inst.element.style.animation = 'kt-toast-out 0.25s forwards';
15111
+ setTimeout(function () {
15112
+ var _a;
15113
+ var parent = inst === null || inst === void 0 ? void 0 : inst.element.parentElement;
15114
+ inst === null || inst === void 0 ? void 0 : inst.element.remove();
15115
+ KTToast.toasts.delete(id);
15116
+ // Try to call onDismiss if available in the toast instance (if stored)
15117
+ if (typeof ((_a = inst.options) === null || _a === void 0 ? void 0 : _a.onDismiss) === 'function') {
15118
+ inst.options.onDismiss(id);
15119
+ }
15120
+ KTToast._fireEventOnElement(inst.element, 'hidden', { id: id });
15121
+ KTToast._dispatchEventOnElement(inst.element, 'hidden', { id: id });
15122
+ // update toasts asynchronously after DOM update
15123
+ setTimeout(function () {
15124
+ KTToast.update(parent);
15125
+ }, 0);
15126
+ }, 250);
15127
+ };
15128
+ /**
15129
+ * Dispatches a custom 'kt.toast.{eventType}' event on the given element.
15130
+ * @param element The toast element.
15131
+ * @param eventType The event type (e.g. 'show', 'hide').
15132
+ * @param payload Optional event detail payload.
15133
+ */
15134
+ KTToast._fireEventOnElement = function (element, eventType, payload) {
15135
+ var event = new CustomEvent("kt.toast.".concat(eventType), { detail: payload });
15136
+ element.dispatchEvent(event);
15137
+ };
15138
+ /**
15139
+ * Dispatches a custom event (not namespaced) on the given element.
15140
+ * @param element The toast element.
15141
+ * @param eventType The event type.
15142
+ * @param payload Optional event detail payload.
15143
+ */
15144
+ KTToast._dispatchEventOnElement = function (element, eventType, payload) {
15145
+ var event = new CustomEvent(eventType, { detail: payload });
15146
+ element.dispatchEvent(event);
15147
+ };
15148
+ /**
15149
+ * Initialize toast system (placeholder for future use).
15150
+ */
15151
+ KTToast.init = function () { };
15152
+ KTToast.containerMap = new Map();
15153
+ KTToast.toasts = new Map();
15154
+ KTToast.globalConfig = __assign({}, DEFAULT_CONFIG);
15155
+ return KTToast;
15156
+ }(component_1.default));
15157
+ exports.KTToast = KTToast;
15158
+
15159
+
14873
15160
  /***/ }),
14874
15161
 
14875
15162
  /***/ 9010:
@@ -15164,6 +15451,30 @@ var KTDom = {
15164
15451
  }
15165
15452
  return attributes;
15166
15453
  },
15454
+ getDataAttributesByJson: function (element, prefix) {
15455
+ if (!element) {
15456
+ return {};
15457
+ }
15458
+ var rawValue = element.dataset[prefix];
15459
+ if (!rawValue) {
15460
+ return {};
15461
+ }
15462
+ var parsedValue = utils_1.default.parseDataAttribute(rawValue);
15463
+ if (typeof parsedValue === 'string') {
15464
+ try {
15465
+ return JSON.parse(parsedValue);
15466
+ }
15467
+ catch (e) {
15468
+ console.error("Invalid JSON format for '".concat(prefix, "': ").concat(e instanceof Error ? e.message : e, " ").concat(rawValue));
15469
+ }
15470
+ }
15471
+ // If it's already an object, return as is
15472
+ if (typeof parsedValue === 'object' && parsedValue !== null) {
15473
+ return parsedValue;
15474
+ }
15475
+ // For other types (number, boolean, null), return an empty object
15476
+ return {};
15477
+ },
15167
15478
  ready: function (callback) {
15168
15479
  if (document.readyState === 'loading') {
15169
15480
  document.addEventListener('DOMContentLoaded', function () {
@@ -15189,12 +15500,14 @@ exports["default"] = KTDom;
15189
15500
  * Copyright 2025 by Keenthemes Inc
15190
15501
  */
15191
15502
  Object.defineProperty(exports, "__esModule", ({ value: true }));
15192
- exports.EventManager = exports.FocusManager = void 0;
15503
+ exports.TypeToSearchBuffer = exports.EventManager = exports.FocusManager = exports.highlightTextInElementDebounced = void 0;
15193
15504
  exports.formatCurrency = formatCurrency;
15194
15505
  exports.filterOptions = filterOptions;
15195
15506
  exports.highlightTextInElement = highlightTextInElement;
15196
- exports.handleDropdownKeyNavigation = handleDropdownKeyNavigation;
15197
15507
  exports.debounce = debounce;
15508
+ exports.renderTemplateString = renderTemplateString;
15509
+ exports.stringToElement = stringToElement;
15510
+ // utils.ts
15198
15511
  var templates_1 = __webpack_require__(9069);
15199
15512
  /**
15200
15513
  * Format a number as a currency string
@@ -15235,6 +15548,17 @@ function filterOptions(options, query, config, dropdownElement, onVisibleCount)
15235
15548
  option.setAttribute('style', styleAttr.replace(/display:\s*[^;]+;?/gi, '').trim());
15236
15549
  }
15237
15550
  }
15551
+ // Clear highlights by restoring original text content
15552
+ if (option.dataset && option.dataset.originalText) {
15553
+ option.innerHTML = option.dataset.originalText;
15554
+ }
15555
+ else {
15556
+ option.innerHTML = option.textContent || '';
15557
+ }
15558
+ // Remove the cache if present
15559
+ if (option.dataset && option.dataset.originalText) {
15560
+ delete option.dataset.originalText;
15561
+ }
15238
15562
  visibleOptionsCount++;
15239
15563
  }
15240
15564
  // Call the callback with the visible count if provided
@@ -15248,6 +15572,8 @@ function filterOptions(options, query, config, dropdownElement, onVisibleCount)
15248
15572
  var option = options_2[_b];
15249
15573
  var optionText = ((_a = option.textContent) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
15250
15574
  var isMatch = optionText.includes(query.toLowerCase());
15575
+ // Check if option is disabled
15576
+ var isDisabled = option.classList.contains('disabled') || option.getAttribute('aria-disabled') === 'true';
15251
15577
  if (isMatch || query.trim() === '') {
15252
15578
  // Show option by removing the hidden class and any display inline styles
15253
15579
  option.classList.remove('hidden');
@@ -15264,22 +15590,11 @@ function filterOptions(options, query, config, dropdownElement, onVisibleCount)
15264
15590
  }
15265
15591
  }
15266
15592
  visibleOptionsCount++;
15267
- // Apply highlighting if needed - but preserve the option structure
15268
- if (isMatch && config.searchHighlight && query.trim() !== '') {
15269
- // Clone option elements that contain icons or descriptions
15270
- var hasIcon = option.querySelector('[data-kt-select-option-icon]') !== null;
15271
- var hasDescription = option.querySelector('[data-kt-select-option-description]') !== null;
15272
- if (hasIcon || hasDescription) {
15273
- // Only highlight the text part without changing structure
15274
- var titleElement = option.querySelector('[data-kt-option-title]');
15275
- if (titleElement) {
15276
- highlightTextInElement(titleElement, query, config);
15277
- }
15278
- }
15279
- else {
15280
- // Simple option with just text - standard highlighting
15281
- highlightTextInElement(option, query, config);
15593
+ if (config.searchHighlight && query.trim() !== '') {
15594
+ if (option.dataset && !option.dataset.originalText) {
15595
+ option.dataset.originalText = option.innerHTML;
15282
15596
  }
15597
+ (0, exports.highlightTextInElementDebounced)(option, query, config);
15283
15598
  }
15284
15599
  }
15285
15600
  else {
@@ -15316,37 +15631,39 @@ function highlightTextInElement(element, query, config) {
15316
15631
  if (!element || !query || query.trim() === '')
15317
15632
  return;
15318
15633
  var queryLower = query.toLowerCase();
15319
- function walk(node) {
15320
- var _a;
15321
- if (node.nodeType === Node.TEXT_NODE) {
15322
- var text = node.nodeValue || '';
15323
- var textLower = text.toLowerCase();
15324
- var matchIndex = textLower.indexOf(queryLower);
15325
- if (matchIndex !== -1) {
15326
- var before = text.slice(0, matchIndex);
15327
- var match = text.slice(matchIndex, matchIndex + query.length);
15328
- var after = text.slice(matchIndex + query.length);
15329
- var frag = document.createDocumentFragment();
15330
- if (before)
15331
- frag.appendChild(document.createTextNode(before));
15332
- // Use the highlight template, which returns an HTMLElement
15333
- var highlightSpan = templates_1.defaultTemplates.highlight(config, match);
15334
- frag.appendChild(highlightSpan);
15335
- if (after)
15336
- frag.appendChild(document.createTextNode(after));
15337
- (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(frag, node);
15338
- // Only highlight the first occurrence in this node
15339
- }
15340
- }
15341
- else if (node.nodeType === Node.ELEMENT_NODE) {
15342
- // Don't re-highlight already highlighted nodes
15343
- if (node.classList.contains('highlight'))
15344
- return;
15345
- Array.from(node.childNodes).forEach(walk);
15346
- }
15634
+ var text = element.textContent || '';
15635
+ if (!text)
15636
+ return;
15637
+ // Escape regex special characters in query
15638
+ var escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
15639
+ var regex = new RegExp(escapedQuery, 'gi');
15640
+ // Replace all matches with the highlight template
15641
+ var lastIndex = 0;
15642
+ var result = '';
15643
+ var match;
15644
+ var matches = [];
15645
+ while ((match = regex.exec(text)) !== null) {
15646
+ matches.push({ start: match.index, end: regex.lastIndex });
15347
15647
  }
15348
- walk(element);
15648
+ if (matches.length === 0) {
15649
+ element.innerHTML = text;
15650
+ return;
15651
+ }
15652
+ for (var i = 0; i < matches.length; i++) {
15653
+ var _a = matches[i], start = _a.start, end = _a.end;
15654
+ // Add text before match
15655
+ result += text.slice(lastIndex, start);
15656
+ // Add highlighted match using template
15657
+ var highlighted = templates_1.defaultTemplates.highlight(config, text.slice(start, end)).outerHTML;
15658
+ result += highlighted;
15659
+ lastIndex = end;
15660
+ }
15661
+ // Add remaining text
15662
+ result += text.slice(lastIndex);
15663
+ element.innerHTML = result;
15349
15664
  }
15665
+ // Debounced version for performance
15666
+ exports.highlightTextInElementDebounced = debounce(highlightTextInElement, 100);
15350
15667
  /**
15351
15668
  * Focus manager for keyboard navigation
15352
15669
  * Consolidates redundant focus management logic into shared functions
@@ -15355,16 +15672,14 @@ var FocusManager = /** @class */ (function () {
15355
15672
  function FocusManager(element, optionsSelector, config) {
15356
15673
  if (optionsSelector === void 0) { optionsSelector = '[data-kt-select-option]'; }
15357
15674
  this._focusedOptionIndex = null;
15675
+ this._onFocusChange = null;
15358
15676
  this._element = element;
15359
15677
  this._optionsSelector = optionsSelector;
15360
15678
  this._eventManager = new EventManager();
15361
- // Use config values if provided, otherwise fallback to defaults
15362
- this._focusClass = (config === null || config === void 0 ? void 0 : config.focusClass) || 'option-focused';
15363
- this._hoverClass = (config === null || config === void 0 ? void 0 : config.hoverClass) || 'hovered';
15364
- this._bgClass = (config === null || config === void 0 ? void 0 : config.bgClass) || 'bg-blue-50';
15365
- this._fontClass = (config === null || config === void 0 ? void 0 : config.fontClass) || 'font-medium';
15366
15679
  // Add click handler to update focus state when options are clicked
15367
15680
  this._setupOptionClickHandlers();
15681
+ this._focusClass = 'focus'; // or whatever your intended class is
15682
+ this._hoverClass = 'hover'; // or your intended class
15368
15683
  }
15369
15684
  /**
15370
15685
  * Set up click handlers for all options to update focus state
@@ -15376,15 +15691,6 @@ var FocusManager = /** @class */ (function () {
15376
15691
  var target = e.target;
15377
15692
  var optionElement = target.closest(_this._optionsSelector);
15378
15693
  if (optionElement) {
15379
- // First clear all focus
15380
- _this.resetFocus();
15381
- // Then update the focused index based on the clicked option
15382
- var options = _this.getVisibleOptions();
15383
- var clickedIndex = options.indexOf(optionElement);
15384
- if (clickedIndex >= 0) {
15385
- _this._focusedOptionIndex = clickedIndex;
15386
- _this.applyFocus(options[clickedIndex]);
15387
- }
15388
15694
  }
15389
15695
  });
15390
15696
  };
@@ -15406,24 +15712,88 @@ var FocusManager = /** @class */ (function () {
15406
15712
  });
15407
15713
  };
15408
15714
  /**
15409
- * Focus the next visible option
15715
+ * Focus the first visible option
15410
15716
  */
15411
- FocusManager.prototype.focusNext = function () {
15717
+ FocusManager.prototype.focusFirst = function () {
15412
15718
  var options = this.getVisibleOptions();
15413
15719
  if (options.length === 0)
15414
15720
  return null;
15415
- this.resetFocus();
15416
- if (this._focusedOptionIndex === null) {
15417
- this._focusedOptionIndex = 0;
15721
+ for (var i = 0; i < options.length; i++) {
15722
+ var option = options[i];
15723
+ if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
15724
+ this.resetFocus();
15725
+ this._focusedOptionIndex = i;
15726
+ this.applyFocus(option);
15727
+ this.scrollIntoView(option);
15728
+ return option;
15729
+ }
15418
15730
  }
15419
- else {
15420
- this._focusedOptionIndex =
15421
- (this._focusedOptionIndex + 1) % options.length;
15731
+ return null;
15732
+ };
15733
+ /**
15734
+ * Focus the last visible option
15735
+ */
15736
+ FocusManager.prototype.focusLast = function () {
15737
+ var options = this.getVisibleOptions();
15738
+ if (options.length === 0)
15739
+ return null;
15740
+ for (var i = options.length - 1; i >= 0; i--) {
15741
+ var option = options[i];
15742
+ if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
15743
+ this.resetFocus();
15744
+ this._focusedOptionIndex = i;
15745
+ this.applyFocus(option);
15746
+ this.scrollIntoView(option);
15747
+ return option;
15748
+ }
15422
15749
  }
15423
- var option = options[this._focusedOptionIndex];
15424
- this.applyFocus(option);
15425
- this.scrollIntoView(option);
15426
- return option;
15750
+ return null;
15751
+ };
15752
+ /**
15753
+ * Focus the next visible option that matches the search string
15754
+ */
15755
+ FocusManager.prototype.focusByString = function (str) {
15756
+ var _a, _b, _c;
15757
+ var options = this.getVisibleOptions();
15758
+ if (options.length === 0)
15759
+ return null;
15760
+ var lowerStr = str.toLowerCase();
15761
+ var startIdx = ((_a = this._focusedOptionIndex) !== null && _a !== void 0 ? _a : -1) + 1;
15762
+ for (var i = 0; i < options.length; i++) {
15763
+ var idx = (startIdx + i) % options.length;
15764
+ var option = options[idx];
15765
+ if (!option.classList.contains('disabled') &&
15766
+ option.getAttribute('aria-disabled') !== 'true' &&
15767
+ (((_b = option.textContent) === null || _b === void 0 ? void 0 : _b.toLowerCase().startsWith(lowerStr)) || ((_c = option.dataset.value) === null || _c === void 0 ? void 0 : _c.toLowerCase().startsWith(lowerStr)))) {
15768
+ this._focusedOptionIndex = idx;
15769
+ this.applyFocus(option);
15770
+ this.scrollIntoView(option);
15771
+ return option;
15772
+ }
15773
+ }
15774
+ return null;
15775
+ };
15776
+ /**
15777
+ * Focus the next visible option
15778
+ */
15779
+ FocusManager.prototype.focusNext = function () {
15780
+ var options = this.getVisibleOptions();
15781
+ if (options.length === 0)
15782
+ return null;
15783
+ var idx = this._focusedOptionIndex === null ? 0 : (this._focusedOptionIndex + 1) % options.length;
15784
+ var startIdx = idx;
15785
+ do {
15786
+ var option = options[idx];
15787
+ if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
15788
+ this.resetFocus();
15789
+ this._focusedOptionIndex = idx;
15790
+ this.applyFocus(option);
15791
+ this.scrollIntoView(option);
15792
+ return option;
15793
+ }
15794
+ idx = (idx + 1) % options.length;
15795
+ } while (idx !== startIdx);
15796
+ return null;
15427
15797
  };
15428
15798
  /**
15429
15799
  * Focus the previous visible option
@@ -15432,18 +15802,20 @@ var FocusManager = /** @class */ (function () {
15432
15802
  var options = this.getVisibleOptions();
15433
15803
  if (options.length === 0)
15434
15804
  return null;
15435
- this.resetFocus();
15436
- if (this._focusedOptionIndex === null) {
15437
- this._focusedOptionIndex = options.length - 1;
15438
- }
15439
- else {
15440
- this._focusedOptionIndex =
15441
- (this._focusedOptionIndex - 1 + options.length) % options.length;
15442
- }
15443
- var option = options[this._focusedOptionIndex];
15444
- this.applyFocus(option);
15445
- this.scrollIntoView(option);
15446
- return option;
15805
+ var idx = this._focusedOptionIndex === null ? options.length - 1 : (this._focusedOptionIndex - 1 + options.length) % options.length;
15806
+ var startIdx = idx;
15807
+ do {
15808
+ var option = options[idx];
15809
+ if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
15810
+ this.resetFocus();
15811
+ this._focusedOptionIndex = idx;
15812
+ this.applyFocus(option);
15813
+ this.scrollIntoView(option);
15814
+ return option;
15815
+ }
15816
+ idx = (idx - 1 + options.length) % options.length;
15817
+ } while (idx !== startIdx);
15818
+ return null;
15447
15819
  };
15448
15820
  /**
15449
15821
  * Apply focus to a specific option
@@ -15451,27 +15823,23 @@ var FocusManager = /** @class */ (function () {
15451
15823
  FocusManager.prototype.applyFocus = function (option) {
15452
15824
  if (!option)
15453
15825
  return;
15454
- // Remove focus from all options first
15826
+ if (option.classList.contains('disabled') || option.getAttribute('aria-disabled') === 'true') {
15827
+ return;
15828
+ }
15455
15829
  this.resetFocus();
15456
- // Add focus to this option
15457
15830
  option.classList.add(this._focusClass);
15458
15831
  option.classList.add(this._hoverClass);
15459
- option.classList.add(this._bgClass);
15460
- option.classList.add(this._fontClass);
15832
+ this._triggerFocusChange();
15461
15833
  };
15462
15834
  /**
15463
15835
  * Reset focus on all options
15464
15836
  */
15465
15837
  FocusManager.prototype.resetFocus = function () {
15466
15838
  var _this = this;
15467
- // Find all elements with the focus classes
15468
- var focusedElements = this._element.querySelectorAll(".".concat(this._focusClass, ", .").concat(this._hoverClass, ", .").concat(this._bgClass, ", .").concat(this._fontClass));
15469
- // Remove classes from all elements
15839
+ var focusedElements = this._element.querySelectorAll(".".concat(this._focusClass, ", .").concat(this._hoverClass));
15840
+ // Remove focus and hover classes from all options
15470
15841
  focusedElements.forEach(function (element) {
15471
- element.classList.remove(_this._focusClass);
15472
- element.classList.remove(_this._hoverClass);
15473
- element.classList.remove(_this._bgClass);
15474
- element.classList.remove(_this._fontClass);
15842
+ element.classList.remove(_this._focusClass, _this._hoverClass);
15475
15843
  });
15476
15844
  // Reset index if visible options have changed
15477
15845
  var visibleOptions = this.getVisibleOptions();
@@ -15486,7 +15854,7 @@ var FocusManager = /** @class */ (function () {
15486
15854
  FocusManager.prototype.scrollIntoView = function (option) {
15487
15855
  if (!option)
15488
15856
  return;
15489
- var container = this._element.querySelector('[data-kt-select-options-container]');
15857
+ var container = this._element.querySelector('[data-kt-select-options]');
15490
15858
  if (!container)
15491
15859
  return;
15492
15860
  var optionRect = option.getBoundingClientRect();
@@ -15537,6 +15905,17 @@ var FocusManager = /** @class */ (function () {
15537
15905
  FocusManager.prototype.setFocusedIndex = function (index) {
15538
15906
  this._focusedOptionIndex = index;
15539
15907
  };
15908
+ /**
15909
+ * Set a callback to be called when focus changes
15910
+ */
15911
+ FocusManager.prototype.setOnFocusChange = function (cb) {
15912
+ this._onFocusChange = cb;
15913
+ };
15914
+ FocusManager.prototype._triggerFocusChange = function () {
15915
+ if (this._onFocusChange) {
15916
+ this._onFocusChange(this.getFocusedOption(), this._focusedOptionIndex);
15917
+ }
15918
+ };
15540
15919
  /**
15541
15920
  * Clean up event listeners
15542
15921
  */
@@ -15548,166 +15927,6 @@ var FocusManager = /** @class */ (function () {
15548
15927
  return FocusManager;
15549
15928
  }());
15550
15929
  exports.FocusManager = FocusManager;
15551
- /**
15552
- * Shared keyboard navigation handler for dropdown options
15553
- * Can be used by both combobox and search modules
15554
- */
15555
- function handleDropdownKeyNavigation(event, select, config, callbacks) {
15556
- try {
15557
- // Get the dropdown state
15558
- var isDropdownOpen = select._dropdownIsOpen;
15559
- // Log the event to help debug
15560
- var origin_1 = 'handleDropdownKeyNavigation';
15561
- if (select.getConfig && select.getConfig().debug)
15562
- console.log("[".concat(origin_1, "] Key: ").concat(event.key, ", Dropdown open: ").concat(isDropdownOpen));
15563
- // Handle basic keyboard navigation
15564
- switch (event.key) {
15565
- case 'ArrowDown':
15566
- if (!isDropdownOpen) {
15567
- if (select.getConfig && select.getConfig().debug)
15568
- console.log("[".concat(origin_1, "] Opening dropdown on ArrowDown"));
15569
- select.openDropdown();
15570
- // Focus the first option after opening
15571
- setTimeout(function () {
15572
- select._focusNextOption();
15573
- }, 50);
15574
- }
15575
- else if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onArrowDown) {
15576
- if (select.getConfig && select.getConfig().debug)
15577
- console.log("[".concat(origin_1, "] Using custom onArrowDown callback"));
15578
- callbacks.onArrowDown();
15579
- }
15580
- else {
15581
- if (select.getConfig && select.getConfig().debug)
15582
- console.log("[".concat(origin_1, "] Using default _focusNextOption"));
15583
- var focusedOption = select._focusNextOption();
15584
- // Ensure we have a focused option
15585
- if (focusedOption) {
15586
- if (select.getConfig && select.getConfig().debug)
15587
- console.log("[".concat(origin_1, "] Focused next option:"), focusedOption);
15588
- }
15589
- }
15590
- event.preventDefault();
15591
- break;
15592
- case 'ArrowUp':
15593
- if (!isDropdownOpen) {
15594
- if (select.getConfig && select.getConfig().debug)
15595
- console.log("[".concat(origin_1, "] Opening dropdown on ArrowUp"));
15596
- select.openDropdown();
15597
- // Focus the last option after opening
15598
- setTimeout(function () {
15599
- select._focusPreviousOption();
15600
- }, 50);
15601
- }
15602
- else if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onArrowUp) {
15603
- if (select.getConfig && select.getConfig().debug)
15604
- console.log("[".concat(origin_1, "] Using custom onArrowUp callback"));
15605
- callbacks.onArrowUp();
15606
- }
15607
- else {
15608
- if (select.getConfig && select.getConfig().debug)
15609
- console.log("[".concat(origin_1, "] Using default _focusPreviousOption"));
15610
- var focusedOption = select._focusPreviousOption();
15611
- // Ensure we have a focused option
15612
- if (focusedOption) {
15613
- if (select.getConfig && select.getConfig().debug)
15614
- console.log("[".concat(origin_1, "] Focused previous option:"), focusedOption);
15615
- }
15616
- }
15617
- event.preventDefault();
15618
- break;
15619
- case 'Enter':
15620
- // Prevent form submission
15621
- event.preventDefault();
15622
- if (isDropdownOpen) {
15623
- if (select.getConfig && select.getConfig().debug)
15624
- console.log("[".concat(origin_1, "] Enter pressed with dropdown open"));
15625
- // For combobox mode, ensure we update the input value directly
15626
- var isCombobox = select.getConfig().mode === 'combobox';
15627
- var comboboxModule = select._comboboxModule;
15628
- if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onEnter) {
15629
- if (select.getConfig && select.getConfig().debug)
15630
- console.log("[".concat(origin_1, "] Using custom onEnter callback"));
15631
- callbacks.onEnter();
15632
- }
15633
- else {
15634
- if (select.getConfig && select.getConfig().debug)
15635
- console.log("[".concat(origin_1, "] Using default selectFocusedOption"));
15636
- // Make sure there is a focused option before trying to select it
15637
- if (select._focusManager &&
15638
- select._focusManager.getFocusedOption()) {
15639
- select.selectFocusedOption();
15640
- }
15641
- else {
15642
- // If no option is focused, try to focus the first one
15643
- var focusedOption = select._focusNextOption();
15644
- // Only select if an option was successfully focused
15645
- if (focusedOption) {
15646
- select.selectFocusedOption();
15647
- }
15648
- }
15649
- }
15650
- // Close dropdown after selection if not multiple and closeOnSelect is true
15651
- if (!config.multiple && config.closeOnSelect !== false) {
15652
- if (select.getConfig && select.getConfig().debug)
15653
- console.log("[".concat(origin_1, "] Closing dropdown after selection"));
15654
- select.closeDropdown();
15655
- }
15656
- }
15657
- else {
15658
- // If dropdown is closed, open it on Enter
15659
- if (select.getConfig && select.getConfig().debug)
15660
- console.log("[".concat(origin_1, "] Opening dropdown on Enter"));
15661
- select.openDropdown();
15662
- // Focus the first option after opening
15663
- setTimeout(function () {
15664
- select._focusNextOption();
15665
- }, 50);
15666
- }
15667
- break;
15668
- case 'Tab':
15669
- // Only handle tab if dropdown is open
15670
- if (isDropdownOpen) {
15671
- if (select.getConfig && select.getConfig().debug)
15672
- console.log("[".concat(origin_1, "] Closing dropdown on Tab"));
15673
- select.closeDropdown();
15674
- if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onClose) {
15675
- callbacks.onClose();
15676
- }
15677
- // Don't prevent default tab behavior - let it move focus naturally
15678
- }
15679
- break;
15680
- case 'Escape':
15681
- // Only handle escape if dropdown is open
15682
- if (isDropdownOpen) {
15683
- if (select.getConfig && select.getConfig().debug)
15684
- console.log("[".concat(origin_1, "] Closing dropdown on Escape"));
15685
- select.closeDropdown();
15686
- if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onClose) {
15687
- callbacks.onClose();
15688
- }
15689
- event.preventDefault(); // Prevent other escape handlers
15690
- }
15691
- break;
15692
- case ' ': // Space key
15693
- // If dropdown is closed, space should open it (but not if in combobox mode)
15694
- if (!isDropdownOpen && !(select.getConfig().mode === 'combobox')) {
15695
- if (select.getConfig && select.getConfig().debug)
15696
- console.log("[".concat(origin_1, "] Opening dropdown on Space"));
15697
- select.openDropdown();
15698
- // Focus the first option after opening
15699
- setTimeout(function () {
15700
- select._focusNextOption();
15701
- }, 50);
15702
- event.preventDefault();
15703
- }
15704
- break;
15705
- }
15706
- }
15707
- catch (error) {
15708
- console.error('Error in keyboard navigation handler:', error);
15709
- }
15710
- }
15711
15930
  /**
15712
15931
  * Centralized event listener management
15713
15932
  */
@@ -15764,7 +15983,7 @@ var EventManager = /** @class */ (function () {
15764
15983
  // Go through each event type
15765
15984
  this._boundHandlers.forEach(function (eventMap, event) {
15766
15985
  // For each event type, go through each handler
15767
- eventMap.forEach(function (boundHandler, originalHandler) {
15986
+ eventMap.forEach(function (boundHandler) {
15768
15987
  element.removeEventListener(event, boundHandler);
15769
15988
  });
15770
15989
  });
@@ -15788,6 +16007,45 @@ function debounce(func, delay) {
15788
16007
  timeout = setTimeout(function () { return func.apply(void 0, args); }, delay);
15789
16008
  };
15790
16009
  }
16010
+ /**
16011
+ * Replaces all {{key}} in the template with the corresponding value from the data object.
16012
+ * If a key is missing in data, replaces with an empty string.
16013
+ */
16014
+ function renderTemplateString(template, data) {
16015
+ return template.replace(/{{(\w+)}}/g, function (_, key) {
16016
+ return data[key] !== undefined && data[key] !== null ? String(data[key]) : '';
16017
+ });
16018
+ }
16019
+ // Type-to-search buffer utility for keyboard navigation
16020
+ var TypeToSearchBuffer = /** @class */ (function () {
16021
+ function TypeToSearchBuffer(timeout) {
16022
+ if (timeout === void 0) { timeout = 500; }
16023
+ this.buffer = '';
16024
+ this.lastTime = 0;
16025
+ this.timeout = timeout;
16026
+ }
16027
+ TypeToSearchBuffer.prototype.push = function (char) {
16028
+ var now = Date.now();
16029
+ if (now - this.lastTime > this.timeout) {
16030
+ this.buffer = '';
16031
+ }
16032
+ this.buffer += char;
16033
+ this.lastTime = now;
16034
+ };
16035
+ TypeToSearchBuffer.prototype.getBuffer = function () {
16036
+ return this.buffer;
16037
+ };
16038
+ TypeToSearchBuffer.prototype.clear = function () {
16039
+ this.buffer = '';
16040
+ };
16041
+ return TypeToSearchBuffer;
16042
+ }());
16043
+ exports.TypeToSearchBuffer = TypeToSearchBuffer;
16044
+ function stringToElement(html) {
16045
+ var template = document.createElement('template');
16046
+ template.innerHTML = html.trim();
16047
+ return template.content.firstElementChild;
16048
+ }
15791
16049
 
15792
16050
 
15793
16051
  /***/ }),
@@ -15828,34 +16086,30 @@ var __assign = (this && this.__assign) || function () {
15828
16086
  return __assign.apply(this, arguments);
15829
16087
  };
15830
16088
  Object.defineProperty(exports, "__esModule", ({ value: true }));
15831
- exports.defaultTemplates = void 0;
16089
+ exports.defaultTemplates = exports.coreTemplateStrings = void 0;
15832
16090
  exports.setTemplateStrings = setTemplateStrings;
15833
16091
  exports.getTemplateStrings = getTemplateStrings;
15834
- var types_1 = __webpack_require__(8135);
16092
+ var utils_1 = __webpack_require__(9011);
15835
16093
  /**
15836
16094
  * Default HTML string templates for KTSelect. All UI structure is defined here.
15837
16095
  * Users can override any template by providing a matching key in the config.templates object.
15838
16096
  */
15839
- var defaultTemplateStrings = {
15840
- dropdownContent: "<div data-kt-select-dropdown-content class=\"kt-select-dropdown hidden\" style=\"z-index: {{zindex}};\">{{content}}</div>",
15841
- optionsContainer: "<ul role=\"listbox\" aria-label=\"{{label}}\" data-kt-select-options-container style=\"max-height: {{height}}px; overflow-y: auto;\">{{options}}</ul>",
15842
- emptyOption: "<option value=\"\">{{placeholder}}</option>",
15843
- errorOption: "<option value=\"\" disabled selected>{{errorMessage}}</option>", // Template for error <option>
15844
- loadMore: "<li class=\"py-2 px-4 text-center text-gray-600 cursor-pointer hover:bg-gray-100\" data-kt-select-load-more>{{loadMoreText}}</li>",
15845
- dropdown: "<div data-kt-select-dropdown-content class=\"absolute z-10 w-full mt-2 bg-white border border-gray-200 rounded-md shadow-md\">\n\t\t{{search}}\n\t\t<ul role=\"listbox\" aria-label=\"{{label}}\" data-kt-select-options-container style=\"max-height: {{height}}px; overflow-y: auto;\">\n\t\t\t{{options}}\n\t\t</ul>\n\t</div>",
15846
- error: "<li class=\"px-3 py-2 text-red-500\" role=\"alert\">{{errorMessage}}</li>",
15847
- highlight: "<span class=\"highlight\">{{text}}</span>",
15848
- main: "<div data-kt-select-wrapper class=\"relative\" data-kt-select-mode=\"{{mode}}\"></div>",
15849
- displayCombobox: "<div class=\"relative flex items-center w-full\">\n\t\t<input data-kt-select-search data-kt-select-display data-kt-select-value type=\"text\" class=\"flex-1 w-full items-center justify-between px-3 py-2 border border-gray-300 rounded-md cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-200 focus:border-blue-400\" placeholder=\"{{placeholder}}\" role=\"searchbox\" aria-label=\"{{label}}\" {{disabled}} />\n\t\t<button type=\"button\" data-kt-select-clear-button class=\"absolute right-3 hidden text-gray-400 hover:text-gray-600\" aria-label=\"Clear selection\">\n\t\t<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t\t\t<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n\t\t\t<line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n\t\t</svg>\n\t\t</button>\n\t</div>",
15850
- icon: "<span class=\"option-icon mr-2\"><img src=\"{{icon}}\" class=\"rounded-full w-6 h-6\" /></span>",
15851
- description: "<div class=\"option-description text-sm text-gray-500\">{{description}}</div>",
15852
- display: "<div data-kt-select-display class=\"flex items-center justify-between px-3 py-2 border border-gray-300 rounded-md cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-200 focus:border-blue-400\" tabindex=\"{{tabindex}}\" role=\"button\" aria-haspopup=\"listbox\" aria-expanded=\"false\" aria-label=\"{{label}}\" {{disabled}}>\n\t\t<span data-kt-select-value>{{placeholder}}</span>\n\t\t<span data-kt-select-arrow class=\"ml-2\">\n\t\t\t<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t\t\t\t<polyline points=\"6 9 12 15 18 9\"></polyline>\n\t\t\t</svg>\n\t\t</span>\n\t</div>",
15853
- option: "<li data-kt-select-option data-value=\"{{value}}\" class=\"px-3 py-2 cursor-pointer hover:bg-gray-100 flex items-center{{selectedClass}}{{disabledClass}}\" role=\"option\" {{selected}} {{disabled}}>{{icon}}<div class=\"option-content\"><div class=\"option-title\" data-kt-option-title>{{text}}</div>{{description}}</div></li>",
15854
- optionGroup: "<li role=\"group\" aria-label=\"{{label}}\" class=\"py-1\"><div class=\"px-3 py-1 text-xs font-semibold text-gray-500 uppercase\">{{label}}</div><ul>{{optionsHtml}}</ul></li>",
15855
- search: "<div class=\"px-3 py-2 border-b border-gray-200\"><input type=\"text\" data-kt-select-search placeholder=\"{{searchPlaceholder}}\" class=\"w-full border-none focus:outline-none text-sm\" role=\"searchbox\" aria-label=\"{{searchPlaceholder}}\"/></div>",
15856
- noResults: "<li class=\"px-3 py-2 text-gray-500\" role=\"status\">{{searchNotFoundText}}</li>",
15857
- loading: "<li class=\"px-3 py-2 text-gray-500 italic\" role=\"status\" aria-live=\"polite\">{{loadingMessage}}</li>",
15858
- tag: "<div data-kt-select-tag class=\"inline-flex items-center bg-blue-50 border border-blue-100 rounded px-2 py-1 text-sm mr-1 mb-1\"><span>{{title}}</span><span data-kt-select-remove-button data-value=\"{{id}}\" class=\"ml-1 text-blue-400 hover:text-blue-600 cursor-pointer\" role=\"button\" aria-label=\"Remove {{safeTitle}}\" tabindex=\"0\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line></svg></span></div>",
16097
+ exports.coreTemplateStrings = {
16098
+ dropdown: "<div data-kt-select-dropdown class=\"kt-select-dropdown hidden {{class}}\" style=\"z-index: {{zindex}};\">{{content}}</div>",
16099
+ options: "<ul role=\"listbox\" aria-label=\"{{label}}\" class=\"kt-select-options {{class}}\" data-kt-select-options=\"true\">{{content}}</ul>",
16100
+ error: "<li class=\"kt-select-error\" role=\"alert\">{{content}}</li>",
16101
+ highlight: "<span data-kt-select-highlight class=\"kt-select-highlight highlighted {{class}}\">{{text}}</span>",
16102
+ wrapper: "<div data-kt-select-wrapper class=\"kt-select-wrapper {{class}}\"></div>",
16103
+ combobox: "\n\t\t<div data-kt-select-combobox data-kt-select-display class=\"kt-select-combobox {{class}}\">\n\t\t\t<input class=\"kt-input kt-select-combobox-input\" data-kt-select-search=\"true\" data-kt-select-value=\"true\" type=\"text\" placeholder=\"{{placeholder}}\" role=\"searchbox\" aria-label=\"{{label}}\" {{disabled}} />\n\t\t\t<button type=\"button\" data-kt-select-clear-button=\"true\" class=\"kt-select-combobox-clear-btn\" aria-label=\"Clear selection\">\n\t\t\t\t<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t\t\t\t\t<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n\t\t\t\t\t<line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n\t\t\t\t</svg>\n\t\t\t</button>\n\t\t</div>\n\t",
16104
+ display: "\n\t\t<div data-kt-select-display class=\"kt-select-display {{class}}\" tabindex=\"{{tabindex}}\" role=\"button\" data-selected=\"0\" aria-haspopup=\"listbox\" aria-expanded=\"false\" aria-label=\"{{label}}\" {{disabled}}>\n\t\t\t<div data-kt-select-value=\"true\" class=\"kt-select-label\">{{content}}</div>\n\t\t</div>\n\t",
16105
+ placeholder: "<div data-kt-select-placeholder class=\"kt-select-placeholder {{class}}\">{{content}}</div>",
16106
+ option: "<li data-kt-select-option data-value=\"{{value}}\" data-text=\"{{text}}\" class=\"kt-select-option {{class}}\" role=\"option\" {{selected}} {{disabled}}>{{content}}</li>",
16107
+ search: "<div data-kt-select-search class=\"kt-select-search {{class}}\"><input type=\"text\" data-kt-select-search=\"true\" placeholder=\"{{searchPlaceholder}}\" class=\"kt-input kt-select-search-input\" role=\"searchbox\" aria-label=\"{{searchPlaceholder}}\"/></div>",
16108
+ empty: "<li data-kt-select-empty class=\"kt-select-no-result {{class}}\" role=\"status\">{{content}}</li>",
16109
+ loading: "<li class=\"kt-select-loading {{class}}\" role=\"status\" aria-live=\"polite\">{{content}}</li>",
16110
+ tag: "<div data-kt-select-tag=\"true\" class=\"kt-select-tag {{class}}\">\n\t\t\t{{content}}\n\t\t</div>",
16111
+ loadMore: "<li class=\"kt-select-load-more {{class}}\" data-kt-select-load-more=\"true\">{{content}}</li>",
16112
+ tagRemoveButton: "<button type=\"button\" data-kt-select-remove-button class=\"kt-select-tag-remove\" aria-label=\"Remove tag\" tabindex=\"0\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"3\" y1=\"3\" x2=\"9\" y2=\"9\"/><line x1=\"9\" y1=\"3\" x2=\"3\" y2=\"9\"/></svg></button>",
15859
16113
  };
15860
16114
  /**
15861
16115
  * Default templates for KTSelect component
@@ -15885,9 +16139,9 @@ function getTemplateStrings(config) {
15885
16139
  ? config.templates
15886
16140
  : undefined;
15887
16141
  if (templates) {
15888
- return __assign(__assign(__assign({}, defaultTemplateStrings), userTemplateStrings), templates);
16142
+ return __assign(__assign(__assign({}, exports.coreTemplateStrings), userTemplateStrings), templates);
15889
16143
  }
15890
- return __assign(__assign({}, defaultTemplateStrings), userTemplateStrings);
16144
+ return __assign(__assign({}, exports.coreTemplateStrings), userTemplateStrings);
15891
16145
  }
15892
16146
  /**
15893
16147
  * Default templates for KTSelect component
@@ -15898,44 +16152,38 @@ exports.defaultTemplates = {
15898
16152
  */
15899
16153
  highlight: function (config, text) {
15900
16154
  var template = getTemplateStrings(config).highlight;
15901
- var html = template.replace('{{text}}', text);
16155
+ var html = template.replace('{{text}}', text).replace('{{class}}', config.highlightClass || '');
15902
16156
  return stringToElement(html);
15903
16157
  },
15904
16158
  /**
15905
16159
  * Renders the dropdown content
15906
16160
  */
15907
- dropdownContent: function (config) {
15908
- var template = getTemplateStrings(config).dropdownContent;
16161
+ dropdown: function (config) {
16162
+ var template = getTemplateStrings(config).dropdown;
16163
+ var content = config.content || '';
16164
+ if (config.dropdownTemplate) {
16165
+ content = (0, utils_1.renderTemplateString)(config.dropdownTemplate, {
16166
+ zindex: config.zindex ? String(config.zindex) : '',
16167
+ content: config.content || '',
16168
+ class: config.dropdownClass || '',
16169
+ });
16170
+ }
15909
16171
  var html = template
15910
16172
  .replace('{{zindex}}', config.zindex ? String(config.zindex) : '')
15911
- .replace('{{content}}', config.content || '');
16173
+ .replace('{{content}}', content)
16174
+ .replace('{{class}}', config.dropdownClass || '');
15912
16175
  return stringToElement(html);
15913
16176
  },
15914
16177
  /**
15915
16178
  * Renders the options container for the dropdown
15916
16179
  */
15917
- optionsContainer: function (config) {
15918
- var template = getTemplateStrings(config).optionsContainer;
16180
+ options: function (config) {
16181
+ var template = getTemplateStrings(config).options;
15919
16182
  var html = template
15920
16183
  .replace('{{label}}', config.label || 'Options')
15921
16184
  .replace('{{height}}', config.height ? String(config.height) : '250')
15922
- .replace('{{options}}', config.options || '');
15923
- return stringToElement(html);
15924
- },
15925
- /**
15926
- * Renders an empty option in the dropdown
15927
- */
15928
- emptyOption: function (config) {
15929
- var template = getTemplateStrings(config).emptyOption;
15930
- var html = template.replace('{{placeholder}}', config.placeholder || 'Select...');
15931
- return stringToElement(html);
15932
- },
15933
- /**
15934
- * Renders an error option in the dropdown
15935
- */
15936
- errorOption: function (config) {
15937
- var template = getTemplateStrings(config).errorOption;
15938
- var html = template.replace('{{errorMessage}}', config.errorMessage || 'An error occurred');
16185
+ .replace('{{options}}', config.options || '')
16186
+ .replace('{{class}}', config.optionsClass || '');
15939
16187
  return stringToElement(html);
15940
16188
  },
15941
16189
  /**
@@ -15950,51 +16198,41 @@ exports.defaultTemplates = {
15950
16198
  */
15951
16199
  error: function (config) {
15952
16200
  var template = getTemplateStrings(config).error;
15953
- return template.replace('{{errorMessage}}', config.errorMessage || 'An error occurred');
16201
+ return template
16202
+ .replace('{{errorMessage}}', config.errorMessage || 'An error occurred')
16203
+ .replace('{{class}}', config.errorClass || '');
15954
16204
  },
15955
16205
  /**
15956
16206
  * Renders the main container for the select component
15957
16207
  */
15958
- main: function (config) {
15959
- var html = getTemplateStrings(config).main.replace('{{mode}}', config.mode || '');
15960
- return stringToElement(html);
16208
+ wrapper: function (config) {
16209
+ var html = getTemplateStrings(config).wrapper
16210
+ .replace('{{class}}', config.wrapperClass || '');
16211
+ var element = stringToElement(html);
16212
+ element.setAttribute('data-kt-select-combobox', config.combobox ? 'true' : 'false');
16213
+ element.setAttribute('data-kt-select-tags', config.tags ? 'true' : 'false');
16214
+ return element;
15961
16215
  },
15962
16216
  /**
15963
16217
  * Renders the display element (trigger) for the select
15964
16218
  */
15965
16219
  display: function (config) {
15966
- var isCombobox = config.mode === types_1.SelectMode.COMBOBOX;
15967
- if (isCombobox) {
16220
+ if (config.combobox) {
15968
16221
  var html_1 = getTemplateStrings(config)
15969
- .displayCombobox.replace(/{{placeholder}}/g, config.placeholder || 'Select...')
16222
+ .combobox.replace(/{{placeholder}}/g, config.placeholder || 'Select...')
15970
16223
  .replace(/{{label}}/g, config.label || config.placeholder || 'Select...')
15971
- .replace('{{disabled}}', config.disabled ? 'disabled' : '');
16224
+ .replace('{{disabled}}', config.disabled ? 'disabled' : '')
16225
+ .replace('{{class}}', config.displayClass || '');
15972
16226
  return stringToElement(html_1);
15973
16227
  }
15974
- var html = getTemplateStrings(config)
15975
- .display.replace('{{tabindex}}', config.disabled ? '-1' : '0')
16228
+ var content = config.label || config.placeholder || 'Select...';
16229
+ var html = getTemplateStrings(config).display
16230
+ .replace('{{tabindex}}', config.disabled ? '-1' : '0')
15976
16231
  .replace('{{label}}', config.label || config.placeholder || 'Select...')
15977
16232
  .replace('{{disabled}}', config.disabled ? 'aria-disabled="true"' : '')
15978
- .replace('{{placeholder}}', config.placeholder || 'Select...');
15979
- return stringToElement(html);
15980
- },
15981
- /**
15982
- * Renders the dropdown content container
15983
- */
15984
- dropdown: function (config, optionsHtml) {
15985
- var isCombobox = config.mode === types_1.SelectMode.COMBOBOX;
15986
- var hasSearch = config.enableSearch && !isCombobox;
15987
- var template = getTemplateStrings(config).dropdown;
15988
- var searchHtml = '';
15989
- if (hasSearch) {
15990
- var searchElement = exports.defaultTemplates.search(config);
15991
- searchHtml = searchElement.outerHTML;
15992
- }
15993
- var html = template
15994
- .replace('{{search}}', searchHtml)
15995
- .replace('{{options}}', optionsHtml)
15996
- .replace('{{label}}', config.label || 'Options')
15997
- .replace('{{height}}', config.height ? String(config.height) : '250');
16233
+ .replace('{{placeholder}}', config.placeholder || 'Select...')
16234
+ .replace('{{class}}', config.displayClass || '')
16235
+ .replace('{{content}}', content);
15998
16236
  return stringToElement(html);
15999
16237
  },
16000
16238
  /**
@@ -16010,141 +16248,102 @@ exports.defaultTemplates = {
16010
16248
  var selected = isHtmlOption
16011
16249
  ? option.selected
16012
16250
  : !!option.selected;
16013
- // Prefer data-kt-select-option (JSON) if present
16014
- var description;
16015
- var icon;
16016
- if (isHtmlOption) {
16017
- var json = option.getAttribute('data-kt-select-option');
16018
- if (json) {
16019
- try {
16020
- var optionData = JSON.parse(json);
16021
- description = optionData === null || optionData === void 0 ? void 0 : optionData.description;
16022
- icon = optionData === null || optionData === void 0 ? void 0 : optionData.icon;
16023
- }
16024
- catch (e) {
16025
- // fallback to legacy attributes if JSON is invalid
16026
- description =
16027
- option.getAttribute('data-kt-select-option-description') ||
16028
- undefined;
16029
- icon = option.getAttribute('data-kt-select-option-icon') || undefined;
16030
- }
16031
- }
16032
- else {
16033
- description =
16034
- option.getAttribute('data-kt-select-option-description') || undefined;
16035
- icon = option.getAttribute('data-kt-select-option-icon') || undefined;
16036
- }
16037
- }
16038
- else {
16039
- description = option.description;
16040
- icon = option.icon;
16251
+ var content = text;
16252
+ if (config.optionTemplate) {
16253
+ // Use the user template to render the content, but only for {{content}}
16254
+ content = (0, utils_1.renderTemplateString)(config.optionTemplate, {
16255
+ value: value,
16256
+ text: text,
16257
+ class: config.optionClass || '',
16258
+ selected: selected ? 'aria-selected="true"' : 'aria-selected="false"',
16259
+ disabled: disabled ? 'aria-disabled="true"' : '',
16260
+ content: text,
16261
+ });
16041
16262
  }
16042
- // Build option element with proper accessibility attributes
16043
- var selectedClass = selected ? ' selected' : '';
16044
- var disabledClass = disabled ? ' disabled' : '';
16045
- var html = getTemplateStrings(config)
16046
- .option.replace('{{value}}', value)
16047
- .replace('{{selectedClass}}', selectedClass)
16048
- .replace('{{disabledClass}}', disabledClass)
16263
+ var html = getTemplateStrings(config).option
16264
+ .replace('{{value}}', value)
16265
+ .replace('{{text}}', text)
16049
16266
  .replace('{{selected}}', selected ? 'aria-selected="true"' : 'aria-selected="false"')
16050
16267
  .replace('{{disabled}}', disabled ? 'aria-disabled="true"' : '')
16051
- .replace(/{{icon}}/g, icon ? exports.defaultTemplates.icon(icon, config).outerHTML : '')
16052
- .replace('{{text}}', text)
16053
- .replace(/{{description}}/g, description
16054
- ? exports.defaultTemplates.description(description, config).outerHTML
16055
- : '');
16056
- return stringToElement(html);
16057
- },
16058
- /**
16059
- * Renders an icon
16060
- */
16061
- icon: function (icon, config) {
16062
- var html = getTemplateStrings(config).icon.replace('{{icon}}', icon);
16063
- return stringToElement(html);
16064
- },
16065
- /**
16066
- * Renders a description
16067
- */
16068
- description: function (description, config) {
16069
- var html = getTemplateStrings(config).description.replace('{{description}}', description);
16070
- return stringToElement(html);
16071
- },
16072
- /**
16073
- * Renders an option group with header
16074
- */
16075
- optionGroup: function (label, optionsHtml, config) {
16076
- var html = getTemplateStrings(config)
16077
- .optionGroup.replace(/{{label}}/g, label)
16078
- .replace('{{optionsHtml}}', optionsHtml);
16268
+ .replace('{{content}}', content)
16269
+ .replace('{{class}}', config.optionClass || '');
16079
16270
  return stringToElement(html);
16080
16271
  },
16081
16272
  /**
16082
16273
  * Renders the search input
16083
16274
  */
16084
16275
  search: function (config) {
16085
- var html = getTemplateStrings(config).search.replace('{{searchPlaceholder}}', config.searchPlaceholder || 'Search...');
16276
+ var html = getTemplateStrings(config)
16277
+ .search.replace('{{searchPlaceholder}}', config.searchPlaceholder || 'Search...')
16278
+ .replace('{{class}}', config.searchClass || '');
16086
16279
  return stringToElement(html);
16087
16280
  },
16088
16281
  /**
16089
16282
  * Renders the no results message
16090
16283
  */
16091
- noResults: function (config) {
16092
- var html = getTemplateStrings(config).noResults.replace('{{searchNotFoundText}}', config.searchNotFoundText || 'No results found');
16284
+ empty: function (config) {
16285
+ var html = getTemplateStrings(config)
16286
+ .empty.replace('{{searchNotFoundText}}', config.searchNotFoundText || 'No results found')
16287
+ .replace('{{class}}', config.emptyClass || '');
16093
16288
  return stringToElement(html);
16094
16289
  },
16095
16290
  /**
16096
16291
  * Renders the loading state
16097
16292
  */
16098
16293
  loading: function (config, loadingMessage) {
16099
- var html = getTemplateStrings(config).loading.replace('{{loadingMessage}}', loadingMessage || 'Loading options...');
16294
+ var html = getTemplateStrings(config)
16295
+ .loading.replace('{{loadingMessage}}', loadingMessage || 'Loading options...')
16296
+ .replace('{{class}}', config.loadingClass || '');
16100
16297
  return stringToElement(html);
16101
16298
  },
16102
16299
  /**
16103
16300
  * Renders a tag for multi-select
16104
16301
  */
16105
16302
  tag: function (option, config) {
16106
- // Escape HTML characters for aria-label to prevent HTML injection
16107
- var escapeHTML = function (str) {
16108
- return str.replace(/[&<>"']/g, function (match) {
16109
- var escapeMap = {
16110
- '&': '&amp;',
16111
- '<': '&lt;',
16112
- '>': '&gt;',
16113
- '"': '&quot;',
16114
- "'": '&#39;',
16115
- };
16116
- return escapeMap[match];
16303
+ var template = getTemplateStrings(config).tag;
16304
+ var content = option.title;
16305
+ if (config.tagTemplate) {
16306
+ var tagTemplate_1 = config.tagTemplate;
16307
+ var text = option.getAttribute('data-text');
16308
+ var value = option.getAttribute('data-value');
16309
+ // Replace all {{varname}} in option.innerHTML with values from _config
16310
+ Object.entries(config.optionsConfig[value] || {}).forEach(function (_a) {
16311
+ var key = _a[0], value = _a[1];
16312
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
16313
+ tagTemplate_1 = tagTemplate_1.replace(new RegExp("{{".concat(key, "}}"), 'g'), String(value));
16314
+ }
16117
16315
  });
16118
- };
16119
- // Ensure we have plain text for the aria-label
16120
- var safeTitle = escapeHTML(option.title);
16121
- var html = getTemplateStrings(config)
16122
- .tag.replace('{{title}}', option.title)
16316
+ content = (0, utils_1.renderTemplateString)(tagTemplate_1, {
16317
+ title: option.title,
16318
+ id: option.id,
16319
+ class: config.tagClass || '',
16320
+ content: option.innerHTML,
16321
+ text: option.innerText,
16322
+ });
16323
+ }
16324
+ content += getTemplateStrings(config).tagRemoveButton;
16325
+ var html = template
16326
+ .replace('{{title}}', option.title)
16123
16327
  .replace('{{id}}', option.id)
16124
- .replace('{{safeTitle}}', safeTitle);
16328
+ .replace('{{content}}', content)
16329
+ .replace('{{class}}', config.tagClass || '');
16125
16330
  return stringToElement(html);
16126
16331
  },
16127
16332
  /**
16128
- * Formats the display of selected values
16333
+ * Renders the placeholder for the select
16129
16334
  */
16130
- selectedDisplay: function (selectedOptions, config) {
16131
- if (!selectedOptions || selectedOptions.length === 0) {
16132
- return config.placeholder || 'Select...';
16133
- }
16134
- if (config.multiple) {
16135
- if (config.renderSelected &&
16136
- typeof config.renderSelected === 'function') {
16137
- return config.renderSelected(selectedOptions);
16138
- }
16139
- if (config.showSelectedCount) {
16140
- var count = selectedOptions.length;
16141
- return "".concat(count, " ").concat(count === 1 ? 'item' : 'items', " selected");
16142
- }
16143
- return selectedOptions.map(function (option) { return option.title; }).join(', ');
16144
- }
16145
- else {
16146
- return selectedOptions[0].title;
16335
+ placeholder: function (config) {
16336
+ var html = getTemplateStrings(config)
16337
+ .placeholder.replace('{{class}}', config.placeholderClass || '');
16338
+ var content = config.placeholder || 'Select...';
16339
+ if (config.placeholderTemplate) {
16340
+ content = (0, utils_1.renderTemplateString)(config.placeholderTemplate, {
16341
+ placeholder: config.placeholder || 'Select...',
16342
+ class: config.placeholderClass || '',
16343
+ });
16147
16344
  }
16345
+ html = html.replace('{{content}}', content);
16346
+ return stringToElement(html);
16148
16347
  },
16149
16348
  };
16150
16349
 
@@ -17263,7 +17462,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
17263
17462
  return to.concat(ar || Array.prototype.slice.call(from));
17264
17463
  };
17265
17464
  Object.defineProperty(exports, "__esModule", ({ value: true }));
17266
- exports.SelectOptionDefaultConfig = exports.KTSelectState = exports.DefaultConfig = void 0;
17465
+ exports.KTSelectState = exports.DefaultConfig = void 0;
17267
17466
  exports.DefaultConfig = {
17268
17467
  // ...other config options
17269
17468
  loadMoreText: 'Load more...',
@@ -17283,10 +17482,6 @@ exports.DefaultConfig = {
17283
17482
  // Field Mapping
17284
17483
  dataValueField: null, // Property in the option object that contains the value (default: 'id')
17285
17484
  dataFieldText: null, // Property in the option object that contains the text (default: 'title')
17286
- dataFieldDescription: null, // Property in the option object that contains the description
17287
- dataFieldIcon: null, // Property in the option object that contains the icon
17288
- dataFieldIconWidth: null, // Property in the option object that contains the icon width
17289
- dataFieldIconHeight: null, // Property in the option object that contains the icon height
17290
17485
  // Search Configuration
17291
17486
  searchParam: '', // Query parameter for API search requests
17292
17487
  searchDebounce: 300, // Debounce delay for search (in ms)
@@ -17299,10 +17494,9 @@ exports.DefaultConfig = {
17299
17494
  // Selection Behavior
17300
17495
  multiple: false, // Enable/disable multi-select
17301
17496
  maxSelections: null, // Maximum number of selections allowed in multi-select mode (null for unlimited)
17302
- closeOnSelect: true, // Close the dropdown after selecting an option (single-select only)
17497
+ closeOnSelect: false, // Close the dropdown after selecting an option (single-select only)
17303
17498
  disabled: false, // Disable the select component
17304
17499
  isRequired: false, // Make selection required
17305
- mode: null, // Select mode: tags or combobox
17306
17500
  // Search Functionality
17307
17501
  enableSearch: false, // Enable/disable search functionality within the dropdown
17308
17502
  searchPlaceholder: 'Search...', // Placeholder text for the search input
@@ -17326,11 +17520,8 @@ exports.DefaultConfig = {
17326
17520
  dropdownPreventOverflow: false,
17327
17521
  dropdownStrategy: null,
17328
17522
  dropdownWidth: null, // Custom width for dropdown (e.g., '300px'), null to match toggle element width
17329
- // Styling
17330
- focusClass: 'option-focused',
17331
- hoverClass: 'hovered',
17332
- bgClass: 'bg-blue-50',
17333
- fontClass: 'font-medium',
17523
+ // New Config
17524
+ dropdownTemplate: '',
17334
17525
  };
17335
17526
  var KTSelectState = /** @class */ (function () {
17336
17527
  function KTSelectState(config) {
@@ -17458,10 +17649,6 @@ var KTSelectState = /** @class */ (function () {
17458
17649
  return KTSelectState;
17459
17650
  }());
17460
17651
  exports.KTSelectState = KTSelectState;
17461
- exports.SelectOptionDefaultConfig = {
17462
- description: '',
17463
- icon: null,
17464
- };
17465
17652
 
17466
17653
 
17467
17654
  /***/ }),