react-grab 0.0.25 → 0.0.27
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 +299 -118
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.global.js +16 -16
- package/dist/index.js +301 -120
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { render, createComponent, memo, template, effect, style,
|
|
1
|
+
import { render, createComponent, memo, template, effect, style, insert, setStyleProperty, use } from 'solid-js/web';
|
|
2
2
|
import { createRoot, createSignal, createMemo, createEffect, on, onCleanup, Show, For, onMount } from 'solid-js';
|
|
3
3
|
import { instrument, _fiberRoots, getFiberFromHostInstance } from 'bippy';
|
|
4
|
-
import { getOwnerStack, getSourcesFromStack } from 'bippy/dist/source';
|
|
4
|
+
import { getOwnerStack, getSourcesFromStack, isSourceFile, normalizeFileName } from 'bippy/dist/source';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @license MIT
|
|
@@ -110,11 +110,12 @@ var SelectionBox = (props) => {
|
|
|
110
110
|
const [opacity, setOpacity] = createSignal(1);
|
|
111
111
|
let hasBeenRenderedOnce = false;
|
|
112
112
|
let animationFrameId = null;
|
|
113
|
+
let fadeTimerId = null;
|
|
113
114
|
let targetBounds = props.bounds;
|
|
114
115
|
let isAnimating = false;
|
|
115
116
|
const lerpFactor = () => {
|
|
116
117
|
if (props.lerpFactor !== void 0) return props.lerpFactor;
|
|
117
|
-
if (props.variant === "drag") return 0.
|
|
118
|
+
if (props.variant === "drag") return 0.7;
|
|
118
119
|
return SELECTION_LERP_FACTOR;
|
|
119
120
|
};
|
|
120
121
|
const startAnimation = () => {
|
|
@@ -151,11 +152,22 @@ var SelectionBox = (props) => {
|
|
|
151
152
|
}
|
|
152
153
|
startAnimation();
|
|
153
154
|
}));
|
|
155
|
+
createEffect(() => {
|
|
156
|
+
if (props.variant === "grabbed" && props.createdAt) {
|
|
157
|
+
fadeTimerId = window.setTimeout(() => {
|
|
158
|
+
setOpacity(0);
|
|
159
|
+
}, 1500);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
154
162
|
onCleanup(() => {
|
|
155
163
|
if (animationFrameId !== null) {
|
|
156
164
|
cancelAnimationFrame(animationFrameId);
|
|
157
165
|
animationFrameId = null;
|
|
158
166
|
}
|
|
167
|
+
if (fadeTimerId !== null) {
|
|
168
|
+
window.clearTimeout(fadeTimerId);
|
|
169
|
+
fadeTimerId = null;
|
|
170
|
+
}
|
|
159
171
|
isAnimating = false;
|
|
160
172
|
});
|
|
161
173
|
const baseStyle = {
|
|
@@ -167,8 +179,8 @@ var SelectionBox = (props) => {
|
|
|
167
179
|
const variantStyle = () => {
|
|
168
180
|
if (props.variant === "drag") {
|
|
169
181
|
return {
|
|
170
|
-
border: "1px dashed
|
|
171
|
-
"background-color": "rgba(210, 57, 192, 0.
|
|
182
|
+
border: "1px dashed rgba(210, 57, 192, 0.4)",
|
|
183
|
+
"background-color": "rgba(210, 57, 192, 0.05)",
|
|
172
184
|
"will-change": "transform, width, height",
|
|
173
185
|
contain: "layout paint size",
|
|
174
186
|
cursor: "crosshair"
|
|
@@ -243,11 +255,47 @@ var getClampedElementPosition = (positionLeft, positionTop, elementWidth, elemen
|
|
|
243
255
|
|
|
244
256
|
// src/components/label.tsx
|
|
245
257
|
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>
|
|
247
|
-
var _tmpl$32 = /* @__PURE__ */ template(`<div style=
|
|
258
|
+
var _tmpl$22 = /* @__PURE__ */ template(`<div style=margin-right:4px>Copied`);
|
|
259
|
+
var _tmpl$32 = /* @__PURE__ */ template(`<div style=margin-left:4px>to clipboard`);
|
|
260
|
+
var _tmpl$4 = /* @__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">`);
|
|
261
|
+
var _tmpl$5 = /* @__PURE__ */ template(`<span style="font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;font-variant-numeric:tabular-nums">`);
|
|
248
262
|
var Label = (props) => {
|
|
249
263
|
const [opacity, setOpacity] = createSignal(0);
|
|
264
|
+
const [positionTick, setPositionTick] = createSignal(0);
|
|
250
265
|
let labelRef;
|
|
266
|
+
let currentX = props.x;
|
|
267
|
+
let currentY = props.y;
|
|
268
|
+
let targetX = props.x;
|
|
269
|
+
let targetY = props.y;
|
|
270
|
+
let animationFrameId = null;
|
|
271
|
+
let hasBeenRenderedOnce = false;
|
|
272
|
+
const animate = () => {
|
|
273
|
+
currentX = lerp(currentX, targetX, 0.3);
|
|
274
|
+
currentY = lerp(currentY, targetY, 0.3);
|
|
275
|
+
setPositionTick((tick) => tick + 1);
|
|
276
|
+
const hasConvergedToTarget = Math.abs(currentX - targetX) < 0.5 && Math.abs(currentY - targetY) < 0.5;
|
|
277
|
+
if (!hasConvergedToTarget) {
|
|
278
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
279
|
+
} else {
|
|
280
|
+
animationFrameId = null;
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
const startAnimation = () => {
|
|
284
|
+
if (animationFrameId !== null) return;
|
|
285
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
286
|
+
};
|
|
287
|
+
const updateTarget = () => {
|
|
288
|
+
targetX = props.x;
|
|
289
|
+
targetY = props.y;
|
|
290
|
+
if (!hasBeenRenderedOnce) {
|
|
291
|
+
currentX = targetX;
|
|
292
|
+
currentY = targetY;
|
|
293
|
+
hasBeenRenderedOnce = true;
|
|
294
|
+
setPositionTick((tick) => tick + 1);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
startAnimation();
|
|
298
|
+
};
|
|
251
299
|
createEffect(on(() => props.visible, (visible) => {
|
|
252
300
|
if (visible !== false) {
|
|
253
301
|
requestAnimationFrame(() => {
|
|
@@ -264,16 +312,26 @@ var Label = (props) => {
|
|
|
264
312
|
onCleanup(() => clearTimeout(fadeOutTimer));
|
|
265
313
|
}
|
|
266
314
|
}));
|
|
315
|
+
createEffect(() => {
|
|
316
|
+
updateTarget();
|
|
317
|
+
});
|
|
318
|
+
onCleanup(() => {
|
|
319
|
+
if (animationFrameId !== null) {
|
|
320
|
+
cancelAnimationFrame(animationFrameId);
|
|
321
|
+
animationFrameId = null;
|
|
322
|
+
}
|
|
323
|
+
});
|
|
267
324
|
const labelBoundingRect = () => labelRef?.getBoundingClientRect();
|
|
268
325
|
const computedPosition = () => {
|
|
326
|
+
positionTick();
|
|
269
327
|
const boundingRect = labelBoundingRect();
|
|
270
328
|
if (!boundingRect) return {
|
|
271
|
-
left:
|
|
272
|
-
top:
|
|
329
|
+
left: currentX,
|
|
330
|
+
top: currentY
|
|
273
331
|
};
|
|
274
332
|
if (props.variant === "success") {
|
|
275
|
-
const indicatorLeft = Math.round(
|
|
276
|
-
const indicatorTop = Math.round(
|
|
333
|
+
const indicatorLeft = Math.round(currentX);
|
|
334
|
+
const indicatorTop = Math.round(currentY) - boundingRect.height - 6;
|
|
277
335
|
const willClampLeft = indicatorLeft < VIEWPORT_MARGIN_PX;
|
|
278
336
|
const willClampTop = indicatorTop < VIEWPORT_MARGIN_PX;
|
|
279
337
|
const isClamped = willClampLeft || willClampTop;
|
|
@@ -288,17 +346,17 @@ var Label = (props) => {
|
|
|
288
346
|
const viewportWidth = window.innerWidth;
|
|
289
347
|
const viewportHeight = window.innerHeight;
|
|
290
348
|
const quadrants = [{
|
|
291
|
-
left: Math.round(
|
|
292
|
-
top: Math.round(
|
|
349
|
+
left: Math.round(currentX) + CROSSHAIR_OFFSET,
|
|
350
|
+
top: Math.round(currentY) + CROSSHAIR_OFFSET
|
|
293
351
|
}, {
|
|
294
|
-
left: Math.round(
|
|
295
|
-
top: Math.round(
|
|
352
|
+
left: Math.round(currentX) - boundingRect.width - CROSSHAIR_OFFSET,
|
|
353
|
+
top: Math.round(currentY) + CROSSHAIR_OFFSET
|
|
296
354
|
}, {
|
|
297
|
-
left: Math.round(
|
|
298
|
-
top: Math.round(
|
|
355
|
+
left: Math.round(currentX) + CROSSHAIR_OFFSET,
|
|
356
|
+
top: Math.round(currentY) - boundingRect.height - CROSSHAIR_OFFSET
|
|
299
357
|
}, {
|
|
300
|
-
left: Math.round(
|
|
301
|
-
top: Math.round(
|
|
358
|
+
left: Math.round(currentX) - boundingRect.width - CROSSHAIR_OFFSET,
|
|
359
|
+
top: Math.round(currentY) - boundingRect.height - CROSSHAIR_OFFSET
|
|
302
360
|
}];
|
|
303
361
|
for (const position of quadrants) {
|
|
304
362
|
const fitsHorizontally = position.left >= VIEWPORT_MARGIN_PX && position.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
|
|
@@ -317,7 +375,7 @@ var Label = (props) => {
|
|
|
317
375
|
return props.visible !== false;
|
|
318
376
|
},
|
|
319
377
|
get children() {
|
|
320
|
-
var _el$ = _tmpl$
|
|
378
|
+
var _el$ = _tmpl$4();
|
|
321
379
|
var _ref$ = labelRef;
|
|
322
380
|
typeof _ref$ === "function" ? use(_ref$, _el$) : labelRef = _el$;
|
|
323
381
|
insert(_el$, createComponent(Show, {
|
|
@@ -327,7 +385,7 @@ var Label = (props) => {
|
|
|
327
385
|
get children() {
|
|
328
386
|
return createComponent(Spinner, {});
|
|
329
387
|
}
|
|
330
|
-
}),
|
|
388
|
+
}), null);
|
|
331
389
|
insert(_el$, createComponent(Show, {
|
|
332
390
|
get when() {
|
|
333
391
|
return props.variant === "success";
|
|
@@ -335,7 +393,7 @@ var Label = (props) => {
|
|
|
335
393
|
get children() {
|
|
336
394
|
return _tmpl$3();
|
|
337
395
|
}
|
|
338
|
-
}),
|
|
396
|
+
}), null);
|
|
339
397
|
insert(_el$, createComponent(Show, {
|
|
340
398
|
get when() {
|
|
341
399
|
return props.variant === "success";
|
|
@@ -343,14 +401,36 @@ var Label = (props) => {
|
|
|
343
401
|
get children() {
|
|
344
402
|
return _tmpl$22();
|
|
345
403
|
}
|
|
346
|
-
}),
|
|
404
|
+
}), null);
|
|
347
405
|
insert(_el$, createComponent(Show, {
|
|
348
406
|
get when() {
|
|
349
407
|
return props.variant === "processing";
|
|
350
408
|
},
|
|
351
409
|
children: "Grabbing\u2026"
|
|
352
|
-
}),
|
|
353
|
-
insert(_el
|
|
410
|
+
}), null);
|
|
411
|
+
insert(_el$, createComponent(Show, {
|
|
412
|
+
get when() {
|
|
413
|
+
return props.text.startsWith("(");
|
|
414
|
+
},
|
|
415
|
+
get fallback() {
|
|
416
|
+
return (() => {
|
|
417
|
+
var _el$5 = _tmpl$5();
|
|
418
|
+
insert(_el$5, () => props.text);
|
|
419
|
+
return _el$5;
|
|
420
|
+
})();
|
|
421
|
+
},
|
|
422
|
+
get children() {
|
|
423
|
+
return props.text;
|
|
424
|
+
}
|
|
425
|
+
}), null);
|
|
426
|
+
insert(_el$, createComponent(Show, {
|
|
427
|
+
get when() {
|
|
428
|
+
return props.variant === "success";
|
|
429
|
+
},
|
|
430
|
+
get children() {
|
|
431
|
+
return _tmpl$32();
|
|
432
|
+
}
|
|
433
|
+
}), null);
|
|
354
434
|
effect((_p$) => {
|
|
355
435
|
var _v$ = `${computedPosition().top}px`, _v$2 = `${computedPosition().left}px`, _v$3 = props.zIndex?.toString() ?? "2147483647", _v$4 = opacity();
|
|
356
436
|
_v$ !== _p$.e && setStyleProperty(_el$, "top", _p$.e = _v$);
|
|
@@ -368,7 +448,7 @@ var Label = (props) => {
|
|
|
368
448
|
}
|
|
369
449
|
});
|
|
370
450
|
};
|
|
371
|
-
var _tmpl$
|
|
451
|
+
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)">`);
|
|
372
452
|
var useFadeInOut = (visible) => {
|
|
373
453
|
const [opacity, setOpacity] = createSignal(0);
|
|
374
454
|
createEffect(on(() => visible, (isVisible) => {
|
|
@@ -401,7 +481,7 @@ var ProgressIndicator = (props) => {
|
|
|
401
481
|
return props.visible !== false;
|
|
402
482
|
},
|
|
403
483
|
get children() {
|
|
404
|
-
var _el$ = _tmpl$
|
|
484
|
+
var _el$ = _tmpl$6(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
|
|
405
485
|
var _ref$ = progressIndicatorRef;
|
|
406
486
|
typeof _ref$ === "function" ? use(_ref$, _el$) : progressIndicatorRef = _el$;
|
|
407
487
|
effect((_p$) => {
|
|
@@ -421,66 +501,99 @@ var ProgressIndicator = (props) => {
|
|
|
421
501
|
}
|
|
422
502
|
});
|
|
423
503
|
};
|
|
424
|
-
var _tmpl$
|
|
504
|
+
var _tmpl$7 = /* @__PURE__ */ template(`<canvas style=position:fixed;top:0;left:0;pointer-events:none;z-index:2147483645>`);
|
|
425
505
|
var Crosshair = (props) => {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
let
|
|
429
|
-
let
|
|
506
|
+
let canvasRef;
|
|
507
|
+
let context = null;
|
|
508
|
+
let width = 0;
|
|
509
|
+
let height = 0;
|
|
510
|
+
let dpr = 1;
|
|
511
|
+
let currentX = props.mouseX;
|
|
512
|
+
let currentY = props.mouseY;
|
|
430
513
|
let targetX = props.mouseX;
|
|
431
514
|
let targetY = props.mouseY;
|
|
432
|
-
let
|
|
515
|
+
let animationFrameId = null;
|
|
516
|
+
let hasBeenRenderedOnce = false;
|
|
517
|
+
const setupCanvas = () => {
|
|
518
|
+
if (!canvasRef) return;
|
|
519
|
+
dpr = Math.max(window.devicePixelRatio || 1, 2);
|
|
520
|
+
width = window.innerWidth;
|
|
521
|
+
height = window.innerHeight;
|
|
522
|
+
canvasRef.width = width * dpr;
|
|
523
|
+
canvasRef.height = height * dpr;
|
|
524
|
+
canvasRef.style.width = `${width}px`;
|
|
525
|
+
canvasRef.style.height = `${height}px`;
|
|
526
|
+
context = canvasRef.getContext("2d");
|
|
527
|
+
if (context) {
|
|
528
|
+
context.scale(dpr, dpr);
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
const render2 = () => {
|
|
532
|
+
if (!context) return;
|
|
533
|
+
context.clearRect(0, 0, width, height);
|
|
534
|
+
context.strokeStyle = "rgba(210, 57, 192)";
|
|
535
|
+
context.lineWidth = 1;
|
|
536
|
+
context.beginPath();
|
|
537
|
+
context.moveTo(currentX, 0);
|
|
538
|
+
context.lineTo(currentX, height);
|
|
539
|
+
context.moveTo(0, currentY);
|
|
540
|
+
context.lineTo(width, currentY);
|
|
541
|
+
context.stroke();
|
|
542
|
+
};
|
|
543
|
+
const animate = () => {
|
|
544
|
+
currentX = lerp(currentX, targetX, 0.3);
|
|
545
|
+
currentY = lerp(currentY, targetY, 0.3);
|
|
546
|
+
render2();
|
|
547
|
+
const hasConvergedToTarget = Math.abs(currentX - targetX) < 0.5 && Math.abs(currentY - targetY) < 0.5;
|
|
548
|
+
if (!hasConvergedToTarget) {
|
|
549
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
550
|
+
} else {
|
|
551
|
+
animationFrameId = null;
|
|
552
|
+
}
|
|
553
|
+
};
|
|
433
554
|
const startAnimation = () => {
|
|
434
|
-
if (
|
|
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
|
-
};
|
|
555
|
+
if (animationFrameId !== null) return;
|
|
449
556
|
animationFrameId = requestAnimationFrame(animate);
|
|
450
557
|
};
|
|
451
|
-
|
|
452
|
-
targetX =
|
|
453
|
-
targetY =
|
|
558
|
+
const updateTarget = () => {
|
|
559
|
+
targetX = props.mouseX;
|
|
560
|
+
targetY = props.mouseY;
|
|
454
561
|
if (!hasBeenRenderedOnce) {
|
|
455
|
-
|
|
456
|
-
|
|
562
|
+
currentX = targetX;
|
|
563
|
+
currentY = targetY;
|
|
457
564
|
hasBeenRenderedOnce = true;
|
|
565
|
+
render2();
|
|
458
566
|
return;
|
|
459
567
|
}
|
|
460
568
|
startAnimation();
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
569
|
+
};
|
|
570
|
+
createEffect(() => {
|
|
571
|
+
setupCanvas();
|
|
572
|
+
render2();
|
|
573
|
+
const handleResize = () => {
|
|
574
|
+
setupCanvas();
|
|
575
|
+
render2();
|
|
576
|
+
};
|
|
577
|
+
window.addEventListener("resize", handleResize);
|
|
578
|
+
onCleanup(() => {
|
|
579
|
+
window.removeEventListener("resize", handleResize);
|
|
580
|
+
if (animationFrameId !== null) {
|
|
581
|
+
cancelAnimationFrame(animationFrameId);
|
|
582
|
+
animationFrameId = null;
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
});
|
|
586
|
+
createEffect(() => {
|
|
587
|
+
updateTarget();
|
|
468
588
|
});
|
|
469
589
|
return createComponent(Show, {
|
|
470
590
|
get when() {
|
|
471
591
|
return props.visible !== false;
|
|
472
592
|
},
|
|
473
593
|
get children() {
|
|
474
|
-
var _el$ = _tmpl$
|
|
475
|
-
|
|
476
|
-
|
|
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
|
-
});
|
|
594
|
+
var _el$ = _tmpl$7();
|
|
595
|
+
var _ref$ = canvasRef;
|
|
596
|
+
typeof _ref$ === "function" ? use(_ref$, _el$) : canvasRef = _el$;
|
|
484
597
|
return _el$;
|
|
485
598
|
}
|
|
486
599
|
});
|
|
@@ -541,6 +654,9 @@ var ReactGrabRenderer = (props) => {
|
|
|
541
654
|
variant: "grabbed",
|
|
542
655
|
get bounds() {
|
|
543
656
|
return box.bounds;
|
|
657
|
+
},
|
|
658
|
+
get createdAt() {
|
|
659
|
+
return box.createdAt;
|
|
544
660
|
}
|
|
545
661
|
})
|
|
546
662
|
}), createComponent(For, {
|
|
@@ -621,7 +737,14 @@ var getSourceTrace = async (element) => {
|
|
|
621
737
|
Number.MAX_SAFE_INTEGER
|
|
622
738
|
);
|
|
623
739
|
if (!sources) return null;
|
|
624
|
-
return sources
|
|
740
|
+
return sources.filter((source) => {
|
|
741
|
+
return isSourceFile(source.fileName);
|
|
742
|
+
}).map((source) => {
|
|
743
|
+
return {
|
|
744
|
+
...source,
|
|
745
|
+
fileName: normalizeFileName(source.fileName)
|
|
746
|
+
};
|
|
747
|
+
});
|
|
625
748
|
};
|
|
626
749
|
var getHTMLSnippet = (element) => {
|
|
627
750
|
const semanticTags = /* @__PURE__ */ new Set([
|
|
@@ -971,11 +1094,65 @@ var filterElementsInDrag = (dragRect, isValidGrabbableElement2, shouldCheckCover
|
|
|
971
1094
|
}
|
|
972
1095
|
return elements;
|
|
973
1096
|
};
|
|
1097
|
+
var removeNestedElements = (elements) => {
|
|
1098
|
+
return elements.filter((element) => {
|
|
1099
|
+
return !elements.some(
|
|
1100
|
+
(otherElement) => otherElement !== element && otherElement.contains(element)
|
|
1101
|
+
);
|
|
1102
|
+
});
|
|
1103
|
+
};
|
|
1104
|
+
var findBestParentElement = (elements, dragRect, isValidGrabbableElement2) => {
|
|
1105
|
+
if (elements.length <= 1) return null;
|
|
1106
|
+
const dragLeft = dragRect.x;
|
|
1107
|
+
const dragTop = dragRect.y;
|
|
1108
|
+
const dragRight = dragRect.x + dragRect.width;
|
|
1109
|
+
const dragBottom = dragRect.y + dragRect.height;
|
|
1110
|
+
let currentParent = elements[0];
|
|
1111
|
+
while (currentParent) {
|
|
1112
|
+
const parent = currentParent.parentElement;
|
|
1113
|
+
if (!parent) break;
|
|
1114
|
+
const parentRect = parent.getBoundingClientRect();
|
|
1115
|
+
const intersectionLeft = Math.max(dragLeft, parentRect.left);
|
|
1116
|
+
const intersectionTop = Math.max(dragTop, parentRect.top);
|
|
1117
|
+
const intersectionRight = Math.min(dragRight, parentRect.left + parentRect.width);
|
|
1118
|
+
const intersectionBottom = Math.min(dragBottom, parentRect.top + parentRect.height);
|
|
1119
|
+
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
1120
|
+
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
1121
|
+
const intersectionArea = intersectionWidth * intersectionHeight;
|
|
1122
|
+
const parentArea = Math.max(0, parentRect.width * parentRect.height);
|
|
1123
|
+
const hasMajorityCoverage = parentArea > 0 && intersectionArea / parentArea >= DRAG_COVERAGE_THRESHOLD;
|
|
1124
|
+
if (!hasMajorityCoverage) break;
|
|
1125
|
+
if (!isValidGrabbableElement2(parent)) {
|
|
1126
|
+
currentParent = parent;
|
|
1127
|
+
continue;
|
|
1128
|
+
}
|
|
1129
|
+
const allChildrenInParent = elements.every(
|
|
1130
|
+
(element) => parent.contains(element)
|
|
1131
|
+
);
|
|
1132
|
+
if (allChildrenInParent) {
|
|
1133
|
+
return parent;
|
|
1134
|
+
}
|
|
1135
|
+
currentParent = parent;
|
|
1136
|
+
}
|
|
1137
|
+
return null;
|
|
1138
|
+
};
|
|
974
1139
|
var getElementsInDrag = (dragRect, isValidGrabbableElement2) => {
|
|
975
|
-
|
|
1140
|
+
const elements = filterElementsInDrag(dragRect, isValidGrabbableElement2, true);
|
|
1141
|
+
const uniqueElements = removeNestedElements(elements);
|
|
1142
|
+
const bestParent = findBestParentElement(uniqueElements, dragRect, isValidGrabbableElement2);
|
|
1143
|
+
if (bestParent) {
|
|
1144
|
+
return [bestParent];
|
|
1145
|
+
}
|
|
1146
|
+
return uniqueElements;
|
|
976
1147
|
};
|
|
977
1148
|
var getElementsInDragLoose = (dragRect, isValidGrabbableElement2) => {
|
|
978
|
-
|
|
1149
|
+
const elements = filterElementsInDrag(dragRect, isValidGrabbableElement2, false);
|
|
1150
|
+
const uniqueElements = removeNestedElements(elements);
|
|
1151
|
+
const bestParent = findBestParentElement(uniqueElements, dragRect, isValidGrabbableElement2);
|
|
1152
|
+
if (bestParent) {
|
|
1153
|
+
return [bestParent];
|
|
1154
|
+
}
|
|
1155
|
+
return uniqueElements;
|
|
979
1156
|
};
|
|
980
1157
|
|
|
981
1158
|
// src/utils/create-element-bounds.ts
|
|
@@ -1020,22 +1197,26 @@ var init = (rawOptions) => {
|
|
|
1020
1197
|
const [successLabels, setSuccessLabels] = createSignal([]);
|
|
1021
1198
|
const [isActivated, setIsActivated] = createSignal(false);
|
|
1022
1199
|
const [showProgressIndicator, setShowProgressIndicator] = createSignal(false);
|
|
1023
|
-
const [grabMouseX, setGrabMouseX] = createSignal(null);
|
|
1024
|
-
const [grabMouseY, setGrabMouseY] = createSignal(null);
|
|
1025
1200
|
let holdTimerId = null;
|
|
1026
1201
|
let progressAnimationId = null;
|
|
1027
1202
|
let progressDelayTimerId = null;
|
|
1203
|
+
let keydownSpamTimerId = null;
|
|
1028
1204
|
const isRendererActive = createMemo(() => isActivated() && !isCopying());
|
|
1029
1205
|
const hasValidMousePosition = createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
|
|
1030
1206
|
const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "c";
|
|
1031
1207
|
const addGrabbedBox = (bounds) => {
|
|
1032
1208
|
const boxId = `grabbed-${Date.now()}-${Math.random()}`;
|
|
1209
|
+
const createdAt = Date.now();
|
|
1033
1210
|
const newBox = {
|
|
1034
1211
|
id: boxId,
|
|
1035
|
-
bounds
|
|
1212
|
+
bounds,
|
|
1213
|
+
createdAt
|
|
1036
1214
|
};
|
|
1037
1215
|
const currentBoxes = grabbedBoxes();
|
|
1038
1216
|
setGrabbedBoxes([...currentBoxes, newBox]);
|
|
1217
|
+
setTimeout(() => {
|
|
1218
|
+
setGrabbedBoxes((previousBoxes) => previousBoxes.filter((box) => box.id !== boxId));
|
|
1219
|
+
}, SUCCESS_LABEL_DURATION_MS);
|
|
1039
1220
|
};
|
|
1040
1221
|
const addSuccessLabel = (text, positionX, positionY) => {
|
|
1041
1222
|
const labelId = `success-${Date.now()}-${Math.random()}`;
|
|
@@ -1058,6 +1239,9 @@ var init = (rawOptions) => {
|
|
|
1058
1239
|
return ` ${functionName} - ${fileName}:${lineNumber}:${columnNumber}`;
|
|
1059
1240
|
}).join("\n");
|
|
1060
1241
|
};
|
|
1242
|
+
const wrapContextInXmlTags = (context) => {
|
|
1243
|
+
return `<selected_element>${context}</selected_element>`;
|
|
1244
|
+
};
|
|
1061
1245
|
const getElementContentWithTrace = async (element) => {
|
|
1062
1246
|
const elementHtml = getHTMLSnippet(element);
|
|
1063
1247
|
const componentStackTrace = await getSourceTrace(element);
|
|
@@ -1074,12 +1258,10 @@ ${formattedStackTrace}`;
|
|
|
1074
1258
|
const handleCopy = async (targetElement2) => {
|
|
1075
1259
|
const elementBounds = targetElement2.getBoundingClientRect();
|
|
1076
1260
|
const tagName = getElementTagName(targetElement2);
|
|
1077
|
-
setGrabMouseX(mouseX());
|
|
1078
|
-
setGrabMouseY(mouseY());
|
|
1079
1261
|
addGrabbedBox(createElementBounds(targetElement2));
|
|
1080
1262
|
try {
|
|
1081
1263
|
const content = await getElementContentWithTrace(targetElement2);
|
|
1082
|
-
await copyContent(content);
|
|
1264
|
+
await copyContent(wrapContextInXmlTags(content));
|
|
1083
1265
|
} catch {
|
|
1084
1266
|
}
|
|
1085
1267
|
addSuccessLabel(tagName ? `<${tagName}>` : "<element>", elementBounds.left, elementBounds.top);
|
|
@@ -1088,8 +1270,6 @@ ${formattedStackTrace}`;
|
|
|
1088
1270
|
if (targetElements.length === 0) return;
|
|
1089
1271
|
let minPositionX = Infinity;
|
|
1090
1272
|
let minPositionY = Infinity;
|
|
1091
|
-
setGrabMouseX(mouseX());
|
|
1092
|
-
setGrabMouseY(mouseY());
|
|
1093
1273
|
for (const element of targetElements) {
|
|
1094
1274
|
const elementBounds = element.getBoundingClientRect();
|
|
1095
1275
|
minPositionX = Math.min(minPositionX, elementBounds.left);
|
|
@@ -1099,7 +1279,7 @@ ${formattedStackTrace}`;
|
|
|
1099
1279
|
try {
|
|
1100
1280
|
const elementSnippets = await Promise.all(targetElements.map((element) => getElementContentWithTrace(element)));
|
|
1101
1281
|
const combinedContent = elementSnippets.join("\n\n---\n\n");
|
|
1102
|
-
await copyContent(combinedContent);
|
|
1282
|
+
await copyContent(wrapContextInXmlTags(combinedContent));
|
|
1103
1283
|
} catch {
|
|
1104
1284
|
}
|
|
1105
1285
|
addSuccessLabel(`${targetElements.length} elements`, minPositionX, minPositionY);
|
|
@@ -1122,7 +1302,7 @@ ${formattedStackTrace}`;
|
|
|
1122
1302
|
y: elementBounds.top
|
|
1123
1303
|
};
|
|
1124
1304
|
});
|
|
1125
|
-
const DRAG_THRESHOLD_PX =
|
|
1305
|
+
const DRAG_THRESHOLD_PX = 2;
|
|
1126
1306
|
const getDragDistance = (endX, endY) => ({
|
|
1127
1307
|
x: Math.abs(endX - dragStartX()),
|
|
1128
1308
|
y: Math.abs(endY - dragStartY())
|
|
@@ -1158,7 +1338,7 @@ ${formattedStackTrace}`;
|
|
|
1158
1338
|
});
|
|
1159
1339
|
const labelText = createMemo(() => {
|
|
1160
1340
|
const element = targetElement();
|
|
1161
|
-
if (!element) return "";
|
|
1341
|
+
if (!element) return "(click or drag to select element(s))";
|
|
1162
1342
|
const tagName = getElementTagName(element);
|
|
1163
1343
|
return tagName ? `<${tagName}>` : "<element>";
|
|
1164
1344
|
});
|
|
@@ -1178,18 +1358,6 @@ ${formattedStackTrace}`;
|
|
|
1178
1358
|
setLastGrabbedElement(null);
|
|
1179
1359
|
}
|
|
1180
1360
|
}));
|
|
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
|
-
}));
|
|
1193
1361
|
const progress = createMemo(() => {
|
|
1194
1362
|
const startTime = progressStartTime();
|
|
1195
1363
|
progressTick();
|
|
@@ -1231,43 +1399,55 @@ ${formattedStackTrace}`;
|
|
|
1231
1399
|
setIsActivated(true);
|
|
1232
1400
|
document.body.style.cursor = "crosshair";
|
|
1233
1401
|
};
|
|
1402
|
+
const deactivateRenderer = () => {
|
|
1403
|
+
setIsHoldingKeys(false);
|
|
1404
|
+
setIsActivated(false);
|
|
1405
|
+
document.body.style.cursor = "";
|
|
1406
|
+
if (isDragging()) {
|
|
1407
|
+
setIsDragging(false);
|
|
1408
|
+
document.body.style.userSelect = "";
|
|
1409
|
+
}
|
|
1410
|
+
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1411
|
+
if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
|
|
1412
|
+
stopProgressAnimation();
|
|
1413
|
+
};
|
|
1234
1414
|
const abortController = new AbortController();
|
|
1235
1415
|
const eventListenerSignal = abortController.signal;
|
|
1236
1416
|
window.addEventListener("keydown", (event) => {
|
|
1237
1417
|
if (event.key === "Escape" && isHoldingKeys()) {
|
|
1238
|
-
|
|
1239
|
-
setIsActivated(false);
|
|
1240
|
-
document.body.style.cursor = "";
|
|
1241
|
-
if (isDragging()) {
|
|
1242
|
-
setIsDragging(false);
|
|
1243
|
-
document.body.style.userSelect = "";
|
|
1244
|
-
}
|
|
1245
|
-
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1246
|
-
stopProgressAnimation();
|
|
1418
|
+
deactivateRenderer();
|
|
1247
1419
|
return;
|
|
1248
1420
|
}
|
|
1249
1421
|
if (isKeyboardEventTriggeredByInput(event)) return;
|
|
1250
|
-
if (isTargetKeyCombination(event)
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1422
|
+
if (isTargetKeyCombination(event)) {
|
|
1423
|
+
if (!isHoldingKeys()) {
|
|
1424
|
+
setIsHoldingKeys(true);
|
|
1425
|
+
startProgressAnimation();
|
|
1426
|
+
holdTimerId = window.setTimeout(() => {
|
|
1427
|
+
activateRenderer();
|
|
1428
|
+
options.onActivate?.();
|
|
1429
|
+
}, options.keyHoldDuration);
|
|
1430
|
+
}
|
|
1431
|
+
if (isActivated()) {
|
|
1432
|
+
if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
|
|
1433
|
+
keydownSpamTimerId = window.setTimeout(() => {
|
|
1434
|
+
deactivateRenderer();
|
|
1435
|
+
}, 200);
|
|
1436
|
+
}
|
|
1257
1437
|
}
|
|
1258
1438
|
}, {
|
|
1259
1439
|
signal: eventListenerSignal
|
|
1260
1440
|
});
|
|
1261
1441
|
window.addEventListener("keyup", (event) => {
|
|
1262
|
-
if (isHoldingKeys() &&
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
stopProgressAnimation();
|
|
1442
|
+
if (!isHoldingKeys() && !isActivated()) return;
|
|
1443
|
+
const isReleasingC = event.key.toLowerCase() === "c";
|
|
1444
|
+
const isReleasingModifier = !event.metaKey && !event.ctrlKey;
|
|
1445
|
+
if (isReleasingC || isReleasingModifier) {
|
|
1446
|
+
deactivateRenderer();
|
|
1268
1447
|
}
|
|
1269
1448
|
}, {
|
|
1270
|
-
signal: eventListenerSignal
|
|
1449
|
+
signal: eventListenerSignal,
|
|
1450
|
+
capture: true
|
|
1271
1451
|
});
|
|
1272
1452
|
window.addEventListener("mousemove", (event) => {
|
|
1273
1453
|
setMouseX(event.clientX);
|
|
@@ -1330,6 +1510,7 @@ ${formattedStackTrace}`;
|
|
|
1330
1510
|
onCleanup(() => {
|
|
1331
1511
|
abortController.abort();
|
|
1332
1512
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1513
|
+
if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
|
|
1333
1514
|
stopProgressAnimation();
|
|
1334
1515
|
document.body.style.userSelect = "";
|
|
1335
1516
|
document.body.style.cursor = "";
|
|
@@ -1338,7 +1519,7 @@ ${formattedStackTrace}`;
|
|
|
1338
1519
|
const selectionVisible = createMemo(() => false);
|
|
1339
1520
|
const dragVisible = createMemo(() => isRendererActive() && isDraggingBeyondThreshold());
|
|
1340
1521
|
const labelVariant = createMemo(() => isCopying() ? "processing" : "hover");
|
|
1341
|
-
const labelVisible = createMemo(() => isRendererActive() && !isDragging() && !!targetElement() && !isSameAsLast() || isCopying());
|
|
1522
|
+
const labelVisible = createMemo(() => isRendererActive() && !isDragging() && (!!targetElement() && !isSameAsLast() || !targetElement()) || isCopying());
|
|
1342
1523
|
const progressVisible = createMemo(() => isHoldingKeys() && showProgressIndicator() && hasValidMousePosition());
|
|
1343
1524
|
const crosshairVisible = createMemo(() => isRendererActive() && !isDragging());
|
|
1344
1525
|
render(() => createComponent(ReactGrabRenderer, {
|