@gfazioli/mantine-window 0.5.5 → 0.5.7

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