zelune 1.5.1 → 1.5.4
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/CHANGELOG.md +30 -0
- package/README.md +8 -15
- package/bin/cli.mjs +17 -6
- package/index.html +9 -2
- package/package.json +2 -1
- package/plugin.json +1 -1
- package/plugins/viteReactNativeFallbackPlugin.ts +568 -0
- package/plugins/viteVirtualScreensPlugin.ts +139 -8
- package/src/canvas/CanvasApp.tsx +111 -23
- package/src/canvas/FlowArrowsLayer.tsx +5 -5
- package/src/canvas/InspectorPanel.tsx +58 -49
- package/src/canvas/ScreenArtboard.tsx +90 -29
- package/src/main.tsx +70 -1
- package/src/runtime/MockNavigationContext.tsx +1007 -38
- package/src/runtime/reactNativeShim.ts +141 -0
- package/src/screens/ProductDetailScreen.tsx +32 -59
- package/src/server/astEngine.ts +10 -1
- package/src/styles.css +182 -21
- package/vite.config.ts +136 -67
|
@@ -7,12 +7,19 @@ const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID;
|
|
|
7
7
|
const PREFERRED_ORDER = ['Login', 'Home', 'ProductDetail', 'Checkout', 'Profile'];
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Vite Virtual Module plugin that dynamically discovers and
|
|
11
|
-
* screen components from any target project (`--project /path/to/app`)
|
|
10
|
+
* Vite Virtual Module plugin that dynamically discovers and loads React Native / Expo
|
|
11
|
+
* screen components from any target project (`--project /path/to/app`) with per-screen
|
|
12
|
+
* dynamic import() fault isolation so a broken import or top-level exception in one screen
|
|
13
|
+
* can never blank out the entire Zelune studio canvas.
|
|
12
14
|
*/
|
|
13
15
|
export function viteVirtualScreensPlugin(workspaceRoot: string): Plugin {
|
|
16
|
+
let isBuild = false;
|
|
17
|
+
|
|
14
18
|
return {
|
|
15
19
|
name: 'vite-virtual-zelune-screens',
|
|
20
|
+
configResolved(config) {
|
|
21
|
+
isBuild = config.command === 'build';
|
|
22
|
+
},
|
|
16
23
|
resolveId(id) {
|
|
17
24
|
if (id === VIRTUAL_MODULE_ID) {
|
|
18
25
|
return RESOLVED_VIRTUAL_MODULE_ID;
|
|
@@ -25,7 +32,7 @@ export function viteVirtualScreensPlugin(workspaceRoot: string): Plugin {
|
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
const discovered = discoverScreenFilesSync(workspaceRoot);
|
|
28
|
-
const
|
|
35
|
+
const lines: string[] = [
|
|
29
36
|
`import React from 'react';`,
|
|
30
37
|
`function resolveScreenComponent(mod) {`,
|
|
31
38
|
` if (!mod) return null;`,
|
|
@@ -37,6 +44,118 @@ export function viteVirtualScreensPlugin(workspaceRoot: string): Plugin {
|
|
|
37
44
|
` }`,
|
|
38
45
|
` return null;`,
|
|
39
46
|
`}`,
|
|
47
|
+
`function createIsolatedScreenComponent(screenId, filePath, loader) {`,
|
|
48
|
+
` let cachedComp = null;`,
|
|
49
|
+
` return function IsolatedScreenWrapper(props) {`,
|
|
50
|
+
` const [state, setState] = React.useState(() => ({`,
|
|
51
|
+
` Comp: cachedComp,`,
|
|
52
|
+
` error: null,`,
|
|
53
|
+
` attempt: 0,`,
|
|
54
|
+
` }));`,
|
|
55
|
+
` React.useEffect(() => {`,
|
|
56
|
+
` let cancelled = false;`,
|
|
57
|
+
` Promise.resolve()`,
|
|
58
|
+
` .then(() => loader(state.attempt))`,
|
|
59
|
+
` .then((mod) => {`,
|
|
60
|
+
` if (cancelled) return;`,
|
|
61
|
+
` const resolved = resolveScreenComponent(mod);`,
|
|
62
|
+
` if (!resolved) {`,
|
|
63
|
+
` setState((prev) => ({`,
|
|
64
|
+
` ...prev,`,
|
|
65
|
+
` Comp: null,`,
|
|
66
|
+
` error: 'No exported React component found in ' + filePath,`,
|
|
67
|
+
` }));`,
|
|
68
|
+
` } else {`,
|
|
69
|
+
` cachedComp = resolved;`,
|
|
70
|
+
` setState((prev) => ({ ...prev, Comp: resolved, error: null }));`,
|
|
71
|
+
` }`,
|
|
72
|
+
` })`,
|
|
73
|
+
` .catch((err) => {`,
|
|
74
|
+
` if (cancelled) return;`,
|
|
75
|
+
` const msg = err instanceof Error ? err.message : String(err);`,
|
|
76
|
+
` setState((prev) => ({ ...prev, Comp: null, error: msg }));`,
|
|
77
|
+
` });`,
|
|
78
|
+
` return () => {`,
|
|
79
|
+
` cancelled = true;`,
|
|
80
|
+
` };`,
|
|
81
|
+
` }, [state.attempt]);`,
|
|
82
|
+
` if (state.error) {`,
|
|
83
|
+
` return React.createElement(`,
|
|
84
|
+
` 'div',`,
|
|
85
|
+
` {`,
|
|
86
|
+
` style: {`,
|
|
87
|
+
` flex: 1,`,
|
|
88
|
+
` padding: 24,`,
|
|
89
|
+
` backgroundColor: '#18181B',`,
|
|
90
|
+
` color: '#FCA5A5',`,
|
|
91
|
+
` display: 'flex',`,
|
|
92
|
+
` flexDirection: 'column',`,
|
|
93
|
+
` justifyContent: 'center',`,
|
|
94
|
+
` gap: 10,`,
|
|
95
|
+
` fontFamily: 'var(--font-mono)',`,
|
|
96
|
+
` },`,
|
|
97
|
+
` },`,
|
|
98
|
+
` React.createElement(`,
|
|
99
|
+
` 'div',`,
|
|
100
|
+
` { style: { color: '#F87171', fontWeight: 700, fontSize: 13 } },`,
|
|
101
|
+
` 'Module Load Error in ' + filePath`,
|
|
102
|
+
` ),`,
|
|
103
|
+
` React.createElement(`,
|
|
104
|
+
` 'div',`,
|
|
105
|
+
` {`,
|
|
106
|
+
` style: {`,
|
|
107
|
+
` fontSize: 11,`,
|
|
108
|
+
` color: '#FECACA',`,
|
|
109
|
+
` whiteSpace: 'pre-wrap',`,
|
|
110
|
+
` wordBreak: 'break-word',`,
|
|
111
|
+
` maxHeight: 360,`,
|
|
112
|
+
` overflowY: 'auto',`,
|
|
113
|
+
` },`,
|
|
114
|
+
` },`,
|
|
115
|
+
` state.error`,
|
|
116
|
+
` ),`,
|
|
117
|
+
` React.createElement(`,
|
|
118
|
+
` 'button',`,
|
|
119
|
+
` {`,
|
|
120
|
+
` type: 'button',`,
|
|
121
|
+
` onClick: () => setState((prev) => ({ ...prev, error: null, attempt: prev.attempt + 1 })),`,
|
|
122
|
+
` style: {`,
|
|
123
|
+
` alignSelf: 'flex-start',`,
|
|
124
|
+
` marginTop: 6,`,
|
|
125
|
+
` padding: '6px 12px',`,
|
|
126
|
+
` borderRadius: 6,`,
|
|
127
|
+
` border: '1px solid rgba(248, 113, 113, 0.45)',`,
|
|
128
|
+
` backgroundColor: 'rgba(127, 29, 29, 0.4)',`,
|
|
129
|
+
` color: '#FEE2E2',`,
|
|
130
|
+
` fontSize: 11,`,
|
|
131
|
+
` fontWeight: 600,`,
|
|
132
|
+
` cursor: 'pointer',`,
|
|
133
|
+
` },`,
|
|
134
|
+
` },`,
|
|
135
|
+
` 'Retry Screen Load'`,
|
|
136
|
+
` )`,
|
|
137
|
+
` );`,
|
|
138
|
+
` }`,
|
|
139
|
+
` if (!state.Comp) {`,
|
|
140
|
+
` return React.createElement(`,
|
|
141
|
+
` 'div',`,
|
|
142
|
+
` {`,
|
|
143
|
+
` style: {`,
|
|
144
|
+
` flex: 1,`,
|
|
145
|
+
` display: 'flex',`,
|
|
146
|
+
` alignItems: 'center',`,
|
|
147
|
+
` justifyContent: 'center',`,
|
|
148
|
+
` color: '#64748B',`,
|
|
149
|
+
` fontSize: 12,`,
|
|
150
|
+
` fontFamily: 'var(--font-mono)',`,
|
|
151
|
+
` },`,
|
|
152
|
+
` },`,
|
|
153
|
+
` 'Loading ' + screenId + '...'`,
|
|
154
|
+
` );`,
|
|
155
|
+
` }`,
|
|
156
|
+
` return React.createElement(state.Comp, props);`,
|
|
157
|
+
` };`,
|
|
158
|
+
`}`,
|
|
40
159
|
];
|
|
41
160
|
|
|
42
161
|
const mapEntries: string[] = [];
|
|
@@ -51,16 +170,28 @@ export function viteVirtualScreensPlugin(workspaceRoot: string): Plugin {
|
|
|
51
170
|
return a.id.localeCompare(b.id);
|
|
52
171
|
});
|
|
53
172
|
|
|
54
|
-
sorted.forEach((scr
|
|
55
|
-
const varName = `_screenMod_${index}`;
|
|
173
|
+
sorted.forEach((scr) => {
|
|
56
174
|
const normalizedFullPath = scr.fullPath.replace(/\\/g, '/');
|
|
57
|
-
|
|
58
|
-
|
|
175
|
+
const fsUrl =
|
|
176
|
+
'/@fs' + (normalizedFullPath.startsWith('/') ? '' : '/') + normalizedFullPath;
|
|
177
|
+
const loaderExpr = isBuild
|
|
178
|
+
? `(attempt) => attempt > 0 ? import(/* @vite-ignore */ ${JSON.stringify(
|
|
179
|
+
normalizedFullPath
|
|
180
|
+
)} + '?t=' + Date.now()) : import(${JSON.stringify(normalizedFullPath)})`
|
|
181
|
+
: `(attempt) => import(/* @vite-ignore */ ${JSON.stringify(
|
|
182
|
+
fsUrl
|
|
183
|
+
)} + (attempt > 0 ? '?t=' + Date.now() : ''))`;
|
|
184
|
+
|
|
185
|
+
mapEntries.push(
|
|
186
|
+
` ${JSON.stringify(scr.id)}: createIsolatedScreenComponent(${JSON.stringify(
|
|
187
|
+
scr.id
|
|
188
|
+
)}, ${JSON.stringify(scr.relPath)}, ${loaderExpr})`
|
|
189
|
+
);
|
|
59
190
|
orderIds.push(scr.id);
|
|
60
191
|
});
|
|
61
192
|
|
|
62
193
|
return [
|
|
63
|
-
...
|
|
194
|
+
...lines,
|
|
64
195
|
`export const SCREEN_COMPONENTS = {`,
|
|
65
196
|
mapEntries.join(',\n'),
|
|
66
197
|
`};`,
|
package/src/canvas/CanvasApp.tsx
CHANGED
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
PanelRightClose,
|
|
17
17
|
PanelRightOpen,
|
|
18
18
|
Sliders,
|
|
19
|
+
Sun,
|
|
20
|
+
Moon,
|
|
19
21
|
} from 'lucide-react';
|
|
20
22
|
import { SCREEN_COMPONENTS, SCREEN_ORDER } from '../screens';
|
|
21
23
|
import { ScreenArtboard } from './ScreenArtboard';
|
|
@@ -67,6 +69,46 @@ export const CanvasApp: React.FC = () => {
|
|
|
67
69
|
const [isLeftPanelOpen, setIsLeftPanelOpen] = useState<boolean>(true);
|
|
68
70
|
const [isRightPanelOpen, setIsRightPanelOpen] = useState<boolean>(true);
|
|
69
71
|
|
|
72
|
+
// Studio color-scheme state ('dark' default, persisted in localStorage & <meta name="color-scheme">)
|
|
73
|
+
const [colorScheme, setColorScheme] = useState<'dark' | 'light'>(() => {
|
|
74
|
+
try {
|
|
75
|
+
return localStorage.getItem('color-scheme') === 'light' ? 'light' : 'dark';
|
|
76
|
+
} catch {
|
|
77
|
+
return 'dark';
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const applyColorScheme = useCallback((next: 'dark' | 'light') => {
|
|
82
|
+
setColorScheme(next);
|
|
83
|
+
const meta = document.querySelector<HTMLMetaElement>('meta[name="color-scheme"]');
|
|
84
|
+
if (meta) {
|
|
85
|
+
meta.content = next;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
localStorage.setItem('color-scheme', next);
|
|
89
|
+
} catch {
|
|
90
|
+
// Ignore storage write errors in restricted environments
|
|
91
|
+
}
|
|
92
|
+
}, []);
|
|
93
|
+
|
|
94
|
+
const toggleColorScheme = useCallback(() => {
|
|
95
|
+
applyColorScheme(colorScheme === 'dark' ? 'light' : 'dark');
|
|
96
|
+
}, [colorScheme, applyColorScheme]);
|
|
97
|
+
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
const handleStorage = (e: StorageEvent) => {
|
|
100
|
+
if (e.key !== 'color-scheme') return;
|
|
101
|
+
const next = e.newValue === 'light' ? 'light' : 'dark';
|
|
102
|
+
setColorScheme(next);
|
|
103
|
+
const meta = document.querySelector<HTMLMetaElement>('meta[name="color-scheme"]');
|
|
104
|
+
if (meta) {
|
|
105
|
+
meta.content = next;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
window.addEventListener('storage', handleStorage);
|
|
109
|
+
return () => window.removeEventListener('storage', handleStorage);
|
|
110
|
+
}, []);
|
|
111
|
+
|
|
70
112
|
const [pan, setPan] = useState<{ x: number; y: number }>({ x: 20, y: 10 });
|
|
71
113
|
const [zoom, setZoom] = useState<number>(0.68);
|
|
72
114
|
const [isPanning, setIsPanning] = useState<boolean>(false);
|
|
@@ -691,7 +733,14 @@ export const CanvasApp: React.FC = () => {
|
|
|
691
733
|
ZL
|
|
692
734
|
</div>
|
|
693
735
|
<div>
|
|
694
|
-
<div
|
|
736
|
+
<div
|
|
737
|
+
style={{
|
|
738
|
+
fontSize: 13.5,
|
|
739
|
+
fontWeight: 700,
|
|
740
|
+
letterSpacing: '-0.02em',
|
|
741
|
+
color: 'var(--studio-text-primary)',
|
|
742
|
+
}}
|
|
743
|
+
>
|
|
695
744
|
Zelune
|
|
696
745
|
</div>
|
|
697
746
|
<div
|
|
@@ -731,14 +780,16 @@ export const CanvasApp: React.FC = () => {
|
|
|
731
780
|
borderRadius: 5,
|
|
732
781
|
border: mode === 'inspect' ? '1px solid rgba(56, 189, 248, 0.35)' : '1px solid transparent',
|
|
733
782
|
backgroundColor: mode === 'inspect' ? 'var(--studio-surface-3)' : 'transparent',
|
|
734
|
-
color: mode === 'inspect' ? '#
|
|
783
|
+
color: mode === 'inspect' ? '#0284C7' : 'var(--studio-text-secondary)',
|
|
735
784
|
fontSize: 12,
|
|
736
785
|
fontWeight: 600,
|
|
737
786
|
cursor: 'pointer',
|
|
738
787
|
}}
|
|
739
788
|
>
|
|
740
|
-
<MousePointer size={14} style={{ flexShrink: 0 }} />
|
|
741
|
-
<span className="zelune-reveal-label"
|
|
789
|
+
<MousePointer size={14} style={{ flexShrink: 0, color: mode === 'inspect' ? '#38BDF8' : 'currentColor' }} />
|
|
790
|
+
<span className="zelune-reveal-label" style={{ color: mode === 'inspect' ? 'var(--studio-text-primary)' : 'inherit' }}>
|
|
791
|
+
Inspect & Edit
|
|
792
|
+
</span>
|
|
742
793
|
</button>
|
|
743
794
|
|
|
744
795
|
<button
|
|
@@ -751,8 +802,8 @@ export const CanvasApp: React.FC = () => {
|
|
|
751
802
|
padding: '6px 9px',
|
|
752
803
|
borderRadius: 5,
|
|
753
804
|
border: mode === 'interact' ? '1px solid rgba(16, 185, 129, 0.4)' : '1px solid transparent',
|
|
754
|
-
backgroundColor: mode === 'interact' ? 'rgba(
|
|
755
|
-
color: mode === 'interact' ? '#34D399' : 'var(--studio-text-secondary)',
|
|
805
|
+
backgroundColor: mode === 'interact' ? 'rgba(16, 185, 129, 0.14)' : 'transparent',
|
|
806
|
+
color: mode === 'interact' ? (colorScheme === 'dark' ? '#34D399' : '#059669') : 'var(--studio-text-secondary)',
|
|
756
807
|
fontSize: 12,
|
|
757
808
|
fontWeight: 600,
|
|
758
809
|
cursor: 'pointer',
|
|
@@ -773,8 +824,8 @@ export const CanvasApp: React.FC = () => {
|
|
|
773
824
|
padding: '7px 9px',
|
|
774
825
|
borderRadius: 7,
|
|
775
826
|
border: `1px solid ${showFlows ? 'rgba(99, 102, 241, 0.45)' : 'var(--studio-border-subtle)'}`,
|
|
776
|
-
backgroundColor: showFlows ? 'rgba(
|
|
777
|
-
color: showFlows ? '#C7D2FE' : 'var(--studio-text-secondary)',
|
|
827
|
+
backgroundColor: showFlows ? 'rgba(99, 102, 241, 0.14)' : 'var(--studio-surface-2)',
|
|
828
|
+
color: showFlows ? (colorScheme === 'dark' ? '#C7D2FE' : '#4F46E5') : 'var(--studio-text-secondary)',
|
|
778
829
|
fontSize: 12,
|
|
779
830
|
fontWeight: 600,
|
|
780
831
|
cursor: 'pointer',
|
|
@@ -785,7 +836,7 @@ export const CanvasApp: React.FC = () => {
|
|
|
785
836
|
</button>
|
|
786
837
|
</div>
|
|
787
838
|
|
|
788
|
-
{/* Right: Undo/Redo, Viewport Controls & Right Inspector Toggle */}
|
|
839
|
+
{/* Right: Undo/Redo, Viewport Controls, Theme Toggle & Right Inspector Toggle */}
|
|
789
840
|
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
790
841
|
<button
|
|
791
842
|
type="button"
|
|
@@ -801,7 +852,10 @@ export const CanvasApp: React.FC = () => {
|
|
|
801
852
|
borderRadius: 6,
|
|
802
853
|
border: '1px solid var(--studio-border-subtle)',
|
|
803
854
|
backgroundColor: 'var(--studio-surface-2)',
|
|
804
|
-
color:
|
|
855
|
+
color:
|
|
856
|
+
historyState.undoAvailable > 0
|
|
857
|
+
? 'var(--studio-text-primary)'
|
|
858
|
+
: 'var(--studio-text-muted)',
|
|
805
859
|
fontSize: 11.5,
|
|
806
860
|
fontFamily: 'var(--font-mono)',
|
|
807
861
|
cursor: historyState.undoAvailable > 0 ? 'pointer' : 'not-allowed',
|
|
@@ -825,7 +879,10 @@ export const CanvasApp: React.FC = () => {
|
|
|
825
879
|
borderRadius: 6,
|
|
826
880
|
border: '1px solid var(--studio-border-subtle)',
|
|
827
881
|
backgroundColor: 'var(--studio-surface-2)',
|
|
828
|
-
color:
|
|
882
|
+
color:
|
|
883
|
+
historyState.redoAvailable > 0
|
|
884
|
+
? 'var(--studio-text-primary)'
|
|
885
|
+
: 'var(--studio-text-muted)',
|
|
829
886
|
fontSize: 11.5,
|
|
830
887
|
cursor: historyState.redoAvailable > 0 ? 'pointer' : 'not-allowed',
|
|
831
888
|
}}
|
|
@@ -848,7 +905,7 @@ export const CanvasApp: React.FC = () => {
|
|
|
848
905
|
borderRadius: 6,
|
|
849
906
|
border: '1px solid var(--studio-border-subtle)',
|
|
850
907
|
backgroundColor: 'var(--studio-surface-2)',
|
|
851
|
-
color: '
|
|
908
|
+
color: 'var(--studio-text-secondary)',
|
|
852
909
|
cursor: 'pointer',
|
|
853
910
|
}}
|
|
854
911
|
>
|
|
@@ -862,7 +919,7 @@ export const CanvasApp: React.FC = () => {
|
|
|
862
919
|
textAlign: 'center',
|
|
863
920
|
fontSize: 11.5,
|
|
864
921
|
fontFamily: 'var(--font-mono)',
|
|
865
|
-
color: '
|
|
922
|
+
color: 'var(--studio-text-secondary)',
|
|
866
923
|
}}
|
|
867
924
|
>
|
|
868
925
|
{Math.round(zoom * 100)}%
|
|
@@ -881,7 +938,7 @@ export const CanvasApp: React.FC = () => {
|
|
|
881
938
|
borderRadius: 6,
|
|
882
939
|
border: '1px solid var(--studio-border-subtle)',
|
|
883
940
|
backgroundColor: 'var(--studio-surface-2)',
|
|
884
|
-
color: '
|
|
941
|
+
color: 'var(--studio-text-secondary)',
|
|
885
942
|
cursor: 'pointer',
|
|
886
943
|
}}
|
|
887
944
|
>
|
|
@@ -899,7 +956,7 @@ export const CanvasApp: React.FC = () => {
|
|
|
899
956
|
borderRadius: 6,
|
|
900
957
|
border: '1px solid var(--studio-border-subtle)',
|
|
901
958
|
backgroundColor: 'var(--studio-surface-2)',
|
|
902
|
-
color: '
|
|
959
|
+
color: 'var(--studio-text-secondary)',
|
|
903
960
|
fontSize: 11.5,
|
|
904
961
|
fontWeight: 500,
|
|
905
962
|
cursor: 'pointer',
|
|
@@ -920,7 +977,7 @@ export const CanvasApp: React.FC = () => {
|
|
|
920
977
|
borderRadius: 6,
|
|
921
978
|
border: '1px solid var(--studio-border-subtle)',
|
|
922
979
|
backgroundColor: 'var(--studio-surface-2)',
|
|
923
|
-
color: '
|
|
980
|
+
color: 'var(--studio-text-secondary)',
|
|
924
981
|
fontSize: 11.5,
|
|
925
982
|
fontWeight: 500,
|
|
926
983
|
cursor: 'pointer',
|
|
@@ -930,6 +987,37 @@ export const CanvasApp: React.FC = () => {
|
|
|
930
987
|
<span className="zelune-reveal-label">Grid</span>
|
|
931
988
|
</button>
|
|
932
989
|
|
|
990
|
+
<button
|
|
991
|
+
type="button"
|
|
992
|
+
className="zelune-interactive zelune-icon-reveal-btn"
|
|
993
|
+
onClick={toggleColorScheme}
|
|
994
|
+
title={
|
|
995
|
+
colorScheme === 'dark' ? 'Switch Canvas to Light Mode' : 'Switch Canvas to Dark Mode'
|
|
996
|
+
}
|
|
997
|
+
aria-label={
|
|
998
|
+
colorScheme === 'dark' ? 'Switch Canvas to Light Mode' : 'Switch Canvas to Dark Mode'
|
|
999
|
+
}
|
|
1000
|
+
style={{
|
|
1001
|
+
padding: '6px 8px',
|
|
1002
|
+
borderRadius: 6,
|
|
1003
|
+
border: '1px solid var(--studio-border-subtle)',
|
|
1004
|
+
backgroundColor: 'var(--studio-surface-2)',
|
|
1005
|
+
color: 'var(--studio-text-secondary)',
|
|
1006
|
+
fontSize: 11.5,
|
|
1007
|
+
fontWeight: 500,
|
|
1008
|
+
cursor: 'pointer',
|
|
1009
|
+
}}
|
|
1010
|
+
>
|
|
1011
|
+
{colorScheme === 'dark' ? (
|
|
1012
|
+
<Sun size={13} style={{ flexShrink: 0, color: '#F59E0B' }} />
|
|
1013
|
+
) : (
|
|
1014
|
+
<Moon size={13} style={{ flexShrink: 0, color: '#6366F1' }} />
|
|
1015
|
+
)}
|
|
1016
|
+
<span className="zelune-reveal-label">
|
|
1017
|
+
{colorScheme === 'dark' ? 'Light' : 'Dark'}
|
|
1018
|
+
</span>
|
|
1019
|
+
</button>
|
|
1020
|
+
|
|
933
1021
|
<div style={{ width: 1, height: 20, backgroundColor: 'var(--studio-border-subtle)', margin: '0 3px' }} />
|
|
934
1022
|
|
|
935
1023
|
<button
|
|
@@ -1068,7 +1156,7 @@ export const CanvasApp: React.FC = () => {
|
|
|
1068
1156
|
isSelected ? 'rgba(56, 189, 248, 0.35)' : 'transparent'
|
|
1069
1157
|
}`,
|
|
1070
1158
|
backgroundColor: isSelected ? 'var(--studio-surface-2)' : 'transparent',
|
|
1071
|
-
color: isSelected ? '
|
|
1159
|
+
color: isSelected ? 'var(--studio-text-primary)' : 'var(--studio-text-secondary)',
|
|
1072
1160
|
fontSize: 12.5,
|
|
1073
1161
|
fontWeight: isSelected ? 600 : 500,
|
|
1074
1162
|
cursor: 'pointer',
|
|
@@ -1108,7 +1196,7 @@ export const CanvasApp: React.FC = () => {
|
|
|
1108
1196
|
fontSize: 10,
|
|
1109
1197
|
fontWeight: 600,
|
|
1110
1198
|
letterSpacing: '0.05em',
|
|
1111
|
-
color: '
|
|
1199
|
+
color: 'var(--studio-text-primary)',
|
|
1112
1200
|
marginBottom: 4,
|
|
1113
1201
|
}}
|
|
1114
1202
|
>
|
|
@@ -1157,12 +1245,12 @@ export const CanvasApp: React.FC = () => {
|
|
|
1157
1245
|
borderRadius: 8,
|
|
1158
1246
|
backgroundColor: 'var(--studio-surface-1)',
|
|
1159
1247
|
border: '1px solid var(--studio-border-subtle)',
|
|
1160
|
-
color: '
|
|
1248
|
+
color: 'var(--studio-text-primary)',
|
|
1161
1249
|
fontSize: 11.5,
|
|
1162
1250
|
fontFamily: 'var(--font-mono)',
|
|
1163
1251
|
fontWeight: 600,
|
|
1164
1252
|
cursor: 'pointer',
|
|
1165
|
-
boxShadow: '0 10px 24px -6px rgba(0, 0, 0, 0.
|
|
1253
|
+
boxShadow: '0 10px 24px -6px rgba(0, 0, 0, 0.28)',
|
|
1166
1254
|
}}
|
|
1167
1255
|
>
|
|
1168
1256
|
<PanelLeftOpen size={13} color="#38BDF8" />
|
|
@@ -1193,19 +1281,19 @@ export const CanvasApp: React.FC = () => {
|
|
|
1193
1281
|
borderRadius: 8,
|
|
1194
1282
|
backgroundColor: 'var(--studio-surface-1)',
|
|
1195
1283
|
border: '1px solid var(--studio-border-subtle)',
|
|
1196
|
-
color: '
|
|
1284
|
+
color: 'var(--studio-text-primary)',
|
|
1197
1285
|
fontSize: 11.5,
|
|
1198
1286
|
fontFamily: 'var(--font-mono)',
|
|
1199
1287
|
fontWeight: 600,
|
|
1200
1288
|
cursor: 'pointer',
|
|
1201
|
-
boxShadow: '0 10px 24px -6px rgba(0, 0, 0, 0.
|
|
1289
|
+
boxShadow: '0 10px 24px -6px rgba(0, 0, 0, 0.28)',
|
|
1202
1290
|
}}
|
|
1203
1291
|
>
|
|
1204
1292
|
<Sliders size={13} color="#38BDF8" />
|
|
1205
1293
|
<span>
|
|
1206
1294
|
{inspectedData ? `<${inspectedData.tagName}> L${inspectedData.line}` : 'AST Inspector'}
|
|
1207
1295
|
</span>
|
|
1208
|
-
<PanelRightOpen size={13} color="
|
|
1296
|
+
<PanelRightOpen size={13} color="var(--studio-text-secondary)" />
|
|
1209
1297
|
</button>
|
|
1210
1298
|
)}
|
|
1211
1299
|
|
|
@@ -146,7 +146,7 @@ export const FlowArrowsLayer: React.FC<FlowArrowsLayerProps> = ({
|
|
|
146
146
|
cx={startX}
|
|
147
147
|
cy={startY}
|
|
148
148
|
r={4}
|
|
149
|
-
fill="
|
|
149
|
+
fill="var(--studio-surface-1)"
|
|
150
150
|
stroke={strokeColor}
|
|
151
151
|
strokeWidth={2}
|
|
152
152
|
/>
|
|
@@ -172,15 +172,15 @@ export const FlowArrowsLayer: React.FC<FlowArrowsLayerProps> = ({
|
|
|
172
172
|
gap: 4,
|
|
173
173
|
padding: '3px 9px',
|
|
174
174
|
borderRadius: 999,
|
|
175
|
-
backgroundColor:
|
|
176
|
-
border: `1px solid ${isHighlighted ? '
|
|
177
|
-
color: isHighlighted ? '
|
|
175
|
+
backgroundColor: 'var(--studio-surface-1)',
|
|
176
|
+
border: `1px solid ${isHighlighted ? 'var(--studio-accent-emerald)' : 'var(--studio-badge-indigo-border)'}`,
|
|
177
|
+
color: isHighlighted ? 'var(--studio-badge-emerald-text)' : 'var(--studio-badge-indigo-text)',
|
|
178
178
|
fontSize: 10,
|
|
179
179
|
fontWeight: 600,
|
|
180
180
|
fontFamily: 'JetBrains Mono, monospace',
|
|
181
181
|
whiteSpace: 'nowrap',
|
|
182
182
|
cursor: 'pointer',
|
|
183
|
-
boxShadow: '0 4px 12px rgba(0,0,0,0.
|
|
183
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.2)',
|
|
184
184
|
margin: '0 auto',
|
|
185
185
|
}}
|
|
186
186
|
>
|