@portabletext/editor 1.10.0 → 1.10.2
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/README.md +21 -6
- package/lib/index.d.mts +163 -653
- package/lib/index.d.ts +163 -653
- package/lib/index.esm.js +48 -91
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +47 -90
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +48 -91
- package/lib/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/editor/PortableTextEditor.tsx +26 -16
- package/src/editor/components/Synchronizer.tsx +2 -25
- package/src/editor/editor-machine.ts +8 -29
- package/src/editor/use-editor.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.2",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"is-hotkey-esm": "^1.0.0",
|
|
50
50
|
"lodash": "^4.17.21",
|
|
51
51
|
"lodash.startcase": "^4.4.0",
|
|
52
|
-
"react-compiler-runtime": "19.0.0-beta-
|
|
52
|
+
"react-compiler-runtime": "19.0.0-beta-0dec889-20241115",
|
|
53
53
|
"slate": "0.110.2",
|
|
54
54
|
"slate-dom": "^0.111.0",
|
|
55
55
|
"slate-react": "0.111.0",
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"@typescript-eslint/parser": "^8.14.0",
|
|
75
75
|
"@vitejs/plugin-react": "^4.3.3",
|
|
76
76
|
"@vitest/browser": "^2.1.5",
|
|
77
|
-
"babel-plugin-react-compiler": "19.0.0-beta-
|
|
77
|
+
"babel-plugin-react-compiler": "19.0.0-beta-0dec889-20241115",
|
|
78
78
|
"eslint": "8.57.1",
|
|
79
|
-
"eslint-plugin-react-compiler": "19.0.0-beta-
|
|
79
|
+
"eslint-plugin-react-compiler": "19.0.0-beta-0dec889-20241115",
|
|
80
80
|
"eslint-plugin-react-hooks": "^5.0.0",
|
|
81
81
|
"jsdom": "^25.0.1",
|
|
82
82
|
"react": "^18.3.1",
|
|
@@ -50,7 +50,7 @@ const debug = debugWithName('component:PortableTextEditor')
|
|
|
50
50
|
export type PortableTextEditorProps<
|
|
51
51
|
TEditor extends Editor | undefined = undefined,
|
|
52
52
|
> = PropsWithChildren<
|
|
53
|
-
|
|
53
|
+
TEditor extends Editor
|
|
54
54
|
? {
|
|
55
55
|
/**
|
|
56
56
|
* @alpha
|
|
@@ -94,17 +94,17 @@ export type PortableTextEditorProps<
|
|
|
94
94
|
* Whether or not the editor should be in read-only mode
|
|
95
95
|
*/
|
|
96
96
|
readOnly?: boolean
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The current value of the portable text field
|
|
100
|
+
*/
|
|
101
|
+
value?: PortableTextBlock[]
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* A ref to the editor instance
|
|
105
|
+
*/
|
|
106
|
+
editorRef?: MutableRefObject<PortableTextEditor | null>
|
|
107
|
+
}
|
|
108
108
|
>
|
|
109
109
|
|
|
110
110
|
/**
|
|
@@ -160,6 +160,7 @@ export class PortableTextEditor extends Component<
|
|
|
160
160
|
input: {
|
|
161
161
|
keyGenerator: props.keyGenerator || defaultKeyGenerator,
|
|
162
162
|
schema: this.schemaTypes,
|
|
163
|
+
value: props.value,
|
|
163
164
|
},
|
|
164
165
|
})
|
|
165
166
|
this.editorActor.start()
|
|
@@ -225,10 +226,20 @@ export class PortableTextEditor extends Component<
|
|
|
225
226
|
: Number.parseInt(this.props.maxBlocks.toString(), 10),
|
|
226
227
|
})
|
|
227
228
|
}
|
|
228
|
-
}
|
|
229
229
|
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
if (this.props.value !== prevProps.value) {
|
|
231
|
+
this.editorActor.send({
|
|
232
|
+
type: 'update value',
|
|
233
|
+
value: this.props.value,
|
|
234
|
+
})
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (
|
|
238
|
+
this.props.editorRef !== prevProps.editorRef &&
|
|
239
|
+
this.props.editorRef
|
|
240
|
+
) {
|
|
241
|
+
this.props.editorRef.current = this
|
|
242
|
+
}
|
|
232
243
|
}
|
|
233
244
|
}
|
|
234
245
|
|
|
@@ -279,7 +290,6 @@ export class PortableTextEditor extends Component<
|
|
|
279
290
|
*/
|
|
280
291
|
this.change$.next(change)
|
|
281
292
|
}}
|
|
282
|
-
value={this.props.value}
|
|
283
293
|
/>
|
|
284
294
|
{this.props.children}
|
|
285
295
|
</PortableTextEditorSelectionProvider>
|
|
@@ -27,7 +27,6 @@ export interface SynchronizerProps {
|
|
|
27
27
|
editorActor: EditorActor
|
|
28
28
|
getValue: () => Array<PortableTextBlock> | undefined
|
|
29
29
|
onChange: (change: EditorChange) => void
|
|
30
|
-
value: Array<PortableTextBlock> | undefined
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
/**
|
|
@@ -37,7 +36,8 @@ export interface SynchronizerProps {
|
|
|
37
36
|
export function Synchronizer(props: SynchronizerProps) {
|
|
38
37
|
const portableTextEditor = usePortableTextEditor()
|
|
39
38
|
const readOnly = useSelector(props.editorActor, (s) => s.context.readOnly)
|
|
40
|
-
const
|
|
39
|
+
const value = useSelector(props.editorActor, (s) => s.context.value)
|
|
40
|
+
const {editorActor, getValue, onChange} = props
|
|
41
41
|
const pendingPatches = useRef<Patch[]>([])
|
|
42
42
|
|
|
43
43
|
const syncValue = useSyncValue({
|
|
@@ -125,14 +125,6 @@ export function Synchronizer(props: SynchronizerProps) {
|
|
|
125
125
|
handleChange({type: 'focus', event: event.event})
|
|
126
126
|
break
|
|
127
127
|
}
|
|
128
|
-
case 'offline': {
|
|
129
|
-
handleChange({type: 'connection', value: 'offline'})
|
|
130
|
-
break
|
|
131
|
-
}
|
|
132
|
-
case 'online': {
|
|
133
|
-
handleChange({type: 'connection', value: 'online'})
|
|
134
|
-
break
|
|
135
|
-
}
|
|
136
128
|
case 'value changed': {
|
|
137
129
|
handleChange({type: 'value', value: event.value})
|
|
138
130
|
break
|
|
@@ -168,21 +160,6 @@ export function Synchronizer(props: SynchronizerProps) {
|
|
|
168
160
|
}
|
|
169
161
|
}, [editorActor, handleChange, onFlushPendingPatches, slateEditor])
|
|
170
162
|
|
|
171
|
-
// Sync the value when going online
|
|
172
|
-
const handleOnline = useCallback(() => {
|
|
173
|
-
debug('Editor is online, syncing from props.value')
|
|
174
|
-
syncValue(value)
|
|
175
|
-
}, [syncValue, value])
|
|
176
|
-
|
|
177
|
-
// Notify about window online and offline status changes
|
|
178
|
-
useEffect(() => {
|
|
179
|
-
const subscription = editorActor.on('online', handleOnline)
|
|
180
|
-
|
|
181
|
-
return () => {
|
|
182
|
-
subscription.unsubscribe()
|
|
183
|
-
}
|
|
184
|
-
}, [handleOnline, editorActor])
|
|
185
|
-
|
|
186
163
|
// This hook must be set up after setting up the subscription above, or it will not pick up validation errors from the useSyncValue hook.
|
|
187
164
|
// This will cause the editor to not be able to signal a validation error and offer invalid value resolution of the initial value.
|
|
188
165
|
const isInitialValueFromProps = useRef(true)
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
assign,
|
|
8
8
|
emit,
|
|
9
9
|
enqueueActions,
|
|
10
|
-
fromCallback,
|
|
11
10
|
setup,
|
|
12
11
|
type ActorRefFrom,
|
|
13
12
|
} from 'xstate'
|
|
@@ -38,23 +37,6 @@ export * from 'xstate/guards'
|
|
|
38
37
|
*/
|
|
39
38
|
export type EditorActor = ActorRefFrom<typeof editorMachine>
|
|
40
39
|
|
|
41
|
-
const networkLogic = fromCallback(({sendBack}) => {
|
|
42
|
-
const onlineHandler = () => {
|
|
43
|
-
sendBack({type: 'online'})
|
|
44
|
-
}
|
|
45
|
-
const offlineHandler = () => {
|
|
46
|
-
sendBack({type: 'offline'})
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
window.addEventListener('online', onlineHandler)
|
|
50
|
-
window.addEventListener('offline', offlineHandler)
|
|
51
|
-
|
|
52
|
-
return () => {
|
|
53
|
-
window.removeEventListener('online', onlineHandler)
|
|
54
|
-
window.removeEventListener('offline', offlineHandler)
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
|
|
58
40
|
/**
|
|
59
41
|
* @internal
|
|
60
42
|
*/
|
|
@@ -102,6 +84,10 @@ export type InternalEditorEvent =
|
|
|
102
84
|
type: 'update behaviors'
|
|
103
85
|
behaviors: Array<Behavior>
|
|
104
86
|
}
|
|
87
|
+
| {
|
|
88
|
+
type: 'update value'
|
|
89
|
+
value: Array<PortableTextBlock> | undefined
|
|
90
|
+
}
|
|
105
91
|
| {
|
|
106
92
|
type: 'toggle readOnly'
|
|
107
93
|
}
|
|
@@ -141,8 +127,6 @@ export type InternalEditorEmittedEvent =
|
|
|
141
127
|
| {type: 'selection'; selection: EditorSelection}
|
|
142
128
|
| {type: 'blur'; event: FocusEvent<HTMLDivElement, Element>}
|
|
143
129
|
| {type: 'focused'; event: FocusEvent<HTMLDivElement, Element>}
|
|
144
|
-
| {type: 'online'}
|
|
145
|
-
| {type: 'offline'}
|
|
146
130
|
| {type: 'loading'}
|
|
147
131
|
| {type: 'done loading'}
|
|
148
132
|
| PickFromUnion<
|
|
@@ -163,6 +147,7 @@ export const editorMachine = setup({
|
|
|
163
147
|
schema: PortableTextMemberSchemaTypes
|
|
164
148
|
readOnly: boolean
|
|
165
149
|
maxBlocks: number | undefined
|
|
150
|
+
value: Array<PortableTextBlock> | undefined
|
|
166
151
|
},
|
|
167
152
|
events: {} as InternalEditorEvent,
|
|
168
153
|
emitted: {} as InternalEditorEmittedEvent,
|
|
@@ -170,6 +155,7 @@ export const editorMachine = setup({
|
|
|
170
155
|
behaviors?: Array<Behavior>
|
|
171
156
|
keyGenerator: () => string
|
|
172
157
|
schema: PortableTextMemberSchemaTypes
|
|
158
|
+
value?: Array<PortableTextBlock>
|
|
173
159
|
},
|
|
174
160
|
},
|
|
175
161
|
actions: {
|
|
@@ -303,9 +289,6 @@ export const editorMachine = setup({
|
|
|
303
289
|
}
|
|
304
290
|
}),
|
|
305
291
|
},
|
|
306
|
-
actors: {
|
|
307
|
-
networkLogic,
|
|
308
|
-
},
|
|
309
292
|
}).createMachine({
|
|
310
293
|
id: 'editor',
|
|
311
294
|
context: ({input}) => ({
|
|
@@ -315,11 +298,8 @@ export const editorMachine = setup({
|
|
|
315
298
|
schema: input.schema,
|
|
316
299
|
readOnly: false,
|
|
317
300
|
maxBlocks: undefined,
|
|
301
|
+
value: input.value,
|
|
318
302
|
}),
|
|
319
|
-
invoke: {
|
|
320
|
-
id: 'networkLogic',
|
|
321
|
-
src: 'networkLogic',
|
|
322
|
-
},
|
|
323
303
|
on: {
|
|
324
304
|
'annotation.add': {
|
|
325
305
|
actions: emit(({event}) => event),
|
|
@@ -345,13 +325,12 @@ export const editorMachine = setup({
|
|
|
345
325
|
'selection': {actions: emit(({event}) => event)},
|
|
346
326
|
'blur': {actions: emit(({event}) => event)},
|
|
347
327
|
'focused': {actions: emit(({event}) => event)},
|
|
348
|
-
'online': {actions: emit({type: 'online'})},
|
|
349
|
-
'offline': {actions: emit({type: 'offline'})},
|
|
350
328
|
'loading': {actions: emit({type: 'loading'})},
|
|
351
329
|
'patches': {actions: emit(({event}) => event)},
|
|
352
330
|
'done loading': {actions: emit({type: 'done loading'})},
|
|
353
331
|
'update behaviors': {actions: 'assign behaviors'},
|
|
354
332
|
'update schema': {actions: 'assign schema'},
|
|
333
|
+
'update value': {actions: assign({value: ({event}) => event.value})},
|
|
355
334
|
'toggle readOnly': {
|
|
356
335
|
actions: assign({readOnly: ({context}) => !context.readOnly}),
|
|
357
336
|
},
|
package/src/editor/use-editor.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {defaultKeyGenerator} from './key-generator'
|
|
|
22
22
|
export type EditorConfig = {
|
|
23
23
|
behaviors?: Array<Behavior>
|
|
24
24
|
keyGenerator?: () => string
|
|
25
|
+
initialValue?: Array<PortableTextBlock>
|
|
25
26
|
} & (
|
|
26
27
|
| {
|
|
27
28
|
schemaDefinition: SchemaDefinition
|
|
@@ -44,6 +45,7 @@ export type EditorEvent = PickFromUnion<
|
|
|
44
45
|
| 'patches'
|
|
45
46
|
| 'toggle readOnly'
|
|
46
47
|
| 'update behaviors'
|
|
48
|
+
| 'update value'
|
|
47
49
|
>
|
|
48
50
|
|
|
49
51
|
/**
|
|
@@ -74,6 +76,7 @@ export function useEditor(config: EditorConfig): Editor {
|
|
|
74
76
|
? config.schema
|
|
75
77
|
: compileType(config.schema),
|
|
76
78
|
),
|
|
79
|
+
value: config.initialValue,
|
|
77
80
|
},
|
|
78
81
|
})
|
|
79
82
|
const slateEditor = createSlateEditor({editorActor})
|