From 2ee76a37612232cfea9837a24cf688eb6fce0034 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Thu, 21 Dec 2023 19:22:42 +0000 Subject: [PATCH 01/13] Proof of concept for `useEditorSelector` --- .../default/example/playground-demo.tsx | 4 + .../registry/default/example/test-toolbar.tsx | 28 ++ packages/core/package.json | 2 +- packages/core/src/hooks/usePlateEffects.ts | 2 +- packages/core/src/libs/jotai.ts | 1 - .../core/src/stores/plate/createPlateStore.ts | 39 +-- .../core/src/stores/plate/selectors/index.ts | 1 + .../stores/plate/selectors/useEditorRef.ts | 2 +- .../plate/selectors/useEditorSelection.ts | 11 +- .../plate/selectors/useEditorSelector.ts | 34 ++ .../stores/plate/selectors/useEditorState.ts | 10 +- packages/core/src/types/PlateEditorMethods.ts | 8 +- yarn.lock | 320 +++++++++--------- 13 files changed, 254 insertions(+), 208 deletions(-) create mode 100644 apps/www/src/registry/default/example/test-toolbar.tsx create mode 100644 packages/core/src/stores/plate/selectors/useEditorSelector.ts diff --git a/apps/www/src/registry/default/example/playground-demo.tsx b/apps/www/src/registry/default/example/playground-demo.tsx index 23ce70072a..af6ff6d3c3 100644 --- a/apps/www/src/registry/default/example/playground-demo.tsx +++ b/apps/www/src/registry/default/example/playground-demo.tsx @@ -103,6 +103,8 @@ import { FixedToolbar } from '@/registry/default/plate-ui/fixed-toolbar'; import { FloatingToolbar } from '@/registry/default/plate-ui/floating-toolbar'; import { MentionCombobox } from '@/registry/default/plate-ui/mention-combobox'; +import { TestToolbar } from './test-toolbar'; + export const usePlaygroundPlugins = ({ id, components = createPlateUI(), @@ -344,6 +346,8 @@ export default function PlaygroundDemo({ id }: { id?: ValueId }) { )} /> + + {enabled['floating-toolbar'] && ( {enabled['floating-toolbar-buttons'] && ( diff --git a/apps/www/src/registry/default/example/test-toolbar.tsx b/apps/www/src/registry/default/example/test-toolbar.tsx new file mode 100644 index 0000000000..ed21f042d5 --- /dev/null +++ b/apps/www/src/registry/default/example/test-toolbar.tsx @@ -0,0 +1,28 @@ +import React, { useEffect, useRef } from 'react'; +import { isSelectionExpanded, useEditorSelector } from '@udecode/plate-common'; + +const useRenderCount = () => { + const renderCount = useRef(0); + useEffect(() => { + renderCount.current += 1; + }); + return renderCount.current; +}; + +export const TestToolbar = () => { + const isExpanded = useEditorSelector(isSelectionExpanded, []); + const renderCount = useRenderCount(); + + return ( + <> + {JSON.stringify( + { + renderCount, // Increments only when isExpanded changes + isExpanded, + }, + null, + 2 + )} + + ); +}; diff --git a/packages/core/package.json b/packages/core/package.json index f46807dbaa..8b8ffb117c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -46,7 +46,7 @@ "clsx": "^1.2.1", "is-hotkey": "^0.2.0", "jotai": "^2.6.0", - "jotai-x": "^1.0.1", + "jotai-x": "0.0.0-20231221184746", "lodash": "^4.17.21", "nanoid": "^3.3.6", "react-hotkeys-hook": "^4.4.1", diff --git a/packages/core/src/hooks/usePlateEffects.ts b/packages/core/src/hooks/usePlateEffects.ts index a9a405ab62..36506dd36e 100644 --- a/packages/core/src/hooks/usePlateEffects.ts +++ b/packages/core/src/hooks/usePlateEffects.ts @@ -21,7 +21,7 @@ export const usePlateEffects = < }: UsePlateEffectsProps) => { const editor = useEditorRef(id); - const states = usePlateStates(id); + const states = usePlateStates(id); const [rawPlugins, setRawPlugins] = states.rawPlugins(); const [, setPlugins] = states.plugins(); diff --git a/packages/core/src/libs/jotai.ts b/packages/core/src/libs/jotai.ts index 8be65074ba..7a7242d445 100644 --- a/packages/core/src/libs/jotai.ts +++ b/packages/core/src/libs/jotai.ts @@ -1,2 +1 @@ -export type { GetRecord, SetRecord, UseRecord } from 'jotai-x'; export { createAtomStore } from 'jotai-x'; diff --git a/packages/core/src/stores/plate/createPlateStore.ts b/packages/core/src/stores/plate/createPlateStore.ts index 9ac7ecd6b3..501acc4357 100644 --- a/packages/core/src/stores/plate/createPlateStore.ts +++ b/packages/core/src/stores/plate/createPlateStore.ts @@ -1,11 +1,7 @@ import { Value } from '@udecode/slate'; +import { atom } from 'jotai'; -import { - createAtomStore, - GetRecord, - SetRecord, - UseRecord, -} from '../../libs/jotai'; +import { createAtomStore } from '../../libs/jotai'; import { PlateEditor } from '../../types/PlateEditor'; import { PlateStoreState } from '../../types/PlateStore'; @@ -61,6 +57,16 @@ export const createPlateStore = < } as PlateStoreState, { name: 'plate', + extend: (atoms) => ({ + trackedEditor: atom((get) => ({ + editor: get(atoms.editor), + version: get(atoms.versionEditor), + })), + trackedSelection: atom((get) => ({ + selection: get(atoms.editor).selection, + version: get(atoms.versionSelection), + })), + }), } ); @@ -70,24 +76,9 @@ export const { PlateProvider: PlateStoreProvider, } = createPlateStore(); -export const usePlateSelectors = < - V extends Value = Value, - E extends PlateEditor = PlateEditor, ->( - id?: PlateId -): GetRecord> => usePlateStore(id).get as any; -export const usePlateActions = < - V extends Value = Value, - E extends PlateEditor = PlateEditor, ->( - id?: PlateId -): SetRecord> => usePlateStore(id).set as any; -export const usePlateStates = < - V extends Value = Value, - E extends PlateEditor = PlateEditor, ->( - id?: PlateId -): UseRecord> => usePlateStore(id).use as any; +export const usePlateSelectors = (id?: PlateId) => usePlateStore(id).get; +export const usePlateActions = (id?: PlateId) => usePlateStore(id).set; +export const usePlateStates = (id?: PlateId) => usePlateStore(id).use; /** * Get the closest `Plate` id. diff --git a/packages/core/src/stores/plate/selectors/index.ts b/packages/core/src/stores/plate/selectors/index.ts index fdf70483ff..dd84c5c107 100644 --- a/packages/core/src/stores/plate/selectors/index.ts +++ b/packages/core/src/stores/plate/selectors/index.ts @@ -5,6 +5,7 @@ export * from './useEditorReadOnly'; export * from './useEditorRef'; export * from './useEditorSelection'; +export * from './useEditorSelector'; export * from './useEditorState'; export * from './useEditorVersion'; export * from './useSelectionVersion'; diff --git a/packages/core/src/stores/plate/selectors/useEditorRef.ts b/packages/core/src/stores/plate/selectors/useEditorRef.ts index f2c4e7b9db..b4ce26a16a 100644 --- a/packages/core/src/stores/plate/selectors/useEditorRef.ts +++ b/packages/core/src/stores/plate/selectors/useEditorRef.ts @@ -11,4 +11,4 @@ export const useEditorRef = < E extends PlateEditor = PlateEditor, >( id?: PlateId -) => usePlateSelectors(id).editor(); +): E => usePlateSelectors(id).editor() as any; diff --git a/packages/core/src/stores/plate/selectors/useEditorSelection.ts b/packages/core/src/stores/plate/selectors/useEditorSelection.ts index 1e7bc883a1..8e4b3143de 100644 --- a/packages/core/src/stores/plate/selectors/useEditorSelection.ts +++ b/packages/core/src/stores/plate/selectors/useEditorSelection.ts @@ -1,12 +1,7 @@ -import { PlateId } from '../createPlateStore'; -import { useEditorRef } from './useEditorRef'; -import { useSelectionVersion } from './useSelectionVersion'; +import { PlateId, usePlateSelectors } from '../createPlateStore'; /** * Get the editor selection (deeply memoized). */ -export const useEditorSelection = (id?: PlateId) => { - useSelectionVersion(id); - - return useEditorRef(id).selection; -}; +export const useEditorSelection = (id?: PlateId) => + usePlateSelectors(id).trackedSelection().selection; diff --git a/packages/core/src/stores/plate/selectors/useEditorSelector.ts b/packages/core/src/stores/plate/selectors/useEditorSelector.ts new file mode 100644 index 0000000000..b24a06a18a --- /dev/null +++ b/packages/core/src/stores/plate/selectors/useEditorSelector.ts @@ -0,0 +1,34 @@ +import { DependencyList, useMemo } from 'react'; +import { Value } from '@udecode/slate'; +import { selectAtom } from 'jotai/utils'; + +import { PlateEditor } from '../../../types/PlateEditor'; +import { PlateId, plateStore, usePlateSelectors } from '../createPlateStore'; + +export interface UseEditorSelectorOptions { + id?: PlateId; + equalityFn?: (a: T, b: T) => boolean; +} + +export const useEditorSelector = < + T, + V extends Value = Value, + E extends PlateEditor = PlateEditor, +>( + selector: (editor: E, prev?: T) => T, + deps: DependencyList, + { id, equalityFn = (a: T, b: T) => a === b }: UseEditorSelectorOptions = {} +): T => { + const selectorAtom = useMemo( + () => + selectAtom<{ editor: E }, T>( + plateStore.atom.trackedEditor, + ({ editor }, prev) => selector(editor, prev), + equalityFn + ), + // eslint-disable-next-line react-hooks/exhaustive-deps + deps + ); + + return usePlateSelectors(id).atom(selectorAtom); +}; diff --git a/packages/core/src/stores/plate/selectors/useEditorState.ts b/packages/core/src/stores/plate/selectors/useEditorState.ts index 06171d050d..e8793afc74 100644 --- a/packages/core/src/stores/plate/selectors/useEditorState.ts +++ b/packages/core/src/stores/plate/selectors/useEditorState.ts @@ -1,9 +1,7 @@ import { Value } from '@udecode/slate'; import { PlateEditor } from '../../../types/PlateEditor'; -import { PlateId } from '../createPlateStore'; -import { useEditorRef } from './useEditorRef'; -import { useEditorVersion } from './useEditorVersion'; +import { PlateId, usePlateSelectors } from '../createPlateStore'; /** * Get editor state which is updated on editor change. @@ -13,8 +11,6 @@ export const useEditorState = < E extends PlateEditor = PlateEditor, >( id?: PlateId -) => { - useEditorVersion(id); - - return useEditorRef(id); +): E => { + return usePlateSelectors(id).trackedEditor().editor; }; diff --git a/packages/core/src/types/PlateEditorMethods.ts b/packages/core/src/types/PlateEditorMethods.ts index ec89ab748b..d3fdb374f4 100644 --- a/packages/core/src/types/PlateEditorMethods.ts +++ b/packages/core/src/types/PlateEditorMethods.ts @@ -2,8 +2,6 @@ import { Value } from '@udecode/slate'; import { EXPOSED_STORE_KEYS, PlateStoreState } from './PlateStore'; -import type { SetRecord } from '../libs/jotai'; - export type PlateEditorMethods = { reset: () => void; redecorate: () => void; @@ -11,9 +9,9 @@ export type PlateEditorMethods = { // Example: editor.plate.set.readOnly(true) plate: { set: { - [K in (typeof EXPOSED_STORE_KEYS)[number]]: ReturnType< - SetRecord>[K] - >; + [K in (typeof EXPOSED_STORE_KEYS)[number]]: ( + value: PlateStoreState[K] + ) => void; }; }; }; diff --git a/yarn.lock b/yarn.lock index f2c138945d..86e823d636 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6033,11 +6033,11 @@ __metadata: languageName: node linkType: hard -"@udecode/plate-alignment@npm:27.0.0, @udecode/plate-alignment@workspace:^, @udecode/plate-alignment@workspace:packages/alignment": +"@udecode/plate-alignment@npm:27.0.3, @udecode/plate-alignment@workspace:^, @udecode/plate-alignment@workspace:packages/alignment": version: 0.0.0-use.local resolution: "@udecode/plate-alignment@workspace:packages/alignment" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6048,11 +6048,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-autoformat@npm:27.0.0, @udecode/plate-autoformat@workspace:^, @udecode/plate-autoformat@workspace:packages/autoformat": +"@udecode/plate-autoformat@npm:27.0.3, @udecode/plate-autoformat@workspace:^, @udecode/plate-autoformat@workspace:packages/autoformat": version: 0.0.0-use.local resolution: "@udecode/plate-autoformat@workspace:packages/autoformat" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" lodash: "npm:^4.17.21" peerDependencies: react: ">=16.8.0" @@ -6064,15 +6064,15 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-basic-elements@npm:27.0.0, @udecode/plate-basic-elements@workspace:^, @udecode/plate-basic-elements@workspace:packages/basic-elements": +"@udecode/plate-basic-elements@npm:27.0.3, @udecode/plate-basic-elements@workspace:^, @udecode/plate-basic-elements@workspace:packages/basic-elements": version: 0.0.0-use.local resolution: "@udecode/plate-basic-elements@workspace:packages/basic-elements" dependencies: - "@udecode/plate-block-quote": "npm:27.0.0" - "@udecode/plate-code-block": "npm:27.0.0" - "@udecode/plate-common": "npm:27.0.0" - "@udecode/plate-heading": "npm:27.0.0" - "@udecode/plate-paragraph": "npm:27.0.0" + "@udecode/plate-block-quote": "npm:27.0.3" + "@udecode/plate-code-block": "npm:27.0.3" + "@udecode/plate-common": "npm:27.0.3" + "@udecode/plate-heading": "npm:27.0.3" + "@udecode/plate-paragraph": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6083,11 +6083,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-basic-marks@npm:27.0.0, @udecode/plate-basic-marks@workspace:^, @udecode/plate-basic-marks@workspace:packages/basic-marks": +"@udecode/plate-basic-marks@npm:27.0.3, @udecode/plate-basic-marks@workspace:^, @udecode/plate-basic-marks@workspace:packages/basic-marks": version: 0.0.0-use.local resolution: "@udecode/plate-basic-marks@workspace:packages/basic-marks" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6098,11 +6098,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-block-quote@npm:27.0.0, @udecode/plate-block-quote@workspace:^, @udecode/plate-block-quote@workspace:packages/block-quote": +"@udecode/plate-block-quote@npm:27.0.3, @udecode/plate-block-quote@workspace:^, @udecode/plate-block-quote@workspace:packages/block-quote": version: 0.0.0-use.local resolution: "@udecode/plate-block-quote@workspace:packages/block-quote" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6113,11 +6113,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-break@npm:27.0.0, @udecode/plate-break@workspace:^, @udecode/plate-break@workspace:packages/break": +"@udecode/plate-break@npm:27.0.3, @udecode/plate-break@workspace:^, @udecode/plate-break@workspace:packages/break": version: 0.0.0-use.local resolution: "@udecode/plate-break@workspace:packages/break" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6132,7 +6132,7 @@ __metadata: version: 0.0.0-use.local resolution: "@udecode/plate-caption@workspace:packages/caption" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" react-textarea-autosize: "npm:^8.5.2" peerDependencies: react: ">=16.8.0" @@ -6149,7 +6149,7 @@ __metadata: resolution: "@udecode/plate-cloud@workspace:packages/cloud" dependencies: "@portive/client": "npm:10.0.3" - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" delay: "npm:5.0.0" p-defer: "npm:^3.0.0" peerDependencies: @@ -6162,11 +6162,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-code-block@npm:27.0.0, @udecode/plate-code-block@workspace:^, @udecode/plate-code-block@workspace:packages/code-block": +"@udecode/plate-code-block@npm:27.0.3, @udecode/plate-code-block@workspace:^, @udecode/plate-code-block@workspace:packages/code-block": version: 0.0.0-use.local resolution: "@udecode/plate-code-block@workspace:packages/code-block" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" prismjs: "npm:^1.29.0" peerDependencies: react: ">=16.8.0" @@ -6178,11 +6178,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-combobox@npm:27.0.0, @udecode/plate-combobox@workspace:^, @udecode/plate-combobox@workspace:packages/combobox": +"@udecode/plate-combobox@npm:27.0.3, @udecode/plate-combobox@workspace:^, @udecode/plate-combobox@workspace:packages/combobox": version: 0.0.0-use.local resolution: "@udecode/plate-combobox@workspace:packages/combobox" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" downshift: "npm:^6.1.12" peerDependencies: react: ">=16.8.0" @@ -6194,11 +6194,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-comments@npm:27.0.0, @udecode/plate-comments@workspace:^, @udecode/plate-comments@workspace:packages/comments": +"@udecode/plate-comments@npm:27.0.3, @udecode/plate-comments@workspace:^, @udecode/plate-comments@workspace:packages/comments": version: 0.0.0-use.local resolution: "@udecode/plate-comments@workspace:packages/comments" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" lodash: "npm:^4.17.21" peerDependencies: react: ">=16.8.0" @@ -6210,12 +6210,12 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-common@npm:27.0.0, @udecode/plate-common@workspace:^, @udecode/plate-common@workspace:packages/common": +"@udecode/plate-common@npm:27.0.3, @udecode/plate-common@workspace:^, @udecode/plate-common@workspace:packages/common": version: 0.0.0-use.local resolution: "@udecode/plate-common@workspace:packages/common" dependencies: - "@udecode/plate-core": "npm:27.0.0" - "@udecode/plate-utils": "npm:27.0.0" + "@udecode/plate-core": "npm:27.0.3" + "@udecode/plate-utils": "npm:27.0.3" "@udecode/slate": "npm:25.0.0" "@udecode/slate-react": "npm:25.0.0" "@udecode/slate-utils": "npm:25.0.0" @@ -6230,7 +6230,7 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-core@npm:27.0.0, @udecode/plate-core@workspace:^, @udecode/plate-core@workspace:packages/core": +"@udecode/plate-core@npm:27.0.3, @udecode/plate-core@workspace:^, @udecode/plate-core@workspace:packages/core": version: 0.0.0-use.local resolution: "@udecode/plate-core@workspace:packages/core" dependencies: @@ -6241,7 +6241,7 @@ __metadata: clsx: "npm:^1.2.1" is-hotkey: "npm:^0.2.0" jotai: "npm:^2.6.0" - jotai-x: "npm:^1.0.1" + jotai-x: "npm:0.0.0-20231221184746" lodash: "npm:^4.17.21" nanoid: "npm:^3.3.6" react-hotkeys-hook: "npm:^4.4.1" @@ -6262,7 +6262,7 @@ __metadata: version: 0.0.0-use.local resolution: "@udecode/plate-cursor@workspace:packages/cursor" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6277,7 +6277,7 @@ __metadata: version: 0.0.0-use.local resolution: "@udecode/plate-dnd@workspace:packages/dnd" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" lodash: "npm:^4.17.21" raf: "npm:^3.4.1" peerDependencies: @@ -6297,8 +6297,8 @@ __metadata: resolution: "@udecode/plate-emoji@workspace:packages/emoji" dependencies: "@emoji-mart/data": "npm:^1.1.2" - "@udecode/plate-combobox": "npm:27.0.0" - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-combobox": "npm:27.0.3" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6314,7 +6314,7 @@ __metadata: resolution: "@udecode/plate-excalidraw@workspace:packages/excalidraw" dependencies: "@excalidraw/excalidraw": "npm:0.12.0" - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6325,11 +6325,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-find-replace@npm:27.0.0, @udecode/plate-find-replace@workspace:^, @udecode/plate-find-replace@workspace:packages/find-replace": +"@udecode/plate-find-replace@npm:27.0.3, @udecode/plate-find-replace@workspace:^, @udecode/plate-find-replace@workspace:packages/find-replace": version: 0.0.0-use.local resolution: "@udecode/plate-find-replace@workspace:packages/find-replace" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6340,13 +6340,13 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-floating@npm:27.0.0, @udecode/plate-floating@workspace:^, @udecode/plate-floating@workspace:packages/floating": +"@udecode/plate-floating@npm:27.0.3, @udecode/plate-floating@workspace:^, @udecode/plate-floating@workspace:packages/floating": version: 0.0.0-use.local resolution: "@udecode/plate-floating@workspace:packages/floating" dependencies: "@floating-ui/core": "npm:^1.3.1" "@floating-ui/react": "npm:^0.22.3" - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6357,11 +6357,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-font@npm:27.0.0, @udecode/plate-font@workspace:^, @udecode/plate-font@workspace:packages/font": +"@udecode/plate-font@npm:27.0.3, @udecode/plate-font@workspace:^, @udecode/plate-font@workspace:packages/font": version: 0.0.0-use.local resolution: "@udecode/plate-font@workspace:packages/font" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" lodash: "npm:^4.17.21" peerDependencies: react: ">=16.8.0" @@ -6373,11 +6373,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-heading@npm:27.0.0, @udecode/plate-heading@workspace:^, @udecode/plate-heading@workspace:packages/heading": +"@udecode/plate-heading@npm:27.0.3, @udecode/plate-heading@workspace:^, @udecode/plate-heading@workspace:packages/heading": version: 0.0.0-use.local resolution: "@udecode/plate-heading@workspace:packages/heading" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6388,11 +6388,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-highlight@npm:27.0.0, @udecode/plate-highlight@workspace:^, @udecode/plate-highlight@workspace:packages/highlight": +"@udecode/plate-highlight@npm:27.0.3, @udecode/plate-highlight@workspace:^, @udecode/plate-highlight@workspace:packages/highlight": version: 0.0.0-use.local resolution: "@udecode/plate-highlight@workspace:packages/highlight" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6403,11 +6403,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-horizontal-rule@npm:27.0.0, @udecode/plate-horizontal-rule@workspace:^, @udecode/plate-horizontal-rule@workspace:packages/horizontal-rule": +"@udecode/plate-horizontal-rule@npm:27.0.3, @udecode/plate-horizontal-rule@workspace:^, @udecode/plate-horizontal-rule@workspace:packages/horizontal-rule": version: 0.0.0-use.local resolution: "@udecode/plate-horizontal-rule@workspace:packages/horizontal-rule" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6418,13 +6418,13 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-indent-list@npm:27.0.0, @udecode/plate-indent-list@workspace:^, @udecode/plate-indent-list@workspace:packages/indent-list": +"@udecode/plate-indent-list@npm:27.0.3, @udecode/plate-indent-list@workspace:^, @udecode/plate-indent-list@workspace:packages/indent-list": version: 0.0.0-use.local resolution: "@udecode/plate-indent-list@workspace:packages/indent-list" dependencies: - "@udecode/plate-common": "npm:27.0.0" - "@udecode/plate-indent": "npm:27.0.0" - "@udecode/plate-list": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" + "@udecode/plate-indent": "npm:27.0.3" + "@udecode/plate-list": "npm:27.0.3" clsx: "npm:^1.2.1" peerDependencies: react: ">=16.8.0" @@ -6436,11 +6436,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-indent@npm:27.0.0, @udecode/plate-indent@workspace:^, @udecode/plate-indent@workspace:packages/indent": +"@udecode/plate-indent@npm:27.0.3, @udecode/plate-indent@workspace:^, @udecode/plate-indent@workspace:packages/indent": version: 0.0.0-use.local resolution: "@udecode/plate-indent@workspace:packages/indent" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6455,7 +6455,7 @@ __metadata: version: 0.0.0-use.local resolution: "@udecode/plate-juice@workspace:packages/juice" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" juice: "npm:^8.1.0" peerDependencies: react: ">=16.8.0" @@ -6467,11 +6467,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-kbd@npm:27.0.0, @udecode/plate-kbd@workspace:^, @udecode/plate-kbd@workspace:packages/kbd": +"@udecode/plate-kbd@npm:27.0.3, @udecode/plate-kbd@workspace:^, @udecode/plate-kbd@workspace:packages/kbd": version: 0.0.0-use.local resolution: "@udecode/plate-kbd@workspace:packages/kbd" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6482,11 +6482,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-line-height@npm:27.0.0, @udecode/plate-line-height@workspace:^, @udecode/plate-line-height@workspace:packages/line-height": +"@udecode/plate-line-height@npm:27.0.3, @udecode/plate-line-height@workspace:^, @udecode/plate-line-height@workspace:packages/line-height": version: 0.0.0-use.local resolution: "@udecode/plate-line-height@workspace:packages/line-height" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6497,13 +6497,13 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-link@npm:27.0.0, @udecode/plate-link@workspace:^, @udecode/plate-link@workspace:packages/link": +"@udecode/plate-link@npm:27.0.3, @udecode/plate-link@workspace:^, @udecode/plate-link@workspace:packages/link": version: 0.0.0-use.local resolution: "@udecode/plate-link@workspace:packages/link" dependencies: - "@udecode/plate-common": "npm:27.0.0" - "@udecode/plate-floating": "npm:27.0.0" - "@udecode/plate-normalizers": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" + "@udecode/plate-floating": "npm:27.0.3" + "@udecode/plate-normalizers": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6514,12 +6514,12 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-list@npm:27.0.0, @udecode/plate-list@workspace:^, @udecode/plate-list@workspace:packages/list": +"@udecode/plate-list@npm:27.0.3, @udecode/plate-list@workspace:^, @udecode/plate-list@workspace:packages/list": version: 0.0.0-use.local resolution: "@udecode/plate-list@workspace:packages/list" dependencies: - "@udecode/plate-common": "npm:27.0.0" - "@udecode/plate-reset-node": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" + "@udecode/plate-reset-node": "npm:27.0.3" lodash: "npm:^4.17.21" peerDependencies: react: ">=16.8.0" @@ -6531,11 +6531,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-media@npm:27.0.0, @udecode/plate-media@workspace:^, @udecode/plate-media@workspace:packages/media": +"@udecode/plate-media@npm:27.0.3, @udecode/plate-media@workspace:^, @udecode/plate-media@workspace:packages/media": version: 0.0.0-use.local resolution: "@udecode/plate-media@workspace:packages/media" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" js-video-url-parser: "npm:^0.5.1" peerDependencies: react: ">=16.8.0" @@ -6547,12 +6547,12 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-mention@npm:27.0.0, @udecode/plate-mention@workspace:^, @udecode/plate-mention@workspace:packages/mention": +"@udecode/plate-mention@npm:27.0.3, @udecode/plate-mention@workspace:^, @udecode/plate-mention@workspace:packages/mention": version: 0.0.0-use.local resolution: "@udecode/plate-mention@workspace:packages/mention" dependencies: - "@udecode/plate-combobox": "npm:27.0.0" - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-combobox": "npm:27.0.3" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6563,11 +6563,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-node-id@npm:27.0.0, @udecode/plate-node-id@workspace:^, @udecode/plate-node-id@workspace:packages/node-id": +"@udecode/plate-node-id@npm:27.0.3, @udecode/plate-node-id@workspace:^, @udecode/plate-node-id@workspace:packages/node-id": version: 0.0.0-use.local resolution: "@udecode/plate-node-id@workspace:packages/node-id" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" lodash: "npm:^4.17.21" peerDependencies: react: ">=16.8.0" @@ -6579,11 +6579,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-normalizers@npm:27.0.0, @udecode/plate-normalizers@workspace:^, @udecode/plate-normalizers@workspace:packages/normalizers": +"@udecode/plate-normalizers@npm:27.0.3, @udecode/plate-normalizers@workspace:^, @udecode/plate-normalizers@workspace:packages/normalizers": version: 0.0.0-use.local resolution: "@udecode/plate-normalizers@workspace:packages/normalizers" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" lodash: "npm:^4.17.21" peerDependencies: react: ">=16.8.0" @@ -6595,11 +6595,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-paragraph@npm:27.0.0, @udecode/plate-paragraph@workspace:^, @udecode/plate-paragraph@workspace:packages/paragraph": +"@udecode/plate-paragraph@npm:27.0.3, @udecode/plate-paragraph@workspace:^, @udecode/plate-paragraph@workspace:packages/paragraph": version: 0.0.0-use.local resolution: "@udecode/plate-paragraph@workspace:packages/paragraph" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6610,11 +6610,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-reset-node@npm:27.0.0, @udecode/plate-reset-node@workspace:^, @udecode/plate-reset-node@workspace:packages/reset-node": +"@udecode/plate-reset-node@npm:27.0.3, @udecode/plate-reset-node@workspace:^, @udecode/plate-reset-node@workspace:packages/reset-node": version: 0.0.0-use.local resolution: "@udecode/plate-reset-node@workspace:packages/reset-node" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6625,11 +6625,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-resizable@npm:27.0.0, @udecode/plate-resizable@workspace:^, @udecode/plate-resizable@workspace:packages/resizable": +"@udecode/plate-resizable@npm:27.0.3, @udecode/plate-resizable@workspace:^, @udecode/plate-resizable@workspace:packages/resizable": version: 0.0.0-use.local resolution: "@udecode/plate-resizable@workspace:packages/resizable" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6640,11 +6640,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-select@npm:27.0.0, @udecode/plate-select@workspace:^, @udecode/plate-select@workspace:packages/select": +"@udecode/plate-select@npm:27.0.3, @udecode/plate-select@workspace:^, @udecode/plate-select@workspace:packages/select": version: 0.0.0-use.local resolution: "@udecode/plate-select@workspace:packages/select" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6659,7 +6659,7 @@ __metadata: version: 0.0.0-use.local resolution: "@udecode/plate-selection@workspace:packages/selection" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" "@viselect/vanilla": "npm:3.2.5" copy-to-clipboard: "npm:^3.3.3" peerDependencies: @@ -6672,13 +6672,13 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-serializer-csv@npm:27.0.2, @udecode/plate-serializer-csv@workspace:^, @udecode/plate-serializer-csv@workspace:packages/serializer-csv": +"@udecode/plate-serializer-csv@npm:27.0.3, @udecode/plate-serializer-csv@workspace:^, @udecode/plate-serializer-csv@workspace:packages/serializer-csv": version: 0.0.0-use.local resolution: "@udecode/plate-serializer-csv@workspace:packages/serializer-csv" dependencies: "@types/papaparse": "npm:^5.3.7" - "@udecode/plate-common": "npm:27.0.0" - "@udecode/plate-table": "npm:27.0.2" + "@udecode/plate-common": "npm:27.0.3" + "@udecode/plate-table": "npm:27.0.3" papaparse: "npm:^5.4.1" peerDependencies: react: ">=16.8.0" @@ -6690,17 +6690,17 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-serializer-docx@npm:27.0.2, @udecode/plate-serializer-docx@workspace:^, @udecode/plate-serializer-docx@workspace:packages/serializer-docx": +"@udecode/plate-serializer-docx@npm:27.0.3, @udecode/plate-serializer-docx@workspace:^, @udecode/plate-serializer-docx@workspace:packages/serializer-docx": version: 0.0.0-use.local resolution: "@udecode/plate-serializer-docx@workspace:packages/serializer-docx" dependencies: - "@udecode/plate-common": "npm:27.0.0" - "@udecode/plate-heading": "npm:27.0.0" - "@udecode/plate-indent": "npm:27.0.0" - "@udecode/plate-indent-list": "npm:27.0.0" - "@udecode/plate-media": "npm:27.0.0" - "@udecode/plate-paragraph": "npm:27.0.0" - "@udecode/plate-table": "npm:27.0.2" + "@udecode/plate-common": "npm:27.0.3" + "@udecode/plate-heading": "npm:27.0.3" + "@udecode/plate-indent": "npm:27.0.3" + "@udecode/plate-indent-list": "npm:27.0.3" + "@udecode/plate-media": "npm:27.0.3" + "@udecode/plate-paragraph": "npm:27.0.3" + "@udecode/plate-table": "npm:27.0.3" validator: "npm:^13.9.0" peerDependencies: react: ">=16.8.0" @@ -6712,12 +6712,12 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-serializer-html@npm:27.0.0, @udecode/plate-serializer-html@workspace:^, @udecode/plate-serializer-html@workspace:packages/serializer-html": +"@udecode/plate-serializer-html@npm:27.0.3, @udecode/plate-serializer-html@workspace:^, @udecode/plate-serializer-html@workspace:packages/serializer-html": version: 0.0.0-use.local resolution: "@udecode/plate-serializer-html@workspace:packages/serializer-html" dependencies: "@types/papaparse": "npm:^5.3.7" - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" html-entities: "npm:^2.4.0" peerDependencies: react: ">=16.8.0" @@ -6729,20 +6729,20 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-serializer-md@npm:27.0.0, @udecode/plate-serializer-md@workspace:^, @udecode/plate-serializer-md@workspace:packages/serializer-md": +"@udecode/plate-serializer-md@npm:27.0.3, @udecode/plate-serializer-md@workspace:^, @udecode/plate-serializer-md@workspace:packages/serializer-md": version: 0.0.0-use.local resolution: "@udecode/plate-serializer-md@workspace:packages/serializer-md" dependencies: - "@udecode/plate-basic-marks": "npm:27.0.0" - "@udecode/plate-block-quote": "npm:27.0.0" - "@udecode/plate-code-block": "npm:27.0.0" - "@udecode/plate-common": "npm:27.0.0" - "@udecode/plate-heading": "npm:27.0.0" - "@udecode/plate-horizontal-rule": "npm:27.0.0" - "@udecode/plate-link": "npm:27.0.0" - "@udecode/plate-list": "npm:27.0.0" - "@udecode/plate-media": "npm:27.0.0" - "@udecode/plate-paragraph": "npm:27.0.0" + "@udecode/plate-basic-marks": "npm:27.0.3" + "@udecode/plate-block-quote": "npm:27.0.3" + "@udecode/plate-code-block": "npm:27.0.3" + "@udecode/plate-common": "npm:27.0.3" + "@udecode/plate-heading": "npm:27.0.3" + "@udecode/plate-horizontal-rule": "npm:27.0.3" + "@udecode/plate-link": "npm:27.0.3" + "@udecode/plate-list": "npm:27.0.3" + "@udecode/plate-media": "npm:27.0.3" + "@udecode/plate-paragraph": "npm:27.0.3" remark-parse: "npm:^9.0.0" unified: "npm:^9.2.2" peerDependencies: @@ -6755,11 +6755,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-suggestion@npm:27.0.0, @udecode/plate-suggestion@workspace:^, @udecode/plate-suggestion@workspace:packages/suggestion": +"@udecode/plate-suggestion@npm:27.0.3, @udecode/plate-suggestion@workspace:^, @udecode/plate-suggestion@workspace:packages/suggestion": version: 0.0.0-use.local resolution: "@udecode/plate-suggestion@workspace:packages/suggestion" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6770,11 +6770,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-tabbable@npm:27.0.0, @udecode/plate-tabbable@workspace:^, @udecode/plate-tabbable@workspace:packages/tabbable": +"@udecode/plate-tabbable@npm:27.0.3, @udecode/plate-tabbable@workspace:^, @udecode/plate-tabbable@workspace:packages/tabbable": version: 0.0.0-use.local resolution: "@udecode/plate-tabbable@workspace:packages/tabbable" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" tabbable: "npm:^6.2.0" peerDependencies: react: ">=16.8.0" @@ -6786,12 +6786,12 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-table@npm:27.0.2, @udecode/plate-table@workspace:^, @udecode/plate-table@workspace:packages/table": +"@udecode/plate-table@npm:27.0.3, @udecode/plate-table@workspace:^, @udecode/plate-table@workspace:packages/table": version: 0.0.0-use.local resolution: "@udecode/plate-table@workspace:packages/table" dependencies: - "@udecode/plate-common": "npm:27.0.0" - "@udecode/plate-resizable": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" + "@udecode/plate-resizable": "npm:27.0.3" lodash: "npm:^4.17.21" peerDependencies: react: ">=16.8.0" @@ -6811,11 +6811,11 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-trailing-block@npm:27.0.0, @udecode/plate-trailing-block@workspace:^, @udecode/plate-trailing-block@workspace:packages/trailing-block": +"@udecode/plate-trailing-block@npm:27.0.3, @udecode/plate-trailing-block@workspace:^, @udecode/plate-trailing-block@workspace:packages/trailing-block": version: 0.0.0-use.local resolution: "@udecode/plate-trailing-block@workspace:packages/trailing-block" dependencies: - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -6855,12 +6855,12 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-utils@npm:27.0.0, @udecode/plate-utils@workspace:^, @udecode/plate-utils@workspace:packages/plate-utils": +"@udecode/plate-utils@npm:27.0.3, @udecode/plate-utils@workspace:^, @udecode/plate-utils@workspace:packages/plate-utils": version: 0.0.0-use.local resolution: "@udecode/plate-utils@workspace:packages/plate-utils" dependencies: "@radix-ui/react-slot": "npm:^1.0.2" - "@udecode/plate-core": "npm:27.0.0" + "@udecode/plate-core": "npm:27.0.3" "@udecode/slate": "npm:25.0.0" "@udecode/slate-react": "npm:25.0.0" "@udecode/slate-utils": "npm:25.0.0" @@ -6883,7 +6883,7 @@ __metadata: dependencies: "@hocuspocus/provider": "npm:^2.2.1" "@slate-yjs/core": "npm:^1.0.1" - "@udecode/plate-common": "npm:27.0.0" + "@udecode/plate-common": "npm:27.0.3" yjs: "npm:^13.5.42" peerDependencies: react: ">=16.8.0" @@ -6899,44 +6899,44 @@ __metadata: version: 0.0.0-use.local resolution: "@udecode/plate@workspace:packages/plate" dependencies: - "@udecode/plate-alignment": "npm:27.0.0" - "@udecode/plate-autoformat": "npm:27.0.0" - "@udecode/plate-basic-elements": "npm:27.0.0" - "@udecode/plate-basic-marks": "npm:27.0.0" - "@udecode/plate-block-quote": "npm:27.0.0" - "@udecode/plate-break": "npm:27.0.0" - "@udecode/plate-code-block": "npm:27.0.0" - "@udecode/plate-combobox": "npm:27.0.0" - "@udecode/plate-comments": "npm:27.0.0" - "@udecode/plate-common": "npm:27.0.0" - "@udecode/plate-find-replace": "npm:27.0.0" - "@udecode/plate-floating": "npm:27.0.0" - "@udecode/plate-font": "npm:27.0.0" - "@udecode/plate-heading": "npm:27.0.0" - "@udecode/plate-highlight": "npm:27.0.0" - "@udecode/plate-horizontal-rule": "npm:27.0.0" - "@udecode/plate-indent": "npm:27.0.0" - "@udecode/plate-indent-list": "npm:27.0.0" - "@udecode/plate-kbd": "npm:27.0.0" - "@udecode/plate-line-height": "npm:27.0.0" - "@udecode/plate-link": "npm:27.0.0" - "@udecode/plate-list": "npm:27.0.0" - "@udecode/plate-media": "npm:27.0.0" - "@udecode/plate-mention": "npm:27.0.0" - "@udecode/plate-node-id": "npm:27.0.0" - "@udecode/plate-normalizers": "npm:27.0.0" - "@udecode/plate-paragraph": "npm:27.0.0" - "@udecode/plate-reset-node": "npm:27.0.0" - "@udecode/plate-resizable": "npm:27.0.0" - "@udecode/plate-select": "npm:27.0.0" - "@udecode/plate-serializer-csv": "npm:27.0.2" - "@udecode/plate-serializer-docx": "npm:27.0.2" - "@udecode/plate-serializer-html": "npm:27.0.0" - "@udecode/plate-serializer-md": "npm:27.0.0" - "@udecode/plate-suggestion": "npm:27.0.0" - "@udecode/plate-tabbable": "npm:27.0.0" - "@udecode/plate-table": "npm:27.0.2" - "@udecode/plate-trailing-block": "npm:27.0.0" + "@udecode/plate-alignment": "npm:27.0.3" + "@udecode/plate-autoformat": "npm:27.0.3" + "@udecode/plate-basic-elements": "npm:27.0.3" + "@udecode/plate-basic-marks": "npm:27.0.3" + "@udecode/plate-block-quote": "npm:27.0.3" + "@udecode/plate-break": "npm:27.0.3" + "@udecode/plate-code-block": "npm:27.0.3" + "@udecode/plate-combobox": "npm:27.0.3" + "@udecode/plate-comments": "npm:27.0.3" + "@udecode/plate-common": "npm:27.0.3" + "@udecode/plate-find-replace": "npm:27.0.3" + "@udecode/plate-floating": "npm:27.0.3" + "@udecode/plate-font": "npm:27.0.3" + "@udecode/plate-heading": "npm:27.0.3" + "@udecode/plate-highlight": "npm:27.0.3" + "@udecode/plate-horizontal-rule": "npm:27.0.3" + "@udecode/plate-indent": "npm:27.0.3" + "@udecode/plate-indent-list": "npm:27.0.3" + "@udecode/plate-kbd": "npm:27.0.3" + "@udecode/plate-line-height": "npm:27.0.3" + "@udecode/plate-link": "npm:27.0.3" + "@udecode/plate-list": "npm:27.0.3" + "@udecode/plate-media": "npm:27.0.3" + "@udecode/plate-mention": "npm:27.0.3" + "@udecode/plate-node-id": "npm:27.0.3" + "@udecode/plate-normalizers": "npm:27.0.3" + "@udecode/plate-paragraph": "npm:27.0.3" + "@udecode/plate-reset-node": "npm:27.0.3" + "@udecode/plate-resizable": "npm:27.0.3" + "@udecode/plate-select": "npm:27.0.3" + "@udecode/plate-serializer-csv": "npm:27.0.3" + "@udecode/plate-serializer-docx": "npm:27.0.3" + "@udecode/plate-serializer-html": "npm:27.0.3" + "@udecode/plate-serializer-md": "npm:27.0.3" + "@udecode/plate-suggestion": "npm:27.0.3" + "@udecode/plate-tabbable": "npm:27.0.3" + "@udecode/plate-table": "npm:27.0.3" + "@udecode/plate-trailing-block": "npm:27.0.3" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" @@ -13522,9 +13522,9 @@ __metadata: languageName: node linkType: hard -"jotai-x@npm:^1.0.1": - version: 1.0.1 - resolution: "jotai-x@npm:1.0.1" +"jotai-x@npm:0.0.0-20231221184746": + version: 0.0.0-20231221184746 + resolution: "jotai-x@npm:0.0.0-20231221184746" peerDependencies: "@types/react": ">=17.0.0" jotai: ">=2.0.0" @@ -13534,7 +13534,7 @@ __metadata: optional: true react: optional: true - checksum: 67cbcd3ead992765b7a6f72e369f63da4a13519474c13a9d9f4acb35f2c205ee79c3e6ed0e698d17de6662f2c6cf97eb4e89486c6cd3e0d4f266b21094eaec1d + checksum: d7076a068f5a444d9982a53cf2031448df0a1b78ccf3dff97a8a511876a42c7205da5f58861f0f23ff778434aa7963766048da5fee6b1e8bdea4fe568c879835 languageName: node linkType: hard From 3ddd5fdaa971e9e0fc2a7ebc0df6a7acc811166f Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Thu, 21 Dec 2023 19:39:45 +0000 Subject: [PATCH 02/13] Remove redundant useMyPlate(Selectors|Actions|States) hooks --- apps/www/src/types/plate-types.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/www/src/types/plate-types.ts b/apps/www/src/types/plate-types.ts index 1750a300f5..f70a6799d9 100644 --- a/apps/www/src/types/plate-types.ts +++ b/apps/www/src/types/plate-types.ts @@ -371,12 +371,6 @@ export const getMyEditor = (editor: MyEditor) => getTEditor(editor); export const useMyEditorRef = () => useEditorRef(); export const useMyEditorState = () => useEditorState(); -export const useMyPlateSelectors = (id?: PlateId) => - usePlateSelectors(id); -export const useMyPlateActions = (id?: PlateId) => - usePlateActions(id); -export const useMyPlateStates = (id?: PlateId) => - usePlateStates(id); /** * Utils From a6a0a521eb6599424f366356e6a99060680ab8e4 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Thu, 21 Dec 2023 21:13:59 +0000 Subject: [PATCH 03/13] Replace all uses of `useEditorState` with `useEditorSelector` --- .../playground-insert-dropdown-menu.tsx | 4 +-- .../playground-mode-dropdown-menu.tsx | 4 +-- .../playground-more-dropdown-menu.tsx | 4 +-- .../playground-turn-into-dropdown-menu.tsx | 31 ++++++++++------- .../registry/default/plate-ui/combobox.tsx | 11 +++--- .../default/plate-ui/insert-dropdown-menu.tsx | 4 +-- .../default/plate-ui/media-popover.tsx | 7 ++-- .../default/plate-ui/mode-dropdown-menu.tsx | 4 +-- .../default/plate-ui/more-dropdown-menu.tsx | 4 +-- .../default/plate-ui/table-dropdown-menu.tsx | 12 ++++--- .../default/plate-ui/table-element.tsx | 11 +++--- .../plate-ui/turn-into-dropdown-menu.tsx | 31 ++++++++++------- .../src/hooks/useAlignDropdownMenu.ts | 30 ++++++++-------- .../src/hooks/useEmojiDropdownMenuState.ts | 5 +-- .../src/utils/EmojiPicker/useEmojiPicker.ts | 6 ++-- .../floating/src/hooks/useFloatingToolbar.ts | 20 +++++------ .../font/src/hooks/useColorDropdownMenu.ts | 25 ++++++++++---- .../src/hooks/useIndentListToolbarButton.ts | 9 +++-- .../src/hooks/useLineHeightDropdownMenu.ts | 23 +++++++------ .../src/components/useLinkToolbarButton.ts | 14 +++++--- .../list/src/hooks/useListToolbarButton.ts | 11 +++--- .../src/hooks/useMarkToolbarButton.ts | 8 +++-- packages/tabbable/src/TabbableEffects.tsx | 18 ++++------ ...useTableBordersDropdownMenuContentState.ts | 20 +++++++---- .../table/src/merge/useTableMergeState.ts | 34 +++++++------------ 25 files changed, 192 insertions(+), 158 deletions(-) diff --git a/apps/www/src/components/plate-ui/playground-insert-dropdown-menu.tsx b/apps/www/src/components/plate-ui/playground-insert-dropdown-menu.tsx index 60a0c65aca..4b44e881e7 100644 --- a/apps/www/src/components/plate-ui/playground-insert-dropdown-menu.tsx +++ b/apps/www/src/components/plate-ui/playground-insert-dropdown-menu.tsx @@ -10,7 +10,7 @@ import { import { focusEditor, insertEmptyElement, - useEditorState, + useEditorRef, } from '@udecode/plate-common'; import { ELEMENT_EXCALIDRAW } from '@udecode/plate-excalidraw'; import { @@ -170,7 +170,7 @@ const items = [ ]; export function PlaygroundInsertDropdownMenu(props: DropdownMenuProps) { - const editor = useEditorState(); + const editor = useEditorRef(); const openState = useOpenState(); return ( diff --git a/apps/www/src/components/plate-ui/playground-mode-dropdown-menu.tsx b/apps/www/src/components/plate-ui/playground-mode-dropdown-menu.tsx index 73eef1456f..bae54b9afe 100644 --- a/apps/www/src/components/plate-ui/playground-mode-dropdown-menu.tsx +++ b/apps/www/src/components/plate-ui/playground-mode-dropdown-menu.tsx @@ -3,7 +3,7 @@ import { DropdownMenuProps } from '@radix-ui/react-dropdown-menu'; import { focusEditor, useEditorReadOnly, - useEditorState, + useEditorRef, usePlateStore, } from '@udecode/plate-common'; @@ -19,7 +19,7 @@ import { import { ToolbarButton } from '@/registry/default/plate-ui/toolbar'; export function PlaygroundModeDropdownMenu(props: DropdownMenuProps) { - const editor = useEditorState(); + const editor = useEditorRef(); const setReadOnly = usePlateStore().set.readOnly(); const readOnly = useEditorReadOnly(); const openState = useOpenState(); diff --git a/apps/www/src/components/plate-ui/playground-more-dropdown-menu.tsx b/apps/www/src/components/plate-ui/playground-more-dropdown-menu.tsx index 38f375115d..5427cb36ce 100644 --- a/apps/www/src/components/plate-ui/playground-more-dropdown-menu.tsx +++ b/apps/www/src/components/plate-ui/playground-more-dropdown-menu.tsx @@ -5,7 +5,7 @@ import { collapseSelection, focusEditor, toggleMark, - useEditorState, + useEditorRef, } from '@udecode/plate-common'; import { MARK_HIGHLIGHT } from '@udecode/plate-highlight'; import { MARK_KBD } from '@udecode/plate-kbd'; @@ -21,7 +21,7 @@ import { import { ToolbarButton } from '@/registry/default/plate-ui/toolbar'; export function PlaygroundMoreDropdownMenu(props: DropdownMenuProps) { - const editor = useEditorState(); + const editor = useEditorRef(); const openState = useOpenState(); return ( diff --git a/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx b/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx index e40aa3df2c..6d82092202 100644 --- a/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx +++ b/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx @@ -6,10 +6,11 @@ import { findNode, focusEditor, isBlock, - isCollapsed, + isSelectionExpanded, TElement, toggleNodeType, - useEditorState, + useEditorRef, + useEditorSelector, } from '@udecode/plate-common'; import { ELEMENT_H1, @@ -105,20 +106,24 @@ const items = [ const defaultItem = items.find((item) => item.value === ELEMENT_PARAGRAPH)!; export function PlaygroundTurnIntoDropdownMenu(props: DropdownMenuProps) { - const editor = useEditorState(); + const editor = useEditorRef(); const openState = useOpenState(); - let value: string = ELEMENT_PARAGRAPH; - if (isCollapsed(editor?.selection)) { - const entry = findNode(editor!, { - match: (n) => isBlock(editor, n), - }); - if (entry) { - value = - items.find((item) => item.value === entry[0].type)?.value ?? - ELEMENT_PARAGRAPH; + // eslint-disable-next-line no-shadow + const value: string = useEditorSelector((editor) => { + if (!isSelectionExpanded(editor)) { + const entry = findNode(editor!, { + match: (n) => isBlock(editor, n), + }); + + if (entry) { + return items.find((item) => item.value === entry[0].type)?.value ?? + ELEMENT_PARAGRAPH; + } } - } + + return ELEMENT_PARAGRAPH; + }, []); const selectedItem = items.find((item) => item.value === value) ?? defaultItem; diff --git a/apps/www/src/registry/default/plate-ui/combobox.tsx b/apps/www/src/registry/default/plate-ui/combobox.tsx index afae2a97ff..2b5c9f0617 100644 --- a/apps/www/src/registry/default/plate-ui/combobox.tsx +++ b/apps/www/src/registry/default/plate-ui/combobox.tsx @@ -17,7 +17,7 @@ import { useComboboxItem, useComboboxSelectors, } from '@udecode/plate-combobox'; -import { useEditorState, useEventEditorSelectors } from '@udecode/plate-common'; +import { useEditorRef, useEditorSelector, useEventEditorSelectors, usePlateSelectors } from '@udecode/plate-common'; import { createVirtualRef } from '@udecode/plate-floating'; import { cn } from '@/lib/utils'; @@ -52,7 +52,7 @@ export function ComboboxContent( onRenderItem, } = props; - const editor = useEditorState(); + const editor = useEditorRef(); const filteredItems = useComboboxSelectors.filteredItems() as TComboboxItem[]; @@ -118,7 +118,8 @@ export function Combobox({ const focusedEditorId = useEventEditorSelectors.focus?.(); const combobox = useComboboxControls(); const activeId = useComboboxSelectors.activeId(); - const editor = useEditorState(); + const selectionDefined = useEditorSelector((editor => !!editor.selection), []); + const editorId = usePlateSelectors().id(); useEffect(() => { comboboxActions.setComboboxById({ @@ -144,8 +145,8 @@ export function Combobox({ if ( !combobox || - !editor.selection || - focusedEditorId !== editor.id || + !selectionDefined || + focusedEditorId !== editorId || activeId !== id || disabled ) { diff --git a/apps/www/src/registry/default/plate-ui/insert-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/insert-dropdown-menu.tsx index 02c221dc8e..fd222cccf0 100644 --- a/apps/www/src/registry/default/plate-ui/insert-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/insert-dropdown-menu.tsx @@ -6,7 +6,7 @@ import { ELEMENT_BLOCKQUOTE } from '@udecode/plate-block-quote'; import { focusEditor, insertEmptyElement, - useEditorState, + useEditorRef, } from '@udecode/plate-common'; import { ELEMENT_H1, ELEMENT_H2, ELEMENT_H3 } from '@udecode/plate-heading'; import { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph'; @@ -127,7 +127,7 @@ const items = [ ]; export function InsertDropdownMenu(props: DropdownMenuProps) { - const editor = useEditorState(); + const editor = useEditorRef(); const openState = useOpenState(); return ( diff --git a/apps/www/src/registry/default/plate-ui/media-popover.tsx b/apps/www/src/registry/default/plate-ui/media-popover.tsx index d3422d14c9..65505e14c3 100644 --- a/apps/www/src/registry/default/plate-ui/media-popover.tsx +++ b/apps/www/src/registry/default/plate-ui/media-popover.tsx @@ -1,7 +1,8 @@ import React, { useEffect } from 'react'; import { isCollapsed, - useEditorState, + isSelectionExpanded, + useEditorSelector, useElement, useRemoveNodeButton, } from '@udecode/plate-common'; @@ -27,9 +28,9 @@ export interface MediaPopoverProps { export function MediaPopover({ pluginKey, children }: MediaPopoverProps) { const readOnly = useReadOnly(); const selected = useSelected(); - const editor = useEditorState(); - const isOpen = !readOnly && selected && isCollapsed(editor.selection); + const selectionCollapsed = useEditorSelector((editor) => !isSelectionExpanded(editor), []); + const isOpen = !readOnly && selected && selectionCollapsed; const isEditing = useFloatingMediaSelectors().isEditing(); useEffect(() => { diff --git a/apps/www/src/registry/default/plate-ui/mode-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/mode-dropdown-menu.tsx index a931815f68..4136cdfc7c 100644 --- a/apps/www/src/registry/default/plate-ui/mode-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/mode-dropdown-menu.tsx @@ -3,7 +3,7 @@ import { DropdownMenuProps } from '@radix-ui/react-dropdown-menu'; import { focusEditor, useEditorReadOnly, - useEditorState, + useEditorRef, usePlateStore, } from '@udecode/plate-common'; @@ -20,7 +20,7 @@ import { import { ToolbarButton } from './toolbar'; export function ModeDropdownMenu(props: DropdownMenuProps) { - const editor = useEditorState(); + const editor = useEditorRef(); const setReadOnly = usePlateStore().set.readOnly(); const readOnly = useEditorReadOnly(); const openState = useOpenState(); diff --git a/apps/www/src/registry/default/plate-ui/more-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/more-dropdown-menu.tsx index 60f3b3bfd8..83853bf94d 100644 --- a/apps/www/src/registry/default/plate-ui/more-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/more-dropdown-menu.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { DropdownMenuProps } from '@radix-ui/react-dropdown-menu'; import { MARK_SUBSCRIPT, MARK_SUPERSCRIPT } from '@udecode/plate-basic-marks'; -import { focusEditor, toggleMark, useEditorState } from '@udecode/plate-common'; +import { focusEditor, toggleMark, useEditorRef } from '@udecode/plate-common'; import { Icons } from '@/components/icons'; @@ -15,7 +15,7 @@ import { import { ToolbarButton } from './toolbar'; export function MoreDropdownMenu(props: DropdownMenuProps) { - const editor = useEditorState(); + const editor = useEditorRef(); const openState = useOpenState(); return ( diff --git a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx index 99f085f8c3..ab7ccaf68a 100644 --- a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { DropdownMenuProps } from '@radix-ui/react-dropdown-menu'; -import { focusEditor, someNode, useEditorState } from '@udecode/plate-common'; +import { focusEditor, someNode, useEditorRef, useEditorSelector } from '@udecode/plate-common'; import { deleteColumn, deleteRow, @@ -26,11 +26,13 @@ import { import { ToolbarButton } from './toolbar'; export function TableDropdownMenu(props: DropdownMenuProps) { - const editor = useEditorState(); + const editor = useEditorRef(); - const tableSelected = someNode(editor, { - match: { type: ELEMENT_TABLE }, - }); + // eslint-disable-next-line no-shadow + const tableSelected = useEditorSelector((editor) => + someNode(editor, { match: { type: ELEMENT_TABLE } }), + [] + ); const openState = useOpenState(); diff --git a/apps/www/src/registry/default/plate-ui/table-element.tsx b/apps/www/src/registry/default/plate-ui/table-element.tsx index b016d57db9..e1b322f76b 100644 --- a/apps/www/src/registry/default/plate-ui/table-element.tsx +++ b/apps/www/src/registry/default/plate-ui/table-element.tsx @@ -2,10 +2,11 @@ import React, { forwardRef } from 'react'; import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; import { PopoverAnchor, PopoverContentProps } from '@radix-ui/react-popover'; import { - isCollapsed, + isSelectionExpanded, PlateElement, PlateElementProps, - useEditorState, + useEditorRef, + useEditorSelector, useElement, useRemoveNodeButton, } from '@udecode/plate-common'; @@ -116,9 +117,11 @@ const TableFloatingToolbar = React.forwardRef< const readOnly = useReadOnly(); const selected = useSelected(); - const editor = useEditorState(); + const editor = useEditorRef(); - const collapsed = !readOnly && selected && isCollapsed(editor.selection); + // eslint-disable-next-line no-shadow + const selectionCollapsed = useEditorSelector((editor) => !isSelectionExpanded(editor), []); + const collapsed = !readOnly && selected && selectionCollapsed; const open = !readOnly && selected; const { canMerge, canUnmerge } = useTableMergeState(); diff --git a/apps/www/src/registry/default/plate-ui/turn-into-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/turn-into-dropdown-menu.tsx index 16818e7ee4..a16d828a2d 100644 --- a/apps/www/src/registry/default/plate-ui/turn-into-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/turn-into-dropdown-menu.tsx @@ -9,7 +9,8 @@ import { isCollapsed, TElement, toggleNodeType, - useEditorState, + useEditorRef, + useEditorSelector, } from '@udecode/plate-common'; import { ELEMENT_H1, ELEMENT_H2, ELEMENT_H3 } from '@udecode/plate-heading'; import { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph'; @@ -75,20 +76,26 @@ const items = [ const defaultItem = items.find((item) => item.value === ELEMENT_PARAGRAPH)!; export function TurnIntoDropdownMenu(props: DropdownMenuProps) { - const editor = useEditorState(); + const editor = useEditorRef(); const openState = useOpenState(); - let value: string = ELEMENT_PARAGRAPH; - if (isCollapsed(editor?.selection)) { - const entry = findNode(editor!, { - match: (n) => isBlock(editor, n), - }); - if (entry) { - value = - items.find((item) => item.value === entry[0].type)?.value ?? - ELEMENT_PARAGRAPH; + // eslint-disable-next-line no-shadow + const value: string = useEditorSelector((editor) => { + if (isCollapsed(editor.selection)) { + const entry = findNode(editor, { + match: (n) => isBlock(editor, n), + }); + + if (entry) { + return ( + items.find((item) => item.value === entry[0].type)?.value ?? + ELEMENT_PARAGRAPH + ); + } } - } + + return ELEMENT_PARAGRAPH; + }, []); const selectedItem = items.find((item) => item.value === value) ?? defaultItem; diff --git a/packages/alignment/src/hooks/useAlignDropdownMenu.ts b/packages/alignment/src/hooks/useAlignDropdownMenu.ts index a53fda7208..5fdaff1d33 100644 --- a/packages/alignment/src/hooks/useAlignDropdownMenu.ts +++ b/packages/alignment/src/hooks/useAlignDropdownMenu.ts @@ -4,26 +4,28 @@ import { isCollapsed, isDefined, useEditorRef, - useEditorState, + useEditorSelector, } from '@udecode/plate-common'; import { Alignment, KEY_ALIGN, setAlign } from '../index'; export const useAlignDropdownMenuState = () => { - const editor = useEditorState(); - - let value: Alignment = 'left'; - if (isCollapsed(editor?.selection)) { - const entry = findNode(editor!, { - match: (n) => isDefined(n[KEY_ALIGN]), - }); - if (entry) { - const nodeValue = entry[0][KEY_ALIGN] as string; - if (nodeValue === 'right') value = 'right'; - if (nodeValue === 'center') value = 'center'; - if (nodeValue === 'justify') value = 'justify'; + const value: Alignment = useEditorSelector((editor) => { + if (isCollapsed(editor.selection)) { + const entry = findNode(editor, { + match: (n) => isDefined(n[KEY_ALIGN]), + }); + + if (entry) { + const nodeValue = entry[0][KEY_ALIGN] as string; + if (nodeValue === 'right') return 'right'; + if (nodeValue === 'center') return 'center'; + if (nodeValue === 'justify') return 'justify'; + } } - } + + return 'left'; + }, []); return { value, diff --git a/packages/emoji/src/hooks/useEmojiDropdownMenuState.ts b/packages/emoji/src/hooks/useEmojiDropdownMenuState.ts index 9efe3e5769..99dfed7248 100644 --- a/packages/emoji/src/hooks/useEmojiDropdownMenuState.ts +++ b/packages/emoji/src/hooks/useEmojiDropdownMenuState.ts @@ -1,4 +1,4 @@ -import { useEditorState, useStableMemo } from '@udecode/plate-common'; +import { useStableMemo } from '@udecode/plate-common'; import { EmojiFloatingIndexSearch, @@ -18,8 +18,6 @@ export function useEmojiDropdownMenuState({ settings = EmojiSettings, closeOnSelect = true, }: EmojiDropdownMenuOptions = {}) { - const editor = useEditorState(); - const [emojiLibrary, indexSearch] = useStableMemo(() => { const frequentEmojiStorage = new FrequentEmojiStorage({ limit: settings.showFrequent.limit, @@ -39,7 +37,6 @@ export function useEmojiDropdownMenuState({ const { isOpen, setIsOpen, ...emojiPickerState } = useEmojiPicker({ closeOnSelect, - editor, emojiLibrary, indexSearch, }); diff --git a/packages/emoji/src/utils/EmojiPicker/useEmojiPicker.ts b/packages/emoji/src/utils/EmojiPicker/useEmojiPicker.ts index ed9a538eba..20ca75abcc 100644 --- a/packages/emoji/src/utils/EmojiPicker/useEmojiPicker.ts +++ b/packages/emoji/src/utils/EmojiPicker/useEmojiPicker.ts @@ -6,7 +6,7 @@ import { useEffect, useRef, } from 'react'; -import { PlateEditor } from '@udecode/plate-common'; +import { useEditorRef } from '@udecode/plate-common'; import { i18n } from '../../constants'; import { getEmojiOnInsert } from '../../handlers/getEmojiOnInsert'; @@ -31,7 +31,6 @@ export type MutableRefs = MutableRefObject<{ export type UseEmojiPickerProps = { closeOnSelect: boolean; - editor: PlateEditor; emojiLibrary: IEmojiFloatingLibrary; indexSearch: AIndexSearch; }; @@ -62,11 +61,12 @@ export type UseEmojiPickerType< }; export const useEmojiPicker = ({ - editor, emojiLibrary, indexSearch, closeOnSelect, }: UseEmojiPickerProps): Omit => { + const editor = useEditorRef(); + const [state, dispatch] = EmojiPickerState(); const refs = useRef({ contentRoot: createRef(), diff --git a/packages/floating/src/hooks/useFloatingToolbar.ts b/packages/floating/src/hooks/useFloatingToolbar.ts index 67fafe66b3..ebb464d311 100644 --- a/packages/floating/src/hooks/useFloatingToolbar.ts +++ b/packages/floating/src/hooks/useFloatingToolbar.ts @@ -3,8 +3,9 @@ import { getSelectionText, isSelectionExpanded, mergeProps, - useEditorState, + useEditorSelector, useEventEditorSelectors, + usePlateSelectors, } from '@udecode/plate-common'; import { useFocused } from 'slate-react'; @@ -25,7 +26,10 @@ export const useFloatingToolbarState = ({ hideToolbar, ignoreReadOnly, }: FloatingToolbarState) => { - const editor = useEditorState(); + const editorId = usePlateSelectors().id(); + const selectionExpanded = useEditorSelector(isSelectionExpanded, []); + const selectionText = useEditorSelector(getSelectionText, []); + const focusedEditorId = useEventEditorSelectors.focus(); const focused = useFocused(); @@ -33,9 +37,6 @@ export const useFloatingToolbarState = ({ const [waitForCollapsedSelection, setWaitForCollapsedSelection] = useState(false); - const selectionExpanded = editor && isSelectionExpanded(editor); - const selectionText = editor && getSelectionText(editor); - const floating = useVirtualFloating( mergeProps( { @@ -48,7 +49,7 @@ export const useFloatingToolbarState = ({ ); return { - editor, + editorId, open, setOpen, waitForCollapsedSelection, @@ -64,7 +65,7 @@ export const useFloatingToolbarState = ({ }; export const useFloatingToolbar = ({ - editor, + editorId, selectionExpanded, selectionText, waitForCollapsedSelection, @@ -98,7 +99,7 @@ export const useFloatingToolbar = ({ if ( !selectionExpanded || !selectionText || - (!(editor.id === focusedEditorId || ignoreReadOnly) && hideToolbar) + (!(editorId === focusedEditorId || ignoreReadOnly) && hideToolbar) ) { setOpen(false); } else if ( @@ -110,8 +111,7 @@ export const useFloatingToolbar = ({ } }, [ setOpen, - editor.id, - editor.selection, + editorId, focusedEditorId, hideToolbar, ignoreReadOnly, diff --git a/packages/font/src/hooks/useColorDropdownMenu.ts b/packages/font/src/hooks/useColorDropdownMenu.ts index 4b33984b9d..cabffe2e77 100644 --- a/packages/font/src/hooks/useColorDropdownMenu.ts +++ b/packages/font/src/hooks/useColorDropdownMenu.ts @@ -5,7 +5,8 @@ import { removeMark, select, setMarks, - useEditorState, + useEditorRef, + useEditorSelector, } from '@udecode/plate-common'; export const useColorDropdownMenuState = ({ @@ -19,9 +20,19 @@ export const useColorDropdownMenuState = ({ customColors: { name: string; value: string; isBrightColor: boolean }[]; closeOnSelect?: boolean; }) => { - const editor = useEditorState(); + const editor = useEditorRef(); - const color = editor && (getMark(editor, nodeType) as string); + const selectionDefined = useEditorSelector( + // eslint-disable-next-line no-shadow + (editor) => !!editor.selection, + [] + ); + + const color = useEditorSelector( + // eslint-disable-next-line no-shadow + (editor) => getMark(editor, nodeType) as string, + [nodeType] + ); const [selectedColor, setSelectedColor] = useState(); @@ -35,7 +46,7 @@ export const useColorDropdownMenuState = ({ const updateColor = useCallback( (value: string) => { - if (editor && editor && editor.selection) { + if (editor.selection) { setSelectedColor(value); select(editor, editor.selection); @@ -56,7 +67,7 @@ export const useColorDropdownMenuState = ({ ); const clearColor = useCallback(() => { - if (editor && editor && editor.selection) { + if (editor.selection) { select(editor, editor.selection); focusEditor(editor); @@ -69,10 +80,10 @@ export const useColorDropdownMenuState = ({ }, [editor, selectedColor, closeOnSelect, onToggle, nodeType]); useEffect(() => { - if (editor?.selection) { + if (selectionDefined) { setSelectedColor(color); } - }, [color, editor?.selection]); + }, [color, selectionDefined]); return { open, diff --git a/packages/indent-list/src/hooks/useIndentListToolbarButton.ts b/packages/indent-list/src/hooks/useIndentListToolbarButton.ts index fcc32f2431..80007c76bb 100644 --- a/packages/indent-list/src/hooks/useIndentListToolbarButton.ts +++ b/packages/indent-list/src/hooks/useIndentListToolbarButton.ts @@ -1,4 +1,4 @@ -import { useEditorRef, useEditorState } from '@udecode/plate-common'; +import { useEditorRef, useEditorSelector } from '@udecode/plate-common'; import { ListStyleType, toggleIndentList } from '../index'; import { someIndentList } from './someIndentList'; @@ -6,10 +6,13 @@ import { someIndentList } from './someIndentList'; export const useIndentListToolbarButtonState = ({ nodeType = ListStyleType.Disc, }: { nodeType?: string } = {}) => { - const editor = useEditorState(); + const pressed = useEditorSelector( + (editor) => someIndentList(editor, nodeType), + [nodeType] + ); return { - pressed: someIndentList(editor, nodeType), + pressed, nodeType, }; }; diff --git a/packages/line-height/src/hooks/useLineHeightDropdownMenu.ts b/packages/line-height/src/hooks/useLineHeightDropdownMenu.ts index 14151e3679..46cb0a0170 100644 --- a/packages/line-height/src/hooks/useLineHeightDropdownMenu.ts +++ b/packages/line-height/src/hooks/useLineHeightDropdownMenu.ts @@ -5,25 +5,28 @@ import { isCollapsed, TElement, useEditorRef, - useEditorState, + useEditorSelector, } from '@udecode/plate-common'; import { KEY_LINE_HEIGHT, setLineHeight } from '../index'; export const useLineHeightDropdownMenuState = () => { - const editor = useEditorState(); + const editor = useEditorRef(); const { validNodeValues: values = [], defaultNodeValue } = getPluginInjectProps(editor, KEY_LINE_HEIGHT); - let value: string | undefined; - if (isCollapsed(editor?.selection)) { - const entry = getBlockAbove(editor); - if (entry) { - value = - values.find((item) => item === entry[0][KEY_LINE_HEIGHT]) ?? - defaultNodeValue; + // eslint-disable-next-line no-shadow + const value: string | undefined = useEditorSelector((editor) => { + if (isCollapsed(editor.selection)) { + const entry = getBlockAbove(editor); + if (entry) { + return ( + values.find((item) => item === entry[0][KEY_LINE_HEIGHT]) ?? + defaultNodeValue + ); + } } - } + }, []); return { value, diff --git a/packages/link/src/components/useLinkToolbarButton.ts b/packages/link/src/components/useLinkToolbarButton.ts index c6529a502b..b2fdeff198 100644 --- a/packages/link/src/components/useLinkToolbarButton.ts +++ b/packages/link/src/components/useLinkToolbarButton.ts @@ -2,16 +2,20 @@ import { getPluginType, someNode, useEditorRef, - useEditorState, + useEditorSelector, } from '@udecode/plate-common'; import { ELEMENT_LINK, triggerFloatingLink } from '../index'; export const useLinkToolbarButtonState = () => { - const editor = useEditorState(); - const pressed = - !!editor?.selection && - someNode(editor, { match: { type: getPluginType(editor, ELEMENT_LINK) } }); + const pressed = useEditorSelector( + (editor) => + !!editor?.selection && + someNode(editor, { + match: { type: getPluginType(editor, ELEMENT_LINK) }, + }), + [] + ); return { pressed, diff --git a/packages/list/src/hooks/useListToolbarButton.ts b/packages/list/src/hooks/useListToolbarButton.ts index 9e64afb489..cc7f9cc243 100644 --- a/packages/list/src/hooks/useListToolbarButton.ts +++ b/packages/list/src/hooks/useListToolbarButton.ts @@ -2,16 +2,17 @@ import { getPluginType, someNode, useEditorRef, - useEditorState, + useEditorSelector, } from '@udecode/plate-common'; import { ELEMENT_UL, toggleList } from '../index'; export const useListToolbarButtonState = ({ nodeType = ELEMENT_UL } = {}) => { - const editor = useEditorState(); - const pressed = - !!editor?.selection && - someNode(editor, { match: { type: getPluginType(editor, nodeType) } }); + const pressed = useEditorSelector((editor) => + !!editor.selection && + someNode(editor, { match: { type: getPluginType(editor, nodeType) } }), + [nodeType] + ); return { pressed, diff --git a/packages/plate-utils/src/hooks/useMarkToolbarButton.ts b/packages/plate-utils/src/hooks/useMarkToolbarButton.ts index 00f3e689de..fd4a14d752 100644 --- a/packages/plate-utils/src/hooks/useMarkToolbarButton.ts +++ b/packages/plate-utils/src/hooks/useMarkToolbarButton.ts @@ -1,4 +1,4 @@ -import { useEditorRef, useEditorState } from '@udecode/plate-core'; +import { useEditorRef, useEditorSelector } from '@udecode/plate-core'; import { isMarkActive, toggleMark } from '@udecode/slate-utils'; export const useMarkToolbarButtonState = ({ @@ -8,8 +8,10 @@ export const useMarkToolbarButtonState = ({ nodeType: string; clear?: string | string[]; }) => { - const editor = useEditorState(); - const pressed = !!editor?.selection && isMarkActive(editor, nodeType); + const pressed = useEditorSelector( + (editor) => isMarkActive(editor, nodeType), + [nodeType] + ); return { pressed, diff --git a/packages/tabbable/src/TabbableEffects.tsx b/packages/tabbable/src/TabbableEffects.tsx index 262910ddc6..67b3346e67 100644 --- a/packages/tabbable/src/TabbableEffects.tsx +++ b/packages/tabbable/src/TabbableEffects.tsx @@ -6,7 +6,7 @@ import { toDOMNode, toSlateNode, useEditorReadOnly, - useEditorState, + useEditorRef, } from '@udecode/plate-common'; import { Path } from 'slate'; import { tabbable } from 'tabbable'; @@ -16,14 +16,15 @@ import { findTabDestination } from './findTabDestination'; import { TabbableEntry, TabbablePlugin } from './types'; export function TabbableEffects() { - const editor = useEditorState(); + const editor = useEditorRef(); const readOnly = useEditorReadOnly(); - const { query, globalEventListener, insertTabbableEntries, isTabbable } = - getPluginOptions(editor, KEY_TABBABLE); useEffect(() => { if (readOnly) return; + const { query, globalEventListener, insertTabbableEntries, isTabbable } = + getPluginOptions(editor, KEY_TABBABLE); + const editorDOMNode = toDOMNode(editor, editor); if (!editorDOMNode) return; @@ -127,14 +128,7 @@ export function TabbableEffects() { eventListenerNode.addEventListener('keydown', handler, true); return () => eventListenerNode.removeEventListener('keydown', handler, true); - }, [ - readOnly, - editor, - globalEventListener, - isTabbable, - insertTabbableEntries, - query, - ]); + }, [readOnly, editor]); return null; } diff --git a/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts b/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts index 00da8b1105..72aaeb7bfe 100644 --- a/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts +++ b/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts @@ -1,17 +1,25 @@ -import { useEditorState } from '@udecode/plate-common'; +import { useEditorRef, useEditorSelector } from '@udecode/plate-common'; import { isTableBorderHidden } from '../../queries/index'; import { useTableStore } from '../../stores/index'; import { getOnSelectTableBorderFactory } from './getOnSelectTableBorderFactory'; export const useTableBordersDropdownMenuContentState = () => { - const editor = useEditorState(); + const editor = useEditorRef(); const selectedCells = useTableStore().get.selectedCells(); - const hasBottomBorder = !isTableBorderHidden(editor, 'bottom'); - const hasTopBorder = !isTableBorderHidden(editor, 'top'); - const hasLeftBorder = !isTableBorderHidden(editor, 'left'); - const hasRightBorder = !isTableBorderHidden(editor, 'right'); + const { + hasBottomBorder, + hasTopBorder, + hasLeftBorder, + hasRightBorder, + // eslint-disable-next-line no-shadow + } = useEditorSelector((editor) => ({ + hasBottomBorder: !isTableBorderHidden(editor, 'bottom'), + hasTopBorder: !isTableBorderHidden(editor, 'top'), + hasLeftBorder: !isTableBorderHidden(editor, 'left'), + hasRightBorder: !isTableBorderHidden(editor, 'right'), + }), []); const hasOuterBorders = hasBottomBorder && hasTopBorder && hasLeftBorder && hasRightBorder; diff --git a/packages/table/src/merge/useTableMergeState.ts b/packages/table/src/merge/useTableMergeState.ts index f142dd8f37..0de50e8964 100644 --- a/packages/table/src/merge/useTableMergeState.ts +++ b/packages/table/src/merge/useTableMergeState.ts @@ -1,11 +1,9 @@ /* eslint-disable react-hooks/rules-of-hooks */ -import { useMemo } from 'react'; import { getPluginOptions, - isCollapsed, - isExpanded, + isSelectionExpanded, useEditorRef, - useEditorState, + useEditorSelector, } from '@udecode/plate-common'; import { useReadOnly, useSelected } from 'slate-react'; @@ -27,32 +25,24 @@ export const useTableMergeState = () => { if (!enableMerging) return { canMerge: false, canUnmerge: false }; - const editor = useEditorState(); - const readOnly = useReadOnly(); const selected = useSelected(); + const selectionExpanded = useEditorSelector(isSelectionExpanded, []); - const collapsed = !readOnly && selected && isCollapsed(editor.selection); + const collapsed = !readOnly && selected && !selectionExpanded; const selectedTables = useTableStore().get.selectedTable(); const selectedTable = selectedTables?.[0]; - const selectedCellEntries = useMemo( - () => - getTableGridAbove(editor, { - format: 'cell', - }), - // eslint-disable-next-line react-hooks/exhaustive-deps - [editor.selection] + const selectedCellEntries = useEditorSelector((editor) => + getTableGridAbove(editor, { + format: 'cell', + }), [] ); - const canMerge = useMemo(() => { - return ( - !readOnly && - selected && - isExpanded(editor.selection) && - isTableRectangular(selectedTable) - ); - }, [readOnly, selected, editor.selection, selectedTable]); + const canMerge = !readOnly && + selected && + selectionExpanded && + isTableRectangular(selectedTable); const canUnmerge = collapsed && From 45d71909cdb9f3d4e6995a4d48d3011380e2b0f6 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Thu, 21 Dec 2023 22:23:30 +0000 Subject: [PATCH 04/13] Remove proof of concept --- .../default/example/playground-demo.tsx | 4 --- .../registry/default/example/test-toolbar.tsx | 28 ------------------- 2 files changed, 32 deletions(-) delete mode 100644 apps/www/src/registry/default/example/test-toolbar.tsx diff --git a/apps/www/src/registry/default/example/playground-demo.tsx b/apps/www/src/registry/default/example/playground-demo.tsx index af6ff6d3c3..23ce70072a 100644 --- a/apps/www/src/registry/default/example/playground-demo.tsx +++ b/apps/www/src/registry/default/example/playground-demo.tsx @@ -103,8 +103,6 @@ import { FixedToolbar } from '@/registry/default/plate-ui/fixed-toolbar'; import { FloatingToolbar } from '@/registry/default/plate-ui/floating-toolbar'; import { MentionCombobox } from '@/registry/default/plate-ui/mention-combobox'; -import { TestToolbar } from './test-toolbar'; - export const usePlaygroundPlugins = ({ id, components = createPlateUI(), @@ -346,8 +344,6 @@ export default function PlaygroundDemo({ id }: { id?: ValueId }) { )} /> - - {enabled['floating-toolbar'] && ( {enabled['floating-toolbar-buttons'] && ( diff --git a/apps/www/src/registry/default/example/test-toolbar.tsx b/apps/www/src/registry/default/example/test-toolbar.tsx deleted file mode 100644 index ed21f042d5..0000000000 --- a/apps/www/src/registry/default/example/test-toolbar.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { useEffect, useRef } from 'react'; -import { isSelectionExpanded, useEditorSelector } from '@udecode/plate-common'; - -const useRenderCount = () => { - const renderCount = useRef(0); - useEffect(() => { - renderCount.current += 1; - }); - return renderCount.current; -}; - -export const TestToolbar = () => { - const isExpanded = useEditorSelector(isSelectionExpanded, []); - const renderCount = useRenderCount(); - - return ( - <> - {JSON.stringify( - { - renderCount, // Increments only when isExpanded changes - isExpanded, - }, - null, - 2 - )} - - ); -}; From aa71b8d63dddeacd9db5f417a2358c00f5911870 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Thu, 21 Dec 2023 22:39:40 +0000 Subject: [PATCH 05/13] Linter fixes --- .../plate-ui/playground-turn-into-dropdown-menu.tsx | 2 +- .../www/src/registry/default/plate-ui/table-dropdown-menu.tsx | 2 +- apps/www/src/registry/default/plate-ui/table-element.tsx | 2 +- .../src/registry/default/plate-ui/turn-into-dropdown-menu.tsx | 2 +- packages/font/src/hooks/useColorDropdownMenu.ts | 4 ++-- packages/line-height/src/hooks/useLineHeightDropdownMenu.ts | 2 +- .../useTableBordersDropdownMenuContentState.ts | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx b/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx index 6d82092202..1cd38e70d0 100644 --- a/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx +++ b/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx @@ -109,7 +109,7 @@ export function PlaygroundTurnIntoDropdownMenu(props: DropdownMenuProps) { const editor = useEditorRef(); const openState = useOpenState(); - // eslint-disable-next-line no-shadow + // eslint-disable-next-line @typescript-eslint/no-shadow const value: string = useEditorSelector((editor) => { if (!isSelectionExpanded(editor)) { const entry = findNode(editor!, { diff --git a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx index ab7ccaf68a..1767d6ac3a 100644 --- a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx @@ -28,7 +28,7 @@ import { ToolbarButton } from './toolbar'; export function TableDropdownMenu(props: DropdownMenuProps) { const editor = useEditorRef(); - // eslint-disable-next-line no-shadow + // eslint-disable-next-line @typescript-eslint/no-shadow const tableSelected = useEditorSelector((editor) => someNode(editor, { match: { type: ELEMENT_TABLE } }), [] diff --git a/apps/www/src/registry/default/plate-ui/table-element.tsx b/apps/www/src/registry/default/plate-ui/table-element.tsx index e1b322f76b..9b3490a20e 100644 --- a/apps/www/src/registry/default/plate-ui/table-element.tsx +++ b/apps/www/src/registry/default/plate-ui/table-element.tsx @@ -119,7 +119,7 @@ const TableFloatingToolbar = React.forwardRef< const selected = useSelected(); const editor = useEditorRef(); - // eslint-disable-next-line no-shadow + // eslint-disable-next-line @typescript-eslint/no-shadow const selectionCollapsed = useEditorSelector((editor) => !isSelectionExpanded(editor), []); const collapsed = !readOnly && selected && selectionCollapsed; const open = !readOnly && selected; diff --git a/apps/www/src/registry/default/plate-ui/turn-into-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/turn-into-dropdown-menu.tsx index a16d828a2d..51b843cb1e 100644 --- a/apps/www/src/registry/default/plate-ui/turn-into-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/turn-into-dropdown-menu.tsx @@ -79,7 +79,7 @@ export function TurnIntoDropdownMenu(props: DropdownMenuProps) { const editor = useEditorRef(); const openState = useOpenState(); - // eslint-disable-next-line no-shadow + // eslint-disable-next-line @typescript-eslint/no-shadow const value: string = useEditorSelector((editor) => { if (isCollapsed(editor.selection)) { const entry = findNode(editor, { diff --git a/packages/font/src/hooks/useColorDropdownMenu.ts b/packages/font/src/hooks/useColorDropdownMenu.ts index cabffe2e77..30cf032468 100644 --- a/packages/font/src/hooks/useColorDropdownMenu.ts +++ b/packages/font/src/hooks/useColorDropdownMenu.ts @@ -23,13 +23,13 @@ export const useColorDropdownMenuState = ({ const editor = useEditorRef(); const selectionDefined = useEditorSelector( - // eslint-disable-next-line no-shadow + // eslint-disable-next-line @typescript-eslint/no-shadow (editor) => !!editor.selection, [] ); const color = useEditorSelector( - // eslint-disable-next-line no-shadow + // eslint-disable-next-line @typescript-eslint/no-shadow (editor) => getMark(editor, nodeType) as string, [nodeType] ); diff --git a/packages/line-height/src/hooks/useLineHeightDropdownMenu.ts b/packages/line-height/src/hooks/useLineHeightDropdownMenu.ts index 46cb0a0170..27404fa273 100644 --- a/packages/line-height/src/hooks/useLineHeightDropdownMenu.ts +++ b/packages/line-height/src/hooks/useLineHeightDropdownMenu.ts @@ -15,7 +15,7 @@ export const useLineHeightDropdownMenuState = () => { const { validNodeValues: values = [], defaultNodeValue } = getPluginInjectProps(editor, KEY_LINE_HEIGHT); - // eslint-disable-next-line no-shadow + // eslint-disable-next-line @typescript-eslint/no-shadow const value: string | undefined = useEditorSelector((editor) => { if (isCollapsed(editor.selection)) { const entry = getBlockAbove(editor); diff --git a/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts b/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts index 72aaeb7bfe..f8cc0553e9 100644 --- a/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts +++ b/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts @@ -13,7 +13,7 @@ export const useTableBordersDropdownMenuContentState = () => { hasTopBorder, hasLeftBorder, hasRightBorder, - // eslint-disable-next-line no-shadow + // eslint-disable-next-line @typescript-eslint/no-shadow } = useEditorSelector((editor) => ({ hasBottomBorder: !isTableBorderHidden(editor, 'bottom'), hasTopBorder: !isTableBorderHidden(editor, 'top'), From 5fe441511643cb48066ca3ad9994ec0203264c07 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Fri, 22 Dec 2023 08:20:26 +0000 Subject: [PATCH 06/13] Fix: Table border dropdown menu uses incorrect `useEditorSelector` --- ...useTableBordersDropdownMenuContentState.ts | 30 +++++++++++-------- .../table/src/merge/useTableMergeState.ts | 13 ++++---- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts b/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts index f8cc0553e9..4fd745d92f 100644 --- a/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts +++ b/packages/table/src/components/TableCellElement/useTableBordersDropdownMenuContentState.ts @@ -8,18 +8,24 @@ export const useTableBordersDropdownMenuContentState = () => { const editor = useEditorRef(); const selectedCells = useTableStore().get.selectedCells(); - const { - hasBottomBorder, - hasTopBorder, - hasLeftBorder, - hasRightBorder, - // eslint-disable-next-line @typescript-eslint/no-shadow - } = useEditorSelector((editor) => ({ - hasBottomBorder: !isTableBorderHidden(editor, 'bottom'), - hasTopBorder: !isTableBorderHidden(editor, 'top'), - hasLeftBorder: !isTableBorderHidden(editor, 'left'), - hasRightBorder: !isTableBorderHidden(editor, 'right'), - }), []); + /* eslint-disable @typescript-eslint/no-shadow */ + const hasBottomBorder = useEditorSelector( + (editor) => !isTableBorderHidden(editor, 'bottom'), + [] + ); + const hasTopBorder = useEditorSelector( + (editor) => !isTableBorderHidden(editor, 'top'), + [] + ); + const hasLeftBorder = useEditorSelector( + (editor) => !isTableBorderHidden(editor, 'left'), + [] + ); + const hasRightBorder = useEditorSelector( + (editor) => !isTableBorderHidden(editor, 'right'), + [] + ); + /* eslint-enable @typescript-eslint/no-shadow */ const hasOuterBorders = hasBottomBorder && hasTopBorder && hasLeftBorder && hasRightBorder; diff --git a/packages/table/src/merge/useTableMergeState.ts b/packages/table/src/merge/useTableMergeState.ts index 0de50e8964..0ff2f09776 100644 --- a/packages/table/src/merge/useTableMergeState.ts +++ b/packages/table/src/merge/useTableMergeState.ts @@ -33,13 +33,16 @@ export const useTableMergeState = () => { const selectedTables = useTableStore().get.selectedTable(); const selectedTable = selectedTables?.[0]; - const selectedCellEntries = useEditorSelector((editor) => - getTableGridAbove(editor, { - format: 'cell', - }), [] + const selectedCellEntries = useEditorSelector( + (editor) => + getTableGridAbove(editor, { + format: 'cell', + }), + [] ); - const canMerge = !readOnly && + const canMerge = + !readOnly && selected && selectionExpanded && isTableRectangular(selectedTable); From 74a8b5f1432c2101e0b809d85a8e88bcea3958b3 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Fri, 22 Dec 2023 09:14:15 +0000 Subject: [PATCH 07/13] Add changesets --- .changeset/patch-alignment.md | 5 +++++ .changeset/patch-emoji.md | 5 +++++ .changeset/patch-floating.md | 5 +++++ .changeset/patch-font.md | 5 +++++ .changeset/patch-indent-list.md | 5 +++++ .changeset/patch-line-height.md | 5 +++++ .changeset/patch-link.md | 5 +++++ .changeset/patch-list.md | 5 +++++ .changeset/patch-tabbable.md | 5 +++++ .changeset/patch-table.md | 5 +++++ .changeset/patch-utils.md | 5 +++++ .changeset/spicy-bobcats-taste.md | 7 +++++++ 12 files changed, 62 insertions(+) create mode 100644 .changeset/patch-alignment.md create mode 100644 .changeset/patch-emoji.md create mode 100644 .changeset/patch-floating.md create mode 100644 .changeset/patch-font.md create mode 100644 .changeset/patch-indent-list.md create mode 100644 .changeset/patch-line-height.md create mode 100644 .changeset/patch-link.md create mode 100644 .changeset/patch-list.md create mode 100644 .changeset/patch-tabbable.md create mode 100644 .changeset/patch-table.md create mode 100644 .changeset/patch-utils.md create mode 100644 .changeset/spicy-bobcats-taste.md diff --git a/.changeset/patch-alignment.md b/.changeset/patch-alignment.md new file mode 100644 index 0000000000..9e2256ccbf --- /dev/null +++ b/.changeset/patch-alignment.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-alignment': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-emoji.md b/.changeset/patch-emoji.md new file mode 100644 index 0000000000..e7c0d9cab0 --- /dev/null +++ b/.changeset/patch-emoji.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-emoji': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-floating.md b/.changeset/patch-floating.md new file mode 100644 index 0000000000..11bcb57d8a --- /dev/null +++ b/.changeset/patch-floating.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-floating': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-font.md b/.changeset/patch-font.md new file mode 100644 index 0000000000..b6c75904f6 --- /dev/null +++ b/.changeset/patch-font.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-font': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-indent-list.md b/.changeset/patch-indent-list.md new file mode 100644 index 0000000000..17ad244df8 --- /dev/null +++ b/.changeset/patch-indent-list.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-indent-list': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-line-height.md b/.changeset/patch-line-height.md new file mode 100644 index 0000000000..6b8cd4bf42 --- /dev/null +++ b/.changeset/patch-line-height.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-line-height': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-link.md b/.changeset/patch-link.md new file mode 100644 index 0000000000..7e646a3024 --- /dev/null +++ b/.changeset/patch-link.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-link': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-list.md b/.changeset/patch-list.md new file mode 100644 index 0000000000..a031457f93 --- /dev/null +++ b/.changeset/patch-list.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-list': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-tabbable.md b/.changeset/patch-tabbable.md new file mode 100644 index 0000000000..b144d50daa --- /dev/null +++ b/.changeset/patch-tabbable.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-tabbable': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-table.md b/.changeset/patch-table.md new file mode 100644 index 0000000000..d685a0de5c --- /dev/null +++ b/.changeset/patch-table.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-table': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/patch-utils.md b/.changeset/patch-utils.md new file mode 100644 index 0000000000..3a0fc9b14a --- /dev/null +++ b/.changeset/patch-utils.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-utils': patch +--- + +- Replace `useEdtiorState` with `useEditorSelector` diff --git a/.changeset/spicy-bobcats-taste.md b/.changeset/spicy-bobcats-taste.md new file mode 100644 index 0000000000..7982f00ccc --- /dev/null +++ b/.changeset/spicy-bobcats-taste.md @@ -0,0 +1,7 @@ +--- +'@udecode/plate-core': major +--- + +- Upgrade to `jotai-x@2.0.0` +- Add `useEditorSelector` hook to only re-render when a specific property of `editor` changes +- Breaking change: `usePlateSelectors`, `usePlateActions` and `usePlateStates` no longer accept generic type arguments. If custom types are required, cast the resulting values at the point of use, or use hooks like `useEditorRef` that still provide generics. From 2e6cd3ed91933e88817d6a4cc359711f197e29b1 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Fri, 22 Dec 2023 09:57:57 +0000 Subject: [PATCH 08/13] Update docs --- apps/www/content/docs/accessing-editor.mdx | 51 ++++++++++++---------- apps/www/content/docs/api/core.mdx | 49 +++++++++++++++------ 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/apps/www/content/docs/accessing-editor.mdx b/apps/www/content/docs/accessing-editor.mdx index bdf1112aa5..f71c3bf6df 100644 --- a/apps/www/content/docs/accessing-editor.mdx +++ b/apps/www/content/docs/accessing-editor.mdx @@ -57,12 +57,38 @@ const createMyPlugin = createPluginFactory({ ## From a Child of Plate -Use the **`useEditorRef`** or **`useEditorState`** hooks. - -Internally, **`useEditorState`** is a wrapper for **`useEditorRef`**. The only difference is that **`useEditorState`** causes React to re-render whenever the **`editor`** state changes, whereas **`useEditorRef`** does not cause a re-render. Since **`editor`** is mutable and is updated by reference, **`useEditorRef`** will be sufficient (and more efficient) in most situations. +Use the **`useEditorRef`**, **`useEditorSelector`** or **`useEditorState`** hooks. Which of these hooks you should use depends on when you want your component to re-render in response to changes to **`editor`**. + +- **`useEditorRef`** - Use a reference to **`editor`** that almost never gets replaced. **This should be the default choice.** + - Since **`editor`** is a mutable object that gets updated by reference, **`useEditorRef`** is always sufficient for accessing the **`editor`** inside callbacks. + - **`useEditorRef`** will almost never cause your component to re-render, so it's the best choice for performance. +- **`useEditorSelector`** - Subscribe to a specific selector based on **`editor`**. **This is the most performant option for subscribing to state changes.** + - Example usage: `const hasSelection = useEditorSelector((editor) => !!editor.selection, []);` + - When you want your component to re-render in response to a specific change that you're interested in, you can use **`useEditorSelector`** to access the relevant property. + - The selector function is called every time the **`editor`** changes (i.e. on every keystroke or selection change), but the component only re-renders when the return value changes. + - For this to work properly, you should make sure that the return value can be compared using `===`. In most cases, this means returning a primitive value, like a number, string or boolean. + - You can provide a custom **`equalityFn`** in the options to **`useEditorSelector`** for cases where `===` isn't sufficient. + - If the selector function depends on any locally scoped variables, you should include these in the dependency list. +- **`useEditorState`** - Re-render every time the **`editor`** changes. + - Using **`useEditorState`** will cause your component to re-render every time the user presses a key or changes the selection. + - This may cause performance issues for large documents, or when re-rendering is particularly expensive. You can call these hooks from any React component that is rendered as a descendant of the **`Plate`** component, including [Plugin Components](/docs/plugin-components). +```tsx +const Toolbar = () => { + const boldActive = useEditorSelector((editor) => isMarkActive(editor, MARK_BOLD), []); + // ... +}; + +const Editor = () => ( + + + + +); +``` + ```tsx showLineNumbers {6} const ParagraphElement = ({ className, @@ -118,25 +144,6 @@ export default () => ( as when the editor is reset. -## From a Sibling of Plate - -Wrap **`PlateContent`** and the sibling in **`Plate`**, and then use **`useEditorRef`** or **`useEditorState`** from within the sibling. - -```tsx showLineNumbers {2,8,11} -const Toolbar = () => { - const editor = useEditorState(); - // Do something with editor - // ... -}; - -const Editor = () => ( - - - - -); -``` - ## From an Ancestor If you need to access the **`editor`** instance from an ancestor of **`PlateContent`**, wrapping the relevant components in a **`Plate`** is the preferred solution. If this is not an option, you can instead use the **`editorRef`** prop to pass a reference to the **`editor`** instance up the React component tree to where it is needed. diff --git a/apps/www/content/docs/api/core.mdx b/apps/www/content/docs/api/core.mdx index 20a774a984..b5954fc95c 100644 --- a/apps/www/content/docs/api/core.mdx +++ b/apps/www/content/docs/api/core.mdx @@ -31,20 +31,6 @@ Plugin attributes to override by plugin key. An array of plugins with overridden components or attributes. - - An object containing the following properties: - - A boolean indicating whether the `nodeType` mark is active in the current - selection. - - - The type of the node. - - - Type or types of the node to clear. - - - ### createAtomStore Creates an atom store from an initial value. Each property of the initial value will have a getter and setter. @@ -344,6 +330,40 @@ A `PlateEditor` object, which is the Slate editor. +### useEditorSelector + +Subscribe to a specific property of the editor. + +- Calls the selector function on editor change. +- Re-renders when the result of the selector changes. +- Should be used inside `Plate`. + + + + The selector function. + + + + The dependency list for the selector function. + + + + + + The ID of the plate editor. Useful only when nesting editors. Default is using the closest editor id. + + + + Equality function to determine whether the result of the selector function has changed. Default is `(a, b) => a === b`. + + + + + + + The return value of the selector function. + + ### useEditorState Get the Slate editor reference with re-rendering. @@ -352,6 +372,7 @@ Get the Slate editor reference with re-rendering. - Supports nested editors. - Should be used inside `Plate`. - Note the reference does not change when the editor changes. +- If performance is a concern, `useEditorSelector` should be used instead. From 34cc5b14aedb2eebbc96f61e851ebfeadce377e4 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Fri, 22 Dec 2023 09:58:05 +0000 Subject: [PATCH 09/13] Update BREAKING_CHANGES.md --- BREAKING_CHANGES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index c91044005d..765b02e765 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -1,3 +1,11 @@ +# 28.0.0 + +## @udecode/plate-core@28.0.0 + +### Major Changes + +- `usePlateSelectors`, `usePlateActions` and `usePlateStates` no longer accept generic type arguments. If custom types are required, cast the resulting values at the point of use, or use hooks like `useEditorRef` that still provide generics. + # 27.0.0 ## @udecode/plate-comments@27.0.0 From 85829919e6df81964614c4cd9478d31092a74c13 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Fri, 22 Dec 2023 14:21:17 +0000 Subject: [PATCH 10/13] Remove `{ fn: ... }` workaround --- .changeset/fn-comments.md | 5 +++ .changeset/fn-resizable.md | 5 +++ .changeset/spicy-bobcats-taste.md | 1 + apps/www/content/docs/api/core/store.mdx | 28 +++------------- .../src/components/CommentDeleteButton.tsx | 2 +- .../src/components/CommentEditSaveButton.tsx | 2 +- .../src/components/CommentNewSubmitButton.tsx | 2 +- .../src/components/CommentResolveButton.tsx | 2 +- .../src/stores/comments/CommentsProvider.tsx | 33 +++---------------- packages/core/package.json | 2 +- .../core/src/components/EditorRefEffect.tsx | 2 +- packages/core/src/components/Plate.tsx | 10 +++--- packages/core/src/hooks/useEditableProps.ts | 6 ++-- packages/core/src/hooks/useSlateProps.ts | 2 +- packages/core/src/types/PlateStore.ts | 10 +++--- .../resizable/src/components/Resizable.tsx | 2 +- .../resizable/src/components/ResizeHandle.tsx | 6 ++-- yarn.lock | 14 ++++---- 18 files changed, 49 insertions(+), 85 deletions(-) create mode 100644 .changeset/fn-comments.md create mode 100644 .changeset/fn-resizable.md diff --git a/.changeset/fn-comments.md b/.changeset/fn-comments.md new file mode 100644 index 0000000000..97a7381597 --- /dev/null +++ b/.changeset/fn-comments.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-comments': patch +--- + +- Remove `{ fn: ... }` workaround for jotai stores that contain functions diff --git a/.changeset/fn-resizable.md b/.changeset/fn-resizable.md new file mode 100644 index 0000000000..94d303b80a --- /dev/null +++ b/.changeset/fn-resizable.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-resizable': patch +--- + +- Remove `{ fn: ... }` workaround for jotai stores that contain functions diff --git a/.changeset/spicy-bobcats-taste.md b/.changeset/spicy-bobcats-taste.md index 7982f00ccc..eea644d754 100644 --- a/.changeset/spicy-bobcats-taste.md +++ b/.changeset/spicy-bobcats-taste.md @@ -4,4 +4,5 @@ - Upgrade to `jotai-x@2.0.0` - Add `useEditorSelector` hook to only re-render when a specific property of `editor` changes +- Remove `{ fn: ... }` workaround for jotai stores that contain functions - Breaking change: `usePlateSelectors`, `usePlateActions` and `usePlateStates` no longer accept generic type arguments. If custom types are required, cast the resulting values at the point of use, or use hooks like `useEditorRef` that still provide generics. diff --git a/apps/www/content/docs/api/core/store.mdx b/apps/www/content/docs/api/core/store.mdx index 94181cb543..1c5b146e1e 100644 --- a/apps/www/content/docs/api/core/store.mdx +++ b/apps/www/content/docs/api/core/store.mdx @@ -84,40 +84,20 @@ Version incremented when calling `redecorate`. This is a dependency of the `deco - - - + - See [`onChange`](/docs/api/core/plate#slate-onchange). - - - - - - + - See [`decorate`](/docs/api/core/plate#editable-decorate). - - - - - - + - See [`renderElement`](/docs/api/core/plate#editable-renderelement). - - - - - - + - See [`renderLeaf`](/docs/api/core/plate#editable-renderleaf). - - - diff --git a/packages/comments/src/components/CommentDeleteButton.tsx b/packages/comments/src/components/CommentDeleteButton.tsx index 66ae8e0530..f36a8fec0d 100644 --- a/packages/comments/src/components/CommentDeleteButton.tsx +++ b/packages/comments/src/components/CommentDeleteButton.tsx @@ -10,7 +10,7 @@ import { unsetCommentNodesById } from '../utils/index'; export const useCommentDeleteButtonState = () => { const activeCommentId = useCommentsSelectors().activeCommentId(); - const onCommentDelete = useCommentsSelectors().onCommentDelete()?.fn; + const onCommentDelete = useCommentsSelectors().onCommentDelete(); const id = useCommentSelectors().id(); const setActiveCommentId = useCommentsActions().activeCommentId(); const removeComment = useRemoveComment(); diff --git a/packages/comments/src/components/CommentEditSaveButton.tsx b/packages/comments/src/components/CommentEditSaveButton.tsx index 1307e5c2b7..558bea509e 100644 --- a/packages/comments/src/components/CommentEditSaveButton.tsx +++ b/packages/comments/src/components/CommentEditSaveButton.tsx @@ -12,7 +12,7 @@ import { } from '../stores/comments/CommentsProvider'; export const useCommentEditSaveButtonState = () => { - const onCommentUpdate = useCommentsSelectors().onCommentUpdate()?.fn; + const onCommentUpdate = useCommentsSelectors().onCommentUpdate(); const editingValue = useCommentSelectors().editingValue(); const setEditingValue = useCommentActions().editingValue(); const id = useCommentSelectors().id(); diff --git a/packages/comments/src/components/CommentNewSubmitButton.tsx b/packages/comments/src/components/CommentNewSubmitButton.tsx index 4a8338538d..3ed7384626 100644 --- a/packages/comments/src/components/CommentNewSubmitButton.tsx +++ b/packages/comments/src/components/CommentNewSubmitButton.tsx @@ -12,7 +12,7 @@ import { } from '../stores/comments/CommentsProvider'; export const useCommentNewSubmitButtonState = () => { - const onCommentAdd = useCommentsSelectors().onCommentAdd()?.fn; + const onCommentAdd = useCommentsSelectors().onCommentAdd(); const activeCommentId = useCommentsSelectors().activeCommentId()!; const comment = useComment(SCOPE_ACTIVE_COMMENT)!; const newValue = useCommentsSelectors().newValue(); diff --git a/packages/comments/src/components/CommentResolveButton.tsx b/packages/comments/src/components/CommentResolveButton.tsx index 8f7f83421d..63eb855669 100644 --- a/packages/comments/src/components/CommentResolveButton.tsx +++ b/packages/comments/src/components/CommentResolveButton.tsx @@ -8,7 +8,7 @@ import { } from '../stores/comments/CommentsProvider'; export const useCommentResolveButton = () => { - const onCommentUpdate = useCommentsSelectors().onCommentUpdate()?.fn; + const onCommentUpdate = useCommentsSelectors().onCommentUpdate(); const activeCommentId = useCommentsSelectors().activeCommentId(); const setActiveCommentId = useCommentsActions().activeCommentId(); const updateComment = useUpdateComment(activeCommentId); diff --git a/packages/comments/src/stores/comments/CommentsProvider.tsx b/packages/comments/src/stores/comments/CommentsProvider.tsx index 5061f781ac..ae030ea8b9 100644 --- a/packages/comments/src/stores/comments/CommentsProvider.tsx +++ b/packages/comments/src/stores/comments/CommentsProvider.tsx @@ -36,17 +36,15 @@ export interface CommentsStoreState { focusTextarea: boolean; - onCommentAdd: { fn: (value: WithPartial) => void } | null; - onCommentUpdate: { - fn: (value: Pick & Partial>) => void; - } | null; - onCommentDelete: { fn: (id: string) => void } | null; + onCommentAdd: ((value: WithPartial) => void) | null; + onCommentUpdate: ((value: Pick & Partial>) => void) | null; + onCommentDelete: ((id: string) => void) | null; } export const { commentsStore, useCommentsStore, - CommentsProvider: PrimitiveCommentsProvider, + CommentsProvider, } = createAtomStore( { myUserId: null, @@ -65,29 +63,6 @@ export const { } ); -export const CommentsProvider = ({ - onCommentAdd, - onCommentUpdate, - onCommentDelete, - ...props -}: Omit< - React.ComponentProps, - 'onCommentAdd' | 'onCommentUpdate' | 'onCommentDelete' -> & { - onCommentAdd?: (value: WithPartial) => void; - onCommentUpdate?: ( - value: Pick & Partial> - ) => void; - onCommentDelete?: (id: string) => void; -}) => ( - -); - export const useCommentsStates = () => useCommentsStore().use; export const useCommentsSelectors = () => useCommentsStore().get; export const useCommentsActions = () => useCommentsStore().set; diff --git a/packages/core/package.json b/packages/core/package.json index 8b8ffb117c..9240869a74 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -46,7 +46,7 @@ "clsx": "^1.2.1", "is-hotkey": "^0.2.0", "jotai": "^2.6.0", - "jotai-x": "0.0.0-20231221184746", + "jotai-x": "0.0.0-20231222135748", "lodash": "^4.17.21", "nanoid": "^3.3.6", "react-hotkeys-hook": "^4.4.1", diff --git a/packages/core/src/components/EditorRefEffect.tsx b/packages/core/src/components/EditorRefEffect.tsx index 672f89f2c2..5164af9996 100644 --- a/packages/core/src/components/EditorRefEffect.tsx +++ b/packages/core/src/components/EditorRefEffect.tsx @@ -26,7 +26,7 @@ export function EditorRefEffect({ id }: { id?: PlateId }) { const setIsMounted = usePlateActions(id).isMounted(); const plugins = usePlateSelectors(id).plugins(); const editorState = useEditorRef(id); - const editorRef = usePlateSelectors(id).editorRef()?.ref; + const editorRef = usePlateSelectors(id).editorRef(); useEffect(() => { setIsMounted(true); diff --git a/packages/core/src/components/Plate.tsx b/packages/core/src/components/Plate.tsx index a73c7792d5..f963a537ac 100644 --- a/packages/core/src/components/Plate.tsx +++ b/packages/core/src/components/Plate.tsx @@ -142,11 +142,11 @@ function PlateInner< rawPlugins={pluginsProp} readOnly={readOnly} value={value} - decorate={{ fn: decorate as any }} - onChange={{ fn: onChange as any }} - editorRef={{ ref: editorRef as any }} - renderElement={{ fn: renderElement as any }} - renderLeaf={{ fn: renderLeaf as any }} + decorate={decorate} + onChange={onChange as PlateStoreState['onChange']} + editorRef={editorRef as PlateStoreState['editorRef']} + renderElement={renderElement} + renderLeaf={renderLeaf} scope={id} > { return pipeDecorate(editor, storeDecorate ?? editableProps?.decorate); diff --git a/packages/core/src/hooks/useSlateProps.ts b/packages/core/src/hooks/useSlateProps.ts index 3b2d3822d3..aa1a41998a 100644 --- a/packages/core/src/hooks/useSlateProps.ts +++ b/packages/core/src/hooks/useSlateProps.ts @@ -17,7 +17,7 @@ export const useSlateProps = ({ const editor = useEditorRef(id); const value = usePlateSelectors(id).value(); const setValue = usePlateActions(id).value(); - const onChangeProp = usePlateSelectors(id).onChange()?.fn; + const onChangeProp = usePlateSelectors(id).onChange(); const onChange = useCallback( (newValue: V) => { diff --git a/packages/core/src/types/PlateStore.ts b/packages/core/src/types/PlateStore.ts index 0875edea3a..d29492f974 100644 --- a/packages/core/src/types/PlateStore.ts +++ b/packages/core/src/types/PlateStore.ts @@ -76,16 +76,16 @@ export type PlateStoreState< /** * Controlled callback called when the editor state changes. */ - onChange: { fn: (value: V) => void }; + onChange: (value: V) => void; /** * Access the editor object using a React ref. */ - editorRef: { ref: ForwardedRef }; + editorRef: ForwardedRef; - decorate: { fn: NonNullable }; - renderElement: { fn: NonNullable }; - renderLeaf: { fn: NonNullable }; + decorate: NonNullable; + renderElement: NonNullable; + renderLeaf: NonNullable; }>; // A list of store keys to be exposed in `editor.plate.set`. diff --git a/packages/resizable/src/components/Resizable.tsx b/packages/resizable/src/components/Resizable.tsx index 9dfcb73a00..ca2c48baf6 100644 --- a/packages/resizable/src/components/Resizable.tsx +++ b/packages/resizable/src/components/Resizable.tsx @@ -137,7 +137,7 @@ const Resizable = React.forwardRef< return (
- + {children}
diff --git a/packages/resizable/src/components/ResizeHandle.tsx b/packages/resizable/src/components/ResizeHandle.tsx index c55e95edc3..a2ea985db9 100644 --- a/packages/resizable/src/components/ResizeHandle.tsx +++ b/packages/resizable/src/components/ResizeHandle.tsx @@ -14,9 +14,7 @@ import { ResizeDirection, ResizeEvent } from '../types'; import { isTouchEvent } from '../utils'; export type ResizeHandleStoreState = { - onResize: { - fn: (event: ResizeEvent) => void; - }; + onResize: (event: ResizeEvent) => void; }; const initialState: Nullable = { @@ -48,7 +46,7 @@ export const useResizeHandleState = ({ onHoverEnd, }: ResizeHandleOptions) => { const onResizeStore = useResizeHandleStore().get.onResize(); - const onResize = onResizeProp ?? onResizeStore.fn; + const onResize = onResizeProp ?? onResizeStore; const [isResizing, setIsResizing] = useState(false); const [initialPosition, setInitialPosition] = useState(0); diff --git a/yarn.lock b/yarn.lock index 86e823d636..39975b7713 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6194,7 +6194,7 @@ __metadata: languageName: unknown linkType: soft -"@udecode/plate-comments@npm:27.0.3, @udecode/plate-comments@workspace:^, @udecode/plate-comments@workspace:packages/comments": +"@udecode/plate-comments@npm:27.0.4, @udecode/plate-comments@workspace:^, @udecode/plate-comments@workspace:packages/comments": version: 0.0.0-use.local resolution: "@udecode/plate-comments@workspace:packages/comments" dependencies: @@ -6241,7 +6241,7 @@ __metadata: clsx: "npm:^1.2.1" is-hotkey: "npm:^0.2.0" jotai: "npm:^2.6.0" - jotai-x: "npm:0.0.0-20231221184746" + jotai-x: "npm:0.0.0-20231222135748" lodash: "npm:^4.17.21" nanoid: "npm:^3.3.6" react-hotkeys-hook: "npm:^4.4.1" @@ -6907,7 +6907,7 @@ __metadata: "@udecode/plate-break": "npm:27.0.3" "@udecode/plate-code-block": "npm:27.0.3" "@udecode/plate-combobox": "npm:27.0.3" - "@udecode/plate-comments": "npm:27.0.3" + "@udecode/plate-comments": "npm:27.0.4" "@udecode/plate-common": "npm:27.0.3" "@udecode/plate-find-replace": "npm:27.0.3" "@udecode/plate-floating": "npm:27.0.3" @@ -13522,9 +13522,9 @@ __metadata: languageName: node linkType: hard -"jotai-x@npm:0.0.0-20231221184746": - version: 0.0.0-20231221184746 - resolution: "jotai-x@npm:0.0.0-20231221184746" +"jotai-x@npm:0.0.0-20231222135748": + version: 0.0.0-20231222135748 + resolution: "jotai-x@npm:0.0.0-20231222135748" peerDependencies: "@types/react": ">=17.0.0" jotai: ">=2.0.0" @@ -13534,7 +13534,7 @@ __metadata: optional: true react: optional: true - checksum: d7076a068f5a444d9982a53cf2031448df0a1b78ccf3dff97a8a511876a42c7205da5f58861f0f23ff778434aa7963766048da5fee6b1e8bdea4fe568c879835 + checksum: 9cc399aa535df9b020efa27dec8a158dbd95fec8afb6ce59995fc59aa3f1980098de83dbae85c40d9ef56dad383871f419fd6c613a082d9a098909d70e028fcc languageName: node linkType: hard From 2d2149d21097980cd98b21703f314e9266c70b8d Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Fri, 22 Dec 2023 14:32:05 +0000 Subject: [PATCH 11/13] Linter fixes --- .../plate-ui/playground-turn-into-dropdown-menu.tsx | 6 ++++-- apps/www/src/registry/default/plate-ui/combobox.tsx | 12 ++++++++++-- .../src/registry/default/plate-ui/media-popover.tsx | 6 ++++-- .../default/plate-ui/table-dropdown-menu.tsx | 11 ++++++++--- .../src/registry/default/plate-ui/table-element.tsx | 5 ++++- apps/www/src/types/plate-types.ts | 3 --- 6 files changed, 30 insertions(+), 13 deletions(-) diff --git a/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx b/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx index 1cd38e70d0..a1e041bd4d 100644 --- a/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx +++ b/apps/www/src/components/plate-ui/playground-turn-into-dropdown-menu.tsx @@ -117,8 +117,10 @@ export function PlaygroundTurnIntoDropdownMenu(props: DropdownMenuProps) { }); if (entry) { - return items.find((item) => item.value === entry[0].type)?.value ?? - ELEMENT_PARAGRAPH; + return ( + items.find((item) => item.value === entry[0].type)?.value ?? + ELEMENT_PARAGRAPH + ); } } diff --git a/apps/www/src/registry/default/plate-ui/combobox.tsx b/apps/www/src/registry/default/plate-ui/combobox.tsx index 2b5c9f0617..57a158e524 100644 --- a/apps/www/src/registry/default/plate-ui/combobox.tsx +++ b/apps/www/src/registry/default/plate-ui/combobox.tsx @@ -17,7 +17,12 @@ import { useComboboxItem, useComboboxSelectors, } from '@udecode/plate-combobox'; -import { useEditorRef, useEditorSelector, useEventEditorSelectors, usePlateSelectors } from '@udecode/plate-common'; +import { + useEditorRef, + useEditorSelector, + useEventEditorSelectors, + usePlateSelectors, +} from '@udecode/plate-common'; import { createVirtualRef } from '@udecode/plate-floating'; import { cn } from '@/lib/utils'; @@ -118,7 +123,10 @@ export function Combobox({ const focusedEditorId = useEventEditorSelectors.focus?.(); const combobox = useComboboxControls(); const activeId = useComboboxSelectors.activeId(); - const selectionDefined = useEditorSelector((editor => !!editor.selection), []); + const selectionDefined = useEditorSelector( + (editor) => !!editor.selection, + [] + ); const editorId = usePlateSelectors().id(); useEffect(() => { diff --git a/apps/www/src/registry/default/plate-ui/media-popover.tsx b/apps/www/src/registry/default/plate-ui/media-popover.tsx index 65505e14c3..5e9396beac 100644 --- a/apps/www/src/registry/default/plate-ui/media-popover.tsx +++ b/apps/www/src/registry/default/plate-ui/media-popover.tsx @@ -1,6 +1,5 @@ import React, { useEffect } from 'react'; import { - isCollapsed, isSelectionExpanded, useEditorSelector, useElement, @@ -29,7 +28,10 @@ export function MediaPopover({ pluginKey, children }: MediaPopoverProps) { const readOnly = useReadOnly(); const selected = useSelected(); - const selectionCollapsed = useEditorSelector((editor) => !isSelectionExpanded(editor), []); + const selectionCollapsed = useEditorSelector( + (editor) => !isSelectionExpanded(editor), + [] + ); const isOpen = !readOnly && selected && selectionCollapsed; const isEditing = useFloatingMediaSelectors().isEditing(); diff --git a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx index 1767d6ac3a..a87a139bea 100644 --- a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx @@ -1,6 +1,11 @@ import React from 'react'; import { DropdownMenuProps } from '@radix-ui/react-dropdown-menu'; -import { focusEditor, someNode, useEditorRef, useEditorSelector } from '@udecode/plate-common'; +import { + focusEditor, + someNode, + useEditorRef, + useEditorSelector, +} from '@udecode/plate-common'; import { deleteColumn, deleteRow, @@ -29,8 +34,8 @@ export function TableDropdownMenu(props: DropdownMenuProps) { const editor = useEditorRef(); // eslint-disable-next-line @typescript-eslint/no-shadow - const tableSelected = useEditorSelector((editor) => - someNode(editor, { match: { type: ELEMENT_TABLE } }), + const tableSelected = useEditorSelector( + (editor) => someNode(editor, { match: { type: ELEMENT_TABLE } }), [] ); diff --git a/apps/www/src/registry/default/plate-ui/table-element.tsx b/apps/www/src/registry/default/plate-ui/table-element.tsx index 9b3490a20e..30e8476566 100644 --- a/apps/www/src/registry/default/plate-ui/table-element.tsx +++ b/apps/www/src/registry/default/plate-ui/table-element.tsx @@ -120,7 +120,10 @@ const TableFloatingToolbar = React.forwardRef< const editor = useEditorRef(); // eslint-disable-next-line @typescript-eslint/no-shadow - const selectionCollapsed = useEditorSelector((editor) => !isSelectionExpanded(editor), []); + const selectionCollapsed = useEditorSelector( + (editor) => !isSelectionExpanded(editor), + [] + ); const collapsed = !readOnly && selected && selectionCollapsed; const open = !readOnly && selected; diff --git a/apps/www/src/types/plate-types.ts b/apps/www/src/types/plate-types.ts index f70a6799d9..ae0fca7578 100644 --- a/apps/www/src/types/plate-types.ts +++ b/apps/www/src/types/plate-types.ts @@ -45,9 +45,6 @@ import { TReactEditor, useEditorRef, useEditorState, - usePlateActions, - usePlateSelectors, - usePlateStates, WithOverride, } from '@udecode/plate-common'; import { From 5fda61f47049c88cd2ee99499e5fcf934716fe55 Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Fri, 22 Dec 2023 14:33:12 +0000 Subject: [PATCH 12/13] Use released version of jotai-x --- .changeset/spicy-bobcats-taste.md | 2 +- packages/core/package.json | 2 +- yarn.lock | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.changeset/spicy-bobcats-taste.md b/.changeset/spicy-bobcats-taste.md index eea644d754..ce9daa2dc2 100644 --- a/.changeset/spicy-bobcats-taste.md +++ b/.changeset/spicy-bobcats-taste.md @@ -2,7 +2,7 @@ '@udecode/plate-core': major --- -- Upgrade to `jotai-x@2.0.0` +- Upgrade to `jotai-x@1.1.0` - Add `useEditorSelector` hook to only re-render when a specific property of `editor` changes - Remove `{ fn: ... }` workaround for jotai stores that contain functions - Breaking change: `usePlateSelectors`, `usePlateActions` and `usePlateStates` no longer accept generic type arguments. If custom types are required, cast the resulting values at the point of use, or use hooks like `useEditorRef` that still provide generics. diff --git a/packages/core/package.json b/packages/core/package.json index 9240869a74..977e26fb57 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -46,7 +46,7 @@ "clsx": "^1.2.1", "is-hotkey": "^0.2.0", "jotai": "^2.6.0", - "jotai-x": "0.0.0-20231222135748", + "jotai-x": "^1.1.0", "lodash": "^4.17.21", "nanoid": "^3.3.6", "react-hotkeys-hook": "^4.4.1", diff --git a/yarn.lock b/yarn.lock index 39975b7713..ed797cb0d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6241,7 +6241,7 @@ __metadata: clsx: "npm:^1.2.1" is-hotkey: "npm:^0.2.0" jotai: "npm:^2.6.0" - jotai-x: "npm:0.0.0-20231222135748" + jotai-x: "npm:^1.1.0" lodash: "npm:^4.17.21" nanoid: "npm:^3.3.6" react-hotkeys-hook: "npm:^4.4.1" @@ -13522,9 +13522,9 @@ __metadata: languageName: node linkType: hard -"jotai-x@npm:0.0.0-20231222135748": - version: 0.0.0-20231222135748 - resolution: "jotai-x@npm:0.0.0-20231222135748" +"jotai-x@npm:^1.1.0": + version: 1.1.0 + resolution: "jotai-x@npm:1.1.0" peerDependencies: "@types/react": ">=17.0.0" jotai: ">=2.0.0" @@ -13534,7 +13534,7 @@ __metadata: optional: true react: optional: true - checksum: 9cc399aa535df9b020efa27dec8a158dbd95fec8afb6ce59995fc59aa3f1980098de83dbae85c40d9ef56dad383871f419fd6c613a082d9a098909d70e028fcc + checksum: 1f42e706f9f7ba28ffd713623672ba46b00afb1b5ee62507948aeacf2f58a1b9074c30445757f387bae5a278050ec0b82b624a59aafdd732403c1d3b64eb87af languageName: node linkType: hard From 775ca9261c997de347a63acfb16ce0599b68814c Mon Sep 17 00:00:00 2001 From: Joe Anderson Date: Fri, 22 Dec 2023 14:37:38 +0000 Subject: [PATCH 13/13] Linter fixes --- .../default/plate-ui/table-dropdown-menu.tsx | 2 +- .../default/plate-ui/table-element.tsx | 2 +- .../src/stores/comments/CommentsProvider.tsx | 44 +++++++++---------- .../list/src/hooks/useListToolbarButton.ts | 7 +-- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx index a87a139bea..cc5de0e78e 100644 --- a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx @@ -33,8 +33,8 @@ import { ToolbarButton } from './toolbar'; export function TableDropdownMenu(props: DropdownMenuProps) { const editor = useEditorRef(); - // eslint-disable-next-line @typescript-eslint/no-shadow const tableSelected = useEditorSelector( + // eslint-disable-next-line @typescript-eslint/no-shadow (editor) => someNode(editor, { match: { type: ELEMENT_TABLE } }), [] ); diff --git a/apps/www/src/registry/default/plate-ui/table-element.tsx b/apps/www/src/registry/default/plate-ui/table-element.tsx index 30e8476566..a7b0130694 100644 --- a/apps/www/src/registry/default/plate-ui/table-element.tsx +++ b/apps/www/src/registry/default/plate-ui/table-element.tsx @@ -119,8 +119,8 @@ const TableFloatingToolbar = React.forwardRef< const selected = useSelected(); const editor = useEditorRef(); - // eslint-disable-next-line @typescript-eslint/no-shadow const selectionCollapsed = useEditorSelector( + // eslint-disable-next-line @typescript-eslint/no-shadow (editor) => !isSelectionExpanded(editor), [] ); diff --git a/packages/comments/src/stores/comments/CommentsProvider.tsx b/packages/comments/src/stores/comments/CommentsProvider.tsx index ae030ea8b9..1e439c4575 100644 --- a/packages/comments/src/stores/comments/CommentsProvider.tsx +++ b/packages/comments/src/stores/comments/CommentsProvider.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { createAtomStore, getNodeString, @@ -37,31 +36,30 @@ export interface CommentsStoreState { focusTextarea: boolean; onCommentAdd: ((value: WithPartial) => void) | null; - onCommentUpdate: ((value: Pick & Partial>) => void) | null; + onCommentUpdate: + | ((value: Pick & Partial>) => void) + | null; onCommentDelete: ((id: string) => void) | null; } -export const { - commentsStore, - useCommentsStore, - CommentsProvider, -} = createAtomStore( - { - myUserId: null, - users: {}, - comments: {}, - activeCommentId: null, - addingCommentId: null, - newValue: [{ type: 'p', children: [{ text: '' }] }], - focusTextarea: false, - onCommentAdd: null, - onCommentUpdate: null, - onCommentDelete: null, - } as CommentsStoreState, - { - name: 'comments', - } -); +export const { commentsStore, useCommentsStore, CommentsProvider } = + createAtomStore( + { + myUserId: null, + users: {}, + comments: {}, + activeCommentId: null, + addingCommentId: null, + newValue: [{ type: 'p', children: [{ text: '' }] }], + focusTextarea: false, + onCommentAdd: null, + onCommentUpdate: null, + onCommentDelete: null, + } as CommentsStoreState, + { + name: 'comments', + } + ); export const useCommentsStates = () => useCommentsStore().use; export const useCommentsSelectors = () => useCommentsStore().get; diff --git a/packages/list/src/hooks/useListToolbarButton.ts b/packages/list/src/hooks/useListToolbarButton.ts index cc7f9cc243..0de05dc2b2 100644 --- a/packages/list/src/hooks/useListToolbarButton.ts +++ b/packages/list/src/hooks/useListToolbarButton.ts @@ -8,9 +8,10 @@ import { import { ELEMENT_UL, toggleList } from '../index'; export const useListToolbarButtonState = ({ nodeType = ELEMENT_UL } = {}) => { - const pressed = useEditorSelector((editor) => - !!editor.selection && - someNode(editor, { match: { type: getPluginType(editor, nodeType) } }), + const pressed = useEditorSelector( + (editor) => + !!editor.selection && + someNode(editor, { match: { type: getPluginType(editor, nodeType) } }), [nodeType] );