@cosmicdrift/kumiko-headless 0.190.0 → 0.192.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-headless",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.192.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,7 +36,7 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
39
|
+
"@cosmicdrift/kumiko-framework": "0.192.0",
|
|
40
40
|
"temporal-polyfill": "^0.3.2",
|
|
41
41
|
"zod": "^4.4.3"
|
|
42
42
|
},
|
|
@@ -549,4 +549,48 @@ describe("computeEditViewModel — embedded-list cells (#1835)", () => {
|
|
|
549
549
|
const field = asFields(vm.sections[0]).fields[0];
|
|
550
550
|
expect(field?.embeddedListCurrency).toBeUndefined();
|
|
551
551
|
});
|
|
552
|
+
|
|
553
|
+
test("imageVariant is the FIRST variant declared on the field def", () => {
|
|
554
|
+
const entity = {
|
|
555
|
+
fields: {
|
|
556
|
+
avatar: {
|
|
557
|
+
type: "image",
|
|
558
|
+
variants: {
|
|
559
|
+
profile: { fit: "cover", size: { width: 512, height: 512 }, format: "webp" },
|
|
560
|
+
big: { fit: "cover", size: { width: 1024, height: 1024 }, format: "webp" },
|
|
561
|
+
},
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
} as unknown as EntityDefinition;
|
|
565
|
+
|
|
566
|
+
const vm = computeEditViewModel({
|
|
567
|
+
screen: editScreen({ sections: [{ title: "x", fields: ["avatar"] }] }),
|
|
568
|
+
entity,
|
|
569
|
+
values: {},
|
|
570
|
+
translate,
|
|
571
|
+
featureName: "orders",
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
const field = asFields(vm.sections[0]).fields[0];
|
|
575
|
+
expect(field?.imageVariant).toBe("profile");
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
test("imageVariant is undefined for an image field without variants", () => {
|
|
579
|
+
const entity = {
|
|
580
|
+
fields: {
|
|
581
|
+
avatar: { type: "image" },
|
|
582
|
+
},
|
|
583
|
+
} as unknown as EntityDefinition;
|
|
584
|
+
|
|
585
|
+
const vm = computeEditViewModel({
|
|
586
|
+
screen: editScreen({ sections: [{ title: "x", fields: ["avatar"] }] }),
|
|
587
|
+
entity,
|
|
588
|
+
values: {},
|
|
589
|
+
translate,
|
|
590
|
+
featureName: "orders",
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
const field = asFields(vm.sections[0]).fields[0];
|
|
594
|
+
expect(field?.imageVariant).toBeUndefined();
|
|
595
|
+
});
|
|
552
596
|
});
|
package/src/view-model/edit.ts
CHANGED
|
@@ -170,8 +170,14 @@ export function computeEditViewModel<
|
|
|
170
170
|
// importing it just for one fallback string.
|
|
171
171
|
const resolvedCurrency = entity.defaultCurrency ?? "EUR";
|
|
172
172
|
const fileDef = isFileType
|
|
173
|
-
? (fieldDef as unknown as {
|
|
173
|
+
? (fieldDef as unknown as {
|
|
174
|
+
accept?: readonly string[];
|
|
175
|
+
maxSize?: string;
|
|
176
|
+
variants?: Readonly<Record<string, unknown>>;
|
|
177
|
+
})
|
|
174
178
|
: undefined;
|
|
179
|
+
const imageVariant =
|
|
180
|
+
fieldDef.type === "image" ? Object.keys(fileDef?.variants ?? {})[0] : undefined;
|
|
175
181
|
// Embedded-LIST field (`multiple: true`) — per-cell metadata for a
|
|
176
182
|
// renderer to draw one row per array item (invoice-positions-style
|
|
177
183
|
// table). A plain (non-list) embedded field emits none of this; the
|
|
@@ -261,6 +267,7 @@ export function computeEditViewModel<
|
|
|
261
267
|
...(fileDef?.accept !== undefined && { accept: fileDef.accept }),
|
|
262
268
|
...(fileDef?.maxSize !== undefined && { maxSize: fileDef.maxSize }),
|
|
263
269
|
...(isFileType && { entityType: screen.entity, fieldName: normalized.field }),
|
|
270
|
+
...(imageVariant !== undefined && { imageVariant }),
|
|
264
271
|
...(normalized.icon !== undefined && { icon: normalized.icon }),
|
|
265
272
|
...(embeddedListCells !== undefined && { embeddedListCells }),
|
|
266
273
|
...(embeddedListDef?.minItems !== undefined && {
|
package/src/view-model/types.ts
CHANGED
|
@@ -181,6 +181,13 @@ export type EditFieldViewModel = {
|
|
|
181
181
|
* die richtige Field-Def prüfen kann. */
|
|
182
182
|
readonly entityType?: string;
|
|
183
183
|
readonly fieldName?: string;
|
|
184
|
+
/** Only for `type: "image"` — the variant name the preview requests
|
|
185
|
+
* (`/api/files/:id/variant/:name`) instead of the original. The FIRST
|
|
186
|
+
* variant declared on the field def wins; a spec may legitimately carry
|
|
187
|
+
* neither `size` nor `maxEdge` (format-/blur-only), so "the smallest one"
|
|
188
|
+
* is not a rule that always has an answer. Absent when the field declares
|
|
189
|
+
* no variants — the preview then loads the original. */
|
|
190
|
+
readonly imageVariant?: string;
|
|
184
191
|
/** Prefix-icon key from `EditFieldSpec.icon`, passed through unchanged
|
|
185
192
|
* (no i18n — it's a symbolic key, not a display string). The renderer
|
|
186
193
|
* resolves it against the FIELD_ICONS registry; unknown keys silently
|