@wordpress/core-data 7.40.2-next.v.202602241322.0 → 7.40.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.
Files changed (183) hide show
  1. package/README.md +0 -27
  2. package/build/actions.cjs +9 -26
  3. package/build/actions.cjs.map +2 -2
  4. package/build/awareness/post-editor-awareness.cjs +45 -6
  5. package/build/awareness/post-editor-awareness.cjs.map +2 -2
  6. package/build/awareness/types.cjs.map +1 -1
  7. package/build/entities.cjs +50 -23
  8. package/build/entities.cjs.map +2 -2
  9. package/build/entity-provider.cjs +15 -6
  10. package/build/entity-provider.cjs.map +2 -2
  11. package/build/hooks/use-entity-prop.cjs +33 -2
  12. package/build/hooks/use-entity-prop.cjs.map +2 -2
  13. package/build/hooks/use-post-editor-awareness-state.cjs +120 -1
  14. package/build/hooks/use-post-editor-awareness-state.cjs.map +2 -2
  15. package/build/index.cjs +0 -3
  16. package/build/index.cjs.map +2 -2
  17. package/build/private-actions.cjs +27 -3
  18. package/build/private-actions.cjs.map +2 -2
  19. package/build/private-apis.cjs +14 -5
  20. package/build/private-apis.cjs.map +3 -3
  21. package/build/private-selectors.cjs +22 -2
  22. package/build/private-selectors.cjs.map +2 -2
  23. package/build/queried-data/actions.cjs +1 -1
  24. package/build/queried-data/actions.cjs.map +2 -2
  25. package/build/queried-data/reducer.cjs +19 -13
  26. package/build/queried-data/reducer.cjs.map +2 -2
  27. package/build/reducer.cjs +19 -2
  28. package/build/reducer.cjs.map +2 -2
  29. package/build/resolvers.cjs +16 -6
  30. package/build/resolvers.cjs.map +2 -2
  31. package/build/selectors.cjs +0 -15
  32. package/build/selectors.cjs.map +2 -2
  33. package/build/sync.cjs +11 -5
  34. package/build/sync.cjs.map +2 -2
  35. package/build/types.cjs.map +1 -1
  36. package/build/utils/block-selection-history.cjs +1 -1
  37. package/build/utils/block-selection-history.cjs.map +2 -2
  38. package/build/utils/crdt-blocks.cjs +125 -49
  39. package/build/utils/crdt-blocks.cjs.map +2 -2
  40. package/build/utils/crdt-selection.cjs +50 -19
  41. package/build/utils/crdt-selection.cjs.map +2 -2
  42. package/build/utils/crdt-text.cjs +52 -0
  43. package/build/utils/crdt-text.cjs.map +7 -0
  44. package/build/utils/crdt-user-selections.cjs +16 -6
  45. package/build/utils/crdt-user-selections.cjs.map +3 -3
  46. package/build/utils/crdt-utils.cjs +54 -2
  47. package/build/utils/crdt-utils.cjs.map +2 -2
  48. package/build/utils/crdt.cjs +38 -29
  49. package/build/utils/crdt.cjs.map +2 -2
  50. package/build-module/actions.mjs +14 -26
  51. package/build-module/actions.mjs.map +2 -2
  52. package/build-module/awareness/post-editor-awareness.mjs +47 -7
  53. package/build-module/awareness/post-editor-awareness.mjs.map +2 -2
  54. package/build-module/entities.mjs +53 -24
  55. package/build-module/entities.mjs.map +2 -2
  56. package/build-module/entity-provider.mjs +15 -6
  57. package/build-module/entity-provider.mjs.map +2 -2
  58. package/build-module/hooks/use-entity-prop.mjs +34 -3
  59. package/build-module/hooks/use-entity-prop.mjs.map +2 -2
  60. package/build-module/hooks/use-post-editor-awareness-state.mjs +117 -1
  61. package/build-module/hooks/use-post-editor-awareness-state.mjs.map +2 -2
  62. package/build-module/index.mjs +0 -2
  63. package/build-module/index.mjs.map +2 -2
  64. package/build-module/private-actions.mjs +24 -2
  65. package/build-module/private-actions.mjs.map +2 -2
  66. package/build-module/private-apis.mjs +21 -6
  67. package/build-module/private-apis.mjs.map +3 -3
  68. package/build-module/private-selectors.mjs +19 -1
  69. package/build-module/private-selectors.mjs.map +2 -2
  70. package/build-module/queried-data/actions.mjs +1 -1
  71. package/build-module/queried-data/actions.mjs.map +2 -2
  72. package/build-module/queried-data/reducer.mjs +19 -13
  73. package/build-module/queried-data/reducer.mjs.map +2 -2
  74. package/build-module/reducer.mjs +18 -2
  75. package/build-module/reducer.mjs.map +2 -2
  76. package/build-module/resolvers.mjs +16 -6
  77. package/build-module/resolvers.mjs.map +2 -2
  78. package/build-module/selectors.mjs +0 -14
  79. package/build-module/selectors.mjs.map +2 -2
  80. package/build-module/sync.mjs +7 -3
  81. package/build-module/sync.mjs.map +2 -2
  82. package/build-module/utils/block-selection-history.mjs +5 -2
  83. package/build-module/utils/block-selection-history.mjs.map +2 -2
  84. package/build-module/utils/crdt-blocks.mjs +124 -49
  85. package/build-module/utils/crdt-blocks.mjs.map +2 -2
  86. package/build-module/utils/crdt-selection.mjs +53 -20
  87. package/build-module/utils/crdt-selection.mjs.map +2 -2
  88. package/build-module/utils/crdt-text.mjs +26 -0
  89. package/build-module/utils/crdt-text.mjs.map +7 -0
  90. package/build-module/utils/crdt-user-selections.mjs +16 -7
  91. package/build-module/utils/crdt-user-selections.mjs.map +3 -3
  92. package/build-module/utils/crdt-utils.mjs +51 -1
  93. package/build-module/utils/crdt-utils.mjs.map +2 -2
  94. package/build-module/utils/crdt.mjs +42 -34
  95. package/build-module/utils/crdt.mjs.map +2 -2
  96. package/build-types/actions.d.ts +0 -11
  97. package/build-types/actions.d.ts.map +1 -1
  98. package/build-types/awareness/post-editor-awareness.d.ts +2 -2
  99. package/build-types/awareness/post-editor-awareness.d.ts.map +1 -1
  100. package/build-types/awareness/types.d.ts +6 -1
  101. package/build-types/awareness/types.d.ts.map +1 -1
  102. package/build-types/entities.d.ts +20 -1
  103. package/build-types/entities.d.ts.map +1 -1
  104. package/build-types/entity-provider.d.ts +11 -6
  105. package/build-types/entity-provider.d.ts.map +1 -1
  106. package/build-types/hooks/use-entity-prop.d.ts.map +1 -1
  107. package/build-types/hooks/use-post-editor-awareness-state.d.ts +40 -7
  108. package/build-types/hooks/use-post-editor-awareness-state.d.ts.map +1 -1
  109. package/build-types/index.d.ts +0 -3
  110. package/build-types/index.d.ts.map +1 -1
  111. package/build-types/parsed-blocks-cache.d.ts +10 -0
  112. package/build-types/parsed-blocks-cache.d.ts.map +1 -0
  113. package/build-types/private-actions.d.ts +12 -0
  114. package/build-types/private-actions.d.ts.map +1 -1
  115. package/build-types/private-apis.d.ts +21 -1
  116. package/build-types/private-apis.d.ts.map +1 -1
  117. package/build-types/private-selectors.d.ts +17 -0
  118. package/build-types/private-selectors.d.ts.map +1 -1
  119. package/build-types/queried-data/reducer.d.ts.map +1 -1
  120. package/build-types/reducer.d.ts +15 -0
  121. package/build-types/reducer.d.ts.map +1 -1
  122. package/build-types/resolvers.d.ts.map +1 -1
  123. package/build-types/selectors.d.ts +1 -9
  124. package/build-types/selectors.d.ts.map +1 -1
  125. package/build-types/sync.d.ts +2 -2
  126. package/build-types/sync.d.ts.map +1 -1
  127. package/build-types/types.d.ts +11 -2
  128. package/build-types/types.d.ts.map +1 -1
  129. package/build-types/utils/block-selection-history.d.ts.map +1 -1
  130. package/build-types/utils/crdt-blocks.d.ts +12 -1
  131. package/build-types/utils/crdt-blocks.d.ts.map +1 -1
  132. package/build-types/utils/crdt-selection.d.ts +10 -0
  133. package/build-types/utils/crdt-selection.d.ts.map +1 -1
  134. package/build-types/utils/crdt-text.d.ts +16 -0
  135. package/build-types/utils/crdt-text.d.ts.map +1 -0
  136. package/build-types/utils/crdt-user-selections.d.ts +17 -4
  137. package/build-types/utils/crdt-user-selections.d.ts.map +1 -1
  138. package/build-types/utils/crdt-utils.d.ts +20 -0
  139. package/build-types/utils/crdt-utils.d.ts.map +1 -1
  140. package/build-types/utils/crdt.d.ts +14 -7
  141. package/build-types/utils/crdt.d.ts.map +1 -1
  142. package/build-types/utils/normalize-query-for-resolution.d.ts +12 -0
  143. package/build-types/utils/normalize-query-for-resolution.d.ts.map +1 -0
  144. package/build-types/utils/save-crdt-doc.d.ts +8 -0
  145. package/build-types/utils/save-crdt-doc.d.ts.map +1 -0
  146. package/build-types/utils/test/crdt-utils.d.ts +2 -0
  147. package/build-types/utils/test/crdt-utils.d.ts.map +1 -0
  148. package/package.json +18 -18
  149. package/src/actions.js +26 -41
  150. package/src/awareness/post-editor-awareness.ts +106 -7
  151. package/src/awareness/test/post-editor-awareness.ts +50 -10
  152. package/src/awareness/types.ts +7 -1
  153. package/src/entities.js +62 -24
  154. package/src/entity-provider.js +24 -11
  155. package/src/hooks/test/use-post-editor-awareness-state.ts +446 -3
  156. package/src/hooks/use-entity-prop.js +43 -3
  157. package/src/hooks/use-post-editor-awareness-state.ts +229 -7
  158. package/src/index.js +0 -6
  159. package/src/private-actions.js +43 -1
  160. package/src/{private-apis.js → private-apis.ts} +21 -3
  161. package/src/private-selectors.ts +43 -0
  162. package/src/queried-data/actions.js +1 -1
  163. package/src/queried-data/reducer.js +26 -14
  164. package/src/reducer.js +36 -1
  165. package/src/resolvers.js +23 -7
  166. package/src/selectors.ts +1 -32
  167. package/src/sync.ts +6 -2
  168. package/src/test/entities.js +231 -14
  169. package/src/test/private-actions.js +1 -1
  170. package/src/test/resolvers.js +64 -11
  171. package/src/test/store.js +116 -0
  172. package/src/types.ts +21 -2
  173. package/src/utils/block-selection-history.ts +5 -2
  174. package/src/utils/crdt-blocks.ts +250 -81
  175. package/src/utils/crdt-selection.ts +92 -26
  176. package/src/utils/crdt-text.ts +43 -0
  177. package/src/utils/crdt-user-selections.ts +29 -8
  178. package/src/utils/crdt-utils.ts +99 -0
  179. package/src/utils/crdt.ts +72 -46
  180. package/src/utils/test/crdt-blocks.ts +1177 -22
  181. package/src/utils/test/crdt-user-selections.ts +5 -0
  182. package/src/utils/test/crdt-utils.ts +387 -0
  183. package/src/utils/test/crdt.ts +423 -60
@@ -23,6 +23,11 @@ jest.mock( '@wordpress/data', () => ( {
23
23
  select: jest.fn(),
24
24
  subscribe: jest.fn(),
25
25
  resolveSelect: jest.fn(),
26
+ // Needed because @wordpress/rich-text initialises its store at import time.
27
+ combineReducers: jest.fn( () => jest.fn( () => ( {} ) ) ),
28
+ createReduxStore: jest.fn( () => ( {} ) ),
29
+ register: jest.fn(),
30
+ createSelector: ( selector: Function ) => selector,
26
31
  } ) );
27
32
 
28
33
  jest.mock( '@wordpress/block-editor', () => ( {
@@ -422,6 +427,41 @@ describe( 'PostEditorAwareness', () => {
422
427
  // Callback should not be called for equal editor states
423
428
  expect( callback ).not.toHaveBeenCalled();
424
429
  } );
430
+
431
+ test( 'should not notify when editorState without selection is unchanged', () => {
432
+ const awareness = new PostEditorAwareness(
433
+ doc,
434
+ 'postType',
435
+ 'post',
436
+ 123
437
+ );
438
+ awareness.setUp();
439
+
440
+ awareness.setLocalStateField( 'editorState', {} );
441
+
442
+ const callback = jest.fn();
443
+ awareness.onStateChange( callback );
444
+
445
+ awareness.emit( 'change', [
446
+ {
447
+ added: [],
448
+ updated: [ awareness.clientID ],
449
+ removed: [],
450
+ },
451
+ ] );
452
+ callback.mockClear();
453
+
454
+ awareness.setLocalStateField( 'editorState', {} );
455
+ awareness.emit( 'change', [
456
+ {
457
+ added: [],
458
+ updated: [ awareness.clientID ],
459
+ removed: [],
460
+ },
461
+ ] );
462
+
463
+ expect( callback ).not.toHaveBeenCalled();
464
+ } );
425
465
  } );
426
466
 
427
467
  describe( 'convertSelectionStateToAbsolute', () => {
@@ -456,7 +496,7 @@ describe( 'PostEditorAwareness', () => {
456
496
  awareness.convertSelectionStateToAbsolute( selection );
457
497
 
458
498
  // Should return nulls when the relative position's type cannot be found
459
- expect( result.textIndex ).toBeNull();
499
+ expect( result.richTextOffset ).toBeNull();
460
500
  expect( result.localClientId ).toBeNull();
461
501
  } );
462
502
 
@@ -494,7 +534,7 @@ describe( 'PostEditorAwareness', () => {
494
534
  const result =
495
535
  awareness.convertSelectionStateToAbsolute( selection );
496
536
 
497
- expect( result.textIndex ).toBe( 5 );
537
+ expect( result.richTextOffset ).toBe( 5 );
498
538
  expect( result.localClientId ).toBe( 'block-1' );
499
539
  } );
500
540
 
@@ -526,7 +566,7 @@ describe( 'PostEditorAwareness', () => {
526
566
  const result =
527
567
  awareness.convertSelectionStateToAbsolute( selection );
528
568
 
529
- expect( result.textIndex ).toBeNull();
569
+ expect( result.richTextOffset ).toBeNull();
530
570
  expect( result.localClientId ).toBe( 'block-1' );
531
571
  } );
532
572
  } );
@@ -732,7 +772,7 @@ describe( 'PostEditorAwareness', () => {
732
772
  const result =
733
773
  awareness.convertSelectionStateToAbsolute( selection );
734
774
 
735
- expect( result.textIndex ).toBe( 2 );
775
+ expect( result.richTextOffset ).toBe( 2 );
736
776
  expect( result.localClientId ).toBe( 'local-2' );
737
777
 
738
778
  nestedDoc.destroy();
@@ -805,7 +845,7 @@ describe( 'PostEditorAwareness', () => {
805
845
  const result =
806
846
  awareness.convertSelectionStateToAbsolute( selection );
807
847
 
808
- expect( result.textIndex ).toBe( 5 );
848
+ expect( result.richTextOffset ).toBe( 5 );
809
849
  expect( result.localClientId ).toBe( 'local-inner-1' );
810
850
 
811
851
  nestedDoc.destroy();
@@ -860,7 +900,7 @@ describe( 'PostEditorAwareness', () => {
860
900
  const result =
861
901
  awareness.convertSelectionStateToAbsolute( selection );
862
902
 
863
- expect( result.textIndex ).toBeNull();
903
+ expect( result.richTextOffset ).toBeNull();
864
904
  expect( result.localClientId ).toBe( 'local-img' );
865
905
 
866
906
  nestedDoc.destroy();
@@ -954,7 +994,7 @@ describe( 'PostEditorAwareness', () => {
954
994
  const result =
955
995
  awareness.convertSelectionStateToAbsolute( selection );
956
996
 
957
- expect( result.textIndex ).toBe( 7 );
997
+ expect( result.richTextOffset ).toBe( 7 );
958
998
  expect( result.localClientId ).toBe( 'local-deep-1' );
959
999
 
960
1000
  nestedDoc.destroy();
@@ -1055,7 +1095,7 @@ describe( 'PostEditorAwareness', () => {
1055
1095
  const result =
1056
1096
  awareness.convertSelectionStateToAbsolute( selection );
1057
1097
 
1058
- expect( result.textIndex ).toBe( 4 );
1098
+ expect( result.richTextOffset ).toBe( 4 );
1059
1099
  // Should resolve to the post-content inner block, not a template block
1060
1100
  expect( result.localClientId ).toBe( 'local-para-1' );
1061
1101
  // Verify getBlocks was called with the post-content clientId
@@ -1127,7 +1167,7 @@ describe( 'PostEditorAwareness', () => {
1127
1167
  const result =
1128
1168
  awareness.convertSelectionStateToAbsolute( selection );
1129
1169
 
1130
- expect( result.textIndex ).toBeNull();
1170
+ expect( result.richTextOffset ).toBeNull();
1131
1171
  expect( result.localClientId ).toBe( 'local-img' );
1132
1172
 
1133
1173
  templateDoc.destroy();
@@ -1176,7 +1216,7 @@ describe( 'PostEditorAwareness', () => {
1176
1216
  const result =
1177
1217
  awareness.convertSelectionStateToAbsolute( selection );
1178
1218
 
1179
- expect( result.textIndex ).toBe( 3 );
1219
+ expect( result.richTextOffset ).toBe( 3 );
1180
1220
  expect( result.localClientId ).toBe( 'local-para' );
1181
1221
 
1182
1222
  normalDoc.destroy();
@@ -30,7 +30,7 @@ export interface BaseState {
30
30
  * The editor state includes information about the collaborator's current selection.
31
31
  */
32
32
  export interface EditorState {
33
- selection: SelectionState;
33
+ selection?: SelectionState;
34
34
  }
35
35
 
36
36
  /**
@@ -94,3 +94,9 @@ export type EqualityFieldCheck< State, FieldName extends keyof State > = (
94
94
  value1?: State[ FieldName ],
95
95
  value2?: State[ FieldName ]
96
96
  ) => boolean;
97
+
98
+ export interface PostSaveEvent {
99
+ savedAt: number;
100
+ savedByClientId: number;
101
+ postStatus: string | undefined;
102
+ }
package/src/entities.js CHANGED
@@ -17,8 +17,10 @@ import { PostEditorAwareness } from './awareness/post-editor-awareness';
17
17
  import { getSyncManager } from './sync';
18
18
  import {
19
19
  applyPostChangesToCRDTDoc,
20
+ defaultCollectionSyncConfig,
20
21
  defaultSyncConfig,
21
22
  getPostChangesFromCRDTDoc,
23
+ POST_META_KEY_FOR_CRDT_DOC_PERSISTENCE,
22
24
  } from './utils/crdt';
23
25
 
24
26
  export const DEFAULT_ENTITY_KEY = 'id';
@@ -140,6 +142,7 @@ export const rootEntitiesConfig = [
140
142
  plural: 'comments',
141
143
  label: __( 'Comment' ),
142
144
  supportsPagination: true,
145
+ syncConfig: defaultCollectionSyncConfig,
143
146
  },
144
147
  {
145
148
  name: 'menu',
@@ -235,14 +238,7 @@ export const rootEntitiesConfig = [
235
238
  plural: 'icons',
236
239
  key: 'name',
237
240
  },
238
- ].map( ( entity ) => {
239
- const syncEnabledRootEntities = new Set( [ 'comment' ] );
240
-
241
- if ( syncEnabledRootEntities.has( entity.name ) ) {
242
- entity.syncConfig = defaultSyncConfig;
243
- }
244
- return entity;
245
- } );
241
+ ];
246
242
 
247
243
  export const deprecatedEntities = {
248
244
  root: {
@@ -274,9 +270,9 @@ export const additionalEntityConfigLoaders = [
274
270
  * @param {Object} edits Edits.
275
271
  * @param {string} name Post type name.
276
272
  * @param {boolean} isTemplate Whether the post type is a template.
277
- * @return {Object} Updated edits.
273
+ * @return {Promise< Object >} Updated edits.
278
274
  */
279
- export const prePersistPostType = (
275
+ export const prePersistPostType = async (
280
276
  persistedRecord,
281
277
  edits,
282
278
  name,
@@ -305,11 +301,17 @@ export const prePersistPostType = (
305
301
  if ( persistedRecord ) {
306
302
  const objectType = `postType/${ name }`;
307
303
  const objectId = persistedRecord.id;
308
- const meta = getSyncManager()?.createMeta( objectType, objectId );
309
- newEdits.meta = {
310
- ...edits.meta,
311
- ...meta,
312
- };
304
+ const serializedDoc = await getSyncManager()?.createPersistedCRDTDoc(
305
+ objectType,
306
+ objectId
307
+ );
308
+
309
+ if ( serializedDoc ) {
310
+ newEdits.meta = {
311
+ ...edits.meta,
312
+ [ POST_META_KEY_FOR_CRDT_DOC_PERSISTENCE ]: serializedDoc,
313
+ };
314
+ }
313
315
  }
314
316
 
315
317
  return newEdits;
@@ -321,15 +323,42 @@ export const prePersistPostType = (
321
323
  * @return {Promise} Entities promise
322
324
  */
323
325
  async function loadPostTypeEntities() {
324
- const postTypes = await apiFetch( {
325
- path: '/wp/v2/types?context=view',
326
- } );
326
+ const postTypesPromise = apiFetch( { path: '/wp/v2/types?context=view' } );
327
+ const taxonomiesPromise = window._wpCollaborationEnabled
328
+ ? apiFetch( { path: '/wp/v2/taxonomies?context=view' } )
329
+ : Promise.resolve( {} );
330
+ const [ postTypes, taxonomies ] = await Promise.all( [
331
+ postTypesPromise,
332
+ taxonomiesPromise,
333
+ ] );
334
+
327
335
  return Object.entries( postTypes ?? {} ).map( ( [ name, postType ] ) => {
328
336
  const isTemplate = [ 'wp_template', 'wp_template_part' ].includes(
329
337
  name
330
338
  );
331
339
  const namespace = postType?.rest_namespace ?? 'wp/v2';
332
340
 
341
+ const syncedProperties = new Set( [
342
+ 'author',
343
+ 'blocks',
344
+ 'content',
345
+ 'comment_status',
346
+ 'date',
347
+ 'excerpt',
348
+ 'featured_media',
349
+ 'format',
350
+ 'meta',
351
+ 'ping_status',
352
+ 'slug',
353
+ 'status',
354
+ 'sticky',
355
+ 'template',
356
+ 'title',
357
+ ...( postType.taxonomies
358
+ ?.map( ( taxonomy ) => taxonomies?.[ taxonomy ]?.rest_base )
359
+ ?.filter( Boolean ) ?? [] ),
360
+ ] );
361
+
333
362
  const entity = {
334
363
  kind: 'postType',
335
364
  baseURL: `/${ namespace }/${ postType.rest_base }`,
@@ -377,7 +406,7 @@ async function loadPostTypeEntities() {
377
406
  * @return {void}
378
407
  */
379
408
  applyChangesToCRDTDoc: ( crdtDoc, changes ) =>
380
- applyPostChangesToCRDTDoc( crdtDoc, changes, postType ),
409
+ applyPostChangesToCRDTDoc( crdtDoc, changes, syncedProperties ),
381
410
 
382
411
  /**
383
412
  * Create the awareness instance for the entity's CRDT document.
@@ -401,15 +430,24 @@ async function loadPostTypeEntities() {
401
430
  * @return {Partial< import('@wordpress/sync').ObjectData >} Changes to record
402
431
  */
403
432
  getChangesFromCRDTDoc: ( crdtDoc, editedRecord ) =>
404
- getPostChangesFromCRDTDoc( crdtDoc, editedRecord, postType ),
433
+ getPostChangesFromCRDTDoc(
434
+ crdtDoc,
435
+ editedRecord,
436
+ syncedProperties
437
+ ),
405
438
 
406
439
  /**
407
- * Sync features supported by the entity.
440
+ * Extract changes from a CRDT document that can be used to update the
441
+ * local editor state.
408
442
  *
409
- * @type {Record< string, boolean >}
443
+ * @param {import('@wordpress/sync').ObjectData} record
444
+ * @return {Partial< import('@wordpress/sync').ObjectData >} Changes to record
410
445
  */
411
- supports: {
412
- crdtPersistence: true,
446
+ getPersistedCRDTDoc: ( record ) => {
447
+ return (
448
+ record?.meta?.[ POST_META_KEY_FOR_CRDT_DOC_PERSISTENCE ] ||
449
+ null
450
+ );
413
451
  },
414
452
  };
415
453
 
@@ -12,26 +12,39 @@ import { EntityContext } from './entity-context';
12
12
  * Context provider component for providing
13
13
  * an entity for a specific entity.
14
14
  *
15
- * @param {Object} props The component's props.
16
- * @param {string} props.kind The entity kind.
17
- * @param {string} props.type The entity name.
18
- * @param {number} props.id The entity ID.
19
- * @param {*} props.children The children to wrap.
15
+ * @param {Object} props The component's props.
16
+ * @param {string} props.kind The entity kind.
17
+ * @param {string} props.type The entity name.
18
+ * @param {number} props.id The entity ID.
19
+ * @param {number} [props.revisionId] Optional revision ID. When set,
20
+ * `useEntityProp` reads from the
21
+ * revision record instead of the
22
+ * current entity.
23
+ * @param {*} props.children The children to wrap.
20
24
  *
21
25
  * @return {Object} The provided children, wrapped with
22
26
  * the entity's context provider.
23
27
  */
24
- export default function EntityProvider( { kind, type: name, id, children } ) {
28
+ export default function EntityProvider( {
29
+ kind,
30
+ type: name,
31
+ id,
32
+ revisionId,
33
+ children,
34
+ } ) {
25
35
  const parent = useContext( EntityContext );
26
36
  const childContext = useMemo(
27
37
  () => ( {
28
38
  ...parent,
29
- [ kind ]: {
30
- ...parent?.[ kind ],
31
- [ name ]: id,
32
- },
39
+ ...( kind && {
40
+ [ kind ]: {
41
+ ...parent?.[ kind ],
42
+ [ name ]: id,
43
+ },
44
+ } ),
45
+ ...( revisionId !== undefined && { revisionId } ),
33
46
  } ),
34
- [ parent, kind, name, id ]
47
+ [ parent, kind, name, id, revisionId ]
35
48
  );
36
49
  return (
37
50
  <EntityContext.Provider value={ childContext }>