@cosmicdrift/kumiko-renderer 0.386.0 → 0.388.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/LICENSE +21 -57
- package/dist/app/action-form-body.d.ts +2 -2
- package/dist/app/action-form-body.js +12 -4
- package/dist/app/action-form-shim.d.ts +8 -8
- package/dist/app/action-form-shim.js +20 -22
- package/dist/app/action-form-support.d.ts +1 -0
- package/dist/app/action-form-support.js +1 -1
- package/dist/app/app-features-context.js +4 -4
- package/dist/app/column-renderers.d.ts +7 -9
- package/dist/app/column-renderers.js +15 -18
- package/dist/app/config-edit-body.js +7 -3
- package/dist/app/config-edit-shim.d.ts +7 -8
- package/dist/app/config-edit-shim.js +18 -20
- package/dist/app/custom-screens.d.ts +3 -3
- package/dist/app/custom-screens.js +8 -8
- package/dist/app/dashboard-body.d.ts +2 -2
- package/dist/app/dashboard-body.js +2 -2
- package/dist/app/entity-edit-prefill.d.ts +11 -0
- package/dist/app/entity-edit-prefill.js +18 -13
- package/dist/app/entity-edit-screen.js +4 -4
- package/dist/app/entity-list-screen.js +3 -3
- package/dist/app/extension-form-submit.d.ts +1 -1
- package/dist/app/extension-form-submit.js +14 -15
- package/dist/app/extension-sections.d.ts +29 -28
- package/dist/app/extension-sections.js +10 -10
- package/dist/app/feature-schema.js +11 -11
- package/dist/app/form-schema.js +2 -2
- package/dist/app/header-actions-bar.js +2 -2
- package/dist/app/kumiko-screen.js +8 -10
- package/dist/app/layout-fields.js +1 -1
- package/dist/app/list-facets.js +3 -3
- package/dist/app/nav.d.ts +10 -10
- package/dist/app/nav.js +13 -13
- package/dist/app/projection-detail-body.js +4 -4
- package/dist/app/projection-detail-shim.d.ts +6 -5
- package/dist/app/projection-detail-shim.js +23 -22
- package/dist/app/projection-list-body.js +10 -10
- package/dist/app/projection-list-shim.d.ts +5 -5
- package/dist/app/projection-list-shim.js +17 -18
- package/dist/app/qn.js +10 -12
- package/dist/app/qualify-screen-id.js +1 -1
- package/dist/app/screen-access.js +2 -2
- package/dist/app/screen-shared.js +1 -1
- package/dist/app/secret-mint-body.js +4 -4
- package/dist/app/write-failed-error.js +8 -7
- package/dist/components/edit-mounts.d.ts +2 -2
- package/dist/components/embedded-list-field.js +5 -5
- package/dist/components/grid-cell-for-field.d.ts +1 -1
- package/dist/components/reference-create-dialog.js +3 -3
- package/dist/components/related-list-section.d.ts +1 -1
- package/dist/components/related-list-section.js +15 -2
- package/dist/components/render-edit-action-button.d.ts +1 -3
- package/dist/components/render-edit-action-button.js +2 -2
- package/dist/components/render-edit-logic.js +1 -1
- package/dist/components/render-edit-types.d.ts +6 -6
- package/dist/components/render-edit.js +74 -73
- package/dist/components/render-field.d.ts +7 -7
- package/dist/components/render-field.js +62 -61
- package/dist/components/render-list.d.ts +42 -43
- package/dist/components/render-list.js +93 -84
- package/dist/components/use-wizard-form-draft.js +10 -10
- package/dist/context/dispatcher-context.js +5 -5
- package/dist/context/user-roles-context.js +2 -2
- package/dist/flow-diagram/render.js +9 -1
- package/dist/headless/apex/index.d.ts +1 -2
- package/dist/headless/apex/index.js +5 -6
- package/dist/headless/form/form-controller.js +14 -6
- package/dist/headless/form/types.d.ts +1 -0
- package/dist/headless/form/zod-bridge.js +2 -2
- package/dist/headless/format/index.js +89 -64
- package/dist/headless/format/money.js +1 -1
- package/dist/headless/index.js +2 -2
- package/dist/headless/view-model/edit.js +4 -2
- package/dist/headless/view-model/list.js +184 -150
- package/dist/headless/view-model/types.d.ts +6 -3
- package/dist/hooks/live-refetch-scheduler.js +4 -0
- package/dist/hooks/reference-limits.js +11 -12
- package/dist/hooks/use-list-url-state.d.ts +13 -13
- package/dist/hooks/use-list-url-state.js +21 -22
- package/dist/hooks/use-query.js +3 -3
- package/dist/hooks/use-reference-lookup.d.ts +9 -1
- package/dist/hooks/use-reference-lookup.js +32 -19
- package/dist/hooks/use-store.js +18 -22
- package/dist/hooks/use-stream-handler.js +4 -2
- package/dist/i18n-defaults.js +6 -8
- package/dist/i18n.d.ts +10 -10
- package/dist/i18n.js +25 -25
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -4
- package/dist/live/dispatcher-live.js +2 -2
- package/dist/primitives.d.ts +244 -221
- package/dist/primitives.js +1 -1
- package/dist/sse/live-events.d.ts +5 -5
- package/dist/sse/live-events.js +17 -17
- package/dist/tokens.d.ts +8 -8
- package/dist/tokens.js +16 -17
- package/dist/web/app/browser-locale.d.ts +9 -9
- package/dist/web/app/browser-locale.js +19 -19
- package/dist/web/app/client-plugin.d.ts +44 -52
- package/dist/web/app/client-plugin.js +4 -5
- package/dist/web/app/create-app.d.ts +28 -31
- package/dist/web/app/create-app.js +29 -25
- package/dist/web/app/dashboard-body.js +17 -1
- package/dist/web/app/dashboard-panels.js +12 -2
- package/dist/web/app/document-lang-sync.js +1 -1
- package/dist/web/app/draft-storage.js +1 -1
- package/dist/web/app/nav-providers-context.d.ts +3 -3
- package/dist/web/app/nav-providers-context.js +3 -3
- package/dist/web/app/nav.d.ts +18 -17
- package/dist/web/app/nav.js +66 -64
- package/dist/web/app/rich-content-editor.js +1 -1
- package/dist/web/components/config-cascade.js +17 -18
- package/dist/web/components/config-source-badge.js +4 -4
- package/dist/web/index.d.ts +1 -1
- package/dist/web/index.js +1 -1
- package/dist/web/layout/app-layout.d.ts +9 -9
- package/dist/web/layout/app-layout.js +2 -2
- package/dist/web/layout/avatar.d.ts +4 -3
- package/dist/web/layout/avatar.js +15 -17
- package/dist/web/layout/default-app-shell.d.ts +22 -23
- package/dist/web/layout/editor-panel.js +3 -3
- package/dist/web/layout/nav-tree.js +86 -84
- package/dist/web/layout/profile-menu.d.ts +1 -1
- package/dist/web/layout/shell-header.js +2 -1
- package/dist/web/layout/sidebar-brand.d.ts +7 -7
- package/dist/web/layout/sidebar-user.d.ts +1 -1
- package/dist/web/layout/sidebar-user.js +4 -4
- package/dist/web/layout/sidebar.d.ts +8 -8
- package/dist/web/layout/sidebar.js +7 -7
- package/dist/web/layout/target-resolver-stub.d.ts +5 -5
- package/dist/web/layout/target-resolver-stub.js +20 -20
- package/dist/web/layout/target-url.d.ts +7 -7
- package/dist/web/layout/target-url.js +22 -22
- package/dist/web/layout/theme-toggle.js +4 -5
- package/dist/web/layout/uniform-bar-controls.d.ts +1 -0
- package/dist/web/layout/uniform-bar-controls.js +4 -0
- package/dist/web/layout/workspace-shell.d.ts +21 -21
- package/dist/web/layout/workspace-shell.js +29 -30
- package/dist/web/lib/cn.d.ts +4 -4
- package/dist/web/lib/cn.js +4 -4
- package/dist/web/lib/file-ref-download.js +4 -1
- package/dist/web/primitives/action-menu.d.ts +8 -8
- package/dist/web/primitives/action-menu.js +14 -13
- package/dist/web/primitives/calendar-popover.d.ts +1 -1
- package/dist/web/primitives/calendar-popover.js +10 -10
- package/dist/web/primitives/card-styles.js +1 -1
- package/dist/web/primitives/card.js +2 -2
- package/dist/web/primitives/code-input.d.ts +6 -0
- package/dist/web/primitives/code-input.js +31 -0
- package/dist/web/primitives/combobox.d.ts +12 -12
- package/dist/web/primitives/combobox.js +34 -35
- package/dist/web/primitives/data-table-cell.js +2 -2
- package/dist/web/primitives/data-table.js +6 -6
- package/dist/web/primitives/date-field.js +2 -2
- package/dist/web/primitives/date-input.js +4 -4
- package/dist/web/primitives/default-form.js +2 -2
- package/dist/web/primitives/dropdown-menu.js +14 -15
- package/dist/web/primitives/embedded-list-input.js +3 -3
- package/dist/web/primitives/facet-filter.js +2 -2
- package/dist/web/primitives/field.js +9 -8
- package/dist/web/primitives/file-thumbnail.d.ts +3 -0
- package/dist/web/primitives/file-thumbnail.js +5 -0
- package/dist/web/primitives/form.d.ts +1 -1
- package/dist/web/primitives/form.js +6 -6
- package/dist/web/primitives/input.js +8 -3
- package/dist/web/primitives/layout-elements.js +7 -5
- package/dist/web/primitives/layout.js +2 -2
- package/dist/web/primitives/located-timestamp-input.js +4 -4
- package/dist/web/primitives/money-input.js +13 -17
- package/dist/web/primitives/page-header.js +3 -1
- package/dist/web/primitives/pager.js +1 -1
- package/dist/web/primitives/row-actions.js +6 -7
- package/dist/web/primitives/secret-reveal.js +1 -1
- package/dist/web/primitives/timestamp-input.d.ts +9 -9
- package/dist/web/primitives/timestamp-input.js +21 -21
- package/dist/web/primitives/toast.js +12 -13
- package/dist/web/primitives/use-focus-on-mount.d.ts +2 -0
- package/dist/web/primitives/use-focus-on-mount.js +9 -0
- package/dist/web/sse/live-events.d.ts +6 -6
- package/dist/web/sse/live-events.js +3 -3
- package/dist/web/tokens.d.ts +11 -12
- package/dist/web/tokens.js +35 -37
- package/dist/web/version/update-checker.js +14 -13
- package/dist/web/widgets/ai-text-field.js +1 -1
- package/dist/web/widgets/bounded-load-cache.d.ts +1 -1
- package/dist/web/widgets/bounded-load-cache.js +10 -4
- package/dist/web/widgets/charts.d.ts +10 -10
- package/dist/web/widgets/charts.js +8 -8
- package/dist/web/widgets/choice-cards.d.ts +17 -0
- package/dist/web/widgets/choice-cards.js +12 -0
- package/dist/web/widgets/collapsible-section.d.ts +3 -3
- package/dist/web/widgets/collapsible-section.js +7 -7
- package/dist/web/widgets/detail-list.d.ts +5 -3
- package/dist/web/widgets/detail-list.js +5 -3
- package/dist/web/widgets/feed-list.d.ts +2 -2
- package/dist/web/widgets/feed-list.js +2 -2
- package/dist/web/widgets/form-fields.d.ts +14 -14
- package/dist/web/widgets/form-fields.js +14 -13
- package/dist/web/widgets/index.d.ts +1 -0
- package/dist/web/widgets/index.js +5 -4
- package/dist/web/widgets/infinity-list.js +3 -3
- package/dist/web/widgets/mode-switch.d.ts +2 -2
- package/dist/web/widgets/mode-switch.js +2 -2
- package/dist/web/widgets/pdf-preview.js +1 -1
- package/dist/web/widgets/plan-card.d.ts +2 -0
- package/dist/web/widgets/plan-card.js +1 -1
- package/dist/web/widgets/progress-list.d.ts +1 -2
- package/dist/web/widgets/progress-list.js +1 -2
- package/dist/web/widgets/query-table.d.ts +6 -6
- package/dist/web/widgets/result-panel.d.ts +16 -16
- package/dist/web/widgets/result-panel.js +10 -10
- package/dist/web/widgets/section-card.d.ts +3 -3
- package/dist/web/widgets/section-card.js +3 -3
- package/dist/web/widgets/stat.d.ts +4 -4
- package/dist/web/widgets/stat.js +6 -6
- package/dist/web/widgets/states.d.ts +4 -4
- package/dist/web/widgets/states.js +4 -4
- package/dist/web/widgets/upload-zone.js +13 -5
- package/dist/web/widgets/use-draft.d.ts +7 -7
- package/dist/web/widgets/use-draft.js +7 -7
- package/package.json +6 -6
- package/src/changes.json +49 -0
package/LICENSE
CHANGED
|
@@ -1,57 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
controlling, or under common control with the Licensor ("Affiliates"), or
|
|
23
|
-
contractors acting on their behalf. The Licensor remains free to use the
|
|
24
|
-
Licensed Work for any purpose, including for the operation of kumiko.rocks.
|
|
25
|
-
|
|
26
|
-
Change Date: 2030-05-05
|
|
27
|
-
Change License: Apache License, Version 2.0
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Terms
|
|
31
|
-
|
|
32
|
-
The Licensor hereby grants you the right to copy, modify, create derivative works,
|
|
33
|
-
redistribute, and make non-production use of the Licensed Work. The Licensor may
|
|
34
|
-
make an Additional Use Grant, above, permitting limited production use.
|
|
35
|
-
|
|
36
|
-
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
37
|
-
available distribution of the Licensed Work under this License, whichever comes
|
|
38
|
-
first, this License will convert to the Change License.
|
|
39
|
-
|
|
40
|
-
This Business Source License governs use of the Licensed Work in all cases, except
|
|
41
|
-
as to any use that is explicitly granted in the Additional Use Grant above or
|
|
42
|
-
under the Change License after the Change Date.
|
|
43
|
-
|
|
44
|
-
If your use of the Licensed Work does not comply with the requirements of this
|
|
45
|
-
License, you must cease use of the Licensed Work immediately.
|
|
46
|
-
|
|
47
|
-
All copies of the Licensed Work, and all derivative works thereof, must include
|
|
48
|
-
this License.
|
|
49
|
-
|
|
50
|
-
This License does not grant you any right, title, or interest in any trademark,
|
|
51
|
-
logo, or branding of the Licensor, except as required to comply with this License.
|
|
52
|
-
|
|
53
|
-
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN
|
|
54
|
-
“AS IS” BASIS. LICENSOR DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
|
55
|
-
WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
|
|
56
|
-
TITLE, AND NON-INFRINGEMENT. IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY DAMAGES
|
|
57
|
-
ARISING OUT OF OR RELATED TO THIS LICENSE OR THE USE OF THE LICENSED WORK.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Marc Frost
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -28,11 +28,11 @@ export declare function ActionFormBody({ schema, screen, translate, entityId, in
|
|
|
28
28
|
readonly translate?: Translate;
|
|
29
29
|
/** Record id from the route path; the source of the `load` query's id. */
|
|
30
30
|
readonly entityId?: string;
|
|
31
|
-
/** Row-drawer usage (RowAction kind:"drawer"
|
|
31
|
+
/** Row-drawer usage (RowAction kind:"drawer"): prefill extracted
|
|
32
32
|
* from the clicked row, applied on top of searchParams through the same
|
|
33
33
|
* renderableFields/sensitive gates (see mergeSearchParamsIntoInitial). */
|
|
34
34
|
readonly initialOverrides?: Readonly<Record<string, unknown>>;
|
|
35
|
-
/** Drawer-hosted usage (toolbarAction kind:"drawer"
|
|
35
|
+
/** Drawer-hosted usage (toolbarAction kind:"drawer"): called
|
|
36
36
|
* instead of the redirect-based navigation on successful submit, so the
|
|
37
37
|
* host closes the drawer + refetches its list regardless of whether
|
|
38
38
|
* `screen.redirect` is set — a full-page redirect would navigate away
|
|
@@ -112,7 +112,7 @@ export function ActionFormBody({ schema, screen, translate, entityId, initialOve
|
|
|
112
112
|
// A drawer-hosted form is not a navigation target, so it never takes a handoff.
|
|
113
113
|
const handoffValues = onSuccess === undefined ? pendingHandoff : undefined;
|
|
114
114
|
// This screen has no entity, so a money field here declares its own currency
|
|
115
|
-
// source (
|
|
115
|
+
// source (boot-enforced) — without one the form would seed a bare
|
|
116
116
|
// `0` the handler's schema rejects. When a tenant-declared field's config
|
|
117
117
|
// query errors or holds no value there is no entity default to use, and
|
|
118
118
|
// submitting a guessed currency would mis-book the amount — block instead.
|
|
@@ -129,6 +129,7 @@ export function ActionFormBody({ schema, screen, translate, entityId, initialOve
|
|
|
129
129
|
})
|
|
130
130
|
: undefined, loadableFieldNames);
|
|
131
131
|
const loadedValues = loadState?.status === "ready" ? loadState.values : undefined;
|
|
132
|
+
const refetchLoadedValues = loadState?.status === "ready" ? loadState.refetch : undefined;
|
|
132
133
|
const initial = useMemo(() => {
|
|
133
134
|
// With `load` the loaded record is the only source of values: a crafted link
|
|
134
135
|
// or a row's params must not seed fields the record would otherwise own.
|
|
@@ -204,8 +205,14 @@ export function ActionFormBody({ schema, screen, translate, entityId, initialOve
|
|
|
204
205
|
else if (hasSuccessLinks || screen.resetOnSuccess === true) {
|
|
205
206
|
publish(effectiveTranslate("kumiko.actionForm.success"));
|
|
206
207
|
}
|
|
207
|
-
if (screen.resetOnSuccess === true)
|
|
208
|
-
|
|
208
|
+
if (screen.resetOnSuccess === true) {
|
|
209
|
+
// A loaded record is stale after the write: reseed the form from the fresh one.
|
|
210
|
+
const remountForm = () => setFormEpoch((epoch) => epoch + 1);
|
|
211
|
+
if (refetchLoadedValues === undefined)
|
|
212
|
+
remountForm();
|
|
213
|
+
else
|
|
214
|
+
void refetchLoadedValues().finally(remountForm);
|
|
215
|
+
}
|
|
209
216
|
}
|
|
210
217
|
// Without a redirect the form stays put; returnTo only replaces an existing
|
|
211
218
|
// navigation, and never one to a record screen (see redirectTargetsRecord).
|
|
@@ -227,6 +234,7 @@ export function ActionFormBody({ schema, screen, translate, entityId, initialOve
|
|
|
227
234
|
dispatcher,
|
|
228
235
|
locale,
|
|
229
236
|
effectiveTranslate,
|
|
237
|
+
refetchLoadedValues,
|
|
230
238
|
]);
|
|
231
239
|
// The success box disappears with the next edit; a submit clears it itself.
|
|
232
240
|
const handleDirtyChange = useCallback((dirty) => {
|
|
@@ -251,7 +259,7 @@ export function ActionFormBody({ schema, screen, translate, entityId, initialOve
|
|
|
251
259
|
return () => navigateToReturnOr(nav, returnTarget, () => nav.navigate({ screenId: lastSegment(target) }));
|
|
252
260
|
}, [nav, screen.redirect, screen.cancelTarget, onCancelOverride, returnTarget]);
|
|
253
261
|
// Rendering the form before a tenant-declared currency lands would show the
|
|
254
|
-
// fallback and, on a fast click, submit it
|
|
262
|
+
// fallback and, on a fast click, submit it — hold instead.
|
|
255
263
|
if (currencyLoading) {
|
|
256
264
|
return _jsx(QueryLoadingBanner, {});
|
|
257
265
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type { ActionFormScreenDefinition, EntityDefinition, EntityEditScreenDefinition, FieldDefinition, SecretMintConfirmStep, SecretMintScreenDefinition } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
2
|
-
/**
|
|
3
|
-
* ActionForm
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
/** Builds a minimal EntityDefinition from the inline fields of an
|
|
3
|
+
* ActionForm or SecretMint screen. RenderEdit and computeEditViewModel
|
|
4
|
+
* iterate over entity.fields at render time; all other EntityDefinition
|
|
5
|
+
* fields remain undefined. */
|
|
6
6
|
export declare function synthesizeActionFormEntity(fields: Readonly<Record<string, FieldDefinition>>): EntityDefinition;
|
|
7
7
|
/** Fields the form may seed and submit. An excluded field the layout does not show
|
|
8
8
|
* would otherwise reach the payload through its `default`, and the handler rejects it. */
|
|
9
9
|
export declare function actionFormSubmittableFields(screen: ActionFormScreenDefinition): Readonly<Record<string, FieldDefinition>>;
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
* "entityEdit"
|
|
13
|
-
*
|
|
10
|
+
/** Converts an ActionFormScreenDefinition or SecretMintScreenDefinition to
|
|
11
|
+
* the EntityEditScreen shape expected by RenderEdit. `type` is set to
|
|
12
|
+
* "entityEdit" to satisfy the type constraint, and `entity` is pinned to
|
|
13
|
+
* the pseudo-name because RenderEdit does not read that field. */
|
|
14
14
|
export declare function synthesizeActionFormScreen(screen: ActionFormScreenDefinition | SecretMintScreenDefinition): EntityEditScreenDefinition;
|
|
15
15
|
/** Separate id (`${screen.id}:confirm`) keeps this confirm-form screen from
|
|
16
16
|
* colliding with the mint-form screen's draft key. */
|
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
// Shim
|
|
1
|
+
// Shim for ActionForm rendering.
|
|
2
2
|
//
|
|
3
|
-
// RenderEdit
|
|
4
|
-
// `screen: EntityEditScreenDefinition`
|
|
5
|
-
// `entity.fields`
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// reused werden kann ohne den Stack zu duplizieren.
|
|
3
|
+
// RenderEdit currently requires an `entity: EntityDefinition` and a
|
|
4
|
+
// `screen: EntityEditScreenDefinition` pair, but internally uses only
|
|
5
|
+
// `entity.fields` and `screen.layout`. ActionForm screens have neither an
|
|
6
|
+
// entity reference nor `type: "entityEdit"`; these helpers reshape the input
|
|
7
|
+
// so RenderEdit can be reused without duplicating the rendering stack.
|
|
9
8
|
//
|
|
10
|
-
//
|
|
11
|
-
// defaultCurrency
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// entity-Lookup), also ist der Server-Pfad davon nicht betroffen.
|
|
9
|
+
// This workaround becomes invalid if RenderEdit starts reading
|
|
10
|
+
// entity.transitions, idType, defaultCurrency, or softDelete, or if a future
|
|
11
|
+
// boot validator cross-references the schema.entities map. At that point,
|
|
12
|
+
// RenderActionForm should accept `fields` directly. The boot validator already
|
|
13
|
+
// handles actionForm independently without an entity lookup, so the server path
|
|
14
|
+
// is unaffected.
|
|
17
15
|
import { ACTION_FORM_PSEUDO_ENTITY, isFieldsEditSection, normalizeEditField, sectionFieldSpecs, } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
18
|
-
/**
|
|
19
|
-
* ActionForm
|
|
20
|
-
*
|
|
21
|
-
*
|
|
16
|
+
/** Builds a minimal EntityDefinition from the inline fields of an
|
|
17
|
+
* ActionForm or SecretMint screen. RenderEdit and computeEditViewModel
|
|
18
|
+
* iterate over entity.fields at render time; all other EntityDefinition
|
|
19
|
+
* fields remain undefined. */
|
|
22
20
|
export function synthesizeActionFormEntity(fields) {
|
|
23
21
|
return { fields };
|
|
24
22
|
}
|
|
@@ -68,10 +66,10 @@ export function actionFormSubmittableFields(screen) {
|
|
|
68
66
|
: []));
|
|
69
67
|
return Object.fromEntries(Object.entries(screen.fields).filter(([name]) => inLayout.has(name) || !excluded.includes(name)));
|
|
70
68
|
}
|
|
71
|
-
/**
|
|
72
|
-
*
|
|
73
|
-
* "entityEdit"
|
|
74
|
-
*
|
|
69
|
+
/** Converts an ActionFormScreenDefinition or SecretMintScreenDefinition to
|
|
70
|
+
* the EntityEditScreen shape expected by RenderEdit. `type` is set to
|
|
71
|
+
* "entityEdit" to satisfy the type constraint, and `entity` is pinned to
|
|
72
|
+
* the pseudo-name because RenderEdit does not read that field. */
|
|
75
73
|
export function synthesizeActionFormScreen(screen) {
|
|
76
74
|
return {
|
|
77
75
|
id: screen.id,
|
|
@@ -21,6 +21,7 @@ export type ActionFormLoadState = {
|
|
|
21
21
|
} | {
|
|
22
22
|
readonly status: "ready";
|
|
23
23
|
readonly values: Readonly<Record<string, unknown>>;
|
|
24
|
+
readonly refetch: () => Promise<void>;
|
|
24
25
|
};
|
|
25
26
|
/** A sensitive, writeOnly or password field never takes a value from a loaded
|
|
26
27
|
* record: the form must not echo a secret back into an input. */
|
|
@@ -53,7 +53,7 @@ export function useActionFormLoad(load, recordId, fieldNames) {
|
|
|
53
53
|
return { status: "loading" };
|
|
54
54
|
if (query.data === null)
|
|
55
55
|
return { status: "missing-record" };
|
|
56
|
-
return { status: "ready", values };
|
|
56
|
+
return { status: "ready", values, refetch: query.refetch };
|
|
57
57
|
}
|
|
58
58
|
/** Banner for every `load` state that is not "ready". */
|
|
59
59
|
export function ActionFormLoadStatus({ state, screenId, translate, }) {
|
|
@@ -2,10 +2,10 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
// Cross-feature schema access for components that need to resolve a
|
|
3
3
|
// screen owned by a DIFFERENT feature than the one they're rendering
|
|
4
4
|
// under — e.g. a reference field opening the target entity's create
|
|
5
|
-
// screen
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
5
|
+
// screen. `createKumikoApp` provides the full `app.features` list;
|
|
6
|
+
// components elsewhere in the render tree default to an empty list (no
|
|
7
|
+
// cross-feature schema known, e.g. outside `createKumikoApp` or in
|
|
8
|
+
// isolated tests).
|
|
9
9
|
import { createContext, useContext } from "react";
|
|
10
10
|
const AppFeaturesContext = createContext([]);
|
|
11
11
|
export function AppFeaturesProvider({ features, children }) {
|
|
@@ -17,14 +17,12 @@ export type ColumnRenderersProviderProps = {
|
|
|
17
17
|
readonly value: ColumnRenderersMap;
|
|
18
18
|
};
|
|
19
19
|
export declare function ColumnRenderersProvider({ children, value, }: ColumnRenderersProviderProps): ReactNode;
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* Default-Type-Renderer zurück.
|
|
20
|
+
/** Looks up the component for a renderer key. Returns undefined when `name` is
|
|
21
|
+
* empty/undefined (the caller has no __component renderer), or when no provider
|
|
22
|
+
* is mounted or the key is absent from the map. The caller (DataTable.renderCell)
|
|
23
|
+
* then logs a warning and falls back to the default type renderer.
|
|
25
24
|
*
|
|
26
|
-
* `name`
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* Caller einen Stub-Key wie `""` reichen muss. */
|
|
25
|
+
* `name` is optional so callers can invoke the hook unconditionally—Rules of
|
|
26
|
+
* Hooks prohibit a function branch that skips the hook. This keeps the call to
|
|
27
|
+
* a single line without requiring the caller to provide a stub key such as `""`. */
|
|
30
28
|
export declare function useColumnRenderer(name?: string): ColumnRendererComponent | undefined;
|
|
@@ -1,29 +1,26 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// Column-Renderer-Map: client-side
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
2
|
+
// Column-Renderer-Map: client-side lookup for ListColumn columns that specify a
|
|
3
|
+
// PlatformComponent renderer (`{ react: { __component: "Name" } }`) in the schema
|
|
4
|
+
// instead of a string function. createKumikoApp in renderer/web collects all
|
|
5
|
+
// clientFeatures.columnRenderers and mounts the provider; the DataTable cell
|
|
6
|
+
// renderer looks up the component through `useColumnRenderer(name)`.
|
|
7
7
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// client-seitig.
|
|
8
|
+
// Like CustomScreensProvider, the renderer web bootstrap mounts both providers
|
|
9
|
+
// at the same location. Schemas remain serializable: the component is referenced
|
|
10
|
+
// only by string key, while the map exists solely on the client.
|
|
12
11
|
import { createContext, useContext } from "react";
|
|
13
12
|
const ColumnRenderersContext = createContext(undefined);
|
|
14
13
|
export function ColumnRenderersProvider({ children, value, }) {
|
|
15
14
|
return (_jsx(ColumnRenderersContext.Provider, { value: value, children: children }));
|
|
16
15
|
}
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* Default-Type-Renderer zurück.
|
|
16
|
+
/** Looks up the component for a renderer key. Returns undefined when `name` is
|
|
17
|
+
* empty/undefined (the caller has no __component renderer), or when no provider
|
|
18
|
+
* is mounted or the key is absent from the map. The caller (DataTable.renderCell)
|
|
19
|
+
* then logs a warning and falls back to the default type renderer.
|
|
22
20
|
*
|
|
23
|
-
* `name`
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* Caller einen Stub-Key wie `""` reichen muss. */
|
|
21
|
+
* `name` is optional so callers can invoke the hook unconditionally—Rules of
|
|
22
|
+
* Hooks prohibit a function branch that skips the hook. This keeps the call to
|
|
23
|
+
* a single line without requiring the caller to provide a stub key such as `""`. */
|
|
27
24
|
export function useColumnRenderer(name) {
|
|
28
25
|
const map = useContext(ColumnRenderersContext);
|
|
29
26
|
if (name === undefined || name === "")
|
|
@@ -15,7 +15,7 @@ import { buildInitialValues } from "./entity-edit-prefill.js";
|
|
|
15
15
|
import { layoutEditFields } from "./layout-fields.js";
|
|
16
16
|
import { QueryErrorBanner, QueryLoadingBanner } from "./query-state-banners.js";
|
|
17
17
|
// A money-typed config-edit field renders through RenderField's entityEdit
|
|
18
|
-
// `{amount, currency}` payload shape (render-field.tsx
|
|
18
|
+
// `{amount, currency}` payload shape (render-field.tsx), but
|
|
19
19
|
// `ConfigKeyType` (write-helpers.ts validateType) only ever knows
|
|
20
20
|
// number/boolean/text/select — a config value is always a bare scalar.
|
|
21
21
|
// Unwrap back to the amount before it hits config:write:set.
|
|
@@ -97,8 +97,12 @@ export function ConfigEditBody({ schema, screen, translate, }) {
|
|
|
97
97
|
// Detail load: config:query:values returns ALL keys of the tenant.
|
|
98
98
|
// We map them via screen.configKeys from short to qualified name onto our
|
|
99
99
|
// form field values.
|
|
100
|
-
const valuesQuery = useQuery("config:query:values", {
|
|
101
|
-
|
|
100
|
+
const valuesQuery = useQuery("config:query:values", {
|
|
101
|
+
scope: screen.scope,
|
|
102
|
+
});
|
|
103
|
+
const cascadeQuery = useQuery("config:query:cascade", {
|
|
104
|
+
scope: screen.scope,
|
|
105
|
+
});
|
|
102
106
|
const secretKeys = screen.secretKeys;
|
|
103
107
|
const secretsQuery = useQuery("secrets:query:list", {}, { enabled: secretKeys !== undefined });
|
|
104
108
|
const synthEntity = useMemo(() => synthesizeConfigEditEntity(screen.fields), [screen.fields]);
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { ConfigEditScreenDefinition, EntityDefinition, EntityEditScreenDefinition } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Felder bleiben undefined. */
|
|
3
|
+
/** Builds a minimal EntityDefinition from the ConfigEdit screen's inline
|
|
4
|
+
* fields. RenderEdit + computeEditViewModel iterate over entity.fields
|
|
5
|
+
* at render time; all other EntityDefinition fields remain undefined. */
|
|
7
6
|
export declare function synthesizeConfigEditEntity(fields: ConfigEditScreenDefinition["fields"]): EntityDefinition;
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
/** Converts a ConfigEditScreenDefinition to the EntityEditScreen shape
|
|
8
|
+
* expected by RenderEdit. `type` is set to "entityEdit" to satisfy the
|
|
9
|
+
* type constraint; `entity` is pinned to the pseudo-name — RenderEdit
|
|
10
|
+
* does not read this field. */
|
|
12
11
|
export declare function synthesizeConfigEditScreen(screen: ConfigEditScreenDefinition): EntityEditScreenDefinition;
|
|
13
12
|
/** Client-side range check for number keys with declared bounds, so an
|
|
14
13
|
* out-of-range value surfaces on its field instead of as the server's
|
|
@@ -1,31 +1,29 @@
|
|
|
1
|
-
// Shim
|
|
1
|
+
// Shim for the ConfigEdit renderer (analogous to action-form-shim.ts).
|
|
2
2
|
//
|
|
3
|
-
// RenderEdit
|
|
4
|
-
// `screen: EntityEditScreenDefinition`
|
|
5
|
-
// `entity.fields`
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// ad-hoc um, damit RenderEdit reused werden kann.
|
|
3
|
+
// RenderEdit requires an `entity: EntityDefinition` +
|
|
4
|
+
// `screen: EntityEditScreenDefinition` pair, but internally uses only
|
|
5
|
+
// `entity.fields` and `screen.layout` for rendering. ConfigEdit screens
|
|
6
|
+
// have neither an entity reference nor `type: "entityEdit"` — these two
|
|
7
|
+
// helpers reshape the data input ad hoc so RenderEdit can be reused.
|
|
9
8
|
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
9
|
+
// The same debt reservation as in action-form-shim applies: if RenderEdit
|
|
10
|
+
// starts accessing entity.transitions / idType / softDelete, or a future
|
|
11
|
+
// boot validator cross-references the schema.entities map, these type lies
|
|
12
|
+
// will fail silently. At that point, a real RenderConfigEdit component
|
|
13
|
+
// that takes fields directly is needed.
|
|
15
14
|
import * as z from "zod";
|
|
16
15
|
import { I18N_KEY_PARAM } from "../headless/index.js";
|
|
17
16
|
const CONFIG_EDIT_PSEUDO_ENTITY = "__config-edit__";
|
|
18
|
-
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* Felder bleiben undefined. */
|
|
17
|
+
/** Builds a minimal EntityDefinition from the ConfigEdit screen's inline
|
|
18
|
+
* fields. RenderEdit + computeEditViewModel iterate over entity.fields
|
|
19
|
+
* at render time; all other EntityDefinition fields remain undefined. */
|
|
22
20
|
export function synthesizeConfigEditEntity(fields) {
|
|
23
21
|
return { fields };
|
|
24
22
|
}
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
23
|
+
/** Converts a ConfigEditScreenDefinition to the EntityEditScreen shape
|
|
24
|
+
* expected by RenderEdit. `type` is set to "entityEdit" to satisfy the
|
|
25
|
+
* type constraint; `entity` is pinned to the pseudo-name — RenderEdit
|
|
26
|
+
* does not read this field. */
|
|
29
27
|
export function synthesizeConfigEditScreen(screen) {
|
|
30
28
|
return {
|
|
31
29
|
id: screen.id,
|
|
@@ -5,7 +5,7 @@ export type CustomScreensProviderProps = {
|
|
|
5
5
|
readonly value: CustomScreensMap;
|
|
6
6
|
};
|
|
7
7
|
export declare function CustomScreensProvider({ children, value }: CustomScreensProviderProps): ReactNode;
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
/** Looks up the component for a custom screen. Returns undefined
|
|
9
|
+
* when neither a provider is mounted nor screenId is in the map—the
|
|
10
|
+
* caller (KumikoScreen) then displays its placeholder banner. */
|
|
11
11
|
export declare function useCustomScreenComponent(screenId: string): ComponentType | undefined;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// Custom-
|
|
3
|
-
// `custom`. KumikoScreen
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
2
|
+
// Custom-screen component map: client-side lookup for screens of type
|
|
3
|
+
// `custom`. KumikoScreen looks up `screen.id` (or qn) here and renders
|
|
4
|
+
// the matching component. createKumikoApp in renderer/web collects all
|
|
5
|
+
// clientFeatures.components and mounts the provider; tests that check
|
|
6
|
+
// individual custom screens mount the provider directly.
|
|
7
7
|
import { createContext, useContext } from "react";
|
|
8
8
|
const CustomScreensContext = createContext(undefined);
|
|
9
9
|
export function CustomScreensProvider({ children, value }) {
|
|
10
10
|
return _jsx(CustomScreensContext.Provider, { value: value, children: children });
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
/** Looks up the component for a custom screen. Returns undefined
|
|
13
|
+
* when neither a provider is mounted nor screenId is in the map—the
|
|
14
|
+
* caller (KumikoScreen) then displays its placeholder banner. */
|
|
15
15
|
export function useCustomScreenComponent(screenId) {
|
|
16
16
|
const map = useContext(CustomScreensContext);
|
|
17
17
|
if (map === undefined)
|
|
@@ -11,6 +11,6 @@ export type DashboardBodyProviderProps = {
|
|
|
11
11
|
readonly value: ComponentType<DashboardBodyProps>;
|
|
12
12
|
};
|
|
13
13
|
export declare function DashboardBodyProvider({ children, value }: DashboardBodyProviderProps): ReactNode;
|
|
14
|
-
/** Undefined
|
|
15
|
-
*
|
|
14
|
+
/** Undefined when no platform package has registered a dashboard body;
|
|
15
|
+
* KumikoScreen then displays its placeholder banner. */
|
|
16
16
|
export declare function useDashboardBody(): ComponentType<DashboardBodyProps> | undefined;
|
|
@@ -4,8 +4,8 @@ const DashboardBodyContext = createContext(undefined);
|
|
|
4
4
|
export function DashboardBodyProvider({ children, value }) {
|
|
5
5
|
return _jsx(DashboardBodyContext.Provider, { value: value, children: children });
|
|
6
6
|
}
|
|
7
|
-
/** Undefined
|
|
8
|
-
*
|
|
7
|
+
/** Undefined when no platform package has registered a dashboard body;
|
|
8
|
+
* KumikoScreen then displays its placeholder banner. */
|
|
9
9
|
export function useDashboardBody() {
|
|
10
10
|
return useContext(DashboardBodyContext);
|
|
11
11
|
}
|
|
@@ -2,6 +2,17 @@ import type { FormValues } from "../headless/index.ts";
|
|
|
2
2
|
export declare function versionOf(record: Readonly<Record<string, unknown>>): number;
|
|
3
3
|
export declare function buildInitialValues(fields: Readonly<Record<string, unknown>>, defaultCurrency?: string, moneyCurrencyOverrides?: Readonly<Record<string, string>>): FormValues;
|
|
4
4
|
export declare function tenantCurrencyMoneyFieldNames(fields: Readonly<Record<string, unknown>>): readonly string[];
|
|
5
|
+
export type TenantCurrencyResolution = {
|
|
6
|
+
readonly status: "not-needed";
|
|
7
|
+
} | {
|
|
8
|
+
readonly status: "loading";
|
|
9
|
+
} | {
|
|
10
|
+
readonly status: "unresolved";
|
|
11
|
+
} | {
|
|
12
|
+
readonly status: "ready";
|
|
13
|
+
readonly currency: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function useTenantCurrency(needed: boolean, fallback: string | undefined): TenantCurrencyResolution;
|
|
5
16
|
export declare function literalCurrencyOverrides(fields: Readonly<Record<string, unknown>>): Readonly<Record<string, string>>;
|
|
6
17
|
export declare function useMoneyCurrencyOverrides(fields: Readonly<Record<string, unknown>>, tenantFieldNames: readonly string[], fallback: string | undefined): {
|
|
7
18
|
readonly overrides: Readonly<Record<string, string>> | undefined;
|