@cosmicdrift/kumiko-renderer 0.361.0 → 0.362.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.
@@ -9,19 +9,19 @@ export function primaryHeaderAction(actions, preferredId) {
9
9
  actions.find((a) => a.style === "primary") ??
10
10
  actions[0]);
11
11
  }
12
- // A bare icon for a destructive or confirm-gated action (e.g. "x" for
13
- // terminate) reads as "close", so only plain icon actions may stand alone.
12
+ // The undeclared fallback picks an action nobody chose for the header, so a
13
+ // destructive or confirm-gated one (a bare "x" reads as "close") may not stand alone.
14
14
  function canStandAsIconButton(action) {
15
15
  return action?.icon !== undefined && action.style !== "danger" && !needsActionConfirm(action);
16
16
  }
17
- // A declared, visible `primaryAction` is always the phone header's button
18
- // (labelled when a bare icon would mislead), so it matches the desktop header
19
- // and `edit` moves into the menu. Without one the pencil-style icon action
20
- // stays visible, falling back to the precedence-only primary.
17
+ // A declared, visible `primaryAction` is always the phone header's button, icon
18
+ // only when it has an icon (the author chose the icon, the label is its aria-label),
19
+ // so it matches the desktop header and `edit` moves into the menu. Without one the
20
+ // pencil-style icon action stays visible, falling back to the precedence-only primary.
21
21
  export function compactHeaderPrimary(actions, preferredId) {
22
22
  const declared = preferredId !== undefined ? actions.find((a) => a.id === preferredId) : undefined;
23
23
  if (declared !== undefined)
24
- return { action: declared, iconOnly: canStandAsIconButton(declared) };
24
+ return { action: declared, iconOnly: declared.icon !== undefined };
25
25
  const iconAction = primaryHeaderAction(actions);
26
26
  return canStandAsIconButton(iconAction) ? { action: iconAction, iconOnly: true } : undefined;
27
27
  }
@@ -254,6 +254,11 @@ export function buildInitialValues(fields, defaultCurrency, moneyCurrencyOverrid
254
254
  out[name] = shape.default;
255
255
  continue;
256
256
  }
257
+ // An untouched optional number must not persist as a deliberate 0.
258
+ if (shape.type === "number" && shape.required !== true) {
259
+ out[name] = undefined;
260
+ continue;
261
+ }
257
262
  if (shape.type === "embedded" && shape.multiple === true) {
258
263
  out[name] = [];
259
264
  continue;
@@ -1161,7 +1166,8 @@ function EntityListScreen({ schema, screen, translate, onRowClick, }) {
1161
1166
  function EntityListBody({ schema, screen, entity, translate, onRowClick, }) {
1162
1167
  const isEmbeddedScreen = useIsEmbeddedScreen();
1163
1168
  const featureName = schema.featureName;
1164
- const onCreate = useNavigateToCreateFor(schema, screen.entity, screen.createScreen, screen.createUnavailable);
1169
+ const resolvedCreate = useNavigateToCreateFor(schema, screen.entity, screen.createScreen, screen.createUnavailable);
1170
+ const onCreate = screen.allowCreate === false ? undefined : resolvedCreate;
1165
1171
  const { Banner } = usePrimitives();
1166
1172
  const queryType = entityQueryCommand(featureName, screen.entity, "list");
1167
1173
  const nav = useNav();
@@ -2559,8 +2565,9 @@ function mapFailedConfigCommandIssuesToField(error, failedIndex, commandFieldNam
2559
2565
  },
2560
2566
  };
2561
2567
  }
2562
- // A number/money field without a declared default starts empty: buildInitialValues
2563
- // maps it to 0, which a save would persist as a deliberate "0" override.
2568
+ // A money field without a declared default starts empty too (buildInitialValues
2569
+ // maps it to 0, which a save would persist as a deliberate "0" override); numbers
2570
+ // are handled there, except a required one, which config fields never are.
2564
2571
  function buildConfigEditDefaults(fields) {
2565
2572
  const defaults = buildInitialValues(fields); // @cast-boundary render-helper
2566
2573
  for (const [shortName, fieldDef] of Object.entries(fields)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-renderer",
3
- "version": "0.361.0",
3
+ "version": "0.362.0",
4
4
  "description": "Platform-agnostic React renderer for Kumiko screens. Contains the shared logic — primitives-contract, hooks, KumikoScreen, navigation & SSE abstractions — that any platform-specific renderer (web, native) composes. No DOM, no EventSource, no react-dom.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -15,9 +15,9 @@
15
15
  }
16
16
  },
17
17
  "dependencies": {
18
- "@cosmicdrift/kumiko-framework": "0.361.0",
19
- "@cosmicdrift/kumiko-headless": "0.361.0",
20
- "@cosmicdrift/kumiko-types": "0.361.0",
18
+ "@cosmicdrift/kumiko-framework": "0.362.0",
19
+ "@cosmicdrift/kumiko-headless": "0.362.0",
20
+ "@cosmicdrift/kumiko-types": "0.362.0",
21
21
  "react": "^19.2.6",
22
22
  "temporal-polyfill": "^0.3.2",
23
23
  "zod": "^4.4.3"
@@ -28,7 +28,7 @@
28
28
  "@types/react-dom": "^19.2.3",
29
29
  "jsdom": "^29.1.1",
30
30
  "react-dom": "^19.2.6",
31
- "@cosmicdrift/kumiko-locale-de": "0.361.0"
31
+ "@cosmicdrift/kumiko-locale-de": "0.362.0"
32
32
  },
33
33
  "repository": {
34
34
  "type": "git",
package/src/changes.json CHANGED
@@ -1,4 +1,16 @@
1
1
  [
2
+ {
3
+ "version": "0.362.0",
4
+ "type": "improvement",
5
+ "title": "entityList honours allowCreate false",
6
+ "detail": "EntityListBody passes no onCreate when the list sets allowCreate false."
7
+ },
8
+ {
9
+ "version": "0.362.0",
10
+ "type": "fix",
11
+ "title": "A declared primaryAction with an icon is icon-only in the phone header",
12
+ "detail": "Regardless of confirm or style; the label is the button's aria-label and title. Without an icon it stays a text button. The ui-walkthrough terminate sample uses the circle-stop icon, since a bare x reads as close."
13
+ },
2
14
  {
3
15
  "version": "0.361.0",
4
16
  "type": "improvement",