@scalewing/react 1.39.0 → 1.41.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.
- package/CHANGELOG.md +33 -0
- package/README.md +255 -5
- package/dist/calendar-labels.d.ts +2 -0
- package/dist/calendar-labels.js +7 -0
- package/dist/calendar-month.d.ts +6 -0
- package/dist/calendar-month.js +15 -0
- package/dist/components/BarChart.d.ts +20 -4
- package/dist/components/BarChart.js +13 -6
- package/dist/components/ButtonGroup.d.ts +8 -1
- package/dist/components/ButtonGroup.js +11 -2
- package/dist/components/DateField.d.ts +14 -2
- package/dist/components/DateField.js +14 -11
- package/dist/components/DateRangeButton.d.ts +65 -0
- package/dist/components/DateRangeButton.js +54 -0
- package/dist/components/DenominationGrid.d.ts +3 -2
- package/dist/components/DenominationGrid.js +21 -3
- package/dist/components/Dialog.d.ts +29 -13
- package/dist/components/Dialog.js +22 -20
- package/dist/components/Field.d.ts +13 -2
- package/dist/components/Field.js +14 -38
- package/dist/components/FilterChips.d.ts +7 -37
- package/dist/components/FilterChips.js +32 -24
- package/dist/components/ListGroup.d.ts +33 -0
- package/dist/components/ListGroup.js +19 -0
- package/dist/components/ListRow.d.ts +60 -0
- package/dist/components/ListRow.js +60 -0
- package/dist/components/NavCount.d.ts +21 -0
- package/dist/components/NavCount.js +23 -0
- package/dist/components/SectionNav.js +1 -8
- package/dist/components/SegmentedControl.d.ts +17 -1
- package/dist/components/SegmentedControl.js +11 -3
- package/dist/components/StatTile.d.ts +11 -4
- package/dist/components/StatTile.js +11 -4
- package/dist/components/Switch.d.ts +16 -1
- package/dist/components/Switch.js +17 -6
- package/dist/components/action-bar/ActionBarSummary.d.ts +10 -2
- package/dist/components/action-bar/ActionBarSummary.js +11 -2
- package/dist/components/{date-field → calendar}/CalendarGrid.d.ts +17 -2
- package/dist/components/{date-field → calendar}/CalendarGrid.js +11 -3
- package/dist/components/calendar/CalendarPopover.d.ts +25 -0
- package/dist/components/calendar/CalendarPopover.js +22 -0
- package/dist/components/calendar/MonthStep.d.ts +16 -0
- package/dist/components/calendar/MonthStep.js +17 -0
- package/dist/components/calendar/use-grid-focus.d.ts +18 -0
- package/dist/components/calendar/use-grid-focus.js +35 -0
- package/dist/components/calendar/wrap-tab.d.ts +7 -0
- package/dist/components/calendar/wrap-tab.js +29 -0
- package/dist/components/date-field/CalendarDialog.js +9 -67
- package/dist/components/date-field/CalendarEntryButton.d.ts +24 -0
- package/dist/components/date-field/CalendarEntryButton.js +16 -0
- package/dist/components/date-field/CalendarHeader.js +2 -11
- package/dist/components/date-field/TypedEntry.d.ts +26 -0
- package/dist/components/date-field/TypedEntry.js +13 -0
- package/dist/components/date-range/DateRangePopover.d.ts +7 -0
- package/dist/components/date-range/DateRangePopover.js +17 -0
- package/dist/components/date-range/DateRangeSheet.d.ts +7 -0
- package/dist/components/date-range/DateRangeSheet.js +15 -0
- package/dist/components/date-range/RangeMonths.d.ts +28 -0
- package/dist/components/date-range/RangeMonths.js +50 -0
- package/dist/components/date-range/RangePresets.d.ts +16 -0
- package/dist/components/date-range/RangePresets.js +10 -0
- package/dist/components/date-range/RangeSummary.d.ts +15 -0
- package/dist/components/date-range/RangeSummary.js +11 -0
- package/dist/components/date-range/range-panel-props.d.ts +31 -0
- package/dist/components/date-range/range-panel-props.js +1 -0
- package/dist/components/date-range/use-range-popup.d.ts +21 -0
- package/dist/components/date-range/use-range-popup.js +53 -0
- package/dist/components/denomination-grid/CountCell.d.ts +16 -0
- package/dist/components/denomination-grid/CountCell.js +14 -0
- package/dist/components/denomination-grid/DenominationStrip.d.ts +4 -1
- package/dist/components/denomination-grid/DenominationStrip.js +2 -2
- package/dist/components/denomination-grid/EntryCell.d.ts +3 -1
- package/dist/components/denomination-grid/EntryCell.js +2 -2
- package/dist/components/denomination-grid/StripRow.js +1 -10
- package/dist/components/denomination-grid/TransposedStrip.d.ts +17 -0
- package/dist/components/denomination-grid/TransposedStrip.js +43 -0
- package/dist/components/denomination-grid/types.d.ts +31 -0
- package/dist/components/denomination-grid/types.js +7 -1
- package/dist/components/denomination-grid/validate-options.d.ts +7 -0
- package/dist/components/denomination-grid/validate-options.js +27 -0
- package/dist/components/dialog/DialogFooter.d.ts +6 -5
- package/dist/components/dialog/DialogFooter.js +6 -6
- package/dist/components/dialog/validate.d.ts +24 -0
- package/dist/components/dialog/validate.js +23 -0
- package/dist/components/field/field-checks.d.ts +34 -0
- package/dist/components/field/field-checks.js +42 -0
- package/dist/components/filter-chips/FilterChip.d.ts +16 -0
- package/dist/components/filter-chips/FilterChip.js +20 -0
- package/dist/components/filter-chips/options.d.ts +75 -0
- package/dist/components/filter-chips/options.js +11 -0
- package/dist/components/filter-chips/validate.d.ts +9 -0
- package/dist/components/filter-chips/validate.js +48 -0
- package/dist/components/link-press.d.ts +7 -0
- package/dist/components/link-press.js +13 -0
- package/dist/components/list/ListRowAccessoryMark.d.ts +5 -0
- package/dist/components/list/ListRowAccessoryMark.js +7 -0
- package/dist/components/list/ListRowContent.d.ts +22 -0
- package/dist/components/list/ListRowContent.js +11 -0
- package/dist/components/list/list-row-container.d.ts +5 -0
- package/dist/components/list/list-row-container.js +6 -0
- package/dist/components/use-media-query.d.ts +5 -0
- package/dist/components/use-media-query.js +18 -0
- package/dist/css/chart-tones.d.ts +2 -0
- package/dist/css/chart-tones.js +5 -1
- package/dist/css/chevron.d.ts +6 -0
- package/dist/css/chevron.js +14 -0
- package/dist/css/css-bar-chart.d.ts +17 -2
- package/dist/css/css-bar-chart.js +38 -7
- package/dist/css/css-button-group-attached.d.ts +3 -0
- package/dist/css/css-button-group-attached.js +26 -5
- package/dist/css/css-button-group-track.js +1 -1
- package/dist/css/css-canvas-grouped.d.ts +17 -0
- package/dist/css/css-canvas-grouped.js +40 -0
- package/dist/css/css-checkbox.js +2 -2
- package/dist/css/css-components.js +15 -0
- package/dist/css/css-count-pill.d.ts +2 -0
- package/dist/css/css-count-pill.js +54 -0
- package/dist/css/css-date-field-calendar-entry.d.ts +11 -0
- package/dist/css/css-date-field-calendar-entry.js +50 -0
- package/dist/css/css-date-field.js +7 -2
- package/dist/css/css-date-range-presets.d.ts +2 -0
- package/dist/css/css-date-range-presets.js +109 -0
- package/dist/css/css-date-range.d.ts +2 -0
- package/dist/css/css-date-range.js +197 -0
- package/dist/css/css-denomination-grid.js +4 -0
- package/dist/css/css-denomination-transposed.d.ts +4 -0
- package/dist/css/css-denomination-transposed.js +178 -0
- package/dist/css/css-dialog-canvas.d.ts +3 -0
- package/dist/css/css-dialog-canvas.js +20 -0
- package/dist/css/css-dialog-frame.js +19 -2
- package/dist/css/css-dialog-grabber.d.ts +4 -0
- package/dist/css/css-dialog-grabber.js +56 -0
- package/dist/css/css-dialog.js +3 -2
- package/dist/css/css-document.js +3 -0
- package/dist/css/css-field-width.d.ts +12 -0
- package/dist/css/css-field-width.js +49 -0
- package/dist/css/css-field.js +4 -0
- package/dist/css/css-filter-chips-layout.d.ts +2 -0
- package/dist/css/css-filter-chips-layout.js +42 -0
- package/dist/css/css-filter-chips.js +4 -0
- package/dist/css/css-list-row.d.ts +8 -0
- package/dist/css/css-list-row.js +209 -0
- package/dist/css/css-list.d.ts +3 -0
- package/dist/css/css-list.js +85 -0
- package/dist/css/css-scroll-region.d.ts +18 -0
- package/dist/css/css-scroll-region.js +41 -0
- package/dist/css/css-section-nav-filled.js +2 -25
- package/dist/css/css-segmented-sizing.d.ts +13 -0
- package/dist/css/css-segmented-sizing.js +66 -0
- package/dist/css/css-segmented.js +4 -0
- package/dist/css/css-stat-tile.d.ts +7 -0
- package/dist/css/css-stat-tile.js +16 -0
- package/dist/css/css-steps.js +2 -2
- package/dist/css/css-switch.d.ts +6 -0
- package/dist/css/css-switch.js +39 -0
- package/dist/css/css-table-bounded-edges.js +4 -27
- package/dist/css/range-band.d.ts +2 -0
- package/dist/css/range-band.js +7 -0
- package/dist/css/stacking.d.ts +1 -0
- package/dist/css/stacking.js +6 -3
- package/dist/css/stylesheet.js +10 -0
- package/dist/date-field-labels.d.ts +5 -0
- package/dist/date-field-labels.js +1 -0
- package/dist/date-range-draft.d.ts +26 -0
- package/dist/date-range-draft.js +36 -0
- package/dist/date-range-input.d.ts +26 -0
- package/dist/date-range-input.js +58 -0
- package/dist/date-range-labels.d.ts +22 -0
- package/dist/date-range-labels.js +26 -0
- package/dist/date-range-view.d.ts +12 -0
- package/dist/date-range-view.js +29 -0
- package/dist/date-range-words.d.ts +11 -0
- package/dist/date-range-words.js +40 -0
- package/dist/index.d.ts +16 -9
- package/dist/index.js +14 -7
- package/dist/list-options.d.ts +71 -0
- package/dist/list-options.js +84 -0
- package/dist/styles.css +863 -41
- package/dist/theme/ThemeProvider.d.ts +11 -1
- package/dist/theme/ThemeProvider.js +4 -2
- package/package.json +1 -1
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { checkStrokeIn, chevronStrokeIn } from './chevron.js';
|
|
3
|
+
import { chartColorMix, chartInkMixes } from './chart-tones.js';
|
|
4
|
+
import { tableCellTones } from './css-table-ledger.js';
|
|
5
|
+
import { quietFill } from './quiet-fill.js';
|
|
6
|
+
import { coarsePointerQuery, touchTarget } from './touch-target.js';
|
|
7
|
+
const label = typographyVariants.label;
|
|
8
|
+
const body = typographyVariants.body;
|
|
9
|
+
const caption = typographyVariants.caption;
|
|
10
|
+
/* Centres a mark of `size` on the title's first line. */
|
|
11
|
+
function onTitleLine(size) {
|
|
12
|
+
return `calc((${label.lineHeight}px - ${size}) / 2)`;
|
|
13
|
+
}
|
|
14
|
+
/*
|
|
15
|
+
* A row: the leading mark, the title over its detail, the value over its
|
|
16
|
+
* detail at the end, then the chevron or check, each lined up with the
|
|
17
|
+
* title's first line. A pressable row is the whole button or link: a
|
|
18
|
+
* quiet fill under the pointer, the focus ring inside its edge, 44 px on a
|
|
19
|
+
* coarse pointer. Plain rows (inside a Card) have no inline padding.
|
|
20
|
+
*/
|
|
21
|
+
function rowRules() {
|
|
22
|
+
return `.sw-list-row {
|
|
23
|
+
align-items: flex-start;
|
|
24
|
+
appearance: none;
|
|
25
|
+
background: transparent;
|
|
26
|
+
border: 0;
|
|
27
|
+
box-sizing: border-box;
|
|
28
|
+
color: var(--sw-color-text);
|
|
29
|
+
display: flex;
|
|
30
|
+
font-family: var(--sw-font-sans);
|
|
31
|
+
font-size: ${label.fontSize}px;
|
|
32
|
+
gap: var(--sw-space-3);
|
|
33
|
+
line-height: ${label.lineHeight}px;
|
|
34
|
+
margin: 0;
|
|
35
|
+
padding: var(--sw-space-3) var(--sw-space-4);
|
|
36
|
+
text-align: start;
|
|
37
|
+
text-decoration: none;
|
|
38
|
+
width: 100%;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.sw-list-group-plain .sw-list-row { padding-inline: 0; }
|
|
42
|
+
|
|
43
|
+
.sw-list-row-pressable { cursor: pointer; }
|
|
44
|
+
|
|
45
|
+
@media (hover: hover) {
|
|
46
|
+
.sw-list-row-pressable:hover:not(.sw-list-row-disabled) { background: ${quietFill}; }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.sw-list-row-pressable:active:not(.sw-list-row-disabled) { background: ${quietFill}; }
|
|
50
|
+
|
|
51
|
+
.sw-list-row-pressable:focus { outline: none; }
|
|
52
|
+
|
|
53
|
+
.sw-list-row-pressable:focus-visible {
|
|
54
|
+
outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
|
|
55
|
+
outline-offset: calc(-1 * var(--sw-focus-ring-width));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* A link row keeps the text colour and the inset ring over the canvas link rules. */
|
|
59
|
+
[data-theme] a.sw-list-row,
|
|
60
|
+
[data-theme] a.sw-list-row:hover {
|
|
61
|
+
color: var(--sw-color-text);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
[data-theme] a.sw-list-row:focus-visible {
|
|
65
|
+
outline-offset: calc(-1 * var(--sw-focus-ring-width));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.sw-list-row-disabled {
|
|
69
|
+
cursor: not-allowed;
|
|
70
|
+
opacity: var(--sw-disabled-opacity);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@media ${coarsePointerQuery} {
|
|
74
|
+
.sw-list-row-pressable { min-height: ${touchTarget}; }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Forced colours drop the fill, so a hovered row is outlined instead, as a pressable table row is. */
|
|
78
|
+
@media (forced-colors: active) {
|
|
79
|
+
.sw-list-row-pressable:hover:not(.sw-list-row-disabled) {
|
|
80
|
+
outline: var(--sw-focus-ring-width) solid Highlight;
|
|
81
|
+
outline-offset: calc(-1 * var(--sw-focus-ring-width));
|
|
82
|
+
}
|
|
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
|
+
}
|
|
99
|
+
function partRules() {
|
|
100
|
+
const tones = tableCellTones
|
|
101
|
+
.map((tone) => `.sw-list-row-value-${tone} { color: var(--sw-color-${tone}); }`)
|
|
102
|
+
.join('\n');
|
|
103
|
+
return `.sw-list-row-leading {
|
|
104
|
+
align-items: center;
|
|
105
|
+
display: flex;
|
|
106
|
+
flex: none;
|
|
107
|
+
height: ${label.lineHeight}px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.sw-list-row-label,
|
|
111
|
+
.sw-list-row-end {
|
|
112
|
+
display: flex;
|
|
113
|
+
flex-direction: column;
|
|
114
|
+
min-width: 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.sw-list-row-label { flex: 1 1 auto; }
|
|
118
|
+
|
|
119
|
+
.sw-list-row-end {
|
|
120
|
+
align-items: flex-end;
|
|
121
|
+
flex: none;
|
|
122
|
+
max-width: 50%;
|
|
123
|
+
text-align: end;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.sw-list-row-title {
|
|
127
|
+
font-weight: ${label.fontWeight};
|
|
128
|
+
overflow-wrap: anywhere;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.sw-list-row-title-plain { font-weight: ${body.fontWeight}; }
|
|
132
|
+
|
|
133
|
+
.sw-list-row-title-danger { color: var(--sw-color-danger); }
|
|
134
|
+
|
|
135
|
+
.sw-list-row-detail,
|
|
136
|
+
.sw-list-row-value-detail {
|
|
137
|
+
color: var(--sw-color-muted);
|
|
138
|
+
font-size: ${caption.fontSize}px;
|
|
139
|
+
line-height: ${caption.lineHeight}px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* The label takes the wrap; the end keeps its words whole up to half the row. */
|
|
143
|
+
.sw-list-row-detail { overflow-wrap: anywhere; }
|
|
144
|
+
|
|
145
|
+
.sw-list-row-value,
|
|
146
|
+
.sw-list-row-value-detail { font-variant-numeric: tabular-nums; }
|
|
147
|
+
|
|
148
|
+
.sw-list-row-value { font-weight: ${label.fontWeight}; }
|
|
149
|
+
|
|
150
|
+
${tones}
|
|
151
|
+
${warningValueRule()}`;
|
|
152
|
+
}
|
|
153
|
+
/*
|
|
154
|
+
* The chevron is the stroke Accordion and the menus share, pointing to the
|
|
155
|
+
* inline end; the check is the same stroke in the accent, a short side and
|
|
156
|
+
* a long one. Both are borders, so forced colours keep them.
|
|
157
|
+
*/
|
|
158
|
+
function accessoryRules() {
|
|
159
|
+
return `.sw-list-row-chevron {
|
|
160
|
+
${chevronStrokeIn('var(--sw-color-muted)')}
|
|
161
|
+
flex: none;
|
|
162
|
+
margin-block-start: ${onTitleLine('var(--sw-space-2)')};
|
|
163
|
+
margin-inline-end: var(--sw-space-1);
|
|
164
|
+
transform: rotate(-45deg);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.sw-list-row-chevron:dir(rtl) { transform: rotate(135deg); }
|
|
168
|
+
|
|
169
|
+
.sw-list-row-check {
|
|
170
|
+
${checkStrokeIn('var(--sw-color-accent)')}
|
|
171
|
+
box-sizing: border-box;
|
|
172
|
+
flex: none;
|
|
173
|
+
height: var(--sw-space-3);
|
|
174
|
+
margin-block-start: ${onTitleLine('var(--sw-space-3)')};
|
|
175
|
+
margin-inline-end: var(--sw-space-1);
|
|
176
|
+
transform: rotate(45deg);
|
|
177
|
+
width: var(--sw-space-2);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@media (forced-colors: active) {
|
|
181
|
+
.sw-list-row-check { border-color: CanvasText; }
|
|
182
|
+
}`;
|
|
183
|
+
}
|
|
184
|
+
export function cssListRowClasses() {
|
|
185
|
+
return `${rowRules()}
|
|
186
|
+
|
|
187
|
+
${partRules()}
|
|
188
|
+
|
|
189
|
+
${accessoryRules()}`;
|
|
190
|
+
}
|
|
191
|
+
export function listRowClassCatalog() {
|
|
192
|
+
return [
|
|
193
|
+
'sw-list-row',
|
|
194
|
+
'sw-list-row-pressable',
|
|
195
|
+
'sw-list-row-disabled',
|
|
196
|
+
'sw-list-row-leading',
|
|
197
|
+
'sw-list-row-label',
|
|
198
|
+
'sw-list-row-title',
|
|
199
|
+
'sw-list-row-title-plain',
|
|
200
|
+
'sw-list-row-title-danger',
|
|
201
|
+
'sw-list-row-detail',
|
|
202
|
+
'sw-list-row-end',
|
|
203
|
+
'sw-list-row-value',
|
|
204
|
+
...listRowValueTones.map((tone) => `sw-list-row-value-${tone}`),
|
|
205
|
+
'sw-list-row-value-detail',
|
|
206
|
+
'sw-list-row-chevron',
|
|
207
|
+
'sw-list-row-check',
|
|
208
|
+
];
|
|
209
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { cssListRowClasses, listRowClassCatalog } from './css-list-row.js';
|
|
3
|
+
import { blockEdgeShadeRules, scrollRegionRules } from './css-scroll-region.js';
|
|
4
|
+
const label = typographyVariants.label;
|
|
5
|
+
const caption = typographyVariants.caption;
|
|
6
|
+
/* A row's padding, shared by the row rules and the bounded list's height. */
|
|
7
|
+
export const listRowPadBlock = 'var(--sw-space-3)';
|
|
8
|
+
const scroll = '.sw-list-group-scroll';
|
|
9
|
+
/*
|
|
10
|
+
* A ListGroup is one list (`sw-list`) with a hairline between its rows:
|
|
11
|
+
* a bordered panel on the surface, or plain rows inside a surface that
|
|
12
|
+
* already has one, with a hairline above the first row too. A footer sits
|
|
13
|
+
* under the rows, outside any scroll, under a hairline.
|
|
14
|
+
*/
|
|
15
|
+
function groupRules() {
|
|
16
|
+
return `.sw-list {
|
|
17
|
+
list-style: none;
|
|
18
|
+
margin: 0;
|
|
19
|
+
padding: 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.sw-list > .sw-list-item + .sw-list-item,
|
|
23
|
+
.sw-list-group-plain .sw-list > .sw-list-item:first-child,
|
|
24
|
+
.sw-list-group-footer {
|
|
25
|
+
border-top: 1px solid var(--sw-color-border);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.sw-list-group-panel {
|
|
29
|
+
background: var(--sw-color-surface);
|
|
30
|
+
border: 1px solid var(--sw-color-border);
|
|
31
|
+
border-radius: var(--sw-radius-md);
|
|
32
|
+
overflow: clip;
|
|
33
|
+
}`;
|
|
34
|
+
}
|
|
35
|
+
/*
|
|
36
|
+
* A bounded list (\`maxHeight\`) is as tall as its row count
|
|
37
|
+
* (\`--sw-list-max-rows\`) of rows with a title and one detail line: the
|
|
38
|
+
* padding twice, the title's line, the detail's line and the hairline.
|
|
39
|
+
* Taller rows show fewer at a time. Its region is the shared scroll
|
|
40
|
+
* region (a named keyboard stop); while rows are past its top or bottom,
|
|
41
|
+
* that edge draws the scroll shade a spacing step 5 deep, a background
|
|
42
|
+
* layer under the rows. Forced colours draw no shade; printed, every row
|
|
43
|
+
* shows.
|
|
44
|
+
*/
|
|
45
|
+
function boundedRules() {
|
|
46
|
+
const top = `${scroll}.sw-scroll-more-top`;
|
|
47
|
+
const bottom = `${scroll}.sw-scroll-more-bottom`;
|
|
48
|
+
return `${scrollRegionRules(scroll)}
|
|
49
|
+
|
|
50
|
+
${scroll} {
|
|
51
|
+
max-height: calc(var(--sw-list-max-rows) * (2 * ${listRowPadBlock} + ${label.lineHeight}px + ${caption.lineHeight}px + 1px));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
${blockEdgeShadeRules({ top, bottom, both: `${top}.sw-scroll-more-bottom` })}
|
|
55
|
+
|
|
56
|
+
@media (forced-colors: active) {
|
|
57
|
+
.sw-list > .sw-list-item + .sw-list-item,
|
|
58
|
+
.sw-list-group-plain .sw-list > .sw-list-item:first-child,
|
|
59
|
+
.sw-list-group-footer,
|
|
60
|
+
.sw-list-group-panel { border-color: CanvasText; }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@media print {
|
|
64
|
+
${scroll} { max-height: none; }
|
|
65
|
+
}`;
|
|
66
|
+
}
|
|
67
|
+
export function cssListClasses() {
|
|
68
|
+
return `${groupRules()}
|
|
69
|
+
|
|
70
|
+
${boundedRules()}
|
|
71
|
+
|
|
72
|
+
${cssListRowClasses()}`;
|
|
73
|
+
}
|
|
74
|
+
export function listClassCatalog() {
|
|
75
|
+
return [
|
|
76
|
+
'sw-list',
|
|
77
|
+
'sw-list-item',
|
|
78
|
+
'sw-list-group',
|
|
79
|
+
'sw-list-group-panel',
|
|
80
|
+
'sw-list-group-plain',
|
|
81
|
+
'sw-list-group-scroll',
|
|
82
|
+
'sw-list-group-footer',
|
|
83
|
+
...listRowClassCatalog(),
|
|
84
|
+
];
|
|
85
|
+
}
|
|
@@ -23,6 +23,24 @@ export declare function scrollShadeRules(selector: string): string;
|
|
|
23
23
|
* and the DenominationGrid strip share it.
|
|
24
24
|
*/
|
|
25
25
|
export declare function scrollRegionRules(selector: string): string;
|
|
26
|
+
/** The scroll shade fading away from an edge, a gradient toward `direction`. */
|
|
27
|
+
export declare function blockShade(direction: 'bottom' | 'top'): string;
|
|
28
|
+
/** The selectors of a region scrolled past its top, its bottom, or both. */
|
|
29
|
+
export type BlockEdgeSelectors = {
|
|
30
|
+
top: string;
|
|
31
|
+
bottom: string;
|
|
32
|
+
both: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The shade a region of bounded height draws on its own top or bottom
|
|
36
|
+
* edge while `ScrollRegion` marks rows past it (`sw-scroll-more-top`,
|
|
37
|
+
* `sw-scroll-more-bottom`): a background layer a spacing step 5 deep,
|
|
38
|
+
* fixed to the box and under the rows. A caller narrows the selectors to
|
|
39
|
+
* the edges nothing pinned covers. Forced colours draw no shade; the
|
|
40
|
+
* system's scrollbar is the cue. A bounded Table and a bounded ListGroup
|
|
41
|
+
* share it.
|
|
42
|
+
*/
|
|
43
|
+
export declare function blockEdgeShadeRules({ top, bottom, both, }: BlockEdgeSelectors): string;
|
|
26
44
|
export declare function scrollRegionClassCatalog(): string[];
|
|
27
45
|
/**
|
|
28
46
|
* A region whose start column is pinned (sticky, on an opaque fill) hides
|
|
@@ -60,6 +60,47 @@ ${selector}:focus-visible {
|
|
|
60
60
|
|
|
61
61
|
${scrollShadeRules(selector)}`;
|
|
62
62
|
}
|
|
63
|
+
/** The scroll shade fading away from an edge, a gradient toward `direction`. */
|
|
64
|
+
export function blockShade(direction) {
|
|
65
|
+
return `linear-gradient(to ${direction}, ${scrollShadeColor}, transparent)`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The shade a region of bounded height draws on its own top or bottom
|
|
69
|
+
* edge while `ScrollRegion` marks rows past it (`sw-scroll-more-top`,
|
|
70
|
+
* `sw-scroll-more-bottom`): a background layer a spacing step 5 deep,
|
|
71
|
+
* fixed to the box and under the rows. A caller narrows the selectors to
|
|
72
|
+
* the edges nothing pinned covers. Forced colours draw no shade; the
|
|
73
|
+
* system's scrollbar is the cue. A bounded Table and a bounded ListGroup
|
|
74
|
+
* share it.
|
|
75
|
+
*/
|
|
76
|
+
export function blockEdgeShadeRules({ top, bottom, both, }) {
|
|
77
|
+
return `${top},
|
|
78
|
+
${bottom} {
|
|
79
|
+
background-repeat: no-repeat;
|
|
80
|
+
background-size: 100% var(--sw-space-5);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
${top} {
|
|
84
|
+
background-image: ${blockShade('bottom')};
|
|
85
|
+
background-position: top;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
${bottom} {
|
|
89
|
+
background-image: ${blockShade('top')};
|
|
90
|
+
background-position: bottom;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
${both} {
|
|
94
|
+
background-image: ${blockShade('bottom')}, ${blockShade('top')};
|
|
95
|
+
background-position: top, bottom;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@media (forced-colors: active) {
|
|
99
|
+
${top},
|
|
100
|
+
${bottom},
|
|
101
|
+
${both} { background-image: none; }
|
|
102
|
+
}`;
|
|
103
|
+
}
|
|
63
104
|
export function scrollRegionClassCatalog() {
|
|
64
105
|
return [
|
|
65
106
|
'sw-scroll-more-start',
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
2
|
import { coarsePointerQuery, touchTarget } from './touch-target.js';
|
|
3
|
-
const caption = typographyVariants.caption;
|
|
4
3
|
const label = typographyVariants.label;
|
|
5
4
|
/** How a section navigation marks its current item. */
|
|
6
5
|
export const sectionNavAppearances = ['underline', 'filled'];
|
|
@@ -18,10 +17,7 @@ export function assertSectionNavAppearance(appearance) {
|
|
|
18
17
|
* hovered link. A 2 px transparent border keeps room for forced colours,
|
|
19
18
|
* where the current link's border turns Highlight.
|
|
20
19
|
*
|
|
21
|
-
* A count after a label
|
|
22
|
-
* danger colour with its on-colour figures (4.5:1 in every palette, as a
|
|
23
|
-
* danger Button's label), caption size at weight 700, a space-5 less
|
|
24
|
-
* space-1 (20) high and at least as wide. Forced colours draw its edge.
|
|
20
|
+
* A count after a label is the shared count pill (`css-count-pill.ts`).
|
|
25
21
|
*/
|
|
26
22
|
export function cssSectionNavFilledClasses() {
|
|
27
23
|
// Two classes, so every filled rule outranks the side list's (one class
|
|
@@ -48,33 +44,14 @@ export function cssSectionNavFilledClasses() {
|
|
|
48
44
|
font-weight: ${label.fontWeight};
|
|
49
45
|
}
|
|
50
46
|
|
|
51
|
-
[data-theme] .sw-section-nav-count {
|
|
52
|
-
align-items: center;
|
|
53
|
-
background: var(--sw-color-danger);
|
|
54
|
-
border-radius: var(--sw-radius-pill);
|
|
55
|
-
box-sizing: border-box;
|
|
56
|
-
color: var(--sw-color-onDanger);
|
|
57
|
-
display: inline-flex;
|
|
58
|
-
font-size: ${caption.fontSize}px;
|
|
59
|
-
font-variant-numeric: tabular-nums;
|
|
60
|
-
font-weight: 700;
|
|
61
|
-
justify-content: center;
|
|
62
|
-
letter-spacing: ${caption.letterSpacing}px;
|
|
63
|
-
line-height: 1;
|
|
64
|
-
min-height: calc(var(--sw-space-5) - var(--sw-space-1));
|
|
65
|
-
min-width: calc(var(--sw-space-5) - var(--sw-space-1));
|
|
66
|
-
padding-inline: var(--sw-space-1);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
47
|
@media ${coarsePointerQuery} {
|
|
70
48
|
[data-theme] ${filled} .sw-section-nav-link { min-height: ${touchTarget}; }
|
|
71
49
|
}
|
|
72
50
|
|
|
73
51
|
@media (forced-colors: active) {
|
|
74
52
|
[data-theme] ${filled} .sw-section-nav-link[aria-current] { border-color: Highlight; }
|
|
75
|
-
[data-theme] .sw-section-nav-count { border: 1px solid CanvasText; }
|
|
76
53
|
}`;
|
|
77
54
|
}
|
|
78
55
|
export function sectionNavFilledClassCatalog() {
|
|
79
|
-
return ['sw-section-nav-filled'
|
|
56
|
+
return ['sw-section-nav-filled'];
|
|
80
57
|
}
|
|
@@ -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,5 +1,12 @@
|
|
|
1
1
|
export declare const statTileTones: readonly ["default", "accent", "success", "danger", "warning"];
|
|
2
2
|
export type StatTileTone = (typeof statTileTones)[number];
|
|
3
|
+
/**
|
|
4
|
+
* `card` (the default) is a tile on the surface with its own hairline and
|
|
5
|
+
* radius; `plain` has no surface, edge or padding, for figures inside a
|
|
6
|
+
* card that already has them, such as a row of answers divided by hairlines.
|
|
7
|
+
*/
|
|
8
|
+
export declare const statTileAppearances: readonly ["card", "plain"];
|
|
9
|
+
export type StatTileAppearance = (typeof statTileAppearances)[number];
|
|
3
10
|
/** The figure tile: a glyph circle before a label, a tabular value and a caption. Text colours come from `Text color`. */
|
|
4
11
|
export declare function cssStatTileClasses(): string;
|
|
5
12
|
export declare function statTileClassCatalog(): string[];
|
|
@@ -5,6 +5,12 @@ export const statTileTones = [
|
|
|
5
5
|
'danger',
|
|
6
6
|
'warning',
|
|
7
7
|
];
|
|
8
|
+
/**
|
|
9
|
+
* `card` (the default) is a tile on the surface with its own hairline and
|
|
10
|
+
* radius; `plain` has no surface, edge or padding, for figures inside a
|
|
11
|
+
* card that already has them, such as a row of answers divided by hairlines.
|
|
12
|
+
*/
|
|
13
|
+
export const statTileAppearances = ['card', 'plain'];
|
|
8
14
|
/** The figure tile: a glyph circle before a label, a tabular value and a caption. Text colours come from `Text color`. */
|
|
9
15
|
export function cssStatTileClasses() {
|
|
10
16
|
return `.sw-stat-tile {
|
|
@@ -44,6 +50,15 @@ export function cssStatTileClasses() {
|
|
|
44
50
|
overflow-wrap: anywhere;
|
|
45
51
|
}
|
|
46
52
|
|
|
53
|
+
/* A plain tile is its figure alone, top-aligned, inside the card around it. */
|
|
54
|
+
.sw-stat-tile-plain {
|
|
55
|
+
align-items: flex-start;
|
|
56
|
+
background: transparent;
|
|
57
|
+
border: 0;
|
|
58
|
+
border-radius: 0;
|
|
59
|
+
padding: 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
47
62
|
.sw-stat-tile-primary {
|
|
48
63
|
background: var(--sw-color-accent);
|
|
49
64
|
border-color: transparent;
|
|
@@ -63,6 +78,7 @@ export function cssStatTileClasses() {
|
|
|
63
78
|
export function statTileClassCatalog() {
|
|
64
79
|
return [
|
|
65
80
|
'sw-stat-tile',
|
|
81
|
+
'sw-stat-tile-plain',
|
|
66
82
|
'sw-stat-tile-primary',
|
|
67
83
|
'sw-stat-tile-glyph',
|
|
68
84
|
'sw-stat-tile-body',
|
package/dist/css/css-steps.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
|
+
import { checkStrokeIn } from './chevron.js';
|
|
2
3
|
const body = typographyVariants.body;
|
|
3
4
|
const caption = typographyVariants.caption;
|
|
4
5
|
const label = typographyVariants.label;
|
|
@@ -29,8 +30,7 @@ function markerRules() {
|
|
|
29
30
|
|
|
30
31
|
/* Private chrome: a check drawn with two borders, as Checkbox's. */
|
|
31
32
|
.sw-steps-item-done .sw-steps-marker::after {
|
|
32
|
-
|
|
33
|
-
border-right: 2px solid var(--sw-color-surface);
|
|
33
|
+
${checkStrokeIn('var(--sw-color-surface)')}
|
|
34
34
|
content: '';
|
|
35
35
|
height: var(--sw-space-3);
|
|
36
36
|
margin-top: calc(-1 * var(--sw-space-1) / 2);
|
package/dist/css/css-switch.d.ts
CHANGED
|
@@ -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[];
|
package/dist/css/css-switch.js
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
import { typographyVariants } from '@scalewing/tokens';
|
|
2
2
|
const label = typographyVariants.label;
|
|
3
3
|
const caption = typographyVariants.caption;
|
|
4
|
+
/** Where the control sits: before its label, or at the row's end after it. */
|
|
5
|
+
export const switchLayouts = ['leading', 'trailing'];
|
|
6
|
+
/** The track's colour while on. */
|
|
7
|
+
export const switchCheckedTones = ['accent', 'success'];
|
|
8
|
+
/*
|
|
9
|
+
* A trailing switch is a row as wide as its column: the label and its
|
|
10
|
+
* description take the room, the control sits at the end, a step apart,
|
|
11
|
+
* lined up with the label's first line. A success switch fills its track
|
|
12
|
+
* with the success colour while on (3:1 or more against the surface in
|
|
13
|
+
* every palette, as the accent is); forced colours keep Highlight.
|
|
14
|
+
*/
|
|
15
|
+
function optionRules() {
|
|
16
|
+
return `.sw-switch-trailing {
|
|
17
|
+
align-items: flex-start;
|
|
18
|
+
display: flex;
|
|
19
|
+
gap: var(--sw-space-3);
|
|
20
|
+
justify-content: space-between;
|
|
21
|
+
width: 100%;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.sw-switch-trailing .sw-switch-copy {
|
|
25
|
+
flex: 1 1 auto;
|
|
26
|
+
min-width: 0;
|
|
27
|
+
padding-block: calc((var(--sw-control-md-min-height) - ${label.lineHeight}px) / 2);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.sw-switch-success .sw-switch-input:checked + .sw-switch-track {
|
|
31
|
+
background: var(--sw-color-success);
|
|
32
|
+
border-color: var(--sw-color-success);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@media (forced-colors: active) {
|
|
36
|
+
.sw-switch-success .sw-switch-input:checked + .sw-switch-track { background: Highlight; border-color: Highlight; }
|
|
37
|
+
}`;
|
|
38
|
+
}
|
|
4
39
|
export function cssSwitchClasses() {
|
|
5
40
|
return `.sw-switch {
|
|
6
41
|
align-items: center;
|
|
@@ -90,6 +125,8 @@ export function cssSwitchClasses() {
|
|
|
90
125
|
line-height: ${caption.lineHeight}px;
|
|
91
126
|
}
|
|
92
127
|
|
|
128
|
+
${optionRules()}
|
|
129
|
+
|
|
93
130
|
@media (prefers-reduced-motion: reduce) {
|
|
94
131
|
.sw-switch-thumb { transition: none; }
|
|
95
132
|
}
|
|
@@ -111,5 +148,7 @@ export function switchClassCatalog() {
|
|
|
111
148
|
'sw-switch-copy',
|
|
112
149
|
'sw-switch-label',
|
|
113
150
|
'sw-switch-description',
|
|
151
|
+
'sw-switch-trailing',
|
|
152
|
+
'sw-switch-success',
|
|
114
153
|
];
|
|
115
154
|
}
|