@cosmicdrift/kumiko-renderer 0.223.0 → 0.224.1
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.
|
|
3
|
+
"version": "0.224.1",
|
|
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.
|
|
19
|
-
"@cosmicdrift/kumiko-headless": "0.
|
|
18
|
+
"@cosmicdrift/kumiko-framework": "0.224.1",
|
|
19
|
+
"@cosmicdrift/kumiko-headless": "0.224.1",
|
|
20
20
|
"react": "^19.2.6",
|
|
21
21
|
"temporal-polyfill": "^0.3.2",
|
|
22
22
|
"zod": "^4.4.3"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@testing-library/react": "^16.3.2",
|
|
26
26
|
"@types/react": "^19.2.14",
|
|
27
27
|
"jsdom": "^29.1.1",
|
|
28
|
-
"@cosmicdrift/kumiko-locale-de": "0.
|
|
28
|
+
"@cosmicdrift/kumiko-locale-de": "0.224.1"
|
|
29
29
|
},
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
} from "./projection-detail-shim";
|
|
52
52
|
import { synthesizeProjectionEntity, synthesizeProjectionScreen } from "./projection-list-shim";
|
|
53
53
|
import { lastSegment, toKebab } from "./qn";
|
|
54
|
-
import { qualifyScreenId } from "./qualify-screen-id";
|
|
54
|
+
import { featureNameFromQualifiedScreenId, qualifyScreenId } from "./qualify-screen-id";
|
|
55
55
|
import { screenAccessAllows } from "./screen-access";
|
|
56
56
|
import { dispatcherErrorText, WriteFailedError } from "./write-failed-error";
|
|
57
57
|
|
|
@@ -2264,6 +2264,7 @@ function ActionFormBody({
|
|
|
2264
2264
|
readonly onCancelOverride?: () => void;
|
|
2265
2265
|
}): ReactNode {
|
|
2266
2266
|
const nav = useNav();
|
|
2267
|
+
const appFeatures = useAppFeatures();
|
|
2267
2268
|
const synthEntity = useMemo(() => synthesizeActionFormEntity(screen.fields), [screen.fields]);
|
|
2268
2269
|
const synthScreen = useMemo(() => synthesizeActionFormScreen(screen), [screen]);
|
|
2269
2270
|
const initial = useMemo(
|
|
@@ -2287,7 +2288,25 @@ function ActionFormBody({
|
|
|
2287
2288
|
// "back to list" (typisch bei Create-style Aktionen).
|
|
2288
2289
|
if (screen.redirect !== undefined) {
|
|
2289
2290
|
const targetId = lastSegment(screen.redirect);
|
|
2290
|
-
const
|
|
2291
|
+
const targetFeatureName = featureNameFromQualifiedScreenId(screen.redirect);
|
|
2292
|
+
// A qualified redirect target may live in a different feature than
|
|
2293
|
+
// this screen's own schema (fw#2485) — resolve over all mounted
|
|
2294
|
+
// features (own schema first, cheap and provider-independent) same
|
|
2295
|
+
// as ProjectionDetailBody's cross-feature editScreen lookup above.
|
|
2296
|
+
// A screen id is only unique WITHIN a feature, so once the QN names
|
|
2297
|
+
// a feature, the fallback must look inside THAT feature, not just
|
|
2298
|
+
// take the first short-id match across every mounted feature — two
|
|
2299
|
+
// features can easily share an id like "list" or "edit".
|
|
2300
|
+
const target =
|
|
2301
|
+
schema.screens.find((s) => lastSegment(s.id) === targetId) ??
|
|
2302
|
+
(targetFeatureName !== undefined
|
|
2303
|
+
? appFeatures
|
|
2304
|
+
.find((f) => f.featureName === targetFeatureName)
|
|
2305
|
+
?.screens.find((s) => lastSegment(s.id) === targetId)
|
|
2306
|
+
: // Bare short-id redirect (no feature prefix) names no feature to
|
|
2307
|
+
// pick by — fall back to the pre-fw#2485 best-effort match by
|
|
2308
|
+
// short id across all mounted features.
|
|
2309
|
+
appFeatures.flatMap((f) => f.screens).find((s) => lastSegment(s.id) === targetId));
|
|
2291
2310
|
const entityId = extractCreatedId(result.data);
|
|
2292
2311
|
const carriesId =
|
|
2293
2312
|
target !== undefined &&
|
|
@@ -2298,7 +2317,7 @@ function ActionFormBody({
|
|
|
2298
2317
|
});
|
|
2299
2318
|
}
|
|
2300
2319
|
},
|
|
2301
|
-
[nav, screen.redirect, onSuccess, schema.screens],
|
|
2320
|
+
[nav, screen.redirect, onSuccess, schema.screens, appFeatures],
|
|
2302
2321
|
);
|
|
2303
2322
|
// Cancel ist nur sinnvoll wenn ein Navigations-Ziel existiert —
|
|
2304
2323
|
// sonst hätte der Button nirgendwo hin zu navigieren. cancelTarget
|
|
@@ -4,3 +4,12 @@
|
|
|
4
4
|
export function qualifyScreenId(featureName: string, screenId: string): string {
|
|
5
5
|
return `${featureName}:screen:${screenId}`;
|
|
6
6
|
}
|
|
7
|
+
|
|
8
|
+
// Inverse of qualifyScreenId. A short id ("task-list") has no feature
|
|
9
|
+
// segment and returns undefined — callers need that to tell "this redirect
|
|
10
|
+
// names a feature" apart from "this redirect is feature-less, resolve by
|
|
11
|
+
// short id alone" (fw#2485).
|
|
12
|
+
export function featureNameFromQualifiedScreenId(id: string): string | undefined {
|
|
13
|
+
const parts = id.split(":");
|
|
14
|
+
return parts.length === 3 && parts[1] === "screen" ? parts[0] : undefined;
|
|
15
|
+
}
|