react-grab 0.0.11 → 0.0.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/index.d.ts +36 -2
- package/dist/index.global.js +843 -336
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
interface StoreApi<T> {
|
|
2
|
+
getInitialState(): T;
|
|
3
|
+
getState(): T;
|
|
4
|
+
setState(partialState: ((prevState: T) => T) | Partial<T>): T;
|
|
5
|
+
subscribe(listener: Listener<T>): () => void;
|
|
6
|
+
subscribe<U>(listener: Listener<U>, selector: (state: T) => unknown): () => void;
|
|
7
|
+
}
|
|
8
|
+
type Listener<T> = (state: T, prevState: T | undefined) => (() => unknown) | void;
|
|
2
9
|
|
|
3
|
-
|
|
10
|
+
type Hotkey = KeyboardEvent["key"];
|
|
11
|
+
|
|
12
|
+
interface Options {
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* hotkey to trigger the overlay
|
|
16
|
+
*
|
|
17
|
+
* default: ["Meta", "C"]
|
|
18
|
+
*/
|
|
19
|
+
hotkey?: Hotkey | Hotkey[];
|
|
20
|
+
/**
|
|
21
|
+
* time required (ms) to hold the key to trigger the overlay
|
|
22
|
+
*
|
|
23
|
+
* default: 1000
|
|
24
|
+
*/
|
|
25
|
+
keyHoldDuration?: number;
|
|
26
|
+
}
|
|
27
|
+
interface LibStore {
|
|
28
|
+
keyPressTimestamps: Map<Hotkey, number>;
|
|
29
|
+
mouseX: number;
|
|
30
|
+
mouseY: number;
|
|
31
|
+
overlayMode: "copying" | "hidden" | "visible";
|
|
32
|
+
pressedKeys: Set<Hotkey>;
|
|
33
|
+
}
|
|
34
|
+
declare const libStore: StoreApi<LibStore>;
|
|
35
|
+
declare const init: (options?: Options) => (() => void) | undefined;
|
|
36
|
+
|
|
37
|
+
export { type Options, init, libStore };
|
package/dist/index.global.js
CHANGED
|
@@ -10,202 +10,210 @@ var ReactGrab = (function (exports) {
|
|
|
10
10
|
* LICENSE file in the root directory of this source tree.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
// src/
|
|
14
|
-
var
|
|
15
|
-
|
|
13
|
+
// src/hotkeys.ts
|
|
14
|
+
var FORM_TAGS_AND_ROLES = [
|
|
15
|
+
"input",
|
|
16
|
+
"textarea",
|
|
17
|
+
"select",
|
|
18
|
+
"searchbox",
|
|
19
|
+
"slider",
|
|
20
|
+
"spinbutton",
|
|
21
|
+
"menuitem",
|
|
22
|
+
"menuitemcheckbox",
|
|
23
|
+
"menuitemradio",
|
|
24
|
+
"option",
|
|
25
|
+
"radio",
|
|
26
|
+
"textbox"
|
|
27
|
+
];
|
|
28
|
+
var isCustomElement = (element) => {
|
|
29
|
+
return Boolean(element.tagName) && !element.tagName.startsWith("-") && element.tagName.includes("-");
|
|
16
30
|
};
|
|
17
|
-
var
|
|
18
|
-
|
|
19
|
-
borderRadius,
|
|
20
|
-
height,
|
|
21
|
-
transform,
|
|
22
|
-
width,
|
|
23
|
-
x,
|
|
24
|
-
y
|
|
25
|
-
}) => {
|
|
26
|
-
const overlay = document.createElement("div");
|
|
27
|
-
overlay.style.position = "fixed";
|
|
28
|
-
overlay.style.top = `${y}px`;
|
|
29
|
-
overlay.style.left = `${x}px`;
|
|
30
|
-
overlay.style.width = `${width}px`;
|
|
31
|
-
overlay.style.height = `${height}px`;
|
|
32
|
-
overlay.style.borderRadius = borderRadius;
|
|
33
|
-
overlay.style.transform = transform;
|
|
34
|
-
overlay.style.pointerEvents = "none";
|
|
35
|
-
overlay.style.border = "2px solid #007AFF";
|
|
36
|
-
overlay.style.backgroundColor = "rgba(0, 122, 255, 0.1)";
|
|
37
|
-
overlay.style.zIndex = "2147483646";
|
|
38
|
-
overlay.style.boxSizing = "border-box";
|
|
39
|
-
overlay.style.display = "none";
|
|
40
|
-
overlay.animate(
|
|
41
|
-
[
|
|
42
|
-
{ backgroundColor: "rgba(0, 122, 255, 0.1)" },
|
|
43
|
-
{ backgroundColor: "rgba(0, 122, 255, 0.15)" },
|
|
44
|
-
{ backgroundColor: "rgba(0, 122, 255, 0.1)" }
|
|
45
|
-
],
|
|
46
|
-
{
|
|
47
|
-
duration: 2e3,
|
|
48
|
-
easing: "ease-in-out",
|
|
49
|
-
iterations: Infinity
|
|
50
|
-
}
|
|
51
|
-
);
|
|
52
|
-
return overlay;
|
|
31
|
+
var isReadonlyArray = (value) => {
|
|
32
|
+
return Array.isArray(value);
|
|
53
33
|
};
|
|
54
|
-
var
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (element.style.borderRadius !== borderRadius) {
|
|
76
|
-
element.style.borderRadius = borderRadius;
|
|
77
|
-
}
|
|
78
|
-
if (element.style.transform !== transform) {
|
|
79
|
-
element.style.transform = transform;
|
|
34
|
+
var isHotkeyEnabledOnTagName = (event, enabledOnTags = false) => {
|
|
35
|
+
const { composed, target } = event;
|
|
36
|
+
let targetTagName;
|
|
37
|
+
let targetRole;
|
|
38
|
+
if (target instanceof HTMLElement && isCustomElement(target) && composed) {
|
|
39
|
+
const composedPath = event.composedPath();
|
|
40
|
+
const targetElement = composedPath[0];
|
|
41
|
+
if (targetElement instanceof HTMLElement) {
|
|
42
|
+
targetTagName = targetElement.tagName;
|
|
43
|
+
targetRole = targetElement.role;
|
|
44
|
+
}
|
|
45
|
+
} else if (target instanceof HTMLElement) {
|
|
46
|
+
targetTagName = target.tagName;
|
|
47
|
+
targetRole = target.role;
|
|
48
|
+
}
|
|
49
|
+
if (isReadonlyArray(enabledOnTags)) {
|
|
50
|
+
return Boolean(
|
|
51
|
+
targetTagName && enabledOnTags && enabledOnTags.some(
|
|
52
|
+
(tag) => typeof targetTagName === "string" && tag.toLowerCase() === targetTagName.toLowerCase() || tag === targetRole
|
|
53
|
+
)
|
|
54
|
+
);
|
|
80
55
|
}
|
|
56
|
+
return Boolean(targetTagName && enabledOnTags && enabledOnTags);
|
|
81
57
|
};
|
|
82
|
-
var
|
|
83
|
-
|
|
84
|
-
visible = false;
|
|
85
|
-
constructor(root) {
|
|
86
|
-
this.element = createSelectionElement({
|
|
87
|
-
borderRadius: "0px",
|
|
88
|
-
height: 0,
|
|
89
|
-
transform: "none",
|
|
90
|
-
width: 0,
|
|
91
|
-
x: -1e3,
|
|
92
|
-
y: -1e3
|
|
93
|
-
});
|
|
94
|
-
root.appendChild(this.element);
|
|
95
|
-
}
|
|
96
|
-
hide() {
|
|
97
|
-
this.visible = false;
|
|
98
|
-
this.element.style.display = "none";
|
|
99
|
-
this.element.style.pointerEvents = "none";
|
|
100
|
-
}
|
|
101
|
-
isVisible() {
|
|
102
|
-
return this.visible;
|
|
103
|
-
}
|
|
104
|
-
show() {
|
|
105
|
-
this.visible = true;
|
|
106
|
-
this.element.style.display = "block";
|
|
107
|
-
this.element.style.pointerEvents = "auto";
|
|
108
|
-
}
|
|
109
|
-
update(selection) {
|
|
110
|
-
updateSelectionElement(this.element, selection);
|
|
111
|
-
}
|
|
58
|
+
var isKeyboardEventTriggeredByInput = (event) => {
|
|
59
|
+
return isHotkeyEnabledOnTagName(event, FORM_TAGS_AND_ROLES);
|
|
112
60
|
};
|
|
113
|
-
var
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
spinner.style.height = "8px";
|
|
118
|
-
spinner.style.border = "1.5px solid #1e4ed8";
|
|
119
|
-
spinner.style.borderTopColor = "transparent";
|
|
120
|
-
spinner.style.borderRadius = "50%";
|
|
121
|
-
spinner.style.marginRight = "4px";
|
|
122
|
-
spinner.style.verticalAlign = "middle";
|
|
123
|
-
spinner.animate(
|
|
124
|
-
[
|
|
125
|
-
{ transform: "rotate(0deg)" },
|
|
126
|
-
{ transform: "rotate(360deg)" }
|
|
127
|
-
],
|
|
128
|
-
{
|
|
129
|
-
duration: 600,
|
|
130
|
-
easing: "linear",
|
|
131
|
-
iterations: Infinity
|
|
61
|
+
var trackHotkeys = () => {
|
|
62
|
+
const handleKeyDown = (event) => {
|
|
63
|
+
if (isKeyboardEventTriggeredByInput(event)) {
|
|
64
|
+
return;
|
|
132
65
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
66
|
+
if (event.code === undefined) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
libStore.setState((state) => {
|
|
70
|
+
const newTimestamps = new Map(state.keyPressTimestamps);
|
|
71
|
+
if (!state.pressedKeys.has(event.key)) {
|
|
72
|
+
newTimestamps.set(event.key, Date.now());
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
...state,
|
|
76
|
+
keyPressTimestamps: newTimestamps,
|
|
77
|
+
pressedKeys: /* @__PURE__ */ new Set([event.key, ...state.pressedKeys])
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const handleKeyUp = (event) => {
|
|
82
|
+
if (event.code === undefined) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
libStore.setState((state) => {
|
|
86
|
+
const newTimestamps = new Map(state.keyPressTimestamps);
|
|
87
|
+
newTimestamps.delete(event.key);
|
|
88
|
+
return {
|
|
89
|
+
...state,
|
|
90
|
+
keyPressTimestamps: newTimestamps,
|
|
91
|
+
pressedKeys: new Set(
|
|
92
|
+
[...state.pressedKeys].filter((key) => key !== event.key)
|
|
93
|
+
)
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
const handleBlur = () => {
|
|
98
|
+
libStore.setState((state) => ({
|
|
99
|
+
...state,
|
|
100
|
+
keyPressTimestamps: /* @__PURE__ */ new Map(),
|
|
101
|
+
pressedKeys: /* @__PURE__ */ new Set()
|
|
102
|
+
}));
|
|
103
|
+
};
|
|
104
|
+
const handleContextmenu = () => {
|
|
105
|
+
libStore.setState((state) => ({
|
|
106
|
+
...state,
|
|
107
|
+
keyPressTimestamps: /* @__PURE__ */ new Map(),
|
|
108
|
+
pressedKeys: /* @__PURE__ */ new Set()
|
|
109
|
+
}));
|
|
110
|
+
};
|
|
111
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
112
|
+
document.addEventListener("keyup", handleKeyUp);
|
|
113
|
+
window.addEventListener("blur", handleBlur);
|
|
114
|
+
window.addEventListener("contextmenu", handleContextmenu);
|
|
169
115
|
return () => {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
setTimeout(() => {
|
|
175
|
-
document.body.removeChild(indicator);
|
|
176
|
-
}, 200);
|
|
177
|
-
}, 1500);
|
|
116
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
117
|
+
document.removeEventListener("keyup", handleKeyUp);
|
|
118
|
+
window.removeEventListener("blur", handleBlur);
|
|
119
|
+
window.removeEventListener("contextmenu", handleContextmenu);
|
|
178
120
|
};
|
|
179
121
|
};
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
try {
|
|
185
|
-
await navigator.clipboard.writeText(text);
|
|
186
|
-
return true;
|
|
187
|
-
} catch {
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
const textareaEl = document.createElement("textarea");
|
|
191
|
-
textareaEl.value = text;
|
|
192
|
-
textareaEl.setAttribute("readonly", "");
|
|
193
|
-
textareaEl.style.position = "fixed";
|
|
194
|
-
textareaEl.style.top = "-9999px";
|
|
195
|
-
textareaEl.style.opacity = "0";
|
|
196
|
-
textareaEl.style.pointerEvents = "none";
|
|
197
|
-
document.body.appendChild(textareaEl);
|
|
198
|
-
textareaEl.select();
|
|
199
|
-
textareaEl.setSelectionRange(0, textareaEl.value.length);
|
|
200
|
-
let didCopy = false;
|
|
201
|
-
try {
|
|
202
|
-
didCopy = document.execCommand("copy");
|
|
203
|
-
} catch {
|
|
204
|
-
didCopy = false;
|
|
205
|
-
} finally {
|
|
206
|
-
document.body.removeChild(textareaEl);
|
|
122
|
+
var isKeyPressed = (key) => {
|
|
123
|
+
const { pressedKeys } = libStore.getState();
|
|
124
|
+
if (key.length === 1) {
|
|
125
|
+
return pressedKeys.has(key.toLowerCase()) || pressedKeys.has(key.toUpperCase());
|
|
207
126
|
}
|
|
208
|
-
return
|
|
127
|
+
return pressedKeys.has(key);
|
|
128
|
+
};
|
|
129
|
+
var watchKeyHeldFor = (key, duration, onHeld) => {
|
|
130
|
+
let timeoutId = null;
|
|
131
|
+
let unsubscribe = null;
|
|
132
|
+
const cleanup = () => {
|
|
133
|
+
if (timeoutId !== null) {
|
|
134
|
+
clearTimeout(timeoutId);
|
|
135
|
+
timeoutId = null;
|
|
136
|
+
}
|
|
137
|
+
if (unsubscribe !== null) {
|
|
138
|
+
unsubscribe();
|
|
139
|
+
unsubscribe = null;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
const checkSingleKeyPressed = (keyToCheck, pressedKeys) => {
|
|
143
|
+
if (keyToCheck.length === 1) {
|
|
144
|
+
return pressedKeys.has(keyToCheck.toLowerCase()) || pressedKeys.has(keyToCheck.toUpperCase());
|
|
145
|
+
}
|
|
146
|
+
return pressedKeys.has(keyToCheck);
|
|
147
|
+
};
|
|
148
|
+
const checkAllKeysPressed = (pressedKeys) => {
|
|
149
|
+
if (Array.isArray(key)) {
|
|
150
|
+
return key.every(
|
|
151
|
+
(keyFromCombo) => checkSingleKeyPressed(keyFromCombo, pressedKeys)
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
return checkSingleKeyPressed(key, pressedKeys);
|
|
155
|
+
};
|
|
156
|
+
const getKeyFromTimestamps = (keyToFind, timestamps) => {
|
|
157
|
+
if (keyToFind.length === 1) {
|
|
158
|
+
return timestamps.get(keyToFind.toLowerCase()) || timestamps.get(keyToFind.toUpperCase());
|
|
159
|
+
}
|
|
160
|
+
return timestamps.get(keyToFind);
|
|
161
|
+
};
|
|
162
|
+
const getEarliestPressTime = (timestamps) => {
|
|
163
|
+
const keysToInspect = Array.isArray(key) ? key : [key];
|
|
164
|
+
let earliest;
|
|
165
|
+
for (const keyFromCombo of keysToInspect) {
|
|
166
|
+
const timestamp = getKeyFromTimestamps(keyFromCombo, timestamps);
|
|
167
|
+
if (timestamp === undefined) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
if (earliest === undefined || timestamp < earliest) {
|
|
171
|
+
earliest = timestamp;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return earliest;
|
|
175
|
+
};
|
|
176
|
+
const scheduleCallback = () => {
|
|
177
|
+
const state = libStore.getState();
|
|
178
|
+
const { keyPressTimestamps, pressedKeys } = state;
|
|
179
|
+
if (!checkAllKeysPressed(pressedKeys)) {
|
|
180
|
+
if (timeoutId !== null) {
|
|
181
|
+
clearTimeout(timeoutId);
|
|
182
|
+
timeoutId = null;
|
|
183
|
+
}
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const earliestPressTime = getEarliestPressTime(keyPressTimestamps);
|
|
187
|
+
if (earliestPressTime === undefined) {
|
|
188
|
+
if (timeoutId !== null) {
|
|
189
|
+
clearTimeout(timeoutId);
|
|
190
|
+
timeoutId = null;
|
|
191
|
+
}
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const elapsed = Date.now() - earliestPressTime;
|
|
195
|
+
const remaining = duration - elapsed;
|
|
196
|
+
if (remaining <= 0) {
|
|
197
|
+
onHeld();
|
|
198
|
+
cleanup();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (timeoutId !== null) {
|
|
202
|
+
clearTimeout(timeoutId);
|
|
203
|
+
}
|
|
204
|
+
timeoutId = setTimeout(() => {
|
|
205
|
+
onHeld();
|
|
206
|
+
cleanup();
|
|
207
|
+
}, remaining);
|
|
208
|
+
};
|
|
209
|
+
unsubscribe = libStore.subscribe(
|
|
210
|
+
() => {
|
|
211
|
+
scheduleCallback();
|
|
212
|
+
},
|
|
213
|
+
(state) => state.pressedKeys
|
|
214
|
+
);
|
|
215
|
+
scheduleCallback();
|
|
216
|
+
return cleanup;
|
|
209
217
|
};
|
|
210
218
|
|
|
211
219
|
// node_modules/.pnpm/bippy@0.3.31_@types+react@19.2.2_react@19.2.0/node_modules/bippy/dist/src-R2iEnVC1.js
|
|
@@ -306,6 +314,7 @@ var ReactGrab = (function (exports) {
|
|
|
306
314
|
return rdtHook;
|
|
307
315
|
};
|
|
308
316
|
var patchRDTHook = (onActive) => {
|
|
317
|
+
if (onActive) onActiveListeners.add(onActive);
|
|
309
318
|
try {
|
|
310
319
|
const rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
311
320
|
if (!rdtHook) return;
|
|
@@ -386,6 +395,28 @@ var ReactGrab = (function (exports) {
|
|
|
386
395
|
if (!unwrappedType) return null;
|
|
387
396
|
return unwrappedType.displayName || unwrappedType.name || null;
|
|
388
397
|
};
|
|
398
|
+
var instrument = (options) => {
|
|
399
|
+
return getRDTHook(() => {
|
|
400
|
+
const rdtHook = getRDTHook();
|
|
401
|
+
options.onActive?.();
|
|
402
|
+
rdtHook._instrumentationSource = options.name ?? BIPPY_INSTRUMENTATION_STRING;
|
|
403
|
+
const prevOnCommitFiberRoot = rdtHook.onCommitFiberRoot;
|
|
404
|
+
if (options.onCommitFiberRoot) rdtHook.onCommitFiberRoot = (rendererID, root, priority) => {
|
|
405
|
+
if (prevOnCommitFiberRoot) prevOnCommitFiberRoot(rendererID, root, priority);
|
|
406
|
+
options.onCommitFiberRoot?.(rendererID, root, priority);
|
|
407
|
+
};
|
|
408
|
+
const prevOnCommitFiberUnmount = rdtHook.onCommitFiberUnmount;
|
|
409
|
+
if (options.onCommitFiberUnmount) rdtHook.onCommitFiberUnmount = (rendererID, root) => {
|
|
410
|
+
if (prevOnCommitFiberUnmount) prevOnCommitFiberUnmount(rendererID, root);
|
|
411
|
+
options.onCommitFiberUnmount?.(rendererID, root);
|
|
412
|
+
};
|
|
413
|
+
const prevOnPostCommitFiberRoot = rdtHook.onPostCommitFiberRoot;
|
|
414
|
+
if (options.onPostCommitFiberRoot) rdtHook.onPostCommitFiberRoot = (rendererID, root) => {
|
|
415
|
+
if (prevOnPostCommitFiberRoot) prevOnPostCommitFiberRoot(rendererID, root);
|
|
416
|
+
options.onPostCommitFiberRoot?.(rendererID, root);
|
|
417
|
+
};
|
|
418
|
+
});
|
|
419
|
+
};
|
|
389
420
|
var getFiberFromHostInstance = (hostInstance) => {
|
|
390
421
|
const rdtHook = getRDTHook();
|
|
391
422
|
for (const renderer of rdtHook.renderers.values()) try {
|
|
@@ -399,6 +430,7 @@ var ReactGrab = (function (exports) {
|
|
|
399
430
|
}
|
|
400
431
|
return null;
|
|
401
432
|
};
|
|
433
|
+
var _fiberRoots = /* @__PURE__ */ new Set();
|
|
402
434
|
safelyInstallRDTHook();
|
|
403
435
|
|
|
404
436
|
// node_modules/.pnpm/bippy@0.3.31_@types+react@19.2.2_react@19.2.0/node_modules/bippy/dist/source-DWOhEbf2.js
|
|
@@ -2181,14 +2213,18 @@ ${error.stack}`;
|
|
|
2181
2213
|
return matches;
|
|
2182
2214
|
};
|
|
2183
2215
|
|
|
2184
|
-
// src/
|
|
2216
|
+
// src/instrumentation.ts
|
|
2217
|
+
var fiberRoots = _fiberRoots;
|
|
2218
|
+
instrument({
|
|
2219
|
+
onCommitFiberRoot(_, fiberRoot) {
|
|
2220
|
+
fiberRoots.add(fiberRoot);
|
|
2221
|
+
}
|
|
2222
|
+
});
|
|
2185
2223
|
var getStack = async (element) => {
|
|
2186
2224
|
const fiber = getFiberFromHostInstance(element);
|
|
2187
2225
|
if (!fiber) return null;
|
|
2188
2226
|
const stackTrace = getFiberStackTrace(fiber);
|
|
2189
|
-
console.log(stackTrace);
|
|
2190
2227
|
const rawOwnerStack = await getOwnerStack(stackTrace);
|
|
2191
|
-
console.log(rawOwnerStack);
|
|
2192
2228
|
const stack = rawOwnerStack.map((item) => ({
|
|
2193
2229
|
componentName: item.name,
|
|
2194
2230
|
fileName: item.source?.fileName
|
|
@@ -2376,7 +2412,9 @@ ${error.stack}`;
|
|
|
2376
2412
|
lines.push(`${indent2} </${prevSibling.tagName.toLowerCase()}>`);
|
|
2377
2413
|
} else if (targetIndex > 0) {
|
|
2378
2414
|
const indent2 = " ".repeat(ancestors.length);
|
|
2379
|
-
lines.push(
|
|
2415
|
+
lines.push(
|
|
2416
|
+
`${indent2} ... (${targetIndex} element${targetIndex === 1 ? "" : "s"})`
|
|
2417
|
+
);
|
|
2380
2418
|
}
|
|
2381
2419
|
}
|
|
2382
2420
|
}
|
|
@@ -2386,7 +2424,9 @@ ${error.stack}`;
|
|
|
2386
2424
|
const childrenCount = element.children.length;
|
|
2387
2425
|
if (textContent && childrenCount === 0 && textContent.length < 40) {
|
|
2388
2426
|
lines.push(
|
|
2389
|
-
`${indent} ${getElementTag(element)}${textContent}${getClosingTag(
|
|
2427
|
+
`${indent} ${getElementTag(element)}${textContent}${getClosingTag(
|
|
2428
|
+
element
|
|
2429
|
+
)}`
|
|
2390
2430
|
);
|
|
2391
2431
|
} else {
|
|
2392
2432
|
lines.push(indent + " " + getElementTag(element));
|
|
@@ -2423,24 +2463,299 @@ ${error.stack}`;
|
|
|
2423
2463
|
return lines.join("\n");
|
|
2424
2464
|
};
|
|
2425
2465
|
|
|
2426
|
-
// src/
|
|
2427
|
-
var
|
|
2428
|
-
|
|
2429
|
-
|
|
2466
|
+
// src/overlay.ts
|
|
2467
|
+
var VIEWPORT_MARGIN_PX = 8;
|
|
2468
|
+
var LABEL_OFFSET_PX = 6;
|
|
2469
|
+
var INDICATOR_CLAMP_PADDING_PX = 4;
|
|
2470
|
+
var INDICATOR_SUCCESS_VISIBLE_MS = 1500;
|
|
2471
|
+
var INDICATOR_FADE_MS = 200;
|
|
2472
|
+
var INDICATOR_TOTAL_HIDE_DELAY_MS = INDICATOR_SUCCESS_VISIBLE_MS + INDICATOR_FADE_MS;
|
|
2473
|
+
var lerp = (start, end, factor) => {
|
|
2474
|
+
return start + (end - start) * factor;
|
|
2475
|
+
};
|
|
2476
|
+
var SELECTION_LERP_FACTOR = 0.95;
|
|
2477
|
+
var createSelectionElement = ({
|
|
2478
|
+
borderRadius,
|
|
2479
|
+
height,
|
|
2480
|
+
transform,
|
|
2481
|
+
width,
|
|
2482
|
+
x,
|
|
2483
|
+
y
|
|
2484
|
+
}) => {
|
|
2485
|
+
const overlay = document.createElement("div");
|
|
2486
|
+
overlay.style.position = "fixed";
|
|
2487
|
+
overlay.style.top = `${y}px`;
|
|
2488
|
+
overlay.style.left = `${x}px`;
|
|
2489
|
+
overlay.style.width = `${width}px`;
|
|
2490
|
+
overlay.style.height = `${height}px`;
|
|
2491
|
+
overlay.style.borderRadius = borderRadius;
|
|
2492
|
+
overlay.style.transform = transform;
|
|
2493
|
+
overlay.style.pointerEvents = "none";
|
|
2494
|
+
overlay.style.border = "1px solid rgb(210, 57, 192)";
|
|
2495
|
+
overlay.style.backgroundColor = "rgba(210, 57, 192, 0.2)";
|
|
2496
|
+
overlay.style.zIndex = "2147483646";
|
|
2497
|
+
overlay.style.boxSizing = "border-box";
|
|
2498
|
+
overlay.style.display = "none";
|
|
2499
|
+
return overlay;
|
|
2500
|
+
};
|
|
2501
|
+
var updateSelectionElement = (element, { borderRadius, height, transform, width, x, y }) => {
|
|
2502
|
+
const currentTop = parseFloat(element.style.top) || 0;
|
|
2503
|
+
const currentLeft = parseFloat(element.style.left) || 0;
|
|
2504
|
+
const currentWidth = parseFloat(element.style.width) || 0;
|
|
2505
|
+
const currentHeight = parseFloat(element.style.height) || 0;
|
|
2506
|
+
const topValue = `${lerp(currentTop, y, SELECTION_LERP_FACTOR)}px`;
|
|
2507
|
+
const leftValue = `${lerp(currentLeft, x, SELECTION_LERP_FACTOR)}px`;
|
|
2508
|
+
const widthValue = `${lerp(currentWidth, width, SELECTION_LERP_FACTOR)}px`;
|
|
2509
|
+
const heightValue = `${lerp(currentHeight, height, SELECTION_LERP_FACTOR)}px`;
|
|
2510
|
+
if (element.style.top !== topValue) {
|
|
2511
|
+
element.style.top = topValue;
|
|
2512
|
+
}
|
|
2513
|
+
if (element.style.left !== leftValue) {
|
|
2514
|
+
element.style.left = leftValue;
|
|
2515
|
+
}
|
|
2516
|
+
if (element.style.width !== widthValue) {
|
|
2517
|
+
element.style.width = widthValue;
|
|
2518
|
+
}
|
|
2519
|
+
if (element.style.height !== heightValue) {
|
|
2520
|
+
element.style.height = heightValue;
|
|
2521
|
+
}
|
|
2522
|
+
if (element.style.borderRadius !== borderRadius) {
|
|
2523
|
+
element.style.borderRadius = borderRadius;
|
|
2430
2524
|
}
|
|
2431
|
-
|
|
2525
|
+
if (element.style.transform !== transform) {
|
|
2526
|
+
element.style.transform = transform;
|
|
2527
|
+
}
|
|
2528
|
+
};
|
|
2529
|
+
var createSelectionOverlay = (root) => {
|
|
2530
|
+
const element = createSelectionElement({
|
|
2531
|
+
borderRadius: "0px",
|
|
2532
|
+
height: 0,
|
|
2533
|
+
transform: "none",
|
|
2534
|
+
width: 0,
|
|
2535
|
+
x: -1e3,
|
|
2536
|
+
y: -1e3
|
|
2537
|
+
});
|
|
2538
|
+
root.appendChild(element);
|
|
2539
|
+
let visible = false;
|
|
2540
|
+
return {
|
|
2541
|
+
hide: () => {
|
|
2542
|
+
visible = false;
|
|
2543
|
+
element.style.display = "none";
|
|
2544
|
+
element.style.pointerEvents = "none";
|
|
2545
|
+
},
|
|
2546
|
+
isVisible: () => visible,
|
|
2547
|
+
show: () => {
|
|
2548
|
+
visible = true;
|
|
2549
|
+
element.style.display = "block";
|
|
2550
|
+
element.style.pointerEvents = "auto";
|
|
2551
|
+
},
|
|
2552
|
+
update: (selection) => {
|
|
2553
|
+
updateSelectionElement(element, selection);
|
|
2554
|
+
}
|
|
2555
|
+
};
|
|
2556
|
+
};
|
|
2557
|
+
var createSpinner = () => {
|
|
2558
|
+
const spinner = document.createElement("span");
|
|
2559
|
+
spinner.style.display = "inline-block";
|
|
2560
|
+
spinner.style.width = "8px";
|
|
2561
|
+
spinner.style.height = "8px";
|
|
2562
|
+
spinner.style.border = "1.5px solid rgb(210, 57, 192)";
|
|
2563
|
+
spinner.style.borderTopColor = "transparent";
|
|
2564
|
+
spinner.style.borderRadius = "50%";
|
|
2565
|
+
spinner.style.marginRight = "4px";
|
|
2566
|
+
spinner.style.verticalAlign = "middle";
|
|
2567
|
+
spinner.animate(
|
|
2568
|
+
[{ transform: "rotate(0deg)" }, { transform: "rotate(360deg)" }],
|
|
2569
|
+
{
|
|
2570
|
+
duration: 600,
|
|
2571
|
+
easing: "linear",
|
|
2572
|
+
iterations: Infinity
|
|
2573
|
+
}
|
|
2574
|
+
);
|
|
2575
|
+
return spinner;
|
|
2576
|
+
};
|
|
2577
|
+
var activeIndicator = null;
|
|
2578
|
+
var createIndicator = () => {
|
|
2579
|
+
const indicator = document.createElement("div");
|
|
2580
|
+
indicator.style.position = "fixed";
|
|
2581
|
+
indicator.style.top = "calc(8px + env(safe-area-inset-top))";
|
|
2582
|
+
indicator.style.padding = "2px 6px";
|
|
2583
|
+
indicator.style.backgroundColor = "#fde7f7";
|
|
2584
|
+
indicator.style.color = "#b21c8e";
|
|
2585
|
+
indicator.style.border = "1px solid #f7c5ec";
|
|
2586
|
+
indicator.style.borderRadius = "4px";
|
|
2587
|
+
indicator.style.fontSize = "11px";
|
|
2588
|
+
indicator.style.fontWeight = "500";
|
|
2589
|
+
indicator.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif";
|
|
2590
|
+
indicator.style.zIndex = "2147483647";
|
|
2591
|
+
indicator.style.pointerEvents = "none";
|
|
2592
|
+
indicator.style.opacity = "0";
|
|
2593
|
+
indicator.style.transition = "opacity 0.2s ease-in-out";
|
|
2594
|
+
indicator.style.display = "flex";
|
|
2595
|
+
indicator.style.alignItems = "center";
|
|
2596
|
+
indicator.style.maxWidth = "calc(100vw - (16px + env(safe-area-inset-left) + env(safe-area-inset-right)))";
|
|
2597
|
+
indicator.style.overflow = "hidden";
|
|
2598
|
+
indicator.style.textOverflow = "ellipsis";
|
|
2599
|
+
indicator.style.whiteSpace = "nowrap";
|
|
2600
|
+
return indicator;
|
|
2601
|
+
};
|
|
2602
|
+
var showLabel = (selectionLeftPx, selectionTopPx, tagName) => {
|
|
2603
|
+
let indicator = activeIndicator;
|
|
2604
|
+
let isNewIndicator = false;
|
|
2605
|
+
if (!indicator) {
|
|
2606
|
+
indicator = createIndicator();
|
|
2607
|
+
document.body.appendChild(indicator);
|
|
2608
|
+
activeIndicator = indicator;
|
|
2609
|
+
isNewIndicator = true;
|
|
2610
|
+
isProcessing = false;
|
|
2611
|
+
}
|
|
2612
|
+
if (!isProcessing) {
|
|
2613
|
+
const labelText = indicator.querySelector("span");
|
|
2614
|
+
if (labelText) {
|
|
2615
|
+
const tagNameMonospace = document.createElement("span");
|
|
2616
|
+
tagNameMonospace.textContent = tagName ? `<${tagName}>` : "<element>";
|
|
2617
|
+
tagNameMonospace.style.fontFamily = "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace";
|
|
2618
|
+
tagNameMonospace.style.fontVariantNumeric = "tabular-nums";
|
|
2619
|
+
labelText.replaceChildren(tagNameMonospace);
|
|
2620
|
+
} else {
|
|
2621
|
+
const newLabelText = document.createElement("span");
|
|
2622
|
+
const tagNameMonospace = document.createElement("span");
|
|
2623
|
+
tagNameMonospace.textContent = tagName ? `<${tagName}>` : "<element>";
|
|
2624
|
+
tagNameMonospace.style.fontFamily = "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace";
|
|
2625
|
+
tagNameMonospace.style.fontVariantNumeric = "tabular-nums";
|
|
2626
|
+
newLabelText.appendChild(tagNameMonospace);
|
|
2627
|
+
indicator.appendChild(newLabelText);
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
const indicatorRect = indicator.getBoundingClientRect();
|
|
2631
|
+
const viewportWidthPx = window.innerWidth;
|
|
2632
|
+
const viewportHeightPx = window.innerHeight;
|
|
2633
|
+
let indicatorLeftPx = Math.round(selectionLeftPx);
|
|
2634
|
+
let indicatorTopPx = Math.round(selectionTopPx) - indicatorRect.height - LABEL_OFFSET_PX;
|
|
2635
|
+
const CLAMPED_PADDING = INDICATOR_CLAMP_PADDING_PX;
|
|
2636
|
+
const minLeft = VIEWPORT_MARGIN_PX;
|
|
2637
|
+
const minTop = VIEWPORT_MARGIN_PX;
|
|
2638
|
+
const maxLeft = viewportWidthPx - indicatorRect.width - VIEWPORT_MARGIN_PX;
|
|
2639
|
+
const maxTop = viewportHeightPx - indicatorRect.height - VIEWPORT_MARGIN_PX;
|
|
2640
|
+
const willClampLeft = indicatorLeftPx < minLeft;
|
|
2641
|
+
const willClampTop = indicatorTopPx < minTop;
|
|
2642
|
+
const isClamped = willClampLeft || willClampTop;
|
|
2643
|
+
indicatorLeftPx = Math.max(minLeft, Math.min(indicatorLeftPx, maxLeft));
|
|
2644
|
+
indicatorTopPx = Math.max(minTop, Math.min(indicatorTopPx, maxTop));
|
|
2645
|
+
if (isClamped) {
|
|
2646
|
+
indicatorLeftPx += CLAMPED_PADDING;
|
|
2647
|
+
indicatorTopPx += CLAMPED_PADDING;
|
|
2648
|
+
}
|
|
2649
|
+
indicator.style.left = `${indicatorLeftPx}px`;
|
|
2650
|
+
indicator.style.top = `${indicatorTopPx}px`;
|
|
2651
|
+
indicator.style.right = "auto";
|
|
2652
|
+
if (isNewIndicator) {
|
|
2653
|
+
requestAnimationFrame(() => {
|
|
2654
|
+
indicator.style.opacity = "1";
|
|
2655
|
+
});
|
|
2656
|
+
} else if (indicator.style.opacity !== "1") {
|
|
2657
|
+
indicator.style.opacity = "1";
|
|
2658
|
+
}
|
|
2659
|
+
};
|
|
2660
|
+
var isProcessing = false;
|
|
2661
|
+
var updateLabelToProcessing = () => {
|
|
2662
|
+
if (!activeIndicator || isProcessing) return () => {
|
|
2663
|
+
};
|
|
2664
|
+
isProcessing = true;
|
|
2665
|
+
const indicator = activeIndicator;
|
|
2666
|
+
indicator.innerHTML = "";
|
|
2667
|
+
const loadingSpinner = createSpinner();
|
|
2668
|
+
const labelText = document.createElement("span");
|
|
2669
|
+
labelText.textContent = "Grabbing\u2026";
|
|
2670
|
+
indicator.appendChild(loadingSpinner);
|
|
2671
|
+
indicator.appendChild(labelText);
|
|
2672
|
+
return (tagName) => {
|
|
2673
|
+
if (!activeIndicator) {
|
|
2674
|
+
isProcessing = false;
|
|
2675
|
+
return;
|
|
2676
|
+
}
|
|
2677
|
+
indicator.textContent = "";
|
|
2678
|
+
const checkmarkIcon = document.createElement("span");
|
|
2679
|
+
checkmarkIcon.textContent = "\u2713";
|
|
2680
|
+
checkmarkIcon.style.display = "inline-block";
|
|
2681
|
+
checkmarkIcon.style.marginRight = "4px";
|
|
2682
|
+
checkmarkIcon.style.fontWeight = "600";
|
|
2683
|
+
const newLabelText = document.createElement("span");
|
|
2684
|
+
const tagNameMonospace = document.createElement("span");
|
|
2685
|
+
tagNameMonospace.textContent = tagName ? `<${tagName}>` : "<element>";
|
|
2686
|
+
tagNameMonospace.style.fontFamily = "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace";
|
|
2687
|
+
tagNameMonospace.style.fontVariantNumeric = "tabular-nums";
|
|
2688
|
+
newLabelText.appendChild(document.createTextNode("Grabbed "));
|
|
2689
|
+
newLabelText.appendChild(tagNameMonospace);
|
|
2690
|
+
indicator.appendChild(checkmarkIcon);
|
|
2691
|
+
indicator.appendChild(newLabelText);
|
|
2692
|
+
setTimeout(() => {
|
|
2693
|
+
indicator.style.opacity = "0";
|
|
2694
|
+
setTimeout(() => {
|
|
2695
|
+
indicator.remove();
|
|
2696
|
+
if (activeIndicator === indicator) {
|
|
2697
|
+
activeIndicator = null;
|
|
2698
|
+
}
|
|
2699
|
+
isProcessing = false;
|
|
2700
|
+
}, INDICATOR_FADE_MS);
|
|
2701
|
+
}, INDICATOR_SUCCESS_VISIBLE_MS);
|
|
2702
|
+
};
|
|
2703
|
+
};
|
|
2704
|
+
var hideLabel = () => {
|
|
2705
|
+
if (activeIndicator) {
|
|
2706
|
+
activeIndicator.remove();
|
|
2707
|
+
activeIndicator = null;
|
|
2708
|
+
}
|
|
2709
|
+
isProcessing = false;
|
|
2710
|
+
};
|
|
2711
|
+
|
|
2712
|
+
// src/utils/copy-text.ts
|
|
2713
|
+
var IS_NAVIGATOR_CLIPBOARD_AVAILABLE = typeof window !== "undefined" && window.navigator.clipboard && window.isSecureContext;
|
|
2714
|
+
var copyTextToClipboard = async (text) => {
|
|
2715
|
+
if (IS_NAVIGATOR_CLIPBOARD_AVAILABLE) {
|
|
2716
|
+
try {
|
|
2717
|
+
await navigator.clipboard.writeText(text);
|
|
2718
|
+
return true;
|
|
2719
|
+
} catch {
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
const textareaElement = document.createElement("textarea");
|
|
2723
|
+
textareaElement.value = text;
|
|
2724
|
+
textareaElement.setAttribute("readonly", "");
|
|
2725
|
+
textareaElement.style.position = "fixed";
|
|
2726
|
+
textareaElement.style.top = "-9999px";
|
|
2727
|
+
textareaElement.style.opacity = "0";
|
|
2728
|
+
textareaElement.style.pointerEvents = "none";
|
|
2729
|
+
const doc = document.body || document.documentElement;
|
|
2730
|
+
doc.appendChild(textareaElement);
|
|
2731
|
+
textareaElement.select();
|
|
2732
|
+
textareaElement.setSelectionRange(0, textareaElement.value.length);
|
|
2733
|
+
let didCopyToClipboard = false;
|
|
2734
|
+
try {
|
|
2735
|
+
didCopyToClipboard = document.execCommand("copy");
|
|
2736
|
+
} catch {
|
|
2737
|
+
didCopyToClipboard = false;
|
|
2738
|
+
} finally {
|
|
2739
|
+
doc.removeChild(textareaElement);
|
|
2740
|
+
}
|
|
2741
|
+
return didCopyToClipboard;
|
|
2742
|
+
};
|
|
2743
|
+
|
|
2744
|
+
// src/utils/is-element-visible.ts
|
|
2745
|
+
var isElementVisible = (element, computedStyle = window.getComputedStyle(element)) => {
|
|
2746
|
+
return computedStyle.display !== "none" && computedStyle.visibility !== "hidden" && computedStyle.opacity !== "0";
|
|
2432
2747
|
};
|
|
2433
2748
|
|
|
2434
2749
|
// src/utils/mount-root.ts
|
|
2435
2750
|
var ATTRIBUTE_NAME = "data-react-grab";
|
|
2436
2751
|
var mountRoot = () => {
|
|
2437
|
-
const
|
|
2438
|
-
if (
|
|
2439
|
-
const
|
|
2752
|
+
const mountedHost = document.querySelector(`[${ATTRIBUTE_NAME}]`);
|
|
2753
|
+
if (mountedHost) {
|
|
2754
|
+
const mountedRoot = mountedHost.shadowRoot?.querySelector(
|
|
2440
2755
|
`[${ATTRIBUTE_NAME}]`
|
|
2441
2756
|
);
|
|
2442
|
-
if (
|
|
2443
|
-
return
|
|
2757
|
+
if (mountedRoot instanceof HTMLDivElement && mountedHost.shadowRoot) {
|
|
2758
|
+
return mountedRoot;
|
|
2444
2759
|
}
|
|
2445
2760
|
}
|
|
2446
2761
|
const host = document.createElement("div");
|
|
@@ -2451,7 +2766,6 @@ ${error.stack}`;
|
|
|
2451
2766
|
host.style.left = "0";
|
|
2452
2767
|
const shadowRoot = host.attachShadow({ mode: "open" });
|
|
2453
2768
|
const root = document.createElement("div");
|
|
2454
|
-
root.style.transition = "opacity 0.1s ease-out";
|
|
2455
2769
|
root.setAttribute(ATTRIBUTE_NAME, "true");
|
|
2456
2770
|
shadowRoot.appendChild(root);
|
|
2457
2771
|
const doc = document.body ?? document.documentElement;
|
|
@@ -2472,6 +2786,77 @@ ${error.stack}`;
|
|
|
2472
2786
|
return setTimeout(callback, 0);
|
|
2473
2787
|
};
|
|
2474
2788
|
|
|
2789
|
+
// src/utils/store.ts
|
|
2790
|
+
var createStore = (initializer) => {
|
|
2791
|
+
const subscriberMap = /* @__PURE__ */ new Map();
|
|
2792
|
+
let currentListenerIndex = 0;
|
|
2793
|
+
let currentState;
|
|
2794
|
+
const setState = (maybeStateOrReducer) => {
|
|
2795
|
+
const prevState = currentState;
|
|
2796
|
+
const resolvedState = typeof maybeStateOrReducer === "function" ? maybeStateOrReducer(prevState) : maybeStateOrReducer;
|
|
2797
|
+
const nextState = {
|
|
2798
|
+
...prevState,
|
|
2799
|
+
...resolvedState
|
|
2800
|
+
};
|
|
2801
|
+
currentState = nextState;
|
|
2802
|
+
for (const entry of subscriberMap.values()) {
|
|
2803
|
+
if (entry.type === "selected" /* Selected */) {
|
|
2804
|
+
const nextSelectedValue = entry.selector(nextState);
|
|
2805
|
+
const prevSelectedValue = entry.prevSelectedValue;
|
|
2806
|
+
if (!Object.is(prevSelectedValue, nextSelectedValue)) {
|
|
2807
|
+
entry.prevSelectedValue = nextSelectedValue;
|
|
2808
|
+
entry.listener(nextSelectedValue, prevSelectedValue);
|
|
2809
|
+
}
|
|
2810
|
+
} else {
|
|
2811
|
+
entry.listener(nextState, prevState);
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
return currentState;
|
|
2815
|
+
};
|
|
2816
|
+
const getState = () => {
|
|
2817
|
+
return currentState;
|
|
2818
|
+
};
|
|
2819
|
+
const initialState = initializer(setState, getState);
|
|
2820
|
+
currentState = initialState;
|
|
2821
|
+
const subscribeWithSelector = (listener, selector) => {
|
|
2822
|
+
const index = String(currentListenerIndex++);
|
|
2823
|
+
const wrappedListener = (value, prevValue) => listener(value, prevValue);
|
|
2824
|
+
const entry = {
|
|
2825
|
+
listener: wrappedListener,
|
|
2826
|
+
prevSelectedValue: selector(currentState),
|
|
2827
|
+
selector,
|
|
2828
|
+
type: "selected" /* Selected */
|
|
2829
|
+
};
|
|
2830
|
+
subscriberMap.set(index, entry);
|
|
2831
|
+
return () => {
|
|
2832
|
+
subscriberMap.delete(index);
|
|
2833
|
+
};
|
|
2834
|
+
};
|
|
2835
|
+
const subscribeToFullState = (listener) => {
|
|
2836
|
+
const index = String(currentListenerIndex++);
|
|
2837
|
+
const entry = {
|
|
2838
|
+
listener,
|
|
2839
|
+
type: "full" /* Full */
|
|
2840
|
+
};
|
|
2841
|
+
subscriberMap.set(index, entry);
|
|
2842
|
+
return () => {
|
|
2843
|
+
subscriberMap.delete(index);
|
|
2844
|
+
};
|
|
2845
|
+
};
|
|
2846
|
+
function subscribe(subscriber, selector) {
|
|
2847
|
+
return selector ? subscribeWithSelector(subscriber, selector) : subscribeToFullState(subscriber);
|
|
2848
|
+
}
|
|
2849
|
+
const store = {
|
|
2850
|
+
getInitialState() {
|
|
2851
|
+
return initialState;
|
|
2852
|
+
},
|
|
2853
|
+
getState,
|
|
2854
|
+
setState,
|
|
2855
|
+
subscribe
|
|
2856
|
+
};
|
|
2857
|
+
return store;
|
|
2858
|
+
};
|
|
2859
|
+
|
|
2475
2860
|
// src/utils/throttle.ts
|
|
2476
2861
|
var throttle = (fn, delay) => {
|
|
2477
2862
|
let timeout = null;
|
|
@@ -2494,167 +2879,288 @@ ${error.stack}`;
|
|
|
2494
2879
|
};
|
|
2495
2880
|
|
|
2496
2881
|
// src/index.ts
|
|
2497
|
-
var TICK_INTERVAL = 50;
|
|
2498
2882
|
var THROTTLE_DELAY = 16;
|
|
2499
|
-
var
|
|
2883
|
+
var libStore = createStore(() => ({
|
|
2884
|
+
keyPressTimestamps: /* @__PURE__ */ new Map(),
|
|
2885
|
+
mouseX: -1e3,
|
|
2886
|
+
mouseY: -1e3,
|
|
2887
|
+
overlayMode: "hidden",
|
|
2888
|
+
pressedKeys: /* @__PURE__ */ new Set()
|
|
2889
|
+
}));
|
|
2890
|
+
var init = (options = {}) => {
|
|
2891
|
+
if (options.enabled === false) {
|
|
2892
|
+
return;
|
|
2893
|
+
}
|
|
2894
|
+
const resolvedOptions = {
|
|
2895
|
+
enabled: true,
|
|
2896
|
+
hotkey: ["Meta", "C"],
|
|
2897
|
+
keyHoldDuration: 500,
|
|
2898
|
+
...options
|
|
2899
|
+
};
|
|
2500
2900
|
const root = mountRoot();
|
|
2501
|
-
|
|
2502
|
-
let
|
|
2503
|
-
let
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2901
|
+
const selectionOverlay = createSelectionOverlay(root);
|
|
2902
|
+
let hoveredElement = null;
|
|
2903
|
+
let isCopying = false;
|
|
2904
|
+
const checkIsActivationHotkeyPressed = () => {
|
|
2905
|
+
if (Array.isArray(resolvedOptions.hotkey)) {
|
|
2906
|
+
for (const key of resolvedOptions.hotkey) {
|
|
2907
|
+
if (!isKeyPressed(key)) {
|
|
2908
|
+
return false;
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
return true;
|
|
2912
|
+
}
|
|
2913
|
+
return isKeyPressed(resolvedOptions.hotkey);
|
|
2914
|
+
};
|
|
2915
|
+
let cleanupActivationHotkeyWatcher = null;
|
|
2916
|
+
const handleKeyStateChange = (pressedKeys) => {
|
|
2917
|
+
const { overlayMode } = libStore.getState();
|
|
2918
|
+
if (pressedKeys.has("Escape") || pressedKeys.has("Esc")) {
|
|
2919
|
+
libStore.setState((state) => {
|
|
2920
|
+
const nextPressedKeys = new Set(state.pressedKeys);
|
|
2921
|
+
nextPressedKeys.delete("Escape");
|
|
2922
|
+
nextPressedKeys.delete("Esc");
|
|
2923
|
+
const nextTimestamps = new Map(state.keyPressTimestamps);
|
|
2924
|
+
nextTimestamps.delete("Escape");
|
|
2925
|
+
nextTimestamps.delete("Esc");
|
|
2926
|
+
const activationKeys = Array.isArray(resolvedOptions.hotkey) ? resolvedOptions.hotkey : [resolvedOptions.hotkey];
|
|
2927
|
+
for (const activationKey of activationKeys) {
|
|
2928
|
+
if (activationKey.length === 1) {
|
|
2929
|
+
nextPressedKeys.delete(activationKey.toLowerCase());
|
|
2930
|
+
nextPressedKeys.delete(activationKey.toUpperCase());
|
|
2931
|
+
nextTimestamps.delete(activationKey.toLowerCase());
|
|
2932
|
+
nextTimestamps.delete(activationKey.toUpperCase());
|
|
2933
|
+
} else {
|
|
2934
|
+
nextPressedKeys.delete(activationKey);
|
|
2935
|
+
nextTimestamps.delete(activationKey);
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
return {
|
|
2939
|
+
...state,
|
|
2940
|
+
keyPressTimestamps: nextTimestamps,
|
|
2941
|
+
overlayMode: "hidden",
|
|
2942
|
+
pressedKeys: nextPressedKeys
|
|
2943
|
+
};
|
|
2944
|
+
});
|
|
2945
|
+
if (cleanupActivationHotkeyWatcher) {
|
|
2946
|
+
cleanupActivationHotkeyWatcher();
|
|
2947
|
+
cleanupActivationHotkeyWatcher = null;
|
|
2948
|
+
}
|
|
2515
2949
|
return;
|
|
2516
2950
|
}
|
|
2517
|
-
const
|
|
2518
|
-
if (!
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2951
|
+
const isActivationHotkeyPressed = checkIsActivationHotkeyPressed();
|
|
2952
|
+
if (!isActivationHotkeyPressed) {
|
|
2953
|
+
if (cleanupActivationHotkeyWatcher) {
|
|
2954
|
+
cleanupActivationHotkeyWatcher();
|
|
2955
|
+
cleanupActivationHotkeyWatcher = null;
|
|
2956
|
+
}
|
|
2957
|
+
if (overlayMode !== "hidden") {
|
|
2958
|
+
libStore.setState((state) => ({
|
|
2959
|
+
...state,
|
|
2960
|
+
overlayMode: "hidden"
|
|
2961
|
+
}));
|
|
2962
|
+
}
|
|
2963
|
+
return;
|
|
2964
|
+
}
|
|
2965
|
+
if (overlayMode === "hidden" && !cleanupActivationHotkeyWatcher) {
|
|
2966
|
+
cleanupActivationHotkeyWatcher = watchKeyHeldFor(
|
|
2967
|
+
resolvedOptions.hotkey,
|
|
2968
|
+
resolvedOptions.keyHoldDuration,
|
|
2969
|
+
() => {
|
|
2970
|
+
libStore.setState((state) => ({
|
|
2971
|
+
...state,
|
|
2972
|
+
overlayMode: "visible"
|
|
2973
|
+
}));
|
|
2974
|
+
cleanupActivationHotkeyWatcher = null;
|
|
2975
|
+
}
|
|
2976
|
+
);
|
|
2977
|
+
}
|
|
2529
2978
|
};
|
|
2530
|
-
const
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2979
|
+
const cleanupKeyStateChangeSubscription = libStore.subscribe(
|
|
2980
|
+
handleKeyStateChange,
|
|
2981
|
+
(state) => state.pressedKeys
|
|
2982
|
+
);
|
|
2983
|
+
const handleMouseMove = throttle((event) => {
|
|
2984
|
+
libStore.setState((state) => ({
|
|
2985
|
+
...state,
|
|
2986
|
+
mouseX: event.clientX,
|
|
2987
|
+
mouseY: event.clientY
|
|
2988
|
+
}));
|
|
2534
2989
|
}, THROTTLE_DELAY);
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
if (
|
|
2558
|
-
|
|
2990
|
+
const handleMouseDown = (event) => {
|
|
2991
|
+
if (event.button !== 0) {
|
|
2992
|
+
return;
|
|
2993
|
+
}
|
|
2994
|
+
const { overlayMode } = libStore.getState();
|
|
2995
|
+
if (overlayMode === "hidden") {
|
|
2996
|
+
return;
|
|
2997
|
+
}
|
|
2998
|
+
event.preventDefault();
|
|
2999
|
+
event.stopPropagation();
|
|
3000
|
+
event.stopImmediatePropagation();
|
|
3001
|
+
libStore.setState((state) => ({
|
|
3002
|
+
...state,
|
|
3003
|
+
overlayMode: "copying"
|
|
3004
|
+
}));
|
|
3005
|
+
};
|
|
3006
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
3007
|
+
window.addEventListener("mousedown", handleMouseDown);
|
|
3008
|
+
const cleanupTrackHotkeys = trackHotkeys();
|
|
3009
|
+
const getElementAtPosition = (x, y) => {
|
|
3010
|
+
const elements = document.elementsFromPoint(x, y);
|
|
3011
|
+
for (const element of elements) {
|
|
3012
|
+
if (element.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
3013
|
+
continue;
|
|
2559
3014
|
}
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
}
|
|
3015
|
+
const computedStyle = window.getComputedStyle(element);
|
|
3016
|
+
if (!isElementVisible(element, computedStyle)) {
|
|
3017
|
+
continue;
|
|
3018
|
+
}
|
|
3019
|
+
return element;
|
|
2564
3020
|
}
|
|
2565
|
-
|
|
3021
|
+
return null;
|
|
3022
|
+
};
|
|
3023
|
+
const handleCopy = async (element) => {
|
|
3024
|
+
const cleanupIndicator = updateLabelToProcessing();
|
|
3025
|
+
try {
|
|
3026
|
+
const stack = await getStack(element);
|
|
3027
|
+
const htmlSnippet = getHTMLSnippet(element);
|
|
3028
|
+
let text = htmlSnippet;
|
|
3029
|
+
if (stack) {
|
|
3030
|
+
const filteredStack = filterStack(stack);
|
|
3031
|
+
const serializedStack = serializeStack(filteredStack);
|
|
3032
|
+
text = `${htmlSnippet}
|
|
3033
|
+
|
|
3034
|
+
Component owner stack:
|
|
3035
|
+
${serializedStack}`;
|
|
3036
|
+
}
|
|
3037
|
+
await copyTextToClipboard(
|
|
3038
|
+
`
|
|
3039
|
+
|
|
3040
|
+
<referenced_element>
|
|
3041
|
+
${text}
|
|
3042
|
+
</referenced_element>`
|
|
3043
|
+
);
|
|
3044
|
+
const tagName = (element.tagName || "").toLowerCase();
|
|
3045
|
+
cleanupIndicator(tagName);
|
|
3046
|
+
} catch {
|
|
3047
|
+
cleanupIndicator();
|
|
3048
|
+
}
|
|
3049
|
+
};
|
|
3050
|
+
const handleRender = throttle((state) => {
|
|
3051
|
+
const { mouseX, mouseY, overlayMode } = state;
|
|
3052
|
+
if (overlayMode === "hidden") {
|
|
2566
3053
|
if (selectionOverlay.isVisible()) {
|
|
2567
3054
|
selectionOverlay.hide();
|
|
2568
|
-
if (
|
|
2569
|
-
|
|
2570
|
-
shiftKeyTimeout = null;
|
|
3055
|
+
if (!isCopying) {
|
|
3056
|
+
hideLabel();
|
|
2571
3057
|
}
|
|
3058
|
+
hoveredElement = null;
|
|
2572
3059
|
}
|
|
3060
|
+
return;
|
|
2573
3061
|
}
|
|
2574
|
-
if (
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
const serializedStack = serializeStack(filteredStack);
|
|
2588
|
-
output = `${serializedStack}
|
|
2589
|
-
|
|
2590
|
-
${htmlSnippet}`;
|
|
2591
|
-
}
|
|
2592
|
-
return copyText(output);
|
|
2593
|
-
}).then((success) => {
|
|
2594
|
-
if (success) {
|
|
2595
|
-
showSuccess();
|
|
2596
|
-
}
|
|
2597
|
-
}).catch(() => {
|
|
2598
|
-
});
|
|
3062
|
+
if (overlayMode === "copying" && hoveredElement) {
|
|
3063
|
+
const computedStyle2 = window.getComputedStyle(hoveredElement);
|
|
3064
|
+
const rect2 = hoveredElement.getBoundingClientRect();
|
|
3065
|
+
selectionOverlay.update({
|
|
3066
|
+
borderRadius: computedStyle2.borderRadius || "0px",
|
|
3067
|
+
height: rect2.height,
|
|
3068
|
+
transform: computedStyle2.transform || "none",
|
|
3069
|
+
width: rect2.width,
|
|
3070
|
+
x: rect2.left,
|
|
3071
|
+
y: rect2.top
|
|
3072
|
+
});
|
|
3073
|
+
if (!selectionOverlay.isVisible()) {
|
|
3074
|
+
selectionOverlay.show();
|
|
2599
3075
|
}
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
const showSuccess = showCopyIndicator(rect.left, rect.top);
|
|
2612
|
-
getStack(element).then((stack) => {
|
|
2613
|
-
const htmlSnippet = getHTMLSnippet(element);
|
|
2614
|
-
let output = htmlSnippet;
|
|
2615
|
-
if (stack) {
|
|
2616
|
-
const filteredStack = filterStack(stack);
|
|
2617
|
-
const serializedStack = serializeStack(filteredStack);
|
|
2618
|
-
output = `## Referenced element:
|
|
2619
|
-
${htmlSnippet}
|
|
2620
|
-
Stack trace:
|
|
2621
|
-
${serializedStack}
|
|
2622
|
-
|
|
2623
|
-
Path: ${window.location.pathname}`;
|
|
2624
|
-
}
|
|
2625
|
-
return copyText(output);
|
|
2626
|
-
}).then((success) => {
|
|
2627
|
-
if (success) {
|
|
2628
|
-
showSuccess();
|
|
2629
|
-
}
|
|
2630
|
-
}).catch(() => {
|
|
3076
|
+
if (!isCopying) {
|
|
3077
|
+
isCopying = true;
|
|
3078
|
+
void handleCopy(hoveredElement).finally(() => {
|
|
3079
|
+
libStore.setState((state2) => ({
|
|
3080
|
+
...state2,
|
|
3081
|
+
overlayMode: "hidden"
|
|
3082
|
+
}));
|
|
3083
|
+
selectionOverlay.hide();
|
|
3084
|
+
window.setTimeout(() => {
|
|
3085
|
+
isCopying = false;
|
|
3086
|
+
}, INDICATOR_TOTAL_HIDE_DELAY_MS);
|
|
2631
3087
|
});
|
|
2632
3088
|
}
|
|
3089
|
+
return;
|
|
2633
3090
|
}
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
3091
|
+
const element = getElementAtPosition(mouseX, mouseY);
|
|
3092
|
+
if (!element) {
|
|
3093
|
+
if (selectionOverlay.isVisible()) {
|
|
3094
|
+
selectionOverlay.hide();
|
|
3095
|
+
if (!isCopying) {
|
|
3096
|
+
hideLabel();
|
|
3097
|
+
}
|
|
2640
3098
|
}
|
|
2641
|
-
|
|
3099
|
+
hoveredElement = null;
|
|
3100
|
+
return;
|
|
3101
|
+
}
|
|
3102
|
+
const tagName = (element.tagName || "").toLowerCase();
|
|
3103
|
+
hoveredElement = element;
|
|
3104
|
+
const rect = element.getBoundingClientRect();
|
|
3105
|
+
const computedStyle = window.getComputedStyle(element);
|
|
3106
|
+
const borderRadius = computedStyle.borderRadius || "0px";
|
|
3107
|
+
const transform = computedStyle.transform || "none";
|
|
3108
|
+
selectionOverlay.update({
|
|
3109
|
+
borderRadius,
|
|
3110
|
+
height: rect.height,
|
|
3111
|
+
transform,
|
|
3112
|
+
width: rect.width,
|
|
3113
|
+
x: rect.left,
|
|
3114
|
+
y: rect.top
|
|
3115
|
+
});
|
|
3116
|
+
if (!selectionOverlay.isVisible()) {
|
|
3117
|
+
selectionOverlay.show();
|
|
2642
3118
|
}
|
|
3119
|
+
showLabel(rect.left, rect.top, tagName);
|
|
3120
|
+
}, 10);
|
|
3121
|
+
const cleanupRenderSubscription = libStore.subscribe((state) => {
|
|
3122
|
+
scheduleRunWhenIdle(() => {
|
|
3123
|
+
handleRender(state);
|
|
3124
|
+
});
|
|
2643
3125
|
});
|
|
3126
|
+
let timeout = null;
|
|
3127
|
+
const render = () => {
|
|
3128
|
+
timeout = window.setTimeout(() => {
|
|
3129
|
+
scheduleRunWhenIdle(() => {
|
|
3130
|
+
handleRender(libStore.getState());
|
|
3131
|
+
render();
|
|
3132
|
+
});
|
|
3133
|
+
}, 100);
|
|
3134
|
+
};
|
|
3135
|
+
render();
|
|
2644
3136
|
return () => {
|
|
3137
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
3138
|
+
window.removeEventListener("mousedown", handleMouseDown);
|
|
3139
|
+
cleanupTrackHotkeys();
|
|
3140
|
+
cleanupRenderSubscription();
|
|
3141
|
+
cleanupKeyStateChangeSubscription();
|
|
2645
3142
|
if (timeout) {
|
|
2646
3143
|
window.clearTimeout(timeout);
|
|
2647
|
-
timeout = null;
|
|
2648
3144
|
}
|
|
2649
|
-
if (
|
|
2650
|
-
|
|
2651
|
-
shiftKeyTimeout = null;
|
|
3145
|
+
if (cleanupActivationHotkeyWatcher) {
|
|
3146
|
+
cleanupActivationHotkeyWatcher();
|
|
2652
3147
|
}
|
|
2653
|
-
root.remove();
|
|
2654
|
-
throttledRender.cancel();
|
|
2655
3148
|
};
|
|
2656
3149
|
};
|
|
2657
|
-
|
|
3150
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
3151
|
+
const currentScript = document.currentScript;
|
|
3152
|
+
let options = {};
|
|
3153
|
+
if (currentScript) {
|
|
3154
|
+
const maybeOptions = currentScript.getAttribute("data-options");
|
|
3155
|
+
if (maybeOptions) {
|
|
3156
|
+
try {
|
|
3157
|
+
options = JSON.parse(maybeOptions);
|
|
3158
|
+
} catch {
|
|
3159
|
+
}
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
init(options);
|
|
3163
|
+
}
|
|
2658
3164
|
/*! Bundled license information:
|
|
2659
3165
|
|
|
2660
3166
|
bippy/dist/src-R2iEnVC1.js:
|
|
@@ -2699,6 +3205,7 @@ Path: ${window.location.pathname}`;
|
|
|
2699
3205
|
*/
|
|
2700
3206
|
|
|
2701
3207
|
exports.init = init;
|
|
3208
|
+
exports.libStore = libStore;
|
|
2702
3209
|
|
|
2703
3210
|
return exports;
|
|
2704
3211
|
|