@tailwind-styled/devtools 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.
package/dist/index.cjs ADDED
@@ -0,0 +1,986 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __defProps = Object.defineProperties;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
8
+ var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
13
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
+ var __spreadValues = (a, b) => {
15
+ for (var prop in b || (b = {}))
16
+ if (__hasOwnProp.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
18
+ if (__getOwnPropSymbols)
19
+ for (var prop of __getOwnPropSymbols(b)) {
20
+ if (__propIsEnum.call(b, prop))
21
+ __defNormalProp(a, prop, b[prop]);
22
+ }
23
+ return a;
24
+ };
25
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
26
+ var __export = (target, all) => {
27
+ for (var name in all)
28
+ __defProp(target, name, { get: all[name], enumerable: true });
29
+ };
30
+ var __copyProps = (to, from, except, desc) => {
31
+ if (from && typeof from === "object" || typeof from === "function") {
32
+ for (let key of __getOwnPropNames(from))
33
+ if (!__hasOwnProp.call(to, key) && key !== except)
34
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
35
+ }
36
+ return to;
37
+ };
38
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
39
+ // If the importer is in node compatibility mode or this is not an ESM
40
+ // file that has been converted to a CommonJS file using a Babel-
41
+ // compatible transform (i.e. "__esModule" has not been set), then set
42
+ // "default" to the CommonJS "module.exports" for node compatibility.
43
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
44
+ mod
45
+ ));
46
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
47
+
48
+ // src/index.tsx
49
+ var index_exports = {};
50
+ __export(index_exports, {
51
+ DevToolsProvider: () => DevToolsProvider,
52
+ TwDevTools: () => TwDevTools
53
+ });
54
+ module.exports = __toCommonJS(index_exports);
55
+ var import_react = __toESM(require("react"), 1);
56
+ function parseDataTw(dataTw) {
57
+ if (!dataTw) return { name: "Unknown", classes: [] };
58
+ const colonIdx = dataTw.indexOf(":");
59
+ if (colonIdx === -1) return { name: dataTw, classes: [] };
60
+ const name = dataTw.slice(0, colonIdx);
61
+ const classes = dataTw.slice(colonIdx + 1).split(/\s+/).filter(Boolean);
62
+ return { name, classes };
63
+ }
64
+ function parseVariantAttr(v) {
65
+ if (!v) return {};
66
+ try {
67
+ return JSON.parse(v);
68
+ } catch (e) {
69
+ return {};
70
+ }
71
+ }
72
+ function findNearestTwElement(el) {
73
+ var _a;
74
+ let cur = el;
75
+ while (cur) {
76
+ if ((_a = cur.dataset) == null ? void 0 : _a.tw) return cur;
77
+ cur = cur.parentElement;
78
+ }
79
+ return null;
80
+ }
81
+ function getAtomicMap(classes) {
82
+ const registry = window.__TW_REGISTRY__;
83
+ if (!registry) return {};
84
+ const map = {};
85
+ for (const cls of classes) {
86
+ if (registry[cls]) map[cls] = registry[cls];
87
+ }
88
+ return map;
89
+ }
90
+ function getActiveStates(el) {
91
+ const states = {};
92
+ for (const attr of el.attributes) {
93
+ if (attr.name.startsWith("data-")) {
94
+ states[attr.name.replace("data-", "")] = attr.value;
95
+ }
96
+ }
97
+ return states;
98
+ }
99
+ function getStateNames(el) {
100
+ const registry = window.__TW_STATE_REGISTRY__;
101
+ if (!registry) return [];
102
+ for (const [id, entry] of registry) {
103
+ if (el.classList.contains(id)) return entry.states;
104
+ }
105
+ return [];
106
+ }
107
+ function getContainerBps(el) {
108
+ const registry = window.__TW_CONTAINER_REGISTRY__;
109
+ if (!registry) return [];
110
+ for (const [id, entry] of registry) {
111
+ if (el.classList.contains(id)) {
112
+ return entry.breakpoints.map((bp) => bp.minWidth);
113
+ }
114
+ }
115
+ return [];
116
+ }
117
+ function InspectorPanel({
118
+ inspected,
119
+ position: _position,
120
+ pinned: _pinned
121
+ }) {
122
+ if (!inspected) {
123
+ return import_react.default.createElement(
124
+ "div",
125
+ { style: S.emptyPanel },
126
+ import_react.default.createElement("span", { style: { opacity: 0.4 } }, "Hover an element to inspect")
127
+ );
128
+ }
129
+ return import_react.default.createElement(
130
+ "div",
131
+ { style: S.scrollArea },
132
+ // Variant props
133
+ Object.keys(inspected.variantProps).length > 0 && import_react.default.createElement(
134
+ "div",
135
+ { style: S.section },
136
+ import_react.default.createElement("div", { style: S.sectionTitle }, "Variants"),
137
+ Object.entries(inspected.variantProps).map(
138
+ ([k, v]) => import_react.default.createElement(
139
+ "div",
140
+ { key: k, style: S.row },
141
+ import_react.default.createElement("span", { style: S.varKey }, k),
142
+ import_react.default.createElement("span", { style: S.varValue }, `"${v}"`)
143
+ )
144
+ )
145
+ ),
146
+ // Active states
147
+ Object.keys(inspected.activeStates).length > 0 && import_react.default.createElement(
148
+ "div",
149
+ { style: S.section },
150
+ import_react.default.createElement("div", { style: S.sectionTitle }, "Active Data Attrs"),
151
+ Object.entries(inspected.activeStates).map(
152
+ ([k, v]) => import_react.default.createElement(
153
+ "div",
154
+ { key: k, style: S.row },
155
+ import_react.default.createElement("code", { style: __spreadProps(__spreadValues({}, S.varKey), { color: "#f59e0b" }) }, `data-${k}`),
156
+ import_react.default.createElement("span", { style: __spreadProps(__spreadValues({}, S.varValue), { color: "#34d399" }) }, `"${v}"`)
157
+ )
158
+ )
159
+ ),
160
+ // State names
161
+ inspected.stateNames.length > 0 && import_react.default.createElement(
162
+ "div",
163
+ { style: S.section },
164
+ import_react.default.createElement("div", { style: S.sectionTitle }, "Reactive States"),
165
+ import_react.default.createElement(
166
+ "div",
167
+ { style: S.classGrid },
168
+ inspected.stateNames.map(
169
+ (s) => import_react.default.createElement(
170
+ "code",
171
+ {
172
+ key: s,
173
+ style: __spreadProps(__spreadValues({}, S.classChip), {
174
+ background: inspected.activeStates[s] === "true" ? "#065f46" : "#18181b",
175
+ borderColor: inspected.activeStates[s] === "true" ? "#34d399" : "#27272a"
176
+ })
177
+ },
178
+ s
179
+ )
180
+ )
181
+ )
182
+ ),
183
+ // Container breakpoints
184
+ inspected.containerBps.length > 0 && import_react.default.createElement(
185
+ "div",
186
+ { style: S.section },
187
+ import_react.default.createElement("div", { style: S.sectionTitle }, "Container Breakpoints"),
188
+ import_react.default.createElement(
189
+ "div",
190
+ { style: S.classGrid },
191
+ inspected.containerBps.map(
192
+ (bp) => import_react.default.createElement(
193
+ "code",
194
+ { key: bp, style: __spreadProps(__spreadValues({}, S.classChip), { color: "#818cf8" }) },
195
+ bp
196
+ )
197
+ )
198
+ )
199
+ ),
200
+ // Tailwind classes
201
+ inspected.twClasses.length > 0 && import_react.default.createElement(
202
+ "div",
203
+ { style: S.section },
204
+ import_react.default.createElement("div", { style: S.sectionTitle }, "Classes"),
205
+ import_react.default.createElement(
206
+ "div",
207
+ { style: S.classGrid },
208
+ inspected.twClasses.map(
209
+ (cls) => import_react.default.createElement(
210
+ "code",
211
+ { key: cls, style: S.classChip, title: inspected.atomicMap[cls] },
212
+ cls
213
+ )
214
+ )
215
+ )
216
+ ),
217
+ // Copy
218
+ import_react.default.createElement(
219
+ "button",
220
+ {
221
+ style: S.copyBtn,
222
+ onClick: () => {
223
+ var _a;
224
+ (_a = navigator.clipboard) == null ? void 0 : _a.writeText(
225
+ JSON.stringify(
226
+ {
227
+ component: inspected.componentName,
228
+ variants: inspected.variantProps,
229
+ states: inspected.activeStates,
230
+ classes: inspected.twClasses
231
+ },
232
+ null,
233
+ 2
234
+ )
235
+ );
236
+ }
237
+ },
238
+ "Copy to clipboard"
239
+ )
240
+ );
241
+ }
242
+ function StatePanel() {
243
+ const [entries, setEntries] = (0, import_react.useState)([]);
244
+ (0, import_react.useEffect)(() => {
245
+ const refresh = () => {
246
+ const reg = window.__TW_STATE_REGISTRY__;
247
+ setEntries(reg ? Array.from(reg.values()) : []);
248
+ };
249
+ refresh();
250
+ const interval = setInterval(refresh, 1e3);
251
+ return () => clearInterval(interval);
252
+ }, []);
253
+ if (entries.length === 0) {
254
+ return import_react.default.createElement(
255
+ "div",
256
+ { style: S.emptyPanel },
257
+ import_react.default.createElement(
258
+ "span",
259
+ { style: { opacity: 0.4 } },
260
+ "No state-enabled components found."
261
+ ),
262
+ import_react.default.createElement("br", null),
263
+ import_react.default.createElement(
264
+ "span",
265
+ { style: { opacity: 0.3, fontSize: "11px" } },
266
+ 'Use tw.button({ state: { active: "..." } }) to register.'
267
+ )
268
+ );
269
+ }
270
+ return import_react.default.createElement(
271
+ "div",
272
+ { style: S.scrollArea },
273
+ entries.map(
274
+ (entry) => import_react.default.createElement(
275
+ "div",
276
+ { key: entry.id, style: S.section },
277
+ import_react.default.createElement(
278
+ "div",
279
+ { style: S.sectionTitle },
280
+ import_react.default.createElement("span", { style: { color: "#60a5fa" } }, entry.tag.toUpperCase()),
281
+ import_react.default.createElement(
282
+ "span",
283
+ { style: { marginLeft: "8px", color: "#52525b", fontSize: "10px" } },
284
+ entry.id
285
+ )
286
+ ),
287
+ import_react.default.createElement(
288
+ "div",
289
+ { style: S.classGrid },
290
+ entry.states.map(
291
+ (s) => import_react.default.createElement(
292
+ "code",
293
+ { key: s, style: __spreadProps(__spreadValues({}, S.classChip), { color: "#f59e0b" }) },
294
+ `data-${s}`
295
+ )
296
+ )
297
+ ),
298
+ import_react.default.createElement(
299
+ "div",
300
+ { style: __spreadProps(__spreadValues({}, S.row), { marginTop: "4px" }) },
301
+ import_react.default.createElement(
302
+ "span",
303
+ {
304
+ style: __spreadProps(__spreadValues({}, S.sectionTitle), {
305
+ marginBottom: 0,
306
+ color: entry.cssInjected ? "#34d399" : "#ef4444"
307
+ })
308
+ },
309
+ entry.cssInjected ? "\u25CF CSS injected" : "\u25CB CSS pending"
310
+ )
311
+ )
312
+ )
313
+ )
314
+ );
315
+ }
316
+ function ContainerPanel() {
317
+ const [entries, setEntries] = (0, import_react.useState)([]);
318
+ (0, import_react.useEffect)(() => {
319
+ const refresh = () => {
320
+ const reg = window.__TW_CONTAINER_REGISTRY__;
321
+ setEntries(reg ? Array.from(reg.values()) : []);
322
+ };
323
+ refresh();
324
+ const interval = setInterval(refresh, 1e3);
325
+ return () => clearInterval(interval);
326
+ }, []);
327
+ if (entries.length === 0) {
328
+ return import_react.default.createElement(
329
+ "div",
330
+ { style: S.emptyPanel },
331
+ import_react.default.createElement(
332
+ "span",
333
+ { style: { opacity: 0.4 } },
334
+ "No container query components found."
335
+ ),
336
+ import_react.default.createElement("br", null),
337
+ import_react.default.createElement(
338
+ "span",
339
+ { style: { opacity: 0.3, fontSize: "11px" } },
340
+ 'Use tw.div({ container: { md: "flex-row" } }) to register.'
341
+ )
342
+ );
343
+ }
344
+ return import_react.default.createElement(
345
+ "div",
346
+ { style: S.scrollArea },
347
+ entries.map(
348
+ (entry) => import_react.default.createElement(
349
+ "div",
350
+ { key: entry.id, style: S.section },
351
+ import_react.default.createElement(
352
+ "div",
353
+ { style: S.sectionTitle },
354
+ import_react.default.createElement("span", { style: { color: "#60a5fa" } }, entry.tag.toUpperCase()),
355
+ entry.containerName && import_react.default.createElement(
356
+ "span",
357
+ { style: { marginLeft: "6px", color: "#818cf8" } },
358
+ `[${entry.containerName}]`
359
+ ),
360
+ import_react.default.createElement(
361
+ "span",
362
+ { style: { marginLeft: "8px", color: "#52525b", fontSize: "10px" } },
363
+ entry.id
364
+ )
365
+ ),
366
+ import_react.default.createElement(
367
+ "div",
368
+ null,
369
+ entry.breakpoints.map(
370
+ (bp, i) => import_react.default.createElement(
371
+ "div",
372
+ { key: i, style: __spreadProps(__spreadValues({}, S.row), { marginBottom: "2px" }) },
373
+ import_react.default.createElement(
374
+ "code",
375
+ { style: { color: "#818cf8", fontSize: "11px" } },
376
+ `\u2265 ${bp.minWidth}`
377
+ ),
378
+ import_react.default.createElement(
379
+ "span",
380
+ { style: { color: "#6b7280", fontSize: "11px" } },
381
+ bp.classes
382
+ )
383
+ )
384
+ )
385
+ )
386
+ )
387
+ )
388
+ );
389
+ }
390
+ function TokensPanel() {
391
+ const [tokens, setTokens_] = (0, import_react.useState)({});
392
+ (0, import_react.useEffect)(() => {
393
+ const engine = window.__TW_TOKEN_ENGINE__;
394
+ if (!engine) return;
395
+ setTokens_(engine.getTokens());
396
+ const unsub = engine.subscribe((t) => setTokens_(__spreadValues({}, t)));
397
+ return unsub;
398
+ }, []);
399
+ const entries = Object.entries(tokens);
400
+ if (entries.length === 0) {
401
+ return import_react.default.createElement(
402
+ "div",
403
+ { style: S.emptyPanel },
404
+ import_react.default.createElement("span", { style: { opacity: 0.4 } }, "No live tokens registered."),
405
+ import_react.default.createElement("br", null),
406
+ import_react.default.createElement(
407
+ "span",
408
+ { style: { opacity: 0.3, fontSize: "11px" } },
409
+ 'Use liveToken({ primary: "#3b82f6" }) to register tokens.'
410
+ )
411
+ );
412
+ }
413
+ return import_react.default.createElement(
414
+ "div",
415
+ { style: S.scrollArea },
416
+ import_react.default.createElement(
417
+ "div",
418
+ { style: __spreadProps(__spreadValues({}, S.sectionTitle), { padding: "8px 12px 4px", color: "#52525b" }) },
419
+ "Click color to edit \xB7 Changes apply instantly"
420
+ ),
421
+ entries.map(([name, value]) => {
422
+ const isColor = value.startsWith("#") || value.startsWith("rgb") || value.startsWith("hsl");
423
+ return import_react.default.createElement(
424
+ "div",
425
+ { key: name, style: __spreadProps(__spreadValues({}, S.row), { padding: "6px 12px", borderBottom: "1px solid #18181b" }) },
426
+ import_react.default.createElement(
427
+ "div",
428
+ { style: { display: "flex", alignItems: "center", gap: "8px" } },
429
+ isColor && import_react.default.createElement("div", {
430
+ style: {
431
+ width: "16px",
432
+ height: "16px",
433
+ borderRadius: "3px",
434
+ background: value,
435
+ border: "1px solid #27272a",
436
+ flexShrink: 0
437
+ }
438
+ }),
439
+ import_react.default.createElement("span", { style: { color: "#a1a1aa", fontSize: "12px" } }, name)
440
+ ),
441
+ isColor ? import_react.default.createElement("input", {
442
+ type: "color",
443
+ defaultValue: value.startsWith("#") ? value : "#000000",
444
+ style: {
445
+ width: "52px",
446
+ height: "22px",
447
+ border: "none",
448
+ background: "none",
449
+ cursor: "pointer"
450
+ },
451
+ onChange: (e) => {
452
+ const engine = window.__TW_TOKEN_ENGINE__;
453
+ if (engine) engine.setToken(name, e.target.value);
454
+ }
455
+ }) : import_react.default.createElement("input", {
456
+ type: "text",
457
+ defaultValue: value,
458
+ style: {
459
+ background: "#18181b",
460
+ border: "1px solid #27272a",
461
+ borderRadius: "3px",
462
+ color: "#e4e4e7",
463
+ fontSize: "11px",
464
+ padding: "2px 6px",
465
+ width: "100px",
466
+ fontFamily: "monospace"
467
+ },
468
+ onBlur: (e) => {
469
+ const engine = window.__TW_TOKEN_ENGINE__;
470
+ if (engine) engine.setToken(name, e.target.value);
471
+ }
472
+ })
473
+ );
474
+ })
475
+ );
476
+ }
477
+ function AnalyzerPanel() {
478
+ const [scanning, setScanning] = (0, import_react.useState)(false);
479
+ const [results, setResults] = (0, import_react.useState)(null);
480
+ const runScan = (0, import_react.useCallback)(() => {
481
+ setScanning(true);
482
+ setTimeout(() => {
483
+ var _a, _b, _c, _d;
484
+ const twEls = document.querySelectorAll("[data-tw]");
485
+ const classMap = /* @__PURE__ */ new Map();
486
+ for (const el of twEls) {
487
+ const { name, classes } = (() => {
488
+ var _a2;
489
+ const dTw = (_a2 = el.dataset.tw) != null ? _a2 : null;
490
+ if (!dTw) return { name: "?", classes: [] };
491
+ const ci = dTw.indexOf(":");
492
+ return {
493
+ name: ci >= 0 ? dTw.slice(0, ci) : dTw,
494
+ classes: ci >= 0 ? dTw.slice(ci + 1).split(/\s+/).filter(Boolean) : []
495
+ };
496
+ })();
497
+ const key = classes.sort().join(" ");
498
+ if (!classMap.has(key)) classMap.set(key, []);
499
+ classMap.get(key).push(name);
500
+ }
501
+ const duplicates = Array.from(classMap.entries()).filter(([, names]) => names.length > 1).map(([pattern, names]) => ({ pattern, count: names.length, names })).sort((a, b) => b.count - a.count).slice(0, 10);
502
+ const stateReg = window.__TW_STATE_REGISTRY__;
503
+ const containerReg = window.__TW_CONTAINER_REGISTRY__;
504
+ const tokenEngine = window.__TW_TOKEN_ENGINE__;
505
+ setResults({
506
+ duplicates,
507
+ stateCount: (_a = stateReg == null ? void 0 : stateReg.size) != null ? _a : 0,
508
+ containerCount: (_b = containerReg == null ? void 0 : containerReg.size) != null ? _b : 0,
509
+ tokenCount: Object.keys((_d = (_c = tokenEngine == null ? void 0 : tokenEngine.getTokens) == null ? void 0 : _c.call(tokenEngine)) != null ? _d : {}).length
510
+ });
511
+ setScanning(false);
512
+ }, 100);
513
+ }, []);
514
+ return import_react.default.createElement(
515
+ "div",
516
+ { style: S.scrollArea },
517
+ import_react.default.createElement(
518
+ "div",
519
+ { style: { padding: "10px 12px" } },
520
+ import_react.default.createElement(
521
+ "button",
522
+ {
523
+ style: __spreadProps(__spreadValues({}, S.copyBtn), { borderTop: "none", color: "#60a5fa", fontWeight: "600" }),
524
+ onClick: runScan,
525
+ disabled: scanning
526
+ },
527
+ scanning ? "Scanning DOM..." : "\u25B6 Run DOM Scan"
528
+ ),
529
+ results && import_react.default.createElement(
530
+ "div",
531
+ null,
532
+ // Summary
533
+ import_react.default.createElement(
534
+ "div",
535
+ { style: S.section },
536
+ import_react.default.createElement("div", { style: S.sectionTitle }, "Summary"),
537
+ import_react.default.createElement(
538
+ "div",
539
+ { style: S.row },
540
+ import_react.default.createElement("span", { style: S.varKey }, "State components"),
541
+ import_react.default.createElement("span", { style: S.varValue }, String(results.stateCount))
542
+ ),
543
+ import_react.default.createElement(
544
+ "div",
545
+ { style: S.row },
546
+ import_react.default.createElement("span", { style: S.varKey }, "Container components"),
547
+ import_react.default.createElement("span", { style: S.varValue }, String(results.containerCount))
548
+ ),
549
+ import_react.default.createElement(
550
+ "div",
551
+ { style: S.row },
552
+ import_react.default.createElement("span", { style: S.varKey }, "Live tokens"),
553
+ import_react.default.createElement("span", { style: S.varValue }, String(results.tokenCount))
554
+ )
555
+ ),
556
+ // Duplicates
557
+ results.duplicates.length > 0 ? import_react.default.createElement(
558
+ "div",
559
+ { style: S.section },
560
+ import_react.default.createElement("div", { style: S.sectionTitle }, "Duplicate Class Sets"),
561
+ results.duplicates.map(
562
+ (d, i) => import_react.default.createElement(
563
+ "div",
564
+ { key: i, style: { marginBottom: "8px" } },
565
+ import_react.default.createElement(
566
+ "div",
567
+ { style: { color: "#f59e0b", fontSize: "11px", marginBottom: "2px" } },
568
+ d.names.join(", ")
569
+ ),
570
+ import_react.default.createElement(
571
+ "code",
572
+ {
573
+ style: {
574
+ color: "#52525b",
575
+ fontSize: "10px",
576
+ wordBreak: "break-all"
577
+ }
578
+ },
579
+ d.pattern.split(" ").slice(0, 8).join(" ") + (d.pattern.split(" ").length > 8 ? "..." : "")
580
+ )
581
+ )
582
+ )
583
+ ) : results && import_react.default.createElement(
584
+ "div",
585
+ { style: S.section },
586
+ import_react.default.createElement(
587
+ "span",
588
+ { style: { color: "#34d399", fontSize: "12px" } },
589
+ "\u2713 No duplicate class sets in current DOM"
590
+ )
591
+ )
592
+ )
593
+ )
594
+ );
595
+ }
596
+ function TwDevTools() {
597
+ if (process.env.NODE_ENV === "production") return null;
598
+ const [state, setState] = (0, import_react.useState)({
599
+ open: false,
600
+ panel: "inspector",
601
+ pinned: false,
602
+ inspected: null,
603
+ position: { x: 0, y: 0 }
604
+ });
605
+ const overlayRef = (0, import_react.useRef)(null);
606
+ const isInspecting = state.open && state.panel === "inspector";
607
+ (0, import_react.useEffect)(() => {
608
+ const onKey = (e) => {
609
+ if (e.ctrlKey && e.shiftKey && e.key === "D") {
610
+ e.preventDefault();
611
+ setState((s) => __spreadProps(__spreadValues({}, s), { open: !s.open, inspected: null }));
612
+ }
613
+ if (e.key === "Escape")
614
+ setState((s) => __spreadProps(__spreadValues({}, s), { open: false, pinned: false, inspected: null }));
615
+ if (e.key === "1") setState((s) => s.open ? __spreadProps(__spreadValues({}, s), { panel: "inspector" }) : s);
616
+ if (e.key === "2") setState((s) => s.open ? __spreadProps(__spreadValues({}, s), { panel: "state" }) : s);
617
+ if (e.key === "3") setState((s) => s.open ? __spreadProps(__spreadValues({}, s), { panel: "container" }) : s);
618
+ if (e.key === "4") setState((s) => s.open ? __spreadProps(__spreadValues({}, s), { panel: "tokens" }) : s);
619
+ if (e.key === "5") setState((s) => s.open ? __spreadProps(__spreadValues({}, s), { panel: "analyzer" }) : s);
620
+ };
621
+ window.addEventListener("keydown", onKey);
622
+ return () => window.removeEventListener("keydown", onKey);
623
+ }, []);
624
+ const onMouseMove = (0, import_react.useCallback)(
625
+ (e) => {
626
+ var _a;
627
+ if (!isInspecting || state.pinned) return;
628
+ const twEl = findNearestTwElement(e.target);
629
+ if (!twEl) {
630
+ setState((s) => __spreadProps(__spreadValues({}, s), { inspected: null, position: { x: e.clientX, y: e.clientY } }));
631
+ return;
632
+ }
633
+ const { name, classes } = parseDataTw((_a = twEl.dataset.tw) != null ? _a : null);
634
+ setState((s) => {
635
+ var _a2;
636
+ return __spreadProps(__spreadValues({}, s), {
637
+ position: { x: e.clientX, y: e.clientY },
638
+ inspected: {
639
+ componentName: name,
640
+ element: twEl,
641
+ rect: twEl.getBoundingClientRect(),
642
+ twClasses: classes,
643
+ variantProps: parseVariantAttr((_a2 = twEl.dataset.twVariants) != null ? _a2 : null),
644
+ atomicMap: getAtomicMap(classes),
645
+ rawClassName: twEl.className,
646
+ stateNames: getStateNames(twEl),
647
+ activeStates: getActiveStates(twEl),
648
+ containerBps: getContainerBps(twEl)
649
+ }
650
+ });
651
+ });
652
+ },
653
+ [isInspecting, state.pinned]
654
+ );
655
+ const onClick = (0, import_react.useCallback)(
656
+ (e) => {
657
+ var _a;
658
+ if (!isInspecting) return;
659
+ if ((_a = overlayRef.current) == null ? void 0 : _a.contains(e.target)) return;
660
+ setState((s) => __spreadProps(__spreadValues({}, s), { pinned: !s.pinned && !!s.inspected }));
661
+ },
662
+ [isInspecting]
663
+ );
664
+ (0, import_react.useEffect)(() => {
665
+ if (!isInspecting) return;
666
+ window.addEventListener("mousemove", onMouseMove);
667
+ window.addEventListener("click", onClick);
668
+ return () => {
669
+ window.removeEventListener("mousemove", onMouseMove);
670
+ window.removeEventListener("click", onClick);
671
+ };
672
+ }, [isInspecting, onMouseMove, onClick]);
673
+ if (!state.open) {
674
+ return import_react.default.createElement(
675
+ "button",
676
+ {
677
+ onClick: () => setState((s) => __spreadProps(__spreadValues({}, s), { open: true })),
678
+ style: S.toggleBtn,
679
+ title: "tailwind-styled-v4 DevTools (Ctrl+Shift+D)"
680
+ },
681
+ "\u{1F3A8}"
682
+ );
683
+ }
684
+ const PANELS = [
685
+ { id: "inspector", label: "Inspector", icon: "\u{1F50D}" },
686
+ { id: "state", label: "State", icon: "\u26A1" },
687
+ { id: "container", label: "Container", icon: "\u{1F4E6}" },
688
+ { id: "tokens", label: "Tokens", icon: "\u{1F3A8}" },
689
+ { id: "analyzer", label: "Analyzer", icon: "\u{1F4CA}" }
690
+ ];
691
+ return import_react.default.createElement(
692
+ "div",
693
+ { style: S.root },
694
+ // ── Element highlight (inspector only) ──────────────────────────────
695
+ isInspecting && state.inspected && import_react.default.createElement("div", {
696
+ style: __spreadProps(__spreadValues({}, S.highlight), {
697
+ top: state.inspected.rect.top + window.scrollY,
698
+ left: state.inspected.rect.left + window.scrollX,
699
+ width: state.inspected.rect.width,
700
+ height: state.inspected.rect.height
701
+ })
702
+ }),
703
+ // ── Component name label ────────────────────────────────────────────
704
+ isInspecting && state.inspected && import_react.default.createElement(
705
+ "div",
706
+ {
707
+ style: {
708
+ position: "absolute",
709
+ top: state.inspected.rect.top + window.scrollY - 22,
710
+ left: state.inspected.rect.left + window.scrollX,
711
+ background: "#1e3a5f",
712
+ color: "#93c5fd",
713
+ fontSize: "11px",
714
+ padding: "2px 6px",
715
+ borderRadius: "3px 3px 0 0",
716
+ pointerEvents: "none",
717
+ zIndex: 2147483646,
718
+ fontFamily: "monospace"
719
+ }
720
+ },
721
+ state.inspected.componentName
722
+ ),
723
+ // ── Main DevTools panel ─────────────────────────────────────────────
724
+ import_react.default.createElement(
725
+ "div",
726
+ {
727
+ ref: overlayRef,
728
+ style: state.panel === "inspector" && state.inspected ? __spreadProps(__spreadValues({}, S.panel), {
729
+ top: Math.min(state.position.y + 16, window.innerHeight - 460),
730
+ left: Math.min(state.position.x + 16, window.innerWidth - 320)
731
+ }) : __spreadProps(__spreadValues({}, S.panel), {
732
+ top: "auto",
733
+ bottom: "40px",
734
+ right: "12px",
735
+ left: "auto"
736
+ })
737
+ },
738
+ // Header
739
+ import_react.default.createElement(
740
+ "div",
741
+ { style: S.header },
742
+ import_react.default.createElement(
743
+ "span",
744
+ { style: S.componentName },
745
+ state.inspected && state.panel === "inspector" ? state.inspected.componentName : "tailwind-styled-v4"
746
+ ),
747
+ import_react.default.createElement(
748
+ "div",
749
+ { style: S.headerActions },
750
+ state.pinned && import_react.default.createElement("span", { style: S.pinBadge }, "\u{1F4CC}"),
751
+ import_react.default.createElement(
752
+ "button",
753
+ {
754
+ style: S.closeBtn,
755
+ onClick: () => setState((s) => __spreadProps(__spreadValues({}, s), { open: false, pinned: false, inspected: null }))
756
+ },
757
+ "\u2715"
758
+ )
759
+ )
760
+ ),
761
+ // Tab bar
762
+ import_react.default.createElement(
763
+ "div",
764
+ { style: S.tabBar },
765
+ PANELS.map(
766
+ (p) => import_react.default.createElement(
767
+ "button",
768
+ {
769
+ key: p.id,
770
+ style: __spreadProps(__spreadValues({}, S.tab), {
771
+ background: state.panel === p.id ? "#18181b" : "none",
772
+ color: state.panel === p.id ? "#e4e4e7" : "#52525b",
773
+ borderBottom: state.panel === p.id ? "2px solid #3b82f6" : "2px solid transparent"
774
+ }),
775
+ onClick: () => setState((s) => __spreadProps(__spreadValues({}, s), { panel: p.id })),
776
+ title: `${p.label} (${PANELS.findIndex((x) => x.id === p.id) + 1})`
777
+ },
778
+ `${p.icon} ${p.label}`
779
+ )
780
+ )
781
+ ),
782
+ // Panel content
783
+ state.panel === "inspector" && import_react.default.createElement(InspectorPanel, {
784
+ inspected: state.inspected,
785
+ position: state.position,
786
+ pinned: state.pinned
787
+ }),
788
+ state.panel === "state" && import_react.default.createElement(StatePanel, null),
789
+ state.panel === "container" && import_react.default.createElement(ContainerPanel, null),
790
+ state.panel === "tokens" && import_react.default.createElement(TokensPanel, null),
791
+ state.panel === "analyzer" && import_react.default.createElement(AnalyzerPanel, null)
792
+ ),
793
+ // ── Status bar ──────────────────────────────────────────────────────
794
+ import_react.default.createElement(
795
+ "div",
796
+ { style: S.statusBar },
797
+ import_react.default.createElement("span", null, "\u{1F3A8} tailwind-styled-v4 DevTools"),
798
+ import_react.default.createElement(
799
+ "span",
800
+ { style: { opacity: 0.6, fontSize: "10px" } },
801
+ state.pinned ? "Click to unpin" : isInspecting ? "Hover to inspect \xB7 Click to pin \xB7 1-5 switch panel \xB7 Esc close" : "Ctrl+Shift+D close \xB7 1-5 switch panel"
802
+ )
803
+ )
804
+ );
805
+ }
806
+ var S = {
807
+ root: {
808
+ position: "fixed",
809
+ inset: 0,
810
+ zIndex: 2147483647,
811
+ pointerEvents: "none",
812
+ fontFamily: "ui-monospace, 'JetBrains Mono', monospace",
813
+ fontSize: "12px"
814
+ },
815
+ highlight: {
816
+ position: "absolute",
817
+ borderRadius: "3px",
818
+ outline: "2px solid #3b82f6",
819
+ outlineOffset: "1px",
820
+ background: "rgba(59,130,246,0.08)",
821
+ pointerEvents: "none",
822
+ transition: "all 0.1s ease",
823
+ zIndex: 2147483646
824
+ },
825
+ panel: {
826
+ position: "fixed",
827
+ width: 320,
828
+ maxHeight: 480,
829
+ background: "#0f0f0f",
830
+ border: "1px solid #27272a",
831
+ borderRadius: "10px",
832
+ boxShadow: "0 8px 32px rgba(0,0,0,0.8)",
833
+ pointerEvents: "all",
834
+ zIndex: 2147483647,
835
+ userSelect: "text",
836
+ display: "flex",
837
+ flexDirection: "column"
838
+ },
839
+ header: {
840
+ display: "flex",
841
+ alignItems: "center",
842
+ justifyContent: "space-between",
843
+ padding: "8px 12px 6px",
844
+ borderBottom: "1px solid #1f1f1f",
845
+ flexShrink: 0
846
+ },
847
+ tabBar: {
848
+ display: "flex",
849
+ borderBottom: "1px solid #18181b",
850
+ flexShrink: 0,
851
+ overflowX: "auto"
852
+ },
853
+ tab: {
854
+ background: "none",
855
+ border: "none",
856
+ cursor: "pointer",
857
+ fontSize: "10px",
858
+ padding: "5px 8px",
859
+ whiteSpace: "nowrap",
860
+ fontFamily: "inherit",
861
+ transition: "color 0.1s",
862
+ pointerEvents: "all"
863
+ },
864
+ scrollArea: {
865
+ overflowY: "auto",
866
+ flex: 1
867
+ },
868
+ emptyPanel: {
869
+ padding: "24px 12px",
870
+ color: "#71717a",
871
+ fontSize: "12px",
872
+ textAlign: "center",
873
+ lineHeight: 1.6
874
+ },
875
+ componentName: {
876
+ color: "#60a5fa",
877
+ fontWeight: "bold",
878
+ fontSize: "13px"
879
+ },
880
+ headerActions: {
881
+ display: "flex",
882
+ alignItems: "center",
883
+ gap: "6px"
884
+ },
885
+ pinBadge: { color: "#fbbf24", fontSize: "10px" },
886
+ closeBtn: {
887
+ background: "none",
888
+ border: "none",
889
+ color: "#71717a",
890
+ cursor: "pointer",
891
+ fontSize: "14px",
892
+ lineHeight: 1,
893
+ padding: "2px 4px",
894
+ pointerEvents: "all"
895
+ },
896
+ section: {
897
+ padding: "8px 12px",
898
+ borderBottom: "1px solid #18181b"
899
+ },
900
+ sectionTitle: {
901
+ color: "#52525b",
902
+ fontSize: "10px",
903
+ textTransform: "uppercase",
904
+ letterSpacing: "0.08em",
905
+ marginBottom: "6px"
906
+ },
907
+ row: {
908
+ display: "flex",
909
+ justifyContent: "space-between",
910
+ alignItems: "center",
911
+ marginBottom: "3px"
912
+ },
913
+ varKey: { color: "#a1a1aa" },
914
+ varValue: { color: "#34d399", fontWeight: "bold" },
915
+ classGrid: {
916
+ display: "flex",
917
+ flexWrap: "wrap",
918
+ gap: "4px"
919
+ },
920
+ classChip: {
921
+ background: "#18181b",
922
+ border: "1px solid #27272a",
923
+ borderRadius: "4px",
924
+ padding: "2px 6px",
925
+ color: "#e4e4e7",
926
+ cursor: "default",
927
+ fontSize: "11px"
928
+ },
929
+ copyBtn: {
930
+ display: "block",
931
+ width: "100%",
932
+ background: "none",
933
+ border: "none",
934
+ borderTop: "1px solid #18181b",
935
+ color: "#52525b",
936
+ cursor: "pointer",
937
+ padding: "8px 12px",
938
+ textAlign: "left",
939
+ fontSize: "11px",
940
+ pointerEvents: "all",
941
+ fontFamily: "inherit"
942
+ },
943
+ statusBar: {
944
+ position: "fixed",
945
+ bottom: 0,
946
+ left: 0,
947
+ right: 0,
948
+ background: "#1e3a5f",
949
+ color: "#93c5fd",
950
+ fontSize: "11px",
951
+ padding: "4px 12px",
952
+ display: "flex",
953
+ justifyContent: "space-between",
954
+ alignItems: "center",
955
+ pointerEvents: "all",
956
+ zIndex: 2147483647
957
+ },
958
+ toggleBtn: {
959
+ position: "fixed",
960
+ bottom: 12,
961
+ right: 12,
962
+ width: 36,
963
+ height: 36,
964
+ borderRadius: "50%",
965
+ background: "#1e3a5f",
966
+ border: "1px solid #3b82f6",
967
+ color: "white",
968
+ cursor: "pointer",
969
+ fontSize: "16px",
970
+ display: "flex",
971
+ alignItems: "center",
972
+ justifyContent: "center",
973
+ zIndex: 2147483647,
974
+ boxShadow: "0 2px 8px rgba(0,0,0,0.4)",
975
+ pointerEvents: "all"
976
+ }
977
+ };
978
+ function DevToolsProvider() {
979
+ if (process.env.NODE_ENV === "production") return null;
980
+ return import_react.default.createElement(TwDevTools);
981
+ }
982
+ // Annotate the CommonJS export names for ESM import in node:
983
+ 0 && (module.exports = {
984
+ DevToolsProvider,
985
+ TwDevTools
986
+ });