@keenthemes/ktui 1.0.19 → 1.0.21

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 (111) hide show
  1. package/dist/ktui.js +690 -166
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +165 -31
  5. package/examples/image-input/file-upload-example.html +189 -0
  6. package/examples/select/remote-data_.html +5 -0
  7. package/examples/select/test-optimizations.html +227 -0
  8. package/examples/select/test-remote-search.html +151 -0
  9. package/examples/sticky/README.md +158 -0
  10. package/examples/sticky/debug-sticky.html +144 -0
  11. package/examples/sticky/test-runner.html +175 -0
  12. package/examples/sticky/test-sticky-logic.js +369 -0
  13. package/examples/sticky/test-sticky-positioning.html +386 -0
  14. package/examples/toast/example.html +52 -0
  15. package/lib/cjs/components/component.js +59 -5
  16. package/lib/cjs/components/component.js.map +1 -1
  17. package/lib/cjs/components/datatable/datatable-sort.js +4 -0
  18. package/lib/cjs/components/datatable/datatable-sort.js.map +1 -1
  19. package/lib/cjs/components/datatable/datatable.js +79 -12
  20. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  21. package/lib/cjs/components/image-input/image-input.js +10 -2
  22. package/lib/cjs/components/image-input/image-input.js.map +1 -1
  23. package/lib/cjs/components/select/combobox.js +50 -20
  24. package/lib/cjs/components/select/combobox.js.map +1 -1
  25. package/lib/cjs/components/select/config.js +1 -0
  26. package/lib/cjs/components/select/config.js.map +1 -1
  27. package/lib/cjs/components/select/dropdown.js +4 -2
  28. package/lib/cjs/components/select/dropdown.js.map +1 -1
  29. package/lib/cjs/components/select/index.js.map +1 -1
  30. package/lib/cjs/components/select/option.js +2 -1
  31. package/lib/cjs/components/select/option.js.map +1 -1
  32. package/lib/cjs/components/select/remote.js +50 -50
  33. package/lib/cjs/components/select/remote.js.map +1 -1
  34. package/lib/cjs/components/select/search.js +15 -5
  35. package/lib/cjs/components/select/search.js.map +1 -1
  36. package/lib/cjs/components/select/select.js +273 -32
  37. package/lib/cjs/components/select/select.js.map +1 -1
  38. package/lib/cjs/components/select/tags.js +3 -1
  39. package/lib/cjs/components/select/tags.js.map +1 -1
  40. package/lib/cjs/components/select/templates.js +6 -0
  41. package/lib/cjs/components/select/templates.js.map +1 -1
  42. package/lib/cjs/components/select/utils.js +23 -10
  43. package/lib/cjs/components/select/utils.js.map +1 -1
  44. package/lib/cjs/components/stepper/stepper.js +59 -12
  45. package/lib/cjs/components/stepper/stepper.js.map +1 -1
  46. package/lib/cjs/components/sticky/sticky.js +52 -14
  47. package/lib/cjs/components/sticky/sticky.js.map +1 -1
  48. package/lib/esm/components/component.js +59 -5
  49. package/lib/esm/components/component.js.map +1 -1
  50. package/lib/esm/components/datatable/datatable-sort.js +4 -0
  51. package/lib/esm/components/datatable/datatable-sort.js.map +1 -1
  52. package/lib/esm/components/datatable/datatable.js +78 -12
  53. package/lib/esm/components/datatable/datatable.js.map +1 -1
  54. package/lib/esm/components/image-input/image-input.js +10 -2
  55. package/lib/esm/components/image-input/image-input.js.map +1 -1
  56. package/lib/esm/components/select/combobox.js +50 -20
  57. package/lib/esm/components/select/combobox.js.map +1 -1
  58. package/lib/esm/components/select/config.js +1 -0
  59. package/lib/esm/components/select/config.js.map +1 -1
  60. package/lib/esm/components/select/dropdown.js +4 -2
  61. package/lib/esm/components/select/dropdown.js.map +1 -1
  62. package/lib/esm/components/select/index.js +1 -1
  63. package/lib/esm/components/select/index.js.map +1 -1
  64. package/lib/esm/components/select/option.js +2 -1
  65. package/lib/esm/components/select/option.js.map +1 -1
  66. package/lib/esm/components/select/remote.js +50 -50
  67. package/lib/esm/components/select/remote.js.map +1 -1
  68. package/lib/esm/components/select/search.js +16 -6
  69. package/lib/esm/components/select/search.js.map +1 -1
  70. package/lib/esm/components/select/select.js +273 -32
  71. package/lib/esm/components/select/select.js.map +1 -1
  72. package/lib/esm/components/select/tags.js +3 -1
  73. package/lib/esm/components/select/tags.js.map +1 -1
  74. package/lib/esm/components/select/templates.js +6 -0
  75. package/lib/esm/components/select/templates.js.map +1 -1
  76. package/lib/esm/components/select/utils.js +23 -10
  77. package/lib/esm/components/select/utils.js.map +1 -1
  78. package/lib/esm/components/stepper/stepper.js +59 -12
  79. package/lib/esm/components/stepper/stepper.js.map +1 -1
  80. package/lib/esm/components/sticky/sticky.js +52 -14
  81. package/lib/esm/components/sticky/sticky.js.map +1 -1
  82. package/package.json +2 -2
  83. package/src/components/component.ts +19 -4
  84. package/src/components/datatable/datatable-sort.ts +6 -0
  85. package/src/components/datatable/datatable.ts +98 -15
  86. package/src/components/datatable/types.ts +5 -1
  87. package/src/components/image-input/image-input.ts +11 -2
  88. package/src/components/image-input/types.ts +1 -0
  89. package/src/components/input/input-group.css +1 -1
  90. package/src/components/input/input.css +1 -1
  91. package/src/components/scrollable/scrollable.css +3 -3
  92. package/src/components/select/combobox.ts +84 -34
  93. package/src/components/select/config.ts +2 -0
  94. package/src/components/select/dropdown.ts +20 -11
  95. package/src/components/select/index.ts +6 -1
  96. package/src/components/select/option.ts +7 -6
  97. package/src/components/select/remote.ts +51 -52
  98. package/src/components/select/search.ts +59 -44
  99. package/src/components/select/select.css +26 -17
  100. package/src/components/select/select.ts +472 -101
  101. package/src/components/select/tags.ts +9 -3
  102. package/src/components/select/templates.ts +10 -0
  103. package/src/components/select/utils.ts +55 -20
  104. package/src/components/select/variants.css +0 -1
  105. package/src/components/stepper/stepper.ts +2 -2
  106. package/src/components/sticky/sticky.ts +47 -16
  107. package/src/components/sticky/types.ts +3 -0
  108. package/src/components/table/table.css +1 -1
  109. package/src/components/textarea/textarea.css +1 -1
  110. package/src/components/toast/toast.css +84 -47
  111. package/src/components/toast/types.ts +3 -0
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,29 @@ 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())
2514
+ .filter(function (callable) {
2515
+ return typeof callable === 'function';
2516
+ })
2517
+ .map(function (callable) {
2518
+ return Promise.resolve(callable(payload));
2519
+ }))];
2520
+ case 1:
2521
+ _a.sent();
2522
+ return [2 /*return*/];
2523
+ }
2524
+ });
2424
2525
  });
2425
2526
  };
2426
2527
  KTComponent.prototype._dispatchEvent = function (eventType, payload) {
@@ -2542,6 +2643,7 @@ var KTImageInput = /** @class */ (function (_super) {
2542
2643
  hiddenClass: 'hidden',
2543
2644
  };
2544
2645
  _this._previewUrl = '';
2646
+ _this._selectedFile = null;
2545
2647
  if (data_1.default.has(element, _this._name))
2546
2648
  return _this;
2547
2649
  _this._init(element);
@@ -2580,6 +2682,7 @@ var KTImageInput = /** @class */ (function (_super) {
2580
2682
  _this._previewElement.style.backgroundImage = "url(".concat(reader.result, ")");
2581
2683
  };
2582
2684
  reader.readAsDataURL(this._inputElement.files[0]);
2685
+ this._selectedFile = this._inputElement.files[0];
2583
2686
  this._inputElement.value = '';
2584
2687
  this._hiddenElement.value = '';
2585
2688
  this._lastMode = 'new';
@@ -2610,6 +2713,7 @@ var KTImageInput = /** @class */ (function (_super) {
2610
2713
  }
2611
2714
  this._inputElement.value = '';
2612
2715
  this._hiddenElement.value = '';
2716
+ this._selectedFile = null;
2613
2717
  this._lastMode = 'saved';
2614
2718
  }
2615
2719
  else if (this._lastMode == 'saved') {
@@ -2619,6 +2723,7 @@ var KTImageInput = /** @class */ (function (_super) {
2619
2723
  this._element.classList.add('empty');
2620
2724
  this._hiddenElement.value = '1';
2621
2725
  this._inputElement.value = '';
2726
+ this._selectedFile = null;
2622
2727
  this._lastMode = 'placeholder';
2623
2728
  }
2624
2729
  else if (this._lastMode == 'placeholder') {
@@ -2632,6 +2737,7 @@ var KTImageInput = /** @class */ (function (_super) {
2632
2737
  }
2633
2738
  this._inputElement.value = '';
2634
2739
  this._hiddenElement.value = '';
2740
+ this._selectedFile = null;
2635
2741
  this._lastMode = 'saved';
2636
2742
  }
2637
2743
  this._fireEvent('remove');
@@ -2656,10 +2762,10 @@ var KTImageInput = /** @class */ (function (_super) {
2656
2762
  this._previewUrl = url.replace(/(url\(|\)|")/g, '');
2657
2763
  };
2658
2764
  KTImageInput.prototype.isEmpty = function () {
2659
- return this._inputElement.value.length === 0;
2765
+ return this._selectedFile === null;
2660
2766
  };
2661
2767
  KTImageInput.prototype.isChanged = function () {
2662
- return this._inputElement.value.length > 0;
2768
+ return this._selectedFile !== null;
2663
2769
  };
2664
2770
  KTImageInput.prototype.remove = function () {
2665
2771
  this._remove();
@@ -2673,6 +2779,9 @@ var KTImageInput = /** @class */ (function (_super) {
2673
2779
  KTImageInput.prototype.getPreviewUrl = function () {
2674
2780
  return this._getPreviewUrl();
2675
2781
  };
2782
+ KTImageInput.prototype.getSelectedFile = function () {
2783
+ return this._selectedFile;
2784
+ };
2676
2785
  KTImageInput.getInstance = function (element) {
2677
2786
  if (!element)
2678
2787
  return null;
@@ -2746,7 +2855,10 @@ var KTSticky = /** @class */ (function (_super) {
2746
2855
  name: '',
2747
2856
  class: '',
2748
2857
  top: '',
2858
+ middle: false,
2859
+ bottom: '',
2749
2860
  start: '',
2861
+ center: false,
2750
2862
  end: '',
2751
2863
  width: '',
2752
2864
  zindex: '',
@@ -2889,7 +3001,10 @@ var KTSticky = /** @class */ (function (_super) {
2889
3001
  return false;
2890
3002
  var width = this._getOption('width');
2891
3003
  var top = this._getOption('top');
3004
+ var middle = this._getOption('middle');
3005
+ var bottom = this._getOption('bottom');
2892
3006
  var start = this._getOption('start');
3007
+ var center = this._getOption('center');
2893
3008
  var end = this._getOption('end');
2894
3009
  var height = this._calculateHeight();
2895
3010
  var zindex = this._getOption('zindex');
@@ -2907,29 +3022,56 @@ var KTSticky = /** @class */ (function (_super) {
2907
3022
  }
2908
3023
  this._element.style.width = "".concat(Math.round(parseFloat(width)), "px");
2909
3024
  }
2910
- if (top) {
2911
- this._element.style.top = "".concat(top, "px");
3025
+ if (middle === true) {
3026
+ this._element.style.insetBlockStart = "50%";
2912
3027
  }
2913
- if (start) {
2914
- if (start === 'auto') {
2915
- var offsetLeft = dom_1.default.offset(this._element).left;
2916
- if (offsetLeft >= 0) {
2917
- this._element.style.insetInlineStart = "".concat(offsetLeft, "px");
3028
+ else {
3029
+ if (top) {
3030
+ if (top === 'auto') {
3031
+ this._element.style.insetBlockStart = "0px";
3032
+ }
3033
+ else {
3034
+ this._element.style.insetBlockStart = "".concat(top, "px");
2918
3035
  }
2919
3036
  }
2920
3037
  else {
2921
- this._element.style.insetInlineStart = "".concat(start, "px");
3038
+ if (bottom) {
3039
+ if (bottom === 'auto') {
3040
+ this._element.style.insetBlockEnd = "0px";
3041
+ }
3042
+ else {
3043
+ this._element.style.insetBlockEnd = "".concat(bottom, "px");
3044
+ }
3045
+ }
2922
3046
  }
2923
3047
  }
2924
- if (end) {
2925
- if (end === 'auto') {
2926
- var offseRight = dom_1.default.offset(this._element).right;
2927
- if (offseRight >= 0) {
2928
- this._element.style.insetInlineEnd = "".concat(offseRight, "px");
3048
+ if (center === true) {
3049
+ this._element.style.insetInlineStart = "50%";
3050
+ }
3051
+ else {
3052
+ if (start) {
3053
+ if (start === 'auto') {
3054
+ var offsetLeft = dom_1.default.offset(this._element).left;
3055
+ if (offsetLeft >= 0) {
3056
+ this._element.style.insetInlineStart = "".concat(offsetLeft, "px");
3057
+ }
3058
+ }
3059
+ else {
3060
+ this._element.style.insetInlineStart = "".concat(start, "px");
2929
3061
  }
2930
3062
  }
2931
3063
  else {
2932
- this._element.style.insetInlineEnd = "".concat(end, "px");
3064
+ if (end) {
3065
+ if (end === 'auto') {
3066
+ var offsetRight = dom_1.default.offset(this._element).right;
3067
+ if (offsetRight >= 0) {
3068
+ this._element.style.insetInlineEnd = "".concat(offsetRight, "px");
3069
+ }
3070
+ }
3071
+ else {
3072
+ this._element.style.insetInlineEnd = "".concat(end, "px");
3073
+ }
3074
+ }
2933
3075
  }
2934
3076
  }
2935
3077
  if (zindex) {
@@ -2950,6 +3092,11 @@ var KTSticky = /** @class */ (function (_super) {
2950
3092
  if (!this._element)
2951
3093
  return;
2952
3094
  this._element.style.top = '';
3095
+ this._element.style.bottom = '';
3096
+ this._element.style.insetInlineStart = '';
3097
+ this._element.style.insetInlineEnd = '';
3098
+ this._element.style.insetBlockStart = '';
3099
+ this._element.style.insetBlockEnd = '';
2953
3100
  this._element.style.width = '';
2954
3101
  this._element.style.left = '';
2955
3102
  this._element.style.right = '';
@@ -3271,11 +3418,9 @@ var KTSelectRemote = /** @class */ (function () {
3271
3418
  console.log("Mapping fields: value=".concat(valueField, ", label=").concat(labelField));
3272
3419
  if (this._config.debug)
3273
3420
  console.log('Item data:', JSON.stringify(item).substring(0, 200) + '...'); // Trimmed for readability
3274
- // Extract values using dot notation if needed
3421
+ // Extract values using improved getValue function
3275
3422
  var getValue = function (obj, path) {
3276
- if (!path)
3277
- return null;
3278
- if (!obj)
3423
+ if (!path || !obj)
3279
3424
  return null;
3280
3425
  try {
3281
3426
  // Handle dot notation to access nested properties
@@ -3304,65 +3449,67 @@ var KTSelectRemote = /** @class */ (function () {
3304
3449
  return null;
3305
3450
  }
3306
3451
  };
3307
- // Try to get a usable ID, with fallbacks
3452
+ // Get ID and ensure it's a string
3308
3453
  var id = getValue(item, valueField);
3309
- // Ensure id is always a proper string
3310
3454
  if (id === null || id === undefined) {
3311
- // If no ID found, check for id.value or item.id as fallbacks
3312
- if (item.id &&
3313
- typeof item.id === 'object' &&
3314
- 'value' in item.id &&
3315
- item.id.value) {
3316
- id = String(item.id.value);
3317
- if (this._config.debug)
3318
- console.log("Using id.value as fallback: ".concat(id));
3319
- }
3320
- else if (item.id) {
3321
- id = String(item.id);
3322
- if (this._config.debug)
3323
- console.log("Using direct item.id as fallback: ".concat(id));
3324
- }
3325
- else {
3326
- // If no ID found at all, use the title instead (will be extracted below)
3327
- if (this._config.debug)
3328
- console.log("No ID found, will use title as fallback");
3329
- id = null;
3455
+ // Try common fallback fields for ID
3456
+ var fallbackFields = ['id', 'value', 'key', 'pk'];
3457
+ for (var _i = 0, fallbackFields_1 = fallbackFields; _i < fallbackFields_1.length; _i++) {
3458
+ var field = fallbackFields_1[_i];
3459
+ if (item[field] !== null && item[field] !== undefined) {
3460
+ id = String(item[field]);
3461
+ if (this._config.debug)
3462
+ console.log("Using fallback field '".concat(field, "' for ID: ").concat(id));
3463
+ break;
3464
+ }
3330
3465
  }
3331
3466
  }
3332
- else if (typeof id === 'object') {
3333
- // If ID is an object, log the issue and set to null to use title fallback
3334
- console.warn("ID for path ".concat(valueField, " is an object, will use title fallback instead"));
3335
- id = null;
3336
- }
3337
3467
  else {
3338
- // Otherwise, ensure it's a string
3339
3468
  id = String(id);
3469
+ }
3470
+ // If still no ID, generate one
3471
+ if (!id) {
3472
+ id = "option-".concat(Math.random().toString(36).substr(2, 9));
3340
3473
  if (this._config.debug)
3341
- console.log("Final ID value: ".concat(id));
3474
+ console.log("Generated fallback ID: ".concat(id));
3342
3475
  }
3343
- // Try to get a usable title, with fallbacks
3476
+ // Get label with proper fallbacks
3344
3477
  var title = getValue(item, labelField);
3345
- title = title !== null ? String(title) : '';
3346
- if (this._config.debug)
3347
- console.log("Title/label field [".concat(labelField, "]:"), title);
3348
- // If title is still empty, try common field names
3349
3478
  if (!title) {
3350
- // Try common field names if the configured one doesn't work
3351
- if (item.name)
3352
- title = String(item.name);
3353
- else if (item.title)
3354
- title = String(item.title);
3355
- else if (item.label)
3356
- title = String(item.label);
3357
- else if (item.text)
3358
- title = String(item.text);
3479
+ // Try common fallback fields for title
3480
+ var fallbackFields = [
3481
+ 'name',
3482
+ 'title',
3483
+ 'label',
3484
+ 'text',
3485
+ 'displayName',
3486
+ 'description',
3487
+ ];
3488
+ for (var _a = 0, fallbackFields_2 = fallbackFields; _a < fallbackFields_2.length; _a++) {
3489
+ var field = fallbackFields_2[_a];
3490
+ if (item[field] !== null && item[field] !== undefined) {
3491
+ title = String(item[field]);
3492
+ if (this._config.debug)
3493
+ console.log("Using fallback field '".concat(field, "' for title: ").concat(title));
3494
+ break;
3495
+ }
3496
+ }
3497
+ }
3498
+ else {
3499
+ title = String(title);
3500
+ }
3501
+ // If still no title, use ID as fallback
3502
+ if (!title) {
3503
+ title = "Option ".concat(id);
3359
3504
  if (this._config.debug)
3360
- console.log('After fallback checks, title:', title);
3505
+ console.log("Using ID as fallback title: ".concat(title));
3361
3506
  }
3362
- // Create the option object with non-empty values
3507
+ // Create the option object with consistent structure
3363
3508
  var result = {
3364
- id: id || title || 'id-' + Math.random().toString(36).substr(2, 9), // Ensure we always have an ID
3365
- title: title || 'Unnamed option',
3509
+ id: id,
3510
+ title: title,
3511
+ selected: Boolean(item.selected),
3512
+ disabled: Boolean(item.disabled),
3366
3513
  };
3367
3514
  if (this._config.debug)
3368
3515
  console.log('Final mapped item:', JSON.stringify(result));
@@ -5684,7 +5831,8 @@ var KTSelectOption = /** @class */ (function (_super) {
5684
5831
  // Ensure optionsConfig is initialized
5685
5832
  if (_this._globalConfig) {
5686
5833
  _this._globalConfig.optionsConfig = _this._globalConfig.optionsConfig || {};
5687
- _this._globalConfig.optionsConfig[element.value] = _this._config;
5834
+ _this._globalConfig.optionsConfig[element.value] =
5835
+ _this._config;
5688
5836
  // console.log('[KTSelectOption] Populating _globalConfig.optionsConfig for value', (element as HTMLInputElement).value, 'with:', JSON.parse(JSON.stringify(this._config)));
5689
5837
  // console.log('[KTSelectOption] _globalConfig.optionsConfig is now:', JSON.parse(JSON.stringify(this._globalConfig.optionsConfig)));
5690
5838
  }
@@ -6501,6 +6649,10 @@ function createSortHandler(config, theadElement, getState, setState, fireEvent,
6501
6649
  // If the sort class is not found, it's not a sortable column
6502
6650
  if (!header.querySelector(".".concat((_b = (_a = config.sort) === null || _a === void 0 ? void 0 : _a.classes) === null || _b === void 0 ? void 0 : _b.base)))
6503
6651
  return;
6652
+ // Check if sorting is disabled for this column
6653
+ var sortDisabled = header.getAttribute('data-kt-datatable-column-sort') === 'false';
6654
+ if (sortDisabled)
6655
+ return;
6504
6656
  var sortAttribute = header.getAttribute('data-kt-datatable-column-sort') ||
6505
6657
  header.getAttribute('data-kt-datatable-column');
6506
6658
  var sortField = sortAttribute
@@ -6587,7 +6739,8 @@ var KTSelectCombobox = /** @class */ (function () {
6587
6739
  */
6588
6740
  KTSelectCombobox.prototype._attachEventListeners = function () {
6589
6741
  this._removeEventListeners();
6590
- if (this._searchInputElement) { // Ensure element exists
6742
+ if (this._searchInputElement) {
6743
+ // Ensure element exists
6591
6744
  this._searchInputElement.addEventListener('input', this._boundInputHandler);
6592
6745
  }
6593
6746
  if (this._clearButtonElement) {
@@ -6612,7 +6765,8 @@ var KTSelectCombobox = /** @class */ (function () {
6612
6765
  var inputElement = event.target;
6613
6766
  var query = inputElement.value;
6614
6767
  this._toggleClearButtonVisibility(query);
6615
- if (!this._select.isDropdownOpen()) { // Use public getter
6768
+ if (!this._select.isDropdownOpen()) {
6769
+ // Use public getter
6616
6770
  this._select.openDropdown();
6617
6771
  }
6618
6772
  // For single select without displayTemplate, if user types, they are essentially clearing the previous selection text
@@ -6651,7 +6805,9 @@ var KTSelectCombobox = /** @class */ (function () {
6651
6805
  if (!this._clearButtonElement)
6652
6806
  return;
6653
6807
  var hasSelectedItems = this._select.getSelectedOptions().length > 0;
6654
- if (inputValue.length > 0 || (hasSelectedItems && (this._config.multiple || this._config.displayTemplate))) {
6808
+ if (inputValue.length > 0 ||
6809
+ (hasSelectedItems &&
6810
+ (this._config.multiple || this._config.displayTemplate))) {
6655
6811
  this._clearButtonElement.classList.remove('hidden');
6656
6812
  }
6657
6813
  else {
@@ -6683,41 +6839,67 @@ var KTSelectCombobox = /** @class */ (function () {
6683
6839
  if (this._valuesContainerElement) {
6684
6840
  this._valuesContainerElement.innerHTML = '';
6685
6841
  }
6686
- if (this._config.tags && this._valuesContainerElement) { // Combobox + Tags
6842
+ if (this._config.tags && this._valuesContainerElement) {
6843
+ // Combobox + Tags
6687
6844
  selectedOptions.forEach(function (value) {
6688
6845
  // Ensure value is properly escaped for querySelector
6689
- var optionElement = _this._select.getElement().querySelector("option[value=\"".concat(CSS.escape(value), "\"]"));
6846
+ var optionElement = _this._select
6847
+ .getElement()
6848
+ .querySelector("option[value=\"".concat(CSS.escape(value), "\"]"));
6690
6849
  if (optionElement) {
6691
6850
  var tagElement = templates_1.defaultTemplates.tag(optionElement, _this._config);
6692
6851
  _this._valuesContainerElement.appendChild(tagElement);
6693
6852
  }
6694
6853
  });
6695
6854
  this._searchInputElement.value = ''; // Input field is for typing new searches
6696
- this._searchInputElement.placeholder = selectedOptions.length > 0 ? '' : (this._config.placeholder || 'Select...');
6697
- }
6698
- else if (this._config.displayTemplate && this._valuesContainerElement) { // Combobox + DisplayTemplate (no tags)
6699
- this._valuesContainerElement.innerHTML = this._select.renderDisplayTemplateForSelected(selectedOptions);
6855
+ this._searchInputElement.placeholder =
6856
+ selectedOptions.length > 0
6857
+ ? ''
6858
+ : this._config.placeholder || 'Select...';
6859
+ }
6860
+ else if (this._config.displayTemplate && this._valuesContainerElement) {
6861
+ // Combobox + DisplayTemplate (no tags)
6862
+ this._valuesContainerElement.innerHTML =
6863
+ this._select.renderDisplayTemplateForSelected(selectedOptions);
6700
6864
  this._searchInputElement.value = ''; // Input field is for typing new searches
6701
- this._searchInputElement.placeholder = selectedOptions.length > 0 ? '' : (this._config.placeholder || 'Select...');
6865
+ this._searchInputElement.placeholder =
6866
+ selectedOptions.length > 0
6867
+ ? ''
6868
+ : this._config.placeholder || 'Select...';
6702
6869
  }
6703
- else if (this._config.multiple && this._valuesContainerElement) { // Combobox + Multiple (no tags, no display template)
6870
+ else if (this._config.multiple && this._valuesContainerElement) {
6871
+ // Combobox + Multiple (no tags, no display template)
6704
6872
  // For simplicity, join text. A proper tag implementation would be more complex here.
6705
- this._valuesContainerElement.innerHTML = selectedOptions.map(function (value) {
6706
- var optionEl = _this._select.getElement().querySelector("option[value=\"".concat(CSS.escape(value), "\"]"));
6873
+ this._valuesContainerElement.innerHTML = selectedOptions
6874
+ .map(function (value) {
6875
+ var optionEl = _this._select
6876
+ .getElement()
6877
+ .querySelector("option[value=\"".concat(CSS.escape(value), "\"]"));
6707
6878
  return optionEl ? optionEl.textContent : '';
6708
- }).join(', '); // Basic comma separation
6879
+ })
6880
+ .join(', '); // Basic comma separation
6709
6881
  this._searchInputElement.value = '';
6710
- this._searchInputElement.placeholder = selectedOptions.length > 0 ? '' : (this._config.placeholder || 'Select...');
6882
+ this._searchInputElement.placeholder =
6883
+ selectedOptions.length > 0
6884
+ ? ''
6885
+ : this._config.placeholder || 'Select...';
6711
6886
  }
6712
- else if (!this._config.multiple && selectedOptions.length > 0) { // Single select combobox: display selected option's text in the input
6887
+ else if (!this._config.multiple && selectedOptions.length > 0) {
6888
+ // Single select combobox: display selected option's text in the input
6713
6889
  var selectedValue = selectedOptions[0];
6714
- var optionElement = this._select.getElement().querySelector("option[value=\"".concat(CSS.escape(selectedValue), "\"]"));
6715
- this._searchInputElement.value = optionElement ? optionElement.textContent || '' : '';
6890
+ var optionElement = this._select
6891
+ .getElement()
6892
+ .querySelector("option[value=\"".concat(CSS.escape(selectedValue), "\"]"));
6893
+ this._searchInputElement.value = optionElement
6894
+ ? optionElement.textContent || ''
6895
+ : '';
6716
6896
  // placeholder is implicitly handled by input value for single select
6717
6897
  }
6718
- else { // No selection or not fitting above categories (e.g. single select, no items)
6898
+ else {
6899
+ // No selection or not fitting above categories (e.g. single select, no items)
6719
6900
  this._searchInputElement.value = '';
6720
- this._searchInputElement.placeholder = this._config.placeholder || 'Select...';
6901
+ this._searchInputElement.placeholder =
6902
+ this._config.placeholder || 'Select...';
6721
6903
  // _valuesContainerElement is already cleared if it exists
6722
6904
  }
6723
6905
  this._toggleClearButtonVisibility(this._searchInputElement.value);
@@ -7587,6 +7769,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
7587
7769
  };
7588
7770
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7589
7771
  exports.KTDataTable = void 0;
7772
+ exports.initAllDataTables = initAllDataTables;
7590
7773
  var component_1 = __webpack_require__(2658);
7591
7774
  var utils_1 = __webpack_require__(2599);
7592
7775
  var index_1 = __webpack_require__(8156);
@@ -7965,7 +8148,11 @@ var KTDataTable = /** @class */ (function (_super) {
7965
8148
  // Set search value
7966
8149
  if (searchElement) {
7967
8150
  searchElement.value =
7968
- search === undefined || search === null ? '' : typeof search === 'string' ? search : String(search);
8151
+ search === undefined || search === null
8152
+ ? ''
8153
+ : typeof search === 'string'
8154
+ ? search
8155
+ : String(search);
7969
8156
  }
7970
8157
  if (searchElement) {
7971
8158
  // Check if a debounced search function already exists
@@ -8372,7 +8559,8 @@ var KTDataTable = /** @class */ (function (_super) {
8372
8559
  }
8373
8560
  if (typeof columnDef.render === 'function') {
8374
8561
  var result = columnDef.render.call(_this, item[key], item, _this);
8375
- if (result instanceof HTMLElement || result instanceof DocumentFragment) {
8562
+ if (result instanceof HTMLElement ||
8563
+ result instanceof DocumentFragment) {
8376
8564
  td.appendChild(result);
8377
8565
  }
8378
8566
  else if (typeof result === 'string') {
@@ -8693,8 +8881,62 @@ var KTDataTable = /** @class */ (function (_super) {
8693
8881
  }
8694
8882
  return id;
8695
8883
  };
8884
+ /**
8885
+ * Clean up all event listeners, handlers, and DOM nodes created by this instance.
8886
+ * This method is called before re-rendering or when disposing the component.
8887
+ */
8696
8888
  KTDataTable.prototype._dispose = function () {
8697
- // Remove all event listeners and clean up resources
8889
+ // --- 1. Remove search input event listener (debounced) ---
8890
+ var tableId = this._tableId();
8891
+ var searchElement = document.querySelector("[data-kt-datatable-search=\"#".concat(tableId, "\"]"));
8892
+ if (searchElement && searchElement._debouncedSearch) {
8893
+ searchElement.removeEventListener('keyup', searchElement._debouncedSearch);
8894
+ delete searchElement._debouncedSearch;
8895
+ }
8896
+ // --- 2. Remove page size dropdown event listener ---
8897
+ if (this._sizeElement && this._sizeElement.onchange) {
8898
+ this._sizeElement.onchange = null;
8899
+ }
8900
+ // --- 3. Remove all pagination button event listeners ---
8901
+ if (this._paginationElement) {
8902
+ // Remove all child nodes (buttons) to ensure no lingering listeners
8903
+ while (this._paginationElement.firstChild) {
8904
+ this._paginationElement.removeChild(this._paginationElement.firstChild);
8905
+ }
8906
+ }
8907
+ // --- 4. Dispose of handler objects (checkbox, sort) ---
8908
+ // KTDataTableCheckboxAPI does not have a dispose method, but we can remove header checkbox listener
8909
+ if (this._checkbox &&
8910
+ typeof this._checkbox.dispose === 'function') {
8911
+ this._checkbox.dispose();
8912
+ }
8913
+ else {
8914
+ // Remove header checkbox event listener if possible
8915
+ var headerCheckElement = this._element.querySelector(this._config.attributes.check);
8916
+ if (headerCheckElement) {
8917
+ headerCheckElement.replaceWith(headerCheckElement.cloneNode(true));
8918
+ }
8919
+ }
8920
+ // KTDataTableSortAPI does not have a dispose method, but we can remove th click listeners by replacing them
8921
+ if (this._theadElement) {
8922
+ var ths = this._theadElement.querySelectorAll('th');
8923
+ ths.forEach(function (th) {
8924
+ th.replaceWith(th.cloneNode(true));
8925
+ });
8926
+ }
8927
+ // --- 5. Remove spinner DOM node if it exists ---
8928
+ var spinner = this._element.querySelector(this._config.attributes.spinner);
8929
+ if (spinner && spinner.parentNode) {
8930
+ spinner.parentNode.removeChild(spinner);
8931
+ }
8932
+ this._element.classList.remove(this._config.loadingClass);
8933
+ // --- 6. Remove instance reference from the DOM element ---
8934
+ if (this._element.instance) {
8935
+ delete this._element.instance;
8936
+ }
8937
+ // --- 7. (Optional) Clear localStorage state ---
8938
+ // Uncomment the following line if you want to clear state on dispose:
8939
+ // this._deleteState();
8698
8940
  };
8699
8941
  KTDataTable.prototype._debounce = function (func, wait) {
8700
8942
  var timeout;
@@ -8830,13 +9072,12 @@ var KTDataTable = /** @class */ (function (_super) {
8830
9072
  };
8831
9073
  /**
8832
9074
  * 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.
9075
+ * This function is now browser-guarded and must be called explicitly.
8837
9076
  */
8838
9077
  KTDataTable.createInstances = function () {
8839
9078
  var _this = this;
9079
+ if (typeof document === 'undefined')
9080
+ return;
8840
9081
  var elements = document.querySelectorAll('[data-kt-datatable="true"]');
8841
9082
  elements.forEach(function (element) {
8842
9083
  if (element.hasAttribute('data-kt-datatable') &&
@@ -8861,11 +9102,11 @@ var KTDataTable = /** @class */ (function (_super) {
8861
9102
  };
8862
9103
  /**
8863
9104
  * 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.
9105
+ * This function is now browser-guarded and must be called explicitly.
8867
9106
  */
8868
9107
  KTDataTable.init = function () {
9108
+ if (typeof document === 'undefined')
9109
+ return;
8869
9110
  // Create instances of KTDataTable for all elements with a
8870
9111
  // data-kt-datatable="true" attribute
8871
9112
  KTDataTable.createInstances();
@@ -8923,8 +9164,16 @@ var KTDataTable = /** @class */ (function (_super) {
8923
9164
  return KTDataTable;
8924
9165
  }(component_1.default));
8925
9166
  exports.KTDataTable = KTDataTable;
8926
- if (typeof window !== 'undefined') {
8927
- window.KTDataTable = KTDataTable;
9167
+ /**
9168
+ * NOTE: This module is now PURE. No side effects or DOM/global assignments occur on import.
9169
+ * To auto-initialize all datatables on the page, call the exported `initAllDataTables()` function explicitly in the browser.
9170
+ */
9171
+ function initAllDataTables() {
9172
+ if (typeof document !== 'undefined') {
9173
+ KTDataTable.createInstances();
9174
+ // Optionally assign to window for legacy support
9175
+ window.KTDataTable = KTDataTable;
9176
+ }
8928
9177
  }
8929
9178
 
8930
9179
 
@@ -9494,13 +9743,15 @@ var KTSelectDropdown = /** @class */ (function (_super) {
9494
9743
  var currentDropdownZIndexStr = dom_1.default.getCssProp(this._dropdownElement, 'z-index');
9495
9744
  if (currentDropdownZIndexStr && currentDropdownZIndexStr !== 'auto') {
9496
9745
  var currentDropdownZIndex = parseInt(currentDropdownZIndexStr);
9497
- if (!isNaN(currentDropdownZIndex) && currentDropdownZIndex > (zIndexToApply || 0)) {
9746
+ if (!isNaN(currentDropdownZIndex) &&
9747
+ currentDropdownZIndex > (zIndexToApply || 0)) {
9498
9748
  zIndexToApply = currentDropdownZIndex;
9499
9749
  }
9500
9750
  }
9501
9751
  // Ensure dropdown is above elements within its original toggle's parent context
9502
9752
  var toggleParentContextZindex = dom_1.default.getHighestZindex(this._element); // _element is the select wrapper
9503
- if (toggleParentContextZindex !== null && toggleParentContextZindex >= (zIndexToApply || 0)) {
9753
+ if (toggleParentContextZindex !== null &&
9754
+ toggleParentContextZindex >= (zIndexToApply || 0)) {
9504
9755
  zIndexToApply = toggleParentContextZindex + 1;
9505
9756
  }
9506
9757
  if (zIndexToApply !== null) {
@@ -9978,7 +10229,9 @@ var KTSelectSearch = /** @class */ (function () {
9978
10229
  });
9979
10230
  }
9980
10231
  // Listen for dropdown close to reset options - ATTACH TO WRAPPER
9981
- this._select.getWrapperElement().addEventListener('dropdown.close', function () {
10232
+ this._select
10233
+ .getWrapperElement()
10234
+ .addEventListener('dropdown.close', function () {
9982
10235
  _this._focusManager.resetFocus();
9983
10236
  // If clearSearchOnClose is false and there's a value, the search term and filtered state should persist.
9984
10237
  // KTSelect's closeDropdown method already calls this._searchModule.clearSearch() (which clears highlights)
@@ -10000,7 +10253,9 @@ var KTSelectSearch = /** @class */ (function () {
10000
10253
  }
10001
10254
  });
10002
10255
  // Consolidated 'dropdown.show' event listener - ATTACH TO WRAPPER
10003
- this._select.getWrapperElement().addEventListener('dropdown.show', function () {
10256
+ this._select
10257
+ .getWrapperElement()
10258
+ .addEventListener('dropdown.show', function () {
10004
10259
  var _a;
10005
10260
  _this._focusManager.resetFocus(); // Always clear previous focus state
10006
10261
  if ((_a = _this._searchInput) === null || _a === void 0 ? void 0 : _a.value) {
@@ -10023,6 +10278,7 @@ var KTSelectSearch = /** @class */ (function () {
10023
10278
  (_a = _this._searchInput) === null || _a === void 0 ? void 0 : _a.focus(); // Focus search input
10024
10279
  }, 50); // Delay to ensure dropdown is visible
10025
10280
  }
10281
+ _this._select.updateSelectAllButtonState();
10026
10282
  });
10027
10283
  }
10028
10284
  }
@@ -10041,6 +10297,11 @@ var KTSelectSearch = /** @class */ (function () {
10041
10297
  KTSelectSearch.prototype._handleSearchKeyDown = function (event) {
10042
10298
  var key = event.key;
10043
10299
  switch (key) {
10300
+ case ' ': // Spacebar
10301
+ // Do nothing, allow space to be typed into the input
10302
+ // Stop propagation to prevent parent handlers from processing this event
10303
+ event.stopPropagation();
10304
+ break;
10044
10305
  case 'ArrowDown':
10045
10306
  event.preventDefault();
10046
10307
  this._focusManager.focusNext();
@@ -10155,9 +10416,8 @@ var KTSelectSearch = /** @class */ (function () {
10155
10416
  }
10156
10417
  // Restore original content before filtering, so highlighting is applied fresh.
10157
10418
  this._restoreOptionContentsBeforeFilter();
10158
- var visibleCount = (0, utils_1.filterOptions)(options, query, config, dropdownElement, function (count) {
10159
- return _this._handleNoResults(count);
10160
- });
10419
+ var visibleCount = (0, utils_1.filterOptions)(options, query, config, dropdownElement, function (count) { return _this._handleNoResults(count); });
10420
+ this._select.updateSelectAllButtonState();
10161
10421
  };
10162
10422
  /**
10163
10423
  * Reset all options to their original state
@@ -10185,6 +10445,7 @@ var KTSelectSearch = /** @class */ (function () {
10185
10445
  }
10186
10446
  });
10187
10447
  this._clearNoResultsMessage(); // Ensure no results message is cleared when resetting
10448
+ this._select.updateSelectAllButtonState();
10188
10449
  };
10189
10450
  KTSelectSearch.prototype._handleNoResults = function (visibleOptionsCount) {
10190
10451
  var _a, _b;
@@ -11388,12 +11649,16 @@ var KTSelect = /** @class */ (function (_super) {
11388
11649
  // Core properties
11389
11650
  _this._name = 'select';
11390
11651
  _this._dataOptionPrefix = 'kt-'; // Use 'kt-' prefix to support data-kt-select-option attributes
11652
+ // Cached DOM references for performance
11653
+ _this._optionsContainer = null;
11391
11654
  // State
11392
11655
  _this._dropdownIsOpen = false;
11393
11656
  _this._comboboxModule = null;
11394
11657
  _this._tagsModule = null;
11395
11658
  _this._dropdownModule = null;
11396
11659
  _this._loadMoreIndicator = null;
11660
+ _this._selectAllButton = null;
11661
+ _this._selectAllButtonToggle = null;
11397
11662
  _this._typeToSearchBuffer = new utils_1.TypeToSearchBuffer();
11398
11663
  _this._mutationObserver = null;
11399
11664
  // Search debounce timeout
@@ -11439,6 +11704,10 @@ var KTSelect = /** @class */ (function (_super) {
11439
11704
  return;
11440
11705
  if (this._config.debug)
11441
11706
  console.log('Initializing remote data with URL:', this._config.dataUrl);
11707
+ // For remote data, we need to create the HTML structure first
11708
+ // so that the component can be properly initialized
11709
+ this._createHtmlStructure();
11710
+ this._setupElementReferences();
11442
11711
  // Show loading state
11443
11712
  this._renderLoadingState();
11444
11713
  // Fetch remote data
@@ -11457,7 +11726,10 @@ var KTSelect = /** @class */ (function (_super) {
11457
11726
  _this._generateOptionsHtml(_this._element);
11458
11727
  if (_this._config.debug)
11459
11728
  console.log('Generating options HTML from remote data');
11460
- _this._setupComponent();
11729
+ // Update the dropdown to show the new options
11730
+ _this._updateDropdownWithNewOptions();
11731
+ // Complete the component setup with the fetched data
11732
+ _this._completeRemoteSetup();
11461
11733
  // Add pagination "Load More" button if needed
11462
11734
  if (_this._config.pagination && _this._remoteModule.hasMorePages()) {
11463
11735
  _this._addLoadMoreButton();
@@ -11481,6 +11753,108 @@ var KTSelect = /** @class */ (function (_super) {
11481
11753
  var options = Array.from(this._element.querySelectorAll('option:not([value=""])'));
11482
11754
  options.forEach(function (option) { return option.remove(); });
11483
11755
  };
11756
+ /**
11757
+ * Unified method to render options in dropdown - eliminates code duplication
11758
+ */
11759
+ KTSelect.prototype._renderOptionsInDropdown = function (optionsData, clearContainer) {
11760
+ var _this = this;
11761
+ if (clearContainer === void 0) { clearContainer = true; }
11762
+ if (!this._dropdownContentElement)
11763
+ return;
11764
+ // Use cached options container for better performance
11765
+ var optionsContainer = this._optionsContainer ||
11766
+ this._dropdownContentElement.querySelector('[data-kt-select-options]');
11767
+ if (!optionsContainer)
11768
+ return;
11769
+ // Clear container if requested
11770
+ if (clearContainer) {
11771
+ optionsContainer.innerHTML = '';
11772
+ }
11773
+ // Use DocumentFragment for efficient DOM manipulation
11774
+ var fragment = document.createDocumentFragment();
11775
+ // Process options data
11776
+ optionsData.forEach(function (optionData) {
11777
+ var optionElement;
11778
+ // Handle different input types
11779
+ if (optionData instanceof HTMLOptionElement) {
11780
+ // Skip empty placeholder options
11781
+ if (optionData.value === '' && optionData.textContent.trim() === '') {
11782
+ return;
11783
+ }
11784
+ optionElement = optionData;
11785
+ }
11786
+ else {
11787
+ // Handle KTSelectOptionData objects - cast to ensure type safety
11788
+ var dataItem = optionData;
11789
+ optionElement = document.createElement('option');
11790
+ optionElement.value = dataItem.id || '';
11791
+ optionElement.textContent = dataItem.title || '';
11792
+ if (dataItem.selected) {
11793
+ optionElement.setAttribute('selected', 'selected');
11794
+ }
11795
+ if (dataItem.disabled) {
11796
+ optionElement.setAttribute('disabled', 'disabled');
11797
+ }
11798
+ }
11799
+ // Create KTSelectOption instance for proper rendering
11800
+ var selectOption = new option_1.KTSelectOption(optionElement, _this._config);
11801
+ var renderedOption = selectOption.render();
11802
+ // Add to fragment for batch DOM operation
11803
+ fragment.appendChild(renderedOption);
11804
+ });
11805
+ // Batch append all options at once
11806
+ optionsContainer.appendChild(fragment);
11807
+ // Update options NodeList
11808
+ this._options = this._wrapperElement.querySelectorAll('[data-kt-select-option]');
11809
+ if (this._config.debug) {
11810
+ console.log("Rendered ".concat(optionsData.length, " options in dropdown"));
11811
+ }
11812
+ };
11813
+ /**
11814
+ * Update dropdown with new options from the original select element
11815
+ */
11816
+ KTSelect.prototype._updateDropdownWithNewOptions = function () {
11817
+ // Get all options from the original select element
11818
+ var options = Array.from(this._element.querySelectorAll('option'));
11819
+ // Use unified renderer
11820
+ this._renderOptionsInDropdown(options, true);
11821
+ };
11822
+ /**
11823
+ * Complete the setup for remote data after HTML structure is created
11824
+ */
11825
+ KTSelect.prototype._completeRemoteSetup = function () {
11826
+ // Initialize options
11827
+ this._preSelectOptions(this._element);
11828
+ // Apply disabled state if needed
11829
+ this._applyInitialDisabledState();
11830
+ // Initialize search if enabled
11831
+ if (this._config.enableSearch) {
11832
+ this._initializeSearchModule();
11833
+ }
11834
+ // Initialize combobox if enabled
11835
+ if (this._config.combobox) {
11836
+ this._comboboxModule = new combobox_1.KTSelectCombobox(this);
11837
+ }
11838
+ // Initialize tags if enabled
11839
+ if (this._config.tags) {
11840
+ this._tagsModule = new tags_1.KTSelectTags(this);
11841
+ }
11842
+ // Initialize focus manager after dropdown element is created
11843
+ this._focusManager = new utils_1.FocusManager(this._dropdownContentElement, '[data-kt-select-option]', this._config);
11844
+ // Initialize dropdown module after all elements are created
11845
+ this._dropdownModule = new dropdown_1.KTSelectDropdown(this._wrapperElement, this._displayElement, this._dropdownContentElement, this._config, this);
11846
+ // Update display and set ARIA attributes
11847
+ this._updateDisplayAndAriaAttributes();
11848
+ this.updateSelectedOptionDisplay();
11849
+ this._setAriaAttributes();
11850
+ // Update select all button state
11851
+ this.updateSelectAllButtonState();
11852
+ // Focus the first selected option or first option if nothing selected
11853
+ this._focusSelectedOption();
11854
+ // Attach event listeners after all modules are initialized
11855
+ this._attachEventListeners();
11856
+ this._observeNativeSelect();
11857
+ };
11484
11858
  /**
11485
11859
  * Helper to show a dropdown message (error, loading, noResults)
11486
11860
  */
@@ -11674,6 +12048,10 @@ var KTSelect = /** @class */ (function (_super) {
11674
12048
  this._updateDisplayAndAriaAttributes();
11675
12049
  this.updateSelectedOptionDisplay();
11676
12050
  this._setAriaAttributes();
12051
+ // Update select all button state
12052
+ this.updateSelectAllButtonState();
12053
+ // Focus the first selected option or first option if nothing selected
12054
+ this._focusSelectedOption();
11677
12055
  // Attach event listeners after all modules are initialized
11678
12056
  this._attachEventListeners();
11679
12057
  this._observeNativeSelect();
@@ -11693,13 +12071,19 @@ var KTSelect = /** @class */ (function (_super) {
11693
12071
  // Move classes from original select to wrapper and display elements
11694
12072
  if (this._element.classList.length > 0) {
11695
12073
  var originalClasses = Array.from(this._element.classList);
11696
- var displaySpecificClasses_1 = ['kt-select', 'kt-select-sm', 'kt-select-lg'];
12074
+ var displaySpecificClasses_1 = [
12075
+ 'kt-select',
12076
+ 'kt-select-sm',
12077
+ 'kt-select-lg',
12078
+ ];
11697
12079
  var classesForWrapper = originalClasses.filter(function (className) { return !displaySpecificClasses_1.includes(className); });
11698
12080
  if (classesForWrapper.length > 0) {
11699
12081
  (_a = wrapperElement.classList).add.apply(_a, classesForWrapper);
11700
12082
  }
11701
12083
  // Move display-specific classes to display element
11702
- var classesForDisplay = originalClasses.filter(function (className) { return displaySpecificClasses_1.includes(className); });
12084
+ var classesForDisplay = originalClasses.filter(function (className) {
12085
+ return displaySpecificClasses_1.includes(className);
12086
+ });
11703
12087
  if (classesForDisplay.length > 0) {
11704
12088
  (_b = displayElement.classList).add.apply(_b, classesForDisplay);
11705
12089
  }
@@ -11712,9 +12096,14 @@ var KTSelect = /** @class */ (function (_super) {
11712
12096
  var searchElement = templates_1.defaultTemplates.search(this._config);
11713
12097
  dropdownElement.appendChild(searchElement);
11714
12098
  }
12099
+ // Add select all button if needed
12100
+ if (this._config.multiple && this._config.enableSelectAll) {
12101
+ var selectAllElement = templates_1.defaultTemplates.selectAll(this._config);
12102
+ dropdownElement.appendChild(selectAllElement);
12103
+ }
11715
12104
  // Create options container using template
11716
12105
  var optionsContainer = templates_1.defaultTemplates.options(this._config);
11717
- // Add each option directly to the container
12106
+ // Add each option directly to the container (only if options exist)
11718
12107
  options.forEach(function (optionElement) {
11719
12108
  // Skip empty placeholder options (only if BOTH value AND text are empty)
11720
12109
  // This allows options with empty value but visible text to display in dropdown
@@ -11741,13 +12130,18 @@ var KTSelect = /** @class */ (function (_super) {
11741
12130
  */
11742
12131
  KTSelect.prototype._setupElementReferences = function () {
11743
12132
  this._wrapperElement = this._element.nextElementSibling;
12133
+ // Safety check - ensure wrapper element exists
12134
+ if (!this._wrapperElement) {
12135
+ console.error('KTSelect: Wrapper element not found. HTML structure may not be created properly.');
12136
+ return;
12137
+ }
11744
12138
  // Get display element
11745
12139
  this._displayElement = this._wrapperElement.querySelector("[data-kt-select-display]");
11746
12140
  // Get dropdown content element - this is critical for dropdown functionality
11747
12141
  this._dropdownContentElement = this._wrapperElement.querySelector("[data-kt-select-dropdown]");
11748
12142
  if (!this._dropdownContentElement) {
11749
- console.log(this._element);
11750
- console.error('Dropdown content element not found', this._wrapperElement);
12143
+ console.error('KTSelect: Dropdown content element not found', this._wrapperElement);
12144
+ return;
11751
12145
  }
11752
12146
  // Get search input element - this is used for the search functionality
11753
12147
  this._searchInputElement = this._dropdownContentElement.querySelector("[data-kt-select-search]");
@@ -11755,6 +12149,9 @@ var KTSelect = /** @class */ (function (_super) {
11755
12149
  if (!this._searchInputElement) {
11756
12150
  this._searchInputElement = this._displayElement;
11757
12151
  }
12152
+ this._selectAllButton = this._wrapperElement.querySelector('[data-kt-select-select-all]');
12153
+ // Cache the options container for performance
12154
+ this._optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
11758
12155
  this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
11759
12156
  };
11760
12157
  /**
@@ -11765,6 +12162,13 @@ var KTSelect = /** @class */ (function (_super) {
11765
12162
  document.addEventListener('click', this._handleDocumentClick.bind(this));
11766
12163
  // Dropdown option click events
11767
12164
  this._eventManager.addListener(this._dropdownContentElement, 'click', this._handleDropdownOptionClick.bind(this));
12165
+ if (this._selectAllButton) {
12166
+ this._selectAllButtonToggle =
12167
+ this._selectAllButton.querySelector('button');
12168
+ if (this._selectAllButtonToggle) {
12169
+ this._eventManager.addListener(this._selectAllButtonToggle, 'click', this._handleSelectAllClick.bind(this));
12170
+ }
12171
+ }
11768
12172
  // Attach centralized keyboard handler to the wrapper element.
11769
12173
  // Events from focusable children like _displayElement or _searchInputElement (if present) will bubble up.
11770
12174
  if (this._wrapperElement) {
@@ -11930,6 +12334,8 @@ var KTSelect = /** @class */ (function (_super) {
11930
12334
  this._fireEvent('show');
11931
12335
  // Update ARIA states
11932
12336
  this._setAriaAttributes();
12337
+ // Update select all button state
12338
+ this.updateSelectAllButtonState();
11933
12339
  // Focus the first selected option or first option if nothing selected
11934
12340
  this._focusSelectedOption();
11935
12341
  };
@@ -12157,6 +12563,8 @@ var KTSelect = /** @class */ (function (_super) {
12157
12563
  this._state.setSelectedOptions([]);
12158
12564
  this.updateSelectedOptionDisplay();
12159
12565
  this._updateSelectedOptionClass();
12566
+ // Update select all button state
12567
+ this.updateSelectAllButtonState();
12160
12568
  // Dispatch change event
12161
12569
  this._dispatchEvent('change');
12162
12570
  this._fireEvent('change');
@@ -12421,6 +12829,7 @@ var KTSelect = /** @class */ (function (_super) {
12421
12829
  if (this._config.debug)
12422
12830
  console.log('Multiple select mode - keeping dropdown open for additional selections');
12423
12831
  // Don't close dropdown in multiple select mode to allow multiple selections
12832
+ this.updateSelectAllButtonState();
12424
12833
  }
12425
12834
  // Dispatch custom change event with additional data
12426
12835
  this._dispatchEvent('change', {
@@ -12500,6 +12909,8 @@ var KTSelect = /** @class */ (function (_super) {
12500
12909
  var query = event.target.value;
12501
12910
  // Check if the query is long enough
12502
12911
  if (query.length < (this._config.searchMinLength || 0)) {
12912
+ // Restore original options if query is too short
12913
+ this._restoreOriginalOptions();
12503
12914
  return;
12504
12915
  }
12505
12916
  // Debounce the search
@@ -12523,6 +12934,7 @@ var KTSelect = /** @class */ (function (_super) {
12523
12934
  if (_this._searchModule) {
12524
12935
  _this._searchModule.refreshAfterSearch();
12525
12936
  }
12937
+ _this.updateSelectAllButtonState();
12526
12938
  })
12527
12939
  .catch(function (error) {
12528
12940
  console.error('Error updating search results:', error);
@@ -12553,7 +12965,36 @@ var KTSelect = /** @class */ (function (_super) {
12553
12965
  * @param message Error message
12554
12966
  */
12555
12967
  KTSelect.prototype._renderSearchErrorState = function (message) {
12968
+ var _this = this;
12556
12969
  this._showDropdownMessage('error', message);
12970
+ // Restore original options after error with a delay
12971
+ setTimeout(function () {
12972
+ _this._restoreOriginalOptions();
12973
+ }, 2000);
12974
+ };
12975
+ /**
12976
+ * Restore original options when search is cleared
12977
+ */
12978
+ KTSelect.prototype._restoreOriginalOptions = function () {
12979
+ if (!this._dropdownContentElement || !this._originalOptionsHtml)
12980
+ return;
12981
+ // Use cached options container for better performance
12982
+ var optionsContainer = this._optionsContainer ||
12983
+ this._dropdownContentElement.querySelector('[data-kt-select-options]');
12984
+ if (!optionsContainer)
12985
+ return;
12986
+ // Restore original options
12987
+ optionsContainer.innerHTML = this._originalOptionsHtml;
12988
+ // Update options NodeList
12989
+ this._options = this._wrapperElement.querySelectorAll('[data-kt-select-option]');
12990
+ // Refresh search module
12991
+ if (this._searchModule) {
12992
+ this._searchModule.refreshAfterSearch();
12993
+ }
12994
+ this.updateSelectAllButtonState();
12995
+ if (this._config.debug) {
12996
+ console.log('Restored original options after search clear');
12997
+ }
12557
12998
  };
12558
12999
  /**
12559
13000
  * Update search results in the dropdown
@@ -12562,31 +13003,24 @@ var KTSelect = /** @class */ (function (_super) {
12562
13003
  KTSelect.prototype._updateSearchResults = function (items) {
12563
13004
  if (!this._dropdownContentElement)
12564
13005
  return;
12565
- var optionsContainer = this._dropdownContentElement.querySelector('[data-kt-select-options]');
13006
+ // Use cached options container for better performance
13007
+ var optionsContainer = this._optionsContainer ||
13008
+ this._dropdownContentElement.querySelector('[data-kt-select-options]');
12566
13009
  if (!optionsContainer)
12567
13010
  return;
12568
- // Clear current options
12569
- optionsContainer.innerHTML = '';
13011
+ // Handle empty results
12570
13012
  if (items.length === 0) {
12571
- // Show no results message using template for consistency and customization
13013
+ optionsContainer.innerHTML = '';
12572
13014
  var noResultsElement = templates_1.defaultTemplates.searchEmpty(this._config);
12573
13015
  optionsContainer.appendChild(noResultsElement);
12574
13016
  return;
12575
13017
  }
12576
- // Process each item individually to create options
12577
- items.forEach(function (item) {
12578
- // Create option for the original select
12579
- var selectOption = document.createElement('option');
12580
- selectOption.value = item.id;
12581
- // Add to dropdown container
12582
- optionsContainer.appendChild(selectOption);
12583
- });
13018
+ // Use unified renderer for search results
13019
+ this._renderOptionsInDropdown(items, true);
12584
13020
  // Add pagination "Load More" button if needed
12585
13021
  if (this._config.pagination && this._remoteModule.hasMorePages()) {
12586
13022
  this._addLoadMoreButton();
12587
13023
  }
12588
- // Update options NodeList
12589
- this._options = this._wrapperElement.querySelectorAll("[data-kt-select-option]");
12590
13024
  };
12591
13025
  /**
12592
13026
  * Check if dropdown is open
@@ -12598,10 +13032,12 @@ var KTSelect = /** @class */ (function (_super) {
12598
13032
  var _this = this;
12599
13033
  var selectedValues = this.getSelectedOptions();
12600
13034
  var displaySeparator = this._config.displaySeparator || ', ';
12601
- var texts = selectedValues.map(function (value) {
13035
+ var texts = selectedValues
13036
+ .map(function (value) {
12602
13037
  var option = Array.from(_this._options).find(function (opt) { return opt.getAttribute('data-value') === value; });
12603
13038
  return (option === null || option === void 0 ? void 0 : option.getAttribute('data-text')) || '';
12604
- }).filter(Boolean);
13039
+ })
13040
+ .filter(Boolean);
12605
13041
  return texts.join(displaySeparator);
12606
13042
  };
12607
13043
  /**
@@ -12609,7 +13045,9 @@ var KTSelect = /** @class */ (function (_super) {
12609
13045
  */
12610
13046
  KTSelect.prototype._isOptionDisabled = function (value) {
12611
13047
  var dropdownOption = Array.from(this._options).find(function (opt) { return opt.getAttribute('data-value') === value; });
12612
- var isDropdownDisabled = dropdownOption && (dropdownOption.classList.contains('disabled') || dropdownOption.getAttribute('aria-disabled') === 'true');
13048
+ var isDropdownDisabled = dropdownOption &&
13049
+ (dropdownOption.classList.contains('disabled') ||
13050
+ dropdownOption.getAttribute('aria-disabled') === 'true');
12613
13051
  var selectOption = Array.from(this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
12614
13052
  var isNativeDisabled = selectOption && selectOption.disabled;
12615
13053
  return Boolean(isDropdownDisabled || isNativeDisabled);
@@ -12631,9 +13069,14 @@ var KTSelect = /** @class */ (function (_super) {
12631
13069
  if (event.target === this._searchInputElement) {
12632
13070
  // Allow navigation keys like ArrowDown, ArrowUp, Escape, Enter (for search/selection) to be handled by the logic below.
12633
13071
  // For other keys (characters, space, backspace, delete), let the input field process them.
12634
- if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp' &&
12635
- event.key !== 'Escape' && event.key !== 'Enter' && event.key !== 'Tab' &&
12636
- event.key !== 'Home' && event.key !== 'End') {
13072
+ if (event.key !== 'ArrowDown' &&
13073
+ event.key !== 'ArrowUp' &&
13074
+ event.key !== 'Escape' &&
13075
+ event.key !== 'Enter' &&
13076
+ event.key !== 'Tab' &&
13077
+ event.key !== 'Home' &&
13078
+ event.key !== 'End' &&
13079
+ event.key !== ' ') {
12637
13080
  // If it's a character key and we are NOT type-to-searching (because search has focus)
12638
13081
  // then let the input field handle it for its own value.
12639
13082
  // The search module's 'input' event will handle filtering based on the input's value.
@@ -12647,7 +13090,10 @@ var KTSelect = /** @class */ (function (_super) {
12647
13090
  if (event.altKey || event.ctrlKey || event.metaKey)
12648
13091
  return;
12649
13092
  // Type-to-search: only for single char keys, when search input does not have focus
12650
- if (event.key.length === 1 && !event.repeat && !event.key.match(/\s/) && document.activeElement !== this._searchInputElement) {
13093
+ if (event.key.length === 1 &&
13094
+ !event.repeat &&
13095
+ !event.key.match(/\s/) &&
13096
+ document.activeElement !== this._searchInputElement) {
12651
13097
  buffer.push(event.key);
12652
13098
  var str = buffer.getBuffer();
12653
13099
  if (isOpen) {
@@ -12696,7 +13142,9 @@ var KTSelect = /** @class */ (function (_super) {
12696
13142
  if (focusedOptionEl) {
12697
13143
  var val = focusedOptionEl.dataset.value;
12698
13144
  // If single select, and the item is already selected, just close.
12699
- if (val !== undefined && !this._config.multiple && this._state.isSelected(val)) {
13145
+ if (val !== undefined &&
13146
+ !this._config.multiple &&
13147
+ this._state.isSelected(val)) {
12700
13148
  if (this._config.debug)
12701
13149
  console.log('Enter on already selected item in single-select mode. Closing.');
12702
13150
  this.closeDropdown();
@@ -12737,7 +13185,8 @@ var KTSelect = /** @class */ (function (_super) {
12737
13185
  var _this = this;
12738
13186
  var optionsConfig = this._config.optionsConfig || {};
12739
13187
  var displaySeparator = this._config.displaySeparator || ', ';
12740
- var contentArray = Array.from(new Set(selectedValues.map(function (value) {
13188
+ var contentArray = Array.from(new Set(selectedValues
13189
+ .map(function (value) {
12741
13190
  var option = Array.from(_this._options).find(function (opt) { return opt.getAttribute('data-value') === value; });
12742
13191
  if (!option)
12743
13192
  return '';
@@ -12746,7 +13195,7 @@ var KTSelect = /** @class */ (function (_super) {
12746
13195
  // Replace all {{varname}} in option.innerHTML with values from _config
12747
13196
  Object.entries(optionsConfig[value] || {}).forEach(function (_a) {
12748
13197
  var key = _a[0], val = _a[1];
12749
- if (["string", "number", "boolean"].includes(typeof val)) {
13198
+ if (['string', 'number', 'boolean'].includes(typeof val)) {
12750
13199
  displayTemplate = displayTemplate.replace(new RegExp("{{".concat(key, "}}"), 'g'), String(val));
12751
13200
  }
12752
13201
  });
@@ -12755,7 +13204,8 @@ var KTSelect = /** @class */ (function (_super) {
12755
13204
  selectedTexts: _this.getSelectedOptionsText() || '',
12756
13205
  text: text,
12757
13206
  });
12758
- }).filter(Boolean)));
13207
+ })
13208
+ .filter(Boolean)));
12759
13209
  return contentArray.join(displaySeparator);
12760
13210
  };
12761
13211
  KTSelect.prototype.getDisplayElement = function () {
@@ -12774,7 +13224,8 @@ var KTSelect = /** @class */ (function (_super) {
12774
13224
  // Option(s) added or removed
12775
13225
  needsRebuild = true;
12776
13226
  }
12777
- else if (mutation.type === 'attributes' && mutation.target instanceof HTMLOptionElement) {
13227
+ else if (mutation.type === 'attributes' &&
13228
+ mutation.target instanceof HTMLOptionElement) {
12778
13229
  if (mutation.attributeName === 'selected') {
12779
13230
  needsSelectionSync = true;
12780
13231
  }
@@ -12827,6 +13278,57 @@ var KTSelect = /** @class */ (function (_super) {
12827
13278
  this._state.setSelectedOptions(this._config.multiple ? selected : selected[0] || '');
12828
13279
  this.updateSelectedOptionDisplay();
12829
13280
  this._updateSelectedOptionClass();
13281
+ this.updateSelectAllButtonState();
13282
+ };
13283
+ KTSelect.prototype._handleSelectAllClick = function (event) {
13284
+ event.preventDefault();
13285
+ event.stopPropagation();
13286
+ var visibleOptions = this._focusManager
13287
+ .getVisibleOptions()
13288
+ .filter(function (opt) { return opt.getAttribute('aria-disabled') !== 'true'; });
13289
+ if (visibleOptions.length === 0)
13290
+ return;
13291
+ var visibleValues = visibleOptions.map(function (opt) { return opt.dataset.value; });
13292
+ var selectedValues = new Set(this.getSelectedOptions());
13293
+ var isAllSelected = visibleOptions.every(function (opt) {
13294
+ return selectedValues.has(opt.dataset.value);
13295
+ });
13296
+ if (isAllSelected) {
13297
+ // Deselect all visible
13298
+ visibleValues.forEach(function (value) { return selectedValues.delete(value); });
13299
+ }
13300
+ else {
13301
+ // Select all visible
13302
+ visibleValues.forEach(function (value) { return selectedValues.add(value); });
13303
+ }
13304
+ this._state.setSelectedOptions(Array.from(selectedValues));
13305
+ this.updateSelectedOptionDisplay();
13306
+ this._updateSelectedOptionClass();
13307
+ this.updateSelectAllButtonState();
13308
+ this._dispatchEvent('change');
13309
+ this._fireEvent('change');
13310
+ };
13311
+ KTSelect.prototype.updateSelectAllButtonState = function () {
13312
+ if (!this._config.multiple ||
13313
+ !this._config.enableSelectAll ||
13314
+ !this._selectAllButtonToggle) {
13315
+ return;
13316
+ }
13317
+ var visibleOptions = this._focusManager
13318
+ .getVisibleOptions()
13319
+ .filter(function (opt) { return opt.getAttribute('aria-disabled') !== 'true'; });
13320
+ if (visibleOptions.length === 0) {
13321
+ this._selectAllButton.style.display = 'none';
13322
+ return;
13323
+ }
13324
+ this._selectAllButton.style.display = '';
13325
+ var selectedValues = new Set(this.getSelectedOptions());
13326
+ var isAllSelected = visibleOptions.every(function (opt) {
13327
+ return selectedValues.has(opt.dataset.value);
13328
+ });
13329
+ this._selectAllButtonToggle.textContent = isAllSelected
13330
+ ? this._config.clearAllText
13331
+ : this._config.selectAllText;
12830
13332
  };
12831
13333
  /**
12832
13334
  * ========================================================================
@@ -14735,7 +15237,9 @@ var KTSelectTags = /** @class */ (function () {
14735
15237
  }
14736
15238
  }
14737
15239
  if (!optionElement) {
14738
- var originalOptions = _this._select.getElement().querySelectorAll('option');
15240
+ var originalOptions = _this._select
15241
+ .getElement()
15242
+ .querySelectorAll('option');
14739
15243
  for (var _b = 0, _c = Array.from(originalOptions); _b < _c.length; _b++) {
14740
15244
  var opt = _c[_b];
14741
15245
  if (opt.value === optionValue) {
@@ -15695,7 +16199,9 @@ function filterOptions(options, query, config, dropdownElement, onVisibleCount)
15695
16199
  for (var _a = 0, options_2 = options; _a < options_2.length; _a++) {
15696
16200
  var option = options_2[_a];
15697
16201
  // Use data-text for matching if available, otherwise fall back to textContent
15698
- var optionText = (option.dataset.text || option.textContent || '').toLowerCase();
16202
+ var optionText = (option.dataset.text ||
16203
+ option.textContent ||
16204
+ '').toLowerCase();
15699
16205
  var isMatch = optionText.includes(queryLower);
15700
16206
  if (isMatch) {
15701
16207
  option.classList.remove('hidden');
@@ -15772,7 +16278,8 @@ var FocusManager = /** @class */ (function () {
15772
16278
  return null;
15773
16279
  for (var i = 0; i < options.length; i++) {
15774
16280
  var option = options[i];
15775
- if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
16281
+ if (!option.classList.contains('disabled') &&
16282
+ option.getAttribute('aria-disabled') !== 'true') {
15776
16283
  this.resetFocus();
15777
16284
  this._focusedOptionIndex = i;
15778
16285
  this.applyFocus(option);
@@ -15791,7 +16298,8 @@ var FocusManager = /** @class */ (function () {
15791
16298
  return null;
15792
16299
  for (var i = options.length - 1; i >= 0; i--) {
15793
16300
  var option = options[i];
15794
- if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
16301
+ if (!option.classList.contains('disabled') &&
16302
+ option.getAttribute('aria-disabled') !== 'true') {
15795
16303
  this.resetFocus();
15796
16304
  this._focusedOptionIndex = i;
15797
16305
  this.applyFocus(option);
@@ -15816,7 +16324,8 @@ var FocusManager = /** @class */ (function () {
15816
16324
  var option = options[idx];
15817
16325
  if (!option.classList.contains('disabled') &&
15818
16326
  option.getAttribute('aria-disabled') !== 'true' &&
15819
- (((_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)))) {
16327
+ (((_b = option.textContent) === null || _b === void 0 ? void 0 : _b.toLowerCase().startsWith(lowerStr)) ||
16328
+ ((_c = option.dataset.value) === null || _c === void 0 ? void 0 : _c.toLowerCase().startsWith(lowerStr)))) {
15820
16329
  this.resetFocus();
15821
16330
  this._focusedOptionIndex = idx;
15822
16331
  this.applyFocus(option);
@@ -15833,11 +16342,14 @@ var FocusManager = /** @class */ (function () {
15833
16342
  var options = this.getVisibleOptions();
15834
16343
  if (options.length === 0)
15835
16344
  return null;
15836
- var idx = this._focusedOptionIndex === null ? 0 : (this._focusedOptionIndex + 1) % options.length;
16345
+ var idx = this._focusedOptionIndex === null
16346
+ ? 0
16347
+ : (this._focusedOptionIndex + 1) % options.length;
15837
16348
  var startIdx = idx;
15838
16349
  do {
15839
16350
  var option = options[idx];
15840
- if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
16351
+ if (!option.classList.contains('disabled') &&
16352
+ option.getAttribute('aria-disabled') !== 'true') {
15841
16353
  this.resetFocus();
15842
16354
  this._focusedOptionIndex = idx;
15843
16355
  this.applyFocus(option);
@@ -15855,11 +16367,14 @@ var FocusManager = /** @class */ (function () {
15855
16367
  var options = this.getVisibleOptions();
15856
16368
  if (options.length === 0)
15857
16369
  return null;
15858
- var idx = this._focusedOptionIndex === null ? options.length - 1 : (this._focusedOptionIndex - 1 + options.length) % options.length;
16370
+ var idx = this._focusedOptionIndex === null
16371
+ ? options.length - 1
16372
+ : (this._focusedOptionIndex - 1 + options.length) % options.length;
15859
16373
  var startIdx = idx;
15860
16374
  do {
15861
16375
  var option = options[idx];
15862
- if (!option.classList.contains('disabled') && option.getAttribute('aria-disabled') !== 'true') {
16376
+ if (!option.classList.contains('disabled') &&
16377
+ option.getAttribute('aria-disabled') !== 'true') {
15863
16378
  this.resetFocus();
15864
16379
  this._focusedOptionIndex = idx;
15865
16380
  this.applyFocus(option);
@@ -15877,7 +16392,8 @@ var FocusManager = /** @class */ (function () {
15877
16392
  if (!option)
15878
16393
  return;
15879
16394
  // Ensure it's not disabled
15880
- if (option.classList.contains('disabled') || option.getAttribute('aria-disabled') === 'true') {
16395
+ if (option.classList.contains('disabled') ||
16396
+ option.getAttribute('aria-disabled') === 'true') {
15881
16397
  return;
15882
16398
  }
15883
16399
  // DO NOT CALL resetFocus() here. Caller's responsibility.
@@ -15926,7 +16442,8 @@ var FocusManager = /** @class */ (function () {
15926
16442
  var index = options.findIndex(function (option) { return option.dataset.value === value; });
15927
16443
  if (index >= 0) {
15928
16444
  var optionToFocus = options[index];
15929
- if (!optionToFocus.classList.contains('disabled') && optionToFocus.getAttribute('aria-disabled') !== 'true') {
16445
+ if (!optionToFocus.classList.contains('disabled') &&
16446
+ optionToFocus.getAttribute('aria-disabled') !== 'true') {
15930
16447
  this.resetFocus();
15931
16448
  this._focusedOptionIndex = index;
15932
16449
  this.applyFocus(optionToFocus);
@@ -16162,6 +16679,7 @@ exports.coreTemplateStrings = {
16162
16679
  loading: "<li class=\"kt-select-loading {{class}}\" role=\"status\" aria-live=\"polite\"></li>",
16163
16680
  tag: "<div data-kt-select-tag=\"true\" class=\"kt-select-tag {{class}}\"></div>",
16164
16681
  loadMore: "<li class=\"kt-select-load-more {{class}}\" data-kt-select-load-more=\"true\"></li>",
16682
+ selectAll: "<div data-kt-select-select-all class=\"kt-select-select-all\"><button type=\"button\" class=\"kt-select-select-all-button\">{{text}}</button></div>",
16165
16683
  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>",
16166
16684
  };
16167
16685
  /**
@@ -16435,6 +16953,11 @@ exports.defaultTemplates = {
16435
16953
  return element;
16436
16954
  }
16437
16955
  },
16956
+ selectAll: function (config) {
16957
+ var template = getTemplateStrings(config).selectAll;
16958
+ var element = stringToElement(template.replace('{{text}}', config.selectAllText || 'Select All'));
16959
+ return element;
16960
+ },
16438
16961
  };
16439
16962
 
16440
16963
 
@@ -17597,6 +18120,7 @@ exports.DefaultConfig = {
17597
18120
  // Multi-Select Display
17598
18121
  selectAllText: 'Select all', // Text for the "Select All" option (if implemented)
17599
18122
  clearAllText: 'Clear all', // Text for the "Clear All" option (if implemented)
18123
+ enableSelectAll: false, // Enable/disable "Select All" button for multi-select
17600
18124
  showSelectedCount: true, // Show the number of selected options in multi-select mode
17601
18125
  renderSelected: null, // Custom function to render the selected value(s) in the display area
17602
18126
  // Accessibility & Usability