react-grab 0.0.24 → 0.0.25
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 +571 -446
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.global.js +16 -29
- package/dist/index.js +573 -448
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { render, createComponent,
|
|
2
|
-
import { createRoot, createSignal, createMemo, createEffect, onCleanup, Show, For } from 'solid-js';
|
|
1
|
+
import { render, createComponent, memo, template, effect, style, setStyleProperty, insert, use } from 'solid-js/web';
|
|
2
|
+
import { createRoot, createSignal, createMemo, createEffect, on, onCleanup, Show, For, onMount } from 'solid-js';
|
|
3
3
|
import { instrument, _fiberRoots, getFiberFromHostInstance } from 'bippy';
|
|
4
4
|
import { getOwnerStack, getSourcesFromStack } from 'bippy/dist/source';
|
|
5
5
|
|
|
@@ -89,93 +89,89 @@ var mountRoot = () => {
|
|
|
89
89
|
return root;
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
-
// src/
|
|
93
|
-
var isElementVisible = (element, computedStyle = window.getComputedStyle(element)) => {
|
|
94
|
-
return computedStyle.display !== "none" && computedStyle.visibility !== "hidden" && computedStyle.opacity !== "0";
|
|
95
|
-
};
|
|
96
|
-
var _tmpl$ = /* @__PURE__ */ template(`<div>`);
|
|
97
|
-
var _tmpl$2 = /* @__PURE__ */ 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">`);
|
|
98
|
-
var _tmpl$3 = /* @__PURE__ */ template(`<span style=display:inline-block;margin-right:4px;font-weight:600>\u2713`);
|
|
99
|
-
var _tmpl$4 = /* @__PURE__ */ template(`<span style="font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;font-variant-numeric:tabular-nums">`);
|
|
100
|
-
var _tmpl$5 = /* @__PURE__ */ 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>`);
|
|
101
|
-
var _tmpl$6 = /* @__PURE__ */ 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)">`);
|
|
92
|
+
// src/constants.ts
|
|
102
93
|
var VIEWPORT_MARGIN_PX = 8;
|
|
103
|
-
var LABEL_OFFSET_PX = 6;
|
|
104
94
|
var INDICATOR_CLAMP_PADDING_PX = 4;
|
|
105
|
-
var
|
|
95
|
+
var CURSOR_OFFSET_PX = 14;
|
|
106
96
|
var SELECTION_LERP_FACTOR = 0.95;
|
|
107
|
-
|
|
97
|
+
|
|
98
|
+
// src/utils/lerp.ts
|
|
108
99
|
var lerp = (start, end, factor) => {
|
|
109
100
|
return start + (end - start) * factor;
|
|
110
101
|
};
|
|
111
|
-
|
|
102
|
+
|
|
103
|
+
// src/components/selection-box.tsx
|
|
104
|
+
var _tmpl$ = /* @__PURE__ */ template(`<div>`);
|
|
105
|
+
var SelectionBox = (props) => {
|
|
112
106
|
const [currentX, setCurrentX] = createSignal(props.bounds.x);
|
|
113
107
|
const [currentY, setCurrentY] = createSignal(props.bounds.y);
|
|
114
108
|
const [currentWidth, setCurrentWidth] = createSignal(props.bounds.width);
|
|
115
109
|
const [currentHeight, setCurrentHeight] = createSignal(props.bounds.height);
|
|
116
110
|
const [opacity, setOpacity] = createSignal(1);
|
|
117
|
-
let
|
|
111
|
+
let hasBeenRenderedOnce = false;
|
|
118
112
|
let animationFrameId = null;
|
|
119
113
|
let targetBounds = props.bounds;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const EPSILON = 0.5;
|
|
114
|
+
let isAnimating = false;
|
|
115
|
+
const lerpFactor = () => {
|
|
116
|
+
if (props.lerpFactor !== void 0) return props.lerpFactor;
|
|
117
|
+
if (props.variant === "drag") return 0.9;
|
|
118
|
+
return SELECTION_LERP_FACTOR;
|
|
119
|
+
};
|
|
120
|
+
const startAnimation = () => {
|
|
121
|
+
if (isAnimating) return;
|
|
122
|
+
isAnimating = true;
|
|
132
123
|
const animate = () => {
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
setCurrentX(
|
|
138
|
-
setCurrentY(
|
|
139
|
-
setCurrentWidth(
|
|
140
|
-
setCurrentHeight(
|
|
141
|
-
const
|
|
142
|
-
if (!
|
|
124
|
+
const interpolatedX = lerp(currentX(), targetBounds.x, lerpFactor());
|
|
125
|
+
const interpolatedY = lerp(currentY(), targetBounds.y, lerpFactor());
|
|
126
|
+
const interpolatedWidth = lerp(currentWidth(), targetBounds.width, lerpFactor());
|
|
127
|
+
const interpolatedHeight = lerp(currentHeight(), targetBounds.height, lerpFactor());
|
|
128
|
+
setCurrentX(interpolatedX);
|
|
129
|
+
setCurrentY(interpolatedY);
|
|
130
|
+
setCurrentWidth(interpolatedWidth);
|
|
131
|
+
setCurrentHeight(interpolatedHeight);
|
|
132
|
+
const hasConvergedToTarget = Math.abs(interpolatedX - targetBounds.x) < 0.5 && Math.abs(interpolatedY - targetBounds.y) < 0.5 && Math.abs(interpolatedWidth - targetBounds.width) < 0.5 && Math.abs(interpolatedHeight - targetBounds.height) < 0.5;
|
|
133
|
+
if (!hasConvergedToTarget) {
|
|
143
134
|
animationFrameId = requestAnimationFrame(animate);
|
|
144
135
|
} else {
|
|
145
136
|
animationFrameId = null;
|
|
137
|
+
isAnimating = false;
|
|
146
138
|
}
|
|
147
139
|
};
|
|
140
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
141
|
+
};
|
|
142
|
+
createEffect(on(() => props.bounds, (newBounds) => {
|
|
143
|
+
targetBounds = newBounds;
|
|
144
|
+
if (!hasBeenRenderedOnce) {
|
|
145
|
+
setCurrentX(targetBounds.x);
|
|
146
|
+
setCurrentY(targetBounds.y);
|
|
147
|
+
setCurrentWidth(targetBounds.width);
|
|
148
|
+
setCurrentHeight(targetBounds.height);
|
|
149
|
+
hasBeenRenderedOnce = true;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
startAnimation();
|
|
153
|
+
}));
|
|
154
|
+
onCleanup(() => {
|
|
148
155
|
if (animationFrameId !== null) {
|
|
149
156
|
cancelAnimationFrame(animationFrameId);
|
|
157
|
+
animationFrameId = null;
|
|
150
158
|
}
|
|
151
|
-
|
|
152
|
-
onCleanup(() => {
|
|
153
|
-
if (animationFrameId !== null) {
|
|
154
|
-
cancelAnimationFrame(animationFrameId);
|
|
155
|
-
animationFrameId = null;
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
createEffect(() => {
|
|
160
|
-
if (props.variant === "grabbed") {
|
|
161
|
-
requestAnimationFrame(() => {
|
|
162
|
-
setOpacity(0);
|
|
163
|
-
});
|
|
164
|
-
}
|
|
159
|
+
isAnimating = false;
|
|
165
160
|
});
|
|
166
161
|
const baseStyle = {
|
|
167
162
|
position: "fixed",
|
|
168
163
|
"box-sizing": "border-box",
|
|
169
|
-
"pointer-events": props.variant === "
|
|
164
|
+
"pointer-events": props.variant === "drag" ? "none" : "auto",
|
|
170
165
|
"z-index": "2147483646"
|
|
171
166
|
};
|
|
172
167
|
const variantStyle = () => {
|
|
173
|
-
if (props.variant === "
|
|
168
|
+
if (props.variant === "drag") {
|
|
174
169
|
return {
|
|
175
170
|
border: "1px dashed rgb(210, 57, 192)",
|
|
176
|
-
"background-color": "rgba(210, 57, 192, 0.
|
|
171
|
+
"background-color": "rgba(210, 57, 192, 0.15)",
|
|
177
172
|
"will-change": "transform, width, height",
|
|
178
|
-
contain: "layout paint size"
|
|
173
|
+
contain: "layout paint size",
|
|
174
|
+
cursor: "crosshair"
|
|
179
175
|
};
|
|
180
176
|
}
|
|
181
177
|
return {
|
|
@@ -205,11 +201,12 @@ var Overlay = (props) => {
|
|
|
205
201
|
}
|
|
206
202
|
});
|
|
207
203
|
};
|
|
204
|
+
var _tmpl$2 = /* @__PURE__ */ 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">`);
|
|
208
205
|
var Spinner = (props) => {
|
|
209
|
-
let
|
|
210
|
-
|
|
211
|
-
if (
|
|
212
|
-
|
|
206
|
+
let spinnerRef;
|
|
207
|
+
onMount(() => {
|
|
208
|
+
if (spinnerRef) {
|
|
209
|
+
spinnerRef.animate([{
|
|
213
210
|
transform: "rotate(0deg)"
|
|
214
211
|
}, {
|
|
215
212
|
transform: "rotate(360deg)"
|
|
@@ -221,126 +218,145 @@ var Spinner = (props) => {
|
|
|
221
218
|
}
|
|
222
219
|
});
|
|
223
220
|
return (() => {
|
|
224
|
-
var _el$
|
|
225
|
-
var _ref$ =
|
|
226
|
-
typeof _ref$ === "function" ? use(_ref$, _el$
|
|
227
|
-
effect((_$p) => style(_el
|
|
221
|
+
var _el$ = _tmpl$2();
|
|
222
|
+
var _ref$ = spinnerRef;
|
|
223
|
+
typeof _ref$ === "function" ? use(_ref$, _el$) : spinnerRef = _el$;
|
|
224
|
+
effect((_$p) => style(_el$, {
|
|
228
225
|
...props.style
|
|
229
226
|
}, _$p));
|
|
230
|
-
return _el
|
|
227
|
+
return _el$;
|
|
231
228
|
})();
|
|
232
229
|
};
|
|
230
|
+
|
|
231
|
+
// src/utils/get-clamped-element-position.ts
|
|
232
|
+
var getClampedElementPosition = (positionLeft, positionTop, elementWidth, elementHeight) => {
|
|
233
|
+
const viewportWidth = window.innerWidth;
|
|
234
|
+
const viewportHeight = window.innerHeight;
|
|
235
|
+
const minLeft = VIEWPORT_MARGIN_PX;
|
|
236
|
+
const minTop = VIEWPORT_MARGIN_PX;
|
|
237
|
+
const maxLeft = viewportWidth - elementWidth - VIEWPORT_MARGIN_PX;
|
|
238
|
+
const maxTop = viewportHeight - elementHeight - VIEWPORT_MARGIN_PX;
|
|
239
|
+
const clampedLeft = Math.max(minLeft, Math.min(positionLeft, maxLeft));
|
|
240
|
+
const clampedTop = Math.max(minTop, Math.min(positionTop, maxTop));
|
|
241
|
+
return { left: clampedLeft, top: clampedTop };
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
// src/components/label.tsx
|
|
245
|
+
var _tmpl$3 = /* @__PURE__ */ template(`<span style=display:inline-block;margin-right:4px;font-weight:600>\u2713`);
|
|
246
|
+
var _tmpl$22 = /* @__PURE__ */ template(`<div style=margin-right:4px>Grabbed`);
|
|
247
|
+
var _tmpl$32 = /* @__PURE__ */ 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 style="font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;font-variant-numeric:tabular-nums">`);
|
|
233
248
|
var Label = (props) => {
|
|
234
249
|
const [opacity, setOpacity] = createSignal(0);
|
|
235
|
-
let
|
|
236
|
-
createEffect(() => {
|
|
237
|
-
if (
|
|
250
|
+
let labelRef;
|
|
251
|
+
createEffect(on(() => props.visible, (visible) => {
|
|
252
|
+
if (visible !== false) {
|
|
238
253
|
requestAnimationFrame(() => {
|
|
239
254
|
setOpacity(1);
|
|
240
255
|
});
|
|
241
256
|
} else {
|
|
242
257
|
setOpacity(0);
|
|
258
|
+
return;
|
|
243
259
|
}
|
|
244
|
-
});
|
|
245
|
-
createEffect(() => {
|
|
246
260
|
if (props.variant === "success") {
|
|
247
261
|
const fadeOutTimer = setTimeout(() => {
|
|
248
262
|
setOpacity(0);
|
|
249
|
-
},
|
|
263
|
+
}, 1500);
|
|
250
264
|
onCleanup(() => clearTimeout(fadeOutTimer));
|
|
251
265
|
}
|
|
252
|
-
});
|
|
253
|
-
const
|
|
266
|
+
}));
|
|
267
|
+
const labelBoundingRect = () => labelRef?.getBoundingClientRect();
|
|
254
268
|
const computedPosition = () => {
|
|
255
|
-
const
|
|
256
|
-
if (!
|
|
269
|
+
const boundingRect = labelBoundingRect();
|
|
270
|
+
if (!boundingRect) return {
|
|
257
271
|
left: props.x,
|
|
258
272
|
top: props.y
|
|
259
273
|
};
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
indicatorTopPx = Math.max(minTop, Math.min(indicatorTopPx, maxTop));
|
|
273
|
-
if (isClamped) {
|
|
274
|
-
indicatorLeftPx += INDICATOR_CLAMP_PADDING_PX;
|
|
275
|
-
indicatorTopPx += INDICATOR_CLAMP_PADDING_PX;
|
|
274
|
+
if (props.variant === "success") {
|
|
275
|
+
const indicatorLeft = Math.round(props.x);
|
|
276
|
+
const indicatorTop = Math.round(props.y) - boundingRect.height - 6;
|
|
277
|
+
const willClampLeft = indicatorLeft < VIEWPORT_MARGIN_PX;
|
|
278
|
+
const willClampTop = indicatorTop < VIEWPORT_MARGIN_PX;
|
|
279
|
+
const isClamped = willClampLeft || willClampTop;
|
|
280
|
+
const clamped = getClampedElementPosition(indicatorLeft, indicatorTop, boundingRect.width, boundingRect.height);
|
|
281
|
+
if (isClamped) {
|
|
282
|
+
clamped.left += INDICATOR_CLAMP_PADDING_PX;
|
|
283
|
+
clamped.top += INDICATOR_CLAMP_PADDING_PX;
|
|
284
|
+
}
|
|
285
|
+
return clamped;
|
|
276
286
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
287
|
+
const CROSSHAIR_OFFSET = 12;
|
|
288
|
+
const viewportWidth = window.innerWidth;
|
|
289
|
+
const viewportHeight = window.innerHeight;
|
|
290
|
+
const quadrants = [{
|
|
291
|
+
left: Math.round(props.x) + CROSSHAIR_OFFSET,
|
|
292
|
+
top: Math.round(props.y) + CROSSHAIR_OFFSET
|
|
293
|
+
}, {
|
|
294
|
+
left: Math.round(props.x) - boundingRect.width - CROSSHAIR_OFFSET,
|
|
295
|
+
top: Math.round(props.y) + CROSSHAIR_OFFSET
|
|
296
|
+
}, {
|
|
297
|
+
left: Math.round(props.x) + CROSSHAIR_OFFSET,
|
|
298
|
+
top: Math.round(props.y) - boundingRect.height - CROSSHAIR_OFFSET
|
|
299
|
+
}, {
|
|
300
|
+
left: Math.round(props.x) - boundingRect.width - CROSSHAIR_OFFSET,
|
|
301
|
+
top: Math.round(props.y) - boundingRect.height - CROSSHAIR_OFFSET
|
|
302
|
+
}];
|
|
303
|
+
for (const position of quadrants) {
|
|
304
|
+
const fitsHorizontally = position.left >= VIEWPORT_MARGIN_PX && position.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
|
|
305
|
+
const fitsVertically = position.top >= VIEWPORT_MARGIN_PX && position.top + boundingRect.height <= viewportHeight - VIEWPORT_MARGIN_PX;
|
|
306
|
+
if (fitsHorizontally && fitsVertically) {
|
|
307
|
+
return position;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const fallback = getClampedElementPosition(quadrants[0].left, quadrants[0].top, boundingRect.width, boundingRect.height);
|
|
311
|
+
fallback.left += INDICATOR_CLAMP_PADDING_PX;
|
|
312
|
+
fallback.top += INDICATOR_CLAMP_PADDING_PX;
|
|
313
|
+
return fallback;
|
|
281
314
|
};
|
|
282
315
|
return createComponent(Show, {
|
|
283
316
|
get when() {
|
|
284
317
|
return props.visible !== false;
|
|
285
318
|
},
|
|
286
319
|
get children() {
|
|
287
|
-
var _el$
|
|
288
|
-
var _ref$
|
|
289
|
-
typeof _ref$
|
|
290
|
-
insert(_el
|
|
320
|
+
var _el$ = _tmpl$32(), _el$4 = _el$.firstChild;
|
|
321
|
+
var _ref$ = labelRef;
|
|
322
|
+
typeof _ref$ === "function" ? use(_ref$, _el$) : labelRef = _el$;
|
|
323
|
+
insert(_el$, createComponent(Show, {
|
|
291
324
|
get when() {
|
|
292
325
|
return props.variant === "processing";
|
|
293
326
|
},
|
|
294
327
|
get children() {
|
|
295
328
|
return createComponent(Spinner, {});
|
|
296
329
|
}
|
|
297
|
-
}), _el$
|
|
298
|
-
insert(_el
|
|
330
|
+
}), _el$4);
|
|
331
|
+
insert(_el$, createComponent(Show, {
|
|
299
332
|
get when() {
|
|
300
333
|
return props.variant === "success";
|
|
301
334
|
},
|
|
302
335
|
get children() {
|
|
303
336
|
return _tmpl$3();
|
|
304
337
|
}
|
|
305
|
-
}), _el$
|
|
306
|
-
insert(_el
|
|
338
|
+
}), _el$4);
|
|
339
|
+
insert(_el$, createComponent(Show, {
|
|
307
340
|
get when() {
|
|
308
341
|
return props.variant === "success";
|
|
309
342
|
},
|
|
310
|
-
children: "Grabbed "
|
|
311
|
-
}), null);
|
|
312
|
-
insert(_el$5, createComponent(Show, {
|
|
313
|
-
get when() {
|
|
314
|
-
return props.variant === "processing";
|
|
315
|
-
},
|
|
316
|
-
children: "Grabbing\u2026"
|
|
317
|
-
}), null);
|
|
318
|
-
insert(_el$5, createComponent(Show, {
|
|
319
|
-
get when() {
|
|
320
|
-
return props.variant === "hover";
|
|
321
|
-
},
|
|
322
343
|
get children() {
|
|
323
|
-
|
|
324
|
-
insert(_el$6, () => props.text);
|
|
325
|
-
return _el$6;
|
|
344
|
+
return _tmpl$22();
|
|
326
345
|
}
|
|
327
|
-
}),
|
|
328
|
-
insert(_el
|
|
346
|
+
}), _el$4);
|
|
347
|
+
insert(_el$, createComponent(Show, {
|
|
329
348
|
get when() {
|
|
330
|
-
return props.variant
|
|
349
|
+
return props.variant === "processing";
|
|
331
350
|
},
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
return _el$7;
|
|
336
|
-
}
|
|
337
|
-
}), null);
|
|
351
|
+
children: "Grabbing\u2026"
|
|
352
|
+
}), _el$4);
|
|
353
|
+
insert(_el$4, () => props.text);
|
|
338
354
|
effect((_p$) => {
|
|
339
355
|
var _v$ = `${computedPosition().top}px`, _v$2 = `${computedPosition().left}px`, _v$3 = props.zIndex?.toString() ?? "2147483647", _v$4 = opacity();
|
|
340
|
-
_v$ !== _p$.e && setStyleProperty(_el
|
|
341
|
-
_v$2 !== _p$.t && setStyleProperty(_el
|
|
342
|
-
_v$3 !== _p$.a && setStyleProperty(_el
|
|
343
|
-
_v$4 !== _p$.o && setStyleProperty(_el
|
|
356
|
+
_v$ !== _p$.e && setStyleProperty(_el$, "top", _p$.e = _v$);
|
|
357
|
+
_v$2 !== _p$.t && setStyleProperty(_el$, "left", _p$.t = _v$2);
|
|
358
|
+
_v$3 !== _p$.a && setStyleProperty(_el$, "z-index", _p$.a = _v$3);
|
|
359
|
+
_v$4 !== _p$.o && setStyleProperty(_el$, "opacity", _p$.o = _v$4);
|
|
344
360
|
return _p$;
|
|
345
361
|
}, {
|
|
346
362
|
e: void 0,
|
|
@@ -348,58 +364,52 @@ var Label = (props) => {
|
|
|
348
364
|
a: void 0,
|
|
349
365
|
o: void 0
|
|
350
366
|
});
|
|
351
|
-
return _el
|
|
367
|
+
return _el$;
|
|
352
368
|
}
|
|
353
369
|
});
|
|
354
370
|
};
|
|
355
|
-
var
|
|
371
|
+
var _tmpl$4 = /* @__PURE__ */ 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)">`);
|
|
372
|
+
var useFadeInOut = (visible) => {
|
|
356
373
|
const [opacity, setOpacity] = createSignal(0);
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
if (props.visible !== false) {
|
|
374
|
+
createEffect(on(() => visible, (isVisible) => {
|
|
375
|
+
if (isVisible !== false) {
|
|
360
376
|
requestAnimationFrame(() => {
|
|
361
377
|
setOpacity(1);
|
|
362
378
|
});
|
|
363
379
|
} else {
|
|
364
380
|
setOpacity(0);
|
|
365
381
|
}
|
|
366
|
-
});
|
|
382
|
+
}));
|
|
383
|
+
return opacity;
|
|
384
|
+
};
|
|
385
|
+
var ProgressIndicator = (props) => {
|
|
386
|
+
const opacity = useFadeInOut(props.visible);
|
|
387
|
+
let progressIndicatorRef;
|
|
367
388
|
const computedPosition = () => {
|
|
368
|
-
const
|
|
369
|
-
if (!
|
|
389
|
+
const boundingRect = progressIndicatorRef?.getBoundingClientRect();
|
|
390
|
+
if (!boundingRect) return {
|
|
370
391
|
left: props.mouseX,
|
|
371
392
|
top: props.mouseY
|
|
372
393
|
};
|
|
373
|
-
const viewportWidth = window.innerWidth;
|
|
374
394
|
const viewportHeight = window.innerHeight;
|
|
375
|
-
const
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
let indicatorTop = props.mouseY + CURSOR_OFFSET;
|
|
379
|
-
if (indicatorTop + rect.height + VIEWPORT_MARGIN > viewportHeight) {
|
|
380
|
-
indicatorTop = props.mouseY - rect.height - CURSOR_OFFSET;
|
|
381
|
-
}
|
|
382
|
-
indicatorTop = Math.max(VIEWPORT_MARGIN, Math.min(indicatorTop, viewportHeight - rect.height - VIEWPORT_MARGIN));
|
|
383
|
-
indicatorLeft = Math.max(VIEWPORT_MARGIN, Math.min(indicatorLeft, viewportWidth - rect.width - VIEWPORT_MARGIN));
|
|
384
|
-
return {
|
|
385
|
-
left: indicatorLeft,
|
|
386
|
-
top: indicatorTop
|
|
387
|
-
};
|
|
395
|
+
const indicatorLeft = props.mouseX - boundingRect.width / 2;
|
|
396
|
+
const indicatorTop = props.mouseY + CURSOR_OFFSET_PX + boundingRect.height + VIEWPORT_MARGIN_PX > viewportHeight ? props.mouseY - boundingRect.height - CURSOR_OFFSET_PX : props.mouseY + CURSOR_OFFSET_PX;
|
|
397
|
+
return getClampedElementPosition(indicatorLeft, indicatorTop, boundingRect.width, boundingRect.height);
|
|
388
398
|
};
|
|
389
399
|
return createComponent(Show, {
|
|
390
400
|
get when() {
|
|
391
401
|
return props.visible !== false;
|
|
392
402
|
},
|
|
393
403
|
get children() {
|
|
394
|
-
var _el$
|
|
395
|
-
var _ref$
|
|
396
|
-
typeof _ref$
|
|
404
|
+
var _el$ = _tmpl$4(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
|
|
405
|
+
var _ref$ = progressIndicatorRef;
|
|
406
|
+
typeof _ref$ === "function" ? use(_ref$, _el$) : progressIndicatorRef = _el$;
|
|
397
407
|
effect((_p$) => {
|
|
398
|
-
var _v$
|
|
399
|
-
_v$
|
|
400
|
-
_v$
|
|
401
|
-
_v$
|
|
402
|
-
_v$
|
|
408
|
+
var _v$ = `${computedPosition().top}px`, _v$2 = `${computedPosition().left}px`, _v$3 = opacity(), _v$4 = `${Math.min(100, Math.max(0, props.progress * 100))}%`;
|
|
409
|
+
_v$ !== _p$.e && setStyleProperty(_el$, "top", _p$.e = _v$);
|
|
410
|
+
_v$2 !== _p$.t && setStyleProperty(_el$, "left", _p$.t = _v$2);
|
|
411
|
+
_v$3 !== _p$.a && setStyleProperty(_el$, "opacity", _p$.a = _v$3);
|
|
412
|
+
_v$4 !== _p$.o && setStyleProperty(_el$3, "width", _p$.o = _v$4);
|
|
403
413
|
return _p$;
|
|
404
414
|
}, {
|
|
405
415
|
e: void 0,
|
|
@@ -407,53 +417,131 @@ var ProgressIndicator = (props) => {
|
|
|
407
417
|
a: void 0,
|
|
408
418
|
o: void 0
|
|
409
419
|
});
|
|
410
|
-
return _el
|
|
420
|
+
return _el$;
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
};
|
|
424
|
+
var _tmpl$5 = /* @__PURE__ */ template(`<div style=position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:2147483645><div style="position:absolute;top:0;width:1px;height:100%;background-color:rgba(210, 57, 192, 0.5);will-change:transform"></div><div style="position:absolute;left:0;width:100%;height:1px;background-color:rgba(210, 57, 192, 0.5);will-change:transform">`);
|
|
425
|
+
var Crosshair = (props) => {
|
|
426
|
+
const [currentX, setCurrentX] = createSignal(props.mouseX);
|
|
427
|
+
const [currentY, setCurrentY] = createSignal(props.mouseY);
|
|
428
|
+
let hasBeenRenderedOnce = false;
|
|
429
|
+
let animationFrameId = null;
|
|
430
|
+
let targetX = props.mouseX;
|
|
431
|
+
let targetY = props.mouseY;
|
|
432
|
+
let isAnimating = false;
|
|
433
|
+
const startAnimation = () => {
|
|
434
|
+
if (isAnimating) return;
|
|
435
|
+
isAnimating = true;
|
|
436
|
+
const animate = () => {
|
|
437
|
+
const interpolatedX = lerp(currentX(), targetX, 0.3);
|
|
438
|
+
const interpolatedY = lerp(currentY(), targetY, 0.3);
|
|
439
|
+
setCurrentX(interpolatedX);
|
|
440
|
+
setCurrentY(interpolatedY);
|
|
441
|
+
const hasConvergedToTarget = Math.abs(interpolatedX - targetX) < 0.5 && Math.abs(interpolatedY - targetY) < 0.5;
|
|
442
|
+
if (!hasConvergedToTarget) {
|
|
443
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
444
|
+
} else {
|
|
445
|
+
animationFrameId = null;
|
|
446
|
+
isAnimating = false;
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
450
|
+
};
|
|
451
|
+
createEffect(on(() => [props.mouseX, props.mouseY], ([newMouseX, newMouseY]) => {
|
|
452
|
+
targetX = newMouseX;
|
|
453
|
+
targetY = newMouseY;
|
|
454
|
+
if (!hasBeenRenderedOnce) {
|
|
455
|
+
setCurrentX(targetX);
|
|
456
|
+
setCurrentY(targetY);
|
|
457
|
+
hasBeenRenderedOnce = true;
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
startAnimation();
|
|
461
|
+
}));
|
|
462
|
+
onCleanup(() => {
|
|
463
|
+
if (animationFrameId !== null) {
|
|
464
|
+
cancelAnimationFrame(animationFrameId);
|
|
465
|
+
animationFrameId = null;
|
|
466
|
+
}
|
|
467
|
+
isAnimating = false;
|
|
468
|
+
});
|
|
469
|
+
return createComponent(Show, {
|
|
470
|
+
get when() {
|
|
471
|
+
return props.visible !== false;
|
|
472
|
+
},
|
|
473
|
+
get children() {
|
|
474
|
+
var _el$ = _tmpl$5(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
|
|
475
|
+
effect((_p$) => {
|
|
476
|
+
var _v$ = `${currentX()}px`, _v$2 = `${currentY()}px`;
|
|
477
|
+
_v$ !== _p$.e && setStyleProperty(_el$2, "left", _p$.e = _v$);
|
|
478
|
+
_v$2 !== _p$.t && setStyleProperty(_el$3, "top", _p$.t = _v$2);
|
|
479
|
+
return _p$;
|
|
480
|
+
}, {
|
|
481
|
+
e: void 0,
|
|
482
|
+
t: void 0
|
|
483
|
+
});
|
|
484
|
+
return _el$;
|
|
411
485
|
}
|
|
412
486
|
});
|
|
413
487
|
};
|
|
414
|
-
|
|
488
|
+
|
|
489
|
+
// src/components/renderer.tsx
|
|
490
|
+
var ReactGrabRenderer = (props) => {
|
|
415
491
|
return [createComponent(Show, {
|
|
416
492
|
get when() {
|
|
417
493
|
return memo(() => !!props.selectionVisible)() && props.selectionBounds;
|
|
418
494
|
},
|
|
419
495
|
get children() {
|
|
420
|
-
return createComponent(
|
|
496
|
+
return createComponent(SelectionBox, {
|
|
421
497
|
variant: "selection",
|
|
422
498
|
get bounds() {
|
|
423
499
|
return props.selectionBounds;
|
|
424
500
|
},
|
|
425
501
|
get visible() {
|
|
426
502
|
return props.selectionVisible;
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
}), createComponent(Show, {
|
|
507
|
+
get when() {
|
|
508
|
+
return memo(() => !!(props.crosshairVisible === true && props.mouseX !== void 0))() && props.mouseY !== void 0;
|
|
509
|
+
},
|
|
510
|
+
get children() {
|
|
511
|
+
return createComponent(Crosshair, {
|
|
512
|
+
get mouseX() {
|
|
513
|
+
return props.mouseX;
|
|
427
514
|
},
|
|
428
|
-
|
|
515
|
+
get mouseY() {
|
|
516
|
+
return props.mouseY;
|
|
517
|
+
},
|
|
518
|
+
visible: true
|
|
429
519
|
});
|
|
430
520
|
}
|
|
431
521
|
}), createComponent(Show, {
|
|
432
522
|
get when() {
|
|
433
|
-
return memo(() => !!props.
|
|
523
|
+
return memo(() => !!props.dragVisible)() && props.dragBounds;
|
|
434
524
|
},
|
|
435
525
|
get children() {
|
|
436
|
-
return createComponent(
|
|
437
|
-
variant: "
|
|
526
|
+
return createComponent(SelectionBox, {
|
|
527
|
+
variant: "drag",
|
|
438
528
|
get bounds() {
|
|
439
|
-
return props.
|
|
529
|
+
return props.dragBounds;
|
|
440
530
|
},
|
|
441
531
|
get visible() {
|
|
442
|
-
return props.
|
|
443
|
-
}
|
|
444
|
-
lerpFactor: MARQUEE_LERP_FACTOR
|
|
532
|
+
return props.dragVisible;
|
|
533
|
+
}
|
|
445
534
|
});
|
|
446
535
|
}
|
|
447
536
|
}), createComponent(For, {
|
|
448
537
|
get each() {
|
|
449
|
-
return props.
|
|
538
|
+
return props.grabbedBoxes ?? [];
|
|
450
539
|
},
|
|
451
|
-
children: (
|
|
540
|
+
children: (box) => createComponent(SelectionBox, {
|
|
452
541
|
variant: "grabbed",
|
|
453
542
|
get bounds() {
|
|
454
|
-
return
|
|
455
|
-
}
|
|
456
|
-
visible: true
|
|
543
|
+
return box.bounds;
|
|
544
|
+
}
|
|
457
545
|
})
|
|
458
546
|
}), createComponent(For, {
|
|
459
547
|
get each() {
|
|
@@ -469,9 +557,7 @@ var ReactGrabOverlay = (props) => {
|
|
|
469
557
|
},
|
|
470
558
|
get y() {
|
|
471
559
|
return label.y;
|
|
472
|
-
}
|
|
473
|
-
visible: true,
|
|
474
|
-
zIndex: 2147483648
|
|
560
|
+
}
|
|
475
561
|
})
|
|
476
562
|
}), createComponent(Show, {
|
|
477
563
|
get when() {
|
|
@@ -526,15 +612,6 @@ instrument({
|
|
|
526
612
|
_fiberRoots.add(fiberRoot);
|
|
527
613
|
}
|
|
528
614
|
});
|
|
529
|
-
var isValidSource = (source) => {
|
|
530
|
-
const fileName = source.fileName;
|
|
531
|
-
if (fileName.includes("node_modules")) return false;
|
|
532
|
-
if (fileName.includes("/dist/")) return false;
|
|
533
|
-
if (fileName.includes("/.next/")) return false;
|
|
534
|
-
if (fileName.includes("/build/")) return false;
|
|
535
|
-
if (fileName.includes("webpack-internal:")) return false;
|
|
536
|
-
return true;
|
|
537
|
-
};
|
|
538
615
|
var getSourceTrace = async (element) => {
|
|
539
616
|
const fiber = getFiberFromHostInstance(element);
|
|
540
617
|
if (!fiber) return null;
|
|
@@ -544,7 +621,7 @@ var getSourceTrace = async (element) => {
|
|
|
544
621
|
Number.MAX_SAFE_INTEGER
|
|
545
622
|
);
|
|
546
623
|
if (!sources) return null;
|
|
547
|
-
return sources
|
|
624
|
+
return sources;
|
|
548
625
|
};
|
|
549
626
|
var getHTMLSnippet = (element) => {
|
|
550
627
|
const semanticTags = /* @__PURE__ */ new Set([
|
|
@@ -819,7 +896,105 @@ var copyContentFallback = (content) => {
|
|
|
819
896
|
}
|
|
820
897
|
};
|
|
821
898
|
|
|
899
|
+
// src/utils/is-element-visible.ts
|
|
900
|
+
var isElementVisible = (element, computedStyle = window.getComputedStyle(element)) => {
|
|
901
|
+
return computedStyle.display !== "none" && computedStyle.visibility !== "hidden" && computedStyle.opacity !== "0";
|
|
902
|
+
};
|
|
903
|
+
|
|
904
|
+
// src/utils/is-valid-grabbable-element.ts
|
|
905
|
+
var isValidGrabbableElement = (element) => {
|
|
906
|
+
if (element.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
907
|
+
return false;
|
|
908
|
+
}
|
|
909
|
+
const computedStyle = window.getComputedStyle(element);
|
|
910
|
+
if (!isElementVisible(element, computedStyle)) {
|
|
911
|
+
return false;
|
|
912
|
+
}
|
|
913
|
+
if (computedStyle.pointerEvents === "none") {
|
|
914
|
+
return false;
|
|
915
|
+
}
|
|
916
|
+
return true;
|
|
917
|
+
};
|
|
918
|
+
|
|
919
|
+
// src/utils/get-element-at-position.ts
|
|
920
|
+
var getElementAtPosition = (clientX, clientY) => {
|
|
921
|
+
const elementsAtPoint = document.elementsFromPoint(clientX, clientY);
|
|
922
|
+
for (const candidateElement of elementsAtPoint) {
|
|
923
|
+
if (isValidGrabbableElement(candidateElement)) {
|
|
924
|
+
return candidateElement;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
return null;
|
|
928
|
+
};
|
|
929
|
+
|
|
930
|
+
// src/utils/get-elements-in-drag.ts
|
|
931
|
+
var DRAG_COVERAGE_THRESHOLD = 0.75;
|
|
932
|
+
var filterElementsInDrag = (dragRect, isValidGrabbableElement2, shouldCheckCoverage) => {
|
|
933
|
+
const elements = [];
|
|
934
|
+
const allElements = Array.from(document.querySelectorAll("*"));
|
|
935
|
+
const dragLeft = dragRect.x;
|
|
936
|
+
const dragTop = dragRect.y;
|
|
937
|
+
const dragRight = dragRect.x + dragRect.width;
|
|
938
|
+
const dragBottom = dragRect.y + dragRect.height;
|
|
939
|
+
for (const candidateElement of allElements) {
|
|
940
|
+
if (!shouldCheckCoverage) {
|
|
941
|
+
const tagName = (candidateElement.tagName || "").toUpperCase();
|
|
942
|
+
if (tagName === "HTML" || tagName === "BODY") continue;
|
|
943
|
+
}
|
|
944
|
+
if (!isValidGrabbableElement2(candidateElement)) {
|
|
945
|
+
continue;
|
|
946
|
+
}
|
|
947
|
+
const elementRect = candidateElement.getBoundingClientRect();
|
|
948
|
+
const elementLeft = elementRect.left;
|
|
949
|
+
const elementTop = elementRect.top;
|
|
950
|
+
const elementRight = elementRect.left + elementRect.width;
|
|
951
|
+
const elementBottom = elementRect.top + elementRect.height;
|
|
952
|
+
if (shouldCheckCoverage) {
|
|
953
|
+
const intersectionLeft = Math.max(dragLeft, elementLeft);
|
|
954
|
+
const intersectionTop = Math.max(dragTop, elementTop);
|
|
955
|
+
const intersectionRight = Math.min(dragRight, elementRight);
|
|
956
|
+
const intersectionBottom = Math.min(dragBottom, elementBottom);
|
|
957
|
+
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
958
|
+
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
959
|
+
const intersectionArea = intersectionWidth * intersectionHeight;
|
|
960
|
+
const elementArea = Math.max(0, elementRect.width * elementRect.height);
|
|
961
|
+
const hasMajorityCoverage = elementArea > 0 && intersectionArea / elementArea >= DRAG_COVERAGE_THRESHOLD;
|
|
962
|
+
if (hasMajorityCoverage) {
|
|
963
|
+
elements.push(candidateElement);
|
|
964
|
+
}
|
|
965
|
+
} else {
|
|
966
|
+
const hasIntersection = elementLeft < dragRight && elementRight > dragLeft && elementTop < dragBottom && elementBottom > dragTop;
|
|
967
|
+
if (hasIntersection) {
|
|
968
|
+
elements.push(candidateElement);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
return elements;
|
|
973
|
+
};
|
|
974
|
+
var getElementsInDrag = (dragRect, isValidGrabbableElement2) => {
|
|
975
|
+
return filterElementsInDrag(dragRect, isValidGrabbableElement2, true);
|
|
976
|
+
};
|
|
977
|
+
var getElementsInDragLoose = (dragRect, isValidGrabbableElement2) => {
|
|
978
|
+
return filterElementsInDrag(dragRect, isValidGrabbableElement2, false);
|
|
979
|
+
};
|
|
980
|
+
|
|
981
|
+
// src/utils/create-element-bounds.ts
|
|
982
|
+
var createElementBounds = (element) => {
|
|
983
|
+
const boundingRect = element.getBoundingClientRect();
|
|
984
|
+
const computedStyle = window.getComputedStyle(element);
|
|
985
|
+
return {
|
|
986
|
+
borderRadius: computedStyle.borderRadius || "0px",
|
|
987
|
+
height: boundingRect.height,
|
|
988
|
+
transform: computedStyle.transform || "none",
|
|
989
|
+
width: boundingRect.width,
|
|
990
|
+
x: boundingRect.left,
|
|
991
|
+
y: boundingRect.top
|
|
992
|
+
};
|
|
993
|
+
};
|
|
994
|
+
|
|
822
995
|
// src/core.tsx
|
|
996
|
+
var SUCCESS_LABEL_DURATION_MS = 1700;
|
|
997
|
+
var PROGRESS_INDICATOR_DELAY_MS = 150;
|
|
823
998
|
var init = (rawOptions) => {
|
|
824
999
|
const options = {
|
|
825
1000
|
enabled: true,
|
|
@@ -830,215 +1005,111 @@ var init = (rawOptions) => {
|
|
|
830
1005
|
return;
|
|
831
1006
|
}
|
|
832
1007
|
return createRoot((dispose) => {
|
|
1008
|
+
const OFFSCREEN_POSITION = -1e3;
|
|
833
1009
|
const [isHoldingKeys, setIsHoldingKeys] = createSignal(false);
|
|
834
|
-
const [mouseX, setMouseX] = createSignal(
|
|
835
|
-
const [mouseY, setMouseY] = createSignal(
|
|
1010
|
+
const [mouseX, setMouseX] = createSignal(OFFSCREEN_POSITION);
|
|
1011
|
+
const [mouseY, setMouseY] = createSignal(OFFSCREEN_POSITION);
|
|
836
1012
|
const [isDragging, setIsDragging] = createSignal(false);
|
|
837
|
-
const [dragStartX, setDragStartX] = createSignal(
|
|
838
|
-
const [dragStartY, setDragStartY] = createSignal(
|
|
1013
|
+
const [dragStartX, setDragStartX] = createSignal(OFFSCREEN_POSITION);
|
|
1014
|
+
const [dragStartY, setDragStartY] = createSignal(OFFSCREEN_POSITION);
|
|
839
1015
|
const [isCopying, setIsCopying] = createSignal(false);
|
|
840
1016
|
const [lastGrabbedElement, setLastGrabbedElement] = createSignal(null);
|
|
841
1017
|
const [progressStartTime, setProgressStartTime] = createSignal(null);
|
|
842
1018
|
const [progressTick, setProgressTick] = createSignal(0);
|
|
843
|
-
const [
|
|
1019
|
+
const [grabbedBoxes, setGrabbedBoxes] = createSignal([]);
|
|
844
1020
|
const [successLabels, setSuccessLabels] = createSignal([]);
|
|
845
1021
|
const [isActivated, setIsActivated] = createSignal(false);
|
|
846
1022
|
const [showProgressIndicator, setShowProgressIndicator] = createSignal(false);
|
|
1023
|
+
const [grabMouseX, setGrabMouseX] = createSignal(null);
|
|
1024
|
+
const [grabMouseY, setGrabMouseY] = createSignal(null);
|
|
847
1025
|
let holdTimerId = null;
|
|
848
1026
|
let progressAnimationId = null;
|
|
849
1027
|
let progressDelayTimerId = null;
|
|
850
|
-
const
|
|
1028
|
+
const isRendererActive = createMemo(() => isActivated() && !isCopying());
|
|
1029
|
+
const hasValidMousePosition = createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
|
|
851
1030
|
const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "c";
|
|
852
|
-
const
|
|
853
|
-
const
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
continue;
|
|
857
|
-
}
|
|
858
|
-
const computedStyle = window.getComputedStyle(candidateElement);
|
|
859
|
-
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
860
|
-
continue;
|
|
861
|
-
}
|
|
862
|
-
if (computedStyle.pointerEvents === "none") {
|
|
863
|
-
continue;
|
|
864
|
-
}
|
|
865
|
-
return candidateElement;
|
|
866
|
-
}
|
|
867
|
-
return null;
|
|
868
|
-
};
|
|
869
|
-
const getElementsInMarquee = (marqueeRect) => {
|
|
870
|
-
const elements = [];
|
|
871
|
-
const allElements = Array.from(document.querySelectorAll("*"));
|
|
872
|
-
const marqueeLeft = marqueeRect.x;
|
|
873
|
-
const marqueeTop = marqueeRect.y;
|
|
874
|
-
const marqueeRight = marqueeRect.x + marqueeRect.width;
|
|
875
|
-
const marqueeBottom = marqueeRect.y + marqueeRect.height;
|
|
876
|
-
for (const candidateElement of allElements) {
|
|
877
|
-
if (candidateElement.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
878
|
-
continue;
|
|
879
|
-
}
|
|
880
|
-
const computedStyle = window.getComputedStyle(candidateElement);
|
|
881
|
-
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
882
|
-
continue;
|
|
883
|
-
}
|
|
884
|
-
if (computedStyle.pointerEvents === "none") {
|
|
885
|
-
continue;
|
|
886
|
-
}
|
|
887
|
-
const rect = candidateElement.getBoundingClientRect();
|
|
888
|
-
const elementLeft = rect.left;
|
|
889
|
-
const elementTop = rect.top;
|
|
890
|
-
const elementRight = rect.left + rect.width;
|
|
891
|
-
const elementBottom = rect.top + rect.height;
|
|
892
|
-
const intersectionLeft = Math.max(marqueeLeft, elementLeft);
|
|
893
|
-
const intersectionTop = Math.max(marqueeTop, elementTop);
|
|
894
|
-
const intersectionRight = Math.min(marqueeRight, elementRight);
|
|
895
|
-
const intersectionBottom = Math.min(marqueeBottom, elementBottom);
|
|
896
|
-
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
897
|
-
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
898
|
-
const intersectionArea = intersectionWidth * intersectionHeight;
|
|
899
|
-
const elementArea = Math.max(0, rect.width * rect.height);
|
|
900
|
-
const COVERAGE_THRESHOLD = 0.75;
|
|
901
|
-
const hasMajorityCoverage = elementArea > 0 && intersectionArea / elementArea >= COVERAGE_THRESHOLD;
|
|
902
|
-
if (hasMajorityCoverage) {
|
|
903
|
-
elements.push(candidateElement);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
return elements;
|
|
907
|
-
};
|
|
908
|
-
const getElementsInMarqueeLoose = (marqueeRect) => {
|
|
909
|
-
const elements = [];
|
|
910
|
-
const allElements = Array.from(document.querySelectorAll("*"));
|
|
911
|
-
const marqueeLeft = marqueeRect.x;
|
|
912
|
-
const marqueeTop = marqueeRect.y;
|
|
913
|
-
const marqueeRight = marqueeRect.x + marqueeRect.width;
|
|
914
|
-
const marqueeBottom = marqueeRect.y + marqueeRect.height;
|
|
915
|
-
for (const candidateElement of allElements) {
|
|
916
|
-
if (candidateElement.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
917
|
-
continue;
|
|
918
|
-
}
|
|
919
|
-
const tag = (candidateElement.tagName || "").toUpperCase();
|
|
920
|
-
if (tag === "HTML" || tag === "BODY") continue;
|
|
921
|
-
const computedStyle = window.getComputedStyle(candidateElement);
|
|
922
|
-
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
923
|
-
continue;
|
|
924
|
-
}
|
|
925
|
-
if (computedStyle.pointerEvents === "none") {
|
|
926
|
-
continue;
|
|
927
|
-
}
|
|
928
|
-
const rect = candidateElement.getBoundingClientRect();
|
|
929
|
-
const elementLeft = rect.left;
|
|
930
|
-
const elementTop = rect.top;
|
|
931
|
-
const elementRight = rect.left + rect.width;
|
|
932
|
-
const elementBottom = rect.top + rect.height;
|
|
933
|
-
const intersects = elementLeft < marqueeRight && elementRight > marqueeLeft && elementTop < marqueeBottom && elementBottom > marqueeTop;
|
|
934
|
-
if (intersects) {
|
|
935
|
-
elements.push(candidateElement);
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
return elements;
|
|
939
|
-
};
|
|
940
|
-
const wrapInReferencedElement = (content) => `
|
|
941
|
-
|
|
942
|
-
<referenced_element>
|
|
943
|
-
${content}
|
|
944
|
-
</referenced_element>`;
|
|
945
|
-
const wrapInReferencedElements = (content) => `
|
|
946
|
-
|
|
947
|
-
<referenced_elements>
|
|
948
|
-
${content}
|
|
949
|
-
</referenced_elements>`;
|
|
950
|
-
const addGrabbedOverlay = (bounds) => {
|
|
951
|
-
const id = `grabbed-${Date.now()}-${Math.random()}`;
|
|
952
|
-
setGrabbedOverlays((prev) => [...prev, {
|
|
953
|
-
id,
|
|
1031
|
+
const addGrabbedBox = (bounds) => {
|
|
1032
|
+
const boxId = `grabbed-${Date.now()}-${Math.random()}`;
|
|
1033
|
+
const newBox = {
|
|
1034
|
+
id: boxId,
|
|
954
1035
|
bounds
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
}, 300);
|
|
1036
|
+
};
|
|
1037
|
+
const currentBoxes = grabbedBoxes();
|
|
1038
|
+
setGrabbedBoxes([...currentBoxes, newBox]);
|
|
959
1039
|
};
|
|
960
|
-
const addSuccessLabel = (text,
|
|
961
|
-
const
|
|
962
|
-
setSuccessLabels((
|
|
963
|
-
id,
|
|
1040
|
+
const addSuccessLabel = (text, positionX, positionY) => {
|
|
1041
|
+
const labelId = `success-${Date.now()}-${Math.random()}`;
|
|
1042
|
+
setSuccessLabels((previousLabels) => [...previousLabels, {
|
|
1043
|
+
id: labelId,
|
|
964
1044
|
text,
|
|
965
|
-
x,
|
|
966
|
-
y
|
|
1045
|
+
x: positionX,
|
|
1046
|
+
y: positionY
|
|
967
1047
|
}]);
|
|
968
1048
|
setTimeout(() => {
|
|
969
|
-
setSuccessLabels((
|
|
970
|
-
},
|
|
1049
|
+
setSuccessLabels((previousLabels) => previousLabels.filter((label) => label.id !== labelId));
|
|
1050
|
+
}, SUCCESS_LABEL_DURATION_MS);
|
|
1051
|
+
};
|
|
1052
|
+
const formatStackTrace = (stackTrace) => {
|
|
1053
|
+
return stackTrace.map((source) => {
|
|
1054
|
+
const functionName = source.functionName ?? "anonymous";
|
|
1055
|
+
const fileName = source.fileName ?? "unknown";
|
|
1056
|
+
const lineNumber = source.lineNumber ?? 0;
|
|
1057
|
+
const columnNumber = source.columnNumber ?? 0;
|
|
1058
|
+
return ` ${functionName} - ${fileName}:${lineNumber}:${columnNumber}`;
|
|
1059
|
+
}).join("\n");
|
|
1060
|
+
};
|
|
1061
|
+
const getElementContentWithTrace = async (element) => {
|
|
1062
|
+
const elementHtml = getHTMLSnippet(element);
|
|
1063
|
+
const componentStackTrace = await getSourceTrace(element);
|
|
1064
|
+
if (componentStackTrace?.length) {
|
|
1065
|
+
const formattedStackTrace = formatStackTrace(componentStackTrace);
|
|
1066
|
+
return `${elementHtml}
|
|
1067
|
+
|
|
1068
|
+
Component owner stack:
|
|
1069
|
+
${formattedStackTrace}`;
|
|
1070
|
+
}
|
|
1071
|
+
return elementHtml;
|
|
971
1072
|
};
|
|
1073
|
+
const getElementTagName = (element) => (element.tagName || "").toLowerCase();
|
|
972
1074
|
const handleCopy = async (targetElement2) => {
|
|
973
1075
|
const elementBounds = targetElement2.getBoundingClientRect();
|
|
974
|
-
const tagName = (targetElement2
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
transform: window.getComputedStyle(targetElement2).transform || "none",
|
|
979
|
-
width: elementBounds.width,
|
|
980
|
-
x: elementBounds.left,
|
|
981
|
-
y: elementBounds.top
|
|
982
|
-
});
|
|
1076
|
+
const tagName = getElementTagName(targetElement2);
|
|
1077
|
+
setGrabMouseX(mouseX());
|
|
1078
|
+
setGrabMouseY(mouseY());
|
|
1079
|
+
addGrabbedBox(createElementBounds(targetElement2));
|
|
983
1080
|
try {
|
|
984
|
-
const
|
|
985
|
-
await copyContent(
|
|
986
|
-
const componentStackTrace = await getSourceTrace(targetElement2);
|
|
987
|
-
if (componentStackTrace?.length) {
|
|
988
|
-
const formattedStackTrace = componentStackTrace.map((source) => ` ${source.functionName} - ${source.fileName}:${source.lineNumber}:${source.columnNumber}`).join("\n");
|
|
989
|
-
await copyContent(wrapInReferencedElement(`${elementHtml}
|
|
990
|
-
|
|
991
|
-
Component owner stack:
|
|
992
|
-
${formattedStackTrace}`));
|
|
993
|
-
}
|
|
1081
|
+
const content = await getElementContentWithTrace(targetElement2);
|
|
1082
|
+
await copyContent(content);
|
|
994
1083
|
} catch {
|
|
995
1084
|
}
|
|
996
1085
|
addSuccessLabel(tagName ? `<${tagName}>` : "<element>", elementBounds.left, elementBounds.top);
|
|
997
1086
|
};
|
|
998
1087
|
const handleMultipleCopy = async (targetElements) => {
|
|
999
1088
|
if (targetElements.length === 0) return;
|
|
1000
|
-
let
|
|
1001
|
-
let
|
|
1089
|
+
let minPositionX = Infinity;
|
|
1090
|
+
let minPositionY = Infinity;
|
|
1091
|
+
setGrabMouseX(mouseX());
|
|
1092
|
+
setGrabMouseY(mouseY());
|
|
1002
1093
|
for (const element of targetElements) {
|
|
1003
1094
|
const elementBounds = element.getBoundingClientRect();
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
borderRadius: window.getComputedStyle(element).borderRadius || "0px",
|
|
1008
|
-
height: elementBounds.height,
|
|
1009
|
-
transform: window.getComputedStyle(element).transform || "none",
|
|
1010
|
-
width: elementBounds.width,
|
|
1011
|
-
x: elementBounds.left,
|
|
1012
|
-
y: elementBounds.top
|
|
1013
|
-
});
|
|
1095
|
+
minPositionX = Math.min(minPositionX, elementBounds.left);
|
|
1096
|
+
minPositionY = Math.min(minPositionY, elementBounds.top);
|
|
1097
|
+
addGrabbedBox(createElementBounds(element));
|
|
1014
1098
|
}
|
|
1015
1099
|
try {
|
|
1016
|
-
const elementSnippets =
|
|
1017
|
-
for (const element of targetElements) {
|
|
1018
|
-
const elementHtml = getHTMLSnippet(element);
|
|
1019
|
-
const componentStackTrace = await getSourceTrace(element);
|
|
1020
|
-
if (componentStackTrace?.length) {
|
|
1021
|
-
const formattedStackTrace = componentStackTrace.map((source) => ` ${source.functionName} - ${source.fileName}:${source.lineNumber}:${source.columnNumber}`).join("\n");
|
|
1022
|
-
elementSnippets.push(`${elementHtml}
|
|
1023
|
-
|
|
1024
|
-
Component owner stack:
|
|
1025
|
-
${formattedStackTrace}`);
|
|
1026
|
-
} else {
|
|
1027
|
-
elementSnippets.push(elementHtml);
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1100
|
+
const elementSnippets = await Promise.all(targetElements.map((element) => getElementContentWithTrace(element)));
|
|
1030
1101
|
const combinedContent = elementSnippets.join("\n\n---\n\n");
|
|
1031
|
-
await copyContent(
|
|
1102
|
+
await copyContent(combinedContent);
|
|
1032
1103
|
} catch {
|
|
1033
1104
|
}
|
|
1034
|
-
addSuccessLabel(`${targetElements.length} elements`,
|
|
1105
|
+
addSuccessLabel(`${targetElements.length} elements`, minPositionX, minPositionY);
|
|
1035
1106
|
};
|
|
1036
1107
|
const targetElement = createMemo(() => {
|
|
1037
|
-
if (!
|
|
1108
|
+
if (!isRendererActive() || isDragging()) return null;
|
|
1038
1109
|
return getElementAtPosition(mouseX(), mouseY());
|
|
1039
1110
|
});
|
|
1040
1111
|
const selectionBounds = createMemo(() => {
|
|
1041
|
-
const element = targetElement()
|
|
1112
|
+
const element = targetElement();
|
|
1042
1113
|
if (!element) return void 0;
|
|
1043
1114
|
const elementBounds = element.getBoundingClientRect();
|
|
1044
1115
|
const computedStyle = window.getComputedStyle(element);
|
|
@@ -1051,54 +1122,80 @@ ${formattedStackTrace}`);
|
|
|
1051
1122
|
y: elementBounds.top
|
|
1052
1123
|
};
|
|
1053
1124
|
});
|
|
1054
|
-
const
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1125
|
+
const DRAG_THRESHOLD_PX = 5;
|
|
1126
|
+
const getDragDistance = (endX, endY) => ({
|
|
1127
|
+
x: Math.abs(endX - dragStartX()),
|
|
1128
|
+
y: Math.abs(endY - dragStartY())
|
|
1129
|
+
});
|
|
1130
|
+
const isDraggingBeyondThreshold = createMemo(() => {
|
|
1131
|
+
if (!isDragging()) return false;
|
|
1132
|
+
const dragDistance = getDragDistance(mouseX(), mouseY());
|
|
1133
|
+
return dragDistance.x > DRAG_THRESHOLD_PX || dragDistance.y > DRAG_THRESHOLD_PX;
|
|
1134
|
+
});
|
|
1135
|
+
const getDragRect = (endX, endY) => {
|
|
1136
|
+
const dragX = Math.min(dragStartX(), endX);
|
|
1137
|
+
const dragY = Math.min(dragStartY(), endY);
|
|
1138
|
+
const dragWidth = Math.abs(endX - dragStartX());
|
|
1139
|
+
const dragHeight = Math.abs(endY - dragStartY());
|
|
1140
|
+
return {
|
|
1141
|
+
x: dragX,
|
|
1142
|
+
y: dragY,
|
|
1143
|
+
width: dragWidth,
|
|
1144
|
+
height: dragHeight
|
|
1145
|
+
};
|
|
1146
|
+
};
|
|
1147
|
+
const dragBounds = createMemo(() => {
|
|
1148
|
+
if (!isDraggingBeyondThreshold()) return void 0;
|
|
1149
|
+
const drag = getDragRect(mouseX(), mouseY());
|
|
1060
1150
|
return {
|
|
1061
1151
|
borderRadius: "0px",
|
|
1062
|
-
height:
|
|
1152
|
+
height: drag.height,
|
|
1063
1153
|
transform: "none",
|
|
1064
|
-
width:
|
|
1065
|
-
x:
|
|
1066
|
-
y:
|
|
1154
|
+
width: drag.width,
|
|
1155
|
+
x: drag.x,
|
|
1156
|
+
y: drag.y
|
|
1067
1157
|
};
|
|
1068
1158
|
});
|
|
1069
1159
|
const labelText = createMemo(() => {
|
|
1070
1160
|
const element = targetElement();
|
|
1071
1161
|
if (!element) return "";
|
|
1072
|
-
const tagName = (element
|
|
1162
|
+
const tagName = getElementTagName(element);
|
|
1073
1163
|
return tagName ? `<${tagName}>` : "<element>";
|
|
1074
1164
|
});
|
|
1075
1165
|
const labelPosition = createMemo(() => {
|
|
1076
|
-
const element = targetElement() ?? lastGrabbedElement();
|
|
1077
|
-
if (element) {
|
|
1078
|
-
const rect = element.getBoundingClientRect();
|
|
1079
|
-
return {
|
|
1080
|
-
x: rect.left,
|
|
1081
|
-
y: rect.top
|
|
1082
|
-
};
|
|
1083
|
-
}
|
|
1084
1166
|
return {
|
|
1085
1167
|
x: mouseX(),
|
|
1086
1168
|
y: mouseY()
|
|
1087
1169
|
};
|
|
1088
1170
|
});
|
|
1089
|
-
|
|
1090
|
-
const
|
|
1091
|
-
const
|
|
1092
|
-
|
|
1171
|
+
const isSameAsLast = createMemo(() => {
|
|
1172
|
+
const currentElement = targetElement();
|
|
1173
|
+
const lastElement = lastGrabbedElement();
|
|
1174
|
+
return !!currentElement && currentElement === lastElement;
|
|
1175
|
+
});
|
|
1176
|
+
createEffect(on(() => [targetElement(), lastGrabbedElement()], ([currentElement, lastElement]) => {
|
|
1177
|
+
if (lastElement && currentElement && lastElement !== currentElement) {
|
|
1093
1178
|
setLastGrabbedElement(null);
|
|
1094
1179
|
}
|
|
1095
|
-
});
|
|
1180
|
+
}));
|
|
1181
|
+
createEffect(on(() => [mouseX(), mouseY(), grabMouseX(), grabMouseY()], ([currentMouseX, currentMouseY, initialGrabMouseX, initialGrabMouseY]) => {
|
|
1182
|
+
if (initialGrabMouseX === null || initialGrabMouseY === null) return;
|
|
1183
|
+
if (grabbedBoxes().length === 0) return;
|
|
1184
|
+
const MOUSE_MOVE_THRESHOLD_PX = 5;
|
|
1185
|
+
const distanceX = Math.abs(currentMouseX - initialGrabMouseX);
|
|
1186
|
+
const distanceY = Math.abs(currentMouseY - initialGrabMouseY);
|
|
1187
|
+
if (distanceX > MOUSE_MOVE_THRESHOLD_PX || distanceY > MOUSE_MOVE_THRESHOLD_PX) {
|
|
1188
|
+
setGrabbedBoxes([]);
|
|
1189
|
+
setGrabMouseX(null);
|
|
1190
|
+
setGrabMouseY(null);
|
|
1191
|
+
}
|
|
1192
|
+
}));
|
|
1096
1193
|
const progress = createMemo(() => {
|
|
1097
1194
|
const startTime = progressStartTime();
|
|
1098
1195
|
progressTick();
|
|
1099
1196
|
if (startTime === null) return 0;
|
|
1100
|
-
const
|
|
1101
|
-
return Math.min(
|
|
1197
|
+
const elapsedTime = Date.now() - startTime;
|
|
1198
|
+
return Math.min(elapsedTime / options.keyHoldDuration, 1);
|
|
1102
1199
|
});
|
|
1103
1200
|
const startProgressAnimation = () => {
|
|
1104
1201
|
setProgressStartTime(Date.now());
|
|
@@ -1106,10 +1203,10 @@ ${formattedStackTrace}`);
|
|
|
1106
1203
|
progressDelayTimerId = window.setTimeout(() => {
|
|
1107
1204
|
setShowProgressIndicator(true);
|
|
1108
1205
|
progressDelayTimerId = null;
|
|
1109
|
-
},
|
|
1206
|
+
}, PROGRESS_INDICATOR_DELAY_MS);
|
|
1110
1207
|
const animateProgress = () => {
|
|
1111
1208
|
if (progressStartTime() === null) return;
|
|
1112
|
-
setProgressTick((
|
|
1209
|
+
setProgressTick((tick) => tick + 1);
|
|
1113
1210
|
const currentProgress = progress();
|
|
1114
1211
|
if (currentProgress < 1) {
|
|
1115
1212
|
progressAnimationId = requestAnimationFrame(animateProgress);
|
|
@@ -1129,16 +1226,22 @@ ${formattedStackTrace}`);
|
|
|
1129
1226
|
setProgressStartTime(null);
|
|
1130
1227
|
setShowProgressIndicator(false);
|
|
1131
1228
|
};
|
|
1132
|
-
const
|
|
1229
|
+
const activateRenderer = () => {
|
|
1133
1230
|
stopProgressAnimation();
|
|
1134
1231
|
setIsActivated(true);
|
|
1232
|
+
document.body.style.cursor = "crosshair";
|
|
1135
1233
|
};
|
|
1136
1234
|
const abortController = new AbortController();
|
|
1137
|
-
const
|
|
1235
|
+
const eventListenerSignal = abortController.signal;
|
|
1138
1236
|
window.addEventListener("keydown", (event) => {
|
|
1139
1237
|
if (event.key === "Escape" && isHoldingKeys()) {
|
|
1140
1238
|
setIsHoldingKeys(false);
|
|
1141
1239
|
setIsActivated(false);
|
|
1240
|
+
document.body.style.cursor = "";
|
|
1241
|
+
if (isDragging()) {
|
|
1242
|
+
setIsDragging(false);
|
|
1243
|
+
document.body.style.userSelect = "";
|
|
1244
|
+
}
|
|
1142
1245
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1143
1246
|
stopProgressAnimation();
|
|
1144
1247
|
return;
|
|
@@ -1148,67 +1251,56 @@ ${formattedStackTrace}`);
|
|
|
1148
1251
|
setIsHoldingKeys(true);
|
|
1149
1252
|
startProgressAnimation();
|
|
1150
1253
|
holdTimerId = window.setTimeout(() => {
|
|
1151
|
-
|
|
1254
|
+
activateRenderer();
|
|
1152
1255
|
options.onActivate?.();
|
|
1153
1256
|
}, options.keyHoldDuration);
|
|
1154
1257
|
}
|
|
1155
1258
|
}, {
|
|
1156
|
-
signal
|
|
1259
|
+
signal: eventListenerSignal
|
|
1157
1260
|
});
|
|
1158
1261
|
window.addEventListener("keyup", (event) => {
|
|
1159
1262
|
if (isHoldingKeys() && (!isTargetKeyCombination(event) || event.key.toLowerCase() === "c")) {
|
|
1160
1263
|
setIsHoldingKeys(false);
|
|
1161
1264
|
setIsActivated(false);
|
|
1265
|
+
document.body.style.cursor = "";
|
|
1162
1266
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1163
1267
|
stopProgressAnimation();
|
|
1164
1268
|
}
|
|
1165
1269
|
}, {
|
|
1166
|
-
signal
|
|
1270
|
+
signal: eventListenerSignal
|
|
1167
1271
|
});
|
|
1168
1272
|
window.addEventListener("mousemove", (event) => {
|
|
1169
1273
|
setMouseX(event.clientX);
|
|
1170
1274
|
setMouseY(event.clientY);
|
|
1171
1275
|
}, {
|
|
1172
|
-
signal
|
|
1276
|
+
signal: eventListenerSignal
|
|
1173
1277
|
});
|
|
1174
1278
|
window.addEventListener("mousedown", (event) => {
|
|
1175
|
-
if (!
|
|
1279
|
+
if (!isRendererActive() || isCopying()) return;
|
|
1280
|
+
event.preventDefault();
|
|
1176
1281
|
setIsDragging(true);
|
|
1177
1282
|
setDragStartX(event.clientX);
|
|
1178
1283
|
setDragStartY(event.clientY);
|
|
1284
|
+
document.body.style.userSelect = "none";
|
|
1179
1285
|
}, {
|
|
1180
|
-
signal
|
|
1286
|
+
signal: eventListenerSignal
|
|
1181
1287
|
});
|
|
1182
1288
|
window.addEventListener("mouseup", (event) => {
|
|
1183
1289
|
if (!isDragging()) return;
|
|
1184
|
-
const
|
|
1185
|
-
const
|
|
1186
|
-
const DRAG_THRESHOLD = 5;
|
|
1187
|
-
const wasDrag = dragDistanceX > DRAG_THRESHOLD || dragDistanceY > DRAG_THRESHOLD;
|
|
1290
|
+
const dragDistance = getDragDistance(event.clientX, event.clientY);
|
|
1291
|
+
const wasDragGesture = dragDistance.x > DRAG_THRESHOLD_PX || dragDistance.y > DRAG_THRESHOLD_PX;
|
|
1188
1292
|
setIsDragging(false);
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
const
|
|
1192
|
-
const
|
|
1193
|
-
const marqueeHeight = Math.abs(event.clientY - dragStartY());
|
|
1194
|
-
const elements = getElementsInMarquee({
|
|
1195
|
-
x: marqueeX,
|
|
1196
|
-
y: marqueeY,
|
|
1197
|
-
width: marqueeWidth,
|
|
1198
|
-
height: marqueeHeight
|
|
1199
|
-
});
|
|
1293
|
+
document.body.style.userSelect = "";
|
|
1294
|
+
if (wasDragGesture) {
|
|
1295
|
+
const dragRect = getDragRect(event.clientX, event.clientY);
|
|
1296
|
+
const elements = getElementsInDrag(dragRect, isValidGrabbableElement);
|
|
1200
1297
|
if (elements.length > 0) {
|
|
1201
1298
|
setIsCopying(true);
|
|
1202
1299
|
void handleMultipleCopy(elements).finally(() => {
|
|
1203
1300
|
setIsCopying(false);
|
|
1204
1301
|
});
|
|
1205
1302
|
} else {
|
|
1206
|
-
const fallbackElements =
|
|
1207
|
-
x: marqueeX,
|
|
1208
|
-
y: marqueeY,
|
|
1209
|
-
width: marqueeWidth,
|
|
1210
|
-
height: marqueeHeight
|
|
1211
|
-
});
|
|
1303
|
+
const fallbackElements = getElementsInDragLoose(dragRect, isValidGrabbableElement);
|
|
1212
1304
|
if (fallbackElements.length > 0) {
|
|
1213
1305
|
setIsCopying(true);
|
|
1214
1306
|
void handleMultipleCopy(fallbackElements).finally(() => {
|
|
@@ -1226,51 +1318,84 @@ ${formattedStackTrace}`);
|
|
|
1226
1318
|
});
|
|
1227
1319
|
}
|
|
1228
1320
|
}, {
|
|
1229
|
-
signal
|
|
1230
|
-
});
|
|
1231
|
-
window.addEventListener("scroll", () => {
|
|
1232
|
-
}, {
|
|
1233
|
-
signal,
|
|
1234
|
-
capture: true
|
|
1235
|
-
});
|
|
1236
|
-
window.addEventListener("resize", () => {
|
|
1237
|
-
}, {
|
|
1238
|
-
signal
|
|
1321
|
+
signal: eventListenerSignal
|
|
1239
1322
|
});
|
|
1240
1323
|
document.addEventListener("visibilitychange", () => {
|
|
1241
1324
|
if (document.hidden) {
|
|
1242
|
-
|
|
1325
|
+
setGrabbedBoxes([]);
|
|
1243
1326
|
}
|
|
1244
1327
|
}, {
|
|
1245
|
-
signal
|
|
1328
|
+
signal: eventListenerSignal
|
|
1246
1329
|
});
|
|
1247
1330
|
onCleanup(() => {
|
|
1248
1331
|
abortController.abort();
|
|
1249
1332
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1250
1333
|
stopProgressAnimation();
|
|
1334
|
+
document.body.style.userSelect = "";
|
|
1335
|
+
document.body.style.cursor = "";
|
|
1251
1336
|
});
|
|
1252
|
-
const
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1337
|
+
const rendererRoot = mountRoot();
|
|
1338
|
+
const selectionVisible = createMemo(() => false);
|
|
1339
|
+
const dragVisible = createMemo(() => isRendererActive() && isDraggingBeyondThreshold());
|
|
1340
|
+
const labelVariant = createMemo(() => isCopying() ? "processing" : "hover");
|
|
1341
|
+
const labelVisible = createMemo(() => isRendererActive() && !isDragging() && !!targetElement() && !isSameAsLast() || isCopying());
|
|
1342
|
+
const progressVisible = createMemo(() => isHoldingKeys() && showProgressIndicator() && hasValidMousePosition());
|
|
1343
|
+
const crosshairVisible = createMemo(() => isRendererActive() && !isDragging());
|
|
1344
|
+
render(() => createComponent(ReactGrabRenderer, {
|
|
1345
|
+
get selectionVisible() {
|
|
1346
|
+
return selectionVisible();
|
|
1347
|
+
},
|
|
1348
|
+
get selectionBounds() {
|
|
1349
|
+
return selectionBounds();
|
|
1350
|
+
},
|
|
1351
|
+
get dragVisible() {
|
|
1352
|
+
return dragVisible();
|
|
1353
|
+
},
|
|
1354
|
+
get dragBounds() {
|
|
1355
|
+
return dragBounds();
|
|
1356
|
+
},
|
|
1357
|
+
get grabbedBoxes() {
|
|
1358
|
+
return grabbedBoxes();
|
|
1359
|
+
},
|
|
1360
|
+
get successLabels() {
|
|
1361
|
+
return successLabels();
|
|
1362
|
+
},
|
|
1363
|
+
get labelVariant() {
|
|
1364
|
+
return labelVariant();
|
|
1365
|
+
},
|
|
1366
|
+
get labelText() {
|
|
1367
|
+
return labelText();
|
|
1368
|
+
},
|
|
1369
|
+
get labelX() {
|
|
1370
|
+
return labelPosition().x;
|
|
1371
|
+
},
|
|
1372
|
+
get labelY() {
|
|
1373
|
+
return labelPosition().y;
|
|
1374
|
+
},
|
|
1375
|
+
get labelVisible() {
|
|
1376
|
+
return labelVisible();
|
|
1377
|
+
},
|
|
1378
|
+
get progressVisible() {
|
|
1379
|
+
return progressVisible();
|
|
1380
|
+
},
|
|
1381
|
+
get progress() {
|
|
1382
|
+
return progress();
|
|
1383
|
+
},
|
|
1384
|
+
get mouseX() {
|
|
1385
|
+
return mouseX();
|
|
1386
|
+
},
|
|
1387
|
+
get mouseY() {
|
|
1388
|
+
return mouseY();
|
|
1389
|
+
},
|
|
1390
|
+
get crosshairVisible() {
|
|
1391
|
+
return crosshairVisible();
|
|
1392
|
+
}
|
|
1393
|
+
}), rendererRoot);
|
|
1271
1394
|
return dispose;
|
|
1272
1395
|
});
|
|
1273
1396
|
};
|
|
1274
1397
|
|
|
1275
1398
|
// src/index.ts
|
|
1276
1399
|
init();
|
|
1400
|
+
|
|
1401
|
+
export { init };
|