@hackcove/ui-react 0.9.0 → 0.9.2
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/README.md +18 -8
- package/dist/Avatar.d.ts +8 -4
- package/dist/Avatar.js +11 -3
- package/dist/AvatarStack.js +1 -0
- package/dist/Callout.d.ts +8 -2
- package/dist/Callout.js +3 -3
- package/dist/Card.d.ts +2 -0
- package/dist/Card.js +14 -8
- package/dist/CardParts.d.ts +6 -0
- package/dist/CardParts.js +6 -0
- package/dist/Cluster.d.ts +9 -4
- package/dist/Cluster.js +12 -5
- package/dist/Dialog.d.ts +4 -2
- package/dist/Dialog.js +9 -3
- package/dist/EmptyState.d.ts +7 -1
- package/dist/EmptyState.js +3 -2
- package/dist/Field.d.ts +8 -1
- package/dist/Field.js +4 -2
- package/dist/Image.d.ts +46 -0
- package/dist/Image.js +42 -0
- package/dist/KeyValueList.d.ts +4 -2
- package/dist/KeyValueList.js +3 -3
- package/dist/ListRow.d.ts +3 -1
- package/dist/ListRow.js +6 -6
- package/dist/MediaTile.d.ts +37 -0
- package/dist/MediaTile.js +19 -0
- package/dist/PageLayouts.d.ts +24 -22
- package/dist/PageLayouts.js +25 -21
- package/dist/Pill.d.ts +24 -6
- package/dist/Pill.js +72 -16
- package/dist/ScrollStrip.d.ts +21 -0
- package/dist/ScrollStrip.js +12 -0
- package/dist/SidebarLayout.d.ts +21 -0
- package/dist/SidebarLayout.js +18 -0
- package/dist/Stack.d.ts +15 -1
- package/dist/Stack.js +12 -2
- package/dist/StatTile.d.ts +2 -2
- package/dist/StatTile.js +2 -0
- package/dist/Table.d.ts +29 -12
- package/dist/Table.js +25 -11
- package/dist/TableEditCell.d.ts +19 -0
- package/dist/TableEditCell.js +58 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/size.d.ts +1 -1
- package/dist/stickyColumn.d.ts +17 -0
- package/dist/stickyColumn.js +17 -0
- package/dist/typography.d.ts +34 -10
- package/dist/typography.js +43 -13
- package/package.json +2 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
import type { Passthrough } from "./props.js";
|
|
3
|
+
/**
|
|
4
|
+
* A `rail` of links beside the `children` canvas, in the Container the shell already gives every
|
|
5
|
+
* page (a plain `<AppShell>`, no `bleed`): the rail starts at the header logo's x and the canvas
|
|
6
|
+
* ends at the header's right edge. The rail has no background and no border, so it is a list of
|
|
7
|
+
* links on the page; a `Tabs variant="pill" orientation="vertical"` is its content. From `md` it is `w-56` with
|
|
8
|
+
* the canvas filling the rest, and it stays in view under the shell's header as a long page scrolls;
|
|
9
|
+
* a rail taller than the screen scrolls itself, so its last link is reachable. Below `md` it stacks
|
|
10
|
+
* above the canvas and nothing sticks. A long rail sets `railLabel`:
|
|
11
|
+
* below `md` it then folds behind a disclosure of that name, closed, so the page comes first on a
|
|
12
|
+
* phone, and from `md` it is the same rail. Upgrading from 0.2: the rail no longer has a fill, a
|
|
13
|
+
* border or a fixed height, and it no longer sits beside the canvas on a phone.
|
|
14
|
+
*/
|
|
15
|
+
export declare function SidebarLayout({ rail, railLabel, children, ...rest }: {
|
|
16
|
+
/** The links beside the canvas, usually a `Tabs variant="pill" orientation="vertical"`. */
|
|
17
|
+
rail: ReactNode;
|
|
18
|
+
/** Folds the rail behind a disclosure with this name below `md` (a long rail). Left out, the rail is always open. */
|
|
19
|
+
railLabel?: string | undefined;
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
} & Passthrough): ReactElement;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cx, focusRing } from "./cx.js";
|
|
3
|
+
import { STICKY_ASIDE_MD, STICKY_SCROLL_MD } from "./stickyColumn.js";
|
|
4
|
+
/**
|
|
5
|
+
* A `rail` of links beside the `children` canvas, in the Container the shell already gives every
|
|
6
|
+
* page (a plain `<AppShell>`, no `bleed`): the rail starts at the header logo's x and the canvas
|
|
7
|
+
* ends at the header's right edge. The rail has no background and no border, so it is a list of
|
|
8
|
+
* links on the page; a `Tabs variant="pill" orientation="vertical"` is its content. From `md` it is `w-56` with
|
|
9
|
+
* the canvas filling the rest, and it stays in view under the shell's header as a long page scrolls;
|
|
10
|
+
* a rail taller than the screen scrolls itself, so its last link is reachable. Below `md` it stacks
|
|
11
|
+
* above the canvas and nothing sticks. A long rail sets `railLabel`:
|
|
12
|
+
* below `md` it then folds behind a disclosure of that name, closed, so the page comes first on a
|
|
13
|
+
* phone, and from `md` it is the same rail. Upgrading from 0.2: the rail no longer has a fill, a
|
|
14
|
+
* border or a fixed height, and it no longer sits beside the canvas on a phone.
|
|
15
|
+
*/
|
|
16
|
+
export function SidebarLayout({ rail, railLabel, children, ...rest }) {
|
|
17
|
+
return (_jsxs("div", { ...rest, className: "flex flex-col gap-8 md:flex-row md:gap-10", children: [_jsx("aside", { className: cx("w-full shrink-0 md:w-56", STICKY_ASIDE_MD), children: _jsx("div", { className: STICKY_SCROLL_MD, children: railLabel === undefined ? (rail) : (_jsxs("details", { className: "group md:[&::details-content]:[content-visibility:visible]", children: [_jsxs("summary", { className: cx("flex cursor-pointer list-none items-center justify-between rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm font-medium text-slate-900 select-none hover:bg-slate-50 md:hidden [&::-webkit-details-marker]:hidden", focusRing), children: [railLabel, _jsx("svg", { viewBox: "0 0 20 20", width: "16", height: "16", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: "shrink-0 text-slate-500 group-open:rotate-180", children: _jsx("path", { d: "M5 8l5 5 5-5" }) })] }), _jsx("div", { className: "mt-2 md:mt-0", children: rail })] })) }) }), _jsx("div", { className: "min-w-0 flex-1", children: children })] }));
|
|
18
|
+
}
|
package/dist/Stack.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ import { type ComponentPropsWithoutRef, type ReactElement, type ReactNode } from
|
|
|
2
2
|
import type { Passthrough, Unstyled } from "./props.js";
|
|
3
3
|
export type StackGap = "xs" | "sm" | "md" | "lg" | "xl";
|
|
4
4
|
export declare const STACK_GAP: Record<StackGap, string>;
|
|
5
|
+
export type StackRowFrom = "sm" | "md" | "lg";
|
|
6
|
+
/** The breakpoint where a `rowFrom` Stack turns from a column into a row. */
|
|
7
|
+
export declare const STACK_ROW_FROM: Record<StackRowFrom, string>;
|
|
5
8
|
export type StackWidth = "narrow" | "default" | "wide" | "full";
|
|
6
9
|
/** `default` adds nothing: the Stack is as wide as its parent. */
|
|
7
10
|
export declare const STACK_WIDTH: Record<StackWidth, string | undefined>;
|
|
@@ -14,12 +17,16 @@ export declare const STACK_WIDTH: Record<StackWidth, string | undefined>;
|
|
|
14
17
|
* is the parent's whole width and `default` sets nothing. A capped Stack starts at its parent's left
|
|
15
18
|
* edge (it is never re-centred), so its first line lines up with every other block on the page.
|
|
16
19
|
*
|
|
20
|
+
* `rowFrom` turns the column into a row from `sm`, `md` or `lg` (a column below it): the blocks sit
|
|
21
|
+
* side by side, `gap` apart, and a `ClusterGrow` around one of them takes the width left. Without it the
|
|
22
|
+
* Stack is always a column; a row that is a row at every width is a `Cluster`.
|
|
23
|
+
*
|
|
17
24
|
* `as` is a closed set: `div` (default), `section`, `form`, `ul` or `ol`. A `form` takes the form
|
|
18
25
|
* props (`onSubmit`, `action`, `method`, `noValidate`, ...). A `ul` or `ol` is drawn with no
|
|
19
26
|
* markers and its children are `<li>`s, as in `BulletList` and `Timeline`: the Stack does not wrap
|
|
20
27
|
* them, so a child is one list item and `Text as="li"` or a bare `<li>` both work.
|
|
21
28
|
*/
|
|
22
|
-
export declare function Stack({ gap, width, as, children, ...rest }: StackProps): ReactElement;
|
|
29
|
+
export declare function Stack({ gap, width, rowFrom, as, children, ...rest }: StackProps): ReactElement;
|
|
23
30
|
type StackBase = {
|
|
24
31
|
/**
|
|
25
32
|
* The space between blocks: `xs` gap-2, `sm` gap-4, `md` gap-6, `lg` gap-8, `xl` gap-12 (gap-16 from `sm`).
|
|
@@ -31,6 +38,13 @@ type StackBase = {
|
|
|
31
38
|
* @default default
|
|
32
39
|
*/
|
|
33
40
|
width?: StackWidth | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Turns the column into a row from this breakpoint (`sm`, `md` or `lg`), a column below it: a main
|
|
43
|
+
* area beside a side column on a wide screen, stacked on a phone. In the row the blocks sit side by side
|
|
44
|
+
* the same `gap` apart and are as tall as the tallest; wrap the one that takes the width left in a
|
|
45
|
+
* `ClusterGrow`. Left out, the Stack is always a column.
|
|
46
|
+
*/
|
|
47
|
+
rowFrom?: StackRowFrom | undefined;
|
|
34
48
|
children?: ReactNode;
|
|
35
49
|
};
|
|
36
50
|
type StackProps = StackBase & (({
|
package/dist/Stack.js
CHANGED
|
@@ -9,6 +9,12 @@ export const STACK_GAP = {
|
|
|
9
9
|
lg: "gap-8",
|
|
10
10
|
xl: "gap-12 sm:gap-16",
|
|
11
11
|
};
|
|
12
|
+
/** The breakpoint where a `rowFrom` Stack turns from a column into a row. */
|
|
13
|
+
export const STACK_ROW_FROM = {
|
|
14
|
+
sm: "sm:flex-row",
|
|
15
|
+
md: "md:flex-row",
|
|
16
|
+
lg: "lg:flex-row",
|
|
17
|
+
};
|
|
12
18
|
/** `default` adds nothing: the Stack is as wide as its parent. */
|
|
13
19
|
export const STACK_WIDTH = {
|
|
14
20
|
narrow: "max-w-3xl",
|
|
@@ -25,13 +31,17 @@ export const STACK_WIDTH = {
|
|
|
25
31
|
* is the parent's whole width and `default` sets nothing. A capped Stack starts at its parent's left
|
|
26
32
|
* edge (it is never re-centred), so its first line lines up with every other block on the page.
|
|
27
33
|
*
|
|
34
|
+
* `rowFrom` turns the column into a row from `sm`, `md` or `lg` (a column below it): the blocks sit
|
|
35
|
+
* side by side, `gap` apart, and a `ClusterGrow` around one of them takes the width left. Without it the
|
|
36
|
+
* Stack is always a column; a row that is a row at every width is a `Cluster`.
|
|
37
|
+
*
|
|
28
38
|
* `as` is a closed set: `div` (default), `section`, `form`, `ul` or `ol`. A `form` takes the form
|
|
29
39
|
* props (`onSubmit`, `action`, `method`, `noValidate`, ...). A `ul` or `ol` is drawn with no
|
|
30
40
|
* markers and its children are `<li>`s, as in `BulletList` and `Timeline`: the Stack does not wrap
|
|
31
41
|
* them, so a child is one list item and `Text as="li"` or a bare `<li>` both work.
|
|
32
42
|
*/
|
|
33
|
-
export function Stack({ gap = "md", width = "default", as = "div", children, ...rest }) {
|
|
34
|
-
return (_jsx(Box, { tag: as, className: cx("flex flex-col", (as === "ul" || as === "ol") && "list-none", STACK_GAP[gap], STACK_WIDTH[width], "*:data-page-header:mb-0"), ...rest, children: children }));
|
|
43
|
+
export function Stack({ gap = "md", width = "default", rowFrom, as = "div", children, ...rest }) {
|
|
44
|
+
return (_jsx(Box, { tag: as, className: cx("flex flex-col", (as === "ul" || as === "ol") && "list-none", rowFrom && STACK_ROW_FROM[rowFrom], STACK_GAP[gap], STACK_WIDTH[width], "*:data-page-header:mb-0"), ...rest, children: children }));
|
|
35
45
|
}
|
|
36
46
|
/** The element `as` picked, drawn with props already narrowed by `StackProps`. */
|
|
37
47
|
function Box({ tag: Tag, ...props }) {
|
package/dist/StatTile.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { HTMLAttributes, ReactElement, ReactNode } from "react";
|
|
2
2
|
import type { Unstyled } from "./props.js";
|
|
3
|
-
/** The colour of a tile's value (and of its accent bar): plain ink, green or red. */
|
|
4
|
-
export type StatTileTone = "neutral" | "positive" | "negative";
|
|
3
|
+
/** The colour of a tile's value (and of its accent bar): plain ink, green, amber or red. */
|
|
4
|
+
export type StatTileTone = "neutral" | "positive" | "warn" | "negative";
|
|
5
5
|
/**
|
|
6
6
|
* One headline figure: an uppercase caption over a large tabular-nums value, with an optional
|
|
7
7
|
* hint line beneath. `tone` colours the value; `accent` adds a bar across the top edge in the same
|
package/dist/StatTile.js
CHANGED
|
@@ -5,11 +5,13 @@ import { Overline } from "./typography.js";
|
|
|
5
5
|
const VALUE = {
|
|
6
6
|
neutral: "text-slate-900",
|
|
7
7
|
positive: "text-emerald-700",
|
|
8
|
+
warn: "text-amber-700",
|
|
8
9
|
negative: "text-red-700",
|
|
9
10
|
};
|
|
10
11
|
const BAR = {
|
|
11
12
|
neutral: BAR_FILL.accent,
|
|
12
13
|
positive: BAR_FILL.positive,
|
|
14
|
+
warn: BAR_FILL.warn,
|
|
13
15
|
negative: BAR_FILL.negative,
|
|
14
16
|
};
|
|
15
17
|
/**
|
package/dist/Table.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef, ReactElement, ReactNode } from "react";
|
|
2
2
|
import type { CalloutTone } from "./Callout.js";
|
|
3
3
|
import { type TextTone } from "./typography.js";
|
|
4
|
-
type Align = "start" | "end";
|
|
4
|
+
type Align = "start" | "center" | "end";
|
|
5
5
|
/**
|
|
6
6
|
* The text of a cell: its weight and colour. `default`, `strong` and `muted` are the plain ones; the
|
|
7
7
|
* rest are the Callout's tones, for an amount that carries a meaning (a gain, an overspend). Colour
|
|
@@ -15,17 +15,28 @@ type TableVariant = "card" | "plain";
|
|
|
15
15
|
* stripe takes the tone's text colour, which every theme already remaps, so no new palette entry.
|
|
16
16
|
*/
|
|
17
17
|
export type RowTone = "neutral" | "info" | "positive" | "warn" | "danger" | "muted";
|
|
18
|
-
/** The row's
|
|
18
|
+
/** The row's mark: a `tone` (stripe and fill, or faded), a `stripe` alone or `emphasis`, only one of them. */
|
|
19
19
|
type RowMark = {
|
|
20
|
-
/** The row's status: a stripe on the leading edge plus the tone's soft fill, or `muted` to fade the row. Give `tone
|
|
20
|
+
/** The row's status: a stripe on the leading edge plus the tone's soft fill, or `muted` to fade the row. Give only one of `tone`, `stripe` and `emphasis`. */
|
|
21
21
|
tone?: RowTone | undefined;
|
|
22
|
-
/** A stripe on the leading edge in this tone, with no fill. Give
|
|
22
|
+
/** A stripe on the leading edge in this tone, with no fill. Give only one of `tone`, `stripe` and `emphasis`. */
|
|
23
23
|
stripe?: undefined;
|
|
24
|
+
/** A subtotal in the body: the look of a `TableFoot` row, with strong cells, a firmer line above and no hover. Give only one of `tone`, `stripe` and `emphasis`. */
|
|
25
|
+
emphasis?: false | undefined;
|
|
24
26
|
} | {
|
|
25
|
-
/** A stripe on the leading edge in this tone, with no fill. Give
|
|
27
|
+
/** A stripe on the leading edge in this tone, with no fill. Give only one of `tone`, `stripe` and `emphasis`. */
|
|
26
28
|
stripe?: TextTone | undefined;
|
|
27
|
-
/** The row's status: a stripe on the leading edge plus the tone's soft fill, or `muted` to fade the row. Give `tone
|
|
29
|
+
/** The row's status: a stripe on the leading edge plus the tone's soft fill, or `muted` to fade the row. Give only one of `tone`, `stripe` and `emphasis`. */
|
|
28
30
|
tone?: undefined;
|
|
31
|
+
/** A subtotal in the body: the look of a `TableFoot` row, with strong cells, a firmer line above and no hover. Give only one of `tone`, `stripe` and `emphasis`. */
|
|
32
|
+
emphasis?: false | undefined;
|
|
33
|
+
} | {
|
|
34
|
+
/** A subtotal in the body: the look of a `TableFoot` row, with strong cells, a firmer line above and no hover. Give only one of `tone`, `stripe` and `emphasis`. */
|
|
35
|
+
emphasis: boolean;
|
|
36
|
+
/** The row's status: a stripe on the leading edge plus the tone's soft fill, or `muted` to fade the row. Give only one of `tone`, `stripe` and `emphasis`. */
|
|
37
|
+
tone?: undefined;
|
|
38
|
+
/** A stripe on the leading edge in this tone, with no fill. Give only one of `tone`, `stripe` and `emphasis`. */
|
|
39
|
+
stripe?: undefined;
|
|
29
40
|
};
|
|
30
41
|
/** What an element passes through (`data-*`, `aria-*`, `id`, …): the layout and the children stay the component's. */
|
|
31
42
|
type Rest<Tag extends "table" | "thead" | "tbody" | "tfoot" | "tr" | "th" | "td", Own extends string = never> = Omit<ComponentPropsWithoutRef<Tag>, "className" | "style" | "children" | Own>;
|
|
@@ -73,9 +84,10 @@ export declare function TableFoot({ children, ...rest }: {
|
|
|
73
84
|
* linked row's link, not a hover fill, says it is clickable. `stripe` is the stripe alone, in the
|
|
74
85
|
* `TextTone` colours (the first five names of a `StackedBar` segment's `VizTone`), with no fill: the row keeps its hover
|
|
75
86
|
* and its own look. Give `tone` or `stripe`, not both. Body rows only; colour alone does not say it,
|
|
76
|
-
* so name the status in a cell too (a `Pill`). A bold subtotal is not a tone:
|
|
87
|
+
* so name the status in a cell too (a `Pill`). A bold subtotal is not a tone: a total of the whole
|
|
88
|
+
* table is a `TableFoot` row, and a subtotal among the body's rows is `emphasis`, the same look.
|
|
77
89
|
*/
|
|
78
|
-
export declare function TableRow({ tone, stripe, children, ...rest }: RowMark & {
|
|
90
|
+
export declare function TableRow({ tone, stripe, emphasis, children, ...rest }: RowMark & {
|
|
79
91
|
children: ReactNode;
|
|
80
92
|
} & Rest<"tr">): ReactElement;
|
|
81
93
|
/**
|
|
@@ -99,7 +111,7 @@ export declare function TableGroupRow({ label, trailing, colSpan, ...rest }: {
|
|
|
99
111
|
*/
|
|
100
112
|
export declare function TableHeaderCell({ align, children, srLabel, ...rest }: {
|
|
101
113
|
/**
|
|
102
|
-
* The cell's horizontal alignment; `end` for figures.
|
|
114
|
+
* The cell's horizontal alignment; `end` for figures, `center` over a centred column.
|
|
103
115
|
* @default start
|
|
104
116
|
*/
|
|
105
117
|
align?: Align | undefined;
|
|
@@ -111,6 +123,8 @@ export declare function TableHeaderCell({ align, children, srLabel, ...rest }: {
|
|
|
111
123
|
/** The column's name for a screen reader, visually hidden, for a column with no visible title (a row's actions). */
|
|
112
124
|
srLabel: string;
|
|
113
125
|
}) & Rest<"th", "align" | "scope">): ReactElement;
|
|
126
|
+
/** A step of a hierarchy under a row: the cell's own `pl-4` plus 1rem a level. */
|
|
127
|
+
type Indent = 1 | 2 | 3;
|
|
114
128
|
/**
|
|
115
129
|
* A `<td>`. `tone` is the text weight and colour (see `CellTone`; in a `TableFoot` it defaults to
|
|
116
130
|
* `strong`); `numeric` sets tabular figures, `mono` a small mono face. `secondary` is a second,
|
|
@@ -119,14 +133,17 @@ export declare function TableHeaderCell({ align, children, srLabel, ...rest }: {
|
|
|
119
133
|
* cell (a figure, a code, a type) never breaks. `truncate` caps a long value's width, cuts it with
|
|
120
134
|
* an ellipsis on one line and puts the full text in a `title`; the content is then plain text (strings and
|
|
121
135
|
* numbers), since that is what the title shows. `colSpan` passes through: a cell that
|
|
122
|
-
* spans the row is a full-width panel (an empty state, a note under a group)
|
|
136
|
+
* spans the row is a full-width panel (an empty state, a note under a group), and `align="center"`
|
|
137
|
+
* centres it. `indent` sets a start-aligned cell in by 1 to 3 levels, for a line under a parent row.
|
|
123
138
|
*/
|
|
124
|
-
export declare function TableCell({ align, tone, numeric, mono, truncate, secondary, children, ...rest }: {
|
|
139
|
+
export declare function TableCell({ align, tone, numeric, mono, truncate, indent, secondary, children, ...rest }: {
|
|
125
140
|
/**
|
|
126
|
-
* The cell's horizontal alignment; `end` for figures.
|
|
141
|
+
* The cell's horizontal alignment; `end` for figures, `center` for a full-width note or empty state.
|
|
127
142
|
* @default start
|
|
128
143
|
*/
|
|
129
144
|
align?: Align | undefined;
|
|
145
|
+
/** Sets the cell in by this many levels (1 to 3), for a line under a parent row. Start-aligned cells only. */
|
|
146
|
+
indent?: Indent | undefined;
|
|
130
147
|
/** The text weight and colour (see `CellTone`). In a `TableFoot` it defaults to `strong`. */
|
|
131
148
|
tone?: CellTone | undefined;
|
|
132
149
|
/** Tabular figures, and the cell never wraps. */
|
package/dist/Table.js
CHANGED
|
@@ -2,7 +2,11 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { Children, createContext, useContext } from "react";
|
|
3
3
|
import { cx, liftInteractive } from "./cx.js";
|
|
4
4
|
import { TEXT_TONE } from "./typography.js";
|
|
5
|
-
const ALIGN = {
|
|
5
|
+
const ALIGN = {
|
|
6
|
+
start: "text-left",
|
|
7
|
+
center: "text-center",
|
|
8
|
+
end: "text-right",
|
|
9
|
+
};
|
|
6
10
|
const TONE = {
|
|
7
11
|
default: "text-slate-700",
|
|
8
12
|
strong: "font-medium text-slate-900",
|
|
@@ -62,12 +66,14 @@ export function TableFoot({ children, ...rest }) {
|
|
|
62
66
|
* linked row's link, not a hover fill, says it is clickable. `stripe` is the stripe alone, in the
|
|
63
67
|
* `TextTone` colours (the first five names of a `StackedBar` segment's `VizTone`), with no fill: the row keeps its hover
|
|
64
68
|
* and its own look. Give `tone` or `stripe`, not both. Body rows only; colour alone does not say it,
|
|
65
|
-
* so name the status in a cell too (a `Pill`). A bold subtotal is not a tone:
|
|
69
|
+
* so name the status in a cell too (a `Pill`). A bold subtotal is not a tone: a total of the whole
|
|
70
|
+
* table is a `TableFoot` row, and a subtotal among the body's rows is `emphasis`, the same look.
|
|
66
71
|
*/
|
|
67
|
-
export function TableRow({ tone, stripe, children, ...rest }) {
|
|
68
|
-
const
|
|
72
|
+
export function TableRow({ tone, stripe, emphasis = false, children, ...rest }) {
|
|
73
|
+
const outer = useContext(SectionContext);
|
|
69
74
|
const plain = useContext(VariantContext) === "plain";
|
|
70
|
-
|
|
75
|
+
const section = emphasis && outer === "body" ? "foot" : outer;
|
|
76
|
+
return (_jsx(SectionContext.Provider, { value: section, children: _jsx("tr", { ...rest, className: rowClass(section, plain, tone, stripe), children: children }) }));
|
|
71
77
|
}
|
|
72
78
|
/** The classes of a row: a line above in the body and the foot, the hover fill and the tone's or stripe's look in the body only. */
|
|
73
79
|
function rowClass(section, plain, tone, stripe) {
|
|
@@ -110,6 +116,13 @@ function figureClass(numeric, mono) {
|
|
|
110
116
|
}
|
|
111
117
|
/** The widest a `truncate` cell grows. */
|
|
112
118
|
const TRUNCATE_WIDTH = "max-w-xs";
|
|
119
|
+
/** Where a `truncate` cell's capped box sits, so it follows the cell's alignment. */
|
|
120
|
+
const TRUNCATE_ALIGN = {
|
|
121
|
+
start: undefined,
|
|
122
|
+
center: "mx-auto",
|
|
123
|
+
end: "ml-auto",
|
|
124
|
+
};
|
|
125
|
+
const INDENT = { 1: "pl-8", 2: "pl-12", 3: "pl-16" };
|
|
113
126
|
/**
|
|
114
127
|
* A `<td>`. `tone` is the text weight and colour (see `CellTone`; in a `TableFoot` it defaults to
|
|
115
128
|
* `strong`); `numeric` sets tabular figures, `mono` a small mono face. `secondary` is a second,
|
|
@@ -118,21 +131,22 @@ const TRUNCATE_WIDTH = "max-w-xs";
|
|
|
118
131
|
* cell (a figure, a code, a type) never breaks. `truncate` caps a long value's width, cuts it with
|
|
119
132
|
* an ellipsis on one line and puts the full text in a `title`; the content is then plain text (strings and
|
|
120
133
|
* numbers), since that is what the title shows. `colSpan` passes through: a cell that
|
|
121
|
-
* spans the row is a full-width panel (an empty state, a note under a group)
|
|
134
|
+
* spans the row is a full-width panel (an empty state, a note under a group), and `align="center"`
|
|
135
|
+
* centres it. `indent` sets a start-aligned cell in by 1 to 3 levels, for a line under a parent row.
|
|
122
136
|
*/
|
|
123
|
-
export function TableCell({ align = "start", tone, numeric = false, mono = false, truncate = false, secondary, children, ...rest }) {
|
|
137
|
+
export function TableCell({ align = "start", tone, numeric = false, mono = false, truncate = false, indent, secondary, children, ...rest }) {
|
|
124
138
|
const foot = useContext(SectionContext) === "foot";
|
|
125
|
-
return (_jsx("td", { ...rest, className: cellClass({ align, tone, foot, numeric, mono }), children: _jsx(CellBody, { align: align, truncate: truncate, secondary: secondary, children: children }) }));
|
|
139
|
+
return (_jsx("td", { ...rest, className: cellClass({ align, indent, tone, foot, numeric, mono }), children: _jsx(CellBody, { align: align, truncate: truncate, secondary: secondary, children: children }) }));
|
|
126
140
|
}
|
|
127
141
|
/** The classes of a cell: the tone (`strong` by default in a foot, and a foot's cells are medium whatever the tone), then the wrapping rule. */
|
|
128
|
-
function cellClass({ align, tone, foot, numeric, mono, }) {
|
|
142
|
+
function cellClass({ align, indent, tone, foot, numeric, mono, }) {
|
|
129
143
|
const resolved = tone ?? (foot ? "strong" : "default");
|
|
130
|
-
return cx("px-4 py-3", ALIGN[align], TONE[resolved], foot && resolved !== "strong" && "font-medium", figureClass(numeric, mono));
|
|
144
|
+
return cx("px-4 py-3", align === "start" && indent !== undefined && INDENT[indent], ALIGN[align], TONE[resolved], foot && resolved !== "strong" && "font-medium", figureClass(numeric, mono));
|
|
131
145
|
}
|
|
132
146
|
const isText = (node) => typeof node === "string" || typeof node === "number";
|
|
133
147
|
/** What a cell holds: the content, cut to one line with its full text in a `title` when `truncate`, then the `secondary` line. */
|
|
134
148
|
function CellBody({ align, truncate, secondary, children, }) {
|
|
135
149
|
const parts = Children.toArray(children);
|
|
136
150
|
const text = parts.every(isText) ? parts.join("") : undefined;
|
|
137
|
-
return (_jsxs(_Fragment, { children: [truncate ? (_jsx("div", { className: cx(TRUNCATE_WIDTH, "truncate", align
|
|
151
|
+
return (_jsxs(_Fragment, { children: [truncate ? (_jsx("div", { className: cx(TRUNCATE_WIDTH, "truncate", TRUNCATE_ALIGN[align]), title: text, children: children })) : (children), secondary != null && secondary !== false && (_jsx("div", { className: "text-xs font-normal text-slate-500", children: secondary }))] }));
|
|
138
152
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ComponentProps, ReactElement, ReactNode } from "react";
|
|
2
|
+
import { TableCell } from "./Table.js";
|
|
3
|
+
/**
|
|
4
|
+
* A `TableCell` whose value opens an editor in place. It shows `children` as a button with a dotted
|
|
5
|
+
* underline; a click, Enter or Space swaps it for `renderEditor(close)` and moves the focus into the
|
|
6
|
+
* editor. The cell keeps its own open state. The editor calls `close` when it has saved, and Esc
|
|
7
|
+
* closes it: both put the focus back on the value. A press outside it or Tab out of it closes it too and leaves the
|
|
8
|
+
* focus where it went, so the editor saves its value on its own change or submit, never on a close.
|
|
9
|
+
* Put the control in the cell itself, not in a popover of its own, which counts as outside. Takes
|
|
10
|
+
* `TableCell`'s `align`, `tone`, `numeric`, `mono`, `indent` and `secondary`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function TableEditCell({ label, renderEditor, children, ...cell }: {
|
|
13
|
+
/** What the button does, for a screen reader, heard after the value: "Edit category". It also names the editor. */
|
|
14
|
+
label: string;
|
|
15
|
+
/** The control that edits the value, drawn while open. `close` shuts it and returns the focus to the value. */
|
|
16
|
+
renderEditor: (close: () => void) => ReactNode;
|
|
17
|
+
/** The value, shown while closed. */
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
} & Omit<ComponentProps<typeof TableCell>, "children" | "truncate">): ReactElement;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { cx, focusRing } from "./cx.js";
|
|
4
|
+
import { TableCell } from "./Table.js";
|
|
5
|
+
/** What takes the focus when the editor opens, unless the editor already took it (`autoFocus`). */
|
|
6
|
+
const FOCUSABLE = "input, select, textarea, button, a[href]";
|
|
7
|
+
/** Whether `target` is a node outside `box`. */
|
|
8
|
+
function isOutside(box, target) {
|
|
9
|
+
return target instanceof Node && box !== null && !box.contains(target);
|
|
10
|
+
}
|
|
11
|
+
/** Closes the editor when a press lands outside `box`, for as long as `open`. */
|
|
12
|
+
function useDismissOnOutsidePress(box, open, dismiss) {
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!open)
|
|
15
|
+
return undefined;
|
|
16
|
+
const onPress = (event) => {
|
|
17
|
+
if (isOutside(box.current, event.target))
|
|
18
|
+
dismiss();
|
|
19
|
+
};
|
|
20
|
+
document.addEventListener("pointerdown", onPress);
|
|
21
|
+
return () => document.removeEventListener("pointerdown", onPress);
|
|
22
|
+
}, [box, open, dismiss]);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A `TableCell` whose value opens an editor in place. It shows `children` as a button with a dotted
|
|
26
|
+
* underline; a click, Enter or Space swaps it for `renderEditor(close)` and moves the focus into the
|
|
27
|
+
* editor. The cell keeps its own open state. The editor calls `close` when it has saved, and Esc
|
|
28
|
+
* closes it: both put the focus back on the value. A press outside it or Tab out of it closes it too and leaves the
|
|
29
|
+
* focus where it went, so the editor saves its value on its own change or submit, never on a close.
|
|
30
|
+
* Put the control in the cell itself, not in a popover of its own, which counts as outside. Takes
|
|
31
|
+
* `TableCell`'s `align`, `tone`, `numeric`, `mono`, `indent` and `secondary`.
|
|
32
|
+
*/
|
|
33
|
+
export function TableEditCell({ label, renderEditor, children, ...cell }) {
|
|
34
|
+
const [phase, setPhase] = useState("closed");
|
|
35
|
+
const open = phase === "open";
|
|
36
|
+
const box = useRef(null);
|
|
37
|
+
const trigger = useRef(null);
|
|
38
|
+
const dismiss = useCallback(() => setPhase("closed"), []);
|
|
39
|
+
const close = () => setPhase("returning");
|
|
40
|
+
useDismissOnOutsidePress(box, open, dismiss);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (phase === "returning")
|
|
43
|
+
trigger.current?.focus();
|
|
44
|
+
if (phase === "open" && !box.current?.contains(document.activeElement))
|
|
45
|
+
box.current?.querySelector(FOCUSABLE)?.focus();
|
|
46
|
+
}, [phase]);
|
|
47
|
+
const onKeyDown = (event) => {
|
|
48
|
+
if (event.key !== "Escape")
|
|
49
|
+
return;
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
event.stopPropagation();
|
|
52
|
+
close();
|
|
53
|
+
};
|
|
54
|
+
return (_jsx(TableCell, { ...cell, children: open ? (_jsx("div", { ref: box, role: "group", "aria-label": label, className: "-mx-2 -my-1", onKeyDown: onKeyDown, onBlur: (event) => {
|
|
55
|
+
if (isOutside(event.currentTarget, event.relatedTarget))
|
|
56
|
+
dismiss();
|
|
57
|
+
}, children: renderEditor(close) })) : (_jsxs("button", { ref: trigger, type: "button", onClick: () => setPhase("open"), className: cx("-mx-2 -my-1 block w-[calc(100%+1rem)] cursor-pointer rounded-md px-2 py-1 [text-align:inherit] underline decoration-dotted underline-offset-4 transition hover:bg-slate-100", focusRing), children: [children, _jsxs("span", { className: "sr-only", children: [" ", label] })] })) }));
|
|
58
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,8 @@ export { Markdown } from "./Markdown.js";
|
|
|
10
10
|
export { AppShell, AppShellBrand, type AppShellBreakpoint, AppShellHideBelow, appShellRootClassFor, } from "./AppShell.js";
|
|
11
11
|
export { Container } from "./Container.js";
|
|
12
12
|
export { PageHeader, type PageHeaderProps } from "./PageHeader.js";
|
|
13
|
-
export { CardGrid, CenteredLayout, DetailLayout, FormLayout, FullBleedLayout, ListLayout, ProseLayout,
|
|
13
|
+
export { CardGrid, CenteredLayout, DetailLayout, FormLayout, FullBleedLayout, ListLayout, ProseLayout, } from "./PageLayouts.js";
|
|
14
|
+
export { SidebarLayout } from "./SidebarLayout.js";
|
|
14
15
|
export { StickyBar } from "./StickyBar.js";
|
|
15
16
|
export { ErrorPage, Forbidden, Maintenance, NotFound, Offline } from "./StatusPages.js";
|
|
16
17
|
export { Cluster, ClusterGrow, type ClusterAlign, type ClusterGap, type ClusterJustify, } from "./Cluster.js";
|
|
@@ -26,6 +27,7 @@ export { Callout, type CalloutTone } from "./Callout.js";
|
|
|
26
27
|
export { ListRow, type ListRowProps } from "./ListRow.js";
|
|
27
28
|
export { OutlineRegion, RegionFrame, type RegionRect } from "./OutlineRegion.js";
|
|
28
29
|
export { type CellTone, type RowTone, Table, TableBody, TableCell, TableFoot, TableGroupRow, TableHead, TableHeaderCell, TableRow, } from "./Table.js";
|
|
30
|
+
export { TableEditCell } from "./TableEditCell.js";
|
|
29
31
|
export { EmptyState } from "./EmptyState.js";
|
|
30
32
|
export { Step, Steps } from "./Steps.js";
|
|
31
33
|
export { Timeline, TimelineItem } from "./Timeline.js";
|
|
@@ -64,6 +66,9 @@ export { KeyValue, KeyValueList } from "./KeyValueList.js";
|
|
|
64
66
|
export { Select } from "./Select.js";
|
|
65
67
|
export { Textarea } from "./Textarea.js";
|
|
66
68
|
export { Video } from "./Video.js";
|
|
69
|
+
export { Image, type ImageAspect, type ImageProps, type ImageWidth } from "./Image.js";
|
|
70
|
+
export { MediaTile, type MediaTileProps } from "./MediaTile.js";
|
|
71
|
+
export { ScrollStrip, type ScrollStripProps } from "./ScrollStrip.js";
|
|
67
72
|
export { TextLink, type TextLinkSize } from "./TextLink.js";
|
|
68
73
|
export { Caption, Display, Lead, Overline, PageHeading, SectionHeading, SubsectionHeading, type SubsectionHeadingSize, Text, type TextTone, type TypographyColor, type TypographyProps, } from "./typography.js";
|
|
69
74
|
export { DateField, type DateFieldProps } from "./DateField.js";
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,8 @@ export { Markdown } from "./Markdown.js";
|
|
|
10
10
|
export { AppShell, AppShellBrand, AppShellHideBelow, appShellRootClassFor, } from "./AppShell.js";
|
|
11
11
|
export { Container } from "./Container.js";
|
|
12
12
|
export { PageHeader } from "./PageHeader.js";
|
|
13
|
-
export { CardGrid, CenteredLayout, DetailLayout, FormLayout, FullBleedLayout, ListLayout, ProseLayout,
|
|
13
|
+
export { CardGrid, CenteredLayout, DetailLayout, FormLayout, FullBleedLayout, ListLayout, ProseLayout, } from "./PageLayouts.js";
|
|
14
|
+
export { SidebarLayout } from "./SidebarLayout.js";
|
|
14
15
|
export { StickyBar } from "./StickyBar.js";
|
|
15
16
|
export { ErrorPage, Forbidden, Maintenance, NotFound, Offline } from "./StatusPages.js";
|
|
16
17
|
export { Cluster, ClusterGrow, } from "./Cluster.js";
|
|
@@ -26,6 +27,7 @@ export { Callout } from "./Callout.js";
|
|
|
26
27
|
export { ListRow } from "./ListRow.js";
|
|
27
28
|
export { OutlineRegion, RegionFrame } from "./OutlineRegion.js";
|
|
28
29
|
export { Table, TableBody, TableCell, TableFoot, TableGroupRow, TableHead, TableHeaderCell, TableRow, } from "./Table.js";
|
|
30
|
+
export { TableEditCell } from "./TableEditCell.js";
|
|
29
31
|
export { EmptyState } from "./EmptyState.js";
|
|
30
32
|
export { Step, Steps } from "./Steps.js";
|
|
31
33
|
export { Timeline, TimelineItem } from "./Timeline.js";
|
|
@@ -60,6 +62,9 @@ export { KeyValue, KeyValueList } from "./KeyValueList.js";
|
|
|
60
62
|
export { Select } from "./Select.js";
|
|
61
63
|
export { Textarea } from "./Textarea.js";
|
|
62
64
|
export { Video } from "./Video.js";
|
|
65
|
+
export { Image } from "./Image.js";
|
|
66
|
+
export { MediaTile } from "./MediaTile.js";
|
|
67
|
+
export { ScrollStrip } from "./ScrollStrip.js";
|
|
63
68
|
export { TextLink } from "./TextLink.js";
|
|
64
69
|
export { Caption, Display, Lead, Overline, PageHeading, SectionHeading, SubsectionHeading, Text, } from "./typography.js";
|
|
65
70
|
export { DateField } from "./DateField.js";
|
package/dist/size.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The one size scale of the library: `sm`, `md` (the default everywhere) and `lg`. A component
|
|
3
|
-
* extends it outward only where it has a real use (Avatar's `xl` and `2xl`, the gap scale's `xs`
|
|
3
|
+
* extends it outward only where it has a real use (Avatar's `xs`, `xl` and `2xl`, the gap scale's `xs`
|
|
4
4
|
* and `xl`), and no scale skips `md`.
|
|
5
5
|
*/
|
|
6
6
|
export type Size = "sm" | "md" | "lg";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A column that stays in view as the page scrolls (`SidebarLayout`'s rail from `md`, `DetailLayout`'s
|
|
3
|
+
* aside from `lg` when asked). The `<aside>` sticks directly under AppShell's header (`--app-header`,
|
|
4
|
+
* as `StickyBar` does; 0 outside a shell) and is as tall as its content. A sticky `top` also pushes a
|
|
5
|
+
* column that starts above it down, so it is exactly the header and no gap: a gap would move a rail
|
|
6
|
+
* rendered at the top of its box. Inside it the scroller is capped at the viewport less the header
|
|
7
|
+
* and 2rem (the room the Container's `py-8` leaves at the page's end, so the column is never pushed
|
|
8
|
+
* up under the header there), so a column taller than that scrolls itself and its end stays
|
|
9
|
+
* reachable. `overflow` clips, which would cut a keyboard focus ring (an outline 4px out) at the
|
|
10
|
+
* scroller's edges, so it is padded 4px (`p-1`) and pulled back out by the same (`-m-1`): the ring
|
|
11
|
+
* has room and the column stays on the page's edges. Each variant is written out whole, so Tailwind
|
|
12
|
+
* sees every class.
|
|
13
|
+
*/
|
|
14
|
+
export declare const STICKY_ASIDE_MD = "md:sticky md:top-[var(--app-header,0px)] md:self-start";
|
|
15
|
+
export declare const STICKY_SCROLL_MD = "md:-m-1 md:max-h-[calc(100dvh-var(--app-header,0px)-2rem)] md:overflow-y-auto md:p-1";
|
|
16
|
+
export declare const STICKY_ASIDE_LG = "lg:sticky lg:top-[var(--app-header,0px)] lg:self-start";
|
|
17
|
+
export declare const STICKY_SCROLL_LG = "lg:-m-1 lg:max-h-[calc(100dvh-var(--app-header,0px)-2rem)] lg:overflow-y-auto lg:p-1";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A column that stays in view as the page scrolls (`SidebarLayout`'s rail from `md`, `DetailLayout`'s
|
|
3
|
+
* aside from `lg` when asked). The `<aside>` sticks directly under AppShell's header (`--app-header`,
|
|
4
|
+
* as `StickyBar` does; 0 outside a shell) and is as tall as its content. A sticky `top` also pushes a
|
|
5
|
+
* column that starts above it down, so it is exactly the header and no gap: a gap would move a rail
|
|
6
|
+
* rendered at the top of its box. Inside it the scroller is capped at the viewport less the header
|
|
7
|
+
* and 2rem (the room the Container's `py-8` leaves at the page's end, so the column is never pushed
|
|
8
|
+
* up under the header there), so a column taller than that scrolls itself and its end stays
|
|
9
|
+
* reachable. `overflow` clips, which would cut a keyboard focus ring (an outline 4px out) at the
|
|
10
|
+
* scroller's edges, so it is padded 4px (`p-1`) and pulled back out by the same (`-m-1`): the ring
|
|
11
|
+
* has room and the column stays on the page's edges. Each variant is written out whole, so Tailwind
|
|
12
|
+
* sees every class.
|
|
13
|
+
*/
|
|
14
|
+
export const STICKY_ASIDE_MD = "md:sticky md:top-[var(--app-header,0px)] md:self-start";
|
|
15
|
+
export const STICKY_SCROLL_MD = "md:-m-1 md:max-h-[calc(100dvh-var(--app-header,0px)-2rem)] md:overflow-y-auto md:p-1";
|
|
16
|
+
export const STICKY_ASIDE_LG = "lg:sticky lg:top-[var(--app-header,0px)] lg:self-start";
|
|
17
|
+
export const STICKY_SCROLL_LG = "lg:-m-1 lg:max-h-[calc(100dvh-var(--app-header,0px)-2rem)] lg:overflow-y-auto lg:p-1";
|
package/dist/typography.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ type OwnProps = {
|
|
|
15
15
|
color?: TypographyColor;
|
|
16
16
|
children?: ReactNode;
|
|
17
17
|
};
|
|
18
|
+
/** Where a run of text sits across its block. */
|
|
19
|
+
export type TextAlign = "start" | "center" | "end";
|
|
18
20
|
/** The opt-in props of the inline roles (`Text`, `Caption`, `Overline`). */
|
|
19
21
|
type InlineOwnProps = {
|
|
20
22
|
/** A meaning's colour (see `TextTone`). Wins over `color`. */
|
|
@@ -25,6 +27,18 @@ type InlineOwnProps = {
|
|
|
25
27
|
mono?: boolean | undefined;
|
|
26
28
|
/** One line, cut with an ellipsis where the container ends; the full text is the `title`. */
|
|
27
29
|
truncate?: boolean | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Set the text at `start`, `center` or `end` of its block. The run becomes block-level, so the
|
|
32
|
+
* alignment has a box to act on (a table header cell, a right-hand column).
|
|
33
|
+
*/
|
|
34
|
+
align?: TextAlign | undefined;
|
|
35
|
+
};
|
|
36
|
+
/** The opt-in props of `Text` and `Caption` only: the face of the run, not a label's. */
|
|
37
|
+
type RunOwnProps = {
|
|
38
|
+
/** Italic: a muted hint or a caption. */
|
|
39
|
+
italic?: boolean | undefined;
|
|
40
|
+
/** Break a long unbroken string (a URL, a token) where the container ends, instead of overflowing. */
|
|
41
|
+
breakWords?: boolean | undefined;
|
|
28
42
|
};
|
|
29
43
|
type Own = OwnProps & InlineOwnProps;
|
|
30
44
|
/** Polymorphic props: own props + `as` + the intrinsic props of whichever element `as` selects. */
|
|
@@ -66,11 +80,14 @@ export declare const PageHeading: {
|
|
|
66
80
|
/**
|
|
67
81
|
* Top-level section header. `h2`, text-base/6 semibold, primary text. `rule` sets
|
|
68
82
|
* a hairline under it (the `Divider` line colour) with the space either side of
|
|
69
|
-
* the line built in.
|
|
83
|
+
* the line built in. `description` is a muted line under the heading, outside the `<h2>`, so the
|
|
84
|
+
* heading's name stays the title; the rule then sits under the description.
|
|
70
85
|
*/
|
|
71
|
-
export declare function SectionHeading<E extends ElementType = "h2">({ rule, ...props }: TypographyProps<E> & {
|
|
86
|
+
export declare function SectionHeading<E extends ElementType = "h2">({ rule, description, ...props }: TypographyProps<E> & {
|
|
72
87
|
/** A hairline under the heading, with the space either side of it built in. */
|
|
73
88
|
rule?: boolean;
|
|
89
|
+
/** A muted line under the heading that says more. It is a paragraph beside the heading, not part of its name. */
|
|
90
|
+
description?: ReactNode;
|
|
74
91
|
}): ReactElement;
|
|
75
92
|
export type SubsectionHeadingSize = Size;
|
|
76
93
|
/**
|
|
@@ -89,12 +106,14 @@ export declare function SubsectionHeading<E extends ElementType = "h3">({ size,
|
|
|
89
106
|
}): ReactElement;
|
|
90
107
|
/**
|
|
91
108
|
* Small all-caps label above a group. `span`, text-xs semibold uppercase, tertiary. `tone`,
|
|
92
|
-
* `numeric`, `mono` and `
|
|
109
|
+
* `numeric`, `mono`, `truncate` and `align` are opt-in, as on `Text`.
|
|
93
110
|
*/
|
|
94
111
|
export declare const Overline: {
|
|
95
112
|
<E extends ElementType = "span">(props: InlineTypographyProps<E>): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
96
113
|
displayName: string;
|
|
97
114
|
};
|
|
115
|
+
/** A fixed width for a run of text: `amount` is a money figure, right-aligned, at a width that lines a column up. */
|
|
116
|
+
export type TextMinWidth = "amount";
|
|
98
117
|
/**
|
|
99
118
|
* Running text. `span` (inline; `as="p"` for a paragraph), text-sm/5 normal, secondary. A block of it
|
|
100
119
|
* stops at a readable line length (`max-w-[72ch]`), wherever it sits. `strong` emphasises it:
|
|
@@ -102,13 +121,17 @@ export declare const Overline: {
|
|
|
102
121
|
* `preserveNewlines` keeps the line breaks in the text (a user-typed note); runs of spaces still collapse.
|
|
103
122
|
* `tone` colours it by meaning (`positive` for "Saved.", `danger` for an error; it wins over `color`),
|
|
104
123
|
* `numeric` sets tabular figures, `mono` the monospace face, and `truncate` cuts it to one line with an
|
|
105
|
-
* ellipsis (the full text becomes its `title`).
|
|
124
|
+
* ellipsis (the full text becomes its `title`). `align` sets it at `start`, `center` or `end`.
|
|
125
|
+
* `italic` slants it, `breakWords` breaks a long unbroken string at the edge of its box, and `minWidth="amount"`
|
|
126
|
+
* fixes a width and right-aligns the figure in it (a column of amounts lines up); it does not take `align`.
|
|
106
127
|
*/
|
|
107
|
-
export declare function Text<E extends ElementType = "span">({ strong, preserveNewlines, ...props }: InlineTypographyProps<E> & {
|
|
128
|
+
export declare function Text<E extends ElementType = "span">({ strong, preserveNewlines, minWidth, italic, breakWords, ...props }: InlineTypographyProps<E> & RunOwnProps & {
|
|
108
129
|
/** Emphasis: font-medium in the primary ink (`color` and `tone` still win). */
|
|
109
130
|
strong?: boolean | undefined;
|
|
110
131
|
/** Keep the line breaks in the text (a user-typed note); runs of spaces still collapse. */
|
|
111
132
|
preserveNewlines?: boolean;
|
|
133
|
+
/** A fixed width: `amount` is a right-aligned money figure, min-w-24, in tabular figures. */
|
|
134
|
+
minWidth?: TextMinWidth | undefined;
|
|
112
135
|
}): ReactElement;
|
|
113
136
|
/**
|
|
114
137
|
* The supporting line under a `Dialog` title: `Text as="p"` without the measure, so
|
|
@@ -117,9 +140,10 @@ export declare function Text<E extends ElementType = "span">({ strong, preserveN
|
|
|
117
140
|
export declare function HeaderText({ children }: {
|
|
118
141
|
children: ReactNode;
|
|
119
142
|
}): ReactElement;
|
|
120
|
-
/**
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Fine print / metadata. `span` (inline; `as="p"` for a block), text-xs/4 normal, tertiary. Takes `tone`,
|
|
145
|
+
* `numeric`, `mono`, `truncate` and `align` like `Text`, and `italic` for a muted hint and `breakWords`
|
|
146
|
+
* for a long unbroken string such as a URL.
|
|
147
|
+
*/
|
|
148
|
+
export declare function Caption<E extends ElementType = "span">({ italic, breakWords, ...props }: InlineTypographyProps<E> & RunOwnProps): ReactElement;
|
|
125
149
|
export {};
|