@portabletext/editor 1.49.2 → 1.49.4
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/lib/_chunks-cjs/selector.get-text-before.cjs +2 -2
- package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +40 -230
- package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-selection-expanded.cjs +201 -0
- package/lib/_chunks-cjs/selector.is-selection-expanded.cjs.map +1 -0
- package/lib/_chunks-cjs/use-editor.cjs +28 -0
- package/lib/_chunks-cjs/use-editor.cjs.map +1 -0
- package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs +79 -0
- package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs.map +1 -0
- package/lib/_chunks-cjs/util.is-equal-selection-points.cjs +34 -0
- package/lib/_chunks-cjs/util.is-equal-selection-points.cjs.map +1 -0
- package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs +6 -78
- package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -1
- package/lib/_chunks-cjs/util.slice-blocks.cjs +0 -31
- package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
- package/lib/_chunks-es/selector.get-text-before.js +1 -1
- package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +13 -201
- package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
- package/lib/_chunks-es/selector.is-selection-expanded.js +203 -0
- package/lib/_chunks-es/selector.is-selection-expanded.js.map +1 -0
- package/lib/_chunks-es/use-editor.js +25 -0
- package/lib/_chunks-es/use-editor.js.map +1 -0
- package/lib/_chunks-es/util.child-selection-point-to-block-offset.js +80 -0
- package/lib/_chunks-es/util.child-selection-point-to-block-offset.js.map +1 -0
- package/lib/_chunks-es/util.is-equal-selection-points.js +35 -0
- package/lib/_chunks-es/util.is-equal-selection-points.js.map +1 -0
- package/lib/_chunks-es/util.selection-point-to-block-offset.js +6 -77
- package/lib/_chunks-es/util.selection-point-to-block-offset.js.map +1 -1
- package/lib/_chunks-es/util.slice-blocks.js +0 -31
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/index.cjs +9031 -290
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +2 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.js +8978 -222
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.cjs +23 -23
- package/lib/plugins/index.cjs.map +1 -1
- package/lib/plugins/index.js +3 -3
- package/lib/plugins/index.js.map +1 -1
- package/lib/selectors/index.cjs +22 -22
- package/lib/selectors/index.cjs.map +1 -1
- package/lib/selectors/index.js +4 -3
- package/lib/selectors/index.js.map +1 -1
- package/lib/utils/index.cjs +10 -10
- package/lib/utils/index.cjs.map +1 -1
- package/lib/utils/index.js +6 -4
- package/lib/utils/index.js.map +1 -1
- package/package.json +13 -13
- package/src/editor/create-editor.ts +2 -58
- package/src/editor/editor-context.tsx +1 -1
- package/src/editor/editor-provider.tsx +4 -31
- package/src/editor/editor-selector.ts +2 -1
- package/src/editor/sync-machine.ts +70 -29
- package/src/editor/use-editor.ts +27 -0
- package/src/editor-event-listener.tsx +1 -1
- package/src/editor.ts +57 -0
- package/src/index.ts +9 -9
- package/src/internal-utils/text-selection.test.ts +11 -0
- package/src/plugins/plugin.behavior.tsx +1 -1
- package/src/plugins/plugin.decorator-shortcut.ts +2 -2
- package/src/plugins/plugin.editor-ref.tsx +2 -2
- package/src/plugins/plugin.event-listener.tsx +1 -1
- package/src/plugins/plugin.markdown.tsx +1 -1
- package/lib/_chunks-cjs/editor-provider.cjs +0 -8756
- package/lib/_chunks-cjs/editor-provider.cjs.map +0 -1
- package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs +0 -11
- package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs.map +0 -1
- package/lib/_chunks-cjs/util.is-selection-collapsed.cjs +0 -6
- package/lib/_chunks-cjs/util.is-selection-collapsed.cjs.map +0 -1
- package/lib/_chunks-es/editor-provider.js +0 -8782
- package/lib/_chunks-es/editor-provider.js.map +0 -1
- package/lib/_chunks-es/selector.get-focus-inline-object.js +0 -13
- package/lib/_chunks-es/selector.get-focus-inline-object.js.map +0 -1
- package/lib/_chunks-es/util.is-selection-collapsed.js +0 -7
- package/lib/_chunks-es/util.is-selection-collapsed.js.map +0 -1
package/lib/utils/index.js.map
CHANGED
|
@@ -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":"
|
|
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.
|
|
3
|
+
"version": "1.49.4",
|
|
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.
|
|
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.
|
|
90
|
-
"@sanity/types": "^3.88.
|
|
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.
|
|
96
|
+
"@types/react": "^19.1.3",
|
|
97
97
|
"@types/react-dom": "^19.1.3",
|
|
98
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
99
|
-
"@typescript-eslint/parser": "^8.
|
|
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.
|
|
102
|
-
"@vitest/coverage-istanbul": "^3.1.
|
|
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-
|
|
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.
|
|
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.
|
|
118
|
-
"@sanity/types": "^3.88.
|
|
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
|
|
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 {
|
|
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'
|
|
@@ -444,48 +444,69 @@ async function updateValue({
|
|
|
444
444
|
schemaTypes: context.schema,
|
|
445
445
|
})
|
|
446
446
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
447
|
+
if (streamBlocks) {
|
|
448
|
+
await new Promise<void>((resolve) => {
|
|
449
|
+
Editor.withoutNormalizing(slateEditor, () => {
|
|
450
|
+
withRemoteChanges(slateEditor, () => {
|
|
451
|
+
withoutPatching(slateEditor, async () => {
|
|
452
|
+
isChanged = removeExtraBlocks({
|
|
453
|
+
slateEditor,
|
|
454
|
+
slateValueFromProps,
|
|
455
|
+
})
|
|
452
456
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
457
|
+
for await (const [
|
|
458
|
+
currentBlock,
|
|
459
|
+
currentBlockIndex,
|
|
460
|
+
] of getStreamedBlocks({
|
|
461
|
+
slateValue: slateValueFromProps,
|
|
462
|
+
})) {
|
|
463
|
+
const {blockChanged, blockValid} = syncBlock({
|
|
464
|
+
context,
|
|
465
|
+
sendBack,
|
|
466
|
+
block: currentBlock,
|
|
467
|
+
index: currentBlockIndex,
|
|
468
|
+
slateEditor,
|
|
469
|
+
value,
|
|
462
470
|
})
|
|
471
|
+
|
|
472
|
+
isChanged = blockChanged || isChanged
|
|
473
|
+
isValid = isValid && blockValid
|
|
463
474
|
}
|
|
464
|
-
isChanged = true
|
|
465
|
-
}
|
|
466
475
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
476
|
+
resolve()
|
|
477
|
+
})
|
|
478
|
+
})
|
|
479
|
+
})
|
|
480
|
+
})
|
|
481
|
+
} else {
|
|
482
|
+
Editor.withoutNormalizing(slateEditor, () => {
|
|
483
|
+
withRemoteChanges(slateEditor, () => {
|
|
484
|
+
withoutPatching(slateEditor, () => {
|
|
485
|
+
isChanged = removeExtraBlocks({
|
|
486
|
+
slateEditor,
|
|
487
|
+
slateValueFromProps,
|
|
488
|
+
})
|
|
489
|
+
|
|
490
|
+
let index = 0
|
|
491
|
+
|
|
492
|
+
for (const currentBlock of slateValueFromProps) {
|
|
472
493
|
const {blockChanged, blockValid} = syncBlock({
|
|
473
494
|
context,
|
|
474
495
|
sendBack,
|
|
475
496
|
block: currentBlock,
|
|
476
|
-
index
|
|
497
|
+
index,
|
|
477
498
|
slateEditor,
|
|
478
499
|
value,
|
|
479
500
|
})
|
|
501
|
+
|
|
480
502
|
isChanged = blockChanged || isChanged
|
|
481
503
|
isValid = isValid && blockValid
|
|
504
|
+
index++
|
|
482
505
|
}
|
|
483
|
-
|
|
484
|
-
resolve()
|
|
485
506
|
})
|
|
486
507
|
})
|
|
487
508
|
})
|
|
488
|
-
}
|
|
509
|
+
}
|
|
489
510
|
}
|
|
490
511
|
|
|
491
512
|
if (!isValid) {
|
|
@@ -523,16 +544,36 @@ async function updateValue({
|
|
|
523
544
|
sendBack({type: 'done syncing', value})
|
|
524
545
|
}
|
|
525
546
|
|
|
526
|
-
|
|
547
|
+
function removeExtraBlocks({
|
|
548
|
+
slateEditor,
|
|
549
|
+
slateValueFromProps,
|
|
550
|
+
}: {
|
|
551
|
+
slateEditor: PortableTextSlateEditor
|
|
552
|
+
slateValueFromProps: Array<Descendant>
|
|
553
|
+
}) {
|
|
554
|
+
let isChanged = false
|
|
555
|
+
const childrenLength = slateEditor.children.length
|
|
556
|
+
|
|
557
|
+
// Remove blocks that have become superfluous
|
|
558
|
+
if (slateValueFromProps.length < childrenLength) {
|
|
559
|
+
for (let i = childrenLength - 1; i > slateValueFromProps.length - 1; i--) {
|
|
560
|
+
Transforms.removeNodes(slateEditor, {
|
|
561
|
+
at: [i],
|
|
562
|
+
})
|
|
563
|
+
}
|
|
564
|
+
isChanged = true
|
|
565
|
+
}
|
|
566
|
+
return isChanged
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
async function* getStreamedBlocks({
|
|
527
570
|
slateValue,
|
|
528
|
-
streamBlocks,
|
|
529
571
|
}: {
|
|
530
572
|
slateValue: Array<Descendant>
|
|
531
|
-
streamBlocks: boolean
|
|
532
573
|
}) {
|
|
533
574
|
let index = 0
|
|
534
575
|
for await (const block of slateValue) {
|
|
535
|
-
if (
|
|
576
|
+
if (index % 10 === 0) {
|
|
536
577
|
await new Promise<void>((resolve) => setTimeout(resolve, 0))
|
|
537
578
|
}
|
|
538
579
|
yield [block, index] as const
|
|
@@ -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
|
|
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
|
|
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',
|
|
@@ -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
|
|
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,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
|
|
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
|
/**
|