react-grab 0.0.40 → 0.0.41
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 +305 -631
- package/dist/index.d.cts +1 -15
- package/dist/index.d.ts +1 -15
- package/dist/index.global.js +31 -87
- package/dist/index.js +307 -627
- package/package.json +3 -8
package/dist/index.cjs
CHANGED
|
@@ -3,13 +3,7 @@
|
|
|
3
3
|
var web = require('solid-js/web');
|
|
4
4
|
var solidJs = require('solid-js');
|
|
5
5
|
var bippy = require('bippy');
|
|
6
|
-
var source = require('bippy/
|
|
7
|
-
var finder = require('@medv/finder');
|
|
8
|
-
var TurndownService = require('turndown');
|
|
9
|
-
|
|
10
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
-
|
|
12
|
-
var TurndownService__default = /*#__PURE__*/_interopDefault(TurndownService);
|
|
6
|
+
var source = require('bippy/source');
|
|
13
7
|
|
|
14
8
|
/**
|
|
15
9
|
* @license MIT
|
|
@@ -101,8 +95,12 @@ var mountRoot = () => {
|
|
|
101
95
|
var VIEWPORT_MARGIN_PX = 8;
|
|
102
96
|
var INDICATOR_CLAMP_PADDING_PX = 4;
|
|
103
97
|
var CURSOR_OFFSET_PX = 14;
|
|
98
|
+
var OFFSCREEN_POSITION = -1e3;
|
|
104
99
|
var SELECTION_LERP_FACTOR = 0.95;
|
|
105
100
|
var SUCCESS_LABEL_DURATION_MS = 1700;
|
|
101
|
+
var PROGRESS_INDICATOR_DELAY_MS = 150;
|
|
102
|
+
var DRAG_THRESHOLD_PX = 2;
|
|
103
|
+
var Z_INDEX_LABEL = 2147483647;
|
|
106
104
|
|
|
107
105
|
// src/utils/lerp.ts
|
|
108
106
|
var lerp = (start, end, factor) => {
|
|
@@ -267,30 +265,22 @@ var getClampedElementPosition = (positionLeft, positionTop, elementWidth, elemen
|
|
|
267
265
|
const clampedTop = Math.max(minTop, Math.min(positionTop, maxTop));
|
|
268
266
|
return { left: clampedLeft, top: clampedTop };
|
|
269
267
|
};
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
var _tmpl$6 = /* @__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">`);
|
|
278
|
-
var Label = (props) => {
|
|
279
|
-
const [opacity, setOpacity] = solidJs.createSignal(0);
|
|
280
|
-
const [positionTick, setPositionTick] = solidJs.createSignal(0);
|
|
281
|
-
let labelRef;
|
|
282
|
-
let currentX = props.x;
|
|
283
|
-
let currentY = props.y;
|
|
284
|
-
let targetX = props.x;
|
|
285
|
-
let targetY = props.y;
|
|
268
|
+
var useAnimatedPosition = (options) => {
|
|
269
|
+
const lerpFactor = options.lerpFactor ?? 0.3;
|
|
270
|
+
const convergenceThreshold = options.convergenceThreshold ?? 0.5;
|
|
271
|
+
const [x, setX] = solidJs.createSignal(options.x());
|
|
272
|
+
const [y, setY] = solidJs.createSignal(options.y());
|
|
273
|
+
let targetX = options.x();
|
|
274
|
+
let targetY = options.y();
|
|
286
275
|
let animationFrameId = null;
|
|
287
276
|
let hasBeenRenderedOnce = false;
|
|
288
277
|
const animate = () => {
|
|
289
|
-
currentX = lerp(
|
|
290
|
-
currentY = lerp(
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
278
|
+
const currentX = lerp(x(), targetX, lerpFactor);
|
|
279
|
+
const currentY = lerp(y(), targetY, lerpFactor);
|
|
280
|
+
setX(currentX);
|
|
281
|
+
setY(currentY);
|
|
282
|
+
const hasConverged = Math.abs(currentX - targetX) < convergenceThreshold && Math.abs(currentY - targetY) < convergenceThreshold;
|
|
283
|
+
if (!hasConverged) {
|
|
294
284
|
animationFrameId = requestAnimationFrame(animate);
|
|
295
285
|
} else {
|
|
296
286
|
animationFrameId = null;
|
|
@@ -300,36 +290,16 @@ var Label = (props) => {
|
|
|
300
290
|
if (animationFrameId !== null) return;
|
|
301
291
|
animationFrameId = requestAnimationFrame(animate);
|
|
302
292
|
};
|
|
303
|
-
|
|
304
|
-
targetX =
|
|
305
|
-
targetY =
|
|
293
|
+
solidJs.createEffect(() => {
|
|
294
|
+
targetX = options.x();
|
|
295
|
+
targetY = options.y();
|
|
306
296
|
if (!hasBeenRenderedOnce) {
|
|
307
|
-
|
|
308
|
-
|
|
297
|
+
setX(targetX);
|
|
298
|
+
setY(targetY);
|
|
309
299
|
hasBeenRenderedOnce = true;
|
|
310
|
-
setPositionTick((tick) => tick + 1);
|
|
311
300
|
return;
|
|
312
301
|
}
|
|
313
302
|
startAnimation();
|
|
314
|
-
};
|
|
315
|
-
solidJs.createEffect(solidJs.on(() => props.visible, (visible) => {
|
|
316
|
-
if (visible !== false) {
|
|
317
|
-
requestAnimationFrame(() => {
|
|
318
|
-
setOpacity(1);
|
|
319
|
-
});
|
|
320
|
-
} else {
|
|
321
|
-
setOpacity(0);
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
if (props.variant === "success") {
|
|
325
|
-
const fadeOutTimer = setTimeout(() => {
|
|
326
|
-
setOpacity(0);
|
|
327
|
-
}, SUCCESS_LABEL_DURATION_MS);
|
|
328
|
-
solidJs.onCleanup(() => clearTimeout(fadeOutTimer));
|
|
329
|
-
}
|
|
330
|
-
}));
|
|
331
|
-
solidJs.createEffect(() => {
|
|
332
|
-
updateTarget();
|
|
333
303
|
});
|
|
334
304
|
solidJs.onCleanup(() => {
|
|
335
305
|
if (animationFrameId !== null) {
|
|
@@ -337,34 +307,89 @@ var Label = (props) => {
|
|
|
337
307
|
animationFrameId = null;
|
|
338
308
|
}
|
|
339
309
|
});
|
|
310
|
+
return { x, y };
|
|
311
|
+
};
|
|
312
|
+
var useFadeInOut = (options) => {
|
|
313
|
+
const [opacity, setOpacity] = solidJs.createSignal(0);
|
|
314
|
+
solidJs.createEffect(
|
|
315
|
+
solidJs.on(
|
|
316
|
+
() => options.visible,
|
|
317
|
+
(isVisible) => {
|
|
318
|
+
if (isVisible !== false) {
|
|
319
|
+
requestAnimationFrame(() => {
|
|
320
|
+
setOpacity(1);
|
|
321
|
+
});
|
|
322
|
+
} else {
|
|
323
|
+
setOpacity(0);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (options.autoFadeOutAfter !== void 0) {
|
|
327
|
+
const fadeOutTimer = setTimeout(() => {
|
|
328
|
+
setOpacity(0);
|
|
329
|
+
}, options.autoFadeOutAfter);
|
|
330
|
+
solidJs.onCleanup(() => clearTimeout(fadeOutTimer));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
)
|
|
334
|
+
);
|
|
335
|
+
return opacity;
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// src/utils/get-cursor-quadrants.ts
|
|
339
|
+
var getCursorQuadrants = (cursorX, cursorY, elementWidth, elementHeight, offset) => {
|
|
340
|
+
return [
|
|
341
|
+
{
|
|
342
|
+
left: Math.round(cursorX) + offset,
|
|
343
|
+
top: Math.round(cursorY) + offset
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
left: Math.round(cursorX) - elementWidth - offset,
|
|
347
|
+
top: Math.round(cursorY) + offset
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
left: Math.round(cursorX) + offset,
|
|
351
|
+
top: Math.round(cursorY) - elementHeight - offset
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
left: Math.round(cursorX) - elementWidth - offset,
|
|
355
|
+
top: Math.round(cursorY) - elementHeight - offset
|
|
356
|
+
}
|
|
357
|
+
];
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
// src/components/label.tsx
|
|
361
|
+
var _tmpl$3 = /* @__PURE__ */ web.template(`<span style=display:inline-block;margin-right:4px;font-weight:600>\u2713`);
|
|
362
|
+
var _tmpl$22 = /* @__PURE__ */ web.template(`<div style=margin-right:4px>Copied`);
|
|
363
|
+
var _tmpl$32 = /* @__PURE__ */ web.template(`<span style="font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;font-variant-numeric:tabular-nums;vertical-align:middle">`);
|
|
364
|
+
var _tmpl$4 = /* @__PURE__ */ web.template(`<span style=font-variant-numeric:tabular-nums;font-size:10px;margin-left:4px;vertical-align:middle>`);
|
|
365
|
+
var _tmpl$5 = /* @__PURE__ */ web.template(`<div style=margin-left:4px>to clipboard`);
|
|
366
|
+
var _tmpl$6 = /* @__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">`);
|
|
367
|
+
var Label = (props) => {
|
|
368
|
+
let labelRef;
|
|
369
|
+
const position = useAnimatedPosition({
|
|
370
|
+
x: () => props.x,
|
|
371
|
+
y: () => props.y,
|
|
372
|
+
lerpFactor: 0.3
|
|
373
|
+
});
|
|
374
|
+
const opacity = useFadeInOut({
|
|
375
|
+
visible: props.visible,
|
|
376
|
+
autoFadeOutAfter: props.variant === "success" ? SUCCESS_LABEL_DURATION_MS : void 0
|
|
377
|
+
});
|
|
340
378
|
const labelBoundingRect = () => labelRef?.getBoundingClientRect();
|
|
341
379
|
const computedPosition = () => {
|
|
342
|
-
positionTick();
|
|
343
380
|
const boundingRect = labelBoundingRect();
|
|
344
381
|
if (!boundingRect) return {
|
|
345
|
-
left:
|
|
346
|
-
top:
|
|
382
|
+
left: position.x(),
|
|
383
|
+
top: position.y()
|
|
347
384
|
};
|
|
348
385
|
const viewportWidth = window.innerWidth;
|
|
349
386
|
const viewportHeight = window.innerHeight;
|
|
350
|
-
const quadrants =
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
left: Math.round(currentX) - boundingRect.width - CURSOR_OFFSET_PX,
|
|
355
|
-
top: Math.round(currentY) + CURSOR_OFFSET_PX
|
|
356
|
-
}, {
|
|
357
|
-
left: Math.round(currentX) + CURSOR_OFFSET_PX,
|
|
358
|
-
top: Math.round(currentY) - boundingRect.height - CURSOR_OFFSET_PX
|
|
359
|
-
}, {
|
|
360
|
-
left: Math.round(currentX) - boundingRect.width - CURSOR_OFFSET_PX,
|
|
361
|
-
top: Math.round(currentY) - boundingRect.height - CURSOR_OFFSET_PX
|
|
362
|
-
}];
|
|
363
|
-
for (const position of quadrants) {
|
|
364
|
-
const fitsHorizontally = position.left >= VIEWPORT_MARGIN_PX && position.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
|
|
365
|
-
const fitsVertically = position.top >= VIEWPORT_MARGIN_PX && position.top + boundingRect.height <= viewportHeight - VIEWPORT_MARGIN_PX;
|
|
387
|
+
const quadrants = getCursorQuadrants(position.x(), position.y(), boundingRect.width, boundingRect.height, CURSOR_OFFSET_PX);
|
|
388
|
+
for (const position2 of quadrants) {
|
|
389
|
+
const fitsHorizontally = position2.left >= VIEWPORT_MARGIN_PX && position2.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
|
|
390
|
+
const fitsVertically = position2.top >= VIEWPORT_MARGIN_PX && position2.top + boundingRect.height <= viewportHeight - VIEWPORT_MARGIN_PX;
|
|
366
391
|
if (fitsHorizontally && fitsVertically) {
|
|
367
|
-
return
|
|
392
|
+
return position2;
|
|
368
393
|
}
|
|
369
394
|
}
|
|
370
395
|
const fallback = getClampedElementPosition(quadrants[0].left, quadrants[0].top, boundingRect.width, boundingRect.height);
|
|
@@ -471,21 +496,10 @@ var Label = (props) => {
|
|
|
471
496
|
});
|
|
472
497
|
};
|
|
473
498
|
var _tmpl$7 = /* @__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)">`);
|
|
474
|
-
var useFadeInOut = (visible) => {
|
|
475
|
-
const [opacity, setOpacity] = solidJs.createSignal(0);
|
|
476
|
-
solidJs.createEffect(solidJs.on(() => visible, (isVisible) => {
|
|
477
|
-
if (isVisible !== false) {
|
|
478
|
-
requestAnimationFrame(() => {
|
|
479
|
-
setOpacity(1);
|
|
480
|
-
});
|
|
481
|
-
} else {
|
|
482
|
-
setOpacity(0);
|
|
483
|
-
}
|
|
484
|
-
}));
|
|
485
|
-
return opacity;
|
|
486
|
-
};
|
|
487
499
|
var ProgressIndicator = (props) => {
|
|
488
|
-
const opacity = useFadeInOut(
|
|
500
|
+
const opacity = useFadeInOut({
|
|
501
|
+
visible: props.visible
|
|
502
|
+
});
|
|
489
503
|
let progressIndicatorRef;
|
|
490
504
|
const computedPosition = () => {
|
|
491
505
|
const boundingRect = progressIndicatorRef?.getBoundingClientRect();
|
|
@@ -530,12 +544,11 @@ var Crosshair = (props) => {
|
|
|
530
544
|
let width = 0;
|
|
531
545
|
let height = 0;
|
|
532
546
|
let dpr = 1;
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
let hasBeenRenderedOnce = false;
|
|
547
|
+
const position = useAnimatedPosition({
|
|
548
|
+
x: () => props.mouseX,
|
|
549
|
+
y: () => props.mouseY,
|
|
550
|
+
lerpFactor: 0.3
|
|
551
|
+
});
|
|
539
552
|
const setupCanvas = () => {
|
|
540
553
|
if (!canvasRef) return;
|
|
541
554
|
dpr = Math.max(window.devicePixelRatio || 1, 2);
|
|
@@ -556,39 +569,12 @@ var Crosshair = (props) => {
|
|
|
556
569
|
context.strokeStyle = "rgba(210, 57, 192)";
|
|
557
570
|
context.lineWidth = 1;
|
|
558
571
|
context.beginPath();
|
|
559
|
-
context.moveTo(
|
|
560
|
-
context.lineTo(
|
|
561
|
-
context.moveTo(0,
|
|
562
|
-
context.lineTo(width,
|
|
572
|
+
context.moveTo(position.x(), 0);
|
|
573
|
+
context.lineTo(position.x(), height);
|
|
574
|
+
context.moveTo(0, position.y());
|
|
575
|
+
context.lineTo(width, position.y());
|
|
563
576
|
context.stroke();
|
|
564
577
|
};
|
|
565
|
-
const animate = () => {
|
|
566
|
-
currentX = lerp(currentX, targetX, 0.3);
|
|
567
|
-
currentY = lerp(currentY, targetY, 0.3);
|
|
568
|
-
render2();
|
|
569
|
-
const hasConvergedToTarget = Math.abs(currentX - targetX) < 0.5 && Math.abs(currentY - targetY) < 0.5;
|
|
570
|
-
if (!hasConvergedToTarget) {
|
|
571
|
-
animationFrameId = requestAnimationFrame(animate);
|
|
572
|
-
} else {
|
|
573
|
-
animationFrameId = null;
|
|
574
|
-
}
|
|
575
|
-
};
|
|
576
|
-
const startAnimation = () => {
|
|
577
|
-
if (animationFrameId !== null) return;
|
|
578
|
-
animationFrameId = requestAnimationFrame(animate);
|
|
579
|
-
};
|
|
580
|
-
const updateTarget = () => {
|
|
581
|
-
targetX = props.mouseX;
|
|
582
|
-
targetY = props.mouseY;
|
|
583
|
-
if (!hasBeenRenderedOnce) {
|
|
584
|
-
currentX = targetX;
|
|
585
|
-
currentY = targetY;
|
|
586
|
-
hasBeenRenderedOnce = true;
|
|
587
|
-
render2();
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
startAnimation();
|
|
591
|
-
};
|
|
592
578
|
solidJs.createEffect(() => {
|
|
593
579
|
setupCanvas();
|
|
594
580
|
render2();
|
|
@@ -599,14 +585,12 @@ var Crosshair = (props) => {
|
|
|
599
585
|
window.addEventListener("resize", handleResize);
|
|
600
586
|
solidJs.onCleanup(() => {
|
|
601
587
|
window.removeEventListener("resize", handleResize);
|
|
602
|
-
if (animationFrameId !== null) {
|
|
603
|
-
cancelAnimationFrame(animationFrameId);
|
|
604
|
-
animationFrameId = null;
|
|
605
|
-
}
|
|
606
588
|
});
|
|
607
589
|
});
|
|
608
590
|
solidJs.createEffect(() => {
|
|
609
|
-
|
|
591
|
+
position.x();
|
|
592
|
+
position.y();
|
|
593
|
+
render2();
|
|
610
594
|
});
|
|
611
595
|
return web.createComponent(solidJs.Show, {
|
|
612
596
|
get when() {
|
|
@@ -750,27 +734,62 @@ var ReactGrabRenderer = (props) => {
|
|
|
750
734
|
var isCapitalized = (value) => value.length > 0 && /^[A-Z]/.test(value);
|
|
751
735
|
|
|
752
736
|
// src/instrumentation.ts
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
737
|
+
var NEXT_INTERNAL_COMPONENT_NAMES = [
|
|
738
|
+
"InnerLayoutRouter",
|
|
739
|
+
"RedirectErrorBoundary",
|
|
740
|
+
"RedirectBoundary",
|
|
741
|
+
"HTTPAccessFallbackErrorBoundary",
|
|
742
|
+
"HTTPAccessFallbackBoundary",
|
|
743
|
+
"LoadingBoundary",
|
|
744
|
+
"ErrorBoundary",
|
|
745
|
+
"InnerScrollAndFocusHandler",
|
|
746
|
+
"ScrollAndFocusHandler",
|
|
747
|
+
"RenderFromTemplateContext",
|
|
748
|
+
"OuterLayoutRouter",
|
|
749
|
+
"body",
|
|
750
|
+
"html",
|
|
751
|
+
"RedirectErrorBoundary",
|
|
752
|
+
"RedirectBoundary",
|
|
753
|
+
"HTTPAccessFallbackErrorBoundary",
|
|
754
|
+
"HTTPAccessFallbackBoundary",
|
|
755
|
+
"DevRootHTTPAccessFallbackBoundary",
|
|
756
|
+
"AppDevOverlayErrorBoundary",
|
|
757
|
+
"AppDevOverlay",
|
|
758
|
+
"HotReload",
|
|
759
|
+
"Router",
|
|
760
|
+
"ErrorBoundaryHandler",
|
|
761
|
+
"ErrorBoundary",
|
|
762
|
+
"AppRouter",
|
|
763
|
+
"ServerRoot",
|
|
764
|
+
"SegmentStateProvider",
|
|
765
|
+
"RootErrorBoundary"
|
|
766
|
+
];
|
|
767
|
+
var checkIsNextProject = () => {
|
|
768
|
+
return Boolean(document.getElementById("__NEXT_DATA__"));
|
|
769
|
+
};
|
|
770
|
+
var checkIsInternalComponentName = (name) => {
|
|
771
|
+
if (name.startsWith("_")) return true;
|
|
772
|
+
if (NEXT_INTERNAL_COMPONENT_NAMES.includes(name)) return true;
|
|
773
|
+
return false;
|
|
760
774
|
};
|
|
761
|
-
var
|
|
762
|
-
|
|
763
|
-
|
|
775
|
+
var checkIsSourceComponentName = (name) => {
|
|
776
|
+
if (checkIsInternalComponentName(name)) return false;
|
|
777
|
+
if (!isCapitalized(name)) return false;
|
|
778
|
+
if (name.startsWith("Primitive.")) return false;
|
|
779
|
+
if (name.includes("Provider") && name.includes("Context")) return false;
|
|
780
|
+
return true;
|
|
781
|
+
};
|
|
782
|
+
var getNearestComponentName = (element) => {
|
|
764
783
|
const fiber = bippy.getFiberFromHostInstance(element);
|
|
765
784
|
if (!fiber) return null;
|
|
766
|
-
let
|
|
785
|
+
let foundComponentName = null;
|
|
767
786
|
bippy.traverseFiber(
|
|
768
787
|
fiber,
|
|
769
788
|
(currentFiber) => {
|
|
770
789
|
if (bippy.isCompositeFiber(currentFiber)) {
|
|
771
790
|
const displayName = bippy.getDisplayName(currentFiber);
|
|
772
|
-
if (displayName &&
|
|
773
|
-
|
|
791
|
+
if (displayName && checkIsSourceComponentName(displayName)) {
|
|
792
|
+
foundComponentName = displayName;
|
|
774
793
|
return true;
|
|
775
794
|
}
|
|
776
795
|
}
|
|
@@ -778,231 +797,95 @@ var getNearestComponentDisplayName = (element) => {
|
|
|
778
797
|
},
|
|
779
798
|
true
|
|
780
799
|
);
|
|
781
|
-
return
|
|
782
|
-
};
|
|
783
|
-
var formatComponentSourceLocation = async (el) => {
|
|
784
|
-
const source$1 = await source.getSourceFromHostInstance(el);
|
|
785
|
-
if (!source$1) return null;
|
|
786
|
-
const fileName = source.normalizeFileName(source$1.fileName);
|
|
787
|
-
if (source.isSourceFile(fileName)) {
|
|
788
|
-
return `${fileName}:${source$1.lineNumber}:${source$1.columnNumber}`;
|
|
789
|
-
}
|
|
790
|
-
if (fileName && (fileName.includes(".tsx") || fileName.includes(".ts") || fileName.includes(".jsx") || fileName.includes(".js"))) {
|
|
791
|
-
const cleanedFileName = fileName.replace(/^webpack:\/\/_N_E\//, "").replace(/^webpack:\/\/\//, "").replace(/^webpack:\/\//, "").replace(/^\.\//, "");
|
|
792
|
-
if (cleanedFileName && !cleanedFileName.startsWith("node_modules") && !cleanedFileName.includes(".next") && !cleanedFileName.startsWith("webpack")) {
|
|
793
|
-
return `${cleanedFileName}:${source$1.lineNumber}:${source$1.columnNumber}`;
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
return null;
|
|
800
|
+
return foundComponentName;
|
|
797
801
|
};
|
|
798
|
-
var
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
if (el.id) return true;
|
|
813
|
-
if (el.className && typeof el.className === "string") {
|
|
814
|
-
const classes = el.className.trim();
|
|
815
|
-
if (classes && classes.length > 0) return true;
|
|
816
|
-
}
|
|
817
|
-
return Array.from(el.attributes).some(
|
|
818
|
-
(attr) => attr.name.startsWith("data-")
|
|
819
|
-
);
|
|
820
|
-
};
|
|
821
|
-
const collectDistinguishingAncestors = (el, maxDepth = 10) => {
|
|
822
|
-
const ancestors2 = [];
|
|
823
|
-
let current = el.parentElement;
|
|
824
|
-
let depth = 0;
|
|
825
|
-
while (current && depth < maxDepth && current.tagName !== "BODY") {
|
|
826
|
-
if (hasDistinguishingFeatures(current)) {
|
|
827
|
-
ancestors2.push(current);
|
|
828
|
-
if (ancestors2.length >= 3) break;
|
|
829
|
-
}
|
|
830
|
-
current = current.parentElement;
|
|
831
|
-
depth++;
|
|
832
|
-
}
|
|
833
|
-
return ancestors2.reverse();
|
|
834
|
-
};
|
|
835
|
-
const formatElementOpeningTag = (el, compact = false) => {
|
|
836
|
-
const tagName = el.tagName.toLowerCase();
|
|
837
|
-
const attrs = [];
|
|
838
|
-
if (el.id) {
|
|
839
|
-
attrs.push(`id="${el.id}"`);
|
|
840
|
-
}
|
|
841
|
-
if (el.className && typeof el.className === "string") {
|
|
842
|
-
const classes = el.className.trim().split(/\s+/);
|
|
843
|
-
if (classes.length > 0 && classes[0]) {
|
|
844
|
-
const displayClasses = compact ? classes.slice(0, 3) : classes;
|
|
845
|
-
const classStr = truncateString(displayClasses.join(" "), 30);
|
|
846
|
-
attrs.push(`class="${classStr}"`);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
const dataAttrs = Array.from(el.attributes).filter(
|
|
850
|
-
(attr) => attr.name.startsWith("data-")
|
|
851
|
-
);
|
|
852
|
-
const displayDataAttrs = compact ? dataAttrs.slice(0, 1) : dataAttrs;
|
|
853
|
-
for (const attr of displayDataAttrs) {
|
|
854
|
-
attrs.push(`${attr.name}="${truncateString(attr.value, 20)}"`);
|
|
855
|
-
}
|
|
856
|
-
const ariaLabel = el.getAttribute("aria-label");
|
|
857
|
-
if (ariaLabel && !compact) {
|
|
858
|
-
attrs.push(`aria-label="${truncateString(ariaLabel, 20)}"`);
|
|
859
|
-
}
|
|
860
|
-
return attrs.length > 0 ? `<${tagName} ${attrs.join(" ")}>` : `<${tagName}>`;
|
|
861
|
-
};
|
|
862
|
-
const formatElementClosingTag = (el) => `</${el.tagName.toLowerCase()}>`;
|
|
863
|
-
const extractTruncatedTextContent = (el) => {
|
|
864
|
-
const text = (el.textContent || "").trim().replace(/\s+/g, " ");
|
|
865
|
-
return truncateString(text, 60);
|
|
866
|
-
};
|
|
867
|
-
const extractSiblingIdentifier = (el) => {
|
|
868
|
-
if (el.id) return `#${el.id}`;
|
|
869
|
-
if (el.className && typeof el.className === "string") {
|
|
870
|
-
const classes = el.className.trim().split(/\s+/);
|
|
871
|
-
if (classes.length > 0 && classes[0]) {
|
|
872
|
-
return `.${classes[0]}`;
|
|
802
|
+
var getStack = async (element) => {
|
|
803
|
+
const maybeFiber = bippy.getFiberFromHostInstance(element);
|
|
804
|
+
if (!maybeFiber || !bippy.isFiber(maybeFiber)) return [];
|
|
805
|
+
const fiber = bippy.getLatestFiber(maybeFiber);
|
|
806
|
+
const unresolvedStack = [];
|
|
807
|
+
bippy.traverseFiber(
|
|
808
|
+
fiber,
|
|
809
|
+
(currentFiber) => {
|
|
810
|
+
const displayName = bippy.isHostFiber(currentFiber) ? typeof currentFiber.type === "string" ? currentFiber.type : null : bippy.getDisplayName(currentFiber);
|
|
811
|
+
if (displayName && !checkIsInternalComponentName(displayName)) {
|
|
812
|
+
unresolvedStack.push({
|
|
813
|
+
name: displayName,
|
|
814
|
+
sourcePromise: source.getSource(currentFiber)
|
|
815
|
+
});
|
|
873
816
|
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
};
|
|
877
|
-
const lines = [];
|
|
878
|
-
const selector = generateCSSSelector(element);
|
|
879
|
-
lines.push(`- selector: ${selector}`);
|
|
880
|
-
const rect = element.getBoundingClientRect();
|
|
881
|
-
lines.push(`- width: ${Math.round(rect.width)}`);
|
|
882
|
-
lines.push(`- height: ${Math.round(rect.height)}`);
|
|
883
|
-
lines.push("HTML snippet:");
|
|
884
|
-
lines.push("```html");
|
|
885
|
-
const ancestors = collectDistinguishingAncestors(element);
|
|
886
|
-
const ancestorComponents = ancestors.map(
|
|
887
|
-
(ancestor) => getNearestComponentDisplayName(ancestor)
|
|
817
|
+
},
|
|
818
|
+
true
|
|
888
819
|
);
|
|
889
|
-
const
|
|
890
|
-
|
|
891
|
-
|
|
820
|
+
const resolvedStack = await Promise.all(
|
|
821
|
+
unresolvedStack.map(async (frame) => ({
|
|
822
|
+
name: frame.name,
|
|
823
|
+
source: await frame.sourcePromise
|
|
824
|
+
}))
|
|
892
825
|
);
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
const isNewComponent = componentName && source && (i === 0 || ancestorComponents[i - 1] !== componentName);
|
|
902
|
-
if (isNewComponent) {
|
|
903
|
-
ancestorComponentIndents[i] = currentIndentLevel;
|
|
904
|
-
lines.push(
|
|
905
|
-
`${getIndent(currentIndentLevel)}<${componentName} used-at="${source}">`
|
|
906
|
-
);
|
|
907
|
-
currentIndentLevel++;
|
|
826
|
+
return resolvedStack.filter((frame) => frame.source !== null);
|
|
827
|
+
};
|
|
828
|
+
var formatStack = (stack) => {
|
|
829
|
+
const isNextProject = checkIsNextProject();
|
|
830
|
+
return stack.map(({ name, source: source$1 }) => {
|
|
831
|
+
if (!source$1) return ` at ${name}`;
|
|
832
|
+
if (source$1.fileName.startsWith("about://React/Server")) {
|
|
833
|
+
return ` at ${name} (Server)`;
|
|
908
834
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
currentIndentLevel++;
|
|
914
|
-
}
|
|
915
|
-
const parent = element.parentElement;
|
|
916
|
-
let targetIndex = -1;
|
|
917
|
-
if (parent) {
|
|
918
|
-
const siblings = Array.from(parent.children);
|
|
919
|
-
targetIndex = siblings.indexOf(element);
|
|
920
|
-
if (targetIndex > 0) {
|
|
921
|
-
const indent = getIndent(currentIndentLevel);
|
|
922
|
-
if (targetIndex <= 2) {
|
|
923
|
-
for (let i = 0; i < targetIndex; i++) {
|
|
924
|
-
const sibling = siblings[i];
|
|
925
|
-
const siblingId = extractSiblingIdentifier(sibling);
|
|
926
|
-
if (siblingId) {
|
|
927
|
-
lines.push(`${indent}${formatElementOpeningTag(sibling, true)}`);
|
|
928
|
-
lines.push(`${indent}</${sibling.tagName.toLowerCase()}>`);
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
} else {
|
|
932
|
-
lines.push(
|
|
933
|
-
`${indent}... (${targetIndex} element${targetIndex === 1 ? "" : "s"})`
|
|
934
|
-
);
|
|
935
|
-
}
|
|
835
|
+
if (!source.isSourceFile(source$1.fileName)) return ` at ${name}`;
|
|
836
|
+
const framePart = ` at ${name} in ${source.normalizeFileName(source$1.fileName)}`;
|
|
837
|
+
if (isNextProject) {
|
|
838
|
+
return `${framePart}:${source$1.lineNumber}:${source$1.columnNumber}`;
|
|
936
839
|
}
|
|
840
|
+
return framePart;
|
|
841
|
+
}).join("\n");
|
|
842
|
+
};
|
|
843
|
+
var getHTMLPreview = (element) => {
|
|
844
|
+
const tagName = element.tagName.toLowerCase();
|
|
845
|
+
if (!(element instanceof HTMLElement)) {
|
|
846
|
+
return `<${tagName} />`;
|
|
937
847
|
}
|
|
938
|
-
const
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
const
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
elementIndentLevel++;
|
|
947
|
-
}
|
|
948
|
-
const elementIndent = getIndent(elementIndentLevel);
|
|
949
|
-
lines.push(`${elementIndent}<!-- IMPORTANT: selected element -->`);
|
|
950
|
-
const textContent = extractTruncatedTextContent(element);
|
|
951
|
-
const childrenCount = element.children.length;
|
|
952
|
-
if (textContent && childrenCount === 0 && textContent.length < 40) {
|
|
953
|
-
lines.push(
|
|
954
|
-
`${elementIndent}${formatElementOpeningTag(element)}${textContent}${formatElementClosingTag(
|
|
955
|
-
element
|
|
956
|
-
)}`
|
|
957
|
-
);
|
|
958
|
-
} else {
|
|
959
|
-
lines.push(`${elementIndent}${formatElementOpeningTag(element)}`);
|
|
960
|
-
if (textContent) {
|
|
961
|
-
lines.push(`${elementIndent} ${textContent}`);
|
|
962
|
-
}
|
|
963
|
-
if (childrenCount > 0) {
|
|
964
|
-
lines.push(
|
|
965
|
-
`${elementIndent} ... (${childrenCount} element${childrenCount === 1 ? "" : "s"})`
|
|
966
|
-
);
|
|
848
|
+
const text = element.innerText?.trim() ?? element.textContent?.trim() ?? "";
|
|
849
|
+
let attrsText = "";
|
|
850
|
+
const attributes = Array.from(element.attributes);
|
|
851
|
+
for (const attribute of attributes) {
|
|
852
|
+
const name = attribute.name;
|
|
853
|
+
let value = attribute.value;
|
|
854
|
+
if (value.length > 20) {
|
|
855
|
+
value = `${value.slice(0, 20)}...`;
|
|
967
856
|
}
|
|
968
|
-
|
|
857
|
+
attrsText += ` ${name}="${value}"`;
|
|
969
858
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
const siblingId = extractSiblingIdentifier(sibling);
|
|
984
|
-
if (siblingId) {
|
|
985
|
-
lines.push(`${indent}${formatElementOpeningTag(sibling, true)}`);
|
|
986
|
-
lines.push(`${indent}</${sibling.tagName.toLowerCase()}>`);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
859
|
+
let topElements = 0;
|
|
860
|
+
let bottomElements = 0;
|
|
861
|
+
let foundFirstText = false;
|
|
862
|
+
const childNodes = Array.from(element.childNodes);
|
|
863
|
+
for (const node of childNodes) {
|
|
864
|
+
if (node.nodeType === Node.COMMENT_NODE) continue;
|
|
865
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
866
|
+
if (node.textContent && node.textContent.trim().length > 0) {
|
|
867
|
+
foundFirstText = true;
|
|
868
|
+
}
|
|
869
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
870
|
+
if (!foundFirstText) {
|
|
871
|
+
topElements++;
|
|
989
872
|
} else {
|
|
990
|
-
|
|
991
|
-
`${indent}... (${siblingsAfter} element${siblingsAfter === 1 ? "" : "s"})`
|
|
992
|
-
);
|
|
873
|
+
bottomElements++;
|
|
993
874
|
}
|
|
994
875
|
}
|
|
995
876
|
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
877
|
+
let content = "";
|
|
878
|
+
if (topElements > 0) content += `
|
|
879
|
+
(${topElements} elements)`;
|
|
880
|
+
if (text.length > 0) content += `
|
|
881
|
+
${text}`;
|
|
882
|
+
if (bottomElements > 0) content += `
|
|
883
|
+
(${bottomElements} elements)`;
|
|
884
|
+
if (content.length > 0) {
|
|
885
|
+
return `<${tagName}${attrsText}>${content}
|
|
886
|
+
</${tagName}>`;
|
|
1003
887
|
}
|
|
1004
|
-
|
|
1005
|
-
return lines.join("\n");
|
|
888
|
+
return `<${tagName}${attrsText} />`;
|
|
1006
889
|
};
|
|
1007
890
|
|
|
1008
891
|
// src/utils/copy-content.ts
|
|
@@ -1022,73 +905,13 @@ var waitForFocus = () => {
|
|
|
1022
905
|
var copyContent = async (content, onSuccess) => {
|
|
1023
906
|
await waitForFocus();
|
|
1024
907
|
try {
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
for (const contentPart of content) {
|
|
1028
|
-
if (typeof contentPart === "string") {
|
|
1029
|
-
const result = copyContentFallback(contentPart, onSuccess);
|
|
1030
|
-
if (!result) return result;
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
onSuccess?.();
|
|
1034
|
-
return true;
|
|
1035
|
-
}
|
|
1036
|
-
const mimeTypeMap = /* @__PURE__ */ new Map();
|
|
1037
|
-
for (const contentPart of content) {
|
|
1038
|
-
if (contentPart instanceof Blob) {
|
|
1039
|
-
const mimeType = contentPart.type || "text/plain";
|
|
1040
|
-
if (!mimeTypeMap.has(mimeType)) {
|
|
1041
|
-
mimeTypeMap.set(mimeType, contentPart);
|
|
1042
|
-
}
|
|
1043
|
-
} else {
|
|
1044
|
-
if (!mimeTypeMap.has("text/plain")) {
|
|
1045
|
-
mimeTypeMap.set(
|
|
1046
|
-
"text/plain",
|
|
1047
|
-
new Blob([contentPart], { type: "text/plain" })
|
|
1048
|
-
);
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
if (mimeTypeMap.size === 0) {
|
|
1053
|
-
const plainTextFallback = content.find(
|
|
1054
|
-
(contentPart) => typeof contentPart === "string"
|
|
1055
|
-
);
|
|
1056
|
-
if (typeof plainTextFallback === "string") {
|
|
1057
|
-
return copyContentFallback(plainTextFallback, onSuccess);
|
|
1058
|
-
}
|
|
1059
|
-
return false;
|
|
1060
|
-
}
|
|
1061
|
-
try {
|
|
1062
|
-
await navigator.clipboard.write([
|
|
1063
|
-
new ClipboardItem(Object.fromEntries(mimeTypeMap))
|
|
1064
|
-
]);
|
|
1065
|
-
onSuccess?.();
|
|
1066
|
-
return true;
|
|
1067
|
-
} catch {
|
|
1068
|
-
const plainTextParts = content.filter(
|
|
1069
|
-
(contentPart) => typeof contentPart === "string"
|
|
1070
|
-
);
|
|
1071
|
-
if (plainTextParts.length > 0) {
|
|
1072
|
-
const combinedText = plainTextParts.join("\n\n");
|
|
1073
|
-
return copyContentFallback(combinedText, onSuccess);
|
|
1074
|
-
}
|
|
1075
|
-
return false;
|
|
1076
|
-
}
|
|
1077
|
-
} else if (content instanceof Blob) {
|
|
1078
|
-
await navigator.clipboard.write([
|
|
1079
|
-
new ClipboardItem({ [content.type]: content })
|
|
1080
|
-
]);
|
|
908
|
+
try {
|
|
909
|
+
await navigator.clipboard.writeText(content);
|
|
1081
910
|
onSuccess?.();
|
|
1082
911
|
return true;
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
onSuccess?.();
|
|
1087
|
-
return true;
|
|
1088
|
-
} catch {
|
|
1089
|
-
const result = copyContentFallback(content, onSuccess);
|
|
1090
|
-
return result;
|
|
1091
|
-
}
|
|
912
|
+
} catch {
|
|
913
|
+
const result = copyContentFallback(content, onSuccess);
|
|
914
|
+
return result;
|
|
1092
915
|
}
|
|
1093
916
|
} catch {
|
|
1094
917
|
return false;
|
|
@@ -1177,13 +1000,27 @@ var getElementAtPosition = (clientX, clientY) => {
|
|
|
1177
1000
|
|
|
1178
1001
|
// src/utils/get-elements-in-drag.ts
|
|
1179
1002
|
var DRAG_COVERAGE_THRESHOLD = 0.75;
|
|
1003
|
+
var calculateIntersectionArea = (rect1, rect2) => {
|
|
1004
|
+
const intersectionLeft = Math.max(rect1.left, rect2.left);
|
|
1005
|
+
const intersectionTop = Math.max(rect1.top, rect2.top);
|
|
1006
|
+
const intersectionRight = Math.min(rect1.right, rect2.right);
|
|
1007
|
+
const intersectionBottom = Math.min(rect1.bottom, rect2.bottom);
|
|
1008
|
+
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
1009
|
+
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
1010
|
+
return intersectionWidth * intersectionHeight;
|
|
1011
|
+
};
|
|
1012
|
+
var hasIntersection = (rect1, rect2) => {
|
|
1013
|
+
return rect1.left < rect2.right && rect1.right > rect2.left && rect1.top < rect2.bottom && rect1.bottom > rect2.top;
|
|
1014
|
+
};
|
|
1180
1015
|
var filterElementsInDrag = (dragRect, isValidGrabbableElement2, shouldCheckCoverage) => {
|
|
1181
1016
|
const elements = [];
|
|
1182
1017
|
const allElements = Array.from(document.querySelectorAll("*"));
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1018
|
+
const dragBounds = {
|
|
1019
|
+
left: dragRect.x,
|
|
1020
|
+
top: dragRect.y,
|
|
1021
|
+
right: dragRect.x + dragRect.width,
|
|
1022
|
+
bottom: dragRect.y + dragRect.height
|
|
1023
|
+
};
|
|
1187
1024
|
for (const candidateElement of allElements) {
|
|
1188
1025
|
if (!shouldCheckCoverage) {
|
|
1189
1026
|
const tagName = (candidateElement.tagName || "").toUpperCase();
|
|
@@ -1193,26 +1030,21 @@ var filterElementsInDrag = (dragRect, isValidGrabbableElement2, shouldCheckCover
|
|
|
1193
1030
|
continue;
|
|
1194
1031
|
}
|
|
1195
1032
|
const elementRect = candidateElement.getBoundingClientRect();
|
|
1196
|
-
const
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1033
|
+
const elementBounds = {
|
|
1034
|
+
left: elementRect.left,
|
|
1035
|
+
top: elementRect.top,
|
|
1036
|
+
right: elementRect.left + elementRect.width,
|
|
1037
|
+
bottom: elementRect.top + elementRect.height
|
|
1038
|
+
};
|
|
1200
1039
|
if (shouldCheckCoverage) {
|
|
1201
|
-
const
|
|
1202
|
-
const intersectionTop = Math.max(dragTop, elementTop);
|
|
1203
|
-
const intersectionRight = Math.min(dragRight, elementRight);
|
|
1204
|
-
const intersectionBottom = Math.min(dragBottom, elementBottom);
|
|
1205
|
-
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
1206
|
-
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
1207
|
-
const intersectionArea = intersectionWidth * intersectionHeight;
|
|
1040
|
+
const intersectionArea = calculateIntersectionArea(dragBounds, elementBounds);
|
|
1208
1041
|
const elementArea = Math.max(0, elementRect.width * elementRect.height);
|
|
1209
1042
|
const hasMajorityCoverage = elementArea > 0 && intersectionArea / elementArea >= DRAG_COVERAGE_THRESHOLD;
|
|
1210
1043
|
if (hasMajorityCoverage) {
|
|
1211
1044
|
elements.push(candidateElement);
|
|
1212
1045
|
}
|
|
1213
1046
|
} else {
|
|
1214
|
-
|
|
1215
|
-
if (hasIntersection) {
|
|
1047
|
+
if (hasIntersection(elementBounds, dragBounds)) {
|
|
1216
1048
|
elements.push(candidateElement);
|
|
1217
1049
|
}
|
|
1218
1050
|
}
|
|
@@ -1251,70 +1083,7 @@ var createElementBounds = (element) => {
|
|
|
1251
1083
|
};
|
|
1252
1084
|
};
|
|
1253
1085
|
|
|
1254
|
-
// src/utils/is-localhost.ts
|
|
1255
|
-
var isLocalhost = () => {
|
|
1256
|
-
const hostname = window.location.hostname;
|
|
1257
|
-
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
1258
|
-
};
|
|
1259
|
-
var turndownService = null;
|
|
1260
|
-
var getTurndownService = () => {
|
|
1261
|
-
if (!turndownService) {
|
|
1262
|
-
turndownService = new TurndownService__default.default({
|
|
1263
|
-
headingStyle: "atx",
|
|
1264
|
-
codeBlockStyle: "fenced",
|
|
1265
|
-
emDelimiter: "_",
|
|
1266
|
-
bulletListMarker: "-",
|
|
1267
|
-
linkStyle: "inlined",
|
|
1268
|
-
linkReferenceStyle: "full"
|
|
1269
|
-
});
|
|
1270
|
-
turndownService.addRule("strikethrough", {
|
|
1271
|
-
filter: ["del", "s"],
|
|
1272
|
-
replacement: (content) => `~~${content}~~`
|
|
1273
|
-
});
|
|
1274
|
-
turndownService.addRule("removeHidden", {
|
|
1275
|
-
filter: (node) => {
|
|
1276
|
-
if (node instanceof HTMLElement) {
|
|
1277
|
-
const style = window.getComputedStyle(node);
|
|
1278
|
-
return style.display === "none" || style.visibility === "hidden" || style.opacity === "0";
|
|
1279
|
-
}
|
|
1280
|
-
return false;
|
|
1281
|
-
},
|
|
1282
|
-
replacement: () => ""
|
|
1283
|
-
});
|
|
1284
|
-
turndownService.addRule("preserveButtons", {
|
|
1285
|
-
filter: ["button"],
|
|
1286
|
-
replacement: (content) => content ? `[${content}]` : ""
|
|
1287
|
-
});
|
|
1288
|
-
turndownService.addRule("preserveInputs", {
|
|
1289
|
-
filter: (node) => {
|
|
1290
|
-
if (node.nodeName === "INPUT" && node instanceof HTMLInputElement) {
|
|
1291
|
-
return true;
|
|
1292
|
-
}
|
|
1293
|
-
return false;
|
|
1294
|
-
},
|
|
1295
|
-
replacement: (_, node) => {
|
|
1296
|
-
if (node instanceof HTMLInputElement) {
|
|
1297
|
-
const value = node.value || node.placeholder;
|
|
1298
|
-
return value ? `[${value}]` : "";
|
|
1299
|
-
}
|
|
1300
|
-
return "";
|
|
1301
|
-
}
|
|
1302
|
-
});
|
|
1303
|
-
}
|
|
1304
|
-
return turndownService;
|
|
1305
|
-
};
|
|
1306
|
-
var htmlToMarkdown = (html) => {
|
|
1307
|
-
const service = getTurndownService();
|
|
1308
|
-
return service.turndown(html).trim();
|
|
1309
|
-
};
|
|
1310
|
-
var elementToMarkdown = (element) => {
|
|
1311
|
-
const clonedElement = element.cloneNode(true);
|
|
1312
|
-
const service = getTurndownService();
|
|
1313
|
-
return service.turndown(clonedElement).trim();
|
|
1314
|
-
};
|
|
1315
|
-
|
|
1316
1086
|
// src/core.tsx
|
|
1317
|
-
var PROGRESS_INDICATOR_DELAY_MS = 150;
|
|
1318
1087
|
var init = (rawOptions) => {
|
|
1319
1088
|
const options = {
|
|
1320
1089
|
enabled: true,
|
|
@@ -1337,7 +1106,6 @@ var init = (rawOptions) => {
|
|
|
1337
1106
|
};
|
|
1338
1107
|
}
|
|
1339
1108
|
return solidJs.createRoot((dispose) => {
|
|
1340
|
-
const OFFSCREEN_POSITION = -1e3;
|
|
1341
1109
|
const [isHoldingKeys, setIsHoldingKeys] = solidJs.createSignal(false);
|
|
1342
1110
|
const [mouseX, setMouseX] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
1343
1111
|
const [mouseY, setMouseY] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
@@ -1347,7 +1115,7 @@ var init = (rawOptions) => {
|
|
|
1347
1115
|
const [isCopying, setIsCopying] = solidJs.createSignal(false);
|
|
1348
1116
|
const [lastGrabbedElement, setLastGrabbedElement] = solidJs.createSignal(null);
|
|
1349
1117
|
const [progressStartTime, setProgressStartTime] = solidJs.createSignal(null);
|
|
1350
|
-
const [
|
|
1118
|
+
const [progress, setProgress] = solidJs.createSignal(0);
|
|
1351
1119
|
const [grabbedBoxes, setGrabbedBoxes] = solidJs.createSignal([]);
|
|
1352
1120
|
const [successLabels, setSuccessLabels] = solidJs.createSignal([]);
|
|
1353
1121
|
const [isActivated, setIsActivated] = solidJs.createSignal(false);
|
|
@@ -1394,55 +1162,10 @@ var init = (rawOptions) => {
|
|
|
1394
1162
|
const wrapInSelectedElementTags = (context) => `<selected_element>
|
|
1395
1163
|
${context}
|
|
1396
1164
|
</selected_element>`;
|
|
1397
|
-
const extractRelevantComputedStyles = (element) => {
|
|
1398
|
-
const computed = window.getComputedStyle(element);
|
|
1399
|
-
const rect = element.getBoundingClientRect();
|
|
1400
|
-
return {
|
|
1401
|
-
width: `${Math.round(rect.width)}px`,
|
|
1402
|
-
height: `${Math.round(rect.height)}px`,
|
|
1403
|
-
paddingTop: computed.paddingTop,
|
|
1404
|
-
paddingRight: computed.paddingRight,
|
|
1405
|
-
paddingBottom: computed.paddingBottom,
|
|
1406
|
-
paddingLeft: computed.paddingLeft,
|
|
1407
|
-
background: computed.background,
|
|
1408
|
-
opacity: computed.opacity
|
|
1409
|
-
};
|
|
1410
|
-
};
|
|
1411
|
-
const createStructuredClipboardHtmlBlob = (elements) => {
|
|
1412
|
-
const structuredData = {
|
|
1413
|
-
elements: elements.map((element) => ({
|
|
1414
|
-
tagName: element.tagName,
|
|
1415
|
-
content: element.content,
|
|
1416
|
-
computedStyles: element.computedStyles
|
|
1417
|
-
}))
|
|
1418
|
-
};
|
|
1419
|
-
const jsonString = JSON.stringify(structuredData);
|
|
1420
|
-
const base64Data = btoa(encodeURIComponent(jsonString).replace(/%([0-9A-F]{2})/g, (_match, p1) => String.fromCharCode(parseInt(p1, 16))));
|
|
1421
|
-
const htmlContent = `<div data-react-grab="${base64Data}"></div>`;
|
|
1422
|
-
return new Blob([htmlContent], {
|
|
1423
|
-
type: "text/html"
|
|
1424
|
-
});
|
|
1425
|
-
};
|
|
1426
1165
|
const extractElementTagName = (element) => (element.tagName || "").toLowerCase();
|
|
1427
|
-
const extractNearestComponentName = (element) => {
|
|
1428
|
-
const fiber = bippy.getFiberFromHostInstance(element);
|
|
1429
|
-
if (!fiber) return null;
|
|
1430
|
-
let componentName = null;
|
|
1431
|
-
bippy.traverseFiber(fiber, (currentFiber) => {
|
|
1432
|
-
if (bippy.isCompositeFiber(currentFiber)) {
|
|
1433
|
-
const displayName = bippy.getDisplayName(currentFiber);
|
|
1434
|
-
if (displayName && isCapitalized(displayName) && !displayName.startsWith("_") && !displayName.startsWith("Primitive.")) {
|
|
1435
|
-
componentName = displayName;
|
|
1436
|
-
return true;
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1439
|
-
return false;
|
|
1440
|
-
}, true);
|
|
1441
|
-
return componentName;
|
|
1442
|
-
};
|
|
1443
1166
|
const extractElementLabelText = (element) => {
|
|
1444
1167
|
const tagName = extractElementTagName(element);
|
|
1445
|
-
const componentName =
|
|
1168
|
+
const componentName = getNearestComponentName(element);
|
|
1446
1169
|
if (tagName && componentName) {
|
|
1447
1170
|
return `<${tagName}> in ${componentName}`;
|
|
1448
1171
|
}
|
|
@@ -1464,8 +1187,6 @@ ${context}
|
|
|
1464
1187
|
} catch {
|
|
1465
1188
|
}
|
|
1466
1189
|
};
|
|
1467
|
-
const isExtensionEnvironment = () => window.__REACT_GRAB_EXTENSION_ACTIVE__ === true || options.isExtension === true;
|
|
1468
|
-
const isExtensionTextOnlyMode = () => isExtensionEnvironment() && !isLocalhost();
|
|
1469
1190
|
const executeCopyOperation = async (positionX, positionY, operation) => {
|
|
1470
1191
|
setCopyStartX(positionX);
|
|
1471
1192
|
setCopyStartY(positionY);
|
|
@@ -1491,39 +1212,37 @@ ${context}
|
|
|
1491
1212
|
return element.textContent ?? "";
|
|
1492
1213
|
};
|
|
1493
1214
|
const createCombinedTextContent = (elements) => elements.map((element) => extractElementTextContent(element).trim()).filter((textContent) => textContent.length > 0).join("\n\n");
|
|
1494
|
-
const
|
|
1495
|
-
const copySingleElementToClipboard = async (targetElement2) => {
|
|
1496
|
-
showTemporaryGrabbedBox(createElementBounds(targetElement2));
|
|
1497
|
-
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
1215
|
+
const tryCopyWithFallback = async (elements) => {
|
|
1498
1216
|
let didCopy = false;
|
|
1499
1217
|
try {
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
const plainTextContent = wrapInSelectedElementTags(
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
if (!didCopy) {
|
|
1515
|
-
const plainTextContentOnly = createCombinedTextContent([targetElement2]);
|
|
1516
|
-
if (plainTextContentOnly.length > 0) {
|
|
1517
|
-
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1518
|
-
}
|
|
1218
|
+
const elementSnippetResults = await Promise.allSettled(elements.map(async (element) => `## HTML Frame:
|
|
1219
|
+
${getHTMLPreview(element)}
|
|
1220
|
+
|
|
1221
|
+
## Code Location:
|
|
1222
|
+
${formatStack(await getStack(element))}`));
|
|
1223
|
+
const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
|
|
1224
|
+
if (elementSnippets.length > 0) {
|
|
1225
|
+
const plainTextContent = elementSnippets.map((snippet) => wrapInSelectedElementTags(snippet)).join("\n\n");
|
|
1226
|
+
didCopy = await copyContent(plainTextContent, options.playCopySound ? playCopySound : void 0);
|
|
1227
|
+
}
|
|
1228
|
+
if (!didCopy) {
|
|
1229
|
+
const plainTextContentOnly = createCombinedTextContent(elements);
|
|
1230
|
+
if (plainTextContentOnly.length > 0) {
|
|
1231
|
+
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1519
1232
|
}
|
|
1520
1233
|
}
|
|
1521
1234
|
} catch {
|
|
1522
|
-
const plainTextContentOnly = createCombinedTextContent(
|
|
1235
|
+
const plainTextContentOnly = createCombinedTextContent(elements);
|
|
1523
1236
|
if (plainTextContentOnly.length > 0) {
|
|
1524
1237
|
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1525
1238
|
}
|
|
1526
1239
|
}
|
|
1240
|
+
return didCopy;
|
|
1241
|
+
};
|
|
1242
|
+
const copySingleElementToClipboard = async (targetElement2) => {
|
|
1243
|
+
showTemporaryGrabbedBox(createElementBounds(targetElement2));
|
|
1244
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
1245
|
+
const didCopy = await tryCopyWithFallback([targetElement2]);
|
|
1527
1246
|
if (didCopy) {
|
|
1528
1247
|
showTemporarySuccessLabel(extractElementLabelText(targetElement2));
|
|
1529
1248
|
}
|
|
@@ -1535,40 +1254,7 @@ ${context}
|
|
|
1535
1254
|
showTemporaryGrabbedBox(createElementBounds(element));
|
|
1536
1255
|
}
|
|
1537
1256
|
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
1538
|
-
|
|
1539
|
-
try {
|
|
1540
|
-
if (isExtensionTextOnlyMode()) {
|
|
1541
|
-
const markdownContent = createCombinedMarkdownContent(targetElements);
|
|
1542
|
-
if (markdownContent.length > 0) {
|
|
1543
|
-
didCopy = await copyContent(markdownContent, options.playCopySound ? playCopySound : void 0);
|
|
1544
|
-
}
|
|
1545
|
-
} else {
|
|
1546
|
-
const elementSnippetResults = await Promise.allSettled(targetElements.map((element) => getHTMLSnippet(element)));
|
|
1547
|
-
const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
|
|
1548
|
-
if (elementSnippets.length > 0) {
|
|
1549
|
-
const plainTextContent = elementSnippets.map((snippet) => wrapInSelectedElementTags(snippet)).join("\n\n");
|
|
1550
|
-
const structuredElements = elementSnippets.map((content, elementIndex) => ({
|
|
1551
|
-
tagName: extractElementTagName(targetElements[elementIndex]),
|
|
1552
|
-
content,
|
|
1553
|
-
computedStyles: extractRelevantComputedStyles(targetElements[elementIndex])
|
|
1554
|
-
}));
|
|
1555
|
-
const htmlContent = createStructuredClipboardHtmlBlob(structuredElements);
|
|
1556
|
-
didCopy = await copyContent([plainTextContent, htmlContent], options.playCopySound ? playCopySound : void 0);
|
|
1557
|
-
if (!didCopy) {
|
|
1558
|
-
const plainTextContentOnly = createCombinedTextContent(targetElements);
|
|
1559
|
-
if (plainTextContentOnly.length > 0) {
|
|
1560
|
-
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
} else {
|
|
1564
|
-
const plainTextContentOnly = createCombinedTextContent(targetElements);
|
|
1565
|
-
if (plainTextContentOnly.length > 0) {
|
|
1566
|
-
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
} catch {
|
|
1571
|
-
}
|
|
1257
|
+
const didCopy = await tryCopyWithFallback(targetElements);
|
|
1572
1258
|
if (didCopy) {
|
|
1573
1259
|
showTemporarySuccessLabel(`${targetElements.length} elements`);
|
|
1574
1260
|
}
|
|
@@ -1592,7 +1278,6 @@ ${context}
|
|
|
1592
1278
|
y: elementBounds.top
|
|
1593
1279
|
};
|
|
1594
1280
|
});
|
|
1595
|
-
const DRAG_THRESHOLD_PX = 2;
|
|
1596
1281
|
const calculateDragDistance = (endX, endY) => ({
|
|
1597
1282
|
x: Math.abs(endX - dragStartX()),
|
|
1598
1283
|
y: Math.abs(endY - dragStartY())
|
|
@@ -1650,30 +1335,23 @@ ${context}
|
|
|
1650
1335
|
setLastGrabbedElement(null);
|
|
1651
1336
|
}
|
|
1652
1337
|
}));
|
|
1653
|
-
const progress = solidJs.createMemo(() => {
|
|
1654
|
-
const startTime = progressStartTime();
|
|
1655
|
-
progressTick();
|
|
1656
|
-
if (startTime === null) return 0;
|
|
1657
|
-
const elapsedTime = Date.now() - startTime;
|
|
1658
|
-
const normalizedTime = elapsedTime / options.keyHoldDuration;
|
|
1659
|
-
const easedProgress = 1 - Math.exp(-normalizedTime);
|
|
1660
|
-
const maxProgressBeforeCompletion = 0.95;
|
|
1661
|
-
if (isCopying()) {
|
|
1662
|
-
return Math.min(easedProgress, maxProgressBeforeCompletion);
|
|
1663
|
-
}
|
|
1664
|
-
return 1;
|
|
1665
|
-
});
|
|
1666
1338
|
const startProgressAnimation = () => {
|
|
1667
|
-
|
|
1339
|
+
const startTime = Date.now();
|
|
1340
|
+
setProgressStartTime(startTime);
|
|
1668
1341
|
setShowProgressIndicator(false);
|
|
1669
1342
|
progressDelayTimerId = window.setTimeout(() => {
|
|
1670
1343
|
setShowProgressIndicator(true);
|
|
1671
1344
|
progressDelayTimerId = null;
|
|
1672
1345
|
}, PROGRESS_INDICATOR_DELAY_MS);
|
|
1673
1346
|
const animateProgress = () => {
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
const
|
|
1347
|
+
const currentStartTime = progressStartTime();
|
|
1348
|
+
if (currentStartTime === null) return;
|
|
1349
|
+
const elapsedTime = Date.now() - currentStartTime;
|
|
1350
|
+
const normalizedTime = elapsedTime / options.keyHoldDuration;
|
|
1351
|
+
const easedProgress = 1 - Math.exp(-normalizedTime);
|
|
1352
|
+
const maxProgressBeforeCompletion = 0.95;
|
|
1353
|
+
const currentProgress = isCopying() ? Math.min(easedProgress, maxProgressBeforeCompletion) : 1;
|
|
1354
|
+
setProgress(currentProgress);
|
|
1677
1355
|
if (currentProgress < 1) {
|
|
1678
1356
|
progressAnimationId = requestAnimationFrame(animateProgress);
|
|
1679
1357
|
}
|
|
@@ -1690,6 +1368,7 @@ ${context}
|
|
|
1690
1368
|
progressDelayTimerId = null;
|
|
1691
1369
|
}
|
|
1692
1370
|
setProgressStartTime(null);
|
|
1371
|
+
setProgress(1);
|
|
1693
1372
|
setShowProgressIndicator(false);
|
|
1694
1373
|
};
|
|
1695
1374
|
const activateRenderer = () => {
|
|
@@ -1930,7 +1609,7 @@ ${context}
|
|
|
1930
1609
|
get labelVisible() {
|
|
1931
1610
|
return labelVisible();
|
|
1932
1611
|
},
|
|
1933
|
-
labelZIndex:
|
|
1612
|
+
labelZIndex: Z_INDEX_LABEL,
|
|
1934
1613
|
get progressVisible() {
|
|
1935
1614
|
return progressVisible();
|
|
1936
1615
|
},
|
|
@@ -1976,13 +1655,8 @@ ${context}
|
|
|
1976
1655
|
// src/index.ts
|
|
1977
1656
|
var globalApi = null;
|
|
1978
1657
|
var getGlobalApi = () => globalApi;
|
|
1979
|
-
|
|
1980
|
-
if (!window[EXTENSION_MARKER]) {
|
|
1981
|
-
globalApi = init();
|
|
1982
|
-
}
|
|
1658
|
+
globalApi = init();
|
|
1983
1659
|
|
|
1984
|
-
exports.elementToMarkdown = elementToMarkdown;
|
|
1985
1660
|
exports.getGlobalApi = getGlobalApi;
|
|
1986
|
-
exports.htmlToMarkdown = htmlToMarkdown;
|
|
1987
1661
|
exports.init = init;
|
|
1988
1662
|
exports.playCopySound = playCopySound;
|