@getguru/slate-yjs-react 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +3 -0
  3. package/dist/hooks/useDecorateRemoteCursors.d.ts +24 -0
  4. package/dist/hooks/useDecorateRemoteCursors.d.ts.map +1 -0
  5. package/dist/hooks/useRemoteCursorEditor.d.ts +4 -0
  6. package/dist/hooks/useRemoteCursorEditor.d.ts.map +1 -0
  7. package/dist/hooks/useRemoteCursorOverlayPositions.d.ts +19 -0
  8. package/dist/hooks/useRemoteCursorOverlayPositions.d.ts.map +1 -0
  9. package/dist/hooks/useRemoteCursorStateStore.d.ts +5 -0
  10. package/dist/hooks/useRemoteCursorStateStore.d.ts.map +1 -0
  11. package/dist/hooks/useRemoteCursorStates.d.ts +4 -0
  12. package/dist/hooks/useRemoteCursorStates.d.ts.map +1 -0
  13. package/dist/hooks/useUnsetCursorPositionOnBlur.d.ts +2 -0
  14. package/dist/hooks/useUnsetCursorPositionOnBlur.d.ts.map +1 -0
  15. package/dist/hooks/utils.d.ts +4 -0
  16. package/dist/hooks/utils.d.ts.map +1 -0
  17. package/dist/index.cjs +453 -0
  18. package/dist/index.cjs.map +1 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.global.js +31900 -0
  22. package/dist/index.global.js.map +1 -0
  23. package/dist/index.js +450 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/types.d.ts +5 -0
  26. package/dist/types.d.ts.map +1 -0
  27. package/dist/utils/getCursorRange.d.ts +4 -0
  28. package/dist/utils/getCursorRange.d.ts.map +1 -0
  29. package/dist/utils/getOverlayPosition.d.ts +24 -0
  30. package/dist/utils/getOverlayPosition.d.ts.map +1 -0
  31. package/dist/utils/react-editor-to-dom-range-safe.d.ts +4 -0
  32. package/dist/utils/react-editor-to-dom-range-safe.d.ts.map +1 -0
  33. package/package.json +55 -0
  34. package/src/hooks/useDecorateRemoteCursors.ts +125 -0
  35. package/src/hooks/useRemoteCursorEditor.ts +15 -0
  36. package/src/hooks/useRemoteCursorOverlayPositions.tsx +144 -0
  37. package/src/hooks/useRemoteCursorStateStore.ts +89 -0
  38. package/src/hooks/useRemoteCursorStates.ts +28 -0
  39. package/src/hooks/useUnsetCursorPositionOnBlur.ts +48 -0
  40. package/src/hooks/utils.ts +61 -0
  41. package/src/index.ts +26 -0
  42. package/src/types.ts +4 -0
  43. package/src/utils/getCursorRange.ts +45 -0
  44. package/src/utils/getOverlayPosition.ts +111 -0
  45. package/src/utils/react-editor-to-dom-range-safe.ts +13 -0
  46. package/tsconfig.json +11 -0
  47. package/tsup.config.ts +32 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/hooks/useDecorateRemoteCursors.ts","../src/utils/getCursorRange.ts","../src/hooks/useRemoteCursorEditor.ts","../src/hooks/useRemoteCursorStates.ts","../src/hooks/useRemoteCursorStateStore.ts","../src/hooks/useUnsetCursorPositionOnBlur.ts","../src/hooks/useRemoteCursorOverlayPositions.tsx","../src/utils/getOverlayPosition.ts","../src/utils/react-editor-to-dom-range-safe.ts","../src/hooks/utils.ts"],"sourcesContent":["export {\n RemoteCursorDecoration,\n RemoteCursorDecoratedRange,\n RemoteCaretDecoration,\n RemoteCaretDecoratedRange,\n TextWithRemoteCursors,\n UseDecorateRemoteCursorsOptions,\n getRemoteCursorsOnLeaf,\n getRemoteCaretsOnLeaf,\n useDecorateRemoteCursors,\n} from './hooks/useDecorateRemoteCursors';\n\nexport {\n useRemoteCursorStatesSelector,\n useRemoteCursorStates,\n} from './hooks/useRemoteCursorStates';\n\nexport { useUnsetCursorPositionOnBlur } from './hooks/useUnsetCursorPositionOnBlur';\n\nexport { getCursorRange } from './utils/getCursorRange';\n\nexport {\n CursorOverlayData,\n UseRemoteCursorOverlayPositionsOptions,\n useRemoteCursorOverlayPositions,\n} from './hooks/useRemoteCursorOverlayPositions';\n","import { CursorState } from '@getguru/slate-yjs-core';\nimport { useCallback, useRef } from 'react';\nimport { BaseRange, BaseText, NodeEntry, Range } from 'slate';\nimport { getCursorRange } from '../utils/getCursorRange';\nimport { useRemoteCursorEditor } from './useRemoteCursorEditor';\nimport { useRemoteCursorStates } from './useRemoteCursorStates';\n\nexport const REMOTE_CURSOR_DECORATION_PREFIX = 'remote-cursor-';\nexport const REMOTE_CURSOR_CARET_DECORATION_PREFIX = 'remote-caret-';\n\nexport type RemoteCaretDecoration<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n> = {\n [\n key: `${typeof REMOTE_CURSOR_CARET_DECORATION_PREFIX}${string}`\n ]: CursorState<TCursorData> & { isBackward: boolean };\n};\n\nexport type RemoteCursorDecoration<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n> = {\n [\n key: `${typeof REMOTE_CURSOR_DECORATION_PREFIX}${string}`\n ]: CursorState<TCursorData>;\n};\n\nexport type RemoteCursorDecoratedRange<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n> = BaseRange & RemoteCursorDecoration<TCursorData>;\n\nexport type RemoteCaretDecoratedRange<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n> = BaseRange & RemoteCaretDecoration<TCursorData>;\n\nexport type TextWithRemoteCursors<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n> = BaseText &\n RemoteCursorDecoration<TCursorData> &\n RemoteCaretDecoration<TCursorData>;\n\nexport function getRemoteCursorsOnLeaf<\n TCursorData extends Record<string, unknown>,\n TLeaf extends TextWithRemoteCursors<TCursorData>\n>(leaf: TLeaf): CursorState<TCursorData>[] {\n return Object.entries(leaf)\n .filter(([key]) => key.startsWith(REMOTE_CURSOR_DECORATION_PREFIX))\n .map(([, data]) => data);\n}\n\nexport function getRemoteCaretsOnLeaf<\n TCursorData extends Record<string, unknown>,\n TLeaf extends TextWithRemoteCursors<TCursorData>\n>(leaf: TLeaf): (CursorState<TCursorData> & { isBackward: boolean })[] {\n return Object.entries(leaf)\n .filter(([key]) => key.startsWith(REMOTE_CURSOR_CARET_DECORATION_PREFIX))\n .map(([, data]) => data);\n}\n\nexport type UseDecorateRemoteCursorsOptions = {\n carets?: boolean;\n};\n\nfunction getDecoration<\n TCursorData extends Record<string, unknown>,\n TCaret extends boolean\n>(\n clientId: string,\n state: CursorState<TCursorData>,\n range: BaseRange,\n caret: TCaret\n): TCaret extends true\n ? RemoteCursorDecoratedRange<TCursorData>\n : RemoteCaretDecoratedRange<TCursorData> {\n if (!caret) {\n const key = `${REMOTE_CURSOR_DECORATION_PREFIX}${clientId}`;\n return { ...range, [key]: state };\n }\n\n const key = `${REMOTE_CURSOR_CARET_DECORATION_PREFIX}${clientId}`;\n return {\n ...range,\n anchor: range.focus,\n [key]: state,\n };\n}\n\nexport function useDecorateRemoteCursors<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n>({ carets = true }: UseDecorateRemoteCursorsOptions = {}) {\n const editor = useRemoteCursorEditor<TCursorData>();\n const cursors = useRemoteCursorStates<TCursorData>();\n\n const cursorsRef = useRef(cursors);\n cursorsRef.current = cursors;\n\n return useCallback(\n (entry: NodeEntry) => {\n const [, path] = entry;\n if (path.length !== 0) {\n return [];\n }\n\n return Object.entries(cursorsRef.current).flatMap(([clientId, state]) => {\n const range = getCursorRange(editor, state);\n if (!range) {\n return [];\n }\n\n if (carets && Range.isCollapsed(range)) {\n return getDecoration(clientId, state, range, true);\n }\n\n if (!carets) {\n return getDecoration(clientId, state, range, false);\n }\n\n return [\n getDecoration(clientId, state, range, false),\n getDecoration(clientId, state, range, true),\n ];\n });\n },\n [carets, editor]\n );\n}\n","import {\n CursorEditor,\n CursorState,\n relativeRangeToSlateRange,\n} from '@getguru/slate-yjs-core';\nimport { BaseRange, Descendant, Range } from 'slate';\n\nconst CHILDREN_TO_CURSOR_STATE_TO_RANGE: WeakMap<\n Descendant[],\n WeakMap<CursorState, Range | null>\n> = new WeakMap();\n\nexport function getCursorRange<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n>(\n editor: CursorEditor<TCursorData>,\n cursorState: CursorState<TCursorData>\n): BaseRange | null {\n if (!cursorState.relativeSelection) {\n return null;\n }\n\n let cursorStates = CHILDREN_TO_CURSOR_STATE_TO_RANGE.get(editor.children);\n if (!cursorStates) {\n cursorStates = new WeakMap();\n CHILDREN_TO_CURSOR_STATE_TO_RANGE.set(editor.children, cursorStates);\n }\n\n let range = cursorStates.get(cursorState);\n if (range === undefined) {\n try {\n range = relativeRangeToSlateRange(\n editor.sharedRoot,\n editor,\n cursorState.relativeSelection\n );\n\n cursorStates.set(cursorState, range);\n } catch (e) {\n return null;\n }\n }\n\n return range;\n}\n","import { CursorEditor } from '@getguru/slate-yjs-core';\nimport { ReactEditor, useSlateStatic } from 'slate-react';\n\nexport function useRemoteCursorEditor<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n>(): CursorEditor<TCursorData> & ReactEditor {\n const editor = useSlateStatic();\n if (!CursorEditor.isCursorEditor(editor)) {\n throw new Error(\n 'Cannot use useSyncExternalStore outside the context of a RemoteCursorEditor'\n );\n }\n\n return editor as CursorEditor & ReactEditor;\n}\n","import { CursorState } from '@getguru/slate-yjs-core';\nimport { useSyncExternalStore } from 'use-sync-external-store/shim';\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';\nimport { useRemoteCursorStateStore } from './useRemoteCursorStateStore';\n\nexport function useRemoteCursorStates<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n>() {\n const [subscribe, getSnapshot] = useRemoteCursorStateStore<TCursorData>();\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n\nexport function useRemoteCursorStatesSelector<\n TCursorData extends Record<string, unknown> = Record<string, unknown>,\n TSelection = unknown\n>(\n selector: (cursors: Record<string, CursorState<TCursorData>>) => TSelection,\n isEqual?: (a: TSelection, b: TSelection) => boolean\n): TSelection {\n const [subscribe, getSnapshot] = useRemoteCursorStateStore<TCursorData>();\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n null,\n selector,\n isEqual\n );\n}\n","import {\n CursorEditor,\n CursorState,\n RemoteCursorChangeEventListener,\n} from '@getguru/slate-yjs-core';\nimport { BaseEditor } from 'slate';\nimport { Store } from '../types';\nimport { useRemoteCursorEditor } from './useRemoteCursorEditor';\n\nexport type CursorStore<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n> = Store<Record<string, CursorState<TCursorData>>>;\n\nconst EDITOR_TO_CURSOR_STORE: WeakMap<BaseEditor, CursorStore> = new WeakMap();\n\nfunction createRemoteCursorStateStore<\n TCursorData extends Record<string, unknown>\n>(editor: CursorEditor<TCursorData>): CursorStore<TCursorData> {\n let cursors: Record<string, CursorState<TCursorData>> = {};\n\n const changed = new Set<number>();\n const addChanged = changed.add.bind(changed);\n const onStoreChangeListeners: Set<() => void> = new Set();\n\n let changeHandler: RemoteCursorChangeEventListener | null = null;\n\n const subscribe = (onStoreChange: () => void) => {\n onStoreChangeListeners.add(onStoreChange);\n if (!changeHandler) {\n changeHandler = (event) => {\n event.added.forEach(addChanged);\n event.removed.forEach(addChanged);\n event.updated.forEach(addChanged);\n onStoreChangeListeners.forEach((listener) => listener());\n };\n CursorEditor.on(editor, 'change', changeHandler);\n }\n\n return () => {\n onStoreChangeListeners.delete(onStoreChange);\n if (changeHandler && onStoreChangeListeners.size === 0) {\n CursorEditor.off(editor, 'change', changeHandler);\n changeHandler = null;\n }\n };\n };\n\n const getSnapshot = () => {\n if (changed.size === 0) {\n return cursors;\n }\n\n changed.forEach((clientId) => {\n const state = CursorEditor.cursorState(editor, clientId);\n if (state === null) {\n delete cursors[clientId.toString()];\n return;\n }\n\n cursors[clientId] = state;\n });\n\n changed.clear();\n cursors = { ...cursors };\n return cursors;\n };\n\n return [subscribe, getSnapshot];\n}\n\nfunction getCursorStateStore<TCursorData extends Record<string, unknown>>(\n editor: CursorEditor<TCursorData>\n): CursorStore<TCursorData> {\n const existing = EDITOR_TO_CURSOR_STORE.get(editor);\n if (existing) {\n return existing as CursorStore<TCursorData>;\n }\n\n const store = createRemoteCursorStateStore(editor);\n EDITOR_TO_CURSOR_STORE.set(editor, store);\n return store;\n}\n\nexport function useRemoteCursorStateStore<\n TCursorData extends Record<string, unknown> = Record<string, unknown>\n>() {\n const editor = useRemoteCursorEditor<TCursorData>();\n return getCursorStateStore(editor);\n}\n","import { CursorEditor } from '@getguru/slate-yjs-core';\nimport { useCallback, useEffect } from 'react';\nimport { useFocused } from 'slate-react';\nimport { useRemoteCursorEditor } from './useRemoteCursorEditor';\n\nexport function useUnsetCursorPositionOnBlur() {\n const editor = useRemoteCursorEditor();\n const isSlateFocused = useFocused();\n\n const sendCursorPosition = useCallback(\n (isFocused?: boolean) => {\n if (isFocused && editor.selection) {\n CursorEditor.sendCursorPosition(editor, editor.selection);\n return;\n }\n\n if (!isFocused) {\n CursorEditor.sendCursorPosition(editor, null);\n }\n },\n [editor]\n );\n\n useEffect(() => {\n const handleWindowBlur = () => {\n if (isSlateFocused) {\n sendCursorPosition(false);\n }\n };\n\n const handleWindowFocus = () => {\n if (isSlateFocused) {\n sendCursorPosition(true);\n }\n };\n\n window.addEventListener('blur', handleWindowBlur);\n window.addEventListener('focus', handleWindowFocus);\n return () => {\n window.removeEventListener('blur', handleWindowBlur);\n window.removeEventListener('focus', handleWindowFocus);\n };\n }, [isSlateFocused, sendCursorPosition]);\n\n useEffect(() => {\n sendCursorPosition(isSlateFocused);\n }, [editor, isSlateFocused, sendCursorPosition]);\n}\n","import { CursorState } from '@getguru/slate-yjs-core';\nimport {\n RefObject,\n useCallback,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { BaseRange, NodeMatch, Text } from 'slate';\nimport { getCursorRange } from '../utils/getCursorRange';\nimport {\n CaretPosition,\n getOverlayPosition,\n OverlayPosition,\n SelectionRect,\n} from '../utils/getOverlayPosition';\nimport { useRemoteCursorEditor } from './useRemoteCursorEditor';\nimport { useRemoteCursorStates } from './useRemoteCursorStates';\nimport { useOnResize, useRequestRerender } from './utils';\n\nconst FROZEN_EMPTY_ARRAY = Object.freeze([]);\n\nexport type UseRemoteCursorOverlayPositionsOptions<T extends HTMLElement> = {\n shouldGenerateOverlay?: NodeMatch<Text>;\n} & (\n | {\n // Container the overlay will be rendered in. If set, all returned overlay positions\n // will be relative to this container and the cursor positions will be automatically\n // updated on container resize.\n containerRef?: undefined;\n }\n | {\n containerRef: RefObject<T>;\n\n // Whether to refresh the cursor overlay positions on container resize. Defaults\n // to true. If set to 'debounced', the remote cursor positions will be updated\n // each animation frame.\n refreshOnResize?: boolean | 'debounced';\n }\n);\n\nexport type CursorOverlayData<TCursorData extends Record<string, unknown>> =\n CursorState<TCursorData> & {\n range: BaseRange | null;\n caretPosition: CaretPosition | null;\n selectionRects: SelectionRect[];\n };\n\nexport function useRemoteCursorOverlayPositions<\n TCursorData extends Record<string, unknown>,\n TContainer extends HTMLElement = HTMLDivElement\n>({\n containerRef,\n shouldGenerateOverlay,\n ...opts\n}: UseRemoteCursorOverlayPositionsOptions<TContainer> = {}) {\n const editor = useRemoteCursorEditor<TCursorData>();\n const cursorStates = useRemoteCursorStates<TCursorData>();\n const requestRerender = useRequestRerender();\n\n const overlayPositionCache = useRef(\n new WeakMap<BaseRange, OverlayPosition>()\n );\n const [overlayPositions, setOverlayPositions] = useState<\n Record<string, OverlayPosition>\n >({});\n\n const refreshOnResize =\n 'refreshOnResize' in opts ? opts.refreshOnResize ?? true : true;\n\n useOnResize(refreshOnResize ? containerRef : undefined, () => {\n overlayPositionCache.current = new WeakMap();\n requestRerender(refreshOnResize !== 'debounced');\n });\n\n // Update selection rects after paint\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(() => {\n // We have a container ref but the ref is null => container\n // isn't mounted to we can't calculate the selection rects.\n if (containerRef && !containerRef.current) {\n return;\n }\n\n const containerRect = containerRef?.current?.getBoundingClientRect();\n const xOffset = containerRect?.x ?? 0;\n const yOffset = containerRect?.y ?? 0;\n\n let overlayPositionsChanged =\n Object.keys(overlayPositions).length !== Object.keys(cursorStates).length;\n\n const updated = Object.fromEntries(\n Object.entries(cursorStates).map(([key, state]) => {\n const range = state.relativeSelection && getCursorRange(editor, state);\n\n if (!range) {\n return [key, FROZEN_EMPTY_ARRAY];\n }\n\n const cached = overlayPositionCache.current.get(range);\n if (cached) {\n return [key, cached];\n }\n\n const overlayPosition = getOverlayPosition(editor, range, {\n xOffset,\n yOffset,\n shouldGenerateOverlay,\n });\n overlayPositionsChanged = true;\n overlayPositionCache.current.set(range, overlayPosition);\n return [key, overlayPosition];\n })\n );\n\n if (overlayPositionsChanged) {\n setOverlayPositions(updated);\n }\n });\n\n const overlayData = useMemo<CursorOverlayData<TCursorData>[]>(\n () =>\n Object.entries(cursorStates).map(([clientId, state]) => {\n const range = state.relativeSelection && getCursorRange(editor, state);\n const overlayPosition = overlayPositions[clientId];\n\n return {\n ...state,\n range,\n caretPosition: overlayPosition?.caretPosition ?? null,\n selectionRects: overlayPosition?.selectionRects ?? FROZEN_EMPTY_ARRAY,\n };\n }),\n [cursorStates, editor, overlayPositions]\n );\n\n const refresh = useCallback(() => {\n overlayPositionCache.current = new WeakMap();\n requestRerender(true);\n }, [requestRerender]);\n\n return [overlayData, refresh] as const;\n}\n","import { BaseRange, Editor, Path, Range, Text } from 'slate';\nimport { ReactEditor } from 'slate-react';\nimport { reactEditorToDomRangeSafe } from './react-editor-to-dom-range-safe';\n\nexport type SelectionRect = {\n width: number;\n height: number;\n top: number;\n left: number;\n};\n\nexport type CaretPosition = {\n height: number;\n top: number;\n left: number;\n};\n\nexport type OverlayPosition = {\n caretPosition: CaretPosition | null;\n selectionRects: SelectionRect[];\n};\n\nexport type GetSelectionRectsOptions = {\n xOffset: number;\n yOffset: number;\n shouldGenerateOverlay?: (node: Text, path: Path) => boolean;\n};\n\nexport function getOverlayPosition(\n editor: ReactEditor,\n range: BaseRange,\n { yOffset, xOffset, shouldGenerateOverlay }: GetSelectionRectsOptions\n): OverlayPosition {\n const [start, end] = Range.edges(range);\n const domRange = reactEditorToDomRangeSafe(editor, range);\n if (!domRange) {\n return {\n caretPosition: null,\n selectionRects: [],\n };\n }\n\n const selectionRects: SelectionRect[] = [];\n const nodeIterator = Editor.nodes(editor, {\n at: range,\n match: (n, p) =>\n Text.isText(n) && (!shouldGenerateOverlay || shouldGenerateOverlay(n, p)),\n });\n\n let caretPosition: CaretPosition | null = null;\n const isBackward = Range.isBackward(range);\n for (const [node, path] of nodeIterator) {\n const domNode = ReactEditor.toDOMNode(editor, node);\n\n const isStartNode = Path.equals(path, start.path);\n const isEndNode = Path.equals(path, end.path);\n\n let clientRects: DOMRectList | null = null;\n if (isStartNode || isEndNode) {\n const nodeRange = document.createRange();\n nodeRange.selectNode(domNode);\n\n if (isStartNode) {\n nodeRange.setStart(domRange.startContainer, domRange.startOffset);\n }\n if (isEndNode) {\n nodeRange.setEnd(domRange.endContainer, domRange.endOffset);\n }\n\n clientRects = nodeRange.getClientRects();\n } else {\n clientRects = domNode.getClientRects();\n }\n\n const isCaret = isBackward ? isStartNode : isEndNode;\n for (let i = 0; i < clientRects.length; i++) {\n const clientRect = clientRects.item(i);\n if (!clientRect) {\n continue;\n }\n\n const isCaretRect =\n isCaret && (isBackward ? i === 0 : i === clientRects.length - 1);\n\n const top = clientRect.top - yOffset;\n const left = clientRect.left - xOffset;\n\n if (isCaretRect) {\n caretPosition = {\n height: clientRect.height,\n top,\n left:\n left +\n (isBackward || Range.isCollapsed(range) ? 0 : clientRect.width),\n };\n }\n\n selectionRects.push({\n width: clientRect.width,\n height: clientRect.height,\n top,\n left,\n });\n }\n }\n\n return {\n selectionRects,\n caretPosition,\n };\n}\n","import { ReactEditor } from 'slate-react';\nimport { BaseRange } from 'slate';\n\nexport function reactEditorToDomRangeSafe(\n editor: ReactEditor,\n range: BaseRange\n): Range | null {\n try {\n return ReactEditor.toDOMRange(editor, range);\n } catch (e) {\n return null;\n }\n}\n","import {\n RefObject,\n useCallback,\n useEffect,\n useReducer,\n useRef,\n useState,\n} from 'react';\n\nexport function useRequestRerender() {\n const [, rerender] = useReducer((s) => s + 1, 0);\n const animationFrameIdRef = useRef<number | null>(null);\n\n const clearAnimationFrame = () => {\n if (animationFrameIdRef.current) {\n cancelAnimationFrame(animationFrameIdRef.current);\n animationFrameIdRef.current = 0;\n }\n };\n\n useEffect(clearAnimationFrame);\n useEffect(() => clearAnimationFrame, []);\n\n return useCallback((immediately = false) => {\n if (immediately) {\n rerender();\n return;\n }\n\n if (animationFrameIdRef.current) {\n return;\n }\n\n animationFrameIdRef.current = requestAnimationFrame(rerender);\n }, []);\n}\n\nexport function useOnResize<T extends HTMLElement>(\n ref: RefObject<T> | undefined,\n onResize: () => void\n) {\n const onResizeRef = useRef(onResize);\n onResizeRef.current = onResize;\n\n const [observer] = useState(\n () =>\n new ResizeObserver(() => {\n onResizeRef.current();\n })\n );\n\n useEffect(() => {\n if (!ref?.current) {\n return;\n }\n\n const { current: element } = ref;\n observer.observe(element);\n return () => observer.unobserve(element);\n }, [observer, ref]);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,6 @@
1
+ export { RemoteCursorDecoration, RemoteCursorDecoratedRange, RemoteCaretDecoration, RemoteCaretDecoratedRange, TextWithRemoteCursors, UseDecorateRemoteCursorsOptions, getRemoteCursorsOnLeaf, getRemoteCaretsOnLeaf, useDecorateRemoteCursors, } from './hooks/useDecorateRemoteCursors';
2
+ export { useRemoteCursorStatesSelector, useRemoteCursorStates, } from './hooks/useRemoteCursorStates';
3
+ export { useUnsetCursorPositionOnBlur } from './hooks/useUnsetCursorPositionOnBlur';
4
+ export { getCursorRange } from './utils/getCursorRange';
5
+ export { CursorOverlayData, UseRemoteCursorOverlayPositionsOptions, useRemoteCursorOverlayPositions, } from './hooks/useRemoteCursorOverlayPositions';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,+BAA+B,EAC/B,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AAEpF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EACL,iBAAiB,EACjB,sCAAsC,EACtC,+BAA+B,GAChC,MAAM,yCAAyC,CAAC"}