@aquera/nile-elements 1.2.6-beta-1.0 → 1.2.6-beta-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/README.md +3 -0
- package/demo/index.html +38 -7
- package/dist/index.js +66 -66
- package/dist/nile-select/nile-select.cjs.js +1 -1
- package/dist/nile-select/nile-select.cjs.js.map +1 -1
- package/dist/nile-select/nile-select.esm.js +2 -2
- package/dist/nile-select/virtual-scroll-helper.cjs.js +1 -1
- package/dist/nile-select/virtual-scroll-helper.cjs.js.map +1 -1
- package/dist/nile-select/virtual-scroll-helper.esm.js +1 -1
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js +2 -2
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js.map +1 -1
- package/dist/nile-virtual-select/nile-virtual-select.esm.js +13 -13
- package/dist/src/nile-select/nile-select.d.ts +12 -12
- package/dist/src/nile-select/nile-select.js +71 -71
- package/dist/src/nile-select/nile-select.js.map +1 -1
- package/dist/src/nile-select/virtual-scroll-helper.js +1 -1
- package/dist/src/nile-select/virtual-scroll-helper.js.map +1 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.d.ts +10 -10
- package/dist/src/nile-virtual-select/nile-virtual-select.js +119 -80
- package/dist/src/nile-virtual-select/nile-virtual-select.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/nile-select/nile-select.ts +96 -101
- package/src/nile-select/virtual-scroll-helper.ts +1 -1
- package/src/nile-virtual-select/nile-virtual-select.ts +149 -115
- package/vscode-html-custom-data.json +22 -22
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Webcomponent nile-elements following open-wc recommendations",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "nile-elements",
|
|
6
|
-
"version": "1.2.6-beta-1.
|
|
6
|
+
"version": "1.2.6-beta-1.3",
|
|
7
7
|
"main": "dist/src/index.js",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"module": "dist/src/index.js",
|
|
@@ -167,8 +167,6 @@ export class NileSelect extends NileElement implements NileFormControl{
|
|
|
167
167
|
|
|
168
168
|
@property({attribute:'internal-search-placeholder'}) internalSearchPlaceHolder = 'Search...';
|
|
169
169
|
|
|
170
|
-
@property({ type: Boolean, reflect: true, attribute: true }) enableVisibilityEffect = false;
|
|
171
|
-
|
|
172
170
|
@property({ type: Boolean, reflect: true }) blockValueChange = false;
|
|
173
171
|
|
|
174
172
|
@property({ type: Boolean, reflect: true }) disableLocalSearch = false;
|
|
@@ -269,10 +267,6 @@ export class NileSelect extends NileElement implements NileFormControl{
|
|
|
269
267
|
|
|
270
268
|
@state() oldMaxOptionsVisible: number = 1;
|
|
271
269
|
|
|
272
|
-
|
|
273
|
-
@property({ type: Boolean, reflect: true, attribute: true }) enableTabClose = false;
|
|
274
|
-
|
|
275
|
-
|
|
276
270
|
@property({ type: Boolean }) showNoResults: boolean = false;
|
|
277
271
|
|
|
278
272
|
@property({ type: String }) noResultsMessage: string = 'No results found';
|
|
@@ -293,6 +287,10 @@ export class NileSelect extends NileElement implements NileFormControl{
|
|
|
293
287
|
/** loading indicator for virtual select */
|
|
294
288
|
@property({ type: Boolean, reflect: true, attribute: true }) loading = false;
|
|
295
289
|
|
|
290
|
+
@property({ type: Boolean, reflect: true, attribute: true }) enableVisibilityEffect = false;
|
|
291
|
+
|
|
292
|
+
@property({ type: Boolean, reflect: true, attribute: true }) enableTabClose = false;
|
|
293
|
+
|
|
296
294
|
/** Gets the validity state object */
|
|
297
295
|
get validity() {
|
|
298
296
|
return this.valueInput?.validity;
|
|
@@ -426,100 +424,6 @@ export class NileSelect extends NileElement implements NileFormControl{
|
|
|
426
424
|
}
|
|
427
425
|
}
|
|
428
426
|
|
|
429
|
-
|
|
430
|
-
/** All active IntersectionObservers for visibility detection */
|
|
431
|
-
private anchorVisibilityObservers: IntersectionObserver[] = [];
|
|
432
|
-
|
|
433
|
-
/** Utility: find ALL scrollable ancestors (not just the nearest) */
|
|
434
|
-
private getScrollableAncestors(element: HTMLElement): HTMLElement[] {
|
|
435
|
-
const scrollables: HTMLElement[] = [];
|
|
436
|
-
let parent = element.parentElement;
|
|
437
|
-
while (parent) {
|
|
438
|
-
const style = getComputedStyle(parent);
|
|
439
|
-
const canScroll =
|
|
440
|
-
/(auto|scroll)/.test(style.overflow + style.overflowY + style.overflowX);
|
|
441
|
-
if (canScroll) {
|
|
442
|
-
scrollables.push(parent);
|
|
443
|
-
}
|
|
444
|
-
parent = parent.parentElement;
|
|
445
|
-
}
|
|
446
|
-
return scrollables;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/** Handles tab visibility (page hidden / tab switched) */
|
|
450
|
-
private handleDocumentVisibilityChange = (): void => {
|
|
451
|
-
if (!this.enableTabClose) return;
|
|
452
|
-
if (document.visibilityState === 'hidden' && this.open) {
|
|
453
|
-
this.hide();
|
|
454
|
-
this.emit('nile-visibility-change', {
|
|
455
|
-
visible: false,
|
|
456
|
-
reason: 'document-hidden',
|
|
457
|
-
name: this.name,
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
};
|
|
461
|
-
|
|
462
|
-
/** Sets up visibility tracking for all relevant contexts */
|
|
463
|
-
private setupAnchorVisibilityObserver(): void {
|
|
464
|
-
if (!this.enableVisibilityEffect) return;
|
|
465
|
-
|
|
466
|
-
this.cleanupAnchorVisibilityObserver();
|
|
467
|
-
|
|
468
|
-
const combobox = this.combobox;
|
|
469
|
-
if (!combobox) return;
|
|
470
|
-
|
|
471
|
-
// Get all scrollable ancestors and viewport
|
|
472
|
-
const scrollContainers = [...this.getScrollableAncestors(this), null];
|
|
473
|
-
|
|
474
|
-
scrollContainers.forEach((rootContainer) => {
|
|
475
|
-
const observer = new IntersectionObserver(
|
|
476
|
-
(entries) => {
|
|
477
|
-
for (const entry of entries) {
|
|
478
|
-
if (!entry.isIntersecting && this.open) {
|
|
479
|
-
this.hide();
|
|
480
|
-
this.emit('nile-visibility-change', {
|
|
481
|
-
visible: false,
|
|
482
|
-
reason: 'anchor-out-of-view',
|
|
483
|
-
name: this.name,
|
|
484
|
-
root: rootContainer,
|
|
485
|
-
});
|
|
486
|
-
return; // stop further triggers
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
},
|
|
490
|
-
{
|
|
491
|
-
root: rootContainer,
|
|
492
|
-
threshold: 0.1, // 10% visible = visible
|
|
493
|
-
}
|
|
494
|
-
);
|
|
495
|
-
|
|
496
|
-
observer.observe(combobox);
|
|
497
|
-
this.anchorVisibilityObservers.push(observer);
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
// Attach tab visibility listener only if property enabled
|
|
501
|
-
if (this.enableTabClose) {
|
|
502
|
-
document.addEventListener(
|
|
503
|
-
'visibilitychange',
|
|
504
|
-
this.handleDocumentVisibilityChange
|
|
505
|
-
);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/** Cleans up all visibility observers and listeners */
|
|
510
|
-
private cleanupAnchorVisibilityObserver(): void {
|
|
511
|
-
this.anchorVisibilityObservers.forEach((o) => o.disconnect());
|
|
512
|
-
this.anchorVisibilityObservers = [];
|
|
513
|
-
|
|
514
|
-
// Always remove listener to avoid stale callbacks
|
|
515
|
-
document.removeEventListener(
|
|
516
|
-
'visibilitychange',
|
|
517
|
-
this.handleDocumentVisibilityChange
|
|
518
|
-
);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
427
|
/**
|
|
524
428
|
* Handles the click event on the footer.
|
|
525
429
|
* @param event - The click event.
|
|
@@ -712,6 +616,97 @@ export class NileSelect extends NileElement implements NileFormControl{
|
|
|
712
616
|
this.hide();
|
|
713
617
|
}
|
|
714
618
|
|
|
619
|
+
/** All active IntersectionObservers for visibility detection */
|
|
620
|
+
private anchorVisibilityObservers: IntersectionObserver[] = [];
|
|
621
|
+
|
|
622
|
+
/** Utility: find ALL scrollable ancestors (not just the nearest) */
|
|
623
|
+
private getScrollableAncestors(element: HTMLElement): HTMLElement[] {
|
|
624
|
+
const scrollables: HTMLElement[] = [];
|
|
625
|
+
let parent = element.parentElement;
|
|
626
|
+
while (parent) {
|
|
627
|
+
const style = getComputedStyle(parent);
|
|
628
|
+
const canScroll =
|
|
629
|
+
/(auto|scroll)/.test(style.overflow + style.overflowY + style.overflowX);
|
|
630
|
+
if (canScroll) {
|
|
631
|
+
scrollables.push(parent);
|
|
632
|
+
}
|
|
633
|
+
parent = parent.parentElement;
|
|
634
|
+
}
|
|
635
|
+
return scrollables;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/** Handles tab visibility (page hidden / tab switched) */
|
|
639
|
+
private handleDocumentVisibilityChange = (): void => {
|
|
640
|
+
if (!this.enableTabClose) return;
|
|
641
|
+
if (document.visibilityState === 'hidden' && this.open) {
|
|
642
|
+
this.hide();
|
|
643
|
+
this.emit('nile-visibility-change', {
|
|
644
|
+
visible: false,
|
|
645
|
+
reason: 'document-hidden',
|
|
646
|
+
name: this.name,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
/** Sets up visibility tracking for all relevant contexts */
|
|
652
|
+
private setupAnchorVisibilityObserver(): void {
|
|
653
|
+
if (!this.enableVisibilityEffect) return;
|
|
654
|
+
|
|
655
|
+
this.cleanupAnchorVisibilityObserver();
|
|
656
|
+
|
|
657
|
+
const combobox = this.combobox;
|
|
658
|
+
if (!combobox) return;
|
|
659
|
+
|
|
660
|
+
// Get all scrollable ancestors and viewport
|
|
661
|
+
const scrollContainers = [...this.getScrollableAncestors(this), null];
|
|
662
|
+
|
|
663
|
+
scrollContainers.forEach((rootContainer) => {
|
|
664
|
+
const observer = new IntersectionObserver(
|
|
665
|
+
(entries) => {
|
|
666
|
+
for (const entry of entries) {
|
|
667
|
+
if (!entry.isIntersecting && this.open) {
|
|
668
|
+
this.hide();
|
|
669
|
+
this.emit('nile-visibility-change', {
|
|
670
|
+
visible: false,
|
|
671
|
+
reason: 'anchor-out-of-view',
|
|
672
|
+
name: this.name,
|
|
673
|
+
root: rootContainer,
|
|
674
|
+
});
|
|
675
|
+
return; // stop further triggers
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
root: rootContainer,
|
|
681
|
+
threshold: 0.1, // 10% visible = visible
|
|
682
|
+
}
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
observer.observe(combobox);
|
|
686
|
+
this.anchorVisibilityObservers.push(observer);
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
// Attach tab visibility listener only if property enabled
|
|
690
|
+
if (this.enableTabClose) {
|
|
691
|
+
document.addEventListener(
|
|
692
|
+
'visibilitychange',
|
|
693
|
+
this.handleDocumentVisibilityChange
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/** Cleans up all visibility observers and listeners */
|
|
699
|
+
private cleanupAnchorVisibilityObserver(): void {
|
|
700
|
+
this.anchorVisibilityObservers.forEach((o) => o.disconnect());
|
|
701
|
+
this.anchorVisibilityObservers = [];
|
|
702
|
+
|
|
703
|
+
// Always remove listener to avoid stale callbacks
|
|
704
|
+
document.removeEventListener(
|
|
705
|
+
'visibilitychange',
|
|
706
|
+
this.handleDocumentVisibilityChange
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
|
|
715
710
|
private handleComboboxMouseDown(event: MouseEvent) {
|
|
716
711
|
const path = event.composedPath();
|
|
717
712
|
const isIconButton = path.some(
|
|
@@ -1183,7 +1178,7 @@ export class NileSelect extends NileElement implements NileFormControl{
|
|
|
1183
1178
|
if (this.enableVisibilityEffect) {
|
|
1184
1179
|
this.setupAnchorVisibilityObserver();
|
|
1185
1180
|
}
|
|
1186
|
-
|
|
1181
|
+
|
|
1187
1182
|
const { keyframes, options } = getAnimation(this, 'select.show', {
|
|
1188
1183
|
dir: 'ltr',
|
|
1189
1184
|
});
|
|
@@ -27,11 +27,11 @@ export class VirtualScrollHelper {
|
|
|
27
27
|
.disableLocalSearch=${component.disableLocalSearch}
|
|
28
28
|
.optionsLoading=${component.optionsLoading}
|
|
29
29
|
.multiple=${component.multiple}
|
|
30
|
+
.enableVisibilityEffect=${component.enableVisibilityEffect}
|
|
30
31
|
.enableTabClose=${component.enableTabClose}
|
|
31
32
|
.helpText=${component.helpText}
|
|
32
33
|
.errorMessage=${component.errorMessage}
|
|
33
34
|
.warning=${component.warning}
|
|
34
|
-
.enableVisibilityEffect=${component.enableVisibilityEffect}
|
|
35
35
|
.error=${component.error}
|
|
36
36
|
.success=${component.success}
|
|
37
37
|
.disabled=${component.disabled}
|
|
@@ -162,8 +162,6 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
162
162
|
/** Enable search functionality */
|
|
163
163
|
@property({ type: Boolean, reflect: true }) searchEnabled = false;
|
|
164
164
|
|
|
165
|
-
@property({ type: Boolean, reflect: true, attribute: true }) enableVisibilityEffect = false;
|
|
166
|
-
|
|
167
165
|
/** Search input placeholder */
|
|
168
166
|
@property({attribute:'internal-search-placeholder'}) internalSearchPlaceHolder = 'Search...';
|
|
169
167
|
|
|
@@ -188,6 +186,10 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
188
186
|
/** Sets the input to a warning state */
|
|
189
187
|
@property({ type: Boolean }) warning = false;
|
|
190
188
|
|
|
189
|
+
@property({ type: Boolean, reflect: true, attribute: true }) enableVisibilityEffect = false;
|
|
190
|
+
|
|
191
|
+
@property({ type: Boolean, reflect: true, attribute: true }) enableTabClose = false;
|
|
192
|
+
|
|
191
193
|
/** Sets the input to an error state */
|
|
192
194
|
@property({ type: Boolean }) error = false;
|
|
193
195
|
|
|
@@ -266,10 +268,6 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
266
268
|
maxOptionsVisible = 3;
|
|
267
269
|
|
|
268
270
|
@state() oldMaxOptionsVisible: number = 1;
|
|
269
|
-
|
|
270
|
-
@property({ type: Boolean, reflect: true, attribute: true }) enableTabClose = false;
|
|
271
|
-
|
|
272
|
-
|
|
273
271
|
@state() showListbox: boolean = false;
|
|
274
272
|
@state() private wasShowSelectedCheckedOnClose: boolean = false;
|
|
275
273
|
|
|
@@ -396,101 +394,6 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
396
394
|
this.emit('nile-blur');
|
|
397
395
|
}
|
|
398
396
|
|
|
399
|
-
/** All active IntersectionObservers for visibility detection */
|
|
400
|
-
private anchorVisibilityObservers: IntersectionObserver[] = [];
|
|
401
|
-
|
|
402
|
-
/** Utility: find ALL scrollable ancestors (not just the nearest) */
|
|
403
|
-
private getScrollableAncestors(element: HTMLElement): HTMLElement[] {
|
|
404
|
-
const scrollables: HTMLElement[] = [];
|
|
405
|
-
let parent = element.parentElement;
|
|
406
|
-
while (parent) {
|
|
407
|
-
const style = getComputedStyle(parent);
|
|
408
|
-
const canScroll =
|
|
409
|
-
/(auto|scroll)/.test(style.overflow + style.overflowY + style.overflowX);
|
|
410
|
-
if (canScroll) {
|
|
411
|
-
scrollables.push(parent);
|
|
412
|
-
}
|
|
413
|
-
parent = parent.parentElement;
|
|
414
|
-
}
|
|
415
|
-
return scrollables;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
/** Handles tab visibility (page hidden / tab switched) */
|
|
419
|
-
private handleDocumentVisibilityChange = (): void => {
|
|
420
|
-
if (!this.enableTabClose) return;
|
|
421
|
-
if (document.visibilityState === 'hidden' && this.open) {
|
|
422
|
-
this.hide();
|
|
423
|
-
this.emit('nile-visibility-change', {
|
|
424
|
-
visible: false,
|
|
425
|
-
reason: 'document-hidden',
|
|
426
|
-
name: this.name,
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
/** Sets up visibility tracking for all relevant contexts */
|
|
432
|
-
private setupAnchorVisibilityObserver(): void {
|
|
433
|
-
if (!this.enableVisibilityEffect) return;
|
|
434
|
-
|
|
435
|
-
this.cleanupAnchorVisibilityObserver();
|
|
436
|
-
|
|
437
|
-
const combobox = this.combobox;
|
|
438
|
-
if (!combobox) return;
|
|
439
|
-
|
|
440
|
-
// Get all scrollable ancestors and viewport
|
|
441
|
-
const scrollContainers = [...this.getScrollableAncestors(this), null];
|
|
442
|
-
|
|
443
|
-
scrollContainers.forEach((rootContainer) => {
|
|
444
|
-
const observer = new IntersectionObserver(
|
|
445
|
-
(entries) => {
|
|
446
|
-
for (const entry of entries) {
|
|
447
|
-
if (!entry.isIntersecting && this.open) {
|
|
448
|
-
this.hide();
|
|
449
|
-
this.emit('nile-visibility-change', {
|
|
450
|
-
visible: false,
|
|
451
|
-
reason: 'anchor-out-of-view',
|
|
452
|
-
name: this.name,
|
|
453
|
-
root: rootContainer,
|
|
454
|
-
});
|
|
455
|
-
return; // stop further triggers
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
},
|
|
459
|
-
{
|
|
460
|
-
root: rootContainer,
|
|
461
|
-
threshold: 0.1, // 10% visible = visible
|
|
462
|
-
}
|
|
463
|
-
);
|
|
464
|
-
|
|
465
|
-
observer.observe(combobox);
|
|
466
|
-
this.anchorVisibilityObservers.push(observer);
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
// Attach tab visibility listener only if property enabled
|
|
470
|
-
if (this.enableTabClose) {
|
|
471
|
-
document.addEventListener(
|
|
472
|
-
'visibilitychange',
|
|
473
|
-
this.handleDocumentVisibilityChange
|
|
474
|
-
);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/** Cleans up all visibility observers and listeners */
|
|
479
|
-
private cleanupAnchorVisibilityObserver(): void {
|
|
480
|
-
this.anchorVisibilityObservers.forEach((o) => o.disconnect());
|
|
481
|
-
this.anchorVisibilityObservers = [];
|
|
482
|
-
|
|
483
|
-
// Always remove listener to avoid stale callbacks
|
|
484
|
-
document.removeEventListener(
|
|
485
|
-
'visibilitychange',
|
|
486
|
-
this.handleDocumentVisibilityChange
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
397
|
private handleDocumentFocusIn(event: FocusEvent): void {
|
|
495
398
|
if (!this.open) return;
|
|
496
399
|
const path = event.composedPath();
|
|
@@ -567,6 +470,98 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
567
470
|
}
|
|
568
471
|
};
|
|
569
472
|
|
|
473
|
+
/** All active IntersectionObservers for visibility detection */
|
|
474
|
+
private anchorVisibilityObservers: IntersectionObserver[] = [];
|
|
475
|
+
|
|
476
|
+
/** Utility: find ALL scrollable ancestors (not just the nearest) */
|
|
477
|
+
private getScrollableAncestors(element: HTMLElement): HTMLElement[] {
|
|
478
|
+
const scrollables: HTMLElement[] = [];
|
|
479
|
+
let parent = element.parentElement;
|
|
480
|
+
while (parent) {
|
|
481
|
+
const style = getComputedStyle(parent);
|
|
482
|
+
const canScroll =
|
|
483
|
+
/(auto|scroll)/.test(style.overflow + style.overflowY + style.overflowX);
|
|
484
|
+
if (canScroll) {
|
|
485
|
+
scrollables.push(parent);
|
|
486
|
+
}
|
|
487
|
+
parent = parent.parentElement;
|
|
488
|
+
}
|
|
489
|
+
return scrollables;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/** Handles tab visibility (page hidden / tab switched) */
|
|
493
|
+
private handleDocumentVisibilityChange = (): void => {
|
|
494
|
+
if (!this.enableTabClose) return;
|
|
495
|
+
if (document.visibilityState === 'hidden' && this.open) {
|
|
496
|
+
this.hide();
|
|
497
|
+
this.emit('nile-visibility-change', {
|
|
498
|
+
visible: false,
|
|
499
|
+
reason: 'document-hidden',
|
|
500
|
+
name: this.name,
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
/** Sets up visibility tracking for all relevant contexts */
|
|
506
|
+
private setupAnchorVisibilityObserver(): void {
|
|
507
|
+
if (!this.enableVisibilityEffect) return;
|
|
508
|
+
|
|
509
|
+
this.cleanupAnchorVisibilityObserver();
|
|
510
|
+
|
|
511
|
+
const combobox = this.combobox;
|
|
512
|
+
if (!combobox) return;
|
|
513
|
+
|
|
514
|
+
// Get all scrollable ancestors and viewport
|
|
515
|
+
const scrollContainers = [...this.getScrollableAncestors(this), null];
|
|
516
|
+
|
|
517
|
+
scrollContainers.forEach((rootContainer) => {
|
|
518
|
+
const observer = new IntersectionObserver(
|
|
519
|
+
(entries) => {
|
|
520
|
+
for (const entry of entries) {
|
|
521
|
+
if (!entry.isIntersecting && this.open) {
|
|
522
|
+
this.hide();
|
|
523
|
+
this.emit('nile-visibility-change', {
|
|
524
|
+
visible: false,
|
|
525
|
+
reason: 'anchor-out-of-view',
|
|
526
|
+
name: this.name,
|
|
527
|
+
root: rootContainer,
|
|
528
|
+
});
|
|
529
|
+
return; // stop further triggers
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
root: rootContainer,
|
|
535
|
+
threshold: 0.1, // 10% visible = visible
|
|
536
|
+
}
|
|
537
|
+
);
|
|
538
|
+
|
|
539
|
+
observer.observe(combobox);
|
|
540
|
+
this.anchorVisibilityObservers.push(observer);
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
// Attach tab visibility listener only if property enabled
|
|
544
|
+
if (this.enableTabClose) {
|
|
545
|
+
document.addEventListener(
|
|
546
|
+
'visibilitychange',
|
|
547
|
+
this.handleDocumentVisibilityChange
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/** Cleans up all visibility observers and listeners */
|
|
553
|
+
private cleanupAnchorVisibilityObserver(): void {
|
|
554
|
+
this.anchorVisibilityObservers.forEach((o) => o.disconnect());
|
|
555
|
+
this.anchorVisibilityObservers = [];
|
|
556
|
+
|
|
557
|
+
// Always remove listener to avoid stale callbacks
|
|
558
|
+
document.removeEventListener(
|
|
559
|
+
'visibilitychange',
|
|
560
|
+
this.handleDocumentVisibilityChange
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
|
|
570
565
|
/**
|
|
571
566
|
* This is a workaround for an error in the Lit Labs virtualizer.
|
|
572
567
|
* Since there are no specific guidelines available to fix the issue,
|
|
@@ -831,6 +826,9 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
831
826
|
|
|
832
827
|
handleSearchChange(e: any): void {
|
|
833
828
|
this.searchValue = e.detail.value;
|
|
829
|
+
if (this.portal) {
|
|
830
|
+
this.portalManager.updatePortalAppendPosition();
|
|
831
|
+
}
|
|
834
832
|
|
|
835
833
|
this.emit('nile-search', {
|
|
836
834
|
query: this.searchValue,
|
|
@@ -908,7 +906,18 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
908
906
|
this.getDisplayText.bind(this),
|
|
909
907
|
this.renderItemConfig?.getSearchText
|
|
910
908
|
);
|
|
911
|
-
|
|
909
|
+
if (this.portal) {
|
|
910
|
+
this.portalManager.updatePortalAppendPosition();
|
|
911
|
+
this.updateComplete.then(() => {
|
|
912
|
+
requestAnimationFrame(() => {
|
|
913
|
+
requestAnimationFrame(() => {
|
|
914
|
+
this.resetScrollPosition();
|
|
915
|
+
});
|
|
916
|
+
});
|
|
917
|
+
});
|
|
918
|
+
} else {
|
|
919
|
+
this.resetScrollPosition();
|
|
920
|
+
}
|
|
912
921
|
this.data = result.filteredItems;
|
|
913
922
|
this.showNoResults = result.showNoResults;
|
|
914
923
|
this.showSelected = false;
|
|
@@ -928,7 +937,6 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
928
937
|
}
|
|
929
938
|
}
|
|
930
939
|
|
|
931
|
-
|
|
932
940
|
@watch('value', { waitUntilFirstUpdate: true })
|
|
933
941
|
handleValueChange(): void {
|
|
934
942
|
this.selectionChanged();
|
|
@@ -1033,11 +1041,12 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
1033
1041
|
this.data = [...this.originalOptionItems];
|
|
1034
1042
|
this.wasShowSelectedCheckedOnClose = false;
|
|
1035
1043
|
}
|
|
1036
|
-
|
|
1044
|
+
|
|
1037
1045
|
if (this.enableVisibilityEffect) {
|
|
1038
1046
|
this.setupAnchorVisibilityObserver();
|
|
1039
1047
|
}
|
|
1040
1048
|
|
|
1049
|
+
|
|
1041
1050
|
this.filterVirtualOptions("");
|
|
1042
1051
|
this.resetScrollPosition();
|
|
1043
1052
|
this.emit('nile-after-show', { value: this.value, name: this.name });
|
|
@@ -1597,23 +1606,48 @@ export class NileVirtualSelect extends NileElement implements NileFormControl {
|
|
|
1597
1606
|
}, 1);
|
|
1598
1607
|
}
|
|
1599
1608
|
|
|
1600
|
-
private resetScrollPosition(): void {
|
|
1601
|
-
this.updateComplete
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1609
|
+
private async resetScrollPosition(): Promise<void> {
|
|
1610
|
+
await this.updateComplete;
|
|
1611
|
+
requestAnimationFrame(() => {
|
|
1612
|
+
requestAnimationFrame(() => {
|
|
1613
|
+
let listbox: HTMLElement | null = null;
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
if (this.portal && this.portalManager.portalContainerElement) {
|
|
1617
|
+
listbox = this.portalManager.portalContainerElement.querySelector('#listbox') as HTMLElement;
|
|
1618
|
+
} else {
|
|
1619
|
+
listbox = this.shadowRoot?.querySelector('#listbox') as HTMLElement;
|
|
1608
1620
|
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1621
|
+
|
|
1622
|
+
if (!listbox || !listbox.isConnected) return;
|
|
1623
|
+
|
|
1624
|
+
listbox.scrollTop = 0;
|
|
1625
|
+
const virtualized = listbox.querySelector('.virtualized') as HTMLElement;
|
|
1626
|
+
if (virtualized && virtualized.isConnected) {
|
|
1627
|
+
const fewItems = this.data.length <= 5;
|
|
1628
|
+
|
|
1629
|
+
if (fewItems) {
|
|
1630
|
+
virtualized.style.overflowY = 'hidden';
|
|
1631
|
+
virtualized.style.maxHeight = 'none';
|
|
1632
|
+
listbox.style.overflowY = 'hidden';
|
|
1633
|
+
listbox.style.maxHeight = 'fit-content';
|
|
1634
|
+
} else {
|
|
1635
|
+
virtualized.style.overflowY = 'auto';
|
|
1636
|
+
virtualized.style.maxHeight = '';
|
|
1637
|
+
listbox.style.overflowY = 'auto';
|
|
1638
|
+
listbox.style.maxHeight = '';
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
virtualized.scrollTop = 0;
|
|
1642
|
+
}
|
|
1643
|
+
const virtualizer = listbox.querySelector('lit-virtualizer') as HTMLElement;
|
|
1611
1644
|
if (virtualizer && virtualizer.isConnected) {
|
|
1612
1645
|
virtualizer.scrollTop = 0;
|
|
1613
1646
|
}
|
|
1614
|
-
}
|
|
1647
|
+
});
|
|
1615
1648
|
});
|
|
1616
1649
|
}
|
|
1650
|
+
|
|
1617
1651
|
|
|
1618
1652
|
}
|
|
1619
1653
|
|