@epoch32/visage 1.1.3 → 1.1.5

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.
Files changed (52) hide show
  1. package/dist/api/index.js +55 -4085
  2. package/dist/charts/index.js +48 -2806
  3. package/dist/devtools/index.js +18 -4771
  4. package/dist/dom/index.js +32 -1639
  5. package/dist/form/index.js +13 -1498
  6. package/dist/index-061jf06a.js +848 -0
  7. package/dist/index-0madxn60.js +442 -0
  8. package/dist/index-1xtrtz1t.js +256 -0
  9. package/dist/index-2zz0g2n2.js +212 -0
  10. package/dist/index-5s255b3w.js +303 -0
  11. package/dist/index-6kfe1nr4.js +1179 -0
  12. package/dist/index-8czhpea8.js +338 -0
  13. package/dist/index-8x8xz80v.js +727 -0
  14. package/dist/index-921pn75b.js +0 -0
  15. package/dist/index-965ryh36.js +537 -0
  16. package/dist/index-9fvarkrx.js +98 -0
  17. package/dist/index-a4xns6cc.js +219 -0
  18. package/dist/index-b5wc752a.js +1696 -0
  19. package/dist/index-df5e614s.js +334 -0
  20. package/dist/index-dyvgtp43.js +1094 -0
  21. package/dist/index-grhdtcb5.js +234 -0
  22. package/dist/index-h6tjqk6e.js +158 -0
  23. package/dist/index-js199er4.js +101 -0
  24. package/dist/index-x2rs3vab.js +124 -0
  25. package/dist/index-y9bq7h9g.js +1162 -0
  26. package/dist/index-zr6cvset.js +2092 -0
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +458 -11920
  29. package/dist/jsx-runtime/index.js +13 -1719
  30. package/dist/query/index.js +47 -2505
  31. package/dist/router/index.js +25 -1945
  32. package/dist/rpc/index.js +39 -3567
  33. package/dist/server/index.js +11 -1256
  34. package/dist/signals/index.js +52 -1160
  35. package/dist/style/index.js +77 -2429
  36. package/dist/template/index.js +7 -1232
  37. package/dist/ui/index.d.ts +1 -1
  38. package/dist/ui/index.js +150 -4249
  39. package/dist/ui/tabs.d.ts +23 -1
  40. package/dist/virtual/index.js +12 -2044
  41. package/dist/vite/index.js +27 -746
  42. package/package.json +2 -2
  43. package/src/dom/render.ts +20 -7
  44. package/src/index.ts +2 -0
  45. package/src/signals/computed.ts +19 -12
  46. package/src/signals/effect.ts +7 -7
  47. package/src/signals/signal.ts +16 -12
  48. package/src/signals/system.ts +50 -21
  49. package/src/ui/index.ts +2 -0
  50. package/src/ui/tabs.tsx +211 -10
  51. package/src/ui/utils.ts +1 -3
  52. package/src/vite/lucide.ts +22 -2
@@ -0,0 +1,2092 @@
1
+ import {
2
+ onCleanup2,
3
+ effect2,
4
+ signal2,
5
+ createSignal2
6
+ } from "./index-6kfe1nr4.js";
7
+ import {
8
+ Show2,
9
+ For2
10
+ } from "./index-5s255b3w.js";
11
+ import {
12
+ jsx2,
13
+ jsxs2
14
+ } from "./index-9fvarkrx.js";
15
+ import {
16
+ Tabs2,
17
+ Tooltip3,
18
+ Switch2
19
+ } from "./index-8x8xz80v.js";
20
+ import {
21
+ Style2
22
+ } from "./index-0madxn60.js";
23
+
24
+ // src/devtools/hub.ts
25
+ class DevToolsHub2 {
26
+ isOpen = signal2(false, { internal: true });
27
+ activeTab = signal2("signals", { internal: true });
28
+ highlightDOM = signal2(false, { internal: true });
29
+ searchQuery = signal2("", { internal: true });
30
+ _signalsMap = new Map;
31
+ signalsList = signal2([], { internal: true });
32
+ _queriesMap = new Map;
33
+ queriesList = signal2([], { internal: true });
34
+ rpcLogs = signal2([], { internal: true });
35
+ _queryClients = new Set;
36
+ _signalCounter = 0;
37
+ constructor() {
38
+ if (typeof window !== "undefined") {
39
+ window.__VISAGE_DEVTOOLS__ = this;
40
+ }
41
+ }
42
+ toggle() {
43
+ this.isOpen.update((v) => !v);
44
+ }
45
+ setTab(tab) {
46
+ this.activeTab.set(tab);
47
+ }
48
+ registerSignal(options) {
49
+ const id = options.id ?? `sig_${++this._signalCounter}`;
50
+ const name = options.name ?? id;
51
+ const type = options.type ?? "signal";
52
+ const record = {
53
+ id,
54
+ name,
55
+ type,
56
+ getValue: options.getValue,
57
+ version: options.version,
58
+ dependencies: options.dependencies,
59
+ dependents: options.dependents,
60
+ subscribersCount: options.subscribersCount,
61
+ lastUpdatedAt: Date.now()
62
+ };
63
+ this._signalsMap.set(id, record);
64
+ this.refreshSignals();
65
+ return id;
66
+ }
67
+ unregisterSignal(id) {
68
+ if (this._signalsMap.delete(id)) {
69
+ this.refreshSignals();
70
+ }
71
+ }
72
+ clearSignals() {
73
+ this._signalsMap.clear();
74
+ this._signalCounter = 0;
75
+ this.refreshSignals();
76
+ }
77
+ clearQueries() {
78
+ this._queriesMap.clear();
79
+ this.queriesList.set([]);
80
+ }
81
+ clearAll() {
82
+ this.clearSignals();
83
+ this.clearQueries();
84
+ this.clearLogs();
85
+ }
86
+ refreshSignals() {
87
+ this.signalsList.set(Array.from(this._signalsMap.values()));
88
+ }
89
+ attachQueryClient(client) {
90
+ if (this._queryClients.has(client))
91
+ return;
92
+ this._queryClients.add(client);
93
+ const syncQueries = () => {
94
+ const cache = client.getQueryCache();
95
+ const allQueries = cache.getAll();
96
+ const records = allQueries.map((q) => ({
97
+ hash: q.queryHash,
98
+ key: q.queryKey,
99
+ status: () => q.status(),
100
+ fetchStatus: () => q.fetchStatus(),
101
+ data: () => q.data(),
102
+ error: () => q.error(),
103
+ dataUpdatedAt: () => q.dataUpdatedAt(),
104
+ refetch: () => q.fetch(),
105
+ invalidate: () => q.invalidate()
106
+ }));
107
+ this._queriesMap.clear();
108
+ for (const r of records) {
109
+ this._queriesMap.set(r.hash, r);
110
+ }
111
+ this.queriesList.set(records);
112
+ };
113
+ client.getQueryCache().subscribe(() => {
114
+ syncQueries();
115
+ });
116
+ syncQueries();
117
+ }
118
+ logRpcCall(record) {
119
+ const fullRecord = {
120
+ ...record,
121
+ status: record.status ?? "pending",
122
+ startTime: Date.now(),
123
+ events: []
124
+ };
125
+ this.rpcLogs.update((prev) => [fullRecord, ...prev.slice(0, 99)]);
126
+ return fullRecord.id;
127
+ }
128
+ updateRpcCall(id, updates) {
129
+ this.rpcLogs.update((prev) => prev.map((item) => {
130
+ if (item.id === id) {
131
+ const duration = updates.duration ?? (updates.status ? Date.now() - item.startTime : item.duration);
132
+ return { ...item, ...updates, duration };
133
+ }
134
+ return item;
135
+ }));
136
+ }
137
+ logRpcEvent(id, data) {
138
+ this.rpcLogs.update((prev) => prev.map((item) => {
139
+ if (item.id === id) {
140
+ const events = item.events ? [...item.events, { timestamp: Date.now(), data }] : [{ timestamp: Date.now(), data }];
141
+ return { ...item, events, status: "streaming" };
142
+ }
143
+ return item;
144
+ }));
145
+ }
146
+ clearLogs() {
147
+ this.rpcLogs.set([]);
148
+ }
149
+ }
150
+ var devtoolsHub2 = new DevToolsHub2;
151
+
152
+ // src/devtools/DomTab.tsx
153
+ function DomTab(props) {
154
+ return /* @__PURE__ */ jsx2("div", {
155
+ style: { flex: 1, padding: "24px", overflowY: "auto", background: "#090d16" },
156
+ children: /* @__PURE__ */ jsxs2("div", {
157
+ style: { maxWidth: "700px", margin: "0 auto" },
158
+ children: [
159
+ /* @__PURE__ */ jsxs2("div", {
160
+ style: {
161
+ display: "flex",
162
+ alignItems: "center",
163
+ justifyContent: "space-between",
164
+ marginBottom: "20px"
165
+ },
166
+ children: [
167
+ /* @__PURE__ */ jsxs2("div", {
168
+ children: [
169
+ /* @__PURE__ */ jsx2("h3", {
170
+ style: { margin: "0 0 6px 0", color: "#f8fafc", fontSize: "16px", fontWeight: 700 },
171
+ children: "Real-Time DOM Mutation Highlighter"
172
+ }),
173
+ /* @__PURE__ */ jsx2("p", {
174
+ style: { margin: 0, color: "#94a3b8", fontSize: "13px", lineHeight: 1.5 },
175
+ children: "Visage uses zero Virtual DOM and fine-grained reactivity. Only exact text nodes and attributes update in-place."
176
+ })
177
+ ]
178
+ }),
179
+ /* @__PURE__ */ jsxs2("div", {
180
+ style: { display: "flex", alignItems: "center", gap: "10px" },
181
+ children: [
182
+ /* @__PURE__ */ jsx2("span", {
183
+ style: {
184
+ fontSize: "11px",
185
+ fontWeight: 700,
186
+ letterSpacing: "0.04em",
187
+ color: () => props.hub.highlightDOM() ? "#10b981" : "#64748b"
188
+ },
189
+ children: () => props.hub.highlightDOM() ? "ENABLED" : "DISABLED"
190
+ }),
191
+ /* @__PURE__ */ jsx2(Switch2, {
192
+ checked: props.hub.highlightDOM,
193
+ onCheckedChange: (val) => props.hub.highlightDOM.set(val)
194
+ })
195
+ ]
196
+ })
197
+ ]
198
+ }),
199
+ /* @__PURE__ */ jsxs2("div", {
200
+ style: {
201
+ background: "#0c111d",
202
+ border: "1px solid #1e293b",
203
+ borderRadius: "8px",
204
+ padding: "16px",
205
+ marginBottom: "20px"
206
+ },
207
+ children: [
208
+ /* @__PURE__ */ jsx2("h4", {
209
+ style: { margin: "0 0 10px 0", color: "#38bdf8", fontSize: "13px", fontWeight: 600 },
210
+ children: "Usage Instructions:"
211
+ }),
212
+ /* @__PURE__ */ jsxs2("ul", {
213
+ style: {
214
+ margin: 0,
215
+ paddingLeft: "20px",
216
+ color: "#cbd5e1",
217
+ fontSize: "13px",
218
+ lineHeight: 1.6
219
+ },
220
+ children: [
221
+ /* @__PURE__ */ jsx2("li", {
222
+ children: "Toggle the switch above to enable visual flashing outlines across your app."
223
+ }),
224
+ /* @__PURE__ */ jsx2("li", {
225
+ children: "Interact with buttons, form inputs, tabs, and modals in your application."
226
+ }),
227
+ /* @__PURE__ */ jsxs2("li", {
228
+ children: [
229
+ "Notice that ",
230
+ /* @__PURE__ */ jsx2("strong", {
231
+ children: "only the exact updated node flashes"
232
+ }),
233
+ " without re-rendering the whole component or tree."
234
+ ]
235
+ })
236
+ ]
237
+ })
238
+ ]
239
+ }),
240
+ /* @__PURE__ */ jsxs2("div", {
241
+ style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "12px" },
242
+ children: [
243
+ /* @__PURE__ */ jsxs2("div", {
244
+ style: {
245
+ background: "#0c111d",
246
+ border: "1px solid #1e293b",
247
+ borderRadius: "8px",
248
+ padding: "14px"
249
+ },
250
+ children: [
251
+ /* @__PURE__ */ jsx2("div", {
252
+ style: {
253
+ fontWeight: 700,
254
+ color: "#f87171",
255
+ marginBottom: "6px",
256
+ fontSize: "12px",
257
+ textTransform: "uppercase",
258
+ letterSpacing: "0.04em"
259
+ },
260
+ children: "Virtual DOM Model"
261
+ }),
262
+ /* @__PURE__ */ jsx2("p", {
263
+ style: { margin: 0, color: "#94a3b8", fontSize: "12px", lineHeight: 1.5 },
264
+ children: "State changes re-run entire component functions, allocate temporary Virtual DOM nodes, and diff tree structures."
265
+ })
266
+ ]
267
+ }),
268
+ /* @__PURE__ */ jsxs2("div", {
269
+ style: {
270
+ background: "#0c111d",
271
+ border: "1px solid #1e293b",
272
+ borderRadius: "8px",
273
+ padding: "14px"
274
+ },
275
+ children: [
276
+ /* @__PURE__ */ jsx2("div", {
277
+ style: {
278
+ fontWeight: 700,
279
+ color: "#34d399",
280
+ marginBottom: "6px",
281
+ fontSize: "12px",
282
+ textTransform: "uppercase",
283
+ letterSpacing: "0.04em"
284
+ },
285
+ children: "Visage Reactive Engine"
286
+ }),
287
+ /* @__PURE__ */ jsx2("p", {
288
+ style: { margin: 0, color: "#94a3b8", fontSize: "12px", lineHeight: 1.5 },
289
+ children: "Component functions execute once during mounting. Signals push direct in-place mutations at native DOM speed."
290
+ })
291
+ ]
292
+ })
293
+ ]
294
+ })
295
+ ]
296
+ })
297
+ });
298
+ }
299
+
300
+ // src/devtools/GraphInspector.tsx
301
+ function GraphInspector(props) {
302
+ return /* @__PURE__ */ jsx2("div", {
303
+ style: {
304
+ width: "320px",
305
+ borderLeft: "1px solid #1e293b",
306
+ background: "#090d16",
307
+ padding: "16px",
308
+ overflowY: "auto"
309
+ },
310
+ children: /* @__PURE__ */ jsx2(Show2, {
311
+ when: props.selectedNode,
312
+ fallback: /* @__PURE__ */ jsxs2("div", {
313
+ style: {
314
+ color: "#64748b",
315
+ textAlign: "center",
316
+ marginTop: "30px",
317
+ fontSize: "12px",
318
+ lineHeight: 1.6
319
+ },
320
+ children: [
321
+ /* @__PURE__ */ jsx2("p", {
322
+ children: "Select any DAG node to inspect live dependencies, downstream subscribers, and reactive version history."
323
+ }),
324
+ /* @__PURE__ */ jsxs2("div", {
325
+ style: {
326
+ marginTop: "16px",
327
+ padding: "12px",
328
+ background: "#0f172a",
329
+ borderRadius: "6px",
330
+ textAlign: "left"
331
+ },
332
+ children: [
333
+ /* @__PURE__ */ jsx2("div", {
334
+ style: { color: "#94a3b8", fontWeight: 600, marginBottom: "4px", fontSize: "11px" },
335
+ children: "Legend:"
336
+ }),
337
+ /* @__PURE__ */ jsx2("div", {
338
+ style: { color: "#38bdf8", fontSize: "11px" },
339
+ children: "[SIG] Upstream Source Signals"
340
+ }),
341
+ /* @__PURE__ */ jsx2("div", {
342
+ style: { color: "#c084fc", fontSize: "11px" },
343
+ children: "[CMP] Derived Computeds"
344
+ })
345
+ ]
346
+ })
347
+ ]
348
+ }),
349
+ children: (node) => {
350
+ const deps = () => props.getDependencies(node());
351
+ const targets = () => props.getDependents(node());
352
+ return /* @__PURE__ */ jsxs2("div", {
353
+ children: [
354
+ /* @__PURE__ */ jsxs2("div", {
355
+ style: {
356
+ display: "flex",
357
+ justifyContent: "space-between",
358
+ alignItems: "flex-start",
359
+ marginBottom: "12px"
360
+ },
361
+ children: [
362
+ /* @__PURE__ */ jsxs2("div", {
363
+ children: [
364
+ /* @__PURE__ */ jsx2("h4", {
365
+ style: { margin: "0 0 2px 0", color: "#f1f5f9", fontSize: "15px" },
366
+ children: () => node().name
367
+ }),
368
+ /* @__PURE__ */ jsxs2("span", {
369
+ style: { fontSize: "11px", color: "#64748b" },
370
+ children: [
371
+ "ID: ",
372
+ () => node().id
373
+ ]
374
+ })
375
+ ]
376
+ }),
377
+ /* @__PURE__ */ jsx2("button", {
378
+ type: "button",
379
+ class: "visage-devtools-btn",
380
+ onClick: () => props.selectedId.set(null),
381
+ title: "Clear Selection",
382
+ children: "Clear"
383
+ })
384
+ ]
385
+ }),
386
+ /* @__PURE__ */ jsxs2("div", {
387
+ style: { display: "flex", gap: "6px", marginBottom: "16px" },
388
+ children: [
389
+ /* @__PURE__ */ jsx2("span", {
390
+ class: "visage-devtools-badge",
391
+ style: {
392
+ background: () => node().type === "computed" ? "#581c87" : "#0369a1",
393
+ color: "#fff"
394
+ },
395
+ children: () => node().type.toUpperCase()
396
+ }),
397
+ /* @__PURE__ */ jsxs2("span", {
398
+ class: "visage-devtools-badge",
399
+ children: [
400
+ "VERSION: ",
401
+ () => node().version()
402
+ ]
403
+ })
404
+ ]
405
+ }),
406
+ /* @__PURE__ */ jsx2("div", {
407
+ style: { fontSize: "12px", color: "#94a3b8", marginBottom: "6px" },
408
+ children: "Live Value:"
409
+ }),
410
+ /* @__PURE__ */ jsx2("pre", {
411
+ class: "visage-devtools-json",
412
+ style: { marginBottom: "16px" },
413
+ children: () => props.formatJSON(node().getValue())
414
+ }),
415
+ /* @__PURE__ */ jsxs2("div", {
416
+ style: { marginBottom: "16px" },
417
+ children: [
418
+ /* @__PURE__ */ jsxs2("div", {
419
+ style: {
420
+ fontSize: "11px",
421
+ fontWeight: 700,
422
+ textTransform: "uppercase",
423
+ color: "#38bdf8",
424
+ marginBottom: "6px"
425
+ },
426
+ children: [
427
+ "Upstream Inputs (",
428
+ () => deps().length,
429
+ ")"
430
+ ]
431
+ }),
432
+ () => deps().length > 0 ? /* @__PURE__ */ jsx2("div", {
433
+ style: { display: "flex", flexDirection: "column", gap: "6px" },
434
+ children: deps().map((d) => /* @__PURE__ */ jsxs2("div", {
435
+ class: "visage-graph-pill source",
436
+ style: {
437
+ width: "100%",
438
+ justifyContent: "space-between",
439
+ padding: "6px 8px"
440
+ },
441
+ onClick: () => props.selectedId.set(d.id),
442
+ children: [
443
+ /* @__PURE__ */ jsx2("span", {
444
+ children: d.name
445
+ }),
446
+ /* @__PURE__ */ jsxs2("span", {
447
+ style: { color: "#94a3b8" },
448
+ children: [
449
+ "v",
450
+ d.version()
451
+ ]
452
+ })
453
+ ]
454
+ }))
455
+ }) : /* @__PURE__ */ jsx2("div", {
456
+ style: { fontSize: "11px", color: "#64748b" },
457
+ children: "None (Root Reactive Source)"
458
+ })
459
+ ]
460
+ }),
461
+ /* @__PURE__ */ jsxs2("div", {
462
+ children: [
463
+ /* @__PURE__ */ jsxs2("div", {
464
+ style: {
465
+ fontSize: "11px",
466
+ fontWeight: 700,
467
+ textTransform: "uppercase",
468
+ color: "#c084fc",
469
+ marginBottom: "6px"
470
+ },
471
+ children: [
472
+ "Downstream Consumers (",
473
+ () => targets().length,
474
+ ")"
475
+ ]
476
+ }),
477
+ () => targets().length > 0 ? /* @__PURE__ */ jsx2("div", {
478
+ style: { display: "flex", flexDirection: "column", gap: "6px" },
479
+ children: targets().map((t) => /* @__PURE__ */ jsxs2("div", {
480
+ class: "visage-graph-pill target",
481
+ style: {
482
+ width: "100%",
483
+ justifyContent: "space-between",
484
+ padding: "6px 8px"
485
+ },
486
+ onClick: () => props.selectedId.set(t.id),
487
+ children: [
488
+ /* @__PURE__ */ jsx2("span", {
489
+ children: t.name
490
+ }),
491
+ /* @__PURE__ */ jsxs2("span", {
492
+ style: { color: "#94a3b8" },
493
+ children: [
494
+ "v",
495
+ t.version()
496
+ ]
497
+ })
498
+ ]
499
+ }))
500
+ }) : /* @__PURE__ */ jsx2("div", {
501
+ style: { fontSize: "11px", color: "#64748b" },
502
+ children: "None (Leaf / UI Consumer)"
503
+ })
504
+ ]
505
+ })
506
+ ]
507
+ });
508
+ }
509
+ })
510
+ });
511
+ }
512
+
513
+ // src/devtools/GraphTab.tsx
514
+ function GraphTab(props) {
515
+ const [filterType, setFilterType] = createSignal2("all", {
516
+ internal: true
517
+ });
518
+ const [hoveredId, setHoveredId] = createSignal2(null, { internal: true });
519
+ const allSignals = () => props.hub.signalsList();
520
+ const getDependencies = (node) => {
521
+ const depIds = node.dependencies ? node.dependencies() : [];
522
+ if (depIds.length === 0)
523
+ return [];
524
+ return allSignals().filter((s) => depIds.includes(s.id));
525
+ };
526
+ const getDependents = (node) => {
527
+ const directDependents = node.dependents ? node.dependents() : [];
528
+ return allSignals().filter((s) => directDependents.includes(s.id) || s.dependencies?.().includes(node.id));
529
+ };
530
+ const activeFocusId = () => hoveredId() ?? props.selectedId();
531
+ const focusedDeps = () => {
532
+ const id = activeFocusId();
533
+ if (!id)
534
+ return [];
535
+ const node = allSignals().find((s) => s.id === id);
536
+ if (!node)
537
+ return [];
538
+ return getDependencies(node).map((s) => s.id);
539
+ };
540
+ const focusedTargets = () => {
541
+ const id = activeFocusId();
542
+ if (!id)
543
+ return [];
544
+ const node = allSignals().find((s) => s.id === id);
545
+ if (!node)
546
+ return [];
547
+ return getDependents(node).map((s) => s.id);
548
+ };
549
+ const filteredSignals = () => allSignals().filter((s) => {
550
+ const q = props.searchQuery().toLowerCase().trim();
551
+ const matchQuery = !q || s.name.toLowerCase().includes(q) || s.id.toLowerCase().includes(q);
552
+ const matchType = filterType() === "all" || s.type === filterType();
553
+ return matchQuery && matchType;
554
+ });
555
+ const stateSignals = () => filteredSignals().filter((s) => s.type === "signal");
556
+ const computedSignals = () => filteredSignals().filter((s) => s.type === "computed");
557
+ const selectedNode = () => {
558
+ const id = props.selectedId();
559
+ if (!id)
560
+ return null;
561
+ return allSignals().find((s) => s.id === id) ?? null;
562
+ };
563
+ return /* @__PURE__ */ jsxs2("div", {
564
+ class: "visage-graph-container",
565
+ children: [
566
+ /* @__PURE__ */ jsxs2("div", {
567
+ class: "visage-graph-toolbar",
568
+ children: [
569
+ /* @__PURE__ */ jsxs2("div", {
570
+ style: { display: "flex", alignItems: "center", gap: "10px" },
571
+ children: [
572
+ /* @__PURE__ */ jsx2("input", {
573
+ class: "visage-devtools-input",
574
+ style: { width: "200px" },
575
+ placeholder: "Filter DAG graph...",
576
+ value: props.searchQuery,
577
+ onInput: (e) => props.searchQuery.set(e.target.value)
578
+ }),
579
+ /* @__PURE__ */ jsxs2("div", {
580
+ style: { display: "flex", gap: "4px" },
581
+ children: [
582
+ /* @__PURE__ */ jsxs2("button", {
583
+ type: "button",
584
+ class: () => `visage-devtools-btn ${filterType() === "all" ? "active" : ""}`,
585
+ onClick: () => setFilterType("all"),
586
+ children: [
587
+ "All (",
588
+ () => filteredSignals().length,
589
+ ")"
590
+ ]
591
+ }),
592
+ /* @__PURE__ */ jsxs2("button", {
593
+ type: "button",
594
+ class: () => `visage-devtools-btn ${filterType() === "signal" ? "active" : ""}`,
595
+ onClick: () => setFilterType("signal"),
596
+ children: [
597
+ "Signals (",
598
+ () => stateSignals().length,
599
+ ")"
600
+ ]
601
+ }),
602
+ /* @__PURE__ */ jsxs2("button", {
603
+ type: "button",
604
+ class: () => `visage-devtools-btn ${filterType() === "computed" ? "active" : ""}`,
605
+ onClick: () => setFilterType("computed"),
606
+ children: [
607
+ "Computeds (",
608
+ () => computedSignals().length,
609
+ ")"
610
+ ]
611
+ })
612
+ ]
613
+ })
614
+ ]
615
+ }),
616
+ /* @__PURE__ */ jsxs2("div", {
617
+ style: {
618
+ fontSize: "11px",
619
+ color: "#64748b",
620
+ display: "flex",
621
+ gap: "14px",
622
+ alignItems: "center"
623
+ },
624
+ children: [
625
+ /* @__PURE__ */ jsx2("span", {
626
+ style: { color: "#38bdf8" },
627
+ children: "[SIG] Upstream"
628
+ }),
629
+ /* @__PURE__ */ jsx2("span", {
630
+ style: { color: "#c084fc" },
631
+ children: "[CMP] Derived"
632
+ }),
633
+ /* @__PURE__ */ jsx2("span", {
634
+ style: { color: "#10b981" },
635
+ children: "Glitch-Free DAG"
636
+ })
637
+ ]
638
+ })
639
+ ]
640
+ }),
641
+ /* @__PURE__ */ jsxs2("div", {
642
+ style: { flex: 1, display: "flex", overflow: "hidden" },
643
+ children: [
644
+ /* @__PURE__ */ jsxs2("div", {
645
+ class: "visage-graph-canvas",
646
+ children: [
647
+ /* @__PURE__ */ jsxs2("div", {
648
+ class: "visage-graph-column",
649
+ children: [
650
+ /* @__PURE__ */ jsxs2("div", {
651
+ class: "visage-graph-col-header",
652
+ children: [
653
+ /* @__PURE__ */ jsx2("span", {
654
+ class: "visage-graph-pulse"
655
+ }),
656
+ /* @__PURE__ */ jsxs2("span", {
657
+ children: [
658
+ "Reactive Sources (",
659
+ () => stateSignals().length,
660
+ ")"
661
+ ]
662
+ })
663
+ ]
664
+ }),
665
+ /* @__PURE__ */ jsx2(For2, {
666
+ each: stateSignals,
667
+ children: (node) => {
668
+ const isSelected = () => props.selectedId() === node.id;
669
+ const isDep = () => focusedDeps().includes(node.id);
670
+ const isTarget = () => focusedTargets().includes(node.id);
671
+ const isDimmed = () => activeFocusId() !== null && !isSelected() && !isDep() && !isTarget();
672
+ const dependents = () => getDependents(node);
673
+ return /* @__PURE__ */ jsxs2("div", {
674
+ class: () => `visage-graph-node ${isSelected() ? "selected" : ""} ${isDep() ? "is-dependency" : ""} ${isTarget() ? "is-dependent" : ""} ${isDimmed() ? "is-dimmed" : ""}`,
675
+ onClick: () => props.selectedId.set(node.id),
676
+ onMouseEnter: () => setHoveredId(node.id),
677
+ onMouseLeave: () => setHoveredId(null),
678
+ children: [
679
+ /* @__PURE__ */ jsxs2("div", {
680
+ class: "visage-graph-node-title",
681
+ children: [
682
+ /* @__PURE__ */ jsxs2("span", {
683
+ style: {
684
+ color: "#f8fafc",
685
+ display: "inline-flex",
686
+ alignItems: "center",
687
+ gap: "6px"
688
+ },
689
+ children: [
690
+ /* @__PURE__ */ jsx2("span", {
691
+ style: {
692
+ fontSize: "9px",
693
+ fontWeight: 700,
694
+ padding: "1px 4px",
695
+ borderRadius: "3px",
696
+ background: "#082f49",
697
+ color: "#38bdf8",
698
+ border: "1px solid #0369a1"
699
+ },
700
+ children: "SIG"
701
+ }),
702
+ /* @__PURE__ */ jsx2("span", {
703
+ children: node.name
704
+ })
705
+ ]
706
+ }),
707
+ /* @__PURE__ */ jsxs2("span", {
708
+ class: "visage-devtools-badge",
709
+ children: [
710
+ "v",
711
+ () => node.version()
712
+ ]
713
+ })
714
+ ]
715
+ }),
716
+ /* @__PURE__ */ jsx2("div", {
717
+ class: "visage-graph-node-val",
718
+ children: () => JSON.stringify(node.getValue())
719
+ }),
720
+ /* @__PURE__ */ jsx2("div", {
721
+ style: { marginTop: "8px", display: "flex", flexWrap: "wrap", gap: "4px" },
722
+ children: () => dependents().length > 0 ? /* @__PURE__ */ jsxs2("span", {
723
+ style: { fontSize: "10px", color: "#94a3b8" },
724
+ children: [
725
+ dependents().length,
726
+ " consumer",
727
+ dependents().length > 1 ? "s" : ""
728
+ ]
729
+ }) : /* @__PURE__ */ jsx2("span", {
730
+ style: { fontSize: "10px", color: "#475569" },
731
+ children: "Root State"
732
+ })
733
+ })
734
+ ]
735
+ });
736
+ }
737
+ })
738
+ ]
739
+ }),
740
+ /* @__PURE__ */ jsx2("div", {
741
+ style: {
742
+ display: "flex",
743
+ flexDirection: "column",
744
+ justifyContent: "center",
745
+ alignItems: "center",
746
+ color: "#334155",
747
+ fontSize: "14px",
748
+ fontWeight: 700,
749
+ padding: "0 10px"
750
+ },
751
+ children: /* @__PURE__ */ jsx2("span", {
752
+ children: ">"
753
+ })
754
+ }),
755
+ /* @__PURE__ */ jsxs2("div", {
756
+ class: "visage-graph-column",
757
+ children: [
758
+ /* @__PURE__ */ jsxs2("div", {
759
+ class: "visage-graph-col-header",
760
+ children: [
761
+ /* @__PURE__ */ jsx2("span", {
762
+ class: "visage-graph-pulse computed"
763
+ }),
764
+ /* @__PURE__ */ jsxs2("span", {
765
+ children: [
766
+ "Derived Computeds (",
767
+ () => computedSignals().length,
768
+ ")"
769
+ ]
770
+ })
771
+ ]
772
+ }),
773
+ /* @__PURE__ */ jsx2(For2, {
774
+ each: computedSignals,
775
+ children: (node) => {
776
+ const isSelected = () => props.selectedId() === node.id;
777
+ const isDep = () => focusedDeps().includes(node.id);
778
+ const isTarget = () => focusedTargets().includes(node.id);
779
+ const isDimmed = () => activeFocusId() !== null && !isSelected() && !isDep() && !isTarget();
780
+ const deps = () => getDependencies(node);
781
+ return /* @__PURE__ */ jsxs2("div", {
782
+ class: () => `visage-graph-node ${isSelected() ? "selected" : ""} ${isDep() ? "is-dependency" : ""} ${isTarget() ? "is-dependent" : ""} ${isDimmed() ? "is-dimmed" : ""}`,
783
+ onClick: () => props.selectedId.set(node.id),
784
+ onMouseEnter: () => setHoveredId(node.id),
785
+ onMouseLeave: () => setHoveredId(null),
786
+ children: [
787
+ /* @__PURE__ */ jsxs2("div", {
788
+ class: "visage-graph-node-title",
789
+ children: [
790
+ /* @__PURE__ */ jsxs2("span", {
791
+ style: {
792
+ color: "#f8fafc",
793
+ display: "inline-flex",
794
+ alignItems: "center",
795
+ gap: "6px"
796
+ },
797
+ children: [
798
+ /* @__PURE__ */ jsx2("span", {
799
+ style: {
800
+ fontSize: "9px",
801
+ fontWeight: 700,
802
+ padding: "1px 4px",
803
+ borderRadius: "3px",
804
+ background: "#3b0764",
805
+ color: "#c084fc",
806
+ border: "1px solid #581c87"
807
+ },
808
+ children: "CMP"
809
+ }),
810
+ /* @__PURE__ */ jsx2("span", {
811
+ children: node.name
812
+ })
813
+ ]
814
+ }),
815
+ /* @__PURE__ */ jsxs2("span", {
816
+ class: "visage-devtools-badge",
817
+ style: { background: "#581c87", color: "#fff" },
818
+ children: [
819
+ "v",
820
+ () => node.version()
821
+ ]
822
+ })
823
+ ]
824
+ }),
825
+ /* @__PURE__ */ jsx2("div", {
826
+ class: "visage-graph-node-val",
827
+ children: () => JSON.stringify(node.getValue())
828
+ }),
829
+ /* @__PURE__ */ jsx2("div", {
830
+ style: { marginTop: "8px", display: "flex", flexWrap: "wrap", gap: "4px" },
831
+ children: () => deps().length > 0 ? deps().map((d) => /* @__PURE__ */ jsxs2("span", {
832
+ class: "visage-graph-pill source",
833
+ onClick: (e) => {
834
+ e.stopPropagation();
835
+ props.selectedId.set(d.id);
836
+ },
837
+ children: [
838
+ "in: ",
839
+ d.name
840
+ ]
841
+ })) : /* @__PURE__ */ jsx2("span", {
842
+ style: { fontSize: "10px", color: "#64748b" },
843
+ children: "Memoized"
844
+ })
845
+ })
846
+ ]
847
+ });
848
+ }
849
+ })
850
+ ]
851
+ })
852
+ ]
853
+ }),
854
+ /* @__PURE__ */ jsx2(GraphInspector, {
855
+ selectedNode,
856
+ selectedId: props.selectedId,
857
+ getDependencies,
858
+ getDependents,
859
+ formatJSON: props.formatJSON
860
+ })
861
+ ]
862
+ })
863
+ ]
864
+ });
865
+ }
866
+
867
+ // src/devtools/highlighter.ts
868
+ var styleInjected = false;
869
+ var activeTimeouts = new WeakMap;
870
+ function injectHighlighterStyles() {
871
+ if (styleInjected || typeof document === "undefined")
872
+ return;
873
+ const style = document.createElement("style");
874
+ style.id = "visage-devtools-highlighter";
875
+ style.textContent = `
876
+ @keyframes visage-devtools-flash {
877
+ 0% {
878
+ outline: 2px solid rgba(56, 189, 248, 0.9);
879
+ box-shadow: 0 0 12px rgba(56, 189, 248, 0.45);
880
+ }
881
+ 100% {
882
+ outline: 2px solid transparent;
883
+ box-shadow: none;
884
+ }
885
+ }
886
+ .visage-dev-highlight {
887
+ outline-offset: -1px;
888
+ animation: visage-devtools-flash 0.5s ease-out !important;
889
+ }
890
+ `;
891
+ document.head.appendChild(style);
892
+ styleInjected = true;
893
+ }
894
+ function highlightElement2(element) {
895
+ if (!element || typeof document === "undefined" || !(element instanceof Element))
896
+ return;
897
+ injectHighlighterStyles();
898
+ const prevTimeout = activeTimeouts.get(element);
899
+ if (prevTimeout) {
900
+ clearTimeout(prevTimeout);
901
+ }
902
+ element.classList.remove("visage-dev-highlight");
903
+ element.offsetWidth;
904
+ element.classList.add("visage-dev-highlight");
905
+ const timeout = setTimeout(() => {
906
+ element.classList.remove("visage-dev-highlight");
907
+ activeTimeouts.delete(element);
908
+ }, 500);
909
+ activeTimeouts.set(element, timeout);
910
+ }
911
+ var observer = null;
912
+ function setupDomMutationHighlighter(enabledGetter) {
913
+ if (typeof window === "undefined" || typeof MutationObserver === "undefined")
914
+ return;
915
+ const startObserver = () => {
916
+ if (observer)
917
+ return;
918
+ injectHighlighterStyles();
919
+ observer = new MutationObserver((mutations) => {
920
+ if (!enabledGetter())
921
+ return;
922
+ const seen = new Set;
923
+ for (const mutation of mutations) {
924
+ const target = mutation.target;
925
+ let el = null;
926
+ if (target instanceof Element) {
927
+ el = target;
928
+ } else if (target.parentElement) {
929
+ el = target.parentElement;
930
+ }
931
+ if (!el)
932
+ continue;
933
+ if (el.closest?.(".visage-devtools-root") || el.closest?.("#visage-devtools-highlighter")) {
934
+ continue;
935
+ }
936
+ if (mutation.type === "attributes" && mutation.attributeName === "class") {
937
+ const oldCls = (mutation.oldValue || "").replace(/\bvisage-dev-highlight\b/g, "").replace(/\s+/g, " ").trim();
938
+ const newCls = (el.getAttribute("class") || "").replace(/\bvisage-dev-highlight\b/g, "").replace(/\s+/g, " ").trim();
939
+ if (oldCls === newCls) {
940
+ continue;
941
+ }
942
+ }
943
+ if (!seen.has(el)) {
944
+ seen.add(el);
945
+ highlightElement2(el);
946
+ }
947
+ }
948
+ });
949
+ const targetNode = document.body || document.documentElement;
950
+ if (targetNode) {
951
+ observer.observe(targetNode, {
952
+ childList: true,
953
+ attributes: true,
954
+ attributeOldValue: true,
955
+ characterData: true,
956
+ subtree: true
957
+ });
958
+ }
959
+ };
960
+ const stopObserver = () => {
961
+ if (observer) {
962
+ observer.disconnect();
963
+ observer = null;
964
+ }
965
+ };
966
+ effect2(() => {
967
+ if (enabledGetter()) {
968
+ startObserver();
969
+ } else {
970
+ stopObserver();
971
+ }
972
+ });
973
+ onCleanup2(() => {
974
+ stopObserver();
975
+ });
976
+ }
977
+
978
+ // src/devtools/QueryTab.tsx
979
+ function QueryTab(props) {
980
+ const filteredQueries = () => {
981
+ const q = props.searchQuery().toLowerCase().trim();
982
+ const list = props.hub.queriesList();
983
+ if (!q)
984
+ return list;
985
+ return list.filter((item) => item.hash.toLowerCase().includes(q) || JSON.stringify(item.key).toLowerCase().includes(q));
986
+ };
987
+ const selectedQuery = () => {
988
+ const id = props.selectedId();
989
+ if (!id)
990
+ return null;
991
+ return props.hub.queriesList().find((qr) => qr.hash === id) ?? null;
992
+ };
993
+ return /* @__PURE__ */ jsxs2("div", {
994
+ style: { display: "flex", flex: 1, width: "100%", height: "100%", overflow: "hidden" },
995
+ children: [
996
+ /* @__PURE__ */ jsxs2("div", {
997
+ class: "visage-devtools-sidebar",
998
+ children: [
999
+ /* @__PURE__ */ jsx2("div", {
1000
+ class: "visage-devtools-search",
1001
+ children: /* @__PURE__ */ jsx2("input", {
1002
+ class: "visage-devtools-input",
1003
+ placeholder: "Search query cache...",
1004
+ value: props.searchQuery,
1005
+ onInput: (e) => props.searchQuery.set(e.target.value)
1006
+ })
1007
+ }),
1008
+ /* @__PURE__ */ jsx2("div", {
1009
+ class: "visage-devtools-list",
1010
+ children: /* @__PURE__ */ jsx2(For2, {
1011
+ each: filteredQueries,
1012
+ fallback: /* @__PURE__ */ jsx2("div", {
1013
+ style: { padding: "12px", color: "#64748b", fontSize: "12px" },
1014
+ children: "No active queries in cache."
1015
+ }),
1016
+ children: (qr) => {
1017
+ const isSelected = () => props.selectedId() === qr.hash;
1018
+ return /* @__PURE__ */ jsxs2("div", {
1019
+ class: () => `visage-devtools-item ${isSelected() ? "selected" : ""}`,
1020
+ onClick: () => props.selectedId.set(qr.hash),
1021
+ children: [
1022
+ /* @__PURE__ */ jsxs2("div", {
1023
+ style: {
1024
+ display: "flex",
1025
+ alignItems: "center",
1026
+ gap: "6px",
1027
+ overflow: "hidden"
1028
+ },
1029
+ children: [
1030
+ /* @__PURE__ */ jsx2("span", {
1031
+ class: "visage-devtools-badge",
1032
+ style: {
1033
+ background: qr.status() === "success" ? "#065f46" : qr.status() === "error" ? "#991b1b" : "#854d0e",
1034
+ color: "#fff"
1035
+ },
1036
+ children: () => qr.status()
1037
+ }),
1038
+ /* @__PURE__ */ jsx2("span", {
1039
+ style: {
1040
+ fontWeight: 500,
1041
+ overflow: "hidden",
1042
+ textOverflow: "ellipsis",
1043
+ whiteSpace: "nowrap"
1044
+ },
1045
+ children: JSON.stringify(qr.key)
1046
+ })
1047
+ ]
1048
+ }),
1049
+ /* @__PURE__ */ jsx2("span", {
1050
+ style: { fontSize: "10px", color: "#64748b" },
1051
+ children: () => qr.fetchStatus()
1052
+ })
1053
+ ]
1054
+ });
1055
+ }
1056
+ })
1057
+ })
1058
+ ]
1059
+ }),
1060
+ /* @__PURE__ */ jsx2("div", {
1061
+ class: "visage-devtools-main",
1062
+ children: /* @__PURE__ */ jsx2(Show2, {
1063
+ when: selectedQuery,
1064
+ fallback: /* @__PURE__ */ jsx2("div", {
1065
+ style: { color: "#64748b", textAlign: "center", marginTop: "40px", fontSize: "13px" },
1066
+ children: "Select a query from the cache list to view live cached response and trigger manual refetches."
1067
+ }),
1068
+ children: (qr) => /* @__PURE__ */ jsxs2("div", {
1069
+ children: [
1070
+ /* @__PURE__ */ jsxs2("div", {
1071
+ style: {
1072
+ display: "flex",
1073
+ alignItems: "center",
1074
+ justifyContent: "space-between",
1075
+ marginBottom: "16px"
1076
+ },
1077
+ children: [
1078
+ /* @__PURE__ */ jsxs2("div", {
1079
+ children: [
1080
+ /* @__PURE__ */ jsx2("h3", {
1081
+ style: { margin: 0, fontSize: "15px", color: "#f8fafc" },
1082
+ children: () => JSON.stringify(qr().key)
1083
+ }),
1084
+ /* @__PURE__ */ jsxs2("span", {
1085
+ style: { fontSize: "11px", color: "#64748b" },
1086
+ children: [
1087
+ "Hash: ",
1088
+ () => qr().hash
1089
+ ]
1090
+ })
1091
+ ]
1092
+ }),
1093
+ /* @__PURE__ */ jsxs2("div", {
1094
+ style: { display: "flex", gap: "8px" },
1095
+ children: [
1096
+ /* @__PURE__ */ jsx2("button", {
1097
+ type: "button",
1098
+ class: "visage-devtools-btn",
1099
+ onClick: () => qr().refetch?.(),
1100
+ children: "Refetch"
1101
+ }),
1102
+ /* @__PURE__ */ jsx2("button", {
1103
+ type: "button",
1104
+ class: "visage-devtools-btn",
1105
+ onClick: () => qr().invalidate?.(),
1106
+ children: "Invalidate Cache"
1107
+ })
1108
+ ]
1109
+ })
1110
+ ]
1111
+ }),
1112
+ /* @__PURE__ */ jsxs2("div", {
1113
+ style: {
1114
+ display: "grid",
1115
+ gridTemplateColumns: "1fr 1fr",
1116
+ gap: "10px",
1117
+ marginBottom: "16px"
1118
+ },
1119
+ children: [
1120
+ /* @__PURE__ */ jsxs2("div", {
1121
+ style: {
1122
+ background: "#0c111d",
1123
+ padding: "10px",
1124
+ borderRadius: "6px",
1125
+ border: "1px solid #1e293b"
1126
+ },
1127
+ children: [
1128
+ /* @__PURE__ */ jsx2("div", {
1129
+ style: { fontSize: "11px", color: "#64748b" },
1130
+ children: "STATUS"
1131
+ }),
1132
+ /* @__PURE__ */ jsx2("div", {
1133
+ style: { fontWeight: 600, color: "#38bdf8" },
1134
+ children: () => `${qr().status()} (${qr().fetchStatus()})`
1135
+ })
1136
+ ]
1137
+ }),
1138
+ /* @__PURE__ */ jsxs2("div", {
1139
+ style: {
1140
+ background: "#0c111d",
1141
+ padding: "10px",
1142
+ borderRadius: "6px",
1143
+ border: "1px solid #1e293b"
1144
+ },
1145
+ children: [
1146
+ /* @__PURE__ */ jsx2("div", {
1147
+ style: { fontSize: "11px", color: "#64748b" },
1148
+ children: "LAST UPDATED"
1149
+ }),
1150
+ /* @__PURE__ */ jsx2("div", {
1151
+ style: { fontWeight: 600, color: "#f1f5f9" },
1152
+ children: () => qr().dataUpdatedAt() ? new Date(qr().dataUpdatedAt()).toLocaleTimeString() : "Never"
1153
+ })
1154
+ ]
1155
+ })
1156
+ ]
1157
+ }),
1158
+ /* @__PURE__ */ jsx2("div", {
1159
+ style: { fontSize: "12px", color: "#94a3b8", marginBottom: "6px" },
1160
+ children: "Cached Response Payload:"
1161
+ }),
1162
+ /* @__PURE__ */ jsx2("pre", {
1163
+ class: "visage-devtools-json",
1164
+ children: () => props.formatJSON(qr().data())
1165
+ })
1166
+ ]
1167
+ })
1168
+ })
1169
+ })
1170
+ ]
1171
+ });
1172
+ }
1173
+
1174
+ // src/devtools/RpcTab.tsx
1175
+ function RpcTab(props) {
1176
+ const filteredRpc = () => {
1177
+ const q = props.searchQuery().toLowerCase().trim();
1178
+ const list = props.hub.rpcLogs();
1179
+ if (!q)
1180
+ return list;
1181
+ return list.filter((r) => r.path.toLowerCase().includes(q) || r.type.toLowerCase().includes(q));
1182
+ };
1183
+ const selectedRpc = () => {
1184
+ const id = props.selectedId();
1185
+ if (!id)
1186
+ return null;
1187
+ return props.hub.rpcLogs().find((r) => r.id === id) ?? null;
1188
+ };
1189
+ return /* @__PURE__ */ jsxs2("div", {
1190
+ style: { display: "flex", flex: 1, width: "100%", height: "100%", overflow: "hidden" },
1191
+ children: [
1192
+ /* @__PURE__ */ jsxs2("div", {
1193
+ class: "visage-devtools-sidebar",
1194
+ children: [
1195
+ /* @__PURE__ */ jsxs2("div", {
1196
+ class: "visage-devtools-search",
1197
+ style: { display: "flex", gap: "6px" },
1198
+ children: [
1199
+ /* @__PURE__ */ jsx2("input", {
1200
+ class: "visage-devtools-input",
1201
+ placeholder: "Filter RPC routes...",
1202
+ value: props.searchQuery,
1203
+ onInput: (e) => props.searchQuery.set(e.target.value)
1204
+ }),
1205
+ /* @__PURE__ */ jsx2("button", {
1206
+ type: "button",
1207
+ class: "visage-devtools-btn",
1208
+ onClick: () => props.hub.clearLogs(),
1209
+ title: "Clear RPC Logs",
1210
+ children: "Clear"
1211
+ })
1212
+ ]
1213
+ }),
1214
+ /* @__PURE__ */ jsx2("div", {
1215
+ class: "visage-devtools-list",
1216
+ children: /* @__PURE__ */ jsx2(For2, {
1217
+ each: filteredRpc,
1218
+ fallback: /* @__PURE__ */ jsx2("div", {
1219
+ style: { padding: "12px", color: "#64748b", fontSize: "12px" },
1220
+ children: "No RPC activity recorded yet."
1221
+ }),
1222
+ children: (r) => {
1223
+ const isSelected = () => props.selectedId() === r.id;
1224
+ return /* @__PURE__ */ jsxs2("div", {
1225
+ class: () => `visage-devtools-item ${isSelected() ? "selected" : ""}`,
1226
+ onClick: () => props.selectedId.set(r.id),
1227
+ children: [
1228
+ /* @__PURE__ */ jsxs2("div", {
1229
+ style: {
1230
+ display: "flex",
1231
+ alignItems: "center",
1232
+ gap: "6px",
1233
+ overflow: "hidden"
1234
+ },
1235
+ children: [
1236
+ /* @__PURE__ */ jsx2("span", {
1237
+ class: "visage-devtools-badge",
1238
+ style: {
1239
+ background: r.type === "mutation" ? "#c026d3" : r.type === "subscription" ? "#7c3aed" : "#0284c7",
1240
+ color: "#fff"
1241
+ },
1242
+ children: r.type.slice(0, 3).toUpperCase()
1243
+ }),
1244
+ /* @__PURE__ */ jsx2("span", {
1245
+ style: {
1246
+ fontWeight: 500,
1247
+ overflow: "hidden",
1248
+ textOverflow: "ellipsis",
1249
+ whiteSpace: "nowrap"
1250
+ },
1251
+ children: r.path
1252
+ })
1253
+ ]
1254
+ }),
1255
+ /* @__PURE__ */ jsxs2("div", {
1256
+ style: { display: "flex", alignItems: "center", gap: "6px" },
1257
+ children: [
1258
+ /* @__PURE__ */ jsx2("span", {
1259
+ style: {
1260
+ fontSize: "11px",
1261
+ color: r.status === "success" ? "#10b981" : r.status === "error" ? "#ef4444" : "#f59e0b"
1262
+ },
1263
+ children: r.status
1264
+ }),
1265
+ r.duration !== undefined ? /* @__PURE__ */ jsxs2("span", {
1266
+ style: { fontSize: "10px", color: "#64748b" },
1267
+ children: [
1268
+ r.duration,
1269
+ "ms"
1270
+ ]
1271
+ }) : null
1272
+ ]
1273
+ })
1274
+ ]
1275
+ });
1276
+ }
1277
+ })
1278
+ })
1279
+ ]
1280
+ }),
1281
+ /* @__PURE__ */ jsx2("div", {
1282
+ class: "visage-devtools-main",
1283
+ children: /* @__PURE__ */ jsx2(Show2, {
1284
+ when: selectedRpc,
1285
+ fallback: /* @__PURE__ */ jsx2("div", {
1286
+ style: { color: "#64748b", textAlign: "center", marginTop: "40px", fontSize: "13px" },
1287
+ children: "Select an RPC procedure call from the left to inspect full payload, latency, and streaming SSE frames."
1288
+ }),
1289
+ children: (r) => /* @__PURE__ */ jsxs2("div", {
1290
+ children: [
1291
+ /* @__PURE__ */ jsxs2("div", {
1292
+ style: {
1293
+ display: "flex",
1294
+ alignItems: "center",
1295
+ justifyContent: "space-between",
1296
+ marginBottom: "16px"
1297
+ },
1298
+ children: [
1299
+ /* @__PURE__ */ jsxs2("div", {
1300
+ children: [
1301
+ /* @__PURE__ */ jsx2("h3", {
1302
+ style: { margin: 0, fontSize: "16px", color: "#f8fafc" },
1303
+ children: () => `${r().type.toUpperCase()}: ${r().path}`
1304
+ }),
1305
+ /* @__PURE__ */ jsxs2("span", {
1306
+ style: { fontSize: "11px", color: "#64748b" },
1307
+ children: [
1308
+ "Call ID: ",
1309
+ () => r().id
1310
+ ]
1311
+ })
1312
+ ]
1313
+ }),
1314
+ /* @__PURE__ */ jsx2("span", {
1315
+ class: "visage-devtools-badge",
1316
+ style: { fontSize: "12px", padding: "3px 8px" },
1317
+ children: () => r().duration !== undefined ? `${r().duration}ms` : "Active"
1318
+ })
1319
+ ]
1320
+ }),
1321
+ /* @__PURE__ */ jsxs2("div", {
1322
+ style: { marginBottom: "12px" },
1323
+ children: [
1324
+ /* @__PURE__ */ jsx2("div", {
1325
+ style: { fontSize: "12px", color: "#94a3b8", marginBottom: "4px" },
1326
+ children: "Input Parameters:"
1327
+ }),
1328
+ /* @__PURE__ */ jsx2("pre", {
1329
+ class: "visage-devtools-json",
1330
+ children: () => props.formatJSON(r().input)
1331
+ })
1332
+ ]
1333
+ }),
1334
+ /* @__PURE__ */ jsx2(Show2, {
1335
+ when: () => r().response !== undefined,
1336
+ children: /* @__PURE__ */ jsxs2("div", {
1337
+ style: { marginBottom: "12px" },
1338
+ children: [
1339
+ /* @__PURE__ */ jsx2("div", {
1340
+ style: { fontSize: "12px", color: "#94a3b8", marginBottom: "4px" },
1341
+ children: "Server Response:"
1342
+ }),
1343
+ /* @__PURE__ */ jsx2("pre", {
1344
+ class: "visage-devtools-json",
1345
+ children: () => props.formatJSON(r().response)
1346
+ })
1347
+ ]
1348
+ })
1349
+ }),
1350
+ /* @__PURE__ */ jsx2(Show2, {
1351
+ when: () => (r().events?.length ?? 0) > 0,
1352
+ children: /* @__PURE__ */ jsxs2("div", {
1353
+ children: [
1354
+ /* @__PURE__ */ jsxs2("div", {
1355
+ style: { fontSize: "12px", color: "#94a3b8", marginBottom: "4px" },
1356
+ children: [
1357
+ "Live SSE Event Stream (",
1358
+ () => r().events?.length ?? 0,
1359
+ " frames):"
1360
+ ]
1361
+ }),
1362
+ /* @__PURE__ */ jsx2("pre", {
1363
+ class: "visage-devtools-json",
1364
+ children: () => props.formatJSON(r().events)
1365
+ })
1366
+ ]
1367
+ })
1368
+ })
1369
+ ]
1370
+ })
1371
+ })
1372
+ })
1373
+ ]
1374
+ });
1375
+ }
1376
+
1377
+ // src/devtools/SignalsTab.tsx
1378
+ function SignalsTab(props) {
1379
+ const filteredSignals = () => {
1380
+ const q = props.searchQuery().toLowerCase().trim();
1381
+ const list = props.hub.signalsList();
1382
+ if (!q)
1383
+ return list;
1384
+ return list.filter((s) => s.name.toLowerCase().includes(q) || s.id.toLowerCase().includes(q));
1385
+ };
1386
+ const selectedSignal = () => {
1387
+ const id = props.selectedId();
1388
+ if (!id)
1389
+ return null;
1390
+ return props.hub.signalsList().find((s) => s.id === id) ?? null;
1391
+ };
1392
+ return /* @__PURE__ */ jsxs2("div", {
1393
+ style: { display: "flex", flex: 1, width: "100%", height: "100%", overflow: "hidden" },
1394
+ children: [
1395
+ /* @__PURE__ */ jsxs2("div", {
1396
+ class: "visage-devtools-sidebar",
1397
+ children: [
1398
+ /* @__PURE__ */ jsx2("div", {
1399
+ class: "visage-devtools-search",
1400
+ children: /* @__PURE__ */ jsx2("input", {
1401
+ class: "visage-devtools-input",
1402
+ placeholder: "Search signals...",
1403
+ value: props.searchQuery,
1404
+ onInput: (e) => props.searchQuery.set(e.target.value)
1405
+ })
1406
+ }),
1407
+ /* @__PURE__ */ jsx2("div", {
1408
+ class: "visage-devtools-list",
1409
+ children: /* @__PURE__ */ jsx2(For2, {
1410
+ each: filteredSignals,
1411
+ children: (sig) => {
1412
+ const isSelected = () => props.selectedId() === sig.id;
1413
+ return /* @__PURE__ */ jsxs2("div", {
1414
+ class: () => `visage-devtools-item ${sig.type} ${isSelected() ? "selected" : ""}`,
1415
+ onClick: () => props.selectedId.set(sig.id),
1416
+ children: [
1417
+ /* @__PURE__ */ jsxs2("div", {
1418
+ style: { display: "flex", alignItems: "center", gap: "8px" },
1419
+ children: [
1420
+ /* @__PURE__ */ jsx2("span", {
1421
+ style: {
1422
+ fontSize: "9px",
1423
+ fontWeight: 700,
1424
+ padding: "1px 4px",
1425
+ borderRadius: "3px",
1426
+ background: sig.type === "computed" ? "#3b0764" : "#082f49",
1427
+ color: sig.type === "computed" ? "#c084fc" : "#38bdf8",
1428
+ border: `1px solid ${sig.type === "computed" ? "#581c87" : "#0369a1"}`
1429
+ },
1430
+ children: sig.type === "computed" ? "CMP" : "SIG"
1431
+ }),
1432
+ /* @__PURE__ */ jsx2("span", {
1433
+ style: { fontWeight: 500, color: "#f1f5f9" },
1434
+ children: sig.name
1435
+ })
1436
+ ]
1437
+ }),
1438
+ /* @__PURE__ */ jsxs2("span", {
1439
+ class: "visage-devtools-badge",
1440
+ children: [
1441
+ "v",
1442
+ () => sig.version()
1443
+ ]
1444
+ })
1445
+ ]
1446
+ });
1447
+ }
1448
+ })
1449
+ })
1450
+ ]
1451
+ }),
1452
+ /* @__PURE__ */ jsx2("div", {
1453
+ class: "visage-devtools-main",
1454
+ children: /* @__PURE__ */ jsx2(Show2, {
1455
+ when: selectedSignal,
1456
+ fallback: /* @__PURE__ */ jsx2("div", {
1457
+ style: {
1458
+ color: "#64748b",
1459
+ textAlign: "center",
1460
+ marginTop: "40px",
1461
+ fontSize: "13px"
1462
+ },
1463
+ children: "Select a signal or computed from the left to inspect its live reactive value."
1464
+ }),
1465
+ children: (sig) => /* @__PURE__ */ jsxs2("div", {
1466
+ children: [
1467
+ /* @__PURE__ */ jsxs2("div", {
1468
+ style: {
1469
+ display: "flex",
1470
+ alignItems: "center",
1471
+ justifyContent: "space-between",
1472
+ marginBottom: "16px"
1473
+ },
1474
+ children: [
1475
+ /* @__PURE__ */ jsxs2("div", {
1476
+ children: [
1477
+ /* @__PURE__ */ jsx2("h3", {
1478
+ style: { margin: 0, fontSize: "16px", color: "#f8fafc" },
1479
+ children: () => sig().name
1480
+ }),
1481
+ /* @__PURE__ */ jsxs2("span", {
1482
+ style: { fontSize: "11px", color: "#64748b" },
1483
+ children: [
1484
+ "ID: ",
1485
+ () => sig().id
1486
+ ]
1487
+ })
1488
+ ]
1489
+ }),
1490
+ /* @__PURE__ */ jsxs2("div", {
1491
+ style: { display: "flex", gap: "8px" },
1492
+ children: [
1493
+ /* @__PURE__ */ jsx2("span", {
1494
+ class: "visage-devtools-badge",
1495
+ style: {
1496
+ background: () => sig().type === "computed" ? "#581c87" : "#0369a1",
1497
+ color: "#fff"
1498
+ },
1499
+ children: () => sig().type.toUpperCase()
1500
+ }),
1501
+ /* @__PURE__ */ jsxs2("span", {
1502
+ class: "visage-devtools-badge",
1503
+ children: [
1504
+ "VERSION: ",
1505
+ () => sig().version()
1506
+ ]
1507
+ })
1508
+ ]
1509
+ })
1510
+ ]
1511
+ }),
1512
+ /* @__PURE__ */ jsx2("div", {
1513
+ style: { marginBottom: "12px", fontSize: "12px", color: "#94a3b8" },
1514
+ children: "Current Reactive Value:"
1515
+ }),
1516
+ /* @__PURE__ */ jsx2("pre", {
1517
+ class: "visage-devtools-json",
1518
+ children: () => props.formatJSON(sig().getValue())
1519
+ })
1520
+ ]
1521
+ })
1522
+ })
1523
+ })
1524
+ ]
1525
+ });
1526
+ }
1527
+
1528
+ // src/devtools/styles.ts
1529
+ var devtoolsStyles = `
1530
+ .visage-devtools-root {
1531
+ position: fixed;
1532
+ z-index: 999999;
1533
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
1534
+ font-size: 13px;
1535
+ color: #f1f5f9;
1536
+ box-sizing: border-box;
1537
+ }
1538
+ .visage-devtools-root * {
1539
+ box-sizing: border-box;
1540
+ }
1541
+ .visage-devtools-trigger {
1542
+ position: fixed;
1543
+ bottom: 20px;
1544
+ left: 20px;
1545
+ background: #0f172a;
1546
+ color: #38bdf8;
1547
+ border: 1px solid #334155;
1548
+ border-radius: 9999px;
1549
+ padding: 8px 14px;
1550
+ display: flex;
1551
+ align-items: center;
1552
+ gap: 8px;
1553
+ cursor: pointer;
1554
+ font-weight: 600;
1555
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 0 10px rgba(56, 189, 248, 0.2);
1556
+ transition: all 0.2s ease;
1557
+ z-index: 999999;
1558
+ }
1559
+ .visage-devtools-trigger:hover {
1560
+ background: #1e293b;
1561
+ border-color: #38bdf8;
1562
+ transform: translateY(-2px);
1563
+ }
1564
+ .visage-devtools-drawer {
1565
+ position: fixed;
1566
+ bottom: 0;
1567
+ left: 0;
1568
+ right: 0;
1569
+ height: 420px;
1570
+ background: #090d16;
1571
+ border-top: 1px solid #1e293b;
1572
+ display: flex;
1573
+ flex-direction: column;
1574
+ box-shadow: 0 -20px 25px -5px rgba(0, 0, 0, 0.7);
1575
+ z-index: 999999;
1576
+ }
1577
+ .visage-devtools-header {
1578
+ display: flex;
1579
+ align-items: center;
1580
+ justify-content: space-between;
1581
+ padding: 8px 16px;
1582
+ background: #0f172a;
1583
+ border-bottom: 1px solid #1e293b;
1584
+ }
1585
+ .visage-devtools-tabs {
1586
+ display: flex;
1587
+ gap: 4px;
1588
+ }
1589
+ .visage-devtools-tab {
1590
+ background: transparent;
1591
+ border: none;
1592
+ color: #94a3b8;
1593
+ padding: 6px 12px;
1594
+ border-radius: 6px;
1595
+ cursor: pointer;
1596
+ font-size: 12px;
1597
+ font-weight: 500;
1598
+ display: flex;
1599
+ align-items: center;
1600
+ gap: 6px;
1601
+ }
1602
+ .visage-devtools-tab:hover {
1603
+ color: #f1f5f9;
1604
+ background: #1e293b;
1605
+ }
1606
+ .visage-devtools-tab.active {
1607
+ color: #38bdf8;
1608
+ background: #1e293b;
1609
+ font-weight: 600;
1610
+ }
1611
+ .visage-devtools-badge {
1612
+ background: #334155;
1613
+ color: #f1f5f9;
1614
+ padding: 1px 6px;
1615
+ border-radius: 9999px;
1616
+ font-size: 10px;
1617
+ font-weight: 600;
1618
+ }
1619
+ .visage-devtools-body {
1620
+ flex: 1;
1621
+ display: flex;
1622
+ overflow: hidden;
1623
+ }
1624
+ .visage-devtools-sidebar {
1625
+ width: 320px;
1626
+ border-right: 1px solid #1e293b;
1627
+ display: flex;
1628
+ flex-direction: column;
1629
+ background: #0c111d;
1630
+ }
1631
+ .visage-devtools-search {
1632
+ padding: 8px;
1633
+ border-bottom: 1px solid #1e293b;
1634
+ }
1635
+ .visage-devtools-input {
1636
+ width: 100%;
1637
+ background: #090d16;
1638
+ border: 1px solid #334155;
1639
+ border-radius: 6px;
1640
+ color: #f1f5f9;
1641
+ padding: 6px 10px;
1642
+ font-size: 12px;
1643
+ outline: none;
1644
+ }
1645
+ .visage-devtools-input:focus {
1646
+ border-color: #38bdf8;
1647
+ }
1648
+ .visage-devtools-list {
1649
+ flex: 1;
1650
+ overflow-y: auto;
1651
+ padding: 4px;
1652
+ }
1653
+ .visage-devtools-item {
1654
+ padding: 8px 10px;
1655
+ border-radius: 6px;
1656
+ cursor: pointer;
1657
+ display: flex;
1658
+ align-items: center;
1659
+ justify-content: space-between;
1660
+ margin-bottom: 2px;
1661
+ font-size: 12px;
1662
+ }
1663
+ .visage-devtools-item:hover {
1664
+ background: #1e293b;
1665
+ }
1666
+ .visage-devtools-item.selected {
1667
+ background: #1e293b;
1668
+ border-left: 3px solid #38bdf8;
1669
+ }
1670
+ .visage-devtools-main {
1671
+ flex: 1;
1672
+ padding: 16px;
1673
+ overflow-y: auto;
1674
+ background: #090d16;
1675
+ }
1676
+ .visage-devtools-json {
1677
+ background: #050811;
1678
+ border: 1px solid #1e293b;
1679
+ border-radius: 6px;
1680
+ padding: 12px;
1681
+ font-family: "JetBrains Mono", Menlo, Monaco, Consolas, monospace;
1682
+ font-size: 12px;
1683
+ color: #38bdf8;
1684
+ overflow-x: auto;
1685
+ white-space: pre-wrap;
1686
+ }
1687
+ .visage-devtools-actions {
1688
+ display: flex;
1689
+ align-items: center;
1690
+ gap: 8px;
1691
+ }
1692
+ .visage-devtools-btn {
1693
+ background: #1e293b;
1694
+ border: 1px solid #334155;
1695
+ color: #f1f5f9;
1696
+ padding: 4px 10px;
1697
+ border-radius: 4px;
1698
+ font-size: 11px;
1699
+ cursor: pointer;
1700
+ font-weight: 500;
1701
+ }
1702
+ .visage-devtools-btn:hover {
1703
+ background: #334155;
1704
+ }
1705
+ .visage-devtools-btn.active {
1706
+ background: #0284c7;
1707
+ border-color: #38bdf8;
1708
+ }
1709
+ /* DAG Graph Visualization */
1710
+ .visage-graph-container {
1711
+ flex: 1;
1712
+ display: flex;
1713
+ flex-direction: column;
1714
+ overflow: hidden;
1715
+ background: #050811;
1716
+ position: relative;
1717
+ }
1718
+ .visage-graph-toolbar {
1719
+ padding: 8px 16px;
1720
+ background: #090d16;
1721
+ border-bottom: 1px solid #1e293b;
1722
+ display: flex;
1723
+ align-items: center;
1724
+ justify-content: space-between;
1725
+ gap: 12px;
1726
+ }
1727
+ .visage-graph-canvas {
1728
+ flex: 1;
1729
+ overflow: auto;
1730
+ padding: 24px;
1731
+ position: relative;
1732
+ display: flex;
1733
+ gap: 40px;
1734
+ }
1735
+ .visage-graph-column {
1736
+ display: flex;
1737
+ flex-direction: column;
1738
+ gap: 16px;
1739
+ min-width: 220px;
1740
+ }
1741
+ .visage-graph-col-header {
1742
+ font-size: 11px;
1743
+ font-weight: 700;
1744
+ text-transform: uppercase;
1745
+ letter-spacing: 0.05em;
1746
+ color: #64748b;
1747
+ margin-bottom: 4px;
1748
+ display: flex;
1749
+ align-items: center;
1750
+ gap: 6px;
1751
+ }
1752
+ .visage-graph-node {
1753
+ background: #0f172a;
1754
+ border: 1px solid #1e293b;
1755
+ border-radius: 8px;
1756
+ padding: 10px 12px;
1757
+ cursor: pointer;
1758
+ transition: all 0.2s ease;
1759
+ position: relative;
1760
+ }
1761
+ .visage-graph-node:hover {
1762
+ border-color: #38bdf8;
1763
+ transform: translateY(-2px);
1764
+ box-shadow: 0 4px 12px rgba(56, 189, 248, 0.15);
1765
+ }
1766
+ .visage-graph-node.selected {
1767
+ border-color: #38bdf8;
1768
+ box-shadow: 0 0 0 2px rgba(56, 189, 248, 0.4);
1769
+ background: #131d35;
1770
+ }
1771
+ .visage-graph-node.is-dependency {
1772
+ border-color: #38bdf8;
1773
+ box-shadow: 0 0 0 1px #38bdf8, 0 2px 8px rgba(56, 189, 248, 0.25);
1774
+ background: #082f49;
1775
+ }
1776
+ .visage-graph-node.is-dependent {
1777
+ border-color: #c084fc;
1778
+ box-shadow: 0 0 0 1px #c084fc, 0 2px 8px rgba(192, 132, 252, 0.25);
1779
+ background: #3b0764;
1780
+ }
1781
+ .visage-graph-node.is-dimmed {
1782
+ opacity: 0.3;
1783
+ filter: grayscale(0.5);
1784
+ }
1785
+ .visage-graph-node-title {
1786
+ font-weight: 600;
1787
+ font-size: 12px;
1788
+ color: #f8fafc;
1789
+ margin-bottom: 4px;
1790
+ display: flex;
1791
+ align-items: center;
1792
+ justify-content: space-between;
1793
+ }
1794
+ .visage-graph-node-val {
1795
+ font-family: monospace;
1796
+ font-size: 11px;
1797
+ color: #94a3b8;
1798
+ overflow: hidden;
1799
+ text-overflow: ellipsis;
1800
+ white-space: nowrap;
1801
+ max-width: 190px;
1802
+ }
1803
+ .visage-graph-pulse {
1804
+ display: inline-block;
1805
+ width: 8px;
1806
+ height: 8px;
1807
+ border-radius: 50%;
1808
+ background: #10b981;
1809
+ box-shadow: 0 0 8px #10b981;
1810
+ }
1811
+ .visage-graph-pulse.computed {
1812
+ background: #a855f7;
1813
+ box-shadow: 0 0 8px #a855f7;
1814
+ }
1815
+ .visage-graph-pill {
1816
+ display: inline-flex;
1817
+ align-items: center;
1818
+ gap: 4px;
1819
+ background: #1e293b;
1820
+ color: #cbd5e1;
1821
+ padding: 3px 8px;
1822
+ border-radius: 4px;
1823
+ font-size: 11px;
1824
+ cursor: pointer;
1825
+ border: 1px solid #334155;
1826
+ transition: all 0.15s ease;
1827
+ }
1828
+ .visage-graph-pill:hover {
1829
+ background: #334155;
1830
+ color: #fff;
1831
+ border-color: #38bdf8;
1832
+ }
1833
+ .visage-graph-pill.source {
1834
+ border-color: #0369a1;
1835
+ color: #7dd3fc;
1836
+ }
1837
+ .visage-graph-pill.target {
1838
+ border-color: #7e22ce;
1839
+ color: #d8b4fe;
1840
+ }
1841
+ `;
1842
+
1843
+ // src/devtools/component.tsx
1844
+ function VisageDevTools2(props = {}) {
1845
+ if (typeof window === "undefined") {
1846
+ return null;
1847
+ }
1848
+ const hub = devtoolsHub2;
1849
+ if (typeof window !== "undefined" && !window.__VISAGE_DEVTOOLS__) {
1850
+ window.__VISAGE_DEVTOOLS__ = hub;
1851
+ }
1852
+ if (props.initialOpen !== undefined) {
1853
+ hub.isOpen.set(props.initialOpen);
1854
+ }
1855
+ if (props.initialTab !== undefined) {
1856
+ hub.activeTab.set(props.initialTab);
1857
+ }
1858
+ if (props.highlightDOM !== undefined) {
1859
+ hub.highlightDOM.set(props.highlightDOM);
1860
+ }
1861
+ setupDomMutationHighlighter(() => hub.highlightDOM());
1862
+ const selectedId = signal2(null, { internal: true });
1863
+ const searchQuery = signal2("", { internal: true });
1864
+ if (typeof window !== "undefined") {
1865
+ const handleKeyDown = (e) => {
1866
+ if (e.shiftKey && e.altKey && e.key.toLowerCase() === "v") {
1867
+ e.preventDefault();
1868
+ hub.toggle();
1869
+ }
1870
+ };
1871
+ window.addEventListener("keydown", handleKeyDown);
1872
+ onCleanup2(() => window.removeEventListener("keydown", handleKeyDown));
1873
+ }
1874
+ const formatJSON = (val) => {
1875
+ try {
1876
+ if (val === undefined)
1877
+ return "undefined";
1878
+ return JSON.stringify(val, null, 2);
1879
+ } catch {
1880
+ return String(val);
1881
+ }
1882
+ };
1883
+ return /* @__PURE__ */ jsxs2("div", {
1884
+ class: "visage-devtools-root",
1885
+ children: [
1886
+ /* @__PURE__ */ jsx2(Style2, {
1887
+ children: devtoolsStyles
1888
+ }),
1889
+ () => !hub.isOpen() ? /* @__PURE__ */ jsx2(Tooltip3, {
1890
+ content: "Press Shift+Alt+V to toggle Visage DevTools",
1891
+ side: "top",
1892
+ children: /* @__PURE__ */ jsxs2("button", {
1893
+ type: "button",
1894
+ class: "visage-devtools-trigger",
1895
+ onClick: () => hub.toggle(),
1896
+ "aria-label": "Open Visage DevTools",
1897
+ children: [
1898
+ /* @__PURE__ */ jsx2("svg", {
1899
+ "aria-hidden": "true",
1900
+ width: "14",
1901
+ height: "14",
1902
+ viewBox: "0 0 24 24",
1903
+ fill: "none",
1904
+ stroke: "currentColor",
1905
+ "stroke-width": "2",
1906
+ "stroke-linecap": "round",
1907
+ "stroke-linejoin": "round",
1908
+ children: /* @__PURE__ */ jsx2("path", {
1909
+ d: "M13 2L3 14h9l-1 8 10-12h-9l1-8z"
1910
+ })
1911
+ }),
1912
+ /* @__PURE__ */ jsx2("span", {
1913
+ children: "DevTools"
1914
+ })
1915
+ ]
1916
+ })
1917
+ }) : /* @__PURE__ */ jsxs2("div", {
1918
+ class: "visage-devtools-drawer",
1919
+ role: "dialog",
1920
+ "aria-label": "Visage In-Browser DevTools",
1921
+ children: [
1922
+ /* @__PURE__ */ jsxs2("div", {
1923
+ class: "visage-devtools-header",
1924
+ children: [
1925
+ /* @__PURE__ */ jsxs2("div", {
1926
+ style: { display: "flex", alignItems: "center", gap: "8px" },
1927
+ children: [
1928
+ /* @__PURE__ */ jsx2("svg", {
1929
+ "aria-hidden": "true",
1930
+ width: "14",
1931
+ height: "14",
1932
+ viewBox: "0 0 24 24",
1933
+ fill: "none",
1934
+ stroke: "#38bdf8",
1935
+ "stroke-width": "2",
1936
+ "stroke-linecap": "round",
1937
+ "stroke-linejoin": "round",
1938
+ children: /* @__PURE__ */ jsx2("path", {
1939
+ d: "M13 2L3 14h9l-1 8 10-12h-9l1-8z"
1940
+ })
1941
+ }),
1942
+ /* @__PURE__ */ jsx2("strong", {
1943
+ style: {
1944
+ fontSize: "12px",
1945
+ letterSpacing: "0.04em",
1946
+ color: "#f8fafc",
1947
+ fontWeight: 700
1948
+ },
1949
+ children: "VISAGE"
1950
+ })
1951
+ ]
1952
+ }),
1953
+ /* @__PURE__ */ jsx2(Tabs2, {
1954
+ value: () => hub.activeTab(),
1955
+ onValueChange: (val) => {
1956
+ hub.setTab(val);
1957
+ selectedId.set(null);
1958
+ },
1959
+ listClass: "visage-devtools-tabs",
1960
+ items: [
1961
+ {
1962
+ value: "signals",
1963
+ label: () => /* @__PURE__ */ jsxs2("span", {
1964
+ style: { display: "inline-flex", alignItems: "center", gap: "6px" },
1965
+ children: [
1966
+ /* @__PURE__ */ jsx2("span", {
1967
+ children: "Signals"
1968
+ }),
1969
+ /* @__PURE__ */ jsx2("span", {
1970
+ class: "visage-devtools-badge",
1971
+ children: () => hub.signalsList().length
1972
+ })
1973
+ ]
1974
+ })
1975
+ },
1976
+ {
1977
+ value: "graph",
1978
+ label: () => /* @__PURE__ */ jsxs2("span", {
1979
+ style: { display: "inline-flex", alignItems: "center", gap: "6px" },
1980
+ children: [
1981
+ /* @__PURE__ */ jsx2("span", {
1982
+ children: "DAG Graph"
1983
+ }),
1984
+ /* @__PURE__ */ jsx2("span", {
1985
+ class: "visage-devtools-badge",
1986
+ style: { background: "#581c87", color: "#fff" },
1987
+ children: "LIVE"
1988
+ })
1989
+ ]
1990
+ })
1991
+ },
1992
+ {
1993
+ value: "query",
1994
+ label: () => /* @__PURE__ */ jsxs2("span", {
1995
+ style: { display: "inline-flex", alignItems: "center", gap: "6px" },
1996
+ children: [
1997
+ /* @__PURE__ */ jsx2("span", {
1998
+ children: "Query Cache"
1999
+ }),
2000
+ /* @__PURE__ */ jsx2("span", {
2001
+ class: "visage-devtools-badge",
2002
+ children: () => hub.queriesList().length
2003
+ })
2004
+ ]
2005
+ })
2006
+ },
2007
+ {
2008
+ value: "rpc",
2009
+ label: () => /* @__PURE__ */ jsxs2("span", {
2010
+ style: { display: "inline-flex", alignItems: "center", gap: "6px" },
2011
+ children: [
2012
+ /* @__PURE__ */ jsx2("span", {
2013
+ children: "RPC"
2014
+ }),
2015
+ /* @__PURE__ */ jsx2("span", {
2016
+ class: "visage-devtools-badge",
2017
+ children: () => hub.rpcLogs().length
2018
+ })
2019
+ ]
2020
+ })
2021
+ },
2022
+ {
2023
+ value: "dom",
2024
+ label: "DOM Inspector"
2025
+ }
2026
+ ]
2027
+ }),
2028
+ /* @__PURE__ */ jsx2("div", {
2029
+ class: "visage-devtools-actions",
2030
+ children: /* @__PURE__ */ jsx2("button", {
2031
+ type: "button",
2032
+ class: "visage-devtools-btn",
2033
+ onClick: () => hub.isOpen.set(false),
2034
+ title: "Close DevTools (Shift+Alt+V)",
2035
+ children: "Close"
2036
+ })
2037
+ })
2038
+ ]
2039
+ }),
2040
+ /* @__PURE__ */ jsx2("div", {
2041
+ class: "visage-devtools-body",
2042
+ children: () => {
2043
+ const tab = hub.activeTab();
2044
+ if (tab === "signals") {
2045
+ return /* @__PURE__ */ jsx2(SignalsTab, {
2046
+ hub,
2047
+ selectedId,
2048
+ searchQuery,
2049
+ formatJSON
2050
+ });
2051
+ }
2052
+ if (tab === "graph") {
2053
+ return /* @__PURE__ */ jsx2(GraphTab, {
2054
+ hub,
2055
+ selectedId,
2056
+ searchQuery,
2057
+ formatJSON
2058
+ });
2059
+ }
2060
+ if (tab === "query") {
2061
+ return /* @__PURE__ */ jsx2(QueryTab, {
2062
+ hub,
2063
+ selectedId,
2064
+ searchQuery,
2065
+ formatJSON
2066
+ });
2067
+ }
2068
+ if (tab === "rpc") {
2069
+ return /* @__PURE__ */ jsx2(RpcTab, {
2070
+ hub,
2071
+ selectedId,
2072
+ searchQuery,
2073
+ formatJSON
2074
+ });
2075
+ }
2076
+ return /* @__PURE__ */ jsx2(DomTab, {
2077
+ hub
2078
+ });
2079
+ }
2080
+ })
2081
+ ]
2082
+ })
2083
+ ]
2084
+ });
2085
+ }
2086
+
2087
+ // src/devtools/index.ts
2088
+ function connectDevTools2(client) {
2089
+ devtoolsHub2.attachQueryClient(client);
2090
+ }
2091
+
2092
+ export { DevToolsHub2, devtoolsHub2, highlightElement2, VisageDevTools2, connectDevTools2 };