@shipfox/client-shell 10.0.1 → 12.0.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 (70) hide show
  1. package/dist/components/user-menu.d.ts.map +1 -1
  2. package/dist/components/user-menu.js +26 -0
  3. package/dist/components/user-menu.js.map +1 -1
  4. package/dist/compose/compose-client-features.d.ts +2 -1
  5. package/dist/compose/compose-client-features.d.ts.map +1 -1
  6. package/dist/compose/compose-client-features.js +5 -3
  7. package/dist/compose/compose-client-features.js.map +1 -1
  8. package/dist/compose/compose-routes.d.ts +6 -2
  9. package/dist/compose/compose-routes.d.ts.map +1 -1
  10. package/dist/compose/compose-routes.js +137 -2
  11. package/dist/compose/compose-routes.js.map +1 -1
  12. package/dist/compose/errors.d.ts +4 -0
  13. package/dist/compose/errors.d.ts.map +1 -1
  14. package/dist/compose/errors.js +6 -0
  15. package/dist/compose/errors.js.map +1 -1
  16. package/dist/compose/validate-registries.d.ts +9 -2
  17. package/dist/compose/validate-registries.d.ts.map +1 -1
  18. package/dist/compose/validate-registries.js +83 -2
  19. package/dist/compose/validate-registries.js.map +1 -1
  20. package/dist/contract.d.ts +23 -3
  21. package/dist/contract.d.ts.map +1 -1
  22. package/dist/contract.js.map +1 -1
  23. package/dist/core/session.d.ts +1 -0
  24. package/dist/core/session.d.ts.map +1 -1
  25. package/dist/core/session.js.map +1 -1
  26. package/dist/hooks/api/session-auth.d.ts.map +1 -1
  27. package/dist/hooks/api/session-auth.js +2 -1
  28. package/dist/hooks/api/session-auth.js.map +1 -1
  29. package/dist/runtime/anchor-paths.d.ts +2 -0
  30. package/dist/runtime/anchor-paths.d.ts.map +1 -1
  31. package/dist/runtime/anchor-paths.js +15 -0
  32. package/dist/runtime/anchor-paths.js.map +1 -1
  33. package/dist/runtime/anchors.d.ts.map +1 -1
  34. package/dist/runtime/anchors.js +6 -3
  35. package/dist/runtime/anchors.js.map +1 -1
  36. package/dist/runtime/assemble-route-tree.d.ts +3 -2
  37. package/dist/runtime/assemble-route-tree.d.ts.map +1 -1
  38. package/dist/runtime/assemble-route-tree.js +76 -5
  39. package/dist/runtime/assemble-route-tree.js.map +1 -1
  40. package/dist/runtime/chrome-context.d.ts +6 -0
  41. package/dist/runtime/chrome-context.d.ts.map +1 -1
  42. package/dist/runtime/chrome-context.js.map +1 -1
  43. package/dist/runtime/index.d.ts +1 -0
  44. package/dist/runtime/index.d.ts.map +1 -1
  45. package/dist/runtime/index.js +1 -0
  46. package/dist/runtime/index.js.map +1 -1
  47. package/dist/runtime/layout-navigation.d.ts +7 -0
  48. package/dist/runtime/layout-navigation.d.ts.map +1 -0
  49. package/dist/runtime/layout-navigation.js +18 -0
  50. package/dist/runtime/layout-navigation.js.map +1 -0
  51. package/dist/runtime/provider-stack.d.ts.map +1 -1
  52. package/dist/runtime/provider-stack.js +7 -3
  53. package/dist/runtime/provider-stack.js.map +1 -1
  54. package/dist/runtime/registries.d.ts +2 -1
  55. package/dist/runtime/registries.d.ts.map +1 -1
  56. package/dist/runtime/registries.js +10 -0
  57. package/dist/runtime/registries.js.map +1 -1
  58. package/dist/runtime/workspace-setup.d.ts +4 -0
  59. package/dist/runtime/workspace-setup.d.ts.map +1 -1
  60. package/dist/runtime/workspace-setup.js +23 -0
  61. package/dist/runtime/workspace-setup.js.map +1 -1
  62. package/dist/tsconfig.test.tsbuildinfo +1 -1
  63. package/dist/vite/generate.d.ts +3 -2
  64. package/dist/vite/generate.d.ts.map +1 -1
  65. package/dist/vite/generate.js +108 -20
  66. package/dist/vite/generate.js.map +1 -1
  67. package/dist/vite/plugin.d.ts.map +1 -1
  68. package/dist/vite/plugin.js +7 -3
  69. package/dist/vite/plugin.js.map +1 -1
  70. package/package.json +3 -3
@@ -2,24 +2,42 @@ import type { IconName } from '@shipfox/react-ui/icon';
2
2
  import type { ComponentType, PropsWithChildren } from 'react';
3
3
  import type { z } from 'zod';
4
4
  export type AnchorId = 'root' | 'workspaceLayout' | 'projectLayout' | 'workspaceSettings';
5
+ /** A fixed shell anchor or the stable id of a feature-owned layout. */
6
+ export type RouteParentId = AnchorId | (string & {});
5
7
  export interface RouteContribution {
6
8
  path: string;
7
- parent: AnchorId;
9
+ parent: RouteParentId;
8
10
  override?: boolean;
9
11
  impl: string;
10
12
  }
13
+ export interface LayoutContribution {
14
+ id: string;
15
+ path: string;
16
+ parent: RouteParentId;
17
+ impl: string;
18
+ }
11
19
  export interface FeatureProvider {
12
20
  id: string;
13
21
  Component: ComponentType<PropsWithChildren>;
14
22
  }
15
- export interface NavTabEntry {
23
+ interface NavTabEntryBase {
16
24
  id: string;
17
- scope: 'workspace' | 'project';
18
25
  label: string;
19
26
  to: string;
20
27
  exact?: boolean;
21
28
  order?: number;
22
29
  }
30
+ export type NavTabEntry = (NavTabEntryBase & {
31
+ scope: 'workspace' | 'project';
32
+ layout?: never;
33
+ }) | (NavTabEntryBase & {
34
+ scope: 'layout';
35
+ layout: string;
36
+ minimumRole?: string;
37
+ });
38
+ export type LayoutNavigationEntry = Extract<NavTabEntry, {
39
+ scope: 'layout';
40
+ }>;
23
41
  export interface SettingsSectionEntry {
24
42
  id: string;
25
43
  pathSegment: string;
@@ -35,6 +53,7 @@ export interface ClientFeature<S extends z.ZodRawShape = z.ZodRawShape> {
35
53
  * feature.
36
54
  */
37
55
  coordinator?: string;
56
+ layouts?: readonly LayoutContribution[];
38
57
  routes?: readonly RouteContribution[];
39
58
  providers?: readonly FeatureProvider[];
40
59
  navigation?: readonly NavTabEntry[];
@@ -42,4 +61,5 @@ export interface ClientFeature<S extends z.ZodRawShape = z.ZodRawShape> {
42
61
  configShape?: S;
43
62
  }
44
63
  export declare function defineClientFeature<const T extends ClientFeature>(feature: T): T;
64
+ export {};
45
65
  //# sourceMappingURL=contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAC,aAAa,EAAE,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAE3B,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,iBAAiB,GAAG,eAAe,GAAG,mBAAmB,CAAC;AAE1F,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,WAAW,GAAG,SAAS,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;IACpE,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACtC,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACvC,UAAU,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACpC,gBAAgB,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACnD,WAAW,CAAC,EAAE,CAAC,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAEhF"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAC,aAAa,EAAE,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAE3B,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,iBAAiB,GAAG,eAAe,GAAG,mBAAmB,CAAC;AAE1F,uEAAuE;AACvE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAErD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;CAC7C;AAED,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,WAAW,GACnB,CAAC,eAAe,GAAG;IAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,CAAA;CAAC,CAAC,GACpE,CAAC,eAAe,GAAG;IAAC,KAAK,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAC,CAAC,CAAC;AAEhF,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,WAAW,EAAE;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAC,CAAC,CAAC;AAE5E,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;IACpE,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACxC,MAAM,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACtC,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACvC,UAAU,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACpC,gBAAgB,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACnD,WAAW,CAAC,EAAE,CAAC,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAEhF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/contract.ts"],"sourcesContent":["import type {IconName} from '@shipfox/react-ui/icon';\nimport type {ComponentType, PropsWithChildren} from 'react';\nimport type {z} from 'zod';\n\nexport type AnchorId = 'root' | 'workspaceLayout' | 'projectLayout' | 'workspaceSettings';\n\nexport interface RouteContribution {\n path: string;\n parent: AnchorId;\n override?: boolean;\n impl: string;\n}\n\nexport interface FeatureProvider {\n id: string;\n Component: ComponentType<PropsWithChildren>;\n}\n\nexport interface NavTabEntry {\n id: string;\n scope: 'workspace' | 'project';\n label: string;\n to: string;\n exact?: boolean;\n order?: number;\n}\n\nexport interface SettingsSectionEntry {\n id: string;\n pathSegment: string;\n label: string;\n icon: IconName;\n order?: number;\n}\n\nexport interface ClientFeature<S extends z.ZodRawShape = z.ZodRawShape> {\n id: string;\n /**\n * Set this to the feature id when the feature intentionally coordinates a\n * navigation or settings contribution whose route belongs to another\n * feature.\n */\n coordinator?: string;\n routes?: readonly RouteContribution[];\n providers?: readonly FeatureProvider[];\n navigation?: readonly NavTabEntry[];\n settingsSections?: readonly SettingsSectionEntry[];\n configShape?: S;\n}\n\nexport function defineClientFeature<const T extends ClientFeature>(feature: T): T {\n return feature;\n}\n"],"names":["defineClientFeature","feature"],"mappings":"AAkDA,OAAO,SAASA,oBAAmDC,OAAU;IAC3E,OAAOA;AACT"}
1
+ {"version":3,"sources":["../src/contract.ts"],"sourcesContent":["import type {IconName} from '@shipfox/react-ui/icon';\nimport type {ComponentType, PropsWithChildren} from 'react';\nimport type {z} from 'zod';\n\nexport type AnchorId = 'root' | 'workspaceLayout' | 'projectLayout' | 'workspaceSettings';\n\n/** A fixed shell anchor or the stable id of a feature-owned layout. */\nexport type RouteParentId = AnchorId | (string & {});\n\nexport interface RouteContribution {\n path: string;\n parent: RouteParentId;\n override?: boolean;\n impl: string;\n}\n\nexport interface LayoutContribution {\n id: string;\n path: string;\n parent: RouteParentId;\n impl: string;\n}\n\nexport interface FeatureProvider {\n id: string;\n Component: ComponentType<PropsWithChildren>;\n}\n\ninterface NavTabEntryBase {\n id: string;\n label: string;\n to: string;\n exact?: boolean;\n order?: number;\n}\n\nexport type NavTabEntry =\n | (NavTabEntryBase & {scope: 'workspace' | 'project'; layout?: never})\n | (NavTabEntryBase & {scope: 'layout'; layout: string; minimumRole?: string});\n\nexport type LayoutNavigationEntry = Extract<NavTabEntry, {scope: 'layout'}>;\n\nexport interface SettingsSectionEntry {\n id: string;\n pathSegment: string;\n label: string;\n icon: IconName;\n order?: number;\n}\n\nexport interface ClientFeature<S extends z.ZodRawShape = z.ZodRawShape> {\n id: string;\n /**\n * Set this to the feature id when the feature intentionally coordinates a\n * navigation or settings contribution whose route belongs to another\n * feature.\n */\n coordinator?: string;\n layouts?: readonly LayoutContribution[];\n routes?: readonly RouteContribution[];\n providers?: readonly FeatureProvider[];\n navigation?: readonly NavTabEntry[];\n settingsSections?: readonly SettingsSectionEntry[];\n configShape?: S;\n}\n\nexport function defineClientFeature<const T extends ClientFeature>(feature: T): T {\n return feature;\n}\n"],"names":["defineClientFeature","feature"],"mappings":"AAkEA,OAAO,SAASA,oBAAmDC,OAAU;IAC3E,OAAOA;AACT"}
@@ -18,5 +18,6 @@ export interface WorkspaceSummary {
18
18
  id: string;
19
19
  name: string;
20
20
  membershipId: string;
21
+ status?: 'active' | 'suspended' | 'deleted';
21
22
  }
22
23
  //# sourceMappingURL=session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,aAAa,CAAC;AAE5E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,aAAa,CAAC;AAE5E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;CAC7C"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/session.ts"],"sourcesContent":["export type AdminRole = 'admin-observer' | 'admin-operator' | 'admin-owner';\n\nexport interface UserIdentity {\n id: string;\n email: string;\n name?: string;\n emailVerifiedAt?: string;\n adminRole?: AdminRole;\n}\n\nexport interface AuthenticatedSession {\n accessToken: string;\n user: UserIdentity;\n}\n\nexport interface WorkspaceMembership {\n id: string;\n workspaceId: string;\n}\n\nexport interface WorkspaceSummary {\n id: string;\n name: string;\n membershipId: string;\n}\n"],"names":[],"mappings":"AAoBA,WAIC"}
1
+ {"version":3,"sources":["../../src/core/session.ts"],"sourcesContent":["export type AdminRole = 'admin-observer' | 'admin-operator' | 'admin-owner';\n\nexport interface UserIdentity {\n id: string;\n email: string;\n name?: string;\n emailVerifiedAt?: string;\n adminRole?: AdminRole;\n}\n\nexport interface AuthenticatedSession {\n accessToken: string;\n user: UserIdentity;\n}\n\nexport interface WorkspaceMembership {\n id: string;\n workspaceId: string;\n}\n\nexport interface WorkspaceSummary {\n id: string;\n name: string;\n membershipId: string;\n status?: 'active' | 'suspended' | 'deleted';\n}\n"],"names":[],"mappings":"AAoBA,WAKC"}
@@ -1 +1 @@
1
- {"version":3,"file":"session-auth.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/session-auth.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,KAAK,iBAAiB,EAAe,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAC,oBAAoB,EAAE,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAG7E,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,gBAAgB,EAAE,CAAC;CACjC;AAED,eAAO,MAAM,mBAAmB,8BAA+B,CAAC;AAChE,eAAO,MAAM,sBAAsB,iCAAkC,CAAC;AAEtE,KAAK,uBAAuB,GAAG,iBAAiB,CAC9C,oBAAoB,EACpB,KAAK,EACL,oBAAoB,EACpB,OAAO,mBAAmB,CAC3B,CAAC;AAEF,KAAK,0BAA0B,GAAG,iBAAiB,CACjD,cAAc,EACd,KAAK,EACL,cAAc,EACd,OAAO,sBAAsB,CAC9B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAazB;AAED,wBAAgB,uBAAuB,IAAI,uBAAuB,CAOjE;AAED,wBAAgB,0BAA0B,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,0BAA0B,CAOrF;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAM/B"}
1
+ {"version":3,"file":"session-auth.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/session-auth.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,KAAK,iBAAiB,EAAe,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAC,oBAAoB,EAAE,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAG7E,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,gBAAgB,EAAE,CAAC;CACjC;AAED,eAAO,MAAM,mBAAmB,8BAA+B,CAAC;AAChE,eAAO,MAAM,sBAAsB,iCAAkC,CAAC;AAEtE,KAAK,uBAAuB,GAAG,iBAAiB,CAC9C,oBAAoB,EACpB,KAAK,EACL,oBAAoB,EACpB,OAAO,mBAAmB,CAC3B,CAAC;AAEF,KAAK,0BAA0B,GAAG,iBAAiB,CACjD,cAAc,EACd,KAAK,EACL,cAAc,EACd,OAAO,sBAAsB,CAC9B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAczB;AAED,wBAAgB,uBAAuB,IAAI,uBAAuB,CAOjE;AAED,wBAAgB,0BAA0B,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,0BAA0B,CAOrF;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAM/B"}
@@ -24,7 +24,8 @@ export async function listUserWorkspaces(token, signal) {
24
24
  memberships: response.memberships.map((membership)=>({
25
25
  id: membership.workspace_id,
26
26
  name: membership.workspace_name,
27
- membershipId: membership.id
27
+ membershipId: membership.id,
28
+ status: membership.workspace_status
28
29
  }))
29
30
  };
30
31
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/api/session-auth.ts"],"sourcesContent":["import {loginResponseSchema} from '@shipfox/api-auth-dto';\nimport {listUserWorkspacesResponseSchema} from '@shipfox/api-workspaces-dto';\nimport {checkedApiRequest} from '@shipfox/client-api';\nimport {type FetchQueryOptions, queryOptions} from '@tanstack/react-query';\nimport type {AuthenticatedSession, WorkspaceSummary} from '#core/session.js';\nimport {toAuthenticatedSession} from './session-mapper.js';\n\nexport interface UserWorkspaces {\n memberships: WorkspaceSummary[];\n}\n\nexport const authRefreshQueryKey = ['auth', 'refresh'] as const;\nexport const userWorkspacesQueryKey = ['workspaces', 'mine'] as const;\n\ntype AuthRefreshQueryOptions = FetchQueryOptions<\n AuthenticatedSession,\n Error,\n AuthenticatedSession,\n typeof authRefreshQueryKey\n>;\n\ntype UserWorkspacesQueryOptions = FetchQueryOptions<\n UserWorkspaces,\n Error,\n UserWorkspaces,\n typeof userWorkspacesQueryKey\n>;\n\nexport async function listUserWorkspaces(\n token?: string,\n signal?: AbortSignal,\n): Promise<UserWorkspaces> {\n const response = await checkedApiRequest(\n listUserWorkspacesResponseSchema,\n '/workspaces',\n token ? {headers: {authorization: `Bearer ${token}`}, signal} : {signal},\n );\n return {\n memberships: response.memberships.map((membership) => ({\n id: membership.workspace_id,\n name: membership.workspace_name,\n membershipId: membership.id,\n })),\n };\n}\n\nexport function authRefreshQueryOptions(): AuthRefreshQueryOptions {\n return queryOptions({\n queryKey: authRefreshQueryKey,\n queryFn: ({signal}) => refreshAuthenticatedSession(signal),\n retry: false,\n staleTime: 0,\n });\n}\n\nexport function userWorkspacesQueryOptions(token?: string): UserWorkspacesQueryOptions {\n return queryOptions({\n queryKey: userWorkspacesQueryKey,\n queryFn: ({signal}) => listUserWorkspaces(token, signal),\n retry: false,\n staleTime: 0,\n });\n}\n\nexport async function refreshAuthenticatedSession(\n signal?: AbortSignal,\n): Promise<AuthenticatedSession> {\n const response = await checkedApiRequest(loginResponseSchema, '/auth/refresh', {\n method: 'POST',\n signal,\n });\n return toAuthenticatedSession(response);\n}\n"],"names":["loginResponseSchema","listUserWorkspacesResponseSchema","checkedApiRequest","queryOptions","toAuthenticatedSession","authRefreshQueryKey","userWorkspacesQueryKey","listUserWorkspaces","token","signal","response","headers","authorization","memberships","map","membership","id","workspace_id","name","workspace_name","membershipId","authRefreshQueryOptions","queryKey","queryFn","refreshAuthenticatedSession","retry","staleTime","userWorkspacesQueryOptions","method"],"mappings":"AAAA,SAAQA,mBAAmB,QAAO,wBAAwB;AAC1D,SAAQC,gCAAgC,QAAO,8BAA8B;AAC7E,SAAQC,iBAAiB,QAAO,sBAAsB;AACtD,SAAgCC,YAAY,QAAO,wBAAwB;AAE3E,SAAQC,sBAAsB,QAAO,sBAAsB;AAM3D,OAAO,MAAMC,sBAAsB;IAAC;IAAQ;CAAU,CAAU;AAChE,OAAO,MAAMC,yBAAyB;IAAC;IAAc;CAAO,CAAU;AAgBtE,OAAO,eAAeC,mBACpBC,KAAc,EACdC,MAAoB;IAEpB,MAAMC,WAAW,MAAMR,kBACrBD,kCACA,eACAO,QAAQ;QAACG,SAAS;YAACC,eAAe,CAAC,OAAO,EAAEJ,OAAO;QAAA;QAAGC;IAAM,IAAI;QAACA;IAAM;IAEzE,OAAO;QACLI,aAAaH,SAASG,WAAW,CAACC,GAAG,CAAC,CAACC,aAAgB,CAAA;gBACrDC,IAAID,WAAWE,YAAY;gBAC3BC,MAAMH,WAAWI,cAAc;gBAC/BC,cAAcL,WAAWC,EAAE;YAC7B,CAAA;IACF;AACF;AAEA,OAAO,SAASK;IACd,OAAOlB,aAAa;QAClBmB,UAAUjB;QACVkB,SAAS,CAAC,EAACd,MAAM,EAAC,GAAKe,4BAA4Bf;QACnDgB,OAAO;QACPC,WAAW;IACb;AACF;AAEA,OAAO,SAASC,2BAA2BnB,KAAc;IACvD,OAAOL,aAAa;QAClBmB,UAAUhB;QACViB,SAAS,CAAC,EAACd,MAAM,EAAC,GAAKF,mBAAmBC,OAAOC;QACjDgB,OAAO;QACPC,WAAW;IACb;AACF;AAEA,OAAO,eAAeF,4BACpBf,MAAoB;IAEpB,MAAMC,WAAW,MAAMR,kBAAkBF,qBAAqB,iBAAiB;QAC7E4B,QAAQ;QACRnB;IACF;IACA,OAAOL,uBAAuBM;AAChC"}
1
+ {"version":3,"sources":["../../../src/hooks/api/session-auth.ts"],"sourcesContent":["import {loginResponseSchema} from '@shipfox/api-auth-dto';\nimport {listUserWorkspacesResponseSchema} from '@shipfox/api-workspaces-dto';\nimport {checkedApiRequest} from '@shipfox/client-api';\nimport {type FetchQueryOptions, queryOptions} from '@tanstack/react-query';\nimport type {AuthenticatedSession, WorkspaceSummary} from '#core/session.js';\nimport {toAuthenticatedSession} from './session-mapper.js';\n\nexport interface UserWorkspaces {\n memberships: WorkspaceSummary[];\n}\n\nexport const authRefreshQueryKey = ['auth', 'refresh'] as const;\nexport const userWorkspacesQueryKey = ['workspaces', 'mine'] as const;\n\ntype AuthRefreshQueryOptions = FetchQueryOptions<\n AuthenticatedSession,\n Error,\n AuthenticatedSession,\n typeof authRefreshQueryKey\n>;\n\ntype UserWorkspacesQueryOptions = FetchQueryOptions<\n UserWorkspaces,\n Error,\n UserWorkspaces,\n typeof userWorkspacesQueryKey\n>;\n\nexport async function listUserWorkspaces(\n token?: string,\n signal?: AbortSignal,\n): Promise<UserWorkspaces> {\n const response = await checkedApiRequest(\n listUserWorkspacesResponseSchema,\n '/workspaces',\n token ? {headers: {authorization: `Bearer ${token}`}, signal} : {signal},\n );\n return {\n memberships: response.memberships.map((membership) => ({\n id: membership.workspace_id,\n name: membership.workspace_name,\n membershipId: membership.id,\n status: membership.workspace_status,\n })),\n };\n}\n\nexport function authRefreshQueryOptions(): AuthRefreshQueryOptions {\n return queryOptions({\n queryKey: authRefreshQueryKey,\n queryFn: ({signal}) => refreshAuthenticatedSession(signal),\n retry: false,\n staleTime: 0,\n });\n}\n\nexport function userWorkspacesQueryOptions(token?: string): UserWorkspacesQueryOptions {\n return queryOptions({\n queryKey: userWorkspacesQueryKey,\n queryFn: ({signal}) => listUserWorkspaces(token, signal),\n retry: false,\n staleTime: 0,\n });\n}\n\nexport async function refreshAuthenticatedSession(\n signal?: AbortSignal,\n): Promise<AuthenticatedSession> {\n const response = await checkedApiRequest(loginResponseSchema, '/auth/refresh', {\n method: 'POST',\n signal,\n });\n return toAuthenticatedSession(response);\n}\n"],"names":["loginResponseSchema","listUserWorkspacesResponseSchema","checkedApiRequest","queryOptions","toAuthenticatedSession","authRefreshQueryKey","userWorkspacesQueryKey","listUserWorkspaces","token","signal","response","headers","authorization","memberships","map","membership","id","workspace_id","name","workspace_name","membershipId","status","workspace_status","authRefreshQueryOptions","queryKey","queryFn","refreshAuthenticatedSession","retry","staleTime","userWorkspacesQueryOptions","method"],"mappings":"AAAA,SAAQA,mBAAmB,QAAO,wBAAwB;AAC1D,SAAQC,gCAAgC,QAAO,8BAA8B;AAC7E,SAAQC,iBAAiB,QAAO,sBAAsB;AACtD,SAAgCC,YAAY,QAAO,wBAAwB;AAE3E,SAAQC,sBAAsB,QAAO,sBAAsB;AAM3D,OAAO,MAAMC,sBAAsB;IAAC;IAAQ;CAAU,CAAU;AAChE,OAAO,MAAMC,yBAAyB;IAAC;IAAc;CAAO,CAAU;AAgBtE,OAAO,eAAeC,mBACpBC,KAAc,EACdC,MAAoB;IAEpB,MAAMC,WAAW,MAAMR,kBACrBD,kCACA,eACAO,QAAQ;QAACG,SAAS;YAACC,eAAe,CAAC,OAAO,EAAEJ,OAAO;QAAA;QAAGC;IAAM,IAAI;QAACA;IAAM;IAEzE,OAAO;QACLI,aAAaH,SAASG,WAAW,CAACC,GAAG,CAAC,CAACC,aAAgB,CAAA;gBACrDC,IAAID,WAAWE,YAAY;gBAC3BC,MAAMH,WAAWI,cAAc;gBAC/BC,cAAcL,WAAWC,EAAE;gBAC3BK,QAAQN,WAAWO,gBAAgB;YACrC,CAAA;IACF;AACF;AAEA,OAAO,SAASC;IACd,OAAOpB,aAAa;QAClBqB,UAAUnB;QACVoB,SAAS,CAAC,EAAChB,MAAM,EAAC,GAAKiB,4BAA4BjB;QACnDkB,OAAO;QACPC,WAAW;IACb;AACF;AAEA,OAAO,SAASC,2BAA2BrB,KAAc;IACvD,OAAOL,aAAa;QAClBqB,UAAUlB;QACVmB,SAAS,CAAC,EAAChB,MAAM,EAAC,GAAKF,mBAAmBC,OAAOC;QACjDkB,OAAO;QACPC,WAAW;IACb;AACF;AAEA,OAAO,eAAeF,4BACpBjB,MAAoB;IAEpB,MAAMC,WAAW,MAAMR,kBAAkBF,qBAAqB,iBAAiB;QAC7E8B,QAAQ;QACRrB;IACF;IACA,OAAOL,uBAAuBM;AAChC"}
@@ -1,3 +1,4 @@
1
+ import type { RouteParentId } from '#contract.js';
1
2
  declare const anchorPaths: {
2
3
  readonly root: "/";
3
4
  readonly workspaceLayout: "/workspaces/$wid";
@@ -6,4 +7,5 @@ declare const anchorPaths: {
6
7
  };
7
8
  export { anchorPaths };
8
9
  export declare function routePathForAnchor(anchor: keyof typeof anchorPaths, fullPath: string): string;
10
+ export declare function routePathForParent(parent: RouteParentId, fullPath: string, layoutPaths?: ReadonlyMap<string, string>): string;
9
11
  //# sourceMappingURL=anchor-paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"anchor-paths.d.ts","sourceRoot":"","sources":["../../src/runtime/anchor-paths.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,WAAW;;;;;CAKP,CAAC;AAEX,OAAO,EAAC,WAAW,EAAC,CAAC;AAErB,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,OAAO,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ7F"}
1
+ {"version":3,"file":"anchor-paths.d.ts","sourceRoot":"","sources":["../../src/runtime/anchor-paths.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAEhD,QAAA,MAAM,WAAW;;;;;CAKP,CAAC;AAEX,OAAO,EAAC,WAAW,EAAC,CAAC;AAErB,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,OAAO,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ7F;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAa,GACnD,MAAM,CAiBR"}
@@ -1,3 +1,4 @@
1
+ import { normalizeRoutePath } from '#compose/normalize-route-path.js';
1
2
  const anchorPaths = {
2
3
  root: '/',
3
4
  workspaceLayout: '/workspaces/$wid',
@@ -14,5 +15,19 @@ export function routePathForAnchor(anchor, fullPath) {
14
15
  }
15
16
  return fullPath.slice(anchorPath.length);
16
17
  }
18
+ export function routePathForParent(parent, fullPath, layoutPaths = new Map()) {
19
+ const normalizedPath = normalizeRoutePath(fullPath);
20
+ const parentPath = Object.hasOwn(anchorPaths, parent) ? anchorPaths[parent] : layoutPaths.get(parent);
21
+ if (!parentPath) {
22
+ throw new Error(`Route "${normalizedPath}" targets missing layout parent "${parent}".`);
23
+ }
24
+ if (parentPath === '/') return normalizedPath;
25
+ if (normalizedPath === parentPath) return '/';
26
+ if (parentPath !== '/' && !normalizedPath.startsWith(`${parentPath}/`)) {
27
+ const parentKind = Object.hasOwn(anchorPaths, parent) ? 'anchor' : 'layout';
28
+ throw new Error(`Route "${normalizedPath}" must be nested under ${parentKind} "${parent}" (${parentPath}).`);
29
+ }
30
+ return normalizedPath.slice(parentPath.length);
31
+ }
17
32
 
18
33
  //# sourceMappingURL=anchor-paths.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/anchor-paths.ts"],"sourcesContent":["const anchorPaths = {\n root: '/',\n workspaceLayout: '/workspaces/$wid',\n projectLayout: '/workspaces/$wid/projects/$pid',\n workspaceSettings: '/workspaces/$wid/settings',\n} as const;\n\nexport {anchorPaths};\n\nexport function routePathForAnchor(anchor: keyof typeof anchorPaths, fullPath: string): string {\n const anchorPath = anchorPaths[anchor];\n if (anchor === 'root') return fullPath;\n if (fullPath === anchorPath) return '/';\n if (!fullPath.startsWith(`${anchorPath}/`)) {\n throw new Error(`Route \"${fullPath}\" must be nested under anchor \"${anchor}\" (${anchorPath}).`);\n }\n return fullPath.slice(anchorPath.length);\n}\n"],"names":["anchorPaths","root","workspaceLayout","projectLayout","workspaceSettings","routePathForAnchor","anchor","fullPath","anchorPath","startsWith","Error","slice","length"],"mappings":"AAAA,MAAMA,cAAc;IAClBC,MAAM;IACNC,iBAAiB;IACjBC,eAAe;IACfC,mBAAmB;AACrB;AAEA,SAAQJ,WAAW,GAAE;AAErB,OAAO,SAASK,mBAAmBC,MAAgC,EAAEC,QAAgB;IACnF,MAAMC,aAAaR,WAAW,CAACM,OAAO;IACtC,IAAIA,WAAW,QAAQ,OAAOC;IAC9B,IAAIA,aAAaC,YAAY,OAAO;IACpC,IAAI,CAACD,SAASE,UAAU,CAAC,GAAGD,WAAW,CAAC,CAAC,GAAG;QAC1C,MAAM,IAAIE,MAAM,CAAC,OAAO,EAAEH,SAAS,+BAA+B,EAAED,OAAO,GAAG,EAAEE,WAAW,EAAE,CAAC;IAChG;IACA,OAAOD,SAASI,KAAK,CAACH,WAAWI,MAAM;AACzC"}
1
+ {"version":3,"sources":["../../src/runtime/anchor-paths.ts"],"sourcesContent":["import {normalizeRoutePath} from '#compose/normalize-route-path.js';\nimport type {RouteParentId} from '#contract.js';\n\nconst anchorPaths = {\n root: '/',\n workspaceLayout: '/workspaces/$wid',\n projectLayout: '/workspaces/$wid/projects/$pid',\n workspaceSettings: '/workspaces/$wid/settings',\n} as const;\n\nexport {anchorPaths};\n\nexport function routePathForAnchor(anchor: keyof typeof anchorPaths, fullPath: string): string {\n const anchorPath = anchorPaths[anchor];\n if (anchor === 'root') return fullPath;\n if (fullPath === anchorPath) return '/';\n if (!fullPath.startsWith(`${anchorPath}/`)) {\n throw new Error(`Route \"${fullPath}\" must be nested under anchor \"${anchor}\" (${anchorPath}).`);\n }\n return fullPath.slice(anchorPath.length);\n}\n\nexport function routePathForParent(\n parent: RouteParentId,\n fullPath: string,\n layoutPaths: ReadonlyMap<string, string> = new Map(),\n): string {\n const normalizedPath = normalizeRoutePath(fullPath);\n const parentPath = Object.hasOwn(anchorPaths, parent)\n ? anchorPaths[parent as keyof typeof anchorPaths]\n : layoutPaths.get(parent);\n if (!parentPath) {\n throw new Error(`Route \"${normalizedPath}\" targets missing layout parent \"${parent}\".`);\n }\n if (parentPath === '/') return normalizedPath;\n if (normalizedPath === parentPath) return '/';\n if (parentPath !== '/' && !normalizedPath.startsWith(`${parentPath}/`)) {\n const parentKind = Object.hasOwn(anchorPaths, parent) ? 'anchor' : 'layout';\n throw new Error(\n `Route \"${normalizedPath}\" must be nested under ${parentKind} \"${parent}\" (${parentPath}).`,\n );\n }\n return normalizedPath.slice(parentPath.length);\n}\n"],"names":["normalizeRoutePath","anchorPaths","root","workspaceLayout","projectLayout","workspaceSettings","routePathForAnchor","anchor","fullPath","anchorPath","startsWith","Error","slice","length","routePathForParent","parent","layoutPaths","Map","normalizedPath","parentPath","Object","hasOwn","get","parentKind"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,mCAAmC;AAGpE,MAAMC,cAAc;IAClBC,MAAM;IACNC,iBAAiB;IACjBC,eAAe;IACfC,mBAAmB;AACrB;AAEA,SAAQJ,WAAW,GAAE;AAErB,OAAO,SAASK,mBAAmBC,MAAgC,EAAEC,QAAgB;IACnF,MAAMC,aAAaR,WAAW,CAACM,OAAO;IACtC,IAAIA,WAAW,QAAQ,OAAOC;IAC9B,IAAIA,aAAaC,YAAY,OAAO;IACpC,IAAI,CAACD,SAASE,UAAU,CAAC,GAAGD,WAAW,CAAC,CAAC,GAAG;QAC1C,MAAM,IAAIE,MAAM,CAAC,OAAO,EAAEH,SAAS,+BAA+B,EAAED,OAAO,GAAG,EAAEE,WAAW,EAAE,CAAC;IAChG;IACA,OAAOD,SAASI,KAAK,CAACH,WAAWI,MAAM;AACzC;AAEA,OAAO,SAASC,mBACdC,MAAqB,EACrBP,QAAgB,EAChBQ,cAA2C,IAAIC,KAAK;IAEpD,MAAMC,iBAAiBlB,mBAAmBQ;IAC1C,MAAMW,aAAaC,OAAOC,MAAM,CAACpB,aAAac,UAC1Cd,WAAW,CAACc,OAAmC,GAC/CC,YAAYM,GAAG,CAACP;IACpB,IAAI,CAACI,YAAY;QACf,MAAM,IAAIR,MAAM,CAAC,OAAO,EAAEO,eAAe,iCAAiC,EAAEH,OAAO,EAAE,CAAC;IACxF;IACA,IAAII,eAAe,KAAK,OAAOD;IAC/B,IAAIA,mBAAmBC,YAAY,OAAO;IAC1C,IAAIA,eAAe,OAAO,CAACD,eAAeR,UAAU,CAAC,GAAGS,WAAW,CAAC,CAAC,GAAG;QACtE,MAAMI,aAAaH,OAAOC,MAAM,CAACpB,aAAac,UAAU,WAAW;QACnE,MAAM,IAAIJ,MACR,CAAC,OAAO,EAAEO,eAAe,uBAAuB,EAAEK,WAAW,EAAE,EAAER,OAAO,GAAG,EAAEI,WAAW,EAAE,CAAC;IAE/F;IACA,OAAOD,eAAeN,KAAK,CAACO,WAAWN,MAAM;AAC/C"}
@@ -1 +1 @@
1
- {"version":3,"file":"anchors.d.ts","sourceRoot":"","sources":["../../src/runtime/anchors.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,WAAW,EAAE,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAKpE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAGvD,OAAO,EAAC,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAErD,wBAAgB,mBAAmB,CAAC,EAClC,UAAU,EACV,gBAAgB,GACjB,EAAE;IACD,UAAU,EAAE,SAAS,WAAW,EAAE,CAAC;IACnC,gBAAgB,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACnD;;;;;;;;;;;EAmFA"}
1
+ {"version":3,"file":"anchors.d.ts","sourceRoot":"","sources":["../../src/runtime/anchors.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,WAAW,EAAE,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAKpE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAOvD,OAAO,EAAC,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAErD,wBAAgB,mBAAmB,CAAC,EAClC,UAAU,EACV,gBAAgB,GACjB,EAAE;IACD,UAAU,EAAE,SAAS,WAAW,EAAE,CAAC;IACnC,gBAAgB,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACnD;;;;;;;;;;;EAyFA"}
@@ -5,11 +5,11 @@ import { createRootRouteWithContext, createRoute, Outlet, redirect } from '@tans
5
5
  import { MainLayout } from '#components/main-layout.js';
6
6
  import { NotFoundPage } from '#components/not-found-page.js';
7
7
  import { SettingsNav } from '#components/settings-nav.js';
8
- import { useActiveWorkspace } from './active-workspace.js';
8
+ import { useActiveWorkspace, useMaybeActiveWorkspace } from './active-workspace.js';
9
9
  import { anchorPaths } from './anchor-paths.js';
10
10
  import { useChrome } from './chrome-context.js';
11
11
  import { rememberLastWorkspaceId } from './last-workspace.js';
12
- import { WorkspaceLayoutErrorRoute, WorkspaceSetupPending } from './workspace-setup.js';
12
+ import { WorkspaceLayoutErrorRoute, WorkspaceSetupPending, WorkspaceUnavailablePage } from './workspace-setup.js';
13
13
  export { routePathForAnchor } from './anchor-paths.js';
14
14
  export function buildAnchorSkeleton({ navigation, settingsSections }) {
15
15
  const rootRoute = createRootRouteWithContext()({
@@ -55,7 +55,10 @@ export function buildAnchorSkeleton({ navigation, settingsSections }) {
55
55
  errorComponent: WorkspaceLayoutErrorRoute,
56
56
  component: ()=>{
57
57
  const setupState = workspaceLayout.useRouteContext();
58
- return setupState.hideProjectNavigation === undefined ? /*#__PURE__*/ _jsx(WorkspaceSetupPending, {}) : /*#__PURE__*/ _jsx(MainLayout, {
58
+ const workspace = useMaybeActiveWorkspace();
59
+ return setupState.hideProjectNavigation === undefined ? /*#__PURE__*/ _jsx(WorkspaceSetupPending, {}) : setupState.unavailable ? /*#__PURE__*/ _jsx(WorkspaceUnavailablePage, {
60
+ workspaceName: workspace?.name
61
+ }) : /*#__PURE__*/ _jsx(MainLayout, {
59
62
  navigation: navigation,
60
63
  hideProjectNavigation: setupState.hideProjectNavigation
61
64
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/anchors.tsx"],"sourcesContent":["import {ShipfoxLoader} from '@shipfox/react-ui/loader';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {createRootRouteWithContext, createRoute, Outlet, redirect} from '@tanstack/react-router';\nimport {MainLayout} from '#components/main-layout.js';\nimport {NotFoundPage} from '#components/not-found-page.js';\nimport {SettingsNav} from '#components/settings-nav.js';\nimport type {NavTabEntry, SettingsSectionEntry} from '#contract.js';\nimport {useActiveWorkspace} from './active-workspace.js';\nimport {anchorPaths} from './anchor-paths.js';\nimport {useChrome} from './chrome-context.js';\nimport {rememberLastWorkspaceId} from './last-workspace.js';\nimport type {RouterContext} from './router-context.js';\nimport {WorkspaceLayoutErrorRoute, WorkspaceSetupPending} from './workspace-setup.js';\n\nexport {routePathForAnchor} from './anchor-paths.js';\n\nexport function buildAnchorSkeleton({\n navigation,\n settingsSections,\n}: {\n navigation: readonly NavTabEntry[];\n settingsSections: readonly SettingsSectionEntry[];\n}) {\n const rootRoute = createRootRouteWithContext<RouterContext>()({\n component: Outlet,\n notFoundComponent: NotFoundPage,\n });\n const workspaceLayout = createRoute({\n getParentRoute: () => rootRoute,\n path: anchorPaths.workspaceLayout,\n beforeLoad: async ({context, params, location}) => {\n const auth = context.auth;\n if (!auth || auth.isLoading || !context.queryClient) return;\n if (!auth.isAuthenticated)\n throw redirect({to: '/auth/login' as never, search: {redirect: location.href} as never});\n if (!auth.workspaces.some((workspace) => workspace.id === params.wid))\n throw redirect({to: '/'});\n try {\n if (auth.user?.id) rememberLastWorkspaceId(auth.user.id, params.wid);\n } catch {\n // Local storage is best effort.\n }\n if (!context.workspaceSetup)\n throw new Error('Client composition includes workspace routes but no workspaceSetup gate.');\n return await context.workspaceSetup({\n queryClient: context.queryClient,\n workspaceId: params.wid,\n pathname: location.pathname,\n });\n },\n pendingComponent: () => (\n <div className=\"flex h-screen items-center justify-center\">\n <ShipfoxLoader size={64} animation=\"circular\" color=\"orange\" background=\"dark\" />\n </div>\n ),\n errorComponent: WorkspaceLayoutErrorRoute,\n component: () => {\n const setupState = workspaceLayout.useRouteContext() as {hideProjectNavigation?: boolean};\n return setupState.hideProjectNavigation === undefined ? (\n <WorkspaceSetupPending />\n ) : (\n <MainLayout\n navigation={navigation}\n hideProjectNavigation={setupState.hideProjectNavigation}\n />\n );\n },\n });\n const projectLayout = createRoute({\n getParentRoute: () => workspaceLayout,\n path: '/projects/$pid',\n component: () => {\n const {ProjectLayoutGuard} = useChrome();\n return <ProjectLayoutGuard />;\n },\n });\n const workspaceSettings = createRoute({\n getParentRoute: () => workspaceLayout,\n path: '/settings',\n component: () => {\n const workspace = useActiveWorkspace();\n return (\n <div className=\"flex w-full flex-col gap-24\">\n <header className=\"flex flex-col gap-6\">\n <Header variant=\"h2\">Workspace settings</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Configure {workspace.name}.\n </Text>\n </header>\n\n <div className=\"grid grid-cols-[180px_minmax(0,1fr)] gap-32 max-[760px]:grid-cols-1\">\n <SettingsNav entries={settingsSections} />\n <Outlet />\n </div>\n </div>\n );\n },\n });\n return {\n anchors: {root: rootRoute, workspaceLayout, projectLayout, workspaceSettings},\n rootRoute,\n workspaceLayout,\n projectLayout,\n workspaceSettings,\n };\n}\n"],"names":["ShipfoxLoader","Header","Text","createRootRouteWithContext","createRoute","Outlet","redirect","MainLayout","NotFoundPage","SettingsNav","useActiveWorkspace","anchorPaths","useChrome","rememberLastWorkspaceId","WorkspaceLayoutErrorRoute","WorkspaceSetupPending","routePathForAnchor","buildAnchorSkeleton","navigation","settingsSections","rootRoute","component","notFoundComponent","workspaceLayout","getParentRoute","path","beforeLoad","context","params","location","auth","isLoading","queryClient","isAuthenticated","to","search","href","workspaces","some","workspace","id","wid","user","workspaceSetup","Error","workspaceId","pathname","pendingComponent","div","className","size","animation","color","background","errorComponent","setupState","useRouteContext","hideProjectNavigation","undefined","projectLayout","ProjectLayoutGuard","workspaceSettings","header","variant","name","entries","anchors","root"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/runtime/anchors.tsx"],"sourcesContent":["import {ShipfoxLoader} from '@shipfox/react-ui/loader';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {createRootRouteWithContext, createRoute, Outlet, redirect} from '@tanstack/react-router';\nimport {MainLayout} from '#components/main-layout.js';\nimport {NotFoundPage} from '#components/not-found-page.js';\nimport {SettingsNav} from '#components/settings-nav.js';\nimport type {NavTabEntry, SettingsSectionEntry} from '#contract.js';\nimport {useActiveWorkspace, useMaybeActiveWorkspace} from './active-workspace.js';\nimport {anchorPaths} from './anchor-paths.js';\nimport {useChrome} from './chrome-context.js';\nimport {rememberLastWorkspaceId} from './last-workspace.js';\nimport type {RouterContext} from './router-context.js';\nimport {\n WorkspaceLayoutErrorRoute,\n WorkspaceSetupPending,\n WorkspaceUnavailablePage,\n} from './workspace-setup.js';\n\nexport {routePathForAnchor} from './anchor-paths.js';\n\nexport function buildAnchorSkeleton({\n navigation,\n settingsSections,\n}: {\n navigation: readonly NavTabEntry[];\n settingsSections: readonly SettingsSectionEntry[];\n}) {\n const rootRoute = createRootRouteWithContext<RouterContext>()({\n component: Outlet,\n notFoundComponent: NotFoundPage,\n });\n const workspaceLayout = createRoute({\n getParentRoute: () => rootRoute,\n path: anchorPaths.workspaceLayout,\n beforeLoad: async ({context, params, location}) => {\n const auth = context.auth;\n if (!auth || auth.isLoading || !context.queryClient) return;\n if (!auth.isAuthenticated)\n throw redirect({to: '/auth/login' as never, search: {redirect: location.href} as never});\n if (!auth.workspaces.some((workspace) => workspace.id === params.wid))\n throw redirect({to: '/'});\n try {\n if (auth.user?.id) rememberLastWorkspaceId(auth.user.id, params.wid);\n } catch {\n // Local storage is best effort.\n }\n if (!context.workspaceSetup)\n throw new Error('Client composition includes workspace routes but no workspaceSetup gate.');\n return await context.workspaceSetup({\n queryClient: context.queryClient,\n workspaceId: params.wid,\n pathname: location.pathname,\n });\n },\n pendingComponent: () => (\n <div className=\"flex h-screen items-center justify-center\">\n <ShipfoxLoader size={64} animation=\"circular\" color=\"orange\" background=\"dark\" />\n </div>\n ),\n errorComponent: WorkspaceLayoutErrorRoute,\n component: () => {\n const setupState = workspaceLayout.useRouteContext() as {\n hideProjectNavigation?: boolean;\n unavailable?: boolean;\n };\n const workspace = useMaybeActiveWorkspace();\n return setupState.hideProjectNavigation === undefined ? (\n <WorkspaceSetupPending />\n ) : setupState.unavailable ? (\n <WorkspaceUnavailablePage workspaceName={workspace?.name} />\n ) : (\n <MainLayout\n navigation={navigation}\n hideProjectNavigation={setupState.hideProjectNavigation}\n />\n );\n },\n });\n const projectLayout = createRoute({\n getParentRoute: () => workspaceLayout,\n path: '/projects/$pid',\n component: () => {\n const {ProjectLayoutGuard} = useChrome();\n return <ProjectLayoutGuard />;\n },\n });\n const workspaceSettings = createRoute({\n getParentRoute: () => workspaceLayout,\n path: '/settings',\n component: () => {\n const workspace = useActiveWorkspace();\n return (\n <div className=\"flex w-full flex-col gap-24\">\n <header className=\"flex flex-col gap-6\">\n <Header variant=\"h2\">Workspace settings</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Configure {workspace.name}.\n </Text>\n </header>\n\n <div className=\"grid grid-cols-[180px_minmax(0,1fr)] gap-32 max-[760px]:grid-cols-1\">\n <SettingsNav entries={settingsSections} />\n <Outlet />\n </div>\n </div>\n );\n },\n });\n return {\n anchors: {root: rootRoute, workspaceLayout, projectLayout, workspaceSettings},\n rootRoute,\n workspaceLayout,\n projectLayout,\n workspaceSettings,\n };\n}\n"],"names":["ShipfoxLoader","Header","Text","createRootRouteWithContext","createRoute","Outlet","redirect","MainLayout","NotFoundPage","SettingsNav","useActiveWorkspace","useMaybeActiveWorkspace","anchorPaths","useChrome","rememberLastWorkspaceId","WorkspaceLayoutErrorRoute","WorkspaceSetupPending","WorkspaceUnavailablePage","routePathForAnchor","buildAnchorSkeleton","navigation","settingsSections","rootRoute","component","notFoundComponent","workspaceLayout","getParentRoute","path","beforeLoad","context","params","location","auth","isLoading","queryClient","isAuthenticated","to","search","href","workspaces","some","workspace","id","wid","user","workspaceSetup","Error","workspaceId","pathname","pendingComponent","div","className","size","animation","color","background","errorComponent","setupState","useRouteContext","hideProjectNavigation","undefined","unavailable","workspaceName","name","projectLayout","ProjectLayoutGuard","workspaceSettings","header","variant","entries","anchors","root"],"mappings":"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"}
@@ -1,10 +1,11 @@
1
- import type { ComposedRoute } from '#compose/compose-routes.js';
1
+ import type { ComposedLayout, ComposedRoute } from '#compose/compose-routes.js';
2
2
  import { buildAnchorSkeleton } from '#runtime/anchors.js';
3
3
  import type { RouteImpl } from '#runtime/define-route.js';
4
4
  export type ResolveRouteImpl = (specifier: string) => RouteImpl | Promise<RouteImpl>;
5
5
  export declare function assembleRouteTree(routes: readonly ComposedRoute[], options: {
6
+ layouts?: readonly ComposedLayout[];
6
7
  resolveImpl: ResolveRouteImpl;
7
8
  navigation: Parameters<typeof buildAnchorSkeleton>[0]['navigation'];
8
9
  settingsSections: Parameters<typeof buildAnchorSkeleton>[0]['settingsSections'];
9
- }): Promise<import("@tanstack/router-core").Route<import("@tanstack/router-core").Register, any, "/", "/", string, "__root__", undefined, {}, import("./router-context").RouterContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, readonly [...import("@tanstack/react-router").Route<unknown, import("@tanstack/router-core").AnyRoute, "/", "/" | `/${any}/`, string, "/" | `/${any}/`, undefined, import("@tanstack/router-core").ResolveParams<"/">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>[], import("@tanstack/router-core").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, import("./router-context").RouterContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/workspaces/$wid", "/workspaces/$wid", string, "/workspaces/$wid", undefined, import("@tanstack/router-core").ResolveParams<"/workspaces/$wid">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, ({ context, params, location }: import("@tanstack/router-core").BeforeLoadContextOptions<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, import("./router-context").RouterContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, undefined, import("@tanstack/router-core").ResolveParams<"/workspaces/$wid">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, "/workspaces/$wid", unknown, undefined>) => Promise<import("./workspace-setup").WorkspaceSetupState | undefined>, {}, undefined, readonly [...import("@tanstack/react-router").Route<unknown, import("@tanstack/router-core").AnyRoute, "/", "/" | `/${any}/`, string, "/" | `/${any}/`, undefined, import("@tanstack/router-core").ResolveParams<"/">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>[], import("@tanstack/router-core").Route<unknown, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, import("./router-context").RouterContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/workspaces/$wid", "/workspaces/$wid", string, "/workspaces/$wid", undefined, import("@tanstack/router-core").ResolveParams<"/workspaces/$wid">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, ({ context, params, location }: import("@tanstack/router-core").BeforeLoadContextOptions<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, import("./router-context").RouterContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, undefined, import("@tanstack/router-core").ResolveParams<"/workspaces/$wid">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, "/workspaces/$wid", unknown, undefined>) => Promise<import("./workspace-setup").WorkspaceSetupState | undefined>, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/projects/$pid", "/workspaces/$wid/projects/$pid", string, "/workspaces/$wid/projects/$pid", undefined, import("@tanstack/router-core").ResolveParams<"/projects/$pid">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, import("@tanstack/react-router").Route<unknown, import("@tanstack/router-core").AnyRoute, "/", "/" | `/${any}/`, string, "/" | `/${any}/`, undefined, import("@tanstack/router-core").ResolveParams<"/">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>[], unknown, unknown, unknown, undefined>, import("@tanstack/router-core").Route<unknown, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, import("./router-context").RouterContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/workspaces/$wid", "/workspaces/$wid", string, "/workspaces/$wid", undefined, import("@tanstack/router-core").ResolveParams<"/workspaces/$wid">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, ({ context, params, location }: import("@tanstack/router-core").BeforeLoadContextOptions<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, import("./router-context").RouterContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, undefined, import("@tanstack/router-core").ResolveParams<"/workspaces/$wid">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, "/workspaces/$wid", unknown, undefined>) => Promise<import("./workspace-setup").WorkspaceSetupState | undefined>, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/settings", "/workspaces/$wid/settings", string, "/workspaces/$wid/settings", undefined, import("@tanstack/router-core").ResolveParams<"/settings">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, import("@tanstack/react-router").Route<unknown, import("@tanstack/router-core").AnyRoute, "/", "/" | `/${any}/`, string, "/" | `/${any}/`, undefined, import("@tanstack/router-core").ResolveParams<"/">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>[], unknown, unknown, unknown, undefined>], unknown, unknown, unknown, undefined>], unknown, unknown, unknown, undefined>>;
10
+ }): Promise<import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, import("./router-context").RouterContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>>;
10
11
  //# sourceMappingURL=assemble-route-tree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assemble-route-tree.d.ts","sourceRoot":"","sources":["../../src/runtime/assemble-route-tree.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAC,mBAAmB,EAAqB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAErF,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,OAAO,EAAE;IACP,WAAW,EAAE,gBAAgB,CAAC;IAC9B,UAAU,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACpE,gBAAgB,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;CACjF,o+MA4BF"}
1
+ {"version":3,"file":"assemble-route-tree.d.ts","sourceRoot":"","sources":["../../src/runtime/assemble-route-tree.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,cAAc,EAAE,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAG9E,OAAO,EAAC,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAkCrF,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,OAAO,EAAE;IACP,OAAO,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACpC,WAAW,EAAE,gBAAgB,CAAC;IAC9B,UAAU,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACpE,gBAAgB,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;CACjF,4SA8EF"}
@@ -1,19 +1,90 @@
1
1
  import { createRoute } from '@tanstack/react-router';
2
- import { buildAnchorSkeleton, routePathForAnchor } from '#runtime/anchors.js';
2
+ import { routePathForParent } from '#runtime/anchor-paths.js';
3
+ import { buildAnchorSkeleton } from '#runtime/anchors.js';
4
+ const shellAnchors = [
5
+ 'root',
6
+ 'workspaceLayout',
7
+ 'projectLayout',
8
+ 'workspaceSettings'
9
+ ];
10
+ function isShellAnchor(parent) {
11
+ return shellAnchors.includes(parent);
12
+ }
13
+ function orderLayouts(layouts) {
14
+ const byId = new Map(layouts.map((layout)=>[
15
+ layout.id,
16
+ layout
17
+ ]));
18
+ const ordered = [];
19
+ const visiting = new Set();
20
+ const visited = new Set();
21
+ function visit(layout) {
22
+ if (visited.has(layout.id)) return;
23
+ if (!isShellAnchor(layout.parent)) {
24
+ if (visiting.has(layout.id)) throw new Error(`Layout "${layout.id}" has a cyclic parent reference.`);
25
+ const parent = byId.get(layout.parent);
26
+ if (!parent) throw new Error(`Layout "${layout.id}" targets missing parent "${layout.parent}".`);
27
+ visiting.add(layout.id);
28
+ visit(parent);
29
+ visiting.delete(layout.id);
30
+ }
31
+ visited.add(layout.id);
32
+ ordered.push(layout);
33
+ }
34
+ for (const layout of layouts)visit(layout);
35
+ return ordered;
36
+ }
3
37
  export async function assembleRouteTree(routes, options) {
38
+ const layouts = orderLayouts(options.layouts ?? []);
39
+ const layoutPaths = new Map(layouts.map((layout)=>[
40
+ layout.id,
41
+ layout.path
42
+ ]));
4
43
  const skeleton = buildAnchorSkeleton(options);
5
- const children = await Promise.all(routes.map(async (route)=>{
44
+ const layoutRoutes = new Map();
45
+ for (const layout of layouts){
46
+ const impl = await options.resolveImpl(layout.impl);
47
+ const parentRoute = isShellAnchor(layout.parent) ? skeleton.anchors[layout.parent] : layoutRoutes.get(layout.parent);
48
+ if (!parentRoute) throw new Error(`Missing layout parent "${layout.parent}".`);
49
+ layoutRoutes.set(layout.id, createRoute({
50
+ getParentRoute: ()=>parentRoute,
51
+ path: routePathForParent(layout.parent, layout.path, layoutPaths),
52
+ ...impl.options
53
+ }));
54
+ }
55
+ const routeEntries = await Promise.all(routes.map(async (route)=>{
6
56
  const impl = await options.resolveImpl(route.impl);
57
+ const parentRoute = isShellAnchor(route.parent) ? skeleton.anchors[route.parent] : layoutRoutes.get(route.parent);
58
+ if (!parentRoute) throw new Error(`Missing route parent "${route.parent}".`);
7
59
  return {
8
60
  parent: route.parent,
9
61
  route: createRoute({
10
- getParentRoute: ()=>skeleton.anchors[route.parent],
11
- path: routePathForAnchor(route.parent, route.path),
62
+ getParentRoute: ()=>parentRoute,
63
+ path: routePathForParent(route.parent, route.path, layoutPaths),
12
64
  ...impl.options
13
65
  })
14
66
  };
15
67
  }));
16
- const childrenFor = (anchor)=>children.filter((child)=>child.parent === anchor).map((child)=>child.route);
68
+ const routeChildrenFor = (parent)=>routeEntries.filter((entry)=>entry.parent === parent).map((entry)=>entry.route);
69
+ const layoutTrees = new Map();
70
+ function layoutTree(layoutId) {
71
+ const existing = layoutTrees.get(layoutId);
72
+ if (existing) return existing;
73
+ const layout = layouts.find((candidate)=>candidate.id === layoutId);
74
+ const route = layoutRoutes.get(layoutId);
75
+ if (!layout || !route) throw new Error(`Missing layout "${layoutId}".`);
76
+ const children = [
77
+ ...routeChildrenFor(layoutId),
78
+ ...layouts.filter((candidate)=>candidate.parent === layoutId).map((candidate)=>layoutTree(candidate.id))
79
+ ];
80
+ const tree = route.addChildren(children);
81
+ layoutTrees.set(layoutId, tree);
82
+ return tree;
83
+ }
84
+ const childrenFor = (parent)=>[
85
+ ...routeChildrenFor(parent),
86
+ ...layouts.filter((layout)=>layout.parent === parent).map((layout)=>layoutTree(layout.id))
87
+ ];
17
88
  const projectLayout = skeleton.projectLayout.addChildren(childrenFor('projectLayout'));
18
89
  const workspaceSettings = skeleton.workspaceSettings.addChildren(childrenFor('workspaceSettings'));
19
90
  const workspaceLayout = skeleton.workspaceLayout.addChildren([
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/assemble-route-tree.ts"],"sourcesContent":["import {createRoute} from '@tanstack/react-router';\nimport type {ComposedRoute} from '#compose/compose-routes.js';\nimport {buildAnchorSkeleton, routePathForAnchor} from '#runtime/anchors.js';\nimport type {RouteImpl} from '#runtime/define-route.js';\n\nexport type ResolveRouteImpl = (specifier: string) => RouteImpl | Promise<RouteImpl>;\n\nexport async function assembleRouteTree(\n routes: readonly ComposedRoute[],\n options: {\n resolveImpl: ResolveRouteImpl;\n navigation: Parameters<typeof buildAnchorSkeleton>[0]['navigation'];\n settingsSections: Parameters<typeof buildAnchorSkeleton>[0]['settingsSections'];\n },\n) {\n const skeleton = buildAnchorSkeleton(options);\n const children = await Promise.all(\n routes.map(async (route) => {\n const impl = await options.resolveImpl(route.impl);\n return {\n parent: route.parent,\n route: createRoute({\n getParentRoute: () => skeleton.anchors[route.parent] as never,\n path: routePathForAnchor(route.parent, route.path),\n ...impl.options,\n } as never),\n };\n }),\n );\n const childrenFor = (anchor: keyof typeof skeleton.anchors) =>\n children.filter((child) => child.parent === anchor).map((child) => child.route);\n const projectLayout = skeleton.projectLayout.addChildren(childrenFor('projectLayout'));\n const workspaceSettings = skeleton.workspaceSettings.addChildren(\n childrenFor('workspaceSettings'),\n );\n const workspaceLayout = skeleton.workspaceLayout.addChildren([\n ...childrenFor('workspaceLayout'),\n projectLayout,\n workspaceSettings,\n ]);\n return skeleton.rootRoute.addChildren([...childrenFor('root'), workspaceLayout]);\n}\n"],"names":["createRoute","buildAnchorSkeleton","routePathForAnchor","assembleRouteTree","routes","options","skeleton","children","Promise","all","map","route","impl","resolveImpl","parent","getParentRoute","anchors","path","childrenFor","anchor","filter","child","projectLayout","addChildren","workspaceSettings","workspaceLayout","rootRoute"],"mappings":"AAAA,SAAQA,WAAW,QAAO,yBAAyB;AAEnD,SAAQC,mBAAmB,EAAEC,kBAAkB,QAAO,sBAAsB;AAK5E,OAAO,eAAeC,kBACpBC,MAAgC,EAChCC,OAIC;IAED,MAAMC,WAAWL,oBAAoBI;IACrC,MAAME,WAAW,MAAMC,QAAQC,GAAG,CAChCL,OAAOM,GAAG,CAAC,OAAOC;QAChB,MAAMC,OAAO,MAAMP,QAAQQ,WAAW,CAACF,MAAMC,IAAI;QACjD,OAAO;YACLE,QAAQH,MAAMG,MAAM;YACpBH,OAAOX,YAAY;gBACjBe,gBAAgB,IAAMT,SAASU,OAAO,CAACL,MAAMG,MAAM,CAAC;gBACpDG,MAAMf,mBAAmBS,MAAMG,MAAM,EAAEH,MAAMM,IAAI;gBACjD,GAAGL,KAAKP,OAAO;YACjB;QACF;IACF;IAEF,MAAMa,cAAc,CAACC,SACnBZ,SAASa,MAAM,CAAC,CAACC,QAAUA,MAAMP,MAAM,KAAKK,QAAQT,GAAG,CAAC,CAACW,QAAUA,MAAMV,KAAK;IAChF,MAAMW,gBAAgBhB,SAASgB,aAAa,CAACC,WAAW,CAACL,YAAY;IACrE,MAAMM,oBAAoBlB,SAASkB,iBAAiB,CAACD,WAAW,CAC9DL,YAAY;IAEd,MAAMO,kBAAkBnB,SAASmB,eAAe,CAACF,WAAW,CAAC;WACxDL,YAAY;QACfI;QACAE;KACD;IACD,OAAOlB,SAASoB,SAAS,CAACH,WAAW,CAAC;WAAIL,YAAY;QAASO;KAAgB;AACjF"}
1
+ {"version":3,"sources":["../../src/runtime/assemble-route-tree.ts"],"sourcesContent":["import {type AnyRoute, createRoute} from '@tanstack/react-router';\nimport type {ComposedLayout, ComposedRoute} from '#compose/compose-routes.js';\nimport type {RouteParentId} from '#contract.js';\nimport {routePathForParent} from '#runtime/anchor-paths.js';\nimport {buildAnchorSkeleton} from '#runtime/anchors.js';\nimport type {RouteImpl} from '#runtime/define-route.js';\n\nexport type ResolveRouteImpl = (specifier: string) => RouteImpl | Promise<RouteImpl>;\n\nconst shellAnchors = ['root', 'workspaceLayout', 'projectLayout', 'workspaceSettings'] as const;\n\nfunction isShellAnchor(parent: RouteParentId): parent is (typeof shellAnchors)[number] {\n return shellAnchors.includes(parent as (typeof shellAnchors)[number]);\n}\n\nfunction orderLayouts(layouts: readonly ComposedLayout[]): ComposedLayout[] {\n const byId = new Map(layouts.map((layout) => [layout.id, layout]));\n const ordered: ComposedLayout[] = [];\n const visiting = new Set<string>();\n const visited = new Set<string>();\n\n function visit(layout: ComposedLayout): void {\n if (visited.has(layout.id)) return;\n if (!isShellAnchor(layout.parent)) {\n if (visiting.has(layout.id))\n throw new Error(`Layout \"${layout.id}\" has a cyclic parent reference.`);\n const parent = byId.get(layout.parent);\n if (!parent)\n throw new Error(`Layout \"${layout.id}\" targets missing parent \"${layout.parent}\".`);\n visiting.add(layout.id);\n visit(parent);\n visiting.delete(layout.id);\n }\n visited.add(layout.id);\n ordered.push(layout);\n }\n\n for (const layout of layouts) visit(layout);\n return ordered;\n}\n\nexport async function assembleRouteTree(\n routes: readonly ComposedRoute[],\n options: {\n layouts?: readonly ComposedLayout[];\n resolveImpl: ResolveRouteImpl;\n navigation: Parameters<typeof buildAnchorSkeleton>[0]['navigation'];\n settingsSections: Parameters<typeof buildAnchorSkeleton>[0]['settingsSections'];\n },\n) {\n const layouts = orderLayouts(options.layouts ?? []);\n const layoutPaths = new Map(layouts.map((layout) => [layout.id, layout.path]));\n const skeleton = buildAnchorSkeleton(options);\n const layoutRoutes = new Map<string, AnyRoute>();\n\n for (const layout of layouts) {\n const impl = await options.resolveImpl(layout.impl);\n const parentRoute = isShellAnchor(layout.parent)\n ? skeleton.anchors[layout.parent]\n : layoutRoutes.get(layout.parent);\n if (!parentRoute) throw new Error(`Missing layout parent \"${layout.parent}\".`);\n layoutRoutes.set(\n layout.id,\n createRoute({\n getParentRoute: () => parentRoute as never,\n path: routePathForParent(layout.parent, layout.path, layoutPaths),\n ...impl.options,\n } as never) as unknown as AnyRoute,\n );\n }\n\n const routeEntries: Array<{parent: RouteParentId; route: AnyRoute}> = await Promise.all(\n routes.map(async (route) => {\n const impl = await options.resolveImpl(route.impl);\n const parentRoute = isShellAnchor(route.parent)\n ? skeleton.anchors[route.parent]\n : layoutRoutes.get(route.parent);\n if (!parentRoute) throw new Error(`Missing route parent \"${route.parent}\".`);\n return {\n parent: route.parent,\n route: createRoute({\n getParentRoute: () => parentRoute as never,\n path: routePathForParent(route.parent, route.path, layoutPaths),\n ...impl.options,\n } as never) as unknown as AnyRoute,\n };\n }),\n );\n\n const routeChildrenFor = (parent: RouteParentId) =>\n routeEntries.filter((entry) => entry.parent === parent).map((entry) => entry.route);\n const layoutTrees = new Map<string, AnyRoute>();\n function layoutTree(layoutId: string): AnyRoute {\n const existing = layoutTrees.get(layoutId);\n if (existing) return existing;\n const layout = layouts.find((candidate) => candidate.id === layoutId);\n const route = layoutRoutes.get(layoutId);\n if (!layout || !route) throw new Error(`Missing layout \"${layoutId}\".`);\n const children = [\n ...routeChildrenFor(layoutId),\n ...layouts\n .filter((candidate) => candidate.parent === layoutId)\n .map((candidate) => layoutTree(candidate.id)),\n ];\n const tree = route.addChildren(children as never) as unknown as AnyRoute;\n layoutTrees.set(layoutId, tree);\n return tree;\n }\n\n const childrenFor = (parent: RouteParentId) => [\n ...routeChildrenFor(parent),\n ...layouts.filter((layout) => layout.parent === parent).map((layout) => layoutTree(layout.id)),\n ];\n const projectLayout = skeleton.projectLayout.addChildren(childrenFor('projectLayout') as never);\n const workspaceSettings = skeleton.workspaceSettings.addChildren(\n childrenFor('workspaceSettings') as never,\n );\n const workspaceLayout = skeleton.workspaceLayout.addChildren([\n ...childrenFor('workspaceLayout'),\n projectLayout,\n workspaceSettings,\n ] as never);\n return skeleton.rootRoute.addChildren([\n ...childrenFor('root'),\n workspaceLayout,\n ] as never) as unknown as typeof skeleton.rootRoute;\n}\n"],"names":["createRoute","routePathForParent","buildAnchorSkeleton","shellAnchors","isShellAnchor","parent","includes","orderLayouts","layouts","byId","Map","map","layout","id","ordered","visiting","Set","visited","visit","has","Error","get","add","delete","push","assembleRouteTree","routes","options","layoutPaths","path","skeleton","layoutRoutes","impl","resolveImpl","parentRoute","anchors","set","getParentRoute","routeEntries","Promise","all","route","routeChildrenFor","filter","entry","layoutTrees","layoutTree","layoutId","existing","find","candidate","children","tree","addChildren","childrenFor","projectLayout","workspaceSettings","workspaceLayout","rootRoute"],"mappings":"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"}
@@ -2,6 +2,12 @@ import type { ComponentType, PropsWithChildren } from 'react';
2
2
  export interface ChromeSlots {
3
3
  ProjectBreadcrumb: ComponentType;
4
4
  ProjectLayoutGuard: ComponentType;
5
+ /**
6
+ * Optional content rendered in the account menu before the shell-owned logout
7
+ * action. The composing component must render one DropdownMenuItem or return
8
+ * null, and owns whether this content renders from the current session.
9
+ */
10
+ AccountMenuEntry?: ComponentType;
5
11
  }
6
12
  export declare function ChromeProvider({ chrome, children, }: PropsWithChildren<{
7
13
  chrome: ChromeSlots | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"chrome-context.d.ts","sourceRoot":"","sources":["../../src/runtime/chrome-context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAG5D,MAAM,WAAW,WAAW;IAC1B,iBAAiB,EAAE,aAAa,CAAC;IACjC,kBAAkB,EAAE,aAAa,CAAC;CACnC;AAID,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,QAAQ,GACT,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;CAAC,CAAC,+BAEtD;AAED,wBAAgB,SAAS,IAAI,WAAW,CAIvC"}
1
+ {"version":3,"file":"chrome-context.d.ts","sourceRoot":"","sources":["../../src/runtime/chrome-context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAG5D,MAAM,WAAW,WAAW;IAC1B,iBAAiB,EAAE,aAAa,CAAC;IACjC,kBAAkB,EAAE,aAAa,CAAC;IAClC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,aAAa,CAAC;CAClC;AAID,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,QAAQ,GACT,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;CAAC,CAAC,+BAEtD;AAED,wBAAgB,SAAS,IAAI,WAAW,CAIvC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/chrome-context.tsx"],"sourcesContent":["import type {ComponentType, PropsWithChildren} from 'react';\nimport {createContext, useContext} from 'react';\n\nexport interface ChromeSlots {\n ProjectBreadcrumb: ComponentType;\n ProjectLayoutGuard: ComponentType;\n}\n\nconst ChromeContext = createContext<ChromeSlots | undefined>(undefined);\n\nexport function ChromeProvider({\n chrome,\n children,\n}: PropsWithChildren<{chrome: ChromeSlots | undefined}>) {\n return <ChromeContext.Provider value={chrome}>{children}</ChromeContext.Provider>;\n}\n\nexport function useChrome(): ChromeSlots {\n const chrome = useContext(ChromeContext);\n if (!chrome) throw new Error('Client composition must provide browser chrome slots.');\n return chrome;\n}\n"],"names":["createContext","useContext","ChromeContext","undefined","ChromeProvider","chrome","children","Provider","value","useChrome","Error"],"mappings":";AACA,SAAQA,aAAa,EAAEC,UAAU,QAAO,QAAQ;AAOhD,MAAMC,8BAAgBF,cAAuCG;AAE7D,OAAO,SAASC,eAAe,EAC7BC,MAAM,EACNC,QAAQ,EAC6C;IACrD,qBAAO,KAACJ,cAAcK,QAAQ;QAACC,OAAOH;kBAASC;;AACjD;AAEA,OAAO,SAASG;IACd,MAAMJ,SAASJ,WAAWC;IAC1B,IAAI,CAACG,QAAQ,MAAM,IAAIK,MAAM;IAC7B,OAAOL;AACT"}
1
+ {"version":3,"sources":["../../src/runtime/chrome-context.tsx"],"sourcesContent":["import type {ComponentType, PropsWithChildren} from 'react';\nimport {createContext, useContext} from 'react';\n\nexport interface ChromeSlots {\n ProjectBreadcrumb: ComponentType;\n ProjectLayoutGuard: ComponentType;\n /**\n * Optional content rendered in the account menu before the shell-owned logout\n * action. The composing component must render one DropdownMenuItem or return\n * null, and owns whether this content renders from the current session.\n */\n AccountMenuEntry?: ComponentType;\n}\n\nconst ChromeContext = createContext<ChromeSlots | undefined>(undefined);\n\nexport function ChromeProvider({\n chrome,\n children,\n}: PropsWithChildren<{chrome: ChromeSlots | undefined}>) {\n return <ChromeContext.Provider value={chrome}>{children}</ChromeContext.Provider>;\n}\n\nexport function useChrome(): ChromeSlots {\n const chrome = useContext(ChromeContext);\n if (!chrome) throw new Error('Client composition must provide browser chrome slots.');\n return chrome;\n}\n"],"names":["createContext","useContext","ChromeContext","undefined","ChromeProvider","chrome","children","Provider","value","useChrome","Error"],"mappings":";AACA,SAAQA,aAAa,EAAEC,UAAU,QAAO,QAAQ;AAahD,MAAMC,8BAAgBF,cAAuCG;AAE7D,OAAO,SAASC,eAAe,EAC7BC,MAAM,EACNC,QAAQ,EAC6C;IACrD,qBAAO,KAACJ,cAAcK,QAAQ;QAACC,OAAOH;kBAASC;;AACjD;AAEA,OAAO,SAASG;IACd,MAAMJ,SAASJ,WAAWC;IAC1B,IAAI,CAACG,QAAQ,MAAM,IAAIK,MAAM;IAC7B,OAAOL;AACT"}
@@ -18,6 +18,7 @@ export * from './chrome-context.js';
18
18
  export * from './compose-client-app.js';
19
19
  export * from './define-route.js';
20
20
  export * from './last-workspace.js';
21
+ export * from './layout-navigation.js';
21
22
  export * from './nav-order.js';
22
23
  export * from './route-inputs.js';
23
24
  export * from './router-context.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,SAAS,EAAE,KAAK,cAAc,EAAC,MAAM,2BAA2B,CAAC;AACtF,OAAO,EAAC,cAAc,EAAE,KAAK,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACxF,OAAO,EAAC,iBAAiB,EAAC,MAAM,mCAAmC,CAAC;AACpE,YAAY,EACV,oBAAoB,EACpB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,sBAAsB,EAAE,cAAc,EAAC,MAAM,8BAA8B,CAAC;AACpF,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,SAAS,EAAE,KAAK,cAAc,EAAC,MAAM,2BAA2B,CAAC;AACtF,OAAO,EAAC,cAAc,EAAE,KAAK,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACxF,OAAO,EAAC,iBAAiB,EAAC,MAAM,mCAAmC,CAAC;AACpE,YAAY,EACV,oBAAoB,EACpB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,sBAAsB,EAAE,cAAc,EAAC,MAAM,8BAA8B,CAAC;AACpF,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC"}
@@ -17,6 +17,7 @@ export * from './chrome-context.js';
17
17
  export * from './compose-client-app.js';
18
18
  export * from './define-route.js';
19
19
  export * from './last-workspace.js';
20
+ export * from './layout-navigation.js';
20
21
  export * from './nav-order.js';
21
22
  export * from './route-inputs.js';
22
23
  export * from './router-context.js';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/index.ts"],"sourcesContent":["export {AuthActions, AuthShell, type AuthShellProps} from '#components/auth-shell.js';\nexport {WorkspaceCrumb, type WorkspaceCrumbProps} from '#components/workspace-crumb.js';\nexport {WorkspaceSwitcher} from '#components/workspace-switcher.js';\nexport type {\n AuthenticatedSession,\n UserIdentity,\n WorkspaceMembership,\n WorkspaceSummary,\n} from '#core/session.js';\nexport {toAuthenticatedSession, toUserIdentity} from '#hooks/api/session-mapper.js';\nexport * from '../compose/compose-client-features.js';\nexport * from '../compose/compose-routes.js';\nexport * from '../compose/errors.js';\nexport * from '../compose/merge-config.js';\nexport * from '../compose/normalize-route-path.js';\nexport * from '../compose/validate-providers.js';\nexport * from '../compose/validate-registries.js';\nexport * from './active-workspace.js';\nexport * from './anchor-paths.js';\nexport * from './anchors.js';\nexport * from './auth.js';\nexport * from './chrome-context.js';\nexport * from './compose-client-app.js';\nexport * from './define-route.js';\nexport * from './last-workspace.js';\nexport * from './nav-order.js';\nexport * from './route-inputs.js';\nexport * from './router-context.js';\nexport * from './workspace-setup.js';\n"],"names":["AuthActions","AuthShell","WorkspaceCrumb","WorkspaceSwitcher","toAuthenticatedSession","toUserIdentity"],"mappings":"AAAA,SAAQA,WAAW,EAAEC,SAAS,QAA4B,4BAA4B;AACtF,SAAQC,cAAc,QAAiC,iCAAiC;AACxF,SAAQC,iBAAiB,QAAO,oCAAoC;AAOpE,SAAQC,sBAAsB,EAAEC,cAAc,QAAO,+BAA+B;AACpF,cAAc,wCAAwC;AACtD,cAAc,+BAA+B;AAC7C,cAAc,uBAAuB;AACrC,cAAc,6BAA6B;AAC3C,cAAc,qCAAqC;AACnD,cAAc,mCAAmC;AACjD,cAAc,oCAAoC;AAClD,cAAc,wBAAwB;AACtC,cAAc,oBAAoB;AAClC,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,sBAAsB;AACpC,cAAc,0BAA0B;AACxC,cAAc,oBAAoB;AAClC,cAAc,sBAAsB;AACpC,cAAc,iBAAiB;AAC/B,cAAc,oBAAoB;AAClC,cAAc,sBAAsB;AACpC,cAAc,uBAAuB"}
1
+ {"version":3,"sources":["../../src/runtime/index.ts"],"sourcesContent":["export {AuthActions, AuthShell, type AuthShellProps} from '#components/auth-shell.js';\nexport {WorkspaceCrumb, type WorkspaceCrumbProps} from '#components/workspace-crumb.js';\nexport {WorkspaceSwitcher} from '#components/workspace-switcher.js';\nexport type {\n AuthenticatedSession,\n UserIdentity,\n WorkspaceMembership,\n WorkspaceSummary,\n} from '#core/session.js';\nexport {toAuthenticatedSession, toUserIdentity} from '#hooks/api/session-mapper.js';\nexport * from '../compose/compose-client-features.js';\nexport * from '../compose/compose-routes.js';\nexport * from '../compose/errors.js';\nexport * from '../compose/merge-config.js';\nexport * from '../compose/normalize-route-path.js';\nexport * from '../compose/validate-providers.js';\nexport * from '../compose/validate-registries.js';\nexport * from './active-workspace.js';\nexport * from './anchor-paths.js';\nexport * from './anchors.js';\nexport * from './auth.js';\nexport * from './chrome-context.js';\nexport * from './compose-client-app.js';\nexport * from './define-route.js';\nexport * from './last-workspace.js';\nexport * from './layout-navigation.js';\nexport * from './nav-order.js';\nexport * from './route-inputs.js';\nexport * from './router-context.js';\nexport * from './workspace-setup.js';\n"],"names":["AuthActions","AuthShell","WorkspaceCrumb","WorkspaceSwitcher","toAuthenticatedSession","toUserIdentity"],"mappings":"AAAA,SAAQA,WAAW,EAAEC,SAAS,QAA4B,4BAA4B;AACtF,SAAQC,cAAc,QAAiC,iCAAiC;AACxF,SAAQC,iBAAiB,QAAO,oCAAoC;AAOpE,SAAQC,sBAAsB,EAAEC,cAAc,QAAO,+BAA+B;AACpF,cAAc,wCAAwC;AACtD,cAAc,+BAA+B;AAC7C,cAAc,uBAAuB;AACrC,cAAc,6BAA6B;AAC3C,cAAc,qCAAqC;AACnD,cAAc,mCAAmC;AACjD,cAAc,oCAAoC;AAClD,cAAc,wBAAwB;AACtC,cAAc,oBAAoB;AAClC,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,sBAAsB;AACpC,cAAc,0BAA0B;AACxC,cAAc,oBAAoB;AAClC,cAAc,sBAAsB;AACpC,cAAc,yBAAyB;AACvC,cAAc,iBAAiB;AAC/B,cAAc,oBAAoB;AAClC,cAAc,sBAAsB;AACpC,cAAc,uBAAuB"}
@@ -0,0 +1,7 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ import type { ClientFeature, LayoutNavigationEntry } from '#contract.js';
3
+ export declare function LayoutNavigationProvider({ features, children, }: PropsWithChildren<{
4
+ features: readonly ClientFeature[];
5
+ }>): import("react").JSX.Element;
6
+ export declare function useLayoutNavigation(layoutId: string): readonly LayoutNavigationEntry[];
7
+ //# sourceMappingURL=layout-navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout-navigation.d.ts","sourceRoot":"","sources":["../../src/runtime/layout-navigation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAE7C,OAAO,KAAK,EAAC,aAAa,EAAE,qBAAqB,EAAC,MAAM,cAAc,CAAC;AAOvE,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,QAAQ,GACT,EAAE,iBAAiB,CAAC;IAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAA;CAAC,CAAC,+BAKzD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,qBAAqB,EAAE,CAEtF"}
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext, useMemo } from 'react';
3
+ import { layoutNavigationRegistry } from './registries.js';
4
+ const LayoutNavigationContext = /*#__PURE__*/ createContext(new Map());
5
+ export function LayoutNavigationProvider({ features, children }) {
6
+ const registry = useMemo(()=>layoutNavigationRegistry(features), [
7
+ features
8
+ ]);
9
+ return /*#__PURE__*/ _jsx(LayoutNavigationContext.Provider, {
10
+ value: registry,
11
+ children: children
12
+ });
13
+ }
14
+ export function useLayoutNavigation(layoutId) {
15
+ return useContext(LayoutNavigationContext).get(layoutId) ?? [];
16
+ }
17
+
18
+ //# sourceMappingURL=layout-navigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/runtime/layout-navigation.tsx"],"sourcesContent":["import type {PropsWithChildren} from 'react';\nimport {createContext, useContext, useMemo} from 'react';\nimport type {ClientFeature, LayoutNavigationEntry} from '#contract.js';\nimport {layoutNavigationRegistry} from './registries.js';\n\ntype LayoutNavigationRegistry = ReadonlyMap<string, readonly LayoutNavigationEntry[]>;\n\nconst LayoutNavigationContext = createContext<LayoutNavigationRegistry>(new Map());\n\nexport function LayoutNavigationProvider({\n features,\n children,\n}: PropsWithChildren<{features: readonly ClientFeature[]}>) {\n const registry = useMemo(() => layoutNavigationRegistry(features), [features]);\n return (\n <LayoutNavigationContext.Provider value={registry}>{children}</LayoutNavigationContext.Provider>\n );\n}\n\nexport function useLayoutNavigation(layoutId: string): readonly LayoutNavigationEntry[] {\n return useContext(LayoutNavigationContext).get(layoutId) ?? [];\n}\n"],"names":["createContext","useContext","useMemo","layoutNavigationRegistry","LayoutNavigationContext","Map","LayoutNavigationProvider","features","children","registry","Provider","value","useLayoutNavigation","layoutId","get"],"mappings":";AACA,SAAQA,aAAa,EAAEC,UAAU,EAAEC,OAAO,QAAO,QAAQ;AAEzD,SAAQC,wBAAwB,QAAO,kBAAkB;AAIzD,MAAMC,wCAA0BJ,cAAwC,IAAIK;AAE5E,OAAO,SAASC,yBAAyB,EACvCC,QAAQ,EACRC,QAAQ,EACgD;IACxD,MAAMC,WAAWP,QAAQ,IAAMC,yBAAyBI,WAAW;QAACA;KAAS;IAC7E,qBACE,KAACH,wBAAwBM,QAAQ;QAACC,OAAOF;kBAAWD;;AAExD;AAEA,OAAO,SAASI,oBAAoBC,QAAgB;IAClD,OAAOZ,WAAWG,yBAAyBU,GAAG,CAACD,aAAa,EAAE;AAChE"}
@@ -1 +1 @@
1
- {"version":3,"file":"provider-stack.d.ts","sourceRoot":"","sources":["../../src/runtime/provider-stack.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,WAAW,EAAsB,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAC,KAAK,WAAW,EAA4B,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAC,iBAAiB,EAAY,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAChD,OAAO,EAAc,KAAK,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAE7D,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAE5C,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,WAAW,EACX,KAAK,EACL,IAAI,EACJ,QAAQ,GACT,EAAE,iBAAiB,CAAC;IACnB,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;CAC1C,CAAC,+BAiBD"}
1
+ {"version":3,"file":"provider-stack.d.ts","sourceRoot":"","sources":["../../src/runtime/provider-stack.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,WAAW,EAAsB,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAC,KAAK,WAAW,EAA4B,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAC,iBAAiB,EAAY,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAChD,OAAO,EAAc,KAAK,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAG7D,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAE5C,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,WAAW,EACX,KAAK,EACL,IAAI,EACJ,QAAQ,GACT,EAAE,iBAAiB,CAAC;IACnB,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;CAC1C,CAAC,+BAmBD"}