UNPKG

@lexical/react

Version:

This package provides Lexical components and hooks for React applications.

101 lines (88 loc) 3.17 kB
/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; import { useLayoutEffect, useEffect, useMemo, useState, useRef } from 'react'; /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined'; /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ // This workaround is no longer necessary in React 19, // but we currently support React >=17.x // https://github.com/facebook/react/pull/26395 const useLayoutEffectImpl = CAN_USE_DOM ? useLayoutEffect : useEffect; /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ /** * Shortcut to Lexical subscriptions when values are used for render. * @param subscription - The function to create the {@link LexicalSubscription}. This function's identity must be stable (e.g. defined at module scope or with useCallback). */ function useLexicalSubscription(subscription) { const [editor] = useLexicalComposerContext(); const initializedSubscription = useMemo(() => subscription(editor), [editor, subscription]); const [value, setValue] = useState(() => initializedSubscription.initialValueFn()); const valueRef = useRef(value); useLayoutEffectImpl(() => { const { initialValueFn, subscribe } = initializedSubscription; const currentValue = initialValueFn(); if (valueRef.current !== currentValue) { valueRef.current = currentValue; setValue(currentValue); } return subscribe(newValue => { valueRef.current = newValue; setValue(newValue); }); }, [initializedSubscription, subscription]); return value; } /** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ function subscription(editor) { return { initialValueFn: () => editor.isEditable(), subscribe: callback => { return editor.registerEditableListener(callback); } }; } /** * Get the current value for {@link LexicalEditor.isEditable} * using {@link useLexicalSubscription}. * You should prefer this over manually observing the value with * {@link LexicalEditor.registerEditableListener}, * which is a bit tricky to do correctly, particularly when using * React StrictMode (the default for development) or concurrency. */ function useLexicalEditable() { return useLexicalSubscription(subscription); } export { useLexicalEditable };