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