@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.
- package/README.md +12 -0
- package/dist/bundle-dts.d.ts.map +1 -1
- package/dist/client-plugin.d.ts.map +1 -1
- package/dist/dev-config-module.d.ts.map +1 -1
- package/dist/dev-host/assets/index-DU3zXL2c.css +1 -0
- package/dist/dev-host/assets/index-Xsb6uYhI.js +13 -0
- package/dist/dev-host/index.html +3 -3
- package/dist/dev-host/manifest.json +2 -2
- package/dist/index.cjs +24 -8
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -8
- package/dist/react-native-plugin.d.ts.map +1 -1
- package/dist/sdk-plugin.d.ts.map +1 -1
- package/dist/server-plugin.d.ts.map +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +9 -10
- package/src/bundle-dts.ts +7 -6
- package/src/client-plugin.ts +8 -6
- package/src/dev-config-module.ts +4 -1
- package/src/dev-host/App.tsx +219 -413
- package/src/dev-host/components/DispatchForm.tsx +108 -122
- package/src/dev-host/components/FlowList.tsx +81 -101
- package/src/dev-host/components/MessageDetailsPane.tsx +56 -83
- package/src/dev-host/components/MessageLogPane.tsx +84 -66
- package/src/dev-host/components/PanelTabs.tsx +29 -10
- package/src/dev-host/config.ts +6 -2
- package/src/dev-host/constants.ts +0 -19
- package/src/dev-host/flow-runtime.ts +33 -12
- package/src/dev-host/index.html +1 -1
- package/src/dev-host/main.tsx +1 -10
- package/src/dev-host/server.ts +9 -3
- package/src/dev-host/styles.css +162 -830
- package/src/dev-host/types.ts +5 -10
- package/src/dev-host/utils.ts +9 -6
- package/src/dev-host/vite.config.mts +2 -0
- package/src/index.ts +15 -5
- package/src/load-config.ts +4 -4
- package/src/package-json.ts +1 -1
- package/src/react-native-plugin.ts +3 -0
- package/src/sdk-plugin.ts +3 -0
- package/src/server-plugin.ts +3 -0
- package/src/utils.ts +1 -1
- package/dist/dev-host/assets/index-CkxvBMpp.css +0 -1
- package/dist/dev-host/assets/index-cNKHRwej.js +0 -11
- package/src/dev-host/components/MessagePayloadDetail.tsx +0 -32
- package/src/dev-host/components/ResizeHandle.tsx +0 -33
- package/src/dev-host/components/icons.tsx +0 -79
- package/src/dev-host/components/ui/Button.tsx +0 -91
- package/src/dev-host/components/ui/DropdownMenu.tsx +0 -84
- package/src/dev-host/components/ui/IconButton.tsx +0 -41
- package/src/dev-host/components/ui/Input.tsx +0 -73
- package/src/dev-host/components/ui/ScrollArea.tsx +0 -20
- package/src/dev-host/components/ui/Tabs.tsx +0 -166
- package/src/dev-host/components/ui/Textarea.tsx +0 -79
- package/src/dev-host/components/ui/ToggleGroup.tsx +0 -120
package/src/dev-host/App.tsx
CHANGED
|
@@ -1,34 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
useRef,
|
|
4
|
-
useState,
|
|
5
|
-
type CSSProperties,
|
|
6
|
-
type FormEvent,
|
|
7
|
-
type PointerEvent as ReactPointerEvent,
|
|
8
|
-
} from 'react';
|
|
9
|
-
import {
|
|
10
|
-
DEFAULT_COMMAND_WIDTH,
|
|
11
|
-
DEFAULT_DEVTOOLS_HEIGHT,
|
|
12
|
-
DETAILS_PANEL_WIDTH,
|
|
13
|
-
MIN_COMMAND_WIDTH,
|
|
14
|
-
MIN_DETAILS_WIDTH,
|
|
15
|
-
MIN_DEVTOOLS_HEIGHT,
|
|
16
|
-
MIN_IFRAME_HEIGHT,
|
|
17
|
-
MIN_NARROW_IFRAME_HEIGHT,
|
|
18
|
-
SPLITTER_SIZE,
|
|
19
|
-
} from './constants.js';
|
|
1
|
+
import { useEffect, useRef, useState, type FormEvent } from 'react';
|
|
2
|
+
import { PluginHeader, PluginShell, Split, Tabs } from '@rozenite/ui';
|
|
20
3
|
import type {
|
|
21
4
|
DevHostFlowEntry,
|
|
22
5
|
DevHostPanelEntry,
|
|
23
6
|
DevHostPresetEntry,
|
|
24
7
|
DevHostState,
|
|
25
8
|
MessageEntry,
|
|
26
|
-
ResizeHandleId,
|
|
27
|
-
ResizeSession,
|
|
28
9
|
} from './types.js';
|
|
29
10
|
import { useFlowRunner } from './flow-runtime.js';
|
|
30
11
|
import {
|
|
31
|
-
clamp,
|
|
32
12
|
createMessageEntry,
|
|
33
13
|
formatPayloadForCommandInput,
|
|
34
14
|
getInitialPanel,
|
|
@@ -41,11 +21,7 @@ import {
|
|
|
41
21
|
} from './components/MessageDetailsPane.js';
|
|
42
22
|
import { MessageLogPane } from './components/MessageLogPane.js';
|
|
43
23
|
import { PanelTabs } from './components/PanelTabs.js';
|
|
44
|
-
import
|
|
45
|
-
import { ToggleGroup } from './components/ui/ToggleGroup.js';
|
|
46
|
-
import { RozeniteLogo } from './components/icons.js';
|
|
47
|
-
|
|
48
|
-
type CSSVariables = CSSProperties & Record<`--${string}`, string>;
|
|
24
|
+
import './styles.css';
|
|
49
25
|
|
|
50
26
|
type AppProps = DevHostState & {
|
|
51
27
|
flows: DevHostFlowEntry[];
|
|
@@ -54,74 +30,85 @@ type AppProps = DevHostState & {
|
|
|
54
30
|
|
|
55
31
|
type MobileDevtoolsTab = 'log' | 'actions';
|
|
56
32
|
|
|
57
|
-
const
|
|
58
|
-
|
|
33
|
+
const useNarrowViewport = () => {
|
|
34
|
+
const [isNarrow, setIsNarrow] = useState(
|
|
35
|
+
() => window.matchMedia('(max-width: 960px)').matches,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const mediaQuery = window.matchMedia('(max-width: 960px)');
|
|
40
|
+
const handleChange = (event: MediaQueryListEvent) => {
|
|
41
|
+
setIsNarrow(event.matches);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
setIsNarrow(mediaQuery.matches);
|
|
45
|
+
mediaQuery.addEventListener('change', handleChange);
|
|
46
|
+
|
|
47
|
+
return () => mediaQuery.removeEventListener('change', handleChange);
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
return isNarrow;
|
|
59
51
|
};
|
|
60
52
|
|
|
61
|
-
export const App = ({
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
53
|
+
export const App = ({
|
|
54
|
+
packageName,
|
|
55
|
+
packageDescription,
|
|
56
|
+
panels,
|
|
57
|
+
flows,
|
|
58
|
+
presets,
|
|
59
|
+
}: AppProps) => {
|
|
60
|
+
const [activePanel, setActivePanel] = useState<DevHostPanelEntry | null>(() =>
|
|
61
|
+
getInitialPanel(panels),
|
|
62
|
+
);
|
|
65
63
|
const [commandType, setCommandType] = useState('');
|
|
66
64
|
const [commandPayload, setCommandPayload] = useState('');
|
|
67
65
|
const [messages, setMessages] = useState<MessageEntry[]>([]);
|
|
68
|
-
const [selectedMessageId, setSelectedMessageId] = useState<string | null>(
|
|
66
|
+
const [selectedMessageId, setSelectedMessageId] = useState<string | null>(
|
|
67
|
+
null,
|
|
68
|
+
);
|
|
69
69
|
const [isDetailsOpen, setIsDetailsOpen] = useState(false);
|
|
70
|
-
const [
|
|
71
|
-
|
|
72
|
-
const [detailsWidth, setDetailsWidth] = useState(DETAILS_PANEL_WIDTH);
|
|
73
|
-
const [activeResizeHandle, setActiveResizeHandle] = useState<ResizeHandleId | null>(null);
|
|
74
|
-
const [isNarrowViewport, setIsNarrowViewport] = useState(getViewportMatch);
|
|
75
|
-
const [activeMobileTab, setActiveMobileTab] = useState<MobileDevtoolsTab>('log');
|
|
70
|
+
const [activeMobileTab, setActiveMobileTab] =
|
|
71
|
+
useState<MobileDevtoolsTab>('log');
|
|
76
72
|
const [iframeLoadNonce, setIframeLoadNonce] = useState(0);
|
|
77
|
-
const workspaceRef = useRef<HTMLElement | null>(null);
|
|
78
|
-
const logWorkspaceRef = useRef<HTMLDivElement | null>(null);
|
|
79
|
-
const devtoolsRef = useRef<HTMLElement | null>(null);
|
|
80
|
-
const resizeSessionRef = useRef<ResizeSession | null>(null);
|
|
81
73
|
const iframeRef = useRef<HTMLIFrameElement | null>(null);
|
|
82
74
|
const lastAutoRunLoadRef = useRef(0);
|
|
83
|
-
const
|
|
75
|
+
const isNarrowViewport = useNarrowViewport();
|
|
76
|
+
const {
|
|
77
|
+
flowRuns,
|
|
78
|
+
runFlow,
|
|
79
|
+
stopFlow,
|
|
80
|
+
hasRunningFlow,
|
|
81
|
+
registerMessage,
|
|
82
|
+
resetMessages,
|
|
83
|
+
} = useFlowRunner({
|
|
84
84
|
sendMessage: (type, payload) => {
|
|
85
85
|
iframeRef.current?.contentWindow?.postMessage(
|
|
86
|
-
{
|
|
87
|
-
pluginId: packageName,
|
|
88
|
-
type,
|
|
89
|
-
payload,
|
|
90
|
-
},
|
|
86
|
+
{ pluginId: packageName, type, payload },
|
|
91
87
|
'*',
|
|
92
88
|
);
|
|
93
|
-
|
|
94
|
-
appendMessage({
|
|
95
|
-
direction: 'in',
|
|
96
|
-
type,
|
|
97
|
-
payload,
|
|
98
|
-
});
|
|
89
|
+
appendMessage({ direction: 'in', type, payload });
|
|
99
90
|
},
|
|
100
91
|
});
|
|
101
92
|
|
|
102
93
|
const activeSource = activePanel?.source ?? '';
|
|
103
94
|
const activeLabel = activePanel?.label ?? '';
|
|
104
|
-
const
|
|
105
|
-
|
|
95
|
+
const selectedMessage =
|
|
96
|
+
messages.find((message) => message.id === selectedMessageId) ?? null;
|
|
97
|
+
const panelDescription = packageDescription.trim();
|
|
106
98
|
const trimmedCommandType = commandType.trim();
|
|
107
99
|
const trimmedCommandPayload = commandPayload.trim();
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
if (!trimmedCommandPayload) {
|
|
100
|
+
const canDispatch = (() => {
|
|
101
|
+
if (!trimmedCommandType || !trimmedCommandPayload) {
|
|
111
102
|
return false;
|
|
112
103
|
}
|
|
113
104
|
|
|
114
105
|
try {
|
|
115
|
-
JSON.parse(
|
|
106
|
+
JSON.parse(trimmedCommandPayload);
|
|
116
107
|
return true;
|
|
117
108
|
} catch {
|
|
118
109
|
return false;
|
|
119
110
|
}
|
|
120
111
|
})();
|
|
121
|
-
const canDispatch = hasCommandType && hasValidCommandPayload;
|
|
122
|
-
const panelDescription = packageDescription.trim();
|
|
123
|
-
const isDetailsVisible = isDetailsOpen && selectedMessage !== null;
|
|
124
|
-
const iframeMinHeight = isNarrowViewport ? MIN_NARROW_IFRAME_HEIGHT : MIN_IFRAME_HEIGHT;
|
|
125
112
|
|
|
126
113
|
useEffect(() => {
|
|
127
114
|
document.title = `${packageName} Dev Host`;
|
|
@@ -145,106 +132,6 @@ export const App = ({ packageName, packageDescription, panels, flows, presets }:
|
|
|
145
132
|
});
|
|
146
133
|
}, [flows, iframeLoadNonce, runFlow]);
|
|
147
134
|
|
|
148
|
-
useEffect(() => {
|
|
149
|
-
const mediaQuery = window.matchMedia('(max-width: 960px)');
|
|
150
|
-
|
|
151
|
-
const handleChange = (event: MediaQueryListEvent) => {
|
|
152
|
-
setIsNarrowViewport(event.matches);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
setIsNarrowViewport(mediaQuery.matches);
|
|
156
|
-
mediaQuery.addEventListener('change', handleChange);
|
|
157
|
-
|
|
158
|
-
return () => {
|
|
159
|
-
mediaQuery.removeEventListener('change', handleChange);
|
|
160
|
-
};
|
|
161
|
-
}, []);
|
|
162
|
-
|
|
163
|
-
useEffect(() => {
|
|
164
|
-
const workspace = workspaceRef.current;
|
|
165
|
-
if (!workspace) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const bounds = workspace.getBoundingClientRect();
|
|
170
|
-
const maxHeight = Math.max(MIN_DEVTOOLS_HEIGHT, bounds.height - iframeMinHeight - 12);
|
|
171
|
-
|
|
172
|
-
setDevToolsHeight((current) => clamp(current, MIN_DEVTOOLS_HEIGHT, maxHeight));
|
|
173
|
-
}, [iframeMinHeight]);
|
|
174
|
-
|
|
175
|
-
useEffect(() => {
|
|
176
|
-
if (!isNarrowViewport) {
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
setActiveMobileTab('log');
|
|
181
|
-
}, [isNarrowViewport]);
|
|
182
|
-
|
|
183
|
-
const selectPanel = (value: string) => {
|
|
184
|
-
const nextPanel = panels.find((panel) => panel.source === value);
|
|
185
|
-
if (!nextPanel) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
setActivePanel(nextPanel);
|
|
190
|
-
const nextUrl = new URL(window.location.href);
|
|
191
|
-
nextUrl.searchParams.set('panel', nextPanel.label);
|
|
192
|
-
window.history.replaceState(null, '', nextUrl);
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
const appendMessage = (input: Omit<MessageEntry, 'id' | 'date'>) => {
|
|
196
|
-
const nextEntry = createMessageEntry(input);
|
|
197
|
-
|
|
198
|
-
registerMessage(nextEntry);
|
|
199
|
-
setMessages((current) => [nextEntry, ...current]);
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
useEffect(() => {
|
|
203
|
-
const handlePointerMove = (event: PointerEvent) => {
|
|
204
|
-
resizeSessionRef.current?.onMove(event);
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const stopDragging = () => {
|
|
208
|
-
const session = resizeSessionRef.current;
|
|
209
|
-
if (!session) {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (session.element.hasPointerCapture(session.pointerId)) {
|
|
214
|
-
session.element.releasePointerCapture(session.pointerId);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
resizeSessionRef.current = null;
|
|
218
|
-
setActiveResizeHandle(null);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
window.addEventListener('pointermove', handlePointerMove);
|
|
222
|
-
window.addEventListener('pointerup', stopDragging);
|
|
223
|
-
window.addEventListener('pointercancel', stopDragging);
|
|
224
|
-
|
|
225
|
-
return () => {
|
|
226
|
-
window.removeEventListener('pointermove', handlePointerMove);
|
|
227
|
-
window.removeEventListener('pointerup', stopDragging);
|
|
228
|
-
window.removeEventListener('pointercancel', stopDragging);
|
|
229
|
-
};
|
|
230
|
-
}, []);
|
|
231
|
-
|
|
232
|
-
const startResize = (
|
|
233
|
-
handleId: ResizeHandleId,
|
|
234
|
-
event: ReactPointerEvent<HTMLDivElement>,
|
|
235
|
-
onMove: (event: PointerEvent) => void,
|
|
236
|
-
) => {
|
|
237
|
-
event.preventDefault();
|
|
238
|
-
event.currentTarget.setPointerCapture(event.pointerId);
|
|
239
|
-
resizeSessionRef.current = {
|
|
240
|
-
handleId,
|
|
241
|
-
pointerId: event.pointerId,
|
|
242
|
-
element: event.currentTarget,
|
|
243
|
-
onMove,
|
|
244
|
-
};
|
|
245
|
-
setActiveResizeHandle(handleId);
|
|
246
|
-
};
|
|
247
|
-
|
|
248
135
|
useEffect(() => {
|
|
249
136
|
const handleMessage = (event: MessageEvent) => {
|
|
250
137
|
if (event.source !== iframeRef.current?.contentWindow) {
|
|
@@ -254,19 +141,14 @@ export const App = ({ packageName, packageDescription, panels, flows, presets }:
|
|
|
254
141
|
if (
|
|
255
142
|
typeof event.data !== 'object' ||
|
|
256
143
|
event.data === null ||
|
|
257
|
-
!('type' in event.data) ||
|
|
258
144
|
event.data.type !== 'rozenite-message' ||
|
|
259
|
-
!('payload' in event.data)
|
|
145
|
+
!('payload' in event.data) ||
|
|
146
|
+
!isPluginMessage(event.data.payload)
|
|
260
147
|
) {
|
|
261
148
|
return;
|
|
262
149
|
}
|
|
263
150
|
|
|
264
151
|
const payload = event.data.payload;
|
|
265
|
-
|
|
266
|
-
if (!isPluginMessage(payload)) {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
152
|
appendMessage({
|
|
271
153
|
direction: 'out',
|
|
272
154
|
type: payload.type,
|
|
@@ -275,20 +157,25 @@ export const App = ({ packageName, packageDescription, panels, flows, presets }:
|
|
|
275
157
|
};
|
|
276
158
|
|
|
277
159
|
window.addEventListener('message', handleMessage);
|
|
278
|
-
|
|
279
|
-
return () => {
|
|
280
|
-
window.removeEventListener('message', handleMessage);
|
|
281
|
-
};
|
|
160
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
282
161
|
}, []);
|
|
283
162
|
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
163
|
+
const appendMessage = (input: Omit<MessageEntry, 'id' | 'date'>) => {
|
|
164
|
+
const nextEntry = createMessageEntry(input);
|
|
165
|
+
registerMessage(nextEntry);
|
|
166
|
+
setMessages((current) => [nextEntry, ...current]);
|
|
287
167
|
};
|
|
288
168
|
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
169
|
+
const selectPanel = (value: string) => {
|
|
170
|
+
const nextPanel = panels.find((panel) => panel.source === value);
|
|
171
|
+
if (!nextPanel) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
setActivePanel(nextPanel);
|
|
176
|
+
const nextUrl = new URL(window.location.href);
|
|
177
|
+
nextUrl.searchParams.set('panel', nextPanel.label);
|
|
178
|
+
window.history.replaceState(null, '', nextUrl);
|
|
292
179
|
};
|
|
293
180
|
|
|
294
181
|
const clearMessages = () => {
|
|
@@ -299,269 +186,188 @@ export const App = ({ packageName, packageDescription, panels, flows, presets }:
|
|
|
299
186
|
setActiveMobileTab('log');
|
|
300
187
|
};
|
|
301
188
|
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const bounds = workspace.getBoundingClientRect();
|
|
309
|
-
const nextHeight = bounds.bottom - event.clientY;
|
|
310
|
-
const maxHeight = Math.max(MIN_DEVTOOLS_HEIGHT, bounds.height - iframeMinHeight - 12);
|
|
311
|
-
|
|
312
|
-
setDevToolsHeight(clamp(nextHeight, MIN_DEVTOOLS_HEIGHT, maxHeight));
|
|
189
|
+
const resetForm = () => {
|
|
190
|
+
setCommandType('');
|
|
191
|
+
setCommandPayload('');
|
|
313
192
|
};
|
|
314
193
|
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const bounds = devtools.getBoundingClientRect();
|
|
322
|
-
const nextWidth = bounds.right - event.clientX;
|
|
323
|
-
const maxWidth = Math.max(MIN_COMMAND_WIDTH, bounds.width - 280);
|
|
324
|
-
|
|
325
|
-
setCommandWidth(clamp(nextWidth, MIN_COMMAND_WIDTH, maxWidth));
|
|
194
|
+
const applyPreset = (preset: DevHostPresetEntry) => {
|
|
195
|
+
setCommandType(preset.type);
|
|
196
|
+
setCommandPayload(formatPayloadForCommandInput(preset.payload));
|
|
326
197
|
};
|
|
327
198
|
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
if (!
|
|
199
|
+
const handleDispatch = (event: FormEvent<HTMLFormElement>) => {
|
|
200
|
+
event.preventDefault();
|
|
201
|
+
if (!canDispatch) {
|
|
331
202
|
return;
|
|
332
203
|
}
|
|
333
204
|
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
205
|
+
const payload = JSON.parse(trimmedCommandPayload) as unknown;
|
|
206
|
+
iframeRef.current?.contentWindow?.postMessage(
|
|
207
|
+
{ pluginId: packageName, type: trimmedCommandType, payload },
|
|
208
|
+
'*',
|
|
209
|
+
);
|
|
210
|
+
appendMessage({
|
|
211
|
+
direction: 'in',
|
|
212
|
+
type: trimmedCommandType,
|
|
213
|
+
payload,
|
|
214
|
+
});
|
|
215
|
+
resetForm();
|
|
339
216
|
};
|
|
340
217
|
|
|
341
218
|
const handleMessageSelect = (messageId: string) => {
|
|
342
219
|
setSelectedMessageId(messageId);
|
|
343
220
|
setIsDetailsOpen(true);
|
|
344
|
-
|
|
345
221
|
if (isNarrowViewport) {
|
|
346
222
|
setActiveMobileTab('log');
|
|
347
223
|
}
|
|
348
224
|
};
|
|
349
225
|
|
|
350
|
-
const
|
|
226
|
+
const useMessage = (message: MessageEntry) => {
|
|
227
|
+
const nextValues = getDispatcherValuesFromMessage(message);
|
|
228
|
+
setCommandType(nextValues.commandType);
|
|
229
|
+
setCommandPayload(nextValues.commandPayload);
|
|
351
230
|
setIsDetailsOpen(false);
|
|
352
|
-
|
|
353
231
|
if (isNarrowViewport) {
|
|
354
|
-
setActiveMobileTab('
|
|
232
|
+
setActiveMobileTab('actions');
|
|
355
233
|
}
|
|
356
234
|
};
|
|
357
235
|
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (!canDispatch) {
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
const type = trimmedCommandType;
|
|
371
|
-
|
|
372
|
-
let payload: unknown;
|
|
373
|
-
|
|
374
|
-
try {
|
|
375
|
-
payload = JSON.parse(commandPayload);
|
|
376
|
-
} catch (error) {
|
|
377
|
-
window.alert(
|
|
378
|
-
error instanceof Error
|
|
379
|
-
? `Payload must be valid JSON. ${error.message}`
|
|
380
|
-
: 'Payload must be valid JSON.',
|
|
381
|
-
);
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
iframeRef.current?.contentWindow?.postMessage({ pluginId: packageName, type, payload }, '*');
|
|
236
|
+
const messageLog = (
|
|
237
|
+
<MessageLogPane
|
|
238
|
+
messages={messages}
|
|
239
|
+
onSelectMessage={handleMessageSelect}
|
|
240
|
+
onClearMessages={clearMessages}
|
|
241
|
+
/>
|
|
242
|
+
);
|
|
386
243
|
|
|
387
|
-
|
|
244
|
+
const actions = (
|
|
245
|
+
<DispatchForm
|
|
246
|
+
commandType={commandType}
|
|
247
|
+
commandPayload={commandPayload}
|
|
248
|
+
flows={flows}
|
|
249
|
+
flowRuns={flowRuns}
|
|
250
|
+
hasRunningFlow={hasRunningFlow}
|
|
251
|
+
presets={presets}
|
|
252
|
+
canDispatch={canDispatch}
|
|
253
|
+
onRunFlow={runFlow}
|
|
254
|
+
onStopFlow={stopFlow}
|
|
255
|
+
onCommandTypeChange={setCommandType}
|
|
256
|
+
onCommandPayloadChange={setCommandPayload}
|
|
257
|
+
onApplyPreset={applyPreset}
|
|
258
|
+
onReset={resetForm}
|
|
259
|
+
onSubmit={handleDispatch}
|
|
260
|
+
/>
|
|
261
|
+
);
|
|
388
262
|
|
|
389
|
-
|
|
390
|
-
|
|
263
|
+
const devtools = isNarrowViewport ? (
|
|
264
|
+
<Tabs
|
|
265
|
+
className="dev-host-mobile-tabs"
|
|
266
|
+
value={activeMobileTab}
|
|
267
|
+
onValueChange={(value) => setActiveMobileTab(value as MobileDevtoolsTab)}
|
|
268
|
+
>
|
|
269
|
+
<Tabs.List
|
|
270
|
+
className="dev-host-mobile-tab-list"
|
|
271
|
+
aria-label="DevTools sections"
|
|
272
|
+
>
|
|
273
|
+
<Tabs.Tab value="log">Log</Tabs.Tab>
|
|
274
|
+
<Tabs.Tab value="actions">Actions</Tabs.Tab>
|
|
275
|
+
</Tabs.List>
|
|
276
|
+
<Tabs.Panel value="log" className="dev-host-mobile-tab-panel">
|
|
277
|
+
{isDetailsOpen && selectedMessage ? (
|
|
278
|
+
<MessageDetailsPane
|
|
279
|
+
selectedMessage={selectedMessage}
|
|
280
|
+
onClose={() => setIsDetailsOpen(false)}
|
|
281
|
+
onUseMessage={useMessage}
|
|
282
|
+
/>
|
|
283
|
+
) : (
|
|
284
|
+
messageLog
|
|
285
|
+
)}
|
|
286
|
+
</Tabs.Panel>
|
|
287
|
+
<Tabs.Panel value="actions" className="dev-host-mobile-tab-panel">
|
|
288
|
+
{actions}
|
|
289
|
+
</Tabs.Panel>
|
|
290
|
+
</Tabs>
|
|
291
|
+
) : (
|
|
292
|
+
<Split direction="horizontal" className="dev-host-devtools">
|
|
293
|
+
<Split.Pane minSize={35}>
|
|
294
|
+
{isDetailsOpen && selectedMessage ? (
|
|
295
|
+
<Split direction="horizontal">
|
|
296
|
+
<Split.Pane minSize={55}>{messageLog}</Split.Pane>
|
|
297
|
+
<Split.Handle />
|
|
298
|
+
<Split.Pane defaultSize={30} minSize={20}>
|
|
299
|
+
<MessageDetailsPane
|
|
300
|
+
selectedMessage={selectedMessage}
|
|
301
|
+
onClose={() => setIsDetailsOpen(false)}
|
|
302
|
+
onUseMessage={useMessage}
|
|
303
|
+
/>
|
|
304
|
+
</Split.Pane>
|
|
305
|
+
</Split>
|
|
306
|
+
) : (
|
|
307
|
+
messageLog
|
|
308
|
+
)}
|
|
309
|
+
</Split.Pane>
|
|
310
|
+
<Split.Handle />
|
|
311
|
+
<Split.Pane defaultSize={28} minSize={20}>
|
|
312
|
+
{actions}
|
|
313
|
+
</Split.Pane>
|
|
314
|
+
</Split>
|
|
315
|
+
);
|
|
391
316
|
|
|
392
317
|
return (
|
|
393
|
-
<
|
|
394
|
-
<
|
|
395
|
-
<div className="
|
|
396
|
-
<
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
318
|
+
<PluginShell className="dev-host">
|
|
319
|
+
<PluginHeader className="dev-host-header">
|
|
320
|
+
<div className="dev-host-header-title">
|
|
321
|
+
<PluginHeader.Title>Rozenite Dev Host</PluginHeader.Title>
|
|
322
|
+
<PluginHeader.Subtitle
|
|
323
|
+
className="dev-host-header-subtitle"
|
|
324
|
+
title={panelDescription}
|
|
325
|
+
>
|
|
326
|
+
{packageName}
|
|
327
|
+
</PluginHeader.Subtitle>
|
|
401
328
|
</div>
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
329
|
+
<PluginHeader.Actions>
|
|
330
|
+
<PluginHeader.ThemeSwitcher />
|
|
331
|
+
<PanelTabs
|
|
332
|
+
panels={panels}
|
|
333
|
+
activeSource={activeSource}
|
|
334
|
+
onValueChange={selectPanel}
|
|
335
|
+
/>
|
|
336
|
+
</PluginHeader.Actions>
|
|
337
|
+
</PluginHeader>
|
|
338
|
+
|
|
339
|
+
<PluginShell.Body className="dev-host-body">
|
|
340
|
+
<Split
|
|
341
|
+
direction="vertical"
|
|
342
|
+
className="dev-host-main-split"
|
|
343
|
+
autoSaveId="dev-host"
|
|
344
|
+
>
|
|
345
|
+
<Split.Pane
|
|
346
|
+
defaultSize={64}
|
|
347
|
+
minSize={30}
|
|
348
|
+
className="dev-host-preview"
|
|
349
|
+
>
|
|
350
|
+
{panels.length === 0 ? (
|
|
351
|
+
<div className="flex h-full items-center justify-center p-8 text-center text-sm text-muted-foreground">
|
|
352
|
+
No panels were defined in rozenite.config.ts.
|
|
353
|
+
</div>
|
|
354
|
+
) : (
|
|
413
355
|
<iframe
|
|
414
356
|
key={activeSource}
|
|
415
357
|
ref={iframeRef}
|
|
416
358
|
title={activeLabel || 'Rozenite panel preview'}
|
|
417
359
|
src={activeSource}
|
|
418
|
-
className="
|
|
419
|
-
data-resizing={activeResizeHandle === 'devtools-height'}
|
|
360
|
+
className="dev-host-iframe"
|
|
420
361
|
onLoad={() => setIframeLoadNonce((value) => value + 1)}
|
|
421
362
|
/>
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
/>
|
|
432
|
-
|
|
433
|
-
{isNarrowViewport ? (
|
|
434
|
-
<section ref={devtoolsRef} className="rz-devtools-mobile">
|
|
435
|
-
<div className="rz-devtools-mobile-tabs">
|
|
436
|
-
<div className="rz-devtools-mobile-toggle">
|
|
437
|
-
<ToggleGroup
|
|
438
|
-
aria-label="DevTools sections"
|
|
439
|
-
value={activeMobileTab}
|
|
440
|
-
onChange={handleMobileTabChange}
|
|
441
|
-
options={[
|
|
442
|
-
{ key: 'log', label: 'Log' },
|
|
443
|
-
{ key: 'actions', label: 'Actions' },
|
|
444
|
-
]}
|
|
445
|
-
/>
|
|
446
|
-
</div>
|
|
447
|
-
|
|
448
|
-
<div className="rz-devtools-mobile-panel">
|
|
449
|
-
{activeMobileTab === 'log' ? (
|
|
450
|
-
isDetailsVisible ? (
|
|
451
|
-
<MessageDetailsPane
|
|
452
|
-
selectedMessage={selectedMessage}
|
|
453
|
-
isOpen={true}
|
|
454
|
-
isNarrowViewport={true}
|
|
455
|
-
activeResizeHandle={activeResizeHandle}
|
|
456
|
-
onClose={handleDetailsClose}
|
|
457
|
-
onUseMessage={(message) => {
|
|
458
|
-
const nextValues = getDispatcherValuesFromMessage(message);
|
|
459
|
-
setCommandType(nextValues.commandType);
|
|
460
|
-
setCommandPayload(nextValues.commandPayload);
|
|
461
|
-
setIsDetailsOpen(false);
|
|
462
|
-
setActiveMobileTab('actions');
|
|
463
|
-
}}
|
|
464
|
-
onResizeStart={(event) => startResize('details-width', event, resizeDetailsPane)}
|
|
465
|
-
/>
|
|
466
|
-
) : (
|
|
467
|
-
<MessageLogPane
|
|
468
|
-
messages={messages}
|
|
469
|
-
selectedMessageId={selectedMessageId}
|
|
470
|
-
onSelectMessage={handleMessageSelect}
|
|
471
|
-
onClearMessages={clearMessages}
|
|
472
|
-
/>
|
|
473
|
-
)
|
|
474
|
-
) : (
|
|
475
|
-
<DispatchForm
|
|
476
|
-
commandType={commandType}
|
|
477
|
-
commandPayload={commandPayload}
|
|
478
|
-
flows={flows}
|
|
479
|
-
flowRuns={flowRuns}
|
|
480
|
-
hasRunningFlow={hasRunningFlow}
|
|
481
|
-
presets={presets}
|
|
482
|
-
canDispatch={canDispatch}
|
|
483
|
-
onRunFlow={runFlow}
|
|
484
|
-
onStopFlow={stopFlow}
|
|
485
|
-
onCommandTypeChange={setCommandType}
|
|
486
|
-
onCommandPayloadChange={setCommandPayload}
|
|
487
|
-
onApplyPreset={applyPreset}
|
|
488
|
-
onReset={resetForm}
|
|
489
|
-
onSubmit={handleDispatch}
|
|
490
|
-
/>
|
|
491
|
-
)}
|
|
492
|
-
</div>
|
|
493
|
-
</div>
|
|
494
|
-
</section>
|
|
495
|
-
) : (
|
|
496
|
-
<section
|
|
497
|
-
ref={devtoolsRef}
|
|
498
|
-
className="rz-devtools"
|
|
499
|
-
style={
|
|
500
|
-
{
|
|
501
|
-
'--rz-command-width': `${commandWidth}px`,
|
|
502
|
-
'--rz-command-splitter-width': `${SPLITTER_SIZE}px`,
|
|
503
|
-
} as CSSVariables
|
|
504
|
-
}
|
|
505
|
-
>
|
|
506
|
-
<div
|
|
507
|
-
ref={logWorkspaceRef}
|
|
508
|
-
className="rz-log-workspace"
|
|
509
|
-
style={
|
|
510
|
-
{
|
|
511
|
-
'--rz-details-width': isDetailsVisible ? `${detailsWidth}px` : '0px',
|
|
512
|
-
'--rz-details-splitter-width': isDetailsVisible ? `${SPLITTER_SIZE}px` : '0px',
|
|
513
|
-
} as CSSVariables
|
|
514
|
-
}
|
|
515
|
-
>
|
|
516
|
-
<MessageLogPane
|
|
517
|
-
messages={messages}
|
|
518
|
-
selectedMessageId={selectedMessageId}
|
|
519
|
-
onSelectMessage={handleMessageSelect}
|
|
520
|
-
onClearMessages={clearMessages}
|
|
521
|
-
/>
|
|
522
|
-
|
|
523
|
-
<MessageDetailsPane
|
|
524
|
-
selectedMessage={selectedMessage}
|
|
525
|
-
isOpen={isDetailsOpen}
|
|
526
|
-
isNarrowViewport={false}
|
|
527
|
-
activeResizeHandle={activeResizeHandle}
|
|
528
|
-
onClose={handleDetailsClose}
|
|
529
|
-
onUseMessage={(message) => {
|
|
530
|
-
const nextValues = getDispatcherValuesFromMessage(message);
|
|
531
|
-
setCommandType(nextValues.commandType);
|
|
532
|
-
setCommandPayload(nextValues.commandPayload);
|
|
533
|
-
}}
|
|
534
|
-
onResizeStart={(event) => startResize('details-width', event, resizeDetailsPane)}
|
|
535
|
-
/>
|
|
536
|
-
</div>
|
|
537
|
-
|
|
538
|
-
<ResizeHandle
|
|
539
|
-
className="rz-column-resize-handle"
|
|
540
|
-
isDragging={activeResizeHandle === 'command-width'}
|
|
541
|
-
orientation="vertical"
|
|
542
|
-
label="Resize command dispatcher"
|
|
543
|
-
onPointerDown={(event) => startResize('command-width', event, resizeCommandPane)}
|
|
544
|
-
/>
|
|
545
|
-
|
|
546
|
-
<DispatchForm
|
|
547
|
-
commandType={commandType}
|
|
548
|
-
commandPayload={commandPayload}
|
|
549
|
-
flows={flows}
|
|
550
|
-
flowRuns={flowRuns}
|
|
551
|
-
hasRunningFlow={hasRunningFlow}
|
|
552
|
-
presets={presets}
|
|
553
|
-
canDispatch={canDispatch}
|
|
554
|
-
onRunFlow={runFlow}
|
|
555
|
-
onStopFlow={stopFlow}
|
|
556
|
-
onCommandTypeChange={setCommandType}
|
|
557
|
-
onCommandPayloadChange={setCommandPayload}
|
|
558
|
-
onApplyPreset={applyPreset}
|
|
559
|
-
onReset={resetForm}
|
|
560
|
-
onSubmit={handleDispatch}
|
|
561
|
-
/>
|
|
562
|
-
</section>
|
|
563
|
-
)}
|
|
564
|
-
</main>
|
|
565
|
-
</div>
|
|
363
|
+
)}
|
|
364
|
+
</Split.Pane>
|
|
365
|
+
<Split.Handle />
|
|
366
|
+
<Split.Pane defaultSize={36} minSize={25}>
|
|
367
|
+
{devtools}
|
|
368
|
+
</Split.Pane>
|
|
369
|
+
</Split>
|
|
370
|
+
</PluginShell.Body>
|
|
371
|
+
</PluginShell>
|
|
566
372
|
);
|
|
567
373
|
};
|