@scalewing/react 1.38.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 +18 -0
- package/README.md +155 -1
- package/dist/calendar-month.d.ts +6 -0
- package/dist/calendar-month.js +15 -0
- package/dist/chart-axis.d.ts +61 -0
- package/dist/chart-axis.js +83 -0
- package/dist/chart-dates.d.ts +6 -0
- package/dist/chart-dates.js +15 -0
- package/dist/chart-metrics.d.ts +40 -0
- package/dist/chart-metrics.js +48 -0
- package/dist/chart-scale.d.ts +48 -0
- package/dist/chart-scale.js +116 -0
- package/dist/chart-table-rows.d.ts +8 -0
- package/dist/chart-table-rows.js +1 -0
- package/dist/column-chart-bars.d.ts +38 -0
- package/dist/column-chart-bars.js +82 -0
- package/dist/column-chart-callouts.d.ts +48 -0
- package/dist/column-chart-callouts.js +54 -0
- package/dist/column-chart-input.d.ts +40 -0
- package/dist/column-chart-input.js +60 -0
- package/dist/column-chart-layout.d.ts +63 -0
- package/dist/column-chart-layout.js +97 -0
- package/dist/components/BarChart.d.ts +1 -1
- package/dist/components/BarChart.js +1 -1
- package/dist/components/ChartLegend.d.ts +38 -0
- package/dist/components/ChartLegend.js +32 -0
- package/dist/components/ColumnChart.d.ts +72 -0
- package/dist/components/ColumnChart.js +71 -0
- package/dist/components/DataBar.d.ts +6 -6
- package/dist/components/DateRangeButton.d.ts +65 -0
- package/dist/components/DateRangeButton.js +54 -0
- package/dist/components/LineChart.d.ts +83 -0
- package/dist/components/LineChart.js +77 -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/chart/ChartTable.d.ts +16 -0
- package/dist/components/chart/ChartTable.js +12 -0
- package/dist/components/chart/ChartValueAxis.d.ts +14 -0
- package/dist/components/chart/ChartValueAxis.js +11 -0
- package/dist/components/chart/use-chart-width.d.ts +8 -0
- package/dist/components/chart/use-chart-width.js +34 -0
- package/dist/components/column-chart/ChartCalloutList.d.ts +16 -0
- package/dist/components/column-chart/ChartCalloutList.js +13 -0
- package/dist/components/column-chart/ColumnChartDrawing.d.ts +17 -0
- package/dist/components/column-chart/ColumnChartDrawing.js +18 -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/line-chart/LineChartDrawing.d.ts +17 -0
- package/dist/components/line-chart/LineChartDrawing.js +16 -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/chart-marks.d.ts +10 -0
- package/dist/css/chart-marks.js +15 -0
- package/dist/css/chart-tones.d.ts +68 -0
- package/dist/css/chart-tones.js +130 -0
- package/dist/css/chevron.d.ts +6 -0
- package/dist/css/chevron.js +14 -0
- package/dist/css/{css-chart.d.ts → css-bar-chart.d.ts} +2 -2
- package/dist/css/{css-chart.js → css-bar-chart.js} +2 -2
- package/dist/css/css-button-group-attached.js +8 -4
- package/dist/css/css-button-group-track.js +1 -1
- package/dist/css/css-chart-legend.d.ts +5 -0
- package/dist/css/css-chart-legend.js +102 -0
- package/dist/css/css-chart-plot.d.ts +2 -0
- package/dist/css/css-chart-plot.js +170 -0
- package/dist/css/css-checkbox.js +2 -2
- package/dist/css/css-components.js +23 -2
- package/dist/css/css-count-pill.d.ts +2 -0
- package/dist/css/css-count-pill.js +54 -0
- package/dist/css/css-data-bar.d.ts +4 -9
- package/dist/css/css-data-bar.js +15 -31
- 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-line-chart.d.ts +2 -0
- package/dist/css/css-line-chart.js +31 -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 +16 -2
- 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 +9 -1
- package/dist/index.js +9 -1
- package/dist/is-one-of.d.ts +5 -0
- package/dist/is-one-of.js +7 -0
- package/dist/line-chart-input.d.ts +39 -0
- package/dist/line-chart-input.js +70 -0
- package/dist/line-chart-layout.d.ts +68 -0
- package/dist/line-chart-layout.js +99 -0
- package/dist/line-chart-markers.d.ts +29 -0
- package/dist/line-chart-markers.js +57 -0
- package/dist/line-chart-path.d.ts +18 -0
- package/dist/line-chart-path.js +33 -0
- package/dist/line-chart-points.d.ts +6 -0
- package/dist/line-chart-points.js +8 -0
- package/dist/line-chart-table.d.ts +15 -0
- package/dist/line-chart-table.js +29 -0
- package/dist/list-options.d.ts +70 -0
- package/dist/list-options.js +77 -0
- package/dist/styles.css +726 -26
- package/package.json +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type NavCountProps = {
|
|
2
|
+
/**
|
|
3
|
+
* How many things wait behind the destination, such as tasks to do: a
|
|
4
|
+
* filled pill after its words, read in the link's name ("Tasks 8"). A
|
|
5
|
+
* whole number; 0 shows nothing.
|
|
6
|
+
*/
|
|
7
|
+
count: number;
|
|
8
|
+
/**
|
|
9
|
+
* What the count means, in the consumer's words ("8 tasks to do"): read
|
|
10
|
+
* in the name in place of the bare number ("Tasks 8 tasks to do"), the
|
|
11
|
+
* pill then hidden from assistive technology.
|
|
12
|
+
*/
|
|
13
|
+
countLabel?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* A count after a Nav destination's words, placed inside its link or
|
|
17
|
+
* Button: `<a href="/tasks">Tasks<NavCount count={8} /></a>`. It is the
|
|
18
|
+
* pill SectionNav's item count draws, and it is part of the destination's
|
|
19
|
+
* accessible name, as there.
|
|
20
|
+
*/
|
|
21
|
+
export declare function NavCount({ count, countLabel }: NavCountProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** Fails closed on a count that is not a whole number or an empty label. */
|
|
3
|
+
function assertNavCount({ count, countLabel }) {
|
|
4
|
+
if (!Number.isInteger(count) || count < 0)
|
|
5
|
+
throw new RangeError(`NavCount count must be a whole number from 0: ${String(count)}`);
|
|
6
|
+
if (countLabel !== undefined &&
|
|
7
|
+
(typeof countLabel !== 'string' || !countLabel.trim()))
|
|
8
|
+
throw new RangeError('NavCount countLabel must be non-empty text');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A count after a Nav destination's words, placed inside its link or
|
|
12
|
+
* Button: `<a href="/tasks">Tasks<NavCount count={8} /></a>`. It is the
|
|
13
|
+
* pill SectionNav's item count draws, and it is part of the destination's
|
|
14
|
+
* accessible name, as there.
|
|
15
|
+
*/
|
|
16
|
+
export function NavCount({ count, countLabel }) {
|
|
17
|
+
assertNavCount({ count, countLabel });
|
|
18
|
+
if (count === 0)
|
|
19
|
+
return null;
|
|
20
|
+
// The space is its own text node, so every browser and the name's
|
|
21
|
+
// computation keep it between the words and the count.
|
|
22
|
+
return (_jsxs(_Fragment, { children: [' ', countLabel ? _jsx("span", { className: "sw-sr-only", children: countLabel }) : null, _jsx("span", { "aria-hidden": countLabel ? true : undefined, className: "sw-nav-count", children: count })] }));
|
|
23
|
+
}
|
|
@@ -4,15 +4,8 @@ import { breakpoints } from '../css/breakpoints.js';
|
|
|
4
4
|
import { sectionNavVerticalClass } from '../css/css-section-nav.js';
|
|
5
5
|
import { assertSectionNavAppearance, } from '../css/css-section-nav-filled.js';
|
|
6
6
|
import { tabStop } from '../tab-stop.js';
|
|
7
|
+
import { plainPress } from './link-press.js';
|
|
7
8
|
export { sectionNavAppearances } from '../css/css-section-nav-filled.js';
|
|
8
|
-
function plainPress(event) {
|
|
9
|
-
return (event.button === 0 &&
|
|
10
|
-
!event.defaultPrevented &&
|
|
11
|
-
!event.metaKey &&
|
|
12
|
-
!event.ctrlKey &&
|
|
13
|
-
!event.shiftKey &&
|
|
14
|
-
!event.altKey);
|
|
15
|
-
}
|
|
16
9
|
function ariaCurrent(current) {
|
|
17
10
|
if (current === true)
|
|
18
11
|
return 'true';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
-
import { type StatTileTone, statTileTones } from '../css/css-stat-tile.js';
|
|
3
|
-
export type { StatTileTone };
|
|
4
|
-
export { statTileTones };
|
|
2
|
+
import { type StatTileAppearance, statTileAppearances, type StatTileTone, statTileTones } from '../css/css-stat-tile.js';
|
|
3
|
+
export type { StatTileAppearance, StatTileTone };
|
|
4
|
+
export { statTileAppearances, statTileTones };
|
|
5
5
|
export type StatTileEmphasis = 'default' | 'primary';
|
|
6
6
|
export type StatTileProps = Omit<HTMLAttributes<HTMLElement>, 'children'> & {
|
|
7
7
|
/** A short name for the figure, set in the label variant. */
|
|
@@ -16,10 +16,17 @@ export type StatTileProps = Omit<HTMLAttributes<HTMLElement>, 'children'> & {
|
|
|
16
16
|
caption?: ReactNode;
|
|
17
17
|
/** `primary` fills the tile in the accent for the one figure a page leads with. */
|
|
18
18
|
emphasis?: StatTileEmphasis;
|
|
19
|
+
/**
|
|
20
|
+
* `plain` drops the tile's surface, edge and padding, so the figure sits
|
|
21
|
+
* inside a card that already has them, such as four answers in a row
|
|
22
|
+
* with hairlines between them. A plain tile cannot be `primary`, which
|
|
23
|
+
* is a fill. Default `card`.
|
|
24
|
+
*/
|
|
25
|
+
appearance?: StatTileAppearance;
|
|
19
26
|
};
|
|
20
27
|
/**
|
|
21
28
|
* One prominent figure with its label: the tiles a report or a list opens
|
|
22
29
|
* with. Presentation only; the consumer formats the number and picks the
|
|
23
30
|
* glyph.
|
|
24
31
|
*/
|
|
25
|
-
export declare function StatTile({ caption, className, emphasis, glyph, label, tone, value, ...rest }: StatTileProps): import("react").JSX.Element;
|
|
32
|
+
export declare function StatTile({ appearance, caption, className, emphasis, glyph, label, tone, value, ...rest }: StatTileProps): import("react").JSX.Element;
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cx } from '../class-names.js';
|
|
3
|
-
import { statTileTones } from '../css/css-stat-tile.js';
|
|
3
|
+
import { statTileAppearances, statTileTones, } from '../css/css-stat-tile.js';
|
|
4
4
|
import { Text } from './Text.js';
|
|
5
|
-
export { statTileTones };
|
|
5
|
+
export { statTileAppearances, statTileTones };
|
|
6
|
+
function assertStatTile(appearance, emphasis) {
|
|
7
|
+
if (!statTileAppearances.includes(appearance))
|
|
8
|
+
throw new RangeError(`Unknown StatTile appearance: ${String(appearance)}`);
|
|
9
|
+
if (appearance === 'plain' && emphasis === 'primary')
|
|
10
|
+
throw new RangeError('A plain StatTile has no surface to fill; emphasis primary needs appearance card');
|
|
11
|
+
}
|
|
6
12
|
/**
|
|
7
13
|
* One prominent figure with its label: the tiles a report or a list opens
|
|
8
14
|
* with. Presentation only; the consumer formats the number and picks the
|
|
9
15
|
* glyph.
|
|
10
16
|
*/
|
|
11
|
-
export function StatTile({ caption, className, emphasis = 'default', glyph, label, tone = 'default', value, ...rest }) {
|
|
17
|
+
export function StatTile({ appearance = 'card', caption, className, emphasis = 'default', glyph, label, tone = 'default', value, ...rest }) {
|
|
18
|
+
assertStatTile(appearance, emphasis);
|
|
12
19
|
const primary = emphasis === 'primary';
|
|
13
|
-
return (_jsxs("section", { className: cx('sw-stat-tile', primary && 'sw-stat-tile-primary', className), ...rest, children: [glyph ? (_jsx("span", { "aria-hidden": "true", className: "sw-stat-tile-glyph", children: glyph })) : null, _jsxs("span", { className: "sw-stat-tile-body", children: [_jsx(Text, { as: "span", className: "sw-stat-tile-label", color: primary ? 'onAccent' : 'muted', variant: "label", children: label }), _jsx(Text, { as: "strong", className: "sw-stat-tile-value", color: primary ? 'onAccent' : tone === 'default' ? 'text' : tone, variant: "heading", children: value }), caption ? (_jsx(Text, { as: "span", className: "sw-stat-tile-caption", color: primary ? 'onAccent' : 'muted', variant: "caption", children: caption })) : null] })] }));
|
|
20
|
+
return (_jsxs("section", { className: cx('sw-stat-tile', appearance === 'plain' && 'sw-stat-tile-plain', primary && 'sw-stat-tile-primary', className), ...rest, children: [glyph ? (_jsx("span", { "aria-hidden": "true", className: "sw-stat-tile-glyph", children: glyph })) : null, _jsxs("span", { className: "sw-stat-tile-body", children: [_jsx(Text, { as: "span", className: "sw-stat-tile-label", color: primary ? 'onAccent' : 'muted', variant: "label", children: label }), _jsx(Text, { as: "strong", className: "sw-stat-tile-value", color: primary ? 'onAccent' : tone === 'default' ? 'text' : tone, variant: "heading", children: value }), caption ? (_jsx(Text, { as: "span", className: "sw-stat-tile-caption", color: primary ? 'onAccent' : 'muted', variant: "caption", children: caption })) : null] })] }));
|
|
14
21
|
}
|
|
@@ -13,7 +13,22 @@ export type CalendarGridProps = {
|
|
|
13
13
|
onSelect: (value: string) => void;
|
|
14
14
|
/** Days to tint as a span, such as the period a page shows. */
|
|
15
15
|
range?: DateOnlyRange;
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* The selected day; `''` for none. A range instead selects every day in
|
|
18
|
+
* it (the grid is then multiselectable) and tints it as `range` does.
|
|
19
|
+
*/
|
|
20
|
+
selected: string | DateOnlyRange;
|
|
21
|
+
/**
|
|
22
|
+
* The last day a press may pick when it is earlier than `max`, such as a
|
|
23
|
+
* range's longest end. Later days are `aria-disabled`; keys still reach
|
|
24
|
+
* them up to `max`, for orientation.
|
|
25
|
+
*/
|
|
26
|
+
latest?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Leave the neighbouring months' days blank, so months shown side by
|
|
29
|
+
* side hold each day once. By default they are shown, muted.
|
|
30
|
+
*/
|
|
31
|
+
blankOutside?: boolean;
|
|
17
32
|
titleId: string;
|
|
18
33
|
today: string;
|
|
19
34
|
weekStartsOn: WeekStart;
|
|
@@ -23,4 +38,4 @@ export type CalendarGridProps = {
|
|
|
23
38
|
* `[min, max]` stay focusable for orientation but are `aria-disabled`;
|
|
24
39
|
* padding past the four-digit years is blank and inert.
|
|
25
40
|
*/
|
|
26
|
-
export declare function CalendarGrid({ focusDate, locale, max, min, month, onFocusDate, onMoveFocus, onSelect, range, selected, titleId, today, weekStartsOn, }: CalendarGridProps): import("react").JSX.Element;
|
|
41
|
+
export declare function CalendarGrid({ focusDate, locale, max, min, month, onFocusDate, onMoveFocus, onSelect, range, selected, latest, blankOutside, titleId, today, weekStartsOn, }: CalendarGridProps): import("react").JSX.Element;
|
|
@@ -12,14 +12,22 @@ function rangeClassNames(place) {
|
|
|
12
12
|
(place === 'end' || place === 'only') && 'sw-date-field-day-range-end',
|
|
13
13
|
];
|
|
14
14
|
}
|
|
15
|
+
function isSelectedDay(value, selected) {
|
|
16
|
+
return typeof selected === 'string'
|
|
17
|
+
? value === selected
|
|
18
|
+
: dayInRange(value, selected) !== null;
|
|
19
|
+
}
|
|
15
20
|
/**
|
|
16
21
|
* The month as a WAI-ARIA grid with one roving tab stop. Days outside
|
|
17
22
|
* `[min, max]` stay focusable for orientation but are `aria-disabled`;
|
|
18
23
|
* padding past the four-digit years is blank and inert.
|
|
19
24
|
*/
|
|
20
|
-
export function CalendarGrid({ focusDate, locale, max, min, month, onFocusDate, onMoveFocus, onSelect, range, selected, titleId, today, weekStartsOn, }) {
|
|
25
|
+
export function CalendarGrid({ focusDate, locale, max, min, month, onFocusDate, onMoveFocus, onSelect, range, selected, latest, blankOutside = false, titleId, today, weekStartsOn, }) {
|
|
26
|
+
const pickMax = latest !== undefined && (max === undefined || latest < max) ? latest : max;
|
|
27
|
+
const tint = typeof selected === 'string' ? range : selected;
|
|
28
|
+
const unavailable = (value) => isOutsideDateRange(value, min, pickMax);
|
|
21
29
|
function choose(value) {
|
|
22
|
-
if (!
|
|
30
|
+
if (!unavailable(value))
|
|
23
31
|
onSelect(value);
|
|
24
32
|
}
|
|
25
33
|
function onKeyDown(event) {
|
|
@@ -35,7 +43,7 @@ export function CalendarGrid({ focusDate, locale, max, min, month, onFocusDate,
|
|
|
35
43
|
event.preventDefault();
|
|
36
44
|
onMoveFocus(target);
|
|
37
45
|
}
|
|
38
|
-
return (_jsxs("table", { "aria-labelledby": titleId, className: "sw-date-field-grid", onKeyDown: onKeyDown, role: "grid", children: [_jsx("thead", { children: _jsx("tr", { children: weekdayLabels(locale, weekStartsOn).map((weekday) => (_jsx("th", { abbr: weekday.long, scope: "col", children: weekday.short }, weekday.long))) }) }), _jsx("tbody", { children: monthGrid(month, weekStartsOn).map((row, rowIndex) => (_jsx("tr", { children: row.map((cell, column) => cell === null ? (_jsx("td", { "aria-disabled": "true", className: "sw-date-field-day sw-date-field-day-outside", role: "gridcell" }, `blank-${column}`)) : (_jsx("td", { "aria-current": cell.value === today ? 'date' : undefined, "aria-disabled":
|
|
46
|
+
return (_jsxs("table", { "aria-labelledby": titleId, "aria-multiselectable": typeof selected === 'string' ? undefined : true, className: "sw-date-field-grid", onKeyDown: onKeyDown, role: "grid", children: [_jsx("thead", { children: _jsx("tr", { children: weekdayLabels(locale, weekStartsOn).map((weekday) => (_jsx("th", { abbr: weekday.long, scope: "col", children: weekday.short }, weekday.long))) }) }), _jsx("tbody", { children: monthGrid(month, weekStartsOn).map((row, rowIndex) => (_jsx("tr", { children: row.map((cell, column) => cell === null || (blankOutside && !cell.inMonth) ? (_jsx("td", { "aria-disabled": "true", className: "sw-date-field-day sw-date-field-day-outside", role: "gridcell" }, `blank-${column}`)) : (_jsx("td", { "aria-current": cell.value === today ? 'date' : undefined, "aria-disabled": unavailable(cell.value) || undefined, "aria-label": formatDateLabel(cell.value, locale), "aria-selected": isSelectedDay(cell.value, selected), className: cx('sw-date-field-day', !cell.inMonth && 'sw-date-field-day-outside', ...rangeClassNames(dayInRange(cell.value, tint))), "data-date": cell.value, onClick: () => choose(cell.value), onFocus: () => {
|
|
39
47
|
// A press on a neighboring month's day selects it; moving
|
|
40
48
|
// the grid first would pull the day out from under it.
|
|
41
49
|
if (cell.inMonth && cell.value !== focusDate)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ReactNode, type RefObject } from 'react';
|
|
2
|
+
import { type GridFocus } from './use-grid-focus.js';
|
|
3
|
+
export type CalendarPopoverProps = {
|
|
4
|
+
/** The element the popover sits beside, such as the field or button. */
|
|
5
|
+
anchorRef: RefObject<HTMLElement | null>;
|
|
6
|
+
/** The button that toggles it; a press there is not a press outside. */
|
|
7
|
+
buttonRef: RefObject<HTMLElement | null>;
|
|
8
|
+
popoverRef: RefObject<HTMLDivElement | null>;
|
|
9
|
+
id: string;
|
|
10
|
+
/** Names the dialog by an element, or by `aria-label`. */
|
|
11
|
+
'aria-labelledby'?: string;
|
|
12
|
+
'aria-label'?: string;
|
|
13
|
+
/** `true` returns focus to the button: Escape does, a press outside does not. */
|
|
14
|
+
onClose: (restoreFocus: boolean) => void;
|
|
15
|
+
/** Follows focus in the grid when the popover itself holds it. */
|
|
16
|
+
focusHandlers?: GridFocus['focusHandlers'];
|
|
17
|
+
className?: string;
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* A calendar's popover: a modal dialog on the top layer beside its anchor,
|
|
22
|
+
* as the WAI-ARIA date picker dialog pattern asks. Escape closes it and
|
|
23
|
+
* returns focus; Tab stays inside; a press outside closes it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function CalendarPopover({ anchorRef, buttonRef, popoverRef, id, 'aria-labelledby': labelledBy, 'aria-label': label, onClose, focusHandlers, className, children, }: CalendarPopoverProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cx } from '../../class-names.js';
|
|
3
|
+
import { useAnchoredPopover } from '../use-anchored-popover.js';
|
|
4
|
+
import { wrapTab } from './wrap-tab.js';
|
|
5
|
+
/**
|
|
6
|
+
* A calendar's popover: a modal dialog on the top layer beside its anchor,
|
|
7
|
+
* as the WAI-ARIA date picker dialog pattern asks. Escape closes it and
|
|
8
|
+
* returns focus; Tab stays inside; a press outside closes it.
|
|
9
|
+
*/
|
|
10
|
+
export function CalendarPopover({ anchorRef, buttonRef, popoverRef, id, 'aria-labelledby': labelledBy, 'aria-label': label, onClose, focusHandlers, className, children, }) {
|
|
11
|
+
useAnchoredPopover(popoverRef, anchorRef, buttonRef, () => onClose(false));
|
|
12
|
+
function onKeyDown(event) {
|
|
13
|
+
if (event.key === 'Escape') {
|
|
14
|
+
event.preventDefault();
|
|
15
|
+
event.stopPropagation();
|
|
16
|
+
onClose(true);
|
|
17
|
+
}
|
|
18
|
+
else if (event.key === 'Tab')
|
|
19
|
+
wrapTab(event);
|
|
20
|
+
}
|
|
21
|
+
return (_jsx("div", { ...focusHandlers, "aria-label": label, "aria-labelledby": labelledBy, "aria-modal": "true", className: cx('sw-date-field-calendar', className), id: id, onKeyDown: onKeyDown, ref: popoverRef, role: "dialog", children: children }));
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CalendarMonth } from '../../calendar-month.js';
|
|
2
|
+
export type MonthStepProps = {
|
|
3
|
+
/** The month the step leaves from: the first or the last month shown. */
|
|
4
|
+
month: CalendarMonth;
|
|
5
|
+
delta: 1 | -1;
|
|
6
|
+
label: string;
|
|
7
|
+
min?: string;
|
|
8
|
+
max?: string;
|
|
9
|
+
onMonthChange: (month: CalendarMonth) => void;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A calendar's previous or next month step. Past the four-digit years or
|
|
13
|
+
* outside `[min, max]` it is `aria-disabled`, so it keeps focus and its
|
|
14
|
+
* press does nothing.
|
|
15
|
+
*/
|
|
16
|
+
export declare function MonthStep({ delta, label, max, min, month, onMonthChange, }: MonthStepProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { monthInRange, shiftMonth, } from '../../calendar-month.js';
|
|
3
|
+
import { tabStop } from '../../tab-stop.js';
|
|
4
|
+
import { DateFieldGlyph } from '../date-field/DateFieldGlyph.js';
|
|
5
|
+
/**
|
|
6
|
+
* A calendar's previous or next month step. Past the four-digit years or
|
|
7
|
+
* outside `[min, max]` it is `aria-disabled`, so it keeps focus and its
|
|
8
|
+
* press does nothing.
|
|
9
|
+
*/
|
|
10
|
+
export function MonthStep({ delta, label, max, min, month, onMonthChange, }) {
|
|
11
|
+
const target = shiftMonth(month, delta);
|
|
12
|
+
const unavailable = target.year < 1 || target.year > 9999 || !monthInRange(target, min, max);
|
|
13
|
+
return (_jsx("button", { "aria-disabled": unavailable || undefined, "aria-label": label, className: "sw-date-field-step", onClick: () => {
|
|
14
|
+
if (!unavailable)
|
|
15
|
+
onMonthChange(target);
|
|
16
|
+
}, tabIndex: tabStop, type: "button", children: _jsx(DateFieldGlyph, { name: delta < 0 ? 'previous' : 'next' }) }));
|
|
17
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type FocusEvent, type RefObject } from 'react';
|
|
2
|
+
export type GridFocus = {
|
|
3
|
+
/** The next focus date takes DOM focus, as after a grid key. */
|
|
4
|
+
requestFocus: () => void;
|
|
5
|
+
/** Spread on the element holding the grids, to follow where focus is. */
|
|
6
|
+
focusHandlers: {
|
|
7
|
+
onBlur: () => void;
|
|
8
|
+
onFocus: (event: FocusEvent<HTMLElement>) => void;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Moves DOM focus to a calendar's focus date when asked (on mount when
|
|
13
|
+
* `focusOnMount`, and after a grid key) and while a day already holds
|
|
14
|
+
* focus, so a new value or new bounds never strand focus on a removed day.
|
|
15
|
+
* Header controls and presses change the date without taking focus from
|
|
16
|
+
* where it is. Shared by DateField's calendar and DateRangeButton.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useGridFocus(containerRef: RefObject<HTMLElement | null>, focusDate: string, focusOnMount: boolean): GridFocus;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useLayoutEffect, useRef, } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Moves DOM focus to a calendar's focus date when asked (on mount when
|
|
4
|
+
* `focusOnMount`, and after a grid key) and while a day already holds
|
|
5
|
+
* focus, so a new value or new bounds never strand focus on a removed day.
|
|
6
|
+
* Header controls and presses change the date without taking focus from
|
|
7
|
+
* where it is. Shared by DateField's calendar and DateRangeButton.
|
|
8
|
+
*/
|
|
9
|
+
export function useGridFocus(containerRef, focusDate, focusOnMount) {
|
|
10
|
+
const focusGrid = useRef(focusOnMount);
|
|
11
|
+
// Whether a day holds DOM focus. Removing that day fires no blur, so this
|
|
12
|
+
// stays true when a new value or bounds move the grid out from under it.
|
|
13
|
+
const gridFocused = useRef(false);
|
|
14
|
+
useLayoutEffect(() => {
|
|
15
|
+
if (!focusGrid.current && !gridFocused.current)
|
|
16
|
+
return;
|
|
17
|
+
focusGrid.current = false;
|
|
18
|
+
containerRef.current
|
|
19
|
+
?.querySelector(`[role="grid"] [data-date="${focusDate}"]`)
|
|
20
|
+
?.focus({ preventScroll: true });
|
|
21
|
+
}, [containerRef, focusDate]);
|
|
22
|
+
return {
|
|
23
|
+
requestFocus: () => {
|
|
24
|
+
focusGrid.current = true;
|
|
25
|
+
},
|
|
26
|
+
focusHandlers: {
|
|
27
|
+
onBlur: () => {
|
|
28
|
+
gridFocused.current = false;
|
|
29
|
+
},
|
|
30
|
+
onFocus: (event) => {
|
|
31
|
+
gridFocused.current = event.target.closest('[role="grid"]') !== null;
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type KeyboardEvent } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Keeps Tab and Shift+Tab inside a calendar popover, as a modal dialog
|
|
4
|
+
* does: from the last stop to the first, and back. Shared by DateField's
|
|
5
|
+
* calendar and DateRangeButton's popover.
|
|
6
|
+
*/
|
|
7
|
+
export declare function wrapTab(event: KeyboardEvent<HTMLElement>): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** A calendar popover's tab stops: enabled buttons and a grid's roving day. */
|
|
2
|
+
function isTabStop(node) {
|
|
3
|
+
if (node instanceof HTMLButtonElement)
|
|
4
|
+
return !node.disabled;
|
|
5
|
+
return node.getAttribute('tabindex') === '0';
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Keeps Tab and Shift+Tab inside a calendar popover, as a modal dialog
|
|
9
|
+
* does: from the last stop to the first, and back. Shared by DateField's
|
|
10
|
+
* calendar and DateRangeButton's popover.
|
|
11
|
+
*/
|
|
12
|
+
export function wrapTab(event) {
|
|
13
|
+
// One universal selector keeps document order in every DOM implementation.
|
|
14
|
+
const items = [
|
|
15
|
+
...event.currentTarget.querySelectorAll('*'),
|
|
16
|
+
].filter(isTabStop);
|
|
17
|
+
const first = items[0];
|
|
18
|
+
const last = items[items.length - 1];
|
|
19
|
+
if (!first || !last)
|
|
20
|
+
return;
|
|
21
|
+
if (event.shiftKey && document.activeElement === first) {
|
|
22
|
+
event.preventDefault();
|
|
23
|
+
last.focus();
|
|
24
|
+
}
|
|
25
|
+
else if (!event.shiftKey && document.activeElement === last) {
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
first.focus();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ChartTableRow } from '../../chart-table-rows.js';
|
|
2
|
+
export type ChartTableProps = {
|
|
3
|
+
caption: string;
|
|
4
|
+
/** The columns' headers, after the rows' own header column. */
|
|
5
|
+
columns: readonly string[];
|
|
6
|
+
rows: readonly ChartTableRow[];
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Every figure a chart draws, as a table kept for assistive technology and
|
|
10
|
+
* not drawn: it sits in a `sw-sr-only` box, because a table is never
|
|
11
|
+
* narrower than its contents and would widen the page. Its caption is the
|
|
12
|
+
* chart's name, with a header per column and per row, and the boxed
|
|
13
|
+
* period's row marked current. The drawing itself is hidden, so this is
|
|
14
|
+
* what a screen reader reads.
|
|
15
|
+
*/
|
|
16
|
+
export declare function ChartTable({ caption, columns, rows }: ChartTableProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Every figure a chart draws, as a table kept for assistive technology and
|
|
4
|
+
* not drawn: it sits in a `sw-sr-only` box, because a table is never
|
|
5
|
+
* narrower than its contents and would widen the page. Its caption is the
|
|
6
|
+
* chart's name, with a header per column and per row, and the boxed
|
|
7
|
+
* period's row marked current. The drawing itself is hidden, so this is
|
|
8
|
+
* what a screen reader reads.
|
|
9
|
+
*/
|
|
10
|
+
export function ChartTable({ caption, columns, rows }) {
|
|
11
|
+
return (_jsx("div", { className: "sw-sr-only", children: _jsxs("table", { children: [_jsx("caption", { children: caption }), columns.length > 0 ? (_jsx("thead", { children: _jsxs("tr", { children: [_jsx("td", {}), columns.map((column, index) => (_jsx("th", { scope: "col", children: column }, `${column}-${index}`)))] }) })) : null, _jsx("tbody", { children: rows.map((row) => (_jsxs("tr", { "aria-current": row.current ? 'true' : undefined, children: [_jsx("th", { scope: "row", children: row.header }), row.cells.map((cell, index) => (_jsx("td", { children: cell }, index)))] }, row.key))) })] }) }));
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ChartPlot, type ChartTick } from '../../chart-axis.js';
|
|
2
|
+
export type ChartValueAxisProps = {
|
|
3
|
+
plot: ChartPlot;
|
|
4
|
+
ticks: readonly ChartTick[];
|
|
5
|
+
/** The side its words sit on: the plot's start, or its end for a line's own scale. */
|
|
6
|
+
side: 'start' | 'end';
|
|
7
|
+
/** Draws the grid lines across the plot (the start axis does). */
|
|
8
|
+
grid?: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* A value axis inside a chart's SVG: a grid line at each tick across the
|
|
12
|
+
* plot, the zero line set apart, and each tick's words beside the plot.
|
|
13
|
+
*/
|
|
14
|
+
export declare function ChartValueAxis({ grid, plot, side, ticks, }: ChartValueAxisProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { chartGap } from '../../chart-metrics.js';
|
|
3
|
+
import { cx } from '../../class-names.js';
|
|
4
|
+
/**
|
|
5
|
+
* A value axis inside a chart's SVG: a grid line at each tick across the
|
|
6
|
+
* plot, the zero line set apart, and each tick's words beside the plot.
|
|
7
|
+
*/
|
|
8
|
+
export function ChartValueAxis({ grid = false, plot, side, ticks, }) {
|
|
9
|
+
const x = side === 'start' ? plot.left - chartGap : plot.right + chartGap;
|
|
10
|
+
return (_jsx("g", { children: ticks.map((tick) => (_jsxs("g", { children: [grid ? (_jsx("line", { className: tick.value === 0 ? 'sw-chart-zero' : 'sw-chart-grid', x1: plot.left, x2: plot.right, y1: tick.y, y2: tick.y })) : null, _jsx("text", { className: cx('sw-chart-tick', side === 'end' && 'sw-chart-tick-line'), dominantBaseline: "central", textAnchor: side === 'start' ? 'end' : 'start', x: x, y: tick.y, children: tick.label })] }, tick.value))) }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Follows the width a chart is given, so its drawing is laid out in its
|
|
4
|
+
* own pixels: on mount, before the first paint, and whenever its box
|
|
5
|
+
* changes size. On the server it reports `chartFallbackWidth`, and a browser with
|
|
6
|
+
* no ResizeObserver measures on window resizes instead.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useChartWidth(ref: RefObject<HTMLElement | null>): number;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useLayoutEffect, useState } from 'react';
|
|
3
|
+
import { chartFallbackWidth } from '../../chart-metrics.js';
|
|
4
|
+
/**
|
|
5
|
+
* Follows the width a chart is given, so its drawing is laid out in its
|
|
6
|
+
* own pixels: on mount, before the first paint, and whenever its box
|
|
7
|
+
* changes size. On the server it reports `chartFallbackWidth`, and a browser with
|
|
8
|
+
* no ResizeObserver measures on window resizes instead.
|
|
9
|
+
*/
|
|
10
|
+
export function useChartWidth(ref) {
|
|
11
|
+
const [width, setWidth] = useState(chartFallbackWidth);
|
|
12
|
+
// Before paint, so a phone never shows the wide layout first.
|
|
13
|
+
useLayoutEffect(() => {
|
|
14
|
+
const box = ref.current;
|
|
15
|
+
if (!box)
|
|
16
|
+
return;
|
|
17
|
+
function measure() {
|
|
18
|
+
if (!box)
|
|
19
|
+
return;
|
|
20
|
+
const next = Math.round(box.getBoundingClientRect().width);
|
|
21
|
+
if (next > 0)
|
|
22
|
+
setWidth(next);
|
|
23
|
+
}
|
|
24
|
+
measure();
|
|
25
|
+
if (typeof ResizeObserver === 'undefined') {
|
|
26
|
+
window.addEventListener('resize', measure);
|
|
27
|
+
return () => window.removeEventListener('resize', measure);
|
|
28
|
+
}
|
|
29
|
+
const observer = new ResizeObserver(measure);
|
|
30
|
+
observer.observe(box);
|
|
31
|
+
return () => observer.disconnect();
|
|
32
|
+
}, [ref]);
|
|
33
|
+
return width;
|
|
34
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CategoricalColor } from '@scalewing/tokens';
|
|
2
|
+
export type ChartCalloutListProps = {
|
|
3
|
+
callouts: readonly {
|
|
4
|
+
text: string;
|
|
5
|
+
tone?: CategoricalColor;
|
|
6
|
+
}[];
|
|
7
|
+
/** Shows the list under the plot; otherwise it is kept for assistive technology only. */
|
|
8
|
+
visible: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* A chart's callouts as a list of their words, each after a dot in its
|
|
12
|
+
* hue: shown under the plot on a compact chart, where they no longer fit
|
|
13
|
+
* above it, and otherwise kept for assistive technology (`sw-sr-only`)
|
|
14
|
+
* while the drawing pins them above their columns.
|
|
15
|
+
*/
|
|
16
|
+
export declare function ChartCalloutList({ callouts, visible }: ChartCalloutListProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cx } from '../../class-names.js';
|
|
3
|
+
/**
|
|
4
|
+
* A chart's callouts as a list of their words, each after a dot in its
|
|
5
|
+
* hue: shown under the plot on a compact chart, where they no longer fit
|
|
6
|
+
* above it, and otherwise kept for assistive technology (`sw-sr-only`)
|
|
7
|
+
* while the drawing pins them above their columns.
|
|
8
|
+
*/
|
|
9
|
+
export function ChartCalloutList({ callouts, visible }) {
|
|
10
|
+
if (callouts.length === 0)
|
|
11
|
+
return null;
|
|
12
|
+
return (_jsx("ul", { className: cx('sw-chart-callouts', !visible && 'sw-sr-only'), role: "list", children: callouts.map((callout, index) => (_jsxs("li", { className: cx('sw-chart-callout', callout.tone && `sw-chart-tone-${callout.tone}`), children: [_jsx("span", { "aria-hidden": "true", className: "sw-chart-callout-dot" }), callout.text] }, `${callout.text}-${index}`))) }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type CategoricalColor } from '@scalewing/tokens';
|
|
2
|
+
import { type ColumnChartLayout } from '../../column-chart-layout.js';
|
|
3
|
+
export type ColumnChartDrawingProps = {
|
|
4
|
+
layout: ColumnChartLayout;
|
|
5
|
+
/** Each series' hue, in series order. */
|
|
6
|
+
tones: readonly CategoricalColor[];
|
|
7
|
+
/** Each callout's hue, in callout order. */
|
|
8
|
+
calloutTones: readonly (CategoricalColor | undefined)[];
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* A column chart's picture, hidden from assistive technology (the table
|
|
12
|
+
* beside it carries every figure): the grid and value axes, the boxed
|
|
13
|
+
* period, the columns, the line and its last value, the category labels
|
|
14
|
+
* and the callouts with their leaders. It is laid out in its own pixels,
|
|
15
|
+
* left to right whatever the writing direction, as a time axis reads.
|
|
16
|
+
*/
|
|
17
|
+
export declare function ColumnChartDrawing({ calloutTones, layout, tones, }: ColumnChartDrawingProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { chartBoxRadius, chartColumnRadius, chartDotRadius, } from '../../chart-metrics.js';
|
|
3
|
+
import { cx } from '../../class-names.js';
|
|
4
|
+
import { ChartValueAxis } from '../chart/ChartValueAxis.js';
|
|
5
|
+
function toneClass(tone) {
|
|
6
|
+
return tone ? `sw-chart-tone-${tone}` : undefined;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A column chart's picture, hidden from assistive technology (the table
|
|
10
|
+
* beside it carries every figure): the grid and value axes, the boxed
|
|
11
|
+
* period, the columns, the line and its last value, the category labels
|
|
12
|
+
* and the callouts with their leaders. It is laid out in its own pixels,
|
|
13
|
+
* left to right whatever the writing direction, as a time axis reads.
|
|
14
|
+
*/
|
|
15
|
+
export function ColumnChartDrawing({ calloutTones, layout, tones, }) {
|
|
16
|
+
const { plot } = layout;
|
|
17
|
+
return (_jsxs("svg", { "aria-hidden": "true", className: "sw-chart-svg", direction: "ltr", focusable: "false", height: layout.height, viewBox: `0 0 ${layout.width} ${layout.height}`, width: layout.width, children: [_jsx(ChartValueAxis, { grid: true, plot: plot, side: "start", ticks: layout.ticks }), layout.highlight ? (_jsx("rect", { className: "sw-chart-highlight sw-chart-tone-accent", height: layout.highlight.height, rx: chartBoxRadius, width: layout.highlight.width, x: layout.highlight.x, y: layout.highlight.y })) : null, layout.columns.map((column) => (_jsx("rect", { className: cx('sw-chart-column', toneClass(tones[column.series])), height: column.height, rx: Math.min(chartColumnRadius, column.width / 2, column.height / 2), width: column.width, x: column.x, y: column.y }, `${column.series}-${column.category}`))), layout.line ? (_jsxs("g", { className: "sw-chart-tone-accent", children: [_jsx("polyline", { className: "sw-chart-line", points: layout.line.points.map((p) => `${p.x},${p.y}`).join(' ') }), _jsx(ChartValueAxis, { plot: plot, side: "end", ticks: layout.lineTicks }), layout.line.end || layout.line.points.length === 1 ? (_jsx("circle", { className: "sw-chart-dot", cx: layout.line.points.at(-1).x, cy: layout.line.points.at(-1).y, r: chartDotRadius })) : null, layout.line.end ? (_jsx("text", { className: "sw-chart-end-label", dominantBaseline: "central", x: layout.line.end.x, y: layout.line.end.y, children: layout.line.end.text })) : null] })) : null, layout.categoryLabels.map((label) => (_jsx("text", { className: "sw-chart-category", textAnchor: "middle", x: label.x, y: label.y, children: label.text }, label.index))), layout.callouts.map((callout) => (_jsxs("g", { className: toneClass(calloutTones[callout.order]), children: [_jsx("line", { className: "sw-chart-leader", x1: callout.x, x2: callout.x, y1: callout.leaderStart, y2: callout.leaderEnd }), _jsx("text", { className: "sw-chart-callout-text", textAnchor: callout.anchor, x: callout.textX, y: callout.textY, children: callout.text })] }, callout.order)))] }));
|
|
18
|
+
}
|