@use-kona/editor 0.1.1 → 0.1.2-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,13 +21,20 @@ const deserialize = (plugins)=>(element)=>{
21
21
  for (const plugin of plugins){
22
22
  if (plugin.blocks?.some((b)=>b.deserialize)) plugin.blocks.forEach((e)=>{
23
23
  if (e.deserialize) {
24
- const childrenAsDescendants = children;
24
+ const childrenAsDescendants = result || children;
25
+ const newResult = e.deserialize(element, childrenAsDescendants);
26
+ if (newResult) result = newResult;
27
+ }
28
+ });
29
+ if (plugin.leafs?.some((b)=>b.deserialize)) plugin.leafs.forEach((e)=>{
30
+ if (e.deserialize) {
31
+ const childrenAsDescendants = result || children;
25
32
  const newResult = e.deserialize(element, childrenAsDescendants);
26
33
  if (newResult) result = newResult;
27
34
  }
28
35
  });
29
- if (result) return result;
30
36
  }
37
+ if (result) return result;
31
38
  return children.filter((child)=>null !== child);
32
39
  };
33
40
  export { deserialize };
@@ -1 +1,8 @@
1
- export declare const ExampleEditor: () => import("react/jsx-runtime").JSX.Element;
1
+ import type { Descendant } from 'slate';
2
+ type Props = {
3
+ initialValueType?: 'kona-editor' | 'html';
4
+ value?: any;
5
+ onChange?: (value: Descendant[]) => void;
6
+ };
7
+ export declare const ExampleEditor: (props: Props) => import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -1,22 +1,39 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
2
3
  import { DndProvider } from "react-dnd";
3
4
  import { HTML5Backend } from "react-dnd-html5-backend";
5
+ import { deserialize } from "../core/deserialize.js";
4
6
  import { KonaEditor } from "../editor.js";
5
7
  import Editor_module from "./Editor.module.js";
6
8
  import { getPlugins } from "./getPlugins.js";
7
9
  import { text as external_text_js_text } from "./text.js";
8
10
  const initialValue = external_text_js_text;
9
- const ExampleEditor = ()=>/*#__PURE__*/ jsx(DndProvider, {
11
+ const ExampleEditor = (props)=>{
12
+ const { initialValueType = 'kona-editor' } = props;
13
+ const [plugins] = useState(getPlugins());
14
+ const [value, setValue] = useState(null);
15
+ const ref = useRef(null);
16
+ useEffect(()=>{
17
+ if ('kona-editor' === initialValueType) setValue(props.value);
18
+ else {
19
+ const parsed = deserialize(plugins)(props.value);
20
+ parsed && setValue(parsed);
21
+ console.log(parsed);
22
+ }
23
+ }, []);
24
+ return /*#__PURE__*/ jsx(DndProvider, {
10
25
  backend: HTML5Backend,
11
26
  children: /*#__PURE__*/ jsx("div", {
12
27
  className: [
13
28
  Editor_module.root
14
29
  ].join(' '),
15
- children: /*#__PURE__*/ jsx(KonaEditor, {
16
- initialValue: initialValue,
17
- plugins: getPlugins(),
18
- onChange: console.log
30
+ children: value && /*#__PURE__*/ jsx(KonaEditor, {
31
+ ref: ref,
32
+ initialValue: value || initialValue,
33
+ plugins: plugins,
34
+ onChange: props.onChange || console.log
19
35
  })
20
36
  })
21
37
  });
38
+ };
22
39
  export { ExampleEditor };
@@ -4,7 +4,6 @@
4
4
  width: 600px;
5
5
  height: calc(100vh - 256px);
6
6
  max-height: 100vh;
7
- margin: 32px auto;
8
7
  overflow: hidden;
9
8
  }
10
9
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
+ export type { CustomElement, CustomText } from '../types';
2
+ export { deserialize } from './core/deserialize';
3
+ export { serialize } from './core/serialize';
1
4
  export { defaultValue } from './defaultValue';
2
5
  export * from './editor';
3
6
  export { ExampleEditor } from './examples/Editor';
4
7
  export * from './plugins';
8
+ export type { EditorRef } from './types';
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { deserialize } from "./core/deserialize.js";
2
+ import { serialize } from "./core/serialize.js";
1
3
  import { defaultValue } from "./defaultValue.js";
2
4
  import { ExampleEditor } from "./examples/Editor.js";
3
5
  export * from "./editor.js";
4
6
  export * from "./plugins/index.js";
5
- export { ExampleEditor, defaultValue };
7
+ export { ExampleEditor, defaultValue, deserialize, serialize };
@@ -1,5 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { Editor } from "slate";
3
+ import { jsx as external_slate_hyperscript_jsx } from "slate-hyperscript";
3
4
  class BasicFormattingPlugin {
4
5
  hotkeys = [
5
6
  [
@@ -48,6 +49,34 @@ class BasicFormattingPlugin {
48
49
  ...attributes,
49
50
  children: content
50
51
  });
52
+ },
53
+ deserialize: (element, children)=>{
54
+ const { nodeName } = element;
55
+ let attrs = null;
56
+ switch(nodeName){
57
+ case 'EM':
58
+ case 'I':
59
+ attrs = {
60
+ italic: true
61
+ };
62
+ break;
63
+ case 'STRONG':
64
+ attrs = {
65
+ bold: true
66
+ };
67
+ break;
68
+ case 'U':
69
+ attrs = {
70
+ underline: true
71
+ };
72
+ break;
73
+ case 'S':
74
+ attrs = {
75
+ strikethrough: true
76
+ };
77
+ break;
78
+ }
79
+ if (attrs) return children?.map((child)=>external_slate_hyperscript_jsx('text', attrs, child));
51
80
  }
52
81
  }
53
82
  ];
@@ -1,6 +1,6 @@
1
1
  import { Editor } from 'slate';
2
- import { RenderElementProps } from 'slate-react';
3
- import { IPlugin } from '../../types';
2
+ import type { RenderElementProps } from 'slate-react';
3
+ import type { IPlugin } from '../../types';
4
4
  export declare class HeadingsPlugin implements IPlugin {
5
5
  static HeadingLevel1: string;
6
6
  static HeadingLevel2: string;
@@ -8,6 +8,7 @@ export declare class HeadingsPlugin implements IPlugin {
8
8
  blocks: {
9
9
  type: string;
10
10
  render: (props: RenderElementProps) => import("react/jsx-runtime").JSX.Element;
11
+ deserialize: (element: HTMLElement, children: any) => import("../..").CustomElement | undefined;
11
12
  }[];
12
13
  static isHeading1Active(editor: Editor): boolean;
13
14
  static isHeading2Active(editor: Editor): boolean;
@@ -1,5 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { Editor, Element, Transforms } from "slate";
3
+ import { jsx as external_slate_hyperscript_jsx } from "slate-hyperscript";
3
4
  class HeadingsPlugin {
4
5
  static HeadingLevel1 = 'h1';
5
6
  static HeadingLevel2 = 'h2';
@@ -10,21 +11,39 @@ class HeadingsPlugin {
10
11
  render: (props)=>/*#__PURE__*/ jsx("h1", {
11
12
  ...props.attributes,
12
13
  children: props.children
13
- })
14
+ }),
15
+ deserialize: (element, children)=>{
16
+ const { nodeName } = element;
17
+ if ('H1' === nodeName) return external_slate_hyperscript_jsx('element', {
18
+ type: HeadingsPlugin.HeadingLevel1
19
+ }, children);
20
+ }
14
21
  },
15
22
  {
16
23
  type: HeadingsPlugin.HeadingLevel2,
17
24
  render: (props)=>/*#__PURE__*/ jsx("h2", {
18
25
  ...props.attributes,
19
26
  children: props.children
20
- })
27
+ }),
28
+ deserialize: (element, children)=>{
29
+ const { nodeName } = element;
30
+ if ('H2' === nodeName) return external_slate_hyperscript_jsx('element', {
31
+ type: HeadingsPlugin.HeadingLevel2
32
+ }, children);
33
+ }
21
34
  },
22
35
  {
23
36
  type: HeadingsPlugin.HeadingLevel3,
24
37
  render: (props)=>/*#__PURE__*/ jsx("h3", {
25
38
  ...props.attributes,
26
39
  children: props.children
27
- })
40
+ }),
41
+ deserialize: (element, children)=>{
42
+ const { nodeName } = element;
43
+ if ('H3' === nodeName) return external_slate_hyperscript_jsx('element', {
44
+ type: HeadingsPlugin.HeadingLevel3
45
+ }, children);
46
+ }
28
47
  }
29
48
  ];
30
49
  static isHeading1Active(editor) {
@@ -11,6 +11,7 @@ export declare class LinksPlugin implements IPlugin {
11
11
  isInline: boolean;
12
12
  type: string;
13
13
  render: (props: RenderElementProps) => import("react/jsx-runtime").JSX.Element;
14
+ deserialize: (element: HTMLElement, children: any) => import("../..").CustomElement | undefined;
14
15
  }[];
15
16
  static addLink: (editor: Editor, url: string) => void;
16
17
  static removeLink: (editor: Editor) => void;
@@ -1,6 +1,7 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import is_url from "is-url";
3
3
  import { Editor, Element, Range, Transforms } from "slate";
4
+ import { jsx as external_slate_hyperscript_jsx } from "slate-hyperscript";
4
5
  import { LINK_ELEMENT } from "./constants.js";
5
6
  import { Link } from "./Link.js";
6
7
  class LinksPlugin {
@@ -47,7 +48,16 @@ class LinksPlugin {
47
48
  ...props,
48
49
  element: props.element,
49
50
  renderHint: this.options.renderHint
50
- })
51
+ }),
52
+ deserialize: (element, children)=>{
53
+ if ('A' === element.tagName) {
54
+ const url = element.getAttribute('href') || '';
55
+ return external_slate_hyperscript_jsx('element', {
56
+ type: LinksPlugin.LINK_TYPE,
57
+ url
58
+ }, children);
59
+ }
60
+ }
51
61
  }
52
62
  ];
53
63
  static addLink = (editor, url)=>{
@@ -1,6 +1,7 @@
1
1
  import type { KeyboardEvent } from 'react';
2
2
  import { Editor } from 'slate';
3
3
  import type { RenderElementProps } from 'slate-react';
4
+ import type { CustomElement } from '../../../types';
4
5
  import type { IPlugin } from '../../types';
5
6
  type Options = {
6
7
  listTypes?: string[];
@@ -16,6 +17,7 @@ export declare class ListsPlugin implements IPlugin {
16
17
  blocks: {
17
18
  type: string;
18
19
  render: (props: RenderElementProps) => import("react/jsx-runtime").JSX.Element;
20
+ deserialize: (element: HTMLElement, children: any) => CustomElement | undefined;
19
21
  }[];
20
22
  handlers: {
21
23
  onKeyDown: (event: KeyboardEvent, editor: Editor) => true | undefined;
@@ -1,5 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { Editor, Element, Node, Transforms } from "slate";
3
+ import { jsx as external_slate_hyperscript_jsx } from "slate-hyperscript";
3
4
  import { getPrev } from "../../core/queries.js";
4
5
  import styles_module from "./styles.module.js";
5
6
  class ListsPlugin {
@@ -76,7 +77,13 @@ class ListsPlugin {
76
77
  className: styles_module.list,
77
78
  ...props.attributes,
78
79
  children: props.children
79
- })
80
+ }),
81
+ deserialize: (element, children)=>{
82
+ const { nodeName } = element;
83
+ if ('UL' === nodeName) return external_slate_hyperscript_jsx('element', {
84
+ type: ListsPlugin.BULLETED_LIST_ELEMENT
85
+ }, children);
86
+ }
80
87
  },
81
88
  {
82
89
  type: ListsPlugin.NUMBERED_LIST_ELEMENT,
@@ -84,7 +91,13 @@ class ListsPlugin {
84
91
  className: styles_module.list,
85
92
  ...props.attributes,
86
93
  children: props.children
87
- })
94
+ }),
95
+ deserialize: (element, children)=>{
96
+ const { nodeName } = element;
97
+ if ('OL' === nodeName) return external_slate_hyperscript_jsx('element', {
98
+ type: ListsPlugin.NUMBERED_LIST_ELEMENT
99
+ }, children);
100
+ }
88
101
  },
89
102
  {
90
103
  type: ListsPlugin.LIST_ITEM_ELEMENT,
@@ -92,7 +105,13 @@ class ListsPlugin {
92
105
  className: styles_module.listItem,
93
106
  ...props.attributes,
94
107
  children: props.children
95
- })
108
+ }),
109
+ deserialize: (element, children)=>{
110
+ const { nodeName } = element;
111
+ if ('LI' === nodeName) return external_slate_hyperscript_jsx('element', {
112
+ type: ListsPlugin.LIST_ITEM_ELEMENT
113
+ }, children);
114
+ }
96
115
  }
97
116
  ];
98
117
  handlers = {
package/dist/types.d.ts CHANGED
@@ -34,6 +34,7 @@ export type Leaf<T extends Editor, TLeaf extends CustomText = CustomText> = {
34
34
  leaf: CustomText & TLeaf;
35
35
  }, editor: T) => ReactElement | null;
36
36
  isVoid?: boolean;
37
+ deserialize?: Deserialize;
37
38
  };
38
39
  type Hotkey = readonly [string, (event: KeyboardEvent, editor: Editor) => void];
39
40
  export type UiParams = {
@@ -46,5 +47,5 @@ export type EditorRef = {
46
47
  deserialize: (element: HTMLElement) => (Descendant | string)[] | string | Descendant | null;
47
48
  };
48
49
  export type Serialize = (node: Node, children?: string) => string | undefined;
49
- export type Deserialize = (element: HTMLElement, children?: (string | Descendant)[]) => Node | undefined;
50
+ export type Deserialize = (element: HTMLElement, children?: (string | Descendant)[]) => CustomElement | CustomText[] | undefined;
50
51
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@use-kona/editor",
3
- "version": "0.1.1",
3
+ "version": "0.1.2-rc.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/index.ts"
@@ -1,5 +1,6 @@
1
1
  import { type Descendant, Element, type Node } from 'slate';
2
2
  import { jsx } from 'slate-hyperscript';
3
+ import { CustomElement, CustomText } from '../../types';
3
4
  import type { IPlugin } from '../types';
4
5
 
5
6
  export const deserialize =
@@ -35,13 +36,16 @@ export const deserialize =
35
36
  return jsx('element', { type: 'paragraph' }, children);
36
37
  }
37
38
 
38
- let result: Node | null = null;
39
+ let result: CustomElement | CustomText[] | null = null;
39
40
  for (const plugin of plugins) {
40
41
  if (plugin.blocks?.some((b) => b.deserialize)) {
41
42
  plugin.blocks.forEach((e) => {
42
43
  if (e.deserialize) {
43
- // Cast children to match the expected type in Deserialize interface
44
- const childrenAsDescendants = children as (string | Descendant)[];
44
+ const childrenAsDescendants = (result || children) as (
45
+ | string
46
+ | Descendant
47
+ )[];
48
+
45
49
  const newResult = e.deserialize(element, childrenAsDescendants);
46
50
  if (newResult) {
47
51
  result = newResult;
@@ -49,9 +53,26 @@ export const deserialize =
49
53
  }
50
54
  });
51
55
  }
52
- if (result) {
53
- return result;
56
+
57
+ if (plugin.leafs?.some((b) => b.deserialize)) {
58
+ plugin.leafs.forEach((e) => {
59
+ if (e.deserialize) {
60
+ const childrenAsDescendants = (result || children) as (
61
+ | string
62
+ | Descendant
63
+ )[];
64
+ const newResult = e.deserialize(element, childrenAsDescendants);
65
+ if (newResult) {
66
+ result = newResult;
67
+ }
68
+ }
69
+ });
54
70
  }
55
71
  }
72
+
73
+ if (result) {
74
+ return result;
75
+ }
76
+
56
77
  return children.filter((child) => child !== null);
57
78
  };
@@ -3,7 +3,6 @@
3
3
  height: calc(100vh - 128px * 2);
4
4
  overflow: hidden;
5
5
  max-height: 100vh;
6
- margin: 32px auto;
7
6
  border: 1px solid var(--kona-editor-border-color);
8
7
  border-radius: 8px;
9
8
  }
@@ -1,22 +1,52 @@
1
+ import { useEffect, useRef, useState } from 'react';
1
2
  import { DndProvider } from 'react-dnd';
2
3
  import { HTML5Backend } from 'react-dnd-html5-backend';
4
+ import type { Descendant } from 'slate';
3
5
  import type { CustomElement } from '../../types';
6
+ import { deserialize } from '../core/deserialize';
4
7
  import { KonaEditor } from '../editor';
8
+ import type { EditorRef } from '../types';
5
9
  import styles from './Editor.module.css';
6
10
  import { getPlugins } from './getPlugins';
7
11
  import { text } from './text';
8
12
 
9
13
  const initialValue = text;
10
14
 
11
- export const ExampleEditor = () => {
15
+ type Props = {
16
+ initialValueType?: 'kona-editor' | 'html';
17
+ value?: any;
18
+ onChange?: (value: Descendant[]) => void;
19
+ };
20
+
21
+ export const ExampleEditor = (props: Props) => {
22
+ const { initialValueType = 'kona-editor' } = props;
23
+ const [plugins] = useState(getPlugins());
24
+ const [value, setValue] = useState<Descendant[] | null>(null);
25
+
26
+ const ref = useRef<EditorRef>(null);
27
+
28
+ // biome-ignore lint/correctness/useExhaustiveDependencies: only on init
29
+ useEffect(() => {
30
+ if (initialValueType === 'kona-editor') {
31
+ setValue(props.value);
32
+ } else {
33
+ const parsed = deserialize(plugins)(props.value);
34
+ parsed && setValue(parsed as Descendant[]);
35
+ console.log(parsed);
36
+ }
37
+ }, []);
38
+
12
39
  return (
13
40
  <DndProvider backend={HTML5Backend}>
14
41
  <div className={[styles.root].join(' ')}>
15
- <KonaEditor
16
- initialValue={initialValue as CustomElement[]}
17
- plugins={getPlugins()}
18
- onChange={console.log}
19
- />
42
+ {value && (
43
+ <KonaEditor
44
+ ref={ref}
45
+ initialValue={value || (initialValue as CustomElement[])}
46
+ plugins={plugins}
47
+ onChange={props.onChange || console.log}
48
+ />
49
+ )}
20
50
  </div>
21
51
  </DndProvider>
22
52
  );
package/src/index.ts CHANGED
@@ -1,4 +1,8 @@
1
+ export type { CustomElement, CustomText } from '../types';
2
+ export { deserialize } from './core/deserialize';
3
+ export { serialize } from './core/serialize';
1
4
  export { defaultValue } from './defaultValue';
2
5
  export * from './editor';
3
6
  export { ExampleEditor } from './examples/Editor';
4
7
  export * from './plugins';
8
+ export type { EditorRef } from './types';
@@ -1,4 +1,5 @@
1
1
  import { Editor } from 'slate';
2
+ import { jsx } from 'slate-hyperscript';
2
3
  import type { CustomElement, CustomText } from '../../../types';
3
4
  import type { IPlugin } from '../../types';
4
5
 
@@ -63,6 +64,36 @@ export class BasicFormattingPlugin
63
64
 
64
65
  return <span {...attributes}>{content}</span>;
65
66
  },
67
+ deserialize: (element: HTMLElement, children) => {
68
+ const { nodeName } = element;
69
+
70
+ let attrs: Record<string, boolean> | null = null;
71
+ switch (nodeName) {
72
+ case 'EM':
73
+ case 'I': {
74
+ attrs = { italic: true };
75
+ break;
76
+ }
77
+ case 'STRONG': {
78
+ attrs = { bold: true };
79
+ break;
80
+ }
81
+ case 'U': {
82
+ attrs = { underline: true };
83
+ break;
84
+ }
85
+ case 'S': {
86
+ attrs = { strikethrough: true };
87
+ break;
88
+ }
89
+ }
90
+
91
+ if (attrs) {
92
+ return children?.map((child) => jsx('text', attrs, child));
93
+ }
94
+
95
+ return undefined;
96
+ },
66
97
  },
67
98
  ];
68
99
 
@@ -1,6 +1,7 @@
1
1
  import { Editor, Element, Transforms } from 'slate';
2
- import { RenderElementProps } from 'slate-react';
3
- import { IPlugin } from '../../types';
2
+ import { jsx } from 'slate-hyperscript';
3
+ import type { RenderElementProps } from 'slate-react';
4
+ import type { IPlugin } from '../../types';
4
5
 
5
6
  export class HeadingsPlugin implements IPlugin {
6
7
  static HeadingLevel1 = 'h1';
@@ -13,18 +14,51 @@ export class HeadingsPlugin implements IPlugin {
13
14
  render: (props: RenderElementProps) => {
14
15
  return <h1 {...props.attributes}>{props.children}</h1>;
15
16
  },
17
+ deserialize: (element: HTMLElement, children) => {
18
+ const { nodeName } = element;
19
+
20
+ if (nodeName === 'H1') {
21
+ return jsx(
22
+ 'element',
23
+ { type: HeadingsPlugin.HeadingLevel1 },
24
+ children,
25
+ );
26
+ }
27
+ },
16
28
  },
17
29
  {
18
30
  type: HeadingsPlugin.HeadingLevel2,
19
31
  render: (props: RenderElementProps) => {
20
32
  return <h2 {...props.attributes}>{props.children}</h2>;
21
33
  },
34
+ deserialize: (element: HTMLElement, children) => {
35
+ const { nodeName } = element;
36
+
37
+ if (nodeName === 'H2') {
38
+ return jsx(
39
+ 'element',
40
+ { type: HeadingsPlugin.HeadingLevel2 },
41
+ children,
42
+ );
43
+ }
44
+ },
22
45
  },
23
46
  {
24
47
  type: HeadingsPlugin.HeadingLevel3,
25
48
  render: (props: RenderElementProps) => {
26
49
  return <h3 {...props.attributes}>{props.children}</h3>;
27
50
  },
51
+ deserialize: (element: HTMLElement, children) => {
52
+ const { nodeName } = element;
53
+
54
+ if (nodeName === 'H3') {
55
+ return jsx(
56
+ 'element',
57
+ { type: HeadingsPlugin.HeadingLevel3 },
58
+ children,
59
+ );
60
+ }
61
+ },
28
62
  },
29
63
  ];
30
64
 
@@ -1,6 +1,8 @@
1
1
  import isUrl from 'is-url';
2
2
  import { Editor, Element, Range, Transforms } from 'slate';
3
+ import { jsx } from 'slate-hyperscript';
3
4
  import type { RenderElementProps } from 'slate-react';
5
+ import { deserialize } from '../../core/deserialize';
4
6
  import type { IPlugin } from '../../types';
5
7
  import { LINK_ELEMENT } from './constants';
6
8
  import { Link } from './Link';
@@ -54,6 +56,19 @@ export class LinksPlugin implements IPlugin {
54
56
  />
55
57
  );
56
58
  },
59
+ deserialize: (element: HTMLElement, children) => {
60
+ if (element.tagName === 'A') {
61
+ const url = element.getAttribute('href') || '';
62
+ return jsx(
63
+ 'element',
64
+ {
65
+ type: LinksPlugin.LINK_TYPE,
66
+ url,
67
+ },
68
+ children,
69
+ );
70
+ }
71
+ },
57
72
  },
58
73
  ];
59
74
 
@@ -8,6 +8,7 @@ import {
8
8
  type Path,
9
9
  Transforms,
10
10
  } from 'slate';
11
+ import { jsx } from 'slate-hyperscript';
11
12
  import type { RenderElementProps } from 'slate-react';
12
13
  import type { CustomElement } from '../../../types';
13
14
  import { getPrev } from '../../core/queries';
@@ -133,6 +134,16 @@ export class ListsPlugin implements IPlugin {
133
134
  </ul>
134
135
  );
135
136
  },
137
+ deserialize: (element: HTMLElement, children) => {
138
+ const { nodeName } = element;
139
+ if (nodeName === 'UL') {
140
+ return jsx(
141
+ 'element',
142
+ { type: ListsPlugin.BULLETED_LIST_ELEMENT },
143
+ children,
144
+ );
145
+ }
146
+ },
136
147
  },
137
148
  {
138
149
  type: ListsPlugin.NUMBERED_LIST_ELEMENT,
@@ -143,6 +154,16 @@ export class ListsPlugin implements IPlugin {
143
154
  </ol>
144
155
  );
145
156
  },
157
+ deserialize: (element: HTMLElement, children) => {
158
+ const { nodeName } = element;
159
+ if (nodeName === 'OL') {
160
+ return jsx(
161
+ 'element',
162
+ { type: ListsPlugin.NUMBERED_LIST_ELEMENT },
163
+ children,
164
+ );
165
+ }
166
+ },
146
167
  },
147
168
  {
148
169
  type: ListsPlugin.LIST_ITEM_ELEMENT,
@@ -153,6 +174,16 @@ export class ListsPlugin implements IPlugin {
153
174
  </li>
154
175
  );
155
176
  },
177
+ deserialize: (element: HTMLElement, children) => {
178
+ const { nodeName } = element;
179
+ if (nodeName === 'LI') {
180
+ return jsx(
181
+ 'element',
182
+ { type: ListsPlugin.LIST_ITEM_ELEMENT },
183
+ children,
184
+ );
185
+ }
186
+ },
156
187
  },
157
188
  ];
158
189
 
package/src/types.ts CHANGED
@@ -60,6 +60,7 @@ export type Leaf<T extends Editor, TLeaf extends CustomText = CustomText> = {
60
60
  editor: T,
61
61
  ) => ReactElement | null;
62
62
  isVoid?: boolean;
63
+ deserialize?: Deserialize;
63
64
  };
64
65
 
65
66
  type Hotkey = readonly [string, (event: KeyboardEvent, editor: Editor) => void];
@@ -84,4 +85,4 @@ export type Serialize = (node: Node, children?: string) => string | undefined;
84
85
  export type Deserialize = (
85
86
  element: HTMLElement,
86
87
  children?: (string | Descendant)[],
87
- ) => Node | undefined;
88
+ ) => CustomElement | CustomText[] | undefined;