Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plate 17: Replace zustand by jotai #1871

Merged
merged 11 commits into from
Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/code-block-major.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@udecode/plate-code-block": major
---

- Removed these imports because of build errors:
- `prismjs/components/prism-django`
- `prismjs/components/prism-ejs`
- `prismjs/components/prism-php`
75 changes: 75 additions & 0 deletions .changeset/core-major.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
"@udecode/plate-core": major
---

- `usePlateStore`:
- Plate no longer has a global store containing all the editor states (zustand). Each editor store is now defined in a React context tree ([jotai](https://github.com/pmndrs/jotai)). If you need to access all the editor states at once (as you could do before), you'll need to build that layer yourself.
- Plate store is now accessible only below `PlateProvider` or `Plate` (provider-less mode). It means it's no longer accessible outside of a Plate React tree. If you have such use-case, you'll need to build your own layer to share the state between your components.
- You can nest many `PlateProvider` with different scopes (`id` prop). Default scope is `PLATE_SCOPE`
- Hook usage:
- `const value = usePlateSelectors(id).value()`
- `const setValue = usePlateActions(id).value()`
- `const [value, setValue] = usePlateStates(id).value()`
- removed from the store:
- `editableProps`, use the props instead
- `enabled`, use conditional rendering instead
- `isReady`, no point anymore as it's now directly ready
- `useEventPlateId` is still used to get the last focused editor id.
- `Plate`
- if rendered below `PlateProvider`, it will render `PlateSlate > PlateEditable`
- if rendered without `PlateProvider`, it will render `PlateProvider > PlateSlate > PlateEditable`
- default `id` is no longer `main`, it's now `PLATE_SCOPE`
- `PlateProvider`
- Each provider has an optional `scope`, so you can have multiple providers in the same React tree and use the plate hooks with the corresponding `scope`.
- Plate effects are now run in `PlateProvider`
- `initialValue, value, editor, normalizeInitialValue, normalizeEditor` are no longer defined in an effect (SSR support)
- Props:
- now extends the previous `Plate` props
- if using `PlateProvider`, set the provider props on it instead of `Plate`. `Plate` would only need `editableProps` and `PlateEditableExtendedProps`
- if not using it, set the provider props on `Plate`
```tsx
// Before
<PlateProvider>
<Toolbar>
<AlignToolbarButtons />
</Toolbar>

<Plate<MyValue> editableProps={editableProps} <MyValue> initialValue={alignValue} plugins={plugins} />
</PlateProvider>

// After
<PlateProvider<MyValue> initialValue={alignValue} plugins={plugins}>
<Toolbar>
<AlignToolbarButtons />
</Toolbar>

<Plate<MyValue> editableProps={editableProps} />
</PlateProvider>

// After (provider-less mode)
<Plate<MyValue> editableProps={editableProps} initialValue={alignValue} plugins={plugins} />
```
- types:
- store `editor` is no longer nullable
- store `value` is no longer nullable
- `id` type is now `PlateId`
- renamed:
- `SCOPE_PLATE` to `PLATE_SCOPE`
- `getEventEditorId` to `getEventPlateId`
- `getPlateActions().resetEditor` to `useResetPlateEditor()`
- removed:
- `plateIdAtom`
- `usePlateId` for `usePlateSelectors().id()`
- `EditablePlugins` for `PlateEditable`
- `SlateChildren`
- `PlateEventProvider` for `PlateProvider`
- `withPlateEventProvider` for `withPlateProvider`
- `usePlate`
- `usePlatesStoreEffect`
- `useEventEditorId` for `useEventPlateId`
- `platesStore, platesActions, platesSelectors, usePlatesSelectors`
- `getPlateActions` for `usePlateActions`
- `getPlateSelectors` for `usePlateSelectors`
- `getPlateEditorRef` for `usePlateEditorRef`
- `getPlateStore, usePlateStore`
- `EditorId` for `PlateId`
69 changes: 69 additions & 0 deletions .changeset/core-minor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
"@udecode/plate-core": minor
---

- **SSR support**
- `useEventPlateId` returns:
- `id` if defined
- focused editor id if defined
- blurred editor id if defined
- last editor id if defined
- provider id if defined
- `PLATE_SCOPE` otherwise
- new dep: `nanoid`
- `PlateProvider`
```tsx
export interface PlateProviderProps<
V extends Value = Value,
E extends PlateEditor<V> = PlateEditor<V>
> extends PlateProviderEffectsProps<V, E>,
Partial<Pick<PlateStoreState<V, E>, 'id' | 'editor'>> {
/**
* Initial value of the editor.
* @default [{ children: [{ text: '' }]}]
*/
initialValue?: PlateStoreState<V>['value'];

/**
* When `true`, it will normalize the initial value passed to the `editor` once it gets created.
* This is useful when adding normalization rules on already existing content.
* @default false
*/
normalizeInitialValue?: boolean;

scope?: Scope;
}
```
- `PlateProviderEffects`
- `PlateSlate`
- `PlateEditable`
```tsx
export interface PlateEditableExtendedProps {
id?: PlateId;

/**
* The children rendered inside `Slate`, after `Editable`.
*/
children?: ReactNode;

/**
* Ref to the `Editable` component.
*/
editableRef?: Ref<HTMLDivElement>;

/**
* The first children rendered inside `Slate`, before `Editable`.
* Slate DOM is not yet resolvable on first render, for that case use `children` instead.
*/
firstChildren?: ReactNode;

/**
* Custom `Editable` node.
*/
renderEditable?: (editable: ReactNode) => ReactNode;
}

export interface PlateEditableProps<V extends Value = Value>
extends Omit<TEditableProps<V>, 'id'>,
PlateEditableExtendedProps {}
```
6 changes: 6 additions & 0 deletions .changeset/core-patch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@udecode/plate-core": patch
---

- Fixes #1508
- Fixes #1343
5 changes: 5 additions & 0 deletions .changeset/ui-major.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@udecode/plate-ui": major
---

- Removed `[ELEMENT_CODE_BLOCK]: CodeBlockElement` from Plate UI. You can define it in your app.
22 changes: 11 additions & 11 deletions docs/docs/getting-started/basic-editor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,37 @@ Each example is using [Sandpack](https://sandpack.codesandbox.io/), a live-runni

Let's start with a minimal editor using [Plate](/docs/Plate) and [editableProps](/docs/Plate#editableprops).

import { BasicEditorDefaultSandpack } from './BasicEditorSandpack'



import {
BasicEditorDefaultSandpack,
BasicEditorHandlerSandpack,
BasicEditorValueSandpack
} from "./BasicEditorSandpack";

<BasicEditorDefaultSandpack />

### Value

Let's set the initial value of the editor: one paragraph.

import { BasicEditorValueSandpack } from './BasicEditorSandpack'

<BasicEditorValueSandpack />

:::note

Once you render multiple `Plate`, you'll need to pass unique `id` prop to each.
This is optional for the first instance.

:::
<BasicEditorValueSandpack />

### Change Handler

Now we would like to listen to editor changes so we can save the value somewhere.
Let's use `onChange` prop.

import { BasicEditorHandlerSandpack } from './BasicEditorSandpack'


<BasicEditorHandlerSandpack />

:::note

`Plate` children are rendered just after the editable component.
`Plate` children are rendered **after** the editable component. Use `firstChildren` prop to render something **before** the editable component.

:::

Expand Down
7 changes: 4 additions & 3 deletions docs/docs/getting-started/basic-plugins.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ Let's use the basic element and basic mark plugins.
`Plate` is using the `type` property so a plugin can render a node by type.
:::

import { BasicPluginsDefaultSandpack } from './BasicPluginsSandpack'

import { BasicPluginsComponentsSandpack, BasicPluginsDefaultSandpack } from "./BasicPluginsSandpack";

<BasicPluginsDefaultSandpack />

Everything actually works, by looking at the debug value. However, we didn't provide any `components` to render, so it's using the default (unstyled) ones.
Everything actually works by looking at the debug value. However, we didn't provide any `components` to render, so it's using the default (unstyled) ones.
The default element component is a `div` and the default leaf component is a `span`.

:::info
Expand All @@ -37,7 +38,7 @@ To plug all the components at once, you can use `createPlugins`:
- use the first parameter for the `plugins`
- use the second parameter for the `components`. In the following example we'll use `createPlateUI()`, which returns all Plate components by plugin key.

import { BasicPluginsComponentsSandpack } from './BasicPluginsSandpack'


<BasicPluginsComponentsSandpack />

Expand Down
27 changes: 16 additions & 11 deletions docs/docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,30 @@ You can install all the packages bundled together:

```bash npm2yarn
npm install @udecode/plate

# required peer deps
npm install slate slate-react slate-history slate-hyperscript react react-dom react-dnd react-dnd-html5-backend styled-components
```

You will also need these peer dependencies:
Alternatively you can install only the packages you need as listed in the following sections.

```bash npm2yarn
npm install slate slate-react slate-history slate-hyperscript react react-dom styled-components
# core
npm install @udecode/plate-core

# if using @udecode/plate-ui-dnd
npm install react-dnd react-dnd-html5-backend
```
# required peer deps
npm install slate slate-react slate-history slate-hyperscript react react-dom

Alternatively you can install only the packages you need as listed in the following sections.
# plugins
npm install @udecode/plate-basic-elements
# npm install @udecode/plate-...

Additional packages:

```bash npm2yarn
# if using @udecode/plate-serializer-docx
npm install @udecode/plate-juice

# Excalidraw
npm install @udecode/plate-ui-excalidraw
# if using @udecode/plate-ui
npm install styled-components

# if using @udecode/plate-ui-dnd
npm install react-dnd react-dnd-html5-backend
```
Loading