UNPKG

react-pattern-lock-ts

Version:

PatternLock is a lightweight and customizable React component for implementing a secure and interactive pattern lock system. Perfect for authentication, games, or creative applications, it supports touch and mouse interactions with real-time state updates

76 lines (75 loc) 3.18 kB
'use client'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useEffect } from 'react'; import './style.css'; import { useRef, useState } from 'react'; const PatternLock = ({ className, numberClassName, bgClassName, setPatterns, useNumber = false, resetStyleByChange, }) => { const [resArr, setResArr] = useState([]); const [isDrawing, setIsDrawing] = useState(false); const containerRef = useRef(null); const parentBulletRef = useRef(null); const resetBullets = () => { setResArr([]); }; const getNumberFromPoint = (x, y) => { const element = document.elementFromPoint(x, y); const cls = `.${className ? className : 'bullet-bYMyWeb'}`; const bullet = element?.closest(cls); if (bullet) { const index = Array.from(document.querySelectorAll(cls)).indexOf(bullet); return index; } return null; }; const startPattern = (num) => { if (!isDrawing) { setIsDrawing(true); setResArr([num]); } }; const movePattern = (num) => { if (isDrawing && !resArr.includes(num)) { setResArr((prev) => [...prev, num]); } }; const endPattern = () => { if (isDrawing) { setIsDrawing(false); if (resArr.length > 0) { setPatterns((prev) => [...prev, resArr]); } } }; // Mouse Events const handleMouseDown = (num) => { // setResArr([]); startPattern(num); }; const handleMouseMove = (num) => { if (isDrawing) { movePattern(num); } }; // Touch Events const handleTouchStart = (num) => { // setResArr([]); startPattern(num); }; const handleTouchMove = (e) => { if (!isDrawing) return null; const touch = e.touches[0]; const rect = e.currentTarget.getBoundingClientRect(); const x = touch.clientX - rect.left; const y = touch.clientY - rect.top; const num = getNumberFromPoint(touch.clientX, touch.clientY); if (num !== null) { movePattern(num); } }; useEffect(() => { resetBullets(); }, [resetStyleByChange]); return (_jsx("section", { ref: containerRef, onMouseUp: endPattern, onMouseLeave: endPattern, onTouchEnd: endPattern, onTouchCancel: endPattern, className: 'pattern-content-bYMyWeb', children: _jsxs("div", { ref: parentBulletRef, className: 'bullet-content-bYMyWeb', children: [_jsx("div", { onMouseDown: resetBullets, onTouchStart: resetBullets, className: `bg-z-index-bYMyWeb ${bgClassName ? bgClassName : 'bg-bYMyWeb'}` }), [0, 1, 2, 3, 4, 5, 6, 7, 8].map((item) => (_jsx("div", { onMouseDown: (e) => handleMouseDown(item), onMouseMove: (e) => handleMouseMove(item), onTouchStart: (e) => handleTouchStart(item), onTouchMove: handleTouchMove, className: `${className ? className : 'bullet-bYMyWeb'} ${resArr.includes(item) ? 'active-bullet-bYMyWeb' : ''}`, children: useNumber && _jsx("span", { className: numberClassName, children: item }) }, item)))] }) })); }; export default PatternLock;