@keenthemes/ktui 1.0.18 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/ktui.js +298 -33
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +27 -1
  5. package/lib/cjs/components/component.js +57 -5
  6. package/lib/cjs/components/component.js.map +1 -1
  7. package/lib/cjs/components/datatable/datatable.js +71 -10
  8. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  9. package/lib/cjs/components/select/config.js +1 -0
  10. package/lib/cjs/components/select/config.js.map +1 -1
  11. package/lib/cjs/components/select/search.js +13 -2
  12. package/lib/cjs/components/select/search.js.map +1 -1
  13. package/lib/cjs/components/select/select.js +80 -3
  14. package/lib/cjs/components/select/select.js.map +1 -1
  15. package/lib/cjs/components/select/templates.js +6 -0
  16. package/lib/cjs/components/select/templates.js.map +1 -1
  17. package/lib/cjs/components/stepper/stepper.js +59 -12
  18. package/lib/cjs/components/stepper/stepper.js.map +1 -1
  19. package/lib/cjs/components/toast/toast.js +11 -1
  20. package/lib/cjs/components/toast/toast.js.map +1 -1
  21. package/lib/esm/components/component.js +57 -5
  22. package/lib/esm/components/component.js.map +1 -1
  23. package/lib/esm/components/datatable/datatable.js +70 -10
  24. package/lib/esm/components/datatable/datatable.js.map +1 -1
  25. package/lib/esm/components/select/config.js +1 -0
  26. package/lib/esm/components/select/config.js.map +1 -1
  27. package/lib/esm/components/select/search.js +13 -2
  28. package/lib/esm/components/select/search.js.map +1 -1
  29. package/lib/esm/components/select/select.js +80 -3
  30. package/lib/esm/components/select/select.js.map +1 -1
  31. package/lib/esm/components/select/templates.js +6 -0
  32. package/lib/esm/components/select/templates.js.map +1 -1
  33. package/lib/esm/components/stepper/stepper.js +59 -12
  34. package/lib/esm/components/stepper/stepper.js.map +1 -1
  35. package/lib/esm/components/toast/toast.js +11 -1
  36. package/lib/esm/components/toast/toast.js.map +1 -1
  37. package/package.json +2 -2
  38. package/src/components/component.ts +18 -4
  39. package/src/components/datatable/datatable.ts +86 -12
  40. package/src/components/datatable/types.ts +5 -1
  41. package/src/components/select/config.ts +2 -0
  42. package/src/components/select/search.ts +14 -2
  43. package/src/components/select/select.css +14 -6
  44. package/src/components/select/select.ts +107 -3
  45. package/src/components/select/templates.ts +13 -0
  46. package/src/components/stepper/stepper.ts +2 -2
  47. package/src/components/toast/toast.ts +10 -1
package/dist/ktui.js CHANGED
@@ -568,6 +568,42 @@ var __extends = (this && this.__extends) || (function () {
568
568
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
569
569
  };
570
570
  })();
571
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
572
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
573
+ return new (P || (P = Promise))(function (resolve, reject) {
574
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
575
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
576
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
577
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
578
+ });
579
+ };
580
+ var __generator = (this && this.__generator) || function (thisArg, body) {
581
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
582
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
583
+ function verb(n) { return function (v) { return step([n, v]); }; }
584
+ function step(op) {
585
+ if (f) throw new TypeError("Generator is already executing.");
586
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
587
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
588
+ if (y = 0, t) op = [op[0] & 2, t.value];
589
+ switch (op[0]) {
590
+ case 0: case 1: t = op; break;
591
+ case 4: _.label++; return { value: op[1], done: false };
592
+ case 5: _.label++; y = op[1]; op = [0]; continue;
593
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
594
+ default:
595
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
596
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
597
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
598
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
599
+ if (t[2]) _.ops.pop();
600
+ _.trys.pop(); continue;
601
+ }
602
+ op = body.call(thisArg, _);
603
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
604
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
605
+ }
606
+ };
571
607
  Object.defineProperty(exports, "__esModule", ({ value: true }));
572
608
  exports.KTStepper = void 0;
573
609
  var data_1 = __webpack_require__(8716);
@@ -677,18 +713,29 @@ var KTStepper = /** @class */ (function (_super) {
677
713
  return elements;
678
714
  };
679
715
  KTStepper.prototype._go = function (step) {
680
- if (step === this._activeStep || step > this._getTotalSteps() || step < 0)
681
- return;
682
- var payload = { step: step, cancel: false };
683
- this._fireEvent('change', payload);
684
- this._dispatchEvent('change', payload);
685
- if (payload.cancel === true) {
686
- return;
687
- }
688
- this._activeStep = step;
689
- this._update();
690
- this._fireEvent('changed');
691
- this._dispatchEvent('changed');
716
+ return __awaiter(this, void 0, void 0, function () {
717
+ var payload;
718
+ return __generator(this, function (_a) {
719
+ switch (_a.label) {
720
+ case 0:
721
+ if (step === this._activeStep || step > this._getTotalSteps() || step < 0)
722
+ return [2 /*return*/];
723
+ payload = { step: step, cancel: false };
724
+ return [4 /*yield*/, this._fireEvent('change', payload)];
725
+ case 1:
726
+ _a.sent();
727
+ this._dispatchEvent('change', payload);
728
+ if (payload.cancel === true) {
729
+ return [2 /*return*/];
730
+ }
731
+ this._activeStep = step;
732
+ this._update();
733
+ this._fireEvent('changed');
734
+ this._dispatchEvent('changed');
735
+ return [2 /*return*/];
736
+ }
737
+ });
738
+ });
692
739
  };
693
740
  KTStepper.prototype._goTo = function (itemElement) {
694
741
  var step = this._getStep(itemElement);
@@ -2395,6 +2442,42 @@ var __assign = (this && this.__assign) || function () {
2395
2442
  };
2396
2443
  return __assign.apply(this, arguments);
2397
2444
  };
2445
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2446
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
2447
+ return new (P || (P = Promise))(function (resolve, reject) {
2448
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2449
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2450
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
2451
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
2452
+ });
2453
+ };
2454
+ var __generator = (this && this.__generator) || function (thisArg, body) {
2455
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
2456
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
2457
+ function verb(n) { return function (v) { return step([n, v]); }; }
2458
+ function step(op) {
2459
+ if (f) throw new TypeError("Generator is already executing.");
2460
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
2461
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
2462
+ if (y = 0, t) op = [op[0] & 2, t.value];
2463
+ switch (op[0]) {
2464
+ case 0: case 1: t = op; break;
2465
+ case 4: _.label++; return { value: op[1], done: false };
2466
+ case 5: _.label++; y = op[1]; op = [0]; continue;
2467
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
2468
+ default:
2469
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
2470
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
2471
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
2472
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
2473
+ if (t[2]) _.ops.pop();
2474
+ _.trys.pop(); continue;
2475
+ }
2476
+ op = body.call(thisArg, _);
2477
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
2478
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
2479
+ }
2480
+ };
2398
2481
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2399
2482
  var data_1 = __webpack_require__(8716);
2400
2483
  var dom_1 = __webpack_require__(9010);
@@ -2416,11 +2499,27 @@ var KTComponent = /** @class */ (function () {
2416
2499
  this._element.setAttribute("data-kt-".concat(this._name, "-initialized"), 'true');
2417
2500
  data_1.default.set(this._element, this._name, this);
2418
2501
  };
2419
- KTComponent.prototype._fireEvent = function (eventType, payload) {
2420
- var _a;
2421
- if (payload === void 0) { payload = null; }
2422
- (_a = this._events.get(eventType)) === null || _a === void 0 ? void 0 : _a.forEach(function (callable) {
2423
- callable(payload);
2502
+ KTComponent.prototype._fireEvent = function (eventType_1) {
2503
+ return __awaiter(this, arguments, void 0, function (eventType, payload) {
2504
+ var callbacks;
2505
+ if (payload === void 0) { payload = null; }
2506
+ return __generator(this, function (_a) {
2507
+ switch (_a.label) {
2508
+ case 0:
2509
+ callbacks = this._events.get(eventType);
2510
+ if ((callbacks instanceof Map) == false) {
2511
+ return [2 /*return*/];
2512
+ }
2513
+ return [4 /*yield*/, Promise.all(Array.from(callbacks.values()).filter(function (callable) {
2514
+ return typeof callable === 'function';
2515
+ }).map(function (callable) {
2516
+ return Promise.resolve(callable(payload));
2517
+ }))];
2518
+ case 1:
2519
+ _a.sent();
2520
+ return [2 /*return*/];
2521
+ }
2522
+ });
2424
2523
  });
2425
2524
  };
2426
2525
  KTComponent.prototype._dispatchEvent = function (eventType, payload) {
@@ -7587,6 +7686,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
7587
7686
  };
7588
7687
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7589
7688
  exports.KTDataTable = void 0;
7689
+ exports.initAllDataTables = initAllDataTables;
7590
7690
  var component_1 = __webpack_require__(2658);
7591
7691
  var utils_1 = __webpack_require__(2599);
7592
7692
  var index_1 = __webpack_require__(8156);
@@ -8693,8 +8793,61 @@ var KTDataTable = /** @class */ (function (_super) {
8693
8793
  }
8694
8794
  return id;
8695
8795
  };
8796
+ /**
8797
+ * Clean up all event listeners, handlers, and DOM nodes created by this instance.
8798
+ * This method is called before re-rendering or when disposing the component.
8799
+ */
8696
8800
  KTDataTable.prototype._dispose = function () {
8697
- // Remove all event listeners and clean up resources
8801
+ // --- 1. Remove search input event listener (debounced) ---
8802
+ var tableId = this._tableId();
8803
+ var searchElement = document.querySelector("[data-kt-datatable-search=\"#".concat(tableId, "\"]"));
8804
+ if (searchElement && searchElement._debouncedSearch) {
8805
+ searchElement.removeEventListener('keyup', searchElement._debouncedSearch);
8806
+ delete searchElement._debouncedSearch;
8807
+ }
8808
+ // --- 2. Remove page size dropdown event listener ---
8809
+ if (this._sizeElement && this._sizeElement.onchange) {
8810
+ this._sizeElement.onchange = null;
8811
+ }
8812
+ // --- 3. Remove all pagination button event listeners ---
8813
+ if (this._paginationElement) {
8814
+ // Remove all child nodes (buttons) to ensure no lingering listeners
8815
+ while (this._paginationElement.firstChild) {
8816
+ this._paginationElement.removeChild(this._paginationElement.firstChild);
8817
+ }
8818
+ }
8819
+ // --- 4. Dispose of handler objects (checkbox, sort) ---
8820
+ // KTDataTableCheckboxAPI does not have a dispose method, but we can remove header checkbox listener
8821
+ if (this._checkbox && typeof this._checkbox.dispose === 'function') {
8822
+ this._checkbox.dispose();
8823
+ }
8824
+ else {
8825
+ // Remove header checkbox event listener if possible
8826
+ var headerCheckElement = this._element.querySelector(this._config.attributes.check);
8827
+ if (headerCheckElement) {
8828
+ headerCheckElement.replaceWith(headerCheckElement.cloneNode(true));
8829
+ }
8830
+ }
8831
+ // KTDataTableSortAPI does not have a dispose method, but we can remove th click listeners by replacing them
8832
+ if (this._theadElement) {
8833
+ var ths = this._theadElement.querySelectorAll('th');
8834
+ ths.forEach(function (th) {
8835
+ th.replaceWith(th.cloneNode(true));
8836
+ });
8837
+ }
8838
+ // --- 5. Remove spinner DOM node if it exists ---
8839
+ var spinner = this._element.querySelector(this._config.attributes.spinner);
8840
+ if (spinner && spinner.parentNode) {
8841
+ spinner.parentNode.removeChild(spinner);
8842
+ }
8843
+ this._element.classList.remove(this._config.loadingClass);
8844
+ // --- 6. Remove instance reference from the DOM element ---
8845
+ if (this._element.instance) {
8846
+ delete this._element.instance;
8847
+ }
8848
+ // --- 7. (Optional) Clear localStorage state ---
8849
+ // Uncomment the following line if you want to clear state on dispose:
8850
+ // this._deleteState();
8698
8851
  };
8699
8852
  KTDataTable.prototype._debounce = function (func, wait) {
8700
8853
  var timeout;
@@ -8830,13 +8983,12 @@ var KTDataTable = /** @class */ (function (_super) {
8830
8983
  };
8831
8984
  /**
8832
8985
  * Create KTDataTable instances for all elements with a data-kt-datatable="true" attribute.
8833
- *
8834
- * This function should be called after the control(s) have been
8835
- * loaded and parsed by the browser. It will create instances of
8836
- * KTDataTable for all elements with a data-kt-datatable="true" attribute.
8986
+ * This function is now browser-guarded and must be called explicitly.
8837
8987
  */
8838
8988
  KTDataTable.createInstances = function () {
8839
8989
  var _this = this;
8990
+ if (typeof document === 'undefined')
8991
+ return;
8840
8992
  var elements = document.querySelectorAll('[data-kt-datatable="true"]');
8841
8993
  elements.forEach(function (element) {
8842
8994
  if (element.hasAttribute('data-kt-datatable') &&
@@ -8861,11 +9013,11 @@ var KTDataTable = /** @class */ (function (_super) {
8861
9013
  };
8862
9014
  /**
8863
9015
  * Initializes all KTDataTable instances on the page.
8864
- *
8865
- * This function should be called after the control(s) have been
8866
- * loaded and parsed by the browser.
9016
+ * This function is now browser-guarded and must be called explicitly.
8867
9017
  */
8868
9018
  KTDataTable.init = function () {
9019
+ if (typeof document === 'undefined')
9020
+ return;
8869
9021
  // Create instances of KTDataTable for all elements with a
8870
9022
  // data-kt-datatable="true" attribute
8871
9023
  KTDataTable.createInstances();
@@ -8923,8 +9075,16 @@ var KTDataTable = /** @class */ (function (_super) {
8923
9075
  return KTDataTable;
8924
9076
  }(component_1.default));
8925
9077
  exports.KTDataTable = KTDataTable;
8926
- if (typeof window !== 'undefined') {
8927
- window.KTDataTable = KTDataTable;
9078
+ /**
9079
+ * NOTE: This module is now PURE. No side effects or DOM/global assignments occur on import.
9080
+ * To auto-initialize all datatables on the page, call the exported `initAllDataTables()` function explicitly in the browser.
9081
+ */
9082
+ function initAllDataTables() {
9083
+ if (typeof document !== 'undefined') {
9084
+ KTDataTable.createInstances();
9085
+ // Optionally assign to window for legacy support
9086
+ window.KTDataTable = KTDataTable;
9087
+ }
8928
9088
  }
8929
9089
 
8930
9090
 
@@ -9993,8 +10153,11 @@ var KTSelectSearch = /** @class */ (function () {
9993
10153
  // Clear highlights when an option is selected - ATTACH TO ORIGINAL SELECT (standard 'change' event)
9994
10154
  this._select.getElement().addEventListener('change', function () {
9995
10155
  _this.clearSearch();
9996
- // Close dropdown if configured to do so
9997
- _this._select.closeDropdown();
10156
+ // Close dropdown only for single select mode
10157
+ // Keep dropdown open for multiple select mode to allow additional selections
10158
+ if (!_this._select.getConfig().multiple) {
10159
+ _this._select.closeDropdown();
10160
+ }
9998
10161
  });
9999
10162
  // Consolidated 'dropdown.show' event listener - ATTACH TO WRAPPER
10000
10163
  this._select.getWrapperElement().addEventListener('dropdown.show', function () {
@@ -10020,6 +10183,7 @@ var KTSelectSearch = /** @class */ (function () {
10020
10183
  (_a = _this._searchInput) === null || _a === void 0 ? void 0 : _a.focus(); // Focus search input
10021
10184
  }, 50); // Delay to ensure dropdown is visible
10022
10185
  }
10186
+ _this._select.updateSelectAllButtonState();
10023
10187
  });
10024
10188
  }
10025
10189
  }
@@ -10038,6 +10202,11 @@ var KTSelectSearch = /** @class */ (function () {
10038
10202
  KTSelectSearch.prototype._handleSearchKeyDown = function (event) {
10039
10203
  var key = event.key;
10040
10204
  switch (key) {
10205
+ case ' ': // Spacebar
10206
+ // Do nothing, allow space to be typed into the input
10207
+ // Stop propagation to prevent parent handlers from processing this event
10208
+ event.stopPropagation();
10209
+ break;
10041
10210
  case 'ArrowDown':
10042
10211
  event.preventDefault();
10043
10212
  this._focusManager.focusNext();
@@ -10155,6 +10324,7 @@ var KTSelectSearch = /** @class */ (function () {
10155
10324
  var visibleCount = (0, utils_1.filterOptions)(options, query, config, dropdownElement, function (count) {
10156
10325
  return _this._handleNoResults(count);
10157
10326
  });
10327
+ this._select.updateSelectAllButtonState();
10158
10328
  };
10159
10329
  /**
10160
10330
  * Reset all options to their original state
@@ -10182,6 +10352,7 @@ var KTSelectSearch = /** @class */ (function () {
10182
10352
  }
10183
10353
  });
10184
10354
  this._clearNoResultsMessage(); // Ensure no results message is cleared when resetting
10355
+ this._select.updateSelectAllButtonState();
10185
10356
  };
10186
10357
  KTSelectSearch.prototype._handleNoResults = function (visibleOptionsCount) {
10187
10358
  var _a, _b;
@@ -11391,6 +11562,8 @@ var KTSelect = /** @class */ (function (_super) {
11391
11562
  _this._tagsModule = null;
11392
11563
  _this._dropdownModule = null;
11393
11564
  _this._loadMoreIndicator = null;
11565
+ _this._selectAllButton = null;
11566
+ _this._selectAllButtonToggle = null;
11394
11567
  _this._typeToSearchBuffer = new utils_1.TypeToSearchBuffer();
11395
11568
  _this._mutationObserver = null;
11396
11569
  // Search debounce timeout
@@ -11671,6 +11844,10 @@ var KTSelect = /** @class */ (function (_super) {
11671
11844
  this._updateDisplayAndAriaAttributes();
11672
11845
  this.updateSelectedOptionDisplay();
11673
11846
  this._setAriaAttributes();
11847
+ // Update select all button state
11848
+ this.updateSelectAllButtonState();
11849
+ // Focus the first selected option or first option if nothing selected
11850
+ this._focusSelectedOption();
11674
11851
  // Attach event listeners after all modules are initialized
11675
11852
  this._attachEventListeners();
11676
11853
  this._observeNativeSelect();
@@ -11709,6 +11886,11 @@ var KTSelect = /** @class */ (function (_super) {
11709
11886
  var searchElement = templates_1.defaultTemplates.search(this._config);
11710
11887
  dropdownElement.appendChild(searchElement);
11711
11888
  }
11889
+ // Add select all button if needed
11890
+ if (this._config.multiple && this._config.enableSelectAll) {
11891
+ var selectAllElement = templates_1.defaultTemplates.selectAll(this._config);
11892
+ dropdownElement.appendChild(selectAllElement);
11893
+ }
11712
11894
  // Create options container using template
11713
11895
  var optionsContainer = templates_1.defaultTemplates.options(this._config);
11714
11896
  // Add each option directly to the container
@@ -11752,6 +11934,7 @@ var KTSelect = /** @class */ (function (_super) {
11752
11934
  if (!this._searchInputElement) {
11753
11935
  this._searchInputElement = this._displayElement;
11754
11936
  }
11937
+ this._selectAllButton = this._wrapperElement.querySelector('[data-kt-select-select-all]');
11755
11938
  this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
11756
11939
  };
11757
11940
  /**
@@ -11762,6 +11945,12 @@ var KTSelect = /** @class */ (function (_super) {
11762
11945
  document.addEventListener('click', this._handleDocumentClick.bind(this));
11763
11946
  // Dropdown option click events
11764
11947
  this._eventManager.addListener(this._dropdownContentElement, 'click', this._handleDropdownOptionClick.bind(this));
11948
+ if (this._selectAllButton) {
11949
+ this._selectAllButtonToggle = this._selectAllButton.querySelector('button');
11950
+ if (this._selectAllButtonToggle) {
11951
+ this._eventManager.addListener(this._selectAllButtonToggle, 'click', this._handleSelectAllClick.bind(this));
11952
+ }
11953
+ }
11765
11954
  // Attach centralized keyboard handler to the wrapper element.
11766
11955
  // Events from focusable children like _displayElement or _searchInputElement (if present) will bubble up.
11767
11956
  if (this._wrapperElement) {
@@ -11927,6 +12116,8 @@ var KTSelect = /** @class */ (function (_super) {
11927
12116
  this._fireEvent('show');
11928
12117
  // Update ARIA states
11929
12118
  this._setAriaAttributes();
12119
+ // Update select all button state
12120
+ this.updateSelectAllButtonState();
11930
12121
  // Focus the first selected option or first option if nothing selected
11931
12122
  this._focusSelectedOption();
11932
12123
  };
@@ -12154,6 +12345,8 @@ var KTSelect = /** @class */ (function (_super) {
12154
12345
  this._state.setSelectedOptions([]);
12155
12346
  this.updateSelectedOptionDisplay();
12156
12347
  this._updateSelectedOptionClass();
12348
+ // Update select all button state
12349
+ this.updateSelectAllButtonState();
12157
12350
  // Dispatch change event
12158
12351
  this._dispatchEvent('change');
12159
12352
  this._fireEvent('change');
@@ -12408,6 +12601,7 @@ var KTSelect = /** @class */ (function (_super) {
12408
12601
  // Update option classes without re-rendering the dropdown content
12409
12602
  this._updateSelectedOptionClass();
12410
12603
  // For single select mode, always close the dropdown after selection
12604
+ // For multiple select mode, keep the dropdown open to allow multiple selections
12411
12605
  if (!this._config.multiple) {
12412
12606
  if (this._config.debug)
12413
12607
  console.log('About to call closeDropdown() for single select mode - always close after selection');
@@ -12415,8 +12609,9 @@ var KTSelect = /** @class */ (function (_super) {
12415
12609
  }
12416
12610
  else {
12417
12611
  if (this._config.debug)
12418
- console.log('About to call closeDropdown() for multiple select');
12419
- this.closeDropdown();
12612
+ console.log('Multiple select mode - keeping dropdown open for additional selections');
12613
+ // Don't close dropdown in multiple select mode to allow multiple selections
12614
+ this.updateSelectAllButtonState();
12420
12615
  }
12421
12616
  // Dispatch custom change event with additional data
12422
12617
  this._dispatchEvent('change', {
@@ -12519,6 +12714,7 @@ var KTSelect = /** @class */ (function (_super) {
12519
12714
  if (_this._searchModule) {
12520
12715
  _this._searchModule.refreshAfterSearch();
12521
12716
  }
12717
+ _this.updateSelectAllButtonState();
12522
12718
  })
12523
12719
  .catch(function (error) {
12524
12720
  console.error('Error updating search results:', error);
@@ -12702,7 +12898,8 @@ var KTSelect = /** @class */ (function (_super) {
12702
12898
  }
12703
12899
  // Proceed with selection if not handled above
12704
12900
  this.selectFocusedOption();
12705
- // Close dropdown if configured to do so (for new selections)
12901
+ // Close dropdown only for single select mode (for new selections)
12902
+ // Keep dropdown open for multiple select mode to allow additional selections
12706
12903
  if (!this._config.multiple) {
12707
12904
  // This will also be true for the case handled above, but closeDropdown is idempotent.
12708
12905
  // However, the break above prevents this from being reached for that specific case.
@@ -12822,6 +13019,57 @@ var KTSelect = /** @class */ (function (_super) {
12822
13019
  this._state.setSelectedOptions(this._config.multiple ? selected : selected[0] || '');
12823
13020
  this.updateSelectedOptionDisplay();
12824
13021
  this._updateSelectedOptionClass();
13022
+ this.updateSelectAllButtonState();
13023
+ };
13024
+ KTSelect.prototype._handleSelectAllClick = function (event) {
13025
+ event.preventDefault();
13026
+ event.stopPropagation();
13027
+ var visibleOptions = this._focusManager
13028
+ .getVisibleOptions()
13029
+ .filter(function (opt) { return opt.getAttribute('aria-disabled') !== 'true'; });
13030
+ if (visibleOptions.length === 0)
13031
+ return;
13032
+ var visibleValues = visibleOptions.map(function (opt) { return opt.dataset.value; });
13033
+ var selectedValues = new Set(this.getSelectedOptions());
13034
+ var isAllSelected = visibleOptions.every(function (opt) {
13035
+ return selectedValues.has(opt.dataset.value);
13036
+ });
13037
+ if (isAllSelected) {
13038
+ // Deselect all visible
13039
+ visibleValues.forEach(function (value) { return selectedValues.delete(value); });
13040
+ }
13041
+ else {
13042
+ // Select all visible
13043
+ visibleValues.forEach(function (value) { return selectedValues.add(value); });
13044
+ }
13045
+ this._state.setSelectedOptions(Array.from(selectedValues));
13046
+ this.updateSelectedOptionDisplay();
13047
+ this._updateSelectedOptionClass();
13048
+ this.updateSelectAllButtonState();
13049
+ this._dispatchEvent('change');
13050
+ this._fireEvent('change');
13051
+ };
13052
+ KTSelect.prototype.updateSelectAllButtonState = function () {
13053
+ if (!this._config.multiple ||
13054
+ !this._config.enableSelectAll ||
13055
+ !this._selectAllButtonToggle) {
13056
+ return;
13057
+ }
13058
+ var visibleOptions = this._focusManager
13059
+ .getVisibleOptions()
13060
+ .filter(function (opt) { return opt.getAttribute('aria-disabled') !== 'true'; });
13061
+ if (visibleOptions.length === 0) {
13062
+ this._selectAllButton.style.display = 'none';
13063
+ return;
13064
+ }
13065
+ this._selectAllButton.style.display = '';
13066
+ var selectedValues = new Set(this.getSelectedOptions());
13067
+ var isAllSelected = visibleOptions.every(function (opt) {
13068
+ return selectedValues.has(opt.dataset.value);
13069
+ });
13070
+ this._selectAllButtonToggle.textContent = isAllSelected
13071
+ ? this._config.clearAllText
13072
+ : this._config.selectAllText;
12825
13073
  };
12826
13074
  /**
12827
13075
  * ========================================================================
@@ -15233,12 +15481,22 @@ var KTToast = /** @class */ (function (_super) {
15233
15481
  /**
15234
15482
  * Close and remove all active toasts.
15235
15483
  */
15236
- KTToast.clearAll = function () {
15484
+ KTToast.clearAll = function (clearContainers) {
15485
+ if (clearContainers === void 0) { clearContainers = false; }
15237
15486
  for (var _i = 0, _a = Array.from(this.toasts.keys()); _i < _a.length; _i++) {
15238
15487
  var id = _a[_i];
15239
15488
  console.log('clearAll:', id);
15240
15489
  this.close(id);
15241
15490
  }
15491
+ if (clearContainers) {
15492
+ // Remove all containers from the DOM.
15493
+ this.containerMap.forEach(function (container, position) {
15494
+ container.remove();
15495
+ console.log('clearAll: removed container for position', position);
15496
+ });
15497
+ // Clear containerMap to prevent stale references.
15498
+ this.containerMap.clear();
15499
+ }
15242
15500
  };
15243
15501
  /**
15244
15502
  * Close a toast by ID or instance.
@@ -16147,6 +16405,7 @@ exports.coreTemplateStrings = {
16147
16405
  loading: "<li class=\"kt-select-loading {{class}}\" role=\"status\" aria-live=\"polite\"></li>",
16148
16406
  tag: "<div data-kt-select-tag=\"true\" class=\"kt-select-tag {{class}}\"></div>",
16149
16407
  loadMore: "<li class=\"kt-select-load-more {{class}}\" data-kt-select-load-more=\"true\"></li>",
16408
+ selectAll: "<div data-kt-select-select-all class=\"kt-select-select-all\"><button type=\"button\" class=\"kt-select-select-all-button\">{{text}}</button></div>",
16150
16409
  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>",
16151
16410
  };
16152
16411
  /**
@@ -16420,6 +16679,11 @@ exports.defaultTemplates = {
16420
16679
  return element;
16421
16680
  }
16422
16681
  },
16682
+ selectAll: function (config) {
16683
+ var template = getTemplateStrings(config).selectAll;
16684
+ var element = stringToElement(template.replace('{{text}}', config.selectAllText || 'Select All'));
16685
+ return element;
16686
+ },
16423
16687
  };
16424
16688
 
16425
16689
 
@@ -17582,6 +17846,7 @@ exports.DefaultConfig = {
17582
17846
  // Multi-Select Display
17583
17847
  selectAllText: 'Select all', // Text for the "Select All" option (if implemented)
17584
17848
  clearAllText: 'Clear all', // Text for the "Clear All" option (if implemented)
17849
+ enableSelectAll: false, // Enable/disable "Select All" button for multi-select
17585
17850
  showSelectedCount: true, // Show the number of selected options in multi-select mode
17586
17851
  renderSelected: null, // Custom function to render the selected value(s) in the display area
17587
17852
  // Accessibility & Usability