Skip to content

Commit

Permalink
Implement PlateController
Browse files Browse the repository at this point in the history
  • Loading branch information
12joan committed Jan 5, 2024
1 parent 459a6a9 commit 6d02746
Show file tree
Hide file tree
Showing 31 changed files with 1,127 additions and 251 deletions.
4 changes: 3 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@
"clsx": "^1.2.1",
"is-hotkey": "^0.2.0",
"jotai": "^2.6.0",
"jotai-x": "^1.1.0",
"jotai-optics": "0.3.1",
"jotai-x": "^1.2.1",
"lodash": "^4.17.21",
"nanoid": "^3.3.6",
"optics-ts": "2.4.1",
"react-hotkeys-hook": "^4.4.1",
"use-deep-compare": "^1.1.0",
"zustand": "^4.4.7",
Expand Down
96 changes: 82 additions & 14 deletions packages/core/src/components/Plate.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
usePlateSelectors,
} from '@udecode/plate-common';

import { PLATE_SCOPE } from '../stores/index';
import { PlateController, usePlateEditorStore } from '../stores';
import { Plate } from './Plate';

describe('Plate', () => {
Expand All @@ -27,24 +27,36 @@ describe('Plate', () => {
});
describe('when editor is not defined', () => {
it('should be default', async () => {
const wrapper = ({ children }: any) => <Plate>{children}</Plate>;
const wrapper = ({ children }: any) => (
<Plate id="test1">
<Plate id="test2">{children}</Plate>
</Plate>
);

const { result } = renderHook(() => useEditorRef(), {
wrapper,
});

expect(result.current.id).toBe(PLATE_SCOPE.toString());
expect(result.current.id).toBe('test2');
});
});
describe('when id is defined', () => {
it('should be id', async () => {
const wrapper = ({ children }: any) => (
<Plate id="test">{children}</Plate>
<Plate id="test1">
<Plate id="test2">{children}</Plate>
</Plate>
);
const { result } = renderHook(() => useEditorRef('test'), {

const { result: result1 } = renderHook(() => useEditorRef('test1'), {
wrapper,
});
const { result: result2 } = renderHook(() => useEditorRef('test2'), {
wrapper,
});

expect(result.current.id).toBe('test');
expect(result1.current.id).toBe('test1');
expect(result2.current.id).toBe('test2');
});
});
});
Expand Down Expand Up @@ -224,19 +236,75 @@ describe('Plate', () => {
expect(result.current).toBe('test');
});
});
});

describe('when Plate with id > Plate without id', () => {
it('should be that id', () => {
describe('usePlateEditorStore', () => {
const getStore = (wrapper: any) =>
renderHook(() => usePlateEditorStore(), { wrapper }).result.current;

const getId = (wrapper: any) =>
renderHook(() => usePlateSelectors().id(), { wrapper }).result.current;

const getIsFallback = (wrapper: any) =>
renderHook(() => useEditorRef().isFallback, { wrapper }).result.current;

describe('when Plate exists', () => {
it('returns the store', () => {
const wrapper = ({ children }: any) => (
<Plate id="test">
<Plate>{children}</Plate>
</Plate>
<Plate id="test">{children}</Plate>
);
const { result } = renderHook(() => usePlateSelectors().id(), {
wrapper,

expect(getStore(wrapper)).toBeDefined();
expect(getId(wrapper)).toBe('test');
expect(getIsFallback(wrapper)).toBe(false);
});
});

describe('when Plate does not exist', () => {
describe('when PlateController exists', () => {
describe('when PlateController returns a store', () => {
it('returns the store', () => {
const EXPECTED_STORE = 'expected store' as any;

const wrapper = ({ children }: any) => (
<PlateController
editorStores={{
test: EXPECTED_STORE,
}}
activeId="test"
>
{children}
</PlateController>
);

expect(getStore(wrapper)).toBe(EXPECTED_STORE);
});
});

expect(result.current).toBe(PLATE_SCOPE);
describe('when PlateController returns null', () => {
it('returns the fallback store', () => {
const wrapper = ({ children }: any) => (
<PlateController
editorStores={{
test: null,
}}
activeId="test"
>
{children}
</PlateController>
);

expect(getStore(wrapper)).toBeDefined();
expect(getIsFallback(wrapper)).toBe(true);
});
});
});

describe('when PlateController does not exist', () => {
it('throws an error', () => {
const wrapper = ({ children }: any) => <>{children}</>;
expect(() => getStore(wrapper)).toThrowError();
});
});
});
});
Expand Down
14 changes: 11 additions & 3 deletions packages/core/src/components/Plate.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import { normalizeEditor, Value } from '@udecode/slate';
import { nanoid } from 'nanoid/non-secure';

import { PLATE_SCOPE, PlateStoreProvider } from '../stores';
import { PlateStoreProvider } from '../stores';
import {
PlateEditor,
PlatePlugin,
Expand All @@ -15,7 +16,10 @@ export interface PlateProps<
V extends Value = Value,
E extends PlateEditor<V> = PlateEditor<V>,
> extends Partial<
Pick<PlateStoreState<V, E>, 'id' | 'editor' | 'value' | 'readOnly'>
Pick<
PlateStoreState<V, E>,
'id' | 'editor' | 'value' | 'readOnly' | 'primary'
>
> {
children: React.ReactNode;
decorate?: TEditableProps['decorate'];
Expand Down Expand Up @@ -78,7 +82,7 @@ function PlateInner<
E extends PlateEditor<V> = PlateEditor<V>,
>({
normalizeInitialValue: shouldNormalizeInitialValue,
id = PLATE_SCOPE,
id: idProp,
editor: editorProp,
initialValue,
value: valueProp,
Expand All @@ -91,8 +95,11 @@ function PlateInner<
renderElement,
renderLeaf,
readOnly,
primary,
maxLength,
}: PlateProps<V, E>) {
const [id] = React.useState(() => idProp ?? nanoid());

const editor: E = React.useMemo(
() =>
editorProp ??
Expand Down Expand Up @@ -141,6 +148,7 @@ function PlateInner<
plugins={editor.plugins as any}
rawPlugins={pluginsProp}
readOnly={readOnly}
primary={primary}
value={value}
decorate={decorate}
onChange={onChange as PlateStoreState['onChange']}
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/components/PlateContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { TEditableProps } from '../types/slate-react/TEditableProps';
import { EditorMethodsEffect } from './EditorMethodsEffect';
import { EditorRefEffect } from './EditorRefEffect';
import { EditorStateEffect } from './EditorStateEffect';
import { PlateControllerEffect } from './PlateControllerEffect';
import { PlateSlate } from './PlateSlate';

export type PlateContentProps = TEditableProps & {
Expand Down Expand Up @@ -81,6 +82,7 @@ const PlateContent = React.forwardRef(
<EditorMethodsEffect id={id} />
<EditorStateEffect id={id} />
<EditorRefEffect id={id} />
<PlateControllerEffect id={id} />

{afterEditable}
</>
Expand Down
Loading

0 comments on commit 6d02746

Please sign in to comment.