react-grab 0.0.20 → 0.0.23
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.cjs +931 -1074
- package/dist/index.d.cts +1 -46
- package/dist/index.d.ts +1 -46
- package/dist/index.global.js +54 -26
- package/dist/index.js +932 -1073
- package/package.json +11 -21
- package/dist/plugins/vite.cjs +0 -46
- package/dist/plugins/vite.d.cts +0 -14
- package/dist/plugins/vite.d.ts +0 -14
- package/dist/plugins/vite.js +0 -44
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var web = require('solid-js/web');
|
|
4
|
+
var solidJs = require('solid-js');
|
|
3
5
|
var bippy = require('bippy');
|
|
4
6
|
var source = require('bippy/dist/source');
|
|
5
7
|
|
|
@@ -12,18 +14,8 @@ var source = require('bippy/dist/source');
|
|
|
12
14
|
* LICENSE file in the root directory of this source tree.
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
|
-
// src/adapters.ts
|
|
16
|
-
var cursorAdapter = {
|
|
17
|
-
name: "cursor",
|
|
18
|
-
open: (promptText) => {
|
|
19
|
-
if (!promptText) return;
|
|
20
|
-
const url = new URL("cursor://anysphere.cursor-deeplink/prompt");
|
|
21
|
-
url.searchParams.set("text", promptText);
|
|
22
|
-
window.open(url.toString(), "_blank");
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
17
|
|
|
26
|
-
// src/
|
|
18
|
+
// src/utils/is-keyboard-event-triggered-by-input.ts
|
|
27
19
|
var FORM_TAGS_AND_ROLES = [
|
|
28
20
|
"input",
|
|
29
21
|
"textarea",
|
|
@@ -71,194 +63,481 @@ var isHotkeyEnabledOnTagName = (event, enabledOnTags = false) => {
|
|
|
71
63
|
var isKeyboardEventTriggeredByInput = (event) => {
|
|
72
64
|
return isHotkeyEnabledOnTagName(event, FORM_TAGS_AND_ROLES);
|
|
73
65
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
66
|
+
|
|
67
|
+
// src/utils/mount-root.ts
|
|
68
|
+
var ATTRIBUTE_NAME = "data-react-grab";
|
|
69
|
+
var mountRoot = () => {
|
|
70
|
+
const mountedHost = document.querySelector(`[${ATTRIBUTE_NAME}]`);
|
|
71
|
+
if (mountedHost) {
|
|
72
|
+
const mountedRoot = mountedHost.shadowRoot?.querySelector(
|
|
73
|
+
`[${ATTRIBUTE_NAME}]`
|
|
74
|
+
);
|
|
75
|
+
if (mountedRoot instanceof HTMLDivElement && mountedHost.shadowRoot) {
|
|
76
|
+
return mountedRoot;
|
|
78
77
|
}
|
|
79
|
-
|
|
78
|
+
}
|
|
79
|
+
const host = document.createElement("div");
|
|
80
|
+
host.setAttribute(ATTRIBUTE_NAME, "true");
|
|
81
|
+
host.style.zIndex = "2147483646";
|
|
82
|
+
host.style.position = "fixed";
|
|
83
|
+
host.style.top = "0";
|
|
84
|
+
host.style.left = "0";
|
|
85
|
+
const shadowRoot = host.attachShadow({ mode: "open" });
|
|
86
|
+
const root = document.createElement("div");
|
|
87
|
+
root.setAttribute(ATTRIBUTE_NAME, "true");
|
|
88
|
+
shadowRoot.appendChild(root);
|
|
89
|
+
const doc = document.body ?? document.documentElement;
|
|
90
|
+
doc.appendChild(host);
|
|
91
|
+
return root;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// src/utils/is-element-visible.ts
|
|
95
|
+
var isElementVisible = (element, computedStyle = window.getComputedStyle(element)) => {
|
|
96
|
+
return computedStyle.display !== "none" && computedStyle.visibility !== "hidden" && computedStyle.opacity !== "0";
|
|
97
|
+
};
|
|
98
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<div>`);
|
|
99
|
+
var _tmpl$2 = /* @__PURE__ */ web.template(`<span style="display:inline-block;width:8px;height:8px;border:1.5px solid rgb(210, 57, 192);border-top-color:transparent;border-radius:50%;margin-right:4px;vertical-align:middle">`);
|
|
100
|
+
var _tmpl$3 = /* @__PURE__ */ web.template(`<span style=display:inline-block;margin-right:4px;font-weight:600>\u2713`);
|
|
101
|
+
var _tmpl$4 = /* @__PURE__ */ web.template(`<span style="font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;font-variant-numeric:tabular-nums">`);
|
|
102
|
+
var _tmpl$5 = /* @__PURE__ */ web.template(`<div style="position:fixed;padding:2px 6px;background-color:#fde7f7;color:#b21c8e;border:1px solid #f7c5ec;border-radius:4px;font-size:11px;font-weight:500;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;pointer-events:none;transition:opacity 0.2s ease-in-out;display:flex;align-items:center;max-width:calc(100vw - (16px + env(safe-area-inset-left) + env(safe-area-inset-right)));overflow:hidden;text-overflow:ellipsis;white-space:nowrap"><span>`);
|
|
103
|
+
var _tmpl$6 = /* @__PURE__ */ web.template(`<div style="position:fixed;z-index:2147483647;pointer-events:none;transition:opacity 0.1s ease-in-out"><div style="width:32px;height:2px;background-color:rgba(178, 28, 142, 0.2);border-radius:1px;overflow:hidden;position:relative"><div style="height:100%;background-color:#b21c8e;border-radius:1px;transition:width 0.05s cubic-bezier(0.165, 0.84, 0.44, 1)">`);
|
|
104
|
+
var VIEWPORT_MARGIN_PX = 8;
|
|
105
|
+
var LABEL_OFFSET_PX = 6;
|
|
106
|
+
var INDICATOR_CLAMP_PADDING_PX = 4;
|
|
107
|
+
var INDICATOR_SUCCESS_VISIBLE_MS = 1500;
|
|
108
|
+
var SELECTION_LERP_FACTOR = 0.95;
|
|
109
|
+
var MARQUEE_LERP_FACTOR = 0.9;
|
|
110
|
+
var lerp = (start, end, factor) => {
|
|
111
|
+
return start + (end - start) * factor;
|
|
112
|
+
};
|
|
113
|
+
var Overlay = (props) => {
|
|
114
|
+
const [currentX, setCurrentX] = solidJs.createSignal(props.bounds.x);
|
|
115
|
+
const [currentY, setCurrentY] = solidJs.createSignal(props.bounds.y);
|
|
116
|
+
const [currentWidth, setCurrentWidth] = solidJs.createSignal(props.bounds.width);
|
|
117
|
+
const [currentHeight, setCurrentHeight] = solidJs.createSignal(props.bounds.height);
|
|
118
|
+
const [opacity, setOpacity] = solidJs.createSignal(1);
|
|
119
|
+
let hasBeenShown = false;
|
|
120
|
+
let animationFrameId = null;
|
|
121
|
+
let targetBounds = props.bounds;
|
|
122
|
+
solidJs.createEffect(() => {
|
|
123
|
+
targetBounds = props.bounds;
|
|
124
|
+
const factor = props.lerpFactor ?? SELECTION_LERP_FACTOR;
|
|
125
|
+
if (!hasBeenShown) {
|
|
126
|
+
setCurrentX(targetBounds.x);
|
|
127
|
+
setCurrentY(targetBounds.y);
|
|
128
|
+
setCurrentWidth(targetBounds.width);
|
|
129
|
+
setCurrentHeight(targetBounds.height);
|
|
130
|
+
hasBeenShown = true;
|
|
80
131
|
return;
|
|
81
132
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
133
|
+
const EPSILON = 0.5;
|
|
134
|
+
const animate = () => {
|
|
135
|
+
const newX = lerp(currentX(), targetBounds.x, factor);
|
|
136
|
+
const newY = lerp(currentY(), targetBounds.y, factor);
|
|
137
|
+
const newWidth = lerp(currentWidth(), targetBounds.width, factor);
|
|
138
|
+
const newHeight = lerp(currentHeight(), targetBounds.height, factor);
|
|
139
|
+
setCurrentX(newX);
|
|
140
|
+
setCurrentY(newY);
|
|
141
|
+
setCurrentWidth(newWidth);
|
|
142
|
+
setCurrentHeight(newHeight);
|
|
143
|
+
const hasConverged = Math.abs(newX - targetBounds.x) < EPSILON && Math.abs(newY - targetBounds.y) < EPSILON && Math.abs(newWidth - targetBounds.width) < EPSILON && Math.abs(newHeight - targetBounds.height) < EPSILON;
|
|
144
|
+
if (!hasConverged) {
|
|
145
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
146
|
+
} else {
|
|
147
|
+
animationFrameId = null;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
if (animationFrameId !== null) {
|
|
151
|
+
cancelAnimationFrame(animationFrameId);
|
|
152
|
+
}
|
|
153
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
154
|
+
solidJs.onCleanup(() => {
|
|
155
|
+
if (animationFrameId !== null) {
|
|
156
|
+
cancelAnimationFrame(animationFrameId);
|
|
157
|
+
animationFrameId = null;
|
|
86
158
|
}
|
|
87
|
-
return {
|
|
88
|
-
...state,
|
|
89
|
-
keyPressTimestamps: newTimestamps,
|
|
90
|
-
pressedKeys: /* @__PURE__ */ new Set([event.key, ...state.pressedKeys])
|
|
91
|
-
};
|
|
92
159
|
});
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
|
|
160
|
+
});
|
|
161
|
+
solidJs.createEffect(() => {
|
|
162
|
+
if (props.variant === "grabbed") {
|
|
163
|
+
requestAnimationFrame(() => {
|
|
164
|
+
setOpacity(0);
|
|
165
|
+
});
|
|
97
166
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
167
|
+
});
|
|
168
|
+
const baseStyle = {
|
|
169
|
+
position: "fixed",
|
|
170
|
+
"box-sizing": "border-box",
|
|
171
|
+
"pointer-events": props.variant === "marquee" ? "none" : "auto",
|
|
172
|
+
"z-index": "2147483646"
|
|
173
|
+
};
|
|
174
|
+
const variantStyle = () => {
|
|
175
|
+
if (props.variant === "marquee") {
|
|
101
176
|
return {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
)
|
|
177
|
+
border: "1px dashed rgb(210, 57, 192)",
|
|
178
|
+
"background-color": "rgba(210, 57, 192, 0.1)",
|
|
179
|
+
"will-change": "transform, width, height",
|
|
180
|
+
contain: "layout paint size"
|
|
107
181
|
};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
pressedKeys: /* @__PURE__ */ new Set()
|
|
115
|
-
}));
|
|
116
|
-
};
|
|
117
|
-
const handleContextmenu = () => {
|
|
118
|
-
libStore.setState((state) => ({
|
|
119
|
-
...state,
|
|
120
|
-
keyPressTimestamps: /* @__PURE__ */ new Map(),
|
|
121
|
-
pressedKeys: /* @__PURE__ */ new Set()
|
|
122
|
-
}));
|
|
123
|
-
};
|
|
124
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
125
|
-
document.addEventListener("keyup", handleKeyUp);
|
|
126
|
-
window.addEventListener("blur", handleBlur);
|
|
127
|
-
window.addEventListener("contextmenu", handleContextmenu);
|
|
128
|
-
return () => {
|
|
129
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
130
|
-
document.removeEventListener("keyup", handleKeyUp);
|
|
131
|
-
window.removeEventListener("blur", handleBlur);
|
|
132
|
-
window.removeEventListener("contextmenu", handleContextmenu);
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
border: "1px solid rgb(210, 57, 192)",
|
|
185
|
+
"background-color": "rgba(210, 57, 192, 0.2)",
|
|
186
|
+
transition: props.variant === "grabbed" ? "opacity 0.3s ease-out" : void 0
|
|
187
|
+
};
|
|
133
188
|
};
|
|
189
|
+
return web.createComponent(solidJs.Show, {
|
|
190
|
+
get when() {
|
|
191
|
+
return props.visible !== false;
|
|
192
|
+
},
|
|
193
|
+
get children() {
|
|
194
|
+
var _el$ = _tmpl$();
|
|
195
|
+
web.effect((_$p) => web.style(_el$, {
|
|
196
|
+
...baseStyle,
|
|
197
|
+
...variantStyle(),
|
|
198
|
+
top: `${currentY()}px`,
|
|
199
|
+
left: `${currentX()}px`,
|
|
200
|
+
width: `${currentWidth()}px`,
|
|
201
|
+
height: `${currentHeight()}px`,
|
|
202
|
+
"border-radius": props.bounds.borderRadius,
|
|
203
|
+
transform: props.bounds.transform,
|
|
204
|
+
opacity: opacity()
|
|
205
|
+
}, _$p));
|
|
206
|
+
return _el$;
|
|
207
|
+
}
|
|
208
|
+
});
|
|
134
209
|
};
|
|
135
|
-
var
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
210
|
+
var Spinner = (props) => {
|
|
211
|
+
let ref;
|
|
212
|
+
solidJs.createEffect(() => {
|
|
213
|
+
if (ref) {
|
|
214
|
+
ref.animate([{
|
|
215
|
+
transform: "rotate(0deg)"
|
|
216
|
+
}, {
|
|
217
|
+
transform: "rotate(360deg)"
|
|
218
|
+
}], {
|
|
219
|
+
duration: 600,
|
|
220
|
+
easing: "linear",
|
|
221
|
+
iterations: Infinity
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
return (() => {
|
|
226
|
+
var _el$2 = _tmpl$2();
|
|
227
|
+
var _ref$ = ref;
|
|
228
|
+
typeof _ref$ === "function" ? web.use(_ref$, _el$2) : ref = _el$2;
|
|
229
|
+
web.effect((_$p) => web.style(_el$2, {
|
|
230
|
+
...props.style
|
|
231
|
+
}, _$p));
|
|
232
|
+
return _el$2;
|
|
233
|
+
})();
|
|
141
234
|
};
|
|
142
|
-
var
|
|
143
|
-
|
|
144
|
-
let
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
235
|
+
var Label = (props) => {
|
|
236
|
+
const [opacity, setOpacity] = solidJs.createSignal(0);
|
|
237
|
+
let ref;
|
|
238
|
+
solidJs.createEffect(() => {
|
|
239
|
+
if (props.visible !== false) {
|
|
240
|
+
requestAnimationFrame(() => {
|
|
241
|
+
setOpacity(1);
|
|
242
|
+
});
|
|
243
|
+
} else {
|
|
244
|
+
setOpacity(0);
|
|
150
245
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
246
|
+
});
|
|
247
|
+
solidJs.createEffect(() => {
|
|
248
|
+
if (props.variant === "success") {
|
|
249
|
+
const fadeOutTimer = setTimeout(() => {
|
|
250
|
+
setOpacity(0);
|
|
251
|
+
}, INDICATOR_SUCCESS_VISIBLE_MS);
|
|
252
|
+
solidJs.onCleanup(() => clearTimeout(fadeOutTimer));
|
|
154
253
|
}
|
|
155
|
-
};
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
254
|
+
});
|
|
255
|
+
const indicatorRect = () => ref?.getBoundingClientRect();
|
|
256
|
+
const computedPosition = () => {
|
|
257
|
+
const rect = indicatorRect();
|
|
258
|
+
if (!rect) return {
|
|
259
|
+
left: props.x,
|
|
260
|
+
top: props.y
|
|
261
|
+
};
|
|
262
|
+
const viewportWidthPx = window.innerWidth;
|
|
263
|
+
const viewportHeightPx = window.innerHeight;
|
|
264
|
+
let indicatorLeftPx = Math.round(props.x);
|
|
265
|
+
let indicatorTopPx = Math.round(props.y) - rect.height - LABEL_OFFSET_PX;
|
|
266
|
+
const minLeft = VIEWPORT_MARGIN_PX;
|
|
267
|
+
const minTop = VIEWPORT_MARGIN_PX;
|
|
268
|
+
const maxLeft = viewportWidthPx - rect.width - VIEWPORT_MARGIN_PX;
|
|
269
|
+
const maxTop = viewportHeightPx - rect.height - VIEWPORT_MARGIN_PX;
|
|
270
|
+
const willClampLeft = indicatorLeftPx < minLeft;
|
|
271
|
+
const willClampTop = indicatorTopPx < minTop;
|
|
272
|
+
const isClamped = willClampLeft || willClampTop;
|
|
273
|
+
indicatorLeftPx = Math.max(minLeft, Math.min(indicatorLeftPx, maxLeft));
|
|
274
|
+
indicatorTopPx = Math.max(minTop, Math.min(indicatorTopPx, maxTop));
|
|
275
|
+
if (isClamped) {
|
|
276
|
+
indicatorLeftPx += INDICATOR_CLAMP_PADDING_PX;
|
|
277
|
+
indicatorTopPx += INDICATOR_CLAMP_PADDING_PX;
|
|
159
278
|
}
|
|
160
|
-
return
|
|
279
|
+
return {
|
|
280
|
+
left: indicatorLeftPx,
|
|
281
|
+
top: indicatorTopPx
|
|
282
|
+
};
|
|
161
283
|
};
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return
|
|
165
|
-
|
|
166
|
-
|
|
284
|
+
return web.createComponent(solidJs.Show, {
|
|
285
|
+
get when() {
|
|
286
|
+
return props.visible !== false;
|
|
287
|
+
},
|
|
288
|
+
get children() {
|
|
289
|
+
var _el$3 = _tmpl$5(), _el$5 = _el$3.firstChild;
|
|
290
|
+
var _ref$2 = ref;
|
|
291
|
+
typeof _ref$2 === "function" ? web.use(_ref$2, _el$3) : ref = _el$3;
|
|
292
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
293
|
+
get when() {
|
|
294
|
+
return props.variant === "processing";
|
|
295
|
+
},
|
|
296
|
+
get children() {
|
|
297
|
+
return web.createComponent(Spinner, {});
|
|
298
|
+
}
|
|
299
|
+
}), _el$5);
|
|
300
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
301
|
+
get when() {
|
|
302
|
+
return props.variant === "success";
|
|
303
|
+
},
|
|
304
|
+
get children() {
|
|
305
|
+
return _tmpl$3();
|
|
306
|
+
}
|
|
307
|
+
}), _el$5);
|
|
308
|
+
web.insert(_el$5, web.createComponent(solidJs.Show, {
|
|
309
|
+
get when() {
|
|
310
|
+
return props.variant === "success";
|
|
311
|
+
},
|
|
312
|
+
children: "Grabbed "
|
|
313
|
+
}), null);
|
|
314
|
+
web.insert(_el$5, web.createComponent(solidJs.Show, {
|
|
315
|
+
get when() {
|
|
316
|
+
return props.variant === "processing";
|
|
317
|
+
},
|
|
318
|
+
children: "Grabbing\u2026"
|
|
319
|
+
}), null);
|
|
320
|
+
web.insert(_el$5, web.createComponent(solidJs.Show, {
|
|
321
|
+
get when() {
|
|
322
|
+
return props.variant === "hover";
|
|
323
|
+
},
|
|
324
|
+
get children() {
|
|
325
|
+
var _el$6 = _tmpl$4();
|
|
326
|
+
web.insert(_el$6, () => props.text);
|
|
327
|
+
return _el$6;
|
|
328
|
+
}
|
|
329
|
+
}), null);
|
|
330
|
+
web.insert(_el$5, web.createComponent(solidJs.Show, {
|
|
331
|
+
get when() {
|
|
332
|
+
return props.variant !== "hover";
|
|
333
|
+
},
|
|
334
|
+
get children() {
|
|
335
|
+
var _el$7 = _tmpl$4();
|
|
336
|
+
web.insert(_el$7, () => props.text);
|
|
337
|
+
return _el$7;
|
|
338
|
+
}
|
|
339
|
+
}), null);
|
|
340
|
+
web.effect((_p$) => {
|
|
341
|
+
var _v$ = `${computedPosition().top}px`, _v$2 = `${computedPosition().left}px`, _v$3 = props.zIndex?.toString() ?? "2147483647", _v$4 = opacity();
|
|
342
|
+
_v$ !== _p$.e && web.setStyleProperty(_el$3, "top", _p$.e = _v$);
|
|
343
|
+
_v$2 !== _p$.t && web.setStyleProperty(_el$3, "left", _p$.t = _v$2);
|
|
344
|
+
_v$3 !== _p$.a && web.setStyleProperty(_el$3, "z-index", _p$.a = _v$3);
|
|
345
|
+
_v$4 !== _p$.o && web.setStyleProperty(_el$3, "opacity", _p$.o = _v$4);
|
|
346
|
+
return _p$;
|
|
347
|
+
}, {
|
|
348
|
+
e: void 0,
|
|
349
|
+
t: void 0,
|
|
350
|
+
a: void 0,
|
|
351
|
+
o: void 0
|
|
352
|
+
});
|
|
353
|
+
return _el$3;
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
};
|
|
357
|
+
var ProgressIndicator = (props) => {
|
|
358
|
+
const [opacity, setOpacity] = solidJs.createSignal(0);
|
|
359
|
+
let ref;
|
|
360
|
+
solidJs.createEffect(() => {
|
|
361
|
+
if (props.visible !== false) {
|
|
362
|
+
requestAnimationFrame(() => {
|
|
363
|
+
setOpacity(1);
|
|
364
|
+
});
|
|
365
|
+
} else {
|
|
366
|
+
setOpacity(0);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
const computedPosition = () => {
|
|
370
|
+
const rect = ref?.getBoundingClientRect();
|
|
371
|
+
if (!rect) return {
|
|
372
|
+
left: props.mouseX,
|
|
373
|
+
top: props.mouseY
|
|
374
|
+
};
|
|
375
|
+
const viewportWidth = window.innerWidth;
|
|
376
|
+
const viewportHeight = window.innerHeight;
|
|
377
|
+
const CURSOR_OFFSET = 14;
|
|
378
|
+
const VIEWPORT_MARGIN = 8;
|
|
379
|
+
let indicatorLeft = props.mouseX - rect.width / 2;
|
|
380
|
+
let indicatorTop = props.mouseY + CURSOR_OFFSET;
|
|
381
|
+
if (indicatorTop + rect.height + VIEWPORT_MARGIN > viewportHeight) {
|
|
382
|
+
indicatorTop = props.mouseY - rect.height - CURSOR_OFFSET;
|
|
167
383
|
}
|
|
168
|
-
|
|
384
|
+
indicatorTop = Math.max(VIEWPORT_MARGIN, Math.min(indicatorTop, viewportHeight - rect.height - VIEWPORT_MARGIN));
|
|
385
|
+
indicatorLeft = Math.max(VIEWPORT_MARGIN, Math.min(indicatorLeft, viewportWidth - rect.width - VIEWPORT_MARGIN));
|
|
386
|
+
return {
|
|
387
|
+
left: indicatorLeft,
|
|
388
|
+
top: indicatorTop
|
|
389
|
+
};
|
|
169
390
|
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
391
|
+
return web.createComponent(solidJs.Show, {
|
|
392
|
+
get when() {
|
|
393
|
+
return props.visible !== false;
|
|
394
|
+
},
|
|
395
|
+
get children() {
|
|
396
|
+
var _el$8 = _tmpl$6(), _el$9 = _el$8.firstChild, _el$0 = _el$9.firstChild;
|
|
397
|
+
var _ref$3 = ref;
|
|
398
|
+
typeof _ref$3 === "function" ? web.use(_ref$3, _el$8) : ref = _el$8;
|
|
399
|
+
web.effect((_p$) => {
|
|
400
|
+
var _v$5 = `${computedPosition().top}px`, _v$6 = `${computedPosition().left}px`, _v$7 = opacity(), _v$8 = `${Math.min(100, Math.max(0, props.progress * 100))}%`;
|
|
401
|
+
_v$5 !== _p$.e && web.setStyleProperty(_el$8, "top", _p$.e = _v$5);
|
|
402
|
+
_v$6 !== _p$.t && web.setStyleProperty(_el$8, "left", _p$.t = _v$6);
|
|
403
|
+
_v$7 !== _p$.a && web.setStyleProperty(_el$8, "opacity", _p$.a = _v$7);
|
|
404
|
+
_v$8 !== _p$.o && web.setStyleProperty(_el$0, "width", _p$.o = _v$8);
|
|
405
|
+
return _p$;
|
|
406
|
+
}, {
|
|
407
|
+
e: void 0,
|
|
408
|
+
t: void 0,
|
|
409
|
+
a: void 0,
|
|
410
|
+
o: void 0
|
|
411
|
+
});
|
|
412
|
+
return _el$8;
|
|
179
413
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
return;
|
|
414
|
+
});
|
|
415
|
+
};
|
|
416
|
+
var ReactGrabOverlay = (props) => {
|
|
417
|
+
return [web.createComponent(solidJs.Show, {
|
|
418
|
+
get when() {
|
|
419
|
+
return web.memo(() => !!props.selectionVisible)() && props.selectionBounds;
|
|
420
|
+
},
|
|
421
|
+
get children() {
|
|
422
|
+
return web.createComponent(Overlay, {
|
|
423
|
+
variant: "selection",
|
|
424
|
+
get bounds() {
|
|
425
|
+
return props.selectionBounds;
|
|
426
|
+
},
|
|
427
|
+
get visible() {
|
|
428
|
+
return props.selectionVisible;
|
|
429
|
+
},
|
|
430
|
+
lerpFactor: SELECTION_LERP_FACTOR
|
|
431
|
+
});
|
|
186
432
|
}
|
|
187
|
-
|
|
188
|
-
|
|
433
|
+
}), web.createComponent(solidJs.Show, {
|
|
434
|
+
get when() {
|
|
435
|
+
return web.memo(() => !!props.marqueeVisible)() && props.marqueeBounds;
|
|
436
|
+
},
|
|
437
|
+
get children() {
|
|
438
|
+
return web.createComponent(Overlay, {
|
|
439
|
+
variant: "marquee",
|
|
440
|
+
get bounds() {
|
|
441
|
+
return props.marqueeBounds;
|
|
442
|
+
},
|
|
443
|
+
get visible() {
|
|
444
|
+
return props.marqueeVisible;
|
|
445
|
+
},
|
|
446
|
+
lerpFactor: MARQUEE_LERP_FACTOR
|
|
447
|
+
});
|
|
189
448
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}, remaining);
|
|
194
|
-
};
|
|
195
|
-
unsubscribe = libStore.subscribe(
|
|
196
|
-
() => {
|
|
197
|
-
scheduleCallback();
|
|
449
|
+
}), web.createComponent(solidJs.For, {
|
|
450
|
+
get each() {
|
|
451
|
+
return props.grabbedOverlays ?? [];
|
|
198
452
|
},
|
|
199
|
-
(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
453
|
+
children: (overlay) => web.createComponent(Overlay, {
|
|
454
|
+
variant: "grabbed",
|
|
455
|
+
get bounds() {
|
|
456
|
+
return overlay.bounds;
|
|
457
|
+
},
|
|
458
|
+
visible: true
|
|
459
|
+
})
|
|
460
|
+
}), web.createComponent(solidJs.For, {
|
|
461
|
+
get each() {
|
|
462
|
+
return props.successLabels ?? [];
|
|
463
|
+
},
|
|
464
|
+
children: (label) => web.createComponent(Label, {
|
|
465
|
+
variant: "success",
|
|
466
|
+
get text() {
|
|
467
|
+
return label.text;
|
|
468
|
+
},
|
|
469
|
+
get x() {
|
|
470
|
+
return label.x;
|
|
471
|
+
},
|
|
472
|
+
get y() {
|
|
473
|
+
return label.y;
|
|
474
|
+
},
|
|
475
|
+
visible: true,
|
|
476
|
+
zIndex: 2147483648
|
|
477
|
+
})
|
|
478
|
+
}), web.createComponent(solidJs.Show, {
|
|
479
|
+
get when() {
|
|
480
|
+
return web.memo(() => !!(props.labelVisible && props.labelVariant && props.labelText && props.labelX !== void 0))() && props.labelY !== void 0;
|
|
481
|
+
},
|
|
482
|
+
get children() {
|
|
483
|
+
return web.createComponent(Label, {
|
|
484
|
+
get variant() {
|
|
485
|
+
return props.labelVariant;
|
|
486
|
+
},
|
|
487
|
+
get text() {
|
|
488
|
+
return props.labelText;
|
|
489
|
+
},
|
|
490
|
+
get x() {
|
|
491
|
+
return props.labelX;
|
|
492
|
+
},
|
|
493
|
+
get y() {
|
|
494
|
+
return props.labelY;
|
|
495
|
+
},
|
|
496
|
+
get visible() {
|
|
497
|
+
return props.labelVisible;
|
|
498
|
+
},
|
|
499
|
+
get zIndex() {
|
|
500
|
+
return props.labelZIndex;
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}), web.createComponent(solidJs.Show, {
|
|
505
|
+
get when() {
|
|
506
|
+
return web.memo(() => !!(props.progressVisible && props.progress !== void 0 && props.mouseX !== void 0))() && props.mouseY !== void 0;
|
|
507
|
+
},
|
|
508
|
+
get children() {
|
|
509
|
+
return web.createComponent(ProgressIndicator, {
|
|
510
|
+
get progress() {
|
|
511
|
+
return props.progress;
|
|
512
|
+
},
|
|
513
|
+
get mouseX() {
|
|
514
|
+
return props.mouseX;
|
|
515
|
+
},
|
|
516
|
+
get mouseY() {
|
|
517
|
+
return props.mouseY;
|
|
518
|
+
},
|
|
519
|
+
get visible() {
|
|
520
|
+
return props.progressVisible;
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
})];
|
|
203
525
|
};
|
|
204
|
-
var fiberRoots = bippy._fiberRoots;
|
|
205
526
|
bippy.instrument({
|
|
206
527
|
onCommitFiberRoot(_, fiberRoot) {
|
|
207
|
-
|
|
528
|
+
bippy._fiberRoots.add(fiberRoot);
|
|
208
529
|
}
|
|
209
530
|
});
|
|
210
|
-
var
|
|
211
|
-
if (!fileName) return fileName;
|
|
212
|
-
const parts = fileName.split("/");
|
|
213
|
-
for (let start = 0; start < parts.length / 2; start++) {
|
|
214
|
-
for (let len = 1; len <= parts.length - start; len++) {
|
|
215
|
-
const firstSeq = parts.slice(start, start + len);
|
|
216
|
-
const secondStart = start + len;
|
|
217
|
-
const secondSeq = parts.slice(secondStart, secondStart + len);
|
|
218
|
-
if (firstSeq.length > 2 && firstSeq.length === secondSeq.length && firstSeq.every((part, i) => part === secondSeq[i])) {
|
|
219
|
-
return parts.slice(secondStart).join("/");
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return fileName;
|
|
224
|
-
};
|
|
225
|
-
var getStack = async (element) => {
|
|
531
|
+
var getSourceTrace = async (element) => {
|
|
226
532
|
const fiber = bippy.getFiberFromHostInstance(element);
|
|
227
533
|
if (!fiber) return null;
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
fileName: dedupeFileName(item.source?.fileName)
|
|
233
|
-
}));
|
|
234
|
-
if (stack.length > 0 && fiber) {
|
|
235
|
-
const fiberSource = await source.getFiberSource(fiber);
|
|
236
|
-
if (fiberSource) {
|
|
237
|
-
const fiberType = fiber.type;
|
|
238
|
-
const displayName = fiberType?.displayName ?? fiberType?.name ?? stack[0].componentName;
|
|
239
|
-
stack[0].displayName = displayName;
|
|
240
|
-
const dedupedFileName = dedupeFileName(fiberSource.fileName);
|
|
241
|
-
stack[0].source = `${dedupedFileName}:${fiberSource.lineNumber}:${fiberSource.columnNumber}`;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return stack;
|
|
245
|
-
};
|
|
246
|
-
var filterStack = (stack) => {
|
|
247
|
-
return stack.filter(
|
|
248
|
-
(item) => item.fileName && !item.fileName.includes("node_modules") && item.componentName.length > 1 && !item.fileName.startsWith("_")
|
|
534
|
+
const ownerStack = source.getOwnerStack(fiber);
|
|
535
|
+
const sources = await source.getSourcesFromStack(
|
|
536
|
+
ownerStack,
|
|
537
|
+
Number.MAX_SAFE_INTEGER
|
|
249
538
|
);
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
return stack.map((item, index) => {
|
|
253
|
-
const fileName = item.fileName;
|
|
254
|
-
const componentName = item.displayName || item.componentName;
|
|
255
|
-
let result = `${componentName}${fileName ? ` (${fileName})` : ""}`;
|
|
256
|
-
if (index === 0 && item.source) {
|
|
257
|
-
result += `
|
|
258
|
-
${item.source}`;
|
|
259
|
-
}
|
|
260
|
-
return result;
|
|
261
|
-
}).join("\n");
|
|
539
|
+
if (!sources) return null;
|
|
540
|
+
return sources;
|
|
262
541
|
};
|
|
263
542
|
var getHTMLSnippet = (element) => {
|
|
264
543
|
const semanticTags = /* @__PURE__ */ new Set([
|
|
@@ -458,953 +737,531 @@ var getHTMLSnippet = (element) => {
|
|
|
458
737
|
return lines.join("\n");
|
|
459
738
|
};
|
|
460
739
|
|
|
461
|
-
// src/
|
|
462
|
-
var
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
var createSelectionElement = ({
|
|
472
|
-
borderRadius,
|
|
473
|
-
height,
|
|
474
|
-
transform,
|
|
475
|
-
width,
|
|
476
|
-
x,
|
|
477
|
-
y
|
|
478
|
-
}) => {
|
|
479
|
-
const overlay = document.createElement("div");
|
|
480
|
-
overlay.style.position = "fixed";
|
|
481
|
-
overlay.style.top = `${y}px`;
|
|
482
|
-
overlay.style.left = `${x}px`;
|
|
483
|
-
overlay.style.width = `${width}px`;
|
|
484
|
-
overlay.style.height = `${height}px`;
|
|
485
|
-
overlay.style.borderRadius = borderRadius;
|
|
486
|
-
overlay.style.transform = transform;
|
|
487
|
-
overlay.style.pointerEvents = "none";
|
|
488
|
-
overlay.style.border = "1px solid rgb(210, 57, 192)";
|
|
489
|
-
overlay.style.backgroundColor = "rgba(210, 57, 192, 0.2)";
|
|
490
|
-
overlay.style.zIndex = "2147483646";
|
|
491
|
-
overlay.style.boxSizing = "border-box";
|
|
492
|
-
overlay.style.display = "none";
|
|
493
|
-
return overlay;
|
|
494
|
-
};
|
|
495
|
-
var updateSelectionElement = (element, { borderRadius, height, transform, width, x, y }) => {
|
|
496
|
-
const currentTop = parseFloat(element.style.top) || 0;
|
|
497
|
-
const currentLeft = parseFloat(element.style.left) || 0;
|
|
498
|
-
const currentWidth = parseFloat(element.style.width) || 0;
|
|
499
|
-
const currentHeight = parseFloat(element.style.height) || 0;
|
|
500
|
-
const topValue = `${lerp(currentTop, y, SELECTION_LERP_FACTOR)}px`;
|
|
501
|
-
const leftValue = `${lerp(currentLeft, x, SELECTION_LERP_FACTOR)}px`;
|
|
502
|
-
const widthValue = `${lerp(currentWidth, width, SELECTION_LERP_FACTOR)}px`;
|
|
503
|
-
const heightValue = `${lerp(currentHeight, height, SELECTION_LERP_FACTOR)}px`;
|
|
504
|
-
if (element.style.top !== topValue) {
|
|
505
|
-
element.style.top = topValue;
|
|
506
|
-
}
|
|
507
|
-
if (element.style.left !== leftValue) {
|
|
508
|
-
element.style.left = leftValue;
|
|
509
|
-
}
|
|
510
|
-
if (element.style.width !== widthValue) {
|
|
511
|
-
element.style.width = widthValue;
|
|
512
|
-
}
|
|
513
|
-
if (element.style.height !== heightValue) {
|
|
514
|
-
element.style.height = heightValue;
|
|
515
|
-
}
|
|
516
|
-
if (element.style.borderRadius !== borderRadius) {
|
|
517
|
-
element.style.borderRadius = borderRadius;
|
|
518
|
-
}
|
|
519
|
-
if (element.style.transform !== transform) {
|
|
520
|
-
element.style.transform = transform;
|
|
521
|
-
}
|
|
522
|
-
};
|
|
523
|
-
var createSelectionOverlay = (root) => {
|
|
524
|
-
const element = createSelectionElement({
|
|
525
|
-
borderRadius: "0px",
|
|
526
|
-
height: 0,
|
|
527
|
-
transform: "none",
|
|
528
|
-
width: 0,
|
|
529
|
-
x: -1e3,
|
|
530
|
-
y: -1e3
|
|
531
|
-
});
|
|
532
|
-
root.appendChild(element);
|
|
533
|
-
let visible = false;
|
|
534
|
-
element.addEventListener("mousedown", (event) => {
|
|
535
|
-
event.preventDefault();
|
|
536
|
-
event.stopPropagation();
|
|
537
|
-
event.stopImmediatePropagation();
|
|
538
|
-
const { overlayMode } = libStore.getState();
|
|
539
|
-
if (overlayMode === "visible") {
|
|
540
|
-
libStore.setState((state) => ({
|
|
541
|
-
...state,
|
|
542
|
-
overlayMode: "copying"
|
|
543
|
-
}));
|
|
544
|
-
}
|
|
545
|
-
}, true);
|
|
546
|
-
return {
|
|
547
|
-
element,
|
|
548
|
-
hide: () => {
|
|
549
|
-
visible = false;
|
|
550
|
-
element.style.display = "none";
|
|
551
|
-
},
|
|
552
|
-
isVisible: () => visible,
|
|
553
|
-
show: () => {
|
|
554
|
-
visible = true;
|
|
555
|
-
element.style.display = "block";
|
|
556
|
-
},
|
|
557
|
-
update: (selection) => {
|
|
558
|
-
updateSelectionElement(element, selection);
|
|
559
|
-
}
|
|
560
|
-
};
|
|
561
|
-
};
|
|
562
|
-
var createGrabbedOverlay = (root, selection) => {
|
|
563
|
-
const element = document.createElement("div");
|
|
564
|
-
element.style.position = "fixed";
|
|
565
|
-
element.style.top = `${selection.y}px`;
|
|
566
|
-
element.style.left = `${selection.x}px`;
|
|
567
|
-
element.style.width = `${selection.width}px`;
|
|
568
|
-
element.style.height = `${selection.height}px`;
|
|
569
|
-
element.style.borderRadius = selection.borderRadius;
|
|
570
|
-
element.style.transform = selection.transform;
|
|
571
|
-
element.style.pointerEvents = "none";
|
|
572
|
-
element.style.border = "1px solid rgb(210, 57, 192)";
|
|
573
|
-
element.style.backgroundColor = "rgba(210, 57, 192, 0.2)";
|
|
574
|
-
element.style.zIndex = "2147483646";
|
|
575
|
-
element.style.boxSizing = "border-box";
|
|
576
|
-
element.style.transition = "opacity 0.3s ease-out";
|
|
577
|
-
element.style.opacity = "1";
|
|
578
|
-
root.appendChild(element);
|
|
579
|
-
requestAnimationFrame(() => {
|
|
580
|
-
element.style.opacity = "0";
|
|
581
|
-
});
|
|
582
|
-
setTimeout(() => {
|
|
583
|
-
element.remove();
|
|
584
|
-
}, 300);
|
|
585
|
-
};
|
|
586
|
-
var createSpinner = () => {
|
|
587
|
-
const spinner = document.createElement("span");
|
|
588
|
-
spinner.style.display = "inline-block";
|
|
589
|
-
spinner.style.width = "8px";
|
|
590
|
-
spinner.style.height = "8px";
|
|
591
|
-
spinner.style.border = "1.5px solid rgb(210, 57, 192)";
|
|
592
|
-
spinner.style.borderTopColor = "transparent";
|
|
593
|
-
spinner.style.borderRadius = "50%";
|
|
594
|
-
spinner.style.marginRight = "4px";
|
|
595
|
-
spinner.style.verticalAlign = "middle";
|
|
596
|
-
spinner.animate(
|
|
597
|
-
[{ transform: "rotate(0deg)" }, { transform: "rotate(360deg)" }],
|
|
598
|
-
{
|
|
599
|
-
duration: 600,
|
|
600
|
-
easing: "linear",
|
|
601
|
-
iterations: Infinity
|
|
602
|
-
}
|
|
603
|
-
);
|
|
604
|
-
return spinner;
|
|
605
|
-
};
|
|
606
|
-
var activeIndicator = null;
|
|
607
|
-
var createIndicator = () => {
|
|
608
|
-
const indicator = document.createElement("div");
|
|
609
|
-
indicator.style.position = "fixed";
|
|
610
|
-
indicator.style.top = "calc(8px + env(safe-area-inset-top))";
|
|
611
|
-
indicator.style.padding = "2px 6px";
|
|
612
|
-
indicator.style.backgroundColor = "#fde7f7";
|
|
613
|
-
indicator.style.color = "#b21c8e";
|
|
614
|
-
indicator.style.border = "1px solid #f7c5ec";
|
|
615
|
-
indicator.style.borderRadius = "4px";
|
|
616
|
-
indicator.style.fontSize = "11px";
|
|
617
|
-
indicator.style.fontWeight = "500";
|
|
618
|
-
indicator.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif";
|
|
619
|
-
indicator.style.zIndex = "2147483647";
|
|
620
|
-
indicator.style.pointerEvents = "none";
|
|
621
|
-
indicator.style.opacity = "0";
|
|
622
|
-
indicator.style.transition = "opacity 0.2s ease-in-out";
|
|
623
|
-
indicator.style.display = "flex";
|
|
624
|
-
indicator.style.alignItems = "center";
|
|
625
|
-
indicator.style.maxWidth = "calc(100vw - (16px + env(safe-area-inset-left) + env(safe-area-inset-right)))";
|
|
626
|
-
indicator.style.overflow = "hidden";
|
|
627
|
-
indicator.style.textOverflow = "ellipsis";
|
|
628
|
-
indicator.style.whiteSpace = "nowrap";
|
|
629
|
-
return indicator;
|
|
630
|
-
};
|
|
631
|
-
var showLabel = (root, selectionLeftPx, selectionTopPx, tagName) => {
|
|
632
|
-
let indicator = activeIndicator;
|
|
633
|
-
let isNewIndicator = false;
|
|
634
|
-
if (!indicator) {
|
|
635
|
-
indicator = createIndicator();
|
|
636
|
-
root.appendChild(indicator);
|
|
637
|
-
activeIndicator = indicator;
|
|
638
|
-
isNewIndicator = true;
|
|
639
|
-
isProcessing = false;
|
|
640
|
-
}
|
|
641
|
-
if (!isProcessing) {
|
|
642
|
-
const labelText = indicator.querySelector("span");
|
|
643
|
-
if (labelText) {
|
|
644
|
-
const tagNameMonospace = document.createElement("span");
|
|
645
|
-
tagNameMonospace.textContent = tagName ? `<${tagName}>` : "<element>";
|
|
646
|
-
tagNameMonospace.style.fontFamily = "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace";
|
|
647
|
-
tagNameMonospace.style.fontVariantNumeric = "tabular-nums";
|
|
648
|
-
labelText.replaceChildren(tagNameMonospace);
|
|
649
|
-
} else {
|
|
650
|
-
const newLabelText = document.createElement("span");
|
|
651
|
-
const tagNameMonospace = document.createElement("span");
|
|
652
|
-
tagNameMonospace.textContent = tagName ? `<${tagName}>` : "<element>";
|
|
653
|
-
tagNameMonospace.style.fontFamily = "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace";
|
|
654
|
-
tagNameMonospace.style.fontVariantNumeric = "tabular-nums";
|
|
655
|
-
newLabelText.appendChild(tagNameMonospace);
|
|
656
|
-
indicator.appendChild(newLabelText);
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
const indicatorRect = indicator.getBoundingClientRect();
|
|
660
|
-
const viewportWidthPx = window.innerWidth;
|
|
661
|
-
const viewportHeightPx = window.innerHeight;
|
|
662
|
-
let indicatorLeftPx = Math.round(selectionLeftPx);
|
|
663
|
-
let indicatorTopPx = Math.round(selectionTopPx) - indicatorRect.height - LABEL_OFFSET_PX;
|
|
664
|
-
const CLAMPED_PADDING = INDICATOR_CLAMP_PADDING_PX;
|
|
665
|
-
const minLeft = VIEWPORT_MARGIN_PX;
|
|
666
|
-
const minTop = VIEWPORT_MARGIN_PX;
|
|
667
|
-
const maxLeft = viewportWidthPx - indicatorRect.width - VIEWPORT_MARGIN_PX;
|
|
668
|
-
const maxTop = viewportHeightPx - indicatorRect.height - VIEWPORT_MARGIN_PX;
|
|
669
|
-
const willClampLeft = indicatorLeftPx < minLeft;
|
|
670
|
-
const willClampTop = indicatorTopPx < minTop;
|
|
671
|
-
const isClamped = willClampLeft || willClampTop;
|
|
672
|
-
indicatorLeftPx = Math.max(minLeft, Math.min(indicatorLeftPx, maxLeft));
|
|
673
|
-
indicatorTopPx = Math.max(minTop, Math.min(indicatorTopPx, maxTop));
|
|
674
|
-
if (isClamped) {
|
|
675
|
-
indicatorLeftPx += CLAMPED_PADDING;
|
|
676
|
-
indicatorTopPx += CLAMPED_PADDING;
|
|
677
|
-
}
|
|
678
|
-
indicator.style.left = `${indicatorLeftPx}px`;
|
|
679
|
-
indicator.style.top = `${indicatorTopPx}px`;
|
|
680
|
-
indicator.style.right = "auto";
|
|
681
|
-
if (isNewIndicator) {
|
|
682
|
-
requestAnimationFrame(() => {
|
|
683
|
-
indicator.style.opacity = "1";
|
|
684
|
-
});
|
|
685
|
-
} else if (indicator.style.opacity !== "1") {
|
|
686
|
-
indicator.style.opacity = "1";
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
var isProcessing = false;
|
|
690
|
-
var activeGrabbedIndicators = /* @__PURE__ */ new Set();
|
|
691
|
-
var updateLabelToProcessing = (root, selectionLeftPx, selectionTopPx) => {
|
|
692
|
-
const indicator = createIndicator();
|
|
693
|
-
indicator.style.zIndex = "2147483648";
|
|
694
|
-
root.appendChild(indicator);
|
|
695
|
-
activeGrabbedIndicators.add(indicator);
|
|
696
|
-
const positionIndicator = () => {
|
|
697
|
-
if (selectionLeftPx === void 0 || selectionTopPx === void 0) return;
|
|
698
|
-
const indicatorRect = indicator.getBoundingClientRect();
|
|
699
|
-
const viewportWidthPx = window.innerWidth;
|
|
700
|
-
const viewportHeightPx = window.innerHeight;
|
|
701
|
-
let indicatorLeftPx = Math.round(selectionLeftPx);
|
|
702
|
-
let indicatorTopPx = Math.round(selectionTopPx) - indicatorRect.height - LABEL_OFFSET_PX;
|
|
703
|
-
const CLAMPED_PADDING = INDICATOR_CLAMP_PADDING_PX;
|
|
704
|
-
const minLeft = VIEWPORT_MARGIN_PX;
|
|
705
|
-
const minTop = VIEWPORT_MARGIN_PX;
|
|
706
|
-
const maxLeft = viewportWidthPx - indicatorRect.width - VIEWPORT_MARGIN_PX;
|
|
707
|
-
const maxTop = viewportHeightPx - indicatorRect.height - VIEWPORT_MARGIN_PX;
|
|
708
|
-
const willClampLeft = indicatorLeftPx < minLeft;
|
|
709
|
-
const willClampTop = indicatorTopPx < minTop;
|
|
710
|
-
const isClamped = willClampLeft || willClampTop;
|
|
711
|
-
indicatorLeftPx = Math.max(minLeft, Math.min(indicatorLeftPx, maxLeft));
|
|
712
|
-
indicatorTopPx = Math.max(minTop, Math.min(indicatorTopPx, maxTop));
|
|
713
|
-
if (isClamped) {
|
|
714
|
-
indicatorLeftPx += CLAMPED_PADDING;
|
|
715
|
-
indicatorTopPx += CLAMPED_PADDING;
|
|
716
|
-
}
|
|
717
|
-
indicator.style.left = `${indicatorLeftPx}px`;
|
|
718
|
-
indicator.style.top = `${indicatorTopPx}px`;
|
|
719
|
-
indicator.style.right = "auto";
|
|
720
|
-
};
|
|
721
|
-
const loadingSpinner = createSpinner();
|
|
722
|
-
const labelText = document.createElement("span");
|
|
723
|
-
labelText.textContent = "Grabbing\u2026";
|
|
724
|
-
indicator.appendChild(loadingSpinner);
|
|
725
|
-
indicator.appendChild(labelText);
|
|
726
|
-
positionIndicator();
|
|
727
|
-
requestAnimationFrame(() => {
|
|
728
|
-
indicator.style.opacity = "1";
|
|
740
|
+
// src/utils/copy-content.ts
|
|
741
|
+
var waitForFocus = () => {
|
|
742
|
+
if (document.hasFocus()) return Promise.resolve();
|
|
743
|
+
return new Promise((resolve) => {
|
|
744
|
+
const onFocus = () => {
|
|
745
|
+
window.removeEventListener("focus", onFocus);
|
|
746
|
+
resolve();
|
|
747
|
+
};
|
|
748
|
+
window.addEventListener("focus", onFocus);
|
|
749
|
+
window.focus();
|
|
729
750
|
});
|
|
730
|
-
return (tagName) => {
|
|
731
|
-
indicator.textContent = "";
|
|
732
|
-
const checkmarkIcon = document.createElement("span");
|
|
733
|
-
checkmarkIcon.textContent = "\u2713";
|
|
734
|
-
checkmarkIcon.style.display = "inline-block";
|
|
735
|
-
checkmarkIcon.style.marginRight = "4px";
|
|
736
|
-
checkmarkIcon.style.fontWeight = "600";
|
|
737
|
-
const newLabelText = document.createElement("span");
|
|
738
|
-
const tagNameMonospace = document.createElement("span");
|
|
739
|
-
tagNameMonospace.textContent = tagName ? `<${tagName}>` : "<element>";
|
|
740
|
-
tagNameMonospace.style.fontFamily = "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace";
|
|
741
|
-
tagNameMonospace.style.fontVariantNumeric = "tabular-nums";
|
|
742
|
-
newLabelText.appendChild(document.createTextNode("Grabbed "));
|
|
743
|
-
newLabelText.appendChild(tagNameMonospace);
|
|
744
|
-
indicator.appendChild(checkmarkIcon);
|
|
745
|
-
indicator.appendChild(newLabelText);
|
|
746
|
-
requestAnimationFrame(() => {
|
|
747
|
-
positionIndicator();
|
|
748
|
-
});
|
|
749
|
-
setTimeout(() => {
|
|
750
|
-
indicator.style.opacity = "0";
|
|
751
|
-
setTimeout(() => {
|
|
752
|
-
indicator.remove();
|
|
753
|
-
activeGrabbedIndicators.delete(indicator);
|
|
754
|
-
}, INDICATOR_FADE_MS);
|
|
755
|
-
}, INDICATOR_SUCCESS_VISIBLE_MS);
|
|
756
|
-
};
|
|
757
|
-
};
|
|
758
|
-
var hideLabel = () => {
|
|
759
|
-
if (activeIndicator) {
|
|
760
|
-
activeIndicator.remove();
|
|
761
|
-
activeIndicator = null;
|
|
762
|
-
}
|
|
763
|
-
isProcessing = false;
|
|
764
|
-
};
|
|
765
|
-
var cleanupGrabbedIndicators = () => {
|
|
766
|
-
for (const indicator of activeGrabbedIndicators) {
|
|
767
|
-
indicator.remove();
|
|
768
|
-
}
|
|
769
|
-
activeGrabbedIndicators.clear();
|
|
770
|
-
};
|
|
771
|
-
var activeProgressIndicator = null;
|
|
772
|
-
var createProgressIndicatorElement = () => {
|
|
773
|
-
const container = document.createElement("div");
|
|
774
|
-
container.style.position = "fixed";
|
|
775
|
-
container.style.zIndex = "2147483647";
|
|
776
|
-
container.style.pointerEvents = "none";
|
|
777
|
-
container.style.opacity = "0";
|
|
778
|
-
container.style.transition = "opacity 0.1s ease-in-out";
|
|
779
|
-
const progressBarContainer = document.createElement("div");
|
|
780
|
-
progressBarContainer.style.width = "32px";
|
|
781
|
-
progressBarContainer.style.height = "2px";
|
|
782
|
-
progressBarContainer.style.backgroundColor = "rgba(178, 28, 142, 0.2)";
|
|
783
|
-
progressBarContainer.style.borderRadius = "1px";
|
|
784
|
-
progressBarContainer.style.overflow = "hidden";
|
|
785
|
-
progressBarContainer.style.position = "relative";
|
|
786
|
-
const progressBarFill = document.createElement("div");
|
|
787
|
-
progressBarFill.style.width = "0%";
|
|
788
|
-
progressBarFill.style.height = "100%";
|
|
789
|
-
progressBarFill.style.backgroundColor = "#b21c8e";
|
|
790
|
-
progressBarFill.style.borderRadius = "1px";
|
|
791
|
-
progressBarFill.style.transition = "width 0.05s linear";
|
|
792
|
-
progressBarFill.setAttribute("data-progress-fill", "true");
|
|
793
|
-
progressBarContainer.appendChild(progressBarFill);
|
|
794
|
-
container.appendChild(progressBarContainer);
|
|
795
|
-
return container;
|
|
796
|
-
};
|
|
797
|
-
var showProgressIndicator = (root, progress, mouseX, mouseY) => {
|
|
798
|
-
if (!activeProgressIndicator) {
|
|
799
|
-
activeProgressIndicator = createProgressIndicatorElement();
|
|
800
|
-
root.appendChild(activeProgressIndicator);
|
|
801
|
-
requestAnimationFrame(() => {
|
|
802
|
-
if (activeProgressIndicator) {
|
|
803
|
-
activeProgressIndicator.style.opacity = "1";
|
|
804
|
-
}
|
|
805
|
-
});
|
|
806
|
-
}
|
|
807
|
-
const indicator = activeProgressIndicator;
|
|
808
|
-
const indicatorRect = indicator.getBoundingClientRect();
|
|
809
|
-
const viewportWidth = window.innerWidth;
|
|
810
|
-
const viewportHeight = window.innerHeight;
|
|
811
|
-
const CURSOR_OFFSET = 14;
|
|
812
|
-
const VIEWPORT_MARGIN = 8;
|
|
813
|
-
let indicatorLeft = mouseX - indicatorRect.width / 2;
|
|
814
|
-
let indicatorTop = mouseY + CURSOR_OFFSET;
|
|
815
|
-
if (indicatorTop + indicatorRect.height + VIEWPORT_MARGIN > viewportHeight) {
|
|
816
|
-
indicatorTop = mouseY - indicatorRect.height - CURSOR_OFFSET;
|
|
817
|
-
}
|
|
818
|
-
indicatorTop = Math.max(
|
|
819
|
-
VIEWPORT_MARGIN,
|
|
820
|
-
Math.min(indicatorTop, viewportHeight - indicatorRect.height - VIEWPORT_MARGIN)
|
|
821
|
-
);
|
|
822
|
-
indicatorLeft = Math.max(
|
|
823
|
-
VIEWPORT_MARGIN,
|
|
824
|
-
Math.min(indicatorLeft, viewportWidth - indicatorRect.width - VIEWPORT_MARGIN)
|
|
825
|
-
);
|
|
826
|
-
indicator.style.top = `${indicatorTop}px`;
|
|
827
|
-
indicator.style.left = `${indicatorLeft}px`;
|
|
828
|
-
const progressFill = indicator.querySelector(
|
|
829
|
-
"[data-progress-fill]"
|
|
830
|
-
);
|
|
831
|
-
if (progressFill) {
|
|
832
|
-
const percentage = Math.min(100, Math.max(0, progress * 100));
|
|
833
|
-
progressFill.style.width = `${percentage}%`;
|
|
834
|
-
}
|
|
835
751
|
};
|
|
836
|
-
var
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
if (
|
|
841
|
-
|
|
842
|
-
|
|
752
|
+
var copyContent = async (content) => {
|
|
753
|
+
await waitForFocus();
|
|
754
|
+
try {
|
|
755
|
+
if (Array.isArray(content)) {
|
|
756
|
+
if (!navigator?.clipboard?.write) {
|
|
757
|
+
for (const contentPart of content) {
|
|
758
|
+
if (typeof contentPart === "string") {
|
|
759
|
+
const result = copyContentFallback(contentPart);
|
|
760
|
+
if (!result) return result;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
return true;
|
|
843
764
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
765
|
+
await navigator.clipboard.write([
|
|
766
|
+
new ClipboardItem(
|
|
767
|
+
Object.fromEntries(
|
|
768
|
+
content.map((contentPart) => {
|
|
769
|
+
if (contentPart instanceof Blob) {
|
|
770
|
+
return [contentPart.type ?? "text/plain", contentPart];
|
|
771
|
+
} else {
|
|
772
|
+
return [
|
|
773
|
+
"text/plain",
|
|
774
|
+
new Blob([contentPart], { type: "text/plain" })
|
|
775
|
+
];
|
|
776
|
+
}
|
|
777
|
+
})
|
|
778
|
+
)
|
|
779
|
+
)
|
|
780
|
+
]);
|
|
781
|
+
return true;
|
|
782
|
+
} else if (content instanceof Blob) {
|
|
783
|
+
await navigator.clipboard.write([
|
|
784
|
+
new ClipboardItem({ [content.type]: content })
|
|
785
|
+
]);
|
|
854
786
|
return true;
|
|
855
|
-
}
|
|
787
|
+
} else {
|
|
788
|
+
try {
|
|
789
|
+
await navigator.clipboard.writeText(String(content));
|
|
790
|
+
return true;
|
|
791
|
+
} catch {
|
|
792
|
+
return copyContentFallback(content);
|
|
793
|
+
}
|
|
856
794
|
}
|
|
795
|
+
} catch {
|
|
796
|
+
return false;
|
|
857
797
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
798
|
+
};
|
|
799
|
+
var copyContentFallback = (content) => {
|
|
800
|
+
if (!document.execCommand) return false;
|
|
801
|
+
const el = document.createElement("textarea");
|
|
802
|
+
el.value = String(content);
|
|
803
|
+
el.style.clipPath = "inset(50%)";
|
|
804
|
+
el.ariaHidden = "true";
|
|
865
805
|
const doc = document.body || document.documentElement;
|
|
866
|
-
doc.
|
|
867
|
-
textareaElement.select();
|
|
868
|
-
textareaElement.setSelectionRange(0, textareaElement.value.length);
|
|
869
|
-
let didCopyToClipboard = false;
|
|
806
|
+
doc.append(el);
|
|
870
807
|
try {
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
didCopyToClipboard = false;
|
|
808
|
+
el.select();
|
|
809
|
+
return document.execCommand("copy");
|
|
874
810
|
} finally {
|
|
875
|
-
|
|
811
|
+
el.remove();
|
|
876
812
|
}
|
|
877
|
-
return didCopyToClipboard;
|
|
878
|
-
};
|
|
879
|
-
|
|
880
|
-
// src/utils/is-element-visible.ts
|
|
881
|
-
var isElementVisible = (element, computedStyle = window.getComputedStyle(element)) => {
|
|
882
|
-
return computedStyle.display !== "none" && computedStyle.visibility !== "hidden" && computedStyle.opacity !== "0";
|
|
883
813
|
};
|
|
884
814
|
|
|
885
|
-
// src/
|
|
886
|
-
var
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
return mountedRoot;
|
|
895
|
-
}
|
|
815
|
+
// src/core.tsx
|
|
816
|
+
var init = (rawOptions) => {
|
|
817
|
+
const options = {
|
|
818
|
+
enabled: true,
|
|
819
|
+
keyHoldDuration: 300,
|
|
820
|
+
...rawOptions
|
|
821
|
+
};
|
|
822
|
+
if (options.enabled === false) {
|
|
823
|
+
return;
|
|
896
824
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
825
|
+
return solidJs.createRoot((dispose) => {
|
|
826
|
+
const [isHoldingKeys, setIsHoldingKeys] = solidJs.createSignal(false);
|
|
827
|
+
const [mouseX, setMouseX] = solidJs.createSignal(-1e3);
|
|
828
|
+
const [mouseY, setMouseY] = solidJs.createSignal(-1e3);
|
|
829
|
+
const [isDragging, setIsDragging] = solidJs.createSignal(false);
|
|
830
|
+
const [dragStartX, setDragStartX] = solidJs.createSignal(-1e3);
|
|
831
|
+
const [dragStartY, setDragStartY] = solidJs.createSignal(-1e3);
|
|
832
|
+
const [isCopying, setIsCopying] = solidJs.createSignal(false);
|
|
833
|
+
const [lastGrabbedElement, setLastGrabbedElement] = solidJs.createSignal(null);
|
|
834
|
+
const [progressStartTime, setProgressStartTime] = solidJs.createSignal(null);
|
|
835
|
+
const [progressTick, setProgressTick] = solidJs.createSignal(0);
|
|
836
|
+
const [grabbedOverlays, setGrabbedOverlays] = solidJs.createSignal([]);
|
|
837
|
+
const [successLabels, setSuccessLabels] = solidJs.createSignal([]);
|
|
838
|
+
const [isActivated, setIsActivated] = solidJs.createSignal(false);
|
|
839
|
+
const [showProgressIndicator, setShowProgressIndicator] = solidJs.createSignal(false);
|
|
840
|
+
let holdTimerId = null;
|
|
841
|
+
let progressAnimationId = null;
|
|
842
|
+
let progressDelayTimerId = null;
|
|
843
|
+
const isOverlayActive = solidJs.createMemo(() => isActivated() && !isCopying());
|
|
844
|
+
const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "c";
|
|
845
|
+
const getElementAtPosition = (x, y) => {
|
|
846
|
+
const elementsAtPoint = document.elementsFromPoint(x, y);
|
|
847
|
+
for (const candidateElement of elementsAtPoint) {
|
|
848
|
+
if (candidateElement.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
const computedStyle = window.getComputedStyle(candidateElement);
|
|
852
|
+
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
853
|
+
continue;
|
|
854
|
+
}
|
|
855
|
+
return candidateElement;
|
|
856
|
+
}
|
|
857
|
+
return null;
|
|
923
858
|
};
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
859
|
+
const getElementsInMarquee = (marqueeRect) => {
|
|
860
|
+
const elements = [];
|
|
861
|
+
const allElements = Array.from(document.querySelectorAll("*"));
|
|
862
|
+
const marqueeLeft = marqueeRect.x;
|
|
863
|
+
const marqueeTop = marqueeRect.y;
|
|
864
|
+
const marqueeRight = marqueeRect.x + marqueeRect.width;
|
|
865
|
+
const marqueeBottom = marqueeRect.y + marqueeRect.height;
|
|
866
|
+
for (const candidateElement of allElements) {
|
|
867
|
+
if (candidateElement.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
868
|
+
continue;
|
|
869
|
+
}
|
|
870
|
+
const computedStyle = window.getComputedStyle(candidateElement);
|
|
871
|
+
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
const rect = candidateElement.getBoundingClientRect();
|
|
875
|
+
const elementLeft = rect.left;
|
|
876
|
+
const elementTop = rect.top;
|
|
877
|
+
const elementRight = rect.left + rect.width;
|
|
878
|
+
const elementBottom = rect.top + rect.height;
|
|
879
|
+
const intersectionLeft = Math.max(marqueeLeft, elementLeft);
|
|
880
|
+
const intersectionTop = Math.max(marqueeTop, elementTop);
|
|
881
|
+
const intersectionRight = Math.min(marqueeRight, elementRight);
|
|
882
|
+
const intersectionBottom = Math.min(marqueeBottom, elementBottom);
|
|
883
|
+
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
884
|
+
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
885
|
+
const intersectionArea = intersectionWidth * intersectionHeight;
|
|
886
|
+
const elementArea = Math.max(0, rect.width * rect.height);
|
|
887
|
+
const COVERAGE_THRESHOLD = 0.75;
|
|
888
|
+
const hasMajorityCoverage = elementArea > 0 && intersectionArea / elementArea >= COVERAGE_THRESHOLD;
|
|
889
|
+
if (hasMajorityCoverage) {
|
|
890
|
+
elements.push(candidateElement);
|
|
932
891
|
}
|
|
933
|
-
} else {
|
|
934
|
-
entry.listener(nextState, prevState);
|
|
935
892
|
}
|
|
936
|
-
|
|
937
|
-
return currentState;
|
|
938
|
-
};
|
|
939
|
-
const getState = () => {
|
|
940
|
-
return currentState;
|
|
941
|
-
};
|
|
942
|
-
const initialState = initializer(setState, getState);
|
|
943
|
-
currentState = initialState;
|
|
944
|
-
const subscribeWithSelector = (listener, selector) => {
|
|
945
|
-
const index = String(currentListenerIndex++);
|
|
946
|
-
const wrappedListener = (value, prevValue) => listener(value, prevValue);
|
|
947
|
-
const entry = {
|
|
948
|
-
listener: wrappedListener,
|
|
949
|
-
prevSelectedValue: selector(currentState),
|
|
950
|
-
selector,
|
|
951
|
-
type: "selected" /* Selected */
|
|
893
|
+
return elements;
|
|
952
894
|
};
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
895
|
+
const getElementsInMarqueeLoose = (marqueeRect) => {
|
|
896
|
+
const elements = [];
|
|
897
|
+
const allElements = Array.from(document.querySelectorAll("*"));
|
|
898
|
+
const marqueeLeft = marqueeRect.x;
|
|
899
|
+
const marqueeTop = marqueeRect.y;
|
|
900
|
+
const marqueeRight = marqueeRect.x + marqueeRect.width;
|
|
901
|
+
const marqueeBottom = marqueeRect.y + marqueeRect.height;
|
|
902
|
+
for (const candidateElement of allElements) {
|
|
903
|
+
if (candidateElement.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
904
|
+
continue;
|
|
905
|
+
}
|
|
906
|
+
const tag = (candidateElement.tagName || "").toUpperCase();
|
|
907
|
+
if (tag === "HTML" || tag === "BODY") continue;
|
|
908
|
+
const computedStyle = window.getComputedStyle(candidateElement);
|
|
909
|
+
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
910
|
+
continue;
|
|
911
|
+
}
|
|
912
|
+
const rect = candidateElement.getBoundingClientRect();
|
|
913
|
+
const elementLeft = rect.left;
|
|
914
|
+
const elementTop = rect.top;
|
|
915
|
+
const elementRight = rect.left + rect.width;
|
|
916
|
+
const elementBottom = rect.top + rect.height;
|
|
917
|
+
const intersects = elementLeft < marqueeRight && elementRight > marqueeLeft && elementTop < marqueeBottom && elementBottom > marqueeTop;
|
|
918
|
+
if (intersects) {
|
|
919
|
+
elements.push(candidateElement);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return elements;
|
|
956
923
|
};
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
924
|
+
const wrapInReferencedElement = (content) => `
|
|
925
|
+
|
|
926
|
+
<referenced_element>
|
|
927
|
+
${content}
|
|
928
|
+
</referenced_element>`;
|
|
929
|
+
const wrapInReferencedElements = (content) => `
|
|
930
|
+
|
|
931
|
+
<referenced_elements>
|
|
932
|
+
${content}
|
|
933
|
+
</referenced_elements>`;
|
|
934
|
+
const addGrabbedOverlay = (bounds) => {
|
|
935
|
+
const id = `grabbed-${Date.now()}-${Math.random()}`;
|
|
936
|
+
setGrabbedOverlays((prev) => [...prev, {
|
|
937
|
+
id,
|
|
938
|
+
bounds
|
|
939
|
+
}]);
|
|
940
|
+
setTimeout(() => {
|
|
941
|
+
setGrabbedOverlays((prev) => prev.filter((overlay) => overlay.id !== id));
|
|
942
|
+
}, 300);
|
|
963
943
|
};
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
944
|
+
const addSuccessLabel = (text, x, y) => {
|
|
945
|
+
const id = `success-${Date.now()}-${Math.random()}`;
|
|
946
|
+
setSuccessLabels((prev) => [...prev, {
|
|
947
|
+
id,
|
|
948
|
+
text,
|
|
949
|
+
x,
|
|
950
|
+
y
|
|
951
|
+
}]);
|
|
952
|
+
setTimeout(() => {
|
|
953
|
+
setSuccessLabels((prev) => prev.filter((label) => label.id !== id));
|
|
954
|
+
}, 1700);
|
|
967
955
|
};
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
956
|
+
const handleCopy = async (targetElement2) => {
|
|
957
|
+
const elementBounds = targetElement2.getBoundingClientRect();
|
|
958
|
+
const tagName = (targetElement2.tagName || "").toLowerCase();
|
|
959
|
+
addGrabbedOverlay({
|
|
960
|
+
borderRadius: window.getComputedStyle(targetElement2).borderRadius || "0px",
|
|
961
|
+
height: elementBounds.height,
|
|
962
|
+
transform: window.getComputedStyle(targetElement2).transform || "none",
|
|
963
|
+
width: elementBounds.width,
|
|
964
|
+
x: elementBounds.left,
|
|
965
|
+
y: elementBounds.top
|
|
966
|
+
});
|
|
967
|
+
try {
|
|
968
|
+
const elementHtml = getHTMLSnippet(targetElement2);
|
|
969
|
+
await copyContent(wrapInReferencedElement(elementHtml));
|
|
970
|
+
const componentStackTrace = await getSourceTrace(targetElement2);
|
|
971
|
+
if (componentStackTrace?.length) {
|
|
972
|
+
const formattedStackTrace = componentStackTrace.map((source) => ` ${source.functionName} - ${source.fileName}:${source.lineNumber}:${source.columnNumber}`).join("\n");
|
|
973
|
+
await copyContent(wrapInReferencedElement(`${elementHtml}
|
|
982
974
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
keyPressTimestamps: /* @__PURE__ */ new Map(),
|
|
986
|
-
mouseX: -1e3,
|
|
987
|
-
mouseY: -1e3,
|
|
988
|
-
overlayMode: "hidden",
|
|
989
|
-
pressedKeys: /* @__PURE__ */ new Set()
|
|
990
|
-
}));
|
|
991
|
-
var getDefaultHotkey = () => {
|
|
992
|
-
if (typeof navigator === "undefined") {
|
|
993
|
-
return ["Meta", "C"];
|
|
994
|
-
}
|
|
995
|
-
const isMac = navigator.platform.toLowerCase().includes("mac");
|
|
996
|
-
return isMac ? ["Meta", "C"] : ["Control", "C"];
|
|
997
|
-
};
|
|
998
|
-
var init = (options = {}) => {
|
|
999
|
-
if (options.enabled === false) {
|
|
1000
|
-
return;
|
|
1001
|
-
}
|
|
1002
|
-
const resolvedOptions = {
|
|
1003
|
-
adapter: void 0,
|
|
1004
|
-
enabled: true,
|
|
1005
|
-
hotkey: options.hotkey ?? getDefaultHotkey(),
|
|
1006
|
-
keyHoldDuration: 500,
|
|
1007
|
-
...options
|
|
1008
|
-
};
|
|
1009
|
-
const root = mountRoot();
|
|
1010
|
-
const selectionOverlay = createSelectionOverlay(root);
|
|
1011
|
-
let hoveredElement = null;
|
|
1012
|
-
let lastGrabbedElement = null;
|
|
1013
|
-
let isCopying = false;
|
|
1014
|
-
let progressAnimationFrame = null;
|
|
1015
|
-
let progressStartTime = null;
|
|
1016
|
-
const checkIsActivationHotkeyPressed = () => {
|
|
1017
|
-
if (Array.isArray(resolvedOptions.hotkey)) {
|
|
1018
|
-
for (const key of resolvedOptions.hotkey) {
|
|
1019
|
-
if (!isKeyPressed(key)) {
|
|
1020
|
-
return false;
|
|
975
|
+
Component owner stack:
|
|
976
|
+
${formattedStackTrace}`));
|
|
1021
977
|
}
|
|
978
|
+
} catch {
|
|
1022
979
|
}
|
|
1023
|
-
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
const handleKeyStateChange = (pressedKeys) => {
|
|
1054
|
-
const { overlayMode } = libStore.getState();
|
|
1055
|
-
if (pressedKeys.has("Escape") || pressedKeys.has("Esc")) {
|
|
1056
|
-
libStore.setState((state) => {
|
|
1057
|
-
const nextPressedKeys = new Set(state.pressedKeys);
|
|
1058
|
-
nextPressedKeys.delete("Escape");
|
|
1059
|
-
nextPressedKeys.delete("Esc");
|
|
1060
|
-
const nextTimestamps = new Map(state.keyPressTimestamps);
|
|
1061
|
-
nextTimestamps.delete("Escape");
|
|
1062
|
-
nextTimestamps.delete("Esc");
|
|
1063
|
-
const activationKeys = Array.isArray(resolvedOptions.hotkey) ? resolvedOptions.hotkey : [resolvedOptions.hotkey];
|
|
1064
|
-
for (const activationKey of activationKeys) {
|
|
1065
|
-
if (activationKey.length === 1) {
|
|
1066
|
-
nextPressedKeys.delete(activationKey.toLowerCase());
|
|
1067
|
-
nextPressedKeys.delete(activationKey.toUpperCase());
|
|
1068
|
-
nextTimestamps.delete(activationKey.toLowerCase());
|
|
1069
|
-
nextTimestamps.delete(activationKey.toUpperCase());
|
|
980
|
+
addSuccessLabel(tagName ? `<${tagName}>` : "<element>", elementBounds.left, elementBounds.top);
|
|
981
|
+
};
|
|
982
|
+
const handleMultipleCopy = async (targetElements) => {
|
|
983
|
+
if (targetElements.length === 0) return;
|
|
984
|
+
let minX = Infinity;
|
|
985
|
+
let minY = Infinity;
|
|
986
|
+
for (const element of targetElements) {
|
|
987
|
+
const elementBounds = element.getBoundingClientRect();
|
|
988
|
+
minX = Math.min(minX, elementBounds.left);
|
|
989
|
+
minY = Math.min(minY, elementBounds.top);
|
|
990
|
+
addGrabbedOverlay({
|
|
991
|
+
borderRadius: window.getComputedStyle(element).borderRadius || "0px",
|
|
992
|
+
height: elementBounds.height,
|
|
993
|
+
transform: window.getComputedStyle(element).transform || "none",
|
|
994
|
+
width: elementBounds.width,
|
|
995
|
+
x: elementBounds.left,
|
|
996
|
+
y: elementBounds.top
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
try {
|
|
1000
|
+
const elementSnippets = [];
|
|
1001
|
+
for (const element of targetElements) {
|
|
1002
|
+
const elementHtml = getHTMLSnippet(element);
|
|
1003
|
+
const componentStackTrace = await getSourceTrace(element);
|
|
1004
|
+
if (componentStackTrace?.length) {
|
|
1005
|
+
const formattedStackTrace = componentStackTrace.map((source) => ` ${source.functionName} - ${source.fileName}:${source.lineNumber}:${source.columnNumber}`).join("\n");
|
|
1006
|
+
elementSnippets.push(`${elementHtml}
|
|
1007
|
+
|
|
1008
|
+
Component owner stack:
|
|
1009
|
+
${formattedStackTrace}`);
|
|
1070
1010
|
} else {
|
|
1071
|
-
|
|
1072
|
-
nextTimestamps.delete(activationKey);
|
|
1011
|
+
elementSnippets.push(elementHtml);
|
|
1073
1012
|
}
|
|
1074
1013
|
}
|
|
1014
|
+
const combinedContent = elementSnippets.join("\n\n---\n\n");
|
|
1015
|
+
await copyContent(wrapInReferencedElements(combinedContent));
|
|
1016
|
+
} catch {
|
|
1017
|
+
}
|
|
1018
|
+
addSuccessLabel(`${targetElements.length} elements`, minX, minY);
|
|
1019
|
+
};
|
|
1020
|
+
const targetElement = solidJs.createMemo(() => {
|
|
1021
|
+
if (!isOverlayActive() || isDragging()) return null;
|
|
1022
|
+
return getElementAtPosition(mouseX(), mouseY());
|
|
1023
|
+
});
|
|
1024
|
+
const selectionBounds = solidJs.createMemo(() => {
|
|
1025
|
+
const element = targetElement();
|
|
1026
|
+
if (!element) return void 0;
|
|
1027
|
+
const last = lastGrabbedElement();
|
|
1028
|
+
if (last && element === last) return void 0;
|
|
1029
|
+
const elementBounds = element.getBoundingClientRect();
|
|
1030
|
+
const computedStyle = window.getComputedStyle(element);
|
|
1031
|
+
return {
|
|
1032
|
+
borderRadius: computedStyle.borderRadius || "0px",
|
|
1033
|
+
height: elementBounds.height,
|
|
1034
|
+
transform: computedStyle.transform || "none",
|
|
1035
|
+
width: elementBounds.width,
|
|
1036
|
+
x: elementBounds.left,
|
|
1037
|
+
y: elementBounds.top
|
|
1038
|
+
};
|
|
1039
|
+
});
|
|
1040
|
+
const marqueeBounds = solidJs.createMemo(() => {
|
|
1041
|
+
if (!isDragging()) return void 0;
|
|
1042
|
+
const marqueeX = Math.min(dragStartX(), mouseX());
|
|
1043
|
+
const marqueeY = Math.min(dragStartY(), mouseY());
|
|
1044
|
+
const marqueeWidth = Math.abs(mouseX() - dragStartX());
|
|
1045
|
+
const marqueeHeight = Math.abs(mouseY() - dragStartY());
|
|
1046
|
+
return {
|
|
1047
|
+
borderRadius: "0px",
|
|
1048
|
+
height: marqueeHeight,
|
|
1049
|
+
transform: "none",
|
|
1050
|
+
width: marqueeWidth,
|
|
1051
|
+
x: marqueeX,
|
|
1052
|
+
y: marqueeY
|
|
1053
|
+
};
|
|
1054
|
+
});
|
|
1055
|
+
const labelText = solidJs.createMemo(() => {
|
|
1056
|
+
const element = targetElement();
|
|
1057
|
+
if (!element) return "";
|
|
1058
|
+
const tagName = (element.tagName || "").toLowerCase();
|
|
1059
|
+
return tagName ? `<${tagName}>` : "<element>";
|
|
1060
|
+
});
|
|
1061
|
+
const labelPosition = solidJs.createMemo(() => {
|
|
1062
|
+
const element = targetElement() ?? lastGrabbedElement();
|
|
1063
|
+
if (element) {
|
|
1064
|
+
const rect = element.getBoundingClientRect();
|
|
1075
1065
|
return {
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
overlayMode: "hidden",
|
|
1079
|
-
pressedKeys: nextPressedKeys
|
|
1066
|
+
x: rect.left,
|
|
1067
|
+
y: rect.top
|
|
1080
1068
|
};
|
|
1081
|
-
});
|
|
1082
|
-
if (cleanupActivationHotkeyWatcher) {
|
|
1083
|
-
cleanupActivationHotkeyWatcher();
|
|
1084
|
-
cleanupActivationHotkeyWatcher = null;
|
|
1085
|
-
}
|
|
1086
|
-
stopProgressTracking();
|
|
1087
|
-
return;
|
|
1088
|
-
}
|
|
1089
|
-
const isActivationHotkeyPressed = checkIsActivationHotkeyPressed();
|
|
1090
|
-
if (!isActivationHotkeyPressed) {
|
|
1091
|
-
if (cleanupActivationHotkeyWatcher) {
|
|
1092
|
-
cleanupActivationHotkeyWatcher();
|
|
1093
|
-
cleanupActivationHotkeyWatcher = null;
|
|
1094
|
-
}
|
|
1095
|
-
if (overlayMode !== "hidden") {
|
|
1096
|
-
libStore.setState((state) => ({
|
|
1097
|
-
...state,
|
|
1098
|
-
overlayMode: "hidden"
|
|
1099
|
-
}));
|
|
1100
1069
|
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
startProgressTracking();
|
|
1106
|
-
cleanupActivationHotkeyWatcher = watchKeyHeldFor(
|
|
1107
|
-
resolvedOptions.hotkey,
|
|
1108
|
-
resolvedOptions.keyHoldDuration,
|
|
1109
|
-
() => {
|
|
1110
|
-
libStore.setState((state) => ({
|
|
1111
|
-
...state,
|
|
1112
|
-
overlayMode: "visible"
|
|
1113
|
-
}));
|
|
1114
|
-
stopProgressTracking();
|
|
1115
|
-
cleanupActivationHotkeyWatcher = null;
|
|
1116
|
-
}
|
|
1117
|
-
);
|
|
1118
|
-
}
|
|
1119
|
-
};
|
|
1120
|
-
const cleanupKeyStateChangeSubscription = libStore.subscribe(
|
|
1121
|
-
handleKeyStateChange,
|
|
1122
|
-
(state) => state.pressedKeys
|
|
1123
|
-
);
|
|
1124
|
-
let mouseMoveScheduled = false;
|
|
1125
|
-
let pendingMouseX = -1e3;
|
|
1126
|
-
let pendingMouseY = -1e3;
|
|
1127
|
-
const handleMouseMove = (event) => {
|
|
1128
|
-
pendingMouseX = event.clientX;
|
|
1129
|
-
pendingMouseY = event.clientY;
|
|
1130
|
-
if (mouseMoveScheduled) return;
|
|
1131
|
-
mouseMoveScheduled = true;
|
|
1132
|
-
requestAnimationFrame(() => {
|
|
1133
|
-
mouseMoveScheduled = false;
|
|
1134
|
-
libStore.setState((state) => ({
|
|
1135
|
-
...state,
|
|
1136
|
-
mouseX: pendingMouseX,
|
|
1137
|
-
mouseY: pendingMouseY
|
|
1138
|
-
}));
|
|
1070
|
+
return {
|
|
1071
|
+
x: mouseX(),
|
|
1072
|
+
y: mouseY()
|
|
1073
|
+
};
|
|
1139
1074
|
});
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
return;
|
|
1144
|
-
}
|
|
1145
|
-
const { overlayMode } = libStore.getState();
|
|
1146
|
-
if (overlayMode === "hidden") {
|
|
1147
|
-
return;
|
|
1148
|
-
}
|
|
1149
|
-
event.preventDefault();
|
|
1150
|
-
event.stopPropagation();
|
|
1151
|
-
event.stopImmediatePropagation();
|
|
1152
|
-
libStore.setState((state) => ({
|
|
1153
|
-
...state,
|
|
1154
|
-
overlayMode: "copying"
|
|
1155
|
-
}));
|
|
1156
|
-
};
|
|
1157
|
-
const handleClick = (event) => {
|
|
1158
|
-
const { overlayMode } = libStore.getState();
|
|
1159
|
-
if (overlayMode === "hidden") {
|
|
1160
|
-
return;
|
|
1161
|
-
}
|
|
1162
|
-
event.preventDefault();
|
|
1163
|
-
event.stopPropagation();
|
|
1164
|
-
event.stopImmediatePropagation();
|
|
1165
|
-
};
|
|
1166
|
-
const handleVisibilityChange = () => {
|
|
1167
|
-
if (document.hidden) {
|
|
1168
|
-
cleanupGrabbedIndicators();
|
|
1169
|
-
hideLabel();
|
|
1170
|
-
}
|
|
1171
|
-
};
|
|
1172
|
-
let scrollScheduled = false;
|
|
1173
|
-
const handleScroll = () => {
|
|
1174
|
-
if (scrollScheduled) return;
|
|
1175
|
-
scrollScheduled = true;
|
|
1176
|
-
requestAnimationFrame(() => {
|
|
1177
|
-
scrollScheduled = false;
|
|
1178
|
-
scheduleRender();
|
|
1075
|
+
const isSameAsLast = solidJs.createMemo(() => {
|
|
1076
|
+
const current = targetElement();
|
|
1077
|
+
const last = lastGrabbedElement();
|
|
1078
|
+
return !!current && current === last;
|
|
1179
1079
|
});
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
resizeScheduled = false;
|
|
1187
|
-
scheduleRender();
|
|
1080
|
+
solidJs.createEffect(() => {
|
|
1081
|
+
const current = targetElement();
|
|
1082
|
+
const last = lastGrabbedElement();
|
|
1083
|
+
if (last && current && last !== current) {
|
|
1084
|
+
setLastGrabbedElement(null);
|
|
1085
|
+
}
|
|
1188
1086
|
});
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1087
|
+
const progress = solidJs.createMemo(() => {
|
|
1088
|
+
const startTime = progressStartTime();
|
|
1089
|
+
progressTick();
|
|
1090
|
+
if (startTime === null) return 0;
|
|
1091
|
+
const elapsed = Date.now() - startTime;
|
|
1092
|
+
return Math.min(elapsed / options.keyHoldDuration, 1);
|
|
1093
|
+
});
|
|
1094
|
+
const startProgressAnimation = () => {
|
|
1095
|
+
setProgressStartTime(Date.now());
|
|
1096
|
+
setShowProgressIndicator(false);
|
|
1097
|
+
progressDelayTimerId = window.setTimeout(() => {
|
|
1098
|
+
setShowProgressIndicator(true);
|
|
1099
|
+
progressDelayTimerId = null;
|
|
1100
|
+
}, 150);
|
|
1101
|
+
const animateProgress = () => {
|
|
1102
|
+
if (progressStartTime() === null) return;
|
|
1103
|
+
setProgressTick((t) => t + 1);
|
|
1104
|
+
const currentProgress = progress();
|
|
1105
|
+
if (currentProgress < 1) {
|
|
1106
|
+
progressAnimationId = requestAnimationFrame(animateProgress);
|
|
1107
|
+
}
|
|
1108
|
+
};
|
|
1109
|
+
animateProgress();
|
|
1110
|
+
};
|
|
1111
|
+
const stopProgressAnimation = () => {
|
|
1112
|
+
if (progressAnimationId !== null) {
|
|
1113
|
+
cancelAnimationFrame(progressAnimationId);
|
|
1114
|
+
progressAnimationId = null;
|
|
1202
1115
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1116
|
+
if (progressDelayTimerId !== null) {
|
|
1117
|
+
window.clearTimeout(progressDelayTimerId);
|
|
1118
|
+
progressDelayTimerId = null;
|
|
1206
1119
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
const
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
);
|
|
1224
|
-
const stack = await getStack(element);
|
|
1225
|
-
if (stack) {
|
|
1226
|
-
const filteredStack = filterStack(stack);
|
|
1227
|
-
if (filteredStack.length > 0) {
|
|
1228
|
-
const serializedStack = serializeStack(filteredStack);
|
|
1229
|
-
const fullText = `${htmlSnippet}
|
|
1230
|
-
|
|
1231
|
-
Component owner stack:
|
|
1232
|
-
${serializedStack}`;
|
|
1233
|
-
await copyTextToClipboard(
|
|
1234
|
-
`
|
|
1235
|
-
|
|
1236
|
-
<referenced_element>
|
|
1237
|
-
${fullText}
|
|
1238
|
-
</referenced_element>`
|
|
1239
|
-
).catch(() => {
|
|
1240
|
-
});
|
|
1241
|
-
if (resolvedOptions.adapter) {
|
|
1242
|
-
resolvedOptions.adapter.open(fullText);
|
|
1243
|
-
}
|
|
1244
|
-
} else if (resolvedOptions.adapter) {
|
|
1245
|
-
resolvedOptions.adapter.open(htmlSnippet);
|
|
1246
|
-
}
|
|
1247
|
-
} else if (resolvedOptions.adapter) {
|
|
1248
|
-
resolvedOptions.adapter.open(htmlSnippet);
|
|
1120
|
+
setProgressStartTime(null);
|
|
1121
|
+
setShowProgressIndicator(false);
|
|
1122
|
+
};
|
|
1123
|
+
const activateOverlay = () => {
|
|
1124
|
+
stopProgressAnimation();
|
|
1125
|
+
setIsActivated(true);
|
|
1126
|
+
};
|
|
1127
|
+
const abortController = new AbortController();
|
|
1128
|
+
const signal = abortController.signal;
|
|
1129
|
+
window.addEventListener("keydown", (event) => {
|
|
1130
|
+
if (event.key === "Escape" && isHoldingKeys()) {
|
|
1131
|
+
setIsHoldingKeys(false);
|
|
1132
|
+
setIsActivated(false);
|
|
1133
|
+
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1134
|
+
stopProgressAnimation();
|
|
1135
|
+
return;
|
|
1249
1136
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
if (selectionOverlay.isVisible()) {
|
|
1259
|
-
selectionOverlay.hide();
|
|
1137
|
+
if (isKeyboardEventTriggeredByInput(event)) return;
|
|
1138
|
+
if (isTargetKeyCombination(event) && !isHoldingKeys()) {
|
|
1139
|
+
setIsHoldingKeys(true);
|
|
1140
|
+
startProgressAnimation();
|
|
1141
|
+
holdTimerId = window.setTimeout(() => {
|
|
1142
|
+
activateOverlay();
|
|
1143
|
+
options.onActivate?.();
|
|
1144
|
+
}, options.keyHoldDuration);
|
|
1260
1145
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1146
|
+
}, {
|
|
1147
|
+
signal
|
|
1148
|
+
});
|
|
1149
|
+
window.addEventListener("keyup", (event) => {
|
|
1150
|
+
if (isHoldingKeys() && (!isTargetKeyCombination(event) || event.key.toLowerCase() === "c")) {
|
|
1151
|
+
setIsHoldingKeys(false);
|
|
1152
|
+
setIsActivated(false);
|
|
1153
|
+
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1154
|
+
stopProgressAnimation();
|
|
1263
1155
|
}
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1156
|
+
}, {
|
|
1157
|
+
signal
|
|
1158
|
+
});
|
|
1159
|
+
window.addEventListener("mousemove", (event) => {
|
|
1160
|
+
setMouseX(event.clientX);
|
|
1161
|
+
setMouseY(event.clientY);
|
|
1162
|
+
}, {
|
|
1163
|
+
signal
|
|
1164
|
+
});
|
|
1165
|
+
window.addEventListener("mousedown", (event) => {
|
|
1166
|
+
if (!isOverlayActive() || isCopying()) return;
|
|
1167
|
+
setIsDragging(true);
|
|
1168
|
+
setDragStartX(event.clientX);
|
|
1169
|
+
setDragStartY(event.clientY);
|
|
1170
|
+
}, {
|
|
1171
|
+
signal
|
|
1172
|
+
});
|
|
1173
|
+
window.addEventListener("mouseup", (event) => {
|
|
1174
|
+
if (!isDragging()) return;
|
|
1175
|
+
const dragDistanceX = Math.abs(event.clientX - dragStartX());
|
|
1176
|
+
const dragDistanceY = Math.abs(event.clientY - dragStartY());
|
|
1177
|
+
const DRAG_THRESHOLD = 5;
|
|
1178
|
+
const wasDrag = dragDistanceX > DRAG_THRESHOLD || dragDistanceY > DRAG_THRESHOLD;
|
|
1179
|
+
setIsDragging(false);
|
|
1180
|
+
if (wasDrag) {
|
|
1181
|
+
const marqueeX = Math.min(dragStartX(), event.clientX);
|
|
1182
|
+
const marqueeY = Math.min(dragStartY(), event.clientY);
|
|
1183
|
+
const marqueeWidth = Math.abs(event.clientX - dragStartX());
|
|
1184
|
+
const marqueeHeight = Math.abs(event.clientY - dragStartY());
|
|
1185
|
+
const elements = getElementsInMarquee({
|
|
1186
|
+
x: marqueeX,
|
|
1187
|
+
y: marqueeY,
|
|
1188
|
+
width: marqueeWidth,
|
|
1189
|
+
height: marqueeHeight
|
|
1281
1190
|
});
|
|
1282
|
-
|
|
1283
|
-
|
|
1191
|
+
if (elements.length > 0) {
|
|
1192
|
+
setIsCopying(true);
|
|
1193
|
+
void handleMultipleCopy(elements).finally(() => {
|
|
1194
|
+
setIsCopying(false);
|
|
1195
|
+
});
|
|
1196
|
+
} else {
|
|
1197
|
+
const fallbackElements = getElementsInMarqueeLoose({
|
|
1198
|
+
x: marqueeX,
|
|
1199
|
+
y: marqueeY,
|
|
1200
|
+
width: marqueeWidth,
|
|
1201
|
+
height: marqueeHeight
|
|
1202
|
+
});
|
|
1203
|
+
if (fallbackElements.length > 0) {
|
|
1204
|
+
setIsCopying(true);
|
|
1205
|
+
void handleMultipleCopy(fallbackElements).finally(() => {
|
|
1206
|
+
setIsCopying(false);
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
} else {
|
|
1211
|
+
const element = getElementAtPosition(event.clientX, event.clientY);
|
|
1212
|
+
if (!element) return;
|
|
1213
|
+
setIsCopying(true);
|
|
1214
|
+
setLastGrabbedElement(element);
|
|
1215
|
+
void handleCopy(element).finally(() => {
|
|
1216
|
+
setIsCopying(false);
|
|
1284
1217
|
});
|
|
1285
|
-
const isStillPressed = checkIsActivationHotkeyPressed();
|
|
1286
|
-
libStore.setState((state2) => ({
|
|
1287
|
-
...state2,
|
|
1288
|
-
overlayMode: isStillPressed ? "visible" : "hidden"
|
|
1289
|
-
}));
|
|
1290
|
-
}
|
|
1291
|
-
return;
|
|
1292
|
-
}
|
|
1293
|
-
const element = getElementAtPosition(mouseX, mouseY);
|
|
1294
|
-
if (!element) {
|
|
1295
|
-
if (selectionOverlay.isVisible()) {
|
|
1296
|
-
selectionOverlay.hide();
|
|
1297
|
-
}
|
|
1298
|
-
if (!isCopying) {
|
|
1299
|
-
hideLabel();
|
|
1300
|
-
}
|
|
1301
|
-
hoveredElement = null;
|
|
1302
|
-
return;
|
|
1303
|
-
}
|
|
1304
|
-
if (lastGrabbedElement && element !== lastGrabbedElement) {
|
|
1305
|
-
lastGrabbedElement = null;
|
|
1306
|
-
}
|
|
1307
|
-
if (element === lastGrabbedElement) {
|
|
1308
|
-
if (selectionOverlay.isVisible()) {
|
|
1309
|
-
selectionOverlay.hide();
|
|
1310
1218
|
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
}
|
|
1314
|
-
hoveredElement = element;
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
const tagName = (element.tagName || "").toLowerCase();
|
|
1318
|
-
hoveredElement = element;
|
|
1319
|
-
const rect = element.getBoundingClientRect();
|
|
1320
|
-
const computedStyle = window.getComputedStyle(element);
|
|
1321
|
-
const borderRadius = computedStyle.borderRadius || "0px";
|
|
1322
|
-
const transform = computedStyle.transform || "none";
|
|
1323
|
-
selectionOverlay.update({
|
|
1324
|
-
borderRadius,
|
|
1325
|
-
height: rect.height,
|
|
1326
|
-
transform,
|
|
1327
|
-
width: rect.width,
|
|
1328
|
-
x: rect.left,
|
|
1329
|
-
y: rect.top
|
|
1219
|
+
}, {
|
|
1220
|
+
signal
|
|
1330
1221
|
});
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
if (
|
|
1342
|
-
|
|
1222
|
+
window.addEventListener("scroll", () => {
|
|
1223
|
+
}, {
|
|
1224
|
+
signal,
|
|
1225
|
+
capture: true
|
|
1226
|
+
});
|
|
1227
|
+
window.addEventListener("resize", () => {
|
|
1228
|
+
}, {
|
|
1229
|
+
signal
|
|
1230
|
+
});
|
|
1231
|
+
document.addEventListener("visibilitychange", () => {
|
|
1232
|
+
if (document.hidden) {
|
|
1233
|
+
setGrabbedOverlays([]);
|
|
1343
1234
|
}
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
let renderScheduled = false;
|
|
1347
|
-
const scheduleRender = () => {
|
|
1348
|
-
if (renderScheduled) return;
|
|
1349
|
-
renderScheduled = true;
|
|
1350
|
-
requestAnimationFrame(() => {
|
|
1351
|
-
renderScheduled = false;
|
|
1352
|
-
handleRender(libStore.getState());
|
|
1235
|
+
}, {
|
|
1236
|
+
signal
|
|
1353
1237
|
});
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1238
|
+
solidJs.onCleanup(() => {
|
|
1239
|
+
abortController.abort();
|
|
1240
|
+
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1241
|
+
stopProgressAnimation();
|
|
1242
|
+
});
|
|
1243
|
+
const overlayRoot = mountRoot();
|
|
1244
|
+
const overlayProps = solidJs.createMemo(() => ({
|
|
1245
|
+
selectionVisible: isOverlayActive() && !isDragging() && !!selectionBounds(),
|
|
1246
|
+
selectionBounds: selectionBounds(),
|
|
1247
|
+
marqueeVisible: isOverlayActive() && isDragging(),
|
|
1248
|
+
marqueeBounds: marqueeBounds(),
|
|
1249
|
+
grabbedOverlays: grabbedOverlays(),
|
|
1250
|
+
successLabels: successLabels(),
|
|
1251
|
+
labelVariant: isCopying() ? "processing" : "hover",
|
|
1252
|
+
labelText: labelText(),
|
|
1253
|
+
labelX: labelPosition().x,
|
|
1254
|
+
labelY: labelPosition().y,
|
|
1255
|
+
labelVisible: isOverlayActive() && !isDragging() && !!targetElement() && !isSameAsLast() || isCopying(),
|
|
1256
|
+
progressVisible: isHoldingKeys() && showProgressIndicator(),
|
|
1257
|
+
progress: progress(),
|
|
1258
|
+
mouseX: mouseX(),
|
|
1259
|
+
mouseY: mouseY()
|
|
1260
|
+
}));
|
|
1261
|
+
web.render(() => web.createComponent(ReactGrabOverlay, web.mergeProps(overlayProps)), overlayRoot);
|
|
1262
|
+
return dispose;
|
|
1357
1263
|
});
|
|
1358
|
-
const continuousRender = () => {
|
|
1359
|
-
scheduleRender();
|
|
1360
|
-
requestAnimationFrame(continuousRender);
|
|
1361
|
-
};
|
|
1362
|
-
continuousRender();
|
|
1363
|
-
return () => {
|
|
1364
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
1365
|
-
window.removeEventListener("mousedown", handleMouseDown, true);
|
|
1366
|
-
window.removeEventListener("click", handleClick, true);
|
|
1367
|
-
window.removeEventListener("scroll", handleScroll, true);
|
|
1368
|
-
window.removeEventListener("resize", handleResize);
|
|
1369
|
-
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
1370
|
-
cleanupTrackHotkeys();
|
|
1371
|
-
cleanupRenderSubscription();
|
|
1372
|
-
cleanupKeyStateChangeSubscription();
|
|
1373
|
-
if (cleanupActivationHotkeyWatcher) {
|
|
1374
|
-
cleanupActivationHotkeyWatcher();
|
|
1375
|
-
}
|
|
1376
|
-
stopProgressTracking();
|
|
1377
|
-
cleanupGrabbedIndicators();
|
|
1378
|
-
hideLabel();
|
|
1379
|
-
};
|
|
1380
1264
|
};
|
|
1381
|
-
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
1382
|
-
const currentScript = document.currentScript;
|
|
1383
|
-
const options = {};
|
|
1384
|
-
if (currentScript?.dataset) {
|
|
1385
|
-
const { adapter, enabled, hotkey, keyHoldDuration } = currentScript.dataset;
|
|
1386
|
-
if (adapter !== void 0) {
|
|
1387
|
-
if (adapter === "cursor") {
|
|
1388
|
-
options.adapter = cursorAdapter;
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
if (enabled !== void 0) {
|
|
1392
|
-
options.enabled = enabled === "true";
|
|
1393
|
-
}
|
|
1394
|
-
if (hotkey !== void 0) {
|
|
1395
|
-
const keys = hotkey.split(",").map((key) => key.trim());
|
|
1396
|
-
options.hotkey = keys.length === 1 ? keys[0] : keys;
|
|
1397
|
-
}
|
|
1398
|
-
if (keyHoldDuration !== void 0) {
|
|
1399
|
-
const duration = Number(keyHoldDuration);
|
|
1400
|
-
if (!Number.isNaN(duration)) {
|
|
1401
|
-
options.keyHoldDuration = duration;
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
init(options);
|
|
1406
|
-
}
|
|
1407
1265
|
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
exports.libStore = libStore;
|
|
1266
|
+
// src/index.ts
|
|
1267
|
+
init();
|