@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.
- package/CHANGELOG.md +9 -0
- package/README.md +102 -0
- package/dist/calendar-month.d.ts +6 -0
- package/dist/calendar-month.js +15 -0
- package/dist/components/DateRangeButton.d.ts +65 -0
- package/dist/components/DateRangeButton.js +54 -0
- package/dist/components/ListGroup.d.ts +33 -0
- package/dist/components/ListGroup.js +19 -0
- package/dist/components/ListRow.d.ts +51 -0
- package/dist/components/ListRow.js +59 -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/StatTile.d.ts +11 -4
- package/dist/components/StatTile.js +11 -4
- 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/CalendarHeader.js +2 -11
- 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/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 +20 -0
- package/dist/components/list/ListRowContent.js +10 -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/chevron.d.ts +6 -0
- package/dist/css/chevron.js +14 -0
- package/dist/css/css-button-group-attached.js +8 -4
- package/dist/css/css-button-group-track.js +1 -1
- package/dist/css/css-checkbox.js +2 -2
- package/dist/css/css-components.js +9 -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.js +3 -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-list-row.d.ts +2 -0
- package/dist/css/css-list-row.js +193 -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-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-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.js +2 -2
- package/dist/css/stylesheet.js +6 -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 +6 -1
- package/dist/index.js +6 -1
- package/dist/list-options.d.ts +70 -0
- package/dist/list-options.js +77 -0
- package/dist/styles.css +507 -26
- 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,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,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
|
+
}
|
package/dist/css/chevron.d.ts
CHANGED
|
@@ -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;
|
package/dist/css/chevron.js
CHANGED
|
@@ -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
|
|
40
|
+
${group} > .sw-button ~ .sw-button {
|
|
37
41
|
margin-inline-start: -1px;
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
${group} > .sw-button:first-
|
|
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-
|
|
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
|
|
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
|
|
package/dist/css/css-checkbox.js
CHANGED
|
@@ -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
|
-
|
|
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,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:
|
|
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:
|
|
271
|
+
background: ${rangeBandHover};
|
|
271
272
|
}
|
|
272
273
|
|
|
273
274
|
.sw-date-field-day[aria-selected='true'],
|
|
@@ -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
|
+
}
|