@bitovi/vybit 0.5.0 → 0.7.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/overlay/dist/overlay.js +805 -670
- package/package.json +1 -1
- package/panel/dist/assets/{DesignMode-BAyjCFC8.js → DesignMode-nOHHHxgv.js} +2 -2
- package/panel/dist/assets/index-BYIDlGa3.js +53 -0
- package/panel/dist/assets/index-BqcsQk03.css +1 -0
- package/panel/dist/index.html +4 -4
- package/server/tailwind-v3.ts +476 -146
- package/server/tailwind-v4.ts +228 -115
- package/shared/types.ts +29 -1
- package/panel/dist/assets/index-DVWn5Mcj.js +0 -49
- package/panel/dist/assets/index-_AiRfYt4.css +0 -1
package/server/tailwind-v4.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
// Tailwind v4 adapter — uses compile() / build() from the target project's tailwindcss v4.
|
|
2
2
|
|
|
3
3
|
import { readFileSync } from "fs";
|
|
4
|
-
import { resolve, dirname } from "path";
|
|
5
4
|
import { createRequire } from "module";
|
|
6
|
-
import
|
|
5
|
+
import { dirname, resolve } from "path";
|
|
6
|
+
import { pathToFileURL } from "url";
|
|
7
|
+
import type {
|
|
8
|
+
TailwindAdapter,
|
|
9
|
+
TailwindThemeSubset,
|
|
10
|
+
} from "./tailwind-adapter.js";
|
|
7
11
|
|
|
8
12
|
// Cached compiler instance (from target project's tailwindcss)
|
|
9
13
|
let compilerCache: { build: (classes: string[]) => string } | null = null;
|
|
@@ -11,17 +15,19 @@ let compilerCache: { build: (classes: string[]) => string } | null = null;
|
|
|
11
15
|
/**
|
|
12
16
|
* Get a Tailwind v4 compile() function from the target project's node_modules.
|
|
13
17
|
*/
|
|
14
|
-
async function getCompile(): Promise<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
async function getCompile(): Promise<
|
|
19
|
+
(css: string, opts: any) => Promise<{ build: (classes: string[]) => string }>
|
|
20
|
+
> {
|
|
21
|
+
const cwd = process.cwd();
|
|
22
|
+
const req = createRequire(resolve(cwd, "package.json"));
|
|
23
|
+
const tw = await import(pathToFileURL(req.resolve("tailwindcss")).href);
|
|
24
|
+
// Handle CJS/ESM interop: compile may be on tw directly or on tw.default
|
|
25
|
+
const mod = tw.default ?? tw;
|
|
26
|
+
const compile = mod.compile ?? mod.default?.compile;
|
|
27
|
+
if (typeof compile !== "function") {
|
|
28
|
+
throw new Error("Could not find compile() in target project's tailwindcss");
|
|
29
|
+
}
|
|
30
|
+
return compile;
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
/**
|
|
@@ -29,132 +35,239 @@ async function getCompile(): Promise<(css: string, opts: any) => Promise<{ build
|
|
|
29
35
|
* Resolves @import "tailwindcss" and other stylesheet imports from the target project.
|
|
30
36
|
*/
|
|
31
37
|
function makeLoadStylesheet(cwd: string) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
const req = createRequire(resolve(cwd, "package.json"));
|
|
39
|
+
return async (id: string, base: string) => {
|
|
40
|
+
let resolved: string;
|
|
41
|
+
if (id === "tailwindcss") {
|
|
42
|
+
resolved = req.resolve("tailwindcss/index.css");
|
|
43
|
+
} else {
|
|
44
|
+
resolved = req.resolve(id, { paths: [base || cwd] });
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
content: readFileSync(resolved, "utf8"),
|
|
48
|
+
base: dirname(resolved),
|
|
49
|
+
};
|
|
50
|
+
};
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
/**
|
|
48
54
|
* Initialize the Tailwind v4 compiler for the target project.
|
|
49
55
|
*/
|
|
50
|
-
async function getCompiler(): Promise<{
|
|
51
|
-
|
|
56
|
+
async function getCompiler(): Promise<{
|
|
57
|
+
build: (classes: string[]) => string;
|
|
58
|
+
}> {
|
|
59
|
+
if (compilerCache) return compilerCache;
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
const cwd = process.cwd();
|
|
62
|
+
const compile = await getCompile();
|
|
55
63
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
const result = await compile('@import "tailwindcss";', {
|
|
65
|
+
loadStylesheet: makeLoadStylesheet(cwd),
|
|
66
|
+
});
|
|
59
67
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
compilerCache = result;
|
|
69
|
+
console.error(
|
|
70
|
+
"[tailwind] Initialized Tailwind v4 compiler from target project",
|
|
71
|
+
);
|
|
72
|
+
return result;
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
// Classes we probe to extract theme values
|
|
66
76
|
const HUES = [
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
"slate",
|
|
78
|
+
"gray",
|
|
79
|
+
"zinc",
|
|
80
|
+
"neutral",
|
|
81
|
+
"stone",
|
|
82
|
+
"red",
|
|
83
|
+
"orange",
|
|
84
|
+
"amber",
|
|
85
|
+
"yellow",
|
|
86
|
+
"lime",
|
|
87
|
+
"green",
|
|
88
|
+
"emerald",
|
|
89
|
+
"teal",
|
|
90
|
+
"cyan",
|
|
91
|
+
"sky",
|
|
92
|
+
"blue",
|
|
93
|
+
"indigo",
|
|
94
|
+
"violet",
|
|
95
|
+
"purple",
|
|
96
|
+
"fuchsia",
|
|
97
|
+
"pink",
|
|
98
|
+
"rose",
|
|
99
|
+
];
|
|
100
|
+
const SHADES = [
|
|
101
|
+
"50",
|
|
102
|
+
"100",
|
|
103
|
+
"200",
|
|
104
|
+
"300",
|
|
105
|
+
"400",
|
|
106
|
+
"500",
|
|
107
|
+
"600",
|
|
108
|
+
"700",
|
|
109
|
+
"800",
|
|
110
|
+
"900",
|
|
111
|
+
"950",
|
|
72
112
|
];
|
|
73
|
-
const SHADES = ["50", "100", "200", "300", "400", "500", "600", "700", "800", "900", "950"];
|
|
74
113
|
const SPECIAL_COLORS = ["black", "white", "transparent"];
|
|
75
114
|
|
|
76
115
|
const SPACING_KEYS = [
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
116
|
+
"0",
|
|
117
|
+
"px",
|
|
118
|
+
"0.5",
|
|
119
|
+
"1",
|
|
120
|
+
"1.5",
|
|
121
|
+
"2",
|
|
122
|
+
"2.5",
|
|
123
|
+
"3",
|
|
124
|
+
"3.5",
|
|
125
|
+
"4",
|
|
126
|
+
"5",
|
|
127
|
+
"6",
|
|
128
|
+
"7",
|
|
129
|
+
"8",
|
|
130
|
+
"9",
|
|
131
|
+
"10",
|
|
132
|
+
"11",
|
|
133
|
+
"12",
|
|
134
|
+
"14",
|
|
135
|
+
"16",
|
|
136
|
+
"20",
|
|
137
|
+
"24",
|
|
138
|
+
"28",
|
|
139
|
+
"32",
|
|
140
|
+
"36",
|
|
141
|
+
"40",
|
|
142
|
+
"44",
|
|
143
|
+
"48",
|
|
144
|
+
"52",
|
|
145
|
+
"56",
|
|
146
|
+
"60",
|
|
147
|
+
"64",
|
|
148
|
+
"72",
|
|
149
|
+
"80",
|
|
150
|
+
"96",
|
|
80
151
|
];
|
|
81
152
|
|
|
82
|
-
const FONT_SIZE_KEYS = [
|
|
83
|
-
|
|
84
|
-
|
|
153
|
+
const FONT_SIZE_KEYS = [
|
|
154
|
+
"xs",
|
|
155
|
+
"sm",
|
|
156
|
+
"base",
|
|
157
|
+
"lg",
|
|
158
|
+
"xl",
|
|
159
|
+
"2xl",
|
|
160
|
+
"3xl",
|
|
161
|
+
"4xl",
|
|
162
|
+
"5xl",
|
|
163
|
+
"6xl",
|
|
164
|
+
"7xl",
|
|
165
|
+
"8xl",
|
|
166
|
+
"9xl",
|
|
167
|
+
];
|
|
168
|
+
const FONT_WEIGHT_KEYS = [
|
|
169
|
+
"thin",
|
|
170
|
+
"extralight",
|
|
171
|
+
"light",
|
|
172
|
+
"normal",
|
|
173
|
+
"medium",
|
|
174
|
+
"semibold",
|
|
175
|
+
"bold",
|
|
176
|
+
"extrabold",
|
|
177
|
+
"black",
|
|
178
|
+
];
|
|
179
|
+
const BORDER_RADIUS_KEYS = [
|
|
180
|
+
"none",
|
|
181
|
+
"sm",
|
|
182
|
+
"",
|
|
183
|
+
"md",
|
|
184
|
+
"lg",
|
|
185
|
+
"xl",
|
|
186
|
+
"2xl",
|
|
187
|
+
"3xl",
|
|
188
|
+
"full",
|
|
189
|
+
];
|
|
85
190
|
|
|
86
191
|
/**
|
|
87
192
|
* Extract --var definitions from compiled CSS output.
|
|
88
193
|
*/
|
|
89
194
|
function extractVars(css: string, prefix: string): Map<string, string> {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
195
|
+
const vars = new Map<string, string>();
|
|
196
|
+
const regex = new RegExp(`^\\s*--${prefix}-([\\w.-]+):\\s*([^;]+);`, "gm");
|
|
197
|
+
let match;
|
|
198
|
+
while ((match = regex.exec(css)) !== null) {
|
|
199
|
+
vars.set(match[1], match[2].trim());
|
|
200
|
+
}
|
|
201
|
+
return vars;
|
|
97
202
|
}
|
|
98
203
|
|
|
99
204
|
export class TailwindV4Adapter implements TailwindAdapter {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
205
|
+
readonly version = 4 as const;
|
|
206
|
+
|
|
207
|
+
async resolveTailwindConfig(): Promise<TailwindThemeSubset> {
|
|
208
|
+
const compiler = await getCompiler();
|
|
209
|
+
|
|
210
|
+
// Probe color classes to extract theme variable definitions
|
|
211
|
+
const probeClasses: string[] = [];
|
|
212
|
+
for (const h of HUES) {
|
|
213
|
+
for (const s of SHADES) probeClasses.push(`bg-${h}-${s}`);
|
|
214
|
+
}
|
|
215
|
+
for (const s of SPECIAL_COLORS) probeClasses.push(`bg-${s}`);
|
|
216
|
+
|
|
217
|
+
const css = compiler.build(probeClasses);
|
|
218
|
+
|
|
219
|
+
// --- Colors (extracted from CSS custom properties) ---
|
|
220
|
+
const colorVars = extractVars(css, "color");
|
|
221
|
+
const colors: Record<string, unknown> = {};
|
|
222
|
+
for (const [name, value] of colorVars) {
|
|
223
|
+
const dashIdx = name.lastIndexOf("-");
|
|
224
|
+
if (dashIdx > 0) {
|
|
225
|
+
const hue = name.substring(0, dashIdx);
|
|
226
|
+
const shade = name.substring(dashIdx + 1);
|
|
227
|
+
if (/^\d+$/.test(shade)) {
|
|
228
|
+
if (!colors[hue]) colors[hue] = {};
|
|
229
|
+
(colors[hue] as Record<string, string>)[shade] = value;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
colors[name] = value;
|
|
234
|
+
}
|
|
235
|
+
if (!colors["transparent"]) colors["transparent"] = "transparent";
|
|
236
|
+
|
|
237
|
+
// --- Spacing (v4 uses calc(var(--spacing) * N)) ---
|
|
238
|
+
const spacing: Record<string, string> = {};
|
|
239
|
+
for (const k of SPACING_KEYS) {
|
|
240
|
+
spacing[k] =
|
|
241
|
+
k === "px" ? "1px" : k === "0" ? "0px" : `calc(var(--spacing) * ${k})`;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// --- Font size, weight, border radius (static scales in v4) ---
|
|
245
|
+
const fontSize: Record<string, unknown> = {};
|
|
246
|
+
for (const k of FONT_SIZE_KEYS) fontSize[k] = k;
|
|
247
|
+
|
|
248
|
+
const fontWeight: Record<string, unknown> = {};
|
|
249
|
+
for (const k of FONT_WEIGHT_KEYS) fontWeight[k] = k;
|
|
250
|
+
|
|
251
|
+
const borderRadius: Record<string, string> = {};
|
|
252
|
+
for (const k of BORDER_RADIUS_KEYS)
|
|
253
|
+
borderRadius[k || "DEFAULT"] = k || "DEFAULT";
|
|
254
|
+
|
|
255
|
+
const result: TailwindThemeSubset = {
|
|
256
|
+
spacing,
|
|
257
|
+
colors,
|
|
258
|
+
fontSize,
|
|
259
|
+
fontWeight,
|
|
260
|
+
borderRadius,
|
|
261
|
+
};
|
|
262
|
+
console.error("[tailwind] v4 resolved theme:", {
|
|
263
|
+
colors: Object.keys(colors).length + " entries",
|
|
264
|
+
spacing: Object.keys(spacing).length + " entries",
|
|
265
|
+
});
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async generateCssForClasses(classes: string[]): Promise<string> {
|
|
270
|
+
const compiler = await getCompiler();
|
|
271
|
+
return compiler.build(classes);
|
|
272
|
+
}
|
|
160
273
|
}
|
package/shared/types.ts
CHANGED
|
@@ -114,12 +114,32 @@ export interface PatchPreviewMessage {
|
|
|
114
114
|
newClass: string;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/** Panel → Overlay: live-preview multiple class swaps atomically */
|
|
118
|
+
export interface PatchPreviewBatchMessage {
|
|
119
|
+
type: 'PATCH_PREVIEW_BATCH';
|
|
120
|
+
to: 'overlay';
|
|
121
|
+
pairs: Array<{ oldClass: string; newClass: string }>;
|
|
122
|
+
}
|
|
123
|
+
|
|
117
124
|
/** Panel → Overlay: revert any active preview */
|
|
118
125
|
export interface PatchRevertMessage {
|
|
119
126
|
type: 'PATCH_REVERT';
|
|
120
127
|
to: 'overlay';
|
|
121
128
|
}
|
|
122
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Panel → Overlay: undo a previously staged class change.
|
|
132
|
+
* Applies oldClass → newClass to the DOM and commits it as the new baseline,
|
|
133
|
+
* WITHOUT sending anything to the server.
|
|
134
|
+
* Use when the user stages back to the original value, removing a draft patch.
|
|
135
|
+
*/
|
|
136
|
+
export interface PatchRevertStagedMessage {
|
|
137
|
+
type: 'PATCH_REVERT_STAGED';
|
|
138
|
+
to: 'overlay';
|
|
139
|
+
oldClass: string; // currently in the DOM (the staged newClass)
|
|
140
|
+
newClass: string; // what to restore to (the original class)
|
|
141
|
+
}
|
|
142
|
+
|
|
123
143
|
/** Panel → Overlay: stage a change (overlay fills context, sends PATCH_STAGED to server) */
|
|
124
144
|
export interface PatchStageMessage {
|
|
125
145
|
type: 'PATCH_STAGE';
|
|
@@ -257,6 +277,11 @@ export interface DesignCloseMessage {
|
|
|
257
277
|
type: 'DESIGN_CLOSE';
|
|
258
278
|
}
|
|
259
279
|
|
|
280
|
+
/** Panel → Overlay: close the inspector panel */
|
|
281
|
+
export interface ClosePanelMessage {
|
|
282
|
+
type: 'CLOSE_PANEL';
|
|
283
|
+
}
|
|
284
|
+
|
|
260
285
|
// ---------------------------------------------------------------------------
|
|
261
286
|
// Union types
|
|
262
287
|
// ---------------------------------------------------------------------------
|
|
@@ -264,12 +289,14 @@ export interface DesignCloseMessage {
|
|
|
264
289
|
export type OverlayToPanel = ElementSelectedMessage;
|
|
265
290
|
export type PanelToOverlay =
|
|
266
291
|
| PatchPreviewMessage
|
|
292
|
+
| PatchPreviewBatchMessage
|
|
267
293
|
| PatchRevertMessage
|
|
268
294
|
| PatchStageMessage
|
|
269
295
|
| ClearHighlightsMessage
|
|
270
296
|
| SwitchContainerMessage
|
|
271
297
|
| InsertDesignCanvasMessage
|
|
272
|
-
| CaptureScreenshotMessage
|
|
298
|
+
| CaptureScreenshotMessage
|
|
299
|
+
| ClosePanelMessage;
|
|
273
300
|
export type OverlayToServer = PatchStagedMessage;
|
|
274
301
|
export type PanelToServer = PatchCommitMessage | MessageStageMessage;
|
|
275
302
|
export type ClientToServer =
|
|
@@ -308,5 +335,6 @@ export type AnyMessage =
|
|
|
308
335
|
| ElementContextMessage
|
|
309
336
|
| DesignSubmitMessage
|
|
310
337
|
| DesignCloseMessage
|
|
338
|
+
| ClosePanelMessage
|
|
311
339
|
| PingMessage
|
|
312
340
|
| PongMessage;
|