@react-component-selector-mcp/react 1.0.0 → 2.0.1
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.js +76 -338
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -3,8 +3,6 @@ import { useCallback, useState, useRef, useEffect } from 'react';
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { nanoid } from 'nanoid';
|
|
6
|
-
import { SourceMapConsumer } from 'source-map-js';
|
|
7
|
-
import { toPng } from 'html-to-image';
|
|
8
6
|
|
|
9
7
|
var ComponentTypeSchema = z.enum(["function", "class", "forwardRef", "memo"]);
|
|
10
8
|
var ComponentInfoSchema = z.object({
|
|
@@ -31,11 +29,6 @@ var DOMInfoSchema = z.object({
|
|
|
31
29
|
className: z.string().nullable(),
|
|
32
30
|
boundingRect: BoundingRectSchema
|
|
33
31
|
});
|
|
34
|
-
var ScreenshotSchema = z.object({
|
|
35
|
-
dataUrl: z.string(),
|
|
36
|
-
width: z.number(),
|
|
37
|
-
height: z.number()
|
|
38
|
-
});
|
|
39
32
|
var SelectionContextSchema = z.object({
|
|
40
33
|
pageUrl: z.string(),
|
|
41
34
|
parentComponents: z.array(z.string())
|
|
@@ -48,7 +41,6 @@ var SelectionDataSchema = z.object({
|
|
|
48
41
|
props: z.record(z.unknown()),
|
|
49
42
|
state: z.record(z.unknown()).nullable(),
|
|
50
43
|
dom: DOMInfoSchema,
|
|
51
|
-
screenshot: ScreenshotSchema,
|
|
52
44
|
context: SelectionContextSchema
|
|
53
45
|
});
|
|
54
46
|
var MessageTypeSchema = z.enum([
|
|
@@ -130,6 +122,7 @@ function useWebSocketClient(options) {
|
|
|
130
122
|
const reconnectTimeoutRef = useRef(null);
|
|
131
123
|
const pingIntervalRef = useRef(null);
|
|
132
124
|
const isCleaningUpRef = useRef(false);
|
|
125
|
+
const hasConnectedRef = useRef(false);
|
|
133
126
|
const [connected, setConnected] = useState(false);
|
|
134
127
|
const [clientId, setClientId] = useState(null);
|
|
135
128
|
const sendSelection = useCallback((data) => {
|
|
@@ -145,17 +138,21 @@ function useWebSocketClient(options) {
|
|
|
145
138
|
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
|
146
139
|
return;
|
|
147
140
|
}
|
|
141
|
+
let connectTimeoutId = null;
|
|
148
142
|
const connect = () => {
|
|
149
143
|
if (wsRef.current?.readyState === WebSocket.OPEN || isCleaningUpRef.current) {
|
|
150
144
|
return;
|
|
151
145
|
}
|
|
152
146
|
try {
|
|
153
147
|
const ws = new WebSocket(`ws://localhost:${port}`);
|
|
148
|
+
let wasIntentionallyClosed = false;
|
|
154
149
|
ws.onopen = () => {
|
|
155
150
|
if (isCleaningUpRef.current) {
|
|
151
|
+
wasIntentionallyClosed = true;
|
|
156
152
|
ws.close();
|
|
157
153
|
return;
|
|
158
154
|
}
|
|
155
|
+
hasConnectedRef.current = true;
|
|
159
156
|
console.log("[component-picker] Connected to server");
|
|
160
157
|
setConnected(true);
|
|
161
158
|
onConnectionChangeRef.current?.(true);
|
|
@@ -166,7 +163,9 @@ function useWebSocketClient(options) {
|
|
|
166
163
|
}, 25e3);
|
|
167
164
|
};
|
|
168
165
|
ws.onclose = () => {
|
|
169
|
-
|
|
166
|
+
if (hasConnectedRef.current && !wasIntentionallyClosed && !isCleaningUpRef.current) {
|
|
167
|
+
console.log("[component-picker] Disconnected from server");
|
|
168
|
+
}
|
|
170
169
|
setConnected(false);
|
|
171
170
|
setClientId(null);
|
|
172
171
|
onConnectionChangeRef.current?.(false);
|
|
@@ -212,7 +211,6 @@ function useWebSocketClient(options) {
|
|
|
212
211
|
};
|
|
213
212
|
wsRef.current = ws;
|
|
214
213
|
} catch (error) {
|
|
215
|
-
console.error("[component-picker] Failed to connect:", error);
|
|
216
214
|
if (!isCleaningUpRef.current) {
|
|
217
215
|
reconnectTimeoutRef.current = setTimeout(() => {
|
|
218
216
|
connect();
|
|
@@ -220,9 +218,18 @@ function useWebSocketClient(options) {
|
|
|
220
218
|
}
|
|
221
219
|
}
|
|
222
220
|
};
|
|
223
|
-
|
|
221
|
+
connectTimeoutId = setTimeout(() => {
|
|
222
|
+
connectTimeoutId = null;
|
|
223
|
+
if (!isCleaningUpRef.current) {
|
|
224
|
+
connect();
|
|
225
|
+
}
|
|
226
|
+
}, 100);
|
|
224
227
|
return () => {
|
|
225
228
|
isCleaningUpRef.current = true;
|
|
229
|
+
if (connectTimeoutId) {
|
|
230
|
+
clearTimeout(connectTimeoutId);
|
|
231
|
+
connectTimeoutId = null;
|
|
232
|
+
}
|
|
226
233
|
if (reconnectTimeoutRef.current) {
|
|
227
234
|
clearTimeout(reconnectTimeoutRef.current);
|
|
228
235
|
reconnectTimeoutRef.current = null;
|
|
@@ -232,7 +239,9 @@ function useWebSocketClient(options) {
|
|
|
232
239
|
pingIntervalRef.current = null;
|
|
233
240
|
}
|
|
234
241
|
if (wsRef.current) {
|
|
235
|
-
wsRef.current.
|
|
242
|
+
if (wsRef.current.readyState === WebSocket.OPEN || wsRef.current.readyState === WebSocket.CONNECTING) {
|
|
243
|
+
wsRef.current.close();
|
|
244
|
+
}
|
|
236
245
|
wsRef.current = null;
|
|
237
246
|
}
|
|
238
247
|
};
|
|
@@ -329,7 +338,7 @@ function useFiberInspector() {
|
|
|
329
338
|
return "function";
|
|
330
339
|
}
|
|
331
340
|
}, []);
|
|
332
|
-
const
|
|
341
|
+
const getComponentName = useCallback((fiber) => {
|
|
333
342
|
const type = fiber.type;
|
|
334
343
|
if (!type) return "Unknown";
|
|
335
344
|
if (typeof type === "function") {
|
|
@@ -349,7 +358,7 @@ function useFiberInspector() {
|
|
|
349
358
|
while (current) {
|
|
350
359
|
const tag = current.tag;
|
|
351
360
|
if (tag === FIBER_TAGS.FunctionComponent || tag === FIBER_TAGS.ClassComponent || tag === FIBER_TAGS.ForwardRef || tag === FIBER_TAGS.MemoComponent || tag === FIBER_TAGS.SimpleMemoComponent) {
|
|
352
|
-
const name =
|
|
361
|
+
const name = getComponentName(current);
|
|
353
362
|
if (!name.startsWith("_") && name !== "Unknown" && name !== "Anonymous") {
|
|
354
363
|
return current;
|
|
355
364
|
}
|
|
@@ -357,7 +366,7 @@ function useFiberInspector() {
|
|
|
357
366
|
current = current.return;
|
|
358
367
|
}
|
|
359
368
|
return null;
|
|
360
|
-
}, [
|
|
369
|
+
}, [getComponentName]);
|
|
361
370
|
const getParentComponents = useCallback(
|
|
362
371
|
(fiber) => {
|
|
363
372
|
const parents = [];
|
|
@@ -365,7 +374,7 @@ function useFiberInspector() {
|
|
|
365
374
|
while (current && parents.length < 10) {
|
|
366
375
|
const tag = current.tag;
|
|
367
376
|
if (tag === FIBER_TAGS.FunctionComponent || tag === FIBER_TAGS.ClassComponent || tag === FIBER_TAGS.ForwardRef || tag === FIBER_TAGS.MemoComponent || tag === FIBER_TAGS.SimpleMemoComponent) {
|
|
368
|
-
const name =
|
|
377
|
+
const name = getComponentName(current);
|
|
369
378
|
if (!name.startsWith("_") && name !== "Unknown") {
|
|
370
379
|
parents.push(name);
|
|
371
380
|
}
|
|
@@ -374,7 +383,7 @@ function useFiberInspector() {
|
|
|
374
383
|
}
|
|
375
384
|
return parents;
|
|
376
385
|
},
|
|
377
|
-
[
|
|
386
|
+
[getComponentName]
|
|
378
387
|
);
|
|
379
388
|
const serializeProps = useCallback((props) => {
|
|
380
389
|
const result = {};
|
|
@@ -416,7 +425,7 @@ function useFiberInspector() {
|
|
|
416
425
|
(fiber) => {
|
|
417
426
|
return {
|
|
418
427
|
componentInfo: {
|
|
419
|
-
name:
|
|
428
|
+
name: getComponentName(fiber),
|
|
420
429
|
type: getComponentType(fiber)
|
|
421
430
|
},
|
|
422
431
|
props: serializeProps(fiber.memoizedProps || {}),
|
|
@@ -429,7 +438,7 @@ function useFiberInspector() {
|
|
|
429
438
|
}
|
|
430
439
|
};
|
|
431
440
|
},
|
|
432
|
-
[
|
|
441
|
+
[getComponentName, getComponentType, serializeProps, extractState, getParentComponents]
|
|
433
442
|
);
|
|
434
443
|
return {
|
|
435
444
|
getFiberFromElement,
|
|
@@ -439,13 +448,12 @@ function useFiberInspector() {
|
|
|
439
448
|
}
|
|
440
449
|
function SelectionOverlay({
|
|
441
450
|
enabled,
|
|
442
|
-
message,
|
|
443
451
|
onSelect,
|
|
444
452
|
onCancel
|
|
445
453
|
}) {
|
|
446
454
|
const [highlight, setHighlight] = useState(null);
|
|
447
455
|
const hoveredElementRef = useRef(null);
|
|
448
|
-
const
|
|
456
|
+
const getComponentName = useCallback((element) => {
|
|
449
457
|
const fiberKey = Object.keys(element).find(
|
|
450
458
|
(k) => k.startsWith("__reactFiber$") || k.startsWith("__reactInternalInstance$")
|
|
451
459
|
);
|
|
@@ -503,10 +511,10 @@ function SelectionOverlay({
|
|
|
503
511
|
left: rect.left,
|
|
504
512
|
width: rect.width,
|
|
505
513
|
height: rect.height,
|
|
506
|
-
componentName:
|
|
514
|
+
componentName: getComponentName(target)
|
|
507
515
|
});
|
|
508
516
|
},
|
|
509
|
-
[enabled,
|
|
517
|
+
[enabled, getComponentName]
|
|
510
518
|
);
|
|
511
519
|
const handleClick = useCallback(
|
|
512
520
|
(event) => {
|
|
@@ -551,215 +559,46 @@ function SelectionOverlay({
|
|
|
551
559
|
};
|
|
552
560
|
}, [enabled, handleMouseMove, handleClick, handleKeyDown]);
|
|
553
561
|
if (!enabled) return null;
|
|
554
|
-
return /* @__PURE__ */
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
{
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
children: highlight.componentName
|
|
591
|
-
}
|
|
592
|
-
)
|
|
593
|
-
}
|
|
594
|
-
),
|
|
595
|
-
/* @__PURE__ */ jsxs(
|
|
596
|
-
"div",
|
|
597
|
-
{
|
|
598
|
-
"data-component-picker": "info-bar",
|
|
599
|
-
style: {
|
|
600
|
-
position: "fixed",
|
|
601
|
-
top: 0,
|
|
602
|
-
left: 0,
|
|
603
|
-
right: 0,
|
|
604
|
-
padding: "12px 16px",
|
|
605
|
-
backgroundColor: "#3b82f6",
|
|
606
|
-
color: "white",
|
|
607
|
-
fontFamily: "system-ui, sans-serif",
|
|
608
|
-
fontSize: "14px",
|
|
609
|
-
textAlign: "center",
|
|
610
|
-
zIndex: 999999,
|
|
611
|
-
display: "flex",
|
|
612
|
-
justifyContent: "center",
|
|
613
|
-
alignItems: "center",
|
|
614
|
-
gap: "16px",
|
|
615
|
-
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)"
|
|
616
|
-
},
|
|
617
|
-
children: [
|
|
618
|
-
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: message || "Click a component to select it" }),
|
|
619
|
-
/* @__PURE__ */ jsx("span", { style: { opacity: 0.8, fontSize: "12px" }, children: "Press ESC to cancel" })
|
|
620
|
-
]
|
|
621
|
-
}
|
|
622
|
-
)
|
|
623
|
-
] });
|
|
624
|
-
}
|
|
625
|
-
var sourceMapCache = /* @__PURE__ */ new Map();
|
|
626
|
-
var failedFetches = /* @__PURE__ */ new Set();
|
|
627
|
-
async function fetchSourceMap(scriptUrl) {
|
|
628
|
-
if (sourceMapCache.has(scriptUrl)) {
|
|
629
|
-
return sourceMapCache.get(scriptUrl) || null;
|
|
630
|
-
}
|
|
631
|
-
if (failedFetches.has(scriptUrl)) {
|
|
632
|
-
return null;
|
|
633
|
-
}
|
|
634
|
-
try {
|
|
635
|
-
const sourceMapUrl = await findSourceMapUrl(scriptUrl);
|
|
636
|
-
if (!sourceMapUrl) {
|
|
637
|
-
failedFetches.add(scriptUrl);
|
|
638
|
-
sourceMapCache.set(scriptUrl, null);
|
|
639
|
-
return null;
|
|
640
|
-
}
|
|
641
|
-
const response = await fetch(sourceMapUrl);
|
|
642
|
-
if (!response.ok) {
|
|
643
|
-
failedFetches.add(scriptUrl);
|
|
644
|
-
sourceMapCache.set(scriptUrl, null);
|
|
645
|
-
return null;
|
|
646
|
-
}
|
|
647
|
-
const sourceMapData = await response.json();
|
|
648
|
-
const consumer = new SourceMapConsumer(sourceMapData);
|
|
649
|
-
sourceMapCache.set(scriptUrl, consumer);
|
|
650
|
-
return consumer;
|
|
651
|
-
} catch (error) {
|
|
652
|
-
console.debug("[component-picker] Failed to fetch source map:", error);
|
|
653
|
-
failedFetches.add(scriptUrl);
|
|
654
|
-
sourceMapCache.set(scriptUrl, null);
|
|
655
|
-
return null;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
async function findSourceMapUrl(scriptUrl) {
|
|
659
|
-
try {
|
|
660
|
-
const scriptResponse = await fetch(scriptUrl);
|
|
661
|
-
if (scriptResponse.ok) {
|
|
662
|
-
const scriptContent = await scriptResponse.text();
|
|
663
|
-
const match = scriptContent.match(
|
|
664
|
-
/\/\/[#@]\s*sourceMappingURL=([^\s'"]+)/
|
|
665
|
-
);
|
|
666
|
-
if (match?.[1]) {
|
|
667
|
-
const mapUrl = match[1];
|
|
668
|
-
if (mapUrl.startsWith("data:")) {
|
|
669
|
-
return null;
|
|
670
|
-
}
|
|
671
|
-
return new URL(mapUrl, scriptUrl).href;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
const patterns = [
|
|
675
|
-
`${scriptUrl}.map`,
|
|
676
|
-
scriptUrl.replace(/\.js$/, ".js.map"),
|
|
677
|
-
scriptUrl.replace(/\.mjs$/, ".mjs.map")
|
|
678
|
-
];
|
|
679
|
-
for (const pattern of patterns) {
|
|
680
|
-
try {
|
|
681
|
-
const response = await fetch(pattern, { method: "HEAD" });
|
|
682
|
-
if (response.ok) {
|
|
683
|
-
return pattern;
|
|
684
|
-
}
|
|
685
|
-
} catch {
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
return null;
|
|
689
|
-
} catch {
|
|
690
|
-
return null;
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
function resolveSourcePath(sourcePath, scriptUrl) {
|
|
694
|
-
if (sourcePath.startsWith("webpack://")) {
|
|
695
|
-
const match = sourcePath.match(/webpack:\/\/(?:[^/]+)?\/\.?\/?(.+)/);
|
|
696
|
-
if (match?.[1]) {
|
|
697
|
-
return match[1];
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
if (sourcePath.startsWith("[project]/")) {
|
|
701
|
-
return sourcePath.replace("[project]/", "");
|
|
702
|
-
}
|
|
703
|
-
if (sourcePath.startsWith("./") || sourcePath.startsWith("../")) {
|
|
704
|
-
try {
|
|
705
|
-
const scriptDir = scriptUrl.substring(0, scriptUrl.lastIndexOf("/"));
|
|
706
|
-
const resolved = new URL(sourcePath, scriptDir + "/").pathname;
|
|
707
|
-
return resolved.replace(/^\//, "");
|
|
708
|
-
} catch {
|
|
709
|
-
return sourcePath;
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
if (sourcePath.startsWith("/")) {
|
|
713
|
-
return sourcePath.substring(1);
|
|
714
|
-
}
|
|
715
|
-
return sourcePath;
|
|
716
|
-
}
|
|
717
|
-
async function searchSourceMapsForComponent(componentName) {
|
|
718
|
-
const scripts = Array.from(document.querySelectorAll("script[src]")).map((s) => s.src).filter((src) => src && !src.includes("node_modules"));
|
|
719
|
-
const nextScripts = Array.from(
|
|
720
|
-
document.querySelectorAll('script[src*="/_next/"]')
|
|
721
|
-
).map((s) => s.src);
|
|
722
|
-
const allScripts = [.../* @__PURE__ */ new Set([...scripts, ...nextScripts])];
|
|
723
|
-
for (const scriptUrl of allScripts) {
|
|
724
|
-
const consumer = await fetchSourceMap(scriptUrl);
|
|
725
|
-
if (!consumer) continue;
|
|
726
|
-
const sources = consumer.sources || [];
|
|
727
|
-
for (const source of sources) {
|
|
728
|
-
const fileName = source.split("/").pop() || "";
|
|
729
|
-
const baseName = fileName.replace(/\.(tsx?|jsx?)$/, "");
|
|
730
|
-
if (baseName === componentName || fileName.toLowerCase().includes(componentName.toLowerCase())) {
|
|
731
|
-
try {
|
|
732
|
-
let firstMapping = null;
|
|
733
|
-
consumer.eachMapping((mapping) => {
|
|
734
|
-
if (mapping.source === source && !firstMapping) {
|
|
735
|
-
if (mapping.name === componentName && mapping.originalLine !== null && mapping.originalColumn !== null) {
|
|
736
|
-
firstMapping = {
|
|
737
|
-
line: mapping.originalLine,
|
|
738
|
-
column: mapping.originalColumn
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
if (firstMapping !== null) {
|
|
744
|
-
return {
|
|
745
|
-
source: resolveSourcePath(source, scriptUrl),
|
|
746
|
-
line: firstMapping.line,
|
|
747
|
-
column: firstMapping.column
|
|
748
|
-
};
|
|
749
|
-
}
|
|
750
|
-
if (baseName === componentName) {
|
|
751
|
-
return {
|
|
752
|
-
source: resolveSourcePath(source, scriptUrl),
|
|
753
|
-
line: 1,
|
|
754
|
-
column: 0
|
|
755
|
-
};
|
|
756
|
-
}
|
|
757
|
-
} catch {
|
|
562
|
+
return /* @__PURE__ */ jsx(Fragment, { children: highlight && /* @__PURE__ */ jsx(
|
|
563
|
+
"div",
|
|
564
|
+
{
|
|
565
|
+
"data-component-picker": "highlight",
|
|
566
|
+
style: {
|
|
567
|
+
position: "fixed",
|
|
568
|
+
top: highlight.top,
|
|
569
|
+
left: highlight.left,
|
|
570
|
+
width: highlight.width,
|
|
571
|
+
height: highlight.height,
|
|
572
|
+
border: "2px solid #3b82f6",
|
|
573
|
+
backgroundColor: "rgba(59, 130, 246, 0.1)",
|
|
574
|
+
pointerEvents: "none",
|
|
575
|
+
zIndex: 999998,
|
|
576
|
+
boxSizing: "border-box"
|
|
577
|
+
},
|
|
578
|
+
children: /* @__PURE__ */ jsx(
|
|
579
|
+
"div",
|
|
580
|
+
{
|
|
581
|
+
style: {
|
|
582
|
+
position: "absolute",
|
|
583
|
+
top: -24,
|
|
584
|
+
left: -2,
|
|
585
|
+
padding: "2px 8px",
|
|
586
|
+
backgroundColor: "#3b82f6",
|
|
587
|
+
color: "white",
|
|
588
|
+
fontSize: "12px",
|
|
589
|
+
fontFamily: "system-ui, sans-serif",
|
|
590
|
+
fontWeight: 500,
|
|
591
|
+
borderRadius: "4px 4px 0 0",
|
|
592
|
+
whiteSpace: "nowrap",
|
|
593
|
+
maxWidth: "300px",
|
|
594
|
+
overflow: "hidden",
|
|
595
|
+
textOverflow: "ellipsis"
|
|
596
|
+
},
|
|
597
|
+
children: highlight.componentName
|
|
758
598
|
}
|
|
759
|
-
|
|
599
|
+
)
|
|
760
600
|
}
|
|
761
|
-
}
|
|
762
|
-
return null;
|
|
601
|
+
) });
|
|
763
602
|
}
|
|
764
603
|
|
|
765
604
|
// src/utils/stackTraceParser.ts
|
|
@@ -834,15 +673,11 @@ function filterInternalFrames(frames) {
|
|
|
834
673
|
}
|
|
835
674
|
|
|
836
675
|
// src/utils/sourceLocationResolver.ts
|
|
837
|
-
async function resolveSourceLocation(fiber,
|
|
676
|
+
async function resolveSourceLocation(fiber, _element) {
|
|
838
677
|
const debugSourceResult = tryDebugSource(fiber);
|
|
839
678
|
if (debugSourceResult.filePath) {
|
|
840
679
|
return debugSourceResult;
|
|
841
680
|
}
|
|
842
|
-
const sourceMapResult = await trySourceMapResolution(fiber);
|
|
843
|
-
if (sourceMapResult?.filePath) {
|
|
844
|
-
return sourceMapResult;
|
|
845
|
-
}
|
|
846
681
|
const stackResult = tryStackTraceParsing();
|
|
847
682
|
if (stackResult?.filePath) {
|
|
848
683
|
return stackResult;
|
|
@@ -854,11 +689,6 @@ async function resolveSourceLocation(fiber, element) {
|
|
|
854
689
|
};
|
|
855
690
|
}
|
|
856
691
|
function tryDebugSource(fiber) {
|
|
857
|
-
if (fiber) {
|
|
858
|
-
console.log("[component-picker] Fiber keys:", Object.keys(fiber));
|
|
859
|
-
console.log("[component-picker] _debugSource:", fiber._debugSource);
|
|
860
|
-
console.log("[component-picker] _debugInfo:", fiber._debugInfo);
|
|
861
|
-
}
|
|
862
692
|
if (!fiber?._debugSource) {
|
|
863
693
|
return { filePath: null, lineNumber: null, columnNumber: null };
|
|
864
694
|
}
|
|
@@ -872,26 +702,6 @@ function tryDebugSource(fiber) {
|
|
|
872
702
|
columnNumber: columnNumber ?? null
|
|
873
703
|
};
|
|
874
704
|
}
|
|
875
|
-
async function trySourceMapResolution(fiber, _element) {
|
|
876
|
-
try {
|
|
877
|
-
const componentName = fiber?.type ? getComponentName(fiber.type) : null;
|
|
878
|
-
if (!componentName) {
|
|
879
|
-
return null;
|
|
880
|
-
}
|
|
881
|
-
const result = await searchSourceMapsForComponent(componentName);
|
|
882
|
-
if (!result) {
|
|
883
|
-
return null;
|
|
884
|
-
}
|
|
885
|
-
return {
|
|
886
|
-
filePath: formatFilePath(result.source),
|
|
887
|
-
lineNumber: result.line,
|
|
888
|
-
columnNumber: result.column
|
|
889
|
-
};
|
|
890
|
-
} catch (error) {
|
|
891
|
-
console.debug("[component-picker] Source map resolution failed:", error);
|
|
892
|
-
return null;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
705
|
function tryStackTraceParsing() {
|
|
896
706
|
try {
|
|
897
707
|
const error = new Error();
|
|
@@ -914,17 +724,6 @@ function tryStackTraceParsing() {
|
|
|
914
724
|
return null;
|
|
915
725
|
}
|
|
916
726
|
}
|
|
917
|
-
function getComponentName(type) {
|
|
918
|
-
if (!type) return null;
|
|
919
|
-
if (typeof type === "function") {
|
|
920
|
-
return type.displayName || type.name || null;
|
|
921
|
-
}
|
|
922
|
-
if (typeof type === "object" && type !== null) {
|
|
923
|
-
const obj = type;
|
|
924
|
-
return obj.displayName || obj.render?.displayName || obj.render?.name || null;
|
|
925
|
-
}
|
|
926
|
-
return null;
|
|
927
|
-
}
|
|
928
727
|
function extractFilePathFromUrl(url) {
|
|
929
728
|
try {
|
|
930
729
|
const urlObj = new URL(url);
|
|
@@ -946,67 +745,6 @@ function formatFilePath(filePath) {
|
|
|
946
745
|
cleaned = cleaned.replace(/\\/g, "/");
|
|
947
746
|
return cleaned;
|
|
948
747
|
}
|
|
949
|
-
var DEFAULT_OPTIONS = {
|
|
950
|
-
maxWidth: 800,
|
|
951
|
-
maxHeight: 600,
|
|
952
|
-
backgroundColor: "#ffffff",
|
|
953
|
-
pixelRatio: 1,
|
|
954
|
-
padding: 10
|
|
955
|
-
};
|
|
956
|
-
async function captureScreenshot(element, options = {}) {
|
|
957
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
958
|
-
try {
|
|
959
|
-
const rect = element.getBoundingClientRect();
|
|
960
|
-
const width = Math.min(rect.width + opts.padding * 2, opts.maxWidth);
|
|
961
|
-
const height = Math.min(rect.height + opts.padding * 2, opts.maxHeight);
|
|
962
|
-
const dataUrl = await toPng(element, {
|
|
963
|
-
backgroundColor: opts.backgroundColor,
|
|
964
|
-
pixelRatio: opts.pixelRatio,
|
|
965
|
-
width: rect.width,
|
|
966
|
-
height: rect.height,
|
|
967
|
-
style: {
|
|
968
|
-
margin: "0",
|
|
969
|
-
padding: "0"
|
|
970
|
-
},
|
|
971
|
-
filter: (node) => {
|
|
972
|
-
if (node instanceof Element) {
|
|
973
|
-
if (node.hasAttribute("data-component-picker")) {
|
|
974
|
-
return false;
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
return true;
|
|
978
|
-
}
|
|
979
|
-
});
|
|
980
|
-
return {
|
|
981
|
-
dataUrl,
|
|
982
|
-
width: Math.round(width),
|
|
983
|
-
height: Math.round(height)
|
|
984
|
-
};
|
|
985
|
-
} catch (error) {
|
|
986
|
-
console.error("[component-picker] Screenshot capture failed:", error);
|
|
987
|
-
return {
|
|
988
|
-
dataUrl: createFallbackScreenshot(element),
|
|
989
|
-
width: 200,
|
|
990
|
-
height: 100
|
|
991
|
-
};
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
function createFallbackScreenshot(element) {
|
|
995
|
-
const canvas = document.createElement("canvas");
|
|
996
|
-
canvas.width = 200;
|
|
997
|
-
canvas.height = 100;
|
|
998
|
-
const ctx = canvas.getContext("2d");
|
|
999
|
-
if (ctx) {
|
|
1000
|
-
ctx.fillStyle = "#f0f0f0";
|
|
1001
|
-
ctx.fillRect(0, 0, 200, 100);
|
|
1002
|
-
ctx.fillStyle = "#666";
|
|
1003
|
-
ctx.font = "12px sans-serif";
|
|
1004
|
-
ctx.textAlign = "center";
|
|
1005
|
-
ctx.fillText("Screenshot unavailable", 100, 45);
|
|
1006
|
-
ctx.fillText(element.tagName.toLowerCase(), 100, 65);
|
|
1007
|
-
}
|
|
1008
|
-
return canvas.toDataURL("image/png");
|
|
1009
|
-
}
|
|
1010
748
|
|
|
1011
749
|
// src/utils/componentMetadata.ts
|
|
1012
750
|
function extractDOMInfo(element) {
|
|
@@ -1031,7 +769,6 @@ async function buildSelectionData(element, fiberData, options = {}) {
|
|
|
1031
769
|
_debugSource: fiberData.debugSource
|
|
1032
770
|
};
|
|
1033
771
|
const source = await resolveSourceLocation(fiber);
|
|
1034
|
-
const screenshot = await captureScreenshot(element, options.screenshotOptions);
|
|
1035
772
|
const selectionData = {
|
|
1036
773
|
id: nanoid(),
|
|
1037
774
|
timestamp: Date.now(),
|
|
@@ -1044,7 +781,6 @@ async function buildSelectionData(element, fiberData, options = {}) {
|
|
|
1044
781
|
props: fiberData.props,
|
|
1045
782
|
state: fiberData.state,
|
|
1046
783
|
dom: extractDOMInfo(element),
|
|
1047
|
-
screenshot,
|
|
1048
784
|
context: {
|
|
1049
785
|
pageUrl: window.location.href,
|
|
1050
786
|
parentComponents: fiberData.parentComponents
|
|
@@ -1135,7 +871,6 @@ function ComponentPickerImpl({
|
|
|
1135
871
|
SelectionOverlay,
|
|
1136
872
|
{
|
|
1137
873
|
enabled: isSelectionMode,
|
|
1138
|
-
message: selectionMessage,
|
|
1139
874
|
onSelect: handleSelect,
|
|
1140
875
|
onCancel: disableSelectionMode
|
|
1141
876
|
}
|
|
@@ -1157,7 +892,7 @@ function ComponentPickerImpl({
|
|
|
1157
892
|
bottom: 16,
|
|
1158
893
|
right: 16,
|
|
1159
894
|
padding: "8px 12px",
|
|
1160
|
-
backgroundColor: !connected ? "#ef4444" : isSelectionMode ? "#
|
|
895
|
+
backgroundColor: !connected ? "#ef4444" : isSelectionMode ? "#3b82f6" : "#22c55e",
|
|
1161
896
|
color: "white",
|
|
1162
897
|
borderRadius: "9999px",
|
|
1163
898
|
fontSize: "12px",
|
|
@@ -1182,11 +917,14 @@ function ComponentPickerImpl({
|
|
|
1182
917
|
height: 8,
|
|
1183
918
|
borderRadius: "50%",
|
|
1184
919
|
backgroundColor: "white",
|
|
1185
|
-
animation: !connected ? "pulse 2s infinite" : "none"
|
|
920
|
+
animation: !connected ? "pulse 2s infinite" : isSelectionMode ? "pulse 1s infinite" : "none"
|
|
1186
921
|
}
|
|
1187
922
|
}
|
|
1188
923
|
),
|
|
1189
|
-
!connected ? "Connecting..." : isSelectionMode ? "
|
|
924
|
+
!connected ? "Connecting..." : isSelectionMode ? /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
925
|
+
/* @__PURE__ */ jsx("span", { children: selectionMessage || "Click a component" }),
|
|
926
|
+
/* @__PURE__ */ jsx("span", { style: { opacity: 0.7, fontSize: "10px" }, children: "ESC to cancel" })
|
|
927
|
+
] }) : "Select Component"
|
|
1190
928
|
]
|
|
1191
929
|
}
|
|
1192
930
|
)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../shared/src/schemas.ts","../../shared/src/messages.ts","../src/hooks/useWebSocketClient.ts","../src/hooks/useKeyboardShortcut.ts","../src/hooks/useSelectionMode.ts","../src/hooks/useFiberInspector.ts","../src/SelectionOverlay.tsx","../src/utils/sourceMapClient.ts","../src/utils/stackTraceParser.ts","../src/utils/sourceLocationResolver.ts","../src/utils/screenshotCapture.ts","../src/utils/componentMetadata.ts","../src/ComponentPicker.tsx"],"names":["z","useCallback","useEffect","useState","getComponentName","useRef","jsx","jsxs","Fragment"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\n\nexport const ComponentTypeSchema = z.enum(['function', 'class', 'forwardRef', 'memo']);\n\nexport const ComponentInfoSchema = z.object({\n name: z.string(),\n type: ComponentTypeSchema,\n});\n\nexport const SourceLocationSchema = z.object({\n filePath: z.string().nullable(),\n lineNumber: z.number().nullable(),\n columnNumber: z.number().nullable(),\n});\n\nexport const BoundingRectSchema = z.object({\n x: z.number(),\n y: z.number(),\n width: z.number(),\n height: z.number(),\n top: z.number(),\n right: z.number(),\n bottom: z.number(),\n left: z.number(),\n});\n\nexport const DOMInfoSchema = z.object({\n tagName: z.string(),\n className: z.string().nullable(),\n boundingRect: BoundingRectSchema,\n});\n\nexport const ScreenshotSchema = z.object({\n dataUrl: z.string(),\n width: z.number(),\n height: z.number(),\n});\n\nexport const SelectionContextSchema = z.object({\n pageUrl: z.string(),\n parentComponents: z.array(z.string()),\n});\n\nexport const SelectionDataSchema = z.object({\n id: z.string(),\n timestamp: z.number(),\n component: ComponentInfoSchema,\n source: SourceLocationSchema,\n props: z.record(z.unknown()),\n state: z.record(z.unknown()).nullable(),\n dom: DOMInfoSchema,\n screenshot: ScreenshotSchema,\n context: SelectionContextSchema,\n});\n\nexport type SelectionDataInput = z.infer<typeof SelectionDataSchema>;\n","import { z } from 'zod';\nimport { SelectionDataSchema } from './schemas.js';\n\n/**\n * WebSocket message types for browser <-> CLI communication\n */\n\n// Message type enum\nexport const MessageTypeSchema = z.enum([\n 'selection',\n 'ping',\n 'pong',\n 'connect',\n 'disconnect',\n 'error',\n 'selectionMode',\n]);\n\nexport type MessageType = z.infer<typeof MessageTypeSchema>;\n\n// Base message structure\nconst BaseMessageSchema = z.object({\n type: MessageTypeSchema,\n timestamp: z.number(),\n});\n\n// Selection message - browser -> CLI\nexport const SelectionMessageSchema = BaseMessageSchema.extend({\n type: z.literal('selection'),\n payload: SelectionDataSchema,\n});\n\n// Ping/Pong for keepalive\nexport const PingMessageSchema = BaseMessageSchema.extend({\n type: z.literal('ping'),\n});\n\nexport const PongMessageSchema = BaseMessageSchema.extend({\n type: z.literal('pong'),\n});\n\n// Connection status messages\nexport const ConnectMessageSchema = BaseMessageSchema.extend({\n type: z.literal('connect'),\n payload: z.object({\n clientId: z.string(),\n userAgent: z.string().optional(),\n }),\n});\n\nexport const DisconnectMessageSchema = BaseMessageSchema.extend({\n type: z.literal('disconnect'),\n payload: z.object({\n clientId: z.string(),\n reason: z.string().optional(),\n }),\n});\n\n// Error message\nexport const ErrorMessageSchema = BaseMessageSchema.extend({\n type: z.literal('error'),\n payload: z.object({\n code: z.string(),\n message: z.string(),\n }),\n});\n\n// Selection mode toggle - CLI -> browser\nexport const SelectionModeMessageSchema = BaseMessageSchema.extend({\n type: z.literal('selectionMode'),\n payload: z.object({\n enabled: z.boolean(),\n message: z.string().optional(),\n }),\n});\n\n// Union of all message types\nexport const WebSocketMessageSchema = z.discriminatedUnion('type', [\n SelectionMessageSchema,\n PingMessageSchema,\n PongMessageSchema,\n ConnectMessageSchema,\n DisconnectMessageSchema,\n ErrorMessageSchema,\n SelectionModeMessageSchema,\n]);\n\nexport type WebSocketMessage = z.infer<typeof WebSocketMessageSchema>;\nexport type SelectionMessage = z.infer<typeof SelectionMessageSchema>;\nexport type PingMessage = z.infer<typeof PingMessageSchema>;\nexport type PongMessage = z.infer<typeof PongMessageSchema>;\nexport type ConnectMessage = z.infer<typeof ConnectMessageSchema>;\nexport type DisconnectMessage = z.infer<typeof DisconnectMessageSchema>;\nexport type ErrorMessage = z.infer<typeof ErrorMessageSchema>;\nexport type SelectionModeMessage = z.infer<typeof SelectionModeMessageSchema>;\n\n// Helper to create messages with overloads for type safety\nexport function createMessage(type: 'ping'): PingMessage;\nexport function createMessage(type: 'pong'): PongMessage;\nexport function createMessage(type: 'selection', payload: SelectionMessage['payload']): SelectionMessage;\nexport function createMessage(type: 'connect', payload: ConnectMessage['payload']): ConnectMessage;\nexport function createMessage(type: 'disconnect', payload: DisconnectMessage['payload']): DisconnectMessage;\nexport function createMessage(type: 'error', payload: ErrorMessage['payload']): ErrorMessage;\nexport function createMessage(type: 'selectionMode', payload: SelectionModeMessage['payload']): SelectionModeMessage;\nexport function createMessage(type: MessageType, payload?: unknown): WebSocketMessage {\n const base = { type, timestamp: Date.now() };\n if (payload !== undefined) {\n return { ...base, payload } as WebSocketMessage;\n }\n return base as WebSocketMessage;\n}\n","import { useEffect, useRef, useState, useCallback } from 'react';\nimport {\n WebSocketMessageSchema,\n createMessage,\n type SelectionData,\n type SelectionModeMessage,\n} from '@react-component-selector-mcp/shared';\n\nexport interface UseWebSocketClientOptions {\n port: number;\n onSelectionModeChange?: (enabled: boolean, message?: string) => void;\n onConnectionChange?: (connected: boolean) => void;\n}\n\nexport interface UseWebSocketClientReturn {\n connected: boolean;\n sendSelection: (data: SelectionData) => void;\n clientId: string | null;\n}\n\nexport function useWebSocketClient(\n options: UseWebSocketClientOptions\n): UseWebSocketClientReturn {\n const { port } = options;\n\n // Use refs for callbacks to avoid re-triggering effects\n const onSelectionModeChangeRef = useRef(options.onSelectionModeChange);\n const onConnectionChangeRef = useRef(options.onConnectionChange);\n onSelectionModeChangeRef.current = options.onSelectionModeChange;\n onConnectionChangeRef.current = options.onConnectionChange;\n\n const wsRef = useRef<WebSocket | null>(null);\n const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isCleaningUpRef = useRef(false);\n\n const [connected, setConnected] = useState(false);\n const [clientId, setClientId] = useState<string | null>(null);\n\n const sendSelection = useCallback((data: SelectionData) => {\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n const message = createMessage('selection', data);\n wsRef.current.send(JSON.stringify(message));\n } else {\n console.warn('[component-picker] Cannot send selection - not connected');\n }\n }, []);\n\n useEffect(() => {\n // Reset cleanup flag on mount\n isCleaningUpRef.current = false;\n\n // Prevent running if already connected\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n return;\n }\n\n const connect = () => {\n if (wsRef.current?.readyState === WebSocket.OPEN || isCleaningUpRef.current) {\n return;\n }\n\n try {\n const ws = new WebSocket(`ws://localhost:${port}`);\n\n ws.onopen = () => {\n if (isCleaningUpRef.current) {\n ws.close();\n return;\n }\n console.log('[component-picker] Connected to server');\n setConnected(true);\n onConnectionChangeRef.current?.(true);\n\n // Start ping interval\n pingIntervalRef.current = setInterval(() => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(createMessage('ping')));\n }\n }, 25000);\n };\n\n ws.onclose = () => {\n console.log('[component-picker] Disconnected from server');\n setConnected(false);\n setClientId(null);\n onConnectionChangeRef.current?.(false);\n\n if (pingIntervalRef.current) {\n clearInterval(pingIntervalRef.current);\n pingIntervalRef.current = null;\n }\n\n // Only attempt reconnection if not cleaning up\n if (!isCleaningUpRef.current) {\n reconnectTimeoutRef.current = setTimeout(() => {\n connect();\n }, 3000);\n }\n };\n\n ws.onerror = () => {\n // Error is logged but we don't need to do anything special\n // onclose will be called after onerror\n };\n\n ws.onmessage = (event: MessageEvent) => {\n try {\n const parsed = JSON.parse(event.data);\n const result = WebSocketMessageSchema.safeParse(parsed);\n\n if (!result.success) {\n console.warn('[component-picker] Invalid message:', result.error);\n return;\n }\n\n const message = result.data;\n\n switch (message.type) {\n case 'connect':\n setClientId(message.payload.clientId);\n break;\n\n case 'selectionMode':\n onSelectionModeChangeRef.current?.(\n (message as SelectionModeMessage).payload.enabled,\n (message as SelectionModeMessage).payload.message\n );\n break;\n\n case 'pong':\n // Keepalive acknowledged\n break;\n\n default:\n break;\n }\n } catch (error) {\n console.error('[component-picker] Error handling message:', error);\n }\n };\n\n wsRef.current = ws;\n } catch (error) {\n console.error('[component-picker] Failed to connect:', error);\n\n // Retry connection if not cleaning up\n if (!isCleaningUpRef.current) {\n reconnectTimeoutRef.current = setTimeout(() => {\n connect();\n }, 3000);\n }\n }\n };\n\n connect();\n\n return () => {\n isCleaningUpRef.current = true;\n\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current);\n reconnectTimeoutRef.current = null;\n }\n if (pingIntervalRef.current) {\n clearInterval(pingIntervalRef.current);\n pingIntervalRef.current = null;\n }\n if (wsRef.current) {\n wsRef.current.close();\n wsRef.current = null;\n }\n };\n }, [port]); // Only depend on port\n\n return {\n connected,\n sendSelection,\n clientId,\n };\n}\n","import { useEffect, useCallback } from 'react';\n\nexport interface UseKeyboardShortcutOptions {\n /** Key to press with modifiers (default: 'C') */\n key?: string;\n /** Callback when shortcut is triggered */\n onTrigger: () => void;\n /** Whether the shortcut is enabled */\n enabled?: boolean;\n}\n\n/**\n * Hook to handle Ctrl+Alt+C (Windows/Linux) / Cmd+Option+C (Mac) keyboard shortcut\n */\nexport function useKeyboardShortcut(options: UseKeyboardShortcutOptions): void {\n const { key = 'C', onTrigger, enabled = true } = options;\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (!enabled) return;\n\n // Check for Ctrl+Alt+C (Windows/Linux) or Cmd+Option+C (Mac)\n const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n const modifierKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (modifierKey && event.altKey && event.key.toUpperCase() === key.toUpperCase()) {\n event.preventDefault();\n event.stopPropagation();\n onTrigger();\n }\n },\n [key, onTrigger, enabled]\n );\n\n useEffect(() => {\n if (!enabled) return;\n\n window.addEventListener('keydown', handleKeyDown, true);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown, true);\n };\n }, [handleKeyDown, enabled]);\n}\n","import { useState, useCallback } from 'react';\n\nexport interface UseSelectionModeReturn {\n isSelectionMode: boolean;\n selectionMessage: string | undefined;\n enableSelectionMode: (message?: string) => void;\n disableSelectionMode: () => void;\n toggleSelectionMode: () => void;\n}\n\n/**\n * Hook to manage selection mode state\n */\nexport function useSelectionMode(): UseSelectionModeReturn {\n const [isSelectionMode, setIsSelectionMode] = useState(false);\n const [selectionMessage, setSelectionMessage] = useState<string | undefined>();\n\n const enableSelectionMode = useCallback((message?: string) => {\n setIsSelectionMode(true);\n setSelectionMessage(message);\n }, []);\n\n const disableSelectionMode = useCallback(() => {\n setIsSelectionMode(false);\n setSelectionMessage(undefined);\n }, []);\n\n const toggleSelectionMode = useCallback(() => {\n setIsSelectionMode((prev) => !prev);\n if (isSelectionMode) {\n setSelectionMessage(undefined);\n }\n }, [isSelectionMode]);\n\n return {\n isSelectionMode,\n selectionMessage,\n enableSelectionMode,\n disableSelectionMode,\n toggleSelectionMode,\n };\n}\n","import { useCallback } from 'react';\nimport type { ComponentInfo, ComponentType } from '@react-component-selector-mcp/shared';\n\n// React Fiber types (internal)\ninterface Fiber {\n tag: number;\n type: unknown;\n stateNode: unknown;\n return: Fiber | null;\n memoizedProps: Record<string, unknown>;\n memoizedState: unknown;\n _debugSource?: {\n fileName: string;\n lineNumber: number;\n columnNumber?: number;\n };\n}\n\n// React DevTools global hook\ninterface ReactDevToolsHook {\n renderers?: Map<number, {\n findFiberByHostInstance?: (element: Element) => Fiber | null;\n }>;\n}\n\ndeclare global {\n interface Window {\n __REACT_DEVTOOLS_GLOBAL_HOOK__?: ReactDevToolsHook;\n }\n}\n\n// React Fiber tags\nconst FIBER_TAGS = {\n FunctionComponent: 0,\n ClassComponent: 1,\n ForwardRef: 11,\n MemoComponent: 14,\n SimpleMemoComponent: 15,\n} as const;\n\nexport interface FiberData {\n componentInfo: ComponentInfo;\n props: Record<string, unknown>;\n state: Record<string, unknown> | null;\n parentComponents: string[];\n debugSource: {\n fileName: string | null;\n lineNumber: number | null;\n columnNumber: number | null;\n };\n}\n\nexport interface UseFiberInspectorReturn {\n getFiberFromElement: (element: HTMLElement) => Fiber | null;\n extractFiberData: (fiber: Fiber) => FiberData;\n findNearestComponentFiber: (fiber: Fiber) => Fiber | null;\n}\n\n/**\n * Hook for inspecting React Fiber internals\n */\nexport function useFiberInspector(): UseFiberInspectorReturn {\n /**\n * Get React Fiber from DOM element\n */\n const getFiberFromElement = useCallback((element: HTMLElement): Fiber | null => {\n // Try DevTools hook first (most reliable)\n if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__?.renderers) {\n for (const renderer of window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.values()) {\n const fiber = renderer.findFiberByHostInstance?.(element);\n if (fiber) return fiber;\n }\n }\n\n // Fallback to internal keys\n const fiberKey = Object.keys(element).find(\n (key) => key.startsWith('__reactFiber$') || key.startsWith('__reactInternalInstance$')\n );\n\n if (fiberKey) {\n const fiber = (element as unknown as Record<string, Fiber | undefined>)[fiberKey];\n return fiber ?? null;\n }\n\n return null;\n }, []);\n\n /**\n * Get component type from fiber tag\n */\n const getComponentType = useCallback((fiber: Fiber): ComponentType => {\n switch (fiber.tag) {\n case FIBER_TAGS.ClassComponent:\n return 'class';\n case FIBER_TAGS.ForwardRef:\n return 'forwardRef';\n case FIBER_TAGS.MemoComponent:\n case FIBER_TAGS.SimpleMemoComponent:\n return 'memo';\n case FIBER_TAGS.FunctionComponent:\n default:\n return 'function';\n }\n }, []);\n\n /**\n * Get component name from fiber\n */\n const getComponentName = useCallback((fiber: Fiber): string => {\n const type = fiber.type;\n\n if (!type) return 'Unknown';\n\n // Function or class component\n if (typeof type === 'function') {\n const fn = type as { displayName?: string; name?: string };\n return fn.displayName || fn.name || 'Anonymous';\n }\n\n // ForwardRef\n if (typeof type === 'object' && type !== null) {\n const obj = type as { displayName?: string; render?: { displayName?: string; name?: string }; type?: { displayName?: string; name?: string } };\n\n if (obj.displayName) return obj.displayName;\n if (obj.render) return obj.render.displayName || obj.render.name || 'ForwardRef';\n if (obj.type) return obj.type.displayName || obj.type.name || 'Memo';\n }\n\n return 'Unknown';\n }, []);\n\n /**\n * Find the nearest user-defined component fiber (skip host/native elements)\n */\n const findNearestComponentFiber = useCallback((fiber: Fiber): Fiber | null => {\n let current: Fiber | null = fiber;\n\n while (current) {\n // Check if it's a user component (function, class, forwardRef, memo)\n const tag = current.tag;\n if (\n tag === FIBER_TAGS.FunctionComponent ||\n tag === FIBER_TAGS.ClassComponent ||\n tag === FIBER_TAGS.ForwardRef ||\n tag === FIBER_TAGS.MemoComponent ||\n tag === FIBER_TAGS.SimpleMemoComponent\n ) {\n const name = getComponentName(current);\n // Skip internal React components\n if (!name.startsWith('_') && name !== 'Unknown' && name !== 'Anonymous') {\n return current;\n }\n }\n\n current = current.return;\n }\n\n return null;\n }, [getComponentName]);\n\n /**\n * Get parent component names from fiber tree\n */\n const getParentComponents = useCallback(\n (fiber: Fiber): string[] => {\n const parents: string[] = [];\n let current = fiber.return;\n\n while (current && parents.length < 10) {\n const tag = current.tag;\n if (\n tag === FIBER_TAGS.FunctionComponent ||\n tag === FIBER_TAGS.ClassComponent ||\n tag === FIBER_TAGS.ForwardRef ||\n tag === FIBER_TAGS.MemoComponent ||\n tag === FIBER_TAGS.SimpleMemoComponent\n ) {\n const name = getComponentName(current);\n if (!name.startsWith('_') && name !== 'Unknown') {\n parents.push(name);\n }\n }\n current = current.return;\n }\n\n return parents;\n },\n [getComponentName]\n );\n\n /**\n * Safely serialize props (handle circular refs, functions, etc.)\n */\n const serializeProps = useCallback((props: Record<string, unknown>): Record<string, unknown> => {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(props)) {\n // Skip React internal props\n if (key === 'children' || key === 'key' || key === 'ref') continue;\n\n try {\n if (typeof value === 'function') {\n result[key] = '[Function]';\n } else if (value instanceof Element) {\n result[key] = '[Element]';\n } else if (typeof value === 'object' && value !== null) {\n // Attempt JSON serialization to check for circular refs\n JSON.stringify(value);\n result[key] = value;\n } else {\n result[key] = value;\n }\n } catch {\n result[key] = '[Circular or Unserializable]';\n }\n }\n\n return result;\n }, []);\n\n /**\n * Extract state from class component\n */\n const extractState = useCallback((fiber: Fiber): Record<string, unknown> | null => {\n if (fiber.tag !== FIBER_TAGS.ClassComponent) {\n return null;\n }\n\n const instance = fiber.stateNode as { state?: Record<string, unknown> } | null;\n if (instance?.state) {\n try {\n JSON.stringify(instance.state);\n return instance.state;\n } catch {\n return { error: '[Unserializable state]' };\n }\n }\n\n return null;\n }, []);\n\n /**\n * Extract all relevant data from a fiber\n */\n const extractFiberData = useCallback(\n (fiber: Fiber): FiberData => {\n return {\n componentInfo: {\n name: getComponentName(fiber),\n type: getComponentType(fiber),\n },\n props: serializeProps(fiber.memoizedProps || {}),\n state: extractState(fiber),\n parentComponents: getParentComponents(fiber),\n debugSource: {\n fileName: fiber._debugSource?.fileName ?? null,\n lineNumber: fiber._debugSource?.lineNumber ?? null,\n columnNumber: fiber._debugSource?.columnNumber ?? null,\n },\n };\n },\n [getComponentName, getComponentType, serializeProps, extractState, getParentComponents]\n );\n\n return {\n getFiberFromElement,\n extractFiberData,\n findNearestComponentFiber,\n };\n}\n","import React, { useEffect, useState, useCallback, useRef } from 'react';\n\nexport interface SelectionOverlayProps {\n enabled: boolean;\n message?: string;\n onSelect: (element: HTMLElement) => void;\n onCancel: () => void;\n}\n\ninterface HighlightRect {\n top: number;\n left: number;\n width: number;\n height: number;\n componentName: string;\n}\n\n/**\n * Overlay component that highlights elements on hover and captures clicks\n */\nexport function SelectionOverlay({\n enabled,\n message,\n onSelect,\n onCancel,\n}: SelectionOverlayProps): React.ReactElement | null {\n const [highlight, setHighlight] = useState<HighlightRect | null>(null);\n const hoveredElementRef = useRef<HTMLElement | null>(null);\n\n // Get display name from element (prefer React component name, then className + text)\n const getComponentName = useCallback((element: HTMLElement): string => {\n // Try to get React component name from fiber first\n const fiberKey = Object.keys(element).find(\n (k) => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n\n let reactName: string | null = null;\n if (fiberKey) {\n const fiber = (element as unknown as Record<string, unknown>)[fiberKey] as {\n type?: { displayName?: string; name?: string } | string;\n return?: { type?: { displayName?: string; name?: string } };\n };\n\n // Check current fiber\n if (fiber?.type && typeof fiber.type === 'function') {\n const fn = fiber.type as { displayName?: string; name?: string };\n reactName = fn.displayName || fn.name || null;\n }\n\n // Walk up to find nearest named component\n if (!reactName || reactName === 'div' || reactName === 'button') {\n let current = fiber;\n while (current?.return) {\n current = current.return as typeof fiber;\n if (current?.type && typeof current.type === 'function') {\n const fn = current.type as { displayName?: string; name?: string };\n const name = fn.displayName || fn.name;\n if (name && !['Fragment', 'Suspense', 'Provider', 'Consumer'].includes(name)) {\n reactName = name;\n break;\n }\n }\n }\n }\n }\n\n // Get text content for context (truncated)\n const textContent = element.textContent?.trim().slice(0, 20) || '';\n const textSuffix = textContent ? ` \"${textContent}${element.textContent && element.textContent.length > 20 ? '...' : ''}\"` : '';\n\n // If we found a React component name, use it\n if (reactName && !['div', 'button', 'span', 'p', 'h1', 'h2', 'h3'].includes(reactName.toLowerCase())) {\n return `<${reactName}>${textSuffix}`;\n }\n\n // Fall back to className with text\n if (element.className && typeof element.className === 'string' && element.className.trim()) {\n const classes = element.className.trim().split(/\\s+/)[0]; // Just first class\n return `.${classes}${textSuffix}`;\n }\n\n // Last resort: tag name with text\n return `<${element.tagName.toLowerCase()}>${textSuffix}`;\n }, []);\n\n // Handle mouse movement\n const handleMouseMove = useCallback(\n (event: MouseEvent) => {\n if (!enabled) return;\n\n const target = event.target as HTMLElement;\n\n // Skip our own overlay elements\n if (target.closest('[data-component-picker]')) {\n setHighlight(null);\n hoveredElementRef.current = null;\n return;\n }\n\n // Skip html, body, and script elements\n if (['HTML', 'BODY', 'SCRIPT', 'STYLE', 'NOSCRIPT'].includes(target.tagName)) {\n setHighlight(null);\n hoveredElementRef.current = null;\n return;\n }\n\n const rect = target.getBoundingClientRect();\n hoveredElementRef.current = target;\n\n setHighlight({\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n componentName: getComponentName(target),\n });\n },\n [enabled, getComponentName]\n );\n\n // Handle click\n const handleClick = useCallback(\n (event: MouseEvent) => {\n if (!enabled) return;\n\n const target = event.target as HTMLElement;\n\n // Skip our own overlay elements\n if (target.closest('[data-component-picker]')) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n if (hoveredElementRef.current) {\n onSelect(hoveredElementRef.current);\n }\n },\n [enabled, onSelect]\n );\n\n // Handle escape key\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (!enabled) return;\n\n if (event.key === 'Escape') {\n event.preventDefault();\n onCancel();\n }\n },\n [enabled, onCancel]\n );\n\n // Add event listeners\n useEffect(() => {\n if (!enabled) {\n setHighlight(null);\n hoveredElementRef.current = null;\n return;\n }\n\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.addEventListener('keydown', handleKeyDown, true);\n\n // Change cursor\n document.body.style.cursor = 'crosshair';\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.removeEventListener('keydown', handleKeyDown, true);\n document.body.style.cursor = '';\n };\n }, [enabled, handleMouseMove, handleClick, handleKeyDown]);\n\n if (!enabled) return null;\n\n return (\n <>\n {/* Highlight box */}\n {highlight && (\n <div\n data-component-picker=\"highlight\"\n style={{\n position: 'fixed',\n top: highlight.top,\n left: highlight.left,\n width: highlight.width,\n height: highlight.height,\n border: '2px solid #3b82f6',\n backgroundColor: 'rgba(59, 130, 246, 0.1)',\n pointerEvents: 'none',\n zIndex: 999998,\n boxSizing: 'border-box',\n }}\n >\n {/* Component name label */}\n <div\n style={{\n position: 'absolute',\n top: -24,\n left: -2,\n padding: '2px 8px',\n backgroundColor: '#3b82f6',\n color: 'white',\n fontSize: '12px',\n fontFamily: 'system-ui, sans-serif',\n fontWeight: 500,\n borderRadius: '4px 4px 0 0',\n whiteSpace: 'nowrap',\n maxWidth: '300px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {highlight.componentName}\n </div>\n </div>\n )}\n\n {/* Info bar at top */}\n <div\n data-component-picker=\"info-bar\"\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n padding: '12px 16px',\n backgroundColor: '#3b82f6',\n color: 'white',\n fontFamily: 'system-ui, sans-serif',\n fontSize: '14px',\n textAlign: 'center',\n zIndex: 999999,\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: '16px',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n }}\n >\n <span style={{ fontWeight: 500 }}>\n {message || 'Click a component to select it'}\n </span>\n <span style={{ opacity: 0.8, fontSize: '12px' }}>Press ESC to cancel</span>\n </div>\n </>\n );\n}\n","/**\n * Source map client for fetching and parsing source maps from dev servers\n * Uses source-map-js for browser-compatible source map parsing\n */\n\nimport { SourceMapConsumer, type RawSourceMap } from 'source-map-js';\n\nexport interface OriginalPosition {\n source: string | null;\n line: number | null;\n column: number | null;\n name: string | null;\n}\n\n// Cache for source map consumers (keyed by script URL)\nconst sourceMapCache = new Map<string, SourceMapConsumer | null>();\n\n// Cache for failed fetches to avoid repeated attempts\nconst failedFetches = new Set<string>();\n\n/**\n * Fetch and parse a source map for a given script URL\n */\nexport async function fetchSourceMap(\n scriptUrl: string\n): Promise<SourceMapConsumer | null> {\n // Check cache first\n if (sourceMapCache.has(scriptUrl)) {\n return sourceMapCache.get(scriptUrl) || null;\n }\n\n // Skip if we already failed to fetch this one\n if (failedFetches.has(scriptUrl)) {\n return null;\n }\n\n try {\n // Try to find the source map URL\n const sourceMapUrl = await findSourceMapUrl(scriptUrl);\n if (!sourceMapUrl) {\n failedFetches.add(scriptUrl);\n sourceMapCache.set(scriptUrl, null);\n return null;\n }\n\n // Fetch the source map\n const response = await fetch(sourceMapUrl);\n if (!response.ok) {\n failedFetches.add(scriptUrl);\n sourceMapCache.set(scriptUrl, null);\n return null;\n }\n\n const sourceMapData = (await response.json()) as RawSourceMap;\n\n // Create the consumer\n const consumer = new SourceMapConsumer(sourceMapData);\n sourceMapCache.set(scriptUrl, consumer);\n return consumer;\n } catch (error) {\n console.debug('[component-picker] Failed to fetch source map:', error);\n failedFetches.add(scriptUrl);\n sourceMapCache.set(scriptUrl, null);\n return null;\n }\n}\n\n/**\n * Find the source map URL for a script\n * Tries multiple strategies:\n * 1. Fetch script and look for //# sourceMappingURL comment\n * 2. Try common source map URL patterns\n */\nasync function findSourceMapUrl(scriptUrl: string): Promise<string | null> {\n try {\n // Strategy 1: Fetch the script and look for sourceMappingURL\n const scriptResponse = await fetch(scriptUrl);\n if (scriptResponse.ok) {\n const scriptContent = await scriptResponse.text();\n\n // Look for sourceMappingURL comment\n const match = scriptContent.match(\n /\\/\\/[#@]\\s*sourceMappingURL=([^\\s'\"]+)/\n );\n if (match?.[1]) {\n const mapUrl = match[1];\n // Handle relative URLs\n if (mapUrl.startsWith('data:')) {\n // Inline source map - not supported yet\n return null;\n }\n return new URL(mapUrl, scriptUrl).href;\n }\n }\n\n // Strategy 2: Try common patterns\n const patterns = [\n `${scriptUrl}.map`,\n scriptUrl.replace(/\\.js$/, '.js.map'),\n scriptUrl.replace(/\\.mjs$/, '.mjs.map'),\n ];\n\n for (const pattern of patterns) {\n try {\n const response = await fetch(pattern, { method: 'HEAD' });\n if (response.ok) {\n return pattern;\n }\n } catch {\n // Continue to next pattern\n }\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve the original position from a bundled position\n */\nexport async function resolveOriginalPosition(\n scriptUrl: string,\n line: number,\n column: number\n): Promise<OriginalPosition | null> {\n const consumer = await fetchSourceMap(scriptUrl);\n if (!consumer) {\n return null;\n }\n\n try {\n const position = consumer.originalPositionFor({\n line,\n column,\n });\n\n // source-map-js returns { source: null } when it can't find the position\n if (!position.source) {\n return null;\n }\n\n return {\n source: position.source,\n line: position.line,\n column: position.column,\n name: position.name ?? null,\n };\n } catch (error) {\n console.debug('[component-picker] Failed to resolve position:', error);\n return null;\n }\n}\n\n/**\n * Resolve source path to an absolute or project-relative path\n */\nexport function resolveSourcePath(\n sourcePath: string,\n scriptUrl: string\n): string {\n // Handle webpack:// protocol\n if (sourcePath.startsWith('webpack://')) {\n // Format: webpack://package-name/./src/file.tsx\n // or: webpack:///./src/file.tsx\n const match = sourcePath.match(/webpack:\\/\\/(?:[^/]+)?\\/\\.?\\/?(.+)/);\n if (match?.[1]) {\n return match[1];\n }\n }\n\n // Handle turbopack paths\n if (sourcePath.startsWith('[project]/')) {\n return sourcePath.replace('[project]/', '');\n }\n\n // Handle relative paths\n if (sourcePath.startsWith('./') || sourcePath.startsWith('../')) {\n try {\n // Resolve relative to script URL's directory\n const scriptDir = scriptUrl.substring(0, scriptUrl.lastIndexOf('/'));\n const resolved = new URL(sourcePath, scriptDir + '/').pathname;\n // Remove leading slash for consistency\n return resolved.replace(/^\\//, '');\n } catch {\n return sourcePath;\n }\n }\n\n // Handle absolute paths that start with /\n if (sourcePath.startsWith('/')) {\n return sourcePath.substring(1);\n }\n\n return sourcePath;\n}\n\n/**\n * Clear the source map cache\n * Useful for HMR scenarios where source maps may have changed\n */\nexport function clearSourceMapCache(): void {\n sourceMapCache.clear();\n failedFetches.clear();\n}\n\n/**\n * Get cache statistics for debugging\n */\nexport function getCacheStats(): { cached: number; failed: number } {\n return {\n cached: sourceMapCache.size,\n failed: failedFetches.size,\n };\n}\n\n/**\n * Search source maps for a component definition by name\n * This is a heuristic approach when _debugSource isn't available\n */\nexport async function searchSourceMapsForComponent(\n componentName: string\n): Promise<{ source: string; line: number; column: number } | null> {\n // Get all script URLs from the page\n const scripts = Array.from(document.querySelectorAll('script[src]'))\n .map((s) => (s as HTMLScriptElement).src)\n .filter((src) => src && !src.includes('node_modules'));\n\n // Also check for Next.js chunks\n const nextScripts = Array.from(\n document.querySelectorAll('script[src*=\"/_next/\"]')\n ).map((s) => (s as HTMLScriptElement).src);\n\n const allScripts = [...new Set([...scripts, ...nextScripts])];\n\n for (const scriptUrl of allScripts) {\n const consumer = await fetchSourceMap(scriptUrl);\n if (!consumer) continue;\n\n // Search through all sources in this source map\n const sources = (consumer as unknown as { sources: string[] }).sources || [];\n\n for (const source of sources) {\n // Check if this source file might contain the component\n // Look for patterns like \"Card.tsx\", \"Card.jsx\", etc.\n const fileName = source.split('/').pop() || '';\n const baseName = fileName.replace(/\\.(tsx?|jsx?)$/, '');\n\n if (\n baseName === componentName ||\n fileName.toLowerCase().includes(componentName.toLowerCase())\n ) {\n // Try to find the component definition in this source\n // Look for \"function ComponentName\" or \"const ComponentName\"\n try {\n // Get all mappings for this source\n let firstMapping: { line: number; column: number } | null = null;\n\n consumer.eachMapping((mapping) => {\n if (mapping.source === source && !firstMapping) {\n // Check if this mapping has the component name\n if (mapping.name === componentName && mapping.originalLine !== null && mapping.originalColumn !== null) {\n firstMapping = {\n line: mapping.originalLine,\n column: mapping.originalColumn,\n };\n }\n }\n });\n\n if (firstMapping !== null) {\n return {\n source: resolveSourcePath(source, scriptUrl),\n line: (firstMapping as { line: number; column: number }).line,\n column: (firstMapping as { line: number; column: number }).column,\n };\n }\n\n // If no exact name match, return the start of the file that matches the name\n if (baseName === componentName) {\n return {\n source: resolveSourcePath(source, scriptUrl),\n line: 1,\n column: 0,\n };\n }\n } catch {\n // Continue to next source\n }\n }\n }\n }\n\n return null;\n}\n","/**\n * Cross-browser stack trace parser\n * Extracts source locations from JavaScript error stack traces\n */\n\nexport interface StackFrame {\n functionName: string | null;\n url: string;\n lineNumber: number;\n columnNumber: number;\n}\n\n/**\n * Parse an error stack trace into structured frames\n * Supports Chrome, Firefox, Safari, and Edge\n */\nexport function parseStackTrace(error: Error): StackFrame[] {\n const stack = error.stack;\n if (!stack) return [];\n\n const frames: StackFrame[] = [];\n const lines = stack.split('\\n');\n\n for (const line of lines) {\n const frame = parseStackLine(line);\n if (frame) {\n frames.push(frame);\n }\n }\n\n return frames;\n}\n\n/**\n * Parse a single stack trace line\n */\nfunction parseStackLine(line: string): StackFrame | null {\n // Chrome/Edge/Node format:\n // \" at FunctionName (http://localhost:3000/file.js:10:15)\"\n // \" at http://localhost:3000/file.js:10:15\"\n // \" at async FunctionName (http://localhost:3000/file.js:10:15)\"\n const chromeMatch = line.match(\n /^\\s*at\\s+(?:async\\s+)?(?:(\\S+)\\s+)?\\(?(https?:\\/\\/[^)]+|file:\\/\\/[^)]+):(\\d+):(\\d+)\\)?/\n );\n if (chromeMatch) {\n return {\n functionName: chromeMatch[1] || null,\n url: chromeMatch[2]!,\n lineNumber: parseInt(chromeMatch[3]!, 10),\n columnNumber: parseInt(chromeMatch[4]!, 10),\n };\n }\n\n // Firefox/Safari format:\n // \"functionName@http://localhost:3000/file.js:10:15\"\n // \"@http://localhost:3000/file.js:10:15\"\n const firefoxMatch = line.match(\n /^(?:(\\S*)@)?(https?:\\/\\/[^:]+|file:\\/\\/[^:]+):(\\d+):(\\d+)/\n );\n if (firefoxMatch) {\n return {\n functionName: firefoxMatch[1] || null,\n url: firefoxMatch[2]!,\n lineNumber: parseInt(firefoxMatch[3]!, 10),\n columnNumber: parseInt(firefoxMatch[4]!, 10),\n };\n }\n\n return null;\n}\n\n/**\n * Filter out internal React and framework frames\n */\nexport function filterInternalFrames(frames: StackFrame[]): StackFrame[] {\n const internalPatterns = [\n /node_modules/,\n /react-dom/,\n /react\\.production/,\n /react\\.development/,\n /scheduler/,\n /\\/_next\\/static\\/chunks\\/webpack/,\n /\\/__webpack_/,\n /\\/turbopack-/,\n // React internal function names\n /^(?:renderWithHooks|mountIndeterminateComponent|beginWork|performUnitOfWork)/,\n /^(?:callCallback|invokeGuardedCallbackDev|invokeGuardedCallback)/,\n /^(?:commitRoot|flushSync|batchedUpdates)/,\n ];\n\n return frames.filter((frame) => {\n // Check URL patterns\n for (const pattern of internalPatterns) {\n if (pattern.test(frame.url)) {\n return false;\n }\n }\n\n // Check function name patterns\n if (frame.functionName) {\n for (const pattern of internalPatterns) {\n if (pattern.test(frame.functionName)) {\n return false;\n }\n }\n }\n\n return true;\n });\n}\n\n/**\n * Get the first user component frame from the stack\n * This is typically the component that was clicked\n */\nexport function getComponentFrame(frames: StackFrame[]): StackFrame | null {\n const userFrames = filterInternalFrames(frames);\n return userFrames[0] || null;\n}\n\n/**\n * Create a stack trace at the current execution point\n * Useful for capturing where a component render is happening\n */\nexport function captureStackTrace(): StackFrame[] {\n const error = new Error();\n return parseStackTrace(error);\n}\n\n/**\n * Extract the script URL from a frame, normalizing various bundler formats\n */\nexport function normalizeScriptUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n // Remove query params (like HMR timestamps)\n urlObj.search = '';\n urlObj.hash = '';\n return urlObj.href;\n } catch {\n return url;\n }\n}\n","/**\n * Multi-strategy source location resolver\n *\n * Attempts to resolve source file locations using three strategies:\n * 1. React's _debugSource (fastest, works with Babel-based builds)\n * 2. Source map resolution (works with any bundler in dev mode)\n * 3. Stack trace parsing (fallback, less accurate)\n */\n\nimport type { SourceLocation } from '@react-component-selector-mcp/shared';\nimport { searchSourceMapsForComponent } from './sourceMapClient.js';\nimport { parseStackTrace, filterInternalFrames } from './stackTraceParser.js';\n\nexport interface DebugSource {\n fileName: string | null;\n lineNumber: number | null;\n columnNumber?: number | null;\n}\n\nexport interface Fiber {\n _debugSource?: DebugSource;\n type?: unknown;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\n/**\n * Resolve source location using multiple strategies\n * This is the main entry point for source resolution\n */\nexport async function resolveSourceLocation(\n fiber: Fiber | null,\n element?: HTMLElement\n): Promise<SourceLocation> {\n // Strategy 1: Try _debugSource first (fastest)\n const debugSourceResult = tryDebugSource(fiber);\n if (debugSourceResult.filePath) {\n return debugSourceResult;\n }\n\n // Strategy 2: Try source map resolution\n const sourceMapResult = await trySourceMapResolution(fiber, element);\n if (sourceMapResult?.filePath) {\n return sourceMapResult;\n }\n\n // Strategy 3: Try stack trace parsing (fallback)\n const stackResult = tryStackTraceParsing();\n if (stackResult?.filePath) {\n return stackResult;\n }\n\n // No source information available\n return {\n filePath: null,\n lineNumber: null,\n columnNumber: null,\n };\n}\n\n/**\n * Strategy 1: Extract source from React's _debugSource\n * This is set by @babel/plugin-transform-react-jsx-source\n */\nfunction tryDebugSource(fiber: Fiber | null): SourceLocation {\n // Debug: log what's in the fiber\n if (fiber) {\n console.log('[component-picker] Fiber keys:', Object.keys(fiber));\n console.log('[component-picker] _debugSource:', fiber._debugSource);\n console.log('[component-picker] _debugInfo:', (fiber as Record<string, unknown>)._debugInfo);\n }\n\n if (!fiber?._debugSource) {\n return { filePath: null, lineNumber: null, columnNumber: null };\n }\n\n const { fileName, lineNumber, columnNumber } = fiber._debugSource;\n\n if (!fileName) {\n return { filePath: null, lineNumber: null, columnNumber: null };\n }\n\n return {\n filePath: formatFilePath(fileName),\n lineNumber: lineNumber ?? null,\n columnNumber: columnNumber ?? null,\n };\n}\n\n/**\n * Strategy 2: Resolve source via source maps\n * Uses component name to search source maps for the definition\n */\nasync function trySourceMapResolution(\n fiber: Fiber | null,\n _element?: HTMLElement\n): Promise<SourceLocation | null> {\n try {\n // Get component name from fiber\n const componentName = fiber?.type ? getComponentName(fiber.type) : null;\n if (!componentName) {\n return null;\n }\n\n // Search source maps for a file/definition matching this component name\n const result = await searchSourceMapsForComponent(componentName);\n if (!result) {\n return null;\n }\n\n return {\n filePath: formatFilePath(result.source),\n lineNumber: result.line,\n columnNumber: result.column,\n };\n } catch (error) {\n console.debug('[component-picker] Source map resolution failed:', error);\n return null;\n }\n}\n\n/**\n * Strategy 3: Parse stack trace directly for source location\n * Less accurate but works as a last resort\n */\nfunction tryStackTraceParsing(): SourceLocation | null {\n try {\n const error = new Error();\n const frames = parseStackTrace(error);\n const userFrames = filterInternalFrames(frames);\n\n if (userFrames.length === 0) {\n return null;\n }\n\n const frame = userFrames[0]!;\n\n // Extract file path from URL\n const filePath = extractFilePathFromUrl(frame.url);\n if (!filePath) {\n return null;\n }\n\n return {\n filePath,\n lineNumber: frame.lineNumber,\n columnNumber: frame.columnNumber,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Extract component name from fiber type\n */\nfunction getComponentName(type: unknown): string | null {\n if (!type) return null;\n\n if (typeof type === 'function') {\n return (type as { displayName?: string; name?: string }).displayName ||\n (type as { name?: string }).name ||\n null;\n }\n\n if (typeof type === 'object' && type !== null) {\n // Handle forwardRef, memo, etc.\n const obj = type as { displayName?: string; render?: { displayName?: string; name?: string } };\n return obj.displayName || obj.render?.displayName || obj.render?.name || null;\n }\n\n return null;\n}\n\n/**\n * Extract relative file path from URL\n */\nfunction extractFilePathFromUrl(url: string): string | null {\n try {\n const urlObj = new URL(url);\n let path = urlObj.pathname;\n\n // Remove leading slash\n path = path.replace(/^\\/+/, '');\n\n // Handle various bundler prefixes\n path = path\n // Next.js\n .replace(/^_next\\/static\\/chunks\\//, '')\n .replace(/^_next\\/static\\/[^/]+\\/pages\\//, 'pages/')\n // Vite\n .replace(/^\\/@fs\\//, '')\n .replace(/^@vite\\//, '')\n // Webpack\n .replace(/^webpack:\\/\\/[^/]+\\//, '')\n // Turbopack\n .replace(/^\\[project\\]\\//, '');\n\n // Remove query params and hash (HMR timestamps etc)\n path = path.split('?')[0]?.split('#')[0] || path;\n\n // If the path looks like a hash (e.g., \"app-pages-internals.js\")\n // and doesn't have a recognizable extension path, it's not useful\n if (!path.includes('/') && !path.match(/\\.(tsx?|jsx?|mjs)$/)) {\n return null;\n }\n\n return path || null;\n } catch {\n return url;\n }\n}\n\n/**\n * Clean up file path for display\n */\nexport function formatFilePath(filePath: string | null): string | null {\n if (!filePath) return null;\n\n let cleaned = filePath\n // Remove webpack:// prefix\n .replace(/^webpack:\\/\\/[^/]+\\//, '')\n // Remove ./ prefix\n .replace(/^\\.\\//g, '')\n // Remove leading slashes\n .replace(/^\\/+/, '')\n // Remove turbopack prefix\n .replace(/^\\[project\\]\\//, '');\n\n // Normalize Windows paths to forward slashes\n cleaned = cleaned.replace(/\\\\/g, '/');\n\n return cleaned;\n}\n\n/**\n * Synchronous version for backward compatibility\n * Only uses _debugSource strategy\n */\nexport function resolveSourceLocationSync(\n debugSource: DebugSource | null\n): SourceLocation {\n if (!debugSource?.fileName) {\n return { filePath: null, lineNumber: null, columnNumber: null };\n }\n\n return {\n filePath: formatFilePath(debugSource.fileName),\n lineNumber: debugSource.lineNumber ?? null,\n columnNumber: debugSource.columnNumber ?? null,\n };\n}\n","import { toPng } from 'html-to-image';\nimport type { Screenshot } from '@react-component-selector-mcp/shared';\n\nexport interface CaptureOptions {\n /** Maximum width of the screenshot (default: 800) */\n maxWidth?: number;\n /** Maximum height of the screenshot (default: 600) */\n maxHeight?: number;\n /** Background color (default: transparent) */\n backgroundColor?: string;\n /** Pixel ratio for higher quality (default: 1) */\n pixelRatio?: number;\n /** Padding around the element (default: 10) */\n padding?: number;\n}\n\nconst DEFAULT_OPTIONS: Required<CaptureOptions> = {\n maxWidth: 800,\n maxHeight: 600,\n backgroundColor: '#ffffff',\n pixelRatio: 1,\n padding: 10,\n};\n\n/**\n * Capture a screenshot of an HTML element\n */\nexport async function captureScreenshot(\n element: HTMLElement,\n options: CaptureOptions = {}\n): Promise<Screenshot> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n try {\n // Get element dimensions\n const rect = element.getBoundingClientRect();\n const width = Math.min(rect.width + opts.padding * 2, opts.maxWidth);\n const height = Math.min(rect.height + opts.padding * 2, opts.maxHeight);\n\n // Capture the element\n const dataUrl = await toPng(element, {\n backgroundColor: opts.backgroundColor,\n pixelRatio: opts.pixelRatio,\n width: rect.width,\n height: rect.height,\n style: {\n margin: '0',\n padding: '0',\n },\n filter: (node) => {\n // Skip our overlay elements\n if (node instanceof Element) {\n if (node.hasAttribute('data-component-picker')) {\n return false;\n }\n }\n return true;\n },\n });\n\n return {\n dataUrl,\n width: Math.round(width),\n height: Math.round(height),\n };\n } catch (error) {\n console.error('[component-picker] Screenshot capture failed:', error);\n\n // Return a fallback empty screenshot\n return {\n dataUrl: createFallbackScreenshot(element),\n width: 200,\n height: 100,\n };\n }\n}\n\n/**\n * Create a simple fallback screenshot when capture fails\n */\nfunction createFallbackScreenshot(element: HTMLElement): string {\n const canvas = document.createElement('canvas');\n canvas.width = 200;\n canvas.height = 100;\n\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.fillStyle = '#f0f0f0';\n ctx.fillRect(0, 0, 200, 100);\n\n ctx.fillStyle = '#666';\n ctx.font = '12px sans-serif';\n ctx.textAlign = 'center';\n ctx.fillText('Screenshot unavailable', 100, 45);\n ctx.fillText(element.tagName.toLowerCase(), 100, 65);\n }\n\n return canvas.toDataURL('image/png');\n}\n","import { nanoid } from 'nanoid';\nimport type { SelectionData, DOMInfo } from '@react-component-selector-mcp/shared';\nimport type { FiberData } from '../hooks/useFiberInspector.js';\nimport {\n resolveSourceLocation,\n formatFilePath,\n type Fiber,\n} from './sourceLocationResolver.js';\nimport { captureScreenshot, type CaptureOptions } from './screenshotCapture.js';\n\nexport interface MetadataOptions {\n screenshotOptions?: CaptureOptions;\n /** The raw React fiber for enhanced source resolution */\n fiber?: Fiber | null;\n}\n\n/**\n * Extract DOM information from an element\n */\nexport function extractDOMInfo(element: HTMLElement): DOMInfo {\n const rect = element.getBoundingClientRect();\n\n return {\n tagName: element.tagName.toLowerCase(),\n className: element.className || null,\n boundingRect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n },\n };\n}\n\n/**\n * Build complete selection data from fiber data and DOM element\n */\nexport async function buildSelectionData(\n element: HTMLElement,\n fiberData: FiberData,\n options: MetadataOptions = {}\n): Promise<SelectionData> {\n // Resolve source location using multi-strategy approach\n // Pass fiber for enhanced source map resolution\n const fiber = options.fiber ?? {\n _debugSource: fiberData.debugSource,\n };\n const source = await resolveSourceLocation(fiber, element);\n\n // Capture screenshot\n const screenshot = await captureScreenshot(element, options.screenshotOptions);\n\n // Build complete selection data\n const selectionData: SelectionData = {\n id: nanoid(),\n timestamp: Date.now(),\n component: fiberData.componentInfo,\n source: {\n filePath: formatFilePath(source.filePath),\n lineNumber: source.lineNumber,\n columnNumber: source.columnNumber,\n },\n props: fiberData.props,\n state: fiberData.state,\n dom: extractDOMInfo(element),\n screenshot,\n context: {\n pageUrl: window.location.href,\n parentComponents: fiberData.parentComponents,\n },\n };\n\n return selectionData;\n}\n","import React, { useCallback, type ReactNode } from 'react';\nimport { useWebSocketClient } from './hooks/useWebSocketClient.js';\nimport { useKeyboardShortcut } from './hooks/useKeyboardShortcut.js';\nimport { useSelectionMode } from './hooks/useSelectionMode.js';\nimport { useFiberInspector } from './hooks/useFiberInspector.js';\nimport { SelectionOverlay } from './SelectionOverlay.js';\nimport { buildSelectionData } from './utils/componentMetadata.js';\n\nexport interface ComponentPickerProps {\n /** WebSocket server port (default: 3333) */\n port?: number;\n /** Children to wrap */\n children: ReactNode;\n /** Keyboard shortcut key (default: 'C' for Ctrl+Alt+C / Cmd+Option+C) */\n shortcutKey?: string;\n /** Called when connection status changes */\n onConnectionChange?: (connected: boolean) => void;\n /** Called when a component is selected */\n onSelect?: (componentName: string, filePath: string | null) => void;\n}\n\n/**\n * Wrapper component that enables component selection in development mode.\n * In production, this is a no-op passthrough.\n */\nexport function ComponentPicker(props: ComponentPickerProps): ReactNode {\n // No-op in production\n if (process.env.NODE_ENV !== 'development') {\n return props.children;\n }\n\n return <ComponentPickerImpl {...props} />;\n}\n\n/**\n * Implementation component (only rendered in development)\n */\nfunction ComponentPickerImpl({\n port = 3333,\n children,\n shortcutKey = 'C',\n onConnectionChange,\n onSelect,\n}: ComponentPickerProps): React.ReactElement {\n const { isSelectionMode, selectionMessage, enableSelectionMode, disableSelectionMode } =\n useSelectionMode();\n\n const { getFiberFromElement, extractFiberData, findNearestComponentFiber } = useFiberInspector();\n\n const { connected, sendSelection } = useWebSocketClient({\n port,\n onSelectionModeChange: (enabled, message) => {\n if (enabled) {\n enableSelectionMode(message);\n } else {\n disableSelectionMode();\n }\n },\n onConnectionChange,\n });\n\n // Handle keyboard shortcut\n useKeyboardShortcut({\n key: shortcutKey,\n onTrigger: () => {\n if (isSelectionMode) {\n disableSelectionMode();\n } else {\n enableSelectionMode();\n }\n },\n enabled: connected,\n });\n\n // Handle element selection\n const handleSelect = useCallback(\n async (element: HTMLElement) => {\n try {\n // Get fiber from element\n const fiber = getFiberFromElement(element);\n if (!fiber) {\n console.warn('[component-picker] No React fiber found for element');\n disableSelectionMode();\n return;\n }\n\n // Find nearest component fiber\n const componentFiber = findNearestComponentFiber(fiber);\n if (!componentFiber) {\n console.warn('[component-picker] No component fiber found');\n disableSelectionMode();\n return;\n }\n\n // Extract fiber data\n const fiberData = extractFiberData(componentFiber);\n\n // Build complete selection data (pass fiber for enhanced source resolution)\n const selectionData = await buildSelectionData(element, fiberData, {\n fiber: componentFiber,\n });\n\n // Send to server\n sendSelection(selectionData);\n\n // Notify callback\n onSelect?.(selectionData.component.name, selectionData.source.filePath);\n\n console.log(\n `[component-picker] Selected: ${selectionData.component.name}`,\n selectionData.source.filePath\n ? `at ${selectionData.source.filePath}:${selectionData.source.lineNumber}`\n : ''\n );\n } catch (error) {\n console.error('[component-picker] Selection error:', error);\n } finally {\n disableSelectionMode();\n }\n },\n [\n getFiberFromElement,\n findNearestComponentFiber,\n extractFiberData,\n sendSelection,\n disableSelectionMode,\n onSelect,\n ]\n );\n\n return (\n <>\n {children}\n <SelectionOverlay\n enabled={isSelectionMode}\n message={selectionMessage}\n onSelect={handleSelect}\n onCancel={disableSelectionMode}\n />\n {/* Selection toggle button (bottom-right corner) */}\n {process.env.NODE_ENV === 'development' && (\n <button\n data-component-picker=\"status\"\n onClick={() => {\n if (!connected) return;\n if (isSelectionMode) {\n disableSelectionMode();\n } else {\n enableSelectionMode();\n }\n }}\n style={{\n position: 'fixed',\n bottom: 16,\n right: 16,\n padding: '8px 12px',\n backgroundColor: !connected\n ? '#ef4444'\n : isSelectionMode\n ? '#f59e0b'\n : '#22c55e',\n color: 'white',\n borderRadius: '9999px',\n fontSize: '12px',\n fontFamily: 'system-ui, sans-serif',\n fontWeight: 500,\n zIndex: 999997,\n opacity: 0.9,\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n border: 'none',\n cursor: connected ? 'pointer' : 'not-allowed',\n transition: 'background-color 0.2s ease',\n }}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n backgroundColor: 'white',\n animation: !connected ? 'pulse 2s infinite' : 'none',\n }}\n />\n {!connected\n ? 'Connecting...'\n : isSelectionMode\n ? 'Click a Component'\n : 'Select Component'}\n </button>\n )}\n </>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../shared/src/schemas.ts","../../shared/src/messages.ts","../src/hooks/useWebSocketClient.ts","../src/hooks/useKeyboardShortcut.ts","../src/hooks/useSelectionMode.ts","../src/hooks/useFiberInspector.ts","../src/SelectionOverlay.tsx","../src/utils/stackTraceParser.ts","../src/utils/sourceLocationResolver.ts","../src/utils/componentMetadata.ts","../src/ComponentPicker.tsx"],"names":["z","useCallback","useEffect","useState","useRef","jsx","Fragment"],"mappings":";;;;;AAEO,IAAM,mBAAA,GAAsB,EAAE,IAAA,CAAK,CAAC,YAAY,OAAA,EAAS,YAAA,EAAc,MAAM,CAAC,CAAA;AAE9E,IAAM,mBAAA,GAAsB,EAAE,MAAA,CAAO;AAC1C,EAAA,IAAA,EAAM,EAAE,MAAA,EAAM;EACd,IAAA,EAAM;AACP,CAAA,CAAA;AAEM,IAAM,oBAAA,GAAuB,EAAE,MAAA,CAAO;EAC3C,QAAA,EAAU,CAAA,CAAE,MAAA,EAAM,CAAG,QAAA,EAAQ;EAC7B,UAAA,EAAY,CAAA,CAAE,MAAA,EAAM,CAAG,QAAA,EAAQ;EAC/B,YAAA,EAAc,CAAA,CAAE,MAAA,EAAM,CAAG,QAAA;AAC1B,CAAA,CAAA;AAEM,IAAM,kBAAA,GAAqB,EAAE,MAAA,CAAO;AACzC,EAAA,CAAA,EAAG,EAAE,MAAA,EAAM;AACX,EAAA,CAAA,EAAG,EAAE,MAAA,EAAM;AACX,EAAA,KAAA,EAAO,EAAE,MAAA,EAAM;AACf,EAAA,MAAA,EAAQ,EAAE,MAAA,EAAM;AAChB,EAAA,GAAA,EAAK,EAAE,MAAA,EAAM;AACb,EAAA,KAAA,EAAO,EAAE,MAAA,EAAM;AACf,EAAA,MAAA,EAAQ,EAAE,MAAA,EAAM;AAChB,EAAA,IAAA,EAAM,EAAE,MAAA;AACT,CAAA,CAAA;AAEM,IAAM,aAAA,GAAgB,EAAE,MAAA,CAAO;AACpC,EAAA,OAAA,EAAS,EAAE,MAAA,EAAM;EACjB,SAAA,EAAW,CAAA,CAAE,MAAA,EAAM,CAAG,QAAA,EAAQ;EAC9B,YAAA,EAAc;AACf,CAAA,CAAA;AAEM,IAAM,sBAAA,GAAyB,EAAE,MAAA,CAAO;AAC7C,EAAA,OAAA,EAAS,EAAE,MAAA,EAAM;AACjB,EAAA,gBAAA,EAAkB,CAAA,CAAE,KAAA,CAAM,CAAA,CAAE,MAAA,EAAQ;AACrC,CAAA,CAAA;AAEM,IAAM,mBAAA,GAAsB,EAAE,MAAA,CAAO;AAC1C,EAAA,EAAA,EAAI,EAAE,MAAA,EAAM;AACZ,EAAA,SAAA,EAAW,EAAE,MAAA,EAAM;EACnB,SAAA,EAAW,mBAAA;EACX,MAAA,EAAQ,oBAAA;AACR,EAAA,KAAA,EAAO,CAAA,CAAE,MAAA,CAAO,CAAA,CAAE,OAAA,EAAS,CAAA;AAC3B,EAAA,KAAA,EAAO,EAAE,MAAA,CAAO,CAAA,CAAE,OAAA,EAAS,EAAE,QAAA,EAAQ;EACrC,GAAA,EAAK,aAAA;EACL,OAAA,EAAS;AACV,CAAA,CAAA;ACtCM,IAAM,iBAAA,GAAoBA,EAAE,IAAA,CAAK;AACtC,EAAA,WAAA;AACA,EAAA,MAAA;AACA,EAAA,MAAA;AACA,EAAA,SAAA;AACA,EAAA,YAAA;AACA,EAAA,OAAA;AACA,EAAA;AACD,CAAA,CAAA;AAKD,IAAM,iBAAA,GAAoBA,EAAE,MAAA,CAAO;EACjC,IAAA,EAAM,iBAAA;AACN,EAAA,SAAA,EAAWA,EAAE,MAAA;AACd,CAAA,CAAA;AAGM,IAAM,sBAAA,GAAyB,kBAAkB,MAAA,CAAO;EAC7D,IAAA,EAAMA,CAAAA,CAAE,QAAQ,WAAW,CAAA;EAC3B,OAAA,EAAS;AACV,CAAA,CAAA;AAGM,IAAM,iBAAA,GAAoB,kBAAkB,MAAA,CAAO;EACxD,IAAA,EAAMA,CAAAA,CAAE,QAAQ,MAAM;AACvB,CAAA,CAAA;AAEM,IAAM,iBAAA,GAAoB,kBAAkB,MAAA,CAAO;EACxD,IAAA,EAAMA,CAAAA,CAAE,QAAQ,MAAM;AACvB,CAAA,CAAA;AAGM,IAAM,oBAAA,GAAuB,kBAAkB,MAAA,CAAO;EAC3D,IAAA,EAAMA,CAAAA,CAAE,QAAQ,SAAS,CAAA;AACzB,EAAA,OAAA,EAASA,EAAE,MAAA,CAAO;AAChB,IAAA,QAAA,EAAUA,EAAE,MAAA,EAAM;IAClB,SAAA,EAAWA,CAAAA,CAAE,MAAA,EAAM,CAAG,QAAA;AACvB,GAAA;AACF,CAAA,CAAA;AAEM,IAAM,uBAAA,GAA0B,kBAAkB,MAAA,CAAO;EAC9D,IAAA,EAAMA,CAAAA,CAAE,QAAQ,YAAY,CAAA;AAC5B,EAAA,OAAA,EAASA,EAAE,MAAA,CAAO;AAChB,IAAA,QAAA,EAAUA,EAAE,MAAA,EAAM;IAClB,MAAA,EAAQA,CAAAA,CAAE,MAAA,EAAM,CAAG,QAAA;AACpB,GAAA;AACF,CAAA,CAAA;AAGM,IAAM,kBAAA,GAAqB,kBAAkB,MAAA,CAAO;EACzD,IAAA,EAAMA,CAAAA,CAAE,QAAQ,OAAO,CAAA;AACvB,EAAA,OAAA,EAASA,EAAE,MAAA,CAAO;AAChB,IAAA,IAAA,EAAMA,EAAE,MAAA,EAAM;AACd,IAAA,OAAA,EAASA,EAAE,MAAA;AACZ,GAAA;AACF,CAAA,CAAA;AAGM,IAAM,0BAAA,GAA6B,kBAAkB,MAAA,CAAO;EACjE,IAAA,EAAMA,CAAAA,CAAE,QAAQ,eAAe,CAAA;AAC/B,EAAA,OAAA,EAASA,EAAE,MAAA,CAAO;AAChB,IAAA,OAAA,EAASA,EAAE,OAAA,EAAO;IAClB,OAAA,EAASA,CAAAA,CAAE,MAAA,EAAM,CAAG,QAAA;AACrB,GAAA;AACF,CAAA,CAAA;AAGM,IAAM,sBAAA,GAAyBA,CAAAA,CAAE,kBAAA,CAAmB,MAAA,EAAQ;AACjE,EAAA,sBAAA;AACA,EAAA,iBAAA;AACA,EAAA,iBAAA;AACA,EAAA,oBAAA;AACA,EAAA,uBAAA;AACA,EAAA,kBAAA;AACA,EAAA;AACD,CAAA,CAAA;AAmBK,SAAU,aAAA,CAAc,MAAmB,OAAA,EAAiB;AAChE,EAAA,MAAM,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,CAAK,KAAG,EAAE;AAC1C,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,OAAA,EAAO;AAC3B,EAAA;AACA,EAAA,OAAO,IAAA;AACT;;;AC1FO,SAAS,mBACd,OAAA,EAC0B;AAC1B,EAAA,MAAM,EAAE,MAAK,GAAI,OAAA;AAGjB,EAAA,MAAM,wBAAA,GAA2B,MAAA,CAAO,OAAA,CAAQ,qBAAqB,CAAA;AACrE,EAAA,MAAM,qBAAA,GAAwB,MAAA,CAAO,OAAA,CAAQ,kBAAkB,CAAA;AAC/D,EAAA,wBAAA,CAAyB,UAAU,OAAA,CAAQ,qBAAA;AAC3C,EAAA,qBAAA,CAAsB,UAAU,OAAA,CAAQ,kBAAA;AAExC,EAAA,MAAM,KAAA,GAAQ,OAAyB,IAAI,CAAA;AAC3C,EAAA,MAAM,mBAAA,GAAsB,OAA6C,IAAI,CAAA;AAC7E,EAAA,MAAM,eAAA,GAAkB,OAA8C,IAAI,CAAA;AAC1E,EAAA,MAAM,eAAA,GAAkB,OAAO,KAAK,CAAA;AAEpC,EAAA,MAAM,eAAA,GAAkB,OAAO,KAAK,CAAA;AAEpC,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAwB,IAAI,CAAA;AAE5D,EAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,CAAC,IAAA,KAAwB;AACzD,IAAA,IAAI,KAAA,CAAM,OAAA,EAAS,UAAA,KAAe,SAAA,CAAU,IAAA,EAAM;AAChD,MAAA,MAAM,OAAA,GAAU,aAAA,CAAc,WAAA,EAAa,IAAI,CAAA;AAC/C,MAAA,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,IAC5C,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,KAAK,0DAA0D,CAAA;AAAA,IACzE;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AAEd,IAAA,eAAA,CAAgB,OAAA,GAAU,KAAA;AAG1B,IAAA,IAAI,KAAA,CAAM,OAAA,EAAS,UAAA,KAAe,SAAA,CAAU,IAAA,EAAM;AAChD,MAAA;AAAA,IACF;AAIA,IAAA,IAAI,gBAAA,GAAyD,IAAA;AAE7D,IAAA,MAAM,UAAU,MAAM;AACpB,MAAA,IAAI,MAAM,OAAA,EAAS,UAAA,KAAe,SAAA,CAAU,IAAA,IAAQ,gBAAgB,OAAA,EAAS;AAC3E,QAAA;AAAA,MACF;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,EAAA,GAAK,IAAI,SAAA,CAAU,CAAA,eAAA,EAAkB,IAAI,CAAA,CAAE,CAAA;AAEjD,QAAA,IAAI,sBAAA,GAAyB,KAAA;AAE7B,QAAA,EAAA,CAAG,SAAS,MAAM;AAChB,UAAA,IAAI,gBAAgB,OAAA,EAAS;AAC3B,YAAA,sBAAA,GAAyB,IAAA;AACzB,YAAA,EAAA,CAAG,KAAA,EAAM;AACT,YAAA;AAAA,UACF;AACA,UAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAC1B,UAAA,OAAA,CAAQ,IAAI,wCAAwC,CAAA;AACpD,UAAA,YAAA,CAAa,IAAI,CAAA;AACjB,UAAA,qBAAA,CAAsB,UAAU,IAAI,CAAA;AAGpC,UAAA,eAAA,CAAgB,OAAA,GAAU,YAAY,MAAM;AAC1C,YAAA,IAAI,EAAA,CAAG,UAAA,KAAe,SAAA,CAAU,IAAA,EAAM;AACpC,cAAA,EAAA,CAAG,KAAK,IAAA,CAAK,SAAA,CAAU,aAAA,CAAc,MAAM,CAAC,CAAC,CAAA;AAAA,YAC/C;AAAA,UACF,GAAG,IAAK,CAAA;AAAA,QACV,CAAA;AAEA,QAAA,EAAA,CAAG,UAAU,MAAM;AAEjB,UAAA,IAAI,gBAAgB,OAAA,IAAW,CAAC,sBAAA,IAA0B,CAAC,gBAAgB,OAAA,EAAS;AAClF,YAAA,OAAA,CAAQ,IAAI,6CAA6C,CAAA;AAAA,UAC3D;AACA,UAAA,YAAA,CAAa,KAAK,CAAA;AAClB,UAAA,WAAA,CAAY,IAAI,CAAA;AAChB,UAAA,qBAAA,CAAsB,UAAU,KAAK,CAAA;AAErC,UAAA,IAAI,gBAAgB,OAAA,EAAS;AAC3B,YAAA,aAAA,CAAc,gBAAgB,OAAO,CAAA;AACrC,YAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAAA,UAC5B;AAGA,UAAA,IAAI,CAAC,gBAAgB,OAAA,EAAS;AAC5B,YAAA,mBAAA,CAAoB,OAAA,GAAU,WAAW,MAAM;AAC7C,cAAA,OAAA,EAAQ;AAAA,YACV,GAAG,GAAI,CAAA;AAAA,UACT;AAAA,QACF,CAAA;AAEA,QAAA,EAAA,CAAG,UAAU,MAAM;AAAA,QAGnB,CAAA;AAEA,QAAA,EAAA,CAAG,SAAA,GAAY,CAAC,KAAA,KAAwB;AACtC,UAAA,IAAI;AACF,YAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AACpC,YAAA,MAAM,MAAA,GAAS,sBAAA,CAAuB,SAAA,CAAU,MAAM,CAAA;AAEtD,YAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,cAAA,OAAA,CAAQ,IAAA,CAAK,qCAAA,EAAuC,MAAA,CAAO,KAAK,CAAA;AAChE,cAAA;AAAA,YACF;AAEA,YAAA,MAAM,UAAU,MAAA,CAAO,IAAA;AAEvB,YAAA,QAAQ,QAAQ,IAAA;AAAM,cACpB,KAAK,SAAA;AACH,gBAAA,WAAA,CAAY,OAAA,CAAQ,QAAQ,QAAQ,CAAA;AACpC,gBAAA;AAAA,cAEF,KAAK,eAAA;AACH,gBAAA,wBAAA,CAAyB,OAAA;AAAA,kBACtB,QAAiC,OAAA,CAAQ,OAAA;AAAA,kBACzC,QAAiC,OAAA,CAAQ;AAAA,iBAC5C;AACA,gBAAA;AAAA,cAEF,KAAK,MAAA;AAEH,gBAAA;AAAA,cAEF;AACE,gBAAA;AAAA;AACJ,UACF,SAAS,KAAA,EAAO;AACd,YAAA,OAAA,CAAQ,KAAA,CAAM,8CAA8C,KAAK,CAAA;AAAA,UACnE;AAAA,QACF,CAAA;AAEA,QAAA,KAAA,CAAM,OAAA,GAAU,EAAA;AAAA,MAClB,SAAS,KAAA,EAAO;AAGd,QAAA,IAAI,CAAC,gBAAgB,OAAA,EAAS;AAC5B,UAAA,mBAAA,CAAoB,OAAA,GAAU,WAAW,MAAM;AAC7C,YAAA,OAAA,EAAQ;AAAA,UACV,GAAG,GAAI,CAAA;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAA;AAIA,IAAA,gBAAA,GAAmB,WAAW,MAAM;AAClC,MAAA,gBAAA,GAAmB,IAAA;AACnB,MAAA,IAAI,CAAC,gBAAgB,OAAA,EAAS;AAC5B,QAAA,OAAA,EAAQ;AAAA,MACV;AAAA,IACF,GAAG,GAAG,CAAA;AAEN,IAAA,OAAO,MAAM;AACX,MAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAG1B,MAAA,IAAI,gBAAA,EAAkB;AACpB,QAAA,YAAA,CAAa,gBAAgB,CAAA;AAC7B,QAAA,gBAAA,GAAmB,IAAA;AAAA,MACrB;AAEA,MAAA,IAAI,oBAAoB,OAAA,EAAS;AAC/B,QAAA,YAAA,CAAa,oBAAoB,OAAO,CAAA;AACxC,QAAA,mBAAA,CAAoB,OAAA,GAAU,IAAA;AAAA,MAChC;AACA,MAAA,IAAI,gBAAgB,OAAA,EAAS;AAC3B,QAAA,aAAA,CAAc,gBAAgB,OAAO,CAAA;AACrC,QAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAAA,MAC5B;AACA,MAAA,IAAI,MAAM,OAAA,EAAS;AAEjB,QAAA,IAAI,KAAA,CAAM,QAAQ,UAAA,KAAe,SAAA,CAAU,QACvC,KAAA,CAAM,OAAA,CAAQ,UAAA,KAAe,SAAA,CAAU,UAAA,EAAY;AACrD,UAAA,KAAA,CAAM,QAAQ,KAAA,EAAM;AAAA,QACtB;AACA,QAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF;AACF;ACnMO,SAAS,oBAAoB,OAAA,EAA2C;AAC7E,EAAA,MAAM,EAAE,GAAA,GAAM,GAAA,EAAK,SAAA,EAAW,OAAA,GAAU,MAAK,GAAI,OAAA;AAEjD,EAAA,MAAM,aAAA,GAAgBC,WAAAA;AAAA,IACpB,CAAC,KAAA,KAAyB;AACxB,MAAA,IAAI,CAAC,OAAA,EAAS;AAGd,MAAA,MAAM,QAAQ,SAAA,CAAU,QAAA,CAAS,aAAY,CAAE,OAAA,CAAQ,KAAK,CAAA,IAAK,CAAA;AACjE,MAAA,MAAM,WAAA,GAAc,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,KAAA,CAAM,OAAA;AAElD,MAAA,IAAI,WAAA,IAAe,MAAM,MAAA,IAAU,KAAA,CAAM,IAAI,WAAA,EAAY,KAAM,GAAA,CAAI,WAAA,EAAY,EAAG;AAChF,QAAA,KAAA,CAAM,cAAA,EAAe;AACrB,QAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,QAAA,SAAA,EAAU;AAAA,MACZ;AAAA,IACF,CAAA;AAAA,IACA,CAAC,GAAA,EAAK,SAAA,EAAW,OAAO;AAAA,GAC1B;AAEA,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAA,EAAW,aAAA,EAAe,IAAI,CAAA;AAEtD,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,aAAA,EAAe,IAAI,CAAA;AAAA,IAC3D,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,aAAA,EAAe,OAAO,CAAC,CAAA;AAC7B;AC9BO,SAAS,gBAAA,GAA2C;AACzD,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAIC,SAAS,KAAK,CAAA;AAC5D,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAIA,QAAAA,EAA6B;AAE7E,EAAA,MAAM,mBAAA,GAAsBF,WAAAA,CAAY,CAAC,OAAA,KAAqB;AAC5D,IAAA,kBAAA,CAAmB,IAAI,CAAA;AACvB,IAAA,mBAAA,CAAoB,OAAO,CAAA;AAAA,EAC7B,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,oBAAA,GAAuBA,YAAY,MAAM;AAC7C,IAAA,kBAAA,CAAmB,KAAK,CAAA;AACxB,IAAA,mBAAA,CAAoB,MAAS,CAAA;AAAA,EAC/B,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,mBAAA,GAAsBA,YAAY,MAAM;AAC5C,IAAA,kBAAA,CAAmB,CAAC,IAAA,KAAS,CAAC,IAAI,CAAA;AAClC,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,mBAAA,CAAoB,MAAS,CAAA;AAAA,IAC/B;AAAA,EACF,CAAA,EAAG,CAAC,eAAe,CAAC,CAAA;AAEpB,EAAA,OAAO;AAAA,IACL,eAAA;AAAA,IACA,gBAAA;AAAA,IACA,mBAAA;AAAA,IACA,oBAAA;AAAA,IACA;AAAA,GACF;AACF;ACTA,IAAM,UAAA,GAAa;AAAA,EACjB,iBAAA,EAAmB,CAAA;AAAA,EACnB,cAAA,EAAgB,CAAA;AAAA,EAChB,UAAA,EAAY,EAAA;AAAA,EACZ,aAAA,EAAe,EAAA;AAAA,EACf,mBAAA,EAAqB;AACvB,CAAA;AAuBO,SAAS,iBAAA,GAA6C;AAI3D,EAAA,MAAM,mBAAA,GAAsBA,WAAAA,CAAY,CAAC,OAAA,KAAuC;AAE9E,IAAA,IAAI,MAAA,CAAO,gCAAgC,SAAA,EAAW;AACpD,MAAA,KAAA,MAAW,QAAA,IAAY,MAAA,CAAO,8BAAA,CAA+B,SAAA,CAAU,QAAO,EAAG;AAC/E,QAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,uBAAA,GAA0B,OAAO,CAAA;AACxD,QAAA,IAAI,OAAO,OAAO,KAAA;AAAA,MACpB;AAAA,IACF;AAGA,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,IAAA;AAAA,MACpC,CAAC,QAAQ,GAAA,CAAI,UAAA,CAAW,eAAe,CAAA,IAAK,GAAA,CAAI,WAAW,0BAA0B;AAAA,KACvF;AAEA,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,KAAA,GAAS,QAAyD,QAAQ,CAAA;AAChF,MAAA,OAAO,KAAA,IAAS,IAAA;AAAA,IAClB;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,gBAAA,GAAmBA,WAAAA,CAAY,CAAC,KAAA,KAAgC;AACpE,IAAA,QAAQ,MAAM,GAAA;AAAK,MACjB,KAAK,UAAA,CAAW,cAAA;AACd,QAAA,OAAO,OAAA;AAAA,MACT,KAAK,UAAA,CAAW,UAAA;AACd,QAAA,OAAO,YAAA;AAAA,MACT,KAAK,UAAA,CAAW,aAAA;AAAA,MAChB,KAAK,UAAA,CAAW,mBAAA;AACd,QAAA,OAAO,MAAA;AAAA,MACT,KAAK,UAAA,CAAW,iBAAA;AAAA,MAChB;AACE,QAAA,OAAO,UAAA;AAAA;AACX,EACF,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,gBAAA,GAAmBA,WAAAA,CAAY,CAAC,KAAA,KAAyB;AAC7D,IAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AAEnB,IAAA,IAAI,CAAC,MAAM,OAAO,SAAA;AAGlB,IAAA,IAAI,OAAO,SAAS,UAAA,EAAY;AAC9B,MAAA,MAAM,EAAA,GAAK,IAAA;AACX,MAAA,OAAO,EAAA,CAAG,WAAA,IAAe,EAAA,CAAG,IAAA,IAAQ,WAAA;AAAA,IACtC;AAGA,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,EAAM;AAC7C,MAAA,MAAM,GAAA,GAAM,IAAA;AAEZ,MAAA,IAAI,GAAA,CAAI,WAAA,EAAa,OAAO,GAAA,CAAI,WAAA;AAChC,MAAA,IAAI,GAAA,CAAI,QAAQ,OAAO,GAAA,CAAI,OAAO,WAAA,IAAe,GAAA,CAAI,OAAO,IAAA,IAAQ,YAAA;AACpE,MAAA,IAAI,GAAA,CAAI,MAAM,OAAO,GAAA,CAAI,KAAK,WAAA,IAAe,GAAA,CAAI,KAAK,IAAA,IAAQ,MAAA;AAAA,IAChE;AAEA,IAAA,OAAO,SAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,yBAAA,GAA4BA,WAAAA,CAAY,CAAC,KAAA,KAA+B;AAC5E,IAAA,IAAI,OAAA,GAAwB,KAAA;AAE5B,IAAA,OAAO,OAAA,EAAS;AAEd,MAAA,MAAM,MAAM,OAAA,CAAQ,GAAA;AACpB,MAAA,IACE,GAAA,KAAQ,UAAA,CAAW,iBAAA,IACnB,GAAA,KAAQ,WAAW,cAAA,IACnB,GAAA,KAAQ,UAAA,CAAW,UAAA,IACnB,GAAA,KAAQ,UAAA,CAAW,aAAA,IACnB,GAAA,KAAQ,WAAW,mBAAA,EACnB;AACA,QAAA,MAAM,IAAA,GAAO,iBAAiB,OAAO,CAAA;AAErC,QAAA,IAAI,CAAC,KAAK,UAAA,CAAW,GAAG,KAAK,IAAA,KAAS,SAAA,IAAa,SAAS,WAAA,EAAa;AACvE,UAAA,OAAO,OAAA;AAAA,QACT;AAAA,MACF;AAEA,MAAA,OAAA,GAAU,OAAA,CAAQ,MAAA;AAAA,IACpB;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,EAAG,CAAC,gBAAgB,CAAC,CAAA;AAKrB,EAAA,MAAM,mBAAA,GAAsBA,WAAAA;AAAA,IAC1B,CAAC,KAAA,KAA2B;AAC1B,MAAA,MAAM,UAAoB,EAAC;AAC3B,MAAA,IAAI,UAAU,KAAA,CAAM,MAAA;AAEpB,MAAA,OAAO,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,EAAA,EAAI;AACrC,QAAA,MAAM,MAAM,OAAA,CAAQ,GAAA;AACpB,QAAA,IACE,GAAA,KAAQ,UAAA,CAAW,iBAAA,IACnB,GAAA,KAAQ,WAAW,cAAA,IACnB,GAAA,KAAQ,UAAA,CAAW,UAAA,IACnB,GAAA,KAAQ,UAAA,CAAW,aAAA,IACnB,GAAA,KAAQ,WAAW,mBAAA,EACnB;AACA,UAAA,MAAM,IAAA,GAAO,iBAAiB,OAAO,CAAA;AACrC,UAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,IAAK,SAAS,SAAA,EAAW;AAC/C,YAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,UACnB;AAAA,QACF;AACA,QAAA,OAAA,GAAU,OAAA,CAAQ,MAAA;AAAA,MACpB;AAEA,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,gBAAgB;AAAA,GACnB;AAKA,EAAA,MAAM,cAAA,GAAiBA,WAAAA,CAAY,CAAC,KAAA,KAA4D;AAC9F,IAAA,MAAM,SAAkC,EAAC;AAEzC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAEhD,MAAA,IAAI,GAAA,KAAQ,UAAA,IAAc,GAAA,KAAQ,KAAA,IAAS,QAAQ,KAAA,EAAO;AAE1D,MAAA,IAAI;AACF,QAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC/B,UAAA,MAAA,CAAO,GAAG,CAAA,GAAI,YAAA;AAAA,QAChB,CAAA,MAAA,IAAW,iBAAiB,OAAA,EAAS;AACnC,UAAA,MAAA,CAAO,GAAG,CAAA,GAAI,WAAA;AAAA,QAChB,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,IAAA,EAAM;AAEtD,UAAA,IAAA,CAAK,UAAU,KAAK,CAAA;AACpB,UAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,QAChB,CAAA,MAAO;AACL,UAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,QAChB;AAAA,MACF,CAAA,CAAA,MAAQ;AACN,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,8BAAA;AAAA,MAChB;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,YAAA,GAAeA,WAAAA,CAAY,CAAC,KAAA,KAAiD;AACjF,IAAA,IAAI,KAAA,CAAM,GAAA,KAAQ,UAAA,CAAW,cAAA,EAAgB;AAC3C,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,WAAW,KAAA,CAAM,SAAA;AACvB,IAAA,IAAI,UAAU,KAAA,EAAO;AACnB,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,SAAA,CAAU,SAAS,KAAK,CAAA;AAC7B,QAAA,OAAO,QAAA,CAAS,KAAA;AAAA,MAClB,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,EAAE,OAAO,wBAAA,EAAyB;AAAA,MAC3C;AAAA,IACF;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,gBAAA,GAAmBA,WAAAA;AAAA,IACvB,CAAC,KAAA,KAA4B;AAC3B,MAAA,OAAO;AAAA,QACL,aAAA,EAAe;AAAA,UACb,IAAA,EAAM,iBAAiB,KAAK,CAAA;AAAA,UAC5B,IAAA,EAAM,iBAAiB,KAAK;AAAA,SAC9B;AAAA,QACA,KAAA,EAAO,cAAA,CAAe,KAAA,CAAM,aAAA,IAAiB,EAAE,CAAA;AAAA,QAC/C,KAAA,EAAO,aAAa,KAAK,CAAA;AAAA,QACzB,gBAAA,EAAkB,oBAAoB,KAAK,CAAA;AAAA,QAC3C,WAAA,EAAa;AAAA,UACX,QAAA,EAAU,KAAA,CAAM,YAAA,EAAc,QAAA,IAAY,IAAA;AAAA,UAC1C,UAAA,EAAY,KAAA,CAAM,YAAA,EAAc,UAAA,IAAc,IAAA;AAAA,UAC9C,YAAA,EAAc,KAAA,CAAM,YAAA,EAAc,YAAA,IAAgB;AAAA;AACpD,OACF;AAAA,IACF,CAAA;AAAA,IACA,CAAC,gBAAA,EAAkB,gBAAA,EAAkB,cAAA,EAAgB,cAAc,mBAAmB;AAAA,GACxF;AAEA,EAAA,OAAO;AAAA,IACL,mBAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACF;AACF;AC1PO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,OAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAqD;AACnD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIE,SAA+B,IAAI,CAAA;AACrE,EAAA,MAAM,iBAAA,GAAoBC,OAA2B,IAAI,CAAA;AAGzD,EAAA,MAAM,gBAAA,GAAmBH,WAAAA,CAAY,CAAC,OAAA,KAAiC;AAErE,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,IAAA;AAAA,MACpC,CAAC,MAAM,CAAA,CAAE,UAAA,CAAW,eAAe,CAAA,IAAK,CAAA,CAAE,WAAW,0BAA0B;AAAA,KACjF;AAEA,IAAA,IAAI,SAAA,GAA2B,IAAA;AAC/B,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,KAAA,GAAS,QAA+C,QAAQ,CAAA;AAMtE,MAAA,IAAI,KAAA,EAAO,IAAA,IAAQ,OAAO,KAAA,CAAM,SAAS,UAAA,EAAY;AACnD,QAAA,MAAM,KAAK,KAAA,CAAM,IAAA;AACjB,QAAA,SAAA,GAAY,EAAA,CAAG,WAAA,IAAe,EAAA,CAAG,IAAA,IAAQ,IAAA;AAAA,MAC3C;AAGA,MAAA,IAAI,CAAC,SAAA,IAAa,SAAA,KAAc,KAAA,IAAS,cAAc,QAAA,EAAU;AAC/D,QAAA,IAAI,OAAA,GAAU,KAAA;AACd,QAAA,OAAO,SAAS,MAAA,EAAQ;AACtB,UAAA,OAAA,GAAU,OAAA,CAAQ,MAAA;AAClB,UAAA,IAAI,OAAA,EAAS,IAAA,IAAQ,OAAO,OAAA,CAAQ,SAAS,UAAA,EAAY;AACvD,YAAA,MAAM,KAAK,OAAA,CAAQ,IAAA;AACnB,YAAA,MAAM,IAAA,GAAO,EAAA,CAAG,WAAA,IAAe,EAAA,CAAG,IAAA;AAClC,YAAA,IAAI,IAAA,IAAQ,CAAC,CAAC,UAAA,EAAY,UAAA,EAAY,YAAY,UAAU,CAAA,CAAE,QAAA,CAAS,IAAI,CAAA,EAAG;AAC5E,cAAA,SAAA,GAAY,IAAA;AACZ,cAAA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,EAAa,IAAA,GAAO,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,IAAK,EAAA;AAChE,IAAA,MAAM,UAAA,GAAa,WAAA,GAAc,CAAA,EAAA,EAAK,WAAW,CAAA,EAAG,OAAA,CAAQ,WAAA,IAAe,OAAA,CAAQ,WAAA,CAAY,MAAA,GAAS,EAAA,GAAK,KAAA,GAAQ,EAAE,CAAA,CAAA,CAAA,GAAM,EAAA;AAG7H,IAAA,IAAI,SAAA,IAAa,CAAC,CAAC,KAAA,EAAO,UAAU,MAAA,EAAQ,GAAA,EAAK,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA,CAAE,QAAA,CAAS,SAAA,CAAU,WAAA,EAAa,CAAA,EAAG;AACpG,MAAA,OAAO,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAAA,IACpC;AAGA,IAAA,IAAI,OAAA,CAAQ,aAAa,OAAO,OAAA,CAAQ,cAAc,QAAA,IAAY,OAAA,CAAQ,SAAA,CAAU,IAAA,EAAK,EAAG;AAC1F,MAAA,MAAM,OAAA,GAAU,QAAQ,SAAA,CAAU,IAAA,GAAO,KAAA,CAAM,KAAK,EAAE,CAAC,CAAA;AACvD,MAAA,OAAO,CAAA,CAAA,EAAI,OAAO,CAAA,EAAG,UAAU,CAAA,CAAA;AAAA,IACjC;AAGA,IAAA,OAAO,IAAI,OAAA,CAAQ,OAAA,CAAQ,WAAA,EAAa,IAAI,UAAU,CAAA,CAAA;AAAA,EACxD,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,eAAA,GAAkBA,WAAAA;AAAA,IACtB,CAAC,KAAA,KAAsB;AACrB,MAAA,IAAI,CAAC,OAAA,EAAS;AAEd,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AAGrB,MAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,yBAAyB,CAAA,EAAG;AAC7C,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,iBAAA,CAAkB,OAAA,GAAU,IAAA;AAC5B,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,CAAC,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,OAAA,EAAS,UAAU,CAAA,CAAE,QAAA,CAAS,MAAA,CAAO,OAAO,CAAA,EAAG;AAC5E,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,iBAAA,CAAkB,OAAA,GAAU,IAAA;AAC5B,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,OAAO,qBAAA,EAAsB;AAC1C,MAAA,iBAAA,CAAkB,OAAA,GAAU,MAAA;AAE5B,MAAA,YAAA,CAAa;AAAA,QACX,KAAK,IAAA,CAAK,GAAA;AAAA,QACV,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,aAAA,EAAe,iBAAiB,MAAM;AAAA,OACvC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,SAAS,gBAAgB;AAAA,GAC5B;AAGA,EAAA,MAAM,WAAA,GAAcA,WAAAA;AAAA,IAClB,CAAC,KAAA,KAAsB;AACrB,MAAA,IAAI,CAAC,OAAA,EAAS;AAEd,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AAGrB,MAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,yBAAyB,CAAA,EAAG;AAC7C,QAAA;AAAA,MACF;AAEA,MAAA,KAAA,CAAM,cAAA,EAAe;AACrB,MAAA,KAAA,CAAM,eAAA,EAAgB;AAEtB,MAAA,IAAI,kBAAkB,OAAA,EAAS;AAC7B,QAAA,QAAA,CAAS,kBAAkB,OAAO,CAAA;AAAA,MACpC;AAAA,IACF,CAAA;AAAA,IACA,CAAC,SAAS,QAAQ;AAAA,GACpB;AAGA,EAAA,MAAM,aAAA,GAAgBA,WAAAA;AAAA,IACpB,CAAC,KAAA,KAAyB;AACxB,MAAA,IAAI,CAAC,OAAA,EAAS;AAEd,MAAA,IAAI,KAAA,CAAM,QAAQ,QAAA,EAAU;AAC1B,QAAA,KAAA,CAAM,cAAA,EAAe;AACrB,QAAA,QAAA,EAAS;AAAA,MACX;AAAA,IACF,CAAA;AAAA,IACA,CAAC,SAAS,QAAQ;AAAA,GACpB;AAGA,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,iBAAA,CAAkB,OAAA,GAAU,IAAA;AAC5B,MAAA;AAAA,IACF;AAEA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAA,EAAa,eAAA,EAAiB,IAAI,CAAA;AAC5D,IAAA,QAAA,CAAS,gBAAA,CAAiB,OAAA,EAAS,WAAA,EAAa,IAAI,CAAA;AACpD,IAAA,QAAA,CAAS,gBAAA,CAAiB,SAAA,EAAW,aAAA,EAAe,IAAI,CAAA;AAGxD,IAAA,QAAA,CAAS,IAAA,CAAK,MAAM,MAAA,GAAS,WAAA;AAE7B,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAA,EAAa,eAAA,EAAiB,IAAI,CAAA;AAC/D,MAAA,QAAA,CAAS,mBAAA,CAAoB,OAAA,EAAS,WAAA,EAAa,IAAI,CAAA;AACvD,MAAA,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,aAAA,EAAe,IAAI,CAAA;AAC3D,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,MAAA,GAAS,EAAA;AAAA,IAC/B,CAAA;AAAA,EACF,GAAG,CAAC,OAAA,EAAS,eAAA,EAAiB,WAAA,EAAa,aAAa,CAAC,CAAA;AAEzD,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAErB,EAAA,uCAGK,QAAA,EAAA,SAAA,oBACC,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,uBAAA,EAAsB,WAAA;AAAA,MACtB,KAAA,EAAO;AAAA,QACL,QAAA,EAAU,OAAA;AAAA,QACV,KAAK,SAAA,CAAU,GAAA;AAAA,QACf,MAAM,SAAA,CAAU,IAAA;AAAA,QAChB,OAAO,SAAA,CAAU,KAAA;AAAA,QACjB,QAAQ,SAAA,CAAU,MAAA;AAAA,QAClB,MAAA,EAAQ,mBAAA;AAAA,QACR,eAAA,EAAiB,yBAAA;AAAA,QACjB,aAAA,EAAe,MAAA;AAAA,QACf,MAAA,EAAQ,MAAA;AAAA,QACR,SAAA,EAAW;AAAA,OACb;AAAA,MAGA,QAAA,kBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO;AAAA,YACL,QAAA,EAAU,UAAA;AAAA,YACV,GAAA,EAAK,GAAA;AAAA,YACL,IAAA,EAAM,EAAA;AAAA,YACN,OAAA,EAAS,SAAA;AAAA,YACT,eAAA,EAAiB,SAAA;AAAA,YACjB,KAAA,EAAO,OAAA;AAAA,YACP,QAAA,EAAU,MAAA;AAAA,YACV,UAAA,EAAY,uBAAA;AAAA,YACZ,UAAA,EAAY,GAAA;AAAA,YACZ,YAAA,EAAc,aAAA;AAAA,YACd,UAAA,EAAY,QAAA;AAAA,YACZ,QAAA,EAAU,OAAA;AAAA,YACV,QAAA,EAAU,QAAA;AAAA,YACV,YAAA,EAAc;AAAA,WAChB;AAAA,UAEC,QAAA,EAAA,SAAA,CAAU;AAAA;AAAA;AACb;AAAA,GACF,EAGJ,CAAA;AAEJ;;;AC/MO,SAAS,gBAAgB,KAAA,EAA4B;AAC1D,EAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AACpB,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAC;AAEpB,EAAA,MAAM,SAAuB,EAAC;AAC9B,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AAE9B,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,eAAe,IAAI,CAAA;AACjC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACnB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAKA,SAAS,eAAe,IAAA,EAAiC;AAKvD,EAAA,MAAM,cAAc,IAAA,CAAK,KAAA;AAAA,IACvB;AAAA,GACF;AACA,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,OAAO;AAAA,MACL,YAAA,EAAc,WAAA,CAAY,CAAC,CAAA,IAAK,IAAA;AAAA,MAChC,GAAA,EAAK,YAAY,CAAC,CAAA;AAAA,MAClB,UAAA,EAAY,QAAA,CAAS,WAAA,CAAY,CAAC,GAAI,EAAE,CAAA;AAAA,MACxC,YAAA,EAAc,QAAA,CAAS,WAAA,CAAY,CAAC,GAAI,EAAE;AAAA,KAC5C;AAAA,EACF;AAKA,EAAA,MAAM,eAAe,IAAA,CAAK,KAAA;AAAA,IACxB;AAAA,GACF;AACA,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,OAAO;AAAA,MACL,YAAA,EAAc,YAAA,CAAa,CAAC,CAAA,IAAK,IAAA;AAAA,MACjC,GAAA,EAAK,aAAa,CAAC,CAAA;AAAA,MACnB,UAAA,EAAY,QAAA,CAAS,YAAA,CAAa,CAAC,GAAI,EAAE,CAAA;AAAA,MACzC,YAAA,EAAc,QAAA,CAAS,YAAA,CAAa,CAAC,GAAI,EAAE;AAAA,KAC7C;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAKO,SAAS,qBAAqB,MAAA,EAAoC;AACvE,EAAA,MAAM,gBAAA,GAAmB;AAAA,IACvB,cAAA;AAAA,IACA,WAAA;AAAA,IACA,mBAAA;AAAA,IACA,oBAAA;AAAA,IACA,WAAA;AAAA,IACA,kCAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA;AAAA,IAEA,8EAAA;AAAA,IACA,kEAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,KAAA,KAAU;AAE9B,IAAA,KAAA,MAAW,WAAW,gBAAA,EAAkB;AACtC,MAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,EAAG;AAC3B,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAGA,IAAA,IAAI,MAAM,YAAA,EAAc;AACtB,MAAA,KAAA,MAAW,WAAW,gBAAA,EAAkB;AACtC,QAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,YAAY,CAAA,EAAG;AACpC,UAAA,OAAO,KAAA;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAC,CAAA;AACH;;;ACjFA,eAAsB,qBAAA,CACpB,OACA,QAAA,EACyB;AAEzB,EAAA,MAAM,iBAAA,GAAoB,eAAe,KAAK,CAAA;AAC9C,EAAA,IAAI,kBAAkB,QAAA,EAAU;AAC9B,IAAA,OAAO,iBAAA;AAAA,EACT;AAGA,EAAA,MAAM,cAAc,oBAAA,EAAqB;AACzC,EAAA,IAAI,aAAa,QAAA,EAAU;AACzB,IAAA,OAAO,WAAA;AAAA,EACT;AAGA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,IAAA;AAAA,IACV,UAAA,EAAY,IAAA;AAAA,IACZ,YAAA,EAAc;AAAA,GAChB;AACF;AAMA,SAAS,eAAe,KAAA,EAAqC;AAC3D,EAAA,IAAI,CAAC,OAAO,YAAA,EAAc;AACxB,IAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,cAAc,IAAA,EAAK;AAAA,EAChE;AAEA,EAAA,MAAM,EAAE,QAAA,EAAU,UAAA,EAAY,YAAA,KAAiB,KAAA,CAAM,YAAA;AAErD,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,cAAc,IAAA,EAAK;AAAA,EAChE;AAEA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,eAAe,QAAQ,CAAA;AAAA,IACjC,YAAY,UAAA,IAAc,IAAA;AAAA,IAC1B,cAAc,YAAA,IAAgB;AAAA,GAChC;AACF;AAMA,SAAS,oBAAA,GAA8C;AACrD,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,EAAM;AACxB,IAAA,MAAM,MAAA,GAAS,gBAAgB,KAAK,CAAA;AACpC,IAAA,MAAM,UAAA,GAAa,qBAAqB,MAAM,CAAA;AAE9C,IAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,KAAA,GAAQ,WAAW,CAAC,CAAA;AAG1B,IAAA,MAAM,QAAA,GAAW,sBAAA,CAAuB,KAAA,CAAM,GAAG,CAAA;AACjD,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,YAAY,KAAA,CAAM,UAAA;AAAA,MAClB,cAAc,KAAA,CAAM;AAAA,KACtB;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKA,SAAS,uBAAuB,GAAA,EAA4B;AAC1D,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,IAAI,OAAO,MAAA,CAAO,QAAA;AAGlB,IAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAG9B,IAAA,IAAA,GAAO,IAAA,CAEJ,QAAQ,0BAAA,EAA4B,EAAE,EACtC,OAAA,CAAQ,gCAAA,EAAkC,QAAQ,CAAA,CAElD,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAA,CACtB,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAA,CAEtB,OAAA,CAAQ,wBAAwB,EAAE,CAAA,CAElC,OAAA,CAAQ,gBAAA,EAAkB,EAAE,CAAA;AAG/B,IAAA,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,GAAG,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,IAAA;AAI5C,IAAA,IAAI,CAAC,KAAK,QAAA,CAAS,GAAG,KAAK,CAAC,IAAA,CAAK,KAAA,CAAM,oBAAoB,CAAA,EAAG;AAC5D,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,IAAA,IAAQ,IAAA;AAAA,EACjB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,GAAA;AAAA,EACT;AACF;AAKO,SAAS,eAAe,QAAA,EAAwC;AACrE,EAAA,IAAI,CAAC,UAAU,OAAO,IAAA;AAEtB,EAAA,IAAI,UAAU,QAAA,CAEX,OAAA,CAAQ,sBAAA,EAAwB,EAAE,EAElC,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA,CAEpB,QAAQ,MAAA,EAAQ,EAAE,CAAA,CAElB,OAAA,CAAQ,kBAAkB,EAAE,CAAA;AAG/B,EAAA,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAEpC,EAAA,OAAO,OAAA;AACT;;;ACpJO,SAAS,eAAe,OAAA,EAA+B;AAC5D,EAAA,MAAM,IAAA,GAAO,QAAQ,qBAAA,EAAsB;AAE3C,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAA,CAAQ,OAAA,CAAQ,WAAA,EAAY;AAAA,IACrC,SAAA,EAAW,QAAQ,SAAA,IAAa,IAAA;AAAA,IAChC,YAAA,EAAc;AAAA,MACZ,GAAG,IAAA,CAAK,CAAA;AAAA,MACR,GAAG,IAAA,CAAK,CAAA;AAAA,MACR,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,KAAK,IAAA,CAAK,GAAA;AAAA,MACV,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,MAAM,IAAA,CAAK;AAAA;AACb,GACF;AACF;AAKA,eAAsB,kBAAA,CACpB,OAAA,EACA,SAAA,EACA,OAAA,GAA2B,EAAC,EACJ;AAGxB,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS;AAAA,IAC7B,cAAc,SAAA,CAAU;AAAA,GAC1B;AACA,EAAA,MAAM,MAAA,GAAS,MAAM,qBAAA,CAAsB,KAAc,CAAA;AAGzD,EAAA,MAAM,aAAA,GAA+B;AAAA,IACnC,IAAI,MAAA,EAAO;AAAA,IACX,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,IACpB,WAAW,SAAA,CAAU,aAAA;AAAA,IACrB,MAAA,EAAQ;AAAA,MACN,QAAA,EAAU,cAAA,CAAe,MAAA,CAAO,QAAQ,CAAA;AAAA,MACxC,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,cAAc,MAAA,CAAO;AAAA,KACvB;AAAA,IACA,OAAO,SAAA,CAAU,KAAA;AAAA,IACjB,OAAO,SAAA,CAAU,KAAA;AAAA,IACjB,GAAA,EAAK,eAAe,OAAO,CAAA;AAAA,IAC3B,OAAA,EAAS;AAAA,MACP,OAAA,EAAS,OAAO,QAAA,CAAS,IAAA;AAAA,MACzB,kBAAkB,SAAA,CAAU;AAAA;AAC9B,GACF;AAEA,EAAA,OAAO,aAAA;AACT;AC9CO,SAAS,gBAAgB,KAAA,EAAwC;AAEtE,EAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA,EAAe;AAC1C,IAAA,OAAO,KAAA,CAAM,QAAA;AAAA,EACf;AAEA,EAAA,uBAAOG,GAAAA,CAAC,mBAAA,EAAA,EAAqB,GAAG,KAAA,EAAO,CAAA;AACzC;AAKA,SAAS,mBAAA,CAAoB;AAAA,EAC3B,IAAA,GAAO,IAAA;AAAA,EACP,QAAA;AAAA,EACA,WAAA,GAAc,GAAA;AAAA,EACd,kBAAA;AAAA,EACA;AACF,CAAA,EAA6C;AAC3C,EAAA,MAAM,EAAE,eAAA,EAAiB,gBAAA,EAAkB,mBAAA,EAAqB,oBAAA,KAC9D,gBAAA,EAAiB;AAEnB,EAAA,MAAM,EAAE,mBAAA,EAAqB,gBAAA,EAAkB,yBAAA,KAA8B,iBAAA,EAAkB;AAE/F,EAAA,MAAM,EAAE,SAAA,EAAW,aAAA,EAAc,GAAI,kBAAA,CAAmB;AAAA,IACtD,IAAA;AAAA,IACA,qBAAA,EAAuB,CAAC,OAAA,EAAS,OAAA,KAAY;AAC3C,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,mBAAA,CAAoB,OAAO,CAAA;AAAA,MAC7B,CAAA,MAAO;AACL,QAAA,oBAAA,EAAqB;AAAA,MACvB;AAAA,IACF,CAAA;AAAA,IACA;AAAA,GACD,CAAA;AAGD,EAAA,mBAAA,CAAoB;AAAA,IAClB,GAAA,EAAK,WAAA;AAAA,IACL,WAAW,MAAM;AACf,MAAA,IAAI,eAAA,EAAiB;AACnB,QAAA,oBAAA,EAAqB;AAAA,MACvB,CAAA,MAAO;AACL,QAAA,mBAAA,EAAoB;AAAA,MACtB;AAAA,IACF,CAAA;AAAA,IACA,OAAA,EAAS;AAAA,GACV,CAAA;AAGD,EAAA,MAAM,YAAA,GAAeJ,WAAAA;AAAA,IACnB,OAAO,OAAA,KAAyB;AAC9B,MAAA,IAAI;AAEF,QAAA,MAAM,KAAA,GAAQ,oBAAoB,OAAO,CAAA;AACzC,QAAA,IAAI,CAAC,KAAA,EAAO;AACV,UAAA,OAAA,CAAQ,KAAK,qDAAqD,CAAA;AAClE,UAAA,oBAAA,EAAqB;AACrB,UAAA;AAAA,QACF;AAGA,QAAA,MAAM,cAAA,GAAiB,0BAA0B,KAAK,CAAA;AACtD,QAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,UAAA,OAAA,CAAQ,KAAK,6CAA6C,CAAA;AAC1D,UAAA,oBAAA,EAAqB;AACrB,UAAA;AAAA,QACF;AAGA,QAAA,MAAM,SAAA,GAAY,iBAAiB,cAAc,CAAA;AAGjD,QAAA,MAAM,aAAA,GAAgB,MAAM,kBAAA,CAAmB,OAAA,EAAS,SAAA,EAAW;AAAA,UACjE,KAAA,EAAO;AAAA,SACR,CAAA;AAGD,QAAA,aAAA,CAAc,aAAa,CAAA;AAG3B,QAAA,QAAA,GAAW,aAAA,CAAc,SAAA,CAAU,IAAA,EAAM,aAAA,CAAc,OAAO,QAAQ,CAAA;AAEtE,QAAA,OAAA,CAAQ,GAAA;AAAA,UACN,CAAA,6BAAA,EAAgC,aAAA,CAAc,SAAA,CAAU,IAAI,CAAA,CAAA;AAAA,UAC5D,aAAA,CAAc,MAAA,CAAO,QAAA,GACjB,CAAA,GAAA,EAAM,aAAA,CAAc,MAAA,CAAO,QAAQ,CAAA,CAAA,EAAI,aAAA,CAAc,MAAA,CAAO,UAAU,CAAA,CAAA,GACtE;AAAA,SACN;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,uCAAuC,KAAK,CAAA;AAAA,MAC5D,CAAA,SAAE;AACA,QAAA,oBAAA,EAAqB;AAAA,MACvB;AAAA,IACF,CAAA;AAAA,IACA;AAAA,MACE,mBAAA;AAAA,MACA,yBAAA;AAAA,MACA,gBAAA;AAAA,MACA,aAAA;AAAA,MACA,oBAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAA,uBACE,IAAA,CAAAK,UAAA,EACG,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACDD,GAAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,eAAA;AAAA,QACT,QAAA,EAAU,YAAA;AAAA,QACV,QAAA,EAAU;AAAA;AAAA,KACZ;AAAA,IAEC,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA,oBACxB,IAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,uBAAA,EAAsB,QAAA;AAAA,QACtB,SAAS,MAAM;AACb,UAAA,IAAI,CAAC,SAAA,EAAW;AAChB,UAAA,IAAI,eAAA,EAAiB;AACnB,YAAA,oBAAA,EAAqB;AAAA,UACvB,CAAA,MAAO;AACL,YAAA,mBAAA,EAAoB;AAAA,UACtB;AAAA,QACF,CAAA;AAAA,QACA,KAAA,EAAO;AAAA,UACL,QAAA,EAAU,OAAA;AAAA,UACV,MAAA,EAAQ,EAAA;AAAA,UACR,KAAA,EAAO,EAAA;AAAA,UACP,OAAA,EAAS,UAAA;AAAA,UACT,eAAA,EAAiB,CAAC,SAAA,GACd,SAAA,GACA,kBACE,SAAA,GACA,SAAA;AAAA,UACN,KAAA,EAAO,OAAA;AAAA,UACP,YAAA,EAAc,QAAA;AAAA,UACd,QAAA,EAAU,MAAA;AAAA,UACV,UAAA,EAAY,uBAAA;AAAA,UACZ,UAAA,EAAY,GAAA;AAAA,UACZ,MAAA,EAAQ,MAAA;AAAA,UACR,OAAA,EAAS,GAAA;AAAA,UACT,OAAA,EAAS,MAAA;AAAA,UACT,UAAA,EAAY,QAAA;AAAA,UACZ,GAAA,EAAK,KAAA;AAAA,UACL,SAAA,EAAW,+BAAA;AAAA,UACX,MAAA,EAAQ,MAAA;AAAA,UACR,MAAA,EAAQ,YAAY,SAAA,GAAY,aAAA;AAAA,UAChC,UAAA,EAAY;AAAA,SACd;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAAA,GAAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,KAAA,EAAO;AAAA,gBACL,KAAA,EAAO,CAAA;AAAA,gBACP,MAAA,EAAQ,CAAA;AAAA,gBACR,YAAA,EAAc,KAAA;AAAA,gBACd,eAAA,EAAiB,OAAA;AAAA,gBACjB,SAAA,EAAW,CAAC,SAAA,GAAY,mBAAA,GAAsB,kBAAkB,mBAAA,GAAsB;AAAA;AACxF;AAAA,WACF;AAAA,UACC,CAAC,SAAA,GACE,eAAA,GACA,eAAA,wBAEG,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,UAAA,EAAY,QAAA,EAAU,GAAA,EAAK,OAAM,EAC/D,QAAA,EAAA;AAAA,4BAAAA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,gBAAA,IAAoB,mBAAA,EAAoB,CAAA;AAAA,4BAC/CA,GAAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,SAAS,GAAA,EAAK,QAAA,EAAU,MAAA,EAAO,EAAG,QAAA,EAAA,eAAA,EAAa;AAAA,WAAA,EAChE,CAAA,GAEA;AAAA;AAAA;AAAA;AACR,GAAA,EAEJ,CAAA;AAEJ","file":"index.js","sourcesContent":["import { z } from 'zod';\n\nexport const ComponentTypeSchema = z.enum(['function', 'class', 'forwardRef', 'memo']);\n\nexport const ComponentInfoSchema = z.object({\n name: z.string(),\n type: ComponentTypeSchema,\n});\n\nexport const SourceLocationSchema = z.object({\n filePath: z.string().nullable(),\n lineNumber: z.number().nullable(),\n columnNumber: z.number().nullable(),\n});\n\nexport const BoundingRectSchema = z.object({\n x: z.number(),\n y: z.number(),\n width: z.number(),\n height: z.number(),\n top: z.number(),\n right: z.number(),\n bottom: z.number(),\n left: z.number(),\n});\n\nexport const DOMInfoSchema = z.object({\n tagName: z.string(),\n className: z.string().nullable(),\n boundingRect: BoundingRectSchema,\n});\n\nexport const SelectionContextSchema = z.object({\n pageUrl: z.string(),\n parentComponents: z.array(z.string()),\n});\n\nexport const SelectionDataSchema = z.object({\n id: z.string(),\n timestamp: z.number(),\n component: ComponentInfoSchema,\n source: SourceLocationSchema,\n props: z.record(z.unknown()),\n state: z.record(z.unknown()).nullable(),\n dom: DOMInfoSchema,\n context: SelectionContextSchema,\n});\n\nexport type SelectionDataInput = z.infer<typeof SelectionDataSchema>;\n","import { z } from 'zod';\nimport { SelectionDataSchema } from './schemas.js';\n\n/**\n * WebSocket message types for browser <-> CLI communication\n */\n\n// Message type enum\nexport const MessageTypeSchema = z.enum([\n 'selection',\n 'ping',\n 'pong',\n 'connect',\n 'disconnect',\n 'error',\n 'selectionMode',\n]);\n\nexport type MessageType = z.infer<typeof MessageTypeSchema>;\n\n// Base message structure\nconst BaseMessageSchema = z.object({\n type: MessageTypeSchema,\n timestamp: z.number(),\n});\n\n// Selection message - browser -> CLI\nexport const SelectionMessageSchema = BaseMessageSchema.extend({\n type: z.literal('selection'),\n payload: SelectionDataSchema,\n});\n\n// Ping/Pong for keepalive\nexport const PingMessageSchema = BaseMessageSchema.extend({\n type: z.literal('ping'),\n});\n\nexport const PongMessageSchema = BaseMessageSchema.extend({\n type: z.literal('pong'),\n});\n\n// Connection status messages\nexport const ConnectMessageSchema = BaseMessageSchema.extend({\n type: z.literal('connect'),\n payload: z.object({\n clientId: z.string(),\n userAgent: z.string().optional(),\n }),\n});\n\nexport const DisconnectMessageSchema = BaseMessageSchema.extend({\n type: z.literal('disconnect'),\n payload: z.object({\n clientId: z.string(),\n reason: z.string().optional(),\n }),\n});\n\n// Error message\nexport const ErrorMessageSchema = BaseMessageSchema.extend({\n type: z.literal('error'),\n payload: z.object({\n code: z.string(),\n message: z.string(),\n }),\n});\n\n// Selection mode toggle - CLI -> browser\nexport const SelectionModeMessageSchema = BaseMessageSchema.extend({\n type: z.literal('selectionMode'),\n payload: z.object({\n enabled: z.boolean(),\n message: z.string().optional(),\n }),\n});\n\n// Union of all message types\nexport const WebSocketMessageSchema = z.discriminatedUnion('type', [\n SelectionMessageSchema,\n PingMessageSchema,\n PongMessageSchema,\n ConnectMessageSchema,\n DisconnectMessageSchema,\n ErrorMessageSchema,\n SelectionModeMessageSchema,\n]);\n\nexport type WebSocketMessage = z.infer<typeof WebSocketMessageSchema>;\nexport type SelectionMessage = z.infer<typeof SelectionMessageSchema>;\nexport type PingMessage = z.infer<typeof PingMessageSchema>;\nexport type PongMessage = z.infer<typeof PongMessageSchema>;\nexport type ConnectMessage = z.infer<typeof ConnectMessageSchema>;\nexport type DisconnectMessage = z.infer<typeof DisconnectMessageSchema>;\nexport type ErrorMessage = z.infer<typeof ErrorMessageSchema>;\nexport type SelectionModeMessage = z.infer<typeof SelectionModeMessageSchema>;\n\n// Helper to create messages with overloads for type safety\nexport function createMessage(type: 'ping'): PingMessage;\nexport function createMessage(type: 'pong'): PongMessage;\nexport function createMessage(type: 'selection', payload: SelectionMessage['payload']): SelectionMessage;\nexport function createMessage(type: 'connect', payload: ConnectMessage['payload']): ConnectMessage;\nexport function createMessage(type: 'disconnect', payload: DisconnectMessage['payload']): DisconnectMessage;\nexport function createMessage(type: 'error', payload: ErrorMessage['payload']): ErrorMessage;\nexport function createMessage(type: 'selectionMode', payload: SelectionModeMessage['payload']): SelectionModeMessage;\nexport function createMessage(type: MessageType, payload?: unknown): WebSocketMessage {\n const base = { type, timestamp: Date.now() };\n if (payload !== undefined) {\n return { ...base, payload } as WebSocketMessage;\n }\n return base as WebSocketMessage;\n}\n","import { useEffect, useRef, useState, useCallback } from 'react';\nimport {\n WebSocketMessageSchema,\n createMessage,\n type SelectionData,\n type SelectionModeMessage,\n} from '@react-component-selector-mcp/shared';\n\nexport interface UseWebSocketClientOptions {\n port: number;\n onSelectionModeChange?: (enabled: boolean, message?: string) => void;\n onConnectionChange?: (connected: boolean) => void;\n}\n\nexport interface UseWebSocketClientReturn {\n connected: boolean;\n sendSelection: (data: SelectionData) => void;\n clientId: string | null;\n}\n\nexport function useWebSocketClient(\n options: UseWebSocketClientOptions\n): UseWebSocketClientReturn {\n const { port } = options;\n\n // Use refs for callbacks to avoid re-triggering effects\n const onSelectionModeChangeRef = useRef(options.onSelectionModeChange);\n const onConnectionChangeRef = useRef(options.onConnectionChange);\n onSelectionModeChangeRef.current = options.onSelectionModeChange;\n onConnectionChangeRef.current = options.onConnectionChange;\n\n const wsRef = useRef<WebSocket | null>(null);\n const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isCleaningUpRef = useRef(false);\n // Track if we've ever successfully connected (to suppress initial connection errors)\n const hasConnectedRef = useRef(false);\n\n const [connected, setConnected] = useState(false);\n const [clientId, setClientId] = useState<string | null>(null);\n\n const sendSelection = useCallback((data: SelectionData) => {\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n const message = createMessage('selection', data);\n wsRef.current.send(JSON.stringify(message));\n } else {\n console.warn('[component-picker] Cannot send selection - not connected');\n }\n }, []);\n\n useEffect(() => {\n // Reset cleanup flag on mount\n isCleaningUpRef.current = false;\n\n // Prevent running if already connected\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n return;\n }\n\n // Small delay to handle React Strict Mode double-invoke\n // This prevents \"WebSocket closed before connection established\" errors\n let connectTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const connect = () => {\n if (wsRef.current?.readyState === WebSocket.OPEN || isCleaningUpRef.current) {\n return;\n }\n\n try {\n const ws = new WebSocket(`ws://localhost:${port}`);\n // Track whether this specific connection was intentionally closed during cleanup\n let wasIntentionallyClosed = false;\n\n ws.onopen = () => {\n if (isCleaningUpRef.current) {\n wasIntentionallyClosed = true;\n ws.close();\n return;\n }\n hasConnectedRef.current = true;\n console.log('[component-picker] Connected to server');\n setConnected(true);\n onConnectionChangeRef.current?.(true);\n\n // Start ping interval\n pingIntervalRef.current = setInterval(() => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(createMessage('ping')));\n }\n }, 25000);\n };\n\n ws.onclose = () => {\n // Only log disconnection if we were previously connected (not during initial failed attempts)\n if (hasConnectedRef.current && !wasIntentionallyClosed && !isCleaningUpRef.current) {\n console.log('[component-picker] Disconnected from server');\n }\n setConnected(false);\n setClientId(null);\n onConnectionChangeRef.current?.(false);\n\n if (pingIntervalRef.current) {\n clearInterval(pingIntervalRef.current);\n pingIntervalRef.current = null;\n }\n\n // Only attempt reconnection if not cleaning up\n if (!isCleaningUpRef.current) {\n reconnectTimeoutRef.current = setTimeout(() => {\n connect();\n }, 3000);\n }\n };\n\n ws.onerror = () => {\n // Silently handle errors - the UI shows connection status\n // onclose will be called after onerror for reconnection\n };\n\n ws.onmessage = (event: MessageEvent) => {\n try {\n const parsed = JSON.parse(event.data);\n const result = WebSocketMessageSchema.safeParse(parsed);\n\n if (!result.success) {\n console.warn('[component-picker] Invalid message:', result.error);\n return;\n }\n\n const message = result.data;\n\n switch (message.type) {\n case 'connect':\n setClientId(message.payload.clientId);\n break;\n\n case 'selectionMode':\n onSelectionModeChangeRef.current?.(\n (message as SelectionModeMessage).payload.enabled,\n (message as SelectionModeMessage).payload.message\n );\n break;\n\n case 'pong':\n // Keepalive acknowledged\n break;\n\n default:\n break;\n }\n } catch (error) {\n console.error('[component-picker] Error handling message:', error);\n }\n };\n\n wsRef.current = ws;\n } catch (error) {\n // Silently handle initial connection errors - UI shows status\n // Retry connection if not cleaning up\n if (!isCleaningUpRef.current) {\n reconnectTimeoutRef.current = setTimeout(() => {\n connect();\n }, 3000);\n }\n }\n };\n\n // Delay initial connection to handle React Strict Mode\n // In Strict Mode, effects run twice quickly - the delay allows cleanup to run before connection starts\n connectTimeoutId = setTimeout(() => {\n connectTimeoutId = null;\n if (!isCleaningUpRef.current) {\n connect();\n }\n }, 100);\n\n return () => {\n isCleaningUpRef.current = true;\n\n // Clear the initial connection timeout\n if (connectTimeoutId) {\n clearTimeout(connectTimeoutId);\n connectTimeoutId = null;\n }\n\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current);\n reconnectTimeoutRef.current = null;\n }\n if (pingIntervalRef.current) {\n clearInterval(pingIntervalRef.current);\n pingIntervalRef.current = null;\n }\n if (wsRef.current) {\n // Only close if not already closed/closing\n if (wsRef.current.readyState === WebSocket.OPEN ||\n wsRef.current.readyState === WebSocket.CONNECTING) {\n wsRef.current.close();\n }\n wsRef.current = null;\n }\n };\n }, [port]); // Only depend on port\n\n return {\n connected,\n sendSelection,\n clientId,\n };\n}\n","import { useEffect, useCallback } from 'react';\n\nexport interface UseKeyboardShortcutOptions {\n /** Key to press with modifiers (default: 'C') */\n key?: string;\n /** Callback when shortcut is triggered */\n onTrigger: () => void;\n /** Whether the shortcut is enabled */\n enabled?: boolean;\n}\n\n/**\n * Hook to handle Ctrl+Alt+C (Windows/Linux) / Cmd+Option+C (Mac) keyboard shortcut\n */\nexport function useKeyboardShortcut(options: UseKeyboardShortcutOptions): void {\n const { key = 'C', onTrigger, enabled = true } = options;\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (!enabled) return;\n\n // Check for Ctrl+Alt+C (Windows/Linux) or Cmd+Option+C (Mac)\n const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n const modifierKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (modifierKey && event.altKey && event.key.toUpperCase() === key.toUpperCase()) {\n event.preventDefault();\n event.stopPropagation();\n onTrigger();\n }\n },\n [key, onTrigger, enabled]\n );\n\n useEffect(() => {\n if (!enabled) return;\n\n window.addEventListener('keydown', handleKeyDown, true);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown, true);\n };\n }, [handleKeyDown, enabled]);\n}\n","import { useState, useCallback } from 'react';\n\nexport interface UseSelectionModeReturn {\n isSelectionMode: boolean;\n selectionMessage: string | undefined;\n enableSelectionMode: (message?: string) => void;\n disableSelectionMode: () => void;\n toggleSelectionMode: () => void;\n}\n\n/**\n * Hook to manage selection mode state\n */\nexport function useSelectionMode(): UseSelectionModeReturn {\n const [isSelectionMode, setIsSelectionMode] = useState(false);\n const [selectionMessage, setSelectionMessage] = useState<string | undefined>();\n\n const enableSelectionMode = useCallback((message?: string) => {\n setIsSelectionMode(true);\n setSelectionMessage(message);\n }, []);\n\n const disableSelectionMode = useCallback(() => {\n setIsSelectionMode(false);\n setSelectionMessage(undefined);\n }, []);\n\n const toggleSelectionMode = useCallback(() => {\n setIsSelectionMode((prev) => !prev);\n if (isSelectionMode) {\n setSelectionMessage(undefined);\n }\n }, [isSelectionMode]);\n\n return {\n isSelectionMode,\n selectionMessage,\n enableSelectionMode,\n disableSelectionMode,\n toggleSelectionMode,\n };\n}\n","import { useCallback } from 'react';\nimport type { ComponentInfo, ComponentType } from '@react-component-selector-mcp/shared';\n\n// React Fiber types (internal)\ninterface Fiber {\n tag: number;\n type: unknown;\n stateNode: unknown;\n return: Fiber | null;\n memoizedProps: Record<string, unknown>;\n memoizedState: unknown;\n _debugSource?: {\n fileName: string;\n lineNumber: number;\n columnNumber?: number;\n };\n}\n\n// React DevTools global hook\ninterface ReactDevToolsHook {\n renderers?: Map<number, {\n findFiberByHostInstance?: (element: Element) => Fiber | null;\n }>;\n}\n\ndeclare global {\n interface Window {\n __REACT_DEVTOOLS_GLOBAL_HOOK__?: ReactDevToolsHook;\n }\n}\n\n// React Fiber tags\nconst FIBER_TAGS = {\n FunctionComponent: 0,\n ClassComponent: 1,\n ForwardRef: 11,\n MemoComponent: 14,\n SimpleMemoComponent: 15,\n} as const;\n\nexport interface FiberData {\n componentInfo: ComponentInfo;\n props: Record<string, unknown>;\n state: Record<string, unknown> | null;\n parentComponents: string[];\n debugSource: {\n fileName: string | null;\n lineNumber: number | null;\n columnNumber: number | null;\n };\n}\n\nexport interface UseFiberInspectorReturn {\n getFiberFromElement: (element: HTMLElement) => Fiber | null;\n extractFiberData: (fiber: Fiber) => FiberData;\n findNearestComponentFiber: (fiber: Fiber) => Fiber | null;\n}\n\n/**\n * Hook for inspecting React Fiber internals\n */\nexport function useFiberInspector(): UseFiberInspectorReturn {\n /**\n * Get React Fiber from DOM element\n */\n const getFiberFromElement = useCallback((element: HTMLElement): Fiber | null => {\n // Try DevTools hook first (most reliable)\n if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__?.renderers) {\n for (const renderer of window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.values()) {\n const fiber = renderer.findFiberByHostInstance?.(element);\n if (fiber) return fiber;\n }\n }\n\n // Fallback to internal keys\n const fiberKey = Object.keys(element).find(\n (key) => key.startsWith('__reactFiber$') || key.startsWith('__reactInternalInstance$')\n );\n\n if (fiberKey) {\n const fiber = (element as unknown as Record<string, Fiber | undefined>)[fiberKey];\n return fiber ?? null;\n }\n\n return null;\n }, []);\n\n /**\n * Get component type from fiber tag\n */\n const getComponentType = useCallback((fiber: Fiber): ComponentType => {\n switch (fiber.tag) {\n case FIBER_TAGS.ClassComponent:\n return 'class';\n case FIBER_TAGS.ForwardRef:\n return 'forwardRef';\n case FIBER_TAGS.MemoComponent:\n case FIBER_TAGS.SimpleMemoComponent:\n return 'memo';\n case FIBER_TAGS.FunctionComponent:\n default:\n return 'function';\n }\n }, []);\n\n /**\n * Get component name from fiber\n */\n const getComponentName = useCallback((fiber: Fiber): string => {\n const type = fiber.type;\n\n if (!type) return 'Unknown';\n\n // Function or class component\n if (typeof type === 'function') {\n const fn = type as { displayName?: string; name?: string };\n return fn.displayName || fn.name || 'Anonymous';\n }\n\n // ForwardRef\n if (typeof type === 'object' && type !== null) {\n const obj = type as { displayName?: string; render?: { displayName?: string; name?: string }; type?: { displayName?: string; name?: string } };\n\n if (obj.displayName) return obj.displayName;\n if (obj.render) return obj.render.displayName || obj.render.name || 'ForwardRef';\n if (obj.type) return obj.type.displayName || obj.type.name || 'Memo';\n }\n\n return 'Unknown';\n }, []);\n\n /**\n * Find the nearest user-defined component fiber (skip host/native elements)\n */\n const findNearestComponentFiber = useCallback((fiber: Fiber): Fiber | null => {\n let current: Fiber | null = fiber;\n\n while (current) {\n // Check if it's a user component (function, class, forwardRef, memo)\n const tag = current.tag;\n if (\n tag === FIBER_TAGS.FunctionComponent ||\n tag === FIBER_TAGS.ClassComponent ||\n tag === FIBER_TAGS.ForwardRef ||\n tag === FIBER_TAGS.MemoComponent ||\n tag === FIBER_TAGS.SimpleMemoComponent\n ) {\n const name = getComponentName(current);\n // Skip internal React components\n if (!name.startsWith('_') && name !== 'Unknown' && name !== 'Anonymous') {\n return current;\n }\n }\n\n current = current.return;\n }\n\n return null;\n }, [getComponentName]);\n\n /**\n * Get parent component names from fiber tree\n */\n const getParentComponents = useCallback(\n (fiber: Fiber): string[] => {\n const parents: string[] = [];\n let current = fiber.return;\n\n while (current && parents.length < 10) {\n const tag = current.tag;\n if (\n tag === FIBER_TAGS.FunctionComponent ||\n tag === FIBER_TAGS.ClassComponent ||\n tag === FIBER_TAGS.ForwardRef ||\n tag === FIBER_TAGS.MemoComponent ||\n tag === FIBER_TAGS.SimpleMemoComponent\n ) {\n const name = getComponentName(current);\n if (!name.startsWith('_') && name !== 'Unknown') {\n parents.push(name);\n }\n }\n current = current.return;\n }\n\n return parents;\n },\n [getComponentName]\n );\n\n /**\n * Safely serialize props (handle circular refs, functions, etc.)\n */\n const serializeProps = useCallback((props: Record<string, unknown>): Record<string, unknown> => {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(props)) {\n // Skip React internal props\n if (key === 'children' || key === 'key' || key === 'ref') continue;\n\n try {\n if (typeof value === 'function') {\n result[key] = '[Function]';\n } else if (value instanceof Element) {\n result[key] = '[Element]';\n } else if (typeof value === 'object' && value !== null) {\n // Attempt JSON serialization to check for circular refs\n JSON.stringify(value);\n result[key] = value;\n } else {\n result[key] = value;\n }\n } catch {\n result[key] = '[Circular or Unserializable]';\n }\n }\n\n return result;\n }, []);\n\n /**\n * Extract state from class component\n */\n const extractState = useCallback((fiber: Fiber): Record<string, unknown> | null => {\n if (fiber.tag !== FIBER_TAGS.ClassComponent) {\n return null;\n }\n\n const instance = fiber.stateNode as { state?: Record<string, unknown> } | null;\n if (instance?.state) {\n try {\n JSON.stringify(instance.state);\n return instance.state;\n } catch {\n return { error: '[Unserializable state]' };\n }\n }\n\n return null;\n }, []);\n\n /**\n * Extract all relevant data from a fiber\n */\n const extractFiberData = useCallback(\n (fiber: Fiber): FiberData => {\n return {\n componentInfo: {\n name: getComponentName(fiber),\n type: getComponentType(fiber),\n },\n props: serializeProps(fiber.memoizedProps || {}),\n state: extractState(fiber),\n parentComponents: getParentComponents(fiber),\n debugSource: {\n fileName: fiber._debugSource?.fileName ?? null,\n lineNumber: fiber._debugSource?.lineNumber ?? null,\n columnNumber: fiber._debugSource?.columnNumber ?? null,\n },\n };\n },\n [getComponentName, getComponentType, serializeProps, extractState, getParentComponents]\n );\n\n return {\n getFiberFromElement,\n extractFiberData,\n findNearestComponentFiber,\n };\n}\n","import React, { useEffect, useState, useCallback, useRef } from 'react';\n\nexport interface SelectionOverlayProps {\n enabled: boolean;\n onSelect: (element: HTMLElement) => void;\n onCancel: () => void;\n}\n\ninterface HighlightRect {\n top: number;\n left: number;\n width: number;\n height: number;\n componentName: string;\n}\n\n/**\n * Overlay component that highlights elements on hover and captures clicks\n */\nexport function SelectionOverlay({\n enabled,\n onSelect,\n onCancel,\n}: SelectionOverlayProps): React.ReactElement | null {\n const [highlight, setHighlight] = useState<HighlightRect | null>(null);\n const hoveredElementRef = useRef<HTMLElement | null>(null);\n\n // Get display name from element (prefer React component name, then className + text)\n const getComponentName = useCallback((element: HTMLElement): string => {\n // Try to get React component name from fiber first\n const fiberKey = Object.keys(element).find(\n (k) => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n\n let reactName: string | null = null;\n if (fiberKey) {\n const fiber = (element as unknown as Record<string, unknown>)[fiberKey] as {\n type?: { displayName?: string; name?: string } | string;\n return?: { type?: { displayName?: string; name?: string } };\n };\n\n // Check current fiber\n if (fiber?.type && typeof fiber.type === 'function') {\n const fn = fiber.type as { displayName?: string; name?: string };\n reactName = fn.displayName || fn.name || null;\n }\n\n // Walk up to find nearest named component\n if (!reactName || reactName === 'div' || reactName === 'button') {\n let current = fiber;\n while (current?.return) {\n current = current.return as typeof fiber;\n if (current?.type && typeof current.type === 'function') {\n const fn = current.type as { displayName?: string; name?: string };\n const name = fn.displayName || fn.name;\n if (name && !['Fragment', 'Suspense', 'Provider', 'Consumer'].includes(name)) {\n reactName = name;\n break;\n }\n }\n }\n }\n }\n\n // Get text content for context (truncated)\n const textContent = element.textContent?.trim().slice(0, 20) || '';\n const textSuffix = textContent ? ` \"${textContent}${element.textContent && element.textContent.length > 20 ? '...' : ''}\"` : '';\n\n // If we found a React component name, use it\n if (reactName && !['div', 'button', 'span', 'p', 'h1', 'h2', 'h3'].includes(reactName.toLowerCase())) {\n return `<${reactName}>${textSuffix}`;\n }\n\n // Fall back to className with text\n if (element.className && typeof element.className === 'string' && element.className.trim()) {\n const classes = element.className.trim().split(/\\s+/)[0]; // Just first class\n return `.${classes}${textSuffix}`;\n }\n\n // Last resort: tag name with text\n return `<${element.tagName.toLowerCase()}>${textSuffix}`;\n }, []);\n\n // Handle mouse movement\n const handleMouseMove = useCallback(\n (event: MouseEvent) => {\n if (!enabled) return;\n\n const target = event.target as HTMLElement;\n\n // Skip our own overlay elements\n if (target.closest('[data-component-picker]')) {\n setHighlight(null);\n hoveredElementRef.current = null;\n return;\n }\n\n // Skip html, body, and script elements\n if (['HTML', 'BODY', 'SCRIPT', 'STYLE', 'NOSCRIPT'].includes(target.tagName)) {\n setHighlight(null);\n hoveredElementRef.current = null;\n return;\n }\n\n const rect = target.getBoundingClientRect();\n hoveredElementRef.current = target;\n\n setHighlight({\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n componentName: getComponentName(target),\n });\n },\n [enabled, getComponentName]\n );\n\n // Handle click\n const handleClick = useCallback(\n (event: MouseEvent) => {\n if (!enabled) return;\n\n const target = event.target as HTMLElement;\n\n // Skip our own overlay elements\n if (target.closest('[data-component-picker]')) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n if (hoveredElementRef.current) {\n onSelect(hoveredElementRef.current);\n }\n },\n [enabled, onSelect]\n );\n\n // Handle escape key\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (!enabled) return;\n\n if (event.key === 'Escape') {\n event.preventDefault();\n onCancel();\n }\n },\n [enabled, onCancel]\n );\n\n // Add event listeners\n useEffect(() => {\n if (!enabled) {\n setHighlight(null);\n hoveredElementRef.current = null;\n return;\n }\n\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n document.addEventListener('keydown', handleKeyDown, true);\n\n // Change cursor\n document.body.style.cursor = 'crosshair';\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.removeEventListener('keydown', handleKeyDown, true);\n document.body.style.cursor = '';\n };\n }, [enabled, handleMouseMove, handleClick, handleKeyDown]);\n\n if (!enabled) return null;\n\n return (\n <>\n {/* Highlight box */}\n {highlight && (\n <div\n data-component-picker=\"highlight\"\n style={{\n position: 'fixed',\n top: highlight.top,\n left: highlight.left,\n width: highlight.width,\n height: highlight.height,\n border: '2px solid #3b82f6',\n backgroundColor: 'rgba(59, 130, 246, 0.1)',\n pointerEvents: 'none',\n zIndex: 999998,\n boxSizing: 'border-box',\n }}\n >\n {/* Component name label */}\n <div\n style={{\n position: 'absolute',\n top: -24,\n left: -2,\n padding: '2px 8px',\n backgroundColor: '#3b82f6',\n color: 'white',\n fontSize: '12px',\n fontFamily: 'system-ui, sans-serif',\n fontWeight: 500,\n borderRadius: '4px 4px 0 0',\n whiteSpace: 'nowrap',\n maxWidth: '300px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {highlight.componentName}\n </div>\n </div>\n )}\n\n </>\n );\n}\n","/**\n * Cross-browser stack trace parser\n * Extracts source locations from JavaScript error stack traces\n */\n\nexport interface StackFrame {\n functionName: string | null;\n url: string;\n lineNumber: number;\n columnNumber: number;\n}\n\n/**\n * Parse an error stack trace into structured frames\n * Supports Chrome, Firefox, Safari, and Edge\n */\nexport function parseStackTrace(error: Error): StackFrame[] {\n const stack = error.stack;\n if (!stack) return [];\n\n const frames: StackFrame[] = [];\n const lines = stack.split('\\n');\n\n for (const line of lines) {\n const frame = parseStackLine(line);\n if (frame) {\n frames.push(frame);\n }\n }\n\n return frames;\n}\n\n/**\n * Parse a single stack trace line\n */\nfunction parseStackLine(line: string): StackFrame | null {\n // Chrome/Edge/Node format:\n // \" at FunctionName (http://localhost:3000/file.js:10:15)\"\n // \" at http://localhost:3000/file.js:10:15\"\n // \" at async FunctionName (http://localhost:3000/file.js:10:15)\"\n const chromeMatch = line.match(\n /^\\s*at\\s+(?:async\\s+)?(?:(\\S+)\\s+)?\\(?(https?:\\/\\/[^)]+|file:\\/\\/[^)]+):(\\d+):(\\d+)\\)?/\n );\n if (chromeMatch) {\n return {\n functionName: chromeMatch[1] || null,\n url: chromeMatch[2]!,\n lineNumber: parseInt(chromeMatch[3]!, 10),\n columnNumber: parseInt(chromeMatch[4]!, 10),\n };\n }\n\n // Firefox/Safari format:\n // \"functionName@http://localhost:3000/file.js:10:15\"\n // \"@http://localhost:3000/file.js:10:15\"\n const firefoxMatch = line.match(\n /^(?:(\\S*)@)?(https?:\\/\\/[^:]+|file:\\/\\/[^:]+):(\\d+):(\\d+)/\n );\n if (firefoxMatch) {\n return {\n functionName: firefoxMatch[1] || null,\n url: firefoxMatch[2]!,\n lineNumber: parseInt(firefoxMatch[3]!, 10),\n columnNumber: parseInt(firefoxMatch[4]!, 10),\n };\n }\n\n return null;\n}\n\n/**\n * Filter out internal React and framework frames\n */\nexport function filterInternalFrames(frames: StackFrame[]): StackFrame[] {\n const internalPatterns = [\n /node_modules/,\n /react-dom/,\n /react\\.production/,\n /react\\.development/,\n /scheduler/,\n /\\/_next\\/static\\/chunks\\/webpack/,\n /\\/__webpack_/,\n /\\/turbopack-/,\n // React internal function names\n /^(?:renderWithHooks|mountIndeterminateComponent|beginWork|performUnitOfWork)/,\n /^(?:callCallback|invokeGuardedCallbackDev|invokeGuardedCallback)/,\n /^(?:commitRoot|flushSync|batchedUpdates)/,\n ];\n\n return frames.filter((frame) => {\n // Check URL patterns\n for (const pattern of internalPatterns) {\n if (pattern.test(frame.url)) {\n return false;\n }\n }\n\n // Check function name patterns\n if (frame.functionName) {\n for (const pattern of internalPatterns) {\n if (pattern.test(frame.functionName)) {\n return false;\n }\n }\n }\n\n return true;\n });\n}\n\n/**\n * Get the first user component frame from the stack\n * This is typically the component that was clicked\n */\nexport function getComponentFrame(frames: StackFrame[]): StackFrame | null {\n const userFrames = filterInternalFrames(frames);\n return userFrames[0] || null;\n}\n\n/**\n * Create a stack trace at the current execution point\n * Useful for capturing where a component render is happening\n */\nexport function captureStackTrace(): StackFrame[] {\n const error = new Error();\n return parseStackTrace(error);\n}\n\n/**\n * Extract the script URL from a frame, normalizing various bundler formats\n */\nexport function normalizeScriptUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n // Remove query params (like HMR timestamps)\n urlObj.search = '';\n urlObj.hash = '';\n return urlObj.href;\n } catch {\n return url;\n }\n}\n","/**\n * Source location resolver\n *\n * Attempts to resolve source file locations using two strategies:\n * 1. React's _debugSource (fastest, works with Babel-based builds)\n * 2. Stack trace parsing (fallback, less accurate)\n */\n\nimport type { SourceLocation } from '@react-component-selector-mcp/shared';\nimport { parseStackTrace, filterInternalFrames } from './stackTraceParser.js';\n\nexport interface DebugSource {\n fileName: string | null;\n lineNumber: number | null;\n columnNumber?: number | null;\n}\n\nexport interface Fiber {\n _debugSource?: DebugSource;\n type?: unknown;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\n/**\n * Resolve source location using multiple strategies\n * This is the main entry point for source resolution\n */\nexport async function resolveSourceLocation(\n fiber: Fiber | null,\n _element?: HTMLElement\n): Promise<SourceLocation> {\n // Strategy 1: Try _debugSource first (fastest)\n const debugSourceResult = tryDebugSource(fiber);\n if (debugSourceResult.filePath) {\n return debugSourceResult;\n }\n\n // Strategy 2: Try stack trace parsing (fallback)\n const stackResult = tryStackTraceParsing();\n if (stackResult?.filePath) {\n return stackResult;\n }\n\n // No source information available\n return {\n filePath: null,\n lineNumber: null,\n columnNumber: null,\n };\n}\n\n/**\n * Strategy 1: Extract source from React's _debugSource\n * This is set by @babel/plugin-transform-react-jsx-source\n */\nfunction tryDebugSource(fiber: Fiber | null): SourceLocation {\n if (!fiber?._debugSource) {\n return { filePath: null, lineNumber: null, columnNumber: null };\n }\n\n const { fileName, lineNumber, columnNumber } = fiber._debugSource;\n\n if (!fileName) {\n return { filePath: null, lineNumber: null, columnNumber: null };\n }\n\n return {\n filePath: formatFilePath(fileName),\n lineNumber: lineNumber ?? null,\n columnNumber: columnNumber ?? null,\n };\n}\n\n/**\n * Strategy 2: Parse stack trace directly for source location\n * Less accurate but works as a last resort\n */\nfunction tryStackTraceParsing(): SourceLocation | null {\n try {\n const error = new Error();\n const frames = parseStackTrace(error);\n const userFrames = filterInternalFrames(frames);\n\n if (userFrames.length === 0) {\n return null;\n }\n\n const frame = userFrames[0]!;\n\n // Extract file path from URL\n const filePath = extractFilePathFromUrl(frame.url);\n if (!filePath) {\n return null;\n }\n\n return {\n filePath,\n lineNumber: frame.lineNumber,\n columnNumber: frame.columnNumber,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Extract relative file path from URL\n */\nfunction extractFilePathFromUrl(url: string): string | null {\n try {\n const urlObj = new URL(url);\n let path = urlObj.pathname;\n\n // Remove leading slash\n path = path.replace(/^\\/+/, '');\n\n // Handle various bundler prefixes\n path = path\n // Next.js\n .replace(/^_next\\/static\\/chunks\\//, '')\n .replace(/^_next\\/static\\/[^/]+\\/pages\\//, 'pages/')\n // Vite\n .replace(/^\\/@fs\\//, '')\n .replace(/^@vite\\//, '')\n // Webpack\n .replace(/^webpack:\\/\\/[^/]+\\//, '')\n // Turbopack\n .replace(/^\\[project\\]\\//, '');\n\n // Remove query params and hash (HMR timestamps etc)\n path = path.split('?')[0]?.split('#')[0] || path;\n\n // If the path looks like a hash (e.g., \"app-pages-internals.js\")\n // and doesn't have a recognizable extension path, it's not useful\n if (!path.includes('/') && !path.match(/\\.(tsx?|jsx?|mjs)$/)) {\n return null;\n }\n\n return path || null;\n } catch {\n return url;\n }\n}\n\n/**\n * Clean up file path for display\n */\nexport function formatFilePath(filePath: string | null): string | null {\n if (!filePath) return null;\n\n let cleaned = filePath\n // Remove webpack:// prefix\n .replace(/^webpack:\\/\\/[^/]+\\//, '')\n // Remove ./ prefix\n .replace(/^\\.\\//g, '')\n // Remove leading slashes\n .replace(/^\\/+/, '')\n // Remove turbopack prefix\n .replace(/^\\[project\\]\\//, '');\n\n // Normalize Windows paths to forward slashes\n cleaned = cleaned.replace(/\\\\/g, '/');\n\n return cleaned;\n}\n\n/**\n * Synchronous version for backward compatibility\n * Only uses _debugSource strategy\n */\nexport function resolveSourceLocationSync(\n debugSource: DebugSource | null\n): SourceLocation {\n if (!debugSource?.fileName) {\n return { filePath: null, lineNumber: null, columnNumber: null };\n }\n\n return {\n filePath: formatFilePath(debugSource.fileName),\n lineNumber: debugSource.lineNumber ?? null,\n columnNumber: debugSource.columnNumber ?? null,\n };\n}\n","import { nanoid } from 'nanoid';\nimport type { SelectionData, DOMInfo } from '@react-component-selector-mcp/shared';\nimport type { FiberData } from '../hooks/useFiberInspector.js';\nimport {\n resolveSourceLocation,\n formatFilePath,\n type Fiber,\n} from './sourceLocationResolver.js';\n\nexport interface MetadataOptions {\n /** The raw React fiber for enhanced source resolution */\n fiber?: Fiber | null;\n}\n\n/**\n * Extract DOM information from an element\n */\nexport function extractDOMInfo(element: HTMLElement): DOMInfo {\n const rect = element.getBoundingClientRect();\n\n return {\n tagName: element.tagName.toLowerCase(),\n className: element.className || null,\n boundingRect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n },\n };\n}\n\n/**\n * Build complete selection data from fiber data and DOM element\n */\nexport async function buildSelectionData(\n element: HTMLElement,\n fiberData: FiberData,\n options: MetadataOptions = {}\n): Promise<SelectionData> {\n // Resolve source location using multi-strategy approach\n // Pass fiber for enhanced source map resolution\n const fiber = options.fiber ?? {\n _debugSource: fiberData.debugSource,\n };\n const source = await resolveSourceLocation(fiber, element);\n\n // Build complete selection data\n const selectionData: SelectionData = {\n id: nanoid(),\n timestamp: Date.now(),\n component: fiberData.componentInfo,\n source: {\n filePath: formatFilePath(source.filePath),\n lineNumber: source.lineNumber,\n columnNumber: source.columnNumber,\n },\n props: fiberData.props,\n state: fiberData.state,\n dom: extractDOMInfo(element),\n context: {\n pageUrl: window.location.href,\n parentComponents: fiberData.parentComponents,\n },\n };\n\n return selectionData;\n}\n","import React, { useCallback, type ReactNode } from 'react';\nimport { useWebSocketClient } from './hooks/useWebSocketClient.js';\nimport { useKeyboardShortcut } from './hooks/useKeyboardShortcut.js';\nimport { useSelectionMode } from './hooks/useSelectionMode.js';\nimport { useFiberInspector } from './hooks/useFiberInspector.js';\nimport { SelectionOverlay } from './SelectionOverlay.js';\nimport { buildSelectionData } from './utils/componentMetadata.js';\n\nexport interface ComponentPickerProps {\n /** WebSocket server port (default: 3333) */\n port?: number;\n /** Children to wrap */\n children: ReactNode;\n /** Keyboard shortcut key (default: 'C' for Ctrl+Alt+C / Cmd+Option+C) */\n shortcutKey?: string;\n /** Called when connection status changes */\n onConnectionChange?: (connected: boolean) => void;\n /** Called when a component is selected */\n onSelect?: (componentName: string, filePath: string | null) => void;\n}\n\n/**\n * Wrapper component that enables component selection in development mode.\n * In production, this is a no-op passthrough.\n */\nexport function ComponentPicker(props: ComponentPickerProps): ReactNode {\n // No-op in production\n if (process.env.NODE_ENV !== 'development') {\n return props.children;\n }\n\n return <ComponentPickerImpl {...props} />;\n}\n\n/**\n * Implementation component (only rendered in development)\n */\nfunction ComponentPickerImpl({\n port = 3333,\n children,\n shortcutKey = 'C',\n onConnectionChange,\n onSelect,\n}: ComponentPickerProps): React.ReactElement {\n const { isSelectionMode, selectionMessage, enableSelectionMode, disableSelectionMode } =\n useSelectionMode();\n\n const { getFiberFromElement, extractFiberData, findNearestComponentFiber } = useFiberInspector();\n\n const { connected, sendSelection } = useWebSocketClient({\n port,\n onSelectionModeChange: (enabled, message) => {\n if (enabled) {\n enableSelectionMode(message);\n } else {\n disableSelectionMode();\n }\n },\n onConnectionChange,\n });\n\n // Handle keyboard shortcut\n useKeyboardShortcut({\n key: shortcutKey,\n onTrigger: () => {\n if (isSelectionMode) {\n disableSelectionMode();\n } else {\n enableSelectionMode();\n }\n },\n enabled: connected,\n });\n\n // Handle element selection\n const handleSelect = useCallback(\n async (element: HTMLElement) => {\n try {\n // Get fiber from element\n const fiber = getFiberFromElement(element);\n if (!fiber) {\n console.warn('[component-picker] No React fiber found for element');\n disableSelectionMode();\n return;\n }\n\n // Find nearest component fiber\n const componentFiber = findNearestComponentFiber(fiber);\n if (!componentFiber) {\n console.warn('[component-picker] No component fiber found');\n disableSelectionMode();\n return;\n }\n\n // Extract fiber data\n const fiberData = extractFiberData(componentFiber);\n\n // Build complete selection data (pass fiber for enhanced source resolution)\n const selectionData = await buildSelectionData(element, fiberData, {\n fiber: componentFiber,\n });\n\n // Send to server\n sendSelection(selectionData);\n\n // Notify callback\n onSelect?.(selectionData.component.name, selectionData.source.filePath);\n\n console.log(\n `[component-picker] Selected: ${selectionData.component.name}`,\n selectionData.source.filePath\n ? `at ${selectionData.source.filePath}:${selectionData.source.lineNumber}`\n : ''\n );\n } catch (error) {\n console.error('[component-picker] Selection error:', error);\n } finally {\n disableSelectionMode();\n }\n },\n [\n getFiberFromElement,\n findNearestComponentFiber,\n extractFiberData,\n sendSelection,\n disableSelectionMode,\n onSelect,\n ]\n );\n\n return (\n <>\n {children}\n <SelectionOverlay\n enabled={isSelectionMode}\n onSelect={handleSelect}\n onCancel={disableSelectionMode}\n />\n {/* Selection toggle button (bottom-right corner) */}\n {process.env.NODE_ENV === 'development' && (\n <button\n data-component-picker=\"status\"\n onClick={() => {\n if (!connected) return;\n if (isSelectionMode) {\n disableSelectionMode();\n } else {\n enableSelectionMode();\n }\n }}\n style={{\n position: 'fixed',\n bottom: 16,\n right: 16,\n padding: '8px 12px',\n backgroundColor: !connected\n ? '#ef4444'\n : isSelectionMode\n ? '#3b82f6'\n : '#22c55e',\n color: 'white',\n borderRadius: '9999px',\n fontSize: '12px',\n fontFamily: 'system-ui, sans-serif',\n fontWeight: 500,\n zIndex: 999997,\n opacity: 0.9,\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n border: 'none',\n cursor: connected ? 'pointer' : 'not-allowed',\n transition: 'background-color 0.2s ease',\n }}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n backgroundColor: 'white',\n animation: !connected ? 'pulse 2s infinite' : isSelectionMode ? 'pulse 1s infinite' : 'none',\n }}\n />\n {!connected\n ? 'Connecting...'\n : isSelectionMode\n ? (\n <span style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\n <span>{selectionMessage || 'Click a component'}</span>\n <span style={{ opacity: 0.7, fontSize: '10px' }}>ESC to cancel</span>\n </span>\n )\n : 'Select Component'}\n </button>\n )}\n </>\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-component-selector-mcp/react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "React component selector with browser selection UI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "zakstam",
|
|
@@ -39,9 +39,7 @@
|
|
|
39
39
|
"clean": "rimraf dist"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"html-to-image": "^1.11.11",
|
|
43
42
|
"nanoid": "^5.0.9",
|
|
44
|
-
"source-map-js": "^1.2.1",
|
|
45
43
|
"zod": "^3.24.1"
|
|
46
44
|
},
|
|
47
45
|
"peerDependencies": {
|
|
@@ -60,5 +58,9 @@
|
|
|
60
58
|
},
|
|
61
59
|
"engines": {
|
|
62
60
|
"node": ">=18"
|
|
61
|
+
},
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public",
|
|
64
|
+
"provenance": true
|
|
63
65
|
}
|
|
64
66
|
}
|