@promakeai/inspector 0.2.2 → 1.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/inspector.css +1 -0
- package/dist/inspector.js +8740 -0
- package/dist/packages/inspector/src/App.d.ts +5 -0
- package/dist/packages/inspector/src/App.d.ts.map +1 -0
- package/dist/packages/inspector/src/__tests__/App.test.d.ts +5 -0
- package/dist/packages/inspector/src/__tests__/App.test.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/Badge.d.ts +9 -0
- package/dist/packages/inspector/src/components/Badge.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ControlBox/ContentArea.d.ts +10 -0
- package/dist/packages/inspector/src/components/ControlBox/ContentArea.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ControlBox/PromptInput.d.ts +12 -0
- package/dist/packages/inspector/src/components/ControlBox/PromptInput.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ControlBox/index.d.ts +21 -0
- package/dist/packages/inspector/src/components/ControlBox/index.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ImageEditor/UploadBox.d.ts +10 -0
- package/dist/packages/inspector/src/components/ImageEditor/UploadBox.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ImageEditor/index.d.ts +11 -0
- package/dist/packages/inspector/src/components/ImageEditor/index.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/Overlay.d.ts +11 -0
- package/dist/packages/inspector/src/components/Overlay.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/BorderSection.d.ts +13 -0
- package/dist/packages/inspector/src/components/StyleEditor/BorderSection.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/ColorPicker.d.ts +13 -0
- package/dist/packages/inspector/src/components/StyleEditor/ColorPicker.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/DisplaySection.d.ts +13 -0
- package/dist/packages/inspector/src/components/StyleEditor/DisplaySection.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/ImageSection.d.ts +13 -0
- package/dist/packages/inspector/src/components/StyleEditor/ImageSection.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/LayoutSection.d.ts +13 -0
- package/dist/packages/inspector/src/components/StyleEditor/LayoutSection.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/NumberInput.d.ts +17 -0
- package/dist/packages/inspector/src/components/StyleEditor/NumberInput.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/SliderInput.d.ts +16 -0
- package/dist/packages/inspector/src/components/StyleEditor/SliderInput.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/SpacingSection.d.ts +13 -0
- package/dist/packages/inspector/src/components/StyleEditor/SpacingSection.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/TextSection.d.ts +13 -0
- package/dist/packages/inspector/src/components/StyleEditor/TextSection.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/StyleEditor/index.d.ts +12 -0
- package/dist/packages/inspector/src/components/StyleEditor/index.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/TextEditor/index.d.ts +11 -0
- package/dist/packages/inspector/src/components/TextEditor/index.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ui/CustomCollapsible.d.ts +26 -0
- package/dist/packages/inspector/src/components/ui/CustomCollapsible.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ui/button.d.ts +9 -0
- package/dist/packages/inspector/src/components/ui/button.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ui/color-picker.d.ts +10 -0
- package/dist/packages/inspector/src/components/ui/color-picker.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ui/input.d.ts +6 -0
- package/dist/packages/inspector/src/components/ui/input.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ui/popover.d.ts +8 -0
- package/dist/packages/inspector/src/components/ui/popover.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ui/select.d.ts +16 -0
- package/dist/packages/inspector/src/components/ui/select.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ui/slider.d.ts +5 -0
- package/dist/packages/inspector/src/components/ui/slider.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ui/textarea.d.ts +4 -0
- package/dist/packages/inspector/src/components/ui/textarea.d.ts.map +1 -0
- package/dist/packages/inspector/src/components/ui/tooltip.d.ts +8 -0
- package/dist/packages/inspector/src/components/ui/tooltip.d.ts.map +1 -0
- package/dist/packages/inspector/src/core/highlighter.d.ts +40 -0
- package/dist/packages/inspector/src/core/highlighter.d.ts.map +1 -0
- package/dist/packages/inspector/src/hooks/useMessageBridge.d.ts +9 -0
- package/dist/packages/inspector/src/hooks/useMessageBridge.d.ts.map +1 -0
- package/dist/packages/inspector/src/hooks/useStylePreview.d.ts +11 -0
- package/dist/packages/inspector/src/hooks/useStylePreview.d.ts.map +1 -0
- package/dist/packages/inspector/src/index.d.ts +16 -0
- package/dist/packages/inspector/src/index.d.ts.map +1 -0
- package/dist/packages/inspector/src/lib/utils.d.ts +3 -0
- package/dist/packages/inspector/src/lib/utils.d.ts.map +1 -0
- package/dist/packages/inspector/src/plugin.d.ts +4 -0
- package/dist/packages/inspector/src/plugin.d.ts.map +1 -0
- package/dist/packages/inspector/src/store/useInspectorStore.d.ts +13 -0
- package/dist/packages/inspector/src/store/useInspectorStore.d.ts.map +1 -0
- package/dist/packages/inspector/src/styles.d.ts +5 -0
- package/dist/packages/inspector/src/styles.d.ts.map +1 -0
- package/dist/packages/inspector/src/utils/colorUtils.d.ts +49 -0
- package/dist/packages/inspector/src/utils/colorUtils.d.ts.map +1 -0
- package/dist/packages/inspector/src/utils/elementNames.d.ts +7 -0
- package/dist/packages/inspector/src/utils/elementNames.d.ts.map +1 -0
- package/dist/packages/inspector/src/utils/elementUtils.d.ts +28 -0
- package/dist/packages/inspector/src/utils/elementUtils.d.ts.map +1 -0
- package/dist/packages/inspector/src/utils/errorTracker.d.ts +48 -0
- package/dist/packages/inspector/src/utils/errorTracker.d.ts.map +1 -0
- package/dist/packages/inspector/src/utils/inputStyles.d.ts +23 -0
- package/dist/packages/inspector/src/utils/inputStyles.d.ts.map +1 -0
- package/dist/packages/inspector/src/utils/styleUtils.d.ts +27 -0
- package/dist/packages/inspector/src/utils/styleUtils.d.ts.map +1 -0
- package/dist/packages/inspector/src/utils/tailwindMapper.d.ts +9 -0
- package/dist/packages/inspector/src/utils/tailwindMapper.d.ts.map +1 -0
- package/dist/packages/inspector/src/utils/urlTracker.d.ts +27 -0
- package/dist/packages/inspector/src/utils/urlTracker.d.ts.map +1 -0
- package/dist/packages/inspector/tsconfig.tsbuildinfo +1 -0
- package/dist/plugin.js +10 -1893
- package/package.json +80 -75
- package/README.md +0 -866
- package/dist/hook.d.ts +0 -115
- package/dist/hook.d.ts.map +0 -1
- package/dist/hook.js +0 -288
- package/dist/plugin.d.ts +0 -44
- package/dist/plugin.d.ts.map +0 -1
- package/dist/types.d.ts +0 -141
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -7
package/README.md
DELETED
|
@@ -1,866 +0,0 @@
|
|
|
1
|
-
# @promakeai/inspector
|
|
2
|
-
|
|
3
|
-
[](https://github.com/promakeai/inspector/actions/workflows/build.yml)
|
|
4
|
-
[](https://github.com/promakeai/inspector/actions/workflows/test.yml)
|
|
5
|
-
[](https://www.npmjs.com/package/@promakeai/inspector)
|
|
6
|
-
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
|
|
8
|
-
Visual element inspector for React apps in iframe with AI prompt support. Perfect for visual editors, page builders, and low-code platforms.
|
|
9
|
-
|
|
10
|
-
## Features
|
|
11
|
-
|
|
12
|
-
- 🎯 **Element Selection** - Click to select any element on the page
|
|
13
|
-
- 🔍 **React Component Detection** - Automatically detects React components via Fiber
|
|
14
|
-
- 📝 **Dynamic Content Input** - Show/hide text editing on-demand with `showContentInput()`
|
|
15
|
-
- 🖼️ **Image Upload Support** - Custom drag & drop image uploader with preview
|
|
16
|
-
- ⚡ **Immediate DOM Updates** - Optional instant feedback while backend processes
|
|
17
|
-
- 🤖 **AI Prompt Support** - Always-visible prompt input for AI modifications
|
|
18
|
-
- 🎨 **Visual Feedback** - Highlight selected elements with overlay
|
|
19
|
-
- 🔒 **Pause Mode** - Lock selection and disable scroll while editing
|
|
20
|
-
- 🌐 **URL Tracking** - Monitor navigation changes in iframe
|
|
21
|
-
- 🐛 **Error Tracking** - Capture JavaScript errors, promise rejections, and console errors
|
|
22
|
-
- 🎨 **Customizable Theme** - Full color customization for all UI elements
|
|
23
|
-
- 🌍 **Customizable Labels** - Multi-language support
|
|
24
|
-
- 🚫 **Ignore Elements** - Mark elements as non-inspectable with `data-inspector-ignore`
|
|
25
|
-
- 🔍 **Text Node Detection** - Automatically detect if selected element is a text node
|
|
26
|
-
- 🖼️ **Image Node Detection** - Automatically detect if selected element is an image
|
|
27
|
-
- 🏷️ **Promake Badge** - Optional "Built by Promake" badge with smooth animations
|
|
28
|
-
- 🔍 **Element Highlighting** - Revisit and highlight previously inspected elements
|
|
29
|
-
- 🆔 **Persistent Element IDs** - Structural signature-based IDs that survive page reloads
|
|
30
|
-
- 🔄 **Reload-Safe Highlighting** - Same element gets same ID even after refresh
|
|
31
|
-
- 🎯 **Smart Fallback** - Position-based matching when DOM structure changes
|
|
32
|
-
- 📦 **TypeScript** - Full type safety
|
|
33
|
-
- ✅ **Well Tested** - 42 unit tests + 35 e2e tests with 90%+ coverage
|
|
34
|
-
|
|
35
|
-
## Installation
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
npm install @promakeai/inspector
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Usage
|
|
42
|
-
|
|
43
|
-
### Template Side (iframe/vite app)
|
|
44
|
-
|
|
45
|
-
Add the plugin to your `vite.config.ts`:
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
import { defineConfig } from "vite";
|
|
49
|
-
import react from "@vitejs/plugin-react";
|
|
50
|
-
import { inspectorPlugin } from "@promakeai/inspector/plugin";
|
|
51
|
-
|
|
52
|
-
export default defineConfig({
|
|
53
|
-
plugins: [react(), inspectorPlugin()],
|
|
54
|
-
});
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Parent App Side
|
|
58
|
-
|
|
59
|
-
Use the hook in your React app:
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
import { useRef } from "react";
|
|
63
|
-
import { useInspector } from "@promakeai/inspector/hook";
|
|
64
|
-
|
|
65
|
-
function App() {
|
|
66
|
-
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
67
|
-
|
|
68
|
-
const { isInspecting, toggleInspector, showContentInput, showImageInput } =
|
|
69
|
-
useInspector(
|
|
70
|
-
iframeRef,
|
|
71
|
-
{
|
|
72
|
-
onElementSelected: (data) => {
|
|
73
|
-
console.log("Element selected:", data);
|
|
74
|
-
console.log("Is text node:", data.isTextNode);
|
|
75
|
-
console.log("Is image node:", data.isImageNode);
|
|
76
|
-
|
|
77
|
-
// Access component info
|
|
78
|
-
console.log(data.component?.fileName);
|
|
79
|
-
console.log(data.component?.lineNumber);
|
|
80
|
-
|
|
81
|
-
// Show content input if it's a text node
|
|
82
|
-
if (data.isTextNode) {
|
|
83
|
-
showContentInput(true);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Show image input if it's an image node
|
|
87
|
-
if (data.isImageNode) {
|
|
88
|
-
showImageInput(true);
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
|
-
onPromptSubmitted: (data) => {
|
|
92
|
-
console.log("AI Prompt:", data.prompt);
|
|
93
|
-
// Send to your AI service
|
|
94
|
-
fetch("/api/ai-edit", {
|
|
95
|
-
method: "POST",
|
|
96
|
-
body: JSON.stringify({
|
|
97
|
-
prompt: data.prompt,
|
|
98
|
-
element: data.element,
|
|
99
|
-
}),
|
|
100
|
-
});
|
|
101
|
-
},
|
|
102
|
-
onTextUpdated: (data) => {
|
|
103
|
-
console.log("Text updated:", data.text);
|
|
104
|
-
// Save to backend
|
|
105
|
-
},
|
|
106
|
-
onImageUpdated: (data) => {
|
|
107
|
-
console.log("Image updated:", data.imageFile.name);
|
|
108
|
-
console.log("Image data (base64):", data.imageData);
|
|
109
|
-
// Upload to server
|
|
110
|
-
fetch("/api/upload-image", {
|
|
111
|
-
method: "POST",
|
|
112
|
-
body: JSON.stringify(data),
|
|
113
|
-
});
|
|
114
|
-
},
|
|
115
|
-
onInspectorClosed: () => {
|
|
116
|
-
console.log("Inspector closed");
|
|
117
|
-
// Update UI state, re-enable elements, etc.
|
|
118
|
-
},
|
|
119
|
-
onUrlChange: (data) => {
|
|
120
|
-
console.log("URL changed:", data.pathname);
|
|
121
|
-
},
|
|
122
|
-
onError: (data) => {
|
|
123
|
-
console.error("Error in template:", data);
|
|
124
|
-
// Send to error tracking service (Sentry, etc.)
|
|
125
|
-
// Sentry.captureException(new Error(data.message));
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
// Optional: Custom labels
|
|
130
|
-
editText: "Edit Text",
|
|
131
|
-
textPlaceholder: "Enter text...",
|
|
132
|
-
updateText: "Update",
|
|
133
|
-
promptPlaceholder: "Ask AI for changes...",
|
|
134
|
-
editImage: "Change Image",
|
|
135
|
-
imageUploadTitle: "Select Image",
|
|
136
|
-
imageUploadHint: "Click or drag",
|
|
137
|
-
updateImage: "Update Image",
|
|
138
|
-
badgeText: "Built with Promake",
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
// Optional: Custom theme colors
|
|
142
|
-
backgroundColor: "#ffffff",
|
|
143
|
-
textColor: "#111827",
|
|
144
|
-
buttonColor: "#4417db",
|
|
145
|
-
buttonTextColor: "#ffffff",
|
|
146
|
-
inputBackgroundColor: "#f9fafb",
|
|
147
|
-
inputTextColor: "#111827",
|
|
148
|
-
inputBorderColor: "#d1d5db",
|
|
149
|
-
badgeGradientStart: "#411E93",
|
|
150
|
-
badgeGradientEnd: "#E87C85",
|
|
151
|
-
badgeTextColor: "#ffffff",
|
|
152
|
-
}
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
return (
|
|
156
|
-
<div>
|
|
157
|
-
<button onClick={() => toggleInspector()}>
|
|
158
|
-
{isInspecting ? "Stop Inspector" : "Start Inspector"}
|
|
159
|
-
</button>
|
|
160
|
-
|
|
161
|
-
{/* Optional: Manual content input toggle */}
|
|
162
|
-
{isInspecting && (
|
|
163
|
-
<button onClick={() => showContentInput(true)}>
|
|
164
|
-
Show Content Input
|
|
165
|
-
</button>
|
|
166
|
-
)}
|
|
167
|
-
|
|
168
|
-
<iframe ref={iframeRef} src="http://localhost:5173" />
|
|
169
|
-
</div>
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
## API
|
|
175
|
-
|
|
176
|
-
### `useInspector(iframeRef, callbacks?, labels?, theme?)`
|
|
177
|
-
|
|
178
|
-
#### Parameters
|
|
179
|
-
|
|
180
|
-
- **iframeRef**: `RefObject<HTMLIFrameElement>` - Reference to the iframe element
|
|
181
|
-
- **callbacks**: `InspectorCallbacks` (optional)
|
|
182
|
-
- `onElementSelected`: Called when an element is selected (receives `isTextNode` and `isImageNode` properties)
|
|
183
|
-
- `onPromptSubmitted`: Called when AI prompt is submitted
|
|
184
|
-
- `onTextUpdated`: Called when text content is updated
|
|
185
|
-
- `onImageUpdated`: Called when image is uploaded
|
|
186
|
-
- `onInspectorClosed`: Called when inspector mode is closed (after submitting prompt/text/image)
|
|
187
|
-
- `onUrlChange`: Called when URL changes in iframe
|
|
188
|
-
- `onError`: Called when an error occurs in iframe
|
|
189
|
-
- **labels**: `InspectorLabels` (optional)
|
|
190
|
-
- `editText`: Label for text edit section
|
|
191
|
-
- `textPlaceholder`: Placeholder for text input
|
|
192
|
-
- `updateText`: Label for update button
|
|
193
|
-
- `promptPlaceholder`: Placeholder for prompt input
|
|
194
|
-
- `editImage`: Label for image edit section
|
|
195
|
-
- `imageUploadTitle`: Upload box title (e.g., "Select Image")
|
|
196
|
-
- `imageUploadHint`: Upload box hint (e.g., "Click or drag")
|
|
197
|
-
- `updateImage`: Label for image update button
|
|
198
|
-
- `badgeText`: Badge text (default: "Built with Promake")
|
|
199
|
-
- **theme**: `InspectorTheme` (optional)
|
|
200
|
-
- `backgroundColor`: Box background color (default: `#ffffff`)
|
|
201
|
-
- `textColor`: Text color (default: `#111827`)
|
|
202
|
-
- `buttonColor`: Button background color (default: `#4417db`)
|
|
203
|
-
- `buttonTextColor`: Button text color (default: `#ffffff`)
|
|
204
|
-
- `inputBackgroundColor`: Input background color (default: `#f9fafb`)
|
|
205
|
-
- `inputTextColor`: Input text color (default: `#111827`)
|
|
206
|
-
- `inputBorderColor`: Input border color (default: `#d1d5db`)
|
|
207
|
-
- `badgeGradientStart`: Badge gradient start color (default: `#411E93`)
|
|
208
|
-
- `badgeGradientEnd`: Badge gradient end color (default: `#E87C85`)
|
|
209
|
-
- `badgeTextColor`: Badge text color (default: `#ffffff`)
|
|
210
|
-
|
|
211
|
-
#### Returns
|
|
212
|
-
|
|
213
|
-
- **isInspecting**: `boolean` - Current inspection state
|
|
214
|
-
- **toggleInspector**: `(active?: boolean) => void` - Toggle inspection mode
|
|
215
|
-
- **startInspecting**: `() => void` - Start inspecting
|
|
216
|
-
- **stopInspecting**: `() => void` - Stop inspecting
|
|
217
|
-
- **showContentInput**: `(show: boolean, updateImmediately?: boolean) => void` - Show or hide text content input dynamically. If `updateImmediately` is true, DOM is updated immediately on submit (useful for slow backend responses)
|
|
218
|
-
- **showImageInput**: `(show: boolean, updateImmediately?: boolean) => void` - Show or hide image input dynamically. If `updateImmediately` is true, DOM is updated immediately on submit (useful for slow backend responses)
|
|
219
|
-
- **setBadgeVisible**: `(visible: boolean) => void` - Show or hide "Built by Promake" badge in bottom-right corner
|
|
220
|
-
- **highlightElement**: `(identifier: string | ElementIdentifier, options?: HighlightOptions) => void` - Highlight an element in the iframe by ID or selector
|
|
221
|
-
- **getElementByInspectorId**: `(inspectorId: string) => void` - Request element info by unique inspector ID
|
|
222
|
-
|
|
223
|
-
## Types
|
|
224
|
-
|
|
225
|
-
### `SelectedElementData`
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
interface SelectedElementData {
|
|
229
|
-
tagName: string;
|
|
230
|
-
className: string;
|
|
231
|
-
id: string;
|
|
232
|
-
component: ComponentInfo | null;
|
|
233
|
-
position: ElementPosition;
|
|
234
|
-
isTextNode?: boolean; // Whether the element is a text node
|
|
235
|
-
textContent?: string; // Text content of the element (if text node)
|
|
236
|
-
isImageNode?: boolean; // Whether the element is an image node
|
|
237
|
-
imageUrl?: string; // Image URL (if image node)
|
|
238
|
-
inspectorId?: string; // Unique inspector ID for element tracking
|
|
239
|
-
selector?: string; // CSS selector for element identification
|
|
240
|
-
}
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
### `ElementIdentifier`
|
|
244
|
-
|
|
245
|
-
```typescript
|
|
246
|
-
interface ElementIdentifier {
|
|
247
|
-
inspectorId: string; // Unique ID (primary)
|
|
248
|
-
selector: string; // CSS selector (fallback)
|
|
249
|
-
position?: {
|
|
250
|
-
// Position (for disambiguation)
|
|
251
|
-
top: number;
|
|
252
|
-
left: number;
|
|
253
|
-
};
|
|
254
|
-
component?: {
|
|
255
|
-
// Component info (metadata)
|
|
256
|
-
name: string;
|
|
257
|
-
fileName: string;
|
|
258
|
-
lineNumber?: number;
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### `HighlightOptions`
|
|
264
|
-
|
|
265
|
-
```typescript
|
|
266
|
-
interface HighlightOptions {
|
|
267
|
-
duration?: number; // Highlight duration in ms (default: 3000)
|
|
268
|
-
scrollIntoView?: boolean; // Scroll to element (default: true)
|
|
269
|
-
color?: string; // Highlight color (default: '#4417db')
|
|
270
|
-
animation?: "pulse" | "fade" | "none"; // Animation type (default: 'pulse')
|
|
271
|
-
}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
## Element Identification & Persistence
|
|
275
|
-
|
|
276
|
-
Inspector uses a **structural signature-based ID system** to ensure the same element gets the same ID across page reloads, making it perfect for features like chat history highlighting.
|
|
277
|
-
|
|
278
|
-
### How Persistent IDs Work
|
|
279
|
-
|
|
280
|
-
#### ID Format
|
|
281
|
-
|
|
282
|
-
```
|
|
283
|
-
pi-{hash}
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
Example: `pi-1f2a3b4c`
|
|
287
|
-
|
|
288
|
-
#### ID Generation
|
|
289
|
-
|
|
290
|
-
IDs are generated based on element's structural properties:
|
|
291
|
-
|
|
292
|
-
1. **XPath** - DOM tree position (primary identifier)
|
|
293
|
-
2. **Static Identifiers** - `id`, `data-id`, `data-testid`, `data-component`, `data-cy`
|
|
294
|
-
3. **Semantic Properties** - `tag`, `role`, `type`, `name`, `href`, `src`
|
|
295
|
-
4. **Structural Context** - sibling index, parent tag (if no static ID)
|
|
296
|
-
|
|
297
|
-
**Excluded for Stability:**
|
|
298
|
-
|
|
299
|
-
- ❌ Class names (frequently change)
|
|
300
|
-
- ❌ Text content (dynamic)
|
|
301
|
-
- ❌ Style attributes (dynamic)
|
|
302
|
-
|
|
303
|
-
#### Consistency Guarantees
|
|
304
|
-
|
|
305
|
-
✅ **Same element → Same ID** (across page reloads)
|
|
306
|
-
✅ **Class changes → ID unchanged**
|
|
307
|
-
✅ **Text changes → ID unchanged**
|
|
308
|
-
✅ **Style changes → ID unchanged**
|
|
309
|
-
❌ **DOM position changes → Different ID** (new structure = new ID)
|
|
310
|
-
|
|
311
|
-
#### Best Practices for Maximum Consistency
|
|
312
|
-
|
|
313
|
-
To ensure the most reliable element identification:
|
|
314
|
-
|
|
315
|
-
```html
|
|
316
|
-
<!-- ✅ Best: Use data-id for elements you want to reliably track -->
|
|
317
|
-
<div data-id="hero-section">...</div>
|
|
318
|
-
<button data-id="cta-button">...</button>
|
|
319
|
-
|
|
320
|
-
<!-- ✅ Good: Use element.id -->
|
|
321
|
-
<div id="main-content">...</div>
|
|
322
|
-
|
|
323
|
-
<!-- ✅ Good: Use data-testid -->
|
|
324
|
-
<button data-testid="submit-form">...</button>
|
|
325
|
-
|
|
326
|
-
<!-- ⚠️ Okay: Relies on DOM position (changes if DOM structure changes) -->
|
|
327
|
-
<div class="card">...</div>
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
#### Fallback System
|
|
331
|
-
|
|
332
|
-
If an element's ID changes (e.g., DOM restructure), the system uses smart fallbacks:
|
|
333
|
-
|
|
334
|
-
1. **Primary**: Try to find by `inspectorId`
|
|
335
|
-
2. **Fallback 1**: Use CSS selector
|
|
336
|
-
3. **Fallback 2**: Use position matching (if multiple matches)
|
|
337
|
-
|
|
338
|
-
```typescript
|
|
339
|
-
// Full identifier with fallback support
|
|
340
|
-
highlightElement({
|
|
341
|
-
inspectorId: "pi-1f2a3b4c", // Primary
|
|
342
|
-
selector: "button.cta-primary", // Fallback 1
|
|
343
|
-
position: { top: 500, left: 100 }, // Fallback 2
|
|
344
|
-
});
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
### `ComponentInfo`
|
|
348
|
-
|
|
349
|
-
```typescript
|
|
350
|
-
interface ComponentInfo {
|
|
351
|
-
componentName: string;
|
|
352
|
-
fileName: string;
|
|
353
|
-
lineNumber: number;
|
|
354
|
-
columnNumber: number;
|
|
355
|
-
}
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
### `PromptSubmittedData`
|
|
359
|
-
|
|
360
|
-
```typescript
|
|
361
|
-
interface PromptSubmittedData {
|
|
362
|
-
prompt: string;
|
|
363
|
-
element: SelectedElementData;
|
|
364
|
-
}
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
### `TextUpdatedData`
|
|
368
|
-
|
|
369
|
-
```typescript
|
|
370
|
-
interface TextUpdatedData {
|
|
371
|
-
text: string;
|
|
372
|
-
originalText: string;
|
|
373
|
-
element: SelectedElementData;
|
|
374
|
-
}
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
### `ImageUpdatedData`
|
|
378
|
-
|
|
379
|
-
```typescript
|
|
380
|
-
interface ImageUpdatedData {
|
|
381
|
-
imageData: string; // Base64 encoded image data
|
|
382
|
-
imageFile: {
|
|
383
|
-
name: string;
|
|
384
|
-
size: number;
|
|
385
|
-
type: string;
|
|
386
|
-
};
|
|
387
|
-
originalImageUrl: string;
|
|
388
|
-
element: SelectedElementData;
|
|
389
|
-
}
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
### `ErrorData`
|
|
393
|
-
|
|
394
|
-
```typescript
|
|
395
|
-
interface ErrorData {
|
|
396
|
-
type: "javascript" | "promise" | "console";
|
|
397
|
-
message: string;
|
|
398
|
-
stack?: string;
|
|
399
|
-
fileName?: string;
|
|
400
|
-
lineNumber?: number;
|
|
401
|
-
columnNumber?: number;
|
|
402
|
-
timestamp: number;
|
|
403
|
-
}
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
### `InspectorLabels`
|
|
407
|
-
|
|
408
|
-
```typescript
|
|
409
|
-
interface InspectorLabels {
|
|
410
|
-
editText?: string; // Label for text edit section
|
|
411
|
-
textPlaceholder?: string; // Placeholder for text input
|
|
412
|
-
updateText?: string; // Label for text update button
|
|
413
|
-
promptPlaceholder?: string; // Placeholder for prompt input
|
|
414
|
-
editImage?: string; // Label for image edit section
|
|
415
|
-
imageUploadTitle?: string; // Upload box title (e.g., "Select Image")
|
|
416
|
-
imageUploadHint?: string; // Upload box hint (e.g., "Click or drag")
|
|
417
|
-
updateImage?: string; // Label for image update button
|
|
418
|
-
badgeText?: string; // Badge text (default: "Built with Promake")
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
### `InspectorTheme`
|
|
423
|
-
|
|
424
|
-
```typescript
|
|
425
|
-
interface InspectorTheme {
|
|
426
|
-
backgroundColor?: string; // Box background color
|
|
427
|
-
textColor?: string; // Text color
|
|
428
|
-
buttonColor?: string; // Button background color
|
|
429
|
-
buttonTextColor?: string; // Button text color
|
|
430
|
-
inputBackgroundColor?: string; // Input background color
|
|
431
|
-
inputTextColor?: string; // Input text color
|
|
432
|
-
inputBorderColor?: string; // Input border color
|
|
433
|
-
badgeGradientStart?: string; // Badge gradient start color
|
|
434
|
-
badgeGradientEnd?: string; // Badge gradient end color
|
|
435
|
-
badgeTextColor?: string; // Badge text color
|
|
436
|
-
}
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
## Features in Detail
|
|
440
|
-
|
|
441
|
-
### Element Selection
|
|
442
|
-
|
|
443
|
-
Click any element to select it. The inspector will:
|
|
444
|
-
|
|
445
|
-
- Show a blue highlight overlay
|
|
446
|
-
- Display a control box below/above the element (always shows prompt input)
|
|
447
|
-
- Pause scrolling
|
|
448
|
-
- Extract React component information
|
|
449
|
-
- Detect if element is a text-only node (`isTextNode`)
|
|
450
|
-
- Detect if element is an image node (`isImageNode`)
|
|
451
|
-
|
|
452
|
-
### Dynamic Content Input
|
|
453
|
-
|
|
454
|
-
The inspector now uses a three-stage approach:
|
|
455
|
-
|
|
456
|
-
1. **Prompt Input (Always Visible)**: Every element shows a prompt input for AI instructions
|
|
457
|
-
2. **Text Content Input (On-Demand)**: Text editing appears only when you call `showContentInput(true)`
|
|
458
|
-
3. **Image Upload (On-Demand)**: Image upload appears only when you call `showImageInput(true)`
|
|
459
|
-
|
|
460
|
-
This allows you to:
|
|
461
|
-
|
|
462
|
-
- Run AI computations after selection
|
|
463
|
-
- Decide programmatically when to show text editing or image upload
|
|
464
|
-
- Keep the UI clean and focused
|
|
465
|
-
|
|
466
|
-
```typescript
|
|
467
|
-
onElementSelected: (data) => {
|
|
468
|
-
if (data.isTextNode) {
|
|
469
|
-
// Show content input above prompt input
|
|
470
|
-
// Pass true as second parameter for immediate DOM update
|
|
471
|
-
showContentInput(true, true);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
if (data.isImageNode) {
|
|
475
|
-
// Show image upload for images
|
|
476
|
-
// Pass true as second parameter for immediate DOM update
|
|
477
|
-
showImageInput(true, true);
|
|
478
|
-
}
|
|
479
|
-
};
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
### Image Upload
|
|
483
|
-
|
|
484
|
-
For image elements:
|
|
485
|
-
|
|
486
|
-
- **Custom Upload Box**: Dashed border box with drag & drop support
|
|
487
|
-
- **Click to Upload**: Click the box to select image from file explorer
|
|
488
|
-
- **Drag & Drop**: Drag image files directly onto the upload box
|
|
489
|
-
- **Preview**: Selected image appears in the same box (max 100px height)
|
|
490
|
-
- **Base64 Encoding**: Image is automatically converted to base64
|
|
491
|
-
- **File Metadata**: File name, size, and type are included
|
|
492
|
-
|
|
493
|
-
The image data is sent to parent app with `onImageUpdated` callback for upload to your server.
|
|
494
|
-
|
|
495
|
-
### Immediate DOM Updates
|
|
496
|
-
|
|
497
|
-
For production environments where backend processing takes time, you can enable immediate DOM updates:
|
|
498
|
-
|
|
499
|
-
```typescript
|
|
500
|
-
// Text updates - DOM is updated immediately, no wait for backend
|
|
501
|
-
showContentInput(true, true); // updateImmediately: true
|
|
502
|
-
|
|
503
|
-
// Image updates - Image appears immediately, no wait for backend
|
|
504
|
-
showImageInput(true, true); // updateImmediately: true
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
**How it works:**
|
|
508
|
-
|
|
509
|
-
1. **Text Updates**: When user submits new text, the DOM text content is updated immediately
|
|
510
|
-
2. **Image Updates**: When user selects an image, the `<img>` src (or background-image) is updated immediately with base64 data
|
|
511
|
-
3. **Backend Sync**: The `onTextUpdated` or `onImageUpdated` callback is still fired for backend sync
|
|
512
|
-
4. **User Experience**: User sees instant feedback, while your backend processes in the background
|
|
513
|
-
|
|
514
|
-
This is perfect for:
|
|
515
|
-
|
|
516
|
-
- Slow API responses
|
|
517
|
-
- AI processing that takes seconds
|
|
518
|
-
- Upload-heavy operations
|
|
519
|
-
- Better perceived performance
|
|
520
|
-
|
|
521
|
-
### Promake Badge
|
|
522
|
-
|
|
523
|
-
Show a beautiful "Built with Promake" badge in the bottom-right corner:
|
|
524
|
-
|
|
525
|
-
```typescript
|
|
526
|
-
// Show badge with default text ("Built with Promake")
|
|
527
|
-
setBadgeVisible(true);
|
|
528
|
-
|
|
529
|
-
// Hide badge
|
|
530
|
-
setBadgeVisible(false);
|
|
531
|
-
|
|
532
|
-
// Customize badge text via labels
|
|
533
|
-
const { setBadgeVisible } = useInspector(iframeRef, callbacks, {
|
|
534
|
-
badgeText: "Made with ❤️ by MyCompany",
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
// Customize badge colors via theme
|
|
538
|
-
const { setBadgeVisible } = useInspector(
|
|
539
|
-
iframeRef,
|
|
540
|
-
callbacks,
|
|
541
|
-
undefined, // no custom labels
|
|
542
|
-
{
|
|
543
|
-
badgeGradientStart: "#10b981", // Green
|
|
544
|
-
badgeGradientEnd: "#3b82f6", // Blue
|
|
545
|
-
badgeTextColor: "#ffffff", // White text
|
|
546
|
-
}
|
|
547
|
-
);
|
|
548
|
-
|
|
549
|
-
// Dark badge with light text
|
|
550
|
-
const { setBadgeVisible } = useInspector(iframeRef, callbacks, undefined, {
|
|
551
|
-
badgeGradientStart: "#1e293b", // Dark slate
|
|
552
|
-
badgeGradientEnd: "#334155", // Slate
|
|
553
|
-
badgeTextColor: "#f8fafc", // Light text
|
|
554
|
-
});
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
**Features:**
|
|
558
|
-
|
|
559
|
-
- 🎨 Beautiful gradient design (purple to violet by default)
|
|
560
|
-
- ⚡ Smooth fade-in/fade-out animations
|
|
561
|
-
- 🖱️ Hover effects with elevation
|
|
562
|
-
- 🔗 Clickable - opens promake.ai in new tab
|
|
563
|
-
- 📍 Fixed position in bottom-right
|
|
564
|
-
- 🚫 Ignored by inspector (has `data-inspector-ignore`)
|
|
565
|
-
- 📝 Customizable text via labels
|
|
566
|
-
- 🎨 Customizable gradient colors via theme
|
|
567
|
-
- 🔤 Customizable text color via theme
|
|
568
|
-
- ❌ Close button appears on hover - users can dismiss the badge
|
|
569
|
-
|
|
570
|
-
**Default**: Badge is hidden by default. Enable it when needed using `setBadgeVisible(true)`. Default text is "Built with Promake". Default gradient colors are deep purple (#411E93) to coral pink (#E87C85). Default text color is white (#ffffff).
|
|
571
|
-
|
|
572
|
-
**Auto-Show**: Badge automatically appears when the app is running in `preview.promake.ai` environment **without** a parent iframe. This ensures the badge is visible in preview deployments where parent control is not available.
|
|
573
|
-
|
|
574
|
-
**Close Button**: When users hover over the badge, a small close button (×) appears in the top-right corner. Clicking it hides the badge with a smooth animation.
|
|
575
|
-
|
|
576
|
-
**Color Examples:**
|
|
577
|
-
|
|
578
|
-
**Gradient Backgrounds:**
|
|
579
|
-
|
|
580
|
-
- **Deep Purple to Coral Pink** (default): `#411E93` → `#E87C85` (white text)
|
|
581
|
-
- **Blue to Cyan**: `#3b82f6` → `#06b6d4` (white text)
|
|
582
|
-
- **Green to Emerald**: `#10b981` → `#059669` (white text)
|
|
583
|
-
- **Pink to Rose**: `#ec4899` → `#f43f5e` (white text)
|
|
584
|
-
- **Orange to Red**: `#f97316` → `#ef4444` (white text)
|
|
585
|
-
- **Dark Slate**: `#1e293b` → `#334155` (light text `#f8fafc`)
|
|
586
|
-
|
|
587
|
-
**Text Colors:**
|
|
588
|
-
|
|
589
|
-
- **White** (default): `#ffffff`
|
|
590
|
-
- **Light**: `#f8fafc`, `#f1f5f9`
|
|
591
|
-
- **Dark**: `#111827`, `#1e293b`
|
|
592
|
-
- **Brand Colors**: Match your brand palette
|
|
593
|
-
|
|
594
|
-
**Auto-Show Behavior:**
|
|
595
|
-
|
|
596
|
-
The badge automatically appears in these conditions:
|
|
597
|
-
|
|
598
|
-
1. The app is **not** inside an iframe (`window.parent === window`)
|
|
599
|
-
2. The URL contains `preview.promake.ai`
|
|
600
|
-
|
|
601
|
-
This ensures the badge is visible in Promake preview deployments where parent window control is unavailable. Users can still close it using the close button on hover.
|
|
602
|
-
|
|
603
|
-
**Use Cases:**
|
|
604
|
-
|
|
605
|
-
- Show attribution to Promake
|
|
606
|
-
- Free tier watermark for preview deployments
|
|
607
|
-
- Branding for templates built with Promake
|
|
608
|
-
- Custom branding with your own text and colors
|
|
609
|
-
- Automatic display in preview environments
|
|
610
|
-
|
|
611
|
-
### AI Prompts
|
|
612
|
-
|
|
613
|
-
For any element:
|
|
614
|
-
|
|
615
|
-
- Prompt input is always visible
|
|
616
|
-
- Enter a prompt describing desired changes
|
|
617
|
-
- Click the send button (↑)
|
|
618
|
-
- Prompt + element data sent to parent app
|
|
619
|
-
|
|
620
|
-
### Ignoring Elements
|
|
621
|
-
|
|
622
|
-
Mark elements as non-inspectable using the `data-inspector-ignore` attribute:
|
|
623
|
-
|
|
624
|
-
```jsx
|
|
625
|
-
<button data-inspector-ignore onClick={toggleInspect}>
|
|
626
|
-
Inspector Controls
|
|
627
|
-
</button>
|
|
628
|
-
|
|
629
|
-
<div data-inspector-ignore>
|
|
630
|
-
{/* All children will be ignored too */}
|
|
631
|
-
<button>Button 1</button>
|
|
632
|
-
<button>Button 2</button>
|
|
633
|
-
</div>
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
This is perfect for:
|
|
637
|
-
|
|
638
|
-
- Inspector control buttons
|
|
639
|
-
- Floating toolbars
|
|
640
|
-
- Fixed navigation
|
|
641
|
-
- Any UI that shouldn't be inspectable
|
|
642
|
-
|
|
643
|
-
### Component Detection
|
|
644
|
-
|
|
645
|
-
Automatically extracts:
|
|
646
|
-
|
|
647
|
-
- Component name
|
|
648
|
-
- Source file path
|
|
649
|
-
- Line number
|
|
650
|
-
- Column number
|
|
651
|
-
|
|
652
|
-
**Note**: Works only in development mode with React DevTools enabled.
|
|
653
|
-
|
|
654
|
-
### Error Tracking
|
|
655
|
-
|
|
656
|
-
Automatically captures and reports:
|
|
657
|
-
|
|
658
|
-
- **JavaScript Errors**: Runtime errors with stack traces
|
|
659
|
-
- **Promise Rejections**: Unhandled promise rejections
|
|
660
|
-
- **Console Errors**: All `console.error()` calls
|
|
661
|
-
|
|
662
|
-
All errors are sent to the parent app with detailed information including:
|
|
663
|
-
|
|
664
|
-
- Error type and message
|
|
665
|
-
- Stack trace
|
|
666
|
-
- File name and line number
|
|
667
|
-
- Timestamp
|
|
668
|
-
|
|
669
|
-
Perfect for integrating with error tracking services like Sentry, LogRocket, or custom logging solutions.
|
|
670
|
-
|
|
671
|
-
## Examples
|
|
672
|
-
|
|
673
|
-
### Element Highlighting from Chat History
|
|
674
|
-
|
|
675
|
-
```typescript
|
|
676
|
-
const { highlightElement, getElementByInspectorId } = useInspector(iframeRef, {
|
|
677
|
-
onElementSelected: (data) => {
|
|
678
|
-
// Store inspectorId in your chat message
|
|
679
|
-
const message = {
|
|
680
|
-
text: `Selected ${data.tagName} element`,
|
|
681
|
-
inspectorId: data.inspectorId,
|
|
682
|
-
selector: data.selector,
|
|
683
|
-
position: data.position,
|
|
684
|
-
};
|
|
685
|
-
saveToChatHistory(message);
|
|
686
|
-
},
|
|
687
|
-
onElementInfoReceived: (data) => {
|
|
688
|
-
if (data.found) {
|
|
689
|
-
console.log("Element found:", data.element);
|
|
690
|
-
} else {
|
|
691
|
-
console.log("Element not found:", data.error);
|
|
692
|
-
}
|
|
693
|
-
},
|
|
694
|
-
});
|
|
695
|
-
|
|
696
|
-
// Later: Click on a chat message to re-highlight the element
|
|
697
|
-
function handleChatMessageClick(message) {
|
|
698
|
-
// Highlight with full identifier (with fallback support)
|
|
699
|
-
highlightElement(
|
|
700
|
-
{
|
|
701
|
-
inspectorId: message.inspectorId,
|
|
702
|
-
selector: message.selector,
|
|
703
|
-
position: message.position,
|
|
704
|
-
},
|
|
705
|
-
{
|
|
706
|
-
duration: 4000,
|
|
707
|
-
color: "#10b981",
|
|
708
|
-
animation: "pulse",
|
|
709
|
-
}
|
|
710
|
-
);
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// Or simply by ID
|
|
714
|
-
function quickHighlight(inspectorId) {
|
|
715
|
-
highlightElement(inspectorId);
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// Request element info
|
|
719
|
-
function checkElementStatus(inspectorId) {
|
|
720
|
-
getElementByInspectorId(inspectorId);
|
|
721
|
-
}
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
### Dynamic Content Input Based on AI Response
|
|
725
|
-
|
|
726
|
-
```typescript
|
|
727
|
-
const { toggleInspector, showContentInput } = useInspector(iframeRef, {
|
|
728
|
-
onElementSelected: async (data) => {
|
|
729
|
-
// Run AI analysis first
|
|
730
|
-
const analysis = await analyzeElement(data);
|
|
731
|
-
|
|
732
|
-
// Show content input only if AI suggests text editing
|
|
733
|
-
if (analysis.shouldShowTextEditor && data.isTextNode) {
|
|
734
|
-
showContentInput(true);
|
|
735
|
-
}
|
|
736
|
-
},
|
|
737
|
-
onPromptSubmitted: async (data) => {
|
|
738
|
-
// Process AI prompt
|
|
739
|
-
const result = await processAIPrompt(data.prompt, data.element);
|
|
740
|
-
|
|
741
|
-
// Optionally show content input after AI processing
|
|
742
|
-
if (result.needsTextInput) {
|
|
743
|
-
showContentInput(true);
|
|
744
|
-
}
|
|
745
|
-
},
|
|
746
|
-
});
|
|
747
|
-
```
|
|
748
|
-
|
|
749
|
-
### Dark Theme
|
|
750
|
-
|
|
751
|
-
```typescript
|
|
752
|
-
const { toggleInspector } = useInspector(iframeRef, callbacks, labels, {
|
|
753
|
-
backgroundColor: "#1a1a1a",
|
|
754
|
-
textColor: "#ffffff",
|
|
755
|
-
buttonColor: "#00ff00",
|
|
756
|
-
buttonTextColor: "#000000",
|
|
757
|
-
inputBackgroundColor: "#2a2a2a",
|
|
758
|
-
inputTextColor: "#ffffff",
|
|
759
|
-
inputBorderColor: "#444444",
|
|
760
|
-
});
|
|
761
|
-
```
|
|
762
|
-
|
|
763
|
-
### Multi-language Support
|
|
764
|
-
|
|
765
|
-
```typescript
|
|
766
|
-
const { toggleInspector } = useInspector(iframeRef, callbacks, {
|
|
767
|
-
editText: "Metni Düzenle",
|
|
768
|
-
textPlaceholder: "Metin girin...",
|
|
769
|
-
updateText: "Güncelle",
|
|
770
|
-
promptPlaceholder: "Promake'e değişiklik sor...",
|
|
771
|
-
});
|
|
772
|
-
```
|
|
773
|
-
|
|
774
|
-
### Prevent Inspector Buttons from Being Selected
|
|
775
|
-
|
|
776
|
-
```jsx
|
|
777
|
-
function App() {
|
|
778
|
-
return (
|
|
779
|
-
<div>
|
|
780
|
-
{/* These buttons won't be inspectable */}
|
|
781
|
-
<div className="inspector-controls" data-inspector-ignore>
|
|
782
|
-
<button onClick={toggleInspect}>Toggle Inspector</button>
|
|
783
|
-
<button onClick={() => showContentInput(true)}>
|
|
784
|
-
Show Content Input
|
|
785
|
-
</button>
|
|
786
|
-
</div>
|
|
787
|
-
|
|
788
|
-
<iframe ref={iframeRef} src="http://localhost:5173" />
|
|
789
|
-
</div>
|
|
790
|
-
);
|
|
791
|
-
}
|
|
792
|
-
```
|
|
793
|
-
|
|
794
|
-
### Open File in Editor
|
|
795
|
-
|
|
796
|
-
```typescript
|
|
797
|
-
onElementSelected: async (data) => {
|
|
798
|
-
if (data.component) {
|
|
799
|
-
await fetch("/api/open-in-editor", {
|
|
800
|
-
method: "POST",
|
|
801
|
-
body: JSON.stringify({
|
|
802
|
-
fileName: data.component.fileName,
|
|
803
|
-
lineNumber: data.component.lineNumber,
|
|
804
|
-
}),
|
|
805
|
-
});
|
|
806
|
-
}
|
|
807
|
-
};
|
|
808
|
-
```
|
|
809
|
-
|
|
810
|
-
### Error Tracking with Sentry
|
|
811
|
-
|
|
812
|
-
```typescript
|
|
813
|
-
import * as Sentry from "@sentry/react";
|
|
814
|
-
|
|
815
|
-
const { toggleInspector } = useInspector(iframeRef, {
|
|
816
|
-
onError: (data) => {
|
|
817
|
-
// Send to Sentry
|
|
818
|
-
Sentry.captureException(new Error(data.message), {
|
|
819
|
-
extra: {
|
|
820
|
-
type: data.type,
|
|
821
|
-
stack: data.stack,
|
|
822
|
-
fileName: data.fileName,
|
|
823
|
-
lineNumber: data.lineNumber,
|
|
824
|
-
timestamp: data.timestamp,
|
|
825
|
-
},
|
|
826
|
-
});
|
|
827
|
-
},
|
|
828
|
-
});
|
|
829
|
-
```
|
|
830
|
-
|
|
831
|
-
## Browser Support
|
|
832
|
-
|
|
833
|
-
- Chrome/Edge: ✅
|
|
834
|
-
- Firefox: ✅
|
|
835
|
-
- Safari: ✅
|
|
836
|
-
|
|
837
|
-
## Requirements
|
|
838
|
-
|
|
839
|
-
- Vite 5.0+
|
|
840
|
-
- React 18.0+
|
|
841
|
-
- TypeScript (recommended)
|
|
842
|
-
|
|
843
|
-
## CI/CD
|
|
844
|
-
|
|
845
|
-
This project includes GitHub Actions workflow:
|
|
846
|
-
|
|
847
|
-
### Build Workflow (`.github/workflows/build.yml`)
|
|
848
|
-
|
|
849
|
-
Automatically runs on every push and pull request:
|
|
850
|
-
|
|
851
|
-
- ✅ Uses Bun for fast installation and build
|
|
852
|
-
- ✅ Runs `bun install` and `bun run build`
|
|
853
|
-
- ✅ Checks for build artifacts
|
|
854
|
-
- ✅ Uploads build artifacts for review
|
|
855
|
-
|
|
856
|
-
## License
|
|
857
|
-
|
|
858
|
-
MIT
|
|
859
|
-
|
|
860
|
-
## Contributing
|
|
861
|
-
|
|
862
|
-
Issues and pull requests are welcome!
|
|
863
|
-
|
|
864
|
-
## Author
|
|
865
|
-
|
|
866
|
-
Promake
|