@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,84 +1,102 @@
1
+ import { Button, DataTable, ScrollArea } from '@rozenite/ui';
2
+ import { Trash2 } from 'lucide-react';
3
+ import { useMemo } from 'react';
4
+ import type { DataTableColumn } from '@rozenite/ui';
1
5
  import type { MessageEntry } from '../types.js';
2
- import { cn, formatMessageTableDate, formatPayloadPreview } from '../utils.js';
3
- import { ClearIcon } from './icons.js';
4
- import { ScrollArea } from './ui/ScrollArea.js';
5
- import { IconButton } from './ui/IconButton.js';
6
+ import { formatMessageTableDate, formatPayloadPreview } from '../utils.js';
6
7
 
7
8
  type MessageLogPaneProps = {
8
9
  messages: MessageEntry[];
9
- selectedMessageId: string | null;
10
10
  onSelectMessage: (messageId: string) => void;
11
11
  onClearMessages: () => void;
12
12
  };
13
13
 
14
14
  export const MessageLogPane = ({
15
15
  messages,
16
- selectedMessageId,
17
16
  onSelectMessage,
18
17
  onClearMessages,
19
18
  }: MessageLogPaneProps) => {
20
- return (
21
- <div className="rz-pane">
22
- <div className="rz-log-pane">
23
- <div className="rz-sidebar-header">
24
- <div className="rz-sidebar-title">Message Log</div>
25
- <div className="rz-header-actions">
26
- <IconButton
27
- type="button"
28
- onClick={onClearMessages}
29
- disabled={messages.length === 0}
30
- aria-label="Clear message log"
31
- title="Clear message log"
32
- >
33
- <ClearIcon />
34
- </IconButton>
35
- </div>
36
- </div>
37
-
38
- <ScrollArea className="rz-sidebar-scroll">
39
- <div className="rz-message-list">
40
- <div className="rz-message-list-header">
41
- <div className="rz-message-header-cell">Dir</div>
42
- <div className="rz-message-header-cell">Date</div>
43
- <div className="rz-message-header-cell">Type</div>
44
- <div className="rz-message-header-cell">Payload</div>
45
- </div>
46
-
47
- {messages.map((message) => (
48
- <button
49
- key={message.id}
50
- type="button"
51
- className="rz-message-row"
52
- data-selected={message.id === selectedMessageId}
53
- onClick={() => onSelectMessage(message.id)}
54
- >
55
- <div
56
- className={cn(
57
- 'rz-message-cell rz-message-direction',
58
- message.direction === 'in' ? 'rz-message-dir-in' : 'rz-message-dir-out',
59
- )}
60
- aria-label={message.direction === 'in' ? 'Sent message' : 'Received message'}
61
- title={message.direction === 'in' ? 'Sent message' : 'Received message'}
62
- >
63
- <span className="rz-message-arrow" aria-hidden="true">
64
- {message.direction === 'in' ? '↑' : '↓'}
65
- </span>
66
- </div>
19
+ const columns = useMemo<DataTableColumn<MessageEntry>[]>(
20
+ () => [
21
+ {
22
+ accessorKey: 'direction',
23
+ header: 'Dir',
24
+ cell: ({ getValue }) => {
25
+ const direction = getValue<MessageEntry['direction']>();
26
+ const isSent = direction === 'in';
67
27
 
68
- <div className="rz-message-cell rz-message-date">
69
- {formatMessageTableDate(message.date)}
70
- </div>
28
+ return (
29
+ <span
30
+ className={
31
+ isSent ? 'dev-host-direction-in' : 'dev-host-direction-out'
32
+ }
33
+ aria-label={isSent ? 'Sent message' : 'Received message'}
34
+ title={isSent ? 'Sent message' : 'Received message'}
35
+ >
36
+ {isSent ? '↑' : '↓'}
37
+ </span>
38
+ );
39
+ },
40
+ },
41
+ {
42
+ accessorKey: 'date',
43
+ header: 'Date',
44
+ cell: ({ row }) => (
45
+ <span className="text-muted-foreground">
46
+ {formatMessageTableDate(row.original.date)}
47
+ </span>
48
+ ),
49
+ },
50
+ {
51
+ accessorKey: 'type',
52
+ header: 'Type',
53
+ cell: ({ getValue }) => (
54
+ <span className="font-medium">{getValue<string>()}</span>
55
+ ),
56
+ },
57
+ {
58
+ id: 'payload',
59
+ accessorFn: (message) => formatPayloadPreview(message.payload),
60
+ header: 'Payload',
61
+ cell: ({ getValue }) => (
62
+ <span className="block max-w-160 truncate font-mono text-xs text-muted-foreground">
63
+ {getValue<string>()}
64
+ </span>
65
+ ),
66
+ },
67
+ ],
68
+ [],
69
+ );
71
70
 
72
- <div className="rz-message-cell rz-message-type">{message.type}</div>
71
+ return (
72
+ <section className="dev-host-pane">
73
+ <header className="dev-host-pane-header">
74
+ <h2 className="dev-host-pane-title">Message Log</h2>
75
+ <Button
76
+ variant="ghost"
77
+ size="icon"
78
+ onClick={onClearMessages}
79
+ disabled={messages.length === 0}
80
+ aria-label="Clear message log"
81
+ title="Clear message log"
82
+ >
83
+ <Trash2 />
84
+ </Button>
85
+ </header>
73
86
 
74
- <pre className="rz-message-cell rz-message-preview">
75
- {formatPayloadPreview(message.payload)}
76
- </pre>
77
- </button>
78
- ))}
79
- </div>
80
- </ScrollArea>
81
- </div>
82
- </div>
87
+ <ScrollArea
88
+ className="dev-host-scroll"
89
+ viewportClassName="dev-host-scroll-viewport"
90
+ >
91
+ <DataTable
92
+ className="dev-host-message-table"
93
+ columns={columns}
94
+ data={messages}
95
+ emptyMessage="No messages yet."
96
+ getRowId={(message) => message.id}
97
+ onRowClick={(message) => onSelectMessage(message.id)}
98
+ />
99
+ </ScrollArea>
100
+ </section>
83
101
  );
84
102
  };
@@ -1,5 +1,5 @@
1
+ import { Select } from '@rozenite/ui';
1
2
  import type { DevHostPanelEntry } from '../types.js';
2
- import { ToggleGroup } from './ui/ToggleGroup.js';
3
3
 
4
4
  type PanelTabsProps = {
5
5
  panels: DevHostPanelEntry[];
@@ -7,16 +7,35 @@ type PanelTabsProps = {
7
7
  onValueChange: (value: string) => void;
8
8
  };
9
9
 
10
- export const PanelTabs = ({ panels, activeSource, onValueChange }: PanelTabsProps) => {
10
+ export const PanelTabs = ({
11
+ panels,
12
+ activeSource,
13
+ onValueChange,
14
+ }: PanelTabsProps) => {
15
+ if (panels.length === 0) {
16
+ return null;
17
+ }
18
+
19
+ const activePanel = panels.find((panel) => panel.source === activeSource);
20
+
11
21
  return (
12
- <ToggleGroup
13
- aria-label="Plugin panels"
22
+ <Select
14
23
  value={activeSource}
15
- onChange={onValueChange}
16
- options={panels.map((panel) => ({
17
- key: panel.source,
18
- label: panel.label,
19
- }))}
20
- />
24
+ onValueChange={(value) => onValueChange(String(value))}
25
+ >
26
+ <Select.Trigger
27
+ className="dev-host-panel-select"
28
+ aria-label="Plugin panel"
29
+ >
30
+ <Select.Value>{activePanel?.label}</Select.Value>
31
+ </Select.Trigger>
32
+ <Select.Content align="end">
33
+ {panels.map((panel) => (
34
+ <Select.Item key={panel.source} value={panel.source}>
35
+ {panel.label}
36
+ </Select.Item>
37
+ ))}
38
+ </Select.Content>
39
+ </Select>
21
40
  );
22
41
  };
@@ -19,7 +19,9 @@ const getEntryDisplayName = (value: unknown, fallback: string) => {
19
19
  };
20
20
 
21
21
  const getDevHostConfig = () => {
22
- const value = (window as unknown as Record<string, unknown>)[DEV_HOST_CONFIG_GLOBAL_KEY];
22
+ const value = (window as unknown as Record<string, unknown>)[
23
+ DEV_HOST_CONFIG_GLOBAL_KEY
24
+ ];
23
25
 
24
26
  if (typeof value !== 'object' || value === null) {
25
27
  return {} as { presets?: unknown; flows?: unknown };
@@ -28,7 +30,9 @@ const getDevHostConfig = () => {
28
30
  return value as { presets?: unknown; flows?: unknown };
29
31
  };
30
32
 
31
- const isDevHostPresetSource = (value: unknown): value is DevHostPresetSource => {
33
+ const isDevHostPresetSource = (
34
+ value: unknown,
35
+ ): value is DevHostPresetSource => {
32
36
  return (
33
37
  typeof value === 'object' &&
34
38
  value !== null &&
@@ -10,22 +10,3 @@ export const MIN_DETAILS_WIDTH = 280;
10
10
  export const DEFAULT_COMMAND_WIDTH = 320;
11
11
  export const MIN_COMMAND_WIDTH = 260;
12
12
  export const SPLITTER_SIZE = 6;
13
-
14
- export const jsonTreeTheme = {
15
- base00: 'transparent',
16
- base01: '#374151',
17
- base02: '#4b5563',
18
- base03: '#6b7280',
19
- base04: '#9ca3af',
20
- base05: '#d1d5db',
21
- base06: '#e5e7eb',
22
- base07: '#f9fafb',
23
- base08: '#ef4444',
24
- base09: '#f59e0b',
25
- base0A: '#10b981',
26
- base0B: '#3b82f6',
27
- base0C: '#06b6d4',
28
- base0D: '#8b5cf6',
29
- base0E: '#ec4899',
30
- base0F: '#f97316',
31
- };
@@ -1,6 +1,14 @@
1
1
  import { useEffect, useRef, useState } from 'react';
2
- import type { DevFlowContext, DevFlowMessage, DevFlowMessageMatcher } from '../load-config.js';
3
- import type { DevHostFlowEntry, DevHostFlowRunState, MessageEntry } from './types.js';
2
+ import type {
3
+ DevFlowContext,
4
+ DevFlowMessage,
5
+ DevFlowMessageMatcher,
6
+ } from '../load-config.js';
7
+ import type {
8
+ DevHostFlowEntry,
9
+ DevHostFlowRunState,
10
+ MessageEntry,
11
+ } from './types.js';
4
12
 
5
13
  type FlowRunnerOptions = {
6
14
  sendMessage: (type: string, payload: unknown) => void;
@@ -138,12 +146,12 @@ export const useFlowRunner = ({ sendMessage }: FlowRunnerOptions) => {
138
146
  }
139
147
  };
140
148
 
141
- const cleanupRun = () => {
142
- activeRun.cleanups.forEach((cleanup) => cleanup());
143
- activeRun.cleanups.clear();
144
- activeRun.listeners.clear();
145
- activeRunsRef.current.delete(runId);
146
- };
149
+ const cleanupRun = () => {
150
+ activeRun.cleanups.forEach((cleanup) => cleanup());
151
+ activeRun.cleanups.clear();
152
+ activeRun.listeners.clear();
153
+ activeRunsRef.current.delete(runId);
154
+ };
147
155
 
148
156
  const onMessage: DevFlowContext['onMessage'] = (matcher, listener) => {
149
157
  throwIfAborted();
@@ -203,13 +211,17 @@ export const useFlowRunner = ({ sendMessage }: FlowRunnerOptions) => {
203
211
  resolve(message);
204
212
  });
205
213
 
206
- controller.signal.addEventListener('abort', handleAbort, { once: true });
214
+ controller.signal.addEventListener('abort', handleAbort, {
215
+ once: true,
216
+ });
207
217
 
208
218
  if (options?.timeoutMs != null) {
209
219
  timeoutId = window.setTimeout(() => {
210
220
  cleanup();
211
221
  reject(
212
- new Error(`Timed out waiting for a matching message after ${options.timeoutMs}ms.`),
222
+ new Error(
223
+ `Timed out waiting for a matching message after ${options.timeoutMs}ms.`,
224
+ ),
213
225
  );
214
226
  }, options.timeoutMs);
215
227
  }
@@ -238,7 +250,14 @@ export const useFlowRunner = ({ sendMessage }: FlowRunnerOptions) => {
238
250
  ...current,
239
251
  ]);
240
252
 
241
- const updateRunState = (nextState: Partial<Omit<DevHostFlowRunState, 'id' | 'flowName' | 'flowDisplayName' | 'autoRun'>>) => {
253
+ const updateRunState = (
254
+ nextState: Partial<
255
+ Omit<
256
+ DevHostFlowRunState,
257
+ 'id' | 'flowName' | 'flowDisplayName' | 'autoRun'
258
+ >
259
+ >,
260
+ ) => {
242
261
  setFlowRuns((current) =>
243
262
  current.map((run) =>
244
263
  run.id === runId
@@ -283,7 +302,9 @@ export const useFlowRunner = ({ sendMessage }: FlowRunnerOptions) => {
283
302
  };
284
303
 
285
304
  const hasRunningFlow = (flowName: string) => {
286
- return flowRuns.some((run) => run.flowName === flowName && run.status === 'running');
305
+ return flowRuns.some(
306
+ (run) => run.flowName === flowName && run.status === 'running',
307
+ );
287
308
  };
288
309
 
289
310
  return {
@@ -1,4 +1,4 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
@@ -1,15 +1,10 @@
1
1
  import { StrictMode } from 'react';
2
2
  import { createRoot } from 'react-dom/client';
3
- import { BaseProvider, DarkTheme } from 'baseui';
4
- import { Client as Styletron } from 'styletron-engine-monolithic';
5
- import { Provider as StyletronProvider } from 'styletron-react';
6
3
  import { App } from './App.js';
7
4
  import { getDevHostFlows, getDevHostPresets } from './config.js';
8
5
  import './styles.css';
9
6
  import { readDevHostState } from './utils.js';
10
7
 
11
- const styletron = new Styletron();
12
-
13
8
  const rootElement = document.getElementById('root');
14
9
 
15
10
  if (!rootElement) {
@@ -22,10 +17,6 @@ const presets = getDevHostPresets();
22
17
 
23
18
  createRoot(rootElement).render(
24
19
  <StrictMode>
25
- <StyletronProvider value={styletron}>
26
- <BaseProvider theme={DarkTheme}>
27
- <App {...state} flows={flows} presets={presets} />
28
- </BaseProvider>
29
- </StyletronProvider>
20
+ <App {...state} flows={flows} presets={presets} />
30
21
  </StrictMode>,
31
22
  );
@@ -33,7 +33,9 @@ export const getDevHostSourceEntryFile = (packageDir: string) => {
33
33
  return path.join(packageDir, 'src', 'dev-host', 'main.tsx');
34
34
  };
35
35
 
36
- export const getBuiltDevHostAssets = (packageDir: string): DevHostBuiltAssets | null => {
36
+ export const getBuiltDevHostAssets = (
37
+ packageDir: string,
38
+ ): DevHostBuiltAssets | null => {
37
39
  const devHostDistDir = path.join(packageDir, 'dist', 'dev-host');
38
40
  const manifestPath = path.join(devHostDistDir, 'manifest.json');
39
41
 
@@ -41,11 +43,15 @@ export const getBuiltDevHostAssets = (packageDir: string): DevHostBuiltAssets |
41
43
  return null;
42
44
  }
43
45
 
44
- const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as DevHostBuildManifest;
46
+ const manifest = JSON.parse(
47
+ fs.readFileSync(manifestPath, 'utf8'),
48
+ ) as DevHostBuildManifest;
45
49
  const entry = manifest[DEV_HOST_BUILD_ENTRY_KEY];
46
50
 
47
51
  if (!entry?.file) {
48
- throw new Error(`Missing ${DEV_HOST_BUILD_ENTRY_KEY} entry in dev host manifest.`);
52
+ throw new Error(
53
+ `Missing ${DEV_HOST_BUILD_ENTRY_KEY} entry in dev host manifest.`,
54
+ );
49
55
  }
50
56
 
51
57
  return {