react-grab 0.0.40 → 0.0.42
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 +395 -698
- package/dist/index.d.cts +2 -15
- package/dist/index.d.ts +2 -15
- package/dist/index.global.js +32 -87
- package/dist/index.js +397 -694
- package/package.json +3 -8
package/dist/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
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
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { finder } from '@medv/finder';
|
|
6
|
-
import TurndownService from 'turndown';
|
|
3
|
+
import { getFiberFromHostInstance, traverseFiber, isCompositeFiber, getDisplayName, isFiber, getLatestFiber, isHostFiber } from 'bippy';
|
|
4
|
+
import { isSourceFile, normalizeFileName, getSource } from 'bippy/source';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* @license MIT
|
|
@@ -95,8 +93,12 @@ var mountRoot = () => {
|
|
|
95
93
|
var VIEWPORT_MARGIN_PX = 8;
|
|
96
94
|
var INDICATOR_CLAMP_PADDING_PX = 4;
|
|
97
95
|
var CURSOR_OFFSET_PX = 14;
|
|
96
|
+
var OFFSCREEN_POSITION = -1e3;
|
|
98
97
|
var SELECTION_LERP_FACTOR = 0.95;
|
|
99
98
|
var SUCCESS_LABEL_DURATION_MS = 1700;
|
|
99
|
+
var PROGRESS_INDICATOR_DELAY_MS = 150;
|
|
100
|
+
var DRAG_THRESHOLD_PX = 2;
|
|
101
|
+
var Z_INDEX_LABEL = 2147483647;
|
|
100
102
|
|
|
101
103
|
// src/utils/lerp.ts
|
|
102
104
|
var lerp = (start, end, factor) => {
|
|
@@ -261,30 +263,22 @@ var getClampedElementPosition = (positionLeft, positionTop, elementWidth, elemen
|
|
|
261
263
|
const clampedTop = Math.max(minTop, Math.min(positionTop, maxTop));
|
|
262
264
|
return { left: clampedLeft, top: clampedTop };
|
|
263
265
|
};
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
var _tmpl$6 = /* @__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">`);
|
|
272
|
-
var Label = (props) => {
|
|
273
|
-
const [opacity, setOpacity] = createSignal(0);
|
|
274
|
-
const [positionTick, setPositionTick] = createSignal(0);
|
|
275
|
-
let labelRef;
|
|
276
|
-
let currentX = props.x;
|
|
277
|
-
let currentY = props.y;
|
|
278
|
-
let targetX = props.x;
|
|
279
|
-
let targetY = props.y;
|
|
266
|
+
var useAnimatedPosition = (options) => {
|
|
267
|
+
const lerpFactor = options.lerpFactor ?? 0.3;
|
|
268
|
+
const convergenceThreshold = options.convergenceThreshold ?? 0.5;
|
|
269
|
+
const [x, setX] = createSignal(options.x());
|
|
270
|
+
const [y, setY] = createSignal(options.y());
|
|
271
|
+
let targetX = options.x();
|
|
272
|
+
let targetY = options.y();
|
|
280
273
|
let animationFrameId = null;
|
|
281
274
|
let hasBeenRenderedOnce = false;
|
|
282
275
|
const animate = () => {
|
|
283
|
-
currentX = lerp(
|
|
284
|
-
currentY = lerp(
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
276
|
+
const currentX = lerp(x(), targetX, lerpFactor);
|
|
277
|
+
const currentY = lerp(y(), targetY, lerpFactor);
|
|
278
|
+
setX(currentX);
|
|
279
|
+
setY(currentY);
|
|
280
|
+
const hasConverged = Math.abs(currentX - targetX) < convergenceThreshold && Math.abs(currentY - targetY) < convergenceThreshold;
|
|
281
|
+
if (!hasConverged) {
|
|
288
282
|
animationFrameId = requestAnimationFrame(animate);
|
|
289
283
|
} else {
|
|
290
284
|
animationFrameId = null;
|
|
@@ -294,36 +288,16 @@ var Label = (props) => {
|
|
|
294
288
|
if (animationFrameId !== null) return;
|
|
295
289
|
animationFrameId = requestAnimationFrame(animate);
|
|
296
290
|
};
|
|
297
|
-
|
|
298
|
-
targetX =
|
|
299
|
-
targetY =
|
|
291
|
+
createEffect(() => {
|
|
292
|
+
targetX = options.x();
|
|
293
|
+
targetY = options.y();
|
|
300
294
|
if (!hasBeenRenderedOnce) {
|
|
301
|
-
|
|
302
|
-
|
|
295
|
+
setX(targetX);
|
|
296
|
+
setY(targetY);
|
|
303
297
|
hasBeenRenderedOnce = true;
|
|
304
|
-
setPositionTick((tick) => tick + 1);
|
|
305
298
|
return;
|
|
306
299
|
}
|
|
307
300
|
startAnimation();
|
|
308
|
-
};
|
|
309
|
-
createEffect(on(() => props.visible, (visible) => {
|
|
310
|
-
if (visible !== false) {
|
|
311
|
-
requestAnimationFrame(() => {
|
|
312
|
-
setOpacity(1);
|
|
313
|
-
});
|
|
314
|
-
} else {
|
|
315
|
-
setOpacity(0);
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
if (props.variant === "success") {
|
|
319
|
-
const fadeOutTimer = setTimeout(() => {
|
|
320
|
-
setOpacity(0);
|
|
321
|
-
}, SUCCESS_LABEL_DURATION_MS);
|
|
322
|
-
onCleanup(() => clearTimeout(fadeOutTimer));
|
|
323
|
-
}
|
|
324
|
-
}));
|
|
325
|
-
createEffect(() => {
|
|
326
|
-
updateTarget();
|
|
327
301
|
});
|
|
328
302
|
onCleanup(() => {
|
|
329
303
|
if (animationFrameId !== null) {
|
|
@@ -331,34 +305,91 @@ var Label = (props) => {
|
|
|
331
305
|
animationFrameId = null;
|
|
332
306
|
}
|
|
333
307
|
});
|
|
308
|
+
return { x, y };
|
|
309
|
+
};
|
|
310
|
+
var useFadeInOut = (options) => {
|
|
311
|
+
const [opacity, setOpacity] = createSignal(0);
|
|
312
|
+
createEffect(
|
|
313
|
+
on(
|
|
314
|
+
() => options.visible,
|
|
315
|
+
(isVisible) => {
|
|
316
|
+
if (isVisible !== false) {
|
|
317
|
+
requestAnimationFrame(() => {
|
|
318
|
+
setOpacity(1);
|
|
319
|
+
});
|
|
320
|
+
} else {
|
|
321
|
+
setOpacity(0);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (options.autoFadeOutAfter !== void 0) {
|
|
325
|
+
const fadeOutTimer = setTimeout(() => {
|
|
326
|
+
setOpacity(0);
|
|
327
|
+
}, options.autoFadeOutAfter);
|
|
328
|
+
onCleanup(() => clearTimeout(fadeOutTimer));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
)
|
|
332
|
+
);
|
|
333
|
+
return opacity;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
// src/utils/get-cursor-quadrants.ts
|
|
337
|
+
var getCursorQuadrants = (cursorX, cursorY, elementWidth, elementHeight, offset) => {
|
|
338
|
+
return [
|
|
339
|
+
{
|
|
340
|
+
left: Math.round(cursorX) + offset,
|
|
341
|
+
top: Math.round(cursorY) + offset
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
left: Math.round(cursorX) - elementWidth - offset,
|
|
345
|
+
top: Math.round(cursorY) + offset
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
left: Math.round(cursorX) + offset,
|
|
349
|
+
top: Math.round(cursorY) - elementHeight - offset
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
left: Math.round(cursorX) - elementWidth - offset,
|
|
353
|
+
top: Math.round(cursorY) - elementHeight - offset
|
|
354
|
+
}
|
|
355
|
+
];
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// src/components/label.tsx
|
|
359
|
+
var _tmpl$3 = /* @__PURE__ */ template(`<div style="position:absolute;top:0;left:0;bottom:0;background-color:rgba(178, 28, 142, 0.2);border-radius:3px;transition:width 0.1s ease-out;pointer-events:none">`);
|
|
360
|
+
var _tmpl$22 = /* @__PURE__ */ template(`<span style=display:inline-block;margin-right:4px;font-weight:600>\u2713`);
|
|
361
|
+
var _tmpl$32 = /* @__PURE__ */ template(`<div style=margin-right:4px>Copied`);
|
|
362
|
+
var _tmpl$4 = /* @__PURE__ */ template(`<span style="font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;font-variant-numeric:tabular-nums;vertical-align:middle">`);
|
|
363
|
+
var _tmpl$5 = /* @__PURE__ */ template(`<span style=font-variant-numeric:tabular-nums;font-size:10px;margin-left:4px;vertical-align:middle>`);
|
|
364
|
+
var _tmpl$6 = /* @__PURE__ */ template(`<div style=margin-left:4px>to clipboard`);
|
|
365
|
+
var _tmpl$7 = /* @__PURE__ */ template(`<div style=font-size:9px;opacity:0.6;text-align:center;margin-top:2px>Click or drag to select`);
|
|
366
|
+
var _tmpl$8 = /* @__PURE__ */ template(`<div style="position:fixed;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;max-width:calc(100vw - (16px + env(safe-area-inset-left) + env(safe-area-inset-right)));overflow:hidden"><div style="position:relative;padding:2px 6px;display:flex;flex-direction:column"><div style=display:flex;align-items:center;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
|
+
});
|
|
334
378
|
const labelBoundingRect = () => labelRef?.getBoundingClientRect();
|
|
335
379
|
const computedPosition = () => {
|
|
336
|
-
positionTick();
|
|
337
380
|
const boundingRect = labelBoundingRect();
|
|
338
381
|
if (!boundingRect) return {
|
|
339
|
-
left:
|
|
340
|
-
top:
|
|
382
|
+
left: position.x(),
|
|
383
|
+
top: position.y()
|
|
341
384
|
};
|
|
342
385
|
const viewportWidth = window.innerWidth;
|
|
343
386
|
const viewportHeight = window.innerHeight;
|
|
344
|
-
const quadrants =
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
left: Math.round(currentX) - boundingRect.width - CURSOR_OFFSET_PX,
|
|
349
|
-
top: Math.round(currentY) + CURSOR_OFFSET_PX
|
|
350
|
-
}, {
|
|
351
|
-
left: Math.round(currentX) + CURSOR_OFFSET_PX,
|
|
352
|
-
top: Math.round(currentY) - boundingRect.height - CURSOR_OFFSET_PX
|
|
353
|
-
}, {
|
|
354
|
-
left: Math.round(currentX) - boundingRect.width - CURSOR_OFFSET_PX,
|
|
355
|
-
top: Math.round(currentY) - boundingRect.height - CURSOR_OFFSET_PX
|
|
356
|
-
}];
|
|
357
|
-
for (const position of quadrants) {
|
|
358
|
-
const fitsHorizontally = position.left >= VIEWPORT_MARGIN_PX && position.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
|
|
359
|
-
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;
|
|
360
391
|
if (fitsHorizontally && fitsVertically) {
|
|
361
|
-
return
|
|
392
|
+
return position2;
|
|
362
393
|
}
|
|
363
394
|
}
|
|
364
395
|
const fallback = getClampedElementPosition(quadrants[0].left, quadrants[0].top, boundingRect.width, boundingRect.height);
|
|
@@ -385,10 +416,20 @@ var Label = (props) => {
|
|
|
385
416
|
return props.visible !== false;
|
|
386
417
|
},
|
|
387
418
|
get children() {
|
|
388
|
-
var _el$ = _tmpl$
|
|
419
|
+
var _el$ = _tmpl$8(), _el$3 = _el$.firstChild, _el$4 = _el$3.firstChild;
|
|
389
420
|
var _ref$ = labelRef;
|
|
390
421
|
typeof _ref$ === "function" ? use(_ref$, _el$) : labelRef = _el$;
|
|
391
422
|
insert(_el$, createComponent(Show, {
|
|
423
|
+
get when() {
|
|
424
|
+
return memo(() => props.variant === "processing")() && props.progress !== void 0;
|
|
425
|
+
},
|
|
426
|
+
get children() {
|
|
427
|
+
var _el$2 = _tmpl$3();
|
|
428
|
+
effect((_$p) => setStyleProperty(_el$2, "width", `${Math.min(100, Math.max(0, (props.progress ?? 0) * 100))}%`));
|
|
429
|
+
return _el$2;
|
|
430
|
+
}
|
|
431
|
+
}), _el$3);
|
|
432
|
+
insert(_el$4, createComponent(Show, {
|
|
392
433
|
get when() {
|
|
393
434
|
return props.variant === "processing";
|
|
394
435
|
},
|
|
@@ -396,55 +437,63 @@ var Label = (props) => {
|
|
|
396
437
|
return createComponent(Spinner, {});
|
|
397
438
|
}
|
|
398
439
|
}), null);
|
|
399
|
-
insert(_el
|
|
440
|
+
insert(_el$4, createComponent(Show, {
|
|
400
441
|
get when() {
|
|
401
442
|
return props.variant === "success";
|
|
402
443
|
},
|
|
403
444
|
get children() {
|
|
404
|
-
return _tmpl$
|
|
445
|
+
return _tmpl$22();
|
|
405
446
|
}
|
|
406
447
|
}), null);
|
|
407
|
-
insert(_el
|
|
448
|
+
insert(_el$4, createComponent(Show, {
|
|
408
449
|
get when() {
|
|
409
450
|
return props.variant === "success";
|
|
410
451
|
},
|
|
411
452
|
get children() {
|
|
412
|
-
return _tmpl$
|
|
453
|
+
return _tmpl$32();
|
|
413
454
|
}
|
|
414
455
|
}), null);
|
|
415
|
-
insert(_el
|
|
456
|
+
insert(_el$4, createComponent(Show, {
|
|
416
457
|
get when() {
|
|
417
458
|
return props.variant === "processing";
|
|
418
459
|
},
|
|
419
|
-
children: "
|
|
460
|
+
children: "Please wait\u2026"
|
|
420
461
|
}), null);
|
|
421
|
-
insert(_el
|
|
462
|
+
insert(_el$4, createComponent(Show, {
|
|
422
463
|
get when() {
|
|
423
464
|
return props.variant !== "processing";
|
|
424
465
|
},
|
|
425
466
|
get children() {
|
|
426
467
|
return [(() => {
|
|
427
|
-
var _el$
|
|
428
|
-
insert(_el$
|
|
429
|
-
return _el$
|
|
468
|
+
var _el$7 = _tmpl$4();
|
|
469
|
+
insert(_el$7, () => labelSegments().primary);
|
|
470
|
+
return _el$7;
|
|
430
471
|
})(), createComponent(Show, {
|
|
431
472
|
get when() {
|
|
432
473
|
return memo(() => props.variant === "hover")() && labelSegments().secondary !== "";
|
|
433
474
|
},
|
|
434
475
|
get children() {
|
|
435
|
-
var _el$
|
|
436
|
-
insert(_el$
|
|
437
|
-
return _el$
|
|
476
|
+
var _el$8 = _tmpl$5();
|
|
477
|
+
insert(_el$8, () => labelSegments().secondary);
|
|
478
|
+
return _el$8;
|
|
438
479
|
}
|
|
439
480
|
})];
|
|
440
481
|
}
|
|
441
482
|
}), null);
|
|
442
|
-
insert(_el
|
|
483
|
+
insert(_el$4, createComponent(Show, {
|
|
443
484
|
get when() {
|
|
444
485
|
return props.variant === "success";
|
|
445
486
|
},
|
|
446
487
|
get children() {
|
|
447
|
-
return _tmpl$
|
|
488
|
+
return _tmpl$6();
|
|
489
|
+
}
|
|
490
|
+
}), null);
|
|
491
|
+
insert(_el$3, createComponent(Show, {
|
|
492
|
+
get when() {
|
|
493
|
+
return memo(() => props.variant === "hover")() && props.showHint;
|
|
494
|
+
},
|
|
495
|
+
get children() {
|
|
496
|
+
return _tmpl$7();
|
|
448
497
|
}
|
|
449
498
|
}), null);
|
|
450
499
|
effect((_p$) => {
|
|
@@ -464,22 +513,11 @@ var Label = (props) => {
|
|
|
464
513
|
}
|
|
465
514
|
});
|
|
466
515
|
};
|
|
467
|
-
var _tmpl$
|
|
468
|
-
var useFadeInOut = (visible) => {
|
|
469
|
-
const [opacity, setOpacity] = createSignal(0);
|
|
470
|
-
createEffect(on(() => visible, (isVisible) => {
|
|
471
|
-
if (isVisible !== false) {
|
|
472
|
-
requestAnimationFrame(() => {
|
|
473
|
-
setOpacity(1);
|
|
474
|
-
});
|
|
475
|
-
} else {
|
|
476
|
-
setOpacity(0);
|
|
477
|
-
}
|
|
478
|
-
}));
|
|
479
|
-
return opacity;
|
|
480
|
-
};
|
|
516
|
+
var _tmpl$9 = /* @__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)">`);
|
|
481
517
|
var ProgressIndicator = (props) => {
|
|
482
|
-
const opacity = useFadeInOut(
|
|
518
|
+
const opacity = useFadeInOut({
|
|
519
|
+
visible: props.visible
|
|
520
|
+
});
|
|
483
521
|
let progressIndicatorRef;
|
|
484
522
|
const computedPosition = () => {
|
|
485
523
|
const boundingRect = progressIndicatorRef?.getBoundingClientRect();
|
|
@@ -497,7 +535,7 @@ var ProgressIndicator = (props) => {
|
|
|
497
535
|
return props.visible !== false;
|
|
498
536
|
},
|
|
499
537
|
get children() {
|
|
500
|
-
var _el$ = _tmpl$
|
|
538
|
+
var _el$ = _tmpl$9(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
|
|
501
539
|
var _ref$ = progressIndicatorRef;
|
|
502
540
|
typeof _ref$ === "function" ? use(_ref$, _el$) : progressIndicatorRef = _el$;
|
|
503
541
|
effect((_p$) => {
|
|
@@ -517,19 +555,18 @@ var ProgressIndicator = (props) => {
|
|
|
517
555
|
}
|
|
518
556
|
});
|
|
519
557
|
};
|
|
520
|
-
var _tmpl$
|
|
558
|
+
var _tmpl$10 = /* @__PURE__ */ template(`<canvas style=position:fixed;top:0;left:0;pointer-events:none;z-index:2147483645>`);
|
|
521
559
|
var Crosshair = (props) => {
|
|
522
560
|
let canvasRef;
|
|
523
561
|
let context = null;
|
|
524
562
|
let width = 0;
|
|
525
563
|
let height = 0;
|
|
526
564
|
let dpr = 1;
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
let hasBeenRenderedOnce = false;
|
|
565
|
+
const position = useAnimatedPosition({
|
|
566
|
+
x: () => props.mouseX,
|
|
567
|
+
y: () => props.mouseY,
|
|
568
|
+
lerpFactor: 0.3
|
|
569
|
+
});
|
|
533
570
|
const setupCanvas = () => {
|
|
534
571
|
if (!canvasRef) return;
|
|
535
572
|
dpr = Math.max(window.devicePixelRatio || 1, 2);
|
|
@@ -550,39 +587,12 @@ var Crosshair = (props) => {
|
|
|
550
587
|
context.strokeStyle = "rgba(210, 57, 192)";
|
|
551
588
|
context.lineWidth = 1;
|
|
552
589
|
context.beginPath();
|
|
553
|
-
context.moveTo(
|
|
554
|
-
context.lineTo(
|
|
555
|
-
context.moveTo(0,
|
|
556
|
-
context.lineTo(width,
|
|
590
|
+
context.moveTo(position.x(), 0);
|
|
591
|
+
context.lineTo(position.x(), height);
|
|
592
|
+
context.moveTo(0, position.y());
|
|
593
|
+
context.lineTo(width, position.y());
|
|
557
594
|
context.stroke();
|
|
558
595
|
};
|
|
559
|
-
const animate = () => {
|
|
560
|
-
currentX = lerp(currentX, targetX, 0.3);
|
|
561
|
-
currentY = lerp(currentY, targetY, 0.3);
|
|
562
|
-
render2();
|
|
563
|
-
const hasConvergedToTarget = Math.abs(currentX - targetX) < 0.5 && Math.abs(currentY - targetY) < 0.5;
|
|
564
|
-
if (!hasConvergedToTarget) {
|
|
565
|
-
animationFrameId = requestAnimationFrame(animate);
|
|
566
|
-
} else {
|
|
567
|
-
animationFrameId = null;
|
|
568
|
-
}
|
|
569
|
-
};
|
|
570
|
-
const startAnimation = () => {
|
|
571
|
-
if (animationFrameId !== null) return;
|
|
572
|
-
animationFrameId = requestAnimationFrame(animate);
|
|
573
|
-
};
|
|
574
|
-
const updateTarget = () => {
|
|
575
|
-
targetX = props.mouseX;
|
|
576
|
-
targetY = props.mouseY;
|
|
577
|
-
if (!hasBeenRenderedOnce) {
|
|
578
|
-
currentX = targetX;
|
|
579
|
-
currentY = targetY;
|
|
580
|
-
hasBeenRenderedOnce = true;
|
|
581
|
-
render2();
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
startAnimation();
|
|
585
|
-
};
|
|
586
596
|
createEffect(() => {
|
|
587
597
|
setupCanvas();
|
|
588
598
|
render2();
|
|
@@ -593,21 +603,19 @@ var Crosshair = (props) => {
|
|
|
593
603
|
window.addEventListener("resize", handleResize);
|
|
594
604
|
onCleanup(() => {
|
|
595
605
|
window.removeEventListener("resize", handleResize);
|
|
596
|
-
if (animationFrameId !== null) {
|
|
597
|
-
cancelAnimationFrame(animationFrameId);
|
|
598
|
-
animationFrameId = null;
|
|
599
|
-
}
|
|
600
606
|
});
|
|
601
607
|
});
|
|
602
608
|
createEffect(() => {
|
|
603
|
-
|
|
609
|
+
position.x();
|
|
610
|
+
position.y();
|
|
611
|
+
render2();
|
|
604
612
|
});
|
|
605
613
|
return createComponent(Show, {
|
|
606
614
|
get when() {
|
|
607
615
|
return props.visible !== false;
|
|
608
616
|
},
|
|
609
617
|
get children() {
|
|
610
|
-
var _el$ = _tmpl$
|
|
618
|
+
var _el$ = _tmpl$10();
|
|
611
619
|
var _ref$ = canvasRef;
|
|
612
620
|
typeof _ref$ === "function" ? use(_ref$, _el$) : canvasRef = _el$;
|
|
613
621
|
return _el$;
|
|
@@ -675,22 +683,29 @@ var ReactGrabRenderer = (props) => {
|
|
|
675
683
|
return box.createdAt;
|
|
676
684
|
}
|
|
677
685
|
})
|
|
678
|
-
}), createComponent(
|
|
679
|
-
get
|
|
680
|
-
return props.
|
|
686
|
+
}), createComponent(Show, {
|
|
687
|
+
get when() {
|
|
688
|
+
return props.labelVariant !== "processing";
|
|
681
689
|
},
|
|
682
|
-
children
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
690
|
+
get children() {
|
|
691
|
+
return createComponent(For, {
|
|
692
|
+
get each() {
|
|
693
|
+
return props.successLabels ?? [];
|
|
694
|
+
},
|
|
695
|
+
children: (label) => createComponent(Label, {
|
|
696
|
+
variant: "success",
|
|
697
|
+
get text() {
|
|
698
|
+
return label.text;
|
|
699
|
+
},
|
|
700
|
+
get x() {
|
|
701
|
+
return props.mouseX ?? 0;
|
|
702
|
+
},
|
|
703
|
+
get y() {
|
|
704
|
+
return props.mouseY ?? 0;
|
|
705
|
+
}
|
|
706
|
+
})
|
|
707
|
+
});
|
|
708
|
+
}
|
|
694
709
|
}), createComponent(Show, {
|
|
695
710
|
get when() {
|
|
696
711
|
return memo(() => !!(props.labelVisible && props.labelVariant && props.labelText && props.labelX !== void 0))() && props.labelY !== void 0;
|
|
@@ -714,6 +729,12 @@ var ReactGrabRenderer = (props) => {
|
|
|
714
729
|
},
|
|
715
730
|
get zIndex() {
|
|
716
731
|
return props.labelZIndex;
|
|
732
|
+
},
|
|
733
|
+
get progress() {
|
|
734
|
+
return props.progress;
|
|
735
|
+
},
|
|
736
|
+
get showHint() {
|
|
737
|
+
return props.labelShowHint;
|
|
717
738
|
}
|
|
718
739
|
});
|
|
719
740
|
}
|
|
@@ -744,27 +765,62 @@ var ReactGrabRenderer = (props) => {
|
|
|
744
765
|
var isCapitalized = (value) => value.length > 0 && /^[A-Z]/.test(value);
|
|
745
766
|
|
|
746
767
|
// src/instrumentation.ts
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
768
|
+
var NEXT_INTERNAL_COMPONENT_NAMES = [
|
|
769
|
+
"InnerLayoutRouter",
|
|
770
|
+
"RedirectErrorBoundary",
|
|
771
|
+
"RedirectBoundary",
|
|
772
|
+
"HTTPAccessFallbackErrorBoundary",
|
|
773
|
+
"HTTPAccessFallbackBoundary",
|
|
774
|
+
"LoadingBoundary",
|
|
775
|
+
"ErrorBoundary",
|
|
776
|
+
"InnerScrollAndFocusHandler",
|
|
777
|
+
"ScrollAndFocusHandler",
|
|
778
|
+
"RenderFromTemplateContext",
|
|
779
|
+
"OuterLayoutRouter",
|
|
780
|
+
"body",
|
|
781
|
+
"html",
|
|
782
|
+
"RedirectErrorBoundary",
|
|
783
|
+
"RedirectBoundary",
|
|
784
|
+
"HTTPAccessFallbackErrorBoundary",
|
|
785
|
+
"HTTPAccessFallbackBoundary",
|
|
786
|
+
"DevRootHTTPAccessFallbackBoundary",
|
|
787
|
+
"AppDevOverlayErrorBoundary",
|
|
788
|
+
"AppDevOverlay",
|
|
789
|
+
"HotReload",
|
|
790
|
+
"Router",
|
|
791
|
+
"ErrorBoundaryHandler",
|
|
792
|
+
"ErrorBoundary",
|
|
793
|
+
"AppRouter",
|
|
794
|
+
"ServerRoot",
|
|
795
|
+
"SegmentStateProvider",
|
|
796
|
+
"RootErrorBoundary"
|
|
797
|
+
];
|
|
798
|
+
var checkIsNextProject = () => {
|
|
799
|
+
return Boolean(document.getElementById("__NEXT_DATA__"));
|
|
800
|
+
};
|
|
801
|
+
var checkIsInternalComponentName = (name) => {
|
|
802
|
+
if (name.startsWith("_")) return true;
|
|
803
|
+
if (NEXT_INTERNAL_COMPONENT_NAMES.includes(name)) return true;
|
|
804
|
+
return false;
|
|
754
805
|
};
|
|
755
|
-
var
|
|
756
|
-
|
|
757
|
-
|
|
806
|
+
var checkIsSourceComponentName = (name) => {
|
|
807
|
+
if (checkIsInternalComponentName(name)) return false;
|
|
808
|
+
if (!isCapitalized(name)) return false;
|
|
809
|
+
if (name.startsWith("Primitive.")) return false;
|
|
810
|
+
if (name.includes("Provider") && name.includes("Context")) return false;
|
|
811
|
+
return true;
|
|
812
|
+
};
|
|
813
|
+
var getNearestComponentName = (element) => {
|
|
758
814
|
const fiber = getFiberFromHostInstance(element);
|
|
759
815
|
if (!fiber) return null;
|
|
760
|
-
let
|
|
816
|
+
let foundComponentName = null;
|
|
761
817
|
traverseFiber(
|
|
762
818
|
fiber,
|
|
763
819
|
(currentFiber) => {
|
|
764
820
|
if (isCompositeFiber(currentFiber)) {
|
|
765
821
|
const displayName = getDisplayName(currentFiber);
|
|
766
|
-
if (displayName &&
|
|
767
|
-
|
|
822
|
+
if (displayName && checkIsSourceComponentName(displayName)) {
|
|
823
|
+
foundComponentName = displayName;
|
|
768
824
|
return true;
|
|
769
825
|
}
|
|
770
826
|
}
|
|
@@ -772,231 +828,107 @@ var getNearestComponentDisplayName = (element) => {
|
|
|
772
828
|
},
|
|
773
829
|
true
|
|
774
830
|
);
|
|
775
|
-
return
|
|
776
|
-
};
|
|
777
|
-
var formatComponentSourceLocation = async (el) => {
|
|
778
|
-
const source = await getSourceFromHostInstance(el);
|
|
779
|
-
if (!source) return null;
|
|
780
|
-
const fileName = normalizeFileName(source.fileName);
|
|
781
|
-
if (isSourceFile(fileName)) {
|
|
782
|
-
return `${fileName}:${source.lineNumber}:${source.columnNumber}`;
|
|
783
|
-
}
|
|
784
|
-
if (fileName && (fileName.includes(".tsx") || fileName.includes(".ts") || fileName.includes(".jsx") || fileName.includes(".js"))) {
|
|
785
|
-
const cleanedFileName = fileName.replace(/^webpack:\/\/_N_E\//, "").replace(/^webpack:\/\/\//, "").replace(/^webpack:\/\//, "").replace(/^\.\//, "");
|
|
786
|
-
if (cleanedFileName && !cleanedFileName.startsWith("node_modules") && !cleanedFileName.includes(".next") && !cleanedFileName.startsWith("webpack")) {
|
|
787
|
-
return `${cleanedFileName}:${source.lineNumber}:${source.columnNumber}`;
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
return null;
|
|
831
|
+
return foundComponentName;
|
|
791
832
|
};
|
|
792
|
-
var
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
if (el.id) return true;
|
|
807
|
-
if (el.className && typeof el.className === "string") {
|
|
808
|
-
const classes = el.className.trim();
|
|
809
|
-
if (classes && classes.length > 0) return true;
|
|
810
|
-
}
|
|
811
|
-
return Array.from(el.attributes).some(
|
|
812
|
-
(attr) => attr.name.startsWith("data-")
|
|
813
|
-
);
|
|
814
|
-
};
|
|
815
|
-
const collectDistinguishingAncestors = (el, maxDepth = 10) => {
|
|
816
|
-
const ancestors2 = [];
|
|
817
|
-
let current = el.parentElement;
|
|
818
|
-
let depth = 0;
|
|
819
|
-
while (current && depth < maxDepth && current.tagName !== "BODY") {
|
|
820
|
-
if (hasDistinguishingFeatures(current)) {
|
|
821
|
-
ancestors2.push(current);
|
|
822
|
-
if (ancestors2.length >= 3) break;
|
|
823
|
-
}
|
|
824
|
-
current = current.parentElement;
|
|
825
|
-
depth++;
|
|
826
|
-
}
|
|
827
|
-
return ancestors2.reverse();
|
|
828
|
-
};
|
|
829
|
-
const formatElementOpeningTag = (el, compact = false) => {
|
|
830
|
-
const tagName = el.tagName.toLowerCase();
|
|
831
|
-
const attrs = [];
|
|
832
|
-
if (el.id) {
|
|
833
|
-
attrs.push(`id="${el.id}"`);
|
|
834
|
-
}
|
|
835
|
-
if (el.className && typeof el.className === "string") {
|
|
836
|
-
const classes = el.className.trim().split(/\s+/);
|
|
837
|
-
if (classes.length > 0 && classes[0]) {
|
|
838
|
-
const displayClasses = compact ? classes.slice(0, 3) : classes;
|
|
839
|
-
const classStr = truncateString(displayClasses.join(" "), 30);
|
|
840
|
-
attrs.push(`class="${classStr}"`);
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
const dataAttrs = Array.from(el.attributes).filter(
|
|
844
|
-
(attr) => attr.name.startsWith("data-")
|
|
845
|
-
);
|
|
846
|
-
const displayDataAttrs = compact ? dataAttrs.slice(0, 1) : dataAttrs;
|
|
847
|
-
for (const attr of displayDataAttrs) {
|
|
848
|
-
attrs.push(`${attr.name}="${truncateString(attr.value, 20)}"`);
|
|
849
|
-
}
|
|
850
|
-
const ariaLabel = el.getAttribute("aria-label");
|
|
851
|
-
if (ariaLabel && !compact) {
|
|
852
|
-
attrs.push(`aria-label="${truncateString(ariaLabel, 20)}"`);
|
|
853
|
-
}
|
|
854
|
-
return attrs.length > 0 ? `<${tagName} ${attrs.join(" ")}>` : `<${tagName}>`;
|
|
855
|
-
};
|
|
856
|
-
const formatElementClosingTag = (el) => `</${el.tagName.toLowerCase()}>`;
|
|
857
|
-
const extractTruncatedTextContent = (el) => {
|
|
858
|
-
const text = (el.textContent || "").trim().replace(/\s+/g, " ");
|
|
859
|
-
return truncateString(text, 60);
|
|
860
|
-
};
|
|
861
|
-
const extractSiblingIdentifier = (el) => {
|
|
862
|
-
if (el.id) return `#${el.id}`;
|
|
863
|
-
if (el.className && typeof el.className === "string") {
|
|
864
|
-
const classes = el.className.trim().split(/\s+/);
|
|
865
|
-
if (classes.length > 0 && classes[0]) {
|
|
866
|
-
return `.${classes[0]}`;
|
|
833
|
+
var getStack = async (element) => {
|
|
834
|
+
const maybeFiber = getFiberFromHostInstance(element);
|
|
835
|
+
if (!maybeFiber || !isFiber(maybeFiber)) return [];
|
|
836
|
+
const fiber = getLatestFiber(maybeFiber);
|
|
837
|
+
const unresolvedStack = [];
|
|
838
|
+
traverseFiber(
|
|
839
|
+
fiber,
|
|
840
|
+
(currentFiber) => {
|
|
841
|
+
const displayName = isHostFiber(currentFiber) ? typeof currentFiber.type === "string" ? currentFiber.type : null : getDisplayName(currentFiber);
|
|
842
|
+
if (displayName && !checkIsInternalComponentName(displayName)) {
|
|
843
|
+
unresolvedStack.push({
|
|
844
|
+
name: displayName,
|
|
845
|
+
sourcePromise: getSource(currentFiber)
|
|
846
|
+
});
|
|
867
847
|
}
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
};
|
|
871
|
-
const lines = [];
|
|
872
|
-
const selector = generateCSSSelector(element);
|
|
873
|
-
lines.push(`- selector: ${selector}`);
|
|
874
|
-
const rect = element.getBoundingClientRect();
|
|
875
|
-
lines.push(`- width: ${Math.round(rect.width)}`);
|
|
876
|
-
lines.push(`- height: ${Math.round(rect.height)}`);
|
|
877
|
-
lines.push("HTML snippet:");
|
|
878
|
-
lines.push("```html");
|
|
879
|
-
const ancestors = collectDistinguishingAncestors(element);
|
|
880
|
-
const ancestorComponents = ancestors.map(
|
|
881
|
-
(ancestor) => getNearestComponentDisplayName(ancestor)
|
|
848
|
+
},
|
|
849
|
+
true
|
|
882
850
|
);
|
|
883
|
-
const
|
|
884
|
-
|
|
885
|
-
|
|
851
|
+
const resolvedStack = await Promise.all(
|
|
852
|
+
unresolvedStack.map(async (frame) => ({
|
|
853
|
+
name: frame.name,
|
|
854
|
+
source: await frame.sourcePromise
|
|
855
|
+
}))
|
|
886
856
|
);
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
const isNewComponent = componentName && source && (i === 0 || ancestorComponents[i - 1] !== componentName);
|
|
896
|
-
if (isNewComponent) {
|
|
897
|
-
ancestorComponentIndents[i] = currentIndentLevel;
|
|
898
|
-
lines.push(
|
|
899
|
-
`${getIndent(currentIndentLevel)}<${componentName} used-at="${source}">`
|
|
900
|
-
);
|
|
901
|
-
currentIndentLevel++;
|
|
857
|
+
return resolvedStack.filter((frame) => frame.source !== null);
|
|
858
|
+
};
|
|
859
|
+
var formatStack = (stack) => {
|
|
860
|
+
const isNextProject = checkIsNextProject();
|
|
861
|
+
return stack.map(({ name, source }) => {
|
|
862
|
+
if (!source) return ` at ${name}`;
|
|
863
|
+
if (source.fileName.startsWith("about://React/Server")) {
|
|
864
|
+
return ` at ${name} (Server)`;
|
|
902
865
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
currentIndentLevel++;
|
|
908
|
-
}
|
|
909
|
-
const parent = element.parentElement;
|
|
910
|
-
let targetIndex = -1;
|
|
911
|
-
if (parent) {
|
|
912
|
-
const siblings = Array.from(parent.children);
|
|
913
|
-
targetIndex = siblings.indexOf(element);
|
|
914
|
-
if (targetIndex > 0) {
|
|
915
|
-
const indent = getIndent(currentIndentLevel);
|
|
916
|
-
if (targetIndex <= 2) {
|
|
917
|
-
for (let i = 0; i < targetIndex; i++) {
|
|
918
|
-
const sibling = siblings[i];
|
|
919
|
-
const siblingId = extractSiblingIdentifier(sibling);
|
|
920
|
-
if (siblingId) {
|
|
921
|
-
lines.push(`${indent}${formatElementOpeningTag(sibling, true)}`);
|
|
922
|
-
lines.push(`${indent}</${sibling.tagName.toLowerCase()}>`);
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
} else {
|
|
926
|
-
lines.push(
|
|
927
|
-
`${indent}... (${targetIndex} element${targetIndex === 1 ? "" : "s"})`
|
|
928
|
-
);
|
|
929
|
-
}
|
|
866
|
+
if (!isSourceFile(source.fileName)) return ` at ${name}`;
|
|
867
|
+
const framePart = ` at ${name} in ${normalizeFileName(source.fileName)}`;
|
|
868
|
+
if (isNextProject) {
|
|
869
|
+
return `${framePart}:${source.lineNumber}:${source.columnNumber}`;
|
|
930
870
|
}
|
|
871
|
+
return framePart;
|
|
872
|
+
}).join("\n");
|
|
873
|
+
};
|
|
874
|
+
var getHTMLPreview = (element) => {
|
|
875
|
+
const tagName = element.tagName.toLowerCase();
|
|
876
|
+
if (!(element instanceof HTMLElement)) {
|
|
877
|
+
return `<${tagName} />`;
|
|
931
878
|
}
|
|
932
|
-
const
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
const
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
elementIndentLevel++;
|
|
941
|
-
}
|
|
942
|
-
const elementIndent = getIndent(elementIndentLevel);
|
|
943
|
-
lines.push(`${elementIndent}<!-- IMPORTANT: selected element -->`);
|
|
944
|
-
const textContent = extractTruncatedTextContent(element);
|
|
945
|
-
const childrenCount = element.children.length;
|
|
946
|
-
if (textContent && childrenCount === 0 && textContent.length < 40) {
|
|
947
|
-
lines.push(
|
|
948
|
-
`${elementIndent}${formatElementOpeningTag(element)}${textContent}${formatElementClosingTag(
|
|
949
|
-
element
|
|
950
|
-
)}`
|
|
951
|
-
);
|
|
952
|
-
} else {
|
|
953
|
-
lines.push(`${elementIndent}${formatElementOpeningTag(element)}`);
|
|
954
|
-
if (textContent) {
|
|
955
|
-
lines.push(`${elementIndent} ${textContent}`);
|
|
956
|
-
}
|
|
957
|
-
if (childrenCount > 0) {
|
|
958
|
-
lines.push(
|
|
959
|
-
`${elementIndent} ... (${childrenCount} element${childrenCount === 1 ? "" : "s"})`
|
|
960
|
-
);
|
|
879
|
+
const text = element.innerText?.trim() ?? element.textContent?.trim() ?? "";
|
|
880
|
+
let attrsText = "";
|
|
881
|
+
const attributes = Array.from(element.attributes);
|
|
882
|
+
for (const attribute of attributes) {
|
|
883
|
+
const name = attribute.name;
|
|
884
|
+
let value = attribute.value;
|
|
885
|
+
if (value.length > 20) {
|
|
886
|
+
value = `${value.slice(0, 20)}...`;
|
|
961
887
|
}
|
|
962
|
-
|
|
888
|
+
attrsText += ` ${name}="${value}"`;
|
|
963
889
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
const siblingId = extractSiblingIdentifier(sibling);
|
|
978
|
-
if (siblingId) {
|
|
979
|
-
lines.push(`${indent}${formatElementOpeningTag(sibling, true)}`);
|
|
980
|
-
lines.push(`${indent}</${sibling.tagName.toLowerCase()}>`);
|
|
981
|
-
}
|
|
982
|
-
}
|
|
890
|
+
const topElements = [];
|
|
891
|
+
const bottomElements = [];
|
|
892
|
+
let foundFirstText = false;
|
|
893
|
+
const childNodes = Array.from(element.childNodes);
|
|
894
|
+
for (const node of childNodes) {
|
|
895
|
+
if (node.nodeType === Node.COMMENT_NODE) continue;
|
|
896
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
897
|
+
if (node.textContent && node.textContent.trim().length > 0) {
|
|
898
|
+
foundFirstText = true;
|
|
899
|
+
}
|
|
900
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
901
|
+
if (!foundFirstText) {
|
|
902
|
+
topElements.push(node);
|
|
983
903
|
} else {
|
|
984
|
-
|
|
985
|
-
`${indent}... (${siblingsAfter} element${siblingsAfter === 1 ? "" : "s"})`
|
|
986
|
-
);
|
|
904
|
+
bottomElements.push(node);
|
|
987
905
|
}
|
|
988
906
|
}
|
|
989
907
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
const compIndent = getIndent(ancestorComponentIndents[i]);
|
|
995
|
-
lines.push(`${compIndent}</${ancestorComponents[i]}>`);
|
|
908
|
+
const formatElements = (elements) => {
|
|
909
|
+
if (elements.length === 0) return "";
|
|
910
|
+
if (elements.length <= 2) {
|
|
911
|
+
return elements.map((el) => `<${el.tagName.toLowerCase()} ...>`).join("\n ");
|
|
996
912
|
}
|
|
913
|
+
return `(${elements.length} elements)`;
|
|
914
|
+
};
|
|
915
|
+
let content = "";
|
|
916
|
+
const topElementsStr = formatElements(topElements);
|
|
917
|
+
if (topElementsStr) content += `
|
|
918
|
+
${topElementsStr}`;
|
|
919
|
+
if (text.length > 0) {
|
|
920
|
+
const truncatedText = text.length > 100 ? `${text.slice(0, 100)}...` : text;
|
|
921
|
+
content += `
|
|
922
|
+
${truncatedText}`;
|
|
997
923
|
}
|
|
998
|
-
|
|
999
|
-
|
|
924
|
+
const bottomElementsStr = formatElements(bottomElements);
|
|
925
|
+
if (bottomElementsStr) content += `
|
|
926
|
+
${bottomElementsStr}`;
|
|
927
|
+
if (content.length > 0) {
|
|
928
|
+
return `<${tagName}${attrsText}>${content}
|
|
929
|
+
</${tagName}>`;
|
|
930
|
+
}
|
|
931
|
+
return `<${tagName}${attrsText} />`;
|
|
1000
932
|
};
|
|
1001
933
|
|
|
1002
934
|
// src/utils/copy-content.ts
|
|
@@ -1016,73 +948,13 @@ var waitForFocus = () => {
|
|
|
1016
948
|
var copyContent = async (content, onSuccess) => {
|
|
1017
949
|
await waitForFocus();
|
|
1018
950
|
try {
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
for (const contentPart of content) {
|
|
1022
|
-
if (typeof contentPart === "string") {
|
|
1023
|
-
const result = copyContentFallback(contentPart, onSuccess);
|
|
1024
|
-
if (!result) return result;
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
onSuccess?.();
|
|
1028
|
-
return true;
|
|
1029
|
-
}
|
|
1030
|
-
const mimeTypeMap = /* @__PURE__ */ new Map();
|
|
1031
|
-
for (const contentPart of content) {
|
|
1032
|
-
if (contentPart instanceof Blob) {
|
|
1033
|
-
const mimeType = contentPart.type || "text/plain";
|
|
1034
|
-
if (!mimeTypeMap.has(mimeType)) {
|
|
1035
|
-
mimeTypeMap.set(mimeType, contentPart);
|
|
1036
|
-
}
|
|
1037
|
-
} else {
|
|
1038
|
-
if (!mimeTypeMap.has("text/plain")) {
|
|
1039
|
-
mimeTypeMap.set(
|
|
1040
|
-
"text/plain",
|
|
1041
|
-
new Blob([contentPart], { type: "text/plain" })
|
|
1042
|
-
);
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
if (mimeTypeMap.size === 0) {
|
|
1047
|
-
const plainTextFallback = content.find(
|
|
1048
|
-
(contentPart) => typeof contentPart === "string"
|
|
1049
|
-
);
|
|
1050
|
-
if (typeof plainTextFallback === "string") {
|
|
1051
|
-
return copyContentFallback(plainTextFallback, onSuccess);
|
|
1052
|
-
}
|
|
1053
|
-
return false;
|
|
1054
|
-
}
|
|
1055
|
-
try {
|
|
1056
|
-
await navigator.clipboard.write([
|
|
1057
|
-
new ClipboardItem(Object.fromEntries(mimeTypeMap))
|
|
1058
|
-
]);
|
|
1059
|
-
onSuccess?.();
|
|
1060
|
-
return true;
|
|
1061
|
-
} catch {
|
|
1062
|
-
const plainTextParts = content.filter(
|
|
1063
|
-
(contentPart) => typeof contentPart === "string"
|
|
1064
|
-
);
|
|
1065
|
-
if (plainTextParts.length > 0) {
|
|
1066
|
-
const combinedText = plainTextParts.join("\n\n");
|
|
1067
|
-
return copyContentFallback(combinedText, onSuccess);
|
|
1068
|
-
}
|
|
1069
|
-
return false;
|
|
1070
|
-
}
|
|
1071
|
-
} else if (content instanceof Blob) {
|
|
1072
|
-
await navigator.clipboard.write([
|
|
1073
|
-
new ClipboardItem({ [content.type]: content })
|
|
1074
|
-
]);
|
|
951
|
+
try {
|
|
952
|
+
await navigator.clipboard.writeText(content);
|
|
1075
953
|
onSuccess?.();
|
|
1076
954
|
return true;
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
onSuccess?.();
|
|
1081
|
-
return true;
|
|
1082
|
-
} catch {
|
|
1083
|
-
const result = copyContentFallback(content, onSuccess);
|
|
1084
|
-
return result;
|
|
1085
|
-
}
|
|
955
|
+
} catch {
|
|
956
|
+
const result = copyContentFallback(content, onSuccess);
|
|
957
|
+
return result;
|
|
1086
958
|
}
|
|
1087
959
|
} catch {
|
|
1088
960
|
return false;
|
|
@@ -1171,13 +1043,27 @@ var getElementAtPosition = (clientX, clientY) => {
|
|
|
1171
1043
|
|
|
1172
1044
|
// src/utils/get-elements-in-drag.ts
|
|
1173
1045
|
var DRAG_COVERAGE_THRESHOLD = 0.75;
|
|
1046
|
+
var calculateIntersectionArea = (rect1, rect2) => {
|
|
1047
|
+
const intersectionLeft = Math.max(rect1.left, rect2.left);
|
|
1048
|
+
const intersectionTop = Math.max(rect1.top, rect2.top);
|
|
1049
|
+
const intersectionRight = Math.min(rect1.right, rect2.right);
|
|
1050
|
+
const intersectionBottom = Math.min(rect1.bottom, rect2.bottom);
|
|
1051
|
+
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
1052
|
+
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
1053
|
+
return intersectionWidth * intersectionHeight;
|
|
1054
|
+
};
|
|
1055
|
+
var hasIntersection = (rect1, rect2) => {
|
|
1056
|
+
return rect1.left < rect2.right && rect1.right > rect2.left && rect1.top < rect2.bottom && rect1.bottom > rect2.top;
|
|
1057
|
+
};
|
|
1174
1058
|
var filterElementsInDrag = (dragRect, isValidGrabbableElement2, shouldCheckCoverage) => {
|
|
1175
1059
|
const elements = [];
|
|
1176
1060
|
const allElements = Array.from(document.querySelectorAll("*"));
|
|
1177
|
-
const
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1061
|
+
const dragBounds = {
|
|
1062
|
+
left: dragRect.x,
|
|
1063
|
+
top: dragRect.y,
|
|
1064
|
+
right: dragRect.x + dragRect.width,
|
|
1065
|
+
bottom: dragRect.y + dragRect.height
|
|
1066
|
+
};
|
|
1181
1067
|
for (const candidateElement of allElements) {
|
|
1182
1068
|
if (!shouldCheckCoverage) {
|
|
1183
1069
|
const tagName = (candidateElement.tagName || "").toUpperCase();
|
|
@@ -1187,26 +1073,21 @@ var filterElementsInDrag = (dragRect, isValidGrabbableElement2, shouldCheckCover
|
|
|
1187
1073
|
continue;
|
|
1188
1074
|
}
|
|
1189
1075
|
const elementRect = candidateElement.getBoundingClientRect();
|
|
1190
|
-
const
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1076
|
+
const elementBounds = {
|
|
1077
|
+
left: elementRect.left,
|
|
1078
|
+
top: elementRect.top,
|
|
1079
|
+
right: elementRect.left + elementRect.width,
|
|
1080
|
+
bottom: elementRect.top + elementRect.height
|
|
1081
|
+
};
|
|
1194
1082
|
if (shouldCheckCoverage) {
|
|
1195
|
-
const
|
|
1196
|
-
const intersectionTop = Math.max(dragTop, elementTop);
|
|
1197
|
-
const intersectionRight = Math.min(dragRight, elementRight);
|
|
1198
|
-
const intersectionBottom = Math.min(dragBottom, elementBottom);
|
|
1199
|
-
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
1200
|
-
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
1201
|
-
const intersectionArea = intersectionWidth * intersectionHeight;
|
|
1083
|
+
const intersectionArea = calculateIntersectionArea(dragBounds, elementBounds);
|
|
1202
1084
|
const elementArea = Math.max(0, elementRect.width * elementRect.height);
|
|
1203
1085
|
const hasMajorityCoverage = elementArea > 0 && intersectionArea / elementArea >= DRAG_COVERAGE_THRESHOLD;
|
|
1204
1086
|
if (hasMajorityCoverage) {
|
|
1205
1087
|
elements.push(candidateElement);
|
|
1206
1088
|
}
|
|
1207
1089
|
} else {
|
|
1208
|
-
|
|
1209
|
-
if (hasIntersection) {
|
|
1090
|
+
if (hasIntersection(elementBounds, dragBounds)) {
|
|
1210
1091
|
elements.push(candidateElement);
|
|
1211
1092
|
}
|
|
1212
1093
|
}
|
|
@@ -1245,70 +1126,7 @@ var createElementBounds = (element) => {
|
|
|
1245
1126
|
};
|
|
1246
1127
|
};
|
|
1247
1128
|
|
|
1248
|
-
// src/utils/is-localhost.ts
|
|
1249
|
-
var isLocalhost = () => {
|
|
1250
|
-
const hostname = window.location.hostname;
|
|
1251
|
-
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
1252
|
-
};
|
|
1253
|
-
var turndownService = null;
|
|
1254
|
-
var getTurndownService = () => {
|
|
1255
|
-
if (!turndownService) {
|
|
1256
|
-
turndownService = new TurndownService({
|
|
1257
|
-
headingStyle: "atx",
|
|
1258
|
-
codeBlockStyle: "fenced",
|
|
1259
|
-
emDelimiter: "_",
|
|
1260
|
-
bulletListMarker: "-",
|
|
1261
|
-
linkStyle: "inlined",
|
|
1262
|
-
linkReferenceStyle: "full"
|
|
1263
|
-
});
|
|
1264
|
-
turndownService.addRule("strikethrough", {
|
|
1265
|
-
filter: ["del", "s"],
|
|
1266
|
-
replacement: (content) => `~~${content}~~`
|
|
1267
|
-
});
|
|
1268
|
-
turndownService.addRule("removeHidden", {
|
|
1269
|
-
filter: (node) => {
|
|
1270
|
-
if (node instanceof HTMLElement) {
|
|
1271
|
-
const style = window.getComputedStyle(node);
|
|
1272
|
-
return style.display === "none" || style.visibility === "hidden" || style.opacity === "0";
|
|
1273
|
-
}
|
|
1274
|
-
return false;
|
|
1275
|
-
},
|
|
1276
|
-
replacement: () => ""
|
|
1277
|
-
});
|
|
1278
|
-
turndownService.addRule("preserveButtons", {
|
|
1279
|
-
filter: ["button"],
|
|
1280
|
-
replacement: (content) => content ? `[${content}]` : ""
|
|
1281
|
-
});
|
|
1282
|
-
turndownService.addRule("preserveInputs", {
|
|
1283
|
-
filter: (node) => {
|
|
1284
|
-
if (node.nodeName === "INPUT" && node instanceof HTMLInputElement) {
|
|
1285
|
-
return true;
|
|
1286
|
-
}
|
|
1287
|
-
return false;
|
|
1288
|
-
},
|
|
1289
|
-
replacement: (_, node) => {
|
|
1290
|
-
if (node instanceof HTMLInputElement) {
|
|
1291
|
-
const value = node.value || node.placeholder;
|
|
1292
|
-
return value ? `[${value}]` : "";
|
|
1293
|
-
}
|
|
1294
|
-
return "";
|
|
1295
|
-
}
|
|
1296
|
-
});
|
|
1297
|
-
}
|
|
1298
|
-
return turndownService;
|
|
1299
|
-
};
|
|
1300
|
-
var htmlToMarkdown = (html) => {
|
|
1301
|
-
const service = getTurndownService();
|
|
1302
|
-
return service.turndown(html).trim();
|
|
1303
|
-
};
|
|
1304
|
-
var elementToMarkdown = (element) => {
|
|
1305
|
-
const clonedElement = element.cloneNode(true);
|
|
1306
|
-
const service = getTurndownService();
|
|
1307
|
-
return service.turndown(clonedElement).trim();
|
|
1308
|
-
};
|
|
1309
|
-
|
|
1310
1129
|
// src/core.tsx
|
|
1311
|
-
var PROGRESS_INDICATOR_DELAY_MS = 150;
|
|
1312
1130
|
var init = (rawOptions) => {
|
|
1313
1131
|
const options = {
|
|
1314
1132
|
enabled: true,
|
|
@@ -1331,7 +1149,6 @@ var init = (rawOptions) => {
|
|
|
1331
1149
|
};
|
|
1332
1150
|
}
|
|
1333
1151
|
return createRoot((dispose) => {
|
|
1334
|
-
const OFFSCREEN_POSITION = -1e3;
|
|
1335
1152
|
const [isHoldingKeys, setIsHoldingKeys] = createSignal(false);
|
|
1336
1153
|
const [mouseX, setMouseX] = createSignal(OFFSCREEN_POSITION);
|
|
1337
1154
|
const [mouseY, setMouseY] = createSignal(OFFSCREEN_POSITION);
|
|
@@ -1341,7 +1158,7 @@ var init = (rawOptions) => {
|
|
|
1341
1158
|
const [isCopying, setIsCopying] = createSignal(false);
|
|
1342
1159
|
const [lastGrabbedElement, setLastGrabbedElement] = createSignal(null);
|
|
1343
1160
|
const [progressStartTime, setProgressStartTime] = createSignal(null);
|
|
1344
|
-
const [
|
|
1161
|
+
const [progress, setProgress] = createSignal(0);
|
|
1345
1162
|
const [grabbedBoxes, setGrabbedBoxes] = createSignal([]);
|
|
1346
1163
|
const [successLabels, setSuccessLabels] = createSignal([]);
|
|
1347
1164
|
const [isActivated, setIsActivated] = createSignal(false);
|
|
@@ -1356,8 +1173,6 @@ var init = (rawOptions) => {
|
|
|
1356
1173
|
let progressDelayTimerId = null;
|
|
1357
1174
|
let keydownSpamTimerId = null;
|
|
1358
1175
|
let mouseSettleTimerId = null;
|
|
1359
|
-
let referenceMouseX = OFFSCREEN_POSITION;
|
|
1360
|
-
let referenceMouseY = OFFSCREEN_POSITION;
|
|
1361
1176
|
const isRendererActive = createMemo(() => isActivated() && !isCopying());
|
|
1362
1177
|
const hasValidMousePosition = createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
|
|
1363
1178
|
const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "c";
|
|
@@ -1388,55 +1203,10 @@ var init = (rawOptions) => {
|
|
|
1388
1203
|
const wrapInSelectedElementTags = (context) => `<selected_element>
|
|
1389
1204
|
${context}
|
|
1390
1205
|
</selected_element>`;
|
|
1391
|
-
const extractRelevantComputedStyles = (element) => {
|
|
1392
|
-
const computed = window.getComputedStyle(element);
|
|
1393
|
-
const rect = element.getBoundingClientRect();
|
|
1394
|
-
return {
|
|
1395
|
-
width: `${Math.round(rect.width)}px`,
|
|
1396
|
-
height: `${Math.round(rect.height)}px`,
|
|
1397
|
-
paddingTop: computed.paddingTop,
|
|
1398
|
-
paddingRight: computed.paddingRight,
|
|
1399
|
-
paddingBottom: computed.paddingBottom,
|
|
1400
|
-
paddingLeft: computed.paddingLeft,
|
|
1401
|
-
background: computed.background,
|
|
1402
|
-
opacity: computed.opacity
|
|
1403
|
-
};
|
|
1404
|
-
};
|
|
1405
|
-
const createStructuredClipboardHtmlBlob = (elements) => {
|
|
1406
|
-
const structuredData = {
|
|
1407
|
-
elements: elements.map((element) => ({
|
|
1408
|
-
tagName: element.tagName,
|
|
1409
|
-
content: element.content,
|
|
1410
|
-
computedStyles: element.computedStyles
|
|
1411
|
-
}))
|
|
1412
|
-
};
|
|
1413
|
-
const jsonString = JSON.stringify(structuredData);
|
|
1414
|
-
const base64Data = btoa(encodeURIComponent(jsonString).replace(/%([0-9A-F]{2})/g, (_match, p1) => String.fromCharCode(parseInt(p1, 16))));
|
|
1415
|
-
const htmlContent = `<div data-react-grab="${base64Data}"></div>`;
|
|
1416
|
-
return new Blob([htmlContent], {
|
|
1417
|
-
type: "text/html"
|
|
1418
|
-
});
|
|
1419
|
-
};
|
|
1420
1206
|
const extractElementTagName = (element) => (element.tagName || "").toLowerCase();
|
|
1421
|
-
const extractNearestComponentName = (element) => {
|
|
1422
|
-
const fiber = getFiberFromHostInstance(element);
|
|
1423
|
-
if (!fiber) return null;
|
|
1424
|
-
let componentName = null;
|
|
1425
|
-
traverseFiber(fiber, (currentFiber) => {
|
|
1426
|
-
if (isCompositeFiber(currentFiber)) {
|
|
1427
|
-
const displayName = getDisplayName(currentFiber);
|
|
1428
|
-
if (displayName && isCapitalized(displayName) && !displayName.startsWith("_") && !displayName.startsWith("Primitive.")) {
|
|
1429
|
-
componentName = displayName;
|
|
1430
|
-
return true;
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
return false;
|
|
1434
|
-
}, true);
|
|
1435
|
-
return componentName;
|
|
1436
|
-
};
|
|
1437
1207
|
const extractElementLabelText = (element) => {
|
|
1438
1208
|
const tagName = extractElementTagName(element);
|
|
1439
|
-
const componentName =
|
|
1209
|
+
const componentName = getNearestComponentName(element);
|
|
1440
1210
|
if (tagName && componentName) {
|
|
1441
1211
|
return `<${tagName}> in ${componentName}`;
|
|
1442
1212
|
}
|
|
@@ -1458,8 +1228,6 @@ ${context}
|
|
|
1458
1228
|
} catch {
|
|
1459
1229
|
}
|
|
1460
1230
|
};
|
|
1461
|
-
const isExtensionEnvironment = () => window.__REACT_GRAB_EXTENSION_ACTIVE__ === true || options.isExtension === true;
|
|
1462
|
-
const isExtensionTextOnlyMode = () => isExtensionEnvironment() && !isLocalhost();
|
|
1463
1231
|
const executeCopyOperation = async (positionX, positionY, operation) => {
|
|
1464
1232
|
setCopyStartX(positionX);
|
|
1465
1233
|
setCopyStartY(positionY);
|
|
@@ -1485,39 +1253,37 @@ ${context}
|
|
|
1485
1253
|
return element.textContent ?? "";
|
|
1486
1254
|
};
|
|
1487
1255
|
const createCombinedTextContent = (elements) => elements.map((element) => extractElementTextContent(element).trim()).filter((textContent) => textContent.length > 0).join("\n\n");
|
|
1488
|
-
const
|
|
1489
|
-
const copySingleElementToClipboard = async (targetElement2) => {
|
|
1490
|
-
showTemporaryGrabbedBox(createElementBounds(targetElement2));
|
|
1491
|
-
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
1256
|
+
const tryCopyWithFallback = async (elements) => {
|
|
1492
1257
|
let didCopy = false;
|
|
1493
1258
|
try {
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
const plainTextContent = wrapInSelectedElementTags(
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
if (!didCopy) {
|
|
1509
|
-
const plainTextContentOnly = createCombinedTextContent([targetElement2]);
|
|
1510
|
-
if (plainTextContentOnly.length > 0) {
|
|
1511
|
-
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1512
|
-
}
|
|
1259
|
+
const elementSnippetResults = await Promise.allSettled(elements.map(async (element) => `## HTML Frame:
|
|
1260
|
+
${getHTMLPreview(element)}
|
|
1261
|
+
|
|
1262
|
+
## Code Location:
|
|
1263
|
+
${formatStack(await getStack(element))}`));
|
|
1264
|
+
const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
|
|
1265
|
+
if (elementSnippets.length > 0) {
|
|
1266
|
+
const plainTextContent = elementSnippets.map((snippet) => wrapInSelectedElementTags(snippet)).join("\n\n");
|
|
1267
|
+
didCopy = await copyContent(plainTextContent, options.playCopySound ? playCopySound : void 0);
|
|
1268
|
+
}
|
|
1269
|
+
if (!didCopy) {
|
|
1270
|
+
const plainTextContentOnly = createCombinedTextContent(elements);
|
|
1271
|
+
if (plainTextContentOnly.length > 0) {
|
|
1272
|
+
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1513
1273
|
}
|
|
1514
1274
|
}
|
|
1515
1275
|
} catch {
|
|
1516
|
-
const plainTextContentOnly = createCombinedTextContent(
|
|
1276
|
+
const plainTextContentOnly = createCombinedTextContent(elements);
|
|
1517
1277
|
if (plainTextContentOnly.length > 0) {
|
|
1518
1278
|
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1519
1279
|
}
|
|
1520
1280
|
}
|
|
1281
|
+
return didCopy;
|
|
1282
|
+
};
|
|
1283
|
+
const copySingleElementToClipboard = async (targetElement2) => {
|
|
1284
|
+
showTemporaryGrabbedBox(createElementBounds(targetElement2));
|
|
1285
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
1286
|
+
const didCopy = await tryCopyWithFallback([targetElement2]);
|
|
1521
1287
|
if (didCopy) {
|
|
1522
1288
|
showTemporarySuccessLabel(extractElementLabelText(targetElement2));
|
|
1523
1289
|
}
|
|
@@ -1529,40 +1295,7 @@ ${context}
|
|
|
1529
1295
|
showTemporaryGrabbedBox(createElementBounds(element));
|
|
1530
1296
|
}
|
|
1531
1297
|
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
1532
|
-
|
|
1533
|
-
try {
|
|
1534
|
-
if (isExtensionTextOnlyMode()) {
|
|
1535
|
-
const markdownContent = createCombinedMarkdownContent(targetElements);
|
|
1536
|
-
if (markdownContent.length > 0) {
|
|
1537
|
-
didCopy = await copyContent(markdownContent, options.playCopySound ? playCopySound : void 0);
|
|
1538
|
-
}
|
|
1539
|
-
} else {
|
|
1540
|
-
const elementSnippetResults = await Promise.allSettled(targetElements.map((element) => getHTMLSnippet(element)));
|
|
1541
|
-
const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
|
|
1542
|
-
if (elementSnippets.length > 0) {
|
|
1543
|
-
const plainTextContent = elementSnippets.map((snippet) => wrapInSelectedElementTags(snippet)).join("\n\n");
|
|
1544
|
-
const structuredElements = elementSnippets.map((content, elementIndex) => ({
|
|
1545
|
-
tagName: extractElementTagName(targetElements[elementIndex]),
|
|
1546
|
-
content,
|
|
1547
|
-
computedStyles: extractRelevantComputedStyles(targetElements[elementIndex])
|
|
1548
|
-
}));
|
|
1549
|
-
const htmlContent = createStructuredClipboardHtmlBlob(structuredElements);
|
|
1550
|
-
didCopy = await copyContent([plainTextContent, htmlContent], options.playCopySound ? playCopySound : void 0);
|
|
1551
|
-
if (!didCopy) {
|
|
1552
|
-
const plainTextContentOnly = createCombinedTextContent(targetElements);
|
|
1553
|
-
if (plainTextContentOnly.length > 0) {
|
|
1554
|
-
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
} else {
|
|
1558
|
-
const plainTextContentOnly = createCombinedTextContent(targetElements);
|
|
1559
|
-
if (plainTextContentOnly.length > 0) {
|
|
1560
|
-
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
} catch {
|
|
1565
|
-
}
|
|
1298
|
+
const didCopy = await tryCopyWithFallback(targetElements);
|
|
1566
1299
|
if (didCopy) {
|
|
1567
1300
|
showTemporarySuccessLabel(`${targetElements.length} elements`);
|
|
1568
1301
|
}
|
|
@@ -1586,7 +1319,6 @@ ${context}
|
|
|
1586
1319
|
y: elementBounds.top
|
|
1587
1320
|
};
|
|
1588
1321
|
});
|
|
1589
|
-
const DRAG_THRESHOLD_PX = 2;
|
|
1590
1322
|
const calculateDragDistance = (endX, endY) => ({
|
|
1591
1323
|
x: Math.abs(endX - dragStartX()),
|
|
1592
1324
|
y: Math.abs(endY - dragStartY())
|
|
@@ -1638,36 +1370,28 @@ ${context}
|
|
|
1638
1370
|
x: mouseX(),
|
|
1639
1371
|
y: mouseY()
|
|
1640
1372
|
});
|
|
1641
|
-
const isSameAsLast = createMemo(() => Boolean(targetElement() && targetElement() === lastGrabbedElement()));
|
|
1642
1373
|
createEffect(on(() => [targetElement(), lastGrabbedElement()], ([currentElement, lastElement]) => {
|
|
1643
1374
|
if (lastElement && currentElement && lastElement !== currentElement) {
|
|
1644
1375
|
setLastGrabbedElement(null);
|
|
1645
1376
|
}
|
|
1646
1377
|
}));
|
|
1647
|
-
const progress = createMemo(() => {
|
|
1648
|
-
const startTime = progressStartTime();
|
|
1649
|
-
progressTick();
|
|
1650
|
-
if (startTime === null) return 0;
|
|
1651
|
-
const elapsedTime = Date.now() - startTime;
|
|
1652
|
-
const normalizedTime = elapsedTime / options.keyHoldDuration;
|
|
1653
|
-
const easedProgress = 1 - Math.exp(-normalizedTime);
|
|
1654
|
-
const maxProgressBeforeCompletion = 0.95;
|
|
1655
|
-
if (isCopying()) {
|
|
1656
|
-
return Math.min(easedProgress, maxProgressBeforeCompletion);
|
|
1657
|
-
}
|
|
1658
|
-
return 1;
|
|
1659
|
-
});
|
|
1660
1378
|
const startProgressAnimation = () => {
|
|
1661
|
-
|
|
1379
|
+
const startTime = Date.now();
|
|
1380
|
+
setProgressStartTime(startTime);
|
|
1662
1381
|
setShowProgressIndicator(false);
|
|
1663
1382
|
progressDelayTimerId = window.setTimeout(() => {
|
|
1664
1383
|
setShowProgressIndicator(true);
|
|
1665
1384
|
progressDelayTimerId = null;
|
|
1666
1385
|
}, PROGRESS_INDICATOR_DELAY_MS);
|
|
1667
1386
|
const animateProgress = () => {
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
const
|
|
1387
|
+
const currentStartTime = progressStartTime();
|
|
1388
|
+
if (currentStartTime === null) return;
|
|
1389
|
+
const elapsedTime = Date.now() - currentStartTime;
|
|
1390
|
+
const normalizedTime = elapsedTime / options.keyHoldDuration;
|
|
1391
|
+
const easedProgress = 1 - Math.exp(-normalizedTime);
|
|
1392
|
+
const maxProgressBeforeCompletion = 0.95;
|
|
1393
|
+
const currentProgress = isCopying() ? Math.min(easedProgress, maxProgressBeforeCompletion) : 1;
|
|
1394
|
+
setProgress(currentProgress);
|
|
1671
1395
|
if (currentProgress < 1) {
|
|
1672
1396
|
progressAnimationId = requestAnimationFrame(animateProgress);
|
|
1673
1397
|
}
|
|
@@ -1684,6 +1408,7 @@ ${context}
|
|
|
1684
1408
|
progressDelayTimerId = null;
|
|
1685
1409
|
}
|
|
1686
1410
|
setProgressStartTime(null);
|
|
1411
|
+
setProgress(1);
|
|
1687
1412
|
setShowProgressIndicator(false);
|
|
1688
1413
|
};
|
|
1689
1414
|
const activateRenderer = () => {
|
|
@@ -1707,8 +1432,6 @@ ${context}
|
|
|
1707
1432
|
mouseSettleTimerId = null;
|
|
1708
1433
|
}
|
|
1709
1434
|
setMouseHasSettled(false);
|
|
1710
|
-
referenceMouseX = OFFSCREEN_POSITION;
|
|
1711
|
-
referenceMouseY = OFFSCREEN_POSITION;
|
|
1712
1435
|
stopProgressAnimation();
|
|
1713
1436
|
};
|
|
1714
1437
|
const abortController = new AbortController();
|
|
@@ -1775,34 +1498,14 @@ ${context}
|
|
|
1775
1498
|
window.addEventListener("mousemove", (event) => {
|
|
1776
1499
|
setMouseX(event.clientX);
|
|
1777
1500
|
setMouseY(event.clientY);
|
|
1778
|
-
if (
|
|
1779
|
-
|
|
1780
|
-
referenceMouseY = event.clientY;
|
|
1781
|
-
}
|
|
1782
|
-
const deltaX = event.clientX - referenceMouseX;
|
|
1783
|
-
const deltaY = event.clientY - referenceMouseY;
|
|
1784
|
-
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
1785
|
-
if (distance >= 200) {
|
|
1786
|
-
if (mouseSettleTimerId !== null) {
|
|
1787
|
-
window.clearTimeout(mouseSettleTimerId);
|
|
1788
|
-
}
|
|
1789
|
-
setMouseHasSettled(false);
|
|
1790
|
-
referenceMouseX = event.clientX;
|
|
1791
|
-
referenceMouseY = event.clientY;
|
|
1792
|
-
mouseSettleTimerId = window.setTimeout(() => {
|
|
1793
|
-
setMouseHasSettled(true);
|
|
1794
|
-
referenceMouseX = mouseX();
|
|
1795
|
-
referenceMouseY = mouseY();
|
|
1796
|
-
mouseSettleTimerId = null;
|
|
1797
|
-
}, 100);
|
|
1798
|
-
} else if (mouseSettleTimerId === null && !mouseHasSettled()) {
|
|
1799
|
-
mouseSettleTimerId = window.setTimeout(() => {
|
|
1800
|
-
setMouseHasSettled(true);
|
|
1801
|
-
referenceMouseX = mouseX();
|
|
1802
|
-
referenceMouseY = mouseY();
|
|
1803
|
-
mouseSettleTimerId = null;
|
|
1804
|
-
}, 100);
|
|
1501
|
+
if (mouseSettleTimerId !== null) {
|
|
1502
|
+
window.clearTimeout(mouseSettleTimerId);
|
|
1805
1503
|
}
|
|
1504
|
+
setMouseHasSettled(false);
|
|
1505
|
+
mouseSettleTimerId = window.setTimeout(() => {
|
|
1506
|
+
setMouseHasSettled(true);
|
|
1507
|
+
mouseSettleTimerId = null;
|
|
1508
|
+
}, 300);
|
|
1806
1509
|
}, {
|
|
1807
1510
|
signal: eventListenerSignal
|
|
1808
1511
|
});
|
|
@@ -1886,7 +1589,7 @@ ${context}
|
|
|
1886
1589
|
const labelVisible = createMemo(() => {
|
|
1887
1590
|
if (isCopying()) return true;
|
|
1888
1591
|
if (successLabels().length > 0) return false;
|
|
1889
|
-
return isRendererActive() && !isDragging() &&
|
|
1592
|
+
return isRendererActive() && !isDragging() && Boolean(targetElement());
|
|
1890
1593
|
});
|
|
1891
1594
|
const progressVisible = createMemo(() => isCopying() && showProgressIndicator() && hasValidMousePosition());
|
|
1892
1595
|
const crosshairVisible = createMemo(() => isRendererActive() && !isDragging());
|
|
@@ -1924,7 +1627,10 @@ ${context}
|
|
|
1924
1627
|
get labelVisible() {
|
|
1925
1628
|
return labelVisible();
|
|
1926
1629
|
},
|
|
1927
|
-
labelZIndex:
|
|
1630
|
+
labelZIndex: Z_INDEX_LABEL,
|
|
1631
|
+
get labelShowHint() {
|
|
1632
|
+
return mouseHasSettled();
|
|
1633
|
+
},
|
|
1928
1634
|
get progressVisible() {
|
|
1929
1635
|
return progressVisible();
|
|
1930
1636
|
},
|
|
@@ -1970,9 +1676,6 @@ ${context}
|
|
|
1970
1676
|
// src/index.ts
|
|
1971
1677
|
var globalApi = null;
|
|
1972
1678
|
var getGlobalApi = () => globalApi;
|
|
1973
|
-
|
|
1974
|
-
if (!window[EXTENSION_MARKER]) {
|
|
1975
|
-
globalApi = init();
|
|
1976
|
-
}
|
|
1679
|
+
globalApi = init();
|
|
1977
1680
|
|
|
1978
|
-
export {
|
|
1681
|
+
export { getGlobalApi, init, playCopySound };
|