@keenthemes/ktui 1.1.2 → 1.1.3

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 (56) hide show
  1. package/dist/ktui.js +506 -49
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +12 -0
  5. package/lib/cjs/components/component.js +22 -0
  6. package/lib/cjs/components/component.js.map +1 -1
  7. package/lib/cjs/components/datatable/datatable.js +7 -1
  8. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  9. package/lib/cjs/components/drawer/drawer.js +255 -9
  10. package/lib/cjs/components/drawer/drawer.js.map +1 -1
  11. package/lib/cjs/components/dropdown/dropdown.js +55 -8
  12. package/lib/cjs/components/dropdown/dropdown.js.map +1 -1
  13. package/lib/cjs/components/select/search.js +17 -7
  14. package/lib/cjs/components/select/search.js.map +1 -1
  15. package/lib/cjs/components/select/select.js +92 -14
  16. package/lib/cjs/components/select/select.js.map +1 -1
  17. package/lib/cjs/components/sticky/sticky.js +44 -5
  18. package/lib/cjs/components/sticky/sticky.js.map +1 -1
  19. package/lib/cjs/helpers/data.js +8 -0
  20. package/lib/cjs/helpers/data.js.map +1 -1
  21. package/lib/cjs/helpers/event-handler.js +6 -5
  22. package/lib/cjs/helpers/event-handler.js.map +1 -1
  23. package/lib/cjs/index.js.map +1 -1
  24. package/lib/esm/components/component.js +22 -0
  25. package/lib/esm/components/component.js.map +1 -1
  26. package/lib/esm/components/datatable/datatable.js +7 -1
  27. package/lib/esm/components/datatable/datatable.js.map +1 -1
  28. package/lib/esm/components/drawer/drawer.js +255 -9
  29. package/lib/esm/components/drawer/drawer.js.map +1 -1
  30. package/lib/esm/components/dropdown/dropdown.js +55 -8
  31. package/lib/esm/components/dropdown/dropdown.js.map +1 -1
  32. package/lib/esm/components/select/search.js +17 -7
  33. package/lib/esm/components/select/search.js.map +1 -1
  34. package/lib/esm/components/select/select.js +92 -14
  35. package/lib/esm/components/select/select.js.map +1 -1
  36. package/lib/esm/components/sticky/sticky.js +44 -5
  37. package/lib/esm/components/sticky/sticky.js.map +1 -1
  38. package/lib/esm/helpers/data.js +8 -0
  39. package/lib/esm/helpers/data.js.map +1 -1
  40. package/lib/esm/helpers/event-handler.js +6 -5
  41. package/lib/esm/helpers/event-handler.js.map +1 -1
  42. package/lib/esm/index.js.map +1 -1
  43. package/package.json +4 -2
  44. package/src/components/component.ts +26 -0
  45. package/src/components/datatable/__tests__/race-conditions.test.ts +2 -2
  46. package/src/components/datatable/datatable.ts +8 -1
  47. package/src/components/drawer/drawer.ts +266 -10
  48. package/src/components/dropdown/dropdown.ts +63 -8
  49. package/src/components/select/__tests__/ux-behaviors.test.ts +382 -4
  50. package/src/components/select/search.ts +16 -7
  51. package/src/components/select/select.css +5 -1
  52. package/src/components/select/select.ts +105 -16
  53. package/src/components/sticky/sticky.ts +55 -5
  54. package/src/helpers/data.ts +10 -0
  55. package/src/helpers/event-handler.ts +7 -6
  56. package/src/index.ts +2 -0
package/dist/ktui.js CHANGED
@@ -173,6 +173,15 @@ var __extends = (this && this.__extends) || (function () {
173
173
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
174
174
  };
175
175
  })();
176
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
177
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
178
+ if (ar || !(i in from)) {
179
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
180
+ ar[i] = from[i];
181
+ }
182
+ }
183
+ return to.concat(ar || Array.prototype.slice.call(from));
184
+ };
176
185
  Object.defineProperty(exports, "__esModule", ({ value: true }));
177
186
  exports.KTDrawer = void 0;
178
187
  var data_1 = __webpack_require__(8716);
@@ -205,8 +214,9 @@ var KTDrawer = /** @class */ (function (_super) {
205
214
  _this._isTransitioning = false;
206
215
  _this._backdropElement = null;
207
216
  _this._relatedTarget = null;
208
- if (data_1.default.has(element, _this._name))
217
+ if (data_1.default.has(element, _this._name)) {
209
218
  return _this;
219
+ }
210
220
  _this._init(element);
211
221
  _this._buildConfig(config);
212
222
  _this._handleClose();
@@ -248,6 +258,27 @@ var KTDrawer = /** @class */ (function (_super) {
248
258
  return;
249
259
  }
250
260
  KTDrawer.hide();
261
+ // If drawer needs to be in front of backdrop, ensure it's in body (for proper z-index stacking)
262
+ // This ensures the drawer and backdrop are in the same stacking context
263
+ if (this._getOption('container') === 'body' && this._element.parentElement !== document.body) {
264
+ // Store original parent for restoration when hiding
265
+ if (!this._element.hasAttribute('data-kt-drawer-original-parent-id')) {
266
+ var originalParent = this._element.parentElement;
267
+ if (originalParent && originalParent !== document.body) {
268
+ this._element.setAttribute('data-kt-drawer-original-parent-id', originalParent.id || '');
269
+ // Store a reference to find the parent later (using closest to find Livewire component or header)
270
+ var livewireComponent = originalParent.closest('[wire\\:id]');
271
+ var header = originalParent.closest('header#header');
272
+ if (livewireComponent) {
273
+ this._element.setAttribute('data-kt-drawer-original-wire-id', livewireComponent.getAttribute('wire:id') || '');
274
+ }
275
+ if (header) {
276
+ this._element.setAttribute('data-kt-drawer-original-in-header', 'true');
277
+ }
278
+ }
279
+ }
280
+ document.body.appendChild(this._element);
281
+ }
251
282
  if (this._getOption('backdrop') === true)
252
283
  this._createBackdrop();
253
284
  if (relatedTarget)
@@ -312,6 +343,9 @@ var KTDrawer = /** @class */ (function (_super) {
312
343
  _this._element.classList.add(_this._getOption('hiddenClass'));
313
344
  _this._element.classList.remove(_this._getOption('shownClass'));
314
345
  _this._element.style.zIndex = '';
346
+ // Note: We don't move drawer back to original location here
347
+ // Livewire will handle DOM structure on next navigation, and drawer will be reinitialized
348
+ // in its original location from the persisted component HTML
315
349
  _this._fireEvent('hidden');
316
350
  _this._dispatchEvent('hidden');
317
351
  });
@@ -331,7 +365,25 @@ var KTDrawer = /** @class */ (function (_super) {
331
365
  var _a;
332
366
  if (this._getOption('container')) {
333
367
  if (this._getOption('container') === 'body') {
334
- document.body.appendChild(this._element);
368
+ // Check if drawer is in a persisted Livewire component (like header with @persist)
369
+ // If so, don't move it to body - keep it in place so Livewire can preserve it
370
+ // This follows the same pattern as dropdowns/menus which work with wire:navigate
371
+ var originalParent = this._element.parentNode;
372
+ var isInPersistedComponent = originalParent &&
373
+ (originalParent.closest('[wire\\:id]') !== null ||
374
+ originalParent.closest('header#header') !== null);
375
+ if (isInPersistedComponent) {
376
+ // Don't move to body - keep in original location for Livewire persistence
377
+ // Use fixed positioning to achieve the same visual effect
378
+ // Ensure drawer has fixed positioning to work from its current location
379
+ if (!this._element.style.position || this._element.style.position === 'static') {
380
+ this._element.style.position = 'fixed';
381
+ }
382
+ }
383
+ else {
384
+ // Not in persisted component - safe to move to body (follows original behavior)
385
+ document.body.appendChild(this._element);
386
+ }
335
387
  }
336
388
  else {
337
389
  (_a = document
@@ -402,14 +454,117 @@ var KTDrawer = /** @class */ (function (_super) {
402
454
  KTDrawer.prototype.isEnabled = function () {
403
455
  return this._isEnabled();
404
456
  };
457
+ KTDrawer.getElement = function (reference) {
458
+ if (reference && reference.hasAttribute('data-kt-drawer-initialized'))
459
+ return reference;
460
+ var findElement = reference &&
461
+ reference.closest('[data-kt-drawer-initialized]');
462
+ if (findElement)
463
+ return findElement;
464
+ // Fallback: look for parent with data-kt-drawer attribute
465
+ if (reference) {
466
+ var drawerContainer = reference.closest('[data-kt-drawer]');
467
+ if (drawerContainer)
468
+ return drawerContainer;
469
+ }
470
+ // If reference is a toggle button with a selector, find the drawer by selector
471
+ // This handles cases where the toggle button is not a child of the drawer
472
+ if (reference && reference.hasAttribute('data-kt-drawer-toggle')) {
473
+ var selector = reference.getAttribute('data-kt-drawer-toggle');
474
+ if (selector) {
475
+ // Check both document and body (drawers with container="body" are moved to body)
476
+ var drawerElInDoc = document.querySelector(selector);
477
+ var drawerElInBody = document.body.querySelector(selector);
478
+ var drawerEl = drawerElInDoc || drawerElInBody;
479
+ if (drawerEl)
480
+ return drawerEl;
481
+ }
482
+ }
483
+ return null;
484
+ };
485
+ /**
486
+ * Wait for an element to appear in the DOM using polling with MutationObserver fallback
487
+ * Useful for persisted Livewire components that may not be in DOM immediately
488
+ */
489
+ KTDrawer.waitForElement = function (selector, timeout) {
490
+ if (timeout === void 0) { timeout = 2000; }
491
+ return new Promise(function (resolve) {
492
+ var resolved = false;
493
+ var doResolve = function (element) {
494
+ if (!resolved) {
495
+ resolved = true;
496
+ resolve(element);
497
+ }
498
+ };
499
+ // Check if element already exists
500
+ var existing = document.querySelector(selector) || document.body.querySelector(selector);
501
+ if (existing) {
502
+ doResolve(existing);
503
+ return;
504
+ }
505
+ // Use polling for faster detection (check every 50ms)
506
+ var attempts = 0;
507
+ var maxAttempts = timeout / 50;
508
+ var pollInterval = setInterval(function () {
509
+ if (resolved) {
510
+ clearInterval(pollInterval);
511
+ return;
512
+ }
513
+ attempts++;
514
+ var element = document.querySelector(selector) || document.body.querySelector(selector);
515
+ if (element) {
516
+ clearInterval(pollInterval);
517
+ doResolve(element);
518
+ return;
519
+ }
520
+ if (attempts >= maxAttempts) {
521
+ clearInterval(pollInterval);
522
+ doResolve(null);
523
+ }
524
+ }, 50);
525
+ // Also use MutationObserver as backup for immediate detection
526
+ var observer = new MutationObserver(function () {
527
+ if (resolved) {
528
+ observer.disconnect();
529
+ return;
530
+ }
531
+ var element = document.querySelector(selector) || document.body.querySelector(selector);
532
+ if (element) {
533
+ clearInterval(pollInterval);
534
+ observer.disconnect();
535
+ doResolve(element);
536
+ }
537
+ });
538
+ observer.observe(document.body, {
539
+ childList: true,
540
+ subtree: true,
541
+ });
542
+ // Cleanup on timeout
543
+ setTimeout(function () {
544
+ if (!resolved) {
545
+ clearInterval(pollInterval);
546
+ observer.disconnect();
547
+ doResolve(null);
548
+ }
549
+ }, timeout);
550
+ });
551
+ };
405
552
  KTDrawer.getInstance = function (element) {
406
553
  if (!element)
407
554
  return null;
408
- if (data_1.default.has(element, 'drawer')) {
409
- return data_1.default.get(element, 'drawer');
555
+ var drawerElement = KTDrawer.getElement(element);
556
+ if (!drawerElement) {
557
+ // If element is a toggle button and drawer element wasn't found, return null
558
+ // The handleToggle() will handle waiting for the element to appear
559
+ if (element.hasAttribute('data-kt-drawer-toggle')) {
560
+ }
561
+ return null;
562
+ }
563
+ if (data_1.default.has(drawerElement, 'drawer')) {
564
+ return data_1.default.get(drawerElement, 'drawer');
410
565
  }
411
- if (element.getAttribute('data-kt-drawer-initialized') === 'true') {
412
- return new KTDrawer(element);
566
+ if (drawerElement.getAttribute('data-kt-drawer-initialized') === 'true') {
567
+ return new KTDrawer(drawerElement);
413
568
  }
414
569
  return null;
415
570
  };
@@ -442,16 +597,62 @@ var KTDrawer = /** @class */ (function (_super) {
442
597
  });
443
598
  };
444
599
  KTDrawer.handleToggle = function () {
600
+ // Add raw click listener to document.body to track all clicks
601
+ document.body.addEventListener('click', function (rawEvent) {
602
+ var target = rawEvent.target;
603
+ if (target && target.hasAttribute('data-kt-drawer-toggle')) {
604
+ }
605
+ }, true); // Use capture phase to catch before any stopPropagation
445
606
  event_handler_1.default.on(document.body, '[data-kt-drawer-toggle]', 'click', function (event, target) {
607
+ var _a;
446
608
  event.stopPropagation();
447
609
  var selector = target.getAttribute('data-kt-drawer-toggle');
448
610
  if (!selector)
449
611
  return;
450
- var drawerEl = document.querySelector(selector);
451
- var drawer = KTDrawer.getInstance(drawerEl);
612
+ // Try to get instance immediately
613
+ var drawer = KTDrawer.getInstance(target);
452
614
  if (drawer) {
453
615
  drawer.toggle();
454
616
  }
617
+ else {
618
+ // Drawer element not found - wait for it to appear (handles persisted Livewire components)
619
+ // Check if drawer exists in persisted components (might be in header that's persisted)
620
+ var persistedHeader = ((_a = document.querySelector('[wire\\:id]')) === null || _a === void 0 ? void 0 : _a.closest('[wire\\:id]')) || document.querySelector('header#header');
621
+ var drawerInPersisted = persistedHeader ? persistedHeader.querySelector(selector) : null;
622
+ // Wait longer for persisted components that may take time to render
623
+ // Also check if drawer exists in persisted header component
624
+ KTDrawer.waitForElement(selector, 5000).then(function (drawerElement) {
625
+ if (drawerElement) {
626
+ // Initialize the drawer if not already initialized
627
+ if (!data_1.default.has(drawerElement, 'drawer')) {
628
+ new KTDrawer(drawerElement);
629
+ }
630
+ // Get instance and toggle
631
+ var drawerInstance = KTDrawer.getInstance(drawerElement);
632
+ if (drawerInstance) {
633
+ drawerInstance.toggle();
634
+ }
635
+ }
636
+ else {
637
+ // Drawer never appeared - trigger a reinit to see if it helps
638
+ // This handles cases where drawers are in persisted components that haven't rendered yet
639
+ setTimeout(function () {
640
+ KTDrawer.reinit();
641
+ // Try one more time after reinit
642
+ var drawerAfterReinit = document.querySelector(selector) || document.body.querySelector(selector);
643
+ if (drawerAfterReinit) {
644
+ if (!data_1.default.has(drawerAfterReinit, 'drawer')) {
645
+ new KTDrawer(drawerAfterReinit);
646
+ }
647
+ var drawerInstance = KTDrawer.getInstance(drawerAfterReinit);
648
+ if (drawerInstance) {
649
+ drawerInstance.toggle();
650
+ }
651
+ }
652
+ }, 500);
653
+ }
654
+ });
655
+ }
455
656
  });
456
657
  };
457
658
  KTDrawer.handleDismiss = function () {
@@ -503,7 +704,12 @@ var KTDrawer = /** @class */ (function (_super) {
503
704
  });
504
705
  };
505
706
  KTDrawer.createInstances = function () {
506
- var elements = document.querySelectorAll('[data-kt-drawer]');
707
+ // Find all drawer elements - check both document and body (drawers with container="body" are moved there)
708
+ var elementsInDoc = document.querySelectorAll('[data-kt-drawer]');
709
+ var elementsInBody = document.body.querySelectorAll('[data-kt-drawer]');
710
+ // Combine and deduplicate
711
+ var allElements = new Set(__spreadArray(__spreadArray([], Array.from(elementsInDoc), true), Array.from(elementsInBody), true));
712
+ var elements = Array.from(allElements);
507
713
  elements.forEach(function (element) {
508
714
  new KTDrawer(element);
509
715
  });
@@ -519,6 +725,46 @@ var KTDrawer = /** @class */ (function (_super) {
519
725
  window.KT_DRAWER_INITIALIZED = true;
520
726
  }
521
727
  };
728
+ /**
729
+ * Force reinitialization of drawers by clearing KTData entries.
730
+ * Useful for Livewire wire:navigate where persisted elements need reinitialization.
731
+ */
732
+ KTDrawer.reinit = function () {
733
+ // Follow the same simple pattern as KTDropdown.reinit()
734
+ // Find all drawer elements - check both document and body (some may be moved to body)
735
+ var elementsInDoc = document.querySelectorAll('[data-kt-drawer]');
736
+ var elementsInBody = document.body.querySelectorAll('[data-kt-drawer]');
737
+ // Combine and deduplicate
738
+ var allElements = new Set(__spreadArray(__spreadArray([], Array.from(elementsInDoc), true), Array.from(elementsInBody), true));
739
+ var elements = Array.from(allElements);
740
+ // Clean up existing instances
741
+ elements.forEach(function (element) {
742
+ try {
743
+ // Get existing instance to clean up
744
+ var instance = KTDrawer.getInstance(element);
745
+ if (instance && typeof instance.hide === 'function') {
746
+ instance.hide(); // This will clean up backdrop and state
747
+ }
748
+ // Clear KTData entries
749
+ var hadDrawer = data_1.default.has(element, 'drawer');
750
+ data_1.default.remove(element, 'drawer');
751
+ // Remove initialization attribute to allow fresh initialization
752
+ element.removeAttribute('data-kt-drawer-initialized');
753
+ }
754
+ catch (e) {
755
+ // Ignore errors for individual elements
756
+ }
757
+ });
758
+ // Now create fresh instances
759
+ KTDrawer.createInstances();
760
+ // Always ensure handlers are set up (similar to KTMenu.init() behavior)
761
+ // Event handlers use delegation so they persist, but we ensure they're attached
762
+ KTDrawer.handleToggle();
763
+ KTDrawer.handleDismiss();
764
+ KTDrawer.handleResize();
765
+ KTDrawer.handleClickAway();
766
+ KTDrawer.handleKeyword();
767
+ };
522
768
  return KTDrawer;
523
769
  }(component_1.default));
524
770
  exports.KTDrawer = KTDrawer;
@@ -1929,6 +2175,28 @@ var KTComponent = /** @class */ (function () {
1929
2175
  this._uid = null;
1930
2176
  this._element = null;
1931
2177
  }
2178
+ /**
2179
+ * Check if component should skip initialization
2180
+ * Returns true if element already has an instance and is still connected to DOM
2181
+ * Returns false if element should be initialized (no instance or disconnected)
2182
+ * @param element The element to check
2183
+ * @returns true if initialization should be skipped, false otherwise
2184
+ */
2185
+ KTComponent.prototype._shouldSkipInit = function (element) {
2186
+ if (!data_1.default.has(element, this._name)) {
2187
+ return false;
2188
+ }
2189
+ var existingInstance = data_1.default.get(element, this._name);
2190
+ // If element is not connected to DOM, dispose old instance and allow reinitialization
2191
+ if (element.isConnected === false) {
2192
+ if (existingInstance && typeof existingInstance.dispose === 'function') {
2193
+ existingInstance.dispose();
2194
+ }
2195
+ return false;
2196
+ }
2197
+ // Element is connected and has instance, skip initialization
2198
+ return true;
2199
+ };
1932
2200
  KTComponent.prototype._init = function (element) {
1933
2201
  element = dom_1.default.getElement(element);
1934
2202
  if (!element) {
@@ -2307,8 +2575,12 @@ var KTSticky = /** @class */ (function (_super) {
2307
2575
  };
2308
2576
  _this._config = _this._defaultConfig;
2309
2577
  _this._targetElement = null;
2310
- if (data_1.default.has(element, _this._name))
2578
+ _this._resizeHandler = null;
2579
+ _this._scrollHandler = null;
2580
+ // Check if element already has an instance and is still connected
2581
+ if (_this._shouldSkipInit(element)) {
2311
2582
  return _this;
2583
+ }
2312
2584
  _this._init(element);
2313
2585
  _this._buildConfig(config);
2314
2586
  _this._releaseElement = dom_1.default.getElement(_this._getOption('release'));
@@ -2334,15 +2606,26 @@ var KTSticky = /** @class */ (function (_super) {
2334
2606
  };
2335
2607
  KTSticky.prototype._handlers = function () {
2336
2608
  var _this = this;
2337
- window.addEventListener('resize', function () {
2609
+ // Store resize handler reference for cleanup
2610
+ this._resizeHandler = function () {
2338
2611
  var timer;
2339
2612
  utils_1.default.throttle(timer, function () {
2340
2613
  _this._update();
2341
2614
  }, 200);
2342
- });
2343
- this._targetElement.addEventListener('scroll', function () {
2615
+ };
2616
+ window.addEventListener('resize', this._resizeHandler);
2617
+ // Store scroll handler reference for cleanup
2618
+ this._scrollHandler = function () {
2344
2619
  _this._process();
2345
- });
2620
+ };
2621
+ if (this._targetElement) {
2622
+ if (this._targetElement === document) {
2623
+ window.addEventListener('scroll', this._scrollHandler);
2624
+ }
2625
+ else {
2626
+ this._targetElement.addEventListener('scroll', this._scrollHandler);
2627
+ }
2628
+ }
2346
2629
  };
2347
2630
  KTSticky.prototype._process = function () {
2348
2631
  var reverse = this._getOption('reverse');
@@ -2583,6 +2866,30 @@ var KTSticky = /** @class */ (function (_super) {
2583
2866
  KTSticky.prototype.isActive = function () {
2584
2867
  return this._isActive();
2585
2868
  };
2869
+ KTSticky.prototype.dispose = function () {
2870
+ // Remove resize event listener
2871
+ if (this._resizeHandler) {
2872
+ window.removeEventListener('resize', this._resizeHandler);
2873
+ this._resizeHandler = null;
2874
+ }
2875
+ // Remove scroll event listener
2876
+ if (this._scrollHandler) {
2877
+ if (this._targetElement === document) {
2878
+ window.removeEventListener('scroll', this._scrollHandler);
2879
+ }
2880
+ else if (this._targetElement) {
2881
+ this._targetElement.removeEventListener('scroll', this._scrollHandler);
2882
+ }
2883
+ this._scrollHandler = null;
2884
+ }
2885
+ // Clean up state
2886
+ this._disable();
2887
+ if (this._attributeRoot && document.body.hasAttribute(this._attributeRoot)) {
2888
+ document.body.removeAttribute(this._attributeRoot);
2889
+ }
2890
+ // Call parent dispose to clean up data attributes and KTData
2891
+ _super.prototype.dispose.call(this);
2892
+ };
2586
2893
  KTSticky.getInstance = function (element) {
2587
2894
  if (!element)
2588
2895
  return null;
@@ -5743,13 +6050,14 @@ var KTEventHandler = {
5743
6050
  }
5744
6051
  var eventId = utils_1.default.geUID('event');
5745
6052
  KTDelegatedEventHandlers[eventId] = function (event) {
5746
- var targets = element.querySelectorAll(selector);
6053
+ // Fix: Check selector dynamically instead of pre-computing targets
6054
+ // This allows event delegation to work with dynamically added elements
5747
6055
  var target = event.target;
5748
6056
  while (target && target !== element) {
5749
- for (var i = 0, j = targets.length; i < j; i++) {
5750
- if (target === targets[i]) {
5751
- handler.call(_this, event, target);
5752
- }
6057
+ // Check if current target matches the selector
6058
+ if (target.matches && target.matches(selector)) {
6059
+ handler.call(_this, event, target);
6060
+ return; // Stop bubbling once we've handled it
5753
6061
  }
5754
6062
  target = target.parentNode;
5755
6063
  }
@@ -8090,7 +8398,13 @@ var KTDataTable = /** @class */ (function (_super) {
8090
8398
  * @returns The KTDataTable instance or undefined if not found
8091
8399
  */
8092
8400
  KTDataTable.getInstance = function (element) {
8093
- return this._instances.get(element);
8401
+ // First check the static Map (for instances created via createInstances)
8402
+ var instanceFromMap = this._instances.get(element);
8403
+ if (instanceFromMap) {
8404
+ return instanceFromMap;
8405
+ }
8406
+ // Fallback to element's instance property (for manually created instances)
8407
+ return element.instance;
8094
8408
  };
8095
8409
  /**
8096
8410
  * Initializes all KTDataTable instances on the page.
@@ -9391,6 +9705,7 @@ var KTSelectSearch = /** @class */ (function () {
9391
9705
  * Handles keydown events on the search input for navigation and actions.
9392
9706
  */
9393
9707
  KTSelectSearch.prototype._handleSearchKeyDown = function (event) {
9708
+ var _this = this;
9394
9709
  var key = event.key;
9395
9710
  switch (key) {
9396
9711
  case ' ': // Spacebar
@@ -9408,19 +9723,28 @@ var KTSelectSearch = /** @class */ (function () {
9408
9723
  break;
9409
9724
  case 'Enter':
9410
9725
  event.preventDefault();
9411
- // Always attempt to select the first available option in the list.
9412
- // focusFirst() finds, focuses, and returns the first visible, non-disabled option.
9413
9726
  var firstAvailableOption = this._focusManager.focusFirst();
9414
9727
  if (firstAvailableOption) {
9415
9728
  var optionValue = firstAvailableOption.getAttribute('data-value');
9416
9729
  if (optionValue) {
9417
- // toggleSelection() already handles closing the dropdown based on closeOnEnter config
9418
- // for single-select mode, so we don't need to call closeDropdown() here
9419
- this._select.toggleSelection(optionValue);
9420
- // If closeOnEnter is false, dropdown remains open for additional selections
9730
+ var config = this._select.getConfig();
9731
+ var isAlreadySelected = !config.multiple && this._select.getSelectedOptions().includes(optionValue);
9732
+ var shouldClose = !config.multiple && config.closeOnEnter !== false;
9733
+ if (isAlreadySelected && shouldClose) {
9734
+ this._select.closeDropdown();
9735
+ }
9736
+ else {
9737
+ this._select.toggleSelection(optionValue);
9738
+ }
9739
+ // Focus display element after closing so user can press Enter again
9740
+ if (shouldClose) {
9741
+ setTimeout(function () {
9742
+ var _a;
9743
+ (_a = _this._select.getDisplayElement()) === null || _a === void 0 ? void 0 : _a.focus();
9744
+ }, 0);
9745
+ }
9421
9746
  }
9422
9747
  }
9423
- // If no available option, do nothing (dropdown remains open)
9424
9748
  break;
9425
9749
  case 'Escape':
9426
9750
  event.preventDefault();
@@ -9790,21 +10114,29 @@ var KTSelect = /** @class */ (function (_super) {
9790
10114
  // Also dispatch on document if configured
9791
10115
  var dispatchGlobalEvents = this._config.dispatchGlobalEvents !== false; // Default to true
9792
10116
  if (dispatchGlobalEvents) {
9793
- // Create namespaced event name for document dispatch
10117
+ // Create event detail structure
10118
+ var eventDetail = {
10119
+ payload: payload,
10120
+ instance: this, // Include component instance reference
10121
+ element: this._element, // Include element reference
10122
+ };
10123
+ // Dispatch non-namespaced event on document (for jQuery compatibility: $(document).on('show', ...))
10124
+ var nonNamespacedEvent = new CustomEvent(eventType, {
10125
+ detail: eventDetail,
10126
+ bubbles: true,
10127
+ cancelable: true,
10128
+ composed: true, // Allow event to cross shadow DOM boundaries
10129
+ });
10130
+ document.dispatchEvent(nonNamespacedEvent);
10131
+ // Also dispatch namespaced event on document (for namespaced listeners: $(document).on('kt-select:show', ...))
9794
10132
  var namespacedEventType = "kt-select:".concat(eventType);
9795
- // Create event with same detail structure
9796
- var globalEvent = new CustomEvent(namespacedEventType, {
9797
- detail: {
9798
- payload: payload,
9799
- instance: this, // Include component instance reference
9800
- element: this._element, // Include element reference
9801
- },
10133
+ var namespacedEvent = new CustomEvent(namespacedEventType, {
10134
+ detail: eventDetail,
9802
10135
  bubbles: true,
9803
10136
  cancelable: true,
9804
10137
  composed: true, // Allow event to cross shadow DOM boundaries
9805
10138
  });
9806
- // Dispatch on document
9807
- document.dispatchEvent(globalEvent);
10139
+ document.dispatchEvent(namespacedEvent);
9808
10140
  }
9809
10141
  };
9810
10142
  /**
@@ -10494,7 +10826,23 @@ var KTSelect = /** @class */ (function (_super) {
10494
10826
  // Update select all button state
10495
10827
  this.updateSelectAllButtonState();
10496
10828
  // Focus the first selected option or first option if nothing selected
10497
- this._focusSelectedOption();
10829
+ // BUT: Skip this if search autofocus is enabled, as we want search input to get focus
10830
+ if (!(this._config.enableSearch && this._config.searchAutofocus)) {
10831
+ this._focusSelectedOption();
10832
+ }
10833
+ // Dispatch dropdown.show event on the wrapper element for search module
10834
+ // Use requestAnimationFrame to ensure dropdown is visible and transition has started
10835
+ requestAnimationFrame(function () {
10836
+ requestAnimationFrame(function () {
10837
+ if (_this._wrapperElement) {
10838
+ var dropdownShowEvent_1 = new CustomEvent('dropdown.show', {
10839
+ bubbles: true,
10840
+ cancelable: true,
10841
+ });
10842
+ _this._wrapperElement.dispatchEvent(dropdownShowEvent_1);
10843
+ }
10844
+ });
10845
+ });
10498
10846
  };
10499
10847
  /**
10500
10848
  * Close the dropdown
@@ -10523,7 +10871,7 @@ var KTSelect = /** @class */ (function (_super) {
10523
10871
  if (this._focusManager) {
10524
10872
  this._focusManager.resetFocus();
10525
10873
  }
10526
- // Dispatch custom events
10874
+ // Dispatch custom events on the select element
10527
10875
  this._dispatchEvent('close');
10528
10876
  this._fireEvent('close');
10529
10877
  // Dispatch dropdown.close event on wrapper for search module
@@ -10747,6 +11095,55 @@ var KTSelect = /** @class */ (function (_super) {
10747
11095
  this._dispatchEvent('change');
10748
11096
  this._fireEvent('change');
10749
11097
  };
11098
+ /**
11099
+ * Deselect a specific option by value
11100
+ * @param value The value of the option to deselect
11101
+ * @public
11102
+ */
11103
+ KTSelect.prototype.deselectOption = function (value) {
11104
+ // Check if the option is currently selected
11105
+ if (!this._state.isSelected(value)) {
11106
+ return; // Already deselected
11107
+ }
11108
+ // For single-select mode, check if clearing is allowed
11109
+ if (!this._config.multiple && !this._config.allowClear) {
11110
+ return; // Cannot deselect in single-select mode unless allowClear is true
11111
+ }
11112
+ // Remove from selected options
11113
+ if (this._config.multiple) {
11114
+ // For multiple select, just toggle it off
11115
+ this._state.toggleSelectedOptions(value);
11116
+ }
11117
+ else {
11118
+ // For single select, clear all selections
11119
+ this._state.setSelectedOptions([]);
11120
+ }
11121
+ // Update the native select element
11122
+ var optionEl = Array.from(this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
11123
+ if (optionEl) {
11124
+ optionEl.selected = false;
11125
+ }
11126
+ // For single select, clear the native select value
11127
+ if (!this._config.multiple) {
11128
+ this._element.value = '';
11129
+ }
11130
+ // Update the display
11131
+ this.updateSelectedOptionDisplay();
11132
+ this._updateSelectedOptionClass();
11133
+ // Update select all button state
11134
+ this.updateSelectAllButtonState();
11135
+ // Dispatch change event
11136
+ this._dispatchEvent('change', {
11137
+ value: value,
11138
+ selected: false,
11139
+ selectedOptions: this.getSelectedOptions(),
11140
+ });
11141
+ this._fireEvent('change', {
11142
+ value: value,
11143
+ selected: false,
11144
+ selectedOptions: this.getSelectedOptions(),
11145
+ });
11146
+ };
10750
11147
  /**
10751
11148
  * Set selected options programmatically
10752
11149
  */
@@ -10948,9 +11345,14 @@ var KTSelect = /** @class */ (function (_super) {
10948
11345
  }
10949
11346
  // Get current selection state
10950
11347
  var isSelected = this._state.isSelected(value);
10951
- // If already selected in single select mode, do nothing (can't deselect in single select)
11348
+ // If already selected in single select mode, allow deselecting only if allowClear is true
10952
11349
  if (isSelected && !this._config.multiple) {
10953
- return;
11350
+ if (this._config.allowClear) {
11351
+ // Use the deselectOption method to handle clearing
11352
+ this.deselectOption(value);
11353
+ return;
11354
+ }
11355
+ return; // Can't deselect in single select mode when allowClear is false
10954
11356
  }
10955
11357
  // Ensure any search input is cleared when selection changes
10956
11358
  if (this._searchModule) {
@@ -12019,16 +12421,19 @@ var KTDropdown = /** @class */ (function (_super) {
12019
12421
  _this._disabled = false;
12020
12422
  _this._isTransitioning = false;
12021
12423
  _this._isOpen = false;
12022
- if (data_1.default.has(element, _this._name))
12424
+ if (data_1.default.has(element, _this._name)) {
12023
12425
  return _this;
12426
+ }
12024
12427
  _this._init(element);
12025
12428
  _this._buildConfig(config);
12026
12429
  _this._toggleElement = _this._element.querySelector('[data-kt-dropdown-toggle]');
12027
- if (!_this._toggleElement)
12430
+ if (!_this._toggleElement) {
12028
12431
  return _this;
12432
+ }
12029
12433
  _this._menuElement = _this._element.querySelector('[data-kt-dropdown-menu]');
12030
- if (!_this._menuElement)
12434
+ if (!_this._menuElement) {
12031
12435
  return _this;
12436
+ }
12032
12437
  data_1.default.set(_this._menuElement, 'dropdownElement', _this._element);
12033
12438
  _this._setupNestedDropdowns();
12034
12439
  _this._handleContainer();
@@ -12061,10 +12466,12 @@ var KTDropdown = /** @class */ (function (_super) {
12061
12466
  KTDropdown.prototype._click = function (event) {
12062
12467
  event.preventDefault();
12063
12468
  event.stopPropagation();
12064
- if (this._disabled)
12469
+ if (this._disabled) {
12065
12470
  return;
12066
- if (this._getOption('trigger') !== 'click')
12471
+ }
12472
+ if (this._getOption('trigger') !== 'click') {
12067
12473
  return;
12474
+ }
12068
12475
  this._toggle();
12069
12476
  };
12070
12477
  KTDropdown.prototype._mouseover = function (event) {
@@ -12107,8 +12514,9 @@ var KTDropdown = /** @class */ (function (_super) {
12107
12514
  };
12108
12515
  KTDropdown.prototype._show = function () {
12109
12516
  var _this = this;
12110
- if (this._isOpen || this._isTransitioning)
12517
+ if (this._isOpen || this._isTransitioning) {
12111
12518
  return;
12519
+ }
12112
12520
  var payload = { cancel: false };
12113
12521
  this._fireEvent('show', payload);
12114
12522
  this._dispatchEvent('show', payload);
@@ -12281,6 +12689,12 @@ var KTDropdown = /** @class */ (function (_super) {
12281
12689
  reference.closest('[data-kt-dropdown-initialized]');
12282
12690
  if (findElement)
12283
12691
  return findElement;
12692
+ // Fallback: look for parent with data-kt-dropdown attribute
12693
+ if (reference) {
12694
+ var dropdownContainer = reference.closest('[data-kt-dropdown]');
12695
+ if (dropdownContainer)
12696
+ return dropdownContainer;
12697
+ }
12284
12698
  if (reference &&
12285
12699
  reference.hasAttribute('data-kt-dropdown-menu') &&
12286
12700
  data_1.default.has(reference, 'dropdownElement')) {
@@ -12290,10 +12704,12 @@ var KTDropdown = /** @class */ (function (_super) {
12290
12704
  };
12291
12705
  KTDropdown.getInstance = function (element) {
12292
12706
  element = this.getElement(element);
12293
- if (!element)
12707
+ if (!element) {
12294
12708
  return null;
12709
+ }
12295
12710
  if (data_1.default.has(element, 'dropdown')) {
12296
- return data_1.default.get(element, 'dropdown');
12711
+ var instance = data_1.default.get(element, 'dropdown');
12712
+ return instance;
12297
12713
  }
12298
12714
  if (element.getAttribute('data-kt-dropdown-initialized') === 'true') {
12299
12715
  return new KTDropdown(element);
@@ -12408,6 +12824,39 @@ var KTDropdown = /** @class */ (function (_super) {
12408
12824
  window.KT_DROPDOWN_INITIALIZED = true;
12409
12825
  }
12410
12826
  };
12827
+ /**
12828
+ * Force reinitialization of dropdowns by clearing KTData entries.
12829
+ * Useful for Livewire wire:navigate where persisted elements need reinitialization.
12830
+ */
12831
+ KTDropdown.reinit = function () {
12832
+ var elements = document.querySelectorAll('[data-kt-dropdown]');
12833
+ elements.forEach(function (element) {
12834
+ try {
12835
+ // Get existing instance to clean up Popper
12836
+ var instance = KTDropdown.getInstance(element);
12837
+ if (instance && typeof instance.hide === 'function') {
12838
+ instance.hide(); // This will destroy Popper
12839
+ }
12840
+ // Clear KTData entries
12841
+ data_1.default.remove(element, 'dropdown');
12842
+ data_1.default.remove(element, 'popper');
12843
+ // Remove initialization attribute to allow fresh initialization
12844
+ element.removeAttribute('data-kt-dropdown-initialized');
12845
+ var menu = element.querySelector('[data-kt-dropdown-menu]');
12846
+ if (menu) {
12847
+ data_1.default.remove(menu, 'dropdownElement');
12848
+ }
12849
+ }
12850
+ catch (e) {
12851
+ // Ignore errors for individual elements
12852
+ }
12853
+ });
12854
+ // Now create fresh instances
12855
+ KTDropdown.createInstances();
12856
+ // Always ensure handlers are set up (similar to KTMenu.init() behavior)
12857
+ // Event handlers use delegation so they persist, but we ensure they're attached
12858
+ KTDropdown.initHandlers();
12859
+ };
12411
12860
  return KTDropdown;
12412
12861
  }(component_1.default));
12413
12862
  exports.KTDropdown = KTDropdown;
@@ -12471,7 +12920,15 @@ var KTData = {
12471
12920
  KTElementMap.delete(element);
12472
12921
  }
12473
12922
  },
12923
+ // Clear all data for a specific element (useful for reinitialization)
12924
+ clear: function (element) {
12925
+ KTElementMap.delete(element);
12926
+ },
12474
12927
  };
12928
+ // Expose KTData on window for external access (useful for Livewire wire:navigate)
12929
+ if (typeof window !== 'undefined') {
12930
+ window.KTData = KTData;
12931
+ }
12475
12932
  exports["default"] = KTData;
12476
12933
 
12477
12934