@scalewing/react 1.37.0 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +39 -1
- package/dist/accessible-name.d.ts +13 -0
- package/dist/accessible-name.js +1 -0
- package/dist/components/DataBar.d.ts +48 -0
- package/dist/components/DataBar.js +28 -0
- package/dist/components/Pagination.d.ts +34 -0
- package/dist/components/Pagination.js +27 -0
- package/dist/components/ScrollRegion.d.ts +9 -5
- package/dist/components/ScrollRegion.js +8 -6
- package/dist/components/SectionNav.d.ts +2 -8
- package/dist/components/SegmentedControl.d.ts +2 -8
- package/dist/components/Table.d.ts +48 -4
- package/dist/components/Table.js +9 -3
- package/dist/components/Tabs.d.ts +2 -9
- package/dist/components/table/TableRow.d.ts +8 -2
- package/dist/components/table/TableRow.js +1 -1
- package/dist/components/table/table-max-height.d.ts +20 -0
- package/dist/components/table/table-max-height.js +23 -0
- package/dist/components/use-scroll-overflow.d.ts +10 -8
- package/dist/components/use-scroll-overflow.js +23 -10
- package/dist/css/chevron.d.ts +6 -3
- package/dist/css/chevron.js +9 -4
- package/dist/css/css-components.js +6 -0
- package/dist/css/css-data-bar.d.ts +16 -0
- package/dist/css/css-data-bar.js +107 -0
- package/dist/css/css-pagination.d.ts +2 -0
- package/dist/css/css-pagination.js +63 -0
- package/dist/css/css-scroll-region.d.ts +1 -0
- package/dist/css/css-scroll-region.js +10 -5
- package/dist/css/css-table-bounded-edges.d.ts +1 -0
- package/dist/css/css-table-bounded-edges.js +132 -0
- package/dist/css/css-table-bounded.d.ts +2 -0
- package/dist/css/css-table-bounded.js +73 -0
- package/dist/css/css-table-ledger.d.ts +5 -2
- package/dist/css/css-table-ledger.js +5 -2
- package/dist/css/css-table-metrics.d.ts +14 -0
- package/dist/css/css-table-metrics.js +13 -0
- package/dist/css/css-table-sort.js +2 -1
- package/dist/css/css-table-total-row.d.ts +2 -0
- package/dist/css/css-table-total-row.js +29 -0
- package/dist/css/css-table.js +14 -3
- package/dist/css/stylesheet.js +4 -0
- package/dist/data-bar-geometry.d.ts +24 -0
- package/dist/data-bar-geometry.js +41 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/pagination-pages.d.ts +13 -0
- package/dist/pagination-pages.js +22 -0
- package/dist/scroll-overflow.d.ts +12 -0
- package/dist/scroll-overflow.js +31 -7
- package/dist/styles.css +223 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @scalewing/react
|
|
2
2
|
|
|
3
|
+
## 1.38.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ac063ea: `DataBar`: a decorative (`aria-hidden`) horizontal range bar for a table cell or a list row, from `from` to `to` on a track whose domain runs from `min` to `max`, such as where a statement's line leaves the running total. A domain from below zero to above it draws a zero line, so a column of differences diverges around it, the bar's end at zero square. `tone` (`DataBarTone`: `neutral`, `success`, `muted`, `strong`, `accent`; no danger tone, money out is `muted`) colours it from the semantic colours mixed into the surface. Values past the domain are clamped; non-finite numbers, a `min` not under `max` and an unknown tone throw a `RangeError`. The bar follows the writing direction and is drawn in the system text colour in forced colours. New exports `DataBar`, `DataBarProps`, `DataBarTone`, `dataBarTones`; new classes `sw-data-bar`, `sw-data-bar-fill`, `sw-data-bar-diverging`, `sw-data-bar-zero-start`, `sw-data-bar-zero-end` and `sw-data-bar-<tone>`; no new tokens, no new dependency. Request: `docs/requests/teisoro-data-bar.md`.
|
|
8
|
+
- b95f9ea: `Pagination`: previous and next steps through a list shown a page at a time, in a `nav` landmark named by `aria-label` or `aria-labelledby`. It shows the consumer's `rangeLabel` (such as "1–25 of 130 changes") at the inline start, a polite live region, and the steps at the end: icon-only neutral `sm` Buttons named by `labels` (`PaginationLabels`: `previous`, `next`), square, 44 px on a coarse pointer, with a private chevron mirrored right to left. `page` and `pageCount` count from 1 and `onPageChange` receives the page a step goes to. At either end a step is `aria-disabled` (the neutral grey) but stays a Tab stop, so focus is not dropped at the last page, and a press there does nothing. Invalid pages or an empty step label (`labels.previous` or `labels.next`) throw a `RangeError`. New exports `Pagination`, `PaginationProps`, `PaginationLabels`; new classes `sw-pagination`, `sw-pagination-range`, `sw-pagination-steps`, `sw-pagination-step`, `sw-pagination-glyph`, `sw-pagination-glyph-previous` and `sw-pagination-glyph-next`; no new tokens, no new dependency. Request: `docs/requests/teisoro-pagination.md`.
|
|
9
|
+
- 744ed13: `Table` `maxHeight` (opt-in): bounds a table's height by a row count, `{ rows: number }` (new type `TableMaxHeight`), and the rest of the rows scroll inside the table's own region. The region is as tall as that many single-line body rows plus the header row and the footer row when there is one, from the type and spacing tokens the cells are drawn with (compact density included; a sorting header as tall as its buttons, the 44 px touch target on a coarse pointer). The header pins to the region's top and a `TableFooter sticky` total to its bottom; the region stays a keyboard stop named after the table, and an edge with rows scrolled past it draws the scroll shade, cast from the pinned header or total, or from the region's own edge where nothing is pinned (none in forced colours). While the region has keyboard focus, the pinned header and total carry the part of its focus ring they cover. Printed, every row shows. Page pinning (`stickyHeader="page"`, a sticky footer in a table that fits) is unchanged for tables without `maxHeight`; with it, `stickyHeader` `'page'` or `false` throw a `RangeError`, as does a row count that is not a whole number from 1. New classes `sw-table-bounded`, `sw-scroll-more-top` and `sw-scroll-more-bottom`; no new tokens, no new dependency. Request: `docs/requests/teisoro-table-contained-scroll.md`.
|
|
10
|
+
- b638b5e: `TableRow` `variant="total"`: a total mid-table, such as a subtotal the rows above add up to before the table goes on. Its cells are at weight 600 under a 2 px rule across its top (the cells' own collapsed border, kept in forced colours), as a `TableFooter` total is drawn, with no fill, so accent text keeps the contrast it has on the table's own surface. `tableRowVariants` is now `['default', 'sub', 'total']`. New class `sw-table-row-total`; no new tokens, no new dependency. Request: `docs/requests/teisoro-table-row-total.md`.
|
|
11
|
+
|
|
3
12
|
## 1.37.0
|
|
4
13
|
|
|
5
14
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
ActionBar,
|
|
11
11
|
ActionMenu,
|
|
12
12
|
BarChart,
|
|
13
|
+
DataBar,
|
|
13
14
|
Box,
|
|
14
15
|
Button,
|
|
15
16
|
CalendarButton,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
RadioGroup,
|
|
19
20
|
SectionNav,
|
|
20
21
|
Spinner,
|
|
22
|
+
Pagination,
|
|
21
23
|
Progress,
|
|
22
24
|
Tooltip,
|
|
23
25
|
InfoTip,
|
|
@@ -418,7 +420,7 @@ An option's optional `description` (a `ReactNode`) is secondary text for that op
|
|
|
418
420
|
|
|
419
421
|
A header `TableCell` (`as="th"`) with `sort` (`'ascending'`, `'descending'` or `'none'`) and `onSort` is its column's sort control: its children become a button in the header's own style with a chevron (before the name in a `numeric` or end-aligned column), and the cell carries `aria-sort` only while it is the sorted column. `sort` on a data cell, or one of the two without the other, throws a `TypeError`. `Table` `layout="fixed"` (default `auto`) sizes the columns from the header row alone, so a filter that hides a row moves no column, and `verticalAlign="top"` (default `middle`) starts every cell of a tall row on its first line. `TableCell` `width` is `min` (an auto table's column takes the least room its content allows, on one line; set it on each cell of the column) or a size, `xs` to `xl` (4, 6, 8, 12 and 16 rem); in a fixed table a column without a width shares what is left, so leave one column, such as a description, unsized. The HTML `width` attribute is not accepted. Unknown values throw a `RangeError`.
|
|
420
422
|
|
|
421
|
-
A ledger read across as well as down takes `Table` `columnRules` (a hairline at the inline start of every cell after a row's first, mirrored right to left) and `TableCell` `tone` (`success`, `danger`, `muted` or `accent`: the cell's text in the theme colour, as `Text color` uses it; never the only signal, so keep the sign or the words). `TableRow` `variant="sub"` (default `"default"`) sets a row under the one above, as a batch's items: its row header, a `TableCell as="th" scope="row"`, is indented a `space-6` step with a guide bar at the indent (a sub row without a row header is not indented). `TableRow` `struck` keeps a voided row on the record: the subtle fill and the text muted and struck through, toned cells included; it works with
|
|
423
|
+
A ledger read across as well as down takes `Table` `columnRules` (a hairline at the inline start of every cell after a row's first, mirrored right to left) and `TableCell` `tone` (`success`, `danger`, `muted` or `accent`: the cell's text in the theme colour, as `Text color` uses it; never the only signal, so keep the sign or the words). `TableRow` `variant="sub"` (default `"default"`) sets a row under the one above, as a batch's items: its row header, a `TableCell as="th" scope="row"`, is indented a `space-6` step with a guide bar at the indent (a sub row without a row header is not indented). `TableRow` `variant="total"` is a total mid-table, such as a subtotal the rows above add up to before the table goes on: its cells at weight 600 under a 2 px rule across its top (the cells' own collapsed top border, so forced colors keep it), as a `TableFooter` total is drawn, with no fill, so accent text in it keeps the contrast it has on the table's own surface. Name it with a row header and keep it in the body, after the rows it adds up (not the body's first row under a pinned header, whose rule would sit on its own); a cell's `tone` keeps its colour, and `struck` works on it. Its cells are all at weight 600, so a quiet link or a `TableCell onPress` action in it is no longer set apart by weight: keep a total row's name plain text (a `TableFooter` row is the same). `TableRow` `struck` keeps a voided row on the record: the subtle fill and the text muted and struck through, toned cells included; it works with any variant. A line-through is not read aloud, so say why in the row, such as a `Badge` "Voided": a Badge in a line of text is not struck, but one that is itself a flex item (a direct child of `Inline`) is, so put it in the title's line. A row header in the body or footer (`th scope="row"`) reads as body text. An unknown `tone` or `variant` throws a `RangeError`.
|
|
422
424
|
|
|
423
425
|
`Table` `stickyHeader` pins the header: the whole `TableHeader` as one group, every row in it (the column headings and any row under them, such as a running total) with all its cells, `th` and `td`, each row under the one above, on the glass with its row and column rules. `true` (default) pins it to the top of the table's own scroll region, `false` lets it scroll away, and `'page'` pins it to the page's top as the page scrolls. With `'page'`, while the table fits its width its region stops being a scroll box (`sw-table-sticky-page`), so the header stays in view under any sticky `AppHeader` (which covers it); a table wider than its region scrolls sideways in it and pins inside it. Use it for a long table whose last row, such as a non-sticky `TableFooter` total, should scroll with the rows. An unknown value throws a `RangeError`.
|
|
424
426
|
|
|
@@ -430,8 +432,44 @@ A ledger read across as well as down takes `Table` `columnRules` (a hairline at
|
|
|
430
432
|
|
|
431
433
|
`TableFooter` is the table's `tfoot`, for a total: its cells are set at weight 600 under a 2 px rule across its first row (drawn on each cell's `::before`, so forced colors keep it), and a `TableCell as="th" scope="row"` in it names the total. `sticky` pins the footer to the bottom edge on the header's glass (solid under Reduce Transparency, the system canvas in forced colors), on its own layer over the cells and the pinned header. While the table fits its width, a table with a sticky footer stops being a scroll box, so the footer pins to the page's bottom and the sticky header to its top as the page scrolls; a sticky `AppHeader` covers that header. A table wider than its region scrolls sideways in it and pins to the region instead. A sticky `ActionBar` covers a pinned footer, and so does a `Dialog`'s pinned footer, so do not pair them.
|
|
432
434
|
|
|
435
|
+
`Table` `maxHeight` (opt-in, `{ rows: number }`, type `TableMaxHeight`) bounds the table's height by a row count, and the rest of the rows scroll inside the table's own region: the region is as tall as that many single-line body rows plus the header row and, when there is one, the footer row (from the type and spacing tokens the cells are drawn with, compact density included, a sorting header as tall as its buttons and the 44 px touch target on a coarse pointer; rows of two lines or with controls, a second header or footer row, and a horizontal scrollbar that takes room show fewer at a time). The header pins to the region's top and a `TableFooter sticky` total to its bottom, so a total over every row stays in view while the rows scroll; a non-sticky footer scrolls with the rows. The region stays a keyboard stop named after the table, and while rows are scrolled out past its top or bottom that edge draws the scroll shade (`sw-scroll-more-top`, `sw-scroll-more-bottom`): cast from the pinned header's last row (a header cell spanning rows from an earlier row casts none) or total over the rows under it, or from the region's own edge where nothing is pinned; none in forced colors. While the region has keyboard focus, the pinned header and total carry the part of its focus ring they cover (their side parts on the first and last cells, so avoid `rowSpan` in a bounded table's header). Printed, every row shows. A bounded table never pins to the page, and without `maxHeight` the page pinning above is unchanged. `stickyHeader` `'page'` or `false` with it, a value that is not `{ rows }`, or a row count that is not a whole number from 1 throw a `RangeError`.
|
|
436
|
+
|
|
437
|
+
```tsx
|
|
438
|
+
<Table aria-label="Closeouts" maxHeight={{ rows: 12 }}>
|
|
439
|
+
<TableHeader>…</TableHeader>
|
|
440
|
+
<TableBody>…</TableBody>
|
|
441
|
+
<TableFooter sticky>…</TableFooter>
|
|
442
|
+
</Table>
|
|
443
|
+
```
|
|
444
|
+
|
|
433
445
|
`BarChart` `formatValue` writes the axis's values and each value without its own `valueLabel`, such as a currency. `diverging` puts zero in the middle of each track behind a hairline: a positive bar grows toward the inline end and a negative one toward the start, on one scale, and the axis reads minus the maximum, zero and the maximum. Without it every bar grows from the start. An item's `tone` (`BarChartTone`: `'accent'`, `'success'`, `'warning'` or `'danger'`, listed in the exported `barChartTones`) colors its bar by what it means in place of its sign's default (the accent, or danger for a negative value), such as a diverging chart's overage in `'warning'` and shortage in `'danger'`; a toned bar keeps its sign's place, every tone keeps 3:1 against the track, and an unknown tone throws a `RangeError`. Forced colors draw every bar in the system text color, so the value and its side of zero carry the meaning there.
|
|
434
446
|
|
|
447
|
+
`DataBar` is a horizontal range bar for a table cell or a list row: a bar from `from` to `to` (whichever is larger is its far end) on a track whose domain runs from `min` to `max`, such as where a statement's line leaves the running total. It fills its container's width, a spacing step 4 tall with no track fill, and its ends follow the writing direction. It is decorative (`aria-hidden`): the figure is the cell's own text, so keep the value beside it, and a cell holding both is named by the figure alone. `tone` (`DataBarTone`, listed in `dataBarTones`; default `'neutral'`) says what the bar is: `'neutral'` for where it started, `'success'` for what came in, `'muted'` for what went out (there is no danger tone: an outflow is not an error), `'strong'` for a subtotal and `'accent'` for what was counted or recorded. Each is a semantic colour mixed into the surface, 1.5:1 or more on it, the three greys 1.5:1 or more apart, in every palette and scheme. A domain from below zero to above it (`min < 0 < max`) draws a hairline at zero, so a column of differences diverges around it (`from={0} to={value}`), and the bar's end at zero is square. Values past the domain are clamped to it; non-finite numbers, a `min` not under `max`, or an unknown tone throw a `RangeError`. Forced colors draw the bar and the zero line in the system text color.
|
|
448
|
+
|
|
449
|
+
A bar in its own column reads as empty cells to assistive technology, which is fine while the figure's cell carries the value; a bar and its figure can also share one cell, side by side in a `Grid`.
|
|
450
|
+
|
|
451
|
+
```tsx
|
|
452
|
+
<TableCell numeric>
|
|
453
|
+
<Grid align="center" columns={2} gap={2}>
|
|
454
|
+
<DataBar from={0} to={-6} min={-10} max={10} tone="muted" />
|
|
455
|
+
<span>−6</span>
|
|
456
|
+
</Grid>
|
|
457
|
+
</TableCell>
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
`Pagination` steps through a list shown a page at a time, for a list with no total to keep in view (a list that adds up scrolls inside itself instead, with `Table` `maxHeight`). It is a `nav` landmark named by `aria-label` or `aria-labelledby` (one is required), holding the consumer's words for what the page shows (`rangeLabel`, such as "1–25 of 130 changes", in the muted caption at the inline start and announced politely when it changes) and the previous and next steps at the end: icon-only neutral `sm` Buttons, square, the 44 px touch target on a coarse pointer, named by `labels` (`PaginationLabels`: `previous`, `next`) with a private chevron glyph mirrored right to left. `page` (from 1) and `pageCount` place it; a step calls `onPageChange` with the page it goes to. At either end its step looks disabled (`aria-disabled`, the neutral grey) but stays a Tab stop, so focus is never dropped when the last page is reached, and a press there does nothing. Pages that are not whole numbers in range, or an empty step label (`labels.previous` or `labels.next`), throw a `RangeError`. The row wraps on a narrow column, the steps staying at the end.
|
|
461
|
+
|
|
462
|
+
```tsx
|
|
463
|
+
<Pagination
|
|
464
|
+
aria-label="Change pages"
|
|
465
|
+
page={page}
|
|
466
|
+
pageCount={6}
|
|
467
|
+
onPageChange={setPage}
|
|
468
|
+
rangeLabel="1–25 of 130 changes"
|
|
469
|
+
labels={{ previous: 'Previous page', next: 'Next page' }}
|
|
470
|
+
/>
|
|
471
|
+
```
|
|
472
|
+
|
|
435
473
|
`Spinner` shows indeterminate loading in small, medium, or large sizes. Supply localized `label` for the one announced status in a loading region. Use `decorative` on additional indicators beside that status so screen readers do not hear the same message repeatedly. Reduced motion leaves a static accented ring.
|
|
436
474
|
|
|
437
475
|
`GlyphTile` is a small rounded square in a categorical colour with the consumer's glyph in white: the mark of a kind beside its name, such as a service in a list. `hue` is one of the `@scalewing/tokens` categorical colours (`green`, `blue`, `orange`, `purple`, `teal`, `rose`, or `neutral`); which kind takes which hue is yours. `size` is `sm` (24), `md` (28, the default) or `lg` (32); the glyph is drawn at spacing step 4 in white, which keeps 3:1 on every fill; pass the SVG (a Lucide component) as the tile's direct child, since only a direct-child SVG is sized. It is always `aria-hidden`, so put the kind's name in visible text beside it. An unknown `hue` or `size` throws a `RangeError`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A component's accessible name, given one way: `aria-label` with the words,
|
|
3
|
+
* or `aria-labelledby` with the id of an element that holds them, never both.
|
|
4
|
+
* Shared by the components whose name is required (a group, a list of tabs,
|
|
5
|
+
* a navigation landmark).
|
|
6
|
+
*/
|
|
7
|
+
export type AccessibleName = {
|
|
8
|
+
'aria-label': string;
|
|
9
|
+
'aria-labelledby'?: never;
|
|
10
|
+
} | {
|
|
11
|
+
'aria-label'?: never;
|
|
12
|
+
'aria-labelledby': string;
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type HTMLAttributes } from 'react';
|
|
2
|
+
import { type DataBarTone, dataBarTones } from '../css/css-data-bar.js';
|
|
3
|
+
export type { DataBarTone };
|
|
4
|
+
export { dataBarTones };
|
|
5
|
+
export type DataBarProps = Omit<HTMLAttributes<HTMLSpanElement>, 'children' | 'aria-hidden'> & {
|
|
6
|
+
/** One end of the range, in the domain's units. */
|
|
7
|
+
from: number;
|
|
8
|
+
/** The other end; the bar runs between the two whichever is larger. */
|
|
9
|
+
to: number;
|
|
10
|
+
/** The domain's least value, at the track's inline start. */
|
|
11
|
+
min: number;
|
|
12
|
+
/** The domain's greatest value, at the track's inline end. */
|
|
13
|
+
max: number;
|
|
14
|
+
/**
|
|
15
|
+
* What the bar means (default `neutral`): `success` for money in,
|
|
16
|
+
* `muted` for money out (an outflow is not an error, so there is no
|
|
17
|
+
* danger tone), `strong` for a subtotal and `accent` for a counted or
|
|
18
|
+
* recorded figure.
|
|
19
|
+
*/
|
|
20
|
+
tone?: DataBarTone;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A horizontal range bar for a table cell or a list row: a bar from `from`
|
|
24
|
+
* to `to` on a track whose domain runs from `min` to `max`, such as where a
|
|
25
|
+
* statement's line leaves the running total, or a day's difference on a
|
|
26
|
+
* domain from below zero to above it, which draws a zero line. It is
|
|
27
|
+
* decorative (`aria-hidden`): the figure is the cell's own text, so keep
|
|
28
|
+
* the value beside it. Values past the domain are clamped to it;
|
|
29
|
+
* non-finite numbers, a `min` not under `max` or an unknown tone throw a
|
|
30
|
+
* `RangeError`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const DataBar: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLSpanElement>, "children" | "aria-hidden"> & {
|
|
33
|
+
/** One end of the range, in the domain's units. */
|
|
34
|
+
from: number;
|
|
35
|
+
/** The other end; the bar runs between the two whichever is larger. */
|
|
36
|
+
to: number;
|
|
37
|
+
/** The domain's least value, at the track's inline start. */
|
|
38
|
+
min: number;
|
|
39
|
+
/** The domain's greatest value, at the track's inline end. */
|
|
40
|
+
max: number;
|
|
41
|
+
/**
|
|
42
|
+
* What the bar means (default `neutral`): `success` for money in,
|
|
43
|
+
* `muted` for money out (an outflow is not an error, so there is no
|
|
44
|
+
* danger tone), `strong` for a subtotal and `accent` for a counted or
|
|
45
|
+
* recorded figure.
|
|
46
|
+
*/
|
|
47
|
+
tone?: DataBarTone;
|
|
48
|
+
} & import("react").RefAttributes<HTMLSpanElement>>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { cx } from '../class-names.js';
|
|
4
|
+
import { dataBarTones } from '../css/css-data-bar.js';
|
|
5
|
+
import { dataBarGeometry } from '../data-bar-geometry.js';
|
|
6
|
+
export { dataBarTones };
|
|
7
|
+
/**
|
|
8
|
+
* A horizontal range bar for a table cell or a list row: a bar from `from`
|
|
9
|
+
* to `to` on a track whose domain runs from `min` to `max`, such as where a
|
|
10
|
+
* statement's line leaves the running total, or a day's difference on a
|
|
11
|
+
* domain from below zero to above it, which draws a zero line. It is
|
|
12
|
+
* decorative (`aria-hidden`): the figure is the cell's own text, so keep
|
|
13
|
+
* the value beside it. Values past the domain are clamped to it;
|
|
14
|
+
* non-finite numbers, a `min` not under `max` or an unknown tone throw a
|
|
15
|
+
* `RangeError`.
|
|
16
|
+
*/
|
|
17
|
+
export const DataBar = forwardRef(function DataBar({ className, from, max, min, style, to, tone = 'neutral', ...rest }, ref) {
|
|
18
|
+
if (!dataBarTones.includes(tone))
|
|
19
|
+
throw new RangeError(`DataBar tone must be one of ${dataBarTones.join(', ')}; received ${String(tone)}`);
|
|
20
|
+
const { start, size, zero, zeroEnd } = dataBarGeometry(from, to, min, max);
|
|
21
|
+
return (_jsx("span", { ref: ref, className: cx('sw-data-bar', `sw-data-bar-${tone}`, zero !== null && 'sw-data-bar-diverging', zeroEnd !== null && `sw-data-bar-zero-${zeroEnd}`, className), style: {
|
|
22
|
+
...style,
|
|
23
|
+
...(zero === null ? {} : { '--sw-data-bar-zero': zero }),
|
|
24
|
+
}, ...rest, "aria-hidden": "true", children: _jsx("span", { className: "sw-data-bar-fill", style: {
|
|
25
|
+
'--sw-data-bar-start': start,
|
|
26
|
+
'--sw-data-bar-size': size,
|
|
27
|
+
} }) }));
|
|
28
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type HTMLAttributes } from 'react';
|
|
2
|
+
import { type AccessibleName } from '../accessible-name.js';
|
|
3
|
+
/** The steps' accessible names, in the product's words. */
|
|
4
|
+
export type PaginationLabels = {
|
|
5
|
+
/** Names the step to the page before, such as "Previous page". */
|
|
6
|
+
previous: string;
|
|
7
|
+
/** Names the step to the page after, such as "Next page". */
|
|
8
|
+
next: string;
|
|
9
|
+
};
|
|
10
|
+
export type PaginationProps = Omit<HTMLAttributes<HTMLElement>, 'children' | 'aria-label' | 'aria-labelledby'> & AccessibleName & {
|
|
11
|
+
/** The page shown, from 1. */
|
|
12
|
+
page: number;
|
|
13
|
+
/** How many pages there are, from 1. */
|
|
14
|
+
pageCount: number;
|
|
15
|
+
/** Called with the page a step goes to; never past either end. */
|
|
16
|
+
onPageChange: (page: number) => void;
|
|
17
|
+
/**
|
|
18
|
+
* What the page shows, in the product's words, such as "1–25 of 130
|
|
19
|
+
* changes". It is announced politely when it changes.
|
|
20
|
+
*/
|
|
21
|
+
rangeLabel: string;
|
|
22
|
+
labels: PaginationLabels;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Previous and next steps through a list shown a page at a time, beside
|
|
26
|
+
* the consumer's words for what the page shows, in a navigation landmark
|
|
27
|
+
* named by `aria-label` or `aria-labelledby`. Each step is an icon-only
|
|
28
|
+
* neutral Button named by `labels`. At either end its step looks disabled
|
|
29
|
+
* (`aria-disabled`) but stays a Tab stop, so focus is never dropped when
|
|
30
|
+
* the last page is reached, and a press there does nothing. Invalid pages
|
|
31
|
+
* or an empty step label (`labels.previous` or `labels.next`) throw a
|
|
32
|
+
* `RangeError`.
|
|
33
|
+
*/
|
|
34
|
+
export declare const Pagination: import("react").ForwardRefExoticComponent<PaginationProps & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { cx } from '../class-names.js';
|
|
4
|
+
import { assertPaginationLabels, assertPaginationPages, paginationStep, } from '../pagination-pages.js';
|
|
5
|
+
import { Button } from './Button.js';
|
|
6
|
+
/**
|
|
7
|
+
* Previous and next steps through a list shown a page at a time, beside
|
|
8
|
+
* the consumer's words for what the page shows, in a navigation landmark
|
|
9
|
+
* named by `aria-label` or `aria-labelledby`. Each step is an icon-only
|
|
10
|
+
* neutral Button named by `labels`. At either end its step looks disabled
|
|
11
|
+
* (`aria-disabled`) but stays a Tab stop, so focus is never dropped when
|
|
12
|
+
* the last page is reached, and a press there does nothing. Invalid pages
|
|
13
|
+
* or an empty step label (`labels.previous` or `labels.next`) throw a
|
|
14
|
+
* `RangeError`.
|
|
15
|
+
*/
|
|
16
|
+
export const Pagination = forwardRef(function Pagination({ className, labels, onPageChange, page, pageCount, rangeLabel, ...rest }, ref) {
|
|
17
|
+
assertPaginationPages(page, pageCount);
|
|
18
|
+
assertPaginationLabels(labels);
|
|
19
|
+
const step = (direction) => {
|
|
20
|
+
const target = paginationStep(page, pageCount, direction);
|
|
21
|
+
return (_jsx(Button, { "aria-disabled": target === null || undefined, "aria-label": labels[direction], className: "sw-pagination-step", disabledAppearance: "neutral", onPress: () => {
|
|
22
|
+
if (target !== null)
|
|
23
|
+
onPageChange(target);
|
|
24
|
+
}, size: "sm", variant: "neutral", children: _jsx("span", { "aria-hidden": "true", className: `sw-pagination-glyph sw-pagination-glyph-${direction}` }) }));
|
|
25
|
+
};
|
|
26
|
+
return (_jsxs("nav", { ref: ref, className: cx('sw-pagination', className), ...rest, children: [_jsx("span", { "aria-atomic": "true", "aria-live": "polite", className: "sw-pagination-range", children: rangeLabel }), _jsxs("span", { className: "sw-pagination-steps", children: [step('previous'), step('next')] })] }));
|
|
27
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ReactNode } from 'react';
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
2
|
type ScrollRegionProps = {
|
|
3
3
|
children: ReactNode;
|
|
4
4
|
className: string;
|
|
@@ -6,6 +6,8 @@ type ScrollRegionProps = {
|
|
|
6
6
|
'aria-labelledby'?: string;
|
|
7
7
|
/** Adds `sw-scroll-fits` once measured with content that fits its width. */
|
|
8
8
|
markFits?: boolean;
|
|
9
|
+
/** Generated custom properties only, such as a bounded table's row count. */
|
|
10
|
+
style?: CSSProperties;
|
|
9
11
|
};
|
|
10
12
|
/**
|
|
11
13
|
* Private wrapper that scrolls wide content inside its own box (see
|
|
@@ -14,9 +16,11 @@ type ScrollRegionProps = {
|
|
|
14
16
|
* keyboard and is announced as one group. While content is scrolled out past
|
|
15
17
|
* an inline edge, that edge draws a shade (`sw-scroll-more-start`,
|
|
16
18
|
* `sw-scroll-more-end`), so a phone, whose scrollbars hide, still shows that
|
|
17
|
-
* the table goes on.
|
|
18
|
-
* its
|
|
19
|
-
*
|
|
19
|
+
* the table goes on. A region of bounded height that scrolls its rows marks
|
|
20
|
+
* its top and bottom the same way (`sw-scroll-more-top`,
|
|
21
|
+
* `sw-scroll-more-bottom`). With `markFits`, a measured region whose content
|
|
22
|
+
* fits its width carries `sw-scroll-fits`, so a table with a sticky footer
|
|
23
|
+
* can stop being a scroll box and pin its header and footer to the page.
|
|
20
24
|
*/
|
|
21
|
-
export declare function ScrollRegion({ children, className, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, markFits, }: ScrollRegionProps): import("react").JSX.Element;
|
|
25
|
+
export declare function ScrollRegion({ children, className, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, markFits, style, }: ScrollRegionProps): import("react").JSX.Element;
|
|
22
26
|
export {};
|
|
@@ -10,16 +10,18 @@ import { useScrollOverflow } from './use-scroll-overflow.js';
|
|
|
10
10
|
* keyboard and is announced as one group. While content is scrolled out past
|
|
11
11
|
* an inline edge, that edge draws a shade (`sw-scroll-more-start`,
|
|
12
12
|
* `sw-scroll-more-end`), so a phone, whose scrollbars hide, still shows that
|
|
13
|
-
* the table goes on.
|
|
14
|
-
* its
|
|
15
|
-
*
|
|
13
|
+
* the table goes on. A region of bounded height that scrolls its rows marks
|
|
14
|
+
* its top and bottom the same way (`sw-scroll-more-top`,
|
|
15
|
+
* `sw-scroll-more-bottom`). With `markFits`, a measured region whose content
|
|
16
|
+
* fits its width carries `sw-scroll-fits`, so a table with a sticky footer
|
|
17
|
+
* can stop being a scroll box and pin its header and footer to the page.
|
|
16
18
|
*/
|
|
17
|
-
export function ScrollRegion({ children, className, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, markFits = false, }) {
|
|
19
|
+
export function ScrollRegion({ children, className, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, markFits = false, style, }) {
|
|
18
20
|
const ref = useRef(null);
|
|
19
21
|
const overflow = useScrollOverflow(ref);
|
|
20
|
-
return (_jsx("div", { ref: ref, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, className: cx(className, overflow.start && 'sw-scroll-more-start', overflow.end && 'sw-scroll-more-end', markFits &&
|
|
22
|
+
return (_jsx("div", { ref: ref, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, className: cx(className, overflow.start && 'sw-scroll-more-start', overflow.end && 'sw-scroll-more-end', overflow.top && 'sw-scroll-more-top', overflow.bottom && 'sw-scroll-more-bottom', markFits &&
|
|
21
23
|
overflow.measured &&
|
|
22
24
|
!overflow.start &&
|
|
23
25
|
!overflow.end &&
|
|
24
|
-
'sw-scroll-fits'), role: "group", tabIndex: 0, children: children }));
|
|
26
|
+
'sw-scroll-fits'), role: "group", style: style, tabIndex: 0, children: children }));
|
|
25
27
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
+
import { type AccessibleName } from '../accessible-name.js';
|
|
2
3
|
import { type Breakpoint } from '../css/breakpoints.js';
|
|
3
4
|
import { type SectionNavAppearance } from '../css/css-section-nav-filled.js';
|
|
4
5
|
export type { SectionNavAppearance };
|
|
@@ -29,14 +30,7 @@ export type SectionNavItem = {
|
|
|
29
30
|
*/
|
|
30
31
|
countLabel?: string;
|
|
31
32
|
};
|
|
32
|
-
type
|
|
33
|
-
'aria-label': string;
|
|
34
|
-
'aria-labelledby'?: never;
|
|
35
|
-
} | {
|
|
36
|
-
'aria-label'?: never;
|
|
37
|
-
'aria-labelledby': string;
|
|
38
|
-
};
|
|
39
|
-
export type SectionNavProps = SectionNavLabel & {
|
|
33
|
+
export type SectionNavProps = AccessibleName & {
|
|
40
34
|
items: readonly SectionNavItem[];
|
|
41
35
|
/**
|
|
42
36
|
* Called for a plain press on an item (the main button, no modifier key),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
+
import { type AccessibleName } from '../accessible-name.js';
|
|
2
3
|
export type SegmentedItem = {
|
|
3
4
|
id: string;
|
|
4
5
|
label: ReactNode;
|
|
@@ -11,13 +12,6 @@ export type SegmentedItem = {
|
|
|
11
12
|
*/
|
|
12
13
|
icon?: ReactNode;
|
|
13
14
|
};
|
|
14
|
-
type SegmentedLabel = {
|
|
15
|
-
'aria-label': string;
|
|
16
|
-
'aria-labelledby'?: never;
|
|
17
|
-
} | {
|
|
18
|
-
'aria-label'?: never;
|
|
19
|
-
'aria-labelledby': string;
|
|
20
|
-
};
|
|
21
15
|
/**
|
|
22
16
|
* `compact` is the quiet chip track for a section switch; `filled` gives every
|
|
23
17
|
* segment the same width and paints the selected one in the accent, for a
|
|
@@ -40,7 +34,7 @@ type SegmentedChange = {
|
|
|
40
34
|
disabled: true;
|
|
41
35
|
onChange?: (id: string) => void;
|
|
42
36
|
};
|
|
43
|
-
export type SegmentedControlProps =
|
|
37
|
+
export type SegmentedControlProps = AccessibleName & SegmentedChange & {
|
|
44
38
|
items: readonly SegmentedItem[];
|
|
45
39
|
value: string;
|
|
46
40
|
variant?: SegmentedControlVariant;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { type HTMLAttributes } from 'react';
|
|
2
2
|
import { type TableLayout, type TableStickyHeader, type TableVerticalAlign } from './table/table-layout.js';
|
|
3
|
+
import { type TableMaxHeight } from './table/table-max-height.js';
|
|
3
4
|
export { TableCell, type TableCellProps, type TableColumnWidth, type TableSort, } from './table/TableCell.js';
|
|
4
5
|
export { TableRow, type TableRowProps, type TableRowVariant, } from './table/TableRow.js';
|
|
5
6
|
export type { TableCellTone } from '../css/css-table-ledger.js';
|
|
6
7
|
export { tableCellTones, tableRowVariants } from '../css/css-table-ledger.js';
|
|
7
|
-
export type { TableLayout, TableStickyHeader, TableVerticalAlign };
|
|
8
|
+
export type { TableLayout, TableMaxHeight, TableStickyHeader, TableVerticalAlign, };
|
|
8
9
|
export type TableDensity = 'comfortable' | 'compact';
|
|
9
10
|
export type TableProps = HTMLAttributes<HTMLTableElement> & {
|
|
10
11
|
density?: TableDensity;
|
|
@@ -40,8 +41,30 @@ export type TableProps = HTMLAttributes<HTMLTableElement> & {
|
|
|
40
41
|
* after a row's first, for a ledger read across as well as down.
|
|
41
42
|
*/
|
|
42
43
|
columnRules?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Bounds the table's height, counted in rows (`{ rows: 12 }`): its region
|
|
46
|
+
* is as tall as that many single-line body rows plus the header row (a
|
|
47
|
+
* sorting header as tall as its buttons, the touch target on a coarse
|
|
48
|
+
* pointer) and, when there is one, the footer row, and the rest of the
|
|
49
|
+
* rows scroll inside it. Rows of two lines or with controls, a second
|
|
50
|
+
* header or footer row and a horizontal scrollbar that takes room show
|
|
51
|
+
* fewer rows. The header pins to the region's top and a sticky
|
|
52
|
+
* `TableFooter` total to its bottom, so a total over every row stays in
|
|
53
|
+
* view. The region is a keyboard stop named after the table, its focus
|
|
54
|
+
* ring drawn over the pinned rows too, and an edge with rows scrolled
|
|
55
|
+
* out past it draws a shade (cast from the pinned header's last row or
|
|
56
|
+
* the total when there is one). Printed, every row shows. It keeps its
|
|
57
|
+
* header pinned to the region, so `stickyHeader` `'page'` or `false`
|
|
58
|
+
* throw with it, as do a value that is not `{ rows }` and a row count
|
|
59
|
+
* that is not a whole number from 1. Without it (the default) the table
|
|
60
|
+
* is as tall as its rows.
|
|
61
|
+
*/
|
|
62
|
+
maxHeight?: TableMaxHeight;
|
|
43
63
|
};
|
|
44
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* A wide table scrolls inside its own `ScrollRegion`, named after the
|
|
66
|
+
* table; a bounded one (`maxHeight`) scrolls its rows in it too.
|
|
67
|
+
*/
|
|
45
68
|
export declare const Table: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLTableElement> & {
|
|
46
69
|
density?: TableDensity;
|
|
47
70
|
/**
|
|
@@ -76,6 +99,25 @@ export declare const Table: import("react").ForwardRefExoticComponent<HTMLAttrib
|
|
|
76
99
|
* after a row's first, for a ledger read across as well as down.
|
|
77
100
|
*/
|
|
78
101
|
columnRules?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Bounds the table's height, counted in rows (`{ rows: 12 }`): its region
|
|
104
|
+
* is as tall as that many single-line body rows plus the header row (a
|
|
105
|
+
* sorting header as tall as its buttons, the touch target on a coarse
|
|
106
|
+
* pointer) and, when there is one, the footer row, and the rest of the
|
|
107
|
+
* rows scroll inside it. Rows of two lines or with controls, a second
|
|
108
|
+
* header or footer row and a horizontal scrollbar that takes room show
|
|
109
|
+
* fewer rows. The header pins to the region's top and a sticky
|
|
110
|
+
* `TableFooter` total to its bottom, so a total over every row stays in
|
|
111
|
+
* view. The region is a keyboard stop named after the table, its focus
|
|
112
|
+
* ring drawn over the pinned rows too, and an edge with rows scrolled
|
|
113
|
+
* out past it draws a shade (cast from the pinned header's last row or
|
|
114
|
+
* the total when there is one). Printed, every row shows. It keeps its
|
|
115
|
+
* header pinned to the region, so `stickyHeader` `'page'` or `false`
|
|
116
|
+
* throw with it, as do a value that is not `{ rows }` and a row count
|
|
117
|
+
* that is not a whole number from 1. Without it (the default) the table
|
|
118
|
+
* is as tall as its rows.
|
|
119
|
+
*/
|
|
120
|
+
maxHeight?: TableMaxHeight;
|
|
79
121
|
} & import("react").RefAttributes<HTMLTableElement>>;
|
|
80
122
|
export type TableHeaderProps = HTMLAttributes<HTMLTableSectionElement>;
|
|
81
123
|
export declare const TableHeader: import("react").ForwardRefExoticComponent<TableHeaderProps & import("react").RefAttributes<HTMLTableSectionElement>>;
|
|
@@ -87,7 +129,8 @@ export type TableFooterProps = HTMLAttributes<HTMLTableSectionElement> & {
|
|
|
87
129
|
* scroll under it: to the page while the table fits its width (the
|
|
88
130
|
* sticky header then pins to the page's top too, under any sticky
|
|
89
131
|
* AppHeader, which covers it), or to the table's own region while the
|
|
90
|
-
* table scrolls sideways in it
|
|
132
|
+
* table scrolls sideways in it or is bounded (`Table maxHeight`), where
|
|
133
|
+
* it stays at the region's bottom. A sticky ActionBar covers a pinned
|
|
91
134
|
* footer, and so does a Dialog's pinned footer, so do not pair them.
|
|
92
135
|
*/
|
|
93
136
|
sticky?: boolean;
|
|
@@ -103,7 +146,8 @@ export declare const TableFooter: import("react").ForwardRefExoticComponent<HTML
|
|
|
103
146
|
* scroll under it: to the page while the table fits its width (the
|
|
104
147
|
* sticky header then pins to the page's top too, under any sticky
|
|
105
148
|
* AppHeader, which covers it), or to the table's own region while the
|
|
106
|
-
* table scrolls sideways in it
|
|
149
|
+
* table scrolls sideways in it or is bounded (`Table maxHeight`), where
|
|
150
|
+
* it stays at the region's bottom. A sticky ActionBar covers a pinned
|
|
107
151
|
* footer, and so does a Dialog's pinned footer, so do not pair them.
|
|
108
152
|
*/
|
|
109
153
|
sticky?: boolean;
|
package/dist/components/Table.js
CHANGED
|
@@ -3,15 +3,21 @@ import { forwardRef } from 'react';
|
|
|
3
3
|
import { cx } from '../class-names.js';
|
|
4
4
|
import { ScrollRegion } from './ScrollRegion.js';
|
|
5
5
|
import { assertTableLayout, assertTableStickyHeader, assertTableVerticalAlign, } from './table/table-layout.js';
|
|
6
|
+
import { assertTableMaxHeight, tableMaxHeightStyle, } from './table/table-max-height.js';
|
|
6
7
|
export { TableCell, } from './table/TableCell.js';
|
|
7
8
|
export { TableRow, } from './table/TableRow.js';
|
|
8
9
|
export { tableCellTones, tableRowVariants } from '../css/css-table-ledger.js';
|
|
9
|
-
/**
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* A wide table scrolls inside its own `ScrollRegion`, named after the
|
|
12
|
+
* table; a bounded one (`maxHeight`) scrolls its rows in it too.
|
|
13
|
+
*/
|
|
14
|
+
export const Table = forwardRef(function Table({ children, className, columnRules = false, density = 'comfortable', layout = 'auto', maxHeight, stickyHeader = true, verticalAlign = 'middle', ...rest }, ref) {
|
|
11
15
|
assertTableLayout(layout);
|
|
12
16
|
assertTableStickyHeader(stickyHeader);
|
|
13
17
|
assertTableVerticalAlign(verticalAlign);
|
|
14
|
-
|
|
18
|
+
assertTableMaxHeight(maxHeight, stickyHeader);
|
|
19
|
+
const bounded = maxHeight !== undefined;
|
|
20
|
+
return (_jsx(ScrollRegion, { "aria-label": rest['aria-label'], "aria-labelledby": rest['aria-labelledby'], className: cx('sw-table-wrap', bounded && 'sw-table-bounded'), markFits: !bounded, style: tableMaxHeightStyle(maxHeight), children: _jsx("table", { ref: ref, className: cx('sw-table', density === 'compact' && 'sw-table-compact', layout === 'fixed' && 'sw-table-fixed', stickyHeader !== false && 'sw-table-sticky', stickyHeader === 'page' && 'sw-table-sticky-page', verticalAlign === 'top' && 'sw-table-top', columnRules && 'sw-table-column-rules', className), ...rest, children: children }) }));
|
|
15
21
|
});
|
|
16
22
|
export const TableHeader = forwardRef(function TableHeader({ className, ...rest }, ref) {
|
|
17
23
|
return _jsx("thead", { ref: ref, className: className, ...rest });
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
import { type AccessibleName } from '../accessible-name.js';
|
|
2
3
|
export type TabItem = {
|
|
3
4
|
id: string;
|
|
4
5
|
label: ReactNode;
|
|
5
6
|
};
|
|
6
|
-
type
|
|
7
|
-
'aria-label': string;
|
|
8
|
-
'aria-labelledby'?: never;
|
|
9
|
-
} | {
|
|
10
|
-
'aria-label'?: never;
|
|
11
|
-
'aria-labelledby': string;
|
|
12
|
-
};
|
|
13
|
-
export type TabsProps = TabsLabel & {
|
|
7
|
+
export type TabsProps = AccessibleName & {
|
|
14
8
|
/** Prefix for the tab and panel ids, so a `TabPanel` can point back at its tab. */
|
|
15
9
|
id: string;
|
|
16
10
|
items: readonly TabItem[];
|
|
@@ -58,4 +52,3 @@ export type TabPanelProps = Omit<HTMLAttributes<HTMLDivElement>, 'id'> & {
|
|
|
58
52
|
};
|
|
59
53
|
/** The content of one tab, labelled by its tab and hidden while another tab is current. */
|
|
60
54
|
export declare function TabPanel({ children, className, id, tabsId, value, ...rest }: TabPanelProps): import("react").JSX.Element;
|
|
61
|
-
export {};
|
|
@@ -7,7 +7,10 @@ export type TableRowProps = HTMLAttributes<HTMLTableRowElement> & {
|
|
|
7
7
|
* `sub` sets the row under the one above it, as an item of a batch: its
|
|
8
8
|
* row header (`TableCell as="th" scope="row"`) is indented with a guide
|
|
9
9
|
* bar at the indent; a sub row without a row header is not indented.
|
|
10
|
-
* `
|
|
10
|
+
* `total` is a total mid-table, such as a subtotal the rows above add up
|
|
11
|
+
* to: its cells at weight 600 under a 2 px rule, as a
|
|
12
|
+
* `TableFooter` total is; name it with a row header and keep it in the
|
|
13
|
+
* body. `default` is a row of its own.
|
|
11
14
|
*/
|
|
12
15
|
variant?: TableRowVariant;
|
|
13
16
|
/**
|
|
@@ -40,7 +43,10 @@ export declare const TableRow: import("react").ForwardRefExoticComponent<HTMLAtt
|
|
|
40
43
|
* `sub` sets the row under the one above it, as an item of a batch: its
|
|
41
44
|
* row header (`TableCell as="th" scope="row"`) is indented with a guide
|
|
42
45
|
* bar at the indent; a sub row without a row header is not indented.
|
|
43
|
-
* `
|
|
46
|
+
* `total` is a total mid-table, such as a subtotal the rows above add up
|
|
47
|
+
* to: its cells at weight 600 under a 2 px rule, as a
|
|
48
|
+
* `TableFooter` total is; name it with a row header and keep it in the
|
|
49
|
+
* body. `default` is a row of its own.
|
|
44
50
|
*/
|
|
45
51
|
variant?: TableRowVariant;
|
|
46
52
|
/**
|
|
@@ -25,5 +25,5 @@ export const TableRow = forwardRef(function TableRow({ className, onClick, press
|
|
|
25
25
|
forwarding.current = false;
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
|
-
return (_jsx("tr", { ref: ref, "aria-selected": selected || undefined, className: cx(selected && 'sw-table-row-selected', variant === 'sub' && 'sw-table-row-sub', struck && 'sw-table-row-struck', pressable && 'sw-table-row-press', className), onClick: pressable || onClick ? press : undefined, ...rest }));
|
|
28
|
+
return (_jsx("tr", { ref: ref, "aria-selected": selected || undefined, className: cx(selected && 'sw-table-row-selected', variant === 'sub' && 'sw-table-row-sub', variant === 'total' && 'sw-table-row-total', struck && 'sw-table-row-struck', pressable && 'sw-table-row-press', className), onClick: pressable || onClick ? press : undefined, ...rest }));
|
|
29
29
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
2
|
+
import type { TableStickyHeader } from './table-layout.js';
|
|
3
|
+
/**
|
|
4
|
+
* A table's bounded height, counted in rows: the table's region is as tall
|
|
5
|
+
* as `rows` single-line body rows plus its header row and, when it has one,
|
|
6
|
+
* its footer row, and the rest of the rows scroll inside the region. Rows
|
|
7
|
+
* taller than one line show fewer at a time.
|
|
8
|
+
*/
|
|
9
|
+
export type TableMaxHeight = {
|
|
10
|
+
rows: number;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* A bounded table pins its header to its own region (`stickyHeader` true,
|
|
14
|
+
* the default); `'page'` and `false` contradict that and throw, as do a
|
|
15
|
+
* value that is not `{ rows }` and a row count that is not a whole number
|
|
16
|
+
* from 1.
|
|
17
|
+
*/
|
|
18
|
+
export declare function assertTableMaxHeight(maxHeight: TableMaxHeight | undefined, stickyHeader: TableStickyHeader): void;
|
|
19
|
+
/** The row count the generated `sw-table-bounded` height reads. */
|
|
20
|
+
export declare function tableMaxHeightStyle(maxHeight: TableMaxHeight | undefined): CSSProperties | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bounded table pins its header to its own region (`stickyHeader` true,
|
|
3
|
+
* the default); `'page'` and `false` contradict that and throw, as do a
|
|
4
|
+
* value that is not `{ rows }` and a row count that is not a whole number
|
|
5
|
+
* from 1.
|
|
6
|
+
*/
|
|
7
|
+
export function assertTableMaxHeight(maxHeight, stickyHeader) {
|
|
8
|
+
if (maxHeight === undefined)
|
|
9
|
+
return;
|
|
10
|
+
if (typeof maxHeight !== 'object' || maxHeight === null)
|
|
11
|
+
throw new RangeError(`Table maxHeight must be a row count, { rows }: ${String(maxHeight)}`);
|
|
12
|
+
const rows = maxHeight.rows;
|
|
13
|
+
if (typeof rows !== 'number' || !Number.isInteger(rows) || rows < 1)
|
|
14
|
+
throw new RangeError(`Table maxHeight rows must be a whole number from 1: ${String(rows)}`);
|
|
15
|
+
if (stickyHeader !== true)
|
|
16
|
+
throw new RangeError(`Table maxHeight pins the header to the table's own region; stickyHeader ${String(stickyHeader)} cannot be used with it`);
|
|
17
|
+
}
|
|
18
|
+
/** The row count the generated `sw-table-bounded` height reads. */
|
|
19
|
+
export function tableMaxHeightStyle(maxHeight) {
|
|
20
|
+
if (maxHeight === undefined)
|
|
21
|
+
return undefined;
|
|
22
|
+
return { '--sw-table-max-rows': maxHeight.rows };
|
|
23
|
+
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { type RefObject } from 'react';
|
|
2
|
-
import { type ScrollOverflow } from '../scroll-overflow.js';
|
|
3
|
-
/** A box's overflow, and whether it has been measured yet. */
|
|
4
|
-
export type MeasuredScrollOverflow = ScrollOverflow & {
|
|
2
|
+
import { type BlockScrollOverflow, type ScrollOverflow } from '../scroll-overflow.js';
|
|
3
|
+
/** A box's overflow on both axes, and whether it has been measured yet. */
|
|
4
|
+
export type MeasuredScrollOverflow = ScrollOverflow & BlockScrollOverflow & {
|
|
5
5
|
measured: boolean;
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
|
-
* Follows which
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* `measured: false`, so the box
|
|
12
|
-
* measured; a measured box with
|
|
8
|
+
* Follows which edges of a scroll box have more content past them, the
|
|
9
|
+
* inline start and end and the top and bottom: on mount, on every scroll,
|
|
10
|
+
* and whenever the box or its content changes size. Before mount (and on
|
|
11
|
+
* the server) it reports no overflow and `measured: false`, so the box
|
|
12
|
+
* renders as it always has until it is measured; a measured box with
|
|
13
|
+
* neither inline edge set fits its content's width. A box whose height
|
|
14
|
+
* follows its content never reports a block edge.
|
|
13
15
|
*/
|
|
14
16
|
export declare function useScrollOverflow(ref: RefObject<HTMLElement | null>): MeasuredScrollOverflow;
|