@portabletext/editor 1.19.0 → 1.21.0

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.
Files changed (132) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +8 -68
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/selector.get-text-before.cjs +11 -39
  4. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  5. package/lib/_chunks-cjs/selector.is-selection-collapsed.cjs.map +1 -1
  6. package/lib/_chunks-cjs/util.get-block-start-point.cjs +30 -0
  7. package/lib/_chunks-cjs/util.get-block-start-point.cjs.map +1 -0
  8. package/lib/_chunks-cjs/util.is-empty-text-block.cjs +71 -0
  9. package/lib/_chunks-cjs/util.is-empty-text-block.cjs.map +1 -0
  10. package/lib/_chunks-cjs/util.is-keyed-segment.cjs +6 -0
  11. package/lib/_chunks-cjs/util.is-keyed-segment.cjs.map +1 -0
  12. package/lib/_chunks-es/behavior.core.js +7 -66
  13. package/lib/_chunks-es/behavior.core.js.map +1 -1
  14. package/lib/_chunks-es/selector.get-text-before.js +5 -31
  15. package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
  16. package/lib/_chunks-es/selector.is-selection-collapsed.js.map +1 -1
  17. package/lib/_chunks-es/util.get-block-start-point.js +31 -0
  18. package/lib/_chunks-es/util.get-block-start-point.js.map +1 -0
  19. package/lib/_chunks-es/util.is-empty-text-block.js +73 -0
  20. package/lib/_chunks-es/util.is-empty-text-block.js.map +1 -0
  21. package/lib/_chunks-es/util.is-keyed-segment.js +7 -0
  22. package/lib/_chunks-es/util.is-keyed-segment.js.map +1 -0
  23. package/lib/behaviors/index.cjs +7 -7
  24. package/lib/behaviors/index.cjs.map +1 -1
  25. package/lib/behaviors/index.d.cts +179 -119
  26. package/lib/behaviors/index.d.ts +179 -119
  27. package/lib/behaviors/index.js +3 -2
  28. package/lib/behaviors/index.js.map +1 -1
  29. package/lib/index.cjs +72 -177
  30. package/lib/index.cjs.map +1 -1
  31. package/lib/index.d.cts +1061 -140
  32. package/lib/index.d.ts +1061 -140
  33. package/lib/index.js +72 -177
  34. package/lib/index.js.map +1 -1
  35. package/lib/selectors/index.cjs +73 -1
  36. package/lib/selectors/index.cjs.map +1 -1
  37. package/lib/selectors/index.d.cts +14 -0
  38. package/lib/selectors/index.d.ts +14 -0
  39. package/lib/selectors/index.js +73 -0
  40. package/lib/selectors/index.js.map +1 -1
  41. package/lib/utils/index.cjs +11 -0
  42. package/lib/utils/index.cjs.map +1 -0
  43. package/lib/utils/index.d.cts +87 -0
  44. package/lib/utils/index.d.ts +87 -0
  45. package/lib/utils/index.js +13 -0
  46. package/lib/utils/index.js.map +1 -0
  47. package/package.json +18 -14
  48. package/src/behavior-actions/behavior.action-utils.insert-block.ts +1 -1
  49. package/src/behavior-actions/behavior.action.insert-block-object.ts +1 -1
  50. package/src/behavior-actions/behavior.action.insert-inline-object.ts +1 -1
  51. package/src/behavior-actions/behavior.action.text-block.set.ts +1 -1
  52. package/src/behavior-actions/behavior.action.text-block.unset.ts +1 -1
  53. package/src/behavior-actions/behavior.actions.ts +5 -5
  54. package/src/behaviors/behavior.code-editor.ts +1 -1
  55. package/src/behaviors/behavior.core.block-objects.ts +2 -2
  56. package/src/behaviors/behavior.core.decorators.ts +1 -1
  57. package/src/behaviors/behavior.core.lists.ts +2 -2
  58. package/src/behaviors/behavior.emoji-picker.ts +1 -1
  59. package/src/behaviors/behavior.links.ts +1 -1
  60. package/src/behaviors/behavior.markdown.ts +2 -2
  61. package/src/behaviors/behavior.types.ts +52 -19
  62. package/src/behaviors/index.ts +1 -0
  63. package/src/editor/Editable.tsx +12 -12
  64. package/src/editor/PortableTextEditor.tsx +2 -2
  65. package/src/editor/components/DraggableBlock.tsx +2 -2
  66. package/src/editor/components/Element.tsx +20 -26
  67. package/src/editor/components/Leaf.tsx +1 -1
  68. package/src/editor/components/Synchronizer.tsx +1 -1
  69. package/src/editor/create-editor.ts +39 -20
  70. package/src/editor/create-slate-editor.tsx +5 -2
  71. package/src/editor/editor-machine.ts +72 -18
  72. package/src/editor/get-value.ts +2 -2
  73. package/src/editor/hooks/usePortableTextEditorSelection.tsx +1 -1
  74. package/src/editor/mutation-machine.ts +2 -2
  75. package/src/editor/nodes/DefaultObject.tsx +2 -2
  76. package/src/editor/plugins/create-with-event-listeners.ts +11 -3
  77. package/src/editor/plugins/createWithEditableAPI.ts +7 -7
  78. package/src/editor/plugins/createWithHotKeys.ts +2 -2
  79. package/src/editor/plugins/createWithInsertData.ts +7 -7
  80. package/src/editor/plugins/createWithMaxBlocks.ts +2 -2
  81. package/src/editor/plugins/createWithObjectKeys.ts +2 -2
  82. package/src/editor/plugins/createWithPatches.ts +10 -10
  83. package/src/editor/plugins/createWithPlaceholderBlock.ts +3 -3
  84. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +1 -1
  85. package/src/editor/plugins/createWithPortableTextMarkModel.ts +4 -4
  86. package/src/editor/plugins/createWithPortableTextSelections.ts +6 -6
  87. package/src/editor/plugins/createWithSchemaTypes.ts +1 -1
  88. package/src/editor/plugins/createWithUndoRedo.ts +5 -5
  89. package/src/editor/plugins/createWithUtils.ts +2 -2
  90. package/src/editor/plugins/with-plugins.ts +1 -1
  91. package/src/editor/sync-machine.ts +8 -5
  92. package/src/index.ts +5 -1
  93. package/src/selectors/index.ts +2 -0
  94. package/src/selectors/selector.get-selection-text.test.ts +75 -0
  95. package/src/selectors/selector.get-selection-text.ts +3 -3
  96. package/src/selectors/selector.get-text-before.ts +7 -4
  97. package/src/selectors/selector.is-point-after-selection.ts +82 -0
  98. package/src/selectors/selector.is-point-before-selection.ts +82 -0
  99. package/src/utils/_exports/index.ts +1 -0
  100. package/src/utils/index.ts +11 -0
  101. package/src/{editor/utils/utils.block-offset.test.ts → utils/util.block-offset.test.ts} +1 -1
  102. package/src/{editor/utils/utils.block-offset.ts → utils/util.block-offset.ts} +23 -7
  103. package/src/{editor/utils/utils.get-start-point.ts → utils/util.get-block-start-point.ts} +5 -2
  104. package/src/utils/util.get-text-block-text.ts +8 -0
  105. package/src/{editor/utils/utils.ts → utils/util.is-empty-text-block.ts} +4 -5
  106. package/src/{editor/utils/utils.is-keyed-segment.ts → utils/util.is-keyed-segment.ts} +3 -0
  107. package/src/{editor/utils/utils.reverse-selection.ts → utils/util.reverse-selection.ts} +4 -1
  108. package/src/editor/nodes/index.ts +0 -189
  109. /package/src/{utils → internal-utils}/__tests__/dmpToOperations.test.ts +0 -0
  110. /package/src/{utils → internal-utils}/__tests__/operationToPatches.test.ts +0 -0
  111. /package/src/{utils → internal-utils}/__tests__/patchToOperations.test.ts +0 -0
  112. /package/src/{utils → internal-utils}/__tests__/ranges.test.ts +0 -0
  113. /package/src/{utils → internal-utils}/__tests__/valueNormalization.test.tsx +0 -0
  114. /package/src/{utils → internal-utils}/__tests__/values.test.ts +0 -0
  115. /package/src/{utils → internal-utils}/applyPatch.ts +0 -0
  116. /package/src/{utils → internal-utils}/debug.ts +0 -0
  117. /package/src/{utils → internal-utils}/is-hotkey.test.ts +0 -0
  118. /package/src/{utils → internal-utils}/is-hotkey.ts +0 -0
  119. /package/src/{utils → internal-utils}/looks-like-url.test.ts +0 -0
  120. /package/src/{utils → internal-utils}/looks-like-url.ts +0 -0
  121. /package/src/{utils → internal-utils}/operationToPatches.ts +0 -0
  122. /package/src/{utils → internal-utils}/paths.ts +0 -0
  123. /package/src/{utils → internal-utils}/ranges.ts +0 -0
  124. /package/src/{utils → internal-utils}/schema.ts +0 -0
  125. /package/src/{utils → internal-utils}/selection.ts +0 -0
  126. /package/src/{utils → internal-utils}/sibling-utils.ts +0 -0
  127. /package/src/{utils → internal-utils}/validateValue.ts +0 -0
  128. /package/src/{utils → internal-utils}/values.ts +0 -0
  129. /package/src/{utils → internal-utils}/weakMaps.ts +0 -0
  130. /package/src/{utils → internal-utils}/withChanges.ts +0 -0
  131. /package/src/{utils → internal-utils}/withUndoRedo.ts +0 -0
  132. /package/src/{utils → internal-utils}/withoutPatching.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.19.0",
3
+ "version": "1.21.0",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -45,6 +45,12 @@
45
45
  "require": "./lib/selectors/index.cjs",
46
46
  "default": "./lib/selectors/index.js"
47
47
  },
48
+ "./utils": {
49
+ "source": "./src/utils/_exports/index.ts",
50
+ "import": "./lib/utils/index.js",
51
+ "require": "./lib/utils/index.cjs",
52
+ "default": "./lib/utils/index.js"
53
+ },
48
54
  "./package.json": "./package.json"
49
55
  },
50
56
  "main": "./lib/index.cjs",
@@ -70,11 +76,11 @@
70
76
  },
71
77
  "devDependencies": {
72
78
  "@portabletext/toolkit": "^2.0.16",
73
- "@sanity/block-tools": "^3.68.3",
79
+ "@sanity/block-tools": "^3.69.0",
74
80
  "@sanity/diff-match-patch": "^3.1.2",
75
- "@sanity/pkg-utils": "^6.12.3",
76
- "@sanity/schema": "^3.68.3",
77
- "@sanity/types": "^3.68.3",
81
+ "@sanity/pkg-utils": "^7.0.1",
82
+ "@sanity/schema": "^3.69.0",
83
+ "@sanity/types": "^3.69.0",
78
84
  "@testing-library/jest-dom": "^6.6.3",
79
85
  "@testing-library/react": "^16.1.0",
80
86
  "@types/debug": "^4.1.5",
@@ -87,28 +93,26 @@
87
93
  "@vitejs/plugin-react": "^4.3.4",
88
94
  "@vitest/browser": "^2.1.8",
89
95
  "@vitest/coverage-istanbul": "^2.1.8",
90
- "babel-plugin-react-compiler": "19.0.0-beta-55955c9-20241229",
96
+ "babel-plugin-react-compiler": "19.0.0-beta-63e3235-20250105",
91
97
  "eslint": "8.57.1",
92
- "eslint-plugin-react-compiler": "19.0.0-beta-55955c9-20241229",
98
+ "eslint-plugin-react-compiler": "19.0.0-beta-63e3235-20250105",
93
99
  "eslint-plugin-react-hooks": "^5.1.0",
94
100
  "jsdom": "^25.0.1",
95
101
  "react": "^19.0.0",
96
102
  "react-dom": "^19.0.0",
97
103
  "rxjs": "^7.8.1",
98
- "styled-components": "^6.1.13",
99
- "typescript": "5.7.2",
104
+ "typescript": "5.7.3",
100
105
  "vite": "^6.0.4",
101
106
  "vitest": "^2.1.8",
102
107
  "vitest-browser-react": "^0.0.4",
103
108
  "racejar": "1.1.1"
104
109
  },
105
110
  "peerDependencies": {
106
- "@sanity/block-tools": "^3.68.3",
107
- "@sanity/schema": "^3.68.3",
108
- "@sanity/types": "^3.68.3",
111
+ "@sanity/block-tools": "^3.69.0",
112
+ "@sanity/schema": "^3.69.0",
113
+ "@sanity/types": "^3.69.0",
109
114
  "react": "^16.9 || ^17 || ^18 || ^19",
110
- "rxjs": "^7.8.1",
111
- "styled-components": "^6.1.13"
115
+ "rxjs": "^7.8.1"
112
116
  },
113
117
  "engines": {
114
118
  "node": ">=18"
@@ -1,7 +1,7 @@
1
1
  import {Editor, Transforms, type Descendant} from 'slate'
2
2
  import type {EditorSchema} from '../editor/define-schema'
3
+ import {isEqualToEmptyEditor} from '../internal-utils/values'
3
4
  import type {PortableTextSlateEditor} from '../types/editor'
4
- import {isEqualToEmptyEditor} from '../utils/values'
5
5
 
6
6
  export function insertBlock({
7
7
  block,
@@ -1,4 +1,4 @@
1
- import {toSlateValue} from '../utils/values'
1
+ import {toSlateValue} from '../internal-utils/values'
2
2
  import {insertBlock} from './behavior.action-utils.insert-block'
3
3
  import type {BehaviorActionImplementation} from './behavior.actions'
4
4
 
@@ -1,5 +1,5 @@
1
1
  import {Editor, Transforms, type Element} from 'slate'
2
- import {toSlateValue} from '../utils/values'
2
+ import {toSlateValue} from '../internal-utils/values'
3
3
  import type {BehaviorActionImplementation} from './behavior.actions'
4
4
 
5
5
  export const insertInlineObjectActionImplementation: BehaviorActionImplementation<
@@ -1,5 +1,5 @@
1
1
  import {Transforms} from 'slate'
2
- import {toSlateRange} from '../utils/ranges'
2
+ import {toSlateRange} from '../internal-utils/ranges'
3
3
  import type {BehaviorActionImplementation} from './behavior.actions'
4
4
 
5
5
  export const textBlockSetActionImplementation: BehaviorActionImplementation<
@@ -1,5 +1,5 @@
1
1
  import {Transforms} from 'slate'
2
- import {toSlateRange} from '../utils/ranges'
2
+ import {toSlateRange} from '../internal-utils/ranges'
3
3
  import type {BehaviorActionImplementation} from './behavior.actions'
4
4
 
5
5
  export const textBlockUnsetActionImplementation: BehaviorActionImplementation<
@@ -21,12 +21,12 @@ import {
21
21
  removeDecoratorActionImplementation,
22
22
  toggleDecoratorActionImplementation,
23
23
  } from '../editor/plugins/createWithPortableTextMarkModel'
24
- import {blockOffsetToSpanSelectionPoint} from '../editor/utils/utils.block-offset'
24
+ import {toSlatePath} from '../internal-utils/paths'
25
+ import {toSlateRange} from '../internal-utils/ranges'
26
+ import {fromSlateValue, toSlateValue} from '../internal-utils/values'
27
+ import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
25
28
  import type {PickFromUnion} from '../type-utils'
26
- import {toSlatePath} from '../utils/paths'
27
- import {toSlateRange} from '../utils/ranges'
28
- import {fromSlateValue, toSlateValue} from '../utils/values'
29
- import {KEY_TO_VALUE_ELEMENT} from '../utils/weakMaps'
29
+ import {blockOffsetToSpanSelectionPoint} from '../utils/util.block-offset'
30
30
  import {insertBlock} from './behavior.action-utils.insert-block'
31
31
  import {insertBlockObjectActionImplementation} from './behavior.action.insert-block-object'
32
32
  import {
@@ -1,5 +1,5 @@
1
+ import {isHotkey} from '../internal-utils/is-hotkey'
1
2
  import * as selectors from '../selectors'
2
- import {isHotkey} from '../utils/is-hotkey'
3
3
  import {defineBehavior} from './behavior.types'
4
4
 
5
5
  /**
@@ -1,7 +1,7 @@
1
1
  import {isPortableTextTextBlock} from '@sanity/types'
2
- import {isEmptyTextBlock} from '../editor/utils/utils'
2
+ import {isHotkey} from '../internal-utils/is-hotkey'
3
3
  import * as selectors from '../selectors'
4
- import {isHotkey} from '../utils/is-hotkey'
4
+ import {isEmptyTextBlock} from '../utils/util.is-empty-text-block'
5
5
  import {defineBehavior} from './behavior.types'
6
6
 
7
7
  const arrowDownOnLonelyBlockObject = defineBehavior({
@@ -1,4 +1,4 @@
1
- import {isHotkey} from '../utils/is-hotkey'
1
+ import {isHotkey} from '../internal-utils/is-hotkey'
2
2
  import {defineBehavior, raise} from './behavior.types'
3
3
 
4
4
  export const coreDecoratorBehaviors = {
@@ -1,7 +1,7 @@
1
1
  import {createGuards} from '../behavior-actions/behavior.guards'
2
- import {isEmptyTextBlock} from '../editor/utils/utils'
2
+ import {isHotkey} from '../internal-utils/is-hotkey'
3
3
  import * as selectors from '../selectors'
4
- import {isHotkey} from '../utils/is-hotkey'
4
+ import {isEmptyTextBlock} from '../utils/util.is-empty-text-block'
5
5
  import {defineBehavior} from './behavior.types'
6
6
 
7
7
  const MAX_LIST_LEVEL = 10
@@ -1,6 +1,6 @@
1
1
  import {assertEvent, assign, createActor, setup} from 'xstate'
2
+ import {isHotkey} from '../internal-utils/is-hotkey'
2
3
  import * as selectors from '../selectors'
3
- import {isHotkey} from '../utils/is-hotkey'
4
4
  import {defineBehavior} from './behavior.types'
5
5
 
6
6
  const emojiCharRegEx = /^[a-zA-Z-_0-9]{1}$/
@@ -1,6 +1,6 @@
1
1
  import type {EditorSchema} from '../editor/define-schema'
2
+ import {looksLikeUrl} from '../internal-utils/looks-like-url'
2
3
  import * as selectors from '../selectors'
3
- import {looksLikeUrl} from '../utils/looks-like-url'
4
4
  import {defineBehavior} from './behavior.types'
5
5
 
6
6
  /**
@@ -1,9 +1,9 @@
1
1
  import {isPortableTextTextBlock} from '@sanity/types'
2
2
  import type {EditorSchema} from '../editor/define-schema'
3
- import {getTextBlockText} from '../editor/utils/utils'
4
- import {spanSelectionPointToBlockOffset} from '../editor/utils/utils.block-offset'
5
3
  import * as selectors from '../selectors'
6
4
  import {getBlockTextBefore} from '../selectors/selector.get-text-before'
5
+ import {spanSelectionPointToBlockOffset} from '../utils/util.block-offset'
6
+ import {getTextBlockText} from '../utils/util.get-text-block-text'
7
7
  import {defineBehavior} from './behavior.types'
8
8
 
9
9
  /**
@@ -106,6 +106,23 @@ export type NativeBehaviorEvent =
106
106
  data: DataTransfer
107
107
  }
108
108
 
109
+ /**
110
+ * @beta
111
+ */
112
+ export type CustomBehaviorEvent<
113
+ TPayload extends Record<string, unknown> = Record<string, unknown>,
114
+ TType extends string = string,
115
+ TInternalType extends `custom.${TType}` = `custom.${TType}`,
116
+ > = {
117
+ type: TInternalType
118
+ } & TPayload
119
+
120
+ export function isCustomBehaviorEvent(
121
+ event: BehaviorEvent,
122
+ ): event is CustomBehaviorEvent {
123
+ return event.type.startsWith('custom.')
124
+ }
125
+
109
126
  /**
110
127
  * @beta
111
128
  */
@@ -113,7 +130,7 @@ export type BehaviorActionIntend =
113
130
  | SyntheticBehaviorEvent
114
131
  | {
115
132
  type: 'raise'
116
- event: SyntheticBehaviorEvent
133
+ event: SyntheticBehaviorEvent | CustomBehaviorEvent
117
134
  }
118
135
  | {
119
136
  type: 'annotation.toggle'
@@ -225,7 +242,7 @@ export type BehaviorAction = OmitFromUnion<
225
242
  * @beta
226
243
  */
227
244
  export function raise(
228
- event: SyntheticBehaviorEvent,
245
+ event: SyntheticBehaviorEvent | CustomBehaviorEvent,
229
246
  ): PickFromUnion<BehaviorActionIntend, 'type', 'raise'> {
230
247
  return {type: 'raise', event}
231
248
  }
@@ -233,7 +250,10 @@ export function raise(
233
250
  /**
234
251
  * @beta
235
252
  */
236
- export type BehaviorEvent = SyntheticBehaviorEvent | NativeBehaviorEvent
253
+ export type BehaviorEvent =
254
+ | SyntheticBehaviorEvent
255
+ | NativeBehaviorEvent
256
+ | CustomBehaviorEvent
237
257
 
238
258
  /**
239
259
  * @beta
@@ -241,6 +261,7 @@ export type BehaviorEvent = SyntheticBehaviorEvent | NativeBehaviorEvent
241
261
  export type Behavior<
242
262
  TBehaviorEventType extends BehaviorEvent['type'] = BehaviorEvent['type'],
243
263
  TGuardResponse = true,
264
+ TBehaviorEvent extends BehaviorEvent = BehaviorEvent,
244
265
  > = {
245
266
  /**
246
267
  * The internal editor event that triggers this behavior.
@@ -251,23 +272,17 @@ export type Behavior<
251
272
  * Returning a non-nullable value from the guard will pass the value to the
252
273
  * actions and execute them.
253
274
  */
254
- guard?: BehaviorGuard<
255
- PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>,
256
- TGuardResponse
257
- >
275
+ guard?: BehaviorGuard<TBehaviorEvent, TGuardResponse>
258
276
  /**
259
277
  * Array of behavior action sets.
260
278
  */
261
- actions: Array<BehaviorActionIntendSet<TBehaviorEventType, TGuardResponse>>
279
+ actions: Array<BehaviorActionIntendSet<TBehaviorEvent, TGuardResponse>>
262
280
  }
263
281
 
264
282
  /**
265
283
  * @beta
266
284
  */
267
- export type BehaviorGuard<
268
- TBehaviorEvent extends BehaviorEvent,
269
- TGuardResponse,
270
- > = ({
285
+ export type BehaviorGuard<TBehaviorEvent, TGuardResponse> = ({
271
286
  context,
272
287
  event,
273
288
  }: {
@@ -278,16 +293,13 @@ export type BehaviorGuard<
278
293
  /**
279
294
  * @beta
280
295
  */
281
- export type BehaviorActionIntendSet<
282
- TBehaviorEventType extends BehaviorEvent['type'] = BehaviorEvent['type'],
283
- TGuardResponse = true,
284
- > = (
296
+ export type BehaviorActionIntendSet<TBehaviorEvent, TGuardResponse> = (
285
297
  {
286
298
  context,
287
299
  event,
288
300
  }: {
289
301
  context: EditorContext
290
- event: PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>
302
+ event: TBehaviorEvent
291
303
  },
292
304
  guardResponse: TGuardResponse,
293
305
  ) => Array<BehaviorActionIntend>
@@ -296,9 +308,30 @@ export type BehaviorActionIntendSet<
296
308
  * @beta
297
309
  */
298
310
  export function defineBehavior<
299
- TAnyBehaviorEventType extends BehaviorEvent['type'],
311
+ TPayload extends Record<string, unknown>,
312
+ TBehaviorEventType extends
313
+ BehaviorEvent['type'] = CustomBehaviorEvent['type'],
314
+ TGuardResponse = true,
315
+ >(
316
+ behavior: Behavior<
317
+ TBehaviorEventType,
318
+ TGuardResponse,
319
+ TBehaviorEventType extends `custom.${infer TType}`
320
+ ? CustomBehaviorEvent<TPayload, TType>
321
+ : PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>
322
+ >,
323
+ ): Behavior
324
+ export function defineBehavior<
325
+ TPayload extends never = never,
326
+ TBehaviorEventType extends BehaviorEvent['type'] = BehaviorEvent['type'],
300
327
  TGuardResponse = true,
301
- >(behavior: Behavior<TAnyBehaviorEventType, TGuardResponse>): Behavior {
328
+ TBehaviorEvent extends
329
+ BehaviorEvent = TBehaviorEventType extends `custom.${infer TType}`
330
+ ? CustomBehaviorEvent<TPayload, TType>
331
+ : PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>,
332
+ >(
333
+ behavior: Behavior<TBehaviorEventType, TGuardResponse, TBehaviorEvent>,
334
+ ): Behavior {
302
335
  return behavior as unknown as Behavior
303
336
  }
304
337
 
@@ -29,6 +29,7 @@ export {
29
29
  type BehaviorEvent,
30
30
  type BehaviorGuard,
31
31
  type BlockOffset,
32
+ type CustomBehaviorEvent,
32
33
  type NativeBehaviorEvent,
33
34
  type SyntheticBehaviorEvent,
34
35
  } from './behavior.types'
@@ -35,6 +35,18 @@ import {
35
35
  type RenderElementProps,
36
36
  type RenderLeafProps,
37
37
  } from 'slate-react'
38
+ import {debugWithName} from '../internal-utils/debug'
39
+ import {
40
+ moveRangeByOperation,
41
+ toPortableTextRange,
42
+ toSlateRange,
43
+ } from '../internal-utils/ranges'
44
+ import {normalizeSelection} from '../internal-utils/selection'
45
+ import {
46
+ fromSlateValue,
47
+ isEqualToEmptyEditor,
48
+ toSlateValue,
49
+ } from '../internal-utils/values'
38
50
  import type {
39
51
  EditorSelection,
40
52
  OnCopyFn,
@@ -51,18 +63,6 @@ import type {
51
63
  } from '../types/editor'
52
64
  import type {HotkeyOptions} from '../types/options'
53
65
  import type {SlateTextBlock, VoidElement} from '../types/slate'
54
- import {debugWithName} from '../utils/debug'
55
- import {
56
- moveRangeByOperation,
57
- toPortableTextRange,
58
- toSlateRange,
59
- } from '../utils/ranges'
60
- import {normalizeSelection} from '../utils/selection'
61
- import {
62
- fromSlateValue,
63
- isEqualToEmptyEditor,
64
- toSlateValue,
65
- } from '../utils/values'
66
66
  import {Element} from './components/Element'
67
67
  import {Leaf} from './components/Leaf'
68
68
  import {EditorActorContext} from './editor-actor-context'
@@ -15,6 +15,8 @@ import {
15
15
  import {Subject} from 'rxjs'
16
16
  import {Slate} from 'slate-react'
17
17
  import {useEffectEvent} from 'use-effect-event'
18
+ import {debugWithName} from '../internal-utils/debug'
19
+ import {compileType} from '../internal-utils/schema'
18
20
  import type {
19
21
  EditableAPI,
20
22
  EditableAPIDeleteOptions,
@@ -24,8 +26,6 @@ import type {
24
26
  PatchObservable,
25
27
  PortableTextMemberSchemaTypes,
26
28
  } from '../types/editor'
27
- import {debugWithName} from '../utils/debug'
28
- import {compileType} from '../utils/schema'
29
29
  import {Synchronizer} from './components/Synchronizer'
30
30
  import {createEditor, type Editor} from './create-editor'
31
31
  import {createEditorSchema} from './create-editor-schema'
@@ -10,13 +10,13 @@ import {
10
10
  } from 'react'
11
11
  import {Editor, Path, Transforms, type Element as SlateElement} from 'slate'
12
12
  import {ReactEditor, useSlateStatic} from 'slate-react'
13
- import {debugWithName} from '../../utils/debug'
13
+ import {debugWithName} from '../../internal-utils/debug'
14
14
  import {
15
15
  IS_DRAGGING,
16
16
  IS_DRAGGING_BLOCK_ELEMENT,
17
17
  IS_DRAGGING_BLOCK_TARGET_POSITION,
18
18
  IS_DRAGGING_ELEMENT_TARGET,
19
- } from '../../utils/weakMaps'
19
+ } from '../../internal-utils/weakMaps'
20
20
 
21
21
  const debug = debugWithName('components:DraggableBlock')
22
22
  const debugRenders = false
@@ -18,6 +18,9 @@ import {
18
18
  useSlateStatic,
19
19
  type RenderElementProps,
20
20
  } from 'slate-react'
21
+ import {debugWithName} from '../../internal-utils/debug'
22
+ import {fromSlateValue} from '../../internal-utils/values'
23
+ import {KEY_TO_VALUE_ELEMENT} from '../../internal-utils/weakMaps'
21
24
  import type {
22
25
  BlockRenderProps,
23
26
  PortableTextMemberSchemaTypes,
@@ -26,15 +29,7 @@ import type {
26
29
  RenderListItemFunction,
27
30
  RenderStyleFunction,
28
31
  } from '../../types/editor'
29
- import {debugWithName} from '../../utils/debug'
30
- import {fromSlateValue} from '../../utils/values'
31
- import {KEY_TO_VALUE_ELEMENT} from '../../utils/weakMaps'
32
32
  import ObjectNode from '../nodes/DefaultObject'
33
- import {
34
- DefaultBlockObject,
35
- DefaultListItem,
36
- DefaultListItemInner,
37
- } from '../nodes/index'
38
33
  import {DraggableBlock} from './DraggableBlock'
39
34
 
40
35
  const debug = debugWithName('components:Element')
@@ -185,12 +180,14 @@ export const Element: FunctionComponent<ElementProps> = ({
185
180
  })
186
181
  }
187
182
  let level: number | undefined
183
+
188
184
  if (isListItem) {
189
185
  if (typeof element.level === 'number') {
190
186
  level = element.level
191
187
  }
192
188
  className += ` pt-list-item pt-list-item-${element.listItem} pt-list-item-level-${level || 1}`
193
189
  }
190
+
194
191
  if (editor.isListBlock(value) && isListItem && element.listItem) {
195
192
  const listType = schemaTypes.lists.find(
196
193
  (item) => item.value === element.listItem,
@@ -207,17 +204,9 @@ export const Element: FunctionComponent<ElementProps> = ({
207
204
  level: value.level || 1,
208
205
  editorElementRef: blockRef,
209
206
  })
210
- } else {
211
- renderedBlock = (
212
- <DefaultListItem
213
- listStyle={value.listItem || schemaTypes.lists[0].value}
214
- listLevel={value.level || 1}
215
- >
216
- <DefaultListItemInner>{renderedBlock}</DefaultListItemInner>
217
- </DefaultListItem>
218
- )
219
207
  }
220
208
  }
209
+
221
210
  const renderProps: Omit<BlockRenderProps, 'type'> = Object.defineProperty(
222
211
  {
223
212
  children: renderedBlock,
@@ -263,24 +252,31 @@ export const Element: FunctionComponent<ElementProps> = ({
263
252
  </div>
264
253
  )
265
254
  }
255
+
266
256
  const schemaType = schemaTypes.blockObjects.find(
267
257
  (_type) => _type.name === element._type,
268
258
  )
259
+
269
260
  if (!schemaType) {
270
261
  throw new Error(
271
262
  `Could not find schema type for block element of _type ${element._type}`,
272
263
  )
273
264
  }
265
+
274
266
  if (debugRenders) {
275
267
  debug(`Render ${element._key} (object block)`)
276
268
  }
269
+
277
270
  className = 'pt-block pt-object-block'
271
+
278
272
  const block = fromSlateValue(
279
273
  [element],
280
274
  schemaTypes.block.name,
281
275
  KEY_TO_VALUE_ELEMENT.get(editor),
282
276
  )[0]
277
+
283
278
  let renderedBlockFromProps: JSX.Element | undefined
279
+
284
280
  if (renderBlock) {
285
281
  const _props: Omit<BlockRenderProps, 'type'> = Object.defineProperty(
286
282
  {
@@ -305,20 +301,18 @@ export const Element: FunctionComponent<ElementProps> = ({
305
301
  )
306
302
  renderedBlockFromProps = renderBlock(_props as BlockRenderProps)
307
303
  }
304
+
308
305
  return (
309
306
  <div key={element._key} {...attributes} className={className}>
310
307
  {children}
311
308
  <DraggableBlock element={element} readOnly={readOnly} blockRef={blockRef}>
312
- {renderedBlockFromProps && (
313
- <div ref={blockRef} contentEditable={false}>
314
- {renderedBlockFromProps}
315
- </div>
316
- )}
317
- {!renderedBlockFromProps && (
318
- <DefaultBlockObject selected={selected}>
309
+ <div ref={blockRef} contentEditable={false}>
310
+ {renderedBlockFromProps ? (
311
+ renderedBlockFromProps
312
+ ) : (
319
313
  <ObjectNode value={value} />
320
- </DefaultBlockObject>
321
- )}
314
+ )}
315
+ </div>
322
316
  </DraggableBlock>
323
317
  </div>
324
318
  )
@@ -15,6 +15,7 @@ import {
15
15
  } from 'react'
16
16
  import {Text} from 'slate'
17
17
  import {useSelected, type RenderLeafProps} from 'slate-react'
18
+ import {debugWithName} from '../../internal-utils/debug'
18
19
  import type {
19
20
  BlockAnnotationRenderProps,
20
21
  BlockChildRenderProps,
@@ -24,7 +25,6 @@ import type {
24
25
  RenderChildFunction,
25
26
  RenderDecoratorFunction,
26
27
  } from '../../types/editor'
27
- import {debugWithName} from '../../utils/debug'
28
28
  import type {EditorActor} from '../editor-machine'
29
29
  import {usePortableTextEditor} from '../hooks/usePortableTextEditor'
30
30
  import {DefaultAnnotation} from '../nodes/DefaultAnnotation'
@@ -1,7 +1,7 @@
1
1
  import {useActorRef, useSelector} from '@xstate/react'
2
2
  import {useEffect} from 'react'
3
+ import {debugWithName} from '../../internal-utils/debug'
3
4
  import type {PortableTextSlateEditor} from '../../types/editor'
4
- import {debugWithName} from '../../utils/debug'
5
5
  import type {EditorActor} from '../editor-machine'
6
6
  import {mutationMachine} from '../mutation-machine'
7
7
  import {syncMachine} from '../sync-machine'
@@ -11,10 +11,10 @@ import {
11
11
  type EventObject,
12
12
  type Snapshot,
13
13
  } from 'xstate'
14
- import type {Behavior} from '../behaviors/behavior.types'
14
+ import type {Behavior, CustomBehaviorEvent} from '../behaviors/behavior.types'
15
+ import {compileType} from '../internal-utils/schema'
15
16
  import type {PickFromUnion} from '../type-utils'
16
17
  import type {EditableAPI} from '../types/editor'
17
- import {compileType} from '../utils/schema'
18
18
  import {createEditorSchema} from './create-editor-schema'
19
19
  import {createSlateEditor, type SlateEditor} from './create-slate-editor'
20
20
  import {compileSchemaDefinition, type SchemaDefinition} from './define-schema'
@@ -58,30 +58,36 @@ export type EditorConfig = {
58
58
  /**
59
59
  * @public
60
60
  */
61
- export type EditorEvent = PickFromUnion<
62
- InternalEditorEvent,
63
- 'type',
64
- | 'annotation.add'
65
- | 'annotation.remove'
66
- | 'blur'
67
- | 'decorator.toggle'
68
- | 'focus'
69
- | 'insert.block object'
70
- | 'insert.inline object'
71
- | 'list item.toggle'
72
- | 'select'
73
- | 'style.toggle'
74
- | 'patches'
75
- | 'update behaviors'
76
- | 'update readOnly'
77
- | 'update value'
78
- >
61
+ export type EditorEvent =
62
+ | PickFromUnion<
63
+ InternalEditorEvent,
64
+ 'type',
65
+ | 'annotation.add'
66
+ | 'annotation.remove'
67
+ | 'blur'
68
+ | 'decorator.toggle'
69
+ | 'focus'
70
+ | 'insert.block object'
71
+ | 'insert.inline object'
72
+ | 'list item.toggle'
73
+ | 'select'
74
+ | 'style.toggle'
75
+ | 'patches'
76
+ | 'update behaviors'
77
+ | 'update readOnly'
78
+ | 'update value'
79
+ >
80
+ | CustomBehaviorEvent
79
81
 
80
82
  /**
81
83
  * @public
82
84
  */
83
85
  export type Editor = {
84
86
  getSnapshot: () => EditorSnapshot
87
+ /**
88
+ * @beta
89
+ */
90
+ registerBehavior: (config: {behavior: Behavior}) => () => void
85
91
  send: (event: EditorEvent) => void
86
92
  on: ActorRef<Snapshot<unknown>, EventObject, EditorEmittedEvent>['on']
87
93
  _internal: {
@@ -135,6 +141,19 @@ function createEditorFromActor(editorActor: EditorActor): Editor {
135
141
  editorActorSnapshot: editorActor.getSnapshot(),
136
142
  slateEditorInstance: slateEditor.instance,
137
143
  }),
144
+ registerBehavior: (config) => {
145
+ editorActor.send({
146
+ type: 'add behavior',
147
+ behavior: config.behavior,
148
+ })
149
+
150
+ return () => {
151
+ editorActor.send({
152
+ type: 'remove behavior',
153
+ behavior: config.behavior,
154
+ })
155
+ }
156
+ },
138
157
  send: (event) => {
139
158
  editorActor.send(event)
140
159
  },