@cosmicdrift/kumiko-renderer 0.327.0 → 0.328.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/action-form-shim.d.ts +14 -0
- package/{src/app/action-form-shim.ts → dist/app/action-form-shim.js} +26 -44
- package/dist/app/app-features-context.d.ts +8 -0
- package/dist/app/app-features-context.js +16 -0
- package/dist/app/column-renderers.d.ts +30 -0
- package/dist/app/column-renderers.js +34 -0
- package/dist/app/config-edit-shim.d.ts +11 -0
- package/{src/app/config-edit-shim.ts → dist/app/config-edit-shim.js} +12 -25
- package/dist/app/content-editors.d.ts +38 -0
- package/dist/app/content-editors.js +26 -0
- package/dist/app/content-preview.d.ts +11 -0
- package/dist/app/content-preview.js +30 -0
- package/dist/app/custom-screens.d.ts +11 -0
- package/dist/app/custom-screens.js +20 -0
- package/dist/app/dashboard-body.d.ts +16 -0
- package/dist/app/dashboard-body.js +11 -0
- package/dist/app/extension-form-submit.d.ts +32 -0
- package/dist/app/extension-form-submit.js +73 -0
- package/dist/app/extension-sections.d.ts +72 -0
- package/dist/app/extension-sections.js +34 -0
- package/dist/app/feature-schema.d.ts +4 -0
- package/{src/app/feature-schema.ts → dist/app/feature-schema.js} +12 -22
- package/dist/app/form-schema.d.ts +4 -0
- package/dist/app/form-schema.js +85 -0
- package/dist/app/kumiko-screen.d.ts +43 -0
- package/dist/app/kumiko-screen.js +2206 -0
- package/dist/app/layout-fields.d.ts +3 -0
- package/dist/app/layout-fields.js +20 -0
- package/dist/app/list-facets.d.ts +48 -0
- package/dist/app/list-facets.js +185 -0
- package/dist/app/nav.d.ts +61 -0
- package/dist/app/nav.js +139 -0
- package/dist/app/projection-detail-shim.d.ts +8 -0
- package/dist/app/projection-detail-shim.js +71 -0
- package/dist/app/projection-list-shim.d.ts +13 -0
- package/{src/app/projection-list-shim.ts → dist/app/projection-list-shim.js} +26 -38
- package/dist/app/qn.d.ts +7 -0
- package/{src/app/qn.ts → dist/app/qn.js} +9 -11
- package/dist/app/qualify-screen-id.d.ts +2 -0
- package/{src/app/qualify-screen-id.ts → dist/app/qualify-screen-id.js} +5 -6
- package/dist/app/reference-facet-bridge.d.ts +10 -0
- package/dist/app/reference-facet-bridge.js +22 -0
- package/dist/app/return-to.d.ts +31 -0
- package/dist/app/return-to.js +188 -0
- package/dist/app/row-actions.d.ts +77 -0
- package/dist/app/row-actions.js +416 -0
- package/dist/app/screen-access.d.ts +8 -0
- package/dist/app/screen-access.js +48 -0
- package/dist/app/secret-mint-body.d.ts +10 -0
- package/dist/app/secret-mint-body.js +140 -0
- package/dist/app/secrets-edit-body.d.ts +8 -0
- package/dist/app/secrets-edit-body.js +76 -0
- package/dist/app/use-embedded-screen.d.ts +6 -0
- package/dist/app/use-embedded-screen.js +19 -0
- package/dist/app/variable-chips.d.ts +7 -0
- package/dist/app/variable-chips.js +16 -0
- package/dist/app/write-failed-error.d.ts +6 -0
- package/dist/app/write-failed-error.js +21 -0
- package/dist/components/embedded-list-field.d.ts +10 -0
- package/dist/components/embedded-list-field.js +259 -0
- package/dist/components/grid-cell-for-field.d.ts +25 -0
- package/dist/components/grid-cell-for-field.js +31 -0
- package/dist/components/multi-select-checkboxes.d.ts +14 -0
- package/dist/components/multi-select-checkboxes.js +36 -0
- package/dist/components/reference-create-dialog.d.ts +13 -0
- package/dist/components/reference-create-dialog.js +46 -0
- package/dist/components/related-list-section.d.ts +25 -0
- package/dist/components/related-list-section.js +273 -0
- package/dist/components/render-edit-action-button.d.ts +22 -0
- package/dist/components/render-edit-action-button.js +43 -0
- package/dist/components/render-edit-logic.d.ts +6 -0
- package/dist/components/render-edit-logic.js +63 -0
- package/dist/components/render-edit-types.d.ts +209 -0
- package/dist/components/render-edit-types.js +1 -0
- package/dist/components/render-edit.d.ts +6 -0
- package/dist/components/render-edit.js +1169 -0
- package/dist/components/render-field.d.ts +38 -0
- package/dist/components/render-field.js +544 -0
- package/dist/components/render-list.d.ts +117 -0
- package/dist/components/render-list.js +232 -0
- package/dist/components/write-form-section.d.ts +17 -0
- package/dist/components/write-form-section.js +104 -0
- package/dist/context/dispatcher-context.d.ts +10 -0
- package/{src/context/dispatcher-context.tsx → dist/context/dispatcher-context.js} +16 -29
- package/dist/context/draft-storage-context.d.ts +12 -0
- package/dist/context/draft-storage-context.js +18 -0
- package/dist/context/user-roles-context.d.ts +7 -0
- package/{src/context/user-roles-context.tsx → dist/context/user-roles-context.js} +7 -15
- package/dist/format-when.d.ts +1 -0
- package/{src/format-when.ts → dist/format-when.js} +7 -7
- package/dist/hooks/reference-limits.d.ts +3 -0
- package/{src/hooks/reference-limits.ts → dist/hooks/reference-limits.js} +0 -1
- package/dist/hooks/use-ai-text.d.ts +52 -0
- package/dist/hooks/use-ai-text.js +90 -0
- package/dist/hooks/use-disclosure.d.ts +7 -0
- package/dist/hooks/use-disclosure.js +8 -0
- package/dist/hooks/use-form.d.ts +7 -0
- package/dist/hooks/use-form.js +36 -0
- package/dist/hooks/use-list-url-state.d.ts +43 -0
- package/dist/hooks/use-list-url-state.js +131 -0
- package/dist/hooks/use-mutation.d.ts +9 -0
- package/dist/hooks/use-mutation.js +37 -0
- package/dist/hooks/use-query.d.ts +14 -0
- package/dist/hooks/use-query.js +118 -0
- package/dist/hooks/use-reference-lookup.d.ts +14 -0
- package/dist/hooks/use-reference-lookup.js +63 -0
- package/dist/hooks/use-store.d.ts +3 -0
- package/dist/hooks/use-store.js +38 -0
- package/dist/hooks/use-stream-handler.d.ts +14 -0
- package/dist/hooks/use-stream-handler.js +93 -0
- package/dist/i18n-defaults.d.ts +2 -0
- package/dist/i18n-defaults.js +201 -0
- package/dist/i18n.d.ts +64 -0
- package/dist/i18n.js +166 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +55 -0
- package/dist/inside-drawer.d.ts +2 -0
- package/dist/inside-drawer.js +9 -0
- package/dist/page-header-slot.d.ts +2 -0
- package/dist/page-header-slot.js +9 -0
- package/dist/primitives.d.ts +1351 -0
- package/dist/primitives.js +73 -0
- package/dist/screen-fills-height.d.ts +3 -0
- package/dist/screen-fills-height.js +3 -0
- package/dist/share-links.d.ts +4 -0
- package/dist/share-links.js +11 -0
- package/dist/sort-by-accessor.d.ts +5 -0
- package/dist/sort-by-accessor.js +16 -0
- package/dist/sse/live-events.d.ts +23 -0
- package/dist/sse/live-events.js +28 -0
- package/dist/tokens.d.ts +83 -0
- package/dist/tokens.js +80 -0
- package/package.json +16 -9
- package/src/changes.json +52 -0
- package/src/__tests__/error-i18n-defaults.test.ts +0 -82
- package/src/__tests__/format-when.test.ts +0 -12
- package/src/__tests__/i18n.test.tsx +0 -283
- package/src/__tests__/merge-search-params-into-initial.test.ts +0 -525
- package/src/__tests__/qn.test.ts +0 -83
- package/src/__tests__/share-links.test.ts +0 -26
- package/src/__tests__/sort-by-accessor.test.ts +0 -48
- package/src/__tests__/stringify-nav-params.test.ts +0 -33
- package/src/__tests__/use-list-url-state.test.tsx +0 -250
- package/src/app/__tests__/action-form-field-labels.test.tsx +0 -92
- package/src/app/__tests__/action-form-shim.test.ts +0 -137
- package/src/app/__tests__/build-list-query-payload.test.ts +0 -107
- package/src/app/__tests__/config-edit-shim.test.ts +0 -57
- package/src/app/__tests__/content-editors.test.tsx +0 -128
- package/src/app/__tests__/content-preview.test.tsx +0 -184
- package/src/app/__tests__/entity-edit-create-search-params.test.tsx +0 -236
- package/src/app/__tests__/entity-edit-jsonb-embedded-submit.test.tsx +0 -239
- package/src/app/__tests__/entity-list-create-singleton.test.tsx +0 -128
- package/src/app/__tests__/entity-list-row-action-entity-target.test.tsx +0 -424
- package/src/app/__tests__/entity-list-row-action-icon.test.tsx +0 -248
- package/src/app/__tests__/entity-list-row-action-kumiko-actions-view.test.tsx +0 -162
- package/src/app/__tests__/entity-list-row-action-refetch.test.tsx +0 -401
- package/src/app/__tests__/entity-list-screen-padding.test.tsx +0 -111
- package/src/app/__tests__/feature-schema.test.ts +0 -40
- package/src/app/__tests__/form-schema.test.ts +0 -247
- package/src/app/__tests__/list-daterange-facet.test.ts +0 -165
- package/src/app/__tests__/list-filter-facets.test.tsx +0 -521
- package/src/app/__tests__/nav.test.ts +0 -198
- package/src/app/__tests__/projection-detail-actions.test.tsx +0 -719
- package/src/app/__tests__/projection-detail-reference-field.test.tsx +0 -165
- package/src/app/__tests__/projection-detail-shim.test.ts +0 -188
- package/src/app/__tests__/projection-detail-singleton.test.tsx +0 -191
- package/src/app/__tests__/projection-list-bad-shape.test.tsx +0 -152
- package/src/app/__tests__/projection-list-reference-column.test.tsx +0 -219
- package/src/app/__tests__/projection-list-search-sort.test.tsx +0 -212
- package/src/app/__tests__/qualified-names.test.ts +0 -37
- package/src/app/__tests__/return-to.test.ts +0 -396
- package/src/app/__tests__/row-actions-navigate-tab.test.ts +0 -223
- package/src/app/__tests__/row-default-edit-action.test.tsx +0 -324
- package/src/app/__tests__/screen-access-allows.test.ts +0 -34
- package/src/app/__tests__/secret-mint-body.test.tsx +0 -404
- package/src/app/__tests__/variable-chips.test.tsx +0 -70
- package/src/app/app-features-context.tsx +0 -25
- package/src/app/column-renderers.tsx +0 -68
- package/src/app/content-editors.tsx +0 -85
- package/src/app/content-preview.tsx +0 -67
- package/src/app/custom-screens.tsx +0 -29
- package/src/app/dashboard-body.tsx +0 -33
- package/src/app/extension-form-submit.tsx +0 -123
- package/src/app/extension-sections.tsx +0 -111
- package/src/app/form-schema.ts +0 -91
- package/src/app/kumiko-screen.tsx +0 -3614
- package/src/app/layout-fields.ts +0 -31
- package/src/app/list-facets.ts +0 -259
- package/src/app/nav.tsx +0 -258
- package/src/app/projection-detail-shim.ts +0 -85
- package/src/app/reference-facet-bridge.tsx +0 -58
- package/src/app/return-to.tsx +0 -234
- package/src/app/row-actions.ts +0 -639
- package/src/app/screen-access.ts +0 -63
- package/src/app/secret-mint-body.tsx +0 -259
- package/src/app/secrets-edit-body.tsx +0 -194
- package/src/app/use-embedded-screen.ts +0 -27
- package/src/app/variable-chips.tsx +0 -39
- package/src/app/write-failed-error.ts +0 -27
- package/src/components/__tests__/embedded-list-field.test.tsx +0 -531
- package/src/components/__tests__/multi-select-checkboxes.test.tsx +0 -162
- package/src/components/__tests__/related-list-section-empty-state.test.tsx +0 -143
- package/src/components/__tests__/related-list-section.test.tsx +0 -1669
- package/src/components/__tests__/render-edit-action-button.test.tsx +0 -205
- package/src/components/__tests__/render-edit-hidden-section.test.tsx +0 -128
- package/src/components/__tests__/render-edit-logic.test.ts +0 -314
- package/src/components/__tests__/render-edit-screen-description.test.tsx +0 -152
- package/src/components/__tests__/render-edit-submit-actions.test.tsx +0 -460
- package/src/components/__tests__/render-field-app-locale.test.tsx +0 -142
- package/src/components/__tests__/render-field-enum-option.test.tsx +0 -99
- package/src/components/__tests__/render-field-icon-derivation.test.tsx +0 -119
- package/src/components/__tests__/render-field-json-format.test.tsx +0 -164
- package/src/components/__tests__/render-field-money-embedded-list-consistency.test.tsx +0 -212
- package/src/components/__tests__/render-field-money-roundtrip.test.tsx +0 -217
- package/src/components/__tests__/render-field-number-grouping.test.tsx +0 -76
- package/src/components/__tests__/render-field-number-unit.test.tsx +0 -227
- package/src/components/__tests__/render-field-password-format.test.tsx +0 -101
- package/src/components/__tests__/render-field-select-display.test.tsx +0 -134
- package/src/components/__tests__/render-field-unit-format.test.tsx +0 -107
- package/src/components/__tests__/render-field-unsupported-types.test.tsx +0 -195
- package/src/components/__tests__/render-list-toolbar-icon-only.test.tsx +0 -146
- package/src/components/__tests__/write-form-section.test.tsx +0 -375
- package/src/components/embedded-list-field.tsx +0 -354
- package/src/components/grid-cell-for-field.tsx +0 -60
- package/src/components/multi-select-checkboxes.tsx +0 -93
- package/src/components/reference-create-dialog.tsx +0 -91
- package/src/components/related-list-section.tsx +0 -467
- package/src/components/render-edit-action-button.tsx +0 -106
- package/src/components/render-edit-logic.ts +0 -85
- package/src/components/render-edit-types.ts +0 -216
- package/src/components/render-edit.tsx +0 -1700
- package/src/components/render-field.tsx +0 -942
- package/src/components/render-list.tsx +0 -561
- package/src/components/write-form-section.tsx +0 -199
- package/src/context/draft-storage-context.tsx +0 -39
- package/src/hooks/__tests__/use-ai-text.test.tsx +0 -177
- package/src/hooks/__tests__/use-disclosure.test.tsx +0 -25
- package/src/hooks/__tests__/use-form.test.tsx +0 -65
- package/src/hooks/__tests__/use-mutation.test.tsx +0 -77
- package/src/hooks/__tests__/use-stream-handler.test.tsx +0 -107
- package/src/hooks/use-ai-text.ts +0 -172
- package/src/hooks/use-disclosure.ts +0 -20
- package/src/hooks/use-form.ts +0 -78
- package/src/hooks/use-list-url-state.ts +0 -171
- package/src/hooks/use-mutation.ts +0 -61
- package/src/hooks/use-query.ts +0 -132
- package/src/hooks/use-reference-lookup.ts +0 -76
- package/src/hooks/use-store.ts +0 -48
- package/src/hooks/use-stream-handler.ts +0 -134
- package/src/i18n-defaults.ts +0 -220
- package/src/i18n.tsx +0 -286
- package/src/index.ts +0 -272
- package/src/primitives.tsx +0 -1446
- package/src/share-links.ts +0 -12
- package/src/sort-by-accessor.ts +0 -20
- package/src/sse/live-events.tsx +0 -56
- package/src/tokens.tsx +0 -170
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
/** Extrahiert den `__component`-Namen aus einer PlatformComponent. Liest
|
|
4
|
+
* react- und native-Branch (die App-Author registriert beide unter dem
|
|
5
|
+
* gleichen Namen); returnt den ersten gefundenen string. Pure narrowing
|
|
6
|
+
* via `in` — kein cast, kein assertion. */
|
|
7
|
+
export function extensionSectionName(component) {
|
|
8
|
+
for (const branch of [component.react, component.native]) {
|
|
9
|
+
if (branch !== null && typeof branch === "object" && "__component" in branch) {
|
|
10
|
+
const candidate = branch.__component;
|
|
11
|
+
if (typeof candidate === "string")
|
|
12
|
+
return candidate;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const ExtensionSectionsContext = createContext(undefined);
|
|
18
|
+
export function ExtensionSectionsProvider({ children, value, }) {
|
|
19
|
+
return (_jsx(ExtensionSectionsContext.Provider, { value: value, children: children }));
|
|
20
|
+
}
|
|
21
|
+
/** Schaut die Component für einen extension-section-Namen nach. Returnt
|
|
22
|
+
* undefined wenn weder Provider gemounted noch der Name in der Map
|
|
23
|
+
* registriert ist — der Caller (RenderEdit) zeigt dann seinen
|
|
24
|
+
* Placeholder-Banner. `name` ist optional damit Caller den Hook
|
|
25
|
+
* unkonditional aufrufen können (Rules-of-Hooks), ohne einen Stub-Key
|
|
26
|
+
* wie `""` reichen zu müssen — analog `useColumnRenderer`. */
|
|
27
|
+
export function useExtensionSectionComponent(name) {
|
|
28
|
+
const map = useContext(ExtensionSectionsContext);
|
|
29
|
+
if (name === undefined || name === "")
|
|
30
|
+
return undefined;
|
|
31
|
+
if (map === undefined)
|
|
32
|
+
return undefined;
|
|
33
|
+
return map[name];
|
|
34
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AppSchema, FeatureSchema, QualifiedContentCollection, WorkspaceSchema } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
2
|
+
export type { AppSchema, FeatureSchema, QualifiedContentCollection, WorkspaceSchema };
|
|
3
|
+
export declare function toAppSchema(input: FeatureSchema | AppSchema): AppSchema;
|
|
4
|
+
export declare function isAppSchema(input: FeatureSchema | AppSchema): input is AppSchema;
|
|
@@ -21,40 +21,30 @@
|
|
|
21
21
|
// };
|
|
22
22
|
//
|
|
23
23
|
// // feature.ts (server-only — imports defineFeature)
|
|
24
|
-
// import { taskEntity, editScreen, ... } from "./feature-schema";
|
|
24
|
+
// import { taskEntity, editScreen, ... } from "./feature-schema.js";
|
|
25
25
|
// export const taskFeature = defineFeature("tasks", (r) => {
|
|
26
26
|
// r.entity("task", taskEntity);
|
|
27
27
|
// r.writeHandler(...);
|
|
28
28
|
// r.screen(editScreen);
|
|
29
29
|
// ...
|
|
30
30
|
// });
|
|
31
|
-
|
|
32
|
-
import type {
|
|
33
|
-
AppSchema,
|
|
34
|
-
FeatureSchema,
|
|
35
|
-
QualifiedContentCollection,
|
|
36
|
-
WorkspaceSchema,
|
|
37
|
-
} from "@cosmicdrift/kumiko-framework/ui-types";
|
|
38
|
-
|
|
39
|
-
export type { AppSchema, FeatureSchema, QualifiedContentCollection, WorkspaceSchema };
|
|
40
|
-
|
|
41
31
|
// Normalisiert FeatureSchema → AppSchema. Idempotent für AppSchema.
|
|
42
32
|
// Hebt eine Feature-lokal deklarierte `workspaces`-Liste (Legacy) auf
|
|
43
33
|
// App-Ebene hoch, damit alle Layouts mit der neuen Form arbeiten können
|
|
44
34
|
// ohne dass alte clientSchemas migriert werden müssen.
|
|
45
|
-
export function toAppSchema(input
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
export function toAppSchema(input) {
|
|
36
|
+
if ("features" in input)
|
|
37
|
+
return input;
|
|
38
|
+
// Old single-feature shape — wrap.
|
|
39
|
+
const { workspaces, ...feature } = input;
|
|
40
|
+
return {
|
|
41
|
+
features: [feature],
|
|
42
|
+
...(workspaces !== undefined && { workspaces }),
|
|
43
|
+
};
|
|
53
44
|
}
|
|
54
|
-
|
|
55
45
|
// TypeGuard — Caller die schon zur Laufzeit unterscheiden müssen
|
|
56
46
|
// (selten; meist reicht toAppSchema). Nicht via `"features" in x` inline
|
|
57
47
|
// machen — narrow'd TS dann auf den join-Typ statt die echte Differenz.
|
|
58
|
-
export function isAppSchema(input
|
|
59
|
-
|
|
48
|
+
export function isAppSchema(input) {
|
|
49
|
+
return "features" in input;
|
|
60
50
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { EntityDefinition, EntityEditScreenDefinition } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
export declare const REQUIRED_FIELD_I18N_KEY = "kumiko.validation.required";
|
|
4
|
+
export declare function buildFormSchema(entity: EntityDefinition, screen: EntityEditScreenDefinition): z.ZodType;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { evalFieldCondition, NO_WIDGET_FIELD_TYPES } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
2
|
+
import { I18N_KEY_PARAM } from "@cosmicdrift/kumiko-headless";
|
|
3
|
+
import * as z from "zod";
|
|
4
|
+
import { layoutEditFields } from "./layout-fields.js";
|
|
5
|
+
// `required` means "has a value", not "is truthy" — `false` and `0` count
|
|
6
|
+
// as present, only the actually-empty representations don't.
|
|
7
|
+
function isPresent(value) {
|
|
8
|
+
if (value === undefined || value === null || value === "")
|
|
9
|
+
return false;
|
|
10
|
+
if (Array.isArray(value) && value.length === 0)
|
|
11
|
+
return false;
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
function isEmbeddedListField(field) {
|
|
15
|
+
return field.type === "embedded" && field.multiple === true;
|
|
16
|
+
}
|
|
17
|
+
// Renders raw to the user without a de+en default in i18n-defaults.ts.
|
|
18
|
+
export const REQUIRED_FIELD_I18N_KEY = "kumiko.validation.required";
|
|
19
|
+
// Client-side presence validation for the auto-wired entityEdit path —
|
|
20
|
+
// checks that every rendered required field HAS a value, not that the
|
|
21
|
+
// value has the right shape. Format/range/type validation stays server-
|
|
22
|
+
// authoritative (buildInsertSchema/buildUpdateSchema): the form-state
|
|
23
|
+
// representation of a value can diverge from the server-payload shape (e.g.
|
|
24
|
+
// money is `{amount,currency}`, not a bare number), so a format check here
|
|
25
|
+
// would either reject valid values or need per-representation branches that
|
|
26
|
+
// rot the moment either side changes.
|
|
27
|
+
//
|
|
28
|
+
// One `superRefine` instead of a per-field shape: a field-level `.refine()`
|
|
29
|
+
// wouldn't run at all for a key that's simply absent from `values` —
|
|
30
|
+
// `superRefine` sees the whole object and catches that case too.
|
|
31
|
+
// `.passthrough()` is load-bearing: the default `z.object({})` STRIPS every
|
|
32
|
+
// key (there's no declared shape), so `superRefine` would see an empty
|
|
33
|
+
// object regardless of what was actually submitted — every required field
|
|
34
|
+
// would misreport as missing.
|
|
35
|
+
//
|
|
36
|
+
// Iterates the screen's layout field specs, not `entity.fields` — `required`
|
|
37
|
+
// and `readOnly` are per-spec, evaluated against the current values the
|
|
38
|
+
// same way `view-model/edit.ts` resolves them for the rendered form. Not
|
|
39
|
+
// checked here: `visible`. `runValidate` already filters issues on hidden
|
|
40
|
+
// fields via `computeFieldStates(options.fields, …)` (form-controller.ts:163,181),
|
|
41
|
+
// fed by `deriveFormFields(screen)` in render-edit.tsx.
|
|
42
|
+
export function buildFormSchema(entity, screen) {
|
|
43
|
+
const fields = layoutEditFields(screen);
|
|
44
|
+
return z
|
|
45
|
+
.object({})
|
|
46
|
+
.passthrough()
|
|
47
|
+
.superRefine((values, ctx) => {
|
|
48
|
+
// `.passthrough()` types `values` as a plain object but doesn't declare
|
|
49
|
+
// its keys — the runtime object always carries every form field.
|
|
50
|
+
// @cast-boundary form-values
|
|
51
|
+
const record = values;
|
|
52
|
+
for (const spec of fields) {
|
|
53
|
+
const field = entity.fields[spec.field];
|
|
54
|
+
if (!field)
|
|
55
|
+
continue;
|
|
56
|
+
// Not operable by the user — a presence error would be unresolvable,
|
|
57
|
+
// same reason as the NO_WIDGET_FIELD_TYPES check below.
|
|
58
|
+
if (spec.readOnly !== undefined && evalFieldCondition(spec.readOnly, record))
|
|
59
|
+
continue;
|
|
60
|
+
// Screen-spec `required` overrides the entity default, mirroring
|
|
61
|
+
// `view-model/edit.ts` — the rendered form is the reference, and a
|
|
62
|
+
// presence check stricter than the form blocks the user for nothing.
|
|
63
|
+
const entityRequired = "required" in field && field.required === true;
|
|
64
|
+
const isRequired = spec.required === undefined ? entityRequired : evalFieldCondition(spec.required, record);
|
|
65
|
+
if (!isRequired)
|
|
66
|
+
continue;
|
|
67
|
+
// Embedded LIST fields get their own EmbeddedListField grid widget
|
|
68
|
+
// (#1838) — they're fillable, so NO_WIDGET_FIELD_TYPES's "embedded"
|
|
69
|
+
// entry must not exempt them. A statically-`required: true` field
|
|
70
|
+
// with no bound widget is also caught at boot
|
|
71
|
+
// (validateNoWidgetRequiredField in boot-validator/screens.ts).
|
|
72
|
+
if (NO_WIDGET_FIELD_TYPES.includes(field.type) && !isEmbeddedListField(field))
|
|
73
|
+
continue;
|
|
74
|
+
if (isPresent(record[spec.field]))
|
|
75
|
+
continue;
|
|
76
|
+
ctx.addIssue({
|
|
77
|
+
code: "custom",
|
|
78
|
+
path: [spec.field],
|
|
79
|
+
message: `"${spec.field}" is required.`,
|
|
80
|
+
// I18N_KEY_PARAM override, see packages/headless/src/form/zod-bridge.ts.
|
|
81
|
+
params: { [I18N_KEY_PARAM]: REQUIRED_FIELD_I18N_KEY },
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ScreenDefinition } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
2
|
+
import type { ListRowViewModel, Translate } from "@cosmicdrift/kumiko-headless";
|
|
3
|
+
import { type ReactNode } from "react";
|
|
4
|
+
import { type ListSort } from "../hooks/use-list-url-state.js";
|
|
5
|
+
import type { FeatureSchema } from "./feature-schema.js";
|
|
6
|
+
import { qualifyScreenId } from "./qualify-screen-id.js";
|
|
7
|
+
import { screenAccessAllows } from "./screen-access.js";
|
|
8
|
+
export type KumikoScreenProps = {
|
|
9
|
+
readonly schema: FeatureSchema;
|
|
10
|
+
readonly qn: string;
|
|
11
|
+
readonly translate?: Translate;
|
|
12
|
+
readonly entityId?: string;
|
|
13
|
+
readonly onRowClick?: (row: ListRowViewModel, entityName: string) => void;
|
|
14
|
+
readonly onCopyLink?: () => Promise<void> | void;
|
|
15
|
+
};
|
|
16
|
+
export { qualifyScreenId };
|
|
17
|
+
/** Mirrors qualifyScreenId for nav QNs (registry form `<feature>:nav:<short-id>`).
|
|
18
|
+
* Callers building QNs (e.g. the WorkspaceShell resolver) should use this instead of string-concat, so a QN-schema change only touches one place. */
|
|
19
|
+
export declare function qualifyNavId(featureName: string, navId: string): string;
|
|
20
|
+
export { screenAccessAllows };
|
|
21
|
+
export declare function KumikoScreen({ schema, qn, translate, entityId, onRowClick, onCopyLink, }: KumikoScreenProps): ReactNode;
|
|
22
|
+
export declare function buildInitialValues(fields: Readonly<Record<string, unknown>>, defaultCurrency?: string, moneyCurrencyOverrides?: Readonly<Record<string, string>>): Readonly<Record<string, unknown>>;
|
|
23
|
+
export declare function literalCurrencyOverrides(fields: Readonly<Record<string, unknown>>): Readonly<Record<string, string>>;
|
|
24
|
+
export type InitialValueSources = {
|
|
25
|
+
readonly searchParams: Readonly<Record<string, string>>;
|
|
26
|
+
readonly urlPrefillFields: readonly string[] | undefined;
|
|
27
|
+
readonly renderableFields?: ReadonlySet<string>;
|
|
28
|
+
readonly defaultCurrency?: string;
|
|
29
|
+
readonly moneyCurrencyOverrides?: Readonly<Record<string, string>>;
|
|
30
|
+
readonly drawerOverrides?: Readonly<Record<string, unknown>>;
|
|
31
|
+
readonly handoffValues?: Readonly<Record<string, unknown>>;
|
|
32
|
+
};
|
|
33
|
+
export declare function mergeSearchParamsIntoInitial(fields: Readonly<Record<string, unknown>>, sources: InitialValueSources): Record<string, unknown>;
|
|
34
|
+
export declare function buildListQueryPayload(state: {
|
|
35
|
+
readonly limit: number;
|
|
36
|
+
readonly search: string;
|
|
37
|
+
readonly sort: ListSort | null;
|
|
38
|
+
readonly usePager: boolean;
|
|
39
|
+
readonly page: number;
|
|
40
|
+
readonly useInfinite: boolean;
|
|
41
|
+
readonly cursor: string | undefined;
|
|
42
|
+
}): Record<string, unknown>;
|
|
43
|
+
export type { ScreenDefinition };
|