@cohesivesystems/presentation-react 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/LICENSE +55 -0
  2. package/dist/collection-chrome-slot-renderer-registry.d.ts +12 -0
  3. package/dist/collection-chrome-slot-renderer-registry.d.ts.map +1 -0
  4. package/dist/collection-chrome-slot-renderer-registry.js +12 -0
  5. package/dist/collection-chrome-slot-renderer-registry.js.map +1 -0
  6. package/dist/collection-selection-state-context.d.ts +6 -0
  7. package/dist/collection-selection-state-context.d.ts.map +1 -0
  8. package/dist/collection-selection-state-context.js +25 -0
  9. package/dist/collection-selection-state-context.js.map +1 -0
  10. package/dist/collection-selection-state.d.ts +3 -0
  11. package/dist/collection-selection-state.d.ts.map +1 -0
  12. package/dist/collection-selection-state.js +52 -0
  13. package/dist/collection-selection-state.js.map +1 -0
  14. package/dist/document-workspace-runtime.d.ts +262 -0
  15. package/dist/document-workspace-runtime.d.ts.map +1 -0
  16. package/dist/document-workspace-runtime.js +699 -0
  17. package/dist/document-workspace-runtime.js.map +1 -0
  18. package/dist/index.d.ts +51 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +51 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/input-form-endpoint-runtime.d.ts +140 -0
  23. package/dist/input-form-endpoint-runtime.d.ts.map +1 -0
  24. package/dist/input-form-endpoint-runtime.js +280 -0
  25. package/dist/input-form-endpoint-runtime.js.map +1 -0
  26. package/dist/local-flow-state-data-source-projection.d.ts +21 -0
  27. package/dist/local-flow-state-data-source-projection.d.ts.map +1 -0
  28. package/dist/local-flow-state-data-source-projection.js +65 -0
  29. package/dist/local-flow-state-data-source-projection.js.map +1 -0
  30. package/dist/navigation-runtime-context.d.ts +22 -0
  31. package/dist/navigation-runtime-context.d.ts.map +1 -0
  32. package/dist/navigation-runtime-context.js +23 -0
  33. package/dist/navigation-runtime-context.js.map +1 -0
  34. package/dist/navigation-shell-frame-renderer-registry.d.ts +20 -0
  35. package/dist/navigation-shell-frame-renderer-registry.d.ts.map +1 -0
  36. package/dist/navigation-shell-frame-renderer-registry.js +9 -0
  37. package/dist/navigation-shell-frame-renderer-registry.js.map +1 -0
  38. package/dist/navigation-shell-region-component-registry.d.ts +50 -0
  39. package/dist/navigation-shell-region-component-registry.d.ts.map +1 -0
  40. package/dist/navigation-shell-region-component-registry.js +44 -0
  41. package/dist/navigation-shell-region-component-registry.js.map +1 -0
  42. package/dist/navigation-shell-slot-renderer-registry.d.ts +22 -0
  43. package/dist/navigation-shell-slot-renderer-registry.d.ts.map +1 -0
  44. package/dist/navigation-shell-slot-renderer-registry.js +9 -0
  45. package/dist/navigation-shell-slot-renderer-registry.js.map +1 -0
  46. package/dist/page-host-projection.d.ts +127 -0
  47. package/dist/page-host-projection.d.ts.map +1 -0
  48. package/dist/page-host-projection.js +59 -0
  49. package/dist/page-host-projection.js.map +1 -0
  50. package/dist/page-host-renderer-registry.d.ts +72 -0
  51. package/dist/page-host-renderer-registry.d.ts.map +1 -0
  52. package/dist/page-host-renderer-registry.js +63 -0
  53. package/dist/page-host-renderer-registry.js.map +1 -0
  54. package/dist/presentation-action-group-runtime-options.d.ts +36 -0
  55. package/dist/presentation-action-group-runtime-options.d.ts.map +1 -0
  56. package/dist/presentation-action-group-runtime-options.js +50 -0
  57. package/dist/presentation-action-group-runtime-options.js.map +1 -0
  58. package/dist/presentation-action-runtime.d.ts +52 -0
  59. package/dist/presentation-action-runtime.d.ts.map +1 -0
  60. package/dist/presentation-action-runtime.js +78 -0
  61. package/dist/presentation-action-runtime.js.map +1 -0
  62. package/dist/presentation-data-source-binding-runtime.d.ts +3 -0
  63. package/dist/presentation-data-source-binding-runtime.d.ts.map +1 -0
  64. package/dist/presentation-data-source-binding-runtime.js +65 -0
  65. package/dist/presentation-data-source-binding-runtime.js.map +1 -0
  66. package/dist/presentation-data-source-binding.d.ts +12 -0
  67. package/dist/presentation-data-source-binding.d.ts.map +1 -0
  68. package/dist/presentation-data-source-binding.js +13 -0
  69. package/dist/presentation-data-source-binding.js.map +1 -0
  70. package/dist/presentation-flow-runtime.d.ts +139 -0
  71. package/dist/presentation-flow-runtime.d.ts.map +1 -0
  72. package/dist/presentation-flow-runtime.js +514 -0
  73. package/dist/presentation-flow-runtime.js.map +1 -0
  74. package/dist/presentation-module-context.d.ts +4 -0
  75. package/dist/presentation-module-context.d.ts.map +1 -0
  76. package/dist/presentation-module-context.js +6 -0
  77. package/dist/presentation-module-context.js.map +1 -0
  78. package/dist/presentation-module-provider.d.ts +7 -0
  79. package/dist/presentation-module-provider.d.ts.map +1 -0
  80. package/dist/presentation-module-provider.js +7 -0
  81. package/dist/presentation-module-provider.js.map +1 -0
  82. package/dist/presentation-projection-diagnostics-context.d.ts +8 -0
  83. package/dist/presentation-projection-diagnostics-context.d.ts.map +1 -0
  84. package/dist/presentation-projection-diagnostics-context.js +3 -0
  85. package/dist/presentation-projection-diagnostics-context.js.map +1 -0
  86. package/dist/presentation-projection-diagnostics-hooks.d.ts +4 -0
  87. package/dist/presentation-projection-diagnostics-hooks.d.ts.map +1 -0
  88. package/dist/presentation-projection-diagnostics-hooks.js +17 -0
  89. package/dist/presentation-projection-diagnostics-hooks.js.map +1 -0
  90. package/dist/presentation-projection-diagnostics-runtime.d.ts +12 -0
  91. package/dist/presentation-projection-diagnostics-runtime.d.ts.map +1 -0
  92. package/dist/presentation-projection-diagnostics-runtime.js +54 -0
  93. package/dist/presentation-projection-diagnostics-runtime.js.map +1 -0
  94. package/dist/presentation-projection-trace.d.ts +27 -0
  95. package/dist/presentation-projection-trace.d.ts.map +1 -0
  96. package/dist/presentation-projection-trace.js +54 -0
  97. package/dist/presentation-projection-trace.js.map +1 -0
  98. package/dist/presentation-query-form-runtime.d.ts +30 -0
  99. package/dist/presentation-query-form-runtime.d.ts.map +1 -0
  100. package/dist/presentation-query-form-runtime.js +75 -0
  101. package/dist/presentation-query-form-runtime.js.map +1 -0
  102. package/dist/presentation-query-form-state-adapter-registry.d.ts +4 -0
  103. package/dist/presentation-query-form-state-adapter-registry.d.ts.map +1 -0
  104. package/dist/presentation-query-form-state-adapter-registry.js +13 -0
  105. package/dist/presentation-query-form-state-adapter-registry.js.map +1 -0
  106. package/dist/presentation-query-form-state-context.d.ts +20 -0
  107. package/dist/presentation-query-form-state-context.d.ts.map +1 -0
  108. package/dist/presentation-query-form-state-context.js +20 -0
  109. package/dist/presentation-query-form-state-context.js.map +1 -0
  110. package/dist/presentation-query-form-state.d.ts +29 -0
  111. package/dist/presentation-query-form-state.d.ts.map +1 -0
  112. package/dist/presentation-query-form-state.js +99 -0
  113. package/dist/presentation-query-form-state.js.map +1 -0
  114. package/dist/presentation-renderer-registry.d.ts +109 -0
  115. package/dist/presentation-renderer-registry.d.ts.map +1 -0
  116. package/dist/presentation-renderer-registry.js +25 -0
  117. package/dist/presentation-renderer-registry.js.map +1 -0
  118. package/dist/presentation-standards-context.d.ts +4 -0
  119. package/dist/presentation-standards-context.d.ts.map +1 -0
  120. package/dist/presentation-standards-context.js +12 -0
  121. package/dist/presentation-standards-context.js.map +1 -0
  122. package/dist/presentation-standards-provider.d.ts +14 -0
  123. package/dist/presentation-standards-provider.d.ts.map +1 -0
  124. package/dist/presentation-standards-provider.js +16 -0
  125. package/dist/presentation-standards-provider.js.map +1 -0
  126. package/dist/projected-document-action-runtime-bindings.d.ts +20 -0
  127. package/dist/projected-document-action-runtime-bindings.d.ts.map +1 -0
  128. package/dist/projected-document-action-runtime-bindings.js +88 -0
  129. package/dist/projected-document-action-runtime-bindings.js.map +1 -0
  130. package/dist/projected-document-action-runtime.d.ts +76 -0
  131. package/dist/projected-document-action-runtime.d.ts.map +1 -0
  132. package/dist/projected-document-action-runtime.js +224 -0
  133. package/dist/projected-document-action-runtime.js.map +1 -0
  134. package/dist/projected-document-process-preview-action-runtime-bindings.d.ts +26 -0
  135. package/dist/projected-document-process-preview-action-runtime-bindings.d.ts.map +1 -0
  136. package/dist/projected-document-process-preview-action-runtime-bindings.js +106 -0
  137. package/dist/projected-document-process-preview-action-runtime-bindings.js.map +1 -0
  138. package/dist/projected-document-process-preview-action-runtime.d.ts +321 -0
  139. package/dist/projected-document-process-preview-action-runtime.d.ts.map +1 -0
  140. package/dist/projected-document-process-preview-action-runtime.js +729 -0
  141. package/dist/projected-document-process-preview-action-runtime.js.map +1 -0
  142. package/dist/projected-document-process-preview-capability-runtime.d.ts +47 -0
  143. package/dist/projected-document-process-preview-capability-runtime.d.ts.map +1 -0
  144. package/dist/projected-document-process-preview-capability-runtime.js +49 -0
  145. package/dist/projected-document-process-preview-capability-runtime.js.map +1 -0
  146. package/dist/projected-document-workspace-action-runtime.d.ts +87 -0
  147. package/dist/projected-document-workspace-action-runtime.d.ts.map +1 -0
  148. package/dist/projected-document-workspace-action-runtime.js +150 -0
  149. package/dist/projected-document-workspace-action-runtime.js.map +1 -0
  150. package/dist/projected-document-workspace-projection-renderer-diagnostics.d.ts +18 -0
  151. package/dist/projected-document-workspace-projection-renderer-diagnostics.d.ts.map +1 -0
  152. package/dist/projected-document-workspace-projection-renderer-diagnostics.js +207 -0
  153. package/dist/projected-document-workspace-projection-renderer-diagnostics.js.map +1 -0
  154. package/dist/projected-document-workspace-runtime-binding-diagnostics.d.ts +19 -0
  155. package/dist/projected-document-workspace-runtime-binding-diagnostics.d.ts.map +1 -0
  156. package/dist/projected-document-workspace-runtime-binding-diagnostics.js +124 -0
  157. package/dist/projected-document-workspace-runtime-binding-diagnostics.js.map +1 -0
  158. package/dist/projected-navigation-provider.d.ts +16 -0
  159. package/dist/projected-navigation-provider.d.ts.map +1 -0
  160. package/dist/projected-navigation-provider.js +51 -0
  161. package/dist/projected-navigation-provider.js.map +1 -0
  162. package/dist/projected-presentation-flow-host.d.ts +16 -0
  163. package/dist/projected-presentation-flow-host.d.ts.map +1 -0
  164. package/dist/projected-presentation-flow-host.js +14 -0
  165. package/dist/projected-presentation-flow-host.js.map +1 -0
  166. package/dist/projected-query-form-state-adapter.d.ts +12 -0
  167. package/dist/projected-query-form-state-adapter.d.ts.map +1 -0
  168. package/dist/projected-query-form-state-adapter.js +361 -0
  169. package/dist/projected-query-form-state-adapter.js.map +1 -0
  170. package/dist/react-router-binding.d.ts +133 -0
  171. package/dist/react-router-binding.d.ts.map +1 -0
  172. package/dist/react-router-binding.js +76 -0
  173. package/dist/react-router-binding.js.map +1 -0
  174. package/dist/react-router-path.d.ts +4 -0
  175. package/dist/react-router-path.d.ts.map +1 -0
  176. package/dist/react-router-path.js +11 -0
  177. package/dist/react-router-path.js.map +1 -0
  178. package/dist/scope-selection-context.d.ts +28 -0
  179. package/dist/scope-selection-context.d.ts.map +1 -0
  180. package/dist/scope-selection-context.js +13 -0
  181. package/dist/scope-selection-context.js.map +1 -0
  182. package/dist/scope-selection-provider.d.ts +33 -0
  183. package/dist/scope-selection-provider.d.ts.map +1 -0
  184. package/dist/scope-selection-provider.js +162 -0
  185. package/dist/scope-selection-provider.js.map +1 -0
  186. package/dist/scope-selection-request.d.ts +6 -0
  187. package/dist/scope-selection-request.d.ts.map +1 -0
  188. package/dist/scope-selection-request.js +12 -0
  189. package/dist/scope-selection-request.js.map +1 -0
  190. package/dist/standard-navigation-shell-frame-renderers.d.ts +15 -0
  191. package/dist/standard-navigation-shell-frame-renderers.d.ts.map +1 -0
  192. package/dist/standard-navigation-shell-frame-renderers.js +22 -0
  193. package/dist/standard-navigation-shell-frame-renderers.js.map +1 -0
  194. package/dist/standard-navigation-shell-slot-renderers.d.ts +59 -0
  195. package/dist/standard-navigation-shell-slot-renderers.d.ts.map +1 -0
  196. package/dist/standard-navigation-shell-slot-renderers.js +67 -0
  197. package/dist/standard-navigation-shell-slot-renderers.js.map +1 -0
  198. package/dist/view-chrome-slot-renderer-registry.d.ts +12 -0
  199. package/dist/view-chrome-slot-renderer-registry.d.ts.map +1 -0
  200. package/dist/view-chrome-slot-renderer-registry.js +12 -0
  201. package/dist/view-chrome-slot-renderer-registry.js.map +1 -0
  202. package/package.json +60 -0
  203. package/src/collection-chrome-slot-renderer-registry.ts +66 -0
  204. package/src/collection-selection-state-context.ts +51 -0
  205. package/src/collection-selection-state.tsx +101 -0
  206. package/src/document-workspace-runtime.tsx +1505 -0
  207. package/src/index.ts +50 -0
  208. package/src/input-form-endpoint-runtime.ts +632 -0
  209. package/src/local-flow-state-data-source-projection.ts +133 -0
  210. package/src/navigation-runtime-context.ts +40 -0
  211. package/src/navigation-shell-frame-renderer-registry.ts +54 -0
  212. package/src/navigation-shell-region-component-registry.tsx +127 -0
  213. package/src/navigation-shell-slot-renderer-registry.ts +88 -0
  214. package/src/page-host-projection.ts +356 -0
  215. package/src/page-host-renderer-registry.tsx +353 -0
  216. package/src/presentation-action-group-runtime-options.ts +121 -0
  217. package/src/presentation-action-runtime.ts +190 -0
  218. package/src/presentation-data-source-binding-runtime.ts +109 -0
  219. package/src/presentation-data-source-binding.tsx +24 -0
  220. package/src/presentation-flow-runtime.tsx +835 -0
  221. package/src/presentation-module-context.ts +10 -0
  222. package/src/presentation-module-provider.tsx +19 -0
  223. package/src/presentation-projection-diagnostics-context.ts +17 -0
  224. package/src/presentation-projection-diagnostics-hooks.ts +29 -0
  225. package/src/presentation-projection-diagnostics-runtime.tsx +95 -0
  226. package/src/presentation-projection-trace.ts +117 -0
  227. package/src/presentation-query-form-runtime.ts +148 -0
  228. package/src/presentation-query-form-state-adapter-registry.ts +25 -0
  229. package/src/presentation-query-form-state-context.ts +56 -0
  230. package/src/presentation-query-form-state.tsx +250 -0
  231. package/src/presentation-renderer-registry.ts +214 -0
  232. package/src/presentation-standards-context.ts +21 -0
  233. package/src/presentation-standards-provider.tsx +44 -0
  234. package/src/projected-document-action-runtime-bindings.ts +132 -0
  235. package/src/projected-document-action-runtime.ts +414 -0
  236. package/src/projected-document-process-preview-action-runtime-bindings.ts +231 -0
  237. package/src/projected-document-process-preview-action-runtime.ts +1725 -0
  238. package/src/projected-document-process-preview-capability-runtime.ts +216 -0
  239. package/src/projected-document-workspace-action-runtime.ts +402 -0
  240. package/src/projected-document-workspace-projection-renderer-diagnostics.ts +342 -0
  241. package/src/projected-document-workspace-runtime-binding-diagnostics.ts +208 -0
  242. package/src/projected-navigation-provider.tsx +104 -0
  243. package/src/projected-presentation-flow-host.tsx +46 -0
  244. package/src/projected-query-form-state-adapter.ts +578 -0
  245. package/src/react-router-binding.tsx +417 -0
  246. package/src/react-router-path.ts +16 -0
  247. package/src/scope-selection-context.ts +58 -0
  248. package/src/scope-selection-provider.tsx +324 -0
  249. package/src/scope-selection-request.ts +21 -0
  250. package/src/standard-navigation-shell-frame-renderers.tsx +106 -0
  251. package/src/standard-navigation-shell-slot-renderers.tsx +289 -0
  252. package/src/view-chrome-slot-renderer-registry.ts +66 -0
@@ -0,0 +1,342 @@
1
+ import type {
2
+ PresentationModuleDefinition,
3
+ } from '@cohesivesystems/presentation-core'
4
+ import type {
5
+ DocumentWorkspaceProjectionRendererRegistry,
6
+ DocumentWorkspaceProjectionRendererResolution,
7
+ DocumentWorkspaceRuntimeSnapshot,
8
+ } from './document-workspace-runtime'
9
+ import {
10
+ resolveDocumentWorkspaceProjectionCapability,
11
+ resolveDocumentWorkspaceProjectionRenderer,
12
+ } from './document-workspace-runtime'
13
+ import type {
14
+ PresentationProjectionDiagnostic,
15
+ } from '@cohesivesystems/presentation-core'
16
+ import {
17
+ createPresentationEnumDiscriminator,
18
+ matchesPresentationEnum,
19
+ } from '@cohesivesystems/presentation-core'
20
+ import {
21
+ coordinationActionKinds,
22
+ coordinationTriggerKinds,
23
+ } from '@cohesivesystems/presentation-contracts'
24
+
25
+ export interface ProjectDocumentWorkspaceProjectionRendererDiagnosticsOptions<
26
+ TContext,
27
+ TComponentSystem = unknown,
28
+ TDesignSystem = unknown,
29
+ > {
30
+ readonly componentSet?: string | null
31
+ readonly module: PresentationModuleDefinition | null
32
+ readonly projectionRenderers: DocumentWorkspaceProjectionRendererRegistry<
33
+ TContext,
34
+ TComponentSystem,
35
+ TDesignSystem
36
+ >
37
+ readonly runtime: DocumentWorkspaceRuntimeSnapshot
38
+ readonly sourceId?: string
39
+ }
40
+
41
+ /**
42
+ * Reports projection renderer coverage for the document views exposed by the
43
+ * active workspace runtime. The same semantic resolver used for rendering is
44
+ * used here so the developer toolbar reports stale component bindings and
45
+ * unhandled IR projection semantics as actionable frontend TODOs.
46
+ */
47
+ export function projectDocumentWorkspaceProjectionRendererDiagnostics<
48
+ TContext,
49
+ TComponentSystem = unknown,
50
+ TDesignSystem = unknown,
51
+ >({
52
+ componentSet,
53
+ module,
54
+ projectionRenderers,
55
+ runtime,
56
+ sourceId = 'document-workspace-projection-renderers',
57
+ }: ProjectDocumentWorkspaceProjectionRendererDiagnosticsOptions<
58
+ TContext,
59
+ TComponentSystem,
60
+ TDesignSystem
61
+ >): readonly PresentationProjectionDiagnostic[] {
62
+ return [
63
+ ...runtime.projectionViewIds.flatMap((viewId) =>
64
+ projectProjectionRendererDiagnostics({
65
+ componentSet,
66
+ module,
67
+ projectionRenderers,
68
+ runtime,
69
+ sourceId,
70
+ viewId,
71
+ }),
72
+ ),
73
+ ...projectProjectionCoordinationDiagnostics({
74
+ componentSet,
75
+ module,
76
+ projectionRenderers,
77
+ runtime,
78
+ sourceId,
79
+ }),
80
+ ]
81
+ }
82
+
83
+ function projectProjectionRendererDiagnostics<
84
+ TContext,
85
+ TComponentSystem = unknown,
86
+ TDesignSystem = unknown,
87
+ >({
88
+ componentSet,
89
+ module,
90
+ projectionRenderers,
91
+ runtime,
92
+ sourceId,
93
+ viewId,
94
+ }: ProjectDocumentWorkspaceProjectionRendererDiagnosticsOptions<
95
+ TContext,
96
+ TComponentSystem,
97
+ TDesignSystem
98
+ > & {
99
+ readonly viewId: string
100
+ }) {
101
+ const resolution = resolveDocumentWorkspaceProjectionRenderer({
102
+ componentSet,
103
+ module,
104
+ registry: projectionRenderers,
105
+ runtime,
106
+ viewId,
107
+ })
108
+ const projection = resolution.projection
109
+
110
+ if (!projection) {
111
+ return [
112
+ {
113
+ details: { viewId },
114
+ id: `document-projection.${viewId}.missing-projection`,
115
+ message:
116
+ `Document workspace view '${viewId}' does not resolve to a declared ` +
117
+ 'document projection.',
118
+ severity: 'warning',
119
+ source: sourceId ?? 'document-workspace-projection-renderers',
120
+ subject: {
121
+ id: viewId,
122
+ kind: 'document-projection-view',
123
+ },
124
+ } satisfies PresentationProjectionDiagnostic,
125
+ ]
126
+ }
127
+
128
+ const diagnostics: PresentationProjectionDiagnostic[] = []
129
+ if (!resolution.renderer) {
130
+ diagnostics.push({
131
+ details: createProjectionRendererDiagnosticDetails(resolution, viewId),
132
+ id: `document-projection.${projection.Id}.missing-renderer`,
133
+ message: `Document projection '${projection.Name}' has no frontend renderer binding.`,
134
+ severity: 'warning',
135
+ source: sourceId ?? 'document-workspace-projection-renderers',
136
+ subject: {
137
+ id: projection.Id,
138
+ kind: 'document-projection',
139
+ name: projection.Name,
140
+ },
141
+ })
142
+ }
143
+
144
+ if (resolution.renderer && isCompatibilityRendererSource(resolution.resolutionSource)) {
145
+ diagnostics.push({
146
+ details: createProjectionRendererDiagnosticDetails(resolution, viewId),
147
+ id: `document-projection.${projection.Id}.semantic-renderer-fallback`,
148
+ category: resolution.componentRole ? 'unbound' : 'missing-binding',
149
+ interpretation: {
150
+ status: resolution.componentRole ? 'unbound' : 'locally-interpreted',
151
+ target: 'document-projection-component-role',
152
+ },
153
+ message: resolution.componentRole
154
+ ? `Document projection '${projection.Name}' declares component role ` +
155
+ `'${resolution.componentRole}', but rendering fell back to ` +
156
+ `'${resolution.resolutionSource}'.`
157
+ : `Document projection '${projection.Name}' rendered through ` +
158
+ `'${resolution.resolutionSource}' because it has no ProjectionRenderer ` +
159
+ 'target component role binding.',
160
+ severity: 'warning',
161
+ source: sourceId ?? 'document-workspace-projection-renderers',
162
+ suggestedNextStep: resolution.componentRole
163
+ ? `Bind frontend component role '${resolution.componentRole}' in the document projection component pack.`
164
+ : 'Declare a ProjectionRenderer target binding with ComponentRole for this projection and bind that role in the frontend component pack.',
165
+ subject: {
166
+ id: projection.Id,
167
+ kind: 'document-projection',
168
+ name: projection.Name,
169
+ },
170
+ })
171
+ }
172
+
173
+ if (
174
+ resolution.renderer &&
175
+ resolution.componentKey &&
176
+ resolution.resolutionSource === 'component-key'
177
+ ) {
178
+ diagnostics.push({
179
+ category: 'escape-hatch',
180
+ details: createProjectionRendererDiagnosticDetails(resolution, viewId),
181
+ id: `document-projection.${projection.Id}.component-key-escape-hatch`,
182
+ interpretation: {
183
+ status: 'escape-hatch',
184
+ target: 'document-projection-component-key',
185
+ },
186
+ message:
187
+ `Document projection '${projection.Name}' rendered through concrete ` +
188
+ `component key '${resolution.componentKey}' as an escape hatch.`,
189
+ severity: 'warning',
190
+ source: sourceId ?? 'document-workspace-projection-renderers',
191
+ suggestedNextStep:
192
+ 'Prefer ComponentRole for document projections and keep ComponentKey only for adapter-specific overrides.',
193
+ subject: {
194
+ id: projection.Id,
195
+ kind: 'document-projection',
196
+ name: projection.Name,
197
+ },
198
+ })
199
+ }
200
+
201
+ if (resolution.rendererKey) {
202
+ diagnostics.push({
203
+ category: 'escape-hatch',
204
+ details: createProjectionRendererDiagnosticDetails(resolution, viewId),
205
+ id: `document-projection.${projection.Id}.legacy-renderer-key`,
206
+ interpretation: {
207
+ status: 'escape-hatch',
208
+ target: 'document-projection-component-role',
209
+ },
210
+ message:
211
+ `Document projection '${projection.Name}' declares renderer key ` +
212
+ `'${resolution.rendererKey}'. Document projection dispatch now uses ` +
213
+ 'ProjectionRenderer target component roles and semantic projection interpretation.',
214
+ severity: 'warning',
215
+ source: sourceId ?? 'document-workspace-projection-renderers',
216
+ suggestedNextStep:
217
+ 'Replace the renderer key with a ProjectionRenderer target binding that declares ComponentRole.',
218
+ subject: {
219
+ id: projection.Id,
220
+ kind: 'document-projection',
221
+ name: projection.Name,
222
+ },
223
+ })
224
+ }
225
+
226
+ return diagnostics
227
+ }
228
+
229
+ function isCompatibilityRendererSource(
230
+ source: DocumentWorkspaceProjectionRendererResolution<
231
+ unknown,
232
+ unknown,
233
+ unknown
234
+ >['resolutionSource'],
235
+ ) {
236
+ return source === 'projection-kind' ||
237
+ source === 'semantic-reference-kind' ||
238
+ source === 'subject-kind'
239
+ }
240
+
241
+ function projectProjectionCoordinationDiagnostics<
242
+ TContext,
243
+ TComponentSystem = unknown,
244
+ TDesignSystem = unknown,
245
+ >({
246
+ componentSet,
247
+ module,
248
+ projectionRenderers,
249
+ runtime,
250
+ sourceId = 'document-workspace-projection-renderers',
251
+ }: ProjectDocumentWorkspaceProjectionRendererDiagnosticsOptions<
252
+ TContext,
253
+ TComponentSystem,
254
+ TDesignSystem
255
+ >) {
256
+ const revealTargetProjectionIds = new Set(
257
+ runtime.documentProfile.Coordination
258
+ .filter((coordination) =>
259
+ matchesPresentationEnum(coordination.Trigger.Kind, selectionChangedTriggerKind) &&
260
+ matchesPresentationEnum(coordination.Action.Kind, revealSemanticSelectionActionKind),
261
+ )
262
+ .flatMap((coordination) => coordination.Action.TargetProjectionIds),
263
+ )
264
+
265
+ return [...revealTargetProjectionIds].flatMap((projectionId) => {
266
+ const projection = runtime.projections.find((candidate) => candidate.Id === projectionId)
267
+ if (!projection) {
268
+ return []
269
+ }
270
+
271
+ const hasRevealCapability = resolveDocumentWorkspaceProjectionCapability({
272
+ capability: 'revealSemanticSelection',
273
+ componentSet,
274
+ module,
275
+ projection,
276
+ registry: projectionRenderers,
277
+ })
278
+ if (hasRevealCapability) {
279
+ return []
280
+ }
281
+
282
+ return [
283
+ {
284
+ details: {
285
+ coordinationActionKind: 'RevealSemanticSelection',
286
+ projectionKind: projection.Kind,
287
+ semanticReferenceKind: projection.Coordinates?.SemanticReferenceKind ?? null,
288
+ subjectKind: projection.Subject.Kind,
289
+ viewId: projection.ViewId,
290
+ },
291
+ id: `document-projection.${projection.Id}.missing-reveal-semantic-selection`,
292
+ message:
293
+ `Document projection '${projection.Name}' is targeted by semantic ` +
294
+ 'selection reveal coordination, but this frontend adapter has not ' +
295
+ 'declared a reveal interpretation for it.',
296
+ severity: 'warning',
297
+ source: sourceId,
298
+ subject: {
299
+ id: projection.Id,
300
+ kind: 'document-projection',
301
+ name: projection.Name,
302
+ },
303
+ } satisfies PresentationProjectionDiagnostic,
304
+ ]
305
+ })
306
+ }
307
+
308
+ function createProjectionRendererDiagnosticDetails<
309
+ TContext,
310
+ TComponentSystem,
311
+ TDesignSystem,
312
+ >(
313
+ resolution: DocumentWorkspaceProjectionRendererResolution<
314
+ TContext,
315
+ TComponentSystem,
316
+ TDesignSystem
317
+ >,
318
+ viewId: string,
319
+ ) {
320
+ return {
321
+ componentKey: resolution.componentKey,
322
+ componentRole: resolution.componentRole,
323
+ projectionKind: resolution.projection?.Kind ?? null,
324
+ rendererKey: resolution.rendererKey,
325
+ resolutionSource: resolution.resolutionSource,
326
+ semanticReferenceKind: resolution.projection?.Coordinates?.SemanticReferenceKind ?? null,
327
+ subjectKind: resolution.projection?.Subject.Kind ?? null,
328
+ viewId,
329
+ }
330
+ }
331
+
332
+ const selectionChangedTriggerKind = createPresentationEnumDiscriminator(
333
+ coordinationTriggerKinds,
334
+ 'selectionChanged',
335
+ 'SelectionChanged',
336
+ )
337
+
338
+ const revealSemanticSelectionActionKind = createPresentationEnumDiscriminator(
339
+ coordinationActionKinds,
340
+ 'revealSemanticSelection',
341
+ 'RevealSemanticSelection',
342
+ )
@@ -0,0 +1,208 @@
1
+ import type {
2
+ PresentationModuleDefinition,
3
+ } from '@cohesivesystems/presentation-core'
4
+ import {
5
+ createPresentationProjectionDiagnostic,
6
+ type PresentationProjectionDiagnostic,
7
+ } from '@cohesivesystems/presentation-core'
8
+ import {
9
+ createPresentationEnumDiscriminator,
10
+ findPresentationComponentBinding,
11
+ } from '@cohesivesystems/presentation-core'
12
+ import type {
13
+ DocumentWorkspaceRuntimeSnapshot,
14
+ } from './document-workspace-runtime'
15
+ import {
16
+ workspaceRuntimeComponentRoles,
17
+ } from '@cohesivesystems/presentation-contracts'
18
+ import {
19
+ presentationBindingKinds,
20
+ presentationTargetKinds,
21
+ } from '@cohesivesystems/presentation-contracts'
22
+
23
+ export interface ProjectDocumentWorkspaceRuntimeBindingDiagnosticsOptions {
24
+ readonly componentSet?: string | null
25
+ readonly module: PresentationModuleDefinition | null
26
+ readonly runtime: DocumentWorkspaceRuntimeSnapshot
27
+ readonly sourceId?: string
28
+ readonly supportedComponentRoles?: readonly string[]
29
+ }
30
+
31
+ const defaultSupportedDocumentWorkspaceRuntimeRoles = [
32
+ workspaceRuntimeComponentRoles.documentWorkspace,
33
+ ] as const
34
+
35
+ /**
36
+ * Reports whether the backend WorkspaceRuntime target binding is projected as
37
+ * a semantic component role that this frontend document workspace host
38
+ * interprets. The host still mounts the runtime locally, but this diagnostic
39
+ * keeps the target binding honest and prevents concrete ComponentKey bindings
40
+ * from quietly lingering.
41
+ */
42
+ export function projectDocumentWorkspaceRuntimeBindingDiagnostics({
43
+ componentSet,
44
+ module,
45
+ runtime,
46
+ sourceId = 'document-workspace-runtime-binding',
47
+ supportedComponentRoles = defaultSupportedDocumentWorkspaceRuntimeRoles,
48
+ }: ProjectDocumentWorkspaceRuntimeBindingDiagnosticsOptions): readonly PresentationProjectionDiagnostic[] {
49
+ if (!module) {
50
+ return []
51
+ }
52
+
53
+ const binding = findPresentationComponentBinding(module, {
54
+ bindingKind: createPresentationEnumDiscriminator(
55
+ presentationBindingKinds,
56
+ 'workspaceRuntime',
57
+ 'WorkspaceRuntime',
58
+ ),
59
+ componentSet,
60
+ id: runtime.workspace.Id,
61
+ targetKind: createPresentationEnumDiscriminator(
62
+ presentationTargetKinds,
63
+ 'react',
64
+ 'React',
65
+ ),
66
+ })
67
+ const componentKey = binding?.ComponentKey ?? null
68
+ const componentRole = binding?.ComponentRole ?? null
69
+ const supportedRoleSet = new Set(supportedComponentRoles)
70
+ const diagnostics: PresentationProjectionDiagnostic[] = []
71
+
72
+ if (!binding) {
73
+ diagnostics.push(
74
+ createWorkspaceRuntimeDiagnostic({
75
+ category: 'missing-binding',
76
+ componentKey,
77
+ componentRole,
78
+ idSuffix: 'missing-binding',
79
+ message:
80
+ `Document workspace '${runtime.workspace.Id}' has no WorkspaceRuntime ` +
81
+ 'target binding for the active frontend target.',
82
+ severity: 'warning',
83
+ sourceId,
84
+ status: 'unbound',
85
+ suggestedNextStep:
86
+ 'Declare a WorkspaceRuntime target binding with ComponentRole for this document workspace.',
87
+ runtime,
88
+ }),
89
+ )
90
+ return diagnostics
91
+ }
92
+
93
+ if (componentKey) {
94
+ diagnostics.push(
95
+ createWorkspaceRuntimeDiagnostic({
96
+ category: 'escape-hatch',
97
+ componentKey,
98
+ componentRole,
99
+ idSuffix: 'component-key-escape-hatch',
100
+ message:
101
+ `Document workspace '${runtime.workspace.Id}' declares concrete ` +
102
+ `workspace runtime component key '${componentKey}'.`,
103
+ severity: 'warning',
104
+ sourceId,
105
+ status: 'escape-hatch',
106
+ suggestedNextStep:
107
+ 'Use WorkspaceRuntime ComponentRole for document workspace runtimes and reserve ComponentKey for adapter-specific overrides.',
108
+ runtime,
109
+ }),
110
+ )
111
+ }
112
+
113
+ if (!componentRole) {
114
+ diagnostics.push(
115
+ createWorkspaceRuntimeDiagnostic({
116
+ category: 'missing-binding',
117
+ componentKey,
118
+ componentRole,
119
+ idSuffix: 'missing-component-role',
120
+ message:
121
+ `Document workspace '${runtime.workspace.Id}' WorkspaceRuntime binding ` +
122
+ 'does not declare a component role.',
123
+ severity: 'warning',
124
+ sourceId,
125
+ status: 'unbound',
126
+ suggestedNextStep:
127
+ `Set ComponentRole to '${workspaceRuntimeComponentRoles.documentWorkspace}'.`,
128
+ runtime,
129
+ }),
130
+ )
131
+ return diagnostics
132
+ }
133
+
134
+ const isSupportedRole = supportedRoleSet.has(componentRole)
135
+
136
+ diagnostics.push(
137
+ createWorkspaceRuntimeDiagnostic({
138
+ category: isSupportedRole ? 'local-interpretation' : 'missing-binding',
139
+ componentKey,
140
+ componentRole,
141
+ idSuffix: 'component-role-coverage',
142
+ message: isSupportedRole
143
+ ? `Document workspace '${runtime.workspace.Id}' WorkspaceRuntime role ` +
144
+ `'${componentRole}' is interpreted by the local document workspace host.`
145
+ : `Document workspace '${runtime.workspace.Id}' WorkspaceRuntime role ` +
146
+ `'${componentRole}' is not interpreted by the local document workspace host.`,
147
+ severity: isSupportedRole ? 'info' : 'warning',
148
+ sourceId,
149
+ status: isSupportedRole ? 'locally-interpreted' : 'unbound',
150
+ suggestedNextStep: isSupportedRole
151
+ ? undefined
152
+ : 'Bind this WorkspaceRuntime component role in the frontend document workspace host adapter.',
153
+ runtime,
154
+ }),
155
+ )
156
+
157
+ return diagnostics
158
+ }
159
+
160
+ function createWorkspaceRuntimeDiagnostic({
161
+ category,
162
+ componentKey,
163
+ componentRole,
164
+ idSuffix,
165
+ message,
166
+ runtime,
167
+ severity,
168
+ sourceId,
169
+ status,
170
+ suggestedNextStep,
171
+ }: {
172
+ readonly category: PresentationProjectionDiagnostic['category']
173
+ readonly componentKey: string | null
174
+ readonly componentRole: string | null
175
+ readonly idSuffix: string
176
+ readonly message: string
177
+ readonly runtime: DocumentWorkspaceRuntimeSnapshot
178
+ readonly severity: PresentationProjectionDiagnostic['severity']
179
+ readonly sourceId: string
180
+ readonly status: NonNullable<PresentationProjectionDiagnostic['interpretation']>['status']
181
+ readonly suggestedNextStep?: string
182
+ }) {
183
+ return createPresentationProjectionDiagnostic({
184
+ category,
185
+ details: {
186
+ componentKey,
187
+ componentRole,
188
+ documentProfileId: runtime.documentProfile.Id,
189
+ pageViewId: runtime.pageView.Id,
190
+ workspaceId: runtime.workspace.Id,
191
+ workspaceViewId: runtime.workspaceView.Id,
192
+ },
193
+ id: `document-workspace-runtime.${runtime.workspace.Id}.${idSuffix}`,
194
+ interpretation: {
195
+ status,
196
+ target: 'workspace-runtime-component-role',
197
+ },
198
+ message,
199
+ severity,
200
+ source: sourceId,
201
+ subject: {
202
+ id: runtime.workspace.Id,
203
+ kind: 'document-workspace-runtime',
204
+ name: runtime.workspace.Name,
205
+ },
206
+ suggestedNextStep,
207
+ })
208
+ }
@@ -0,0 +1,104 @@
1
+ import { useCallback, useMemo, type Context, type PropsWithChildren } from 'react'
2
+ import { useNavigate, useResolvedPath } from 'react-router'
3
+
4
+ import {
5
+ createNavigationHref,
6
+ type NavigationDefinitionProjection,
7
+ type PresentationNavigationRuntime,
8
+ } from '@cohesivesystems/presentation-core'
9
+ import {
10
+ PresentationNavigationRuntimeContext,
11
+ } from './navigation-runtime-context'
12
+
13
+ export interface ProjectedNavigationContextValue<TNavigation extends NavigationDefinitionProjection = NavigationDefinitionProjection> extends PresentationNavigationRuntime {
14
+ readonly navigation: TNavigation | null
15
+ }
16
+
17
+ export interface ProjectedNavigationProviderProps<
18
+ TNavigation extends NavigationDefinitionProjection,
19
+ > extends PropsWithChildren {
20
+ readonly context?: Context<ProjectedNavigationContextValue<TNavigation>>
21
+ readonly navigation: TNavigation | null
22
+ }
23
+
24
+ /**
25
+ * Generic React binding for semantic navigation definitions. App-specific
26
+ * navigation contexts can be layered on top, but href creation and route
27
+ * execution stay owned by the presentation projection runtime.
28
+ */
29
+ export function ProjectedNavigationProvider<
30
+ TNavigation extends NavigationDefinitionProjection,
31
+ >({
32
+ children,
33
+ context,
34
+ navigation,
35
+ }: ProjectedNavigationProviderProps<TNavigation>) {
36
+ const navigate = useNavigate()
37
+ const rootPath = useResolvedPath('/')
38
+ const createHref = useCallback<ProjectedNavigationContextValue['createHref']>(
39
+ (routeId, parameters) =>
40
+ navigation ? createNavigationHref(navigation, routeId, parameters) : null,
41
+ [navigation],
42
+ )
43
+ const navigateHref = useCallback<ProjectedNavigationContextValue['navigateHref']>(
44
+ (href) => {
45
+ if (href.length > 0) {
46
+ void navigate(toRootRelativeHref(href, rootPath.pathname), {
47
+ flushSync: true,
48
+ relative: 'path',
49
+ })
50
+ }
51
+ },
52
+ [navigate, rootPath.pathname],
53
+ )
54
+ const navigateRoute = useCallback<ProjectedNavigationContextValue['navigateRoute']>(
55
+ (routeId, parameters) => {
56
+ const href = createHref(routeId, parameters)
57
+ if (href) {
58
+ navigateHref(href)
59
+ }
60
+ },
61
+ [createHref, navigateHref],
62
+ )
63
+ const runtime = useMemo<PresentationNavigationRuntime>(
64
+ () => ({
65
+ createHref,
66
+ navigateHref,
67
+ navigateRoute,
68
+ }),
69
+ [createHref, navigateHref, navigateRoute],
70
+ )
71
+ const contextValue = useMemo<ProjectedNavigationContextValue<TNavigation>>(
72
+ () => ({
73
+ ...runtime,
74
+ navigation,
75
+ }),
76
+ [navigation, runtime],
77
+ )
78
+ const ApplicationNavigationContext = context
79
+
80
+ return (
81
+ <PresentationNavigationRuntimeContext.Provider value={runtime}>
82
+ {ApplicationNavigationContext ? (
83
+ <ApplicationNavigationContext.Provider value={contextValue}>
84
+ {children}
85
+ </ApplicationNavigationContext.Provider>
86
+ ) : (
87
+ children
88
+ )}
89
+ </PresentationNavigationRuntimeContext.Provider>
90
+ )
91
+ }
92
+
93
+ function toRootRelativeHref(href: string, rootPathname: string) {
94
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(href) || href.startsWith('//')) {
95
+ return href
96
+ }
97
+
98
+ if (href.startsWith('/')) {
99
+ return href
100
+ }
101
+
102
+ const root = rootPathname === '/' ? '' : rootPathname.replace(/\/+$/g, '')
103
+ return `${root}/${href.replace(/^\/+/g, '')}`
104
+ }
@@ -0,0 +1,46 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ import type {
4
+ FlowDefinition,
5
+ FlowStateDefinition,
6
+ ViewDefinition,
7
+ } from '@cohesivesystems/presentation-core'
8
+ import type {
9
+ PresentationFlowInstance,
10
+ PresentationFlowRuntimeSnapshot,
11
+ } from './presentation-flow-runtime'
12
+
13
+ export interface ProjectedPresentationFlowHostProps {
14
+ readonly fallback?: ReactNode
15
+ readonly renderView: (context: ProjectedPresentationFlowViewRenderContext) => ReactNode
16
+ readonly runtime: PresentationFlowRuntimeSnapshot
17
+ }
18
+
19
+ export interface ProjectedPresentationFlowViewRenderContext {
20
+ readonly flow: FlowDefinition
21
+ readonly instance: PresentationFlowInstance
22
+ readonly state: FlowStateDefinition
23
+ readonly view: ViewDefinition
24
+ }
25
+
26
+ export function ProjectedPresentationFlowHost({
27
+ fallback = null,
28
+ renderView,
29
+ runtime,
30
+ }: ProjectedPresentationFlowHostProps) {
31
+ const { activeFlow, activeInstance, activeState, activeView } = runtime
32
+ if (!activeFlow || !activeInstance || !activeState || !activeView) {
33
+ return <>{fallback}</>
34
+ }
35
+
36
+ return (
37
+ <>
38
+ {renderView({
39
+ flow: activeFlow,
40
+ instance: activeInstance,
41
+ state: activeState,
42
+ view: activeView,
43
+ })}
44
+ </>
45
+ )
46
+ }