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