Skip to content

Commit

Permalink
update text align and color icon to reflect selection
Browse files Browse the repository at this point in the history
  • Loading branch information
ibastawisi committed Aug 17, 2024
1 parent 1da2b7d commit 8264e50
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/editor/nodes/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function getCSSFromStyleObject(styles: Record<string, string>): string {
export function $getNodeStyleValueForProperty(
node: LexicalNode,
styleProperty: string,
defaultValue: string,
defaultValue: string = '',
): string {
if (!isStylableNode(node)) return defaultValue;
const css = node.getStyle();
Expand Down
70 changes: 50 additions & 20 deletions src/editor/plugins/ToolbarPlugin/Menus/AlignTextMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"use client"
import * as React from 'react';
import { $getSelection, $setSelection, FORMAT_ELEMENT_COMMAND, INDENT_CONTENT_COMMAND, LexicalEditor, OUTDENT_CONTENT_COMMAND } from 'lexical';
import { $getSelection, $isElementNode, $isParagraphNode, $isRangeSelection, $isTextNode, $setSelection, COMMAND_PRIORITY_CRITICAL, ElementFormatType, FORMAT_ELEMENT_COMMAND, INDENT_CONTENT_COMMAND, LexicalEditor, OUTDENT_CONTENT_COMMAND, SELECTION_CHANGE_COMMAND } from 'lexical';
import { IconButton, Menu, MenuItem, ListItemIcon, ListItemText, Divider } from '@mui/material';
import { FormatAlignLeft, FormatAlignCenter, FormatAlignRight, FormatAlignJustify, FormatIndentIncrease, FormatIndentDecrease } from '@mui/icons-material';
import { useCallback } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { getSelectedNode } from '@/editor/utils/getSelectedNode';
import { mergeRegister, $findMatchingParent } from '@lexical/utils';

export default function AlignTextMenu({ editor, isRTL }: { editor: LexicalEditor, isRTL: boolean }): JSX.Element {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
Expand All @@ -28,6 +30,37 @@ export default function AlignTextMenu({ editor, isRTL }: { editor: LexicalEditor
}, 0);
}, [editor]);

const [formatType, setFormatType] = useState<ElementFormatType>('left');
const [indentationLevel, setIndentationLevel] = useState<number>(0);

const $updateToolbar = useCallback(() => {
const selection = $getSelection();
if (!selection) return;
const element = $findMatchingParent($isRangeSelection(selection) ? getSelectedNode(selection) : selection.getNodes()[0], $isElementNode);
if (!element) return;
setFormatType(element.getFormatType() || 'left');
setIndentationLevel(element.getIndent() || 0);
}, [editor]);

useEffect(() => {
return mergeRegister(
editor.registerCommand(
SELECTION_CHANGE_COMMAND,
() => {
$updateToolbar();
return false;
},
COMMAND_PRIORITY_CRITICAL,
),
editor.registerUpdateListener(({ editorState, tags }) => {
editorState.read(() => {
$updateToolbar();
});
}),
);
}, [editor, $updateToolbar]);


return (
<>
<IconButton
Expand All @@ -37,7 +70,10 @@ export default function AlignTextMenu({ editor, isRTL }: { editor: LexicalEditor
aria-expanded={open ? 'true' : undefined}
aria-label='Align Text'
onClick={handleClick}>
<FormatAlignLeft />
{formatType === 'left' && <FormatAlignLeft />}
{formatType === 'center' && <FormatAlignCenter />}
{formatType === 'right' && <FormatAlignRight />}
{formatType === 'justify' && <FormatAlignJustify />}
</IconButton>
<Menu
id="align-menu"
Expand All @@ -57,36 +93,32 @@ export default function AlignTextMenu({ editor, isRTL }: { editor: LexicalEditor
'& .MuiBackdrop-root': { userSelect: 'none' }
}}
>
<MenuItem onClick={() => {
<MenuItem selected={formatType === 'left'} onClick={() => {
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'left');
handleClose();
}}>
<ListItemIcon>
<FormatAlignLeft fontSize="small" />
</ListItemIcon>
<ListItemText>Left Align</ListItemText>
</MenuItem>
<MenuItem onClick={() => {
<MenuItem selected={formatType === 'center'} onClick={() => {
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'center');
handleClose();
}}>
<ListItemIcon>
<FormatAlignCenter fontSize="small" />
</ListItemIcon>
<ListItemText>Center Align</ListItemText>
</MenuItem>
<MenuItem onClick={() => {
<MenuItem selected={formatType === 'right'} onClick={() => {
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'right');
handleClose();
}}>
<ListItemIcon>
<FormatAlignRight fontSize="small" />
</ListItemIcon>
<ListItemText>Right Align</ListItemText>
</MenuItem>
<MenuItem onClick={() => {
<MenuItem selected={formatType === 'justify'} onClick={() => {
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'justify');
handleClose();
}}>
<ListItemIcon>
<FormatAlignJustify fontSize="small" />
Expand All @@ -97,22 +129,20 @@ export default function AlignTextMenu({ editor, isRTL }: { editor: LexicalEditor
<Divider />

<MenuItem onClick={() => {
editor.dispatchCommand(OUTDENT_CONTENT_COMMAND, undefined);
handleClose();
editor.dispatchCommand(INDENT_CONTENT_COMMAND, undefined);
}}>
<ListItemIcon>
{isRTL ? <FormatIndentIncrease fontSize="small" /> : <FormatIndentDecrease fontSize="small" />}
{isRTL ? <FormatIndentDecrease fontSize="small" /> : <FormatIndentIncrease fontSize="small" />}
</ListItemIcon>
<ListItemText>Outdent</ListItemText>
<ListItemText>Indent</ListItemText>
</MenuItem>
<MenuItem onClick={() => {
editor.dispatchCommand(INDENT_CONTENT_COMMAND, undefined);
handleClose();
<MenuItem disabled={indentationLevel === 0} onClick={() => {
editor.dispatchCommand(OUTDENT_CONTENT_COMMAND, undefined);
}}>
<ListItemIcon>
{isRTL ? <FormatIndentDecrease fontSize="small" /> : <FormatIndentIncrease fontSize="small" />}
{isRTL ? <FormatIndentIncrease fontSize="small" /> : <FormatIndentDecrease fontSize="small" />}
</ListItemIcon>
<ListItemText>Indent</ListItemText>
<ListItemText>Outdent</ListItemText>
</MenuItem>
</Menu>
</>
Expand Down
17 changes: 15 additions & 2 deletions src/editor/plugins/ToolbarPlugin/Tools/MathTools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,26 @@ export default function MathTools({ editor, node, sx }: { editor: LexicalEditor,
const isOnline = useOnlineStatus();
const [excalidrawAPI, excalidrawAPIRefCallback] = useCallbackRefState();
const [fontSize, setFontSize] = useState('16px');

const [textColor, setTextColor] = useState<string>();
const [backgroundColor, setBackgroundColor] = useState<string>();
const [loading, setLoading] = useState(false);

useEffect(() => {
editor.getEditorState().read(() => {
const fontSize = $getNodeStyleValueForProperty(node, 'font-size', '16px');
setFontSize(fontSize);
const mathfield = editor.getElementByKey(node.__key)?.querySelector("math-field") as MathfieldElement | null;
if (!mathfield) return;
if (mathfield.selectionIsCollapsed) {
const color = $getNodeStyleValueForProperty(node, 'color');
setTextColor(color);
const backgroundColor = $getNodeStyleValueForProperty(node, 'background-color');
setBackgroundColor(backgroundColor);
} else {
// TODO: implement selection color
setTextColor('');
setBackgroundColor('');
}
});
}, [node]);

Expand Down Expand Up @@ -249,7 +262,7 @@ export default function MathTools({ editor, node, sx }: { editor: LexicalEditor,
<LinearProgress sx={{ visibility: loading ? 'visible' : 'hidden', position: "absolute", bottom: 0, left: 0, right: 0, zIndex: 1000 }} />
</Paper>
</Collapse>}
<ColorPicker onColorChange={onColorChange} onClose={handleClose} />
<ColorPicker onColorChange={onColorChange} onClose={handleClose} textColor={textColor} backgroundColor={backgroundColor} />
</ToggleButtonGroup>
<FontSizePicker fontSize={fontSize} updateFontSize={updateFontSize} onBlur={restoreFocus} />
<ToggleButtonGroup size="small" sx={{ position: "relative", ...sx }} exclusive>
Expand Down
8 changes: 4 additions & 4 deletions src/editor/plugins/ToolbarPlugin/Tools/NoteTools.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client"
import { $getSelection, $setSelection, LexicalEditor, } from "lexical";
import { LexicalEditor, } from "lexical";
import { useEffect, useState } from "react";
import { ToggleButtonGroup, ToggleButton, SvgIcon, Menu, Button, MenuItem, ListItemIcon, ListItemText, Typography, Divider } from "@mui/material";
import { Delete, KeyboardArrowDown, Note } from "@mui/icons-material";
Expand All @@ -25,11 +25,11 @@ export default function NoteTools({ editor, node }: { editor: LexicalEditor, nod

useEffect(() => {
editor.getEditorState().read(() => {
const float = $getNodeStyleValueForProperty(node, 'float', 'left');
const float = $getNodeStyleValueForProperty(node, 'float');
setFloat(float);
const color = $getNodeStyleValueForProperty(node, 'color', 'inherit');
const color = $getNodeStyleValueForProperty(node, 'color');
setTextColor(color);
const backgroundColor = $getNodeStyleValueForProperty(node, 'background-color', '#bceac4');
const backgroundColor = $getNodeStyleValueForProperty(node, 'background-color');
setBackgroundColor(backgroundColor);
});
}, [node]);
Expand Down
7 changes: 5 additions & 2 deletions src/editor/plugins/ToolbarPlugin/Tools/TableTools.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client"
import { $createParagraphNode, $getRoot, $getSelection, $isElementNode, $isParagraphNode, $isRangeSelection, $isTextNode, $setSelection, ElementFormatType, ElementNode, LexicalEditor, } from "lexical";
import { $createParagraphNode, $getSelection, $isElementNode, $isParagraphNode, $isRangeSelection, $isTextNode, $setSelection, ElementFormatType, ElementNode, LexicalEditor, } from "lexical";
import { useCallback, useEffect, useState } from "react";
import { ToggleButtonGroup, ToggleButton, SvgIcon, Menu, Button, MenuItem, ListItemIcon, ListItemText, Typography, Divider } from "@mui/material";
import { ViewHeadline, Delete, KeyboardArrowDown, TableChart } from "@mui/icons-material";
Expand Down Expand Up @@ -208,7 +208,8 @@ export default function TableTools({ editor, node }: { editor: LexicalEditor, no
const [tableCellStyle, setTableCellStyle] = useState<Record<string, string> | null>(null);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);

const textColor = tableCellStyle?.color;
const backgroundColor = tableCellStyle?.['background-color'];

useEffect(() => {
return editor.registerUpdateListener(() => {
Expand Down Expand Up @@ -676,6 +677,8 @@ export default function TableTools({ editor, node }: { editor: LexicalEditor, no
onColorChange={updateCellColor}
toggle="menuitem"
label='Cell color'
textColor={textColor}
backgroundColor={backgroundColor}
/>
<MenuItem onClick={() => toggleTableRowIsHeader()}>
<ListItemIcon>
Expand Down
11 changes: 9 additions & 2 deletions src/editor/plugins/ToolbarPlugin/Tools/TextFormatToggles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useCallback, useEffect, useState } from 'react';
import ColorPicker from './ColorPicker';
import { $isMathNode, MathNode } from '@/editor/nodes/MathNode';
import { $patchStyle } from '@/editor/nodes/utils';

import { $getSelectionStyleValueForProperty } from '@lexical/selection';
import { SxProps, Theme } from '@mui/material/styles';
import { ToggleButtonGroup, ToggleButton, SvgIcon } from '@mui/material';
import { FormatBold, FormatItalic, FormatUnderlined, Code, FormatStrikethrough, Subscript, Superscript, Link } from '@mui/icons-material';
Expand All @@ -21,6 +21,8 @@ const Highlight = () => <SvgIcon viewBox='0 -960 960 960'>

export default function TextFormatToggles({ editor, sx }: { editor: LexicalEditor, sx?: SxProps<Theme> | undefined }): JSX.Element {
const [format, setFormat] = useState<{ [key: string]: boolean }>({});
const [textColor, setTextColor] = useState<string>();
const [backgroundColor, setBackgroundColor] = useState<string>();

const updateToolbar = useCallback(() => {
const selection = $getSelection();
Expand All @@ -38,6 +40,11 @@ export default function TextFormatToggles({ editor, sx }: { editor: LexicalEdito
highlight: selection.hasFormat('highlight'),
link: $isLinkNode(parent) || $isLinkNode(node),
});
const color = $getSelectionStyleValueForProperty(selection, 'color');
setTextColor(color);
const backgroundColor = $getSelectionStyleValueForProperty(selection, 'background-color');
setBackgroundColor(backgroundColor);

}
}, [editor]);

Expand Down Expand Up @@ -153,6 +160,6 @@ export default function TextFormatToggles({ editor, sx }: { editor: LexicalEdito
<ToggleButton value="link" title={IS_APPLE ? 'Insert Link (⌘K)' : 'Insert Link (Ctrl+K)'} aria-label={`Insert a link. Shortcut: ${IS_APPLE ? '⌘K' : 'Ctrl+K'}`} onClick={openLinkDialog}>
<Link />
</ToggleButton>
<ColorPicker onColorChange={onColorChange} />
<ColorPicker onColorChange={onColorChange} textColor={textColor} backgroundColor={backgroundColor} />
</ToggleButtonGroup>)
}

0 comments on commit 8264e50

Please sign in to comment.