import { useQuickReactor } from '@tldraw/state-react' import { TLCursorType } from '@tldraw/tlschema' import { PI, radiansToDegrees } from '../primitives/utils' import { useContainer } from './useContainer' import { useEditor } from './useEditor' import { useIsDarkMode } from './useIsDarkMode' const CORNER_SVG = `` const EDGE_SVG = `` const ROTATE_CORNER_SVG = `` function getCursorCss( svg: string, r: number, tr: number, f: boolean, color: string, hotspotX = 16, hotspotY = 16 ) { const a = (-tr - r) * (PI / 180) const s = Math.sin(a) const c = Math.cos(a) const dx = 1 * c - 1 * s const dy = 1 * s + 1 * c return ( `url("data:image/svg+xml,` + svg.replaceAll(`"`, `'`) + `") ${hotspotX} ${hotspotY}, pointer` ) } const STATIC_CURSORS = [ 'default', 'pointer', 'cross', 'move', 'grab', 'grabbing', 'text', 'zoom-in', 'zoom-out', ] type CursorFunction = (rotation: number, flip: boolean, color: string) => string const CURSORS: Record = { none: () => 'none', 'ew-resize': (r, f, c) => getCursorCss(EDGE_SVG, r, 0, f, c), 'ns-resize': (r, f, c) => getCursorCss(EDGE_SVG, r, 90, f, c), 'nesw-resize': (r, f, c) => getCursorCss(CORNER_SVG, r, 0, f, c), 'nwse-resize': (r, f, c) => getCursorCss(CORNER_SVG, r, 90, f, c), 'nwse-rotate': (r, f, c) => getCursorCss(ROTATE_CORNER_SVG, r, 0, f, c), 'nesw-rotate': (r, f, c) => getCursorCss(ROTATE_CORNER_SVG, r, 90, f, c), 'senw-rotate': (r, f, c) => getCursorCss(ROTATE_CORNER_SVG, r, 180, f, c), 'swne-rotate': (r, f, c) => getCursorCss(ROTATE_CORNER_SVG, r, 270, f, c), } /** @public */ export function getCursor(cursor: TLCursorType, rotation = 0, color = 'black') { return CURSORS[cursor](radiansToDegrees(rotation), false, color) } export function useCursor() { const editor = useEditor() const container = useContainer() const isDarkMode = useIsDarkMode() useQuickReactor( 'useCursor', () => { const { type, rotation } = editor.getInstanceState().cursor if (STATIC_CURSORS.includes(type)) { container.style.setProperty('--tl-cursor', `var(--tl-cursor-${type})`) return } container.style.setProperty( '--tl-cursor', getCursor(type, rotation, isDarkMode ? 'white' : 'black') ) }, [editor, container, isDarkMode] ) }