@rozenite/vite-plugin 1.13.0 → 2.0.0

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 (56) hide show
  1. package/README.md +12 -0
  2. package/dist/bundle-dts.d.ts.map +1 -1
  3. package/dist/client-plugin.d.ts.map +1 -1
  4. package/dist/dev-config-module.d.ts.map +1 -1
  5. package/dist/dev-host/assets/index-DU3zXL2c.css +1 -0
  6. package/dist/dev-host/assets/index-Xsb6uYhI.js +13 -0
  7. package/dist/dev-host/index.html +3 -3
  8. package/dist/dev-host/manifest.json +2 -2
  9. package/dist/index.cjs +24 -8
  10. package/dist/index.d.ts +9 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +24 -8
  13. package/dist/react-native-plugin.d.ts.map +1 -1
  14. package/dist/sdk-plugin.d.ts.map +1 -1
  15. package/dist/server-plugin.d.ts.map +1 -1
  16. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  17. package/package.json +9 -10
  18. package/src/bundle-dts.ts +7 -6
  19. package/src/client-plugin.ts +8 -6
  20. package/src/dev-config-module.ts +4 -1
  21. package/src/dev-host/App.tsx +219 -413
  22. package/src/dev-host/components/DispatchForm.tsx +108 -122
  23. package/src/dev-host/components/FlowList.tsx +81 -101
  24. package/src/dev-host/components/MessageDetailsPane.tsx +56 -83
  25. package/src/dev-host/components/MessageLogPane.tsx +84 -66
  26. package/src/dev-host/components/PanelTabs.tsx +29 -10
  27. package/src/dev-host/config.ts +6 -2
  28. package/src/dev-host/constants.ts +0 -19
  29. package/src/dev-host/flow-runtime.ts +33 -12
  30. package/src/dev-host/index.html +1 -1
  31. package/src/dev-host/main.tsx +1 -10
  32. package/src/dev-host/server.ts +9 -3
  33. package/src/dev-host/styles.css +162 -830
  34. package/src/dev-host/types.ts +5 -10
  35. package/src/dev-host/utils.ts +9 -6
  36. package/src/dev-host/vite.config.mts +2 -0
  37. package/src/index.ts +15 -5
  38. package/src/load-config.ts +4 -4
  39. package/src/package-json.ts +1 -1
  40. package/src/react-native-plugin.ts +3 -0
  41. package/src/sdk-plugin.ts +3 -0
  42. package/src/server-plugin.ts +3 -0
  43. package/src/utils.ts +1 -1
  44. package/dist/dev-host/assets/index-CkxvBMpp.css +0 -1
  45. package/dist/dev-host/assets/index-cNKHRwej.js +0 -11
  46. package/src/dev-host/components/MessagePayloadDetail.tsx +0 -32
  47. package/src/dev-host/components/ResizeHandle.tsx +0 -33
  48. package/src/dev-host/components/icons.tsx +0 -79
  49. package/src/dev-host/components/ui/Button.tsx +0 -91
  50. package/src/dev-host/components/ui/DropdownMenu.tsx +0 -84
  51. package/src/dev-host/components/ui/IconButton.tsx +0 -41
  52. package/src/dev-host/components/ui/Input.tsx +0 -73
  53. package/src/dev-host/components/ui/ScrollArea.tsx +0 -20
  54. package/src/dev-host/components/ui/Tabs.tsx +0 -166
  55. package/src/dev-host/components/ui/Textarea.tsx +0 -79
  56. package/src/dev-host/components/ui/ToggleGroup.tsx +0 -120
@@ -1,13 +1,12 @@
1
+ import { Button, Input, Select, Tabs, Textarea } from '@rozenite/ui';
2
+ import { RotateCcw, Send } from 'lucide-react';
1
3
  import { useState, type FormEvent } from 'react';
2
- import type { DevHostFlowEntry, DevHostFlowRunState, DevHostPresetEntry } from '../types.js';
3
- import { ClearIcon, PresetsIcon, SendIcon } from './icons.js';
4
+ import type {
5
+ DevHostFlowEntry,
6
+ DevHostFlowRunState,
7
+ DevHostPresetEntry,
8
+ } from '../types.js';
4
9
  import { FlowList } from './FlowList.js';
5
- import { DropdownMenu, type DropdownMenuItem } from './ui/DropdownMenu.js';
6
- import { IconButton } from './ui/IconButton.js';
7
- import { Input } from './ui/Input.js';
8
- import { ScrollArea } from './ui/ScrollArea.js';
9
- import { Textarea } from './ui/Textarea.js';
10
- import { ToggleGroup } from './ui/ToggleGroup.js';
11
10
 
12
11
  type DispatchFormProps = {
13
12
  commandType: string;
@@ -43,127 +42,114 @@ export const DispatchForm = ({
43
42
  onSubmit,
44
43
  }: DispatchFormProps) => {
45
44
  const [activeTab, setActiveTab] = useState<'dispatch' | 'flows'>('dispatch');
46
- const presetItems: DropdownMenuItem<DevHostPresetEntry>[] = presets.map((preset) => ({
47
- id: preset.displayName,
48
- label: preset.displayName,
49
- item: preset,
50
- }));
51
- const presetButton = (
52
- <IconButton
53
- type="button"
54
- variant="default"
55
- aria-label={presets.length > 0 ? 'Open presets' : 'No presets available'}
56
- title={presets.length > 0 ? 'Presets' : 'No presets available'}
57
- disabled={presets.length === 0}
58
- overrides={{
59
- BaseButton: {
60
- style: {
61
- borderRadius: '6px',
62
- backgroundColor: 'rgba(255, 255, 255, 0.04)',
63
- color: 'rgba(255, 255, 255, 0.88)',
64
- },
65
- },
66
- }}
67
- >
68
- <PresetsIcon />
69
- </IconButton>
70
- );
71
45
 
72
46
  return (
73
- <div className="rz-pane">
74
- <div className="rz-sidebar">
75
- <div className="rz-sidebar-header">
76
- <div className="rz-sidebar-title">Actions</div>
77
- </div>
47
+ <section className="dev-host-pane">
48
+ <header className="dev-host-pane-header">
49
+ <h2 className="dev-host-pane-title">Actions</h2>
50
+ </header>
78
51
 
79
- <ScrollArea className="rz-sidebar-scroll">
80
- <div className="rz-action-tabs rz-command-form">
81
- <div className="rz-action-tabs-header">
82
- <ToggleGroup
83
- aria-label="Action modes"
84
- value={activeTab}
85
- onChange={(value) => setActiveTab(value as 'dispatch' | 'flows')}
86
- options={[
87
- { key: 'dispatch', label: 'Dispatch' },
88
- { key: 'flows', label: 'Flows' },
89
- ]}
90
- />
91
-
92
- {activeTab === 'dispatch'
93
- ? presets.length > 0
94
- ? <DropdownMenu items={presetItems} onSelect={onApplyPreset}>{presetButton}</DropdownMenu>
95
- : presetButton
96
- : null}
97
- </div>
52
+ <Tabs
53
+ className="flex min-h-0 flex-1 flex-col"
54
+ value={activeTab}
55
+ onValueChange={(value) => setActiveTab(value as 'dispatch' | 'flows')}
56
+ >
57
+ <div className="dev-host-tabs-header">
58
+ <Tabs.List aria-label="Action modes">
59
+ <Tabs.Tab value="dispatch">Dispatch</Tabs.Tab>
60
+ <Tabs.Tab value="flows">Flows</Tabs.Tab>
61
+ </Tabs.List>
98
62
 
99
- {activeTab === 'dispatch' ? (
100
- <div className="rz-action-tab-panel">
101
- <form className="rz-action-form" onSubmit={onSubmit}>
102
- <div className="rz-field">
103
- <label className="rz-label" htmlFor="command-type">
104
- Command
105
- </label>
106
- <Input
107
- id="command-type"
108
- value={commandType}
109
- onChange={(event) => onCommandTypeChange(event.currentTarget.value)}
110
- placeholder="get-snapshot"
111
- spellCheck={false}
112
- />
113
- </div>
63
+ {activeTab === 'dispatch' ? (
64
+ <Select
65
+ value={null}
66
+ onValueChange={(value) => {
67
+ const preset = presets.find((item) => item.name === value);
68
+ if (preset) {
69
+ onApplyPreset(preset);
70
+ }
71
+ }}
72
+ >
73
+ <Select.Trigger
74
+ className="w-auto"
75
+ aria-label={
76
+ presets.length > 0 ? 'Open presets' : 'No presets available'
77
+ }
78
+ disabled={presets.length === 0}
79
+ title={presets.length > 0 ? 'Presets' : 'No presets available'}
80
+ >
81
+ <Select.Value>Presets</Select.Value>
82
+ </Select.Trigger>
83
+ <Select.Content align="end">
84
+ {presets.map((preset) => (
85
+ <Select.Item key={preset.name} value={preset.name}>
86
+ {preset.displayName}
87
+ </Select.Item>
88
+ ))}
89
+ </Select.Content>
90
+ </Select>
91
+ ) : null}
92
+ </div>
114
93
 
115
- <div className="rz-field">
116
- <label className="rz-label" htmlFor="command-payload">
117
- Payload
118
- </label>
119
- <Textarea
120
- id="command-payload"
121
- value={commandPayload}
122
- onChange={(event) => onCommandPayloadChange(event.currentTarget.value)}
123
- placeholder='{"example": true}'
124
- spellCheck={false}
125
- />
126
- </div>
94
+ <Tabs.Panel value="dispatch" className="dev-host-tab-panel">
95
+ <form className="dev-host-form" onSubmit={onSubmit}>
96
+ <label className="dev-host-field">
97
+ <span className="dev-host-label">Command</span>
98
+ <Input
99
+ value={commandType}
100
+ onChange={(event) =>
101
+ onCommandTypeChange(event.currentTarget.value)
102
+ }
103
+ placeholder="get-snapshot"
104
+ spellCheck={false}
105
+ />
106
+ </label>
127
107
 
128
- <div className="rz-button-row">
129
- <IconButton
130
- type="button"
131
- variant="default"
132
- aria-label="Reset dispatcher"
133
- title="Reset dispatcher"
134
- onClick={onReset}
135
- >
136
- <ClearIcon />
137
- </IconButton>
108
+ <label className="dev-host-field">
109
+ <span className="dev-host-label">Payload</span>
110
+ <Textarea
111
+ value={commandPayload}
112
+ onChange={(event) =>
113
+ onCommandPayloadChange(event.currentTarget.value)
114
+ }
115
+ placeholder='{"example": true}'
116
+ spellCheck={false}
117
+ />
118
+ </label>
138
119
 
139
- <IconButton
140
- type="submit"
141
- variant="primary"
142
- aria-label="Dispatch message"
143
- title="Dispatch message"
144
- disabled={!canDispatch}
145
- >
146
- <SendIcon />
147
- </IconButton>
148
- </div>
149
- </form>
150
- </div>
151
- ) : null}
120
+ <div className="dev-host-actions">
121
+ <Button
122
+ variant="outline"
123
+ size="icon"
124
+ onClick={onReset}
125
+ aria-label="Reset dispatcher"
126
+ title="Reset dispatcher"
127
+ >
128
+ <RotateCcw />
129
+ </Button>
130
+ <Button
131
+ type="submit"
132
+ size="icon"
133
+ disabled={!canDispatch}
134
+ aria-label="Dispatch message"
135
+ title="Dispatch message"
136
+ >
137
+ <Send />
138
+ </Button>
139
+ </div>
140
+ </form>
141
+ </Tabs.Panel>
152
142
 
153
- {activeTab === 'flows' ? (
154
- <div className="rz-action-tab-panel">
155
- <FlowList
156
- flows={flows}
157
- flowRuns={flowRuns}
158
- hasRunningFlow={hasRunningFlow}
159
- onRunFlow={onRunFlow}
160
- onStopFlow={onStopFlow}
161
- />
162
- </div>
163
- ) : null}
164
- </div>
165
- </ScrollArea>
166
- </div>
167
- </div>
143
+ <Tabs.Panel value="flows" className="dev-host-tab-panel">
144
+ <FlowList
145
+ flows={flows}
146
+ flowRuns={flowRuns}
147
+ hasRunningFlow={hasRunningFlow}
148
+ onRunFlow={onRunFlow}
149
+ onStopFlow={onStopFlow}
150
+ />
151
+ </Tabs.Panel>
152
+ </Tabs>
153
+ </section>
168
154
  );
169
155
  };
@@ -1,6 +1,7 @@
1
+ import { Badge, Button, EmptyState } from '@rozenite/ui';
2
+ import { Play, Square } from 'lucide-react';
1
3
  import { formatPayloadForCommandInput } from '../utils.js';
2
4
  import type { DevHostFlowEntry, DevHostFlowRunState } from '../types.js';
3
- import { Button } from './ui/Button.js';
4
5
 
5
6
  type FlowListProps = {
6
7
  flows: DevHostFlowEntry[];
@@ -11,129 +12,108 @@ type FlowListProps = {
11
12
  };
12
13
 
13
14
  const getStatusLabel = (status: DevHostFlowRunState['status']) => {
14
- if (status === 'running') {
15
- return 'Running';
15
+ switch (status) {
16
+ case 'running':
17
+ return 'Running';
18
+ case 'succeeded':
19
+ return 'Completed';
20
+ case 'failed':
21
+ return 'Failed';
22
+ case 'aborted':
23
+ return 'Stopped';
16
24
  }
17
-
18
- if (status === 'succeeded') {
19
- return 'Completed';
20
- }
21
-
22
- if (status === 'failed') {
23
- return 'Failed';
24
- }
25
-
26
- if (status === 'aborted') {
27
- return 'Stopped';
28
- }
29
-
30
- return status;
31
25
  };
32
26
 
33
- export const FlowList = ({ flows, flowRuns, hasRunningFlow, onRunFlow, onStopFlow }: FlowListProps) => {
27
+ export const FlowList = ({
28
+ flows,
29
+ flowRuns,
30
+ hasRunningFlow,
31
+ onRunFlow,
32
+ onStopFlow,
33
+ }: FlowListProps) => {
34
34
  if (flows.length === 0) {
35
- return <div className="rz-flow-empty-state">No flows were configured for this plugin.</div>;
35
+ return (
36
+ <EmptyState
37
+ className="h-full"
38
+ title="No flows configured"
39
+ description="Add flows to rozenite.config.ts to run them here."
40
+ />
41
+ );
36
42
  }
37
43
 
38
- const hasExecutionState = flowRuns.length > 0;
39
-
40
44
  return (
41
- <div className="rz-flow-panel">
42
- <div className="rz-field">
43
- <div className="rz-label">Available flows</div>
44
-
45
- <div className="rz-flow-list">
46
- {flows.map((flow, index) => {
47
- const isActive = hasRunningFlow(flow.name);
45
+ <div className="dev-host-flow-list">
46
+ <div className="dev-host-field">
47
+ <span className="dev-host-label">Available flows</span>
48
+ <div className="grid gap-2">
49
+ {flows.map((flow) => {
50
+ const isRunning = hasRunningFlow(flow.name);
48
51
 
49
52
  return (
50
53
  <Button
51
- key={`${flow.name}-${index}`}
52
- type="button"
54
+ key={flow.name}
55
+ variant={isRunning ? 'secondary' : 'outline'}
56
+ className="dev-host-flow-button"
53
57
  onClick={() => onRunFlow(flow)}
54
- variant="default"
55
- isSelected={isActive}
56
- title={`Run ${flow.displayName}`}
57
- overrides={{
58
- BaseButton: {
59
- style: {
60
- display: 'flex',
61
- alignItems: 'center',
62
- justifyContent: 'space-between',
63
- gap: '12px',
64
- width: '100%',
65
- borderRadius: '8px',
66
- backgroundColor: isActive ? 'rgba(130, 50, 255, 0.14)' : 'rgba(255, 255, 255, 0.03)',
67
- borderColor: isActive ? 'rgba(130, 50, 255, 0.45)' : 'rgba(255, 255, 255, 0.08)',
68
- color: 'rgba(255, 255, 255, 0.88)',
69
- paddingTop: '10px',
70
- paddingRight: '12px',
71
- paddingBottom: '10px',
72
- paddingLeft: '12px',
73
- textAlign: 'left',
74
- },
75
- },
76
- }}
58
+ aria-label={`Run ${flow.displayName}`}
77
59
  >
78
- <span className="rz-flow-list-name">
60
+ <span className="dev-host-flow-name">
61
+ <Play />
79
62
  {flow.displayName}
80
- {flow.autoRun ? <span className="rz-flow-list-badge">Auto</span> : null}
63
+ {flow.autoRun ? <Badge variant="outline">Auto</Badge> : null}
64
+ </span>
65
+ <span className="text-xs text-muted-foreground">
66
+ {isRunning ? 'Running' : 'Run'}
81
67
  </span>
82
- <span className="rz-flow-list-action">{isActive ? 'Running' : 'Run'}</span>
83
68
  </Button>
84
69
  );
85
70
  })}
86
71
  </div>
87
72
  </div>
88
73
 
89
- {hasExecutionState ? (
90
- <div className="rz-field">
91
- <div className="rz-label">Flow runs</div>
92
-
93
- <div className="rz-flow-runs">
94
- {flowRuns.map((flowRun) => {
95
- const isRunning = flowRun.status === 'running';
96
-
97
- return (
98
- <div key={flowRun.id} className="rz-flow-state" data-status={flowRun.status}>
99
- <div className="rz-flow-state-header">
100
- <div className="rz-flow-state-title">
101
- {flowRun.flowDisplayName}
102
- {flowRun.autoRun ? <span className="rz-flow-state-badge">Auto</span> : null}
103
- </div>
104
-
105
- {isRunning ? (
106
- <Button
107
- type="button"
108
- variant="pill"
109
- onClick={() => onStopFlow(flowRun.id)}
110
- overrides={{
111
- BaseButton: {
112
- style: {
113
- flexShrink: 0,
114
- },
115
- },
116
- }}
117
- >
118
- Stop
119
- </Button>
74
+ {flowRuns.length > 0 ? (
75
+ <div className="dev-host-field">
76
+ <span className="dev-host-label">Flow runs</span>
77
+ <div className="dev-host-flow-runs">
78
+ {flowRuns.map((flowRun) => (
79
+ <div
80
+ key={flowRun.id}
81
+ className="dev-host-flow-state"
82
+ data-status={flowRun.status}
83
+ >
84
+ <div className="dev-host-flow-state-header">
85
+ <span className="dev-host-flow-title">
86
+ {flowRun.flowDisplayName}
87
+ {flowRun.autoRun ? (
88
+ <Badge variant="outline">Auto</Badge>
120
89
  ) : null}
121
- </div>
122
-
123
- <div className="rz-flow-state-status">{getStatusLabel(flowRun.status)}</div>
124
-
125
- {flowRun.error ? (
126
- <div className="rz-flow-state-error">{flowRun.error}</div>
127
- ) : null}
128
-
129
- {flowRun.result != null ? (
130
- <pre className="rz-flow-state-result">
131
- {formatPayloadForCommandInput(flowRun.result)}
132
- </pre>
90
+ </span>
91
+ {flowRun.status === 'running' ? (
92
+ <Button
93
+ variant="ghost"
94
+ size="compact"
95
+ onClick={() => onStopFlow(flowRun.id)}
96
+ >
97
+ <Square />
98
+ Stop
99
+ </Button>
133
100
  ) : null}
134
101
  </div>
135
- );
136
- })}
102
+ <span className="text-xs text-muted-foreground">
103
+ {getStatusLabel(flowRun.status)}
104
+ </span>
105
+ {flowRun.error ? (
106
+ <div className="dev-host-flow-state-error">
107
+ {flowRun.error}
108
+ </div>
109
+ ) : null}
110
+ {flowRun.result != null ? (
111
+ <pre className="dev-host-flow-state-result">
112
+ {formatPayloadForCommandInput(flowRun.result)}
113
+ </pre>
114
+ ) : null}
115
+ </div>
116
+ ))}
137
117
  </div>
138
118
  </div>
139
119
  ) : null}
@@ -1,103 +1,76 @@
1
- import type { PointerEvent as ReactPointerEvent } from 'react';
2
- import type { MessageEntry, ResizeHandleId } from '../types.js';
1
+ import { Button, JsonInspector, ScrollArea } from '@rozenite/ui';
2
+ import { Send, X } from 'lucide-react';
3
+ import type { MessageEntry } from '../types.js';
3
4
  import { formatMessageDate, formatPayloadForCommandInput } from '../utils.js';
4
- import { MessagePayloadDetail } from './MessagePayloadDetail.js';
5
- import { ResizeHandle } from './ResizeHandle.js';
6
- import { ScrollArea } from './ui/ScrollArea.js';
7
- import { SendIcon } from './icons.js';
8
- import { IconButton } from './ui/IconButton.js';
9
5
 
10
6
  type MessageDetailsPaneProps = {
11
- selectedMessage: MessageEntry | null;
12
- isOpen: boolean;
13
- isNarrowViewport: boolean;
14
- activeResizeHandle: ResizeHandleId | null;
7
+ selectedMessage: MessageEntry;
15
8
  onClose: () => void;
16
9
  onUseMessage: (message: MessageEntry) => void;
17
- onResizeStart: (event: ReactPointerEvent<HTMLDivElement>) => void;
18
10
  };
19
11
 
20
12
  export const MessageDetailsPane = ({
21
13
  selectedMessage,
22
- isOpen,
23
- isNarrowViewport,
24
- activeResizeHandle,
25
14
  onClose,
26
15
  onUseMessage,
27
- onResizeStart,
28
16
  }: MessageDetailsPaneProps) => {
29
- const isHidden = !isOpen || !selectedMessage;
30
-
31
17
  return (
32
- <>
33
- {!isNarrowViewport ? (
34
- <ResizeHandle
35
- className="rz-column-resize-handle"
36
- isDragging={activeResizeHandle === 'details-width'}
37
- isHidden={isHidden}
38
- orientation="vertical"
39
- label="Resize message details"
40
- onPointerDown={onResizeStart}
41
- />
42
- ) : null}
43
-
44
- <div className="rz-pane" data-hidden={isHidden} aria-hidden={isHidden}>
45
- <div className="rz-sidebar">
46
- <div className="rz-sidebar-header">
47
- <div className="rz-sidebar-title">Message Details</div>
48
- <div className="rz-header-actions">
49
- <IconButton
50
- type="button"
51
- aria-label="Use message in dispatcher"
52
- title="Use message in dispatcher"
53
- onClick={() => {
54
- if (selectedMessage) {
55
- onUseMessage(selectedMessage);
56
- }
57
- }}
58
- >
59
- <SendIcon />
60
- </IconButton>
18
+ <section className="dev-host-pane">
19
+ <header className="dev-host-pane-header">
20
+ <h2 className="dev-host-pane-title">Message Details</h2>
21
+ <div className="dev-host-pane-actions">
22
+ <Button
23
+ variant="ghost"
24
+ size="icon"
25
+ onClick={() => onUseMessage(selectedMessage)}
26
+ aria-label="Use message in dispatcher"
27
+ title="Use message in dispatcher"
28
+ >
29
+ <Send />
30
+ </Button>
31
+ <Button
32
+ variant="ghost"
33
+ size="icon"
34
+ onClick={onClose}
35
+ aria-label="Close message details"
36
+ title="Close message details"
37
+ >
38
+ <X />
39
+ </Button>
40
+ </div>
41
+ </header>
61
42
 
62
- <IconButton
63
- type="button"
64
- aria-label="Close message details"
65
- onClick={onClose}
66
- >
67
- ×
68
- </IconButton>
43
+ <ScrollArea className="dev-host-scroll">
44
+ <div className="dev-host-details">
45
+ <div className="dev-host-detail-section">
46
+ <span className="dev-host-label">Date</span>
47
+ <div className="dev-host-detail-value">
48
+ {formatMessageDate(selectedMessage.date)}
49
+ </div>
50
+ </div>
51
+ <div className="dev-host-detail-section">
52
+ <span className="dev-host-label">Type</span>
53
+ <div className="dev-host-detail-value">{selectedMessage.type}</div>
54
+ </div>
55
+ <div className="dev-host-detail-section">
56
+ <span className="dev-host-label">Payload</span>
57
+ <div className="dev-host-detail-payload">
58
+ {typeof selectedMessage.payload === 'object' &&
59
+ selectedMessage.payload !== null ? (
60
+ <JsonInspector
61
+ data={selectedMessage.payload}
62
+ defaultExpandedDepth={2}
63
+ />
64
+ ) : (
65
+ <pre className="m-0 whitespace-pre-wrap break-words">
66
+ {formatPayloadForCommandInput(selectedMessage.payload)}
67
+ </pre>
68
+ )}
69
69
  </div>
70
70
  </div>
71
-
72
- <ScrollArea className="rz-sidebar-scroll">
73
- {selectedMessage ? (
74
- <div className="rz-message-detail">
75
- <div className="rz-detail-section">
76
- <div className="rz-label">Date</div>
77
- <div className="rz-detail-value rz-detail-mono">
78
- {formatMessageDate(selectedMessage.date)}
79
- </div>
80
- </div>
81
-
82
- <div className="rz-detail-section">
83
- <div className="rz-label">Type</div>
84
- <div className="rz-detail-value rz-detail-mono">{selectedMessage.type}</div>
85
- </div>
86
-
87
- <div className="rz-detail-section">
88
- <div className="rz-label">Payload</div>
89
- <div className="rz-detail-payload">
90
- <MessagePayloadDetail payload={selectedMessage.payload} />
91
- </div>
92
- </div>
93
- </div>
94
- ) : (
95
- <div className="rz-empty-state">Select a message to inspect its details.</div>
96
- )}
97
- </ScrollArea>
98
71
  </div>
99
- </div>
100
- </>
72
+ </ScrollArea>
73
+ </section>
101
74
  );
102
75
  };
103
76