UNPKG

@lexical/react

Version:

This package provides Lexical components and hooks for React applications.

100 lines (87 loc) • 3.56 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 { createContext, useContext } 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. * */ // Do not require this module directly! Use normal `invariant` calls. function formatDevErrorMessage(message) { throw new Error(message); } /** * The value stored in the {@link CollaborationContext}: the local user's * display `name` and cursor `color`, whether collaboration is currently active, * and the map of Yjs documents shared by the editors under this provider. */ const entries = [['Cat', 'rgb(125, 50, 0)'], ['Dog', 'rgb(100, 0, 0)'], ['Rabbit', 'rgb(150, 0, 0)'], ['Frog', 'rgb(200, 0, 0)'], ['Fox', 'rgb(200, 75, 0)'], ['Hedgehog', 'rgb(0, 75, 0)'], ['Pigeon', 'rgb(0, 125, 0)'], ['Squirrel', 'rgb(75, 100, 0)'], ['Bear', 'rgb(125, 100, 0)'], ['Tiger', 'rgb(0, 0, 150)'], ['Leopard', 'rgb(0, 0, 200)'], ['Zebra', 'rgb(0, 0, 250)'], ['Wolf', 'rgb(0, 100, 150)'], ['Owl', 'rgb(0, 100, 100)'], ['Gull', 'rgb(100, 0, 100)'], ['Squid', 'rgb(150, 0, 150)']]; // Picked on first use rather than at module scope, where the `Math.random()` // call is a side effect to bundlers that would pin this module (and the // table above) into every bundle importing it. It is still picked once and // shared by every context created afterwards, as before. let randomEntry; function getRandomEntry() { if (randomEntry === undefined) { randomEntry = entries[Math.floor(Math.random() * entries.length)]; } return randomEntry; } /** * The React context that holds the shared {@link CollaborationContextType} for * collaborative editors. Provide it with {@link LexicalCollaboration} and read * it with {@link useCollaborationContext}. */ const CollaborationContext = // Annotated by hand: React's createContext is not a Lexical factory, so the // build does not annotate it, and an unannotated module-scope call pins the // module into every bundle. /* @__PURE__ */ createContext(null); /** * @internal * @__NO_SIDE_EFFECTS__ */ function newContext() { const [name, color] = getRandomEntry(); return { color, isCollabActive: false, name, yjsDocMap: new Map() }; } // This is here to help the transition post-#7818, however should be removed in a future release as // a shared context across editors is likely to lead to bugs. const UNSAFE_GLOBAL_CONTEXT = /* @__PURE__ */newContext(); /** * Reads the current {@link CollaborationContextType} from the nearest * {@link LexicalCollaboration} provider. Optionally pass `username` and `color` * to set the local user's display name and cursor color. * * @returns The active collaboration context. */ function useCollaborationContext(username, color) { let collabContext = useContext(CollaborationContext); if (!(collabContext != null)) { formatDevErrorMessage(`useCollaborationContext: no context provider found`); } collabContext = collabContext ?? UNSAFE_GLOBAL_CONTEXT; if (username != null) { // eslint-disable-next-line react-hooks/immutability collabContext.name = username; } if (color != null) { // eslint-disable-next-line react-hooks/immutability collabContext.color = color; } return collabContext; } export { CollaborationContext, newContext, useCollaborationContext };