@cosmicdrift/kumiko-renderer 0.258.1 → 0.259.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-renderer",
3
- "version": "0.258.1",
3
+ "version": "0.259.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,8 +15,8 @@
15
15
  }
16
16
  },
17
17
  "dependencies": {
18
- "@cosmicdrift/kumiko-framework": "0.258.1",
19
- "@cosmicdrift/kumiko-headless": "0.258.1",
18
+ "@cosmicdrift/kumiko-framework": "0.259.0",
19
+ "@cosmicdrift/kumiko-headless": "0.259.0",
20
20
  "react": "^19.2.6",
21
21
  "temporal-polyfill": "^0.3.2",
22
22
  "zod": "^4.4.3"
@@ -27,7 +27,7 @@
27
27
  "@types/react-dom": "^19.2.3",
28
28
  "jsdom": "^29.1.1",
29
29
  "react-dom": "^19.2.6",
30
- "@cosmicdrift/kumiko-locale-de": "0.258.1"
30
+ "@cosmicdrift/kumiko-locale-de": "0.259.0"
31
31
  },
32
32
  "repository": {
33
33
  "type": "git",
@@ -8,6 +8,7 @@ import type { Translate } from "@cosmicdrift/kumiko-headless";
8
8
  import { type ComponentType, createContext, type ReactNode, useContext } from "react";
9
9
 
10
10
  export type DashboardBodyProps = {
11
+ readonly featureName: string;
11
12
  readonly screen: DashboardScreenDefinition;
12
13
  readonly translate?: Translate;
13
14
  };
@@ -209,7 +209,13 @@ export function KumikoScreen({
209
209
  />
210
210
  );
211
211
  case "dashboard":
212
- return <DashboardScreenBody screen={screen} translate={translate} />;
212
+ return (
213
+ <DashboardScreenBody
214
+ featureName={schema.featureName}
215
+ screen={screen}
216
+ translate={translate}
217
+ />
218
+ );
213
219
  case "actionForm":
214
220
  return <ActionFormBody schema={schema} screen={screen} translate={translate} />;
215
221
  case "secretMint":
@@ -227,9 +233,11 @@ export function KumikoScreen({
227
233
  // Charts) ist plattform-spezifisch und kommt aus dem DashboardBody-Context
228
234
  // (renderer-web registriert die Web-Variante in createKumikoApp).
229
235
  function DashboardScreenBody({
236
+ featureName,
230
237
  screen,
231
238
  translate,
232
239
  }: {
240
+ readonly featureName: string;
233
241
  readonly screen: DashboardScreenDefinition;
234
242
  readonly translate?: Translate;
235
243
  }): ReactNode {
@@ -243,7 +251,13 @@ function DashboardScreenBody({
243
251
  </Banner>
244
252
  );
245
253
  }
246
- return <Body screen={screen} {...(translate !== undefined && { translate })} />;
254
+ return (
255
+ <Body
256
+ featureName={featureName}
257
+ screen={screen}
258
+ {...(translate !== undefined && { translate })}
259
+ />
260
+ );
247
261
  }
248
262
 
249
263
  // Lookup-Body für custom-screens: schaut die Component aus dem
@@ -0,0 +1,27 @@
1
+ import { useUserRoles } from "../context/user-roles-context";
2
+ import { useAppFeatures } from "./app-features-context";
3
+ import type { FeatureSchema } from "./feature-schema";
4
+ import { featureNameFromQualifiedScreenId, qualifyScreenId } from "./qualify-screen-id";
5
+ import { screenAccessAllows } from "./screen-access";
6
+
7
+ export type EmbeddedScreenTarget = {
8
+ readonly schema: FeatureSchema;
9
+ readonly qn: string;
10
+ };
11
+
12
+ // Undefined (not KumikoScreen's access-denied banner) so the host can drop the whole tile.
13
+ export function useEmbeddedScreen(
14
+ hostFeatureName: string,
15
+ screen: string,
16
+ ): EmbeddedScreenTarget | undefined {
17
+ const features = useAppFeatures();
18
+ const userRoles = useUserRoles();
19
+ const crossFeatureName = featureNameFromQualifiedScreenId(screen);
20
+ const targetFeatureName = crossFeatureName ?? hostFeatureName;
21
+ const qn = crossFeatureName !== undefined ? screen : qualifyScreenId(hostFeatureName, screen);
22
+ const schema = features.find((f) => f.featureName === targetFeatureName);
23
+ const target = schema?.screens.find((s) => qualifyScreenId(targetFeatureName, s.id) === qn);
24
+ if (schema === undefined || target === undefined) return undefined;
25
+ if (!screenAccessAllows(target.access, userRoles)) return undefined;
26
+ return { schema, qn };
27
+ }
package/src/index.ts CHANGED
@@ -81,6 +81,8 @@ export {
81
81
  useNav,
82
82
  } from "./app/nav";
83
83
  export { lastSegment } from "./app/qn";
84
+ export type { EmbeddedScreenTarget } from "./app/use-embedded-screen";
85
+ export { useEmbeddedScreen } from "./app/use-embedded-screen";
84
86
  export type { VariableChipsProps } from "./app/variable-chips";
85
87
  export { VariableChips } from "./app/variable-chips";
86
88
  export { dispatcherErrorText, WriteFailedError } from "./app/write-failed-error";