@abbox/inspector 0.4.11 → 0.4.13
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/host/client-bridge.d.ts.map +1 -1
- package/dist/host/client-bridge.js +4 -19
- package/dist/host/host-bridge.d.ts +1 -0
- package/dist/host/host-bridge.d.ts.map +1 -1
- package/dist/host/host-bridge.js +3 -0
- package/dist/host/validate.d.ts.map +1 -1
- package/dist/host/validate.js +1 -28
- package/dist/protocol.d.ts +21 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/runtime/bootstrap.d.ts.map +1 -1
- package/dist/runtime/bootstrap.js +4 -3
- package/dist/runtime/inspector.d.ts +1 -0
- package/dist/runtime/inspector.d.ts.map +1 -1
- package/dist/runtime/inspector.js +156 -57
- package/dist/runtime/metadata.d.ts.map +1 -1
- package/dist/runtime/metadata.js +54 -0
- package/dist/runtime/overlay.d.ts.map +1 -1
- package/dist/runtime/overlay.js +5 -7
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-bridge.d.ts","sourceRoot":"","sources":["../../src/host/client-bridge.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAEF,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,GAC9B,eAAe,
|
|
1
|
+
{"version":3,"file":"client-bridge.d.ts","sourceRoot":"","sources":["../../src/host/client-bridge.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAEF,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,GAC9B,eAAe,CA4EjB"}
|
|
@@ -9,26 +9,8 @@ export function createInspectorClient(options) {
|
|
|
9
9
|
const send = (message) => {
|
|
10
10
|
if (!win.parent || win.parent === win)
|
|
11
11
|
return;
|
|
12
|
-
let sent = false;
|
|
13
|
-
// Try each allowed origin
|
|
14
12
|
for (const targetOrigin of allowedOrigins) {
|
|
15
|
-
|
|
16
|
-
win.parent.postMessage(message, targetOrigin);
|
|
17
|
-
sent = true;
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
catch (err) {
|
|
21
|
-
// Try next origin
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
// If all allowed origins failed, try wildcard
|
|
25
|
-
if (!sent) {
|
|
26
|
-
try {
|
|
27
|
-
win.parent.postMessage(message, "*");
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
// Give up silently
|
|
31
|
-
}
|
|
13
|
+
win.parent.postMessage(message, targetOrigin);
|
|
32
14
|
}
|
|
33
15
|
};
|
|
34
16
|
const base = () => ({
|
|
@@ -59,6 +41,9 @@ export function createInspectorClient(options) {
|
|
|
59
41
|
onChangeMarkerSelected: (changeId) => {
|
|
60
42
|
send({ ...base(), type: "CHANGE_MARKER_SELECTED", changeId });
|
|
61
43
|
},
|
|
44
|
+
onRouteChange: (path) => {
|
|
45
|
+
send({ ...base(), type: "ROUTE_CHANGED", path });
|
|
46
|
+
},
|
|
62
47
|
});
|
|
63
48
|
const onMessage = (event) => {
|
|
64
49
|
const msg = validateIncomingMessage(event.data, event.origin, {
|
|
@@ -19,6 +19,7 @@ export type InspectorHostHandlers = {
|
|
|
19
19
|
onSelect?: (payload: SelectPayload) => void;
|
|
20
20
|
onCleared?: () => void;
|
|
21
21
|
onChangeMarkerSelected?: (changeId: string) => void;
|
|
22
|
+
onRouteChange?: (path: string) => void;
|
|
22
23
|
onError?: (code: string, message: string) => void;
|
|
23
24
|
};
|
|
24
25
|
export type InspectorHost = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-bridge.d.ts","sourceRoot":"","sources":["../../src/host/host-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,mBAAmB,EAGzB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACvC,CAAC;AAEF,KAAK,YAAY,GAAG,OAAO,CACzB,mBAAmB,EACnB;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,CAC5B,CAAC,SAAS,CAAC,CAAC;AACb,KAAK,aAAa,GAAG,OAAO,CAC1B,mBAAmB,EACnB;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE,CAC7B,CAAC,SAAS,CAAC,CAAC;AAEb,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,kBAAkB,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IACtD,0EAA0E;IAC1E,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,qBAAqB,GAC9B,aAAa,
|
|
1
|
+
{"version":3,"file":"host-bridge.d.ts","sourceRoot":"","sources":["../../src/host/host-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,mBAAmB,EAGzB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACvC,CAAC;AAEF,KAAK,YAAY,GAAG,OAAO,CACzB,mBAAmB,EACnB;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,CAC5B,CAAC,SAAS,CAAC,CAAC;AACb,KAAK,aAAa,GAAG,OAAO,CAC1B,mBAAmB,EACnB;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE,CAC7B,CAAC,SAAS,CAAC,CAAC;AAEb,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,kBAAkB,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IACtD,0EAA0E;IAC1E,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,qBAAqB,GAC9B,aAAa,CAkEf"}
|
package/dist/host/host-bridge.js
CHANGED
|
@@ -35,6 +35,9 @@ export function createInspectorHost(options, handlers) {
|
|
|
35
35
|
if (msg.type === "CHANGE_MARKER_SELECTED") {
|
|
36
36
|
handlers.onChangeMarkerSelected?.(msg.changeId);
|
|
37
37
|
}
|
|
38
|
+
if (msg.type === "ROUTE_CHANGED") {
|
|
39
|
+
handlers.onRouteChange?.(msg.path);
|
|
40
|
+
}
|
|
38
41
|
if (msg.type === "INSPECTOR_ERROR") {
|
|
39
42
|
handlers.onError?.(msg.code, msg.message);
|
|
40
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/host/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAsB,MAAM,gBAAgB,CAAC;AAE3E,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,GACvB,gBAAgB,GAAG,IAAI,CAKzB;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,EACzB,YAAY,EAAE,MAAM,GACnB,IAAI,
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/host/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAsB,MAAM,gBAAgB,CAAC;AAE3E,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,GACvB,gBAAgB,GAAG,IAAI,CAKzB;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,EACzB,YAAY,EAAE,MAAM,GACnB,IAAI,CAEN"}
|
package/dist/host/validate.js
CHANGED
|
@@ -9,32 +9,5 @@ export function validateIncomingMessage(data, origin, options) {
|
|
|
9
9
|
return data;
|
|
10
10
|
}
|
|
11
11
|
export function postToTarget(target, message, targetOrigin) {
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
target.postMessage(message, targetOrigin);
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
// Silently fail and try fallback
|
|
19
|
-
}
|
|
20
|
-
// Try localhost/127.0.0.1 variant
|
|
21
|
-
const variant = targetOrigin
|
|
22
|
-
.replace("://localhost", "://127.0.0.1")
|
|
23
|
-
.replace("://127.0.0.1", "://localhost");
|
|
24
|
-
if (variant !== targetOrigin) {
|
|
25
|
-
try {
|
|
26
|
-
target.postMessage(message, variant);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
// Silently fail and try wildcard
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
// Last resort: wildcard (bypasses origin check)
|
|
34
|
-
try {
|
|
35
|
-
target.postMessage(message, "*");
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
// Give up silently
|
|
39
|
-
}
|
|
12
|
+
target.postMessage(message, targetOrigin);
|
|
40
13
|
}
|
package/dist/protocol.d.ts
CHANGED
|
@@ -47,6 +47,21 @@ export type ElementMetadata = {
|
|
|
47
47
|
/** Native disabled state when the element supports it (e.g. button, input). */
|
|
48
48
|
disabled: boolean | null;
|
|
49
49
|
attributes: Record<string, string>;
|
|
50
|
+
/**
|
|
51
|
+
* Live state of form controls near the element (its form, or the nearest
|
|
52
|
+
* container with controls). Values are never included, only whether filled.
|
|
53
|
+
*/
|
|
54
|
+
nearbyFields?: NearbyFieldState[];
|
|
55
|
+
};
|
|
56
|
+
export type NearbyFieldState = {
|
|
57
|
+
tagName: string;
|
|
58
|
+
type: string | null;
|
|
59
|
+
label: string | null;
|
|
60
|
+
placeholder: string | null;
|
|
61
|
+
required: boolean;
|
|
62
|
+
disabled: boolean;
|
|
63
|
+
state: "empty" | "filled" | "checked" | "unchecked";
|
|
64
|
+
isSelected: boolean;
|
|
50
65
|
};
|
|
51
66
|
export type RuntimeElementRef = {
|
|
52
67
|
/** Stable within a preview session for a given DOM node identity. */
|
|
@@ -94,12 +109,17 @@ export type ChangeMarkerSelectedMessage = InspectorMessageBase & {
|
|
|
94
109
|
type: "CHANGE_MARKER_SELECTED";
|
|
95
110
|
changeId: string;
|
|
96
111
|
};
|
|
112
|
+
/** The preview navigated (client-side or full load) to a new path. */
|
|
113
|
+
export type RouteChangedMessage = InspectorMessageBase & {
|
|
114
|
+
type: "ROUTE_CHANGED";
|
|
115
|
+
path: string;
|
|
116
|
+
};
|
|
97
117
|
export type ApplyChangeMarkersMessage = InspectorMessageBase & {
|
|
98
118
|
type: "APPLY_CHANGE_MARKERS";
|
|
99
119
|
markers: ChangeMarker[];
|
|
100
120
|
};
|
|
101
121
|
export type HostToClientMessage = InspectorEnableMessage | InspectorDisableMessage | InspectorHostHelloMessage | ApplyChangeMarkersMessage;
|
|
102
|
-
export type ClientToHostMessage = InspectorReadyMessage | ElementHoveredMessage | ElementSelectedMessage | ElementClearedMessage | ChangeMarkerSelectedMessage | InspectorErrorMessage;
|
|
122
|
+
export type ClientToHostMessage = InspectorReadyMessage | ElementHoveredMessage | ElementSelectedMessage | ElementClearedMessage | ChangeMarkerSelectedMessage | RouteChangedMessage | InspectorErrorMessage;
|
|
103
123
|
export type InspectorMessage = HostToClientMessage | ClientToHostMessage;
|
|
104
124
|
export declare function isInspectorMessage(value: unknown): value is InspectorMessage;
|
|
105
125
|
//# sourceMappingURL=protocol.d.ts.map
|
package/dist/protocol.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,EAAG,CAAU,CAAC;AAE3C,eAAO,MAAM,wBAAwB,EAAG,iBAA0B,CAAC;AAEnE,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,OAAO,wBAAwB,CAAC;IACzC,OAAO,EAAE,OAAO,gBAAgB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,oBAAoB,GAAG;IACzD,IAAI,EAAE,iBAAiB,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,oBAAoB,GAAG;IAC1D,IAAI,EAAE,kBAAkB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,oBAAoB,GAAG;IAC3D,IAAI,EAAE,mBAAmB,CAAC;CAC3B,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,yBAAyB,GAAG,oBAAoB,GAAG;IAC7D,IAAI,EAAE,sBAAsB,CAAC;IAC7B,qFAAqF;IACrF,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC;AAExE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/runtime/bootstrap.ts"],"names":[],"mappings":"AAuCA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,YAAY,CAAC,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzD,CAAC;AA8CF;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,gBAAqB,GAC7B,IAAI,
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/runtime/bootstrap.ts"],"names":[],"mappings":"AAuCA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,YAAY,CAAC,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzD,CAAC;AA8CF;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,gBAAqB,GAC7B,IAAI,CAkDN;AAED,4CAA4C;AAC5C,wBAAgB,+BAA+B,IAAI,IAAI,CAMtD"}
|
|
@@ -75,9 +75,10 @@ export function bootstrapInspectorPreview(options = {}) {
|
|
|
75
75
|
// In Next.js 13+ RSC, window.location.search may be empty. Fallback to passed searchParams.
|
|
76
76
|
let params;
|
|
77
77
|
if (options.searchParams) {
|
|
78
|
-
params =
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
params =
|
|
79
|
+
options.searchParams instanceof URLSearchParams
|
|
80
|
+
? options.searchParams
|
|
81
|
+
: new URLSearchParams(options.searchParams);
|
|
81
82
|
}
|
|
82
83
|
else {
|
|
83
84
|
params = new URLSearchParams(win.location.search);
|
|
@@ -6,6 +6,7 @@ export type InspectorRuntimeOptions = {
|
|
|
6
6
|
onSelect?: (payload: ElementHoverPayload) => void;
|
|
7
7
|
onClear?: () => void;
|
|
8
8
|
onChangeMarkerSelected?: (changeId: string) => void;
|
|
9
|
+
onRouteChange?: (path: string) => void;
|
|
9
10
|
};
|
|
10
11
|
export type InspectorRuntime = {
|
|
11
12
|
enable: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/runtime/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/runtime/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAyCxE,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,gBAAgB,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IACpD,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;IACrD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,gBAAgB,CAkTlB"}
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { runtimeElementRefFor } from "./element-ref.js";
|
|
2
2
|
import { extractMetadata, findSourceLocation, sourceKeyFor, sourceMappingStatus, } from "./metadata.js";
|
|
3
3
|
import { createOverlay, hideHighlight, hideSelectedHighlight, positionHighlight, positionSelectedHighlight, rectForElement, renderChangeMarkers, } from "./overlay.js";
|
|
4
|
+
const SOURCE_LINE_TOLERANCE = 2;
|
|
5
|
+
function parseSourceKey(raw) {
|
|
6
|
+
const m = raw ? /^(.*?):(\d+)(?::\d+)?$/.exec(raw) : null;
|
|
7
|
+
return m?.[1] ? { file: m[1], line: Number(m[2]) } : null;
|
|
8
|
+
}
|
|
9
|
+
function sameFile(a, b) {
|
|
10
|
+
return a === b || a.endsWith(`/${b}`) || b.endsWith(`/${a}`);
|
|
11
|
+
}
|
|
12
|
+
const SWALLOWED_EVENTS = [
|
|
13
|
+
"pointerup",
|
|
14
|
+
"mousedown",
|
|
15
|
+
"mouseup",
|
|
16
|
+
"click",
|
|
17
|
+
"dblclick",
|
|
18
|
+
"auxclick",
|
|
19
|
+
"contextmenu",
|
|
20
|
+
];
|
|
4
21
|
export function createInspectorRuntime(options) {
|
|
5
22
|
const { document: doc, window: win } = options;
|
|
6
23
|
const overlay = createOverlay(doc);
|
|
@@ -15,6 +32,35 @@ export function createInspectorRuntime(options) {
|
|
|
15
32
|
const teardownListeners = () => {
|
|
16
33
|
win.removeEventListener("mousemove", onMove, true);
|
|
17
34
|
win.removeEventListener("pointerdown", onPointerDownCapture, true);
|
|
35
|
+
doc.removeEventListener("mouseout", onLeave, true);
|
|
36
|
+
for (const type of SWALLOWED_EVENTS) {
|
|
37
|
+
win.removeEventListener(type, swallowAppInteraction, true);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const isChangeMarker = (target) => target instanceof Element &&
|
|
41
|
+
target.closest("[data-abbox-change-marker]") !== null;
|
|
42
|
+
/**
|
|
43
|
+
* While inspecting, a click only selects. Cancelling pointerdown alone does
|
|
44
|
+
* not stop the mousedown/mouseup/click that follow, so the app would still
|
|
45
|
+
* react (navigate, submit, open modals).
|
|
46
|
+
*/
|
|
47
|
+
const swallowAppInteraction = (event) => {
|
|
48
|
+
if (!enabled || isChangeMarker(event.target))
|
|
49
|
+
return;
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
event.stopImmediatePropagation();
|
|
52
|
+
};
|
|
53
|
+
/** No mousemove fires once the pointer leaves the iframe, so clear hover here. */
|
|
54
|
+
const onLeave = (event) => {
|
|
55
|
+
if (event.relatedTarget)
|
|
56
|
+
return;
|
|
57
|
+
if (raf) {
|
|
58
|
+
win.cancelAnimationFrame(raf);
|
|
59
|
+
raf = 0;
|
|
60
|
+
}
|
|
61
|
+
pendingTarget = null;
|
|
62
|
+
hovered = null;
|
|
63
|
+
hideHighlight(overlay.highlight);
|
|
18
64
|
};
|
|
19
65
|
const onMove = (event) => {
|
|
20
66
|
if (!enabled)
|
|
@@ -37,13 +83,12 @@ export function createInspectorRuntime(options) {
|
|
|
37
83
|
const onPointerDownCapture = (event) => {
|
|
38
84
|
if (!enabled)
|
|
39
85
|
return;
|
|
40
|
-
if (event.
|
|
41
|
-
return;
|
|
42
|
-
if (event.target instanceof Element &&
|
|
43
|
-
event.target.closest("[data-abbox-change-marker]"))
|
|
86
|
+
if (isChangeMarker(event.target))
|
|
44
87
|
return;
|
|
45
88
|
event.preventDefault();
|
|
46
|
-
event.
|
|
89
|
+
event.stopImmediatePropagation();
|
|
90
|
+
if (event.button !== 0)
|
|
91
|
+
return;
|
|
47
92
|
const target = deepestElementAt(doc, event.clientX, event.clientY, event.target);
|
|
48
93
|
if (!target || !doc.body.contains(target))
|
|
49
94
|
return;
|
|
@@ -81,56 +126,120 @@ export function createInspectorRuntime(options) {
|
|
|
81
126
|
options.onHover?.(payloadFor(el));
|
|
82
127
|
}
|
|
83
128
|
function select(el) {
|
|
84
|
-
console.log("[inspector] element selected", el.tagName);
|
|
85
129
|
selected = el;
|
|
86
130
|
hovered = el;
|
|
87
131
|
positionSelectedHighlight(overlay.selectedHighlight, rectForElement(el));
|
|
88
132
|
positionHighlight(overlay.highlight, rectForElement(el));
|
|
89
133
|
options.onSelect?.(payloadFor(el));
|
|
90
134
|
}
|
|
91
|
-
|
|
135
|
+
const onCurrentRoute = (marker) => !marker.route ||
|
|
136
|
+
win.location.pathname.replace(/\/$/, "") ===
|
|
137
|
+
marker.route.replace(/\/$/, "");
|
|
138
|
+
function resolveMarkerElement(marker) {
|
|
92
139
|
const isRendered = (node) => {
|
|
93
140
|
const rect = node.getBoundingClientRect();
|
|
94
141
|
return node.isConnected && rect.width > 0 && rect.height > 0;
|
|
95
142
|
};
|
|
143
|
+
const target = parseSourceKey(marker.sourceKeyPrefix);
|
|
144
|
+
const byLine = new Map();
|
|
145
|
+
if (target) {
|
|
146
|
+
for (const node of Array.from(doc.querySelectorAll("[data-abbox-src]"))) {
|
|
147
|
+
const src = parseSourceKey(node.getAttribute("data-abbox-src"));
|
|
148
|
+
if (!src || !sameFile(src.file, target.file))
|
|
149
|
+
continue;
|
|
150
|
+
const distance = Math.abs(src.line - target.line);
|
|
151
|
+
if (distance > SOURCE_LINE_TOLERANCE || !isRendered(node))
|
|
152
|
+
continue;
|
|
153
|
+
byLine.set(distance, [...(byLine.get(distance) ?? []), node]);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const nearestDistance = Math.min(...byLine.keys());
|
|
157
|
+
const sourceCandidates = byLine.get(nearestDistance) ?? [];
|
|
158
|
+
const hint = marker.textHint?.trim();
|
|
159
|
+
const hasHint = (node) => node.textContent?.trim() === hint;
|
|
160
|
+
const sourceTextCandidates = hint ? sourceCandidates.filter(hasHint) : [];
|
|
161
|
+
const textCandidates = hint
|
|
162
|
+
? Array.from(doc.querySelectorAll("body *")).filter((node) => node.children.length === 0 &&
|
|
163
|
+
isRendered(node) &&
|
|
164
|
+
hasHint(node) &&
|
|
165
|
+
!node.closest("[data-abbox-inspector]"))
|
|
166
|
+
: [];
|
|
167
|
+
if (sourceTextCandidates.length === 1)
|
|
168
|
+
return sourceTextCandidates[0] ?? null;
|
|
169
|
+
if (sourceCandidates.length === 1)
|
|
170
|
+
return sourceCandidates[0] ?? null;
|
|
171
|
+
if (textCandidates.length === 1)
|
|
172
|
+
return textCandidates[0] ?? null;
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
function resolveMarkerElements(next) {
|
|
96
176
|
for (const marker of next) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
marker.route.replace(/\/$/, ""))
|
|
177
|
+
const cached = refIdToElement.get(marker.elementRefId);
|
|
178
|
+
if (cached?.isConnected && onCurrentRoute(marker))
|
|
100
179
|
continue;
|
|
101
|
-
|
|
180
|
+
refIdToElement.delete(marker.elementRefId);
|
|
181
|
+
if (!onCurrentRoute(marker))
|
|
102
182
|
continue;
|
|
103
|
-
const
|
|
104
|
-
? `${marker.sourceKeyPrefix}:`
|
|
105
|
-
: null;
|
|
106
|
-
const sourceCandidates = sourceKey
|
|
107
|
-
? Array.from(doc.querySelectorAll("[data-abbox-src]")).filter((node) => {
|
|
108
|
-
const raw = node.getAttribute("data-abbox-src") ?? "";
|
|
109
|
-
return (isRendered(node) &&
|
|
110
|
-
(raw.startsWith(sourceKey) || raw.endsWith(`/${sourceKey}`)));
|
|
111
|
-
})
|
|
112
|
-
: [];
|
|
113
|
-
const hint = marker.textHint?.trim();
|
|
114
|
-
const textCandidates = hint
|
|
115
|
-
? Array.from(doc.querySelectorAll("body *")).filter((node) => node.children.length === 0 &&
|
|
116
|
-
isRendered(node) &&
|
|
117
|
-
node.textContent?.trim() === hint &&
|
|
118
|
-
!node.closest("[data-abbox-inspector]"))
|
|
119
|
-
: [];
|
|
120
|
-
const sourceTextCandidates = hint
|
|
121
|
-
? sourceCandidates.filter((node) => node.textContent?.trim() === hint)
|
|
122
|
-
: [];
|
|
123
|
-
const match = sourceTextCandidates.length === 1
|
|
124
|
-
? sourceTextCandidates[0]
|
|
125
|
-
: textCandidates.length === 1
|
|
126
|
-
? textCandidates[0]
|
|
127
|
-
: !hint && sourceCandidates.length === 1
|
|
128
|
-
? sourceCandidates[0]
|
|
129
|
-
: null;
|
|
183
|
+
const match = resolveMarkerElement(marker);
|
|
130
184
|
if (match)
|
|
131
185
|
refIdToElement.set(marker.elementRefId, match);
|
|
132
186
|
}
|
|
133
187
|
}
|
|
188
|
+
/** Selects the element of the change the host focused, once it renders. */
|
|
189
|
+
function focusPulsedMarker() {
|
|
190
|
+
const focused = markers.find((marker) => marker.pulse && refIdToElement.has(marker.elementRefId));
|
|
191
|
+
if (!focused) {
|
|
192
|
+
if (!markers.some((marker) => marker.pulse))
|
|
193
|
+
focusedMarkerId = null;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (focused.elementRefId === focusedMarkerId)
|
|
197
|
+
return;
|
|
198
|
+
focusedMarkerId = focused.elementRefId;
|
|
199
|
+
const el = refIdToElement.get(focused.elementRefId);
|
|
200
|
+
if (!el)
|
|
201
|
+
return;
|
|
202
|
+
el.scrollIntoView?.({ block: "center", inline: "nearest" });
|
|
203
|
+
select(el);
|
|
204
|
+
}
|
|
205
|
+
function refreshMarkers() {
|
|
206
|
+
resolveMarkerElements(markers);
|
|
207
|
+
focusPulsedMarker();
|
|
208
|
+
renderChangeMarkers(overlay.markerLayer, markers, (id) => refIdToElement.get(id) ?? null, options.onChangeMarkerSelected);
|
|
209
|
+
if (selected?.isConnected) {
|
|
210
|
+
positionSelectedHighlight(overlay.selectedHighlight, rectForElement(selected));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
let lastPath = win.location.pathname;
|
|
214
|
+
let refreshFrame = 0;
|
|
215
|
+
/** SPA navigation and async data swap the DOM after markers arrive. */
|
|
216
|
+
const scheduleRefresh = () => {
|
|
217
|
+
if (refreshFrame)
|
|
218
|
+
return;
|
|
219
|
+
refreshFrame = win.requestAnimationFrame(() => {
|
|
220
|
+
refreshFrame = 0;
|
|
221
|
+
if (win.location.pathname !== lastPath) {
|
|
222
|
+
lastPath = win.location.pathname;
|
|
223
|
+
options.onRouteChange?.(lastPath);
|
|
224
|
+
}
|
|
225
|
+
if (markers.length)
|
|
226
|
+
refreshMarkers();
|
|
227
|
+
});
|
|
228
|
+
};
|
|
229
|
+
const observer = typeof MutationObserver === "undefined"
|
|
230
|
+
? null
|
|
231
|
+
: new MutationObserver((records) => {
|
|
232
|
+
const ownChange = records.every((record) => record.target instanceof Element &&
|
|
233
|
+
record.target.closest("[data-abbox-inspector]") !== null);
|
|
234
|
+
if (!ownChange)
|
|
235
|
+
scheduleRefresh();
|
|
236
|
+
});
|
|
237
|
+
observer?.observe(doc.body, {
|
|
238
|
+
childList: true,
|
|
239
|
+
subtree: true,
|
|
240
|
+
characterData: true,
|
|
241
|
+
});
|
|
242
|
+
win.addEventListener("popstate", scheduleRefresh);
|
|
134
243
|
function clearSelection() {
|
|
135
244
|
hovered = null;
|
|
136
245
|
selected = null;
|
|
@@ -147,6 +256,10 @@ export function createInspectorRuntime(options) {
|
|
|
147
256
|
enabled = true;
|
|
148
257
|
win.addEventListener("mousemove", onMove, true);
|
|
149
258
|
win.addEventListener("pointerdown", onPointerDownCapture, true);
|
|
259
|
+
doc.addEventListener("mouseout", onLeave, true);
|
|
260
|
+
for (const type of SWALLOWED_EVENTS) {
|
|
261
|
+
win.addEventListener(type, swallowAppInteraction, true);
|
|
262
|
+
}
|
|
150
263
|
},
|
|
151
264
|
disable: () => {
|
|
152
265
|
if (!enabled)
|
|
@@ -163,25 +276,7 @@ export function createInspectorRuntime(options) {
|
|
|
163
276
|
markers = next;
|
|
164
277
|
for (const marker of next)
|
|
165
278
|
refIdToElement.delete(marker.elementRefId);
|
|
166
|
-
|
|
167
|
-
const focused = next.find((marker) => marker.pulse && refIdToElement.has(marker.elementRefId));
|
|
168
|
-
if (focused && focused.elementRefId !== focusedMarkerId) {
|
|
169
|
-
refIdToElement
|
|
170
|
-
.get(focused.elementRefId)
|
|
171
|
-
?.scrollIntoView?.({ block: "center", inline: "nearest" });
|
|
172
|
-
}
|
|
173
|
-
focusedMarkerId = focused?.elementRefId ?? null;
|
|
174
|
-
const unresolved = next.filter((marker) => (!marker.route ||
|
|
175
|
-
marker.route.replace(/\/$/, "") ===
|
|
176
|
-
win.location.pathname.replace(/\/$/, "")) &&
|
|
177
|
-
!refIdToElement.has(marker.elementRefId));
|
|
178
|
-
if (unresolved.length) {
|
|
179
|
-
console.warn("[abbox-inspector] change markers could not be matched to rendered elements", {
|
|
180
|
-
route: win.location.pathname,
|
|
181
|
-
changeIds: unresolved.map((marker) => marker.elementRefId),
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
renderChangeMarkers(overlay.markerLayer, markers, (id) => refIdToElement.get(id) ?? null, options.onChangeMarkerSelected);
|
|
279
|
+
refreshMarkers();
|
|
185
280
|
},
|
|
186
281
|
getElementByRefId: (id) => refIdToElement.get(id) ?? null,
|
|
187
282
|
destroy: () => {
|
|
@@ -191,6 +286,10 @@ export function createInspectorRuntime(options) {
|
|
|
191
286
|
}
|
|
192
287
|
win.removeEventListener("scroll", onScrollOrResize, true);
|
|
193
288
|
win.removeEventListener("resize", onScrollOrResize);
|
|
289
|
+
win.removeEventListener("popstate", scheduleRefresh);
|
|
290
|
+
observer?.disconnect();
|
|
291
|
+
if (refreshFrame)
|
|
292
|
+
win.cancelAnimationFrame(refreshFrame);
|
|
194
293
|
hovered = null;
|
|
195
294
|
hideHighlight(overlay.highlight);
|
|
196
295
|
overlay.destroy();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/runtime/metadata.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/runtime/metadata.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EAEf,cAAc,EACd,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAYxB,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAarE;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,cAAc,GAAG,IAAI,GAC5B,mBAAmB,CAGrB;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,GAAG,eAAe,CAkC5D;AA2FD,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAGzE"}
|
package/dist/runtime/metadata.js
CHANGED
|
@@ -60,8 +60,62 @@ export function extractMetadata(el) {
|
|
|
60
60
|
textPreview,
|
|
61
61
|
disabled: readDisabledState(el),
|
|
62
62
|
attributes,
|
|
63
|
+
nearbyFields: nearbyFieldStates(el),
|
|
63
64
|
};
|
|
64
65
|
}
|
|
66
|
+
const FIELD_SELECTOR = "input:not([type=hidden]), textarea, select";
|
|
67
|
+
const MAX_CONTAINER_HOPS = 4;
|
|
68
|
+
const MAX_NEARBY_FIELDS = 15;
|
|
69
|
+
function fieldContainer(el) {
|
|
70
|
+
const form = el.closest("form");
|
|
71
|
+
if (form)
|
|
72
|
+
return form;
|
|
73
|
+
let node = el.parentElement;
|
|
74
|
+
for (let hop = 0; node && hop < MAX_CONTAINER_HOPS; hop++) {
|
|
75
|
+
if (node.querySelector(FIELD_SELECTOR))
|
|
76
|
+
return node;
|
|
77
|
+
node = node.parentElement;
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
function fieldLabel(control) {
|
|
82
|
+
const text = control.getAttribute("aria-label") ??
|
|
83
|
+
control.labels?.[0]?.textContent ??
|
|
84
|
+
null;
|
|
85
|
+
return text?.trim().slice(0, 80) || null;
|
|
86
|
+
}
|
|
87
|
+
/** Field emptiness only; typed values never leave the preview. */
|
|
88
|
+
function nearbyFieldStates(el) {
|
|
89
|
+
const container = fieldContainer(el);
|
|
90
|
+
if (!container)
|
|
91
|
+
return undefined;
|
|
92
|
+
const controls = Array.from(container.querySelectorAll(FIELD_SELECTOR)).slice(0, MAX_NEARBY_FIELDS);
|
|
93
|
+
if (controls.length === 0)
|
|
94
|
+
return undefined;
|
|
95
|
+
return controls.map((control) => {
|
|
96
|
+
const type = control instanceof HTMLInputElement
|
|
97
|
+
? control.type
|
|
98
|
+
: control.getAttribute("type");
|
|
99
|
+
const checkable = control instanceof HTMLInputElement &&
|
|
100
|
+
(control.type === "checkbox" || control.type === "radio");
|
|
101
|
+
return {
|
|
102
|
+
tagName: control.tagName.toLowerCase(),
|
|
103
|
+
type,
|
|
104
|
+
label: fieldLabel(control),
|
|
105
|
+
placeholder: control.getAttribute("placeholder"),
|
|
106
|
+
required: control.required,
|
|
107
|
+
disabled: control.disabled,
|
|
108
|
+
state: checkable
|
|
109
|
+
? control.checked
|
|
110
|
+
? "checked"
|
|
111
|
+
: "unchecked"
|
|
112
|
+
: control.value.trim()
|
|
113
|
+
? "filled"
|
|
114
|
+
: "empty",
|
|
115
|
+
isSelected: control === el,
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
}
|
|
65
119
|
function readDisabledState(el) {
|
|
66
120
|
if (el instanceof HTMLButtonElement ||
|
|
67
121
|
el instanceof HTMLInputElement ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/runtime/overlay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAMhE,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,cAAc,CAAC;IAC1B,iBAAiB,EAAE,cAAc,CAAC;IAClC,WAAW,EAAE,cAAc,CAAC;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/runtime/overlay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAMhE,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,cAAc,CAAC;IAC1B,iBAAiB,EAAE,cAAc,CAAC;IAClC,WAAW,EAAE,cAAc,CAAC;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAgD5D;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,cAAc,EACzB,IAAI,EAAE,WAAW,GAChB,IAAI,CAQN;AAED,wBAAgB,yBAAyB,CACvC,iBAAiB,EAAE,cAAc,EACjC,IAAI,EAAE,WAAW,GAChB,IAAI,CAQN;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAE7D;AAED,wBAAgB,qBAAqB,CAAC,iBAAiB,EAAE,cAAc,GAAG,IAAI,CAE7E;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,WAAW,CAQvD;AAOD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,YAAY,EAAE,EACvB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,EACjD,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GACpC,IAAI,CA+DN"}
|
package/dist/runtime/overlay.js
CHANGED
|
@@ -2,13 +2,12 @@ const HIGHLIGHT_Z = 2147483646;
|
|
|
2
2
|
const SELECTED_HIGHLIGHT_Z = 2147483643;
|
|
3
3
|
const MARKER_Z = 2147483645;
|
|
4
4
|
export function createOverlay(root) {
|
|
5
|
-
console.log("[inspector] creating overlay");
|
|
6
5
|
const selectedHighlight = root.createElement("div");
|
|
7
6
|
selectedHighlight.setAttribute("data-abbox-inspector", "selected-highlight");
|
|
8
7
|
Object.assign(selectedHighlight.style, {
|
|
9
8
|
position: "fixed",
|
|
10
9
|
pointerEvents: "none",
|
|
11
|
-
border: "
|
|
10
|
+
border: "2px dashed #2563eb",
|
|
12
11
|
background: "rgba(37, 99, 235, 0.06)",
|
|
13
12
|
borderRadius: "2px",
|
|
14
13
|
zIndex: String(SELECTED_HIGHLIGHT_Z),
|
|
@@ -20,7 +19,7 @@ export function createOverlay(root) {
|
|
|
20
19
|
Object.assign(highlight.style, {
|
|
21
20
|
position: "fixed",
|
|
22
21
|
pointerEvents: "none",
|
|
23
|
-
border: "
|
|
22
|
+
border: "2px solid #2563eb",
|
|
24
23
|
background: "rgba(37, 99, 235, 0.12)",
|
|
25
24
|
borderRadius: "2px",
|
|
26
25
|
zIndex: String(HIGHLIGHT_Z),
|
|
@@ -57,7 +56,6 @@ export function positionHighlight(highlight, rect) {
|
|
|
57
56
|
});
|
|
58
57
|
}
|
|
59
58
|
export function positionSelectedHighlight(selectedHighlight, rect) {
|
|
60
|
-
console.log("[inspector] positioning selected highlight at", rect);
|
|
61
59
|
Object.assign(selectedHighlight.style, {
|
|
62
60
|
display: "block",
|
|
63
61
|
left: `${rect.x}px`,
|
|
@@ -117,7 +115,7 @@ export function renderChangeMarkers(layer, markers, resolveElement, onSelect) {
|
|
|
117
115
|
background: marker.kind === "change-added"
|
|
118
116
|
? "#22c55e"
|
|
119
117
|
: marker.kind === "change-modified"
|
|
120
|
-
? "#
|
|
118
|
+
? "#f97316"
|
|
121
119
|
: marker.kind === "mock"
|
|
122
120
|
? "#f59e0b"
|
|
123
121
|
: "#ef4444",
|
|
@@ -142,8 +140,8 @@ export function renderChangeMarkers(layer, markers, resolveElement, onSelect) {
|
|
|
142
140
|
: "0 0 0 1px rgba(0,0,0,0.2)";
|
|
143
141
|
if (marker.pulse)
|
|
144
142
|
ensurePulseStyle(layer.ownerDocument);
|
|
145
|
-
dot.style.left = `${rect.x
|
|
146
|
-
dot.style.top = `${rect.top -
|
|
143
|
+
dot.style.left = `${rect.x - 6}px`;
|
|
144
|
+
dot.style.top = `${rect.top - 6}px`;
|
|
147
145
|
}
|
|
148
146
|
}
|
|
149
147
|
function ensurePulseStyle(doc) {
|