@nanisoft/prism-ui 0.16.1 → 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/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 +35 -3
- package/package.json +7 -2
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId, useState } from 'react';
|
|
4
|
+
import { Button } from '../../components/ui/button.js';
|
|
5
|
+
import { Field, FieldDescription, FieldError, FieldGroup } from '../../components/ui/field.js';
|
|
6
|
+
import { Label } from '../../components/ui/label.js';
|
|
7
|
+
import { childLevel, headingSizeClass } from '../../components/ui/section.js';
|
|
8
|
+
import { fieldText, NEEDS_HIDDEN, renderControl, serialize, SELF_LABELLED, } from '../../lib/field-render.js';
|
|
9
|
+
import { cn } from '../../lib/utils.js';
|
|
10
|
+
/**
|
|
11
|
+
* The record write form: a typed field specification, rendered whole.
|
|
12
|
+
*
|
|
13
|
+
* **It takes a field specification and draws the whole form.** `groups` is an
|
|
14
|
+
* ordered list of `FieldSpecGroup`, each an optional heading, an optional
|
|
15
|
+
* description and an ordered list of `FieldSpec`; every field carries a stable
|
|
16
|
+
* `key`, a required `label`, a required `kind` drawn from Prism's own input
|
|
17
|
+
* vocabulary, and optional help, hint, placeholder, disabled flag and starting
|
|
18
|
+
* value. A field whose control this package does not ship carries the `slot` arm,
|
|
19
|
+
* and the Block still draws the label, the help and the error around it, so a
|
|
20
|
+
* field has the same shell either way. Order is the array's order, and the Block
|
|
21
|
+
* never reorders, hides or drops a field.
|
|
22
|
+
*
|
|
23
|
+
* **Prism owns the shape and the vocabulary; the consumer owns the values, the
|
|
24
|
+
* errors and the fetch.** The specification carries no validator, no constraint
|
|
25
|
+
* object, no schema and no pattern, because evaluating a rule is behaviour and a
|
|
26
|
+
* Block ships none. Requiredness is not validation: it is a rendering fact and an
|
|
27
|
+
* HTML fact, so the Block draws the mark and sets the attribute and never checks a
|
|
28
|
+
* value against it.
|
|
29
|
+
*
|
|
30
|
+
* **The error state arrives as an issue list keyed by field.** An entry is a
|
|
31
|
+
* `field` naming a key and a `message` in the product's own words, the shape
|
|
32
|
+
* `FormDialog` and `FormWizard` already take, and a control's issue is drawn
|
|
33
|
+
* under that control. A message about the submission rather than about a control
|
|
34
|
+
* is `submitError`: it names no field and marks at most one.
|
|
35
|
+
*
|
|
36
|
+
* **Where the submission goes is a union with three arms, at least one
|
|
37
|
+
* required.** `action` posts the form to a URL the caller names. `onSubmit` hands
|
|
38
|
+
* the form's own element to a function and makes the Block a client Component.
|
|
39
|
+
* `submit` is a slot holding the caller's own control, placed unstyled in the
|
|
40
|
+
* footer. Each arm forbids the other two, so the compiler holds the rule rather
|
|
41
|
+
* than this paragraph. The save control is `type="submit"` inside a `<form>` the
|
|
42
|
+
* Block renders, and the Block never wires a save to a handler of its own.
|
|
43
|
+
*
|
|
44
|
+
* **Layout is derived, and the only knob is how many columns the fields sit
|
|
45
|
+
* in.** `columns` is `1 | 2` at the form level; two is the only multi-column form
|
|
46
|
+
* layout in which a label stays above its control, and a two-column form fills
|
|
47
|
+
* across rows rather than down columns, because column-wise filling breaks the
|
|
48
|
+
* reading order a screen reader and a keyboard follow. At the narrow breakpoint a
|
|
49
|
+
* two-column form is one column again. There is no per-field layout prop and no
|
|
50
|
+
* slot per region.
|
|
51
|
+
*
|
|
52
|
+
* **A field whose value is absent renders empty rather than absent**, because a
|
|
53
|
+
* form that changes shape while the reader is halfway through it is a form the
|
|
54
|
+
* reader has to read twice. The plain form is uncontrolled where a Prism control
|
|
55
|
+
* can be, so the caller reads the values out of the form element at submit: the
|
|
56
|
+
* `onSubmit` arm passes that element, and `action` lets the browser post it. The
|
|
57
|
+
* handful of Prism controls the platform will not submit on their own hold their
|
|
58
|
+
* value and carry a hidden input under the field's key, so the payload is
|
|
59
|
+
* complete either way.
|
|
60
|
+
*/
|
|
61
|
+
export function RecordForm01(props) {
|
|
62
|
+
const { title, description, groups, columns = 1, issues, submitError, headingLevel = 'h2', footerStart, className, } = props;
|
|
63
|
+
const headingId = useId();
|
|
64
|
+
const prefix = useId();
|
|
65
|
+
const [values, setValues] = useState({});
|
|
66
|
+
const setValue = (key, value) => setValues((previous) => ({ ...previous, [key]: value }));
|
|
67
|
+
const hasSubmit = 'submit' in props;
|
|
68
|
+
const onSubmit = props.onSubmit;
|
|
69
|
+
const hasHandler = typeof onSubmit === 'function';
|
|
70
|
+
const hasAction = typeof props.action === 'string';
|
|
71
|
+
const handleSubmit = (event) => {
|
|
72
|
+
if (!hasHandler)
|
|
73
|
+
return;
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
onSubmit(event.currentTarget);
|
|
76
|
+
};
|
|
77
|
+
const Heading = headingLevel;
|
|
78
|
+
const GroupHeading = title ? childLevel(headingLevel) : headingLevel;
|
|
79
|
+
const grid = columns === 2 ? 'grid grid-cols-1 gap-6 sm:grid-cols-2' : 'flex flex-col gap-6';
|
|
80
|
+
return (_jsxs("form", { "data-slot": "record-form-01-form", ...(hasAction ? { action: props.action, method: 'post' } : null), onSubmit: hasHandler ? handleSubmit : undefined, className: cn('flex w-full flex-col gap-8', className), children: [title || description ? (_jsxs("div", { "data-slot": "record-form-01-header", className: "flex flex-col gap-1", children: [title ? (_jsx(Heading, { id: headingId, className: cn('font-semibold tracking-tight text-balance', headingSizeClass(Heading)), children: title })) : null, description ? (_jsx("p", { className: "text-muted-foreground text-sm", children: description })) : null] })) : null, submitError ? (_jsx(FieldError, { "data-slot": "record-form-01-submit-error", children: submitError })) : null, groups.map((group, groupIndex) => {
|
|
81
|
+
const groupHeadingId = `${prefix}-g${groupIndex}`;
|
|
82
|
+
return (_jsxs("section", { "data-slot": "record-form-01-group", "aria-labelledby": group.label ? groupHeadingId : undefined, className: "flex flex-col gap-4", children: [group.label ? (_jsx(GroupHeading, { id: groupHeadingId, className: cn('font-semibold tracking-tight text-balance', headingSizeClass(GroupHeading)), children: group.label })) : null, group.description ? (_jsx("p", { className: "text-muted-foreground text-sm", children: group.description })) : null, _jsx(FieldGroup, { "data-slot": "record-form-01-fields", className: grid, children: group.fields.map((field, fieldIndex) => {
|
|
83
|
+
const kind = field.kind.toLowerCase();
|
|
84
|
+
const id = `${prefix}-f${fieldIndex}`;
|
|
85
|
+
const labelId = `${prefix}-l${fieldIndex}`;
|
|
86
|
+
const helpId = field.help === undefined ? undefined : `${prefix}-h${fieldIndex}`;
|
|
87
|
+
const fieldIssues = (issues ?? []).filter((issue) => issue.field === field.key);
|
|
88
|
+
const errorId = fieldIssues.length > 0 ? `${prefix}-e${fieldIndex}` : undefined;
|
|
89
|
+
const describedBy = helpId === undefined
|
|
90
|
+
? errorId
|
|
91
|
+
: errorId === undefined
|
|
92
|
+
? helpId
|
|
93
|
+
: `${helpId} ${errorId}`;
|
|
94
|
+
const ctx = {
|
|
95
|
+
id,
|
|
96
|
+
labelId,
|
|
97
|
+
describedBy,
|
|
98
|
+
invalid: fieldIssues.length > 0,
|
|
99
|
+
text: fieldText(field),
|
|
100
|
+
values,
|
|
101
|
+
setValue,
|
|
102
|
+
};
|
|
103
|
+
return (_jsxs(Field, { "data-slot": "record-form-01-field", children: [SELF_LABELLED.has(kind) ? null : (_jsx(Label, { id: labelId, htmlFor: id, required: field.required, disabled: field.disabled, children: field.label })), renderControl(field, ctx), NEEDS_HIDDEN.has(kind) ? (_jsx("input", { type: "hidden", name: field.key, value: serialize(ctx.values[field.key] ?? field.defaultValue) })) : null, field.help === undefined ? null : (_jsx(FieldDescription, { id: helpId, children: field.help })), fieldIssues.length === 0 ? null : (_jsx(FieldError, { id: errorId, children: fieldIssues.map((issue, issueIndex) => (_jsx("span", { "data-slot": "record-form-01-issue", children: issue.message }, issueIndex))) }))] }, field.key));
|
|
104
|
+
}) })] }, group.id ?? groupIndex));
|
|
105
|
+
}), _jsxs("div", { "data-slot": "record-form-01-footer", className: "flex flex-wrap items-center justify-end gap-2", children: [footerStart, hasSubmit ? (props.submit) : (_jsx(Button, { "data-slot": "record-form-01-save", type: "submit", children: props.submitLabel }))] })] }));
|
|
106
|
+
}
|
|
107
|
+
export default RecordForm01;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/record-grid-01/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACrD,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RecordGrid01, default } from './record-grid.js';
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type HeadingLevel } from '../../components/ui/section.js';
|
|
3
|
+
import type { FieldSpec } from '../../lib/spec.js';
|
|
4
|
+
/**
|
|
5
|
+
* One edit a reader made in place.
|
|
6
|
+
*
|
|
7
|
+
* `rowId` is the record's stable identity from `getRowId` and never its position,
|
|
8
|
+
* because a row's index moves the moment the caller re-sorts or re-pages and a
|
|
9
|
+
* change keyed by a position would be applied to the wrong record. `key` is the
|
|
10
|
+
* column's own `key` and never the words of its header, for the reason the field
|
|
11
|
+
* specification gives: a key built from a label's words breaks the moment the label
|
|
12
|
+
* is translated. `value` is whatever the control reported, in the shape that arm
|
|
13
|
+
* reports it.
|
|
14
|
+
*/
|
|
15
|
+
export type RecordGrid01Change = {
|
|
16
|
+
/** The record's stable identity, from `getRowId`. */
|
|
17
|
+
rowId: string;
|
|
18
|
+
/** The edited column's own `key`, and never the words of its header. */
|
|
19
|
+
key: string;
|
|
20
|
+
/** The value the control reported, in the shape that control reports it. */
|
|
21
|
+
value: unknown;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Every string the grid renders. Required because the Block ships no copy of its
|
|
25
|
+
* own, and an empty grid still has a sentence to say.
|
|
26
|
+
*/
|
|
27
|
+
export type RecordGrid01Labels = {
|
|
28
|
+
/** Shown in the body when `rows` is empty and `emptyMessage` is not set. */
|
|
29
|
+
empty: string;
|
|
30
|
+
};
|
|
31
|
+
/** The props a `RecordGrid01` accepts. */
|
|
32
|
+
export type RecordGrid01Props = {
|
|
33
|
+
/** The grid's own heading, absent for a grid that needs none. */
|
|
34
|
+
title?: ReactNode;
|
|
35
|
+
/** One line under the heading saying what editing here does. */
|
|
36
|
+
description?: ReactNode;
|
|
37
|
+
/**
|
|
38
|
+
* Heading level for the grid's own heading. See `HeadingLevel`.
|
|
39
|
+
*
|
|
40
|
+
* @defaultValue 'h2'
|
|
41
|
+
*/
|
|
42
|
+
headingLevel?: HeadingLevel;
|
|
43
|
+
/** Names the grid for assistive technology when no heading does. */
|
|
44
|
+
caption?: ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* The columns, as the shared field specification.
|
|
47
|
+
*
|
|
48
|
+
* `key`, `label` and `kind` are required on each one, and the whole list is
|
|
49
|
+
* drawn in the order it is written. The header of a column is its `label` and
|
|
50
|
+
* the control under it is the one its `kind` names, so the words a consumer
|
|
51
|
+
* learns on a write form are the words on a grid.
|
|
52
|
+
*/
|
|
53
|
+
columns: readonly FieldSpec[];
|
|
54
|
+
/** The rows for the grid. The Block renders them; it never fetches or reorders. */
|
|
55
|
+
rows: readonly Record<string, unknown>[];
|
|
56
|
+
/**
|
|
57
|
+
* Returns a stable identity for a row.
|
|
58
|
+
*
|
|
59
|
+
* Required rather than optional, because paging and re-sorting move a row's
|
|
60
|
+
* index, and a change reported against a position would be written to the wrong
|
|
61
|
+
* record.
|
|
62
|
+
*/
|
|
63
|
+
getRowId: (row: Record<string, unknown>) => string;
|
|
64
|
+
/**
|
|
65
|
+
* Called with every edit, as the cell it happened in.
|
|
66
|
+
*
|
|
67
|
+
* Required, because a control that edits a value with nowhere to report it is a
|
|
68
|
+
* control a reader can type into and nothing can hear. The Block holds the
|
|
69
|
+
* in-progress values so a cell redraws as it is typed, and it reports each one
|
|
70
|
+
* through here rather than submitting a form.
|
|
71
|
+
*/
|
|
72
|
+
onCellChange: (change: RecordGrid01Change) => void;
|
|
73
|
+
/** Replaces the fallback empty line. */
|
|
74
|
+
emptyMessage?: ReactNode;
|
|
75
|
+
labels: RecordGrid01Labels;
|
|
76
|
+
/** Layout only. Changing a Prism-owned visual property from here is prohibited. */
|
|
77
|
+
className?: string;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* The editable record grid: many records as a grid whose cells are edited in place.
|
|
81
|
+
*
|
|
82
|
+
* **It is a write, and it is a different job from the record index.** `DataTable01`
|
|
83
|
+
* draws the rows it was handed and reports what a reader asked for: a sort, a
|
|
84
|
+
* filter, a page, a selection. Nothing in it changes a value. This Block's whole
|
|
85
|
+
* contract is the opposite: each cell is a control, a reader types into it, and the
|
|
86
|
+
* Block reports the edit. `DESIGN.md` rules that a grid edited in place is a write
|
|
87
|
+
* and not the index with one more prop, and this is that write as its own Item.
|
|
88
|
+
*
|
|
89
|
+
* **Its columns are the shared field specification, and that is the decision the
|
|
90
|
+
* closed unions forced.** A cell that writes is a control, and the only vocabulary
|
|
91
|
+
* this package publishes for a control is `FieldSpec`. `ColumnKind` is the
|
|
92
|
+
* vocabulary for a value a reader reads, and it is held disjoint from `FieldKind`
|
|
93
|
+
* by `scripts/check-spec-unions.mjs`: a cell that writes named on `ColumnKind`
|
|
94
|
+
* would either draw a field Component inside a table the index owns or name
|
|
95
|
+
* something no Component answers to, and the gate reports both. So a write grid
|
|
96
|
+
* takes the field union, and the fact that it needs to is the gate saying the job
|
|
97
|
+
* is a different one. A column's `label` is its header and its `kind` is the
|
|
98
|
+
* control drawn under it, so a grid column and a form field are one declaration.
|
|
99
|
+
*
|
|
100
|
+
* **It holds the in-progress values and reports every change.** This is the same
|
|
101
|
+
* kind of held value the record index keeps for its selection set: a set of values
|
|
102
|
+
* the caller handed for the rows about to be drawn, which a reader edits and the
|
|
103
|
+
* Block redraws from. It fetches nothing, sorts nothing, filters nothing and pages
|
|
104
|
+
* nothing, and it never derives a value from application state. A caller that wants
|
|
105
|
+
* the edits mirrored writes one line in `onCellChange`; the values a cell shows are
|
|
106
|
+
* the caller's row value until the reader edits that cell, and the reader's value
|
|
107
|
+
* after.
|
|
108
|
+
*
|
|
109
|
+
* **The controls are the ones this package ships, drawn by the same renderer a form
|
|
110
|
+
* uses.** `renderControl` is the one place a `FieldKind` becomes a control, so a
|
|
111
|
+
* cell and a form field draw the same Component and a kind added to the union fails
|
|
112
|
+
* the compiler in one place rather than two. The arms that hold a value and report a
|
|
113
|
+
* change through the shared context are the editable ones (`Input`, `Textarea`,
|
|
114
|
+
* `NumberField`, `MoneyField`, `SearchField`, `PasswordField`, `NativeSelect`,
|
|
115
|
+
* `ToggleGroup`, `Toggle`, `Switch`, `Calendar`, `Dropzone`, `FileUpload`,
|
|
116
|
+
* `ImageListField`, `RepeatableRows`); an arm that submits through a form element
|
|
117
|
+
* it owns rather than reporting through the context (`Select`, `Combobox`,
|
|
118
|
+
* `DatePicker`, `Slider` and their kin) is drawn and reaches no report, and that is
|
|
119
|
+
* the honest limit of a Block that ships no form of its own. A caller who needs one
|
|
120
|
+
* of those brings their own control through the `slot` arm, which the renderer
|
|
121
|
+
* places in the cell.
|
|
122
|
+
*
|
|
123
|
+
* **The grid names every cell's control, and it is the columns that name them.**
|
|
124
|
+
* A column's header carries its visible label, so a cell draws a control the reader
|
|
125
|
+
* can see named; the control itself is given the column's own words as an
|
|
126
|
+
* assistive-technology name where the Component does not carry its own, and the
|
|
127
|
+
* table's own row and column structure is what says which record a cell belongs to.
|
|
128
|
+
* The table takes its accessible name from its caption when the caller brings one
|
|
129
|
+
* and from the heading otherwise, which is the same rule `DataTable01` follows and
|
|
130
|
+
* the same reason: a table a reader reaches without a name is a table every cell
|
|
131
|
+
* announces as untitled.
|
|
132
|
+
*
|
|
133
|
+
* **It owns no command.** There is no save button, no delete, no bulk action and no
|
|
134
|
+
* confirmation: every edit is reported the moment it is made, and what to do with it
|
|
135
|
+
* is the caller's. A caller who wants a save adds their own control beside the grid,
|
|
136
|
+
* in the product's own copy and on its own store, rather than asking this Block to
|
|
137
|
+
* hold a draft the caller cannot see.
|
|
138
|
+
*
|
|
139
|
+
* **Nothing here is a rule.** The grid draws the mark for a `required` column and
|
|
140
|
+
* sets the attribute, and it never checks a value against it: validation is the
|
|
141
|
+
* consumer's, entirely, and evaluating a rule is behaviour a Block does not own.
|
|
142
|
+
*/
|
|
143
|
+
export declare function RecordGrid01(props: RecordGrid01Props): import("react").JSX.Element;
|
|
144
|
+
export default RecordGrid01;
|
|
145
|
+
//# sourceMappingURL=record-grid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-grid.d.ts","sourceRoot":"","sources":["../../../src/blocks/record-grid-01/record-grid.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGvD,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAWjF,OAAO,KAAK,EAAa,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG1D;;;;;;;;;;GAUG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAA;IACb,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAA;IACX,4EAA4E;IAC5E,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,0CAA0C;AAC1C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,iEAAiE;IACjE,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,gEAAgE;IAChE,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,oEAAoE;IACpE,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;;;;;;;OAOG;IACH,OAAO,EAAE,SAAS,SAAS,EAAE,CAAA;IAC7B,mFAAmF;IACnF,IAAI,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IACxC;;;;;;OAMG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAA;IAClD;;;;;;;OAOG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAClD,wCAAwC;IACxC,YAAY,CAAC,EAAE,SAAS,CAAA;IACxB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BAqHpD;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId, useState } from 'react';
|
|
4
|
+
import { Label } from '../../components/ui/label.js';
|
|
5
|
+
import { headingSizeClass } from '../../components/ui/section.js';
|
|
6
|
+
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, } from '../../components/ui/table.js';
|
|
7
|
+
import { fieldText, renderControl, SELF_LABELLED } from '../../lib/field-render.js';
|
|
8
|
+
import { cn } from '../../lib/utils.js';
|
|
9
|
+
/**
|
|
10
|
+
* The editable record grid: many records as a grid whose cells are edited in place.
|
|
11
|
+
*
|
|
12
|
+
* **It is a write, and it is a different job from the record index.** `DataTable01`
|
|
13
|
+
* draws the rows it was handed and reports what a reader asked for: a sort, a
|
|
14
|
+
* filter, a page, a selection. Nothing in it changes a value. This Block's whole
|
|
15
|
+
* contract is the opposite: each cell is a control, a reader types into it, and the
|
|
16
|
+
* Block reports the edit. `DESIGN.md` rules that a grid edited in place is a write
|
|
17
|
+
* and not the index with one more prop, and this is that write as its own Item.
|
|
18
|
+
*
|
|
19
|
+
* **Its columns are the shared field specification, and that is the decision the
|
|
20
|
+
* closed unions forced.** A cell that writes is a control, and the only vocabulary
|
|
21
|
+
* this package publishes for a control is `FieldSpec`. `ColumnKind` is the
|
|
22
|
+
* vocabulary for a value a reader reads, and it is held disjoint from `FieldKind`
|
|
23
|
+
* by `scripts/check-spec-unions.mjs`: a cell that writes named on `ColumnKind`
|
|
24
|
+
* would either draw a field Component inside a table the index owns or name
|
|
25
|
+
* something no Component answers to, and the gate reports both. So a write grid
|
|
26
|
+
* takes the field union, and the fact that it needs to is the gate saying the job
|
|
27
|
+
* is a different one. A column's `label` is its header and its `kind` is the
|
|
28
|
+
* control drawn under it, so a grid column and a form field are one declaration.
|
|
29
|
+
*
|
|
30
|
+
* **It holds the in-progress values and reports every change.** This is the same
|
|
31
|
+
* kind of held value the record index keeps for its selection set: a set of values
|
|
32
|
+
* the caller handed for the rows about to be drawn, which a reader edits and the
|
|
33
|
+
* Block redraws from. It fetches nothing, sorts nothing, filters nothing and pages
|
|
34
|
+
* nothing, and it never derives a value from application state. A caller that wants
|
|
35
|
+
* the edits mirrored writes one line in `onCellChange`; the values a cell shows are
|
|
36
|
+
* the caller's row value until the reader edits that cell, and the reader's value
|
|
37
|
+
* after.
|
|
38
|
+
*
|
|
39
|
+
* **The controls are the ones this package ships, drawn by the same renderer a form
|
|
40
|
+
* uses.** `renderControl` is the one place a `FieldKind` becomes a control, so a
|
|
41
|
+
* cell and a form field draw the same Component and a kind added to the union fails
|
|
42
|
+
* the compiler in one place rather than two. The arms that hold a value and report a
|
|
43
|
+
* change through the shared context are the editable ones (`Input`, `Textarea`,
|
|
44
|
+
* `NumberField`, `MoneyField`, `SearchField`, `PasswordField`, `NativeSelect`,
|
|
45
|
+
* `ToggleGroup`, `Toggle`, `Switch`, `Calendar`, `Dropzone`, `FileUpload`,
|
|
46
|
+
* `ImageListField`, `RepeatableRows`); an arm that submits through a form element
|
|
47
|
+
* it owns rather than reporting through the context (`Select`, `Combobox`,
|
|
48
|
+
* `DatePicker`, `Slider` and their kin) is drawn and reaches no report, and that is
|
|
49
|
+
* the honest limit of a Block that ships no form of its own. A caller who needs one
|
|
50
|
+
* of those brings their own control through the `slot` arm, which the renderer
|
|
51
|
+
* places in the cell.
|
|
52
|
+
*
|
|
53
|
+
* **The grid names every cell's control, and it is the columns that name them.**
|
|
54
|
+
* A column's header carries its visible label, so a cell draws a control the reader
|
|
55
|
+
* can see named; the control itself is given the column's own words as an
|
|
56
|
+
* assistive-technology name where the Component does not carry its own, and the
|
|
57
|
+
* table's own row and column structure is what says which record a cell belongs to.
|
|
58
|
+
* The table takes its accessible name from its caption when the caller brings one
|
|
59
|
+
* and from the heading otherwise, which is the same rule `DataTable01` follows and
|
|
60
|
+
* the same reason: a table a reader reaches without a name is a table every cell
|
|
61
|
+
* announces as untitled.
|
|
62
|
+
*
|
|
63
|
+
* **It owns no command.** There is no save button, no delete, no bulk action and no
|
|
64
|
+
* confirmation: every edit is reported the moment it is made, and what to do with it
|
|
65
|
+
* is the caller's. A caller who wants a save adds their own control beside the grid,
|
|
66
|
+
* in the product's own copy and on its own store, rather than asking this Block to
|
|
67
|
+
* hold a draft the caller cannot see.
|
|
68
|
+
*
|
|
69
|
+
* **Nothing here is a rule.** The grid draws the mark for a `required` column and
|
|
70
|
+
* sets the attribute, and it never checks a value against it: validation is the
|
|
71
|
+
* consumer's, entirely, and evaluating a rule is behaviour a Block does not own.
|
|
72
|
+
*/
|
|
73
|
+
export function RecordGrid01(props) {
|
|
74
|
+
const { title, description, headingLevel = 'h2', caption, columns, rows, getRowId, onCellChange, emptyMessage, labels, className, } = props;
|
|
75
|
+
const Heading = headingLevel;
|
|
76
|
+
const headingId = useId();
|
|
77
|
+
const prefix = useId();
|
|
78
|
+
const [edited, setEdited] = useState({});
|
|
79
|
+
const valueFor = (rowId, row, field) => {
|
|
80
|
+
const rowEdits = edited[rowId];
|
|
81
|
+
if (rowEdits !== undefined && Object.prototype.hasOwnProperty.call(rowEdits, field.key)) {
|
|
82
|
+
return rowEdits[field.key];
|
|
83
|
+
}
|
|
84
|
+
const rowValue = row[field.key];
|
|
85
|
+
return rowValue === undefined ? field.defaultValue : rowValue;
|
|
86
|
+
};
|
|
87
|
+
const setCell = (rowId) => (key, value) => {
|
|
88
|
+
setEdited((previous) => ({
|
|
89
|
+
...previous,
|
|
90
|
+
[rowId]: { ...(previous[rowId] ?? {}), [key]: value },
|
|
91
|
+
}));
|
|
92
|
+
onCellChange({ rowId, key, value });
|
|
93
|
+
};
|
|
94
|
+
return (_jsxs("div", { "data-slot": "record-grid-01", className: cn('flex flex-col gap-4', className), children: [title || description ? (_jsxs("div", { "data-slot": "record-grid-01-header", className: "flex flex-col gap-1", children: [title ? (_jsx(Heading, { id: headingId, className: cn('font-semibold tracking-tight text-balance', headingSizeClass(Heading)), children: title })) : null, description ? (_jsx("p", { className: "text-muted-foreground text-sm", children: description })) : null] })) : null, _jsx("div", { className: "border-border overflow-hidden rounded-xl border", children: _jsxs(Table, { "aria-labelledby": caption === undefined && title ? headingId : undefined, children: [caption ? _jsx(TableCaption, { children: caption }) : null, _jsx(TableHeader, { children: _jsx(TableRow, { children: columns.map((column) => (_jsx(TableHead, { children: column.label }, column.key))) }) }), _jsx(TableBody, { children: rows.length ? (rows.map((row) => {
|
|
95
|
+
const rowId = getRowId(row);
|
|
96
|
+
return (_jsx(TableRow, { "data-slot": "record-grid-01-row", children: columns.map((column, columnIndex) => {
|
|
97
|
+
const kind = column.kind.toLowerCase();
|
|
98
|
+
const id = `${prefix}-${rowId}-${columnIndex}`;
|
|
99
|
+
const labelId = `${id}-label`;
|
|
100
|
+
const ctx = {
|
|
101
|
+
id,
|
|
102
|
+
labelId,
|
|
103
|
+
describedBy: undefined,
|
|
104
|
+
invalid: false,
|
|
105
|
+
text: fieldText(column),
|
|
106
|
+
values: { [column.key]: valueFor(rowId, row, column) },
|
|
107
|
+
setValue: setCell(rowId),
|
|
108
|
+
controlled: true,
|
|
109
|
+
};
|
|
110
|
+
return (_jsxs(TableCell, { "data-slot": "record-grid-01-cell", children: [SELF_LABELLED.has(kind) ? null : (_jsx(Label, { id: labelId, htmlFor: id, required: column.required, className: "sr-only", children: column.label })), renderControl(column, ctx), column.help === undefined ? null : (_jsx("span", { className: "sr-only", children: column.help }))] }, column.key));
|
|
111
|
+
}) }, rowId));
|
|
112
|
+
})) : (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: Math.max(1, columns.length), className: "text-muted-foreground h-24 text-center", children: emptyMessage ?? labels.empty }) })) })] }) })] }));
|
|
113
|
+
}
|
|
114
|
+
export default RecordGrid01;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/record-wizard-01/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RecordWizard01, default } from './record-wizard.js';
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { FieldSpecGroup } from '../../lib/spec.js';
|
|
3
|
+
import type { RecordForm01Issue } from '../record-form-01/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* The props a `RecordWizard01` accepts.
|
|
6
|
+
*
|
|
7
|
+
* **The step is the consumer's.** `current` is required and controlled,
|
|
8
|
+
* `onStepChange` is required, and the Block draws the step it was handed and no
|
|
9
|
+
* reachability at all: no completed mark beyond the one the shipped rail already
|
|
10
|
+
* derives from the index, no disabled step, no skipped step and no count of what
|
|
11
|
+
* has been answered. Reachability is branching, and branching is the consumer's.
|
|
12
|
+
*
|
|
13
|
+
* **The specification is per step, and a step is a `FieldSpecGroup`.** Nothing new
|
|
14
|
+
* is declared in order to hold the steps: a step is the shared group type, with a
|
|
15
|
+
* stable `id` and a `label` that is a `string` rather than a node, because the rail
|
|
16
|
+
* draws the same word at the width a step gets in a six-step row, so a step's rail
|
|
17
|
+
* label and its own heading are one string by construction rather than two words
|
|
18
|
+
* kept in step by a caller. One specification sliced by a caller-supplied grouping
|
|
19
|
+
* is refused: the specification already carries the groups, and a second list saying
|
|
20
|
+
* which groups sit on which step would be free to disagree with it.
|
|
21
|
+
*/
|
|
22
|
+
export type RecordWizard01Props = {
|
|
23
|
+
/**
|
|
24
|
+
* The steps, in order, each a `FieldSpecGroup` with a stable `id` and a string
|
|
25
|
+
* `label`.
|
|
26
|
+
*
|
|
27
|
+
* Each step is drawn as a heading and its fields, one step at a time. The
|
|
28
|
+
* `id` is required because the caller keys its own per-step state by it, and a
|
|
29
|
+
* sequence whose entries have no identity is a sequence whose saved answers have
|
|
30
|
+
* nowhere to live.
|
|
31
|
+
*/
|
|
32
|
+
steps: readonly FieldSpecGroup[];
|
|
33
|
+
/**
|
|
34
|
+
* The step the reader is on, counting from zero.
|
|
35
|
+
*
|
|
36
|
+
* Controlled and clamped by the shipped wizard, and clamped rather than optional
|
|
37
|
+
* for the reason `Steps` gives: a sequence with no position is a list. An index
|
|
38
|
+
* the specification does not contain draws a real step rather than nothing,
|
|
39
|
+
* because a region with no route out is worse; the nearest step is the one answer
|
|
40
|
+
* that is not a claim about a cause.
|
|
41
|
+
*/
|
|
42
|
+
current: number;
|
|
43
|
+
/**
|
|
44
|
+
* Called when the reader moves, given the step's index and which way they asked.
|
|
45
|
+
*
|
|
46
|
+
* Required, and the second argument is there because forward and back are not the
|
|
47
|
+
* same move. A refused forward press arrives here as nothing at all, so a caller
|
|
48
|
+
* who wants to know its validation ran hears it from the issue list rather than
|
|
49
|
+
* from this callback.
|
|
50
|
+
*/
|
|
51
|
+
onStepChange: (index: number, direction: 'forward' | 'back') => void;
|
|
52
|
+
/**
|
|
53
|
+
* The values, controlled, keyed by field.
|
|
54
|
+
*
|
|
55
|
+
* **Entered values do not survive a step change inside this package.** Only the
|
|
56
|
+
* current step's fields are in the document, and there is no draft to restore
|
|
57
|
+
* from, because a Block that held the draft would be holding application state.
|
|
58
|
+
* So every field on this arm is controlled and carries the consumer's value and
|
|
59
|
+
* change handler, and the values are the consumer's from the first keystroke. The
|
|
60
|
+
* named cost is one state object per screen instead of one form.
|
|
61
|
+
*/
|
|
62
|
+
values: Record<string, unknown>;
|
|
63
|
+
/** Sets one controlled field's value, keyed by field. */
|
|
64
|
+
onValueChange: (key: string, value: unknown) => void;
|
|
65
|
+
/**
|
|
66
|
+
* The issues to draw, keyed by field, from the shape `FormDialog`, `FormWizard`
|
|
67
|
+
* and the record write form already publish.
|
|
68
|
+
*
|
|
69
|
+
* **An issue naming a key that is not on the step being drawn is left undrawn, and
|
|
70
|
+
* the reader is not moved.** There is no control on this step for the message to
|
|
71
|
+
* sit under, and moving the reader is a call on `onStepChange`, which the caller
|
|
72
|
+
* already holds. A cross-step rule is a message about the submission and belongs
|
|
73
|
+
* to the sequence's own `validate`, in the caller's words.
|
|
74
|
+
*/
|
|
75
|
+
issues?: readonly RecordForm01Issue[];
|
|
76
|
+
/** The label of the control that goes back. */
|
|
77
|
+
backLabel: ReactNode;
|
|
78
|
+
/** The label of the control that goes forward, on every step but the last. */
|
|
79
|
+
nextLabel: ReactNode;
|
|
80
|
+
/** The label of the control on the last step, which submits rather than advances. */
|
|
81
|
+
finishLabel: ReactNode;
|
|
82
|
+
/** The heading above a refusal. */
|
|
83
|
+
blockedLabel: ReactNode;
|
|
84
|
+
/** The accessible name of the progress rail. */
|
|
85
|
+
progressLabel: string;
|
|
86
|
+
/** The accessible name of one issue's control, given the field it belongs to. */
|
|
87
|
+
issueLabel: (field: string) => string;
|
|
88
|
+
/** The words for the sequence's keyboard model, read once. */
|
|
89
|
+
instructionsLabel: string;
|
|
90
|
+
/** Layout only. Changing a Prism-owned visual property from here is prohibited. */
|
|
91
|
+
className?: string;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* The multi-step record write form: one group of fields at a time above the rail
|
|
95
|
+
* the package already ships.
|
|
96
|
+
*
|
|
97
|
+
* **This is the write form's second arrangement and not a `-02`.** A wizard draws
|
|
98
|
+
* one group of fields at a time, puts a rail above them, and asks a decision the
|
|
99
|
+
* plain form never asks, which is whether this step may be left forwards. One Item
|
|
100
|
+
* could not draw both without gaining the rail, the partition and that decision. It
|
|
101
|
+
* is a property of how many fields the record has rather than one of two renderings
|
|
102
|
+
* a consumer picks between on purpose, which is what a `-02` is for, so it earns
|
|
103
|
+
* its own name.
|
|
104
|
+
*
|
|
105
|
+
* **Back, the forward control and the rail are the shipped wizard's.** This Block
|
|
106
|
+
* renders none of them: it composes `FormWizard`, hands it the steps, and draws each
|
|
107
|
+
* step's fields as that step's children. Every one of those controls is a call on
|
|
108
|
+
* the caller's own step change, and the rail is an ordered indicator with no opinion
|
|
109
|
+
* about whether a reader may move, so a caller who wants a navigable rail writes
|
|
110
|
+
* call to action links carrying their own destinations beside this Block. A Block
|
|
111
|
+
* that cannot make a control work should not render one, which is why this one
|
|
112
|
+
* renders none of the three.
|
|
113
|
+
*
|
|
114
|
+
* **The stepped arm declares no submission arm of its own.** On the last step the
|
|
115
|
+
* forward control is the form's submit and it reports the last index with the
|
|
116
|
+
* direction `forward`, so the finish signal is a callback the caller already passes
|
|
117
|
+
* and no second prop is needed to name it. An `action` arm would be an arm that
|
|
118
|
+
* cannot be honoured: the shipped wizard refuses the browser's own submission
|
|
119
|
+
* because its submit *is* the forward control. A caller whose answer is a URL post
|
|
120
|
+
* composes the per-step form beside this Block.
|
|
121
|
+
*
|
|
122
|
+
* **Every field is controlled and the Block holds no value of its own across a step
|
|
123
|
+
* change.** Only the current step's fields are in the document, so a step that
|
|
124
|
+
* unmounts takes every uncontrolled value in it with it, and there is no draft to
|
|
125
|
+
* restore from because a Block that held the draft would be holding application
|
|
126
|
+
* state. The values are the consumer's from the first keystroke, and the cost is one
|
|
127
|
+
* state object per screen instead of one form.
|
|
128
|
+
*
|
|
129
|
+
* **The step is the consumer's, and the Block draws the step it was handed and no
|
|
130
|
+
* reachability at all.** It draws nothing about a step it is not showing: no
|
|
131
|
+
* completed mark beyond the one the shipped rail already derives from the index, no
|
|
132
|
+
* disabled step, no skipped step and no count of what has been answered. An index
|
|
133
|
+
* the specification does not contain draws a real step rather than nothing, because
|
|
134
|
+
* a region with no route out is worse and drawing the nearest step is the one answer
|
|
135
|
+
* that is not a claim about a cause. It publishes no state for a step that does not
|
|
136
|
+
* exist, because a step that does not exist, a stale link and a step this reader may
|
|
137
|
+
* not see are one index and three sentences.
|
|
138
|
+
*
|
|
139
|
+
* **An issue naming a key off the current step is left undrawn and the reader is not
|
|
140
|
+
* moved.** Validation is the consumer's, entirely: this Block evaluates no rule,
|
|
141
|
+
* carries no validator and derives no fraction complete, because a fraction over a
|
|
142
|
+
* sequence whose steps are gated by rules it cannot see is false the moment a
|
|
143
|
+
* consumer skips one. A cross-step rule arrives as an issue and is drawn only while
|
|
144
|
+
* its control is on the step being drawn.
|
|
145
|
+
*
|
|
146
|
+
* It is a client Component, because the shipped wizard is one and every value prop
|
|
147
|
+
* here is a function the caller hands it, which is a client-to-client boundary
|
|
148
|
+
* wherever it is written.
|
|
149
|
+
*/
|
|
150
|
+
export declare function RecordWizard01({ steps, current, onStepChange, values, onValueChange, issues, backLabel, nextLabel, finishLabel, blockedLabel, progressLabel, issueLabel, instructionsLabel, className, }: RecordWizard01Props): import("react").JSX.Element;
|
|
151
|
+
export default RecordWizard01;
|
|
152
|
+
//# sourceMappingURL=record-wizard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-wizard.d.ts","sourceRoot":"","sources":["../../../src/blocks/record-wizard-01/record-wizard.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAgB7C,OAAO,KAAK,EAAa,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;;;;;OAQG;IACH,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;IAChC;;;;;;;;OAQG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;OAOG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,MAAM,KAAK,IAAI,CAAA;IACpE;;;;;;;;;OASG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,yDAAyD;IACzD,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACpD;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACrC,+CAA+C;IAC/C,SAAS,EAAE,SAAS,CAAA;IACpB,8EAA8E;IAC9E,SAAS,EAAE,SAAS,CAAA;IACpB,qFAAqF;IACrF,WAAW,EAAE,SAAS,CAAA;IACtB,mCAAmC;IACnC,YAAY,EAAE,SAAS,CAAA;IACvB,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAA;IACrB,iFAAiF;IACjF,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACrC,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,CAAA;IACzB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AA6HD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,OAAO,EACP,YAAY,EACZ,MAAM,EACN,aAAa,EACb,MAAM,EACN,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,SAAS,GACV,EAAE,mBAAmB,+BA4CrB;AAED,eAAe,cAAc,CAAA"}
|