@cohesivesystems/presentation-react-shadcn 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 (262) hide show
  1. package/LICENSE +55 -0
  2. package/dist/document-workspace-surface-slot-renderers.d.ts +58 -0
  3. package/dist/document-workspace-surface-slot-renderers.d.ts.map +1 -0
  4. package/dist/document-workspace-surface-slot-renderers.js +206 -0
  5. package/dist/document-workspace-surface-slot-renderers.js.map +1 -0
  6. package/dist/index.d.ts +53 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +53 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/navigation-shell-frame-renderer-registry.d.ts +8 -0
  11. package/dist/navigation-shell-frame-renderer-registry.d.ts.map +1 -0
  12. package/dist/navigation-shell-frame-renderer-registry.js +2 -0
  13. package/dist/navigation-shell-frame-renderer-registry.js.map +1 -0
  14. package/dist/navigation-shell-slot-renderer-registry.d.ts +9 -0
  15. package/dist/navigation-shell-slot-renderer-registry.d.ts.map +1 -0
  16. package/dist/navigation-shell-slot-renderer-registry.js +2 -0
  17. package/dist/navigation-shell-slot-renderer-registry.js.map +1 -0
  18. package/dist/page-host-unavailable-renderer.d.ts +10 -0
  19. package/dist/page-host-unavailable-renderer.d.ts.map +1 -0
  20. package/dist/page-host-unavailable-renderer.js +27 -0
  21. package/dist/page-host-unavailable-renderer.js.map +1 -0
  22. package/dist/presentation-action-group.d.ts +99 -0
  23. package/dist/presentation-action-group.d.ts.map +1 -0
  24. package/dist/presentation-action-group.js +214 -0
  25. package/dist/presentation-action-group.js.map +1 -0
  26. package/dist/presentation-badge-target-interpreter.d.ts +26 -0
  27. package/dist/presentation-badge-target-interpreter.d.ts.map +1 -0
  28. package/dist/presentation-badge-target-interpreter.js +17 -0
  29. package/dist/presentation-badge-target-interpreter.js.map +1 -0
  30. package/dist/presentation-component-groups.d.ts +968 -0
  31. package/dist/presentation-component-groups.d.ts.map +1 -0
  32. package/dist/presentation-component-groups.js +505 -0
  33. package/dist/presentation-component-groups.js.map +1 -0
  34. package/dist/presentation-component-system-diagnostics.d.ts +27 -0
  35. package/dist/presentation-component-system-diagnostics.d.ts.map +1 -0
  36. package/dist/presentation-component-system-diagnostics.js +399 -0
  37. package/dist/presentation-component-system-diagnostics.js.map +1 -0
  38. package/dist/presentation-component-system.d.ts +31 -0
  39. package/dist/presentation-component-system.d.ts.map +1 -0
  40. package/dist/presentation-component-system.js +61 -0
  41. package/dist/presentation-component-system.js.map +1 -0
  42. package/dist/presentation-icon-diagnostics.d.ts +12 -0
  43. package/dist/presentation-icon-diagnostics.d.ts.map +1 -0
  44. package/dist/presentation-icon-diagnostics.js +17 -0
  45. package/dist/presentation-icon-diagnostics.js.map +1 -0
  46. package/dist/presentation-icon-registry.d.ts +28 -0
  47. package/dist/presentation-icon-registry.d.ts.map +1 -0
  48. package/dist/presentation-icon-registry.js +80 -0
  49. package/dist/presentation-icon-registry.js.map +1 -0
  50. package/dist/presentation-projection-trace-panel.d.ts +10 -0
  51. package/dist/presentation-projection-trace-panel.d.ts.map +1 -0
  52. package/dist/presentation-projection-trace-panel.js +48 -0
  53. package/dist/presentation-projection-trace-panel.js.map +1 -0
  54. package/dist/presentation-routed-surface-host.d.ts +19 -0
  55. package/dist/presentation-routed-surface-host.d.ts.map +1 -0
  56. package/dist/presentation-routed-surface-host.js +12 -0
  57. package/dist/presentation-routed-surface-host.js.map +1 -0
  58. package/dist/presentation-shadcn-component-system.d.ts +22 -0
  59. package/dist/presentation-shadcn-component-system.d.ts.map +1 -0
  60. package/dist/presentation-shadcn-component-system.js +2 -0
  61. package/dist/presentation-shadcn-component-system.js.map +1 -0
  62. package/dist/presentation-standard-renderers.d.ts +168 -0
  63. package/dist/presentation-standard-renderers.d.ts.map +1 -0
  64. package/dist/presentation-standard-renderers.js +440 -0
  65. package/dist/presentation-standard-renderers.js.map +1 -0
  66. package/dist/presentation-surface-renderer.d.ts +23 -0
  67. package/dist/presentation-surface-renderer.d.ts.map +1 -0
  68. package/dist/presentation-surface-renderer.js +119 -0
  69. package/dist/presentation-surface-renderer.js.map +1 -0
  70. package/dist/presentation-value-renderers.d.ts +10 -0
  71. package/dist/presentation-value-renderers.d.ts.map +1 -0
  72. package/dist/presentation-value-renderers.js +14 -0
  73. package/dist/presentation-value-renderers.js.map +1 -0
  74. package/dist/process-task-icons.d.ts +49 -0
  75. package/dist/process-task-icons.d.ts.map +1 -0
  76. package/dist/process-task-icons.js +154 -0
  77. package/dist/process-task-icons.js.map +1 -0
  78. package/dist/projected-activity-state.d.ts +17 -0
  79. package/dist/projected-activity-state.d.ts.map +1 -0
  80. package/dist/projected-activity-state.js +22 -0
  81. package/dist/projected-activity-state.js.map +1 -0
  82. package/dist/projected-collection-action-runtime-diagnostics.d.ts +4 -0
  83. package/dist/projected-collection-action-runtime-diagnostics.d.ts.map +1 -0
  84. package/dist/projected-collection-action-runtime-diagnostics.js +9 -0
  85. package/dist/projected-collection-action-runtime-diagnostics.js.map +1 -0
  86. package/dist/projected-collection-view.d.ts +90 -0
  87. package/dist/projected-collection-view.d.ts.map +1 -0
  88. package/dist/projected-collection-view.js +532 -0
  89. package/dist/projected-collection-view.js.map +1 -0
  90. package/dist/projected-document-action-status-notices.d.ts +15 -0
  91. package/dist/projected-document-action-status-notices.d.ts.map +1 -0
  92. package/dist/projected-document-action-status-notices.js +33 -0
  93. package/dist/projected-document-action-status-notices.js.map +1 -0
  94. package/dist/projected-document-badges.d.ts +24 -0
  95. package/dist/projected-document-badges.d.ts.map +1 -0
  96. package/dist/projected-document-badges.js +53 -0
  97. package/dist/projected-document-badges.js.map +1 -0
  98. package/dist/projected-document-editor-surface.d.ts +46 -0
  99. package/dist/projected-document-editor-surface.d.ts.map +1 -0
  100. package/dist/projected-document-editor-surface.js +399 -0
  101. package/dist/projected-document-editor-surface.js.map +1 -0
  102. package/dist/projected-document-workspace-notices.d.ts +24 -0
  103. package/dist/projected-document-workspace-notices.d.ts.map +1 -0
  104. package/dist/projected-document-workspace-notices.js +14 -0
  105. package/dist/projected-document-workspace-notices.js.map +1 -0
  106. package/dist/projected-document-workspace-prompt-child-view-registry.d.ts +25 -0
  107. package/dist/projected-document-workspace-prompt-child-view-registry.d.ts.map +1 -0
  108. package/dist/projected-document-workspace-prompt-child-view-registry.js +41 -0
  109. package/dist/projected-document-workspace-prompt-child-view-registry.js.map +1 -0
  110. package/dist/projected-document-workspace-prompt-child-view-renderers.d.ts +32 -0
  111. package/dist/projected-document-workspace-prompt-child-view-renderers.d.ts.map +1 -0
  112. package/dist/projected-document-workspace-prompt-child-view-renderers.js +77 -0
  113. package/dist/projected-document-workspace-prompt-child-view-renderers.js.map +1 -0
  114. package/dist/projected-document-workspace-shell.d.ts +100 -0
  115. package/dist/projected-document-workspace-shell.d.ts.map +1 -0
  116. package/dist/projected-document-workspace-shell.js +153 -0
  117. package/dist/projected-document-workspace-shell.js.map +1 -0
  118. package/dist/projected-document-workspace.d.ts +39 -0
  119. package/dist/projected-document-workspace.d.ts.map +1 -0
  120. package/dist/projected-document-workspace.js +63 -0
  121. package/dist/projected-document-workspace.js.map +1 -0
  122. package/dist/projected-field-value-rendering.d.ts +94 -0
  123. package/dist/projected-field-value-rendering.d.ts.map +1 -0
  124. package/dist/projected-field-value-rendering.js +377 -0
  125. package/dist/projected-field-value-rendering.js.map +1 -0
  126. package/dist/projected-inline-list.d.ts +20 -0
  127. package/dist/projected-inline-list.d.ts.map +1 -0
  128. package/dist/projected-inline-list.js +149 -0
  129. package/dist/projected-inline-list.js.map +1 -0
  130. package/dist/projected-input-form.d.ts +143 -0
  131. package/dist/projected-input-form.d.ts.map +1 -0
  132. package/dist/projected-input-form.js +612 -0
  133. package/dist/projected-input-form.js.map +1 -0
  134. package/dist/projected-metric-dashboard.d.ts +26 -0
  135. package/dist/projected-metric-dashboard.d.ts.map +1 -0
  136. package/dist/projected-metric-dashboard.js +20 -0
  137. package/dist/projected-metric-dashboard.js.map +1 -0
  138. package/dist/projected-metric-strip.d.ts +20 -0
  139. package/dist/projected-metric-strip.d.ts.map +1 -0
  140. package/dist/projected-metric-strip.js +131 -0
  141. package/dist/projected-metric-strip.js.map +1 -0
  142. package/dist/projected-navigation-shell-view-host.d.ts +34 -0
  143. package/dist/projected-navigation-shell-view-host.d.ts.map +1 -0
  144. package/dist/projected-navigation-shell-view-host.js +75 -0
  145. package/dist/projected-navigation-shell-view-host.js.map +1 -0
  146. package/dist/projected-navigation-shell.d.ts +33 -0
  147. package/dist/projected-navigation-shell.d.ts.map +1 -0
  148. package/dist/projected-navigation-shell.js +112 -0
  149. package/dist/projected-navigation-shell.js.map +1 -0
  150. package/dist/projected-presentation-badges.d.ts +34 -0
  151. package/dist/projected-presentation-badges.d.ts.map +1 -0
  152. package/dist/projected-presentation-badges.js +22 -0
  153. package/dist/projected-presentation-badges.js.map +1 -0
  154. package/dist/projected-presentation-diagnostics.d.ts +10 -0
  155. package/dist/projected-presentation-diagnostics.d.ts.map +1 -0
  156. package/dist/projected-presentation-diagnostics.js +40 -0
  157. package/dist/projected-presentation-diagnostics.js.map +1 -0
  158. package/dist/projected-presentation-flow-layer.d.ts +33 -0
  159. package/dist/projected-presentation-flow-layer.d.ts.map +1 -0
  160. package/dist/projected-presentation-flow-layer.js +71 -0
  161. package/dist/projected-presentation-flow-layer.js.map +1 -0
  162. package/dist/projected-process-task-notices.d.ts +37 -0
  163. package/dist/projected-process-task-notices.d.ts.map +1 -0
  164. package/dist/projected-process-task-notices.js +225 -0
  165. package/dist/projected-process-task-notices.js.map +1 -0
  166. package/dist/projected-prompt-child-view-renderer.d.ts +101 -0
  167. package/dist/projected-prompt-child-view-renderer.d.ts.map +1 -0
  168. package/dist/projected-prompt-child-view-renderer.js +442 -0
  169. package/dist/projected-prompt-child-view-renderer.js.map +1 -0
  170. package/dist/projected-prompt-document-preview.d.ts +39 -0
  171. package/dist/projected-prompt-document-preview.d.ts.map +1 -0
  172. package/dist/projected-prompt-document-preview.js +50 -0
  173. package/dist/projected-prompt-document-preview.js.map +1 -0
  174. package/dist/projected-prompt-view.d.ts +35 -0
  175. package/dist/projected-prompt-view.d.ts.map +1 -0
  176. package/dist/projected-prompt-view.js +292 -0
  177. package/dist/projected-prompt-view.js.map +1 -0
  178. package/dist/projected-query-form.d.ts +56 -0
  179. package/dist/projected-query-form.d.ts.map +1 -0
  180. package/dist/projected-query-form.js +100 -0
  181. package/dist/projected-query-form.js.map +1 -0
  182. package/dist/projected-record-details.d.ts +20 -0
  183. package/dist/projected-record-details.d.ts.map +1 -0
  184. package/dist/projected-record-details.js +60 -0
  185. package/dist/projected-record-details.js.map +1 -0
  186. package/dist/projected-routed-surface-runtime.d.ts +86 -0
  187. package/dist/projected-routed-surface-runtime.d.ts.map +1 -0
  188. package/dist/projected-routed-surface-runtime.js +332 -0
  189. package/dist/projected-routed-surface-runtime.js.map +1 -0
  190. package/dist/projected-tabs-view.d.ts +21 -0
  191. package/dist/projected-tabs-view.d.ts.map +1 -0
  192. package/dist/projected-tabs-view.js +140 -0
  193. package/dist/projected-tabs-view.js.map +1 -0
  194. package/dist/projected-view-chrome.d.ts +15 -0
  195. package/dist/projected-view-chrome.d.ts.map +1 -0
  196. package/dist/projected-view-chrome.js +67 -0
  197. package/dist/projected-view-chrome.js.map +1 -0
  198. package/dist/projected-view-surface.d.ts +34 -0
  199. package/dist/projected-view-surface.d.ts.map +1 -0
  200. package/dist/projected-view-surface.js +40 -0
  201. package/dist/projected-view-surface.js.map +1 -0
  202. package/dist/standard-collection-chrome-slot-renderers.d.ts +26 -0
  203. package/dist/standard-collection-chrome-slot-renderers.d.ts.map +1 -0
  204. package/dist/standard-collection-chrome-slot-renderers.js +250 -0
  205. package/dist/standard-collection-chrome-slot-renderers.js.map +1 -0
  206. package/dist/standard-view-chrome-slot-renderers.d.ts +57 -0
  207. package/dist/standard-view-chrome-slot-renderers.d.ts.map +1 -0
  208. package/dist/standard-view-chrome-slot-renderers.js +614 -0
  209. package/dist/standard-view-chrome-slot-renderers.js.map +1 -0
  210. package/package.json +68 -0
  211. package/src/document-workspace-surface-slot-renderers.tsx +395 -0
  212. package/src/index.ts +53 -0
  213. package/src/navigation-shell-frame-renderer-registry.ts +29 -0
  214. package/src/navigation-shell-slot-renderer-registry.ts +46 -0
  215. package/src/page-host-unavailable-renderer.tsx +79 -0
  216. package/src/presentation-action-group.tsx +475 -0
  217. package/src/presentation-badge-target-interpreter.ts +54 -0
  218. package/src/presentation-component-groups.ts +2505 -0
  219. package/src/presentation-component-system-diagnostics.ts +848 -0
  220. package/src/presentation-component-system.ts +365 -0
  221. package/src/presentation-icon-diagnostics.ts +53 -0
  222. package/src/presentation-icon-registry.tsx +181 -0
  223. package/src/presentation-projection-trace-panel.tsx +140 -0
  224. package/src/presentation-routed-surface-host.tsx +48 -0
  225. package/src/presentation-shadcn-component-system.ts +102 -0
  226. package/src/presentation-standard-renderers.tsx +1290 -0
  227. package/src/presentation-surface-renderer.tsx +263 -0
  228. package/src/presentation-value-renderers.tsx +40 -0
  229. package/src/process-task-icons.tsx +258 -0
  230. package/src/projected-activity-state.tsx +63 -0
  231. package/src/projected-collection-action-runtime-diagnostics.ts +22 -0
  232. package/src/projected-collection-view.tsx +1273 -0
  233. package/src/projected-document-action-status-notices.tsx +66 -0
  234. package/src/projected-document-badges.tsx +134 -0
  235. package/src/projected-document-editor-surface.tsx +808 -0
  236. package/src/projected-document-workspace-notices.tsx +77 -0
  237. package/src/projected-document-workspace-prompt-child-view-registry.ts +99 -0
  238. package/src/projected-document-workspace-prompt-child-view-renderers.tsx +205 -0
  239. package/src/projected-document-workspace-shell.tsx +427 -0
  240. package/src/projected-document-workspace.tsx +216 -0
  241. package/src/projected-field-value-rendering.tsx +704 -0
  242. package/src/projected-inline-list.tsx +434 -0
  243. package/src/projected-input-form.tsx +1218 -0
  244. package/src/projected-metric-dashboard.tsx +106 -0
  245. package/src/projected-metric-strip.tsx +244 -0
  246. package/src/projected-navigation-shell-view-host.tsx +177 -0
  247. package/src/projected-navigation-shell.tsx +219 -0
  248. package/src/projected-presentation-badges.tsx +95 -0
  249. package/src/projected-presentation-diagnostics.tsx +120 -0
  250. package/src/projected-presentation-flow-layer.tsx +186 -0
  251. package/src/projected-process-task-notices.tsx +501 -0
  252. package/src/projected-prompt-child-view-renderer.tsx +698 -0
  253. package/src/projected-prompt-document-preview.tsx +197 -0
  254. package/src/projected-prompt-view.tsx +592 -0
  255. package/src/projected-query-form.tsx +286 -0
  256. package/src/projected-record-details.tsx +133 -0
  257. package/src/projected-routed-surface-runtime.tsx +713 -0
  258. package/src/projected-tabs-view.tsx +308 -0
  259. package/src/projected-view-chrome.tsx +148 -0
  260. package/src/projected-view-surface.tsx +131 -0
  261. package/src/standard-collection-chrome-slot-renderers.tsx +391 -0
  262. package/src/standard-view-chrome-slot-renderers.tsx +1064 -0
@@ -0,0 +1,286 @@
1
+ import {
2
+ createPresentationProjectionDiagnostic,
3
+ createRelationQueryInputFormTarget,
4
+ findPresentationInputForm,
5
+ type PresentationProjectionDiagnostic,
6
+ type PresentationModuleDefinition,
7
+ type PresentationDataSourceResolver,
8
+ type ProjectedInputFormRuntime,
9
+ type ProjectedInputFormValueChangeContext,
10
+ type ProjectedQueryFormActionContext,
11
+ type ProjectedQueryFormRuntime,
12
+ type ProjectedQueryFormValueChangeContext,
13
+ type QueryFormDefinition,
14
+ type ViewDefinition,
15
+ } from '@cohesivesystems/presentation-core'
16
+ import { useMemo } from 'react'
17
+ import { useRegisterPresentationProjectionDiagnostics } from '@cohesivesystems/presentation-react'
18
+ import type {
19
+ PresentationShadcnComponentSystem as PresentationComponentSystem,
20
+ } from './presentation-shadcn-component-system'
21
+ import type { PresentationDesignSystem } from '@cohesivesystems/presentation-tailwind'
22
+ import {
23
+ ProjectedInputForm,
24
+ type ProjectedInputFormChoice,
25
+ type ProjectedInputFormChoiceClassNameContext,
26
+ type ProjectedInputFormChoiceClassNameResolver,
27
+ type ProjectedInputFormChoiceRenderContext,
28
+ type ProjectedInputFormChoiceToneResolver,
29
+ type ProjectedInputFormFieldRenderer,
30
+ type ProjectedInputFormFieldRenderContext,
31
+ } from './projected-input-form'
32
+ import { ProjectedStatusBlock } from './projected-activity-state'
33
+ import type {
34
+ ProjectedViewSurfaceChromeSlotRenderer,
35
+ } from './projected-view-surface'
36
+
37
+ export type {
38
+ ProjectedInputFormChoice as ProjectedQueryFormChoice,
39
+ ProjectedInputFormChoiceClassNameContext as ProjectedQueryFormChoiceClassNameContext,
40
+ ProjectedInputFormChoiceClassNameResolver as ProjectedQueryFormChoiceClassNameResolver,
41
+ ProjectedInputFormChoiceRenderContext as ProjectedQueryFormChoiceRenderContext,
42
+ ProjectedInputFormChoiceToneResolver as ProjectedQueryFormChoiceToneResolver,
43
+ ProjectedInputFormFieldRenderer as ProjectedQueryFormFieldRenderer,
44
+ ProjectedInputFormFieldRenderContext as ProjectedQueryFormFieldRenderContext,
45
+ }
46
+
47
+ export type {
48
+ ProjectedQueryFormActionContext,
49
+ ProjectedQueryFormRuntime,
50
+ ProjectedQueryFormValueChangeContext,
51
+ } from '@cohesivesystems/presentation-core'
52
+
53
+ /**
54
+ * Props required to project a backend-declared query form into React controls.
55
+ *
56
+ * @typeParam TValue - Shape of the caller-owned query state object.
57
+ */
58
+ export interface ProjectedQueryFormProps<TValue extends object = object> {
59
+ /** Optional resolver that maps a choice and tone to toggle styling. */
60
+ readonly choiceToggleClassName?: ProjectedInputFormChoiceClassNameResolver
61
+
62
+ /** Optional resolver that normalizes domain choice metadata into a presentation tone. */
63
+ readonly choiceTone?: ProjectedInputFormChoiceToneResolver
64
+
65
+ /** Class name applied to the projected view surface. */
66
+ readonly className?: string
67
+
68
+ /** Class name applied to projected view chrome after the form body. */
69
+ readonly chromeAfterContentClassName?: string
70
+
71
+ /** Class name applied to projected view chrome before the form body. */
72
+ readonly chromeBeforeContentClassName?: string
73
+
74
+ /** Class name applied to projected view chrome in the surface footer. */
75
+ readonly chromeFooterClassName?: string
76
+
77
+ /** Class name applied to projected view chrome in the surface header. */
78
+ readonly chromeHeaderClassName?: string
79
+
80
+ /** Class name applied to the projected view surface content area. */
81
+ readonly contentClassName?: string
82
+
83
+ /** Component implementation set used for projected form controls. */
84
+ readonly componentSystem: PresentationComponentSystem
85
+
86
+ /** Presentation target component set used to resolve declared icons. */
87
+ readonly componentSet?: string
88
+
89
+ /** Design-system class and semantic resolvers used for projected form layout. */
90
+ readonly designSystem: PresentationDesignSystem
91
+
92
+ /** Resolver for data sources used by field choice sources. */
93
+ readonly dataSourceResolver: PresentationDataSourceResolver
94
+
95
+ /** Field renderer overrides keyed by input-form field id or presentation field id. */
96
+ readonly fieldRenderers?: Readonly<Record<string, ProjectedInputFormFieldRenderer>>
97
+
98
+ /** Presentation module that owns the query form, input form, fields, and actions. */
99
+ readonly module: PresentationModuleDefinition
100
+
101
+ /** Query form to project; null renders a diagnostic status block. */
102
+ readonly queryForm: QueryFormDefinition | null
103
+
104
+ /** Runtime state and action handlers; null renders a diagnostic status block. */
105
+ readonly runtime: ProjectedQueryFormRuntime<TValue> | null
106
+
107
+ /** Interprets non-form view chrome slots declared by the hosting view. */
108
+ readonly renderChromeSlot?: ProjectedViewSurfaceChromeSlotRenderer
109
+
110
+ /** View that hosts the query form and supplies surface identity. */
111
+ readonly view: ViewDefinition
112
+ }
113
+
114
+ /**
115
+ * Projects a relation-query specialization by delegating the interaction surface
116
+ * to the generic input-form renderer.
117
+ */
118
+ export function ProjectedQueryForm<TValue extends object = object>({
119
+ choiceToggleClassName,
120
+ choiceTone,
121
+ className,
122
+ chromeAfterContentClassName,
123
+ chromeBeforeContentClassName,
124
+ chromeFooterClassName,
125
+ chromeHeaderClassName,
126
+ componentSet,
127
+ componentSystem,
128
+ contentClassName,
129
+ dataSourceResolver,
130
+ designSystem,
131
+ fieldRenderers,
132
+ module,
133
+ queryForm,
134
+ renderChromeSlot,
135
+ runtime,
136
+ view,
137
+ }: ProjectedQueryFormProps<TValue>) {
138
+ const inputForm = queryForm
139
+ ? findPresentationInputForm(module, queryForm.FormId)
140
+ : null
141
+ const bindingDiagnosticsSource =
142
+ `projected-query-form-binding:${view.Id}:${queryForm?.Id ?? 'missing'}`
143
+ const bindingDiagnostics = useMemo(
144
+ () => createQueryFormBindingDiagnostics({
145
+ inputForm,
146
+ queryForm,
147
+ source: bindingDiagnosticsSource,
148
+ view,
149
+ }),
150
+ [bindingDiagnosticsSource, inputForm, queryForm, view],
151
+ )
152
+ useRegisterPresentationProjectionDiagnostics(
153
+ bindingDiagnosticsSource,
154
+ bindingDiagnostics,
155
+ )
156
+
157
+ if (!queryForm) {
158
+ return <ProjectedStatusBlock label={`Presentation view '${view.Name}' has no query form binding.`} />
159
+ }
160
+
161
+ if (!inputForm) {
162
+ return null
163
+ }
164
+
165
+ if (!runtime) {
166
+ return <ProjectedStatusBlock label={`Query form '${inputForm.Name}' has no runtime binding.`} />
167
+ }
168
+
169
+ return (
170
+ <ProjectedInputForm
171
+ choiceToggleClassName={choiceToggleClassName}
172
+ choiceTone={choiceTone}
173
+ className={className}
174
+ chromeAfterContentClassName={chromeAfterContentClassName}
175
+ chromeBeforeContentClassName={chromeBeforeContentClassName}
176
+ chromeFooterClassName={chromeFooterClassName}
177
+ chromeHeaderClassName={chromeHeaderClassName}
178
+ componentSystem={componentSystem}
179
+ componentSet={componentSet}
180
+ contentClassName={contentClassName}
181
+ dataSourceResolver={dataSourceResolver}
182
+ designSystem={designSystem}
183
+ fieldRenderers={fieldRenderers}
184
+ inputForm={inputForm}
185
+ module={module}
186
+ renderChromeSlot={renderChromeSlot}
187
+ runtime={createQueryInputFormRuntime(runtime, queryForm)}
188
+ target={createRelationQueryInputFormTarget({
189
+ dataSourceResolver,
190
+ inputForm,
191
+ queryForm,
192
+ view,
193
+ })}
194
+ view={view}
195
+ />
196
+ )
197
+ }
198
+
199
+ function createQueryFormBindingDiagnostics({
200
+ inputForm,
201
+ queryForm,
202
+ source,
203
+ view,
204
+ }: {
205
+ readonly inputForm: ReturnType<typeof findPresentationInputForm>
206
+ readonly queryForm: QueryFormDefinition | null
207
+ readonly source: string
208
+ readonly view: ViewDefinition
209
+ }): readonly PresentationProjectionDiagnostic[] {
210
+ if (!queryForm || inputForm) {
211
+ return []
212
+ }
213
+
214
+ return [
215
+ createPresentationProjectionDiagnostic({
216
+ category: 'missing-definition',
217
+ details: {
218
+ formId: queryForm.FormId,
219
+ queryFormId: queryForm.Id,
220
+ viewId: view.Id,
221
+ },
222
+ id: `query-form.${queryForm.Id}.input-form.${queryForm.FormId}.missing-definition`,
223
+ interpretation: {
224
+ status: 'unbound',
225
+ target: 'query-form-input-form-definition',
226
+ },
227
+ message: `Query form '${queryForm.Id}' has no input form '${queryForm.FormId}'.`,
228
+ severity: 'error',
229
+ source,
230
+ subject: {
231
+ id: queryForm.Id,
232
+ kind: 'query-form',
233
+ name: queryForm.Id,
234
+ },
235
+ suggestedNextStep:
236
+ `Define input form '${queryForm.FormId}' or update query form '${queryForm.Id}' to reference an existing input form.`,
237
+ }),
238
+ ]
239
+ }
240
+
241
+ function createQueryInputFormRuntime<TValue extends object>(
242
+ runtime: ProjectedQueryFormRuntime<TValue>,
243
+ queryForm: QueryFormDefinition,
244
+ ): ProjectedInputFormRuntime<TValue> {
245
+ return {
246
+ invokeAction: ({ choiceValuesByFieldId, inputForm, placement, target, value }) => {
247
+ const queryContext = {
248
+ choiceValuesByFieldId,
249
+ inputForm,
250
+ queryForm,
251
+ stateId: target.stateId,
252
+ value,
253
+ } satisfies ProjectedQueryFormActionContext<TValue>
254
+
255
+ if (isResetAction(placement.ActionId)) {
256
+ runtime.reset(queryContext)
257
+ return
258
+ }
259
+
260
+ runtime.apply(queryContext)
261
+ },
262
+ setValue: (update, context) =>
263
+ runtime.setValue(
264
+ update,
265
+ context ? createQueryFormValueChangeContext(queryForm, context) : undefined,
266
+ ),
267
+ value: runtime.value,
268
+ }
269
+ }
270
+
271
+ function createQueryFormValueChangeContext<TValue extends object>(
272
+ queryForm: QueryFormDefinition,
273
+ context: ProjectedInputFormValueChangeContext<TValue>,
274
+ ): ProjectedQueryFormValueChangeContext<TValue> {
275
+ return {
276
+ choiceValuesByFieldId: context.choiceValuesByFieldId,
277
+ inputForm: context.inputForm,
278
+ queryForm,
279
+ stateId: context.target.stateId,
280
+ value: context.value,
281
+ }
282
+ }
283
+
284
+ function isResetAction(actionId: string) {
285
+ return actionId.toLocaleLowerCase().includes('reset')
286
+ }
@@ -0,0 +1,133 @@
1
+ import { type ReactNode } from 'react'
2
+
3
+ import {
4
+ findPresentationField,
5
+ findPresentationView,
6
+ getPresentationViewProjectedFieldIds,
7
+ readObjectPath,
8
+ type FieldPresentationDefinition,
9
+ type PresentationHrefNavigator,
10
+ type PresentationNavigationHrefFactory,
11
+ type ViewDefinition,
12
+ } from '@cohesivesystems/presentation-core'
13
+ import {
14
+ usePresentationModule,
15
+ usePresentationNavigationRuntime,
16
+ } from '@cohesivesystems/presentation-react'
17
+ import type {
18
+ PresentationShadcnComponentSystem as PresentationComponentSystem,
19
+ } from './presentation-shadcn-component-system'
20
+ import {
21
+ renderProjectedFieldValue,
22
+ } from './projected-field-value-rendering'
23
+
24
+ export interface ProjectedRecordFieldRenderContext<TData extends object> {
25
+ readonly field: FieldPresentationDefinition
26
+ readonly record: TData
27
+ readonly value: unknown
28
+ }
29
+
30
+ export interface ProjectedRecordDetailsProps<TData extends object> {
31
+ readonly componentSystem: PresentationComponentSystem
32
+ readonly createHref?: PresentationNavigationHrefFactory
33
+ readonly data: TData
34
+ readonly emptyMessage?: string
35
+ readonly fieldRenderers?: Record<
36
+ string,
37
+ (context: ProjectedRecordFieldRenderContext<TData>) => ReactNode
38
+ >
39
+ readonly hiddenFieldLabels?: readonly string[]
40
+ readonly navigateHref?: PresentationHrefNavigator
41
+ readonly viewId: string
42
+ }
43
+
44
+ export function ProjectedRecordDetails<TData extends object>({
45
+ componentSystem,
46
+ createHref: createHrefOverride,
47
+ data,
48
+ emptyMessage = 'No details are available.',
49
+ fieldRenderers,
50
+ hiddenFieldLabels = [],
51
+ navigateHref: navigateHrefOverride,
52
+ viewId,
53
+ }: ProjectedRecordDetailsProps<TData>) {
54
+ const module = usePresentationModule()
55
+ const navigation = usePresentationNavigationRuntime()
56
+ const createHref = createHrefOverride ?? navigation.createHref
57
+ const navigateHref = navigateHrefOverride ?? navigation.navigateHref
58
+ const view = findPresentationView<ViewDefinition>(module, viewId)
59
+ const fields =
60
+ (view ? getPresentationViewProjectedFieldIds(view) : []).flatMap((fieldId) => {
61
+ const field = findPresentationField<FieldPresentationDefinition>(module, fieldId)
62
+ return field ? [field] : []
63
+ })
64
+ const RecordDetailEmptyState = componentSystem.records.RecordDetailEmptyState
65
+ const RecordDetailField = componentSystem.records.RecordDetailField
66
+ const RecordDetails = componentSystem.records.RecordDetails
67
+
68
+ if (!module || !view || fields.length === 0) {
69
+ return (
70
+ <RecordDetailEmptyState label={emptyMessage} viewId={viewId} />
71
+ )
72
+ }
73
+
74
+ return (
75
+ <RecordDetails viewId={viewId}>
76
+ {fields.map((field) => {
77
+ const value = readProjectedValue(data, field.Field)
78
+ const renderer = fieldRenderers?.[field.Id] ?? fieldRenderers?.[field.Field]
79
+ const hideLabel = isFieldLabelHidden(field, hiddenFieldLabels)
80
+ const renderedValue = renderer
81
+ ? renderer({ field, record: data, value })
82
+ : renderProjectedFieldValue({
83
+ componentSystem,
84
+ createHref,
85
+ emptyValueFallback: <span className="text-slate-400">n/a</span>,
86
+ field,
87
+ module,
88
+ navigateHref,
89
+ resource: data,
90
+ value,
91
+ })
92
+ return (
93
+ <RecordDetailField
94
+ fieldId={field.Id}
95
+ hideLabel={hideLabel}
96
+ key={field.Id}
97
+ label={field.Label}
98
+ value={renderedValue}
99
+ />
100
+ )
101
+ })}
102
+ </RecordDetails>
103
+ )
104
+ }
105
+
106
+ function isFieldLabelHidden(
107
+ field: FieldPresentationDefinition,
108
+ hiddenFieldLabels: readonly string[],
109
+ ) {
110
+ return hiddenFieldLabels.includes(field.Id) || hiddenFieldLabels.includes(field.Field)
111
+ }
112
+
113
+ function readProjectedValue<TData extends object>(row: TData, fieldPath: string) {
114
+ const exactValue = readObjectPath(row, fieldPath)
115
+ if (exactValue !== undefined) {
116
+ return exactValue
117
+ }
118
+
119
+ const fieldName = fieldPath.split('.').at(-1) ?? fieldPath
120
+ return readObjectProperty(row, fieldName)
121
+ }
122
+
123
+ function readObjectProperty<TData extends object>(row: TData, propertyName: string) {
124
+ const record = row as Record<string, unknown>
125
+ if (Object.prototype.hasOwnProperty.call(record, propertyName)) {
126
+ return record[propertyName]
127
+ }
128
+
129
+ const match = Object.keys(record).find(
130
+ (candidate) => candidate.toLocaleLowerCase() === propertyName.toLocaleLowerCase(),
131
+ )
132
+ return match ? record[match] : undefined
133
+ }