@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.
Files changed (191) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +274 -7
  3. package/dist/calendar-labels.d.ts +2 -0
  4. package/dist/calendar-labels.js +7 -0
  5. package/dist/components/Article.d.ts +60 -0
  6. package/dist/components/Article.js +42 -0
  7. package/dist/components/BarChart.d.ts +20 -4
  8. package/dist/components/BarChart.js +13 -6
  9. package/dist/components/ButtonGroup.d.ts +8 -1
  10. package/dist/components/ButtonGroup.js +11 -2
  11. package/dist/components/DateField.d.ts +14 -2
  12. package/dist/components/DateField.js +14 -11
  13. package/dist/components/DenominationGrid.d.ts +3 -2
  14. package/dist/components/DenominationGrid.js +21 -3
  15. package/dist/components/Dialog.d.ts +29 -13
  16. package/dist/components/Dialog.js +22 -20
  17. package/dist/components/DocumentViewer.d.ts +41 -0
  18. package/dist/components/DocumentViewer.js +72 -0
  19. package/dist/components/Field.d.ts +13 -2
  20. package/dist/components/Field.js +14 -38
  21. package/dist/components/FileField.d.ts +44 -0
  22. package/dist/components/FileField.js +66 -0
  23. package/dist/components/FilterChips.d.ts +7 -37
  24. package/dist/components/FilterChips.js +32 -24
  25. package/dist/components/ListRow.d.ts +33 -3
  26. package/dist/components/ListRow.js +18 -17
  27. package/dist/components/MarkdownView.d.ts +39 -0
  28. package/dist/components/MarkdownView.js +30 -0
  29. package/dist/components/NavCount.d.ts +15 -2
  30. package/dist/components/NavCount.js +16 -6
  31. package/dist/components/SegmentedControl.d.ts +17 -1
  32. package/dist/components/SegmentedControl.js +11 -3
  33. package/dist/components/Switch.d.ts +16 -1
  34. package/dist/components/Switch.js +17 -6
  35. package/dist/components/action-bar/ActionBarSummary.d.ts +10 -2
  36. package/dist/components/action-bar/ActionBarSummary.js +11 -2
  37. package/dist/components/chart/use-chart-width.js +2 -24
  38. package/dist/components/date-field/CalendarEntryButton.d.ts +24 -0
  39. package/dist/components/date-field/CalendarEntryButton.js +16 -0
  40. package/dist/components/date-field/TypedEntry.d.ts +26 -0
  41. package/dist/components/date-field/TypedEntry.js +13 -0
  42. package/dist/components/denomination-grid/CountCell.d.ts +16 -0
  43. package/dist/components/denomination-grid/CountCell.js +14 -0
  44. package/dist/components/denomination-grid/DenominationStrip.d.ts +4 -1
  45. package/dist/components/denomination-grid/DenominationStrip.js +2 -2
  46. package/dist/components/denomination-grid/EntryCell.d.ts +3 -1
  47. package/dist/components/denomination-grid/EntryCell.js +2 -2
  48. package/dist/components/denomination-grid/StripRow.js +1 -10
  49. package/dist/components/denomination-grid/TransposedStrip.d.ts +17 -0
  50. package/dist/components/denomination-grid/TransposedStrip.js +43 -0
  51. package/dist/components/denomination-grid/types.d.ts +31 -0
  52. package/dist/components/denomination-grid/types.js +7 -1
  53. package/dist/components/denomination-grid/validate-options.d.ts +7 -0
  54. package/dist/components/denomination-grid/validate-options.js +27 -0
  55. package/dist/components/dialog/DialogFooter.d.ts +6 -5
  56. package/dist/components/dialog/DialogFooter.js +6 -6
  57. package/dist/components/dialog/validate.d.ts +24 -0
  58. package/dist/components/dialog/validate.js +23 -0
  59. package/dist/components/document-viewer/document-viewer-labels.d.ts +23 -0
  60. package/dist/components/document-viewer/document-viewer-labels.js +23 -0
  61. package/dist/components/document-viewer/page-box.d.ts +8 -0
  62. package/dist/components/document-viewer/page-box.js +12 -0
  63. package/dist/components/document-viewer/pdf-document.d.ts +32 -0
  64. package/dist/components/document-viewer/pdf-document.js +66 -0
  65. package/dist/components/document-viewer/pdf-options.d.ts +36 -0
  66. package/dist/components/document-viewer/pdf-options.js +46 -0
  67. package/dist/components/document-viewer/render-pdf-page.d.ts +20 -0
  68. package/dist/components/document-viewer/render-pdf-page.js +38 -0
  69. package/dist/components/document-viewer/scroll-chain.d.ts +6 -0
  70. package/dist/components/document-viewer/scroll-chain.js +23 -0
  71. package/dist/components/document-viewer/use-error-report.d.ts +5 -0
  72. package/dist/components/document-viewer/use-error-report.js +13 -0
  73. package/dist/components/document-viewer/use-page-render.d.ts +21 -0
  74. package/dist/components/document-viewer/use-page-render.js +70 -0
  75. package/dist/components/document-viewer/use-pdf-document.d.ts +22 -0
  76. package/dist/components/document-viewer/use-pdf-document.js +47 -0
  77. package/dist/components/document-viewer/use-pinch-zoom.d.ts +12 -0
  78. package/dist/components/document-viewer/use-pinch-zoom.js +67 -0
  79. package/dist/components/document-viewer/use-zoom.d.ts +23 -0
  80. package/dist/components/document-viewer/use-zoom.js +70 -0
  81. package/dist/components/document-viewer/zoom.d.ts +29 -0
  82. package/dist/components/document-viewer/zoom.js +37 -0
  83. package/dist/components/field/field-checks.d.ts +34 -0
  84. package/dist/components/field/field-checks.js +42 -0
  85. package/dist/components/file-field/file-field-checks.d.ts +13 -0
  86. package/dist/components/file-field/file-field-checks.js +21 -0
  87. package/dist/components/file-field/use-file-drop.d.ts +34 -0
  88. package/dist/components/file-field/use-file-drop.js +78 -0
  89. package/dist/components/file-field/use-swap-focus.d.ts +15 -0
  90. package/dist/components/file-field/use-swap-focus.js +40 -0
  91. package/dist/components/filter-chips/FilterChip.d.ts +16 -0
  92. package/dist/components/filter-chips/FilterChip.js +20 -0
  93. package/dist/components/filter-chips/options.d.ts +75 -0
  94. package/dist/components/filter-chips/options.js +11 -0
  95. package/dist/components/filter-chips/validate.d.ts +9 -0
  96. package/dist/components/filter-chips/validate.js +48 -0
  97. package/dist/components/list/ListRowContent.d.ts +8 -2
  98. package/dist/components/list/ListRowContent.js +6 -3
  99. package/dist/components/list/ListRowItem.d.ts +10 -0
  100. package/dist/components/list/ListRowItem.js +17 -0
  101. package/dist/components/list/row-naming.d.ts +17 -0
  102. package/dist/components/list/row-naming.js +19 -0
  103. package/dist/components/list/row-slot.d.ts +8 -0
  104. package/dist/components/list/row-slot.js +12 -0
  105. package/dist/components/markdown/markdown-limits.d.ts +14 -0
  106. package/dist/components/markdown/markdown-limits.js +14 -0
  107. package/dist/components/markdown/markdown-model.d.ts +94 -0
  108. package/dist/components/markdown/markdown-model.js +8 -0
  109. package/dist/components/markdown/markdown-options.d.ts +18 -0
  110. package/dist/components/markdown/markdown-options.js +10 -0
  111. package/dist/components/markdown/markdown-rules.d.ts +28 -0
  112. package/dist/components/markdown/markdown-rules.js +81 -0
  113. package/dist/components/markdown/markdown-text.d.ts +17 -0
  114. package/dist/components/markdown/markdown-text.js +86 -0
  115. package/dist/components/markdown/parse-markdown.d.ts +4 -0
  116. package/dist/components/markdown/parse-markdown.js +21 -0
  117. package/dist/components/markdown/read-blocks.d.ts +8 -0
  118. package/dist/components/markdown/read-blocks.js +168 -0
  119. package/dist/components/markdown/read-inlines.d.ts +12 -0
  120. package/dist/components/markdown/read-inlines.js +126 -0
  121. package/dist/components/markdown/read-markdown.d.ts +9 -0
  122. package/dist/components/markdown/read-markdown.js +27 -0
  123. package/dist/components/markdown/reading-context.d.ts +18 -0
  124. package/dist/components/markdown/reading-context.js +35 -0
  125. package/dist/components/markdown/render-markdown.d.ts +10 -0
  126. package/dist/components/markdown/render-markdown.js +52 -0
  127. package/dist/components/use-element-width.d.ts +11 -0
  128. package/dist/components/use-element-width.js +38 -0
  129. package/dist/css/chart-tones.d.ts +2 -0
  130. package/dist/css/chart-tones.js +5 -1
  131. package/dist/css/css-article.d.ts +2 -0
  132. package/dist/css/css-article.js +110 -0
  133. package/dist/css/css-bar-chart.d.ts +17 -2
  134. package/dist/css/css-bar-chart.js +38 -7
  135. package/dist/css/css-button-group-attached.d.ts +3 -0
  136. package/dist/css/css-button-group-attached.js +18 -1
  137. package/dist/css/css-canvas-grouped.d.ts +17 -0
  138. package/dist/css/css-canvas-grouped.js +40 -0
  139. package/dist/css/css-components.js +18 -0
  140. package/dist/css/css-count-pill.js +14 -1
  141. package/dist/css/css-date-field-calendar-entry.d.ts +11 -0
  142. package/dist/css/css-date-field-calendar-entry.js +50 -0
  143. package/dist/css/css-date-field.js +4 -0
  144. package/dist/css/css-denomination-grid.js +4 -0
  145. package/dist/css/css-denomination-transposed.d.ts +4 -0
  146. package/dist/css/css-denomination-transposed.js +178 -0
  147. package/dist/css/css-dialog-canvas.d.ts +3 -0
  148. package/dist/css/css-dialog-canvas.js +20 -0
  149. package/dist/css/css-dialog-frame.js +19 -2
  150. package/dist/css/css-dialog-grabber.d.ts +4 -0
  151. package/dist/css/css-dialog-grabber.js +56 -0
  152. package/dist/css/css-dialog.js +3 -2
  153. package/dist/css/css-document-viewer.d.ts +2 -0
  154. package/dist/css/css-document-viewer.js +186 -0
  155. package/dist/css/css-document.js +3 -0
  156. package/dist/css/css-field-width.d.ts +12 -0
  157. package/dist/css/css-field-width.js +49 -0
  158. package/dist/css/css-field.js +4 -0
  159. package/dist/css/css-file-field.d.ts +2 -0
  160. package/dist/css/css-file-field.js +180 -0
  161. package/dist/css/css-filter-chips-layout.d.ts +2 -0
  162. package/dist/css/css-filter-chips-layout.js +42 -0
  163. package/dist/css/css-filter-chips.js +4 -0
  164. package/dist/css/css-list-row-trailing.d.ts +2 -0
  165. package/dist/css/css-list-row-trailing.js +91 -0
  166. package/dist/css/css-list-row.d.ts +6 -0
  167. package/dist/css/css-list-row.js +19 -3
  168. package/dist/css/css-list.js +5 -1
  169. package/dist/css/css-markdown.d.ts +2 -0
  170. package/dist/css/css-markdown.js +144 -0
  171. package/dist/css/css-segmented-sizing.d.ts +13 -0
  172. package/dist/css/css-segmented-sizing.js +66 -0
  173. package/dist/css/css-segmented.js +4 -0
  174. package/dist/css/css-switch.d.ts +6 -0
  175. package/dist/css/css-switch.js +39 -0
  176. package/dist/css/css-variables.js +1 -0
  177. package/dist/css/stacking.d.ts +1 -0
  178. package/dist/css/stacking.js +4 -1
  179. package/dist/css/stylesheet.js +12 -0
  180. package/dist/date-field-labels.d.ts +5 -0
  181. package/dist/date-field-labels.js +1 -0
  182. package/dist/document-viewer-worker.d.ts +9 -0
  183. package/dist/document-viewer-worker.js +9 -0
  184. package/dist/index.d.ts +15 -9
  185. package/dist/index.js +13 -7
  186. package/dist/list-options.d.ts +11 -7
  187. package/dist/list-options.js +20 -8
  188. package/dist/styles.css +889 -44
  189. package/dist/theme/ThemeProvider.d.ts +11 -1
  190. package/dist/theme/ThemeProvider.js +4 -2
  191. 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 and `'danger'` for a shortage. The color is a cue beside the
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 axis = diverging ? [-scaleMax, 0, scaleMax] : [0, scaleMax];
16
- return (_jsxs("div", { ref: ref, className: cx('sw-bar-chart', diverging && 'sw-bar-chart-diverging', className), style: style, ...rest, children: [_jsx("ul", { "aria-label": ariaLabel, className: "sw-bar-chart-plot", children: items.map((item, index) => {
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
- return (_jsx(Box, { className: cx('sw-button-group', `sw-button-group-${justify}`, attached && 'sw-button-group-attached', appearance === 'track' && buttonGroupTrackClass, className), role: "group", ...rest }));
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 { DateFieldGlyph } from './date-field/DateFieldGlyph.js';
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
- import { tabStop } from '../tab-stop.js';
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("input", { "aria-describedby": describedBy || undefined, "aria-invalid": invalid, autoComplete: "off", className: "sw-date-field-input", disabled: disabled, id: inputId, onBlur: entry.check, onChange: (event) => entry.change(event.currentTarget.value), onKeyDown: (event) => {
57
- if (event.key === 'Enter')
58
- entry.check();
59
- }, placeholder: dateEntryPlaceholder(pattern, {
60
- day: words.dayPlaceholder,
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
- return (_jsx(DenominationStrip, { className: appearanceClass || undefined, columns: columns, framed: frame === 'table', label: label, labelWidth: labelWidth, rows: rows, totalLabel: totalLabel, zeroLabel: zeroLabel }));
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 declare const dialogSizes: readonly ["md", "lg", "xl"];
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 grabber
48
- * (and no drag): it closes as any dialog does. From the breakpoint up it
49
- * is the centered dialog, at its `size`.
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 const dialogSizes = ['md', 'lg', 'xl'];
15
- const dialogRoles = ['dialog', 'alertdialog'];
16
- function assertDialogProps(size, role, description, summary, appearance) {
17
- if (!dialogSizes.includes(size))
18
- throw new RangeError(`Unknown Dialog size: ${String(size)}`);
19
- if (!dialogAppearances.includes(appearance))
20
- throw new RangeError(`Unknown Dialog appearance: ${String(appearance)}`);
21
- if (role !== undefined && !dialogRoles.includes(role))
22
- throw new RangeError(`Unknown Dialog role: ${String(role)}`);
23
- if (description !== undefined &&
24
- (typeof description !== 'string' || !description.trim()))
25
- throw new RangeError('Dialog description must not be empty');
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
- const hasFooter = Boolean(footer) || Boolean(summary);
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 (_jsx("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, ...spacingClassNames({ padding: 5 }), className), role: role === 'alertdialog' ? 'alertdialog' : undefined, ...handlers, children: _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, { summary: summary, children: footer })) : null] }) }));
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;