@portabletext/editor 1.49.2 → 1.49.3

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 (76) hide show
  1. package/lib/_chunks-cjs/selector.get-text-before.cjs +2 -2
  2. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  3. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +40 -230
  4. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
  5. package/lib/_chunks-cjs/selector.is-selection-expanded.cjs +201 -0
  6. package/lib/_chunks-cjs/selector.is-selection-expanded.cjs.map +1 -0
  7. package/lib/_chunks-cjs/use-editor.cjs +28 -0
  8. package/lib/_chunks-cjs/use-editor.cjs.map +1 -0
  9. package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs +79 -0
  10. package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs.map +1 -0
  11. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs +34 -0
  12. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs.map +1 -0
  13. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs +6 -78
  14. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -1
  15. package/lib/_chunks-cjs/util.slice-blocks.cjs +0 -31
  16. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  17. package/lib/_chunks-es/selector.get-text-before.js +1 -1
  18. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +13 -201
  19. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
  20. package/lib/_chunks-es/selector.is-selection-expanded.js +203 -0
  21. package/lib/_chunks-es/selector.is-selection-expanded.js.map +1 -0
  22. package/lib/_chunks-es/use-editor.js +25 -0
  23. package/lib/_chunks-es/use-editor.js.map +1 -0
  24. package/lib/_chunks-es/util.child-selection-point-to-block-offset.js +80 -0
  25. package/lib/_chunks-es/util.child-selection-point-to-block-offset.js.map +1 -0
  26. package/lib/_chunks-es/util.is-equal-selection-points.js +35 -0
  27. package/lib/_chunks-es/util.is-equal-selection-points.js.map +1 -0
  28. package/lib/_chunks-es/util.selection-point-to-block-offset.js +6 -77
  29. package/lib/_chunks-es/util.selection-point-to-block-offset.js.map +1 -1
  30. package/lib/_chunks-es/util.slice-blocks.js +0 -31
  31. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  32. package/lib/index.cjs +8998 -290
  33. package/lib/index.cjs.map +1 -1
  34. package/lib/index.d.cts +2 -2
  35. package/lib/index.d.ts +2 -2
  36. package/lib/index.js +8945 -222
  37. package/lib/index.js.map +1 -1
  38. package/lib/plugins/index.cjs +23 -23
  39. package/lib/plugins/index.cjs.map +1 -1
  40. package/lib/plugins/index.js +3 -3
  41. package/lib/plugins/index.js.map +1 -1
  42. package/lib/selectors/index.cjs +22 -22
  43. package/lib/selectors/index.cjs.map +1 -1
  44. package/lib/selectors/index.js +4 -3
  45. package/lib/selectors/index.js.map +1 -1
  46. package/lib/utils/index.cjs +10 -10
  47. package/lib/utils/index.cjs.map +1 -1
  48. package/lib/utils/index.js +6 -4
  49. package/lib/utils/index.js.map +1 -1
  50. package/package.json +13 -13
  51. package/src/editor/create-editor.ts +2 -58
  52. package/src/editor/editor-context.tsx +1 -1
  53. package/src/editor/editor-provider.tsx +4 -31
  54. package/src/editor/editor-selector.ts +2 -1
  55. package/src/editor/use-editor.ts +27 -0
  56. package/src/editor-event-listener.tsx +1 -1
  57. package/src/editor.ts +57 -0
  58. package/src/index.ts +9 -9
  59. package/src/internal-utils/text-selection.test.ts +11 -0
  60. package/src/plugins/plugin.behavior.tsx +1 -1
  61. package/src/plugins/plugin.decorator-shortcut.ts +2 -2
  62. package/src/plugins/plugin.editor-ref.tsx +2 -2
  63. package/src/plugins/plugin.event-listener.tsx +1 -1
  64. package/src/plugins/plugin.markdown.tsx +1 -1
  65. package/lib/_chunks-cjs/editor-provider.cjs +0 -8756
  66. package/lib/_chunks-cjs/editor-provider.cjs.map +0 -1
  67. package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs +0 -11
  68. package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs.map +0 -1
  69. package/lib/_chunks-cjs/util.is-selection-collapsed.cjs +0 -6
  70. package/lib/_chunks-cjs/util.is-selection-collapsed.cjs.map +0 -1
  71. package/lib/_chunks-es/editor-provider.js +0 -8782
  72. package/lib/_chunks-es/editor-provider.js.map +0 -1
  73. package/lib/_chunks-es/selector.get-focus-inline-object.js +0 -13
  74. package/lib/_chunks-es/selector.get-focus-inline-object.js.map +0 -1
  75. package/lib/_chunks-es/util.is-selection-collapsed.js +0 -7
  76. package/lib/_chunks-es/util.is-selection-collapsed.js.map +0 -1
@@ -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.49.2",
3
+ "version": "1.49.3",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -79,43 +79,43 @@
79
79
  "slate-react": "0.114.2",
80
80
  "use-effect-event": "^1.0.2",
81
81
  "xstate": "^5.19.2",
82
- "@portabletext/block-tools": "1.1.24",
82
+ "@portabletext/block-tools": "1.1.25",
83
83
  "@portabletext/patches": "1.1.3"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@portabletext/toolkit": "^2.0.17",
87
87
  "@sanity/diff-match-patch": "^3.2.0",
88
88
  "@sanity/pkg-utils": "^7.2.2",
89
- "@sanity/schema": "^3.88.0",
90
- "@sanity/types": "^3.88.0",
89
+ "@sanity/schema": "^3.88.2",
90
+ "@sanity/types": "^3.88.2",
91
91
  "@testing-library/jest-dom": "^6.6.3",
92
92
  "@testing-library/react": "^16.3.0",
93
93
  "@types/debug": "^4.1.12",
94
94
  "@types/lodash": "^4.17.16",
95
95
  "@types/lodash.startcase": "^4.4.9",
96
- "@types/react": "^19.1.2",
96
+ "@types/react": "^19.1.3",
97
97
  "@types/react-dom": "^19.1.3",
98
- "@typescript-eslint/eslint-plugin": "^8.29.0",
99
- "@typescript-eslint/parser": "^8.29.0",
98
+ "@typescript-eslint/eslint-plugin": "^8.32.0",
99
+ "@typescript-eslint/parser": "^8.32.0",
100
100
  "@vitejs/plugin-react": "^4.4.1",
101
- "@vitest/browser": "^3.1.2",
102
- "@vitest/coverage-istanbul": "^3.1.2",
101
+ "@vitest/browser": "^3.1.3",
102
+ "@vitest/coverage-istanbul": "^3.1.3",
103
103
  "babel-plugin-react-compiler": "19.1.0-rc.1",
104
104
  "eslint": "8.57.1",
105
- "eslint-plugin-react-hooks": "0.0.0-experimental-0038c501-20250429",
105
+ "eslint-plugin-react-hooks": "0.0.0-experimental-7a2c7045-20250506",
106
106
  "jsdom": "^26.0.0",
107
107
  "react": "^19.1.0",
108
108
  "react-dom": "^19.1.0",
109
109
  "rxjs": "^7.8.2",
110
110
  "typescript": "5.8.3",
111
111
  "vite": "^6.2.5",
112
- "vitest": "^3.1.2",
112
+ "vitest": "^3.1.3",
113
113
  "vitest-browser-react": "^0.1.1",
114
114
  "racejar": "1.2.4"
115
115
  },
116
116
  "peerDependencies": {
117
- "@sanity/schema": "^3.88.0",
118
- "@sanity/types": "^3.88.0",
117
+ "@sanity/schema": "^3.88.2",
118
+ "@sanity/types": "^3.88.2",
119
119
  "react": "^16.9 || ^17 || ^18 || ^19",
120
120
  "rxjs": "^7.8.2"
121
121
  },
@@ -1,76 +1,20 @@
1
- import type {
2
- ArrayDefinition,
3
- ArraySchemaType,
4
- PortableTextBlock,
5
- } from '@sanity/types'
6
- import type {ActorRef, EventObject, Snapshot} from 'xstate'
7
- import type {Behavior} from '../behaviors/behavior.types.behavior'
8
- import type {ExternalBehaviorEvent} from '../behaviors/behavior.types.event'
9
1
  import {createCoreConverters} from '../converters/converters.core'
2
+ import type {Editor, EditorConfig} from '../editor'
10
3
  import {compileType} from '../internal-utils/schema'
11
4
  import {corePriority} from '../priority/priority.core'
12
5
  import {createEditorPriority} from '../priority/priority.types'
13
6
  import type {EditableAPI} from '../types/editor'
14
7
  import {createSlateEditor, type SlateEditor} from './create-slate-editor'
15
- import type {
16
- EditorActor,
17
- EditorEmittedEvent,
18
- ExternalEditorEvent,
19
- } from './editor-machine'
8
+ import type {EditorActor} from './editor-machine'
20
9
  import {
21
10
  compileSchemaDefinitionToLegacySchema,
22
11
  legacySchemaToEditorSchema,
23
- type SchemaDefinition,
24
12
  } from './editor-schema'
25
13
  import {getEditorSnapshot} from './editor-selector'
26
- import type {EditorSnapshot} from './editor-snapshot'
27
14
  import {defaultKeyGenerator} from './key-generator'
28
15
  import {createLegacySchema} from './legacy-schema'
29
16
  import {createEditableAPI} from './plugins/createWithEditableAPI'
30
17
 
31
- /**
32
- * @public
33
- */
34
- export type EditorConfig = {
35
- /**
36
- * @beta
37
- */
38
- keyGenerator?: () => string
39
- /**
40
- * @deprecated Will be removed in the next major version
41
- */
42
- maxBlocks?: number
43
- readOnly?: boolean
44
- initialValue?: Array<PortableTextBlock>
45
- } & (
46
- | {
47
- schemaDefinition: SchemaDefinition
48
- schema?: undefined
49
- }
50
- | {
51
- schemaDefinition?: undefined
52
- schema: ArraySchemaType<PortableTextBlock> | ArrayDefinition
53
- }
54
- )
55
-
56
- /**
57
- * @public
58
- */
59
- export type EditorEvent = ExternalEditorEvent | ExternalBehaviorEvent
60
-
61
- /**
62
- * @public
63
- */
64
- export type Editor = {
65
- getSnapshot: () => EditorSnapshot
66
- /**
67
- * @beta
68
- */
69
- registerBehavior: (config: {behavior: Behavior}) => () => void
70
- send: (event: EditorEvent) => void
71
- on: ActorRef<Snapshot<unknown>, EventObject, EditorEmittedEvent>['on']
72
- }
73
-
74
18
  export type InternalEditor = Editor & {
75
19
  _internal: {
76
20
  editable: EditableAPI
@@ -1,5 +1,5 @@
1
+ import type {Editor} from '../editor'
1
2
  import {createGloballyScopedContext} from '../internal-utils/globally-scoped-context'
2
- import type {Editor} from './create-editor'
3
3
 
4
4
  export const EditorContext = createGloballyScopedContext<Editor | null>(
5
5
  '@portabletext/editor/context/editor',
@@ -1,12 +1,10 @@
1
1
  import {useActorRef} from '@xstate/react'
2
- import React, {useMemo} from 'react'
2
+ import type React from 'react'
3
+ import {useMemo} from 'react'
3
4
  import {Slate} from 'slate-react'
5
+ import type {EditorConfig} from '../editor'
4
6
  import {Synchronizer} from './components/Synchronizer'
5
- import {
6
- createInternalEditor,
7
- editorConfigToMachineInput,
8
- type EditorConfig,
9
- } from './create-editor'
7
+ import {createInternalEditor, editorConfigToMachineInput} from './create-editor'
10
8
  import {EditorActorContext} from './editor-actor-context'
11
9
  import {EditorContext} from './editor-context'
12
10
  import {editorMachine} from './editor-machine'
@@ -87,28 +85,3 @@ export function EditorProvider(props: EditorProviderProps) {
87
85
  </EditorContext.Provider>
88
86
  )
89
87
  }
90
-
91
- /**
92
- * @public
93
- * Get the current editor context from the `EditorProvider`.
94
- * Must be used inside the `EditorProvider` component.
95
- * @returns The current editor object.
96
- * @example
97
- * ```tsx
98
- * import { useEditor } from '@portabletext/editor'
99
- *
100
- * function MyComponent() {
101
- * const editor = useEditor()
102
- * }
103
- * ```
104
- * @group Hooks
105
- */
106
- export function useEditor() {
107
- const editor = React.useContext(EditorContext)
108
-
109
- if (!editor) {
110
- throw new Error('No Editor set. Use EditorProvider to set one.')
111
- }
112
-
113
- return editor
114
- }
@@ -1,7 +1,8 @@
1
1
  import {useSelector} from '@xstate/react'
2
+ import type {Editor} from '../editor'
2
3
  import {slateChildrenToBlocks} from '../internal-utils/slate-children-to-blocks'
3
4
  import type {PortableTextSlateEditor} from '../types/editor'
4
- import type {Editor, InternalEditor} from './create-editor'
5
+ import type {InternalEditor} from './create-editor'
5
6
  import type {EditorActor} from './editor-machine'
6
7
  import type {EditorSnapshot} from './editor-snapshot'
7
8
  import {getActiveDecorators} from './get-active-decorators'
@@ -0,0 +1,27 @@
1
+ import React from 'react'
2
+ import {EditorContext} from './editor-context'
3
+
4
+ /**
5
+ * @public
6
+ * Get the current editor context from the `EditorProvider`.
7
+ * Must be used inside the `EditorProvider` component.
8
+ * @returns The current editor object.
9
+ * @example
10
+ * ```tsx
11
+ * import { useEditor } from '@portabletext/editor'
12
+ *
13
+ * function MyComponent() {
14
+ * const editor = useEditor()
15
+ * }
16
+ * ```
17
+ * @group Hooks
18
+ */
19
+ export function useEditor() {
20
+ const editor = React.useContext(EditorContext)
21
+
22
+ if (!editor) {
23
+ throw new Error('No Editor set. Use EditorProvider to set one.')
24
+ }
25
+
26
+ return editor
27
+ }
@@ -1,7 +1,7 @@
1
1
  import {useEffect} from 'react'
2
2
  import {useEffectEvent} from 'use-effect-event'
3
3
  import type {EditorEmittedEvent} from './editor/editor-machine'
4
- import {useEditor} from './editor/editor-provider'
4
+ import {useEditor} from './editor/use-editor'
5
5
 
6
6
  /**
7
7
  * @public
package/src/editor.ts ADDED
@@ -0,0 +1,57 @@
1
+ import type {
2
+ ArrayDefinition,
3
+ ArraySchemaType,
4
+ PortableTextBlock,
5
+ } from '@sanity/types'
6
+ import type {ActorRef, EventObject, Snapshot} from 'xstate'
7
+ import type {Behavior} from './behaviors/behavior.types.behavior'
8
+ import type {ExternalBehaviorEvent} from './behaviors/behavior.types.event'
9
+ import type {
10
+ EditorEmittedEvent,
11
+ ExternalEditorEvent,
12
+ } from './editor/editor-machine'
13
+ import type {SchemaDefinition} from './editor/editor-schema'
14
+ import type {EditorSnapshot} from './editor/editor-snapshot'
15
+
16
+ /**
17
+ * @public
18
+ */
19
+ export type EditorConfig = {
20
+ /**
21
+ * @beta
22
+ */
23
+ keyGenerator?: () => string
24
+ /**
25
+ * @deprecated Will be removed in the next major version
26
+ */
27
+ maxBlocks?: number
28
+ readOnly?: boolean
29
+ initialValue?: Array<PortableTextBlock>
30
+ } & (
31
+ | {
32
+ schemaDefinition: SchemaDefinition
33
+ schema?: undefined
34
+ }
35
+ | {
36
+ schemaDefinition?: undefined
37
+ schema: ArraySchemaType<PortableTextBlock> | ArrayDefinition
38
+ }
39
+ )
40
+
41
+ /**
42
+ * @public
43
+ */
44
+ export type EditorEvent = ExternalEditorEvent | ExternalBehaviorEvent
45
+
46
+ /**
47
+ * @public
48
+ */
49
+ export type Editor = {
50
+ getSnapshot: () => EditorSnapshot
51
+ /**
52
+ * @beta
53
+ */
54
+ registerBehavior: (config: {behavior: Behavior}) => () => void
55
+ send: (event: EditorEvent) => void
56
+ on: ActorRef<Snapshot<unknown>, EventObject, EditorEmittedEvent>['on']
57
+ }
package/src/index.ts CHANGED
@@ -4,15 +4,8 @@ export type {
4
4
  PortableTextChild,
5
5
  PortableTextSpan,
6
6
  } from '@sanity/types'
7
- export type {AddedAnnotationPaths} from './operations/behavior.operation.annotation.add'
8
7
  export {EditorEventListener} from './editor-event-listener'
9
- export type {Editor, EditorConfig, EditorEvent} from './editor/create-editor'
10
- export {
11
- defineSchema,
12
- type BaseDefinition,
13
- type SchemaDefinition,
14
- } from './editor/editor-schema'
15
- export type {EditorSchema} from './editor/editor-schema'
8
+ export type {Editor, EditorConfig, EditorEvent} from './editor'
16
9
  export {PortableTextEditable} from './editor/Editable'
17
10
  export type {PortableTextEditableProps} from './editor/Editable'
18
11
  export type {
@@ -22,9 +15,14 @@ export type {
22
15
  } from './editor/editor-machine'
23
16
  export {
24
17
  EditorProvider,
25
- useEditor,
26
18
  type EditorProviderProps,
27
19
  } from './editor/editor-provider'
20
+ export {
21
+ defineSchema,
22
+ type BaseDefinition,
23
+ type SchemaDefinition,
24
+ } from './editor/editor-schema'
25
+ export type {EditorSchema} from './editor/editor-schema'
28
26
  export {useEditorSelector, type EditorSelector} from './editor/editor-selector'
29
27
  export type {EditorContext, EditorSnapshot} from './editor/editor-snapshot'
30
28
  export {usePortableTextEditor} from './editor/hooks/usePortableTextEditor'
@@ -32,6 +30,8 @@ export {usePortableTextEditorSelection} from './editor/hooks/usePortableTextEdit
32
30
  export {defaultKeyGenerator as keyGenerator} from './editor/key-generator'
33
31
  export {PortableTextEditor} from './editor/PortableTextEditor'
34
32
  export type {PortableTextEditorProps} from './editor/PortableTextEditor'
33
+ export {useEditor} from './editor/use-editor'
34
+ export type {AddedAnnotationPaths} from './operations/behavior.operation.annotation.add'
35
35
  export type {BlockOffset} from './types/block-offset'
36
36
  export type {
37
37
  BlockAnnotationRenderProps,
@@ -6,6 +6,17 @@ import {
6
6
  } from './text-selection'
7
7
 
8
8
  test(getTextSelection.name, () => {
9
+ const simpleBlock = {
10
+ _key: 'b1',
11
+ _type: 'block',
12
+ children: [{_key: 's1', _type: 'span', text: 'foo'}],
13
+ }
14
+
15
+ expect(getTextSelection([simpleBlock], 'foo')).toEqual({
16
+ anchor: {path: [{_key: 'b1'}, 'children', {_key: 's1'}], offset: 0},
17
+ focus: {path: [{_key: 'b1'}, 'children', {_key: 's1'}], offset: 3},
18
+ })
19
+
9
20
  const joinedBlock = {
10
21
  _key: 'b1',
11
22
  _type: 'block',
@@ -1,6 +1,6 @@
1
1
  import {useEffect} from 'react'
2
2
  import type {Behavior} from '../behaviors'
3
- import {useEditor} from '../editor/editor-provider'
3
+ import {useEditor} from '../editor/use-editor'
4
4
 
5
5
  /**
6
6
  * @beta
@@ -10,9 +10,9 @@ import {
10
10
  import {createDecoratorPairBehavior} from '../behaviors/behavior.decorator-pair'
11
11
  import {effect, execute, forward} from '../behaviors/behavior.types.action'
12
12
  import {defineBehavior} from '../behaviors/behavior.types.behavior'
13
- import type {Editor} from '../editor/create-editor'
14
- import {useEditor} from '../editor/editor-provider'
13
+ import type {Editor} from '../editor'
15
14
  import type {EditorSchema} from '../editor/editor-schema'
15
+ import {useEditor} from '../editor/use-editor'
16
16
  import type {BlockOffset} from '../types/block-offset'
17
17
  import * as utils from '../utils'
18
18
 
@@ -1,6 +1,6 @@
1
1
  import React from 'react'
2
- import type {Editor} from '../editor/create-editor'
3
- import {useEditor} from '../editor/editor-provider'
2
+ import type {Editor} from '../editor'
3
+ import {useEditor} from '../editor/use-editor'
4
4
 
5
5
  /**
6
6
  * @beta
@@ -1,7 +1,7 @@
1
1
  import {useEffect} from 'react'
2
2
  import {useEffectEvent} from 'use-effect-event'
3
3
  import type {EditorEmittedEvent} from '../editor/editor-machine'
4
- import {useEditor} from '../editor/editor-provider'
4
+ import {useEditor} from '../editor/use-editor'
5
5
 
6
6
  /**
7
7
  * @public
@@ -3,8 +3,8 @@ import {
3
3
  createMarkdownBehaviors,
4
4
  type MarkdownBehaviorsConfig,
5
5
  } from '../behaviors/behavior.markdown'
6
- import {useEditor} from '../editor/editor-provider'
7
6
  import type {EditorSchema} from '../editor/editor-schema'
7
+ import {useEditor} from '../editor/use-editor'
8
8
  import {DecoratorShortcutPlugin} from './plugin.decorator-shortcut'
9
9
 
10
10
  /**