mirror of
https://github.com/zadam/trilium.git
synced 2026-03-20 19:01:37 +01:00
chore(lexical): start working on a toolbar
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 <div className="divider" />;
|
||||
}
|
||||
|
||||
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 (
|
||||
<div className="toolbar" ref={toolbarRef}>
|
||||
<button
|
||||
disabled={!canUndo}
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(UNDO_COMMAND, undefined);
|
||||
}}
|
||||
className="toolbar-item spaced"
|
||||
aria-label="Undo">
|
||||
<i className="format undo" />
|
||||
</button>
|
||||
<button
|
||||
disabled={!canRedo}
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(REDO_COMMAND, undefined);
|
||||
}}
|
||||
className="toolbar-item"
|
||||
aria-label="Redo">
|
||||
<i className="format redo" />
|
||||
</button>
|
||||
<Divider />
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
|
||||
}}
|
||||
className={`toolbar-item spaced ${ isBold ? 'active' : ''}`}
|
||||
aria-label="Format Bold">
|
||||
<i className="format bold" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
|
||||
}}
|
||||
className={`toolbar-item spaced ${ isItalic ? 'active' : ''}`}
|
||||
aria-label="Format Italics">
|
||||
<i className="format italic" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline');
|
||||
}}
|
||||
className={`toolbar-item spaced ${ isUnderline ? 'active' : ''}`}
|
||||
aria-label="Format Underline">
|
||||
<i className="format underline" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'strikethrough');
|
||||
}}
|
||||
className={`toolbar-item spaced ${ isStrikethrough ? 'active' : ''}`}
|
||||
aria-label="Format Strikethrough">
|
||||
<i className="format strikethrough" />
|
||||
</button>
|
||||
<Divider />
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'left');
|
||||
}}
|
||||
className="toolbar-item spaced"
|
||||
aria-label="Left Align">
|
||||
<i className="format left-align" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'center');
|
||||
}}
|
||||
className="toolbar-item spaced"
|
||||
aria-label="Center Align">
|
||||
<i className="format center-align" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'right');
|
||||
}}
|
||||
className="toolbar-item spaced"
|
||||
aria-label="Right Align">
|
||||
<i className="format right-align" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'justify');
|
||||
}}
|
||||
className="toolbar-item"
|
||||
aria-label="Justify Align">
|
||||
<i className="format justify-align" />
|
||||
</button>{' '}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import { useEffect } from 'preact/hooks';
|
||||
|
||||
import { useEditorSpacedUpdate, useTriliumEvent } from '../../../react/hooks';
|
||||
import { TypeWidgetProps } from "../../type_widget";
|
||||
import ToolbarPlugin from "./ToolbarPlugin";
|
||||
|
||||
const theme = {
|
||||
// Theme styling goes here
|
||||
@@ -40,6 +41,7 @@ export default function LexicalText(props: TypeWidgetProps) {
|
||||
|
||||
return (
|
||||
<LexicalComposer initialConfig={initialConfig}>
|
||||
<ToolbarPlugin />
|
||||
<div className="lexical-wrapper">
|
||||
<RichTextPlugin
|
||||
contentEditable={<ContentEditable /> as never}
|
||||
|
||||
Reference in New Issue
Block a user