@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,250 @@
1
+ import {
2
+ useMemo,
3
+ useState,
4
+ type PropsWithChildren,
5
+ type SetStateAction,
6
+ } from 'react'
7
+ import { useLocation } from 'react-router'
8
+
9
+ import {
10
+ findPresentationInputForm,
11
+ findPresentationQueryForm,
12
+ type InputFormDefinition,
13
+ type PresentationModuleDefinition,
14
+ type QueryFormDefinition,
15
+ } from '@cohesivesystems/presentation-core'
16
+ import { usePresentationModule } from './presentation-module-context'
17
+ import {
18
+ PresentationQueryFormStateContext,
19
+ type PresentationQueryFormStateEntry,
20
+ } from './presentation-query-form-state-context'
21
+ import { resolvePresentationQueryFormStateAdapters } from './presentation-query-form-state-adapter-registry'
22
+ import type {
23
+ PresentationQueryFormState,
24
+ PresentationQueryFormStateMap,
25
+ } from '@cohesivesystems/presentation-core'
26
+
27
+ export interface PresentationQueryFormStateAdapter<TValue extends object = object> {
28
+ readonly queryFormId: string
29
+
30
+ createAppliedSearch?(context: PresentationQueryFormAppliedSearchContext<TValue>): string
31
+ createDefaultValue(context: PresentationQueryFormStateAdapterContext): TValue
32
+ createSearchKey?(context: PresentationQueryFormStateAdapterContext): string
33
+ normalizeValue?(context: PresentationQueryFormAdapterValueContext<TValue>): TValue
34
+ readValueFromSearch?(context: PresentationQueryFormStateAdapterContext): TValue
35
+ }
36
+
37
+ export type PresentationQueryFormStateAdapterRegistry = Readonly<
38
+ Record<string, PresentationQueryFormStateAdapter | undefined>
39
+ >
40
+
41
+ export interface PresentationQueryFormStateAdapterContext {
42
+ readonly choiceValuesByFieldId?: Readonly<Record<string, readonly string[]>>
43
+ readonly inputForm: InputFormDefinition | null
44
+ readonly module: PresentationModuleDefinition | null
45
+ readonly queryForm: QueryFormDefinition | null
46
+ readonly search: string
47
+ }
48
+
49
+ export interface PresentationQueryFormAdapterValueContext<TValue extends object>
50
+ extends PresentationQueryFormStateAdapterContext {
51
+ readonly choiceValuesByFieldId: Readonly<Record<string, readonly string[]>>
52
+ readonly value: TValue
53
+ }
54
+
55
+ export type PresentationQueryFormAppliedSearchContext<TValue extends object> =
56
+ PresentationQueryFormAdapterValueContext<TValue>
57
+
58
+ interface PresentationQueryFormStateProviderProps extends PropsWithChildren {
59
+ readonly adapterRegistry: PresentationQueryFormStateAdapterRegistry
60
+ }
61
+
62
+ interface PresentationQueryFormInitialState {
63
+ readonly initialValue: object
64
+ readonly inputForm: InputFormDefinition | null
65
+ readonly queryForm: QueryFormDefinition | null
66
+ readonly queryFormId: string
67
+ }
68
+
69
+ interface PresentationQueryFormStoredState {
70
+ readonly appliedValue: unknown
71
+ readonly draftValue: unknown
72
+ }
73
+
74
+ export function PresentationQueryFormStateProvider({
75
+ adapterRegistry,
76
+ children,
77
+ }: PresentationQueryFormStateProviderProps) {
78
+ const location = useLocation()
79
+ const module = usePresentationModule()
80
+ const adapters = useMemo(
81
+ () => resolvePresentationQueryFormStateAdapters(module, adapterRegistry),
82
+ [adapterRegistry, module],
83
+ )
84
+ const initialStates = useMemo(
85
+ () =>
86
+ adapters.map((adapter) =>
87
+ createInitialQueryFormState(adapter, module, location.search),
88
+ ),
89
+ [adapters, location.search, module],
90
+ )
91
+ const stateKey = useMemo(
92
+ () =>
93
+ adapters.map((adapter) =>
94
+ createQueryFormStateKey(adapter, module, location.search),
95
+ ).join('|'),
96
+ [adapters, location.search, module],
97
+ )
98
+
99
+ return (
100
+ <PresentationQueryFormStateScope
101
+ initialStates={initialStates}
102
+ key={stateKey}
103
+ >
104
+ {children}
105
+ </PresentationQueryFormStateScope>
106
+ )
107
+ }
108
+
109
+ function PresentationQueryFormStateScope({
110
+ children,
111
+ initialStates,
112
+ }: PropsWithChildren<{
113
+ readonly initialStates: readonly PresentationQueryFormInitialState[]
114
+ }>) {
115
+ const [storedStates, setStoredStates] = useState<Record<string, PresentationQueryFormStoredState>>(() =>
116
+ Object.fromEntries(
117
+ initialStates.map((state) => [
118
+ state.queryFormId,
119
+ {
120
+ appliedValue: state.initialValue,
121
+ draftValue: state.initialValue,
122
+ } satisfies PresentationQueryFormStoredState,
123
+ ]),
124
+ ),
125
+ )
126
+ const entries = useMemo(
127
+ () =>
128
+ Object.fromEntries(
129
+ initialStates.map((state) => {
130
+ const storedState = storedStates[state.queryFormId] ?? {
131
+ appliedValue: state.initialValue,
132
+ draftValue: state.initialValue,
133
+ }
134
+ return [
135
+ state.queryFormId,
136
+ {
137
+ appliedValue: storedState.appliedValue,
138
+ draftValue: storedState.draftValue,
139
+ inputForm: state.inputForm,
140
+ queryForm: state.queryForm,
141
+ queryFormId: state.queryFormId,
142
+ setAppliedValue: (update: SetStateAction<unknown>) =>
143
+ setStoredStates((current) =>
144
+ updateStoredQueryFormState(current, state.queryFormId, 'appliedValue', update),
145
+ ),
146
+ setDraftValue: (update: SetStateAction<unknown>) =>
147
+ setStoredStates((current) =>
148
+ updateStoredQueryFormState(current, state.queryFormId, 'draftValue', update),
149
+ ),
150
+ } satisfies PresentationQueryFormStateEntry,
151
+ ]
152
+ }),
153
+ ),
154
+ [initialStates, storedStates],
155
+ )
156
+ const queryFormStates = useMemo(
157
+ () =>
158
+ Object.fromEntries(
159
+ Object.values(entries).flatMap((entry) =>
160
+ entry.queryForm
161
+ ? [[
162
+ entry.queryFormId,
163
+ {
164
+ appliedValue: entry.appliedValue,
165
+ draftValue: entry.draftValue,
166
+ queryForm: entry.queryForm,
167
+ queryFormId: entry.queryFormId,
168
+ } satisfies PresentationQueryFormState,
169
+ ]]
170
+ : [],
171
+ ),
172
+ ) satisfies PresentationQueryFormStateMap,
173
+ [entries],
174
+ )
175
+ const value = useMemo(
176
+ () => ({
177
+ entries,
178
+ queryFormStates,
179
+ }),
180
+ [entries, queryFormStates],
181
+ )
182
+
183
+ return (
184
+ <PresentationQueryFormStateContext.Provider value={value}>
185
+ {children}
186
+ </PresentationQueryFormStateContext.Provider>
187
+ )
188
+ }
189
+
190
+ function createInitialQueryFormState(
191
+ adapter: PresentationQueryFormStateAdapter,
192
+ module: PresentationModuleDefinition | null,
193
+ search: string,
194
+ ): PresentationQueryFormInitialState {
195
+ const adapterContext = createAdapterContext(adapter, module, search)
196
+ return {
197
+ initialValue: adapter.readValueFromSearch?.(adapterContext) ??
198
+ adapter.createDefaultValue(adapterContext),
199
+ inputForm: adapterContext.inputForm,
200
+ queryForm: adapterContext.queryForm,
201
+ queryFormId: adapter.queryFormId,
202
+ }
203
+ }
204
+
205
+ function createQueryFormStateKey(
206
+ adapter: PresentationQueryFormStateAdapter,
207
+ module: PresentationModuleDefinition | null,
208
+ search: string,
209
+ ) {
210
+ const adapterContext = createAdapterContext(adapter, module, search)
211
+ return `${adapter.queryFormId}:${adapter.createSearchKey?.(adapterContext) ?? ''}`
212
+ }
213
+
214
+ function createAdapterContext(
215
+ adapter: PresentationQueryFormStateAdapter,
216
+ module: PresentationModuleDefinition | null,
217
+ search: string,
218
+ ): PresentationQueryFormStateAdapterContext {
219
+ const queryForm = findPresentationQueryForm(module, adapter.queryFormId)
220
+ return {
221
+ inputForm: queryForm ? findPresentationInputForm(module, queryForm.FormId) : null,
222
+ module,
223
+ queryForm,
224
+ search,
225
+ }
226
+ }
227
+
228
+ function updateStoredQueryFormState(
229
+ current: Record<string, PresentationQueryFormStoredState>,
230
+ queryFormId: string,
231
+ field: keyof PresentationQueryFormStoredState,
232
+ update: SetStateAction<unknown>,
233
+ ) {
234
+ const currentState = current[queryFormId] ?? {
235
+ appliedValue: {},
236
+ draftValue: {},
237
+ }
238
+ const currentValue = currentState[field]
239
+ const nextValue = typeof update === 'function'
240
+ ? (update as (value: unknown) => unknown)(currentValue)
241
+ : update
242
+
243
+ return {
244
+ ...current,
245
+ [queryFormId]: {
246
+ ...currentState,
247
+ [field]: nextValue,
248
+ },
249
+ }
250
+ }
@@ -0,0 +1,214 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ import {
4
+ createPresentationEnumDiscriminator,
5
+ mergePresentationRendererRegistries as mergeCorePresentationRendererRegistries,
6
+ resolvePresentationViewRenderer as resolveCorePresentationViewRenderer,
7
+ type FieldPresentationDefinition,
8
+ type PresentationDataSourceResolver,
9
+ type PresentationModuleDefinition,
10
+ type PresentationSurface,
11
+ type PresentationCompositeRendererRegistry as CorePresentationCompositeRendererRegistry,
12
+ type PresentationRendererBindingModuleProjection,
13
+ type PresentationRendererRegistry as CorePresentationRendererRegistry,
14
+ type PresentationViewRendererResolution as CorePresentationViewRendererResolution,
15
+ type PresentationViewRendererResolutionSource,
16
+ type ViewDefinition,
17
+ } from '@cohesivesystems/presentation-core'
18
+ import { presentationTargetKinds } from '@cohesivesystems/presentation-contracts'
19
+
20
+ /**
21
+ * Options that let a view renderer project only selected regions of a view.
22
+ */
23
+ export interface PresentationViewRegionRenderOptions {
24
+ /** Region ids to render. Omit this to render every region declared by the view. */
25
+ readonly includeRegionIds?: readonly string[]
26
+ }
27
+
28
+ /**
29
+ * Runtime context supplied to a concrete renderer for a semantic presentation view.
30
+ *
31
+ * @typeParam TContext - App-specific projection context carried through rendering.
32
+ */
33
+ export interface PresentationViewRenderContext<TContext> {
34
+ /** Component key resolved from presentation target bindings, when matched. */
35
+ readonly componentKey: string | null
36
+
37
+ /** Component role resolved from presentation target bindings, when matched. */
38
+ readonly componentRole: string | null
39
+
40
+ /** App-specific runtime context supplied by the projection host. */
41
+ readonly context: TContext
42
+
43
+ /** Resolver for semantic data sources referenced by the view or nested renderers. */
44
+ readonly dataSourceResolver: PresentationDataSourceResolver
45
+
46
+ /** Presentation module that owns the projected view graph and bindings. */
47
+ readonly module: PresentationModuleDefinition
48
+
49
+ /** Renders this view's regions, optionally restricted to specific region ids. */
50
+ readonly renderRegions: (
51
+ view: ViewDefinition,
52
+ options?: PresentationViewRegionRenderOptions,
53
+ ) => ReactNode
54
+
55
+ /** Renders another view from the same presentation module by semantic view id. */
56
+ readonly renderView: (viewId: string) => ReactNode
57
+
58
+ /** Surface on which the current view is being projected. */
59
+ readonly surface: PresentationSurface
60
+
61
+ /** Semantic view definition being adapted to React. */
62
+ readonly view: ViewDefinition
63
+ }
64
+
65
+ /**
66
+ * React renderer for a semantic presentation view.
67
+ */
68
+ export type PresentationViewRenderer<TContext> = (
69
+ context: PresentationViewRenderContext<TContext>,
70
+ ) => ReactNode
71
+
72
+ /**
73
+ * Runtime context supplied when rendering a scalar or structured presentation value.
74
+ *
75
+ * @typeParam TContext - App-specific projection context carried through rendering.
76
+ */
77
+ export interface PresentationValueRenderContext<TContext> {
78
+ /** App-specific runtime context supplied by the projection host. */
79
+ readonly context: TContext
80
+
81
+ /** Resolver for data sources available to value renderers. */
82
+ readonly dataSourceResolver: PresentationDataSourceResolver
83
+
84
+ /** Field metadata that describes the value, when the value came from a field. */
85
+ readonly field?: FieldPresentationDefinition | null
86
+
87
+ /** Presentation module that owns the value's field and binding definitions. */
88
+ readonly module: PresentationModuleDefinition
89
+
90
+ /** Raw value selected from the semantic data source. */
91
+ readonly value: unknown
92
+ }
93
+
94
+ /**
95
+ * React renderer for an individual presentation value.
96
+ */
97
+ export type PresentationValueRenderer<TContext> = (
98
+ context: PresentationValueRenderContext<TContext>,
99
+ ) => ReactNode
100
+
101
+ /**
102
+ * Runtime context supplied to presentation controls that are not tied to a single view.
103
+ *
104
+ * @typeParam TContext - App-specific projection context carried through rendering.
105
+ */
106
+ export interface PresentationControlRenderContext<TContext> {
107
+ /** App-specific runtime context supplied by the projection host. */
108
+ readonly context: TContext
109
+
110
+ /** Resolver for data sources available to control renderers. */
111
+ readonly dataSourceResolver: PresentationDataSourceResolver
112
+
113
+ /** Presentation module that owns the control binding definitions. */
114
+ readonly module: PresentationModuleDefinition
115
+ }
116
+
117
+ /**
118
+ * React renderer for an auxiliary presentation control.
119
+ */
120
+ export type PresentationControlRenderer<TContext> = (
121
+ context: PresentationControlRenderContext<TContext>,
122
+ ) => ReactNode
123
+
124
+ export type PresentationCompositeRendererRegistry<TContext> =
125
+ CorePresentationCompositeRendererRegistry<PresentationViewRenderer<TContext>>
126
+
127
+ /**
128
+ * Complete renderer registry used by the React presentation projection runtime.
129
+ */
130
+ export interface PresentationRendererRegistry<TContext>
131
+ extends CorePresentationRendererRegistry<
132
+ PresentationViewRenderer<TContext>,
133
+ PresentationControlRenderer<TContext>,
134
+ PresentationValueRenderer<TContext>
135
+ > {
136
+ /** Composite renderers that adapt whole semantic views. */
137
+ readonly composites?: PresentationCompositeRendererRegistry<TContext>
138
+
139
+ /** Control renderers keyed by presentation control ids or component keys. */
140
+ readonly controls?: Readonly<Record<string, PresentationControlRenderer<TContext>>>
141
+
142
+ /** Value renderers keyed by semantic value or field renderer ids. */
143
+ readonly values?: Readonly<Record<string, PresentationValueRenderer<TContext>>>
144
+ }
145
+
146
+ export type PresentationViewRendererResolution<TContext> =
147
+ CorePresentationViewRendererResolution<PresentationViewRenderer<TContext>>
148
+
149
+ export type { PresentationRendererBindingModuleProjection }
150
+
151
+ export type { PresentationViewRendererResolutionSource }
152
+
153
+ export interface ResolvePresentationViewRendererOptions<
154
+ TContext,
155
+ TModule extends PresentationRendererBindingModuleProjection =
156
+ PresentationRendererBindingModuleProjection,
157
+ > {
158
+ readonly componentSet?: string | null
159
+ readonly module: TModule
160
+ readonly registry: PresentationRendererRegistry<TContext>
161
+ readonly routeId?: string | null
162
+ readonly view: ViewDefinition
163
+ }
164
+
165
+ /**
166
+ * Combines renderer registries in declaration order, with later registries
167
+ * overriding earlier renderer keys and fallback renderers.
168
+ */
169
+ export function mergePresentationRendererRegistries<TContext>(
170
+ ...registries: readonly PresentationRendererRegistry<TContext>[]
171
+ ): PresentationRendererRegistry<TContext> {
172
+ return mergeCorePresentationRendererRegistries<
173
+ PresentationViewRenderer<TContext>,
174
+ PresentationControlRenderer<TContext>,
175
+ PresentationValueRenderer<TContext>
176
+ >(...registries) as PresentationRendererRegistry<TContext>
177
+ }
178
+
179
+ /**
180
+ * Resolves the React renderer for a semantic view while keeping binding
181
+ * resolution in the framework-neutral core package.
182
+ */
183
+ export function resolvePresentationViewRenderer<
184
+ TContext,
185
+ TModule extends PresentationRendererBindingModuleProjection =
186
+ PresentationRendererBindingModuleProjection,
187
+ >({
188
+ componentSet,
189
+ module,
190
+ registry,
191
+ routeId,
192
+ view,
193
+ }: ResolvePresentationViewRendererOptions<
194
+ TContext,
195
+ TModule
196
+ >): PresentationViewRendererResolution<TContext> {
197
+ return resolveCorePresentationViewRenderer<
198
+ PresentationViewRenderer<TContext>,
199
+ TModule
200
+ >({
201
+ componentSet,
202
+ module,
203
+ registry,
204
+ routeId,
205
+ targetKind: reactPresentationTargetKind,
206
+ view,
207
+ })
208
+ }
209
+
210
+ const reactPresentationTargetKind = createPresentationEnumDiscriminator(
211
+ presentationTargetKinds,
212
+ 'react',
213
+ 'React',
214
+ )
@@ -0,0 +1,21 @@
1
+ import {
2
+ createContext,
3
+ useContext,
4
+ type Context,
5
+ } from 'react'
6
+
7
+ export function createPresentationStandardsContext<TStandards>() {
8
+ return createContext<TStandards | null>(null)
9
+ }
10
+
11
+ export function usePresentationStandards<TStandards>(
12
+ context: Context<TStandards | null>,
13
+ label = 'Presentation standards',
14
+ ) {
15
+ const standards = useContext(context)
16
+ if (!standards) {
17
+ throw new Error(`${label} are not available.`)
18
+ }
19
+
20
+ return standards
21
+ }
@@ -0,0 +1,44 @@
1
+ import {
2
+ useContext,
3
+ useMemo,
4
+ type Context,
5
+ type PropsWithChildren,
6
+ } from 'react'
7
+
8
+ import type { PresentationStandardsComposer } from '@cohesivesystems/presentation-core'
9
+
10
+ export interface PresentationStandardsProviderProps<TStandards, TContribution>
11
+ extends PropsWithChildren {
12
+ readonly compose: PresentationStandardsComposer<TStandards, TContribution>
13
+ readonly context: Context<TStandards | null>
14
+ readonly standards: TContribution
15
+ }
16
+
17
+ /**
18
+ * Generic standards provider. Nested providers compose their local contribution
19
+ * over the inherited standards, so feature areas can override or enrich app
20
+ * defaults without replacing the whole standards object.
21
+ */
22
+ export function PresentationStandardsProvider<TStandards, TContribution>({
23
+ children,
24
+ compose,
25
+ context,
26
+ standards,
27
+ }: PresentationStandardsProviderProps<TStandards, TContribution>) {
28
+ const StandardsContext = context
29
+ const parent = useContext(StandardsContext)
30
+ const value = useMemo(
31
+ () => (
32
+ parent
33
+ ? compose(parent as unknown as TContribution, standards)
34
+ : compose(standards)
35
+ ),
36
+ [compose, parent, standards],
37
+ )
38
+
39
+ return (
40
+ <StandardsContext.Provider value={value}>
41
+ {children}
42
+ </StandardsContext.Provider>
43
+ )
44
+ }
@@ -0,0 +1,132 @@
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
+ ProjectedDocumentActionRuntime,
12
+ ProjectedDocumentJsonValidationState,
13
+ } from './projected-document-action-runtime'
14
+ import {
15
+ actionSemanticsKinds,
16
+ documentWorkspaceActionKinds,
17
+ localDocumentEditorActionKinds,
18
+ } from '@cohesivesystems/presentation-contracts'
19
+
20
+ export interface ProjectDocumentActionRuntimeBindingsOptions<
21
+ TLabel = string,
22
+ > {
23
+ readonly formatDocument?: () => void
24
+ readonly hasResource: boolean
25
+ readonly isEditorDirty: boolean
26
+ readonly jsonValidation: ProjectedDocumentJsonValidationState
27
+ readonly pendingLabels?: {
28
+ readonly save?: TLabel
29
+ }
30
+ readonly resetDocument?: () => void
31
+ readonly runtime: ProjectedDocumentActionRuntime
32
+ }
33
+
34
+ /**
35
+ * Projects generic document action runtime state into adapter-neutral action
36
+ * bindings. The runtime owns the semantic document mechanics; UI adapters own
37
+ * how these bindings become concrete controls.
38
+ */
39
+ export function projectDocumentActionRuntimeBindings<
40
+ TExecuteContext = unknown,
41
+ TLabel = string,
42
+ >({
43
+ formatDocument,
44
+ hasResource,
45
+ isEditorDirty,
46
+ jsonValidation,
47
+ pendingLabels,
48
+ resetDocument,
49
+ runtime,
50
+ }: ProjectDocumentActionRuntimeBindingsOptions<
51
+ TLabel
52
+ >): readonly PresentationActionRuntimeBinding<TExecuteContext, TLabel>[] {
53
+ const savePendingLabel = resolveActionPendingLabel({
54
+ action: runtime.actions.save,
55
+ fallback: pendingLabels?.save ?? ('Saving' as TLabel),
56
+ })
57
+ const saveCommitPendingLabel = resolveActionPendingLabel({
58
+ action: runtime.actions.saveCommit,
59
+ fallback: savePendingLabel,
60
+ })
61
+
62
+ return [
63
+ createPresentationActionRuntimeBinding<TExecuteContext, TLabel>({
64
+ documentWorkspaceKind: documentWorkspaceActionKinds.saveReview,
65
+ id: 'document-save-preview-flow',
66
+ semanticsKind: actionSemanticsKinds.documentWorkspace,
67
+ project: () => ({
68
+ execute: runtime.requestSaveReview,
69
+ isDisabled:
70
+ !isEditorDirty ||
71
+ !jsonValidation.ok ||
72
+ !runtime.save.endpointId ||
73
+ runtime.save.isPending ||
74
+ runtime.isSaveReviewOpen,
75
+ isHidden: !hasResource,
76
+ isPending: runtime.save.isPending,
77
+ pendingLabel: savePendingLabel,
78
+ }),
79
+ }),
80
+ createPresentationActionRuntimeBinding<TExecuteContext, TLabel>({
81
+ documentWorkspaceKind: documentWorkspaceActionKinds.saveCommit,
82
+ id: 'accept-save-review',
83
+ semanticsKind: actionSemanticsKinds.documentWorkspace,
84
+ project: () => ({
85
+ execute: runtime.acceptSaveReview,
86
+ isDisabled: runtime.save.isPending,
87
+ isHidden: !runtime.isSaveReviewOpen,
88
+ isPending: runtime.save.isPending,
89
+ pendingLabel: saveCommitPendingLabel,
90
+ }),
91
+ }),
92
+ createPresentationActionRuntimeBinding<TExecuteContext, TLabel>({
93
+ documentWorkspaceKind: documentWorkspaceActionKinds.saveCancel,
94
+ id: 'cancel-save-review',
95
+ semanticsKind: actionSemanticsKinds.documentWorkspace,
96
+ project: () => ({
97
+ execute: runtime.cancelSaveReview,
98
+ isDisabled: runtime.save.isPending,
99
+ isHidden: !runtime.isSaveReviewOpen,
100
+ }),
101
+ }),
102
+ createPresentationActionRuntimeBinding<TExecuteContext, TLabel>({
103
+ documentWorkspaceKind: documentWorkspaceActionKinds.saveRevert,
104
+ id: 'revert-save-review',
105
+ semanticsKind: actionSemanticsKinds.documentWorkspace,
106
+ project: () => ({
107
+ execute: runtime.resetSaveReview,
108
+ isDisabled: runtime.save.isPending,
109
+ isHidden: !runtime.isSaveReviewOpen,
110
+ }),
111
+ }),
112
+ createPresentationActionRuntimeBinding<TExecuteContext, TLabel>({
113
+ id: 'reset-json-document',
114
+ localDocumentEditorKind: localDocumentEditorActionKinds.reset,
115
+ semanticsKind: actionSemanticsKinds.localDocumentEditor,
116
+ project: () => ({
117
+ execute: resetDocument ?? runtime.resetDocument,
118
+ isHidden: !hasResource,
119
+ }),
120
+ }),
121
+ createPresentationActionRuntimeBinding<TExecuteContext, TLabel>({
122
+ id: 'format-json-document',
123
+ localDocumentEditorKind: localDocumentEditorActionKinds.format,
124
+ semanticsKind: actionSemanticsKinds.localDocumentEditor,
125
+ project: () => ({
126
+ execute: formatDocument ?? runtime.formatDocument,
127
+ isDisabled: !jsonValidation.ok,
128
+ isHidden: !hasResource,
129
+ }),
130
+ }),
131
+ ]
132
+ }