@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,414 @@
1
+ import { useMemo } from 'react'
2
+
3
+ import type {
4
+ ProjectedDocumentResource,
5
+ } from '@cohesivesystems/presentation-core'
6
+ import type {
7
+ ActionDefinition,
8
+ ActionPlacementDefinition,
9
+ FlowDefinition,
10
+ PresentationModuleDefinition,
11
+ ViewDefinition,
12
+ } from '@cohesivesystems/presentation-core'
13
+ import {
14
+ findPresentationFlow,
15
+ findPresentationView,
16
+ } from '@cohesivesystems/presentation-core'
17
+ import {
18
+ getPresentationViewProjectedActionPlacements,
19
+ } from '@cohesivesystems/presentation-core'
20
+ import type {
21
+ PresentationActionEndpointExecutor,
22
+ PresentationActionSuccessContext,
23
+ } from './presentation-action-runtime'
24
+ import {
25
+ usePresentationActionExecutor,
26
+ } from './presentation-action-runtime'
27
+ import {
28
+ projectRequiredPresentationActionEndpointRequest,
29
+ } from '@cohesivesystems/presentation-core'
30
+ import {
31
+ advancePresentationFlowToStateKind,
32
+ findPresentationFlowErrorSurfaceState,
33
+ findPresentationFlowSurfaceState,
34
+ isPresentationFlowSurfaceOpenForData,
35
+ resolvePresentationActionPreparedFlow,
36
+ usePresentationFlowRuntimeRegistry,
37
+ type PresentationFlowRuntimeRegistrySnapshot,
38
+ type PresentationFlowRuntimeSnapshot,
39
+ } from './presentation-flow-runtime'
40
+ import {
41
+ type PresentationProjectionDiagnostic,
42
+ } from '@cohesivesystems/presentation-core'
43
+ import {
44
+ findDocumentSaveAction,
45
+ findLocalDocumentEditorAction,
46
+ findPromptCommitAction,
47
+ findPromptDismissAction,
48
+ findPromptLocalAction,
49
+ } from '@cohesivesystems/presentation-core'
50
+ import {
51
+ projectLocalDocumentEditorActionBindingDiagnostics,
52
+ } from '@cohesivesystems/presentation-core'
53
+ import { flowStateKinds } from '@cohesivesystems/presentation-contracts'
54
+
55
+ export interface ProjectedDocumentJsonValidationState {
56
+ readonly ok: boolean
57
+ readonly value?: unknown
58
+ }
59
+
60
+ export interface UseProjectedDocumentActionRuntimeOptions<
61
+ TResource extends ProjectedDocumentResource = ProjectedDocumentResource,
62
+ > {
63
+ readonly actionPlacements: readonly ActionPlacementDefinition[]
64
+ readonly additionalDiagnosticActionPlacements?: readonly ActionPlacementDefinition[]
65
+ readonly dataSourceId: string
66
+ readonly dataSourceQueryKey?: (dataSourceId: string) => readonly unknown[]
67
+ readonly executeEndpoint: PresentationActionEndpointExecutor
68
+ readonly formatDocument?: (value: unknown) => string
69
+ readonly jsonValidation: ProjectedDocumentJsonValidationState
70
+ readonly module: PresentationModuleDefinition | null
71
+ readonly onResetEditorState: () => void
72
+ readonly onSetEditorText: (text: string) => void
73
+ readonly resource: TResource | undefined
74
+ readonly resourceId: string
75
+ readonly resourceKey: string | null
76
+ readonly setSaveResultQueryData?: (
77
+ context: PresentationActionSuccessContext<void, TResource>,
78
+ ) => void
79
+ }
80
+
81
+ export interface ProjectedDocumentActionRuntime {
82
+ readonly actions: {
83
+ readonly formatDocument: ActionDefinition | null
84
+ readonly resetDocument: ActionDefinition | null
85
+ readonly save: ActionDefinition | null
86
+ readonly saveCommit: ActionDefinition | null
87
+ readonly saveDismiss: ActionDefinition | null
88
+ readonly saveRevert: ActionDefinition | null
89
+ }
90
+ readonly actionIds: {
91
+ readonly formatDocument: string
92
+ readonly resetDocument: string
93
+ readonly save: string
94
+ readonly saveCommit: string
95
+ readonly saveDismiss: string
96
+ readonly saveRevert: string
97
+ }
98
+ readonly acceptSaveReview: () => void
99
+ readonly cancelSaveReview: () => void
100
+ readonly diagnosticActionPlacements: readonly ActionPlacementDefinition[]
101
+ readonly diagnostics: readonly PresentationProjectionDiagnostic[]
102
+ readonly flowRegistry: PresentationFlowRuntimeRegistrySnapshot
103
+ readonly formatDocument: () => void
104
+ readonly isSaveReviewOpen: boolean
105
+ readonly promptView: ViewDefinition | null
106
+ readonly resetDocument: () => void
107
+ readonly resetSaveReview: () => void
108
+ readonly resetTransientState: () => void
109
+ readonly requestSaveReview: () => void
110
+ readonly save: {
111
+ readonly action: ActionDefinition | null
112
+ readonly endpointId: string | null
113
+ readonly error: unknown
114
+ readonly isPending: boolean
115
+ readonly reset: () => void
116
+ }
117
+ readonly saveFlow: FlowDefinition | null
118
+ readonly saveFlowId: string
119
+ readonly saveFlowRuntime: PresentationFlowRuntimeSnapshot
120
+ }
121
+
122
+ /**
123
+ * Generic runtime for document-local actions declared in the presentation IR.
124
+ *
125
+ * It owns save review flow mechanics and local editor actions, while callers
126
+ * still supply endpoint execution, action rendering, and product-specific
127
+ * extension actions.
128
+ */
129
+ export function useProjectedDocumentActionRuntime<
130
+ TResource extends ProjectedDocumentResource = ProjectedDocumentResource,
131
+ >({
132
+ actionPlacements,
133
+ additionalDiagnosticActionPlacements = emptyActionPlacements,
134
+ dataSourceId,
135
+ dataSourceQueryKey,
136
+ executeEndpoint,
137
+ formatDocument: formatDocumentValue = formatJsonDocumentValue,
138
+ jsonValidation,
139
+ module,
140
+ onResetEditorState,
141
+ onSetEditorText,
142
+ resource,
143
+ resourceId,
144
+ resourceKey,
145
+ setSaveResultQueryData,
146
+ }: UseProjectedDocumentActionRuntimeOptions<TResource>): ProjectedDocumentActionRuntime {
147
+ const flowRegistry = usePresentationFlowRuntimeRegistry({ module })
148
+ const saveAction = useMemo(
149
+ () =>
150
+ findDocumentSaveAction({
151
+ actionPlacements,
152
+ dataSourceId,
153
+ module,
154
+ }),
155
+ [actionPlacements, dataSourceId, module],
156
+ )
157
+ const saveActionFlow = useMemo(
158
+ () => resolvePresentationActionPreparedFlow(saveAction),
159
+ [saveAction],
160
+ )
161
+ const saveFlowId = saveActionFlow?.flowId ?? ''
162
+ const saveFlow = useMemo(
163
+ () => findPresentationFlow<FlowDefinition>(module, saveFlowId),
164
+ [module, saveFlowId],
165
+ )
166
+ const savePromptView = useMemo(() => {
167
+ const promptViewId =
168
+ saveActionFlow?.promptViewId ??
169
+ findPresentationFlowSurfaceState(saveFlow)?.ViewId
170
+
171
+ return promptViewId
172
+ ? findPresentationView<ViewDefinition>(module, promptViewId)
173
+ : null
174
+ }, [module, saveActionFlow?.promptViewId, saveFlow])
175
+ const saveCommitAction = useMemo(
176
+ () => findPromptCommitAction({ module, view: savePromptView }),
177
+ [module, savePromptView],
178
+ )
179
+ const saveDismissAction = useMemo(
180
+ () => findPromptDismissAction({ module, view: savePromptView }),
181
+ [module, savePromptView],
182
+ )
183
+ const saveRevertAction = useMemo(
184
+ () => findPromptLocalAction({ intent: 'revert', module, view: savePromptView }),
185
+ [module, savePromptView],
186
+ )
187
+ const resetDocumentAction = useMemo(
188
+ () => findLocalDocumentEditorAction({ actionPlacements, intent: 'reset', module }),
189
+ [actionPlacements, module],
190
+ )
191
+ const formatDocumentAction = useMemo(
192
+ () => findLocalDocumentEditorAction({ actionPlacements, intent: 'format', module }),
193
+ [actionPlacements, module],
194
+ )
195
+ const diagnosticActionPlacements = useMemo(
196
+ () =>
197
+ mergeActionPlacements(
198
+ actionPlacements,
199
+ getPresentationViewProjectedActionPlacements(savePromptView),
200
+ additionalDiagnosticActionPlacements,
201
+ ),
202
+ [actionPlacements, additionalDiagnosticActionPlacements, savePromptView],
203
+ )
204
+ const diagnostics = useMemo(
205
+ () =>
206
+ projectLocalDocumentEditorActionBindingDiagnostics({
207
+ actionPlacements: diagnosticActionPlacements,
208
+ module,
209
+ supportedIntents: supportedLocalDocumentEditorActionIntents,
210
+ }),
211
+ [diagnosticActionPlacements, module],
212
+ )
213
+ const saveFlowRuntime = flowRegistry.getRuntime(saveFlowId)
214
+ const isSaveReviewOpen = isPresentationFlowSurfaceOpenForData({
215
+ dataKey: 'resourceKey',
216
+ dataValue: resourceKey,
217
+ flowId: saveFlowId,
218
+ runtime: saveFlowRuntime,
219
+ })
220
+ const saveActionId = optionalActionId(saveAction, 'document-save')
221
+ const saveCommitActionId = optionalActionId(saveCommitAction, 'save-commit')
222
+ const saveDismissActionId = optionalActionId(saveDismissAction, 'save-dismiss')
223
+ const saveRevertActionId = optionalActionId(saveRevertAction, 'save-revert')
224
+ const resetDocumentActionId = optionalActionId(resetDocumentAction, 'document-reset')
225
+ const formatDocumentActionId = optionalActionId(formatDocumentAction, 'document-format')
226
+
227
+ const save = usePresentationActionExecutor<void, TResource>({
228
+ actionId: saveActionId,
229
+ dataSourceId,
230
+ dataSourceQueryKey,
231
+ executeEndpoint,
232
+ module,
233
+ prepareRequest: ({ action, endpointId }) => {
234
+ if (!resource) {
235
+ throw new Error('A loaded resource is required before saving.')
236
+ }
237
+ if (!jsonValidation.ok) {
238
+ throw new Error('Valid JSON is required before saving.')
239
+ }
240
+
241
+ return projectRequiredPresentationActionEndpointRequest({
242
+ action,
243
+ actionId: saveActionId,
244
+ dataSourceId,
245
+ endpointId,
246
+ sources: {
247
+ document: { value: jsonValidation.value },
248
+ resource,
249
+ route: { id: resourceId },
250
+ },
251
+ })
252
+ },
253
+ setResultQueryData: setSaveResultQueryData,
254
+ })
255
+
256
+ function resetTransientState() {
257
+ save.reset()
258
+ saveFlowRuntime.clearFlow()
259
+ }
260
+
261
+ function resetDocument() {
262
+ resetTransientState()
263
+ onResetEditorState()
264
+ }
265
+
266
+ function formatDocument() {
267
+ if (jsonValidation.ok && resourceKey) {
268
+ resetTransientState()
269
+ onSetEditorText(formatDocumentValue(jsonValidation.value))
270
+ }
271
+ }
272
+
273
+ function requestSaveReview() {
274
+ if (!resource || !resourceKey || !jsonValidation.ok || !save.endpointId || save.isPending) {
275
+ return
276
+ }
277
+
278
+ save.reset()
279
+ const started = saveFlowRuntime.startFlow({
280
+ actionId: saveActionId,
281
+ data: { resourceKey },
282
+ flowId: saveFlowId,
283
+ })
284
+ if (!started) {
285
+ const surfaceState = findPresentationFlowSurfaceState(saveFlow)
286
+ saveFlowRuntime.startFlow({
287
+ data: { resourceKey },
288
+ flowId: saveFlowId,
289
+ stateId: surfaceState?.Id,
290
+ })
291
+ }
292
+ }
293
+
294
+ function acceptSaveReview() {
295
+ if (!resource || !jsonValidation.ok || save.isPending) {
296
+ return
297
+ }
298
+
299
+ saveFlowRuntime.dispatchAction(saveCommitActionId)
300
+ void save.executeAsync(undefined)
301
+ .then(() => {
302
+ onResetEditorState()
303
+ advancePresentationFlowToStateKind({
304
+ flow: saveFlow,
305
+ runtime: saveFlowRuntime,
306
+ stateKinds: [flowStateKinds.terminal],
307
+ })
308
+ saveFlowRuntime.clearFlow()
309
+ })
310
+ .catch(() => {
311
+ const failed = advancePresentationFlowToStateKind({
312
+ flow: saveFlow,
313
+ runtime: saveFlowRuntime,
314
+ stateKinds: [flowStateKinds.error],
315
+ })
316
+ if (!failed) {
317
+ const errorState = findPresentationFlowErrorSurfaceState(saveFlow)
318
+ if (errorState) {
319
+ saveFlowRuntime.transitionTo(errorState.Id, { flowId: saveFlowId })
320
+ }
321
+ }
322
+ })
323
+ }
324
+
325
+ function cancelSaveReview() {
326
+ save.reset()
327
+ if (!saveFlowRuntime.dispatchAction(saveDismissActionId)) {
328
+ saveFlowRuntime.clearFlow()
329
+ return
330
+ }
331
+ saveFlowRuntime.clearFlow()
332
+ }
333
+
334
+ function resetSaveReview() {
335
+ save.reset()
336
+ if (!saveFlowRuntime.dispatchAction(saveRevertActionId)) {
337
+ saveFlowRuntime.clearFlow()
338
+ }
339
+ saveFlowRuntime.clearFlow()
340
+ onResetEditorState()
341
+ }
342
+
343
+ return {
344
+ actions: {
345
+ formatDocument: formatDocumentAction,
346
+ resetDocument: resetDocumentAction,
347
+ save: save.action,
348
+ saveCommit: saveCommitAction,
349
+ saveDismiss: saveDismissAction,
350
+ saveRevert: saveRevertAction,
351
+ },
352
+ actionIds: {
353
+ formatDocument: formatDocumentActionId,
354
+ resetDocument: resetDocumentActionId,
355
+ save: saveActionId,
356
+ saveCommit: saveCommitActionId,
357
+ saveDismiss: saveDismissActionId,
358
+ saveRevert: saveRevertActionId,
359
+ },
360
+ acceptSaveReview,
361
+ cancelSaveReview,
362
+ diagnosticActionPlacements,
363
+ diagnostics,
364
+ flowRegistry,
365
+ formatDocument,
366
+ isSaveReviewOpen,
367
+ promptView: savePromptView,
368
+ resetDocument,
369
+ resetSaveReview,
370
+ resetTransientState,
371
+ requestSaveReview,
372
+ save: {
373
+ action: save.action,
374
+ endpointId: save.endpointId,
375
+ error: save.error,
376
+ isPending: save.isPending,
377
+ reset: save.reset,
378
+ },
379
+ saveFlow,
380
+ saveFlowId,
381
+ saveFlowRuntime,
382
+ }
383
+ }
384
+
385
+ const supportedLocalDocumentEditorActionIntents = ['reset', 'format'] as const
386
+ const emptyActionPlacements: readonly ActionPlacementDefinition[] = []
387
+
388
+ export function mergeActionPlacements(
389
+ ...groups: readonly (readonly ActionPlacementDefinition[])[]
390
+ ) {
391
+ const seen = new Set<string>()
392
+ return groups.flatMap((group) =>
393
+ group.filter((placement) => {
394
+ const key = `${placement.Region}:${placement.ActionId}`
395
+ if (seen.has(key)) {
396
+ return false
397
+ }
398
+
399
+ seen.add(key)
400
+ return true
401
+ }),
402
+ )
403
+ }
404
+
405
+ export function optionalActionId(
406
+ action: Pick<ActionDefinition, 'Id'> | null | undefined,
407
+ fallback: string,
408
+ ) {
409
+ return action?.Id ?? `missing:${fallback}`
410
+ }
411
+
412
+ function formatJsonDocumentValue(value: unknown) {
413
+ return JSON.stringify(value ?? null, null, 2)
414
+ }
@@ -0,0 +1,231 @@
1
+ import type {
2
+ PresentationActionRuntimeBinding,
3
+ } from '@cohesivesystems/presentation-core'
4
+ import {
5
+ createPresentationActionRuntimeBinding,
6
+ } from '@cohesivesystems/presentation-core'
7
+ import {
8
+ resolveActionPendingLabel,
9
+ } from '@cohesivesystems/presentation-core'
10
+ import type {
11
+ ProjectedActionStatusSource,
12
+ } from '@cohesivesystems/presentation-core'
13
+ import type {
14
+ ProjectedDocumentProcessPreviewActionRuntime,
15
+ } from './projected-document-process-preview-action-runtime'
16
+ import type {
17
+ ProjectedPromptDocumentPreviewResource,
18
+ } from '@cohesivesystems/presentation-core'
19
+ import {
20
+ actionSemanticsKinds,
21
+ documentWorkspaceActionKinds,
22
+ } from '@cohesivesystems/presentation-contracts'
23
+
24
+ export interface ProjectDocumentProcessPreviewActionRuntimeBindingsOptions<
25
+ TLabel = string,
26
+ TPreviewRequest extends object = object,
27
+ TPreviewResponse = unknown,
28
+ TPreviewValues extends Readonly<Record<string, unknown>> =
29
+ Readonly<Record<string, never>>,
30
+ TPreviewResource extends ProjectedPromptDocumentPreviewResource =
31
+ ProjectedPromptDocumentPreviewResource,
32
+ > {
33
+ readonly hasResource: boolean
34
+ readonly isActionAvailable: boolean
35
+ readonly isPreviewBlocked?: boolean
36
+ readonly pendingLabels?: {
37
+ readonly preview?: TLabel
38
+ readonly start?: TLabel | ((
39
+ runtime: ProjectedDocumentProcessPreviewActionRuntime<
40
+ TPreviewRequest,
41
+ TPreviewResponse,
42
+ TPreviewValues,
43
+ TPreviewResource
44
+ >,
45
+ ) => TLabel)
46
+ }
47
+ readonly runtime: ProjectedDocumentProcessPreviewActionRuntime<
48
+ TPreviewRequest,
49
+ TPreviewResponse,
50
+ TPreviewValues,
51
+ TPreviewResource
52
+ >
53
+ }
54
+
55
+ /**
56
+ * Projects document process-preview runtime state into adapter-neutral action
57
+ * bindings. Product code can still provide presentation labels and additional
58
+ * blocking policy while the runtime owns the IR flow mechanics.
59
+ */
60
+ export function projectDocumentProcessPreviewActionRuntimeBindings<
61
+ TExecuteContext = unknown,
62
+ TLabel = string,
63
+ TPreviewRequest extends object = object,
64
+ TPreviewResponse = unknown,
65
+ TPreviewValues extends Readonly<Record<string, unknown>> =
66
+ Readonly<Record<string, never>>,
67
+ TPreviewResource extends ProjectedPromptDocumentPreviewResource =
68
+ ProjectedPromptDocumentPreviewResource,
69
+ >({
70
+ hasResource,
71
+ isActionAvailable,
72
+ isPreviewBlocked = false,
73
+ pendingLabels,
74
+ runtime,
75
+ }: ProjectDocumentProcessPreviewActionRuntimeBindingsOptions<
76
+ TLabel,
77
+ TPreviewRequest,
78
+ TPreviewResponse,
79
+ TPreviewValues,
80
+ TPreviewResource
81
+ >): readonly PresentationActionRuntimeBinding<TExecuteContext, TLabel>[] {
82
+ const previewPendingLabel = resolveActionPendingLabel({
83
+ action: runtime.actions.preview,
84
+ data: runtime.activePreview,
85
+ fallback: pendingLabels?.preview ?? ('Processing' as TLabel),
86
+ })
87
+ const isPreviewDisabled =
88
+ isPreviewBlocked ||
89
+ runtime.actionEnablement.preview.isDisabled
90
+ const previewDisabledReason =
91
+ runtime.disabledReasons.preview ??
92
+ runtime.actionEnablement.preview.message ??
93
+ runtime.processTask.message ??
94
+ null
95
+ const startDisabledReason =
96
+ runtime.disabledReasons.start ??
97
+ runtime.actionEnablement.start.message ??
98
+ runtime.processTask.message ??
99
+ null
100
+
101
+ return [
102
+ createPresentationActionRuntimeBinding<TExecuteContext, TLabel>({
103
+ documentWorkspaceKind: documentWorkspaceActionKinds.processPreview,
104
+ id: 'document-process-preview-flow',
105
+ semanticsKind: actionSemanticsKinds.documentWorkspace,
106
+ project: () => ({
107
+ disabledReason: previewDisabledReason
108
+ ? previewDisabledReason as TLabel
109
+ : undefined,
110
+ execute: () => runtime.requestPreview(),
111
+ isDisabled:
112
+ !runtime.canExecuteAction ||
113
+ isPreviewDisabled ||
114
+ runtime.preview.isPending ||
115
+ runtime.start.isPending ||
116
+ runtime.processTask.isDisabled,
117
+ isHidden: !(runtime.hasAction && isActionAvailable && hasResource),
118
+ isPending:
119
+ runtime.preview.isPending ||
120
+ runtime.start.isPending ||
121
+ Boolean(runtime.processTask.activeTask),
122
+ pendingLabel: previewPendingLabel,
123
+ }),
124
+ }),
125
+ createPresentationActionRuntimeBinding<TExecuteContext, TLabel>({
126
+ documentWorkspaceKind: documentWorkspaceActionKinds.processStart,
127
+ id: 'accept-document-process-preview',
128
+ semanticsKind: actionSemanticsKinds.documentWorkspace,
129
+ project: () => ({
130
+ disabledReason: startDisabledReason
131
+ ? startDisabledReason as TLabel
132
+ : undefined,
133
+ execute: runtime.acceptPreview,
134
+ isDisabled:
135
+ !runtime.canAcceptPreview ||
136
+ runtime.start.isPending ||
137
+ runtime.actionEnablement.start.isDisabled ||
138
+ Boolean(runtime.processTask.activeTask),
139
+ isHidden: !runtime.activePreview,
140
+ isPending:
141
+ runtime.start.isPending ||
142
+ Boolean(runtime.processTask.activeTask),
143
+ pendingLabel: resolveActionPendingLabel({
144
+ action: runtime.actions.start,
145
+ data: runtime.activePreview,
146
+ fallback: resolveStartPendingLabel(runtime, pendingLabels?.start),
147
+ }),
148
+ }),
149
+ }),
150
+ createPresentationActionRuntimeBinding<TExecuteContext, TLabel>({
151
+ documentWorkspaceKind: documentWorkspaceActionKinds.processCancel,
152
+ id: 'cancel-document-process-preview',
153
+ semanticsKind: actionSemanticsKinds.documentWorkspace,
154
+ project: () => ({
155
+ execute: runtime.activePreview ? runtime.cancelPreview : runtime.cancelPrompt,
156
+ isDisabled: runtime.start.isPending,
157
+ isHidden: !(runtime.isPromptOpen || runtime.activePreview),
158
+ }),
159
+ }),
160
+ ]
161
+ }
162
+
163
+ /**
164
+ * Projects a document process-preview runtime into action status sources used
165
+ * by document-profile action status notices.
166
+ */
167
+ export function projectDocumentProcessPreviewActionStatusSources<
168
+ TPreviewRequest extends object,
169
+ TPreviewResponse,
170
+ TPreviewValues extends Readonly<Record<string, unknown>>,
171
+ TPreviewResource extends ProjectedPromptDocumentPreviewResource,
172
+ >(
173
+ runtime: ProjectedDocumentProcessPreviewActionRuntime<
174
+ TPreviewRequest,
175
+ TPreviewResponse,
176
+ TPreviewValues,
177
+ TPreviewResource
178
+ >,
179
+ ): readonly ProjectedActionStatusSource[] {
180
+ return [
181
+ {
182
+ action: runtime.actions.preview,
183
+ error: runtime.preview.error,
184
+ isPending: runtime.preview.isPending,
185
+ },
186
+ {
187
+ action: runtime.start.action,
188
+ error: runtime.start.error,
189
+ isPending: runtime.start.isPending,
190
+ },
191
+ ]
192
+ }
193
+
194
+ function resolveStartPendingLabel<
195
+ TLabel,
196
+ TPreviewRequest extends object,
197
+ TPreviewResponse,
198
+ TPreviewValues extends Readonly<Record<string, unknown>>,
199
+ TPreviewResource extends ProjectedPromptDocumentPreviewResource,
200
+ >(
201
+ runtime: ProjectedDocumentProcessPreviewActionRuntime<
202
+ TPreviewRequest,
203
+ TPreviewResponse,
204
+ TPreviewValues,
205
+ TPreviewResource
206
+ >,
207
+ label:
208
+ | TLabel
209
+ | ((
210
+ runtime: ProjectedDocumentProcessPreviewActionRuntime<
211
+ TPreviewRequest,
212
+ TPreviewResponse,
213
+ TPreviewValues,
214
+ TPreviewResource
215
+ >,
216
+ ) => TLabel)
217
+ | undefined,
218
+ ) {
219
+ if (typeof label === 'function') {
220
+ return (label as (
221
+ runtime: ProjectedDocumentProcessPreviewActionRuntime<
222
+ TPreviewRequest,
223
+ TPreviewResponse,
224
+ TPreviewValues,
225
+ TPreviewResource
226
+ >,
227
+ ) => TLabel)(runtime)
228
+ }
229
+
230
+ return label
231
+ }