@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
package/dist/ktui.js
CHANGED
|
@@ -2453,7 +2453,7 @@ var KTComponent = /** @class */ (function () {
|
|
|
2453
2453
|
if (config === void 0) { config = {}; }
|
|
2454
2454
|
if (!this._element)
|
|
2455
2455
|
return;
|
|
2456
|
-
this._config = __assign(__assign(__assign(__assign(
|
|
2456
|
+
this._config = __assign(__assign(__assign(__assign({}, this._defaultConfig), this._getGlobalConfig()), dom_1.default.getDataAttributes(this._element, this._dataOptionPrefix + this._name)), config);
|
|
2457
2457
|
};
|
|
2458
2458
|
KTComponent.prototype.dispose = function () {
|
|
2459
2459
|
if (!this._element)
|
|
@@ -5653,6 +5653,17 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
5653
5653
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
5654
5654
|
};
|
|
5655
5655
|
})();
|
|
5656
|
+
var __assign = (this && this.__assign) || function () {
|
|
5657
|
+
__assign = Object.assign || function(t) {
|
|
5658
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5659
|
+
s = arguments[i];
|
|
5660
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
5661
|
+
t[p] = s[p];
|
|
5662
|
+
}
|
|
5663
|
+
return t;
|
|
5664
|
+
};
|
|
5665
|
+
return __assign.apply(this, arguments);
|
|
5666
|
+
};
|
|
5656
5667
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
5657
5668
|
exports.KTSelectOption = void 0;
|
|
5658
5669
|
var component_1 = __webpack_require__(2658);
|
|
@@ -5665,39 +5676,61 @@ var KTSelectOption = /** @class */ (function (_super) {
|
|
|
5665
5676
|
_this._dataOptionPrefix = 'kt-'; // Use 'kt-' prefix to support data-kt-select-option attributes
|
|
5666
5677
|
// Always initialize a new option instance
|
|
5667
5678
|
_this._init(element);
|
|
5668
|
-
_this._buildConfig();
|
|
5669
5679
|
_this._globalConfig = config;
|
|
5680
|
+
_this._buildConfig();
|
|
5670
5681
|
// Clean the config
|
|
5671
5682
|
_this._config = _this._config[''] || {};
|
|
5672
5683
|
// Add the option config to the global config
|
|
5673
|
-
|
|
5674
|
-
_this._globalConfig
|
|
5684
|
+
// Ensure optionsConfig is initialized
|
|
5685
|
+
if (_this._globalConfig) {
|
|
5686
|
+
_this._globalConfig.optionsConfig = _this._globalConfig.optionsConfig || {};
|
|
5687
|
+
_this._globalConfig.optionsConfig[element.value] = _this._config;
|
|
5688
|
+
}
|
|
5689
|
+
else {
|
|
5690
|
+
// Handle case where _globalConfig might be undefined, though constructor expects it.
|
|
5691
|
+
// This might indicate a need to ensure config is always passed or has a default.
|
|
5692
|
+
console.warn('KTSelectOption: _globalConfig is undefined during constructor.');
|
|
5693
|
+
}
|
|
5675
5694
|
// Don't store in KTData to avoid Singleton pattern issues
|
|
5676
5695
|
// Each option should be a unique instance
|
|
5677
5696
|
element.instance = _this;
|
|
5678
5697
|
return _this;
|
|
5679
5698
|
}
|
|
5699
|
+
Object.defineProperty(KTSelectOption.prototype, "id", {
|
|
5700
|
+
get: function () {
|
|
5701
|
+
return this.getHTMLOptionElement().value;
|
|
5702
|
+
},
|
|
5703
|
+
enumerable: false,
|
|
5704
|
+
configurable: true
|
|
5705
|
+
});
|
|
5706
|
+
Object.defineProperty(KTSelectOption.prototype, "title", {
|
|
5707
|
+
get: function () {
|
|
5708
|
+
return this.getHTMLOptionElement().textContent || '';
|
|
5709
|
+
},
|
|
5710
|
+
enumerable: false,
|
|
5711
|
+
configurable: true
|
|
5712
|
+
});
|
|
5680
5713
|
KTSelectOption.prototype.getHTMLOptionElement = function () {
|
|
5681
5714
|
return this._element;
|
|
5682
5715
|
};
|
|
5716
|
+
/**
|
|
5717
|
+
* Gathers all necessary data for rendering this option,
|
|
5718
|
+
* including standard HTML attributes and custom data-kt-* attributes.
|
|
5719
|
+
*/
|
|
5720
|
+
KTSelectOption.prototype.getOptionDataForTemplate = function () {
|
|
5721
|
+
var el = this.getHTMLOptionElement();
|
|
5722
|
+
var text = el.textContent || '';
|
|
5723
|
+
return __assign(__assign({}, this._config), {
|
|
5724
|
+
// Standard HTMLOptionElement properties
|
|
5725
|
+
value: el.value, text: text, selected: el.selected, disabled: el.disabled,
|
|
5726
|
+
// Provide 'content' for convenience in templates, defaulting to text.
|
|
5727
|
+
// User's optionTemplate can then use {{content}} or specific fields like {{text}}, {{icon}}, etc.
|
|
5728
|
+
content: text });
|
|
5729
|
+
};
|
|
5683
5730
|
KTSelectOption.prototype.render = function () {
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
var originalTemplate = this._globalConfig.optionTemplate;
|
|
5688
|
-
if (this._globalConfig.optionTemplate) {
|
|
5689
|
-
// Replace all {{varname}} in option.innerHTML with values from _config
|
|
5690
|
-
Object.entries(this._config || {}).forEach(function (_a) {
|
|
5691
|
-
var key = _a[0], value = _a[1];
|
|
5692
|
-
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
5693
|
-
_this._globalConfig.optionTemplate = _this._globalConfig.optionTemplate.replace(new RegExp("{{".concat(key, "}}"), 'g'), String(value));
|
|
5694
|
-
}
|
|
5695
|
-
});
|
|
5696
|
-
}
|
|
5697
|
-
var template = templates_1.defaultTemplates.option(optionElement, this._globalConfig);
|
|
5698
|
-
// Restore the original template
|
|
5699
|
-
this._globalConfig.optionTemplate = originalTemplate;
|
|
5700
|
-
return template;
|
|
5731
|
+
// 'this' is the KTSelectOption instance.
|
|
5732
|
+
// defaultTemplates.option will handle using this instance's data along with _globalConfig.
|
|
5733
|
+
return templates_1.defaultTemplates.option(this, this._globalConfig);
|
|
5701
5734
|
};
|
|
5702
5735
|
return KTSelectOption;
|
|
5703
5736
|
}(component_1.default));
|
|
@@ -6515,52 +6548,35 @@ Object.defineProperty(exports, "KTScrollspy", ({ enumerable: true, get: function
|
|
|
6515
6548
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6516
6549
|
exports.KTSelectCombobox = void 0;
|
|
6517
6550
|
var utils_1 = __webpack_require__(9011);
|
|
6551
|
+
var templates_1 = __webpack_require__(9069);
|
|
6518
6552
|
/**
|
|
6519
6553
|
* KTSelectCombobox - Handles combobox-specific functionality for KTSelect
|
|
6520
6554
|
*/
|
|
6521
6555
|
var KTSelectCombobox = /** @class */ (function () {
|
|
6522
6556
|
function KTSelectCombobox(select) {
|
|
6523
6557
|
var _this = this;
|
|
6524
|
-
var _a;
|
|
6525
6558
|
this._select = select;
|
|
6526
6559
|
this._config = select.getConfig();
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
this.
|
|
6531
|
-
displayElement.tagName === 'INPUT'
|
|
6532
|
-
? displayElement
|
|
6533
|
-
: displayElement.querySelector('input[data-kt-select-search]');
|
|
6534
|
-
// Find the clear button robustly
|
|
6535
|
-
var clearButtonContainer = null;
|
|
6536
|
-
if (displayElement.tagName === 'DIV') {
|
|
6537
|
-
clearButtonContainer = displayElement;
|
|
6538
|
-
}
|
|
6539
|
-
else if (displayElement.tagName === 'INPUT') {
|
|
6540
|
-
clearButtonContainer = displayElement.parentElement;
|
|
6541
|
-
}
|
|
6542
|
-
this._clearButtonElement = clearButtonContainer
|
|
6543
|
-
? clearButtonContainer.querySelector('[data-kt-select-clear-button]')
|
|
6544
|
-
: null;
|
|
6545
|
-
this._valuesContainerElement = (_a = displayElement === null || displayElement === void 0 ? void 0 : displayElement.closest('[data-kt-select-combobox]')) === null || _a === void 0 ? void 0 : _a.querySelector('[data-kt-select-combobox-values]');
|
|
6546
|
-
// Create bound handler references to allow proper cleanup
|
|
6560
|
+
var displayElement = select.getDisplayElement(); // KTSelect's main display element for combobox
|
|
6561
|
+
this._searchInputElement = displayElement.querySelector('input[data-kt-select-search]');
|
|
6562
|
+
this._clearButtonElement = displayElement.querySelector('[data-kt-select-clear-button]');
|
|
6563
|
+
this._valuesContainerElement = displayElement.querySelector('[data-kt-select-combobox-values]');
|
|
6547
6564
|
this._boundInputHandler = this._handleComboboxInput.bind(this);
|
|
6548
6565
|
this._boundClearHandler = this._handleClearButtonClick.bind(this);
|
|
6549
|
-
// Attach event listeners
|
|
6550
6566
|
this._attachEventListeners();
|
|
6551
|
-
// Reset combobox search state when dropdown closes
|
|
6552
6567
|
this._select.getElement().addEventListener('dropdown.close', function () {
|
|
6553
|
-
|
|
6554
|
-
//
|
|
6555
|
-
_this.
|
|
6568
|
+
// When dropdown closes, if not multi-select and not using displayTemplate,
|
|
6569
|
+
// ensure input shows the selected value or placeholder.
|
|
6570
|
+
if (!_this._config.multiple && !_this._config.displayTemplate) {
|
|
6571
|
+
_this.updateDisplay(_this._select.getSelectedOptions());
|
|
6572
|
+
}
|
|
6573
|
+
else {
|
|
6574
|
+
// For tags or displayTemplate, the input should be clear for typing.
|
|
6575
|
+
_this._searchInputElement.value = '';
|
|
6576
|
+
}
|
|
6577
|
+
_this._toggleClearButtonVisibility(_this._searchInputElement.value);
|
|
6578
|
+
// this._select.showAllOptions(); // showAllOptions might be too broad, filtering is managed by typing.
|
|
6556
6579
|
});
|
|
6557
|
-
// When selection changes, update the input value to the selected option's text
|
|
6558
|
-
// this._select.getElement().addEventListener('change', () => {
|
|
6559
|
-
// // Only update the input value, do not reset the filter or show all options
|
|
6560
|
-
// const selectedValues = this._select.getSelectedOptions();
|
|
6561
|
-
// const content = this._select.renderDisplayTemplateForSelected(selectedValues);
|
|
6562
|
-
// this._valuesContainerElement?.append(stringToElement(content));
|
|
6563
|
-
// });
|
|
6564
6580
|
if (this._config.debug)
|
|
6565
6581
|
console.log('KTSelectCombobox initialized');
|
|
6566
6582
|
}
|
|
@@ -6568,16 +6584,13 @@ var KTSelectCombobox = /** @class */ (function () {
|
|
|
6568
6584
|
* Attach event listeners specific to combobox
|
|
6569
6585
|
*/
|
|
6570
6586
|
KTSelectCombobox.prototype._attachEventListeners = function () {
|
|
6571
|
-
// First remove any existing listeners to prevent duplicates
|
|
6572
6587
|
this._removeEventListeners();
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6588
|
+
if (this._searchInputElement) { // Ensure element exists
|
|
6589
|
+
this._searchInputElement.addEventListener('input', this._boundInputHandler);
|
|
6590
|
+
}
|
|
6576
6591
|
if (this._clearButtonElement) {
|
|
6577
6592
|
this._clearButtonElement.addEventListener('click', this._boundClearHandler);
|
|
6578
6593
|
}
|
|
6579
|
-
if (this._config.debug)
|
|
6580
|
-
console.log('Combobox event listeners attached to:', this._searchInputElement);
|
|
6581
6594
|
};
|
|
6582
6595
|
/**
|
|
6583
6596
|
* Remove event listeners to prevent memory leaks or duplicates
|
|
@@ -6595,16 +6608,21 @@ var KTSelectCombobox = /** @class */ (function () {
|
|
|
6595
6608
|
*/
|
|
6596
6609
|
KTSelectCombobox.prototype._handleComboboxInput = function (event) {
|
|
6597
6610
|
var inputElement = event.target;
|
|
6598
|
-
var query = inputElement.value
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
// Toggle clear button visibility based on input value
|
|
6602
|
-
// this._toggleClearButtonVisibility(query);
|
|
6603
|
-
// If dropdown isn't open, open it when user starts typing
|
|
6604
|
-
if (!this._select._dropdownIsOpen) {
|
|
6611
|
+
var query = inputElement.value;
|
|
6612
|
+
this._toggleClearButtonVisibility(query);
|
|
6613
|
+
if (!this._select.isDropdownOpen()) { // Use public getter
|
|
6605
6614
|
this._select.openDropdown();
|
|
6606
6615
|
}
|
|
6607
|
-
//
|
|
6616
|
+
// For single select without displayTemplate, if user types, they are essentially clearing the previous selection text
|
|
6617
|
+
// The actual selection state isn't cleared until they pick a new option or clear explicitly.
|
|
6618
|
+
// For multi-select or with displayTemplate, the input is purely for search.
|
|
6619
|
+
if (this._config.multiple || this._config.displayTemplate) {
|
|
6620
|
+
// Values are in _valuesContainerElement, input is for search
|
|
6621
|
+
}
|
|
6622
|
+
else {
|
|
6623
|
+
// Single select, no displayTemplate: If user types, it implies they might be changing selection.
|
|
6624
|
+
// We don't clear the actual _select state here, just the visual in input.
|
|
6625
|
+
}
|
|
6608
6626
|
this._filterOptionsForCombobox(query);
|
|
6609
6627
|
};
|
|
6610
6628
|
/**
|
|
@@ -6613,29 +6631,25 @@ var KTSelectCombobox = /** @class */ (function () {
|
|
|
6613
6631
|
KTSelectCombobox.prototype._handleClearButtonClick = function (event) {
|
|
6614
6632
|
event.preventDefault();
|
|
6615
6633
|
event.stopPropagation();
|
|
6616
|
-
// Clear the input
|
|
6617
6634
|
this._searchInputElement.value = '';
|
|
6618
|
-
|
|
6619
|
-
// this._toggleClearButtonVisibility('');
|
|
6620
|
-
// Show all options and open dropdown
|
|
6621
|
-
this._select.showAllOptions();
|
|
6622
|
-
this._select.openDropdown();
|
|
6623
|
-
// Clear the current selection
|
|
6624
|
-
this._select.clearSelection();
|
|
6625
|
-
// Clear the combobox values container if present (for displayTemplate)
|
|
6635
|
+
this._toggleClearButtonVisibility('');
|
|
6626
6636
|
if (this._valuesContainerElement) {
|
|
6627
6637
|
this._valuesContainerElement.innerHTML = '';
|
|
6628
6638
|
}
|
|
6629
|
-
//
|
|
6639
|
+
this._select.clearSelection(); // This will also trigger updateSelectedOptionDisplay
|
|
6640
|
+
this._select.showAllOptions(); // Show all options after clearing
|
|
6641
|
+
this._select.openDropdown();
|
|
6630
6642
|
this._searchInputElement.focus();
|
|
6631
6643
|
};
|
|
6632
6644
|
/**
|
|
6633
|
-
* Toggle clear button visibility based on input value
|
|
6645
|
+
* Toggle clear button visibility based on input value and selection state.
|
|
6646
|
+
* Clear button should be visible if there's text in input OR if there are selected items (for multi/displayTemplate modes).
|
|
6634
6647
|
*/
|
|
6635
|
-
KTSelectCombobox.prototype._toggleClearButtonVisibility = function (
|
|
6648
|
+
KTSelectCombobox.prototype._toggleClearButtonVisibility = function (inputValue) {
|
|
6636
6649
|
if (!this._clearButtonElement)
|
|
6637
6650
|
return;
|
|
6638
|
-
|
|
6651
|
+
var hasSelectedItems = this._select.getSelectedOptions().length > 0;
|
|
6652
|
+
if (inputValue.length > 0 || (hasSelectedItems && (this._config.multiple || this._config.displayTemplate))) {
|
|
6639
6653
|
this._clearButtonElement.classList.remove('hidden');
|
|
6640
6654
|
}
|
|
6641
6655
|
else {
|
|
@@ -6646,11 +6660,65 @@ var KTSelectCombobox = /** @class */ (function () {
|
|
|
6646
6660
|
* Filter options for combobox based on input query
|
|
6647
6661
|
*/
|
|
6648
6662
|
KTSelectCombobox.prototype._filterOptionsForCombobox = function (query) {
|
|
6649
|
-
// Use the same filter logic as KTSelectSearch
|
|
6650
6663
|
var options = Array.from(this._select.getOptionsElement());
|
|
6651
6664
|
var config = this._select.getConfig();
|
|
6652
6665
|
var dropdownElement = this._select.getDropdownElement();
|
|
6653
6666
|
(0, utils_1.filterOptions)(options, query, config, dropdownElement);
|
|
6667
|
+
// After filtering, focusManager in KTSelectSearch (if search is also enabled there)
|
|
6668
|
+
// or the main FocusManager should adjust focus if needed.
|
|
6669
|
+
// For combobox, this filtering is the primary search mechanism.
|
|
6670
|
+
// We might need to tell select's focus manager to focus first option.
|
|
6671
|
+
this._select._focusManager.focusFirst(); // Consider if this is always right
|
|
6672
|
+
};
|
|
6673
|
+
/**
|
|
6674
|
+
* Updates the combobox display (input field or values container) based on selection.
|
|
6675
|
+
*/
|
|
6676
|
+
KTSelectCombobox.prototype.updateDisplay = function (selectedOptions) {
|
|
6677
|
+
var _this = this;
|
|
6678
|
+
if (!this._searchInputElement)
|
|
6679
|
+
return;
|
|
6680
|
+
// Always clear the values container first if it exists
|
|
6681
|
+
if (this._valuesContainerElement) {
|
|
6682
|
+
this._valuesContainerElement.innerHTML = '';
|
|
6683
|
+
}
|
|
6684
|
+
if (this._config.tags && this._valuesContainerElement) { // Combobox + Tags
|
|
6685
|
+
selectedOptions.forEach(function (value) {
|
|
6686
|
+
// Ensure value is properly escaped for querySelector
|
|
6687
|
+
var optionElement = _this._select.getElement().querySelector("option[value=\"".concat(CSS.escape(value), "\"]"));
|
|
6688
|
+
if (optionElement) {
|
|
6689
|
+
var tagElement = templates_1.defaultTemplates.tag(optionElement, _this._config);
|
|
6690
|
+
_this._valuesContainerElement.appendChild(tagElement);
|
|
6691
|
+
}
|
|
6692
|
+
});
|
|
6693
|
+
this._searchInputElement.value = ''; // Input field is for typing new searches
|
|
6694
|
+
this._searchInputElement.placeholder = selectedOptions.length > 0 ? '' : (this._config.placeholder || 'Select...');
|
|
6695
|
+
}
|
|
6696
|
+
else if (this._config.displayTemplate && this._valuesContainerElement) { // Combobox + DisplayTemplate (no tags)
|
|
6697
|
+
this._valuesContainerElement.innerHTML = this._select.renderDisplayTemplateForSelected(selectedOptions);
|
|
6698
|
+
this._searchInputElement.value = ''; // Input field is for typing new searches
|
|
6699
|
+
this._searchInputElement.placeholder = selectedOptions.length > 0 ? '' : (this._config.placeholder || 'Select...');
|
|
6700
|
+
}
|
|
6701
|
+
else if (this._config.multiple && this._valuesContainerElement) { // Combobox + Multiple (no tags, no display template)
|
|
6702
|
+
// For simplicity, join text. A proper tag implementation would be more complex here.
|
|
6703
|
+
this._valuesContainerElement.innerHTML = selectedOptions.map(function (value) {
|
|
6704
|
+
var optionEl = _this._select.getElement().querySelector("option[value=\"".concat(CSS.escape(value), "\"]"));
|
|
6705
|
+
return optionEl ? optionEl.textContent : '';
|
|
6706
|
+
}).join(', '); // Basic comma separation
|
|
6707
|
+
this._searchInputElement.value = '';
|
|
6708
|
+
this._searchInputElement.placeholder = selectedOptions.length > 0 ? '' : (this._config.placeholder || 'Select...');
|
|
6709
|
+
}
|
|
6710
|
+
else if (!this._config.multiple && selectedOptions.length > 0) { // Single select combobox: display selected option's text in the input
|
|
6711
|
+
var selectedValue = selectedOptions[0];
|
|
6712
|
+
var optionElement = this._select.getElement().querySelector("option[value=\"".concat(CSS.escape(selectedValue), "\"]"));
|
|
6713
|
+
this._searchInputElement.value = optionElement ? optionElement.textContent || '' : '';
|
|
6714
|
+
// placeholder is implicitly handled by input value for single select
|
|
6715
|
+
}
|
|
6716
|
+
else { // No selection or not fitting above categories (e.g. single select, no items)
|
|
6717
|
+
this._searchInputElement.value = '';
|
|
6718
|
+
this._searchInputElement.placeholder = this._config.placeholder || 'Select...';
|
|
6719
|
+
// _valuesContainerElement is already cleared if it exists
|
|
6720
|
+
}
|
|
6721
|
+
this._toggleClearButtonVisibility(this._searchInputElement.value);
|
|
6654
6722
|
};
|
|
6655
6723
|
/**
|
|
6656
6724
|
* Destroy the combobox component and clean up event listeners
|
|
@@ -7895,7 +7963,7 @@ var KTDataTable = /** @class */ (function (_super) {
|
|
|
7895
7963
|
// Set search value
|
|
7896
7964
|
if (searchElement) {
|
|
7897
7965
|
searchElement.value =
|
|
7898
|
-
typeof search === 'string' ? search : String(search);
|
|
7966
|
+
search === undefined || search === null ? '' : typeof search === 'string' ? search : String(search);
|
|
7899
7967
|
}
|
|
7900
7968
|
if (searchElement) {
|
|
7901
7969
|
// Check if a debounced search function already exists
|
|
@@ -9217,7 +9285,7 @@ var utils_1 = __webpack_require__(9011);
|
|
|
9217
9285
|
*
|
|
9218
9286
|
* A specialized dropdown implementation for the KTSelect component.
|
|
9219
9287
|
* This module handles the dropdown functionality for the select component,
|
|
9220
|
-
* including positioning
|
|
9288
|
+
* including positioning and showing/hiding.
|
|
9221
9289
|
*/
|
|
9222
9290
|
var KTSelectDropdown = /** @class */ (function (_super) {
|
|
9223
9291
|
__extends(KTSelectDropdown, _super);
|
|
@@ -9228,7 +9296,7 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9228
9296
|
* @param dropdownElement The dropdown content element
|
|
9229
9297
|
* @param config The configuration options
|
|
9230
9298
|
*/
|
|
9231
|
-
function KTSelectDropdown(element, toggleElement, dropdownElement, config) {
|
|
9299
|
+
function KTSelectDropdown(element, toggleElement, dropdownElement, config, ktSelectInstance) {
|
|
9232
9300
|
var _this = _super.call(this) || this;
|
|
9233
9301
|
_this._name = 'select-dropdown';
|
|
9234
9302
|
// State
|
|
@@ -9239,6 +9307,7 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9239
9307
|
_this._toggleElement = toggleElement;
|
|
9240
9308
|
_this._dropdownElement = dropdownElement;
|
|
9241
9309
|
_this._config = config;
|
|
9310
|
+
_this._ktSelectInstance = ktSelectInstance; // Assign instance
|
|
9242
9311
|
_this._eventManager = new utils_1.EventManager();
|
|
9243
9312
|
_this._focusManager = new utils_1.FocusManager(dropdownElement, '[data-kt-select-option]', config);
|
|
9244
9313
|
_this._setupEventListeners();
|
|
@@ -9259,7 +9328,18 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9259
9328
|
KTSelectDropdown.prototype._handleToggleClick = function (event) {
|
|
9260
9329
|
event.preventDefault();
|
|
9261
9330
|
event.stopPropagation();
|
|
9262
|
-
this.
|
|
9331
|
+
if (this._config.disabled) {
|
|
9332
|
+
if (this._config.debug)
|
|
9333
|
+
console.log('KTSelectDropdown._handleToggleClick: select is disabled');
|
|
9334
|
+
return;
|
|
9335
|
+
}
|
|
9336
|
+
// Call KTSelect's methods
|
|
9337
|
+
if (this._ktSelectInstance.isDropdownOpen()) {
|
|
9338
|
+
this._ktSelectInstance.closeDropdown();
|
|
9339
|
+
}
|
|
9340
|
+
else {
|
|
9341
|
+
this._ktSelectInstance.openDropdown();
|
|
9342
|
+
}
|
|
9263
9343
|
};
|
|
9264
9344
|
/**
|
|
9265
9345
|
* Handle clicks outside the dropdown
|
|
@@ -9270,7 +9350,8 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9270
9350
|
var target = event.target;
|
|
9271
9351
|
if (!this._element.contains(target) &&
|
|
9272
9352
|
!this._dropdownElement.contains(target)) {
|
|
9273
|
-
|
|
9353
|
+
// Call KTSelect's closeDropdown method
|
|
9354
|
+
this._ktSelectInstance.closeDropdown();
|
|
9274
9355
|
}
|
|
9275
9356
|
};
|
|
9276
9357
|
/**
|
|
@@ -9372,29 +9453,6 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9372
9453
|
this._popperInstance.update();
|
|
9373
9454
|
}
|
|
9374
9455
|
};
|
|
9375
|
-
/**
|
|
9376
|
-
* Toggle the dropdown
|
|
9377
|
-
*/
|
|
9378
|
-
KTSelectDropdown.prototype.toggle = function () {
|
|
9379
|
-
if (this._config.disabled) {
|
|
9380
|
-
if (this._config.debug)
|
|
9381
|
-
console.log('KTSelectDropdown.toggle: select is disabled, not toggling');
|
|
9382
|
-
return;
|
|
9383
|
-
}
|
|
9384
|
-
if (this._config.debug)
|
|
9385
|
-
console.log('KTSelectDropdown.toggle called - isOpen:', this._isOpen);
|
|
9386
|
-
if (this._isTransitioning) {
|
|
9387
|
-
if (this._config.debug)
|
|
9388
|
-
console.log('KTSelectDropdown.toggle - ignoring during transition');
|
|
9389
|
-
return;
|
|
9390
|
-
}
|
|
9391
|
-
if (this._isOpen) {
|
|
9392
|
-
this.close();
|
|
9393
|
-
}
|
|
9394
|
-
else {
|
|
9395
|
-
this.open();
|
|
9396
|
-
}
|
|
9397
|
-
};
|
|
9398
9456
|
/**
|
|
9399
9457
|
* Open the dropdown
|
|
9400
9458
|
*/
|
|
@@ -9407,71 +9465,41 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9407
9465
|
}
|
|
9408
9466
|
if (this._isOpen || this._isTransitioning)
|
|
9409
9467
|
return;
|
|
9410
|
-
// Fire before show event
|
|
9411
|
-
var beforeShowEvent = new CustomEvent('kt.select.dropdown.show', {
|
|
9412
|
-
bubbles: true,
|
|
9413
|
-
cancelable: true,
|
|
9414
|
-
});
|
|
9415
|
-
this._element.dispatchEvent(beforeShowEvent);
|
|
9416
|
-
if (beforeShowEvent.defaultPrevented)
|
|
9417
|
-
return;
|
|
9418
9468
|
// Begin opening transition
|
|
9419
9469
|
this._isTransitioning = true;
|
|
9420
|
-
// Set initial styles
|
|
9470
|
+
// Set initial styles
|
|
9421
9471
|
this._dropdownElement.classList.remove('hidden');
|
|
9422
9472
|
this._dropdownElement.style.opacity = '0';
|
|
9423
9473
|
// Set dropdown width
|
|
9424
9474
|
this._setDropdownWidth();
|
|
9425
|
-
//
|
|
9475
|
+
// Reflow
|
|
9426
9476
|
dom_1.default.reflow(this._dropdownElement);
|
|
9427
|
-
// Apply z-index
|
|
9477
|
+
// Apply z-index
|
|
9428
9478
|
if (this._config.dropdownZindex) {
|
|
9429
9479
|
this._dropdownElement.style.zIndex =
|
|
9430
9480
|
this._config.dropdownZindex.toString();
|
|
9431
9481
|
}
|
|
9432
9482
|
else {
|
|
9433
|
-
// Auto-calculate z-index
|
|
9434
9483
|
var parentZindex = dom_1.default.getHighestZindex(this._element);
|
|
9435
9484
|
if (parentZindex) {
|
|
9436
9485
|
this._dropdownElement.style.zIndex = (parentZindex + 1).toString();
|
|
9437
9486
|
}
|
|
9438
9487
|
}
|
|
9439
|
-
// Initialize popper
|
|
9488
|
+
// Initialize popper
|
|
9440
9489
|
this._initPopper();
|
|
9441
|
-
// Add active classes
|
|
9490
|
+
// Add active classes for visual state
|
|
9442
9491
|
this._dropdownElement.classList.add('open');
|
|
9443
9492
|
this._toggleElement.classList.add('active');
|
|
9444
|
-
|
|
9493
|
+
// ARIA attributes will be handled by KTSelect
|
|
9445
9494
|
// Start transition
|
|
9446
9495
|
this._dropdownElement.style.opacity = '1';
|
|
9447
9496
|
// Handle transition end
|
|
9448
9497
|
dom_1.default.transitionEnd(this._dropdownElement, function () {
|
|
9449
9498
|
_this._isTransitioning = false;
|
|
9450
9499
|
_this._isOpen = true;
|
|
9451
|
-
// Focus
|
|
9452
|
-
if (_this._config.enableSearch) {
|
|
9453
|
-
var searchInput = _this._dropdownElement.querySelector('input[type="search"]');
|
|
9454
|
-
if (searchInput) {
|
|
9455
|
-
searchInput.focus();
|
|
9456
|
-
}
|
|
9457
|
-
}
|
|
9458
|
-
// Fire after show event
|
|
9459
|
-
var afterShowEvent = new CustomEvent('kt.select.dropdown.shown', {
|
|
9460
|
-
bubbles: true,
|
|
9461
|
-
});
|
|
9462
|
-
_this._element.dispatchEvent(afterShowEvent);
|
|
9500
|
+
// Focus and events will be handled by KTSelect
|
|
9463
9501
|
});
|
|
9464
9502
|
};
|
|
9465
|
-
/**
|
|
9466
|
-
* Focus the first option in the dropdown
|
|
9467
|
-
*/
|
|
9468
|
-
KTSelectDropdown.prototype._focusFirstOption = function () {
|
|
9469
|
-
var firstOption = this._focusManager.getVisibleOptions()[0];
|
|
9470
|
-
if (firstOption) {
|
|
9471
|
-
this._focusManager.applyFocus(firstOption);
|
|
9472
|
-
this._focusManager.scrollIntoView(firstOption);
|
|
9473
|
-
}
|
|
9474
|
-
};
|
|
9475
9503
|
/**
|
|
9476
9504
|
* Close the dropdown
|
|
9477
9505
|
*/
|
|
@@ -9484,34 +9512,19 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9484
9512
|
console.log('KTSelectDropdown.close - early return: dropdown not open or is transitioning');
|
|
9485
9513
|
return;
|
|
9486
9514
|
}
|
|
9487
|
-
//
|
|
9488
|
-
var beforeHideEvent = new CustomEvent('kt.select.dropdown.hide', {
|
|
9489
|
-
bubbles: true,
|
|
9490
|
-
cancelable: true,
|
|
9491
|
-
});
|
|
9492
|
-
this._element.dispatchEvent(beforeHideEvent);
|
|
9493
|
-
if (beforeHideEvent.defaultPrevented) {
|
|
9494
|
-
if (this._config.debug)
|
|
9495
|
-
console.log('KTSelectDropdown.close - canceling due to defaultPrevented on beforeHideEvent');
|
|
9496
|
-
return;
|
|
9497
|
-
}
|
|
9515
|
+
// Events and ARIA will be handled by KTSelect
|
|
9498
9516
|
if (this._config.debug)
|
|
9499
9517
|
console.log('KTSelectDropdown.close - starting transition');
|
|
9500
|
-
// Begin closing transition
|
|
9501
9518
|
this._isTransitioning = true;
|
|
9502
|
-
// Start transition
|
|
9503
9519
|
this._dropdownElement.style.opacity = '0';
|
|
9504
|
-
// Use a combination of transition end and a fallback timer
|
|
9505
9520
|
var transitionComplete = false;
|
|
9506
|
-
// Set a fixed-duration fallback in case the transition event doesn't fire
|
|
9507
9521
|
var fallbackTimer = setTimeout(function () {
|
|
9508
9522
|
if (!transitionComplete) {
|
|
9509
9523
|
if (_this._config.debug)
|
|
9510
9524
|
console.log('KTSelectDropdown.close - fallback timer triggered');
|
|
9511
9525
|
completeTransition();
|
|
9512
9526
|
}
|
|
9513
|
-
}, 300);
|
|
9514
|
-
// Setup the transition end function
|
|
9527
|
+
}, 300);
|
|
9515
9528
|
var completeTransition = function () {
|
|
9516
9529
|
if (transitionComplete)
|
|
9517
9530
|
return;
|
|
@@ -9519,30 +9532,21 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9519
9532
|
clearTimeout(fallbackTimer);
|
|
9520
9533
|
if (_this._config.debug)
|
|
9521
9534
|
console.log('KTSelectDropdown.close - transition ended');
|
|
9522
|
-
// Remove active classes
|
|
9523
9535
|
_this._dropdownElement.classList.add('hidden');
|
|
9524
9536
|
_this._dropdownElement.classList.remove('open');
|
|
9525
9537
|
_this._toggleElement.classList.remove('active');
|
|
9526
|
-
|
|
9527
|
-
// Reset styles - replace display: none with adding hidden class
|
|
9528
|
-
_this._dropdownElement.classList.add('hidden');
|
|
9529
|
-
_this._dropdownElement.style.opacity = '';
|
|
9530
|
-
_this._dropdownElement.style.zIndex = '';
|
|
9531
|
-
// Destroy popper
|
|
9538
|
+
// ARIA attributes will be handled by KTSelect
|
|
9532
9539
|
_this._destroyPopper();
|
|
9533
|
-
// Update state
|
|
9534
9540
|
_this._isTransitioning = false;
|
|
9535
9541
|
_this._isOpen = false;
|
|
9536
|
-
//
|
|
9537
|
-
var afterHideEvent = new CustomEvent('kt.select.dropdown.hidden', {
|
|
9538
|
-
bubbles: true,
|
|
9539
|
-
});
|
|
9540
|
-
_this._element.dispatchEvent(afterHideEvent);
|
|
9542
|
+
// Events will be handled by KTSelect
|
|
9541
9543
|
if (_this._config.debug)
|
|
9542
|
-
console.log('KTSelectDropdown.close -
|
|
9544
|
+
console.log('KTSelectDropdown.close - visual part complete');
|
|
9543
9545
|
};
|
|
9544
|
-
// Handle transition end via the utility but also have the fallback
|
|
9545
9546
|
dom_1.default.transitionEnd(this._dropdownElement, completeTransition);
|
|
9547
|
+
if (dom_1.default.getCssProp(this._dropdownElement, 'transition-duration') === '0s') {
|
|
9548
|
+
completeTransition();
|
|
9549
|
+
}
|
|
9546
9550
|
};
|
|
9547
9551
|
/**
|
|
9548
9552
|
* Check if dropdown is open
|
|
@@ -9910,15 +9914,17 @@ var KTSelectSearch = /** @class */ (function () {
|
|
|
9910
9914
|
console.log('Initializing search module with input:', this._searchInput);
|
|
9911
9915
|
// First remove any existing listeners to prevent duplicates
|
|
9912
9916
|
this._removeEventListeners();
|
|
9913
|
-
// Add the event listener
|
|
9917
|
+
// Add the input event listener for filtering
|
|
9914
9918
|
this._eventManager.addListener(this._searchInput, 'input', this.handleSearchInput);
|
|
9919
|
+
// Add keydown event listener for navigation, selection, and escape
|
|
9920
|
+
this._eventManager.addListener(this._searchInput, 'keydown', this._handleSearchKeyDown.bind(this));
|
|
9915
9921
|
// Add blur event listener to ensure highlights are cleared when focus is lost
|
|
9916
9922
|
this._eventManager.addListener(this._searchInput, 'blur', function () {
|
|
9917
9923
|
// Small delay to prevent race conditions with selection
|
|
9918
9924
|
setTimeout(function () {
|
|
9919
9925
|
if (!_this._searchInput.value) {
|
|
9920
9926
|
_this._resetAllOptions();
|
|
9921
|
-
_this.
|
|
9927
|
+
_this.clearSearch();
|
|
9922
9928
|
}
|
|
9923
9929
|
}, 100);
|
|
9924
9930
|
});
|
|
@@ -9936,39 +9942,48 @@ var KTSelectSearch = /** @class */ (function () {
|
|
|
9936
9942
|
_this.refreshOptionCache();
|
|
9937
9943
|
});
|
|
9938
9944
|
}
|
|
9939
|
-
// Listen for dropdown close to reset options
|
|
9940
|
-
this._select.
|
|
9945
|
+
// Listen for dropdown close to reset options - ATTACH TO WRAPPER
|
|
9946
|
+
this._select.getWrapperElement().addEventListener('dropdown.close', function () {
|
|
9941
9947
|
_this._focusManager.resetFocus();
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9948
|
+
// If clearSearchOnClose is false and there's a value, the search term and filtered state should persist.
|
|
9949
|
+
// KTSelect's closeDropdown method already calls this._searchModule.clearSearch() (which clears highlights)
|
|
9950
|
+
// and conditionally clears the input value based on KTSelect's config.clearSearchOnClose.
|
|
9951
|
+
// This listener in search.ts seems to unconditionally clear everything.
|
|
9952
|
+
// For now, keeping its original behavior:
|
|
9953
|
+
_this.clearSearch(); // Clears highlights from current options
|
|
9954
|
+
_this._searchInput.value = ''; // Clears the search input field
|
|
9955
|
+
_this._resetAllOptions(); // Shows all options, restores original text, removes highlights
|
|
9956
|
+
_this._clearNoResultsMessage(); // Clears any "no results" message
|
|
9946
9957
|
});
|
|
9947
|
-
// Clear highlights when an option is selected
|
|
9958
|
+
// Clear highlights when an option is selected - ATTACH TO ORIGINAL SELECT (standard 'change' event)
|
|
9948
9959
|
this._select.getElement().addEventListener('change', function () {
|
|
9949
|
-
_this.
|
|
9960
|
+
_this.clearSearch();
|
|
9950
9961
|
// Close dropdown if configured to do so
|
|
9951
|
-
|
|
9952
|
-
!_this._select.getConfig().multiple) {
|
|
9953
|
-
_this._select.closeDropdown();
|
|
9954
|
-
}
|
|
9962
|
+
_this._select.closeDropdown();
|
|
9955
9963
|
});
|
|
9956
|
-
//
|
|
9957
|
-
|
|
9958
|
-
|
|
9964
|
+
// Consolidated 'dropdown.show' event listener - ATTACH TO WRAPPER
|
|
9965
|
+
this._select.getWrapperElement().addEventListener('dropdown.show', function () {
|
|
9966
|
+
var _a;
|
|
9967
|
+
_this._focusManager.resetFocus(); // Always clear previous focus state
|
|
9968
|
+
if ((_a = _this._searchInput) === null || _a === void 0 ? void 0 : _a.value) {
|
|
9969
|
+
// If there's an existing search term:
|
|
9970
|
+
// 1. Re-filter options. This ensures the display (hidden/visible) is correct
|
|
9971
|
+
// and "no results" message is handled if query yields nothing.
|
|
9972
|
+
_this._filterOptions(_this._searchInput.value);
|
|
9973
|
+
}
|
|
9974
|
+
else {
|
|
9975
|
+
// If search input is empty:
|
|
9976
|
+
// 1. Reset all options to their full, unfiltered, original state.
|
|
9977
|
+
_this._resetAllOptions(); // Shows all, clears highlights from options, restores original text
|
|
9978
|
+
// 2. Clear any "no results" message.
|
|
9979
|
+
_this._clearNoResultsMessage();
|
|
9980
|
+
}
|
|
9981
|
+
// Handle autofocus for the search input (this was one of the original separate listeners)
|
|
9982
|
+
if (_this._select.getConfig().searchAutofocus) {
|
|
9959
9983
|
setTimeout(function () {
|
|
9960
9984
|
var _a;
|
|
9961
|
-
|
|
9962
|
-
|
|
9963
|
-
}, 50);
|
|
9964
|
-
});
|
|
9965
|
-
}
|
|
9966
|
-
// Listen for explicit dropdown open event to clear highlights if needed
|
|
9967
|
-
this._select.getElement().addEventListener('dropdown.show', function () {
|
|
9968
|
-
var _a;
|
|
9969
|
-
// If search input is empty, ensure highlights are cleared on open
|
|
9970
|
-
if (!((_a = _this._searchInput) === null || _a === void 0 ? void 0 : _a.value)) {
|
|
9971
|
-
_this.clearSearchHighlights();
|
|
9985
|
+
(_a = _this._searchInput) === null || _a === void 0 ? void 0 : _a.focus(); // Focus search input
|
|
9986
|
+
}, 50); // Delay to ensure dropdown is visible
|
|
9972
9987
|
}
|
|
9973
9988
|
});
|
|
9974
9989
|
}
|
|
@@ -9983,18 +9998,42 @@ var KTSelectSearch = /** @class */ (function () {
|
|
|
9983
9998
|
}
|
|
9984
9999
|
};
|
|
9985
10000
|
/**
|
|
9986
|
-
*
|
|
10001
|
+
* Handles keydown events on the search input for navigation and actions.
|
|
9987
10002
|
*/
|
|
9988
|
-
KTSelectSearch.prototype.
|
|
9989
|
-
var
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
10003
|
+
KTSelectSearch.prototype._handleSearchKeyDown = function (event) {
|
|
10004
|
+
var key = event.key;
|
|
10005
|
+
switch (key) {
|
|
10006
|
+
case 'ArrowDown':
|
|
10007
|
+
event.preventDefault();
|
|
10008
|
+
this._focusManager.focusNext();
|
|
10009
|
+
break;
|
|
10010
|
+
case 'ArrowUp':
|
|
10011
|
+
event.preventDefault();
|
|
10012
|
+
this._focusManager.focusPrevious();
|
|
10013
|
+
break;
|
|
10014
|
+
case 'Enter':
|
|
10015
|
+
event.preventDefault();
|
|
10016
|
+
// Always attempt to select the first available option in the list.
|
|
10017
|
+
// focusFirst() finds, focuses, and returns the first visible, non-disabled option.
|
|
10018
|
+
var firstAvailableOption = this._focusManager.focusFirst();
|
|
10019
|
+
if (firstAvailableOption) {
|
|
10020
|
+
var optionValue = firstAvailableOption.getAttribute('data-value');
|
|
10021
|
+
if (optionValue) {
|
|
10022
|
+
this._select.toggleSelection(optionValue);
|
|
10023
|
+
// KTSelect.toggleSelection handles closing the dropdown based on config.closeOnSelect and config.multiple
|
|
10024
|
+
}
|
|
10025
|
+
}
|
|
10026
|
+
break;
|
|
10027
|
+
case 'Escape':
|
|
10028
|
+
event.preventDefault();
|
|
10029
|
+
this._searchInput.value = '';
|
|
10030
|
+
this.clearSearch();
|
|
10031
|
+
this._resetAllOptions();
|
|
10032
|
+
this._clearNoResultsMessage();
|
|
10033
|
+
this._focusManager.focusFirst();
|
|
10034
|
+
break;
|
|
10035
|
+
default:
|
|
10036
|
+
break;
|
|
9998
10037
|
}
|
|
9999
10038
|
};
|
|
10000
10039
|
/**
|
|
@@ -10005,42 +10044,66 @@ var KTSelectSearch = /** @class */ (function () {
|
|
|
10005
10044
|
var _this = this;
|
|
10006
10045
|
// Wait for options to be initialized
|
|
10007
10046
|
setTimeout(function () {
|
|
10047
|
+
_this._originalOptionContents.clear(); // Clear before re-caching
|
|
10008
10048
|
var options = Array.from(_this._select.getOptionsElement());
|
|
10009
10049
|
options.forEach(function (option) {
|
|
10010
10050
|
var value = option.getAttribute('data-value');
|
|
10011
10051
|
if (value) {
|
|
10052
|
+
// Store the full innerHTML as the original content
|
|
10012
10053
|
_this._originalOptionContents.set(value, option.innerHTML);
|
|
10013
10054
|
}
|
|
10014
10055
|
});
|
|
10015
10056
|
}, 0);
|
|
10016
10057
|
};
|
|
10058
|
+
/**
|
|
10059
|
+
* Restores the innerHTML of all options from the cache if they have been modified.
|
|
10060
|
+
* This is typically called before applying new filters/highlights.
|
|
10061
|
+
*/
|
|
10062
|
+
KTSelectSearch.prototype._restoreOptionContentsBeforeFilter = function () {
|
|
10063
|
+
var _this = this;
|
|
10064
|
+
var options = Array.from(this._select.getOptionsElement());
|
|
10065
|
+
options.forEach(function (option) {
|
|
10066
|
+
var value = option.getAttribute('data-value');
|
|
10067
|
+
if (value && _this._originalOptionContents.has(value)) {
|
|
10068
|
+
var originalContent = _this._originalOptionContents.get(value);
|
|
10069
|
+
// Only restore if current content is different, to avoid unnecessary DOM manipulation
|
|
10070
|
+
if (option.innerHTML !== originalContent) {
|
|
10071
|
+
option.innerHTML = originalContent;
|
|
10072
|
+
}
|
|
10073
|
+
}
|
|
10074
|
+
});
|
|
10075
|
+
};
|
|
10017
10076
|
KTSelectSearch.prototype._handleSearchInput = function (event) {
|
|
10018
|
-
var query = event.target.value
|
|
10077
|
+
var query = event.target.value;
|
|
10019
10078
|
var config = this._select.getConfig();
|
|
10020
10079
|
// Reset focused option when search changes
|
|
10021
10080
|
this._focusManager.resetFocus();
|
|
10022
|
-
//
|
|
10081
|
+
// Restore original content for all options before filtering/highlighting again
|
|
10082
|
+
this._restoreOptionContentsBeforeFilter();
|
|
10023
10083
|
if (query.trim() === '') {
|
|
10024
|
-
this.
|
|
10084
|
+
this._resetAllOptions();
|
|
10085
|
+
this._focusManager.focusFirst(); // Focus first option when search is cleared
|
|
10086
|
+
return;
|
|
10025
10087
|
}
|
|
10026
|
-
// For remote search,
|
|
10027
|
-
//
|
|
10088
|
+
// For remote search, KTSelect component handles it.
|
|
10089
|
+
// KTSelect will call refreshAfterSearch on this module when remote data is updated.
|
|
10028
10090
|
if (config.remote && config.searchParam) {
|
|
10029
|
-
// If query is too short, reset all options to visible state
|
|
10030
10091
|
if (query.length < config.searchMinLength) {
|
|
10031
10092
|
this._resetAllOptions();
|
|
10032
10093
|
this._clearNoResultsMessage();
|
|
10094
|
+
this._focusManager.focusFirst(); // Focus first if query too short
|
|
10033
10095
|
}
|
|
10034
|
-
// Otherwise, let KTSelect handle remote search
|
|
10035
10096
|
return;
|
|
10036
10097
|
}
|
|
10037
10098
|
// For local search
|
|
10038
10099
|
if (query.length >= config.searchMinLength) {
|
|
10039
10100
|
this._filterOptions(query);
|
|
10101
|
+
this._focusManager.focusFirst(); // Focus first visible option after local filtering
|
|
10040
10102
|
}
|
|
10041
10103
|
else {
|
|
10042
10104
|
this._resetAllOptions();
|
|
10043
10105
|
this._clearNoResultsMessage();
|
|
10106
|
+
this._focusManager.focusFirst(); // Focus first if query too short and not remote
|
|
10044
10107
|
}
|
|
10045
10108
|
};
|
|
10046
10109
|
KTSelectSearch.prototype._filterOptions = function (query) {
|
|
@@ -10052,20 +10115,11 @@ var KTSelectSearch = /** @class */ (function () {
|
|
|
10052
10115
|
if (this._originalOptionContents.size === 0) {
|
|
10053
10116
|
this._cacheOriginalOptionContents();
|
|
10054
10117
|
}
|
|
10055
|
-
//
|
|
10056
|
-
|
|
10057
|
-
|
|
10118
|
+
// Restore original content before filtering, so highlighting is applied fresh.
|
|
10119
|
+
this._restoreOptionContentsBeforeFilter();
|
|
10120
|
+
var visibleCount = (0, utils_1.filterOptions)(options, query, config, dropdownElement, function (count) {
|
|
10121
|
+
return _this._handleNoResults(count);
|
|
10058
10122
|
});
|
|
10059
|
-
// Apply specialized text highlighting if needed
|
|
10060
|
-
if (config.searchHighlight && query.trim() !== '') {
|
|
10061
|
-
this._applyHighlightToDisplay(query);
|
|
10062
|
-
}
|
|
10063
|
-
};
|
|
10064
|
-
/**
|
|
10065
|
-
* Apply highlighting to the display element for multi-select
|
|
10066
|
-
*/
|
|
10067
|
-
KTSelectSearch.prototype._applyHighlightToDisplay = function (query) {
|
|
10068
|
-
// Implementation for display highlighting
|
|
10069
10123
|
};
|
|
10070
10124
|
/**
|
|
10071
10125
|
* Reset all options to their original state
|
|
@@ -10074,34 +10128,29 @@ var KTSelectSearch = /** @class */ (function () {
|
|
|
10074
10128
|
var _this = this;
|
|
10075
10129
|
// Show all options
|
|
10076
10130
|
var options = Array.from(this._select.getOptionsElement());
|
|
10077
|
-
//
|
|
10131
|
+
// Ensure the cache is populated if it's somehow empty here
|
|
10078
10132
|
if (this._originalOptionContents.size === 0) {
|
|
10079
10133
|
this._cacheOriginalOptionContents();
|
|
10080
10134
|
}
|
|
10081
10135
|
options.forEach(function (option) {
|
|
10082
|
-
// Remove the hidden class
|
|
10083
10136
|
option.classList.remove('hidden');
|
|
10137
|
+
if (option.style.display === 'none')
|
|
10138
|
+
option.style.display = ''; // Ensure visible
|
|
10084
10139
|
// Restore original HTML content (remove highlights)
|
|
10085
10140
|
var value = option.getAttribute('data-value');
|
|
10086
10141
|
if (value && _this._originalOptionContents.has(value)) {
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
option.getAttribute('style').includes('display:')) {
|
|
10092
|
-
var styleAttr = option.getAttribute('style');
|
|
10093
|
-
if (styleAttr.trim() === 'display: none;' ||
|
|
10094
|
-
styleAttr.trim() === 'display: block;') {
|
|
10095
|
-
option.removeAttribute('style');
|
|
10096
|
-
}
|
|
10097
|
-
else {
|
|
10098
|
-
option.setAttribute('style', styleAttr.replace(/display:\s*[^;]+;?/gi, '').trim());
|
|
10142
|
+
var originalContent = _this._originalOptionContents.get(value);
|
|
10143
|
+
// Only update if different, to minimize DOM changes
|
|
10144
|
+
if (option.innerHTML !== originalContent) {
|
|
10145
|
+
option.innerHTML = originalContent;
|
|
10099
10146
|
}
|
|
10100
10147
|
}
|
|
10101
10148
|
});
|
|
10149
|
+
this._clearNoResultsMessage(); // Ensure no results message is cleared when resetting
|
|
10102
10150
|
};
|
|
10103
10151
|
KTSelectSearch.prototype._handleNoResults = function (visibleOptionsCount) {
|
|
10104
|
-
|
|
10152
|
+
var _a, _b;
|
|
10153
|
+
if (visibleOptionsCount === 0 && ((_b = (_a = this._searchInput) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.trim()) !== '') {
|
|
10105
10154
|
this._showNoResultsMessage();
|
|
10106
10155
|
}
|
|
10107
10156
|
else {
|
|
@@ -10131,28 +10180,22 @@ var KTSelectSearch = /** @class */ (function () {
|
|
|
10131
10180
|
* Public method to explicitly clear all search highlights
|
|
10132
10181
|
* This is called when search is reset or selection changes
|
|
10133
10182
|
*/
|
|
10134
|
-
KTSelectSearch.prototype.
|
|
10183
|
+
KTSelectSearch.prototype.clearSearch = function () {
|
|
10135
10184
|
var _this = this;
|
|
10136
10185
|
// Restore original option content (removes highlighting)
|
|
10137
|
-
var
|
|
10138
|
-
|
|
10186
|
+
var optionsToClear = Array.from(this._select.getOptionsElement());
|
|
10187
|
+
// Ensure cache is available
|
|
10188
|
+
if (this._originalOptionContents.size === 0 && optionsToClear.length > 0) {
|
|
10189
|
+
this._cacheOriginalOptionContents();
|
|
10190
|
+
}
|
|
10191
|
+
optionsToClear.forEach(function (option) {
|
|
10139
10192
|
var value = option.getAttribute('data-value');
|
|
10140
10193
|
if (value && _this._originalOptionContents.has(value)) {
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
|
|
10146
|
-
};
|
|
10147
|
-
/**
|
|
10148
|
-
* Clear any highlights from the display element (selected values)
|
|
10149
|
-
*/
|
|
10150
|
-
KTSelectSearch.prototype._clearDisplayHighlights = function () {
|
|
10151
|
-
// Implementation for clearing display highlights
|
|
10152
|
-
var options = Array.from(this._select.getOptionsElement());
|
|
10153
|
-
options.forEach(function (option) {
|
|
10154
|
-
if (option.dataset && !option.dataset.originalText) {
|
|
10155
|
-
option.dataset.originalText = option.innerHTML;
|
|
10194
|
+
var originalContent = _this._originalOptionContents.get(value);
|
|
10195
|
+
// Only restore if different
|
|
10196
|
+
if (option.innerHTML !== originalContent) {
|
|
10197
|
+
option.innerHTML = originalContent;
|
|
10198
|
+
}
|
|
10156
10199
|
}
|
|
10157
10200
|
});
|
|
10158
10201
|
};
|
|
@@ -10163,14 +10206,23 @@ var KTSelectSearch = /** @class */ (function () {
|
|
|
10163
10206
|
var _this = this;
|
|
10164
10207
|
// Re-cache all option contents
|
|
10165
10208
|
this._originalOptionContents.clear();
|
|
10166
|
-
var
|
|
10167
|
-
|
|
10209
|
+
var currentOptions = Array.from(this._select.getOptionsElement());
|
|
10210
|
+
currentOptions.forEach(function (option) {
|
|
10168
10211
|
var value = option.getAttribute('data-value');
|
|
10169
10212
|
if (value) {
|
|
10170
10213
|
_this._originalOptionContents.set(value, option.innerHTML);
|
|
10171
10214
|
}
|
|
10172
10215
|
});
|
|
10173
10216
|
};
|
|
10217
|
+
/**
|
|
10218
|
+
* Called after search (local or remote via KTSelect) to reset focus.
|
|
10219
|
+
*/
|
|
10220
|
+
KTSelectSearch.prototype.refreshAfterSearch = function () {
|
|
10221
|
+
this._focusManager.resetFocus();
|
|
10222
|
+
this._focusManager.focusFirst();
|
|
10223
|
+
// Re-cache original contents as options might have changed (especially after remote search)
|
|
10224
|
+
this.refreshOptionCache();
|
|
10225
|
+
};
|
|
10174
10226
|
/**
|
|
10175
10227
|
* Clean up all resources used by the search module
|
|
10176
10228
|
*/
|
|
@@ -10178,12 +10230,13 @@ var KTSelectSearch = /** @class */ (function () {
|
|
|
10178
10230
|
// Remove all event listeners
|
|
10179
10231
|
this._removeEventListeners();
|
|
10180
10232
|
// Clear all references
|
|
10181
|
-
this._focusManager
|
|
10182
|
-
|
|
10233
|
+
if (this._focusManager) {
|
|
10234
|
+
this._focusManager.dispose();
|
|
10235
|
+
}
|
|
10183
10236
|
// Clear cached content
|
|
10184
10237
|
this._originalOptionContents.clear();
|
|
10185
10238
|
// Clear highlight elements
|
|
10186
|
-
this.
|
|
10239
|
+
this.clearSearch();
|
|
10187
10240
|
};
|
|
10188
10241
|
return KTSelectSearch;
|
|
10189
10242
|
}());
|
|
@@ -11399,15 +11452,16 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11399
11452
|
var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
|
|
11400
11453
|
if (!optionsContainer)
|
|
11401
11454
|
return;
|
|
11455
|
+
// Clear previous messages
|
|
11456
|
+
optionsContainer.innerHTML = '';
|
|
11402
11457
|
switch (type) {
|
|
11403
11458
|
case 'error':
|
|
11404
|
-
optionsContainer.
|
|
11459
|
+
optionsContainer.appendChild(templates_1.defaultTemplates.error(__assign(__assign({}, this._config), { errorMessage: message })));
|
|
11405
11460
|
break;
|
|
11406
11461
|
case 'loading':
|
|
11407
|
-
optionsContainer.
|
|
11462
|
+
optionsContainer.appendChild(templates_1.defaultTemplates.loading(this._config, message || 'Loading...'));
|
|
11408
11463
|
break;
|
|
11409
11464
|
case 'empty':
|
|
11410
|
-
optionsContainer.innerHTML = '';
|
|
11411
11465
|
optionsContainer.appendChild(templates_1.defaultTemplates.empty(this._config));
|
|
11412
11466
|
break;
|
|
11413
11467
|
}
|
|
@@ -11579,7 +11633,7 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11579
11633
|
// Initialize focus manager after dropdown element is created
|
|
11580
11634
|
this._focusManager = new utils_1.FocusManager(this._dropdownContentElement, '[data-kt-select-option]', this._config);
|
|
11581
11635
|
// Initialize dropdown module after all elements are created
|
|
11582
|
-
this._dropdownModule = new dropdown_1.KTSelectDropdown(this._wrapperElement, this._displayElement, this._dropdownContentElement, this._config);
|
|
11636
|
+
this._dropdownModule = new dropdown_1.KTSelectDropdown(this._wrapperElement, this._displayElement, this._dropdownContentElement, this._config, this);
|
|
11583
11637
|
// Update display and set ARIA attributes
|
|
11584
11638
|
this._updateDisplayAndAriaAttributes();
|
|
11585
11639
|
this.updateSelectedOptionDisplay();
|
|
@@ -11587,12 +11641,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11587
11641
|
// Attach event listeners after all modules are initialized
|
|
11588
11642
|
this._attachEventListeners();
|
|
11589
11643
|
};
|
|
11590
|
-
/**
|
|
11591
|
-
* Initialize options HTML from data
|
|
11592
|
-
*/
|
|
11593
|
-
// private _initializeOptionsHtml() {
|
|
11594
|
-
// this._generateOptionsHtml(this._element);
|
|
11595
|
-
// }
|
|
11596
11644
|
/**
|
|
11597
11645
|
* Creates the HTML structure for the select component
|
|
11598
11646
|
*/
|
|
@@ -11662,7 +11710,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11662
11710
|
if (!this._searchInputElement) {
|
|
11663
11711
|
this._searchInputElement = this._displayElement;
|
|
11664
11712
|
}
|
|
11665
|
-
this._valueDisplayElement = this._wrapperElement.querySelector("[data-kt-select-value]");
|
|
11666
11713
|
this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
|
|
11667
11714
|
};
|
|
11668
11715
|
/**
|
|
@@ -11673,16 +11720,10 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11673
11720
|
document.addEventListener('click', this._handleDocumentClick.bind(this));
|
|
11674
11721
|
// Dropdown option click events
|
|
11675
11722
|
this._eventManager.addListener(this._dropdownContentElement, 'click', this._handleDropdownOptionClick.bind(this));
|
|
11676
|
-
//
|
|
11677
|
-
//
|
|
11678
|
-
|
|
11679
|
-
|
|
11680
|
-
// this._handleDropdownClick.bind(this),
|
|
11681
|
-
// );
|
|
11682
|
-
// Attach centralized keyboard handler
|
|
11683
|
-
var keyboardTarget = this._searchInputElement || this._wrapperElement;
|
|
11684
|
-
if (keyboardTarget) {
|
|
11685
|
-
keyboardTarget.addEventListener('keydown', this._handleKeyboardEvent.bind(this));
|
|
11723
|
+
// Attach centralized keyboard handler to the wrapper element.
|
|
11724
|
+
// Events from focusable children like _displayElement or _searchInputElement (if present) will bubble up.
|
|
11725
|
+
if (this._wrapperElement) {
|
|
11726
|
+
this._wrapperElement.addEventListener('keydown', this._handleKeyboardEvent.bind(this));
|
|
11686
11727
|
}
|
|
11687
11728
|
};
|
|
11688
11729
|
/**
|
|
@@ -11825,37 +11866,10 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11825
11866
|
* DROPDOWN MANAGEMENT
|
|
11826
11867
|
* ========================================================================
|
|
11827
11868
|
*/
|
|
11828
|
-
/**
|
|
11829
|
-
* Toggle dropdown visibility
|
|
11830
|
-
* @deprecated
|
|
11831
|
-
*/
|
|
11832
|
-
KTSelect.prototype.toggleDropdown = function () {
|
|
11833
|
-
if (this._config.disabled) {
|
|
11834
|
-
if (this._config.debug)
|
|
11835
|
-
console.log('toggleDropdown: select is disabled, not opening');
|
|
11836
|
-
return;
|
|
11837
|
-
}
|
|
11838
|
-
if (this._config.debug)
|
|
11839
|
-
console.log('toggleDropdown called');
|
|
11840
|
-
if (this._dropdownModule) {
|
|
11841
|
-
// Always use the dropdown module's state to determine whether to open or close
|
|
11842
|
-
if (this._dropdownModule.isOpen()) {
|
|
11843
|
-
if (this._config.debug)
|
|
11844
|
-
console.log('Dropdown is open, closing...');
|
|
11845
|
-
this.closeDropdown();
|
|
11846
|
-
}
|
|
11847
|
-
else {
|
|
11848
|
-
if (this._config.debug)
|
|
11849
|
-
console.log('Dropdown is closed, opening...');
|
|
11850
|
-
this.openDropdown();
|
|
11851
|
-
}
|
|
11852
|
-
}
|
|
11853
|
-
};
|
|
11854
11869
|
/**
|
|
11855
11870
|
* Open the dropdown
|
|
11856
11871
|
*/
|
|
11857
11872
|
KTSelect.prototype.openDropdown = function () {
|
|
11858
|
-
var _this = this;
|
|
11859
11873
|
if (this._config.disabled) {
|
|
11860
11874
|
if (this._config.debug)
|
|
11861
11875
|
console.log('openDropdown: select is disabled, not opening');
|
|
@@ -11883,14 +11897,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11883
11897
|
// Dispatch custom event
|
|
11884
11898
|
this._dispatchEvent('show');
|
|
11885
11899
|
this._fireEvent('show');
|
|
11886
|
-
// Focus search input if configured and exists
|
|
11887
|
-
if (this._config.enableSearch &&
|
|
11888
|
-
this._config.searchAutofocus &&
|
|
11889
|
-
this._searchInputElement) {
|
|
11890
|
-
setTimeout(function () {
|
|
11891
|
-
_this._searchInputElement.focus();
|
|
11892
|
-
}, 50);
|
|
11893
|
-
}
|
|
11894
11900
|
// Update ARIA states
|
|
11895
11901
|
this._setAriaAttributes();
|
|
11896
11902
|
// Focus the first selected option or first option if nothing selected
|
|
@@ -11911,14 +11917,14 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11911
11917
|
// Always close by delegating to the dropdown module, which is the source of truth
|
|
11912
11918
|
if (this._config.debug)
|
|
11913
11919
|
console.log('Closing dropdown via dropdownModule...');
|
|
11914
|
-
// Clear search input
|
|
11920
|
+
// Clear search input if the dropdown is closing
|
|
11915
11921
|
if (this._searchModule && this._searchInputElement) {
|
|
11916
11922
|
// Clear search input if configured to do so
|
|
11917
11923
|
if (this._config.clearSearchOnClose) {
|
|
11918
11924
|
this._searchInputElement.value = '';
|
|
11919
11925
|
}
|
|
11920
|
-
//
|
|
11921
|
-
this._searchModule.
|
|
11926
|
+
// Clear search input when dropdown closes
|
|
11927
|
+
this._searchModule.clearSearch();
|
|
11922
11928
|
}
|
|
11923
11929
|
// Set our internal flag to match what we're doing
|
|
11924
11930
|
this._dropdownIsOpen = false;
|
|
@@ -11952,10 +11958,13 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11952
11958
|
var selectedOptions = this.getSelectedOptions();
|
|
11953
11959
|
if (selectedOptions.length === 0)
|
|
11954
11960
|
return;
|
|
11955
|
-
//
|
|
11956
|
-
var
|
|
11957
|
-
|
|
11958
|
-
|
|
11961
|
+
// Iterate through selected options and focus the first one that is visible
|
|
11962
|
+
for (var _i = 0, selectedOptions_1 = selectedOptions; _i < selectedOptions_1.length; _i++) {
|
|
11963
|
+
var value = selectedOptions_1[_i];
|
|
11964
|
+
if (this._focusManager && this._focusManager.focusOptionByValue(value)) {
|
|
11965
|
+
break; // Stop after focusing the first found selected and visible option
|
|
11966
|
+
}
|
|
11967
|
+
}
|
|
11959
11968
|
};
|
|
11960
11969
|
/**
|
|
11961
11970
|
* ========================================================================
|
|
@@ -12018,38 +12027,90 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12018
12027
|
*/
|
|
12019
12028
|
KTSelect.prototype.updateSelectedOptionDisplay = function () {
|
|
12020
12029
|
var selectedOptions = this.getSelectedOptions();
|
|
12021
|
-
|
|
12022
|
-
|
|
12030
|
+
var tagsEnabled = this._config.tags && this._tagsModule;
|
|
12031
|
+
var valueDisplayEl = this.getValueDisplayElement();
|
|
12032
|
+
if (tagsEnabled) {
|
|
12033
|
+
// Tags module will render tags if selectedOptions > 0, or clear them if selectedOptions === 0.
|
|
12023
12034
|
this._tagsModule.updateTagsDisplay(selectedOptions);
|
|
12024
|
-
return;
|
|
12025
12035
|
}
|
|
12036
|
+
// Guard against valueDisplayEl being null due to template modifications
|
|
12037
|
+
if (!valueDisplayEl) {
|
|
12038
|
+
if (this._config.debug) {
|
|
12039
|
+
console.warn('KTSelect: Value display element is null. Cannot update display or placeholder. Check template for [data-kt-select-value].');
|
|
12040
|
+
}
|
|
12041
|
+
return; // Nothing to display on if the element is missing
|
|
12042
|
+
}
|
|
12043
|
+
// 1. Custom render function takes highest precedence
|
|
12026
12044
|
if (typeof this._config.renderSelected === 'function') {
|
|
12027
|
-
|
|
12028
|
-
|
|
12045
|
+
valueDisplayEl.innerHTML = this._config.renderSelected(selectedOptions);
|
|
12046
|
+
return;
|
|
12047
|
+
}
|
|
12048
|
+
// 2. Custom displayTemplate string
|
|
12049
|
+
// Check if a custom display template string is provided directly in config or via config.templates
|
|
12050
|
+
var customDisplayTemplateString = this._config.displayTemplate || (this._config.templates && this._config.templates.display);
|
|
12051
|
+
if (customDisplayTemplateString) {
|
|
12052
|
+
// If tags are enabled and items are selected, the tags module handles display, so clear the main display area.
|
|
12053
|
+
if (tagsEnabled && selectedOptions.length > 0) {
|
|
12054
|
+
valueDisplayEl.innerHTML = '';
|
|
12055
|
+
}
|
|
12056
|
+
else {
|
|
12057
|
+
// Otherwise, render the custom display template.
|
|
12058
|
+
// If no options are selected, renderDisplayTemplateForSelected should handle showing a placeholder if the template supports it,
|
|
12059
|
+
// or we might need a separate placeholder rendering for custom templates if they don't handle empty selection.
|
|
12060
|
+
// For now, assume renderDisplayTemplateForSelected handles it or shows selected text.
|
|
12061
|
+
valueDisplayEl.innerHTML = this.renderDisplayTemplateForSelected(selectedOptions);
|
|
12062
|
+
}
|
|
12063
|
+
return;
|
|
12064
|
+
}
|
|
12065
|
+
// 3. Default template behavior (no custom function or string template)
|
|
12066
|
+
var textContainer = valueDisplayEl.querySelector('[data-kt-text-container="true"]');
|
|
12067
|
+
if (tagsEnabled && selectedOptions.length > 0) {
|
|
12068
|
+
// Tags are active and have content, clear the text container if it exists,
|
|
12069
|
+
// or the whole display if it doesn't (though it should with default template).
|
|
12070
|
+
if (textContainer) {
|
|
12071
|
+
textContainer.innerHTML = '';
|
|
12072
|
+
}
|
|
12073
|
+
else {
|
|
12074
|
+
valueDisplayEl.innerHTML = ''; // Fallback: clear entire display area
|
|
12075
|
+
}
|
|
12076
|
+
}
|
|
12077
|
+
else if (selectedOptions.length === 0) {
|
|
12078
|
+
// No options selected: display placeholder text in the text container.
|
|
12079
|
+
var placeholderTemplate = templates_1.defaultTemplates.placeholder(this._config);
|
|
12080
|
+
var placeholderText = placeholderTemplate.textContent || ''; // Get text from placeholder element
|
|
12081
|
+
if (textContainer) {
|
|
12082
|
+
textContainer.innerHTML = placeholderText;
|
|
12083
|
+
}
|
|
12084
|
+
else {
|
|
12085
|
+
// Fallback: If no text container, replace children of valueDisplayEl with the placeholder element itself.
|
|
12086
|
+
// This ensures the placeholder (which might have its own structure/classes) is displayed.
|
|
12087
|
+
valueDisplayEl.replaceChildren(placeholderTemplate);
|
|
12088
|
+
}
|
|
12029
12089
|
}
|
|
12030
12090
|
else {
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12091
|
+
// Options are selected, and tags are not enabled (or no selected options for tags):
|
|
12092
|
+
// Render normal selected text in the text container.
|
|
12093
|
+
var content = this.getSelectedOptionsText();
|
|
12094
|
+
if (textContainer) {
|
|
12095
|
+
textContainer.innerHTML = content;
|
|
12034
12096
|
}
|
|
12035
12097
|
else {
|
|
12036
|
-
|
|
12037
|
-
if (this._config.displayTemplate) {
|
|
12038
|
-
var selectedValues = this.getSelectedOptions();
|
|
12039
|
-
content = this.renderDisplayTemplateForSelected(selectedValues);
|
|
12040
|
-
}
|
|
12041
|
-
else {
|
|
12042
|
-
// If no displayTemplate is provided, use the default comma-separated list of selected options
|
|
12043
|
-
content = this.getSelectedOptionsText();
|
|
12044
|
-
}
|
|
12045
|
-
this._valueDisplayElement.innerHTML = content;
|
|
12098
|
+
valueDisplayEl.innerHTML = content; // Fallback: set content on whole display area
|
|
12046
12099
|
}
|
|
12047
12100
|
}
|
|
12048
12101
|
};
|
|
12102
|
+
/**
|
|
12103
|
+
* Check if an option was originally disabled in the HTML
|
|
12104
|
+
*/
|
|
12105
|
+
KTSelect.prototype._isOptionOriginallyDisabled = function (value) {
|
|
12106
|
+
var originalOption = Array.from(this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
|
|
12107
|
+
return originalOption ? originalOption.disabled : false;
|
|
12108
|
+
};
|
|
12049
12109
|
/**
|
|
12050
12110
|
* Update CSS classes for selected options
|
|
12051
12111
|
*/
|
|
12052
12112
|
KTSelect.prototype._updateSelectedOptionClass = function () {
|
|
12113
|
+
var _this = this;
|
|
12053
12114
|
var allOptions = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
|
|
12054
12115
|
var selectedValues = this._state.getSelectedOptions();
|
|
12055
12116
|
var maxReached = typeof this._config.maxSelections === 'number' &&
|
|
@@ -12061,9 +12122,11 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12061
12122
|
if (!optionValue)
|
|
12062
12123
|
return;
|
|
12063
12124
|
var isSelected = selectedValues.includes(optionValue);
|
|
12125
|
+
var isOriginallyDisabled = _this._isOptionOriginallyDisabled(optionValue);
|
|
12064
12126
|
if (isSelected) {
|
|
12065
12127
|
option.classList.add('selected');
|
|
12066
12128
|
option.setAttribute('aria-selected', 'true');
|
|
12129
|
+
// Selected options should not be visually hidden or disabled by maxSelections logic
|
|
12067
12130
|
option.classList.remove('hidden');
|
|
12068
12131
|
option.classList.remove('disabled');
|
|
12069
12132
|
option.removeAttribute('aria-disabled');
|
|
@@ -12071,7 +12134,8 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12071
12134
|
else {
|
|
12072
12135
|
option.classList.remove('selected');
|
|
12073
12136
|
option.setAttribute('aria-selected', 'false');
|
|
12074
|
-
if
|
|
12137
|
+
// An option should be disabled if it was originally disabled OR if maxSelections is reached
|
|
12138
|
+
if (isOriginallyDisabled || maxReached) {
|
|
12075
12139
|
option.classList.add('disabled');
|
|
12076
12140
|
option.setAttribute('aria-disabled', 'true');
|
|
12077
12141
|
}
|
|
@@ -12131,17 +12195,6 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12131
12195
|
* EVENT HANDLERS
|
|
12132
12196
|
* ========================================================================
|
|
12133
12197
|
*/
|
|
12134
|
-
/**
|
|
12135
|
-
* Handle display element click
|
|
12136
|
-
* @deprecated
|
|
12137
|
-
*/
|
|
12138
|
-
KTSelect.prototype._handleDropdownClick = function (event) {
|
|
12139
|
-
if (this._config.debug)
|
|
12140
|
-
console.log('Display element clicked', event.target);
|
|
12141
|
-
event.preventDefault();
|
|
12142
|
-
event.stopPropagation(); // Prevent event bubbling
|
|
12143
|
-
this.toggleDropdown();
|
|
12144
|
-
};
|
|
12145
12198
|
/**
|
|
12146
12199
|
* Handle click within the dropdown
|
|
12147
12200
|
*/
|
|
@@ -12182,6 +12235,13 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12182
12235
|
}
|
|
12183
12236
|
if (this._config.debug)
|
|
12184
12237
|
console.log('Option clicked:', optionValue);
|
|
12238
|
+
// If in single-select mode and the clicked option is already selected, just close the dropdown.
|
|
12239
|
+
if (!this._config.multiple && this._state.isSelected(optionValue)) {
|
|
12240
|
+
if (this._config.debug)
|
|
12241
|
+
console.log('Single select mode: clicked already selected option. Closing dropdown.');
|
|
12242
|
+
this.closeDropdown();
|
|
12243
|
+
return;
|
|
12244
|
+
}
|
|
12185
12245
|
// Use toggleSelection instead of _selectOption to prevent re-rendering
|
|
12186
12246
|
this.toggleSelection(optionValue);
|
|
12187
12247
|
};
|
|
@@ -12245,7 +12305,13 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12245
12305
|
* Get value display element
|
|
12246
12306
|
*/
|
|
12247
12307
|
KTSelect.prototype.getValueDisplayElement = function () {
|
|
12248
|
-
return this.
|
|
12308
|
+
return this._displayElement;
|
|
12309
|
+
};
|
|
12310
|
+
/**
|
|
12311
|
+
* Get wrapper element
|
|
12312
|
+
*/
|
|
12313
|
+
KTSelect.prototype.getWrapperElement = function () {
|
|
12314
|
+
return this._wrapperElement;
|
|
12249
12315
|
};
|
|
12250
12316
|
/**
|
|
12251
12317
|
* Show all options in the dropdown
|
|
@@ -12255,6 +12321,7 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12255
12321
|
var options = Array.from(this._wrapperElement.querySelectorAll("[data-kt-select-option]"));
|
|
12256
12322
|
// Show all options by removing the hidden class and any inline styles
|
|
12257
12323
|
options.forEach(function (option) {
|
|
12324
|
+
var _a;
|
|
12258
12325
|
// Remove hidden class
|
|
12259
12326
|
option.classList.remove('hidden');
|
|
12260
12327
|
// Clean up any existing inline styles for backward compatibility
|
|
@@ -12268,7 +12335,7 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12268
12335
|
}
|
|
12269
12336
|
else {
|
|
12270
12337
|
// Otherwise, remove just the display property
|
|
12271
|
-
option.setAttribute('style', styleAttr.replace(/display:\s*[^;]+;?/gi, '').trim());
|
|
12338
|
+
option.setAttribute('style', (_a = styleAttr === null || styleAttr === void 0 ? void 0 : styleAttr.replace(/display:\s*[^;]+;?/gi, '')) === null || _a === void 0 ? void 0 : _a.trim());
|
|
12272
12339
|
}
|
|
12273
12340
|
}
|
|
12274
12341
|
}
|
|
@@ -12278,7 +12345,7 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12278
12345
|
this._searchInputElement.value = '';
|
|
12279
12346
|
// If we have a search module, clear any search filtering
|
|
12280
12347
|
if (this._searchModule) {
|
|
12281
|
-
this._searchModule.
|
|
12348
|
+
this._searchModule.clearSearch();
|
|
12282
12349
|
}
|
|
12283
12350
|
}
|
|
12284
12351
|
};
|
|
@@ -12307,7 +12374,7 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12307
12374
|
// Get current selection state
|
|
12308
12375
|
var isSelected = this._state.isSelected(value);
|
|
12309
12376
|
if (this._config.debug)
|
|
12310
|
-
console.log("toggleSelection called for value: ".concat(value, ", isSelected: ").concat(isSelected, ", multiple: ").concat(this._config.multiple
|
|
12377
|
+
console.log("toggleSelection called for value: ".concat(value, ", isSelected: ").concat(isSelected, ", multiple: ").concat(this._config.multiple));
|
|
12311
12378
|
// If already selected in single select mode, do nothing (can't deselect in single select)
|
|
12312
12379
|
if (isSelected && !this._config.multiple) {
|
|
12313
12380
|
if (this._config.debug)
|
|
@@ -12316,9 +12383,9 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12316
12383
|
}
|
|
12317
12384
|
if (this._config.debug)
|
|
12318
12385
|
console.log("Toggling selection for option: ".concat(value, ", currently selected: ").concat(isSelected));
|
|
12319
|
-
// Ensure any search
|
|
12386
|
+
// Ensure any search input is cleared when selection changes
|
|
12320
12387
|
if (this._searchModule) {
|
|
12321
|
-
this._searchModule.
|
|
12388
|
+
this._searchModule.clearSearch();
|
|
12322
12389
|
}
|
|
12323
12390
|
// Toggle the selection in the state
|
|
12324
12391
|
this._state.toggleSelectedOptions(value);
|
|
@@ -12341,15 +12408,14 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12341
12408
|
// Update option classes without re-rendering the dropdown content
|
|
12342
12409
|
this._updateSelectedOptionClass();
|
|
12343
12410
|
// For single select mode, always close the dropdown after selection
|
|
12344
|
-
// For multiple select mode, only close if closeOnSelect is true
|
|
12345
12411
|
if (!this._config.multiple) {
|
|
12346
12412
|
if (this._config.debug)
|
|
12347
12413
|
console.log('About to call closeDropdown() for single select mode - always close after selection');
|
|
12348
12414
|
this.closeDropdown();
|
|
12349
12415
|
}
|
|
12350
|
-
else
|
|
12416
|
+
else {
|
|
12351
12417
|
if (this._config.debug)
|
|
12352
|
-
console.log('About to call closeDropdown() for multiple select
|
|
12418
|
+
console.log('About to call closeDropdown() for multiple select');
|
|
12353
12419
|
this.closeDropdown();
|
|
12354
12420
|
}
|
|
12355
12421
|
// Dispatch custom change event with additional data
|
|
@@ -12449,9 +12515,9 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12449
12515
|
.then(function () {
|
|
12450
12516
|
// Update options in the dropdown
|
|
12451
12517
|
_this._updateSearchResults(items);
|
|
12452
|
-
// Refresh the search module
|
|
12453
|
-
if (_this._searchModule
|
|
12454
|
-
_this._searchModule.
|
|
12518
|
+
// Refresh the search module to update focus and cache
|
|
12519
|
+
if (_this._searchModule) {
|
|
12520
|
+
_this._searchModule.refreshAfterSearch();
|
|
12455
12521
|
}
|
|
12456
12522
|
})
|
|
12457
12523
|
.catch(function (error) {
|
|
@@ -12548,19 +12614,47 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12548
12614
|
* Centralized keyboard event handler for all select modes
|
|
12549
12615
|
*/
|
|
12550
12616
|
KTSelect.prototype._handleKeyboardEvent = function (event) {
|
|
12617
|
+
// If the event target is the search input and the event was already handled (defaultPrevented),
|
|
12618
|
+
// then return early to avoid duplicate processing by this broader handler.
|
|
12619
|
+
if (event.target === this._searchInputElement && event.defaultPrevented) {
|
|
12620
|
+
return;
|
|
12621
|
+
}
|
|
12551
12622
|
var isOpen = this._dropdownIsOpen;
|
|
12552
12623
|
var config = this._config;
|
|
12553
12624
|
var focusManager = this._focusManager;
|
|
12554
12625
|
var buffer = this._typeToSearchBuffer;
|
|
12555
|
-
//
|
|
12626
|
+
// If the event target is the search input, let it handle most typing keys naturally.
|
|
12627
|
+
if (event.target === this._searchInputElement) {
|
|
12628
|
+
// Allow navigation keys like ArrowDown, ArrowUp, Escape, Enter (for search/selection) to be handled by the logic below.
|
|
12629
|
+
// For other keys (characters, space, backspace, delete), let the input field process them.
|
|
12630
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp' &&
|
|
12631
|
+
event.key !== 'Escape' && event.key !== 'Enter' && event.key !== 'Tab' &&
|
|
12632
|
+
event.key !== 'Home' && event.key !== 'End') {
|
|
12633
|
+
// If it's a character key and we are NOT type-to-searching (because search has focus)
|
|
12634
|
+
// then let the input field handle it for its own value.
|
|
12635
|
+
// The search module's 'input' event will handle filtering based on the input's value.
|
|
12636
|
+
buffer.clear(); // Clear type-to-search buffer when typing in search field
|
|
12637
|
+
return;
|
|
12638
|
+
}
|
|
12639
|
+
// For Enter specifically in search input, we might want to select the focused option or submit search.
|
|
12640
|
+
// This is handled later in the switch.
|
|
12641
|
+
}
|
|
12642
|
+
// Ignore modifier keys (except for specific combinations if added later)
|
|
12556
12643
|
if (event.altKey || event.ctrlKey || event.metaKey)
|
|
12557
12644
|
return;
|
|
12558
|
-
// Type-to-search: only for single char keys
|
|
12559
|
-
if (event.key.length === 1 && !event.repeat && !event.key.match(/\s/)) {
|
|
12645
|
+
// Type-to-search: only for single char keys, when search input does not have focus
|
|
12646
|
+
if (event.key.length === 1 && !event.repeat && !event.key.match(/\s/) && document.activeElement !== this._searchInputElement) {
|
|
12560
12647
|
buffer.push(event.key);
|
|
12561
12648
|
var str = buffer.getBuffer();
|
|
12562
|
-
|
|
12563
|
-
|
|
12649
|
+
if (isOpen) {
|
|
12650
|
+
focusManager.focusByString(str);
|
|
12651
|
+
}
|
|
12652
|
+
else {
|
|
12653
|
+
// If closed, type-to-search could potentially open and select.
|
|
12654
|
+
// For now, let's assume it only works when open or opens it first.
|
|
12655
|
+
// Or, we could find the matching option and set it directly without opening.
|
|
12656
|
+
}
|
|
12657
|
+
return; // Type-to-search handles the event
|
|
12564
12658
|
}
|
|
12565
12659
|
switch (event.key) {
|
|
12566
12660
|
case 'ArrowDown':
|
|
@@ -12594,18 +12688,28 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12594
12688
|
case 'Enter':
|
|
12595
12689
|
case ' ': // Space
|
|
12596
12690
|
if (isOpen) {
|
|
12597
|
-
var
|
|
12598
|
-
if (
|
|
12599
|
-
var
|
|
12600
|
-
|
|
12601
|
-
|
|
12602
|
-
if (
|
|
12603
|
-
|
|
12604
|
-
|
|
12691
|
+
var focusedOptionEl = this._focusManager.getFocusedOption();
|
|
12692
|
+
if (focusedOptionEl) {
|
|
12693
|
+
var val = focusedOptionEl.dataset.value;
|
|
12694
|
+
// If single select, and the item is already selected, just close.
|
|
12695
|
+
if (val !== undefined && !this._config.multiple && this._state.isSelected(val)) {
|
|
12696
|
+
if (this._config.debug)
|
|
12697
|
+
console.log('Enter on already selected item in single-select mode. Closing.');
|
|
12698
|
+
this.closeDropdown();
|
|
12699
|
+
event.preventDefault();
|
|
12700
|
+
break;
|
|
12605
12701
|
}
|
|
12606
12702
|
}
|
|
12607
|
-
//
|
|
12608
|
-
|
|
12703
|
+
// Proceed with selection if not handled above
|
|
12704
|
+
this.selectFocusedOption();
|
|
12705
|
+
// Close dropdown if configured to do so (for new selections)
|
|
12706
|
+
if (!this._config.multiple) {
|
|
12707
|
+
// This will also be true for the case handled above, but closeDropdown is idempotent.
|
|
12708
|
+
// However, the break above prevents this from being reached for that specific case.
|
|
12709
|
+
this.closeDropdown();
|
|
12710
|
+
}
|
|
12711
|
+
event.preventDefault(); // Prevent form submission or other default actions
|
|
12712
|
+
break;
|
|
12609
12713
|
}
|
|
12610
12714
|
else {
|
|
12611
12715
|
this.openDropdown();
|
|
@@ -12649,6 +12753,9 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12649
12753
|
}).filter(Boolean)));
|
|
12650
12754
|
return contentArray.join(displaySeparator);
|
|
12651
12755
|
};
|
|
12756
|
+
KTSelect.prototype.getDisplayElement = function () {
|
|
12757
|
+
return this._displayElement;
|
|
12758
|
+
};
|
|
12652
12759
|
/**
|
|
12653
12760
|
* ========================================================================
|
|
12654
12761
|
* STATIC METHODS
|
|
@@ -14564,32 +14671,6 @@ var KTSelectTags = /** @class */ (function () {
|
|
|
14564
14671
|
wrapper.insertBefore(tag, _this._valueDisplayElement);
|
|
14565
14672
|
});
|
|
14566
14673
|
};
|
|
14567
|
-
/**
|
|
14568
|
-
* Get the label/text for an option by its value
|
|
14569
|
-
*/
|
|
14570
|
-
KTSelectTags.prototype._getOptionLabel = function (optionValue) {
|
|
14571
|
-
var _a, _b;
|
|
14572
|
-
// First look for an option element in the dropdown with matching value
|
|
14573
|
-
var optionElements = this._select.getOptionsElement();
|
|
14574
|
-
for (var _i = 0, _c = Array.from(optionElements); _i < _c.length; _i++) {
|
|
14575
|
-
var option = _c[_i];
|
|
14576
|
-
if (option.dataset.value === optionValue) {
|
|
14577
|
-
return ((_a = option.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || optionValue;
|
|
14578
|
-
}
|
|
14579
|
-
}
|
|
14580
|
-
// If not found in dropdown, look in original select element
|
|
14581
|
-
var originalOptions = this._select
|
|
14582
|
-
.getElement()
|
|
14583
|
-
.querySelectorAll('option');
|
|
14584
|
-
for (var _d = 0, _e = Array.from(originalOptions); _d < _e.length; _d++) {
|
|
14585
|
-
var option = _e[_d];
|
|
14586
|
-
if (option.value === optionValue) {
|
|
14587
|
-
return ((_b = option.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || optionValue;
|
|
14588
|
-
}
|
|
14589
|
-
}
|
|
14590
|
-
// If still not found, return the value itself
|
|
14591
|
-
return optionValue;
|
|
14592
|
-
};
|
|
14593
14674
|
/**
|
|
14594
14675
|
* Remove a tag and its selection
|
|
14595
14676
|
*/
|
|
@@ -15451,30 +15532,6 @@ var KTDom = {
|
|
|
15451
15532
|
}
|
|
15452
15533
|
return attributes;
|
|
15453
15534
|
},
|
|
15454
|
-
getDataAttributesByJson: function (element, prefix) {
|
|
15455
|
-
if (!element) {
|
|
15456
|
-
return {};
|
|
15457
|
-
}
|
|
15458
|
-
var rawValue = element.dataset[prefix];
|
|
15459
|
-
if (!rawValue) {
|
|
15460
|
-
return {};
|
|
15461
|
-
}
|
|
15462
|
-
var parsedValue = utils_1.default.parseDataAttribute(rawValue);
|
|
15463
|
-
if (typeof parsedValue === 'string') {
|
|
15464
|
-
try {
|
|
15465
|
-
return JSON.parse(parsedValue);
|
|
15466
|
-
}
|
|
15467
|
-
catch (e) {
|
|
15468
|
-
console.error("Invalid JSON format for '".concat(prefix, "': ").concat(e instanceof Error ? e.message : e, " ").concat(rawValue));
|
|
15469
|
-
}
|
|
15470
|
-
}
|
|
15471
|
-
// If it's already an object, return as is
|
|
15472
|
-
if (typeof parsedValue === 'object' && parsedValue !== null) {
|
|
15473
|
-
return parsedValue;
|
|
15474
|
-
}
|
|
15475
|
-
// For other types (number, boolean, null), return an empty object
|
|
15476
|
-
return {};
|
|
15477
|
-
},
|
|
15478
15535
|
ready: function (callback) {
|
|
15479
15536
|
if (document.readyState === 'loading') {
|
|
15480
15537
|
document.addEventListener('DOMContentLoaded', function () {
|
|
@@ -15492,7 +15549,7 @@ exports["default"] = KTDom;
|
|
|
15492
15549
|
/***/ }),
|
|
15493
15550
|
|
|
15494
15551
|
/***/ 9011:
|
|
15495
|
-
/***/ (function(__unused_webpack_module, exports
|
|
15552
|
+
/***/ (function(__unused_webpack_module, exports) {
|
|
15496
15553
|
|
|
15497
15554
|
|
|
15498
15555
|
/**
|
|
@@ -15500,15 +15557,12 @@ exports["default"] = KTDom;
|
|
|
15500
15557
|
* Copyright 2025 by Keenthemes Inc
|
|
15501
15558
|
*/
|
|
15502
15559
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
15503
|
-
exports.TypeToSearchBuffer = exports.EventManager = exports.FocusManager =
|
|
15560
|
+
exports.TypeToSearchBuffer = exports.EventManager = exports.FocusManager = void 0;
|
|
15504
15561
|
exports.formatCurrency = formatCurrency;
|
|
15505
15562
|
exports.filterOptions = filterOptions;
|
|
15506
|
-
exports.highlightTextInElement = highlightTextInElement;
|
|
15507
15563
|
exports.debounce = debounce;
|
|
15508
15564
|
exports.renderTemplateString = renderTemplateString;
|
|
15509
15565
|
exports.stringToElement = stringToElement;
|
|
15510
|
-
// utils.ts
|
|
15511
|
-
var templates_1 = __webpack_require__(9069);
|
|
15512
15566
|
/**
|
|
15513
15567
|
* Format a number as a currency string
|
|
15514
15568
|
*/
|
|
@@ -15522,148 +15576,50 @@ function formatCurrency(value) {
|
|
|
15522
15576
|
* Filter options based on a search query
|
|
15523
15577
|
*/
|
|
15524
15578
|
function filterOptions(options, query, config, dropdownElement, onVisibleCount) {
|
|
15525
|
-
var _a;
|
|
15526
15579
|
var visibleOptionsCount = 0;
|
|
15527
|
-
//
|
|
15528
|
-
|
|
15529
|
-
if (noResultsElement) {
|
|
15530
|
-
noResultsElement.remove();
|
|
15531
|
-
}
|
|
15532
|
-
// For empty query, ensure highlights are cleared from all options
|
|
15580
|
+
// For empty query, make all options visible
|
|
15581
|
+
// The KTSelectSearch class is now responsible for restoring original content before calling this.
|
|
15533
15582
|
if (!query || query.trim() === '') {
|
|
15534
|
-
// Just make all options visible without highlighting
|
|
15535
15583
|
for (var _i = 0, options_1 = options; _i < options_1.length; _i++) {
|
|
15536
15584
|
var option = options_1[_i];
|
|
15537
|
-
// Make option visible by removing hidden classes and inline styles
|
|
15538
15585
|
option.classList.remove('hidden');
|
|
15539
|
-
//
|
|
15540
|
-
if (option.
|
|
15541
|
-
option.
|
|
15542
|
-
var styleAttr = option.getAttribute('style');
|
|
15543
|
-
if (styleAttr.trim() === 'display: none;' ||
|
|
15544
|
-
styleAttr.trim() === 'display: block;') {
|
|
15545
|
-
option.removeAttribute('style');
|
|
15546
|
-
}
|
|
15547
|
-
else {
|
|
15548
|
-
option.setAttribute('style', styleAttr.replace(/display:\s*[^;]+;?/gi, '').trim());
|
|
15549
|
-
}
|
|
15550
|
-
}
|
|
15551
|
-
// Clear highlights by restoring original text content
|
|
15552
|
-
if (option.dataset && option.dataset.originalText) {
|
|
15553
|
-
option.innerHTML = option.dataset.originalText;
|
|
15554
|
-
}
|
|
15555
|
-
else {
|
|
15556
|
-
option.innerHTML = option.textContent || '';
|
|
15557
|
-
}
|
|
15558
|
-
// Remove the cache if present
|
|
15559
|
-
if (option.dataset && option.dataset.originalText) {
|
|
15560
|
-
delete option.dataset.originalText;
|
|
15586
|
+
// Remove inline display style if it was used to hide
|
|
15587
|
+
if (option.style.display === 'none') {
|
|
15588
|
+
option.style.display = '';
|
|
15561
15589
|
}
|
|
15590
|
+
// At this point, option.innerHTML should be its original.
|
|
15562
15591
|
visibleOptionsCount++;
|
|
15563
15592
|
}
|
|
15564
|
-
// Call the callback with the visible count if provided
|
|
15565
15593
|
if (onVisibleCount) {
|
|
15566
15594
|
onVisibleCount(visibleOptionsCount);
|
|
15567
15595
|
}
|
|
15568
15596
|
return visibleOptionsCount;
|
|
15569
15597
|
}
|
|
15570
|
-
|
|
15571
|
-
for (var
|
|
15572
|
-
var option = options_2[
|
|
15573
|
-
|
|
15574
|
-
var
|
|
15575
|
-
|
|
15576
|
-
|
|
15577
|
-
if (isMatch || query.trim() === '') {
|
|
15578
|
-
// Show option by removing the hidden class and any display inline styles
|
|
15598
|
+
var queryLower = query.toLowerCase();
|
|
15599
|
+
for (var _a = 0, options_2 = options; _a < options_2.length; _a++) {
|
|
15600
|
+
var option = options_2[_a];
|
|
15601
|
+
// Use data-text for matching if available, otherwise fall back to textContent
|
|
15602
|
+
var optionText = (option.dataset.text || option.textContent || '').toLowerCase();
|
|
15603
|
+
var isMatch = optionText.includes(queryLower);
|
|
15604
|
+
if (isMatch) {
|
|
15579
15605
|
option.classList.remove('hidden');
|
|
15580
|
-
|
|
15581
|
-
|
|
15582
|
-
option.getAttribute('style').includes('display:')) {
|
|
15583
|
-
var styleAttr = option.getAttribute('style');
|
|
15584
|
-
if (styleAttr.trim() === 'display: none;' ||
|
|
15585
|
-
styleAttr.trim() === 'display: block;') {
|
|
15586
|
-
option.removeAttribute('style');
|
|
15587
|
-
}
|
|
15588
|
-
else {
|
|
15589
|
-
option.setAttribute('style', styleAttr.replace(/display:\s*[^;]+;?/gi, '').trim());
|
|
15590
|
-
}
|
|
15591
|
-
}
|
|
15606
|
+
if (option.style.display === 'none')
|
|
15607
|
+
option.style.display = ''; // Ensure visible
|
|
15592
15608
|
visibleOptionsCount++;
|
|
15593
|
-
if (config.searchHighlight && query.trim() !== '') {
|
|
15594
|
-
if (option.dataset && !option.dataset.originalText) {
|
|
15595
|
-
option.dataset.originalText = option.innerHTML;
|
|
15596
|
-
}
|
|
15597
|
-
(0, exports.highlightTextInElementDebounced)(option, query, config);
|
|
15598
|
-
}
|
|
15599
15609
|
}
|
|
15600
15610
|
else {
|
|
15601
|
-
// Hide option using hidden class
|
|
15602
15611
|
option.classList.add('hidden');
|
|
15603
|
-
// Remove any inline display styles
|
|
15604
|
-
if (option.hasAttribute('style') &&
|
|
15605
|
-
option.getAttribute('style').includes('display:')) {
|
|
15606
|
-
var styleAttr = option.getAttribute('style');
|
|
15607
|
-
if (styleAttr.trim() === 'display: none;' ||
|
|
15608
|
-
styleAttr.trim() === 'display: block;') {
|
|
15609
|
-
option.removeAttribute('style');
|
|
15610
|
-
}
|
|
15611
|
-
else {
|
|
15612
|
-
option.setAttribute('style', styleAttr.replace(/display:\s*[^;]+;?/gi, '').trim());
|
|
15613
|
-
}
|
|
15614
|
-
}
|
|
15615
|
-
}
|
|
15616
|
-
// Early exit if maxItems limit is reached
|
|
15617
|
-
if (config.searchMaxItems && visibleOptionsCount >= config.searchMaxItems) {
|
|
15618
|
-
break;
|
|
15619
15612
|
}
|
|
15613
|
+
// Early exit if maxItems limit is reached (optional)
|
|
15614
|
+
// if (config.searchMaxItems && visibleOptionsCount >= config.searchMaxItems) {
|
|
15615
|
+
// break;
|
|
15616
|
+
// }
|
|
15620
15617
|
}
|
|
15621
|
-
// Call the callback with the visible count if provided
|
|
15622
15618
|
if (onVisibleCount) {
|
|
15623
15619
|
onVisibleCount(visibleOptionsCount);
|
|
15624
15620
|
}
|
|
15625
15621
|
return visibleOptionsCount;
|
|
15626
15622
|
}
|
|
15627
|
-
/**
|
|
15628
|
-
* Highlight text only within a specific element, preserving other elements
|
|
15629
|
-
*/
|
|
15630
|
-
function highlightTextInElement(element, query, config) {
|
|
15631
|
-
if (!element || !query || query.trim() === '')
|
|
15632
|
-
return;
|
|
15633
|
-
var queryLower = query.toLowerCase();
|
|
15634
|
-
var text = element.textContent || '';
|
|
15635
|
-
if (!text)
|
|
15636
|
-
return;
|
|
15637
|
-
// Escape regex special characters in query
|
|
15638
|
-
var escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
15639
|
-
var regex = new RegExp(escapedQuery, 'gi');
|
|
15640
|
-
// Replace all matches with the highlight template
|
|
15641
|
-
var lastIndex = 0;
|
|
15642
|
-
var result = '';
|
|
15643
|
-
var match;
|
|
15644
|
-
var matches = [];
|
|
15645
|
-
while ((match = regex.exec(text)) !== null) {
|
|
15646
|
-
matches.push({ start: match.index, end: regex.lastIndex });
|
|
15647
|
-
}
|
|
15648
|
-
if (matches.length === 0) {
|
|
15649
|
-
element.innerHTML = text;
|
|
15650
|
-
return;
|
|
15651
|
-
}
|
|
15652
|
-
for (var i = 0; i < matches.length; i++) {
|
|
15653
|
-
var _a = matches[i], start = _a.start, end = _a.end;
|
|
15654
|
-
// Add text before match
|
|
15655
|
-
result += text.slice(lastIndex, start);
|
|
15656
|
-
// Add highlighted match using template
|
|
15657
|
-
var highlighted = templates_1.defaultTemplates.highlight(config, text.slice(start, end)).outerHTML;
|
|
15658
|
-
result += highlighted;
|
|
15659
|
-
lastIndex = end;
|
|
15660
|
-
}
|
|
15661
|
-
// Add remaining text
|
|
15662
|
-
result += text.slice(lastIndex);
|
|
15663
|
-
element.innerHTML = result;
|
|
15664
|
-
}
|
|
15665
|
-
// Debounced version for performance
|
|
15666
|
-
exports.highlightTextInElementDebounced = debounce(highlightTextInElement, 100);
|
|
15667
15623
|
/**
|
|
15668
15624
|
* Focus manager for keyboard navigation
|
|
15669
15625
|
* Consolidates redundant focus management logic into shared functions
|
|
@@ -15765,6 +15721,7 @@ var FocusManager = /** @class */ (function () {
|
|
|
15765
15721
|
if (!option.classList.contains('disabled') &&
|
|
15766
15722
|
option.getAttribute('aria-disabled') !== 'true' &&
|
|
15767
15723
|
(((_b = option.textContent) === null || _b === void 0 ? void 0 : _b.toLowerCase().startsWith(lowerStr)) || ((_c = option.dataset.value) === null || _c === void 0 ? void 0 : _c.toLowerCase().startsWith(lowerStr)))) {
|
|
15724
|
+
this.resetFocus();
|
|
15768
15725
|
this._focusedOptionIndex = idx;
|
|
15769
15726
|
this.applyFocus(option);
|
|
15770
15727
|
this.scrollIntoView(option);
|
|
@@ -15823,12 +15780,14 @@ var FocusManager = /** @class */ (function () {
|
|
|
15823
15780
|
FocusManager.prototype.applyFocus = function (option) {
|
|
15824
15781
|
if (!option)
|
|
15825
15782
|
return;
|
|
15783
|
+
// Ensure it's not disabled
|
|
15826
15784
|
if (option.classList.contains('disabled') || option.getAttribute('aria-disabled') === 'true') {
|
|
15827
15785
|
return;
|
|
15828
15786
|
}
|
|
15829
|
-
|
|
15787
|
+
// DO NOT CALL resetFocus() here. Caller's responsibility.
|
|
15830
15788
|
option.classList.add(this._focusClass);
|
|
15831
15789
|
option.classList.add(this._hoverClass);
|
|
15790
|
+
// _triggerFocusChange needs _focusedOptionIndex to be set by the caller before this.
|
|
15832
15791
|
this._triggerFocusChange();
|
|
15833
15792
|
};
|
|
15834
15793
|
/**
|
|
@@ -15841,12 +15800,7 @@ var FocusManager = /** @class */ (function () {
|
|
|
15841
15800
|
focusedElements.forEach(function (element) {
|
|
15842
15801
|
element.classList.remove(_this._focusClass, _this._hoverClass);
|
|
15843
15802
|
});
|
|
15844
|
-
|
|
15845
|
-
var visibleOptions = this.getVisibleOptions();
|
|
15846
|
-
if (this._focusedOptionIndex !== null &&
|
|
15847
|
-
this._focusedOptionIndex >= visibleOptions.length) {
|
|
15848
|
-
this._focusedOptionIndex = null;
|
|
15849
|
-
}
|
|
15803
|
+
this._focusedOptionIndex = null; // Always reset the index
|
|
15850
15804
|
};
|
|
15851
15805
|
/**
|
|
15852
15806
|
* Ensure the focused option is visible in the scrollable container
|
|
@@ -15875,10 +15829,14 @@ var FocusManager = /** @class */ (function () {
|
|
|
15875
15829
|
var options = this.getVisibleOptions();
|
|
15876
15830
|
var index = options.findIndex(function (option) { return option.dataset.value === value; });
|
|
15877
15831
|
if (index >= 0) {
|
|
15878
|
-
|
|
15879
|
-
|
|
15880
|
-
|
|
15881
|
-
|
|
15832
|
+
var optionToFocus = options[index];
|
|
15833
|
+
if (!optionToFocus.classList.contains('disabled') && optionToFocus.getAttribute('aria-disabled') !== 'true') {
|
|
15834
|
+
this.resetFocus();
|
|
15835
|
+
this._focusedOptionIndex = index;
|
|
15836
|
+
this.applyFocus(optionToFocus);
|
|
15837
|
+
this.scrollIntoView(optionToFocus);
|
|
15838
|
+
return true;
|
|
15839
|
+
}
|
|
15882
15840
|
}
|
|
15883
15841
|
return false;
|
|
15884
15842
|
};
|
|
@@ -16095,20 +16053,19 @@ var utils_1 = __webpack_require__(9011);
|
|
|
16095
16053
|
* Users can override any template by providing a matching key in the config.templates object.
|
|
16096
16054
|
*/
|
|
16097
16055
|
exports.coreTemplateStrings = {
|
|
16098
|
-
dropdown: "<div data-kt-select-dropdown class=\"kt-select-dropdown hidden {{class}}\" style=\"z-index: {{zindex}};\"
|
|
16099
|
-
options: "<ul role=\"listbox\" aria-label=\"{{label}}\" class=\"kt-select-options {{class}}\" data-kt-select-options=\"true\"
|
|
16100
|
-
error: "<li class=\"kt-select-error\" role=\"alert\"
|
|
16101
|
-
highlight: "<span data-kt-select-highlight class=\"kt-select-highlight highlighted {{class}}\">{{text}}</span>",
|
|
16056
|
+
dropdown: "<div data-kt-select-dropdown class=\"kt-select-dropdown hidden {{class}}\" style=\"z-index: {{zindex}};\"></div>",
|
|
16057
|
+
options: "<ul role=\"listbox\" aria-label=\"{{label}}\" class=\"kt-select-options {{class}}\" data-kt-select-options=\"true\"></ul>",
|
|
16058
|
+
error: "<li class=\"kt-select-error\" role=\"alert\"></li>",
|
|
16102
16059
|
wrapper: "<div data-kt-select-wrapper class=\"kt-select-wrapper {{class}}\"></div>",
|
|
16103
|
-
combobox: "\n\t\t<div data-kt-select-combobox data-kt-select-display class=\"kt-select-combobox {{class}}\">\n\t\t\t<
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
option: "<li data-kt-select-option data-value=\"{{value}}\" data-text=\"{{text}}\" class=\"kt-select-option {{class}}\" role=\"option\" {{selected}} {{disabled}}>{{
|
|
16107
|
-
search: "<div data-kt-select-search class=\"kt-select-search {{class}}\"><input type=\"text\" data-kt-select-search=\"true\" placeholder=\"{{searchPlaceholder}}\" class=\"kt-input kt-
|
|
16108
|
-
empty: "<li data-kt-select-empty class=\"kt-select-no-result {{class}}\" role=\"status\"
|
|
16109
|
-
loading: "<li class=\"kt-select-loading {{class}}\" role=\"status\" aria-live=\"polite\"
|
|
16110
|
-
tag: "<div data-kt-select-tag=\"true\" class=\"kt-select-tag {{class}}\"
|
|
16111
|
-
loadMore: "<li class=\"kt-select-load-more {{class}}\" data-kt-select-load-more=\"true\"
|
|
16060
|
+
combobox: "\n\t\t<div data-kt-select-combobox data-kt-select-display class=\"kt-select-combobox {{class}}\">\n\t\t\t<div data-kt-select-combobox-values=\"true\" class=\"kt-select-combobox-values\"></div>\n\t\t\t<input class=\"kt-input kt-select-combobox-input\" data-kt-select-search=\"true\" type=\"text\" placeholder=\"{{placeholder}}\" role=\"searchbox\" aria-label=\"{{label}}\" {{disabled}} />\n\t\t\t<button type=\"button\" data-kt-select-clear-button=\"true\" class=\"kt-select-combobox-clear-btn\" aria-label=\"Clear selection\">\n\t\t\t\t<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t\t\t\t\t<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n\t\t\t\t\t<line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n\t\t\t\t</svg>\n\t\t\t</button>\n\t\t</div>\n\t",
|
|
16061
|
+
placeholder: "<div data-kt-select-placeholder class=\"kt-select-placeholder {{class}}\"></div>",
|
|
16062
|
+
display: "\n\t\t<div data-kt-select-display class=\"kt-select-display {{class}}\" tabindex=\"{{tabindex}}\" role=\"button\" data-selected=\"0\" aria-haspopup=\"listbox\" aria-expanded=\"false\" aria-label=\"{{label}}\" {{disabled}}>\n\t\t\t<div class=\"kt-select-option-text\" data-kt-text-container=\"true\">{{text}}</div>\n\t\t</div>\n\t",
|
|
16063
|
+
option: "\n\t\t<li data-kt-select-option data-value=\"{{value}}\" data-text=\"{{text}}\" class=\"kt-select-option {{class}}\" role=\"option\" {{selected}} {{disabled}}>\n\t\t\t<div class=\"kt-select-option-text\" data-kt-text-container=\"true\">{{text}}</div><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"size-3.5 ms-auto hidden text-primary kt-select-option-selected:block\"><path d=\"M20 6 9 17l-5-5\"/></svg>\n\t\t</li>\n\t",
|
|
16064
|
+
search: "<div data-kt-select-search class=\"kt-select-search {{class}}\"><input type=\"text\" data-kt-select-search=\"true\" placeholder=\"{{searchPlaceholder}}\" class=\"kt-input kt-input-ghost\" role=\"searchbox\" aria-label=\"{{searchPlaceholder}}\"/></div>",
|
|
16065
|
+
empty: "<li data-kt-select-empty class=\"kt-select-no-result {{class}}\" role=\"status\"></li>",
|
|
16066
|
+
loading: "<li class=\"kt-select-loading {{class}}\" role=\"status\" aria-live=\"polite\"></li>",
|
|
16067
|
+
tag: "<div data-kt-select-tag=\"true\" class=\"kt-select-tag {{class}}\"></div>",
|
|
16068
|
+
loadMore: "<li class=\"kt-select-load-more {{class}}\" data-kt-select-load-more=\"true\"></li>",
|
|
16112
16069
|
tagRemoveButton: "<button type=\"button\" data-kt-select-remove-button class=\"kt-select-tag-remove\" aria-label=\"Remove tag\" tabindex=\"0\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"3\" y1=\"3\" x2=\"9\" y2=\"9\"/><line x1=\"9\" y1=\"3\" x2=\"3\" y2=\"9\"/></svg></button>",
|
|
16113
16070
|
};
|
|
16114
16071
|
/**
|
|
@@ -16147,30 +16104,31 @@ function getTemplateStrings(config) {
|
|
|
16147
16104
|
* Default templates for KTSelect component
|
|
16148
16105
|
*/
|
|
16149
16106
|
exports.defaultTemplates = {
|
|
16150
|
-
/**
|
|
16151
|
-
* Renders a highlighted text
|
|
16152
|
-
*/
|
|
16153
|
-
highlight: function (config, text) {
|
|
16154
|
-
var template = getTemplateStrings(config).highlight;
|
|
16155
|
-
var html = template.replace('{{text}}', text).replace('{{class}}', config.highlightClass || '');
|
|
16156
|
-
return stringToElement(html);
|
|
16157
|
-
},
|
|
16158
16107
|
/**
|
|
16159
16108
|
* Renders the dropdown content
|
|
16160
16109
|
*/
|
|
16161
16110
|
dropdown: function (config) {
|
|
16111
|
+
var _a;
|
|
16162
16112
|
var template = getTemplateStrings(config).dropdown;
|
|
16163
|
-
|
|
16113
|
+
// If a custom dropdownTemplate is provided, it's responsible for its own content.
|
|
16114
|
+
// Otherwise, the base template is used, and content is appended later.
|
|
16164
16115
|
if (config.dropdownTemplate) {
|
|
16165
|
-
|
|
16116
|
+
var renderedCustomTemplate = (0, utils_1.renderTemplateString)(config.dropdownTemplate, {
|
|
16166
16117
|
zindex: config.zindex ? String(config.zindex) : '',
|
|
16167
|
-
content: config.content || '',
|
|
16118
|
+
// content: config.content || '', // No longer pass content to custom template directly here
|
|
16168
16119
|
class: config.dropdownClass || '',
|
|
16169
16120
|
});
|
|
16121
|
+
// The custom template IS the dropdown element
|
|
16122
|
+
var customDropdownEl = stringToElement(renderedCustomTemplate);
|
|
16123
|
+
if (config.zindex)
|
|
16124
|
+
customDropdownEl.style.zIndex = String(config.zindex);
|
|
16125
|
+
if (config.dropdownClass)
|
|
16126
|
+
(_a = customDropdownEl.classList).add.apply(_a, config.dropdownClass.split(' '));
|
|
16127
|
+
return customDropdownEl;
|
|
16170
16128
|
}
|
|
16171
16129
|
var html = template
|
|
16172
16130
|
.replace('{{zindex}}', config.zindex ? String(config.zindex) : '')
|
|
16173
|
-
.replace('{{content}}',
|
|
16131
|
+
// .replace('{{content}}', '') // Content is no longer part of the base template string
|
|
16174
16132
|
.replace('{{class}}', config.dropdownClass || '');
|
|
16175
16133
|
return stringToElement(html);
|
|
16176
16134
|
},
|
|
@@ -16182,7 +16140,7 @@ exports.defaultTemplates = {
|
|
|
16182
16140
|
var html = template
|
|
16183
16141
|
.replace('{{label}}', config.label || 'Options')
|
|
16184
16142
|
.replace('{{height}}', config.height ? String(config.height) : '250')
|
|
16185
|
-
.replace('{{options}}',
|
|
16143
|
+
// .replace('{{options}}', '') // Options are now appended dynamically
|
|
16186
16144
|
.replace('{{class}}', config.optionsClass || '');
|
|
16187
16145
|
return stringToElement(html);
|
|
16188
16146
|
},
|
|
@@ -16190,24 +16148,31 @@ exports.defaultTemplates = {
|
|
|
16190
16148
|
* Renders the load more button for pagination
|
|
16191
16149
|
*/
|
|
16192
16150
|
loadMore: function (config) {
|
|
16193
|
-
var html = getTemplateStrings(config)
|
|
16194
|
-
|
|
16151
|
+
var html = getTemplateStrings(config)
|
|
16152
|
+
.loadMore // .replace('{{loadMoreText}}', config.loadMoreText || 'Load more...') // Content is no longer in template string
|
|
16153
|
+
.replace('{{class}}', config.loadMoreClass || '');
|
|
16154
|
+
var element = stringToElement(html);
|
|
16155
|
+
element.textContent = config.loadMoreText || 'Load more...';
|
|
16156
|
+
return element;
|
|
16195
16157
|
},
|
|
16196
16158
|
/**
|
|
16197
16159
|
* Renders an error message in the dropdown
|
|
16198
16160
|
*/
|
|
16199
16161
|
error: function (config) {
|
|
16162
|
+
// Changed return type to HTMLElement
|
|
16200
16163
|
var template = getTemplateStrings(config).error;
|
|
16201
|
-
|
|
16202
|
-
.replace('{{errorMessage}}', config.errorMessage || 'An error occurred')
|
|
16164
|
+
var html = template
|
|
16165
|
+
// .replace('{{errorMessage}}', config.errorMessage || 'An error occurred') // Content is no longer in template string
|
|
16203
16166
|
.replace('{{class}}', config.errorClass || '');
|
|
16167
|
+
var element = stringToElement(html);
|
|
16168
|
+
element.textContent = config.errorMessage || 'An error occurred';
|
|
16169
|
+
return element;
|
|
16204
16170
|
},
|
|
16205
16171
|
/**
|
|
16206
16172
|
* Renders the main container for the select component
|
|
16207
16173
|
*/
|
|
16208
16174
|
wrapper: function (config) {
|
|
16209
|
-
var html = getTemplateStrings(config).wrapper
|
|
16210
|
-
.replace('{{class}}', config.wrapperClass || '');
|
|
16175
|
+
var html = getTemplateStrings(config).wrapper.replace('{{class}}', config.wrapperClass || '');
|
|
16211
16176
|
var element = stringToElement(html);
|
|
16212
16177
|
element.setAttribute('data-kt-select-combobox', config.combobox ? 'true' : 'false');
|
|
16213
16178
|
element.setAttribute('data-kt-select-tags', config.tags ? 'true' : 'false');
|
|
@@ -16217,57 +16182,66 @@ exports.defaultTemplates = {
|
|
|
16217
16182
|
* Renders the display element (trigger) for the select
|
|
16218
16183
|
*/
|
|
16219
16184
|
display: function (config) {
|
|
16220
|
-
|
|
16221
|
-
|
|
16222
|
-
.combobox.replace(/{{placeholder}}/g, config.placeholder || 'Select...')
|
|
16223
|
-
.replace(/{{label}}/g, config.label || config.placeholder || 'Select...')
|
|
16224
|
-
.replace('{{disabled}}', config.disabled ? 'disabled' : '')
|
|
16225
|
-
.replace('{{class}}', config.displayClass || '');
|
|
16226
|
-
return stringToElement(html_1);
|
|
16227
|
-
}
|
|
16228
|
-
var content = config.label || config.placeholder || 'Select...';
|
|
16229
|
-
var html = getTemplateStrings(config).display
|
|
16230
|
-
.replace('{{tabindex}}', config.disabled ? '-1' : '0')
|
|
16185
|
+
var html = getTemplateStrings(config)
|
|
16186
|
+
.display.replace('{{tabindex}}', config.disabled ? '-1' : '0')
|
|
16231
16187
|
.replace('{{label}}', config.label || config.placeholder || 'Select...')
|
|
16232
16188
|
.replace('{{disabled}}', config.disabled ? 'aria-disabled="true"' : '')
|
|
16233
16189
|
.replace('{{placeholder}}', config.placeholder || 'Select...')
|
|
16234
|
-
.replace('{{class}}', config.displayClass || '')
|
|
16235
|
-
|
|
16236
|
-
|
|
16190
|
+
.replace('{{class}}', config.displayClass || '');
|
|
16191
|
+
var element = stringToElement(html);
|
|
16192
|
+
// Add data-multiple attribute if in multiple select mode
|
|
16193
|
+
if (config.multiple) {
|
|
16194
|
+
element.setAttribute('data-multiple', 'true');
|
|
16195
|
+
}
|
|
16196
|
+
return element;
|
|
16237
16197
|
},
|
|
16238
16198
|
/**
|
|
16239
16199
|
* Renders a single option
|
|
16240
16200
|
*/
|
|
16241
16201
|
option: function (option, config) {
|
|
16202
|
+
var _a, _b;
|
|
16242
16203
|
var isHtmlOption = option instanceof HTMLOptionElement;
|
|
16243
|
-
var
|
|
16244
|
-
|
|
16245
|
-
|
|
16246
|
-
|
|
16247
|
-
|
|
16248
|
-
|
|
16249
|
-
?
|
|
16250
|
-
|
|
16251
|
-
|
|
16204
|
+
var optionData;
|
|
16205
|
+
if (isHtmlOption) {
|
|
16206
|
+
// If it's a plain HTMLOptionElement, construct data similarly to how KTSelectOption would
|
|
16207
|
+
// This branch might be less common if KTSelectOption instances are always used for rendering.
|
|
16208
|
+
var el = option;
|
|
16209
|
+
var textContent = el.textContent || '';
|
|
16210
|
+
optionData = __assign({ value: el.value, text: textContent, selected: el.selected, disabled: el.disabled, content: textContent }, (((_a = config.optionsConfig) === null || _a === void 0 ? void 0 : _a[el.value]) || {}));
|
|
16211
|
+
}
|
|
16212
|
+
else {
|
|
16213
|
+
// If it's a KTSelectOption class instance (from './option')
|
|
16214
|
+
// which should have the getOptionDataForTemplate method.
|
|
16215
|
+
optionData = option.getOptionDataForTemplate();
|
|
16216
|
+
}
|
|
16217
|
+
var content = optionData.text; // Default content to option's text
|
|
16252
16218
|
if (config.optionTemplate) {
|
|
16253
|
-
// Use the user template
|
|
16254
|
-
|
|
16255
|
-
|
|
16256
|
-
text: text,
|
|
16257
|
-
class: config.optionClass || '',
|
|
16258
|
-
selected: selected ? 'aria-selected="true"' : 'aria-selected="false"',
|
|
16259
|
-
disabled: disabled ? 'aria-disabled="true"' : '',
|
|
16260
|
-
content: text,
|
|
16261
|
-
});
|
|
16219
|
+
// Use the user-provided template string, rendering with the full optionData.
|
|
16220
|
+
// renderTemplateString will replace {{key}} with values from optionData.
|
|
16221
|
+
content = (0, utils_1.renderTemplateString)(config.optionTemplate, optionData);
|
|
16262
16222
|
}
|
|
16263
|
-
|
|
16264
|
-
.
|
|
16265
|
-
|
|
16266
|
-
|
|
16267
|
-
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
|
|
16223
|
+
else {
|
|
16224
|
+
content = optionData.text || optionData.content; // Prefer explicit text, fallback to content
|
|
16225
|
+
}
|
|
16226
|
+
// Use the core option template string as the base structure.
|
|
16227
|
+
var baseTemplate = getTemplateStrings(config).option;
|
|
16228
|
+
var optionClasses = [config.optionClass || ''];
|
|
16229
|
+
if (optionData.disabled) {
|
|
16230
|
+
optionClasses.push('disabled');
|
|
16231
|
+
}
|
|
16232
|
+
// Populate the base template for the <li> attributes.
|
|
16233
|
+
// The actual display content (text or custom HTML) will be set on the inner span later.
|
|
16234
|
+
var html = (0, utils_1.renderTemplateString)(baseTemplate, __assign(__assign({}, optionData), { class: optionClasses.join(' ').trim() || '', selected: optionData.selected
|
|
16235
|
+
? 'aria-selected="true"'
|
|
16236
|
+
: 'aria-selected="false"', disabled: optionData.disabled ? 'aria-disabled="true"' : '', content: content }));
|
|
16237
|
+
var element = stringToElement(html);
|
|
16238
|
+
// If a custom option template is provided, replace the element's innerHTML with the content.
|
|
16239
|
+
if (config.optionTemplate) {
|
|
16240
|
+
element.innerHTML = content;
|
|
16241
|
+
}
|
|
16242
|
+
// Ensure data-text attribute is set to the original, clean text for searching/filtering
|
|
16243
|
+
element.setAttribute('data-text', ((_b = optionData === null || optionData === void 0 ? void 0 : optionData.text) === null || _b === void 0 ? void 0 : _b.trim()) || '');
|
|
16244
|
+
return element;
|
|
16271
16245
|
},
|
|
16272
16246
|
/**
|
|
16273
16247
|
* Renders the search input
|
|
@@ -16282,68 +16256,79 @@ exports.defaultTemplates = {
|
|
|
16282
16256
|
* Renders the no results message
|
|
16283
16257
|
*/
|
|
16284
16258
|
empty: function (config) {
|
|
16285
|
-
var html = getTemplateStrings(config)
|
|
16286
|
-
|
|
16287
|
-
|
|
16288
|
-
return
|
|
16259
|
+
var html = getTemplateStrings(config).empty.replace('{{class}}', config.emptyClass || '');
|
|
16260
|
+
var element = stringToElement(html);
|
|
16261
|
+
element.textContent = config.searchNotFoundText || 'No results found';
|
|
16262
|
+
return element;
|
|
16289
16263
|
},
|
|
16290
16264
|
/**
|
|
16291
16265
|
* Renders the loading state
|
|
16292
16266
|
*/
|
|
16293
16267
|
loading: function (config, loadingMessage) {
|
|
16294
|
-
var html = getTemplateStrings(config)
|
|
16295
|
-
|
|
16296
|
-
|
|
16297
|
-
return
|
|
16268
|
+
var html = getTemplateStrings(config).loading.replace('{{class}}', config.loadingClass || '');
|
|
16269
|
+
var element = stringToElement(html);
|
|
16270
|
+
element.textContent = loadingMessage || 'Loading options...';
|
|
16271
|
+
return element;
|
|
16298
16272
|
},
|
|
16299
16273
|
/**
|
|
16300
16274
|
* Renders a tag for multi-select
|
|
16301
16275
|
*/
|
|
16302
16276
|
tag: function (option, config) {
|
|
16277
|
+
var _a;
|
|
16303
16278
|
var template = getTemplateStrings(config).tag;
|
|
16304
|
-
var
|
|
16279
|
+
var preparedContent = option.title; // Default content is the option's title
|
|
16305
16280
|
if (config.tagTemplate) {
|
|
16306
|
-
var
|
|
16307
|
-
var
|
|
16308
|
-
|
|
16309
|
-
|
|
16310
|
-
|
|
16311
|
-
|
|
16312
|
-
|
|
16313
|
-
|
|
16281
|
+
var tagTemplateString_1 = config.tagTemplate;
|
|
16282
|
+
var optionValue = option.getAttribute('data-value') || option.value;
|
|
16283
|
+
// Replace all {{varname}} in option.innerHTML with values from _config.optionsConfig
|
|
16284
|
+
Object.entries(((_a = config.optionsConfig) === null || _a === void 0 ? void 0 : _a[optionValue]) || {}).forEach(function (_a) {
|
|
16285
|
+
var key = _a[0], val = _a[1];
|
|
16286
|
+
if (typeof val === 'string' ||
|
|
16287
|
+
typeof val === 'number' ||
|
|
16288
|
+
typeof val === 'boolean') {
|
|
16289
|
+
tagTemplateString_1 = tagTemplateString_1.replace(new RegExp("{{".concat(key, "}}"), 'g'), String(val));
|
|
16314
16290
|
}
|
|
16315
16291
|
});
|
|
16316
|
-
|
|
16292
|
+
// Render the custom tag template with option data
|
|
16293
|
+
preparedContent = (0, utils_1.renderTemplateString)(tagTemplateString_1, {
|
|
16317
16294
|
title: option.title,
|
|
16318
16295
|
id: option.id,
|
|
16319
|
-
class: config.tagClass || '',
|
|
16320
|
-
content: option.innerHTML,
|
|
16321
|
-
text: option.innerText,
|
|
16296
|
+
class: config.tagClass || '', // This class is for content, not the main tag div
|
|
16297
|
+
// content: option.innerHTML, // Avoid direct innerHTML from option due to potential XSS
|
|
16298
|
+
text: option.innerText || option.textContent || '',
|
|
16299
|
+
value: optionValue,
|
|
16322
16300
|
});
|
|
16323
16301
|
}
|
|
16324
|
-
|
|
16302
|
+
// Append the remove button HTML string to the prepared content
|
|
16303
|
+
preparedContent += getTemplateStrings(config).tagRemoveButton;
|
|
16325
16304
|
var html = template
|
|
16326
|
-
.replace('{{title}}', option.title)
|
|
16327
|
-
.replace('{{id}}', option.id)
|
|
16328
|
-
.replace('{{
|
|
16329
|
-
|
|
16330
|
-
|
|
16305
|
+
// .replace('{{title}}', option.title) // Title is part of preparedContent if using custom template
|
|
16306
|
+
// .replace('{{id}}', option.id) // ID is part of preparedContent if using custom template
|
|
16307
|
+
.replace('{{class}}', config.tagClass || ''); // Class for the main tag div
|
|
16308
|
+
var element = stringToElement(html);
|
|
16309
|
+
element.innerHTML = preparedContent; // Set the fully prepared content (text/HTML + remove button)
|
|
16310
|
+
return element;
|
|
16331
16311
|
},
|
|
16332
16312
|
/**
|
|
16333
16313
|
* Renders the placeholder for the select
|
|
16334
16314
|
*/
|
|
16335
16315
|
placeholder: function (config) {
|
|
16336
|
-
var html = getTemplateStrings(config)
|
|
16337
|
-
.placeholder.replace('{{class}}', config.placeholderClass || '');
|
|
16316
|
+
var html = getTemplateStrings(config).placeholder.replace('{{class}}', config.placeholderClass || '');
|
|
16338
16317
|
var content = config.placeholder || 'Select...';
|
|
16339
16318
|
if (config.placeholderTemplate) {
|
|
16340
16319
|
content = (0, utils_1.renderTemplateString)(config.placeholderTemplate, {
|
|
16341
16320
|
placeholder: config.placeholder || 'Select...',
|
|
16342
16321
|
class: config.placeholderClass || '',
|
|
16343
16322
|
});
|
|
16323
|
+
var element = stringToElement(html);
|
|
16324
|
+
element.innerHTML = content; // For templates, content can be HTML
|
|
16325
|
+
return element;
|
|
16326
|
+
}
|
|
16327
|
+
else {
|
|
16328
|
+
var element = stringToElement(html);
|
|
16329
|
+
element.textContent = content; // For simple text, use textContent
|
|
16330
|
+
return element;
|
|
16344
16331
|
}
|
|
16345
|
-
html = html.replace('{{content}}', content);
|
|
16346
|
-
return stringToElement(html);
|
|
16347
16332
|
},
|
|
16348
16333
|
};
|
|
16349
16334
|
|
|
@@ -17494,7 +17479,6 @@ exports.DefaultConfig = {
|
|
|
17494
17479
|
// Selection Behavior
|
|
17495
17480
|
multiple: false, // Enable/disable multi-select
|
|
17496
17481
|
maxSelections: null, // Maximum number of selections allowed in multi-select mode (null for unlimited)
|
|
17497
|
-
closeOnSelect: false, // Close the dropdown after selecting an option (single-select only)
|
|
17498
17482
|
disabled: false, // Disable the select component
|
|
17499
17483
|
isRequired: false, // Make selection required
|
|
17500
17484
|
// Search Functionality
|
|
@@ -17504,7 +17488,6 @@ exports.DefaultConfig = {
|
|
|
17504
17488
|
searchMinLength: 0, // Minimum characters required to trigger search
|
|
17505
17489
|
searchMaxItems: 50, // Maximum number of search results to display
|
|
17506
17490
|
searchNotFoundText: 'No results found', // Text to display when no search results are found
|
|
17507
|
-
searchHighlight: true, // Highlight matching search terms within the options
|
|
17508
17491
|
clearSearchOnClose: true, // Clear search input when dropdown closes
|
|
17509
17492
|
// Multi-Select Display
|
|
17510
17493
|
selectAllText: 'Select all', // Text for the "Select All" option (if implemented)
|
|
@@ -17529,7 +17512,7 @@ var KTSelectState = /** @class */ (function () {
|
|
|
17529
17512
|
this._config = this._initDefaultConfig(config);
|
|
17530
17513
|
}
|
|
17531
17514
|
KTSelectState.prototype._initDefaultConfig = function (config) {
|
|
17532
|
-
return __assign(__assign({}, exports.DefaultConfig), config);
|
|
17515
|
+
return __assign(__assign(__assign({}, exports.DefaultConfig), config), config.config);
|
|
17533
17516
|
};
|
|
17534
17517
|
KTSelectState.prototype.setItems = function (items, query) {
|
|
17535
17518
|
var _this = this;
|