diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2025-06-24 14:34:49 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2025-06-24 14:34:49 +0700 |
| commit | 918ece5f2c351895c83653fb71d3065e2d2992a0 (patch) | |
| tree | 8a29e7da6449d3efe98be3f2ce9ace2c8e5a399b /src | |
| parent | 57fa96f28d768a0c0a4940330f76cd3badf819f0 (diff) | |
<hafid> dragable banner
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/home/components/PopupBannerPromotion.jsx | 108 |
1 files changed, 76 insertions, 32 deletions
diff --git a/src/lib/home/components/PopupBannerPromotion.jsx b/src/lib/home/components/PopupBannerPromotion.jsx index c5466009..347617d6 100644 --- a/src/lib/home/components/PopupBannerPromotion.jsx +++ b/src/lib/home/components/PopupBannerPromotion.jsx @@ -18,6 +18,9 @@ const PagePopupInformation = () => { const [position, setPosition] = useState({ x: 20, y: window.innerHeight - 170 }); const dragStartPos = useRef({ x: 0, y: 0 }); const isDragging = useRef(false); + const isTouching = useRef(false); + + const [isSnapping, setIsSnapping] = useState(false); // 🔥 Penanda kapan transisi diaktifkan useEffect(() => { const getData = async () => { @@ -41,10 +44,62 @@ const PagePopupInformation = () => { } }, [isHomePage, auth]); + useEffect(() => { + const handleGlobalTouchMove = (e) => { + if (isTouching.current) { + e.preventDefault(); + isDragging.current = true; + setIsSnapping(false); // 🔥 Matikan transisi saat drag + + let newX = e.touches[0].clientX - dragStartPos.current.x; + let newY = e.touches[0].clientY - dragStartPos.current.y; + + const popupWidth = popupRef.current?.offsetWidth || 0; + const popupHeight = popupRef.current?.offsetHeight || 0; + const maxX = window.innerWidth - popupWidth - 20; + const maxY = window.innerHeight - popupHeight - 20; + + newX = Math.max(0, Math.min(newX, maxX)); + newY = Math.max(0, Math.min(newY, maxY)); + + setPosition({ x: newX, y: newY }); + } + }; + + const handleGlobalTouchEnd = () => { + if (isDragging.current) { + const popupWidth = popupRef.current?.offsetWidth || 0; + const screenMiddle = window.innerWidth / 2; + + setIsSnapping(true); // 🔥 Aktifkan transisi saat snap + + if (position.x + popupWidth / 2 < screenMiddle) { + // Snap ke kiri + setPosition({ x: 20, y: position.y }); + } else { + // Snap ke kanan + setPosition({ x: window.innerWidth - popupWidth - 20, y: position.y }); + } + } + + isTouching.current = false; + isDragging.current = false; + }; + + window.addEventListener('touchmove', handleGlobalTouchMove, { passive: false }); + window.addEventListener('touchend', handleGlobalTouchEnd); + + return () => { + window.removeEventListener('touchmove', handleGlobalTouchMove); + window.removeEventListener('touchend', handleGlobalTouchEnd); + }; + }, [position]); + const handleMouseDown = (e) => { e.preventDefault(); dragStartPos.current = { x: e.clientX - position.x, y: e.clientY - position.y }; isDragging.current = false; + setIsSnapping(false); // 🔥 Matikan transisi saat drag window.addEventListener('mousemove', handleMouseMove); window.addEventListener('mouseup', handleMouseUp); @@ -68,47 +123,36 @@ const PagePopupInformation = () => { }; const handleMouseUp = () => { + if (isDragging.current) { + const popupWidth = popupRef.current?.offsetWidth || 0; + const screenMiddle = window.innerWidth / 2; + + setIsSnapping(true); // 🔥 Aktifkan transisi saat snap + + if (position.x + popupWidth / 2 < screenMiddle) { + // Snap ke kiri + setPosition({ x: 20, y: position.y }); + } else { + // Snap ke kanan + setPosition({ x: window.innerWidth - popupWidth - 20, y: position.y }); + } + } + window.removeEventListener('mousemove', handleMouseMove); window.removeEventListener('mouseup', handleMouseUp); + + isDragging.current = false; }; - // Touch Events (Mobile) const handleTouchStart = (e) => { if (e.touches.length === 1) { - const touch = e.touches[0]; - dragStartPos.current = { x: touch.clientX - position.x, y: touch.clientY - position.y }; + dragStartPos.current = { x: e.touches[0].clientX - position.x, y: e.touches[0].clientY - position.y }; isDragging.current = false; - - window.addEventListener('touchmove', handleTouchMove, { passive: false }); - window.addEventListener('touchend', handleTouchEnd); - } - }; - - const handleTouchMove = (e) => { - if (e.touches.length === 1) { - e.preventDefault(); - isDragging.current = true; - - let newX = e.touches[0].clientX - dragStartPos.current.x; - let newY = e.touches[0].clientY - dragStartPos.current.y; - - const popupWidth = popupRef.current?.offsetWidth || 0; - const popupHeight = popupRef.current?.offsetHeight || 0; - const maxX = window.innerWidth - popupWidth - 20; - const maxY = window.innerHeight - popupHeight - 20; - - newX = Math.max(0, Math.min(newX, maxX)); - newY = Math.max(0, Math.min(newY, maxY)); - - setPosition({ x: newX, y: newY }); + isTouching.current = true; + setIsSnapping(false); // 🔥 Matikan transisi saat drag } }; - const handleTouchEnd = () => { - window.removeEventListener('touchmove', handleTouchMove); - window.removeEventListener('touchend', handleTouchEnd); - }; - if (!active || !data || loading || !Array.isArray(data) || !data[0]?.image) return null; const banner = data[0]; @@ -117,7 +161,7 @@ const PagePopupInformation = () => { <div className="fixed inset-0 z-[9999] pointer-events-none"> <div ref={popupRef} - className="absolute pointer-events-auto" + className={`absolute pointer-events-auto ${isSnapping ? 'transition-transform duration-300 ease-out' : ''}`} style={{ transform: `translate(${position.x}px, ${position.y}px)`, cursor: 'grab', |
