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