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