@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,592 @@
1
+ import { Fragment, useEffect, useMemo, type MouseEvent, type ReactNode } from 'react'
2
+
3
+ import {
4
+ findPresentationAction,
5
+ getPresentationViewProjectedActionPlacements,
6
+ isPresentationViewFetching,
7
+ isViewChromeSlotKind,
8
+ isViewChromeSlotPlacementValue,
9
+ promptChromeIconIds,
10
+ resolvePresentationViewDataSourceIds,
11
+ type ActionDefinition,
12
+ type ActionPlacementDefinition,
13
+ type PresentationDataSourceResolver,
14
+ type PresentationModuleDefinition,
15
+ type ViewChromeSlotDefinition,
16
+ type ViewDefinition,
17
+ type ViewRegionDefinition,
18
+ } from '@cohesivesystems/presentation-core'
19
+ import {
20
+ PresentationActionGroup,
21
+ type PresentationActionGroupOptions,
22
+ type PresentationActionRenderContext,
23
+ } from './presentation-action-group'
24
+ import type {
25
+ PresentationShadcnComponentSystem as PresentationComponentSystem,
26
+ } from './presentation-shadcn-component-system'
27
+ import type { PresentationDesignSystem } from '@cohesivesystems/presentation-tailwind'
28
+ import {
29
+ renderPresentationIcon,
30
+ } from './presentation-icon-registry'
31
+ import {
32
+ projectPresentationIconDiagnostics,
33
+ } from './presentation-icon-diagnostics'
34
+ import {
35
+ useRegisterPresentationProjectionDiagnostics,
36
+ } from '@cohesivesystems/presentation-react'
37
+ import {
38
+ ProjectedViewChrome,
39
+ resolveViewChromeSlotPlacement,
40
+ } from './projected-view-chrome'
41
+ import type {
42
+ ProjectedViewSurfaceChromeSlotRenderer,
43
+ } from './projected-view-surface'
44
+ import {
45
+ viewChromeSlotKinds,
46
+ viewChromeSlotPlacements,
47
+ viewRegionKinds,
48
+ } from '@cohesivesystems/presentation-contracts'
49
+
50
+ export interface ProjectedPromptViewProps<TContext> {
51
+ readonly actionGroupOptions?: PresentationActionGroupOptions<TContext>
52
+ readonly actionRegionId?: string
53
+ readonly className?: string
54
+ readonly componentSystem: PresentationComponentSystem
55
+ readonly contentClassName?: string
56
+ readonly context: TContext
57
+ readonly dataSourceResolver: PresentationDataSourceResolver
58
+ readonly designSystem: PresentationDesignSystem
59
+ readonly description?: ReactNode
60
+ readonly module: PresentationModuleDefinition
61
+ readonly regionRenderers?: Readonly<Record<string, ProjectedPromptRegionRenderer<TContext>>>
62
+ readonly renderChromeSlot?: ProjectedViewSurfaceChromeSlotRenderer
63
+ readonly renderRegion?: ProjectedPromptRegionRenderer<TContext>
64
+ readonly renderView?: (viewId: string) => ReactNode
65
+ readonly title?: ReactNode
66
+ readonly view: ViewDefinition
67
+ }
68
+
69
+ export interface ProjectedPromptRegionRenderContext<TContext> {
70
+ readonly context: TContext
71
+ readonly dataSourceResolver: PresentationDataSourceResolver
72
+ readonly module: PresentationModuleDefinition
73
+ readonly region: ViewRegionDefinition
74
+ readonly renderView?: (viewId: string) => ReactNode
75
+ readonly view: ViewDefinition
76
+ }
77
+
78
+ export type ProjectedPromptRegionRenderer<TContext> = (
79
+ context: ProjectedPromptRegionRenderContext<TContext>,
80
+ ) => ReactNode | undefined
81
+
82
+ export function ProjectedPromptView<TContext>({
83
+ actionGroupOptions,
84
+ actionRegionId = 'footer',
85
+ className,
86
+ componentSystem,
87
+ contentClassName,
88
+ context,
89
+ dataSourceResolver,
90
+ designSystem,
91
+ description,
92
+ module,
93
+ regionRenderers,
94
+ renderChromeSlot,
95
+ renderRegion,
96
+ renderView,
97
+ title,
98
+ view,
99
+ }: ProjectedPromptViewProps<TContext>) {
100
+ const titleId = `${toDomId(view.Id)}-title`
101
+ const ActionButton = componentSystem.actions.ActionButton
102
+ const layoutClasses = resolvePromptLayoutClasses(view, dataSourceResolver)
103
+ const bodyRegions = view.Regions.filter((region) => !isActionRegion(region, actionRegionId))
104
+ const actionView = {
105
+ ...view,
106
+ Actions: getPresentationViewProjectedActionPlacements(view)
107
+ .filter((action) => action.Region === actionRegionId),
108
+ Chrome: null,
109
+ } satisfies ViewDefinition
110
+ const hasFooterActionChrome = hasActionChromeSlotAtPlacement(
111
+ view,
112
+ viewChromeSlotPlacements.footer,
113
+ )
114
+ const hasDescriptionStatusChrome =
115
+ Boolean(renderChromeSlot) &&
116
+ hasStatusChromeSlotAtPlacement(view, viewChromeSlotPlacements.beforeContent)
117
+ const dismissAction = resolvePromptDismissAction({
118
+ actionGroupOptions,
119
+ context,
120
+ dataSourceResolver,
121
+ module,
122
+ view,
123
+ })
124
+ const promptIconDiagnostics = useMemo(
125
+ () => projectPresentationIconDiagnostics({
126
+ icons: view.PromptDismiss?.ShowCloseButton
127
+ ? [{
128
+ icon: promptChromeIconIds.close,
129
+ id: `${view.Id}:close`,
130
+ kind: 'prompt-chrome-icon',
131
+ label: 'Close prompt',
132
+ }]
133
+ : [],
134
+ module,
135
+ source: `projected-prompt-icons:${view.Id}`,
136
+ surfaceId: view.Id,
137
+ surfaceName: view.Name,
138
+ }),
139
+ [
140
+ module,
141
+ view.Id,
142
+ view.Name,
143
+ view.PromptDismiss?.ShowCloseButton,
144
+ ],
145
+ )
146
+ useRegisterPresentationProjectionDiagnostics(
147
+ `projected-prompt-icons:${view.Id}`,
148
+ promptIconDiagnostics,
149
+ )
150
+
151
+ useEffect(() => {
152
+ if (
153
+ !view.PromptDismiss?.DismissOnEscape ||
154
+ !dismissAction ||
155
+ dismissAction.isHidden ||
156
+ !dismissAction.canDismiss
157
+ ) {
158
+ return
159
+ }
160
+
161
+ const executeDismiss = dismissAction.execute
162
+ function handleKeyDown(event: KeyboardEvent) {
163
+ if (event.key !== 'Escape') {
164
+ return
165
+ }
166
+
167
+ event.preventDefault()
168
+ executeDismiss()
169
+ }
170
+
171
+ window.addEventListener('keydown', handleKeyDown)
172
+ return () => window.removeEventListener('keydown', handleKeyDown)
173
+ }, [dismissAction, view.PromptDismiss?.DismissOnEscape])
174
+
175
+ function handleBackdropMouseDown(event: MouseEvent<HTMLDivElement>) {
176
+ if (
177
+ event.target !== event.currentTarget ||
178
+ !view.PromptDismiss?.DismissOnBackdrop ||
179
+ !dismissAction ||
180
+ dismissAction.isHidden ||
181
+ !dismissAction.canDismiss
182
+ ) {
183
+ return
184
+ }
185
+
186
+ event.preventDefault()
187
+ dismissAction.execute()
188
+ }
189
+ const renderPromptChromeSlot = (
190
+ slot: ViewChromeSlotDefinition,
191
+ chromeView: ViewDefinition | null,
192
+ ) => {
193
+ if (isViewChromeSlotKind(slot, viewChromeSlotKinds.actions)) {
194
+ return renderPromptActionGroup({
195
+ actionGroupOptions,
196
+ actions: slot.Actions.length > 0 ? slot.Actions : actionView.Actions,
197
+ componentSystem,
198
+ context,
199
+ dataSourceResolver,
200
+ designSystem,
201
+ module,
202
+ view,
203
+ })
204
+ }
205
+
206
+ return renderChromeSlot?.(slot, chromeView) ?? null
207
+ }
208
+
209
+ const headerActions = componentSystem.prompts.PromptHeaderActions({
210
+ actions: (
211
+ <ProjectedViewChrome
212
+ componentSystem={componentSystem}
213
+ placement={viewChromeSlotPlacements.header}
214
+ renderSlot={(slot) => renderPromptChromeSlot(slot, view)}
215
+ view={view}
216
+ />
217
+ ),
218
+ closeButton: view.PromptDismiss?.ShowCloseButton && dismissAction && !dismissAction.isHidden ? (
219
+ <ActionButton
220
+ aria-label="Close"
221
+ disabled={!dismissAction.canDismiss}
222
+ onClick={dismissAction.execute}
223
+ size="icon-sm"
224
+ type="button"
225
+ variant="ghost"
226
+ >
227
+ {renderPresentationIcon({
228
+ className: 'size-4',
229
+ icon: promptChromeIconIds.close,
230
+ module,
231
+ })}
232
+ </ActionButton>
233
+ ) : null,
234
+ viewId: view.Id,
235
+ })
236
+ const footer = componentSystem.prompts.PromptFooter({
237
+ children: hasFooterActionChrome ? (
238
+ <ProjectedViewChrome
239
+ componentSystem={componentSystem}
240
+ placement={viewChromeSlotPlacements.footer}
241
+ renderSlot={(slot) => renderPromptChromeSlot(slot, view)}
242
+ view={view}
243
+ />
244
+ ) : (
245
+ renderPromptActionFooter({
246
+ actionGroupOptions,
247
+ componentSystem,
248
+ context,
249
+ dataSourceResolver,
250
+ designSystem,
251
+ module,
252
+ view: actionView,
253
+ })
254
+ ),
255
+ viewId: view.Id,
256
+ })
257
+
258
+ return componentSystem.prompts.PromptModal({
259
+ ariaLabelledBy: titleId,
260
+ className: cn(layoutClasses.containerClassName, className),
261
+ description: description && !hasDescriptionStatusChrome ? description : null,
262
+ footer,
263
+ headerActions,
264
+ onBackdropMouseDown: handleBackdropMouseDown,
265
+ role: view.Accessibility?.Role ?? 'dialog',
266
+ title: title ?? view.Name,
267
+ titleId,
268
+ children: (
269
+ <>
270
+ <ProjectedViewChrome
271
+ componentSystem={componentSystem}
272
+ placement={viewChromeSlotPlacements.beforeContent}
273
+ renderSlot={(slot) => renderPromptChromeSlot(slot, view)}
274
+ view={view}
275
+ />
276
+
277
+ {componentSystem.prompts.PromptContent({
278
+ className: cn(layoutClasses.contentClassName, contentClassName),
279
+ viewId: view.Id,
280
+ children: (
281
+ <>
282
+ {bodyRegions.map((region) => renderPromptRegion({
283
+ componentSystem,
284
+ context,
285
+ dataSourceResolver,
286
+ module,
287
+ region,
288
+ regionRenderers,
289
+ renderRegion,
290
+ renderView,
291
+ view,
292
+ }))}
293
+ </>
294
+ ),
295
+ })}
296
+
297
+ <ProjectedViewChrome
298
+ componentSystem={componentSystem}
299
+ placement={viewChromeSlotPlacements.afterContent}
300
+ renderSlot={(slot) => renderPromptChromeSlot(slot, view)}
301
+ view={view}
302
+ />
303
+ </>
304
+ ),
305
+ })
306
+ }
307
+
308
+ function renderPromptActionFooter<TContext>({
309
+ actionGroupOptions,
310
+ componentSystem,
311
+ context,
312
+ dataSourceResolver,
313
+ designSystem,
314
+ module,
315
+ view,
316
+ }: {
317
+ readonly actionGroupOptions?: PresentationActionGroupOptions<TContext>
318
+ readonly componentSystem: PresentationComponentSystem
319
+ readonly context: TContext
320
+ readonly dataSourceResolver: PresentationDataSourceResolver
321
+ readonly designSystem: PresentationDesignSystem
322
+ readonly module: PresentationModuleDefinition
323
+ readonly view: ViewDefinition
324
+ }) {
325
+ if (view.Actions.length === 0 || !actionGroupOptions) {
326
+ return null
327
+ }
328
+
329
+ return (
330
+ <PresentationActionGroup
331
+ context={context}
332
+ dataSourceResolver={dataSourceResolver}
333
+ module={module}
334
+ options={{
335
+ ...actionGroupOptions,
336
+ className: actionGroupOptions.className ?? 'flex flex-wrap items-center justify-end gap-2',
337
+ componentSystem,
338
+ designSystem,
339
+ }}
340
+ view={view}
341
+ />
342
+ )
343
+ }
344
+
345
+ function renderPromptActionGroup<TContext>({
346
+ actionGroupOptions,
347
+ actions,
348
+ componentSystem,
349
+ context,
350
+ dataSourceResolver,
351
+ designSystem,
352
+ module,
353
+ view,
354
+ }: {
355
+ readonly actionGroupOptions?: PresentationActionGroupOptions<TContext>
356
+ readonly actions: readonly ActionPlacementDefinition[]
357
+ readonly componentSystem: PresentationComponentSystem
358
+ readonly context: TContext
359
+ readonly dataSourceResolver: PresentationDataSourceResolver
360
+ readonly designSystem: PresentationDesignSystem
361
+ readonly module: PresentationModuleDefinition
362
+ readonly view: ViewDefinition
363
+ }) {
364
+ if (actions.length === 0 || !actionGroupOptions) {
365
+ return null
366
+ }
367
+
368
+ return (
369
+ <PresentationActionGroup
370
+ context={context}
371
+ dataSourceResolver={dataSourceResolver}
372
+ module={module}
373
+ options={{
374
+ ...actionGroupOptions,
375
+ className: actionGroupOptions.className ?? 'flex flex-wrap items-center justify-end gap-2',
376
+ componentSystem,
377
+ designSystem,
378
+ }}
379
+ view={{
380
+ ...view,
381
+ Actions: [...actions],
382
+ Chrome: null,
383
+ }}
384
+ />
385
+ )
386
+ }
387
+
388
+ function hasActionChromeSlotAtPlacement(
389
+ view: ViewDefinition,
390
+ placement: string | number,
391
+ ) {
392
+ return view.Chrome?.Slots.some((slot) =>
393
+ isViewChromeSlotKind(slot, viewChromeSlotKinds.actions) &&
394
+ isViewChromeSlotPlacementValue(resolveViewChromeSlotPlacement(slot), placement)) ?? false
395
+ }
396
+
397
+ function hasStatusChromeSlotAtPlacement(
398
+ view: ViewDefinition,
399
+ placement: string | number,
400
+ ) {
401
+ return view.Chrome?.Slots.some((slot) =>
402
+ isViewChromeSlotKind(slot, viewChromeSlotKinds.status) &&
403
+ isViewChromeSlotPlacementValue(resolveViewChromeSlotPlacement(slot), placement)) ?? false
404
+ }
405
+
406
+ function resolvePromptLayoutClasses(
407
+ view: ViewDefinition,
408
+ dataSourceResolver: PresentationDataSourceResolver,
409
+ ) {
410
+ if (view.Design?.Layout === 'expanded') {
411
+ return {
412
+ containerClassName: 'h-full max-w-6xl overflow-hidden',
413
+ contentClassName: 'min-h-0 flex-1 overflow-hidden',
414
+ }
415
+ }
416
+
417
+ if (view.Design?.Layout === 'active-content-expanded' && isPromptContentActive(view, dataSourceResolver)) {
418
+ return {
419
+ containerClassName: 'h-full max-w-6xl overflow-hidden',
420
+ contentClassName: 'min-h-0 flex-1 overflow-hidden',
421
+ }
422
+ }
423
+
424
+ return {}
425
+ }
426
+
427
+ function isPromptContentActive(
428
+ view: ViewDefinition,
429
+ dataSourceResolver: PresentationDataSourceResolver,
430
+ ) {
431
+ return resolvePresentationViewDataSourceIds(view).some((dataSourceId) => {
432
+ const state = dataSourceResolver.resolve(dataSourceId)
433
+ return Boolean(
434
+ state?.isPending ||
435
+ state?.isFetching ||
436
+ state?.data !== null && state?.data !== undefined,
437
+ )
438
+ })
439
+ }
440
+
441
+ function renderPromptRegion<TContext>({
442
+ componentSystem,
443
+ context,
444
+ dataSourceResolver,
445
+ module,
446
+ region,
447
+ regionRenderers,
448
+ renderRegion,
449
+ renderView,
450
+ view,
451
+ }: ProjectedPromptRegionRenderContext<TContext> & {
452
+ readonly componentSystem: PresentationComponentSystem
453
+ readonly regionRenderers?: Readonly<Record<string, ProjectedPromptRegionRenderer<TContext>>>
454
+ readonly renderRegion?: ProjectedPromptRegionRenderer<TContext>
455
+ }) {
456
+ const regionContext = {
457
+ context,
458
+ dataSourceResolver,
459
+ module,
460
+ region,
461
+ renderView,
462
+ view,
463
+ } satisfies ProjectedPromptRegionRenderContext<TContext>
464
+ const rendered = regionRenderers?.[region.Id]?.(regionContext) ?? renderRegion?.(regionContext)
465
+ if (rendered !== undefined) {
466
+ return (
467
+ <Fragment key={region.Id}>
468
+ {componentSystem.prompts.PromptRegion({
469
+ region,
470
+ viewId: view.Id,
471
+ children: rendered,
472
+ })}
473
+ </Fragment>
474
+ )
475
+ }
476
+
477
+ if (!renderView || region.ViewIds.length === 0) {
478
+ return null
479
+ }
480
+
481
+ return (
482
+ <Fragment key={region.Id}>
483
+ {componentSystem.prompts.PromptRegion({
484
+ region,
485
+ viewId: view.Id,
486
+ children: region.ViewIds.map((viewId) => (
487
+ <div className="h-full min-h-0" key={viewId}>
488
+ {renderView(viewId)}
489
+ </div>
490
+ )),
491
+ })}
492
+ </Fragment>
493
+ )
494
+ }
495
+
496
+ function isActionRegion(region: ViewRegionDefinition, actionRegionId: string) {
497
+ return region.Id === actionRegionId || region.Kind === viewRegionKinds.footer
498
+ }
499
+
500
+ function resolvePromptDismissAction<TContext>({
501
+ actionGroupOptions,
502
+ context,
503
+ dataSourceResolver,
504
+ module,
505
+ view,
506
+ }: {
507
+ readonly actionGroupOptions?: PresentationActionGroupOptions<TContext>
508
+ readonly context: TContext
509
+ readonly dataSourceResolver: PresentationDataSourceResolver
510
+ readonly module: PresentationModuleDefinition
511
+ readonly view: ViewDefinition
512
+ }) {
513
+ const dismissPolicy = view.PromptDismiss
514
+ if (!dismissPolicy || !actionGroupOptions?.executeAction) {
515
+ return null
516
+ }
517
+
518
+ const placement =
519
+ getPresentationViewProjectedActionPlacements(view)
520
+ .find((candidate) => candidate.ActionId === dismissPolicy.DismissActionId) ??
521
+ ({
522
+ ActionId: dismissPolicy.DismissActionId,
523
+ Icon: 'x',
524
+ Label: 'Close',
525
+ Region: 'dismiss',
526
+ } satisfies ActionPlacementDefinition)
527
+ const action = findPresentationAction<ActionDefinition>(
528
+ module,
529
+ placement.ActionId,
530
+ )
531
+ const invalidatedDataSourceIds =
532
+ action?.Result?.InvalidateDataSourceIds ??
533
+ resolvePresentationViewDataSourceIds(view)
534
+ const isFetching = isPresentationViewFetching(
535
+ {
536
+ ...view,
537
+ DataSourceIds: invalidatedDataSourceIds,
538
+ },
539
+ dataSourceResolver,
540
+ )
541
+ const baseContext = {
542
+ action,
543
+ context,
544
+ dataSourceResolver,
545
+ invalidatedDataSourceIds,
546
+ isFetching,
547
+ module,
548
+ placement,
549
+ view,
550
+ } satisfies PresentationActionRenderContext<TContext>
551
+ const resolvedInvalidatedDataSourceIds =
552
+ actionGroupOptions.resolveInvalidatedDataSourceIds?.(baseContext) ??
553
+ invalidatedDataSourceIds
554
+ const resolvedContext = {
555
+ ...baseContext,
556
+ invalidatedDataSourceIds: resolvedInvalidatedDataSourceIds,
557
+ } satisfies PresentationActionRenderContext<TContext>
558
+ const actionState = actionGroupOptions.resolveActionState?.(resolvedContext) ?? {}
559
+ const isBlocked = resolvedInvalidatedDataSourceIds.some(
560
+ (dataSourceId) => dataSourceResolver.resolve(dataSourceId)?.isBlocked,
561
+ )
562
+ const canExecute = actionGroupOptions.canExecuteAction?.(resolvedContext) ?? true
563
+ const isHidden = Boolean(actionState.isHidden)
564
+ const isPending = Boolean(actionState.isPending)
565
+ const canDismiss = Boolean(
566
+ canExecute &&
567
+ !actionState.isDisabled &&
568
+ !isBlocked &&
569
+ !isFetching &&
570
+ (!dismissPolicy.DisableWhenActionPending || !isPending),
571
+ )
572
+
573
+ return {
574
+ canDismiss,
575
+ execute: () => {
576
+ if (isHidden || !canDismiss) {
577
+ return
578
+ }
579
+
580
+ void actionGroupOptions.executeAction?.(resolvedContext)
581
+ },
582
+ isHidden,
583
+ }
584
+ }
585
+
586
+ function toDomId(value: string) {
587
+ return value.replace(/[^a-zA-Z0-9_-]+/g, '-')
588
+ }
589
+
590
+ function cn(...values: readonly (false | null | string | undefined)[]) {
591
+ return values.filter(Boolean).join(' ')
592
+ }