@cosmicdrift/kumiko-headless 0.170.0 → 0.171.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.170.0",
3
+ "version": "0.171.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.170.0",
39
+ "@cosmicdrift/kumiko-framework": "0.171.0",
40
40
  "temporal-polyfill": "^0.3.2",
41
41
  "zod": "^4.4.3"
42
42
  },
@@ -287,6 +287,42 @@ describe("computeEditViewModel", () => {
287
287
  });
288
288
  expect(asFields(vm.sections[0]).fields[0]?.span).toBe(2);
289
289
  });
290
+
291
+ test("section.description is translated and passed through; absent stays undefined", () => {
292
+ const vm = computeEditViewModel({
293
+ screen: editScreen({
294
+ sections: [
295
+ {
296
+ title: "Basics",
297
+ description: "orders:screen:order-edit.basics.help",
298
+ fields: ["notes"],
299
+ },
300
+ { title: "Extra", fields: ["kind"] },
301
+ ],
302
+ }),
303
+ entity: orderEntity,
304
+ values: {},
305
+ translate,
306
+ featureName: "orders",
307
+ });
308
+ expect(asFields(vm.sections[0]).description).toBe("orders:screen:order-edit.basics.help");
309
+ expect(asFields(vm.sections[1]).description).toBeUndefined();
310
+ });
311
+
312
+ test("field.icon propagates to the view model; absent stays undefined", () => {
313
+ const vm = computeEditViewModel({
314
+ screen: editScreen({
315
+ sections: [{ title: "x", fields: [{ field: "customerName", icon: "user" }, "notes"] }],
316
+ }),
317
+ entity: orderEntity,
318
+ values: {},
319
+ translate,
320
+ featureName: "orders",
321
+ });
322
+ const fields = asFields(vm.sections[0]).fields;
323
+ expect(fields[0]?.icon).toBe("user");
324
+ expect(fields[1]?.icon).toBeUndefined();
325
+ });
290
326
  });
291
327
 
292
328
  describe("computeEditViewModel — date/timestamp min/max/locale (#369)", () => {
@@ -151,6 +151,7 @@ export function computeEditViewModel<
151
151
  ...(fileDef?.accept !== undefined && { accept: fileDef.accept }),
152
152
  ...(fileDef?.maxSize !== undefined && { maxSize: fileDef.maxSize }),
153
153
  ...(isFileType && { entityType: screen.entity, fieldName: normalized.field }),
154
+ ...(normalized.icon !== undefined && { icon: normalized.icon }),
154
155
  };
155
156
  return view;
156
157
  });
@@ -162,6 +163,9 @@ export function computeEditViewModel<
162
163
  visible,
163
164
  // Titellose Section (flache Form) → kein h3; nur übersetzen wenn gesetzt.
164
165
  ...(sectionSpec.title !== undefined && { title: translate(sectionSpec.title) }),
166
+ ...(sectionSpec.description !== undefined && {
167
+ description: translate(sectionSpec.description),
168
+ }),
165
169
  columns: sectionSpec.columns ?? 1,
166
170
  fields,
167
171
  };
@@ -143,6 +143,11 @@ export type EditFieldViewModel = {
143
143
  * die richtige Field-Def prüfen kann. */
144
144
  readonly entityType?: string;
145
145
  readonly fieldName?: string;
146
+ /** Prefix-icon key from `EditFieldSpec.icon`, passed through unchanged
147
+ * (no i18n — it's a symbolic key, not a display string). The renderer
148
+ * resolves it against the FIELD_ICONS registry; unknown keys silently
149
+ * fall back to "no icon". */
150
+ readonly icon?: string;
146
151
  };
147
152
 
148
153
  // Discriminated by `kind` — mirrors EditSectionSpec on the engine side.
@@ -158,6 +163,9 @@ export type EditFieldsSectionViewModel = {
158
163
  readonly visible: boolean;
159
164
  /** Optional — eine titellose Section rendert nur ihre Felder (flache Form). */
160
165
  readonly title?: string;
166
+ /** Translated help text under the block heading, from
167
+ * `EditFieldsSection.description`. Renders even without `title`. */
168
+ readonly description?: string;
161
169
  readonly columns: number;
162
170
  readonly fields: readonly EditFieldViewModel[];
163
171
  };