@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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,659 @@
|
|
|
1
1
|
# @object-ui/plugin-form
|
|
2
2
|
|
|
3
|
+
## 17.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8c0d52e: A form's ruled `submitBehavior.url` redirect can now be performed by the HOST, so a destination stays inside a console mounted at a sub-path (objectui#4989 defect 4).
|
|
8
|
+
|
|
9
|
+
`ObjectForm` and `WizardForm` accept a relative in-app path and used to travel to it with `window.location.assign`. A rooted path resolves against the ORIGIN there, so under a mounted host — `<BrowserRouter basename="/_console">`, which the framework CLI configures for every embedded deployment — an authored `/thanks` left the application. The destination was correct and the navigation was wrong, and a published renderer cannot fix that alone: only the host knows its mount.
|
|
10
|
+
|
|
11
|
+
**New: `HostNavigationContext` (`@object-ui/react`).** A host offers its own navigate; a renderer uses it when it is there:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { HostNavigationProvider } from '@object-ui/react';
|
|
15
|
+
import { useNavigate } from 'react-router-dom';
|
|
16
|
+
|
|
17
|
+
function Bridge({ children }) {
|
|
18
|
+
const navigate = useNavigate();
|
|
19
|
+
return (
|
|
20
|
+
<HostNavigationProvider value={{ navigate: (to, o) => navigate(to, { replace: o?.replace ?? false }) }}>
|
|
21
|
+
{children}
|
|
22
|
+
</HostNavigationProvider>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`@object-ui/app-shell`'s `ConsoleShell` now mounts that bridge above every console route, so the console's own routes, and its basename, are what a post-submit redirect resolves against — and the redirect becomes an SPA transition instead of a full page load.
|
|
28
|
+
|
|
29
|
+
**Nothing changes for a host that wires nothing.** With no provider the behaviour is byte-for-byte what it was: one `window.location.assign` of the resolved path after the declared `delayMs`. A host with no router has no basename, so origin-rooted resolution is already right there — the seam changes what a MOUNTED host gets and nothing else. `useHostNavigation()` outside a provider answers `{ navigate: undefined }` and never throws.
|
|
30
|
+
|
|
31
|
+
Two mechanisms were weighed and rejected by the ruling, recorded so they are not re-proposed. **Reading React Router's context when a router happens to be present** is implicit, and unavailable anyway: a React context is a module-instance object, so reading the host's means importing `react-router` into the renderer — which `@object-ui/plugin-form` declares in none of its dependency fields, whose published build externalises every bare specifier, and which two real consumers (`apps/site`, `packages/plugin-view`) do not install. **Requiring `react-router` as a peer** is the honest version of the same thing and costs the package its property of dropping into any React application.
|
|
32
|
+
|
|
33
|
+
What the host takes on by supplying a navigate: the destination becomes a client-side transition, so an in-app path with no matching route renders the host's not-found instead of a full page load. That is the host's routing table to answer for, which is why the choice is the host's. The contract verdict is unchanged either way — a destination `@objectstack/spec` refuses is refused identically with or without a seam, so an injected navigate can never launder a value the authoring door rejects.
|
|
34
|
+
|
|
35
|
+
`navigateOnSuccess` is a different declared key with its own open contract question (objectui#5034) and is deliberately untouched here.
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- 9b20dea: Fix: a `drawer` form with no `sections` now renders the object's declared
|
|
40
|
+
`fieldGroups` as sections, matching `ObjectForm` and `ModalForm`.
|
|
41
|
+
|
|
42
|
+
`deriveFieldGroupSections` had exactly two call sites in the repo —
|
|
43
|
+
`ObjectForm` and `ModalForm` — so the same object, with the same metadata,
|
|
44
|
+
rendered one section per declared group in the modal create dialog and one
|
|
45
|
+
ungrouped flat list in the drawer. The author who laid the groups out in the
|
|
46
|
+
object designer saw them honoured on two surfaces out of three.
|
|
47
|
+
|
|
48
|
+
`DrawerForm` now runs the same fallback the modal does: gated on "no explicit
|
|
49
|
+
`sections`, no `customFields`", over the same auto-layout-filtered field list
|
|
50
|
+
(system fields dropped, auto-generated fields dropped in create mode), with the
|
|
51
|
+
flat path's inferred column count carried onto the grouped layout. A curated
|
|
52
|
+
`sections` list from a form view still wins, and an object whose fields join no
|
|
53
|
+
declared group keeps its flat layout untouched. A derived group declaring
|
|
54
|
+
ADR-0085 `collapse` renders as a collapsible header, like an authored one.
|
|
55
|
+
- 469b604: Fix: a `drawer` form with no `sections` now honours the object's field-level
|
|
56
|
+
conditional rules (`visibleWhen` / `readonlyWhen` / `requiredWhen`) and field
|
|
57
|
+
`group`.
|
|
58
|
+
|
|
59
|
+
`ModalForm` and `DrawerForm` each carried their own copy of the "object-schema
|
|
60
|
+
field to runtime FormField" loop for the no-sections case, and the drawer's
|
|
61
|
+
copy had fallen behind: it stopped at `multiple`, so the ADR-0036 predicates
|
|
62
|
+
never reached the runtime field and `resolveFieldRuleState` had nothing to
|
|
63
|
+
resolve. A hidden field rendered anyway, a frozen field stayed editable (with
|
|
64
|
+
the server then dropping the write), and a conditionally-required field never
|
|
65
|
+
blocked the submit.
|
|
66
|
+
|
|
67
|
+
Both containers now build that list through one shared `buildFlatFields`, which
|
|
68
|
+
resolves each field through the same `fromObjectSchema` the sectioned path uses
|
|
69
|
+
— so the next field-mapping fix lands once and reaches every container.
|
|
70
|
+
- d7be3bd: `EmbeddableForm`'s thank-you redirect stops being mount-blind: an in-app destination now goes through the host's injected navigate.
|
|
71
|
+
|
|
72
|
+
The redirect ended in one unconditional `window.location.href = url`. That is
|
|
73
|
+
right for the external destination this key deliberately admits, and wrong for
|
|
74
|
+
the in-app one it equally admits: a rooted path such as `/thanks` assigned to
|
|
75
|
+
`location.href` resolves against the ORIGIN root, so under a host mounted at a
|
|
76
|
+
sub-path — the framework CLI configures one for every embedded deployment, and
|
|
77
|
+
the console runs at basename `/_console` — the submitter landed outside the
|
|
78
|
+
application, usually on the host's own 404. Nothing refused either half of that
|
|
79
|
+
authoring, so the failure was silent. This is objectui#4989 defect 4 on the key
|
|
80
|
+
that card explicitly did not cover, and it is fixed here through the seam
|
|
81
|
+
objectui#5111 landed (`HostNavigationContext`, `@object-ui/react`).
|
|
82
|
+
|
|
83
|
+
The destinations are now split by who can travel to them:
|
|
84
|
+
|
|
85
|
+
- an **app-relative** destination (`/thanks`, `thanks`, `?ok=1`, `#done`) is
|
|
86
|
+
handed to the host's navigate when a host supplied one, so a mounted host
|
|
87
|
+
places it inside its mount; with no provider the behaviour is byte-for-byte
|
|
88
|
+
what it was — a host with no router has no basename, so origin-rooted
|
|
89
|
+
resolution is already correct there;
|
|
90
|
+
- an **external** destination admitted by `allowedRedirectHosts` keeps
|
|
91
|
+
browser-level navigation **unconditionally**. This is the seam's own declared
|
|
92
|
+
input contract, not a conservatism: `HostNavigationValue.navigate` documents
|
|
93
|
+
`to` as an application-relative path, "never an absolute URL", because a host
|
|
94
|
+
navigate is a client-side router transition. Since a relative reference cannot
|
|
95
|
+
carry an authority, the seam is now structurally incapable of being handed a
|
|
96
|
+
cross-origin URL.
|
|
97
|
+
|
|
98
|
+
A same-origin **absolute** URL — the one shape those two arms do not name — also
|
|
99
|
+
keeps browser-level navigation. Routing it through the seam would mean rewriting
|
|
100
|
+
the author's full address into a path a mounted router then places at a
|
|
101
|
+
different address; an author who spelled out the whole address asked for that
|
|
102
|
+
address.
|
|
103
|
+
|
|
104
|
+
Not changed, deliberately: `isRedirectUrlSafe` and `allowedRedirectHosts` —
|
|
105
|
+
WHICH destinations are followed. That acceptance set (same-origin OR the
|
|
106
|
+
author's allowlist) is this key's own contract, a refused destination reaches
|
|
107
|
+
neither the seam nor the browser, and objectstack#7496's relative-only ruling
|
|
108
|
+
belongs to `submitBehavior.url` and is not imported onto this key. The wait's
|
|
109
|
+
ownership (objectui#5049) and the thank-you panel's copy (objectui#5073) are
|
|
110
|
+
carried over unchanged: unmounting or pressing "Submit Another Response" still
|
|
111
|
+
cancels a pending redirect, seam or no seam.
|
|
112
|
+
- a954b48: A public form's thank-you countdown ("Redirecting in {{seconds}} seconds…") now
|
|
113
|
+
actually counts down, instead of rendering a number once and leaving it frozen
|
|
114
|
+
for the whole wait.
|
|
115
|
+
|
|
116
|
+
All ten locale packs document `publicForm.redirecting`'s `{{seconds}}` as "the
|
|
117
|
+
remaining seconds", but `EmbeddableForm` computed it exactly once — at the render
|
|
118
|
+
that first shows the thank-you panel — from `pendingRedirect.delayMs`, and never
|
|
119
|
+
touched it again. On the 3 second default delay, a submitter saw a fully static
|
|
120
|
+
"Redirecting in 3 seconds…" for the entire wait (objectui#5083).
|
|
121
|
+
|
|
122
|
+
The number is now owned by a per-second `setInterval`, on the same ownership
|
|
123
|
+
model PR #5070 established for the redirect wait itself: an effect keyed on the
|
|
124
|
+
accepted destination (`pendingRedirect`), cancelled on unmount and on
|
|
125
|
+
`handleReset`'s `Submit Another Response` — the exact regression surface
|
|
126
|
+
objectui#5049 fixed for the navigation timer, restated here rather than
|
|
127
|
+
reintroduced. The interval also stops itself once it reaches 0, rather than
|
|
128
|
+
ticking indefinitely past a wait that has already ended.
|
|
129
|
+
|
|
130
|
+
Nothing about WHICH destinations are followed or refused changes
|
|
131
|
+
(`isRedirectUrlSafe` / `allowedRedirectHosts`, objectui#4989), and neither does
|
|
132
|
+
the navigation wait's own ownership (objectui#5049 / PR #5070) — this is the
|
|
133
|
+
display only.
|
|
134
|
+
- bda9b12: A public form's thank-you panel no longer promises a redirect its own guard just
|
|
135
|
+
refused, and the `texts.redirectBlocked` string can finally reach a screen.
|
|
136
|
+
|
|
137
|
+
`EmbeddableForm` decided whether to redirect from `isRedirectUrlSafe` /
|
|
138
|
+
`allowedRedirectHosts`, but the panel's copy was keyed on something else: whether
|
|
139
|
+
a `thankYouPage.redirectUrl` had been *authored* (objectui#5073). An author who
|
|
140
|
+
declared a cross-origin destination without allowlisting its host therefore got a
|
|
141
|
+
submitter who was told `Redirecting in 3 seconds…` and was then never redirected.
|
|
142
|
+
The guard did its job; the screen contradicted it. That screen is the terminal
|
|
143
|
+
state of a public form, so nothing came after to correct the impression.
|
|
144
|
+
|
|
145
|
+
On the same path, the `texts.redirectBlocked` string the refusal set was
|
|
146
|
+
unreachable in every locale. It was recorded with `setError(...)`, whose banner
|
|
147
|
+
lives in the form branch — and `setSubmitted(true)` has already run one statement
|
|
148
|
+
earlier, so the component is showing the thank-you branch, which renders no error
|
|
149
|
+
at all. That was the only assignment of the key anywhere; pressing
|
|
150
|
+
`Submit Another Response` cleared it rather than showing it.
|
|
151
|
+
|
|
152
|
+
Both now follow the verdict:
|
|
153
|
+
|
|
154
|
+
- The countdown renders on `pendingRedirect` — the destination that was actually
|
|
155
|
+
accepted — and reads its seconds from the delay captured with it, so the
|
|
156
|
+
displayed wait is the wait being served. A refused destination, and the
|
|
157
|
+
honeypot's silent fake-success (which accepts no destination either), simply
|
|
158
|
+
omit the line.
|
|
159
|
+
- A refused destination renders `texts.redirectBlocked` in the thank-you panel
|
|
160
|
+
when the author declared it — the case the key exists for, in the author's own
|
|
161
|
+
words to the public. Undeclared means silence; the author keeps the existing
|
|
162
|
+
`console.warn`, which is the channel for the person who can fix the
|
|
163
|
+
declaration.
|
|
164
|
+
|
|
165
|
+
Which destinations are refused is unchanged: `isRedirectUrlSafe` and
|
|
166
|
+
`allowedRedirectHosts` are untouched, as is the timer ownership introduced for
|
|
167
|
+
objectui#5049. Nothing was ever at risk in the data — the write succeeds before
|
|
168
|
+
any of this — the harm was a false statement on the confirmation screen and a
|
|
169
|
+
shipped, translated string no user could see.
|
|
170
|
+
- e354dd0: A public form's thank-you redirect no longer outlives the form that armed it, and
|
|
171
|
+
"Submit Another Response" now cancels it.
|
|
172
|
+
|
|
173
|
+
`EmbeddableForm` armed the `thankYouPage.redirectUrl` wait with a bare
|
|
174
|
+
`setTimeout` inside the submit handler: the handle was not stored, nothing cleared
|
|
175
|
+
it, and no part of the component owned it (objectui#5049). Two consequences, and
|
|
176
|
+
the second needs no unmount at all:
|
|
177
|
+
|
|
178
|
+
- For the whole of the delay a full-page navigation was pending that survived the
|
|
179
|
+
form being taken off screen — an embed removed by the host page, a route change,
|
|
180
|
+
a re-keyed subtree. With `redirectDelay` unset that window is the 3000 ms
|
|
181
|
+
default, so this was the normal state of every submit on this surface rather
|
|
182
|
+
than an edge authoring; the thank-you panel says as much out loud with
|
|
183
|
+
`Redirecting in {{seconds}} seconds…`.
|
|
184
|
+
- Under `allowMultiple`, `Submit Another Response` only flipped `submitted` back
|
|
185
|
+
to false while the pending navigation kept ticking. The component invited the
|
|
186
|
+
submitter into a fresh form and then, about three seconds later, threw the whole
|
|
187
|
+
page away while they were typing the next response.
|
|
188
|
+
|
|
189
|
+
The wait now lives in an effect keyed on the accepted destination, with a
|
|
190
|
+
`clearTimeout` cleanup, so unmounting cancels it; and `handleReset` drops the
|
|
191
|
+
destination, so pressing `Submit Another Response` cancels it too. The button
|
|
192
|
+
offers the submitter a fresh form, and that offer cannot be honoured alongside
|
|
193
|
+
discarding the page a moment later. This is the same move `ObjectForm` /
|
|
194
|
+
`WizardForm` (objectui#5033) and `apps/console`'s `FormPage` already made for
|
|
195
|
+
their own copies of this defect.
|
|
196
|
+
|
|
197
|
+
Nothing else changed. Which destinations are followed and which are refused is
|
|
198
|
+
still decided by the same `isRedirectUrlSafe` / `allowedRedirectHosts` guard, on
|
|
199
|
+
the same line as before — only who owns the wait changed. The delay is captured
|
|
200
|
+
together with the destination at the moment the write is accepted, so a host
|
|
201
|
+
re-rendering with a different `redirectDelay` mid-wait cannot restart the pause
|
|
202
|
+
under the submitter. The countdown copy is untouched. No data was ever at risk:
|
|
203
|
+
the write has already succeeded before the wait begins, so the harm was a
|
|
204
|
+
surprising navigation — and, on the `allowMultiple` path, the loss of what the
|
|
205
|
+
submitter had just re-typed.
|
|
206
|
+
- f68018d: A form's declared redirect delay no longer outlives the form that armed it.
|
|
207
|
+
|
|
208
|
+
`ObjectForm` and `WizardForm` consumed `submitBehavior: { kind: 'redirect' }` by
|
|
209
|
+
arming the `delayMs` wait with a bare `setTimeout` inside the submit handler. The
|
|
210
|
+
handle was not stored, nothing cleared it on unmount, and no part of the component
|
|
211
|
+
owned it — so for the whole of the declared delay there was a pending full-page
|
|
212
|
+
navigation that survived the form being taken off screen (objectui#5033). A
|
|
213
|
+
submitter who dismissed the modal or drawer variant after the confirmation, who
|
|
214
|
+
clicked an in-app link, or whose host re-keyed the subtree for its own reasons was
|
|
215
|
+
pulled away from wherever they had gone by a timer belonging to a form that no
|
|
216
|
+
longer existed. The longer the authored delay, the wider that window — and a
|
|
217
|
+
non-trivial delay is the intended authoring, since `delayMs` exists so the
|
|
218
|
+
confirmation is readable before the redirect.
|
|
219
|
+
|
|
220
|
+
The wait now lives in an effect keyed on the accepted destination, with a
|
|
221
|
+
`clearTimeout` cleanup, so unmounting cancels it. This is the same move
|
|
222
|
+
`apps/console`'s `FormPage` already made for its own copy of this defect.
|
|
223
|
+
|
|
224
|
+
`delayMs` semantics are unchanged: the pause is still a pause, an unset value is
|
|
225
|
+
still "go now" (a zero timer, exactly as the in-handler version scheduled it), and
|
|
226
|
+
which destinations are followed or refused is untouched — the contract verdict
|
|
227
|
+
that decides WHETHER to navigate is the same one, only WHEN it happens is now
|
|
228
|
+
owned by the component. The delay is captured together with the destination at the
|
|
229
|
+
moment the write is accepted, so a host re-rendering with a different `delayMs`
|
|
230
|
+
mid-wait cannot restart the pause under the submitter. Nothing was ever at risk of
|
|
231
|
+
being lost: the write has already succeeded before the wait begins, so the harm
|
|
232
|
+
was a surprising navigation, not a corrupted record.
|
|
233
|
+
- 375efb4: Publish the authoring surfaces of the four GA `object-*` blocks
|
|
234
|
+
|
|
235
|
+
`object-form`, `object-grid`, `object-master-detail-form` and `object-metric`
|
|
236
|
+
each honoured far more keys than they declared as registry `inputs`. An author —
|
|
237
|
+
very often an AI author — who wrote one of the undeclared keys got an
|
|
238
|
+
`unknown-prop` report from `sdui-parser` on a key that works, while the designer
|
|
239
|
+
panel and the generated `sdui-intrinsics.d.ts` denied it existed.
|
|
240
|
+
|
|
241
|
+
68 keys are now declared with descriptions written to teach correct authoring:
|
|
242
|
+
`object-form` +20 (record binding, button labels, post-submit behaviour, mobile
|
|
243
|
+
overrides), `object-grid` +21 (sorting, pagination, grouping, selection, row and
|
|
244
|
+
bulk actions, navigation, export), `object-master-detail-form` +10, and
|
|
245
|
+
`object-metric` +14 (formatting, comparison, drill-down). No renderer behaviour
|
|
246
|
+
changes — this documents what already shipped, so the manifest, the generated
|
|
247
|
+
`.d.ts`, the designer panel and the renderers finally agree.
|
|
248
|
+
|
|
249
|
+
Ten of `object-grid`'s spec-declared keys are deliberately NOT published:
|
|
250
|
+
its own `@deprecated` legacy spellings (`fields`, `staticData`, `selectable`,
|
|
251
|
+
`pageSize`, `showSearch`, `showPagination`, `defaultSort`, `defaultFilters`,
|
|
252
|
+
`resizableColumns`, `title`). The renderer keeps reading them so existing
|
|
253
|
+
documents render, but recommending a deprecated alias as new authoring surface
|
|
254
|
+
would harden it into a second dialect. Each canonical replacement — `columns`,
|
|
255
|
+
`data`, `selection`, `pagination`, `searchableFields`, `sort`, `filter`,
|
|
256
|
+
`resizable`, `label` — is declared, and each carries a description naming the
|
|
257
|
+
legacy spelling it supersedes.
|
|
258
|
+
- 800f455: fix(fields): grid columns are keyed by the declared `name`, so spec-compliant grid metadata renders populated cells
|
|
259
|
+
|
|
260
|
+
`GridField` declared its own column interface keyed by `field` and read
|
|
261
|
+
`c.field` at every site (`key=`, `row[…]`, the blank row, cell writes, the
|
|
262
|
+
column chooser, the running-total lookup), while the published
|
|
263
|
+
`GridColumnDefinition` in `@object-ui/types` — and the grid documentation, and
|
|
264
|
+
the `fields-grid` catalog examples — declare the key as `name`. Metadata
|
|
265
|
+
authored against the published type therefore rendered a grid with the correct
|
|
266
|
+
row count and every cell empty, plus a React "unique key" warning per column.
|
|
267
|
+
|
|
268
|
+
The renderer now reads the declared `name`, and the master-detail derivation
|
|
269
|
+
(`deriveColumns` / `hydrateColumns` / `pickAmountField`) produces and consumes
|
|
270
|
+
the same key. There is deliberately **no** `col.field ?? col.name` alias: one
|
|
271
|
+
spelling at the producer (AGENTS.md #0.1).
|
|
272
|
+
|
|
273
|
+
**Breaking for `field`-keyed columns.** Grid / line-item / master-detail
|
|
274
|
+
subform columns spelled `{ field: 'amount' }` must be re-spelled
|
|
275
|
+
`{ name: 'amount' }`. This affects author-supplied `columns` on the `grid`
|
|
276
|
+
field, `record:line_items`, `object-master-detail-form` details and a
|
|
277
|
+
relationship field's `inlineColumns`. Auto-derived columns (no explicit
|
|
278
|
+
`columns` block) need no change. List-view and `object-grid` columns are a
|
|
279
|
+
different contract (`ListColumn`) and keep their own `field` key.
|
|
280
|
+
- 3b03704: `mobile.fullscreenLongText` now reaches fields the spec spells `richtext` (objectui#4831).
|
|
281
|
+
|
|
282
|
+
`ObjectForm` is the one and only producer of the `mobile_fullscreen` flag: when a form
|
|
283
|
+
sets `mobile: { fullscreenLongText: true }` it stamps that flag onto the metadata of
|
|
284
|
+
every long-text field, and the widget renders an expand affordance plus a full-height
|
|
285
|
+
editing dialog from it. The list of types it stamped was four hand-written literals —
|
|
286
|
+
`textarea`, `field:textarea`, `field:markdown`, `field:html` — and `field:richtext` was
|
|
287
|
+
not among them.
|
|
288
|
+
|
|
289
|
+
`richtext` is the name `@objectstack/spec`'s `FieldType` gives this type; `markdown` and
|
|
290
|
+
`html` are the other two, and all three are registry keys on ONE widget, `RichTextField`,
|
|
291
|
+
which has read the flag since objectui#3301. So the consumer side was complete and two of
|
|
292
|
+
the widget's three keys were stamped: a field authored exactly as the spec prescribes
|
|
293
|
+
(`type: richtext`) rendered the rich-text editor with no expand button, on a form whose
|
|
294
|
+
`mobile` documentation promises "textarea/rich-text get an expand button". `markdown` and
|
|
295
|
+
`html` beside it worked. This is the same hole objectui#4250 found in this package's
|
|
296
|
+
`WIDE_FIELD_TYPES`, which is why the twin set already lists `richtext` and this one did
|
|
297
|
+
not.
|
|
298
|
+
|
|
299
|
+
Adding the missing key is the whole change; no other type's behaviour moves, and a form
|
|
300
|
+
that has not opted in still stamps nothing.
|
|
301
|
+
- 958d757: The plugin-form documentation-site page now teaches the `validation` shape the
|
|
302
|
+
form renderer actually reads, so a copied example validates instead of only
|
|
303
|
+
looking as though it does.
|
|
304
|
+
|
|
305
|
+
`content/docs/plugins/plugin-form.mdx` carried the same two defects
|
|
306
|
+
`packages/plugin-form/README.md` did before it was rewritten (objectui#5075 /
|
|
307
|
+
objectui#5118): the README half was fixed and the documentation-site mirror was
|
|
308
|
+
not touched.
|
|
309
|
+
|
|
310
|
+
`### Form Field` redeclared a local `interface FormField` whose `validation` was
|
|
311
|
+
`ValidationRule[]`. No `ValidationRule` type exists in this repository under any
|
|
312
|
+
spelling, and `validation` is not an array — it is `FieldValidationRules`
|
|
313
|
+
(`packages/types/src/form.ts`), an object keyed by rule name. The block also
|
|
314
|
+
listed `defaultValue` and `className`, neither of which is a declared member of
|
|
315
|
+
`FormField`, and marked `type` and `label` required when `name` is the only
|
|
316
|
+
required key of the 23. The section no longer declares a local interface at all
|
|
317
|
+
— a hand-written `interface` in a documentation snippet compiles nowhere, which
|
|
318
|
+
is how it drifted this far — and references the declared keys instead, each one
|
|
319
|
+
measured against the renderer's read points.
|
|
320
|
+
|
|
321
|
+
`### Form with Validation` authored the array to match, and that spelling fails
|
|
322
|
+
silently rather than loudly. The only reader of the key spreads it into the rule
|
|
323
|
+
object handed to react-hook-form (`const rules: any = { ...validation }`,
|
|
324
|
+
`packages/components/src/renderers/form/form.tsx:1652`); spreading an array
|
|
325
|
+
produces numeric keys, react-hook-form recognises none of them, and every rule
|
|
326
|
+
is dropped without an error. Measured against the real renderer: the old snippet
|
|
327
|
+
submits a two-character username under `minLength: 3` with no message shown,
|
|
328
|
+
while the rewritten one blocks it. The example is now annotated `FormSchema`, so
|
|
329
|
+
the array spelling is a compile error (TS2559) rather than a runtime surprise,
|
|
330
|
+
and a JSON variant is given alongside it for metadata authoring.
|
|
331
|
+
|
|
332
|
+
Three facts a reader could previously only discover by experiment are now
|
|
333
|
+
stated: `validation.required` supplies the required *message* while `required` /
|
|
334
|
+
`requiredWhen` on the field decide whether it is required; there is no `email`
|
|
335
|
+
rule name, an email check is a `pattern`; and a hand-authored `pattern` has to
|
|
336
|
+
carry a RegExp, because react-hook-form applies a pattern only when its value is
|
|
337
|
+
`instanceof RegExp` — it is the object-metadata path (`buildValidationRules`)
|
|
338
|
+
that compiles a declared string into one.
|
|
339
|
+
|
|
340
|
+
The two `DOC_TYPE_EXEMPTIONS` entries this page held in
|
|
341
|
+
`scripts/check-doc-component-types.mjs` are deleted with it. They exempted
|
|
342
|
+
`minLength` / `maxLength` as "ValidationRule discriminants under a field's
|
|
343
|
+
`validation[]`" — a reason whose every clause was the fiction being removed —
|
|
344
|
+
and without them the gate now fails if the array spelling returns.
|
|
345
|
+
- bfb64ee: `plugin-form` README: the "Integration with Data Sources" section now teaches the adapter's real path instead of two keys no form renderer reads.
|
|
346
|
+
|
|
347
|
+
The section taught backend wiring as two keys on a form schema — `dataSource`
|
|
348
|
+
(the adapter itself) and `resource: 'users'` — on an un-annotated
|
|
349
|
+
`const schema = { … }`. Neither key is read anywhere on either form route:
|
|
350
|
+
|
|
351
|
+
- **`dataSource`** is *discarded* by the basic form. The renderer reads its
|
|
352
|
+
adapter off `SchemaRendererContext`
|
|
353
|
+
(`packages/components/src/renderers/form/form.tsx:1004`) and passes it down per
|
|
354
|
+
field (`:2061`); a same-named key arriving on the schema or props is dropped by
|
|
355
|
+
the discard destructures at `form.tsx:304` and `:2168`, so it reaches neither a
|
|
356
|
+
widget nor the DOM.
|
|
357
|
+
- **`resource`** is declared on neither `FormSchema` nor `ObjectFormSchema`. The
|
|
358
|
+
key exists in the protocol, but on `CRUDSchema` (`packages/types/src/crud.ts`,
|
|
359
|
+
`type: 'crud'`); no form renderer reads it under any spelling.
|
|
360
|
+
|
|
361
|
+
Both survived compilation because `FormSchema` and `ObjectFormSchema` extend
|
|
362
|
+
`BaseSchema`, which declares `[key: string]: any` — so an invented key is never a
|
|
363
|
+
type error, merely never read. A reader who copied the block got a form that did
|
|
364
|
+
not connect to a backend, with nothing reported: what appeared to work was the
|
|
365
|
+
hand-written `onSubmit` closure, which genuinely runs (the renderer awaits it at
|
|
366
|
+
`form.tsx:1428`) using the adapter its *closure* captured, entirely independently
|
|
367
|
+
of the two keys beside it.
|
|
368
|
+
|
|
369
|
+
The section is rewritten around the real mechanism: the adapter is injected once
|
|
370
|
+
by `SchemaRendererProvider` and travels on context, the metadata route uses
|
|
371
|
+
`object-form` with its required `objectName` + `mode`, and the TypeScript route
|
|
372
|
+
is a bare `form` whose `onSubmit` owns persistence. Both examples now carry real
|
|
373
|
+
type annotations (`ObjectFormSchema` / `FormSchema`) in line with the rest of the
|
|
374
|
+
file — an un-annotated object literal type-checks whatever is written in it. A
|
|
375
|
+
closing note records the one thing a top-level `dataSource` *does* mean on a
|
|
376
|
+
schema node: the spec's element binding (`{ object }`, objectstack#6953), which
|
|
377
|
+
explicitly rejects a live adapter (`element-data-source.ts:131` refuses any value
|
|
378
|
+
carrying a `find` method).
|
|
379
|
+
|
|
380
|
+
Documentation only — no source, type or behavior change. This also removes a
|
|
381
|
+
self-contradiction inside the same README, whose "Registering a component under
|
|
382
|
+
your own key" section already stated the rule correctly ("never a `dataSource` —
|
|
383
|
+
that travels on `SchemaRendererContext`").
|
|
384
|
+
- e09f9e8: Docs only: `packages/plugin-form/README.md`'s Schema API and Examples now spell
|
|
385
|
+
the keys the form renderers actually read (objectui#5075). Three connected
|
|
386
|
+
drifts, judged against the build product's `dist/index.d.ts` under `strict`:
|
|
387
|
+
|
|
388
|
+
- **`validation` was written as an ARRAY** of `{ type, value, message }` entries
|
|
389
|
+
in three places. The real key is `FormField.validation?: FieldValidationRules`
|
|
390
|
+
— an OBJECT keyed by rule name (`required`, `minLength`, `maxLength`, `min`,
|
|
391
|
+
`max`, `pattern`, `validate`). The array form is worse than a type error,
|
|
392
|
+
because its runtime failure is SILENT: the only reader spreads the value into
|
|
393
|
+
the rule object handed to react-hook-form (`const rules: any = { ...validation }`,
|
|
394
|
+
`packages/components/src/renderers/form/form.tsx:1652`), and spreading an array
|
|
395
|
+
into an object literal yields numeric keys (`{ '0': …, '1': … }`).
|
|
396
|
+
react-hook-form's field validator reads exactly `required`, `maxLength`,
|
|
397
|
+
`minLength`, `min`, `max`, `pattern`, `validate`, `valueAsNumber` off its
|
|
398
|
+
descriptor, so every documented rule was dropped with nothing thrown — a form
|
|
399
|
+
copied from this README looked validated while validating nothing. The rewrite
|
|
400
|
+
also records two facts a reader could not have guessed: `validation.required`
|
|
401
|
+
supplies the required MESSAGE only (presence is decided by the field's own
|
|
402
|
+
`required` / `requiredWhen`), and a hand-authored `pattern.value` must be a
|
|
403
|
+
RegExp, since react-hook-form only applies a pattern whose value
|
|
404
|
+
`instanceof RegExp` and it is the object-metadata path (`buildValidationRules`)
|
|
405
|
+
that compiles a declared string into one.
|
|
406
|
+
|
|
407
|
+
- **`type: 'multi-step-form'` is registered nowhere**, and `steps` is not a key
|
|
408
|
+
on any form schema — so the whole "Multi-Step Form" example rendered the
|
|
409
|
+
unknown-component placeholder, with the fields inside `steps` never read. The
|
|
410
|
+
example is replaced by the two real entry points: an `object-form` with
|
|
411
|
+
`formType: 'wizard'`, whose steps are its `sections` (this is what
|
|
412
|
+
`ObjectForm` routes to `WizardForm`), and the exported `WizardForm` itself
|
|
413
|
+
with inline section fields and no data source — the shape closest to what the
|
|
414
|
+
old snippet was reaching for. No new schema type was registered to make the
|
|
415
|
+
old spelling true.
|
|
416
|
+
|
|
417
|
+
- **The `FormField` reference block declared a local `interface FormField`**,
|
|
418
|
+
which type-checks whatever it says because it is unrelated to the real type.
|
|
419
|
+
Five of its rows were wrong (`type` and `label` are OPTIONAL; `validation` is
|
|
420
|
+
the object above; `defaultValue` and `className` are not declared keys — the
|
|
421
|
+
form-level `defaultValues` and `span` / `colSpan` / `fieldContainerClass` are),
|
|
422
|
+
it named a `ValidationRule` type that exists nowhere in the repo, and it listed
|
|
423
|
+
7 of the real 23 keys. The block is now a key table over the real declaration,
|
|
424
|
+
with `FormSchema`'s own keys beside it, and both examples are annotated with
|
|
425
|
+
their real types — the annotation is the point: `FormField` and `BaseSchema`
|
|
426
|
+
both declare `[key: string]: any`, so an un-annotated `const schema = { … }`
|
|
427
|
+
accepts any invented key and a nonexistent key is never a compile error.
|
|
428
|
+
|
|
429
|
+
No renderer behaviour changes, and no capability, export or type was added to
|
|
430
|
+
make an example true.
|
|
431
|
+
- 03e5f97: `packages/plugin-form/README.md`: three assertions about this package's export
|
|
432
|
+
surface were false, and the export names are now taken from the built
|
|
433
|
+
`dist/index.d.ts` (TS compiler API `checker.getExportsOfModule`) with every
|
|
434
|
+
TypeScript block compiled against those same declarations under `strict`.
|
|
435
|
+
|
|
436
|
+
- **`formComponents`** — fiction, and not a name that could be corrected: there
|
|
437
|
+
is no aggregate component map on the surface at all, so the "Manual
|
|
438
|
+
Registration" section described a mechanism that does not exist. Copying it got
|
|
439
|
+
`undefined` and threw on `Object.entries(undefined)`. It is replaced by what
|
|
440
|
+
actually happens: registration is a side effect of importing the entry, whose
|
|
441
|
+
six `ComponentRegistry.register(...)` calls claim
|
|
442
|
+
`plugin-form:object-form`, `view:form`, `plugin-form:embeddable-form`,
|
|
443
|
+
`plugin-form:form-analytics`, `plugin-form:object-master-detail-form` and
|
|
444
|
+
`record:line_items` — the two `skipFallback: true` calls being why bare `form`
|
|
445
|
+
and bare `line_items` are *not* taken over. The section also lists the real
|
|
446
|
+
export surface, and shows the thing the old snippet was reaching for: putting
|
|
447
|
+
an exported component on a schema type of your own, with the caveat that the
|
|
448
|
+
package's own registered renderers are internal wrappers that first resolve
|
|
449
|
+
`dataSource` from `SchemaRendererContext`.
|
|
450
|
+
- **`FormSchema` / `FormField`** — real types imported from the wrong package.
|
|
451
|
+
Both are protocol types declared in `@object-ui/types` (`src/form.ts`); this
|
|
452
|
+
package imports them and does not re-export them, so the documented import was
|
|
453
|
+
a `TS2305` pair. Only the import path changed — no re-export was added to make
|
|
454
|
+
the old path true, since widening a package's public surface is a contract
|
|
455
|
+
change and not a documentation fix. The section now also points at the form
|
|
456
|
+
types that *are* on this entry (`TabbedFormSchema`, `WizardFormSchema`,
|
|
457
|
+
`ModalFormSchema`, …).
|
|
458
|
+
- **`isRuntimeDefault` "(re-exported here)"** — the create-defaults section
|
|
459
|
+
claimed the predicate is re-exported by this package. It is re-exported by
|
|
460
|
+
`src/schemaDefaults.ts` for internal use only, never from the entry, and the
|
|
461
|
+
package publishes just the `"."` export — so `import { isRuntimeDefault } from
|
|
462
|
+
'@object-ui/plugin-form'` is another `TS2305`. The parenthetical now says where
|
|
463
|
+
the re-export actually lives.
|
|
464
|
+
|
|
465
|
+
No code, types or runtime behaviour change — the diff is one README plus this
|
|
466
|
+
changeset. It declares a patch because `README.md` is in the package's published
|
|
467
|
+
`files`, so the correction reaches npm with the next release.
|
|
468
|
+
- ae804ec: `ObjectForm` and `WizardForm` now consume a declared `submitBehavior: { kind: 'redirect' }` the way objectstack#7496 ruled it (objectui#4989): the destination is a **relative** path, `{{record.field_name}}` tokens are substituted from the record the submit just wrote and URL-escaped as the redirect is built, and a destination outside the contract is **refused on screen** instead of being dropped in silence.
|
|
469
|
+
|
|
470
|
+
Both call sites previously read the value through `isSameOriginUrl` — resolve against `window.location.href`, compare origins — and navigated when that answered yes. That is not an open redirect (a cross-origin destination never reached the navigation) but it diverged from the ruled contract three ways, all fixed here:
|
|
471
|
+
|
|
472
|
+
- **An out-of-contract destination was dropped in silence.** When the guard answered no the `if` simply did not fire: no toast, no error, no confirmation. The write had already succeeded, so the submitter was left facing a still-filled form with no feedback about what happened — and the obvious next move, submitting again, wrote a second record. A refusal now shows the spec's own author-facing prescription in an alert beside the confirmation that the record WAS written, toasts it, and replaces the filled form so there is nothing left to resubmit. Silence is the one outcome the ruling's consumer half rules out.
|
|
473
|
+
- **A same-origin ABSOLUTE url was followed**, where the contract is relative-only — so this renderer accepted a spelling the authoring door refuses, which is how a rejected spelling stays alive in a corpus. The verdict is no longer restated here at all: `resolveSubmitRedirect` asks `@objectstack/spec`'s own `FormViewSchema` at the moment of use, so an absolute URL, a protocol-relative `//host`, a backslash, a whitespace or control-character smuggle, a malformed token or a document-relative path is refused with the spec's own wording — and a later widening of the ruling is followed by the version pin rather than by an edit here.
|
|
474
|
+
- **`{{record.field_name}}` tokens were never substituted**, so an authored `/thanks?ref={{record.id}}` navigated with the literal braces in the query. Substitution now happens where the ruling assigns it — when the redirect is built — from the values as submitted with whatever the DataSource answered layered on top, and every interpolated value goes through `encodeURIComponent`, so a token is a value in the path and never a way to add path structure.
|
|
475
|
+
|
|
476
|
+
`delayMs` semantics are unchanged. `navigateOnSuccess` is a different declared key with its own dialect and its own open contract question, and is deliberately untouched; `isSameOriginUrl` survives because that key still needs it.
|
|
477
|
+
|
|
478
|
+
**Escalated rather than guessed at, and since ruled:** this change left a ruled in-app path handed to a browser-level navigation, which resolves it against the origin root, so under a host mounted at a sub-path the destination still left the app (objectui#4989 defect 4). Applying the mount means learning it, and every mechanism available to a published renderer package changes its contract. The maintainer ruled the mechanism on 2026-08-17 — an optional injected navigation seam — and it ships in the same release; see the `plugin-form-injected-navigation-4989` changeset for what a host now supplies and what a host that supplies nothing still gets.
|
|
479
|
+
- d971e51: A create form no longer deadlocks on a `requiredWhen` field that also declares a runtime `defaultValue`.
|
|
480
|
+
|
|
481
|
+
`#4069` ruled that in **create** mode a field whose `defaultValue` is a runtime
|
|
482
|
+
instruction the server resolves per insert (`NOW()` / `current_user`, or a CEL
|
|
483
|
+
Expression envelope) is producer-owned: the control is deliberately left empty
|
|
484
|
+
and the key is omitted from the payload, because `ObjectQL.applyFieldDefaults`
|
|
485
|
+
resolves the declaration only for a field that arrives absent or null. That was
|
|
486
|
+
implemented on the STATIC `required` flag.
|
|
487
|
+
|
|
488
|
+
The conditional spelling was not covered. `requiredWhen` is resolved one layer
|
|
489
|
+
downstream, in the form renderer, against the live record — so a predicate
|
|
490
|
+
resolving TRUE on a create form put the requirement straight back: the control
|
|
491
|
+
was still empty by design, the submit was refused, and the user had nothing
|
|
492
|
+
sensible to type.
|
|
493
|
+
|
|
494
|
+
Both spellings now behave identically on a producer-owned field. A
|
|
495
|
+
`requiredWhen` predicate is a claim about the value at rest in a given state,
|
|
496
|
+
and `NOW()` / `current_user` resolve at insert regardless of state, so the
|
|
497
|
+
producer's guarantee covers the conditional claim by the same argument that
|
|
498
|
+
covers the unconditional one. An author who really means "the user must supply
|
|
499
|
+
this in this state" has a natural spelling for it: do not declare the default.
|
|
500
|
+
|
|
501
|
+
The suppression lands in the single evaluator both layers read,
|
|
502
|
+
`resolveFieldRuleState` — the same verdict that draws the required marker and
|
|
503
|
+
the one the submit-time check consults — so a field can never lose its asterisk
|
|
504
|
+
while still refusing the write. The classifier that answers "is this value the
|
|
505
|
+
producer's to supply" moved down to `@object-ui/core`
|
|
506
|
+
(`isRuntimeDefault` / `isServerOwnedValue`, re-exported from
|
|
507
|
+
`@object-ui/plugin-form`) so the renderer, the wizard's cross-step gate and the
|
|
508
|
+
create-form field builders all read one implementation rather than three.
|
|
509
|
+
|
|
510
|
+
**Edit mode is unchanged.** Defaults do not re-apply to an existing record, so
|
|
511
|
+
on a persisted row the token was already resolved at insert and blanking the
|
|
512
|
+
column is a real removal: `requiredWhen` enforces there exactly as authored.
|
|
513
|
+
Fields with no declared default, and fields whose default is a static literal
|
|
514
|
+
(which IS seeded into the control), are also unaffected in both modes.
|
|
515
|
+
- 2165d88: Rename four component-props types off the names `@objectstack/spec` starts owning in
|
|
516
|
+
17.0.0, keeping the old spellings as deprecated aliases. No behaviour changes and no
|
|
517
|
+
importer breaks.
|
|
518
|
+
|
|
519
|
+
`@objectstack/spec/ui` exports `ObjectCalendarProps`, `ObjectFormProps`, `ObjectGridProps`
|
|
520
|
+
and `ObjectKanbanProps` from 17.0.0, where each is the AUTHORED props document of the
|
|
521
|
+
matching element — a serialisable authoring surface (`z.input< typeof
|
|
522
|
+
ObjectGridPropsSchema >`). The same-named interfaces here are the RENDERERS' props: a live
|
|
523
|
+
`dataSource`, records pre-fetched by a parent, and the host callbacks. Two different things
|
|
524
|
+
under one word, so the local ones are renamed rather than derived, following the split this
|
|
525
|
+
repo already made for `PageHeaderProps` -> `PageHeaderComponentProps` and the
|
|
526
|
+
`Record*ComponentProps` family in `@object-ui/types`:
|
|
527
|
+
|
|
528
|
+
| package | new name | old name |
|
|
529
|
+
|---|---|---|
|
|
530
|
+
| `@object-ui/plugin-calendar` | `ObjectCalendarComponentProps` | `ObjectCalendarProps` |
|
|
531
|
+
| `@object-ui/plugin-form` | `ObjectFormComponentProps` | `ObjectFormProps` |
|
|
532
|
+
| `@object-ui/plugin-grid` | `ObjectGridComponentProps` | `ObjectGridProps` |
|
|
533
|
+
| `@object-ui/plugin-kanban` | `ObjectKanbanComponentProps` | `ObjectKanbanProps` |
|
|
534
|
+
|
|
535
|
+
Every old name is still exported from its package barrel as a `@deprecated` alias denoting
|
|
536
|
+
the SAME type, pinned per package by `spec-symbol-4650.test.ts`, so existing imports keep
|
|
537
|
+
compiling. New code should use the `ComponentProps` spelling.
|
|
538
|
+
|
|
539
|
+
`@object-ui/app-shell` carries no API change: its `SECRET_MASK` — the ADR-0100 credential
|
|
540
|
+
read mask, which 17.0.0 moves into `@objectstack/spec/data` — is renamed to
|
|
541
|
+
`OBJECTUI_SECRET_MASK` at its declaration in `views/metadata-admin/widgets.tsx`. That
|
|
542
|
+
constant is package-internal and is not re-exported from the barrel, so nothing published
|
|
543
|
+
changes; the rename exists so the local copy cannot be read as the spec's own definition
|
|
544
|
+
while this repo is still pinned below the release that exports it.
|
|
545
|
+
- Updated dependencies [88085e3]
|
|
546
|
+
- Updated dependencies [69251bf]
|
|
547
|
+
- Updated dependencies [57e668f]
|
|
548
|
+
- Updated dependencies [516663d]
|
|
549
|
+
- Updated dependencies [41ac1b7]
|
|
550
|
+
- Updated dependencies [1eaf0a1]
|
|
551
|
+
- Updated dependencies [a09bc33]
|
|
552
|
+
- Updated dependencies [460c4d0]
|
|
553
|
+
- Updated dependencies [0ae27f7]
|
|
554
|
+
- Updated dependencies [2533ec5]
|
|
555
|
+
- Updated dependencies [78c0f9a]
|
|
556
|
+
- Updated dependencies [bbe8b86]
|
|
557
|
+
- Updated dependencies [8477be5]
|
|
558
|
+
- Updated dependencies [279fb13]
|
|
559
|
+
- Updated dependencies [2e82ab2]
|
|
560
|
+
- Updated dependencies [ad07b65]
|
|
561
|
+
- Updated dependencies [41f498b]
|
|
562
|
+
- Updated dependencies [ef0d150]
|
|
563
|
+
- Updated dependencies [f34226e]
|
|
564
|
+
- Updated dependencies [564b605]
|
|
565
|
+
- Updated dependencies [e1d4251]
|
|
566
|
+
- Updated dependencies [40d3a33]
|
|
567
|
+
- Updated dependencies [8b9dc62]
|
|
568
|
+
- Updated dependencies [1184192]
|
|
569
|
+
- Updated dependencies [a2a9747]
|
|
570
|
+
- Updated dependencies [65e88e6]
|
|
571
|
+
- Updated dependencies [a1609a6]
|
|
572
|
+
- Updated dependencies [53f23bc]
|
|
573
|
+
- Updated dependencies [c4533dc]
|
|
574
|
+
- Updated dependencies [be60815]
|
|
575
|
+
- Updated dependencies [37f6844]
|
|
576
|
+
- Updated dependencies [93de4f6]
|
|
577
|
+
- Updated dependencies [2b50261]
|
|
578
|
+
- Updated dependencies [384f30d]
|
|
579
|
+
- Updated dependencies [ac600e5]
|
|
580
|
+
- Updated dependencies [97fba31]
|
|
581
|
+
- Updated dependencies [232f61a]
|
|
582
|
+
- Updated dependencies [d374caf]
|
|
583
|
+
- Updated dependencies [5673576]
|
|
584
|
+
- Updated dependencies [c1ef923]
|
|
585
|
+
- Updated dependencies [911ceaa]
|
|
586
|
+
- Updated dependencies [98eab36]
|
|
587
|
+
- Updated dependencies [af5e292]
|
|
588
|
+
- Updated dependencies [3fbbea1]
|
|
589
|
+
- Updated dependencies [0bffb18]
|
|
590
|
+
- Updated dependencies [800f455]
|
|
591
|
+
- Updated dependencies [5458414]
|
|
592
|
+
- Updated dependencies [3241559]
|
|
593
|
+
- Updated dependencies [7f96b10]
|
|
594
|
+
- Updated dependencies [167ec42]
|
|
595
|
+
- Updated dependencies [616a2a5]
|
|
596
|
+
- Updated dependencies [6c68b13]
|
|
597
|
+
- Updated dependencies [0046d8f]
|
|
598
|
+
- Updated dependencies [f1d4748]
|
|
599
|
+
- Updated dependencies [bea374e]
|
|
600
|
+
- Updated dependencies [b1119ec]
|
|
601
|
+
- Updated dependencies [5607092]
|
|
602
|
+
- Updated dependencies [9f23d2b]
|
|
603
|
+
- Updated dependencies [578e025]
|
|
604
|
+
- Updated dependencies [af025ee]
|
|
605
|
+
- Updated dependencies [d109a4d]
|
|
606
|
+
- Updated dependencies [598c89a]
|
|
607
|
+
- Updated dependencies [4a0bd17]
|
|
608
|
+
- Updated dependencies [b8b9af4]
|
|
609
|
+
- Updated dependencies [d8b9259]
|
|
610
|
+
- Updated dependencies [31676be]
|
|
611
|
+
- Updated dependencies [8c0d52e]
|
|
612
|
+
- Updated dependencies [aff10e2]
|
|
613
|
+
- Updated dependencies [70a774b]
|
|
614
|
+
- Updated dependencies [9ce096f]
|
|
615
|
+
- Updated dependencies [e05db88]
|
|
616
|
+
- Updated dependencies [7458a41]
|
|
617
|
+
- Updated dependencies [ad13d63]
|
|
618
|
+
- Updated dependencies [5ffcc14]
|
|
619
|
+
- Updated dependencies [d971e51]
|
|
620
|
+
- Updated dependencies [97abb24]
|
|
621
|
+
- Updated dependencies [deb157a]
|
|
622
|
+
- Updated dependencies [9c60144]
|
|
623
|
+
- Updated dependencies [e7747f1]
|
|
624
|
+
- Updated dependencies [d2ce342]
|
|
625
|
+
- Updated dependencies [9695da7]
|
|
626
|
+
- Updated dependencies [ac2f332]
|
|
627
|
+
- Updated dependencies [a777058]
|
|
628
|
+
- Updated dependencies [75444e3]
|
|
629
|
+
- Updated dependencies [58b8346]
|
|
630
|
+
- Updated dependencies [2d0bd16]
|
|
631
|
+
- Updated dependencies [a9e17b4]
|
|
632
|
+
- Updated dependencies [b8ce7dc]
|
|
633
|
+
- Updated dependencies [dad51e5]
|
|
634
|
+
- Updated dependencies [1c9c342]
|
|
635
|
+
- Updated dependencies [787c738]
|
|
636
|
+
- Updated dependencies [8396656]
|
|
637
|
+
- Updated dependencies [dbbd38a]
|
|
638
|
+
- Updated dependencies [61556dc]
|
|
639
|
+
- Updated dependencies [8871c14]
|
|
640
|
+
- Updated dependencies [93fe362]
|
|
641
|
+
- Updated dependencies [dfc6975]
|
|
642
|
+
- Updated dependencies [3cf4de0]
|
|
643
|
+
- Updated dependencies [c9dc811]
|
|
644
|
+
- Updated dependencies [144ef9b]
|
|
645
|
+
- Updated dependencies [138ab04]
|
|
646
|
+
- Updated dependencies [a0b9e91]
|
|
647
|
+
- Updated dependencies [99bd015]
|
|
648
|
+
- Updated dependencies [21e4585]
|
|
649
|
+
- @object-ui/types@17.6.0
|
|
650
|
+
- @object-ui/fields@17.6.0
|
|
651
|
+
- @object-ui/i18n@17.6.0
|
|
652
|
+
- @object-ui/react@17.6.0
|
|
653
|
+
- @object-ui/components@17.6.0
|
|
654
|
+
- @object-ui/core@17.6.0
|
|
655
|
+
- @object-ui/permissions@17.6.0
|
|
656
|
+
|
|
3
657
|
## 17.5.0
|
|
4
658
|
|
|
5
659
|
### Patch Changes
|