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