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.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,91 @@ 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(`<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">`);
|
|
362
|
+
var _tmpl$22 = /* @__PURE__ */ web.template(`<span style=display:inline-block;margin-right:4px;font-weight:600>\u2713`);
|
|
363
|
+
var _tmpl$32 = /* @__PURE__ */ web.template(`<div style=margin-right:4px>Copied`);
|
|
364
|
+
var _tmpl$4 = /* @__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">`);
|
|
365
|
+
var _tmpl$5 = /* @__PURE__ */ web.template(`<span style=font-variant-numeric:tabular-nums;font-size:10px;margin-left:4px;vertical-align:middle>`);
|
|
366
|
+
var _tmpl$6 = /* @__PURE__ */ web.template(`<div style=margin-left:4px>to clipboard`);
|
|
367
|
+
var _tmpl$7 = /* @__PURE__ */ web.template(`<div style=font-size:9px;opacity:0.6;text-align:center;margin-top:2px>Click or drag to select`);
|
|
368
|
+
var _tmpl$8 = /* @__PURE__ */ web.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>`);
|
|
369
|
+
var Label = (props) => {
|
|
370
|
+
let labelRef;
|
|
371
|
+
const position = useAnimatedPosition({
|
|
372
|
+
x: () => props.x,
|
|
373
|
+
y: () => props.y,
|
|
374
|
+
lerpFactor: 0.3
|
|
375
|
+
});
|
|
376
|
+
const opacity = useFadeInOut({
|
|
377
|
+
visible: props.visible,
|
|
378
|
+
autoFadeOutAfter: props.variant === "success" ? SUCCESS_LABEL_DURATION_MS : void 0
|
|
379
|
+
});
|
|
340
380
|
const labelBoundingRect = () => labelRef?.getBoundingClientRect();
|
|
341
381
|
const computedPosition = () => {
|
|
342
|
-
positionTick();
|
|
343
382
|
const boundingRect = labelBoundingRect();
|
|
344
383
|
if (!boundingRect) return {
|
|
345
|
-
left:
|
|
346
|
-
top:
|
|
384
|
+
left: position.x(),
|
|
385
|
+
top: position.y()
|
|
347
386
|
};
|
|
348
387
|
const viewportWidth = window.innerWidth;
|
|
349
388
|
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;
|
|
389
|
+
const quadrants = getCursorQuadrants(position.x(), position.y(), boundingRect.width, boundingRect.height, CURSOR_OFFSET_PX);
|
|
390
|
+
for (const position2 of quadrants) {
|
|
391
|
+
const fitsHorizontally = position2.left >= VIEWPORT_MARGIN_PX && position2.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
|
|
392
|
+
const fitsVertically = position2.top >= VIEWPORT_MARGIN_PX && position2.top + boundingRect.height <= viewportHeight - VIEWPORT_MARGIN_PX;
|
|
366
393
|
if (fitsHorizontally && fitsVertically) {
|
|
367
|
-
return
|
|
394
|
+
return position2;
|
|
368
395
|
}
|
|
369
396
|
}
|
|
370
397
|
const fallback = getClampedElementPosition(quadrants[0].left, quadrants[0].top, boundingRect.width, boundingRect.height);
|
|
@@ -391,10 +418,20 @@ var Label = (props) => {
|
|
|
391
418
|
return props.visible !== false;
|
|
392
419
|
},
|
|
393
420
|
get children() {
|
|
394
|
-
var _el$ = _tmpl$
|
|
421
|
+
var _el$ = _tmpl$8(), _el$3 = _el$.firstChild, _el$4 = _el$3.firstChild;
|
|
395
422
|
var _ref$ = labelRef;
|
|
396
423
|
typeof _ref$ === "function" ? web.use(_ref$, _el$) : labelRef = _el$;
|
|
397
424
|
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
425
|
+
get when() {
|
|
426
|
+
return web.memo(() => props.variant === "processing")() && props.progress !== void 0;
|
|
427
|
+
},
|
|
428
|
+
get children() {
|
|
429
|
+
var _el$2 = _tmpl$3();
|
|
430
|
+
web.effect((_$p) => web.setStyleProperty(_el$2, "width", `${Math.min(100, Math.max(0, (props.progress ?? 0) * 100))}%`));
|
|
431
|
+
return _el$2;
|
|
432
|
+
}
|
|
433
|
+
}), _el$3);
|
|
434
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
398
435
|
get when() {
|
|
399
436
|
return props.variant === "processing";
|
|
400
437
|
},
|
|
@@ -402,55 +439,63 @@ var Label = (props) => {
|
|
|
402
439
|
return web.createComponent(Spinner, {});
|
|
403
440
|
}
|
|
404
441
|
}), null);
|
|
405
|
-
web.insert(_el
|
|
442
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
406
443
|
get when() {
|
|
407
444
|
return props.variant === "success";
|
|
408
445
|
},
|
|
409
446
|
get children() {
|
|
410
|
-
return _tmpl$
|
|
447
|
+
return _tmpl$22();
|
|
411
448
|
}
|
|
412
449
|
}), null);
|
|
413
|
-
web.insert(_el
|
|
450
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
414
451
|
get when() {
|
|
415
452
|
return props.variant === "success";
|
|
416
453
|
},
|
|
417
454
|
get children() {
|
|
418
|
-
return _tmpl$
|
|
455
|
+
return _tmpl$32();
|
|
419
456
|
}
|
|
420
457
|
}), null);
|
|
421
|
-
web.insert(_el
|
|
458
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
422
459
|
get when() {
|
|
423
460
|
return props.variant === "processing";
|
|
424
461
|
},
|
|
425
|
-
children: "
|
|
462
|
+
children: "Please wait\u2026"
|
|
426
463
|
}), null);
|
|
427
|
-
web.insert(_el
|
|
464
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
428
465
|
get when() {
|
|
429
466
|
return props.variant !== "processing";
|
|
430
467
|
},
|
|
431
468
|
get children() {
|
|
432
469
|
return [(() => {
|
|
433
|
-
var _el$
|
|
434
|
-
web.insert(_el$
|
|
435
|
-
return _el$
|
|
470
|
+
var _el$7 = _tmpl$4();
|
|
471
|
+
web.insert(_el$7, () => labelSegments().primary);
|
|
472
|
+
return _el$7;
|
|
436
473
|
})(), web.createComponent(solidJs.Show, {
|
|
437
474
|
get when() {
|
|
438
475
|
return web.memo(() => props.variant === "hover")() && labelSegments().secondary !== "";
|
|
439
476
|
},
|
|
440
477
|
get children() {
|
|
441
|
-
var _el$
|
|
442
|
-
web.insert(_el$
|
|
443
|
-
return _el$
|
|
478
|
+
var _el$8 = _tmpl$5();
|
|
479
|
+
web.insert(_el$8, () => labelSegments().secondary);
|
|
480
|
+
return _el$8;
|
|
444
481
|
}
|
|
445
482
|
})];
|
|
446
483
|
}
|
|
447
484
|
}), null);
|
|
448
|
-
web.insert(_el
|
|
485
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
449
486
|
get when() {
|
|
450
487
|
return props.variant === "success";
|
|
451
488
|
},
|
|
452
489
|
get children() {
|
|
453
|
-
return _tmpl$
|
|
490
|
+
return _tmpl$6();
|
|
491
|
+
}
|
|
492
|
+
}), null);
|
|
493
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
494
|
+
get when() {
|
|
495
|
+
return web.memo(() => props.variant === "hover")() && props.showHint;
|
|
496
|
+
},
|
|
497
|
+
get children() {
|
|
498
|
+
return _tmpl$7();
|
|
454
499
|
}
|
|
455
500
|
}), null);
|
|
456
501
|
web.effect((_p$) => {
|
|
@@ -470,22 +515,11 @@ var Label = (props) => {
|
|
|
470
515
|
}
|
|
471
516
|
});
|
|
472
517
|
};
|
|
473
|
-
var _tmpl$
|
|
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
|
-
};
|
|
518
|
+
var _tmpl$9 = /* @__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)">`);
|
|
487
519
|
var ProgressIndicator = (props) => {
|
|
488
|
-
const opacity = useFadeInOut(
|
|
520
|
+
const opacity = useFadeInOut({
|
|
521
|
+
visible: props.visible
|
|
522
|
+
});
|
|
489
523
|
let progressIndicatorRef;
|
|
490
524
|
const computedPosition = () => {
|
|
491
525
|
const boundingRect = progressIndicatorRef?.getBoundingClientRect();
|
|
@@ -503,7 +537,7 @@ var ProgressIndicator = (props) => {
|
|
|
503
537
|
return props.visible !== false;
|
|
504
538
|
},
|
|
505
539
|
get children() {
|
|
506
|
-
var _el$ = _tmpl$
|
|
540
|
+
var _el$ = _tmpl$9(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
|
|
507
541
|
var _ref$ = progressIndicatorRef;
|
|
508
542
|
typeof _ref$ === "function" ? web.use(_ref$, _el$) : progressIndicatorRef = _el$;
|
|
509
543
|
web.effect((_p$) => {
|
|
@@ -523,19 +557,18 @@ var ProgressIndicator = (props) => {
|
|
|
523
557
|
}
|
|
524
558
|
});
|
|
525
559
|
};
|
|
526
|
-
var _tmpl$
|
|
560
|
+
var _tmpl$10 = /* @__PURE__ */ web.template(`<canvas style=position:fixed;top:0;left:0;pointer-events:none;z-index:2147483645>`);
|
|
527
561
|
var Crosshair = (props) => {
|
|
528
562
|
let canvasRef;
|
|
529
563
|
let context = null;
|
|
530
564
|
let width = 0;
|
|
531
565
|
let height = 0;
|
|
532
566
|
let dpr = 1;
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
let hasBeenRenderedOnce = false;
|
|
567
|
+
const position = useAnimatedPosition({
|
|
568
|
+
x: () => props.mouseX,
|
|
569
|
+
y: () => props.mouseY,
|
|
570
|
+
lerpFactor: 0.3
|
|
571
|
+
});
|
|
539
572
|
const setupCanvas = () => {
|
|
540
573
|
if (!canvasRef) return;
|
|
541
574
|
dpr = Math.max(window.devicePixelRatio || 1, 2);
|
|
@@ -556,39 +589,12 @@ var Crosshair = (props) => {
|
|
|
556
589
|
context.strokeStyle = "rgba(210, 57, 192)";
|
|
557
590
|
context.lineWidth = 1;
|
|
558
591
|
context.beginPath();
|
|
559
|
-
context.moveTo(
|
|
560
|
-
context.lineTo(
|
|
561
|
-
context.moveTo(0,
|
|
562
|
-
context.lineTo(width,
|
|
592
|
+
context.moveTo(position.x(), 0);
|
|
593
|
+
context.lineTo(position.x(), height);
|
|
594
|
+
context.moveTo(0, position.y());
|
|
595
|
+
context.lineTo(width, position.y());
|
|
563
596
|
context.stroke();
|
|
564
597
|
};
|
|
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
598
|
solidJs.createEffect(() => {
|
|
593
599
|
setupCanvas();
|
|
594
600
|
render2();
|
|
@@ -599,21 +605,19 @@ var Crosshair = (props) => {
|
|
|
599
605
|
window.addEventListener("resize", handleResize);
|
|
600
606
|
solidJs.onCleanup(() => {
|
|
601
607
|
window.removeEventListener("resize", handleResize);
|
|
602
|
-
if (animationFrameId !== null) {
|
|
603
|
-
cancelAnimationFrame(animationFrameId);
|
|
604
|
-
animationFrameId = null;
|
|
605
|
-
}
|
|
606
608
|
});
|
|
607
609
|
});
|
|
608
610
|
solidJs.createEffect(() => {
|
|
609
|
-
|
|
611
|
+
position.x();
|
|
612
|
+
position.y();
|
|
613
|
+
render2();
|
|
610
614
|
});
|
|
611
615
|
return web.createComponent(solidJs.Show, {
|
|
612
616
|
get when() {
|
|
613
617
|
return props.visible !== false;
|
|
614
618
|
},
|
|
615
619
|
get children() {
|
|
616
|
-
var _el$ = _tmpl$
|
|
620
|
+
var _el$ = _tmpl$10();
|
|
617
621
|
var _ref$ = canvasRef;
|
|
618
622
|
typeof _ref$ === "function" ? web.use(_ref$, _el$) : canvasRef = _el$;
|
|
619
623
|
return _el$;
|
|
@@ -681,22 +685,29 @@ var ReactGrabRenderer = (props) => {
|
|
|
681
685
|
return box.createdAt;
|
|
682
686
|
}
|
|
683
687
|
})
|
|
684
|
-
}), web.createComponent(solidJs.
|
|
685
|
-
get
|
|
686
|
-
return props.
|
|
688
|
+
}), web.createComponent(solidJs.Show, {
|
|
689
|
+
get when() {
|
|
690
|
+
return props.labelVariant !== "processing";
|
|
687
691
|
},
|
|
688
|
-
children
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
692
|
+
get children() {
|
|
693
|
+
return web.createComponent(solidJs.For, {
|
|
694
|
+
get each() {
|
|
695
|
+
return props.successLabels ?? [];
|
|
696
|
+
},
|
|
697
|
+
children: (label) => web.createComponent(Label, {
|
|
698
|
+
variant: "success",
|
|
699
|
+
get text() {
|
|
700
|
+
return label.text;
|
|
701
|
+
},
|
|
702
|
+
get x() {
|
|
703
|
+
return props.mouseX ?? 0;
|
|
704
|
+
},
|
|
705
|
+
get y() {
|
|
706
|
+
return props.mouseY ?? 0;
|
|
707
|
+
}
|
|
708
|
+
})
|
|
709
|
+
});
|
|
710
|
+
}
|
|
700
711
|
}), web.createComponent(solidJs.Show, {
|
|
701
712
|
get when() {
|
|
702
713
|
return web.memo(() => !!(props.labelVisible && props.labelVariant && props.labelText && props.labelX !== void 0))() && props.labelY !== void 0;
|
|
@@ -720,6 +731,12 @@ var ReactGrabRenderer = (props) => {
|
|
|
720
731
|
},
|
|
721
732
|
get zIndex() {
|
|
722
733
|
return props.labelZIndex;
|
|
734
|
+
},
|
|
735
|
+
get progress() {
|
|
736
|
+
return props.progress;
|
|
737
|
+
},
|
|
738
|
+
get showHint() {
|
|
739
|
+
return props.labelShowHint;
|
|
723
740
|
}
|
|
724
741
|
});
|
|
725
742
|
}
|
|
@@ -750,27 +767,62 @@ var ReactGrabRenderer = (props) => {
|
|
|
750
767
|
var isCapitalized = (value) => value.length > 0 && /^[A-Z]/.test(value);
|
|
751
768
|
|
|
752
769
|
// src/instrumentation.ts
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
770
|
+
var NEXT_INTERNAL_COMPONENT_NAMES = [
|
|
771
|
+
"InnerLayoutRouter",
|
|
772
|
+
"RedirectErrorBoundary",
|
|
773
|
+
"RedirectBoundary",
|
|
774
|
+
"HTTPAccessFallbackErrorBoundary",
|
|
775
|
+
"HTTPAccessFallbackBoundary",
|
|
776
|
+
"LoadingBoundary",
|
|
777
|
+
"ErrorBoundary",
|
|
778
|
+
"InnerScrollAndFocusHandler",
|
|
779
|
+
"ScrollAndFocusHandler",
|
|
780
|
+
"RenderFromTemplateContext",
|
|
781
|
+
"OuterLayoutRouter",
|
|
782
|
+
"body",
|
|
783
|
+
"html",
|
|
784
|
+
"RedirectErrorBoundary",
|
|
785
|
+
"RedirectBoundary",
|
|
786
|
+
"HTTPAccessFallbackErrorBoundary",
|
|
787
|
+
"HTTPAccessFallbackBoundary",
|
|
788
|
+
"DevRootHTTPAccessFallbackBoundary",
|
|
789
|
+
"AppDevOverlayErrorBoundary",
|
|
790
|
+
"AppDevOverlay",
|
|
791
|
+
"HotReload",
|
|
792
|
+
"Router",
|
|
793
|
+
"ErrorBoundaryHandler",
|
|
794
|
+
"ErrorBoundary",
|
|
795
|
+
"AppRouter",
|
|
796
|
+
"ServerRoot",
|
|
797
|
+
"SegmentStateProvider",
|
|
798
|
+
"RootErrorBoundary"
|
|
799
|
+
];
|
|
800
|
+
var checkIsNextProject = () => {
|
|
801
|
+
return Boolean(document.getElementById("__NEXT_DATA__"));
|
|
802
|
+
};
|
|
803
|
+
var checkIsInternalComponentName = (name) => {
|
|
804
|
+
if (name.startsWith("_")) return true;
|
|
805
|
+
if (NEXT_INTERNAL_COMPONENT_NAMES.includes(name)) return true;
|
|
806
|
+
return false;
|
|
807
|
+
};
|
|
808
|
+
var checkIsSourceComponentName = (name) => {
|
|
809
|
+
if (checkIsInternalComponentName(name)) return false;
|
|
810
|
+
if (!isCapitalized(name)) return false;
|
|
811
|
+
if (name.startsWith("Primitive.")) return false;
|
|
812
|
+
if (name.includes("Provider") && name.includes("Context")) return false;
|
|
813
|
+
return true;
|
|
760
814
|
};
|
|
761
|
-
var
|
|
762
|
-
var isInternalComponent = (name) => !isCapitalized(name) || name.startsWith("_") || name.startsWith("Primitive.") || name.includes("Provider") && name.includes("Context");
|
|
763
|
-
var getNearestComponentDisplayName = (element) => {
|
|
815
|
+
var getNearestComponentName = (element) => {
|
|
764
816
|
const fiber = bippy.getFiberFromHostInstance(element);
|
|
765
817
|
if (!fiber) return null;
|
|
766
|
-
let
|
|
818
|
+
let foundComponentName = null;
|
|
767
819
|
bippy.traverseFiber(
|
|
768
820
|
fiber,
|
|
769
821
|
(currentFiber) => {
|
|
770
822
|
if (bippy.isCompositeFiber(currentFiber)) {
|
|
771
823
|
const displayName = bippy.getDisplayName(currentFiber);
|
|
772
|
-
if (displayName &&
|
|
773
|
-
|
|
824
|
+
if (displayName && checkIsSourceComponentName(displayName)) {
|
|
825
|
+
foundComponentName = displayName;
|
|
774
826
|
return true;
|
|
775
827
|
}
|
|
776
828
|
}
|
|
@@ -778,231 +830,107 @@ var getNearestComponentDisplayName = (element) => {
|
|
|
778
830
|
},
|
|
779
831
|
true
|
|
780
832
|
);
|
|
781
|
-
return
|
|
833
|
+
return foundComponentName;
|
|
782
834
|
};
|
|
783
|
-
var
|
|
784
|
-
const
|
|
785
|
-
if (!
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
};
|
|
798
|
-
var getHTMLSnippet = async (element) => {
|
|
799
|
-
const semanticTags = /* @__PURE__ */ new Set([
|
|
800
|
-
"article",
|
|
801
|
-
"aside",
|
|
802
|
-
"footer",
|
|
803
|
-
"form",
|
|
804
|
-
"header",
|
|
805
|
-
"main",
|
|
806
|
-
"nav",
|
|
807
|
-
"section"
|
|
808
|
-
]);
|
|
809
|
-
const hasDistinguishingFeatures = (el) => {
|
|
810
|
-
const tagName = el.tagName.toLowerCase();
|
|
811
|
-
if (semanticTags.has(tagName)) return true;
|
|
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]}`;
|
|
835
|
+
var getStack = async (element) => {
|
|
836
|
+
const maybeFiber = bippy.getFiberFromHostInstance(element);
|
|
837
|
+
if (!maybeFiber || !bippy.isFiber(maybeFiber)) return [];
|
|
838
|
+
const fiber = bippy.getLatestFiber(maybeFiber);
|
|
839
|
+
const unresolvedStack = [];
|
|
840
|
+
bippy.traverseFiber(
|
|
841
|
+
fiber,
|
|
842
|
+
(currentFiber) => {
|
|
843
|
+
const displayName = bippy.isHostFiber(currentFiber) ? typeof currentFiber.type === "string" ? currentFiber.type : null : bippy.getDisplayName(currentFiber);
|
|
844
|
+
if (displayName && !checkIsInternalComponentName(displayName)) {
|
|
845
|
+
unresolvedStack.push({
|
|
846
|
+
name: displayName,
|
|
847
|
+
sourcePromise: source.getSource(currentFiber)
|
|
848
|
+
});
|
|
873
849
|
}
|
|
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)
|
|
850
|
+
},
|
|
851
|
+
true
|
|
888
852
|
);
|
|
889
|
-
const
|
|
890
|
-
|
|
891
|
-
|
|
853
|
+
const resolvedStack = await Promise.all(
|
|
854
|
+
unresolvedStack.map(async (frame) => ({
|
|
855
|
+
name: frame.name,
|
|
856
|
+
source: await frame.sourcePromise
|
|
857
|
+
}))
|
|
892
858
|
);
|
|
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++;
|
|
859
|
+
return resolvedStack.filter((frame) => frame.source !== null);
|
|
860
|
+
};
|
|
861
|
+
var formatStack = (stack) => {
|
|
862
|
+
const isNextProject = checkIsNextProject();
|
|
863
|
+
return stack.map(({ name, source: source$1 }) => {
|
|
864
|
+
if (!source$1) return ` at ${name}`;
|
|
865
|
+
if (source$1.fileName.startsWith("about://React/Server")) {
|
|
866
|
+
return ` at ${name} (Server)`;
|
|
908
867
|
}
|
|
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
|
-
}
|
|
868
|
+
if (!source.isSourceFile(source$1.fileName)) return ` at ${name}`;
|
|
869
|
+
const framePart = ` at ${name} in ${source.normalizeFileName(source$1.fileName)}`;
|
|
870
|
+
if (isNextProject) {
|
|
871
|
+
return `${framePart}:${source$1.lineNumber}:${source$1.columnNumber}`;
|
|
936
872
|
}
|
|
873
|
+
return framePart;
|
|
874
|
+
}).join("\n");
|
|
875
|
+
};
|
|
876
|
+
var getHTMLPreview = (element) => {
|
|
877
|
+
const tagName = element.tagName.toLowerCase();
|
|
878
|
+
if (!(element instanceof HTMLElement)) {
|
|
879
|
+
return `<${tagName} />`;
|
|
937
880
|
}
|
|
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}`);
|
|
881
|
+
const text = element.innerText?.trim() ?? element.textContent?.trim() ?? "";
|
|
882
|
+
let attrsText = "";
|
|
883
|
+
const attributes = Array.from(element.attributes);
|
|
884
|
+
for (const attribute of attributes) {
|
|
885
|
+
const name = attribute.name;
|
|
886
|
+
let value = attribute.value;
|
|
887
|
+
if (value.length > 20) {
|
|
888
|
+
value = `${value.slice(0, 20)}...`;
|
|
962
889
|
}
|
|
963
|
-
|
|
964
|
-
lines.push(
|
|
965
|
-
`${elementIndent} ... (${childrenCount} element${childrenCount === 1 ? "" : "s"})`
|
|
966
|
-
);
|
|
967
|
-
}
|
|
968
|
-
lines.push(`${elementIndent}${formatElementClosingTag(element)}`);
|
|
969
|
-
}
|
|
970
|
-
if (showElementComponent) {
|
|
971
|
-
lines.push(
|
|
972
|
-
`${getIndent(elementComponentIndentLevel)}</${elementComponent}>`
|
|
973
|
-
);
|
|
890
|
+
attrsText += ` ${name}="${value}"`;
|
|
974
891
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
}
|
|
892
|
+
const topElements = [];
|
|
893
|
+
const bottomElements = [];
|
|
894
|
+
let foundFirstText = false;
|
|
895
|
+
const childNodes = Array.from(element.childNodes);
|
|
896
|
+
for (const node of childNodes) {
|
|
897
|
+
if (node.nodeType === Node.COMMENT_NODE) continue;
|
|
898
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
899
|
+
if (node.textContent && node.textContent.trim().length > 0) {
|
|
900
|
+
foundFirstText = true;
|
|
901
|
+
}
|
|
902
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
903
|
+
if (!foundFirstText) {
|
|
904
|
+
topElements.push(node);
|
|
989
905
|
} else {
|
|
990
|
-
|
|
991
|
-
`${indent}... (${siblingsAfter} element${siblingsAfter === 1 ? "" : "s"})`
|
|
992
|
-
);
|
|
906
|
+
bottomElements.push(node);
|
|
993
907
|
}
|
|
994
908
|
}
|
|
995
909
|
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
const compIndent = getIndent(ancestorComponentIndents[i]);
|
|
1001
|
-
lines.push(`${compIndent}</${ancestorComponents[i]}>`);
|
|
910
|
+
const formatElements = (elements) => {
|
|
911
|
+
if (elements.length === 0) return "";
|
|
912
|
+
if (elements.length <= 2) {
|
|
913
|
+
return elements.map((el) => `<${el.tagName.toLowerCase()} ...>`).join("\n ");
|
|
1002
914
|
}
|
|
915
|
+
return `(${elements.length} elements)`;
|
|
916
|
+
};
|
|
917
|
+
let content = "";
|
|
918
|
+
const topElementsStr = formatElements(topElements);
|
|
919
|
+
if (topElementsStr) content += `
|
|
920
|
+
${topElementsStr}`;
|
|
921
|
+
if (text.length > 0) {
|
|
922
|
+
const truncatedText = text.length > 100 ? `${text.slice(0, 100)}...` : text;
|
|
923
|
+
content += `
|
|
924
|
+
${truncatedText}`;
|
|
925
|
+
}
|
|
926
|
+
const bottomElementsStr = formatElements(bottomElements);
|
|
927
|
+
if (bottomElementsStr) content += `
|
|
928
|
+
${bottomElementsStr}`;
|
|
929
|
+
if (content.length > 0) {
|
|
930
|
+
return `<${tagName}${attrsText}>${content}
|
|
931
|
+
</${tagName}>`;
|
|
1003
932
|
}
|
|
1004
|
-
|
|
1005
|
-
return lines.join("\n");
|
|
933
|
+
return `<${tagName}${attrsText} />`;
|
|
1006
934
|
};
|
|
1007
935
|
|
|
1008
936
|
// src/utils/copy-content.ts
|
|
@@ -1022,73 +950,13 @@ var waitForFocus = () => {
|
|
|
1022
950
|
var copyContent = async (content, onSuccess) => {
|
|
1023
951
|
await waitForFocus();
|
|
1024
952
|
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
|
-
]);
|
|
953
|
+
try {
|
|
954
|
+
await navigator.clipboard.writeText(content);
|
|
1081
955
|
onSuccess?.();
|
|
1082
956
|
return true;
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
onSuccess?.();
|
|
1087
|
-
return true;
|
|
1088
|
-
} catch {
|
|
1089
|
-
const result = copyContentFallback(content, onSuccess);
|
|
1090
|
-
return result;
|
|
1091
|
-
}
|
|
957
|
+
} catch {
|
|
958
|
+
const result = copyContentFallback(content, onSuccess);
|
|
959
|
+
return result;
|
|
1092
960
|
}
|
|
1093
961
|
} catch {
|
|
1094
962
|
return false;
|
|
@@ -1177,13 +1045,27 @@ var getElementAtPosition = (clientX, clientY) => {
|
|
|
1177
1045
|
|
|
1178
1046
|
// src/utils/get-elements-in-drag.ts
|
|
1179
1047
|
var DRAG_COVERAGE_THRESHOLD = 0.75;
|
|
1048
|
+
var calculateIntersectionArea = (rect1, rect2) => {
|
|
1049
|
+
const intersectionLeft = Math.max(rect1.left, rect2.left);
|
|
1050
|
+
const intersectionTop = Math.max(rect1.top, rect2.top);
|
|
1051
|
+
const intersectionRight = Math.min(rect1.right, rect2.right);
|
|
1052
|
+
const intersectionBottom = Math.min(rect1.bottom, rect2.bottom);
|
|
1053
|
+
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
1054
|
+
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
1055
|
+
return intersectionWidth * intersectionHeight;
|
|
1056
|
+
};
|
|
1057
|
+
var hasIntersection = (rect1, rect2) => {
|
|
1058
|
+
return rect1.left < rect2.right && rect1.right > rect2.left && rect1.top < rect2.bottom && rect1.bottom > rect2.top;
|
|
1059
|
+
};
|
|
1180
1060
|
var filterElementsInDrag = (dragRect, isValidGrabbableElement2, shouldCheckCoverage) => {
|
|
1181
1061
|
const elements = [];
|
|
1182
1062
|
const allElements = Array.from(document.querySelectorAll("*"));
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1063
|
+
const dragBounds = {
|
|
1064
|
+
left: dragRect.x,
|
|
1065
|
+
top: dragRect.y,
|
|
1066
|
+
right: dragRect.x + dragRect.width,
|
|
1067
|
+
bottom: dragRect.y + dragRect.height
|
|
1068
|
+
};
|
|
1187
1069
|
for (const candidateElement of allElements) {
|
|
1188
1070
|
if (!shouldCheckCoverage) {
|
|
1189
1071
|
const tagName = (candidateElement.tagName || "").toUpperCase();
|
|
@@ -1193,26 +1075,21 @@ var filterElementsInDrag = (dragRect, isValidGrabbableElement2, shouldCheckCover
|
|
|
1193
1075
|
continue;
|
|
1194
1076
|
}
|
|
1195
1077
|
const elementRect = candidateElement.getBoundingClientRect();
|
|
1196
|
-
const
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1078
|
+
const elementBounds = {
|
|
1079
|
+
left: elementRect.left,
|
|
1080
|
+
top: elementRect.top,
|
|
1081
|
+
right: elementRect.left + elementRect.width,
|
|
1082
|
+
bottom: elementRect.top + elementRect.height
|
|
1083
|
+
};
|
|
1200
1084
|
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;
|
|
1085
|
+
const intersectionArea = calculateIntersectionArea(dragBounds, elementBounds);
|
|
1208
1086
|
const elementArea = Math.max(0, elementRect.width * elementRect.height);
|
|
1209
1087
|
const hasMajorityCoverage = elementArea > 0 && intersectionArea / elementArea >= DRAG_COVERAGE_THRESHOLD;
|
|
1210
1088
|
if (hasMajorityCoverage) {
|
|
1211
1089
|
elements.push(candidateElement);
|
|
1212
1090
|
}
|
|
1213
1091
|
} else {
|
|
1214
|
-
|
|
1215
|
-
if (hasIntersection) {
|
|
1092
|
+
if (hasIntersection(elementBounds, dragBounds)) {
|
|
1216
1093
|
elements.push(candidateElement);
|
|
1217
1094
|
}
|
|
1218
1095
|
}
|
|
@@ -1251,70 +1128,7 @@ var createElementBounds = (element) => {
|
|
|
1251
1128
|
};
|
|
1252
1129
|
};
|
|
1253
1130
|
|
|
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
1131
|
// src/core.tsx
|
|
1317
|
-
var PROGRESS_INDICATOR_DELAY_MS = 150;
|
|
1318
1132
|
var init = (rawOptions) => {
|
|
1319
1133
|
const options = {
|
|
1320
1134
|
enabled: true,
|
|
@@ -1337,7 +1151,6 @@ var init = (rawOptions) => {
|
|
|
1337
1151
|
};
|
|
1338
1152
|
}
|
|
1339
1153
|
return solidJs.createRoot((dispose) => {
|
|
1340
|
-
const OFFSCREEN_POSITION = -1e3;
|
|
1341
1154
|
const [isHoldingKeys, setIsHoldingKeys] = solidJs.createSignal(false);
|
|
1342
1155
|
const [mouseX, setMouseX] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
1343
1156
|
const [mouseY, setMouseY] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
@@ -1347,7 +1160,7 @@ var init = (rawOptions) => {
|
|
|
1347
1160
|
const [isCopying, setIsCopying] = solidJs.createSignal(false);
|
|
1348
1161
|
const [lastGrabbedElement, setLastGrabbedElement] = solidJs.createSignal(null);
|
|
1349
1162
|
const [progressStartTime, setProgressStartTime] = solidJs.createSignal(null);
|
|
1350
|
-
const [
|
|
1163
|
+
const [progress, setProgress] = solidJs.createSignal(0);
|
|
1351
1164
|
const [grabbedBoxes, setGrabbedBoxes] = solidJs.createSignal([]);
|
|
1352
1165
|
const [successLabels, setSuccessLabels] = solidJs.createSignal([]);
|
|
1353
1166
|
const [isActivated, setIsActivated] = solidJs.createSignal(false);
|
|
@@ -1362,8 +1175,6 @@ var init = (rawOptions) => {
|
|
|
1362
1175
|
let progressDelayTimerId = null;
|
|
1363
1176
|
let keydownSpamTimerId = null;
|
|
1364
1177
|
let mouseSettleTimerId = null;
|
|
1365
|
-
let referenceMouseX = OFFSCREEN_POSITION;
|
|
1366
|
-
let referenceMouseY = OFFSCREEN_POSITION;
|
|
1367
1178
|
const isRendererActive = solidJs.createMemo(() => isActivated() && !isCopying());
|
|
1368
1179
|
const hasValidMousePosition = solidJs.createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
|
|
1369
1180
|
const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "c";
|
|
@@ -1394,55 +1205,10 @@ var init = (rawOptions) => {
|
|
|
1394
1205
|
const wrapInSelectedElementTags = (context) => `<selected_element>
|
|
1395
1206
|
${context}
|
|
1396
1207
|
</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
1208
|
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
1209
|
const extractElementLabelText = (element) => {
|
|
1444
1210
|
const tagName = extractElementTagName(element);
|
|
1445
|
-
const componentName =
|
|
1211
|
+
const componentName = getNearestComponentName(element);
|
|
1446
1212
|
if (tagName && componentName) {
|
|
1447
1213
|
return `<${tagName}> in ${componentName}`;
|
|
1448
1214
|
}
|
|
@@ -1464,8 +1230,6 @@ ${context}
|
|
|
1464
1230
|
} catch {
|
|
1465
1231
|
}
|
|
1466
1232
|
};
|
|
1467
|
-
const isExtensionEnvironment = () => window.__REACT_GRAB_EXTENSION_ACTIVE__ === true || options.isExtension === true;
|
|
1468
|
-
const isExtensionTextOnlyMode = () => isExtensionEnvironment() && !isLocalhost();
|
|
1469
1233
|
const executeCopyOperation = async (positionX, positionY, operation) => {
|
|
1470
1234
|
setCopyStartX(positionX);
|
|
1471
1235
|
setCopyStartY(positionY);
|
|
@@ -1491,39 +1255,37 @@ ${context}
|
|
|
1491
1255
|
return element.textContent ?? "";
|
|
1492
1256
|
};
|
|
1493
1257
|
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));
|
|
1258
|
+
const tryCopyWithFallback = async (elements) => {
|
|
1498
1259
|
let didCopy = false;
|
|
1499
1260
|
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
|
-
}
|
|
1261
|
+
const elementSnippetResults = await Promise.allSettled(elements.map(async (element) => `## HTML Frame:
|
|
1262
|
+
${getHTMLPreview(element)}
|
|
1263
|
+
|
|
1264
|
+
## Code Location:
|
|
1265
|
+
${formatStack(await getStack(element))}`));
|
|
1266
|
+
const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
|
|
1267
|
+
if (elementSnippets.length > 0) {
|
|
1268
|
+
const plainTextContent = elementSnippets.map((snippet) => wrapInSelectedElementTags(snippet)).join("\n\n");
|
|
1269
|
+
didCopy = await copyContent(plainTextContent, options.playCopySound ? playCopySound : void 0);
|
|
1270
|
+
}
|
|
1271
|
+
if (!didCopy) {
|
|
1272
|
+
const plainTextContentOnly = createCombinedTextContent(elements);
|
|
1273
|
+
if (plainTextContentOnly.length > 0) {
|
|
1274
|
+
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1519
1275
|
}
|
|
1520
1276
|
}
|
|
1521
1277
|
} catch {
|
|
1522
|
-
const plainTextContentOnly = createCombinedTextContent(
|
|
1278
|
+
const plainTextContentOnly = createCombinedTextContent(elements);
|
|
1523
1279
|
if (plainTextContentOnly.length > 0) {
|
|
1524
1280
|
didCopy = await copyContent(plainTextContentOnly, options.playCopySound ? playCopySound : void 0);
|
|
1525
1281
|
}
|
|
1526
1282
|
}
|
|
1283
|
+
return didCopy;
|
|
1284
|
+
};
|
|
1285
|
+
const copySingleElementToClipboard = async (targetElement2) => {
|
|
1286
|
+
showTemporaryGrabbedBox(createElementBounds(targetElement2));
|
|
1287
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
1288
|
+
const didCopy = await tryCopyWithFallback([targetElement2]);
|
|
1527
1289
|
if (didCopy) {
|
|
1528
1290
|
showTemporarySuccessLabel(extractElementLabelText(targetElement2));
|
|
1529
1291
|
}
|
|
@@ -1535,40 +1297,7 @@ ${context}
|
|
|
1535
1297
|
showTemporaryGrabbedBox(createElementBounds(element));
|
|
1536
1298
|
}
|
|
1537
1299
|
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
|
-
}
|
|
1300
|
+
const didCopy = await tryCopyWithFallback(targetElements);
|
|
1572
1301
|
if (didCopy) {
|
|
1573
1302
|
showTemporarySuccessLabel(`${targetElements.length} elements`);
|
|
1574
1303
|
}
|
|
@@ -1592,7 +1321,6 @@ ${context}
|
|
|
1592
1321
|
y: elementBounds.top
|
|
1593
1322
|
};
|
|
1594
1323
|
});
|
|
1595
|
-
const DRAG_THRESHOLD_PX = 2;
|
|
1596
1324
|
const calculateDragDistance = (endX, endY) => ({
|
|
1597
1325
|
x: Math.abs(endX - dragStartX()),
|
|
1598
1326
|
y: Math.abs(endY - dragStartY())
|
|
@@ -1644,36 +1372,28 @@ ${context}
|
|
|
1644
1372
|
x: mouseX(),
|
|
1645
1373
|
y: mouseY()
|
|
1646
1374
|
});
|
|
1647
|
-
const isSameAsLast = solidJs.createMemo(() => Boolean(targetElement() && targetElement() === lastGrabbedElement()));
|
|
1648
1375
|
solidJs.createEffect(solidJs.on(() => [targetElement(), lastGrabbedElement()], ([currentElement, lastElement]) => {
|
|
1649
1376
|
if (lastElement && currentElement && lastElement !== currentElement) {
|
|
1650
1377
|
setLastGrabbedElement(null);
|
|
1651
1378
|
}
|
|
1652
1379
|
}));
|
|
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
1380
|
const startProgressAnimation = () => {
|
|
1667
|
-
|
|
1381
|
+
const startTime = Date.now();
|
|
1382
|
+
setProgressStartTime(startTime);
|
|
1668
1383
|
setShowProgressIndicator(false);
|
|
1669
1384
|
progressDelayTimerId = window.setTimeout(() => {
|
|
1670
1385
|
setShowProgressIndicator(true);
|
|
1671
1386
|
progressDelayTimerId = null;
|
|
1672
1387
|
}, PROGRESS_INDICATOR_DELAY_MS);
|
|
1673
1388
|
const animateProgress = () => {
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
const
|
|
1389
|
+
const currentStartTime = progressStartTime();
|
|
1390
|
+
if (currentStartTime === null) return;
|
|
1391
|
+
const elapsedTime = Date.now() - currentStartTime;
|
|
1392
|
+
const normalizedTime = elapsedTime / options.keyHoldDuration;
|
|
1393
|
+
const easedProgress = 1 - Math.exp(-normalizedTime);
|
|
1394
|
+
const maxProgressBeforeCompletion = 0.95;
|
|
1395
|
+
const currentProgress = isCopying() ? Math.min(easedProgress, maxProgressBeforeCompletion) : 1;
|
|
1396
|
+
setProgress(currentProgress);
|
|
1677
1397
|
if (currentProgress < 1) {
|
|
1678
1398
|
progressAnimationId = requestAnimationFrame(animateProgress);
|
|
1679
1399
|
}
|
|
@@ -1690,6 +1410,7 @@ ${context}
|
|
|
1690
1410
|
progressDelayTimerId = null;
|
|
1691
1411
|
}
|
|
1692
1412
|
setProgressStartTime(null);
|
|
1413
|
+
setProgress(1);
|
|
1693
1414
|
setShowProgressIndicator(false);
|
|
1694
1415
|
};
|
|
1695
1416
|
const activateRenderer = () => {
|
|
@@ -1713,8 +1434,6 @@ ${context}
|
|
|
1713
1434
|
mouseSettleTimerId = null;
|
|
1714
1435
|
}
|
|
1715
1436
|
setMouseHasSettled(false);
|
|
1716
|
-
referenceMouseX = OFFSCREEN_POSITION;
|
|
1717
|
-
referenceMouseY = OFFSCREEN_POSITION;
|
|
1718
1437
|
stopProgressAnimation();
|
|
1719
1438
|
};
|
|
1720
1439
|
const abortController = new AbortController();
|
|
@@ -1781,34 +1500,14 @@ ${context}
|
|
|
1781
1500
|
window.addEventListener("mousemove", (event) => {
|
|
1782
1501
|
setMouseX(event.clientX);
|
|
1783
1502
|
setMouseY(event.clientY);
|
|
1784
|
-
if (
|
|
1785
|
-
|
|
1786
|
-
referenceMouseY = event.clientY;
|
|
1787
|
-
}
|
|
1788
|
-
const deltaX = event.clientX - referenceMouseX;
|
|
1789
|
-
const deltaY = event.clientY - referenceMouseY;
|
|
1790
|
-
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
1791
|
-
if (distance >= 200) {
|
|
1792
|
-
if (mouseSettleTimerId !== null) {
|
|
1793
|
-
window.clearTimeout(mouseSettleTimerId);
|
|
1794
|
-
}
|
|
1795
|
-
setMouseHasSettled(false);
|
|
1796
|
-
referenceMouseX = event.clientX;
|
|
1797
|
-
referenceMouseY = event.clientY;
|
|
1798
|
-
mouseSettleTimerId = window.setTimeout(() => {
|
|
1799
|
-
setMouseHasSettled(true);
|
|
1800
|
-
referenceMouseX = mouseX();
|
|
1801
|
-
referenceMouseY = mouseY();
|
|
1802
|
-
mouseSettleTimerId = null;
|
|
1803
|
-
}, 100);
|
|
1804
|
-
} else if (mouseSettleTimerId === null && !mouseHasSettled()) {
|
|
1805
|
-
mouseSettleTimerId = window.setTimeout(() => {
|
|
1806
|
-
setMouseHasSettled(true);
|
|
1807
|
-
referenceMouseX = mouseX();
|
|
1808
|
-
referenceMouseY = mouseY();
|
|
1809
|
-
mouseSettleTimerId = null;
|
|
1810
|
-
}, 100);
|
|
1503
|
+
if (mouseSettleTimerId !== null) {
|
|
1504
|
+
window.clearTimeout(mouseSettleTimerId);
|
|
1811
1505
|
}
|
|
1506
|
+
setMouseHasSettled(false);
|
|
1507
|
+
mouseSettleTimerId = window.setTimeout(() => {
|
|
1508
|
+
setMouseHasSettled(true);
|
|
1509
|
+
mouseSettleTimerId = null;
|
|
1510
|
+
}, 300);
|
|
1812
1511
|
}, {
|
|
1813
1512
|
signal: eventListenerSignal
|
|
1814
1513
|
});
|
|
@@ -1892,7 +1591,7 @@ ${context}
|
|
|
1892
1591
|
const labelVisible = solidJs.createMemo(() => {
|
|
1893
1592
|
if (isCopying()) return true;
|
|
1894
1593
|
if (successLabels().length > 0) return false;
|
|
1895
|
-
return isRendererActive() && !isDragging() &&
|
|
1594
|
+
return isRendererActive() && !isDragging() && Boolean(targetElement());
|
|
1896
1595
|
});
|
|
1897
1596
|
const progressVisible = solidJs.createMemo(() => isCopying() && showProgressIndicator() && hasValidMousePosition());
|
|
1898
1597
|
const crosshairVisible = solidJs.createMemo(() => isRendererActive() && !isDragging());
|
|
@@ -1930,7 +1629,10 @@ ${context}
|
|
|
1930
1629
|
get labelVisible() {
|
|
1931
1630
|
return labelVisible();
|
|
1932
1631
|
},
|
|
1933
|
-
labelZIndex:
|
|
1632
|
+
labelZIndex: Z_INDEX_LABEL,
|
|
1633
|
+
get labelShowHint() {
|
|
1634
|
+
return mouseHasSettled();
|
|
1635
|
+
},
|
|
1934
1636
|
get progressVisible() {
|
|
1935
1637
|
return progressVisible();
|
|
1936
1638
|
},
|
|
@@ -1976,13 +1678,8 @@ ${context}
|
|
|
1976
1678
|
// src/index.ts
|
|
1977
1679
|
var globalApi = null;
|
|
1978
1680
|
var getGlobalApi = () => globalApi;
|
|
1979
|
-
|
|
1980
|
-
if (!window[EXTENSION_MARKER]) {
|
|
1981
|
-
globalApi = init();
|
|
1982
|
-
}
|
|
1681
|
+
globalApi = init();
|
|
1983
1682
|
|
|
1984
|
-
exports.elementToMarkdown = elementToMarkdown;
|
|
1985
1683
|
exports.getGlobalApi = getGlobalApi;
|
|
1986
|
-
exports.htmlToMarkdown = htmlToMarkdown;
|
|
1987
1684
|
exports.init = init;
|
|
1988
1685
|
exports.playCopySound = playCopySound;
|