@portabletext/editor 1.3.1 → 1.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.3.1",
3
+ "version": "1.4.1",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -43,17 +43,19 @@
43
43
  ],
44
44
  "dependencies": {
45
45
  "@portabletext/patches": "1.1.0",
46
+ "@xstate/react": "^4.1.3",
46
47
  "debug": "^4.3.4",
47
48
  "is-hotkey-esm": "^1.0.0",
48
49
  "lodash": "^4.17.21",
49
50
  "react-compiler-runtime": "19.0.0-beta-6fc168f-20241025",
50
51
  "slate": "0.110.2",
51
- "slate-react": "0.110.3",
52
+ "slate-dom": "^0.111.0",
53
+ "slate-react": "0.111.0",
52
54
  "use-effect-event": "^1.0.2",
53
55
  "xstate": "^5.18.2"
54
56
  },
55
57
  "devDependencies": {
56
- "@babel/preset-env": "^7.25.9",
58
+ "@babel/preset-env": "^7.26.0",
57
59
  "@babel/preset-react": "^7.25.9",
58
60
  "@jest/globals": "^29.7.0",
59
61
  "@jest/types": "^29.6.3",
@@ -64,7 +66,7 @@
64
66
  "@sanity/pkg-utils": "^6.11.8",
65
67
  "@sanity/schema": "^3.62.3",
66
68
  "@sanity/types": "^3.62.3",
67
- "@sanity/ui": "^2.8.17",
69
+ "@sanity/ui": "^2.8.18",
68
70
  "@sanity/util": "^3.62.3",
69
71
  "@testing-library/dom": "^10.4.0",
70
72
  "@testing-library/jest-dom": "^6.6.3",
@@ -73,7 +75,7 @@
73
75
  "@types/debug": "^4.1.5",
74
76
  "@types/express": "^4.17.21",
75
77
  "@types/express-ws": "^3.0.5",
76
- "@types/lodash": "^4.17.12",
78
+ "@types/lodash": "^4.17.13",
77
79
  "@types/node": "^18.19.8",
78
80
  "@types/node-ipc": "^9.2.3",
79
81
  "@types/react": "^18.3.12",
@@ -83,16 +85,15 @@
83
85
  "@typescript-eslint/parser": "^8.12.2",
84
86
  "@vitejs/plugin-react": "^4.3.3",
85
87
  "@vitest/browser": "^2.1.4",
86
- "@xstate/react": "^4.1.3",
87
88
  "babel-plugin-react-compiler": "beta",
88
89
  "dotenv": "^16.4.5",
89
- "eslint": "8",
90
+ "eslint": "8.57.1",
90
91
  "eslint-plugin-react-compiler": "beta",
91
92
  "eslint-plugin-react-hooks": "^5.0.0",
92
93
  "express": "^4.21.1",
93
94
  "express-ws": "^5.0.2",
94
95
  "jest": "^29.7.0",
95
- "jest-dev-server": "^10.1.1",
96
+ "jest-dev-server": "^10.1.4",
96
97
  "jest-environment-node": "^29.7.0",
97
98
  "jsdom": "^25.0.1",
98
99
  "node-ipc": "npm:@node-ipc/compat@9.2.5",
@@ -29,7 +29,6 @@ import type {
29
29
  import {debugWithName} from '../utils/debug'
30
30
  import {getPortableTextMemberSchemaTypes} from '../utils/getPortableTextMemberSchemaTypes'
31
31
  import {compileType} from '../utils/schema'
32
- import {coreBehaviors} from './behavior/behavior.core'
33
32
  import {SlateContainer} from './components/SlateContainer'
34
33
  import {Synchronizer} from './components/Synchronizer'
35
34
  import {EditorActorContext} from './editor-actor-context'
@@ -38,6 +37,7 @@ import {PortableTextEditorContext} from './hooks/usePortableTextEditor'
38
37
  import {PortableTextEditorSelectionProvider} from './hooks/usePortableTextEditorSelection'
39
38
  import {PortableTextEditorReadOnlyContext} from './hooks/usePortableTextReadOnly'
40
39
  import {defaultKeyGenerator} from './key-generator'
40
+ import type {Editor} from './use-editor'
41
41
 
42
42
  const debug = debugWithName('component:PortableTextEditor')
43
43
 
@@ -46,58 +46,73 @@ const debug = debugWithName('component:PortableTextEditor')
46
46
  *
47
47
  * @public
48
48
  */
49
- export type PortableTextEditorProps = PropsWithChildren<{
50
- /**
51
- * Function that gets called when the editor changes the value
52
- */
53
- onChange: (change: EditorChange) => void
49
+ export type PortableTextEditorProps<
50
+ TEditor extends Editor | undefined = undefined,
51
+ > = PropsWithChildren<
52
+ (TEditor extends Editor
53
+ ? {
54
+ /**
55
+ * @alpha
56
+ */
57
+ editor: TEditor
58
+ }
59
+ : {
60
+ editor?: undefined
54
61
 
55
- /**
56
- * Schema type for the portable text field
57
- */
58
- schemaType: ArraySchemaType<PortableTextBlock> | ArrayDefinition
62
+ /**
63
+ * Function that gets called when the editor changes the value
64
+ */
65
+ onChange: (change: EditorChange) => void
59
66
 
60
- /**
61
- * Maximum number of blocks to allow within the editor
62
- */
63
- maxBlocks?: number | string
67
+ /**
68
+ * Schema type for the portable text field
69
+ */
70
+ schemaType: ArraySchemaType<PortableTextBlock> | ArrayDefinition
64
71
 
65
- /**
66
- * Whether or not the editor should be in read-only mode
67
- */
68
- readOnly?: boolean
72
+ /**
73
+ * Maximum number of blocks to allow within the editor
74
+ */
75
+ maxBlocks?: number | string
69
76
 
70
- /**
71
- * The current value of the portable text field
72
- */
73
- value?: PortableTextBlock[]
77
+ /**
78
+ * Function used to generate keys for array items (`_key`)
79
+ */
80
+ keyGenerator?: () => string
74
81
 
75
- /**
76
- * Function used to generate keys for array items (`_key`)
77
- */
78
- keyGenerator?: () => string
82
+ /**
83
+ * Observable of local and remote patches for the edited value.
84
+ */
85
+ patches$?: PatchObservable
79
86
 
80
- /**
81
- * Observable of local and remote patches for the edited value.
82
- */
83
- patches$?: PatchObservable
87
+ /**
88
+ * Backward compatibility (renamed to patches$).
89
+ */
90
+ incomingPatches$?: PatchObservable
91
+ }) & {
92
+ /**
93
+ * Whether or not the editor should be in read-only mode
94
+ */
95
+ readOnly?: boolean
84
96
 
85
- /**
86
- * Backward compatibility (renamed to patches$).
87
- */
88
- incomingPatches$?: PatchObservable
97
+ /**
98
+ * The current value of the portable text field
99
+ */
100
+ value?: PortableTextBlock[]
89
101
 
90
- /**
91
- * A ref to the editor instance
92
- */
93
- editorRef?: MutableRefObject<PortableTextEditor | null>
94
- }>
102
+ /**
103
+ * A ref to the editor instance
104
+ */
105
+ editorRef?: MutableRefObject<PortableTextEditor | null>
106
+ }
107
+ >
95
108
 
96
109
  /**
97
110
  * The main Portable Text Editor component.
98
111
  * @public
99
112
  */
100
- export class PortableTextEditor extends Component<PortableTextEditorProps> {
113
+ export class PortableTextEditor extends Component<
114
+ PortableTextEditorProps<Editor | undefined>
115
+ > {
101
116
  public static displayName = 'PortableTextEditor'
102
117
  /**
103
118
  * An observable of all the editor changes.
@@ -116,35 +131,46 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
116
131
  constructor(props: PortableTextEditorProps) {
117
132
  super(props)
118
133
 
119
- if (!props.schemaType) {
120
- throw new Error('PortableTextEditor: missing "schemaType" property')
121
- }
134
+ if (props.editor) {
135
+ this.editorActor = props.editor
136
+ this.editorActor.start()
137
+ this.schemaTypes = this.editorActor.getSnapshot().context.schema
138
+ } else {
139
+ if (!props.schemaType) {
140
+ throw new Error('PortableTextEditor: missing "schemaType" property')
141
+ }
122
142
 
123
- if (props.incomingPatches$) {
124
- console.warn(
125
- `The prop 'incomingPatches$' is deprecated and renamed to 'patches$'`,
126
- )
127
- }
143
+ if (props.incomingPatches$) {
144
+ console.warn(
145
+ `The prop 'incomingPatches$' is deprecated and renamed to 'patches$'`,
146
+ )
147
+ }
128
148
 
129
- this.schemaTypes = getPortableTextMemberSchemaTypes(
130
- props.schemaType.hasOwnProperty('jsonType')
131
- ? props.schemaType
132
- : compileType(props.schemaType),
133
- )
149
+ this.schemaTypes = getPortableTextMemberSchemaTypes(
150
+ props.schemaType.hasOwnProperty('jsonType')
151
+ ? props.schemaType
152
+ : compileType(props.schemaType),
153
+ )
134
154
 
135
- this.editorActor = createActor(editorMachine, {
136
- input: {
137
- behaviors: coreBehaviors,
138
- keyGenerator: props.keyGenerator || defaultKeyGenerator,
139
- schema: this.schemaTypes,
140
- },
141
- })
142
- this.editorActor.start()
155
+ this.editorActor =
156
+ props.editor ??
157
+ createActor(editorMachine, {
158
+ input: {
159
+ keyGenerator: props.keyGenerator || defaultKeyGenerator,
160
+ schema: this.schemaTypes,
161
+ },
162
+ })
163
+ this.editorActor.start()
164
+ }
143
165
  }
144
166
 
145
167
  componentDidUpdate(prevProps: PortableTextEditorProps) {
146
168
  // Set up the schema type lookup table again if the source schema type changes
147
- if (this.props.schemaType !== prevProps.schemaType) {
169
+ if (
170
+ !this.props.editor &&
171
+ !prevProps.editor &&
172
+ this.props.schemaType !== prevProps.schemaType
173
+ ) {
148
174
  this.schemaTypes = getPortableTextMemberSchemaTypes(
149
175
  this.props.schemaType.hasOwnProperty('jsonType')
150
176
  ? this.props.schemaType
@@ -175,22 +201,23 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
175
201
  }
176
202
 
177
203
  render() {
178
- const {value, children, patches$, incomingPatches$} = this.props
179
- const _patches$ = incomingPatches$ || patches$ // Backward compatibility
180
-
181
- const maxBlocks =
182
- typeof this.props.maxBlocks === 'undefined'
204
+ const maxBlocks = !this.props.editor
205
+ ? typeof this.props.maxBlocks === 'undefined'
183
206
  ? undefined
184
207
  : Number.parseInt(this.props.maxBlocks.toString(), 10) || undefined
208
+ : undefined
185
209
 
186
210
  const readOnly = Boolean(this.props.readOnly)
211
+ const legacyPatches = !this.props.editor
212
+ ? (this.props.incomingPatches$ ?? this.props.patches$)
213
+ : undefined
187
214
 
188
215
  return (
189
216
  <>
190
- {_patches$ ? (
217
+ {legacyPatches ? (
191
218
  <RoutePatchesObservableToEditorActor
192
219
  editorActor={this.editorActor}
193
- patches$={_patches$}
220
+ patches$={legacyPatches}
194
221
  />
195
222
  ) : null}
196
223
  <EditorActorContext.Provider value={this.editorActor}>
@@ -209,16 +236,18 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
209
236
  editorActor={this.editorActor}
210
237
  getValue={this.getValue}
211
238
  onChange={(change) => {
212
- this.props.onChange(change)
239
+ if (!this.props.editor) {
240
+ this.props.onChange(change)
241
+ }
213
242
  /**
214
243
  * For backwards compatibility, we relay all changes to the
215
244
  * `change$` Subject as well.
216
245
  */
217
246
  this.change$.next(change)
218
247
  }}
219
- value={value}
248
+ value={this.props.value}
220
249
  />
221
- {children}
250
+ {this.props.children}
222
251
  </PortableTextEditorSelectionProvider>
223
252
  </PortableTextEditorReadOnlyContext.Provider>
224
253
  </PortableTextEditorContext.Provider>
@@ -0,0 +1,203 @@
1
+ import type {PortableTextMemberSchemaTypes} from '../../types/editor'
2
+ import {defineBehavior} from './behavior.types'
3
+ import {
4
+ getFocusSpan,
5
+ getFocusTextBlock,
6
+ selectionIsCollapsed,
7
+ } from './behavior.utils'
8
+
9
+ /**
10
+ * @alpha
11
+ */
12
+ export type MarkdownBehaviorsConfig = {
13
+ mapDefaultStyle: (schema: PortableTextMemberSchemaTypes) => string | undefined
14
+ mapHeadingStyle: (
15
+ schema: PortableTextMemberSchemaTypes,
16
+ level: number,
17
+ ) => string | undefined
18
+ mapBlockquoteStyle: (
19
+ schema: PortableTextMemberSchemaTypes,
20
+ ) => string | undefined
21
+ mapUnorderedListStyle: (
22
+ schema: PortableTextMemberSchemaTypes,
23
+ ) => string | undefined
24
+ mapOrderedListStyle: (
25
+ schema: PortableTextMemberSchemaTypes,
26
+ ) => string | undefined
27
+ }
28
+
29
+ /**
30
+ * @alpha
31
+ */
32
+ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
33
+ const automaticStyleOnSpace = defineBehavior({
34
+ on: 'insert text',
35
+ guard: ({context, event}) => {
36
+ const isSpace = event.text === ' '
37
+
38
+ if (!isSpace) {
39
+ return false
40
+ }
41
+
42
+ const selectionCollapsed = selectionIsCollapsed(context)
43
+ const focusTextBlock = getFocusTextBlock(context)
44
+ const focusSpan = getFocusSpan(context)
45
+
46
+ if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
47
+ return false
48
+ }
49
+
50
+ const looksLikeMarkdownHeading = /^#+/.test(focusSpan.node.text)
51
+ const headingStyle = config.mapHeadingStyle(
52
+ context.schema,
53
+ focusSpan.node.text.length,
54
+ )
55
+
56
+ const looksLikeMarkdownQuote = /^>/.test(focusSpan.node.text)
57
+ const blockquoteStyle = config.mapBlockquoteStyle(context.schema)
58
+
59
+ if (looksLikeMarkdownHeading && headingStyle !== undefined) {
60
+ return {focusTextBlock, focusSpan, style: headingStyle}
61
+ }
62
+
63
+ if (looksLikeMarkdownQuote && blockquoteStyle !== undefined) {
64
+ return {focusTextBlock, focusSpan, style: blockquoteStyle}
65
+ }
66
+
67
+ return false
68
+ },
69
+ actions: [
70
+ () => [
71
+ {
72
+ type: 'insert text',
73
+ text: ' ',
74
+ },
75
+ ],
76
+ (_, {focusTextBlock, focusSpan, style}) => [
77
+ {
78
+ type: 'set block',
79
+ style,
80
+ paths: [focusTextBlock.path],
81
+ },
82
+ {
83
+ type: 'delete',
84
+ selection: {
85
+ anchor: {path: focusSpan.path, offset: 0},
86
+ focus: {
87
+ path: focusSpan.path,
88
+ offset: focusSpan.node.text.length + 1,
89
+ },
90
+ },
91
+ },
92
+ ],
93
+ ],
94
+ })
95
+ const clearStyleOnBackspace = defineBehavior({
96
+ on: 'delete backward',
97
+ guard: ({context}) => {
98
+ const selectionCollapsed = selectionIsCollapsed(context)
99
+ const focusTextBlock = getFocusTextBlock(context)
100
+ const focusSpan = getFocusSpan(context)
101
+
102
+ if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
103
+ return false
104
+ }
105
+
106
+ const defaultStyle = config.mapDefaultStyle(context.schema)
107
+
108
+ if (
109
+ defaultStyle &&
110
+ focusTextBlock.node.children.length === 1 &&
111
+ focusTextBlock.node.style !== config.mapDefaultStyle(context.schema) &&
112
+ focusSpan.node.text === ''
113
+ ) {
114
+ return {defaultStyle, focusTextBlock}
115
+ }
116
+
117
+ return false
118
+ },
119
+ actions: [
120
+ (_, {defaultStyle, focusTextBlock}) => [
121
+ {
122
+ type: 'set block',
123
+ style: defaultStyle,
124
+ paths: [focusTextBlock.path],
125
+ },
126
+ ],
127
+ ],
128
+ })
129
+
130
+ const automaticListOnSpace = defineBehavior({
131
+ on: 'insert text',
132
+ guard: ({context, event}) => {
133
+ const isSpace = event.text === ' '
134
+
135
+ if (!isSpace) {
136
+ return false
137
+ }
138
+
139
+ const selectionCollapsed = selectionIsCollapsed(context)
140
+ const focusTextBlock = getFocusTextBlock(context)
141
+ const focusSpan = getFocusSpan(context)
142
+
143
+ if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
144
+ return false
145
+ }
146
+
147
+ const looksLikeUnorderedList = /^-/.test(focusSpan.node.text)
148
+ const unorderedListStyle = config.mapUnorderedListStyle(context.schema)
149
+
150
+ if (looksLikeUnorderedList && unorderedListStyle !== undefined) {
151
+ return {focusTextBlock, focusSpan, listItem: unorderedListStyle}
152
+ }
153
+
154
+ const looksLikeOrderedList = /^1./.test(focusSpan.node.text)
155
+ const orderedListStyle = config.mapOrderedListStyle(context.schema)
156
+
157
+ if (looksLikeOrderedList && orderedListStyle !== undefined) {
158
+ return {focusTextBlock, focusSpan, listItem: orderedListStyle}
159
+ }
160
+
161
+ return false
162
+ },
163
+ actions: [
164
+ () => [
165
+ {
166
+ type: 'insert text',
167
+ text: ' ',
168
+ },
169
+ ],
170
+ (_, {focusTextBlock, focusSpan, listItem}) => [
171
+ {
172
+ type: 'unset block',
173
+ props: ['style'],
174
+ paths: [focusTextBlock.path],
175
+ },
176
+ {
177
+ type: 'set block',
178
+ listItem,
179
+ level: 1,
180
+ paths: [focusTextBlock.path],
181
+ },
182
+ {
183
+ type: 'delete',
184
+ selection: {
185
+ anchor: {path: focusSpan.path, offset: 0},
186
+ focus: {
187
+ path: focusSpan.path,
188
+ offset: focusSpan.node.text.length + 1,
189
+ },
190
+ },
191
+ },
192
+ ],
193
+ ],
194
+ })
195
+
196
+ const markdownBehaviors = [
197
+ automaticStyleOnSpace,
198
+ clearStyleOnBackspace,
199
+ automaticListOnSpace,
200
+ ]
201
+
202
+ return markdownBehaviors
203
+ }
@@ -21,6 +21,7 @@ import {toPortableTextRange} from '../utils/ranges'
21
21
  import {fromSlateValue} from '../utils/values'
22
22
  import {KEY_TO_VALUE_ELEMENT} from '../utils/weakMaps'
23
23
  import {performAction, performDefaultAction} from './behavior/behavior.actions'
24
+ import {coreBehaviors} from './behavior/behavior.core'
24
25
  import type {
25
26
  Behavior,
26
27
  BehaviorAction,
@@ -91,6 +92,10 @@ type EditorEvent =
91
92
  type: 'update schema'
92
93
  schema: PortableTextMemberSchemaTypes
93
94
  }
95
+ | {
96
+ type: 'update behaviors'
97
+ behaviors: Array<Behavior>
98
+ }
94
99
  | EditorEmittedEvent
95
100
 
96
101
  type EditorEmittedEvent =
@@ -139,12 +144,18 @@ export const editorMachine = setup({
139
144
  events: {} as EditorEvent,
140
145
  emitted: {} as EditorEmittedEvent,
141
146
  input: {} as {
142
- behaviors: Array<Behavior>
147
+ behaviors?: Array<Behavior>
143
148
  keyGenerator: () => string
144
149
  schema: PortableTextMemberSchemaTypes
145
150
  },
146
151
  },
147
152
  actions: {
153
+ 'assign behaviors': assign({
154
+ behaviors: ({event}) => {
155
+ assertEvent(event, 'update behaviors')
156
+ return [...coreBehaviors, ...event.behaviors]
157
+ },
158
+ }),
148
159
  'assign schema': assign({
149
160
  schema: ({event}) => {
150
161
  assertEvent(event, 'update schema')
@@ -263,7 +274,9 @@ export const editorMachine = setup({
263
274
  }).createMachine({
264
275
  id: 'editor',
265
276
  context: ({input}) => ({
266
- behaviors: input.behaviors,
277
+ behaviors: input.behaviors
278
+ ? [...coreBehaviors, ...input.behaviors]
279
+ : coreBehaviors,
267
280
  keyGenerator: input.keyGenerator,
268
281
  pendingEvents: [],
269
282
  schema: input.schema,
@@ -286,6 +299,7 @@ export const editorMachine = setup({
286
299
  'loading': {actions: emit({type: 'loading'})},
287
300
  'patches': {actions: emit(({event}) => event)},
288
301
  'done loading': {actions: emit({type: 'done loading'})},
302
+ 'update behaviors': {actions: 'assign behaviors'},
289
303
  'update schema': {actions: 'assign schema'},
290
304
  'behavior event': {actions: 'handle behavior event'},
291
305
  'behavior action intends': {
@@ -18,8 +18,8 @@ import {
18
18
  Text,
19
19
  Transforms,
20
20
  } from 'slate'
21
+ import type {DOMNode} from 'slate-dom'
21
22
  import {ReactEditor} from 'slate-react'
22
- import type {DOMNode} from 'slate-react/dist/utils/dom'
23
23
  import type {
24
24
  EditableAPI,
25
25
  EditableAPIDeleteOptions,
@@ -0,0 +1,45 @@
1
+ import type {
2
+ ArrayDefinition,
3
+ ArraySchemaType,
4
+ PortableTextBlock,
5
+ } from '@sanity/types'
6
+ import {useActorRef} from '@xstate/react'
7
+ import {getPortableTextMemberSchemaTypes} from '../utils/getPortableTextMemberSchemaTypes'
8
+ import {compileType} from '../utils/schema'
9
+ import type {Behavior} from './behavior/behavior.types'
10
+ import {editorMachine} from './editor-machine'
11
+ import {defaultKeyGenerator} from './key-generator'
12
+
13
+ /**
14
+ * @alpha
15
+ */
16
+ export type EditorConfig = {
17
+ behaviors?: Array<Behavior>
18
+ keyGenerator?: () => string
19
+ schema: ArraySchemaType<PortableTextBlock> | ArrayDefinition
20
+ }
21
+
22
+ /**
23
+ * @alpha
24
+ */
25
+ export type Editor = ReturnType<typeof useEditor>
26
+
27
+ /**
28
+ * @alpha
29
+ */
30
+ export function useEditor(config: EditorConfig) {
31
+ const schema = getPortableTextMemberSchemaTypes(
32
+ config.schema.hasOwnProperty('jsonType')
33
+ ? config.schema
34
+ : compileType(config.schema),
35
+ )
36
+ const editorActor = useActorRef(editorMachine, {
37
+ input: {
38
+ behaviors: config.behaviors,
39
+ keyGenerator: config.keyGenerator ?? defaultKeyGenerator,
40
+ schema,
41
+ },
42
+ })
43
+
44
+ return editorActor
45
+ }
package/src/index.ts CHANGED
@@ -1,13 +1,18 @@
1
1
  export type {Patch} from '@portabletext/patches'
2
- export type {
3
- Behavior,
4
- BehaviorActionIntend,
5
- BehaviorContext,
6
- BehaviorEvent,
7
- BehaviorGuard,
8
- PickFromUnion,
9
- BehaviorActionIntendSet,
2
+ export {
3
+ type Behavior,
4
+ type BehaviorActionIntend,
5
+ type BehaviorContext,
6
+ type BehaviorEvent,
7
+ type BehaviorGuard,
8
+ type PickFromUnion,
9
+ type BehaviorActionIntendSet,
10
+ defineBehavior,
10
11
  } from './editor/behavior/behavior.types'
12
+ export {
13
+ createMarkdownBehaviors,
14
+ type MarkdownBehaviorsConfig,
15
+ } from './editor/behavior/behavior.markdown'
11
16
  export {PortableTextEditable} from './editor/Editable'
12
17
  export type {PortableTextEditableProps} from './editor/Editable'
13
18
  export {
@@ -22,5 +27,6 @@ export {usePortableTextEditorSelection} from './editor/hooks/usePortableTextEdit
22
27
  export {defaultKeyGenerator as keyGenerator} from './editor/key-generator'
23
28
  export {PortableTextEditor} from './editor/PortableTextEditor'
24
29
  export type {PortableTextEditorProps} from './editor/PortableTextEditor'
30
+ export {useEditor, type Editor, type EditorConfig} from './editor/use-editor'
25
31
  export * from './types/editor'
26
32
  export * from './types/options'
@@ -30,8 +30,8 @@ import type {
30
30
  Node as SlateNode,
31
31
  Operation as SlateOperation,
32
32
  } from 'slate'
33
+ import type {DOMNode} from 'slate-dom'
33
34
  import type {ReactEditor} from 'slate-react'
34
- import type {DOMNode} from 'slate-react/dist/utils/dom'
35
35
  import type {PortableTextEditableProps} from '../editor/Editable'
36
36
  import type {PortableTextEditor} from '../editor/PortableTextEditor'
37
37