react-grab 0.0.28 → 0.0.30
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 +246 -227
- package/dist/index.global.js +29 -18
- package/dist/index.js +248 -229
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
var web = require('solid-js/web');
|
|
4
4
|
var solidJs = require('solid-js');
|
|
5
|
+
var modernScreenshot = require('modern-screenshot');
|
|
5
6
|
var bippy = require('bippy');
|
|
6
7
|
var source = require('bippy/dist/source');
|
|
8
|
+
var finder = require('@medv/finder');
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* @license MIT
|
|
@@ -96,6 +98,7 @@ var VIEWPORT_MARGIN_PX = 8;
|
|
|
96
98
|
var INDICATOR_CLAMP_PADDING_PX = 4;
|
|
97
99
|
var CURSOR_OFFSET_PX = 14;
|
|
98
100
|
var SELECTION_LERP_FACTOR = 0.95;
|
|
101
|
+
var SUCCESS_LABEL_DURATION_MS = 1700;
|
|
99
102
|
|
|
100
103
|
// src/utils/lerp.ts
|
|
101
104
|
var lerp = (start, end, factor) => {
|
|
@@ -258,9 +261,9 @@ var getClampedElementPosition = (positionLeft, positionTop, elementWidth, elemen
|
|
|
258
261
|
// src/components/label.tsx
|
|
259
262
|
var _tmpl$3 = /* @__PURE__ */ web.template(`<span style=display:inline-block;margin-right:4px;font-weight:600>\u2713`);
|
|
260
263
|
var _tmpl$22 = /* @__PURE__ */ web.template(`<div style=margin-right:4px>Copied`);
|
|
261
|
-
var _tmpl$32 = /* @__PURE__ */ web.template(`<
|
|
262
|
-
var _tmpl$4 = /* @__PURE__ */ web.template(`<div style=
|
|
263
|
-
var _tmpl$5 = /* @__PURE__ */ web.template(`<
|
|
264
|
+
var _tmpl$32 = /* @__PURE__ */ web.template(`<span style="font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;font-variant-numeric:tabular-nums">`);
|
|
265
|
+
var _tmpl$4 = /* @__PURE__ */ web.template(`<div style=margin-left:4px>to clipboard`);
|
|
266
|
+
var _tmpl$5 = /* @__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">`);
|
|
264
267
|
var Label = (props) => {
|
|
265
268
|
const [opacity, setOpacity] = solidJs.createSignal(0);
|
|
266
269
|
const [positionTick, setPositionTick] = solidJs.createSignal(0);
|
|
@@ -310,7 +313,7 @@ var Label = (props) => {
|
|
|
310
313
|
if (props.variant === "success") {
|
|
311
314
|
const fadeOutTimer = setTimeout(() => {
|
|
312
315
|
setOpacity(0);
|
|
313
|
-
},
|
|
316
|
+
}, SUCCESS_LABEL_DURATION_MS);
|
|
314
317
|
solidJs.onCleanup(() => clearTimeout(fadeOutTimer));
|
|
315
318
|
}
|
|
316
319
|
}));
|
|
@@ -331,34 +334,20 @@ var Label = (props) => {
|
|
|
331
334
|
left: currentX,
|
|
332
335
|
top: currentY
|
|
333
336
|
};
|
|
334
|
-
if (props.variant === "success") {
|
|
335
|
-
const indicatorLeft = Math.round(currentX);
|
|
336
|
-
const indicatorTop = Math.round(currentY) - boundingRect.height - 6;
|
|
337
|
-
const willClampLeft = indicatorLeft < VIEWPORT_MARGIN_PX;
|
|
338
|
-
const willClampTop = indicatorTop < VIEWPORT_MARGIN_PX;
|
|
339
|
-
const isClamped = willClampLeft || willClampTop;
|
|
340
|
-
const clamped = getClampedElementPosition(indicatorLeft, indicatorTop, boundingRect.width, boundingRect.height);
|
|
341
|
-
if (isClamped) {
|
|
342
|
-
clamped.left += INDICATOR_CLAMP_PADDING_PX;
|
|
343
|
-
clamped.top += INDICATOR_CLAMP_PADDING_PX;
|
|
344
|
-
}
|
|
345
|
-
return clamped;
|
|
346
|
-
}
|
|
347
|
-
const CROSSHAIR_OFFSET = 12;
|
|
348
337
|
const viewportWidth = window.innerWidth;
|
|
349
338
|
const viewportHeight = window.innerHeight;
|
|
350
339
|
const quadrants = [{
|
|
351
|
-
left: Math.round(currentX) +
|
|
352
|
-
top: Math.round(currentY) +
|
|
340
|
+
left: Math.round(currentX) + CURSOR_OFFSET_PX,
|
|
341
|
+
top: Math.round(currentY) + CURSOR_OFFSET_PX
|
|
353
342
|
}, {
|
|
354
|
-
left: Math.round(currentX) - boundingRect.width -
|
|
355
|
-
top: Math.round(currentY) +
|
|
343
|
+
left: Math.round(currentX) - boundingRect.width - CURSOR_OFFSET_PX,
|
|
344
|
+
top: Math.round(currentY) + CURSOR_OFFSET_PX
|
|
356
345
|
}, {
|
|
357
|
-
left: Math.round(currentX) +
|
|
358
|
-
top: Math.round(currentY) - boundingRect.height -
|
|
346
|
+
left: Math.round(currentX) + CURSOR_OFFSET_PX,
|
|
347
|
+
top: Math.round(currentY) - boundingRect.height - CURSOR_OFFSET_PX
|
|
359
348
|
}, {
|
|
360
|
-
left: Math.round(currentX) - boundingRect.width -
|
|
361
|
-
top: Math.round(currentY) - boundingRect.height -
|
|
349
|
+
left: Math.round(currentX) - boundingRect.width - CURSOR_OFFSET_PX,
|
|
350
|
+
top: Math.round(currentY) - boundingRect.height - CURSOR_OFFSET_PX
|
|
362
351
|
}];
|
|
363
352
|
for (const position of quadrants) {
|
|
364
353
|
const fitsHorizontally = position.left >= VIEWPORT_MARGIN_PX && position.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
|
|
@@ -377,7 +366,7 @@ var Label = (props) => {
|
|
|
377
366
|
return props.visible !== false;
|
|
378
367
|
},
|
|
379
368
|
get children() {
|
|
380
|
-
var _el$ = _tmpl$
|
|
369
|
+
var _el$ = _tmpl$5();
|
|
381
370
|
var _ref$ = labelRef;
|
|
382
371
|
typeof _ref$ === "function" ? web.use(_ref$, _el$) : labelRef = _el$;
|
|
383
372
|
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
@@ -412,17 +401,12 @@ var Label = (props) => {
|
|
|
412
401
|
}), null);
|
|
413
402
|
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
414
403
|
get when() {
|
|
415
|
-
return props.
|
|
416
|
-
},
|
|
417
|
-
get fallback() {
|
|
418
|
-
return (() => {
|
|
419
|
-
var _el$5 = _tmpl$5();
|
|
420
|
-
web.insert(_el$5, () => props.text);
|
|
421
|
-
return _el$5;
|
|
422
|
-
})();
|
|
404
|
+
return props.variant !== "processing";
|
|
423
405
|
},
|
|
424
406
|
get children() {
|
|
425
|
-
|
|
407
|
+
var _el$4 = _tmpl$32();
|
|
408
|
+
web.insert(_el$4, () => props.text);
|
|
409
|
+
return _el$4;
|
|
426
410
|
}
|
|
427
411
|
}), null);
|
|
428
412
|
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
@@ -430,7 +414,7 @@ var Label = (props) => {
|
|
|
430
414
|
return props.variant === "success";
|
|
431
415
|
},
|
|
432
416
|
get children() {
|
|
433
|
-
return _tmpl$
|
|
417
|
+
return _tmpl$4();
|
|
434
418
|
}
|
|
435
419
|
}), null);
|
|
436
420
|
web.effect((_p$) => {
|
|
@@ -730,26 +714,43 @@ bippy.instrument({
|
|
|
730
714
|
bippy._fiberRoots.add(fiberRoot);
|
|
731
715
|
}
|
|
732
716
|
});
|
|
733
|
-
var
|
|
734
|
-
|
|
735
|
-
if (!fiber) return null;
|
|
736
|
-
const ownerStack = source.getOwnerStack(fiber);
|
|
737
|
-
const sources = await source.getSourcesFromStack(
|
|
738
|
-
ownerStack,
|
|
739
|
-
Number.MAX_SAFE_INTEGER
|
|
740
|
-
);
|
|
741
|
-
if (!sources) return null;
|
|
742
|
-
console.log(sources);
|
|
743
|
-
return sources.map((source$1) => {
|
|
744
|
-
return {
|
|
745
|
-
...source$1,
|
|
746
|
-
fileName: source.normalizeFileName(source$1.fileName)
|
|
747
|
-
};
|
|
748
|
-
}).filter((source$1) => {
|
|
749
|
-
return source.isSourceFile(source$1.fileName);
|
|
750
|
-
});
|
|
717
|
+
var generateCSSSelector = (element) => {
|
|
718
|
+
return finder.finder(element);
|
|
751
719
|
};
|
|
752
|
-
var getHTMLSnippet = (element) => {
|
|
720
|
+
var getHTMLSnippet = async (element) => {
|
|
721
|
+
const truncateString = (string, maxLength) => string.length > maxLength ? `${string.substring(0, maxLength)}...` : string;
|
|
722
|
+
const isInternalComponent = (name) => {
|
|
723
|
+
if (name.startsWith("_")) return true;
|
|
724
|
+
if (name.includes("Provider") && name.includes("Context")) return true;
|
|
725
|
+
return false;
|
|
726
|
+
};
|
|
727
|
+
const extractReactComponentName = (el) => {
|
|
728
|
+
const fiber = bippy.getFiberFromHostInstance(el);
|
|
729
|
+
if (!fiber) return null;
|
|
730
|
+
let componentName = null;
|
|
731
|
+
bippy.traverseFiber(
|
|
732
|
+
fiber,
|
|
733
|
+
(currentFiber) => {
|
|
734
|
+
if (bippy.isCompositeFiber(currentFiber)) {
|
|
735
|
+
const displayName = bippy.getDisplayName(currentFiber);
|
|
736
|
+
if (displayName && !isInternalComponent(displayName)) {
|
|
737
|
+
componentName = displayName;
|
|
738
|
+
return true;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return false;
|
|
742
|
+
},
|
|
743
|
+
true
|
|
744
|
+
);
|
|
745
|
+
return componentName;
|
|
746
|
+
};
|
|
747
|
+
const formatComponentSourceLocation = async (el) => {
|
|
748
|
+
const source$1 = await source.getSourceFromHostInstance(el);
|
|
749
|
+
if (!source$1) return null;
|
|
750
|
+
const fileName = source.normalizeFileName(source$1.fileName);
|
|
751
|
+
if (!source.isSourceFile(fileName)) return null;
|
|
752
|
+
return `${fileName}:${source$1.lineNumber}:${source$1.columnNumber}`;
|
|
753
|
+
};
|
|
753
754
|
const semanticTags = /* @__PURE__ */ new Set([
|
|
754
755
|
"article",
|
|
755
756
|
"aside",
|
|
@@ -772,7 +773,7 @@ var getHTMLSnippet = (element) => {
|
|
|
772
773
|
(attr) => attr.name.startsWith("data-")
|
|
773
774
|
);
|
|
774
775
|
};
|
|
775
|
-
const
|
|
776
|
+
const collectDistinguishingAncestors = (el, maxDepth = 10) => {
|
|
776
777
|
const ancestors2 = [];
|
|
777
778
|
let current = el.parentElement;
|
|
778
779
|
let depth = 0;
|
|
@@ -786,35 +787,7 @@ var getHTMLSnippet = (element) => {
|
|
|
786
787
|
}
|
|
787
788
|
return ancestors2.reverse();
|
|
788
789
|
};
|
|
789
|
-
const
|
|
790
|
-
const parts = [];
|
|
791
|
-
let current = el;
|
|
792
|
-
let depth = 0;
|
|
793
|
-
const maxDepth = 5;
|
|
794
|
-
while (current && depth < maxDepth && current.tagName !== "BODY") {
|
|
795
|
-
let selector = current.tagName.toLowerCase();
|
|
796
|
-
if (current.id) {
|
|
797
|
-
selector += `#${current.id}`;
|
|
798
|
-
parts.unshift(selector);
|
|
799
|
-
break;
|
|
800
|
-
} else if (current.className && typeof current.className === "string" && current.className.trim()) {
|
|
801
|
-
const classes = current.className.trim().split(/\s+/).slice(0, 2);
|
|
802
|
-
selector += `.${classes.join(".")}`;
|
|
803
|
-
}
|
|
804
|
-
if (!current.id && (!current.className || !current.className.trim()) && current.parentElement) {
|
|
805
|
-
const siblings = Array.from(current.parentElement.children);
|
|
806
|
-
const index = siblings.indexOf(current);
|
|
807
|
-
if (index >= 0 && siblings.length > 1) {
|
|
808
|
-
selector += `:nth-child(${index + 1})`;
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
parts.unshift(selector);
|
|
812
|
-
current = current.parentElement;
|
|
813
|
-
depth++;
|
|
814
|
-
}
|
|
815
|
-
return parts.join(" > ");
|
|
816
|
-
};
|
|
817
|
-
const getElementTag = (el, compact = false) => {
|
|
790
|
+
const formatElementOpeningTag = (el, compact = false) => {
|
|
818
791
|
const tagName = el.tagName.toLowerCase();
|
|
819
792
|
const attrs = [];
|
|
820
793
|
if (el.id) {
|
|
@@ -824,10 +797,7 @@ var getHTMLSnippet = (element) => {
|
|
|
824
797
|
const classes = el.className.trim().split(/\s+/);
|
|
825
798
|
if (classes.length > 0 && classes[0]) {
|
|
826
799
|
const displayClasses = compact ? classes.slice(0, 3) : classes;
|
|
827
|
-
|
|
828
|
-
if (classStr.length > 30) {
|
|
829
|
-
classStr = classStr.substring(0, 30) + "...";
|
|
830
|
-
}
|
|
800
|
+
const classStr = truncateString(displayClasses.join(" "), 30);
|
|
831
801
|
attrs.push(`class="${classStr}"`);
|
|
832
802
|
}
|
|
833
803
|
}
|
|
@@ -836,35 +806,20 @@ var getHTMLSnippet = (element) => {
|
|
|
836
806
|
);
|
|
837
807
|
const displayDataAttrs = compact ? dataAttrs.slice(0, 1) : dataAttrs;
|
|
838
808
|
for (const attr of displayDataAttrs) {
|
|
839
|
-
|
|
840
|
-
if (value.length > 20) {
|
|
841
|
-
value = value.substring(0, 20) + "...";
|
|
842
|
-
}
|
|
843
|
-
attrs.push(`${attr.name}="${value}"`);
|
|
809
|
+
attrs.push(`${attr.name}="${truncateString(attr.value, 20)}"`);
|
|
844
810
|
}
|
|
845
811
|
const ariaLabel = el.getAttribute("aria-label");
|
|
846
812
|
if (ariaLabel && !compact) {
|
|
847
|
-
|
|
848
|
-
if (value.length > 20) {
|
|
849
|
-
value = value.substring(0, 20) + "...";
|
|
850
|
-
}
|
|
851
|
-
attrs.push(`aria-label="${value}"`);
|
|
813
|
+
attrs.push(`aria-label="${truncateString(ariaLabel, 20)}"`);
|
|
852
814
|
}
|
|
853
815
|
return attrs.length > 0 ? `<${tagName} ${attrs.join(" ")}>` : `<${tagName}>`;
|
|
854
816
|
};
|
|
855
|
-
const
|
|
856
|
-
|
|
817
|
+
const formatElementClosingTag = (el) => `</${el.tagName.toLowerCase()}>`;
|
|
818
|
+
const extractTruncatedTextContent = (el) => {
|
|
819
|
+
const text = (el.textContent || "").trim().replace(/\s+/g, " ");
|
|
820
|
+
return truncateString(text, 60);
|
|
857
821
|
};
|
|
858
|
-
const
|
|
859
|
-
let text = el.textContent || "";
|
|
860
|
-
text = text.trim().replace(/\s+/g, " ");
|
|
861
|
-
const maxLength = 60;
|
|
862
|
-
if (text.length > maxLength) {
|
|
863
|
-
text = text.substring(0, maxLength) + "...";
|
|
864
|
-
}
|
|
865
|
-
return text;
|
|
866
|
-
};
|
|
867
|
-
const getSiblingIdentifier = (el) => {
|
|
822
|
+
const extractSiblingIdentifier = (el) => {
|
|
868
823
|
if (el.id) return `#${el.id}`;
|
|
869
824
|
if (el.className && typeof el.className === "string") {
|
|
870
825
|
const classes = el.className.trim().split(/\s+/);
|
|
@@ -875,12 +830,31 @@ var getHTMLSnippet = (element) => {
|
|
|
875
830
|
return null;
|
|
876
831
|
};
|
|
877
832
|
const lines = [];
|
|
878
|
-
|
|
879
|
-
lines.push(
|
|
880
|
-
|
|
833
|
+
const selector = generateCSSSelector(element);
|
|
834
|
+
lines.push(`Locate this element in the codebase:`);
|
|
835
|
+
lines.push(`- selector: ${selector}`);
|
|
836
|
+
const rect = element.getBoundingClientRect();
|
|
837
|
+
lines.push(`- width: ${Math.round(rect.width)}`);
|
|
838
|
+
lines.push(`- height: ${Math.round(rect.height)}`);
|
|
839
|
+
lines.push("HTML snippet:");
|
|
840
|
+
lines.push("```html");
|
|
841
|
+
const ancestors = collectDistinguishingAncestors(element);
|
|
842
|
+
const ancestorComponents = ancestors.map(
|
|
843
|
+
(ancestor) => extractReactComponentName(ancestor)
|
|
844
|
+
);
|
|
845
|
+
const elementComponent = extractReactComponentName(element);
|
|
846
|
+
const ancestorSources = await Promise.all(
|
|
847
|
+
ancestors.map((ancestor) => formatComponentSourceLocation(ancestor))
|
|
848
|
+
);
|
|
849
|
+
const elementSource = await formatComponentSourceLocation(element);
|
|
881
850
|
for (let i = 0; i < ancestors.length; i++) {
|
|
882
851
|
const indent2 = " ".repeat(i);
|
|
883
|
-
|
|
852
|
+
const componentName = ancestorComponents[i];
|
|
853
|
+
const source = ancestorSources[i];
|
|
854
|
+
if (componentName && source && (i === 0 || ancestorComponents[i - 1] !== componentName)) {
|
|
855
|
+
lines.push(`${indent2}<${componentName} source="${source}">`);
|
|
856
|
+
}
|
|
857
|
+
lines.push(`${indent2}${formatElementOpeningTag(ancestors[i], true)}`);
|
|
884
858
|
}
|
|
885
859
|
const parent = element.parentElement;
|
|
886
860
|
let targetIndex = -1;
|
|
@@ -889,10 +863,10 @@ var getHTMLSnippet = (element) => {
|
|
|
889
863
|
targetIndex = siblings.indexOf(element);
|
|
890
864
|
if (targetIndex > 0) {
|
|
891
865
|
const prevSibling = siblings[targetIndex - 1];
|
|
892
|
-
const prevId =
|
|
866
|
+
const prevId = extractSiblingIdentifier(prevSibling);
|
|
893
867
|
if (prevId && targetIndex <= 2) {
|
|
894
868
|
const indent2 = " ".repeat(ancestors.length);
|
|
895
|
-
lines.push(`${indent2} ${
|
|
869
|
+
lines.push(`${indent2} ${formatElementOpeningTag(prevSibling, true)}`);
|
|
896
870
|
lines.push(`${indent2} </${prevSibling.tagName.toLowerCase()}>`);
|
|
897
871
|
} else if (targetIndex > 0) {
|
|
898
872
|
const indent2 = " ".repeat(ancestors.length);
|
|
@@ -903,35 +877,44 @@ var getHTMLSnippet = (element) => {
|
|
|
903
877
|
}
|
|
904
878
|
}
|
|
905
879
|
const indent = " ".repeat(ancestors.length);
|
|
906
|
-
|
|
907
|
-
const
|
|
880
|
+
const lastAncestorComponent = ancestors.length > 0 ? ancestorComponents[ancestorComponents.length - 1] : null;
|
|
881
|
+
const showElementComponent = elementComponent && elementSource && elementComponent !== lastAncestorComponent;
|
|
882
|
+
if (showElementComponent) {
|
|
883
|
+
lines.push(`${indent} <${elementComponent} used-at="${elementSource}">`);
|
|
884
|
+
}
|
|
885
|
+
lines.push(`${indent} <!-- IMPORTANT: selected element -->`);
|
|
886
|
+
const textContent = extractTruncatedTextContent(element);
|
|
908
887
|
const childrenCount = element.children.length;
|
|
888
|
+
const elementIndent = `${indent}${showElementComponent ? " " : " "}`;
|
|
909
889
|
if (textContent && childrenCount === 0 && textContent.length < 40) {
|
|
910
890
|
lines.push(
|
|
911
|
-
`${
|
|
891
|
+
`${elementIndent}${formatElementOpeningTag(element)}${textContent}${formatElementClosingTag(
|
|
912
892
|
element
|
|
913
893
|
)}`
|
|
914
894
|
);
|
|
915
895
|
} else {
|
|
916
|
-
lines.push(
|
|
896
|
+
lines.push(`${elementIndent}${formatElementOpeningTag(element)}`);
|
|
917
897
|
if (textContent) {
|
|
918
|
-
lines.push(`${
|
|
898
|
+
lines.push(`${elementIndent} ${textContent}`);
|
|
919
899
|
}
|
|
920
900
|
if (childrenCount > 0) {
|
|
921
901
|
lines.push(
|
|
922
|
-
`${
|
|
902
|
+
`${elementIndent} ... (${childrenCount} element${childrenCount === 1 ? "" : "s"})`
|
|
923
903
|
);
|
|
924
904
|
}
|
|
925
|
-
lines.push(
|
|
905
|
+
lines.push(`${elementIndent}${formatElementClosingTag(element)}`);
|
|
906
|
+
}
|
|
907
|
+
if (showElementComponent) {
|
|
908
|
+
lines.push(`${indent} </${elementComponent}>`);
|
|
926
909
|
}
|
|
927
910
|
if (parent && targetIndex >= 0) {
|
|
928
911
|
const siblings = Array.from(parent.children);
|
|
929
912
|
const siblingsAfter = siblings.length - targetIndex - 1;
|
|
930
913
|
if (siblingsAfter > 0) {
|
|
931
914
|
const nextSibling = siblings[targetIndex + 1];
|
|
932
|
-
const nextId =
|
|
915
|
+
const nextId = extractSiblingIdentifier(nextSibling);
|
|
933
916
|
if (nextId && siblingsAfter <= 2) {
|
|
934
|
-
lines.push(`${indent} ${
|
|
917
|
+
lines.push(`${indent} ${formatElementOpeningTag(nextSibling, true)}`);
|
|
935
918
|
lines.push(`${indent} </${nextSibling.tagName.toLowerCase()}>`);
|
|
936
919
|
} else {
|
|
937
920
|
lines.push(
|
|
@@ -942,8 +925,14 @@ var getHTMLSnippet = (element) => {
|
|
|
942
925
|
}
|
|
943
926
|
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
944
927
|
const indent2 = " ".repeat(i);
|
|
945
|
-
lines.push(indent2
|
|
928
|
+
lines.push(`${indent2}${formatElementClosingTag(ancestors[i])}`);
|
|
929
|
+
const componentName = ancestorComponents[i];
|
|
930
|
+
const source = ancestorSources[i];
|
|
931
|
+
if (componentName && source && (i === ancestors.length - 1 || ancestorComponents[i + 1] !== componentName)) {
|
|
932
|
+
lines.push(`${indent2}</${componentName}>`);
|
|
933
|
+
}
|
|
946
934
|
}
|
|
935
|
+
lines.push("```");
|
|
947
936
|
return lines.join("\n");
|
|
948
937
|
};
|
|
949
938
|
|
|
@@ -1173,8 +1162,8 @@ var createElementBounds = (element) => {
|
|
|
1173
1162
|
};
|
|
1174
1163
|
|
|
1175
1164
|
// src/core.tsx
|
|
1176
|
-
var SUCCESS_LABEL_DURATION_MS = 1700;
|
|
1177
1165
|
var PROGRESS_INDICATOR_DELAY_MS = 150;
|
|
1166
|
+
var QUICK_REPRESS_THRESHOLD_MS = 150;
|
|
1178
1167
|
var init = (rawOptions) => {
|
|
1179
1168
|
const options = {
|
|
1180
1169
|
enabled: true,
|
|
@@ -1200,14 +1189,19 @@ var init = (rawOptions) => {
|
|
|
1200
1189
|
const [successLabels, setSuccessLabels] = solidJs.createSignal([]);
|
|
1201
1190
|
const [isActivated, setIsActivated] = solidJs.createSignal(false);
|
|
1202
1191
|
const [showProgressIndicator, setShowProgressIndicator] = solidJs.createSignal(false);
|
|
1192
|
+
const [didJustDrag, setDidJustDrag] = solidJs.createSignal(false);
|
|
1193
|
+
const [isModifierHeld, setIsModifierHeld] = solidJs.createSignal(false);
|
|
1194
|
+
const [copyStartX, setCopyStartX] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
1195
|
+
const [copyStartY, setCopyStartY] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
1203
1196
|
let holdTimerId = null;
|
|
1204
1197
|
let progressAnimationId = null;
|
|
1205
1198
|
let progressDelayTimerId = null;
|
|
1206
1199
|
let keydownSpamTimerId = null;
|
|
1200
|
+
let lastDeactivationTime = null;
|
|
1207
1201
|
const isRendererActive = solidJs.createMemo(() => isActivated() && !isCopying());
|
|
1208
1202
|
const hasValidMousePosition = solidJs.createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
|
|
1209
1203
|
const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "c";
|
|
1210
|
-
const
|
|
1204
|
+
const showTemporaryGrabbedBox = (bounds) => {
|
|
1211
1205
|
const boxId = `grabbed-${Date.now()}-${Math.random()}`;
|
|
1212
1206
|
const createdAt = Date.now();
|
|
1213
1207
|
const newBox = {
|
|
@@ -1221,7 +1215,7 @@ var init = (rawOptions) => {
|
|
|
1221
1215
|
setGrabbedBoxes((previousBoxes) => previousBoxes.filter((box) => box.id !== boxId));
|
|
1222
1216
|
}, SUCCESS_LABEL_DURATION_MS);
|
|
1223
1217
|
};
|
|
1224
|
-
const
|
|
1218
|
+
const showTemporarySuccessLabel = (text, positionX, positionY) => {
|
|
1225
1219
|
const labelId = `success-${Date.now()}-${Math.random()}`;
|
|
1226
1220
|
setSuccessLabels((previousLabels) => [...previousLabels, {
|
|
1227
1221
|
id: labelId,
|
|
@@ -1233,24 +1227,15 @@ var init = (rawOptions) => {
|
|
|
1233
1227
|
setSuccessLabels((previousLabels) => previousLabels.filter((label) => label.id !== labelId));
|
|
1234
1228
|
}, SUCCESS_LABEL_DURATION_MS);
|
|
1235
1229
|
};
|
|
1236
|
-
const
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
const lineNumber = source.lineNumber ?? 0;
|
|
1241
|
-
const columnNumber = source.columnNumber ?? 0;
|
|
1242
|
-
return ` at ${functionName} (${fileName}:${lineNumber}:${columnNumber})`;
|
|
1243
|
-
}).join("\n");
|
|
1244
|
-
};
|
|
1245
|
-
const wrapContextInXmlTags = (context) => {
|
|
1246
|
-
return `<selected_element>${context}</selected_element>`;
|
|
1247
|
-
};
|
|
1248
|
-
const getComputedStyles = (element) => {
|
|
1230
|
+
const wrapInSelectedElementTags = (context) => `<selected_element>
|
|
1231
|
+
${context}
|
|
1232
|
+
</selected_element>`;
|
|
1233
|
+
const extractRelevantComputedStyles = (element) => {
|
|
1249
1234
|
const computed = window.getComputedStyle(element);
|
|
1250
1235
|
const rect = element.getBoundingClientRect();
|
|
1251
1236
|
return {
|
|
1252
|
-
width: `${rect.width}px`,
|
|
1253
|
-
height: `${rect.height}px`,
|
|
1237
|
+
width: `${Math.round(rect.width)}px`,
|
|
1238
|
+
height: `${Math.round(rect.height)}px`,
|
|
1254
1239
|
paddingTop: computed.paddingTop,
|
|
1255
1240
|
paddingRight: computed.paddingRight,
|
|
1256
1241
|
paddingBottom: computed.paddingBottom,
|
|
@@ -1259,7 +1244,7 @@ var init = (rawOptions) => {
|
|
|
1259
1244
|
opacity: computed.opacity
|
|
1260
1245
|
};
|
|
1261
1246
|
};
|
|
1262
|
-
const
|
|
1247
|
+
const createStructuredClipboardHtmlBlob = (elements) => {
|
|
1263
1248
|
const structuredData = {
|
|
1264
1249
|
elements: elements.map((element) => ({
|
|
1265
1250
|
tagName: element.tagName,
|
|
@@ -1273,60 +1258,74 @@ var init = (rawOptions) => {
|
|
|
1273
1258
|
type: "text/html"
|
|
1274
1259
|
});
|
|
1275
1260
|
};
|
|
1276
|
-
const
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
${formattedStackTrace}`;
|
|
1285
|
-
}
|
|
1286
|
-
return elementHtml;
|
|
1261
|
+
const extractElementTagName = (element) => (element.tagName || "").toLowerCase();
|
|
1262
|
+
const executeCopyOperation = async (positionX, positionY, operation) => {
|
|
1263
|
+
setCopyStartX(positionX);
|
|
1264
|
+
setCopyStartY(positionY);
|
|
1265
|
+
setIsCopying(true);
|
|
1266
|
+
await operation().finally(() => {
|
|
1267
|
+
setIsCopying(false);
|
|
1268
|
+
});
|
|
1287
1269
|
};
|
|
1288
|
-
const
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
const tagName = getElementTagName(targetElement2);
|
|
1292
|
-
addGrabbedBox(createElementBounds(targetElement2));
|
|
1270
|
+
const copySingleElementToClipboard = async (targetElement2) => {
|
|
1271
|
+
const tagName = extractElementTagName(targetElement2);
|
|
1272
|
+
showTemporaryGrabbedBox(createElementBounds(targetElement2));
|
|
1293
1273
|
try {
|
|
1294
|
-
const content = await
|
|
1295
|
-
const plainTextContent =
|
|
1296
|
-
const htmlContent =
|
|
1274
|
+
const content = await getHTMLSnippet(targetElement2);
|
|
1275
|
+
const plainTextContent = wrapInSelectedElementTags(content);
|
|
1276
|
+
const htmlContent = createStructuredClipboardHtmlBlob([{
|
|
1297
1277
|
tagName,
|
|
1298
|
-
content
|
|
1299
|
-
computedStyles:
|
|
1278
|
+
content,
|
|
1279
|
+
computedStyles: extractRelevantComputedStyles(targetElement2)
|
|
1300
1280
|
}]);
|
|
1301
|
-
|
|
1281
|
+
const clipboardData = [plainTextContent, htmlContent];
|
|
1282
|
+
try {
|
|
1283
|
+
const screenshotDataUrl = await modernScreenshot.domToPng(targetElement2);
|
|
1284
|
+
const response = await fetch(screenshotDataUrl);
|
|
1285
|
+
const pngBlob = await response.blob();
|
|
1286
|
+
const imagePngBlob = new Blob([pngBlob], {
|
|
1287
|
+
type: "image/png"
|
|
1288
|
+
});
|
|
1289
|
+
clipboardData.push(imagePngBlob);
|
|
1290
|
+
} catch {
|
|
1291
|
+
}
|
|
1292
|
+
await copyContent(clipboardData);
|
|
1302
1293
|
} catch {
|
|
1303
1294
|
}
|
|
1304
|
-
|
|
1295
|
+
showTemporarySuccessLabel(tagName ? `<${tagName}>` : "<element>", copyStartX(), copyStartY());
|
|
1305
1296
|
};
|
|
1306
|
-
const
|
|
1297
|
+
const copyMultipleElementsToClipboard = async (targetElements) => {
|
|
1307
1298
|
if (targetElements.length === 0) return;
|
|
1308
|
-
let minPositionX = Infinity;
|
|
1309
|
-
let minPositionY = Infinity;
|
|
1310
1299
|
for (const element of targetElements) {
|
|
1311
|
-
|
|
1312
|
-
minPositionX = Math.min(minPositionX, elementBounds.left);
|
|
1313
|
-
minPositionY = Math.min(minPositionY, elementBounds.top);
|
|
1314
|
-
addGrabbedBox(createElementBounds(element));
|
|
1300
|
+
showTemporaryGrabbedBox(createElementBounds(element));
|
|
1315
1301
|
}
|
|
1316
1302
|
try {
|
|
1317
|
-
const elementSnippets = await Promise.all(targetElements.map((element) =>
|
|
1303
|
+
const elementSnippets = await Promise.all(targetElements.map((element) => getHTMLSnippet(element)));
|
|
1318
1304
|
const combinedContent = elementSnippets.join("\n\n---\n\n");
|
|
1319
|
-
const plainTextContent =
|
|
1320
|
-
const structuredElements =
|
|
1321
|
-
tagName:
|
|
1322
|
-
content
|
|
1323
|
-
computedStyles:
|
|
1324
|
-
}))
|
|
1325
|
-
const htmlContent =
|
|
1326
|
-
|
|
1305
|
+
const plainTextContent = wrapInSelectedElementTags(combinedContent);
|
|
1306
|
+
const structuredElements = elementSnippets.map((content, index) => ({
|
|
1307
|
+
tagName: extractElementTagName(targetElements[index]),
|
|
1308
|
+
content,
|
|
1309
|
+
computedStyles: extractRelevantComputedStyles(targetElements[index])
|
|
1310
|
+
}));
|
|
1311
|
+
const htmlContent = createStructuredClipboardHtmlBlob(structuredElements);
|
|
1312
|
+
const clipboardData = [plainTextContent, htmlContent];
|
|
1313
|
+
if (targetElements.length > 0) {
|
|
1314
|
+
try {
|
|
1315
|
+
const screenshotDataUrl = await modernScreenshot.domToPng(targetElements[0]);
|
|
1316
|
+
const response = await fetch(screenshotDataUrl);
|
|
1317
|
+
const pngBlob = await response.blob();
|
|
1318
|
+
const imagePngBlob = new Blob([pngBlob], {
|
|
1319
|
+
type: "image/png"
|
|
1320
|
+
});
|
|
1321
|
+
clipboardData.push(imagePngBlob);
|
|
1322
|
+
} catch {
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
await copyContent(clipboardData);
|
|
1327
1326
|
} catch {
|
|
1328
1327
|
}
|
|
1329
|
-
|
|
1328
|
+
showTemporarySuccessLabel(`${targetElements.length} elements`, copyStartX(), copyStartY());
|
|
1330
1329
|
};
|
|
1331
1330
|
const targetElement = solidJs.createMemo(() => {
|
|
1332
1331
|
if (!isRendererActive() || isDragging()) return null;
|
|
@@ -1347,16 +1346,16 @@ ${formattedStackTrace}`;
|
|
|
1347
1346
|
};
|
|
1348
1347
|
});
|
|
1349
1348
|
const DRAG_THRESHOLD_PX = 2;
|
|
1350
|
-
const
|
|
1349
|
+
const calculateDragDistance = (endX, endY) => ({
|
|
1351
1350
|
x: Math.abs(endX - dragStartX()),
|
|
1352
1351
|
y: Math.abs(endY - dragStartY())
|
|
1353
1352
|
});
|
|
1354
1353
|
const isDraggingBeyondThreshold = solidJs.createMemo(() => {
|
|
1355
1354
|
if (!isDragging()) return false;
|
|
1356
|
-
const dragDistance =
|
|
1355
|
+
const dragDistance = calculateDragDistance(mouseX(), mouseY());
|
|
1357
1356
|
return dragDistance.x > DRAG_THRESHOLD_PX || dragDistance.y > DRAG_THRESHOLD_PX;
|
|
1358
1357
|
});
|
|
1359
|
-
const
|
|
1358
|
+
const calculateDragRectangle = (endX, endY) => {
|
|
1360
1359
|
const dragX = Math.min(dragStartX(), endX);
|
|
1361
1360
|
const dragY = Math.min(dragStartY(), endY);
|
|
1362
1361
|
const dragWidth = Math.abs(endX - dragStartX());
|
|
@@ -1370,7 +1369,7 @@ ${formattedStackTrace}`;
|
|
|
1370
1369
|
};
|
|
1371
1370
|
const dragBounds = solidJs.createMemo(() => {
|
|
1372
1371
|
if (!isDraggingBeyondThreshold()) return void 0;
|
|
1373
|
-
const drag =
|
|
1372
|
+
const drag = calculateDragRectangle(mouseX(), mouseY());
|
|
1374
1373
|
return {
|
|
1375
1374
|
borderRadius: "0px",
|
|
1376
1375
|
height: drag.height,
|
|
@@ -1382,21 +1381,16 @@ ${formattedStackTrace}`;
|
|
|
1382
1381
|
});
|
|
1383
1382
|
const labelText = solidJs.createMemo(() => {
|
|
1384
1383
|
const element = targetElement();
|
|
1385
|
-
|
|
1386
|
-
const tagName = getElementTagName(element);
|
|
1387
|
-
return tagName ? `<${tagName}>` : "<element>";
|
|
1388
|
-
});
|
|
1389
|
-
const labelPosition = solidJs.createMemo(() => {
|
|
1390
|
-
return {
|
|
1391
|
-
x: mouseX(),
|
|
1392
|
-
y: mouseY()
|
|
1393
|
-
};
|
|
1384
|
+
return element ? `<${extractElementTagName(element)}>` : "<element>";
|
|
1394
1385
|
});
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1386
|
+
const labelPosition = solidJs.createMemo(() => isCopying() ? {
|
|
1387
|
+
x: copyStartX(),
|
|
1388
|
+
y: copyStartY()
|
|
1389
|
+
} : {
|
|
1390
|
+
x: mouseX(),
|
|
1391
|
+
y: mouseY()
|
|
1399
1392
|
});
|
|
1393
|
+
const isSameAsLast = solidJs.createMemo(() => Boolean(targetElement() && targetElement() === lastGrabbedElement()));
|
|
1400
1394
|
solidJs.createEffect(solidJs.on(() => [targetElement(), lastGrabbedElement()], ([currentElement, lastElement]) => {
|
|
1401
1395
|
if (lastElement && currentElement && lastElement !== currentElement) {
|
|
1402
1396
|
setLastGrabbedElement(null);
|
|
@@ -1443,9 +1437,12 @@ ${formattedStackTrace}`;
|
|
|
1443
1437
|
setIsActivated(true);
|
|
1444
1438
|
document.body.style.cursor = "crosshair";
|
|
1445
1439
|
};
|
|
1446
|
-
const deactivateRenderer = () => {
|
|
1440
|
+
const deactivateRenderer = (shouldResetModifier = true) => {
|
|
1447
1441
|
setIsHoldingKeys(false);
|
|
1448
1442
|
setIsActivated(false);
|
|
1443
|
+
if (shouldResetModifier) {
|
|
1444
|
+
setIsModifierHeld(false);
|
|
1445
|
+
}
|
|
1449
1446
|
document.body.style.cursor = "";
|
|
1450
1447
|
if (isDragging()) {
|
|
1451
1448
|
setIsDragging(false);
|
|
@@ -1454,23 +1451,38 @@ ${formattedStackTrace}`;
|
|
|
1454
1451
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1455
1452
|
if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
|
|
1456
1453
|
stopProgressAnimation();
|
|
1454
|
+
lastDeactivationTime = Date.now();
|
|
1457
1455
|
};
|
|
1458
1456
|
const abortController = new AbortController();
|
|
1459
1457
|
const eventListenerSignal = abortController.signal;
|
|
1460
1458
|
window.addEventListener("keydown", (event) => {
|
|
1459
|
+
if (event.metaKey || event.ctrlKey) {
|
|
1460
|
+
setIsModifierHeld(true);
|
|
1461
|
+
}
|
|
1461
1462
|
if (event.key === "Escape" && isHoldingKeys()) {
|
|
1462
1463
|
deactivateRenderer();
|
|
1463
1464
|
return;
|
|
1464
1465
|
}
|
|
1465
1466
|
if (isKeyboardEventTriggeredByInput(event)) return;
|
|
1466
1467
|
if (isTargetKeyCombination(event)) {
|
|
1468
|
+
const wasRecentlyDeactivated = lastDeactivationTime !== null && Date.now() - lastDeactivationTime < QUICK_REPRESS_THRESHOLD_MS;
|
|
1467
1469
|
if (!isHoldingKeys()) {
|
|
1468
1470
|
setIsHoldingKeys(true);
|
|
1469
|
-
|
|
1470
|
-
holdTimerId = window.setTimeout(() => {
|
|
1471
|
+
if (wasRecentlyDeactivated && isModifierHeld()) {
|
|
1471
1472
|
activateRenderer();
|
|
1472
1473
|
options.onActivate?.();
|
|
1473
|
-
|
|
1474
|
+
const element = getElementAtPosition(mouseX(), mouseY());
|
|
1475
|
+
if (element) {
|
|
1476
|
+
setLastGrabbedElement(element);
|
|
1477
|
+
void executeCopyOperation(mouseX(), mouseY(), () => copySingleElementToClipboard(element));
|
|
1478
|
+
}
|
|
1479
|
+
} else {
|
|
1480
|
+
startProgressAnimation();
|
|
1481
|
+
holdTimerId = window.setTimeout(() => {
|
|
1482
|
+
activateRenderer();
|
|
1483
|
+
options.onActivate?.();
|
|
1484
|
+
}, options.keyHoldDuration);
|
|
1485
|
+
}
|
|
1474
1486
|
}
|
|
1475
1487
|
if (isActivated()) {
|
|
1476
1488
|
if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
|
|
@@ -1483,11 +1495,16 @@ ${formattedStackTrace}`;
|
|
|
1483
1495
|
signal: eventListenerSignal
|
|
1484
1496
|
});
|
|
1485
1497
|
window.addEventListener("keyup", (event) => {
|
|
1486
|
-
if (!isHoldingKeys() && !isActivated()) return;
|
|
1487
|
-
const isReleasingC = event.key.toLowerCase() === "c";
|
|
1488
1498
|
const isReleasingModifier = !event.metaKey && !event.ctrlKey;
|
|
1489
|
-
|
|
1490
|
-
|
|
1499
|
+
const isReleasingC = event.key.toLowerCase() === "c";
|
|
1500
|
+
if (isReleasingModifier) {
|
|
1501
|
+
setIsModifierHeld(false);
|
|
1502
|
+
}
|
|
1503
|
+
if (!isHoldingKeys() && !isActivated()) return;
|
|
1504
|
+
if (isReleasingC) {
|
|
1505
|
+
deactivateRenderer(false);
|
|
1506
|
+
} else if (isReleasingModifier) {
|
|
1507
|
+
deactivateRenderer(true);
|
|
1491
1508
|
}
|
|
1492
1509
|
}, {
|
|
1493
1510
|
signal: eventListenerSignal,
|
|
@@ -1511,39 +1528,41 @@ ${formattedStackTrace}`;
|
|
|
1511
1528
|
});
|
|
1512
1529
|
window.addEventListener("mouseup", (event) => {
|
|
1513
1530
|
if (!isDragging()) return;
|
|
1514
|
-
const dragDistance =
|
|
1531
|
+
const dragDistance = calculateDragDistance(event.clientX, event.clientY);
|
|
1515
1532
|
const wasDragGesture = dragDistance.x > DRAG_THRESHOLD_PX || dragDistance.y > DRAG_THRESHOLD_PX;
|
|
1516
1533
|
setIsDragging(false);
|
|
1517
1534
|
document.body.style.userSelect = "";
|
|
1518
1535
|
if (wasDragGesture) {
|
|
1519
|
-
|
|
1536
|
+
setDidJustDrag(true);
|
|
1537
|
+
const dragRect = calculateDragRectangle(event.clientX, event.clientY);
|
|
1520
1538
|
const elements = getElementsInDrag(dragRect, isValidGrabbableElement);
|
|
1521
1539
|
if (elements.length > 0) {
|
|
1522
|
-
|
|
1523
|
-
void handleMultipleCopy(elements).finally(() => {
|
|
1524
|
-
setIsCopying(false);
|
|
1525
|
-
});
|
|
1540
|
+
void executeCopyOperation(event.clientX, event.clientY, () => copyMultipleElementsToClipboard(elements));
|
|
1526
1541
|
} else {
|
|
1527
1542
|
const fallbackElements = getElementsInDragLoose(dragRect, isValidGrabbableElement);
|
|
1528
1543
|
if (fallbackElements.length > 0) {
|
|
1529
|
-
|
|
1530
|
-
void handleMultipleCopy(fallbackElements).finally(() => {
|
|
1531
|
-
setIsCopying(false);
|
|
1532
|
-
});
|
|
1544
|
+
void executeCopyOperation(event.clientX, event.clientY, () => copyMultipleElementsToClipboard(fallbackElements));
|
|
1533
1545
|
}
|
|
1534
1546
|
}
|
|
1535
1547
|
} else {
|
|
1536
1548
|
const element = getElementAtPosition(event.clientX, event.clientY);
|
|
1537
1549
|
if (!element) return;
|
|
1538
|
-
setIsCopying(true);
|
|
1539
1550
|
setLastGrabbedElement(element);
|
|
1540
|
-
void
|
|
1541
|
-
setIsCopying(false);
|
|
1542
|
-
});
|
|
1551
|
+
void executeCopyOperation(event.clientX, event.clientY, () => copySingleElementToClipboard(element));
|
|
1543
1552
|
}
|
|
1544
1553
|
}, {
|
|
1545
1554
|
signal: eventListenerSignal
|
|
1546
1555
|
});
|
|
1556
|
+
window.addEventListener("click", (event) => {
|
|
1557
|
+
if (didJustDrag()) {
|
|
1558
|
+
event.preventDefault();
|
|
1559
|
+
event.stopPropagation();
|
|
1560
|
+
setDidJustDrag(false);
|
|
1561
|
+
}
|
|
1562
|
+
}, {
|
|
1563
|
+
signal: eventListenerSignal,
|
|
1564
|
+
capture: true
|
|
1565
|
+
});
|
|
1547
1566
|
document.addEventListener("visibilitychange", () => {
|
|
1548
1567
|
if (document.hidden) {
|
|
1549
1568
|
setGrabbedBoxes([]);
|
|
@@ -1563,7 +1582,7 @@ ${formattedStackTrace}`;
|
|
|
1563
1582
|
const selectionVisible = solidJs.createMemo(() => false);
|
|
1564
1583
|
const dragVisible = solidJs.createMemo(() => isRendererActive() && isDraggingBeyondThreshold());
|
|
1565
1584
|
const labelVariant = solidJs.createMemo(() => isCopying() ? "processing" : "hover");
|
|
1566
|
-
const labelVisible = solidJs.createMemo(() => isRendererActive() && !isDragging() && (
|
|
1585
|
+
const labelVisible = solidJs.createMemo(() => isRendererActive() && !isDragging() && (Boolean(targetElement()) && !isSameAsLast() || !targetElement()) || isCopying());
|
|
1567
1586
|
const progressVisible = solidJs.createMemo(() => isHoldingKeys() && showProgressIndicator() && hasValidMousePosition());
|
|
1568
1587
|
const crosshairVisible = solidJs.createMemo(() => isRendererActive() && !isDragging());
|
|
1569
1588
|
web.render(() => web.createComponent(ReactGrabRenderer, {
|