@scalewing/react 1.47.0 → 1.49.0

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 (135) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +215 -6
  3. package/dist/command-palette.test-support.d.ts +21 -0
  4. package/dist/command-palette.test-support.js +55 -0
  5. package/dist/components/AppHeader.d.ts +3 -0
  6. package/dist/components/AppShell.d.ts +4 -3
  7. package/dist/components/AppShell.js +24 -7
  8. package/dist/components/Band.d.ts +30 -0
  9. package/dist/components/Band.js +23 -0
  10. package/dist/components/ButtonLink.d.ts +33 -0
  11. package/dist/components/ButtonLink.js +27 -0
  12. package/dist/components/CommandPalette.d.ts +12 -0
  13. package/dist/components/CommandPalette.js +143 -0
  14. package/dist/components/CommandPaletteTrigger.d.ts +9 -0
  15. package/dist/components/CommandPaletteTrigger.js +16 -0
  16. package/dist/components/ContextSwitcher.d.ts +12 -0
  17. package/dist/components/ContextSwitcher.js +62 -0
  18. package/dist/components/EmptyState.d.ts +23 -0
  19. package/dist/components/EmptyState.js +40 -0
  20. package/dist/components/FixtureGroup.d.ts +9 -0
  21. package/dist/components/FixtureGroup.js +16 -0
  22. package/dist/components/FixtureRow.d.ts +10 -0
  23. package/dist/components/FixtureRow.js +46 -0
  24. package/dist/components/GlyphTile.d.ts +9 -3
  25. package/dist/components/GlyphTile.js +15 -4
  26. package/dist/components/Grid.d.ts +11 -3
  27. package/dist/components/Grid.js +13 -4
  28. package/dist/components/Hero.d.ts +26 -0
  29. package/dist/components/Hero.js +23 -0
  30. package/dist/components/SiteFooter.d.ts +12 -0
  31. package/dist/components/SiteFooter.js +23 -0
  32. package/dist/components/SiteHeader.d.ts +14 -0
  33. package/dist/components/SiteHeader.js +24 -0
  34. package/dist/components/Skeleton.d.ts +22 -0
  35. package/dist/components/Skeleton.js +30 -0
  36. package/dist/components/Stepper.d.ts +11 -1
  37. package/dist/components/Stepper.js +10 -8
  38. package/dist/components/Text.js +3 -0
  39. package/dist/components/app-shell/AppShellBar.d.ts +23 -0
  40. package/dist/components/app-shell/AppShellBar.js +25 -0
  41. package/dist/components/app-shell/types.d.ts +36 -1
  42. package/dist/components/app-shell/validate.d.ts +4 -3
  43. package/dist/components/app-shell/validate.js +21 -3
  44. package/dist/components/command-palette/PaletteList.d.ts +20 -0
  45. package/dist/components/command-palette/PaletteList.js +21 -0
  46. package/dist/components/command-palette/shortcut.d.ts +19 -0
  47. package/dist/components/command-palette/shortcut.js +75 -0
  48. package/dist/components/command-palette/types.d.ts +72 -0
  49. package/dist/components/command-palette/types.js +2 -0
  50. package/dist/components/command-palette/validate.d.ts +10 -0
  51. package/dist/components/command-palette/validate.js +50 -0
  52. package/dist/components/context-switcher/SwitcherOption.d.ts +17 -0
  53. package/dist/components/context-switcher/SwitcherOption.js +20 -0
  54. package/dist/components/context-switcher/SwitcherPopup.d.ts +31 -0
  55. package/dist/components/context-switcher/SwitcherPopup.js +111 -0
  56. package/dist/components/context-switcher/options.d.ts +33 -0
  57. package/dist/components/context-switcher/options.js +60 -0
  58. package/dist/components/context-switcher/types.d.ts +96 -0
  59. package/dist/components/context-switcher/types.js +1 -0
  60. package/dist/components/context-switcher/use-switcher-list.d.ts +29 -0
  61. package/dist/components/context-switcher/use-switcher-list.js +93 -0
  62. package/dist/components/context-switcher/validate.d.ts +8 -0
  63. package/dist/components/context-switcher/validate.js +94 -0
  64. package/dist/components/fixture/fixture-list-context.d.ts +4 -0
  65. package/dist/components/fixture/fixture-list-context.js +9 -0
  66. package/dist/components/fixture/types.d.ts +50 -0
  67. package/dist/components/fixture/types.js +1 -0
  68. package/dist/components/fixture/validate.d.ts +8 -0
  69. package/dist/components/fixture/validate.js +36 -0
  70. package/dist/components/site-footer/types.d.ts +31 -0
  71. package/dist/components/site-footer/types.js +1 -0
  72. package/dist/components/site-footer/validate.d.ts +7 -0
  73. package/dist/components/site-footer/validate.js +22 -0
  74. package/dist/components/site-header/SiteHeaderLinks.d.ts +7 -0
  75. package/dist/components/site-header/SiteHeaderLinks.js +7 -0
  76. package/dist/components/site-header/types.d.ts +38 -0
  77. package/dist/components/site-header/types.js +1 -0
  78. package/dist/components/site-header/use-menu-dismiss.d.ts +8 -0
  79. package/dist/components/site-header/use-menu-dismiss.js +62 -0
  80. package/dist/components/site-header/validate.d.ts +7 -0
  81. package/dist/components/site-header/validate.js +17 -0
  82. package/dist/components/stepper/StepperCountFrame.d.ts +15 -0
  83. package/dist/components/stepper/StepperCountFrame.js +25 -0
  84. package/dist/components/use-element-height.d.ts +10 -0
  85. package/dist/components/use-element-height.js +35 -0
  86. package/dist/context-switcher.test-support.d.ts +9 -0
  87. package/dist/context-switcher.test-support.js +41 -0
  88. package/dist/css/css-app-shell-page-bar.d.ts +3 -0
  89. package/dist/css/css-app-shell-page-bar.js +81 -0
  90. package/dist/css/css-app-shell.js +6 -1
  91. package/dist/css/css-band.d.ts +10 -0
  92. package/dist/css/css-band.js +101 -0
  93. package/dist/css/css-button-link.d.ts +3 -0
  94. package/dist/css/css-button-link.js +48 -0
  95. package/dist/css/css-command-palette-key.d.ts +1 -0
  96. package/dist/css/css-command-palette-key.js +33 -0
  97. package/dist/css/css-command-palette-trigger.d.ts +2 -0
  98. package/dist/css/css-command-palette-trigger.js +88 -0
  99. package/dist/css/css-command-palette.d.ts +2 -0
  100. package/dist/css/css-command-palette.js +209 -0
  101. package/dist/css/css-components.js +30 -0
  102. package/dist/css/css-context-switcher-trigger.d.ts +15 -0
  103. package/dist/css/css-context-switcher-trigger.js +175 -0
  104. package/dist/css/css-context-switcher.d.ts +4 -0
  105. package/dist/css/css-context-switcher.js +219 -0
  106. package/dist/css/css-count-pill.d.ts +2 -2
  107. package/dist/css/css-count-pill.js +11 -3
  108. package/dist/css/css-empty-state.d.ts +2 -0
  109. package/dist/css/css-empty-state.js +77 -0
  110. package/dist/css/css-fixture.d.ts +5 -0
  111. package/dist/css/css-fixture.js +260 -0
  112. package/dist/css/css-glyph-tile.d.ts +2 -0
  113. package/dist/css/css-glyph-tile.js +29 -1
  114. package/dist/css/css-grid-span.js +5 -2
  115. package/dist/css/css-grid.d.ts +13 -0
  116. package/dist/css/css-grid.js +17 -1
  117. package/dist/css/css-hero.d.ts +2 -0
  118. package/dist/css/css-hero.js +62 -0
  119. package/dist/css/css-site-footer.d.ts +2 -0
  120. package/dist/css/css-site-footer.js +152 -0
  121. package/dist/css/css-site-header.d.ts +2 -0
  122. package/dist/css/css-site-header.js +262 -0
  123. package/dist/css/css-skeleton.d.ts +10 -0
  124. package/dist/css/css-skeleton.js +110 -0
  125. package/dist/css/css-stepper-unit.d.ts +9 -0
  126. package/dist/css/css-stepper-unit.js +102 -0
  127. package/dist/css/css-stepper.js +5 -1
  128. package/dist/css/stacking.js +7 -4
  129. package/dist/css/stylesheet.js +20 -0
  130. package/dist/index.d.ts +18 -2
  131. package/dist/index.js +13 -1
  132. package/dist/stepper-count.d.ts +8 -0
  133. package/dist/stepper-count.js +17 -0
  134. package/dist/styles.css +2202 -702
  135. package/package.json +2 -2
@@ -0,0 +1,262 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ import { breakpointQuery } from './breakpoints.js';
3
+ import { quietFill } from './quiet-fill.js';
4
+ import { zIndex } from './stacking.js';
5
+ const label = typographyVariants.label;
6
+ const title = typographyVariants.title;
7
+ /** The bar's height: 56 px on a phone, 72 px from `lg`. */
8
+ const compactHeight = 'calc(var(--sw-control-md-min-height) + var(--sw-space-3))';
9
+ const wideHeight = 'calc(var(--sw-control-md-min-height) + var(--sw-space-5) + var(--sw-space-1))';
10
+ const wide = breakpointQuery('from', 'lg');
11
+ /*
12
+ * The bar: the solid surface with a hairline under it, its content in the
13
+ * page container with the page gutter. Below `lg` it holds the brand, the
14
+ * compact actions and the menu button; from `lg` the brand, the
15
+ * destinations (the current one at label weight over a bar in the words'
16
+ * colour, as tall as the bar) and the actions, spread apart.
17
+ */
18
+ function barRules() {
19
+ return `.sw-site-header {
20
+ --sw-site-header-height: ${compactHeight};
21
+ background: var(--sw-color-surface);
22
+ border-bottom: 1px solid var(--sw-color-border);
23
+ color: var(--sw-color-text);
24
+ font-family: var(--sw-font-sans);
25
+ position: relative;
26
+ }
27
+
28
+ .sw-site-header-sticky {
29
+ position: sticky;
30
+ top: 0;
31
+ ${zIndex('topChrome')}
32
+ }
33
+
34
+ .sw-site-header-bar {
35
+ align-items: center;
36
+ box-sizing: border-box;
37
+ display: flex;
38
+ gap: var(--sw-space-5);
39
+ justify-content: space-between;
40
+ margin-inline: auto;
41
+ max-width: calc(var(--sw-container-max) + 2 * var(--sw-space-5));
42
+ min-height: var(--sw-site-header-height);
43
+ padding-inline: var(--sw-space-4);
44
+ }
45
+
46
+ .sw-site-header-brand {
47
+ align-items: center;
48
+ display: flex;
49
+ flex: none;
50
+ }
51
+
52
+ .sw-site-header-nav,
53
+ .sw-site-header-actions {
54
+ display: none;
55
+ }
56
+
57
+ .sw-site-header-compact {
58
+ align-items: center;
59
+ display: flex;
60
+ gap: var(--sw-space-1);
61
+ }
62
+
63
+ .sw-site-header-list {
64
+ list-style: none;
65
+ margin: 0;
66
+ padding: 0;
67
+ }
68
+
69
+ .sw-site-header-nav .sw-site-header-list {
70
+ display: flex;
71
+ gap: var(--sw-space-5);
72
+ }
73
+
74
+ [data-theme] .sw-site-header-nav .sw-site-header-link {
75
+ align-items: center;
76
+ color: var(--sw-color-text);
77
+ display: inline-flex;
78
+ font-size: ${label.fontSize}px;
79
+ font-weight: 400;
80
+ letter-spacing: ${label.letterSpacing}px;
81
+ line-height: ${label.lineHeight}px;
82
+ min-height: var(--sw-site-header-height);
83
+ text-decoration: none;
84
+ }
85
+
86
+ [data-theme] .sw-site-header-nav .sw-site-header-link:hover {
87
+ box-shadow: inset 0 -2px 0 var(--sw-color-border);
88
+ }
89
+
90
+ [data-theme] .sw-site-header-nav .sw-site-header-link[aria-current] {
91
+ box-shadow: inset 0 -2px 0 currentColor;
92
+ font-weight: ${label.fontWeight};
93
+ }
94
+
95
+ [data-theme] .sw-site-header-nav .sw-site-header-link:focus-visible {
96
+ outline-offset: calc(-1 * var(--sw-focus-ring-width));
97
+ }
98
+
99
+ .sw-site-header-actions {
100
+ align-items: center;
101
+ gap: var(--sw-space-4);
102
+ }
103
+
104
+ @media ${breakpointQuery('from', 'md')} {
105
+ .sw-site-header-bar { padding-inline: var(--sw-space-5); }
106
+ }
107
+
108
+ @media ${wide} {
109
+ .sw-site-header { --sw-site-header-height: ${wideHeight}; }
110
+ .sw-site-header-nav { display: block; }
111
+ .sw-site-header-actions { display: flex; }
112
+ .sw-site-header-compact { display: none; }
113
+ }`;
114
+ }
115
+ /*
116
+ * The menu is a native \`details\`: its \`summary\` is the button (the menu
117
+ * glyph and its name while closed, the close glyph and its name while
118
+ * open, the other pair hidden so only one is read), and its panel lies
119
+ * under the bar over the rest of the window, the destinations as large
120
+ * rows with hairlines and the menu's actions at the panel's foot. It
121
+ * scrolls on its own when the window is short.
122
+ */
123
+ function menuRules() {
124
+ return `.sw-site-header-menu > summary {
125
+ list-style: none;
126
+ }
127
+
128
+ .sw-site-header-menu > summary::-webkit-details-marker {
129
+ display: none;
130
+ }
131
+
132
+ .sw-site-header-menu-button {
133
+ align-items: center;
134
+ border-radius: var(--sw-radius-pill);
135
+ box-sizing: border-box;
136
+ color: var(--sw-color-text);
137
+ cursor: pointer;
138
+ display: inline-flex;
139
+ height: var(--sw-control-md-min-height);
140
+ justify-content: center;
141
+ width: var(--sw-control-md-min-height);
142
+ }
143
+
144
+ .sw-site-header-menu-button:hover {
145
+ background: ${quietFill};
146
+ }
147
+
148
+ .sw-site-header-menu-button:focus-visible {
149
+ outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
150
+ outline-offset: calc(-1 * var(--sw-focus-ring-width));
151
+ }
152
+
153
+ .sw-site-header-menu-open,
154
+ .sw-site-header-menu-close,
155
+ .sw-site-header-glyph {
156
+ align-items: center;
157
+ display: inline-flex;
158
+ }
159
+
160
+ .sw-site-header-menu[open] .sw-site-header-menu-open,
161
+ .sw-site-header-menu:not([open]) .sw-site-header-menu-close {
162
+ display: none;
163
+ }
164
+
165
+ .sw-site-header-panel {
166
+ background: var(--sw-color-surface);
167
+ box-sizing: border-box;
168
+ display: flex;
169
+ flex-direction: column;
170
+ height: calc(100dvh - var(--sw-site-header-height) - 1px);
171
+ inset-inline: 0;
172
+ overflow-y: auto;
173
+ padding: var(--sw-space-2) var(--sw-space-4) var(--sw-space-6);
174
+ position: absolute;
175
+ top: calc(100% + 1px);
176
+ }
177
+
178
+ .sw-site-header-menu-nav .sw-site-header-list {
179
+ display: flex;
180
+ flex-direction: column;
181
+ }
182
+
183
+ [data-theme] .sw-site-header-menu-nav .sw-site-header-link {
184
+ align-items: center;
185
+ border-bottom: 1px solid var(--sw-color-border);
186
+ color: var(--sw-color-text);
187
+ display: flex;
188
+ font-size: ${title.fontSize}px;
189
+ font-weight: ${title.fontWeight};
190
+ letter-spacing: ${title.letterSpacing}px;
191
+ line-height: ${title.lineHeight}px;
192
+ min-height: ${compactHeight};
193
+ text-decoration: none;
194
+ }
195
+
196
+ [data-theme] .sw-site-header-menu-nav .sw-site-header-link[aria-current] {
197
+ color: var(--sw-color-accent);
198
+ }
199
+
200
+ [data-theme] .sw-site-header-menu-nav .sw-site-header-link:focus-visible {
201
+ outline-offset: calc(-1 * var(--sw-focus-ring-width));
202
+ }
203
+
204
+ .sw-site-header-menu-actions {
205
+ display: flex;
206
+ flex-direction: column;
207
+ gap: var(--sw-space-3);
208
+ margin-top: auto;
209
+ padding-top: var(--sw-space-5);
210
+ }`;
211
+ }
212
+ export function cssSiteHeaderClasses() {
213
+ return `${barRules()}
214
+
215
+ ${menuRules()}
216
+
217
+ /*
218
+ * Forced colours drop box shadows, so the current destination's bar is a
219
+ * thick underline there.
220
+ */
221
+ @media (forced-colors: active) {
222
+ .sw-site-header,
223
+ [data-theme] .sw-site-header-menu-nav .sw-site-header-link {
224
+ border-color: CanvasText;
225
+ }
226
+
227
+ [data-theme] .sw-site-header-link[aria-current] {
228
+ color: Highlight;
229
+ }
230
+
231
+ [data-theme] .sw-site-header-nav .sw-site-header-link[aria-current] {
232
+ text-decoration: underline;
233
+ text-decoration-thickness: 2px;
234
+ text-underline-offset: var(--sw-space-2);
235
+ }
236
+
237
+ .sw-site-header-menu-button {
238
+ border: 1px solid ButtonText;
239
+ }
240
+ }`;
241
+ }
242
+ export function siteHeaderClassCatalog() {
243
+ return [
244
+ 'sw-site-header',
245
+ 'sw-site-header-sticky',
246
+ 'sw-site-header-bar',
247
+ 'sw-site-header-brand',
248
+ 'sw-site-header-nav',
249
+ 'sw-site-header-actions',
250
+ 'sw-site-header-compact',
251
+ 'sw-site-header-list',
252
+ 'sw-site-header-link',
253
+ 'sw-site-header-menu',
254
+ 'sw-site-header-menu-button',
255
+ 'sw-site-header-menu-open',
256
+ 'sw-site-header-menu-close',
257
+ 'sw-site-header-glyph',
258
+ 'sw-site-header-panel',
259
+ 'sw-site-header-menu-nav',
260
+ 'sw-site-header-menu-actions',
261
+ ];
262
+ }
@@ -0,0 +1,10 @@
1
+ export declare const skeletonVariants: readonly ["lines", "rows"];
2
+ /** `lines` is bars of text in a column; `rows` is list rows with hairlines. */
3
+ export type SkeletonVariant = (typeof skeletonVariants)[number];
4
+ /** How many bars or rows a Skeleton draws. */
5
+ export declare const skeletonLineRange: {
6
+ readonly min: 1;
7
+ readonly max: 6;
8
+ };
9
+ export declare function cssSkeletonClasses(): string;
10
+ export declare function skeletonClassCatalog(): string[];
@@ -0,0 +1,110 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ import { quietFill } from './quiet-fill.js';
3
+ import { coarsePointerQuery, touchTarget } from './touch-target.js';
4
+ const body = typographyVariants.body;
5
+ export const skeletonVariants = ['lines', 'rows'];
6
+ /** How many bars or rows a Skeleton draws. */
7
+ export const skeletonLineRange = { min: 1, max: 6 };
8
+ /*
9
+ * The widths the bars take in turn, so a column reads as text with ragged
10
+ * ends rather than a grid; the last bar of `lines` is shorter still.
11
+ */
12
+ const barWidths = ['100%', '92%', '84%', '96%', '88%', '80%'];
13
+ function barWidthRules(parent) {
14
+ return barWidths
15
+ .map((width, index) => `${parent} > .sw-skeleton-bar:nth-of-type(${index + 1}) { width: ${width}; }`)
16
+ .join('\n');
17
+ }
18
+ /*
19
+ * Skeleton: grey placeholder bars in the quiet fill, rounded, a text
20
+ * line's height apart. `rows` draws each as a list row: a mark (space-6,
21
+ * the small radius) and a bar at the control height (44 px on a coarse
22
+ * pointer, as a pressable row there), hairlines between. The bars pulse
23
+ * between full and 60 % opacity over the travel duration, and stay still
24
+ * under reduced motion. Forced colours, which drop fills, draw each bar's
25
+ * edge in GrayText so the shape stays.
26
+ */
27
+ export function cssSkeletonClasses() {
28
+ return `.sw-skeleton {
29
+ display: flex;
30
+ flex-direction: column;
31
+ gap: var(--sw-space-3);
32
+ width: 100%;
33
+ }
34
+
35
+ .sw-skeleton-bar,
36
+ .sw-skeleton-mark {
37
+ animation: sw-skeleton-pulse calc(2 * var(--sw-motion-travel)) var(--sw-motion-travel-easing) infinite alternate;
38
+ background: ${quietFill};
39
+ border-radius: var(--sw-radius-sm);
40
+ box-sizing: border-box;
41
+ display: block;
42
+ flex: none;
43
+ }
44
+
45
+ .sw-skeleton-bar {
46
+ height: calc(${body.fontSize}px * 0.8);
47
+ }
48
+
49
+ ${barWidthRules('.sw-skeleton-lines')}
50
+ .sw-skeleton-lines > .sw-skeleton-bar:last-of-type:not(:first-of-type) { width: 60%; }
51
+
52
+ .sw-skeleton-rows {
53
+ gap: 0;
54
+ }
55
+
56
+ .sw-skeleton-row {
57
+ align-items: center;
58
+ box-sizing: border-box;
59
+ display: flex;
60
+ gap: var(--sw-space-3);
61
+ min-height: var(--sw-control-md-min-height);
62
+ padding-block: var(--sw-space-2);
63
+ }
64
+
65
+ .sw-skeleton-row + .sw-skeleton-row {
66
+ border-top: 1px solid var(--sw-color-border);
67
+ }
68
+
69
+ .sw-skeleton-row .sw-skeleton-bar {
70
+ flex: 0 1 60%;
71
+ }
72
+
73
+ .sw-skeleton-row:nth-of-type(even) .sw-skeleton-bar {
74
+ flex-basis: 45%;
75
+ }
76
+
77
+ .sw-skeleton-mark {
78
+ height: var(--sw-space-6);
79
+ width: var(--sw-space-6);
80
+ }
81
+
82
+ @keyframes sw-skeleton-pulse {
83
+ from { opacity: 1; }
84
+ to { opacity: 0.6; }
85
+ }
86
+
87
+ @media ${coarsePointerQuery} {
88
+ .sw-skeleton-row { min-height: ${touchTarget}; }
89
+ }
90
+
91
+ @media (prefers-reduced-motion: reduce) {
92
+ .sw-skeleton-bar,
93
+ .sw-skeleton-mark { animation: none; }
94
+ }
95
+
96
+ @media (forced-colors: active) {
97
+ .sw-skeleton-bar,
98
+ .sw-skeleton-mark { border: 1px solid GrayText; }
99
+ .sw-skeleton-row + .sw-skeleton-row { border-color: GrayText; }
100
+ }`;
101
+ }
102
+ export function skeletonClassCatalog() {
103
+ return [
104
+ 'sw-skeleton',
105
+ ...skeletonVariants.map((variant) => `sw-skeleton-${variant}`),
106
+ 'sw-skeleton-bar',
107
+ 'sw-skeleton-row',
108
+ 'sw-skeleton-mark',
109
+ ];
110
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * A Stepper with a `unit`: the count and its muted word ("90 min") inside
3
+ * one control frame, as Field's suffix. The frame draws the canvas control
4
+ * surface, the focus ring and the states; the input inside drops its own and
5
+ * keeps its few-digit width, its digits against the unit, so the frame never
6
+ * follows the count. The pair is centred, also in a full-width stepper.
7
+ */
8
+ export declare function cssStepperUnitClasses(): string;
9
+ export declare function stepperUnitClassCatalog(): string[];
@@ -0,0 +1,102 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ import { controlSurface, disabledControlForcedColors, disabledControlSurface, } from './css-document.js';
3
+ import { changedTintLayer } from './css-field-changed.js';
4
+ const body = typographyVariants.body;
5
+ /*
6
+ * Outranks the stepper's own input rules and state rules (the invalid
7
+ * border, the changed shadow and tint), which the frame draws instead.
8
+ */
9
+ const framedInput = '[data-theme] .sw-stepper .sw-stepper-count > input.sw-stepper-input';
10
+ const tintedFrame = '.sw-stepper-changed .sw-stepper-count:not(:has(> input:placeholder-shown))';
11
+ /**
12
+ * A Stepper with a `unit`: the count and its muted word ("90 min") inside
13
+ * one control frame, as Field's suffix. The frame draws the canvas control
14
+ * surface, the focus ring and the states; the input inside drops its own and
15
+ * keeps its few-digit width, its digits against the unit, so the frame never
16
+ * follows the count. The pair is centred, also in a full-width stepper.
17
+ */
18
+ export function cssStepperUnitClasses() {
19
+ return `.sw-stepper-count {
20
+ ${controlSurface}
21
+ align-items: center;
22
+ box-sizing: border-box;
23
+ cursor: text;
24
+ display: inline-flex;
25
+ gap: var(--sw-space-1);
26
+ justify-content: center;
27
+ min-height: var(--sw-control-md-min-height);
28
+ min-width: 0;
29
+ padding-inline: var(--sw-space-2);
30
+ }
31
+
32
+ .sw-stepper-full .sw-stepper-count { display: flex; }
33
+
34
+ ${framedInput} {
35
+ align-self: stretch;
36
+ background: transparent;
37
+ background-image: none;
38
+ border: 0;
39
+ border-radius: 0;
40
+ box-shadow: none;
41
+ inline-size: 5ch;
42
+ min-height: 0;
43
+ padding-inline: 0;
44
+ text-align: end;
45
+ }
46
+
47
+ ${framedInput}:focus-visible { outline: none; }
48
+
49
+ .sw-stepper-count:focus-within {
50
+ outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
51
+ outline-offset: var(--sw-focus-ring-offset);
52
+ }
53
+
54
+ .sw-stepper-unit {
55
+ color: var(--sw-color-muted);
56
+ flex: none;
57
+ font-size: ${body.fontSize}px;
58
+ line-height: ${body.lineHeight}px;
59
+ user-select: none;
60
+ white-space: nowrap;
61
+ }
62
+
63
+ .sw-stepper-invalid .sw-stepper-count { border-color: var(--sw-color-danger); }
64
+
65
+ .sw-stepper-changed .sw-stepper-count {
66
+ border-color: var(--sw-color-accent);
67
+ box-shadow: inset 0 0 0 1px var(--sw-color-accent);
68
+ }
69
+
70
+ ${tintedFrame} { background-image: ${changedTintLayer}; }
71
+
72
+ ${tintedFrame} > .sw-stepper-unit { color: var(--sw-color-text); }
73
+
74
+ /*
75
+ * The frame draws the surface, so it carries the disabled look for its count,
76
+ * and only that look: a locked count drops the invalid and changed edges and
77
+ * tint, which name nothing a person can act on.
78
+ */
79
+ .sw-stepper .sw-stepper-count:has(> input:disabled) {
80
+ ${disabledControlSurface}
81
+ background-image: none;
82
+ border-color: var(--sw-color-border);
83
+ box-shadow: none;
84
+ }
85
+
86
+ .sw-stepper .sw-stepper-count:has(> input:disabled) > .sw-stepper-unit {
87
+ color: var(--sw-color-muted);
88
+ }
89
+
90
+ @media (forced-colors: active) {
91
+ .sw-stepper-unit { color: CanvasText; }
92
+ .sw-stepper-invalid .sw-stepper-count { border-color: Mark; }
93
+ .sw-stepper-changed .sw-stepper-count { border-color: Highlight; box-shadow: inset 0 0 0 1px Highlight; background-image: none; }
94
+ .sw-stepper .sw-stepper-count:has(> input:disabled) {
95
+ ${disabledControlForcedColors}
96
+ box-shadow: none;
97
+ }
98
+ }`;
99
+ }
100
+ export function stepperUnitClassCatalog() {
101
+ return ['sw-stepper-count', 'sw-stepper-unit'];
102
+ }
@@ -1,5 +1,6 @@
1
1
  import { typographyVariants } from '@scalewing/tokens';
2
2
  import { changedTintLayer } from './css-field-changed.js';
3
+ import { cssStepperUnitClasses, stepperUnitClassCatalog, } from './css-stepper-unit.js';
3
4
  const body = typographyVariants.body;
4
5
  const label = typographyVariants.label;
5
6
  const title = typographyVariants.title;
@@ -116,7 +117,9 @@ ${input} {
116
117
 
117
118
  .sw-stepper-full input.sw-stepper-input { inline-size: 100%; }
118
119
 
119
- ${stateRules()}`;
120
+ ${stateRules()}
121
+
122
+ ${cssStepperUnitClasses()}`;
120
123
  }
121
124
  export function stepperClassCatalog() {
122
125
  return [
@@ -129,5 +132,6 @@ export function stepperClassCatalog() {
129
132
  'sw-stepper-changed',
130
133
  'sw-stepper-readonly',
131
134
  'sw-stepper-limit-plain',
135
+ ...stepperUnitClassCatalog(),
132
136
  ];
133
137
  }
@@ -13,15 +13,15 @@
13
13
  * its popup can only paint as high as the surface does; lifting the surface
14
14
  * over the ActionBar keeps an open list tappable where the bar would cover
15
15
  * it, and over the next surface in the flow.
16
- * 5. `topChrome`: the sticky AppHeader or sticky Tabs strip (and a banded
17
- * Dialog's title band, inside its dialog), over a lifted
16
+ * 5. `topChrome`: the sticky AppHeader, sticky Tabs strip or AppShell page
17
+ * bar (and a banded Dialog's title band, inside its dialog), over a lifted
18
18
  * surface that scrolls up under it (the header is the page's way back, the
19
19
  * strip its way between sections, and a popup opens downward).
20
20
  * 6. `sheetGrabber`: a bottom sheet's grabber, inside its dialog, over the
21
21
  * banded title band that sticks under it.
22
22
  * 7. `popup`: a popup outside any lifted surface (Select list, ActionMenu
23
- * list, MultiSelect panel, Combobox list, Tooltip, the DateField and CalendarButton
24
- * calendar) over everything in the page.
23
+ * list, ContextSwitcher popup, MultiSelect panel, Combobox list, Tooltip,
24
+ * the DateField and CalendarButton calendar) over everything in the page.
25
25
  *
26
26
  * Dialog and Toast sit on the browser's top layer, above all of these.
27
27
  */
@@ -60,6 +60,9 @@ const openPopups = [
60
60
  // Combobox's list. Rendered only while open; on the top layer where the
61
61
  // popover API exists.
62
62
  '.sw-combobox-popup',
63
+ // ContextSwitcher's popup. Rendered only while open; on the top layer
64
+ // where the popover API exists.
65
+ '.sw-context-switcher-popup',
63
66
  '.sw-tooltip:not([hidden])',
64
67
  // DateField, CalendarButton and DateRangeButton share it. Rendered only
65
68
  // while open; on the top layer where the popover API exists.
@@ -2,6 +2,8 @@ import { cardVariants, darkTheme, lightTheme, typographyVariants, } from '@scale
2
2
  import { chartToneClassCatalog } from './chart-tones.js';
3
3
  import { actionBarClassCatalog } from './css-action-bar.js';
4
4
  import { actionMenuClassCatalog } from './css-action-menu.js';
5
+ import { commandPaletteClassCatalog } from './css-command-palette.js';
6
+ import { contextSwitcherClassCatalog } from './css-context-switcher.js';
5
7
  import { accordionClassCatalog } from './css-accordion.js';
6
8
  import { switchClassCatalog } from './css-switch.js';
7
9
  import { dateFieldClassCatalog } from './css-date-field.js';
@@ -10,11 +12,14 @@ import { dateRangeClassCatalog } from './css-date-range.js';
10
12
  import { fileFieldClassCatalog } from './css-file-field.js';
11
13
  import { articleClassCatalog } from './css-article.js';
12
14
  import { documentViewerClassCatalog } from './css-document-viewer.js';
15
+ import { fixtureClassCatalog } from './css-fixture.js';
13
16
  import { listClassCatalog } from './css-list.js';
14
17
  import { markdownClassCatalog } from './css-markdown.js';
15
18
  import { countPillClassCatalog } from './css-count-pill.js';
16
19
  import { checkboxClassCatalog } from './css-checkbox.js';
17
20
  import { radioGroupClassCatalog } from './css-radio-group.js';
21
+ import { skeletonClassCatalog } from './css-skeleton.js';
22
+ import { emptyStateClassCatalog } from './css-empty-state.js';
18
23
  import { spinnerClassCatalog } from './css-spinner.js';
19
24
  import { progressClassCatalog } from './css-progress.js';
20
25
  import { noticeClassCatalog } from './css-notice.js';
@@ -22,6 +27,10 @@ import { glyphTileClassCatalog } from './css-glyph-tile.js';
22
27
  import { tooltipClassCatalog } from './css-tooltip.js';
23
28
  import { infoTipClassCatalog } from './css-info-tip.js';
24
29
  import { separatorClassCatalog } from './css-separator.js';
30
+ import { bandClassCatalog } from './css-band.js';
31
+ import { heroClassCatalog } from './css-hero.js';
32
+ import { siteFooterClassCatalog } from './css-site-footer.js';
33
+ import { siteHeaderClassCatalog } from './css-site-header.js';
25
34
  import { statTileClassCatalog } from './css-stat-tile.js';
26
35
  import { descriptionListClassCatalog } from './css-description-list.js';
27
36
  import { tabsClassCatalog } from './css-tabs.js';
@@ -39,6 +48,7 @@ import { boxBorderClassCatalog } from './css-box-border.js';
39
48
  import { boxLinkClassCatalog } from './css-box-link.js';
40
49
  import { cssComponentClasses } from './css-components.js';
41
50
  import { buttonClassCatalog } from './css-button.js';
51
+ import { buttonLinkClassCatalog } from './css-button-link.js';
42
52
  import { barChartClassCatalog } from './css-bar-chart.js';
43
53
  import { chartLegendClassCatalog } from './css-chart-legend.js';
44
54
  import { chartPlotClassCatalog } from './css-chart-plot.js';
@@ -81,6 +91,7 @@ export function utilityClassCatalog() {
81
91
  'sw-tabular',
82
92
  ...Object.keys(typographyVariants).map((name) => `sw-text-${name}`),
83
93
  ...buttonClassCatalog(),
94
+ ...buttonLinkClassCatalog(),
84
95
  ...dataClassCatalog(),
85
96
  ...segmentedClassCatalog(),
86
97
  ...tableClassCatalog(),
@@ -103,6 +114,8 @@ export function utilityClassCatalog() {
103
114
  ...accordionClassCatalog(),
104
115
  ...selectClassCatalog(),
105
116
  ...actionMenuClassCatalog(),
117
+ ...contextSwitcherClassCatalog(),
118
+ ...commandPaletteClassCatalog(),
106
119
  ...multiSelectClassCatalog(),
107
120
  ...comboboxClassCatalog(),
108
121
  ...actionBarClassCatalog(),
@@ -111,6 +124,7 @@ export function utilityClassCatalog() {
111
124
  ...calendarButtonClassCatalog(),
112
125
  ...dateRangeClassCatalog(),
113
126
  ...listClassCatalog(),
127
+ ...fixtureClassCatalog(),
114
128
  ...fileFieldClassCatalog(),
115
129
  ...articleClassCatalog(),
116
130
  ...documentViewerClassCatalog(),
@@ -119,12 +133,18 @@ export function utilityClassCatalog() {
119
133
  ...checkboxClassCatalog(),
120
134
  ...radioGroupClassCatalog(),
121
135
  ...spinnerClassCatalog(),
136
+ ...skeletonClassCatalog(),
137
+ ...emptyStateClassCatalog(),
122
138
  ...progressClassCatalog(),
123
139
  ...noticeClassCatalog(),
124
140
  ...glyphTileClassCatalog(),
125
141
  ...tooltipClassCatalog(),
126
142
  ...infoTipClassCatalog(),
127
143
  ...separatorClassCatalog(),
144
+ ...bandClassCatalog(),
145
+ ...heroClassCatalog(),
146
+ ...siteFooterClassCatalog(),
147
+ ...siteHeaderClassCatalog(),
128
148
  ...statTileClassCatalog(),
129
149
  ...descriptionListClassCatalog(),
130
150
  ...tabsClassCatalog(),
package/dist/index.d.ts CHANGED
@@ -16,6 +16,8 @@ export { listGroupVariants, listRowTitleAppearances, listRowTones, listRowValueT
16
16
  export { listTileColumnCounts, type ListGroupTileColumns, } from './css/css-list-tiles.js';
17
17
  export { Checkbox, type CheckboxProps } from './components/Checkbox.js';
18
18
  export { Spinner, type SpinnerProps, type SpinnerSize, } from './components/Spinner.js';
19
+ export { Skeleton, skeletonVariants, type SkeletonProps, type SkeletonVariant, } from './components/Skeleton.js';
20
+ export { EmptyState, emptyStateTitleElements, type EmptyStateProps, type EmptyStateTitleElement, } from './components/EmptyState.js';
19
21
  export { GlyphTile, glyphTileSizes, type GlyphTileHue, type GlyphTileProps, type GlyphTileSize, } from './components/GlyphTile.js';
20
22
  export { Notice, noticeTones, noticeVariants, type NoticeProps, type NoticeRole, type NoticeTone, type NoticeVariant, } from './components/Notice.js';
21
23
  export { Progress, progressTones, type ProgressProps, type ProgressTone, } from './components/Progress.js';
@@ -31,6 +33,7 @@ export { LineChart, type LineChartCurve, type LineChartMarker, type LineChartPer
31
33
  export { DataBar, type DataBarProps, type DataBarTone, dataBarTones, } from './components/DataBar.js';
32
34
  export { Pagination, type PaginationLabels, type PaginationProps, } from './components/Pagination.js';
33
35
  export { Button, type ButtonDisabledAppearance, type ButtonProps, type ButtonSize, type ButtonVariant, type ButtonWidth, } from './components/Button.js';
36
+ export { ButtonLink, type ButtonLinkProps } from './components/ButtonLink.js';
34
37
  export { buttonWidths } from './css/css-button-width.js';
35
38
  export { buttonDisabledAppearances, webButtonVariants, } from './css/css-button.js';
36
39
  export { Box, type BoxBorder, type BoxElement, type BoxLink, type BoxProps, } from './components/Box.js';
@@ -52,6 +55,11 @@ export { Split } from './components/Split.js';
52
55
  export type { SplitProps } from './components/Split.js';
53
56
  export { Nav, navAppearances, type NavAppearance, type NavProps, } from './components/Nav.js';
54
57
  export { NavCount, navCountTones, type NavCountProps, type NavCountTone, } from './components/NavCount.js';
58
+ export { FixtureGroup, type FixtureGroupProps, } from './components/FixtureGroup.js';
59
+ export { FixtureRow, type FixtureRowProps, type FixtureSide, type FixtureStatus, } from './components/FixtureRow.js';
60
+ export { CommandPalette, commandPaletteShortcuts, type CommandPaletteGroup, type CommandPaletteItem, type CommandPaletteProps, type CommandPaletteShortcut, } from './components/CommandPalette.js';
61
+ export { CommandPaletteTrigger, type CommandPaletteTriggerProps, } from './components/CommandPaletteTrigger.js';
62
+ export { ContextSwitcher, contextSwitcherTriggerAppearances, contextSwitcherWidths, type ContextSwitcherAction, type ContextSwitcherBadge, type ContextSwitcherFilter, type ContextSwitcherGroup, type ContextSwitcherOption, type ContextSwitcherProps, type ContextSwitcherTriggerAppearance, type ContextSwitcherWidth, } from './components/ContextSwitcher.js';
55
63
  export { AppShell, type AppShellLabels, type AppShellNavGroup, type AppShellNavItem, type AppShellProps, } from './components/AppShell.js';
56
64
  export { SectionNav, sectionNavAppearances, type SectionNavAppearance, type SectionNavItem, type SectionNavProps, } from './components/SectionNav.js';
57
65
  export { SegmentedControl, type SegmentedControlProps, type SegmentedControlVariant, segmentedSizes, type SegmentedSize, type SegmentedItem, } from './components/SegmentedControl.js';
@@ -68,12 +76,20 @@ export { utilityClassCatalog } from './css/stylesheet.js';
68
76
  export type { VisibilityProps } from './visibility-classes.js';
69
77
  export type { Breakpoint, BreakpointDirection, VisibilityBreakpoint, } from './css/breakpoints.js';
70
78
  export { breakpointQuery } from './css/breakpoints.js';
79
+ export { Band, bandElements, bandTones, bandWidths, } from './components/Band.js';
80
+ export type { BandElement, BandProps, BandTone, BandWidth, } from './components/Band.js';
81
+ export { SiteHeader } from './components/SiteHeader.js';
82
+ export type { SiteHeaderItem, SiteHeaderLabels, SiteHeaderProps, } from './components/SiteHeader.js';
83
+ export { Hero } from './components/Hero.js';
84
+ export type { HeroProps } from './components/Hero.js';
85
+ export { SiteFooter } from './components/SiteFooter.js';
86
+ export type { SiteFooterGroup, SiteFooterLink, SiteFooterProps, } from './components/SiteFooter.js';
71
87
  export { Separator } from './components/Separator.js';
72
88
  export type { SeparatorOrientation, SeparatorProps, } from './components/Separator.js';
73
89
  export { DescriptionItem, DescriptionList, descriptionListLayouts, } from './components/DescriptionList.js';
74
90
  export type { DescriptionItemProps, DescriptionListLayout, DescriptionListProps, } from './components/DescriptionList.js';
75
- export { Grid } from './components/Grid.js';
76
- export type { GridColumns, GridProps } from './components/Grid.js';
91
+ export { Grid, gridFits } from './components/Grid.js';
92
+ export type { GridColumns, GridFit, GridProps } from './components/Grid.js';
77
93
  export type { GridColumnSpan } from './css/css-grid-span.js';
78
94
  export type { ColumnSpanProps } from './column-span-classes.js';
79
95
  export { DenominationGrid, denominationCellToneAppearances, denominationGridFrames, denominationLabelAppearances, denominationNegativeAppearances, denominationTotalEmphases, denominationTransposeBreakpoints, } from './components/DenominationGrid.js';