@object-ui/plugin-form 17.5.0 → 17.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +654 -0
- package/README.md +440 -77
- package/dist/DrawerForm.d.ts.map +1 -1
- package/dist/EmbeddableForm.d.ts.map +1 -1
- package/dist/MasterDetailForm.d.ts.map +1 -1
- package/dist/ModalForm.d.ts.map +1 -1
- package/dist/ObjectForm.d.ts +18 -2
- package/dist/ObjectForm.d.ts.map +1 -1
- package/dist/SplitForm.d.ts.map +1 -1
- package/dist/TabbedForm.d.ts.map +1 -1
- package/dist/WizardForm.d.ts +33 -0
- package/dist/WizardForm.d.ts.map +1 -1
- package/dist/deriveMasterDetail.d.ts +1 -1
- package/dist/flatFields.d.ts +21 -0
- package/dist/flatFields.d.ts.map +1 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1457 -1090
- package/dist/index.umd.cjs +1 -1
- package/dist/schemaDefaults.d.ts +29 -29
- package/dist/schemaDefaults.d.ts.map +1 -1
- package/dist/sectionFields.d.ts +9 -0
- package/dist/sectionFields.d.ts.map +1 -1
- package/dist/submitRedirect.d.ts +148 -0
- package/dist/submitRedirect.d.ts.map +1 -0
- package/dist/submitRedirectNavigation.d.ts +82 -0
- package/dist/submitRedirectNavigation.d.ts.map +1 -0
- package/dist/successBehavior.d.ts +18 -1
- package/dist/successBehavior.d.ts.map +1 -1
- package/dist/thankYouRedirectCountdown.d.ts +17 -0
- package/dist/thankYouRedirectCountdown.d.ts.map +1 -0
- package/dist/thankYouRedirectNavigation.d.ts +111 -0
- package/dist/thankYouRedirectNavigation.d.ts.map +1 -0
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -35,53 +35,222 @@ const schema = {
|
|
|
35
35
|
};
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
###
|
|
38
|
+
### What the side-effect import registers
|
|
39
|
+
|
|
40
|
+
There is no component map to iterate: registration is a side effect of importing
|
|
41
|
+
the package entry, which makes six `ComponentRegistry.register(...)` calls. These
|
|
42
|
+
are the schema types those calls claim, read off the calls themselves in
|
|
43
|
+
`src/index.tsx`:
|
|
44
|
+
|
|
45
|
+
| Namespaced type | Bare-name fallback | Component behind it |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `plugin-form:object-form` | `object-form` | `ObjectForm` — metadata-driven form over one record |
|
|
48
|
+
| `view:form` | none | the same renderer under the view protocol |
|
|
49
|
+
| `plugin-form:embeddable-form` | `embeddable-form` | `EmbeddableForm` — standalone public form |
|
|
50
|
+
| `plugin-form:form-analytics` | `form-analytics` | `FormAnalytics` — submission dashboard |
|
|
51
|
+
| `plugin-form:object-master-detail-form` | `object-master-detail-form` | `MasterDetailForm` — parent + child line items in one submit |
|
|
52
|
+
| `record:line_items` | none | `LineItemsPanel` — child grid bound to the record on the page |
|
|
53
|
+
|
|
54
|
+
`ComponentRegistry.register` also registers a namespaced type under its bare name
|
|
55
|
+
for backwards compatibility, unless the call passes `skipFallback: true`
|
|
56
|
+
(`@object-ui/core`, `src/registry/Registry.ts`). Two calls here do: bare `form`
|
|
57
|
+
stays the basic `@object-ui/components` form, and bare `line_items` is left to
|
|
58
|
+
whoever else claims it.
|
|
59
|
+
|
|
60
|
+
### Public exports
|
|
61
|
+
|
|
62
|
+
The package entry exports these — components, their prop/schema types, and the
|
|
63
|
+
layout helpers. There is no aggregate map among them:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import {
|
|
67
|
+
ObjectForm,
|
|
68
|
+
TabbedForm,
|
|
69
|
+
WizardForm,
|
|
70
|
+
SplitForm,
|
|
71
|
+
DrawerForm,
|
|
72
|
+
ModalForm,
|
|
73
|
+
EmbeddableForm,
|
|
74
|
+
MasterDetailForm,
|
|
75
|
+
LineItemsPanel,
|
|
76
|
+
FormAnalytics,
|
|
77
|
+
FormSectionContainer,
|
|
78
|
+
applyAutoLayout,
|
|
79
|
+
applyAutoColSpan,
|
|
80
|
+
inferColumns,
|
|
81
|
+
inferModalSize,
|
|
82
|
+
isWideFieldType,
|
|
83
|
+
isAutoGeneratedFieldType,
|
|
84
|
+
containerGridColsFor,
|
|
85
|
+
filterCreateModeFields,
|
|
86
|
+
filterSystemFields,
|
|
87
|
+
filterAutoGeneratedFields,
|
|
88
|
+
deriveDetail,
|
|
89
|
+
deriveColumns,
|
|
90
|
+
deriveFormFields,
|
|
91
|
+
findRelationshipField,
|
|
92
|
+
resolveInlineMode,
|
|
93
|
+
} from '@object-ui/plugin-form';
|
|
94
|
+
|
|
95
|
+
import type {
|
|
96
|
+
ObjectFormComponentProps,
|
|
97
|
+
ObjectFormProps, // deprecated alias of ObjectFormComponentProps
|
|
98
|
+
FormSectionContainerProps,
|
|
99
|
+
TabbedFormProps,
|
|
100
|
+
TabbedFormSchema,
|
|
101
|
+
FormSectionConfig,
|
|
102
|
+
WizardFormProps,
|
|
103
|
+
WizardFormSchema,
|
|
104
|
+
SplitFormProps,
|
|
105
|
+
SplitFormSchema,
|
|
106
|
+
DrawerFormProps,
|
|
107
|
+
DrawerFormSchema,
|
|
108
|
+
ModalFormProps,
|
|
109
|
+
ModalFormSchema,
|
|
110
|
+
EmbeddableFormProps,
|
|
111
|
+
EmbeddableFormConfig,
|
|
112
|
+
EmbeddableFormTexts,
|
|
113
|
+
FormAnalyticsProps,
|
|
114
|
+
FormSubmissionMetric,
|
|
115
|
+
MasterDetailFormProps,
|
|
116
|
+
MasterDetailFormSchema,
|
|
117
|
+
MasterDetailDetailConfig,
|
|
118
|
+
LineItemsPanelSchema,
|
|
119
|
+
DerivedDetail,
|
|
120
|
+
InlineMode,
|
|
121
|
+
} from '@object-ui/plugin-form';
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Registering a component under your own key
|
|
125
|
+
|
|
126
|
+
To put one of these components on a schema type of your own, register the
|
|
127
|
+
exported component:
|
|
39
128
|
|
|
40
129
|
```typescript
|
|
41
|
-
import { formComponents } from '@object-ui/plugin-form';
|
|
42
130
|
import { ComponentRegistry } from '@object-ui/core';
|
|
131
|
+
import { ObjectForm } from '@object-ui/plugin-form';
|
|
43
132
|
|
|
44
|
-
|
|
45
|
-
Object.entries(formComponents).forEach(([type, component]) => {
|
|
46
|
-
ComponentRegistry.register(type, component);
|
|
47
|
-
});
|
|
133
|
+
ComponentRegistry.register('my-form', ObjectForm, { namespace: 'my-app' });
|
|
48
134
|
```
|
|
49
135
|
|
|
136
|
+
The renderers this package registers for itself are internal wrappers rather
|
|
137
|
+
than these exported components. `SchemaRenderer` hands a registered component its
|
|
138
|
+
`schema` (plus the schema's own props), but never a `dataSource` — that travels
|
|
139
|
+
on `SchemaRendererContext` — so each wrapper reads it off the context first.
|
|
140
|
+
`ObjectForm` takes `dataSource` as a prop, optional because inline `customFields`
|
|
141
|
+
need no adapter, so a custom-key registration either supplies one or wraps the
|
|
142
|
+
component the same way.
|
|
143
|
+
|
|
50
144
|
## Schema API
|
|
51
145
|
|
|
52
|
-
|
|
146
|
+
Two form schemas reach a renderer, and **both are declared in
|
|
147
|
+
`@object-ui/types`** — this package imports them and declares neither. The
|
|
148
|
+
tables below name the keys and point at the declaration; the declaration is the
|
|
149
|
+
contract. (Restating an interface inside this README is what let this section
|
|
150
|
+
drift away from the code in the first place — objectui#5075.)
|
|
53
151
|
|
|
54
|
-
|
|
152
|
+
| Schema | `type` | Declared in | Rendered by |
|
|
153
|
+
|---|---|---|---|
|
|
154
|
+
| `FormSchema` | `'form'` | `packages/types/src/form.ts` | the basic form in `@object-ui/components` — bare `form` is deliberately **not** claimed by this plugin (`skipFallback: true`, see the table above) |
|
|
155
|
+
| `ObjectFormSchema` | `'object-form'` | `packages/types/src/objectql.ts` | `ObjectForm` here, through `plugin-form:object-form` / `object-form` |
|
|
55
156
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
157
|
+
Both `type` slots are string **literals**. A schema whose `type` names something
|
|
158
|
+
no registration claims does not fall back to a form — it renders the
|
|
159
|
+
unknown-component placeholder.
|
|
160
|
+
|
|
161
|
+
### Form (`type: 'form'`)
|
|
162
|
+
|
|
163
|
+
| Key | Type | Notes |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| `type` | `'form'` | literal, not a free string |
|
|
166
|
+
| `fields` | `FormField[]` | **optional** — a form may render `children` instead |
|
|
167
|
+
| `defaultValues` | `Record<string, any>` | form-level initial values. There is no field-level `defaultValue` |
|
|
168
|
+
| `submitLabel` / `cancelLabel` | `string` | button text |
|
|
169
|
+
| `showCancel` / `showActions` | `boolean` | action-row composition |
|
|
170
|
+
| `mobileStickyActions` | `boolean` | pin the action row on small viewports |
|
|
171
|
+
| `layout` | `'vertical' \| 'horizontal'` | label placement |
|
|
172
|
+
| `columns` | `number` | grid width (1–4) |
|
|
173
|
+
| `validationMode` | `'onSubmit' \| 'onBlur' \| 'onChange' \| 'onTouched' \| 'all'` | when the rules run |
|
|
174
|
+
| `resetOnSubmit` / `disabled` | `boolean` | |
|
|
175
|
+
| `mode` | `'edit' \| 'read' \| 'disabled'` | whole-form mode |
|
|
176
|
+
| `objectName` | `string` | enables metadata field locators `data-testid="field:{objectName}.{field}"` (ADR-0054 C4) |
|
|
177
|
+
| `previousValues` | `Record<string, any>` | edit-mode hosts only — the persisted record, as evaluation context for `previous` / `readonlyWhen`. Never sent anywhere |
|
|
178
|
+
| `fieldContainerClass` | `string` | class for the field grid inside the `<form>` |
|
|
179
|
+
| `fieldTabs` / `defaultFieldTab` / `fieldTabsPosition` | see [Tabbed field layout](#tabbed-field-layout-fieldtabs) | |
|
|
180
|
+
| `fieldPanes` / `fieldPanesOrientation` / `fieldPanesResizable` | see [Split field layout](#split-field-layout-fieldpanes) | |
|
|
181
|
+
| `actions` | `SchemaNode[]` | extra nodes in the action row |
|
|
182
|
+
| `children` | `SchemaNode \| SchemaNode[]` | custom body instead of `fields` |
|
|
183
|
+
| `onSubmit` / `onChange` / `onDirtyChange` / `onCancel` | callbacks | **TypeScript-authored schemas only** — a JSON metadata document cannot carry a function. Metadata pages go through the object-form route instead |
|
|
184
|
+
| `className`, `id`, `hidden`, … | — | inherited from `BaseSchema` |
|
|
185
|
+
|
|
186
|
+
⚠️ `FormSchema` extends `BaseSchema`, which declares `[key: string]: any`
|
|
187
|
+
(`packages/types/src/base.ts`), so an invented or misspelled key on a form schema
|
|
188
|
+
is **not** a compile error — it is simply never read. That is why every example
|
|
189
|
+
below is annotated with its real type *and* checked against these key tables:
|
|
190
|
+
an un-annotated `const schema = { … }` type-checks whatever is written in it.
|
|
67
191
|
|
|
68
192
|
### Form Field
|
|
69
193
|
|
|
70
|
-
|
|
194
|
+
`FormField` (`packages/types/src/form.ts`) declares 23 keys, and `name` is the
|
|
195
|
+
only **required** one:
|
|
71
196
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
197
|
+
| Key | Type | What it does |
|
|
198
|
+
|---|---|---|
|
|
199
|
+
| `name` | `string` | **required** — the submit key |
|
|
200
|
+
| `id` | `string` | stable render key; falls back to `name` |
|
|
201
|
+
| `label` | `string` | optional — with none, no label element is rendered at all (validation messages fall back to `name`). The object-bound paths always fill it from the object field |
|
|
202
|
+
| `description` | `string` | help text under the control |
|
|
203
|
+
| `type` | `string` | optional, defaults to `'input'`. Built-ins: `input`, `textarea`, `checkbox`, `switch`, `select`; any other value resolves through the registry (`field:<type>` first, then the bare name) |
|
|
204
|
+
| `inputType` | `string` | HTML input type for `type: 'input'` — `'email'`, `'password'`, `'tel'`, … |
|
|
205
|
+
| `widget` | `string` | widget override; wins over `type` (spec `FormField.widget`) |
|
|
206
|
+
| `placeholder` | `string` | |
|
|
207
|
+
| `required` | `boolean` | the presence rule. `validation.required` does **not** make a field required — see below |
|
|
208
|
+
| `disabled` | `boolean` | not interactive, muted |
|
|
209
|
+
| `readonly` | `boolean` | shown plainly, not editable — deliberately distinct from `disabled` |
|
|
210
|
+
| `hidden` | `boolean` | field is not rendered at all |
|
|
211
|
+
| `options` | `SelectOption[] \| RadioOption[]` | for `select` / radio fields |
|
|
212
|
+
| `validation` | `FieldValidationRules` | **an object keyed by rule name** — see below |
|
|
213
|
+
| `condition` | `FieldCondition` | legacy `{ field, equals, notEquals, in, custom }` matcher |
|
|
214
|
+
| `visibleWhen` / `readonlyWhen` / `requiredWhen` | `string \| { dialect?, source }` | CEL predicates over the live record, evaluated by `@objectstack/formula` — the same engine and dialect the server uses. Fail open |
|
|
215
|
+
| `visibleOn` | `string \| { dialect?, source }` | view-level visibility predicate (spec `FormField.visibleOn`) |
|
|
216
|
+
| `dependsOn` | `DependsOnInput` | cascading parent(s): a bare name, a list of names, or `{ field, param }` entries |
|
|
217
|
+
| `span` | `'auto' \| 'full'` | relative width, independent of the column count (preferred) |
|
|
218
|
+
| `colSpan` | `number` | legacy column span (1–4), clamped to the current column count |
|
|
219
|
+
| `field` | `Record<string, any>` | the resolved object-field **metadata object**, stashed by the object-bound paths so widgets can read `precision`, `currency`, `reference_to`, … In the *spec* form-view vocabulary `field` is a string (the referenced field name); that shape ends at `normalizeSectionField` and never reaches a runtime `FormField` |
|
|
220
|
+
|
|
221
|
+
`FormField` also declares `[key: string]: any`, so an invented key type-checks
|
|
222
|
+
here too. Two that a reader might expect, and that are **not** declared:
|
|
223
|
+
|
|
224
|
+
| Not a `FormField` key | Write this instead |
|
|
225
|
+
|---|---|
|
|
226
|
+
| `defaultValue` | `FormSchema.defaultValues` at form level. An object-bound form seeds from the object field's own declared `defaultValue` — see [What a create form opens with](#what-a-create-form-opens-with) |
|
|
227
|
+
| `className` | `span` / `colSpan` for width, `FormSchema.fieldContainerClass` for the grid. (An undeclared key still rides the props spread down to whichever component the field resolves to, so a field-level `className` can visibly land on a built-in control — but nothing in the contract promises that, and a registered widget honours it only if it happens to spread its leftover props. The renderer reads it *explicitly* on exactly one pseudo-field, `type: 'section-divider'`, where it styles the inline section header.) |
|
|
228
|
+
|
|
229
|
+
There is no `ValidationRule` type in this repo, under any spelling.
|
|
230
|
+
|
|
231
|
+
#### `validation` is an object keyed by rule name
|
|
232
|
+
|
|
233
|
+
`FieldValidationRules` (`packages/types/src/form.ts`) is **not** an array of
|
|
234
|
+
`{ type, value, message }` entries:
|
|
235
|
+
|
|
236
|
+
| Rule | Type | Notes |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| `required` | `string \| boolean` | supplies the required **message** only. Whether the field is required is decided by `required` / `requiredWhen` **on the field** |
|
|
239
|
+
| `minLength` / `maxLength` | `{ value: number; message: string }` | `message` is not optional when you author the rule by hand |
|
|
240
|
+
| `min` / `max` | `{ value: number; message: string }` | numeric range |
|
|
241
|
+
| `pattern` | `{ value: string \| RegExp; message: string }` | pass a **RegExp** in a hand-authored schema: react-hook-form only applies a pattern whose value `instanceof RegExp`, and it is the object-metadata path (`buildValidationRules` in `@object-ui/fields`) that compiles a declared string into one |
|
|
242
|
+
| `validate` | `(value) => boolean \| string \| Promise<boolean \| string>` | custom check; TypeScript-authored schemas only |
|
|
243
|
+
|
|
244
|
+
There is no `email` rule name — an email check is a `pattern`, which is exactly
|
|
245
|
+
what `buildValidationRules` emits for an object field of type `email`.
|
|
246
|
+
|
|
247
|
+
**Why the array spelling fails silently.** The only reader of this key is the
|
|
248
|
+
basic form renderer, which spreads it into the rule object handed to
|
|
249
|
+
react-hook-form — `const rules: any = { ...validation }`
|
|
250
|
+
(`packages/components/src/renderers/form/form.tsx:1652`). Spreading an **array**
|
|
251
|
+
into an object literal produces numeric keys (`{ '0': …, '1': … }`), which
|
|
252
|
+
react-hook-form does not recognise: every rule is dropped, nothing throws, and
|
|
253
|
+
the form looks validated while validating nothing.
|
|
85
254
|
|
|
86
255
|
### What a create form opens with
|
|
87
256
|
|
|
@@ -115,7 +284,7 @@ it; folding a default in over a column the record leaves unset would arm a
|
|
|
115
284
|
silent write of a value the user never chose, on the next save of any other
|
|
116
285
|
field.
|
|
117
286
|
|
|
118
|
-
#### `required` + a runtime default
|
|
287
|
+
#### `required` (or `requiredWhen`) + a runtime default
|
|
119
288
|
|
|
120
289
|
A field may declare both, and it is coherent authoring — storage-level required,
|
|
121
290
|
with the value guaranteed by the producer:
|
|
@@ -131,22 +300,37 @@ rule, and the field is **omitted from the payload** — omitted, not sent empty,
|
|
|
131
300
|
because `applyFieldDefaults` resolves the declaration only for a field that
|
|
132
301
|
arrives absent or null, and a blank string is neither.
|
|
133
302
|
|
|
303
|
+
The **conditional** spelling reaches the same verdict. A `requiredWhen`
|
|
304
|
+
predicate says "required in this state", but `NOW()` / `current_user` resolve
|
|
305
|
+
at insert regardless of state, so the producer's guarantee covers the
|
|
306
|
+
conditional claim exactly as it covers the unconditional one:
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
remind_at: Field.datetime({ requiredWhen: 'record.status == "scheduled"', defaultValue: 'NOW()' }),
|
|
310
|
+
```
|
|
311
|
+
|
|
134
312
|
| Mode | Declared | Left empty | Effect |
|
|
135
313
|
|---|---|---|---|
|
|
136
|
-
| create | `required` + a runtime default | yes | submits; the key is absent, and the server resolves it |
|
|
137
|
-
| create | `required` + a runtime default | no (user typed) | submits the typed value — it outranks the default |
|
|
138
|
-
| create | `required` + a static literal | user cleared the seeded control | refused: they removed a value that was really there |
|
|
139
|
-
|
|
|
314
|
+
| create | `required` / `requiredWhen` TRUE + a runtime default | yes | submits; the key is absent, and the server resolves it |
|
|
315
|
+
| create | `required` / `requiredWhen` TRUE + a runtime default | no (user typed) | submits the typed value — it outranks the default |
|
|
316
|
+
| create | `required` / `requiredWhen` TRUE + a static literal | user cleared the seeded control | refused: they removed a value that was really there |
|
|
317
|
+
| create | `requiredWhen` TRUE, no default | yes | refused: nobody else supplies this value |
|
|
318
|
+
| edit | `required` / `requiredWhen` TRUE, anything | user blanked it | refused: the token was resolved at insert, so this is a real removal |
|
|
140
319
|
|
|
141
320
|
The required marker and `aria-required` go with the rule in the create case,
|
|
142
|
-
since one
|
|
321
|
+
since one verdict drives all three — in that mode the user genuinely is not
|
|
143
322
|
required to provide the value. Showing what the server *will* supply, as a
|
|
144
323
|
non-authoritative preview, is a separate follow-up.
|
|
145
324
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
325
|
+
Every consumer reads one predicate, `isRuntimeDefault` in `@object-ui/core`
|
|
326
|
+
(re-exported for this package's own use by `src/schemaDefaults.ts`, not from the
|
|
327
|
+
package entry listed above) — which is what keeps a form from seeding a field it
|
|
328
|
+
also refuses to submit. The static half is decided at the producer, in
|
|
329
|
+
`isRequiredInForm`; the conditional half cannot be, because `requiredWhen` is
|
|
330
|
+
resolved downstream against the live record, so it is suppressed inside the one
|
|
331
|
+
evaluator that resolves it — `resolveFieldRuleState`, reading
|
|
332
|
+
`isServerOwnedValue`. Display and validation share that single verdict, so a
|
|
333
|
+
field can never lose its asterisk while still refusing the submit.
|
|
150
334
|
|
|
151
335
|
### Column width of a sectioned form
|
|
152
336
|
|
|
@@ -259,7 +443,9 @@ primary pane, the rest stack in the secondary one behind inline section headers.
|
|
|
259
443
|
### Basic Form
|
|
260
444
|
|
|
261
445
|
```typescript
|
|
262
|
-
|
|
446
|
+
import type { FormSchema } from '@object-ui/types';
|
|
447
|
+
|
|
448
|
+
const schema: FormSchema = {
|
|
263
449
|
type: 'form',
|
|
264
450
|
fields: [
|
|
265
451
|
{
|
|
@@ -275,9 +461,15 @@ const schema = {
|
|
|
275
461
|
inputType: 'email',
|
|
276
462
|
label: 'Email Address',
|
|
277
463
|
required: true,
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
464
|
+
// Rule name → rule. Not an array (see Schema API above), and there is no
|
|
465
|
+
// 'email' rule: the email check is the pattern the metadata path builds
|
|
466
|
+
// for a field of type `email`.
|
|
467
|
+
validation: {
|
|
468
|
+
pattern: {
|
|
469
|
+
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
470
|
+
message: 'Invalid email format'
|
|
471
|
+
}
|
|
472
|
+
}
|
|
281
473
|
},
|
|
282
474
|
{
|
|
283
475
|
name: 'country',
|
|
@@ -304,51 +496,111 @@ const schema = {
|
|
|
304
496
|
|
|
305
497
|
### Multi-Step Form
|
|
306
498
|
|
|
499
|
+
A multi-step form is an **`object-form` with `formType: 'wizard'`**, and its
|
|
500
|
+
steps are its `sections` — one step per section. There is no
|
|
501
|
+
`multi-step-form` schema type (no registration anywhere claims that name) and no
|
|
502
|
+
`steps` key on any form schema, so a schema written that way renders the
|
|
503
|
+
unknown-component placeholder and the fields inside `steps` are never read.
|
|
504
|
+
|
|
307
505
|
```typescript
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
506
|
+
import type { ObjectFormSchema } from '@object-ui/types';
|
|
507
|
+
|
|
508
|
+
const schema: ObjectFormSchema = {
|
|
509
|
+
type: 'object-form',
|
|
510
|
+
objectName: 'contacts', // required
|
|
511
|
+
mode: 'create', // required
|
|
512
|
+
formType: 'wizard', // routes to WizardForm — needs at least one section
|
|
513
|
+
sections: [
|
|
514
|
+
{
|
|
515
|
+
name: 'personal',
|
|
516
|
+
label: 'Personal Info',
|
|
517
|
+
fields: ['first_name', 'last_name'] // field NAMES, resolved from the object schema
|
|
518
|
+
},
|
|
311
519
|
{
|
|
312
|
-
|
|
520
|
+
name: 'contact',
|
|
521
|
+
label: 'Contact Info',
|
|
522
|
+
fields: ['email', 'phone']
|
|
523
|
+
}
|
|
524
|
+
],
|
|
525
|
+
allowSkip: false, // see "Wizard steps and allowSkip" above
|
|
526
|
+
showStepIndicator: true
|
|
527
|
+
};
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
A section's `fields` accepts three shapes — a field **name**, a spec
|
|
531
|
+
`FormFieldSchema` object (whose identity key is `field`), or an inline runtime
|
|
532
|
+
`FormField` object. The inline shape is what lets a wizard run with no data
|
|
533
|
+
source at all, which is the closest equivalent of the old snippet; note that
|
|
534
|
+
`WizardForm` reports a data-source-less submit through `onSuccess` (there is no
|
|
535
|
+
`onSubmit` on this schema):
|
|
536
|
+
|
|
537
|
+
```tsx
|
|
538
|
+
import { WizardForm } from '@object-ui/plugin-form';
|
|
539
|
+
import type { WizardFormSchema } from '@object-ui/plugin-form';
|
|
540
|
+
|
|
541
|
+
const wizard: WizardFormSchema = {
|
|
542
|
+
type: 'object-form',
|
|
543
|
+
formType: 'wizard',
|
|
544
|
+
objectName: 'contacts',
|
|
545
|
+
mode: 'create',
|
|
546
|
+
sections: [
|
|
547
|
+
{
|
|
548
|
+
name: 'personal',
|
|
549
|
+
label: 'Personal Info',
|
|
313
550
|
fields: [
|
|
314
551
|
{ name: 'firstName', type: 'input', label: 'First Name', required: true },
|
|
315
552
|
{ name: 'lastName', type: 'input', label: 'Last Name', required: true }
|
|
316
553
|
]
|
|
317
554
|
},
|
|
318
555
|
{
|
|
319
|
-
|
|
556
|
+
name: 'contact',
|
|
557
|
+
label: 'Contact Info',
|
|
320
558
|
fields: [
|
|
321
559
|
{ name: 'email', type: 'input', inputType: 'email', label: 'Email', required: true },
|
|
322
560
|
{ name: 'phone', type: 'input', inputType: 'tel', label: 'Phone' }
|
|
323
561
|
]
|
|
324
|
-
},
|
|
325
|
-
{
|
|
326
|
-
title: 'Review',
|
|
327
|
-
fields: []
|
|
328
562
|
}
|
|
329
563
|
],
|
|
330
|
-
|
|
564
|
+
onSuccess: (data) => {
|
|
331
565
|
console.log('Multi-step form completed:', data);
|
|
332
566
|
}
|
|
333
567
|
};
|
|
568
|
+
|
|
569
|
+
<WizardForm schema={wizard} /> // dataSource omitted: every step lists inline fields
|
|
334
570
|
```
|
|
335
571
|
|
|
572
|
+
`WizardFormSchema` declares no index signature, so an invented key on *this*
|
|
573
|
+
type is a real compile error — unlike `ObjectFormSchema`, which inherits
|
|
574
|
+
`BaseSchema`'s `[key: string]: any`.
|
|
575
|
+
|
|
576
|
+
One more route exists and is worth knowing about rather than reinventing: a flat
|
|
577
|
+
`object-form` can be turned into a stepper on small viewports with
|
|
578
|
+
`mobile: { stepper: true | 'auto', stepperFieldsPerStep, stepperMinFields }`,
|
|
579
|
+
which feeds the same `WizardForm`.
|
|
580
|
+
|
|
336
581
|
### Form with Validation
|
|
337
582
|
|
|
338
583
|
```typescript
|
|
339
|
-
|
|
584
|
+
import type { FormSchema } from '@object-ui/types';
|
|
585
|
+
|
|
586
|
+
const schema: FormSchema = {
|
|
340
587
|
type: 'form',
|
|
588
|
+
validationMode: 'onBlur',
|
|
341
589
|
fields: [
|
|
342
590
|
{
|
|
343
591
|
name: 'username',
|
|
344
592
|
type: 'input',
|
|
345
593
|
label: 'Username',
|
|
346
|
-
required: true,
|
|
347
|
-
validation:
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
594
|
+
required: true, // presence: this is the key that decides it
|
|
595
|
+
validation: {
|
|
596
|
+
required: 'Pick a username', // the MESSAGE for the rule above, nothing more
|
|
597
|
+
minLength: { value: 3, message: 'Username must be at least 3 characters' },
|
|
598
|
+
maxLength: { value: 20, message: 'Username must be less than 20 characters' },
|
|
599
|
+
pattern: {
|
|
600
|
+
value: /^[a-zA-Z0-9_]+$/, // a RegExp, not a string
|
|
601
|
+
message: 'Only letters, numbers, and underscores'
|
|
602
|
+
}
|
|
603
|
+
}
|
|
352
604
|
},
|
|
353
605
|
{
|
|
354
606
|
name: 'password',
|
|
@@ -356,42 +608,153 @@ const schema = {
|
|
|
356
608
|
inputType: 'password',
|
|
357
609
|
label: 'Password',
|
|
358
610
|
required: true,
|
|
359
|
-
validation:
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
611
|
+
validation: {
|
|
612
|
+
minLength: { value: 8, message: 'Password must be at least 8 characters' },
|
|
613
|
+
pattern: {
|
|
614
|
+
value: /(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])/,
|
|
615
|
+
message: 'Must contain uppercase, lowercase, and number'
|
|
616
|
+
},
|
|
617
|
+
validate: (value) =>
|
|
618
|
+
String(value).toLowerCase() !== 'password' || 'Pick something less guessable'
|
|
619
|
+
}
|
|
363
620
|
}
|
|
364
621
|
]
|
|
365
622
|
};
|
|
366
623
|
```
|
|
367
624
|
|
|
625
|
+
Each rule appears **once**, under its own name — an object, not a list. A second
|
|
626
|
+
`minLength` cannot exist, which is the point: the shape the renderer hands
|
|
627
|
+
react-hook-form is one rule per kind.
|
|
628
|
+
|
|
368
629
|
## Integration with Data Sources
|
|
369
630
|
|
|
370
|
-
|
|
631
|
+
**The adapter is not a schema key.** A schema is a serialisable document; a live
|
|
632
|
+
adapter is an object with methods, so it cannot travel in one. Both form routes
|
|
633
|
+
read the adapter from React context, which the host installs once above the whole
|
|
634
|
+
tree — the same rule [Registering a component under your own
|
|
635
|
+
key](#registering-a-component-under-your-own-key) states for custom
|
|
636
|
+
registrations.
|
|
371
637
|
|
|
372
|
-
|
|
638
|
+
### The metadata route — `object-form`
|
|
639
|
+
|
|
640
|
+
This is the route that actually reads and writes a record. `ObjectFormSchema`
|
|
641
|
+
names its object with **`objectName`** and its intent with **`mode`**, and both
|
|
642
|
+
are **required** (`packages/types/src/objectql.ts`); the adapter arrives on the
|
|
643
|
+
context, which `ObjectFormRenderer` reads at `src/index.tsx` before handing
|
|
644
|
+
`ObjectForm` its `dataSource` prop.
|
|
645
|
+
|
|
646
|
+
```tsx
|
|
647
|
+
import { SchemaRendererProvider, SchemaRenderer } from '@object-ui/react';
|
|
373
648
|
import { createObjectStackAdapter } from '@object-ui/data-objectstack';
|
|
649
|
+
import '@object-ui/plugin-form';
|
|
650
|
+
import type { ObjectFormSchema } from '@object-ui/types';
|
|
374
651
|
|
|
375
652
|
const dataSource = createObjectStackAdapter({
|
|
376
653
|
baseUrl: 'https://api.example.com',
|
|
377
|
-
token: 'your-auth-token'
|
|
654
|
+
token: 'your-auth-token',
|
|
378
655
|
});
|
|
379
656
|
|
|
380
|
-
const schema = {
|
|
657
|
+
const schema: ObjectFormSchema = {
|
|
658
|
+
type: 'object-form',
|
|
659
|
+
objectName: 'users',
|
|
660
|
+
mode: 'create',
|
|
661
|
+
fields: ['name', 'email'],
|
|
662
|
+
submitText: 'Create user',
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
export const App = () => (
|
|
666
|
+
<SchemaRendererProvider dataSource={dataSource}>
|
|
667
|
+
<SchemaRenderer schema={schema} />
|
|
668
|
+
</SchemaRendererProvider>
|
|
669
|
+
);
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
The object comes from `objectName`; there is no `resource` key. For `mode: 'edit'`
|
|
673
|
+
or `'view'`, add the `recordId` of the record being opened. Note that this
|
|
674
|
+
`mode` vocabulary is `'create' | 'edit' | 'view'` — the basic form's `mode` is a
|
|
675
|
+
different key with a different vocabulary (`'edit' | 'read' | 'disabled'`, see
|
|
676
|
+
[Schema API](#schema-api)).
|
|
677
|
+
|
|
678
|
+
### The TypeScript route — basic `form`
|
|
679
|
+
|
|
680
|
+
A bare `form` never fetches or saves by itself: it has no object name and no
|
|
681
|
+
query, so there is nothing for it to call an adapter *with*. It collects values
|
|
682
|
+
and hands them to your `onSubmit`, which the renderer awaits
|
|
683
|
+
(`packages/components/src/renderers/form/form.tsx:1428`). Any persistence is
|
|
684
|
+
whatever that function does:
|
|
685
|
+
|
|
686
|
+
```typescript
|
|
687
|
+
import type { FormSchema } from '@object-ui/types';
|
|
688
|
+
|
|
689
|
+
const dataSource = createObjectStackAdapter({
|
|
690
|
+
baseUrl: 'https://api.example.com',
|
|
691
|
+
token: 'your-auth-token',
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
const schema: FormSchema = {
|
|
381
695
|
type: 'form',
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
696
|
+
fields: [
|
|
697
|
+
{ name: 'name', type: 'input', label: 'Full Name', required: true },
|
|
698
|
+
{ name: 'email', type: 'input', inputType: 'email', label: 'Email', required: true },
|
|
699
|
+
],
|
|
700
|
+
submitLabel: 'Create user',
|
|
701
|
+
// The adapter reaches this call through the CLOSURE, not through the schema.
|
|
385
702
|
onSubmit: async (data) => {
|
|
386
703
|
await dataSource.create('users', data);
|
|
387
|
-
}
|
|
704
|
+
},
|
|
388
705
|
};
|
|
389
706
|
```
|
|
390
707
|
|
|
708
|
+
`onSubmit` is a function, so this route is **TypeScript-authored schemas only** —
|
|
709
|
+
a JSON metadata document cannot carry one. Metadata pages take the `object-form`
|
|
710
|
+
route above.
|
|
711
|
+
|
|
712
|
+
What the adapter on the context still does for a bare `form` is supply the
|
|
713
|
+
**field widgets**: the renderer reads it at `form.tsx:1004`
|
|
714
|
+
(`const contextDataSource = schemaCtx?.dataSource ?? null`) and passes it down
|
|
715
|
+
per field at `:2061`, which is how a lookup or cascading select loads its
|
|
716
|
+
options. Nothing else about the form is wired to it.
|
|
717
|
+
|
|
718
|
+
### Keys that look like wiring but are not
|
|
719
|
+
|
|
720
|
+
Neither of these is a key of either form schema, and writing them changes
|
|
721
|
+
nothing:
|
|
722
|
+
|
|
723
|
+
| Written on a form schema | What actually happens |
|
|
724
|
+
|---|---|
|
|
725
|
+
| `dataSource` | **Discarded.** The basic form strips it in both directions — `dataSource: _dataSource` at `form.tsx:304` (`stripRendererOnlyProps`) and `:2168` — so it never reaches a widget and never reaches the DOM. The adapter the fields receive is the context one |
|
|
726
|
+
| `resource` | **Never read.** It is not declared on `FormSchema` or `ObjectFormSchema` at all. The key exists elsewhere in the protocol — on **`CRUDSchema`** (`packages/types/src/crud.ts`, `type: 'crud'`), where `CRUDBuilder` in `@object-ui/core` sets it — but no form renderer reads it under any spelling. On a form it names nothing |
|
|
727
|
+
|
|
728
|
+
Both survive compilation for the reason [Schema API](#schema-api) gives: `FormSchema`
|
|
729
|
+
and `ObjectFormSchema` extend `BaseSchema`, which declares `[key: string]: any`, so an
|
|
730
|
+
invented key is not a type error — it is simply never read. That is also why the
|
|
731
|
+
older version of this section looked like it worked: its `onSubmit` genuinely ran
|
|
732
|
+
and genuinely saved, but through the adapter its closure captured. The `dataSource`
|
|
733
|
+
and `resource` keys sitting beside it in the same object were inert. Delete them and
|
|
734
|
+
that example behaves identically — which is the test for whether a key is doing
|
|
735
|
+
anything.
|
|
736
|
+
|
|
737
|
+
> A top-level `dataSource` **does** mean something on a schema node, but it is not
|
|
738
|
+
> an adapter: it is the spec's element **binding** (`PageComponentSchema.dataSource`,
|
|
739
|
+
> objectstack#6953) — a descriptor such as `{ object: 'users' }` — resolved by
|
|
740
|
+
> `useElementDataSource` (`packages/react/src/hooks/useElementDataSource.ts:139`).
|
|
741
|
+
> `object-form` passes through that gate, and honours the binding's `object` key
|
|
742
|
+
> only. Handing that slot a live adapter is rejected on purpose: the predicate
|
|
743
|
+
> refuses any value carrying a `find` method
|
|
744
|
+
> (`packages/core/src/data-scope/element-data-source.ts:131`), so an adapter written
|
|
745
|
+
> there is ignored rather than mistaken for a binding. Pass adapters through the
|
|
746
|
+
> provider above.
|
|
747
|
+
|
|
391
748
|
## TypeScript Support
|
|
392
749
|
|
|
750
|
+
`FormSchema` and `FormField` are protocol types, so they live in
|
|
751
|
+
`@object-ui/types` alongside the rest of the JSON contract. This package imports
|
|
752
|
+
them and does not re-export them — the form types on its own entry are the
|
|
753
|
+
per-container ones (`TabbedFormSchema`, `WizardFormSchema`, `ModalFormSchema`, …)
|
|
754
|
+
listed under [Public exports](#public-exports).
|
|
755
|
+
|
|
393
756
|
```typescript
|
|
394
|
-
import type { FormSchema, FormField } from '@object-ui/
|
|
757
|
+
import type { FormSchema, FormField } from '@object-ui/types';
|
|
395
758
|
|
|
396
759
|
const emailField: FormField = {
|
|
397
760
|
name: 'email',
|
package/dist/DrawerForm.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DrawerForm.d.ts","sourceRoot":"","sources":["../src/DrawerForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AAEH,OAAO,KAAmE,MAAM,OAAO,CAAC;AACxF,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"DrawerForm.d.ts","sourceRoot":"","sources":["../src/DrawerForm.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddableForm.d.ts","sourceRoot":"","sources":["../src/EmbeddableForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;GAYG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"EmbeddableForm.d.ts","sourceRoot":"","sources":["../src/EmbeddableForm.tsx"],"names":[],"mappings":"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"}
|