UNPKG

@mantine/hooks

Version:

A collection of 50+ hooks for state and UI management

1 lines 6.23 kB
{"version":3,"file":"use-move.cjs","names":["clamp"],"sources":["../../src/use-move/use-move.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { clamp } from '../utils';\n\nexport interface UseMovePosition {\n x: number;\n y: number;\n}\n\nexport function clampUseMovePosition(position: UseMovePosition) {\n return {\n x: clamp(position.x, 0, 1),\n y: clamp(position.y, 0, 1),\n };\n}\n\nexport interface UseMoveHandlers {\n onScrubStart?: () => void;\n onScrubEnd?: () => void;\n}\n\nexport interface UseMoveReturnValue<T extends HTMLElement = any> {\n ref: React.RefCallback<T | null>;\n active: boolean;\n}\n\nexport function useMove<T extends HTMLElement = any>(\n onChange: (value: UseMovePosition) => void,\n handlers?: UseMoveHandlers,\n dir: 'ltr' | 'rtl' = 'ltr'\n): UseMoveReturnValue<T> {\n const mounted = useRef<boolean>(false);\n const isSliding = useRef(false);\n const frame = useRef(0);\n const [active, setActive] = useState(false);\n\n useEffect(() => {\n mounted.current = true;\n }, []);\n\n const refCallback: React.RefCallback<T | null> = useCallback(\n (node) => {\n const onScrub = ({ x, y }: UseMovePosition) => {\n cancelAnimationFrame(frame.current);\n\n frame.current = requestAnimationFrame(() => {\n if (mounted.current && node) {\n node.style.userSelect = 'none';\n const rect = node.getBoundingClientRect();\n\n if (rect.width && rect.height) {\n const _x = clamp((x - rect.left) / rect.width, 0, 1);\n onChange({\n x: dir === 'ltr' ? _x : 1 - _x,\n y: clamp((y - rect.top) / rect.height, 0, 1),\n });\n }\n }\n });\n };\n\n const bindEvents = () => {\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', stopScrubbing);\n document.addEventListener('touchmove', onTouchMove, { passive: false });\n document.addEventListener('touchend', stopScrubbing);\n };\n\n const unbindEvents = () => {\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', stopScrubbing);\n document.removeEventListener('touchmove', onTouchMove);\n document.removeEventListener('touchend', stopScrubbing);\n };\n\n const startScrubbing = () => {\n if (!isSliding.current && mounted.current) {\n isSliding.current = true;\n typeof handlers?.onScrubStart === 'function' && handlers.onScrubStart();\n setActive(true);\n bindEvents();\n }\n };\n\n const stopScrubbing = () => {\n if (isSliding.current && mounted.current) {\n isSliding.current = false;\n setActive(false);\n unbindEvents();\n setTimeout(() => {\n typeof handlers?.onScrubEnd === 'function' && handlers.onScrubEnd();\n }, 0);\n }\n };\n\n const onMouseDown = (event: MouseEvent) => {\n startScrubbing();\n event.preventDefault();\n onMouseMove(event);\n };\n\n const onMouseMove = (event: MouseEvent) => onScrub({ x: event.clientX, y: event.clientY });\n\n const onTouchStart = (event: TouchEvent) => {\n if (event.cancelable) {\n event.preventDefault();\n }\n\n startScrubbing();\n onTouchMove(event);\n };\n\n const onTouchMove = (event: TouchEvent) => {\n if (event.cancelable) {\n event.preventDefault();\n }\n\n onScrub({ x: event.changedTouches[0].clientX, y: event.changedTouches[0].clientY });\n };\n\n node?.addEventListener('mousedown', onMouseDown);\n node?.addEventListener('touchstart', onTouchStart, { passive: false });\n\n return () => {\n if (node) {\n node.removeEventListener('mousedown', onMouseDown);\n node.removeEventListener('touchstart', onTouchStart);\n }\n };\n },\n [dir, onChange]\n );\n\n return { ref: refCallback, active };\n}\n\nexport namespace useMove {\n export type Handlers = UseMoveHandlers;\n export type ReturnValue<T extends HTMLElement> = UseMoveReturnValue<T>;\n}\n"],"mappings":";;;;AAQA,SAAgB,qBAAqB,UAA2B;AAC9D,QAAO;EACL,GAAGA,cAAAA,MAAM,SAAS,GAAG,GAAG,EAAE;EAC1B,GAAGA,cAAAA,MAAM,SAAS,GAAG,GAAG,EAAE;EAC3B;;AAaH,SAAgB,QACd,UACA,UACA,MAAqB,OACE;CACvB,MAAM,WAAA,GAAA,MAAA,QAA0B,MAAM;CACtC,MAAM,aAAA,GAAA,MAAA,QAAmB,MAAM;CAC/B,MAAM,SAAA,GAAA,MAAA,QAAe,EAAE;CACvB,MAAM,CAAC,QAAQ,cAAA,GAAA,MAAA,UAAsB,MAAM;AAE3C,EAAA,GAAA,MAAA,iBAAgB;AACd,UAAQ,UAAU;IACjB,EAAE,CAAC;AA+FN,QAAO;EAAE,MAAA,GAAA,MAAA,cA5FN,SAAS;GACR,MAAM,WAAW,EAAE,GAAG,QAAyB;AAC7C,yBAAqB,MAAM,QAAQ;AAEnC,UAAM,UAAU,4BAA4B;AAC1C,SAAI,QAAQ,WAAW,MAAM;AAC3B,WAAK,MAAM,aAAa;MACxB,MAAM,OAAO,KAAK,uBAAuB;AAEzC,UAAI,KAAK,SAAS,KAAK,QAAQ;OAC7B,MAAM,KAAKA,cAAAA,OAAO,IAAI,KAAK,QAAQ,KAAK,OAAO,GAAG,EAAE;AACpD,gBAAS;QACP,GAAG,QAAQ,QAAQ,KAAK,IAAI;QAC5B,GAAGA,cAAAA,OAAO,IAAI,KAAK,OAAO,KAAK,QAAQ,GAAG,EAAE;QAC7C,CAAC;;;MAGN;;GAGJ,MAAM,mBAAmB;AACvB,aAAS,iBAAiB,aAAa,YAAY;AACnD,aAAS,iBAAiB,WAAW,cAAc;AACnD,aAAS,iBAAiB,aAAa,aAAa,EAAE,SAAS,OAAO,CAAC;AACvE,aAAS,iBAAiB,YAAY,cAAc;;GAGtD,MAAM,qBAAqB;AACzB,aAAS,oBAAoB,aAAa,YAAY;AACtD,aAAS,oBAAoB,WAAW,cAAc;AACtD,aAAS,oBAAoB,aAAa,YAAY;AACtD,aAAS,oBAAoB,YAAY,cAAc;;GAGzD,MAAM,uBAAuB;AAC3B,QAAI,CAAC,UAAU,WAAW,QAAQ,SAAS;AACzC,eAAU,UAAU;AACpB,YAAO,UAAU,iBAAiB,cAAc,SAAS,cAAc;AACvE,eAAU,KAAK;AACf,iBAAY;;;GAIhB,MAAM,sBAAsB;AAC1B,QAAI,UAAU,WAAW,QAAQ,SAAS;AACxC,eAAU,UAAU;AACpB,eAAU,MAAM;AAChB,mBAAc;AACd,sBAAiB;AACf,aAAO,UAAU,eAAe,cAAc,SAAS,YAAY;QAClE,EAAE;;;GAIT,MAAM,eAAe,UAAsB;AACzC,oBAAgB;AAChB,UAAM,gBAAgB;AACtB,gBAAY,MAAM;;GAGpB,MAAM,eAAe,UAAsB,QAAQ;IAAE,GAAG,MAAM;IAAS,GAAG,MAAM;IAAS,CAAC;GAE1F,MAAM,gBAAgB,UAAsB;AAC1C,QAAI,MAAM,WACR,OAAM,gBAAgB;AAGxB,oBAAgB;AAChB,gBAAY,MAAM;;GAGpB,MAAM,eAAe,UAAsB;AACzC,QAAI,MAAM,WACR,OAAM,gBAAgB;AAGxB,YAAQ;KAAE,GAAG,MAAM,eAAe,GAAG;KAAS,GAAG,MAAM,eAAe,GAAG;KAAS,CAAC;;AAGrF,SAAM,iBAAiB,aAAa,YAAY;AAChD,SAAM,iBAAiB,cAAc,cAAc,EAAE,SAAS,OAAO,CAAC;AAEtE,gBAAa;AACX,QAAI,MAAM;AACR,UAAK,oBAAoB,aAAa,YAAY;AAClD,UAAK,oBAAoB,cAAc,aAAa;;;KAI1D,CAAC,KAAK,SAAS,CAChB;EAE0B;EAAQ"}