@cosmicdrift/kumiko-renderer 0.367.0 → 0.368.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.
@@ -93,8 +93,7 @@ export function KumikoScreen({ schema, qn, translate, entityId, onRowClick, onCo
93
93
  return _jsx(ReturnHostProvider, { value: ownHost, children: body });
94
94
  }
95
95
  function ScreenVisibilityGate({ featureName, visibleWhen, fallback, translate, children, }) {
96
- const { Banner, PageHeader } = usePrimitives();
97
- const pageHeaderSlotAvailable = usePageHeaderSlotAvailable();
96
+ const { Banner } = usePrimitives();
98
97
  const result = useQuery(visibleWhen.query, {}, { live: true });
99
98
  const wasShown = useRef(false);
100
99
  const verdict = evalVisibleWhenAfterShown(visibleWhen, result, wasShown.current);
@@ -107,9 +106,19 @@ function ScreenVisibilityGate({ featureName, visibleWhen, fallback, translate, c
107
106
  if (verdict === "loading") {
108
107
  return (_jsx(Banner, { padded: true, variant: "loading", testId: "kumiko-screen-loading", children: "Loading\u2026" }));
109
108
  }
110
- // The route still names the locked screen; its breadcrumb must not label what stands in for it.
111
- const hideLockedBreadcrumb = PageHeader !== undefined && pageHeaderSlotAvailable ? _jsx(PageHeader, { hideBreadcrumb: true }) : null;
112
- return (_jsxs(_Fragment, { children: [hideLockedBreadcrumb, fallback !== undefined ? (_jsx(FallbackScreen, { featureName: featureName, fallback: fallback, translate: translate })) : (_jsx(ScreenUnavailableBanner, {}))] }));
109
+ if (fallback !== undefined) {
110
+ return _jsx(FallbackScreen, { featureName: featureName, fallback: fallback, translate: translate });
111
+ }
112
+ return (_jsxs(_Fragment, { children: [_jsx(LockedScreenHeader, {}), _jsx(ScreenUnavailableBanner, {})] }));
113
+ }
114
+ // The route still names the locked screen; its breadcrumb must not label what stands in for it.
115
+ // With a stand-in the header is labelled with that screen instead, none if it has no title.
116
+ function LockedScreenHeader({ standInScreenId }) {
117
+ const { PageHeader } = usePrimitives();
118
+ const pageHeaderSlotAvailable = usePageHeaderSlotAvailable();
119
+ if (PageHeader === undefined || !pageHeaderSlotAvailable)
120
+ return null;
121
+ return standInScreenId !== undefined ? (_jsx(PageHeader, { hideBreadcrumb: true, breadcrumbScreenId: standInScreenId })) : (_jsx(PageHeader, { hideBreadcrumb: true }));
113
122
  }
114
123
  function ScreenMissingHomeButton({ homeScreenId, testId, }) {
115
124
  const { Button } = usePrimitives();
@@ -144,9 +153,10 @@ function FallbackScreen({ featureName, fallback, translate, }) {
144
153
  const target = useEmbeddedScreen(featureName, fallback);
145
154
  // Also undefined when the user lacks access to the fallback screen, which is
146
155
  // not a framework error.
147
- if (target === undefined)
148
- return _jsx(ScreenUnavailableBanner, {});
149
- return _jsx(KumikoScreen, { schema: target.schema, qn: target.qn, translate: translate });
156
+ if (target === undefined) {
157
+ return (_jsxs(_Fragment, { children: [_jsx(LockedScreenHeader, {}), _jsx(ScreenUnavailableBanner, {})] }));
158
+ }
159
+ return (_jsxs(_Fragment, { children: [_jsx(LockedScreenHeader, { standInScreenId: lastSegment(target.qn) }), _jsx(KumikoScreen, { schema: target.schema, qn: target.qn, translate: translate })] }));
150
160
  }
151
161
  function renderScreenBody({ schema, screen, translate, entityId, onRowClick, onCopyLink, }) {
152
162
  switch (screen.type) {
@@ -1353,6 +1353,9 @@ export type PageHeaderProps = {
1353
1353
  /** Hide the shell header's breadcrumb while mounted, for a screen that stands in
1354
1354
  * for the one the route names (a locked screen's fallback). */
1355
1355
  readonly hideBreadcrumb?: boolean;
1356
+ /** Label the breadcrumb with this screen (id as in the route) instead of the one
1357
+ * the route names, for a locked screen's fallback. Wins over `hideBreadcrumb`. */
1358
+ readonly breadcrumbScreenId?: string;
1356
1359
  };
1357
1360
  /** One item in an `ActionOverflowMenu` (A7: header/row actions beyond the
1358
1361
  * primary one collapse into this menu instead of a wall of buttons). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-renderer",
3
- "version": "0.367.0",
3
+ "version": "0.368.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.367.0",
19
- "@cosmicdrift/kumiko-headless": "0.367.0",
20
- "@cosmicdrift/kumiko-types": "0.367.0",
18
+ "@cosmicdrift/kumiko-framework": "0.368.0",
19
+ "@cosmicdrift/kumiko-headless": "0.368.0",
20
+ "@cosmicdrift/kumiko-types": "0.368.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.367.0"
31
+ "@cosmicdrift/kumiko-locale-de": "0.368.0"
32
32
  },
33
33
  "repository": {
34
34
  "type": "git",
package/src/changes.json CHANGED
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.368.0",
4
+ "type": "fix",
5
+ "title": "A screen that falls back via visibleWhen shows the fallback's title",
6
+ "detail": "When visibleWhen locks a screen and its fallback renders instead, the header no longer stays empty. It shows the title of the fallback screen (resolved like any other screen title, from its nav label), never the locked screen's. A fallback without a title still leaves the header empty. PageHeader takes a new breadcrumbScreenId prop for this."
7
+ },
2
8
  {
3
9
  "version": "0.367.0",
4
10
  "type": "fix",