fixdog 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +80 -433
- package/dist/api/client.d.ts +74 -0
- package/dist/components/ConversationalInputReact.d.ts +26 -0
- package/dist/components/ElementInfoDisplayReact.d.ts +9 -0
- package/dist/components/FixdogSidebarReact.d.ts +29 -0
- package/dist/fiber.d.ts +9 -0
- package/dist/index.cjs.js +33 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +6 -158
- package/dist/index.esm.js +29 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/inspector-B4F5CBT7.cjs.js +1159 -0
- package/dist/inspector-B4F5CBT7.cjs.js.map +1 -0
- package/dist/inspector-BL2pNjn-.cjs.js +1173 -0
- package/dist/inspector-BL2pNjn-.cjs.js.map +1 -0
- package/dist/inspector-Bg6uSvk0.esm.js +1273 -0
- package/dist/inspector-Bg6uSvk0.esm.js.map +1 -0
- package/dist/inspector-BuOffbVc.cjs.js +1280 -0
- package/dist/inspector-BuOffbVc.cjs.js.map +1 -0
- package/dist/inspector-CNgFkZOU.esm.js +1185 -0
- package/dist/inspector-CNgFkZOU.esm.js.map +1 -0
- package/dist/inspector-CPF1N9dL.esm.js +1185 -0
- package/dist/inspector-CPF1N9dL.esm.js.map +1 -0
- package/dist/inspector-CPGK5Lg7.esm.js +1155 -0
- package/dist/inspector-CPGK5Lg7.esm.js.map +1 -0
- package/dist/inspector-CWcTSREy.cjs.js +1174 -0
- package/dist/inspector-CWcTSREy.cjs.js.map +1 -0
- package/dist/inspector-Cn_bl9Io.cjs.js +1189 -0
- package/dist/inspector-Cn_bl9Io.cjs.js.map +1 -0
- package/dist/inspector-D9DuXirp.cjs.js +1189 -0
- package/dist/inspector-D9DuXirp.cjs.js.map +1 -0
- package/dist/inspector-DQEtAjyM.esm.js +1129 -0
- package/dist/inspector-DQEtAjyM.esm.js.map +1 -0
- package/dist/inspector-DVlU9p44.cjs.js +1189 -0
- package/dist/inspector-DVlU9p44.cjs.js.map +1 -0
- package/dist/inspector-DaRVppX9.cjs.js +1134 -0
- package/dist/inspector-DaRVppX9.cjs.js.map +1 -0
- package/dist/inspector-huqtI2MD.esm.js +1170 -0
- package/dist/inspector-huqtI2MD.esm.js.map +1 -0
- package/dist/inspector-spoCY1tf.esm.js +1169 -0
- package/dist/inspector-spoCY1tf.esm.js.map +1 -0
- package/dist/inspector-tY1kJK5_.esm.js +1185 -0
- package/dist/inspector-tY1kJK5_.esm.js.map +1 -0
- package/dist/inspector.d.ts +43 -0
- package/dist/keyboard.d.ts +10 -0
- package/dist/overlay.d.ts +31 -0
- package/dist/react/InspectorProvider.d.ts +6 -0
- package/dist/react/index.cjs.js +32 -0
- package/dist/react/index.cjs.js.map +1 -0
- package/dist/react/index.esm.js +30 -0
- package/dist/react/index.esm.js.map +1 -0
- package/dist/sidebar/SidebarRuntime.d.ts +8 -0
- package/dist/sidebar-runtime.esm.js +2122 -0
- package/dist/sidebar-runtime.esm.js.map +1 -0
- package/dist/sidebar-runtime.iife.js +2991 -0
- package/dist/styles/sidebarStyles.d.ts +2 -0
- package/dist/styles.d.ts +8 -0
- package/dist/types/sidebar.d.ts +62 -0
- package/dist/types.d.ts +47 -0
- package/dist/utils/cookies.d.ts +10 -0
- package/dist/utils/devMode.d.ts +17 -0
- package/dist/utils/sessionStorage.d.ts +19 -0
- package/package.json +57 -40
- package/USAGE.md +0 -77
- package/dist/client/index.d.mts +0 -110
- package/dist/client/index.d.ts +0 -110
- package/dist/client/index.js +0 -1601
- package/dist/client/index.mjs +0 -1582
- package/dist/client/init.d.mts +0 -67
- package/dist/client/init.d.ts +0 -67
- package/dist/client/init.js +0 -1609
- package/dist/client/init.mjs +0 -1593
- package/dist/index.d.mts +0 -158
- package/dist/index.js +0 -1635
- package/dist/index.mjs +0 -1606
- package/src/api/client.ts +0 -141
- package/src/client/index.ts +0 -75
- package/src/client/init.tsx +0 -78
- package/src/components/ConversationalInputReact.tsx +0 -406
- package/src/components/ElementInfoDisplayReact.tsx +0 -84
- package/src/components/UiDogSidebarReact.tsx +0 -49
- package/src/element-detector.ts +0 -186
- package/src/index.ts +0 -228
- package/src/instrument.ts +0 -171
- package/src/sidebar-initializer.ts +0 -171
- package/src/source-resolver.ts +0 -121
- package/src/styles/sidebarStyles.ts +0 -597
- package/src/types/css.d.ts +0 -9
- package/src/types/sidebar.ts +0 -56
- package/src/types.ts +0 -119
- package/tsconfig.json +0 -23
- package/tsup.config.ts +0 -40
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import type { ElementInfo } from "../types";
|
|
2
|
-
|
|
3
|
-
interface ElementInfoDisplayProps {
|
|
4
|
-
elementInfo: ElementInfo;
|
|
5
|
-
onClose: () => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function ElementInfoDisplayReact(props: ElementInfoDisplayProps) {
|
|
9
|
-
const isDomSnapshot = props.elementInfo.kind === "dom";
|
|
10
|
-
|
|
11
|
-
if (isDomSnapshot) {
|
|
12
|
-
const dom = props.elementInfo.domSnapshot;
|
|
13
|
-
const outerHTML = dom?.outerHTML || "No HTML available";
|
|
14
|
-
const text = dom?.text || "";
|
|
15
|
-
const attributes = dom?.attributes || {};
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<div className="uidog-element-info">
|
|
19
|
-
<div className="uidog-element-info-content">
|
|
20
|
-
<div className="uidog-file-location">
|
|
21
|
-
Server-rendered DOM (no source available)
|
|
22
|
-
</div>
|
|
23
|
-
<button
|
|
24
|
-
className="uidog-close-btn"
|
|
25
|
-
onClick={props.onClose}
|
|
26
|
-
title="Close sidebar (ESC)"
|
|
27
|
-
aria-label="Close sidebar"
|
|
28
|
-
>
|
|
29
|
-
×
|
|
30
|
-
</button>
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<div className="uidog-dom-snapshot">
|
|
34
|
-
<div className="uidog-dom-label">outerHTML (trimmed):</div>
|
|
35
|
-
<pre className="uidog-dom-snippet">{outerHTML}</pre>
|
|
36
|
-
|
|
37
|
-
{text && (
|
|
38
|
-
<>
|
|
39
|
-
<div className="uidog-dom-label">textContent (trimmed):</div>
|
|
40
|
-
<pre className="uidog-dom-snippet">{text}</pre>
|
|
41
|
-
</>
|
|
42
|
-
)}
|
|
43
|
-
|
|
44
|
-
{Object.keys(attributes).length > 0 && (
|
|
45
|
-
<div className="uidog-dom-attributes">
|
|
46
|
-
<div className="uidog-dom-label">attributes:</div>
|
|
47
|
-
<ul>
|
|
48
|
-
{Object.entries(attributes).map(([key, value]) => (
|
|
49
|
-
<li key={key}>
|
|
50
|
-
<code>{key}</code>=<code>{value}</code>
|
|
51
|
-
</li>
|
|
52
|
-
))}
|
|
53
|
-
</ul>
|
|
54
|
-
</div>
|
|
55
|
-
)}
|
|
56
|
-
|
|
57
|
-
<div className="uidog-dom-hint">
|
|
58
|
-
To see file/line info, render this DOM through a small client
|
|
59
|
-
boundary.
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const fileName = props.elementInfo.filePath?.split("/").pop() || "";
|
|
67
|
-
const fileLocation = `Selected element at ${fileName}`;
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<div className="uidog-element-info">
|
|
71
|
-
<div className="uidog-element-info-content">
|
|
72
|
-
<span className="uidog-file-location">{fileLocation}</span>
|
|
73
|
-
<button
|
|
74
|
-
className="uidog-close-btn"
|
|
75
|
-
onClick={props.onClose}
|
|
76
|
-
title="Close sidebar (ESC)"
|
|
77
|
-
aria-label="Close sidebar"
|
|
78
|
-
>
|
|
79
|
-
×
|
|
80
|
-
</button>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
2
|
-
import type { ElementInfo } from "../types";
|
|
3
|
-
import { ElementInfoDisplayReact } from "./ElementInfoDisplayReact";
|
|
4
|
-
import { ConversationalInputReact } from "./ConversationalInputReact";
|
|
5
|
-
|
|
6
|
-
interface UiDogSidebarProps {
|
|
7
|
-
elementInfo: ElementInfo;
|
|
8
|
-
editorUrl: string;
|
|
9
|
-
onClose: () => void;
|
|
10
|
-
apiEndpoint: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function UiDogSidebarReact(props: UiDogSidebarProps) {
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
const handleEscapeKey = (e: KeyboardEvent) => {
|
|
16
|
-
if (e.key === "Escape") {
|
|
17
|
-
props.onClose();
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
document.addEventListener("keydown", handleEscapeKey);
|
|
22
|
-
return () => {
|
|
23
|
-
document.removeEventListener("keydown", handleEscapeKey);
|
|
24
|
-
};
|
|
25
|
-
}, [props]);
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<div className="uidog-sidebar-overlay">
|
|
29
|
-
<div className="uidog-sidebar">
|
|
30
|
-
{/* Element Info Section */}
|
|
31
|
-
<div className="uidog-element-info-section">
|
|
32
|
-
<ElementInfoDisplayReact
|
|
33
|
-
elementInfo={props.elementInfo}
|
|
34
|
-
onClose={props.onClose}
|
|
35
|
-
/>
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
{/* Chat Area - Messages + Input */}
|
|
39
|
-
<div className="uidog-chat-container">
|
|
40
|
-
<ConversationalInputReact
|
|
41
|
-
elementInfo={props.elementInfo}
|
|
42
|
-
editorUrl={props.editorUrl}
|
|
43
|
-
apiEndpoint={props.apiEndpoint}
|
|
44
|
-
/>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
);
|
|
49
|
-
}
|
package/src/element-detector.ts
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Element detector - handles Alt+click detection and source resolution using Bippy
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
getSourceFromElement,
|
|
7
|
-
getComponentNameFromFiber,
|
|
8
|
-
getFiberFromHostInstance,
|
|
9
|
-
} from "./instrument";
|
|
10
|
-
import { isSourceFile } from "./source-resolver";
|
|
11
|
-
import type { ElementDetectorOptions, SourceLocation } from "./types";
|
|
12
|
-
|
|
13
|
-
let detectorCleanup: (() => void) | null = null;
|
|
14
|
-
let isSetup = false;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Setup element detection with Alt+click (or other modifier)
|
|
18
|
-
*/
|
|
19
|
-
export function setupElementDetector(
|
|
20
|
-
options: ElementDetectorOptions
|
|
21
|
-
): () => void {
|
|
22
|
-
const { onElementSelected, modifier = "alt" } = options;
|
|
23
|
-
|
|
24
|
-
// Cleanup any existing detector
|
|
25
|
-
if (detectorCleanup) {
|
|
26
|
-
detectorCleanup();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
isSetup = true;
|
|
30
|
-
|
|
31
|
-
const handleClick = async (event: MouseEvent) => {
|
|
32
|
-
// Check if modifier key is pressed
|
|
33
|
-
const modifierPressed =
|
|
34
|
-
(modifier === "alt" && event.altKey) ||
|
|
35
|
-
(modifier === "ctrl" && event.ctrlKey) ||
|
|
36
|
-
(modifier === "meta" && event.metaKey) ||
|
|
37
|
-
(modifier === "shift" && event.shiftKey);
|
|
38
|
-
|
|
39
|
-
if (!modifierPressed) return;
|
|
40
|
-
|
|
41
|
-
event.preventDefault();
|
|
42
|
-
event.stopPropagation();
|
|
43
|
-
|
|
44
|
-
const target = event.target as Element;
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
// Get source location using Bippy
|
|
48
|
-
const source = await getSourceFromElement(target);
|
|
49
|
-
|
|
50
|
-
if (source && source.fileName && isSourceFile(source.fileName)) {
|
|
51
|
-
// Get component name
|
|
52
|
-
const fiber = getFiberFromHostInstance(target);
|
|
53
|
-
const componentName = fiber
|
|
54
|
-
? getComponentNameFromFiber(fiber)
|
|
55
|
-
: "Unknown";
|
|
56
|
-
|
|
57
|
-
const enrichedSource: SourceLocation = {
|
|
58
|
-
...source,
|
|
59
|
-
functionName: source.functionName || componentName,
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
onElementSelected(enrichedSource, target);
|
|
63
|
-
} else {
|
|
64
|
-
console.info(
|
|
65
|
-
"[UiDog Next] Could not find source for element. Falling back to DOM snapshot (likely server component or library code)."
|
|
66
|
-
);
|
|
67
|
-
onElementSelected(null, target);
|
|
68
|
-
}
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.warn("[UiDog Next] Error detecting element source:", error);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// Handle mouse movement for hover highlighting (optional enhancement)
|
|
75
|
-
const handleMouseMove = (event: MouseEvent) => {
|
|
76
|
-
// Check if modifier key is pressed
|
|
77
|
-
const modifierPressed =
|
|
78
|
-
(modifier === "alt" && event.altKey) ||
|
|
79
|
-
(modifier === "ctrl" && event.ctrlKey) ||
|
|
80
|
-
(modifier === "meta" && event.metaKey) ||
|
|
81
|
-
(modifier === "shift" && event.shiftKey);
|
|
82
|
-
|
|
83
|
-
if (!modifierPressed) {
|
|
84
|
-
removeHighlight();
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const target = event.target as Element;
|
|
89
|
-
highlightElement(target);
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
// Handle key up to remove highlight when modifier is released
|
|
93
|
-
const handleKeyUp = (event: KeyboardEvent) => {
|
|
94
|
-
const relevantKey =
|
|
95
|
-
(modifier === "alt" && event.key === "Alt") ||
|
|
96
|
-
(modifier === "ctrl" && event.key === "Control") ||
|
|
97
|
-
(modifier === "meta" && event.key === "Meta") ||
|
|
98
|
-
(modifier === "shift" && event.key === "Shift");
|
|
99
|
-
|
|
100
|
-
if (relevantKey) {
|
|
101
|
-
removeHighlight();
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// Use capture phase to intercept before other handlers
|
|
106
|
-
document.addEventListener("click", handleClick, true);
|
|
107
|
-
document.addEventListener("mousemove", handleMouseMove, true);
|
|
108
|
-
document.addEventListener("keyup", handleKeyUp, true);
|
|
109
|
-
|
|
110
|
-
detectorCleanup = () => {
|
|
111
|
-
document.removeEventListener("click", handleClick, true);
|
|
112
|
-
document.removeEventListener("mousemove", handleMouseMove, true);
|
|
113
|
-
document.removeEventListener("keyup", handleKeyUp, true);
|
|
114
|
-
removeHighlight();
|
|
115
|
-
isSetup = false;
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
return detectorCleanup;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Highlight state
|
|
122
|
-
let currentHighlight: HTMLElement | null = null;
|
|
123
|
-
let highlightOverlay: HTMLElement | null = null;
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Highlight an element on hover when modifier is pressed
|
|
127
|
-
*/
|
|
128
|
-
function highlightElement(element: Element): void {
|
|
129
|
-
// Don't highlight our own overlay
|
|
130
|
-
if (element === highlightOverlay || highlightOverlay?.contains(element)) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Create overlay if it doesn't exist
|
|
135
|
-
if (!highlightOverlay) {
|
|
136
|
-
highlightOverlay = document.createElement("div");
|
|
137
|
-
highlightOverlay.id = "uidog-highlight-overlay";
|
|
138
|
-
highlightOverlay.style.cssText = `
|
|
139
|
-
position: fixed;
|
|
140
|
-
pointer-events: none;
|
|
141
|
-
background: rgba(59, 130, 246, 0.2);
|
|
142
|
-
border: 2px solid rgba(59, 130, 246, 0.8);
|
|
143
|
-
border-radius: 4px;
|
|
144
|
-
z-index: 999998;
|
|
145
|
-
transition: all 0.1s ease-out;
|
|
146
|
-
`;
|
|
147
|
-
document.body.appendChild(highlightOverlay);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Update position
|
|
151
|
-
const rect = element.getBoundingClientRect();
|
|
152
|
-
highlightOverlay.style.top = `${rect.top}px`;
|
|
153
|
-
highlightOverlay.style.left = `${rect.left}px`;
|
|
154
|
-
highlightOverlay.style.width = `${rect.width}px`;
|
|
155
|
-
highlightOverlay.style.height = `${rect.height}px`;
|
|
156
|
-
highlightOverlay.style.display = "block";
|
|
157
|
-
|
|
158
|
-
currentHighlight = element as HTMLElement;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Remove highlight overlay
|
|
163
|
-
*/
|
|
164
|
-
function removeHighlight(): void {
|
|
165
|
-
if (highlightOverlay) {
|
|
166
|
-
highlightOverlay.style.display = "none";
|
|
167
|
-
}
|
|
168
|
-
currentHighlight = null;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Check if element detector is set up
|
|
173
|
-
*/
|
|
174
|
-
export function isElementDetectorSetup(): boolean {
|
|
175
|
-
return isSetup;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Cleanup element detector
|
|
180
|
-
*/
|
|
181
|
-
export function cleanupElementDetector(): void {
|
|
182
|
-
if (detectorCleanup) {
|
|
183
|
-
detectorCleanup();
|
|
184
|
-
detectorCleanup = null;
|
|
185
|
-
}
|
|
186
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UiDog SDK for Next.js - Main entry point
|
|
3
|
-
*
|
|
4
|
-
* Uses Bippy to hook into React's internals for element source detection,
|
|
5
|
-
* providing a seamless developer experience for inspecting component locations.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { setupBippyInstrumentation } from "./instrument";
|
|
9
|
-
import {
|
|
10
|
-
setupElementDetector,
|
|
11
|
-
cleanupElementDetector,
|
|
12
|
-
} from "./element-detector";
|
|
13
|
-
import {
|
|
14
|
-
initializeSidebar,
|
|
15
|
-
openSidebar,
|
|
16
|
-
closeSidebar,
|
|
17
|
-
cleanupSidebar,
|
|
18
|
-
} from "./sidebar-initializer";
|
|
19
|
-
import {
|
|
20
|
-
buildEditorUrl,
|
|
21
|
-
normalizeFileName,
|
|
22
|
-
getShortFileName,
|
|
23
|
-
} from "./source-resolver";
|
|
24
|
-
import type {
|
|
25
|
-
UiDogNextOptions,
|
|
26
|
-
SourceLocation,
|
|
27
|
-
ElementInfo,
|
|
28
|
-
EditorType,
|
|
29
|
-
} from "./types";
|
|
30
|
-
|
|
31
|
-
let isInitialized = false;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Initialize UiDog for Next.js
|
|
35
|
-
*
|
|
36
|
-
* This function sets up Bippy instrumentation, element detection, and the sidebar UI.
|
|
37
|
-
* It should be called early in your application's lifecycle, ideally via
|
|
38
|
-
* instrumentation-client.ts (Next.js 15.3+) or at the top of _app.tsx.
|
|
39
|
-
*/
|
|
40
|
-
export function initializeUiDogNext(options: UiDogNextOptions = {}): void {
|
|
41
|
-
if (typeof window === "undefined") return;
|
|
42
|
-
if (isInitialized) {
|
|
43
|
-
console.warn("[UiDog Next] Already initialized");
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Check if in development mode
|
|
48
|
-
if (process.env.NODE_ENV === "production") {
|
|
49
|
-
console.warn(
|
|
50
|
-
"[UiDog Next] Running in production mode. Element source detection may not work as _debugSource is stripped in production builds."
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const {
|
|
55
|
-
editor = "cursor",
|
|
56
|
-
projectPath = "",
|
|
57
|
-
modifier = "alt",
|
|
58
|
-
enableSidebar = true,
|
|
59
|
-
apiEndpoint = "https://api.ui.dog",
|
|
60
|
-
} = options;
|
|
61
|
-
|
|
62
|
-
isInitialized = true;
|
|
63
|
-
window.__UIDOG_NEXT_INITIALIZED__ = true;
|
|
64
|
-
|
|
65
|
-
// Setup Bippy instrumentation (hooks into React DevTools API)
|
|
66
|
-
setupBippyInstrumentation();
|
|
67
|
-
|
|
68
|
-
// Initialize sidebar if enabled
|
|
69
|
-
if (enableSidebar) {
|
|
70
|
-
initializeSidebar({ apiEndpoint });
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Setup element detection (Alt+click to select elements)
|
|
74
|
-
setupElementDetector({
|
|
75
|
-
modifier,
|
|
76
|
-
onElementSelected: (source: SourceLocation | null, element: Element) => {
|
|
77
|
-
const rect = element.getBoundingClientRect
|
|
78
|
-
? element.getBoundingClientRect()
|
|
79
|
-
: null;
|
|
80
|
-
|
|
81
|
-
const buildDomSnapshot = () => {
|
|
82
|
-
const outerHTML = element.outerHTML || "";
|
|
83
|
-
const text = (element.textContent || "").trim();
|
|
84
|
-
const attributes: Record<string, string> = {};
|
|
85
|
-
|
|
86
|
-
Array.from(element.attributes || []).forEach((attr) => {
|
|
87
|
-
attributes[attr.name] = attr.value;
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
outerHTML:
|
|
92
|
-
outerHTML.length > 4000
|
|
93
|
-
? `${outerHTML.slice(0, 4000)}…`
|
|
94
|
-
: outerHTML,
|
|
95
|
-
text: text.length > 1000 ? `${text.slice(0, 1000)}…` : text,
|
|
96
|
-
attributes,
|
|
97
|
-
};
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
if (source) {
|
|
101
|
-
const editorUrl = buildEditorUrl(source, editor, projectPath);
|
|
102
|
-
|
|
103
|
-
console.info(
|
|
104
|
-
"[UiDog Next] Source detected:",
|
|
105
|
-
normalizeFileName(source.fileName),
|
|
106
|
-
"line",
|
|
107
|
-
source.lineNumber,
|
|
108
|
-
"column",
|
|
109
|
-
source.columnNumber
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
if (enableSidebar) {
|
|
113
|
-
const elementInfo: ElementInfo = {
|
|
114
|
-
kind: "source",
|
|
115
|
-
componentName: source.functionName || "Unknown",
|
|
116
|
-
filePath: normalizeFileName(source.fileName),
|
|
117
|
-
line: source.lineNumber,
|
|
118
|
-
column: source.columnNumber,
|
|
119
|
-
box: rect
|
|
120
|
-
? {
|
|
121
|
-
x: rect.x,
|
|
122
|
-
y: rect.y,
|
|
123
|
-
width: rect.width,
|
|
124
|
-
height: rect.height,
|
|
125
|
-
}
|
|
126
|
-
: undefined,
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
openSidebar(elementInfo, editorUrl);
|
|
130
|
-
} else {
|
|
131
|
-
console.log("[UiDog Next] Element selected:");
|
|
132
|
-
console.log(" Component:", source.functionName || "Unknown");
|
|
133
|
-
console.log(" File:", source.fileName);
|
|
134
|
-
console.log(" Line:", source.lineNumber);
|
|
135
|
-
console.log(" Column:", source.columnNumber);
|
|
136
|
-
console.log(" Editor URL:", editorUrl);
|
|
137
|
-
}
|
|
138
|
-
} else {
|
|
139
|
-
const domSnapshot = buildDomSnapshot();
|
|
140
|
-
|
|
141
|
-
console.info("[UiDog Next] DOM snapshot (no source):", {
|
|
142
|
-
outerHTML: domSnapshot.outerHTML,
|
|
143
|
-
text: domSnapshot.text,
|
|
144
|
-
attributes: domSnapshot.attributes,
|
|
145
|
-
box: rect
|
|
146
|
-
? {
|
|
147
|
-
x: rect.x,
|
|
148
|
-
y: rect.y,
|
|
149
|
-
width: rect.width,
|
|
150
|
-
height: rect.height,
|
|
151
|
-
}
|
|
152
|
-
: undefined,
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
const elementInfo: ElementInfo = {
|
|
156
|
-
kind: "dom",
|
|
157
|
-
componentName: "Server-rendered element",
|
|
158
|
-
domSnapshot,
|
|
159
|
-
box: rect
|
|
160
|
-
? {
|
|
161
|
-
x: rect.x,
|
|
162
|
-
y: rect.y,
|
|
163
|
-
width: rect.width,
|
|
164
|
-
height: rect.height,
|
|
165
|
-
}
|
|
166
|
-
: undefined,
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
if (enableSidebar) {
|
|
170
|
-
openSidebar(elementInfo, "");
|
|
171
|
-
} else {
|
|
172
|
-
console.log("[UiDog Next] Element selected (DOM snapshot):");
|
|
173
|
-
console.log(" outerHTML:", domSnapshot.outerHTML);
|
|
174
|
-
console.log(" text:", domSnapshot.text);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
console.log(
|
|
181
|
-
`[UiDog Next] Initialized (${modifier}+click to select elements)`
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Cleanup UiDog - removes all event listeners and UI
|
|
187
|
-
*/
|
|
188
|
-
export function cleanupUiDogNext(): void {
|
|
189
|
-
cleanupElementDetector();
|
|
190
|
-
cleanupSidebar();
|
|
191
|
-
isInitialized = false;
|
|
192
|
-
|
|
193
|
-
if (typeof window !== "undefined") {
|
|
194
|
-
window.__UIDOG_NEXT_INITIALIZED__ = false;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Check if UiDog is initialized
|
|
200
|
-
*/
|
|
201
|
-
export function isUiDogNextInitialized(): boolean {
|
|
202
|
-
return isInitialized;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Re-export types and utilities
|
|
206
|
-
export type {
|
|
207
|
-
UiDogNextOptions,
|
|
208
|
-
SourceLocation,
|
|
209
|
-
ElementInfo,
|
|
210
|
-
EditorType,
|
|
211
|
-
SidebarConfig,
|
|
212
|
-
EditRequest,
|
|
213
|
-
EditResponse,
|
|
214
|
-
} from "./types";
|
|
215
|
-
|
|
216
|
-
export {
|
|
217
|
-
buildEditorUrl,
|
|
218
|
-
normalizeFileName,
|
|
219
|
-
getShortFileName,
|
|
220
|
-
} from "./source-resolver";
|
|
221
|
-
|
|
222
|
-
export { openSidebar, closeSidebar } from "./sidebar-initializer";
|
|
223
|
-
|
|
224
|
-
export {
|
|
225
|
-
setupBippyInstrumentation,
|
|
226
|
-
getSourceFromElement,
|
|
227
|
-
getComponentNameFromFiber,
|
|
228
|
-
} from "./instrument";
|