@nonoun/native-ui 0.2.7 → 0.2.9

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 (153) hide show
  1. package/dist/components/ui-accordion/ui-accordion-element.d.ts.map +1 -1
  2. package/dist/components/ui-avatar/ui-avatar-element.d.ts +2 -0
  3. package/dist/components/ui-avatar/ui-avatar-element.d.ts.map +1 -1
  4. package/dist/components/ui-calendar/calendar-store.d.ts.map +1 -1
  5. package/dist/components/ui-calendar/ui-calendar-element.d.ts +1 -0
  6. package/dist/components/ui-calendar/ui-calendar-element.d.ts.map +1 -1
  7. package/dist/components/ui-chat/ui-chat-input-element.d.ts.map +1 -1
  8. package/dist/components/ui-checkbox/ui-checkbox-element.d.ts +1 -0
  9. package/dist/components/ui-checkbox/ui-checkbox-element.d.ts.map +1 -1
  10. package/dist/components/ui-combobox/ui-combobox-element.d.ts +1 -0
  11. package/dist/components/ui-combobox/ui-combobox-element.d.ts.map +1 -1
  12. package/dist/components/ui-command/ui-command-element.d.ts.map +1 -1
  13. package/dist/components/ui-command/ui-command-group-element.d.ts +1 -0
  14. package/dist/components/ui-command/ui-command-group-element.d.ts.map +1 -1
  15. package/dist/components/ui-controller/ui-controller-element.d.ts +1 -0
  16. package/dist/components/ui-controller/ui-controller-element.d.ts.map +1 -1
  17. package/dist/components/ui-dialog/ui-dialog-element.d.ts +0 -1
  18. package/dist/components/ui-dialog/ui-dialog-element.d.ts.map +1 -1
  19. package/dist/components/ui-drawer/ui-drawer-element.d.ts +0 -1
  20. package/dist/components/ui-drawer/ui-drawer-element.d.ts.map +1 -1
  21. package/dist/components/ui-field/ui-field-element.d.ts.map +1 -1
  22. package/dist/components/ui-input/ui-input-element.d.ts +1 -0
  23. package/dist/components/ui-input/ui-input-element.d.ts.map +1 -1
  24. package/dist/components/ui-input-otp/ui-input-otp-element.d.ts +1 -0
  25. package/dist/components/ui-input-otp/ui-input-otp-element.d.ts.map +1 -1
  26. package/dist/components/ui-listbox/ui-listbox-element.d.ts.map +1 -1
  27. package/dist/components/ui-nav/ui-nav-group-element.d.ts +1 -1
  28. package/dist/components/ui-pagination/ui-pagination-element.d.ts.map +1 -1
  29. package/dist/components/ui-radio/ui-radio-element.d.ts.map +1 -1
  30. package/dist/components/ui-radio/ui-radio-group-element.d.ts +1 -0
  31. package/dist/components/ui-radio/ui-radio-group-element.d.ts.map +1 -1
  32. package/dist/components/ui-range/ui-range-element.d.ts +4 -0
  33. package/dist/components/ui-range/ui-range-element.d.ts.map +1 -1
  34. package/dist/components/ui-segmented-control/ui-segment-element.d.ts.map +1 -1
  35. package/dist/components/ui-segmented-control/ui-segmented-control-element.d.ts +1 -0
  36. package/dist/components/ui-segmented-control/ui-segmented-control-element.d.ts.map +1 -1
  37. package/dist/components/ui-select/ui-select-element.d.ts +1 -0
  38. package/dist/components/ui-select/ui-select-element.d.ts.map +1 -1
  39. package/dist/components/ui-slideshow/ui-slideshow-element.d.ts.map +1 -1
  40. package/dist/components/ui-switch/ui-switch-element.d.ts +4 -0
  41. package/dist/components/ui-switch/ui-switch-element.d.ts.map +1 -1
  42. package/dist/components/ui-table/index.d.ts +1 -1
  43. package/dist/components/ui-table/index.d.ts.map +1 -1
  44. package/dist/components/ui-table/table-store.d.ts +0 -1
  45. package/dist/components/ui-table/table-store.d.ts.map +1 -1
  46. package/dist/components/ui-table/ui-table-element.d.ts +1 -0
  47. package/dist/components/ui-table/ui-table-element.d.ts.map +1 -1
  48. package/dist/components/ui-table/ui-table-header-element.d.ts +1 -0
  49. package/dist/components/ui-table/ui-table-header-element.d.ts.map +1 -1
  50. package/dist/components/ui-tabs/ui-tab-element.d.ts.map +1 -1
  51. package/dist/components/ui-tabs/ui-tabs-element.d.ts.map +1 -1
  52. package/dist/components/ui-textarea/ui-textarea-element.d.ts +1 -0
  53. package/dist/components/ui-textarea/ui-textarea-element.d.ts.map +1 -1
  54. package/dist/components/ui-tree/ui-tree-item-element.d.ts +4 -0
  55. package/dist/components/ui-tree/ui-tree-item-element.d.ts.map +1 -1
  56. package/dist/components-lean.css +208 -84
  57. package/dist/components.css +216 -84
  58. package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-element.d.ts.map +1 -1
  59. package/dist/core/form-associable.d.ts +2 -2
  60. package/dist/core/trait-runtime.d.ts.map +1 -1
  61. package/dist/core/ui-element.d.ts +2 -0
  62. package/dist/core/ui-element.d.ts.map +1 -1
  63. package/dist/custom-elements.json +4715 -2573
  64. package/dist/dialog-controller.js +54 -349
  65. package/dist/foundation.css +1 -15
  66. package/dist/icons/ui-icon-element.d.ts +1 -0
  67. package/dist/icons/ui-icon-element.d.ts.map +1 -1
  68. package/dist/index.d.ts +1 -1
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/{nav/inspector → inspector}/build-inspector.d.ts +2 -2
  71. package/dist/inspector/build-inspector.d.ts.map +1 -0
  72. package/dist/{nav/inspector → inspector}/ds-color-swatch-element.d.ts +1 -1
  73. package/dist/inspector/ds-color-swatch-element.d.ts.map +1 -0
  74. package/dist/inspector/ds-color-swatch.d.ts.map +1 -0
  75. package/dist/{nav/inspector → inspector}/ds-colors-element.d.ts +1 -1
  76. package/dist/inspector/ds-colors-element.d.ts.map +1 -0
  77. package/dist/inspector/ds-colors.d.ts.map +1 -0
  78. package/dist/inspector/ds-inspector-element.d.ts +15 -0
  79. package/dist/inspector/ds-inspector-element.d.ts.map +1 -0
  80. package/dist/inspector/ds-inspector.d.ts +3 -0
  81. package/dist/inspector/ds-inspector.d.ts.map +1 -0
  82. package/dist/{nav/inspector → inspector}/ds-themes-element.d.ts +1 -1
  83. package/dist/inspector/ds-themes-element.d.ts.map +1 -0
  84. package/dist/inspector/ds-themes.d.ts.map +1 -0
  85. package/dist/{nav/inspector → inspector}/ds-variable-element.d.ts +1 -1
  86. package/dist/inspector/ds-variable-element.d.ts.map +1 -0
  87. package/dist/inspector/ds-variable.d.ts.map +1 -0
  88. package/dist/{nav/inspector → inspector}/index.d.ts +1 -0
  89. package/dist/inspector/index.d.ts.map +1 -0
  90. package/dist/inspector.css +1 -1
  91. package/dist/inspector.d.ts +10 -6
  92. package/dist/inspector.d.ts.map +1 -1
  93. package/dist/inspector.js +94 -75
  94. package/dist/kernel/index.d.ts +1 -0
  95. package/dist/kernel/index.d.ts.map +1 -1
  96. package/dist/kernel/overlay-manager.d.ts +5 -1
  97. package/dist/kernel/overlay-manager.d.ts.map +1 -1
  98. package/dist/kernel.js +212 -194
  99. package/dist/list-navigate-controller.js +457 -0
  100. package/dist/native-ui-lean.css +209 -99
  101. package/dist/native-ui.css +217 -99
  102. package/dist/native-ui.js +7 -7
  103. package/dist/register-all.js +4 -3
  104. package/dist/register-all2.js +151 -79
  105. package/dist/traits/adapters/collapsible-adapter.d.ts.map +1 -1
  106. package/dist/traits/adapters/copyable-adapter.d.ts.map +1 -1
  107. package/dist/traits/adapters/draggable-adapter.d.ts.map +1 -1
  108. package/dist/traits/adapters/hoverable-adapter.d.ts.map +1 -1
  109. package/dist/traits/adapters/intersectable-adapter.d.ts.map +1 -1
  110. package/dist/traits/adapters/resizable-adapter.d.ts.map +1 -1
  111. package/dist/traits/adapters/searchable-adapter.d.ts.map +1 -1
  112. package/dist/traits/adapters/sortable-adapter.d.ts.map +1 -1
  113. package/dist/traits/adapters/swipeable-adapter.d.ts.map +1 -1
  114. package/dist/traits/adapters/virtualizable-adapter.d.ts.map +1 -1
  115. package/dist/traits/collapsible-controller.d.ts.map +1 -1
  116. package/dist/traits/dialog-controller.d.ts.map +1 -1
  117. package/dist/traits/drag-controller.d.ts +3 -0
  118. package/dist/traits/drag-controller.d.ts.map +1 -1
  119. package/dist/traits/drop-zone-controller.d.ts +1 -1
  120. package/dist/traits/drop-zone-controller.d.ts.map +1 -1
  121. package/dist/traits/focus-trap-controller.d.ts.map +1 -1
  122. package/dist/traits/hover-controller.d.ts +1 -1
  123. package/dist/traits/hover-controller.d.ts.map +1 -1
  124. package/dist/traits/intersect-controller.d.ts.map +1 -1
  125. package/dist/traits/popover-controller.d.ts.map +1 -1
  126. package/dist/traits/press-controller.d.ts.map +1 -1
  127. package/dist/traits/resize-controller.d.ts.map +1 -1
  128. package/dist/traits/selection-controller.d.ts.map +1 -1
  129. package/dist/traits/sort-controller.d.ts.map +1 -1
  130. package/dist/traits/swipe-controller.d.ts.map +1 -1
  131. package/dist/traits/validate-controller.d.ts +2 -0
  132. package/dist/traits/validate-controller.d.ts.map +1 -1
  133. package/dist/traits.js +5 -6
  134. package/dist/ui-icon-element.js +407 -3949
  135. package/dist/ui-layout-inspector-element.js +3777 -0
  136. package/dist/uid.js +63 -3
  137. package/package.json +1 -1
  138. package/dist/define.js +0 -62
  139. package/dist/nav/inspector/build-inspector.d.ts.map +0 -1
  140. package/dist/nav/inspector/ds-color-swatch-element.d.ts.map +0 -1
  141. package/dist/nav/inspector/ds-color-swatch.d.ts.map +0 -1
  142. package/dist/nav/inspector/ds-colors-element.d.ts.map +0 -1
  143. package/dist/nav/inspector/ds-colors.d.ts.map +0 -1
  144. package/dist/nav/inspector/ds-themes-element.d.ts.map +0 -1
  145. package/dist/nav/inspector/ds-themes.d.ts.map +0 -1
  146. package/dist/nav/inspector/ds-variable-element.d.ts.map +0 -1
  147. package/dist/nav/inspector/ds-variable.d.ts.map +0 -1
  148. package/dist/nav/inspector/index.d.ts.map +0 -1
  149. package/dist/ui-element.js +0 -128
  150. /package/dist/{nav/inspector → inspector}/ds-color-swatch.d.ts +0 -0
  151. /package/dist/{nav/inspector → inspector}/ds-colors.d.ts +0 -0
  152. /package/dist/{nav/inspector → inspector}/ds-themes.d.ts +0 -0
  153. /package/dist/{nav/inspector → inspector}/ds-variable.d.ts +0 -0
@@ -1,3 +1,54 @@
1
+ @layer ui {
2
+
3
+ /* ── Icon Base ── */
4
+
5
+ :where(ui-icon) {
6
+ --ui-icon-size: var(--_icon-size);
7
+ --ui-icon-color: currentColor;
8
+
9
+ box-sizing: border-box;
10
+ display: inline-flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ width: var(--ui-icon-size);
14
+ height: var(--ui-icon-size);
15
+ color: var(--ui-icon-color);
16
+ flex-shrink: 0;
17
+ vertical-align: middle;
18
+ line-height: 0;
19
+ }
20
+
21
+ :where(ui-icon) > :where(svg) {
22
+ width: 100%;
23
+ height: 100%;
24
+ }
25
+
26
+ /* WHY: Unregistered icons (no SVG content) should collapse to zero size
27
+ so surrounding buttons/slots don't render with phantom dimensions */
28
+ :where(ui-icon:empty) {
29
+ width: 0;
30
+ height: 0;
31
+ overflow: hidden;
32
+ }
33
+
34
+ /* ── Icon Size Variants ── */
35
+
36
+ :where(ui-icon[size="xs"]) { --ui-icon-size: var(--ui-icon-xs); }
37
+ :where(ui-icon[size="sm"]) { --ui-icon-size: var(--ui-icon-sm); }
38
+ :where(ui-icon[size="md"]) { --ui-icon-size: var(--ui-icon-md); }
39
+ :where(ui-icon[size="lg"]) { --ui-icon-size: var(--ui-icon-lg); }
40
+ :where(ui-icon[size="xl"]) { --ui-icon-size: var(--ui-icon-xl); }
41
+
42
+ /* ── Forced Colors ── */
43
+
44
+ @media (forced-colors: active) {
45
+ :where(ui-icon) {
46
+ --ui-icon-color: ButtonText;
47
+ }
48
+ }
49
+
50
+ }
51
+
1
52
  @layer ui {
2
53
 
3
54
  /* ── Accordion Container ── */
@@ -474,7 +525,8 @@
474
525
  display: inline-flex;
475
526
  flex-direction: column;
476
527
  gap: calc(var(--_space));
477
- padding: calc(var(--_space) * 2);
528
+ padding-block: calc(var(--_space) * 2);
529
+ padding-inline: calc(var(--_space) * 2);
478
530
  border: 1px solid var(--_border-color);
479
531
  border-radius: var(--_radius);
480
532
  background: var(--_background);
@@ -686,11 +738,17 @@
686
738
  }
687
739
 
688
740
  :where(ui-calendar) :where([data-range-start]) {
689
- border-radius: calc(var(--_radius) - var(--_space)) 0 0 calc(var(--_radius) - var(--_space));
741
+ border-start-start-radius: calc(var(--_radius) - var(--_space));
742
+ border-end-start-radius: calc(var(--_radius) - var(--_space));
743
+ border-start-end-radius: 0;
744
+ border-end-end-radius: 0;
690
745
  }
691
746
 
692
747
  :where(ui-calendar) :where([data-range-end]) {
693
- border-radius: 0 calc(var(--_radius) - var(--_space)) calc(var(--_radius) - var(--_space)) 0;
748
+ border-start-start-radius: 0;
749
+ border-end-start-radius: 0;
750
+ border-start-end-radius: calc(var(--_radius) - var(--_space));
751
+ border-end-end-radius: calc(var(--_radius) - var(--_space));
694
752
  }
695
753
 
696
754
  :where(ui-calendar) :where([data-range-start][data-range-end]) {
@@ -1030,13 +1088,16 @@
1030
1088
 
1031
1089
  /* ── Active (pressed) ── */
1032
1090
 
1033
- :where(ui-checkbox)[pressed]::before {
1091
+ :where(ui-checkbox)[pressed]::before,
1092
+ :where(ui-checkbox)[force-active]::before {
1034
1093
  background: var(--_background-active, var(--_widget-active));
1035
1094
  border-color: var(--_border-color-active, var(--_border-active));
1036
1095
  }
1037
1096
 
1038
1097
  :where(ui-checkbox)[aria-checked="true"][pressed]::before,
1039
- :where(ui-checkbox)[aria-checked="mixed"][pressed]::before {
1098
+ :where(ui-checkbox)[aria-checked="mixed"][pressed]::before,
1099
+ :where(ui-checkbox)[aria-checked="true"][force-active]::before,
1100
+ :where(ui-checkbox)[aria-checked="mixed"][force-active]::before {
1040
1101
  background: var(--_surface-active);
1041
1102
  border-color: var(--_surface-active);
1042
1103
  }
@@ -1093,6 +1154,23 @@
1093
1154
  cursor: text;
1094
1155
  }
1095
1156
 
1157
+ /* ── Popover Listbox Positioning ──
1158
+ WHY: Must come after ui-listbox.css base rule (which sets min-width: 0
1159
+ for flex-child shrinking) so min-width: anchor-size(inline) wins by
1160
+ source order — both are zero-specificity via :where(). */
1161
+
1162
+ :where(ui-combobox) > :where(ui-listbox[popover]) {
1163
+ position: fixed;
1164
+ position-area: block-end span-inline-end;
1165
+ position-try-fallbacks: flip-block;
1166
+ margin-block: var(--ui-popover-viewport-margin);
1167
+ margin-inline: 0;
1168
+ margin-block-start: var(--ui-popover-gap);
1169
+ min-width: anchor-size(inline);
1170
+ max-height: var(--ui-popover-max-height);
1171
+ overflow-y: auto;
1172
+ }
1173
+
1096
1174
  }
1097
1175
 
1098
1176
  @layer ui {
@@ -1145,7 +1223,8 @@
1145
1223
  :where(ui-command-list) {
1146
1224
  overflow-y: auto;
1147
1225
  max-height: var(--ui-popover-max-height);
1148
- padding: var(--_space);
1226
+ padding-block: var(--_space);
1227
+ padding-inline: var(--_space);
1149
1228
  }
1150
1229
 
1151
1230
  /* ── Command Group ── */
@@ -1237,7 +1316,8 @@
1237
1316
  }
1238
1317
 
1239
1318
  :where(ui-dialog) > :where(dialog)::backdrop {
1240
- background: var(--ui-backdrop-color) / var(--ui-backdrop-opacity);
1319
+ background: var(--ui-backdrop-color);
1320
+ opacity: var(--ui-backdrop-opacity);
1241
1321
  }
1242
1322
 
1243
1323
  }
@@ -1277,7 +1357,8 @@
1277
1357
  /* WHY: Animate backdrop opacity on open for a smooth reveal. */
1278
1358
 
1279
1359
  :where(ui-drawer) > :where(dialog)::backdrop {
1280
- background: var(--ui-backdrop-color) / var(--ui-backdrop-opacity);
1360
+ background: var(--ui-backdrop-color);
1361
+ opacity: var(--ui-backdrop-opacity);
1281
1362
  animation: drawer-backdrop-in var(--_duration) ease-out;
1282
1363
  }
1283
1364
 
@@ -1739,7 +1820,8 @@
1739
1820
  min-width: 0;
1740
1821
  flex-direction: column;
1741
1822
  gap: 0;
1742
- padding: var(--_space);
1823
+ padding-block: var(--_space);
1824
+ padding-inline: var(--_space);
1743
1825
  border-radius: var(--_radius);
1744
1826
  border: 1px solid var(--_border-color, var(--_border-rest));
1745
1827
  background: var(--_background, var(--_control));
@@ -1755,6 +1837,39 @@
1755
1837
  display: none;
1756
1838
  }
1757
1839
 
1840
+ /* ── Popover Animation ──
1841
+ WHY: Shared entry/exit transition for all popover listboxes.
1842
+ Context CSS overrides --_popover-origin and --_popover-from
1843
+ to match the popover's anchor direction (e.g. sidebar flyouts
1844
+ open to the right → rotateY instead of rotateX). */
1845
+
1846
+ :where(ui-listbox[popover]) {
1847
+ --_popover-origin: top center;
1848
+ --_popover-from: perspective(800px) scale(0.96) rotateX(-20deg);
1849
+
1850
+ transform-origin: var(--_popover-origin);
1851
+ opacity: 0;
1852
+ transform: var(--_popover-from);
1853
+
1854
+ transition:
1855
+ opacity var(--_duration) var(--_easing),
1856
+ transform var(--_duration) var(--_easing),
1857
+ display var(--_duration) var(--_easing) allow-discrete,
1858
+ overlay var(--_duration) var(--_easing) allow-discrete;
1859
+ }
1860
+
1861
+ :where(ui-listbox[popover]):popover-open {
1862
+ opacity: 1;
1863
+ transform: none;
1864
+ }
1865
+
1866
+ @starting-style {
1867
+ :where(ui-listbox[popover]):popover-open {
1868
+ opacity: 0;
1869
+ transform: var(--_popover-from);
1870
+ }
1871
+ }
1872
+
1758
1873
  /* ── Option / Command Item Base ── */
1759
1874
 
1760
1875
  :where(ui-option, ui-command-item, [role="option"]) {
@@ -1919,10 +2034,6 @@
1919
2034
  color: var(--_ink-hover);
1920
2035
  }
1921
2036
 
1922
- :where(ui-nav-item)[active] {
1923
- color: var(--_ink-hover);
1924
- }
1925
-
1926
2037
  :where(ui-nav-item):active,
1927
2038
  :where(ui-nav-item)[force-active] {
1928
2039
  color: var(--_ink-active);
@@ -2147,10 +2258,15 @@
2147
2258
  instead of expanding the <details>. Same pattern as sidebar-trigger menus. */
2148
2259
 
2149
2260
  :where(ui-nav-group) > :where(ui-listbox.nav-group-flyout[popover]) {
2261
+ --_popover-origin: left center;
2262
+ --_popover-from: perspective(800px) scale(0.96) rotateY(20deg);
2263
+
2150
2264
  position: fixed;
2151
2265
  position-area: inline-end span-block-end;
2152
2266
  position-try-fallbacks: --nav-flyout-flip-up;
2153
- margin: 0 0 0 var(--ui-popover-gap);
2267
+ margin-block: var(--ui-popover-viewport-margin);
2268
+ margin-inline: 0;
2269
+ margin-inline-start: var(--ui-popover-gap);
2154
2270
  min-width: 200px;
2155
2271
  max-height: var(--ui-popover-max-height);
2156
2272
  overflow-y: auto;
@@ -2160,6 +2276,10 @@
2160
2276
  position-area: inline-end span-block-start;
2161
2277
  }
2162
2278
 
2279
+ @position-try --nav-flyout-flip-down {
2280
+ position-area: inline-end span-block-end;
2281
+ }
2282
+
2163
2283
  /* ── Container Query: Collapsed Sidebar ── */
2164
2284
  /* WHY: Nav components own their own collapsed behavior via @container.
2165
2285
  The sidebar aside declares container-name: sidebar. When it shrinks
@@ -2203,6 +2323,14 @@
2203
2323
  font-size: var(--_font-size, 1rem);
2204
2324
  }
2205
2325
 
2326
+ /* WHY: In collapsed mode the group is a small icon — centering
2327
+ the flyout vertically with the anchor is more natural than top-aligning.
2328
+ Fallbacks handle viewport clipping (top/bottom edge). */
2329
+ :where(ui-nav-group) > :where(ui-listbox.nav-group-flyout[popover]) {
2330
+ position-area: inline-end;
2331
+ position-try-fallbacks: --nav-flyout-flip-up, --nav-flyout-flip-down;
2332
+ }
2333
+
2206
2334
  /* Collapse inter-group spacing in icon rail. */
2207
2335
  :where(ui-nav-group) + :where(ui-nav-group) {
2208
2336
  margin-block-start: 0;
@@ -2381,12 +2509,14 @@
2381
2509
 
2382
2510
  /* ── Active (pressed) ── */
2383
2511
 
2384
- :where(ui-radio)[pressed]::before {
2512
+ :where(ui-radio)[pressed]::before,
2513
+ :where(ui-radio)[force-active]::before {
2385
2514
  background: var(--_background-active, var(--_widget-active));
2386
2515
  border-color: var(--_border-color-active, var(--_border-active));
2387
2516
  }
2388
2517
 
2389
- :where(ui-radio)[aria-checked="true"][pressed]::before {
2518
+ :where(ui-radio)[aria-checked="true"][pressed]::before,
2519
+ :where(ui-radio)[aria-checked="true"][force-active]::before {
2390
2520
  background: var(--_surface-active);
2391
2521
  border-color: var(--_surface-active);
2392
2522
  }
@@ -2440,6 +2570,8 @@
2440
2570
  min-width: 0;
2441
2571
  align-items: center;
2442
2572
  position: relative;
2573
+ /* WHY: Isolate internal z-index (thumb z-index: 1) from parent stacking context */
2574
+ isolation: isolate;
2443
2575
 
2444
2576
  min-height: var(--_track-height);
2445
2577
 
@@ -2536,11 +2668,13 @@
2536
2668
 
2537
2669
  /* ── Active (dragging) ── */
2538
2670
 
2539
- :where(ui-range)[pressed]::after {
2671
+ :where(ui-range)[pressed]::after,
2672
+ :where(ui-range)[force-active]::after {
2540
2673
  background: var(--_surface-active);
2541
2674
  }
2542
2675
 
2543
- :where(ui-range)[pressed] > :where(.ui-range-thumb) {
2676
+ :where(ui-range)[pressed] > :where(.ui-range-thumb),
2677
+ :where(ui-range)[force-active] > :where(.ui-range-thumb) {
2544
2678
  border-color: var(--_surface-active);
2545
2679
  box-shadow: var(--ui-shadow-sm), 0 0 0 6px var(--_surface);
2546
2680
  }
@@ -2728,6 +2862,23 @@
2728
2862
  display: contents;
2729
2863
  }
2730
2864
 
2865
+ /* ── Popover Listbox Positioning ──
2866
+ WHY: Must come after ui-listbox.css base rule (which sets min-width: 0
2867
+ for flex-child shrinking) so min-width: anchor-size(inline) wins by
2868
+ source order — both are zero-specificity via :where(). */
2869
+
2870
+ :where(ui-select) > :where(ui-listbox[popover]) {
2871
+ position: fixed;
2872
+ position-area: block-end span-inline-end;
2873
+ position-try-fallbacks: flip-block;
2874
+ margin-block: var(--ui-popover-viewport-margin);
2875
+ margin-inline: 0;
2876
+ margin-block-start: var(--ui-popover-gap);
2877
+ min-width: anchor-size(inline);
2878
+ max-height: var(--ui-popover-max-height);
2879
+ overflow-y: auto;
2880
+ }
2881
+
2731
2882
  }
2732
2883
 
2733
2884
  @layer ui {
@@ -3126,12 +3277,14 @@
3126
3277
 
3127
3278
  /* ── Active (pressed) ── */
3128
3279
 
3129
- :where(ui-switch)[pressed]::before {
3280
+ :where(ui-switch)[pressed]::before,
3281
+ :where(ui-switch)[force-active]::before {
3130
3282
  background: var(--_track-bg-active);
3131
3283
  border-color: var(--_track-border-active);
3132
3284
  }
3133
3285
 
3134
- :where(ui-switch)[aria-checked="true"][pressed]::before {
3286
+ :where(ui-switch)[aria-checked="true"][pressed]::before,
3287
+ :where(ui-switch)[aria-checked="true"][force-active]::before {
3135
3288
  background: var(--_surface-active);
3136
3289
  border-color: var(--_surface-active);
3137
3290
  }
@@ -3878,7 +4031,7 @@
3878
4031
  /* Default placement: above the anchor */
3879
4032
  position-area: block-start;
3880
4033
  position-try-fallbacks: flip-block, flip-inline;
3881
- margin: 0;
4034
+ margin: var(--ui-popover-viewport-margin);
3882
4035
 
3883
4036
  max-width: var(--ui-tooltip-max-width);
3884
4037
  padding-block: calc(var(--_space) * 1.5);
@@ -3900,8 +4053,12 @@
3900
4053
  inset: unset;
3901
4054
  overflow: visible;
3902
4055
 
4056
+ --_popover-origin: bottom center;
4057
+ --_popover-from: perspective(800px) scale(0.96) rotateX(10deg);
4058
+
4059
+ transform-origin: var(--_popover-origin);
3903
4060
  opacity: 0;
3904
- transform: scale(0.96);
4061
+ transform: var(--_popover-from);
3905
4062
  transition:
3906
4063
  opacity var(--_duration) var(--_easing),
3907
4064
  transform var(--_duration) var(--_easing),
@@ -3913,37 +4070,45 @@
3913
4070
 
3914
4071
  :where(ui-tooltip[popover]):popover-open {
3915
4072
  opacity: 1;
3916
- transform: scale(1);
4073
+ transform: none;
3917
4074
  }
3918
4075
 
3919
4076
  /* Starting style for entry animation */
3920
4077
  @starting-style {
3921
4078
  :where(ui-tooltip[popover]):popover-open {
3922
4079
  opacity: 0;
3923
- transform: scale(0.96);
4080
+ transform: var(--_popover-from);
3924
4081
  }
3925
4082
  }
3926
4083
 
3927
4084
  /* ── Placement Variants ── */
3928
4085
 
3929
4086
  :where(ui-tooltip[placement="top"]) {
4087
+ --_popover-origin: bottom center;
4088
+ --_popover-from: perspective(800px) scale(0.96) rotateX(10deg);
3930
4089
  position-area: block-start;
3931
- margin-bottom: calc(var(--_space) * 2);
4090
+ margin-block-end: calc(var(--_space) * 2);
3932
4091
  }
3933
4092
 
3934
4093
  :where(ui-tooltip[placement="bottom"]) {
4094
+ --_popover-origin: top center;
4095
+ --_popover-from: perspective(800px) scale(0.96) rotateX(-10deg);
3935
4096
  position-area: block-end;
3936
- margin-top: calc(var(--_space) * 2);
4097
+ margin-block-start: calc(var(--_space) * 2);
3937
4098
  }
3938
4099
 
3939
4100
  :where(ui-tooltip[placement="left"]) {
4101
+ --_popover-origin: right center;
4102
+ --_popover-from: perspective(800px) scale(0.96) rotateY(-10deg);
3940
4103
  position-area: inline-start;
3941
- margin-right: calc(var(--_space) * 2);
4104
+ margin-inline-end: calc(var(--_space) * 2);
3942
4105
  }
3943
4106
 
3944
4107
  :where(ui-tooltip[placement="right"]) {
4108
+ --_popover-origin: left center;
4109
+ --_popover-from: perspective(800px) scale(0.96) rotateY(10deg);
3945
4110
  position-area: inline-end;
3946
- margin-left: calc(var(--_space) * 2);
4111
+ margin-inline-start: calc(var(--_space) * 2);
3947
4112
  }
3948
4113
 
3949
4114
  /* ── Hidden (not :popover-open) ── */
@@ -3967,7 +4132,8 @@
3967
4132
  flex: 1 1 0%;
3968
4133
  min-width: 0;
3969
4134
  flex-direction: column;
3970
- padding: var(--_space);
4135
+ padding-block: var(--_space);
4136
+ padding-inline: var(--_space);
3971
4137
  font-size: var(--_font-size);
3972
4138
  line-height: var(--_line-height);
3973
4139
  }
@@ -4052,7 +4218,7 @@
4052
4218
 
4053
4219
  /* ── Disabled ── */
4054
4220
 
4055
- :where(ui-tree-item[disabled]) > :where([slot="label"]) {
4221
+ :where(ui-tree-item[aria-disabled="true"]) > :where([slot="label"]) {
4056
4222
  color: var(--_ink-disabled);
4057
4223
  cursor: not-allowed;
4058
4224
  pointer-events: none;
@@ -4762,11 +4928,11 @@
4762
4928
  /* WHY: When collapsed to icon rail, the sidebar edge meets content — drop left padding. */
4763
4929
 
4764
4930
  :where(ui-layout-sidebar)[collapsed] :where(ui-layout-canvas) {
4765
- padding-left: 0;
4931
+ padding-inline-start: 0;
4766
4932
  }
4767
4933
 
4768
4934
  :where(ui-layout-sidebar)[collapsed] :where(ui-layout-breadcrumb) {
4769
- padding-left: 0;
4935
+ padding-inline-start: 0;
4770
4936
  }
4771
4937
 
4772
4938
  /* ── Sidebar Header ── */
@@ -4935,10 +5101,15 @@
4935
5101
  Flip: bottom-aligned, grows upward (span-block-start). */
4936
5102
 
4937
5103
  :where(ui-layout-sidebar-item) > :where(ui-listbox[popover]) {
5104
+ --_popover-origin: left center;
5105
+ --_popover-from: perspective(800px) scale(0.96) rotateY(20deg);
5106
+
4938
5107
  position: fixed;
4939
5108
  position-area: inline-end span-block-end;
4940
5109
  position-try-fallbacks: --sidebar-item-flip-up;
4941
- margin: 0 0 0 var(--ui-popover-gap);
5110
+ margin-block: var(--ui-popover-viewport-margin);
5111
+ margin-inline: 0;
5112
+ margin-inline-start: var(--ui-popover-gap);
4942
5113
  min-width: 200px;
4943
5114
  max-height: var(--ui-popover-max-height);
4944
5115
  overflow-y: auto;
@@ -4948,6 +5119,10 @@
4948
5119
  position-area: inline-end span-block-start;
4949
5120
  }
4950
5121
 
5122
+ @position-try --sidebar-item-flip-down {
5123
+ position-area: inline-end span-block-end;
5124
+ }
5125
+
4951
5126
  /* ── Container Query: Collapsed Sidebar ── */
4952
5127
  /* WHY: Each component owns its own collapsed behavior via @container.
4953
5128
  The aside is the container (container-name: sidebar). When it shrinks
@@ -4988,6 +5163,14 @@
4988
5163
  :where(ui-layout-sidebar-item) > :where(:not([slot="icon"]):not(ui-listbox[popover]):not(.nav-group-flyout)) {
4989
5164
  display: none;
4990
5165
  }
5166
+
5167
+ /* WHY: In collapsed mode the sidebar item is a small icon — centering
5168
+ the popover vertically with the anchor is more natural than top-aligning.
5169
+ Fallbacks handle viewport clipping (top/bottom edge). */
5170
+ :where(ui-layout-sidebar-item) > :where(ui-listbox[popover]) {
5171
+ position-area: inline-end;
5172
+ position-try-fallbacks: --sidebar-item-flip-up, --sidebar-item-flip-down;
5173
+ }
4991
5174
  }
4992
5175
 
4993
5176
  }
@@ -5196,57 +5379,6 @@
5196
5379
 
5197
5380
  }
5198
5381
 
5199
- @layer ui {
5200
-
5201
- /* ── Icon Base ── */
5202
-
5203
- :where(ui-icon) {
5204
- --ui-icon-size: var(--_icon-size);
5205
- --ui-icon-color: currentColor;
5206
-
5207
- box-sizing: border-box;
5208
- display: inline-flex;
5209
- align-items: center;
5210
- justify-content: center;
5211
- width: var(--ui-icon-size);
5212
- height: var(--ui-icon-size);
5213
- color: var(--ui-icon-color);
5214
- flex-shrink: 0;
5215
- vertical-align: middle;
5216
- line-height: 0;
5217
- }
5218
-
5219
- :where(ui-icon) > :where(svg) {
5220
- width: 100%;
5221
- height: 100%;
5222
- }
5223
-
5224
- /* WHY: Unregistered icons (no SVG content) should collapse to zero size
5225
- so surrounding buttons/slots don't render with phantom dimensions */
5226
- :where(ui-icon:empty) {
5227
- width: 0;
5228
- height: 0;
5229
- overflow: hidden;
5230
- }
5231
-
5232
- /* ── Icon Size Variants ── */
5233
-
5234
- :where(ui-icon[size="xs"]) { --ui-icon-size: var(--ui-icon-xs); }
5235
- :where(ui-icon[size="sm"]) { --ui-icon-size: var(--ui-icon-sm); }
5236
- :where(ui-icon[size="md"]) { --ui-icon-size: var(--ui-icon-md); }
5237
- :where(ui-icon[size="lg"]) { --ui-icon-size: var(--ui-icon-lg); }
5238
- :where(ui-icon[size="xl"]) { --ui-icon-size: var(--ui-icon-xl); }
5239
-
5240
- /* ── Forced Colors ── */
5241
-
5242
- @media (forced-colors: active) {
5243
- :where(ui-icon) {
5244
- --ui-icon-color: ButtonText;
5245
- }
5246
- }
5247
-
5248
- }
5249
-
5250
5382
  @layer ui {
5251
5383
 
5252
5384
  /* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -1 +1 @@
1
- {"version":3,"file":"ui-layout-sidebar-element.d.ts","sourceRoot":"","sources":["../../../src/containers/ui-layout-sidebar/ui-layout-sidebar-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAIrD;2EAC2E;AAC3E,qBAAa,eAAgB,SAAQ,SAAS;;IAC5C,MAAM,CAAC,kBAAkB,WAAiB;IAS1C,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IASpF,KAAK,IAAI,IAAI;IA+Bb,QAAQ,IAAI,IAAI;CAoGjB"}
1
+ {"version":3,"file":"ui-layout-sidebar-element.d.ts","sourceRoot":"","sources":["../../../src/containers/ui-layout-sidebar/ui-layout-sidebar-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAIrD;2EAC2E;AAC3E,qBAAa,eAAgB,SAAQ,SAAS;;IAC5C,MAAM,CAAC,kBAAkB,WAAiB;IAS1C,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IASpF,KAAK,IAAI,IAAI;IAmCb,QAAQ,IAAI,IAAI;CAoGjB"}
@@ -5,14 +5,14 @@ import type { Constructor } from './types.ts';
5
5
  * - `static formAssociated = true`
6
6
  * - `formDisabledCallback` → calls `onFormDisabled(disabled)`
7
7
  * - `formResetCallback` → calls `onFormReset()`
8
- *
9
- * Subclasses override `onFormDisabled` and `onFormReset` with their own logic.
8
+ * - `formStateRestoreCallback` → calls `onFormStateRestore(state)`
10
9
  *
11
10
  * Must remain a mixin (not a controller) because the Web Components spec
12
11
  * requires `static formAssociated = true` on the class constructor.
13
12
  *
14
13
  * ```ts
15
14
  * class UIInput extends FormAssociable(UIElement) {
15
+ * #internals = this.attachInternals();
16
16
  * onFormDisabled(disabled: boolean) { this.#disabled.value = disabled; }
17
17
  * onFormReset() { this.textContent = ''; }
18
18
  * }
@@ -1 +1 @@
1
- {"version":3,"file":"trait-runtime.d.ts","sourceRoot":"","sources":["../../src/core/trait-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;GAIG;AACH,qBAAa,YAAY;;IAmBvB,IAAI,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAO3B,MAAM,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;CAmB9B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAQD,qBAAa,YAAY;;IA0BvB,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM;IAuCvD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAazB,UAAU,IAAI,IAAI;CAKnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;CACvC;AAID,wBAAgB,eAAe,IAAI,YAAY,CAS9C"}
1
+ {"version":3,"file":"trait-runtime.d.ts","sourceRoot":"","sources":["../../src/core/trait-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;GAIG;AACH,qBAAa,YAAY;;IAsBvB,IAAI,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAO3B,MAAM,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;CAmB9B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAQD,qBAAa,YAAY;;IA0BvB,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM;IAuCvD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAazB,UAAU,IAAI,IAAI;CAKnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;CACvC;AAID,wBAAgB,eAAe,IAAI,YAAY,CAS9C"}
@@ -1,6 +1,8 @@
1
1
  /** Base custom element class with reactive effect lifecycle, child deferral, and trait protocol. */
2
2
  export declare class UIElement extends HTMLElement {
3
3
  #private;
4
+ /** Resolves after setup() and any deferChildren microtask have completed. */
5
+ readonly ready: Promise<void>;
4
6
  addEffect(fn: () => void): void;
5
7
  connectedCallback(): void;
6
8
  disconnectedCallback(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"ui-element.d.ts","sourceRoot":"","sources":["../../src/core/ui-element.ts"],"names":[],"mappings":"AAKA,oGAAoG;AACpG,qBAAa,SAAU,SAAQ,WAAW;;IAQxC,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;IAI/B,iBAAiB,IAAI,IAAI;IAazB,oBAAoB,IAAI,IAAI;IAa5B,KAAK,IAAI,IAAI;IACb,QAAQ,IAAI,IAAI;IAEhB,SAAS,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;IAU7C,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAEvF;;;OAGG;IACH,kBAAkB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;CAsG9C"}
1
+ {"version":3,"file":"ui-element.d.ts","sourceRoot":"","sources":["../../src/core/ui-element.ts"],"names":[],"mappings":"AAKA,oGAAoG;AACpG,qBAAa,SAAU,SAAQ,WAAW;;IASxC,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAE1B;IAEH,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;IAI/B,iBAAiB,IAAI,IAAI;IAgBzB,oBAAoB,IAAI,IAAI;IAa5B,KAAK,IAAI,IAAI;IACb,QAAQ,IAAI,IAAI;IAEhB,SAAS,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;IAU7C,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAEvF;;;OAGG;IACH,kBAAkB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;CAsG9C"}