@keenthemes/ktui 1.0.12 → 1.0.13

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 (92) hide show
  1. package/dist/ktui.js +668 -685
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +5822 -0
  5. package/examples/select/avatar.html +47 -0
  6. package/examples/select/basic-usage.html +10 -14
  7. package/examples/select/{test.html → combobox-icons_.html} +13 -48
  8. package/examples/select/country.html +43 -0
  9. package/examples/select/description.html +25 -41
  10. package/examples/select/disable-option.html +10 -16
  11. package/examples/select/disable-select.html +7 -6
  12. package/examples/select/icon-multiple.html +23 -31
  13. package/examples/select/icon.html +20 -30
  14. package/examples/select/max-selection.html +8 -9
  15. package/examples/select/modal.html +19 -17
  16. package/examples/select/multiple.html +11 -13
  17. package/examples/select/placeholder.html +9 -12
  18. package/examples/select/search.html +30 -22
  19. package/examples/select/sizes.html +94 -0
  20. package/examples/select/template-customization.html +0 -3
  21. package/lib/cjs/components/component.js +1 -1
  22. package/lib/cjs/components/component.js.map +1 -1
  23. package/lib/cjs/components/datatable/datatable.js +1 -1
  24. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  25. package/lib/cjs/components/select/combobox.js +96 -61
  26. package/lib/cjs/components/select/combobox.js.map +1 -1
  27. package/lib/cjs/components/select/config.js +1 -3
  28. package/lib/cjs/components/select/config.js.map +1 -1
  29. package/lib/cjs/components/select/dropdown.js +32 -96
  30. package/lib/cjs/components/select/dropdown.js.map +1 -1
  31. package/lib/cjs/components/select/option.js +53 -20
  32. package/lib/cjs/components/select/option.js.map +1 -1
  33. package/lib/cjs/components/select/search.js +146 -97
  34. package/lib/cjs/components/select/search.js.map +1 -1
  35. package/lib/cjs/components/select/select.js +174 -120
  36. package/lib/cjs/components/select/select.js.map +1 -1
  37. package/lib/cjs/components/select/tags.js +0 -26
  38. package/lib/cjs/components/select/tags.js.map +1 -1
  39. package/lib/cjs/components/select/templates.js +130 -103
  40. package/lib/cjs/components/select/templates.js.map +1 -1
  41. package/lib/cjs/components/select/utils.js +33 -132
  42. package/lib/cjs/components/select/utils.js.map +1 -1
  43. package/lib/cjs/helpers/dom.js +0 -24
  44. package/lib/cjs/helpers/dom.js.map +1 -1
  45. package/lib/esm/components/component.js +1 -1
  46. package/lib/esm/components/component.js.map +1 -1
  47. package/lib/esm/components/datatable/datatable.js +1 -1
  48. package/lib/esm/components/datatable/datatable.js.map +1 -1
  49. package/lib/esm/components/select/combobox.js +96 -61
  50. package/lib/esm/components/select/combobox.js.map +1 -1
  51. package/lib/esm/components/select/config.js +1 -3
  52. package/lib/esm/components/select/config.js.map +1 -1
  53. package/lib/esm/components/select/dropdown.js +32 -96
  54. package/lib/esm/components/select/dropdown.js.map +1 -1
  55. package/lib/esm/components/select/option.js +53 -20
  56. package/lib/esm/components/select/option.js.map +1 -1
  57. package/lib/esm/components/select/search.js +146 -97
  58. package/lib/esm/components/select/search.js.map +1 -1
  59. package/lib/esm/components/select/select.js +174 -120
  60. package/lib/esm/components/select/select.js.map +1 -1
  61. package/lib/esm/components/select/tags.js +0 -26
  62. package/lib/esm/components/select/tags.js.map +1 -1
  63. package/lib/esm/components/select/templates.js +130 -103
  64. package/lib/esm/components/select/templates.js.map +1 -1
  65. package/lib/esm/components/select/utils.js +32 -130
  66. package/lib/esm/components/select/utils.js.map +1 -1
  67. package/lib/esm/helpers/dom.js +0 -24
  68. package/lib/esm/helpers/dom.js.map +1 -1
  69. package/package.json +9 -6
  70. package/src/components/component.ts +0 -4
  71. package/src/components/datatable/datatable.ts +1 -1
  72. package/src/components/input/input.css +1 -1
  73. package/src/components/scrollable/scrollable.css +9 -5
  74. package/src/components/select/combobox.ts +99 -88
  75. package/src/components/select/config.ts +2 -8
  76. package/src/components/select/dropdown.ts +43 -108
  77. package/src/components/select/option.ts +44 -25
  78. package/src/components/select/search.ts +158 -117
  79. package/src/components/select/select.css +97 -27
  80. package/src/components/select/select.ts +181 -127
  81. package/src/components/select/tags.ts +1 -27
  82. package/src/components/select/templates.ts +194 -131
  83. package/src/components/select/utils.ts +30 -166
  84. package/src/helpers/dom.ts +0 -30
  85. package/webpack.config.js +6 -1
  86. package/examples/select/combobox-icons.html +0 -58
  87. package/examples/select/icon-description.html +0 -56
  88. /package/examples/select/{combobox.html → combobox_.html} +0 -0
  89. /package/examples/select/{remote-data.html → remote-data_.html} +0 -0
  90. /package/examples/select/{tags-icons.html → tags-icons_.html} +0 -0
  91. /package/examples/select/{tags-selected.html → tags-selected_.html} +0 -0
  92. /package/examples/select/{tags.html → tags_.html} +0 -0
@@ -163,15 +163,16 @@ var KTSelect = /** @class */ (function (_super) {
163
163
  var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
164
164
  if (!optionsContainer)
165
165
  return;
166
+ // Clear previous messages
167
+ optionsContainer.innerHTML = '';
166
168
  switch (type) {
167
169
  case 'error':
168
- optionsContainer.innerHTML = templates_1.defaultTemplates.error(__assign(__assign({}, this._config), { errorMessage: message }));
170
+ optionsContainer.appendChild(templates_1.defaultTemplates.error(__assign(__assign({}, this._config), { errorMessage: message })));
169
171
  break;
170
172
  case 'loading':
171
- optionsContainer.innerHTML = templates_1.defaultTemplates.loading(this._config, message || 'Loading...').outerHTML;
173
+ optionsContainer.appendChild(templates_1.defaultTemplates.loading(this._config, message || 'Loading...'));
172
174
  break;
173
175
  case 'empty':
174
- optionsContainer.innerHTML = '';
175
176
  optionsContainer.appendChild(templates_1.defaultTemplates.empty(this._config));
176
177
  break;
177
178
  }
@@ -343,7 +344,7 @@ var KTSelect = /** @class */ (function (_super) {
343
344
  // Initialize focus manager after dropdown element is created
344
345
  this._focusManager = new utils_1.FocusManager(this._dropdownContentElement, '[data-kt-select-option]', this._config);
345
346
  // Initialize dropdown module after all elements are created
346
- this._dropdownModule = new dropdown_1.KTSelectDropdown(this._wrapperElement, this._displayElement, this._dropdownContentElement, this._config);
347
+ this._dropdownModule = new dropdown_1.KTSelectDropdown(this._wrapperElement, this._displayElement, this._dropdownContentElement, this._config, this);
347
348
  // Update display and set ARIA attributes
348
349
  this._updateDisplayAndAriaAttributes();
349
350
  this.updateSelectedOptionDisplay();
@@ -351,12 +352,6 @@ var KTSelect = /** @class */ (function (_super) {
351
352
  // Attach event listeners after all modules are initialized
352
353
  this._attachEventListeners();
353
354
  };
354
- /**
355
- * Initialize options HTML from data
356
- */
357
- // private _initializeOptionsHtml() {
358
- // this._generateOptionsHtml(this._element);
359
- // }
360
355
  /**
361
356
  * Creates the HTML structure for the select component
362
357
  */
@@ -426,7 +421,6 @@ var KTSelect = /** @class */ (function (_super) {
426
421
  if (!this._searchInputElement) {
427
422
  this._searchInputElement = this._displayElement;
428
423
  }
429
- this._valueDisplayElement = this._wrapperElement.querySelector("[data-kt-select-value]");
430
424
  this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
431
425
  };
432
426
  /**
@@ -437,16 +431,10 @@ var KTSelect = /** @class */ (function (_super) {
437
431
  document.addEventListener('click', this._handleDocumentClick.bind(this));
438
432
  // Dropdown option click events
439
433
  this._eventManager.addListener(this._dropdownContentElement, 'click', this._handleDropdownOptionClick.bind(this));
440
- // Only attach click handler to display element
441
- // this._eventManager.addListener(
442
- // this._wrapperElement,
443
- // 'click',
444
- // this._handleDropdownClick.bind(this),
445
- // );
446
- // Attach centralized keyboard handler
447
- var keyboardTarget = this._searchInputElement || this._wrapperElement;
448
- if (keyboardTarget) {
449
- keyboardTarget.addEventListener('keydown', this._handleKeyboardEvent.bind(this));
434
+ // Attach centralized keyboard handler to the wrapper element.
435
+ // Events from focusable children like _displayElement or _searchInputElement (if present) will bubble up.
436
+ if (this._wrapperElement) {
437
+ this._wrapperElement.addEventListener('keydown', this._handleKeyboardEvent.bind(this));
450
438
  }
451
439
  };
452
440
  /**
@@ -589,37 +577,10 @@ var KTSelect = /** @class */ (function (_super) {
589
577
  * DROPDOWN MANAGEMENT
590
578
  * ========================================================================
591
579
  */
592
- /**
593
- * Toggle dropdown visibility
594
- * @deprecated
595
- */
596
- KTSelect.prototype.toggleDropdown = function () {
597
- if (this._config.disabled) {
598
- if (this._config.debug)
599
- console.log('toggleDropdown: select is disabled, not opening');
600
- return;
601
- }
602
- if (this._config.debug)
603
- console.log('toggleDropdown called');
604
- if (this._dropdownModule) {
605
- // Always use the dropdown module's state to determine whether to open or close
606
- if (this._dropdownModule.isOpen()) {
607
- if (this._config.debug)
608
- console.log('Dropdown is open, closing...');
609
- this.closeDropdown();
610
- }
611
- else {
612
- if (this._config.debug)
613
- console.log('Dropdown is closed, opening...');
614
- this.openDropdown();
615
- }
616
- }
617
- };
618
580
  /**
619
581
  * Open the dropdown
620
582
  */
621
583
  KTSelect.prototype.openDropdown = function () {
622
- var _this = this;
623
584
  if (this._config.disabled) {
624
585
  if (this._config.debug)
625
586
  console.log('openDropdown: select is disabled, not opening');
@@ -647,14 +608,6 @@ var KTSelect = /** @class */ (function (_super) {
647
608
  // Dispatch custom event
648
609
  this._dispatchEvent('show');
649
610
  this._fireEvent('show');
650
- // Focus search input if configured and exists
651
- if (this._config.enableSearch &&
652
- this._config.searchAutofocus &&
653
- this._searchInputElement) {
654
- setTimeout(function () {
655
- _this._searchInputElement.focus();
656
- }, 50);
657
- }
658
611
  // Update ARIA states
659
612
  this._setAriaAttributes();
660
613
  // Focus the first selected option or first option if nothing selected
@@ -675,14 +628,14 @@ var KTSelect = /** @class */ (function (_super) {
675
628
  // Always close by delegating to the dropdown module, which is the source of truth
676
629
  if (this._config.debug)
677
630
  console.log('Closing dropdown via dropdownModule...');
678
- // Clear search input and highlights if the dropdown is closing
631
+ // Clear search input if the dropdown is closing
679
632
  if (this._searchModule && this._searchInputElement) {
680
633
  // Clear search input if configured to do so
681
634
  if (this._config.clearSearchOnClose) {
682
635
  this._searchInputElement.value = '';
683
636
  }
684
- // Always clear the highlights when dropdown closes
685
- this._searchModule.clearSearchHighlights();
637
+ // Clear search input when dropdown closes
638
+ this._searchModule.clearSearch();
686
639
  }
687
640
  // Set our internal flag to match what we're doing
688
641
  this._dropdownIsOpen = false;
@@ -716,10 +669,13 @@ var KTSelect = /** @class */ (function (_super) {
716
669
  var selectedOptions = this.getSelectedOptions();
717
670
  if (selectedOptions.length === 0)
718
671
  return;
719
- // Get the first selected option element
720
- var firstSelectedValue = selectedOptions[0];
721
- // Use the FocusManager to focus on the option
722
- this._focusManager.focusOptionByValue(firstSelectedValue);
672
+ // Iterate through selected options and focus the first one that is visible
673
+ for (var _i = 0, selectedOptions_1 = selectedOptions; _i < selectedOptions_1.length; _i++) {
674
+ var value = selectedOptions_1[_i];
675
+ if (this._focusManager && this._focusManager.focusOptionByValue(value)) {
676
+ break; // Stop after focusing the first found selected and visible option
677
+ }
678
+ }
723
679
  };
724
680
  /**
725
681
  * ========================================================================
@@ -782,38 +738,90 @@ var KTSelect = /** @class */ (function (_super) {
782
738
  */
783
739
  KTSelect.prototype.updateSelectedOptionDisplay = function () {
784
740
  var selectedOptions = this.getSelectedOptions();
785
- // Tag mode: render tags if enabled
786
- if (this._config.tags && this._tagsModule) {
741
+ var tagsEnabled = this._config.tags && this._tagsModule;
742
+ var valueDisplayEl = this.getValueDisplayElement();
743
+ if (tagsEnabled) {
744
+ // Tags module will render tags if selectedOptions > 0, or clear them if selectedOptions === 0.
787
745
  this._tagsModule.updateTagsDisplay(selectedOptions);
788
- return;
789
746
  }
747
+ // Guard against valueDisplayEl being null due to template modifications
748
+ if (!valueDisplayEl) {
749
+ if (this._config.debug) {
750
+ console.warn('KTSelect: Value display element is null. Cannot update display or placeholder. Check template for [data-kt-select-value].');
751
+ }
752
+ return; // Nothing to display on if the element is missing
753
+ }
754
+ // 1. Custom render function takes highest precedence
790
755
  if (typeof this._config.renderSelected === 'function') {
791
- // Use the custom renderSelected function if provided
792
- this._valueDisplayElement.innerHTML = this._config.renderSelected(selectedOptions);
756
+ valueDisplayEl.innerHTML = this._config.renderSelected(selectedOptions);
757
+ return;
758
+ }
759
+ // 2. Custom displayTemplate string
760
+ // Check if a custom display template string is provided directly in config or via config.templates
761
+ var customDisplayTemplateString = this._config.displayTemplate || (this._config.templates && this._config.templates.display);
762
+ if (customDisplayTemplateString) {
763
+ // If tags are enabled and items are selected, the tags module handles display, so clear the main display area.
764
+ if (tagsEnabled && selectedOptions.length > 0) {
765
+ valueDisplayEl.innerHTML = '';
766
+ }
767
+ else {
768
+ // Otherwise, render the custom display template.
769
+ // If no options are selected, renderDisplayTemplateForSelected should handle showing a placeholder if the template supports it,
770
+ // or we might need a separate placeholder rendering for custom templates if they don't handle empty selection.
771
+ // For now, assume renderDisplayTemplateForSelected handles it or shows selected text.
772
+ valueDisplayEl.innerHTML = this.renderDisplayTemplateForSelected(selectedOptions);
773
+ }
774
+ return;
775
+ }
776
+ // 3. Default template behavior (no custom function or string template)
777
+ var textContainer = valueDisplayEl.querySelector('[data-kt-text-container="true"]');
778
+ if (tagsEnabled && selectedOptions.length > 0) {
779
+ // Tags are active and have content, clear the text container if it exists,
780
+ // or the whole display if it doesn't (though it should with default template).
781
+ if (textContainer) {
782
+ textContainer.innerHTML = '';
783
+ }
784
+ else {
785
+ valueDisplayEl.innerHTML = ''; // Fallback: clear entire display area
786
+ }
787
+ }
788
+ else if (selectedOptions.length === 0) {
789
+ // No options selected: display placeholder text in the text container.
790
+ var placeholderTemplate = templates_1.defaultTemplates.placeholder(this._config);
791
+ var placeholderText = placeholderTemplate.textContent || ''; // Get text from placeholder element
792
+ if (textContainer) {
793
+ textContainer.innerHTML = placeholderText;
794
+ }
795
+ else {
796
+ // Fallback: If no text container, replace children of valueDisplayEl with the placeholder element itself.
797
+ // This ensures the placeholder (which might have its own structure/classes) is displayed.
798
+ valueDisplayEl.replaceChildren(placeholderTemplate);
799
+ }
793
800
  }
794
801
  else {
795
- if (selectedOptions.length === 0) {
796
- var placeholder = templates_1.defaultTemplates.placeholder(this._config);
797
- this._valueDisplayElement.replaceChildren(placeholder);
802
+ // Options are selected, and tags are not enabled (or no selected options for tags):
803
+ // Render normal selected text in the text container.
804
+ var content = this.getSelectedOptionsText();
805
+ if (textContainer) {
806
+ textContainer.innerHTML = content;
798
807
  }
799
808
  else {
800
- var content = '';
801
- if (this._config.displayTemplate) {
802
- var selectedValues = this.getSelectedOptions();
803
- content = this.renderDisplayTemplateForSelected(selectedValues);
804
- }
805
- else {
806
- // If no displayTemplate is provided, use the default comma-separated list of selected options
807
- content = this.getSelectedOptionsText();
808
- }
809
- this._valueDisplayElement.innerHTML = content;
809
+ valueDisplayEl.innerHTML = content; // Fallback: set content on whole display area
810
810
  }
811
811
  }
812
812
  };
813
+ /**
814
+ * Check if an option was originally disabled in the HTML
815
+ */
816
+ KTSelect.prototype._isOptionOriginallyDisabled = function (value) {
817
+ var originalOption = Array.from(this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
818
+ return originalOption ? originalOption.disabled : false;
819
+ };
813
820
  /**
814
821
  * Update CSS classes for selected options
815
822
  */
816
823
  KTSelect.prototype._updateSelectedOptionClass = function () {
824
+ var _this = this;
817
825
  var allOptions = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
818
826
  var selectedValues = this._state.getSelectedOptions();
819
827
  var maxReached = typeof this._config.maxSelections === 'number' &&
@@ -825,9 +833,11 @@ var KTSelect = /** @class */ (function (_super) {
825
833
  if (!optionValue)
826
834
  return;
827
835
  var isSelected = selectedValues.includes(optionValue);
836
+ var isOriginallyDisabled = _this._isOptionOriginallyDisabled(optionValue);
828
837
  if (isSelected) {
829
838
  option.classList.add('selected');
830
839
  option.setAttribute('aria-selected', 'true');
840
+ // Selected options should not be visually hidden or disabled by maxSelections logic
831
841
  option.classList.remove('hidden');
832
842
  option.classList.remove('disabled');
833
843
  option.removeAttribute('aria-disabled');
@@ -835,7 +845,8 @@ var KTSelect = /** @class */ (function (_super) {
835
845
  else {
836
846
  option.classList.remove('selected');
837
847
  option.setAttribute('aria-selected', 'false');
838
- if (maxReached) {
848
+ // An option should be disabled if it was originally disabled OR if maxSelections is reached
849
+ if (isOriginallyDisabled || maxReached) {
839
850
  option.classList.add('disabled');
840
851
  option.setAttribute('aria-disabled', 'true');
841
852
  }
@@ -895,17 +906,6 @@ var KTSelect = /** @class */ (function (_super) {
895
906
  * EVENT HANDLERS
896
907
  * ========================================================================
897
908
  */
898
- /**
899
- * Handle display element click
900
- * @deprecated
901
- */
902
- KTSelect.prototype._handleDropdownClick = function (event) {
903
- if (this._config.debug)
904
- console.log('Display element clicked', event.target);
905
- event.preventDefault();
906
- event.stopPropagation(); // Prevent event bubbling
907
- this.toggleDropdown();
908
- };
909
909
  /**
910
910
  * Handle click within the dropdown
911
911
  */
@@ -946,6 +946,13 @@ var KTSelect = /** @class */ (function (_super) {
946
946
  }
947
947
  if (this._config.debug)
948
948
  console.log('Option clicked:', optionValue);
949
+ // If in single-select mode and the clicked option is already selected, just close the dropdown.
950
+ if (!this._config.multiple && this._state.isSelected(optionValue)) {
951
+ if (this._config.debug)
952
+ console.log('Single select mode: clicked already selected option. Closing dropdown.');
953
+ this.closeDropdown();
954
+ return;
955
+ }
949
956
  // Use toggleSelection instead of _selectOption to prevent re-rendering
950
957
  this.toggleSelection(optionValue);
951
958
  };
@@ -1009,7 +1016,13 @@ var KTSelect = /** @class */ (function (_super) {
1009
1016
  * Get value display element
1010
1017
  */
1011
1018
  KTSelect.prototype.getValueDisplayElement = function () {
1012
- return this._valueDisplayElement;
1019
+ return this._displayElement;
1020
+ };
1021
+ /**
1022
+ * Get wrapper element
1023
+ */
1024
+ KTSelect.prototype.getWrapperElement = function () {
1025
+ return this._wrapperElement;
1013
1026
  };
1014
1027
  /**
1015
1028
  * Show all options in the dropdown
@@ -1019,6 +1032,7 @@ var KTSelect = /** @class */ (function (_super) {
1019
1032
  var options = Array.from(this._wrapperElement.querySelectorAll("[data-kt-select-option]"));
1020
1033
  // Show all options by removing the hidden class and any inline styles
1021
1034
  options.forEach(function (option) {
1035
+ var _a;
1022
1036
  // Remove hidden class
1023
1037
  option.classList.remove('hidden');
1024
1038
  // Clean up any existing inline styles for backward compatibility
@@ -1032,7 +1046,7 @@ var KTSelect = /** @class */ (function (_super) {
1032
1046
  }
1033
1047
  else {
1034
1048
  // Otherwise, remove just the display property
1035
- option.setAttribute('style', styleAttr.replace(/display:\s*[^;]+;?/gi, '').trim());
1049
+ option.setAttribute('style', (_a = styleAttr === null || styleAttr === void 0 ? void 0 : styleAttr.replace(/display:\s*[^;]+;?/gi, '')) === null || _a === void 0 ? void 0 : _a.trim());
1036
1050
  }
1037
1051
  }
1038
1052
  }
@@ -1042,7 +1056,7 @@ var KTSelect = /** @class */ (function (_super) {
1042
1056
  this._searchInputElement.value = '';
1043
1057
  // If we have a search module, clear any search filtering
1044
1058
  if (this._searchModule) {
1045
- this._searchModule.clearSearchHighlights();
1059
+ this._searchModule.clearSearch();
1046
1060
  }
1047
1061
  }
1048
1062
  };
@@ -1071,7 +1085,7 @@ var KTSelect = /** @class */ (function (_super) {
1071
1085
  // Get current selection state
1072
1086
  var isSelected = this._state.isSelected(value);
1073
1087
  if (this._config.debug)
1074
- console.log("toggleSelection called for value: ".concat(value, ", isSelected: ").concat(isSelected, ", multiple: ").concat(this._config.multiple, ", closeOnSelect: ").concat(this._config.closeOnSelect));
1088
+ console.log("toggleSelection called for value: ".concat(value, ", isSelected: ").concat(isSelected, ", multiple: ").concat(this._config.multiple));
1075
1089
  // If already selected in single select mode, do nothing (can't deselect in single select)
1076
1090
  if (isSelected && !this._config.multiple) {
1077
1091
  if (this._config.debug)
@@ -1080,9 +1094,9 @@ var KTSelect = /** @class */ (function (_super) {
1080
1094
  }
1081
1095
  if (this._config.debug)
1082
1096
  console.log("Toggling selection for option: ".concat(value, ", currently selected: ").concat(isSelected));
1083
- // Ensure any search highlights are cleared when selection changes
1097
+ // Ensure any search input is cleared when selection changes
1084
1098
  if (this._searchModule) {
1085
- this._searchModule.clearSearchHighlights();
1099
+ this._searchModule.clearSearch();
1086
1100
  }
1087
1101
  // Toggle the selection in the state
1088
1102
  this._state.toggleSelectedOptions(value);
@@ -1105,15 +1119,14 @@ var KTSelect = /** @class */ (function (_super) {
1105
1119
  // Update option classes without re-rendering the dropdown content
1106
1120
  this._updateSelectedOptionClass();
1107
1121
  // For single select mode, always close the dropdown after selection
1108
- // For multiple select mode, only close if closeOnSelect is true
1109
1122
  if (!this._config.multiple) {
1110
1123
  if (this._config.debug)
1111
1124
  console.log('About to call closeDropdown() for single select mode - always close after selection');
1112
1125
  this.closeDropdown();
1113
1126
  }
1114
- else if (this._config.closeOnSelect) {
1127
+ else {
1115
1128
  if (this._config.debug)
1116
- console.log('About to call closeDropdown() for multiple select with closeOnSelect:true');
1129
+ console.log('About to call closeDropdown() for multiple select');
1117
1130
  this.closeDropdown();
1118
1131
  }
1119
1132
  // Dispatch custom change event with additional data
@@ -1213,9 +1226,9 @@ var KTSelect = /** @class */ (function (_super) {
1213
1226
  .then(function () {
1214
1227
  // Update options in the dropdown
1215
1228
  _this._updateSearchResults(items);
1216
- // Refresh the search module's option cache if search is enabled
1217
- if (_this._searchModule && _this._config.enableSearch) {
1218
- _this._searchModule.refreshOptionCache();
1229
+ // Refresh the search module to update focus and cache
1230
+ if (_this._searchModule) {
1231
+ _this._searchModule.refreshAfterSearch();
1219
1232
  }
1220
1233
  })
1221
1234
  .catch(function (error) {
@@ -1312,19 +1325,47 @@ var KTSelect = /** @class */ (function (_super) {
1312
1325
  * Centralized keyboard event handler for all select modes
1313
1326
  */
1314
1327
  KTSelect.prototype._handleKeyboardEvent = function (event) {
1328
+ // If the event target is the search input and the event was already handled (defaultPrevented),
1329
+ // then return early to avoid duplicate processing by this broader handler.
1330
+ if (event.target === this._searchInputElement && event.defaultPrevented) {
1331
+ return;
1332
+ }
1315
1333
  var isOpen = this._dropdownIsOpen;
1316
1334
  var config = this._config;
1317
1335
  var focusManager = this._focusManager;
1318
1336
  var buffer = this._typeToSearchBuffer;
1319
- // Ignore modifier keys
1337
+ // If the event target is the search input, let it handle most typing keys naturally.
1338
+ if (event.target === this._searchInputElement) {
1339
+ // Allow navigation keys like ArrowDown, ArrowUp, Escape, Enter (for search/selection) to be handled by the logic below.
1340
+ // For other keys (characters, space, backspace, delete), let the input field process them.
1341
+ if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp' &&
1342
+ event.key !== 'Escape' && event.key !== 'Enter' && event.key !== 'Tab' &&
1343
+ event.key !== 'Home' && event.key !== 'End') {
1344
+ // If it's a character key and we are NOT type-to-searching (because search has focus)
1345
+ // then let the input field handle it for its own value.
1346
+ // The search module's 'input' event will handle filtering based on the input's value.
1347
+ buffer.clear(); // Clear type-to-search buffer when typing in search field
1348
+ return;
1349
+ }
1350
+ // For Enter specifically in search input, we might want to select the focused option or submit search.
1351
+ // This is handled later in the switch.
1352
+ }
1353
+ // Ignore modifier keys (except for specific combinations if added later)
1320
1354
  if (event.altKey || event.ctrlKey || event.metaKey)
1321
1355
  return;
1322
- // Type-to-search: only for single char keys
1323
- if (event.key.length === 1 && !event.repeat && !event.key.match(/\s/)) {
1356
+ // Type-to-search: only for single char keys, when search input does not have focus
1357
+ if (event.key.length === 1 && !event.repeat && !event.key.match(/\s/) && document.activeElement !== this._searchInputElement) {
1324
1358
  buffer.push(event.key);
1325
1359
  var str = buffer.getBuffer();
1326
- focusManager.focusByString(str);
1327
- return;
1360
+ if (isOpen) {
1361
+ focusManager.focusByString(str);
1362
+ }
1363
+ else {
1364
+ // If closed, type-to-search could potentially open and select.
1365
+ // For now, let's assume it only works when open or opens it first.
1366
+ // Or, we could find the matching option and set it directly without opening.
1367
+ }
1368
+ return; // Type-to-search handles the event
1328
1369
  }
1329
1370
  switch (event.key) {
1330
1371
  case 'ArrowDown':
@@ -1358,18 +1399,28 @@ var KTSelect = /** @class */ (function (_super) {
1358
1399
  case 'Enter':
1359
1400
  case ' ': // Space
1360
1401
  if (isOpen) {
1361
- var focused = focusManager.getFocusedOption();
1362
- if (focused) {
1363
- var value = focused.dataset.value;
1364
- if (value) {
1365
- this.toggleSelection(value);
1366
- if (!config.multiple && config.closeOnSelect) {
1367
- this.closeDropdown();
1368
- }
1402
+ var focusedOptionEl = this._focusManager.getFocusedOption();
1403
+ if (focusedOptionEl) {
1404
+ var val = focusedOptionEl.dataset.value;
1405
+ // If single select, and the item is already selected, just close.
1406
+ if (val !== undefined && !this._config.multiple && this._state.isSelected(val)) {
1407
+ if (this._config.debug)
1408
+ console.log('Enter on already selected item in single-select mode. Closing.');
1409
+ this.closeDropdown();
1410
+ event.preventDefault();
1411
+ break;
1369
1412
  }
1370
1413
  }
1371
- // Prevent form submit
1372
- event.preventDefault();
1414
+ // Proceed with selection if not handled above
1415
+ this.selectFocusedOption();
1416
+ // Close dropdown if configured to do so (for new selections)
1417
+ if (!this._config.multiple) {
1418
+ // This will also be true for the case handled above, but closeDropdown is idempotent.
1419
+ // However, the break above prevents this from being reached for that specific case.
1420
+ this.closeDropdown();
1421
+ }
1422
+ event.preventDefault(); // Prevent form submission or other default actions
1423
+ break;
1373
1424
  }
1374
1425
  else {
1375
1426
  this.openDropdown();
@@ -1413,6 +1464,9 @@ var KTSelect = /** @class */ (function (_super) {
1413
1464
  }).filter(Boolean)));
1414
1465
  return contentArray.join(displaySeparator);
1415
1466
  };
1467
+ KTSelect.prototype.getDisplayElement = function () {
1468
+ return this._displayElement;
1469
+ };
1416
1470
  /**
1417
1471
  * ========================================================================
1418
1472
  * STATIC METHODS