@scalewing/react 1.48.0 → 1.50.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 (46) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +75 -2
  3. package/dist/components/EmptyState.d.ts +23 -0
  4. package/dist/components/EmptyState.js +40 -0
  5. package/dist/components/Grid.d.ts +11 -3
  6. package/dist/components/Grid.js +13 -4
  7. package/dist/components/Hero.d.ts +26 -0
  8. package/dist/components/Hero.js +23 -0
  9. package/dist/components/ScreenPreview.d.ts +25 -0
  10. package/dist/components/ScreenPreview.js +20 -0
  11. package/dist/components/Stepper.d.ts +11 -1
  12. package/dist/components/Stepper.js +10 -8
  13. package/dist/components/Text.js +3 -0
  14. package/dist/components/screen-preview/PreviewGroup.d.ts +8 -0
  15. package/dist/components/screen-preview/PreviewGroup.js +8 -0
  16. package/dist/components/screen-preview/PreviewRow.d.ts +15 -0
  17. package/dist/components/screen-preview/PreviewRow.js +11 -0
  18. package/dist/components/screen-preview/PreviewTiles.d.ts +16 -0
  19. package/dist/components/screen-preview/PreviewTiles.js +15 -0
  20. package/dist/components/stepper/StepperCountFrame.d.ts +15 -0
  21. package/dist/components/stepper/StepperCountFrame.js +25 -0
  22. package/dist/css/css-components.js +9 -0
  23. package/dist/css/css-document.js +3 -0
  24. package/dist/css/css-empty-state.d.ts +2 -0
  25. package/dist/css/css-empty-state.js +77 -0
  26. package/dist/css/css-grid-span.js +5 -2
  27. package/dist/css/css-grid.d.ts +13 -0
  28. package/dist/css/css-grid.js +17 -1
  29. package/dist/css/css-hero.d.ts +2 -0
  30. package/dist/css/css-hero.js +62 -0
  31. package/dist/css/css-screen-preview.d.ts +10 -0
  32. package/dist/css/css-screen-preview.js +232 -0
  33. package/dist/css/css-stepper-unit.d.ts +9 -0
  34. package/dist/css/css-stepper-unit.js +102 -0
  35. package/dist/css/css-stepper.js +5 -1
  36. package/dist/css/css-theme-frame.d.ts +10 -0
  37. package/dist/css/css-theme-frame.js +26 -0
  38. package/dist/css/stylesheet.js +6 -0
  39. package/dist/index.d.ts +13 -2
  40. package/dist/index.js +8 -1
  41. package/dist/stepper-count.d.ts +8 -0
  42. package/dist/stepper-count.js +17 -0
  43. package/dist/styles.css +393 -1
  44. package/dist/theme/ThemeProvider.d.ts +10 -1
  45. package/dist/theme/ThemeProvider.js +4 -2
  46. package/package.json +2 -2
@@ -0,0 +1,26 @@
1
+ /**
2
+ * How the themed root lays out its children: `none` (default) leaves them
3
+ * in the document's flow; `site` is a public site's page, a column at least
4
+ * the window's height whose last child (the footer) is pushed to its foot,
5
+ * so a short page's footer still meets the window's foot.
6
+ */
7
+ export const themeFrames = ['none', 'site'];
8
+ export function assertThemeFrame(frame) {
9
+ if (!themeFrames.includes(frame))
10
+ throw new RangeError(`Unknown ThemeProvider frame: ${String(frame)}`);
11
+ }
12
+ /*
13
+ * The themed root already keeps the window's height (the document canvas);
14
+ * the site frame makes it a column and gives its last child the space the
15
+ * content leaves above it.
16
+ */
17
+ export function cssThemeFrameRules() {
18
+ return `[data-theme][data-frame='site'] {
19
+ display: flex;
20
+ flex-direction: column;
21
+ }
22
+
23
+ [data-theme][data-frame='site'] > :last-child {
24
+ margin-top: auto;
25
+ }`;
26
+ }
@@ -19,6 +19,7 @@ import { countPillClassCatalog } from './css-count-pill.js';
19
19
  import { checkboxClassCatalog } from './css-checkbox.js';
20
20
  import { radioGroupClassCatalog } from './css-radio-group.js';
21
21
  import { skeletonClassCatalog } from './css-skeleton.js';
22
+ import { emptyStateClassCatalog } from './css-empty-state.js';
22
23
  import { spinnerClassCatalog } from './css-spinner.js';
23
24
  import { progressClassCatalog } from './css-progress.js';
24
25
  import { noticeClassCatalog } from './css-notice.js';
@@ -27,6 +28,8 @@ import { tooltipClassCatalog } from './css-tooltip.js';
27
28
  import { infoTipClassCatalog } from './css-info-tip.js';
28
29
  import { separatorClassCatalog } from './css-separator.js';
29
30
  import { bandClassCatalog } from './css-band.js';
31
+ import { screenPreviewClassCatalog } from './css-screen-preview.js';
32
+ import { heroClassCatalog } from './css-hero.js';
30
33
  import { siteFooterClassCatalog } from './css-site-footer.js';
31
34
  import { siteHeaderClassCatalog } from './css-site-header.js';
32
35
  import { statTileClassCatalog } from './css-stat-tile.js';
@@ -132,6 +135,7 @@ export function utilityClassCatalog() {
132
135
  ...radioGroupClassCatalog(),
133
136
  ...spinnerClassCatalog(),
134
137
  ...skeletonClassCatalog(),
138
+ ...emptyStateClassCatalog(),
135
139
  ...progressClassCatalog(),
136
140
  ...noticeClassCatalog(),
137
141
  ...glyphTileClassCatalog(),
@@ -139,6 +143,8 @@ export function utilityClassCatalog() {
139
143
  ...infoTipClassCatalog(),
140
144
  ...separatorClassCatalog(),
141
145
  ...bandClassCatalog(),
146
+ ...screenPreviewClassCatalog(),
147
+ ...heroClassCatalog(),
142
148
  ...siteFooterClassCatalog(),
143
149
  ...siteHeaderClassCatalog(),
144
150
  ...statTileClassCatalog(),
package/dist/index.d.ts CHANGED
@@ -17,6 +17,7 @@ export { listTileColumnCounts, type ListGroupTileColumns, } from './css/css-list
17
17
  export { Checkbox, type CheckboxProps } from './components/Checkbox.js';
18
18
  export { Spinner, type SpinnerProps, type SpinnerSize, } from './components/Spinner.js';
19
19
  export { Skeleton, skeletonVariants, type SkeletonProps, type SkeletonVariant, } from './components/Skeleton.js';
20
+ export { EmptyState, emptyStateTitleElements, type EmptyStateProps, type EmptyStateTitleElement, } from './components/EmptyState.js';
20
21
  export { GlyphTile, glyphTileSizes, type GlyphTileHue, type GlyphTileProps, type GlyphTileSize, } from './components/GlyphTile.js';
21
22
  export { Notice, noticeTones, noticeVariants, type NoticeProps, type NoticeRole, type NoticeTone, type NoticeVariant, } from './components/Notice.js';
22
23
  export { Progress, progressTones, type ProgressProps, type ProgressTone, } from './components/Progress.js';
@@ -71,6 +72,7 @@ export { Table, TableBody, TableCell, TableFooter, TableHeader, TableRow, tableC
71
72
  export { Text, type TextAlign, type TextElement, type TextProps, } from './components/Text.js';
72
73
  export { ThemeProvider, useTheme, type ThemeProviderProps, } from './theme/ThemeProvider.js';
73
74
  export { themeCanvases, type ThemeCanvas } from './css/css-canvas-grouped.js';
75
+ export { themeFrames, type ThemeFrame } from './css/css-theme-frame.js';
74
76
  export { utilityClassCatalog } from './css/stylesheet.js';
75
77
  export type { VisibilityProps } from './visibility-classes.js';
76
78
  export type { Breakpoint, BreakpointDirection, VisibilityBreakpoint, } from './css/breakpoints.js';
@@ -79,14 +81,23 @@ export { Band, bandElements, bandTones, bandWidths, } from './components/Band.js
79
81
  export type { BandElement, BandProps, BandTone, BandWidth, } from './components/Band.js';
80
82
  export { SiteHeader } from './components/SiteHeader.js';
81
83
  export type { SiteHeaderItem, SiteHeaderLabels, SiteHeaderProps, } from './components/SiteHeader.js';
84
+ export { ScreenPreview, screenPreviewFrames, } from './components/ScreenPreview.js';
85
+ export type { ScreenPreviewFrame, ScreenPreviewProps, } from './components/ScreenPreview.js';
86
+ export { PreviewGroup } from './components/screen-preview/PreviewGroup.js';
87
+ export { PreviewRow, previewRowKinds, } from './components/screen-preview/PreviewRow.js';
88
+ export type { PreviewRowKind, PreviewRowProps, } from './components/screen-preview/PreviewRow.js';
89
+ export { PreviewTiles } from './components/screen-preview/PreviewTiles.js';
90
+ export type { PreviewTile, PreviewTilesProps, } from './components/screen-preview/PreviewTiles.js';
91
+ export { Hero } from './components/Hero.js';
92
+ export type { HeroProps } from './components/Hero.js';
82
93
  export { SiteFooter } from './components/SiteFooter.js';
83
94
  export type { SiteFooterGroup, SiteFooterLink, SiteFooterProps, } from './components/SiteFooter.js';
84
95
  export { Separator } from './components/Separator.js';
85
96
  export type { SeparatorOrientation, SeparatorProps, } from './components/Separator.js';
86
97
  export { DescriptionItem, DescriptionList, descriptionListLayouts, } from './components/DescriptionList.js';
87
98
  export type { DescriptionItemProps, DescriptionListLayout, DescriptionListProps, } from './components/DescriptionList.js';
88
- export { Grid } from './components/Grid.js';
89
- export type { GridColumns, GridProps } from './components/Grid.js';
99
+ export { Grid, gridFits } from './components/Grid.js';
100
+ export type { GridColumns, GridFit, GridProps } from './components/Grid.js';
90
101
  export type { GridColumnSpan } from './css/css-grid-span.js';
91
102
  export type { ColumnSpanProps } from './column-span-classes.js';
92
103
  export { DenominationGrid, denominationCellToneAppearances, denominationGridFrames, denominationLabelAppearances, denominationNegativeAppearances, denominationTotalEmphases, denominationTransposeBreakpoints, } from './components/DenominationGrid.js';
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ export { listTileColumnCounts, } from './css/css-list-tiles.js';
16
16
  export { Checkbox } from './components/Checkbox.js';
17
17
  export { Spinner, } from './components/Spinner.js';
18
18
  export { Skeleton, skeletonVariants, } from './components/Skeleton.js';
19
+ export { EmptyState, emptyStateTitleElements, } from './components/EmptyState.js';
19
20
  export { GlyphTile, glyphTileSizes, } from './components/GlyphTile.js';
20
21
  export { Notice, noticeTones, noticeVariants, } from './components/Notice.js';
21
22
  export { Progress, progressTones, } from './components/Progress.js';
@@ -67,14 +68,20 @@ export { Table, TableBody, TableCell, TableFooter, TableHeader, TableRow, tableC
67
68
  export { Text, } from './components/Text.js';
68
69
  export { ThemeProvider, useTheme, } from './theme/ThemeProvider.js';
69
70
  export { themeCanvases } from './css/css-canvas-grouped.js';
71
+ export { themeFrames } from './css/css-theme-frame.js';
70
72
  export { utilityClassCatalog } from './css/stylesheet.js';
71
73
  export { breakpointQuery } from './css/breakpoints.js';
72
74
  export { Band, bandElements, bandTones, bandWidths, } from './components/Band.js';
73
75
  export { SiteHeader } from './components/SiteHeader.js';
76
+ export { ScreenPreview, screenPreviewFrames, } from './components/ScreenPreview.js';
77
+ export { PreviewGroup } from './components/screen-preview/PreviewGroup.js';
78
+ export { PreviewRow, previewRowKinds, } from './components/screen-preview/PreviewRow.js';
79
+ export { PreviewTiles } from './components/screen-preview/PreviewTiles.js';
80
+ export { Hero } from './components/Hero.js';
74
81
  export { SiteFooter } from './components/SiteFooter.js';
75
82
  export { Separator } from './components/Separator.js';
76
83
  export { DescriptionItem, DescriptionList, descriptionListLayouts, } from './components/DescriptionList.js';
77
- export { Grid } from './components/Grid.js';
84
+ export { Grid, gridFits } from './components/Grid.js';
78
85
  export { DenominationGrid, denominationCellToneAppearances, denominationGridFrames, denominationLabelAppearances, denominationNegativeAppearances, denominationTotalEmphases, denominationTransposeBreakpoints, } from './components/DenominationGrid.js';
79
86
  export { FilterChips, filterChipCountAppearances, filterChipsOverflows, filterChipTones, } from './components/FilterChips.js';
80
87
  export { FilterChipsRow } from './components/FilterChipsRow.js';
@@ -35,3 +35,11 @@ export declare function stepperMoves(value: number | null, bounds: StepperBounds
35
35
  export declare function readStepperEntry(text: string, allowsNegative: boolean): StepperEntry;
36
36
  /** The box's text for a count: the plain number, or empty for none. */
37
37
  export declare function stepperText(value: number | null): string;
38
+ /** A consumer bug: a unit, when given, is a word to show after the count. */
39
+ export declare function assertStepperUnit(unit: string | undefined): void;
40
+ /**
41
+ * The count in words for assistive technology: the consumer's own words
42
+ * when given, otherwise the count and its unit ("90 min"), or nothing extra
43
+ * (the bare count is `aria-valuenow`) when there is no unit or no count.
44
+ */
45
+ export declare function stepperValueText(value: number | null, unit: string | undefined, valueText: string | undefined): string | undefined;
@@ -48,3 +48,20 @@ export function readStepperEntry(text, allowsNegative) {
48
48
  export function stepperText(value) {
49
49
  return value === null ? '' : String(value);
50
50
  }
51
+ /** A consumer bug: a unit, when given, is a word to show after the count. */
52
+ export function assertStepperUnit(unit) {
53
+ if (unit !== undefined && unit.trim() === '')
54
+ throw new RangeError('Stepper unit must not be blank');
55
+ }
56
+ /**
57
+ * The count in words for assistive technology: the consumer's own words
58
+ * when given, otherwise the count and its unit ("90 min"), or nothing extra
59
+ * (the bare count is `aria-valuenow`) when there is no unit or no count.
60
+ */
61
+ export function stepperValueText(value, unit, valueText) {
62
+ if (valueText !== undefined)
63
+ return valueText;
64
+ if (unit === undefined || value === null)
65
+ return undefined;
66
+ return `${value} ${unit.trim()}`;
67
+ }
package/dist/styles.css CHANGED
@@ -632,6 +632,15 @@ body {
632
632
  background-color: var(--sw-canvas-grouped);
633
633
  }
634
634
 
635
+ [data-theme][data-frame='site'] {
636
+ display: flex;
637
+ flex-direction: column;
638
+ }
639
+
640
+ [data-theme][data-frame='site'] > :last-child {
641
+ margin-top: auto;
642
+ }
643
+
635
644
  [data-theme] a {
636
645
  color: var(--sw-color-accent);
637
646
  text-decoration: none;
@@ -894,19 +903,25 @@ body {
894
903
  .sw-text-align-center { text-align: center; }
895
904
  .sw-text-align-end { text-align: end; }
896
905
 
897
- :where(.sw-text-display, .sw-text-heading, .sw-text-title, .sw-text-body, .sw-text-label, .sw-text-caption, .sw-text-data) { margin: 0; }
906
+ :where(.sw-text-hero, .sw-text-display, .sw-text-headline, .sw-text-heading, .sw-text-title, .sw-text-lead, .sw-text-body, .sw-text-label, .sw-text-caption, .sw-text-data) { margin: 0; }
898
907
 
908
+ .sw-text-hero { font-family: var(--sw-font-sans); font-size: 56px; line-height: 60px; font-weight: 700; letter-spacing: -1.7px; }
899
909
  .sw-text-display { font-family: var(--sw-font-sans); font-size: 40px; line-height: 48px; font-weight: 600; letter-spacing: -0.8px; }
910
+ .sw-text-headline { font-family: var(--sw-font-sans); font-size: 36px; line-height: 40px; font-weight: 700; letter-spacing: -0.7px; }
900
911
  .sw-text-heading { font-family: var(--sw-font-sans); font-size: 28px; line-height: 34px; font-weight: 600; letter-spacing: -0.45px; }
901
912
  .sw-text-title { font-family: var(--sw-font-sans); font-size: 20px; line-height: 28px; font-weight: 600; letter-spacing: -0.3px; }
913
+ .sw-text-lead { font-family: var(--sw-font-sans); font-size: 20px; line-height: 29px; font-weight: 400; letter-spacing: -0.3px; }
902
914
  .sw-text-body { font-family: var(--sw-font-sans); font-size: 17px; line-height: 25px; font-weight: 400; letter-spacing: -0.2px; }
903
915
  .sw-text-label { font-family: var(--sw-font-sans); font-size: 15px; line-height: 20px; font-weight: 600; letter-spacing: -0.2px; }
904
916
  .sw-text-caption { font-family: var(--sw-font-sans); font-size: 13px; line-height: 18px; font-weight: 400; letter-spacing: -0.08px; }
905
917
  .sw-text-data { font-family: var(--sw-font-sans); font-size: 13px; line-height: 18px; font-weight: 500; letter-spacing: -0.08px; font-variant-numeric: tabular-nums; }
906
918
 
907
919
  @media not all and (min-width: 48rem) {
920
+ .sw-text-hero { font-size: 36px; line-height: 40px; letter-spacing: -0.7px; }
908
921
  .sw-text-display { font-size: 32px; line-height: 38px; letter-spacing: -0.6px; }
922
+ .sw-text-headline { font-size: 26px; line-height: 30px; letter-spacing: -0.4px; }
909
923
  .sw-text-heading { font-size: 24px; line-height: 30px; letter-spacing: -0.4px; }
924
+ .sw-text-lead { font-size: 17px; line-height: 25px; letter-spacing: -0.2px; }
910
925
  }
911
926
 
912
927
  [data-theme] .sw-font-mono,
@@ -4600,6 +4615,219 @@ body {
4600
4615
  .sw-band-inverse { border-block: 1px solid CanvasText; }
4601
4616
  }
4602
4617
 
4618
+ .sw-screen-preview {
4619
+ display: flex;
4620
+ flex-direction: column;
4621
+ gap: var(--sw-space-2);
4622
+ margin: 0;
4623
+ max-width: 100%;
4624
+ min-width: 0;
4625
+ }
4626
+
4627
+ .sw-screen-preview-screen {
4628
+ background: var(--sw-color-surface);
4629
+ border-radius: var(--sw-radius-md);
4630
+ color: var(--sw-color-text);
4631
+ display: flex;
4632
+ flex-direction: column;
4633
+ font-family: var(--sw-font-sans);
4634
+ font-size: 15px;
4635
+ font-variant-numeric: tabular-nums;
4636
+ gap: var(--sw-space-3);
4637
+ line-height: 20px;
4638
+ padding: var(--sw-space-4);
4639
+ }
4640
+
4641
+ .sw-screen-preview-header {
4642
+ display: flex;
4643
+ flex-direction: column;
4644
+ }
4645
+
4646
+ .sw-screen-preview-eyebrow {
4647
+ color: var(--sw-color-muted);
4648
+ font-size: 13px;
4649
+ line-height: 18px;
4650
+ }
4651
+
4652
+ .sw-screen-preview-title {
4653
+ font-size: 20px;
4654
+ font-weight: 600;
4655
+ line-height: 28px;
4656
+ }
4657
+
4658
+ .sw-screen-preview-body {
4659
+ display: flex;
4660
+ flex-direction: column;
4661
+ gap: var(--sw-space-2);
4662
+ }
4663
+
4664
+ .sw-preview-group {
4665
+ display: flex;
4666
+ flex-direction: column;
4667
+ gap: var(--sw-space-2);
4668
+ }
4669
+
4670
+ .sw-preview-group + .sw-preview-group {
4671
+ border-top: 1px solid var(--sw-color-border);
4672
+ padding-top: var(--sw-space-2);
4673
+ }
4674
+
4675
+ .sw-screen-preview-caption {
4676
+ color: var(--sw-color-muted);
4677
+ font-size: 13px;
4678
+ line-height: 18px;
4679
+ }
4680
+
4681
+ .sw-preview-row {
4682
+ display: flex;
4683
+ gap: var(--sw-space-3);
4684
+ justify-content: space-between;
4685
+ min-width: 0;
4686
+ }
4687
+
4688
+ .sw-preview-row-value {
4689
+ text-align: end;
4690
+ }
4691
+
4692
+ .sw-preview-row-total {
4693
+ border-top: 1px solid var(--sw-color-border);
4694
+ font-weight: 600;
4695
+ padding-top: var(--sw-space-2);
4696
+ }
4697
+
4698
+ .sw-preview-row-note {
4699
+ flex-direction: column;
4700
+ gap: 0;
4701
+ }
4702
+
4703
+ .sw-preview-row-note .sw-preview-row-label {
4704
+ color: var(--sw-color-muted);
4705
+ font-size: 13px;
4706
+ line-height: 18px;
4707
+ }
4708
+
4709
+ .sw-preview-row-note .sw-preview-row-value {
4710
+ text-align: start;
4711
+ }
4712
+
4713
+ .sw-preview-row-filled,
4714
+ .sw-preview-row-alert {
4715
+ border-radius: var(--sw-radius-sm);
4716
+ padding: var(--sw-space-2) var(--sw-space-3);
4717
+ }
4718
+
4719
+ .sw-preview-row-filled {
4720
+ background: var(--sw-color-subtle);
4721
+ }
4722
+
4723
+ .sw-preview-row-alert {
4724
+ background: color-mix(in srgb, var(--sw-color-danger) 10%, var(--sw-color-surface));
4725
+ color: color-mix(in srgb, var(--sw-color-danger) 70%, var(--sw-color-text));
4726
+ }
4727
+
4728
+ .sw-preview-tiles {
4729
+ display: grid;
4730
+ gap: var(--sw-space-2);
4731
+ grid-template-columns: repeat(3, minmax(0, 1fr));
4732
+ }
4733
+
4734
+ .sw-preview-tile {
4735
+ align-items: center;
4736
+ background: var(--sw-color-subtle);
4737
+ border-radius: var(--sw-radius-sm);
4738
+ display: flex;
4739
+ flex-direction: column;
4740
+ min-width: 0;
4741
+ padding: var(--sw-space-2);
4742
+ }
4743
+
4744
+ .sw-preview-tile-label {
4745
+ color: var(--sw-color-muted);
4746
+ font-size: 13px;
4747
+ line-height: 18px;
4748
+ }
4749
+
4750
+ @media (min-width: 48rem) {
4751
+ .sw-screen-preview-card .sw-screen-preview-screen { padding: var(--sw-space-5); }
4752
+ .sw-preview-tiles { grid-template-columns: repeat(6, minmax(0, 1fr)); }
4753
+ .sw-screen-preview-device { width: 20rem; }
4754
+ .sw-screen-preview-device .sw-screen-preview-bezel {
4755
+ background: var(--sw-color-text);
4756
+ border-radius: calc(var(--sw-radius-lg) + var(--sw-space-3));
4757
+ padding: var(--sw-space-3);
4758
+ }
4759
+ .sw-screen-preview-device .sw-screen-preview-screen {
4760
+ background: var(--sw-color-subtle);
4761
+ border-radius: var(--sw-radius-lg);
4762
+ gap: 0;
4763
+ overflow: hidden;
4764
+ padding: 0;
4765
+ }
4766
+ .sw-screen-preview-device .sw-screen-preview-header {
4767
+ background: var(--sw-color-surface);
4768
+ border-bottom: 1px solid var(--sw-color-border);
4769
+ padding: var(--sw-space-4);
4770
+ }
4771
+ .sw-screen-preview-device .sw-screen-preview-body { gap: var(--sw-space-3); padding: var(--sw-space-3); }
4772
+ .sw-screen-preview-device .sw-preview-group {
4773
+ background: var(--sw-color-surface);
4774
+ border-radius: var(--sw-radius-md);
4775
+ padding: var(--sw-space-3);
4776
+ }
4777
+ .sw-screen-preview-device .sw-preview-group + .sw-preview-group { border-top: 0; }
4778
+ .sw-screen-preview-device .sw-screen-preview-caption { text-align: center; }
4779
+ }
4780
+
4781
+ @media (forced-colors: active) {
4782
+ .sw-screen-preview-screen { border: 1px solid CanvasText; }
4783
+ }
4784
+
4785
+ @media (forced-colors: active) and (min-width: 48rem) {
4786
+ .sw-screen-preview-device .sw-screen-preview-screen { border: 0; }
4787
+ .sw-screen-preview-device .sw-screen-preview-bezel { border: 1px solid CanvasText; }
4788
+ }
4789
+
4790
+ .sw-hero {
4791
+ align-items: center;
4792
+ display: grid;
4793
+ gap: var(--sw-space-8);
4794
+ min-width: 0;
4795
+ }
4796
+
4797
+ .sw-hero-text {
4798
+ display: flex;
4799
+ flex-direction: column;
4800
+ gap: var(--sw-space-4);
4801
+ min-width: 0;
4802
+ }
4803
+
4804
+ .sw-hero:not(.sw-hero-with-media) .sw-hero-text {
4805
+ max-width: var(--sw-reading-max);
4806
+ }
4807
+
4808
+ .sw-hero-actions {
4809
+ display: flex;
4810
+ flex-wrap: wrap;
4811
+ gap: var(--sw-space-3);
4812
+ padding-top: var(--sw-space-1);
4813
+ }
4814
+
4815
+ .sw-hero-media {
4816
+ justify-self: center;
4817
+ max-width: 100%;
4818
+ min-width: 0;
4819
+ }
4820
+
4821
+ @media (min-width: 48rem) {
4822
+ .sw-hero-text { gap: var(--sw-space-5); }
4823
+ .sw-hero-with-media { grid-template-columns: minmax(0, 1fr) auto; }
4824
+ }
4825
+
4826
+ @media not all and (min-width: 48rem) {
4827
+ .sw-hero { gap: var(--sw-space-6); }
4828
+ .sw-hero-actions { align-items: stretch; flex-direction: column; }
4829
+ }
4830
+
4603
4831
  .sw-site-footer-top {
4604
4832
  display: grid;
4605
4833
  gap: var(--sw-space-6) var(--sw-space-5);
@@ -7141,6 +7369,62 @@ body {
7141
7369
  .sw-skeleton-row + .sw-skeleton-row { border-color: GrayText; }
7142
7370
  }
7143
7371
 
7372
+ .sw-empty-state {
7373
+ align-items: center;
7374
+ background: var(--sw-color-surface);
7375
+ border: 1px dashed var(--sw-color-border);
7376
+ border-radius: var(--sw-radius-md);
7377
+ box-sizing: border-box;
7378
+ display: flex;
7379
+ flex-direction: column;
7380
+ gap: var(--sw-space-3);
7381
+ min-width: 0;
7382
+ overflow-wrap: anywhere;
7383
+ padding: var(--sw-space-8) var(--sw-space-4);
7384
+ text-align: center;
7385
+ width: 100%;
7386
+ }
7387
+
7388
+ .sw-empty-state-icon {
7389
+ align-items: center;
7390
+ background: var(--sw-color-subtle);
7391
+ border-radius: var(--sw-radius-md);
7392
+ color: var(--sw-color-muted);
7393
+ display: inline-flex;
7394
+ flex: none;
7395
+ height: var(--sw-space-8);
7396
+ justify-content: center;
7397
+ width: var(--sw-space-8);
7398
+ }
7399
+
7400
+ .sw-empty-state-icon > svg {
7401
+ height: var(--sw-space-5);
7402
+ width: var(--sw-space-5);
7403
+ }
7404
+
7405
+ .sw-empty-state-title,
7406
+ .sw-empty-state-description {
7407
+ margin: 0;
7408
+ max-width: var(--sw-reading-max);
7409
+ }
7410
+
7411
+ .sw-empty-state-actions {
7412
+ display: flex;
7413
+ flex-wrap: wrap;
7414
+ gap: var(--sw-space-2);
7415
+ justify-content: center;
7416
+ margin-top: var(--sw-space-1);
7417
+ }
7418
+
7419
+ @media (pointer: coarse) {
7420
+ .sw-empty-state-actions .sw-button { min-height: var(--sw-control-md-min-height); }
7421
+ }
7422
+
7423
+ @media (forced-colors: active) {
7424
+ .sw-empty-state { border-color: CanvasText; }
7425
+ .sw-empty-state-icon { color: CanvasText; }
7426
+ }
7427
+
7144
7428
  .sw-progress {
7145
7429
  display: flex;
7146
7430
  flex-direction: column;
@@ -7868,6 +8152,9 @@ body {
7868
8152
  .sw-grid-cols-below-md-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
7869
8153
  .sw-grid-cols-below-md-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
7870
8154
  }
8155
+ .sw-grid-fit-narrow { grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); }
8156
+ .sw-grid-fit-medium { grid-template-columns: repeat(auto-fit, minmax(min(100%, 16.25rem), 1fr)); }
8157
+ .sw-grid-fit-wide { grid-template-columns: repeat(auto-fit, minmax(min(100%, 18.75rem), 1fr)); }
7871
8158
  .sw-grid-span-1 { grid-column: span 1; }
7872
8159
  .sw-grid-span-2 { grid-column: span 2; }
7873
8160
  .sw-grid-span-3 { grid-column: span 3; }
@@ -7883,6 +8170,18 @@ body {
7883
8170
  :where(.sw-grid-cols-3) > .sw-grid-span-4 { grid-column: span 3; }
7884
8171
  :where(.sw-grid-cols-3) > .sw-grid-span-6 { grid-column: span 3; }
7885
8172
  :where(.sw-grid-cols-4) > .sw-grid-span-6 { grid-column: span 4; }
8173
+ :where(.sw-grid-fit-narrow) > .sw-grid-span-2 { grid-column: auto; }
8174
+ :where(.sw-grid-fit-narrow) > .sw-grid-span-3 { grid-column: auto; }
8175
+ :where(.sw-grid-fit-narrow) > .sw-grid-span-4 { grid-column: auto; }
8176
+ :where(.sw-grid-fit-narrow) > .sw-grid-span-6 { grid-column: auto; }
8177
+ :where(.sw-grid-fit-medium) > .sw-grid-span-2 { grid-column: auto; }
8178
+ :where(.sw-grid-fit-medium) > .sw-grid-span-3 { grid-column: auto; }
8179
+ :where(.sw-grid-fit-medium) > .sw-grid-span-4 { grid-column: auto; }
8180
+ :where(.sw-grid-fit-medium) > .sw-grid-span-6 { grid-column: auto; }
8181
+ :where(.sw-grid-fit-wide) > .sw-grid-span-2 { grid-column: auto; }
8182
+ :where(.sw-grid-fit-wide) > .sw-grid-span-3 { grid-column: auto; }
8183
+ :where(.sw-grid-fit-wide) > .sw-grid-span-4 { grid-column: auto; }
8184
+ :where(.sw-grid-fit-wide) > .sw-grid-span-6 { grid-column: auto; }
7886
8185
  @media not all and (min-width: 48rem) {
7887
8186
  :where(.sw-grid-cols-below-md-1) > .sw-grid-span-2 { grid-column: span 1; }
7888
8187
  :where(.sw-grid-cols-below-md-1) > .sw-grid-span-3 { grid-column: span 1; }
@@ -8915,6 +9214,99 @@ body {
8915
9214
  [data-theme] .sw-stepper-changed input.sw-stepper-input { border-color: Highlight; box-shadow: inset 0 0 0 1px Highlight; background-image: none; }
8916
9215
  }
8917
9216
 
9217
+ .sw-stepper-count {
9218
+ background-color: var(--sw-glass-fill);
9219
+ border: 1px solid var(--sw-color-border);
9220
+ border-radius: var(--sw-radius-sm);
9221
+ color: inherit;
9222
+ font-family: inherit;
9223
+ font-size: inherit;
9224
+ padding-inline: var(--sw-control-md-padding-inline);
9225
+ align-items: center;
9226
+ box-sizing: border-box;
9227
+ cursor: text;
9228
+ display: inline-flex;
9229
+ gap: var(--sw-space-1);
9230
+ justify-content: center;
9231
+ min-height: var(--sw-control-md-min-height);
9232
+ min-width: 0;
9233
+ padding-inline: var(--sw-space-2);
9234
+ }
9235
+
9236
+ .sw-stepper-full .sw-stepper-count { display: flex; }
9237
+
9238
+ [data-theme] .sw-stepper .sw-stepper-count > input.sw-stepper-input {
9239
+ align-self: stretch;
9240
+ background: transparent;
9241
+ background-image: none;
9242
+ border: 0;
9243
+ border-radius: 0;
9244
+ box-shadow: none;
9245
+ inline-size: 5ch;
9246
+ min-height: 0;
9247
+ padding-inline: 0;
9248
+ text-align: end;
9249
+ }
9250
+
9251
+ [data-theme] .sw-stepper .sw-stepper-count > input.sw-stepper-input:focus-visible { outline: none; }
9252
+
9253
+ .sw-stepper-count:focus-within {
9254
+ outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
9255
+ outline-offset: var(--sw-focus-ring-offset);
9256
+ }
9257
+
9258
+ .sw-stepper-unit {
9259
+ color: var(--sw-color-muted);
9260
+ flex: none;
9261
+ font-size: 17px;
9262
+ line-height: 25px;
9263
+ user-select: none;
9264
+ white-space: nowrap;
9265
+ }
9266
+
9267
+ .sw-stepper-invalid .sw-stepper-count { border-color: var(--sw-color-danger); }
9268
+
9269
+ .sw-stepper-changed .sw-stepper-count {
9270
+ border-color: var(--sw-color-accent);
9271
+ box-shadow: inset 0 0 0 1px var(--sw-color-accent);
9272
+ }
9273
+
9274
+ .sw-stepper-changed .sw-stepper-count:not(:has(> input:placeholder-shown)) { background-image: linear-gradient(color-mix(in srgb, var(--sw-color-accent) 12%, transparent), color-mix(in srgb, var(--sw-color-accent) 12%, transparent)); }
9275
+
9276
+ .sw-stepper-changed .sw-stepper-count:not(:has(> input:placeholder-shown)) > .sw-stepper-unit { color: var(--sw-color-text); }
9277
+
9278
+ /*
9279
+ * The frame draws the surface, so it carries the disabled look for its count,
9280
+ * and only that look: a locked count drops the invalid and changed edges and
9281
+ * tint, which name nothing a person can act on.
9282
+ */
9283
+ .sw-stepper .sw-stepper-count:has(> input:disabled) {
9284
+ background-color: var(--sw-color-subtle);
9285
+ border-style: dashed;
9286
+ cursor: not-allowed;
9287
+ opacity: 1;
9288
+ -webkit-text-fill-color: currentColor;
9289
+ background-image: none;
9290
+ border-color: var(--sw-color-border);
9291
+ box-shadow: none;
9292
+ }
9293
+
9294
+ .sw-stepper .sw-stepper-count:has(> input:disabled) > .sw-stepper-unit {
9295
+ color: var(--sw-color-muted);
9296
+ }
9297
+
9298
+ @media (forced-colors: active) {
9299
+ .sw-stepper-unit { color: CanvasText; }
9300
+ .sw-stepper-invalid .sw-stepper-count { border-color: Mark; }
9301
+ .sw-stepper-changed .sw-stepper-count { border-color: Highlight; box-shadow: inset 0 0 0 1px Highlight; background-image: none; }
9302
+ .sw-stepper .sw-stepper-count:has(> input:disabled) {
9303
+ border-color: GrayText;
9304
+ color: GrayText;
9305
+ -webkit-text-fill-color: GrayText;
9306
+ box-shadow: none;
9307
+ }
9308
+ }
9309
+
8918
9310
  .sw-steps {
8919
9311
  display: flex;
8920
9312
  flex-direction: column;
@@ -1,6 +1,7 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import { type ColorScheme, type PaletteId, type Theme, type ThemeColors } from '@scalewing/tokens';
3
3
  import { type ThemeCanvas } from '../css/css-canvas-grouped.js';
4
+ import { type ThemeFrame } from '../css/css-theme-frame.js';
4
5
  export type ThemeProviderProps = {
5
6
  colorScheme?: ColorScheme | 'system';
6
7
  palette?: PaletteId;
@@ -14,7 +15,15 @@ export type ThemeProviderProps = {
14
15
  * colours keep it. An unknown value throws a `RangeError`.
15
16
  */
16
17
  canvas?: ThemeCanvas;
18
+ /**
19
+ * `none` (default) leaves the children in the document's flow; `site`
20
+ * (opt-in) makes the themed root a public site's page: a column at least
21
+ * the window's height whose last child (the footer) sits at its foot, so
22
+ * a short page's footer meets the window's foot. An unknown value throws
23
+ * a `RangeError`.
24
+ */
25
+ frame?: ThemeFrame;
17
26
  children: ReactNode;
18
27
  };
19
- export declare function ThemeProvider({ colorScheme, palette, colors, canvas, children, }: ThemeProviderProps): import("react").JSX.Element;
28
+ export declare function ThemeProvider({ colorScheme, palette, colors, canvas, frame, children, }: ThemeProviderProps): import("react").JSX.Element;
20
29
  export declare function useTheme(): Theme;
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useEffect, useMemo, useState, } from 'react';
3
3
  import { createTheme, secondaryActionBorder, semanticColorKeys, } from '@scalewing/tokens';
4
4
  import { assertThemeCanvas, } from '../css/css-canvas-grouped.js';
5
+ import { assertThemeFrame } from '../css/css-theme-frame.js';
5
6
  const ThemeContext = createContext(null);
6
7
  function schemeFromMedia() {
7
8
  if (typeof window === 'undefined' ||
@@ -25,8 +26,9 @@ function themeCssVars(theme) {
25
26
  vars['--sw-glass-specular'] = theme.glass.specular;
26
27
  return vars;
27
28
  }
28
- export function ThemeProvider({ colorScheme = 'system', palette, colors, canvas = 'default', children, }) {
29
+ export function ThemeProvider({ colorScheme = 'system', palette, colors, canvas = 'default', frame = 'none', children, }) {
29
30
  assertThemeCanvas(canvas);
31
+ assertThemeFrame(frame);
30
32
  const [systemScheme, setSystemScheme] = useState(schemeFromMedia);
31
33
  useEffect(() => {
32
34
  if (colorScheme !== 'system' || typeof window.matchMedia !== 'function') {
@@ -42,7 +44,7 @@ export function ThemeProvider({ colorScheme = 'system', palette, colors, canvas
42
44
  }, [colorScheme]);
43
45
  const resolvedScheme = colorScheme === 'system' ? systemScheme : colorScheme;
44
46
  const theme = useMemo(() => createTheme({ colorScheme: resolvedScheme, palette, colors }), [colors, palette, resolvedScheme]);
45
- return (_jsx(ThemeContext.Provider, { value: theme, children: _jsx("div", { "data-canvas": canvas === 'default' ? undefined : canvas, "data-palette": palette, "data-theme": theme.colorScheme, style: themeCssVars(theme), children: children }) }));
47
+ return (_jsx(ThemeContext.Provider, { value: theme, children: _jsx("div", { "data-canvas": canvas === 'default' ? undefined : canvas, "data-frame": frame === 'none' ? undefined : frame, "data-palette": palette, "data-theme": theme.colorScheme, style: themeCssVars(theme), children: children }) }));
46
48
  }
47
49
  export function useTheme() {
48
50
  const theme = useContext(ThemeContext);