@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.10.0",
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-a7bf2bd-20241110",
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-a7bf2bd-20241110",
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-a7bf2bd-20241110",
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
- (TEditor extends Editor
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
- * 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
- }
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
- if (this.props.editorRef !== prevProps.editorRef && this.props.editorRef) {
231
- this.props.editorRef.current = this
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 {editorActor, getValue, onChange, value} = props
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
  },
@@ -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})