@progen-labs/spectra 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +99 -2
- package/bin/spectra.js +215 -0
- package/dist/assets/index-BvBsPok5.js +46 -0
- package/dist/assets/index-Da3Le5Px.css +1 -0
- package/dist/index.html +14 -0
- package/index.html +13 -0
- package/package.json +76 -4
- package/server/analysis/cpu.js +369 -0
- package/server/analysis/findings.js +551 -0
- package/server/analysis/locate.js +99 -0
- package/server/analysis/report.js +750 -0
- package/server/analysis/sources.js +249 -0
- package/server/analysis/trace.js +314 -0
- package/server/api.js +292 -0
- package/server/chrome.js +81 -0
- package/server/cli.js +94 -0
- package/server/config.js +59 -0
- package/server/dashboard.js +154 -0
- package/server/explore/boot.js +150 -0
- package/server/explore/classify.js +169 -0
- package/server/explore/discover.js +162 -0
- package/server/explore/evaluate-cli.js +101 -0
- package/server/explore/evaluate.js +165 -0
- package/server/explore/paths.js +105 -0
- package/server/explore/runner.js +94 -0
- package/server/explore/test-explore.js +139 -0
- package/server/explore/test-paths.js +75 -0
- package/server/framework.js +67 -0
- package/server/git.js +59 -0
- package/server/pdf/render.js +60 -0
- package/server/pdf/template.js +419 -0
- package/server/plugin.js +19 -0
- package/server/probe.browser.js +689 -0
- package/server/recorder.js +610 -0
- package/server/signin.js +27 -0
- package/server/test-analysis.js +424 -0
- package/server/test-compare.js +473 -0
- package/server/test-sources.js +136 -0
- package/shared/compare.js +977 -0
- package/shared/snapshot.js +77 -0
- package/src/App.jsx +361 -0
- package/src/api.js +51 -0
- package/src/components/AppearanceMenu.jsx +76 -0
- package/src/components/CodeRef.jsx +48 -0
- package/src/components/ComparePanel.jsx +143 -0
- package/src/components/CompareResults.jsx +473 -0
- package/src/components/ControlBar.jsx +336 -0
- package/src/components/CulpritSphere.jsx +218 -0
- package/src/components/Culprits.jsx +118 -0
- package/src/components/CulpritsHero.jsx +109 -0
- package/src/components/EvaluationPanel.jsx +160 -0
- package/src/components/FilePanel.jsx +225 -0
- package/src/components/FindingsList.jsx +381 -0
- package/src/components/HeatTrees.jsx +222 -0
- package/src/components/Icons.jsx +58 -0
- package/src/components/LongTasks.jsx +199 -0
- package/src/components/NetworkPanel.jsx +98 -0
- package/src/components/PageMap.jsx +329 -0
- package/src/components/Popover.jsx +51 -0
- package/src/components/ReactPanel.jsx +200 -0
- package/src/components/SidePicker.jsx +207 -0
- package/src/components/SnapshotButton.jsx +140 -0
- package/src/components/TimeBreakdown.jsx +45 -0
- package/src/components/TraceButton.jsx +76 -0
- package/src/components/TreeView.jsx +173 -0
- package/src/components/Vitals.jsx +163 -0
- package/src/culprits.js +127 -0
- package/src/download.js +18 -0
- package/src/format.js +26 -0
- package/src/heat.js +177 -0
- package/src/highlight.js +45 -0
- package/src/hooks/useCompare.js +187 -0
- package/src/hooks/useSession.js +73 -0
- package/src/layout.js +55 -0
- package/src/main.jsx +15 -0
- package/src/styles.css +2478 -0
- package/src/theme.js +75 -0
- package/src/themes.css +286 -0
- package/vite.config.js +8 -0
package/src/theme.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
const STYLE_KEY = 'perf-profiler:theme';
|
|
4
|
+
const MODE_KEY = 'perf-profiler:mode';
|
|
5
|
+
|
|
6
|
+
export const STYLES = [
|
|
7
|
+
{
|
|
8
|
+
id: 'glass',
|
|
9
|
+
label: 'Liquid Glass',
|
|
10
|
+
description: 'Frosted, translucent surfaces',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: 'space',
|
|
14
|
+
label: 'Space',
|
|
15
|
+
description: 'Deep-space mission control',
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export const MODES = [
|
|
20
|
+
{ id: 'light', label: 'Light' },
|
|
21
|
+
{ id: 'dark', label: 'Dark' },
|
|
22
|
+
{ id: 'system', label: 'Auto' },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const DEFAULTS = { style: 'glass', mode: 'system' };
|
|
26
|
+
|
|
27
|
+
const readKey = (key, allowed, fallback) => {
|
|
28
|
+
try {
|
|
29
|
+
const value = localStorage.getItem(key);
|
|
30
|
+
return allowed.some(option => option.id === value) ? value : fallback;
|
|
31
|
+
} catch {
|
|
32
|
+
return fallback;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const readAppearance = () => ({
|
|
37
|
+
style: readKey(STYLE_KEY, STYLES, DEFAULTS.style),
|
|
38
|
+
mode: readKey(MODE_KEY, MODES, DEFAULTS.mode),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const darkQuery = () => window.matchMedia('(prefers-color-scheme: dark)');
|
|
42
|
+
|
|
43
|
+
/** Writes the theme to <html> so every CSS variable block can key off it. */
|
|
44
|
+
export function applyAppearance({ style, mode }) {
|
|
45
|
+
const resolved =
|
|
46
|
+
mode === 'system' ? (darkQuery().matches ? 'dark' : 'light') : mode;
|
|
47
|
+
const root = document.documentElement;
|
|
48
|
+
root.dataset.theme = style;
|
|
49
|
+
root.dataset.mode = resolved;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function useAppearance() {
|
|
53
|
+
const [appearance, setAppearance] = useState(readAppearance);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
applyAppearance(appearance);
|
|
57
|
+
try {
|
|
58
|
+
localStorage.setItem(STYLE_KEY, appearance.style);
|
|
59
|
+
localStorage.setItem(MODE_KEY, appearance.mode);
|
|
60
|
+
} catch {
|
|
61
|
+
// Storage can be blocked; the choice then lasts for this session only.
|
|
62
|
+
}
|
|
63
|
+
if (appearance.mode !== 'system') return undefined;
|
|
64
|
+
const query = darkQuery();
|
|
65
|
+
const onChange = () => applyAppearance(appearance);
|
|
66
|
+
query.addEventListener('change', onChange);
|
|
67
|
+
return () => query.removeEventListener('change', onChange);
|
|
68
|
+
}, [appearance]);
|
|
69
|
+
|
|
70
|
+
const update = useCallback(
|
|
71
|
+
patch => setAppearance(prev => ({ ...prev, ...patch })),
|
|
72
|
+
[],
|
|
73
|
+
);
|
|
74
|
+
return [appearance, update];
|
|
75
|
+
}
|
package/src/themes.css
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Design tokens. <html data-theme="glass|space" data-mode="light|dark"> (set by
|
|
3
|
+
* theme.js) selects one of four palettes. Components only read the variables,
|
|
4
|
+
* so a theme never needs to touch component rules except for a few signature
|
|
5
|
+
* details at the bottom of this file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/* Shared shape + type tokens; themes override what they need. */
|
|
9
|
+
:root {
|
|
10
|
+
--font-ui:
|
|
11
|
+
-apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', system-ui,
|
|
12
|
+
sans-serif;
|
|
13
|
+
--font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
|
|
14
|
+
--radius: 14px;
|
|
15
|
+
--radius-sm: 9px;
|
|
16
|
+
--btn-radius: 9px;
|
|
17
|
+
--blur: none;
|
|
18
|
+
--on-accent: #fff;
|
|
19
|
+
--label-case: none;
|
|
20
|
+
--label-tracking: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* ============ Liquid Glass ============ */
|
|
24
|
+
:root[data-theme='glass'] {
|
|
25
|
+
--radius: 22px;
|
|
26
|
+
--radius-sm: 12px;
|
|
27
|
+
--btn-radius: 999px;
|
|
28
|
+
--blur: blur(28px) saturate(180%);
|
|
29
|
+
--font-ui:
|
|
30
|
+
-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text',
|
|
31
|
+
system-ui, sans-serif;
|
|
32
|
+
}
|
|
33
|
+
:root[data-theme='glass'][data-mode='light'] {
|
|
34
|
+
color-scheme: light;
|
|
35
|
+
--bg:
|
|
36
|
+
radial-gradient(900px 600px at 8% -8%, #b9dcff 0%, transparent 62%),
|
|
37
|
+
radial-gradient(800px 560px at 96% 4%, #ffd3ea 0%, transparent 58%),
|
|
38
|
+
radial-gradient(1000px 700px at 62% 112%, #d6cfff 0%, transparent 62%),
|
|
39
|
+
#eaeff7;
|
|
40
|
+
--panel: rgb(255 255 255 / 0.5);
|
|
41
|
+
--panel-solid: #f4f7fc;
|
|
42
|
+
--panel-border: rgb(255 255 255 / 0.75);
|
|
43
|
+
--panel-edge:
|
|
44
|
+
inset 0 1px 0 rgb(255 255 255 / 0.9), inset 0 -1px 0 rgb(120 135 170 / 0.08);
|
|
45
|
+
--shadow: 0 1px 2px rgb(40 60 110 / 0.06), 0 12px 36px rgb(40 60 110 / 0.12);
|
|
46
|
+
--shadow-pop:
|
|
47
|
+
0 4px 12px rgb(40 60 110 / 0.12), 0 24px 60px rgb(40 60 110 / 0.22);
|
|
48
|
+
--surface: #f6f8fc;
|
|
49
|
+
--surface-2: rgb(255 255 255 / 0.62);
|
|
50
|
+
--control: rgb(255 255 255 / 0.7);
|
|
51
|
+
--control-hover: rgb(255 255 255 / 0.95);
|
|
52
|
+
--border: rgb(70 85 125 / 0.16);
|
|
53
|
+
--text: #0e1220;
|
|
54
|
+
--text-2: #444c5e;
|
|
55
|
+
--text-muted: #6d7588;
|
|
56
|
+
--grid: rgb(70 85 125 / 0.1);
|
|
57
|
+
--accent: #0a67d1;
|
|
58
|
+
--accent-strong: #0a6fdb;
|
|
59
|
+
--accent-soft: rgb(10 111 219 / 0.12);
|
|
60
|
+
--accent-glow: 0 6px 18px rgb(10 111 219 / 0.35);
|
|
61
|
+
--heat: #f2602f;
|
|
62
|
+
--cat-1: #0a6fdb;
|
|
63
|
+
--cat-2: #f2602f;
|
|
64
|
+
--cat-3: #1fa971;
|
|
65
|
+
--cat-4: #eba000;
|
|
66
|
+
--cat-5: #e5679b;
|
|
67
|
+
--cat-6: #5b54d6;
|
|
68
|
+
--cat-other: #a3a9b8;
|
|
69
|
+
--good: #1a7f37;
|
|
70
|
+
--warn: #a35607;
|
|
71
|
+
--poor: #c9302c;
|
|
72
|
+
--code-string: #17754f;
|
|
73
|
+
--code-keyword: #5b54d6;
|
|
74
|
+
--code-number: #a35607;
|
|
75
|
+
}
|
|
76
|
+
:root[data-theme='glass'][data-mode='dark'] {
|
|
77
|
+
color-scheme: dark;
|
|
78
|
+
--bg:
|
|
79
|
+
radial-gradient(
|
|
80
|
+
900px 600px at 6% -10%,
|
|
81
|
+
rgb(36 99 235 / 0.5) 0%,
|
|
82
|
+
transparent 62%
|
|
83
|
+
),
|
|
84
|
+
radial-gradient(
|
|
85
|
+
800px 560px at 98% 0%,
|
|
86
|
+
rgb(168 56 200 / 0.38) 0%,
|
|
87
|
+
transparent 58%
|
|
88
|
+
),
|
|
89
|
+
radial-gradient(
|
|
90
|
+
1000px 700px at 60% 115%,
|
|
91
|
+
rgb(20 150 170 / 0.3) 0%,
|
|
92
|
+
transparent 62%
|
|
93
|
+
),
|
|
94
|
+
#0a0c13;
|
|
95
|
+
--panel: rgb(34 38 54 / 0.52);
|
|
96
|
+
--panel-solid: #161924;
|
|
97
|
+
--panel-border: rgb(255 255 255 / 0.14);
|
|
98
|
+
--panel-edge:
|
|
99
|
+
inset 0 1px 0 rgb(255 255 255 / 0.18),
|
|
100
|
+
inset 0 -1px 0 rgb(255 255 255 / 0.03);
|
|
101
|
+
--shadow: 0 1px 2px rgb(0 0 0 / 0.3), 0 16px 44px rgb(0 0 0 / 0.38);
|
|
102
|
+
--shadow-pop: 0 4px 14px rgb(0 0 0 / 0.4), 0 28px 70px rgb(0 0 0 / 0.55);
|
|
103
|
+
--surface: #12141d;
|
|
104
|
+
--surface-2: rgb(255 255 255 / 0.06);
|
|
105
|
+
--control: rgb(255 255 255 / 0.09);
|
|
106
|
+
--control-hover: rgb(255 255 255 / 0.16);
|
|
107
|
+
--border: rgb(255 255 255 / 0.13);
|
|
108
|
+
--text: #f4f6fb;
|
|
109
|
+
--text-2: #b8bfd0;
|
|
110
|
+
--text-muted: #8990a3;
|
|
111
|
+
--grid: rgb(255 255 255 / 0.07);
|
|
112
|
+
--accent: #4da3ff;
|
|
113
|
+
--accent-strong: #0a6fdb;
|
|
114
|
+
--accent-soft: rgb(77 163 255 / 0.18);
|
|
115
|
+
--accent-glow: 0 6px 22px rgb(10 111 219 / 0.5);
|
|
116
|
+
--heat: #ff7a4d;
|
|
117
|
+
--cat-1: #4da3ff;
|
|
118
|
+
--cat-2: #ff7a4d;
|
|
119
|
+
--cat-3: #30c98a;
|
|
120
|
+
--cat-4: #f0b429;
|
|
121
|
+
--cat-5: #f06ea0;
|
|
122
|
+
--cat-6: #9a93f5;
|
|
123
|
+
--cat-other: #6c7386;
|
|
124
|
+
--good: #3fcf6b;
|
|
125
|
+
--warn: #f0b04a;
|
|
126
|
+
--poor: #ff6b6b;
|
|
127
|
+
--code-string: #3fd49b;
|
|
128
|
+
--code-keyword: #a29bf7;
|
|
129
|
+
--code-number: #f0b04a;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* ============ Space ============ */
|
|
133
|
+
:root[data-theme='space'] {
|
|
134
|
+
--radius: 12px;
|
|
135
|
+
--radius-sm: 8px;
|
|
136
|
+
--btn-radius: 8px;
|
|
137
|
+
--blur: blur(10px);
|
|
138
|
+
--label-case: uppercase;
|
|
139
|
+
--label-tracking: 0.08em;
|
|
140
|
+
--font-ui:
|
|
141
|
+
'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui,
|
|
142
|
+
sans-serif;
|
|
143
|
+
}
|
|
144
|
+
:root[data-theme='space'][data-mode='dark'] {
|
|
145
|
+
color-scheme: dark;
|
|
146
|
+
--bg:
|
|
147
|
+
radial-gradient(1px 1px at 22px 34px, rgb(255 255 255 / 0.9), transparent),
|
|
148
|
+
radial-gradient(1px 1px at 96px 128px, rgb(255 255 255 / 0.6), transparent),
|
|
149
|
+
radial-gradient(
|
|
150
|
+
1.5px 1.5px at 168px 62px,
|
|
151
|
+
rgb(160 200 255 / 0.9),
|
|
152
|
+
transparent
|
|
153
|
+
),
|
|
154
|
+
radial-gradient(1px 1px at 58px 176px, rgb(255 255 255 / 0.5), transparent),
|
|
155
|
+
radial-gradient(
|
|
156
|
+
1.5px 1.5px at 190px 190px,
|
|
157
|
+
rgb(200 180 255 / 0.8),
|
|
158
|
+
transparent
|
|
159
|
+
),
|
|
160
|
+
radial-gradient(
|
|
161
|
+
900px 620px at 82% -12%,
|
|
162
|
+
rgb(124 92 255 / 0.3),
|
|
163
|
+
transparent 62%
|
|
164
|
+
),
|
|
165
|
+
radial-gradient(
|
|
166
|
+
800px 600px at -6% 108%,
|
|
167
|
+
rgb(0 190 255 / 0.18),
|
|
168
|
+
transparent 60%
|
|
169
|
+
),
|
|
170
|
+
#04050d;
|
|
171
|
+
--bg-size:
|
|
172
|
+
210px 210px, 210px 210px, 210px 210px, 210px 210px, 210px 210px, auto, auto,
|
|
173
|
+
auto;
|
|
174
|
+
--panel: rgb(12 16 36 / 0.74);
|
|
175
|
+
--panel-solid: #0b0f24;
|
|
176
|
+
--panel-border: rgb(110 130 255 / 0.24);
|
|
177
|
+
--panel-edge: inset 0 1px 0 rgb(160 180 255 / 0.1);
|
|
178
|
+
--shadow: 0 0 0 1px rgb(0 0 0 / 0.4), 0 18px 50px rgb(0 0 0 / 0.55);
|
|
179
|
+
--shadow-pop:
|
|
180
|
+
0 0 0 1px rgb(110 130 255 / 0.25), 0 0 40px rgb(100 100 255 / 0.18),
|
|
181
|
+
0 28px 70px rgb(0 0 0 / 0.7);
|
|
182
|
+
--surface: #0a0d20;
|
|
183
|
+
--surface-2: rgb(110 130 255 / 0.07);
|
|
184
|
+
--control: rgb(110 130 255 / 0.1);
|
|
185
|
+
--control-hover: rgb(110 130 255 / 0.2);
|
|
186
|
+
--border: rgb(110 130 255 / 0.22);
|
|
187
|
+
--text: #eaeefc;
|
|
188
|
+
--text-2: #aab3d6;
|
|
189
|
+
--text-muted: #7b85ad;
|
|
190
|
+
--grid: rgb(110 130 255 / 0.1);
|
|
191
|
+
--accent: #6f9bff;
|
|
192
|
+
--accent-strong: #4565f0;
|
|
193
|
+
--accent-soft: rgb(111 155 255 / 0.16);
|
|
194
|
+
--accent-glow: 0 0 22px rgb(80 110 255 / 0.55);
|
|
195
|
+
--accent-2: #22d3ee;
|
|
196
|
+
--heat: #ff8a3d;
|
|
197
|
+
--cat-1: #6f9bff;
|
|
198
|
+
--cat-2: #ff8a3d;
|
|
199
|
+
--cat-3: #2dd4a0;
|
|
200
|
+
--cat-4: #fbbf24;
|
|
201
|
+
--cat-5: #f472b6;
|
|
202
|
+
--cat-6: #a78bfa;
|
|
203
|
+
--cat-other: #5f6890;
|
|
204
|
+
--good: #34d98b;
|
|
205
|
+
--warn: #fbbf24;
|
|
206
|
+
--poor: #ff6b81;
|
|
207
|
+
--code-string: #34d9a0;
|
|
208
|
+
--code-keyword: #b49bff;
|
|
209
|
+
--code-number: #fbbf24;
|
|
210
|
+
}
|
|
211
|
+
:root[data-theme='space'][data-mode='light'] {
|
|
212
|
+
color-scheme: light;
|
|
213
|
+
--bg:
|
|
214
|
+
radial-gradient(1px 1px at 22px 34px, rgb(79 70 229 / 0.35), transparent),
|
|
215
|
+
radial-gradient(1px 1px at 120px 130px, rgb(14 116 144 / 0.3), transparent),
|
|
216
|
+
radial-gradient(
|
|
217
|
+
1.5px 1.5px at 170px 70px,
|
|
218
|
+
rgb(79 70 229 / 0.3),
|
|
219
|
+
transparent
|
|
220
|
+
),
|
|
221
|
+
radial-gradient(
|
|
222
|
+
900px 600px at 84% -12%,
|
|
223
|
+
rgb(129 140 248 / 0.32),
|
|
224
|
+
transparent 62%
|
|
225
|
+
),
|
|
226
|
+
radial-gradient(
|
|
227
|
+
800px 600px at -6% 108%,
|
|
228
|
+
rgb(34 211 238 / 0.2),
|
|
229
|
+
transparent 60%
|
|
230
|
+
),
|
|
231
|
+
#eef0fa;
|
|
232
|
+
--bg-size: 210px 210px, 210px 210px, 210px 210px, auto, auto, auto;
|
|
233
|
+
--panel: rgb(255 255 255 / 0.8);
|
|
234
|
+
--panel-solid: #f8f9ff;
|
|
235
|
+
--panel-border: rgb(79 70 229 / 0.2);
|
|
236
|
+
--panel-edge: inset 0 1px 0 rgb(255 255 255 / 0.9);
|
|
237
|
+
--shadow: 0 1px 2px rgb(30 27 100 / 0.06), 0 14px 40px rgb(30 27 100 / 0.12);
|
|
238
|
+
--shadow-pop:
|
|
239
|
+
0 0 0 1px rgb(79 70 229 / 0.15), 0 24px 60px rgb(30 27 100 / 0.24);
|
|
240
|
+
--surface: #f8f9ff;
|
|
241
|
+
--surface-2: rgb(79 70 229 / 0.05);
|
|
242
|
+
--control: rgb(255 255 255 / 0.9);
|
|
243
|
+
--control-hover: #fff;
|
|
244
|
+
--border: rgb(79 70 229 / 0.2);
|
|
245
|
+
--text: #0f1226;
|
|
246
|
+
--text-2: #424a6b;
|
|
247
|
+
--text-muted: #6a7192;
|
|
248
|
+
--grid: rgb(79 70 229 / 0.1);
|
|
249
|
+
--accent: #4338ca;
|
|
250
|
+
--accent-strong: #4f46e5;
|
|
251
|
+
--accent-soft: rgb(79 70 229 / 0.1);
|
|
252
|
+
--accent-glow: 0 6px 20px rgb(79 70 229 / 0.35);
|
|
253
|
+
--accent-2: #0e7490;
|
|
254
|
+
--heat: #e0560c;
|
|
255
|
+
--cat-1: #4f46e5;
|
|
256
|
+
--cat-2: #e0560c;
|
|
257
|
+
--cat-3: #0f9f78;
|
|
258
|
+
--cat-4: #d99100;
|
|
259
|
+
--cat-5: #d6458a;
|
|
260
|
+
--cat-6: #7c3aed;
|
|
261
|
+
--cat-other: #9aa0bd;
|
|
262
|
+
--good: #14803f;
|
|
263
|
+
--warn: #9a5200;
|
|
264
|
+
--poor: #c62839;
|
|
265
|
+
--code-string: #0f7a5a;
|
|
266
|
+
--code-keyword: #6d3fd6;
|
|
267
|
+
--code-number: #9a5200;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* ---- signature details ---- */
|
|
271
|
+
:root[data-theme='glass'] button.primary,
|
|
272
|
+
:root[data-theme='glass'] .tabs button[aria-selected='true'] {
|
|
273
|
+
background:
|
|
274
|
+
linear-gradient(180deg, rgb(255 255 255 / 0.28), transparent 55%),
|
|
275
|
+
var(--accent-strong);
|
|
276
|
+
}
|
|
277
|
+
:root[data-theme='space'] button.primary {
|
|
278
|
+
background: linear-gradient(135deg, var(--accent-strong), #8b5cf6);
|
|
279
|
+
border-color: transparent;
|
|
280
|
+
}
|
|
281
|
+
:root[data-theme='space'] .brand-mark {
|
|
282
|
+
background: conic-gradient(from 210deg, #22d3ee, #6f6bff, #c084fc, #22d3ee);
|
|
283
|
+
}
|
|
284
|
+
:root[data-theme='glass'] .brand-mark {
|
|
285
|
+
background: linear-gradient(135deg, #5ac8fa, #0a84ff 55%, #bf5af2);
|
|
286
|
+
}
|
package/vite.config.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import react from '@vitejs/plugin-react';
|
|
2
|
+
import { defineConfig } from 'vite';
|
|
3
|
+
import perfProfiler from './server/plugin.js';
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [react(), perfProfiler()],
|
|
7
|
+
server: { port: Number(process.env.PORT) || 5178, open: false },
|
|
8
|
+
});
|