@scalewing/react 1.40.0 → 1.41.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 (105) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +154 -6
  3. package/dist/calendar-labels.d.ts +2 -0
  4. package/dist/calendar-labels.js +7 -0
  5. package/dist/components/BarChart.d.ts +20 -4
  6. package/dist/components/BarChart.js +13 -6
  7. package/dist/components/ButtonGroup.d.ts +8 -1
  8. package/dist/components/ButtonGroup.js +11 -2
  9. package/dist/components/DateField.d.ts +14 -2
  10. package/dist/components/DateField.js +14 -11
  11. package/dist/components/DenominationGrid.d.ts +3 -2
  12. package/dist/components/DenominationGrid.js +21 -3
  13. package/dist/components/Dialog.d.ts +29 -13
  14. package/dist/components/Dialog.js +22 -20
  15. package/dist/components/Field.d.ts +13 -2
  16. package/dist/components/Field.js +14 -38
  17. package/dist/components/FilterChips.d.ts +7 -37
  18. package/dist/components/FilterChips.js +32 -24
  19. package/dist/components/ListRow.d.ts +11 -2
  20. package/dist/components/ListRow.js +3 -2
  21. package/dist/components/SegmentedControl.d.ts +17 -1
  22. package/dist/components/SegmentedControl.js +11 -3
  23. package/dist/components/Switch.d.ts +16 -1
  24. package/dist/components/Switch.js +17 -6
  25. package/dist/components/action-bar/ActionBarSummary.d.ts +10 -2
  26. package/dist/components/action-bar/ActionBarSummary.js +11 -2
  27. package/dist/components/date-field/CalendarEntryButton.d.ts +24 -0
  28. package/dist/components/date-field/CalendarEntryButton.js +16 -0
  29. package/dist/components/date-field/TypedEntry.d.ts +26 -0
  30. package/dist/components/date-field/TypedEntry.js +13 -0
  31. package/dist/components/denomination-grid/CountCell.d.ts +16 -0
  32. package/dist/components/denomination-grid/CountCell.js +14 -0
  33. package/dist/components/denomination-grid/DenominationStrip.d.ts +4 -1
  34. package/dist/components/denomination-grid/DenominationStrip.js +2 -2
  35. package/dist/components/denomination-grid/EntryCell.d.ts +3 -1
  36. package/dist/components/denomination-grid/EntryCell.js +2 -2
  37. package/dist/components/denomination-grid/StripRow.js +1 -10
  38. package/dist/components/denomination-grid/TransposedStrip.d.ts +17 -0
  39. package/dist/components/denomination-grid/TransposedStrip.js +43 -0
  40. package/dist/components/denomination-grid/types.d.ts +31 -0
  41. package/dist/components/denomination-grid/types.js +7 -1
  42. package/dist/components/denomination-grid/validate-options.d.ts +7 -0
  43. package/dist/components/denomination-grid/validate-options.js +27 -0
  44. package/dist/components/dialog/DialogFooter.d.ts +6 -5
  45. package/dist/components/dialog/DialogFooter.js +6 -6
  46. package/dist/components/dialog/validate.d.ts +24 -0
  47. package/dist/components/dialog/validate.js +23 -0
  48. package/dist/components/field/field-checks.d.ts +34 -0
  49. package/dist/components/field/field-checks.js +42 -0
  50. package/dist/components/filter-chips/FilterChip.d.ts +16 -0
  51. package/dist/components/filter-chips/FilterChip.js +20 -0
  52. package/dist/components/filter-chips/options.d.ts +75 -0
  53. package/dist/components/filter-chips/options.js +11 -0
  54. package/dist/components/filter-chips/validate.d.ts +9 -0
  55. package/dist/components/filter-chips/validate.js +48 -0
  56. package/dist/components/list/ListRowContent.d.ts +3 -1
  57. package/dist/components/list/ListRowContent.js +3 -2
  58. package/dist/css/chart-tones.d.ts +2 -0
  59. package/dist/css/chart-tones.js +5 -1
  60. package/dist/css/css-bar-chart.d.ts +17 -2
  61. package/dist/css/css-bar-chart.js +38 -7
  62. package/dist/css/css-button-group-attached.d.ts +3 -0
  63. package/dist/css/css-button-group-attached.js +18 -1
  64. package/dist/css/css-canvas-grouped.d.ts +17 -0
  65. package/dist/css/css-canvas-grouped.js +40 -0
  66. package/dist/css/css-components.js +6 -0
  67. package/dist/css/css-date-field-calendar-entry.d.ts +11 -0
  68. package/dist/css/css-date-field-calendar-entry.js +50 -0
  69. package/dist/css/css-date-field.js +4 -0
  70. package/dist/css/css-denomination-grid.js +4 -0
  71. package/dist/css/css-denomination-transposed.d.ts +4 -0
  72. package/dist/css/css-denomination-transposed.js +178 -0
  73. package/dist/css/css-dialog-canvas.d.ts +3 -0
  74. package/dist/css/css-dialog-canvas.js +20 -0
  75. package/dist/css/css-dialog-frame.js +19 -2
  76. package/dist/css/css-dialog-grabber.d.ts +4 -0
  77. package/dist/css/css-dialog-grabber.js +56 -0
  78. package/dist/css/css-dialog.js +3 -2
  79. package/dist/css/css-document.js +3 -0
  80. package/dist/css/css-field-width.d.ts +12 -0
  81. package/dist/css/css-field-width.js +49 -0
  82. package/dist/css/css-field.js +4 -0
  83. package/dist/css/css-filter-chips-layout.d.ts +2 -0
  84. package/dist/css/css-filter-chips-layout.js +42 -0
  85. package/dist/css/css-filter-chips.js +4 -0
  86. package/dist/css/css-list-row.d.ts +6 -0
  87. package/dist/css/css-list-row.js +19 -3
  88. package/dist/css/css-segmented-sizing.d.ts +13 -0
  89. package/dist/css/css-segmented-sizing.js +66 -0
  90. package/dist/css/css-segmented.js +4 -0
  91. package/dist/css/css-switch.d.ts +6 -0
  92. package/dist/css/css-switch.js +39 -0
  93. package/dist/css/stacking.d.ts +1 -0
  94. package/dist/css/stacking.js +4 -1
  95. package/dist/css/stylesheet.js +4 -0
  96. package/dist/date-field-labels.d.ts +5 -0
  97. package/dist/date-field-labels.js +1 -0
  98. package/dist/index.d.ts +10 -8
  99. package/dist/index.js +8 -6
  100. package/dist/list-options.d.ts +8 -7
  101. package/dist/list-options.js +15 -8
  102. package/dist/styles.css +343 -2
  103. package/dist/theme/ThemeProvider.d.ts +11 -1
  104. package/dist/theme/ThemeProvider.js +4 -2
  105. package/package.json +1 -1
@@ -2,11 +2,19 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { forwardRef, useId } from 'react';
4
4
  import { cx } from '../class-names.js';
5
+ import { breakpoints } from '../css/breakpoints.js';
5
6
  import { segmentedRaisedClass } from '../css/css-segmented-raised.js';
7
+ import { segmentedFullWidthClass, segmentedSizes, segmentedSmClass, } from '../css/css-segmented-sizing.js';
6
8
  import { FieldErrorRegion } from './FieldErrorRegion.js';
7
9
  import { tabStop } from '../tab-stop.js';
8
- export const SegmentedControl = forwardRef(function SegmentedControl({ disabled = false, error, items, onChange, required = false, value, variant = 'compact', ...labelProps }, ref) {
10
+ export { segmentedSizes };
11
+ export const SegmentedControl = forwardRef(function SegmentedControl({ disabled = false, error, fullWidthBelow, items, onChange, required = false, size = 'md', value, variant = 'compact', ...labelProps }, ref) {
9
12
  const errorId = useId();
13
+ if (fullWidthBelow !== undefined &&
14
+ !breakpoints.includes(fullWidthBelow))
15
+ throw new RangeError(`Unknown SegmentedControl fullWidthBelow: ${String(fullWidthBelow)}`);
16
+ if (!segmentedSizes.includes(size))
17
+ throw new RangeError(`Unknown SegmentedControl size: ${String(size)}`);
10
18
  const withIcons = items.some((item) => item.icon);
11
19
  function onKeyDown(event) {
12
20
  if (disabled || (event.key !== 'ArrowRight' && event.key !== 'ArrowLeft')) {
@@ -25,7 +33,7 @@ export const SegmentedControl = forwardRef(function SegmentedControl({ disabled
25
33
  }
26
34
  // The wrapper is always rendered, so an error that appears later swaps
27
35
  // text into a live region that already exists and the group keeps focus.
28
- return (_jsxs("div", { className: cx('sw-segmented-field', variant === 'filled' && 'sw-segmented-field-filled'), children: [_jsx("div", { ref: ref, "aria-describedby": error ? errorId : undefined, "aria-disabled": disabled || undefined, "aria-invalid": error ? true : undefined, "aria-required": required || undefined, className: cx('sw-segmented', variant === 'filled' && 'sw-segmented-filled', variant === 'raised' && segmentedRaisedClass, withIcons && 'sw-segmented-with-icons', disabled && 'sw-segmented-disabled'), onKeyDown: onKeyDown, role: "radiogroup", ...labelProps, children: items.map((item) => {
36
+ return (_jsxs("div", { className: cx('sw-segmented-field', variant === 'filled' && 'sw-segmented-field-filled', fullWidthBelow && segmentedFullWidthClass(fullWidthBelow)), children: [_jsx("div", { ref: ref, "aria-describedby": error ? errorId : undefined, "aria-disabled": disabled || undefined, "aria-invalid": error ? true : undefined, "aria-required": required || undefined, className: cx('sw-segmented', variant === 'filled' && 'sw-segmented-filled', variant === 'raised' && segmentedRaisedClass, withIcons && 'sw-segmented-with-icons', disabled && 'sw-segmented-disabled', size === 'sm' && segmentedSmClass), onKeyDown: onKeyDown, role: "radiogroup", ...labelProps, children: items.map((item) => {
29
37
  const selected = item.id === value;
30
38
  return (_jsxs("button", { "aria-checked": selected, className: cx('sw-segmented-item', selected && 'sw-segmented-item-selected'), disabled: disabled, onClick: () => {
31
39
  if (!selected) {
@@ -34,6 +42,6 @@ export const SegmentedControl = forwardRef(function SegmentedControl({ disabled
34
42
  }, role: "radio",
35
43
  // Every item stays a tab stop, as each already was outside
36
44
  // Safari: the arrow keys change the value, not the focus.
37
- tabIndex: tabStop, type: "button", children: [item.icon ? (_jsx("span", { "aria-hidden": "true", className: "sw-segmented-item-icon", children: item.icon })) : null, item.label] }, item.id));
45
+ tabIndex: tabStop, type: "button", children: [item.icon ? (_jsx("span", { "aria-hidden": "true", className: "sw-segmented-item-icon", children: item.icon })) : null, size === 'sm' ? (_jsx("span", { className: "sw-segmented-item-label", children: item.label })) : (item.label)] }, item.id));
38
46
  }) }), _jsx(FieldErrorRegion, { className: "sw-field-error", id: errorId, message: error })] }));
39
47
  });
@@ -1,8 +1,23 @@
1
+ import { type SwitchCheckedTone, switchCheckedTones, type SwitchLayout, switchLayouts } from '../css/css-switch.js';
2
+ export { switchCheckedTones, switchLayouts, type SwitchCheckedTone, type SwitchLayout, };
1
3
  export type SwitchProps = {
2
4
  label: string;
3
5
  checked: boolean;
4
6
  onCheckedChange: (checked: boolean) => void;
5
7
  disabled?: boolean;
6
8
  description?: string;
9
+ /**
10
+ * `leading` (the default) puts the control before its label;
11
+ * `trailing` puts the label and description first and the control at
12
+ * the row's end, the row as wide as its column, as a settings list
13
+ * draws it.
14
+ */
15
+ layout?: SwitchLayout;
16
+ /**
17
+ * The track's colour while on: `accent` (the default) or `success`, for
18
+ * a switch whose on state is the healthy one, such as a feature turned
19
+ * on. The thumb's place says the state either way.
20
+ */
21
+ checkedTone?: SwitchCheckedTone;
7
22
  };
8
- export declare function Switch({ label, checked, onCheckedChange, disabled, description, }: SwitchProps): import("react").JSX.Element;
23
+ export declare function Switch({ label, checked, onCheckedChange, disabled, description, layout, checkedTone, }: SwitchProps): import("react").JSX.Element;
@@ -1,12 +1,23 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useId } from 'react';
4
+ import { cx } from '../class-names.js';
5
+ import { switchCheckedTones, switchLayouts, } from '../css/css-switch.js';
4
6
  import { tabStop } from '../tab-stop.js';
5
- export function Switch({ label, checked, onCheckedChange, disabled = false, description, }) {
7
+ export { switchCheckedTones, switchLayouts, };
8
+ function assertOneOf(values, value, prop) {
9
+ if (!values.includes(value))
10
+ throw new RangeError(`Unknown Switch ${prop}: ${String(value)}`);
11
+ }
12
+ export function Switch({ label, checked, onCheckedChange, disabled = false, description, layout = 'leading', checkedTone = 'accent', }) {
13
+ assertOneOf(switchLayouts, layout, 'layout');
14
+ assertOneOf(switchCheckedTones, checkedTone, 'checkedTone');
6
15
  const labelId = useId();
7
16
  const descriptionId = useId();
8
- return (_jsxs("label", { className: "sw-switch", children: [_jsxs("span", { className: "sw-switch-control", children: [_jsx("input", { "aria-checked": checked, "aria-describedby": description ? descriptionId : undefined, "aria-labelledby": labelId, checked: checked, className: "sw-switch-input", disabled: disabled, onChange: (event) => {
9
- if (!disabled)
10
- onCheckedChange(event.currentTarget.checked);
11
- }, role: "switch", tabIndex: tabStop, type: "checkbox" }), _jsx("span", { "aria-hidden": "true", className: "sw-switch-track", children: _jsx("span", { className: "sw-switch-thumb" }) })] }), _jsxs("span", { className: "sw-switch-copy", children: [_jsx("span", { className: "sw-switch-label", id: labelId, children: label }), description ? (_jsx("span", { className: "sw-switch-description", id: descriptionId, children: description })) : null] })] }));
17
+ const control = (_jsxs("span", { className: "sw-switch-control", children: [_jsx("input", { "aria-checked": checked, "aria-describedby": description ? descriptionId : undefined, "aria-labelledby": labelId, checked: checked, className: "sw-switch-input", disabled: disabled, onChange: (event) => {
18
+ if (!disabled)
19
+ onCheckedChange(event.currentTarget.checked);
20
+ }, role: "switch", tabIndex: tabStop, type: "checkbox" }), _jsx("span", { "aria-hidden": "true", className: "sw-switch-track", children: _jsx("span", { className: "sw-switch-thumb" }) })] }));
21
+ const copy = (_jsxs("span", { className: "sw-switch-copy", children: [_jsx("span", { className: "sw-switch-label", id: labelId, children: label }), description ? (_jsx("span", { className: "sw-switch-description", id: descriptionId, children: description })) : null] }));
22
+ return (_jsx("label", { className: cx('sw-switch', layout === 'trailing' && 'sw-switch-trailing', checkedTone === 'success' && 'sw-switch-success'), children: layout === 'trailing' ? (_jsxs(_Fragment, { children: [copy, control] })) : (_jsxs(_Fragment, { children: [control, copy] })) }));
12
23
  }
@@ -5,18 +5,26 @@ export type ActionBarSummaryTone = (typeof actionBarSummaryTones)[number];
5
5
  export type ActionBarSummary = {
6
6
  /** What the figure is, such as "Counted". */
7
7
  label: string;
8
- /** The figure, formatted by the consumer, such as "$33,790.00". */
8
+ /**
9
+ * The figure, formatted by the consumer, such as "$33,790.00". An empty
10
+ * string (or only spaces) means there is no figure yet, such as before
11
+ * anything is counted: the summary line is left out and the live region
12
+ * stays, so the first figure is announced when it arrives.
13
+ */
9
14
  value: string;
10
15
  /** A short line after the figure, such as "short $4,000.00". */
11
16
  detail?: string;
12
17
  /** Colors the value only; the words say why. Defaults to `default`. */
13
18
  tone?: ActionBarSummaryTone;
14
19
  };
20
+ /** Whether the summary has a figure to show; an empty value has none yet. */
21
+ export declare function hasActionBarSummaryFigure(summary: ActionBarSummary): boolean;
15
22
  export declare function assertActionBarSummary(summary: ActionBarSummary): void;
16
23
  /**
17
24
  * The bar's figure: its label, the value in the heading variant at tabular
18
25
  * figures, and its detail, on one baseline, wrapping as one phrase.
26
+ * Nothing while the value is empty.
19
27
  */
20
28
  export declare function ActionBarSummaryLine({ summary, }: {
21
29
  summary: ActionBarSummary;
22
- }): import("react").JSX.Element;
30
+ }): import("react").JSX.Element | null;
@@ -4,9 +4,15 @@ export const actionBarSummaryTones = ['default', 'danger', 'success'];
4
4
  function isBlank(text) {
5
5
  return typeof text !== 'string' || !text.trim();
6
6
  }
7
+ /** Whether the summary has a figure to show; an empty value has none yet. */
8
+ export function hasActionBarSummaryFigure(summary) {
9
+ return !isBlank(summary.value);
10
+ }
7
11
  export function assertActionBarSummary(summary) {
8
- if (isBlank(summary.label) || isBlank(summary.value))
9
- throw new RangeError('ActionBar summary needs a label and a value');
12
+ if (isBlank(summary.label))
13
+ throw new RangeError('ActionBar summary needs a label');
14
+ if (typeof summary.value !== 'string')
15
+ throw new RangeError('ActionBar summary value must be a string');
10
16
  if (summary.detail !== undefined && isBlank(summary.detail))
11
17
  throw new RangeError('ActionBar summary detail must not be empty');
12
18
  if (summary.tone !== undefined &&
@@ -16,8 +22,11 @@ export function assertActionBarSummary(summary) {
16
22
  /**
17
23
  * The bar's figure: its label, the value in the heading variant at tabular
18
24
  * figures, and its detail, on one baseline, wrapping as one phrase.
25
+ * Nothing while the value is empty.
19
26
  */
20
27
  export function ActionBarSummaryLine({ summary, }) {
28
+ if (!hasActionBarSummaryFigure(summary))
29
+ return null;
21
30
  const tone = summary.tone ?? 'default';
22
31
  return (_jsxs("span", { className: cx('sw-action-bar-summary', tone !== 'default' && `sw-action-bar-summary-${tone}`), children: [_jsx("span", { className: "sw-action-bar-summary-label", children: summary.label }), ' ', _jsx("span", { className: "sw-action-bar-summary-value sw-text-heading sw-tabular", children: summary.value }), summary.detail ? (_jsxs(_Fragment, { children: [' ', _jsx("span", { className: "sw-action-bar-summary-detail", children: summary.detail })] })) : null] }));
23
32
  }
@@ -0,0 +1,24 @@
1
+ import { type Ref } from 'react';
2
+ import { type CalendarPopup } from './use-calendar-popup.js';
3
+ export type CalendarEntryButtonProps = {
4
+ id: string;
5
+ /** The field's label element, which names the button with its words. */
6
+ labelId: string;
7
+ describedBy: string | undefined;
8
+ value: string;
9
+ locale: string;
10
+ /** What an empty field shows, such as "Choose a day". */
11
+ emptyText: string;
12
+ disabled: boolean;
13
+ invalid: boolean;
14
+ buttonRef: Ref<HTMLButtonElement>;
15
+ trigger: CalendarPopup['trigger'];
16
+ onPress: () => void;
17
+ };
18
+ /**
19
+ * DateField's calendar entry: a neutral Button showing the calendar glyph
20
+ * and the chosen day, or the words that ask for one, that opens the
21
+ * calendar. It is named by the field's label and its own words ("Hire date
22
+ * Choose a day", "Hire date Oct 6, 2026") and described as the field is.
23
+ */
24
+ export declare function CalendarEntryButton({ id, labelId, describedBy, value, locale, emptyText, disabled, invalid, buttonRef, trigger, onPress, }: CalendarEntryButtonProps): import("react").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useId } from 'react';
3
+ import { formatDateMedium } from '../../calendar-labels.js';
4
+ import { cx } from '../../class-names.js';
5
+ import { Button } from '../Button.js';
6
+ import { DateFieldGlyph } from './DateFieldGlyph.js';
7
+ /**
8
+ * DateField's calendar entry: a neutral Button showing the calendar glyph
9
+ * and the chosen day, or the words that ask for one, that opens the
10
+ * calendar. It is named by the field's label and its own words ("Hire date
11
+ * Choose a day", "Hire date Oct 6, 2026") and described as the field is.
12
+ */
13
+ export function CalendarEntryButton({ id, labelId, describedBy, value, locale, emptyText, disabled, invalid, buttonRef, trigger, onPress, }) {
14
+ const textId = useId();
15
+ return (_jsxs(Button, { ...trigger, "aria-describedby": describedBy, "aria-labelledby": `${labelId} ${textId}`, className: cx('sw-date-field-calendar-entry', invalid && 'sw-date-field-calendar-entry-invalid'), disabled: disabled, id: id, onPress: onPress, ref: buttonRef, variant: "neutral", children: [_jsx(DateFieldGlyph, { name: "calendar" }), _jsx("span", { className: "sw-date-field-calendar-entry-text", id: textId, children: value ? formatDateMedium(value, locale) : emptyText })] }));
16
+ }
@@ -0,0 +1,26 @@
1
+ import { type Ref } from 'react';
2
+ import { type CalendarPopup } from './use-calendar-popup.js';
3
+ import { type DateEntry } from './use-date-entry.js';
4
+ export type TypedEntryProps = {
5
+ id: string;
6
+ /** The field's label element, which describes the calendar button. */
7
+ labelId: string;
8
+ describedBy: string | undefined;
9
+ entry: DateEntry;
10
+ placeholder: string;
11
+ /** The calendar button's name, `labels.chooseDate`. */
12
+ toggleName: string;
13
+ disabled: boolean;
14
+ required: boolean;
15
+ invalid: boolean;
16
+ controlRef: Ref<HTMLDivElement>;
17
+ inputRef: Ref<HTMLInputElement>;
18
+ buttonRef: Ref<HTMLButtonElement>;
19
+ trigger: CalendarPopup['trigger'];
20
+ onToggle: () => void;
21
+ };
22
+ /**
23
+ * DateField's typed entry: the text input in the locale's order, checked
24
+ * on blur and Enter, and the calendar button inside its end.
25
+ */
26
+ export declare function TypedEntry({ id, labelId, describedBy, entry, placeholder, toggleName, disabled, required, invalid, controlRef, inputRef, buttonRef, trigger, onToggle, }: TypedEntryProps): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { tabStop } from '../../tab-stop.js';
3
+ import { DateFieldGlyph } from './DateFieldGlyph.js';
4
+ /**
5
+ * DateField's typed entry: the text input in the locale's order, checked
6
+ * on blur and Enter, and the calendar button inside its end.
7
+ */
8
+ export function TypedEntry({ id, labelId, describedBy, entry, placeholder, toggleName, disabled, required, invalid, controlRef, inputRef, buttonRef, trigger, onToggle, }) {
9
+ return (_jsxs("div", { className: "sw-date-field-control", ref: controlRef, children: [_jsx("input", { "aria-describedby": describedBy, "aria-invalid": invalid, autoComplete: "off", className: "sw-date-field-input", disabled: disabled, id: id, onBlur: entry.check, onChange: (event) => entry.change(event.currentTarget.value), onKeyDown: (event) => {
10
+ if (event.key === 'Enter')
11
+ entry.check();
12
+ }, placeholder: placeholder, 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: onToggle, ref: buttonRef, tabIndex: tabStop, type: "button", children: [_jsx("span", { className: "sw-sr-only", children: toggleName }), _jsx(DateFieldGlyph, { name: "calendar" })] })] }));
13
+ }
@@ -0,0 +1,16 @@
1
+ import { type DenominationGridRow } from './types.js';
2
+ type CountCellProps = {
3
+ row: DenominationGridRow;
4
+ index: number;
5
+ zeroLabel: string;
6
+ /** More classes for the cell, such as the transposed layout's row look. */
7
+ className?: string;
8
+ };
9
+ /**
10
+ * One count, read-only: the zero label, a signed delta, and the cell's tone.
11
+ * A signed row's positive count is success; a negative count is danger
12
+ * unless its row's `negativeAppearance` is `plain`. The value has its own
13
+ * box, which the `pill` tone appearance fills.
14
+ */
15
+ export declare function CountCell({ row, index, zeroLabel, className, }: CountCellProps): import("react").JSX.Element;
16
+ export {};
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cx } from '../../class-names.js';
3
+ import { denominationCellToneClassNames } from '../../css/css-denomination-cell-tones.js';
4
+ import { denominationCellView } from '../../denomination-cells.js';
5
+ /**
6
+ * One count, read-only: the zero label, a signed delta, and the cell's tone.
7
+ * A signed row's positive count is success; a negative count is danger
8
+ * unless its row's `negativeAppearance` is `plain`. The value has its own
9
+ * box, which the `pill` tone appearance fills.
10
+ */
11
+ export function CountCell({ row, index, zeroLabel, className, }) {
12
+ const view = denominationCellView(row.cells[index] ?? null, row.signed ?? false, zeroLabel);
13
+ return (_jsx("td", { className: cx('sw-denomination-cell', `sw-denomination-cell-${view.state}`, row.signed && 'sw-denomination-cell-signed', row.negativeAppearance === 'plain' && 'sw-denomination-cell-plain', ...denominationCellToneClassNames(row.cellTones?.[index]), className), children: _jsx("span", { className: "sw-denomination-cell-value", children: view.text }) }));
14
+ }
@@ -1,9 +1,12 @@
1
+ import { type CSSProperties } from 'react';
1
2
  import { type DenominationGridProps } from './types.js';
2
3
  type StripProps = Required<Pick<DenominationGridProps, 'label' | 'columns' | 'rows' | 'zeroLabel'>> & Pick<DenominationGridProps, 'totalLabel' | 'labelWidth'> & {
3
4
  /** The grid's appearance classes (labels, totals, cell tones), if any. */
4
5
  className?: string;
5
6
  /** The `table` frame: a hairline around the region and a heading-row fill. */
6
7
  framed: boolean;
8
+ /** The entry counts' room (`countDigits`), if set. */
9
+ countStyle?: CSSProperties;
7
10
  };
8
- export declare function DenominationStrip({ className, framed, label, columns, rows, zeroLabel, totalLabel, labelWidth, }: StripProps): import("react").JSX.Element;
11
+ export declare function DenominationStrip({ className, countStyle, framed, label, columns, rows, zeroLabel, totalLabel, labelWidth, }: StripProps): import("react").JSX.Element;
9
12
  export {};
@@ -18,7 +18,7 @@ function TotalHead({ totalLabel }) {
18
18
  return _jsx("td", { className: "sw-denomination-corner sw-denomination-total-head" });
19
19
  return (_jsx("th", { className: "sw-denomination-head sw-denomination-total-head", scope: "col", children: _jsx("span", { className: "sw-denomination-total-label", children: totalLabel }) }));
20
20
  }
21
- export function DenominationStrip({ className, framed, label, columns, rows, zeroLabel, totalLabel, labelWidth, }) {
21
+ export function DenominationStrip({ className, countStyle, framed, label, columns, rows, zeroLabel, totalLabel, labelWidth, }) {
22
22
  const idPrefix = useId();
23
23
  const hasTotals = rows.some((row) => row.total !== undefined);
24
24
  // An aligned strip sizes its columns from the region's width; it needs
@@ -29,5 +29,5 @@ export function DenominationStrip({ className, framed, label, columns, rows, zer
29
29
  '--sw-denomination-columns': columns.length,
30
30
  '--sw-denomination-total': hasTotals ? 1 : 0,
31
31
  };
32
- return (_jsx(ScrollRegion, { "aria-label": label, className: cx('sw-denomination-scroll', aligned && 'sw-denomination-scroll-aligned', framed && denominationScrollFramedClass), children: _jsxs("table", { className: cx('sw-denomination-grid sw-denomination-strip', labelWidth && 'sw-denomination-strip-aligned', rows.some((row) => row.entry) && 'sw-denomination-strip-entry', labelWidth && denominationLabelWidthClass(labelWidth), framed && denominationFramedClass, className), style: aligned, children: [_jsx("caption", { className: "sw-sr-only", children: label }), _jsx("thead", { children: _jsxs("tr", { children: [_jsx("td", { className: "sw-denomination-corner" }), columns.map((column) => (_jsx("th", { className: "sw-denomination-head", scope: "col", children: _jsx(ColumnHeadText, { column: column }) }, column.key))), hasTotals ? _jsx(TotalHead, { totalLabel: totalLabel }) : null] }) }), _jsx("tbody", { children: rows.map((row, rowIndex) => (_jsx(StripRow, { columns: columns, hasTotals: hasTotals, idPrefix: idPrefix, row: row, rowIndex: rowIndex, zeroLabel: zeroLabel }, row.id))) })] }) }));
32
+ return (_jsx(ScrollRegion, { "aria-label": label, className: cx('sw-denomination-scroll', aligned && 'sw-denomination-scroll-aligned', framed && denominationScrollFramedClass), children: _jsxs("table", { className: cx('sw-denomination-grid sw-denomination-strip', labelWidth && 'sw-denomination-strip-aligned', rows.some((row) => row.entry) && 'sw-denomination-strip-entry', labelWidth && denominationLabelWidthClass(labelWidth), framed && denominationFramedClass, className), style: aligned || countStyle ? { ...aligned, ...countStyle } : undefined, children: [_jsx("caption", { className: "sw-sr-only", children: label }), _jsx("thead", { children: _jsxs("tr", { children: [_jsx("td", { className: "sw-denomination-corner" }), columns.map((column) => (_jsx("th", { className: "sw-denomination-head", scope: "col", children: _jsx(ColumnHeadText, { column: column }) }, column.key))), hasTotals ? _jsx(TotalHead, { totalLabel: totalLabel }) : null] }) }), _jsx("tbody", { children: rows.map((row, rowIndex) => (_jsx(StripRow, { columns: columns, hasTotals: hasTotals, idPrefix: idPrefix, row: row, rowIndex: rowIndex, zeroLabel: zeroLabel }, row.id))) })] }) }));
33
33
  }
@@ -6,6 +6,8 @@ type EntryCellProps = {
6
6
  index: number;
7
7
  /** The value cell under this count, which describes it, if any. */
8
8
  describedBy?: string;
9
+ /** More classes for the cell, such as the transposed layout's row look. */
10
+ className?: string;
9
11
  };
10
12
  /**
11
13
  * One editable count of a strip row: a full-width `Stepper` named by the
@@ -13,5 +15,5 @@ type EntryCellProps = {
13
15
  * message from the entry, and the cell's tone on its border (an accent one
14
16
  * is the Stepper's changed look).
15
17
  */
16
- export declare function EntryCell({ row, entry, column, index, describedBy, }: EntryCellProps): import("react").JSX.Element;
18
+ export declare function EntryCell({ row, entry, column, index, describedBy, className, }: EntryCellProps): import("react").JSX.Element;
17
19
  export {};
@@ -9,8 +9,8 @@ import { columnName } from './ColumnHeadText.js';
9
9
  * message from the entry, and the cell's tone on its border (an accent one
10
10
  * is the Stepper's changed look).
11
11
  */
12
- export function EntryCell({ row, entry, column, index, describedBy, }) {
12
+ export function EntryCell({ row, entry, column, index, describedBy, className, }) {
13
13
  const max = entry.max?.[index] ?? undefined;
14
14
  const tone = row.cellTones?.[index];
15
- return (_jsx("td", { className: cx('sw-denomination-entry', ...denominationCellToneClassNames(tone)), children: _jsx(Stepper, { "aria-describedby": describedBy, changed: tone === 'accent', decrementLabel: entry.decrementLabel, disabled: row.disabled, error: entry.errors?.[index] ?? undefined, incrementLabel: entry.incrementLabel, label: `${row.label} ${columnName(column)}`, labelVisuallyHidden: true, limitAppearance: entry.limitAppearance, max: max, onChange: (value) => entry.onChange(column.key, value), placeholder: entry.placeholder, value: row.cells[index] ?? null, width: "full" }) }));
15
+ return (_jsx("td", { className: cx('sw-denomination-entry', ...denominationCellToneClassNames(tone), className), children: _jsx(Stepper, { "aria-describedby": describedBy, changed: tone === 'accent', decrementLabel: entry.decrementLabel, disabled: row.disabled, error: entry.errors?.[index] ?? undefined, incrementLabel: entry.incrementLabel, label: `${row.label} ${columnName(column)}`, labelVisuallyHidden: true, limitAppearance: entry.limitAppearance, max: max, onChange: (value) => entry.onChange(column.key, value), placeholder: entry.placeholder, value: row.cells[index] ?? null, width: "full" }) }));
16
16
  }
@@ -1,19 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { cx } from '../../class-names.js';
3
- import { denominationCellToneClassNames } from '../../css/css-denomination-cell-tones.js';
4
- import { denominationCellView } from '../../denomination-cells.js';
3
+ import { CountCell } from './CountCell.js';
5
4
  import { EntryCell } from './EntryCell.js';
6
5
  import { RowLabelLine } from './RowLabelLine.js';
7
6
  import { StripTotalCell, StripTotalInline } from './StripTotal.js';
8
7
  import { hasValue, StripValueRow, valueCellId } from './StripValueRow.js';
9
- /**
10
- * One count, read-only: the zero label, a signed delta, and the cell's tone.
11
- * The value has its own box, which the `pill` tone appearance fills.
12
- */
13
- function CountCell({ row, index, zeroLabel, }) {
14
- const view = denominationCellView(row.cells[index] ?? null, row.signed ?? false, zeroLabel);
15
- return (_jsx("td", { className: cx('sw-denomination-cell', `sw-denomination-cell-${view.state}`, ...denominationCellToneClassNames(row.cellTones?.[index])), children: _jsx("span", { className: "sw-denomination-cell-value", children: view.text }) }));
16
- }
17
8
  /**
18
9
  * One strip row: its pinned label (with the phone total under it), a count
19
10
  * per column, read-only or entered, and its total. With a `valueRow`, the
@@ -0,0 +1,17 @@
1
+ import { type CSSProperties } from 'react';
2
+ import { type DenominationGridProps } from './types.js';
3
+ type TransposedProps = Required<Pick<DenominationGridProps, 'label' | 'columns' | 'rows' | 'zeroLabel'>> & Pick<DenominationGridProps, 'totalLabel'> & {
4
+ /** The grid's appearance classes (cell tones), if any. */
5
+ className?: string;
6
+ /** The entry counts' room, as the strip's. */
7
+ style?: CSSProperties;
8
+ };
9
+ /**
10
+ * A strip drawn for a phone: a row per denomination (its label and
11
+ * caption), a column per grid row (its counts, read-only or entered, then
12
+ * its value line's values), and the totals in a last row named by
13
+ * `totalLabel`. Names, entry, tones and the zero label are the strip's;
14
+ * the denomination column stays in view while the columns scroll under it.
15
+ */
16
+ export declare function TransposedStrip({ className, style, label, columns, rows, zeroLabel, totalLabel, }: TransposedProps): import("react").JSX.Element;
17
+ export {};
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment, useId } from 'react';
3
+ import { cx } from '../../class-names.js';
4
+ import { ScrollRegion } from '../ScrollRegion.js';
5
+ import { ColumnHeadText } from './ColumnHeadText.js';
6
+ import { CountCell } from './CountCell.js';
7
+ import { EntryCell } from './EntryCell.js';
8
+ import { RowLabelLine } from './RowLabelLine.js';
9
+ import { hasValue, valueCellId } from './StripValueRow.js';
10
+ /** The look a grid row lends each of its cells in a column. */
11
+ function columnClass(row) {
12
+ return (cx(row.emphasis === 'quiet' && 'sw-denomination-transposed-quiet', row.disabled && 'sw-denomination-transposed-disabled') || undefined);
13
+ }
14
+ /**
15
+ * A grid row's heads: its label (glyph, words, caption), then its value
16
+ * line's. A disabled row says so on its heads (a column header may be
17
+ * `aria-disabled`), as the strip's row does, since a column has no element
18
+ * of its own.
19
+ */
20
+ function RowHeads({ row }) {
21
+ return (_jsxs(_Fragment, { children: [_jsx("th", { "aria-disabled": row.disabled || undefined, className: cx('sw-denomination-head sw-denomination-transposed-head', columnClass(row)), scope: "col", children: _jsx(RowLabelLine, { row: row }) }), row.valueRow ? (_jsx("th", { "aria-disabled": row.disabled || undefined, "aria-label": `${row.label} ${row.valueRow.label}`, className: cx('sw-denomination-head sw-denomination-transposed-head', columnClass(row)), scope: "col", children: row.valueRow.label })) : null] }));
22
+ }
23
+ /** A grid row's total: under its value line when it has one, else under its counts. */
24
+ function RowTotal({ row }) {
25
+ const total = (_jsx("td", { className: cx('sw-denomination-transposed-total', `sw-denomination-row-${row.tone ?? 'neutral'}`, columnClass(row)), children: row.total ?? '' }));
26
+ return row.valueRow ? (_jsxs(_Fragment, { children: [_jsx("td", { className: columnClass(row) }), total] })) : (total);
27
+ }
28
+ /**
29
+ * A strip drawn for a phone: a row per denomination (its label and
30
+ * caption), a column per grid row (its counts, read-only or entered, then
31
+ * its value line's values), and the totals in a last row named by
32
+ * `totalLabel`. Names, entry, tones and the zero label are the strip's;
33
+ * the denomination column stays in view while the columns scroll under it.
34
+ */
35
+ export function TransposedStrip({ className, style, label, columns, rows, zeroLabel, totalLabel, }) {
36
+ const idPrefix = useId();
37
+ const hasTotals = rows.some((row) => row.total !== undefined);
38
+ return (_jsx(ScrollRegion, { "aria-label": label, className: "sw-denomination-scroll sw-denomination-scroll-transposed", children: _jsxs("table", { className: cx('sw-denomination-grid sw-denomination-transposed', rows.some((row) => row.entry) && 'sw-denomination-transposed-entry', className), style: style, children: [_jsx("caption", { className: "sw-sr-only", children: label }), _jsx("thead", { children: _jsxs("tr", { children: [_jsx("td", { className: "sw-denomination-corner" }), rows.map((row) => (_jsx(RowHeads, { row: row }, row.id)))] }) }), _jsx("tbody", { children: columns.map((column, index) => (_jsxs("tr", { className: "sw-denomination-row", children: [_jsx("th", { className: "sw-denomination-transposed-label", scope: "row", children: _jsx(ColumnHeadText, { column: column }) }), rows.map((row, rowIndex) => {
39
+ const value = row.valueRow?.cells[index];
40
+ const valueId = valueCellId(idPrefix, rowIndex, index);
41
+ return (_jsxs(Fragment, { children: [row.entry ? (_jsx(EntryCell, { className: columnClass(row), column: column, describedBy: hasValue(value) ? valueId : undefined, entry: row.entry, index: index, row: row })) : (_jsx(CountCell, { className: columnClass(row), index: index, row: row, zeroLabel: zeroLabel })), row.valueRow ? (_jsx("td", { className: cx('sw-denomination-transposed-value', columnClass(row)), id: valueId, children: hasValue(value) ? value : '' })) : null] }, row.id));
42
+ })] }, column.key))) }), hasTotals ? (_jsx("tfoot", { children: _jsxs("tr", { className: "sw-denomination-row", children: [totalLabel === undefined ? (_jsx("td", { className: "sw-denomination-corner" })) : (_jsx("th", { className: "sw-denomination-transposed-label", scope: "row", children: totalLabel })), rows.map((row) => (_jsx(RowTotal, { row: row }, row.id)))] }) })) : null] }) }));
43
+ }
@@ -8,6 +8,15 @@ import { type StepperLimitAppearance } from '../Stepper.js';
8
8
  export type { DenominationCellToneAppearance, DenominationGridFrame, DenominationLabelWidth, DenominationTotalEmphasis, };
9
9
  export type DenominationGridTone = BadgeTone;
10
10
  export type DenominationGridLayout = 'strip' | 'tiles';
11
+ /** How a negative count reads: in the danger colour, or plain text. */
12
+ export declare const denominationNegativeAppearances: readonly ["danger", "plain"];
13
+ export type DenominationGridNegativeAppearance = (typeof denominationNegativeAppearances)[number];
14
+ /**
15
+ * The widths below which a strip is drawn transposed: the denominations as
16
+ * rows, the grid's rows as columns.
17
+ */
18
+ export declare const denominationTransposeBreakpoints: readonly ["md", "lg"];
19
+ export type DenominationTransposeBreakpoint = (typeof denominationTransposeBreakpoints)[number];
11
20
  /**
12
21
  * What a named tiles row is to assistive technology: a `region` (a landmark,
13
22
  * the default) or a `group` (named, but not in the landmark list).
@@ -77,6 +86,13 @@ export type DenominationGridRow = {
77
86
  cellTones?: readonly (DenominationGridTone | null)[];
78
87
  /** A muted line under the label, such as "from the customer". */
79
88
  caption?: string;
89
+ /**
90
+ * How a negative count reads: `danger` (the default) in the danger
91
+ * colour; `plain` in the text colour, with its minus sign, for counts
92
+ * that go out by design, such as bills paid out (cash out is never an
93
+ * error, so never red).
94
+ */
95
+ negativeAppearance?: DenominationGridNegativeAppearance;
80
96
  /** The `strip` layout only. */
81
97
  emphasis?: DenominationGridRowEmphasis;
82
98
  /**
@@ -164,4 +180,19 @@ export type DenominationGridProps = {
164
180
  * changed count in accent. Entry counts and tiles keep their tone border.
165
181
  */
166
182
  cellToneAppearance?: DenominationCellToneAppearance;
183
+ /**
184
+ * Below this breakpoint (`md` or `lg`) the strip is drawn transposed,
185
+ * for a phone: one row per denomination (its label and caption) and one
186
+ * column per grid row (its label over its counts, entry steppers or
187
+ * value line), the totals in a last row. Its names, entry, cell tones
188
+ * and zero label are the strip's. The `strip` layout only.
189
+ */
190
+ transposeBelow?: DenominationTransposeBreakpoint;
191
+ /**
192
+ * The digits an entry count holds without clipping, from 3 (the
193
+ * default room) to 6: a column of steppers keeps that many digits'
194
+ * width before the strip scrolls, such as 4 for a count in the
195
+ * thousands in a grid of seven columns. Entry rows only.
196
+ */
197
+ countDigits?: number;
167
198
  };
@@ -1 +1,7 @@
1
- export {};
1
+ /** How a negative count reads: in the danger colour, or plain text. */
2
+ export const denominationNegativeAppearances = ['danger', 'plain'];
3
+ /**
4
+ * The widths below which a strip is drawn transposed: the denominations as
5
+ * rows, the grid's rows as columns.
6
+ */
7
+ export const denominationTransposeBreakpoints = ['md', 'lg'];
@@ -0,0 +1,7 @@
1
+ import { type DenominationGridLayout, type DenominationGridRow } from './types.js';
2
+ /**
3
+ * The grid's later options: a known negative appearance per row, a known
4
+ * transpose breakpoint on a strip only, and a whole count of digits (3 to
5
+ * 6) for a grid with entry rows.
6
+ */
7
+ export declare function assertDenominationOptions(layout: DenominationGridLayout, rows: readonly DenominationGridRow[], transposeBelow: unknown, countDigits: unknown): void;
@@ -0,0 +1,27 @@
1
+ import { denominationNegativeAppearances, denominationTransposeBreakpoints, } from './types.js';
2
+ /** The digits an entry count can be given room for. */
3
+ const countDigitsRange = { min: 3, max: 6 };
4
+ /**
5
+ * The grid's later options: a known negative appearance per row, a known
6
+ * transpose breakpoint on a strip only, and a whole count of digits (3 to
7
+ * 6) for a grid with entry rows.
8
+ */
9
+ export function assertDenominationOptions(layout, rows, transposeBelow, countDigits) {
10
+ if (rows.some((row) => row.negativeAppearance !== undefined &&
11
+ !denominationNegativeAppearances.includes(row.negativeAppearance)))
12
+ throw new RangeError("negativeAppearance must be 'danger' or 'plain'");
13
+ if (transposeBelow !== undefined) {
14
+ if (!denominationTransposeBreakpoints.includes(transposeBelow))
15
+ throw new RangeError("transposeBelow must be 'md' or 'lg'");
16
+ if (layout !== 'strip')
17
+ throw new RangeError('transposeBelow needs the strip layout');
18
+ }
19
+ if (countDigits !== undefined) {
20
+ if (!Number.isInteger(countDigits) ||
21
+ countDigits < countDigitsRange.min ||
22
+ countDigits > countDigitsRange.max)
23
+ throw new RangeError('countDigits must be a whole number from 3 to 6');
24
+ if (!rows.some((row) => row.entry))
25
+ throw new RangeError('countDigits needs entry rows');
26
+ }
27
+ }
@@ -2,13 +2,14 @@ import { type ReactNode } from 'react';
2
2
  import { type ActionBarSummary } from '../action-bar/ActionBarSummary.js';
3
3
  type DialogFooterProps = {
4
4
  summary?: ActionBarSummary;
5
+ status?: ReactNode;
5
6
  children?: ReactNode;
6
7
  };
7
8
  /**
8
- * The dialog's pinned footer: the summary figure (in a polite live region,
9
- * as in ActionBar) at the start, the actions at the end. Rendered only when
10
- * the dialog has a footer or a summary, and then always with its status
11
- * region, so a new figure is announced.
9
+ * The dialog's pinned footer: the summary figure and the status line (in
10
+ * one polite live region, as in ActionBar) at the start, the actions at the
11
+ * end. Rendered only when the dialog has a footer, a summary or a status,
12
+ * and then always with its live region, so a new figure is announced.
12
13
  */
13
- export declare function DialogFooter({ children, summary }: DialogFooterProps): import("react").JSX.Element;
14
+ export declare function DialogFooter({ children, status, summary }: DialogFooterProps): import("react").JSX.Element;
14
15
  export {};
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ActionBarSummaryLine, } from '../action-bar/ActionBarSummary.js';
3
3
  /**
4
- * The dialog's pinned footer: the summary figure (in a polite live region,
5
- * as in ActionBar) at the start, the actions at the end. Rendered only when
6
- * the dialog has a footer or a summary, and then always with its status
7
- * region, so a new figure is announced.
4
+ * The dialog's pinned footer: the summary figure and the status line (in
5
+ * one polite live region, as in ActionBar) at the start, the actions at the
6
+ * end. Rendered only when the dialog has a footer, a summary or a status,
7
+ * and then always with its live region, so a new figure is announced.
8
8
  */
9
- export function DialogFooter({ children, summary }) {
10
- return (_jsxs("div", { className: "sw-dialog-footer", children: [_jsx("div", { className: "sw-dialog-footer-status", role: "status", children: summary ? _jsx(ActionBarSummaryLine, { summary: summary }) : null }), children ? (_jsx("div", { className: "sw-dialog-footer-actions", children: children })) : null] }));
9
+ export function DialogFooter({ children, status, summary }) {
10
+ return (_jsxs("div", { className: "sw-dialog-footer", children: [_jsxs("div", { className: "sw-dialog-footer-status", role: "status", children: [summary ? _jsx(ActionBarSummaryLine, { summary: summary }) : null, status !== undefined ? (_jsx("span", { className: "sw-dialog-footer-note", children: status })) : null] }), children ? (_jsx("div", { className: "sw-dialog-footer-actions", children: children })) : null] }));
11
11
  }
@@ -0,0 +1,24 @@
1
+ import { type Breakpoint } from '../../css/breakpoints.js';
2
+ import { type DialogAppearance } from '../../css/css-dialog-banded.js';
3
+ import { type ThemeCanvas } from '../../css/css-canvas-grouped.js';
4
+ import { type ActionBarSummary } from '../action-bar/ActionBarSummary.js';
5
+ export declare const dialogSizes: readonly ["md", "lg", "xl"];
6
+ /**
7
+ * `md` is the reading width (32rem) for a message or a short form; `lg`
8
+ * (56rem) holds a row of six fields or a data grid without folding it;
9
+ * `xl` (65rem) holds a grid of six count columns with its labels and total.
10
+ */
11
+ export type DialogSize = (typeof dialogSizes)[number];
12
+ /** `alertdialog` for a dialog that interrupts to warn, such as an idle sign-out. */
13
+ export type DialogRole = 'dialog' | 'alertdialog';
14
+ export type DialogChecks = {
15
+ size: DialogSize;
16
+ role: DialogRole | undefined;
17
+ description: string | undefined;
18
+ summary: ActionBarSummary | undefined;
19
+ appearance: DialogAppearance;
20
+ canvas: ThemeCanvas;
21
+ sheetBelow: Breakpoint | undefined;
22
+ sheetGrabber: boolean;
23
+ };
24
+ export declare function assertDialogProps({ appearance, canvas, description, role, sheetBelow, sheetGrabber, size, summary, }: DialogChecks): void;