react-grab 0.0.24 → 0.0.25
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 +571 -446
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.global.js +16 -29
- package/dist/index.js +573 -448
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -91,93 +91,89 @@ var mountRoot = () => {
|
|
|
91
91
|
return root;
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
-
// src/
|
|
95
|
-
var isElementVisible = (element, computedStyle = window.getComputedStyle(element)) => {
|
|
96
|
-
return computedStyle.display !== "none" && computedStyle.visibility !== "hidden" && computedStyle.opacity !== "0";
|
|
97
|
-
};
|
|
98
|
-
var _tmpl$ = /* @__PURE__ */ web.template(`<div>`);
|
|
99
|
-
var _tmpl$2 = /* @__PURE__ */ web.template(`<span style="display:inline-block;width:8px;height:8px;border:1.5px solid rgb(210, 57, 192);border-top-color:transparent;border-radius:50%;margin-right:4px;vertical-align:middle">`);
|
|
100
|
-
var _tmpl$3 = /* @__PURE__ */ web.template(`<span style=display:inline-block;margin-right:4px;font-weight:600>\u2713`);
|
|
101
|
-
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">`);
|
|
102
|
-
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"><span>`);
|
|
103
|
-
var _tmpl$6 = /* @__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)">`);
|
|
94
|
+
// src/constants.ts
|
|
104
95
|
var VIEWPORT_MARGIN_PX = 8;
|
|
105
|
-
var LABEL_OFFSET_PX = 6;
|
|
106
96
|
var INDICATOR_CLAMP_PADDING_PX = 4;
|
|
107
|
-
var
|
|
97
|
+
var CURSOR_OFFSET_PX = 14;
|
|
108
98
|
var SELECTION_LERP_FACTOR = 0.95;
|
|
109
|
-
|
|
99
|
+
|
|
100
|
+
// src/utils/lerp.ts
|
|
110
101
|
var lerp = (start, end, factor) => {
|
|
111
102
|
return start + (end - start) * factor;
|
|
112
103
|
};
|
|
113
|
-
|
|
104
|
+
|
|
105
|
+
// src/components/selection-box.tsx
|
|
106
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<div>`);
|
|
107
|
+
var SelectionBox = (props) => {
|
|
114
108
|
const [currentX, setCurrentX] = solidJs.createSignal(props.bounds.x);
|
|
115
109
|
const [currentY, setCurrentY] = solidJs.createSignal(props.bounds.y);
|
|
116
110
|
const [currentWidth, setCurrentWidth] = solidJs.createSignal(props.bounds.width);
|
|
117
111
|
const [currentHeight, setCurrentHeight] = solidJs.createSignal(props.bounds.height);
|
|
118
112
|
const [opacity, setOpacity] = solidJs.createSignal(1);
|
|
119
|
-
let
|
|
113
|
+
let hasBeenRenderedOnce = false;
|
|
120
114
|
let animationFrameId = null;
|
|
121
115
|
let targetBounds = props.bounds;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const EPSILON = 0.5;
|
|
116
|
+
let isAnimating = false;
|
|
117
|
+
const lerpFactor = () => {
|
|
118
|
+
if (props.lerpFactor !== void 0) return props.lerpFactor;
|
|
119
|
+
if (props.variant === "drag") return 0.9;
|
|
120
|
+
return SELECTION_LERP_FACTOR;
|
|
121
|
+
};
|
|
122
|
+
const startAnimation = () => {
|
|
123
|
+
if (isAnimating) return;
|
|
124
|
+
isAnimating = true;
|
|
134
125
|
const animate = () => {
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
setCurrentX(
|
|
140
|
-
setCurrentY(
|
|
141
|
-
setCurrentWidth(
|
|
142
|
-
setCurrentHeight(
|
|
143
|
-
const
|
|
144
|
-
if (!
|
|
126
|
+
const interpolatedX = lerp(currentX(), targetBounds.x, lerpFactor());
|
|
127
|
+
const interpolatedY = lerp(currentY(), targetBounds.y, lerpFactor());
|
|
128
|
+
const interpolatedWidth = lerp(currentWidth(), targetBounds.width, lerpFactor());
|
|
129
|
+
const interpolatedHeight = lerp(currentHeight(), targetBounds.height, lerpFactor());
|
|
130
|
+
setCurrentX(interpolatedX);
|
|
131
|
+
setCurrentY(interpolatedY);
|
|
132
|
+
setCurrentWidth(interpolatedWidth);
|
|
133
|
+
setCurrentHeight(interpolatedHeight);
|
|
134
|
+
const hasConvergedToTarget = Math.abs(interpolatedX - targetBounds.x) < 0.5 && Math.abs(interpolatedY - targetBounds.y) < 0.5 && Math.abs(interpolatedWidth - targetBounds.width) < 0.5 && Math.abs(interpolatedHeight - targetBounds.height) < 0.5;
|
|
135
|
+
if (!hasConvergedToTarget) {
|
|
145
136
|
animationFrameId = requestAnimationFrame(animate);
|
|
146
137
|
} else {
|
|
147
138
|
animationFrameId = null;
|
|
139
|
+
isAnimating = false;
|
|
148
140
|
}
|
|
149
141
|
};
|
|
142
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
143
|
+
};
|
|
144
|
+
solidJs.createEffect(solidJs.on(() => props.bounds, (newBounds) => {
|
|
145
|
+
targetBounds = newBounds;
|
|
146
|
+
if (!hasBeenRenderedOnce) {
|
|
147
|
+
setCurrentX(targetBounds.x);
|
|
148
|
+
setCurrentY(targetBounds.y);
|
|
149
|
+
setCurrentWidth(targetBounds.width);
|
|
150
|
+
setCurrentHeight(targetBounds.height);
|
|
151
|
+
hasBeenRenderedOnce = true;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
startAnimation();
|
|
155
|
+
}));
|
|
156
|
+
solidJs.onCleanup(() => {
|
|
150
157
|
if (animationFrameId !== null) {
|
|
151
158
|
cancelAnimationFrame(animationFrameId);
|
|
159
|
+
animationFrameId = null;
|
|
152
160
|
}
|
|
153
|
-
|
|
154
|
-
solidJs.onCleanup(() => {
|
|
155
|
-
if (animationFrameId !== null) {
|
|
156
|
-
cancelAnimationFrame(animationFrameId);
|
|
157
|
-
animationFrameId = null;
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
solidJs.createEffect(() => {
|
|
162
|
-
if (props.variant === "grabbed") {
|
|
163
|
-
requestAnimationFrame(() => {
|
|
164
|
-
setOpacity(0);
|
|
165
|
-
});
|
|
166
|
-
}
|
|
161
|
+
isAnimating = false;
|
|
167
162
|
});
|
|
168
163
|
const baseStyle = {
|
|
169
164
|
position: "fixed",
|
|
170
165
|
"box-sizing": "border-box",
|
|
171
|
-
"pointer-events": props.variant === "
|
|
166
|
+
"pointer-events": props.variant === "drag" ? "none" : "auto",
|
|
172
167
|
"z-index": "2147483646"
|
|
173
168
|
};
|
|
174
169
|
const variantStyle = () => {
|
|
175
|
-
if (props.variant === "
|
|
170
|
+
if (props.variant === "drag") {
|
|
176
171
|
return {
|
|
177
172
|
border: "1px dashed rgb(210, 57, 192)",
|
|
178
|
-
"background-color": "rgba(210, 57, 192, 0.
|
|
173
|
+
"background-color": "rgba(210, 57, 192, 0.15)",
|
|
179
174
|
"will-change": "transform, width, height",
|
|
180
|
-
contain: "layout paint size"
|
|
175
|
+
contain: "layout paint size",
|
|
176
|
+
cursor: "crosshair"
|
|
181
177
|
};
|
|
182
178
|
}
|
|
183
179
|
return {
|
|
@@ -207,11 +203,12 @@ var Overlay = (props) => {
|
|
|
207
203
|
}
|
|
208
204
|
});
|
|
209
205
|
};
|
|
206
|
+
var _tmpl$2 = /* @__PURE__ */ web.template(`<span style="display:inline-block;width:8px;height:8px;border:1.5px solid rgb(210, 57, 192);border-top-color:transparent;border-radius:50%;margin-right:4px;vertical-align:middle">`);
|
|
210
207
|
var Spinner = (props) => {
|
|
211
|
-
let
|
|
212
|
-
solidJs.
|
|
213
|
-
if (
|
|
214
|
-
|
|
208
|
+
let spinnerRef;
|
|
209
|
+
solidJs.onMount(() => {
|
|
210
|
+
if (spinnerRef) {
|
|
211
|
+
spinnerRef.animate([{
|
|
215
212
|
transform: "rotate(0deg)"
|
|
216
213
|
}, {
|
|
217
214
|
transform: "rotate(360deg)"
|
|
@@ -223,126 +220,145 @@ var Spinner = (props) => {
|
|
|
223
220
|
}
|
|
224
221
|
});
|
|
225
222
|
return (() => {
|
|
226
|
-
var _el$
|
|
227
|
-
var _ref$ =
|
|
228
|
-
typeof _ref$ === "function" ? web.use(_ref$, _el$
|
|
229
|
-
web.effect((_$p) => web.style(_el
|
|
223
|
+
var _el$ = _tmpl$2();
|
|
224
|
+
var _ref$ = spinnerRef;
|
|
225
|
+
typeof _ref$ === "function" ? web.use(_ref$, _el$) : spinnerRef = _el$;
|
|
226
|
+
web.effect((_$p) => web.style(_el$, {
|
|
230
227
|
...props.style
|
|
231
228
|
}, _$p));
|
|
232
|
-
return _el
|
|
229
|
+
return _el$;
|
|
233
230
|
})();
|
|
234
231
|
};
|
|
232
|
+
|
|
233
|
+
// src/utils/get-clamped-element-position.ts
|
|
234
|
+
var getClampedElementPosition = (positionLeft, positionTop, elementWidth, elementHeight) => {
|
|
235
|
+
const viewportWidth = window.innerWidth;
|
|
236
|
+
const viewportHeight = window.innerHeight;
|
|
237
|
+
const minLeft = VIEWPORT_MARGIN_PX;
|
|
238
|
+
const minTop = VIEWPORT_MARGIN_PX;
|
|
239
|
+
const maxLeft = viewportWidth - elementWidth - VIEWPORT_MARGIN_PX;
|
|
240
|
+
const maxTop = viewportHeight - elementHeight - VIEWPORT_MARGIN_PX;
|
|
241
|
+
const clampedLeft = Math.max(minLeft, Math.min(positionLeft, maxLeft));
|
|
242
|
+
const clampedTop = Math.max(minTop, Math.min(positionTop, maxTop));
|
|
243
|
+
return { left: clampedLeft, top: clampedTop };
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// src/components/label.tsx
|
|
247
|
+
var _tmpl$3 = /* @__PURE__ */ web.template(`<span style=display:inline-block;margin-right:4px;font-weight:600>\u2713`);
|
|
248
|
+
var _tmpl$22 = /* @__PURE__ */ web.template(`<div style=margin-right:4px>Grabbed`);
|
|
249
|
+
var _tmpl$32 = /* @__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"><span style="font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;font-variant-numeric:tabular-nums">`);
|
|
235
250
|
var Label = (props) => {
|
|
236
251
|
const [opacity, setOpacity] = solidJs.createSignal(0);
|
|
237
|
-
let
|
|
238
|
-
solidJs.createEffect(() => {
|
|
239
|
-
if (
|
|
252
|
+
let labelRef;
|
|
253
|
+
solidJs.createEffect(solidJs.on(() => props.visible, (visible) => {
|
|
254
|
+
if (visible !== false) {
|
|
240
255
|
requestAnimationFrame(() => {
|
|
241
256
|
setOpacity(1);
|
|
242
257
|
});
|
|
243
258
|
} else {
|
|
244
259
|
setOpacity(0);
|
|
260
|
+
return;
|
|
245
261
|
}
|
|
246
|
-
});
|
|
247
|
-
solidJs.createEffect(() => {
|
|
248
262
|
if (props.variant === "success") {
|
|
249
263
|
const fadeOutTimer = setTimeout(() => {
|
|
250
264
|
setOpacity(0);
|
|
251
|
-
},
|
|
265
|
+
}, 1500);
|
|
252
266
|
solidJs.onCleanup(() => clearTimeout(fadeOutTimer));
|
|
253
267
|
}
|
|
254
|
-
});
|
|
255
|
-
const
|
|
268
|
+
}));
|
|
269
|
+
const labelBoundingRect = () => labelRef?.getBoundingClientRect();
|
|
256
270
|
const computedPosition = () => {
|
|
257
|
-
const
|
|
258
|
-
if (!
|
|
271
|
+
const boundingRect = labelBoundingRect();
|
|
272
|
+
if (!boundingRect) return {
|
|
259
273
|
left: props.x,
|
|
260
274
|
top: props.y
|
|
261
275
|
};
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
indicatorTopPx = Math.max(minTop, Math.min(indicatorTopPx, maxTop));
|
|
275
|
-
if (isClamped) {
|
|
276
|
-
indicatorLeftPx += INDICATOR_CLAMP_PADDING_PX;
|
|
277
|
-
indicatorTopPx += INDICATOR_CLAMP_PADDING_PX;
|
|
276
|
+
if (props.variant === "success") {
|
|
277
|
+
const indicatorLeft = Math.round(props.x);
|
|
278
|
+
const indicatorTop = Math.round(props.y) - boundingRect.height - 6;
|
|
279
|
+
const willClampLeft = indicatorLeft < VIEWPORT_MARGIN_PX;
|
|
280
|
+
const willClampTop = indicatorTop < VIEWPORT_MARGIN_PX;
|
|
281
|
+
const isClamped = willClampLeft || willClampTop;
|
|
282
|
+
const clamped = getClampedElementPosition(indicatorLeft, indicatorTop, boundingRect.width, boundingRect.height);
|
|
283
|
+
if (isClamped) {
|
|
284
|
+
clamped.left += INDICATOR_CLAMP_PADDING_PX;
|
|
285
|
+
clamped.top += INDICATOR_CLAMP_PADDING_PX;
|
|
286
|
+
}
|
|
287
|
+
return clamped;
|
|
278
288
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
289
|
+
const CROSSHAIR_OFFSET = 12;
|
|
290
|
+
const viewportWidth = window.innerWidth;
|
|
291
|
+
const viewportHeight = window.innerHeight;
|
|
292
|
+
const quadrants = [{
|
|
293
|
+
left: Math.round(props.x) + CROSSHAIR_OFFSET,
|
|
294
|
+
top: Math.round(props.y) + CROSSHAIR_OFFSET
|
|
295
|
+
}, {
|
|
296
|
+
left: Math.round(props.x) - boundingRect.width - CROSSHAIR_OFFSET,
|
|
297
|
+
top: Math.round(props.y) + CROSSHAIR_OFFSET
|
|
298
|
+
}, {
|
|
299
|
+
left: Math.round(props.x) + CROSSHAIR_OFFSET,
|
|
300
|
+
top: Math.round(props.y) - boundingRect.height - CROSSHAIR_OFFSET
|
|
301
|
+
}, {
|
|
302
|
+
left: Math.round(props.x) - boundingRect.width - CROSSHAIR_OFFSET,
|
|
303
|
+
top: Math.round(props.y) - boundingRect.height - CROSSHAIR_OFFSET
|
|
304
|
+
}];
|
|
305
|
+
for (const position of quadrants) {
|
|
306
|
+
const fitsHorizontally = position.left >= VIEWPORT_MARGIN_PX && position.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
|
|
307
|
+
const fitsVertically = position.top >= VIEWPORT_MARGIN_PX && position.top + boundingRect.height <= viewportHeight - VIEWPORT_MARGIN_PX;
|
|
308
|
+
if (fitsHorizontally && fitsVertically) {
|
|
309
|
+
return position;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
const fallback = getClampedElementPosition(quadrants[0].left, quadrants[0].top, boundingRect.width, boundingRect.height);
|
|
313
|
+
fallback.left += INDICATOR_CLAMP_PADDING_PX;
|
|
314
|
+
fallback.top += INDICATOR_CLAMP_PADDING_PX;
|
|
315
|
+
return fallback;
|
|
283
316
|
};
|
|
284
317
|
return web.createComponent(solidJs.Show, {
|
|
285
318
|
get when() {
|
|
286
319
|
return props.visible !== false;
|
|
287
320
|
},
|
|
288
321
|
get children() {
|
|
289
|
-
var _el$
|
|
290
|
-
var _ref$
|
|
291
|
-
typeof _ref$
|
|
292
|
-
web.insert(_el
|
|
322
|
+
var _el$ = _tmpl$32(), _el$4 = _el$.firstChild;
|
|
323
|
+
var _ref$ = labelRef;
|
|
324
|
+
typeof _ref$ === "function" ? web.use(_ref$, _el$) : labelRef = _el$;
|
|
325
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
293
326
|
get when() {
|
|
294
327
|
return props.variant === "processing";
|
|
295
328
|
},
|
|
296
329
|
get children() {
|
|
297
330
|
return web.createComponent(Spinner, {});
|
|
298
331
|
}
|
|
299
|
-
}), _el$
|
|
300
|
-
web.insert(_el
|
|
332
|
+
}), _el$4);
|
|
333
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
301
334
|
get when() {
|
|
302
335
|
return props.variant === "success";
|
|
303
336
|
},
|
|
304
337
|
get children() {
|
|
305
338
|
return _tmpl$3();
|
|
306
339
|
}
|
|
307
|
-
}), _el$
|
|
308
|
-
web.insert(_el
|
|
340
|
+
}), _el$4);
|
|
341
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
309
342
|
get when() {
|
|
310
343
|
return props.variant === "success";
|
|
311
344
|
},
|
|
312
|
-
children: "Grabbed "
|
|
313
|
-
}), null);
|
|
314
|
-
web.insert(_el$5, web.createComponent(solidJs.Show, {
|
|
315
|
-
get when() {
|
|
316
|
-
return props.variant === "processing";
|
|
317
|
-
},
|
|
318
|
-
children: "Grabbing\u2026"
|
|
319
|
-
}), null);
|
|
320
|
-
web.insert(_el$5, web.createComponent(solidJs.Show, {
|
|
321
|
-
get when() {
|
|
322
|
-
return props.variant === "hover";
|
|
323
|
-
},
|
|
324
345
|
get children() {
|
|
325
|
-
|
|
326
|
-
web.insert(_el$6, () => props.text);
|
|
327
|
-
return _el$6;
|
|
346
|
+
return _tmpl$22();
|
|
328
347
|
}
|
|
329
|
-
}),
|
|
330
|
-
web.insert(_el
|
|
348
|
+
}), _el$4);
|
|
349
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
331
350
|
get when() {
|
|
332
|
-
return props.variant
|
|
351
|
+
return props.variant === "processing";
|
|
333
352
|
},
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
return _el$7;
|
|
338
|
-
}
|
|
339
|
-
}), null);
|
|
353
|
+
children: "Grabbing\u2026"
|
|
354
|
+
}), _el$4);
|
|
355
|
+
web.insert(_el$4, () => props.text);
|
|
340
356
|
web.effect((_p$) => {
|
|
341
357
|
var _v$ = `${computedPosition().top}px`, _v$2 = `${computedPosition().left}px`, _v$3 = props.zIndex?.toString() ?? "2147483647", _v$4 = opacity();
|
|
342
|
-
_v$ !== _p$.e && web.setStyleProperty(_el
|
|
343
|
-
_v$2 !== _p$.t && web.setStyleProperty(_el
|
|
344
|
-
_v$3 !== _p$.a && web.setStyleProperty(_el
|
|
345
|
-
_v$4 !== _p$.o && web.setStyleProperty(_el
|
|
358
|
+
_v$ !== _p$.e && web.setStyleProperty(_el$, "top", _p$.e = _v$);
|
|
359
|
+
_v$2 !== _p$.t && web.setStyleProperty(_el$, "left", _p$.t = _v$2);
|
|
360
|
+
_v$3 !== _p$.a && web.setStyleProperty(_el$, "z-index", _p$.a = _v$3);
|
|
361
|
+
_v$4 !== _p$.o && web.setStyleProperty(_el$, "opacity", _p$.o = _v$4);
|
|
346
362
|
return _p$;
|
|
347
363
|
}, {
|
|
348
364
|
e: void 0,
|
|
@@ -350,58 +366,52 @@ var Label = (props) => {
|
|
|
350
366
|
a: void 0,
|
|
351
367
|
o: void 0
|
|
352
368
|
});
|
|
353
|
-
return _el
|
|
369
|
+
return _el$;
|
|
354
370
|
}
|
|
355
371
|
});
|
|
356
372
|
};
|
|
357
|
-
var
|
|
373
|
+
var _tmpl$4 = /* @__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)">`);
|
|
374
|
+
var useFadeInOut = (visible) => {
|
|
358
375
|
const [opacity, setOpacity] = solidJs.createSignal(0);
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
if (props.visible !== false) {
|
|
376
|
+
solidJs.createEffect(solidJs.on(() => visible, (isVisible) => {
|
|
377
|
+
if (isVisible !== false) {
|
|
362
378
|
requestAnimationFrame(() => {
|
|
363
379
|
setOpacity(1);
|
|
364
380
|
});
|
|
365
381
|
} else {
|
|
366
382
|
setOpacity(0);
|
|
367
383
|
}
|
|
368
|
-
});
|
|
384
|
+
}));
|
|
385
|
+
return opacity;
|
|
386
|
+
};
|
|
387
|
+
var ProgressIndicator = (props) => {
|
|
388
|
+
const opacity = useFadeInOut(props.visible);
|
|
389
|
+
let progressIndicatorRef;
|
|
369
390
|
const computedPosition = () => {
|
|
370
|
-
const
|
|
371
|
-
if (!
|
|
391
|
+
const boundingRect = progressIndicatorRef?.getBoundingClientRect();
|
|
392
|
+
if (!boundingRect) return {
|
|
372
393
|
left: props.mouseX,
|
|
373
394
|
top: props.mouseY
|
|
374
395
|
};
|
|
375
|
-
const viewportWidth = window.innerWidth;
|
|
376
396
|
const viewportHeight = window.innerHeight;
|
|
377
|
-
const
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
let indicatorTop = props.mouseY + CURSOR_OFFSET;
|
|
381
|
-
if (indicatorTop + rect.height + VIEWPORT_MARGIN > viewportHeight) {
|
|
382
|
-
indicatorTop = props.mouseY - rect.height - CURSOR_OFFSET;
|
|
383
|
-
}
|
|
384
|
-
indicatorTop = Math.max(VIEWPORT_MARGIN, Math.min(indicatorTop, viewportHeight - rect.height - VIEWPORT_MARGIN));
|
|
385
|
-
indicatorLeft = Math.max(VIEWPORT_MARGIN, Math.min(indicatorLeft, viewportWidth - rect.width - VIEWPORT_MARGIN));
|
|
386
|
-
return {
|
|
387
|
-
left: indicatorLeft,
|
|
388
|
-
top: indicatorTop
|
|
389
|
-
};
|
|
397
|
+
const indicatorLeft = props.mouseX - boundingRect.width / 2;
|
|
398
|
+
const indicatorTop = props.mouseY + CURSOR_OFFSET_PX + boundingRect.height + VIEWPORT_MARGIN_PX > viewportHeight ? props.mouseY - boundingRect.height - CURSOR_OFFSET_PX : props.mouseY + CURSOR_OFFSET_PX;
|
|
399
|
+
return getClampedElementPosition(indicatorLeft, indicatorTop, boundingRect.width, boundingRect.height);
|
|
390
400
|
};
|
|
391
401
|
return web.createComponent(solidJs.Show, {
|
|
392
402
|
get when() {
|
|
393
403
|
return props.visible !== false;
|
|
394
404
|
},
|
|
395
405
|
get children() {
|
|
396
|
-
var _el$
|
|
397
|
-
var _ref$
|
|
398
|
-
typeof _ref$
|
|
406
|
+
var _el$ = _tmpl$4(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
|
|
407
|
+
var _ref$ = progressIndicatorRef;
|
|
408
|
+
typeof _ref$ === "function" ? web.use(_ref$, _el$) : progressIndicatorRef = _el$;
|
|
399
409
|
web.effect((_p$) => {
|
|
400
|
-
var _v$
|
|
401
|
-
_v$
|
|
402
|
-
_v$
|
|
403
|
-
_v$
|
|
404
|
-
_v$
|
|
410
|
+
var _v$ = `${computedPosition().top}px`, _v$2 = `${computedPosition().left}px`, _v$3 = opacity(), _v$4 = `${Math.min(100, Math.max(0, props.progress * 100))}%`;
|
|
411
|
+
_v$ !== _p$.e && web.setStyleProperty(_el$, "top", _p$.e = _v$);
|
|
412
|
+
_v$2 !== _p$.t && web.setStyleProperty(_el$, "left", _p$.t = _v$2);
|
|
413
|
+
_v$3 !== _p$.a && web.setStyleProperty(_el$, "opacity", _p$.a = _v$3);
|
|
414
|
+
_v$4 !== _p$.o && web.setStyleProperty(_el$3, "width", _p$.o = _v$4);
|
|
405
415
|
return _p$;
|
|
406
416
|
}, {
|
|
407
417
|
e: void 0,
|
|
@@ -409,53 +419,131 @@ var ProgressIndicator = (props) => {
|
|
|
409
419
|
a: void 0,
|
|
410
420
|
o: void 0
|
|
411
421
|
});
|
|
412
|
-
return _el
|
|
422
|
+
return _el$;
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
};
|
|
426
|
+
var _tmpl$5 = /* @__PURE__ */ web.template(`<div style=position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:2147483645><div style="position:absolute;top:0;width:1px;height:100%;background-color:rgba(210, 57, 192, 0.5);will-change:transform"></div><div style="position:absolute;left:0;width:100%;height:1px;background-color:rgba(210, 57, 192, 0.5);will-change:transform">`);
|
|
427
|
+
var Crosshair = (props) => {
|
|
428
|
+
const [currentX, setCurrentX] = solidJs.createSignal(props.mouseX);
|
|
429
|
+
const [currentY, setCurrentY] = solidJs.createSignal(props.mouseY);
|
|
430
|
+
let hasBeenRenderedOnce = false;
|
|
431
|
+
let animationFrameId = null;
|
|
432
|
+
let targetX = props.mouseX;
|
|
433
|
+
let targetY = props.mouseY;
|
|
434
|
+
let isAnimating = false;
|
|
435
|
+
const startAnimation = () => {
|
|
436
|
+
if (isAnimating) return;
|
|
437
|
+
isAnimating = true;
|
|
438
|
+
const animate = () => {
|
|
439
|
+
const interpolatedX = lerp(currentX(), targetX, 0.3);
|
|
440
|
+
const interpolatedY = lerp(currentY(), targetY, 0.3);
|
|
441
|
+
setCurrentX(interpolatedX);
|
|
442
|
+
setCurrentY(interpolatedY);
|
|
443
|
+
const hasConvergedToTarget = Math.abs(interpolatedX - targetX) < 0.5 && Math.abs(interpolatedY - targetY) < 0.5;
|
|
444
|
+
if (!hasConvergedToTarget) {
|
|
445
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
446
|
+
} else {
|
|
447
|
+
animationFrameId = null;
|
|
448
|
+
isAnimating = false;
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
452
|
+
};
|
|
453
|
+
solidJs.createEffect(solidJs.on(() => [props.mouseX, props.mouseY], ([newMouseX, newMouseY]) => {
|
|
454
|
+
targetX = newMouseX;
|
|
455
|
+
targetY = newMouseY;
|
|
456
|
+
if (!hasBeenRenderedOnce) {
|
|
457
|
+
setCurrentX(targetX);
|
|
458
|
+
setCurrentY(targetY);
|
|
459
|
+
hasBeenRenderedOnce = true;
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
startAnimation();
|
|
463
|
+
}));
|
|
464
|
+
solidJs.onCleanup(() => {
|
|
465
|
+
if (animationFrameId !== null) {
|
|
466
|
+
cancelAnimationFrame(animationFrameId);
|
|
467
|
+
animationFrameId = null;
|
|
468
|
+
}
|
|
469
|
+
isAnimating = false;
|
|
470
|
+
});
|
|
471
|
+
return web.createComponent(solidJs.Show, {
|
|
472
|
+
get when() {
|
|
473
|
+
return props.visible !== false;
|
|
474
|
+
},
|
|
475
|
+
get children() {
|
|
476
|
+
var _el$ = _tmpl$5(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
|
|
477
|
+
web.effect((_p$) => {
|
|
478
|
+
var _v$ = `${currentX()}px`, _v$2 = `${currentY()}px`;
|
|
479
|
+
_v$ !== _p$.e && web.setStyleProperty(_el$2, "left", _p$.e = _v$);
|
|
480
|
+
_v$2 !== _p$.t && web.setStyleProperty(_el$3, "top", _p$.t = _v$2);
|
|
481
|
+
return _p$;
|
|
482
|
+
}, {
|
|
483
|
+
e: void 0,
|
|
484
|
+
t: void 0
|
|
485
|
+
});
|
|
486
|
+
return _el$;
|
|
413
487
|
}
|
|
414
488
|
});
|
|
415
489
|
};
|
|
416
|
-
|
|
490
|
+
|
|
491
|
+
// src/components/renderer.tsx
|
|
492
|
+
var ReactGrabRenderer = (props) => {
|
|
417
493
|
return [web.createComponent(solidJs.Show, {
|
|
418
494
|
get when() {
|
|
419
495
|
return web.memo(() => !!props.selectionVisible)() && props.selectionBounds;
|
|
420
496
|
},
|
|
421
497
|
get children() {
|
|
422
|
-
return web.createComponent(
|
|
498
|
+
return web.createComponent(SelectionBox, {
|
|
423
499
|
variant: "selection",
|
|
424
500
|
get bounds() {
|
|
425
501
|
return props.selectionBounds;
|
|
426
502
|
},
|
|
427
503
|
get visible() {
|
|
428
504
|
return props.selectionVisible;
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
}), web.createComponent(solidJs.Show, {
|
|
509
|
+
get when() {
|
|
510
|
+
return web.memo(() => !!(props.crosshairVisible === true && props.mouseX !== void 0))() && props.mouseY !== void 0;
|
|
511
|
+
},
|
|
512
|
+
get children() {
|
|
513
|
+
return web.createComponent(Crosshair, {
|
|
514
|
+
get mouseX() {
|
|
515
|
+
return props.mouseX;
|
|
429
516
|
},
|
|
430
|
-
|
|
517
|
+
get mouseY() {
|
|
518
|
+
return props.mouseY;
|
|
519
|
+
},
|
|
520
|
+
visible: true
|
|
431
521
|
});
|
|
432
522
|
}
|
|
433
523
|
}), web.createComponent(solidJs.Show, {
|
|
434
524
|
get when() {
|
|
435
|
-
return web.memo(() => !!props.
|
|
525
|
+
return web.memo(() => !!props.dragVisible)() && props.dragBounds;
|
|
436
526
|
},
|
|
437
527
|
get children() {
|
|
438
|
-
return web.createComponent(
|
|
439
|
-
variant: "
|
|
528
|
+
return web.createComponent(SelectionBox, {
|
|
529
|
+
variant: "drag",
|
|
440
530
|
get bounds() {
|
|
441
|
-
return props.
|
|
531
|
+
return props.dragBounds;
|
|
442
532
|
},
|
|
443
533
|
get visible() {
|
|
444
|
-
return props.
|
|
445
|
-
}
|
|
446
|
-
lerpFactor: MARQUEE_LERP_FACTOR
|
|
534
|
+
return props.dragVisible;
|
|
535
|
+
}
|
|
447
536
|
});
|
|
448
537
|
}
|
|
449
538
|
}), web.createComponent(solidJs.For, {
|
|
450
539
|
get each() {
|
|
451
|
-
return props.
|
|
540
|
+
return props.grabbedBoxes ?? [];
|
|
452
541
|
},
|
|
453
|
-
children: (
|
|
542
|
+
children: (box) => web.createComponent(SelectionBox, {
|
|
454
543
|
variant: "grabbed",
|
|
455
544
|
get bounds() {
|
|
456
|
-
return
|
|
457
|
-
}
|
|
458
|
-
visible: true
|
|
545
|
+
return box.bounds;
|
|
546
|
+
}
|
|
459
547
|
})
|
|
460
548
|
}), web.createComponent(solidJs.For, {
|
|
461
549
|
get each() {
|
|
@@ -471,9 +559,7 @@ var ReactGrabOverlay = (props) => {
|
|
|
471
559
|
},
|
|
472
560
|
get y() {
|
|
473
561
|
return label.y;
|
|
474
|
-
}
|
|
475
|
-
visible: true,
|
|
476
|
-
zIndex: 2147483648
|
|
562
|
+
}
|
|
477
563
|
})
|
|
478
564
|
}), web.createComponent(solidJs.Show, {
|
|
479
565
|
get when() {
|
|
@@ -528,15 +614,6 @@ bippy.instrument({
|
|
|
528
614
|
bippy._fiberRoots.add(fiberRoot);
|
|
529
615
|
}
|
|
530
616
|
});
|
|
531
|
-
var isValidSource = (source) => {
|
|
532
|
-
const fileName = source.fileName;
|
|
533
|
-
if (fileName.includes("node_modules")) return false;
|
|
534
|
-
if (fileName.includes("/dist/")) return false;
|
|
535
|
-
if (fileName.includes("/.next/")) return false;
|
|
536
|
-
if (fileName.includes("/build/")) return false;
|
|
537
|
-
if (fileName.includes("webpack-internal:")) return false;
|
|
538
|
-
return true;
|
|
539
|
-
};
|
|
540
617
|
var getSourceTrace = async (element) => {
|
|
541
618
|
const fiber = bippy.getFiberFromHostInstance(element);
|
|
542
619
|
if (!fiber) return null;
|
|
@@ -546,7 +623,7 @@ var getSourceTrace = async (element) => {
|
|
|
546
623
|
Number.MAX_SAFE_INTEGER
|
|
547
624
|
);
|
|
548
625
|
if (!sources) return null;
|
|
549
|
-
return sources
|
|
626
|
+
return sources;
|
|
550
627
|
};
|
|
551
628
|
var getHTMLSnippet = (element) => {
|
|
552
629
|
const semanticTags = /* @__PURE__ */ new Set([
|
|
@@ -821,7 +898,105 @@ var copyContentFallback = (content) => {
|
|
|
821
898
|
}
|
|
822
899
|
};
|
|
823
900
|
|
|
901
|
+
// src/utils/is-element-visible.ts
|
|
902
|
+
var isElementVisible = (element, computedStyle = window.getComputedStyle(element)) => {
|
|
903
|
+
return computedStyle.display !== "none" && computedStyle.visibility !== "hidden" && computedStyle.opacity !== "0";
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
// src/utils/is-valid-grabbable-element.ts
|
|
907
|
+
var isValidGrabbableElement = (element) => {
|
|
908
|
+
if (element.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
909
|
+
return false;
|
|
910
|
+
}
|
|
911
|
+
const computedStyle = window.getComputedStyle(element);
|
|
912
|
+
if (!isElementVisible(element, computedStyle)) {
|
|
913
|
+
return false;
|
|
914
|
+
}
|
|
915
|
+
if (computedStyle.pointerEvents === "none") {
|
|
916
|
+
return false;
|
|
917
|
+
}
|
|
918
|
+
return true;
|
|
919
|
+
};
|
|
920
|
+
|
|
921
|
+
// src/utils/get-element-at-position.ts
|
|
922
|
+
var getElementAtPosition = (clientX, clientY) => {
|
|
923
|
+
const elementsAtPoint = document.elementsFromPoint(clientX, clientY);
|
|
924
|
+
for (const candidateElement of elementsAtPoint) {
|
|
925
|
+
if (isValidGrabbableElement(candidateElement)) {
|
|
926
|
+
return candidateElement;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
return null;
|
|
930
|
+
};
|
|
931
|
+
|
|
932
|
+
// src/utils/get-elements-in-drag.ts
|
|
933
|
+
var DRAG_COVERAGE_THRESHOLD = 0.75;
|
|
934
|
+
var filterElementsInDrag = (dragRect, isValidGrabbableElement2, shouldCheckCoverage) => {
|
|
935
|
+
const elements = [];
|
|
936
|
+
const allElements = Array.from(document.querySelectorAll("*"));
|
|
937
|
+
const dragLeft = dragRect.x;
|
|
938
|
+
const dragTop = dragRect.y;
|
|
939
|
+
const dragRight = dragRect.x + dragRect.width;
|
|
940
|
+
const dragBottom = dragRect.y + dragRect.height;
|
|
941
|
+
for (const candidateElement of allElements) {
|
|
942
|
+
if (!shouldCheckCoverage) {
|
|
943
|
+
const tagName = (candidateElement.tagName || "").toUpperCase();
|
|
944
|
+
if (tagName === "HTML" || tagName === "BODY") continue;
|
|
945
|
+
}
|
|
946
|
+
if (!isValidGrabbableElement2(candidateElement)) {
|
|
947
|
+
continue;
|
|
948
|
+
}
|
|
949
|
+
const elementRect = candidateElement.getBoundingClientRect();
|
|
950
|
+
const elementLeft = elementRect.left;
|
|
951
|
+
const elementTop = elementRect.top;
|
|
952
|
+
const elementRight = elementRect.left + elementRect.width;
|
|
953
|
+
const elementBottom = elementRect.top + elementRect.height;
|
|
954
|
+
if (shouldCheckCoverage) {
|
|
955
|
+
const intersectionLeft = Math.max(dragLeft, elementLeft);
|
|
956
|
+
const intersectionTop = Math.max(dragTop, elementTop);
|
|
957
|
+
const intersectionRight = Math.min(dragRight, elementRight);
|
|
958
|
+
const intersectionBottom = Math.min(dragBottom, elementBottom);
|
|
959
|
+
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
960
|
+
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
961
|
+
const intersectionArea = intersectionWidth * intersectionHeight;
|
|
962
|
+
const elementArea = Math.max(0, elementRect.width * elementRect.height);
|
|
963
|
+
const hasMajorityCoverage = elementArea > 0 && intersectionArea / elementArea >= DRAG_COVERAGE_THRESHOLD;
|
|
964
|
+
if (hasMajorityCoverage) {
|
|
965
|
+
elements.push(candidateElement);
|
|
966
|
+
}
|
|
967
|
+
} else {
|
|
968
|
+
const hasIntersection = elementLeft < dragRight && elementRight > dragLeft && elementTop < dragBottom && elementBottom > dragTop;
|
|
969
|
+
if (hasIntersection) {
|
|
970
|
+
elements.push(candidateElement);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return elements;
|
|
975
|
+
};
|
|
976
|
+
var getElementsInDrag = (dragRect, isValidGrabbableElement2) => {
|
|
977
|
+
return filterElementsInDrag(dragRect, isValidGrabbableElement2, true);
|
|
978
|
+
};
|
|
979
|
+
var getElementsInDragLoose = (dragRect, isValidGrabbableElement2) => {
|
|
980
|
+
return filterElementsInDrag(dragRect, isValidGrabbableElement2, false);
|
|
981
|
+
};
|
|
982
|
+
|
|
983
|
+
// src/utils/create-element-bounds.ts
|
|
984
|
+
var createElementBounds = (element) => {
|
|
985
|
+
const boundingRect = element.getBoundingClientRect();
|
|
986
|
+
const computedStyle = window.getComputedStyle(element);
|
|
987
|
+
return {
|
|
988
|
+
borderRadius: computedStyle.borderRadius || "0px",
|
|
989
|
+
height: boundingRect.height,
|
|
990
|
+
transform: computedStyle.transform || "none",
|
|
991
|
+
width: boundingRect.width,
|
|
992
|
+
x: boundingRect.left,
|
|
993
|
+
y: boundingRect.top
|
|
994
|
+
};
|
|
995
|
+
};
|
|
996
|
+
|
|
824
997
|
// src/core.tsx
|
|
998
|
+
var SUCCESS_LABEL_DURATION_MS = 1700;
|
|
999
|
+
var PROGRESS_INDICATOR_DELAY_MS = 150;
|
|
825
1000
|
var init = (rawOptions) => {
|
|
826
1001
|
const options = {
|
|
827
1002
|
enabled: true,
|
|
@@ -832,215 +1007,111 @@ var init = (rawOptions) => {
|
|
|
832
1007
|
return;
|
|
833
1008
|
}
|
|
834
1009
|
return solidJs.createRoot((dispose) => {
|
|
1010
|
+
const OFFSCREEN_POSITION = -1e3;
|
|
835
1011
|
const [isHoldingKeys, setIsHoldingKeys] = solidJs.createSignal(false);
|
|
836
|
-
const [mouseX, setMouseX] = solidJs.createSignal(
|
|
837
|
-
const [mouseY, setMouseY] = solidJs.createSignal(
|
|
1012
|
+
const [mouseX, setMouseX] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
1013
|
+
const [mouseY, setMouseY] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
838
1014
|
const [isDragging, setIsDragging] = solidJs.createSignal(false);
|
|
839
|
-
const [dragStartX, setDragStartX] = solidJs.createSignal(
|
|
840
|
-
const [dragStartY, setDragStartY] = solidJs.createSignal(
|
|
1015
|
+
const [dragStartX, setDragStartX] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
1016
|
+
const [dragStartY, setDragStartY] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
841
1017
|
const [isCopying, setIsCopying] = solidJs.createSignal(false);
|
|
842
1018
|
const [lastGrabbedElement, setLastGrabbedElement] = solidJs.createSignal(null);
|
|
843
1019
|
const [progressStartTime, setProgressStartTime] = solidJs.createSignal(null);
|
|
844
1020
|
const [progressTick, setProgressTick] = solidJs.createSignal(0);
|
|
845
|
-
const [
|
|
1021
|
+
const [grabbedBoxes, setGrabbedBoxes] = solidJs.createSignal([]);
|
|
846
1022
|
const [successLabels, setSuccessLabels] = solidJs.createSignal([]);
|
|
847
1023
|
const [isActivated, setIsActivated] = solidJs.createSignal(false);
|
|
848
1024
|
const [showProgressIndicator, setShowProgressIndicator] = solidJs.createSignal(false);
|
|
1025
|
+
const [grabMouseX, setGrabMouseX] = solidJs.createSignal(null);
|
|
1026
|
+
const [grabMouseY, setGrabMouseY] = solidJs.createSignal(null);
|
|
849
1027
|
let holdTimerId = null;
|
|
850
1028
|
let progressAnimationId = null;
|
|
851
1029
|
let progressDelayTimerId = null;
|
|
852
|
-
const
|
|
1030
|
+
const isRendererActive = solidJs.createMemo(() => isActivated() && !isCopying());
|
|
1031
|
+
const hasValidMousePosition = solidJs.createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
|
|
853
1032
|
const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "c";
|
|
854
|
-
const
|
|
855
|
-
const
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
continue;
|
|
859
|
-
}
|
|
860
|
-
const computedStyle = window.getComputedStyle(candidateElement);
|
|
861
|
-
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
862
|
-
continue;
|
|
863
|
-
}
|
|
864
|
-
if (computedStyle.pointerEvents === "none") {
|
|
865
|
-
continue;
|
|
866
|
-
}
|
|
867
|
-
return candidateElement;
|
|
868
|
-
}
|
|
869
|
-
return null;
|
|
870
|
-
};
|
|
871
|
-
const getElementsInMarquee = (marqueeRect) => {
|
|
872
|
-
const elements = [];
|
|
873
|
-
const allElements = Array.from(document.querySelectorAll("*"));
|
|
874
|
-
const marqueeLeft = marqueeRect.x;
|
|
875
|
-
const marqueeTop = marqueeRect.y;
|
|
876
|
-
const marqueeRight = marqueeRect.x + marqueeRect.width;
|
|
877
|
-
const marqueeBottom = marqueeRect.y + marqueeRect.height;
|
|
878
|
-
for (const candidateElement of allElements) {
|
|
879
|
-
if (candidateElement.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
880
|
-
continue;
|
|
881
|
-
}
|
|
882
|
-
const computedStyle = window.getComputedStyle(candidateElement);
|
|
883
|
-
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
884
|
-
continue;
|
|
885
|
-
}
|
|
886
|
-
if (computedStyle.pointerEvents === "none") {
|
|
887
|
-
continue;
|
|
888
|
-
}
|
|
889
|
-
const rect = candidateElement.getBoundingClientRect();
|
|
890
|
-
const elementLeft = rect.left;
|
|
891
|
-
const elementTop = rect.top;
|
|
892
|
-
const elementRight = rect.left + rect.width;
|
|
893
|
-
const elementBottom = rect.top + rect.height;
|
|
894
|
-
const intersectionLeft = Math.max(marqueeLeft, elementLeft);
|
|
895
|
-
const intersectionTop = Math.max(marqueeTop, elementTop);
|
|
896
|
-
const intersectionRight = Math.min(marqueeRight, elementRight);
|
|
897
|
-
const intersectionBottom = Math.min(marqueeBottom, elementBottom);
|
|
898
|
-
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
899
|
-
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
900
|
-
const intersectionArea = intersectionWidth * intersectionHeight;
|
|
901
|
-
const elementArea = Math.max(0, rect.width * rect.height);
|
|
902
|
-
const COVERAGE_THRESHOLD = 0.75;
|
|
903
|
-
const hasMajorityCoverage = elementArea > 0 && intersectionArea / elementArea >= COVERAGE_THRESHOLD;
|
|
904
|
-
if (hasMajorityCoverage) {
|
|
905
|
-
elements.push(candidateElement);
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
return elements;
|
|
909
|
-
};
|
|
910
|
-
const getElementsInMarqueeLoose = (marqueeRect) => {
|
|
911
|
-
const elements = [];
|
|
912
|
-
const allElements = Array.from(document.querySelectorAll("*"));
|
|
913
|
-
const marqueeLeft = marqueeRect.x;
|
|
914
|
-
const marqueeTop = marqueeRect.y;
|
|
915
|
-
const marqueeRight = marqueeRect.x + marqueeRect.width;
|
|
916
|
-
const marqueeBottom = marqueeRect.y + marqueeRect.height;
|
|
917
|
-
for (const candidateElement of allElements) {
|
|
918
|
-
if (candidateElement.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
919
|
-
continue;
|
|
920
|
-
}
|
|
921
|
-
const tag = (candidateElement.tagName || "").toUpperCase();
|
|
922
|
-
if (tag === "HTML" || tag === "BODY") continue;
|
|
923
|
-
const computedStyle = window.getComputedStyle(candidateElement);
|
|
924
|
-
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
925
|
-
continue;
|
|
926
|
-
}
|
|
927
|
-
if (computedStyle.pointerEvents === "none") {
|
|
928
|
-
continue;
|
|
929
|
-
}
|
|
930
|
-
const rect = candidateElement.getBoundingClientRect();
|
|
931
|
-
const elementLeft = rect.left;
|
|
932
|
-
const elementTop = rect.top;
|
|
933
|
-
const elementRight = rect.left + rect.width;
|
|
934
|
-
const elementBottom = rect.top + rect.height;
|
|
935
|
-
const intersects = elementLeft < marqueeRight && elementRight > marqueeLeft && elementTop < marqueeBottom && elementBottom > marqueeTop;
|
|
936
|
-
if (intersects) {
|
|
937
|
-
elements.push(candidateElement);
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
return elements;
|
|
941
|
-
};
|
|
942
|
-
const wrapInReferencedElement = (content) => `
|
|
943
|
-
|
|
944
|
-
<referenced_element>
|
|
945
|
-
${content}
|
|
946
|
-
</referenced_element>`;
|
|
947
|
-
const wrapInReferencedElements = (content) => `
|
|
948
|
-
|
|
949
|
-
<referenced_elements>
|
|
950
|
-
${content}
|
|
951
|
-
</referenced_elements>`;
|
|
952
|
-
const addGrabbedOverlay = (bounds) => {
|
|
953
|
-
const id = `grabbed-${Date.now()}-${Math.random()}`;
|
|
954
|
-
setGrabbedOverlays((prev) => [...prev, {
|
|
955
|
-
id,
|
|
1033
|
+
const addGrabbedBox = (bounds) => {
|
|
1034
|
+
const boxId = `grabbed-${Date.now()}-${Math.random()}`;
|
|
1035
|
+
const newBox = {
|
|
1036
|
+
id: boxId,
|
|
956
1037
|
bounds
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
}, 300);
|
|
1038
|
+
};
|
|
1039
|
+
const currentBoxes = grabbedBoxes();
|
|
1040
|
+
setGrabbedBoxes([...currentBoxes, newBox]);
|
|
961
1041
|
};
|
|
962
|
-
const addSuccessLabel = (text,
|
|
963
|
-
const
|
|
964
|
-
setSuccessLabels((
|
|
965
|
-
id,
|
|
1042
|
+
const addSuccessLabel = (text, positionX, positionY) => {
|
|
1043
|
+
const labelId = `success-${Date.now()}-${Math.random()}`;
|
|
1044
|
+
setSuccessLabels((previousLabels) => [...previousLabels, {
|
|
1045
|
+
id: labelId,
|
|
966
1046
|
text,
|
|
967
|
-
x,
|
|
968
|
-
y
|
|
1047
|
+
x: positionX,
|
|
1048
|
+
y: positionY
|
|
969
1049
|
}]);
|
|
970
1050
|
setTimeout(() => {
|
|
971
|
-
setSuccessLabels((
|
|
972
|
-
},
|
|
1051
|
+
setSuccessLabels((previousLabels) => previousLabels.filter((label) => label.id !== labelId));
|
|
1052
|
+
}, SUCCESS_LABEL_DURATION_MS);
|
|
1053
|
+
};
|
|
1054
|
+
const formatStackTrace = (stackTrace) => {
|
|
1055
|
+
return stackTrace.map((source) => {
|
|
1056
|
+
const functionName = source.functionName ?? "anonymous";
|
|
1057
|
+
const fileName = source.fileName ?? "unknown";
|
|
1058
|
+
const lineNumber = source.lineNumber ?? 0;
|
|
1059
|
+
const columnNumber = source.columnNumber ?? 0;
|
|
1060
|
+
return ` ${functionName} - ${fileName}:${lineNumber}:${columnNumber}`;
|
|
1061
|
+
}).join("\n");
|
|
1062
|
+
};
|
|
1063
|
+
const getElementContentWithTrace = async (element) => {
|
|
1064
|
+
const elementHtml = getHTMLSnippet(element);
|
|
1065
|
+
const componentStackTrace = await getSourceTrace(element);
|
|
1066
|
+
if (componentStackTrace?.length) {
|
|
1067
|
+
const formattedStackTrace = formatStackTrace(componentStackTrace);
|
|
1068
|
+
return `${elementHtml}
|
|
1069
|
+
|
|
1070
|
+
Component owner stack:
|
|
1071
|
+
${formattedStackTrace}`;
|
|
1072
|
+
}
|
|
1073
|
+
return elementHtml;
|
|
973
1074
|
};
|
|
1075
|
+
const getElementTagName = (element) => (element.tagName || "").toLowerCase();
|
|
974
1076
|
const handleCopy = async (targetElement2) => {
|
|
975
1077
|
const elementBounds = targetElement2.getBoundingClientRect();
|
|
976
|
-
const tagName = (targetElement2
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
transform: window.getComputedStyle(targetElement2).transform || "none",
|
|
981
|
-
width: elementBounds.width,
|
|
982
|
-
x: elementBounds.left,
|
|
983
|
-
y: elementBounds.top
|
|
984
|
-
});
|
|
1078
|
+
const tagName = getElementTagName(targetElement2);
|
|
1079
|
+
setGrabMouseX(mouseX());
|
|
1080
|
+
setGrabMouseY(mouseY());
|
|
1081
|
+
addGrabbedBox(createElementBounds(targetElement2));
|
|
985
1082
|
try {
|
|
986
|
-
const
|
|
987
|
-
await copyContent(
|
|
988
|
-
const componentStackTrace = await getSourceTrace(targetElement2);
|
|
989
|
-
if (componentStackTrace?.length) {
|
|
990
|
-
const formattedStackTrace = componentStackTrace.map((source) => ` ${source.functionName} - ${source.fileName}:${source.lineNumber}:${source.columnNumber}`).join("\n");
|
|
991
|
-
await copyContent(wrapInReferencedElement(`${elementHtml}
|
|
992
|
-
|
|
993
|
-
Component owner stack:
|
|
994
|
-
${formattedStackTrace}`));
|
|
995
|
-
}
|
|
1083
|
+
const content = await getElementContentWithTrace(targetElement2);
|
|
1084
|
+
await copyContent(content);
|
|
996
1085
|
} catch {
|
|
997
1086
|
}
|
|
998
1087
|
addSuccessLabel(tagName ? `<${tagName}>` : "<element>", elementBounds.left, elementBounds.top);
|
|
999
1088
|
};
|
|
1000
1089
|
const handleMultipleCopy = async (targetElements) => {
|
|
1001
1090
|
if (targetElements.length === 0) return;
|
|
1002
|
-
let
|
|
1003
|
-
let
|
|
1091
|
+
let minPositionX = Infinity;
|
|
1092
|
+
let minPositionY = Infinity;
|
|
1093
|
+
setGrabMouseX(mouseX());
|
|
1094
|
+
setGrabMouseY(mouseY());
|
|
1004
1095
|
for (const element of targetElements) {
|
|
1005
1096
|
const elementBounds = element.getBoundingClientRect();
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
borderRadius: window.getComputedStyle(element).borderRadius || "0px",
|
|
1010
|
-
height: elementBounds.height,
|
|
1011
|
-
transform: window.getComputedStyle(element).transform || "none",
|
|
1012
|
-
width: elementBounds.width,
|
|
1013
|
-
x: elementBounds.left,
|
|
1014
|
-
y: elementBounds.top
|
|
1015
|
-
});
|
|
1097
|
+
minPositionX = Math.min(minPositionX, elementBounds.left);
|
|
1098
|
+
minPositionY = Math.min(minPositionY, elementBounds.top);
|
|
1099
|
+
addGrabbedBox(createElementBounds(element));
|
|
1016
1100
|
}
|
|
1017
1101
|
try {
|
|
1018
|
-
const elementSnippets =
|
|
1019
|
-
for (const element of targetElements) {
|
|
1020
|
-
const elementHtml = getHTMLSnippet(element);
|
|
1021
|
-
const componentStackTrace = await getSourceTrace(element);
|
|
1022
|
-
if (componentStackTrace?.length) {
|
|
1023
|
-
const formattedStackTrace = componentStackTrace.map((source) => ` ${source.functionName} - ${source.fileName}:${source.lineNumber}:${source.columnNumber}`).join("\n");
|
|
1024
|
-
elementSnippets.push(`${elementHtml}
|
|
1025
|
-
|
|
1026
|
-
Component owner stack:
|
|
1027
|
-
${formattedStackTrace}`);
|
|
1028
|
-
} else {
|
|
1029
|
-
elementSnippets.push(elementHtml);
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1102
|
+
const elementSnippets = await Promise.all(targetElements.map((element) => getElementContentWithTrace(element)));
|
|
1032
1103
|
const combinedContent = elementSnippets.join("\n\n---\n\n");
|
|
1033
|
-
await copyContent(
|
|
1104
|
+
await copyContent(combinedContent);
|
|
1034
1105
|
} catch {
|
|
1035
1106
|
}
|
|
1036
|
-
addSuccessLabel(`${targetElements.length} elements`,
|
|
1107
|
+
addSuccessLabel(`${targetElements.length} elements`, minPositionX, minPositionY);
|
|
1037
1108
|
};
|
|
1038
1109
|
const targetElement = solidJs.createMemo(() => {
|
|
1039
|
-
if (!
|
|
1110
|
+
if (!isRendererActive() || isDragging()) return null;
|
|
1040
1111
|
return getElementAtPosition(mouseX(), mouseY());
|
|
1041
1112
|
});
|
|
1042
1113
|
const selectionBounds = solidJs.createMemo(() => {
|
|
1043
|
-
const element = targetElement()
|
|
1114
|
+
const element = targetElement();
|
|
1044
1115
|
if (!element) return void 0;
|
|
1045
1116
|
const elementBounds = element.getBoundingClientRect();
|
|
1046
1117
|
const computedStyle = window.getComputedStyle(element);
|
|
@@ -1053,54 +1124,80 @@ ${formattedStackTrace}`);
|
|
|
1053
1124
|
y: elementBounds.top
|
|
1054
1125
|
};
|
|
1055
1126
|
});
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1127
|
+
const DRAG_THRESHOLD_PX = 5;
|
|
1128
|
+
const getDragDistance = (endX, endY) => ({
|
|
1129
|
+
x: Math.abs(endX - dragStartX()),
|
|
1130
|
+
y: Math.abs(endY - dragStartY())
|
|
1131
|
+
});
|
|
1132
|
+
const isDraggingBeyondThreshold = solidJs.createMemo(() => {
|
|
1133
|
+
if (!isDragging()) return false;
|
|
1134
|
+
const dragDistance = getDragDistance(mouseX(), mouseY());
|
|
1135
|
+
return dragDistance.x > DRAG_THRESHOLD_PX || dragDistance.y > DRAG_THRESHOLD_PX;
|
|
1136
|
+
});
|
|
1137
|
+
const getDragRect = (endX, endY) => {
|
|
1138
|
+
const dragX = Math.min(dragStartX(), endX);
|
|
1139
|
+
const dragY = Math.min(dragStartY(), endY);
|
|
1140
|
+
const dragWidth = Math.abs(endX - dragStartX());
|
|
1141
|
+
const dragHeight = Math.abs(endY - dragStartY());
|
|
1142
|
+
return {
|
|
1143
|
+
x: dragX,
|
|
1144
|
+
y: dragY,
|
|
1145
|
+
width: dragWidth,
|
|
1146
|
+
height: dragHeight
|
|
1147
|
+
};
|
|
1148
|
+
};
|
|
1149
|
+
const dragBounds = solidJs.createMemo(() => {
|
|
1150
|
+
if (!isDraggingBeyondThreshold()) return void 0;
|
|
1151
|
+
const drag = getDragRect(mouseX(), mouseY());
|
|
1062
1152
|
return {
|
|
1063
1153
|
borderRadius: "0px",
|
|
1064
|
-
height:
|
|
1154
|
+
height: drag.height,
|
|
1065
1155
|
transform: "none",
|
|
1066
|
-
width:
|
|
1067
|
-
x:
|
|
1068
|
-
y:
|
|
1156
|
+
width: drag.width,
|
|
1157
|
+
x: drag.x,
|
|
1158
|
+
y: drag.y
|
|
1069
1159
|
};
|
|
1070
1160
|
});
|
|
1071
1161
|
const labelText = solidJs.createMemo(() => {
|
|
1072
1162
|
const element = targetElement();
|
|
1073
1163
|
if (!element) return "";
|
|
1074
|
-
const tagName = (element
|
|
1164
|
+
const tagName = getElementTagName(element);
|
|
1075
1165
|
return tagName ? `<${tagName}>` : "<element>";
|
|
1076
1166
|
});
|
|
1077
1167
|
const labelPosition = solidJs.createMemo(() => {
|
|
1078
|
-
const element = targetElement() ?? lastGrabbedElement();
|
|
1079
|
-
if (element) {
|
|
1080
|
-
const rect = element.getBoundingClientRect();
|
|
1081
|
-
return {
|
|
1082
|
-
x: rect.left,
|
|
1083
|
-
y: rect.top
|
|
1084
|
-
};
|
|
1085
|
-
}
|
|
1086
1168
|
return {
|
|
1087
1169
|
x: mouseX(),
|
|
1088
1170
|
y: mouseY()
|
|
1089
1171
|
};
|
|
1090
1172
|
});
|
|
1091
|
-
solidJs.
|
|
1092
|
-
const
|
|
1093
|
-
const
|
|
1094
|
-
|
|
1173
|
+
const isSameAsLast = solidJs.createMemo(() => {
|
|
1174
|
+
const currentElement = targetElement();
|
|
1175
|
+
const lastElement = lastGrabbedElement();
|
|
1176
|
+
return !!currentElement && currentElement === lastElement;
|
|
1177
|
+
});
|
|
1178
|
+
solidJs.createEffect(solidJs.on(() => [targetElement(), lastGrabbedElement()], ([currentElement, lastElement]) => {
|
|
1179
|
+
if (lastElement && currentElement && lastElement !== currentElement) {
|
|
1095
1180
|
setLastGrabbedElement(null);
|
|
1096
1181
|
}
|
|
1097
|
-
});
|
|
1182
|
+
}));
|
|
1183
|
+
solidJs.createEffect(solidJs.on(() => [mouseX(), mouseY(), grabMouseX(), grabMouseY()], ([currentMouseX, currentMouseY, initialGrabMouseX, initialGrabMouseY]) => {
|
|
1184
|
+
if (initialGrabMouseX === null || initialGrabMouseY === null) return;
|
|
1185
|
+
if (grabbedBoxes().length === 0) return;
|
|
1186
|
+
const MOUSE_MOVE_THRESHOLD_PX = 5;
|
|
1187
|
+
const distanceX = Math.abs(currentMouseX - initialGrabMouseX);
|
|
1188
|
+
const distanceY = Math.abs(currentMouseY - initialGrabMouseY);
|
|
1189
|
+
if (distanceX > MOUSE_MOVE_THRESHOLD_PX || distanceY > MOUSE_MOVE_THRESHOLD_PX) {
|
|
1190
|
+
setGrabbedBoxes([]);
|
|
1191
|
+
setGrabMouseX(null);
|
|
1192
|
+
setGrabMouseY(null);
|
|
1193
|
+
}
|
|
1194
|
+
}));
|
|
1098
1195
|
const progress = solidJs.createMemo(() => {
|
|
1099
1196
|
const startTime = progressStartTime();
|
|
1100
1197
|
progressTick();
|
|
1101
1198
|
if (startTime === null) return 0;
|
|
1102
|
-
const
|
|
1103
|
-
return Math.min(
|
|
1199
|
+
const elapsedTime = Date.now() - startTime;
|
|
1200
|
+
return Math.min(elapsedTime / options.keyHoldDuration, 1);
|
|
1104
1201
|
});
|
|
1105
1202
|
const startProgressAnimation = () => {
|
|
1106
1203
|
setProgressStartTime(Date.now());
|
|
@@ -1108,10 +1205,10 @@ ${formattedStackTrace}`);
|
|
|
1108
1205
|
progressDelayTimerId = window.setTimeout(() => {
|
|
1109
1206
|
setShowProgressIndicator(true);
|
|
1110
1207
|
progressDelayTimerId = null;
|
|
1111
|
-
},
|
|
1208
|
+
}, PROGRESS_INDICATOR_DELAY_MS);
|
|
1112
1209
|
const animateProgress = () => {
|
|
1113
1210
|
if (progressStartTime() === null) return;
|
|
1114
|
-
setProgressTick((
|
|
1211
|
+
setProgressTick((tick) => tick + 1);
|
|
1115
1212
|
const currentProgress = progress();
|
|
1116
1213
|
if (currentProgress < 1) {
|
|
1117
1214
|
progressAnimationId = requestAnimationFrame(animateProgress);
|
|
@@ -1131,16 +1228,22 @@ ${formattedStackTrace}`);
|
|
|
1131
1228
|
setProgressStartTime(null);
|
|
1132
1229
|
setShowProgressIndicator(false);
|
|
1133
1230
|
};
|
|
1134
|
-
const
|
|
1231
|
+
const activateRenderer = () => {
|
|
1135
1232
|
stopProgressAnimation();
|
|
1136
1233
|
setIsActivated(true);
|
|
1234
|
+
document.body.style.cursor = "crosshair";
|
|
1137
1235
|
};
|
|
1138
1236
|
const abortController = new AbortController();
|
|
1139
|
-
const
|
|
1237
|
+
const eventListenerSignal = abortController.signal;
|
|
1140
1238
|
window.addEventListener("keydown", (event) => {
|
|
1141
1239
|
if (event.key === "Escape" && isHoldingKeys()) {
|
|
1142
1240
|
setIsHoldingKeys(false);
|
|
1143
1241
|
setIsActivated(false);
|
|
1242
|
+
document.body.style.cursor = "";
|
|
1243
|
+
if (isDragging()) {
|
|
1244
|
+
setIsDragging(false);
|
|
1245
|
+
document.body.style.userSelect = "";
|
|
1246
|
+
}
|
|
1144
1247
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1145
1248
|
stopProgressAnimation();
|
|
1146
1249
|
return;
|
|
@@ -1150,67 +1253,56 @@ ${formattedStackTrace}`);
|
|
|
1150
1253
|
setIsHoldingKeys(true);
|
|
1151
1254
|
startProgressAnimation();
|
|
1152
1255
|
holdTimerId = window.setTimeout(() => {
|
|
1153
|
-
|
|
1256
|
+
activateRenderer();
|
|
1154
1257
|
options.onActivate?.();
|
|
1155
1258
|
}, options.keyHoldDuration);
|
|
1156
1259
|
}
|
|
1157
1260
|
}, {
|
|
1158
|
-
signal
|
|
1261
|
+
signal: eventListenerSignal
|
|
1159
1262
|
});
|
|
1160
1263
|
window.addEventListener("keyup", (event) => {
|
|
1161
1264
|
if (isHoldingKeys() && (!isTargetKeyCombination(event) || event.key.toLowerCase() === "c")) {
|
|
1162
1265
|
setIsHoldingKeys(false);
|
|
1163
1266
|
setIsActivated(false);
|
|
1267
|
+
document.body.style.cursor = "";
|
|
1164
1268
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1165
1269
|
stopProgressAnimation();
|
|
1166
1270
|
}
|
|
1167
1271
|
}, {
|
|
1168
|
-
signal
|
|
1272
|
+
signal: eventListenerSignal
|
|
1169
1273
|
});
|
|
1170
1274
|
window.addEventListener("mousemove", (event) => {
|
|
1171
1275
|
setMouseX(event.clientX);
|
|
1172
1276
|
setMouseY(event.clientY);
|
|
1173
1277
|
}, {
|
|
1174
|
-
signal
|
|
1278
|
+
signal: eventListenerSignal
|
|
1175
1279
|
});
|
|
1176
1280
|
window.addEventListener("mousedown", (event) => {
|
|
1177
|
-
if (!
|
|
1281
|
+
if (!isRendererActive() || isCopying()) return;
|
|
1282
|
+
event.preventDefault();
|
|
1178
1283
|
setIsDragging(true);
|
|
1179
1284
|
setDragStartX(event.clientX);
|
|
1180
1285
|
setDragStartY(event.clientY);
|
|
1286
|
+
document.body.style.userSelect = "none";
|
|
1181
1287
|
}, {
|
|
1182
|
-
signal
|
|
1288
|
+
signal: eventListenerSignal
|
|
1183
1289
|
});
|
|
1184
1290
|
window.addEventListener("mouseup", (event) => {
|
|
1185
1291
|
if (!isDragging()) return;
|
|
1186
|
-
const
|
|
1187
|
-
const
|
|
1188
|
-
const DRAG_THRESHOLD = 5;
|
|
1189
|
-
const wasDrag = dragDistanceX > DRAG_THRESHOLD || dragDistanceY > DRAG_THRESHOLD;
|
|
1292
|
+
const dragDistance = getDragDistance(event.clientX, event.clientY);
|
|
1293
|
+
const wasDragGesture = dragDistance.x > DRAG_THRESHOLD_PX || dragDistance.y > DRAG_THRESHOLD_PX;
|
|
1190
1294
|
setIsDragging(false);
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
const
|
|
1194
|
-
const
|
|
1195
|
-
const marqueeHeight = Math.abs(event.clientY - dragStartY());
|
|
1196
|
-
const elements = getElementsInMarquee({
|
|
1197
|
-
x: marqueeX,
|
|
1198
|
-
y: marqueeY,
|
|
1199
|
-
width: marqueeWidth,
|
|
1200
|
-
height: marqueeHeight
|
|
1201
|
-
});
|
|
1295
|
+
document.body.style.userSelect = "";
|
|
1296
|
+
if (wasDragGesture) {
|
|
1297
|
+
const dragRect = getDragRect(event.clientX, event.clientY);
|
|
1298
|
+
const elements = getElementsInDrag(dragRect, isValidGrabbableElement);
|
|
1202
1299
|
if (elements.length > 0) {
|
|
1203
1300
|
setIsCopying(true);
|
|
1204
1301
|
void handleMultipleCopy(elements).finally(() => {
|
|
1205
1302
|
setIsCopying(false);
|
|
1206
1303
|
});
|
|
1207
1304
|
} else {
|
|
1208
|
-
const fallbackElements =
|
|
1209
|
-
x: marqueeX,
|
|
1210
|
-
y: marqueeY,
|
|
1211
|
-
width: marqueeWidth,
|
|
1212
|
-
height: marqueeHeight
|
|
1213
|
-
});
|
|
1305
|
+
const fallbackElements = getElementsInDragLoose(dragRect, isValidGrabbableElement);
|
|
1214
1306
|
if (fallbackElements.length > 0) {
|
|
1215
1307
|
setIsCopying(true);
|
|
1216
1308
|
void handleMultipleCopy(fallbackElements).finally(() => {
|
|
@@ -1228,51 +1320,84 @@ ${formattedStackTrace}`);
|
|
|
1228
1320
|
});
|
|
1229
1321
|
}
|
|
1230
1322
|
}, {
|
|
1231
|
-
signal
|
|
1232
|
-
});
|
|
1233
|
-
window.addEventListener("scroll", () => {
|
|
1234
|
-
}, {
|
|
1235
|
-
signal,
|
|
1236
|
-
capture: true
|
|
1237
|
-
});
|
|
1238
|
-
window.addEventListener("resize", () => {
|
|
1239
|
-
}, {
|
|
1240
|
-
signal
|
|
1323
|
+
signal: eventListenerSignal
|
|
1241
1324
|
});
|
|
1242
1325
|
document.addEventListener("visibilitychange", () => {
|
|
1243
1326
|
if (document.hidden) {
|
|
1244
|
-
|
|
1327
|
+
setGrabbedBoxes([]);
|
|
1245
1328
|
}
|
|
1246
1329
|
}, {
|
|
1247
|
-
signal
|
|
1330
|
+
signal: eventListenerSignal
|
|
1248
1331
|
});
|
|
1249
1332
|
solidJs.onCleanup(() => {
|
|
1250
1333
|
abortController.abort();
|
|
1251
1334
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1252
1335
|
stopProgressAnimation();
|
|
1336
|
+
document.body.style.userSelect = "";
|
|
1337
|
+
document.body.style.cursor = "";
|
|
1253
1338
|
});
|
|
1254
|
-
const
|
|
1255
|
-
const
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1339
|
+
const rendererRoot = mountRoot();
|
|
1340
|
+
const selectionVisible = solidJs.createMemo(() => false);
|
|
1341
|
+
const dragVisible = solidJs.createMemo(() => isRendererActive() && isDraggingBeyondThreshold());
|
|
1342
|
+
const labelVariant = solidJs.createMemo(() => isCopying() ? "processing" : "hover");
|
|
1343
|
+
const labelVisible = solidJs.createMemo(() => isRendererActive() && !isDragging() && !!targetElement() && !isSameAsLast() || isCopying());
|
|
1344
|
+
const progressVisible = solidJs.createMemo(() => isHoldingKeys() && showProgressIndicator() && hasValidMousePosition());
|
|
1345
|
+
const crosshairVisible = solidJs.createMemo(() => isRendererActive() && !isDragging());
|
|
1346
|
+
web.render(() => web.createComponent(ReactGrabRenderer, {
|
|
1347
|
+
get selectionVisible() {
|
|
1348
|
+
return selectionVisible();
|
|
1349
|
+
},
|
|
1350
|
+
get selectionBounds() {
|
|
1351
|
+
return selectionBounds();
|
|
1352
|
+
},
|
|
1353
|
+
get dragVisible() {
|
|
1354
|
+
return dragVisible();
|
|
1355
|
+
},
|
|
1356
|
+
get dragBounds() {
|
|
1357
|
+
return dragBounds();
|
|
1358
|
+
},
|
|
1359
|
+
get grabbedBoxes() {
|
|
1360
|
+
return grabbedBoxes();
|
|
1361
|
+
},
|
|
1362
|
+
get successLabels() {
|
|
1363
|
+
return successLabels();
|
|
1364
|
+
},
|
|
1365
|
+
get labelVariant() {
|
|
1366
|
+
return labelVariant();
|
|
1367
|
+
},
|
|
1368
|
+
get labelText() {
|
|
1369
|
+
return labelText();
|
|
1370
|
+
},
|
|
1371
|
+
get labelX() {
|
|
1372
|
+
return labelPosition().x;
|
|
1373
|
+
},
|
|
1374
|
+
get labelY() {
|
|
1375
|
+
return labelPosition().y;
|
|
1376
|
+
},
|
|
1377
|
+
get labelVisible() {
|
|
1378
|
+
return labelVisible();
|
|
1379
|
+
},
|
|
1380
|
+
get progressVisible() {
|
|
1381
|
+
return progressVisible();
|
|
1382
|
+
},
|
|
1383
|
+
get progress() {
|
|
1384
|
+
return progress();
|
|
1385
|
+
},
|
|
1386
|
+
get mouseX() {
|
|
1387
|
+
return mouseX();
|
|
1388
|
+
},
|
|
1389
|
+
get mouseY() {
|
|
1390
|
+
return mouseY();
|
|
1391
|
+
},
|
|
1392
|
+
get crosshairVisible() {
|
|
1393
|
+
return crosshairVisible();
|
|
1394
|
+
}
|
|
1395
|
+
}), rendererRoot);
|
|
1273
1396
|
return dispose;
|
|
1274
1397
|
});
|
|
1275
1398
|
};
|
|
1276
1399
|
|
|
1277
1400
|
// src/index.ts
|
|
1278
1401
|
init();
|
|
1402
|
+
|
|
1403
|
+
exports.init = init;
|