@scalewing/react 1.41.0 → 1.44.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 (136) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +180 -1
  3. package/dist/components/ActionMenu.d.ts +4 -2
  4. package/dist/components/ActionMenu.js +4 -8
  5. package/dist/components/Article.d.ts +60 -0
  6. package/dist/components/Article.js +42 -0
  7. package/dist/components/DescriptionList.d.ts +12 -2
  8. package/dist/components/DescriptionList.js +7 -3
  9. package/dist/components/DocumentViewer.d.ts +41 -0
  10. package/dist/components/DocumentViewer.js +72 -0
  11. package/dist/components/FileField.d.ts +55 -0
  12. package/dist/components/FileField.js +75 -0
  13. package/dist/components/FilterChips.d.ts +1 -1
  14. package/dist/components/FilterChips.js +1 -1
  15. package/dist/components/FilterChipsRow.d.ts +24 -0
  16. package/dist/components/FilterChipsRow.js +14 -0
  17. package/dist/components/ListRow.d.ts +31 -2
  18. package/dist/components/ListRow.js +19 -18
  19. package/dist/components/MarkdownView.d.ts +39 -0
  20. package/dist/components/MarkdownView.js +30 -0
  21. package/dist/components/NavCount.d.ts +15 -2
  22. package/dist/components/NavCount.js +16 -6
  23. package/dist/components/action-menu/assert-action-menu.d.ts +13 -0
  24. package/dist/components/action-menu/assert-action-menu.js +21 -0
  25. package/dist/components/chart/use-chart-width.js +2 -24
  26. package/dist/components/description-list-layout.d.ts +10 -0
  27. package/dist/components/description-list-layout.js +13 -0
  28. package/dist/components/document-viewer/document-viewer-labels.d.ts +23 -0
  29. package/dist/components/document-viewer/document-viewer-labels.js +23 -0
  30. package/dist/components/document-viewer/page-box.d.ts +8 -0
  31. package/dist/components/document-viewer/page-box.js +12 -0
  32. package/dist/components/document-viewer/pdf-document.d.ts +32 -0
  33. package/dist/components/document-viewer/pdf-document.js +66 -0
  34. package/dist/components/document-viewer/pdf-options.d.ts +36 -0
  35. package/dist/components/document-viewer/pdf-options.js +46 -0
  36. package/dist/components/document-viewer/render-pdf-page.d.ts +20 -0
  37. package/dist/components/document-viewer/render-pdf-page.js +38 -0
  38. package/dist/components/document-viewer/scroll-chain.d.ts +6 -0
  39. package/dist/components/document-viewer/scroll-chain.js +23 -0
  40. package/dist/components/document-viewer/use-error-report.d.ts +5 -0
  41. package/dist/components/document-viewer/use-error-report.js +13 -0
  42. package/dist/components/document-viewer/use-page-render.d.ts +21 -0
  43. package/dist/components/document-viewer/use-page-render.js +70 -0
  44. package/dist/components/document-viewer/use-pdf-document.d.ts +22 -0
  45. package/dist/components/document-viewer/use-pdf-document.js +47 -0
  46. package/dist/components/document-viewer/use-pinch-zoom.d.ts +12 -0
  47. package/dist/components/document-viewer/use-pinch-zoom.js +67 -0
  48. package/dist/components/document-viewer/use-zoom.d.ts +23 -0
  49. package/dist/components/document-viewer/use-zoom.js +70 -0
  50. package/dist/components/document-viewer/zoom.d.ts +29 -0
  51. package/dist/components/document-viewer/zoom.js +37 -0
  52. package/dist/components/file-field/file-field-checks.d.ts +13 -0
  53. package/dist/components/file-field/file-field-checks.js +23 -0
  54. package/dist/components/file-field/use-file-drop.d.ts +34 -0
  55. package/dist/components/file-field/use-file-drop.js +78 -0
  56. package/dist/components/file-field/use-swap-focus.d.ts +15 -0
  57. package/dist/components/file-field/use-swap-focus.js +40 -0
  58. package/dist/components/filter-chips/FilterChip.js +1 -1
  59. package/dist/components/filter-chips/options.d.ts +10 -0
  60. package/dist/components/filter-chips/options.js +8 -0
  61. package/dist/components/filter-chips/validate.d.ts +3 -3
  62. package/dist/components/filter-chips/validate.js +8 -4
  63. package/dist/components/list/ListRowContent.d.ts +9 -2
  64. package/dist/components/list/ListRowContent.js +6 -3
  65. package/dist/components/list/ListRowItem.d.ts +10 -0
  66. package/dist/components/list/ListRowItem.js +17 -0
  67. package/dist/components/list/row-naming.d.ts +17 -0
  68. package/dist/components/list/row-naming.js +19 -0
  69. package/dist/components/markdown/markdown-limits.d.ts +14 -0
  70. package/dist/components/markdown/markdown-limits.js +14 -0
  71. package/dist/components/markdown/markdown-model.d.ts +94 -0
  72. package/dist/components/markdown/markdown-model.js +8 -0
  73. package/dist/components/markdown/markdown-options.d.ts +18 -0
  74. package/dist/components/markdown/markdown-options.js +10 -0
  75. package/dist/components/markdown/markdown-rules.d.ts +28 -0
  76. package/dist/components/markdown/markdown-rules.js +81 -0
  77. package/dist/components/markdown/markdown-text.d.ts +17 -0
  78. package/dist/components/markdown/markdown-text.js +86 -0
  79. package/dist/components/markdown/parse-markdown.d.ts +4 -0
  80. package/dist/components/markdown/parse-markdown.js +21 -0
  81. package/dist/components/markdown/read-blocks.d.ts +8 -0
  82. package/dist/components/markdown/read-blocks.js +168 -0
  83. package/dist/components/markdown/read-inlines.d.ts +12 -0
  84. package/dist/components/markdown/read-inlines.js +126 -0
  85. package/dist/components/markdown/read-markdown.d.ts +9 -0
  86. package/dist/components/markdown/read-markdown.js +27 -0
  87. package/dist/components/markdown/reading-context.d.ts +18 -0
  88. package/dist/components/markdown/reading-context.js +35 -0
  89. package/dist/components/markdown/render-markdown.d.ts +10 -0
  90. package/dist/components/markdown/render-markdown.js +52 -0
  91. package/dist/components/slot.d.ts +9 -0
  92. package/dist/components/slot.js +13 -0
  93. package/dist/components/use-element-width.d.ts +11 -0
  94. package/dist/components/use-element-width.js +38 -0
  95. package/dist/css/css-action-menu-trigger.d.ts +6 -2
  96. package/dist/css/css-action-menu-trigger.js +50 -2
  97. package/dist/css/css-action-menu.js +4 -2
  98. package/dist/css/css-article.d.ts +2 -0
  99. package/dist/css/css-article.js +110 -0
  100. package/dist/css/css-components.js +15 -0
  101. package/dist/css/css-count-pill.js +14 -1
  102. package/dist/css/css-description-list.d.ts +1 -0
  103. package/dist/css/css-description-list.js +24 -0
  104. package/dist/css/css-document-viewer.d.ts +2 -0
  105. package/dist/css/css-document-viewer.js +186 -0
  106. package/dist/css/css-file-field.d.ts +2 -0
  107. package/dist/css/css-file-field.js +194 -0
  108. package/dist/css/css-filter-chip-tones.d.ts +3 -0
  109. package/dist/css/css-filter-chip-tones.js +28 -0
  110. package/dist/css/css-filter-chips-layout.d.ts +1 -0
  111. package/dist/css/css-filter-chips-layout.js +1 -1
  112. package/dist/css/css-filter-chips-row.d.ts +2 -0
  113. package/dist/css/css-filter-chips-row.js +79 -0
  114. package/dist/css/css-filter-chips.js +8 -0
  115. package/dist/css/css-font-mono.d.ts +3 -0
  116. package/dist/css/css-font-mono.js +23 -0
  117. package/dist/css/css-list-row-trailing.d.ts +2 -0
  118. package/dist/css/css-list-row-trailing.js +91 -0
  119. package/dist/css/css-list-row-truncate.d.ts +2 -0
  120. package/dist/css/css-list-row-truncate.js +29 -0
  121. package/dist/css/css-list.js +9 -1
  122. package/dist/css/css-markdown.d.ts +2 -0
  123. package/dist/css/css-markdown.js +144 -0
  124. package/dist/css/css-utilities.js +3 -0
  125. package/dist/css/css-variables.js +1 -0
  126. package/dist/css/spacing-classes.d.ts +1 -1
  127. package/dist/css/spacing-classes.js +1 -0
  128. package/dist/css/stylesheet.js +10 -0
  129. package/dist/document-viewer-worker.d.ts +9 -0
  130. package/dist/document-viewer-worker.js +9 -0
  131. package/dist/index.d.ts +11 -5
  132. package/dist/index.js +8 -3
  133. package/dist/list-options.d.ts +5 -2
  134. package/dist/list-options.js +7 -2
  135. package/dist/styles.css +649 -0
  136. package/package.json +10 -2
@@ -1,4 +1,24 @@
1
1
  import { breakpointQuery } from './breakpoints.js';
2
+ /*
3
+ * A spread list sets each row on its own two columns, at every width: the
4
+ * term fits its words up to half the row at the start, and the detail
5
+ * takes the rest, its lines end-aligned at the row's end, a space-4 apart
6
+ * (the list's column gap, which a row's own grid does not inherit). The
7
+ * rows still share the hairlines, the padding and the top alignment.
8
+ */
9
+ function spreadRules() {
10
+ return `.sw-description-list-spread { grid-template-columns: minmax(0, 1fr); }
11
+
12
+ .sw-description-list-spread > .sw-description-item {
13
+ column-gap: var(--sw-space-4);
14
+ grid-template-columns: fit-content(50%) minmax(0, 1fr);
15
+ }
16
+
17
+ .sw-description-list-spread .sw-description-detail {
18
+ align-items: flex-end;
19
+ text-align: end;
20
+ }`;
21
+ }
2
22
  /**
3
23
  * The description list: a two-column grid whose items share its columns
4
24
  * (`subgrid`), so every term starts the same column and every detail the
@@ -8,6 +28,7 @@ import { breakpointQuery } from './breakpoints.js';
8
28
  * a term sits over its detail. A term and a detail are columns of lines:
9
29
  * each child is its own line with its own line height, so a caption term
10
30
  * starts level with a caption detail instead of on the list's taller line.
31
+ * `spread` puts each detail at its row's end, beside its term at every width.
11
32
  */
12
33
  export function cssDescriptionListClasses() {
13
34
  return `.sw-description-list {
@@ -49,6 +70,8 @@ export function cssDescriptionListClasses() {
49
70
  .sw-description-list { grid-template-columns: minmax(0, 1fr); }
50
71
  }
51
72
 
73
+ ${spreadRules()}
74
+
52
75
  @media (forced-colors: active) {
53
76
  .sw-description-item + .sw-description-item { border-top-color: CanvasText; }
54
77
  }`;
@@ -56,6 +79,7 @@ export function cssDescriptionListClasses() {
56
79
  export function descriptionListClassCatalog() {
57
80
  return [
58
81
  'sw-description-list',
82
+ 'sw-description-list-spread',
59
83
  'sw-description-item',
60
84
  'sw-description-term',
61
85
  'sw-description-detail',
@@ -0,0 +1,2 @@
1
+ export declare function cssDocumentViewerClasses(): string;
2
+ export declare function documentViewerClassCatalog(): string[];
@@ -0,0 +1,186 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ import { breakpointQuery } from './breakpoints.js';
3
+ import { quietFill } from './quiet-fill.js';
4
+ const label = typographyVariants.label;
5
+ /** How much accent tints a selection of the page's text, in percent. */
6
+ const selectionTint = 30;
7
+ /*
8
+ * The viewer: a quiet grey stage at the large radius holding the page,
9
+ * and under it the page steps around "Page n of m". The stage scrolls
10
+ * sideways when the page is zoomed past its width; it only pans, so two
11
+ * fingers zoom the page, not the screen. The page is centred in it with a
12
+ * space-5 margin (space-3 on a phone), on the surface with the small
13
+ * elevation until PDF.js paints it.
14
+ */
15
+ function stageRules() {
16
+ return `.sw-document-viewer {
17
+ background: ${quietFill};
18
+ border-radius: var(--sw-radius-lg);
19
+ display: flex;
20
+ flex-direction: column;
21
+ min-width: 0;
22
+ padding-block-end: var(--sw-space-4);
23
+ }
24
+
25
+ .sw-document-viewer-stage {
26
+ box-sizing: border-box;
27
+ min-width: 0;
28
+ overflow-x: auto;
29
+ overscroll-behavior-x: contain;
30
+ padding: var(--sw-space-5);
31
+ touch-action: pan-x pan-y;
32
+ }
33
+
34
+ @media ${breakpointQuery('below', 'md')} {
35
+ .sw-document-viewer-stage { padding: var(--sw-space-3); }
36
+ }
37
+
38
+ .sw-document-viewer-stage:focus { outline: none; }
39
+
40
+ .sw-document-viewer-stage:focus-visible {
41
+ border-radius: var(--sw-radius-lg);
42
+ outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
43
+ outline-offset: calc(-1 * var(--sw-focus-ring-width));
44
+ }
45
+
46
+ .sw-document-viewer-page {
47
+ aspect-ratio: 1 / var(--sw-document-page-aspect);
48
+ background: var(--sw-color-surface);
49
+ box-shadow: var(--sw-elevation-sm);
50
+ margin-inline: auto;
51
+ position: relative;
52
+ width: var(--sw-document-page-width);
53
+ }
54
+
55
+ .sw-document-viewer-page > canvas {
56
+ display: block;
57
+ height: 100%;
58
+ width: 100%;
59
+ }`;
60
+ }
61
+ /*
62
+ * The page's text, laid over the drawing by PDF.js's TextLayer: each run
63
+ * transparent at its place and size, so it is read by assistive
64
+ * technology and selected, never seen. These are the rules PDF.js's own
65
+ * viewer gives its text layer, at the scale the viewer sets
66
+ * (--total-scale-factor) with whole-pixel rounding; a selection shows in a
67
+ * tint of the accent.
68
+ */
69
+ function textLayerRules() {
70
+ return `.sw-document-viewer-text {
71
+ --scale-round-x: 1px;
72
+ --scale-round-y: 1px;
73
+ --min-font-size: 1;
74
+ --text-scale-factor: calc(var(--total-scale-factor) * var(--min-font-size));
75
+ --min-font-size-inv: calc(1 / var(--min-font-size));
76
+ forced-color-adjust: none;
77
+ inset: 0;
78
+ letter-spacing: normal;
79
+ line-height: 1;
80
+ overflow: clip;
81
+ position: absolute;
82
+ text-align: initial;
83
+ text-size-adjust: none;
84
+ transform-origin: 0 0;
85
+ word-spacing: normal;
86
+ }
87
+
88
+ .sw-document-viewer-text :is(span, br) {
89
+ color: transparent;
90
+ cursor: text;
91
+ position: absolute;
92
+ transform-origin: 0% 0%;
93
+ user-select: text;
94
+ white-space: pre;
95
+ }
96
+
97
+ .sw-document-viewer-text > :not(.markedContent),
98
+ .sw-document-viewer-text .markedContent span:not(.markedContent) {
99
+ --font-height: 0;
100
+ --scale-x: 1;
101
+ --rotate: 0deg;
102
+ font-size: calc(var(--text-scale-factor) * var(--font-height));
103
+ transform: rotate(var(--rotate)) scaleX(var(--scale-x)) scale(var(--min-font-size-inv));
104
+ }
105
+
106
+ .sw-document-viewer-text .markedContent { display: contents; }
107
+
108
+ .sw-document-viewer-text ::selection {
109
+ background: color-mix(in srgb, var(--sw-color-accent) ${selectionTint}%, transparent);
110
+ color: transparent;
111
+ }`;
112
+ }
113
+ /*
114
+ * The steps are 48-point round neutral Buttons (spacing step 8) with the
115
+ * pager's private chevron, around the page words in label type; with one
116
+ * page only the words show. Loading and a failed page centre their words
117
+ * (and the consumer's actions) in the stage.
118
+ */
119
+ function barRules() {
120
+ return `.sw-document-viewer-bar {
121
+ align-items: center;
122
+ display: flex;
123
+ gap: var(--sw-space-3);
124
+ justify-content: center;
125
+ padding-inline: var(--sw-space-3);
126
+ }
127
+
128
+ .sw-button.sw-document-viewer-step {
129
+ border-radius: var(--sw-radius-pill);
130
+ flex: none;
131
+ min-height: var(--sw-space-8);
132
+ min-width: var(--sw-space-8);
133
+ padding-inline: 0;
134
+ }
135
+
136
+ .sw-document-viewer-status {
137
+ font-family: var(--sw-font-sans);
138
+ font-size: ${label.fontSize}px;
139
+ font-variant-numeric: tabular-nums;
140
+ line-height: ${label.lineHeight}px;
141
+ text-align: center;
142
+ }
143
+
144
+ .sw-document-viewer-message {
145
+ align-items: center;
146
+ display: flex;
147
+ flex-direction: column;
148
+ gap: var(--sw-space-2);
149
+ justify-content: center;
150
+ min-height: calc(4 * var(--sw-space-8));
151
+ text-align: center;
152
+ }
153
+
154
+ .sw-document-viewer-actions {
155
+ display: flex;
156
+ flex-wrap: wrap;
157
+ gap: var(--sw-space-2);
158
+ justify-content: center;
159
+ margin-block-start: var(--sw-space-2);
160
+ }
161
+
162
+ @media (forced-colors: active) {
163
+ .sw-document-viewer { border: 1px solid CanvasText; }
164
+ .sw-document-viewer-page { outline: 1px solid CanvasText; }
165
+ }`;
166
+ }
167
+ export function cssDocumentViewerClasses() {
168
+ return `${stageRules()}
169
+
170
+ ${textLayerRules()}
171
+
172
+ ${barRules()}`;
173
+ }
174
+ export function documentViewerClassCatalog() {
175
+ return [
176
+ 'sw-document-viewer',
177
+ 'sw-document-viewer-stage',
178
+ 'sw-document-viewer-page',
179
+ 'sw-document-viewer-text',
180
+ 'sw-document-viewer-bar',
181
+ 'sw-document-viewer-step',
182
+ 'sw-document-viewer-status',
183
+ 'sw-document-viewer-message',
184
+ 'sw-document-viewer-actions',
185
+ ];
186
+ }
@@ -0,0 +1,2 @@
1
+ export declare function cssFileFieldClasses(): string;
2
+ export declare function fileFieldClassCatalog(): string[];
@@ -0,0 +1,194 @@
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. A
110
+ * photo's preview takes the mark's place: a 3:2 thumbnail a space-8 wide
111
+ * and a space-6 tall, cropped to fill, at the small radius, on the subtle
112
+ * fill while it loads.
113
+ */
114
+ function fileRules() {
115
+ return `.sw-file-field-icon {
116
+ align-items: center;
117
+ color: var(--sw-color-muted);
118
+ display: flex;
119
+ flex: none;
120
+ }
121
+
122
+ .sw-file-field-preview {
123
+ background: var(--sw-color-subtle);
124
+ border-radius: var(--sw-radius-sm);
125
+ display: block;
126
+ flex: none;
127
+ height: var(--sw-space-6);
128
+ object-fit: cover;
129
+ width: var(--sw-space-8);
130
+ }
131
+
132
+ .sw-file-field-file {
133
+ display: flex;
134
+ flex: 1 1 calc(4 * var(--sw-space-8));
135
+ flex-direction: column;
136
+ min-width: 0;
137
+ }
138
+
139
+ .sw-file-field-name {
140
+ font-size: ${label.fontSize}px;
141
+ font-weight: ${label.fontWeight};
142
+ line-height: ${label.lineHeight}px;
143
+ overflow-wrap: anywhere;
144
+ }
145
+
146
+ .sw-file-field-detail {
147
+ color: var(--sw-color-muted);
148
+ font-size: ${caption.fontSize}px;
149
+ line-height: ${caption.lineHeight}px;
150
+ }
151
+
152
+ .sw-file-field-chosen > .sw-button {
153
+ flex: none;
154
+ margin-inline-start: auto;
155
+ }`;
156
+ }
157
+ /* Forced colours: system edges, Highlight for a drag, the button text colour for the words. */
158
+ function forcedColorRules() {
159
+ return `@media (forced-colors: active) {
160
+ .sw-file-field-frame { border-color: CanvasText; }
161
+ .sw-field-invalid .sw-file-field-frame { border-color: Mark; }
162
+ .sw-file-field-frame.sw-file-field-dragging { border-color: Highlight; outline-color: Highlight; }
163
+ .sw-file-field-choose { color: ButtonText; }
164
+ .sw-file-field-zone:disabled,
165
+ .sw-file-field-zone:disabled .sw-file-field-choose { color: GrayText; }
166
+ }`;
167
+ }
168
+ export function cssFileFieldClasses() {
169
+ return `${frameRules()}
170
+
171
+ ${zoneRules()}
172
+
173
+ ${fileRules()}
174
+
175
+ ${forcedColorRules()}`;
176
+ }
177
+ export function fileFieldClassCatalog() {
178
+ return [
179
+ 'sw-file-field',
180
+ 'sw-file-field-frame',
181
+ 'sw-file-field-empty',
182
+ 'sw-file-field-chosen',
183
+ 'sw-file-field-dragging',
184
+ 'sw-file-field-disabled',
185
+ 'sw-file-field-zone',
186
+ 'sw-file-field-choose',
187
+ 'sw-file-field-drop',
188
+ 'sw-file-field-icon',
189
+ 'sw-file-field-preview',
190
+ 'sw-file-field-file',
191
+ 'sw-file-field-name',
192
+ 'sw-file-field-detail',
193
+ ];
194
+ }
@@ -0,0 +1,3 @@
1
+ export declare const warningChipUnchosen = ".sw-filter-chip-warning:not(.sw-filter-chip-quiet) .sw-filter-chip-input:not(:checked) + .sw-filter-chip-face";
2
+ export declare function cssFilterChipToneClasses(): string;
3
+ export declare function filterChipToneClassCatalog(): string[];
@@ -0,0 +1,28 @@
1
+ import { toneTintFill, toneTintInk } from './tone-tint.js';
2
+ /*
3
+ * A warning chip, while it is not chosen, is the warning tint with its
4
+ * words and count in the warning ink, as a warning Notice's (4.5:1 on the
5
+ * tint in every palette). It keeps the chips' hairline, so an error's
6
+ * danger edge still shows on it. Chosen, it is the accent like every chip;
7
+ * with nothing to count it is quiet like every chip. Forced colours draw
8
+ * it as every chip, so its words say why it matters. The focus ring sits
9
+ * outside the face (the chips' ring offset), on the page, not on the tint.
10
+ */
11
+ export const warningChipUnchosen = '.sw-filter-chip-warning:not(.sw-filter-chip-quiet) .sw-filter-chip-input:not(:checked) + .sw-filter-chip-face';
12
+ export function cssFilterChipToneClasses() {
13
+ return `${warningChipUnchosen} {
14
+ background: ${toneTintFill('warning')};
15
+ color: ${toneTintInk('warning')};
16
+ }
17
+
18
+ ${warningChipUnchosen} .sw-filter-chip-count {
19
+ color: inherit;
20
+ }
21
+
22
+ @media (forced-colors: active) {
23
+ ${warningChipUnchosen} { background: Canvas; color: CanvasText; }
24
+ }`;
25
+ }
26
+ export function filterChipToneClassCatalog() {
27
+ return ['sw-filter-chip-warning'];
28
+ }
@@ -1,2 +1,3 @@
1
+ export declare const ringReach = "calc(var(--sw-focus-ring-width) + var(--sw-focus-ring-offset))";
1
2
  export declare function cssFilterChipsLayoutClasses(): string;
2
3
  export declare function filterChipsLayoutClassCatalog(): string[];
@@ -13,7 +13,7 @@
13
13
  * scrolled into view by the browser. The scrollbar stays, thin, so a
14
14
  * pointer without a sideways wheel can still reach the last chip.
15
15
  */
16
- const ringReach = 'calc(var(--sw-focus-ring-width) + var(--sw-focus-ring-offset))';
16
+ export const ringReach = 'calc(var(--sw-focus-ring-width) + var(--sw-focus-ring-offset))';
17
17
  export function cssFilterChipsLayoutClasses() {
18
18
  return `.sw-filter-chip-count-inline {
19
19
  font-variant-numeric: tabular-nums;
@@ -0,0 +1,2 @@
1
+ export declare function cssFilterChipsRowClasses(): string;
2
+ export declare function filterChipsRowClassCatalog(): string[];
@@ -0,0 +1,79 @@
1
+ import { ringReach } from './css-filter-chips-layout.js';
2
+ /*
3
+ * A chips row lays several FilterChips groups on one line, a space-2 apart
4
+ * as chips are, their chips level along the bottom (a group may draw its
5
+ * label above; an error under one lifts its chips above the others'). The
6
+ * `end` group sits at the row's end, or at its own line's end when the row
7
+ * wraps.
8
+ *
9
+ * Wrapping, a group is as wide as its chips and wraps them itself when it
10
+ * is wider than the row. Scrolling, every group's chips stay on one line
11
+ * and the row is the one box that scrolls sideways (never the page),
12
+ * padded by the focus ring's reach and pulled back as a scrolling group
13
+ * is; a group's own scroll gives way, so its chips scroll with the rest.
14
+ * A scrolling group is as wide as its chips (min-content: the chips do not
15
+ * wrap), so a drawn label or an error wraps under them instead of widening
16
+ * the group. The scrolling row is positioned, so a group's visually hidden
17
+ * legend (absolutely placed where it would sit, past the edge) stays inside
18
+ * the box it scrolls in rather than widening the page. These rules follow
19
+ * the groups' own layout rules, which they override.
20
+ */
21
+ export function cssFilterChipsRowClasses() {
22
+ const scroll = '.sw-filter-chips-row-scroll';
23
+ return `.sw-filter-chips-row {
24
+ align-items: flex-end;
25
+ display: flex;
26
+ flex-wrap: wrap;
27
+ gap: var(--sw-space-2);
28
+ max-width: 100%;
29
+ min-width: 0;
30
+ }
31
+
32
+ .sw-filter-chips-row-end {
33
+ display: flex;
34
+ margin-inline-start: auto;
35
+ max-width: 100%;
36
+ min-width: 0;
37
+ }
38
+
39
+ ${scroll} {
40
+ flex-wrap: nowrap;
41
+ margin: calc(-1 * ${ringReach});
42
+ overflow-x: auto;
43
+ overscroll-behavior-x: contain;
44
+ padding: ${ringReach};
45
+ position: relative;
46
+ scrollbar-width: thin;
47
+ }
48
+
49
+ ${scroll} .sw-filter-chips,
50
+ ${scroll} > .sw-filter-chips-row-end {
51
+ flex: none;
52
+ max-width: none;
53
+ }
54
+
55
+ ${scroll} .sw-filter-chips { width: min-content; }
56
+
57
+ ${scroll} .sw-filter-chips-options {
58
+ flex-wrap: nowrap;
59
+ margin: 0;
60
+ overflow: visible;
61
+ padding: 0;
62
+ }
63
+
64
+ ${scroll} .sw-filter-chip {
65
+ flex: none;
66
+ max-width: none;
67
+ }
68
+
69
+ ${scroll} .sw-filter-chip-face {
70
+ white-space: nowrap;
71
+ }`;
72
+ }
73
+ export function filterChipsRowClassCatalog() {
74
+ return [
75
+ 'sw-filter-chips-row',
76
+ 'sw-filter-chips-row-end',
77
+ 'sw-filter-chips-row-scroll',
78
+ ];
79
+ }
@@ -1,5 +1,7 @@
1
1
  import { typographyVariants } from '@scalewing/tokens';
2
+ import { cssFilterChipToneClasses, filterChipToneClassCatalog, } from './css-filter-chip-tones.js';
2
3
  import { cssFilterChipsLayoutClasses, filterChipsLayoutClassCatalog, } from './css-filter-chips-layout.js';
4
+ import { cssFilterChipsRowClasses, filterChipsRowClassCatalog, } from './css-filter-chips-row.js';
3
5
  const label = typographyVariants.label;
4
6
  const data = typographyVariants.data;
5
7
  const caption = typographyVariants.caption;
@@ -126,6 +128,10 @@ export function cssFilterChipsClasses() {
126
128
 
127
129
  ${cssFilterChipsLayoutClasses()}
128
130
 
131
+ ${cssFilterChipToneClasses()}
132
+
133
+ ${cssFilterChipsRowClasses()}
134
+
129
135
  @media (forced-colors: active) {
130
136
  .sw-filter-chip-face { background: Canvas; border-color: CanvasText; color: CanvasText; }
131
137
  .sw-filter-chips-error { color: Mark; }
@@ -148,5 +154,7 @@ export function filterChipsClassCatalog() {
148
154
  'sw-filter-chip-quiet',
149
155
  'sw-filter-chips-error',
150
156
  ...filterChipsLayoutClassCatalog(),
157
+ ...filterChipToneClassCatalog(),
158
+ ...filterChipsRowClassCatalog(),
151
159
  ];
152
160
  }
@@ -0,0 +1,3 @@
1
+ export declare const monospaceFamilies = "ui-monospace, monospace";
2
+ export declare function cssFontMonoClasses(): string;
3
+ export declare function fontMonoClassCatalog(): string[];
@@ -0,0 +1,23 @@
1
+ import { typedInputs } from './css-document.js';
2
+ /*
3
+ * The platform's monospace face by its generic CSS names only, as the
4
+ * forced-colour rules name system colours: no face is chosen here, so
5
+ * there is no type value for the tokens to own. Each platform draws its
6
+ * own (SF Mono, Cascadia, Menlo …).
7
+ */
8
+ export const monospaceFamilies = 'ui-monospace, monospace';
9
+ /*
10
+ * Monospace text, for words read as typed code or marks (a Markdown source
11
+ * being written), at the size the text already has. It outranks the
12
+ * canvas's text controls, which take the page's family, so a `textarea` or
13
+ * a text input can take it too.
14
+ */
15
+ export function cssFontMonoClasses() {
16
+ return `[data-theme] .sw-font-mono,
17
+ [data-theme] :is(${typedInputs}).sw-font-mono {
18
+ font-family: ${monospaceFamilies};
19
+ }`;
20
+ }
21
+ export function fontMonoClassCatalog() {
22
+ return ['sw-font-mono'];
23
+ }
@@ -0,0 +1,2 @@
1
+ export declare function cssListRowTrailingClasses(): string;
2
+ export declare function listRowTrailingClassCatalog(): string[];