diff --git a/apps/client/src/widgets/type_widgets/text/lexical/ToolbarPlugin.css b/apps/client/src/widgets/type_widgets/text/lexical/ToolbarPlugin.css new file mode 100644 index 0000000000..ba1cb82eee --- /dev/null +++ b/apps/client/src/widgets/type_widgets/text/lexical/ToolbarPlugin.css @@ -0,0 +1,86 @@ +.note-detail-editable-text { + .toolbar { + display: flex; + margin-bottom: 1px; + background: #fff; + padding: 4px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + vertical-align: middle; + } + + .toolbar button.toolbar-item { + border: 0; + display: flex; + background: none; + border-radius: 10px; + padding: 8px; + cursor: pointer; + vertical-align: middle; + } + + .toolbar button.toolbar-item:disabled { + cursor: not-allowed; + } + + .toolbar button.toolbar-item.spaced { + margin-right: 2px; + } + + .toolbar button.toolbar-item i.format { + background-size: contain; + display: inline-block; + height: 18px; + width: 18px; + margin-top: 2px; + vertical-align: -0.25em; + display: flex; + opacity: 0.6; + } + + .toolbar button.toolbar-item:disabled i.format { + opacity: 0.2; + } + + .toolbar button.toolbar-item.active { + background-color: rgba(223, 232, 250, 0.3); + } + + .toolbar button.toolbar-item.active i { + opacity: 1; + } + + .toolbar .toolbar-item:hover:not([disabled]) { + background-color: #eee; + } + + .toolbar .divider { + width: 1px; + background-color: #eee; + margin: 0 4px; + } + + .toolbar .toolbar-item .text { + display: flex; + line-height: 20px; + width: 200px; + vertical-align: middle; + font-size: 14px; + color: #777; + text-overflow: ellipsis; + width: 70px; + overflow: hidden; + height: 20px; + text-align: left; + } + + .toolbar .toolbar-item .icon { + display: flex; + width: 20px; + height: 20px; + user-select: none; + margin-right: 8px; + line-height: 16px; + background-size: contain; + } +} diff --git a/apps/client/src/widgets/type_widgets/text/lexical/ToolbarPlugin.tsx b/apps/client/src/widgets/type_widgets/text/lexical/ToolbarPlugin.tsx new file mode 100644 index 0000000000..df3924a41b --- /dev/null +++ b/apps/client/src/widgets/type_widgets/text/lexical/ToolbarPlugin.tsx @@ -0,0 +1,176 @@ +/** + * 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 "./ToolbarPlugin.css"; + +import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext'; +import {mergeRegister} from '@lexical/utils'; +import { + $getSelection, + $isRangeSelection, + CAN_REDO_COMMAND, + CAN_UNDO_COMMAND, + COMMAND_PRIORITY_LOW, + FORMAT_ELEMENT_COMMAND, + FORMAT_TEXT_COMMAND, + REDO_COMMAND, + SELECTION_CHANGE_COMMAND, + UNDO_COMMAND, +} from 'lexical'; +import {useCallback, useEffect, useRef, useState} from 'react'; + +function Divider() { + return
; +} + +export default function ToolbarPlugin() { + const [editor] = useLexicalComposerContext(); + const toolbarRef = useRef(null); + const [canUndo, setCanUndo] = useState(false); + const [canRedo, setCanRedo] = useState(false); + const [isBold, setIsBold] = useState(false); + const [isItalic, setIsItalic] = useState(false); + const [isUnderline, setIsUnderline] = useState(false); + const [isStrikethrough, setIsStrikethrough] = useState(false); + + const $updateToolbar = useCallback(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection)) { + // Update text format + setIsBold(selection.hasFormat('bold')); + setIsItalic(selection.hasFormat('italic')); + setIsUnderline(selection.hasFormat('underline')); + setIsStrikethrough(selection.hasFormat('strikethrough')); + } + }, []); + + useEffect(() => { + return mergeRegister( + editor.registerUpdateListener(({editorState}) => { + editorState.read( + () => { + $updateToolbar(); + }, + {editor}, + ); + }), + editor.registerCommand( + SELECTION_CHANGE_COMMAND, + (_payload, _newEditor) => { + $updateToolbar(); + return false; + }, + COMMAND_PRIORITY_LOW, + ), + editor.registerCommand( + CAN_UNDO_COMMAND, + (payload) => { + setCanUndo(payload); + return false; + }, + COMMAND_PRIORITY_LOW, + ), + editor.registerCommand( + CAN_REDO_COMMAND, + (payload) => { + setCanRedo(payload); + return false; + }, + COMMAND_PRIORITY_LOW, + ), + ); + }, [editor, $updateToolbar]); + + return ( +