@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.
- package/dist/ktui.js +506 -49
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +12 -0
- package/lib/cjs/components/component.js +22 -0
- package/lib/cjs/components/component.js.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +7 -1
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/drawer/drawer.js +255 -9
- package/lib/cjs/components/drawer/drawer.js.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.js +55 -8
- package/lib/cjs/components/dropdown/dropdown.js.map +1 -1
- package/lib/cjs/components/select/search.js +17 -7
- package/lib/cjs/components/select/search.js.map +1 -1
- package/lib/cjs/components/select/select.js +92 -14
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/cjs/components/sticky/sticky.js +44 -5
- package/lib/cjs/components/sticky/sticky.js.map +1 -1
- package/lib/cjs/helpers/data.js +8 -0
- package/lib/cjs/helpers/data.js.map +1 -1
- package/lib/cjs/helpers/event-handler.js +6 -5
- package/lib/cjs/helpers/event-handler.js.map +1 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/components/component.js +22 -0
- package/lib/esm/components/component.js.map +1 -1
- package/lib/esm/components/datatable/datatable.js +7 -1
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/drawer/drawer.js +255 -9
- package/lib/esm/components/drawer/drawer.js.map +1 -1
- package/lib/esm/components/dropdown/dropdown.js +55 -8
- package/lib/esm/components/dropdown/dropdown.js.map +1 -1
- package/lib/esm/components/select/search.js +17 -7
- package/lib/esm/components/select/search.js.map +1 -1
- package/lib/esm/components/select/select.js +92 -14
- package/lib/esm/components/select/select.js.map +1 -1
- package/lib/esm/components/sticky/sticky.js +44 -5
- package/lib/esm/components/sticky/sticky.js.map +1 -1
- package/lib/esm/helpers/data.js +8 -0
- package/lib/esm/helpers/data.js.map +1 -1
- package/lib/esm/helpers/event-handler.js +6 -5
- package/lib/esm/helpers/event-handler.js.map +1 -1
- package/lib/esm/index.js.map +1 -1
- package/package.json +4 -2
- package/src/components/component.ts +26 -0
- package/src/components/datatable/__tests__/race-conditions.test.ts +2 -2
- package/src/components/datatable/datatable.ts +8 -1
- package/src/components/drawer/drawer.ts +266 -10
- package/src/components/dropdown/dropdown.ts +63 -8
- package/src/components/select/__tests__/ux-behaviors.test.ts +382 -4
- package/src/components/select/search.ts +16 -7
- package/src/components/select/select.css +5 -1
- package/src/components/select/select.ts +105 -16
- package/src/components/sticky/sticky.ts +55 -5
- package/src/helpers/data.ts +10 -0
- package/src/helpers/event-handler.ts +7 -6
- package/src/index.ts +2 -0
|
@@ -43,13 +43,16 @@ export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
|
|
43
43
|
constructor(element: HTMLElement, config?: KTDrawerConfigInterface) {
|
|
44
44
|
super();
|
|
45
45
|
|
|
46
|
-
if (KTData.has(element as HTMLElement, this._name))
|
|
46
|
+
if (KTData.has(element as HTMLElement, this._name)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
47
49
|
|
|
48
50
|
this._init(element);
|
|
49
51
|
this._buildConfig(config);
|
|
50
52
|
this._handleClose();
|
|
51
53
|
this._update();
|
|
52
54
|
this._handleContainer();
|
|
55
|
+
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
protected _handleClose(): void {
|
|
@@ -88,6 +91,28 @@ export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
|
|
88
91
|
|
|
89
92
|
KTDrawer.hide();
|
|
90
93
|
|
|
94
|
+
// If drawer needs to be in front of backdrop, ensure it's in body (for proper z-index stacking)
|
|
95
|
+
// This ensures the drawer and backdrop are in the same stacking context
|
|
96
|
+
if (this._getOption('container') === 'body' && this._element.parentElement !== document.body) {
|
|
97
|
+
// Store original parent for restoration when hiding
|
|
98
|
+
if (!this._element.hasAttribute('data-kt-drawer-original-parent-id')) {
|
|
99
|
+
const originalParent = this._element.parentElement;
|
|
100
|
+
if (originalParent && originalParent !== document.body) {
|
|
101
|
+
this._element.setAttribute('data-kt-drawer-original-parent-id', originalParent.id || '');
|
|
102
|
+
// Store a reference to find the parent later (using closest to find Livewire component or header)
|
|
103
|
+
const livewireComponent = originalParent.closest('[wire\\:id]');
|
|
104
|
+
const header = originalParent.closest('header#header');
|
|
105
|
+
if (livewireComponent) {
|
|
106
|
+
this._element.setAttribute('data-kt-drawer-original-wire-id', (livewireComponent as HTMLElement).getAttribute('wire:id') || '');
|
|
107
|
+
}
|
|
108
|
+
if (header) {
|
|
109
|
+
this._element.setAttribute('data-kt-drawer-original-in-header', 'true');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
document.body.appendChild(this._element);
|
|
114
|
+
}
|
|
115
|
+
|
|
91
116
|
if (this._getOption('backdrop') === true) this._createBackdrop();
|
|
92
117
|
|
|
93
118
|
if (relatedTarget) this._relatedTarget = relatedTarget;
|
|
@@ -162,6 +187,10 @@ export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
|
|
162
187
|
this._element.classList.remove(this._getOption('shownClass') as string);
|
|
163
188
|
this._element.style.zIndex = '';
|
|
164
189
|
|
|
190
|
+
// Note: We don't move drawer back to original location here
|
|
191
|
+
// Livewire will handle DOM structure on next navigation, and drawer will be reinitialized
|
|
192
|
+
// in its original location from the persisted component HTML
|
|
193
|
+
|
|
165
194
|
this._fireEvent('hidden');
|
|
166
195
|
this._dispatchEvent('hidden');
|
|
167
196
|
});
|
|
@@ -180,7 +209,25 @@ export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
|
|
180
209
|
protected _handleContainer(): void {
|
|
181
210
|
if (this._getOption('container')) {
|
|
182
211
|
if (this._getOption('container') === 'body') {
|
|
183
|
-
|
|
212
|
+
// Check if drawer is in a persisted Livewire component (like header with @persist)
|
|
213
|
+
// If so, don't move it to body - keep it in place so Livewire can preserve it
|
|
214
|
+
// This follows the same pattern as dropdowns/menus which work with wire:navigate
|
|
215
|
+
const originalParent = this._element.parentNode;
|
|
216
|
+
const isInPersistedComponent = originalParent &&
|
|
217
|
+
((originalParent as HTMLElement).closest('[wire\\:id]') !== null ||
|
|
218
|
+
(originalParent as HTMLElement).closest('header#header') !== null);
|
|
219
|
+
|
|
220
|
+
if (isInPersistedComponent) {
|
|
221
|
+
// Don't move to body - keep in original location for Livewire persistence
|
|
222
|
+
// Use fixed positioning to achieve the same visual effect
|
|
223
|
+
// Ensure drawer has fixed positioning to work from its current location
|
|
224
|
+
if (!this._element.style.position || this._element.style.position === 'static') {
|
|
225
|
+
this._element.style.position = 'fixed';
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
// Not in persisted component - safe to move to body (follows original behavior)
|
|
229
|
+
document.body.appendChild(this._element);
|
|
230
|
+
}
|
|
184
231
|
} else {
|
|
185
232
|
document
|
|
186
233
|
.querySelector(this._getOption('container') as string)
|
|
@@ -265,15 +312,128 @@ export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
|
|
265
312
|
return this._isEnabled();
|
|
266
313
|
}
|
|
267
314
|
|
|
315
|
+
public static getElement(reference: HTMLElement): HTMLElement {
|
|
316
|
+
if (reference && reference.hasAttribute('data-kt-drawer-initialized'))
|
|
317
|
+
return reference;
|
|
318
|
+
|
|
319
|
+
const findElement =
|
|
320
|
+
reference &&
|
|
321
|
+
(reference.closest('[data-kt-drawer-initialized]') as HTMLElement);
|
|
322
|
+
if (findElement) return findElement;
|
|
323
|
+
|
|
324
|
+
// Fallback: look for parent with data-kt-drawer attribute
|
|
325
|
+
if (reference) {
|
|
326
|
+
const drawerContainer = reference.closest('[data-kt-drawer]') as HTMLElement;
|
|
327
|
+
if (drawerContainer) return drawerContainer;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// If reference is a toggle button with a selector, find the drawer by selector
|
|
331
|
+
// This handles cases where the toggle button is not a child of the drawer
|
|
332
|
+
if (reference && reference.hasAttribute('data-kt-drawer-toggle')) {
|
|
333
|
+
const selector = reference.getAttribute('data-kt-drawer-toggle');
|
|
334
|
+
if (selector) {
|
|
335
|
+
// Check both document and body (drawers with container="body" are moved to body)
|
|
336
|
+
const drawerElInDoc = document.querySelector(selector);
|
|
337
|
+
const drawerElInBody = document.body.querySelector(selector);
|
|
338
|
+
const drawerEl = drawerElInDoc || drawerElInBody;
|
|
339
|
+
if (drawerEl) return drawerEl as HTMLElement;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Wait for an element to appear in the DOM using polling with MutationObserver fallback
|
|
348
|
+
* Useful for persisted Livewire components that may not be in DOM immediately
|
|
349
|
+
*/
|
|
350
|
+
public static waitForElement(selector: string, timeout: number = 2000): Promise<HTMLElement | null> {
|
|
351
|
+
return new Promise((resolve) => {
|
|
352
|
+
let resolved = false;
|
|
353
|
+
|
|
354
|
+
const doResolve = (element: HTMLElement | null) => {
|
|
355
|
+
if (!resolved) {
|
|
356
|
+
resolved = true;
|
|
357
|
+
resolve(element);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// Check if element already exists
|
|
362
|
+
const existing = document.querySelector(selector) || document.body.querySelector(selector);
|
|
363
|
+
if (existing) {
|
|
364
|
+
doResolve(existing as HTMLElement);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Use polling for faster detection (check every 50ms)
|
|
369
|
+
let attempts = 0;
|
|
370
|
+
const maxAttempts = timeout / 50;
|
|
371
|
+
const pollInterval = setInterval(() => {
|
|
372
|
+
if (resolved) {
|
|
373
|
+
clearInterval(pollInterval);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
attempts++;
|
|
377
|
+
const element = document.querySelector(selector) || document.body.querySelector(selector);
|
|
378
|
+
if (element) {
|
|
379
|
+
clearInterval(pollInterval);
|
|
380
|
+
doResolve(element as HTMLElement);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (attempts >= maxAttempts) {
|
|
384
|
+
clearInterval(pollInterval);
|
|
385
|
+
doResolve(null);
|
|
386
|
+
}
|
|
387
|
+
}, 50);
|
|
388
|
+
|
|
389
|
+
// Also use MutationObserver as backup for immediate detection
|
|
390
|
+
const observer = new MutationObserver(() => {
|
|
391
|
+
if (resolved) {
|
|
392
|
+
observer.disconnect();
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
const element = document.querySelector(selector) || document.body.querySelector(selector);
|
|
396
|
+
if (element) {
|
|
397
|
+
clearInterval(pollInterval);
|
|
398
|
+
observer.disconnect();
|
|
399
|
+
doResolve(element as HTMLElement);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
observer.observe(document.body, {
|
|
404
|
+
childList: true,
|
|
405
|
+
subtree: true,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// Cleanup on timeout
|
|
409
|
+
setTimeout(() => {
|
|
410
|
+
if (!resolved) {
|
|
411
|
+
clearInterval(pollInterval);
|
|
412
|
+
observer.disconnect();
|
|
413
|
+
doResolve(null);
|
|
414
|
+
}
|
|
415
|
+
}, timeout);
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
|
|
268
419
|
public static getInstance(element: HTMLElement): KTDrawer {
|
|
269
420
|
if (!element) return null;
|
|
270
421
|
|
|
271
|
-
|
|
272
|
-
|
|
422
|
+
const drawerElement = KTDrawer.getElement(element);
|
|
423
|
+
if (!drawerElement) {
|
|
424
|
+
// If element is a toggle button and drawer element wasn't found, return null
|
|
425
|
+
// The handleToggle() will handle waiting for the element to appear
|
|
426
|
+
if (element.hasAttribute('data-kt-drawer-toggle')) {
|
|
427
|
+
}
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (KTData.has(drawerElement, 'drawer')) {
|
|
432
|
+
return KTData.get(drawerElement, 'drawer') as KTDrawer;
|
|
273
433
|
}
|
|
274
434
|
|
|
275
|
-
if (
|
|
276
|
-
return new KTDrawer(
|
|
435
|
+
if (drawerElement.getAttribute('data-kt-drawer-initialized') === 'true') {
|
|
436
|
+
return new KTDrawer(drawerElement);
|
|
277
437
|
}
|
|
278
438
|
|
|
279
439
|
return null;
|
|
@@ -322,6 +482,14 @@ export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
|
|
322
482
|
}
|
|
323
483
|
|
|
324
484
|
public static handleToggle(): void {
|
|
485
|
+
|
|
486
|
+
// Add raw click listener to document.body to track all clicks
|
|
487
|
+
document.body.addEventListener('click', (rawEvent: MouseEvent) => {
|
|
488
|
+
const target = rawEvent.target as HTMLElement;
|
|
489
|
+
if (target && target.hasAttribute('data-kt-drawer-toggle')) {
|
|
490
|
+
}
|
|
491
|
+
}, true); // Use capture phase to catch before any stopPropagation
|
|
492
|
+
|
|
325
493
|
KTEventHandler.on(
|
|
326
494
|
document.body,
|
|
327
495
|
'[data-kt-drawer-toggle]',
|
|
@@ -332,10 +500,49 @@ export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
|
|
332
500
|
const selector = target.getAttribute('data-kt-drawer-toggle');
|
|
333
501
|
if (!selector) return;
|
|
334
502
|
|
|
335
|
-
|
|
336
|
-
const drawer = KTDrawer.getInstance(
|
|
503
|
+
// Try to get instance immediately
|
|
504
|
+
const drawer = KTDrawer.getInstance(target);
|
|
505
|
+
|
|
337
506
|
if (drawer) {
|
|
338
507
|
drawer.toggle();
|
|
508
|
+
} else {
|
|
509
|
+
// Drawer element not found - wait for it to appear (handles persisted Livewire components)
|
|
510
|
+
// Check if drawer exists in persisted components (might be in header that's persisted)
|
|
511
|
+
const persistedHeader = document.querySelector('[wire\\:id]')?.closest('[wire\\:id]') || document.querySelector('header#header');
|
|
512
|
+
const drawerInPersisted = persistedHeader ? persistedHeader.querySelector(selector) : null;
|
|
513
|
+
|
|
514
|
+
// Wait longer for persisted components that may take time to render
|
|
515
|
+
// Also check if drawer exists in persisted header component
|
|
516
|
+
KTDrawer.waitForElement(selector, 5000).then((drawerElement) => {
|
|
517
|
+
if (drawerElement) {
|
|
518
|
+
// Initialize the drawer if not already initialized
|
|
519
|
+
if (!KTData.has(drawerElement, 'drawer')) {
|
|
520
|
+
new KTDrawer(drawerElement);
|
|
521
|
+
}
|
|
522
|
+
// Get instance and toggle
|
|
523
|
+
const drawerInstance = KTDrawer.getInstance(drawerElement);
|
|
524
|
+
if (drawerInstance) {
|
|
525
|
+
drawerInstance.toggle();
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
// Drawer never appeared - trigger a reinit to see if it helps
|
|
529
|
+
// This handles cases where drawers are in persisted components that haven't rendered yet
|
|
530
|
+
setTimeout(() => {
|
|
531
|
+
KTDrawer.reinit();
|
|
532
|
+
// Try one more time after reinit
|
|
533
|
+
const drawerAfterReinit = document.querySelector(selector) || document.body.querySelector(selector);
|
|
534
|
+
if (drawerAfterReinit) {
|
|
535
|
+
if (!KTData.has(drawerAfterReinit as HTMLElement, 'drawer')) {
|
|
536
|
+
new KTDrawer(drawerAfterReinit as HTMLElement);
|
|
537
|
+
}
|
|
538
|
+
const drawerInstance = KTDrawer.getInstance(drawerAfterReinit as HTMLElement);
|
|
539
|
+
if (drawerInstance) {
|
|
540
|
+
drawerInstance.toggle();
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}, 500);
|
|
544
|
+
}
|
|
545
|
+
});
|
|
339
546
|
}
|
|
340
547
|
},
|
|
341
548
|
);
|
|
@@ -411,8 +618,12 @@ export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
|
|
411
618
|
}
|
|
412
619
|
|
|
413
620
|
public static createInstances(): void {
|
|
414
|
-
|
|
415
|
-
|
|
621
|
+
// Find all drawer elements - check both document and body (drawers with container="body" are moved there)
|
|
622
|
+
const elementsInDoc = document.querySelectorAll('[data-kt-drawer]');
|
|
623
|
+
const elementsInBody = document.body.querySelectorAll('[data-kt-drawer]');
|
|
624
|
+
// Combine and deduplicate
|
|
625
|
+
const allElements = new Set([...Array.from(elementsInDoc), ...Array.from(elementsInBody)]);
|
|
626
|
+
const elements = Array.from(allElements);
|
|
416
627
|
elements.forEach((element) => {
|
|
417
628
|
new KTDrawer(element as HTMLElement);
|
|
418
629
|
});
|
|
@@ -430,6 +641,51 @@ export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
|
|
430
641
|
window.KT_DRAWER_INITIALIZED = true;
|
|
431
642
|
}
|
|
432
643
|
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Force reinitialization of drawers by clearing KTData entries.
|
|
647
|
+
* Useful for Livewire wire:navigate where persisted elements need reinitialization.
|
|
648
|
+
*/
|
|
649
|
+
public static reinit(): void {
|
|
650
|
+
// Follow the same simple pattern as KTDropdown.reinit()
|
|
651
|
+
// Find all drawer elements - check both document and body (some may be moved to body)
|
|
652
|
+
const elementsInDoc = document.querySelectorAll('[data-kt-drawer]');
|
|
653
|
+
const elementsInBody = document.body.querySelectorAll('[data-kt-drawer]');
|
|
654
|
+
// Combine and deduplicate
|
|
655
|
+
const allElements = new Set([...Array.from(elementsInDoc), ...Array.from(elementsInBody)]);
|
|
656
|
+
const elements = Array.from(allElements);
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
// Clean up existing instances
|
|
660
|
+
elements.forEach((element) => {
|
|
661
|
+
try {
|
|
662
|
+
// Get existing instance to clean up
|
|
663
|
+
const instance = KTDrawer.getInstance(element as HTMLElement);
|
|
664
|
+
if (instance && typeof instance.hide === 'function') {
|
|
665
|
+
instance.hide(); // This will clean up backdrop and state
|
|
666
|
+
}
|
|
667
|
+
// Clear KTData entries
|
|
668
|
+
const hadDrawer = KTData.has(element as HTMLElement, 'drawer');
|
|
669
|
+
KTData.remove(element as HTMLElement, 'drawer');
|
|
670
|
+
// Remove initialization attribute to allow fresh initialization
|
|
671
|
+
element.removeAttribute('data-kt-drawer-initialized');
|
|
672
|
+
} catch (e) {
|
|
673
|
+
// Ignore errors for individual elements
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
// Now create fresh instances
|
|
678
|
+
KTDrawer.createInstances();
|
|
679
|
+
|
|
680
|
+
// Always ensure handlers are set up (similar to KTMenu.init() behavior)
|
|
681
|
+
// Event handlers use delegation so they persist, but we ensure they're attached
|
|
682
|
+
KTDrawer.handleToggle();
|
|
683
|
+
KTDrawer.handleDismiss();
|
|
684
|
+
KTDrawer.handleResize();
|
|
685
|
+
KTDrawer.handleClickAway();
|
|
686
|
+
KTDrawer.handleKeyword();
|
|
687
|
+
|
|
688
|
+
}
|
|
433
689
|
}
|
|
434
690
|
|
|
435
691
|
if (typeof window !== 'undefined') {
|
|
@@ -49,7 +49,9 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
49
49
|
constructor(element: HTMLElement, config?: KTDropdownConfigInterface) {
|
|
50
50
|
super();
|
|
51
51
|
|
|
52
|
-
if (KTData.has(element as HTMLElement, this._name))
|
|
52
|
+
if (KTData.has(element as HTMLElement, this._name)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
53
55
|
|
|
54
56
|
this._init(element);
|
|
55
57
|
this._buildConfig(config);
|
|
@@ -57,11 +59,15 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
57
59
|
this._toggleElement = this._element.querySelector(
|
|
58
60
|
'[data-kt-dropdown-toggle]',
|
|
59
61
|
) as HTMLElement;
|
|
60
|
-
if (!this._toggleElement)
|
|
62
|
+
if (!this._toggleElement) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
61
65
|
this._menuElement = this._element.querySelector(
|
|
62
66
|
'[data-kt-dropdown-menu]',
|
|
63
67
|
) as HTMLElement;
|
|
64
|
-
if (!this._menuElement)
|
|
68
|
+
if (!this._menuElement) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
65
71
|
|
|
66
72
|
KTData.set(this._menuElement, 'dropdownElement', this._element);
|
|
67
73
|
this._setupNestedDropdowns();
|
|
@@ -101,9 +107,13 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
101
107
|
event.preventDefault();
|
|
102
108
|
event.stopPropagation();
|
|
103
109
|
|
|
104
|
-
if (this._disabled)
|
|
110
|
+
if (this._disabled) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
105
113
|
|
|
106
|
-
if (this._getOption('trigger') !== 'click')
|
|
114
|
+
if (this._getOption('trigger') !== 'click') {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
107
117
|
|
|
108
118
|
this._toggle();
|
|
109
119
|
}
|
|
@@ -154,7 +164,9 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
154
164
|
}
|
|
155
165
|
|
|
156
166
|
protected _show(): void {
|
|
157
|
-
if (this._isOpen || this._isTransitioning)
|
|
167
|
+
if (this._isOpen || this._isTransitioning) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
158
170
|
|
|
159
171
|
const payload = { cancel: false };
|
|
160
172
|
this._fireEvent('show', payload);
|
|
@@ -372,6 +384,12 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
372
384
|
(reference.closest('[data-kt-dropdown-initialized]') as HTMLElement);
|
|
373
385
|
if (findElement) return findElement;
|
|
374
386
|
|
|
387
|
+
// Fallback: look for parent with data-kt-dropdown attribute
|
|
388
|
+
if (reference) {
|
|
389
|
+
const dropdownContainer = reference.closest('[data-kt-dropdown]') as HTMLElement;
|
|
390
|
+
if (dropdownContainer) return dropdownContainer;
|
|
391
|
+
}
|
|
392
|
+
|
|
375
393
|
if (
|
|
376
394
|
reference &&
|
|
377
395
|
reference.hasAttribute('data-kt-dropdown-menu') &&
|
|
@@ -386,10 +404,13 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
386
404
|
public static getInstance(element: HTMLElement): KTDropdown {
|
|
387
405
|
element = this.getElement(element);
|
|
388
406
|
|
|
389
|
-
if (!element)
|
|
407
|
+
if (!element) {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
390
410
|
|
|
391
411
|
if (KTData.has(element, 'dropdown')) {
|
|
392
|
-
|
|
412
|
+
const instance = KTData.get(element, 'dropdown') as KTDropdown;
|
|
413
|
+
return instance;
|
|
393
414
|
}
|
|
394
415
|
|
|
395
416
|
if (element.getAttribute('data-kt-dropdown-initialized') === 'true') {
|
|
@@ -556,6 +577,40 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
556
577
|
window.KT_DROPDOWN_INITIALIZED = true;
|
|
557
578
|
}
|
|
558
579
|
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Force reinitialization of dropdowns by clearing KTData entries.
|
|
583
|
+
* Useful for Livewire wire:navigate where persisted elements need reinitialization.
|
|
584
|
+
*/
|
|
585
|
+
public static reinit(): void {
|
|
586
|
+
const elements = document.querySelectorAll('[data-kt-dropdown]');
|
|
587
|
+
elements.forEach((element) => {
|
|
588
|
+
try {
|
|
589
|
+
// Get existing instance to clean up Popper
|
|
590
|
+
const instance = KTDropdown.getInstance(element as HTMLElement);
|
|
591
|
+
if (instance && typeof instance.hide === 'function') {
|
|
592
|
+
instance.hide(); // This will destroy Popper
|
|
593
|
+
}
|
|
594
|
+
// Clear KTData entries
|
|
595
|
+
KTData.remove(element as HTMLElement, 'dropdown');
|
|
596
|
+
KTData.remove(element as HTMLElement, 'popper');
|
|
597
|
+
// Remove initialization attribute to allow fresh initialization
|
|
598
|
+
element.removeAttribute('data-kt-dropdown-initialized');
|
|
599
|
+
const menu = element.querySelector('[data-kt-dropdown-menu]');
|
|
600
|
+
if (menu) {
|
|
601
|
+
KTData.remove(menu as HTMLElement, 'dropdownElement');
|
|
602
|
+
}
|
|
603
|
+
} catch (e) {
|
|
604
|
+
// Ignore errors for individual elements
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
// Now create fresh instances
|
|
608
|
+
KTDropdown.createInstances();
|
|
609
|
+
|
|
610
|
+
// Always ensure handlers are set up (similar to KTMenu.init() behavior)
|
|
611
|
+
// Event handlers use delegation so they persist, but we ensure they're attached
|
|
612
|
+
KTDropdown.initHandlers();
|
|
613
|
+
}
|
|
559
614
|
}
|
|
560
615
|
|
|
561
616
|
if (typeof window !== 'undefined') {
|