@scalewing/react 1.42.0 → 1.45.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 (76) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +65 -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 +19 -2
  6. package/dist/components/Article.js +9 -5
  7. package/dist/components/DescriptionList.d.ts +12 -2
  8. package/dist/components/DescriptionList.js +7 -3
  9. package/dist/components/FileField.d.ts +15 -4
  10. package/dist/components/FileField.js +13 -4
  11. package/dist/components/FilterChips.d.ts +1 -1
  12. package/dist/components/FilterChips.js +1 -1
  13. package/dist/components/FilterChipsRow.d.ts +24 -0
  14. package/dist/components/FilterChipsRow.js +14 -0
  15. package/dist/components/ListRow.d.ts +18 -2
  16. package/dist/components/ListRow.js +7 -4
  17. package/dist/components/action-menu/assert-action-menu.d.ts +13 -0
  18. package/dist/components/action-menu/assert-action-menu.js +21 -0
  19. package/dist/components/description-list-layout.d.ts +10 -0
  20. package/dist/components/description-list-layout.js +13 -0
  21. package/dist/components/file-field/file-field-checks.d.ts +2 -2
  22. package/dist/components/file-field/file-field-checks.js +4 -2
  23. package/dist/components/filter-chips/FilterChip.js +1 -1
  24. package/dist/components/filter-chips/options.d.ts +10 -0
  25. package/dist/components/filter-chips/options.js +8 -0
  26. package/dist/components/filter-chips/validate.d.ts +3 -3
  27. package/dist/components/filter-chips/validate.js +8 -4
  28. package/dist/components/list/ListRowContent.d.ts +9 -2
  29. package/dist/components/list/ListRowContent.js +7 -4
  30. package/dist/components/list/ListRowItem.js +1 -1
  31. package/dist/components/list/row-naming.js +1 -1
  32. package/dist/components/slot.d.ts +9 -0
  33. package/dist/components/slot.js +13 -0
  34. package/dist/components/steps/Step.d.ts +10 -1
  35. package/dist/components/steps/Step.js +15 -19
  36. package/dist/components/steps/StepTitleLine.d.ts +19 -0
  37. package/dist/components/steps/StepTitleLine.js +13 -0
  38. package/dist/components/steps/StepTitleWords.d.ts +27 -0
  39. package/dist/components/steps/StepTitleWords.js +21 -0
  40. package/dist/components/steps/assert-step.d.ts +7 -0
  41. package/dist/components/steps/assert-step.js +19 -0
  42. package/dist/css/css-action-menu-trigger.d.ts +6 -2
  43. package/dist/css/css-action-menu-trigger.js +50 -2
  44. package/dist/css/css-action-menu.js +4 -2
  45. package/dist/css/css-components.js +3 -0
  46. package/dist/css/css-description-list.d.ts +1 -0
  47. package/dist/css/css-description-list.js +24 -0
  48. package/dist/css/css-file-field.js +15 -1
  49. package/dist/css/css-filter-chip-tones.d.ts +3 -0
  50. package/dist/css/css-filter-chip-tones.js +28 -0
  51. package/dist/css/css-filter-chips-layout.d.ts +1 -0
  52. package/dist/css/css-filter-chips-layout.js +1 -1
  53. package/dist/css/css-filter-chips-row.d.ts +2 -0
  54. package/dist/css/css-filter-chips-row.js +79 -0
  55. package/dist/css/css-filter-chips.js +8 -0
  56. package/dist/css/css-font-mono.d.ts +3 -0
  57. package/dist/css/css-font-mono.js +23 -0
  58. package/dist/css/css-list-row-truncate.d.ts +2 -0
  59. package/dist/css/css-list-row-truncate.js +29 -0
  60. package/dist/css/css-list.js +5 -1
  61. package/dist/css/css-steps-title-detail.d.ts +2 -0
  62. package/dist/css/css-steps-title-detail.js +36 -0
  63. package/dist/css/css-steps.d.ts +2 -2
  64. package/dist/css/css-steps.js +6 -2
  65. package/dist/css/css-utilities.js +3 -0
  66. package/dist/css/spacing-classes.d.ts +1 -1
  67. package/dist/css/spacing-classes.js +1 -0
  68. package/dist/css/stylesheet.js +2 -0
  69. package/dist/index.d.ts +6 -4
  70. package/dist/index.js +3 -2
  71. package/dist/list-options.d.ts +7 -6
  72. package/dist/list-options.js +8 -6
  73. package/dist/styles.css +164 -0
  74. package/package.json +1 -1
  75. package/dist/components/list/row-slot.d.ts +0 -8
  76. package/dist/components/list/row-slot.js +0 -12
@@ -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',
@@ -106,7 +106,10 @@ function zoneRules() {
106
106
  }
107
107
  /*
108
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.
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.
110
113
  */
111
114
  function fileRules() {
112
115
  return `.sw-file-field-icon {
@@ -116,6 +119,16 @@ function fileRules() {
116
119
  flex: none;
117
120
  }
118
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
+
119
132
  .sw-file-field-file {
120
133
  display: flex;
121
134
  flex: 1 1 calc(4 * var(--sw-space-8));
@@ -173,6 +186,7 @@ export function fileFieldClassCatalog() {
173
186
  'sw-file-field-choose',
174
187
  'sw-file-field-drop',
175
188
  'sw-file-field-icon',
189
+ 'sw-file-field-preview',
176
190
  'sw-file-field-file',
177
191
  'sw-file-field-name',
178
192
  'sw-file-field-detail',
@@ -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 cssListRowTruncateClasses(): string;
2
+ export declare function listRowTruncateClassCatalog(): string[];
@@ -0,0 +1,29 @@
1
+ /*
2
+ * A truncated row keeps its title and its detail to one line each, cut
3
+ * with "…" where they do not fit. The title's words sit in their own box
4
+ * (`sw-list-row-title-text`) beside the unread dot, so the cut never hides
5
+ * the dot; the title is a one-line flex row centring them. The label
6
+ * column already shrinks (`min-width: 0`), so the value, the tag and the
7
+ * action keep their place and their words whole.
8
+ */
9
+ export function cssListRowTruncateClasses() {
10
+ return `.sw-list-row-truncate .sw-list-row-title {
11
+ align-items: center;
12
+ display: flex;
13
+ min-width: 0;
14
+ }
15
+
16
+ .sw-list-row-truncate .sw-list-row-unread { flex: none; }
17
+
18
+ .sw-list-row-truncate .sw-list-row-title-text,
19
+ .sw-list-row-truncate .sw-list-row-detail {
20
+ min-width: 0;
21
+ overflow: hidden;
22
+ overflow-wrap: normal;
23
+ text-overflow: ellipsis;
24
+ white-space: nowrap;
25
+ }`;
26
+ }
27
+ export function listRowTruncateClassCatalog() {
28
+ return ['sw-list-row-truncate', 'sw-list-row-title-text'];
29
+ }
@@ -1,6 +1,7 @@
1
1
  import { typographyVariants } from '@scalewing/tokens';
2
2
  import { cssListRowClasses, listRowClassCatalog } from './css-list-row.js';
3
3
  import { cssListRowTrailingClasses, listRowTrailingClassCatalog, } from './css-list-row-trailing.js';
4
+ import { cssListRowTruncateClasses, listRowTruncateClassCatalog, } from './css-list-row-truncate.js';
4
5
  import { blockEdgeShadeRules, scrollRegionRules } from './css-scroll-region.js';
5
6
  const label = typographyVariants.label;
6
7
  const caption = typographyVariants.caption;
@@ -72,7 +73,9 @@ ${boundedRules()}
72
73
 
73
74
  ${cssListRowClasses()}
74
75
 
75
- ${cssListRowTrailingClasses()}`;
76
+ ${cssListRowTrailingClasses()}
77
+
78
+ ${cssListRowTruncateClasses()}`;
76
79
  }
77
80
  export function listClassCatalog() {
78
81
  return [
@@ -85,5 +88,6 @@ export function listClassCatalog() {
85
88
  'sw-list-group-footer',
86
89
  ...listRowClassCatalog(),
87
90
  ...listRowTrailingClassCatalog(),
91
+ ...listRowTruncateClassCatalog(),
88
92
  ];
89
93
  }
@@ -0,0 +1,2 @@
1
+ export declare function cssStepsTitleDetailClasses(): string;
2
+ export declare function stepsTitleDetailClassCatalog(): string[];
@@ -0,0 +1,36 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ const body = typographyVariants.body;
3
+ const label = typographyVariants.label;
4
+ /*
5
+ * An open step's muted words after its title ("Optional", "Wetlands done ·
6
+ * Woodlands empty"): the title and the words share one line that wraps, the
7
+ * words on the title's baseline a space-2 after it, or on a line of their
8
+ * own under the title when they do not fit beside it. The line gives way
9
+ * to a done step's summary and Edit in an open list, as the title does.
10
+ * The words are the label size at the body's weight in the muted colour,
11
+ * a skipped step's reason's colour beside its title; a long word breaks
12
+ * rather than pass the panel.
13
+ */
14
+ export function cssStepsTitleDetailClasses() {
15
+ return `.sw-steps-title-line {
16
+ align-items: baseline;
17
+ column-gap: var(--sw-space-2);
18
+ display: flex;
19
+ flex: 0 1 auto;
20
+ flex-wrap: wrap;
21
+ min-width: 0;
22
+ }
23
+
24
+ .sw-steps-title-detail {
25
+ color: var(--sw-color-muted);
26
+ font-size: ${label.fontSize}px;
27
+ font-weight: ${body.fontWeight};
28
+ letter-spacing: ${label.letterSpacing}px;
29
+ line-height: ${label.lineHeight}px;
30
+ min-width: 0;
31
+ overflow-wrap: anywhere;
32
+ }`;
33
+ }
34
+ export function stepsTitleDetailClassCatalog() {
35
+ return ['sw-steps-title-line', 'sw-steps-title-detail'];
36
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The one-page vertical stepper: an ordered list of glass panels a small
3
- * gap apart. Each has a header line (marker, title, and on a done step its
4
- * summary and Edit) and, while open (current or error), a body indented to
3
+ * gap apart. Each has a header line (marker, title, an open step's muted
4
+ * words beside it, and on a done step its summary and Edit) and, while open (current or error), a body indented to
5
5
  * the title. An open step's title is the title variant; a folded one's is
6
6
  * body size at label weight, muted ahead of the form or skipped. In an
7
7
  * open list (`sw-steps-open`) every step is open: each panel takes the open
@@ -1,5 +1,6 @@
1
1
  import { typographyVariants } from '@scalewing/tokens';
2
2
  import { checkStrokeIn } from './chevron.js';
3
+ import { cssStepsTitleDetailClasses, stepsTitleDetailClassCatalog, } from './css-steps-title-detail.js';
3
4
  const body = typographyVariants.body;
4
5
  const caption = typographyVariants.caption;
5
6
  const label = typographyVariants.label;
@@ -69,8 +70,8 @@ function forcedColorRules() {
69
70
  }
70
71
  /**
71
72
  * The one-page vertical stepper: an ordered list of glass panels a small
72
- * gap apart. Each has a header line (marker, title, and on a done step its
73
- * summary and Edit) and, while open (current or error), a body indented to
73
+ * gap apart. Each has a header line (marker, title, an open step's muted
74
+ * words beside it, and on a done step its summary and Edit) and, while open (current or error), a body indented to
74
75
  * the title. An open step's title is the title variant; a folded one's is
75
76
  * body size at label weight, muted ahead of the form or skipped. In an
76
77
  * open list (`sw-steps-open`) every step is open: each panel takes the open
@@ -190,6 +191,8 @@ export function cssStepsClasses() {
190
191
  min-width: 0;
191
192
  }
192
193
 
194
+ ${cssStepsTitleDetailClasses()}
195
+
193
196
  ${markerRules()}
194
197
 
195
198
  ${connectorRules()}
@@ -214,5 +217,6 @@ export function stepsClassCatalog() {
214
217
  'sw-steps-edit',
215
218
  'sw-steps-body',
216
219
  'sw-steps-region',
220
+ ...stepsTitleDetailClassCatalog(),
217
221
  ];
218
222
  }
@@ -41,6 +41,9 @@ const layoutRules = {
41
41
  'sw-grow': '.sw-grow { flex-grow: 1; }',
42
42
  'sw-full-width': '.sw-full-width { width: 100%; }',
43
43
  'sw-container': '.sw-container { width: 100%; max-width: var(--sw-container-max); margin-inline: auto; }',
44
+ // A narrower centred column at the reading width (Article's), for a
45
+ // form or text that reads better than it would across the container.
46
+ 'sw-container-reading': '.sw-container-reading { width: 100%; max-width: var(--sw-reading-max); margin-inline: auto; }',
44
47
  'sw-sr-only': `.sw-sr-only { ${visuallyHiddenDeclarations} }`,
45
48
  'sw-align-start': '.sw-align-start { align-items: flex-start; }',
46
49
  'sw-align-center': '.sw-align-center { align-items: center; }',
@@ -7,4 +7,4 @@ export type SpacingKind = 'padding' | 'gap';
7
7
  export declare function spacingClass(kind: SpacingKind, axis: PaddingAxis | GapAxis, step: SpacingStep): string;
8
8
  export declare function paddingClassNames(): string[];
9
9
  export declare function gapClassNames(): string[];
10
- export declare const layoutClassNames: readonly ["sw-stack", "sw-inline", "sw-wrap", "sw-grow", "sw-full-width", "sw-container", "sw-sr-only", "sw-align-start", "sw-align-center", "sw-align-end", "sw-align-stretch", "sw-justify-start", "sw-justify-center", "sw-justify-end", "sw-justify-between"];
10
+ export declare const layoutClassNames: readonly ["sw-stack", "sw-inline", "sw-wrap", "sw-grow", "sw-full-width", "sw-container", "sw-container-reading", "sw-sr-only", "sw-align-start", "sw-align-center", "sw-align-end", "sw-align-stretch", "sw-justify-start", "sw-justify-center", "sw-justify-end", "sw-justify-between"];
@@ -28,6 +28,7 @@ export const layoutClassNames = [
28
28
  'sw-grow',
29
29
  'sw-full-width',
30
30
  'sw-container',
31
+ 'sw-container-reading',
31
32
  'sw-sr-only',
32
33
  'sw-align-start',
33
34
  'sw-align-center',
@@ -27,6 +27,7 @@ import { descriptionListClassCatalog } from './css-description-list.js';
27
27
  import { tabsClassCatalog } from './css-tabs.js';
28
28
  import { responsiveClassCatalog } from './css-responsive.js';
29
29
  import { filterChipsClassCatalog } from './css-filter-chips.js';
30
+ import { fontMonoClassCatalog } from './css-font-mono.js';
30
31
  import { gridClassCatalog } from './css-grid.js';
31
32
  import { gridSpanClassCatalog } from './css-grid-span.js';
32
33
  import { denominationGridClassCatalog } from './css-denomination-grid.js';
@@ -126,6 +127,7 @@ export function utilityClassCatalog() {
126
127
  ...descriptionListClassCatalog(),
127
128
  ...tabsClassCatalog(),
128
129
  ...filterChipsClassCatalog(),
130
+ ...fontMonoClassCatalog(),
129
131
  ...gridClassCatalog(),
130
132
  ...gridSpanClassCatalog(),
131
133
  ...denominationGridClassCatalog(),
package/dist/index.d.ts CHANGED
@@ -67,13 +67,15 @@ export type { Breakpoint, BreakpointDirection, VisibilityBreakpoint, } from './c
67
67
  export { breakpointQuery } from './css/breakpoints.js';
68
68
  export { Separator } from './components/Separator.js';
69
69
  export type { SeparatorOrientation, SeparatorProps, } from './components/Separator.js';
70
- export { DescriptionItem, DescriptionList, } from './components/DescriptionList.js';
71
- export type { DescriptionItemProps, DescriptionListProps, } from './components/DescriptionList.js';
70
+ export { DescriptionItem, DescriptionList, descriptionListLayouts, } from './components/DescriptionList.js';
71
+ export type { DescriptionItemProps, DescriptionListLayout, DescriptionListProps, } from './components/DescriptionList.js';
72
72
  export { Grid } from './components/Grid.js';
73
73
  export type { GridColumns, GridProps } from './components/Grid.js';
74
74
  export type { GridColumnSpan } from './css/css-grid-span.js';
75
75
  export type { ColumnSpanProps } from './column-span-classes.js';
76
76
  export { DenominationGrid, denominationCellToneAppearances, denominationGridFrames, denominationLabelAppearances, denominationNegativeAppearances, denominationTotalEmphases, denominationTransposeBreakpoints, } from './components/DenominationGrid.js';
77
77
  export type { DenominationCellToneAppearance, DenominationGridColumn, DenominationGridEntry, DenominationGridFrame, DenominationGridLayout, DenominationGridNegativeAppearance, DenominationGridProps, DenominationGridRow, DenominationGridRowEmphasis, DenominationGridRowRole, DenominationGridTone, DenominationGridValueRow, DenominationLabelAppearance, DenominationLabelWidth, DenominationTotalEmphasis, DenominationTransposeBreakpoint, } from './components/DenominationGrid.js';
78
- export { FilterChips, filterChipCountAppearances, filterChipsOverflows, } from './components/FilterChips.js';
79
- export type { FilterChipCountAppearance, FilterChipOption, FilterChipsOverflow, FilterChipsProps, } from './components/FilterChips.js';
78
+ export { FilterChips, filterChipCountAppearances, filterChipsOverflows, filterChipTones, } from './components/FilterChips.js';
79
+ export { FilterChipsRow } from './components/FilterChipsRow.js';
80
+ export type { FilterChipsRowProps } from './components/FilterChipsRow.js';
81
+ export type { FilterChipCountAppearance, FilterChipOption, FilterChipsOverflow, FilterChipsProps, FilterChipTone, } from './components/FilterChips.js';
package/dist/index.js CHANGED
@@ -60,7 +60,8 @@ export { themeCanvases } from './css/css-canvas-grouped.js';
60
60
  export { utilityClassCatalog } from './css/stylesheet.js';
61
61
  export { breakpointQuery } from './css/breakpoints.js';
62
62
  export { Separator } from './components/Separator.js';
63
- export { DescriptionItem, DescriptionList, } from './components/DescriptionList.js';
63
+ export { DescriptionItem, DescriptionList, descriptionListLayouts, } from './components/DescriptionList.js';
64
64
  export { Grid } from './components/Grid.js';
65
65
  export { DenominationGrid, denominationCellToneAppearances, denominationGridFrames, denominationLabelAppearances, denominationNegativeAppearances, denominationTotalEmphases, denominationTransposeBreakpoints, } from './components/DenominationGrid.js';
66
- export { FilterChips, filterChipCountAppearances, filterChipsOverflows, } from './components/FilterChips.js';
66
+ export { FilterChips, filterChipCountAppearances, filterChipsOverflows, filterChipTones, } from './components/FilterChips.js';
67
+ export { FilterChipsRow } from './components/FilterChipsRow.js';
@@ -41,6 +41,7 @@ export declare function assertListGroup({ label, labelledBy, variant, maxHeight,
41
41
  export declare function listMaxHeightStyle(maxHeight: ListGroupMaxHeight): CSSProperties;
42
42
  export type ListRowInput = {
43
43
  title: string;
44
+ titleLang: string | undefined;
44
45
  tone: unknown;
45
46
  titleAppearance: unknown;
46
47
  valueTone: unknown;
@@ -54,12 +55,12 @@ export type ListRowInput = {
54
55
  unreadLabel: string | undefined;
55
56
  };
56
57
  /**
57
- * Fails closed on a ListRow it cannot draw: an empty title or value, an
58
- * unknown tone, title appearance, value tone, badge tone or accessory, a
59
- * `valueDetail`, `valueTone` or `valueBadge` with no value, a value both
60
- * toned and a badge, `selected` on a row that is not a button or link
61
- * (its check would be a state nothing can read), or an unread row with no
62
- * words for its dot (a colour alone says nothing).
58
+ * Fails closed on a ListRow it cannot draw: an empty title, titleLang or
59
+ * value, an unknown tone, title appearance, value tone, badge tone or
60
+ * accessory, a `valueDetail`, `valueTone` or `valueBadge` with no value, a
61
+ * value both toned and a badge, `selected` on a row that is not a button or
62
+ * link (its check would be a state nothing can read), or an unread row with
63
+ * no words for its dot (a colour alone says nothing).
63
64
  */
64
65
  export declare function assertListRow(input: ListRowInput): void;
65
66
  /**
@@ -38,16 +38,18 @@ export function listMaxHeightStyle(maxHeight) {
38
38
  return { '--sw-list-max-rows': maxHeight.rows };
39
39
  }
40
40
  /**
41
- * Fails closed on a ListRow it cannot draw: an empty title or value, an
42
- * unknown tone, title appearance, value tone, badge tone or accessory, a
43
- * `valueDetail`, `valueTone` or `valueBadge` with no value, a value both
44
- * toned and a badge, `selected` on a row that is not a button or link
45
- * (its check would be a state nothing can read), or an unread row with no
46
- * words for its dot (a colour alone says nothing).
41
+ * Fails closed on a ListRow it cannot draw: an empty title, titleLang or
42
+ * value, an unknown tone, title appearance, value tone, badge tone or
43
+ * accessory, a `valueDetail`, `valueTone` or `valueBadge` with no value, a
44
+ * value both toned and a badge, `selected` on a row that is not a button or
45
+ * link (its check would be a state nothing can read), or an unread row with
46
+ * no words for its dot (a colour alone says nothing).
47
47
  */
48
48
  export function assertListRow(input) {
49
49
  if (isBlank(input.title))
50
50
  throw new RangeError('ListRow title must be non-empty text');
51
+ if (input.titleLang !== undefined && isBlank(input.titleLang))
52
+ throw new RangeError('ListRow titleLang must be a non-empty language tag');
51
53
  if (!isOneOf(listRowTones, input.tone))
52
54
  throw new RangeError(`Unknown ListRow tone: ${String(input.tone)}`);
53
55
  if (!isOneOf(listRowTitleAppearances, input.titleAppearance))