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.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() {
|
|
@@ -812,7 +898,105 @@ var copyContentFallback = (content) => {
|
|
|
812
898
|
}
|
|
813
899
|
};
|
|
814
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
|
+
|
|
815
997
|
// src/core.tsx
|
|
998
|
+
var SUCCESS_LABEL_DURATION_MS = 1700;
|
|
999
|
+
var PROGRESS_INDICATOR_DELAY_MS = 150;
|
|
816
1000
|
var init = (rawOptions) => {
|
|
817
1001
|
const options = {
|
|
818
1002
|
enabled: true,
|
|
@@ -823,209 +1007,112 @@ var init = (rawOptions) => {
|
|
|
823
1007
|
return;
|
|
824
1008
|
}
|
|
825
1009
|
return solidJs.createRoot((dispose) => {
|
|
1010
|
+
const OFFSCREEN_POSITION = -1e3;
|
|
826
1011
|
const [isHoldingKeys, setIsHoldingKeys] = solidJs.createSignal(false);
|
|
827
|
-
const [mouseX, setMouseX] = solidJs.createSignal(
|
|
828
|
-
const [mouseY, setMouseY] = solidJs.createSignal(
|
|
1012
|
+
const [mouseX, setMouseX] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
1013
|
+
const [mouseY, setMouseY] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
829
1014
|
const [isDragging, setIsDragging] = solidJs.createSignal(false);
|
|
830
|
-
const [dragStartX, setDragStartX] = solidJs.createSignal(
|
|
831
|
-
const [dragStartY, setDragStartY] = solidJs.createSignal(
|
|
1015
|
+
const [dragStartX, setDragStartX] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
1016
|
+
const [dragStartY, setDragStartY] = solidJs.createSignal(OFFSCREEN_POSITION);
|
|
832
1017
|
const [isCopying, setIsCopying] = solidJs.createSignal(false);
|
|
833
1018
|
const [lastGrabbedElement, setLastGrabbedElement] = solidJs.createSignal(null);
|
|
834
1019
|
const [progressStartTime, setProgressStartTime] = solidJs.createSignal(null);
|
|
835
1020
|
const [progressTick, setProgressTick] = solidJs.createSignal(0);
|
|
836
|
-
const [
|
|
1021
|
+
const [grabbedBoxes, setGrabbedBoxes] = solidJs.createSignal([]);
|
|
837
1022
|
const [successLabels, setSuccessLabels] = solidJs.createSignal([]);
|
|
838
1023
|
const [isActivated, setIsActivated] = solidJs.createSignal(false);
|
|
839
1024
|
const [showProgressIndicator, setShowProgressIndicator] = solidJs.createSignal(false);
|
|
1025
|
+
const [grabMouseX, setGrabMouseX] = solidJs.createSignal(null);
|
|
1026
|
+
const [grabMouseY, setGrabMouseY] = solidJs.createSignal(null);
|
|
840
1027
|
let holdTimerId = null;
|
|
841
1028
|
let progressAnimationId = null;
|
|
842
1029
|
let progressDelayTimerId = null;
|
|
843
|
-
const
|
|
1030
|
+
const isRendererActive = solidJs.createMemo(() => isActivated() && !isCopying());
|
|
1031
|
+
const hasValidMousePosition = solidJs.createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
|
|
844
1032
|
const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "c";
|
|
845
|
-
const
|
|
846
|
-
const
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
continue;
|
|
850
|
-
}
|
|
851
|
-
const computedStyle = window.getComputedStyle(candidateElement);
|
|
852
|
-
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
853
|
-
continue;
|
|
854
|
-
}
|
|
855
|
-
return candidateElement;
|
|
856
|
-
}
|
|
857
|
-
return null;
|
|
858
|
-
};
|
|
859
|
-
const getElementsInMarquee = (marqueeRect) => {
|
|
860
|
-
const elements = [];
|
|
861
|
-
const allElements = Array.from(document.querySelectorAll("*"));
|
|
862
|
-
const marqueeLeft = marqueeRect.x;
|
|
863
|
-
const marqueeTop = marqueeRect.y;
|
|
864
|
-
const marqueeRight = marqueeRect.x + marqueeRect.width;
|
|
865
|
-
const marqueeBottom = marqueeRect.y + marqueeRect.height;
|
|
866
|
-
for (const candidateElement of allElements) {
|
|
867
|
-
if (candidateElement.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
868
|
-
continue;
|
|
869
|
-
}
|
|
870
|
-
const computedStyle = window.getComputedStyle(candidateElement);
|
|
871
|
-
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
872
|
-
continue;
|
|
873
|
-
}
|
|
874
|
-
const rect = candidateElement.getBoundingClientRect();
|
|
875
|
-
const elementLeft = rect.left;
|
|
876
|
-
const elementTop = rect.top;
|
|
877
|
-
const elementRight = rect.left + rect.width;
|
|
878
|
-
const elementBottom = rect.top + rect.height;
|
|
879
|
-
const intersectionLeft = Math.max(marqueeLeft, elementLeft);
|
|
880
|
-
const intersectionTop = Math.max(marqueeTop, elementTop);
|
|
881
|
-
const intersectionRight = Math.min(marqueeRight, elementRight);
|
|
882
|
-
const intersectionBottom = Math.min(marqueeBottom, elementBottom);
|
|
883
|
-
const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);
|
|
884
|
-
const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);
|
|
885
|
-
const intersectionArea = intersectionWidth * intersectionHeight;
|
|
886
|
-
const elementArea = Math.max(0, rect.width * rect.height);
|
|
887
|
-
const COVERAGE_THRESHOLD = 0.75;
|
|
888
|
-
const hasMajorityCoverage = elementArea > 0 && intersectionArea / elementArea >= COVERAGE_THRESHOLD;
|
|
889
|
-
if (hasMajorityCoverage) {
|
|
890
|
-
elements.push(candidateElement);
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
return elements;
|
|
894
|
-
};
|
|
895
|
-
const getElementsInMarqueeLoose = (marqueeRect) => {
|
|
896
|
-
const elements = [];
|
|
897
|
-
const allElements = Array.from(document.querySelectorAll("*"));
|
|
898
|
-
const marqueeLeft = marqueeRect.x;
|
|
899
|
-
const marqueeTop = marqueeRect.y;
|
|
900
|
-
const marqueeRight = marqueeRect.x + marqueeRect.width;
|
|
901
|
-
const marqueeBottom = marqueeRect.y + marqueeRect.height;
|
|
902
|
-
for (const candidateElement of allElements) {
|
|
903
|
-
if (candidateElement.closest(`[${ATTRIBUTE_NAME}]`)) {
|
|
904
|
-
continue;
|
|
905
|
-
}
|
|
906
|
-
const tag = (candidateElement.tagName || "").toUpperCase();
|
|
907
|
-
if (tag === "HTML" || tag === "BODY") continue;
|
|
908
|
-
const computedStyle = window.getComputedStyle(candidateElement);
|
|
909
|
-
if (!isElementVisible(candidateElement, computedStyle)) {
|
|
910
|
-
continue;
|
|
911
|
-
}
|
|
912
|
-
const rect = candidateElement.getBoundingClientRect();
|
|
913
|
-
const elementLeft = rect.left;
|
|
914
|
-
const elementTop = rect.top;
|
|
915
|
-
const elementRight = rect.left + rect.width;
|
|
916
|
-
const elementBottom = rect.top + rect.height;
|
|
917
|
-
const intersects = elementLeft < marqueeRight && elementRight > marqueeLeft && elementTop < marqueeBottom && elementBottom > marqueeTop;
|
|
918
|
-
if (intersects) {
|
|
919
|
-
elements.push(candidateElement);
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
return elements;
|
|
923
|
-
};
|
|
924
|
-
const wrapInReferencedElement = (content) => `
|
|
925
|
-
|
|
926
|
-
<referenced_element>
|
|
927
|
-
${content}
|
|
928
|
-
</referenced_element>`;
|
|
929
|
-
const wrapInReferencedElements = (content) => `
|
|
930
|
-
|
|
931
|
-
<referenced_elements>
|
|
932
|
-
${content}
|
|
933
|
-
</referenced_elements>`;
|
|
934
|
-
const addGrabbedOverlay = (bounds) => {
|
|
935
|
-
const id = `grabbed-${Date.now()}-${Math.random()}`;
|
|
936
|
-
setGrabbedOverlays((prev) => [...prev, {
|
|
937
|
-
id,
|
|
1033
|
+
const addGrabbedBox = (bounds) => {
|
|
1034
|
+
const boxId = `grabbed-${Date.now()}-${Math.random()}`;
|
|
1035
|
+
const newBox = {
|
|
1036
|
+
id: boxId,
|
|
938
1037
|
bounds
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
}, 300);
|
|
1038
|
+
};
|
|
1039
|
+
const currentBoxes = grabbedBoxes();
|
|
1040
|
+
setGrabbedBoxes([...currentBoxes, newBox]);
|
|
943
1041
|
};
|
|
944
|
-
const addSuccessLabel = (text,
|
|
945
|
-
const
|
|
946
|
-
setSuccessLabels((
|
|
947
|
-
id,
|
|
1042
|
+
const addSuccessLabel = (text, positionX, positionY) => {
|
|
1043
|
+
const labelId = `success-${Date.now()}-${Math.random()}`;
|
|
1044
|
+
setSuccessLabels((previousLabels) => [...previousLabels, {
|
|
1045
|
+
id: labelId,
|
|
948
1046
|
text,
|
|
949
|
-
x,
|
|
950
|
-
y
|
|
1047
|
+
x: positionX,
|
|
1048
|
+
y: positionY
|
|
951
1049
|
}]);
|
|
952
1050
|
setTimeout(() => {
|
|
953
|
-
setSuccessLabels((
|
|
954
|
-
},
|
|
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;
|
|
955
1074
|
};
|
|
1075
|
+
const getElementTagName = (element) => (element.tagName || "").toLowerCase();
|
|
956
1076
|
const handleCopy = async (targetElement2) => {
|
|
957
1077
|
const elementBounds = targetElement2.getBoundingClientRect();
|
|
958
|
-
const tagName = (targetElement2
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
transform: window.getComputedStyle(targetElement2).transform || "none",
|
|
963
|
-
width: elementBounds.width,
|
|
964
|
-
x: elementBounds.left,
|
|
965
|
-
y: elementBounds.top
|
|
966
|
-
});
|
|
1078
|
+
const tagName = getElementTagName(targetElement2);
|
|
1079
|
+
setGrabMouseX(mouseX());
|
|
1080
|
+
setGrabMouseY(mouseY());
|
|
1081
|
+
addGrabbedBox(createElementBounds(targetElement2));
|
|
967
1082
|
try {
|
|
968
|
-
const
|
|
969
|
-
await copyContent(
|
|
970
|
-
const componentStackTrace = await getSourceTrace(targetElement2);
|
|
971
|
-
if (componentStackTrace?.length) {
|
|
972
|
-
const formattedStackTrace = componentStackTrace.map((source) => ` ${source.functionName} - ${source.fileName}:${source.lineNumber}:${source.columnNumber}`).join("\n");
|
|
973
|
-
await copyContent(wrapInReferencedElement(`${elementHtml}
|
|
974
|
-
|
|
975
|
-
Component owner stack:
|
|
976
|
-
${formattedStackTrace}`));
|
|
977
|
-
}
|
|
1083
|
+
const content = await getElementContentWithTrace(targetElement2);
|
|
1084
|
+
await copyContent(content);
|
|
978
1085
|
} catch {
|
|
979
1086
|
}
|
|
980
1087
|
addSuccessLabel(tagName ? `<${tagName}>` : "<element>", elementBounds.left, elementBounds.top);
|
|
981
1088
|
};
|
|
982
1089
|
const handleMultipleCopy = async (targetElements) => {
|
|
983
1090
|
if (targetElements.length === 0) return;
|
|
984
|
-
let
|
|
985
|
-
let
|
|
1091
|
+
let minPositionX = Infinity;
|
|
1092
|
+
let minPositionY = Infinity;
|
|
1093
|
+
setGrabMouseX(mouseX());
|
|
1094
|
+
setGrabMouseY(mouseY());
|
|
986
1095
|
for (const element of targetElements) {
|
|
987
1096
|
const elementBounds = element.getBoundingClientRect();
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
borderRadius: window.getComputedStyle(element).borderRadius || "0px",
|
|
992
|
-
height: elementBounds.height,
|
|
993
|
-
transform: window.getComputedStyle(element).transform || "none",
|
|
994
|
-
width: elementBounds.width,
|
|
995
|
-
x: elementBounds.left,
|
|
996
|
-
y: elementBounds.top
|
|
997
|
-
});
|
|
1097
|
+
minPositionX = Math.min(minPositionX, elementBounds.left);
|
|
1098
|
+
minPositionY = Math.min(minPositionY, elementBounds.top);
|
|
1099
|
+
addGrabbedBox(createElementBounds(element));
|
|
998
1100
|
}
|
|
999
1101
|
try {
|
|
1000
|
-
const elementSnippets =
|
|
1001
|
-
for (const element of targetElements) {
|
|
1002
|
-
const elementHtml = getHTMLSnippet(element);
|
|
1003
|
-
const componentStackTrace = await getSourceTrace(element);
|
|
1004
|
-
if (componentStackTrace?.length) {
|
|
1005
|
-
const formattedStackTrace = componentStackTrace.map((source) => ` ${source.functionName} - ${source.fileName}:${source.lineNumber}:${source.columnNumber}`).join("\n");
|
|
1006
|
-
elementSnippets.push(`${elementHtml}
|
|
1007
|
-
|
|
1008
|
-
Component owner stack:
|
|
1009
|
-
${formattedStackTrace}`);
|
|
1010
|
-
} else {
|
|
1011
|
-
elementSnippets.push(elementHtml);
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1102
|
+
const elementSnippets = await Promise.all(targetElements.map((element) => getElementContentWithTrace(element)));
|
|
1014
1103
|
const combinedContent = elementSnippets.join("\n\n---\n\n");
|
|
1015
|
-
await copyContent(
|
|
1104
|
+
await copyContent(combinedContent);
|
|
1016
1105
|
} catch {
|
|
1017
1106
|
}
|
|
1018
|
-
addSuccessLabel(`${targetElements.length} elements`,
|
|
1107
|
+
addSuccessLabel(`${targetElements.length} elements`, minPositionX, minPositionY);
|
|
1019
1108
|
};
|
|
1020
1109
|
const targetElement = solidJs.createMemo(() => {
|
|
1021
|
-
if (!
|
|
1110
|
+
if (!isRendererActive() || isDragging()) return null;
|
|
1022
1111
|
return getElementAtPosition(mouseX(), mouseY());
|
|
1023
1112
|
});
|
|
1024
1113
|
const selectionBounds = solidJs.createMemo(() => {
|
|
1025
1114
|
const element = targetElement();
|
|
1026
1115
|
if (!element) return void 0;
|
|
1027
|
-
const last = lastGrabbedElement();
|
|
1028
|
-
if (last && element === last) return void 0;
|
|
1029
1116
|
const elementBounds = element.getBoundingClientRect();
|
|
1030
1117
|
const computedStyle = window.getComputedStyle(element);
|
|
1031
1118
|
return {
|
|
@@ -1037,59 +1124,80 @@ ${formattedStackTrace}`);
|
|
|
1037
1124
|
y: elementBounds.top
|
|
1038
1125
|
};
|
|
1039
1126
|
});
|
|
1040
|
-
const
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
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());
|
|
1046
1152
|
return {
|
|
1047
1153
|
borderRadius: "0px",
|
|
1048
|
-
height:
|
|
1154
|
+
height: drag.height,
|
|
1049
1155
|
transform: "none",
|
|
1050
|
-
width:
|
|
1051
|
-
x:
|
|
1052
|
-
y:
|
|
1156
|
+
width: drag.width,
|
|
1157
|
+
x: drag.x,
|
|
1158
|
+
y: drag.y
|
|
1053
1159
|
};
|
|
1054
1160
|
});
|
|
1055
1161
|
const labelText = solidJs.createMemo(() => {
|
|
1056
1162
|
const element = targetElement();
|
|
1057
1163
|
if (!element) return "";
|
|
1058
|
-
const tagName = (element
|
|
1164
|
+
const tagName = getElementTagName(element);
|
|
1059
1165
|
return tagName ? `<${tagName}>` : "<element>";
|
|
1060
1166
|
});
|
|
1061
1167
|
const labelPosition = solidJs.createMemo(() => {
|
|
1062
|
-
const element = targetElement() ?? lastGrabbedElement();
|
|
1063
|
-
if (element) {
|
|
1064
|
-
const rect = element.getBoundingClientRect();
|
|
1065
|
-
return {
|
|
1066
|
-
x: rect.left,
|
|
1067
|
-
y: rect.top
|
|
1068
|
-
};
|
|
1069
|
-
}
|
|
1070
1168
|
return {
|
|
1071
1169
|
x: mouseX(),
|
|
1072
1170
|
y: mouseY()
|
|
1073
1171
|
};
|
|
1074
1172
|
});
|
|
1075
1173
|
const isSameAsLast = solidJs.createMemo(() => {
|
|
1076
|
-
const
|
|
1077
|
-
const
|
|
1078
|
-
return !!
|
|
1174
|
+
const currentElement = targetElement();
|
|
1175
|
+
const lastElement = lastGrabbedElement();
|
|
1176
|
+
return !!currentElement && currentElement === lastElement;
|
|
1079
1177
|
});
|
|
1080
|
-
solidJs.createEffect(() => {
|
|
1081
|
-
|
|
1082
|
-
const last = lastGrabbedElement();
|
|
1083
|
-
if (last && current && last !== current) {
|
|
1178
|
+
solidJs.createEffect(solidJs.on(() => [targetElement(), lastGrabbedElement()], ([currentElement, lastElement]) => {
|
|
1179
|
+
if (lastElement && currentElement && lastElement !== currentElement) {
|
|
1084
1180
|
setLastGrabbedElement(null);
|
|
1085
1181
|
}
|
|
1086
|
-
});
|
|
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
|
+
}));
|
|
1087
1195
|
const progress = solidJs.createMemo(() => {
|
|
1088
1196
|
const startTime = progressStartTime();
|
|
1089
1197
|
progressTick();
|
|
1090
1198
|
if (startTime === null) return 0;
|
|
1091
|
-
const
|
|
1092
|
-
return Math.min(
|
|
1199
|
+
const elapsedTime = Date.now() - startTime;
|
|
1200
|
+
return Math.min(elapsedTime / options.keyHoldDuration, 1);
|
|
1093
1201
|
});
|
|
1094
1202
|
const startProgressAnimation = () => {
|
|
1095
1203
|
setProgressStartTime(Date.now());
|
|
@@ -1097,10 +1205,10 @@ ${formattedStackTrace}`);
|
|
|
1097
1205
|
progressDelayTimerId = window.setTimeout(() => {
|
|
1098
1206
|
setShowProgressIndicator(true);
|
|
1099
1207
|
progressDelayTimerId = null;
|
|
1100
|
-
},
|
|
1208
|
+
}, PROGRESS_INDICATOR_DELAY_MS);
|
|
1101
1209
|
const animateProgress = () => {
|
|
1102
1210
|
if (progressStartTime() === null) return;
|
|
1103
|
-
setProgressTick((
|
|
1211
|
+
setProgressTick((tick) => tick + 1);
|
|
1104
1212
|
const currentProgress = progress();
|
|
1105
1213
|
if (currentProgress < 1) {
|
|
1106
1214
|
progressAnimationId = requestAnimationFrame(animateProgress);
|
|
@@ -1120,16 +1228,22 @@ ${formattedStackTrace}`);
|
|
|
1120
1228
|
setProgressStartTime(null);
|
|
1121
1229
|
setShowProgressIndicator(false);
|
|
1122
1230
|
};
|
|
1123
|
-
const
|
|
1231
|
+
const activateRenderer = () => {
|
|
1124
1232
|
stopProgressAnimation();
|
|
1125
1233
|
setIsActivated(true);
|
|
1234
|
+
document.body.style.cursor = "crosshair";
|
|
1126
1235
|
};
|
|
1127
1236
|
const abortController = new AbortController();
|
|
1128
|
-
const
|
|
1237
|
+
const eventListenerSignal = abortController.signal;
|
|
1129
1238
|
window.addEventListener("keydown", (event) => {
|
|
1130
1239
|
if (event.key === "Escape" && isHoldingKeys()) {
|
|
1131
1240
|
setIsHoldingKeys(false);
|
|
1132
1241
|
setIsActivated(false);
|
|
1242
|
+
document.body.style.cursor = "";
|
|
1243
|
+
if (isDragging()) {
|
|
1244
|
+
setIsDragging(false);
|
|
1245
|
+
document.body.style.userSelect = "";
|
|
1246
|
+
}
|
|
1133
1247
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1134
1248
|
stopProgressAnimation();
|
|
1135
1249
|
return;
|
|
@@ -1139,67 +1253,56 @@ ${formattedStackTrace}`);
|
|
|
1139
1253
|
setIsHoldingKeys(true);
|
|
1140
1254
|
startProgressAnimation();
|
|
1141
1255
|
holdTimerId = window.setTimeout(() => {
|
|
1142
|
-
|
|
1256
|
+
activateRenderer();
|
|
1143
1257
|
options.onActivate?.();
|
|
1144
1258
|
}, options.keyHoldDuration);
|
|
1145
1259
|
}
|
|
1146
1260
|
}, {
|
|
1147
|
-
signal
|
|
1261
|
+
signal: eventListenerSignal
|
|
1148
1262
|
});
|
|
1149
1263
|
window.addEventListener("keyup", (event) => {
|
|
1150
1264
|
if (isHoldingKeys() && (!isTargetKeyCombination(event) || event.key.toLowerCase() === "c")) {
|
|
1151
1265
|
setIsHoldingKeys(false);
|
|
1152
1266
|
setIsActivated(false);
|
|
1267
|
+
document.body.style.cursor = "";
|
|
1153
1268
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1154
1269
|
stopProgressAnimation();
|
|
1155
1270
|
}
|
|
1156
1271
|
}, {
|
|
1157
|
-
signal
|
|
1272
|
+
signal: eventListenerSignal
|
|
1158
1273
|
});
|
|
1159
1274
|
window.addEventListener("mousemove", (event) => {
|
|
1160
1275
|
setMouseX(event.clientX);
|
|
1161
1276
|
setMouseY(event.clientY);
|
|
1162
1277
|
}, {
|
|
1163
|
-
signal
|
|
1278
|
+
signal: eventListenerSignal
|
|
1164
1279
|
});
|
|
1165
1280
|
window.addEventListener("mousedown", (event) => {
|
|
1166
|
-
if (!
|
|
1281
|
+
if (!isRendererActive() || isCopying()) return;
|
|
1282
|
+
event.preventDefault();
|
|
1167
1283
|
setIsDragging(true);
|
|
1168
1284
|
setDragStartX(event.clientX);
|
|
1169
1285
|
setDragStartY(event.clientY);
|
|
1286
|
+
document.body.style.userSelect = "none";
|
|
1170
1287
|
}, {
|
|
1171
|
-
signal
|
|
1288
|
+
signal: eventListenerSignal
|
|
1172
1289
|
});
|
|
1173
1290
|
window.addEventListener("mouseup", (event) => {
|
|
1174
1291
|
if (!isDragging()) return;
|
|
1175
|
-
const
|
|
1176
|
-
const
|
|
1177
|
-
const DRAG_THRESHOLD = 5;
|
|
1178
|
-
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;
|
|
1179
1294
|
setIsDragging(false);
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
const
|
|
1183
|
-
const
|
|
1184
|
-
const marqueeHeight = Math.abs(event.clientY - dragStartY());
|
|
1185
|
-
const elements = getElementsInMarquee({
|
|
1186
|
-
x: marqueeX,
|
|
1187
|
-
y: marqueeY,
|
|
1188
|
-
width: marqueeWidth,
|
|
1189
|
-
height: marqueeHeight
|
|
1190
|
-
});
|
|
1295
|
+
document.body.style.userSelect = "";
|
|
1296
|
+
if (wasDragGesture) {
|
|
1297
|
+
const dragRect = getDragRect(event.clientX, event.clientY);
|
|
1298
|
+
const elements = getElementsInDrag(dragRect, isValidGrabbableElement);
|
|
1191
1299
|
if (elements.length > 0) {
|
|
1192
1300
|
setIsCopying(true);
|
|
1193
1301
|
void handleMultipleCopy(elements).finally(() => {
|
|
1194
1302
|
setIsCopying(false);
|
|
1195
1303
|
});
|
|
1196
1304
|
} else {
|
|
1197
|
-
const fallbackElements =
|
|
1198
|
-
x: marqueeX,
|
|
1199
|
-
y: marqueeY,
|
|
1200
|
-
width: marqueeWidth,
|
|
1201
|
-
height: marqueeHeight
|
|
1202
|
-
});
|
|
1305
|
+
const fallbackElements = getElementsInDragLoose(dragRect, isValidGrabbableElement);
|
|
1203
1306
|
if (fallbackElements.length > 0) {
|
|
1204
1307
|
setIsCopying(true);
|
|
1205
1308
|
void handleMultipleCopy(fallbackElements).finally(() => {
|
|
@@ -1217,51 +1320,84 @@ ${formattedStackTrace}`);
|
|
|
1217
1320
|
});
|
|
1218
1321
|
}
|
|
1219
1322
|
}, {
|
|
1220
|
-
signal
|
|
1221
|
-
});
|
|
1222
|
-
window.addEventListener("scroll", () => {
|
|
1223
|
-
}, {
|
|
1224
|
-
signal,
|
|
1225
|
-
capture: true
|
|
1226
|
-
});
|
|
1227
|
-
window.addEventListener("resize", () => {
|
|
1228
|
-
}, {
|
|
1229
|
-
signal
|
|
1323
|
+
signal: eventListenerSignal
|
|
1230
1324
|
});
|
|
1231
1325
|
document.addEventListener("visibilitychange", () => {
|
|
1232
1326
|
if (document.hidden) {
|
|
1233
|
-
|
|
1327
|
+
setGrabbedBoxes([]);
|
|
1234
1328
|
}
|
|
1235
1329
|
}, {
|
|
1236
|
-
signal
|
|
1330
|
+
signal: eventListenerSignal
|
|
1237
1331
|
});
|
|
1238
1332
|
solidJs.onCleanup(() => {
|
|
1239
1333
|
abortController.abort();
|
|
1240
1334
|
if (holdTimerId) window.clearTimeout(holdTimerId);
|
|
1241
1335
|
stopProgressAnimation();
|
|
1336
|
+
document.body.style.userSelect = "";
|
|
1337
|
+
document.body.style.cursor = "";
|
|
1242
1338
|
});
|
|
1243
|
-
const
|
|
1244
|
-
const
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
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);
|
|
1262
1396
|
return dispose;
|
|
1263
1397
|
});
|
|
1264
1398
|
};
|
|
1265
1399
|
|
|
1266
1400
|
// src/index.ts
|
|
1267
1401
|
init();
|
|
1402
|
+
|
|
1403
|
+
exports.init = init;
|