@promakeai/inspector-hook 1.1.1 → 1.2.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/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -1
- package/dist/utils/jsxUpdater.d.ts +101 -0
- package/dist/utils/jsxUpdater.d.ts.map +1 -1
- package/dist/utils/jsxUpdater.js +511 -9
- package/package.json +54 -54
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RefObject } from "react";
|
|
2
2
|
import type { InspectorCallbacks, InspectorLabels, InspectorTheme, UseInspectorReturn } from "@promakeai/inspector-types";
|
|
3
3
|
export declare function useInspector(iframeRef: RefObject<HTMLIFrameElement>, callbacks?: InspectorCallbacks, labels?: InspectorLabels, theme?: InspectorTheme): UseInspectorReturn;
|
|
4
|
-
export type { ComponentInfo, ElementPosition, SelectedElementData, UrlChangeData, PromptSubmittedData, TextUpdatedData, ImageUpdatedData, StyleChanges, StyleUpdatedData, ErrorData, HighlightOptions, ElementInfoData, InspectorLabels, InspectorTheme, ContentInputRequestData, InspectorCallbacks, UseInspectorReturn, } from "@promakeai/inspector-types";
|
|
5
|
-
export { updateJSXSource } from "./utils/jsxUpdater.js";
|
|
6
|
-
export type { UpdateJSXSourceOptions, UpdateJSXSourceResult, } from "./utils/jsxUpdater.js";
|
|
4
|
+
export type { ComponentInfo, ElementPosition, SelectedElementData, UrlChangeData, PromptSubmittedData, TextUpdatedData, ImageUpdatedData, StyleChanges, StyleUpdatedData, ErrorData, HighlightOptions, ElementInfoData, ElementDeletedData, ElementDuplicatedData, ChangeType, ChangeHistoryEntry, InspectorChange, InspectorChangeType, InspectorChangesSavedData, InspectorLabels, InspectorTheme, ContentInputRequestData, InspectorCallbacks, UseInspectorReturn, } from "@promakeai/inspector-types";
|
|
5
|
+
export { updateJSXSource, deleteJSXElement, duplicateJSXElement, updateTextContent, applyChangesToJSXSource, } from "./utils/jsxUpdater.js";
|
|
6
|
+
export type { UpdateJSXSourceOptions, UpdateJSXSourceResult, DeleteJSXElementOptions, DuplicateJSXElementOptions, UpdateTextContentOptions, ApplyChangesOptions, ApplyChangesResult, ChangeApplicationResult, } from "./utils/jsxUpdater.js";
|
|
7
7
|
export { inspectorHookPlugin } from "./vite-plugin.js";
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,kBAAkB,EAcnB,MAAM,4BAA4B,CAAC;AAsGpC,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,CAuSpB;AAGD,YAAY,EACV,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EACzB,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,16 @@ export function useInspector(iframeRef, callbacks, labels, theme) {
|
|
|
42
42
|
const stopInspecting = useCallback(() => {
|
|
43
43
|
toggleInspector(false);
|
|
44
44
|
}, [toggleInspector]);
|
|
45
|
+
/**
|
|
46
|
+
* Force close inspector - hard reset for emergencies
|
|
47
|
+
* Use when inspector becomes unresponsive
|
|
48
|
+
*/
|
|
49
|
+
const forceCloseInspector = useCallback(() => {
|
|
50
|
+
setIsInspecting(false);
|
|
51
|
+
sendMessage({
|
|
52
|
+
type: "FORCE_CLOSE_INSPECTOR",
|
|
53
|
+
});
|
|
54
|
+
}, [sendMessage]);
|
|
45
55
|
/**
|
|
46
56
|
* Show or hide content input
|
|
47
57
|
*/
|
|
@@ -71,6 +81,15 @@ export function useInspector(iframeRef, callbacks, labels, theme) {
|
|
|
71
81
|
show: show,
|
|
72
82
|
});
|
|
73
83
|
}, [sendMessage]);
|
|
84
|
+
/**
|
|
85
|
+
* Show or hide actions tab (delete, duplicate, etc.)
|
|
86
|
+
*/
|
|
87
|
+
const showActionsTab = useCallback((show) => {
|
|
88
|
+
sendMessage({
|
|
89
|
+
type: "SHOW_ACTIONS_TAB",
|
|
90
|
+
show: show,
|
|
91
|
+
});
|
|
92
|
+
}, [sendMessage]);
|
|
74
93
|
/**
|
|
75
94
|
* Show or hide "Built with Promake" badge
|
|
76
95
|
*/
|
|
@@ -160,6 +179,18 @@ export function useInspector(iframeRef, callbacks, labels, theme) {
|
|
|
160
179
|
case "ELEMENT_INFO_RESPONSE":
|
|
161
180
|
callbacks?.onElementInfoReceived?.(messageData.data);
|
|
162
181
|
break;
|
|
182
|
+
case "INSPECTOR_ELEMENT_DELETED":
|
|
183
|
+
callbacks?.onElementDeleted?.(messageData.data);
|
|
184
|
+
break;
|
|
185
|
+
case "INSPECTOR_ELEMENT_DUPLICATED":
|
|
186
|
+
callbacks?.onElementDuplicated?.(messageData.data);
|
|
187
|
+
break;
|
|
188
|
+
case "INSPECTOR_CHANGES_SAVED":
|
|
189
|
+
callbacks?.onChangesSaved?.(messageData.data);
|
|
190
|
+
break;
|
|
191
|
+
case "INSPECTOR_GO_TO_CODE":
|
|
192
|
+
callbacks?.onGoToCode?.(messageData.data);
|
|
193
|
+
break;
|
|
163
194
|
default:
|
|
164
195
|
// Unknown message type - ignore
|
|
165
196
|
break;
|
|
@@ -190,9 +221,11 @@ export function useInspector(iframeRef, callbacks, labels, theme) {
|
|
|
190
221
|
toggleInspector,
|
|
191
222
|
startInspecting,
|
|
192
223
|
stopInspecting,
|
|
224
|
+
forceCloseInspector,
|
|
193
225
|
showContentInput,
|
|
194
226
|
showImageInput,
|
|
195
227
|
showStyleEditor,
|
|
228
|
+
showActionsTab,
|
|
196
229
|
setBadgeVisible,
|
|
197
230
|
highlightElement,
|
|
198
231
|
getElementByInspectorId,
|
|
@@ -200,6 +233,6 @@ export function useInspector(iframeRef, callbacks, labels, theme) {
|
|
|
200
233
|
};
|
|
201
234
|
}
|
|
202
235
|
// Export utility functions
|
|
203
|
-
export { updateJSXSource } from "./utils/jsxUpdater.js";
|
|
236
|
+
export { updateJSXSource, deleteJSXElement, duplicateJSXElement, updateTextContent, applyChangesToJSXSource, } from "./utils/jsxUpdater.js";
|
|
204
237
|
// Export Vite plugin
|
|
205
238
|
export { inspectorHookPlugin } from "./vite-plugin.js";
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Lightweight regex-based utility for updating styles and classNames in JSX/TSX source code
|
|
4
4
|
* No Babel dependencies - works perfectly in browser environments!
|
|
5
5
|
*/
|
|
6
|
+
import type { InspectorChange, InspectorChangeType } from "@promakeai/inspector-types";
|
|
6
7
|
export interface UpdateJSXSourceOptions {
|
|
7
8
|
sourceCode: string;
|
|
8
9
|
lineNumber: number;
|
|
@@ -16,6 +17,18 @@ export interface UpdateJSXSourceResult {
|
|
|
16
17
|
code: string;
|
|
17
18
|
message?: string;
|
|
18
19
|
}
|
|
20
|
+
export interface DeleteJSXElementOptions {
|
|
21
|
+
sourceCode: string;
|
|
22
|
+
lineNumber: number;
|
|
23
|
+
columnNumber: number;
|
|
24
|
+
tagName: string;
|
|
25
|
+
}
|
|
26
|
+
export interface DuplicateJSXElementOptions {
|
|
27
|
+
sourceCode: string;
|
|
28
|
+
lineNumber: number;
|
|
29
|
+
columnNumber: number;
|
|
30
|
+
tagName: string;
|
|
31
|
+
}
|
|
19
32
|
/**
|
|
20
33
|
* Update JSX source code with new styles and/or className
|
|
21
34
|
*
|
|
@@ -36,4 +49,92 @@ export interface UpdateJSXSourceResult {
|
|
|
36
49
|
* ```
|
|
37
50
|
*/
|
|
38
51
|
export declare function updateJSXSource(options: UpdateJSXSourceOptions): UpdateJSXSourceResult;
|
|
52
|
+
/**
|
|
53
|
+
* Delete a JSX element from source code
|
|
54
|
+
*
|
|
55
|
+
* @param options - Configuration options for deletion
|
|
56
|
+
* @returns Result object with success status, updated code, and optional message
|
|
57
|
+
*/
|
|
58
|
+
export declare function deleteJSXElement(options: DeleteJSXElementOptions): UpdateJSXSourceResult;
|
|
59
|
+
/**
|
|
60
|
+
* Duplicate a JSX element in source code (inserts copy after the original)
|
|
61
|
+
*
|
|
62
|
+
* @param options - Configuration options for duplication
|
|
63
|
+
* @returns Result object with success status, updated code, and optional message
|
|
64
|
+
*/
|
|
65
|
+
export declare function duplicateJSXElement(options: DuplicateJSXElementOptions): UpdateJSXSourceResult;
|
|
66
|
+
/**
|
|
67
|
+
* Options for updating text content
|
|
68
|
+
*/
|
|
69
|
+
export interface UpdateTextContentOptions {
|
|
70
|
+
sourceCode: string;
|
|
71
|
+
lineNumber: number;
|
|
72
|
+
columnNumber: number;
|
|
73
|
+
tagName: string;
|
|
74
|
+
newText: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Update the text content of a JSX element
|
|
78
|
+
* Only works if the element contains pure text (no JS expressions or nested elements)
|
|
79
|
+
*
|
|
80
|
+
* @param options - Configuration options for the text update
|
|
81
|
+
* @returns Result object with success status, updated code, and optional message
|
|
82
|
+
*/
|
|
83
|
+
export declare function updateTextContent(options: UpdateTextContentOptions): UpdateJSXSourceResult;
|
|
84
|
+
/**
|
|
85
|
+
* Options for applying changes to JSX source
|
|
86
|
+
*/
|
|
87
|
+
export interface ApplyChangesOptions {
|
|
88
|
+
sourceCode: string;
|
|
89
|
+
changes: InspectorChange[];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Result of a single change application
|
|
93
|
+
*/
|
|
94
|
+
export interface ChangeApplicationResult {
|
|
95
|
+
changeId: string;
|
|
96
|
+
type: InspectorChangeType;
|
|
97
|
+
success: boolean;
|
|
98
|
+
message?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Result of applying all changes
|
|
102
|
+
*/
|
|
103
|
+
export interface ApplyChangesResult {
|
|
104
|
+
success: boolean;
|
|
105
|
+
code: string;
|
|
106
|
+
results: ChangeApplicationResult[];
|
|
107
|
+
summary: {
|
|
108
|
+
total: number;
|
|
109
|
+
successful: number;
|
|
110
|
+
failed: number;
|
|
111
|
+
skipped: number;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Apply a collection of InspectorChange objects to JSX source code
|
|
116
|
+
*
|
|
117
|
+
* This function processes changes in a logical order:
|
|
118
|
+
* 1. Groups changes by element
|
|
119
|
+
* 2. For each element:
|
|
120
|
+
* - If delete: deletes the element, skips other changes for that element
|
|
121
|
+
* - If duplicate: applies styles/text first, then duplicates
|
|
122
|
+
* - Merges all style changes into single update
|
|
123
|
+
* - Applies text changes (only if pure text)
|
|
124
|
+
*
|
|
125
|
+
* @param options - Source code and changes to apply
|
|
126
|
+
* @returns Result with updated code and detailed results for each change
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const result = applyChangesToJSXSource({
|
|
131
|
+
* sourceCode: '<div>Hello</div>',
|
|
132
|
+
* changes: [
|
|
133
|
+
* { type: 'singleStyle', singleStyle: { property: 'color', currentValue: 'red' }, ... },
|
|
134
|
+
* { type: 'text', text: { current: 'World' }, ... }
|
|
135
|
+
* ]
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export declare function applyChangesToJSXSource(options: ApplyChangesOptions): ApplyChangesResult;
|
|
39
140
|
//# sourceMappingURL=jsxUpdater.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsxUpdater.d.ts","sourceRoot":"","sources":["../../src/utils/jsxUpdater.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA4YD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,qBAAqB,
|
|
1
|
+
{"version":3,"file":"jsxUpdater.d.ts","sourceRoot":"","sources":["../../src/utils/jsxUpdater.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EAEpB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AA4YD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,qBAAqB,CAmFvB;AAoGD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,uBAAuB,GAC/B,qBAAqB,CAqDvB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,qBAAqB,CAmDvB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAmBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,wBAAwB,GAChC,qBAAqB,CA+FvB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AA4CD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,CA2MpB"}
|
package/dist/utils/jsxUpdater.js
CHANGED
|
@@ -347,14 +347,9 @@ export function updateJSXSource(options) {
|
|
|
347
347
|
message: `Could not find JSX element <${tagName}> at line ${lineNumber}, column ${columnNumber}`,
|
|
348
348
|
};
|
|
349
349
|
}
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
success: false,
|
|
354
|
-
code: sourceCode,
|
|
355
|
-
message: `Tag name mismatch: expected <${tagName}>, found <${tagInfo.foundTagName}>`,
|
|
356
|
-
};
|
|
357
|
-
}
|
|
350
|
+
// Check for tag name mismatch (warning only - continue anyway)
|
|
351
|
+
// This handles cases like Link component rendering as <a> in DOM
|
|
352
|
+
const tagNameMismatch = tagInfo.foundTagName.toLowerCase() !== tagName.toLowerCase();
|
|
358
353
|
// Validate that the element has proper closing tag
|
|
359
354
|
if (!hasProperClosingTag(sourceCode, tagInfo.start, tagInfo.end, tagInfo.foundTagName)) {
|
|
360
355
|
return {
|
|
@@ -376,10 +371,14 @@ export function updateJSXSource(options) {
|
|
|
376
371
|
const updatedCode = sourceCode.slice(0, tagInfo.start) +
|
|
377
372
|
updatedTagContent +
|
|
378
373
|
sourceCode.slice(tagInfo.end);
|
|
374
|
+
// Include warning in message if tag names didn't match
|
|
375
|
+
const message = tagNameMismatch
|
|
376
|
+
? `JSX source updated successfully (note: expected <${tagName}>, found <${tagInfo.foundTagName}>)`
|
|
377
|
+
: "JSX source updated successfully";
|
|
379
378
|
return {
|
|
380
379
|
success: true,
|
|
381
380
|
code: updatedCode,
|
|
382
|
-
message
|
|
381
|
+
message,
|
|
383
382
|
};
|
|
384
383
|
}
|
|
385
384
|
catch (error) {
|
|
@@ -392,3 +391,506 @@ export function updateJSXSource(options) {
|
|
|
392
391
|
};
|
|
393
392
|
}
|
|
394
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* Find the full JSX element boundaries (from opening tag to closing tag)
|
|
396
|
+
*/
|
|
397
|
+
function findFullJSXElementBoundaries(sourceCode, lineNumber, columnNumber, tagName) {
|
|
398
|
+
// First find the opening tag
|
|
399
|
+
const tagInfo = findJSXTagAtPosition(sourceCode, lineNumber, columnNumber, tagName);
|
|
400
|
+
if (!tagInfo) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
// Check if self-closing
|
|
404
|
+
if (tagInfo.content.trim().endsWith("/>")) {
|
|
405
|
+
return {
|
|
406
|
+
start: tagInfo.start,
|
|
407
|
+
end: tagInfo.end,
|
|
408
|
+
content: tagInfo.content,
|
|
409
|
+
isSelfClosing: true,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
// Find the matching closing tag
|
|
413
|
+
const afterOpening = sourceCode.slice(tagInfo.end);
|
|
414
|
+
let depth = 1;
|
|
415
|
+
let i = 0;
|
|
416
|
+
let inString = false;
|
|
417
|
+
let stringChar = "";
|
|
418
|
+
while (i < afterOpening.length && depth > 0) {
|
|
419
|
+
const char = afterOpening[i];
|
|
420
|
+
const prevChar = i > 0 ? afterOpening[i - 1] : "";
|
|
421
|
+
// Handle strings
|
|
422
|
+
if ((char === '"' || char === "'" || char === "`") && prevChar !== "\\") {
|
|
423
|
+
if (!inString) {
|
|
424
|
+
inString = true;
|
|
425
|
+
stringChar = char;
|
|
426
|
+
}
|
|
427
|
+
else if (char === stringChar) {
|
|
428
|
+
inString = false;
|
|
429
|
+
stringChar = "";
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
if (!inString && char === "<") {
|
|
433
|
+
// Check for opening or closing tag
|
|
434
|
+
const remainingCode = afterOpening.slice(i);
|
|
435
|
+
const tagMatch = remainingCode.match(/^<\/?([A-Za-z_$][A-Za-z0-9_$]*)/);
|
|
436
|
+
if (tagMatch) {
|
|
437
|
+
const isClosing = remainingCode.startsWith("</");
|
|
438
|
+
const foundTag = tagMatch[1];
|
|
439
|
+
if (isClosing && foundTag === tagInfo.foundTagName) {
|
|
440
|
+
depth--;
|
|
441
|
+
if (depth === 0) {
|
|
442
|
+
// Find end of closing tag
|
|
443
|
+
const closingEnd = remainingCode.indexOf(">");
|
|
444
|
+
if (closingEnd !== -1) {
|
|
445
|
+
const fullEnd = tagInfo.end + i + closingEnd + 1;
|
|
446
|
+
return {
|
|
447
|
+
start: tagInfo.start,
|
|
448
|
+
end: fullEnd,
|
|
449
|
+
content: sourceCode.slice(tagInfo.start, fullEnd),
|
|
450
|
+
isSelfClosing: false,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
else if (!isClosing && foundTag === tagInfo.foundTagName) {
|
|
456
|
+
// Check if self-closing
|
|
457
|
+
const tagEndMatch = remainingCode.match(/^<[^>]+?(\/?)>/);
|
|
458
|
+
if (tagEndMatch && !tagEndMatch[1]) {
|
|
459
|
+
depth++;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
i++;
|
|
465
|
+
}
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Delete a JSX element from source code
|
|
470
|
+
*
|
|
471
|
+
* @param options - Configuration options for deletion
|
|
472
|
+
* @returns Result object with success status, updated code, and optional message
|
|
473
|
+
*/
|
|
474
|
+
export function deleteJSXElement(options) {
|
|
475
|
+
const { sourceCode, lineNumber, columnNumber, tagName } = options;
|
|
476
|
+
try {
|
|
477
|
+
const elementBounds = findFullJSXElementBoundaries(sourceCode, lineNumber, columnNumber, tagName);
|
|
478
|
+
if (!elementBounds) {
|
|
479
|
+
return {
|
|
480
|
+
success: false,
|
|
481
|
+
code: sourceCode,
|
|
482
|
+
message: `Could not find JSX element <${tagName}> at line ${lineNumber}, column ${columnNumber}`,
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
// Get content before and after the element
|
|
486
|
+
let before = sourceCode.slice(0, elementBounds.start);
|
|
487
|
+
let after = sourceCode.slice(elementBounds.end);
|
|
488
|
+
// Clean up whitespace - remove trailing whitespace from before and leading newline from after
|
|
489
|
+
// This prevents leaving empty lines
|
|
490
|
+
const trailingWhitespaceMatch = before.match(/(\s*)$/);
|
|
491
|
+
const leadingWhitespaceMatch = after.match(/^(\s*\n)?/);
|
|
492
|
+
if (trailingWhitespaceMatch && leadingWhitespaceMatch) {
|
|
493
|
+
// If there's a newline after, remove the trailing whitespace before
|
|
494
|
+
if (leadingWhitespaceMatch[0].includes("\n")) {
|
|
495
|
+
before = before.replace(/[ \t]*$/, "");
|
|
496
|
+
after = after.replace(/^[ \t]*\n/, "\n");
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
const updatedCode = before + after;
|
|
500
|
+
return {
|
|
501
|
+
success: true,
|
|
502
|
+
code: updatedCode,
|
|
503
|
+
message: `JSX element <${tagName}> deleted successfully`,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
catch (error) {
|
|
507
|
+
return {
|
|
508
|
+
success: false,
|
|
509
|
+
code: sourceCode,
|
|
510
|
+
message: error instanceof Error
|
|
511
|
+
? error.message
|
|
512
|
+
: "Unknown error occurred during JSX deletion",
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Duplicate a JSX element in source code (inserts copy after the original)
|
|
518
|
+
*
|
|
519
|
+
* @param options - Configuration options for duplication
|
|
520
|
+
* @returns Result object with success status, updated code, and optional message
|
|
521
|
+
*/
|
|
522
|
+
export function duplicateJSXElement(options) {
|
|
523
|
+
const { sourceCode, lineNumber, columnNumber, tagName } = options;
|
|
524
|
+
try {
|
|
525
|
+
const elementBounds = findFullJSXElementBoundaries(sourceCode, lineNumber, columnNumber, tagName);
|
|
526
|
+
if (!elementBounds) {
|
|
527
|
+
return {
|
|
528
|
+
success: false,
|
|
529
|
+
code: sourceCode,
|
|
530
|
+
message: `Could not find JSX element <${tagName}> at line ${lineNumber}, column ${columnNumber}`,
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
// Get the indentation of the original element
|
|
534
|
+
const beforeElement = sourceCode.slice(0, elementBounds.start);
|
|
535
|
+
const lastNewline = beforeElement.lastIndexOf("\n");
|
|
536
|
+
const indentation = lastNewline !== -1
|
|
537
|
+
? beforeElement.slice(lastNewline + 1).match(/^(\s*)/)?.[1] || ""
|
|
538
|
+
: "";
|
|
539
|
+
// Create the duplicated element with proper indentation
|
|
540
|
+
const duplicatedElement = "\n" + indentation + elementBounds.content;
|
|
541
|
+
// Insert the duplicate after the original
|
|
542
|
+
const updatedCode = sourceCode.slice(0, elementBounds.end) +
|
|
543
|
+
duplicatedElement +
|
|
544
|
+
sourceCode.slice(elementBounds.end);
|
|
545
|
+
return {
|
|
546
|
+
success: true,
|
|
547
|
+
code: updatedCode,
|
|
548
|
+
message: `JSX element <${tagName}> duplicated successfully`,
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
catch (error) {
|
|
552
|
+
return {
|
|
553
|
+
success: false,
|
|
554
|
+
code: sourceCode,
|
|
555
|
+
message: error instanceof Error
|
|
556
|
+
? error.message
|
|
557
|
+
: "Unknown error occurred during JSX duplication",
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Check if element content is pure text (no JS expressions or nested elements)
|
|
563
|
+
*/
|
|
564
|
+
function isPureTextContent(content) {
|
|
565
|
+
// Check for JSX expressions {something}
|
|
566
|
+
if (content.includes("{") && content.includes("}")) {
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
// Check for nested elements <something>
|
|
570
|
+
if (/<[A-Za-z_$][A-Za-z0-9_$]*/.test(content)) {
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Update the text content of a JSX element
|
|
577
|
+
* Only works if the element contains pure text (no JS expressions or nested elements)
|
|
578
|
+
*
|
|
579
|
+
* @param options - Configuration options for the text update
|
|
580
|
+
* @returns Result object with success status, updated code, and optional message
|
|
581
|
+
*/
|
|
582
|
+
export function updateTextContent(options) {
|
|
583
|
+
const { sourceCode, lineNumber, columnNumber, tagName, newText } = options;
|
|
584
|
+
try {
|
|
585
|
+
// Find the full element boundaries
|
|
586
|
+
const elementBounds = findFullJSXElementBoundaries(sourceCode, lineNumber, columnNumber, tagName);
|
|
587
|
+
if (!elementBounds) {
|
|
588
|
+
return {
|
|
589
|
+
success: false,
|
|
590
|
+
code: sourceCode,
|
|
591
|
+
message: `Could not find JSX element <${tagName}> at line ${lineNumber}, column ${columnNumber}`,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
// Self-closing elements can't have text content
|
|
595
|
+
if (elementBounds.isSelfClosing) {
|
|
596
|
+
return {
|
|
597
|
+
success: false,
|
|
598
|
+
code: sourceCode,
|
|
599
|
+
message: `Element <${tagName}> is self-closing and cannot have text content`,
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
// Find the opening tag end and closing tag start
|
|
603
|
+
const tagInfo = findJSXTagAtPosition(sourceCode, lineNumber, columnNumber, tagName);
|
|
604
|
+
if (!tagInfo) {
|
|
605
|
+
return {
|
|
606
|
+
success: false,
|
|
607
|
+
code: sourceCode,
|
|
608
|
+
message: `Could not find opening tag for <${tagName}>`,
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
// Use the found tag name for closing tag search (handles Link -> a mapping etc.)
|
|
612
|
+
const actualTagName = tagInfo.foundTagName;
|
|
613
|
+
// Extract content between opening and closing tag
|
|
614
|
+
const closingTagPattern = new RegExp(`</${actualTagName}\\s*>`);
|
|
615
|
+
const afterOpening = sourceCode.slice(tagInfo.end);
|
|
616
|
+
const closingMatch = closingTagPattern.exec(afterOpening);
|
|
617
|
+
if (!closingMatch) {
|
|
618
|
+
return {
|
|
619
|
+
success: false,
|
|
620
|
+
code: sourceCode,
|
|
621
|
+
message: `Could not find closing tag for <${actualTagName}>`,
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
const contentStart = tagInfo.end;
|
|
625
|
+
const contentEnd = tagInfo.end + closingMatch.index;
|
|
626
|
+
const currentContent = sourceCode.slice(contentStart, contentEnd);
|
|
627
|
+
// Check if content is pure text
|
|
628
|
+
if (!isPureTextContent(currentContent)) {
|
|
629
|
+
return {
|
|
630
|
+
success: false,
|
|
631
|
+
code: sourceCode,
|
|
632
|
+
message: `Element <${actualTagName}> contains JS expressions or nested elements. Text update skipped.`,
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
// Replace the content
|
|
636
|
+
const updatedCode = sourceCode.slice(0, contentStart) +
|
|
637
|
+
newText +
|
|
638
|
+
sourceCode.slice(contentEnd);
|
|
639
|
+
return {
|
|
640
|
+
success: true,
|
|
641
|
+
code: updatedCode,
|
|
642
|
+
message: `Text content of <${actualTagName}> updated successfully`,
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
catch (error) {
|
|
646
|
+
return {
|
|
647
|
+
success: false,
|
|
648
|
+
code: sourceCode,
|
|
649
|
+
message: error instanceof Error
|
|
650
|
+
? error.message
|
|
651
|
+
: "Unknown error occurred during text update",
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Group changes by element ID
|
|
657
|
+
*/
|
|
658
|
+
function groupChangesByElement(changes) {
|
|
659
|
+
const grouped = new Map();
|
|
660
|
+
for (const change of changes) {
|
|
661
|
+
const elementId = change.element.id || change.element.selector || "unknown";
|
|
662
|
+
const existing = grouped.get(elementId) || [];
|
|
663
|
+
existing.push(change);
|
|
664
|
+
grouped.set(elementId, existing);
|
|
665
|
+
}
|
|
666
|
+
return grouped;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Merge multiple style changes into a single styles object
|
|
670
|
+
*/
|
|
671
|
+
function mergeStyleChanges(changes) {
|
|
672
|
+
const mergedStyles = {};
|
|
673
|
+
for (const change of changes) {
|
|
674
|
+
if (change.type === "singleStyle" && change.singleStyle) {
|
|
675
|
+
const { property, currentValue } = change.singleStyle;
|
|
676
|
+
mergedStyles[property] = currentValue;
|
|
677
|
+
}
|
|
678
|
+
else if (change.type === "style" && change.style?.current) {
|
|
679
|
+
// Merge all current styles
|
|
680
|
+
const currentStyles = change.style.current;
|
|
681
|
+
for (const [key, value] of Object.entries(currentStyles)) {
|
|
682
|
+
if (value !== undefined && value !== "") {
|
|
683
|
+
mergedStyles[key] = value;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return mergedStyles;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Apply a collection of InspectorChange objects to JSX source code
|
|
692
|
+
*
|
|
693
|
+
* This function processes changes in a logical order:
|
|
694
|
+
* 1. Groups changes by element
|
|
695
|
+
* 2. For each element:
|
|
696
|
+
* - If delete: deletes the element, skips other changes for that element
|
|
697
|
+
* - If duplicate: applies styles/text first, then duplicates
|
|
698
|
+
* - Merges all style changes into single update
|
|
699
|
+
* - Applies text changes (only if pure text)
|
|
700
|
+
*
|
|
701
|
+
* @param options - Source code and changes to apply
|
|
702
|
+
* @returns Result with updated code and detailed results for each change
|
|
703
|
+
*
|
|
704
|
+
* @example
|
|
705
|
+
* ```typescript
|
|
706
|
+
* const result = applyChangesToJSXSource({
|
|
707
|
+
* sourceCode: '<div>Hello</div>',
|
|
708
|
+
* changes: [
|
|
709
|
+
* { type: 'singleStyle', singleStyle: { property: 'color', currentValue: 'red' }, ... },
|
|
710
|
+
* { type: 'text', text: { current: 'World' }, ... }
|
|
711
|
+
* ]
|
|
712
|
+
* });
|
|
713
|
+
* ```
|
|
714
|
+
*/
|
|
715
|
+
export function applyChangesToJSXSource(options) {
|
|
716
|
+
const { sourceCode, changes } = options;
|
|
717
|
+
const results = [];
|
|
718
|
+
let currentCode = sourceCode;
|
|
719
|
+
let successful = 0;
|
|
720
|
+
let failed = 0;
|
|
721
|
+
let skipped = 0;
|
|
722
|
+
// Group changes by element
|
|
723
|
+
const groupedChanges = groupChangesByElement(changes);
|
|
724
|
+
// Process each element's changes
|
|
725
|
+
for (const [elementId, elementChanges] of groupedChanges) {
|
|
726
|
+
// Check if there's a delete change for this element
|
|
727
|
+
const deleteChange = elementChanges.find((c) => c.type === "delete");
|
|
728
|
+
if (deleteChange) {
|
|
729
|
+
// If delete exists, delete the element and skip all other changes for this element
|
|
730
|
+
const element = deleteChange.element;
|
|
731
|
+
if (element.lineNumber && element.columnNumber !== undefined) {
|
|
732
|
+
const deleteResult = deleteJSXElement({
|
|
733
|
+
sourceCode: currentCode,
|
|
734
|
+
lineNumber: element.lineNumber,
|
|
735
|
+
columnNumber: element.columnNumber,
|
|
736
|
+
tagName: element.tagName,
|
|
737
|
+
});
|
|
738
|
+
results.push({
|
|
739
|
+
changeId: deleteChange.id,
|
|
740
|
+
type: "delete",
|
|
741
|
+
success: deleteResult.success,
|
|
742
|
+
message: deleteResult.message,
|
|
743
|
+
});
|
|
744
|
+
if (deleteResult.success) {
|
|
745
|
+
currentCode = deleteResult.code;
|
|
746
|
+
successful++;
|
|
747
|
+
}
|
|
748
|
+
else {
|
|
749
|
+
failed++;
|
|
750
|
+
}
|
|
751
|
+
// Skip other changes for this element
|
|
752
|
+
for (const change of elementChanges) {
|
|
753
|
+
if (change.id !== deleteChange.id) {
|
|
754
|
+
results.push({
|
|
755
|
+
changeId: change.id,
|
|
756
|
+
type: change.type,
|
|
757
|
+
success: false,
|
|
758
|
+
message: "Skipped: element was deleted",
|
|
759
|
+
});
|
|
760
|
+
skipped++;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
else {
|
|
766
|
+
results.push({
|
|
767
|
+
changeId: deleteChange.id,
|
|
768
|
+
type: "delete",
|
|
769
|
+
success: false,
|
|
770
|
+
message: "Missing line/column number for delete operation",
|
|
771
|
+
});
|
|
772
|
+
failed++;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
// Separate changes by type
|
|
776
|
+
const styleChanges = elementChanges.filter((c) => c.type === "singleStyle" || c.type === "style");
|
|
777
|
+
const textChanges = elementChanges.filter((c) => c.type === "text");
|
|
778
|
+
const duplicateChanges = elementChanges.filter((c) => c.type === "duplicate");
|
|
779
|
+
// Get element position from first change that has it
|
|
780
|
+
const firstChange = elementChanges[0];
|
|
781
|
+
const element = firstChange.element;
|
|
782
|
+
if (!element.lineNumber || element.columnNumber === undefined) {
|
|
783
|
+
// Can't process without position
|
|
784
|
+
for (const change of elementChanges) {
|
|
785
|
+
if (change.type !== "delete") {
|
|
786
|
+
results.push({
|
|
787
|
+
changeId: change.id,
|
|
788
|
+
type: change.type,
|
|
789
|
+
success: false,
|
|
790
|
+
message: "Missing line/column number",
|
|
791
|
+
});
|
|
792
|
+
failed++;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
continue;
|
|
796
|
+
}
|
|
797
|
+
// Apply style changes (merged)
|
|
798
|
+
if (styleChanges.length > 0) {
|
|
799
|
+
const mergedStyles = mergeStyleChanges(styleChanges);
|
|
800
|
+
if (Object.keys(mergedStyles).length > 0) {
|
|
801
|
+
const styleResult = updateJSXSource({
|
|
802
|
+
sourceCode: currentCode,
|
|
803
|
+
lineNumber: element.lineNumber,
|
|
804
|
+
columnNumber: element.columnNumber,
|
|
805
|
+
tagName: element.tagName,
|
|
806
|
+
styles: mergedStyles,
|
|
807
|
+
});
|
|
808
|
+
// Record result for each style change
|
|
809
|
+
for (const change of styleChanges) {
|
|
810
|
+
results.push({
|
|
811
|
+
changeId: change.id,
|
|
812
|
+
type: change.type,
|
|
813
|
+
success: styleResult.success,
|
|
814
|
+
message: styleResult.success
|
|
815
|
+
? "Style applied (merged with other styles)"
|
|
816
|
+
: styleResult.message,
|
|
817
|
+
});
|
|
818
|
+
if (styleResult.success) {
|
|
819
|
+
successful++;
|
|
820
|
+
}
|
|
821
|
+
else {
|
|
822
|
+
failed++;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
if (styleResult.success) {
|
|
826
|
+
currentCode = styleResult.code;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
// Apply text changes
|
|
831
|
+
for (const change of textChanges) {
|
|
832
|
+
if (change.text?.current) {
|
|
833
|
+
const textResult = updateTextContent({
|
|
834
|
+
sourceCode: currentCode,
|
|
835
|
+
lineNumber: element.lineNumber,
|
|
836
|
+
columnNumber: element.columnNumber,
|
|
837
|
+
tagName: element.tagName,
|
|
838
|
+
newText: change.text.current,
|
|
839
|
+
});
|
|
840
|
+
results.push({
|
|
841
|
+
changeId: change.id,
|
|
842
|
+
type: "text",
|
|
843
|
+
success: textResult.success,
|
|
844
|
+
message: textResult.message,
|
|
845
|
+
});
|
|
846
|
+
if (textResult.success) {
|
|
847
|
+
currentCode = textResult.code;
|
|
848
|
+
successful++;
|
|
849
|
+
}
|
|
850
|
+
else {
|
|
851
|
+
// Check if it was skipped due to JS expressions
|
|
852
|
+
if (textResult.message?.includes("JS expressions")) {
|
|
853
|
+
skipped++;
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
failed++;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
// Apply duplicate changes
|
|
862
|
+
for (const change of duplicateChanges) {
|
|
863
|
+
const dupResult = duplicateJSXElement({
|
|
864
|
+
sourceCode: currentCode,
|
|
865
|
+
lineNumber: element.lineNumber,
|
|
866
|
+
columnNumber: element.columnNumber,
|
|
867
|
+
tagName: element.tagName,
|
|
868
|
+
});
|
|
869
|
+
results.push({
|
|
870
|
+
changeId: change.id,
|
|
871
|
+
type: "duplicate",
|
|
872
|
+
success: dupResult.success,
|
|
873
|
+
message: dupResult.message,
|
|
874
|
+
});
|
|
875
|
+
if (dupResult.success) {
|
|
876
|
+
currentCode = dupResult.code;
|
|
877
|
+
successful++;
|
|
878
|
+
}
|
|
879
|
+
else {
|
|
880
|
+
failed++;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
const allSuccessful = failed === 0 && skipped === 0;
|
|
885
|
+
return {
|
|
886
|
+
success: allSuccessful,
|
|
887
|
+
code: currentCode,
|
|
888
|
+
results,
|
|
889
|
+
summary: {
|
|
890
|
+
total: changes.length,
|
|
891
|
+
successful,
|
|
892
|
+
failed,
|
|
893
|
+
skipped,
|
|
894
|
+
},
|
|
895
|
+
};
|
|
896
|
+
}
|
package/package.json
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@promakeai/inspector-hook",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "React hook for controlling inspector in parent applications",
|
|
5
|
-
"author": "Promake",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"main": "./dist/index.js",
|
|
8
|
-
"module": "./dist/index.js",
|
|
9
|
-
"types": "./dist/index.d.ts",
|
|
10
|
-
"exports": {
|
|
11
|
-
".": {
|
|
12
|
-
"types": "./dist/index.d.ts",
|
|
13
|
-
"import": "./dist/index.js"
|
|
14
|
-
},
|
|
15
|
-
"./package.json": "./package.json"
|
|
16
|
-
},
|
|
17
|
-
"files": [
|
|
18
|
-
"dist"
|
|
19
|
-
],
|
|
20
|
-
"scripts": {
|
|
21
|
-
"build": "tsc --build",
|
|
22
|
-
"dev": "tsc --watch",
|
|
23
|
-
"clean": "rm -rf dist",
|
|
24
|
-
"lint": "tsc --build --force --dry",
|
|
25
|
-
"test": "vitest run",
|
|
26
|
-
"test:watch": "vitest",
|
|
27
|
-
"test:coverage": "vitest run --coverage",
|
|
28
|
-
"prepublishOnly": "bun run build",
|
|
29
|
-
"release": "bun run build && npm publish --access public"
|
|
30
|
-
},
|
|
31
|
-
"keywords": [
|
|
32
|
-
"react",
|
|
33
|
-
"hook",
|
|
34
|
-
"inspector",
|
|
35
|
-
"iframe"
|
|
36
|
-
],
|
|
37
|
-
"peerDependencies": {
|
|
38
|
-
"react": ">=18.0.0",
|
|
39
|
-
"react-dom": ">=18.0.0",
|
|
40
|
-
"vite": ">=5.0.0"
|
|
41
|
-
},
|
|
42
|
-
"peerDependenciesMeta": {
|
|
43
|
-
"vite": {
|
|
44
|
-
"optional": true
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
"devDependencies": {
|
|
48
|
-
"@promakeai/inspector-types": "1.0.2",
|
|
49
|
-
"vitest": "^1.0.0"
|
|
50
|
-
},
|
|
51
|
-
"publishConfig": {
|
|
52
|
-
"access": "public"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@promakeai/inspector-hook",
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "React hook for controlling inspector in parent applications",
|
|
5
|
+
"author": "Promake",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc --build",
|
|
22
|
+
"dev": "tsc --watch",
|
|
23
|
+
"clean": "rm -rf dist",
|
|
24
|
+
"lint": "tsc --build --force --dry",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:watch": "vitest",
|
|
27
|
+
"test:coverage": "vitest run --coverage",
|
|
28
|
+
"prepublishOnly": "bun run build",
|
|
29
|
+
"release": "bun run build && npm publish --access public"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"react",
|
|
33
|
+
"hook",
|
|
34
|
+
"inspector",
|
|
35
|
+
"iframe"
|
|
36
|
+
],
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"react": ">=18.0.0",
|
|
39
|
+
"react-dom": ">=18.0.0",
|
|
40
|
+
"vite": ">=5.0.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependenciesMeta": {
|
|
43
|
+
"vite": {
|
|
44
|
+
"optional": true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@promakeai/inspector-types": "1.0.2",
|
|
49
|
+
"vitest": "^1.0.0"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
}
|
|
54
|
+
}
|