@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,106 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ import {
4
+ findPresentationView,
5
+ getPresentationViewProjectedFieldIds,
6
+ isViewChromeSlotKind,
7
+ type PresentationDataSourceResolver,
8
+ type ViewDefinition,
9
+ } from '@cohesivesystems/presentation-core'
10
+ import type {
11
+ PresentationShadcnComponentSystem as PresentationComponentSystem,
12
+ } from './presentation-shadcn-component-system'
13
+ import { usePresentationModule } from '@cohesivesystems/presentation-react'
14
+ import { ProjectedMetricStrip, type ProjectedMetricValue } from './projected-metric-strip'
15
+ import {
16
+ ProjectedViewSurface,
17
+ type ProjectedViewSurfaceChromeSlotRenderer,
18
+ } from './projected-view-surface'
19
+ import { viewChromeSlotKinds } from '@cohesivesystems/presentation-contracts'
20
+
21
+ export interface ProjectedMetricDashboardProps {
22
+ readonly action?: ReactNode
23
+ readonly children?: ReactNode
24
+ readonly className?: string
25
+ readonly chromeAfterContentClassName?: string
26
+ readonly chromeBeforeContentClassName?: string
27
+ readonly chromeFooterClassName?: string
28
+ readonly chromeHeaderClassName?: string
29
+ readonly componentSystem: PresentationComponentSystem
30
+ readonly contentClassName?: string
31
+ readonly dataSourceResolver?: PresentationDataSourceResolver
32
+ readonly description?: string
33
+ readonly iconByFieldId?: Readonly<Record<string, ReactNode>>
34
+ readonly metricValues?: Readonly<Record<string, ProjectedMetricValue>>
35
+ readonly renderChromeSlot?: ProjectedViewSurfaceChromeSlotRenderer
36
+ readonly title?: string
37
+ readonly view?: ViewDefinition | null
38
+ readonly viewId: string
39
+ }
40
+
41
+ export function ProjectedMetricDashboard({
42
+ action,
43
+ children,
44
+ className,
45
+ chromeAfterContentClassName,
46
+ chromeBeforeContentClassName,
47
+ chromeFooterClassName,
48
+ chromeHeaderClassName,
49
+ componentSystem,
50
+ contentClassName = 'grid gap-4',
51
+ dataSourceResolver,
52
+ description,
53
+ iconByFieldId,
54
+ metricValues,
55
+ renderChromeSlot,
56
+ title,
57
+ view: viewOverride,
58
+ viewId,
59
+ }: ProjectedMetricDashboardProps) {
60
+ const module = usePresentationModule()
61
+ const view = viewOverride ?? findPresentationView<ViewDefinition>(module, viewId)
62
+ const renderLegacyMetricStrip = !renderChromeSlot || !hasMetricStripChromeSlot(view)
63
+
64
+ return (
65
+ <ProjectedViewSurface
66
+ action={action}
67
+ className={className}
68
+ chromeAfterContentClassName={chromeAfterContentClassName}
69
+ chromeBeforeContentClassName={chromeBeforeContentClassName}
70
+ chromeFooterClassName={chromeFooterClassName}
71
+ chromeHeaderClassName={chromeHeaderClassName}
72
+ collapsible={view?.Chrome?.Collapsible ?? true}
73
+ collapseLabel={view?.Name ?? 'summary'}
74
+ componentSystem={componentSystem}
75
+ contentClassName={contentClassName}
76
+ description={description}
77
+ renderChromeSlot={renderChromeSlot}
78
+ title={title}
79
+ view={view}
80
+ >
81
+ {renderLegacyMetricStrip ? (
82
+ <ProjectedMetricStrip
83
+ componentSystem={componentSystem}
84
+ dataSourceResolver={dataSourceResolver}
85
+ fieldIds={readMetricFieldIds(view)}
86
+ iconByFieldId={iconByFieldId}
87
+ values={metricValues}
88
+ viewId={viewId}
89
+ />
90
+ ) : null}
91
+ {children}
92
+ </ProjectedViewSurface>
93
+ )
94
+ }
95
+
96
+ function readMetricFieldIds(view: ViewDefinition | null) {
97
+ const metricSlot = view?.Chrome?.Slots?.find(
98
+ (slot) => isViewChromeSlotKind(slot, viewChromeSlotKinds.metricStrip),
99
+ )
100
+ return metricSlot?.FieldIds ?? (view ? getPresentationViewProjectedFieldIds(view) : undefined)
101
+ }
102
+
103
+ function hasMetricStripChromeSlot(view: ViewDefinition | null) {
104
+ return view?.Chrome?.Slots.some((slot) =>
105
+ isViewChromeSlotKind(slot, viewChromeSlotKinds.metricStrip)) ?? false
106
+ }
@@ -0,0 +1,244 @@
1
+ import { Fragment, useMemo, type ReactNode } from 'react'
2
+
3
+ import {
4
+ findPresentationField,
5
+ findPresentationView,
6
+ getPresentationViewProjectedFieldIds,
7
+ type PresentationDataSourceResolver,
8
+ type FieldPresentationDefinition,
9
+ type ViewDefinition,
10
+ } from '@cohesivesystems/presentation-core'
11
+ import {
12
+ renderPresentationIcon,
13
+ } from './presentation-icon-registry'
14
+ import {
15
+ projectPresentationIconDiagnostics,
16
+ } from './presentation-icon-diagnostics'
17
+ import type {
18
+ PresentationShadcnComponentSystem as PresentationComponentSystem,
19
+ } from './presentation-shadcn-component-system'
20
+ import {
21
+ usePresentationModule,
22
+ useRegisterPresentationProjectionDiagnostics,
23
+ } from '@cohesivesystems/presentation-react'
24
+ import { fieldDisplayKinds } from '@cohesivesystems/presentation-contracts'
25
+
26
+ export interface ProjectedMetricValue {
27
+ readonly icon?: ReactNode
28
+ readonly label?: string
29
+ readonly value: ReactNode
30
+ readonly variant?: 'number' | 'text'
31
+ }
32
+
33
+ export interface ProjectedMetricStripProps {
34
+ readonly className?: string
35
+ readonly componentSystem: PresentationComponentSystem
36
+ readonly dataSourceResolver?: PresentationDataSourceResolver
37
+ readonly fieldIds?: readonly string[]
38
+ readonly iconByFieldId?: Readonly<Record<string, ReactNode>>
39
+ readonly values?: Readonly<Record<string, ProjectedMetricValue>>
40
+ readonly viewId?: string
41
+ }
42
+
43
+ const emptyMetricValues: Readonly<Record<string, ProjectedMetricValue>> = {}
44
+
45
+ export function ProjectedMetricStrip({
46
+ className,
47
+ componentSystem,
48
+ dataSourceResolver,
49
+ fieldIds,
50
+ iconByFieldId,
51
+ values,
52
+ viewId,
53
+ }: ProjectedMetricStripProps) {
54
+ const module = usePresentationModule()
55
+ const resolvedValues = values ?? emptyMetricValues
56
+ const view = viewId ? findPresentationView<ViewDefinition>(module, viewId) : null
57
+ const items = useMemo(
58
+ () => createMetricItems(module, view, resolvedValues, fieldIds, dataSourceResolver, iconByFieldId),
59
+ [dataSourceResolver, fieldIds, iconByFieldId, module, resolvedValues, view],
60
+ )
61
+ const iconDiagnosticSource = `projected-metric-strip-icons:${view?.Id ?? viewId ?? 'adhoc'}`
62
+ const iconDiagnostics = useMemo(
63
+ () => projectPresentationIconDiagnostics({
64
+ icons: resolveMetricIconSubjects(module, view, resolvedValues, fieldIds),
65
+ module,
66
+ source: iconDiagnosticSource,
67
+ surfaceId: view?.Id ?? viewId,
68
+ surfaceName: view?.Name,
69
+ }),
70
+ [
71
+ fieldIds,
72
+ iconDiagnosticSource,
73
+ module,
74
+ resolvedValues,
75
+ view,
76
+ viewId,
77
+ ],
78
+ )
79
+ useRegisterPresentationProjectionDiagnostics(iconDiagnosticSource, iconDiagnostics)
80
+
81
+ if (items.length === 0) {
82
+ return null
83
+ }
84
+
85
+ return componentSystem.metrics.MetricStrip({
86
+ children: items.map((item) =>
87
+ <Fragment key={item.id}>
88
+ {componentSystem.metrics.MetricItem({
89
+ icon: item.icon,
90
+ id: item.id,
91
+ label: item.label,
92
+ value: item.value,
93
+ variant: item.variant,
94
+ })}
95
+ </Fragment>,
96
+ ),
97
+ className,
98
+ })
99
+ }
100
+
101
+ interface MetricItem extends ProjectedMetricValue {
102
+ readonly id: string
103
+ readonly label: string
104
+ }
105
+
106
+ function createMetricItems(
107
+ module: ReturnType<typeof usePresentationModule>,
108
+ view: ViewDefinition | null,
109
+ values: Readonly<Record<string, ProjectedMetricValue>>,
110
+ fieldIds?: readonly string[],
111
+ dataSourceResolver?: PresentationDataSourceResolver,
112
+ iconByFieldId?: Readonly<Record<string, ReactNode>>,
113
+ ): readonly MetricItem[] {
114
+ const projectedFieldIds = resolveMetricFieldIds(view, values, fieldIds)
115
+ const orderedFieldIds = projectedFieldIds.length > 0 ? projectedFieldIds : Object.keys(values)
116
+
117
+ return orderedFieldIds.flatMap((fieldId) => {
118
+ const field = findPresentationField<FieldPresentationDefinition>(module, fieldId)
119
+ const value = resolveMetricValue(module, fieldId, field, values[fieldId], dataSourceResolver, iconByFieldId)
120
+
121
+ if (!value) {
122
+ return []
123
+ }
124
+
125
+ return [{
126
+ ...value,
127
+ id: fieldId,
128
+ label: value.label ?? field?.Label ?? fieldId,
129
+ variant: value.variant ?? 'number',
130
+ }]
131
+ })
132
+ }
133
+
134
+ function resolveMetricValue(
135
+ module: ReturnType<typeof usePresentationModule>,
136
+ fieldId: string,
137
+ field: FieldPresentationDefinition | null,
138
+ value: ProjectedMetricValue | undefined,
139
+ dataSourceResolver: PresentationDataSourceResolver | undefined,
140
+ iconByFieldId: Readonly<Record<string, ReactNode>> | undefined,
141
+ ) {
142
+ if (!value) {
143
+ return createMetricValue(module, fieldId, field, dataSourceResolver, iconByFieldId)
144
+ }
145
+
146
+ return {
147
+ ...value,
148
+ icon: value.icon ?? iconByFieldId?.[fieldId] ?? renderMetricFieldIcon(module, field),
149
+ }
150
+ }
151
+
152
+ function createMetricValue(
153
+ module: ReturnType<typeof usePresentationModule>,
154
+ fieldId: string,
155
+ field: FieldPresentationDefinition | null,
156
+ dataSourceResolver: PresentationDataSourceResolver | undefined,
157
+ iconByFieldId: Readonly<Record<string, ReactNode>> | undefined,
158
+ ): ProjectedMetricValue | null {
159
+ const value = readMetricFieldValue(field, dataSourceResolver)
160
+ if (value === undefined) {
161
+ return null
162
+ }
163
+
164
+ return {
165
+ icon: iconByFieldId?.[fieldId] ?? renderMetricFieldIcon(module, field),
166
+ value: renderMetricValue(value),
167
+ variant: isTextMetric(field) ? 'text' : 'number',
168
+ }
169
+ }
170
+
171
+ function resolveMetricIconSubjects(
172
+ module: ReturnType<typeof usePresentationModule>,
173
+ view: ViewDefinition | null,
174
+ values: Readonly<Record<string, ProjectedMetricValue>>,
175
+ fieldIds?: readonly string[],
176
+ ) {
177
+ return resolveMetricFieldIds(view, values, fieldIds).flatMap((fieldId) => {
178
+ const field = findPresentationField<FieldPresentationDefinition>(module, fieldId)
179
+ if (!field?.Icon) {
180
+ return []
181
+ }
182
+
183
+ return [{
184
+ details: {
185
+ fieldId,
186
+ },
187
+ icon: field.Icon,
188
+ id: fieldId,
189
+ kind: 'metric-field-icon',
190
+ label: field.Label,
191
+ }]
192
+ })
193
+ }
194
+
195
+ function resolveMetricFieldIds(
196
+ view: ViewDefinition | null,
197
+ values: Readonly<Record<string, ProjectedMetricValue>>,
198
+ fieldIds?: readonly string[],
199
+ ) {
200
+ return fieldIds ?? (view ? getPresentationViewProjectedFieldIds(view) : Object.keys(values))
201
+ }
202
+
203
+ function renderMetricFieldIcon(
204
+ module: ReturnType<typeof usePresentationModule>,
205
+ field: FieldPresentationDefinition | null,
206
+ ) {
207
+ return renderPresentationIcon({
208
+ className: 'size-4',
209
+ icon: field?.Icon,
210
+ module,
211
+ })
212
+ }
213
+
214
+ function readMetricFieldValue(
215
+ field: FieldPresentationDefinition | null,
216
+ dataSourceResolver: PresentationDataSourceResolver | undefined,
217
+ ) {
218
+ if (!field || !dataSourceResolver) {
219
+ return undefined
220
+ }
221
+
222
+ const source = field.Source
223
+ if (source) {
224
+ const sourceValue = dataSourceResolver.readPath(source.DataSourceId, source.FieldPath)
225
+ if (sourceValue !== undefined) {
226
+ return sourceValue
227
+ }
228
+ }
229
+
230
+ const [root, ...path] = field.Field.split('.')
231
+ return root ? dataSourceResolver.readPath(root, path.join('.')) : undefined
232
+ }
233
+
234
+ function renderMetricValue(value: unknown) {
235
+ if (value === null || value === undefined || value === '') {
236
+ return 'none'
237
+ }
238
+
239
+ return String(value)
240
+ }
241
+
242
+ function isTextMetric(field: FieldPresentationDefinition | null) {
243
+ return field?.DisplayKind === fieldDisplayKinds.text
244
+ }
@@ -0,0 +1,177 @@
1
+ import { useMemo } from 'react'
2
+
3
+ import {
4
+ createPresentationSurfaceFromRootView,
5
+ findPresentationView,
6
+ getPresentationSurfaceDataSourceIds,
7
+ projectPresentationDataSourceBindings,
8
+ projectPresentationDataSourceCoverageDiagnostics,
9
+ type PresentationDataSourceBinding,
10
+ type PresentationDataSourceBindingProjectionRegistry,
11
+ type PresentationDataSourceProjectionContext,
12
+ type PresentationDataSourceTargetInterpretation,
13
+ type ViewDefinition,
14
+ } from '@cohesivesystems/presentation-core'
15
+ import {
16
+ PresentationDataSourceBinder,
17
+ usePresentationModule,
18
+ useRegisterPresentationProjectionDiagnostics,
19
+ } from '@cohesivesystems/presentation-react'
20
+ import type {
21
+ PresentationRendererRegistry,
22
+ } from '@cohesivesystems/presentation-react'
23
+ import { PresentationSurfaceRenderer } from './presentation-surface-renderer'
24
+ import { ProjectedStatusBlock } from './projected-activity-state'
25
+ import type {
26
+ NavigationShellRegionDefinition,
27
+ } from '@cohesivesystems/presentation-contracts'
28
+
29
+ export interface ProjectedNavigationShellViewHostProps<TContext> {
30
+ readonly bindings: readonly PresentationDataSourceBinding[]
31
+ readonly componentSet?: string
32
+ readonly context: TContext
33
+ readonly region: NavigationShellRegionDefinition
34
+ readonly rendererRegistry: PresentationRendererRegistry<TContext>
35
+ }
36
+
37
+ export interface ProjectedNavigationShellRegionViewProps<TContext> {
38
+ readonly context: TContext
39
+ readonly dataSourceBindingRegistry: PresentationDataSourceBindingProjectionRegistry
40
+ readonly componentSet?: string
41
+ readonly diagnosticsSourceId?: string
42
+ readonly projectionContext?: PresentationDataSourceProjectionContext
43
+ readonly region: NavigationShellRegionDefinition
44
+ readonly rendererRegistry: PresentationRendererRegistry<TContext>
45
+ readonly targetInterpretation?: PresentationDataSourceTargetInterpretation
46
+ }
47
+
48
+ /**
49
+ * Projects a presentation view referenced by a navigation shell region.
50
+ *
51
+ * Shell regions are persistent app chrome, but their bodies can still be
52
+ * ordinary presentation views with the same data-source and renderer
53
+ * interpretation model used by routed surfaces.
54
+ */
55
+ export function ProjectedNavigationShellViewHost<TContext>({
56
+ bindings,
57
+ componentSet,
58
+ context,
59
+ region,
60
+ rendererRegistry,
61
+ }: ProjectedNavigationShellViewHostProps<TContext>) {
62
+ const module = usePresentationModule()
63
+ const viewId = region.ViewId ?? null
64
+ const rootView = viewId ? findPresentationView<ViewDefinition>(module, viewId) : null
65
+ const surface = useMemo(
66
+ () =>
67
+ rootView
68
+ ? createPresentationSurfaceFromRootView(rootView, {
69
+ id: region.Id,
70
+ })
71
+ : null,
72
+ [region.Id, rootView],
73
+ )
74
+
75
+ if (!viewId) {
76
+ return <ProjectedStatusBlock label={`Shell region '${region.Id}' has no presentation view.`} />
77
+ }
78
+
79
+ return (
80
+ <PresentationDataSourceBinder bindings={bindings}>
81
+ {(dataSources) => (
82
+ <PresentationSurfaceRenderer
83
+ componentSet={componentSet}
84
+ context={context}
85
+ dataSources={dataSources}
86
+ rendererRegistry={rendererRegistry}
87
+ surface={surface}
88
+ />
89
+ )}
90
+ </PresentationDataSourceBinder>
91
+ )
92
+ }
93
+
94
+ /**
95
+ * Projects a shell region ViewId with the same data-source binding and
96
+ * diagnostics pipeline used by routed presentation surfaces.
97
+ */
98
+ export function ProjectedNavigationShellRegionView<TContext>({
99
+ componentSet,
100
+ context,
101
+ dataSourceBindingRegistry,
102
+ diagnosticsSourceId,
103
+ projectionContext = defaultNavigationShellRegionProjectionContext,
104
+ region,
105
+ rendererRegistry,
106
+ targetInterpretation,
107
+ }: ProjectedNavigationShellRegionViewProps<TContext>) {
108
+ const module = usePresentationModule()
109
+ const rootView = region.ViewId
110
+ ? findPresentationView<ViewDefinition>(module, region.ViewId)
111
+ : null
112
+ const surface = useMemo(
113
+ () =>
114
+ rootView
115
+ ? createPresentationSurfaceFromRootView(rootView, { id: region.Id })
116
+ : null,
117
+ [region.Id, rootView],
118
+ )
119
+ const dataSourceIds = useMemo(
120
+ () => getPresentationSurfaceDataSourceIds(module, surface),
121
+ [module, surface],
122
+ )
123
+ const bindings = useMemo(
124
+ () =>
125
+ projectPresentationDataSourceBindings({
126
+ context: projectionContext,
127
+ dataSourceIds,
128
+ module,
129
+ registry: dataSourceBindingRegistry,
130
+ }),
131
+ [
132
+ dataSourceBindingRegistry,
133
+ dataSourceIds,
134
+ module,
135
+ projectionContext,
136
+ ],
137
+ )
138
+ const sourceId = diagnosticsSourceId ?? `navigation-shell-data-sources:${region.Id}`
139
+ const dataSourceCoverageDiagnostics = useMemo(
140
+ () =>
141
+ projectPresentationDataSourceCoverageDiagnostics({
142
+ bindings,
143
+ dataSourceIds,
144
+ module,
145
+ routeParameters: projectionContext.routeParameters,
146
+ sourceId,
147
+ targetInterpretation,
148
+ }),
149
+ [
150
+ bindings,
151
+ dataSourceIds,
152
+ module,
153
+ projectionContext.routeParameters,
154
+ sourceId,
155
+ targetInterpretation,
156
+ ],
157
+ )
158
+ useRegisterPresentationProjectionDiagnostics(
159
+ sourceId,
160
+ dataSourceCoverageDiagnostics,
161
+ )
162
+
163
+ return (
164
+ <ProjectedNavigationShellViewHost
165
+ bindings={bindings}
166
+ componentSet={componentSet}
167
+ context={context}
168
+ region={region}
169
+ rendererRegistry={rendererRegistry}
170
+ />
171
+ )
172
+ }
173
+
174
+ const defaultNavigationShellRegionProjectionContext = {
175
+ routeParameters: {},
176
+ workspaceId: null,
177
+ } satisfies PresentationDataSourceProjectionContext