@keenthemes/ktui 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/ktui.js +1283 -1100
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/examples/select/basic-usage.html +43 -0
- package/examples/select/combobox-icons.html +58 -0
- package/examples/select/combobox.html +46 -0
- package/examples/select/description.html +69 -0
- package/examples/select/disable-option.html +43 -0
- package/examples/select/disable-select.html +34 -0
- package/examples/select/icon-description.html +56 -0
- package/examples/select/icon-multiple.html +58 -0
- package/examples/select/icon.html +58 -0
- package/examples/select/max-selection.html +39 -0
- package/examples/select/modal.html +70 -0
- package/examples/select/multiple.html +42 -0
- package/examples/select/placeholder.html +43 -0
- package/examples/select/remote-data.html +32 -0
- package/examples/select/search.html +49 -0
- package/examples/select/tags-icons.html +58 -0
- package/examples/select/tags-selected.html +59 -0
- package/examples/select/tags.html +58 -0
- package/examples/select/template-customization.html +65 -0
- package/examples/select/test.html +94 -0
- package/examples/toast/example.html +427 -0
- package/lib/cjs/components/component.js +1 -1
- package/lib/cjs/components/component.js.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +22 -6
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/modal/modal.js +0 -4
- package/lib/cjs/components/modal/modal.js.map +1 -1
- package/lib/cjs/components/select/combobox.js +38 -120
- package/lib/cjs/components/select/combobox.js.map +1 -1
- package/lib/cjs/components/select/config.js +4 -16
- package/lib/cjs/components/select/config.js.map +1 -1
- package/lib/cjs/components/select/dropdown.js +10 -49
- package/lib/cjs/components/select/dropdown.js.map +1 -1
- package/lib/cjs/components/select/index.js +2 -1
- package/lib/cjs/components/select/index.js.map +1 -1
- package/lib/cjs/components/select/option.js +21 -4
- package/lib/cjs/components/select/option.js.map +1 -1
- package/lib/cjs/components/select/remote.js +1 -37
- package/lib/cjs/components/select/remote.js.map +1 -1
- package/lib/cjs/components/select/search.js +11 -41
- package/lib/cjs/components/select/search.js.map +1 -1
- package/lib/cjs/components/select/select.js +213 -326
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/cjs/components/select/tags.js +39 -31
- package/lib/cjs/components/select/tags.js.map +1 -1
- package/lib/cjs/components/select/templates.js +120 -179
- package/lib/cjs/components/select/templates.js.map +1 -1
- package/lib/cjs/components/select/types.js +0 -12
- package/lib/cjs/components/select/types.js.map +1 -1
- package/lib/cjs/components/select/utils.js +204 -257
- package/lib/cjs/components/select/utils.js.map +1 -1
- package/lib/cjs/components/toast/index.js +10 -0
- package/lib/cjs/components/toast/index.js.map +1 -0
- package/lib/cjs/components/toast/toast.js +543 -0
- package/lib/cjs/components/toast/toast.js.map +1 -0
- package/lib/cjs/components/toast/types.js +7 -0
- package/lib/cjs/components/toast/types.js.map +1 -0
- package/lib/cjs/helpers/dom.js +24 -0
- package/lib/cjs/helpers/dom.js.map +1 -1
- package/lib/cjs/index.js +5 -1
- package/lib/cjs/index.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 +22 -6
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/modal/modal.js +0 -4
- package/lib/esm/components/modal/modal.js.map +1 -1
- package/lib/esm/components/select/combobox.js +39 -121
- package/lib/esm/components/select/combobox.js.map +1 -1
- package/lib/esm/components/select/config.js +3 -15
- package/lib/esm/components/select/config.js.map +1 -1
- package/lib/esm/components/select/dropdown.js +10 -49
- package/lib/esm/components/select/dropdown.js.map +1 -1
- package/lib/esm/components/select/index.js +1 -1
- package/lib/esm/components/select/index.js.map +1 -1
- package/lib/esm/components/select/option.js +21 -4
- package/lib/esm/components/select/option.js.map +1 -1
- package/lib/esm/components/select/remote.js +1 -37
- package/lib/esm/components/select/remote.js.map +1 -1
- package/lib/esm/components/select/search.js +12 -42
- package/lib/esm/components/select/search.js.map +1 -1
- package/lib/esm/components/select/select.js +214 -327
- package/lib/esm/components/select/select.js.map +1 -1
- package/lib/esm/components/select/tags.js +39 -31
- package/lib/esm/components/select/tags.js.map +1 -1
- package/lib/esm/components/select/templates.js +119 -178
- package/lib/esm/components/select/templates.js.map +1 -1
- package/lib/esm/components/select/types.js +1 -11
- package/lib/esm/components/select/types.js.map +1 -1
- package/lib/esm/components/select/utils.js +201 -255
- package/lib/esm/components/select/utils.js.map +1 -1
- package/lib/esm/components/toast/index.js +6 -0
- package/lib/esm/components/toast/index.js.map +1 -0
- package/lib/esm/components/toast/toast.js +540 -0
- package/lib/esm/components/toast/toast.js.map +1 -0
- package/lib/esm/components/toast/types.js +6 -0
- package/lib/esm/components/toast/types.js.map +1 -0
- package/lib/esm/helpers/dom.js +24 -0
- package/lib/esm/helpers/dom.js.map +1 -1
- package/lib/esm/index.js +3 -0
- package/lib/esm/index.js.map +1 -1
- package/package.json +8 -6
- package/src/components/alert/alert.css +20 -2
- package/src/components/badge/badge.css +5 -0
- package/src/components/component.ts +4 -0
- package/src/components/datatable/datatable.ts +24 -16
- package/src/components/drawer/drawer.css +1 -1
- package/src/components/input/input.css +3 -1
- package/src/components/link/link.css +2 -2
- package/src/components/modal/modal.css +18 -2
- package/src/components/modal/modal.ts +0 -5
- package/src/components/select/combobox.ts +42 -149
- package/src/components/select/config.ts +38 -33
- package/src/components/select/dropdown.ts +8 -55
- package/src/components/select/index.ts +1 -1
- package/src/components/select/option.ts +28 -7
- package/src/components/select/remote.ts +2 -42
- package/src/components/select/search.ts +14 -54
- package/src/components/select/select.css +49 -0
- package/src/components/select/select.ts +231 -437
- package/src/components/select/tags.ts +40 -37
- package/src/components/select/templates.ts +166 -303
- package/src/components/select/types.ts +0 -10
- package/src/components/select/utils.ts +214 -304
- package/src/components/table/table.css +1 -1
- package/src/components/textarea/textarea.css +2 -1
- package/src/components/toast/index.ts +7 -0
- package/src/components/toast/toast.css +60 -0
- package/src/components/toast/toast.ts +605 -0
- package/src/components/toast/types.ts +169 -0
- package/src/helpers/dom.ts +30 -0
- package/src/index.ts +4 -0
- package/styles/main.css +3 -0
- package/styles/vars.css +138 -0
- package/styles.css +1 -0
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
* Copyright 2025 by Keenthemes Inc
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.EventManager = exports.FocusManager = void 0;
|
|
7
|
+
exports.TypeToSearchBuffer = exports.EventManager = exports.FocusManager = exports.highlightTextInElementDebounced = void 0;
|
|
8
8
|
exports.formatCurrency = formatCurrency;
|
|
9
9
|
exports.filterOptions = filterOptions;
|
|
10
10
|
exports.highlightTextInElement = highlightTextInElement;
|
|
11
|
-
exports.handleDropdownKeyNavigation = handleDropdownKeyNavigation;
|
|
12
11
|
exports.debounce = debounce;
|
|
12
|
+
exports.renderTemplateString = renderTemplateString;
|
|
13
|
+
exports.stringToElement = stringToElement;
|
|
14
|
+
// utils.ts
|
|
13
15
|
var templates_1 = require("./templates");
|
|
14
16
|
/**
|
|
15
17
|
* Format a number as a currency string
|
|
@@ -50,6 +52,17 @@ function filterOptions(options, query, config, dropdownElement, onVisibleCount)
|
|
|
50
52
|
option.setAttribute('style', styleAttr.replace(/display:\s*[^;]+;?/gi, '').trim());
|
|
51
53
|
}
|
|
52
54
|
}
|
|
55
|
+
// Clear highlights by restoring original text content
|
|
56
|
+
if (option.dataset && option.dataset.originalText) {
|
|
57
|
+
option.innerHTML = option.dataset.originalText;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
option.innerHTML = option.textContent || '';
|
|
61
|
+
}
|
|
62
|
+
// Remove the cache if present
|
|
63
|
+
if (option.dataset && option.dataset.originalText) {
|
|
64
|
+
delete option.dataset.originalText;
|
|
65
|
+
}
|
|
53
66
|
visibleOptionsCount++;
|
|
54
67
|
}
|
|
55
68
|
// Call the callback with the visible count if provided
|
|
@@ -63,6 +76,8 @@ function filterOptions(options, query, config, dropdownElement, onVisibleCount)
|
|
|
63
76
|
var option = options_2[_b];
|
|
64
77
|
var optionText = ((_a = option.textContent) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
|
|
65
78
|
var isMatch = optionText.includes(query.toLowerCase());
|
|
79
|
+
// Check if option is disabled
|
|
80
|
+
var isDisabled = option.classList.contains('disabled') || option.getAttribute('aria-disabled') === 'true';
|
|
66
81
|
if (isMatch || query.trim() === '') {
|
|
67
82
|
// Show option by removing the hidden class and any display inline styles
|
|
68
83
|
option.classList.remove('hidden');
|
|
@@ -79,22 +94,11 @@ function filterOptions(options, query, config, dropdownElement, onVisibleCount)
|
|
|
79
94
|
}
|
|
80
95
|
}
|
|
81
96
|
visibleOptionsCount++;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
var hasIcon = option.querySelector('[data-kt-select-option-icon]') !== null;
|
|
86
|
-
var hasDescription = option.querySelector('[data-kt-select-option-description]') !== null;
|
|
87
|
-
if (hasIcon || hasDescription) {
|
|
88
|
-
// Only highlight the text part without changing structure
|
|
89
|
-
var titleElement = option.querySelector('[data-kt-option-title]');
|
|
90
|
-
if (titleElement) {
|
|
91
|
-
highlightTextInElement(titleElement, query, config);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
// Simple option with just text - standard highlighting
|
|
96
|
-
highlightTextInElement(option, query, config);
|
|
97
|
+
if (config.searchHighlight && query.trim() !== '') {
|
|
98
|
+
if (option.dataset && !option.dataset.originalText) {
|
|
99
|
+
option.dataset.originalText = option.innerHTML;
|
|
97
100
|
}
|
|
101
|
+
(0, exports.highlightTextInElementDebounced)(option, query, config);
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
104
|
else {
|
|
@@ -131,37 +135,39 @@ function highlightTextInElement(element, query, config) {
|
|
|
131
135
|
if (!element || !query || query.trim() === '')
|
|
132
136
|
return;
|
|
133
137
|
var queryLower = query.toLowerCase();
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
Array.from(node.childNodes).forEach(walk);
|
|
161
|
-
}
|
|
138
|
+
var text = element.textContent || '';
|
|
139
|
+
if (!text)
|
|
140
|
+
return;
|
|
141
|
+
// Escape regex special characters in query
|
|
142
|
+
var escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
143
|
+
var regex = new RegExp(escapedQuery, 'gi');
|
|
144
|
+
// Replace all matches with the highlight template
|
|
145
|
+
var lastIndex = 0;
|
|
146
|
+
var result = '';
|
|
147
|
+
var match;
|
|
148
|
+
var matches = [];
|
|
149
|
+
while ((match = regex.exec(text)) !== null) {
|
|
150
|
+
matches.push({ start: match.index, end: regex.lastIndex });
|
|
151
|
+
}
|
|
152
|
+
if (matches.length === 0) {
|
|
153
|
+
element.innerHTML = text;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
for (var i = 0; i < matches.length; i++) {
|
|
157
|
+
var _a = matches[i], start = _a.start, end = _a.end;
|
|
158
|
+
// Add text before match
|
|
159
|
+
result += text.slice(lastIndex, start);
|
|
160
|
+
// Add highlighted match using template
|
|
161
|
+
var highlighted = templates_1.defaultTemplates.highlight(config, text.slice(start, end)).outerHTML;
|
|
162
|
+
result += highlighted;
|
|
163
|
+
lastIndex = end;
|
|
162
164
|
}
|
|
163
|
-
|
|
165
|
+
// Add remaining text
|
|
166
|
+
result += text.slice(lastIndex);
|
|
167
|
+
element.innerHTML = result;
|
|
164
168
|
}
|
|
169
|
+
// Debounced version for performance
|
|
170
|
+
exports.highlightTextInElementDebounced = debounce(highlightTextInElement, 100);
|
|
165
171
|
/**
|
|
166
172
|
* Focus manager for keyboard navigation
|
|
167
173
|
* Consolidates redundant focus management logic into shared functions
|
|
@@ -170,16 +176,14 @@ var FocusManager = /** @class */ (function () {
|
|
|
170
176
|
function FocusManager(element, optionsSelector, config) {
|
|
171
177
|
if (optionsSelector === void 0) { optionsSelector = '[data-kt-select-option]'; }
|
|
172
178
|
this._focusedOptionIndex = null;
|
|
179
|
+
this._onFocusChange = null;
|
|
173
180
|
this._element = element;
|
|
174
181
|
this._optionsSelector = optionsSelector;
|
|
175
182
|
this._eventManager = new EventManager();
|
|
176
|
-
// Use config values if provided, otherwise fallback to defaults
|
|
177
|
-
this._focusClass = (config === null || config === void 0 ? void 0 : config.focusClass) || 'option-focused';
|
|
178
|
-
this._hoverClass = (config === null || config === void 0 ? void 0 : config.hoverClass) || 'hovered';
|
|
179
|
-
this._bgClass = (config === null || config === void 0 ? void 0 : config.bgClass) || 'bg-blue-50';
|
|
180
|
-
this._fontClass = (config === null || config === void 0 ? void 0 : config.fontClass) || 'font-medium';
|
|
181
183
|
// Add click handler to update focus state when options are clicked
|
|
182
184
|
this._setupOptionClickHandlers();
|
|
185
|
+
this._focusClass = 'focus'; // or whatever your intended class is
|
|
186
|
+
this._hoverClass = 'hover'; // or your intended class
|
|
183
187
|
}
|
|
184
188
|
/**
|
|
185
189
|
* Set up click handlers for all options to update focus state
|
|
@@ -191,15 +195,6 @@ var FocusManager = /** @class */ (function () {
|
|
|
191
195
|
var target = e.target;
|
|
192
196
|
var optionElement = target.closest(_this._optionsSelector);
|
|
193
197
|
if (optionElement) {
|
|
194
|
-
// First clear all focus
|
|
195
|
-
_this.resetFocus();
|
|
196
|
-
// Then update the focused index based on the clicked option
|
|
197
|
-
var options = _this.getVisibleOptions();
|
|
198
|
-
var clickedIndex = options.indexOf(optionElement);
|
|
199
|
-
if (clickedIndex >= 0) {
|
|
200
|
-
_this._focusedOptionIndex = clickedIndex;
|
|
201
|
-
_this.applyFocus(options[clickedIndex]);
|
|
202
|
-
}
|
|
203
198
|
}
|
|
204
199
|
});
|
|
205
200
|
};
|
|
@@ -221,24 +216,88 @@ var FocusManager = /** @class */ (function () {
|
|
|
221
216
|
});
|
|
222
217
|
};
|
|
223
218
|
/**
|
|
224
|
-
* Focus the
|
|
219
|
+
* Focus the first visible option
|
|
225
220
|
*/
|
|
226
|
-
FocusManager.prototype.
|
|
221
|
+
FocusManager.prototype.focusFirst = function () {
|
|
227
222
|
var options = this.getVisibleOptions();
|
|
228
223
|
if (options.length === 0)
|
|
229
224
|
return null;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
225
|
+
for (var i = 0; i < options.length; i++) {
|
|
226
|
+
var option = options[i];
|
|
227
|
+
if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
|
|
228
|
+
this.resetFocus();
|
|
229
|
+
this._focusedOptionIndex = i;
|
|
230
|
+
this.applyFocus(option);
|
|
231
|
+
this.scrollIntoView(option);
|
|
232
|
+
return option;
|
|
233
|
+
}
|
|
233
234
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
235
|
+
return null;
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Focus the last visible option
|
|
239
|
+
*/
|
|
240
|
+
FocusManager.prototype.focusLast = function () {
|
|
241
|
+
var options = this.getVisibleOptions();
|
|
242
|
+
if (options.length === 0)
|
|
243
|
+
return null;
|
|
244
|
+
for (var i = options.length - 1; i >= 0; i--) {
|
|
245
|
+
var option = options[i];
|
|
246
|
+
if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
|
|
247
|
+
this.resetFocus();
|
|
248
|
+
this._focusedOptionIndex = i;
|
|
249
|
+
this.applyFocus(option);
|
|
250
|
+
this.scrollIntoView(option);
|
|
251
|
+
return option;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* Focus the next visible option that matches the search string
|
|
258
|
+
*/
|
|
259
|
+
FocusManager.prototype.focusByString = function (str) {
|
|
260
|
+
var _a, _b, _c;
|
|
261
|
+
var options = this.getVisibleOptions();
|
|
262
|
+
if (options.length === 0)
|
|
263
|
+
return null;
|
|
264
|
+
var lowerStr = str.toLowerCase();
|
|
265
|
+
var startIdx = ((_a = this._focusedOptionIndex) !== null && _a !== void 0 ? _a : -1) + 1;
|
|
266
|
+
for (var i = 0; i < options.length; i++) {
|
|
267
|
+
var idx = (startIdx + i) % options.length;
|
|
268
|
+
var option = options[idx];
|
|
269
|
+
if (!option.classList.contains('disabled') &&
|
|
270
|
+
option.getAttribute('aria-disabled') !== 'true' &&
|
|
271
|
+
(((_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)))) {
|
|
272
|
+
this._focusedOptionIndex = idx;
|
|
273
|
+
this.applyFocus(option);
|
|
274
|
+
this.scrollIntoView(option);
|
|
275
|
+
return option;
|
|
276
|
+
}
|
|
237
277
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
278
|
+
return null;
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* Focus the next visible option
|
|
282
|
+
*/
|
|
283
|
+
FocusManager.prototype.focusNext = function () {
|
|
284
|
+
var options = this.getVisibleOptions();
|
|
285
|
+
if (options.length === 0)
|
|
286
|
+
return null;
|
|
287
|
+
var idx = this._focusedOptionIndex === null ? 0 : (this._focusedOptionIndex + 1) % options.length;
|
|
288
|
+
var startIdx = idx;
|
|
289
|
+
do {
|
|
290
|
+
var option = options[idx];
|
|
291
|
+
if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
|
|
292
|
+
this.resetFocus();
|
|
293
|
+
this._focusedOptionIndex = idx;
|
|
294
|
+
this.applyFocus(option);
|
|
295
|
+
this.scrollIntoView(option);
|
|
296
|
+
return option;
|
|
297
|
+
}
|
|
298
|
+
idx = (idx + 1) % options.length;
|
|
299
|
+
} while (idx !== startIdx);
|
|
300
|
+
return null;
|
|
242
301
|
};
|
|
243
302
|
/**
|
|
244
303
|
* Focus the previous visible option
|
|
@@ -247,18 +306,20 @@ var FocusManager = /** @class */ (function () {
|
|
|
247
306
|
var options = this.getVisibleOptions();
|
|
248
307
|
if (options.length === 0)
|
|
249
308
|
return null;
|
|
250
|
-
this.
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
309
|
+
var idx = this._focusedOptionIndex === null ? options.length - 1 : (this._focusedOptionIndex - 1 + options.length) % options.length;
|
|
310
|
+
var startIdx = idx;
|
|
311
|
+
do {
|
|
312
|
+
var option = options[idx];
|
|
313
|
+
if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
|
|
314
|
+
this.resetFocus();
|
|
315
|
+
this._focusedOptionIndex = idx;
|
|
316
|
+
this.applyFocus(option);
|
|
317
|
+
this.scrollIntoView(option);
|
|
318
|
+
return option;
|
|
319
|
+
}
|
|
320
|
+
idx = (idx - 1 + options.length) % options.length;
|
|
321
|
+
} while (idx !== startIdx);
|
|
322
|
+
return null;
|
|
262
323
|
};
|
|
263
324
|
/**
|
|
264
325
|
* Apply focus to a specific option
|
|
@@ -266,27 +327,23 @@ var FocusManager = /** @class */ (function () {
|
|
|
266
327
|
FocusManager.prototype.applyFocus = function (option) {
|
|
267
328
|
if (!option)
|
|
268
329
|
return;
|
|
269
|
-
|
|
330
|
+
if (option.classList.contains('disabled') || option.getAttribute('aria-disabled') === 'true') {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
270
333
|
this.resetFocus();
|
|
271
|
-
// Add focus to this option
|
|
272
334
|
option.classList.add(this._focusClass);
|
|
273
335
|
option.classList.add(this._hoverClass);
|
|
274
|
-
|
|
275
|
-
option.classList.add(this._fontClass);
|
|
336
|
+
this._triggerFocusChange();
|
|
276
337
|
};
|
|
277
338
|
/**
|
|
278
339
|
* Reset focus on all options
|
|
279
340
|
*/
|
|
280
341
|
FocusManager.prototype.resetFocus = function () {
|
|
281
342
|
var _this = this;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
// Remove classes from all elements
|
|
343
|
+
var focusedElements = this._element.querySelectorAll(".".concat(this._focusClass, ", .").concat(this._hoverClass));
|
|
344
|
+
// Remove focus and hover classes from all options
|
|
285
345
|
focusedElements.forEach(function (element) {
|
|
286
|
-
element.classList.remove(_this._focusClass);
|
|
287
|
-
element.classList.remove(_this._hoverClass);
|
|
288
|
-
element.classList.remove(_this._bgClass);
|
|
289
|
-
element.classList.remove(_this._fontClass);
|
|
346
|
+
element.classList.remove(_this._focusClass, _this._hoverClass);
|
|
290
347
|
});
|
|
291
348
|
// Reset index if visible options have changed
|
|
292
349
|
var visibleOptions = this.getVisibleOptions();
|
|
@@ -301,7 +358,7 @@ var FocusManager = /** @class */ (function () {
|
|
|
301
358
|
FocusManager.prototype.scrollIntoView = function (option) {
|
|
302
359
|
if (!option)
|
|
303
360
|
return;
|
|
304
|
-
var container = this._element.querySelector('[data-kt-select-options
|
|
361
|
+
var container = this._element.querySelector('[data-kt-select-options]');
|
|
305
362
|
if (!container)
|
|
306
363
|
return;
|
|
307
364
|
var optionRect = option.getBoundingClientRect();
|
|
@@ -352,6 +409,17 @@ var FocusManager = /** @class */ (function () {
|
|
|
352
409
|
FocusManager.prototype.setFocusedIndex = function (index) {
|
|
353
410
|
this._focusedOptionIndex = index;
|
|
354
411
|
};
|
|
412
|
+
/**
|
|
413
|
+
* Set a callback to be called when focus changes
|
|
414
|
+
*/
|
|
415
|
+
FocusManager.prototype.setOnFocusChange = function (cb) {
|
|
416
|
+
this._onFocusChange = cb;
|
|
417
|
+
};
|
|
418
|
+
FocusManager.prototype._triggerFocusChange = function () {
|
|
419
|
+
if (this._onFocusChange) {
|
|
420
|
+
this._onFocusChange(this.getFocusedOption(), this._focusedOptionIndex);
|
|
421
|
+
}
|
|
422
|
+
};
|
|
355
423
|
/**
|
|
356
424
|
* Clean up event listeners
|
|
357
425
|
*/
|
|
@@ -363,166 +431,6 @@ var FocusManager = /** @class */ (function () {
|
|
|
363
431
|
return FocusManager;
|
|
364
432
|
}());
|
|
365
433
|
exports.FocusManager = FocusManager;
|
|
366
|
-
/**
|
|
367
|
-
* Shared keyboard navigation handler for dropdown options
|
|
368
|
-
* Can be used by both combobox and search modules
|
|
369
|
-
*/
|
|
370
|
-
function handleDropdownKeyNavigation(event, select, config, callbacks) {
|
|
371
|
-
try {
|
|
372
|
-
// Get the dropdown state
|
|
373
|
-
var isDropdownOpen = select._dropdownIsOpen;
|
|
374
|
-
// Log the event to help debug
|
|
375
|
-
var origin_1 = 'handleDropdownKeyNavigation';
|
|
376
|
-
if (select.getConfig && select.getConfig().debug)
|
|
377
|
-
console.log("[".concat(origin_1, "] Key: ").concat(event.key, ", Dropdown open: ").concat(isDropdownOpen));
|
|
378
|
-
// Handle basic keyboard navigation
|
|
379
|
-
switch (event.key) {
|
|
380
|
-
case 'ArrowDown':
|
|
381
|
-
if (!isDropdownOpen) {
|
|
382
|
-
if (select.getConfig && select.getConfig().debug)
|
|
383
|
-
console.log("[".concat(origin_1, "] Opening dropdown on ArrowDown"));
|
|
384
|
-
select.openDropdown();
|
|
385
|
-
// Focus the first option after opening
|
|
386
|
-
setTimeout(function () {
|
|
387
|
-
select._focusNextOption();
|
|
388
|
-
}, 50);
|
|
389
|
-
}
|
|
390
|
-
else if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onArrowDown) {
|
|
391
|
-
if (select.getConfig && select.getConfig().debug)
|
|
392
|
-
console.log("[".concat(origin_1, "] Using custom onArrowDown callback"));
|
|
393
|
-
callbacks.onArrowDown();
|
|
394
|
-
}
|
|
395
|
-
else {
|
|
396
|
-
if (select.getConfig && select.getConfig().debug)
|
|
397
|
-
console.log("[".concat(origin_1, "] Using default _focusNextOption"));
|
|
398
|
-
var focusedOption = select._focusNextOption();
|
|
399
|
-
// Ensure we have a focused option
|
|
400
|
-
if (focusedOption) {
|
|
401
|
-
if (select.getConfig && select.getConfig().debug)
|
|
402
|
-
console.log("[".concat(origin_1, "] Focused next option:"), focusedOption);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
event.preventDefault();
|
|
406
|
-
break;
|
|
407
|
-
case 'ArrowUp':
|
|
408
|
-
if (!isDropdownOpen) {
|
|
409
|
-
if (select.getConfig && select.getConfig().debug)
|
|
410
|
-
console.log("[".concat(origin_1, "] Opening dropdown on ArrowUp"));
|
|
411
|
-
select.openDropdown();
|
|
412
|
-
// Focus the last option after opening
|
|
413
|
-
setTimeout(function () {
|
|
414
|
-
select._focusPreviousOption();
|
|
415
|
-
}, 50);
|
|
416
|
-
}
|
|
417
|
-
else if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onArrowUp) {
|
|
418
|
-
if (select.getConfig && select.getConfig().debug)
|
|
419
|
-
console.log("[".concat(origin_1, "] Using custom onArrowUp callback"));
|
|
420
|
-
callbacks.onArrowUp();
|
|
421
|
-
}
|
|
422
|
-
else {
|
|
423
|
-
if (select.getConfig && select.getConfig().debug)
|
|
424
|
-
console.log("[".concat(origin_1, "] Using default _focusPreviousOption"));
|
|
425
|
-
var focusedOption = select._focusPreviousOption();
|
|
426
|
-
// Ensure we have a focused option
|
|
427
|
-
if (focusedOption) {
|
|
428
|
-
if (select.getConfig && select.getConfig().debug)
|
|
429
|
-
console.log("[".concat(origin_1, "] Focused previous option:"), focusedOption);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
event.preventDefault();
|
|
433
|
-
break;
|
|
434
|
-
case 'Enter':
|
|
435
|
-
// Prevent form submission
|
|
436
|
-
event.preventDefault();
|
|
437
|
-
if (isDropdownOpen) {
|
|
438
|
-
if (select.getConfig && select.getConfig().debug)
|
|
439
|
-
console.log("[".concat(origin_1, "] Enter pressed with dropdown open"));
|
|
440
|
-
// For combobox mode, ensure we update the input value directly
|
|
441
|
-
var isCombobox = select.getConfig().mode === 'combobox';
|
|
442
|
-
var comboboxModule = select._comboboxModule;
|
|
443
|
-
if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onEnter) {
|
|
444
|
-
if (select.getConfig && select.getConfig().debug)
|
|
445
|
-
console.log("[".concat(origin_1, "] Using custom onEnter callback"));
|
|
446
|
-
callbacks.onEnter();
|
|
447
|
-
}
|
|
448
|
-
else {
|
|
449
|
-
if (select.getConfig && select.getConfig().debug)
|
|
450
|
-
console.log("[".concat(origin_1, "] Using default selectFocusedOption"));
|
|
451
|
-
// Make sure there is a focused option before trying to select it
|
|
452
|
-
if (select._focusManager &&
|
|
453
|
-
select._focusManager.getFocusedOption()) {
|
|
454
|
-
select.selectFocusedOption();
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
// If no option is focused, try to focus the first one
|
|
458
|
-
var focusedOption = select._focusNextOption();
|
|
459
|
-
// Only select if an option was successfully focused
|
|
460
|
-
if (focusedOption) {
|
|
461
|
-
select.selectFocusedOption();
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
// Close dropdown after selection if not multiple and closeOnSelect is true
|
|
466
|
-
if (!config.multiple && config.closeOnSelect !== false) {
|
|
467
|
-
if (select.getConfig && select.getConfig().debug)
|
|
468
|
-
console.log("[".concat(origin_1, "] Closing dropdown after selection"));
|
|
469
|
-
select.closeDropdown();
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
else {
|
|
473
|
-
// If dropdown is closed, open it on Enter
|
|
474
|
-
if (select.getConfig && select.getConfig().debug)
|
|
475
|
-
console.log("[".concat(origin_1, "] Opening dropdown on Enter"));
|
|
476
|
-
select.openDropdown();
|
|
477
|
-
// Focus the first option after opening
|
|
478
|
-
setTimeout(function () {
|
|
479
|
-
select._focusNextOption();
|
|
480
|
-
}, 50);
|
|
481
|
-
}
|
|
482
|
-
break;
|
|
483
|
-
case 'Tab':
|
|
484
|
-
// Only handle tab if dropdown is open
|
|
485
|
-
if (isDropdownOpen) {
|
|
486
|
-
if (select.getConfig && select.getConfig().debug)
|
|
487
|
-
console.log("[".concat(origin_1, "] Closing dropdown on Tab"));
|
|
488
|
-
select.closeDropdown();
|
|
489
|
-
if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onClose) {
|
|
490
|
-
callbacks.onClose();
|
|
491
|
-
}
|
|
492
|
-
// Don't prevent default tab behavior - let it move focus naturally
|
|
493
|
-
}
|
|
494
|
-
break;
|
|
495
|
-
case 'Escape':
|
|
496
|
-
// Only handle escape if dropdown is open
|
|
497
|
-
if (isDropdownOpen) {
|
|
498
|
-
if (select.getConfig && select.getConfig().debug)
|
|
499
|
-
console.log("[".concat(origin_1, "] Closing dropdown on Escape"));
|
|
500
|
-
select.closeDropdown();
|
|
501
|
-
if (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onClose) {
|
|
502
|
-
callbacks.onClose();
|
|
503
|
-
}
|
|
504
|
-
event.preventDefault(); // Prevent other escape handlers
|
|
505
|
-
}
|
|
506
|
-
break;
|
|
507
|
-
case ' ': // Space key
|
|
508
|
-
// If dropdown is closed, space should open it (but not if in combobox mode)
|
|
509
|
-
if (!isDropdownOpen && !(select.getConfig().mode === 'combobox')) {
|
|
510
|
-
if (select.getConfig && select.getConfig().debug)
|
|
511
|
-
console.log("[".concat(origin_1, "] Opening dropdown on Space"));
|
|
512
|
-
select.openDropdown();
|
|
513
|
-
// Focus the first option after opening
|
|
514
|
-
setTimeout(function () {
|
|
515
|
-
select._focusNextOption();
|
|
516
|
-
}, 50);
|
|
517
|
-
event.preventDefault();
|
|
518
|
-
}
|
|
519
|
-
break;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
catch (error) {
|
|
523
|
-
console.error('Error in keyboard navigation handler:', error);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
434
|
/**
|
|
527
435
|
* Centralized event listener management
|
|
528
436
|
*/
|
|
@@ -579,7 +487,7 @@ var EventManager = /** @class */ (function () {
|
|
|
579
487
|
// Go through each event type
|
|
580
488
|
this._boundHandlers.forEach(function (eventMap, event) {
|
|
581
489
|
// For each event type, go through each handler
|
|
582
|
-
eventMap.forEach(function (boundHandler
|
|
490
|
+
eventMap.forEach(function (boundHandler) {
|
|
583
491
|
element.removeEventListener(event, boundHandler);
|
|
584
492
|
});
|
|
585
493
|
});
|
|
@@ -603,4 +511,43 @@ function debounce(func, delay) {
|
|
|
603
511
|
timeout = setTimeout(function () { return func.apply(void 0, args); }, delay);
|
|
604
512
|
};
|
|
605
513
|
}
|
|
514
|
+
/**
|
|
515
|
+
* Replaces all {{key}} in the template with the corresponding value from the data object.
|
|
516
|
+
* If a key is missing in data, replaces with an empty string.
|
|
517
|
+
*/
|
|
518
|
+
function renderTemplateString(template, data) {
|
|
519
|
+
return template.replace(/{{(\w+)}}/g, function (_, key) {
|
|
520
|
+
return data[key] !== undefined && data[key] !== null ? String(data[key]) : '';
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
// Type-to-search buffer utility for keyboard navigation
|
|
524
|
+
var TypeToSearchBuffer = /** @class */ (function () {
|
|
525
|
+
function TypeToSearchBuffer(timeout) {
|
|
526
|
+
if (timeout === void 0) { timeout = 500; }
|
|
527
|
+
this.buffer = '';
|
|
528
|
+
this.lastTime = 0;
|
|
529
|
+
this.timeout = timeout;
|
|
530
|
+
}
|
|
531
|
+
TypeToSearchBuffer.prototype.push = function (char) {
|
|
532
|
+
var now = Date.now();
|
|
533
|
+
if (now - this.lastTime > this.timeout) {
|
|
534
|
+
this.buffer = '';
|
|
535
|
+
}
|
|
536
|
+
this.buffer += char;
|
|
537
|
+
this.lastTime = now;
|
|
538
|
+
};
|
|
539
|
+
TypeToSearchBuffer.prototype.getBuffer = function () {
|
|
540
|
+
return this.buffer;
|
|
541
|
+
};
|
|
542
|
+
TypeToSearchBuffer.prototype.clear = function () {
|
|
543
|
+
this.buffer = '';
|
|
544
|
+
};
|
|
545
|
+
return TypeToSearchBuffer;
|
|
546
|
+
}());
|
|
547
|
+
exports.TypeToSearchBuffer = TypeToSearchBuffer;
|
|
548
|
+
function stringToElement(html) {
|
|
549
|
+
var template = document.createElement('template');
|
|
550
|
+
template.innerHTML = html.trim();
|
|
551
|
+
return template.content.firstElementChild;
|
|
552
|
+
}
|
|
606
553
|
//# sourceMappingURL=utils.js.map
|