@cosmicdrift/kumiko-renderer-web 0.269.2 → 0.270.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-web",
3
- "version": "0.269.2",
3
+ "version": "0.270.0",
4
4
  "description": "Web-platform bindings for @cosmicdrift/kumiko-renderer. HTML default-primitives, browser history-based navigation, EventSource-backed live events, and a one-call createKumikoApp that mounts the whole stack via react-dom.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -16,9 +16,9 @@
16
16
  "./styles.css": "./src/styles.css"
17
17
  },
18
18
  "dependencies": {
19
- "@cosmicdrift/kumiko-dispatcher-live": "0.269.2",
20
- "@cosmicdrift/kumiko-headless": "0.269.2",
21
- "@cosmicdrift/kumiko-renderer": "0.269.2",
19
+ "@cosmicdrift/kumiko-dispatcher-live": "0.270.0",
20
+ "@cosmicdrift/kumiko-headless": "0.270.0",
21
+ "@cosmicdrift/kumiko-renderer": "0.270.0",
22
22
  "@radix-ui/react-dialog": "^1.1.15",
23
23
  "@radix-ui/react-dropdown-menu": "^2.1.16",
24
24
  "@radix-ui/react-label": "^2.1.8",
@@ -66,7 +66,7 @@
66
66
  "@types/react-dom": "^19.2.3",
67
67
  "jsdom": "^29.1.1",
68
68
  "tailwindcss": "^4.3.0",
69
- "@cosmicdrift/kumiko-locale-de": "0.269.2"
69
+ "@cosmicdrift/kumiko-locale-de": "0.270.0"
70
70
  },
71
71
  "repository": {
72
72
  "type": "git",
@@ -183,7 +183,12 @@ describe("createKumikoApp", () => {
183
183
  const openFeature: FeatureSchema = {
184
184
  featureName: "tasks",
185
185
  entities: { task: taskEntity },
186
- screens: [{ ...listScreen, access: { openToAll: true } }],
186
+ screens: [
187
+ {
188
+ ...listScreen,
189
+ access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
190
+ },
191
+ ],
187
192
  navs: [{ id: "task-list", label: "tasks:nav.task-list", screen: "tasks:screen:task-list" }],
188
193
  };
189
194
  const schema: AppSchema = { features: [restrictedFeature, openFeature] };
@@ -282,7 +287,7 @@ describe("createKumikoApp", () => {
282
287
  id: "privacy-center",
283
288
  type: "custom",
284
289
  renderer: { react: { __component: "PrivacyCenterScreen" } },
285
- access: { openToAll: true },
290
+ access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
286
291
  dormant: true,
287
292
  },
288
293
  ],
@@ -539,7 +539,7 @@ const sessionsSchema: FeatureSchema = {
539
539
  type: "projectionList",
540
540
  query: "sessions:query:user-session:mine",
541
541
  columns: [{ field: "userAgent", label: "sessions.mine.col.userAgent" }],
542
- access: { openToAll: true },
542
+ access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
543
543
  },
544
544
  {
545
545
  id: "session-list",
@@ -563,7 +563,7 @@ const mfaSchema: FeatureSchema = {
563
563
  layout: { sections: [] },
564
564
  submitLabel: "mfa.enable.start",
565
565
  reveal: { fields: [{ field: "recoveryCodes", label: "codes", display: "list" }] },
566
- access: { openToAll: true },
566
+ access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
567
567
  },
568
568
  {
569
569
  id: "auth-mfa-disable",
@@ -572,7 +572,7 @@ const mfaSchema: FeatureSchema = {
572
572
  fields: { code: { type: "text", required: true } },
573
573
  layout: { sections: [{ fields: ["code"] }] },
574
574
  submitLabel: "mfa.disable.submit",
575
- access: { openToAll: true },
575
+ access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
576
576
  },
577
577
  ],
578
578
  };
@@ -74,7 +74,7 @@ function ws(
74
74
  } = {},
75
75
  ): WorkspaceSchema {
76
76
  const access = options.openToAll
77
- ? ({ openToAll: true } as const)
77
+ ? ({ openToAll: { reason: "test handler callable by any signed-in test user" } } as const)
78
78
  : options.roles !== undefined
79
79
  ? ({ roles: options.roles } as const)
80
80
  : undefined;
@@ -121,9 +121,18 @@ describe("filterByAccess", () => {
121
121
 
122
122
  test("sorts by order then insertion order", () => {
123
123
  const list = [
124
- ws("c", { openToAll: true, order: 3 }),
125
- ws("a", { openToAll: true, order: 1 }),
126
- ws("b", { openToAll: true, order: 2 }),
124
+ ws("c", {
125
+ openToAll: true,
126
+ order: 3,
127
+ }),
128
+ ws("a", {
129
+ openToAll: true,
130
+ order: 1,
131
+ }),
132
+ ws("b", {
133
+ openToAll: true,
134
+ order: 2,
135
+ }),
127
136
  ws("d", { openToAll: true }), // no order — sorts last
128
137
  ];
129
138
  expect(filterByAccess(list, []).map((w) => w.definition.id)).toEqual(["a", "b", "c", "d"]);
@@ -133,7 +142,10 @@ describe("filterByAccess", () => {
133
142
  describe("resolveDefaultId", () => {
134
143
  const visible = [
135
144
  ws("admin", { openToAll: true }),
136
- ws("dispatch", { openToAll: true, isDefault: true }),
145
+ ws("dispatch", {
146
+ openToAll: true,
147
+ isDefault: true,
148
+ }),
137
149
  ws("driver", { openToAll: true }),
138
150
  ];
139
151
 
@@ -234,8 +246,14 @@ describe("WorkspaceSwitcher", () => {
234
246
  renderWithSidebar(
235
247
  <WorkspaceSwitcher
236
248
  workspaces={[
237
- ws("admin", { label: "Admin", openToAll: true }),
238
- ws("driver", { label: "Driver", openToAll: true }),
249
+ ws("admin", {
250
+ label: "Admin",
251
+ openToAll: true,
252
+ }),
253
+ ws("driver", {
254
+ label: "Driver",
255
+ openToAll: true,
256
+ }),
239
257
  ]}
240
258
  activeId="admin"
241
259
  onSelect={() => {}}
@@ -253,8 +271,14 @@ describe("WorkspaceSwitcher", () => {
253
271
  renderWithSidebar(
254
272
  <WorkspaceSwitcher
255
273
  workspaces={[
256
- ws("admin", { label: "Admin", openToAll: true }),
257
- ws("driver", { label: "Driver", openToAll: true }),
274
+ ws("admin", {
275
+ label: "Admin",
276
+ openToAll: true,
277
+ }),
278
+ ws("driver", {
279
+ label: "Driver",
280
+ openToAll: true,
281
+ }),
258
282
  ]}
259
283
  activeId="admin"
260
284
  onSelect={onSelect}
@@ -31,7 +31,12 @@ describe("firstOpenScreenQn", () => {
31
31
  const features: readonly FeatureSchema[] = [
32
32
  feature({
33
33
  featureName: "auth-mfa",
34
- screens: [customScreen({ id: "auth-mfa-enable", access: { openToAll: true } })],
34
+ screens: [
35
+ customScreen({
36
+ id: "auth-mfa-enable",
37
+ access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
38
+ }),
39
+ ],
35
40
  // No nav entry — this is auth-mfa's dormant custom-screen convention.
36
41
  }),
37
42
  feature({
@@ -58,7 +63,12 @@ describe("firstOpenScreenQn", () => {
58
63
  const features: readonly FeatureSchema[] = [
59
64
  feature({
60
65
  featureName: "auth-mfa",
61
- screens: [customScreen({ id: "auth-mfa-enable", access: { openToAll: true } })],
66
+ screens: [
67
+ customScreen({
68
+ id: "auth-mfa-enable",
69
+ access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
70
+ }),
71
+ ],
62
72
  }),
63
73
  ];
64
74
  expect(firstOpenScreenQn(features)).toBeUndefined();
@@ -1,5 +1,6 @@
1
1
  import { createLiveDispatcher } from "@cosmicdrift/kumiko-dispatcher-live";
2
2
  import type { TreeChildrenSubscribe } from "@cosmicdrift/kumiko-framework/engine";
3
+ import { isOpenToAllGranted } from "@cosmicdrift/kumiko-framework/ui-types";
3
4
  import type {
4
5
  Dispatcher,
5
6
  ListRowViewModel,
@@ -236,7 +237,7 @@ export function firstOpenScreenQn(features: readonly FeatureSchema[]): string |
236
237
  for (const feature of features) {
237
238
  const openScreen = feature.screens.find(
238
239
  (s) =>
239
- (s.access === undefined || "openToAll" in s.access) &&
240
+ (s.access === undefined || isOpenToAllGranted(s.access)) &&
240
241
  navScreenQns.has(qualifyScreenId(feature.featureName, s.id)),
241
242
  );
242
243
  if (openScreen !== undefined) return qualifyScreenId(feature.featureName, openScreen.id);