UNPKG

@lexical/react

Version:

This package provides Lexical components and hooks for React applications.

132 lines (127 loc) 3.96 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 { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection'; import { addClassNamesToElement, mergeRegister, removeClassNamesFromElement } from '@lexical/utils'; import { createCommand, DecoratorNode, $applyNodeReplacement, $getSelection, $isNodeSelection, CLICK_COMMAND, COMMAND_PRIORITY_LOW, KEY_DELETE_COMMAND, KEY_BACKSPACE_COMMAND } from 'lexical'; import { useCallback, useEffect } from 'react'; import { jsx } from 'react/jsx-runtime'; /** * 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 INSERT_HORIZONTAL_RULE_COMMAND = createCommand('INSERT_HORIZONTAL_RULE_COMMAND'); function HorizontalRuleComponent({ nodeKey }) { const [editor] = useLexicalComposerContext(); const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey); const $onDelete = useCallback(event => { const deleteSelection = $getSelection(); if (isSelected && $isNodeSelection(deleteSelection)) { event.preventDefault(); editor.update(() => { deleteSelection.getNodes().forEach(node => { if ($isHorizontalRuleNode(node)) { node.remove(); } }); }); } return false; }, [editor, isSelected]); useEffect(() => { return mergeRegister(editor.registerCommand(CLICK_COMMAND, event => { const hrElem = editor.getElementByKey(nodeKey); if (event.target === hrElem) { if (!event.shiftKey) { clearSelection(); } setSelected(!isSelected); return true; } return false; }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_DELETE_COMMAND, $onDelete, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_BACKSPACE_COMMAND, $onDelete, COMMAND_PRIORITY_LOW)); }, [clearSelection, editor, isSelected, nodeKey, $onDelete, setSelected]); useEffect(() => { const hrElem = editor.getElementByKey(nodeKey); const isSelectedClassName = 'selected'; if (hrElem !== null) { if (isSelected) { addClassNamesToElement(hrElem, isSelectedClassName); } else { removeClassNamesFromElement(hrElem, isSelectedClassName); } } }, [editor, isSelected, nodeKey]); return null; } class HorizontalRuleNode extends DecoratorNode { static getType() { return 'horizontalrule'; } static clone(node) { return new HorizontalRuleNode(node.__key); } static importJSON(serializedNode) { return $createHorizontalRuleNode(); } static importDOM() { return { hr: () => ({ conversion: $convertHorizontalRuleElement, priority: 0 }) }; } exportJSON() { return { type: 'horizontalrule', version: 1 }; } exportDOM() { return { element: document.createElement('hr') }; } createDOM(config) { const element = document.createElement('hr'); addClassNamesToElement(element, config.theme.hr); return element; } getTextContent() { return '\n'; } isInline() { return false; } updateDOM() { return false; } decorate() { return /*#__PURE__*/jsx(HorizontalRuleComponent, { nodeKey: this.__key }); } } function $convertHorizontalRuleElement() { return { node: $createHorizontalRuleNode() }; } function $createHorizontalRuleNode() { return $applyNodeReplacement(new HorizontalRuleNode()); } function $isHorizontalRuleNode(node) { return node instanceof HorizontalRuleNode; } export { $createHorizontalRuleNode, $isHorizontalRuleNode, HorizontalRuleNode, INSERT_HORIZONTAL_RULE_COMMAND };