@ankhorage/studio 0.15.0 → 0.16.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.
Files changed (58) hide show
  1. package/README.md +1 -1
  2. package/dist/contractGuards.d.ts.map +1 -1
  3. package/dist/contractGuards.js +4 -2
  4. package/dist/contractGuards.js.map +1 -1
  5. package/dist/core/StudioProvider.d.ts.map +1 -1
  6. package/dist/core/StudioProvider.js +87 -10
  7. package/dist/core/StudioProvider.js.map +1 -1
  8. package/dist/host/layout/auth/resolveAuthLayoutPlan.js +2 -2
  9. package/dist/host/layout/auth/resolveAuthLayoutPlan.js.map +1 -1
  10. package/dist/host/layout/layoutGenerator.js +3 -3
  11. package/dist/host/layout/layoutGenerator.js.map +1 -1
  12. package/dist/host/layout/templates/navigation.js +4 -10
  13. package/dist/host/layout/templates/navigation.js.map +1 -1
  14. package/dist/host/layout/templates/rootLayout.d.ts.map +1 -1
  15. package/dist/host/layout/templates/rootLayout.js +11 -7
  16. package/dist/host/layout/templates/rootLayout.js.map +1 -1
  17. package/dist/host/orchestrator/templates.d.ts.map +1 -1
  18. package/dist/host/orchestrator/templates.js +1 -11
  19. package/dist/host/orchestrator/templates.js.map +1 -1
  20. package/dist/host/templateRegistry/index.d.ts.map +1 -1
  21. package/dist/host/templateRegistry/index.js +2 -17
  22. package/dist/host/templateRegistry/index.js.map +1 -1
  23. package/dist/index.d.ts +6 -5
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/manifestNavigatorPreviewModel.js +1 -1
  27. package/dist/manifestNavigatorPreviewModel.js.map +1 -1
  28. package/dist/manifestState.d.ts +59 -2
  29. package/dist/manifestState.d.ts.map +1 -1
  30. package/dist/manifestState.js +336 -51
  31. package/dist/manifestState.js.map +1 -1
  32. package/dist/routeUtils.d.ts +1 -2
  33. package/dist/routeUtils.d.ts.map +1 -1
  34. package/dist/routeUtils.js +6 -44
  35. package/dist/routeUtils.js.map +1 -1
  36. package/dist/studioAdminRouteModel.d.ts +7 -1
  37. package/dist/studioAdminRouteModel.d.ts.map +1 -1
  38. package/dist/studioAdminRouteModel.js +54 -0
  39. package/dist/studioAdminRouteModel.js.map +1 -1
  40. package/dist/ui/admin/AnkhAdminPage.d.ts.map +1 -1
  41. package/dist/ui/admin/AnkhAdminPage.js +5 -1
  42. package/dist/ui/admin/AnkhAdminPage.js.map +1 -1
  43. package/dist/ui/admin/AnkhAdminShell.d.ts.map +1 -1
  44. package/dist/ui/admin/AnkhAdminShell.js +5 -2
  45. package/dist/ui/admin/AnkhAdminShell.js.map +1 -1
  46. package/dist/ui/admin/pages/ScreenDetailAdminPage.d.ts +6 -0
  47. package/dist/ui/admin/pages/ScreenDetailAdminPage.d.ts.map +1 -0
  48. package/dist/ui/admin/pages/ScreenDetailAdminPage.js +86 -0
  49. package/dist/ui/admin/pages/ScreenDetailAdminPage.js.map +1 -0
  50. package/dist/ui/admin/pages/ScreensAdminPage.d.ts +3 -0
  51. package/dist/ui/admin/pages/ScreensAdminPage.d.ts.map +1 -0
  52. package/dist/ui/admin/pages/ScreensAdminPage.js +99 -0
  53. package/dist/ui/admin/pages/ScreensAdminPage.js.map +1 -0
  54. package/dist/ui/admin/pages/screens/screensAdminActions.d.ts +28 -0
  55. package/dist/ui/admin/pages/screens/screensAdminActions.d.ts.map +1 -0
  56. package/dist/ui/admin/pages/screens/screensAdminActions.js +22 -0
  57. package/dist/ui/admin/pages/screens/screensAdminActions.js.map +1 -0
  58. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"manifestState.d.ts","sourceRoot":"","sources":["../src/manifestState.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifestState.d.ts","sourceRoot":"","sources":["../src/manifestState.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { NAVIGATOR_TYPES } from '@ankhorage/contracts';
1
2
  import { insertNodeAtPlacement, moveNodeToPlacement } from './index';
2
3
  export const DEFAULT_STUDIO_SCREEN_TEMPLATE = {
3
4
  id: 'tpl-screen-empty',
@@ -104,6 +105,215 @@ export function groupScreenRouteEntries(entries) {
104
105
  }
105
106
  return Array.from(groups.values());
106
107
  }
108
+ /**
109
+ * Verifies the Studio manifest invariant that route registry keys and stable
110
+ * ScreenSpec identities are the same unique value.
111
+ */
112
+ export function hasCanonicalStudioScreenRegistryIdentity(screens) {
113
+ const screenIds = new Set();
114
+ for (const [registryKey, screen] of Object.entries(screens)) {
115
+ if (registryKey !== screen.id || screenIds.has(screen.id))
116
+ return false;
117
+ screenIds.add(screen.id);
118
+ }
119
+ return true;
120
+ }
121
+ function resolveCanonicalStudioScreen(manifest, screenId) {
122
+ if (!hasCanonicalStudioScreenRegistryIdentity(manifest.screens))
123
+ return undefined;
124
+ return manifest.screens[screenId];
125
+ }
126
+ /**
127
+ * Derives the complete package-neutral screen/navigation authoring model from
128
+ * the manifest without flattening its navigator tree.
129
+ */
130
+ export function deriveStudioScreenNavigationModel(manifest) {
131
+ const primaryNavigatorPath = getPrimaryNavigatorPath(manifest.navigator.routes);
132
+ const primaryNavigator = findNavigatorAtPath(manifest.navigator, primaryNavigatorPath) ?? manifest.navigator;
133
+ const diagnostics = [];
134
+ const referencesByRegistryKey = new Map();
135
+ collectNavigationModelReferences({
136
+ navigator: manifest.navigator,
137
+ screens: manifest.screens,
138
+ primaryNavigatorPath,
139
+ parentPath: [],
140
+ routePathPrefix: [],
141
+ runtimePathPrefix: [],
142
+ diagnostics,
143
+ referencesByRegistryKey,
144
+ });
145
+ const screenIdCounts = new Map();
146
+ for (const screen of Object.values(manifest.screens)) {
147
+ screenIdCounts.set(screen.id, (screenIdCounts.get(screen.id) ?? 0) + 1);
148
+ }
149
+ const reportedDuplicateScreenIds = new Set();
150
+ const screens = Object.entries(manifest.screens).map(([registryKey, screen]) => {
151
+ const screenId = screen.id;
152
+ const routeReferences = referencesByRegistryKey.get(registryKey) ?? [];
153
+ if (registryKey !== screenId) {
154
+ diagnostics.push({
155
+ code: 'screen-registry-key-mismatch',
156
+ message: `Screen registry key "${registryKey}" does not match stable ScreenSpec.id "${screenId}".`,
157
+ parentPath: [],
158
+ screenId,
159
+ });
160
+ }
161
+ if ((screenIdCounts.get(screenId) ?? 0) > 1 && !reportedDuplicateScreenIds.has(screenId)) {
162
+ reportedDuplicateScreenIds.add(screenId);
163
+ diagnostics.push({
164
+ code: 'duplicate-screen-id',
165
+ message: `Stable ScreenSpec.id "${screenId}" is used by multiple screen registry entries.`,
166
+ parentPath: [],
167
+ screenId,
168
+ });
169
+ }
170
+ if (routeReferences.length > 1) {
171
+ diagnostics.push({
172
+ code: 'ambiguous-screen-route-reference',
173
+ message: `Screen "${screenId}" is referenced by ${routeReferences.length} routes.`,
174
+ parentPath: [],
175
+ screenId,
176
+ });
177
+ }
178
+ return { screenId, screen, routeReferences };
179
+ });
180
+ return {
181
+ primaryNavigatorPath,
182
+ primaryNavigator,
183
+ screens,
184
+ diagnostics,
185
+ };
186
+ }
187
+ /**
188
+ * Returns a concrete canonical app pathname only when a screen has one route
189
+ * reference and that route does not require runtime parameters.
190
+ */
191
+ export function resolveStudioScreenAppPath(model, screenId) {
192
+ const matchingEntries = model.screens.filter((candidate) => candidate.screenId === screenId);
193
+ if (matchingEntries.length !== 1)
194
+ return null;
195
+ const [entry] = matchingEntries;
196
+ if (!entry)
197
+ return null;
198
+ if (entry.routeReferences.length !== 1)
199
+ return null;
200
+ const [reference] = entry.routeReferences;
201
+ if (!reference)
202
+ return null;
203
+ const hasDynamicSegment = reference.pathnamePattern
204
+ .split('/')
205
+ .some((segment) => segment.startsWith(':') || /^\[.*\]$/u.test(segment));
206
+ if (hasDynamicSegment)
207
+ return null;
208
+ const matchingReferences = model.screens.flatMap((candidate) => candidate.routeReferences.filter((candidateReference) => candidateReference.pathnamePattern === reference.pathnamePattern));
209
+ return matchingReferences.length === 1 ? reference.pathnamePattern : null;
210
+ }
211
+ function collectNavigationModelReferences(args) {
212
+ const { navigator, screens, primaryNavigatorPath, parentPath, routePathPrefix, runtimePathPrefix, diagnostics, referencesByRegistryKey, } = args;
213
+ const siblingNameCounts = new Map();
214
+ for (const route of navigator.routes) {
215
+ siblingNameCounts.set(route.name, (siblingNameCounts.get(route.name) ?? 0) + 1);
216
+ }
217
+ if (navigator.routes.length === 0) {
218
+ diagnostics.push({
219
+ code: 'empty-navigator',
220
+ message: `Navigator at "${formatParentPath(parentPath)}" has no routes.`,
221
+ parentPath,
222
+ });
223
+ }
224
+ if (navigator.initialRouteName !== undefined &&
225
+ siblingNameCounts.get(navigator.initialRouteName) !== 1) {
226
+ diagnostics.push({
227
+ code: 'invalid-initial-route',
228
+ message: `Initial route "${navigator.initialRouteName}" is not one unambiguous direct route of "${formatParentPath(parentPath)}".`,
229
+ parentPath,
230
+ routeName: navigator.initialRouteName,
231
+ });
232
+ }
233
+ for (const [siblingIndex, route] of navigator.routes.entries()) {
234
+ const routePath = [...routePathPrefix, route.name];
235
+ const runtimePath = appendRuntimeRoutePath(runtimePathPrefix, route);
236
+ const isPrimaryNavigatorMember = pathsEqual(parentPath, primaryNavigatorPath);
237
+ if ((siblingNameCounts.get(route.name) ?? 0) > 1 &&
238
+ navigator.routes.findIndex((candidate) => candidate.name === route.name) === siblingIndex) {
239
+ diagnostics.push({
240
+ code: 'duplicate-sibling-route-name',
241
+ message: `Route name "${route.name}" is duplicated under "${formatParentPath(parentPath)}".`,
242
+ parentPath,
243
+ routeName: route.name,
244
+ screenId: route.screenId,
245
+ });
246
+ }
247
+ if (!route.screenId && !route.navigator) {
248
+ diagnostics.push({
249
+ code: 'missing-route-target',
250
+ message: `Route "${route.name}" has neither a screen nor a nested navigator.`,
251
+ parentPath,
252
+ routeName: route.name,
253
+ });
254
+ }
255
+ else if (route.screenId && route.navigator) {
256
+ diagnostics.push({
257
+ code: 'ambiguous-route-target',
258
+ message: `Route "${route.name}" targets both a screen and a nested navigator.`,
259
+ parentPath,
260
+ routeName: route.name,
261
+ screenId: route.screenId,
262
+ });
263
+ }
264
+ if (route.screenId) {
265
+ if (!screens[route.screenId]) {
266
+ diagnostics.push({
267
+ code: 'missing-screen-reference',
268
+ message: `Route "${route.name}" references missing screen "${route.screenId}".`,
269
+ parentPath,
270
+ routeName: route.name,
271
+ screenId: route.screenId,
272
+ });
273
+ }
274
+ else {
275
+ const reference = {
276
+ route,
277
+ parentPath,
278
+ routePath,
279
+ pathnamePattern: toCanonicalRoutePattern(runtimePath),
280
+ siblingIndex,
281
+ navigatorType: navigator.type,
282
+ isPrimaryNavigatorMember,
283
+ showInPrimaryNavigation: route.showInPrimaryNavigation !== false,
284
+ isPrimaryInitialRoute: isPrimaryNavigatorMember && navigator.initialRouteName === route.name,
285
+ };
286
+ const currentReferences = referencesByRegistryKey.get(route.screenId) ?? [];
287
+ currentReferences.push(reference);
288
+ referencesByRegistryKey.set(route.screenId, currentReferences);
289
+ }
290
+ }
291
+ if (route.navigator) {
292
+ collectNavigationModelReferences({
293
+ navigator: route.navigator,
294
+ screens,
295
+ primaryNavigatorPath,
296
+ parentPath: routePath,
297
+ routePathPrefix: routePath,
298
+ runtimePathPrefix: runtimePath,
299
+ diagnostics,
300
+ referencesByRegistryKey,
301
+ });
302
+ }
303
+ }
304
+ }
305
+ function appendRuntimeRoutePath(runtimePathPrefix, route) {
306
+ const explicitPath = route.path?.trim();
307
+ const segmentPath = explicitPath ?? route.name;
308
+ const segments = segmentPath.split('/').filter(Boolean);
309
+ return explicitPath?.startsWith('/') ? segments : [...runtimePathPrefix, ...segments];
310
+ }
311
+ function pathsEqual(first, second) {
312
+ return first.length === second.length && first.every((value, index) => value === second[index]);
313
+ }
314
+ function formatParentPath(parentPath) {
315
+ return parentPath.length === 0 ? '<root>' : parentPath.join('/');
316
+ }
107
317
  export function listScreenIdsInRouteOrder(routes) {
108
318
  return collectScreenRouteEntries(routes).map((entry) => entry.screenId);
109
319
  }
@@ -113,6 +323,8 @@ export function listScreenIdsInRouteOrder(routes) {
113
323
  * back to the first route that reaches an available screen.
114
324
  */
115
325
  export function resolveInitialScreenId(navigator, screens) {
326
+ if (screens && !hasCanonicalStudioScreenRegistryIdentity(screens))
327
+ return null;
116
328
  const initialRoute = navigator.initialRouteName
117
329
  ? navigator.routes.find((route) => route.name === navigator.initialRouteName)
118
330
  : undefined;
@@ -126,22 +338,22 @@ export function resolveInitialScreenId(navigator, screens) {
126
338
  return nestedScreenId;
127
339
  }
128
340
  if (route.screenId && (!screens || screens[route.screenId])) {
129
- return route.screenId;
341
+ return screens ? (screens[route.screenId]?.id ?? null) : route.screenId;
130
342
  }
131
343
  }
132
344
  return null;
133
345
  }
134
346
  export function resolveInitialActiveScreenId(manifest) {
135
- if (!manifest)
347
+ if (!manifest || !hasCanonicalStudioScreenRegistryIdentity(manifest.screens))
136
348
  return null;
137
349
  const firstRoutedScreenId = resolveInitialScreenId(manifest.navigator, manifest.screens);
138
- const [firstScreenId] = Object.keys(manifest.screens);
350
+ const [firstScreenId] = Object.values(manifest.screens).map((screen) => screen.id);
139
351
  return firstRoutedScreenId ?? firstScreenId ?? null;
140
352
  }
141
353
  export function resolveActiveRootNode(manifest, activeScreenId) {
142
354
  if (!manifest || !activeScreenId)
143
355
  return null;
144
- return manifest.screens[activeScreenId]?.root ?? null;
356
+ return resolveCanonicalStudioScreen(manifest, activeScreenId)?.root ?? null;
145
357
  }
146
358
  export function findNodeInManifest(root, id) {
147
359
  if (root.id === id)
@@ -159,9 +371,11 @@ export function resolveSafeSelectedNodeId(rootNode, selectedNodeId) {
159
371
  return findNodeInManifest(rootNode, selectedNodeId) ? selectedNodeId : null;
160
372
  }
161
373
  export function findScreenIdForNode(manifest, nodeId) {
162
- for (const [screenId, screen] of Object.entries(manifest.screens)) {
374
+ if (!hasCanonicalStudioScreenRegistryIdentity(manifest.screens))
375
+ return null;
376
+ for (const screen of Object.values(manifest.screens)) {
163
377
  if (findNodeInManifest(screen.root, nodeId)) {
164
- return screenId;
378
+ return screen.id;
165
379
  }
166
380
  }
167
381
  return null;
@@ -169,7 +383,7 @@ export function findScreenIdForNode(manifest, nodeId) {
169
383
  export function updateStudioManifestNode(manifest, activeScreenId, nodeId, newProps) {
170
384
  if (!activeScreenId)
171
385
  return manifest;
172
- const screen = manifest.screens[activeScreenId];
386
+ const screen = resolveCanonicalStudioScreen(manifest, activeScreenId);
173
387
  if (!screen)
174
388
  return manifest;
175
389
  const newRoot = updateNodeInManifestTree(screen.root, nodeId, newProps);
@@ -189,7 +403,7 @@ export function updateStudioManifestNode(manifest, activeScreenId, nodeId, newPr
189
403
  export function deleteStudioManifestNode(manifest, activeScreenId, nodeId) {
190
404
  if (!activeScreenId)
191
405
  return manifest;
192
- const screen = manifest.screens[activeScreenId];
406
+ const screen = resolveCanonicalStudioScreen(manifest, activeScreenId);
193
407
  if (!screen || screen.root.id === nodeId)
194
408
  return manifest;
195
409
  const deletedNode = findNodeInManifest(screen.root, nodeId);
@@ -216,7 +430,7 @@ export function insertStudioManifestNodeAtPlacement(args) {
216
430
  const { manifest, activeScreenId, placement, newNode, componentMeta } = args;
217
431
  if (!activeScreenId)
218
432
  return null;
219
- const screen = manifest.screens[activeScreenId];
433
+ const screen = resolveCanonicalStudioScreen(manifest, activeScreenId);
220
434
  if (!screen)
221
435
  return null;
222
436
  const insertion = insertNodeAtPlacement({
@@ -245,7 +459,7 @@ export function moveStudioManifestNodeToPlacement(args) {
245
459
  const { manifest, activeScreenId, nodeId, placement, componentMeta } = args;
246
460
  if (!activeScreenId)
247
461
  return null;
248
- const screen = manifest.screens[activeScreenId];
462
+ const screen = resolveCanonicalStudioScreen(manifest, activeScreenId);
249
463
  if (!screen)
250
464
  return null;
251
465
  const movement = moveNodeToPlacement({
@@ -420,7 +634,10 @@ export function findRoutesAtParentPath(routes, parentPath) {
420
634
  const [segment, ...rest] = parentPath;
421
635
  if (!segment)
422
636
  return null;
423
- const route = routes.find((item) => item.name === segment);
637
+ const matches = routes.filter((item) => item.name === segment);
638
+ if (matches.length !== 1)
639
+ return null;
640
+ const [route] = matches;
424
641
  if (!route?.navigator?.routes)
425
642
  return null;
426
643
  return findRoutesAtParentPath(route.navigator.routes, rest);
@@ -429,8 +646,12 @@ export function insertRouteAtParentPath(routes, parentPath, newRoute) {
429
646
  if (parentPath.length === 0)
430
647
  return [...routes, newRoute];
431
648
  const [segment, ...rest] = parentPath;
649
+ const matches = routes.filter((route) => route.name === segment && route.navigator);
650
+ if (matches.length !== 1)
651
+ return routes;
652
+ const [targetRoute] = matches;
432
653
  return routes.map((route) => {
433
- if (route.name !== segment || !route.navigator?.routes)
654
+ if (route !== targetRoute || !route.navigator?.routes)
434
655
  return route;
435
656
  return {
436
657
  ...route,
@@ -447,7 +668,10 @@ export function findNavigatorAtPath(navigator, parentPath) {
447
668
  const [segment, ...rest] = parentPath;
448
669
  if (!segment)
449
670
  return null;
450
- const route = navigator.routes.find((item) => item.name === segment);
671
+ const matches = navigator.routes.filter((item) => item.name === segment);
672
+ if (matches.length !== 1)
673
+ return null;
674
+ const [route] = matches;
451
675
  if (!route?.navigator)
452
676
  return null;
453
677
  return findNavigatorAtPath(route.navigator, rest);
@@ -456,10 +680,14 @@ export function updateNavigatorAtPath(navigator, parentPath, updater) {
456
680
  if (parentPath.length === 0)
457
681
  return updater(navigator);
458
682
  const [segment, ...rest] = parentPath;
683
+ const matches = navigator.routes.filter((route) => route.name === segment && route.navigator);
684
+ if (matches.length !== 1)
685
+ return navigator;
686
+ const [targetRoute] = matches;
459
687
  return {
460
688
  ...navigator,
461
689
  routes: navigator.routes.map((route) => {
462
- if (route.name !== segment || !route.navigator)
690
+ if (route !== targetRoute || !route.navigator)
463
691
  return route;
464
692
  return {
465
693
  ...route,
@@ -469,6 +697,8 @@ export function updateNavigatorAtPath(navigator, parentPath, updater) {
469
697
  };
470
698
  }
471
699
  export function setStudioManifestNavigatorType(manifest, type) {
700
+ if (!NAVIGATOR_TYPES.includes(type))
701
+ return manifest;
472
702
  const primaryNavigatorPath = getPrimaryNavigatorPath(manifest.navigator.routes);
473
703
  const currentNavigator = findNavigatorAtPath(manifest.navigator, primaryNavigatorPath);
474
704
  if (!currentNavigator || currentNavigator.type === type)
@@ -489,8 +719,9 @@ export function setStudioManifestNavigatorInitialRoute(manifest, routeName) {
489
719
  const currentNavigator = findNavigatorAtPath(manifest.navigator, primaryNavigatorPath);
490
720
  if (!currentNavigator)
491
721
  return manifest;
492
- if (!currentNavigator.routes.some((route) => route.name === normalizedRoute))
722
+ if (currentNavigator.routes.filter((route) => route.name === normalizedRoute).length !== 1) {
493
723
  return manifest;
724
+ }
494
725
  if (currentNavigator.initialRouteName === normalizedRoute)
495
726
  return manifest;
496
727
  return {
@@ -501,26 +732,82 @@ export function setStudioManifestNavigatorInitialRoute(manifest, routeName) {
501
732
  })),
502
733
  };
503
734
  }
735
+ export function setStudioManifestRoutePrimaryNavigationVisibility(args) {
736
+ const { manifest, parentPath, routeName, showInPrimaryNavigation } = args;
737
+ const navigator = findNavigatorAtPath(manifest.navigator, parentPath);
738
+ if (!navigator)
739
+ return manifest;
740
+ const matches = navigator.routes.filter((route) => route.name === routeName);
741
+ if (matches.length !== 1)
742
+ return manifest;
743
+ const [matchedRoute] = matches;
744
+ if (!matchedRoute)
745
+ return manifest;
746
+ const alreadyCanonical = showInPrimaryNavigation
747
+ ? matchedRoute.showInPrimaryNavigation === undefined
748
+ : matchedRoute.showInPrimaryNavigation === false;
749
+ if (alreadyCanonical)
750
+ return manifest;
751
+ return {
752
+ ...manifest,
753
+ navigator: updateNavigatorAtPath(manifest.navigator, parentPath, (current) => ({
754
+ ...current,
755
+ routes: current.routes.map((route) => {
756
+ if (route !== matchedRoute)
757
+ return route;
758
+ if (!showInPrimaryNavigation) {
759
+ return { ...route, showInPrimaryNavigation: false };
760
+ }
761
+ const { showInPrimaryNavigation: _visibility, ...visibleRoute } = route;
762
+ return visibleRoute;
763
+ }),
764
+ })),
765
+ };
766
+ }
767
+ export function moveStudioManifestRoute(args) {
768
+ const { manifest, parentPath, routeName, toIndex } = args;
769
+ if (!Number.isInteger(toIndex))
770
+ return manifest;
771
+ const navigator = findNavigatorAtPath(manifest.navigator, parentPath);
772
+ if (!navigator || toIndex < 0 || toIndex >= navigator.routes.length)
773
+ return manifest;
774
+ const matchingIndexes = navigator.routes.flatMap((route, index) => route.name === routeName ? [index] : []);
775
+ if (matchingIndexes.length !== 1)
776
+ return manifest;
777
+ const [fromIndex] = matchingIndexes;
778
+ if (fromIndex === undefined || fromIndex === toIndex)
779
+ return manifest;
780
+ return {
781
+ ...manifest,
782
+ navigator: updateNavigatorAtPath(manifest.navigator, parentPath, (current) => {
783
+ const routes = [...current.routes];
784
+ const [route] = routes.splice(fromIndex, 1);
785
+ if (!route)
786
+ return current;
787
+ routes.splice(toIndex, 0, route);
788
+ return { ...current, routes };
789
+ }),
790
+ };
791
+ }
504
792
  export function addStudioManifestScreen(args) {
505
793
  const { manifest, activeScreenId, createId = generateManifestStateId } = args;
794
+ if (!hasCanonicalStudioScreenRegistryIdentity(manifest.screens)) {
795
+ return { manifest, activeScreenId };
796
+ }
506
797
  const trimmedName = args.name.trim();
507
798
  if (!trimmedName)
508
799
  return { manifest, activeScreenId };
509
800
  const baseRouteName = normalizeRouteName(trimmedName);
510
- const activeParentPath = activeScreenId
511
- ? findParentPathForScreenId(manifest.navigator.routes, activeScreenId)
512
- : null;
513
- const fallbackParentPath = getPrimaryNavigatorPath(manifest.navigator.routes);
514
- const activeParentRoutes = activeParentPath !== null
515
- ? findRoutesAtParentPath(manifest.navigator.routes, activeParentPath)
516
- : null;
517
- const parentPath = activeParentPath && activeParentRoutes ? activeParentPath : fallbackParentPath;
518
- const siblingRoutes = findRoutesAtParentPath(manifest.navigator.routes, parentPath) ?? [];
801
+ const parentPath = args.parentPath ?? getPrimaryNavigatorPath(manifest.navigator.routes);
802
+ const siblingRoutes = findRoutesAtParentPath(manifest.navigator.routes, parentPath);
803
+ if (!siblingRoutes)
804
+ return { manifest, activeScreenId };
805
+ const existingScreenIds = new Set(Object.values(manifest.screens).map((screen) => screen.id));
519
806
  let screenId = createId('Screen');
520
- while (manifest.screens[screenId]) {
807
+ while (manifest.screens[screenId] || existingScreenIds.has(screenId)) {
521
808
  screenId = createId('Screen');
522
809
  }
523
- const existingPatterns = new Set(collectScreenRouteEntries(manifest.navigator.routes).map((entry) => toCanonicalRoutePattern(entry.routePath)));
810
+ const existingPatterns = new Set(collectCanonicalRoutePatterns(manifest.navigator.routes));
524
811
  const routeName = makeUniqueRouteNameForParent(baseRouteName, siblingRoutes, parentPath, existingPatterns);
525
812
  const newScreen = {
526
813
  id: screenId,
@@ -548,46 +835,33 @@ export function addStudioManifestScreen(args) {
548
835
  };
549
836
  }
550
837
  export function deleteStudioManifestScreen(manifest, screenId, activeScreenId) {
838
+ if (!hasCanonicalStudioScreenRegistryIdentity(manifest.screens)) {
839
+ return { manifest, activeScreenId };
840
+ }
551
841
  if (Object.keys(manifest.screens).length <= 1)
552
842
  return { manifest, activeScreenId };
843
+ const deletedScreen = manifest.screens[screenId];
844
+ if (!deletedScreen)
845
+ return { manifest, activeScreenId };
553
846
  const { [screenId]: _deletedScreen, ...remainingScreens } = manifest.screens;
554
847
  const remainingScreenIds = Object.keys(remainingScreens);
555
- let safeRoutes = removeScreenIdFromRoutes(manifest.navigator.routes, screenId);
556
- if (safeRoutes.length === 0 && remainingScreenIds.length > 0) {
557
- const [fallbackScreenId] = remainingScreenIds;
558
- if (!fallbackScreenId)
559
- return { manifest, activeScreenId };
560
- const fallbackScreen = remainingScreens[fallbackScreenId];
561
- safeRoutes = [
562
- {
563
- name: makeUniqueSiblingRouteName('screen', []),
564
- label: fallbackScreen?.name ?? 'Screen',
565
- screenId: fallbackScreenId,
566
- },
567
- ];
568
- }
848
+ const safeRoutes = removeScreenIdFromRoutes(manifest.navigator.routes, screenId);
569
849
  const orderedScreenIds = listScreenIdsInRouteOrder(safeRoutes).filter((id) => !!remainingScreens[id]);
570
850
  const nextActiveScreenId = !activeScreenId || activeScreenId === screenId || !remainingScreens[activeScreenId]
571
851
  ? (orderedScreenIds[0] ?? remainingScreenIds[0] ?? null)
572
852
  : activeScreenId;
853
+ const deletedNodeIds = collectNodeIds(deletedScreen.root);
854
+ const dataBindings = Object.fromEntries(Object.entries(manifest.dataBindings ?? {}).filter(([componentId, binding]) => !deletedNodeIds.has(componentId) && !deletedNodeIds.has(binding.componentId)));
573
855
  return {
574
856
  activeScreenId: nextActiveScreenId,
575
857
  manifest: {
576
858
  ...manifest,
859
+ dataBindings,
577
860
  screens: remainingScreens,
578
- navigator: {
861
+ navigator: normalizeNavigatorAfterRouteUpdate({
579
862
  ...manifest.navigator,
580
863
  routes: safeRoutes,
581
- },
582
- },
583
- };
584
- }
585
- export function reorderStudioManifestScreens(manifest, newRoutes) {
586
- return {
587
- ...manifest,
588
- navigator: {
589
- ...manifest.navigator,
590
- routes: newRoutes,
864
+ }),
591
865
  },
592
866
  };
593
867
  }
@@ -653,6 +927,17 @@ function normalizeRouteName(value) {
653
927
  .replace(/[^a-z0-9]+/g, '-')
654
928
  .replace(/^-+|-+$/g, '') || 'screen');
655
929
  }
930
+ function collectCanonicalRoutePatterns(routes, runtimePathPrefix = []) {
931
+ const patterns = [];
932
+ for (const route of routes) {
933
+ const runtimePath = appendRuntimeRoutePath(runtimePathPrefix, route);
934
+ patterns.push(toCanonicalRoutePattern(runtimePath));
935
+ if (route.navigator) {
936
+ patterns.push(...collectCanonicalRoutePatterns(route.navigator.routes, runtimePath));
937
+ }
938
+ }
939
+ return patterns;
940
+ }
656
941
  function cloneNodeWithNewIds(node, createId) {
657
942
  const clonedNode = {
658
943
  ...node,