From 289c8e716f539ab5f2b8bb5b0982f4f58714ddfa Mon Sep 17 00:00:00 2001 From: Ziad Beyens Date: Sun, 13 Mar 2022 16:45:29 +0100 Subject: [PATCH] Fix selection on focus (#1435) * fix * Create stupid-readers-fetch.md * Create popular-months-obey.md * fix * fix --- .changeset/popular-months-obey.md | 9 +++++ .changeset/stupid-readers-fetch.md | 11 +++++ docs/docs/guides/multiple-editors.mdx | 3 +- packages/core/src/common/hoc/index.ts | 2 +- packages/core/src/common/hoc/withHOC.tsx | 5 ++- .../src/components/PlateEventProvider.tsx | 19 +++++++++ .../core/src/components/PlateProvider.tsx | 16 +++----- packages/core/src/components/index.ts | 3 +- packages/core/src/hooks/index.ts | 2 +- packages/core/src/hooks/usePlate/index.ts | 1 + .../core/src/hooks/usePlatesStoreEffect.ts | 26 ++---------- .../core/src/stores/event-editor/index.ts | 1 + .../selectors/getEventEditorId.ts | 13 ++++++ .../stores/event-editor/selectors/index.ts | 7 ++++ .../selectors/useEventEditorId.ts | 14 +++++++ .../event-editor/selectors/useEventPlateId.ts | 9 +++++ packages/core/src/stores/index.ts | 2 +- .../src/stores/plate/selectors/getPlateId.ts | 40 ------------------- .../core/src/stores/plate/selectors/index.ts | 2 +- .../src/stores/plate/selectors/usePlateId.ts | 11 +++++ .../core/src/stores/plate/usePlateStore.ts | 8 ++-- .../createEditorWithMentions.tsx | 0 packages/nodes/mention/src/handlers/index.ts | 4 ++ .../handlers/mentionOnKeyDownHandler.spec.tsx | 2 +- packages/nodes/mention/src/index.ts | 2 +- .../nodes/mention/src/withMention.spec.tsx | 2 +- .../AlignToolbarButton/AlignToolbarButton.tsx | 10 +++-- .../CodeBlockToolbarButton.tsx | 9 +++-- .../ColorPickerToolbarDropdown.tsx | 12 ++++-- .../ImageToolbarButton/ImageToolbarButton.tsx | 3 +- .../LineHeightToolbarDropdown.tsx | 10 +++-- .../LinkToolbarButton/LinkToolbarButton.tsx | 10 +++-- .../ListToolbarButton/ListToolbarButton.tsx | 14 +++++-- .../MediaEmbedToolbarButton.tsx | 3 +- .../TableToolbarButton/TableToolbarButton.tsx | 10 +++-- .../src/BalloonToolbar/BalloonToolbar.tsx | 4 +- .../BalloonToolbar/useBalloonToolbarPopper.ts | 22 ++++++++-- .../BlockToolbarButton/BlockToolbarButton.tsx | 10 +++-- .../MarkToolbarButton/MarkToolbarButton.tsx | 10 +++-- .../src/ToolbarButton/ToolbarButton.types.ts | 2 + 40 files changed, 215 insertions(+), 128 deletions(-) create mode 100644 .changeset/popular-months-obey.md create mode 100644 .changeset/stupid-readers-fetch.md create mode 100644 packages/core/src/components/PlateEventProvider.tsx create mode 100644 packages/core/src/stores/event-editor/selectors/getEventEditorId.ts create mode 100644 packages/core/src/stores/event-editor/selectors/index.ts create mode 100644 packages/core/src/stores/event-editor/selectors/useEventEditorId.ts create mode 100644 packages/core/src/stores/event-editor/selectors/useEventPlateId.ts delete mode 100644 packages/core/src/stores/plate/selectors/getPlateId.ts create mode 100644 packages/core/src/stores/plate/selectors/usePlateId.ts rename packages/nodes/mention/src/{testing => __tests__}/createEditorWithMentions.tsx (100%) diff --git a/.changeset/popular-months-obey.md b/.changeset/popular-months-obey.md new file mode 100644 index 0000000000..e73df37822 --- /dev/null +++ b/.changeset/popular-months-obey.md @@ -0,0 +1,9 @@ +--- +"@udecode/plate-ui-alignment": minor +"@udecode/plate-ui-code-block": minor +"@udecode/plate-ui-font": minor +"@udecode/plate-ui-image": minor +"@udecode/plate-ui-line-height": minor +--- + +new prop: editor `id` diff --git a/.changeset/stupid-readers-fetch.md b/.changeset/stupid-readers-fetch.md new file mode 100644 index 0000000000..b27d4690ad --- /dev/null +++ b/.changeset/stupid-readers-fetch.md @@ -0,0 +1,11 @@ +--- +"@udecode/plate-core": minor +--- + +Fix a critical issue when using multiple editors #1352 +- `withHOC`: 3rd parameter can be used to add props to HOC. +- `usePlateId` now just gets plate id atom value and no longer gets event editor id as fallback. +- `useEventEditorId`: Get last event editor id: focus, blur or last. +- `useEventPlateId`: Get provider plate id or event editor id. +- `PlateEventProvider`: `PlateProvider` where id is the event editor id (used for toolbar buttons). +- `withPlateEventProvider` diff --git a/docs/docs/guides/multiple-editors.mdx b/docs/docs/guides/multiple-editors.mdx index 634535ca8b..e03c340757 100644 --- a/docs/docs/guides/multiple-editors.mdx +++ b/docs/docs/guides/multiple-editors.mdx @@ -34,7 +34,6 @@ Let's render 3 editors with common heading and balloon toolbars. -
diff --git a/packages/core/src/common/hoc/index.ts b/packages/core/src/common/hoc/index.ts index 9749e7bf6e..a178e8ec0c 100644 --- a/packages/core/src/common/hoc/index.ts +++ b/packages/core/src/common/hoc/index.ts @@ -4,6 +4,6 @@ export * from './createNodeHOC'; export * from './createNodesHOC'; +export * from './withHOC'; export * from './withProps'; export * from './withProviders'; -export * from './withHOC'; diff --git a/packages/core/src/common/hoc/withHOC.tsx b/packages/core/src/common/hoc/withHOC.tsx index ecdf8e3d4c..bbcc98934a 100644 --- a/packages/core/src/common/hoc/withHOC.tsx +++ b/packages/core/src/common/hoc/withHOC.tsx @@ -2,9 +2,10 @@ import React, { FunctionComponent } from 'react'; export const withHOC = ( HOC: FunctionComponent, - Component: FunctionComponent + Component: FunctionComponent, + hocProps?: any ): FunctionComponent => (props: T) => ( - + ); diff --git a/packages/core/src/components/PlateEventProvider.tsx b/packages/core/src/components/PlateEventProvider.tsx new file mode 100644 index 0000000000..95dbb3d01e --- /dev/null +++ b/packages/core/src/components/PlateEventProvider.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { withHOC } from '../common/hoc/withHOC'; +import { useEventPlateId } from '../stores/event-editor/selectors/useEventPlateId'; +import { PlateProvider } from './PlateProvider'; + +export const PlateEventProvider = ({ + id, + children, +}: { + id?: string; + children: any; +}) => { + id = useEventPlateId(id); + + return {children}; +}; + +export const withPlateEventProvider = (Component: FC, hocProps?: T) => + withHOC(PlateEventProvider, Component, hocProps); diff --git a/packages/core/src/components/PlateProvider.tsx b/packages/core/src/components/PlateProvider.tsx index b794a362bd..ae0defcf48 100644 --- a/packages/core/src/components/PlateProvider.tsx +++ b/packages/core/src/components/PlateProvider.tsx @@ -1,27 +1,23 @@ import React, { FC } from 'react'; -import { castArray } from 'lodash'; import { withHOC } from '../common/hoc/withHOC'; import { usePlatesStoreEffect } from '../hooks/usePlatesStoreEffect'; import { usePlatesSelectors } from '../stores/plate/platesStore'; export const PlateProvider = ({ - id: _ids = 'main', + id = 'main', children, }: { - id?: string | string[]; + id?: string; children: any; }) => { - const ids = castArray(_ids) ?? ['main']; - const id = ids[0]; + const hasId = usePlatesSelectors.has(id); - const hasId = usePlatesSelectors.has(ids); - - usePlatesStoreEffect(_ids); + usePlatesStoreEffect(id); if (!hasId) return null; return {children}; }; -export const withPlateProvider = (Component: FC) => - withHOC(PlateProvider, Component); +export const withPlateProvider = (Component: FC, hocProps?: T) => + withHOC(PlateProvider, Component, hocProps); diff --git a/packages/core/src/components/index.ts b/packages/core/src/components/index.ts index 3c27462303..08fc78c403 100644 --- a/packages/core/src/components/index.ts +++ b/packages/core/src/components/index.ts @@ -4,8 +4,9 @@ export * from './DefaultLeaf'; export * from './EditablePlugins'; -export * from './PlateProvider'; export * from './EditorRefEffect'; export * from './EditorStateEffect'; export * from './Plate'; +export * from './PlateEventProvider'; +export * from './PlateProvider'; export * from './PlateTest'; diff --git a/packages/core/src/hooks/index.ts b/packages/core/src/hooks/index.ts index 9cbc627f8e..afd435e21d 100644 --- a/packages/core/src/hooks/index.ts +++ b/packages/core/src/hooks/index.ts @@ -4,5 +4,5 @@ export * from './useEditorRef'; export * from './useEditorState'; -export * from './usePlate/index'; export * from './usePlatesStoreEffect'; +export * from './usePlate/index'; diff --git a/packages/core/src/hooks/usePlate/index.ts b/packages/core/src/hooks/usePlate/index.ts index f23772a3c2..600bdef6cb 100644 --- a/packages/core/src/hooks/usePlate/index.ts +++ b/packages/core/src/hooks/usePlate/index.ts @@ -5,4 +5,5 @@ export * from './useEditableProps'; export * from './usePlate'; export * from './usePlateEffects'; +export * from './usePlateStoreEffects'; export * from './useSlateProps'; diff --git a/packages/core/src/hooks/usePlatesStoreEffect.ts b/packages/core/src/hooks/usePlatesStoreEffect.ts index 64751c88fe..4fe837a06e 100644 --- a/packages/core/src/hooks/usePlatesStoreEffect.ts +++ b/packages/core/src/hooks/usePlatesStoreEffect.ts @@ -1,34 +1,16 @@ import { useEffect } from 'react'; -import { castArray } from 'lodash'; import { PlateProps } from '../components/Plate'; import { platesActions, platesSelectors } from '../stores/plate/platesStore'; -import { usePlateId } from '../stores/plate/selectors/getPlateId'; /** * On mount: create plate store and set it to the plates store. * If id is not defined, event id is used. */ -export const usePlatesStoreEffect = ( - _ids?: string | string[], - props?: PlateProps -) => { - const __ids = castArray(_ids); - const id = usePlateId(__ids[0]); - +export const usePlatesStoreEffect = (id?: string, props?: PlateProps) => { useEffect(() => { - // Set multiple plate stores - if (Array.isArray(_ids)) { - const ids = castArray(_ids); - - ids.forEach((_id) => { - if (!platesSelectors.has(_id)) { - platesActions.set(_id, props); - } - }); - } else if (!platesSelectors.has(id)) { - platesActions.set(id, props); + if (!platesSelectors.has(id)) { + platesActions.set(id!, props); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [_ids, id]); + }, [id]); }; diff --git a/packages/core/src/stores/event-editor/index.ts b/packages/core/src/stores/event-editor/index.ts index ddee975b1b..6d1e85d1d3 100644 --- a/packages/core/src/stores/event-editor/index.ts +++ b/packages/core/src/stores/event-editor/index.ts @@ -3,3 +3,4 @@ */ export * from './event-editor.store'; +export * from './selectors/index'; diff --git a/packages/core/src/stores/event-editor/selectors/getEventEditorId.ts b/packages/core/src/stores/event-editor/selectors/getEventEditorId.ts new file mode 100644 index 0000000000..6347dd8902 --- /dev/null +++ b/packages/core/src/stores/event-editor/selectors/getEventEditorId.ts @@ -0,0 +1,13 @@ +import { eventEditorSelectors } from '../event-editor.store'; + +export const getEventEditorId = (id?: string) => { + if (id) return id; + + const focus = eventEditorSelectors.focus(); + if (focus) return focus; + + const blur = eventEditorSelectors.blur(); + if (blur) return blur; + + return eventEditorSelectors.last() ?? 'main'; +}; diff --git a/packages/core/src/stores/event-editor/selectors/index.ts b/packages/core/src/stores/event-editor/selectors/index.ts new file mode 100644 index 0000000000..9a1a496200 --- /dev/null +++ b/packages/core/src/stores/event-editor/selectors/index.ts @@ -0,0 +1,7 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './getEventEditorId'; +export * from './useEventEditorId'; +export * from './useEventPlateId'; diff --git a/packages/core/src/stores/event-editor/selectors/useEventEditorId.ts b/packages/core/src/stores/event-editor/selectors/useEventEditorId.ts new file mode 100644 index 0000000000..25efe99026 --- /dev/null +++ b/packages/core/src/stores/event-editor/selectors/useEventEditorId.ts @@ -0,0 +1,14 @@ +import { useEventEditorSelectors } from '../event-editor.store'; + +/** + * Get last event editor id: focus, blur or last. + */ +export const useEventEditorId = () => { + const focus = useEventEditorSelectors.focus(); + const blur = useEventEditorSelectors.blur(); + const last = useEventEditorSelectors.last(); + + if (focus) return focus; + if (blur) return blur; + return last; +}; diff --git a/packages/core/src/stores/event-editor/selectors/useEventPlateId.ts b/packages/core/src/stores/event-editor/selectors/useEventPlateId.ts new file mode 100644 index 0000000000..0f43a61b3e --- /dev/null +++ b/packages/core/src/stores/event-editor/selectors/useEventPlateId.ts @@ -0,0 +1,9 @@ +import { usePlateId } from '../../plate/selectors/usePlateId'; +import { useEventEditorId } from './useEventEditorId'; + +export const useEventPlateId = (id?: string) => { + const plateId = usePlateId(); + const eventEditorId = useEventEditorId(); + + return id ?? plateId ?? eventEditorId ?? 'main'; +}; diff --git a/packages/core/src/stores/index.ts b/packages/core/src/stores/index.ts index 6d1b8ea3e3..e50c5a8cca 100644 --- a/packages/core/src/stores/index.ts +++ b/packages/core/src/stores/index.ts @@ -2,6 +2,6 @@ * @file Automatically generated by barrelsby. */ +export * from './plateIdAtom'; export * from './event-editor/index'; export * from './plate/index'; -export { plateIdAtom } from './plateIdAtom'; diff --git a/packages/core/src/stores/plate/selectors/getPlateId.ts b/packages/core/src/stores/plate/selectors/getPlateId.ts deleted file mode 100644 index 0c0cdb2d05..0000000000 --- a/packages/core/src/stores/plate/selectors/getPlateId.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { useAtom } from 'jotai'; -import { - eventEditorSelectors, - useEventEditorSelectors, -} from '../../event-editor/event-editor.store'; -import { plateIdAtom } from '../../plateIdAtom'; - -/** - * - Get the last focused editor id if any - * - Else, get the last blurred editor id if any - * - Else, get the last editor id if any - * - Else, `null` - */ -export const getPlateId = (id?: string): string => { - if (id) return id; - - const focus = eventEditorSelectors.focus?.(); - if (focus) return focus; - - const blur = eventEditorSelectors.blur?.(); - if (blur) return blur; - - const last = eventEditorSelectors.last?.(); - return last ?? 'main'; -}; - -export const usePlateId = (id?: string): string => { - const [plateId] = useAtom(plateIdAtom); - - const focus = useEventEditorSelectors.focus(); - const blur = useEventEditorSelectors.blur(); - const last = useEventEditorSelectors.last(); - - if (id) return id; - if (plateId) return plateId; - if (focus) return focus; - if (blur) return blur; - - return last ?? 'main'; -}; diff --git a/packages/core/src/stores/plate/selectors/index.ts b/packages/core/src/stores/plate/selectors/index.ts index cc6d8c73d8..9cb56e093a 100644 --- a/packages/core/src/stores/plate/selectors/index.ts +++ b/packages/core/src/stores/plate/selectors/index.ts @@ -2,8 +2,8 @@ * @file Automatically generated by barrelsby. */ -export * from './getPlateId'; export * from './usePlateEditorRef'; export * from './usePlateEditorState'; +export * from './usePlateId'; export * from './usePlatePlugins'; export * from './usePlateSelection'; diff --git a/packages/core/src/stores/plate/selectors/usePlateId.ts b/packages/core/src/stores/plate/selectors/usePlateId.ts new file mode 100644 index 0000000000..3e2b8be06f --- /dev/null +++ b/packages/core/src/stores/plate/selectors/usePlateId.ts @@ -0,0 +1,11 @@ +import { useAtom } from 'jotai'; +import { plateIdAtom } from '../../plateIdAtom'; + +/** + * Get plate editor id provided by PlateProvider. + */ +export const usePlateId = () => { + const [plateId] = useAtom(plateIdAtom); + + return plateId; +}; diff --git a/packages/core/src/stores/plate/usePlateStore.ts b/packages/core/src/stores/plate/usePlateStore.ts index f7e1962ba7..ad058f16bf 100644 --- a/packages/core/src/stores/plate/usePlateStore.ts +++ b/packages/core/src/stores/plate/usePlateStore.ts @@ -1,5 +1,6 @@ import { PlateStoreApi } from '../../types/PlateStore'; -import { getPlateId, usePlateId } from './selectors/getPlateId'; +import { getEventEditorId } from '../event-editor/selectors/getEventEditorId'; +import { usePlateId } from './selectors/usePlateId'; import { createPlateStore } from './createPlateStore'; import { platesStore } from './platesStore'; @@ -8,7 +9,7 @@ const loadingStore = createPlateStore({ }); export const getPlateStore = (id?: string): PlateStoreApi => { - id = getPlateId(id); + id = getEventEditorId(id); const store = platesStore.get.get(id); @@ -16,7 +17,8 @@ export const getPlateStore = (id?: string): PlateStoreApi => { }; export const usePlateStore = (id?: string): PlateStoreApi => { - id = usePlateId(id); + const plateId = usePlateId(); + id = id ?? plateId ?? 'main'; const store = platesStore.use.get(id); diff --git a/packages/nodes/mention/src/testing/createEditorWithMentions.tsx b/packages/nodes/mention/src/__tests__/createEditorWithMentions.tsx similarity index 100% rename from packages/nodes/mention/src/testing/createEditorWithMentions.tsx rename to packages/nodes/mention/src/__tests__/createEditorWithMentions.tsx diff --git a/packages/nodes/mention/src/handlers/index.ts b/packages/nodes/mention/src/handlers/index.ts index 599769c36a..93f53b6c1d 100644 --- a/packages/nodes/mention/src/handlers/index.ts +++ b/packages/nodes/mention/src/handlers/index.ts @@ -1,3 +1,7 @@ +/** + * @file Automatically generated by barrelsby. + */ + export * from './KeyboardEventHandler'; export * from './mentionOnKeyDownHandler'; export * from './moveSelectionByOffset'; diff --git a/packages/nodes/mention/src/handlers/mentionOnKeyDownHandler.spec.tsx b/packages/nodes/mention/src/handlers/mentionOnKeyDownHandler.spec.tsx index 18b6b465fb..1c2fc556e7 100644 --- a/packages/nodes/mention/src/handlers/mentionOnKeyDownHandler.spec.tsx +++ b/packages/nodes/mention/src/handlers/mentionOnKeyDownHandler.spec.tsx @@ -1,7 +1,7 @@ /** @jsx jsx */ import { jsx } from '@udecode/plate-test-utils'; -import { createEditorWithMentions } from '../testing/createEditorWithMentions'; +import { createEditorWithMentions } from '../__tests__/createEditorWithMentions'; import { mentionOnKeyDownHandler } from './mentionOnKeyDownHandler'; jsx; diff --git a/packages/nodes/mention/src/index.ts b/packages/nodes/mention/src/index.ts index a215ade019..d1612be983 100644 --- a/packages/nodes/mention/src/index.ts +++ b/packages/nodes/mention/src/index.ts @@ -4,8 +4,8 @@ export * from './createMentionPlugin'; export * from './getMentionOnSelectItem'; -export * from './handlers'; export * from './types'; export * from './withMention'; +export * from './handlers/index'; export * from './queries/index'; export * from './transforms/index'; diff --git a/packages/nodes/mention/src/withMention.spec.tsx b/packages/nodes/mention/src/withMention.spec.tsx index a76693da6d..37e883dabb 100644 --- a/packages/nodes/mention/src/withMention.spec.tsx +++ b/packages/nodes/mention/src/withMention.spec.tsx @@ -8,7 +8,7 @@ import { import { PlateEditor } from '@udecode/plate-core'; import { jsx } from '@udecode/plate-test-utils'; import { Range, Transforms } from 'slate'; -import { createEditorWithMentions } from './testing/createEditorWithMentions'; +import { createEditorWithMentions } from './__tests__/createEditorWithMentions'; import { getMentionOnSelectItem } from './getMentionOnSelectItem'; import { withMention } from './withMention'; diff --git a/packages/ui/nodes/alignment/src/AlignToolbarButton/AlignToolbarButton.tsx b/packages/ui/nodes/alignment/src/AlignToolbarButton/AlignToolbarButton.tsx index 9a23e50981..be14b64a75 100644 --- a/packages/ui/nodes/alignment/src/AlignToolbarButton/AlignToolbarButton.tsx +++ b/packages/ui/nodes/alignment/src/AlignToolbarButton/AlignToolbarButton.tsx @@ -4,8 +4,9 @@ import { getPreventDefaultHandler, isCollapsed, someNode, + useEventPlateId, usePlateEditorState, - withPlateProvider, + withPlateEventProvider, } from '@udecode/plate-core'; import { ToolbarButton, ToolbarButtonProps } from '@udecode/plate-ui-toolbar'; @@ -14,9 +15,10 @@ export interface AlignToolbarButtonProps extends ToolbarButtonProps { pluginKey?: string; } -export const AlignToolbarButton = withPlateProvider( - ({ value, pluginKey = KEY_ALIGN, ...props }: AlignToolbarButtonProps) => { - const editor = usePlateEditorState()!; +export const AlignToolbarButton = withPlateEventProvider( + ({ id, value, pluginKey = KEY_ALIGN, ...props }: AlignToolbarButtonProps) => { + id = useEventPlateId(id); + const editor = usePlateEditorState(id)!; return ( { - const editor = usePlateEditorState()!; + id = useEventPlateId(id); + const editor = usePlateEditorState(id)!; if (!editor) { return null; } diff --git a/packages/ui/nodes/font/src/ColorPickerToolbarDropdown/ColorPickerToolbarDropdown.tsx b/packages/ui/nodes/font/src/ColorPickerToolbarDropdown/ColorPickerToolbarDropdown.tsx index 6578dd5e96..dad49cdf6f 100644 --- a/packages/ui/nodes/font/src/ColorPickerToolbarDropdown/ColorPickerToolbarDropdown.tsx +++ b/packages/ui/nodes/font/src/ColorPickerToolbarDropdown/ColorPickerToolbarDropdown.tsx @@ -5,9 +5,10 @@ import { isMarkActive, removeMark, setMarks, + useEventPlateId, usePlateEditorRef, usePlateEditorState, - withPlateProvider, + withPlateEventProvider, } from '@udecode/plate-core'; import { ToolbarButton, @@ -29,8 +30,9 @@ type ColorPickerToolbarDropdownProps = { closeOnSelect?: boolean; }; -export const ColorPickerToolbarDropdown = withPlateProvider( +export const ColorPickerToolbarDropdown = withPlateEventProvider( ({ + id, pluginKey, icon, selectedIcon, @@ -39,9 +41,11 @@ export const ColorPickerToolbarDropdown = withPlateProvider( closeOnSelect = true, ...rest }: ColorPickerToolbarDropdownProps & ToolbarButtonProps) => { + id = useEventPlateId(id); + const editor = usePlateEditorState(id)!; + const editorRef = usePlateEditorRef(id)!; + const [open, setOpen] = useState(false); - const editor = usePlateEditorState()!; - const editorRef = usePlateEditorRef()!; const type = getPluginType(editorRef, pluginKey); diff --git a/packages/ui/nodes/image/src/ImageToolbarButton/ImageToolbarButton.tsx b/packages/ui/nodes/image/src/ImageToolbarButton/ImageToolbarButton.tsx index c3e2a42b9c..6719f001a7 100644 --- a/packages/ui/nodes/image/src/ImageToolbarButton/ImageToolbarButton.tsx +++ b/packages/ui/nodes/image/src/ImageToolbarButton/ImageToolbarButton.tsx @@ -11,10 +11,11 @@ export interface ImageToolbarButtonProps extends ToolbarButtonProps { } export const ImageToolbarButton = ({ + id, getImageUrl, ...props }: ImageToolbarButtonProps) => { - const editor = usePlateEditorRef()!; + const editor = usePlateEditorRef(id)!; return ( { + let { id } = props; + id = useEventPlateId(id); + const editor = usePlateEditorState(id)!; + const [open, setOpen] = React.useState(false); - const editor = usePlateEditorState()!; const { validNodeValues } = getPluginInjectProps(editor, KEY_LINE_HEIGHT); diff --git a/packages/ui/nodes/link/src/LinkToolbarButton/LinkToolbarButton.tsx b/packages/ui/nodes/link/src/LinkToolbarButton/LinkToolbarButton.tsx index 67b001c9f3..ab86ffdfc5 100644 --- a/packages/ui/nodes/link/src/LinkToolbarButton/LinkToolbarButton.tsx +++ b/packages/ui/nodes/link/src/LinkToolbarButton/LinkToolbarButton.tsx @@ -2,8 +2,9 @@ import React from 'react'; import { getPluginType, someNode, + useEventPlateId, usePlateEditorState, - withPlateProvider, + withPlateEventProvider, } from '@udecode/plate-core'; import { ELEMENT_LINK, getAndUpsertLink } from '@udecode/plate-link'; import { ToolbarButton, ToolbarButtonProps } from '@udecode/plate-ui-toolbar'; @@ -15,9 +16,10 @@ export interface LinkToolbarButtonProps extends ToolbarButtonProps { getLinkUrl?: (prevUrl: string | null) => Promise; } -export const LinkToolbarButton = withPlateProvider( - ({ getLinkUrl, ...props }: LinkToolbarButtonProps) => { - const editor = usePlateEditorState()!; +export const LinkToolbarButton = withPlateEventProvider( + ({ id, getLinkUrl, ...props }: LinkToolbarButtonProps) => { + id = useEventPlateId(id); + const editor = usePlateEditorState(id)!; const type = getPluginType(editor, ELEMENT_LINK); const isLink = !!editor?.selection && someNode(editor, { match: { type } }); diff --git a/packages/ui/nodes/list/src/ListToolbarButton/ListToolbarButton.tsx b/packages/ui/nodes/list/src/ListToolbarButton/ListToolbarButton.tsx index 4252853c4c..57baf7af96 100644 --- a/packages/ui/nodes/list/src/ListToolbarButton/ListToolbarButton.tsx +++ b/packages/ui/nodes/list/src/ListToolbarButton/ListToolbarButton.tsx @@ -1,8 +1,9 @@ import React from 'react'; import { getPreventDefaultHandler, + useEventPlateId, usePlateEditorState, - withPlateProvider, + withPlateEventProvider, } from '@udecode/plate-core'; import { ELEMENT_UL, getListItemEntry, toggleList } from '@udecode/plate-list'; import { @@ -10,9 +11,14 @@ import { ToolbarButtonProps, } from '@udecode/plate-ui-toolbar'; -export const ListToolbarButton = withPlateProvider( - ({ type = ELEMENT_UL, ...props }: ToolbarButtonProps & { type?: string }) => { - const editor = usePlateEditorState()!; +export const ListToolbarButton = withPlateEventProvider( + ({ + id, + type = ELEMENT_UL, + ...props + }: ToolbarButtonProps & { type?: string }) => { + id = useEventPlateId(id); + const editor = usePlateEditorState(id)!; const res = !!editor?.selection && getListItemEntry(editor); diff --git a/packages/ui/nodes/media-embed/src/MediaEmbedToolbarButton/MediaEmbedToolbarButton.tsx b/packages/ui/nodes/media-embed/src/MediaEmbedToolbarButton/MediaEmbedToolbarButton.tsx index 6465dfd2f0..19382c5553 100644 --- a/packages/ui/nodes/media-embed/src/MediaEmbedToolbarButton/MediaEmbedToolbarButton.tsx +++ b/packages/ui/nodes/media-embed/src/MediaEmbedToolbarButton/MediaEmbedToolbarButton.tsx @@ -11,10 +11,11 @@ export interface MediaEmbedToolbarButtonProps extends ToolbarButtonProps { } export const MediaEmbedToolbarButton = ({ + id, getEmbedUrl, ...props }: MediaEmbedToolbarButtonProps) => { - const editor = usePlateEditorRef()!; + const editor = usePlateEditorRef(id)!; return ( { - const editor = usePlateEditorState()!; +export const TableToolbarButton = withPlateEventProvider( + ({ id, transform, header, ...props }: TableToolbarButtonProps) => { + id = useEventPlateId(id); + const editor = usePlateEditorState(id)!; const type = getPluginType(editor, ELEMENT_TABLE); return ( diff --git a/packages/ui/toolbar/src/BalloonToolbar/BalloonToolbar.tsx b/packages/ui/toolbar/src/BalloonToolbar/BalloonToolbar.tsx index 01b2aa64e5..a6dda04be6 100644 --- a/packages/ui/toolbar/src/BalloonToolbar/BalloonToolbar.tsx +++ b/packages/ui/toolbar/src/BalloonToolbar/BalloonToolbar.tsx @@ -1,5 +1,5 @@ import React, { useRef } from 'react'; -import { withPlateProvider } from '@udecode/plate-core'; +import { withPlateEventProvider } from '@udecode/plate-core'; import { PortalBody } from '@udecode/plate-styled-components'; import { UsePopperPositionOptions } from '@udecode/plate-ui-popper'; import { ToolbarBase } from '../Toolbar/Toolbar'; @@ -7,7 +7,7 @@ import { getBalloonToolbarStyles } from './BalloonToolbar.styles'; import { BalloonToolbarProps } from './BalloonToolbar.types'; import { useBalloonToolbarPopper } from './useBalloonToolbarPopper'; -export const BalloonToolbar = withPlateProvider( +export const BalloonToolbar = withPlateEventProvider( (props: BalloonToolbarProps) => { const { children, diff --git a/packages/ui/toolbar/src/BalloonToolbar/useBalloonToolbarPopper.ts b/packages/ui/toolbar/src/BalloonToolbar/useBalloonToolbarPopper.ts index 40f9e17efd..02a01f5e4b 100644 --- a/packages/ui/toolbar/src/BalloonToolbar/useBalloonToolbarPopper.ts +++ b/packages/ui/toolbar/src/BalloonToolbar/useBalloonToolbarPopper.ts @@ -3,6 +3,7 @@ import { getSelectionText, isSelectionExpanded, useEditorState, + useEventEditorSelectors, } from '@udecode/plate-core'; import { getSelectionBoundingClientRect, @@ -12,6 +13,7 @@ import { import { useFocused } from 'slate-react'; export const useBalloonToolbarPopper = (options: UsePopperPositionOptions) => { + const focusedEditorId = useEventEditorSelectors.focus(); const editor = useEditorState(); const focused = useFocused(); @@ -21,12 +23,24 @@ export const useBalloonToolbarPopper = (options: UsePopperPositionOptions) => { const selectionText = editor && getSelectionText(editor); useEffect(() => { - if (!selectionText || !focused) { + if ( + !selectionExpanded || + !selectionText || + !focused || + editor.id !== focusedEditorId + ) { setIsHidden(true); } else if (selectionText && selectionExpanded) { setIsHidden(false); } - }, [focused, selectionExpanded, selectionText]); + }, [ + editor.id, + editor.selection, + focused, + focusedEditorId, + selectionExpanded, + selectionText, + ]); const popperResult = usePopperPosition({ isHidden, @@ -38,7 +52,9 @@ export const useBalloonToolbarPopper = (options: UsePopperPositionOptions) => { const { update } = popperResult; useEffect(() => { - selectionTextLength > 0 && update?.(); + if (selectionTextLength > 0) { + update?.(); + } }, [selectionTextLength, update]); return popperResult; diff --git a/packages/ui/toolbar/src/BlockToolbarButton/BlockToolbarButton.tsx b/packages/ui/toolbar/src/BlockToolbarButton/BlockToolbarButton.tsx index 0c47093bd8..d2bec8f5bd 100644 --- a/packages/ui/toolbar/src/BlockToolbarButton/BlockToolbarButton.tsx +++ b/packages/ui/toolbar/src/BlockToolbarButton/BlockToolbarButton.tsx @@ -3,8 +3,9 @@ import { getPreventDefaultHandler, someNode, toggleNodeType, + useEventPlateId, usePlateEditorState, - withPlateProvider, + withPlateEventProvider, } from '@udecode/plate-core'; import { ToolbarButton } from '../ToolbarButton'; import { BlockToolbarButtonProps } from './BlockToolbarButton.types'; @@ -12,9 +13,10 @@ import { BlockToolbarButtonProps } from './BlockToolbarButton.types'; /** * Toolbar button to toggle the type of elements in selection. */ -export const BlockToolbarButton = withPlateProvider( - ({ type, inactiveType, active, ...props }: BlockToolbarButtonProps) => { - const editor = usePlateEditorState()!; +export const BlockToolbarButton = withPlateEventProvider( + ({ id, type, inactiveType, active, ...props }: BlockToolbarButtonProps) => { + id = useEventPlateId(id); + const editor = usePlateEditorState(id)!; return ( { - const editor = usePlateEditorState()!; +export const MarkToolbarButton = withPlateEventProvider( + ({ id, type, clear, ...props }: MarkToolbarButtonProps) => { + id = useEventPlateId(id); + const editor = usePlateEditorState(id)!; return ( , AnyObject { + id?: string; + /** * Is it active. */