@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.
Files changed (181) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +255 -5
  3. package/dist/calendar-labels.d.ts +2 -0
  4. package/dist/calendar-labels.js +7 -0
  5. package/dist/calendar-month.d.ts +6 -0
  6. package/dist/calendar-month.js +15 -0
  7. package/dist/components/BarChart.d.ts +20 -4
  8. package/dist/components/BarChart.js +13 -6
  9. package/dist/components/ButtonGroup.d.ts +8 -1
  10. package/dist/components/ButtonGroup.js +11 -2
  11. package/dist/components/DateField.d.ts +14 -2
  12. package/dist/components/DateField.js +14 -11
  13. package/dist/components/DateRangeButton.d.ts +65 -0
  14. package/dist/components/DateRangeButton.js +54 -0
  15. package/dist/components/DenominationGrid.d.ts +3 -2
  16. package/dist/components/DenominationGrid.js +21 -3
  17. package/dist/components/Dialog.d.ts +29 -13
  18. package/dist/components/Dialog.js +22 -20
  19. package/dist/components/Field.d.ts +13 -2
  20. package/dist/components/Field.js +14 -38
  21. package/dist/components/FilterChips.d.ts +7 -37
  22. package/dist/components/FilterChips.js +32 -24
  23. package/dist/components/ListGroup.d.ts +33 -0
  24. package/dist/components/ListGroup.js +19 -0
  25. package/dist/components/ListRow.d.ts +60 -0
  26. package/dist/components/ListRow.js +60 -0
  27. package/dist/components/NavCount.d.ts +21 -0
  28. package/dist/components/NavCount.js +23 -0
  29. package/dist/components/SectionNav.js +1 -8
  30. package/dist/components/SegmentedControl.d.ts +17 -1
  31. package/dist/components/SegmentedControl.js +11 -3
  32. package/dist/components/StatTile.d.ts +11 -4
  33. package/dist/components/StatTile.js +11 -4
  34. package/dist/components/Switch.d.ts +16 -1
  35. package/dist/components/Switch.js +17 -6
  36. package/dist/components/action-bar/ActionBarSummary.d.ts +10 -2
  37. package/dist/components/action-bar/ActionBarSummary.js +11 -2
  38. package/dist/components/{date-field → calendar}/CalendarGrid.d.ts +17 -2
  39. package/dist/components/{date-field → calendar}/CalendarGrid.js +11 -3
  40. package/dist/components/calendar/CalendarPopover.d.ts +25 -0
  41. package/dist/components/calendar/CalendarPopover.js +22 -0
  42. package/dist/components/calendar/MonthStep.d.ts +16 -0
  43. package/dist/components/calendar/MonthStep.js +17 -0
  44. package/dist/components/calendar/use-grid-focus.d.ts +18 -0
  45. package/dist/components/calendar/use-grid-focus.js +35 -0
  46. package/dist/components/calendar/wrap-tab.d.ts +7 -0
  47. package/dist/components/calendar/wrap-tab.js +29 -0
  48. package/dist/components/date-field/CalendarDialog.js +9 -67
  49. package/dist/components/date-field/CalendarEntryButton.d.ts +24 -0
  50. package/dist/components/date-field/CalendarEntryButton.js +16 -0
  51. package/dist/components/date-field/CalendarHeader.js +2 -11
  52. package/dist/components/date-field/TypedEntry.d.ts +26 -0
  53. package/dist/components/date-field/TypedEntry.js +13 -0
  54. package/dist/components/date-range/DateRangePopover.d.ts +7 -0
  55. package/dist/components/date-range/DateRangePopover.js +17 -0
  56. package/dist/components/date-range/DateRangeSheet.d.ts +7 -0
  57. package/dist/components/date-range/DateRangeSheet.js +15 -0
  58. package/dist/components/date-range/RangeMonths.d.ts +28 -0
  59. package/dist/components/date-range/RangeMonths.js +50 -0
  60. package/dist/components/date-range/RangePresets.d.ts +16 -0
  61. package/dist/components/date-range/RangePresets.js +10 -0
  62. package/dist/components/date-range/RangeSummary.d.ts +15 -0
  63. package/dist/components/date-range/RangeSummary.js +11 -0
  64. package/dist/components/date-range/range-panel-props.d.ts +31 -0
  65. package/dist/components/date-range/range-panel-props.js +1 -0
  66. package/dist/components/date-range/use-range-popup.d.ts +21 -0
  67. package/dist/components/date-range/use-range-popup.js +53 -0
  68. package/dist/components/denomination-grid/CountCell.d.ts +16 -0
  69. package/dist/components/denomination-grid/CountCell.js +14 -0
  70. package/dist/components/denomination-grid/DenominationStrip.d.ts +4 -1
  71. package/dist/components/denomination-grid/DenominationStrip.js +2 -2
  72. package/dist/components/denomination-grid/EntryCell.d.ts +3 -1
  73. package/dist/components/denomination-grid/EntryCell.js +2 -2
  74. package/dist/components/denomination-grid/StripRow.js +1 -10
  75. package/dist/components/denomination-grid/TransposedStrip.d.ts +17 -0
  76. package/dist/components/denomination-grid/TransposedStrip.js +43 -0
  77. package/dist/components/denomination-grid/types.d.ts +31 -0
  78. package/dist/components/denomination-grid/types.js +7 -1
  79. package/dist/components/denomination-grid/validate-options.d.ts +7 -0
  80. package/dist/components/denomination-grid/validate-options.js +27 -0
  81. package/dist/components/dialog/DialogFooter.d.ts +6 -5
  82. package/dist/components/dialog/DialogFooter.js +6 -6
  83. package/dist/components/dialog/validate.d.ts +24 -0
  84. package/dist/components/dialog/validate.js +23 -0
  85. package/dist/components/field/field-checks.d.ts +34 -0
  86. package/dist/components/field/field-checks.js +42 -0
  87. package/dist/components/filter-chips/FilterChip.d.ts +16 -0
  88. package/dist/components/filter-chips/FilterChip.js +20 -0
  89. package/dist/components/filter-chips/options.d.ts +75 -0
  90. package/dist/components/filter-chips/options.js +11 -0
  91. package/dist/components/filter-chips/validate.d.ts +9 -0
  92. package/dist/components/filter-chips/validate.js +48 -0
  93. package/dist/components/link-press.d.ts +7 -0
  94. package/dist/components/link-press.js +13 -0
  95. package/dist/components/list/ListRowAccessoryMark.d.ts +5 -0
  96. package/dist/components/list/ListRowAccessoryMark.js +7 -0
  97. package/dist/components/list/ListRowContent.d.ts +22 -0
  98. package/dist/components/list/ListRowContent.js +11 -0
  99. package/dist/components/list/list-row-container.d.ts +5 -0
  100. package/dist/components/list/list-row-container.js +6 -0
  101. package/dist/components/use-media-query.d.ts +5 -0
  102. package/dist/components/use-media-query.js +18 -0
  103. package/dist/css/chart-tones.d.ts +2 -0
  104. package/dist/css/chart-tones.js +5 -1
  105. package/dist/css/chevron.d.ts +6 -0
  106. package/dist/css/chevron.js +14 -0
  107. package/dist/css/css-bar-chart.d.ts +17 -2
  108. package/dist/css/css-bar-chart.js +38 -7
  109. package/dist/css/css-button-group-attached.d.ts +3 -0
  110. package/dist/css/css-button-group-attached.js +26 -5
  111. package/dist/css/css-button-group-track.js +1 -1
  112. package/dist/css/css-canvas-grouped.d.ts +17 -0
  113. package/dist/css/css-canvas-grouped.js +40 -0
  114. package/dist/css/css-checkbox.js +2 -2
  115. package/dist/css/css-components.js +15 -0
  116. package/dist/css/css-count-pill.d.ts +2 -0
  117. package/dist/css/css-count-pill.js +54 -0
  118. package/dist/css/css-date-field-calendar-entry.d.ts +11 -0
  119. package/dist/css/css-date-field-calendar-entry.js +50 -0
  120. package/dist/css/css-date-field.js +7 -2
  121. package/dist/css/css-date-range-presets.d.ts +2 -0
  122. package/dist/css/css-date-range-presets.js +109 -0
  123. package/dist/css/css-date-range.d.ts +2 -0
  124. package/dist/css/css-date-range.js +197 -0
  125. package/dist/css/css-denomination-grid.js +4 -0
  126. package/dist/css/css-denomination-transposed.d.ts +4 -0
  127. package/dist/css/css-denomination-transposed.js +178 -0
  128. package/dist/css/css-dialog-canvas.d.ts +3 -0
  129. package/dist/css/css-dialog-canvas.js +20 -0
  130. package/dist/css/css-dialog-frame.js +19 -2
  131. package/dist/css/css-dialog-grabber.d.ts +4 -0
  132. package/dist/css/css-dialog-grabber.js +56 -0
  133. package/dist/css/css-dialog.js +3 -2
  134. package/dist/css/css-document.js +3 -0
  135. package/dist/css/css-field-width.d.ts +12 -0
  136. package/dist/css/css-field-width.js +49 -0
  137. package/dist/css/css-field.js +4 -0
  138. package/dist/css/css-filter-chips-layout.d.ts +2 -0
  139. package/dist/css/css-filter-chips-layout.js +42 -0
  140. package/dist/css/css-filter-chips.js +4 -0
  141. package/dist/css/css-list-row.d.ts +8 -0
  142. package/dist/css/css-list-row.js +209 -0
  143. package/dist/css/css-list.d.ts +3 -0
  144. package/dist/css/css-list.js +85 -0
  145. package/dist/css/css-scroll-region.d.ts +18 -0
  146. package/dist/css/css-scroll-region.js +41 -0
  147. package/dist/css/css-section-nav-filled.js +2 -25
  148. package/dist/css/css-segmented-sizing.d.ts +13 -0
  149. package/dist/css/css-segmented-sizing.js +66 -0
  150. package/dist/css/css-segmented.js +4 -0
  151. package/dist/css/css-stat-tile.d.ts +7 -0
  152. package/dist/css/css-stat-tile.js +16 -0
  153. package/dist/css/css-steps.js +2 -2
  154. package/dist/css/css-switch.d.ts +6 -0
  155. package/dist/css/css-switch.js +39 -0
  156. package/dist/css/css-table-bounded-edges.js +4 -27
  157. package/dist/css/range-band.d.ts +2 -0
  158. package/dist/css/range-band.js +7 -0
  159. package/dist/css/stacking.d.ts +1 -0
  160. package/dist/css/stacking.js +6 -3
  161. package/dist/css/stylesheet.js +10 -0
  162. package/dist/date-field-labels.d.ts +5 -0
  163. package/dist/date-field-labels.js +1 -0
  164. package/dist/date-range-draft.d.ts +26 -0
  165. package/dist/date-range-draft.js +36 -0
  166. package/dist/date-range-input.d.ts +26 -0
  167. package/dist/date-range-input.js +58 -0
  168. package/dist/date-range-labels.d.ts +22 -0
  169. package/dist/date-range-labels.js +26 -0
  170. package/dist/date-range-view.d.ts +12 -0
  171. package/dist/date-range-view.js +29 -0
  172. package/dist/date-range-words.d.ts +11 -0
  173. package/dist/date-range-words.js +40 -0
  174. package/dist/index.d.ts +16 -9
  175. package/dist/index.js +14 -7
  176. package/dist/list-options.d.ts +71 -0
  177. package/dist/list-options.js +84 -0
  178. package/dist/styles.css +863 -41
  179. package/dist/theme/ThemeProvider.d.ts +11 -1
  180. package/dist/theme/ThemeProvider.js +4 -2
  181. package/package.json +1 -1
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The page tones a canvas can take: `default`, the theme's background, and
3
+ * `grouped`, a quieter grey so white cards stand apart from the page, as a
4
+ * settings or report page groups its content in cards.
5
+ */
6
+ export declare const themeCanvases: readonly ["default", "grouped"];
7
+ export type ThemeCanvas = (typeof themeCanvases)[number];
8
+ /**
9
+ * How much of the muted colour the light grouped canvas mixes into the
10
+ * background: a grey a step off white that keeps the text and muted
11
+ * colours at 4.5:1 or more in every palette (`canvas-grouped.test.tsx`).
12
+ */
13
+ export declare const groupedCanvasMutedShare = 0.07;
14
+ /** The grouped canvas's colour, for a surface that sits on it, such as a dialog's body. */
15
+ export declare const groupedCanvasFill = "var(--sw-canvas-grouped)";
16
+ export declare function cssCanvasGroupedRules(): string;
17
+ export declare function assertThemeCanvas(canvas: unknown): void;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The page tones a canvas can take: `default`, the theme's background, and
3
+ * `grouped`, a quieter grey so white cards stand apart from the page, as a
4
+ * settings or report page groups its content in cards.
5
+ */
6
+ export const themeCanvases = ['default', 'grouped'];
7
+ /**
8
+ * How much of the muted colour the light grouped canvas mixes into the
9
+ * background: a grey a step off white that keeps the text and muted
10
+ * colours at 4.5:1 or more in every palette (`canvas-grouped.test.tsx`).
11
+ */
12
+ export const groupedCanvasMutedShare = 0.07;
13
+ /** The grouped canvas's colour, for a surface that sits on it, such as a dialog's body. */
14
+ export const groupedCanvasFill = 'var(--sw-canvas-grouped)';
15
+ /*
16
+ * The grouped canvas: in the light scheme the background with a little of
17
+ * the muted colour, in the dark scheme the background itself, which is
18
+ * already darker than its surface. The colour is declared on every themed
19
+ * node (a nested one recomputes it from its own colours) and painted only
20
+ * where `data-canvas="grouped"` asks for it, so no other page changes.
21
+ * Forced colours paint the system canvas as they do the default page.
22
+ */
23
+ export function cssCanvasGroupedRules() {
24
+ const share = Math.round(groupedCanvasMutedShare * 100);
25
+ return `[data-theme] {
26
+ --sw-canvas-grouped: color-mix(in srgb, var(--sw-color-muted) ${share}%, var(--sw-color-background));
27
+ }
28
+
29
+ [data-theme='dark'] {
30
+ --sw-canvas-grouped: var(--sw-color-background);
31
+ }
32
+
33
+ [data-theme][data-canvas='grouped'] {
34
+ background-color: ${groupedCanvasFill};
35
+ }`;
36
+ }
37
+ export function assertThemeCanvas(canvas) {
38
+ if (!themeCanvases.includes(canvas))
39
+ throw new RangeError(`Unknown ThemeProvider canvas: ${String(canvas)}`);
40
+ }
@@ -1,4 +1,5 @@
1
1
  import { typographyVariants } from '@scalewing/tokens';
2
+ import { checkStrokeIn } from './chevron.js';
2
3
  const label = typographyVariants.label;
3
4
  const caption = typographyVariants.caption;
4
5
  export function cssCheckboxClasses() {
@@ -49,8 +50,7 @@ export function cssCheckboxClasses() {
49
50
  }
50
51
 
51
52
  .sw-checkbox-mark::after {
52
- border-bottom: 2px solid var(--sw-color-surface);
53
- border-right: 2px solid var(--sw-color-surface);
53
+ ${checkStrokeIn('var(--sw-color-surface)')}
54
54
  content: '';
55
55
  display: none;
56
56
  height: var(--sw-space-2);
@@ -4,6 +4,9 @@ import { cssActionMenuClasses } from './css-action-menu.js';
4
4
  import { cssAccordionClasses } from './css-accordion.js';
5
5
  import { cssButtonClasses } from './css-button.js';
6
6
  import { cssCalendarButtonClasses } from './css-calendar-button.js';
7
+ import { cssDateRangeClasses } from './css-date-range.js';
8
+ import { cssListClasses } from './css-list.js';
9
+ import { cssCountPillClasses } from './css-count-pill.js';
7
10
  import { cssBarChartClasses } from './css-bar-chart.js';
8
11
  import { cssChartLegendClasses } from './css-chart-legend.js';
9
12
  import { cssChartPlotClasses } from './css-chart-plot.js';
@@ -21,6 +24,8 @@ import { cssDateFieldClasses } from './css-date-field.js';
21
24
  import { cssDialogClasses } from './css-dialog.js';
22
25
  import { cssDialogBandedClasses } from './css-dialog-banded.js';
23
26
  import { cssDialogFrameClasses } from './css-dialog-frame.js';
27
+ import { cssDialogCanvasClasses } from './css-dialog-canvas.js';
28
+ import { cssDialogGrabberClasses } from './css-dialog-grabber.js';
24
29
  import { cssComboboxClasses } from './css-combobox.js';
25
30
  import { cssSelectClasses } from './css-select.js';
26
31
  import { cssMultiSelectClasses } from './css-multi-select.js';
@@ -141,6 +146,12 @@ ${cssDateFieldClasses()}
141
146
 
142
147
  ${cssCalendarButtonClasses()}
143
148
 
149
+ ${cssDateRangeClasses()}
150
+
151
+ ${cssListClasses()}
152
+
153
+ ${cssCountPillClasses()}
154
+
144
155
  ${cssBarChartClasses()}
145
156
 
146
157
  ${cssDataBarClasses()}
@@ -165,6 +176,10 @@ ${cssDialogFrameClasses()}
165
176
 
166
177
  ${cssDialogBandedClasses()}
167
178
 
179
+ ${cssDialogCanvasClasses()}
180
+
181
+ ${cssDialogGrabberClasses()}
182
+
168
183
  ${cssAccordionClasses()}
169
184
 
170
185
  ${cssSelectClasses()}
@@ -0,0 +1,2 @@
1
+ export declare function cssCountPillClasses(): string;
2
+ export declare function countPillClassCatalog(): string[];
@@ -0,0 +1,54 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ const caption = typographyVariants.caption;
3
+ /** The counts drawn as the pill: SectionNav's and a Nav word's. */
4
+ const pills = ['sw-section-nav-count', 'sw-nav-count'];
5
+ /*
6
+ * A count after a destination's words (a number waiting there, such as
7
+ * tasks to do) is a filled pill: the danger colour with its on-colour
8
+ * figures (4.5:1 in every palette, as a danger Button's label), caption
9
+ * size at weight 700, a space-5 less space-1 (20) high and at least as
10
+ * wide. Forced colours draw its edge. SectionNav's item count and Nav's
11
+ * NavCount share it, so an area's count reads the same in both.
12
+ */
13
+ export function cssCountPillClasses() {
14
+ const selector = pills.map((name) => `[data-theme] .${name}`).join(',\n');
15
+ return `${selector} {
16
+ align-items: center;
17
+ background: var(--sw-color-danger);
18
+ border-radius: var(--sw-radius-pill);
19
+ box-sizing: border-box;
20
+ color: var(--sw-color-onDanger);
21
+ display: inline-flex;
22
+ font-size: ${caption.fontSize}px;
23
+ font-variant-numeric: tabular-nums;
24
+ font-weight: 700;
25
+ justify-content: center;
26
+ letter-spacing: ${caption.letterSpacing}px;
27
+ line-height: 1;
28
+ min-height: calc(var(--sw-space-5) - var(--sw-space-1));
29
+ min-width: calc(var(--sw-space-5) - var(--sw-space-1));
30
+ padding-inline: var(--sw-space-1);
31
+ }
32
+
33
+ /*
34
+ * A Nav link holding a count lays out as SectionNav's link does: the words
35
+ * and the pill centred on one line a space-2 apart (the space text node
36
+ * that keeps the name collapses), so the link is as tall as its siblings
37
+ * and its words stay level with theirs. A Button already does this. At
38
+ * zero specificity, so a link's \`hideBelow\` or \`hideFrom\` still hides it.
39
+ * In forced colours a current link's underline runs under the pill's
40
+ * figure too, as the pill is a flex item of the link.
41
+ */
42
+ :where(.sw-nav a:has(> .sw-nav-count)) {
43
+ align-items: center;
44
+ display: inline-flex;
45
+ gap: var(--sw-space-2);
46
+ }
47
+
48
+ @media (forced-colors: active) {
49
+ ${selector.replaceAll('\n', '\n ')} { border: 1px solid CanvasText; }
50
+ }`;
51
+ }
52
+ export function countPillClassCatalog() {
53
+ return [...pills];
54
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * DateField's calendar entry: one neutral Button showing the chosen day (or
3
+ * the words that ask for one) after the calendar glyph, shaped as a field's
4
+ * control rather than a pill, sized to its words on one line at the
5
+ * column's start, the danger edge while the field is invalid.
6
+ */
7
+ export declare const dateFieldEntries: readonly ["typed", "calendar"];
8
+ export type DateFieldEntry = (typeof dateFieldEntries)[number];
9
+ export declare function assertDateFieldEntry(entry: unknown): void;
10
+ export declare function cssDateFieldCalendarEntryClasses(): string;
11
+ export declare function dateFieldCalendarEntryClassCatalog(): string[];
@@ -0,0 +1,50 @@
1
+ /**
2
+ * DateField's calendar entry: one neutral Button showing the chosen day (or
3
+ * the words that ask for one) after the calendar glyph, shaped as a field's
4
+ * control rather than a pill, sized to its words on one line at the
5
+ * column's start, the danger edge while the field is invalid.
6
+ */
7
+ export const dateFieldEntries = ['typed', 'calendar'];
8
+ export function assertDateFieldEntry(entry) {
9
+ if (!dateFieldEntries.includes(entry))
10
+ throw new RangeError(`Unknown DateField entry: ${String(entry)}`);
11
+ }
12
+ const entry = '.sw-button.sw-date-field-calendar-entry';
13
+ export function cssDateFieldCalendarEntryClasses() {
14
+ return `${entry} {
15
+ align-self: flex-start;
16
+ border-radius: var(--sw-radius-sm);
17
+ flex: none;
18
+ justify-content: flex-start;
19
+ max-width: 100%;
20
+ text-align: start;
21
+ white-space: nowrap;
22
+ }
23
+
24
+ /* A long day or word in a narrow column ends in an ellipsis; the name keeps it whole. */
25
+ .sw-date-field-calendar-entry-text {
26
+ min-width: 0;
27
+ overflow: hidden;
28
+ text-overflow: ellipsis;
29
+ }
30
+
31
+ ${entry} .sw-date-field-glyph {
32
+ height: var(--sw-space-4);
33
+ width: var(--sw-space-4);
34
+ }
35
+
36
+ ${entry}.sw-date-field-calendar-entry-invalid {
37
+ border-color: var(--sw-color-danger);
38
+ }
39
+
40
+ @media (forced-colors: active) {
41
+ ${entry}.sw-date-field-calendar-entry-invalid { border-color: Mark; }
42
+ }`;
43
+ }
44
+ export function dateFieldCalendarEntryClassCatalog() {
45
+ return [
46
+ 'sw-date-field-calendar-entry',
47
+ 'sw-date-field-calendar-entry-text',
48
+ 'sw-date-field-calendar-entry-invalid',
49
+ ];
50
+ }
@@ -1,7 +1,9 @@
1
1
  import { typographyVariants } from '@scalewing/tokens';
2
2
  import { disabledControlForcedColors, disabledControlSurface, } from './css-document.js';
3
+ import { cssDateFieldCalendarEntryClasses, dateFieldCalendarEntryClassCatalog, } from './css-date-field-calendar-entry.js';
3
4
  import { zIndex } from './stacking.js';
4
5
  import { quietFill } from './quiet-fill.js';
6
+ import { rangeBand, rangeBandHover } from './range-band.js';
5
7
  const body = typographyVariants.body;
6
8
  const label = typographyVariants.label;
7
9
  const caption = typographyVariants.caption;
@@ -241,7 +243,7 @@ function calendarRules() {
241
243
  * accent ring (3:1 or more on the band). The selected day sits on top.
242
244
  */
243
245
  .sw-date-field-day-in-range {
244
- background: color-mix(in srgb, var(--sw-color-accent) 16%, transparent);
246
+ background: ${rangeBand};
245
247
  border-radius: 0;
246
248
  color: var(--sw-color-text);
247
249
  }
@@ -267,7 +269,7 @@ function calendarRules() {
267
269
  }
268
270
 
269
271
  .sw-date-field-day-in-range:hover:not([aria-disabled='true']) {
270
- background: color-mix(in srgb, var(--sw-color-accent) 24%, transparent);
272
+ background: ${rangeBandHover};
271
273
  }
272
274
 
273
275
  .sw-date-field-day[aria-selected='true'],
@@ -333,12 +335,15 @@ function adaptiveRules() {
333
335
  export function cssDateFieldClasses() {
334
336
  return `${fieldRules()}
335
337
 
338
+ ${cssDateFieldCalendarEntryClasses()}
339
+
336
340
  ${calendarRules()}
337
341
 
338
342
  ${adaptiveRules()}`;
339
343
  }
340
344
  export function dateFieldClassCatalog() {
341
345
  return [
346
+ ...dateFieldCalendarEntryClassCatalog(),
342
347
  'sw-date-field',
343
348
  'sw-date-field-label',
344
349
  'sw-date-field-control',
@@ -0,0 +1,2 @@
1
+ export declare function cssDateRangePresetsClasses(): string;
2
+ export declare function dateRangePresetsClassCatalog(): string[];
@@ -0,0 +1,109 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ import { breakpointQuery } from './breakpoints.js';
3
+ import { quietFill } from './quiet-fill.js';
4
+ import { coarsePointerQuery, touchTarget } from './touch-target.js';
5
+ const label = typographyVariants.label;
6
+ const body = typographyVariants.body;
7
+ /*
8
+ * DateRangeButton's presets. In the popover they are a list beside the
9
+ * months from `lg` up, the pressed one on the quiet fill in the label
10
+ * weight; from `md` to `lg`, where two months and a list do not fit side
11
+ * by side, the same list wraps in a row above the months and takes no
12
+ * width of its own. In the sheet they are one row of pills that scrolls
13
+ * sideways, the pressed one in the text colour.
14
+ */
15
+ export function cssDateRangePresetsClasses() {
16
+ return `.sw-date-range-presets {
17
+ contain: inline-size;
18
+ display: flex;
19
+ flex-wrap: wrap;
20
+ gap: var(--sw-space-1);
21
+ padding: var(--sw-space-3) var(--sw-space-3) 0;
22
+ }
23
+
24
+ @media ${breakpointQuery('from', 'lg')} {
25
+ .sw-date-range-presets:not(.sw-date-range-presets-row) {
26
+ border-inline-end: 1px solid var(--sw-color-border);
27
+ contain: none;
28
+ flex-direction: column;
29
+ flex-wrap: nowrap;
30
+ padding: var(--sw-space-3) var(--sw-space-2);
31
+ }
32
+ }
33
+
34
+ .sw-date-range-preset {
35
+ appearance: none;
36
+ background: transparent;
37
+ border: 1px solid transparent;
38
+ border-radius: var(--sw-radius-sm);
39
+ box-sizing: border-box;
40
+ color: var(--sw-color-text);
41
+ cursor: pointer;
42
+ flex: none;
43
+ font-family: var(--sw-font-sans);
44
+ font-size: ${label.fontSize}px;
45
+ font-weight: ${body.fontWeight};
46
+ line-height: ${label.lineHeight}px;
47
+ margin: 0;
48
+ min-height: var(--sw-control-sm-min-height);
49
+ padding: 0 var(--sw-control-sm-padding-inline);
50
+ text-align: start;
51
+ white-space: nowrap;
52
+ }
53
+
54
+ .sw-date-range-preset:hover,
55
+ .sw-date-range-preset[aria-pressed='true'] {
56
+ background: ${quietFill};
57
+ }
58
+
59
+ .sw-date-range-preset[aria-pressed='true'] {
60
+ font-weight: ${label.fontWeight};
61
+ }
62
+
63
+ .sw-date-range-preset:focus { outline: none; }
64
+
65
+ .sw-date-range-preset:focus-visible {
66
+ outline: var(--sw-focus-ring-width) solid var(--sw-color-accent);
67
+ outline-offset: var(--sw-focus-ring-offset);
68
+ }
69
+
70
+ .sw-date-range-presets-row {
71
+ contain: none;
72
+ flex-wrap: nowrap;
73
+ gap: var(--sw-space-2);
74
+ overflow-x: auto;
75
+ padding: var(--sw-focus-ring-width) var(--sw-focus-ring-offset);
76
+ }
77
+
78
+ .sw-date-range-presets-row .sw-date-range-preset {
79
+ background: ${quietFill};
80
+ border-radius: var(--sw-radius-pill);
81
+ }
82
+
83
+ .sw-date-range-presets-row .sw-date-range-preset[aria-pressed='true'] {
84
+ background: var(--sw-color-text);
85
+ color: var(--sw-color-surface);
86
+ }
87
+
88
+ @media ${coarsePointerQuery} {
89
+ .sw-date-range-preset { min-height: ${touchTarget}; }
90
+ }
91
+
92
+ @media (forced-colors: active) {
93
+ .sw-date-range-presets { border-color: CanvasText; }
94
+ .sw-date-range-presets-row .sw-date-range-preset { border-color: ButtonText; }
95
+ .sw-date-range-preset[aria-pressed='true'],
96
+ .sw-date-range-presets-row .sw-date-range-preset[aria-pressed='true'] {
97
+ background: Highlight;
98
+ color: HighlightText;
99
+ forced-color-adjust: none;
100
+ }
101
+ }`;
102
+ }
103
+ export function dateRangePresetsClassCatalog() {
104
+ return [
105
+ 'sw-date-range-presets',
106
+ 'sw-date-range-presets-row',
107
+ 'sw-date-range-preset',
108
+ ];
109
+ }
@@ -0,0 +1,2 @@
1
+ export declare function cssDateRangeClasses(): string;
2
+ export declare function dateRangeClassCatalog(): string[];
@@ -0,0 +1,197 @@
1
+ import { typographyVariants } from '@scalewing/tokens';
2
+ import { breakpointQuery } from './breakpoints.js';
3
+ import { rangeBand, rangeBandHover } from './range-band.js';
4
+ import { cssDateRangePresetsClasses, dateRangePresetsClassCatalog, } from './css-date-range-presets.js';
5
+ import { coarsePointerQuery, touchTarget } from './touch-target.js';
6
+ const label = typographyVariants.label;
7
+ const caption = typographyVariants.caption;
8
+ /* The steps and days are one square control wide, as in DateField's calendar. */
9
+ const square = 'var(--sw-control-md-min-height)';
10
+ /* A day between a picked range's ends: selected, but drawn as the band. */
11
+ const between = ".sw-date-range-months .sw-date-field-day-in-range[aria-selected='true']:not(.sw-date-field-day-range-start, .sw-date-field-day-range-end)";
12
+ function buttonRules() {
13
+ return `.sw-date-range-button {
14
+ font-variant-numeric: tabular-nums;
15
+ white-space: nowrap;
16
+ }
17
+
18
+ .sw-date-range-button:not(.sw-button-md) .sw-date-field-glyph {
19
+ height: var(--sw-space-4);
20
+ width: var(--sw-space-4);
21
+ }
22
+
23
+ @media ${coarsePointerQuery} {
24
+ .sw-button.sw-date-range-button,
25
+ .sw-date-range-actions > .sw-button { min-height: ${touchTarget}; }
26
+ }`;
27
+ }
28
+ /*
29
+ * The popover is DateField's calendar surface with no padding of its own:
30
+ * the presets, then the months, then a footer under a hairline. Below
31
+ * `lg` the presets sit above the months; from `lg` beside them.
32
+ */
33
+ function popoverRules() {
34
+ return `.sw-date-field-calendar.sw-date-range-popover {
35
+ gap: 0;
36
+ padding: 0;
37
+ }
38
+
39
+ .sw-date-range-body {
40
+ display: flex;
41
+ flex-direction: column;
42
+ }
43
+
44
+ @media ${breakpointQuery('from', 'lg')} {
45
+ .sw-date-range-body { flex-direction: row; }
46
+ }
47
+
48
+ .sw-date-range-footer {
49
+ align-items: center;
50
+ border-top: 1px solid var(--sw-color-border);
51
+ contain: inline-size;
52
+ display: flex;
53
+ flex-wrap: wrap;
54
+ gap: var(--sw-space-2) var(--sw-space-4);
55
+ padding: var(--sw-space-3);
56
+ }
57
+
58
+ .sw-date-range-summary {
59
+ color: var(--sw-color-muted);
60
+ flex: 1 1 auto;
61
+ font-size: ${caption.fontSize}px;
62
+ line-height: ${caption.lineHeight}px;
63
+ min-width: 0;
64
+ }
65
+
66
+ .sw-date-range-status { display: inline; }
67
+
68
+ .sw-date-range-line {
69
+ color: var(--sw-color-text);
70
+ display: block;
71
+ font-size: ${label.fontSize}px;
72
+ font-weight: ${label.fontWeight};
73
+ line-height: ${label.lineHeight}px;
74
+ }
75
+
76
+ .sw-date-range-actions {
77
+ display: flex;
78
+ gap: var(--sw-space-2);
79
+ margin-inline-start: auto;
80
+ }`;
81
+ }
82
+ function monthRules() {
83
+ return `.sw-date-range-months {
84
+ display: flex;
85
+ gap: var(--sw-space-5);
86
+ justify-content: center;
87
+ padding: var(--sw-space-3);
88
+ }
89
+
90
+ .sw-date-range-month {
91
+ display: flex;
92
+ flex-direction: column;
93
+ gap: var(--sw-space-1);
94
+ }
95
+
96
+ .sw-date-range-month-header {
97
+ align-items: center;
98
+ display: grid;
99
+ grid-template-columns: ${square} 1fr ${square};
100
+ min-height: ${square};
101
+ }
102
+
103
+ .sw-date-range-month-title {
104
+ font-size: ${label.fontSize}px;
105
+ font-weight: ${label.fontWeight};
106
+ grid-column: 2;
107
+ line-height: ${label.lineHeight}px;
108
+ text-align: center;
109
+ }
110
+
111
+ ${between} {
112
+ background: ${rangeBand};
113
+ border-color: transparent;
114
+ border-radius: 0;
115
+ color: var(--sw-color-text);
116
+ font-weight: inherit;
117
+ }
118
+
119
+ ${between}:hover:not([aria-disabled='true']) { background: ${rangeBandHover}; }
120
+
121
+ ${between}[aria-current='date'] { border-color: var(--sw-color-accent); }`;
122
+ }
123
+ /*
124
+ * Below \`md\` the range is a Dialog bottom sheet: the presets in a
125
+ * scrolling row, one month, and a footer with the hint over Cancel and
126
+ * Apply, the primary twice as wide.
127
+ */
128
+ function sheetRules() {
129
+ return `.sw-date-range-sheet .sw-date-range-months { padding: 0; }
130
+
131
+ .sw-date-range-sheet .sw-dialog-footer-actions {
132
+ flex: 1 1 100%;
133
+ margin-inline-start: 0;
134
+ }
135
+
136
+ .sw-date-range-sheet-footer {
137
+ display: flex;
138
+ flex: 1 1 100%;
139
+ flex-direction: column;
140
+ gap: var(--sw-space-2);
141
+ }
142
+
143
+ .sw-date-range-sheet-footer .sw-date-range-hint {
144
+ color: var(--sw-color-muted);
145
+ font-size: ${caption.fontSize}px;
146
+ line-height: ${caption.lineHeight}px;
147
+ }
148
+
149
+ .sw-date-range-sheet-footer .sw-date-range-actions {
150
+ display: grid;
151
+ grid-template-columns: 1fr 2fr;
152
+ margin-inline-start: 0;
153
+ }`;
154
+ }
155
+ function forcedColorRules() {
156
+ return `@media (forced-colors: active) {
157
+ .sw-date-range-footer { border-top-color: CanvasText; }
158
+ ${between},
159
+ ${between}:hover:not([aria-disabled='true']) {
160
+ background: Mark;
161
+ color: MarkText;
162
+ forced-color-adjust: none;
163
+ }
164
+ }`;
165
+ }
166
+ export function cssDateRangeClasses() {
167
+ return [
168
+ buttonRules(),
169
+ popoverRules(),
170
+ monthRules(),
171
+ sheetRules(),
172
+ cssDateRangePresetsClasses(),
173
+ forcedColorRules(),
174
+ ].join('\n\n');
175
+ }
176
+ export function dateRangeClassCatalog() {
177
+ return [
178
+ 'sw-date-range-button',
179
+ 'sw-date-range-popover',
180
+ 'sw-date-range-body',
181
+ 'sw-date-range-months',
182
+ 'sw-date-range-month',
183
+ 'sw-date-range-month-header',
184
+ 'sw-date-range-month-title',
185
+ 'sw-date-range-footer',
186
+ 'sw-date-range-summary',
187
+ 'sw-date-range-status',
188
+ 'sw-date-range-line',
189
+ 'sw-date-range-count',
190
+ 'sw-date-range-separator',
191
+ 'sw-date-range-hint',
192
+ 'sw-date-range-actions',
193
+ 'sw-date-range-sheet',
194
+ 'sw-date-range-sheet-footer',
195
+ ...dateRangePresetsClassCatalog(),
196
+ ];
197
+ }
@@ -6,6 +6,7 @@ import { cssDenominationLabelClasses, denominationLabelClassCatalog, } from './c
6
6
  import { cssDenominationAlignedClasses, denominationAlignedClassCatalog, } from './css-denomination-aligned.js';
7
7
  import { cssDenominationEntryClasses, denominationEntryClassCatalog, } from './css-denomination-entry.js';
8
8
  import { cssDenominationValueRowClasses, denominationValueRowClassCatalog, } from './css-denomination-value-row.js';
9
+ import { cssDenominationTransposedClasses, denominationTransposedClassCatalog, } from './css-denomination-transposed.js';
9
10
  import { cssDenominationCellToneClasses, denominationCellToneClassCatalog, } from './css-denomination-cell-tones.js';
10
11
  import { pinnedStartShadeRules, scrollRegionRules, } from './css-scroll-region.js';
11
12
  import { visuallyHiddenDeclarations } from './css-utilities.js';
@@ -263,6 +264,8 @@ ${cssDenominationAppearanceClasses()}
263
264
 
264
265
  ${cssDenominationValueRowClasses()}
265
266
 
267
+ ${cssDenominationTransposedClasses()}
268
+
266
269
  @media (forced-colors: active) {
267
270
  .sw-denomination-label { border-inline-start-color: CanvasText; color: CanvasText; }
268
271
  .sw-denomination-strip .sw-denomination-label::before { background: CanvasText; forced-color-adjust: none; }
@@ -307,5 +310,6 @@ export function denominationGridClassCatalog() {
307
310
  ...denominationLabelClassCatalog(),
308
311
  ...denominationAppearanceClassCatalog(),
309
312
  ...denominationValueRowClassCatalog(),
313
+ ...denominationTransposedClassCatalog(),
310
314
  ];
311
315
  }
@@ -0,0 +1,4 @@
1
+ /** A grid whose entry counts keep room for `--sw-denomination-count-digits` digits. */
2
+ export declare const denominationCountDigitsClass = "sw-denomination-count-digits";
3
+ export declare function cssDenominationTransposedClasses(): string;
4
+ export declare function denominationTransposedClassCatalog(): string[];