@cosmicdrift/kumiko-headless 0.358.0 → 0.360.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/view-model/edit.d.ts +2 -0
- package/dist/view-model/edit.js +27 -17
- package/dist/view-model/types.d.ts +6 -1
- package/package.json +3 -3
- package/src/changes.json +6 -0
|
@@ -10,6 +10,8 @@ export type ComputeEditViewModelInput<TValues extends Readonly<Record<string, un
|
|
|
10
10
|
* for that verb (create hides them, update shows them read-only); omitted
|
|
11
11
|
* means no exclusion applies. */
|
|
12
12
|
readonly mode?: EditFormMode;
|
|
13
|
+
/** The record being edited; omitted on create. */
|
|
14
|
+
readonly entityId?: string;
|
|
13
15
|
};
|
|
14
16
|
export type EditFormMode = "create" | "update";
|
|
15
17
|
export declare function computeRelatedListSectionViewModel(sectionSpec: EditRelatedListSection, translate: Translate): EditRelatedListSectionViewModel;
|
package/dist/view-model/edit.js
CHANGED
|
@@ -220,23 +220,33 @@ function deriveReferenceMultiHints(fieldDef, declaredRefTarget) {
|
|
|
220
220
|
...(refMultiple !== undefined && { refMultiple }),
|
|
221
221
|
};
|
|
222
222
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const capture = fieldDef.type === "image" ? fileDef?.capture : undefined;
|
|
223
|
+
function isFileFieldType(fieldDef) {
|
|
224
|
+
return (fieldDef.type === "file" ||
|
|
225
|
+
fieldDef.type === "image" ||
|
|
226
|
+
fieldDef.type === "files" ||
|
|
227
|
+
fieldDef.type === "images");
|
|
228
|
+
}
|
|
229
|
+
function deriveImageHints(fieldDef, fileDef) {
|
|
230
|
+
if (fieldDef.type !== "image" && fieldDef.type !== "images")
|
|
231
|
+
return {};
|
|
232
|
+
const imageVariant = Object.keys(fileDef.variants ?? {})[0];
|
|
234
233
|
return {
|
|
235
|
-
...(fileDef?.accept !== undefined && { accept: fileDef.accept }),
|
|
236
|
-
...(fileDef?.maxSize !== undefined && { maxSize: fileDef.maxSize }),
|
|
237
|
-
...(isFileType && { entityType: entityName, fieldName }),
|
|
238
234
|
...(imageVariant !== undefined && { imageVariant }),
|
|
239
|
-
...(capture !== undefined && { capture }),
|
|
235
|
+
...(fileDef.capture !== undefined && { capture: fileDef.capture }),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function deriveFileFieldHints(fieldDef, entityName, fieldName, entityId) {
|
|
239
|
+
if (!isFileFieldType(fieldDef))
|
|
240
|
+
return {};
|
|
241
|
+
const fileDef = fieldDef;
|
|
242
|
+
return {
|
|
243
|
+
...(fileDef.accept !== undefined && { accept: fileDef.accept }),
|
|
244
|
+
...(fileDef.maxSize !== undefined && { maxSize: fileDef.maxSize }),
|
|
245
|
+
...(fileDef.maxCount !== undefined && { maxCount: fileDef.maxCount }),
|
|
246
|
+
entityType: entityName,
|
|
247
|
+
fieldName,
|
|
248
|
+
...(entityId !== undefined && { entityId }),
|
|
249
|
+
...deriveImageHints(fieldDef, fileDef),
|
|
240
250
|
};
|
|
241
251
|
}
|
|
242
252
|
// Embedded-LIST field (`multiple: true`) — per-cell metadata for a renderer
|
|
@@ -316,7 +326,7 @@ function buildExtensionSectionViewModel(sectionSpec, translate) {
|
|
|
316
326
|
// section/field tree the renderer draws. FieldConditions are evaluated here
|
|
317
327
|
// so the renderer never re-runs them during React render.
|
|
318
328
|
export function computeEditViewModel(input) {
|
|
319
|
-
const { screen, entity, values, translate, featureName, mode } = input;
|
|
329
|
+
const { screen, entity, values, translate, featureName, mode, entityId } = input;
|
|
320
330
|
const excludedFields = new Set(mode === undefined ? [] : screen.writeExcludedFields?.[mode]);
|
|
321
331
|
const isHiddenByExclusion = (fieldSpec) => mode === "create" && excludedFields.has(normalizeEditField(fieldSpec).field);
|
|
322
332
|
const sections = screen.layout.sections.map((sectionSpec) => {
|
|
@@ -378,7 +388,7 @@ export function computeEditViewModel(input) {
|
|
|
378
388
|
const dateHints = deriveDateFieldHints(fieldDef);
|
|
379
389
|
const numericHints = deriveNumericFieldHints(fieldDef, resolvedCurrency);
|
|
380
390
|
const referenceHints = deriveReferenceFieldHints(fieldDef, normalized, declaredRefTarget, featureName);
|
|
381
|
-
const fileHints = deriveFileFieldHints(fieldDef, screen.entity, normalized.field);
|
|
391
|
+
const fileHints = deriveFileFieldHints(fieldDef, screen.entity, normalized.field, entityId);
|
|
382
392
|
const embeddedListHints = deriveEmbeddedListHints(fieldDef, translate, featureName, screen.entity, normalized.field, resolvedCurrency);
|
|
383
393
|
const view = {
|
|
384
394
|
field: normalized.field,
|
|
@@ -171,12 +171,17 @@ export type EditFieldViewModel = {
|
|
|
171
171
|
* Upload-Endpoint gegen die Field-Def. */
|
|
172
172
|
readonly accept?: readonly string[];
|
|
173
173
|
readonly maxSize?: string;
|
|
174
|
+
/** Only for `type: "files" | "images"` — upper bound on list length. */
|
|
175
|
+
readonly maxCount?: number;
|
|
174
176
|
/** Nur bei `type: "file" | "image"` — Entity-Name + Field-Name für den
|
|
175
177
|
* Upload-POST (`/api/files`), damit der Endpoint maxSize/accept gegen
|
|
176
178
|
* die richtige Field-Def prüfen kann. */
|
|
177
179
|
readonly entityType?: string;
|
|
178
180
|
readonly fieldName?: string;
|
|
179
|
-
/**
|
|
181
|
+
/** Record being edited (update mode only). Sent with the upload so the
|
|
182
|
+
* FileRef is attached to the record. */
|
|
183
|
+
readonly entityId?: string;
|
|
184
|
+
/** Only for `type: "image"` and `"images"` — the variant name the preview requests
|
|
180
185
|
* (`/api/files/:id/variant/:name`) instead of the original. The FIRST
|
|
181
186
|
* variant declared on the field def wins; a spec may legitimately carry
|
|
182
187
|
* neither `size` nor `maxEdge` (format-/blur-only), so "the smallest one"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-headless",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.360.0",
|
|
4
4
|
"description": "Headless UI logic for Kumiko — Dispatcher contract, Form-Controller, View-Model, Nav-Resolver. Plattform- und React-frei; jeder Renderer (renderer, renderer-web, renderer-native, …) komponiert darauf.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
40
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
39
|
+
"@cosmicdrift/kumiko-framework": "0.360.0",
|
|
40
|
+
"@cosmicdrift/kumiko-types": "0.360.0",
|
|
41
41
|
"temporal-polyfill": "^0.3.2",
|
|
42
42
|
"zod": "^4.4.3"
|
|
43
43
|
},
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.360.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "Edit view model carries entityId and maxCount for file fields",
|
|
6
|
+
"detail": "ComputeEditViewModelInput has an optional entityId (the record being edited, omitted on create). EditFieldViewModel gains entityId for file, image, files and images fields and maxCount for files and images. The file-field hints now also cover type files, which was missing."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.357.0",
|
|
4
10
|
"type": "improvement",
|