@aquera/nile-elements 2.0.18 → 2.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/demo/index.js +0 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1275 -490
- package/dist/nile-badge/index.cjs.js +1 -1
- package/dist/nile-badge/index.esm.js +1 -1
- package/dist/nile-badge/nile-badge.cjs.js +1 -1
- package/dist/nile-badge/nile-badge.cjs.js.map +1 -1
- package/dist/nile-badge/nile-badge.css.cjs.js +1 -1
- package/dist/nile-badge/nile-badge.css.cjs.js.map +1 -1
- package/dist/nile-badge/nile-badge.css.esm.js +24 -3
- package/dist/nile-badge/nile-badge.esm.js +5 -3
- package/dist/nile-breadcrumb/nile-breadcrumb.cjs.js +1 -1
- package/dist/nile-breadcrumb/nile-breadcrumb.cjs.js.map +1 -1
- package/dist/nile-breadcrumb/nile-breadcrumb.esm.js +2 -2
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.cjs.js +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.cjs.js.map +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.css.cjs.js +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.css.cjs.js.map +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.css.esm.js +14 -2
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.esm.js +4 -4
- package/dist/nile-calendar/index.cjs.js +1 -1
- package/dist/nile-calendar/index.esm.js +1 -1
- package/dist/nile-calendar/nile-calendar.cjs.js +2 -1
- package/dist/nile-calendar/nile-calendar.cjs.js.map +1 -1
- package/dist/nile-calendar/nile-calendar.css.cjs.js +1 -1
- package/dist/nile-calendar/nile-calendar.css.cjs.js.map +1 -1
- package/dist/nile-calendar/nile-calendar.css.esm.js +357 -2
- package/dist/nile-calendar/nile-calendar.esm.js +365 -41
- package/dist/nile-calendar/timezones.cjs.js +1 -1
- package/dist/nile-calendar/timezones.cjs.js.map +1 -1
- package/dist/nile-calendar/timezones.esm.js +1 -1
- package/dist/nile-date-time-picker/index.cjs.js +2 -0
- package/dist/nile-date-time-picker/index.cjs.js.map +1 -0
- package/dist/nile-date-time-picker/index.esm.js +1 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.cjs.js +2 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.cjs.js.map +1 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.css.cjs.js +2 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.css.cjs.js.map +1 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.css.esm.js +13 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.esm.js +53 -0
- package/dist/nile-select/index.cjs.js +1 -1
- package/dist/nile-select/index.esm.js +1 -1
- package/dist/nile-select/nile-select.cjs.js +2 -2
- package/dist/nile-select/nile-select.cjs.js.map +1 -1
- package/dist/nile-select/nile-select.esm.js +1 -1
- 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 +48 -47
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js +4 -4
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js.map +1 -1
- package/dist/nile-virtual-select/nile-virtual-select.esm.js +2 -2
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/nile-badge/nile-badge.css.js +24 -3
- package/dist/src/nile-badge/nile-badge.css.js.map +1 -1
- package/dist/src/nile-badge/nile-badge.d.ts +7 -4
- package/dist/src/nile-badge/nile-badge.js +22 -5
- package/dist/src/nile-badge/nile-badge.js.map +1 -1
- package/dist/src/nile-badge/nile-badge.test.js +88 -0
- package/dist/src/nile-badge/nile-badge.test.js.map +1 -1
- package/dist/src/nile-breadcrumb/nile-breadcrumb.d.ts +7 -0
- package/dist/src/nile-breadcrumb/nile-breadcrumb.js +24 -1
- package/dist/src/nile-breadcrumb/nile-breadcrumb.js.map +1 -1
- package/dist/src/nile-breadcrumb/nile-breadcrumb.test.js +51 -0
- package/dist/src/nile-breadcrumb/nile-breadcrumb.test.js.map +1 -1
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.css.js +12 -0
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.css.js.map +1 -1
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.d.ts +5 -0
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.js +9 -0
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.js.map +1 -1
- package/dist/src/nile-calendar/nile-calendar.css.js +355 -0
- package/dist/src/nile-calendar/nile-calendar.css.js.map +1 -1
- package/dist/src/nile-calendar/nile-calendar.d.ts +175 -0
- package/dist/src/nile-calendar/nile-calendar.js +1726 -26
- package/dist/src/nile-calendar/nile-calendar.js.map +1 -1
- package/dist/src/nile-calendar/nile-calendar.test.d.ts +1 -0
- package/dist/src/nile-calendar/nile-calendar.test.js +3580 -0
- package/dist/src/nile-calendar/nile-calendar.test.js.map +1 -1
- package/dist/src/nile-calendar/timezones.d.ts +21 -0
- package/dist/src/nile-calendar/timezones.js +49 -0
- package/dist/src/nile-calendar/timezones.js.map +1 -1
- package/dist/src/nile-date-time-picker/index.d.ts +1 -0
- package/dist/src/nile-date-time-picker/index.js +2 -0
- package/dist/src/nile-date-time-picker/index.js.map +1 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.css.d.ts +11 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.css.js +49 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.css.js.map +1 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.d.ts +173 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.js +1270 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.js.map +1 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.test.d.ts +143 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.test.js +7277 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.test.js.map +1 -0
- package/dist/src/nile-select/nile-select.d.ts +1 -0
- package/dist/src/nile-select/nile-select.js +16 -1
- package/dist/src/nile-select/nile-select.js.map +1 -1
- package/dist/src/nile-select/nile-select.test.js +430 -5
- package/dist/src/nile-select/nile-select.test.js.map +1 -1
- package/dist/src/nile-select/virtual-scroll-helper.js +7 -4
- package/dist/src/nile-select/virtual-scroll-helper.js.map +1 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.d.ts +3 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.js +14 -6
- package/dist/src/nile-virtual-select/nile-virtual-select.js.map +1 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.test.js +115 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.test.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/dist/utilities/animation-registry.cjs.js +1 -1
- package/dist/utilities/animation-registry.cjs.js.map +1 -1
- package/dist/utilities/animation-registry.esm.js +1 -1
- package/package.json +3 -1
- package/scripts/coverage-report.mjs +96 -0
- package/src/index.ts +1 -0
- package/src/nile-badge/nile-badge.css.ts +24 -3
- package/src/nile-badge/nile-badge.test.ts +102 -0
- package/src/nile-badge/nile-badge.ts +28 -5
- package/src/nile-breadcrumb/nile-breadcrumb.test.ts +57 -0
- package/src/nile-breadcrumb/nile-breadcrumb.ts +19 -0
- package/src/nile-breadcrumb-item/nile-breadcrumb-item.css.ts +12 -0
- package/src/nile-breadcrumb-item/nile-breadcrumb-item.ts +7 -0
- package/src/nile-calendar/nile-calendar.css.ts +355 -0
- package/src/nile-calendar/nile-calendar.test.ts +3793 -0
- package/src/nile-calendar/nile-calendar.ts +1760 -28
- package/src/nile-calendar/timezones.ts +57 -0
- package/src/nile-date-time-picker/index.ts +1 -0
- package/src/nile-date-time-picker/nile-date-time-picker.css.ts +54 -0
- package/src/nile-date-time-picker/nile-date-time-picker.test.ts +7886 -0
- package/src/nile-date-time-picker/nile-date-time-picker.ts +1153 -0
- package/src/nile-select/nile-select.test.ts +560 -5
- package/src/nile-select/nile-select.ts +21 -1
- package/src/nile-select/virtual-scroll-helper.ts +7 -4
- package/src/nile-virtual-select/nile-virtual-select.test.ts +139 -1
- package/src/nile-virtual-select/nile-virtual-select.ts +17 -6
- package/vscode-html-custom-data.json +200 -20
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aTimeout, expect, fixture, html, nextFrame, waitUntil } from '@open-wc/testing';
|
|
1
|
+
import { aTimeout, expect, fixture, html, nextFrame, oneEvent, waitUntil } from '@open-wc/testing';
|
|
2
2
|
import './nile-select';
|
|
3
3
|
import '../nile-option/nile-option';
|
|
4
4
|
import '../nile-input/nile-input';
|
|
@@ -661,7 +661,7 @@ describe('NileSelect chip fitting behaviour matrix', () => {
|
|
|
661
661
|
});
|
|
662
662
|
});
|
|
663
663
|
|
|
664
|
-
describe('NileSelect enableVirtualScroll value sync', () => {
|
|
664
|
+
describe('NileSelect enableVirtualScroll value sync (showTooltip)', () => {
|
|
665
665
|
const ROLES = ['Administrators', 'Users', 'Guests', 'Print Operators'];
|
|
666
666
|
const DATA = ROLES.map(role => ({ label: role, value: role }));
|
|
667
667
|
|
|
@@ -675,6 +675,7 @@ describe('NileSelect enableVirtualScroll value sync', () => {
|
|
|
675
675
|
async function virtualSelect(tpl = html`<nile-select
|
|
676
676
|
multiple
|
|
677
677
|
.enableVirtualScroll=${true}
|
|
678
|
+
.showTooltip=${true}
|
|
678
679
|
.data=${DATA}
|
|
679
680
|
.value=${[]}
|
|
680
681
|
></nile-select>`) {
|
|
@@ -717,6 +718,7 @@ describe('NileSelect enableVirtualScroll value sync', () => {
|
|
|
717
718
|
const { el, inner } = await virtualSelect(html`<nile-select
|
|
718
719
|
multiple
|
|
719
720
|
.enableVirtualScroll=${true}
|
|
721
|
+
.showTooltip=${true}
|
|
720
722
|
.data=${DATA}
|
|
721
723
|
.value=${['Administrators', 'Users', 'Guests']}
|
|
722
724
|
></nile-select>`);
|
|
@@ -747,6 +749,7 @@ describe('NileSelect enableVirtualScroll value sync', () => {
|
|
|
747
749
|
it('V5. single-select virtual mode keeps the wrapper value in sync', async () => {
|
|
748
750
|
const { el, inner } = await virtualSelect(html`<nile-select
|
|
749
751
|
.enableVirtualScroll=${true}
|
|
752
|
+
.showTooltip=${true}
|
|
750
753
|
.data=${DATA}
|
|
751
754
|
></nile-select>`);
|
|
752
755
|
|
|
@@ -761,7 +764,8 @@ describe('NileSelect enableVirtualScroll value sync', () => {
|
|
|
761
764
|
|
|
762
765
|
it('V6. resizing the host does not re-render the wrapper without autoResize', async () => {
|
|
763
766
|
const host = await fixture<HTMLElement>(html`<div style="width: 400px">
|
|
764
|
-
<nile-select multiple .enableVirtualScroll=${true}
|
|
767
|
+
<nile-select multiple .enableVirtualScroll=${true}
|
|
768
|
+
.showTooltip=${true} .data=${DATA}></nile-select>
|
|
765
769
|
</div>`);
|
|
766
770
|
const el = host.querySelector('nile-select') as NileSelect;
|
|
767
771
|
await el.updateComplete;
|
|
@@ -784,7 +788,7 @@ describe('NileSelect enableVirtualScroll value sync', () => {
|
|
|
784
788
|
});
|
|
785
789
|
});
|
|
786
790
|
|
|
787
|
-
describe('NileSelect enableVirtualScroll + searchEnabled value sync', () => {
|
|
791
|
+
describe('NileSelect enableVirtualScroll + searchEnabled value sync (showTooltip)', () => {
|
|
788
792
|
const ROLES = ['Administrators', 'Users', 'Guests', 'Print Operators'];
|
|
789
793
|
const DATA = ROLES.map(role => ({ label: role, value: role }));
|
|
790
794
|
|
|
@@ -809,6 +813,7 @@ describe('NileSelect enableVirtualScroll + searchEnabled value sync', () => {
|
|
|
809
813
|
?multiple=${multiple}
|
|
810
814
|
.searchEnabled=${true}
|
|
811
815
|
.enableVirtualScroll=${true}
|
|
816
|
+
.showTooltip=${true}
|
|
812
817
|
.portal=${portal}
|
|
813
818
|
.data=${DATA}
|
|
814
819
|
.value=${value}
|
|
@@ -1594,7 +1599,7 @@ describe('NileSelect 2.0.8 compatibility matrix', () => {
|
|
|
1594
1599
|
expect(inner.shadowRoot.querySelectorAll('.select__tags nile-tag').length).to.equal(1);
|
|
1595
1600
|
});
|
|
1596
1601
|
|
|
1597
|
-
it('C9. enableVirtualScroll: programmatic value
|
|
1602
|
+
it('C9. enableVirtualScroll: programmatic value reaches the inner select; clear-all leaves the outer value alone (pre-2.0.9)', async () => {
|
|
1598
1603
|
const el = await fixture<NileSelect>(html`<nile-select multiple .enableVirtualScroll=${true} .data=${DATA}></nile-select>`);
|
|
1599
1604
|
await settle(el);
|
|
1600
1605
|
const inner = el.shadowRoot!.querySelector('nile-virtual-select') as any;
|
|
@@ -1604,6 +1609,24 @@ describe('NileSelect 2.0.8 compatibility matrix', () => {
|
|
|
1604
1609
|
await inner.updateComplete;
|
|
1605
1610
|
expect(inner.value).to.deep.equal(['a', 'c']);
|
|
1606
1611
|
|
|
1612
|
+
inner.unSelectAll();
|
|
1613
|
+
await inner.updateComplete;
|
|
1614
|
+
await settle(el);
|
|
1615
|
+
expect(inner.value).to.deep.equal([]);
|
|
1616
|
+
// Without showTooltip the inner select owns the selection; the outer value is not written back.
|
|
1617
|
+
expect(el.value).to.deep.equal(['a', 'c']);
|
|
1618
|
+
});
|
|
1619
|
+
|
|
1620
|
+
it('C9b. enableVirtualScroll + showTooltip: programmatic value and clear-all reach both selects', async () => {
|
|
1621
|
+
const el = await fixture<NileSelect>(html`<nile-select multiple showTooltip .enableVirtualScroll=${true} .data=${DATA}></nile-select>`);
|
|
1622
|
+
await settle(el);
|
|
1623
|
+
const inner = el.shadowRoot!.querySelector('nile-virtual-select') as any;
|
|
1624
|
+
|
|
1625
|
+
el.value = ['a', 'c'];
|
|
1626
|
+
await settle(el);
|
|
1627
|
+
await inner.updateComplete;
|
|
1628
|
+
expect(inner.value).to.deep.equal(['a', 'c']);
|
|
1629
|
+
|
|
1607
1630
|
inner.unSelectAll();
|
|
1608
1631
|
await inner.updateComplete;
|
|
1609
1632
|
await settle(el);
|
|
@@ -1676,3 +1699,535 @@ describe('NileSelect showtooltip tooltip on sub-pixel truncation', () => {
|
|
|
1676
1699
|
}
|
|
1677
1700
|
});
|
|
1678
1701
|
});
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
/**
|
|
1705
|
+
* enableVirtualScroll: the two value/data paths.
|
|
1706
|
+
*
|
|
1707
|
+
* - without `showTooltip` the wrapper behaves as it did before 2.0.9: the inner select owns the
|
|
1708
|
+
* selection, the wrapper `value` is not written back, and `.data` is re-applied as before;
|
|
1709
|
+
* - with `showTooltip` the inner value is synced up, `.data` is only re-applied when its reference
|
|
1710
|
+
* changes, and an external `value` change recomputes an open "Selected" view.
|
|
1711
|
+
*
|
|
1712
|
+
* These tests drive the rendered DOM (option mouseup, footer checkbox, search input, chip remove button)
|
|
1713
|
+
* rather than the inner select's methods.
|
|
1714
|
+
*/
|
|
1715
|
+
type VsInner = HTMLElement & {
|
|
1716
|
+
value: string | string[];
|
|
1717
|
+
data: Array<{ value: string; label: string }>;
|
|
1718
|
+
showSelected: boolean;
|
|
1719
|
+
searchValue: string;
|
|
1720
|
+
maxOptionsVisible: number;
|
|
1721
|
+
updateComplete: Promise<boolean>;
|
|
1722
|
+
};
|
|
1723
|
+
|
|
1724
|
+
const vsMounted: VsInner[] = [];
|
|
1725
|
+
|
|
1726
|
+
const VS_OPTIONS = Array.from({ length: 300 }, (_, i) => ({ value: `option-${i + 1}`, label: `Option ${i + 1}` }));
|
|
1727
|
+
|
|
1728
|
+
function vsRoots(inner: VsInner): ParentNode[] {
|
|
1729
|
+
const portal = document.body.querySelector('.nile-virtual-select-portal-append');
|
|
1730
|
+
return [inner.shadowRoot!, ...(portal ? [portal] : [])];
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
function vsAll(inner: VsInner, selector: string): HTMLElement[] {
|
|
1734
|
+
return vsRoots(inner).flatMap(root => Array.from(root.querySelectorAll<HTMLElement>(selector)));
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
async function vsMount({
|
|
1738
|
+
showTooltip = false,
|
|
1739
|
+
multiple = true,
|
|
1740
|
+
search = false,
|
|
1741
|
+
portal = false,
|
|
1742
|
+
value = undefined as string | string[] | undefined,
|
|
1743
|
+
data = VS_OPTIONS,
|
|
1744
|
+
} = {}) {
|
|
1745
|
+
const initial = value ?? (multiple ? [] : '');
|
|
1746
|
+
const el = await fixture<NileSelect>(html`<nile-select
|
|
1747
|
+
?multiple=${multiple}
|
|
1748
|
+
?searchEnabled=${search}
|
|
1749
|
+
?showTooltip=${showTooltip}
|
|
1750
|
+
.enableVirtualScroll=${true}
|
|
1751
|
+
.portal=${portal}
|
|
1752
|
+
.data=${data}
|
|
1753
|
+
.value=${initial}
|
|
1754
|
+
></nile-select>`);
|
|
1755
|
+
await el.updateComplete;
|
|
1756
|
+
const inner = el.shadowRoot!.querySelector('nile-virtual-select') as unknown as VsInner;
|
|
1757
|
+
await inner.updateComplete;
|
|
1758
|
+
vsMounted.push(inner);
|
|
1759
|
+
let updates = 0;
|
|
1760
|
+
const update = (el as any).update;
|
|
1761
|
+
(el as any).update = function (this: NileSelect, changed: Map<string, unknown>) {
|
|
1762
|
+
updates++;
|
|
1763
|
+
return update.call(this, changed);
|
|
1764
|
+
};
|
|
1765
|
+
return { el, inner, updates: () => updates, resetUpdates: () => (updates = 0) };
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
async function vsSettle(el: NileSelect, inner: VsInner) {
|
|
1769
|
+
await inner.updateComplete;
|
|
1770
|
+
await el.updateComplete;
|
|
1771
|
+
await inner.updateComplete;
|
|
1772
|
+
await aTimeout(30);
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
async function vsOpen(inner: VsInner) {
|
|
1776
|
+
const shown = oneEvent(inner, 'nile-after-show');
|
|
1777
|
+
(inner.shadowRoot!.querySelector('[part="combobox"]') as HTMLElement).dispatchEvent(
|
|
1778
|
+
new MouseEvent('mousedown', { bubbles: true, composed: true, button: 0 })
|
|
1779
|
+
);
|
|
1780
|
+
await shown;
|
|
1781
|
+
await aTimeout(50);
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
async function vsPick(el: NileSelect, inner: VsInner, value: string) {
|
|
1785
|
+
await waitUntil(
|
|
1786
|
+
() => vsAll(inner, 'nile-option').find(o => (o as any).value === value),
|
|
1787
|
+
`option ${value} was not rendered`
|
|
1788
|
+
);
|
|
1789
|
+
const option = vsAll(inner, 'nile-option').find(o => (o as any).value === value)!;
|
|
1790
|
+
option.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, composed: true, button: 0 }));
|
|
1791
|
+
await vsSettle(el, inner);
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
async function vsToggleSelected(el: NileSelect, inner: VsInner) {
|
|
1795
|
+
(vsAll(inner, '.select__footer nile-checkbox')[0] as HTMLElement).click();
|
|
1796
|
+
await vsSettle(el, inner);
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
async function vsType(el: NileSelect, inner: VsInner, text: string) {
|
|
1800
|
+
const input = vsAll(inner, '.select__search nile-input')[0].shadowRoot!.querySelector('input') as HTMLInputElement;
|
|
1801
|
+
input.value = text;
|
|
1802
|
+
input.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
1803
|
+
await vsSettle(el, inner);
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
async function vsRemoveChip(el: NileSelect, inner: VsInner, index = 0) {
|
|
1807
|
+
const tag = inner.shadowRoot!.querySelectorAll('nile-tag')[index] as HTMLElement;
|
|
1808
|
+
const remove = tag.shadowRoot!.querySelector('[part="remove-button"], nile-icon-button, button') as HTMLElement;
|
|
1809
|
+
((remove.shadowRoot?.querySelector('button') as HTMLElement | null) ?? remove).click();
|
|
1810
|
+
await vsSettle(el, inner);
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
const VS_SEARCH = 'Option 99';
|
|
1814
|
+
const VS_SEARCH_HITS = VS_OPTIONS.filter(o => o.label.includes(VS_SEARCH)).length;
|
|
1815
|
+
const vsDataValues = (inner: VsInner) => inner.data.map(item => item.value);
|
|
1816
|
+
|
|
1817
|
+
// Known, pre-existing noise from @lit-labs/virtualizer, unrelated to these tests: a "ResizeObserver loop" notice
|
|
1818
|
+
// while a list is laid out, and a detached-list error when the visible list swaps between a short and a long data
|
|
1819
|
+
// set (for example leaving the Selected view). The browser raises them as window errors, which would fail
|
|
1820
|
+
// whichever test happens to be running. Only the new virtual-scroll describes below install this filter; their
|
|
1821
|
+
// assertions still decide pass or fail.
|
|
1822
|
+
// The virtualizer-only errors are matched on message AND on a `virtualizer` frame in the stack, so the same message
|
|
1823
|
+
// thrown from anywhere else still fails the test. "ResizeObserver loop" is a browser notice with no stack.
|
|
1824
|
+
const VS_VIRTUALIZER_ERRORS = ['ChildPart` has no `parentNode`', "reading 'insertBefore'"];
|
|
1825
|
+
|
|
1826
|
+
function vsIsKnownVirtualizerNoise(message: unknown, error?: Error | null): boolean {
|
|
1827
|
+
if (typeof message !== 'string') return false;
|
|
1828
|
+
if (message.includes('ResizeObserver loop')) return true;
|
|
1829
|
+
return (
|
|
1830
|
+
VS_VIRTUALIZER_ERRORS.some(known => message.includes(known)) &&
|
|
1831
|
+
!!error?.stack &&
|
|
1832
|
+
error.stack.toLowerCase().includes('virtualizer')
|
|
1833
|
+
);
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
function vsIgnoreKnownVirtualizerErrors(): () => void {
|
|
1837
|
+
const previous = window.onerror;
|
|
1838
|
+
window.onerror = (message, source, lineno, colno, error) => {
|
|
1839
|
+
if (vsIsKnownVirtualizerNoise(message, error)) return true;
|
|
1840
|
+
return previous ? previous.call(window, message, source, lineno, colno, error) : false;
|
|
1841
|
+
};
|
|
1842
|
+
return () => {
|
|
1843
|
+
window.onerror = previous;
|
|
1844
|
+
};
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
// Close every dropdown and let it finish hiding before its fixture goes away, so the virtualizer is not
|
|
1848
|
+
// still laying out a list that has already been detached. Registered per describe below, not file-wide.
|
|
1849
|
+
async function vsCloseDropdowns() {
|
|
1850
|
+
const mounted = vsMounted.splice(0);
|
|
1851
|
+
for (const inner of mounted) {
|
|
1852
|
+
if (!(inner as any).open) continue;
|
|
1853
|
+
const hidden = oneEvent(inner, 'nile-after-hide');
|
|
1854
|
+
(inner as any).open = false;
|
|
1855
|
+
await Promise.race([hidden, aTimeout(1500)]);
|
|
1856
|
+
}
|
|
1857
|
+
if (mounted.length) {
|
|
1858
|
+
await nextFrame();
|
|
1859
|
+
await nextFrame();
|
|
1860
|
+
await aTimeout(250);
|
|
1861
|
+
}
|
|
1862
|
+
document.body.querySelectorAll('.nile-virtual-select-portal-append').forEach(n => n.remove());
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
describe('NileSelect enableVirtualScroll without showTooltip keeps the pre-2.0.9 behaviour', () => {
|
|
1866
|
+
let restoreOnError: () => void;
|
|
1867
|
+
before(() => {
|
|
1868
|
+
restoreOnError = vsIgnoreKnownVirtualizerErrors();
|
|
1869
|
+
});
|
|
1870
|
+
after(() => {
|
|
1871
|
+
restoreOnError();
|
|
1872
|
+
});
|
|
1873
|
+
afterEach(vsCloseDropdowns);
|
|
1874
|
+
|
|
1875
|
+
it('L1. a pick does not write the outer value', async () => {
|
|
1876
|
+
const { el, inner } = await vsMount();
|
|
1877
|
+
await vsOpen(inner);
|
|
1878
|
+
await vsPick(el, inner, 'option-1');
|
|
1879
|
+
|
|
1880
|
+
expect(inner.value).to.deep.equal(['option-1']);
|
|
1881
|
+
expect(el.value).to.deep.equal([]);
|
|
1882
|
+
});
|
|
1883
|
+
|
|
1884
|
+
it('L2. a normal pick, uncheck and chip removal cause no outer update', async () => {
|
|
1885
|
+
const { el, inner, updates, resetUpdates } = await vsMount({ value: ['option-9'] });
|
|
1886
|
+
await vsOpen(inner);
|
|
1887
|
+
resetUpdates();
|
|
1888
|
+
|
|
1889
|
+
await vsPick(el, inner, 'option-1');
|
|
1890
|
+
await vsPick(el, inner, 'option-1');
|
|
1891
|
+
await vsRemoveChip(el, inner, 0);
|
|
1892
|
+
|
|
1893
|
+
expect(updates()).to.equal(0);
|
|
1894
|
+
});
|
|
1895
|
+
|
|
1896
|
+
it('L3. a parent re-render pushes the stale outer value back over the selection', async () => {
|
|
1897
|
+
const { el, inner } = await vsMount();
|
|
1898
|
+
await vsOpen(inner);
|
|
1899
|
+
await vsPick(el, inner, 'option-1');
|
|
1900
|
+
expect(inner.value).to.deep.equal(['option-1']);
|
|
1901
|
+
|
|
1902
|
+
el.requestUpdate();
|
|
1903
|
+
await vsSettle(el, inner);
|
|
1904
|
+
|
|
1905
|
+
expect(inner.value).to.deep.equal([]);
|
|
1906
|
+
});
|
|
1907
|
+
|
|
1908
|
+
it('L4. nile-input / nile-change from the inner select are not synced (no sync listeners)', async () => {
|
|
1909
|
+
const { el, inner } = await vsMount({ value: ['option-1'] });
|
|
1910
|
+
const fire = (name: string, value: unknown) =>
|
|
1911
|
+
inner.dispatchEvent(new CustomEvent(name, { detail: { value }, bubbles: true, composed: true }));
|
|
1912
|
+
|
|
1913
|
+
fire('nile-input', ['option-2']);
|
|
1914
|
+
fire('nile-change', ['option-3']);
|
|
1915
|
+
await vsSettle(el, inner);
|
|
1916
|
+
|
|
1917
|
+
expect(el.value).to.deep.equal(['option-1']);
|
|
1918
|
+
});
|
|
1919
|
+
|
|
1920
|
+
it('L5. a direct syncValueFromVirtualSelect call does not change the outer value', async () => {
|
|
1921
|
+
const { el, inner } = await vsMount({ value: ['option-1'] });
|
|
1922
|
+
const event = new CustomEvent('nile-change', { detail: { value: ['option-2'] } });
|
|
1923
|
+
Object.defineProperty(event, 'currentTarget', { value: inner });
|
|
1924
|
+
Object.defineProperty(event, 'composedPath', { value: () => [inner] });
|
|
1925
|
+
|
|
1926
|
+
el.syncValueFromVirtualSelect(event as any);
|
|
1927
|
+
await vsSettle(el, inner);
|
|
1928
|
+
|
|
1929
|
+
expect(el.value).to.deep.equal(['option-1']);
|
|
1930
|
+
});
|
|
1931
|
+
|
|
1932
|
+
it('L6. Selected stays filtered through a normal uncheck', async () => {
|
|
1933
|
+
const { el, inner } = await vsMount();
|
|
1934
|
+
await vsOpen(inner);
|
|
1935
|
+
await vsPick(el, inner, 'option-1');
|
|
1936
|
+
await vsPick(el, inner, 'option-2');
|
|
1937
|
+
await vsPick(el, inner, 'option-3');
|
|
1938
|
+
await vsToggleSelected(el, inner);
|
|
1939
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-3']);
|
|
1940
|
+
|
|
1941
|
+
await vsPick(el, inner, 'option-2');
|
|
1942
|
+
|
|
1943
|
+
expect(inner.showSelected).to.be.true;
|
|
1944
|
+
expect(inner.value).to.deep.equal(['option-1', 'option-3']);
|
|
1945
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-3']);
|
|
1946
|
+
});
|
|
1947
|
+
|
|
1948
|
+
it('L7. search stays filtered through a pick and an unpick', async () => {
|
|
1949
|
+
const { el, inner } = await vsMount({ search: true });
|
|
1950
|
+
await vsOpen(inner);
|
|
1951
|
+
await vsType(el, inner, VS_SEARCH);
|
|
1952
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
1953
|
+
|
|
1954
|
+
await vsPick(el, inner, 'option-99');
|
|
1955
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
1956
|
+
expect(inner.searchValue).to.equal(VS_SEARCH);
|
|
1957
|
+
|
|
1958
|
+
await vsPick(el, inner, 'option-99');
|
|
1959
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
1960
|
+
expect(inner.value).to.deep.equal([]);
|
|
1961
|
+
});
|
|
1962
|
+
|
|
1963
|
+
it('L9. the wrapper pushes maxOptionsVisible to the inner select (pre-2.0.9 binding)', async () => {
|
|
1964
|
+
const { el, inner } = await vsMount({ value: ['option-1'] });
|
|
1965
|
+
const writes: number[] = [];
|
|
1966
|
+
const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(inner), 'maxOptionsVisible')!;
|
|
1967
|
+
Object.defineProperty(inner, 'maxOptionsVisible', {
|
|
1968
|
+
configurable: true,
|
|
1969
|
+
get() {
|
|
1970
|
+
return descriptor.get!.call(this);
|
|
1971
|
+
},
|
|
1972
|
+
set(value: number) {
|
|
1973
|
+
writes.push(value);
|
|
1974
|
+
descriptor.set!.call(this, value);
|
|
1975
|
+
},
|
|
1976
|
+
});
|
|
1977
|
+
|
|
1978
|
+
el.maxOptionsVisible = 5;
|
|
1979
|
+
await vsSettle(el, inner);
|
|
1980
|
+
|
|
1981
|
+
expect(writes).to.include(5);
|
|
1982
|
+
});
|
|
1983
|
+
|
|
1984
|
+
it('L10. the untouched default maxOptionsVisible is not pushed, so the inner select is not pinned as explicit', async () => {
|
|
1985
|
+
const { inner } = await vsMount();
|
|
1986
|
+
|
|
1987
|
+
expect((inner as any).maxOptionsVisibleExplicit).to.be.false;
|
|
1988
|
+
});
|
|
1989
|
+
|
|
1990
|
+
it('L8. data is re-applied on every wrapper render (plain binding, pre-2.0.9)', async () => {
|
|
1991
|
+
const { el, inner } = await vsMount({ value: ['option-1'] });
|
|
1992
|
+
await vsOpen(inner);
|
|
1993
|
+
// After opening, the inner select holds its own copy of the list.
|
|
1994
|
+
expect(inner.data).to.not.equal(el.data);
|
|
1995
|
+
|
|
1996
|
+
el.requestUpdate();
|
|
1997
|
+
await vsSettle(el, inner);
|
|
1998
|
+
|
|
1999
|
+
expect(inner.data).to.equal(el.data);
|
|
2000
|
+
});
|
|
2001
|
+
});
|
|
2002
|
+
|
|
2003
|
+
describe('NileSelect enableVirtualScroll with showTooltip: guarded data and external value updates', () => {
|
|
2004
|
+
let restoreOnError: () => void;
|
|
2005
|
+
before(() => {
|
|
2006
|
+
restoreOnError = vsIgnoreKnownVirtualizerErrors();
|
|
2007
|
+
});
|
|
2008
|
+
after(() => {
|
|
2009
|
+
restoreOnError();
|
|
2010
|
+
});
|
|
2011
|
+
afterEach(vsCloseDropdowns);
|
|
2012
|
+
|
|
2013
|
+
it('T1. Selected + uncheck stays filtered', async () => {
|
|
2014
|
+
const { el, inner } = await vsMount({ showTooltip: true });
|
|
2015
|
+
await vsOpen(inner);
|
|
2016
|
+
await vsPick(el, inner, 'option-1');
|
|
2017
|
+
await vsPick(el, inner, 'option-2');
|
|
2018
|
+
await vsPick(el, inner, 'option-3');
|
|
2019
|
+
await vsToggleSelected(el, inner);
|
|
2020
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-3']);
|
|
2021
|
+
|
|
2022
|
+
await vsPick(el, inner, 'option-2');
|
|
2023
|
+
|
|
2024
|
+
expect(inner.showSelected).to.be.true;
|
|
2025
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-3']);
|
|
2026
|
+
expect(el.value).to.deep.equal(['option-1', 'option-3']);
|
|
2027
|
+
});
|
|
2028
|
+
|
|
2029
|
+
it('T2. search + pick/unpick stays filtered', async () => {
|
|
2030
|
+
const { el, inner } = await vsMount({ showTooltip: true, search: true });
|
|
2031
|
+
await vsOpen(inner);
|
|
2032
|
+
await vsType(el, inner, VS_SEARCH);
|
|
2033
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
2034
|
+
|
|
2035
|
+
await vsPick(el, inner, 'option-99');
|
|
2036
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
2037
|
+
expect(inner.searchValue).to.equal(VS_SEARCH);
|
|
2038
|
+
expect(el.value).to.deep.equal(['option-99']);
|
|
2039
|
+
|
|
2040
|
+
await vsPick(el, inner, 'option-99');
|
|
2041
|
+
expect(inner.data.length).to.equal(VS_SEARCH_HITS);
|
|
2042
|
+
expect(el.value).to.deep.equal([]);
|
|
2043
|
+
});
|
|
2044
|
+
|
|
2045
|
+
it('T3. chip removal while Selected stays filtered', async () => {
|
|
2046
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2', 'option-3'] });
|
|
2047
|
+
await vsOpen(inner);
|
|
2048
|
+
await vsToggleSelected(el, inner);
|
|
2049
|
+
expect(inner.data.length).to.equal(3);
|
|
2050
|
+
|
|
2051
|
+
await vsRemoveChip(el, inner, 0);
|
|
2052
|
+
|
|
2053
|
+
expect(inner.showSelected).to.be.true;
|
|
2054
|
+
expect(inner.data.length).to.equal(3);
|
|
2055
|
+
expect(el.value).to.deep.equal(['option-2', 'option-3']);
|
|
2056
|
+
});
|
|
2057
|
+
|
|
2058
|
+
it('T4. portal: Selected + uncheck stays filtered', async () => {
|
|
2059
|
+
const { el, inner } = await vsMount({ showTooltip: true, portal: true });
|
|
2060
|
+
await vsOpen(inner);
|
|
2061
|
+
await waitUntil(() => document.body.querySelector('.nile-virtual-select-portal-append #listbox'), 'listbox never portalled');
|
|
2062
|
+
await vsPick(el, inner, 'option-1');
|
|
2063
|
+
await vsPick(el, inner, 'option-2');
|
|
2064
|
+
await vsToggleSelected(el, inner);
|
|
2065
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2']);
|
|
2066
|
+
|
|
2067
|
+
await vsPick(el, inner, 'option-2');
|
|
2068
|
+
|
|
2069
|
+
expect(inner.showSelected).to.be.true;
|
|
2070
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2']);
|
|
2071
|
+
expect(el.value).to.deep.equal(['option-1']);
|
|
2072
|
+
});
|
|
2073
|
+
|
|
2074
|
+
it('T5. picking, removing a chip and clearing sync the outer value; nile-change listeners see it', async () => {
|
|
2075
|
+
const { el, inner } = await vsMount({ showTooltip: true });
|
|
2076
|
+
const seen: unknown[] = [];
|
|
2077
|
+
el.addEventListener('nile-change', () => seen.push(el.value));
|
|
2078
|
+
await vsOpen(inner);
|
|
2079
|
+
|
|
2080
|
+
await vsPick(el, inner, 'option-1');
|
|
2081
|
+
await vsPick(el, inner, 'option-2');
|
|
2082
|
+
expect(el.value).to.deep.equal(['option-1', 'option-2']);
|
|
2083
|
+
expect(seen[0]).to.deep.equal(['option-1']);
|
|
2084
|
+
|
|
2085
|
+
await vsRemoveChip(el, inner, 0);
|
|
2086
|
+
expect(el.value).to.deep.equal(['option-2']);
|
|
2087
|
+
|
|
2088
|
+
(vsAll(inner, '.select__clear')[0] as HTMLElement).click();
|
|
2089
|
+
await vsSettle(el, inner);
|
|
2090
|
+
expect(el.value).to.deep.equal([]);
|
|
2091
|
+
});
|
|
2092
|
+
|
|
2093
|
+
it('T6. an external value replace while Selected recomputes the list', async () => {
|
|
2094
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
2095
|
+
await vsOpen(inner);
|
|
2096
|
+
await vsToggleSelected(el, inner);
|
|
2097
|
+
|
|
2098
|
+
el.value = ['option-5'];
|
|
2099
|
+
await vsSettle(el, inner);
|
|
2100
|
+
|
|
2101
|
+
expect(inner.showSelected).to.be.true;
|
|
2102
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-5']);
|
|
2103
|
+
});
|
|
2104
|
+
|
|
2105
|
+
it('T7. an external value that adds an item while Selected shows the new item', async () => {
|
|
2106
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
2107
|
+
await vsOpen(inner);
|
|
2108
|
+
await vsToggleSelected(el, inner);
|
|
2109
|
+
|
|
2110
|
+
el.value = ['option-1', 'option-2', 'option-7'];
|
|
2111
|
+
await vsSettle(el, inner);
|
|
2112
|
+
|
|
2113
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1', 'option-2', 'option-7']);
|
|
2114
|
+
});
|
|
2115
|
+
|
|
2116
|
+
it('T8. an external value that removes an item while Selected drops it from the list', async () => {
|
|
2117
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
2118
|
+
await vsOpen(inner);
|
|
2119
|
+
await vsToggleSelected(el, inner);
|
|
2120
|
+
|
|
2121
|
+
el.value = ['option-1'];
|
|
2122
|
+
await vsSettle(el, inner);
|
|
2123
|
+
|
|
2124
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-1']);
|
|
2125
|
+
});
|
|
2126
|
+
|
|
2127
|
+
it('T9. an external empty value leaves the Selected view', async () => {
|
|
2128
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
2129
|
+
await vsOpen(inner);
|
|
2130
|
+
await vsToggleSelected(el, inner);
|
|
2131
|
+
|
|
2132
|
+
el.value = [];
|
|
2133
|
+
await vsSettle(el, inner);
|
|
2134
|
+
|
|
2135
|
+
expect(inner.showSelected).to.be.false;
|
|
2136
|
+
expect(inner.data.length).to.equal(VS_OPTIONS.length);
|
|
2137
|
+
});
|
|
2138
|
+
|
|
2139
|
+
it('T10. a normal pick after an external value update still keeps the item listed', async () => {
|
|
2140
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
2141
|
+
await vsOpen(inner);
|
|
2142
|
+
await vsToggleSelected(el, inner);
|
|
2143
|
+
el.value = ['option-5', 'option-6'];
|
|
2144
|
+
await vsSettle(el, inner);
|
|
2145
|
+
|
|
2146
|
+
await vsPick(el, inner, 'option-5');
|
|
2147
|
+
|
|
2148
|
+
expect(inner.value).to.deep.equal(['option-6']);
|
|
2149
|
+
expect(el.value).to.deep.equal(['option-6']);
|
|
2150
|
+
expect(inner.showSelected).to.be.true;
|
|
2151
|
+
expect(vsDataValues(inner)).to.deep.equal(['option-5', 'option-6']);
|
|
2152
|
+
});
|
|
2153
|
+
|
|
2154
|
+
it('T11. a normal pick does not re-send the data array', async () => {
|
|
2155
|
+
const { el, inner } = await vsMount({ showTooltip: true, value: ['option-1', 'option-2'] });
|
|
2156
|
+
await vsOpen(inner);
|
|
2157
|
+
await vsToggleSelected(el, inner);
|
|
2158
|
+
const before = inner.data;
|
|
2159
|
+
|
|
2160
|
+
await vsPick(el, inner, 'option-2');
|
|
2161
|
+
|
|
2162
|
+
expect(inner.data).to.equal(before);
|
|
2163
|
+
});
|
|
2164
|
+
|
|
2165
|
+
it('T12. turning showTooltip on at runtime keeps the selection', async () => {
|
|
2166
|
+
const { el, inner } = await vsMount({ showTooltip: false });
|
|
2167
|
+
await vsOpen(inner);
|
|
2168
|
+
await vsPick(el, inner, 'option-1');
|
|
2169
|
+
await vsPick(el, inner, 'option-2');
|
|
2170
|
+
expect(el.value).to.deep.equal([]);
|
|
2171
|
+
expect(inner.value).to.deep.equal(['option-1', 'option-2']);
|
|
2172
|
+
|
|
2173
|
+
el.showTooltip = true;
|
|
2174
|
+
await vsSettle(el, inner);
|
|
2175
|
+
|
|
2176
|
+
expect(el.value).to.deep.equal(['option-1', 'option-2']);
|
|
2177
|
+
expect(inner.value).to.deep.equal(['option-1', 'option-2']);
|
|
2178
|
+
});
|
|
2179
|
+
|
|
2180
|
+
it('T15. turning showTooltip on at runtime engages the fitted chip row', async () => {
|
|
2181
|
+
const { el, inner } = await vsMount({
|
|
2182
|
+
showTooltip: false,
|
|
2183
|
+
value: ['option-1', 'option-2', 'option-3', 'option-4', 'option-5'],
|
|
2184
|
+
});
|
|
2185
|
+
const fitted = () => !!inner.shadowRoot!.querySelector('.select__tags--fitted');
|
|
2186
|
+
expect(fitted()).to.be.false;
|
|
2187
|
+
|
|
2188
|
+
el.showTooltip = true;
|
|
2189
|
+
await vsSettle(el, inner);
|
|
2190
|
+
|
|
2191
|
+
await waitUntil(fitted, 'the fitted chip row never engaged');
|
|
2192
|
+
expect(el.value).to.deep.equal(['option-1', 'option-2', 'option-3', 'option-4', 'option-5']);
|
|
2193
|
+
});
|
|
2194
|
+
|
|
2195
|
+
it('T16. changing showTooltip and value in the same update keeps the consumer value', async () => {
|
|
2196
|
+
const { el, inner } = await vsMount({ showTooltip: false });
|
|
2197
|
+
await vsOpen(inner);
|
|
2198
|
+
await vsPick(el, inner, 'option-1');
|
|
2199
|
+
expect(inner.value).to.deep.equal(['option-1']);
|
|
2200
|
+
expect(el.value).to.deep.equal([]);
|
|
2201
|
+
|
|
2202
|
+
el.value = ['option-7'];
|
|
2203
|
+
el.showTooltip = true;
|
|
2204
|
+
await vsSettle(el, inner);
|
|
2205
|
+
|
|
2206
|
+
expect(el.value).to.deep.equal(['option-7']);
|
|
2207
|
+
expect(inner.value).to.deep.equal(['option-7']);
|
|
2208
|
+
});
|
|
2209
|
+
|
|
2210
|
+
it('T13. assigning a new data array propagates', async () => {
|
|
2211
|
+
const { el, inner } = await vsMount({ showTooltip: true });
|
|
2212
|
+
await vsOpen(inner);
|
|
2213
|
+
|
|
2214
|
+
el.data = [...VS_OPTIONS.slice(0, 10), { value: 'extra', label: 'Extra' }];
|
|
2215
|
+
await vsSettle(el, inner);
|
|
2216
|
+
|
|
2217
|
+
expect(inner.data.length).to.equal(11);
|
|
2218
|
+
expect(vsDataValues(inner)).to.include('extra');
|
|
2219
|
+
});
|
|
2220
|
+
|
|
2221
|
+
it('T14. mutating data in place (data.push) is not propagated; assign a new array instead', async () => {
|
|
2222
|
+
const data = VS_OPTIONS.slice(0, 20);
|
|
2223
|
+
const { el, inner } = await vsMount({ showTooltip: true, data });
|
|
2224
|
+
await vsOpen(inner);
|
|
2225
|
+
|
|
2226
|
+
data.push({ value: 'extra', label: 'Extra' });
|
|
2227
|
+
el.requestUpdate();
|
|
2228
|
+
await vsSettle(el, inner);
|
|
2229
|
+
|
|
2230
|
+
expect(inner.data.length).to.equal(20);
|
|
2231
|
+
expect(vsDataValues(inner)).to.not.include('extra');
|
|
2232
|
+
});
|
|
2233
|
+
});
|
|
@@ -474,11 +474,31 @@ export class NileSelect extends NileElement implements NileFormControl{
|
|
|
474
474
|
}
|
|
475
475
|
|
|
476
476
|
syncValueFromVirtualSelect(event: CustomEvent<{ value?: string | string[] }>) {
|
|
477
|
+
if (!this.showTooltip) return;
|
|
477
478
|
if (event.composedPath()[0] !== event.currentTarget) return;
|
|
478
479
|
if (!event.detail || !('value' in event.detail)) return;
|
|
479
480
|
this.value = event.detail.value ?? (this.multiple ? [] : '');
|
|
480
481
|
}
|
|
481
482
|
|
|
483
|
+
protected willUpdate(changedProperties: PropertyValues): void {
|
|
484
|
+
super.willUpdate(changedProperties);
|
|
485
|
+
|
|
486
|
+
if (
|
|
487
|
+
changedProperties.has('showTooltip') &&
|
|
488
|
+
changedProperties.get('showTooltip') === false &&
|
|
489
|
+
this.showTooltip &&
|
|
490
|
+
this.enableVirtualScroll &&
|
|
491
|
+
!changedProperties.has('value')
|
|
492
|
+
) {
|
|
493
|
+
const inner = this.shadowRoot?.querySelector('nile-virtual-select') as
|
|
494
|
+
| { value: string | string[] }
|
|
495
|
+
| null;
|
|
496
|
+
if (inner && inner.value !== this.value) {
|
|
497
|
+
this.value = inner.value;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
482
502
|
protected updated(_changedProperties: PropertyValues): void {
|
|
483
503
|
if(_changedProperties.has('searchEnabled')) {
|
|
484
504
|
this.updateGroupStickyOffsets();
|
|
@@ -1165,7 +1185,7 @@ export class NileSelect extends NileElement implements NileFormControl{
|
|
|
1165
1185
|
|
|
1166
1186
|
// Update the value and display label
|
|
1167
1187
|
if (this.multiple) {
|
|
1168
|
-
const hasOptions = this.getAllOptions().length > 0;
|
|
1188
|
+
const hasOptions = !this.showTooltip || this.getAllOptions().length > 0;
|
|
1169
1189
|
|
|
1170
1190
|
if (hasOptions) {
|
|
1171
1191
|
this.value = this.selectedOptions.map(el => el.value);
|