@cosmicdrift/kumiko-headless 0.222.0 → 0.223.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.223.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.223.0",
|
|
40
40
|
"temporal-polyfill": "^0.3.2",
|
|
41
41
|
"zod": "^4.4.3"
|
|
42
42
|
},
|
|
@@ -632,3 +632,47 @@ describe("computeEditViewModel — embedded-list cells (#1835)", () => {
|
|
|
632
632
|
expect(field?.capture).toBeUndefined();
|
|
633
633
|
});
|
|
634
634
|
});
|
|
635
|
+
|
|
636
|
+
describe("computeEditViewModel — multiSelect display/columns/maxRows passthrough", () => {
|
|
637
|
+
function multiSelectEntity(overrides?: Record<string, unknown>): EntityDefinition {
|
|
638
|
+
return {
|
|
639
|
+
fields: {
|
|
640
|
+
languages: {
|
|
641
|
+
type: "multiSelect",
|
|
642
|
+
options: ["en", "de", "es"],
|
|
643
|
+
...overrides,
|
|
644
|
+
},
|
|
645
|
+
},
|
|
646
|
+
} as unknown as EntityDefinition;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
test("display/columns/maxRows carry through when set on the field def", () => {
|
|
650
|
+
const vm = computeEditViewModel({
|
|
651
|
+
screen: editScreen({ sections: [{ title: "x", fields: ["languages"] }] }),
|
|
652
|
+
entity: multiSelectEntity({ display: "checkboxes", columns: 2, maxRows: 3 }),
|
|
653
|
+
values: {},
|
|
654
|
+
translate,
|
|
655
|
+
featureName: "orders",
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
const field = asFields(vm.sections[0]).fields[0];
|
|
659
|
+
expect(field?.display).toBe("checkboxes");
|
|
660
|
+
expect(field?.columns).toBe(2);
|
|
661
|
+
expect(field?.maxRows).toBe(3);
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
test("display/columns/maxRows are absent when not set on the field def (back-compat)", () => {
|
|
665
|
+
const vm = computeEditViewModel({
|
|
666
|
+
screen: editScreen({ sections: [{ title: "x", fields: ["languages"] }] }),
|
|
667
|
+
entity: multiSelectEntity(),
|
|
668
|
+
values: {},
|
|
669
|
+
translate,
|
|
670
|
+
featureName: "orders",
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
const field = asFields(vm.sections[0]).fields[0];
|
|
674
|
+
expect(field?.display).toBeUndefined();
|
|
675
|
+
expect(field?.columns).toBeUndefined();
|
|
676
|
+
expect(field?.maxRows).toBeUndefined();
|
|
677
|
+
});
|
|
678
|
+
});
|
package/src/view-model/edit.ts
CHANGED
|
@@ -128,6 +128,11 @@ export function computeEditViewModel<
|
|
|
128
128
|
options,
|
|
129
129
|
)
|
|
130
130
|
: undefined;
|
|
131
|
+
// Checkbox-grid rendering hints for `type: "multiSelect"` — pass
|
|
132
|
+
// through unchanged so the renderer can pick the grid layout.
|
|
133
|
+
const display = fieldDef.type === "multiSelect" ? fieldDef.display : undefined;
|
|
134
|
+
const columns = fieldDef.type === "multiSelect" ? fieldDef.columns : undefined;
|
|
135
|
+
const maxRows = fieldDef.type === "multiSelect" ? fieldDef.maxRows : undefined;
|
|
131
136
|
// Multiline hint for `type: "text"` — the renderer then switches to a
|
|
132
137
|
// textarea. `type: "longText"` always renders a textarea regardless
|
|
133
138
|
// of this hint; it's only carried through as an optional `{ rows }`
|
|
@@ -275,6 +280,9 @@ export function computeEditViewModel<
|
|
|
275
280
|
...(normalized.renderer !== undefined && { renderer: normalized.renderer }),
|
|
276
281
|
...(options !== undefined && { options }),
|
|
277
282
|
...(optionLabels !== undefined && { optionLabels }),
|
|
283
|
+
...(display !== undefined && { display }),
|
|
284
|
+
...(columns !== undefined && { columns }),
|
|
285
|
+
...(maxRows !== undefined && { maxRows }),
|
|
278
286
|
...(multiline !== undefined && { multiline }),
|
|
279
287
|
...(wallClock !== undefined && { wallClock }),
|
|
280
288
|
...(min !== undefined && { min }),
|
package/src/view-model/types.ts
CHANGED
|
@@ -140,6 +140,18 @@ export type EditFieldViewModel = {
|
|
|
140
140
|
* raw value. Convention key:
|
|
141
141
|
* `<feature>:entity:<entity>:field:<field>:option:<value>`. */
|
|
142
142
|
readonly optionLabels?: Readonly<Record<string, string>>;
|
|
143
|
+
/** Set for `type: "multiSelect"` when MultiSelectFieldDef.display is
|
|
144
|
+
* "checkboxes" — the renderer shows a checkbox grid with a select-all
|
|
145
|
+
* toggle instead of the default combobox dropdown. */
|
|
146
|
+
readonly display?: "checkboxes" | "dropdown";
|
|
147
|
+
/** Set for `type: "multiSelect"` when MultiSelectFieldDef.columns is
|
|
148
|
+
* defined — column count for the checkbox grid at the widest breakpoint.
|
|
149
|
+
* Ignored unless `display` is "checkboxes". */
|
|
150
|
+
readonly columns?: 1 | 2 | 3 | 4;
|
|
151
|
+
/** Set for `type: "multiSelect"` when MultiSelectFieldDef.maxRows is
|
|
152
|
+
* defined — grid rows visible before the checkbox grid becomes
|
|
153
|
+
* scrollable. Ignored unless `display` is "checkboxes". */
|
|
154
|
+
readonly maxRows?: number;
|
|
143
155
|
/** For `type: "text"`, set when TextFieldDef.multiline is true — the
|
|
144
156
|
* renderer then renders a textarea instead of a single-line input.
|
|
145
157
|
* `type: "longText"` always renders a textarea regardless of this
|