@portabletext/editor 1.0.11 → 1.0.13

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.
@@ -51,6 +51,7 @@ describe('plugin:withEditableAPI: .insertChild()', () => {
51
51
  it('inserts child nodes correctly', async () => {
52
52
  const editorRef: RefObject<PortableTextEditor> = createRef()
53
53
  const onChange = jest.fn()
54
+
54
55
  render(
55
56
  <PortableTextEditorTester
56
57
  onChange={onChange}
@@ -59,102 +60,105 @@ describe('plugin:withEditableAPI: .insertChild()', () => {
59
60
  value={initialValue}
60
61
  />,
61
62
  )
62
- const editor = editorRef.current
63
- const inlineType = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
63
+
64
64
  await waitFor(() => {
65
- if (editor && inlineType) {
66
- PortableTextEditor.focus(editor)
67
- PortableTextEditor.select(editor, initialSelection)
65
+ if (editorRef.current) {
66
+ expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
67
+ expect(onChange).toHaveBeenCalledWith({type: 'ready'})
68
+ }
69
+ })
70
+
71
+ await waitFor(() => {
72
+ if (editorRef.current) {
73
+ PortableTextEditor.focus(editorRef.current)
74
+ PortableTextEditor.select(editorRef.current, initialSelection)
75
+ }
76
+ })
77
+
78
+ await waitFor(() => {
79
+ if (editorRef.current) {
80
+ const inlineType = editorRef.current.schemaTypes.inlineObjects.find(
81
+ (t) => t.name === 'someObject',
82
+ )!
68
83
  PortableTextEditor.insertChild(editorRef.current, inlineType, {color: 'red'})
69
- expect(PortableTextEditor.getValue(editorRef.current)).toMatchInlineSnapshot(`
70
- Array [
71
- Object {
72
- "_key": "a",
73
- "_type": "myTestBlockType",
74
- "children": Array [
75
- Object {
76
- "_key": "a1",
77
- "_type": "span",
78
- "marks": Array [],
79
- "text": "Block A",
80
- },
81
- Object {
82
- "_key": "3",
83
- "_type": "someObject",
84
- "color": "red",
85
- },
86
- Object {
87
- "_key": "4",
88
- "_type": "span",
89
- "marks": Array [],
90
- "text": "",
91
- },
92
- ],
93
- "markDefs": Array [],
94
- "style": "normal",
95
- },
96
- ]
97
- `)
98
- PortableTextEditor.insertChild(editor, editor.schemaTypes.span, {text: ' '})
99
- expect(PortableTextEditor.getValue(editor)).toMatchInlineSnapshot(`
100
- Array [
101
- Object {
102
- "_key": "a",
103
- "_type": "myTestBlockType",
104
- "children": Array [
105
- Object {
106
- "_key": "a1",
107
- "_type": "span",
108
- "marks": Array [],
109
- "text": "Block A",
110
- },
111
- Object {
112
- "_key": "3",
113
- "_type": "someObject",
114
- "color": "red",
115
- },
116
- Object {
117
- "_key": "7",
118
- "_type": "span",
119
- "marks": Array [],
120
- "text": " ",
121
- },
122
- ],
123
- "markDefs": Array [],
124
- "style": "normal",
125
- },
126
- ]
127
- `)
128
- const sel = PortableTextEditor.getSelection(editor)
129
- expect(sel).toMatchInlineSnapshot(`
130
- Object {
131
- "anchor": Object {
132
- "offset": 1,
133
- "path": Array [
134
- Object {
135
- "_key": "a",
136
- },
137
- "children",
138
- Object {
139
- "_key": "7",
140
- },
141
- ],
142
- },
143
- "backward": false,
144
- "focus": Object {
145
- "offset": 1,
146
- "path": Array [
147
- Object {
148
- "_key": "a",
149
- },
150
- "children",
151
- Object {
152
- "_key": "7",
153
- },
154
- ],
155
- },
156
- }
157
- `)
84
+ }
85
+ })
86
+
87
+ await waitFor(() => {
88
+ if (editorRef.current) {
89
+ expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
90
+ {
91
+ _key: 'a',
92
+ _type: 'myTestBlockType',
93
+ children: [
94
+ {
95
+ _key: 'a1',
96
+ _type: 'span',
97
+ marks: [],
98
+ text: 'Block A',
99
+ },
100
+ {
101
+ _key: '3',
102
+ _type: 'someObject',
103
+ color: 'red',
104
+ },
105
+ {
106
+ _key: '4',
107
+ _type: 'span',
108
+ marks: [],
109
+ text: '',
110
+ },
111
+ ],
112
+ markDefs: [],
113
+ style: 'normal',
114
+ },
115
+ ])
116
+ }
117
+ })
118
+
119
+ await waitFor(() => {
120
+ if (editorRef.current) {
121
+ PortableTextEditor.insertChild(editorRef.current, editorRef.current.schemaTypes.span, {
122
+ text: ' ',
123
+ })
124
+ }
125
+ })
126
+
127
+ await waitFor(() => {
128
+ if (editorRef.current) {
129
+ expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
130
+ {
131
+ _key: 'a',
132
+ _type: 'myTestBlockType',
133
+ children: [
134
+ {
135
+ _key: 'a1',
136
+ _type: 'span',
137
+ marks: [],
138
+ text: 'Block A',
139
+ },
140
+ {
141
+ _key: '3',
142
+ _type: 'someObject',
143
+ color: 'red',
144
+ },
145
+ {
146
+ _key: '7',
147
+ _type: 'span',
148
+ marks: [],
149
+ text: ' ',
150
+ },
151
+ ],
152
+ markDefs: [],
153
+ style: 'normal',
154
+ },
155
+ ])
156
+
157
+ expect(PortableTextEditor.getSelection(editorRef.current)).toEqual({
158
+ anchor: {path: [{_key: 'a'}, 'children', {_key: '7'}], offset: 1},
159
+ focus: {path: [{_key: 'a'}, 'children', {_key: '7'}], offset: 1},
160
+ backward: false,
161
+ })
158
162
  }
159
163
  })
160
164
  })
@@ -163,29 +167,62 @@ describe('plugin:withEditableAPI: .insertChild()', () => {
163
167
  describe('plugin:withEditableAPI: .insertBlock()', () => {
164
168
  it('should not add empty blank blocks: empty block', async () => {
165
169
  const editorRef: RefObject<PortableTextEditor> = createRef()
170
+ const value = [
171
+ {
172
+ _key: 'emptyBlock',
173
+ _type: 'myTestBlockType',
174
+ children: [
175
+ {
176
+ _key: 'emptySpan',
177
+ _type: 'span',
178
+ marks: [],
179
+ text: '',
180
+ },
181
+ ],
182
+ markDefs: [],
183
+ style: 'normal',
184
+ },
185
+ ]
166
186
  const onChange = jest.fn()
187
+
167
188
  render(
168
189
  <PortableTextEditorTester
169
- onChange={onChange}
170
190
  ref={editorRef}
171
191
  schemaType={schemaType}
172
192
  value={emptyTextBlock}
193
+ onChange={onChange}
173
194
  />,
174
195
  )
175
- const editor = editorRef.current
176
- const someObject = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
177
196
 
178
197
  await waitFor(() => {
179
- if (editorRef.current && someObject) {
198
+ if (editorRef.current) {
199
+ expect(onChange).toHaveBeenCalledWith({type: 'value', value})
200
+ expect(onChange).toHaveBeenCalledWith({type: 'ready'})
201
+ }
202
+ })
203
+
204
+ await waitFor(() => {
205
+ if (editorRef.current) {
180
206
  PortableTextEditor.focus(editorRef.current)
181
207
  PortableTextEditor.select(editorRef.current, emptyBlockSelection)
208
+ }
209
+ })
210
+
211
+ await waitFor(() => {
212
+ if (editorRef.current) {
213
+ const someObject = editorRef.current.schemaTypes.inlineObjects.find(
214
+ (t) => t.name === 'someObject',
215
+ )!
216
+
182
217
  PortableTextEditor.insertBlock(editorRef.current, someObject, {color: 'red'})
218
+ }
219
+ })
183
220
 
221
+ await waitFor(() => {
222
+ if (editorRef.current) {
184
223
  expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
185
224
  {_key: '2', _type: 'someObject', color: 'red'},
186
225
  ])
187
- } else {
188
- throw new Error('No editor or someObject')
189
226
  }
190
227
  })
191
228
  })
@@ -193,34 +230,54 @@ describe('plugin:withEditableAPI: .insertBlock()', () => {
193
230
  it('should not add empty blank blocks: non-empty block', async () => {
194
231
  const editorRef: RefObject<PortableTextEditor> = createRef()
195
232
  const onChange = jest.fn()
233
+
196
234
  render(
197
235
  <PortableTextEditorTester
198
- onChange={onChange}
199
236
  ref={editorRef}
200
237
  schemaType={schemaType}
201
238
  value={initialValue}
239
+ onChange={onChange}
202
240
  />,
203
241
  )
204
- const editor = editorRef.current
205
- const someObject = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
206
242
 
207
243
  await waitFor(() => {
208
- if (editorRef.current && someObject) {
244
+ if (editorRef.current) {
245
+ expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
246
+ expect(onChange).toHaveBeenCalledWith({type: 'ready'})
247
+ }
248
+ })
249
+
250
+ await waitFor(() => {
251
+ if (editorRef.current) {
209
252
  PortableTextEditor.focus(editorRef.current)
210
253
  PortableTextEditor.select(editorRef.current, initialSelection)
254
+ }
255
+ })
256
+
257
+ await waitFor(() => {
258
+ if (editorRef.current) {
259
+ const someObject = editorRef.current.schemaTypes.inlineObjects.find(
260
+ (t) => t.name === 'someObject',
261
+ )!
262
+
211
263
  PortableTextEditor.insertBlock(editorRef.current, someObject, {color: 'red'})
264
+ }
265
+ })
266
+
267
+ await waitFor(() => {
268
+ if (editorRef.current) {
212
269
  expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
213
270
  ...initialValue,
214
271
  {_key: '2', _type: 'someObject', color: 'red'},
215
272
  ])
216
- } else {
217
- throw new Error('No editor or someObject')
218
273
  }
219
274
  })
220
275
  })
276
+
221
277
  it('should be inserted before if focus is on start of block', async () => {
222
278
  const editorRef: RefObject<PortableTextEditor> = createRef()
223
279
  const onChange = jest.fn()
280
+
224
281
  render(
225
282
  <PortableTextEditorTester
226
283
  onChange={onChange}
@@ -229,117 +286,185 @@ describe('plugin:withEditableAPI: .insertBlock()', () => {
229
286
  value={initialValue}
230
287
  />,
231
288
  )
232
- const editor = editorRef.current
233
- const someObject = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
234
289
 
235
290
  await waitFor(() => {
236
- if (editorRef.current && someObject) {
291
+ if (editorRef.current) {
292
+ expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
293
+ expect(onChange).toHaveBeenCalledWith({type: 'ready'})
294
+ }
295
+ })
296
+
297
+ await waitFor(() => {
298
+ if (editorRef.current) {
237
299
  PortableTextEditor.focus(editorRef.current)
238
300
  PortableTextEditor.select(editorRef.current, {
239
301
  focus: {path: [{_key: 'a'}, 'children', {_key: 'a1'}], offset: 0},
240
302
  anchor: {path: [{_key: 'a'}, 'children', {_key: 'a1'}], offset: 0},
241
303
  })
304
+ }
305
+ })
306
+
307
+ await waitFor(() => {
308
+ if (editorRef.current) {
309
+ const someObject = editorRef.current.schemaTypes.inlineObjects.find(
310
+ (t) => t.name === 'someObject',
311
+ )!
242
312
  PortableTextEditor.insertBlock(editorRef.current, someObject, {color: 'red'})
313
+ }
314
+ })
315
+
316
+ await waitFor(() => {
317
+ if (editorRef.current) {
243
318
  expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
244
319
  {_key: '2', _type: 'someObject', color: 'red'},
245
320
  ...initialValue,
246
321
  ])
247
- } else {
248
- throw new Error('No editor or someObject')
249
322
  }
250
323
  })
251
324
  })
325
+
252
326
  it('should not add empty blank blocks: non text block', async () => {
253
327
  const editorRef: RefObject<PortableTextEditor> = createRef()
254
- const onChange = jest.fn()
255
328
  const value = [...initialValue, {_key: 'b', _type: 'someObject', color: 'red'}]
329
+ const onChange = jest.fn()
330
+
256
331
  render(
257
332
  <PortableTextEditorTester
258
- onChange={onChange}
259
333
  ref={editorRef}
260
334
  schemaType={schemaType}
261
335
  value={value}
336
+ onChange={onChange}
262
337
  />,
263
338
  )
264
- const editor = editorRef.current
265
- const someObject = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
266
339
 
267
340
  await waitFor(() => {
268
- if (editorRef.current && someObject) {
341
+ if (editorRef.current) {
342
+ expect(onChange).toHaveBeenCalledWith({type: 'value', value})
343
+ expect(onChange).toHaveBeenCalledWith({type: 'ready'})
344
+ }
345
+ })
346
+
347
+ await waitFor(() => {
348
+ if (editorRef.current) {
269
349
  PortableTextEditor.focus(editorRef.current)
270
350
  // Focus the `someObject` block
271
351
  PortableTextEditor.select(editorRef.current, {
272
352
  focus: {path: [{_key: 'b'}], offset: 0},
273
353
  anchor: {path: [{_key: 'b'}], offset: 0},
274
354
  })
355
+ }
356
+ })
357
+
358
+ await waitFor(() => {
359
+ if (editorRef.current) {
360
+ const someObject = editorRef.current.schemaTypes.inlineObjects.find(
361
+ (t) => t.name === 'someObject',
362
+ )!
275
363
  PortableTextEditor.insertBlock(editorRef.current, someObject, {color: 'yellow'})
364
+ }
365
+ })
366
+
367
+ await waitFor(() => {
368
+ if (editorRef.current) {
276
369
  expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
277
370
  ...value,
278
371
  {_key: '2', _type: 'someObject', color: 'yellow'},
279
372
  ])
280
- } else {
281
- throw new Error('No editor or someObject')
282
373
  }
283
374
  })
284
375
  })
376
+
285
377
  it('should not add empty blank blocks: in between blocks', async () => {
286
378
  const editorRef: RefObject<PortableTextEditor> = createRef()
287
- const onChange = jest.fn()
288
379
  const value = [...initialValue, {_key: 'b', _type: 'someObject', color: 'red'}]
380
+ const onChange = jest.fn()
381
+
289
382
  render(
290
383
  <PortableTextEditorTester
291
- onChange={onChange}
292
384
  ref={editorRef}
293
385
  schemaType={schemaType}
294
386
  value={value}
387
+ onChange={onChange}
295
388
  />,
296
389
  )
297
- const editor = editorRef.current
298
- const someObject = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
299
390
 
300
391
  await waitFor(() => {
301
- if (editorRef.current && someObject) {
392
+ if (editorRef.current) {
393
+ expect(onChange).toHaveBeenCalledWith({type: 'value', value})
394
+ expect(onChange).toHaveBeenCalledWith({type: 'ready'})
395
+ }
396
+ })
397
+
398
+ await waitFor(() => {
399
+ if (editorRef.current) {
302
400
  PortableTextEditor.focus(editorRef.current)
303
401
  // Focus the `text` block
304
402
  PortableTextEditor.select(editorRef.current, initialSelection)
403
+ }
404
+ })
405
+
406
+ await waitFor(() => {
407
+ if (editorRef.current) {
408
+ const someObject = editorRef.current.schemaTypes.inlineObjects.find(
409
+ (t) => t.name === 'someObject',
410
+ )!
305
411
  PortableTextEditor.insertBlock(editorRef.current, someObject, {color: 'yellow'})
412
+ }
413
+ })
414
+
415
+ await waitFor(() => {
416
+ if (editorRef.current) {
306
417
  expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
307
418
  value[0],
308
419
  {_key: '2', _type: 'someObject', color: 'yellow'},
309
420
  value[1],
310
421
  ])
311
- } else {
312
- throw new Error('No editor or someObject')
313
422
  }
314
423
  })
315
424
  })
425
+
316
426
  it('should not add empty blank blocks: in new empty text block', async () => {
317
427
  const editorRef: RefObject<PortableTextEditor> = createRef()
318
- const onChange = jest.fn()
319
428
  const value = [...initialValue, ...emptyTextBlock]
429
+ const onChange = jest.fn()
430
+
320
431
  render(
321
432
  <PortableTextEditorTester
322
- onChange={onChange}
323
433
  ref={editorRef}
324
434
  schemaType={schemaType}
325
435
  value={value}
436
+ onChange={onChange}
326
437
  />,
327
438
  )
328
- const editor = editorRef.current
329
- const someObject = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
330
439
 
331
440
  await waitFor(() => {
332
- if (editorRef.current && someObject) {
333
- PortableTextEditor.focus(editorRef.current)
334
- // Focus the empty `text` block
441
+ if (editorRef.current) {
442
+ expect(onChange).toHaveBeenCalledWith({type: 'value', value})
443
+ expect(onChange).toHaveBeenCalledWith({type: 'ready'})
444
+ }
445
+ })
446
+
447
+ await waitFor(() => {
448
+ if (editorRef.current) {
335
449
  PortableTextEditor.select(editorRef.current, emptyBlockSelection)
450
+ }
451
+ })
452
+
453
+ await waitFor(() => {
454
+ if (editorRef.current) {
455
+ const someObject = editorRef.current.schemaTypes.inlineObjects.find(
456
+ (t) => t.name === 'someObject',
457
+ )!
336
458
  PortableTextEditor.insertBlock(editorRef.current, someObject, {color: 'yellow'})
459
+ }
460
+ })
461
+
462
+ await waitFor(() => {
463
+ if (editorRef.current) {
337
464
  expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
338
465
  value[0],
339
466
  {_key: '2', _type: 'someObject', color: 'yellow'},
340
467
  ])
341
- } else {
342
- throw new Error('No editor or someObject')
343
468
  }
344
469
  })
345
470
  })
@@ -49,7 +49,7 @@ describe('plugin:withHotkeys: .ArrowDown', () => {
49
49
  const editor = editorRef.current
50
50
  const inlineType = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
51
51
  await waitFor(async () => {
52
- if (editor && inlineType && element) {
52
+ if (editor && inlineType && editor) {
53
53
  PortableTextEditor.focus(editor)
54
54
  PortableTextEditor.select(editor, initialSelection)
55
55
  PortableTextEditor.insertBreak(editor)
@@ -42,9 +42,9 @@ describe('plugin:withInsertBreak: "enter"', () => {
42
42
  focus: {path: [{_key: 'b'}, 'children', {_key: 'b1'}], offset: 0},
43
43
  anchor: {path: [{_key: 'b'}, 'children', {_key: 'b1'}], offset: 0},
44
44
  }
45
-
46
45
  const editorRef: RefObject<PortableTextEditor> = createRef()
47
46
  const onChange = jest.fn()
47
+
48
48
  render(
49
49
  <PortableTextEditorTester
50
50
  onChange={onChange}
@@ -53,6 +53,14 @@ describe('plugin:withInsertBreak: "enter"', () => {
53
53
  value={initialValue}
54
54
  />,
55
55
  )
56
+
57
+ await waitFor(() => {
58
+ if (editorRef.current) {
59
+ expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
60
+ expect(onChange).toHaveBeenCalledWith({type: 'ready'})
61
+ }
62
+ })
63
+
56
64
  const editor = editorRef.current
57
65
  const inlineType = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
58
66
  await waitFor(async () => {
@@ -102,9 +110,9 @@ describe('plugin:withInsertBreak: "enter"', () => {
102
110
  markDefs: [],
103
111
  style: 'normal',
104
112
  }
105
-
106
113
  const editorRef: RefObject<PortableTextEditor> = createRef()
107
114
  const onChange = jest.fn()
115
+
108
116
  render(
109
117
  <PortableTextEditorTester
110
118
  onChange={onChange}
@@ -113,6 +121,14 @@ describe('plugin:withInsertBreak: "enter"', () => {
113
121
  value={[emptyBlock]}
114
122
  />,
115
123
  )
124
+
125
+ await waitFor(() => {
126
+ if (editorRef.current) {
127
+ expect(onChange).toHaveBeenCalledWith({type: 'value', value: [emptyBlock]})
128
+ expect(onChange).toHaveBeenCalledWith({type: 'ready'})
129
+ }
130
+ })
131
+
116
132
  const editor = editorRef.current
117
133
  const inlineType = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
118
134
  await waitFor(async () => {