@scalewing/react 1.40.0 → 1.42.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 (191) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +274 -7
  3. package/dist/calendar-labels.d.ts +2 -0
  4. package/dist/calendar-labels.js +7 -0
  5. package/dist/components/Article.d.ts +60 -0
  6. package/dist/components/Article.js +42 -0
  7. package/dist/components/BarChart.d.ts +20 -4
  8. package/dist/components/BarChart.js +13 -6
  9. package/dist/components/ButtonGroup.d.ts +8 -1
  10. package/dist/components/ButtonGroup.js +11 -2
  11. package/dist/components/DateField.d.ts +14 -2
  12. package/dist/components/DateField.js +14 -11
  13. package/dist/components/DenominationGrid.d.ts +3 -2
  14. package/dist/components/DenominationGrid.js +21 -3
  15. package/dist/components/Dialog.d.ts +29 -13
  16. package/dist/components/Dialog.js +22 -20
  17. package/dist/components/DocumentViewer.d.ts +41 -0
  18. package/dist/components/DocumentViewer.js +72 -0
  19. package/dist/components/Field.d.ts +13 -2
  20. package/dist/components/Field.js +14 -38
  21. package/dist/components/FileField.d.ts +44 -0
  22. package/dist/components/FileField.js +66 -0
  23. package/dist/components/FilterChips.d.ts +7 -37
  24. package/dist/components/FilterChips.js +32 -24
  25. package/dist/components/ListRow.d.ts +33 -3
  26. package/dist/components/ListRow.js +18 -17
  27. package/dist/components/MarkdownView.d.ts +39 -0
  28. package/dist/components/MarkdownView.js +30 -0
  29. package/dist/components/NavCount.d.ts +15 -2
  30. package/dist/components/NavCount.js +16 -6
  31. package/dist/components/SegmentedControl.d.ts +17 -1
  32. package/dist/components/SegmentedControl.js +11 -3
  33. package/dist/components/Switch.d.ts +16 -1
  34. package/dist/components/Switch.js +17 -6
  35. package/dist/components/action-bar/ActionBarSummary.d.ts +10 -2
  36. package/dist/components/action-bar/ActionBarSummary.js +11 -2
  37. package/dist/components/chart/use-chart-width.js +2 -24
  38. package/dist/components/date-field/CalendarEntryButton.d.ts +24 -0
  39. package/dist/components/date-field/CalendarEntryButton.js +16 -0
  40. package/dist/components/date-field/TypedEntry.d.ts +26 -0
  41. package/dist/components/date-field/TypedEntry.js +13 -0
  42. package/dist/components/denomination-grid/CountCell.d.ts +16 -0
  43. package/dist/components/denomination-grid/CountCell.js +14 -0
  44. package/dist/components/denomination-grid/DenominationStrip.d.ts +4 -1
  45. package/dist/components/denomination-grid/DenominationStrip.js +2 -2
  46. package/dist/components/denomination-grid/EntryCell.d.ts +3 -1
  47. package/dist/components/denomination-grid/EntryCell.js +2 -2
  48. package/dist/components/denomination-grid/StripRow.js +1 -10
  49. package/dist/components/denomination-grid/TransposedStrip.d.ts +17 -0
  50. package/dist/components/denomination-grid/TransposedStrip.js +43 -0
  51. package/dist/components/denomination-grid/types.d.ts +31 -0
  52. package/dist/components/denomination-grid/types.js +7 -1
  53. package/dist/components/denomination-grid/validate-options.d.ts +7 -0
  54. package/dist/components/denomination-grid/validate-options.js +27 -0
  55. package/dist/components/dialog/DialogFooter.d.ts +6 -5
  56. package/dist/components/dialog/DialogFooter.js +6 -6
  57. package/dist/components/dialog/validate.d.ts +24 -0
  58. package/dist/components/dialog/validate.js +23 -0
  59. package/dist/components/document-viewer/document-viewer-labels.d.ts +23 -0
  60. package/dist/components/document-viewer/document-viewer-labels.js +23 -0
  61. package/dist/components/document-viewer/page-box.d.ts +8 -0
  62. package/dist/components/document-viewer/page-box.js +12 -0
  63. package/dist/components/document-viewer/pdf-document.d.ts +32 -0
  64. package/dist/components/document-viewer/pdf-document.js +66 -0
  65. package/dist/components/document-viewer/pdf-options.d.ts +36 -0
  66. package/dist/components/document-viewer/pdf-options.js +46 -0
  67. package/dist/components/document-viewer/render-pdf-page.d.ts +20 -0
  68. package/dist/components/document-viewer/render-pdf-page.js +38 -0
  69. package/dist/components/document-viewer/scroll-chain.d.ts +6 -0
  70. package/dist/components/document-viewer/scroll-chain.js +23 -0
  71. package/dist/components/document-viewer/use-error-report.d.ts +5 -0
  72. package/dist/components/document-viewer/use-error-report.js +13 -0
  73. package/dist/components/document-viewer/use-page-render.d.ts +21 -0
  74. package/dist/components/document-viewer/use-page-render.js +70 -0
  75. package/dist/components/document-viewer/use-pdf-document.d.ts +22 -0
  76. package/dist/components/document-viewer/use-pdf-document.js +47 -0
  77. package/dist/components/document-viewer/use-pinch-zoom.d.ts +12 -0
  78. package/dist/components/document-viewer/use-pinch-zoom.js +67 -0
  79. package/dist/components/document-viewer/use-zoom.d.ts +23 -0
  80. package/dist/components/document-viewer/use-zoom.js +70 -0
  81. package/dist/components/document-viewer/zoom.d.ts +29 -0
  82. package/dist/components/document-viewer/zoom.js +37 -0
  83. package/dist/components/field/field-checks.d.ts +34 -0
  84. package/dist/components/field/field-checks.js +42 -0
  85. package/dist/components/file-field/file-field-checks.d.ts +13 -0
  86. package/dist/components/file-field/file-field-checks.js +21 -0
  87. package/dist/components/file-field/use-file-drop.d.ts +34 -0
  88. package/dist/components/file-field/use-file-drop.js +78 -0
  89. package/dist/components/file-field/use-swap-focus.d.ts +15 -0
  90. package/dist/components/file-field/use-swap-focus.js +40 -0
  91. package/dist/components/filter-chips/FilterChip.d.ts +16 -0
  92. package/dist/components/filter-chips/FilterChip.js +20 -0
  93. package/dist/components/filter-chips/options.d.ts +75 -0
  94. package/dist/components/filter-chips/options.js +11 -0
  95. package/dist/components/filter-chips/validate.d.ts +9 -0
  96. package/dist/components/filter-chips/validate.js +48 -0
  97. package/dist/components/list/ListRowContent.d.ts +8 -2
  98. package/dist/components/list/ListRowContent.js +6 -3
  99. package/dist/components/list/ListRowItem.d.ts +10 -0
  100. package/dist/components/list/ListRowItem.js +17 -0
  101. package/dist/components/list/row-naming.d.ts +17 -0
  102. package/dist/components/list/row-naming.js +19 -0
  103. package/dist/components/list/row-slot.d.ts +8 -0
  104. package/dist/components/list/row-slot.js +12 -0
  105. package/dist/components/markdown/markdown-limits.d.ts +14 -0
  106. package/dist/components/markdown/markdown-limits.js +14 -0
  107. package/dist/components/markdown/markdown-model.d.ts +94 -0
  108. package/dist/components/markdown/markdown-model.js +8 -0
  109. package/dist/components/markdown/markdown-options.d.ts +18 -0
  110. package/dist/components/markdown/markdown-options.js +10 -0
  111. package/dist/components/markdown/markdown-rules.d.ts +28 -0
  112. package/dist/components/markdown/markdown-rules.js +81 -0
  113. package/dist/components/markdown/markdown-text.d.ts +17 -0
  114. package/dist/components/markdown/markdown-text.js +86 -0
  115. package/dist/components/markdown/parse-markdown.d.ts +4 -0
  116. package/dist/components/markdown/parse-markdown.js +21 -0
  117. package/dist/components/markdown/read-blocks.d.ts +8 -0
  118. package/dist/components/markdown/read-blocks.js +168 -0
  119. package/dist/components/markdown/read-inlines.d.ts +12 -0
  120. package/dist/components/markdown/read-inlines.js +126 -0
  121. package/dist/components/markdown/read-markdown.d.ts +9 -0
  122. package/dist/components/markdown/read-markdown.js +27 -0
  123. package/dist/components/markdown/reading-context.d.ts +18 -0
  124. package/dist/components/markdown/reading-context.js +35 -0
  125. package/dist/components/markdown/render-markdown.d.ts +10 -0
  126. package/dist/components/markdown/render-markdown.js +52 -0
  127. package/dist/components/use-element-width.d.ts +11 -0
  128. package/dist/components/use-element-width.js +38 -0
  129. package/dist/css/chart-tones.d.ts +2 -0
  130. package/dist/css/chart-tones.js +5 -1
  131. package/dist/css/css-article.d.ts +2 -0
  132. package/dist/css/css-article.js +110 -0
  133. package/dist/css/css-bar-chart.d.ts +17 -2
  134. package/dist/css/css-bar-chart.js +38 -7
  135. package/dist/css/css-button-group-attached.d.ts +3 -0
  136. package/dist/css/css-button-group-attached.js +18 -1
  137. package/dist/css/css-canvas-grouped.d.ts +17 -0
  138. package/dist/css/css-canvas-grouped.js +40 -0
  139. package/dist/css/css-components.js +18 -0
  140. package/dist/css/css-count-pill.js +14 -1
  141. package/dist/css/css-date-field-calendar-entry.d.ts +11 -0
  142. package/dist/css/css-date-field-calendar-entry.js +50 -0
  143. package/dist/css/css-date-field.js +4 -0
  144. package/dist/css/css-denomination-grid.js +4 -0
  145. package/dist/css/css-denomination-transposed.d.ts +4 -0
  146. package/dist/css/css-denomination-transposed.js +178 -0
  147. package/dist/css/css-dialog-canvas.d.ts +3 -0
  148. package/dist/css/css-dialog-canvas.js +20 -0
  149. package/dist/css/css-dialog-frame.js +19 -2
  150. package/dist/css/css-dialog-grabber.d.ts +4 -0
  151. package/dist/css/css-dialog-grabber.js +56 -0
  152. package/dist/css/css-dialog.js +3 -2
  153. package/dist/css/css-document-viewer.d.ts +2 -0
  154. package/dist/css/css-document-viewer.js +186 -0
  155. package/dist/css/css-document.js +3 -0
  156. package/dist/css/css-field-width.d.ts +12 -0
  157. package/dist/css/css-field-width.js +49 -0
  158. package/dist/css/css-field.js +4 -0
  159. package/dist/css/css-file-field.d.ts +2 -0
  160. package/dist/css/css-file-field.js +180 -0
  161. package/dist/css/css-filter-chips-layout.d.ts +2 -0
  162. package/dist/css/css-filter-chips-layout.js +42 -0
  163. package/dist/css/css-filter-chips.js +4 -0
  164. package/dist/css/css-list-row-trailing.d.ts +2 -0
  165. package/dist/css/css-list-row-trailing.js +91 -0
  166. package/dist/css/css-list-row.d.ts +6 -0
  167. package/dist/css/css-list-row.js +19 -3
  168. package/dist/css/css-list.js +5 -1
  169. package/dist/css/css-markdown.d.ts +2 -0
  170. package/dist/css/css-markdown.js +144 -0
  171. package/dist/css/css-segmented-sizing.d.ts +13 -0
  172. package/dist/css/css-segmented-sizing.js +66 -0
  173. package/dist/css/css-segmented.js +4 -0
  174. package/dist/css/css-switch.d.ts +6 -0
  175. package/dist/css/css-switch.js +39 -0
  176. package/dist/css/css-variables.js +1 -0
  177. package/dist/css/stacking.d.ts +1 -0
  178. package/dist/css/stacking.js +4 -1
  179. package/dist/css/stylesheet.js +12 -0
  180. package/dist/date-field-labels.d.ts +5 -0
  181. package/dist/date-field-labels.js +1 -0
  182. package/dist/document-viewer-worker.d.ts +9 -0
  183. package/dist/document-viewer-worker.js +9 -0
  184. package/dist/index.d.ts +15 -9
  185. package/dist/index.js +13 -7
  186. package/dist/list-options.d.ts +11 -7
  187. package/dist/list-options.js +20 -8
  188. package/dist/styles.css +889 -44
  189. package/dist/theme/ThemeProvider.d.ts +11 -1
  190. package/dist/theme/ThemeProvider.js +4 -2
  191. package/package.json +10 -2
@@ -0,0 +1,180 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ import { disabledControlSurface } from './css-document.js';
3
+ import { coarsePointerQuery, touchTarget } from './touch-target.js';
4
+ const label = typographyVariants.label;
5
+ const caption = typographyVariants.caption;
6
+ /*
7
+ * The frame holds the field's one file: empty, a wide zone on the subtle
8
+ * fill that opens the picker (the choose words in the text colour at
9
+ * label weight, as the accent falls under 4.5:1 on the subtle fill in
10
+ * some palettes, the drop words muted after them); chosen, a row on the surface
11
+ * with the consumer's mark, the file's name over its detail and the
12
+ * change button at the end. Both are a hairline frame at the medium
13
+ * radius. A file dragged over either draws the accent edge and tint. A
14
+ * chosen row too narrow for a long name and the button wraps the button
15
+ * under the name, at the row's end.
16
+ */
17
+ function frameRules() {
18
+ return `.sw-file-field-frame {
19
+ border: 1px solid var(--sw-color-border);
20
+ border-radius: var(--sw-radius-md);
21
+ box-sizing: border-box;
22
+ min-width: 0;
23
+ }
24
+
25
+ .sw-file-field-empty { background: var(--sw-color-subtle); }
26
+
27
+ .sw-file-field-chosen {
28
+ align-items: center;
29
+ background: var(--sw-color-surface);
30
+ display: flex;
31
+ flex-wrap: wrap;
32
+ gap: var(--sw-space-2) var(--sw-space-3);
33
+ padding: var(--sw-space-2) var(--sw-space-2) var(--sw-space-2) var(--sw-space-4);
34
+ }
35
+
36
+ .sw-field-invalid .sw-file-field-frame { border-color: var(--sw-color-danger); }
37
+
38
+ /* A drag wins over an error's edge: it says where the file goes. */
39
+ .sw-file-field-frame.sw-file-field-dragging {
40
+ background: var(--sw-color-accentSubtle);
41
+ border-color: var(--sw-color-accent);
42
+ outline: 1px solid var(--sw-color-accent);
43
+ }
44
+
45
+ /* On the tint, muted words fall under 4.5:1 in light palettes: every word takes the text colour. */
46
+ .sw-file-field-dragging :is(.sw-file-field-choose, .sw-file-field-drop, .sw-file-field-detail, .sw-file-field-icon) {
47
+ color: var(--sw-color-text);
48
+ }
49
+
50
+ /* Disabled, the frame's hairline is dashed, as a disabled text control's. */
51
+ .sw-file-field-disabled { border-style: dashed; }`;
52
+ }
53
+ /*
54
+ * The empty zone is one button filling the frame, a space-6 of padding
55
+ * above and below its words, its focus ring inside the frame's edge. On a
56
+ * coarse pointer, where nothing is dragged, the drop words are left out.
57
+ */
58
+ function zoneRules() {
59
+ return `.sw-file-field-zone {
60
+ align-items: center;
61
+ appearance: none;
62
+ background: transparent;
63
+ border: 0;
64
+ border-radius: inherit;
65
+ box-sizing: border-box;
66
+ color: var(--sw-color-text);
67
+ cursor: pointer;
68
+ display: flex;
69
+ flex-wrap: wrap;
70
+ font-family: var(--sw-font-sans);
71
+ font-size: ${label.fontSize}px;
72
+ gap: var(--sw-space-1);
73
+ justify-content: center;
74
+ line-height: ${label.lineHeight}px;
75
+ margin: 0;
76
+ min-height: ${touchTarget};
77
+ padding: var(--sw-space-6) var(--sw-space-4);
78
+ text-align: center;
79
+ width: 100%;
80
+ }
81
+
82
+ .sw-file-field-zone:focus { outline: none; }
83
+
84
+ .sw-file-field-zone:focus-visible {
85
+ outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
86
+ outline-offset: calc(-1 * var(--sw-focus-ring-width));
87
+ }
88
+
89
+ .sw-file-field-choose {
90
+ color: var(--sw-color-text);
91
+ font-weight: ${label.fontWeight};
92
+ }
93
+
94
+ .sw-file-field-drop { color: var(--sw-color-muted); }
95
+
96
+ .sw-file-field-zone:disabled {
97
+ ${disabledControlSurface}
98
+ border-radius: inherit;
99
+ }
100
+
101
+ .sw-file-field-zone:disabled .sw-file-field-choose { color: var(--sw-color-muted); }
102
+
103
+ @media ${coarsePointerQuery} {
104
+ .sw-file-field-drop { display: none; }
105
+ }`;
106
+ }
107
+ /*
108
+ * The chosen file: the mark, then the name over its detail (at least four
109
+ * space-8 wide before the button wraps under it), then the button.
110
+ */
111
+ function fileRules() {
112
+ return `.sw-file-field-icon {
113
+ align-items: center;
114
+ color: var(--sw-color-muted);
115
+ display: flex;
116
+ flex: none;
117
+ }
118
+
119
+ .sw-file-field-file {
120
+ display: flex;
121
+ flex: 1 1 calc(4 * var(--sw-space-8));
122
+ flex-direction: column;
123
+ min-width: 0;
124
+ }
125
+
126
+ .sw-file-field-name {
127
+ font-size: ${label.fontSize}px;
128
+ font-weight: ${label.fontWeight};
129
+ line-height: ${label.lineHeight}px;
130
+ overflow-wrap: anywhere;
131
+ }
132
+
133
+ .sw-file-field-detail {
134
+ color: var(--sw-color-muted);
135
+ font-size: ${caption.fontSize}px;
136
+ line-height: ${caption.lineHeight}px;
137
+ }
138
+
139
+ .sw-file-field-chosen > .sw-button {
140
+ flex: none;
141
+ margin-inline-start: auto;
142
+ }`;
143
+ }
144
+ /* Forced colours: system edges, Highlight for a drag, the button text colour for the words. */
145
+ function forcedColorRules() {
146
+ return `@media (forced-colors: active) {
147
+ .sw-file-field-frame { border-color: CanvasText; }
148
+ .sw-field-invalid .sw-file-field-frame { border-color: Mark; }
149
+ .sw-file-field-frame.sw-file-field-dragging { border-color: Highlight; outline-color: Highlight; }
150
+ .sw-file-field-choose { color: ButtonText; }
151
+ .sw-file-field-zone:disabled,
152
+ .sw-file-field-zone:disabled .sw-file-field-choose { color: GrayText; }
153
+ }`;
154
+ }
155
+ export function cssFileFieldClasses() {
156
+ return `${frameRules()}
157
+
158
+ ${zoneRules()}
159
+
160
+ ${fileRules()}
161
+
162
+ ${forcedColorRules()}`;
163
+ }
164
+ export function fileFieldClassCatalog() {
165
+ return [
166
+ 'sw-file-field',
167
+ 'sw-file-field-frame',
168
+ 'sw-file-field-empty',
169
+ 'sw-file-field-chosen',
170
+ 'sw-file-field-dragging',
171
+ 'sw-file-field-disabled',
172
+ 'sw-file-field-zone',
173
+ 'sw-file-field-choose',
174
+ 'sw-file-field-drop',
175
+ 'sw-file-field-icon',
176
+ 'sw-file-field-file',
177
+ 'sw-file-field-name',
178
+ 'sw-file-field-detail',
179
+ ];
180
+ }
@@ -0,0 +1,2 @@
1
+ export declare function cssFilterChipsLayoutClasses(): string;
2
+ export declare function filterChipsLayoutClassCatalog(): string[];
@@ -0,0 +1,42 @@
1
+ /*
2
+ * The chips' opt-in layouts.
3
+ *
4
+ * An inline count is set in the chip's own words, at tabular figures, after
5
+ * a middle dot ("Open · 3"); a chosen chip keeps it in its own ink.
6
+ *
7
+ * Chips that scroll keep one row and scroll sideways inside their own box
8
+ * (never the page) when they do not fit, each chip at its words' width on
9
+ * one line (no wrapping, which overrides the wrapping row's
10
+ * `overflow-wrap: anywhere`). The box is padded by the focus ring's reach and pulled back by
11
+ * the same amount, so a focused chip's ring is not clipped and the chips
12
+ * stay where a wrapped row puts them. A focused chip past the edge is
13
+ * scrolled into view by the browser. The scrollbar stays, thin, so a
14
+ * pointer without a sideways wheel can still reach the last chip.
15
+ */
16
+ const ringReach = 'calc(var(--sw-focus-ring-width) + var(--sw-focus-ring-offset))';
17
+ export function cssFilterChipsLayoutClasses() {
18
+ return `.sw-filter-chip-count-inline {
19
+ font-variant-numeric: tabular-nums;
20
+ }
21
+
22
+ .sw-filter-chips-scroll .sw-filter-chips-options {
23
+ flex-wrap: nowrap;
24
+ margin: calc(-1 * ${ringReach});
25
+ overflow-x: auto;
26
+ overscroll-behavior-x: contain;
27
+ padding: ${ringReach};
28
+ scrollbar-width: thin;
29
+ }
30
+
31
+ .sw-filter-chips-scroll .sw-filter-chip {
32
+ flex: none;
33
+ max-width: none;
34
+ }
35
+
36
+ .sw-filter-chips-scroll .sw-filter-chip-face {
37
+ white-space: nowrap;
38
+ }`;
39
+ }
40
+ export function filterChipsLayoutClassCatalog() {
41
+ return ['sw-filter-chip-count-inline', 'sw-filter-chips-scroll'];
42
+ }
@@ -1,4 +1,5 @@
1
1
  import { typographyVariants } from '@scalewing/tokens';
2
+ import { cssFilterChipsLayoutClasses, filterChipsLayoutClassCatalog, } from './css-filter-chips-layout.js';
2
3
  const label = typographyVariants.label;
3
4
  const data = typographyVariants.data;
4
5
  const caption = typographyVariants.caption;
@@ -123,6 +124,8 @@ export function cssFilterChipsClasses() {
123
124
  border-color: var(--sw-color-danger);
124
125
  }
125
126
 
127
+ ${cssFilterChipsLayoutClasses()}
128
+
126
129
  @media (forced-colors: active) {
127
130
  .sw-filter-chip-face { background: Canvas; border-color: CanvasText; color: CanvasText; }
128
131
  .sw-filter-chips-error { color: Mark; }
@@ -144,5 +147,6 @@ export function filterChipsClassCatalog() {
144
147
  'sw-filter-chip-count',
145
148
  'sw-filter-chip-quiet',
146
149
  'sw-filter-chips-error',
150
+ ...filterChipsLayoutClassCatalog(),
147
151
  ];
148
152
  }
@@ -0,0 +1,2 @@
1
+ export declare function cssListRowTrailingClasses(): string;
2
+ export declare function listRowTrailingClassCatalog(): string[];
@@ -0,0 +1,91 @@
1
+ import { quietFill } from './quiet-fill.js';
2
+ /*
3
+ * The unread dot: an accent circle a space-2 across after the title's last
4
+ * word, on its line. It is drawn as a border, so forced colours keep it
5
+ * (in the text colour); the hidden words beside the title say what it is.
6
+ * Centred on the words' middle, as an inline mark.
7
+ */
8
+ function unreadRules() {
9
+ return `.sw-list-row-unread {
10
+ border: calc(var(--sw-space-2) / 2) solid var(--sw-color-accent);
11
+ border-radius: var(--sw-radius-pill);
12
+ box-sizing: border-box;
13
+ display: inline-block;
14
+ height: var(--sw-space-2);
15
+ margin-inline-start: var(--sw-space-2);
16
+ vertical-align: middle;
17
+ width: var(--sw-space-2);
18
+ }
19
+
20
+ @media (forced-colors: active) {
21
+ .sw-list-row-unread { border-color: CanvasText; }
22
+ }`;
23
+ }
24
+ /*
25
+ * The tag (a Badge, "Only in English") sits before the accessory, centred
26
+ * on the row's height and never shrunk or wrapped.
27
+ */
28
+ function tagRules() {
29
+ return `.sw-list-row-tag {
30
+ align-self: center;
31
+ display: inline-flex;
32
+ flex: none;
33
+ white-space: nowrap;
34
+ }`;
35
+ }
36
+ /*
37
+ * A row with an action is the row's button or link followed by the
38
+ * action's control in one list item, the control centred on the row's
39
+ * height after it and outside its press area. The row ends a space-2
40
+ * before the control, and the control keeps the row's inline end padding
41
+ * after it (a space-4 in a panel, none in a plain list). Where :has() is
42
+ * supported, the hover fill spans the whole item, so the row and its
43
+ * control read as one line; elsewhere the row keeps its own fill.
44
+ */
45
+ function actionRules() {
46
+ return `.sw-list-item-action {
47
+ align-items: center;
48
+ display: flex;
49
+ }
50
+
51
+ .sw-list-item-action > .sw-list-row {
52
+ flex: 1 1 auto;
53
+ min-width: 0;
54
+ padding-inline-end: var(--sw-space-2);
55
+ }
56
+
57
+ .sw-list-row-action {
58
+ display: inline-flex;
59
+ flex: none;
60
+ padding-inline-end: var(--sw-space-4);
61
+ }
62
+
63
+ .sw-list-group-plain .sw-list-row-action { padding-inline-end: 0; }
64
+
65
+ @supports selector(:has(*)) {
66
+ @media (hover: hover) {
67
+ .sw-list-item-action:has(> .sw-list-row-pressable:hover:not(.sw-list-row-disabled)) {
68
+ background: ${quietFill};
69
+ }
70
+
71
+ .sw-list-item-action > .sw-list-row-pressable:hover:not(.sw-list-row-disabled) {
72
+ background: transparent;
73
+ }
74
+ }
75
+ }`;
76
+ }
77
+ export function cssListRowTrailingClasses() {
78
+ return `${unreadRules()}
79
+
80
+ ${tagRules()}
81
+
82
+ ${actionRules()}`;
83
+ }
84
+ export function listRowTrailingClassCatalog() {
85
+ return [
86
+ 'sw-list-row-unread',
87
+ 'sw-list-row-tag',
88
+ 'sw-list-item-action',
89
+ 'sw-list-row-action',
90
+ ];
91
+ }
@@ -1,2 +1,8 @@
1
+ /**
2
+ * The colours a row's value can take: a table cell's, and `warning`, for a
3
+ * figure that needs a look but is not wrong yet.
4
+ */
5
+ export declare const listRowValueTones: readonly ["success", "danger", "muted", "accent", "warning"];
6
+ export type ListRowValueTone = (typeof listRowValueTones)[number];
1
7
  export declare function cssListRowClasses(): string;
2
8
  export declare function listRowClassCatalog(): string[];
@@ -1,6 +1,7 @@
1
1
  import { typographyVariants } from '@scalewing/tokens';
2
2
  import { checkStrokeIn, chevronStrokeIn } from './chevron.js';
3
- import { tableCellTones as listRowValueTones } from './css-table-ledger.js';
3
+ import { chartColorMix, chartInkMixes } from './chart-tones.js';
4
+ import { tableCellTones } from './css-table-ledger.js';
4
5
  import { quietFill } from './quiet-fill.js';
5
6
  import { coarsePointerQuery, touchTarget } from './touch-target.js';
6
7
  const label = typographyVariants.label;
@@ -81,8 +82,22 @@ function rowRules() {
81
82
  }
82
83
  }`;
83
84
  }
85
+ /**
86
+ * The colours a row's value can take: a table cell's, and `warning`, for a
87
+ * figure that needs a look but is not wrong yet.
88
+ */
89
+ export const listRowValueTones = [...tableCellTones, 'warning'];
90
+ /*
91
+ * A warning value is the warning colour's ink, moved halfway to the text
92
+ * colour as a chart's warning words are: the warning colour alone falls
93
+ * under 4.5:1 on the surface in some palettes. Forced colours draw it as
94
+ * text, as every tone.
95
+ */
96
+ function warningValueRule() {
97
+ return `.sw-list-row-value-warning { color: ${chartColorMix(chartInkMixes.warning)}; }`;
98
+ }
84
99
  function partRules() {
85
- const tones = listRowValueTones
100
+ const tones = tableCellTones
86
101
  .map((tone) => `.sw-list-row-value-${tone} { color: var(--sw-color-${tone}); }`)
87
102
  .join('\n');
88
103
  return `.sw-list-row-leading {
@@ -132,7 +147,8 @@ function partRules() {
132
147
 
133
148
  .sw-list-row-value { font-weight: ${label.fontWeight}; }
134
149
 
135
- ${tones}`;
150
+ ${tones}
151
+ ${warningValueRule()}`;
136
152
  }
137
153
  /*
138
154
  * The chevron is the stroke Accordion and the menus share, pointing to the
@@ -1,5 +1,6 @@
1
1
  import { typographyVariants } from '@scalewing/tokens';
2
2
  import { cssListRowClasses, listRowClassCatalog } from './css-list-row.js';
3
+ import { cssListRowTrailingClasses, listRowTrailingClassCatalog, } from './css-list-row-trailing.js';
3
4
  import { blockEdgeShadeRules, scrollRegionRules } from './css-scroll-region.js';
4
5
  const label = typographyVariants.label;
5
6
  const caption = typographyVariants.caption;
@@ -69,7 +70,9 @@ export function cssListClasses() {
69
70
 
70
71
  ${boundedRules()}
71
72
 
72
- ${cssListRowClasses()}`;
73
+ ${cssListRowClasses()}
74
+
75
+ ${cssListRowTrailingClasses()}`;
73
76
  }
74
77
  export function listClassCatalog() {
75
78
  return [
@@ -81,5 +84,6 @@ export function listClassCatalog() {
81
84
  'sw-list-group-scroll',
82
85
  'sw-list-group-footer',
83
86
  ...listRowClassCatalog(),
87
+ ...listRowTrailingClassCatalog(),
84
88
  ];
85
89
  }
@@ -0,0 +1,2 @@
1
+ export declare function cssMarkdownClasses(): string;
2
+ export declare function markdownClassCatalog(): string[];
@@ -0,0 +1,144 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ const { body, title, label, caption } = typographyVariants;
3
+ /*
4
+ * A page of Markdown in body type: blocks a space-4 apart, a heading a
5
+ * space-6 below what comes before it and a space-2 above what follows.
6
+ * `#` is the title size, `##` body size and `###` label size, all at the
7
+ * title's weight. At zero specificity (`:where`), so a consumer's layout
8
+ * can still space the view itself.
9
+ */
10
+ function flowRules() {
11
+ return `.sw-markdown {
12
+ color: var(--sw-color-text);
13
+ font-family: var(--sw-font-sans);
14
+ font-size: ${body.fontSize}px;
15
+ letter-spacing: ${body.letterSpacing}px;
16
+ line-height: ${body.lineHeight}px;
17
+ overflow-wrap: anywhere;
18
+ }
19
+
20
+ :where(.sw-markdown) > *,
21
+ :where(.sw-markdown-quote) > *,
22
+ :where(.sw-markdown-list li) > * { margin-block: 0; }
23
+
24
+ :where(.sw-markdown, .sw-markdown-quote, .sw-markdown-list li) > * + * {
25
+ margin-block-start: var(--sw-space-4);
26
+ }
27
+
28
+ :where(.sw-markdown) > * + .sw-markdown-heading { margin-block-start: var(--sw-space-6); }
29
+ :where(.sw-markdown) > .sw-markdown-heading + * { margin-block-start: var(--sw-space-2); }
30
+
31
+ .sw-markdown-heading {
32
+ color: var(--sw-color-text);
33
+ font-weight: ${title.fontWeight};
34
+ scroll-margin-block-start: var(--sw-space-6);
35
+ }
36
+
37
+ .sw-markdown-heading-1 {
38
+ font-size: ${title.fontSize}px;
39
+ letter-spacing: ${title.letterSpacing}px;
40
+ line-height: ${title.lineHeight}px;
41
+ }
42
+
43
+ .sw-markdown-heading-2 {
44
+ font-size: ${body.fontSize}px;
45
+ line-height: ${body.lineHeight}px;
46
+ }
47
+
48
+ .sw-markdown-heading-3 {
49
+ font-size: ${label.fontSize}px;
50
+ letter-spacing: ${label.letterSpacing}px;
51
+ line-height: ${label.lineHeight}px;
52
+ }`;
53
+ }
54
+ /*
55
+ * Lists hang their markers in the page's margin a space-5 in; a tight
56
+ * list's items are a space-2 apart. A link is the accent, underlined, so
57
+ * it never depends on colour alone, and thickens to the focus ring's
58
+ * width while hovered. In the highlighted box, whose tint neither the
59
+ * accent nor the muted colour clears at 4.5:1 in every palette, links
60
+ * (still underlined) and photo captions are the text colour.
61
+ */
62
+ function inlineRules() {
63
+ return `.sw-markdown-list {
64
+ padding-inline-start: var(--sw-space-5);
65
+ }
66
+
67
+ .sw-markdown-list > li + li { margin-block-start: var(--sw-space-2); }
68
+
69
+ [data-theme] .sw-markdown-link {
70
+ color: var(--sw-color-accent);
71
+ text-decoration-line: underline;
72
+ }
73
+
74
+ [data-theme] .sw-markdown-link:hover {
75
+ text-decoration-thickness: var(--sw-focus-ring-width);
76
+ }
77
+
78
+ [data-theme] .sw-markdown-quote :is(.sw-markdown-link, .sw-markdown-caption) {
79
+ color: var(--sw-color-text);
80
+ }`;
81
+ }
82
+ /*
83
+ * A block quote is the highlighted box: the accent's subtle tint with an
84
+ * accent bar at its start, at the small radius. A photo fills the page's
85
+ * width at the medium radius, its caption muted under it.
86
+ */
87
+ function boxRules() {
88
+ return `.sw-markdown-quote {
89
+ background: var(--sw-color-accentSubtle);
90
+ border-inline-start: var(--sw-space-1) solid var(--sw-color-accent);
91
+ border-radius: var(--sw-radius-sm);
92
+ margin-inline: 0;
93
+ padding: var(--sw-space-3) var(--sw-space-4);
94
+ }
95
+
96
+ .sw-markdown-figure {
97
+ display: flex;
98
+ flex-direction: column;
99
+ gap: var(--sw-space-2);
100
+ margin-inline: 0;
101
+ }
102
+
103
+ .sw-markdown-image {
104
+ border-radius: var(--sw-radius-md);
105
+ display: block;
106
+ height: auto;
107
+ width: 100%;
108
+ }
109
+
110
+ .sw-markdown-caption {
111
+ color: var(--sw-color-muted);
112
+ font-size: ${caption.fontSize}px;
113
+ letter-spacing: ${caption.letterSpacing}px;
114
+ line-height: ${caption.lineHeight}px;
115
+ }
116
+
117
+ @media (forced-colors: active) {
118
+ .sw-markdown-quote { border: 1px solid CanvasText; border-inline-start-width: var(--sw-space-1); }
119
+ }`;
120
+ }
121
+ export function cssMarkdownClasses() {
122
+ return `${flowRules()}
123
+
124
+ ${inlineRules()}
125
+
126
+ ${boxRules()}`;
127
+ }
128
+ export function markdownClassCatalog() {
129
+ return [
130
+ 'sw-markdown',
131
+ 'sw-markdown-paragraph',
132
+ 'sw-markdown-heading',
133
+ 'sw-markdown-heading-1',
134
+ 'sw-markdown-heading-2',
135
+ 'sw-markdown-heading-3',
136
+ 'sw-markdown-list',
137
+ 'sw-markdown-item-text',
138
+ 'sw-markdown-link',
139
+ 'sw-markdown-quote',
140
+ 'sw-markdown-figure',
141
+ 'sw-markdown-image',
142
+ 'sw-markdown-caption',
143
+ ];
144
+ }
@@ -0,0 +1,13 @@
1
+ import { type Breakpoint } from './breakpoints.js';
2
+ /** The class that stretches a SegmentedControl's field below a breakpoint. */
3
+ export declare function segmentedFullWidthClass(breakpoint: Breakpoint): string;
4
+ /**
5
+ * `md` (the default) is each track's own segment padding; `sm` pads every
6
+ * segment a step less and keeps its label on one line, ending in an
7
+ * ellipsis past its share, so a few segments fit a phone's card.
8
+ */
9
+ export declare const segmentedSizes: readonly ["md", "sm"];
10
+ export type SegmentedSize = (typeof segmentedSizes)[number];
11
+ export declare const segmentedSmClass = "sw-segmented-sm";
12
+ export declare function cssSegmentedSizingClasses(): string;
13
+ export declare function segmentedSizingClassCatalog(): string[];
@@ -0,0 +1,66 @@
1
+ import { breakpointQuery } from './breakpoints.js';
2
+ /** The class that stretches a SegmentedControl's field below a breakpoint. */
3
+ export function segmentedFullWidthClass(breakpoint) {
4
+ return `sw-segmented-field-full-below-${breakpoint}`;
5
+ }
6
+ /**
7
+ * `md` (the default) is each track's own segment padding; `sm` pads every
8
+ * segment a step less and keeps its label on one line, ending in an
9
+ * ellipsis past its share, so a few segments fit a phone's card.
10
+ */
11
+ export const segmentedSizes = ['md', 'sm'];
12
+ export const segmentedSmClass = 'sw-segmented-sm';
13
+ /*
14
+ * Below the breakpoint a full-width field fills its column and its track
15
+ * shares that width equally among its segments (the filled track's grid),
16
+ * whatever its variant, a raised one included (three classes, after the
17
+ * raised and Inline rules that size it to its segments).
18
+ *
19
+ * A small track pads each segment without a mark a space-2 step on both
20
+ * sides (a segment with a mark keeps its variant's padding), never wraps a
21
+ * label and ends a label that does not fit its segment in an ellipsis on
22
+ * the label's own block box (`sw-segmented-item-label`; an inline box
23
+ * cannot clip), so a plain segment and a flex item (a
24
+ * filled or marked segment) truncate too; the radio's name still reads
25
+ * the whole label. After every variant's padding.
26
+ */
27
+ export function cssSegmentedSizingClasses() {
28
+ const full = segmentedFullWidthClass('md');
29
+ return `@media ${breakpointQuery('below', 'md')} {
30
+ .sw-segmented-field.${full} {
31
+ align-self: stretch;
32
+ display: flex;
33
+ width: 100%;
34
+ }
35
+ .sw-segmented-field.${full} > .sw-segmented {
36
+ align-self: stretch;
37
+ display: grid;
38
+ grid-auto-columns: minmax(0, 1fr);
39
+ grid-auto-flow: column;
40
+ }
41
+ }
42
+
43
+ .sw-segmented.${segmentedSmClass} .sw-segmented-item {
44
+ min-width: 0;
45
+ overflow: hidden;
46
+ white-space: nowrap;
47
+ }
48
+
49
+ .sw-segmented.${segmentedSmClass}:not(.sw-segmented-with-icons) .sw-segmented-item {
50
+ padding-inline: var(--sw-space-2);
51
+ }
52
+
53
+ .${segmentedSmClass} .sw-segmented-item-label {
54
+ display: block;
55
+ min-width: 0;
56
+ overflow: hidden;
57
+ text-overflow: ellipsis;
58
+ }`;
59
+ }
60
+ export function segmentedSizingClassCatalog() {
61
+ return [
62
+ segmentedFullWidthClass('md'),
63
+ segmentedSmClass,
64
+ 'sw-segmented-item-label',
65
+ ];
66
+ }
@@ -1,5 +1,6 @@
1
1
  import { trackInset, typographyVariants } from '@scalewing/tokens';
2
2
  import { cssSegmentedRaisedClasses, segmentedRaisedClassCatalog, } from './css-segmented-raised.js';
3
+ import { cssSegmentedSizingClasses, segmentedSizingClassCatalog, } from './css-segmented-sizing.js';
3
4
  const body = typographyVariants.body;
4
5
  const data = typographyVariants.data;
5
6
  const label = typographyVariants.label;
@@ -167,6 +168,8 @@ ${iconRules()}
167
168
 
168
169
  ${cssSegmentedRaisedClasses()}
169
170
 
171
+ ${cssSegmentedSizingClasses()}
172
+
170
173
  .sw-segmented-disabled {
171
174
  opacity: var(--sw-disabled-opacity);
172
175
  }
@@ -187,5 +190,6 @@ export function segmentedClassCatalog() {
187
190
  'sw-segmented-item-icon',
188
191
  'sw-segmented-disabled',
189
192
  ...segmentedRaisedClassCatalog(),
193
+ ...segmentedSizingClassCatalog(),
190
194
  ];
191
195
  }
@@ -1,2 +1,8 @@
1
+ /** Where the control sits: before its label, or at the row's end after it. */
2
+ export declare const switchLayouts: readonly ["leading", "trailing"];
3
+ export type SwitchLayout = (typeof switchLayouts)[number];
4
+ /** The track's colour while on. */
5
+ export declare const switchCheckedTones: readonly ["accent", "success"];
6
+ export type SwitchCheckedTone = (typeof switchCheckedTones)[number];
1
7
  export declare function cssSwitchClasses(): string;
2
8
  export declare function switchClassCatalog(): string[];