@scalewing/react 1.39.0 → 1.40.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 (95) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +102 -0
  3. package/dist/calendar-month.d.ts +6 -0
  4. package/dist/calendar-month.js +15 -0
  5. package/dist/components/DateRangeButton.d.ts +65 -0
  6. package/dist/components/DateRangeButton.js +54 -0
  7. package/dist/components/ListGroup.d.ts +33 -0
  8. package/dist/components/ListGroup.js +19 -0
  9. package/dist/components/ListRow.d.ts +51 -0
  10. package/dist/components/ListRow.js +59 -0
  11. package/dist/components/NavCount.d.ts +21 -0
  12. package/dist/components/NavCount.js +23 -0
  13. package/dist/components/SectionNav.js +1 -8
  14. package/dist/components/StatTile.d.ts +11 -4
  15. package/dist/components/StatTile.js +11 -4
  16. package/dist/components/{date-field → calendar}/CalendarGrid.d.ts +17 -2
  17. package/dist/components/{date-field → calendar}/CalendarGrid.js +11 -3
  18. package/dist/components/calendar/CalendarPopover.d.ts +25 -0
  19. package/dist/components/calendar/CalendarPopover.js +22 -0
  20. package/dist/components/calendar/MonthStep.d.ts +16 -0
  21. package/dist/components/calendar/MonthStep.js +17 -0
  22. package/dist/components/calendar/use-grid-focus.d.ts +18 -0
  23. package/dist/components/calendar/use-grid-focus.js +35 -0
  24. package/dist/components/calendar/wrap-tab.d.ts +7 -0
  25. package/dist/components/calendar/wrap-tab.js +29 -0
  26. package/dist/components/date-field/CalendarDialog.js +9 -67
  27. package/dist/components/date-field/CalendarHeader.js +2 -11
  28. package/dist/components/date-range/DateRangePopover.d.ts +7 -0
  29. package/dist/components/date-range/DateRangePopover.js +17 -0
  30. package/dist/components/date-range/DateRangeSheet.d.ts +7 -0
  31. package/dist/components/date-range/DateRangeSheet.js +15 -0
  32. package/dist/components/date-range/RangeMonths.d.ts +28 -0
  33. package/dist/components/date-range/RangeMonths.js +50 -0
  34. package/dist/components/date-range/RangePresets.d.ts +16 -0
  35. package/dist/components/date-range/RangePresets.js +10 -0
  36. package/dist/components/date-range/RangeSummary.d.ts +15 -0
  37. package/dist/components/date-range/RangeSummary.js +11 -0
  38. package/dist/components/date-range/range-panel-props.d.ts +31 -0
  39. package/dist/components/date-range/range-panel-props.js +1 -0
  40. package/dist/components/date-range/use-range-popup.d.ts +21 -0
  41. package/dist/components/date-range/use-range-popup.js +53 -0
  42. package/dist/components/link-press.d.ts +7 -0
  43. package/dist/components/link-press.js +13 -0
  44. package/dist/components/list/ListRowAccessoryMark.d.ts +5 -0
  45. package/dist/components/list/ListRowAccessoryMark.js +7 -0
  46. package/dist/components/list/ListRowContent.d.ts +20 -0
  47. package/dist/components/list/ListRowContent.js +10 -0
  48. package/dist/components/list/list-row-container.d.ts +5 -0
  49. package/dist/components/list/list-row-container.js +6 -0
  50. package/dist/components/use-media-query.d.ts +5 -0
  51. package/dist/components/use-media-query.js +18 -0
  52. package/dist/css/chevron.d.ts +6 -0
  53. package/dist/css/chevron.js +14 -0
  54. package/dist/css/css-button-group-attached.js +8 -4
  55. package/dist/css/css-button-group-track.js +1 -1
  56. package/dist/css/css-checkbox.js +2 -2
  57. package/dist/css/css-components.js +9 -0
  58. package/dist/css/css-count-pill.d.ts +2 -0
  59. package/dist/css/css-count-pill.js +54 -0
  60. package/dist/css/css-date-field.js +3 -2
  61. package/dist/css/css-date-range-presets.d.ts +2 -0
  62. package/dist/css/css-date-range-presets.js +109 -0
  63. package/dist/css/css-date-range.d.ts +2 -0
  64. package/dist/css/css-date-range.js +197 -0
  65. package/dist/css/css-list-row.d.ts +2 -0
  66. package/dist/css/css-list-row.js +193 -0
  67. package/dist/css/css-list.d.ts +3 -0
  68. package/dist/css/css-list.js +85 -0
  69. package/dist/css/css-scroll-region.d.ts +18 -0
  70. package/dist/css/css-scroll-region.js +41 -0
  71. package/dist/css/css-section-nav-filled.js +2 -25
  72. package/dist/css/css-stat-tile.d.ts +7 -0
  73. package/dist/css/css-stat-tile.js +16 -0
  74. package/dist/css/css-steps.js +2 -2
  75. package/dist/css/css-table-bounded-edges.js +4 -27
  76. package/dist/css/range-band.d.ts +2 -0
  77. package/dist/css/range-band.js +7 -0
  78. package/dist/css/stacking.js +2 -2
  79. package/dist/css/stylesheet.js +6 -0
  80. package/dist/date-range-draft.d.ts +26 -0
  81. package/dist/date-range-draft.js +36 -0
  82. package/dist/date-range-input.d.ts +26 -0
  83. package/dist/date-range-input.js +58 -0
  84. package/dist/date-range-labels.d.ts +22 -0
  85. package/dist/date-range-labels.js +26 -0
  86. package/dist/date-range-view.d.ts +12 -0
  87. package/dist/date-range-view.js +29 -0
  88. package/dist/date-range-words.d.ts +11 -0
  89. package/dist/date-range-words.js +40 -0
  90. package/dist/index.d.ts +6 -1
  91. package/dist/index.js +6 -1
  92. package/dist/list-options.d.ts +70 -0
  93. package/dist/list-options.js +77 -0
  94. package/dist/styles.css +507 -26
  95. package/package.json +1 -1
@@ -0,0 +1,53 @@
1
+ import { useId, useLayoutEffect, useRef, useState, } from 'react';
2
+ import { pressDay, sameRange, settledDraft, } from '../../date-range-draft.js';
3
+ /**
4
+ * DateRangeButton's open state and the range being picked. Opening starts
5
+ * from the value; a new value while open starts over from it. Disabling
6
+ * closes it for good.
7
+ */
8
+ export function useRangePopup(value, disabled, onChange) {
9
+ const buttonRef = useRef(null);
10
+ const id = useId();
11
+ const [open, setOpen] = useState(false);
12
+ const [draft, setDraft] = useState(() => settledDraft(value));
13
+ const [openedWith, setOpenedWith] = useState(value);
14
+ if (!sameRange(openedWith, value)) {
15
+ setOpenedWith(value);
16
+ setDraft(settledDraft(value));
17
+ }
18
+ if (disabled && open)
19
+ setOpen(false);
20
+ const shown = open && !disabled;
21
+ // Focus returns once the calendar is gone: while the sheet is still a
22
+ // modal dialog, the page behind it, the button included, is inert.
23
+ const restoreFocus = useRef(false);
24
+ useLayoutEffect(() => {
25
+ if (shown || !restoreFocus.current)
26
+ return;
27
+ restoreFocus.current = false;
28
+ buttonRef.current?.focus();
29
+ }, [shown]);
30
+ function cancel(restore) {
31
+ restoreFocus.current = restore;
32
+ setOpen(false);
33
+ }
34
+ return {
35
+ buttonRef,
36
+ id,
37
+ shown,
38
+ toggle: () => {
39
+ if (shown)
40
+ return cancel(true);
41
+ setDraft(settledDraft(value));
42
+ setOpen(true);
43
+ },
44
+ draft,
45
+ press: (day) => setDraft((current) => pressDay(current, day)),
46
+ apply: (range) => {
47
+ cancel(true);
48
+ if (!sameRange(range, value))
49
+ onChange(range);
50
+ },
51
+ cancel,
52
+ };
53
+ }
@@ -0,0 +1,7 @@
1
+ import { type MouseEvent } from 'react';
2
+ /**
3
+ * Whether a press on a link is a plain one a client router may take: the
4
+ * primary button, no modifier key (which opens a tab or a window) and not
5
+ * already handled. Shared by SectionNav and ListRow.
6
+ */
7
+ export declare function plainPress(event: MouseEvent<HTMLAnchorElement>): boolean;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Whether a press on a link is a plain one a client router may take: the
3
+ * primary button, no modifier key (which opens a tab or a window) and not
4
+ * already handled. Shared by SectionNav and ListRow.
5
+ */
6
+ export function plainPress(event) {
7
+ return (event.button === 0 &&
8
+ !event.defaultPrevented &&
9
+ !event.metaKey &&
10
+ !event.ctrlKey &&
11
+ !event.shiftKey &&
12
+ !event.altKey);
13
+ }
@@ -0,0 +1,5 @@
1
+ import { type ListRowAccessory } from '../../list-options.js';
2
+ /** A row's chevron or check: control chrome drawn by the generated CSS. */
3
+ export declare function ListRowAccessoryMark({ kind }: {
4
+ kind: ListRowAccessory;
5
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /** A row's chevron or check: control chrome drawn by the generated CSS. */
3
+ export function ListRowAccessoryMark({ kind }) {
4
+ if (kind === 'none')
5
+ return null;
6
+ return (_jsx("span", { "aria-hidden": "true", className: kind === 'check' ? 'sw-list-row-check' : 'sw-list-row-chevron' }));
7
+ }
@@ -0,0 +1,20 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type ListRowAccessory, type ListRowTitleAppearance, type ListRowTone, type ListRowValueTone } from '../../list-options.js';
3
+ export type ListRowContentProps = {
4
+ /** Prefixes the ids that name and describe a pressable row. */
5
+ id: string;
6
+ title: string;
7
+ detail?: string;
8
+ value?: string;
9
+ valueDetail?: string;
10
+ valueTone?: ListRowValueTone;
11
+ leading?: ReactNode;
12
+ tone: ListRowTone;
13
+ titleAppearance: ListRowTitleAppearance;
14
+ accessory: ListRowAccessory;
15
+ };
16
+ /**
17
+ * A list row's parts in reading order: the hidden leading mark, the title
18
+ * over its detail, the value over its detail, then the chevron or check.
19
+ */
20
+ export declare function ListRowContent({ id, title, detail, value, valueDetail, valueTone, leading, tone, titleAppearance, accessory, }: ListRowContentProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { cx } from '../../class-names.js';
3
+ import { ListRowAccessoryMark } from './ListRowAccessoryMark.js';
4
+ /**
5
+ * A list row's parts in reading order: the hidden leading mark, the title
6
+ * over its detail, the value over its detail, then the chevron or check.
7
+ */
8
+ export function ListRowContent({ id, title, detail, value, valueDetail, valueTone, leading, tone, titleAppearance, accessory, }) {
9
+ return (_jsxs(_Fragment, { children: [leading === undefined ? null : (_jsx("span", { "aria-hidden": "true", className: "sw-list-row-leading", children: leading })), _jsxs("span", { className: "sw-list-row-label", children: [_jsx("span", { className: cx('sw-list-row-title', titleAppearance === 'plain' && 'sw-list-row-title-plain', tone === 'danger' && 'sw-list-row-title-danger'), id: `${id}-title`, children: title }), detail ? (_jsx("span", { className: "sw-list-row-detail", id: `${id}-detail`, children: detail })) : null] }), value === undefined ? null : (_jsxs("span", { className: "sw-list-row-end", children: [_jsx("span", { className: cx('sw-list-row-value', valueTone && `sw-list-row-value-${valueTone}`), id: `${id}-value`, children: value }), valueDetail ? (_jsx("span", { className: "sw-list-row-value-detail", id: `${id}-value-detail`, children: valueDetail })) : null] })), _jsx(ListRowAccessoryMark, { kind: accessory })] }));
10
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * The element a ListRow renders as: an `li` in a ListGroup's list, a `div`
3
+ * anywhere else, such as a ListGroup's `footer`.
4
+ */
5
+ export declare const ListRowContainer: import("react").Context<"div" | "li">;
@@ -0,0 +1,6 @@
1
+ import { createContext } from 'react';
2
+ /**
3
+ * The element a ListRow renders as: an `li` in a ListGroup's list, a `div`
4
+ * anywhere else, such as a ListGroup's `footer`.
5
+ */
6
+ export const ListRowContainer = createContext('div');
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Whether a media query matches now, following its changes. Where there is
3
+ * no `matchMedia` (a server render, jsdom) it reads as `fallback`.
4
+ */
5
+ export declare function useMediaQuery(query: string, fallback: boolean): boolean;
@@ -0,0 +1,18 @@
1
+ import { useCallback, useSyncExternalStore } from 'react';
2
+ function canMatch() {
3
+ return (typeof window !== 'undefined' && typeof window.matchMedia === 'function');
4
+ }
5
+ /**
6
+ * Whether a media query matches now, following its changes. Where there is
7
+ * no `matchMedia` (a server render, jsdom) it reads as `fallback`.
8
+ */
9
+ export function useMediaQuery(query, fallback) {
10
+ const subscribe = useCallback((onChange) => {
11
+ if (!canMatch())
12
+ return () => undefined;
13
+ const list = window.matchMedia(query);
14
+ list.addEventListener('change', onChange);
15
+ return () => list.removeEventListener('change', onChange);
16
+ }, [query]);
17
+ return useSyncExternalStore(subscribe, () => (canMatch() ? window.matchMedia(query).matches : fallback), () => fallback);
18
+ }
@@ -6,3 +6,9 @@
6
6
  export declare function chevronStrokeIn(color: string): string;
7
7
  /** The muted chevron Accordion, Select and the menus share. */
8
8
  export declare const chevronStroke: string;
9
+ /**
10
+ * A check's two strokes in `color`: the bottom and right borders of a box
11
+ * the caller sizes and turns 45°, so forced colours keep them. Checkbox,
12
+ * Steps and ListRow share it.
13
+ */
14
+ export declare function checkStrokeIn(color: string): string;
@@ -1,3 +1,8 @@
1
+ /*
2
+ * The strokes of Scalewing's private control chrome, drawn with borders so
3
+ * forced colours keep them: the chevron (Accordion, Select, the menus,
4
+ * Pagination, ListRow) and the check (Checkbox, Steps, ListRow).
5
+ */
1
6
  /**
2
7
  * A stroked chevron in `color`: two sides of a `space-2` square (its
3
8
  * bottom and right borders, so forced colours keep it), turned by each
@@ -12,3 +17,12 @@ export function chevronStrokeIn(color) {
12
17
  }
13
18
  /** The muted chevron Accordion, Select and the menus share. */
14
19
  export const chevronStroke = chevronStrokeIn('var(--sw-color-muted)');
20
+ /**
21
+ * A check's two strokes in `color`: the bottom and right borders of a box
22
+ * the caller sizes and turns 45°, so forced colours keep them. Checkbox,
23
+ * Steps and ListRow share it.
24
+ */
25
+ export function checkStrokeIn(color) {
26
+ return `border-bottom: 2px solid ${color};
27
+ border-right: 2px solid ${color};`;
28
+ }
@@ -13,6 +13,10 @@ import { joinedZIndex } from './stacking.js';
13
13
  * divider in its own text colour at low strength, so a joined row of them
14
14
  * still reads as separate buttons; forced colours draw every border.
15
15
  *
16
+ * The buttons are found by type, not by place, so an open calendar a
17
+ * button renders beside itself (CalendarButton, DateRangeButton) does not
18
+ * cost the next button its divider or the last one its rounded corners.
19
+ *
16
20
  * The group is its own stacking context: a pressed button's ring paints
17
21
  * over its neighbours and the focused button's standard outer ring over
18
22
  * both, so neither is covered by the next button.
@@ -33,21 +37,21 @@ ${group} > .sw-button {
33
37
  border-radius: 0;
34
38
  }
35
39
 
36
- ${group} > .sw-button + .sw-button {
40
+ ${group} > .sw-button ~ .sw-button {
37
41
  margin-inline-start: -1px;
38
42
  }
39
43
 
40
- ${group} > .sw-button:first-child {
44
+ ${group} > .sw-button:first-of-type {
41
45
  border-end-start-radius: var(--sw-radius-sm);
42
46
  border-start-start-radius: var(--sw-radius-sm);
43
47
  }
44
48
 
45
- ${group} > .sw-button:last-child {
49
+ ${group} > .sw-button:last-of-type {
46
50
  border-end-end-radius: var(--sw-radius-sm);
47
51
  border-start-end-radius: var(--sw-radius-sm);
48
52
  }
49
53
 
50
- ${group} > .sw-button + .sw-button:not(.sw-button-secondary) {
54
+ ${group} > .sw-button ~ .sw-button:not(.sw-button-secondary) {
51
55
  border-inline-start-color: color-mix(in srgb, currentColor 30%, transparent);
52
56
  }
53
57
 
@@ -30,7 +30,7 @@ ${track} > .sw-button {
30
30
  color: var(--sw-color-text);
31
31
  }
32
32
 
33
- ${track} > .sw-button + .sw-button {
33
+ ${track} > .sw-button ~ .sw-button {
34
34
  border-inline-start-color: var(--sw-color-border);
35
35
  }
36
36
 
@@ -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';
@@ -141,6 +144,12 @@ ${cssDateFieldClasses()}
141
144
 
142
145
  ${cssCalendarButtonClasses()}
143
146
 
147
+ ${cssDateRangeClasses()}
148
+
149
+ ${cssListClasses()}
150
+
151
+ ${cssCountPillClasses()}
152
+
144
153
  ${cssBarChartClasses()}
145
154
 
146
155
  ${cssDataBarClasses()}
@@ -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
+ }
@@ -2,6 +2,7 @@ import { typographyVariants } from '@scalewing/tokens';
2
2
  import { disabledControlForcedColors, disabledControlSurface, } from './css-document.js';
3
3
  import { zIndex } from './stacking.js';
4
4
  import { quietFill } from './quiet-fill.js';
5
+ import { rangeBand, rangeBandHover } from './range-band.js';
5
6
  const body = typographyVariants.body;
6
7
  const label = typographyVariants.label;
7
8
  const caption = typographyVariants.caption;
@@ -241,7 +242,7 @@ function calendarRules() {
241
242
  * accent ring (3:1 or more on the band). The selected day sits on top.
242
243
  */
243
244
  .sw-date-field-day-in-range {
244
- background: color-mix(in srgb, var(--sw-color-accent) 16%, transparent);
245
+ background: ${rangeBand};
245
246
  border-radius: 0;
246
247
  color: var(--sw-color-text);
247
248
  }
@@ -267,7 +268,7 @@ function calendarRules() {
267
268
  }
268
269
 
269
270
  .sw-date-field-day-in-range:hover:not([aria-disabled='true']) {
270
- background: color-mix(in srgb, var(--sw-color-accent) 24%, transparent);
271
+ background: ${rangeBandHover};
271
272
  }
272
273
 
273
274
  .sw-date-field-day[aria-selected='true'],
@@ -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[];