@promakeai/inspector 0.0.3 → 0.1.0
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/README.md +285 -80
- package/dist/hook.d.ts +38 -5
- package/dist/hook.d.ts.map +1 -1
- package/dist/hook.js +89 -14
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +575 -29
- package/dist/types.d.ts +26 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -11,6 +11,8 @@ Visual element inspector for React apps in iframe with AI prompt support. Perfec
|
|
|
11
11
|
- 🎯 **Element Selection** - Click to select any element on the page
|
|
12
12
|
- 🔍 **React Component Detection** - Automatically detects React components via Fiber
|
|
13
13
|
- 📝 **Dynamic Content Input** - Show/hide text editing on-demand with `showContentInput()`
|
|
14
|
+
- 🖼️ **Image Upload Support** - Custom drag & drop image uploader with preview
|
|
15
|
+
- ⚡ **Immediate DOM Updates** - Optional instant feedback while backend processes
|
|
14
16
|
- 🤖 **AI Prompt Support** - Always-visible prompt input for AI modifications
|
|
15
17
|
- 🎨 **Visual Feedback** - Highlight selected elements with overlay
|
|
16
18
|
- 🔒 **Pause Mode** - Lock selection and disable scroll while editing
|
|
@@ -20,6 +22,8 @@ Visual element inspector for React apps in iframe with AI prompt support. Perfec
|
|
|
20
22
|
- 🌍 **Customizable Labels** - Multi-language support
|
|
21
23
|
- 🚫 **Ignore Elements** - Mark elements as non-inspectable with `data-inspector-ignore`
|
|
22
24
|
- 🔍 **Text Node Detection** - Automatically detect if selected element is a text node
|
|
25
|
+
- 🖼️ **Image Node Detection** - Automatically detect if selected element is an image
|
|
26
|
+
- 🏷️ **Promake Badge** - Optional "Built by Promake" badge with smooth animations
|
|
23
27
|
- 📦 **TypeScript** - Full type safety
|
|
24
28
|
|
|
25
29
|
## Installation
|
|
@@ -55,64 +59,92 @@ import { useInspector } from "@promakeai/inspector/hook";
|
|
|
55
59
|
function App() {
|
|
56
60
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
57
61
|
|
|
58
|
-
const { isInspecting, toggleInspector, showContentInput } =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
62
|
+
const { isInspecting, toggleInspector, showContentInput, showImageInput } =
|
|
63
|
+
useInspector(
|
|
64
|
+
iframeRef,
|
|
65
|
+
{
|
|
66
|
+
onElementSelected: (data) => {
|
|
67
|
+
console.log("Element selected:", data);
|
|
68
|
+
console.log("Is text node:", data.isTextNode);
|
|
69
|
+
console.log("Is image node:", data.isImageNode);
|
|
70
|
+
|
|
71
|
+
// Access component info
|
|
72
|
+
console.log(data.component?.fileName);
|
|
73
|
+
console.log(data.component?.lineNumber);
|
|
74
|
+
|
|
75
|
+
// Show content input if it's a text node
|
|
76
|
+
if (data.isTextNode) {
|
|
77
|
+
showContentInput(true);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Show image input if it's an image node
|
|
81
|
+
if (data.isImageNode) {
|
|
82
|
+
showImageInput(true);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
onPromptSubmitted: (data) => {
|
|
86
|
+
console.log("AI Prompt:", data.prompt);
|
|
87
|
+
// Send to your AI service
|
|
88
|
+
fetch("/api/ai-edit", {
|
|
89
|
+
method: "POST",
|
|
90
|
+
body: JSON.stringify({
|
|
91
|
+
prompt: data.prompt,
|
|
92
|
+
element: data.element,
|
|
93
|
+
}),
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
onTextUpdated: (data) => {
|
|
97
|
+
console.log("Text updated:", data.text);
|
|
98
|
+
// Save to backend
|
|
99
|
+
},
|
|
100
|
+
onImageUpdated: (data) => {
|
|
101
|
+
console.log("Image updated:", data.imageFile.name);
|
|
102
|
+
console.log("Image data (base64):", data.imageData);
|
|
103
|
+
// Upload to server
|
|
104
|
+
fetch("/api/upload-image", {
|
|
105
|
+
method: "POST",
|
|
106
|
+
body: JSON.stringify(data),
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
onInspectorClosed: () => {
|
|
110
|
+
console.log("Inspector closed");
|
|
111
|
+
// Update UI state, re-enable elements, etc.
|
|
112
|
+
},
|
|
113
|
+
onUrlChange: (data) => {
|
|
114
|
+
console.log("URL changed:", data.pathname);
|
|
115
|
+
},
|
|
116
|
+
onError: (data) => {
|
|
117
|
+
console.error("Error in template:", data);
|
|
118
|
+
// Send to error tracking service (Sentry, etc.)
|
|
119
|
+
// Sentry.captureException(new Error(data.message));
|
|
120
|
+
},
|
|
73
121
|
},
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
122
|
+
{
|
|
123
|
+
// Optional: Custom labels
|
|
124
|
+
editText: "Edit Text",
|
|
125
|
+
textPlaceholder: "Enter text...",
|
|
126
|
+
updateText: "Update",
|
|
127
|
+
promptPlaceholder: "Ask AI for changes...",
|
|
128
|
+
editImage: "Change Image",
|
|
129
|
+
imageUploadTitle: "Select Image",
|
|
130
|
+
imageUploadHint: "Click or drag",
|
|
131
|
+
updateImage: "Update Image",
|
|
132
|
+
badgeText: "Built with Promake",
|
|
84
133
|
},
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// Optional: Custom labels
|
|
100
|
-
editText: "Edit Text",
|
|
101
|
-
textPlaceholder: "Enter text...",
|
|
102
|
-
updateText: "Update",
|
|
103
|
-
promptPlaceholder: "Ask AI for changes...",
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
// Optional: Custom theme colors
|
|
107
|
-
backgroundColor: "#ffffff",
|
|
108
|
-
textColor: "#111827",
|
|
109
|
-
buttonColor: "#4417db",
|
|
110
|
-
buttonTextColor: "#ffffff",
|
|
111
|
-
inputBackgroundColor: "#f9fafb",
|
|
112
|
-
inputTextColor: "#111827",
|
|
113
|
-
inputBorderColor: "#d1d5db",
|
|
114
|
-
}
|
|
115
|
-
);
|
|
134
|
+
{
|
|
135
|
+
// Optional: Custom theme colors
|
|
136
|
+
backgroundColor: "#ffffff",
|
|
137
|
+
textColor: "#111827",
|
|
138
|
+
buttonColor: "#4417db",
|
|
139
|
+
buttonTextColor: "#ffffff",
|
|
140
|
+
inputBackgroundColor: "#f9fafb",
|
|
141
|
+
inputTextColor: "#111827",
|
|
142
|
+
inputBorderColor: "#d1d5db",
|
|
143
|
+
badgeGradientStart: "#411E93",
|
|
144
|
+
badgeGradientEnd: "#E87C85",
|
|
145
|
+
badgeTextColor: "#ffffff",
|
|
146
|
+
}
|
|
147
|
+
);
|
|
116
148
|
|
|
117
149
|
return (
|
|
118
150
|
<div>
|
|
@@ -141,9 +173,11 @@ function App() {
|
|
|
141
173
|
|
|
142
174
|
- **iframeRef**: `RefObject<HTMLIFrameElement>` - Reference to the iframe element
|
|
143
175
|
- **callbacks**: `InspectorCallbacks` (optional)
|
|
144
|
-
- `onElementSelected`: Called when an element is selected (receives `isTextNode`
|
|
176
|
+
- `onElementSelected`: Called when an element is selected (receives `isTextNode` and `isImageNode` properties)
|
|
145
177
|
- `onPromptSubmitted`: Called when AI prompt is submitted
|
|
146
178
|
- `onTextUpdated`: Called when text content is updated
|
|
179
|
+
- `onImageUpdated`: Called when image is uploaded
|
|
180
|
+
- `onInspectorClosed`: Called when inspector mode is closed (after submitting prompt/text/image)
|
|
147
181
|
- `onUrlChange`: Called when URL changes in iframe
|
|
148
182
|
- `onError`: Called when an error occurs in iframe
|
|
149
183
|
- **labels**: `InspectorLabels` (optional)
|
|
@@ -151,6 +185,11 @@ function App() {
|
|
|
151
185
|
- `textPlaceholder`: Placeholder for text input
|
|
152
186
|
- `updateText`: Label for update button
|
|
153
187
|
- `promptPlaceholder`: Placeholder for prompt input
|
|
188
|
+
- `editImage`: Label for image edit section
|
|
189
|
+
- `imageUploadTitle`: Upload box title (e.g., "Select Image")
|
|
190
|
+
- `imageUploadHint`: Upload box hint (e.g., "Click or drag")
|
|
191
|
+
- `updateImage`: Label for image update button
|
|
192
|
+
- `badgeText`: Badge text (default: "Built with Promake")
|
|
154
193
|
- **theme**: `InspectorTheme` (optional)
|
|
155
194
|
- `backgroundColor`: Box background color (default: `#ffffff`)
|
|
156
195
|
- `textColor`: Text color (default: `#111827`)
|
|
@@ -159,6 +198,9 @@ function App() {
|
|
|
159
198
|
- `inputBackgroundColor`: Input background color (default: `#f9fafb`)
|
|
160
199
|
- `inputTextColor`: Input text color (default: `#111827`)
|
|
161
200
|
- `inputBorderColor`: Input border color (default: `#d1d5db`)
|
|
201
|
+
- `badgeGradientStart`: Badge gradient start color (default: `#411E93`)
|
|
202
|
+
- `badgeGradientEnd`: Badge gradient end color (default: `#E87C85`)
|
|
203
|
+
- `badgeTextColor`: Badge text color (default: `#ffffff`)
|
|
162
204
|
|
|
163
205
|
#### Returns
|
|
164
206
|
|
|
@@ -166,7 +208,9 @@ function App() {
|
|
|
166
208
|
- **toggleInspector**: `(active?: boolean) => void` - Toggle inspection mode
|
|
167
209
|
- **startInspecting**: `() => void` - Start inspecting
|
|
168
210
|
- **stopInspecting**: `() => void` - Stop inspecting
|
|
169
|
-
- **showContentInput**: `(show: boolean) => void` - Show or hide content input dynamically
|
|
211
|
+
- **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)
|
|
212
|
+
- **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)
|
|
213
|
+
- **setBadgeVisible**: `(visible: boolean) => void` - Show or hide "Built by Promake" badge in bottom-right corner
|
|
170
214
|
|
|
171
215
|
## Types
|
|
172
216
|
|
|
@@ -179,7 +223,10 @@ interface SelectedElementData {
|
|
|
179
223
|
id: string;
|
|
180
224
|
component: ComponentInfo | null;
|
|
181
225
|
position: ElementPosition;
|
|
182
|
-
isTextNode?: boolean; // Whether the element is a text
|
|
226
|
+
isTextNode?: boolean; // Whether the element is a text node
|
|
227
|
+
textContent?: string; // Text content of the element (if text node)
|
|
228
|
+
isImageNode?: boolean; // Whether the element is an image node
|
|
229
|
+
imageUrl?: string; // Image URL (if image node)
|
|
183
230
|
}
|
|
184
231
|
```
|
|
185
232
|
|
|
@@ -213,6 +260,21 @@ interface TextUpdatedData {
|
|
|
213
260
|
}
|
|
214
261
|
```
|
|
215
262
|
|
|
263
|
+
### `ImageUpdatedData`
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
interface ImageUpdatedData {
|
|
267
|
+
imageData: string; // Base64 encoded image data
|
|
268
|
+
imageFile: {
|
|
269
|
+
name: string;
|
|
270
|
+
size: number;
|
|
271
|
+
type: string;
|
|
272
|
+
};
|
|
273
|
+
originalImageUrl: string;
|
|
274
|
+
element: SelectedElementData;
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
216
278
|
### `ErrorData`
|
|
217
279
|
|
|
218
280
|
```typescript
|
|
@@ -227,6 +289,22 @@ interface ErrorData {
|
|
|
227
289
|
}
|
|
228
290
|
```
|
|
229
291
|
|
|
292
|
+
### `InspectorLabels`
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
interface InspectorLabels {
|
|
296
|
+
editText?: string; // Label for text edit section
|
|
297
|
+
textPlaceholder?: string; // Placeholder for text input
|
|
298
|
+
updateText?: string; // Label for text update button
|
|
299
|
+
promptPlaceholder?: string; // Placeholder for prompt input
|
|
300
|
+
editImage?: string; // Label for image edit section
|
|
301
|
+
imageUploadTitle?: string; // Upload box title (e.g., "Select Image")
|
|
302
|
+
imageUploadHint?: string; // Upload box hint (e.g., "Click or drag")
|
|
303
|
+
updateImage?: string; // Label for image update button
|
|
304
|
+
badgeText?: string; // Badge text (default: "Built with Promake")
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
230
308
|
### `InspectorTheme`
|
|
231
309
|
|
|
232
310
|
```typescript
|
|
@@ -238,6 +316,9 @@ interface InspectorTheme {
|
|
|
238
316
|
inputBackgroundColor?: string; // Input background color
|
|
239
317
|
inputTextColor?: string; // Input text color
|
|
240
318
|
inputBorderColor?: string; // Input border color
|
|
319
|
+
badgeGradientStart?: string; // Badge gradient start color
|
|
320
|
+
badgeGradientEnd?: string; // Badge gradient end color
|
|
321
|
+
badgeTextColor?: string; // Badge text color
|
|
241
322
|
}
|
|
242
323
|
```
|
|
243
324
|
|
|
@@ -252,29 +333,167 @@ Click any element to select it. The inspector will:
|
|
|
252
333
|
- Pause scrolling
|
|
253
334
|
- Extract React component information
|
|
254
335
|
- Detect if element is a text-only node (`isTextNode`)
|
|
336
|
+
- Detect if element is an image node (`isImageNode`)
|
|
255
337
|
|
|
256
338
|
### Dynamic Content Input
|
|
257
339
|
|
|
258
|
-
The inspector now uses a
|
|
340
|
+
The inspector now uses a three-stage approach:
|
|
259
341
|
|
|
260
342
|
1. **Prompt Input (Always Visible)**: Every element shows a prompt input for AI instructions
|
|
261
|
-
2. **Content Input (On-Demand)**: Text editing appears only when you call `showContentInput(true)`
|
|
343
|
+
2. **Text Content Input (On-Demand)**: Text editing appears only when you call `showContentInput(true)`
|
|
344
|
+
3. **Image Upload (On-Demand)**: Image upload appears only when you call `showImageInput(true)`
|
|
262
345
|
|
|
263
346
|
This allows you to:
|
|
264
347
|
|
|
265
348
|
- Run AI computations after selection
|
|
266
|
-
- Decide programmatically when to show text editing
|
|
349
|
+
- Decide programmatically when to show text editing or image upload
|
|
267
350
|
- Keep the UI clean and focused
|
|
268
351
|
|
|
269
352
|
```typescript
|
|
270
353
|
onElementSelected: (data) => {
|
|
271
354
|
if (data.isTextNode) {
|
|
272
355
|
// Show content input above prompt input
|
|
273
|
-
|
|
356
|
+
// Pass true as second parameter for immediate DOM update
|
|
357
|
+
showContentInput(true, true);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (data.isImageNode) {
|
|
361
|
+
// Show image upload for images
|
|
362
|
+
// Pass true as second parameter for immediate DOM update
|
|
363
|
+
showImageInput(true, true);
|
|
274
364
|
}
|
|
275
365
|
};
|
|
276
366
|
```
|
|
277
367
|
|
|
368
|
+
### Image Upload
|
|
369
|
+
|
|
370
|
+
For image elements:
|
|
371
|
+
|
|
372
|
+
- **Custom Upload Box**: Dashed border box with drag & drop support
|
|
373
|
+
- **Click to Upload**: Click the box to select image from file explorer
|
|
374
|
+
- **Drag & Drop**: Drag image files directly onto the upload box
|
|
375
|
+
- **Preview**: Selected image appears in the same box (max 100px height)
|
|
376
|
+
- **Base64 Encoding**: Image is automatically converted to base64
|
|
377
|
+
- **File Metadata**: File name, size, and type are included
|
|
378
|
+
|
|
379
|
+
The image data is sent to parent app with `onImageUpdated` callback for upload to your server.
|
|
380
|
+
|
|
381
|
+
### Immediate DOM Updates
|
|
382
|
+
|
|
383
|
+
For production environments where backend processing takes time, you can enable immediate DOM updates:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
// Text updates - DOM is updated immediately, no wait for backend
|
|
387
|
+
showContentInput(true, true); // updateImmediately: true
|
|
388
|
+
|
|
389
|
+
// Image updates - Image appears immediately, no wait for backend
|
|
390
|
+
showImageInput(true, true); // updateImmediately: true
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**How it works:**
|
|
394
|
+
|
|
395
|
+
1. **Text Updates**: When user submits new text, the DOM text content is updated immediately
|
|
396
|
+
2. **Image Updates**: When user selects an image, the `<img>` src (or background-image) is updated immediately with base64 data
|
|
397
|
+
3. **Backend Sync**: The `onTextUpdated` or `onImageUpdated` callback is still fired for backend sync
|
|
398
|
+
4. **User Experience**: User sees instant feedback, while your backend processes in the background
|
|
399
|
+
|
|
400
|
+
This is perfect for:
|
|
401
|
+
|
|
402
|
+
- Slow API responses
|
|
403
|
+
- AI processing that takes seconds
|
|
404
|
+
- Upload-heavy operations
|
|
405
|
+
- Better perceived performance
|
|
406
|
+
|
|
407
|
+
### Promake Badge
|
|
408
|
+
|
|
409
|
+
Show a beautiful "Built with Promake" badge in the bottom-right corner:
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
// Show badge with default text ("Built with Promake")
|
|
413
|
+
setBadgeVisible(true);
|
|
414
|
+
|
|
415
|
+
// Hide badge
|
|
416
|
+
setBadgeVisible(false);
|
|
417
|
+
|
|
418
|
+
// Customize badge text via labels
|
|
419
|
+
const { setBadgeVisible } = useInspector(iframeRef, callbacks, {
|
|
420
|
+
badgeText: "Made with ❤️ by MyCompany",
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// Customize badge colors via theme
|
|
424
|
+
const { setBadgeVisible } = useInspector(
|
|
425
|
+
iframeRef,
|
|
426
|
+
callbacks,
|
|
427
|
+
undefined, // no custom labels
|
|
428
|
+
{
|
|
429
|
+
badgeGradientStart: "#10b981", // Green
|
|
430
|
+
badgeGradientEnd: "#3b82f6", // Blue
|
|
431
|
+
badgeTextColor: "#ffffff", // White text
|
|
432
|
+
}
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
// Dark badge with light text
|
|
436
|
+
const { setBadgeVisible } = useInspector(iframeRef, callbacks, undefined, {
|
|
437
|
+
badgeGradientStart: "#1e293b", // Dark slate
|
|
438
|
+
badgeGradientEnd: "#334155", // Slate
|
|
439
|
+
badgeTextColor: "#f8fafc", // Light text
|
|
440
|
+
});
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**Features:**
|
|
444
|
+
|
|
445
|
+
- 🎨 Beautiful gradient design (purple to violet by default)
|
|
446
|
+
- ⚡ Smooth fade-in/fade-out animations
|
|
447
|
+
- 🖱️ Hover effects with elevation
|
|
448
|
+
- 🔗 Clickable - opens promake.ai in new tab
|
|
449
|
+
- 📍 Fixed position in bottom-right
|
|
450
|
+
- 🚫 Ignored by inspector (has `data-inspector-ignore`)
|
|
451
|
+
- 📝 Customizable text via labels
|
|
452
|
+
- 🎨 Customizable gradient colors via theme
|
|
453
|
+
- 🔤 Customizable text color via theme
|
|
454
|
+
- ❌ Close button appears on hover - users can dismiss the badge
|
|
455
|
+
|
|
456
|
+
**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).
|
|
457
|
+
|
|
458
|
+
**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.
|
|
459
|
+
|
|
460
|
+
**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.
|
|
461
|
+
|
|
462
|
+
**Color Examples:**
|
|
463
|
+
|
|
464
|
+
**Gradient Backgrounds:**
|
|
465
|
+
|
|
466
|
+
- **Deep Purple to Coral Pink** (default): `#411E93` → `#E87C85` (white text)
|
|
467
|
+
- **Blue to Cyan**: `#3b82f6` → `#06b6d4` (white text)
|
|
468
|
+
- **Green to Emerald**: `#10b981` → `#059669` (white text)
|
|
469
|
+
- **Pink to Rose**: `#ec4899` → `#f43f5e` (white text)
|
|
470
|
+
- **Orange to Red**: `#f97316` → `#ef4444` (white text)
|
|
471
|
+
- **Dark Slate**: `#1e293b` → `#334155` (light text `#f8fafc`)
|
|
472
|
+
|
|
473
|
+
**Text Colors:**
|
|
474
|
+
|
|
475
|
+
- **White** (default): `#ffffff`
|
|
476
|
+
- **Light**: `#f8fafc`, `#f1f5f9`
|
|
477
|
+
- **Dark**: `#111827`, `#1e293b`
|
|
478
|
+
- **Brand Colors**: Match your brand palette
|
|
479
|
+
|
|
480
|
+
**Auto-Show Behavior:**
|
|
481
|
+
|
|
482
|
+
The badge automatically appears in these conditions:
|
|
483
|
+
|
|
484
|
+
1. The app is **not** inside an iframe (`window.parent === window`)
|
|
485
|
+
2. The URL contains `preview.promake.ai`
|
|
486
|
+
|
|
487
|
+
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.
|
|
488
|
+
|
|
489
|
+
**Use Cases:**
|
|
490
|
+
|
|
491
|
+
- Show attribution to Promake
|
|
492
|
+
- Free tier watermark for preview deployments
|
|
493
|
+
- Branding for templates built with Promake
|
|
494
|
+
- Custom branding with your own text and colors
|
|
495
|
+
- Automatic display in preview environments
|
|
496
|
+
|
|
278
497
|
### AI Prompts
|
|
279
498
|
|
|
280
499
|
For any element:
|
|
@@ -458,31 +677,17 @@ const { toggleInspector } = useInspector(iframeRef, {
|
|
|
458
677
|
|
|
459
678
|
## CI/CD
|
|
460
679
|
|
|
461
|
-
This project includes GitHub Actions
|
|
680
|
+
This project includes GitHub Actions workflow:
|
|
462
681
|
|
|
463
682
|
### Build Workflow (`.github/workflows/build.yml`)
|
|
464
683
|
|
|
465
684
|
Automatically runs on every push and pull request:
|
|
466
685
|
|
|
467
|
-
- ✅
|
|
468
|
-
- ✅
|
|
686
|
+
- ✅ Uses Bun for fast installation and build
|
|
687
|
+
- ✅ Runs `bun install` and `bun run build`
|
|
469
688
|
- ✅ Checks for build artifacts
|
|
470
689
|
- ✅ Uploads build artifacts for review
|
|
471
690
|
|
|
472
|
-
### Publish Workflow (`.github/workflows/publish.yml`)
|
|
473
|
-
|
|
474
|
-
Automatically publishes to NPM when a release is created:
|
|
475
|
-
|
|
476
|
-
- ✅ Builds the package
|
|
477
|
-
- ✅ Publishes to NPM with `--access public`
|
|
478
|
-
- ✅ Manual trigger support via workflow_dispatch
|
|
479
|
-
|
|
480
|
-
**Setup for NPM publishing:**
|
|
481
|
-
|
|
482
|
-
1. Create an NPM access token at [npmjs.com](https://www.npmjs.com/settings/YOUR_USERNAME/tokens)
|
|
483
|
-
2. Add the token as `NPM_TOKEN` secret in your GitHub repository settings
|
|
484
|
-
3. Create a release on GitHub to trigger automatic publishing
|
|
485
|
-
|
|
486
691
|
## License
|
|
487
692
|
|
|
488
693
|
MIT
|
package/dist/hook.d.ts
CHANGED
|
@@ -12,16 +12,22 @@
|
|
|
12
12
|
* function App() {
|
|
13
13
|
* const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
14
14
|
*
|
|
15
|
-
* const { isInspecting, toggleInspector, showContentInput } = useInspector(
|
|
15
|
+
* const { isInspecting, toggleInspector, showContentInput, showImageInput } = useInspector(
|
|
16
16
|
* iframeRef,
|
|
17
17
|
* {
|
|
18
18
|
* onElementSelected: (data) => {
|
|
19
19
|
* console.log('Element selected:', data);
|
|
20
20
|
* console.log('Is text node:', data.isTextNode);
|
|
21
|
+
* console.log('Is image node:', data.isImageNode);
|
|
21
22
|
*
|
|
22
23
|
* // Dynamically show content input for text nodes
|
|
23
24
|
* if (data.isTextNode) {
|
|
24
|
-
* showContentInput(true);
|
|
25
|
+
* showContentInput(true, true); // updateImmediately: true for instant feedback
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* // Dynamically show image input for image nodes
|
|
29
|
+
* if (data.isImageNode) {
|
|
30
|
+
* showImageInput(true, true); // updateImmediately: true for instant feedback
|
|
25
31
|
* }
|
|
26
32
|
* },
|
|
27
33
|
* onPromptSubmitted: (data) => {
|
|
@@ -35,6 +41,19 @@
|
|
|
35
41
|
* onTextUpdated: (data) => {
|
|
36
42
|
* console.log('Text updated:', data.text);
|
|
37
43
|
* },
|
|
44
|
+
* onImageUpdated: (data) => {
|
|
45
|
+
* console.log('Image updated:', data.imageFile.name);
|
|
46
|
+
* console.log('Image data (base64):', data.imageData);
|
|
47
|
+
* // Upload to server
|
|
48
|
+
* fetch('/api/upload-image', {
|
|
49
|
+
* method: 'POST',
|
|
50
|
+
* body: JSON.stringify(data)
|
|
51
|
+
* });
|
|
52
|
+
* },
|
|
53
|
+
* onInspectorClosed: () => {
|
|
54
|
+
* console.log('Inspector closed');
|
|
55
|
+
* // Update UI state, re-enable elements, etc.
|
|
56
|
+
* },
|
|
38
57
|
* onError: (data) => {
|
|
39
58
|
* console.error('Error:', data);
|
|
40
59
|
* // Send to error tracking service
|
|
@@ -45,7 +64,12 @@
|
|
|
45
64
|
* editText: 'Edit Text',
|
|
46
65
|
* textPlaceholder: 'Enter text...',
|
|
47
66
|
* updateText: 'Update',
|
|
48
|
-
* promptPlaceholder: 'Ask AI for changes...'
|
|
67
|
+
* promptPlaceholder: 'Ask AI for changes...',
|
|
68
|
+
* editImage: 'Change Image',
|
|
69
|
+
* imageUploadTitle: 'Select Image',
|
|
70
|
+
* imageUploadHint: 'Click or drag',
|
|
71
|
+
* updateImage: 'Update Image',
|
|
72
|
+
* badgeText: 'Built with Promake'
|
|
49
73
|
* },
|
|
50
74
|
* {
|
|
51
75
|
* // Optional: Custom theme colors (all optional)
|
|
@@ -55,7 +79,10 @@
|
|
|
55
79
|
* buttonTextColor: '#ffffff',
|
|
56
80
|
* inputBackgroundColor: '#f9fafb',
|
|
57
81
|
* inputTextColor: '#111827',
|
|
58
|
-
* inputBorderColor: '#d1d5db'
|
|
82
|
+
* inputBorderColor: '#d1d5db',
|
|
83
|
+
* badgeGradientStart: '#411E93',
|
|
84
|
+
* badgeGradientEnd: '#E87C85',
|
|
85
|
+
* badgeTextColor: '#ffffff'
|
|
59
86
|
* }
|
|
60
87
|
* );
|
|
61
88
|
*
|
|
@@ -66,7 +93,13 @@
|
|
|
66
93
|
* Toggle Inspector
|
|
67
94
|
* </button>
|
|
68
95
|
* <button onClick={() => showContentInput(true)}>
|
|
69
|
-
* Show
|
|
96
|
+
* Show Text Input
|
|
97
|
+
* </button>
|
|
98
|
+
* <button onClick={() => showImageInput(true)}>
|
|
99
|
+
* Show Image Input
|
|
100
|
+
* </button>
|
|
101
|
+
* <button onClick={() => setBadgeVisible(true)}>
|
|
102
|
+
* Show Promake Badge
|
|
70
103
|
* </button>
|
|
71
104
|
* </div>
|
|
72
105
|
* <iframe ref={iframeRef} src="http://localhost:5173" />
|
package/dist/hook.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6GG;AAEH,OAAO,EAAoC,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,kBAAkB,EAOnB,MAAM,SAAS,CAAC;AAsDjB,wBAAgB,YAAY,CAC1B,SAAS,EAAE,SAAS,CAAC,iBAAiB,CAAC,EACvC,SAAS,CAAC,EAAE,kBAAkB,EAC9B,MAAM,CAAC,EAAE,eAAe,EACxB,KAAK,CAAC,EAAE,cAAc,GACrB,kBAAkB,CA4LpB;AAGD,mBAAmB,SAAS,CAAC"}
|