@portabletext/editor 1.48.9 → 1.48.11

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 (80) hide show
  1. package/lib/_chunks-cjs/editor-provider.cjs +879 -169
  2. package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
  3. package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs +2 -2
  4. package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs.map +1 -1
  5. package/lib/_chunks-cjs/selector.get-text-before.cjs +2 -2
  6. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  7. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +464 -19
  8. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
  9. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs +9 -1
  10. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -1
  11. package/lib/_chunks-cjs/util.slice-blocks.cjs +2 -2
  12. package/lib/_chunks-es/editor-provider.js +773 -65
  13. package/lib/_chunks-es/editor-provider.js.map +1 -1
  14. package/lib/_chunks-es/selector.get-focus-inline-object.js +1 -1
  15. package/lib/_chunks-es/selector.get-text-before.js +1 -1
  16. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +448 -3
  17. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
  18. package/lib/_chunks-es/util.selection-point-to-block-offset.js +9 -1
  19. package/lib/_chunks-es/util.selection-point-to-block-offset.js.map +1 -1
  20. package/lib/_chunks-es/util.slice-blocks.js +2 -2
  21. package/lib/behaviors/index.cjs +27 -377
  22. package/lib/behaviors/index.cjs.map +1 -1
  23. package/lib/behaviors/index.d.cts +3696 -13915
  24. package/lib/behaviors/index.d.ts +3696 -13915
  25. package/lib/behaviors/index.js +22 -377
  26. package/lib/behaviors/index.js.map +1 -1
  27. package/lib/index.cjs +17 -17
  28. package/lib/index.cjs.map +1 -1
  29. package/lib/index.d.cts +3008 -394
  30. package/lib/index.d.ts +3008 -394
  31. package/lib/index.js +4 -5
  32. package/lib/index.js.map +1 -1
  33. package/lib/plugins/index.cjs +347 -30
  34. package/lib/plugins/index.cjs.map +1 -1
  35. package/lib/plugins/index.d.cts +3008 -395
  36. package/lib/plugins/index.d.ts +3008 -395
  37. package/lib/plugins/index.js +324 -8
  38. package/lib/plugins/index.js.map +1 -1
  39. package/lib/selectors/index.cjs +29 -29
  40. package/lib/selectors/index.cjs.map +1 -1
  41. package/lib/selectors/index.d.cts +3007 -387
  42. package/lib/selectors/index.d.ts +3007 -387
  43. package/lib/selectors/index.js +2 -3
  44. package/lib/selectors/index.js.map +1 -1
  45. package/lib/utils/index.cjs +5 -5
  46. package/lib/utils/index.cjs.map +1 -1
  47. package/lib/utils/index.d.cts +3008 -389
  48. package/lib/utils/index.d.ts +3008 -389
  49. package/lib/utils/index.js +2 -3
  50. package/lib/utils/index.js.map +1 -1
  51. package/package.json +1 -1
  52. package/src/behaviors/behavior.emoji-picker.ts +0 -6
  53. package/src/behaviors/behavior.markdown.ts +0 -48
  54. package/src/behaviors/index.ts +0 -15
  55. package/src/editor/create-editor.ts +0 -3
  56. package/src/editor/editor-machine.ts +105 -52
  57. package/src/editor/sync-machine.ts +10 -4
  58. package/src/internal-utils/__tests__/operationToPatches.test.ts +0 -2
  59. package/src/internal-utils/__tests__/patchToOperations.test.ts +0 -2
  60. package/src/plugins/plugin.core.tsx +1 -1
  61. package/lib/_chunks-cjs/behavior.core.cjs +0 -700
  62. package/lib/_chunks-cjs/behavior.core.cjs.map +0 -1
  63. package/lib/_chunks-cjs/behavior.markdown.cjs +0 -321
  64. package/lib/_chunks-cjs/behavior.markdown.cjs.map +0 -1
  65. package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs +0 -449
  66. package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs.map +0 -1
  67. package/lib/_chunks-cjs/util.get-selection-start-point.cjs +0 -10
  68. package/lib/_chunks-cjs/util.get-selection-start-point.cjs.map +0 -1
  69. package/lib/_chunks-es/behavior.core.js +0 -703
  70. package/lib/_chunks-es/behavior.core.js.map +0 -1
  71. package/lib/_chunks-es/behavior.markdown.js +0 -325
  72. package/lib/_chunks-es/behavior.markdown.js.map +0 -1
  73. package/lib/_chunks-es/selector.is-overlapping-selection.js +0 -451
  74. package/lib/_chunks-es/selector.is-overlapping-selection.js.map +0 -1
  75. package/lib/_chunks-es/util.get-selection-start-point.js +0 -11
  76. package/lib/_chunks-es/util.get-selection-start-point.js.map +0 -1
  77. package/src/behaviors/behavior.code-editor.ts +0 -77
  78. package/src/behaviors/behavior.links.ts +0 -84
  79. package/src/internal-utils/looks-like-url.test.ts +0 -19
  80. package/src/internal-utils/looks-like-url.ts +0 -15
@@ -1,7 +1,6 @@
1
- import { isEqualSelectionPoints, sliceBlocks, isSpan$1 as isSpan } from "../_chunks-es/util.slice-blocks.js";
1
+ import { isEqualSelectionPoints, sliceBlocks, isSpan } from "../_chunks-es/util.slice-blocks.js";
2
2
  import { blockOffsetToSpanSelectionPoint, getBlockEndPoint, getBlockStartPoint, getTextBlockText, isEmptyTextBlock, isKeyedSegment, reverseSelection, spanSelectionPointToBlockOffset } from "../_chunks-es/util.slice-blocks.js";
3
- import { blockOffsetToBlockSelectionPoint, blockOffsetToSelectionPoint, blockOffsetsToSelection, childSelectionPointToBlockOffset, selectionPointToBlockOffset } from "../_chunks-es/util.selection-point-to-block-offset.js";
4
- import { getSelectionEndPoint, getSelectionStartPoint } from "../_chunks-es/util.get-selection-start-point.js";
3
+ import { blockOffsetToBlockSelectionPoint, blockOffsetToSelectionPoint, blockOffsetsToSelection, childSelectionPointToBlockOffset, getSelectionEndPoint, getSelectionStartPoint, selectionPointToBlockOffset } from "../_chunks-es/util.selection-point-to-block-offset.js";
5
4
  import { isSelectionCollapsed } from "../_chunks-es/util.is-selection-collapsed.js";
6
5
  import { isTextBlock } from "../_chunks-es/util.merge-text-blocks.js";
7
6
  import { mergeTextBlocks } from "../_chunks-es/util.merge-text-blocks.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/utils/util.is-equal-selections.ts","../../src/utils/util.split-text-block.ts"],"sourcesContent":["import type {EditorSelection} from '../types/editor'\nimport {isEqualSelectionPoints} from './util.is-equal-selection-points'\n\n/**\n * @public\n */\nexport function isEqualSelections(a: EditorSelection, b: EditorSelection) {\n if (!a && !b) {\n return true\n }\n\n if (!a || !b) {\n return false\n }\n\n return (\n isEqualSelectionPoints(a.anchor, b.anchor) &&\n isEqualSelectionPoints(a.focus, b.focus)\n )\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelectionPoint} from '..'\nimport type {EditorContext} from '../editor/editor-snapshot'\nimport {isSpan} from './util.is-span'\nimport {isTextBlock} from './util.is-text-block'\nimport {sliceBlocks} from './util.slice-blocks'\n\n/**\n * @beta\n */\nexport function splitTextBlock({\n context,\n block,\n point,\n}: {\n context: Pick<EditorContext, 'schema'>\n block: PortableTextTextBlock\n point: EditorSelectionPoint\n}): {before: PortableTextTextBlock; after: PortableTextTextBlock} | undefined {\n const firstChild = block.children.at(0)\n const lastChild = block.children.at(block.children.length - 1)\n\n if (!firstChild || !lastChild) {\n return undefined\n }\n\n const before = sliceBlocks({\n context: {\n schema: context.schema,\n selection: {\n anchor: {\n path: [{_key: block._key}, 'children', {_key: firstChild._key}],\n offset: 0,\n },\n focus: point,\n },\n },\n blocks: [block],\n }).at(0)\n const after = sliceBlocks({\n context: {\n schema: context.schema,\n selection: {\n anchor: point,\n focus: {\n path: [{_key: block._key}, 'children', {_key: lastChild._key}],\n offset: isSpan(context, lastChild) ? lastChild.text.length : 0,\n },\n },\n },\n blocks: [block],\n }).at(0)\n\n if (!before || !after) {\n return undefined\n }\n\n if (!isTextBlock(context, before) || !isTextBlock(context, after)) {\n return undefined\n }\n\n return {before, after}\n}\n"],"names":["isEqualSelections","a","b","isEqualSelectionPoints","anchor","focus","splitTextBlock","context","block","point","firstChild","children","at","lastChild","length","before","sliceBlocks","schema","selection","path","_key","offset","blocks","after","isSpan","text","isTextBlock"],"mappings":";;;;;;;AAMgBA,SAAAA,kBAAkBC,GAAoBC,GAAoB;AACpE,SAAA,CAACD,KAAK,CAACC,IACF,KAGL,CAACD,KAAK,CAACC,IACF,KAIPC,uBAAuBF,EAAEG,QAAQF,EAAEE,MAAM,KACzCD,uBAAuBF,EAAEI,OAAOH,EAAEG,KAAK;AAE3C;ACTO,SAASC,eAAe;AAAA,EAC7BC;AAAAA,EACAC;AAAAA,EACAC;AAKF,GAA8E;AAC5E,QAAMC,aAAaF,MAAMG,SAASC,GAAG,CAAC,GAChCC,YAAYL,MAAMG,SAASC,GAAGJ,MAAMG,SAASG,SAAS,CAAC;AAEzD,MAAA,CAACJ,cAAc,CAACG;AAClB;AAGF,QAAME,SAASC,YAAY;AAAA,IACzBT,SAAS;AAAA,MACPU,QAAQV,QAAQU;AAAAA,MAChBC,WAAW;AAAA,QACTd,QAAQ;AAAA,UACNe,MAAM,CAAC;AAAA,YAACC,MAAMZ,MAAMY;AAAAA,aAAO,YAAY;AAAA,YAACA,MAAMV,WAAWU;AAAAA,UAAAA,CAAK;AAAA,UAC9DC,QAAQ;AAAA,QACV;AAAA,QACAhB,OAAOI;AAAAA,MAAAA;AAAAA,IAEX;AAAA,IACAa,QAAQ,CAACd,KAAK;AAAA,EACf,CAAA,EAAEI,GAAG,CAAC,GACDW,QAAQP,YAAY;AAAA,IACxBT,SAAS;AAAA,MACPU,QAAQV,QAAQU;AAAAA,MAChBC,WAAW;AAAA,QACTd,QAAQK;AAAAA,QACRJ,OAAO;AAAA,UACLc,MAAM,CAAC;AAAA,YAACC,MAAMZ,MAAMY;AAAAA,aAAO,YAAY;AAAA,YAACA,MAAMP,UAAUO;AAAAA,UAAAA,CAAK;AAAA,UAC7DC,QAAQG,OAAOjB,SAASM,SAAS,IAAIA,UAAUY,KAAKX,SAAS;AAAA,QAAA;AAAA,MAC/D;AAAA,IAEJ;AAAA,IACAQ,QAAQ,CAACd,KAAK;AAAA,EAAA,CACf,EAAEI,GAAG,CAAC;AAEP,MAAI,EAACG,CAAAA,UAAU,CAACQ,UAIZ,EAACG,CAAAA,YAAYnB,SAASQ,MAAM,KAAK,CAACW,YAAYnB,SAASgB,KAAK;AAIzD,WAAA;AAAA,MAACR;AAAAA,MAAQQ;AAAAA,IAAK;AACvB;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/utils/util.is-equal-selections.ts","../../src/utils/util.split-text-block.ts"],"sourcesContent":["import type {EditorSelection} from '../types/editor'\nimport {isEqualSelectionPoints} from './util.is-equal-selection-points'\n\n/**\n * @public\n */\nexport function isEqualSelections(a: EditorSelection, b: EditorSelection) {\n if (!a && !b) {\n return true\n }\n\n if (!a || !b) {\n return false\n }\n\n return (\n isEqualSelectionPoints(a.anchor, b.anchor) &&\n isEqualSelectionPoints(a.focus, b.focus)\n )\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelectionPoint} from '..'\nimport type {EditorContext} from '../editor/editor-snapshot'\nimport {isSpan} from './util.is-span'\nimport {isTextBlock} from './util.is-text-block'\nimport {sliceBlocks} from './util.slice-blocks'\n\n/**\n * @beta\n */\nexport function splitTextBlock({\n context,\n block,\n point,\n}: {\n context: Pick<EditorContext, 'schema'>\n block: PortableTextTextBlock\n point: EditorSelectionPoint\n}): {before: PortableTextTextBlock; after: PortableTextTextBlock} | undefined {\n const firstChild = block.children.at(0)\n const lastChild = block.children.at(block.children.length - 1)\n\n if (!firstChild || !lastChild) {\n return undefined\n }\n\n const before = sliceBlocks({\n context: {\n schema: context.schema,\n selection: {\n anchor: {\n path: [{_key: block._key}, 'children', {_key: firstChild._key}],\n offset: 0,\n },\n focus: point,\n },\n },\n blocks: [block],\n }).at(0)\n const after = sliceBlocks({\n context: {\n schema: context.schema,\n selection: {\n anchor: point,\n focus: {\n path: [{_key: block._key}, 'children', {_key: lastChild._key}],\n offset: isSpan(context, lastChild) ? lastChild.text.length : 0,\n },\n },\n },\n blocks: [block],\n }).at(0)\n\n if (!before || !after) {\n return undefined\n }\n\n if (!isTextBlock(context, before) || !isTextBlock(context, after)) {\n return undefined\n }\n\n return {before, after}\n}\n"],"names":["isEqualSelections","a","b","isEqualSelectionPoints","anchor","focus","splitTextBlock","context","block","point","firstChild","children","at","lastChild","length","before","sliceBlocks","schema","selection","path","_key","offset","blocks","after","isSpan","text","isTextBlock"],"mappings":";;;;;;AAMgBA,SAAAA,kBAAkBC,GAAoBC,GAAoB;AACpE,SAAA,CAACD,KAAK,CAACC,IACF,KAGL,CAACD,KAAK,CAACC,IACF,KAIPC,uBAAuBF,EAAEG,QAAQF,EAAEE,MAAM,KACzCD,uBAAuBF,EAAEI,OAAOH,EAAEG,KAAK;AAE3C;ACTO,SAASC,eAAe;AAAA,EAC7BC;AAAAA,EACAC;AAAAA,EACAC;AAKF,GAA8E;AAC5E,QAAMC,aAAaF,MAAMG,SAASC,GAAG,CAAC,GAChCC,YAAYL,MAAMG,SAASC,GAAGJ,MAAMG,SAASG,SAAS,CAAC;AAEzD,MAAA,CAACJ,cAAc,CAACG;AAClB;AAGF,QAAME,SAASC,YAAY;AAAA,IACzBT,SAAS;AAAA,MACPU,QAAQV,QAAQU;AAAAA,MAChBC,WAAW;AAAA,QACTd,QAAQ;AAAA,UACNe,MAAM,CAAC;AAAA,YAACC,MAAMZ,MAAMY;AAAAA,aAAO,YAAY;AAAA,YAACA,MAAMV,WAAWU;AAAAA,UAAAA,CAAK;AAAA,UAC9DC,QAAQ;AAAA,QACV;AAAA,QACAhB,OAAOI;AAAAA,MAAAA;AAAAA,IAEX;AAAA,IACAa,QAAQ,CAACd,KAAK;AAAA,EACf,CAAA,EAAEI,GAAG,CAAC,GACDW,QAAQP,YAAY;AAAA,IACxBT,SAAS;AAAA,MACPU,QAAQV,QAAQU;AAAAA,MAChBC,WAAW;AAAA,QACTd,QAAQK;AAAAA,QACRJ,OAAO;AAAA,UACLc,MAAM,CAAC;AAAA,YAACC,MAAMZ,MAAMY;AAAAA,aAAO,YAAY;AAAA,YAACA,MAAMP,UAAUO;AAAAA,UAAAA,CAAK;AAAA,UAC7DC,QAAQG,OAAOjB,SAASM,SAAS,IAAIA,UAAUY,KAAKX,SAAS;AAAA,QAAA;AAAA,MAC/D;AAAA,IAEJ;AAAA,IACAQ,QAAQ,CAACd,KAAK;AAAA,EAAA,CACf,EAAEI,GAAG,CAAC;AAEP,MAAI,EAACG,CAAAA,UAAU,CAACQ,UAIZ,EAACG,CAAAA,YAAYnB,SAASQ,MAAM,KAAK,CAACW,YAAYnB,SAASgB,KAAK;AAIzD,WAAA;AAAA,MAACR;AAAAA,MAAQQ;AAAAA,IAAK;AACvB;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.48.9",
3
+ "version": "1.48.11",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -8,9 +8,6 @@ const emojiCharRegEx = /^[a-zA-Z-_0-9]{1}$/
8
8
  const incompleteEmojiRegEx = /:([a-zA-Z-_0-9]+)$/
9
9
  const emojiRegEx = /:([a-zA-Z-_0-9]+):$/
10
10
 
11
- /**
12
- * @beta
13
- */
14
11
  export type EmojiPickerBehaviorsConfig<TEmojiMatch> = {
15
12
  /**
16
13
  * Match emojis by keyword.
@@ -24,9 +21,6 @@ export type EmojiPickerBehaviorsConfig<TEmojiMatch> = {
24
21
  parseMatch: ({match}: {match: TEmojiMatch}) => string | undefined
25
22
  }
26
23
 
27
- /**
28
- * @beta
29
- */
30
24
  export function createEmojiPickerBehaviors<TEmojiMatch>(
31
25
  config: EmojiPickerBehaviorsConfig<TEmojiMatch>,
32
26
  ) {
@@ -6,9 +6,6 @@ import {getTextBlockText} from '../utils/util.get-text-block-text'
6
6
  import {execute} from './behavior.types.action'
7
7
  import {defineBehavior} from './behavior.types.behavior'
8
8
 
9
- /**
10
- * @beta
11
- */
12
9
  export type MarkdownBehaviorsConfig = {
13
10
  horizontalRuleObject?: (context: {
14
11
  schema: EditorSchema
@@ -23,51 +20,6 @@ export type MarkdownBehaviorsConfig = {
23
20
  orderedListStyle?: (context: {schema: EditorSchema}) => string | undefined
24
21
  }
25
22
 
26
- /**
27
- * @beta
28
- * Create markdown behaviors for common markdown actions such as converting ### to headings, --- to HRs, and more.
29
- *
30
- * @example
31
- * Configure the bundled markdown behaviors
32
- * ```ts
33
- * import {EditorProvider} from '@portabletext/editor'
34
- * import {createMarkdownBehaviors, coreBehaviors} from '@portabletext/editor/behaviors'
35
- *
36
- * function App() {
37
- * return (
38
- * <EditorProvider
39
- * initialConfig={{
40
- * behaviors: [
41
- * ...coreBehaviors,
42
- * ...createMarkdownBehaviors({
43
- * horizontalRuleObject: ({schema}) => {
44
- * const name = schema.blockObjects.find(
45
- * (object) => object.name === 'break',
46
- * )?.name
47
- * return name ? {name} : undefined
48
- * },
49
- * defaultStyle: ({schema}) => schema.styles[0].value,
50
- * headingStyle: ({schema, level}) =>
51
- * schema.styles.find((style) => style.value === `h${level}`)
52
- * ?.value,
53
- * blockquoteStyle: ({schema}) =>
54
- * schema.styles.find((style) => style.value === 'blockquote')
55
- * ?.value,
56
- * unorderedListStyle: ({schema}) =>
57
- * schema.lists.find((list) => list.value === 'bullet')?.value,
58
- * orderedListStyle: ({schema}) =>
59
- * schema.lists.find((list) => list.value === 'number')?.value,
60
- * }),
61
- * ]
62
- * }}
63
- * >
64
- * {...}
65
- * </EditorProvider>
66
- * )
67
- * }
68
- * ```
69
- *
70
- */
71
23
  export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
72
24
  const automaticBlockquoteOnSpace = defineBehavior({
73
25
  on: 'insert.text',
@@ -1,18 +1,3 @@
1
- export {
2
- createCodeEditorBehaviors,
3
- type CodeEditorBehaviorsConfig,
4
- } from './behavior.code-editor'
5
- export {coreBehaviors} from './behavior.core'
6
- export {
7
- createEmojiPickerBehaviors,
8
- type EmojiPickerBehaviorsConfig,
9
- } from './behavior.emoji-picker'
10
- export {createLinkBehaviors, type LinkBehaviorsConfig} from './behavior.links'
11
- export {
12
- createMarkdownBehaviors,
13
- type MarkdownBehaviorsConfig,
14
- } from './behavior.markdown'
15
-
16
1
  export {
17
2
  execute,
18
3
  forward,
@@ -33,7 +33,6 @@ export type EditorConfig = {
33
33
  /**
34
34
  * @beta
35
35
  */
36
- behaviors?: Array<Behavior>
37
36
  keyGenerator?: () => string
38
37
  /**
39
38
  * @deprecated Will be removed in the next major version
@@ -98,7 +97,6 @@ export function editorConfigToMachineInput(config: EditorConfig) {
98
97
  const {legacySchema, schema} = compileSchemasFromEditorConfig(config)
99
98
 
100
99
  return {
101
- behaviors: config.behaviors,
102
100
  converters: createCoreConverters(legacySchema),
103
101
  getLegacySchema: () => legacySchema,
104
102
  keyGenerator: config.keyGenerator ?? defaultKeyGenerator,
@@ -136,7 +134,6 @@ export function createInternalEditor(editorActor: EditorActor): InternalEditor {
136
134
  switch (event.type) {
137
135
  case 'add behavior':
138
136
  case 'remove behavior':
139
- case 'update behaviors':
140
137
  case 'update key generator':
141
138
  case 'update readOnly':
142
139
  case 'patches':
@@ -71,10 +71,6 @@ export type ExternalEditorEvent =
71
71
  type: 'update schema'
72
72
  schema: EditorSchema
73
73
  }
74
- | {
75
- type: 'update behaviors'
76
- behaviors: Array<Behavior>
77
- }
78
74
  | {
79
75
  type: 'update key generator'
80
76
  keyGenerator: () => string
@@ -179,7 +175,10 @@ export type InternalEditorEvent =
179
175
  type: 'done normalizing'
180
176
  }
181
177
  | {
182
- type: 'done syncing initial value'
178
+ type: 'done syncing value'
179
+ }
180
+ | {
181
+ type: 'syncing value'
183
182
  }
184
183
  | {
185
184
  type: 'behavior event'
@@ -219,6 +218,7 @@ export const editorMachine = setup({
219
218
  getLegacySchema: () => PortableTextMemberSchemaTypes
220
219
  keyGenerator: () => string
221
220
  pendingEvents: Array<InternalPatchEvent | MutationEvent>
221
+ pendingIncomingPatchesEvents: Array<PatchesEvent>
222
222
  schema: EditorSchema
223
223
  initialReadOnly: boolean
224
224
  maxBlocks: number | undefined
@@ -233,7 +233,6 @@ export const editorMachine = setup({
233
233
  events: {} as InternalEditorEvent,
234
234
  emitted: {} as InternalEditorEmittedEvent,
235
235
  input: {} as {
236
- behaviors?: Array<Behavior>
237
236
  converters?: Array<Converter>
238
237
  getLegacySchema: () => PortableTextMemberSchemaTypes
239
238
  keyGenerator: () => string
@@ -261,12 +260,6 @@ export const editorMachine = setup({
261
260
  return new Set([...context.behaviors])
262
261
  },
263
262
  }),
264
- 'assign behaviors': assign({
265
- behaviors: ({event}) => {
266
- assertEvent(event, 'update behaviors')
267
- return new Set([...event.behaviors])
268
- },
269
- }),
270
263
  'assign schema': assign({
271
264
  schema: ({event}) => {
272
265
  assertEvent(event, 'update schema')
@@ -305,6 +298,21 @@ export const editorMachine = setup({
305
298
  'clear pending events': assign({
306
299
  pendingEvents: [],
307
300
  }),
301
+ 'defer incoming patches': assign({
302
+ pendingIncomingPatchesEvents: ({context, event}) => {
303
+ return event.type === 'patches'
304
+ ? [...context.pendingIncomingPatchesEvents, event]
305
+ : context.pendingIncomingPatchesEvents
306
+ },
307
+ }),
308
+ 'emit pending incoming patches': enqueueActions(({context, enqueue}) => {
309
+ for (const event of context.pendingIncomingPatchesEvents) {
310
+ enqueue.emit(event)
311
+ }
312
+ }),
313
+ 'clear pending incoming patches': assign({
314
+ pendingIncomingPatchesEvents: [],
315
+ }),
308
316
  'handle blur': ({event}) => {
309
317
  assertEvent(event, 'blur')
310
318
 
@@ -367,11 +375,12 @@ export const editorMachine = setup({
367
375
  }).createMachine({
368
376
  id: 'editor',
369
377
  context: ({input}) => ({
370
- behaviors: new Set([...(input.behaviors ?? coreBehaviors)]),
378
+ behaviors: new Set([...coreBehaviors]),
371
379
  converters: new Set(input.converters ?? []),
372
380
  getLegacySchema: input.getLegacySchema,
373
381
  keyGenerator: input.keyGenerator,
374
382
  pendingEvents: [],
383
+ pendingIncomingPatchesEvents: [],
375
384
  schema: input.schema,
376
385
  selection: null,
377
386
  initialReadOnly: input.readOnly ?? false,
@@ -404,8 +413,6 @@ export const editorMachine = setup({
404
413
 
405
414
  'add behavior': {actions: 'add behavior to context'},
406
415
  'remove behavior': {actions: 'remove behavior from context'},
407
- 'patches': {actions: emit(({event}) => event)},
408
- 'update behaviors': {actions: 'assign behaviors'},
409
416
  'update key generator': {
410
417
  actions: assign({keyGenerator: ({event}) => event.keyGenerator}),
411
418
  },
@@ -439,7 +446,7 @@ export const editorMachine = setup({
439
446
  states: {
440
447
  'determine initial edit mode': {
441
448
  on: {
442
- 'done syncing initial value': [
449
+ 'done syncing value': [
443
450
  {
444
451
  target: '#editor.edit mode.read only.read only',
445
452
  guard: ({context}) => context.initialReadOnly,
@@ -553,7 +560,11 @@ export const editorMachine = setup({
553
560
  initial: 'setting up',
554
561
  states: {
555
562
  'setting up': {
556
- exit: ['emit ready'],
563
+ exit: [
564
+ 'emit ready',
565
+ 'emit pending incoming patches',
566
+ 'clear pending incoming patches',
567
+ ],
557
568
  on: {
558
569
  'internal.patch': {
559
570
  actions: 'defer event',
@@ -561,55 +572,97 @@ export const editorMachine = setup({
561
572
  'mutation': {
562
573
  actions: 'defer event',
563
574
  },
564
- 'done syncing initial value': {
565
- target: 'pristine',
575
+ 'done syncing value': {
576
+ target: 'set up',
577
+ },
578
+ 'patches': {
579
+ actions: ['defer incoming patches'],
566
580
  },
567
581
  },
568
582
  },
569
- 'pristine': {
570
- initial: 'idle',
583
+ 'set up': {
584
+ type: 'parallel',
571
585
  states: {
572
- idle: {
573
- on: {
574
- 'normalizing': {
575
- target: 'normalizing',
576
- },
577
- 'internal.patch': {
578
- actions: 'defer event',
579
- target: '#editor.setup.dirty',
586
+ 'value sync': {
587
+ initial: 'idle',
588
+ states: {
589
+ 'idle': {
590
+ on: {
591
+ 'patches': {
592
+ actions: [emit(({event}) => event)],
593
+ },
594
+ 'syncing value': {
595
+ target: 'syncing value',
596
+ },
597
+ },
580
598
  },
581
- 'mutation': {
582
- actions: 'defer event',
583
- target: '#editor.setup.dirty',
599
+ 'syncing value': {
600
+ exit: [
601
+ 'emit pending incoming patches',
602
+ 'clear pending incoming patches',
603
+ ],
604
+ on: {
605
+ 'patches': {
606
+ actions: ['defer incoming patches'],
607
+ },
608
+ 'done syncing value': {
609
+ target: 'idle',
610
+ },
611
+ },
584
612
  },
585
613
  },
586
614
  },
587
- normalizing: {
588
- on: {
589
- 'done normalizing': {
590
- target: 'idle',
591
- },
592
- 'internal.patch': {
593
- actions: 'defer event',
615
+ 'writing': {
616
+ initial: 'pristine',
617
+ states: {
618
+ pristine: {
619
+ initial: 'idle',
620
+ states: {
621
+ idle: {
622
+ on: {
623
+ 'normalizing': {
624
+ target: 'normalizing',
625
+ },
626
+ 'internal.patch': {
627
+ actions: 'defer event',
628
+ target: '#editor.setup.set up.writing.dirty',
629
+ },
630
+ 'mutation': {
631
+ actions: 'defer event',
632
+ target: '#editor.setup.set up.writing.dirty',
633
+ },
634
+ },
635
+ },
636
+ normalizing: {
637
+ on: {
638
+ 'done normalizing': {
639
+ target: 'idle',
640
+ },
641
+ 'internal.patch': {
642
+ actions: 'defer event',
643
+ },
644
+ 'mutation': {
645
+ actions: 'defer event',
646
+ },
647
+ },
648
+ },
649
+ },
594
650
  },
595
- 'mutation': {
596
- actions: 'defer event',
651
+ dirty: {
652
+ entry: ['emit pending events', 'clear pending events'],
653
+ on: {
654
+ 'internal.patch': {
655
+ actions: 'emit patch event',
656
+ },
657
+ 'mutation': {
658
+ actions: 'emit mutation event',
659
+ },
660
+ },
597
661
  },
598
662
  },
599
663
  },
600
664
  },
601
665
  },
602
- 'dirty': {
603
- entry: ['emit pending events', 'clear pending events'],
604
- on: {
605
- 'internal.patch': {
606
- actions: 'emit patch event',
607
- },
608
- 'mutation': {
609
- actions: 'emit mutation event',
610
- },
611
- },
612
- },
613
666
  },
614
667
  },
615
668
  },
@@ -126,7 +126,8 @@ export const syncMachine = setup({
126
126
  'type',
127
127
  'invalid value' | 'patch' | 'value changed'
128
128
  >
129
- | {type: 'done syncing initial value'},
129
+ | {type: 'done syncing value'}
130
+ | {type: 'syncing value'},
130
131
  },
131
132
  actions: {
132
133
  'assign initial value synced': assign({
@@ -153,8 +154,11 @@ export const syncMachine = setup({
153
154
  return event.value
154
155
  },
155
156
  }),
156
- 'emit done syncing initial value': emit({
157
- type: 'done syncing initial value',
157
+ 'emit done syncing value': emit({
158
+ type: 'done syncing value',
159
+ }),
160
+ 'emit syncing value': emit({
161
+ type: 'syncing value',
158
162
  }),
159
163
  },
160
164
  guards: {
@@ -230,7 +234,7 @@ export const syncMachine = setup({
230
234
  },
231
235
  'done syncing initial value': {
232
236
  entry: [
233
- 'emit done syncing initial value',
237
+ 'emit done syncing value',
234
238
  () => {
235
239
  debug('entry: done syncing initial value')
236
240
  },
@@ -313,11 +317,13 @@ export const syncMachine = setup({
313
317
  () => {
314
318
  debug('entry: syncing->syncing')
315
319
  },
320
+ 'emit syncing value',
316
321
  ],
317
322
  exit: [
318
323
  () => {
319
324
  debug('exit: syncing->syncing')
320
325
  },
326
+ 'emit done syncing value',
321
327
  ],
322
328
  always: {
323
329
  guard: 'pending value equals previous value',
@@ -2,7 +2,6 @@ import type {PortableTextTextBlock} from '@sanity/types'
2
2
  import {createEditor, type Descendant} from 'slate'
3
3
  import {beforeEach, describe, expect, it} from 'vitest'
4
4
  import {createActor} from 'xstate'
5
- import {coreBehaviors} from '../../behaviors/behavior.core'
6
5
  import {schemaType} from '../../editor/__tests__/PortableTextEditorTester'
7
6
  import {editorMachine} from '../../editor/editor-machine'
8
7
  import {legacySchemaToEditorSchema} from '../../editor/editor-schema'
@@ -15,7 +14,6 @@ const legacySchema = createLegacySchema(schemaType)
15
14
  const schemaTypes = legacySchemaToEditorSchema(legacySchema)
16
15
  const editorActor = createActor(editorMachine, {
17
16
  input: {
18
- behaviors: coreBehaviors,
19
17
  schema: schemaTypes,
20
18
  keyGenerator: defaultKeyGenerator,
21
19
  getLegacySchema: () => legacySchema,
@@ -2,7 +2,6 @@ import type {Patch} from '@portabletext/patches'
2
2
  import {createEditor, type Descendant} from 'slate'
3
3
  import {beforeEach, describe, expect, it} from 'vitest'
4
4
  import {createActor} from 'xstate'
5
- import {coreBehaviors} from '../../behaviors/behavior.core'
6
5
  import {schemaType} from '../../editor/__tests__/PortableTextEditorTester'
7
6
  import {editorMachine} from '../../editor/editor-machine'
8
7
  import {legacySchemaToEditorSchema} from '../../editor/editor-schema'
@@ -20,7 +19,6 @@ const patchToOperations = createApplyPatch(schemaTypes)
20
19
  const editor = withPlugins(createEditor(), {
21
20
  editorActor: createActor(editorMachine, {
22
21
  input: {
23
- behaviors: coreBehaviors,
24
22
  schema: schemaTypes,
25
23
  keyGenerator: defaultKeyGenerator,
26
24
  getLegacySchema: () => legacySchema,
@@ -1,4 +1,4 @@
1
- import {coreBehaviors} from '../behaviors'
1
+ import {coreBehaviors} from '../behaviors/behavior.core'
2
2
  import {BehaviorPlugin} from './plugin.behavior'
3
3
 
4
4
  /**