@aquera/nile-elements 2.0.12 → 2.0.14

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 (83) hide show
  1. package/README.md +13 -0
  2. package/dist/index.js +132 -134
  3. package/dist/nile-auto-complete/nile-auto-complete.css.cjs.js +1 -1
  4. package/dist/nile-auto-complete/nile-auto-complete.css.cjs.js.map +1 -1
  5. package/dist/nile-auto-complete/nile-auto-complete.css.esm.js +5 -2
  6. package/dist/nile-chip/nile-chip.css.cjs.js +1 -1
  7. package/dist/nile-chip/nile-chip.css.cjs.js.map +1 -1
  8. package/dist/nile-chip/nile-chip.css.esm.js +2 -0
  9. package/dist/nile-combobox/nile-combobox.css.cjs.js +1 -1
  10. package/dist/nile-combobox/nile-combobox.css.cjs.js.map +1 -1
  11. package/dist/nile-combobox/nile-combobox.css.esm.js +9 -9
  12. package/dist/nile-command-menu/nile-command-menu.css.cjs.js +1 -1
  13. package/dist/nile-command-menu/nile-command-menu.css.cjs.js.map +1 -1
  14. package/dist/nile-command-menu/nile-command-menu.css.esm.js +5 -5
  15. package/dist/nile-command-menu-item/nile-command-menu-item.css.cjs.js +1 -1
  16. package/dist/nile-command-menu-item/nile-command-menu-item.css.cjs.js.map +1 -1
  17. package/dist/nile-command-menu-item/nile-command-menu-item.css.esm.js +2 -2
  18. package/dist/nile-option/nile-option.css.cjs.js +1 -1
  19. package/dist/nile-option/nile-option.css.cjs.js.map +1 -1
  20. package/dist/nile-option/nile-option.css.esm.js +1 -1
  21. package/dist/nile-select/nile-select.cjs.js +2 -2
  22. package/dist/nile-select/nile-select.cjs.js.map +1 -1
  23. package/dist/nile-select/nile-select.css.cjs.js +1 -1
  24. package/dist/nile-select/nile-select.css.cjs.js.map +1 -1
  25. package/dist/nile-select/nile-select.css.esm.js +19 -24
  26. package/dist/nile-select/nile-select.esm.js +43 -42
  27. package/dist/nile-select/virtual-scroll-helper.cjs.js +1 -1
  28. package/dist/nile-select/virtual-scroll-helper.cjs.js.map +1 -1
  29. package/dist/nile-select/virtual-scroll-helper.esm.js +2 -0
  30. package/dist/nile-virtual-select/nile-virtual-select.cjs.js +4 -4
  31. package/dist/nile-virtual-select/nile-virtual-select.cjs.js.map +1 -1
  32. package/dist/nile-virtual-select/nile-virtual-select.css.cjs.js +1 -1
  33. package/dist/nile-virtual-select/nile-virtual-select.css.cjs.js.map +1 -1
  34. package/dist/nile-virtual-select/nile-virtual-select.css.esm.js +20 -25
  35. package/dist/nile-virtual-select/nile-virtual-select.esm.js +26 -26
  36. package/dist/src/nile-auto-complete/nile-auto-complete.css.js +3 -0
  37. package/dist/src/nile-auto-complete/nile-auto-complete.css.js.map +1 -1
  38. package/dist/src/nile-chip/nile-chip.css.js +2 -0
  39. package/dist/src/nile-chip/nile-chip.css.js.map +1 -1
  40. package/dist/src/nile-combobox/nile-combobox.css.js +9 -9
  41. package/dist/src/nile-combobox/nile-combobox.css.js.map +1 -1
  42. package/dist/src/nile-command-menu/nile-command-menu.css.js +5 -5
  43. package/dist/src/nile-command-menu/nile-command-menu.css.js.map +1 -1
  44. package/dist/src/nile-command-menu-item/nile-command-menu-item.css.js +2 -2
  45. package/dist/src/nile-command-menu-item/nile-command-menu-item.css.js.map +1 -1
  46. package/dist/src/nile-option/nile-option.css.js +1 -1
  47. package/dist/src/nile-option/nile-option.css.js.map +1 -1
  48. package/dist/src/nile-select/nile-select.css.js +19 -24
  49. package/dist/src/nile-select/nile-select.css.js.map +1 -1
  50. package/dist/src/nile-select/nile-select.d.ts +18 -2
  51. package/dist/src/nile-select/nile-select.js +226 -64
  52. package/dist/src/nile-select/nile-select.js.map +1 -1
  53. package/dist/src/nile-select/nile-select.test.d.ts +1 -0
  54. package/dist/src/nile-select/nile-select.test.js +896 -17
  55. package/dist/src/nile-select/nile-select.test.js.map +1 -1
  56. package/dist/src/nile-select/virtual-scroll-helper.js +2 -0
  57. package/dist/src/nile-select/virtual-scroll-helper.js.map +1 -1
  58. package/dist/src/nile-virtual-select/nile-virtual-select.css.js +20 -25
  59. package/dist/src/nile-virtual-select/nile-virtual-select.css.js.map +1 -1
  60. package/dist/src/nile-virtual-select/nile-virtual-select.d.ts +10 -2
  61. package/dist/src/nile-virtual-select/nile-virtual-select.js +142 -30
  62. package/dist/src/nile-virtual-select/nile-virtual-select.js.map +1 -1
  63. package/dist/src/nile-virtual-select/nile-virtual-select.test.d.ts +1 -0
  64. package/dist/src/nile-virtual-select/nile-virtual-select.test.js +331 -16
  65. package/dist/src/nile-virtual-select/nile-virtual-select.test.js.map +1 -1
  66. package/dist/src/version.js +1 -1
  67. package/dist/src/version.js.map +1 -1
  68. package/dist/tsconfig.tsbuildinfo +1 -1
  69. package/package.json +1 -1
  70. package/src/nile-auto-complete/nile-auto-complete.css.ts +3 -0
  71. package/src/nile-chip/nile-chip.css.ts +2 -0
  72. package/src/nile-combobox/nile-combobox.css.ts +9 -9
  73. package/src/nile-command-menu/nile-command-menu.css.ts +5 -5
  74. package/src/nile-command-menu-item/nile-command-menu-item.css.ts +2 -2
  75. package/src/nile-option/nile-option.css.ts +1 -1
  76. package/src/nile-select/nile-select.css.ts +19 -24
  77. package/src/nile-select/nile-select.test.ts +1112 -17
  78. package/src/nile-select/nile-select.ts +237 -67
  79. package/src/nile-select/virtual-scroll-helper.ts +2 -0
  80. package/src/nile-virtual-select/nile-virtual-select.css.ts +20 -25
  81. package/src/nile-virtual-select/nile-virtual-select.test.ts +404 -16
  82. package/src/nile-virtual-select/nile-virtual-select.ts +200 -79
  83. package/vscode-html-custom-data.json +9 -4
@@ -131,6 +131,7 @@ export class NileSelect extends NileElement implements NileFormControl{
131
131
  private observedTagsContainer?: Element;
132
132
 
133
133
  private resizeController = new ResizeController(this, {
134
+ target: null,
134
135
  callback: (entries: ResizeObserverEntry[]) => {
135
136
  for (const entry of entries) {
136
137
  if (entry.target.classList.contains('select__tags')) {
@@ -141,6 +142,7 @@ export class NileSelect extends NileElement implements NileFormControl{
141
142
  });
142
143
  private visibilityManager?: VisibilityManager;
143
144
  private chipFitFrame = 0;
145
+ private measurableWatch?: { observer: ResizeObserver; target: Element };
144
146
  private lastChipLayout = { hidden: -1, visible: -1 };
145
147
  @state() private clippedChips: boolean[] = [];
146
148
  private clipFrame = 0;
@@ -158,6 +160,7 @@ export class NileSelect extends NileElement implements NileFormControl{
158
160
  @state() selectedOptions: NileOption[] = [];
159
161
  @state() oldValue: string | string[] = '';
160
162
  @state() private hiddenChipCount = 0;
163
+ @state() oldMaxOptionsVisible: number = 1;
161
164
 
162
165
  /** Last measured width of the overflow button, in px. */
163
166
  private lastOverflowWidth = 0;
@@ -269,18 +272,29 @@ export class NileSelect extends NileElement implements NileFormControl{
269
272
  }
270
273
 
271
274
  private get chipFittingEnabled(): boolean {
272
- return !!this.multiple && !this.maxOptionsVisibleExplicit;
275
+ return !!this.multiple && this.showTooltip && !this.maxOptionsVisibleExplicit;
276
+ }
277
+
278
+ private get legacyTagFitEnabled(): boolean {
279
+ return !!this.multiple && !this.showTooltip;
280
+ }
281
+
282
+ private setFittedMaxOptionsVisible(value: number): void {
283
+ const previous = this._maxOptionsVisible;
284
+ this._maxOptionsVisible = value;
285
+ this.requestUpdate('maxOptionsVisible', previous);
273
286
  }
274
287
 
275
288
  /** Minimum width, in px, of a squeezed chip. Needs `showtooltip`. */
276
- @property({ type: Number, reflect: true, attribute: true }) chipMinWidth = 110;
289
+ @property({ type: Number, attribute: true }) chipMinWidth = 110;
277
290
 
278
291
  /** Maximum width, in px, of a squeezed chip. Needs `showtooltip`. */
279
- @property({ type: Number, reflect: true, attribute: true }) chipMaxWidth = 180;
292
+ @property({ type: Number, attribute: true }) chipMaxWidth = 180;
280
293
 
281
294
  /**
282
- * Shows a chip's full value in a tooltip when its text is clipped, and is
283
- * what allows a chip to be truncated at all.
295
+ * Opts into the fitted chip row: chips are sized between chipMinWidth and chipMaxWidth, the
296
+ * rest collapse into a +N button, and a clipped chip shows its full value in a tooltip.
297
+ * Off by default, which keeps the pre-2.0.9 chip row.
284
298
  */
285
299
  @property({ type: Boolean, attribute: true, reflect: true }) showTooltip = false;
286
300
 
@@ -399,6 +413,9 @@ export class NileSelect extends NileElement implements NileFormControl{
399
413
 
400
414
  // Because this is a form control, it shouldn't be opened initially
401
415
  this.open = false;
416
+ if (this.hasUpdated && this.chipFittingEnabled) {
417
+ this.calculateTotalWidthOfTags();
418
+ }
402
419
  this.emit('nile-init');
403
420
  }
404
421
 
@@ -418,7 +435,7 @@ export class NileSelect extends NileElement implements NileFormControl{
418
435
 
419
436
  private setupResizeObserver(): void {
420
437
  const wanted =
421
- this.autoResize && this.chipFittingEnabled
438
+ this.autoResize && (this.chipFittingEnabled || this.legacyTagFitEnabled)
422
439
  ? (this.shadowRoot?.querySelector('.select__tags') as HTMLElement | null) ??
423
440
  undefined
424
441
  : undefined;
@@ -456,6 +473,12 @@ export class NileSelect extends NileElement implements NileFormControl{
456
473
  }
457
474
  }
458
475
 
476
+ syncValueFromVirtualSelect(event: CustomEvent<{ value?: string | string[] }>) {
477
+ if (event.composedPath()[0] !== event.currentTarget) return;
478
+ if (!event.detail || !('value' in event.detail)) return;
479
+ this.value = event.detail.value ?? (this.multiple ? [] : '');
480
+ }
481
+
459
482
  protected updated(_changedProperties: PropertyValues): void {
460
483
  if(_changedProperties.has('searchEnabled')) {
461
484
  this.updateGroupStickyOffsets();
@@ -472,10 +495,18 @@ export class NileSelect extends NileElement implements NileFormControl{
472
495
  if (
473
496
  _changedProperties.has('autoResize') ||
474
497
  _changedProperties.has('multiple') ||
475
- _changedProperties.has('maxOptionsVisible')
498
+ _changedProperties.has('maxOptionsVisible') ||
499
+ _changedProperties.has('showTooltip')
476
500
  ) {
477
501
  this.setupResizeObserver();
478
502
  }
503
+ if (
504
+ _changedProperties.has('showTooltip') &&
505
+ _changedProperties.get('showTooltip') !== undefined &&
506
+ this.legacyTagFitEnabled
507
+ ) {
508
+ this.calculateTotalWidthOfTags();
509
+ }
479
510
  this.syncVirtualSelectMaxOptionsVisible();
480
511
  if(_changedProperties.has('enableDescription')) {
481
512
  this.setEnableDescriptionInOptions();
@@ -1045,13 +1076,27 @@ export class NileSelect extends NileElement implements NileFormControl{
1045
1076
  return options;
1046
1077
  }
1047
1078
 
1048
- private getOptionPrefixNodes(option: NileOption): Node[] {
1079
+ private prefixCopies = new WeakMap<NileOption, Map<string, { markup: string; nodes: Node[] }>>();
1080
+
1081
+ private getOptionPrefixNodes(option: NileOption, site: 'trigger' | 'chip'): Node[] {
1049
1082
  const prefixSlot = option.shadowRoot?.querySelector(
1050
1083
  'slot[name="prefix"]'
1051
1084
  ) as HTMLSlotElement | null;
1052
1085
  if (!prefixSlot) return [];
1053
1086
 
1054
- return prefixSlot.assignedElements().map(el => el.cloneNode(true));
1087
+ const sources = prefixSlot.assignedElements();
1088
+ const markup = sources.map(el => el.outerHTML).join('');
1089
+ let sites = this.prefixCopies.get(option);
1090
+ if (!sites) {
1091
+ sites = new Map();
1092
+ this.prefixCopies.set(option, sites);
1093
+ }
1094
+ const cached = sites.get(site);
1095
+ if (cached && cached.markup === markup) return cached.nodes;
1096
+
1097
+ const nodes = sources.map(el => el.cloneNode(true));
1098
+ sites.set(site, { markup, nodes });
1099
+ return nodes;
1055
1100
  }
1056
1101
 
1057
1102
  // Gets the first <nile-option> element
@@ -1458,6 +1503,10 @@ export class NileSelect extends NileElement implements NileFormControl{
1458
1503
  }
1459
1504
 
1460
1505
  calculateTotalWidthOfTags() {
1506
+ if (this.legacyTagFitEnabled) {
1507
+ this.fitTagsLegacy();
1508
+ return;
1509
+ }
1461
1510
  if (!this.chipFittingEnabled) return;
1462
1511
 
1463
1512
  if (this.chipFitFrame) cancelAnimationFrame(this.chipFitFrame);
@@ -1467,6 +1516,56 @@ export class NileSelect extends NileElement implements NileFormControl{
1467
1516
  });
1468
1517
  }
1469
1518
 
1519
+ private calculateWidthOfSelectTagsDiv() {
1520
+ if (this.shadowRoot) {
1521
+ const selectTagsDiv = this.shadowRoot.querySelector('div.select__tags');
1522
+ if (selectTagsDiv instanceof HTMLElement) {
1523
+ const width = selectTagsDiv.offsetWidth;
1524
+ return width - 70;
1525
+ }
1526
+ }
1527
+ }
1528
+
1529
+ private fitTagsLegacy() {
1530
+ if (this.maxOptionsVisible !== Infinity) {
1531
+ this.oldMaxOptionsVisible = this.maxOptionsVisible;
1532
+ }
1533
+
1534
+ this.setFittedMaxOptionsVisible(Infinity);
1535
+ setTimeout(() => {
1536
+ const widths: number[] = [];
1537
+ if (this.shadowRoot) {
1538
+ const tags = this.shadowRoot.querySelectorAll('nile-tag');
1539
+ tags.forEach(tag => {
1540
+ if (tag instanceof HTMLElement) {
1541
+ widths.push(tag.offsetWidth);
1542
+ }
1543
+ });
1544
+ }
1545
+ if (this.value.length !== widths.length) {
1546
+ return;
1547
+ }
1548
+
1549
+ const widthOfSelectTagsDiv = this.calculateWidthOfSelectTagsDiv();
1550
+ if (!widthOfSelectTagsDiv) {
1551
+ return;
1552
+ }
1553
+
1554
+ let summ = 0;
1555
+ let lastindex = 0;
1556
+
1557
+ for (let i = 0; i < widths.length; i++) {
1558
+ summ += widths[i];
1559
+
1560
+ if (summ > widthOfSelectTagsDiv) {
1561
+ lastindex = i;
1562
+ break;
1563
+ }
1564
+ }
1565
+ this.setFittedMaxOptionsVisible(lastindex);
1566
+ }, 1);
1567
+ }
1568
+
1470
1569
  private allocateChipWidths(
1471
1570
  natural: number[],
1472
1571
  available: number
@@ -1567,6 +1666,12 @@ export class NileSelect extends NileElement implements NileFormControl{
1567
1666
  return;
1568
1667
  }
1569
1668
 
1669
+ if (container.clientWidth === 0) {
1670
+ this.refitWhenMeasurable(container);
1671
+ return;
1672
+ }
1673
+ this.stopMeasurableWatch();
1674
+
1570
1675
  const overflowEl = container.querySelector(
1571
1676
  '.select__tags-count'
1572
1677
  ) as HTMLElement | null;
@@ -1632,6 +1737,35 @@ export class NileSelect extends NileElement implements NileFormControl{
1632
1737
  this.refreshClippedChips();
1633
1738
  }
1634
1739
 
1740
+ private labelOverflows(content: HTMLSlotElement): boolean {
1741
+ let left = Infinity;
1742
+ let right = -Infinity;
1743
+ const range = document.createRange();
1744
+ for (const node of content.assignedNodes({ flatten: true })) {
1745
+ let rect: DOMRect;
1746
+ if (node.nodeType === Node.TEXT_NODE) {
1747
+ if (!node.textContent?.trim()) continue;
1748
+ range.selectNodeContents(node);
1749
+ rect = range.getBoundingClientRect();
1750
+ } else if (node instanceof Element) {
1751
+ rect = node.getBoundingClientRect();
1752
+ } else {
1753
+ continue;
1754
+ }
1755
+ if (rect.width === 0) continue;
1756
+ left = Math.min(left, rect.left);
1757
+ right = Math.max(right, rect.right);
1758
+ }
1759
+ if (right < left) return false;
1760
+
1761
+ const box = content.getBoundingClientRect();
1762
+ const styles = getComputedStyle(content);
1763
+ const boxLeft = box.left + parseFloat(styles.borderLeftWidth) + parseFloat(styles.paddingLeft);
1764
+ const boxRight = box.right - parseFloat(styles.borderRightWidth) - parseFloat(styles.paddingRight);
1765
+ const epsilon = 1 / 64;
1766
+ return right > boxRight + epsilon || left < boxLeft - epsilon;
1767
+ }
1768
+
1635
1769
  private isChipClipped(el: HTMLElement | null | undefined): boolean {
1636
1770
  if (!el) return false;
1637
1771
 
@@ -1639,8 +1773,8 @@ export class NileSelect extends NileElement implements NileFormControl{
1639
1773
  if (root) {
1640
1774
  const content = root.querySelector(
1641
1775
  '[part="content"]'
1642
- ) as HTMLElement | null;
1643
- if (content && content.scrollWidth > content.clientWidth + 1) return true;
1776
+ ) as HTMLSlotElement | null;
1777
+ if (content && this.labelOverflows(content)) return true;
1644
1778
 
1645
1779
  const inner = root.querySelector(
1646
1780
  '[part="prefix_content_wrapper"]'
@@ -1691,6 +1825,25 @@ export class NileSelect extends NileElement implements NileFormControl{
1691
1825
  if (this.clipFrame) cancelAnimationFrame(this.clipFrame);
1692
1826
  this.clipFrame = 0;
1693
1827
  this.lastChipLayout = { hidden: -1, visible: -1 };
1828
+ this.stopMeasurableWatch();
1829
+ }
1830
+
1831
+ private refitWhenMeasurable(container: Element): void {
1832
+ if (!this.isConnected) return;
1833
+ if (this.measurableWatch?.target === container) return;
1834
+ this.stopMeasurableWatch();
1835
+ const observer = new ResizeObserver(entries => {
1836
+ if (!entries.some(entry => entry.contentRect.width > 0)) return;
1837
+ this.stopMeasurableWatch();
1838
+ this.calculateTotalWidthOfTags();
1839
+ });
1840
+ observer.observe(container);
1841
+ this.measurableWatch = { observer, target: container };
1842
+ }
1843
+
1844
+ private stopMeasurableWatch(): void {
1845
+ this.measurableWatch?.observer.disconnect();
1846
+ this.measurableWatch = undefined;
1694
1847
  }
1695
1848
 
1696
1849
  private getChipLabel(option: NileOption): string {
@@ -1761,7 +1914,7 @@ export class NileSelect extends NileElement implements NileFormControl{
1761
1914
  <div part="tags" class="select__tags select__tags--fitted">
1762
1915
  ${this.selectedOptions.map((option, index) => {
1763
1916
  const label = this.getChipLabel(option);
1764
- const prefixNodes = this.getOptionPrefixNodes(option);
1917
+ const prefixNodes = this.getOptionPrefixNodes(option, 'chip');
1765
1918
  return html`
1766
1919
  <nile-lite-tooltip
1767
1920
  class="select__tag-tip"
@@ -1816,6 +1969,69 @@ export class NileSelect extends NileElement implements NileFormControl{
1816
1969
  `;
1817
1970
  }
1818
1971
 
1972
+ private renderLegacyTags() {
1973
+ return html`
1974
+ <div part="tags" class="select__tags">
1975
+ ${this.selectedOptions.map((option, index) => {
1976
+ if (index < this.maxOptionsVisible || this.maxOptionsVisible <= 0) {
1977
+ return this.showTooltip
1978
+ ? html`<nile-lite-tooltip
1979
+ class="select__tag-tip"
1980
+ .content=${option.getTextLabel()}
1981
+ ?disabled=${this.chipTooltipDisabled(index)}
1982
+ >${this.renderLegacyTag(option, index)}</nile-lite-tooltip
1983
+ >`
1984
+ : this.renderLegacyTag(option, index);
1985
+ } else if (index === this.maxOptionsVisible) {
1986
+ return html`
1987
+ <span class="select__tags-count"
1988
+ >+${this.selectedOptions.length - index} More
1989
+ </span>
1990
+ `;
1991
+ } else {
1992
+ return null;
1993
+ }
1994
+ })}
1995
+ </div>
1996
+ `;
1997
+ }
1998
+
1999
+ private renderLegacyTag(option: NileOption, index: number) {
2000
+ const prefixNodes = this.getOptionPrefixNodes(option, 'chip');
2001
+ const classes = {
2002
+ select__invisible:
2003
+ index + 1 > this.oldMaxOptionsVisible &&
2004
+ this.maxOptionsVisible === Infinity,
2005
+ };
2006
+ return html`
2007
+ <nile-tag
2008
+ class=${classMap(classes)}
2009
+ part="tag"
2010
+ exportparts="
2011
+ base:tag__base,
2012
+ content:tag__content,
2013
+ remove-button:tag__remove-button,
2014
+ remove-button__base:tag__remove-button__base,
2015
+ prefix:tag__prefix,
2016
+ prefix_content_wrapper:tag__prefix_content_wrapper
2017
+ "
2018
+ style=${ifDefined(
2019
+ this.showTooltip ? `max-width:${this.chipMaxWidth}px` : undefined
2020
+ )}
2021
+ ?pill=${this.pill}
2022
+ size=${this.size}
2023
+ removable
2024
+ @nile-remove=${(event: NileRemoveEvent) =>
2025
+ this.handleTagRemove(event, option)}
2026
+ >
2027
+ ${prefixNodes.length
2028
+ ? html`<span class="tag__prefix" slot="prefix">${prefixNodes}</span>`
2029
+ : ''}
2030
+ ${option.getTextLabel()}
2031
+ </nile-tag>
2032
+ `;
2033
+ }
2034
+
1819
2035
  handleInputAfterInit() {
1820
2036
  this.shadowRoot?.querySelector('nile-input')?.inputFocus();
1821
2037
  }
@@ -1836,7 +2052,7 @@ export class NileSelect extends NileElement implements NileFormControl{
1836
2052
  const hasHelpText = (this.helpText || this.help_text) ? true : false;
1837
2053
  const hasErrorMessage = this.errorMessage ? true : false;
1838
2054
  const prefixNodes = this.selectedOptions[0]
1839
- ? this.getOptionPrefixNodes(this.selectedOptions[0])
2055
+ ? this.getOptionPrefixNodes(this.selectedOptions[0], 'trigger')
1840
2056
  : [];
1841
2057
 
1842
2058
  return html`
@@ -1951,59 +2167,7 @@ export class NileSelect extends NileElement implements NileFormControl{
1951
2167
  ${this.multiple
1952
2168
  ? this.chipFittingEnabled
1953
2169
  ? this.renderFittedTags()
1954
- : html`
1955
- <div part="tags" class="select__tags">
1956
- ${this.selectedOptions.map((option, index) => {
1957
- if (
1958
- index < this.maxOptionsVisible ||
1959
- this.maxOptionsVisible <= 0
1960
- ) {
1961
- const prefixNodes =
1962
- this.getOptionPrefixNodes(option);
1963
- return html`
1964
- <nile-lite-tooltip
1965
- class="select__tag-tip"
1966
- .content=${option.getTextLabel()}
1967
- ?disabled=${this.chipTooltipDisabled(index)}
1968
- >
1969
- <nile-tag
1970
- part="tag"
1971
- exportparts="
1972
- base:tag__base,
1973
- content:tag__content,
1974
- remove-button:tag__remove-button,
1975
- remove-button__base:tag__remove-button__base,
1976
- prefix:tag__prefix,
1977
- prefix_content_wrapper:tag__prefix_content_wrapper
1978
- "
1979
- style="max-width:${this.chipMaxWidth}px"
1980
- ?pill=${this.pill}
1981
- size=${this.size}
1982
- removable
1983
- @nile-remove=${(event: NileRemoveEvent) =>
1984
- this.handleTagRemove(event, option)}
1985
- >
1986
- ${prefixNodes.length
1987
- ? html`<span class="tag__prefix" slot="prefix"
1988
- >${prefixNodes}</span
1989
- >`
1990
- : ''}
1991
- ${option.getTextLabel()}
1992
- </nile-tag>
1993
- </nile-lite-tooltip>
1994
- `;
1995
- } else if (index === this.maxOptionsVisible) {
1996
- return html`
1997
- <span class="select__tags-count"
1998
- >+${this.selectedOptions.length - index} More
1999
- </span>
2000
- `;
2001
- } else {
2002
- return null;
2003
- }
2004
- })}
2005
- </div>
2006
- `
2170
+ : this.renderLegacyTags()
2007
2171
  : ''}
2008
2172
 
2009
2173
  <input
@@ -2115,7 +2279,13 @@ export class NileSelect extends NileElement implements NileFormControl{
2115
2279
  </div>
2116
2280
 
2117
2281
  ${this.hasSlotController.test('pre-footer') || this.multiple
2118
- ? html`<div part="footer-area" class="select__pre-footer-area">
2282
+ ? html`<div
2283
+ part="footer-area"
2284
+ class=${classMap({
2285
+ 'select__pre-footer-area': true,
2286
+ 'select__pre-footer-area--query': !this.noWidthSync || this.portal,
2287
+ })}
2288
+ >
2119
2289
  ${this.hasSlotController.test('pre-footer')
2120
2290
  ? html`
2121
2291
  <div part="pre-footer" @click=${this.handlePreFooterClick}>
@@ -60,6 +60,8 @@ export class VirtualScrollHelper {
60
60
  .enableDescription=${component.enableDescription}
61
61
  .tickOnSelect=${component.tickOnSelect}
62
62
  .legacy=${component.legacy}
63
+ @nile-input=${(e: CustomEvent) => component.syncValueFromVirtualSelect(e)}
64
+ @nile-change=${(e: CustomEvent) => component.syncValueFromVirtualSelect(e)}
63
65
  exportparts="
64
66
  select-options,
65
67
  select-no-results,
@@ -246,35 +246,23 @@ export const styles = css`
246
246
  display: contents;
247
247
  }
248
248
 
249
- .select__tags nile-tag {
249
+ :host([showtooltip]) .select__tags nile-tag {
250
250
  flex: 0 1 auto;
251
251
  cursor: pointer;
252
252
  min-width: 0;
253
- }
254
-
255
- /* A chip is capped - and so truncated - only when a tooltip can reveal the
256
- full value. Without one it keeps its natural width and the fit pass moves
257
- the surplus into the +N button instead. */
258
- :host([showtooltip]) .select__tags nile-tag {
259
253
  max-width: var(--nile-width-180px, var(--ng-height-180px));
260
254
  }
261
255
 
262
- /* Only the fitted layout can move a chip into the +N button, so only there
263
- can a chip refuse to shrink. */
264
- :host(:not([showtooltip])) .select__tags--fitted nile-tag {
265
- flex-shrink: 0;
266
- }
267
-
268
- .select__tags nile-tag::part(base) {
256
+ :host([showtooltip]) .select__tags nile-tag::part(base) {
269
257
  max-width: 100%;
270
258
  }
271
259
 
272
- .select__tags nile-tag::part(prefix_content_wrapper) {
260
+ :host([showtooltip]) .select__tags nile-tag::part(prefix_content_wrapper) {
273
261
  flex: 1 1 auto;
274
262
  min-width: 0;
275
263
  }
276
264
 
277
- .select__tags nile-tag::part(content) {
265
+ :host([showtooltip]) .select__tags nile-tag::part(content) {
278
266
  display: block;
279
267
  flex: 1 1 auto;
280
268
  min-width: 0;
@@ -290,7 +278,7 @@ export const styles = css`
290
278
  text-overflow: ellipsis;
291
279
  }
292
280
 
293
- .select__tags nile-tag::part(remove-button) {
281
+ :host([showtooltip]) .select__tags nile-tag::part(remove-button) {
294
282
  flex: 0 0 auto;
295
283
  }
296
284
 
@@ -310,7 +298,7 @@ export const styles = css`
310
298
  white-space: nowrap;
311
299
  cursor: pointer;
312
300
  border: 1px dashed
313
- var(--nile-colors-neutral-500, var(--ng-colors-border-secondary));
301
+ var(--nile-colors-neutral-500, var(--ng-colors-border-primary));
314
302
  border-radius: var(--nile-radius-sm, var(--ng-radius-sm));
315
303
  }
316
304
 
@@ -361,7 +349,7 @@ export const styles = css`
361
349
 
362
350
  .select--standard:not(.select--disabled).select--open .select__combobox,
363
351
  .select--standard:not(.select--disabled).select--focused .select__combobox {
364
- background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary));
352
+ background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-primary));
365
353
  }
366
354
 
367
355
  .select--warning .select__combobox {
@@ -380,12 +368,12 @@ export const styles = css`
380
368
  /* Filled selects */
381
369
  .select--filled .select__combobox {
382
370
  border: none;
383
- background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary));
371
+ background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-primary));
384
372
  color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));
385
373
  }
386
374
 
387
375
  .select--filled:hover:not(.select--disabled) .select__combobox {
388
- background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary));
376
+ background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-primary-hover));
389
377
  }
390
378
 
391
379
  .select--filled.select--disabled .select__combobox {
@@ -396,7 +384,7 @@ export const styles = css`
396
384
 
397
385
  .select--filled:not(.select--disabled).select--open .select__combobox,
398
386
  .select--filled:not(.select--disabled).select--focused .select__combobox {
399
- background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary));
387
+ background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-primary));
400
388
  outline: 3px solid rgba(0, 89, 255, 0.4);
401
389
  }
402
390
 
@@ -493,7 +481,7 @@ export const styles = css`
493
481
  font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));
494
482
  font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular));
495
483
  background: var(--nile-colors-white-base, var(--ng-colors-bg-primary));
496
- border: solid 1px var(--nile-colors-neutral-500, var(--ng-colors-border-secondary-alt));
484
+ border: solid 1px var(--nile-colors-neutral-500, var(--ng-colors-border-primary));
497
485
  border-radius: var(--nile-radius-sm, var(--ng-radius-md));
498
486
  padding-block: var(--nile-spacing-none, var(--ng-spacing-xs));
499
487
  padding-inline: var(--nile-spacing-none, var(--ng-spacing-xs));
@@ -541,7 +529,7 @@ export const styles = css`
541
529
  position: sticky;
542
530
  bottom: 0px;
543
531
  background: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary));
544
- border-top: 1px solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
532
+ border-top: 1px solid var(--nile-colors-neutral-400, var(--ng-colors-border-primary));
545
533
  display: flex;
546
534
  height: 15px;
547
535
  /* Auto layout */
@@ -552,6 +540,9 @@ export const styles = css`
552
540
  gap: var(--nile-spacing-none, var(--ng-spacing-none));
553
541
  justify-content: space-between;
554
542
  box-sizing: unset;
543
+ }
544
+
545
+ .select__footer--query {
555
546
  container-type: inline-size;
556
547
  container-name: nile-select-footer;
557
548
  }
@@ -620,6 +611,10 @@ export const styles = css`
620
611
  }
621
612
  }
622
613
 
614
+ .select__invisible {
615
+ opacity: 0;
616
+ }
617
+
623
618
  .select__prefix--from-options {
624
619
  margin-inline-end: var(--nile-spacing-lg, var(--ng-spacing-md));
625
620
  }
@@ -629,7 +624,7 @@ export const styles = css`
629
624
  }
630
625
 
631
626
  .virtualized nile-option[selected] {
632
- background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary));
627
+ background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-active));
633
628
  }
634
629
 
635
630
  .virtualized nile-option[selected]::part(base) {