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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -433
  3. package/dist/api/client.d.ts +74 -0
  4. package/dist/components/ConversationalInputReact.d.ts +26 -0
  5. package/dist/components/ElementInfoDisplayReact.d.ts +9 -0
  6. package/dist/components/FixdogSidebarReact.d.ts +29 -0
  7. package/dist/fiber.d.ts +9 -0
  8. package/dist/index.cjs.js +33 -0
  9. package/dist/index.cjs.js.map +1 -0
  10. package/dist/index.d.ts +6 -158
  11. package/dist/index.esm.js +29 -0
  12. package/dist/index.esm.js.map +1 -0
  13. package/dist/inspector-B4F5CBT7.cjs.js +1159 -0
  14. package/dist/inspector-B4F5CBT7.cjs.js.map +1 -0
  15. package/dist/inspector-BL2pNjn-.cjs.js +1173 -0
  16. package/dist/inspector-BL2pNjn-.cjs.js.map +1 -0
  17. package/dist/inspector-Bg6uSvk0.esm.js +1273 -0
  18. package/dist/inspector-Bg6uSvk0.esm.js.map +1 -0
  19. package/dist/inspector-BuOffbVc.cjs.js +1280 -0
  20. package/dist/inspector-BuOffbVc.cjs.js.map +1 -0
  21. package/dist/inspector-CNgFkZOU.esm.js +1185 -0
  22. package/dist/inspector-CNgFkZOU.esm.js.map +1 -0
  23. package/dist/inspector-CPF1N9dL.esm.js +1185 -0
  24. package/dist/inspector-CPF1N9dL.esm.js.map +1 -0
  25. package/dist/inspector-CPGK5Lg7.esm.js +1155 -0
  26. package/dist/inspector-CPGK5Lg7.esm.js.map +1 -0
  27. package/dist/inspector-CWcTSREy.cjs.js +1174 -0
  28. package/dist/inspector-CWcTSREy.cjs.js.map +1 -0
  29. package/dist/inspector-Cn_bl9Io.cjs.js +1189 -0
  30. package/dist/inspector-Cn_bl9Io.cjs.js.map +1 -0
  31. package/dist/inspector-D9DuXirp.cjs.js +1189 -0
  32. package/dist/inspector-D9DuXirp.cjs.js.map +1 -0
  33. package/dist/inspector-DQEtAjyM.esm.js +1129 -0
  34. package/dist/inspector-DQEtAjyM.esm.js.map +1 -0
  35. package/dist/inspector-DVlU9p44.cjs.js +1189 -0
  36. package/dist/inspector-DVlU9p44.cjs.js.map +1 -0
  37. package/dist/inspector-DaRVppX9.cjs.js +1134 -0
  38. package/dist/inspector-DaRVppX9.cjs.js.map +1 -0
  39. package/dist/inspector-huqtI2MD.esm.js +1170 -0
  40. package/dist/inspector-huqtI2MD.esm.js.map +1 -0
  41. package/dist/inspector-spoCY1tf.esm.js +1169 -0
  42. package/dist/inspector-spoCY1tf.esm.js.map +1 -0
  43. package/dist/inspector-tY1kJK5_.esm.js +1185 -0
  44. package/dist/inspector-tY1kJK5_.esm.js.map +1 -0
  45. package/dist/inspector.d.ts +43 -0
  46. package/dist/keyboard.d.ts +10 -0
  47. package/dist/overlay.d.ts +31 -0
  48. package/dist/react/InspectorProvider.d.ts +6 -0
  49. package/dist/react/index.cjs.js +32 -0
  50. package/dist/react/index.cjs.js.map +1 -0
  51. package/dist/react/index.esm.js +30 -0
  52. package/dist/react/index.esm.js.map +1 -0
  53. package/dist/sidebar/SidebarRuntime.d.ts +8 -0
  54. package/dist/sidebar-runtime.esm.js +2122 -0
  55. package/dist/sidebar-runtime.esm.js.map +1 -0
  56. package/dist/sidebar-runtime.iife.js +2991 -0
  57. package/dist/styles/sidebarStyles.d.ts +2 -0
  58. package/dist/styles.d.ts +8 -0
  59. package/dist/types/sidebar.d.ts +62 -0
  60. package/dist/types.d.ts +47 -0
  61. package/dist/utils/cookies.d.ts +10 -0
  62. package/dist/utils/devMode.d.ts +17 -0
  63. package/dist/utils/sessionStorage.d.ts +19 -0
  64. package/package.json +57 -40
  65. package/USAGE.md +0 -77
  66. package/dist/client/index.d.mts +0 -110
  67. package/dist/client/index.d.ts +0 -110
  68. package/dist/client/index.js +0 -1601
  69. package/dist/client/index.mjs +0 -1582
  70. package/dist/client/init.d.mts +0 -67
  71. package/dist/client/init.d.ts +0 -67
  72. package/dist/client/init.js +0 -1609
  73. package/dist/client/init.mjs +0 -1593
  74. package/dist/index.d.mts +0 -158
  75. package/dist/index.js +0 -1635
  76. package/dist/index.mjs +0 -1606
  77. package/src/api/client.ts +0 -141
  78. package/src/client/index.ts +0 -75
  79. package/src/client/init.tsx +0 -78
  80. package/src/components/ConversationalInputReact.tsx +0 -406
  81. package/src/components/ElementInfoDisplayReact.tsx +0 -84
  82. package/src/components/UiDogSidebarReact.tsx +0 -49
  83. package/src/element-detector.ts +0 -186
  84. package/src/index.ts +0 -228
  85. package/src/instrument.ts +0 -171
  86. package/src/sidebar-initializer.ts +0 -171
  87. package/src/source-resolver.ts +0 -121
  88. package/src/styles/sidebarStyles.ts +0 -597
  89. package/src/types/css.d.ts +0 -9
  90. package/src/types/sidebar.ts +0 -56
  91. package/src/types.ts +0 -119
  92. package/tsconfig.json +0 -23
  93. package/tsup.config.ts +0 -40
package/src/instrument.ts DELETED
@@ -1,171 +0,0 @@
1
- /**
2
- * Bippy instrumentation setup for React fiber inspection
3
- *
4
- * Bippy hooks into React's DevTools API (window.__REACT_DEVTOOLS_GLOBAL_HOOK__)
5
- * to intercept fiber tree data and extract source location information.
6
- */
7
-
8
- import {
9
- instrument,
10
- secure,
11
- isCompositeFiber,
12
- isHostFiber,
13
- traverseFiber,
14
- getDisplayName,
15
- getFiberFromHostInstance,
16
- } from "bippy";
17
- import { getSource } from "bippy/source";
18
- import type { SourceLocation } from "./types";
19
-
20
- let isInstrumented = false;
21
-
22
- /**
23
- * Setup Bippy instrumentation to hook into React's internals
24
- * This must be called BEFORE React loads (via instrumentation-client.ts)
25
- */
26
- export function setupBippyInstrumentation(): void {
27
- if (isInstrumented) return;
28
- if (typeof window === "undefined") return;
29
-
30
- isInstrumented = true;
31
-
32
- instrument(
33
- secure({
34
- onCommitFiberRoot: (_rendererID, _fiberRoot) => {
35
- // Called when React commits a render
36
- // We can use this for additional tracking if needed
37
- },
38
- })
39
- );
40
- }
41
-
42
- /**
43
- * Get source location from a DOM element by traversing its React fiber
44
- */
45
- export async function getSourceFromElement(
46
- element: Element
47
- ): Promise<SourceLocation | null> {
48
- try {
49
- // Get the fiber associated with this DOM element
50
- const fiber = getFiberFromHostInstance(element);
51
-
52
- if (!fiber) {
53
- return null;
54
- }
55
-
56
- // Try to get source from the fiber
57
- const source = await getSource(fiber);
58
-
59
- if (source && source.fileName) {
60
- // Filter out node_modules and internal files
61
- if (
62
- source.fileName.includes("node_modules") ||
63
- source.fileName.includes("react-dom") ||
64
- source.fileName.includes("react/")
65
- ) {
66
- // Try parent fibers to find user code
67
- return await findUserSourceFromFiber(fiber);
68
- }
69
-
70
- return {
71
- fileName: source.fileName,
72
- lineNumber: source.lineNumber ?? 1,
73
- columnNumber: source.columnNumber ?? 1,
74
- functionName: source.functionName ?? undefined,
75
- };
76
- }
77
-
78
- // Fallback: traverse up the fiber tree to find source
79
- return await findUserSourceFromFiber(fiber);
80
- } catch (error) {
81
- console.warn("[UiDog Next] Error getting source from element:", error);
82
- return null;
83
- }
84
- }
85
-
86
- /**
87
- * Traverse up the fiber tree to find the first user-code source
88
- */
89
- async function findUserSourceFromFiber(
90
- startFiber: any
91
- ): Promise<SourceLocation | null> {
92
- let result: SourceLocation | null = null;
93
-
94
- // Traverse upward through the fiber tree
95
- traverseFiber(
96
- startFiber,
97
- async (fiber) => {
98
- // Only check composite fibers (components, not host elements)
99
- if (isCompositeFiber(fiber)) {
100
- try {
101
- const source = await getSource(fiber);
102
-
103
- if (source && source.fileName) {
104
- // Skip internal/library code
105
- if (
106
- !source.fileName.includes("node_modules") &&
107
- !source.fileName.includes("react-dom") &&
108
- !source.fileName.includes("react/")
109
- ) {
110
- result = {
111
- fileName: source.fileName,
112
- lineNumber: source.lineNumber ?? 1,
113
- columnNumber: source.columnNumber ?? 1,
114
- functionName: source.functionName ?? getDisplayName(fiber) ?? undefined,
115
- };
116
- return true; // Stop traversal
117
- }
118
- }
119
- } catch {
120
- // Continue to next fiber
121
- }
122
- }
123
- return false; // Continue traversal
124
- },
125
- true // Traverse upward (toward root)
126
- );
127
-
128
- return result;
129
- }
130
-
131
- /**
132
- * Get component name from a fiber
133
- */
134
- export function getComponentNameFromFiber(fiber: any): string {
135
- if (!fiber) return "Unknown";
136
-
137
- // Try to get display name directly
138
- const displayName = getDisplayName(fiber);
139
- if (displayName && displayName !== "Unknown") {
140
- return displayName;
141
- }
142
-
143
- // Traverse up to find the nearest named component
144
- let componentName = "Unknown";
145
-
146
- traverseFiber(
147
- fiber,
148
- (f) => {
149
- if (isCompositeFiber(f)) {
150
- const name = getDisplayName(f);
151
- if (name && name !== "Unknown") {
152
- componentName = name;
153
- return true; // Stop traversal
154
- }
155
- }
156
- return false;
157
- },
158
- true // Traverse upward
159
- );
160
-
161
- return componentName;
162
- }
163
-
164
- // Re-export useful bippy utilities
165
- export {
166
- isCompositeFiber,
167
- isHostFiber,
168
- traverseFiber,
169
- getDisplayName,
170
- getFiberFromHostInstance,
171
- };
@@ -1,171 +0,0 @@
1
- /**
2
- * Sidebar initializer - mounts the UiDog sidebar in a shadow DOM for style isolation
3
- */
4
-
5
- import { createRoot, Root } from "react-dom/client";
6
- import { createElement } from "react";
7
- import { UiDogSidebarReact } from "./components/UiDogSidebarReact";
8
- import sidebarStyles from "./styles/sidebarStyles";
9
- import type { ElementInfo, SidebarConfig } from "./types";
10
-
11
- let sidebarRoot: Root | null = null;
12
- let sidebarContainer: HTMLElement | null = null;
13
- let shadowRoot: ShadowRoot | null = null;
14
- let config: SidebarConfig = { apiEndpoint: "https://api.ui.dog" };
15
-
16
- // Current sidebar state
17
- let currentState: {
18
- isOpen: boolean;
19
- elementInfo: ElementInfo | null;
20
- editorUrl: string;
21
- } = {
22
- isOpen: false,
23
- elementInfo: null,
24
- editorUrl: "",
25
- };
26
-
27
- /**
28
- * Initialize the sidebar with configuration
29
- */
30
- export function initializeSidebar(sidebarConfig: SidebarConfig): void {
31
- if (typeof window === "undefined") return;
32
-
33
- config = sidebarConfig;
34
-
35
- // Check if already initialized
36
- if (document.getElementById("uidog-next-sidebar-root")) {
37
- return;
38
- }
39
-
40
- // Create container
41
- sidebarContainer = document.createElement("div");
42
- sidebarContainer.id = "uidog-next-sidebar-root";
43
- document.body.appendChild(sidebarContainer);
44
-
45
- // Create shadow DOM for style isolation
46
- shadowRoot = sidebarContainer.attachShadow({ mode: "open" });
47
-
48
- // Inject styles
49
- const styleElement = document.createElement("style");
50
- styleElement.textContent = sidebarStyles;
51
- shadowRoot.appendChild(styleElement);
52
-
53
- // Create mount point
54
- const mountPoint = document.createElement("div");
55
- mountPoint.id = "uidog-sidebar-mount";
56
- shadowRoot.appendChild(mountPoint);
57
-
58
- // Create React root
59
- sidebarRoot = createRoot(mountPoint);
60
-
61
- // Initial render (empty)
62
- render();
63
- }
64
-
65
- /**
66
- * Render the sidebar based on current state
67
- */
68
- function render(): void {
69
- if (!sidebarRoot) return;
70
-
71
- const { isOpen, elementInfo, editorUrl } = currentState;
72
-
73
- if (!isOpen || !elementInfo) {
74
- sidebarRoot.render(null);
75
- return;
76
- }
77
-
78
- sidebarRoot.render(
79
- createElement(UiDogSidebarReact, {
80
- elementInfo,
81
- editorUrl,
82
- onClose: closeSidebar,
83
- apiEndpoint: config.apiEndpoint,
84
- })
85
- );
86
- }
87
-
88
- /**
89
- * Open the sidebar with element information
90
- */
91
- export function openSidebar(elementInfo: ElementInfo, editorUrl: string): void {
92
- currentState = {
93
- isOpen: true,
94
- elementInfo,
95
- editorUrl,
96
- };
97
-
98
- // Update global state for debugging
99
- if (typeof window !== "undefined") {
100
- window.__UIDOG_SIDEBAR__ = {
101
- isOpen: true,
102
- elementInfo,
103
- editorUrl,
104
- };
105
- }
106
-
107
- render();
108
- }
109
-
110
- /**
111
- * Close the sidebar
112
- */
113
- export function closeSidebar(): void {
114
- currentState = {
115
- isOpen: false,
116
- elementInfo: null,
117
- editorUrl: "",
118
- };
119
-
120
- // Update global state
121
- if (typeof window !== "undefined") {
122
- window.__UIDOG_SIDEBAR__ = {
123
- isOpen: false,
124
- elementInfo: null,
125
- editorUrl: null,
126
- };
127
- }
128
-
129
- render();
130
- }
131
-
132
- /**
133
- * Check if the sidebar is currently open
134
- */
135
- export function isSidebarOpen(): boolean {
136
- return currentState.isOpen;
137
- }
138
-
139
- /**
140
- * Get current sidebar state
141
- */
142
- export function getSidebarState(): typeof currentState {
143
- return { ...currentState };
144
- }
145
-
146
- /**
147
- * Cleanup sidebar (for testing or unmounting)
148
- */
149
- export function cleanupSidebar(): void {
150
- if (sidebarRoot) {
151
- sidebarRoot.unmount();
152
- sidebarRoot = null;
153
- }
154
-
155
- if (sidebarContainer && sidebarContainer.parentNode) {
156
- sidebarContainer.parentNode.removeChild(sidebarContainer);
157
- sidebarContainer = null;
158
- }
159
-
160
- shadowRoot = null;
161
-
162
- currentState = {
163
- isOpen: false,
164
- elementInfo: null,
165
- editorUrl: "",
166
- };
167
-
168
- if (typeof window !== "undefined") {
169
- delete window.__UIDOG_SIDEBAR__;
170
- }
171
- }
@@ -1,121 +0,0 @@
1
- /**
2
- * Source resolver - builds editor URLs from source location information
3
- */
4
-
5
- import type { SourceLocation, EditorType } from "./types";
6
-
7
- const EDITOR_SCHEMES: Record<EditorType, string> = {
8
- vscode: "vscode://file/{path}:{line}:{column}",
9
- "vscode-insiders": "vscode-insiders://file/{path}:{line}:{column}",
10
- cursor: "cursor://file/{path}:{line}:{column}",
11
- webstorm: "webstorm://open?file={path}&line={line}&column={column}",
12
- atom: "atom://core/open/file?filename={path}&line={line}&column={column}",
13
- sublime: "subl://open?url=file://{path}&line={line}&column={column}",
14
- };
15
-
16
- /**
17
- * Build an editor URL from source location information
18
- */
19
- export function buildEditorUrl(
20
- source: SourceLocation,
21
- editor: EditorType = "cursor",
22
- projectPath: string = ""
23
- ): string {
24
- const template = EDITOR_SCHEMES[editor] || EDITOR_SCHEMES.cursor;
25
-
26
- // Normalize and build full path
27
- let fullPath = normalizeFileName(source.fileName);
28
-
29
- // If path is relative and we have a project path, make it absolute
30
- if (projectPath && !fullPath.startsWith("/")) {
31
- const normalizedProjectPath = projectPath.endsWith("/")
32
- ? projectPath.slice(0, -1)
33
- : projectPath;
34
- fullPath = `${normalizedProjectPath}/${fullPath}`;
35
- }
36
-
37
- return template
38
- .replace("{path}", fullPath)
39
- .replace("{line}", String(source.lineNumber || 1))
40
- .replace("{column}", String(source.columnNumber || 1));
41
- }
42
-
43
- /**
44
- * Normalize file name by removing bundler prefixes and query strings
45
- */
46
- export function normalizeFileName(fileName: string): string {
47
- if (!fileName) return "";
48
-
49
- let normalized = fileName;
50
-
51
- // Remove common bundler prefixes
52
- const prefixPatterns = [
53
- /^webpack:\/\/[^/]*\//,
54
- /^webpack-internal:\/\/\//,
55
- /^file:\/\//,
56
- /^about:react/,
57
- /^\.\//,
58
- /^https?:\/\/localhost:\d+\//,
59
- /^https?:\/\/[^/]+\/@fs\//,
60
- /^https?:\/\/[^/]+\//,
61
- /^\/@fs\//,
62
- /^@fs\//,
63
- ];
64
-
65
- for (const pattern of prefixPatterns) {
66
- normalized = normalized.replace(pattern, "");
67
- }
68
-
69
- // Remove query strings and hash fragments
70
- normalized = normalized.split("?")[0].split("#")[0];
71
-
72
- // Remove leading slashes if duplicated
73
- normalized = normalized.replace(/^\/+/, "/");
74
-
75
- return normalized;
76
- }
77
-
78
- /**
79
- * Check if a file name represents actual source code (not bundled/internal)
80
- */
81
- export function isSourceFile(fileName: string): boolean {
82
- if (!fileName) return false;
83
-
84
- const normalized = normalizeFileName(fileName);
85
-
86
- // Exclude patterns
87
- const excludePatterns = [
88
- /node_modules/,
89
- /react-dom/,
90
- /^react\//,
91
- /\.next\//,
92
- /_next\//,
93
- /webpack/,
94
- /@vite\//,
95
- /vite\/client/,
96
- /\[eval\]/,
97
- /<anonymous>/,
98
- ];
99
-
100
- for (const pattern of excludePatterns) {
101
- if (pattern.test(normalized)) {
102
- return false;
103
- }
104
- }
105
-
106
- // Include patterns (common source file extensions)
107
- const includeExtensions = [".tsx", ".ts", ".jsx", ".js", ".mjs", ".cjs"];
108
-
109
- return includeExtensions.some((ext) =>
110
- normalized.toLowerCase().endsWith(ext)
111
- );
112
- }
113
-
114
- /**
115
- * Get the file name without path for display
116
- */
117
- export function getShortFileName(filePath: string): string {
118
- const normalized = normalizeFileName(filePath);
119
- const parts = normalized.split("/");
120
- return parts[parts.length - 1] || normalized;
121
- }