@lexical/react
Version:
This package provides Lexical components and hooks for React applications.
103 lines (89 loc) • 3.33 kB
text/typescript
/**
* 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 type {EditorThemeClasses, LexicalEditor} from 'lexical';
import invariant from '@lexical/internal/invariant';
import {createContext as createReactContext, useContext} from 'react';
/**
* The context value provided alongside a {@link LexicalEditor} by a
* {@link LexicalComposer}. It exposes a `getTheme()` function that resolves the
* active {@link EditorThemeClasses}, falling back to any parent composer's
* theme.
*/
export type LexicalComposerContextType = {
getTheme: () => EditorThemeClasses | null | undefined;
};
/**
* A tuple of the {@link LexicalEditor} and its
* {@link LexicalComposerContextType}, as stored in {@link LexicalComposerContext}
* and returned by {@link useLexicalComposerContext}.
*/
export type LexicalComposerContextWithEditor = [
LexicalEditor,
LexicalComposerContextType,
];
/**
* The React context used to share the {@link LexicalEditor} and its
* {@link LexicalComposerContextType} with descendant plugins and components.
* Most code should read it through {@link useLexicalComposerContext} rather than
* consuming the context directly.
*/
export const LexicalComposerContext: React.Context<
LexicalComposerContextWithEditor | null | undefined
> =
// 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__ */ createReactContext<
LexicalComposerContextWithEditor | null | undefined
>(null);
/**
* Creates a {@link LexicalComposerContextType} for a composer. Theme resolution
* falls back to the optional `parent` context, so nested composers inherit the
* parent's theme unless they provide their own.
*
* @param parent - The parent composer context to inherit from, if any.
* @param theme - The theme classes for this composer, or `null`/`undefined` to
* inherit from `parent`.
* @returns The new composer context value.
*/
export function createLexicalComposerContext(
parent: LexicalComposerContextWithEditor | null | undefined,
theme: EditorThemeClasses | null | undefined,
): LexicalComposerContextType {
let parentContext: LexicalComposerContextType | null = null;
if (parent != null) {
parentContext = parent[1];
}
function getTheme() {
if (theme != null) {
return theme;
}
return parentContext != null ? parentContext.getTheme() : null;
}
return {
getTheme,
};
}
/**
* Returns the {@link LexicalEditor} and its {@link LexicalComposerContextType}
* from the nearest {@link LexicalComposer} (or nested composer). This is the
* primary way plugins and components access the editor instance.
*
* @returns The `[editor, context]` tuple for the current composer.
* @throws If called outside of a LexicalComposer.
*/
export function useLexicalComposerContext(): LexicalComposerContextWithEditor {
const composerContext = useContext(LexicalComposerContext);
if (composerContext == null) {
invariant(
false,
'LexicalComposerContext.useLexicalComposerContext: cannot find a LexicalComposerContext',
);
}
return composerContext;
}