@nanisoft/prism-ui 0.16.0 → 1.0.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/dist/.tsbuildinfo +1 -1
- package/dist/blocks/activity-feed-01/activity-feed-01.d.ts +120 -190
- package/dist/blocks/activity-feed-01/activity-feed-01.d.ts.map +1 -1
- package/dist/blocks/activity-feed-01/activity-feed-01.js +107 -97
- package/dist/blocks/activity-feed-01/index.d.ts +1 -1
- package/dist/blocks/activity-feed-01/index.d.ts.map +1 -1
- package/dist/blocks/auth-form-01/auth-form.d.ts +86 -53
- package/dist/blocks/auth-form-01/auth-form.d.ts.map +1 -1
- package/dist/blocks/auth-form-01/auth-form.js +95 -31
- package/dist/blocks/auth-form-01/index.d.ts +1 -1
- package/dist/blocks/auth-form-01/index.d.ts.map +1 -1
- package/dist/blocks/calendar-01/calendar.d.ts +28 -0
- package/dist/blocks/calendar-01/calendar.d.ts.map +1 -1
- package/dist/blocks/calendar-01/calendar.js +15 -1
- package/dist/blocks/card-index-01/card-index.d.ts +225 -0
- package/dist/blocks/card-index-01/card-index.d.ts.map +1 -0
- package/dist/blocks/card-index-01/card-index.js +154 -0
- package/dist/blocks/card-index-01/index.d.ts +3 -0
- package/dist/blocks/card-index-01/index.d.ts.map +1 -0
- package/dist/blocks/card-index-01/index.js +1 -0
- package/dist/blocks/chart-card-01/chart-card-01.d.ts +23 -21
- package/dist/blocks/chart-card-01/chart-card-01.d.ts.map +1 -1
- package/dist/blocks/chart-card-01/chart-card-01.js +46 -1
- package/dist/blocks/chart-card-01/index.d.ts +1 -1
- package/dist/blocks/chart-card-01/index.d.ts.map +1 -1
- package/dist/blocks/chart-group-01/chart-group-01.d.ts +3 -3
- package/dist/blocks/chart-group-01/chart-group-01.d.ts.map +1 -1
- package/dist/blocks/contact-01/contact.d.ts +30 -82
- package/dist/blocks/contact-01/contact.d.ts.map +1 -1
- package/dist/blocks/contact-01/contact.js +59 -30
- package/dist/blocks/contact-01/index.d.ts +1 -1
- package/dist/blocks/contact-01/index.d.ts.map +1 -1
- package/dist/blocks/dashboard-01/dashboard-01.d.ts +26 -71
- package/dist/blocks/dashboard-01/dashboard-01.d.ts.map +1 -1
- package/dist/blocks/dashboard-01/dashboard-01.js +34 -23
- package/dist/blocks/dashboard-01/index.d.ts +1 -1
- package/dist/blocks/dashboard-01/index.d.ts.map +1 -1
- package/dist/blocks/data-table-01/data-table.d.ts +276 -59
- package/dist/blocks/data-table-01/data-table.d.ts.map +1 -1
- package/dist/blocks/data-table-01/data-table.js +217 -35
- package/dist/blocks/data-table-01/index.d.ts +1 -1
- package/dist/blocks/data-table-01/index.d.ts.map +1 -1
- package/dist/blocks/directory-01/directory-01.d.ts +23 -2
- package/dist/blocks/directory-01/directory-01.d.ts.map +1 -1
- package/dist/blocks/directory-01/directory-01.js +3 -3
- package/dist/blocks/empty-state-01/empty-state.d.ts +60 -21
- package/dist/blocks/empty-state-01/empty-state.d.ts.map +1 -1
- package/dist/blocks/empty-state-01/empty-state.js +52 -17
- package/dist/blocks/index-detail-01/index-detail.d.ts +85 -0
- package/dist/blocks/index-detail-01/index-detail.d.ts.map +1 -0
- package/dist/blocks/index-detail-01/index-detail.js +58 -0
- package/dist/blocks/index-detail-01/index.d.ts +3 -0
- package/dist/blocks/index-detail-01/index.d.ts.map +1 -0
- package/dist/blocks/index-detail-01/index.js +1 -0
- package/dist/blocks/index.d.ts +20 -8
- package/dist/blocks/index.d.ts.map +1 -1
- package/dist/blocks/index.js +7 -0
- package/dist/blocks/issue-detail-01/issue-detail.d.ts +18 -0
- package/dist/blocks/issue-detail-01/issue-detail.d.ts.map +1 -1
- package/dist/blocks/issue-detail-01/issue-detail.js +18 -0
- package/dist/blocks/nothing-chosen-01/index.d.ts +3 -0
- package/dist/blocks/nothing-chosen-01/index.d.ts.map +1 -0
- package/dist/blocks/nothing-chosen-01/index.js +1 -0
- package/dist/blocks/nothing-chosen-01/nothing-chosen.d.ts +119 -0
- package/dist/blocks/nothing-chosen-01/nothing-chosen.d.ts.map +1 -0
- package/dist/blocks/nothing-chosen-01/nothing-chosen.js +79 -0
- package/dist/blocks/project-dashboard-01/index.d.ts +1 -1
- package/dist/blocks/project-dashboard-01/index.d.ts.map +1 -1
- package/dist/blocks/project-dashboard-01/project-dashboard.d.ts +21 -27
- package/dist/blocks/project-dashboard-01/project-dashboard.d.ts.map +1 -1
- package/dist/blocks/project-dashboard-01/project-dashboard.js +45 -5
- package/dist/blocks/provisioning-01/index.d.ts +1 -1
- package/dist/blocks/provisioning-01/index.d.ts.map +1 -1
- package/dist/blocks/provisioning-01/provisioning.d.ts +9 -97
- package/dist/blocks/provisioning-01/provisioning.d.ts.map +1 -1
- package/dist/blocks/provisioning-01/provisioning.js +26 -13
- package/dist/blocks/record-detail-01/index.d.ts +3 -0
- package/dist/blocks/record-detail-01/index.d.ts.map +1 -0
- package/dist/blocks/record-detail-01/index.js +1 -0
- package/dist/blocks/record-detail-01/record-detail.d.ts +239 -0
- package/dist/blocks/record-detail-01/record-detail.d.ts.map +1 -0
- package/dist/blocks/record-detail-01/record-detail.js +150 -0
- package/dist/blocks/record-form-01/index.d.ts +3 -0
- package/dist/blocks/record-form-01/index.d.ts.map +1 -0
- package/dist/blocks/record-form-01/index.js +1 -0
- package/dist/blocks/record-form-01/record-form.d.ts +148 -0
- package/dist/blocks/record-form-01/record-form.d.ts.map +1 -0
- package/dist/blocks/record-form-01/record-form.js +107 -0
- package/dist/blocks/record-grid-01/index.d.ts +3 -0
- package/dist/blocks/record-grid-01/index.d.ts.map +1 -0
- package/dist/blocks/record-grid-01/index.js +1 -0
- package/dist/blocks/record-grid-01/record-grid.d.ts +145 -0
- package/dist/blocks/record-grid-01/record-grid.d.ts.map +1 -0
- package/dist/blocks/record-grid-01/record-grid.js +114 -0
- package/dist/blocks/record-wizard-01/index.d.ts +3 -0
- package/dist/blocks/record-wizard-01/index.d.ts.map +1 -0
- package/dist/blocks/record-wizard-01/index.js +1 -0
- package/dist/blocks/record-wizard-01/record-wizard.d.ts +152 -0
- package/dist/blocks/record-wizard-01/record-wizard.d.ts.map +1 -0
- package/dist/blocks/record-wizard-01/record-wizard.js +144 -0
- package/dist/blocks/settings-members-01/settings-members.d.ts +2 -1
- package/dist/blocks/settings-members-01/settings-members.d.ts.map +1 -1
- package/dist/blocks/settings-panel-01/index.d.ts +1 -1
- package/dist/blocks/settings-panel-01/index.d.ts.map +1 -1
- package/dist/blocks/settings-panel-01/settings-panel.d.ts +165 -67
- package/dist/blocks/settings-panel-01/settings-panel.d.ts.map +1 -1
- package/dist/blocks/settings-panel-01/settings-panel.js +92 -33
- package/dist/blocks/signup-01/index.d.ts +1 -1
- package/dist/blocks/signup-01/index.d.ts.map +1 -1
- package/dist/blocks/signup-01/signup-01.d.ts +10 -84
- package/dist/blocks/signup-01/signup-01.d.ts.map +1 -1
- package/dist/blocks/signup-01/signup-01.js +41 -23
- package/dist/blocks/stats-01/index.d.ts +5 -5
- package/dist/blocks/stats-01/index.d.ts.map +1 -1
- package/dist/blocks/stats-01/index.js +4 -4
- package/dist/blocks/stats-01/stats.d.ts +49 -14
- package/dist/blocks/stats-01/stats.d.ts.map +1 -1
- package/dist/blocks/stats-01/stats.js +65 -15
- package/dist/blocks/trend-01/index.d.ts +1 -1
- package/dist/blocks/trend-01/index.d.ts.map +1 -1
- package/dist/blocks/trend-01/trend.d.ts +26 -73
- package/dist/blocks/trend-01/trend.d.ts.map +1 -1
- package/dist/blocks/trend-01/trend.js +47 -30
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +93 -3
- package/dist/components/ui/metric.d.ts +4 -2
- package/dist/components/ui/metric.d.ts.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/lib/field-render.d.ts +107 -0
- package/dist/lib/field-render.d.ts.map +1 -0
- package/dist/lib/field-render.js +251 -0
- package/dist/lib/spec.d.ts +609 -0
- package/dist/lib/spec.d.ts.map +1 -0
- package/dist/lib/spec.js +1 -0
- package/dist/live/index.d.ts +2 -0
- package/dist/live/index.d.ts.map +1 -1
- package/dist/live/index.js +6 -0
- package/dist/live/message-thread-01/index.d.ts +3 -0
- package/dist/live/message-thread-01/index.d.ts.map +1 -0
- package/dist/live/message-thread-01/index.js +1 -0
- package/dist/live/message-thread-01/message-thread.d.ts +282 -0
- package/dist/live/message-thread-01/message-thread.d.ts.map +1 -0
- package/dist/live/message-thread-01/message-thread.js +221 -0
- package/dist/live/run-stream-01/run-stream.d.ts +2 -1
- package/dist/live/run-stream-01/run-stream.d.ts.map +1 -1
- package/dist/live/run-stream-01/run-stream.js +1 -7
- package/dist/live/status.d.ts +27 -0
- package/dist/live/status.d.ts.map +1 -0
- package/dist/live/status.js +15 -0
- package/dist/live/tool-call-row.d.ts +26 -0
- package/dist/live/tool-call-row.d.ts.map +1 -0
- package/dist/live/tool-call-row.js +60 -0
- package/dist/live/tool-ledger-01/tool-ledger.d.ts.map +1 -1
- package/dist/live/tool-ledger-01/tool-ledger.js +2 -42
- package/dist/pages/contact-page/index.d.ts +7 -7
- package/dist/pages/contact-page/index.d.ts.map +1 -1
- package/dist/pages/contact-page/index.js +17 -5
- package/dist/pages/docs-shell/docs-shell.d.ts +42 -30
- package/dist/pages/docs-shell/docs-shell.d.ts.map +1 -1
- package/dist/pages/docs-shell/docs-shell.js +70 -48
- package/dist/pages/document-page/document-page.d.ts +146 -0
- package/dist/pages/document-page/document-page.d.ts.map +1 -0
- package/dist/pages/document-page/document-page.js +80 -0
- package/dist/pages/document-page/index.d.ts +3 -0
- package/dist/pages/document-page/index.d.ts.map +1 -0
- package/dist/pages/document-page/index.js +1 -0
- package/dist/pages/index.d.ts +2 -0
- package/dist/pages/index.d.ts.map +1 -1
- package/dist/pages/index.js +6 -0
- package/dist/styles.css +59 -3
- package/package.json +7 -2
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../lib/utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* The ink each state is stated in, and the tick beside it.
|
|
5
|
+
*
|
|
6
|
+
* The tick is the state's own first letter rather than a glyph this file invented,
|
|
7
|
+
* so there is nothing to translate and nothing to learn twice: `f` is the failed
|
|
8
|
+
* call in every locale, and it is a letter rather than a shape, so it survives a
|
|
9
|
+
* monochrome render and a screen at 200 per cent the way a hairline does not.
|
|
10
|
+
*
|
|
11
|
+
* `queued` and `cancelled` share the muted ink, and the letters are what tell them
|
|
12
|
+
* apart. That is the same trade `Status` makes and states: a wider palette on a
|
|
13
|
+
* surface a reader scans is a wider set of colours they have to learn, and the
|
|
14
|
+
* cost of a shared ink is one letter.
|
|
15
|
+
*/
|
|
16
|
+
const STATE_INK = {
|
|
17
|
+
queued: 'text-muted-foreground',
|
|
18
|
+
running: 'text-foreground',
|
|
19
|
+
succeeded: 'text-success',
|
|
20
|
+
failed: 'text-destructive',
|
|
21
|
+
cancelled: 'text-muted-foreground',
|
|
22
|
+
};
|
|
23
|
+
/** The tick each state draws, so the five are told apart without relying on colour. */
|
|
24
|
+
const STATE_MARK = {
|
|
25
|
+
queued: 'q',
|
|
26
|
+
running: 'r',
|
|
27
|
+
succeeded: 's',
|
|
28
|
+
failed: 'f',
|
|
29
|
+
cancelled: 'c',
|
|
30
|
+
};
|
|
31
|
+
/** The clock a row reads, in UTC, because the surface holds no locale to format in. */
|
|
32
|
+
export const clockOf = (at) => new Date(at).toISOString().slice(11, 19);
|
|
33
|
+
/**
|
|
34
|
+
* One tool call, drawn as the ledger draws it.
|
|
35
|
+
*
|
|
36
|
+
* **This is the tool-call row the `live` Kind owns, and it is shared rather than
|
|
37
|
+
* copied.** `ToolLedger01` draws one row per call in its ledger, and a
|
|
38
|
+
* conversation's tool-call part draws the same row inside a message, so the two
|
|
39
|
+
* surfaces cannot drift into two shapes for one call. `ToolLedger01` renders this
|
|
40
|
+
* inside its own `<li>`; the message thread renders it inside a part. The
|
|
41
|
+
* Component owns no `<li>`, so it can sit in either list without nesting one.
|
|
42
|
+
*
|
|
43
|
+
* **The duration is the difference between two sightings of the same call, and
|
|
44
|
+
* only when there are two.** `openedAt` is the moment the surface first saw the
|
|
45
|
+
* call's `id`; a call seen once has no second timestamp and draws no duration,
|
|
46
|
+
* because a zero is a claim that a call took no time. The sentence is the
|
|
47
|
+
* consumer's, on `call.durationLabel`, and the arithmetic is one subtraction of
|
|
48
|
+
* the consumer's own `at` values. There is no clock in this file.
|
|
49
|
+
*/
|
|
50
|
+
export function ToolCallRow({ call, openedAt }) {
|
|
51
|
+
// The difference between two sightings of the same call, and only when there
|
|
52
|
+
// are two. The sentence is the consumer's, the arithmetic is one subtraction of
|
|
53
|
+
// the consumer's own timestamps, and there is no clock in this file.
|
|
54
|
+
const elapsed = call.at - openedAt;
|
|
55
|
+
const duration = elapsed > 0 && call.durationLabel !== undefined
|
|
56
|
+
? call.durationLabel(elapsed, { id: call.id, name: call.name })
|
|
57
|
+
: null;
|
|
58
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [_jsx("span", { "aria-hidden": "true", className: cn('font-mono text-xs', STATE_INK[call.state]), children: STATE_MARK[call.state] }), _jsx("time", { dateTime: new Date(openedAt).toISOString(), className: "text-muted-foreground font-mono text-xs tabular-nums", children: clockOf(openedAt) }), _jsx("span", { className: "text-foreground text-sm font-medium", children: call.name }), call.spanLabel ? (_jsx("span", { "data-slot": "tool-ledger-span", className: "border-border text-muted-foreground rounded border px-1 font-mono text-xs", children: call.spanLabel })) : null, duration === null ? null : (_jsx("span", { "data-slot": "tool-ledger-duration", className: "text-muted-foreground ml-auto font-mono text-xs tabular-nums", children: duration }))] }), call.argumentsText === undefined ? null : (_jsx("span", { "data-slot": "tool-ledger-arguments", className: "text-muted-foreground font-mono text-xs break-words", children: call.argumentsText })), call.resultText === undefined ? null : (_jsx("span", { "data-slot": "tool-ledger-result", className: "text-muted-foreground text-pretty text-xs", children: call.resultText })), call.errorText === undefined ? null : (_jsx("span", { "data-slot": "tool-ledger-error", className: "text-destructive text-pretty text-xs", children: call.errorText })), call.link === undefined ? null : (_jsx("a", { "data-slot": "tool-ledger-link", href: call.link.href, className: "text-foreground self-start rounded-sm text-xs underline-offset-4 hover:underline", children: call.link.label }))] }));
|
|
59
|
+
}
|
|
60
|
+
export default ToolCallRow;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-ledger.d.ts","sourceRoot":"","sources":["../../../src/live/tool-ledger-01/tool-ledger.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"tool-ledger.d.ts","sourceRoot":"","sources":["../../../src/live/tool-ledger-01/tool-ledger.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAQnE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAA;AAEvF;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB;;;;;;OAMG;IACH,EAAE,EAAE,MAAM,CAAA;IACV;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;;;OAOG;IACH,EAAE,EAAE,MAAM,CAAA;IACV,sDAAsD;IACtD,KAAK,EAAE,aAAa,CAAA;IACpB;;;;;;;;;;;;;;;;;OAiBG;IACH,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IAC1E;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE;QACL,qBAAqB;QACrB,IAAI,EAAE,MAAM,CAAA;QACZ,6BAA6B;QAC7B,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;AAE1E;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;;;;OAQG;IACH,SAAS,EAAE,aAAa,CAAA;IACxB;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAA;IAC/B;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;OAOG;IACH,KAAK,EAAE,SAAS,CAAA;IAChB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACxC;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,CACA;IAAE,YAAY,CAAC,EAAE,KAAK,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAC;IAAC,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,GACjE;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAClE,CAAA;AA8DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,SAAS,EACT,cAAc,EACd,KAAK,EACL,KAAK,EACL,KAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,WAAW,EACX,MAAM,EACN,SAAS,GACV,EAAE,iBAAiB,+BAgInB;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -5,6 +5,7 @@ import { Button } from '../../components/ui/button.js';
|
|
|
5
5
|
import { LiveRegion } from '../../components/ui/live-region.js';
|
|
6
6
|
import { ScrollArea } from '../../components/ui/scroll-area.js';
|
|
7
7
|
import { cn } from '../../lib/utils.js';
|
|
8
|
+
import { ToolCallRow } from '../tool-call-row.js';
|
|
8
9
|
/**
|
|
9
10
|
* The one source of truth for order, so a late call with an earlier `at` sorts
|
|
10
11
|
* there and two runs of the same suite render the same ledger. Ties break on
|
|
@@ -27,36 +28,6 @@ function seedOf(calls, limit) {
|
|
|
27
28
|
const dropped = rows.length - limit;
|
|
28
29
|
return { rows: rows.slice(dropped), dropped };
|
|
29
30
|
}
|
|
30
|
-
/**
|
|
31
|
-
* The ink each state is stated in, and the tick beside it.
|
|
32
|
-
*
|
|
33
|
-
* The tick is the state's own first letter rather than a glyph this file invented,
|
|
34
|
-
* so there is nothing to translate and nothing to learn twice: `f` is the failed
|
|
35
|
-
* call in every locale, and it is a letter rather than a shape, so it survives a
|
|
36
|
-
* monochrome render and a screen at 200 per cent the way a hairline does not.
|
|
37
|
-
*
|
|
38
|
-
* `queued` and `cancelled` share the muted ink, and the letters are what tell them
|
|
39
|
-
* apart. That is the same trade `Status` makes and states: a wider palette on a
|
|
40
|
-
* surface a reader scans is a wider set of colours they have to learn, and the
|
|
41
|
-
* cost of a shared ink is one letter.
|
|
42
|
-
*/
|
|
43
|
-
const STATE_INK = {
|
|
44
|
-
queued: 'text-muted-foreground',
|
|
45
|
-
running: 'text-foreground',
|
|
46
|
-
succeeded: 'text-success',
|
|
47
|
-
failed: 'text-destructive',
|
|
48
|
-
cancelled: 'text-muted-foreground',
|
|
49
|
-
};
|
|
50
|
-
/** The tick each state draws, so the five are told apart without relying on colour. */
|
|
51
|
-
const STATE_MARK = {
|
|
52
|
-
queued: 'q',
|
|
53
|
-
running: 'r',
|
|
54
|
-
succeeded: 's',
|
|
55
|
-
failed: 'f',
|
|
56
|
-
cancelled: 'c',
|
|
57
|
-
};
|
|
58
|
-
/** The clock a row reads, in UTC, because the surface holds no locale to format in. */
|
|
59
|
-
const clockOf = (at) => new Date(at).toISOString().slice(11, 19);
|
|
60
31
|
/** One call merged into the ledger, and what fell off the top doing it. */
|
|
61
32
|
function merge(rows, call, limit) {
|
|
62
33
|
const at = rows.findIndex((row) => row.call.id === call.id);
|
|
@@ -229,17 +200,6 @@ export function ToolLedger01({ subscribe, callbacks, resubscribeKey, label, empt
|
|
|
229
200
|
stop();
|
|
230
201
|
};
|
|
231
202
|
}, [subscribe, resubscribeKey, limit]);
|
|
232
|
-
return (_jsxs("section", { "data-slot": "tool-ledger", className: cn('border-border flex flex-col gap-4 rounded-lg border p-4', className), children: [LiveRegion({ politeness: 'polite', children: newest }), droppedLabel === undefined && pauseControl !== true ? null : (_jsxs("div", { "data-slot": "tool-ledger-bar", className: "flex flex-wrap items-center gap-3", children: [run.dropped > 0 && droppedLabel !== undefined ? (_jsx("p", { "data-slot": "tool-ledger-dropped", className: "text-muted-foreground text-xs", children: droppedLabel(run.dropped) })) : null, pauseControl !== true ? null : (_jsx(Button, { "data-slot": "tool-ledger-pause", type: "button", variant: "outline", size: "sm", "aria-pressed": held, className: "ml-auto", onClick: () => setHeld(!heldRef.current), children: held ? resumeLabel : pauseLabel }))] })), rows.length === 0 ? (_jsx("p", { "data-slot": "tool-ledger-empty", className: "text-muted-foreground text-sm", children: empty })) : (_jsx(ScrollArea, { label: label, className: "max-h-96", children: _jsx("ol", { "data-slot": "tool-ledger-calls", className: "flex flex-col", children: rows.map((row) => {
|
|
233
|
-
const { call } = row;
|
|
234
|
-
// The difference between two sightings of the same call, and only when
|
|
235
|
-
// there are two. The sentence is the consumer's, the arithmetic is one
|
|
236
|
-
// subtraction of the consumer's own timestamps, and there is no clock
|
|
237
|
-
// in this file.
|
|
238
|
-
const elapsed = call.at - row.openedAt;
|
|
239
|
-
const duration = elapsed > 0 && call.durationLabel !== undefined
|
|
240
|
-
? call.durationLabel(elapsed, { id: call.id, name: call.name })
|
|
241
|
-
: null;
|
|
242
|
-
return (_jsxs("li", { "data-slot": "tool-ledger-call", "data-state": call.state, className: "border-border flex flex-col gap-1 border-b py-3 last:border-b-0", children: [_jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [_jsx("span", { "aria-hidden": "true", className: cn('font-mono text-xs', STATE_INK[call.state]), children: STATE_MARK[call.state] }), _jsx("time", { dateTime: new Date(row.openedAt).toISOString(), className: "text-muted-foreground font-mono text-xs tabular-nums", children: clockOf(row.openedAt) }), _jsx("span", { className: "text-foreground text-sm font-medium", children: call.name }), call.spanLabel ? (_jsx("span", { "data-slot": "tool-ledger-span", className: "border-border text-muted-foreground rounded border px-1 font-mono text-xs", children: call.spanLabel })) : null, duration === null ? null : (_jsx("span", { "data-slot": "tool-ledger-duration", className: "text-muted-foreground ml-auto font-mono text-xs tabular-nums", children: duration }))] }), call.argumentsText === undefined ? null : (_jsx("span", { "data-slot": "tool-ledger-arguments", className: "text-muted-foreground font-mono text-xs break-words", children: call.argumentsText })), call.resultText === undefined ? null : (_jsx("span", { "data-slot": "tool-ledger-result", className: "text-muted-foreground text-pretty text-xs", children: call.resultText })), call.errorText === undefined ? null : (_jsx("span", { "data-slot": "tool-ledger-error", className: "text-destructive text-pretty text-xs", children: call.errorText })), call.link === undefined ? null : (_jsx("a", { "data-slot": "tool-ledger-link", href: call.link.href, className: "text-foreground self-start rounded-sm text-xs underline-offset-4 hover:underline", children: call.link.label }))] }, call.id));
|
|
243
|
-
}) }) }))] }));
|
|
203
|
+
return (_jsxs("section", { "data-slot": "tool-ledger", className: cn('border-border flex flex-col gap-4 rounded-lg border p-4', className), children: [LiveRegion({ politeness: 'polite', children: newest }), droppedLabel === undefined && pauseControl !== true ? null : (_jsxs("div", { "data-slot": "tool-ledger-bar", className: "flex flex-wrap items-center gap-3", children: [run.dropped > 0 && droppedLabel !== undefined ? (_jsx("p", { "data-slot": "tool-ledger-dropped", className: "text-muted-foreground text-xs", children: droppedLabel(run.dropped) })) : null, pauseControl !== true ? null : (_jsx(Button, { "data-slot": "tool-ledger-pause", type: "button", variant: "outline", size: "sm", "aria-pressed": held, className: "ml-auto", onClick: () => setHeld(!heldRef.current), children: held ? resumeLabel : pauseLabel }))] })), rows.length === 0 ? (_jsx("p", { "data-slot": "tool-ledger-empty", className: "text-muted-foreground text-sm", children: empty })) : (_jsx(ScrollArea, { label: label, className: "max-h-96", children: _jsx("ol", { "data-slot": "tool-ledger-calls", className: "flex flex-col", children: rows.map((row) => (_jsx("li", { "data-slot": "tool-ledger-call", "data-state": row.call.state, className: "border-border flex flex-col gap-1 border-b py-3 last:border-b-0", children: _jsx(ToolCallRow, { call: row.call, openedAt: row.openedAt }) }, row.call.id))) }) }))] }));
|
|
244
204
|
}
|
|
245
205
|
export default ToolLedger01;
|
|
@@ -18,16 +18,16 @@ export type ContactPageOption = {
|
|
|
18
18
|
/**
|
|
19
19
|
* One declared field of the contact form.
|
|
20
20
|
*
|
|
21
|
-
* **Flat, on purpose, where `
|
|
21
|
+
* **Flat, on purpose, where `FieldSpec` is a union.** A consumer's form data is
|
|
22
22
|
* flat: a record read out of a content type, a CMS entry or a JSON file has one
|
|
23
23
|
* shape with an optional `options` key, and a caller that had to narrow their own
|
|
24
24
|
* record before they could hand it to a page would be doing the Block's type work
|
|
25
|
-
* at every call site. So the
|
|
26
|
-
* shape it cannot build is refused here with
|
|
27
|
-
* prop. That is `AboutPage`'s arrangement for
|
|
28
|
-
* cost is the same: a caller who wants the
|
|
29
|
-
* types their fields
|
|
30
|
-
*
|
|
25
|
+
* at every call site. So the flat record is converted to the shared specification
|
|
26
|
+
* once, inside this module, and the one shape it cannot build is refused here with
|
|
27
|
+
* a message that names the Page's own prop. That is `AboutPage`'s arrangement for
|
|
28
|
+
* the same pair of link fields, and the cost is the same: a caller who wants the
|
|
29
|
+
* compile error rather than the thrown one types their fields as `FieldSpec` and
|
|
30
|
+
* composes `Contact01` directly.
|
|
31
31
|
*/
|
|
32
32
|
export type ContactPageField = {
|
|
33
33
|
/** The caller's key for this field, and the key the value arrives under. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/pages/contact-page/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,EAEL,KAAK,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/pages/contact-page/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import { Contact01, } from '../../blocks/contact-01/index.js';
|
|
|
4
4
|
import { Card, CardContent, CardHeader, CardTitle } from '../../components/ui/card.js';
|
|
5
5
|
import { CtaLink } from '../../components/ui/cta-link.js';
|
|
6
6
|
import { Section, SectionHeading, childLevel } from '../../components/ui/section.js';
|
|
7
|
+
import { FieldKindName } from '../../lib/field-render.js';
|
|
7
8
|
import { cn } from '../../lib/utils.js';
|
|
8
9
|
/**
|
|
9
10
|
* One declared field as `Contact01` draws it, with the two shapes kept apart.
|
|
@@ -16,15 +17,26 @@ import { cn } from '../../lib/utils.js';
|
|
|
16
17
|
*/
|
|
17
18
|
function asContactField(field) {
|
|
18
19
|
const shared = {
|
|
19
|
-
|
|
20
|
+
key: field.id,
|
|
20
21
|
label: field.label,
|
|
21
22
|
required: field.required,
|
|
22
|
-
|
|
23
|
+
help: field.description,
|
|
23
24
|
placeholder: field.placeholder,
|
|
24
25
|
autoComplete: field.autoComplete,
|
|
25
26
|
};
|
|
27
|
+
if (field.type === 'textarea')
|
|
28
|
+
return { ...shared, kind: FieldKindName.textarea, rows: 4 };
|
|
29
|
+
/*
|
|
30
|
+
`text`, `email` and `tel` all draw Prism's `Input`, which is the control this
|
|
31
|
+
package ships for a run of characters; the platform's own `type` attributes are
|
|
32
|
+
not part of the shared vocabulary, so asking for an email is asking for an
|
|
33
|
+
`Input` with the `autoComplete` hint a password manager reads. `inputMode` and
|
|
34
|
+
`type` are the platform's, and the caller who needs a numeric keypad reaches for
|
|
35
|
+
the `NumberField` kind on the Block directly rather than through this Page's
|
|
36
|
+
flat prop.
|
|
37
|
+
*/
|
|
26
38
|
if (field.type !== 'select')
|
|
27
|
-
return { ...shared,
|
|
39
|
+
return { ...shared, kind: FieldKindName.input };
|
|
28
40
|
const options = field.options ?? [];
|
|
29
41
|
if (options.length === 0) {
|
|
30
42
|
throw new Error(`ContactPage: the field "${field.id}" is a select and passes no options, so the control would render with ` +
|
|
@@ -32,7 +44,7 @@ function asContactField(field) {
|
|
|
32
44
|
'there and focusable. Pass the choices, or declare the field as a text field and check the answer in ' +
|
|
33
45
|
'your own handler.');
|
|
34
46
|
}
|
|
35
|
-
return { ...shared,
|
|
47
|
+
return { ...shared, kind: FieldKindName.nativeSelect, options: options.map((option) => ({ ...option })) };
|
|
36
48
|
}
|
|
37
49
|
/**
|
|
38
50
|
* The two checks the office union makes for a TypeScript caller, run here for the
|
|
@@ -125,7 +137,7 @@ export function ContactPage({ eyebrow, title, description, form, fields, onSubmi
|
|
|
125
137
|
*/
|
|
126
138
|
const BandHeading = childLevel(headingLevel);
|
|
127
139
|
const OfficeHeading = childLevel(BandHeading);
|
|
128
|
-
return (_jsxs("div", { "data-slot": "contact-page", className: cn(className), children: [_jsx(Section, { "data-slot": "contact-page-heading", children: _jsx(SectionHeading, { as: headingLevel, align: "left", eyebrow: eyebrow, title: title, description: description }) }), _jsx(Contact01, { title: form.title, description: form.description, fields: fields.map(asContactField), onSubmit: onSubmit, submitLabel: submitLabel, consent: consent, status: status, variant: "stacked", headingLevel: BandHeading }), offices === undefined ? null : (_jsxs(Section, { "data-slot": "contact-page-offices", children: [_jsx(SectionHeading, { as: BandHeading, align: "left", title: officesLabel, className: "mb-10" }), _jsx("div", { "data-slot": "contact-page-office-row", className: "grid items-start gap-6 md:grid-cols-2 lg:grid-cols-3", children: offices.map((office) => (_jsxs(Card, { "data-slot": "contact-page-office", "data-office": office.id, className: "h-full", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { as: OfficeHeading, children: office.name }) }), _jsxs(CardContent, { className: "flex flex-col items-start gap-4", children: [_jsx("address", { "data-slot": "contact-page-office-address", className: "text-muted-foreground flex flex-col gap-1 not-italic text-sm", children: office.lines.map((line, index) => (
|
|
140
|
+
return (_jsxs("div", { "data-slot": "contact-page", className: cn(className), children: [_jsx(Section, { "data-slot": "contact-page-heading", children: _jsx(SectionHeading, { as: headingLevel, align: "left", eyebrow: eyebrow, title: title, description: description }) }), _jsx(Contact01, { title: form.title, description: form.description, groups: [{ fields: fields.map(asContactField) }], onSubmit: onSubmit, submitLabel: submitLabel, consent: consent, status: status, variant: "stacked", headingLevel: BandHeading }), offices === undefined ? null : (_jsxs(Section, { "data-slot": "contact-page-offices", children: [_jsx(SectionHeading, { as: BandHeading, align: "left", title: officesLabel, className: "mb-10" }), _jsx("div", { "data-slot": "contact-page-office-row", className: "grid items-start gap-6 md:grid-cols-2 lg:grid-cols-3", children: offices.map((office) => (_jsxs(Card, { "data-slot": "contact-page-office", "data-office": office.id, className: "h-full", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { as: OfficeHeading, children: office.name }) }), _jsxs(CardContent, { className: "flex flex-col items-start gap-4", children: [_jsx("address", { "data-slot": "contact-page-office-address", className: "text-muted-foreground flex flex-col gap-1 not-italic text-sm", children: office.lines.map((line, index) => (
|
|
129
141
|
/*
|
|
130
142
|
Positional, because a postal line is display content and a
|
|
131
143
|
business with two branches on one street can legitimately
|
|
@@ -188,17 +188,11 @@ export type DocsShellProps = {
|
|
|
188
188
|
* The accessible name of the rail. Required whenever `nav` is passed, because
|
|
189
189
|
* it is a word a reader hears and a Page that ships no copy ships no
|
|
190
190
|
* reader-facing copy either.
|
|
191
|
-
*
|
|
192
|
-
* It is also the visible word on the disclosure that stands in for the rail
|
|
193
|
-
* below `lg`, because it is already this navigation's name and a Page cannot
|
|
194
|
-
* invent a second one. A consumer that files its navigation in another language
|
|
195
|
-
* gets the control in that language by having done this once.
|
|
196
191
|
*/
|
|
197
192
|
navLabel: string;
|
|
198
193
|
/**
|
|
199
194
|
* The accessible name of the contents rail. Required whenever `toc` is passed,
|
|
200
|
-
* for the same reason `navLabel` is
|
|
201
|
-
* carries it for the same reason too.
|
|
195
|
+
* for the same reason `navLabel` is.
|
|
202
196
|
*/
|
|
203
197
|
tocLabel: string;
|
|
204
198
|
/**
|
|
@@ -347,32 +341,51 @@ export type DocsShellProps = {
|
|
|
347
341
|
* a fact about ink, and announcing it would put a sentence in the middle of a
|
|
348
342
|
* list of a consumer's own pages.
|
|
349
343
|
*
|
|
350
|
-
* **
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
344
|
+
* **The tree is in the document once, at every width, and the price of that is a
|
|
345
|
+
* phone reader crossing the whole navigation to reach the article.** At 768 and
|
|
346
|
+
* at 1024 both rails used to be `hidden`, so the only navigation left inside
|
|
347
|
+
* `<main>` was the two-item pager at the foot of the article, and a reader on a
|
|
348
|
+
* twenty-seven document reference at tablet width had no contents, no
|
|
349
|
+
* on-this-page and no way to a sibling page except Previous and Next. 0.16.0
|
|
350
|
+
* closed that gap by drawing the tree a second time behind a `<details>`, one
|
|
351
|
+
* copy for the rail and one for the narrow frame, and it shipped a doubled
|
|
352
|
+
* document to every documentation page in the family with it: two
|
|
353
|
+
* `aria-current` markers for one page, two lists of a consumer's own pages, two
|
|
354
|
+
* `docs-nav-page` rows for every document, and a second `<nav>` carrying the
|
|
355
|
+
* rail's own accessible name, which is the thing a consumer's suite reaches the
|
|
356
|
+
* rail by. Three consumer test files failed against the published package: two on
|
|
357
|
+
* a count that came back doubled, and two on a `getByRole('navigation', { name })`
|
|
358
|
+
* that had two answers where it expects one. So there is one copy now, and it
|
|
359
|
+
* shows at every width.
|
|
360
|
+
*
|
|
361
|
+
* **What that costs, with the number.** A consumer's rail measured 1,318 pixels
|
|
362
|
+
* of content in a built export at 1280 by 680, and those rows wrap on a phone, so
|
|
363
|
+
* a reader arriving at the top of a documentation page scrolls past a thousand
|
|
364
|
+
* pixels of navigation before the article begins. That is a real regression for
|
|
365
|
+
* that reader and it is the reason a disclosure was reached for in the first
|
|
366
|
+
* place. It is paid rather than hidden, because every arrangement that avoids it
|
|
367
|
+
* is worse: a rail at `lg` and nothing below it reopens the gap this change
|
|
368
|
+
* closes, and drawing the tree twice to keep the scroll short is what broke three
|
|
369
|
+
* consumer test files in the first place.
|
|
360
370
|
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
371
|
+
* **What would actually remove the scroll.** A collapsed rail below `lg` needs an
|
|
372
|
+
* open state. A server Component cannot hold one, and `<details>` is the only
|
|
373
|
+
* disclosure the platform holds on the Page's behalf, so the control that opens
|
|
374
|
+
* it has to be a client island inside the Page. That is a separate piece of work
|
|
375
|
+
* with its own budget, and it is not built here: a Page that ships a client
|
|
376
|
+
* boundary to save one scroll is making a different trade than the one stated
|
|
377
|
+
* above, and it should be made deliberately rather than smuggled in as the side
|
|
378
|
+
* effect of fixing a duplicate.
|
|
368
379
|
*
|
|
369
380
|
* **The frame is three columns from `lg`, and the third is the consumer's to
|
|
370
381
|
* fill.** The rail is 15rem, the document takes the rest, and the contents rail
|
|
371
382
|
* is 13rem. The third track exists only when `toc` is passed, because the
|
|
372
383
|
* document takes the second track by auto-placement and a template that named a
|
|
373
384
|
* track no child occupies would leave the document in the 15rem one. Below `lg`
|
|
374
|
-
* the frame is a single column
|
|
375
|
-
*
|
|
385
|
+
* the frame is a single column and the children flow in the order they are
|
|
386
|
+
* written: the rail, then the document, then the contents rail. The rail is the
|
|
387
|
+
* first child for that reason, so a reader below `lg` meets the navigation before
|
|
388
|
+
* the text rather than after it, and one arrangement serves both widths.
|
|
376
389
|
*
|
|
377
390
|
* It is a Page rather than a Block because it is a whole screen and it is the
|
|
378
391
|
* screen a content pipeline targets: a route that reads one document and hands
|
|
@@ -383,10 +396,9 @@ export type DocsShellProps = {
|
|
|
383
396
|
*
|
|
384
397
|
* It is a server Component. It fetches nothing, it holds no state and it imports
|
|
385
398
|
* no router, so a consumer renders it from whichever route their framework names
|
|
386
|
-
* and hands it the document their pipeline produced.
|
|
387
|
-
* the
|
|
388
|
-
*
|
|
389
|
-
* as markup instead.
|
|
399
|
+
* and hands it the document their pipeline produced. Nothing here needs a client
|
|
400
|
+
* boundary, and the one feature that would want one is named above as work not
|
|
401
|
+
* done rather than quietly added.
|
|
390
402
|
*/
|
|
391
403
|
export declare function DocsShell({ title, description, nav, toc, currentHref, navLabel, tocLabel, pagerLabel, pagerLabels, header, footer, className, children, }: DocsShellProps): import("react").JSX.Element;
|
|
392
404
|
export default DocsShell;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-shell.d.ts","sourceRoot":"","sources":["../../../src/pages/docs-shell/docs-shell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAOtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAA;IACb;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,KAAK,EAAE,SAAS,YAAY,EAAE,CAAA;CAC/B,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,SAAS,CAAA;IACf,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,YAAY,GAAG,cAAc,CAAA;AAEtE;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;IAChB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB;;;;OAIG;IACH,GAAG,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IAC7B;;;;;;;OAOG;IACH,GAAG,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB
|
|
1
|
+
{"version":3,"file":"docs-shell.d.ts","sourceRoot":"","sources":["../../../src/pages/docs-shell/docs-shell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAOtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAA;IACb;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,KAAK,EAAE,SAAS,YAAY,EAAE,CAAA;CAC/B,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,SAAS,CAAA;IACf,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,YAAY,GAAG,cAAc,CAAA;AAEtE;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;IAChB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB;;;;OAIG;IACH,GAAG,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IAC7B;;;;;;;OAOG;IACH,GAAG,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,WAAW,EAAE,eAAe,CAAA;IAC5B;;;;;OAKG;IACH,QAAQ,EAAE,SAAS,CAAA;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwKG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,WAAW,EACX,GAAG,EACH,GAAG,EACH,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,WAAW,EACX,MAAM,EACN,MAAM,EACN,SAAS,EACT,QAAQ,GACT,EAAE,cAAc,+BAiFhB;AA+fD,eAAe,SAAS,CAAA"}
|
|
@@ -113,32 +113,51 @@ import { cn } from '../../lib/utils.js';
|
|
|
113
113
|
* a fact about ink, and announcing it would put a sentence in the middle of a
|
|
114
114
|
* list of a consumer's own pages.
|
|
115
115
|
*
|
|
116
|
-
* **
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
116
|
+
* **The tree is in the document once, at every width, and the price of that is a
|
|
117
|
+
* phone reader crossing the whole navigation to reach the article.** At 768 and
|
|
118
|
+
* at 1024 both rails used to be `hidden`, so the only navigation left inside
|
|
119
|
+
* `<main>` was the two-item pager at the foot of the article, and a reader on a
|
|
120
|
+
* twenty-seven document reference at tablet width had no contents, no
|
|
121
|
+
* on-this-page and no way to a sibling page except Previous and Next. 0.16.0
|
|
122
|
+
* closed that gap by drawing the tree a second time behind a `<details>`, one
|
|
123
|
+
* copy for the rail and one for the narrow frame, and it shipped a doubled
|
|
124
|
+
* document to every documentation page in the family with it: two
|
|
125
|
+
* `aria-current` markers for one page, two lists of a consumer's own pages, two
|
|
126
|
+
* `docs-nav-page` rows for every document, and a second `<nav>` carrying the
|
|
127
|
+
* rail's own accessible name, which is the thing a consumer's suite reaches the
|
|
128
|
+
* rail by. Three consumer test files failed against the published package: two on
|
|
129
|
+
* a count that came back doubled, and two on a `getByRole('navigation', { name })`
|
|
130
|
+
* that had two answers where it expects one. So there is one copy now, and it
|
|
131
|
+
* shows at every width.
|
|
132
|
+
*
|
|
133
|
+
* **What that costs, with the number.** A consumer's rail measured 1,318 pixels
|
|
134
|
+
* of content in a built export at 1280 by 680, and those rows wrap on a phone, so
|
|
135
|
+
* a reader arriving at the top of a documentation page scrolls past a thousand
|
|
136
|
+
* pixels of navigation before the article begins. That is a real regression for
|
|
137
|
+
* that reader and it is the reason a disclosure was reached for in the first
|
|
138
|
+
* place. It is paid rather than hidden, because every arrangement that avoids it
|
|
139
|
+
* is worse: a rail at `lg` and nothing below it reopens the gap this change
|
|
140
|
+
* closes, and drawing the tree twice to keep the scroll short is what broke three
|
|
141
|
+
* consumer test files in the first place.
|
|
142
|
+
*
|
|
143
|
+
* **What would actually remove the scroll.** A collapsed rail below `lg` needs an
|
|
144
|
+
* open state. A server Component cannot hold one, and `<details>` is the only
|
|
145
|
+
* disclosure the platform holds on the Page's behalf, so the control that opens
|
|
146
|
+
* it has to be a client island inside the Page. That is a separate piece of work
|
|
147
|
+
* with its own budget, and it is not built here: a Page that ships a client
|
|
148
|
+
* boundary to save one scroll is making a different trade than the one stated
|
|
149
|
+
* above, and it should be made deliberately rather than smuggled in as the side
|
|
150
|
+
* effect of fixing a duplicate.
|
|
134
151
|
*
|
|
135
152
|
* **The frame is three columns from `lg`, and the third is the consumer's to
|
|
136
153
|
* fill.** The rail is 15rem, the document takes the rest, and the contents rail
|
|
137
154
|
* is 13rem. The third track exists only when `toc` is passed, because the
|
|
138
155
|
* document takes the second track by auto-placement and a template that named a
|
|
139
156
|
* track no child occupies would leave the document in the 15rem one. Below `lg`
|
|
140
|
-
* the frame is a single column
|
|
141
|
-
*
|
|
157
|
+
* the frame is a single column and the children flow in the order they are
|
|
158
|
+
* written: the rail, then the document, then the contents rail. The rail is the
|
|
159
|
+
* first child for that reason, so a reader below `lg` meets the navigation before
|
|
160
|
+
* the text rather than after it, and one arrangement serves both widths.
|
|
142
161
|
*
|
|
143
162
|
* It is a Page rather than a Block because it is a whole screen and it is the
|
|
144
163
|
* screen a content pipeline targets: a route that reads one document and hands
|
|
@@ -149,10 +168,9 @@ import { cn } from '../../lib/utils.js';
|
|
|
149
168
|
*
|
|
150
169
|
* It is a server Component. It fetches nothing, it holds no state and it imports
|
|
151
170
|
* no router, so a consumer renders it from whichever route their framework names
|
|
152
|
-
* and hands it the document their pipeline produced.
|
|
153
|
-
* the
|
|
154
|
-
*
|
|
155
|
-
* as markup instead.
|
|
171
|
+
* and hands it the document their pipeline produced. Nothing here needs a client
|
|
172
|
+
* boundary, and the one feature that would want one is named above as work not
|
|
173
|
+
* done rather than quietly added.
|
|
156
174
|
*/
|
|
157
175
|
export function DocsShell({ title, description, nav, toc, currentHref, navLabel, tocLabel, pagerLabel, pagerLabels, header, footer, className, children, }) {
|
|
158
176
|
readTree(nav, 'nav');
|
|
@@ -177,10 +195,10 @@ export function DocsShell({ title, description, nav, toc, currentHref, navLabel,
|
|
|
177
195
|
// contents rail landed in an implicit `auto` track rather than the
|
|
178
196
|
// 13rem one. `check-breakpoint-variants.mjs` is the gate that says so
|
|
179
197
|
// to the next class written against a screen the theme does not emit.
|
|
180
|
-
contents ? 'lg:grid lg:grid-cols-[15rem_minmax(0,1fr)_13rem]' : 'lg:grid lg:grid-cols-[15rem_minmax(0,1fr)]'), children: [rail
|
|
198
|
+
contents ? 'lg:grid lg:grid-cols-[15rem_minmax(0,1fr)_13rem]' : 'lg:grid lg:grid-cols-[15rem_minmax(0,1fr)]'), children: [rail ? (_jsx("aside", { "data-slot": "docs-rail", className: "lg:col-start-1 lg:row-start-1", children: _jsx(Rail, { label: navLabel, entries: rail, currentHref: currentHref, unnamed: unnamedNav }) })) : null, _jsxs("article", { "data-slot": "docs-article", className: "flex min-w-0 flex-col gap-8", children: [title ? (_jsxs("header", { className: "flex flex-col gap-3", children: [_jsx(Heading, { as: "h1", className: headingSizeClass('h1'), children: title }), description ? (_jsx(Text, { size: "lg", tone: "muted", className: "max-w-measure", children: description })) : null] })) : description ? (_jsx(Text, { size: "lg", tone: "muted", className: "max-w-measure", children: description })) : null, _jsx(Prose, { fullWidth: true, children: children }), neighbours ? (_jsx(Pager, { previous: neighbours.previous, next: neighbours.next, label: pagerLabel, labels: pagerLabels })) : null] }), contents ? (_jsx("aside", { "data-slot": "docs-contents", className: "lg:col-start-3 lg:row-start-1", children: _jsx(Rail, { label: tocLabel, entries: contents, currentHref: currentHref, unnamed: unnamedToc }) })) : null] }), footer] }));
|
|
181
199
|
}
|
|
182
200
|
/* ------------------------------------------------------------------ *
|
|
183
|
-
* The two rails
|
|
201
|
+
* The two rails
|
|
184
202
|
* ------------------------------------------------------------------ */
|
|
185
203
|
/**
|
|
186
204
|
* One rail: a region that scrolls inside a bound against the viewport, with the
|
|
@@ -214,32 +232,36 @@ export function DocsShell({ title, description, nav, toc, currentHref, navLabel,
|
|
|
214
232
|
* usual cost of a fade and the reason the padding is part of the answer rather
|
|
215
233
|
* than a detail.
|
|
216
234
|
*
|
|
235
|
+
* **The bound, the sticky offset, the band and the fade are all written against
|
|
236
|
+
* the same `lg:`, so below `lg` this rail is an ordinary block in the flow: no
|
|
237
|
+
* scroll region, no cut, no reservation, no fade.** That is the right shape for a
|
|
238
|
+
* rail that is the first thing in a single column, because a sticky region a full
|
|
239
|
+
* viewport tall above the article would be worse than a long one above it.
|
|
240
|
+
*
|
|
241
|
+
* **The fade and the band are bound to the cut rather than to the rail, and the
|
|
242
|
+
* reason is what a fade is for.** A fade marks a cut, so it may only exist where
|
|
243
|
+
* there is one, and the cut is the `overflow-y` at `lg`: the scroll region, the
|
|
244
|
+
* cap, the sticky offset, the reserved band and the gradient are one arrangement
|
|
245
|
+
* or none of them. The fade shipped unprefixed, which put the arrangement out of
|
|
246
|
+
* step with itself at the one width that has no cut to mark. Below `lg` the region
|
|
247
|
+
* is an ordinary block, so the `pb-8` reserving the band is inert there and the
|
|
248
|
+
* gradient fell on the last row or two of a rail that was simply running on. The
|
|
249
|
+
* band and the fade still measured equal and the reader still lost nothing
|
|
250
|
+
* legible, which is why looking did not catch it: a gradient painted over content
|
|
251
|
+
* is a defect, and it is not a legibility one.
|
|
252
|
+
*
|
|
253
|
+
* **The limit bought here is stated rather than left to be found.** Below `lg` the
|
|
254
|
+
* rail is bounded by its content rather than by the viewport, so a long tree runs
|
|
255
|
+
* past the fold of a phone screen with nothing marking where it ends: no cut to
|
|
256
|
+
* mark, no band to reserve and no scroll region to scroll inside. That is the
|
|
257
|
+
* honest price of one copy of the tree at every width, and the measurement behind
|
|
258
|
+
* it is stated once on the Page above rather than repeated here.
|
|
259
|
+
*
|
|
217
260
|
* `unnamed` is carried on the `<nav>` rather than logged, for the reason
|
|
218
261
|
* `unnamedIn` gives.
|
|
219
262
|
*/
|
|
220
263
|
function Rail({ label, entries, currentHref, unnamed, }) {
|
|
221
|
-
return (_jsxs("div", { className: "relative lg:sticky lg:top-20", children: [_jsx("nav", { "aria-label": label, "data-unnamed-entries": unnamed, className: "lg:max-h-[calc(100svh-7rem)] lg:overflow-y-auto lg:pe-4 lg:pb-8", children: _jsx(NavList, { entries: entries, currentHref: currentHref, depth: 0 }) }), _jsx("div", { "aria-hidden": "true", "data-slot": "docs-rail-fade", className: "
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* One tree behind a native disclosure, for the widths where there is no rail.
|
|
225
|
-
*
|
|
226
|
-
* `<details>` rather than a Component, and the whole argument is that it needs no
|
|
227
|
-
* runtime: the platform holds the expanded state, the control is in the Tab order
|
|
228
|
-
* with a real expanded state, and the Page stays a server Component. A Page that
|
|
229
|
-
* shipped a client disclosure for this would put JavaScript on every documentation
|
|
230
|
-
* page in the family to replace a browser feature that has been in the platform
|
|
231
|
-
* since 2018.
|
|
232
|
-
*
|
|
233
|
-
* **The summary's word is the caller's.** `navLabel` and `tocLabel` are already
|
|
234
|
-
* required props and already name these two navigations for a screen reader, so
|
|
235
|
-
* the control that opens one says the same thing the region inside it is called
|
|
236
|
-
* and the Page ships no word of its own. Nothing suppresses the browser's own
|
|
237
|
-
* disclosure marker or its own focus ring: the marker is the cheapest honest
|
|
238
|
-
* signal that the row is a disclosure, and `py-3` puts the target at 44 pixels for
|
|
239
|
-
* a coarse pointer without a variant.
|
|
240
|
-
*/
|
|
241
|
-
function Disclosure({ label, unnamed, children, }) {
|
|
242
|
-
return (_jsxs("details", { "data-slot": "docs-nav-disclosure", children: [_jsx("summary", { className: "text-foreground cursor-pointer py-3 text-sm font-medium", children: label }), _jsx("nav", { "aria-label": label, "data-unnamed-entries": unnamed, className: "pb-4", children: children })] }));
|
|
264
|
+
return (_jsxs("div", { className: "relative lg:sticky lg:top-20", children: [_jsx("nav", { "aria-label": label, "data-unnamed-entries": unnamed, className: "lg:max-h-[calc(100svh-7rem)] lg:overflow-y-auto lg:pe-4 lg:pb-8", children: _jsx(NavList, { entries: entries, currentHref: currentHref, depth: 0 }) }), _jsx("div", { "aria-hidden": "true", "data-slot": "docs-rail-fade", className: "pointer-events-none lg:absolute lg:inset-x-0 lg:bottom-0 lg:h-8 lg:bg-gradient-to-t lg:from-background lg:to-transparent" })] }));
|
|
243
265
|
}
|
|
244
266
|
/* ------------------------------------------------------------------ *
|
|
245
267
|
* The tree
|