@gfazioli/mantine-window 0.5.5 → 0.5.6

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.
@@ -104,6 +104,23 @@ function useMantineWindow(props) {
104
104
  },
105
105
  [position, bringToFront]
106
106
  );
107
+ const handleTouchStartDrag = useCallback(
108
+ (e) => {
109
+ if (e.target.closest("[data-resize-handle]")) {
110
+ return;
111
+ }
112
+ const touch = e.touches[0];
113
+ bringToFront();
114
+ isDragging.current = true;
115
+ dragStart.current = {
116
+ x: touch.clientX - position.x,
117
+ y: touch.clientY - position.y
118
+ };
119
+ document.body.style.userSelect = "none";
120
+ e.preventDefault();
121
+ },
122
+ [position, bringToFront]
123
+ );
107
124
  const resizeDirection = useRef("");
108
125
  const handleMouseDownResizeTopLeft = useCallback(
109
126
  (e) => {
@@ -125,6 +142,25 @@ function useMantineWindow(props) {
125
142
  },
126
143
  [size, position, bringToFront]
127
144
  );
145
+ const handleTouchStartResizeTopLeft = useCallback(
146
+ (e) => {
147
+ const touch = e.touches[0];
148
+ bringToFront();
149
+ isResizing.current = true;
150
+ resizeDirection.current = "topLeft";
151
+ resizeStart.current = {
152
+ x: touch.clientX,
153
+ y: touch.clientY,
154
+ width: size.width,
155
+ height: size.height,
156
+ posX: position.x,
157
+ posY: position.y
158
+ };
159
+ document.body.style.userSelect = "none";
160
+ e.stopPropagation();
161
+ },
162
+ [size, position, bringToFront]
163
+ );
128
164
  const handleMouseDownResizeTop = useCallback(
129
165
  (e) => {
130
166
  bringToFront();
@@ -145,6 +181,25 @@ function useMantineWindow(props) {
145
181
  },
146
182
  [size, position, bringToFront]
147
183
  );
184
+ const handleTouchStartResizeTop = useCallback(
185
+ (e) => {
186
+ const touch = e.touches[0];
187
+ bringToFront();
188
+ isResizing.current = true;
189
+ resizeDirection.current = "top";
190
+ resizeStart.current = {
191
+ x: touch.clientX,
192
+ y: touch.clientY,
193
+ width: size.width,
194
+ height: size.height,
195
+ posX: position.x,
196
+ posY: position.y
197
+ };
198
+ document.body.style.userSelect = "none";
199
+ e.stopPropagation();
200
+ },
201
+ [size, position, bringToFront]
202
+ );
148
203
  const handleMouseDownResizeTopRight = useCallback(
149
204
  (e) => {
150
205
  bringToFront();
@@ -165,6 +220,25 @@ function useMantineWindow(props) {
165
220
  },
166
221
  [size, position, bringToFront]
167
222
  );
223
+ const handleTouchStartResizeTopRight = useCallback(
224
+ (e) => {
225
+ const touch = e.touches[0];
226
+ bringToFront();
227
+ isResizing.current = true;
228
+ resizeDirection.current = "topRight";
229
+ resizeStart.current = {
230
+ x: touch.clientX,
231
+ y: touch.clientY,
232
+ width: size.width,
233
+ height: size.height,
234
+ posX: position.x,
235
+ posY: position.y
236
+ };
237
+ document.body.style.userSelect = "none";
238
+ e.stopPropagation();
239
+ },
240
+ [size, position, bringToFront]
241
+ );
168
242
  const handleMouseDownResizeRight = useCallback(
169
243
  (e) => {
170
244
  bringToFront();
@@ -185,6 +259,25 @@ function useMantineWindow(props) {
185
259
  },
186
260
  [size, position, bringToFront]
187
261
  );
262
+ const handleTouchStartResizeRight = useCallback(
263
+ (e) => {
264
+ const touch = e.touches[0];
265
+ bringToFront();
266
+ isResizing.current = true;
267
+ resizeDirection.current = "right";
268
+ resizeStart.current = {
269
+ x: touch.clientX,
270
+ y: touch.clientY,
271
+ width: size.width,
272
+ height: size.height,
273
+ posX: position.x,
274
+ posY: position.y
275
+ };
276
+ document.body.style.userSelect = "none";
277
+ e.stopPropagation();
278
+ },
279
+ [size, position, bringToFront]
280
+ );
188
281
  const handleMouseDownResizeBottomRight = useCallback(
189
282
  (e) => {
190
283
  bringToFront();
@@ -205,6 +298,25 @@ function useMantineWindow(props) {
205
298
  },
206
299
  [size, position, bringToFront]
207
300
  );
301
+ const handleTouchStartResizeBottomRight = useCallback(
302
+ (e) => {
303
+ const touch = e.touches[0];
304
+ bringToFront();
305
+ isResizing.current = true;
306
+ resizeDirection.current = "bottomRight";
307
+ resizeStart.current = {
308
+ x: touch.clientX,
309
+ y: touch.clientY,
310
+ width: size.width,
311
+ height: size.height,
312
+ posX: position.x,
313
+ posY: position.y
314
+ };
315
+ document.body.style.userSelect = "none";
316
+ e.stopPropagation();
317
+ },
318
+ [size, position, bringToFront]
319
+ );
208
320
  const handleMouseDownResizeBottom = useCallback(
209
321
  (e) => {
210
322
  bringToFront();
@@ -225,6 +337,25 @@ function useMantineWindow(props) {
225
337
  },
226
338
  [size, position, bringToFront]
227
339
  );
340
+ const handleTouchStartResizeBottom = useCallback(
341
+ (e) => {
342
+ const touch = e.touches[0];
343
+ bringToFront();
344
+ isResizing.current = true;
345
+ resizeDirection.current = "bottom";
346
+ resizeStart.current = {
347
+ x: touch.clientX,
348
+ y: touch.clientY,
349
+ width: size.width,
350
+ height: size.height,
351
+ posX: position.x,
352
+ posY: position.y
353
+ };
354
+ document.body.style.userSelect = "none";
355
+ e.stopPropagation();
356
+ },
357
+ [size, position, bringToFront]
358
+ );
228
359
  const handleMouseDownResizeBottomLeft = useCallback(
229
360
  (e) => {
230
361
  bringToFront();
@@ -245,6 +376,25 @@ function useMantineWindow(props) {
245
376
  },
246
377
  [size, position, bringToFront]
247
378
  );
379
+ const handleTouchStartResizeBottomLeft = useCallback(
380
+ (e) => {
381
+ const touch = e.touches[0];
382
+ bringToFront();
383
+ isResizing.current = true;
384
+ resizeDirection.current = "bottomLeft";
385
+ resizeStart.current = {
386
+ x: touch.clientX,
387
+ y: touch.clientY,
388
+ width: size.width,
389
+ height: size.height,
390
+ posX: position.x,
391
+ posY: position.y
392
+ };
393
+ document.body.style.userSelect = "none";
394
+ e.stopPropagation();
395
+ },
396
+ [size, position, bringToFront]
397
+ );
248
398
  const handleMouseDownResizeLeft = useCallback(
249
399
  (e) => {
250
400
  bringToFront();
@@ -265,105 +415,162 @@ function useMantineWindow(props) {
265
415
  },
266
416
  [size, position, bringToFront]
267
417
  );
418
+ const handleTouchStartResizeLeft = useCallback(
419
+ (e) => {
420
+ const touch = e.touches[0];
421
+ bringToFront();
422
+ isResizing.current = true;
423
+ resizeDirection.current = "left";
424
+ resizeStart.current = {
425
+ x: touch.clientX,
426
+ y: touch.clientY,
427
+ width: size.width,
428
+ height: size.height,
429
+ posX: position.x,
430
+ posY: position.y
431
+ };
432
+ document.body.style.userSelect = "none";
433
+ e.stopPropagation();
434
+ },
435
+ [size, position, bringToFront]
436
+ );
268
437
  const handleClose = useCallback(() => {
269
438
  if (onClose) {
270
439
  return onClose();
271
440
  }
272
441
  setIsVisible(false);
273
442
  }, [onClose]);
443
+ const clampWidth = useCallback(
444
+ (w) => {
445
+ let clamped = Math.max(minWidth, w);
446
+ if (maxWidth !== void 0) {
447
+ clamped = Math.min(maxWidth, clamped);
448
+ }
449
+ return clamped;
450
+ },
451
+ [minWidth, maxWidth]
452
+ );
453
+ const clampHeight = useCallback(
454
+ (h) => {
455
+ let clamped = Math.max(minHeight, h);
456
+ if (maxHeight !== void 0) {
457
+ clamped = Math.min(maxHeight, clamped);
458
+ }
459
+ return clamped;
460
+ },
461
+ [minHeight, maxHeight]
462
+ );
463
+ const applyDragBounds = useCallback(
464
+ (newX, newY) => {
465
+ let boundedX = newX;
466
+ let boundedY = newY;
467
+ if (dragBounds) {
468
+ if (dragBounds.minX !== void 0) {
469
+ boundedX = Math.max(dragBounds.minX, boundedX);
470
+ }
471
+ if (dragBounds.maxX !== void 0) {
472
+ boundedX = Math.min(dragBounds.maxX, boundedX);
473
+ }
474
+ if (dragBounds.minY !== void 0) {
475
+ boundedY = Math.max(dragBounds.minY, boundedY);
476
+ }
477
+ if (dragBounds.maxY !== void 0) {
478
+ boundedY = Math.min(dragBounds.maxY, boundedY);
479
+ }
480
+ } else if (withinPortal) {
481
+ boundedX = Math.max(0, Math.min(boundedX, window.innerWidth - size.width));
482
+ boundedY = Math.max(0, Math.min(boundedY, window.innerHeight - 50));
483
+ } else {
484
+ const parent = windowRef.current?.offsetParent;
485
+ if (parent instanceof HTMLElement) {
486
+ const parentWidth = parent.clientWidth;
487
+ const parentHeight = parent.clientHeight;
488
+ boundedX = Math.max(0, Math.min(boundedX, parentWidth - size.width));
489
+ boundedY = Math.max(0, Math.min(boundedY, parentHeight - 50));
490
+ }
491
+ }
492
+ return { x: boundedX, y: boundedY };
493
+ },
494
+ [dragBounds, withinPortal, size.width]
495
+ );
496
+ const handleResize = useCallback(
497
+ (clientX, clientY) => {
498
+ const deltaX = clientX - resizeStart.current.x;
499
+ const deltaY = clientY - resizeStart.current.y;
500
+ let newWidth = size.width;
501
+ let newHeight = size.height;
502
+ let newX = resizeStart.current.posX;
503
+ let newY = resizeStart.current.posY;
504
+ switch (resizeDirection.current) {
505
+ case "topLeft":
506
+ newWidth = clampWidth(resizeStart.current.width - deltaX);
507
+ newHeight = clampHeight(resizeStart.current.height - deltaY);
508
+ newX = resizeStart.current.posX + (resizeStart.current.width - newWidth);
509
+ newY = resizeStart.current.posY + (resizeStart.current.height - newHeight);
510
+ break;
511
+ case "top":
512
+ newHeight = clampHeight(resizeStart.current.height - deltaY);
513
+ newY = resizeStart.current.posY + (resizeStart.current.height - newHeight);
514
+ break;
515
+ case "topRight":
516
+ newWidth = clampWidth(resizeStart.current.width + deltaX);
517
+ newHeight = clampHeight(resizeStart.current.height - deltaY);
518
+ newY = resizeStart.current.posY + (resizeStart.current.height - newHeight);
519
+ break;
520
+ case "right":
521
+ newWidth = clampWidth(resizeStart.current.width + deltaX);
522
+ break;
523
+ case "bottomRight":
524
+ newWidth = clampWidth(resizeStart.current.width + deltaX);
525
+ newHeight = clampHeight(resizeStart.current.height + deltaY);
526
+ break;
527
+ case "bottom":
528
+ newHeight = clampHeight(resizeStart.current.height + deltaY);
529
+ break;
530
+ case "bottomLeft":
531
+ newWidth = clampWidth(resizeStart.current.width - deltaX);
532
+ newHeight = clampHeight(resizeStart.current.height + deltaY);
533
+ newX = resizeStart.current.posX + (resizeStart.current.width - newWidth);
534
+ break;
535
+ case "left":
536
+ newWidth = clampWidth(resizeStart.current.width - deltaX);
537
+ newX = resizeStart.current.posX + (resizeStart.current.width - newWidth);
538
+ break;
539
+ }
540
+ setSize({ width: newWidth, height: newHeight });
541
+ if (newX !== resizeStart.current.posX || newY !== resizeStart.current.posY) {
542
+ setPosition({ x: newX, y: newY });
543
+ }
544
+ },
545
+ [size.width, size.height, clampWidth, clampHeight, setSize, setPosition]
546
+ );
274
547
  useEffect(() => {
275
548
  const handleMouseMove = (e) => {
276
549
  if (isDragging.current) {
277
- let newX = e.clientX - dragStart.current.x;
278
- let newY = e.clientY - dragStart.current.y;
279
- if (dragBounds) {
280
- if (dragBounds.minX !== void 0) {
281
- newX = Math.max(dragBounds.minX, newX);
282
- }
283
- if (dragBounds.maxX !== void 0) {
284
- newX = Math.min(dragBounds.maxX, newX);
285
- }
286
- if (dragBounds.minY !== void 0) {
287
- newY = Math.max(dragBounds.minY, newY);
288
- }
289
- if (dragBounds.maxY !== void 0) {
290
- newY = Math.min(dragBounds.maxY, newY);
291
- }
292
- } else if (withinPortal) {
293
- newX = Math.max(0, Math.min(newX, window.innerWidth - size.width));
294
- newY = Math.max(0, Math.min(newY, window.innerHeight - 50));
295
- } else {
296
- const parent = windowRef.current?.offsetParent;
297
- if (parent instanceof HTMLElement) {
298
- const parentWidth = parent.clientWidth;
299
- const parentHeight = parent.clientHeight;
300
- newX = Math.max(0, Math.min(newX, parentWidth - size.width));
301
- newY = Math.max(0, Math.min(newY, parentHeight - 50));
302
- }
303
- }
304
- setPosition({ x: newX, y: newY });
550
+ const newPos = applyDragBounds(
551
+ e.clientX - dragStart.current.x,
552
+ e.clientY - dragStart.current.y
553
+ );
554
+ setPosition(newPos);
305
555
  }
306
556
  if (isResizing.current) {
307
- const deltaX = e.clientX - resizeStart.current.x;
308
- const deltaY = e.clientY - resizeStart.current.y;
309
- let newWidth = size.width;
310
- let newHeight = size.height;
311
- let newX = resizeStart.current.posX;
312
- let newY = resizeStart.current.posY;
313
- const clampWidth = (w) => {
314
- let clamped = Math.max(minWidth, w);
315
- if (maxWidth !== void 0) {
316
- clamped = Math.min(maxWidth, clamped);
317
- }
318
- return clamped;
319
- };
320
- const clampHeight = (h) => {
321
- let clamped = Math.max(minHeight, h);
322
- if (maxHeight !== void 0) {
323
- clamped = Math.min(maxHeight, clamped);
324
- }
325
- return clamped;
326
- };
327
- switch (resizeDirection.current) {
328
- case "topLeft":
329
- newWidth = clampWidth(resizeStart.current.width - deltaX);
330
- newHeight = clampHeight(resizeStart.current.height - deltaY);
331
- newX = resizeStart.current.posX + (resizeStart.current.width - newWidth);
332
- newY = resizeStart.current.posY + (resizeStart.current.height - newHeight);
333
- break;
334
- case "top":
335
- newHeight = clampHeight(resizeStart.current.height - deltaY);
336
- newY = resizeStart.current.posY + (resizeStart.current.height - newHeight);
337
- break;
338
- case "topRight":
339
- newWidth = clampWidth(resizeStart.current.width + deltaX);
340
- newHeight = clampHeight(resizeStart.current.height - deltaY);
341
- newY = resizeStart.current.posY + (resizeStart.current.height - newHeight);
342
- break;
343
- case "right":
344
- newWidth = clampWidth(resizeStart.current.width + deltaX);
345
- break;
346
- case "bottomRight":
347
- newWidth = clampWidth(resizeStart.current.width + deltaX);
348
- newHeight = clampHeight(resizeStart.current.height + deltaY);
349
- break;
350
- case "bottom":
351
- newHeight = clampHeight(resizeStart.current.height + deltaY);
352
- break;
353
- case "bottomLeft":
354
- newWidth = clampWidth(resizeStart.current.width - deltaX);
355
- newHeight = clampHeight(resizeStart.current.height + deltaY);
356
- newX = resizeStart.current.posX + (resizeStart.current.width - newWidth);
357
- break;
358
- case "left":
359
- newWidth = clampWidth(resizeStart.current.width - deltaX);
360
- newX = resizeStart.current.posX + (resizeStart.current.width - newWidth);
361
- break;
557
+ handleResize(e.clientX, e.clientY);
558
+ }
559
+ };
560
+ const handleTouchMove = (e) => {
561
+ if (isDragging.current || isResizing.current) {
562
+ const touch = e.touches[0];
563
+ if (isDragging.current) {
564
+ const newPos = applyDragBounds(
565
+ touch.clientX - dragStart.current.x,
566
+ touch.clientY - dragStart.current.y
567
+ );
568
+ setPosition(newPos);
362
569
  }
363
- setSize({ width: newWidth, height: newHeight });
364
- if (newX !== resizeStart.current.posX || newY !== resizeStart.current.posY) {
365
- setPosition({ x: newX, y: newY });
570
+ if (isResizing.current) {
571
+ handleResize(touch.clientX, touch.clientY);
366
572
  }
573
+ e.preventDefault();
367
574
  }
368
575
  };
369
576
  const handleMouseUp = () => {
@@ -374,27 +581,29 @@ function useMantineWindow(props) {
374
581
  document.body.style.cursor = "";
375
582
  }
376
583
  };
584
+ const handleTouchEnd = () => {
585
+ if (isDragging.current || isResizing.current) {
586
+ isDragging.current = false;
587
+ isResizing.current = false;
588
+ document.body.style.userSelect = "";
589
+ document.body.style.cursor = "";
590
+ }
591
+ };
377
592
  document.addEventListener("mousemove", handleMouseMove);
378
593
  document.addEventListener("mouseup", handleMouseUp);
594
+ document.addEventListener("touchmove", handleTouchMove, { passive: false });
595
+ document.addEventListener("touchend", handleTouchEnd);
596
+ document.addEventListener("touchcancel", handleTouchEnd);
379
597
  return () => {
380
598
  document.removeEventListener("mousemove", handleMouseMove);
381
599
  document.removeEventListener("mouseup", handleMouseUp);
600
+ document.removeEventListener("touchmove", handleTouchMove);
601
+ document.removeEventListener("touchend", handleTouchEnd);
602
+ document.removeEventListener("touchcancel", handleTouchEnd);
382
603
  document.body.style.userSelect = "";
604
+ document.body.style.cursor = "";
383
605
  };
384
- }, [
385
- size.width,
386
- size.height,
387
- position.x,
388
- position.y,
389
- dragBounds,
390
- minWidth,
391
- minHeight,
392
- maxWidth,
393
- maxHeight,
394
- withinPortal,
395
- setPosition,
396
- setSize
397
- ]);
606
+ }, [applyDragBounds, handleResize, setPosition]);
398
607
  return {
399
608
  isCollapsed,
400
609
  setIsCollapsed,
@@ -405,14 +614,23 @@ function useMantineWindow(props) {
405
614
  size,
406
615
  windowRef,
407
616
  handleMouseDownDrag,
617
+ handleTouchStartDrag,
408
618
  handleMouseDownResizeTopLeft,
619
+ handleTouchStartResizeTopLeft,
409
620
  handleMouseDownResizeTop,
621
+ handleTouchStartResizeTop,
410
622
  handleMouseDownResizeTopRight,
623
+ handleTouchStartResizeTopRight,
411
624
  handleMouseDownResizeRight,
625
+ handleTouchStartResizeRight,
412
626
  handleMouseDownResizeBottomRight,
627
+ handleTouchStartResizeBottomRight,
413
628
  handleMouseDownResizeBottom,
629
+ handleTouchStartResizeBottom,
414
630
  handleMouseDownResizeBottomLeft,
631
+ handleTouchStartResizeBottomLeft,
415
632
  handleMouseDownResizeLeft,
633
+ handleTouchStartResizeLeft,
416
634
  handleClose,
417
635
  bringToFront
418
636
  };