UNPKG

@arolariu/components

Version:

🎨 60+ beautiful, accessible React components built on Radix UI. TypeScript-first, tree-shakeable, SSR-ready. Perfect for modern web apps, design systems & rapid prototyping. Zero config, maximum flexibility! ⚡

179 lines (178 loc) • 7.24 kB
"use client"; "use strict"; var __webpack_require__ = {}; (()=>{ __webpack_require__.d = (exports1, definition)=>{ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, { enumerable: true, get: definition[key] }); }; })(); (()=>{ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop); })(); (()=>{ __webpack_require__.r = (exports1)=>{ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, { value: 'Module' }); Object.defineProperty(exports1, '__esModule', { value: true }); }; })(); var __webpack_exports__ = {}; __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { Scratcher: ()=>Scratcher }); const jsx_runtime_namespaceObject = require("react/jsx-runtime"); const utils_cjs_namespaceObject = require("../../lib/utils.cjs"); const react_namespaceObject = require("motion/react"); const external_react_namespaceObject = require("react"); const Scratcher = ({ width, height, minScratchPercentage = 50, onComplete, children, className, gradientColors = [ "#A97CF8", "#F38CB8", "#FDCC92" ] })=>{ const canvasRef = (0, external_react_namespaceObject.useRef)(null); const [isScratching, setIsScratching] = (0, external_react_namespaceObject.useState)(false); const [isComplete, setIsComplete] = (0, external_react_namespaceObject.useState)(false); const controls = (0, react_namespaceObject.useAnimation)(); (0, external_react_namespaceObject.useEffect)(()=>{ const canvas = canvasRef.current; const ctx = canvas?.getContext("2d"); if (canvas && ctx) { ctx.fillStyle = "#ccc"; ctx.fillRect(0, 0, canvas.width, canvas.height); const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height); gradient.addColorStop(0, gradientColors[0]); gradient.addColorStop(0.5, gradientColors[1]); gradient.addColorStop(1, gradientColors[2]); ctx.fillStyle = gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); } }, [ gradientColors ]); (0, external_react_namespaceObject.useEffect)(()=>{ const handleDocumentMouseMove = (event)=>{ if (!isScratching) return; scratch(event.clientX, event.clientY); }; const handleDocumentTouchMove = (event)=>{ if (!isScratching) return; const touch = event.touches[0]; scratch(touch.clientX, touch.clientY); }; const handleDocumentMouseUp = ()=>{ setIsScratching(false); checkCompletion(); }; const handleDocumentTouchEnd = ()=>{ setIsScratching(false); checkCompletion(); }; document.addEventListener("mousedown", handleDocumentMouseMove); document.addEventListener("mousemove", handleDocumentMouseMove); document.addEventListener("touchstart", handleDocumentTouchMove); document.addEventListener("touchmove", handleDocumentTouchMove); document.addEventListener("mouseup", handleDocumentMouseUp); document.addEventListener("touchend", handleDocumentTouchEnd); document.addEventListener("touchcancel", handleDocumentTouchEnd); return ()=>{ document.removeEventListener("mousedown", handleDocumentMouseMove); document.removeEventListener("mousemove", handleDocumentMouseMove); document.removeEventListener("touchstart", handleDocumentTouchMove); document.removeEventListener("touchmove", handleDocumentTouchMove); document.removeEventListener("mouseup", handleDocumentMouseUp); document.removeEventListener("touchend", handleDocumentTouchEnd); document.removeEventListener("touchcancel", handleDocumentTouchEnd); }; }, [ isScratching ]); const handleMouseDown = ()=>setIsScratching(true); const handleTouchStart = ()=>setIsScratching(true); const scratch = (clientX, clientY)=>{ const canvas = canvasRef.current; const ctx = canvas?.getContext("2d"); if (canvas && ctx) { const rect = canvas.getBoundingClientRect(); const x = clientX - rect.left + 16; const y = clientY - rect.top + 16; ctx.globalCompositeOperation = "destination-out"; ctx.beginPath(); ctx.arc(x, y, 30, 0, 2 * Math.PI); ctx.fill(); } }; const startAnimation = async ()=>{ await controls.start({ scale: [ 1, 1.5, 1 ], rotate: [ 0, 10, -10, 10, -10, 0 ], transition: { duration: 0.5 } }); if (onComplete) onComplete(); }; const checkCompletion = ()=>{ if (isComplete) return; const canvas = canvasRef.current; const ctx = canvas?.getContext("2d"); if (canvas && ctx) { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const pixels = imageData.data; const totalPixels = pixels.length / 4; let clearPixels = 0; for(let i = 3; i < pixels.length; i += 4)if (0 === pixels[i]) clearPixels++; const percentage = clearPixels / totalPixels * 100; if (percentage >= minScratchPercentage) { setIsComplete(true); ctx.clearRect(0, 0, canvas.width, canvas.height); startAnimation(); } } }; return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(react_namespaceObject.motion.div, { className: (0, utils_cjs_namespaceObject.cn)("relative select-none", className), style: { width, height, cursor: "url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj4KICA8Y2lyY2xlIGN4PSIxNiIgY3k9IjE2IiByPSIxNSIgc3R5bGU9ImZpbGw6I2ZmZjtzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MXB4OyIgLz4KPC9zdmc+'), auto" }, animate: controls, children: [ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("canvas", { ref: canvasRef, width: width, height: height, className: "absolute left-0 top-0", onMouseDown: handleMouseDown, onTouchStart: handleTouchStart }), children ] }); }; exports.Scratcher = __webpack_exports__.Scratcher; for(var __webpack_i__ in __webpack_exports__)if (-1 === [ "Scratcher" ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__]; Object.defineProperty(exports, '__esModule', { value: true }); //# sourceMappingURL=scratcher.cjs.map