@portabletext/editor 1.50.3 → 1.50.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/behaviors/index.d.cts +1 -0
- package/lib/behaviors/index.d.ts +1 -0
- package/lib/index.cjs +322 -55
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +2 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +323 -55
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.cts +1 -0
- package/lib/plugins/index.d.ts +1 -0
- package/lib/selectors/index.d.cts +1 -0
- package/lib/selectors/index.d.ts +1 -0
- package/lib/utils/index.d.cts +1 -0
- package/lib/utils/index.d.ts +1 -0
- package/package.json +2 -1
- package/src/editor/PortableTextEditor.tsx +22 -22
- package/src/editor/create-slate-editor.tsx +9 -1
- package/src/editor/editor-selector.ts +1 -5
- package/src/editor/editor-snapshot.ts +1 -3
- package/src/editor/plugins/slate-plugin.update-value.ts +30 -0
- package/src/editor/plugins/with-plugins.ts +8 -1
- package/src/internal-utils/apply-operation-to-portable-text.test.ts +175 -0
- package/src/internal-utils/apply-operation-to-portable-text.ts +435 -0
- package/src/internal-utils/create-placeholder-block.ts +20 -0
- package/src/internal-utils/portable-text-node.ts +209 -0
- package/src/types/editor.ts +1 -0
- package/src/internal-utils/__tests__/patchToOperations.test.ts +0 -312
- package/src/internal-utils/slate-children-to-blocks.ts +0 -49
package/lib/plugins/index.d.cts
CHANGED
|
@@ -2950,6 +2950,7 @@ declare interface PortableTextSlateEditor extends ReactEditor {
|
|
|
2950
2950
|
isTextBlock: (value: unknown) => value is PortableTextTextBlock
|
|
2951
2951
|
isTextSpan: (value: unknown) => value is PortableTextSpan
|
|
2952
2952
|
isListBlock: (value: unknown) => value is PortableTextListBlock
|
|
2953
|
+
value: Array<PortableTextBlock>
|
|
2953
2954
|
/**
|
|
2954
2955
|
* Use hotkeys
|
|
2955
2956
|
*/
|
package/lib/plugins/index.d.ts
CHANGED
|
@@ -2950,6 +2950,7 @@ declare interface PortableTextSlateEditor extends ReactEditor {
|
|
|
2950
2950
|
isTextBlock: (value: unknown) => value is PortableTextTextBlock
|
|
2951
2951
|
isTextSpan: (value: unknown) => value is PortableTextSpan
|
|
2952
2952
|
isListBlock: (value: unknown) => value is PortableTextListBlock
|
|
2953
|
+
value: Array<PortableTextBlock>
|
|
2953
2954
|
/**
|
|
2954
2955
|
* Use hotkeys
|
|
2955
2956
|
*/
|
|
@@ -3049,6 +3049,7 @@ declare interface PortableTextSlateEditor extends ReactEditor {
|
|
|
3049
3049
|
isTextBlock: (value: unknown) => value is PortableTextTextBlock
|
|
3050
3050
|
isTextSpan: (value: unknown) => value is PortableTextSpan
|
|
3051
3051
|
isListBlock: (value: unknown) => value is PortableTextListBlock
|
|
3052
|
+
value: Array<PortableTextBlock>
|
|
3052
3053
|
/**
|
|
3053
3054
|
* Use hotkeys
|
|
3054
3055
|
*/
|
package/lib/selectors/index.d.ts
CHANGED
|
@@ -3049,6 +3049,7 @@ declare interface PortableTextSlateEditor extends ReactEditor {
|
|
|
3049
3049
|
isTextBlock: (value: unknown) => value is PortableTextTextBlock
|
|
3050
3050
|
isTextSpan: (value: unknown) => value is PortableTextSpan
|
|
3051
3051
|
isListBlock: (value: unknown) => value is PortableTextListBlock
|
|
3052
|
+
value: Array<PortableTextBlock>
|
|
3052
3053
|
/**
|
|
3053
3054
|
* Use hotkeys
|
|
3054
3055
|
*/
|
package/lib/utils/index.d.cts
CHANGED
|
@@ -2810,6 +2810,7 @@ declare interface PortableTextSlateEditor extends ReactEditor {
|
|
|
2810
2810
|
isTextBlock: (value: unknown) => value is PortableTextTextBlock
|
|
2811
2811
|
isTextSpan: (value: unknown) => value is PortableTextSpan
|
|
2812
2812
|
isListBlock: (value: unknown) => value is PortableTextListBlock
|
|
2813
|
+
value: Array<PortableTextBlock>
|
|
2813
2814
|
/**
|
|
2814
2815
|
* Use hotkeys
|
|
2815
2816
|
*/
|
package/lib/utils/index.d.ts
CHANGED
|
@@ -2810,6 +2810,7 @@ declare interface PortableTextSlateEditor extends ReactEditor {
|
|
|
2810
2810
|
isTextBlock: (value: unknown) => value is PortableTextTextBlock
|
|
2811
2811
|
isTextSpan: (value: unknown) => value is PortableTextSpan
|
|
2812
2812
|
isListBlock: (value: unknown) => value is PortableTextListBlock
|
|
2813
|
+
value: Array<PortableTextBlock>
|
|
2813
2814
|
/**
|
|
2814
2815
|
* Use hotkeys
|
|
2815
2816
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "1.50.
|
|
3
|
+
"version": "1.50.4",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"@xstate/react": "^5.0.4",
|
|
72
72
|
"debug": "^4.4.1",
|
|
73
73
|
"get-random-values-esm": "^1.0.2",
|
|
74
|
+
"immer": "^10.1.1",
|
|
74
75
|
"lodash": "^4.17.21",
|
|
75
76
|
"lodash.startcase": "^4.4.0",
|
|
76
77
|
"react-compiler-runtime": "19.1.0-rc.1",
|
|
@@ -138,6 +138,7 @@ export class PortableTextEditor extends Component<
|
|
|
138
138
|
syncActor: SyncActor
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
private subscriptions: Array<() => () => void> = []
|
|
141
142
|
private unsubscribers: Array<() => void> = []
|
|
142
143
|
|
|
143
144
|
constructor(props: PortableTextEditorProps) {
|
|
@@ -160,28 +161,7 @@ export class PortableTextEditor extends Component<
|
|
|
160
161
|
schema: props.schemaType,
|
|
161
162
|
})
|
|
162
163
|
|
|
163
|
-
this.
|
|
164
|
-
(() => {
|
|
165
|
-
const subscription = actors.relayActor.on('*', (event) => {
|
|
166
|
-
const change = eventToChange(event)
|
|
167
|
-
|
|
168
|
-
if (change) {
|
|
169
|
-
props.onChange(change)
|
|
170
|
-
|
|
171
|
-
this.change$.next(change)
|
|
172
|
-
}
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
return () => {
|
|
176
|
-
subscription.unsubscribe()
|
|
177
|
-
}
|
|
178
|
-
})(),
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
for (const subscription of subscriptions) {
|
|
182
|
-
this.unsubscribers.push(subscription())
|
|
183
|
-
}
|
|
184
|
-
|
|
164
|
+
this.subscriptions = subscriptions
|
|
185
165
|
this.actors = actors
|
|
186
166
|
|
|
187
167
|
this.editor = editor
|
|
@@ -198,6 +178,26 @@ export class PortableTextEditor extends Component<
|
|
|
198
178
|
return
|
|
199
179
|
}
|
|
200
180
|
|
|
181
|
+
for (const subscription of this.subscriptions) {
|
|
182
|
+
this.unsubscribers.push(subscription())
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const relayActorSubscription = this.actors.relayActor.on('*', (event) => {
|
|
186
|
+
const change = eventToChange(event)
|
|
187
|
+
|
|
188
|
+
if (!change) {
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!this.props.editor) {
|
|
193
|
+
this.props.onChange(change)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
this.change$.next(change)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
this.unsubscribers.push(relayActorSubscription.unsubscribe)
|
|
200
|
+
|
|
201
201
|
this.actors.editorActor.start()
|
|
202
202
|
this.actors.mutationActor.start()
|
|
203
203
|
this.actors.relayActor.start()
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {createEditor, type Descendant} from 'slate'
|
|
2
2
|
import {withReact} from 'slate-react'
|
|
3
|
+
import {createPlaceholderBlock} from '../internal-utils/create-placeholder-block'
|
|
3
4
|
import {debugWithName} from '../internal-utils/debug'
|
|
5
|
+
import {toSlateValue} from '../internal-utils/values'
|
|
4
6
|
import {
|
|
5
7
|
KEY_TO_SLATE_ELEMENT,
|
|
6
8
|
KEY_TO_VALUE_ELEMENT,
|
|
@@ -35,7 +37,13 @@ export function createSlateEditor(config: SlateEditorConfig): SlateEditor {
|
|
|
35
37
|
KEY_TO_VALUE_ELEMENT.set(instance, {})
|
|
36
38
|
KEY_TO_SLATE_ELEMENT.set(instance, {})
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
instance.value = [
|
|
41
|
+
createPlaceholderBlock(config.editorActor.getSnapshot().context),
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
const initialValue = toSlateValue(instance.value, {
|
|
45
|
+
schemaTypes: config.editorActor.getSnapshot().context.schema,
|
|
46
|
+
})
|
|
39
47
|
|
|
40
48
|
const slateEditor: SlateEditor = {
|
|
41
49
|
instance,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {useSelector} from '@xstate/react'
|
|
2
2
|
import type {Editor} from '../editor'
|
|
3
|
-
import {slateChildrenToBlocks} from '../internal-utils/slate-children-to-blocks'
|
|
4
3
|
import type {PortableTextSlateEditor} from '../types/editor'
|
|
5
4
|
import type {InternalEditor} from './create-editor'
|
|
6
5
|
import type {EditorActor} from './editor-machine'
|
|
@@ -78,10 +77,7 @@ export function getEditorSnapshot({
|
|
|
78
77
|
readOnly: editorActorSnapshot.matches({'edit mode': 'read only'}),
|
|
79
78
|
schema: editorActorSnapshot.context.schema,
|
|
80
79
|
selection: editorActorSnapshot.context.selection,
|
|
81
|
-
value:
|
|
82
|
-
editorActorSnapshot.context.schema,
|
|
83
|
-
slateEditorInstance.children,
|
|
84
|
-
),
|
|
80
|
+
value: slateEditorInstance.value,
|
|
85
81
|
},
|
|
86
82
|
beta: {
|
|
87
83
|
hasTag: (tag) => editorActorSnapshot.hasTag(tag),
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type {PortableTextBlock} from '@sanity/types'
|
|
2
2
|
import type {Converter} from '../converters/converter.types'
|
|
3
3
|
import type {EventPosition} from '../internal-utils/event-position'
|
|
4
|
-
import {slateChildrenToBlocks} from '../internal-utils/slate-children-to-blocks'
|
|
5
4
|
import {slateRangeToSelection} from '../internal-utils/slate-utils'
|
|
6
5
|
import type {EditorSelection, PortableTextSlateEditor} from '../types/editor'
|
|
7
6
|
import type {HasTag} from './editor-machine'
|
|
@@ -61,7 +60,6 @@ export function createEditorSnapshot({
|
|
|
61
60
|
}
|
|
62
61
|
| undefined
|
|
63
62
|
}) {
|
|
64
|
-
const value = slateChildrenToBlocks(schema, editor.children)
|
|
65
63
|
const selection = editor.selection
|
|
66
64
|
? slateRangeToSelection({
|
|
67
65
|
schema,
|
|
@@ -80,7 +78,7 @@ export function createEditorSnapshot({
|
|
|
80
78
|
readOnly,
|
|
81
79
|
schema,
|
|
82
80
|
selection,
|
|
83
|
-
value,
|
|
81
|
+
value: editor.value,
|
|
84
82
|
} satisfies EditorContext
|
|
85
83
|
|
|
86
84
|
return {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {applyOperationToPortableText} from '../../internal-utils/apply-operation-to-portable-text'
|
|
2
|
+
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
3
|
+
import type {EditorContext} from '../editor-snapshot'
|
|
4
|
+
|
|
5
|
+
export function pluginUpdateValue(
|
|
6
|
+
context: Pick<EditorContext, 'keyGenerator' | 'schema'>,
|
|
7
|
+
editor: PortableTextSlateEditor,
|
|
8
|
+
) {
|
|
9
|
+
const {apply} = editor
|
|
10
|
+
|
|
11
|
+
editor.apply = (operation) => {
|
|
12
|
+
if (operation.type === 'set_selection') {
|
|
13
|
+
apply(operation)
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
editor.value = applyOperationToPortableText(
|
|
18
|
+
{
|
|
19
|
+
keyGenerator: context.keyGenerator,
|
|
20
|
+
schema: context.schema,
|
|
21
|
+
},
|
|
22
|
+
editor.value,
|
|
23
|
+
operation,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
apply(operation)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return editor
|
|
30
|
+
}
|
|
@@ -13,6 +13,7 @@ import {createWithPortableTextSelections} from './createWithPortableTextSelectio
|
|
|
13
13
|
import {createWithSchemaTypes} from './createWithSchemaTypes'
|
|
14
14
|
import {createWithUndoRedo} from './createWithUndoRedo'
|
|
15
15
|
import {createWithUtils} from './createWithUtils'
|
|
16
|
+
import {pluginUpdateValue} from './slate-plugin.update-value'
|
|
16
17
|
|
|
17
18
|
export interface OriginalEditorFunctions {
|
|
18
19
|
apply: (operation: BaseOperation) => void
|
|
@@ -68,7 +69,13 @@ export const withPlugins = <T extends Editor>(
|
|
|
68
69
|
withPlaceholderBlock(
|
|
69
70
|
withUtils(
|
|
70
71
|
withMaxBlocks(
|
|
71
|
-
withUndoRedo(
|
|
72
|
+
withUndoRedo(
|
|
73
|
+
withPatches(
|
|
74
|
+
withPortableTextSelections(
|
|
75
|
+
pluginUpdateValue(editorActor.getSnapshot().context, e),
|
|
76
|
+
),
|
|
77
|
+
),
|
|
78
|
+
),
|
|
72
79
|
),
|
|
73
80
|
),
|
|
74
81
|
),
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import {describe, expect, test} from 'vitest'
|
|
2
|
+
import {compileSchemaDefinition, defineSchema} from '../editor/editor-schema'
|
|
3
|
+
import {applyOperationToPortableText} from './apply-operation-to-portable-text'
|
|
4
|
+
import {createTestKeyGenerator} from './test-key-generator'
|
|
5
|
+
|
|
6
|
+
function createContext() {
|
|
7
|
+
const keyGenerator = createTestKeyGenerator()
|
|
8
|
+
const schema = compileSchemaDefinition(defineSchema({}))
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
keyGenerator,
|
|
12
|
+
schema,
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe(applyOperationToPortableText.name, () => {
|
|
17
|
+
test('setting block object properties', () => {
|
|
18
|
+
expect(
|
|
19
|
+
applyOperationToPortableText(
|
|
20
|
+
createContext(),
|
|
21
|
+
[
|
|
22
|
+
{
|
|
23
|
+
_type: 'image',
|
|
24
|
+
_key: 'k0',
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
{
|
|
28
|
+
type: 'set_node',
|
|
29
|
+
path: [0],
|
|
30
|
+
properties: {},
|
|
31
|
+
newProperties: {
|
|
32
|
+
value: {src: 'https://example.com/image.jpg'},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
),
|
|
36
|
+
).toEqual([
|
|
37
|
+
{
|
|
38
|
+
_type: 'image',
|
|
39
|
+
_key: 'k0',
|
|
40
|
+
src: 'https://example.com/image.jpg',
|
|
41
|
+
},
|
|
42
|
+
])
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('updating block object properties', () => {
|
|
46
|
+
expect(
|
|
47
|
+
applyOperationToPortableText(
|
|
48
|
+
createContext(),
|
|
49
|
+
[
|
|
50
|
+
{
|
|
51
|
+
_type: 'image',
|
|
52
|
+
_key: 'k0',
|
|
53
|
+
src: 'https://example.com/image.jpg',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
{
|
|
57
|
+
type: 'set_node',
|
|
58
|
+
path: [0],
|
|
59
|
+
properties: {
|
|
60
|
+
value: {src: 'https://example.com/image.jpg'},
|
|
61
|
+
},
|
|
62
|
+
newProperties: {
|
|
63
|
+
value: {
|
|
64
|
+
src: 'https://example.com/image.jpg',
|
|
65
|
+
alt: 'An image',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
),
|
|
70
|
+
).toEqual([
|
|
71
|
+
{
|
|
72
|
+
_type: 'image',
|
|
73
|
+
_key: 'k0',
|
|
74
|
+
src: 'https://example.com/image.jpg',
|
|
75
|
+
alt: 'An image',
|
|
76
|
+
},
|
|
77
|
+
])
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('removing block object properties', () => {
|
|
81
|
+
expect(
|
|
82
|
+
applyOperationToPortableText(
|
|
83
|
+
createContext(),
|
|
84
|
+
[{_type: 'image', _key: 'k0', alt: 'An image'}],
|
|
85
|
+
{
|
|
86
|
+
type: 'set_node',
|
|
87
|
+
path: [0],
|
|
88
|
+
properties: {
|
|
89
|
+
value: {
|
|
90
|
+
alt: 'An image',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
newProperties: {value: {}},
|
|
94
|
+
},
|
|
95
|
+
),
|
|
96
|
+
).toEqual([{_type: 'image', _key: 'k0'}])
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('updating block object _key', () => {
|
|
100
|
+
expect(
|
|
101
|
+
applyOperationToPortableText(
|
|
102
|
+
createContext(),
|
|
103
|
+
[
|
|
104
|
+
{
|
|
105
|
+
_type: 'image',
|
|
106
|
+
_key: 'k0',
|
|
107
|
+
src: 'https://example.com/image.jpg',
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
{
|
|
111
|
+
type: 'set_node',
|
|
112
|
+
path: [0],
|
|
113
|
+
properties: {_key: 'k0'},
|
|
114
|
+
newProperties: {_key: 'k1'},
|
|
115
|
+
},
|
|
116
|
+
),
|
|
117
|
+
).toEqual([
|
|
118
|
+
{
|
|
119
|
+
_type: 'image',
|
|
120
|
+
_key: 'k1',
|
|
121
|
+
src: 'https://example.com/image.jpg',
|
|
122
|
+
},
|
|
123
|
+
])
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('updating inline object properties', () => {
|
|
127
|
+
expect(
|
|
128
|
+
applyOperationToPortableText(
|
|
129
|
+
createContext(),
|
|
130
|
+
[
|
|
131
|
+
{
|
|
132
|
+
_key: 'k0',
|
|
133
|
+
_type: 'block',
|
|
134
|
+
children: [
|
|
135
|
+
{
|
|
136
|
+
_key: 'k1',
|
|
137
|
+
_type: 'span',
|
|
138
|
+
text: '',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
_key: 'k2',
|
|
142
|
+
_type: 'stock ticker',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
_key: 'k3',
|
|
146
|
+
_type: 'span',
|
|
147
|
+
text: '',
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
{
|
|
153
|
+
type: 'set_node',
|
|
154
|
+
path: [0, 1],
|
|
155
|
+
properties: {},
|
|
156
|
+
newProperties: {
|
|
157
|
+
value: {
|
|
158
|
+
symbol: 'AAPL',
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
),
|
|
163
|
+
).toEqual([
|
|
164
|
+
{
|
|
165
|
+
_type: 'block',
|
|
166
|
+
_key: 'k0',
|
|
167
|
+
children: [
|
|
168
|
+
{_type: 'span', _key: 'k1', text: ''},
|
|
169
|
+
{_type: 'stock ticker', _key: 'k2', symbol: 'AAPL'},
|
|
170
|
+
{_type: 'span', _key: 'k3', text: ''},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
])
|
|
174
|
+
})
|
|
175
|
+
})
|