@scalewing/react 1.40.0 → 1.42.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 +38 -0
- package/README.md +274 -7
- package/dist/calendar-labels.d.ts +2 -0
- package/dist/calendar-labels.js +7 -0
- package/dist/components/Article.d.ts +60 -0
- package/dist/components/Article.js +42 -0
- package/dist/components/BarChart.d.ts +20 -4
- package/dist/components/BarChart.js +13 -6
- package/dist/components/ButtonGroup.d.ts +8 -1
- package/dist/components/ButtonGroup.js +11 -2
- package/dist/components/DateField.d.ts +14 -2
- package/dist/components/DateField.js +14 -11
- package/dist/components/DenominationGrid.d.ts +3 -2
- package/dist/components/DenominationGrid.js +21 -3
- package/dist/components/Dialog.d.ts +29 -13
- package/dist/components/Dialog.js +22 -20
- package/dist/components/DocumentViewer.d.ts +41 -0
- package/dist/components/DocumentViewer.js +72 -0
- package/dist/components/Field.d.ts +13 -2
- package/dist/components/Field.js +14 -38
- package/dist/components/FileField.d.ts +44 -0
- package/dist/components/FileField.js +66 -0
- package/dist/components/FilterChips.d.ts +7 -37
- package/dist/components/FilterChips.js +32 -24
- package/dist/components/ListRow.d.ts +33 -3
- package/dist/components/ListRow.js +18 -17
- package/dist/components/MarkdownView.d.ts +39 -0
- package/dist/components/MarkdownView.js +30 -0
- package/dist/components/NavCount.d.ts +15 -2
- package/dist/components/NavCount.js +16 -6
- package/dist/components/SegmentedControl.d.ts +17 -1
- package/dist/components/SegmentedControl.js +11 -3
- package/dist/components/Switch.d.ts +16 -1
- package/dist/components/Switch.js +17 -6
- package/dist/components/action-bar/ActionBarSummary.d.ts +10 -2
- package/dist/components/action-bar/ActionBarSummary.js +11 -2
- package/dist/components/chart/use-chart-width.js +2 -24
- package/dist/components/date-field/CalendarEntryButton.d.ts +24 -0
- package/dist/components/date-field/CalendarEntryButton.js +16 -0
- package/dist/components/date-field/TypedEntry.d.ts +26 -0
- package/dist/components/date-field/TypedEntry.js +13 -0
- package/dist/components/denomination-grid/CountCell.d.ts +16 -0
- package/dist/components/denomination-grid/CountCell.js +14 -0
- package/dist/components/denomination-grid/DenominationStrip.d.ts +4 -1
- package/dist/components/denomination-grid/DenominationStrip.js +2 -2
- package/dist/components/denomination-grid/EntryCell.d.ts +3 -1
- package/dist/components/denomination-grid/EntryCell.js +2 -2
- package/dist/components/denomination-grid/StripRow.js +1 -10
- package/dist/components/denomination-grid/TransposedStrip.d.ts +17 -0
- package/dist/components/denomination-grid/TransposedStrip.js +43 -0
- package/dist/components/denomination-grid/types.d.ts +31 -0
- package/dist/components/denomination-grid/types.js +7 -1
- package/dist/components/denomination-grid/validate-options.d.ts +7 -0
- package/dist/components/denomination-grid/validate-options.js +27 -0
- package/dist/components/dialog/DialogFooter.d.ts +6 -5
- package/dist/components/dialog/DialogFooter.js +6 -6
- package/dist/components/dialog/validate.d.ts +24 -0
- package/dist/components/dialog/validate.js +23 -0
- package/dist/components/document-viewer/document-viewer-labels.d.ts +23 -0
- package/dist/components/document-viewer/document-viewer-labels.js +23 -0
- package/dist/components/document-viewer/page-box.d.ts +8 -0
- package/dist/components/document-viewer/page-box.js +12 -0
- package/dist/components/document-viewer/pdf-document.d.ts +32 -0
- package/dist/components/document-viewer/pdf-document.js +66 -0
- package/dist/components/document-viewer/pdf-options.d.ts +36 -0
- package/dist/components/document-viewer/pdf-options.js +46 -0
- package/dist/components/document-viewer/render-pdf-page.d.ts +20 -0
- package/dist/components/document-viewer/render-pdf-page.js +38 -0
- package/dist/components/document-viewer/scroll-chain.d.ts +6 -0
- package/dist/components/document-viewer/scroll-chain.js +23 -0
- package/dist/components/document-viewer/use-error-report.d.ts +5 -0
- package/dist/components/document-viewer/use-error-report.js +13 -0
- package/dist/components/document-viewer/use-page-render.d.ts +21 -0
- package/dist/components/document-viewer/use-page-render.js +70 -0
- package/dist/components/document-viewer/use-pdf-document.d.ts +22 -0
- package/dist/components/document-viewer/use-pdf-document.js +47 -0
- package/dist/components/document-viewer/use-pinch-zoom.d.ts +12 -0
- package/dist/components/document-viewer/use-pinch-zoom.js +67 -0
- package/dist/components/document-viewer/use-zoom.d.ts +23 -0
- package/dist/components/document-viewer/use-zoom.js +70 -0
- package/dist/components/document-viewer/zoom.d.ts +29 -0
- package/dist/components/document-viewer/zoom.js +37 -0
- package/dist/components/field/field-checks.d.ts +34 -0
- package/dist/components/field/field-checks.js +42 -0
- package/dist/components/file-field/file-field-checks.d.ts +13 -0
- package/dist/components/file-field/file-field-checks.js +21 -0
- package/dist/components/file-field/use-file-drop.d.ts +34 -0
- package/dist/components/file-field/use-file-drop.js +78 -0
- package/dist/components/file-field/use-swap-focus.d.ts +15 -0
- package/dist/components/file-field/use-swap-focus.js +40 -0
- package/dist/components/filter-chips/FilterChip.d.ts +16 -0
- package/dist/components/filter-chips/FilterChip.js +20 -0
- package/dist/components/filter-chips/options.d.ts +75 -0
- package/dist/components/filter-chips/options.js +11 -0
- package/dist/components/filter-chips/validate.d.ts +9 -0
- package/dist/components/filter-chips/validate.js +48 -0
- package/dist/components/list/ListRowContent.d.ts +8 -2
- package/dist/components/list/ListRowContent.js +6 -3
- package/dist/components/list/ListRowItem.d.ts +10 -0
- package/dist/components/list/ListRowItem.js +17 -0
- package/dist/components/list/row-naming.d.ts +17 -0
- package/dist/components/list/row-naming.js +19 -0
- package/dist/components/list/row-slot.d.ts +8 -0
- package/dist/components/list/row-slot.js +12 -0
- package/dist/components/markdown/markdown-limits.d.ts +14 -0
- package/dist/components/markdown/markdown-limits.js +14 -0
- package/dist/components/markdown/markdown-model.d.ts +94 -0
- package/dist/components/markdown/markdown-model.js +8 -0
- package/dist/components/markdown/markdown-options.d.ts +18 -0
- package/dist/components/markdown/markdown-options.js +10 -0
- package/dist/components/markdown/markdown-rules.d.ts +28 -0
- package/dist/components/markdown/markdown-rules.js +81 -0
- package/dist/components/markdown/markdown-text.d.ts +17 -0
- package/dist/components/markdown/markdown-text.js +86 -0
- package/dist/components/markdown/parse-markdown.d.ts +4 -0
- package/dist/components/markdown/parse-markdown.js +21 -0
- package/dist/components/markdown/read-blocks.d.ts +8 -0
- package/dist/components/markdown/read-blocks.js +168 -0
- package/dist/components/markdown/read-inlines.d.ts +12 -0
- package/dist/components/markdown/read-inlines.js +126 -0
- package/dist/components/markdown/read-markdown.d.ts +9 -0
- package/dist/components/markdown/read-markdown.js +27 -0
- package/dist/components/markdown/reading-context.d.ts +18 -0
- package/dist/components/markdown/reading-context.js +35 -0
- package/dist/components/markdown/render-markdown.d.ts +10 -0
- package/dist/components/markdown/render-markdown.js +52 -0
- package/dist/components/use-element-width.d.ts +11 -0
- package/dist/components/use-element-width.js +38 -0
- package/dist/css/chart-tones.d.ts +2 -0
- package/dist/css/chart-tones.js +5 -1
- package/dist/css/css-article.d.ts +2 -0
- package/dist/css/css-article.js +110 -0
- package/dist/css/css-bar-chart.d.ts +17 -2
- package/dist/css/css-bar-chart.js +38 -7
- package/dist/css/css-button-group-attached.d.ts +3 -0
- package/dist/css/css-button-group-attached.js +18 -1
- package/dist/css/css-canvas-grouped.d.ts +17 -0
- package/dist/css/css-canvas-grouped.js +40 -0
- package/dist/css/css-components.js +18 -0
- package/dist/css/css-count-pill.js +14 -1
- package/dist/css/css-date-field-calendar-entry.d.ts +11 -0
- package/dist/css/css-date-field-calendar-entry.js +50 -0
- package/dist/css/css-date-field.js +4 -0
- package/dist/css/css-denomination-grid.js +4 -0
- package/dist/css/css-denomination-transposed.d.ts +4 -0
- package/dist/css/css-denomination-transposed.js +178 -0
- package/dist/css/css-dialog-canvas.d.ts +3 -0
- package/dist/css/css-dialog-canvas.js +20 -0
- package/dist/css/css-dialog-frame.js +19 -2
- package/dist/css/css-dialog-grabber.d.ts +4 -0
- package/dist/css/css-dialog-grabber.js +56 -0
- package/dist/css/css-dialog.js +3 -2
- package/dist/css/css-document-viewer.d.ts +2 -0
- package/dist/css/css-document-viewer.js +186 -0
- package/dist/css/css-document.js +3 -0
- package/dist/css/css-field-width.d.ts +12 -0
- package/dist/css/css-field-width.js +49 -0
- package/dist/css/css-field.js +4 -0
- package/dist/css/css-file-field.d.ts +2 -0
- package/dist/css/css-file-field.js +180 -0
- package/dist/css/css-filter-chips-layout.d.ts +2 -0
- package/dist/css/css-filter-chips-layout.js +42 -0
- package/dist/css/css-filter-chips.js +4 -0
- package/dist/css/css-list-row-trailing.d.ts +2 -0
- package/dist/css/css-list-row-trailing.js +91 -0
- package/dist/css/css-list-row.d.ts +6 -0
- package/dist/css/css-list-row.js +19 -3
- package/dist/css/css-list.js +5 -1
- package/dist/css/css-markdown.d.ts +2 -0
- package/dist/css/css-markdown.js +144 -0
- package/dist/css/css-segmented-sizing.d.ts +13 -0
- package/dist/css/css-segmented-sizing.js +66 -0
- package/dist/css/css-segmented.js +4 -0
- package/dist/css/css-switch.d.ts +6 -0
- package/dist/css/css-switch.js +39 -0
- package/dist/css/css-variables.js +1 -0
- package/dist/css/stacking.d.ts +1 -0
- package/dist/css/stacking.js +4 -1
- package/dist/css/stylesheet.js +12 -0
- package/dist/date-field-labels.d.ts +5 -0
- package/dist/date-field-labels.js +1 -0
- package/dist/document-viewer-worker.d.ts +9 -0
- package/dist/document-viewer-worker.js +9 -0
- package/dist/index.d.ts +15 -9
- package/dist/index.js +13 -7
- package/dist/list-options.d.ts +11 -7
- package/dist/list-options.js +20 -8
- package/dist/styles.css +889 -44
- package/dist/theme/ThemeProvider.d.ts +11 -1
- package/dist/theme/ThemeProvider.js +4 -2
- package/package.json +10 -2
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type CardVariant } from '@scalewing/tokens';
|
|
2
|
+
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
3
|
+
/** The photo across the top of an article. */
|
|
4
|
+
export type ArticleCover = {
|
|
5
|
+
src: string;
|
|
6
|
+
/** What the photo shows; `''` when it only decorates. */
|
|
7
|
+
alt: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const articleTitleElements: readonly ["h1", "h2", "h3"];
|
|
10
|
+
export type ArticleTitleElement = (typeof articleTitleElements)[number];
|
|
11
|
+
export type ArticleProps = Omit<HTMLAttributes<HTMLElement>, 'children' | 'title'> & {
|
|
12
|
+
/** The article's title, in heading type. */
|
|
13
|
+
title: string;
|
|
14
|
+
/**
|
|
15
|
+
* `h1` (the default) on the article's own page; `h2` or `h3` where it
|
|
16
|
+
* sits under another page's headings.
|
|
17
|
+
*/
|
|
18
|
+
titleAs?: ArticleTitleElement;
|
|
19
|
+
/** A short line over the title, such as "Store procedure · Services". */
|
|
20
|
+
eyebrow?: ReactNode;
|
|
21
|
+
/** A muted line under the title, such as "Manager 1 · Oct 16 · 4 min read". */
|
|
22
|
+
meta?: ReactNode;
|
|
23
|
+
/** A photo across the top, edge to edge; `null` is none. */
|
|
24
|
+
cover?: ArticleCover | null;
|
|
25
|
+
/** Controls at the end of the eyebrow's row, such as a language switch. */
|
|
26
|
+
actions?: ReactNode;
|
|
27
|
+
/** The card look, as `Card`'s. */
|
|
28
|
+
variant?: CardVariant;
|
|
29
|
+
/** The article's body, under a hairline. */
|
|
30
|
+
children?: ReactNode;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* A page that reads like a post, on a card at a reading width: an optional
|
|
34
|
+
* cover photo edge to edge across the top, then the eyebrow (with the
|
|
35
|
+
* consumer's actions at its row's end), the title in heading type, the
|
|
36
|
+
* muted meta line, a hairline, and the body. The article is named by its
|
|
37
|
+
* title (an `aria-labelledby` you pass replaces that). The ref is the
|
|
38
|
+
* `article` element.
|
|
39
|
+
*/
|
|
40
|
+
export declare const Article: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLElement>, "title" | "children"> & {
|
|
41
|
+
/** The article's title, in heading type. */
|
|
42
|
+
title: string;
|
|
43
|
+
/**
|
|
44
|
+
* `h1` (the default) on the article's own page; `h2` or `h3` where it
|
|
45
|
+
* sits under another page's headings.
|
|
46
|
+
*/
|
|
47
|
+
titleAs?: ArticleTitleElement;
|
|
48
|
+
/** A short line over the title, such as "Store procedure · Services". */
|
|
49
|
+
eyebrow?: ReactNode;
|
|
50
|
+
/** A muted line under the title, such as "Manager 1 · Oct 16 · 4 min read". */
|
|
51
|
+
meta?: ReactNode;
|
|
52
|
+
/** A photo across the top, edge to edge; `null` is none. */
|
|
53
|
+
cover?: ArticleCover | null;
|
|
54
|
+
/** Controls at the end of the eyebrow's row, such as a language switch. */
|
|
55
|
+
actions?: ReactNode;
|
|
56
|
+
/** The card look, as `Card`'s. */
|
|
57
|
+
variant?: CardVariant;
|
|
58
|
+
/** The article's body, under a hairline. */
|
|
59
|
+
children?: ReactNode;
|
|
60
|
+
} & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cardVariants } from '@scalewing/tokens';
|
|
3
|
+
import { forwardRef, useId } from 'react';
|
|
4
|
+
import { cx } from '../class-names.js';
|
|
5
|
+
import { Separator } from './Separator.js';
|
|
6
|
+
import { Text } from './Text.js';
|
|
7
|
+
export const articleTitleElements = ['h1', 'h2', 'h3'];
|
|
8
|
+
function hasContent(node) {
|
|
9
|
+
return (node !== undefined &&
|
|
10
|
+
node !== null &&
|
|
11
|
+
typeof node !== 'boolean' &&
|
|
12
|
+
node !== '');
|
|
13
|
+
}
|
|
14
|
+
function assertArticle({ title, titleAs, cover, variant }) {
|
|
15
|
+
if (typeof title !== 'string' || title.trim() === '')
|
|
16
|
+
throw new RangeError('Article title must be non-empty text');
|
|
17
|
+
if (titleAs !== undefined && !articleTitleElements.includes(titleAs))
|
|
18
|
+
throw new RangeError(`Unknown Article titleAs: ${String(titleAs)}`);
|
|
19
|
+
if (variant !== undefined && !cardVariants.includes(variant))
|
|
20
|
+
throw new RangeError(`Unknown Article variant: ${String(variant)}`);
|
|
21
|
+
if (cover !== undefined && cover !== null) {
|
|
22
|
+
if (typeof cover.src !== 'string' || cover.src.trim() === '')
|
|
23
|
+
throw new RangeError('Article cover src must be non-empty text');
|
|
24
|
+
if (typeof cover.alt !== 'string')
|
|
25
|
+
throw new RangeError("Article cover alt must be text ('' for a photo that only decorates)");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A page that reads like a post, on a card at a reading width: an optional
|
|
30
|
+
* cover photo edge to edge across the top, then the eyebrow (with the
|
|
31
|
+
* consumer's actions at its row's end), the title in heading type, the
|
|
32
|
+
* muted meta line, a hairline, and the body. The article is named by its
|
|
33
|
+
* title (an `aria-labelledby` you pass replaces that). The ref is the
|
|
34
|
+
* `article` element.
|
|
35
|
+
*/
|
|
36
|
+
export const Article = forwardRef(function Article(props, ref) {
|
|
37
|
+
assertArticle(props);
|
|
38
|
+
const { title, titleAs = 'h1', eyebrow, meta, cover, actions, variant = 'glass', children, className, ...rest } = props;
|
|
39
|
+
const titleId = useId();
|
|
40
|
+
const top = hasContent(eyebrow) || hasContent(actions);
|
|
41
|
+
return (_jsxs("article", { "aria-labelledby": titleId, className: cx('sw-card', `sw-card-${variant}`, 'sw-article', className), ref: ref, ...rest, children: [cover ? (_jsx("img", { alt: cover.alt, className: "sw-article-cover", src: cover.src })) : null, _jsxs("div", { className: "sw-article-body", children: [_jsxs("header", { className: "sw-article-header", children: [top ? (_jsxs("div", { className: "sw-article-top", children: [hasContent(eyebrow) ? (_jsx("div", { className: "sw-article-eyebrow", children: eyebrow })) : null, hasContent(actions) ? (_jsx("div", { className: "sw-article-actions", children: actions })) : null] })) : null, _jsx(Text, { as: titleAs, className: "sw-article-title", id: titleId, variant: "heading", children: title }), hasContent(meta) ? (_jsx("div", { className: "sw-article-meta", children: meta })) : null] }), _jsx(Separator, { decorative: true }), hasContent(children) ? (_jsx("div", { className: "sw-article-content", children: children })) : null] })] }));
|
|
42
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type HTMLAttributes } from 'react';
|
|
2
|
-
import { type BarChartTone, barChartTones } from '../css/css-bar-chart.js';
|
|
3
|
-
export type { BarChartTone };
|
|
4
|
-
export { barChartTones };
|
|
2
|
+
import { type BarChartAppearance, barChartAppearances, type BarChartTone, barChartTones } from '../css/css-bar-chart.js';
|
|
3
|
+
export type { BarChartAppearance, BarChartTone };
|
|
4
|
+
export { barChartAppearances, barChartTones };
|
|
5
5
|
export type BarChartItem = {
|
|
6
6
|
label: string;
|
|
7
7
|
value: number;
|
|
@@ -9,7 +9,9 @@ export type BarChartItem = {
|
|
|
9
9
|
/**
|
|
10
10
|
* Colors the bar by what it means, in place of its sign's default (the
|
|
11
11
|
* accent, or danger for a negative value): such as `'warning'` for an
|
|
12
|
-
* overage
|
|
12
|
+
* overage, `'danger'` for a shortage and `'neutral'` (the muted grey)
|
|
13
|
+
* for a bar that is counted but not the point, such as the usual days
|
|
14
|
+
* beside the busiest ones. The color is a cue beside the
|
|
13
15
|
* value and its label, never the only sign of the meaning. An unknown tone
|
|
14
16
|
* throws a `RangeError`.
|
|
15
17
|
*/
|
|
@@ -33,6 +35,13 @@ export type BarChartProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
|
|
|
33
35
|
* alone tells a negative value.
|
|
34
36
|
*/
|
|
35
37
|
diverging?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* `track` (the default) draws each bar in a track with the value axis
|
|
40
|
+
* under the bars. `bare` draws the bars alone, with no track and no
|
|
41
|
+
* axis, for bars whose values are all written beside them. An unknown
|
|
42
|
+
* appearance throws a `RangeError`.
|
|
43
|
+
*/
|
|
44
|
+
appearance?: BarChartAppearance;
|
|
36
45
|
};
|
|
37
46
|
export declare const BarChart: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
38
47
|
'aria-label': string;
|
|
@@ -52,4 +61,11 @@ export declare const BarChart: import("react").ForwardRefExoticComponent<Omit<HT
|
|
|
52
61
|
* alone tells a negative value.
|
|
53
62
|
*/
|
|
54
63
|
diverging?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* `track` (the default) draws each bar in a track with the value axis
|
|
66
|
+
* under the bars. `bare` draws the bars alone, with no track and no
|
|
67
|
+
* axis, for bars whose values are all written beside them. An unknown
|
|
68
|
+
* appearance throws a `RangeError`.
|
|
69
|
+
*/
|
|
70
|
+
appearance?: BarChartAppearance;
|
|
55
71
|
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -2,21 +2,28 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { barChartFillRatio, barChartScaleMax, formatBarChartValue, } from '@scalewing/tokens';
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { cx } from '../class-names.js';
|
|
5
|
-
import { barChartTones } from '../css/css-bar-chart.js';
|
|
6
|
-
export { barChartTones };
|
|
5
|
+
import { barChartAppearances, barChartTones, } from '../css/css-bar-chart.js';
|
|
6
|
+
export { barChartAppearances, barChartTones };
|
|
7
7
|
/** The fill's classes: the sign's (which also shapes a diverging bar) and the tone's. */
|
|
8
8
|
function barChartFillClassName(item) {
|
|
9
9
|
if (item.tone !== undefined && !barChartTones.includes(item.tone))
|
|
10
10
|
throw new RangeError(`BarChart item tone must be one of ${barChartTones.join(', ')}; received ${String(item.tone)}`);
|
|
11
11
|
return cx('sw-bar-chart-fill', item.value < 0 && 'sw-bar-chart-fill-negative', item.tone && `sw-bar-chart-fill-${item.tone}`);
|
|
12
12
|
}
|
|
13
|
-
export const BarChart = forwardRef(function BarChart({ 'aria-label': ariaLabel, className, diverging = false, formatValue = formatBarChartValue, items, max, style, ...rest }, ref) {
|
|
13
|
+
export const BarChart = forwardRef(function BarChart({ 'aria-label': ariaLabel, appearance = 'track', className, diverging = false, formatValue = formatBarChartValue, items, max, style, ...rest }, ref) {
|
|
14
|
+
if (!barChartAppearances.includes(appearance))
|
|
15
|
+
throw new RangeError(`Unknown BarChart appearance: ${String(appearance)}`);
|
|
14
16
|
const scaleMax = barChartScaleMax(items.map((item) => item.value), max);
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
+
const bare = appearance === 'bare';
|
|
18
|
+
const axis = bare
|
|
19
|
+
? []
|
|
20
|
+
: diverging
|
|
21
|
+
? [-scaleMax, 0, scaleMax]
|
|
22
|
+
: [0, scaleMax];
|
|
23
|
+
return (_jsxs("div", { ref: ref, className: cx('sw-bar-chart', diverging && 'sw-bar-chart-diverging', bare && 'sw-bar-chart-bare', className), style: style, ...rest, children: [_jsx("ul", { "aria-label": ariaLabel, className: "sw-bar-chart-plot", children: items.map((item, index) => {
|
|
17
24
|
const ratio = barChartFillRatio(item.value, scaleMax);
|
|
18
25
|
return (_jsxs("li", { className: "sw-bar-chart-row", children: [_jsx("span", { className: "sw-bar-chart-label", children: item.label }), _jsx("span", { className: "sw-bar-chart-track", children: _jsx("span", { className: barChartFillClassName(item), style: {
|
|
19
26
|
'--sw-bar-fill': ratio,
|
|
20
27
|
} }) }), _jsx("span", { className: "sw-bar-chart-value", children: item.valueLabel ?? formatValue(item.value) })] }, `${item.label}-${index}`));
|
|
21
|
-
}) }), _jsxs("div", { "aria-hidden": "true", className: "sw-bar-chart-axis", children: [_jsx("span", {}), _jsx("span", { className: "sw-bar-chart-axis-track", children: axis.map((value) => (_jsx("span", { children: formatValue(value) }, value))) }), _jsx("span", {})] })] }));
|
|
28
|
+
}) }), bare ? null : (_jsxs("div", { "aria-hidden": "true", className: "sw-bar-chart-axis", children: [_jsx("span", {}), _jsx("span", { className: "sw-bar-chart-axis-track", children: axis.map((value) => (_jsx("span", { children: formatValue(value) }, value))) }), _jsx("span", {})] }))] }));
|
|
22
29
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Breakpoint } from '../css/breakpoints.js';
|
|
1
2
|
import { type ButtonGroupAppearance, buttonGroupAppearances } from '../css/css-button-group-track.js';
|
|
2
3
|
import { type BoxProps } from './Box.js';
|
|
3
4
|
export type ButtonGroupJustify = 'start' | 'end' | 'between';
|
|
@@ -19,6 +20,12 @@ export type ButtonGroupProps = BoxProps & {
|
|
|
19
20
|
* variant; `default` keeps each button's own fill and outline.
|
|
20
21
|
*/
|
|
21
22
|
appearance?: ButtonGroupAppearance;
|
|
23
|
+
/**
|
|
24
|
+
* Below this breakpoint (an `attached` group only) the group fills its
|
|
25
|
+
* column and its buttons share the width equally, such as ‹, a period and
|
|
26
|
+
* › across a phone. From it up the group sizes to its buttons.
|
|
27
|
+
*/
|
|
28
|
+
fullWidthBelow?: Breakpoint;
|
|
22
29
|
};
|
|
23
30
|
/**
|
|
24
31
|
* The action row of a form or dialog: buttons on one line, wrapping when
|
|
@@ -27,4 +34,4 @@ export type ButtonGroupProps = BoxProps & {
|
|
|
27
34
|
* (put the primary action last, as the row already does). It is a `group`,
|
|
28
35
|
* so an `aria-label` names the row for assistive tech.
|
|
29
36
|
*/
|
|
30
|
-
export declare function ButtonGroup({ appearance, attached, className, justify, ...rest }: ButtonGroupProps): import("react").JSX.Element;
|
|
37
|
+
export declare function ButtonGroup({ appearance, attached, className, fullWidthBelow, justify, ...rest }: ButtonGroupProps): import("react").JSX.Element;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cx } from '../class-names.js';
|
|
3
|
+
import { breakpoints } from '../css/breakpoints.js';
|
|
4
|
+
import { buttonGroupFullWidthClass } from '../css/css-button-group-attached.js';
|
|
3
5
|
import { buttonGroupAppearances, buttonGroupTrackClass, } from '../css/css-button-group-track.js';
|
|
4
6
|
import { Box } from './Box.js';
|
|
5
7
|
export { buttonGroupAppearances };
|
|
@@ -10,10 +12,17 @@ export { buttonGroupAppearances };
|
|
|
10
12
|
* (put the primary action last, as the row already does). It is a `group`,
|
|
11
13
|
* so an `aria-label` names the row for assistive tech.
|
|
12
14
|
*/
|
|
13
|
-
export function ButtonGroup({ appearance = 'default', attached = false, className, justify = 'end', ...rest }) {
|
|
15
|
+
export function ButtonGroup({ appearance = 'default', attached = false, className, fullWidthBelow, justify = 'end', ...rest }) {
|
|
14
16
|
if (!buttonGroupAppearances.includes(appearance))
|
|
15
17
|
throw new RangeError(`Unknown ButtonGroup appearance: ${String(appearance)}`);
|
|
16
18
|
if (appearance === 'track' && !attached)
|
|
17
19
|
throw new RangeError('ButtonGroup appearance="track" needs attached');
|
|
18
|
-
|
|
20
|
+
if (fullWidthBelow !== undefined) {
|
|
21
|
+
if (!breakpoints.includes(fullWidthBelow))
|
|
22
|
+
throw new RangeError(`Unknown ButtonGroup fullWidthBelow: ${String(fullWidthBelow)}`);
|
|
23
|
+
// An unattached group already stacks full width below md.
|
|
24
|
+
if (!attached)
|
|
25
|
+
throw new RangeError('ButtonGroup fullWidthBelow needs attached');
|
|
26
|
+
}
|
|
27
|
+
return (_jsx(Box, { className: cx('sw-button-group', `sw-button-group-${justify}`, attached && 'sw-button-group-attached', appearance === 'track' && buttonGroupTrackClass, fullWidthBelow && buttonGroupFullWidthClass(fullWidthBelow), className), role: "group", ...rest }));
|
|
19
28
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type WeekStart } from '../calendar-month.js';
|
|
2
2
|
import { type DateFieldLabels } from '../date-field-labels.js';
|
|
3
|
+
import { type DateFieldEntry } from '../css/css-date-field-calendar-entry.js';
|
|
3
4
|
import { type RequiredMark } from './FieldLabelText.js';
|
|
4
|
-
export type { DateFieldLabels, WeekStart };
|
|
5
|
+
export type { DateFieldEntry, DateFieldLabels, WeekStart };
|
|
6
|
+
export { dateFieldEntries } from '../css/css-date-field-calendar-entry.js';
|
|
5
7
|
export type DateFieldProps = {
|
|
6
8
|
label: string;
|
|
7
9
|
/** Calendar date `YYYY-MM-DD`, or '' for no date. */
|
|
@@ -37,5 +39,15 @@ export type DateFieldProps = {
|
|
|
37
39
|
weekStartsOn?: WeekStart;
|
|
38
40
|
/** The control's own words; English by default. */
|
|
39
41
|
labels?: Partial<DateFieldLabels>;
|
|
42
|
+
/**
|
|
43
|
+
* `typed` (the default) is a text entry in the locale's order with a
|
|
44
|
+
* calendar button. `calendar` is one button showing the chosen day (or
|
|
45
|
+
* `labels.chooseDate`, such as "Choose a day", while empty) that opens
|
|
46
|
+
* the same calendar, for a form where a day is picked, never typed. It
|
|
47
|
+
* has no text to check, so validation and a required day stay with the
|
|
48
|
+
* consumer's `error`; while `required`, `labels.required` is said after
|
|
49
|
+
* its name.
|
|
50
|
+
*/
|
|
51
|
+
entry?: DateFieldEntry;
|
|
40
52
|
};
|
|
41
|
-
export declare function DateField({ label, value, onChange, min, max, today, disabled, required, requiredMark, description, error, locale, weekStartsOn, labels, }: DateFieldProps): import("react").JSX.Element;
|
|
53
|
+
export declare function DateField({ label, value, onChange, min, max, today, disabled, required, requiredMark, description, error, locale, weekStartsOn, labels, entry: entryKind, }: DateFieldProps): import("react").JSX.Element;
|
|
@@ -6,16 +6,19 @@ import { resolveDateFieldLabels, } from '../date-field-labels.js';
|
|
|
6
6
|
import { dateEntryPattern, dateEntryPlaceholder } from '../date-entry.js';
|
|
7
7
|
import { dateEntryValidity } from '../date-entry-validity.js';
|
|
8
8
|
import { assertDateBounds, isOutsideDateRange } from '../date-only.js';
|
|
9
|
+
import { assertDateFieldEntry, } from '../css/css-date-field-calendar-entry.js';
|
|
9
10
|
import { FieldErrorRegion } from './FieldErrorRegion.js';
|
|
10
11
|
import { assertRequiredMark, FieldLabelText, } from './FieldLabelText.js';
|
|
11
12
|
import { CalendarDialog } from './date-field/CalendarDialog.js';
|
|
12
|
-
import {
|
|
13
|
+
import { CalendarEntryButton } from './date-field/CalendarEntryButton.js';
|
|
14
|
+
import { TypedEntry } from './date-field/TypedEntry.js';
|
|
13
15
|
import { useCalendarPopup } from './date-field/use-calendar-popup.js';
|
|
14
16
|
import { useDateEntry } from './date-field/use-date-entry.js';
|
|
15
17
|
import { useLangLocale } from './date-field/use-lang-locale.js';
|
|
16
|
-
|
|
17
|
-
export function DateField({ label, value, onChange, min, max, today, disabled = false, required = false, requiredMark = 'visible', description, error, locale, weekStartsOn = 0, labels, }) {
|
|
18
|
+
export { dateFieldEntries } from '../css/css-date-field-calendar-entry.js';
|
|
19
|
+
export function DateField({ label, value, onChange, min, max, today, disabled = false, required = false, requiredMark = 'visible', description, error, locale, weekStartsOn = 0, labels, entry: entryKind = 'typed', }) {
|
|
18
20
|
assertRequiredMark(requiredMark);
|
|
21
|
+
assertDateFieldEntry(entryKind);
|
|
19
22
|
assertDateBounds(value, min, max);
|
|
20
23
|
assertWeekStart(weekStartsOn);
|
|
21
24
|
const words = resolveDateFieldLabels(labels);
|
|
@@ -45,7 +48,10 @@ export function DateField({ label, value, onChange, min, max, today, disabled =
|
|
|
45
48
|
const descriptionId = useId();
|
|
46
49
|
const entryErrorId = useId();
|
|
47
50
|
const errorId = useId();
|
|
51
|
+
const requiredId = useId();
|
|
52
|
+
const calendarEntry = entryKind === 'calendar';
|
|
48
53
|
const describedBy = [
|
|
54
|
+
calendarEntry && required ? requiredId : null,
|
|
49
55
|
description ? descriptionId : null,
|
|
50
56
|
entry.invalid ? entryErrorId : null,
|
|
51
57
|
error ? errorId : null,
|
|
@@ -53,12 +59,9 @@ export function DateField({ label, value, onChange, min, max, today, disabled =
|
|
|
53
59
|
.filter((id) => id !== null)
|
|
54
60
|
.join(' ');
|
|
55
61
|
const invalid = Boolean(error) || entry.invalid || isOutsideDateRange(value, min, max);
|
|
56
|
-
return (_jsxs("div", { className: "sw-date-field", ref: rootRef, children: [_jsx("label", { className: "sw-date-field-label", htmlFor: inputId, id: labelId, children: _jsx(FieldLabelText, { label: label, required: required, requiredMark: requiredMark }) }), _jsxs("div", { className: "sw-date-field-control", ref: controlRef, children: [_jsx(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
month: words.monthPlaceholder,
|
|
62
|
-
year: words.yearPlaceholder,
|
|
63
|
-
}), ref: inputRef, required: required, spellCheck: false, type: "text", value: entry.text }), _jsxs("button", { ...trigger, "aria-describedby": labelId, className: "sw-date-field-button", disabled: disabled, onClick: toggle, ref: buttonRef, tabIndex: tabStop, type: "button", children: [_jsx("span", { className: "sw-sr-only", children: words.chooseDate }), _jsx(DateFieldGlyph, { name: "calendar" })] })] }), description ? (_jsx("span", { className: "sw-date-field-description", id: descriptionId, children: description })) : null, _jsx(FieldErrorRegion, { className: "sw-date-field-error", id: entryErrorId, message: entry.invalid ? words.invalidEntry : undefined }), _jsx(FieldErrorRegion, { className: "sw-date-field-error", id: errorId, message: error }), shown ? (_jsx(CalendarDialog, { ...dialog, buttonRef: buttonRef, anchorRef: controlRef, labelId: labelId, labels: words, locale: resolvedLocale, max: max, min: min, required: required, value: value, weekStartsOn: weekStartsOn })) : null] }));
|
|
62
|
+
return (_jsxs("div", { className: "sw-date-field", ref: rootRef, children: [_jsx("label", { className: "sw-date-field-label", htmlFor: inputId, id: labelId, children: _jsx(FieldLabelText, { label: label, required: required, requiredMark: requiredMark }) }), calendarEntry ? (_jsxs("div", { className: "sw-date-field-control", ref: controlRef, children: [_jsx(CalendarEntryButton, { buttonRef: buttonRef, describedBy: describedBy || undefined, disabled: disabled, emptyText: words.chooseDate, id: inputId, invalid: invalid, labelId: labelId, locale: resolvedLocale, onPress: toggle, trigger: trigger, value: value }), required ? (_jsx("span", { hidden: true, id: requiredId, children: words.required })) : null] })) : (_jsx(TypedEntry, { buttonRef: buttonRef, controlRef: controlRef, describedBy: describedBy || undefined, disabled: disabled, entry: entry, id: inputId, inputRef: inputRef, invalid: invalid, labelId: labelId, onToggle: toggle, placeholder: dateEntryPlaceholder(pattern, {
|
|
63
|
+
day: words.dayPlaceholder,
|
|
64
|
+
month: words.monthPlaceholder,
|
|
65
|
+
year: words.yearPlaceholder,
|
|
66
|
+
}), required: required, toggleName: words.chooseDate, trigger: trigger })), description ? (_jsx("span", { className: "sw-date-field-description", id: descriptionId, children: description })) : null, _jsx(FieldErrorRegion, { className: "sw-date-field-error", id: entryErrorId, message: entry.invalid ? words.invalidEntry : undefined }), _jsx(FieldErrorRegion, { className: "sw-date-field-error", id: errorId, message: error }), shown ? (_jsx(CalendarDialog, { ...dialog, buttonRef: buttonRef, anchorRef: controlRef, labelId: labelId, labels: words, locale: resolvedLocale, max: max, min: min, required: required, value: value, weekStartsOn: weekStartsOn })) : null] }));
|
|
64
67
|
}
|
|
@@ -2,7 +2,8 @@ import { denominationGridFrames, denominationTotalEmphases } from '../css/css-de
|
|
|
2
2
|
import { denominationCellToneAppearances } from '../css/css-denomination-cell-tones.js';
|
|
3
3
|
import { denominationLabelAppearances } from '../css/css-denomination-label.js';
|
|
4
4
|
import { type DenominationGridProps } from './denomination-grid/types.js';
|
|
5
|
-
export type { DenominationCellToneAppearance, DenominationGridColumn, DenominationGridEntry, DenominationGridFrame, DenominationGridLayout, DenominationGridProps, DenominationGridRow, DenominationGridRowEmphasis, DenominationGridRowRole, DenominationGridTone, DenominationGridValueRow, DenominationLabelWidth, DenominationTotalEmphasis, } from './denomination-grid/types.js';
|
|
5
|
+
export type { DenominationCellToneAppearance, DenominationGridColumn, DenominationGridEntry, DenominationGridFrame, DenominationGridLayout, DenominationGridNegativeAppearance, DenominationGridProps, DenominationGridRow, DenominationGridRowEmphasis, DenominationGridRowRole, DenominationGridTone, DenominationGridValueRow, DenominationLabelWidth, DenominationTotalEmphasis, DenominationTransposeBreakpoint, } from './denomination-grid/types.js';
|
|
6
|
+
export { denominationNegativeAppearances, denominationTransposeBreakpoints, } from './denomination-grid/types.js';
|
|
6
7
|
export type { DenominationLabelAppearance } from '../css/css-denomination-label.js';
|
|
7
8
|
export { denominationCellToneAppearances, denominationGridFrames, denominationLabelAppearances, denominationTotalEmphases, };
|
|
8
|
-
export declare function DenominationGrid({ label, columns, rows, layout, subtotal, zeroLabel, totalLabel, rowRole, labelWidth, labelAppearance, frame, totalEmphasis, cellToneAppearance, }: DenominationGridProps): import("react").JSX.Element;
|
|
9
|
+
export declare function DenominationGrid({ label, columns, rows, layout, subtotal, zeroLabel, totalLabel, rowRole, labelWidth, labelAppearance, frame, totalEmphasis, cellToneAppearance, transposeBelow, countDigits, }: DenominationGridProps): import("react").JSX.Element;
|
|
@@ -1,25 +1,33 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
3
|
import { cx } from '../class-names.js';
|
|
4
|
+
import { breakpointQuery } from '../css/breakpoints.js';
|
|
5
|
+
import { denominationCountDigitsClass } from '../css/css-denomination-transposed.js';
|
|
3
6
|
import { denominationLabelWidths } from '../css/css-denomination-aligned.js';
|
|
4
7
|
import { denominationGridFrames, denominationTotalEmphases, denominationTotalsStrongClass, } from '../css/css-denomination-appearance.js';
|
|
5
8
|
import { denominationCellToneAppearances, denominationCellTonesPillClass, } from '../css/css-denomination-cell-tones.js';
|
|
6
9
|
import { denominationLabelAppearances, denominationLabelsPlainClass, } from '../css/css-denomination-label.js';
|
|
7
10
|
import { DenominationStrip } from './denomination-grid/DenominationStrip.js';
|
|
8
11
|
import { DenominationTiles } from './denomination-grid/DenominationTiles.js';
|
|
12
|
+
import { TransposedStrip } from './denomination-grid/TransposedStrip.js';
|
|
9
13
|
import { assertDenominationGrid } from './denomination-grid/validate.js';
|
|
14
|
+
import { assertDenominationOptions } from './denomination-grid/validate-options.js';
|
|
10
15
|
import { assertDenominationValueRows } from './denomination-grid/validate-value-row.js';
|
|
16
|
+
import { useMediaQuery } from './use-media-query.js';
|
|
11
17
|
import { assertDenominationEntries, assertDenominationExtras, } from './denomination-grid/validate-entry.js';
|
|
18
|
+
export { denominationNegativeAppearances, denominationTransposeBreakpoints, } from './denomination-grid/types.js';
|
|
12
19
|
export { denominationCellToneAppearances, denominationGridFrames, denominationLabelAppearances, denominationTotalEmphases, };
|
|
13
20
|
/** Fails closed on a value outside a closed set, naming the prop. */
|
|
14
21
|
function assertOneOf(values, value, prop) {
|
|
15
22
|
if (!values.includes(value))
|
|
16
23
|
throw new RangeError(`Unknown ${prop}: ${String(value)}`);
|
|
17
24
|
}
|
|
18
|
-
export function DenominationGrid({ label, columns, rows, layout = 'strip', subtotal, zeroLabel = '—', totalLabel, rowRole = 'region', labelWidth, labelAppearance = 'tone', frame = 'none', totalEmphasis = 'default', cellToneAppearance = 'text', }) {
|
|
25
|
+
export function DenominationGrid({ label, columns, rows, layout = 'strip', subtotal, zeroLabel = '—', totalLabel, rowRole = 'region', labelWidth, labelAppearance = 'tone', frame = 'none', totalEmphasis = 'default', cellToneAppearance = 'text', transposeBelow, countDigits, }) {
|
|
19
26
|
assertDenominationGrid(label, columns, rows);
|
|
20
27
|
assertDenominationExtras(layout, columns, rows);
|
|
21
28
|
assertDenominationEntries(layout, columns, rows);
|
|
22
29
|
assertDenominationValueRows(layout, columns, rows);
|
|
30
|
+
assertDenominationOptions(layout, rows, transposeBelow, countDigits);
|
|
23
31
|
if (typeof zeroLabel !== 'string')
|
|
24
32
|
throw new RangeError('zeroLabel must be a string');
|
|
25
33
|
if (totalLabel !== undefined && !totalLabel.trim())
|
|
@@ -32,8 +40,18 @@ export function DenominationGrid({ label, columns, rows, layout = 'strip', subto
|
|
|
32
40
|
assertOneOf(denominationGridFrames, frame, 'frame');
|
|
33
41
|
assertOneOf(denominationTotalEmphases, totalEmphasis, 'totalEmphasis');
|
|
34
42
|
assertOneOf(denominationCellToneAppearances, cellToneAppearance, 'cellToneAppearance');
|
|
35
|
-
const appearanceClass = cx(labelAppearance === 'plain' && denominationLabelsPlainClass, totalEmphasis === 'strong' && denominationTotalsStrongClass, cellToneAppearance === 'pill' && denominationCellTonesPillClass);
|
|
43
|
+
const appearanceClass = cx(labelAppearance === 'plain' && denominationLabelsPlainClass, totalEmphasis === 'strong' && denominationTotalsStrongClass, cellToneAppearance === 'pill' && denominationCellTonesPillClass, countDigits !== undefined && denominationCountDigitsClass);
|
|
44
|
+
const countStyle = countDigits === undefined
|
|
45
|
+
? undefined
|
|
46
|
+
: { '--sw-denomination-count-digits': countDigits };
|
|
47
|
+
// Read on every render (hooks run in order); without transposeBelow the
|
|
48
|
+
// query never matches.
|
|
49
|
+
const transposed = useMediaQuery(transposeBelow === undefined
|
|
50
|
+
? 'not all'
|
|
51
|
+
: breakpointQuery('below', transposeBelow), false);
|
|
36
52
|
if (layout === 'tiles')
|
|
37
53
|
return (_jsx(DenominationTiles, { className: appearanceClass || undefined, columns: columns, label: label, rowRole: rowRole, rows: rows, subtotal: subtotal, zeroLabel: zeroLabel }));
|
|
38
|
-
|
|
54
|
+
if (transposeBelow !== undefined && transposed)
|
|
55
|
+
return (_jsx(TransposedStrip, { className: appearanceClass || undefined, columns: columns, label: label, rows: rows, style: countStyle, totalLabel: totalLabel, zeroLabel: zeroLabel }));
|
|
56
|
+
return (_jsx(DenominationStrip, { className: appearanceClass || undefined, countStyle: countStyle, columns: columns, framed: frame === 'table', label: label, labelWidth: labelWidth, rows: rows, totalLabel: totalLabel, zeroLabel: zeroLabel }));
|
|
39
57
|
}
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { type DialogHTMLAttributes, type ReactNode } from 'react';
|
|
2
2
|
import { type Breakpoint } from '../css/breakpoints.js';
|
|
3
3
|
import { type DialogAppearance, dialogAppearances } from '../css/css-dialog-banded.js';
|
|
4
|
+
import { type ThemeCanvas } from '../css/css-canvas-grouped.js';
|
|
4
5
|
import { type ActionBarSummary } from './action-bar/ActionBarSummary.js';
|
|
6
|
+
import { type DialogRole, type DialogSize, dialogSizes } from './dialog/validate.js';
|
|
5
7
|
export { dialogAppearances, type DialogAppearance };
|
|
6
|
-
export
|
|
7
|
-
/**
|
|
8
|
-
* `md` is the reading width (32rem) for a message or a short form; `lg`
|
|
9
|
-
* (56rem) holds a row of six fields or a data grid without folding it;
|
|
10
|
-
* `xl` (65rem) holds a grid of six count columns with its labels and total.
|
|
11
|
-
*/
|
|
12
|
-
export type DialogSize = (typeof dialogSizes)[number];
|
|
13
|
-
/** `alertdialog` for a dialog that interrupts to warn, such as an idle sign-out. */
|
|
14
|
-
export type DialogRole = 'dialog' | 'alertdialog';
|
|
8
|
+
export { dialogSizes, type DialogRole, type DialogSize };
|
|
15
9
|
/**
|
|
16
10
|
* The heading level of the dialog's title. It changes only the element (and
|
|
17
11
|
* so the outline a screen reader reads), never the title's look.
|
|
@@ -44,11 +38,19 @@ export type DialogProps = Omit<DialogHTMLAttributes<HTMLDialogElement>, 'onClose
|
|
|
44
38
|
* bottom edge at the full viewport width, its top corners rounded and its
|
|
45
39
|
* bottom corners square, a strip of backdrop left in view above it, and
|
|
46
40
|
* its bottom padding clearing `env(safe-area-inset-bottom)`. It slides up
|
|
47
|
-
* on open unless reduced motion is asked for. There is no drag
|
|
48
|
-
*
|
|
49
|
-
*
|
|
41
|
+
* on open unless reduced motion is asked for. There is no drag: it
|
|
42
|
+
* closes as any dialog does. From the breakpoint up it is the centered
|
|
43
|
+
* dialog, at its `size`.
|
|
50
44
|
*/
|
|
51
45
|
sheetBelow?: Breakpoint;
|
|
46
|
+
/**
|
|
47
|
+
* Draws a grabber, a short rounded bar centered at the top edge, while
|
|
48
|
+
* the dialog is a bottom sheet (below `sheetBelow`, which it needs). It
|
|
49
|
+
* only marks the sheet as one: it is hidden from assistive technology
|
|
50
|
+
* and does not drag. It stays at the top while the content scrolls.
|
|
51
|
+
* From the breakpoint up it is not drawn.
|
|
52
|
+
*/
|
|
53
|
+
sheetGrabber?: boolean;
|
|
52
54
|
/**
|
|
53
55
|
* The accessible name of a close button, such as "Close". When given, an
|
|
54
56
|
* icon-only ghost button ends the title row and asks `onClose`, like
|
|
@@ -74,6 +76,13 @@ export type DialogProps = Omit<DialogHTMLAttributes<HTMLDialogElement>, 'onClose
|
|
|
74
76
|
* polite live region: "Drawer +$1,000.00 vault −$1,000.00".
|
|
75
77
|
*/
|
|
76
78
|
summary?: ActionBarSummary;
|
|
79
|
+
/**
|
|
80
|
+
* One short line in the footer, after the summary and before the
|
|
81
|
+
* actions, in the same polite live region: plain words (muted, caption
|
|
82
|
+
* size), or a `Badge` and a short line in one `span`. Nothing
|
|
83
|
+
* (`undefined`, `null`, `false`, or blank words) leaves it out.
|
|
84
|
+
*/
|
|
85
|
+
status?: ReactNode;
|
|
77
86
|
/** `alertdialog` for a warning that interrupts. Default `dialog`. */
|
|
78
87
|
role?: DialogRole;
|
|
79
88
|
/**
|
|
@@ -82,6 +91,13 @@ export type DialogProps = Omit<DialogHTMLAttributes<HTMLDialogElement>, 'onClose
|
|
|
82
91
|
* quiet round fill; `glass` (the default) is one frosted panel.
|
|
83
92
|
*/
|
|
84
93
|
appearance?: DialogAppearance;
|
|
94
|
+
/**
|
|
95
|
+
* The dialog's fill. `grouped` puts its content on the grouped canvas
|
|
96
|
+
* (the quieter grey `ThemeProvider canvas="grouped"` paints), solid with
|
|
97
|
+
* no blur, so `Card`s inside stand apart; a banded title row and the
|
|
98
|
+
* footer stay on the surface. `default` keeps the appearance's fill.
|
|
99
|
+
*/
|
|
100
|
+
canvas?: ThemeCanvas;
|
|
85
101
|
children: ReactNode;
|
|
86
102
|
};
|
|
87
|
-
export declare function Dialog({ 'aria-describedby': describedBy, appearance, children, className, closeLabel, description, footer, icon, role, summary, onCancel, onClose, onKeyDown, onPointerDown, onSubmit, open, sheetBelow, size, title, titleLevel, ...rest }: DialogProps): import("react").JSX.Element;
|
|
103
|
+
export declare function Dialog({ 'aria-describedby': describedBy, appearance, canvas, children, className, closeLabel, description, footer, icon, role, summary, onCancel, onClose, onKeyDown, onPointerDown, onSubmit, open, sheetBelow, sheetGrabber, size, status, title, titleLevel, ...rest }: DialogProps): import("react").JSX.Element;
|
|
@@ -4,33 +4,35 @@ import { useId } from 'react';
|
|
|
4
4
|
import { cx } from '../class-names.js';
|
|
5
5
|
import { dialogSheetClass } from '../css/css-dialog.js';
|
|
6
6
|
import { dialogAppearances, dialogBandedClass, } from '../css/css-dialog-banded.js';
|
|
7
|
+
import { dialogCanvasClass } from '../css/css-dialog-canvas.js';
|
|
8
|
+
import { dialogGrabberClass, dialogHasGrabberClass, } from '../css/css-dialog-grabber.js';
|
|
7
9
|
import { spacingClassNames } from '../spacing-classes.js';
|
|
8
10
|
import { useDialogCloseRequests } from './dialog-close-requests.js';
|
|
9
|
-
import { assertActionBarSummary, } from './action-bar/ActionBarSummary.js';
|
|
10
11
|
import { DialogFooter } from './dialog/DialogFooter.js';
|
|
11
12
|
import { DialogTitle } from './dialog/DialogTitle.js';
|
|
13
|
+
import { assertDialogProps, dialogSizes, } from './dialog/validate.js';
|
|
12
14
|
import { Stack } from './Stack.js';
|
|
13
15
|
export { dialogAppearances };
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (summary)
|
|
27
|
-
assertActionBarSummary(summary);
|
|
28
|
-
}
|
|
29
|
-
export function Dialog({ 'aria-describedby': describedBy, appearance = 'glass', children, className, closeLabel, description, footer, icon, role, summary, onCancel, onClose, onKeyDown, onPointerDown, onSubmit, open, sheetBelow, size = 'md', title, titleLevel = 3, ...rest }) {
|
|
30
|
-
assertDialogProps(size, role, description, summary, appearance);
|
|
16
|
+
export { dialogSizes };
|
|
17
|
+
export function Dialog({ 'aria-describedby': describedBy, appearance = 'glass', canvas = 'default', children, className, closeLabel, description, footer, icon, role, summary, onCancel, onClose, onKeyDown, onPointerDown, onSubmit, open, sheetBelow, sheetGrabber = false, size = 'md', status, title, titleLevel = 3, ...rest }) {
|
|
18
|
+
assertDialogProps({
|
|
19
|
+
appearance,
|
|
20
|
+
canvas,
|
|
21
|
+
description,
|
|
22
|
+
role,
|
|
23
|
+
sheetBelow,
|
|
24
|
+
sheetGrabber,
|
|
25
|
+
size,
|
|
26
|
+
summary,
|
|
27
|
+
});
|
|
31
28
|
const titleId = useId();
|
|
32
29
|
const descriptionId = useId();
|
|
33
|
-
|
|
30
|
+
// Nothing, or blank words, leaves the line out, as in ActionBar.
|
|
31
|
+
const hasStatus = status !== undefined &&
|
|
32
|
+
status !== null &&
|
|
33
|
+
status !== false &&
|
|
34
|
+
!(typeof status === 'string' && !status.trim());
|
|
35
|
+
const hasFooter = Boolean(footer) || Boolean(summary) || hasStatus;
|
|
34
36
|
const { nodeRef, handlers } = useDialogCloseRequests({
|
|
35
37
|
open,
|
|
36
38
|
onClose,
|
|
@@ -39,5 +41,5 @@ export function Dialog({ 'aria-describedby': describedBy, appearance = 'glass',
|
|
|
39
41
|
onPointerDown,
|
|
40
42
|
onSubmit,
|
|
41
43
|
});
|
|
42
|
-
return (
|
|
44
|
+
return (_jsxs("dialog", { ...rest, ref: nodeRef, "aria-describedby": describedBy ?? (description ? descriptionId : undefined), "aria-labelledby": titleId, className: cx('sw-dialog', size !== 'md' && `sw-dialog-${size}`, sheetBelow && dialogSheetClass(sheetBelow), appearance === 'banded' && dialogBandedClass, canvas === 'grouped' && dialogCanvasClass, sheetGrabber && dialogHasGrabberClass, ...spacingClassNames({ padding: 5 }), className), role: role === 'alertdialog' ? 'alertdialog' : undefined, ...handlers, children: [sheetGrabber ? (_jsx("span", { "aria-hidden": "true", className: dialogGrabberClass })) : null, _jsxs(Stack, { gap: 4, children: [_jsx(DialogTitle, { banded: appearance === 'banded', closeLabel: closeLabel, description: description, descriptionId: descriptionId, icon: icon, id: titleId, level: titleLevel === 2 ? 2 : 3, onClose: onClose, title: title }), children, hasFooter ? (_jsx(DialogFooter, { status: hasStatus ? status : undefined, summary: summary, children: footer })) : null] })] }));
|
|
43
45
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type DocumentViewerLabels } from './document-viewer/document-viewer-labels.js';
|
|
3
|
+
export type { DocumentViewerLabels };
|
|
4
|
+
export type DocumentViewerProps = {
|
|
5
|
+
/**
|
|
6
|
+
* The PDF's bytes, never a URL. The viewer draws from a copy. Other
|
|
7
|
+
* bytes (another object) open again at the first page, so keep this the
|
|
8
|
+
* same object between renders (state or a memo).
|
|
9
|
+
*/
|
|
10
|
+
data: ArrayBuffer | Uint8Array;
|
|
11
|
+
/**
|
|
12
|
+
* The URL of the bundled worker entry `@scalewing/react/document-viewer-worker`
|
|
13
|
+
* (Scalewing's PDF.js worker, always the viewer's version), such as Vite's
|
|
14
|
+
* `import workerSrc from '@scalewing/react/document-viewer-worker?worker&url'`.
|
|
15
|
+
*/
|
|
16
|
+
workerSrc: string;
|
|
17
|
+
/** Names the viewer, such as the document's title. */
|
|
18
|
+
label: string;
|
|
19
|
+
labels: DocumentViewerLabels;
|
|
20
|
+
/** The page shown, from 1; left out, the viewer keeps its own. */
|
|
21
|
+
page?: number;
|
|
22
|
+
/** Called with the page a step goes to. */
|
|
23
|
+
onPageChange?: (page: number) => void;
|
|
24
|
+
/** The failed state's actions, such as Try again and Download PDF. */
|
|
25
|
+
failedAction?: ReactNode;
|
|
26
|
+
/** Called once the PDF opens, with its page count. */
|
|
27
|
+
onLoad?: (info: {
|
|
28
|
+
pageCount: number;
|
|
29
|
+
}) => void;
|
|
30
|
+
/** Called when the PDF cannot be opened or a page cannot be drawn. */
|
|
31
|
+
onError?: (error: unknown) => void;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A PDF drawn one page at a time from its bytes with PDF.js, fitted to the
|
|
35
|
+
* width it is given, with previous and next steps and "Page n of m" in a
|
|
36
|
+
* polite live region. Two fingers, or `+`, `-` and `0` on the focused
|
|
37
|
+
* page, zoom it. The page's text sits over the drawing, transparent, so it
|
|
38
|
+
* can be read by assistive technology and selected. It opens nothing from
|
|
39
|
+
* the network beyond the worker, and has no download or print of its own.
|
|
40
|
+
*/
|
|
41
|
+
export declare function DocumentViewer({ data, workerSrc, label, labels, page: pageProp, onPageChange, failedAction, onLoad, onError, }: DocumentViewerProps): import("react").JSX.Element;
|