Skip to content

Commit

Permalink
Fix Balloon Toolbar (#1341)
Browse files Browse the repository at this point in the history
* fix

* Create afraid-months-grow.md
  • Loading branch information
zbeyens authored Jan 12, 2022
1 parent 4506554 commit 3c3dea4
Show file tree
Hide file tree
Showing 16 changed files with 327 additions and 276 deletions.
13 changes: 13 additions & 0 deletions .changeset/afraid-months-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@udecode/plate-core": patch
"@udecode/plate-ui-alignment": patch
"@udecode/plate-ui-code-block": patch
"@udecode/plate-ui-font": patch
"@udecode/plate-ui-line-height": patch
"@udecode/plate-ui-link": patch
"@udecode/plate-ui-list": patch
"@udecode/plate-ui-table": patch
"@udecode/plate-ui-toolbar": patch
---

Fix components using `usePlateEditorState` by introducing `withEditor` / `EditorProvider` hoc
1 change: 1 addition & 0 deletions packages/core/src/common/hoc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './createNodeHOC';
export * from './createNodesHOC';
export * from './withProps';
export * from './withProviders';
export * from './withHOC';
10 changes: 10 additions & 0 deletions packages/core/src/common/hoc/withHOC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React, { FunctionComponent } from 'react';

export const withHOC = <T,>(
HOC: FunctionComponent<any>,
Component: FunctionComponent<T>
): FunctionComponent<T> => (props: T) => (
<HOC>
<Component {...props} />
</HOC>
);
18 changes: 18 additions & 0 deletions packages/core/src/components/EditorProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React, { FC } from 'react';
import { withHOC } from '../common/hoc/withHOC';
import { usePlateId } from '../stores/plate/selectors/getPlateId';

export const EditorProvider = ({
id,
children,
}: {
id?: string;
children: any;
}) => {
id = usePlateId(id);

return <React.Fragment key={id}>{children}</React.Fragment>;
};

export const withEditor = <T,>(Component: FC<T>) =>
withHOC<T>(EditorProvider, Component);
1 change: 1 addition & 0 deletions packages/core/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

export * from './DefaultLeaf';
export * from './EditablePlugins';
export * from './EditorProvider';
export * from './EditorRefEffect';
export * from './EditorStateEffect';
export * from './Plate';
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
isCollapsed,
someNode,
usePlateEditorState,
withEditor,
} from '@udecode/plate-core';
import { ToolbarButton, ToolbarButtonProps } from '@udecode/plate-ui-toolbar';

Expand All @@ -13,28 +14,26 @@ export interface AlignToolbarButtonProps extends ToolbarButtonProps {
pluginKey?: string;
}

export const AlignToolbarButton = ({
value,
pluginKey = KEY_ALIGN,
...props
}: AlignToolbarButtonProps) => {
const editor = usePlateEditorState()!;
export const AlignToolbarButton = withEditor(
({ value, pluginKey = KEY_ALIGN, ...props }: AlignToolbarButtonProps) => {
const editor = usePlateEditorState()!;

return (
<ToolbarButton
active={
isCollapsed(editor?.selection) &&
someNode(editor!, { match: { [pluginKey]: value } })
}
onMouseDown={
editor
? getPreventDefaultHandler(setAlign, editor, {
value,
key: pluginKey,
})
: undefined
}
{...props}
/>
);
};
return (
<ToolbarButton
active={
isCollapsed(editor?.selection) &&
someNode(editor!, { match: { [pluginKey]: value } })
}
onMouseDown={
editor
? getPreventDefaultHandler(setAlign, editor, {
value,
key: pluginKey,
})
: undefined
}
{...props}
/>
);
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,34 @@ import {
getPluginType,
getPreventDefaultHandler,
usePlateEditorState,
withEditor,
} from '@udecode/plate-core';
import {
BlockToolbarButton,
ToolbarButtonProps,
} from '@udecode/plate-ui-toolbar';

export const CodeBlockToolbarButton = ({
options,
...props
}: ToolbarButtonProps & {
options?: CodeBlockInsertOptions;
}) => {
const editor = usePlateEditorState()!;
if (!editor) {
return null;
}
export const CodeBlockToolbarButton = withEditor(
({
options,
...props
}: ToolbarButtonProps & {
options?: CodeBlockInsertOptions;
}) => {
const editor = usePlateEditorState()!;
if (!editor) {
return null;
}

return (
<BlockToolbarButton
type={getPluginType(editor, ELEMENT_CODE_BLOCK)}
onMouseDown={getPreventDefaultHandler(insertEmptyCodeBlock, editor, {
insertNodesOptions: { select: true },
...options,
})}
{...props}
/>
);
};
return (
<BlockToolbarButton
type={getPluginType(editor, ELEMENT_CODE_BLOCK)}
onMouseDown={getPreventDefaultHandler(insertEmptyCodeBlock, editor, {
insertNodesOptions: { select: true },
...options,
})}
{...props}
/>
);
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
setMarks,
usePlateEditorRef,
usePlateEditorState,
withEditor,
} from '@udecode/plate-core';
import {
ToolbarButton,
Expand All @@ -28,93 +29,95 @@ type ColorPickerToolbarDropdownProps = {
closeOnSelect?: boolean;
};

export const ColorPickerToolbarDropdown = ({
pluginKey,
icon,
selectedIcon,
colors = DEFAULT_COLORS,
customColors = DEFAULT_CUSTOM_COLORS,
closeOnSelect = true,
...rest
}: ColorPickerToolbarDropdownProps & ToolbarButtonProps) => {
const [open, setOpen] = useState(false);
const editor = usePlateEditorState()!;
const editorRef = usePlateEditorRef()!;
export const ColorPickerToolbarDropdown = withEditor(
({
pluginKey,
icon,
selectedIcon,
colors = DEFAULT_COLORS,
customColors = DEFAULT_CUSTOM_COLORS,
closeOnSelect = true,
...rest
}: ColorPickerToolbarDropdownProps & ToolbarButtonProps) => {
const [open, setOpen] = useState(false);
const editor = usePlateEditorState()!;
const editorRef = usePlateEditorRef()!;

const type = getPluginType(editorRef, pluginKey);
const type = getPluginType(editorRef, pluginKey);

const color = editorRef && getMark(editorRef, type);
const color = editorRef && getMark(editorRef, type);

const [selectedColor, setSelectedColor] = useState<string>();
const [selectedColor, setSelectedColor] = useState<string>();

const onToggle = useCallback(() => {
setOpen(!open);
}, [open, setOpen]);
const onToggle = useCallback(() => {
setOpen(!open);
}, [open, setOpen]);

const updateColor = useCallback(
(value: string) => {
if (editorRef && editor && editor.selection) {
setSelectedColor(value);
const updateColor = useCallback(
(value: string) => {
if (editorRef && editor && editor.selection) {
setSelectedColor(value);

Transforms.select(editorRef, editor.selection);
ReactEditor.focus(editorRef);
Transforms.select(editorRef, editor.selection);
ReactEditor.focus(editorRef);

setMarks(editor, { [type]: value });
}
},
[editor, editorRef, type]
);
setMarks(editor, { [type]: value });
}
},
[editor, editorRef, type]
);

const updateColorAndClose = useCallback(
(value: string) => {
updateColor(value);
closeOnSelect && onToggle();
},
[closeOnSelect, onToggle, updateColor]
);
const updateColorAndClose = useCallback(
(value: string) => {
updateColor(value);
closeOnSelect && onToggle();
},
[closeOnSelect, onToggle, updateColor]
);

const clearColor = useCallback(() => {
if (editorRef && editor && editor.selection) {
Transforms.select(editorRef, editor.selection);
ReactEditor.focus(editorRef);

if (selectedColor) {
removeMark(editor, { key: type });
}
const clearColor = useCallback(() => {
if (editorRef && editor && editor.selection) {
Transforms.select(editorRef, editor.selection);
ReactEditor.focus(editorRef);

closeOnSelect && onToggle();
}
}, [closeOnSelect, editor, editorRef, onToggle, selectedColor, type]);
if (selectedColor) {
removeMark(editor, { key: type });
}

useEffect(() => {
if (editor?.selection) {
setSelectedColor(color);
}
}, [color, editor?.selection]);
closeOnSelect && onToggle();
}
}, [closeOnSelect, editor, editorRef, onToggle, selectedColor, type]);

return (
<ToolbarDropdown
control={
<ToolbarButton
active={!!editor?.selection && isMarkActive(editor, type)}
icon={icon}
{...rest}
/>
useEffect(() => {
if (editor?.selection) {
setSelectedColor(color);
}
open={open}
onOpen={onToggle}
onClose={onToggle}
>
<ColorPicker
color={selectedColor || color}
colors={colors}
customColors={customColors}
selectedIcon={selectedIcon}
updateColor={updateColorAndClose}
updateCustomColor={updateColor}
clearColor={clearColor}
}, [color, editor?.selection]);

return (
<ToolbarDropdown
control={
<ToolbarButton
active={!!editor?.selection && isMarkActive(editor, type)}
icon={icon}
{...rest}
/>
}
open={open}
/>
</ToolbarDropdown>
);
};
onOpen={onToggle}
onClose={onToggle}
>
<ColorPicker
color={selectedColor || color}
colors={colors}
customColors={customColors}
selectedIcon={selectedIcon}
updateColor={updateColorAndClose}
updateCustomColor={updateColor}
clearColor={clearColor}
open={open}
/>
</ToolbarDropdown>
);
}
);
Loading

1 comment on commit 3c3dea4

@vercel
Copy link

@vercel vercel bot commented on 3c3dea4 Jan 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.