@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.
- package/LICENSE +55 -0
- package/dist/document-workspace-surface-slot-renderers.d.ts +58 -0
- package/dist/document-workspace-surface-slot-renderers.d.ts.map +1 -0
- package/dist/document-workspace-surface-slot-renderers.js +206 -0
- package/dist/document-workspace-surface-slot-renderers.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/navigation-shell-frame-renderer-registry.d.ts +8 -0
- package/dist/navigation-shell-frame-renderer-registry.d.ts.map +1 -0
- package/dist/navigation-shell-frame-renderer-registry.js +2 -0
- package/dist/navigation-shell-frame-renderer-registry.js.map +1 -0
- package/dist/navigation-shell-slot-renderer-registry.d.ts +9 -0
- package/dist/navigation-shell-slot-renderer-registry.d.ts.map +1 -0
- package/dist/navigation-shell-slot-renderer-registry.js +2 -0
- package/dist/navigation-shell-slot-renderer-registry.js.map +1 -0
- package/dist/page-host-unavailable-renderer.d.ts +10 -0
- package/dist/page-host-unavailable-renderer.d.ts.map +1 -0
- package/dist/page-host-unavailable-renderer.js +27 -0
- package/dist/page-host-unavailable-renderer.js.map +1 -0
- package/dist/presentation-action-group.d.ts +99 -0
- package/dist/presentation-action-group.d.ts.map +1 -0
- package/dist/presentation-action-group.js +214 -0
- package/dist/presentation-action-group.js.map +1 -0
- package/dist/presentation-badge-target-interpreter.d.ts +26 -0
- package/dist/presentation-badge-target-interpreter.d.ts.map +1 -0
- package/dist/presentation-badge-target-interpreter.js +17 -0
- package/dist/presentation-badge-target-interpreter.js.map +1 -0
- package/dist/presentation-component-groups.d.ts +968 -0
- package/dist/presentation-component-groups.d.ts.map +1 -0
- package/dist/presentation-component-groups.js +505 -0
- package/dist/presentation-component-groups.js.map +1 -0
- package/dist/presentation-component-system-diagnostics.d.ts +27 -0
- package/dist/presentation-component-system-diagnostics.d.ts.map +1 -0
- package/dist/presentation-component-system-diagnostics.js +399 -0
- package/dist/presentation-component-system-diagnostics.js.map +1 -0
- package/dist/presentation-component-system.d.ts +31 -0
- package/dist/presentation-component-system.d.ts.map +1 -0
- package/dist/presentation-component-system.js +61 -0
- package/dist/presentation-component-system.js.map +1 -0
- package/dist/presentation-icon-diagnostics.d.ts +12 -0
- package/dist/presentation-icon-diagnostics.d.ts.map +1 -0
- package/dist/presentation-icon-diagnostics.js +17 -0
- package/dist/presentation-icon-diagnostics.js.map +1 -0
- package/dist/presentation-icon-registry.d.ts +28 -0
- package/dist/presentation-icon-registry.d.ts.map +1 -0
- package/dist/presentation-icon-registry.js +80 -0
- package/dist/presentation-icon-registry.js.map +1 -0
- package/dist/presentation-projection-trace-panel.d.ts +10 -0
- package/dist/presentation-projection-trace-panel.d.ts.map +1 -0
- package/dist/presentation-projection-trace-panel.js +48 -0
- package/dist/presentation-projection-trace-panel.js.map +1 -0
- package/dist/presentation-routed-surface-host.d.ts +19 -0
- package/dist/presentation-routed-surface-host.d.ts.map +1 -0
- package/dist/presentation-routed-surface-host.js +12 -0
- package/dist/presentation-routed-surface-host.js.map +1 -0
- package/dist/presentation-shadcn-component-system.d.ts +22 -0
- package/dist/presentation-shadcn-component-system.d.ts.map +1 -0
- package/dist/presentation-shadcn-component-system.js +2 -0
- package/dist/presentation-shadcn-component-system.js.map +1 -0
- package/dist/presentation-standard-renderers.d.ts +168 -0
- package/dist/presentation-standard-renderers.d.ts.map +1 -0
- package/dist/presentation-standard-renderers.js +440 -0
- package/dist/presentation-standard-renderers.js.map +1 -0
- package/dist/presentation-surface-renderer.d.ts +23 -0
- package/dist/presentation-surface-renderer.d.ts.map +1 -0
- package/dist/presentation-surface-renderer.js +119 -0
- package/dist/presentation-surface-renderer.js.map +1 -0
- package/dist/presentation-value-renderers.d.ts +10 -0
- package/dist/presentation-value-renderers.d.ts.map +1 -0
- package/dist/presentation-value-renderers.js +14 -0
- package/dist/presentation-value-renderers.js.map +1 -0
- package/dist/process-task-icons.d.ts +49 -0
- package/dist/process-task-icons.d.ts.map +1 -0
- package/dist/process-task-icons.js +154 -0
- package/dist/process-task-icons.js.map +1 -0
- package/dist/projected-activity-state.d.ts +17 -0
- package/dist/projected-activity-state.d.ts.map +1 -0
- package/dist/projected-activity-state.js +22 -0
- package/dist/projected-activity-state.js.map +1 -0
- package/dist/projected-collection-action-runtime-diagnostics.d.ts +4 -0
- package/dist/projected-collection-action-runtime-diagnostics.d.ts.map +1 -0
- package/dist/projected-collection-action-runtime-diagnostics.js +9 -0
- package/dist/projected-collection-action-runtime-diagnostics.js.map +1 -0
- package/dist/projected-collection-view.d.ts +90 -0
- package/dist/projected-collection-view.d.ts.map +1 -0
- package/dist/projected-collection-view.js +532 -0
- package/dist/projected-collection-view.js.map +1 -0
- package/dist/projected-document-action-status-notices.d.ts +15 -0
- package/dist/projected-document-action-status-notices.d.ts.map +1 -0
- package/dist/projected-document-action-status-notices.js +33 -0
- package/dist/projected-document-action-status-notices.js.map +1 -0
- package/dist/projected-document-badges.d.ts +24 -0
- package/dist/projected-document-badges.d.ts.map +1 -0
- package/dist/projected-document-badges.js +53 -0
- package/dist/projected-document-badges.js.map +1 -0
- package/dist/projected-document-editor-surface.d.ts +46 -0
- package/dist/projected-document-editor-surface.d.ts.map +1 -0
- package/dist/projected-document-editor-surface.js +399 -0
- package/dist/projected-document-editor-surface.js.map +1 -0
- package/dist/projected-document-workspace-notices.d.ts +24 -0
- package/dist/projected-document-workspace-notices.d.ts.map +1 -0
- package/dist/projected-document-workspace-notices.js +14 -0
- package/dist/projected-document-workspace-notices.js.map +1 -0
- package/dist/projected-document-workspace-prompt-child-view-registry.d.ts +25 -0
- package/dist/projected-document-workspace-prompt-child-view-registry.d.ts.map +1 -0
- package/dist/projected-document-workspace-prompt-child-view-registry.js +41 -0
- package/dist/projected-document-workspace-prompt-child-view-registry.js.map +1 -0
- package/dist/projected-document-workspace-prompt-child-view-renderers.d.ts +32 -0
- package/dist/projected-document-workspace-prompt-child-view-renderers.d.ts.map +1 -0
- package/dist/projected-document-workspace-prompt-child-view-renderers.js +77 -0
- package/dist/projected-document-workspace-prompt-child-view-renderers.js.map +1 -0
- package/dist/projected-document-workspace-shell.d.ts +100 -0
- package/dist/projected-document-workspace-shell.d.ts.map +1 -0
- package/dist/projected-document-workspace-shell.js +153 -0
- package/dist/projected-document-workspace-shell.js.map +1 -0
- package/dist/projected-document-workspace.d.ts +39 -0
- package/dist/projected-document-workspace.d.ts.map +1 -0
- package/dist/projected-document-workspace.js +63 -0
- package/dist/projected-document-workspace.js.map +1 -0
- package/dist/projected-field-value-rendering.d.ts +94 -0
- package/dist/projected-field-value-rendering.d.ts.map +1 -0
- package/dist/projected-field-value-rendering.js +377 -0
- package/dist/projected-field-value-rendering.js.map +1 -0
- package/dist/projected-inline-list.d.ts +20 -0
- package/dist/projected-inline-list.d.ts.map +1 -0
- package/dist/projected-inline-list.js +149 -0
- package/dist/projected-inline-list.js.map +1 -0
- package/dist/projected-input-form.d.ts +143 -0
- package/dist/projected-input-form.d.ts.map +1 -0
- package/dist/projected-input-form.js +612 -0
- package/dist/projected-input-form.js.map +1 -0
- package/dist/projected-metric-dashboard.d.ts +26 -0
- package/dist/projected-metric-dashboard.d.ts.map +1 -0
- package/dist/projected-metric-dashboard.js +20 -0
- package/dist/projected-metric-dashboard.js.map +1 -0
- package/dist/projected-metric-strip.d.ts +20 -0
- package/dist/projected-metric-strip.d.ts.map +1 -0
- package/dist/projected-metric-strip.js +131 -0
- package/dist/projected-metric-strip.js.map +1 -0
- package/dist/projected-navigation-shell-view-host.d.ts +34 -0
- package/dist/projected-navigation-shell-view-host.d.ts.map +1 -0
- package/dist/projected-navigation-shell-view-host.js +75 -0
- package/dist/projected-navigation-shell-view-host.js.map +1 -0
- package/dist/projected-navigation-shell.d.ts +33 -0
- package/dist/projected-navigation-shell.d.ts.map +1 -0
- package/dist/projected-navigation-shell.js +112 -0
- package/dist/projected-navigation-shell.js.map +1 -0
- package/dist/projected-presentation-badges.d.ts +34 -0
- package/dist/projected-presentation-badges.d.ts.map +1 -0
- package/dist/projected-presentation-badges.js +22 -0
- package/dist/projected-presentation-badges.js.map +1 -0
- package/dist/projected-presentation-diagnostics.d.ts +10 -0
- package/dist/projected-presentation-diagnostics.d.ts.map +1 -0
- package/dist/projected-presentation-diagnostics.js +40 -0
- package/dist/projected-presentation-diagnostics.js.map +1 -0
- package/dist/projected-presentation-flow-layer.d.ts +33 -0
- package/dist/projected-presentation-flow-layer.d.ts.map +1 -0
- package/dist/projected-presentation-flow-layer.js +71 -0
- package/dist/projected-presentation-flow-layer.js.map +1 -0
- package/dist/projected-process-task-notices.d.ts +37 -0
- package/dist/projected-process-task-notices.d.ts.map +1 -0
- package/dist/projected-process-task-notices.js +225 -0
- package/dist/projected-process-task-notices.js.map +1 -0
- package/dist/projected-prompt-child-view-renderer.d.ts +101 -0
- package/dist/projected-prompt-child-view-renderer.d.ts.map +1 -0
- package/dist/projected-prompt-child-view-renderer.js +442 -0
- package/dist/projected-prompt-child-view-renderer.js.map +1 -0
- package/dist/projected-prompt-document-preview.d.ts +39 -0
- package/dist/projected-prompt-document-preview.d.ts.map +1 -0
- package/dist/projected-prompt-document-preview.js +50 -0
- package/dist/projected-prompt-document-preview.js.map +1 -0
- package/dist/projected-prompt-view.d.ts +35 -0
- package/dist/projected-prompt-view.d.ts.map +1 -0
- package/dist/projected-prompt-view.js +292 -0
- package/dist/projected-prompt-view.js.map +1 -0
- package/dist/projected-query-form.d.ts +56 -0
- package/dist/projected-query-form.d.ts.map +1 -0
- package/dist/projected-query-form.js +100 -0
- package/dist/projected-query-form.js.map +1 -0
- package/dist/projected-record-details.d.ts +20 -0
- package/dist/projected-record-details.d.ts.map +1 -0
- package/dist/projected-record-details.js +60 -0
- package/dist/projected-record-details.js.map +1 -0
- package/dist/projected-routed-surface-runtime.d.ts +86 -0
- package/dist/projected-routed-surface-runtime.d.ts.map +1 -0
- package/dist/projected-routed-surface-runtime.js +332 -0
- package/dist/projected-routed-surface-runtime.js.map +1 -0
- package/dist/projected-tabs-view.d.ts +21 -0
- package/dist/projected-tabs-view.d.ts.map +1 -0
- package/dist/projected-tabs-view.js +140 -0
- package/dist/projected-tabs-view.js.map +1 -0
- package/dist/projected-view-chrome.d.ts +15 -0
- package/dist/projected-view-chrome.d.ts.map +1 -0
- package/dist/projected-view-chrome.js +67 -0
- package/dist/projected-view-chrome.js.map +1 -0
- package/dist/projected-view-surface.d.ts +34 -0
- package/dist/projected-view-surface.d.ts.map +1 -0
- package/dist/projected-view-surface.js +40 -0
- package/dist/projected-view-surface.js.map +1 -0
- package/dist/standard-collection-chrome-slot-renderers.d.ts +26 -0
- package/dist/standard-collection-chrome-slot-renderers.d.ts.map +1 -0
- package/dist/standard-collection-chrome-slot-renderers.js +250 -0
- package/dist/standard-collection-chrome-slot-renderers.js.map +1 -0
- package/dist/standard-view-chrome-slot-renderers.d.ts +57 -0
- package/dist/standard-view-chrome-slot-renderers.d.ts.map +1 -0
- package/dist/standard-view-chrome-slot-renderers.js +614 -0
- package/dist/standard-view-chrome-slot-renderers.js.map +1 -0
- package/package.json +68 -0
- package/src/document-workspace-surface-slot-renderers.tsx +395 -0
- package/src/index.ts +53 -0
- package/src/navigation-shell-frame-renderer-registry.ts +29 -0
- package/src/navigation-shell-slot-renderer-registry.ts +46 -0
- package/src/page-host-unavailable-renderer.tsx +79 -0
- package/src/presentation-action-group.tsx +475 -0
- package/src/presentation-badge-target-interpreter.ts +54 -0
- package/src/presentation-component-groups.ts +2505 -0
- package/src/presentation-component-system-diagnostics.ts +848 -0
- package/src/presentation-component-system.ts +365 -0
- package/src/presentation-icon-diagnostics.ts +53 -0
- package/src/presentation-icon-registry.tsx +181 -0
- package/src/presentation-projection-trace-panel.tsx +140 -0
- package/src/presentation-routed-surface-host.tsx +48 -0
- package/src/presentation-shadcn-component-system.ts +102 -0
- package/src/presentation-standard-renderers.tsx +1290 -0
- package/src/presentation-surface-renderer.tsx +263 -0
- package/src/presentation-value-renderers.tsx +40 -0
- package/src/process-task-icons.tsx +258 -0
- package/src/projected-activity-state.tsx +63 -0
- package/src/projected-collection-action-runtime-diagnostics.ts +22 -0
- package/src/projected-collection-view.tsx +1273 -0
- package/src/projected-document-action-status-notices.tsx +66 -0
- package/src/projected-document-badges.tsx +134 -0
- package/src/projected-document-editor-surface.tsx +808 -0
- package/src/projected-document-workspace-notices.tsx +77 -0
- package/src/projected-document-workspace-prompt-child-view-registry.ts +99 -0
- package/src/projected-document-workspace-prompt-child-view-renderers.tsx +205 -0
- package/src/projected-document-workspace-shell.tsx +427 -0
- package/src/projected-document-workspace.tsx +216 -0
- package/src/projected-field-value-rendering.tsx +704 -0
- package/src/projected-inline-list.tsx +434 -0
- package/src/projected-input-form.tsx +1218 -0
- package/src/projected-metric-dashboard.tsx +106 -0
- package/src/projected-metric-strip.tsx +244 -0
- package/src/projected-navigation-shell-view-host.tsx +177 -0
- package/src/projected-navigation-shell.tsx +219 -0
- package/src/projected-presentation-badges.tsx +95 -0
- package/src/projected-presentation-diagnostics.tsx +120 -0
- package/src/projected-presentation-flow-layer.tsx +186 -0
- package/src/projected-process-task-notices.tsx +501 -0
- package/src/projected-prompt-child-view-renderer.tsx +698 -0
- package/src/projected-prompt-document-preview.tsx +197 -0
- package/src/projected-prompt-view.tsx +592 -0
- package/src/projected-query-form.tsx +286 -0
- package/src/projected-record-details.tsx +133 -0
- package/src/projected-routed-surface-runtime.tsx +713 -0
- package/src/projected-tabs-view.tsx +308 -0
- package/src/projected-view-chrome.tsx +148 -0
- package/src/projected-view-surface.tsx +131 -0
- package/src/standard-collection-chrome-slot-renderers.tsx +391 -0
- package/src/standard-view-chrome-slot-renderers.tsx +1064 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { Fragment, useEffect, useMemo, useState, type ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
findPresentationView,
|
|
5
|
+
getRegionViewIds,
|
|
6
|
+
isViewChromeSlotKind,
|
|
7
|
+
type ViewChromeSlotDefinition,
|
|
8
|
+
type ViewDefinition,
|
|
9
|
+
type ViewRegionDefinition,
|
|
10
|
+
} from '@cohesivesystems/presentation-core'
|
|
11
|
+
import type {
|
|
12
|
+
PresentationShadcnComponentSystem as PresentationComponentSystem,
|
|
13
|
+
} from './presentation-shadcn-component-system'
|
|
14
|
+
import {
|
|
15
|
+
renderPresentationIcon,
|
|
16
|
+
} from './presentation-icon-registry'
|
|
17
|
+
import {
|
|
18
|
+
projectPresentationIconDiagnostics,
|
|
19
|
+
} from './presentation-icon-diagnostics'
|
|
20
|
+
import {
|
|
21
|
+
usePresentationModule,
|
|
22
|
+
useRegisterPresentationProjectionDiagnostics,
|
|
23
|
+
} from '@cohesivesystems/presentation-react'
|
|
24
|
+
import { ProjectedStatusBlock } from './projected-activity-state'
|
|
25
|
+
import {
|
|
26
|
+
ProjectedViewChrome,
|
|
27
|
+
} from './projected-view-chrome'
|
|
28
|
+
import type {
|
|
29
|
+
ProjectedViewSurfaceChromeSlotRenderer,
|
|
30
|
+
} from './projected-view-surface'
|
|
31
|
+
import {
|
|
32
|
+
viewChromeSlotKinds,
|
|
33
|
+
viewChromeSlotPlacements,
|
|
34
|
+
viewRegionKinds,
|
|
35
|
+
} from '@cohesivesystems/presentation-contracts'
|
|
36
|
+
|
|
37
|
+
export interface ProjectedTabsViewProps {
|
|
38
|
+
readonly chromeAfterContentClassName?: string
|
|
39
|
+
readonly chromeBeforeContentClassName?: string
|
|
40
|
+
readonly chromeFooterClassName?: string
|
|
41
|
+
readonly chromeHeaderClassName?: string
|
|
42
|
+
readonly className?: string
|
|
43
|
+
readonly componentSystem: PresentationComponentSystem
|
|
44
|
+
readonly defaultRegionId?: string
|
|
45
|
+
readonly fallbackRegions?: readonly ViewRegionDefinition[]
|
|
46
|
+
readonly iconByRegionId?: Readonly<Record<string, ReactNode>>
|
|
47
|
+
readonly renderChromeSlot?: ProjectedViewSurfaceChromeSlotRenderer
|
|
48
|
+
readonly renderView: (viewId: string) => ReactNode
|
|
49
|
+
readonly view?: ViewDefinition | null
|
|
50
|
+
readonly viewId: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function ProjectedTabsView({
|
|
54
|
+
chromeAfterContentClassName,
|
|
55
|
+
chromeBeforeContentClassName,
|
|
56
|
+
chromeFooterClassName,
|
|
57
|
+
chromeHeaderClassName,
|
|
58
|
+
className,
|
|
59
|
+
componentSystem,
|
|
60
|
+
defaultRegionId,
|
|
61
|
+
fallbackRegions,
|
|
62
|
+
iconByRegionId,
|
|
63
|
+
renderChromeSlot,
|
|
64
|
+
renderView,
|
|
65
|
+
view: viewOverride,
|
|
66
|
+
viewId,
|
|
67
|
+
}: ProjectedTabsViewProps) {
|
|
68
|
+
const module = usePresentationModule()
|
|
69
|
+
const view = viewOverride ?? findPresentationView<ViewDefinition>(module, viewId)
|
|
70
|
+
const tabRegions = useMemo(
|
|
71
|
+
() => getTabRegions(view, fallbackRegions),
|
|
72
|
+
[fallbackRegions, view],
|
|
73
|
+
)
|
|
74
|
+
const iconDiagnosticSource = `projected-tabs-view-icons:${view?.Id ?? viewId}`
|
|
75
|
+
const iconDiagnostics = useMemo(
|
|
76
|
+
() => projectPresentationIconDiagnostics({
|
|
77
|
+
icons: resolveTabRegionIconSubjects(tabRegions),
|
|
78
|
+
module,
|
|
79
|
+
source: iconDiagnosticSource,
|
|
80
|
+
surfaceId: view?.Id ?? viewId,
|
|
81
|
+
surfaceName: view?.Name,
|
|
82
|
+
}),
|
|
83
|
+
[
|
|
84
|
+
iconDiagnosticSource,
|
|
85
|
+
module,
|
|
86
|
+
tabRegions,
|
|
87
|
+
view?.Id,
|
|
88
|
+
view?.Name,
|
|
89
|
+
viewId,
|
|
90
|
+
],
|
|
91
|
+
)
|
|
92
|
+
useRegisterPresentationProjectionDiagnostics(iconDiagnosticSource, iconDiagnostics)
|
|
93
|
+
const defaultValue =
|
|
94
|
+
defaultRegionId ??
|
|
95
|
+
view?.State?.find((state) => state.Type === 'region-id')?.DefaultValue ??
|
|
96
|
+
tabRegions[0]?.Id
|
|
97
|
+
const [requestedActiveRegionId, setActiveRegionId] = useState(defaultValue ?? '')
|
|
98
|
+
const activeRegionId = tabRegions.some((region) => region.Id === requestedActiveRegionId)
|
|
99
|
+
? requestedActiveRegionId
|
|
100
|
+
: defaultValue ?? ''
|
|
101
|
+
const [visitedRegionIds, setVisitedRegionIds] = useState<ReadonlySet<string>>(
|
|
102
|
+
() => new Set(activeRegionId ? [activeRegionId] : []),
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
if (!activeRegionId) {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
setVisitedRegionIds((current) => {
|
|
111
|
+
if (current.has(activeRegionId)) {
|
|
112
|
+
return current
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return new Set([...current, activeRegionId])
|
|
116
|
+
})
|
|
117
|
+
}, [activeRegionId])
|
|
118
|
+
|
|
119
|
+
if (!module && tabRegions.length === 0) {
|
|
120
|
+
return <ProjectedStatusBlock label="Presentation module is not available." />
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!view && tabRegions.length === 0) {
|
|
124
|
+
return <ProjectedStatusBlock label={`Presentation view '${viewId}' is not available.`} />
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!defaultValue || tabRegions.length === 0) {
|
|
128
|
+
return <ProjectedStatusBlock label={`Presentation view '${view?.Name ?? view?.Id ?? viewId}' has no tabs.`} />
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const renderTabsChromeSlot = (slot: ViewChromeSlotDefinition, chromeView: ViewDefinition | null) => {
|
|
132
|
+
if (isViewChromeSlotKind(slot, viewChromeSlotKinds.viewSwitch)) {
|
|
133
|
+
return renderTabsList({
|
|
134
|
+
activeRegionId: activeRegionId || defaultValue,
|
|
135
|
+
componentSystem,
|
|
136
|
+
iconByRegionId,
|
|
137
|
+
module,
|
|
138
|
+
tabRegions,
|
|
139
|
+
viewId: view?.Id ?? viewId,
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return renderChromeSlot?.(slot, chromeView) ?? null
|
|
144
|
+
}
|
|
145
|
+
const hasTabSwitchChrome = hasTabSwitchChromeSlot(view)
|
|
146
|
+
|
|
147
|
+
return componentSystem.tabs.TabsLayout({
|
|
148
|
+
className,
|
|
149
|
+
onValueChange: setActiveRegionId,
|
|
150
|
+
value: activeRegionId || defaultValue,
|
|
151
|
+
viewId: view?.Id ?? viewId,
|
|
152
|
+
children: (
|
|
153
|
+
<>
|
|
154
|
+
<ProjectedViewChrome
|
|
155
|
+
className={chromeHeaderClassName}
|
|
156
|
+
componentSystem={componentSystem}
|
|
157
|
+
placement={viewChromeSlotPlacements.header}
|
|
158
|
+
renderSlot={(slot) => renderTabsChromeSlot(slot, view)}
|
|
159
|
+
view={view}
|
|
160
|
+
/>
|
|
161
|
+
|
|
162
|
+
{hasTabSwitchChrome ? null : renderTabsList({
|
|
163
|
+
activeRegionId: activeRegionId || defaultValue,
|
|
164
|
+
componentSystem,
|
|
165
|
+
iconByRegionId,
|
|
166
|
+
module,
|
|
167
|
+
tabRegions,
|
|
168
|
+
viewId: view?.Id ?? viewId,
|
|
169
|
+
})}
|
|
170
|
+
|
|
171
|
+
<ProjectedViewChrome
|
|
172
|
+
className={chromeBeforeContentClassName}
|
|
173
|
+
componentSystem={componentSystem}
|
|
174
|
+
placement={viewChromeSlotPlacements.beforeContent}
|
|
175
|
+
renderSlot={(slot) => renderTabsChromeSlot(slot, view)}
|
|
176
|
+
view={view}
|
|
177
|
+
/>
|
|
178
|
+
|
|
179
|
+
{tabRegions.map((region) => {
|
|
180
|
+
const viewIds = getRegionViewIds(region)
|
|
181
|
+
const shouldRenderRegion =
|
|
182
|
+
region.Id === activeRegionId || visitedRegionIds.has(region.Id)
|
|
183
|
+
return (
|
|
184
|
+
<Fragment key={region.Id}>
|
|
185
|
+
{componentSystem.tabs.TabsPanel({
|
|
186
|
+
region,
|
|
187
|
+
value: region.Id,
|
|
188
|
+
viewId: view?.Id ?? viewId,
|
|
189
|
+
children: (
|
|
190
|
+
<>
|
|
191
|
+
{shouldRenderRegion
|
|
192
|
+
? viewIds.map((childViewId) => (
|
|
193
|
+
<div
|
|
194
|
+
className="flex min-h-0 flex-1 flex-col overflow-hidden"
|
|
195
|
+
key={childViewId}
|
|
196
|
+
>
|
|
197
|
+
{renderView(childViewId)}
|
|
198
|
+
</div>
|
|
199
|
+
))
|
|
200
|
+
: null}
|
|
201
|
+
</>
|
|
202
|
+
),
|
|
203
|
+
})}
|
|
204
|
+
</Fragment>
|
|
205
|
+
)
|
|
206
|
+
})}
|
|
207
|
+
|
|
208
|
+
<ProjectedViewChrome
|
|
209
|
+
className={chromeAfterContentClassName}
|
|
210
|
+
componentSystem={componentSystem}
|
|
211
|
+
placement={viewChromeSlotPlacements.afterContent}
|
|
212
|
+
renderSlot={(slot) => renderTabsChromeSlot(slot, view)}
|
|
213
|
+
view={view}
|
|
214
|
+
/>
|
|
215
|
+
|
|
216
|
+
<ProjectedViewChrome
|
|
217
|
+
className={chromeFooterClassName}
|
|
218
|
+
componentSystem={componentSystem}
|
|
219
|
+
placement={viewChromeSlotPlacements.footer}
|
|
220
|
+
renderSlot={(slot) => renderTabsChromeSlot(slot, view)}
|
|
221
|
+
view={view}
|
|
222
|
+
/>
|
|
223
|
+
</>
|
|
224
|
+
),
|
|
225
|
+
})
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function renderTabsList({
|
|
229
|
+
activeRegionId,
|
|
230
|
+
componentSystem,
|
|
231
|
+
iconByRegionId,
|
|
232
|
+
module,
|
|
233
|
+
tabRegions,
|
|
234
|
+
viewId,
|
|
235
|
+
}: {
|
|
236
|
+
readonly activeRegionId: string
|
|
237
|
+
readonly componentSystem: PresentationComponentSystem
|
|
238
|
+
readonly iconByRegionId: Readonly<Record<string, ReactNode>> | undefined
|
|
239
|
+
readonly module: ReturnType<typeof usePresentationModule>
|
|
240
|
+
readonly tabRegions: readonly ViewRegionDefinition[]
|
|
241
|
+
readonly viewId: string | null
|
|
242
|
+
}) {
|
|
243
|
+
return componentSystem.tabs.TabsList({
|
|
244
|
+
viewId,
|
|
245
|
+
children: tabRegions.map((region) => (
|
|
246
|
+
<Fragment key={region.Id}>
|
|
247
|
+
{componentSystem.tabs.TabsTrigger({
|
|
248
|
+
isActive: activeRegionId === region.Id,
|
|
249
|
+
region,
|
|
250
|
+
value: region.Id,
|
|
251
|
+
viewId,
|
|
252
|
+
children: (
|
|
253
|
+
<>
|
|
254
|
+
{iconByRegionId?.[region.Id] ?? renderPresentationIcon({
|
|
255
|
+
className: 'size-3.5',
|
|
256
|
+
icon: region.Icon,
|
|
257
|
+
module,
|
|
258
|
+
})}
|
|
259
|
+
{region.Name ?? region.Id}
|
|
260
|
+
</>
|
|
261
|
+
),
|
|
262
|
+
})}
|
|
263
|
+
</Fragment>
|
|
264
|
+
)),
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function resolveTabRegionIconSubjects(
|
|
269
|
+
tabRegions: readonly ViewRegionDefinition[],
|
|
270
|
+
) {
|
|
271
|
+
return tabRegions.flatMap((region) => {
|
|
272
|
+
if (!region.Icon) {
|
|
273
|
+
return []
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return [{
|
|
277
|
+
details: {
|
|
278
|
+
regionId: region.Id,
|
|
279
|
+
},
|
|
280
|
+
icon: region.Icon,
|
|
281
|
+
id: region.Id,
|
|
282
|
+
kind: 'tab-region-icon',
|
|
283
|
+
label: region.Name,
|
|
284
|
+
}]
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function getTabRegions(
|
|
289
|
+
view: ViewDefinition | null,
|
|
290
|
+
fallbackRegions: readonly ViewRegionDefinition[] | undefined,
|
|
291
|
+
) {
|
|
292
|
+
const regions = view?.Regions ?? fallbackRegions ?? []
|
|
293
|
+
return (
|
|
294
|
+
regions.filter(
|
|
295
|
+
(region): region is ViewRegionDefinition =>
|
|
296
|
+
hasRegionKind(region.Kind, 'Tab', 6) && getRegionViewIds(region).length > 0,
|
|
297
|
+
)
|
|
298
|
+
)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function hasRegionKind(value: string | number, name: string, numericValue: number) {
|
|
302
|
+
return value === name || value === numericValue || value === viewRegionKinds.tab
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function hasTabSwitchChromeSlot(view: ViewDefinition | null) {
|
|
306
|
+
return view?.Chrome?.Slots.some((slot) =>
|
|
307
|
+
isViewChromeSlotKind(slot, viewChromeSlotKinds.viewSwitch)) ?? false
|
|
308
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { useMemo, type ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
ViewChromeSlotDefinition,
|
|
5
|
+
ViewChromeSlotPlacement,
|
|
6
|
+
ViewDefinition,
|
|
7
|
+
} from '@cohesivesystems/presentation-core'
|
|
8
|
+
import type {
|
|
9
|
+
PresentationShadcnComponentSystem as PresentationComponentSystem,
|
|
10
|
+
} from './presentation-shadcn-component-system'
|
|
11
|
+
import {
|
|
12
|
+
isViewChromeSlotKind,
|
|
13
|
+
isViewChromeSlotPlacementValue,
|
|
14
|
+
resolveViewChromeIconSubjects,
|
|
15
|
+
} from '@cohesivesystems/presentation-core'
|
|
16
|
+
import {
|
|
17
|
+
projectPresentationIconDiagnostics,
|
|
18
|
+
} from './presentation-icon-diagnostics'
|
|
19
|
+
import {
|
|
20
|
+
usePresentationModule,
|
|
21
|
+
useRegisterPresentationProjectionDiagnostics,
|
|
22
|
+
} from '@cohesivesystems/presentation-react'
|
|
23
|
+
import {
|
|
24
|
+
viewChromeSlotKinds,
|
|
25
|
+
viewChromeSlotPlacements,
|
|
26
|
+
} from '@cohesivesystems/presentation-contracts'
|
|
27
|
+
|
|
28
|
+
export interface ProjectedViewChromeProps {
|
|
29
|
+
readonly className?: string
|
|
30
|
+
readonly componentSystem: PresentationComponentSystem
|
|
31
|
+
readonly placement: ViewChromeSlotPlacement | string | number
|
|
32
|
+
readonly renderContainer?: (children: ReactNode) => ReactNode
|
|
33
|
+
readonly renderSlot: (slot: ViewChromeSlotDefinition) => ReactNode
|
|
34
|
+
readonly view: ViewDefinition | null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function ProjectedViewChrome({
|
|
38
|
+
className,
|
|
39
|
+
componentSystem,
|
|
40
|
+
placement,
|
|
41
|
+
renderContainer,
|
|
42
|
+
renderSlot,
|
|
43
|
+
view,
|
|
44
|
+
}: ProjectedViewChromeProps) {
|
|
45
|
+
const module = usePresentationModule()
|
|
46
|
+
const slots = useMemo(
|
|
47
|
+
() => resolveViewChromeSlots(view, placement),
|
|
48
|
+
[placement, view],
|
|
49
|
+
)
|
|
50
|
+
const iconDiagnostics = useMemo(
|
|
51
|
+
() => projectPresentationIconDiagnostics({
|
|
52
|
+
icons: resolveViewChromeIconSubjects(slots),
|
|
53
|
+
module,
|
|
54
|
+
source: `projected-view-chrome-icons:${view?.Id ?? 'unknown'}:${String(placement)}`,
|
|
55
|
+
surfaceId: view?.Id,
|
|
56
|
+
surfaceName: view?.Name,
|
|
57
|
+
}),
|
|
58
|
+
[
|
|
59
|
+
module,
|
|
60
|
+
placement,
|
|
61
|
+
slots,
|
|
62
|
+
view?.Id,
|
|
63
|
+
view?.Name,
|
|
64
|
+
],
|
|
65
|
+
)
|
|
66
|
+
useRegisterPresentationProjectionDiagnostics(
|
|
67
|
+
`projected-view-chrome-icons:${view?.Id ?? 'unknown'}:${String(placement)}`,
|
|
68
|
+
iconDiagnostics,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
const ViewChromeSlot = componentSystem.viewChrome.ViewChromeSlot
|
|
72
|
+
const renderedSlots = slots
|
|
73
|
+
.map((slot) => {
|
|
74
|
+
const rendered = renderSlot(slot)
|
|
75
|
+
return isRenderableNode(rendered) ? (
|
|
76
|
+
<ViewChromeSlot
|
|
77
|
+
key={slot.Id}
|
|
78
|
+
placement={placement}
|
|
79
|
+
slot={slot}
|
|
80
|
+
viewId={view?.Id ?? null}
|
|
81
|
+
>
|
|
82
|
+
{rendered}
|
|
83
|
+
</ViewChromeSlot>
|
|
84
|
+
) : null
|
|
85
|
+
})
|
|
86
|
+
.filter(isRenderableNode)
|
|
87
|
+
|
|
88
|
+
if (renderedSlots.length === 0) {
|
|
89
|
+
return null
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (renderContainer) {
|
|
93
|
+
return renderContainer(renderedSlots)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return className ? (
|
|
97
|
+
<div className={cn(className)}>{renderedSlots}</div>
|
|
98
|
+
) : (
|
|
99
|
+
<>{renderedSlots}</>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function resolveViewChromeSlots(
|
|
104
|
+
view: ViewDefinition | null,
|
|
105
|
+
placement: ViewChromeSlotPlacement | string | number,
|
|
106
|
+
) {
|
|
107
|
+
return (view?.Chrome?.Slots ?? []).filter((slot) =>
|
|
108
|
+
isViewChromeSlotPlacementValue(
|
|
109
|
+
resolveViewChromeSlotPlacement(slot),
|
|
110
|
+
placement,
|
|
111
|
+
))
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function resolveViewChromeSlotPlacement(
|
|
115
|
+
slot: ViewChromeSlotDefinition,
|
|
116
|
+
): ViewChromeSlotPlacement {
|
|
117
|
+
if (slot.Placement !== undefined && slot.Placement !== null) {
|
|
118
|
+
return slot.Placement
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (
|
|
122
|
+
isViewChromeSlotKind(slot, viewChromeSlotKinds.actions) ||
|
|
123
|
+
isViewChromeSlotKind(slot, viewChromeSlotKinds.viewSwitch) ||
|
|
124
|
+
isViewChromeSlotKind(slot, viewChromeSlotKinds.layoutSwitch) ||
|
|
125
|
+
isViewChromeSlotKind(slot, viewChromeSlotKinds.headingTrailing) ||
|
|
126
|
+
isViewChromeSlotKind(slot, viewChromeSlotKinds.status)
|
|
127
|
+
) {
|
|
128
|
+
return viewChromeSlotPlacements.header
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (isViewChromeSlotKind(slot, viewChromeSlotKinds.badgeStrip)) {
|
|
132
|
+
return viewChromeSlotPlacements.beforeContent
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (isViewChromeSlotKind(slot, viewChromeSlotKinds.metricStrip)) {
|
|
136
|
+
return viewChromeSlotPlacements.afterContent
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return viewChromeSlotPlacements.none
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function isRenderableNode(node: ReactNode): node is Exclude<ReactNode, null | undefined | false> {
|
|
143
|
+
return node !== null && node !== undefined && node !== false
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function cn(...values: readonly (false | null | string | undefined)[]) {
|
|
147
|
+
return values.filter(Boolean).join(' ')
|
|
148
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
findPresentationView,
|
|
5
|
+
type ViewChromeSlotDefinition,
|
|
6
|
+
type ViewChromeSlotPlacement,
|
|
7
|
+
type ViewDefinition,
|
|
8
|
+
} from '@cohesivesystems/presentation-core'
|
|
9
|
+
import type {
|
|
10
|
+
PresentationShadcnComponentSystem as PresentationComponentSystem,
|
|
11
|
+
} from './presentation-shadcn-component-system'
|
|
12
|
+
import type {
|
|
13
|
+
PresentationViewSurfaceContentTopInset,
|
|
14
|
+
PresentationViewSurfaceVerticalResizeOptions,
|
|
15
|
+
} from './presentation-component-groups'
|
|
16
|
+
import { usePresentationModule } from '@cohesivesystems/presentation-react'
|
|
17
|
+
import {
|
|
18
|
+
ProjectedViewChrome,
|
|
19
|
+
resolveViewChromeSlots,
|
|
20
|
+
} from './projected-view-chrome'
|
|
21
|
+
import { viewChromeSlotPlacements } from '@cohesivesystems/presentation-contracts'
|
|
22
|
+
|
|
23
|
+
interface ProjectedViewSurfaceProps {
|
|
24
|
+
readonly action?: ReactNode
|
|
25
|
+
readonly children?: ReactNode
|
|
26
|
+
readonly className?: string
|
|
27
|
+
readonly chromeAfterContentClassName?: string
|
|
28
|
+
readonly chromeBeforeContentClassName?: string
|
|
29
|
+
readonly chromeFooterClassName?: string
|
|
30
|
+
readonly chromeHeaderClassName?: string
|
|
31
|
+
readonly collapsible?: boolean
|
|
32
|
+
readonly collapsed?: boolean
|
|
33
|
+
readonly collapseLabel?: string
|
|
34
|
+
readonly componentSystem: PresentationComponentSystem
|
|
35
|
+
readonly contentClassName?: string
|
|
36
|
+
readonly contentTopInset?: PresentationViewSurfaceContentTopInset | null
|
|
37
|
+
readonly defaultCollapsed?: boolean
|
|
38
|
+
readonly description?: string
|
|
39
|
+
readonly eyebrow?: string
|
|
40
|
+
readonly onCollapsedChange?: (collapsed: boolean) => void
|
|
41
|
+
readonly renderChromeSlot?: ProjectedViewSurfaceChromeSlotRenderer
|
|
42
|
+
readonly title?: string
|
|
43
|
+
readonly verticalResize?: boolean | PresentationViewSurfaceVerticalResizeOptions | null
|
|
44
|
+
readonly view?: ViewDefinition | null
|
|
45
|
+
readonly viewId?: string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type ProjectedViewSurfaceChromeSlotRenderer = (
|
|
49
|
+
slot: ViewChromeSlotDefinition,
|
|
50
|
+
view: ViewDefinition | null,
|
|
51
|
+
) => ReactNode
|
|
52
|
+
|
|
53
|
+
export type ProjectedViewSurfaceContentTopInset =
|
|
54
|
+
PresentationViewSurfaceContentTopInset
|
|
55
|
+
|
|
56
|
+
export type ProjectedViewSurfaceVerticalResizeOptions =
|
|
57
|
+
PresentationViewSurfaceVerticalResizeOptions
|
|
58
|
+
|
|
59
|
+
export function ProjectedViewSurface({
|
|
60
|
+
action,
|
|
61
|
+
children,
|
|
62
|
+
chromeAfterContentClassName,
|
|
63
|
+
chromeBeforeContentClassName,
|
|
64
|
+
chromeFooterClassName,
|
|
65
|
+
chromeHeaderClassName,
|
|
66
|
+
collapsible,
|
|
67
|
+
componentSystem,
|
|
68
|
+
renderChromeSlot,
|
|
69
|
+
title,
|
|
70
|
+
view: viewOverride,
|
|
71
|
+
viewId,
|
|
72
|
+
...props
|
|
73
|
+
}: ProjectedViewSurfaceProps) {
|
|
74
|
+
const module = usePresentationModule()
|
|
75
|
+
const view = viewOverride ?? (viewId
|
|
76
|
+
? findPresentationView<ViewDefinition>(module, viewId)
|
|
77
|
+
: null)
|
|
78
|
+
const renderChromePlacement = (
|
|
79
|
+
placement: ViewChromeSlotPlacement,
|
|
80
|
+
className?: string,
|
|
81
|
+
) => renderChromeSlot && resolveViewChromeSlots(view, placement).length > 0 ? (
|
|
82
|
+
<ProjectedViewChrome
|
|
83
|
+
componentSystem={componentSystem}
|
|
84
|
+
placement={placement}
|
|
85
|
+
renderContainer={(children) =>
|
|
86
|
+
componentSystem.surfaces.ViewSurfaceChromePlacement({
|
|
87
|
+
children,
|
|
88
|
+
className,
|
|
89
|
+
placement,
|
|
90
|
+
viewId: view?.Id ?? null,
|
|
91
|
+
})}
|
|
92
|
+
renderSlot={(slot) => renderChromeSlot(slot, view)}
|
|
93
|
+
view={view}
|
|
94
|
+
/>
|
|
95
|
+
) : null
|
|
96
|
+
const headerChrome = renderChromePlacement(
|
|
97
|
+
viewChromeSlotPlacements.header,
|
|
98
|
+
chromeHeaderClassName,
|
|
99
|
+
)
|
|
100
|
+
const beforeContentChrome = renderChromePlacement(
|
|
101
|
+
viewChromeSlotPlacements.beforeContent,
|
|
102
|
+
chromeBeforeContentClassName,
|
|
103
|
+
)
|
|
104
|
+
const afterContentChrome = renderChromePlacement(
|
|
105
|
+
viewChromeSlotPlacements.afterContent,
|
|
106
|
+
chromeAfterContentClassName,
|
|
107
|
+
)
|
|
108
|
+
const footerChrome = renderChromePlacement(
|
|
109
|
+
viewChromeSlotPlacements.footer,
|
|
110
|
+
chromeFooterClassName,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return componentSystem.surfaces.ViewSurface({
|
|
114
|
+
...props,
|
|
115
|
+
action: componentSystem.surfaces.ViewSurfaceHeaderActions({
|
|
116
|
+
action,
|
|
117
|
+
chrome: headerChrome,
|
|
118
|
+
viewId: view?.Id ?? null,
|
|
119
|
+
}),
|
|
120
|
+
children: componentSystem.surfaces.ViewSurfaceContent({
|
|
121
|
+
afterContentChrome,
|
|
122
|
+
beforeContentChrome,
|
|
123
|
+
children,
|
|
124
|
+
footerChrome,
|
|
125
|
+
viewId: view?.Id ?? null,
|
|
126
|
+
}),
|
|
127
|
+
collapsible: collapsible ?? view?.Chrome?.Collapsible,
|
|
128
|
+
title: title ?? view?.Name,
|
|
129
|
+
viewId: view?.Id ?? null,
|
|
130
|
+
})
|
|
131
|
+
}
|