@designtools/next-plugin 0.1.2

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.
@@ -0,0 +1,403 @@
1
+ "use client";
2
+ import "./chunk-Y6FXYEAI.mjs";
3
+
4
+ // src/codecanvas.tsx
5
+ import { useEffect, useRef } from "react";
6
+ function CodeCanvas() {
7
+ const stateRef = useRef({
8
+ selectionMode: false,
9
+ hoveredElement: null,
10
+ selectedElement: null,
11
+ selectedDomPath: null,
12
+ overlayRafId: null,
13
+ inlineStyleBackups: /* @__PURE__ */ new Map(),
14
+ highlightOverlay: null,
15
+ tooltip: null,
16
+ selectedOverlay: null
17
+ });
18
+ useEffect(() => {
19
+ const s = stateRef.current;
20
+ s.highlightOverlay = document.createElement("div");
21
+ s.highlightOverlay.id = "tool-highlight";
22
+ Object.assign(s.highlightOverlay.style, {
23
+ position: "fixed",
24
+ pointerEvents: "none",
25
+ border: "2px solid #3b82f6",
26
+ backgroundColor: "rgba(59, 130, 246, 0.08)",
27
+ borderRadius: "2px",
28
+ zIndex: "99999",
29
+ display: "none",
30
+ transition: "all 0.1s ease"
31
+ });
32
+ document.body.appendChild(s.highlightOverlay);
33
+ s.tooltip = document.createElement("div");
34
+ s.tooltip.id = "tool-tooltip";
35
+ Object.assign(s.tooltip.style, {
36
+ position: "fixed",
37
+ pointerEvents: "none",
38
+ backgroundColor: "#1e1e2e",
39
+ color: "#cdd6f4",
40
+ padding: "3px 8px",
41
+ borderRadius: "4px",
42
+ fontSize: "11px",
43
+ fontFamily: "ui-monospace, monospace",
44
+ zIndex: "100000",
45
+ display: "none",
46
+ whiteSpace: "nowrap",
47
+ boxShadow: "0 2px 8px rgba(0,0,0,0.3)"
48
+ });
49
+ document.body.appendChild(s.tooltip);
50
+ s.selectedOverlay = document.createElement("div");
51
+ s.selectedOverlay.id = "tool-selected";
52
+ Object.assign(s.selectedOverlay.style, {
53
+ position: "fixed",
54
+ pointerEvents: "none",
55
+ border: "2px solid #f59e0b",
56
+ backgroundColor: "rgba(245, 158, 11, 0.06)",
57
+ borderRadius: "2px",
58
+ zIndex: "99998",
59
+ display: "none"
60
+ });
61
+ document.body.appendChild(s.selectedOverlay);
62
+ function getElementName(el) {
63
+ const slot = el.getAttribute("data-slot");
64
+ if (slot) return slot.charAt(0).toUpperCase() + slot.slice(1);
65
+ return `<${el.tagName.toLowerCase()}>`;
66
+ }
67
+ function getDomPath(el) {
68
+ const parts = [];
69
+ let current = el;
70
+ while (current && current !== document.body) {
71
+ const parent = current.parentElement;
72
+ if (parent) {
73
+ const idx = Array.from(parent.children).indexOf(current) + 1;
74
+ parts.unshift(`${current.tagName.toLowerCase()}:nth-child(${idx})`);
75
+ } else {
76
+ parts.unshift(current.tagName.toLowerCase());
77
+ }
78
+ current = current.parentElement;
79
+ }
80
+ return parts.join(" > ");
81
+ }
82
+ function positionOverlay(overlay, rect) {
83
+ Object.assign(overlay.style, {
84
+ left: `${rect.left}px`,
85
+ top: `${rect.top}px`,
86
+ width: `${rect.width}px`,
87
+ height: `${rect.height}px`,
88
+ display: "block"
89
+ });
90
+ }
91
+ function findSelectableElement(target) {
92
+ let el = target;
93
+ while (el && el !== document.body) {
94
+ if (el.getAttribute("data-slot")) return el;
95
+ el = el.parentElement;
96
+ }
97
+ return target;
98
+ }
99
+ const relevantProps = [
100
+ "display",
101
+ "position",
102
+ "top",
103
+ "right",
104
+ "bottom",
105
+ "left",
106
+ "z-index",
107
+ "overflow",
108
+ "overflow-x",
109
+ "overflow-y",
110
+ "flex-direction",
111
+ "flex-wrap",
112
+ "justify-content",
113
+ "align-items",
114
+ "align-self",
115
+ "flex-grow",
116
+ "flex-shrink",
117
+ "flex-basis",
118
+ "order",
119
+ "grid-template-columns",
120
+ "grid-template-rows",
121
+ "gap",
122
+ "row-gap",
123
+ "column-gap",
124
+ "width",
125
+ "height",
126
+ "min-width",
127
+ "min-height",
128
+ "max-width",
129
+ "max-height",
130
+ "margin-top",
131
+ "margin-right",
132
+ "margin-bottom",
133
+ "margin-left",
134
+ "padding-top",
135
+ "padding-right",
136
+ "padding-bottom",
137
+ "padding-left",
138
+ "font-family",
139
+ "font-size",
140
+ "font-weight",
141
+ "line-height",
142
+ "letter-spacing",
143
+ "text-align",
144
+ "text-decoration",
145
+ "text-transform",
146
+ "color",
147
+ "white-space",
148
+ "background-color",
149
+ "background-image",
150
+ "background-size",
151
+ "background-position",
152
+ "border-top-width",
153
+ "border-right-width",
154
+ "border-bottom-width",
155
+ "border-left-width",
156
+ "border-style",
157
+ "border-color",
158
+ "border-top-left-radius",
159
+ "border-top-right-radius",
160
+ "border-bottom-right-radius",
161
+ "border-bottom-left-radius",
162
+ "opacity",
163
+ "box-shadow",
164
+ "transform",
165
+ "transition"
166
+ ];
167
+ const inheritableProps = [
168
+ "color",
169
+ "font-family",
170
+ "font-size",
171
+ "font-weight",
172
+ "line-height",
173
+ "letter-spacing",
174
+ "text-align",
175
+ "text-transform",
176
+ "white-space"
177
+ ];
178
+ function extractElementData(el) {
179
+ const computed = getComputedStyle(el);
180
+ const rect = el.getBoundingClientRect();
181
+ const computedStyles = {};
182
+ for (const prop of relevantProps) {
183
+ computedStyles[prop] = computed.getPropertyValue(prop);
184
+ }
185
+ const parentComputedStyles = {};
186
+ const parentEl = el.parentElement;
187
+ if (parentEl) {
188
+ const parentComputed = getComputedStyle(parentEl);
189
+ for (const prop of inheritableProps) {
190
+ parentComputedStyles[prop] = parentComputed.getPropertyValue(prop);
191
+ }
192
+ }
193
+ const attributes = {};
194
+ for (const attr of Array.from(el.attributes)) {
195
+ if (attr.name.startsWith("data-")) {
196
+ attributes[attr.name] = attr.value;
197
+ }
198
+ }
199
+ let sourceFile = null;
200
+ let sourceLine = null;
201
+ let sourceCol = null;
202
+ const dataSource = el.getAttribute("data-source");
203
+ if (dataSource) {
204
+ const lastColon = dataSource.lastIndexOf(":");
205
+ const secondLastColon = dataSource.lastIndexOf(":", lastColon - 1);
206
+ if (secondLastColon > 0) {
207
+ sourceFile = dataSource.slice(0, secondLastColon);
208
+ sourceLine = parseInt(dataSource.slice(secondLastColon + 1, lastColon), 10);
209
+ sourceCol = parseInt(dataSource.slice(lastColon + 1), 10);
210
+ }
211
+ }
212
+ let instanceSourceFile = null;
213
+ let instanceSourceLine = null;
214
+ let instanceSourceCol = null;
215
+ let componentName = null;
216
+ const instanceSource = el.getAttribute("data-instance-source");
217
+ if (instanceSource && el.getAttribute("data-slot")) {
218
+ const lc = instanceSource.lastIndexOf(":");
219
+ const slc = instanceSource.lastIndexOf(":", lc - 1);
220
+ if (slc > 0) {
221
+ instanceSourceFile = instanceSource.slice(0, slc);
222
+ instanceSourceLine = parseInt(instanceSource.slice(slc + 1, lc), 10);
223
+ instanceSourceCol = parseInt(instanceSource.slice(lc + 1), 10);
224
+ }
225
+ const slot = el.getAttribute("data-slot") || "";
226
+ componentName = slot.split("-").map((s2) => s2.charAt(0).toUpperCase() + s2.slice(1)).join("");
227
+ }
228
+ return {
229
+ tag: el.tagName.toLowerCase(),
230
+ className: (el.getAttribute("class") || "").trim(),
231
+ computedStyles,
232
+ parentComputedStyles,
233
+ boundingRect: rect,
234
+ domPath: getDomPath(el),
235
+ textContent: (el.textContent || "").trim().slice(0, 100),
236
+ attributes,
237
+ sourceFile,
238
+ sourceLine,
239
+ sourceCol,
240
+ instanceSourceFile,
241
+ instanceSourceLine,
242
+ instanceSourceCol,
243
+ componentName
244
+ };
245
+ }
246
+ function selectElement(el) {
247
+ s.selectedElement = el;
248
+ s.selectedDomPath = getDomPath(el);
249
+ const data = extractElementData(el);
250
+ if (s.selectedOverlay) {
251
+ positionOverlay(s.selectedOverlay, data.boundingRect);
252
+ }
253
+ startOverlayTracking();
254
+ window.parent.postMessage({ type: "tool:elementSelected", data }, "*");
255
+ }
256
+ function reselectCurrentElement() {
257
+ if (!s.selectedDomPath) return;
258
+ const el = document.querySelector(s.selectedDomPath);
259
+ if (el) {
260
+ s.selectedElement = el;
261
+ const data = extractElementData(el);
262
+ if (s.selectedOverlay) {
263
+ positionOverlay(s.selectedOverlay, data.boundingRect);
264
+ }
265
+ window.parent.postMessage({ type: "tool:elementSelected", data }, "*");
266
+ }
267
+ }
268
+ function startOverlayTracking() {
269
+ if (s.overlayRafId) cancelAnimationFrame(s.overlayRafId);
270
+ let lastRect = "";
271
+ function tick() {
272
+ if (s.selectedElement && s.selectedOverlay) {
273
+ if (!document.contains(s.selectedElement)) {
274
+ if (s.selectedDomPath) {
275
+ const newEl = document.querySelector(s.selectedDomPath);
276
+ if (newEl) {
277
+ s.selectedElement = newEl;
278
+ reselectCurrentElement();
279
+ }
280
+ }
281
+ }
282
+ if (s.selectedElement && document.contains(s.selectedElement)) {
283
+ const rect = s.selectedElement.getBoundingClientRect();
284
+ const key = `${rect.left},${rect.top},${rect.width},${rect.height}`;
285
+ if (key !== lastRect) {
286
+ lastRect = key;
287
+ positionOverlay(s.selectedOverlay, rect);
288
+ }
289
+ }
290
+ }
291
+ s.overlayRafId = requestAnimationFrame(tick);
292
+ }
293
+ tick();
294
+ }
295
+ function onMouseMove(e) {
296
+ if (!s.selectionMode || !s.highlightOverlay || !s.tooltip) return;
297
+ const el = document.elementFromPoint(e.clientX, e.clientY);
298
+ if (!el || el === s.highlightOverlay || el === s.tooltip || el === s.selectedOverlay) return;
299
+ const selectable = findSelectableElement(el);
300
+ if (selectable === s.hoveredElement) return;
301
+ s.hoveredElement = selectable;
302
+ const rect = selectable.getBoundingClientRect();
303
+ positionOverlay(s.highlightOverlay, rect);
304
+ const name = getElementName(selectable);
305
+ s.tooltip.textContent = name;
306
+ s.tooltip.style.display = "block";
307
+ s.tooltip.style.left = `${rect.left}px`;
308
+ s.tooltip.style.top = `${Math.max(0, rect.top - 24)}px`;
309
+ }
310
+ function onMouseLeave() {
311
+ if (!s.highlightOverlay || !s.tooltip) return;
312
+ s.highlightOverlay.style.display = "none";
313
+ s.tooltip.style.display = "none";
314
+ s.hoveredElement = null;
315
+ }
316
+ function onClick(e) {
317
+ if (!s.selectionMode) return;
318
+ e.preventDefault();
319
+ e.stopPropagation();
320
+ const el = document.elementFromPoint(e.clientX, e.clientY);
321
+ if (!el || el === s.highlightOverlay || el === s.tooltip || el === s.selectedOverlay) return;
322
+ const selectable = findSelectableElement(el);
323
+ selectElement(selectable);
324
+ }
325
+ function onMessage(e) {
326
+ const msg = e.data;
327
+ if (!msg || !msg.type || !msg.type.startsWith("tool:")) return;
328
+ switch (msg.type) {
329
+ case "tool:enterSelectionMode":
330
+ s.selectionMode = true;
331
+ document.body.style.cursor = "crosshair";
332
+ break;
333
+ case "tool:exitSelectionMode":
334
+ s.selectionMode = false;
335
+ document.body.style.cursor = "";
336
+ if (s.highlightOverlay) s.highlightOverlay.style.display = "none";
337
+ if (s.tooltip) s.tooltip.style.display = "none";
338
+ s.hoveredElement = null;
339
+ break;
340
+ case "tool:previewInlineStyle": {
341
+ if (s.selectedElement && s.selectedElement instanceof HTMLElement) {
342
+ const prop = msg.property;
343
+ const value = msg.value;
344
+ if (!s.inlineStyleBackups.has(prop)) {
345
+ s.inlineStyleBackups.set(prop, s.selectedElement.style.getPropertyValue(prop));
346
+ }
347
+ s.selectedElement.style.setProperty(prop, value, "important");
348
+ }
349
+ break;
350
+ }
351
+ case "tool:revertInlineStyles": {
352
+ if (s.selectedElement && s.selectedElement instanceof HTMLElement) {
353
+ for (const [prop, original] of s.inlineStyleBackups) {
354
+ if (original) {
355
+ s.selectedElement.style.setProperty(prop, original);
356
+ } else {
357
+ s.selectedElement.style.removeProperty(prop);
358
+ }
359
+ }
360
+ s.inlineStyleBackups.clear();
361
+ }
362
+ break;
363
+ }
364
+ case "tool:reselectElement":
365
+ reselectCurrentElement();
366
+ break;
367
+ case "tool:setTheme":
368
+ if (msg.theme === "dark") {
369
+ document.documentElement.classList.add("dark");
370
+ } else {
371
+ document.documentElement.classList.remove("dark");
372
+ }
373
+ break;
374
+ }
375
+ }
376
+ function notifyPathChanged() {
377
+ const fullPath = window.location.pathname + window.location.search + window.location.hash;
378
+ window.parent.postMessage({ type: "tool:pathChanged", path: fullPath }, "*");
379
+ }
380
+ document.addEventListener("mousemove", onMouseMove, true);
381
+ document.addEventListener("mouseleave", onMouseLeave);
382
+ document.addEventListener("click", onClick, true);
383
+ window.addEventListener("message", onMessage);
384
+ window.addEventListener("popstate", notifyPathChanged);
385
+ window.parent.postMessage({ type: "tool:injectedReady" }, "*");
386
+ notifyPathChanged();
387
+ return () => {
388
+ document.removeEventListener("mousemove", onMouseMove, true);
389
+ document.removeEventListener("mouseleave", onMouseLeave);
390
+ document.removeEventListener("click", onClick, true);
391
+ window.removeEventListener("message", onMessage);
392
+ window.removeEventListener("popstate", notifyPathChanged);
393
+ if (s.overlayRafId) cancelAnimationFrame(s.overlayRafId);
394
+ s.highlightOverlay?.remove();
395
+ s.tooltip?.remove();
396
+ s.selectedOverlay?.remove();
397
+ };
398
+ }, []);
399
+ return null;
400
+ }
401
+ export {
402
+ CodeCanvas
403
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Webpack loader that auto-mounts <CodeSurface /> in the root layout.
3
+ * Only runs in development. Injects the import and component into the JSX.
4
+ *
5
+ * Strategy: Simple string injection — find the {children} pattern in the layout
6
+ * and add <CodeSurface /> alongside it.
7
+ */
8
+ interface LoaderContext {
9
+ resourcePath: string;
10
+ callback(err: Error | null, content?: string): void;
11
+ async(): (err: Error | null, content?: string) => void;
12
+ }
13
+ declare function codesurfaceMountLoader(this: LoaderContext, source: string): void;
14
+
15
+ export { codesurfaceMountLoader as default };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Webpack loader that auto-mounts <CodeSurface /> in the root layout.
3
+ * Only runs in development. Injects the import and component into the JSX.
4
+ *
5
+ * Strategy: Simple string injection — find the {children} pattern in the layout
6
+ * and add <CodeSurface /> alongside it.
7
+ */
8
+ interface LoaderContext {
9
+ resourcePath: string;
10
+ callback(err: Error | null, content?: string): void;
11
+ async(): (err: Error | null, content?: string) => void;
12
+ }
13
+ declare function codesurfaceMountLoader(this: LoaderContext, source: string): void;
14
+
15
+ export { codesurfaceMountLoader as default };
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/codesurface-mount-loader.ts
21
+ var codesurface_mount_loader_exports = {};
22
+ __export(codesurface_mount_loader_exports, {
23
+ default: () => codesurfaceMountLoader
24
+ });
25
+ module.exports = __toCommonJS(codesurface_mount_loader_exports);
26
+ function codesurfaceMountLoader(source) {
27
+ const callback = this.async();
28
+ if (!source.includes("<html")) {
29
+ callback(null, source);
30
+ return;
31
+ }
32
+ if (source.includes("CodeSurface")) {
33
+ callback(null, source);
34
+ return;
35
+ }
36
+ const importStatement = `import { CodeSurface } from "@designtools/next-plugin/codesurface";
37
+ `;
38
+ let modified = source;
39
+ const firstImportIndex = source.indexOf("import ");
40
+ if (firstImportIndex !== -1) {
41
+ modified = source.slice(0, firstImportIndex) + importStatement + source.slice(firstImportIndex);
42
+ } else {
43
+ modified = importStatement + source;
44
+ }
45
+ modified = modified.replace(
46
+ /(\{children\})/,
47
+ `<CodeSurface />
48
+ $1`
49
+ );
50
+ callback(null, modified);
51
+ }
@@ -0,0 +1,32 @@
1
+ import "./chunk-Y6FXYEAI.mjs";
2
+
3
+ // src/codesurface-mount-loader.ts
4
+ function codesurfaceMountLoader(source) {
5
+ const callback = this.async();
6
+ if (!source.includes("<html")) {
7
+ callback(null, source);
8
+ return;
9
+ }
10
+ if (source.includes("CodeSurface")) {
11
+ callback(null, source);
12
+ return;
13
+ }
14
+ const importStatement = `import { CodeSurface } from "@designtools/next-plugin/codesurface";
15
+ `;
16
+ let modified = source;
17
+ const firstImportIndex = source.indexOf("import ");
18
+ if (firstImportIndex !== -1) {
19
+ modified = source.slice(0, firstImportIndex) + importStatement + source.slice(firstImportIndex);
20
+ } else {
21
+ modified = importStatement + source;
22
+ }
23
+ modified = modified.replace(
24
+ /(\{children\})/,
25
+ `<CodeSurface />
26
+ $1`
27
+ );
28
+ callback(null, modified);
29
+ }
30
+ export {
31
+ codesurfaceMountLoader as default
32
+ };
@@ -0,0 +1,3 @@
1
+ declare function CodeSurface(): null;
2
+
3
+ export { CodeSurface };
@@ -0,0 +1,3 @@
1
+ declare function CodeSurface(): null;
2
+
3
+ export { CodeSurface };