@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
|
@@ -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.
|
|
170
|
+
optionsContainer.appendChild(templates_1.defaultTemplates.error(__assign(__assign({}, this._config), { errorMessage: message })));
|
|
169
171
|
break;
|
|
170
172
|
case 'loading':
|
|
171
|
-
optionsContainer.
|
|
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
|
-
//
|
|
441
|
-
//
|
|
442
|
-
|
|
443
|
-
|
|
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
|
|
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
|
-
//
|
|
685
|
-
this._searchModule.
|
|
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
|
-
//
|
|
720
|
-
var
|
|
721
|
-
|
|
722
|
-
|
|
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
|
-
|
|
786
|
-
|
|
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
|
-
|
|
792
|
-
|
|
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
|
-
|
|
796
|
-
|
|
797
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
1097
|
+
// Ensure any search input is cleared when selection changes
|
|
1084
1098
|
if (this._searchModule) {
|
|
1085
|
-
this._searchModule.
|
|
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
|
|
1127
|
+
else {
|
|
1115
1128
|
if (this._config.debug)
|
|
1116
|
-
console.log('About to call closeDropdown() for multiple select
|
|
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
|
|
1217
|
-
if (_this._searchModule
|
|
1218
|
-
_this._searchModule.
|
|
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
|
-
//
|
|
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
|
-
|
|
1327
|
-
|
|
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
|
|
1362
|
-
if (
|
|
1363
|
-
var
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
if (
|
|
1367
|
-
|
|
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
|
-
//
|
|
1372
|
-
|
|
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
|