@promakeai/inspector 0.0.1 → 0.0.4

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 CHANGED
@@ -1,18 +1,25 @@
1
1
  # @promakeai/inspector
2
2
 
3
+ [![Build Status](https://github.com/promakeai/inspector/actions/workflows/build.yml/badge.svg)](https://github.com/promakeai/inspector/actions/workflows/build.yml)
4
+ [![npm version](https://badge.fury.io/js/@promakeai%2Finspector.svg)](https://www.npmjs.com/package/@promakeai/inspector)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
3
7
  Visual element inspector for React apps in iframe with AI prompt support. Perfect for visual editors, page builders, and low-code platforms.
4
8
 
5
9
  ## Features
6
10
 
7
11
  - 🎯 **Element Selection** - Click to select any element on the page
8
12
  - 🔍 **React Component Detection** - Automatically detects React components via Fiber
9
- - 📝 **Text Editing** - Edit text content directly
10
- - 🤖 **AI Prompt Support** - Send prompts to AI for element modifications
13
+ - 📝 **Dynamic Content Input** - Show/hide text editing on-demand with `showContentInput()`
14
+ - 🤖 **AI Prompt Support** - Always-visible prompt input for AI modifications
11
15
  - 🎨 **Visual Feedback** - Highlight selected elements with overlay
12
16
  - 🔒 **Pause Mode** - Lock selection and disable scroll while editing
13
17
  - 🌐 **URL Tracking** - Monitor navigation changes in iframe
14
18
  - 🐛 **Error Tracking** - Capture JavaScript errors, promise rejections, and console errors
15
- - 🎨 **Customizable Labels** - Multi-language support
19
+ - 🎨 **Customizable Theme** - Full color customization for all UI elements
20
+ - 🌍 **Customizable Labels** - Multi-language support
21
+ - 🚫 **Ignore Elements** - Mark elements as non-inspectable with `data-inspector-ignore`
22
+ - 🔍 **Text Node Detection** - Automatically detect if selected element is a text node
16
23
  - 📦 **TypeScript** - Full type safety
17
24
 
18
25
  ## Installation
@@ -48,14 +55,21 @@ import { useInspector } from "@promakeai/inspector/hook";
48
55
  function App() {
49
56
  const iframeRef = useRef<HTMLIFrameElement>(null);
50
57
 
51
- const { isInspecting, toggleInspector } = useInspector(
58
+ const { isInspecting, toggleInspector, showContentInput } = useInspector(
52
59
  iframeRef,
53
60
  {
54
61
  onElementSelected: (data) => {
55
62
  console.log("Element selected:", data);
63
+ console.log("Is text node:", data.isTextNode);
64
+
56
65
  // Access component info
57
66
  console.log(data.component?.fileName);
58
67
  console.log(data.component?.lineNumber);
68
+
69
+ // Show content input if it's a text node
70
+ if (data.isTextNode) {
71
+ showContentInput(true);
72
+ }
59
73
  },
60
74
  onPromptSubmitted: (data) => {
61
75
  console.log("AI Prompt:", data.prompt);
@@ -87,6 +101,16 @@ function App() {
87
101
  textPlaceholder: "Enter text...",
88
102
  updateText: "Update",
89
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",
90
114
  }
91
115
  );
92
116
 
@@ -96,6 +120,13 @@ function App() {
96
120
  {isInspecting ? "Stop Inspector" : "Start Inspector"}
97
121
  </button>
98
122
 
123
+ {/* Optional: Manual content input toggle */}
124
+ {isInspecting && (
125
+ <button onClick={() => showContentInput(true)}>
126
+ Show Content Input
127
+ </button>
128
+ )}
129
+
99
130
  <iframe ref={iframeRef} src="http://localhost:5173" />
100
131
  </div>
101
132
  );
@@ -104,13 +135,13 @@ function App() {
104
135
 
105
136
  ## API
106
137
 
107
- ### `useInspector(iframeRef, callbacks?, labels?)`
138
+ ### `useInspector(iframeRef, callbacks?, labels?, theme?)`
108
139
 
109
140
  #### Parameters
110
141
 
111
142
  - **iframeRef**: `RefObject<HTMLIFrameElement>` - Reference to the iframe element
112
143
  - **callbacks**: `InspectorCallbacks` (optional)
113
- - `onElementSelected`: Called when an element is selected
144
+ - `onElementSelected`: Called when an element is selected (receives `isTextNode` property)
114
145
  - `onPromptSubmitted`: Called when AI prompt is submitted
115
146
  - `onTextUpdated`: Called when text content is updated
116
147
  - `onUrlChange`: Called when URL changes in iframe
@@ -120,6 +151,14 @@ function App() {
120
151
  - `textPlaceholder`: Placeholder for text input
121
152
  - `updateText`: Label for update button
122
153
  - `promptPlaceholder`: Placeholder for prompt input
154
+ - **theme**: `InspectorTheme` (optional)
155
+ - `backgroundColor`: Box background color (default: `#ffffff`)
156
+ - `textColor`: Text color (default: `#111827`)
157
+ - `buttonColor`: Button background color (default: `#4417db`)
158
+ - `buttonTextColor`: Button text color (default: `#ffffff`)
159
+ - `inputBackgroundColor`: Input background color (default: `#f9fafb`)
160
+ - `inputTextColor`: Input text color (default: `#111827`)
161
+ - `inputBorderColor`: Input border color (default: `#d1d5db`)
123
162
 
124
163
  #### Returns
125
164
 
@@ -127,6 +166,7 @@ function App() {
127
166
  - **toggleInspector**: `(active?: boolean) => void` - Toggle inspection mode
128
167
  - **startInspecting**: `() => void` - Start inspecting
129
168
  - **stopInspecting**: `() => void` - Stop inspecting
169
+ - **showContentInput**: `(show: boolean) => void` - Show or hide content input dynamically
130
170
 
131
171
  ## Types
132
172
 
@@ -139,6 +179,8 @@ interface SelectedElementData {
139
179
  id: string;
140
180
  component: ComponentInfo | null;
141
181
  position: ElementPosition;
182
+ isTextNode?: boolean; // Whether the element is a text node
183
+ textContent?: string; // Text content of the element (if text node)
142
184
  }
143
185
  ```
144
186
 
@@ -186,6 +228,20 @@ interface ErrorData {
186
228
  }
187
229
  ```
188
230
 
231
+ ### `InspectorTheme`
232
+
233
+ ```typescript
234
+ interface InspectorTheme {
235
+ backgroundColor?: string; // Box background color
236
+ textColor?: string; // Text color
237
+ buttonColor?: string; // Button background color
238
+ buttonTextColor?: string; // Button text color
239
+ inputBackgroundColor?: string; // Input background color
240
+ inputTextColor?: string; // Input text color
241
+ inputBorderColor?: string; // Input border color
242
+ }
243
+ ```
244
+
189
245
  ## Features in Detail
190
246
 
191
247
  ### Element Selection
@@ -193,26 +249,65 @@ interface ErrorData {
193
249
  Click any element to select it. The inspector will:
194
250
 
195
251
  - Show a blue highlight overlay
196
- - Display a control box below/above the element
252
+ - Display a control box below/above the element (always shows prompt input)
197
253
  - Pause scrolling
198
254
  - Extract React component information
255
+ - Detect if element is a text-only node (`isTextNode`)
256
+
257
+ ### Dynamic Content Input
258
+
259
+ The inspector now uses a two-stage approach:
260
+
261
+ 1. **Prompt Input (Always Visible)**: Every element shows a prompt input for AI instructions
262
+ 2. **Content Input (On-Demand)**: Text editing appears only when you call `showContentInput(true)`
199
263
 
200
- ### Text Editing
264
+ This allows you to:
201
265
 
202
- For text-only elements:
266
+ - Run AI computations after selection
267
+ - Decide programmatically when to show text editing
268
+ - Keep the UI clean and focused
203
269
 
204
- - Textarea appears with current text
205
- - Edit and click "Update"
206
- - Event is sent to parent app
270
+ ```typescript
271
+ onElementSelected: (data) => {
272
+ if (data.isTextNode) {
273
+ // Show content input above prompt input
274
+ showContentInput(true);
275
+ }
276
+ };
277
+ ```
207
278
 
208
279
  ### AI Prompts
209
280
 
210
281
  For any element:
211
282
 
283
+ - Prompt input is always visible
212
284
  - Enter a prompt describing desired changes
213
285
  - Click the send button (↑)
214
286
  - Prompt + element data sent to parent app
215
287
 
288
+ ### Ignoring Elements
289
+
290
+ Mark elements as non-inspectable using the `data-inspector-ignore` attribute:
291
+
292
+ ```jsx
293
+ <button data-inspector-ignore onClick={toggleInspect}>
294
+ Inspector Controls
295
+ </button>
296
+
297
+ <div data-inspector-ignore>
298
+ {/* All children will be ignored too */}
299
+ <button>Button 1</button>
300
+ <button>Button 2</button>
301
+ </div>
302
+ ```
303
+
304
+ This is perfect for:
305
+
306
+ - Inspector control buttons
307
+ - Floating toolbars
308
+ - Fixed navigation
309
+ - Any UI that shouldn't be inspectable
310
+
216
311
  ### Component Detection
217
312
 
218
313
  Automatically extracts:
@@ -243,6 +338,45 @@ Perfect for integrating with error tracking services like Sentry, LogRocket, or
243
338
 
244
339
  ## Examples
245
340
 
341
+ ### Dynamic Content Input Based on AI Response
342
+
343
+ ```typescript
344
+ const { toggleInspector, showContentInput } = useInspector(iframeRef, {
345
+ onElementSelected: async (data) => {
346
+ // Run AI analysis first
347
+ const analysis = await analyzeElement(data);
348
+
349
+ // Show content input only if AI suggests text editing
350
+ if (analysis.shouldShowTextEditor && data.isTextNode) {
351
+ showContentInput(true);
352
+ }
353
+ },
354
+ onPromptSubmitted: async (data) => {
355
+ // Process AI prompt
356
+ const result = await processAIPrompt(data.prompt, data.element);
357
+
358
+ // Optionally show content input after AI processing
359
+ if (result.needsTextInput) {
360
+ showContentInput(true);
361
+ }
362
+ },
363
+ });
364
+ ```
365
+
366
+ ### Dark Theme
367
+
368
+ ```typescript
369
+ const { toggleInspector } = useInspector(iframeRef, callbacks, labels, {
370
+ backgroundColor: "#1a1a1a",
371
+ textColor: "#ffffff",
372
+ buttonColor: "#00ff00",
373
+ buttonTextColor: "#000000",
374
+ inputBackgroundColor: "#2a2a2a",
375
+ inputTextColor: "#ffffff",
376
+ inputBorderColor: "#444444",
377
+ });
378
+ ```
379
+
246
380
  ### Multi-language Support
247
381
 
248
382
  ```typescript
@@ -250,10 +384,30 @@ const { toggleInspector } = useInspector(iframeRef, callbacks, {
250
384
  editText: "Metni Düzenle",
251
385
  textPlaceholder: "Metin girin...",
252
386
  updateText: "Güncelle",
253
- promptPlaceholder: "AI için komut girin...",
387
+ promptPlaceholder: "Promake'e değişiklik sor...",
254
388
  });
255
389
  ```
256
390
 
391
+ ### Prevent Inspector Buttons from Being Selected
392
+
393
+ ```jsx
394
+ function App() {
395
+ return (
396
+ <div>
397
+ {/* These buttons won't be inspectable */}
398
+ <div className="inspector-controls" data-inspector-ignore>
399
+ <button onClick={toggleInspect}>Toggle Inspector</button>
400
+ <button onClick={() => showContentInput(true)}>
401
+ Show Content Input
402
+ </button>
403
+ </div>
404
+
405
+ <iframe ref={iframeRef} src="http://localhost:5173" />
406
+ </div>
407
+ );
408
+ }
409
+ ```
410
+
257
411
  ### Open File in Editor
258
412
 
259
413
  ```typescript
@@ -303,6 +457,19 @@ const { toggleInspector } = useInspector(iframeRef, {
303
457
  - React 18.0+
304
458
  - TypeScript (recommended)
305
459
 
460
+ ## CI/CD
461
+
462
+ This project includes GitHub Actions workflow:
463
+
464
+ ### Build Workflow (`.github/workflows/build.yml`)
465
+
466
+ Automatically runs on every push and pull request:
467
+
468
+ - ✅ Uses Bun for fast installation and build
469
+ - ✅ Runs `bun install` and `bun run build`
470
+ - ✅ Checks for build artifacts
471
+ - ✅ Uploads build artifacts for review
472
+
306
473
  ## License
307
474
 
308
475
  MIT
package/dist/hook.d.ts CHANGED
@@ -12,11 +12,17 @@
12
12
  * function App() {
13
13
  * const iframeRef = useRef<HTMLIFrameElement>(null);
14
14
  *
15
- * const { isInspecting, toggleInspector } = useInspector(
15
+ * const { isInspecting, toggleInspector, showContentInput } = useInspector(
16
16
  * iframeRef,
17
17
  * {
18
18
  * onElementSelected: (data) => {
19
19
  * console.log('Element selected:', data);
20
+ * console.log('Is text node:', data.isTextNode);
21
+ *
22
+ * // Dynamically show content input for text nodes
23
+ * if (data.isTextNode) {
24
+ * showContentInput(true);
25
+ * }
20
26
  * },
21
27
  * onPromptSubmitted: (data) => {
22
28
  * console.log('AI Prompt:', data.prompt);
@@ -40,22 +46,37 @@
40
46
  * textPlaceholder: 'Enter text...',
41
47
  * updateText: 'Update',
42
48
  * promptPlaceholder: 'Ask AI for changes...'
49
+ * },
50
+ * {
51
+ * // Optional: Custom theme colors (all optional)
52
+ * backgroundColor: '#ffffff',
53
+ * textColor: '#111827',
54
+ * buttonColor: '#4417db',
55
+ * buttonTextColor: '#ffffff',
56
+ * inputBackgroundColor: '#f9fafb',
57
+ * inputTextColor: '#111827',
58
+ * inputBorderColor: '#d1d5db'
43
59
  * }
44
60
  * );
45
61
  *
46
62
  * return (
47
- * <div>
48
- * <button onClick={() => toggleInspector()}>
49
- * {isInspecting ? 'Stop' : 'Start'} Inspector
50
- * </button>
63
+ * <>
64
+ * <div data-inspector-ignore>
65
+ * <button onClick={() => toggleInspector()}>
66
+ * Toggle Inspector
67
+ * </button>
68
+ * <button onClick={() => showContentInput(true)}>
69
+ * Show Content Input
70
+ * </button>
71
+ * </div>
51
72
  * <iframe ref={iframeRef} src="http://localhost:5173" />
52
- * </div>
73
+ * </>
53
74
  * );
54
75
  * }
55
76
  * ```
56
77
  */
57
78
  import { RefObject } from "react";
58
- import type { InspectorCallbacks, InspectorLabels, UseInspectorReturn } from "./types";
59
- export declare function useInspector(iframeRef: RefObject<HTMLIFrameElement>, callbacks?: InspectorCallbacks, labels?: InspectorLabels): UseInspectorReturn;
79
+ import type { InspectorCallbacks, InspectorLabels, InspectorTheme, UseInspectorReturn } from "./types";
80
+ export declare function useInspector(iframeRef: RefObject<HTMLIFrameElement>, callbacks?: InspectorCallbacks, labels?: InspectorLabels, theme?: InspectorTheme): UseInspectorReturn;
60
81
  export type * from "./types";
61
82
  //# sourceMappingURL=hook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,OAAO,EAAoC,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAMnB,MAAM,SAAS,CAAC;AA8BjB,wBAAgB,YAAY,CAC1B,SAAS,EAAE,SAAS,CAAC,iBAAiB,CAAC,EACvC,SAAS,CAAC,EAAE,kBAAkB,EAC9B,MAAM,CAAC,EAAE,eAAe,GACvB,kBAAkB,CAwHpB;AAGD,mBAAmB,SAAS,CAAC"}
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AAEH,OAAO,EAAoC,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,kBAAkB,EAMnB,MAAM,SAAS,CAAC;AAoCjB,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,CAsJpB;AAGD,mBAAmB,SAAS,CAAC"}
package/dist/hook.js CHANGED
@@ -12,11 +12,17 @@
12
12
  * function App() {
13
13
  * const iframeRef = useRef<HTMLIFrameElement>(null);
14
14
  *
15
- * const { isInspecting, toggleInspector } = useInspector(
15
+ * const { isInspecting, toggleInspector, showContentInput } = useInspector(
16
16
  * iframeRef,
17
17
  * {
18
18
  * onElementSelected: (data) => {
19
19
  * console.log('Element selected:', data);
20
+ * console.log('Is text node:', data.isTextNode);
21
+ *
22
+ * // Dynamically show content input for text nodes
23
+ * if (data.isTextNode) {
24
+ * showContentInput(true);
25
+ * }
20
26
  * },
21
27
  * onPromptSubmitted: (data) => {
22
28
  * console.log('AI Prompt:', data.prompt);
@@ -40,22 +46,37 @@
40
46
  * textPlaceholder: 'Enter text...',
41
47
  * updateText: 'Update',
42
48
  * promptPlaceholder: 'Ask AI for changes...'
49
+ * },
50
+ * {
51
+ * // Optional: Custom theme colors (all optional)
52
+ * backgroundColor: '#ffffff',
53
+ * textColor: '#111827',
54
+ * buttonColor: '#4417db',
55
+ * buttonTextColor: '#ffffff',
56
+ * inputBackgroundColor: '#f9fafb',
57
+ * inputTextColor: '#111827',
58
+ * inputBorderColor: '#d1d5db'
43
59
  * }
44
60
  * );
45
61
  *
46
62
  * return (
47
- * <div>
48
- * <button onClick={() => toggleInspector()}>
49
- * {isInspecting ? 'Stop' : 'Start'} Inspector
50
- * </button>
63
+ * <>
64
+ * <div data-inspector-ignore>
65
+ * <button onClick={() => toggleInspector()}>
66
+ * Toggle Inspector
67
+ * </button>
68
+ * <button onClick={() => showContentInput(true)}>
69
+ * Show Content Input
70
+ * </button>
71
+ * </div>
51
72
  * <iframe ref={iframeRef} src="http://localhost:5173" />
52
- * </div>
73
+ * </>
53
74
  * );
54
75
  * }
55
76
  * ```
56
77
  */
57
78
  import { useEffect, useState, useCallback } from "react";
58
- export function useInspector(iframeRef, callbacks, labels) {
79
+ export function useInspector(iframeRef, callbacks, labels, theme) {
59
80
  const [isInspecting, setIsInspecting] = useState(false);
60
81
  /**
61
82
  * Send message to iframe
@@ -83,8 +104,9 @@ export function useInspector(iframeRef, callbacks, labels) {
83
104
  type: "TOGGLE_INSPECTOR",
84
105
  active: newState,
85
106
  labels: labels,
107
+ theme: theme,
86
108
  });
87
- }, [isInspecting, sendMessage, labels]);
109
+ }, [isInspecting, sendMessage, labels, theme]);
88
110
  /**
89
111
  * Start inspecting
90
112
  */
@@ -97,16 +119,38 @@ export function useInspector(iframeRef, callbacks, labels) {
97
119
  const stopInspecting = useCallback(() => {
98
120
  toggleInspector(false);
99
121
  }, [toggleInspector]);
122
+ /**
123
+ * Show or hide content input
124
+ */
125
+ const showContentInput = useCallback((show) => {
126
+ sendMessage({
127
+ type: "SHOW_CONTENT_INPUT",
128
+ show: show,
129
+ });
130
+ }, [sendMessage]);
100
131
  /**
101
132
  * Listen for messages from iframe
102
133
  */
103
134
  useEffect(() => {
104
135
  const handleMessage = (event) => {
136
+ // Parse message if it's a string (JSON stringified)
137
+ let messageData;
138
+ if (typeof event.data === "string") {
139
+ try {
140
+ messageData = JSON.parse(event.data);
141
+ }
142
+ catch {
143
+ return; // Invalid JSON, ignore
144
+ }
145
+ }
146
+ else {
147
+ messageData = event.data;
148
+ }
105
149
  // Security: Only handle expected message types
106
- if (!event.data || typeof event.data.type !== "string") {
150
+ if (!messageData || typeof messageData.type !== "string") {
107
151
  return;
108
152
  }
109
- const { type, data } = event.data;
153
+ const { type, data } = messageData;
110
154
  switch (type) {
111
155
  case "INSPECTOR_ELEMENT_SELECTED":
112
156
  callbacks?.onElementSelected?.(data);
@@ -142,6 +186,8 @@ export function useInspector(iframeRef, callbacks, labels) {
142
186
  sendMessage({
143
187
  type: "TOGGLE_INSPECTOR",
144
188
  active: false,
189
+ labels: labels,
190
+ theme: theme,
145
191
  });
146
192
  }
147
193
  };
@@ -151,5 +197,6 @@ export function useInspector(iframeRef, callbacks, labels) {
151
197
  toggleInspector,
152
198
  startInspecting,
153
199
  stopInspecting,
200
+ showContentInput,
154
201
  };
155
202
  }
package/dist/plugin.d.ts CHANGED
@@ -22,12 +22,20 @@
22
22
  * Plugin özellikler:
23
23
  * - Element seçimi (click-to-select)
24
24
  * - React Fiber üzerinden component bilgisi çıkarma
25
- * - Text editing desteği
26
- * - AI prompt gönderme
25
+ * - Text node algılama (isTextNode)
26
+ * - Dinamik content input (showContentInput ile kontrol edilir)
27
+ * - AI prompt gönderme (her zaman görünür)
28
+ * - data-inspector-ignore desteği (belirli elementleri ignore etme)
27
29
  * - URL değişikliği takibi
28
30
  * - JavaScript hata yakalama (error, promise rejection, console.error)
31
+ * - Özelleştirilebilir tema renkleri
29
32
  * - Özelleştirilebilir dil desteği
30
33
  *
34
+ * Kullanım:
35
+ * - Elementlere data-inspector-ignore attribute'u ekleyerek inspector'dan gizleyebilirsiniz
36
+ * - Control box her zaman prompt input gösterir
37
+ * - Content input sadece showContentInput(true) ile dinamik olarak eklenir
38
+ *
31
39
  * Not: Bu plugin otomatik olarak template/iframe'e enjekte edilir.
32
40
  * Ana app'te useInspector hook'u ile kontrol edilir.
33
41
  */
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,wBAAgB,eAAe,IAAI,MAAM,CA+kBxC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,wBAAgB,eAAe,IAAI,MAAM,CAyrBxC"}
package/dist/plugin.js CHANGED
@@ -22,12 +22,20 @@
22
22
  * Plugin özellikler:
23
23
  * - Element seçimi (click-to-select)
24
24
  * - React Fiber üzerinden component bilgisi çıkarma
25
- * - Text editing desteği
26
- * - AI prompt gönderme
25
+ * - Text node algılama (isTextNode)
26
+ * - Dinamik content input (showContentInput ile kontrol edilir)
27
+ * - AI prompt gönderme (her zaman görünür)
28
+ * - data-inspector-ignore desteği (belirli elementleri ignore etme)
27
29
  * - URL değişikliği takibi
28
30
  * - JavaScript hata yakalama (error, promise rejection, console.error)
31
+ * - Özelleştirilebilir tema renkleri
29
32
  * - Özelleştirilebilir dil desteği
30
33
  *
34
+ * Kullanım:
35
+ * - Elementlere data-inspector-ignore attribute'u ekleyerek inspector'dan gizleyebilirsiniz
36
+ * - Control box her zaman prompt input gösterir
37
+ * - Content input sadece showContentInput(true) ile dinamik olarak eklenir
38
+ *
31
39
  * Not: Bu plugin otomatik olarak template/iframe'e enjekte edilir.
32
40
  * Ana app'te useInspector hook'u ile kontrol edilir.
33
41
  */
@@ -62,6 +70,17 @@ export function inspectorPlugin() {
62
70
  promptPlaceholder: 'Ask Promake for changes...'
63
71
  };
64
72
 
73
+ // Customizable theme colors
74
+ let theme = {
75
+ backgroundColor: '#ffffff',
76
+ textColor: '#111827',
77
+ buttonColor: '#4417db',
78
+ buttonTextColor: '#ffffff',
79
+ inputBackgroundColor: '#f9fafb',
80
+ inputTextColor: '#111827',
81
+ inputBorderColor: '#d1d5db'
82
+ };
83
+
65
84
  // Create overlay for highlighting
66
85
  function createOverlay() {
67
86
  if (overlay) return overlay;
@@ -95,6 +114,10 @@ export function inspectorPlugin() {
95
114
  const isTextElement = element.textContent && element.children.length === 0;
96
115
  const currentText = isTextElement ? element.textContent.trim() : '';
97
116
 
117
+ // Store text info in data attribute for later use
118
+ controlBox.setAttribute('data-is-text-element', isTextElement);
119
+ controlBox.setAttribute('data-current-text', currentText);
120
+
98
121
  // Calculate position
99
122
  const boxWidth = Math.max(320, Math.min(rect.width, 500));
100
123
  const centerLeft = rect.left + (rect.width / 2) - (boxWidth / 2);
@@ -102,8 +125,8 @@ export function inspectorPlugin() {
102
125
  const spaceBelow = viewportHeight - rect.bottom;
103
126
  const spaceAbove = rect.top;
104
127
 
105
- // Estimate box height
106
- const estimatedBoxHeight = isTextElement ? 280 : 180;
128
+ // Estimate box height (only prompt input now, smaller)
129
+ const estimatedBoxHeight = 100;
107
130
 
108
131
  // Show above if not enough space below
109
132
  let topPosition;
@@ -122,7 +145,7 @@ export function inspectorPlugin() {
122
145
  top: \${topPosition}px;
123
146
  left: \${Math.max(10, centerLeft)}px;
124
147
  width: \${boxWidth}px;
125
- background: #ffffff;
148
+ background: \${theme.backgroundColor};
126
149
  border: 1px solid #e5e7eb;
127
150
  border-radius: 14px;
128
151
  padding: 12px;
@@ -130,80 +153,33 @@ export function inspectorPlugin() {
130
153
  z-index: 1000000;
131
154
  font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
132
155
  font-size: 14px;
156
+ display: flex;
157
+ flex-direction: column;
158
+ gap: 0;
133
159
  \`;
134
160
 
135
- let html = '';
136
-
137
- // Text input (if text element)
138
- if (isTextElement) {
139
- html += \`
140
- <div style="margin-bottom: 12px;">
141
- <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px;">
142
- <label style="font-weight: 500; color: #111827; font-size: 13px;">
143
- \${labels.editText}
144
- </label>
145
- <button
146
- id="inspector-close"
147
- style="width: 32px; height: 32px; background: transparent; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; border-radius: 14px; transition: all 0.2s; padding: 0; flex-shrink: 0;"
148
- onmouseover="this.style.background='#f3f4f6';"
149
- onmouseout="this.style.background='transparent';"
150
- title="Close"
151
- >
152
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
153
- <path d="M12 4L4 12M4 4L12 12" stroke="#6b7280" stroke-width="2" stroke-linecap="round"/>
154
- </svg>
155
- </button>
156
- </div>
157
- <textarea
158
- id="inspector-text-input"
159
- style="width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 14px; font-size: 14px; color: #111827; background: #f9fafb; transition: all 0.2s; resize: vertical; min-height: 60px; max-height: 200px; font-family: inherit; line-height: 1.5;"
160
- placeholder="\${labels.textPlaceholder}"
161
- onfocus="this.style.background='#ffffff'; this.style.borderColor='#9ca3af';"
162
- onblur="this.style.background='#f9fafb'; this.style.borderColor='#d1d5db';"
163
- >\${currentText}</textarea>
164
- </div>
165
- <div style="margin-bottom: 10px;">
166
- <button
167
- id="inspector-text-submit"
168
- style="width: 100%; padding: 10px 16px; background: #4417db; color: white; border: none; border-radius: 14px; cursor: pointer; font-weight: 500; font-size: 14px; transition: all 0.2s;"
169
- onmouseover="this.style.background='#3712af';"
170
- onmouseout="this.style.background='#4417db';"
171
- title="\${labels.updateText}"
172
- >
173
- \${labels.updateText}
174
- </button>
175
- </div>
176
- <div style="border-top: 1px solid #e5e7eb; margin: 12px 0;"></div>
177
- \`;
178
- }
179
-
180
- // Prompt input and buttons (side by side)
181
- html += \`
182
- <div style="display: flex; gap: 8px; align-items: stretch;">
161
+ // Only prompt input and buttons (always shown)
162
+ let html = \`
163
+ <div id="inspector-prompt-section" style="display: flex; gap: 8px; align-items: stretch;">
183
164
  <input
184
165
  type="text"
185
166
  id="inspector-prompt-input"
186
- style="flex: 1; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 14px; font-size: 14px; color: #111827; background: #f9fafb; transition: all 0.2s;"
167
+ style="flex: 1; padding: 10px 12px; border: 1px solid \${theme.inputBorderColor}; border-radius: 14px; font-size: 14px; color: \${theme.inputTextColor}; background: \${theme.inputBackgroundColor}; transition: all 0.2s;"
187
168
  placeholder="\${labels.promptPlaceholder}"
188
169
  onfocus="this.style.background='#ffffff'; this.style.borderColor='#9ca3af';"
189
- onblur="this.style.background='#f9fafb'; this.style.borderColor='#d1d5db';"
170
+ onblur="this.style.background='\${theme.inputBackgroundColor}'; this.style.borderColor='\${theme.inputBorderColor}';"
190
171
  />
191
172
  <button
192
173
  id="inspector-prompt-submit"
193
- style="width: 44px; height: 44px; padding: 0; background: #4417db; color: white; border: none; border-radius: 14px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; flex-shrink: 0;"
194
- onmouseover="this.style.background='#3712af';"
195
- onmouseout="this.style.background='#4417db';"
174
+ style="width: 44px; height: 44px; padding: 0; background: \${theme.buttonColor}; color: \${theme.buttonTextColor}; border: none; border-radius: 14px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; flex-shrink: 0;"
175
+ onmouseover="this.style.opacity='0.85';"
176
+ onmouseout="this.style.opacity='1';"
196
177
  title="Send"
197
178
  >
198
179
  <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
199
180
  <path d="M10 15V5M10 5L5 10M10 5L15 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
200
181
  </svg>
201
182
  </button>
202
- \`;
203
-
204
- // Close button next to send button (only for non-text elements)
205
- if (!isTextElement) {
206
- html += \`
207
183
  <button
208
184
  id="inspector-close"
209
185
  style="padding: 10px; background: #f3f4f6; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; border-radius: 14px; transition: all 0.2s;"
@@ -215,10 +191,8 @@ export function inspectorPlugin() {
215
191
  <path d="M12 4L4 12M4 4L12 12" stroke="#6b7280" stroke-width="2" stroke-linecap="round"/>
216
192
  </svg>
217
193
  </button>
218
- \`;
219
- }
220
-
221
- html += \`</div>\`;
194
+ </div>
195
+ \`;
222
196
 
223
197
  controlBox.innerHTML = html;
224
198
  document.body.appendChild(controlBox);
@@ -234,13 +208,14 @@ export function inspectorPlugin() {
234
208
  const prompt = promptInput.value.trim();
235
209
  if (prompt) {
236
210
  if (window.parent !== window) {
237
- window.parent.postMessage({
211
+ const message = JSON.stringify({
238
212
  type: 'INSPECTOR_PROMPT_SUBMITTED',
239
213
  data: {
240
214
  prompt: prompt,
241
215
  element: elementData
242
216
  }
243
- }, '*');
217
+ });
218
+ window.parent.postMessage(message, '*');
244
219
  }
245
220
  console.log('Prompt submitted:', elementData);
246
221
 
@@ -257,23 +232,83 @@ export function inspectorPlugin() {
257
232
  }
258
233
  });
259
234
 
260
- // Text input handlers (if exists)
261
- if (isTextElement) {
262
- const textInput = controlBox.querySelector('#inspector-text-input');
263
- const textSubmit = controlBox.querySelector('#inspector-text-submit');
235
+ // Prevent prompt input events from bubbling
236
+ promptInput.addEventListener('click', (e) => e.stopPropagation());
237
+
238
+ // Close button
239
+ closeBtn.addEventListener('click', (e) => {
240
+ e.stopPropagation();
241
+ unpauseInspection();
242
+ });
243
+
244
+ // Focus prompt input
245
+ setTimeout(() => promptInput.focus(), 100);
246
+ }
247
+
248
+ // Show or hide content input section
249
+ function toggleContentInput(show) {
250
+ if (!controlBox) return;
251
+
252
+ const isTextElement = controlBox.getAttribute('data-is-text-element') === 'true';
253
+ const currentText = controlBox.getAttribute('data-current-text') || '';
254
+
255
+ // Check if content input already exists
256
+ let contentSection = controlBox.querySelector('#inspector-content-section');
257
+
258
+ if (show && !contentSection && isTextElement) {
259
+ // Create content input section
260
+ contentSection = document.createElement('div');
261
+ contentSection.id = 'inspector-content-section';
262
+ contentSection.style.cssText = 'margin-bottom: 12px;';
263
+
264
+ contentSection.innerHTML = \`
265
+ <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px;">
266
+ <label style="font-weight: 500; color: \${theme.textColor}; font-size: 13px;">
267
+ \${labels.editText}
268
+ </label>
269
+ </div>
270
+ <textarea
271
+ id="inspector-text-input"
272
+ style="width: 100%; padding: 10px 12px; border: 1px solid \${theme.inputBorderColor}; border-radius: 14px; font-size: 14px; color: \${theme.inputTextColor}; background: \${theme.inputBackgroundColor}; transition: all 0.2s; resize: vertical; min-height: 60px; max-height: 200px; font-family: inherit; line-height: 1.5;"
273
+ placeholder="\${labels.textPlaceholder}"
274
+ onfocus="this.style.background='#ffffff'; this.style.borderColor='#9ca3af';"
275
+ onblur="this.style.background='\${theme.inputBackgroundColor}'; this.style.borderColor='\${theme.inputBorderColor}';"
276
+ >\${currentText}</textarea>
277
+ <div style="margin-top: 8px;">
278
+ <button
279
+ id="inspector-text-submit"
280
+ style="width: 100%; padding: 10px 16px; background: \${theme.buttonColor}; color: \${theme.buttonTextColor}; border: none; border-radius: 14px; cursor: pointer; font-weight: 500; font-size: 14px; transition: all 0.2s;"
281
+ onmouseover="this.style.opacity='0.85';"
282
+ onmouseout="this.style.opacity='1';"
283
+ title="\${labels.updateText}"
284
+ >
285
+ \${labels.updateText}
286
+ </button>
287
+ </div>
288
+ <div style="border-top: 1px solid #e5e7eb; margin-top: 12px; margin-bottom: 12px;"></div>
289
+ \`;
290
+
291
+ // Insert at the beginning of controlBox
292
+ const promptSection = controlBox.querySelector('#inspector-prompt-section');
293
+ controlBox.insertBefore(contentSection, promptSection);
294
+
295
+ // Add event listeners
296
+ const textInput = contentSection.querySelector('#inspector-text-input');
297
+ const textSubmit = contentSection.querySelector('#inspector-text-submit');
264
298
 
265
299
  textSubmit.addEventListener('click', (e) => {
266
300
  e.stopPropagation();
267
301
  const newText = textInput.value;
268
302
  if (window.parent !== window) {
269
- window.parent.postMessage({
303
+ const message = JSON.stringify({
270
304
  type: 'INSPECTOR_TEXT_UPDATED',
271
305
  data: {
272
306
  text: newText,
273
307
  originalText: currentText,
274
- element: elementData
308
+ element: selectedElementData
275
309
  }
276
- }, '*');
310
+ });
311
+ window.parent.postMessage(message, '*');
277
312
  }
278
313
  console.log('Text updated:', newText);
279
314
 
@@ -282,7 +317,8 @@ export function inspectorPlugin() {
282
317
  });
283
318
 
284
319
  textInput.addEventListener('keypress', (e) => {
285
- if (e.key === 'Enter') {
320
+ if (e.key === 'Enter' && !e.shiftKey) {
321
+ e.preventDefault();
286
322
  e.stopPropagation();
287
323
  textSubmit.click();
288
324
  }
@@ -290,19 +326,52 @@ export function inspectorPlugin() {
290
326
 
291
327
  // Prevent input events from bubbling
292
328
  textInput.addEventListener('click', (e) => e.stopPropagation());
329
+
330
+ // Focus text input
331
+ setTimeout(() => textInput.focus(), 100);
332
+
333
+ // Adjust box height
334
+ adjustControlBoxPosition();
335
+ } else if (!show && contentSection) {
336
+ // Remove content input section
337
+ contentSection.remove();
338
+
339
+ // Refocus prompt input
340
+ const promptInput = controlBox.querySelector('#inspector-prompt-input');
341
+ if (promptInput) {
342
+ setTimeout(() => promptInput.focus(), 100);
343
+ }
344
+
345
+ // Adjust box height
346
+ adjustControlBoxPosition();
293
347
  }
348
+ }
349
+
350
+ // Adjust control box position based on content
351
+ function adjustControlBoxPosition() {
352
+ if (!controlBox || !selectedElement) return;
294
353
 
295
- // Prevent prompt input events from bubbling
296
- promptInput.addEventListener('click', (e) => e.stopPropagation());
354
+ const rect = selectedElement.getBoundingClientRect();
355
+ const boxWidth = Math.max(320, Math.min(rect.width, 500));
356
+ const centerLeft = rect.left + (rect.width / 2) - (boxWidth / 2);
357
+ const viewportHeight = window.innerHeight;
358
+ const spaceBelow = viewportHeight - rect.bottom;
359
+ const spaceAbove = rect.top;
297
360
 
298
- // Close button
299
- closeBtn.addEventListener('click', (e) => {
300
- e.stopPropagation();
301
- unpauseInspection();
302
- });
361
+ // Get actual box height
362
+ const boxHeight = controlBox.offsetHeight;
303
363
 
304
- // Focus prompt input
305
- setTimeout(() => promptInput.focus(), 100);
364
+ // Show above if not enough space below
365
+ let topPosition;
366
+ if (spaceBelow < boxHeight + 20 && spaceAbove > spaceBelow) {
367
+ topPosition = rect.top - boxHeight - 10;
368
+ controlBox.setAttribute('data-position', 'above');
369
+ } else {
370
+ topPosition = rect.bottom + 10;
371
+ controlBox.setAttribute('data-position', 'below');
372
+ }
373
+
374
+ controlBox.style.top = topPosition + 'px';
306
375
  }
307
376
 
308
377
  // Pause inspection
@@ -400,8 +469,9 @@ export function inspectorPlugin() {
400
469
 
401
470
  const rect = element.getBoundingClientRect();
402
471
  overlay.style.display = 'block';
403
- overlay.style.top = rect.top + window.scrollY + 'px';
404
- overlay.style.left = rect.left + window.scrollX + 'px';
472
+ // position: fixed uses viewport coordinates, no need for scroll offset
473
+ overlay.style.top = rect.top + 'px';
474
+ overlay.style.left = rect.left + 'px';
405
475
  overlay.style.width = rect.width + 'px';
406
476
  overlay.style.height = rect.height + 'px';
407
477
  }
@@ -417,10 +487,13 @@ export function inspectorPlugin() {
417
487
  function handleMouseMove(e) {
418
488
  if (!inspectMode || isPaused) return;
419
489
 
420
- // Ignore control box and overlay
490
+ // Ignore control box, overlay, and elements with data-inspector-ignore
421
491
  if (e.target.id === 'inspector-control-box' ||
422
492
  e.target.closest('#inspector-control-box') ||
423
- e.target.id === 'inspector-overlay') {
493
+ e.target.id === 'inspector-overlay' ||
494
+ e.target.hasAttribute('data-inspector-ignore') ||
495
+ e.target.closest('[data-inspector-ignore]')) {
496
+ clearHighlight();
424
497
  return;
425
498
  }
426
499
 
@@ -428,20 +501,40 @@ export function inspectorPlugin() {
428
501
  highlightElement(hoveredElement);
429
502
  }
430
503
 
504
+ // Handle scroll - update highlight position
505
+ function handleScroll() {
506
+ if (!inspectMode) return;
507
+
508
+ if (isPaused && selectedElement) {
509
+ // Update overlay for selected element
510
+ highlightElement(selectedElement);
511
+ // Update control box position
512
+ if (controlBox) {
513
+ adjustControlBoxPosition();
514
+ }
515
+ } else if (hoveredElement) {
516
+ // Update overlay for hovered element
517
+ highlightElement(hoveredElement);
518
+ }
519
+ }
520
+
431
521
  // Handle click
432
522
  function handleClick(e) {
433
523
  if (!inspectMode) return;
434
524
 
435
- // Ignore clicks on control box
525
+ // Ignore clicks on control box and elements with data-inspector-ignore
436
526
  if (e.target.id === 'inspector-control-box' ||
437
- e.target.closest('#inspector-control-box')) {
527
+ e.target.closest('#inspector-control-box') ||
528
+ e.target.hasAttribute('data-inspector-ignore') ||
529
+ e.target.closest('[data-inspector-ignore]')) {
438
530
  return;
439
531
  }
440
532
 
441
- // If already paused, ignore clicks (don't select new element)
533
+ // If already paused, unpause first then ignore this click
442
534
  if (isPaused) {
443
535
  e.preventDefault();
444
536
  e.stopPropagation();
537
+ unpauseInspection();
445
538
  return;
446
539
  }
447
540
 
@@ -452,6 +545,10 @@ export function inspectorPlugin() {
452
545
  const fiber = getReactFiber(element);
453
546
  const componentInfo = fiber ? getComponentInfo(fiber) : null;
454
547
 
548
+ // Check if element is a text node
549
+ const isTextNode = element.textContent && element.children.length === 0;
550
+ const textContent = isTextNode ? element.textContent.trim() : '';
551
+
455
552
  const elementData = {
456
553
  tagName: element.tagName,
457
554
  className: element.className,
@@ -462,21 +559,27 @@ export function inspectorPlugin() {
462
559
  left: element.getBoundingClientRect().left,
463
560
  width: element.getBoundingClientRect().width,
464
561
  height: element.getBoundingClientRect().height
465
- }
562
+ },
563
+ isTextNode: isTextNode,
564
+ textContent: textContent
466
565
  };
467
566
 
468
567
  // Send info to parent window
469
568
  if (window.parent !== window) {
470
- window.parent.postMessage({
569
+ // Use JSON.stringify to ensure all properties are serialized correctly
570
+ const message = JSON.stringify({
471
571
  type: 'INSPECTOR_ELEMENT_SELECTED',
472
572
  data: elementData
473
- }, '*');
573
+ });
574
+ window.parent.postMessage(message, '*');
474
575
  }
475
576
 
476
577
  // Log for debugging
477
578
  console.log('Element selected:', {
478
579
  element,
479
- componentInfo
580
+ componentInfo,
581
+ isTextNode,
582
+ textContent
480
583
  });
481
584
 
482
585
  // Pause inspection and show control box
@@ -492,6 +595,7 @@ export function inspectorPlugin() {
492
595
  document.body.style.cursor = 'crosshair';
493
596
  document.addEventListener('mousemove', handleMouseMove, true);
494
597
  document.addEventListener('click', handleClick, true);
598
+ document.addEventListener('scroll', handleScroll, true);
495
599
  } else {
496
600
  // Clean up everything
497
601
  clearHighlight();
@@ -499,6 +603,7 @@ export function inspectorPlugin() {
499
603
  document.body.style.cursor = '';
500
604
  document.removeEventListener('mousemove', handleMouseMove, true);
501
605
  document.removeEventListener('click', handleClick, true);
606
+ document.removeEventListener('scroll', handleScroll, true);
502
607
  }
503
608
  }
504
609
 
@@ -511,6 +616,13 @@ export function inspectorPlugin() {
511
616
  if (event.data.labels) {
512
617
  labels = { ...labels, ...event.data.labels };
513
618
  }
619
+
620
+ // Update theme if provided
621
+ if (event.data.theme) {
622
+ theme = { ...theme, ...event.data.theme };
623
+ }
624
+ } else if (event.data.type === 'SHOW_CONTENT_INPUT') {
625
+ toggleContentInput(event.data.show);
514
626
  }
515
627
  });
516
628
 
@@ -523,7 +635,7 @@ export function inspectorPlugin() {
523
635
  lastUrl = newUrl;
524
636
 
525
637
  if (window.parent !== window) {
526
- window.parent.postMessage({
638
+ const message = JSON.stringify({
527
639
  type: 'URL_CHANGED',
528
640
  data: {
529
641
  url: newUrl,
@@ -531,7 +643,8 @@ export function inspectorPlugin() {
531
643
  search: location.search,
532
644
  hash: location.hash
533
645
  }
534
- }, '*');
646
+ });
647
+ window.parent.postMessage(message, '*');
535
648
  }
536
649
  }
537
650
  }
@@ -564,10 +677,11 @@ export function inspectorPlugin() {
564
677
 
565
678
  function sendError(errorData) {
566
679
  if (window.parent !== window) {
567
- window.parent.postMessage({
680
+ const message = JSON.stringify({
568
681
  type: 'INSPECTOR_ERROR',
569
682
  data: errorData
570
- }, '*');
683
+ });
684
+ window.parent.postMessage(message, '*');
571
685
  }
572
686
  // Use original console.error to avoid infinite loop
573
687
  originalConsoleError.call(console, '🔍 Inspector Error:', errorData);
package/dist/types.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  /**
2
- * Shared types for @promake/inspector
2
+ * Shared types for @promakeai/inspector
3
+ *
4
+ * Bu dosya inspector için kullanılan tüm type'ları içerir.
5
+ * Hook ve plugin arasında paylaşılan type'lar burada tanımlanır.
3
6
  */
4
7
  export interface ComponentInfo {
5
8
  componentName: string;
@@ -19,6 +22,8 @@ export interface SelectedElementData {
19
22
  id: string;
20
23
  component: ComponentInfo | null;
21
24
  position: ElementPosition;
25
+ isTextNode?: boolean;
26
+ textContent?: string;
22
27
  }
23
28
  export interface UrlChangeData {
24
29
  url: string;
@@ -50,6 +55,18 @@ export interface InspectorLabels {
50
55
  updateText?: string;
51
56
  promptPlaceholder?: string;
52
57
  }
58
+ export interface InspectorTheme {
59
+ backgroundColor?: string;
60
+ textColor?: string;
61
+ buttonColor?: string;
62
+ buttonTextColor?: string;
63
+ inputBackgroundColor?: string;
64
+ inputTextColor?: string;
65
+ inputBorderColor?: string;
66
+ }
67
+ export interface ContentInputRequestData {
68
+ show: boolean;
69
+ }
53
70
  export interface InspectorCallbacks {
54
71
  onElementSelected?: (data: SelectedElementData) => void;
55
72
  onUrlChange?: (data: UrlChangeData) => void;
@@ -62,5 +79,6 @@ export interface UseInspectorReturn {
62
79
  toggleInspector: (active?: boolean) => void;
63
80
  startInspecting: () => void;
64
81
  stopInspecting: () => void;
82
+ showContentInput: (show: boolean) => void;
65
83
  }
66
84
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAGD,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAGD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAGD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAGD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAGD,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACxD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACxD,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;CACrC;AAGD,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAGD,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAGD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAGD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAGD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAID,MAAM,WAAW,cAAc;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAGD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,OAAO,CAAC;CACf;AAGD,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACxD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACxD,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;CACrC;AAGD,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3C"}
package/dist/types.js CHANGED
@@ -1,4 +1,7 @@
1
1
  /**
2
- * Shared types for @promake/inspector
2
+ * Shared types for @promakeai/inspector
3
+ *
4
+ * Bu dosya inspector için kullanılan tüm type'ları içerir.
5
+ * Hook ve plugin arasında paylaşılan type'lar burada tanımlanır.
3
6
  */
4
7
  export {};
package/package.json CHANGED
@@ -1,9 +1,18 @@
1
1
  {
2
2
  "name": "@promakeai/inspector",
3
- "version": "0.0.1",
3
+ "version": "0.0.4",
4
4
  "description": "Visual element inspector for React apps in iframe with AI prompt support",
5
5
  "author": "Promake",
6
+ "license": "MIT",
6
7
  "type": "module",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/promakeai/inspector.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/promakeai/inspector/issues"
14
+ },
15
+ "homepage": "https://github.com/promakeai/inspector#readme",
7
16
  "main": "./dist/hook.js",
8
17
  "module": "./dist/hook.js",
9
18
  "types": "./dist/hook.d.ts",
@@ -24,7 +33,8 @@
24
33
  ],
25
34
  "scripts": {
26
35
  "build": "tsc && tsc -p tsconfig.plugin.json",
27
- "prepublishOnly": "npm run build"
36
+ "prepublishOnly": "npm run build",
37
+ "release": "npm run build && npm publish --access public"
28
38
  },
29
39
  "keywords": [
30
40
  "vite",
@@ -38,8 +48,8 @@
38
48
  "prompt"
39
49
  ],
40
50
  "peerDependencies": {
41
- "react": "^18.0.0",
42
- "vite": "^5.0.0"
51
+ "react": ">18.0.0",
52
+ "vite": ">5.0.0"
43
53
  },
44
54
  "devDependencies": {
45
55
  "@types/react": "^18.2.0",