@wordpress/core-data 7.46.0 → 7.47.0

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 (148) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +0 -27
  3. package/build/actions.cjs +0 -19
  4. package/build/actions.cjs.map +2 -2
  5. package/build/awareness/block-lookup.cjs +13 -0
  6. package/build/awareness/block-lookup.cjs.map +2 -2
  7. package/build/awareness/post-editor-awareness.cjs +21 -9
  8. package/build/awareness/post-editor-awareness.cjs.map +2 -2
  9. package/build/hooks/use-entity-block-editor.cjs +4 -4
  10. package/build/hooks/use-entity-block-editor.cjs.map +2 -2
  11. package/build/hooks/use-post-editor-awareness-state.cjs +2 -1
  12. package/build/hooks/use-post-editor-awareness-state.cjs.map +2 -2
  13. package/build/hooks/use-resource-permissions.cjs +3 -5
  14. package/build/hooks/use-resource-permissions.cjs.map +2 -2
  15. package/build/index.cjs +0 -6
  16. package/build/index.cjs.map +2 -2
  17. package/build/parsed-blocks-cache.cjs +36 -0
  18. package/build/parsed-blocks-cache.cjs.map +7 -0
  19. package/build/private-actions.cjs +25 -2
  20. package/build/private-actions.cjs.map +2 -2
  21. package/build/private-apis.cjs +9 -5
  22. package/build/private-apis.cjs.map +3 -3
  23. package/build/private-selectors.cjs +15 -0
  24. package/build/private-selectors.cjs.map +2 -2
  25. package/build/resolvers.cjs +12 -2
  26. package/build/resolvers.cjs.map +2 -2
  27. package/build/selectors.cjs +0 -15
  28. package/build/selectors.cjs.map +2 -2
  29. package/build/sync.cjs +5 -0
  30. package/build/sync.cjs.map +2 -2
  31. package/build/types.cjs +0 -16
  32. package/build/types.cjs.map +3 -3
  33. package/build/utils/block-selection-history.cjs +5 -4
  34. package/build/utils/block-selection-history.cjs.map +2 -2
  35. package/build/utils/crdt-blocks.cjs +3 -0
  36. package/build/utils/crdt-blocks.cjs.map +2 -2
  37. package/build/utils/crdt-user-selections.cjs +10 -2
  38. package/build/utils/crdt-user-selections.cjs.map +3 -3
  39. package/build/utils/crdt-utils.cjs +23 -0
  40. package/build/utils/crdt-utils.cjs.map +2 -2
  41. package/build/utils/crdt.cjs +28 -4
  42. package/build/utils/crdt.cjs.map +2 -2
  43. package/build-module/actions.mjs +0 -18
  44. package/build-module/actions.mjs.map +2 -2
  45. package/build-module/awareness/block-lookup.mjs +12 -0
  46. package/build-module/awareness/block-lookup.mjs.map +2 -2
  47. package/build-module/awareness/post-editor-awareness.mjs +26 -9
  48. package/build-module/awareness/post-editor-awareness.mjs.map +2 -2
  49. package/build-module/hooks/use-entity-block-editor.mjs +2 -2
  50. package/build-module/hooks/use-entity-block-editor.mjs.map +2 -2
  51. package/build-module/hooks/use-post-editor-awareness-state.mjs +2 -1
  52. package/build-module/hooks/use-post-editor-awareness-state.mjs.map +2 -2
  53. package/build-module/hooks/use-resource-permissions.mjs +3 -5
  54. package/build-module/hooks/use-resource-permissions.mjs.map +2 -2
  55. package/build-module/index.mjs +0 -4
  56. package/build-module/index.mjs.map +2 -2
  57. package/build-module/parsed-blocks-cache.mjs +10 -0
  58. package/build-module/parsed-blocks-cache.mjs.map +7 -0
  59. package/build-module/private-actions.mjs +23 -1
  60. package/build-module/private-actions.mjs.map +2 -2
  61. package/build-module/private-apis.mjs +12 -5
  62. package/build-module/private-apis.mjs.map +3 -3
  63. package/build-module/private-selectors.mjs +14 -0
  64. package/build-module/private-selectors.mjs.map +2 -2
  65. package/build-module/resolvers.mjs +12 -2
  66. package/build-module/resolvers.mjs.map +2 -2
  67. package/build-module/selectors.mjs +0 -14
  68. package/build-module/selectors.mjs.map +2 -2
  69. package/build-module/sync.mjs +4 -0
  70. package/build-module/sync.mjs.map +2 -2
  71. package/build-module/types.mjs +0 -9
  72. package/build-module/types.mjs.map +4 -4
  73. package/build-module/utils/block-selection-history.mjs +6 -4
  74. package/build-module/utils/block-selection-history.mjs.map +2 -2
  75. package/build-module/utils/crdt-blocks.mjs +3 -0
  76. package/build-module/utils/crdt-blocks.mjs.map +2 -2
  77. package/build-module/utils/crdt-user-selections.mjs +10 -2
  78. package/build-module/utils/crdt-user-selections.mjs.map +3 -3
  79. package/build-module/utils/crdt-utils.mjs +22 -0
  80. package/build-module/utils/crdt-utils.mjs.map +2 -2
  81. package/build-module/utils/crdt.mjs +32 -5
  82. package/build-module/utils/crdt.mjs.map +2 -2
  83. package/build-types/actions.d.ts +0 -11
  84. package/build-types/actions.d.ts.map +1 -1
  85. package/build-types/awareness/block-lookup.d.ts +12 -0
  86. package/build-types/awareness/block-lookup.d.ts.map +1 -1
  87. package/build-types/awareness/post-editor-awareness.d.ts +2 -5
  88. package/build-types/awareness/post-editor-awareness.d.ts.map +1 -1
  89. package/build-types/hooks/use-post-editor-awareness-state.d.ts.map +1 -1
  90. package/build-types/hooks/use-resource-permissions.d.ts.map +1 -1
  91. package/build-types/index.d.ts +0 -8
  92. package/build-types/index.d.ts.map +1 -1
  93. package/build-types/parsed-blocks-cache.d.ts +10 -0
  94. package/build-types/parsed-blocks-cache.d.ts.map +1 -0
  95. package/build-types/private-actions.d.ts +12 -0
  96. package/build-types/private-actions.d.ts.map +1 -1
  97. package/build-types/private-apis.d.ts +20 -0
  98. package/build-types/private-apis.d.ts.map +1 -1
  99. package/build-types/private-selectors.d.ts +10 -0
  100. package/build-types/private-selectors.d.ts.map +1 -1
  101. package/build-types/queried-data/selectors.d.ts +1 -1
  102. package/build-types/queried-data/selectors.d.ts.map +1 -1
  103. package/build-types/resolvers.d.ts.map +1 -1
  104. package/build-types/selectors.d.ts +0 -9
  105. package/build-types/selectors.d.ts.map +1 -1
  106. package/build-types/sync.d.ts +6 -0
  107. package/build-types/sync.d.ts.map +1 -1
  108. package/build-types/types.d.ts +3 -10
  109. package/build-types/types.d.ts.map +1 -1
  110. package/build-types/utils/block-selection-history.d.ts.map +1 -1
  111. package/build-types/utils/crdt-blocks.d.ts.map +1 -1
  112. package/build-types/utils/crdt-user-selections.d.ts +10 -1
  113. package/build-types/utils/crdt-user-selections.d.ts.map +1 -1
  114. package/build-types/utils/crdt-utils.d.ts +11 -0
  115. package/build-types/utils/crdt-utils.d.ts.map +1 -1
  116. package/build-types/utils/crdt.d.ts +5 -1
  117. package/build-types/utils/crdt.d.ts.map +1 -1
  118. package/package.json +20 -20
  119. package/src/actions.js +0 -29
  120. package/src/awareness/block-lookup.ts +34 -0
  121. package/src/awareness/post-editor-awareness.ts +32 -14
  122. package/src/awareness/test/block-lookup.ts +70 -0
  123. package/src/awareness/test/post-editor-awareness.ts +243 -0
  124. package/src/hooks/test/use-post-editor-awareness-state.ts +3 -0
  125. package/src/hooks/test/use-resource-permissions.js +57 -0
  126. package/src/hooks/use-entity-block-editor.js +2 -2
  127. package/src/hooks/use-post-editor-awareness-state.ts +1 -0
  128. package/src/hooks/use-resource-permissions.ts +5 -7
  129. package/src/index.js +0 -7
  130. package/src/parsed-blocks-cache.js +12 -0
  131. package/src/private-actions.js +34 -0
  132. package/src/{private-apis.js → private-apis.ts} +13 -3
  133. package/src/private-selectors.ts +33 -0
  134. package/src/resolvers.js +27 -5
  135. package/src/selectors.ts +0 -32
  136. package/src/sync.ts +9 -0
  137. package/src/test/resolvers.js +13 -7
  138. package/src/types.ts +16 -11
  139. package/src/utils/block-selection-history.ts +10 -7
  140. package/src/utils/crdt-blocks.ts +24 -0
  141. package/src/utils/crdt-user-selections.ts +15 -2
  142. package/src/utils/crdt-utils.ts +41 -0
  143. package/src/utils/crdt.ts +83 -10
  144. package/src/utils/test/block-selection-history.test.ts +42 -0
  145. package/src/utils/test/crdt-blocks.ts +37 -0
  146. package/src/utils/test/crdt-user-selections.ts +39 -0
  147. package/src/utils/test/crdt-utils.ts +52 -0
  148. package/src/utils/test/crdt.ts +208 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/awareness/post-editor-awareness.ts"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { dispatch, select, subscribe } from '@wordpress/data';\nimport { Y } from '@wordpress/sync';\n// @ts-ignore No exported types for block editor store selectors.\nimport { store as blockEditorStore } from '@wordpress/block-editor';\n\n/**\n * Internal dependencies\n */\nimport { BaseAwarenessState, baseEqualityFieldChecks } from './base-awareness';\nimport { getBlockPathInYdoc, resolveBlockClientIdByPath } from './block-lookup';\nimport {\n\tAWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS,\n\tLOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS,\n} from './config';\nimport { STORE_NAME as coreStore } from '../name';\nimport {\n\tasHtmlStringIndex,\n\thtmlIndexToRichTextOffset,\n} from '../utils/crdt-utils';\nimport {\n\tareSelectionsStatesEqual,\n\tgetSelectionState,\n\tSelectionType,\n} from '../utils/crdt-user-selections';\n\nimport { SelectionDirection } from '../types';\nimport type { SelectionState, WPBlockSelection } from '../types';\nimport type { YBlocks } from '../utils/crdt-blocks';\nimport type {\n\tDebugCollaboratorData,\n\tEditorState,\n\tPostEditorState,\n\tSerializableYItem,\n\tYDocDebugData,\n} from './types';\n\nexport class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {\n\tprotected equalityFieldChecks = {\n\t\t...baseEqualityFieldChecks,\n\t\teditorState: this.areEditorStatesEqual,\n\t};\n\n\tpublic constructor(\n\t\tdoc: Y.Doc,\n\t\tprivate kind: string,\n\t\tprivate name: string,\n\t\tprivate postId: number\n\t) {\n\t\tsuper( doc );\n\t}\n\n\tprotected onSetUp(): void {\n\t\tsuper.onSetUp();\n\n\t\tthis.subscribeToCollaboratorSelectionChanges();\n\t}\n\n\t/**\n\t * Subscribe to collaborator selection changes and update the selection state.\n\t */\n\tprivate subscribeToCollaboratorSelectionChanges(): void {\n\t\tconst {\n\t\t\tgetSelectionStart,\n\t\t\tgetSelectionEnd,\n\t\t\tgetSelectedBlocksInitialCaretPosition,\n\t\t} = select( blockEditorStore );\n\n\t\t// Keep track of the current selection in the outer scope so we can compare\n\t\t// in the subscription.\n\t\tlet selectionStart = getSelectionStart();\n\t\tlet selectionEnd = getSelectionEnd();\n\t\tlet localCursorTimeout: NodeJS.Timeout | null = null;\n\n\t\t// During rapid selection changes (e.g. undo restoring content and\n\t\t// selection), the debounce discards intermediate events. If we use the\n\t\t// last intermediate state instead of the overall change it can produce\n\t\t// the wrong direction.\n\t\t// Use selectionBeforeDebounce to capture the selection state from\n\t\t// before the debounce window so that direction is computed across the\n\t\t// full window when it fires.\n\t\tlet selectionBeforeDebounce: {\n\t\t\tstart: WPBlockSelection;\n\t\t\tend: WPBlockSelection;\n\t\t} | null = null;\n\n\t\tsubscribe( () => {\n\t\t\tconst newSelectionStart = getSelectionStart();\n\t\t\tconst newSelectionEnd = getSelectionEnd();\n\n\t\t\tif (\n\t\t\t\tnewSelectionStart === selectionStart &&\n\t\t\t\tnewSelectionEnd === selectionEnd\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// On the first change of a debounce window, snapshot the state\n\t\t\t// we're moving away from.\n\t\t\tif ( ! selectionBeforeDebounce ) {\n\t\t\t\tselectionBeforeDebounce = {\n\t\t\t\t\tstart: selectionStart,\n\t\t\t\t\tend: selectionEnd,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tselectionStart = newSelectionStart;\n\t\t\tselectionEnd = newSelectionEnd;\n\n\t\t\t// Typically selection position is only persisted after typing in a block, which\n\t\t\t// can cause selection position to be reset by other users making block updates.\n\t\t\t// Ensure we update the controlled selection right away, persisting our cursor position locally.\n\t\t\tconst initialPosition = getSelectedBlocksInitialCaretPosition();\n\t\t\tvoid this.updateSelectionInEntityRecord(\n\t\t\t\tselectionStart,\n\t\t\t\tselectionEnd,\n\t\t\t\tinitialPosition\n\t\t\t);\n\n\t\t\t// We receive two selection changes in quick succession\n\t\t\t// from local selection events:\n\t\t\t// { clientId: \"123...\", attributeKey: \"content\", offset: undefined }\n\t\t\t// { clientId: \"123...\", attributeKey: \"content\", offset: 554 }\n\t\t\t// Add a short debounce to avoid sending the first selection change.\n\t\t\tif ( localCursorTimeout ) {\n\t\t\t\tclearTimeout( localCursorTimeout );\n\t\t\t}\n\n\t\t\tlocalCursorTimeout = setTimeout( () => {\n\t\t\t\t// Compute direction across the full debounce window.\n\t\t\t\tconst selectionStateOptions: {\n\t\t\t\t\tselectionDirection?: SelectionDirection;\n\t\t\t\t} = {};\n\n\t\t\t\tif ( selectionBeforeDebounce ) {\n\t\t\t\t\tselectionStateOptions.selectionDirection =\n\t\t\t\t\t\tdetectSelectionDirection(\n\t\t\t\t\t\t\tselectionBeforeDebounce.start,\n\t\t\t\t\t\t\tselectionBeforeDebounce.end,\n\t\t\t\t\t\t\tselectionStart,\n\t\t\t\t\t\t\tselectionEnd\n\t\t\t\t\t\t);\n\n\t\t\t\t\t// Reset debounced selection state.\n\t\t\t\t\tselectionBeforeDebounce = null;\n\t\t\t\t}\n\n\t\t\t\tconst selectionState = getSelectionState(\n\t\t\t\t\tselectionStart,\n\t\t\t\t\tselectionEnd,\n\t\t\t\t\tthis.doc,\n\t\t\t\t\tselectionStateOptions\n\t\t\t\t);\n\n\t\t\t\tthis.setThrottledLocalStateField(\n\t\t\t\t\t'editorState',\n\t\t\t\t\t{ selection: selectionState },\n\t\t\t\t\tAWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS\n\t\t\t\t);\n\t\t\t}, LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS );\n\t\t} );\n\t}\n\n\t/**\n\t * Update the entity record with the current collaborator's selection.\n\t *\n\t * @param selectionStart - The start position of the selection.\n\t * @param selectionEnd - The end position of the selection.\n\t * @param initialPosition - The initial position of the selection.\n\t */\n\tprivate async updateSelectionInEntityRecord(\n\t\tselectionStart: WPBlockSelection,\n\t\tselectionEnd: WPBlockSelection,\n\t\tinitialPosition: number | null\n\t): Promise< void > {\n\t\t// Send an entityRecord `selection` update if we have a selection.\n\t\t//\n\t\t// Normally WordPress updates the `selection` property of the post when changes are made to blocks.\n\t\t// In a multi-user setup, block changes can occur from other users. When an entity is updated from another\n\t\t// user's changes, useBlockSync() in Gutenberg will reset the user's selection to the last saved selection.\n\t\t//\n\t\t// Manually adding an edit for each movement ensures that other user's changes to the document will\n\t\t// not cause the local user's selection to reset to the last local change location.\n\t\tconst edits = {\n\t\t\tselection: { selectionStart, selectionEnd, initialPosition },\n\t\t};\n\n\t\tconst options = {\n\t\t\tundoIgnore: true,\n\t\t};\n\n\t\t// @ts-ignore Types are not provided when using store name instead of store instance.\n\t\tdispatch( coreStore ).editEntityRecord(\n\t\t\tthis.kind,\n\t\t\tthis.name,\n\t\t\tthis.postId,\n\t\t\tedits,\n\t\t\toptions\n\t\t);\n\t}\n\n\t/**\n\t * Check if two editor states are equal.\n\t *\n\t * @param state1 - The first editor state.\n\t * @param state2 - The second editor state.\n\t * @return True if the editor states are equal, false otherwise.\n\t */\n\tprivate areEditorStatesEqual(\n\t\tstate1?: EditorState,\n\t\tstate2?: EditorState\n\t): boolean {\n\t\tif ( ! state1 || ! state2 ) {\n\t\t\treturn state1 === state2;\n\t\t}\n\n\t\tif ( ! state1.selection || ! state2.selection ) {\n\t\t\treturn state1.selection === state2.selection;\n\t\t}\n\n\t\treturn areSelectionsStatesEqual( state1.selection, state2.selection );\n\t}\n\n\t/**\n\t * Resolve a selection state to a text index and block client ID.\n\t *\n\t * For text-based selections, navigates up from the resolved Y.Text via\n\t * AbstractType.parent to find the containing block, then resolves the\n\t * local clientId via the block's tree path.\n\t * For WholeBlock selections, resolves the block's relative position and\n\t * then finds the local clientId via tree path.\n\t *\n\t * Tree-path resolution is used instead of reading the clientId directly\n\t * from the Yjs block because the local block-editor store may use different\n\t * clientIds (e.g. in \"Show Template\" mode where blocks are cloned).\n\t *\n\t * @param selection - The selection state.\n\t * @return The rich-text offset and block client ID, or nulls if not resolvable.\n\t */\n\tpublic convertSelectionStateToAbsolute( selection: SelectionState ): {\n\t\trichTextOffset: number | null;\n\t\tlocalClientId: string | null;\n\t} {\n\t\tif ( selection.type === SelectionType.None ) {\n\t\t\treturn { richTextOffset: null, localClientId: null };\n\t\t}\n\n\t\tif ( selection.type === SelectionType.WholeBlock ) {\n\t\t\tconst absolutePos = Y.createAbsolutePositionFromRelativePosition(\n\t\t\t\tselection.blockPosition,\n\t\t\t\tthis.doc\n\t\t\t);\n\n\t\t\tlet localClientId: string | null = null;\n\n\t\t\tif ( absolutePos && absolutePos.type instanceof Y.Array ) {\n\t\t\t\tconst parentArray = absolutePos.type as YBlocks;\n\t\t\t\tconst block = parentArray.get( absolutePos.index );\n\n\t\t\t\tif ( block instanceof Y.Map ) {\n\t\t\t\t\tconst path = getBlockPathInYdoc( block );\n\t\t\t\t\tlocalClientId = path\n\t\t\t\t\t\t? resolveBlockClientIdByPath( path )\n\t\t\t\t\t\t: null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { richTextOffset: null, localClientId };\n\t\t}\n\n\t\t// Text-based selections: resolve cursor position and navigate up.\n\t\tconst cursorPos =\n\t\t\t'cursorPosition' in selection\n\t\t\t\t? selection.cursorPosition\n\t\t\t\t: selection.cursorStartPosition;\n\n\t\tconst absolutePosition = Y.createAbsolutePositionFromRelativePosition(\n\t\t\tcursorPos.relativePosition,\n\t\t\tthis.doc\n\t\t);\n\n\t\tif ( ! absolutePosition ) {\n\t\t\treturn { richTextOffset: null, localClientId: null };\n\t\t}\n\n\t\t// Navigate up: Y.Text -> attributes Y.Map -> block Y.Map\n\t\tconst yType = absolutePosition.type.parent?.parent;\n\t\tconst path =\n\t\t\tyType instanceof Y.Map ? getBlockPathInYdoc( yType ) : null;\n\t\tconst localClientId = path ? resolveBlockClientIdByPath( path ) : null;\n\n\t\treturn {\n\t\t\trichTextOffset: htmlIndexToRichTextOffset(\n\t\t\t\tabsolutePosition.type.toString(),\n\t\t\t\tasHtmlStringIndex( absolutePosition.index )\n\t\t\t),\n\t\t\tlocalClientId,\n\t\t};\n\t}\n\n\t/**\n\t * Type guard to check if a struct is a Y.Item (not Y.GC)\n\t * @param struct - The struct to check.\n\t * @return True if the struct is a Y.Item, false otherwise.\n\t */\n\tprivate isYItem( struct: Y.Item | Y.GC ): struct is Y.Item {\n\t\treturn 'content' in struct;\n\t}\n\n\t/**\n\t * Get data for debugging, using the awareness state.\n\t *\n\t * @return {YDocDebugData} The debug data.\n\t */\n\tpublic getDebugData(): YDocDebugData {\n\t\tconst ydoc = this.doc;\n\n\t\t// Manually extract doc data to avoid deprecated toJSON method\n\t\tconst docData: Record< string, unknown > = Object.fromEntries(\n\t\t\tArray.from( ydoc.share, ( [ key, value ] ) => [\n\t\t\t\tkey,\n\t\t\t\tvalue.toJSON(),\n\t\t\t] )\n\t\t);\n\n\t\t// Build collaboratorMap from awareness store (all collaborators seen this session)\n\t\tconst collaboratorMapData = new Map< string, DebugCollaboratorData >(\n\t\t\tArray.from( this.getSeenStates().entries() ).map(\n\t\t\t\t( [ clientId, collaboratorState ] ) => [\n\t\t\t\t\tString( clientId ),\n\t\t\t\t\t{\n\t\t\t\t\t\tname: collaboratorState.collaboratorInfo.name,\n\t\t\t\t\t\twpUserId: collaboratorState.collaboratorInfo.id,\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\n\t\t// Serialize Yjs client items to avoid deep nesting\n\t\tconst serializableClientItems: Record<\n\t\t\tnumber,\n\t\t\tArray< SerializableYItem >\n\t\t> = {};\n\n\t\tydoc.store.clients.forEach( ( structs, clientId ) => {\n\t\t\t// Filter for Y.Item only (skip Y.GC garbage collection structs)\n\t\t\tconst items = structs.filter( this.isYItem );\n\n\t\t\tserializableClientItems[ clientId ] = items.map( ( item ) => {\n\t\t\t\tconst { left, right, ...rest } = item;\n\n\t\t\t\treturn {\n\t\t\t\t\t...rest,\n\t\t\t\t\tleft: left\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: left.id,\n\t\t\t\t\t\t\t\tlength: left.length,\n\t\t\t\t\t\t\t\torigin: left.origin,\n\t\t\t\t\t\t\t\tcontent: left.content,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: null,\n\t\t\t\t\tright: right\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: right.id,\n\t\t\t\t\t\t\t\tlength: right.length,\n\t\t\t\t\t\t\t\torigin: right.origin,\n\t\t\t\t\t\t\t\tcontent: right.content,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: null,\n\t\t\t\t};\n\t\t\t} );\n\t\t} );\n\n\t\treturn {\n\t\t\tdoc: docData,\n\t\t\tclients: serializableClientItems,\n\t\t\tcollaboratorMap: Object.fromEntries( collaboratorMapData ),\n\t\t};\n\t}\n}\n\n/**\n * Detect the direction of a selection change by comparing old and new edges.\n *\n * When the user extends a selection backward (e.g. Shift+Left), the\n * selectionStart edge moves while selectionEnd stays fixed, so the caret\n * is at the start. The reverse is true for forward extension.\n *\n * @param prevStart - The previous selectionStart.\n * @param prevEnd - The previous selectionEnd.\n * @param newStart - The new selectionStart.\n * @param newEnd - The new selectionEnd.\n * @return The detected direction, defaulting to Forward when indeterminate.\n */\nfunction detectSelectionDirection(\n\tprevStart: WPBlockSelection,\n\tprevEnd: WPBlockSelection,\n\tnewStart: WPBlockSelection,\n\tnewEnd: WPBlockSelection\n): SelectionDirection {\n\tconst startMoved = ! areBlockSelectionsEqual( prevStart, newStart );\n\tconst endMoved = ! areBlockSelectionsEqual( prevEnd, newEnd );\n\n\tif ( startMoved && ! endMoved ) {\n\t\treturn SelectionDirection.Backward;\n\t}\n\n\treturn SelectionDirection.Forward;\n}\n\n/**\n * Compare two WPBlockSelection objects by value.\n *\n * @param a - First selection.\n * @param b - Second selection.\n * @return True if all fields are equal.\n */\nfunction areBlockSelectionsEqual(\n\ta: WPBlockSelection,\n\tb: WPBlockSelection\n): boolean {\n\treturn (\n\t\ta.clientId === b.clientId &&\n\t\ta.attributeKey === b.attributeKey &&\n\t\ta.offset === b.offset\n\t);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { dispatch, select, subscribe } from '@wordpress/data';\nimport { Y } from '@wordpress/sync';\n// @ts-ignore No exported types for block editor store selectors.\nimport { store as blockEditorStore } from '@wordpress/block-editor';\n\n/**\n * Internal dependencies\n */\nimport { BaseAwarenessState, baseEqualityFieldChecks } from './base-awareness';\nimport {\n\tgetBlockPathInYdoc,\n\tgetContainingBlockYMap,\n\tresolveBlockClientIdByPath,\n} from './block-lookup';\nimport {\n\tAWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS,\n\tLOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS,\n} from './config';\nimport { STORE_NAME as coreStore } from '../name';\nimport {\n\tasHtmlStringIndex,\n\thtmlIndexToRichTextOffset,\n} from '../utils/crdt-utils';\nimport {\n\tareSelectionsStatesEqual,\n\tgetSelectionState,\n\tSelectionType,\n\tSelectionDirection,\n} from '../utils/crdt-user-selections';\n\nimport type {\n\tResolvedSelection,\n\tSelectionState,\n\tWPBlockSelection,\n} from '../types';\nimport type { YBlocks } from '../utils/crdt-blocks';\nimport type {\n\tDebugCollaboratorData,\n\tEditorState,\n\tPostEditorState,\n\tSerializableYItem,\n\tYDocDebugData,\n} from './types';\n\nexport class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {\n\tprotected equalityFieldChecks = {\n\t\t...baseEqualityFieldChecks,\n\t\teditorState: this.areEditorStatesEqual,\n\t};\n\n\tpublic constructor(\n\t\tdoc: Y.Doc,\n\t\tprivate kind: string,\n\t\tprivate name: string,\n\t\tprivate postId: number\n\t) {\n\t\tsuper( doc );\n\t}\n\n\tprotected onSetUp(): void {\n\t\tsuper.onSetUp();\n\n\t\tthis.subscribeToCollaboratorSelectionChanges();\n\t}\n\n\t/**\n\t * Subscribe to collaborator selection changes and update the selection state.\n\t */\n\tprivate subscribeToCollaboratorSelectionChanges(): void {\n\t\tconst {\n\t\t\tgetSelectionStart,\n\t\t\tgetSelectionEnd,\n\t\t\tgetSelectedBlocksInitialCaretPosition,\n\t\t} = select( blockEditorStore );\n\n\t\t// Keep track of the current selection in the outer scope so we can compare\n\t\t// in the subscription.\n\t\tlet selectionStart = getSelectionStart();\n\t\tlet selectionEnd = getSelectionEnd();\n\t\tlet localCursorTimeout: NodeJS.Timeout | null = null;\n\n\t\t// During rapid selection changes (e.g. undo restoring content and\n\t\t// selection), the debounce discards intermediate events. If we use the\n\t\t// last intermediate state instead of the overall change it can produce\n\t\t// the wrong direction.\n\t\t// Use selectionBeforeDebounce to capture the selection state from\n\t\t// before the debounce window so that direction is computed across the\n\t\t// full window when it fires.\n\t\tlet selectionBeforeDebounce: {\n\t\t\tstart: WPBlockSelection;\n\t\t\tend: WPBlockSelection;\n\t\t} | null = null;\n\n\t\tsubscribe( () => {\n\t\t\tconst newSelectionStart = getSelectionStart();\n\t\t\tconst newSelectionEnd = getSelectionEnd();\n\n\t\t\tif (\n\t\t\t\tnewSelectionStart === selectionStart &&\n\t\t\t\tnewSelectionEnd === selectionEnd\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// On the first change of a debounce window, snapshot the state\n\t\t\t// we're moving away from.\n\t\t\tif ( ! selectionBeforeDebounce ) {\n\t\t\t\tselectionBeforeDebounce = {\n\t\t\t\t\tstart: selectionStart,\n\t\t\t\t\tend: selectionEnd,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tselectionStart = newSelectionStart;\n\t\t\tselectionEnd = newSelectionEnd;\n\n\t\t\t// Typically selection position is only persisted after typing in a block, which\n\t\t\t// can cause selection position to be reset by other users making block updates.\n\t\t\t// Ensure we update the controlled selection right away, persisting our cursor position locally.\n\t\t\tconst initialPosition = getSelectedBlocksInitialCaretPosition();\n\t\t\tvoid this.updateSelectionInEntityRecord(\n\t\t\t\tselectionStart,\n\t\t\t\tselectionEnd,\n\t\t\t\tinitialPosition\n\t\t\t);\n\n\t\t\t// We receive two selection changes in quick succession\n\t\t\t// from local selection events:\n\t\t\t// { clientId: \"123...\", attributeKey: \"content\", offset: undefined }\n\t\t\t// { clientId: \"123...\", attributeKey: \"content\", offset: 554 }\n\t\t\t// Add a short debounce to avoid sending the first selection change.\n\t\t\tif ( localCursorTimeout ) {\n\t\t\t\tclearTimeout( localCursorTimeout );\n\t\t\t}\n\n\t\t\tlocalCursorTimeout = setTimeout( () => {\n\t\t\t\t// Compute direction across the full debounce window.\n\t\t\t\tconst selectionStateOptions: {\n\t\t\t\t\tselectionDirection?: SelectionDirection;\n\t\t\t\t} = {};\n\n\t\t\t\tif ( selectionBeforeDebounce ) {\n\t\t\t\t\tselectionStateOptions.selectionDirection =\n\t\t\t\t\t\tdetectSelectionDirection(\n\t\t\t\t\t\t\tselectionBeforeDebounce.start,\n\t\t\t\t\t\t\tselectionBeforeDebounce.end,\n\t\t\t\t\t\t\tselectionStart,\n\t\t\t\t\t\t\tselectionEnd\n\t\t\t\t\t\t);\n\n\t\t\t\t\t// Reset debounced selection state.\n\t\t\t\t\tselectionBeforeDebounce = null;\n\t\t\t\t}\n\n\t\t\t\tconst selectionState = getSelectionState(\n\t\t\t\t\tselectionStart,\n\t\t\t\t\tselectionEnd,\n\t\t\t\t\tthis.doc,\n\t\t\t\t\tselectionStateOptions\n\t\t\t\t);\n\n\t\t\t\tthis.setThrottledLocalStateField(\n\t\t\t\t\t'editorState',\n\t\t\t\t\t{ selection: selectionState },\n\t\t\t\t\tAWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS\n\t\t\t\t);\n\t\t\t}, LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS );\n\t\t} );\n\t}\n\n\t/**\n\t * Update the entity record with the current collaborator's selection.\n\t *\n\t * @param selectionStart - The start position of the selection.\n\t * @param selectionEnd - The end position of the selection.\n\t * @param initialPosition - The initial position of the selection.\n\t */\n\tprivate async updateSelectionInEntityRecord(\n\t\tselectionStart: WPBlockSelection,\n\t\tselectionEnd: WPBlockSelection,\n\t\tinitialPosition: number | null\n\t): Promise< void > {\n\t\t// Send an entityRecord `selection` update if we have a selection.\n\t\t//\n\t\t// Normally WordPress updates the `selection` property of the post when changes are made to blocks.\n\t\t// In a multi-user setup, block changes can occur from other users. When an entity is updated from another\n\t\t// user's changes, useBlockSync() in Gutenberg will reset the user's selection to the last saved selection.\n\t\t//\n\t\t// Manually adding an edit for each movement ensures that other user's changes to the document will\n\t\t// not cause the local user's selection to reset to the last local change location.\n\t\tconst edits = {\n\t\t\tselection: { selectionStart, selectionEnd, initialPosition },\n\t\t};\n\n\t\tconst options = {\n\t\t\tundoIgnore: true,\n\t\t};\n\n\t\t// @ts-ignore Types are not provided when using store name instead of store instance.\n\t\tdispatch( coreStore ).editEntityRecord(\n\t\t\tthis.kind,\n\t\t\tthis.name,\n\t\t\tthis.postId,\n\t\t\tedits,\n\t\t\toptions\n\t\t);\n\t}\n\n\t/**\n\t * Check if two editor states are equal.\n\t *\n\t * @param state1 - The first editor state.\n\t * @param state2 - The second editor state.\n\t * @return True if the editor states are equal, false otherwise.\n\t */\n\tprivate areEditorStatesEqual(\n\t\tstate1?: EditorState,\n\t\tstate2?: EditorState\n\t): boolean {\n\t\tif ( ! state1 || ! state2 ) {\n\t\t\treturn state1 === state2;\n\t\t}\n\n\t\tif ( ! state1.selection || ! state2.selection ) {\n\t\t\treturn state1.selection === state2.selection;\n\t\t}\n\n\t\treturn areSelectionsStatesEqual( state1.selection, state2.selection );\n\t}\n\n\t/**\n\t * Resolve a selection state to a text index and block client ID.\n\t *\n\t * For text-based selections, navigates up from the resolved Y.Text via\n\t * AbstractType.parent to find the containing block, then resolves the\n\t * local clientId via the block's tree path.\n\t * For WholeBlock selections, resolves the block's relative position and\n\t * then finds the local clientId via tree path.\n\t *\n\t * Tree-path resolution is used instead of reading the clientId directly\n\t * from the Yjs block because the local block-editor store may use different\n\t * clientIds (e.g. in \"Show Template\" mode where blocks are cloned).\n\t *\n\t * @param selection - The selection state.\n\t * @return The rich-text offset and block client ID, or nulls if not resolvable.\n\t */\n\tpublic convertSelectionStateToAbsolute(\n\t\tselection: SelectionState\n\t): ResolvedSelection {\n\t\tif ( selection.type === SelectionType.None ) {\n\t\t\treturn {\n\t\t\t\trichTextOffset: null,\n\t\t\t\tlocalClientId: null,\n\t\t\t\tattributeKey: null,\n\t\t\t};\n\t\t}\n\n\t\tif ( selection.type === SelectionType.WholeBlock ) {\n\t\t\tconst absolutePos = Y.createAbsolutePositionFromRelativePosition(\n\t\t\t\tselection.blockPosition,\n\t\t\t\tthis.doc\n\t\t\t);\n\n\t\t\tlet localClientId: string | null = null;\n\n\t\t\tif ( absolutePos && absolutePos.type instanceof Y.Array ) {\n\t\t\t\tconst parentArray = absolutePos.type as YBlocks;\n\t\t\t\tconst block = parentArray.get( absolutePos.index );\n\n\t\t\t\tif ( block instanceof Y.Map ) {\n\t\t\t\t\tconst path = getBlockPathInYdoc( block );\n\t\t\t\t\tlocalClientId = path\n\t\t\t\t\t\t? resolveBlockClientIdByPath( path )\n\t\t\t\t\t\t: null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\trichTextOffset: null,\n\t\t\t\tlocalClientId,\n\t\t\t\tattributeKey: null,\n\t\t\t};\n\t\t}\n\n\t\t// Text-based selections: resolve cursor position and navigate up.\n\t\tconst cursorPos =\n\t\t\t'cursorPosition' in selection\n\t\t\t\t? selection.cursorPosition\n\t\t\t\t: selection.cursorStartPosition;\n\n\t\tconst absolutePosition = Y.createAbsolutePositionFromRelativePosition(\n\t\t\tcursorPos.relativePosition,\n\t\t\tthis.doc\n\t\t);\n\n\t\tif ( ! absolutePosition ) {\n\t\t\treturn {\n\t\t\t\trichTextOffset: null,\n\t\t\t\tlocalClientId: null,\n\t\t\t\tattributeKey: null,\n\t\t\t};\n\t\t}\n\n\t\tconst yType = getContainingBlockYMap( absolutePosition.type );\n\t\tconst path = yType ? getBlockPathInYdoc( yType ) : null;\n\t\tconst localClientId = path ? resolveBlockClientIdByPath( path ) : null;\n\n\t\treturn {\n\t\t\trichTextOffset: htmlIndexToRichTextOffset(\n\t\t\t\tabsolutePosition.type.toString(),\n\t\t\t\tasHtmlStringIndex( absolutePosition.index )\n\t\t\t),\n\t\t\tlocalClientId,\n\t\t\tattributeKey: cursorPos.attributeKey ?? null,\n\t\t};\n\t}\n\n\t/**\n\t * Type guard to check if a struct is a Y.Item (not Y.GC)\n\t * @param struct - The struct to check.\n\t * @return True if the struct is a Y.Item, false otherwise.\n\t */\n\tprivate isYItem( struct: Y.Item | Y.GC ): struct is Y.Item {\n\t\treturn 'content' in struct;\n\t}\n\n\t/**\n\t * Get data for debugging, using the awareness state.\n\t *\n\t * @return {YDocDebugData} The debug data.\n\t */\n\tpublic getDebugData(): YDocDebugData {\n\t\tconst ydoc = this.doc;\n\n\t\t// Manually extract doc data to avoid deprecated toJSON method\n\t\tconst docData: Record< string, unknown > = Object.fromEntries(\n\t\t\tArray.from( ydoc.share, ( [ key, value ] ) => [\n\t\t\t\tkey,\n\t\t\t\tvalue.toJSON(),\n\t\t\t] )\n\t\t);\n\n\t\t// Build collaboratorMap from awareness store (all collaborators seen this session)\n\t\tconst collaboratorMapData = new Map< string, DebugCollaboratorData >(\n\t\t\tArray.from( this.getSeenStates().entries() ).map(\n\t\t\t\t( [ clientId, collaboratorState ] ) => [\n\t\t\t\t\tString( clientId ),\n\t\t\t\t\t{\n\t\t\t\t\t\tname: collaboratorState.collaboratorInfo.name,\n\t\t\t\t\t\twpUserId: collaboratorState.collaboratorInfo.id,\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\n\t\t// Serialize Yjs client items to avoid deep nesting\n\t\tconst serializableClientItems: Record<\n\t\t\tnumber,\n\t\t\tArray< SerializableYItem >\n\t\t> = {};\n\n\t\tydoc.store.clients.forEach( ( structs, clientId ) => {\n\t\t\t// Filter for Y.Item only (skip Y.GC garbage collection structs)\n\t\t\tconst items = structs.filter( this.isYItem );\n\n\t\t\tserializableClientItems[ clientId ] = items.map( ( item ) => {\n\t\t\t\tconst { left, right, ...rest } = item;\n\n\t\t\t\treturn {\n\t\t\t\t\t...rest,\n\t\t\t\t\tleft: left\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: left.id,\n\t\t\t\t\t\t\t\tlength: left.length,\n\t\t\t\t\t\t\t\torigin: left.origin,\n\t\t\t\t\t\t\t\tcontent: left.content,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: null,\n\t\t\t\t\tright: right\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: right.id,\n\t\t\t\t\t\t\t\tlength: right.length,\n\t\t\t\t\t\t\t\torigin: right.origin,\n\t\t\t\t\t\t\t\tcontent: right.content,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: null,\n\t\t\t\t};\n\t\t\t} );\n\t\t} );\n\n\t\treturn {\n\t\t\tdoc: docData,\n\t\t\tclients: serializableClientItems,\n\t\t\tcollaboratorMap: Object.fromEntries( collaboratorMapData ),\n\t\t};\n\t}\n}\n\n/**\n * Detect the direction of a selection change by comparing old and new edges.\n *\n * When the user extends a selection backward (e.g. Shift+Left), the\n * selectionStart edge moves while selectionEnd stays fixed, so the caret\n * is at the start. The reverse is true for forward extension.\n *\n * @param prevStart - The previous selectionStart.\n * @param prevEnd - The previous selectionEnd.\n * @param newStart - The new selectionStart.\n * @param newEnd - The new selectionEnd.\n * @return The detected direction, defaulting to Forward when indeterminate.\n */\nfunction detectSelectionDirection(\n\tprevStart: WPBlockSelection,\n\tprevEnd: WPBlockSelection,\n\tnewStart: WPBlockSelection,\n\tnewEnd: WPBlockSelection\n): SelectionDirection {\n\tconst startMoved = ! areBlockSelectionsEqual( prevStart, newStart );\n\tconst endMoved = ! areBlockSelectionsEqual( prevEnd, newEnd );\n\n\tif ( startMoved && ! endMoved ) {\n\t\treturn SelectionDirection.Backward;\n\t}\n\n\treturn SelectionDirection.Forward;\n}\n\n/**\n * Compare two WPBlockSelection objects by value.\n *\n * @param a - First selection.\n * @param b - Second selection.\n * @return True if all fields are equal.\n */\nfunction areBlockSelectionsEqual(\n\ta: WPBlockSelection,\n\tb: WPBlockSelection\n): boolean {\n\treturn (\n\t\ta.clientId === b.clientId &&\n\t\ta.attributeKey === b.attributeKey &&\n\t\ta.offset === b.offset\n\t);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["localClientId", "path"]
7
7
  }
@@ -5,8 +5,8 @@ import { parse, __unstableSerializeAndClean } from "@wordpress/blocks";
5
5
  import { STORE_NAME } from "../name.mjs";
6
6
  import useEntityId from "./use-entity-id.mjs";
7
7
  import { updateFootnotesFromMeta } from "../footnotes/index.mjs";
8
+ import { parsedBlocksCache, getCacheKey } from "../parsed-blocks-cache.mjs";
8
9
  var EMPTY_ARRAY = [];
9
- var parsedBlocksCache = /* @__PURE__ */ new Map();
10
10
  function useEntityBlockEditor(kind, name, { id: _id } = {}) {
11
11
  const providerId = useEntityId(kind, name);
12
12
  const id = _id ?? providerId;
@@ -36,7 +36,7 @@ function useEntityBlockEditor(kind, name, { id: _id } = {}) {
36
36
  if (!content || typeof content !== "string") {
37
37
  return EMPTY_ARRAY;
38
38
  }
39
- const cacheKey = `${kind}:${name}:${id}`;
39
+ const cacheKey = getCacheKey(kind, name, id);
40
40
  const cached = parsedBlocksCache.get(cacheKey);
41
41
  let _blocks;
42
42
  if (cached && cached.content === content) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/hooks/use-entity-block-editor.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useCallback, useMemo } from '@wordpress/element';\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { parse, __unstableSerializeAndClean } from '@wordpress/blocks';\n\n/**\n * Internal dependencies\n */\nimport { STORE_NAME } from '../name';\nimport useEntityId from './use-entity-id';\nimport { updateFootnotesFromMeta } from '../footnotes';\n\nconst EMPTY_ARRAY = [];\nconst parsedBlocksCache = new Map();\n\n/**\n * Hook that returns block content getters and setters for\n * the nearest provided entity of the specified type.\n *\n * The return value has the shape `[ blocks, onInput, onChange ]`.\n * `onInput` is for block changes that don't create undo levels\n * or dirty the post, non-persistent changes, and `onChange` is for\n * persistent changes. They map directly to the props of a\n * `BlockEditorProvider` and are intended to be used with it,\n * or similar components or hooks.\n *\n * @param {string} kind The entity kind.\n * @param {string} name The entity name.\n * @param {Object} options\n * @param {string} [options.id] An entity ID to use instead of the context-provided one.\n *\n * @return {[unknown[], Function, Function]} The block array and setters.\n */\nexport default function useEntityBlockEditor( kind, name, { id: _id } = {} ) {\n\tconst providerId = useEntityId( kind, name );\n\tconst id = _id ?? providerId;\n\tconst { content, editedBlocks, meta } = useSelect(\n\t\t( select ) => {\n\t\t\tif ( ! id ) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst { getEditedEntityRecord } = select( STORE_NAME );\n\t\t\tconst editedRecord = getEditedEntityRecord( kind, name, id );\n\t\t\treturn {\n\t\t\t\teditedBlocks: editedRecord.blocks,\n\t\t\t\tcontent: editedRecord.content,\n\t\t\t\tmeta: editedRecord.meta,\n\t\t\t};\n\t\t},\n\t\t[ kind, name, id ]\n\t);\n\tconst { __unstableCreateUndoLevel, editEntityRecord } =\n\t\tuseDispatch( STORE_NAME );\n\n\tconst blocks = useMemo( () => {\n\t\tif ( ! id ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( editedBlocks ) {\n\t\t\treturn editedBlocks;\n\t\t}\n\n\t\tif ( ! content || typeof content !== 'string' ) {\n\t\t\treturn EMPTY_ARRAY;\n\t\t}\n\n\t\t// Cache parsed blocks by entity identity. Store the content\n\t\t// alongside the blocks so we can validate it hasn't changed.\n\t\tconst cacheKey = `${ kind }:${ name }:${ id }`;\n\t\tconst cached = parsedBlocksCache.get( cacheKey );\n\t\tlet _blocks;\n\n\t\tif ( cached && cached.content === content ) {\n\t\t\t_blocks = cached.blocks;\n\t\t} else {\n\t\t\t_blocks = parse( content );\n\t\t\tparsedBlocksCache.set( cacheKey, { content, blocks: _blocks } );\n\t\t}\n\n\t\treturn _blocks;\n\t}, [ kind, name, id, editedBlocks, content ] );\n\n\tconst onChange = useCallback(\n\t\t( newBlocks, options ) => {\n\t\t\tconst noChange = blocks === newBlocks;\n\t\t\tif ( noChange ) {\n\t\t\t\treturn __unstableCreateUndoLevel( kind, name, id );\n\t\t\t}\n\t\t\tconst { selection, ...rest } = options;\n\n\t\t\t// We create a new function here on every persistent edit\n\t\t\t// to make sure the edit makes the post dirty and creates\n\t\t\t// a new undo level.\n\t\t\tconst edits = {\n\t\t\t\tselection,\n\t\t\t\tcontent: ( { blocks: blocksForSerialization = [] } ) =>\n\t\t\t\t\t__unstableSerializeAndClean( blocksForSerialization ),\n\t\t\t\t...updateFootnotesFromMeta( newBlocks, meta ),\n\t\t\t};\n\n\t\t\teditEntityRecord( kind, name, id, edits, {\n\t\t\t\tisCached: false,\n\t\t\t\t...rest,\n\t\t\t} );\n\t\t},\n\t\t[\n\t\t\tkind,\n\t\t\tname,\n\t\t\tid,\n\t\t\tblocks,\n\t\t\tmeta,\n\t\t\t__unstableCreateUndoLevel,\n\t\t\teditEntityRecord,\n\t\t]\n\t);\n\n\tconst onInput = useCallback(\n\t\t( newBlocks, options ) => {\n\t\t\tconst { selection, ...rest } = options;\n\t\t\tconst edits = {\n\t\t\t\tselection,\n\t\t\t\t...updateFootnotesFromMeta( newBlocks, meta ),\n\t\t\t};\n\n\t\t\teditEntityRecord( kind, name, id, edits, {\n\t\t\t\tisCached: true,\n\t\t\t\t...rest,\n\t\t\t} );\n\t\t},\n\t\t[ kind, name, id, meta, editEntityRecord ]\n\t);\n\n\treturn [ blocks, onInput, onChange ];\n}\n"],
5
- "mappings": ";AAGA,SAAS,aAAa,eAAe;AACrC,SAAS,aAAa,iBAAiB;AACvC,SAAS,OAAO,mCAAmC;AAKnD,SAAS,kBAAkB;AAC3B,OAAO,iBAAiB;AACxB,SAAS,+BAA+B;AAExC,IAAM,cAAc,CAAC;AACrB,IAAM,oBAAoB,oBAAI,IAAI;AAoBnB,SAAR,qBAAuC,MAAM,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,GAAI;AAC5E,QAAM,aAAa,YAAa,MAAM,IAAK;AAC3C,QAAM,KAAK,OAAO;AAClB,QAAM,EAAE,SAAS,cAAc,KAAK,IAAI;AAAA,IACvC,CAAE,WAAY;AACb,UAAK,CAAE,IAAK;AACX,eAAO,CAAC;AAAA,MACT;AACA,YAAM,EAAE,sBAAsB,IAAI,OAAQ,UAAW;AACrD,YAAM,eAAe,sBAAuB,MAAM,MAAM,EAAG;AAC3D,aAAO;AAAA,QACN,cAAc,aAAa;AAAA,QAC3B,SAAS,aAAa;AAAA,QACtB,MAAM,aAAa;AAAA,MACpB;AAAA,IACD;AAAA,IACA,CAAE,MAAM,MAAM,EAAG;AAAA,EAClB;AACA,QAAM,EAAE,2BAA2B,iBAAiB,IACnD,YAAa,UAAW;AAEzB,QAAM,SAAS,QAAS,MAAM;AAC7B,QAAK,CAAE,IAAK;AACX,aAAO;AAAA,IACR;AAEA,QAAK,cAAe;AACnB,aAAO;AAAA,IACR;AAEA,QAAK,CAAE,WAAW,OAAO,YAAY,UAAW;AAC/C,aAAO;AAAA,IACR;AAIA,UAAM,WAAW,GAAI,IAAK,IAAK,IAAK,IAAK,EAAG;AAC5C,UAAM,SAAS,kBAAkB,IAAK,QAAS;AAC/C,QAAI;AAEJ,QAAK,UAAU,OAAO,YAAY,SAAU;AAC3C,gBAAU,OAAO;AAAA,IAClB,OAAO;AACN,gBAAU,MAAO,OAAQ;AACzB,wBAAkB,IAAK,UAAU,EAAE,SAAS,QAAQ,QAAQ,CAAE;AAAA,IAC/D;AAEA,WAAO;AAAA,EACR,GAAG,CAAE,MAAM,MAAM,IAAI,cAAc,OAAQ,CAAE;AAE7C,QAAM,WAAW;AAAA,IAChB,CAAE,WAAW,YAAa;AACzB,YAAM,WAAW,WAAW;AAC5B,UAAK,UAAW;AACf,eAAO,0BAA2B,MAAM,MAAM,EAAG;AAAA,MAClD;AACA,YAAM,EAAE,WAAW,GAAG,KAAK,IAAI;AAK/B,YAAM,QAAQ;AAAA,QACb;AAAA,QACA,SAAS,CAAE,EAAE,QAAQ,yBAAyB,CAAC,EAAE,MAChD,4BAA6B,sBAAuB;AAAA,QACrD,GAAG,wBAAyB,WAAW,IAAK;AAAA,MAC7C;AAEA,uBAAkB,MAAM,MAAM,IAAI,OAAO;AAAA,QACxC,UAAU;AAAA,QACV,GAAG;AAAA,MACJ,CAAE;AAAA,IACH;AAAA,IACA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,QAAM,UAAU;AAAA,IACf,CAAE,WAAW,YAAa;AACzB,YAAM,EAAE,WAAW,GAAG,KAAK,IAAI;AAC/B,YAAM,QAAQ;AAAA,QACb;AAAA,QACA,GAAG,wBAAyB,WAAW,IAAK;AAAA,MAC7C;AAEA,uBAAkB,MAAM,MAAM,IAAI,OAAO;AAAA,QACxC,UAAU;AAAA,QACV,GAAG;AAAA,MACJ,CAAE;AAAA,IACH;AAAA,IACA,CAAE,MAAM,MAAM,IAAI,MAAM,gBAAiB;AAAA,EAC1C;AAEA,SAAO,CAAE,QAAQ,SAAS,QAAS;AACpC;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useCallback, useMemo } from '@wordpress/element';\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { parse, __unstableSerializeAndClean } from '@wordpress/blocks';\n\n/**\n * Internal dependencies\n */\nimport { STORE_NAME } from '../name';\nimport useEntityId from './use-entity-id';\nimport { updateFootnotesFromMeta } from '../footnotes';\nimport { parsedBlocksCache, getCacheKey } from '../parsed-blocks-cache';\n\nconst EMPTY_ARRAY = [];\n\n/**\n * Hook that returns block content getters and setters for\n * the nearest provided entity of the specified type.\n *\n * The return value has the shape `[ blocks, onInput, onChange ]`.\n * `onInput` is for block changes that don't create undo levels\n * or dirty the post, non-persistent changes, and `onChange` is for\n * persistent changes. They map directly to the props of a\n * `BlockEditorProvider` and are intended to be used with it,\n * or similar components or hooks.\n *\n * @param {string} kind The entity kind.\n * @param {string} name The entity name.\n * @param {Object} options\n * @param {string} [options.id] An entity ID to use instead of the context-provided one.\n *\n * @return {[unknown[], Function, Function]} The block array and setters.\n */\nexport default function useEntityBlockEditor( kind, name, { id: _id } = {} ) {\n\tconst providerId = useEntityId( kind, name );\n\tconst id = _id ?? providerId;\n\tconst { content, editedBlocks, meta } = useSelect(\n\t\t( select ) => {\n\t\t\tif ( ! id ) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst { getEditedEntityRecord } = select( STORE_NAME );\n\t\t\tconst editedRecord = getEditedEntityRecord( kind, name, id );\n\t\t\treturn {\n\t\t\t\teditedBlocks: editedRecord.blocks,\n\t\t\t\tcontent: editedRecord.content,\n\t\t\t\tmeta: editedRecord.meta,\n\t\t\t};\n\t\t},\n\t\t[ kind, name, id ]\n\t);\n\tconst { __unstableCreateUndoLevel, editEntityRecord } =\n\t\tuseDispatch( STORE_NAME );\n\n\tconst blocks = useMemo( () => {\n\t\tif ( ! id ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( editedBlocks ) {\n\t\t\treturn editedBlocks;\n\t\t}\n\n\t\tif ( ! content || typeof content !== 'string' ) {\n\t\t\treturn EMPTY_ARRAY;\n\t\t}\n\n\t\t// Cache parsed blocks by entity identity. Store the content\n\t\t// alongside the blocks so we can validate it hasn't changed.\n\t\tconst cacheKey = getCacheKey( kind, name, id );\n\t\tconst cached = parsedBlocksCache.get( cacheKey );\n\t\tlet _blocks;\n\n\t\tif ( cached && cached.content === content ) {\n\t\t\t_blocks = cached.blocks;\n\t\t} else {\n\t\t\t_blocks = parse( content );\n\t\t\tparsedBlocksCache.set( cacheKey, { content, blocks: _blocks } );\n\t\t}\n\n\t\treturn _blocks;\n\t}, [ kind, name, id, editedBlocks, content ] );\n\n\tconst onChange = useCallback(\n\t\t( newBlocks, options ) => {\n\t\t\tconst noChange = blocks === newBlocks;\n\t\t\tif ( noChange ) {\n\t\t\t\treturn __unstableCreateUndoLevel( kind, name, id );\n\t\t\t}\n\t\t\tconst { selection, ...rest } = options;\n\n\t\t\t// We create a new function here on every persistent edit\n\t\t\t// to make sure the edit makes the post dirty and creates\n\t\t\t// a new undo level.\n\t\t\tconst edits = {\n\t\t\t\tselection,\n\t\t\t\tcontent: ( { blocks: blocksForSerialization = [] } ) =>\n\t\t\t\t\t__unstableSerializeAndClean( blocksForSerialization ),\n\t\t\t\t...updateFootnotesFromMeta( newBlocks, meta ),\n\t\t\t};\n\n\t\t\teditEntityRecord( kind, name, id, edits, {\n\t\t\t\tisCached: false,\n\t\t\t\t...rest,\n\t\t\t} );\n\t\t},\n\t\t[\n\t\t\tkind,\n\t\t\tname,\n\t\t\tid,\n\t\t\tblocks,\n\t\t\tmeta,\n\t\t\t__unstableCreateUndoLevel,\n\t\t\teditEntityRecord,\n\t\t]\n\t);\n\n\tconst onInput = useCallback(\n\t\t( newBlocks, options ) => {\n\t\t\tconst { selection, ...rest } = options;\n\t\t\tconst edits = {\n\t\t\t\tselection,\n\t\t\t\t...updateFootnotesFromMeta( newBlocks, meta ),\n\t\t\t};\n\n\t\t\teditEntityRecord( kind, name, id, edits, {\n\t\t\t\tisCached: true,\n\t\t\t\t...rest,\n\t\t\t} );\n\t\t},\n\t\t[ kind, name, id, meta, editEntityRecord ]\n\t);\n\n\treturn [ blocks, onInput, onChange ];\n}\n"],
5
+ "mappings": ";AAGA,SAAS,aAAa,eAAe;AACrC,SAAS,aAAa,iBAAiB;AACvC,SAAS,OAAO,mCAAmC;AAKnD,SAAS,kBAAkB;AAC3B,OAAO,iBAAiB;AACxB,SAAS,+BAA+B;AACxC,SAAS,mBAAmB,mBAAmB;AAE/C,IAAM,cAAc,CAAC;AAoBN,SAAR,qBAAuC,MAAM,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,GAAI;AAC5E,QAAM,aAAa,YAAa,MAAM,IAAK;AAC3C,QAAM,KAAK,OAAO;AAClB,QAAM,EAAE,SAAS,cAAc,KAAK,IAAI;AAAA,IACvC,CAAE,WAAY;AACb,UAAK,CAAE,IAAK;AACX,eAAO,CAAC;AAAA,MACT;AACA,YAAM,EAAE,sBAAsB,IAAI,OAAQ,UAAW;AACrD,YAAM,eAAe,sBAAuB,MAAM,MAAM,EAAG;AAC3D,aAAO;AAAA,QACN,cAAc,aAAa;AAAA,QAC3B,SAAS,aAAa;AAAA,QACtB,MAAM,aAAa;AAAA,MACpB;AAAA,IACD;AAAA,IACA,CAAE,MAAM,MAAM,EAAG;AAAA,EAClB;AACA,QAAM,EAAE,2BAA2B,iBAAiB,IACnD,YAAa,UAAW;AAEzB,QAAM,SAAS,QAAS,MAAM;AAC7B,QAAK,CAAE,IAAK;AACX,aAAO;AAAA,IACR;AAEA,QAAK,cAAe;AACnB,aAAO;AAAA,IACR;AAEA,QAAK,CAAE,WAAW,OAAO,YAAY,UAAW;AAC/C,aAAO;AAAA,IACR;AAIA,UAAM,WAAW,YAAa,MAAM,MAAM,EAAG;AAC7C,UAAM,SAAS,kBAAkB,IAAK,QAAS;AAC/C,QAAI;AAEJ,QAAK,UAAU,OAAO,YAAY,SAAU;AAC3C,gBAAU,OAAO;AAAA,IAClB,OAAO;AACN,gBAAU,MAAO,OAAQ;AACzB,wBAAkB,IAAK,UAAU,EAAE,SAAS,QAAQ,QAAQ,CAAE;AAAA,IAC/D;AAEA,WAAO;AAAA,EACR,GAAG,CAAE,MAAM,MAAM,IAAI,cAAc,OAAQ,CAAE;AAE7C,QAAM,WAAW;AAAA,IAChB,CAAE,WAAW,YAAa;AACzB,YAAM,WAAW,WAAW;AAC5B,UAAK,UAAW;AACf,eAAO,0BAA2B,MAAM,MAAM,EAAG;AAAA,MAClD;AACA,YAAM,EAAE,WAAW,GAAG,KAAK,IAAI;AAK/B,YAAM,QAAQ;AAAA,QACb;AAAA,QACA,SAAS,CAAE,EAAE,QAAQ,yBAAyB,CAAC,EAAE,MAChD,4BAA6B,sBAAuB;AAAA,QACrD,GAAG,wBAAyB,WAAW,IAAK;AAAA,MAC7C;AAEA,uBAAkB,MAAM,MAAM,IAAI,OAAO;AAAA,QACxC,UAAU;AAAA,QACV,GAAG;AAAA,MACJ,CAAE;AAAA,IACH;AAAA,IACA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,QAAM,UAAU;AAAA,IACf,CAAE,WAAW,YAAa;AACzB,YAAM,EAAE,WAAW,GAAG,KAAK,IAAI;AAC/B,YAAM,QAAQ;AAAA,QACb;AAAA,QACA,GAAG,wBAAyB,WAAW,IAAK;AAAA,MAC7C;AAEA,uBAAkB,MAAM,MAAM,IAAI,OAAO;AAAA,QACxC,UAAU;AAAA,QACV,GAAG;AAAA,MACJ,CAAE;AAAA,IACH;AAAA,IACA,CAAE,MAAM,MAAM,IAAI,MAAM,gBAAiB;AAAA,EAC1C;AAEA,SAAO,CAAE,QAAQ,SAAS,QAAS;AACpC;",
6
6
  "names": []
7
7
  }
@@ -4,7 +4,8 @@ import { useEffect, useState } from "@wordpress/element";
4
4
  import { getSyncManager } from "../sync.mjs";
5
5
  var defaultResolvedSelection = {
6
6
  richTextOffset: null,
7
- localClientId: null
7
+ localClientId: null,
8
+ attributeKey: null
8
9
  };
9
10
  var defaultState = {
10
11
  activeCollaborators: [],
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/hooks/use-post-editor-awareness-state.ts"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport { usePrevious } from '@wordpress/compose';\nimport { useEffect, useState } from '@wordpress/element';\nimport type { Y } from '@wordpress/sync';\n\n/**\n * Internal dependencies\n */\nimport { getSyncManager } from '../sync';\nimport type {\n\tPostEditorAwarenessState as ActiveCollaborator,\n\tPostSaveEvent,\n\tYDocDebugData,\n} from '../awareness/types';\nimport type { SelectionState, ResolvedSelection } from '../types';\nimport type { PostEditorAwareness } from '../awareness/post-editor-awareness';\n\ninterface AwarenessState {\n\tactiveCollaborators: ActiveCollaborator[];\n\tresolveSelection: ( selection: SelectionState ) => ResolvedSelection;\n\tgetDebugData: () => YDocDebugData;\n\tisCurrentCollaboratorDisconnected: boolean;\n}\n\nconst defaultResolvedSelection: ResolvedSelection = {\n\trichTextOffset: null,\n\tlocalClientId: null,\n};\n\nconst defaultState: AwarenessState = {\n\tactiveCollaborators: [],\n\tresolveSelection: () => defaultResolvedSelection,\n\tgetDebugData: () => ( {\n\t\tdoc: {},\n\t\tclients: {},\n\t\tcollaboratorMap: {},\n\t} ),\n\tisCurrentCollaboratorDisconnected: false,\n};\n\nfunction getAwarenessState(\n\tawareness: PostEditorAwareness,\n\tnewState?: ActiveCollaborator[]\n): AwarenessState {\n\tconst activeCollaborators = newState ?? awareness.getCurrentState();\n\n\treturn {\n\t\tactiveCollaborators,\n\t\tresolveSelection: ( selection: SelectionState ) =>\n\t\t\tawareness.convertSelectionStateToAbsolute( selection ),\n\t\tgetDebugData: () => awareness.getDebugData(),\n\t\tisCurrentCollaboratorDisconnected:\n\t\t\tactiveCollaborators.find( ( collaborator ) => collaborator.isMe )\n\t\t\t\t?.isConnected === false,\n\t};\n}\n\nfunction usePostEditorAwarenessState(\n\tpostId: number | null,\n\tpostType: string | null\n): AwarenessState {\n\tconst [ state, setState ] = useState< AwarenessState >( defaultState );\n\n\tuseEffect( () => {\n\t\tif ( null === postId || null === postType ) {\n\t\t\tsetState( defaultState );\n\t\t\treturn;\n\t\t}\n\n\t\tconst objectType = `postType/${ postType }`;\n\t\tconst objectId = postId.toString();\n\t\tconst awareness = getSyncManager()?.getAwareness< PostEditorAwareness >(\n\t\t\tobjectType,\n\t\t\tobjectId\n\t\t);\n\n\t\tif ( ! awareness ) {\n\t\t\tsetState( defaultState );\n\t\t\treturn;\n\t\t}\n\n\t\tawareness.setUp();\n\n\t\t// Initialize with current awareness state.\n\t\tsetState( getAwarenessState( awareness ) );\n\n\t\tconst unsubscribe = awareness?.onStateChange(\n\t\t\t( newState: ActiveCollaborator[] ) => {\n\t\t\t\tsetState( getAwarenessState( awareness, newState ) );\n\t\t\t}\n\t\t);\n\n\t\treturn unsubscribe;\n\t}, [ postId, postType ] );\n\n\treturn state;\n}\n\n/**\n * Hook to get the active collaborators for a post editor.\n *\n * @param postId - The ID of the post.\n * @param postType - The type of the post.\n * @return {ActiveCollaborator[]} The active collaborators.\n */\nexport function useActiveCollaborators(\n\tpostId: number | null,\n\tpostType: string | null\n): ActiveCollaborator[] {\n\treturn usePostEditorAwarenessState( postId, postType ).activeCollaborators;\n}\n\n/**\n * Hook to resolve a selection state to a text index and block client ID.\n *\n * @param postId - The ID of the post.\n * @param postType - The type of the post.\n * @return A function that resolves a selection to its text index and block client ID.\n */\nexport function useResolvedSelection(\n\tpostId: number | null,\n\tpostType: string | null\n): ( selection: SelectionState ) => ResolvedSelection {\n\treturn usePostEditorAwarenessState( postId, postType ).resolveSelection;\n}\n\n/**\n * Hook to get data for debugging, using the awareness state.\n *\n * @param postId - The ID of the post.\n * @param postType - The type of the post.\n * @return {YDocDebugData} The debug data.\n */\nexport function useGetDebugData(\n\tpostId: number | null,\n\tpostType: string | null\n): YDocDebugData {\n\treturn usePostEditorAwarenessState( postId, postType ).getDebugData();\n}\n\n/**\n * Hook to check if the current collaborator is disconnected.\n *\n * @param postId - The ID of the post.\n * @param postType - The type of the post.\n * @return {boolean} Whether the current collaborator is disconnected.\n */\nexport function useIsDisconnected(\n\tpostId: number | null,\n\tpostType: string | null\n): boolean {\n\treturn usePostEditorAwarenessState( postId, postType )\n\t\t.isCurrentCollaboratorDisconnected;\n}\n\n/**\n * Hook that subscribes to the CRDT state map and returns the most recent\n * save event (timestamp + client ID). The state map is updated by\n * `markEntityAsSaved` in `@wordpress/sync`\n *\n * @param postId The ID of the post.\n * @param postType The type of the post.\n */\nfunction useLastPostSave(\n\tpostId: number | null,\n\tpostType: string | null\n): PostSaveEvent | null {\n\tconst [ lastSave, setLastSave ] = useState< PostSaveEvent | null >( null );\n\n\tuseEffect( () => {\n\t\tif ( null === postId || null === postType ) {\n\t\t\tsetLastSave( null );\n\t\t\treturn;\n\t\t}\n\n\t\tconst awareness = getSyncManager()?.getAwareness< PostEditorAwareness >(\n\t\t\t`postType/${ postType }`,\n\t\t\tpostId.toString()\n\t\t);\n\n\t\tif ( ! awareness ) {\n\t\t\tsetLastSave( null );\n\t\t\treturn;\n\t\t}\n\n\t\tawareness.setUp();\n\n\t\tconst stateMap = awareness.doc.getMap( 'state' );\n\t\tconst recordMap = awareness.doc.getMap( 'document' );\n\n\t\t// Only notify for saves that occur after the observer is\n\t\t// set up. This prevents false notifications when the Y.Doc\n\t\t// syncs historical state on page load or peer reconnect.\n\t\tconst setupTime = Date.now();\n\n\t\tconst observer = ( event: Y.YMapEvent< unknown > ) => {\n\t\t\tif ( event.keysChanged.has( 'savedAt' ) ) {\n\t\t\t\tconst savedAt = stateMap.get( 'savedAt' ) as number;\n\t\t\t\tconst savedByClientId = stateMap.get( 'savedBy' ) as number;\n\n\t\t\t\tif (\n\t\t\t\t\ttypeof savedAt === 'number' &&\n\t\t\t\t\ttypeof savedByClientId === 'number' &&\n\t\t\t\t\tsavedAt > setupTime\n\t\t\t\t) {\n\t\t\t\t\tconst postStatus = recordMap.get( 'status' ) as\n\t\t\t\t\t\t| string\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tsetLastSave( { savedAt, savedByClientId, postStatus } );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tstateMap.observe( observer );\n\n\t\treturn () => {\n\t\t\tstateMap.unobserve( observer );\n\t\t};\n\t}, [ postId, postType ] );\n\n\treturn lastSave;\n}\n\n/**\n * Hook that fires a callback when a new collaborator joins the post.\n * Handles initial hydration and state diffing internally\u2014consumers\n * only receive \"join\" events for collaborators that appear after the\n * initial state has loaded.\n *\n * The callback receives the joining collaborator and, when available,\n * the current user's state (useful for comparing `enteredAt` timestamps).\n *\n * @param postId The ID of the post.\n * @param postType The type of the post.\n * @param callback Invoked for each collaborator that joins.\n */\nexport function useOnCollaboratorJoin(\n\tpostId: number | null,\n\tpostType: string | null,\n\tcallback: (\n\t\tcollaborator: ActiveCollaborator,\n\t\tme?: ActiveCollaborator\n\t) => void\n): void {\n\tconst { activeCollaborators } = usePostEditorAwarenessState(\n\t\tpostId,\n\t\tpostType\n\t);\n\tconst prevCollaborators = usePrevious( activeCollaborators );\n\n\tuseEffect( () => {\n\t\t/*\n\t\t * On first render usePrevious returns undefined. On subsequent\n\t\t * renders the list may still be empty while the store hydrates.\n\t\t * In both cases, skip to avoid spurious \"joined\" callbacks for\n\t\t * users already present.\n\t\t */\n\t\tif ( ! prevCollaborators || prevCollaborators.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst prevMap = new Map< number, ActiveCollaborator >(\n\t\t\tprevCollaborators.map( ( collaborator ) => [\n\t\t\t\tcollaborator.clientId,\n\t\t\t\tcollaborator,\n\t\t\t] )\n\t\t);\n\t\tconst me = activeCollaborators.find(\n\t\t\t( collaborator ) => collaborator.isMe\n\t\t);\n\n\t\tfor ( const collaborator of activeCollaborators ) {\n\t\t\tif (\n\t\t\t\t! prevMap.has( collaborator.clientId ) &&\n\t\t\t\t! collaborator.isMe\n\t\t\t) {\n\t\t\t\tcallback( collaborator, me );\n\t\t\t}\n\t\t}\n\t}, [ activeCollaborators, prevCollaborators, callback ] );\n}\n\n/**\n * Hook that fires a callback when a collaborator leaves the post.\n * A \"leave\" is detected when a previously-connected collaborator either\n * transitions to `isConnected = false` or disappears from the list\n * entirely while still connected. Already-disconnected collaborators\n * that are later removed from the list are silently ignored.\n *\n * @param postId The ID of the post.\n * @param postType The type of the post.\n * @param callback Invoked for each collaborator that leaves.\n */\nexport function useOnCollaboratorLeave(\n\tpostId: number | null,\n\tpostType: string | null,\n\tcallback: ( collaborator: ActiveCollaborator ) => void\n): void {\n\tconst { activeCollaborators } = usePostEditorAwarenessState(\n\t\tpostId,\n\t\tpostType\n\t);\n\tconst prevCollaborators = usePrevious( activeCollaborators );\n\n\tuseEffect( () => {\n\t\tif ( ! prevCollaborators || prevCollaborators.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst newMap = new Map< number, ActiveCollaborator >(\n\t\t\tactiveCollaborators.map( ( collaborator ) => [\n\t\t\t\tcollaborator.clientId,\n\t\t\t\tcollaborator,\n\t\t\t] )\n\t\t);\n\n\t\tfor ( const prevCollab of prevCollaborators ) {\n\t\t\tif ( prevCollab.isMe || ! prevCollab.isConnected ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst newCollab = newMap.get( prevCollab.clientId );\n\t\t\tif ( ! newCollab?.isConnected ) {\n\t\t\t\tcallback( prevCollab );\n\t\t\t}\n\t\t}\n\t}, [ activeCollaborators, prevCollaborators, callback ] );\n}\n\n/**\n * Hook that fires a callback when a remote collaborator saves the post.\n * Only fires for saves by other collaborators (not the current user).\n * Deduplicates by `savedAt` timestamp so the same save event is never\n * reported twice.\n *\n * @param postId The ID of the post.\n * @param postType The type of the post.\n * @param callback Invoked with the save event, the collaborator who saved,\n * and the previous save event (if any) for transition detection.\n */\nexport function useOnPostSave(\n\tpostId: number | null,\n\tpostType: string | null,\n\tcallback: (\n\t\tevent: PostSaveEvent,\n\t\tsaver: ActiveCollaborator,\n\t\tprevEvent: PostSaveEvent | null\n\t) => void\n): void {\n\tconst { activeCollaborators } = usePostEditorAwarenessState(\n\t\tpostId,\n\t\tpostType\n\t);\n\tconst lastPostSave = useLastPostSave( postId, postType );\n\tconst prevPostSave = usePrevious( lastPostSave );\n\n\tuseEffect( () => {\n\t\tif ( ! lastPostSave ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( prevPostSave && lastPostSave.savedAt === prevPostSave.savedAt ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst saver = activeCollaborators.find(\n\t\t\t( collaborator ) =>\n\t\t\t\tcollaborator.clientId === lastPostSave.savedByClientId &&\n\t\t\t\t! collaborator.isMe\n\t\t);\n\n\t\tif ( ! saver ) {\n\t\t\treturn;\n\t\t}\n\n\t\tcallback( lastPostSave, saver, prevPostSave ?? null );\n\t}, [ lastPostSave, prevPostSave, activeCollaborators, callback ] );\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport { usePrevious } from '@wordpress/compose';\nimport { useEffect, useState } from '@wordpress/element';\nimport type { Y } from '@wordpress/sync';\n\n/**\n * Internal dependencies\n */\nimport { getSyncManager } from '../sync';\nimport type {\n\tPostEditorAwarenessState as ActiveCollaborator,\n\tPostSaveEvent,\n\tYDocDebugData,\n} from '../awareness/types';\nimport type { SelectionState, ResolvedSelection } from '../types';\nimport type { PostEditorAwareness } from '../awareness/post-editor-awareness';\n\ninterface AwarenessState {\n\tactiveCollaborators: ActiveCollaborator[];\n\tresolveSelection: ( selection: SelectionState ) => ResolvedSelection;\n\tgetDebugData: () => YDocDebugData;\n\tisCurrentCollaboratorDisconnected: boolean;\n}\n\nconst defaultResolvedSelection: ResolvedSelection = {\n\trichTextOffset: null,\n\tlocalClientId: null,\n\tattributeKey: null,\n};\n\nconst defaultState: AwarenessState = {\n\tactiveCollaborators: [],\n\tresolveSelection: () => defaultResolvedSelection,\n\tgetDebugData: () => ( {\n\t\tdoc: {},\n\t\tclients: {},\n\t\tcollaboratorMap: {},\n\t} ),\n\tisCurrentCollaboratorDisconnected: false,\n};\n\nfunction getAwarenessState(\n\tawareness: PostEditorAwareness,\n\tnewState?: ActiveCollaborator[]\n): AwarenessState {\n\tconst activeCollaborators = newState ?? awareness.getCurrentState();\n\n\treturn {\n\t\tactiveCollaborators,\n\t\tresolveSelection: ( selection: SelectionState ) =>\n\t\t\tawareness.convertSelectionStateToAbsolute( selection ),\n\t\tgetDebugData: () => awareness.getDebugData(),\n\t\tisCurrentCollaboratorDisconnected:\n\t\t\tactiveCollaborators.find( ( collaborator ) => collaborator.isMe )\n\t\t\t\t?.isConnected === false,\n\t};\n}\n\nfunction usePostEditorAwarenessState(\n\tpostId: number | null,\n\tpostType: string | null\n): AwarenessState {\n\tconst [ state, setState ] = useState< AwarenessState >( defaultState );\n\n\tuseEffect( () => {\n\t\tif ( null === postId || null === postType ) {\n\t\t\tsetState( defaultState );\n\t\t\treturn;\n\t\t}\n\n\t\tconst objectType = `postType/${ postType }`;\n\t\tconst objectId = postId.toString();\n\t\tconst awareness = getSyncManager()?.getAwareness< PostEditorAwareness >(\n\t\t\tobjectType,\n\t\t\tobjectId\n\t\t);\n\n\t\tif ( ! awareness ) {\n\t\t\tsetState( defaultState );\n\t\t\treturn;\n\t\t}\n\n\t\tawareness.setUp();\n\n\t\t// Initialize with current awareness state.\n\t\tsetState( getAwarenessState( awareness ) );\n\n\t\tconst unsubscribe = awareness?.onStateChange(\n\t\t\t( newState: ActiveCollaborator[] ) => {\n\t\t\t\tsetState( getAwarenessState( awareness, newState ) );\n\t\t\t}\n\t\t);\n\n\t\treturn unsubscribe;\n\t}, [ postId, postType ] );\n\n\treturn state;\n}\n\n/**\n * Hook to get the active collaborators for a post editor.\n *\n * @param postId - The ID of the post.\n * @param postType - The type of the post.\n * @return {ActiveCollaborator[]} The active collaborators.\n */\nexport function useActiveCollaborators(\n\tpostId: number | null,\n\tpostType: string | null\n): ActiveCollaborator[] {\n\treturn usePostEditorAwarenessState( postId, postType ).activeCollaborators;\n}\n\n/**\n * Hook to resolve a selection state to a text index and block client ID.\n *\n * @param postId - The ID of the post.\n * @param postType - The type of the post.\n * @return A function that resolves a selection to its text index and block client ID.\n */\nexport function useResolvedSelection(\n\tpostId: number | null,\n\tpostType: string | null\n): ( selection: SelectionState ) => ResolvedSelection {\n\treturn usePostEditorAwarenessState( postId, postType ).resolveSelection;\n}\n\n/**\n * Hook to get data for debugging, using the awareness state.\n *\n * @param postId - The ID of the post.\n * @param postType - The type of the post.\n * @return {YDocDebugData} The debug data.\n */\nexport function useGetDebugData(\n\tpostId: number | null,\n\tpostType: string | null\n): YDocDebugData {\n\treturn usePostEditorAwarenessState( postId, postType ).getDebugData();\n}\n\n/**\n * Hook to check if the current collaborator is disconnected.\n *\n * @param postId - The ID of the post.\n * @param postType - The type of the post.\n * @return {boolean} Whether the current collaborator is disconnected.\n */\nexport function useIsDisconnected(\n\tpostId: number | null,\n\tpostType: string | null\n): boolean {\n\treturn usePostEditorAwarenessState( postId, postType )\n\t\t.isCurrentCollaboratorDisconnected;\n}\n\n/**\n * Hook that subscribes to the CRDT state map and returns the most recent\n * save event (timestamp + client ID). The state map is updated by\n * `markEntityAsSaved` in `@wordpress/sync`\n *\n * @param postId The ID of the post.\n * @param postType The type of the post.\n */\nfunction useLastPostSave(\n\tpostId: number | null,\n\tpostType: string | null\n): PostSaveEvent | null {\n\tconst [ lastSave, setLastSave ] = useState< PostSaveEvent | null >( null );\n\n\tuseEffect( () => {\n\t\tif ( null === postId || null === postType ) {\n\t\t\tsetLastSave( null );\n\t\t\treturn;\n\t\t}\n\n\t\tconst awareness = getSyncManager()?.getAwareness< PostEditorAwareness >(\n\t\t\t`postType/${ postType }`,\n\t\t\tpostId.toString()\n\t\t);\n\n\t\tif ( ! awareness ) {\n\t\t\tsetLastSave( null );\n\t\t\treturn;\n\t\t}\n\n\t\tawareness.setUp();\n\n\t\tconst stateMap = awareness.doc.getMap( 'state' );\n\t\tconst recordMap = awareness.doc.getMap( 'document' );\n\n\t\t// Only notify for saves that occur after the observer is\n\t\t// set up. This prevents false notifications when the Y.Doc\n\t\t// syncs historical state on page load or peer reconnect.\n\t\tconst setupTime = Date.now();\n\n\t\tconst observer = ( event: Y.YMapEvent< unknown > ) => {\n\t\t\tif ( event.keysChanged.has( 'savedAt' ) ) {\n\t\t\t\tconst savedAt = stateMap.get( 'savedAt' ) as number;\n\t\t\t\tconst savedByClientId = stateMap.get( 'savedBy' ) as number;\n\n\t\t\t\tif (\n\t\t\t\t\ttypeof savedAt === 'number' &&\n\t\t\t\t\ttypeof savedByClientId === 'number' &&\n\t\t\t\t\tsavedAt > setupTime\n\t\t\t\t) {\n\t\t\t\t\tconst postStatus = recordMap.get( 'status' ) as\n\t\t\t\t\t\t| string\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tsetLastSave( { savedAt, savedByClientId, postStatus } );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tstateMap.observe( observer );\n\n\t\treturn () => {\n\t\t\tstateMap.unobserve( observer );\n\t\t};\n\t}, [ postId, postType ] );\n\n\treturn lastSave;\n}\n\n/**\n * Hook that fires a callback when a new collaborator joins the post.\n * Handles initial hydration and state diffing internally\u2014consumers\n * only receive \"join\" events for collaborators that appear after the\n * initial state has loaded.\n *\n * The callback receives the joining collaborator and, when available,\n * the current user's state (useful for comparing `enteredAt` timestamps).\n *\n * @param postId The ID of the post.\n * @param postType The type of the post.\n * @param callback Invoked for each collaborator that joins.\n */\nexport function useOnCollaboratorJoin(\n\tpostId: number | null,\n\tpostType: string | null,\n\tcallback: (\n\t\tcollaborator: ActiveCollaborator,\n\t\tme?: ActiveCollaborator\n\t) => void\n): void {\n\tconst { activeCollaborators } = usePostEditorAwarenessState(\n\t\tpostId,\n\t\tpostType\n\t);\n\tconst prevCollaborators = usePrevious( activeCollaborators );\n\n\tuseEffect( () => {\n\t\t/*\n\t\t * On first render usePrevious returns undefined. On subsequent\n\t\t * renders the list may still be empty while the store hydrates.\n\t\t * In both cases, skip to avoid spurious \"joined\" callbacks for\n\t\t * users already present.\n\t\t */\n\t\tif ( ! prevCollaborators || prevCollaborators.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst prevMap = new Map< number, ActiveCollaborator >(\n\t\t\tprevCollaborators.map( ( collaborator ) => [\n\t\t\t\tcollaborator.clientId,\n\t\t\t\tcollaborator,\n\t\t\t] )\n\t\t);\n\t\tconst me = activeCollaborators.find(\n\t\t\t( collaborator ) => collaborator.isMe\n\t\t);\n\n\t\tfor ( const collaborator of activeCollaborators ) {\n\t\t\tif (\n\t\t\t\t! prevMap.has( collaborator.clientId ) &&\n\t\t\t\t! collaborator.isMe\n\t\t\t) {\n\t\t\t\tcallback( collaborator, me );\n\t\t\t}\n\t\t}\n\t}, [ activeCollaborators, prevCollaborators, callback ] );\n}\n\n/**\n * Hook that fires a callback when a collaborator leaves the post.\n * A \"leave\" is detected when a previously-connected collaborator either\n * transitions to `isConnected = false` or disappears from the list\n * entirely while still connected. Already-disconnected collaborators\n * that are later removed from the list are silently ignored.\n *\n * @param postId The ID of the post.\n * @param postType The type of the post.\n * @param callback Invoked for each collaborator that leaves.\n */\nexport function useOnCollaboratorLeave(\n\tpostId: number | null,\n\tpostType: string | null,\n\tcallback: ( collaborator: ActiveCollaborator ) => void\n): void {\n\tconst { activeCollaborators } = usePostEditorAwarenessState(\n\t\tpostId,\n\t\tpostType\n\t);\n\tconst prevCollaborators = usePrevious( activeCollaborators );\n\n\tuseEffect( () => {\n\t\tif ( ! prevCollaborators || prevCollaborators.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst newMap = new Map< number, ActiveCollaborator >(\n\t\t\tactiveCollaborators.map( ( collaborator ) => [\n\t\t\t\tcollaborator.clientId,\n\t\t\t\tcollaborator,\n\t\t\t] )\n\t\t);\n\n\t\tfor ( const prevCollab of prevCollaborators ) {\n\t\t\tif ( prevCollab.isMe || ! prevCollab.isConnected ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst newCollab = newMap.get( prevCollab.clientId );\n\t\t\tif ( ! newCollab?.isConnected ) {\n\t\t\t\tcallback( prevCollab );\n\t\t\t}\n\t\t}\n\t}, [ activeCollaborators, prevCollaborators, callback ] );\n}\n\n/**\n * Hook that fires a callback when a remote collaborator saves the post.\n * Only fires for saves by other collaborators (not the current user).\n * Deduplicates by `savedAt` timestamp so the same save event is never\n * reported twice.\n *\n * @param postId The ID of the post.\n * @param postType The type of the post.\n * @param callback Invoked with the save event, the collaborator who saved,\n * and the previous save event (if any) for transition detection.\n */\nexport function useOnPostSave(\n\tpostId: number | null,\n\tpostType: string | null,\n\tcallback: (\n\t\tevent: PostSaveEvent,\n\t\tsaver: ActiveCollaborator,\n\t\tprevEvent: PostSaveEvent | null\n\t) => void\n): void {\n\tconst { activeCollaborators } = usePostEditorAwarenessState(\n\t\tpostId,\n\t\tpostType\n\t);\n\tconst lastPostSave = useLastPostSave( postId, postType );\n\tconst prevPostSave = usePrevious( lastPostSave );\n\n\tuseEffect( () => {\n\t\tif ( ! lastPostSave ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( prevPostSave && lastPostSave.savedAt === prevPostSave.savedAt ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst saver = activeCollaborators.find(\n\t\t\t( collaborator ) =>\n\t\t\t\tcollaborator.clientId === lastPostSave.savedByClientId &&\n\t\t\t\t! collaborator.isMe\n\t\t);\n\n\t\tif ( ! saver ) {\n\t\t\treturn;\n\t\t}\n\n\t\tcallback( lastPostSave, saver, prevPostSave ?? null );\n\t}, [ lastPostSave, prevPostSave, activeCollaborators, callback ] );\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -16,12 +16,10 @@ function useResourcePermissions(resource, id) {
16
16
  (resolve) => {
17
17
  const hasId = isEntity ? !!resource.id : !!id;
18
18
  const { canUser } = resolve(coreStore);
19
- const create = canUser(
20
- "create",
21
- isEntity ? { kind: resource.kind, name: resource.name } : resource
22
- );
19
+ const collectionResource = isEntity ? { kind: resource.kind, name: resource.name } : resource;
20
+ const create = canUser("create", collectionResource);
23
21
  if (!hasId) {
24
- const read2 = canUser("read", resource);
22
+ const read2 = canUser("read", collectionResource);
25
23
  const isResolving2 = create.isResolving || read2.isResolving;
26
24
  const hasResolved2 = create.hasResolved && read2.hasResolved;
27
25
  let status2 = Status.Idle;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/hooks/use-resource-permissions.ts"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport deprecated from '@wordpress/deprecated';\nimport warning from '@wordpress/warning';\n\n/**\n * Internal dependencies\n */\nimport { store as coreStore } from '../';\nimport { Status } from './constants';\nimport useQuerySelect from './use-query-select';\n\ninterface GlobalResourcePermissionsResolution {\n\t/** Can the current user create new resources of this type? */\n\tcanCreate: boolean;\n}\ninterface SpecificResourcePermissionsResolution {\n\t/** Can the current user update resources of this type? */\n\tcanUpdate: boolean;\n\t/** Can the current user delete resources of this type? */\n\tcanDelete: boolean;\n}\ninterface ResolutionDetails {\n\t/** Resolution status */\n\tstatus: Status;\n\t/**\n\t * Is the data still being resolved?\n\t */\n\tisResolving: boolean;\n}\n\n/**\n * Is the data resolved by now?\n */\ntype HasResolved = boolean;\n\ntype ResourcePermissionsResolution< IdType > = [\n\tHasResolved,\n\tResolutionDetails &\n\t\tGlobalResourcePermissionsResolution &\n\t\t( IdType extends void ? SpecificResourcePermissionsResolution : {} ),\n];\n\ntype EntityResource = { kind: string; name: string; id?: string | number };\n\nfunction useResourcePermissions< IdType = void >(\n\tresource: string,\n\tid?: IdType\n): ResourcePermissionsResolution< IdType >;\n\nfunction useResourcePermissions< IdType = void >(\n\tresource: EntityResource,\n\tid?: never\n): ResourcePermissionsResolution< IdType >;\n\n/**\n * Resolves resource permissions.\n *\n * @since 6.1.0 Introduced in WordPress core.\n *\n * @param resource Entity resource to check. Accepts entity object `{ kind: 'postType', name: 'attachment', id: 1 }`\n * or REST base as a string - `media`.\n * @param id Optional ID of the resource to check, e.g. 10. Note: This argument is discouraged\n * when using an entity object as a resource to check permissions and will be ignored.\n *\n * @example\n * ```js\n * import { useResourcePermissions } from '@wordpress/core-data';\n *\n * function PagesList() {\n * const { canCreate, isResolving } = useResourcePermissions( { kind: 'postType', name: 'page' } );\n *\n * if ( isResolving ) {\n * return 'Loading ...';\n * }\n *\n * return (\n * <div>\n * {canCreate ? (<button>+ Create a new page</button>) : false}\n * // ...\n * </div>\n * );\n * }\n *\n * // Rendered in the application:\n * // <PagesList />\n * ```\n *\n * @example\n * ```js\n * import { useResourcePermissions } from '@wordpress/core-data';\n *\n * function Page({ pageId }) {\n * const {\n * canCreate,\n * canUpdate,\n * canDelete,\n * isResolving\n * } = useResourcePermissions( { kind: 'postType', name: 'page', id: pageId } );\n *\n * if ( isResolving ) {\n * return 'Loading ...';\n * }\n *\n * return (\n * <div>\n * {canCreate ? (<button>+ Create a new page</button>) : false}\n * {canUpdate ? (<button>Edit page</button>) : false}\n * {canDelete ? (<button>Delete page</button>) : false}\n * // ...\n * </div>\n * );\n * }\n *\n * // Rendered in the application:\n * // <Page pageId={ 15 } />\n * ```\n *\n * In the above example, when `PagesList` is rendered into an\n * application, the appropriate permissions and the resolution details will be retrieved from\n * the store state using `canUser()`, or resolved if missing.\n *\n * @return Entity records data.\n * @template IdType\n */\nfunction useResourcePermissions< IdType = void >(\n\tresource: string | EntityResource,\n\tid?: IdType\n): ResourcePermissionsResolution< IdType > {\n\t// Serialize `resource` to a string that can be safely used as a React dep.\n\t// We can't just pass `resource` as one of the deps, because if it is passed\n\t// as an object literal, then it will be a different object on each call even\n\t// if the values remain the same.\n\tconst isEntity = typeof resource === 'object';\n\tconst resourceAsString = isEntity ? JSON.stringify( resource ) : resource;\n\n\tif ( isEntity && typeof id !== 'undefined' ) {\n\t\twarning(\n\t\t\t`When 'resource' is an entity object, passing 'id' as a separate argument isn't supported.`\n\t\t);\n\t}\n\n\treturn useQuerySelect(\n\t\t( resolve ) => {\n\t\t\tconst hasId = isEntity ? !! resource.id : !! id;\n\t\t\tconst { canUser } = resolve( coreStore );\n\t\t\tconst create = canUser(\n\t\t\t\t'create',\n\t\t\t\tisEntity\n\t\t\t\t\t? { kind: resource.kind, name: resource.name }\n\t\t\t\t\t: resource\n\t\t\t);\n\n\t\t\tif ( ! hasId ) {\n\t\t\t\tconst read = canUser( 'read', resource );\n\n\t\t\t\tconst isResolving = create.isResolving || read.isResolving;\n\t\t\t\tconst hasResolved = create.hasResolved && read.hasResolved;\n\t\t\t\tlet status = Status.Idle;\n\t\t\t\tif ( isResolving ) {\n\t\t\t\t\tstatus = Status.Resolving;\n\t\t\t\t} else if ( hasResolved ) {\n\t\t\t\t\tstatus = Status.Success;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tstatus,\n\t\t\t\t\tisResolving,\n\t\t\t\t\thasResolved,\n\t\t\t\t\tcanCreate: create.hasResolved && create.data,\n\t\t\t\t\tcanRead: read.hasResolved && read.data,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst read = canUser( 'read', resource, id );\n\t\t\tconst update = canUser( 'update', resource, id );\n\t\t\tconst _delete = canUser( 'delete', resource, id );\n\t\t\tconst isResolving =\n\t\t\t\tread.isResolving ||\n\t\t\t\tcreate.isResolving ||\n\t\t\t\tupdate.isResolving ||\n\t\t\t\t_delete.isResolving;\n\t\t\tconst hasResolved =\n\t\t\t\tread.hasResolved &&\n\t\t\t\tcreate.hasResolved &&\n\t\t\t\tupdate.hasResolved &&\n\t\t\t\t_delete.hasResolved;\n\n\t\t\tlet status = Status.Idle;\n\t\t\tif ( isResolving ) {\n\t\t\t\tstatus = Status.Resolving;\n\t\t\t} else if ( hasResolved ) {\n\t\t\t\tstatus = Status.Success;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus,\n\t\t\t\tisResolving,\n\t\t\t\thasResolved,\n\t\t\t\tcanRead: hasResolved && read.data,\n\t\t\t\tcanCreate: hasResolved && create.data,\n\t\t\t\tcanUpdate: hasResolved && update.data,\n\t\t\t\tcanDelete: hasResolved && _delete.data,\n\t\t\t};\n\t\t},\n\t\t[ resourceAsString, id ]\n\t);\n}\n\nexport default useResourcePermissions;\n\nexport function useDeprecatedResourcePermissions(\n\tresource: string,\n\tid?: unknown\n) {\n\tdeprecated( `wp.data.__experimentalUseResourcePermissions`, {\n\t\talternative: 'wp.data.useResourcePermissions',\n\t\tsince: '6.1',\n\t} );\n\treturn useResourcePermissions( resource, id );\n}\n"],
5
- "mappings": ";AAGA,OAAO,gBAAgB;AACvB,OAAO,aAAa;AAKpB,SAAS,SAAS,iBAAiB;AACnC,SAAS,cAAc;AACvB,OAAO,oBAAoB;AAmH3B,SAAS,uBACR,UACA,IAC0C;AAK1C,QAAM,WAAW,OAAO,aAAa;AACrC,QAAM,mBAAmB,WAAW,KAAK,UAAW,QAAS,IAAI;AAEjE,MAAK,YAAY,OAAO,OAAO,aAAc;AAC5C;AAAA,MACC;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,CAAE,YAAa;AACd,YAAM,QAAQ,WAAW,CAAC,CAAE,SAAS,KAAK,CAAC,CAAE;AAC7C,YAAM,EAAE,QAAQ,IAAI,QAAS,SAAU;AACvC,YAAM,SAAS;AAAA,QACd;AAAA,QACA,WACG,EAAE,MAAM,SAAS,MAAM,MAAM,SAAS,KAAK,IAC3C;AAAA,MACJ;AAEA,UAAK,CAAE,OAAQ;AACd,cAAMA,QAAO,QAAS,QAAQ,QAAS;AAEvC,cAAMC,eAAc,OAAO,eAAeD,MAAK;AAC/C,cAAME,eAAc,OAAO,eAAeF,MAAK;AAC/C,YAAIG,UAAS,OAAO;AACpB,YAAKF,cAAc;AAClB,UAAAE,UAAS,OAAO;AAAA,QACjB,WAAYD,cAAc;AACzB,UAAAC,UAAS,OAAO;AAAA,QACjB;AAEA,eAAO;AAAA,UACN,QAAAA;AAAA,UACA,aAAAF;AAAA,UACA,aAAAC;AAAA,UACA,WAAW,OAAO,eAAe,OAAO;AAAA,UACxC,SAASF,MAAK,eAAeA,MAAK;AAAA,QACnC;AAAA,MACD;AAEA,YAAM,OAAO,QAAS,QAAQ,UAAU,EAAG;AAC3C,YAAM,SAAS,QAAS,UAAU,UAAU,EAAG;AAC/C,YAAM,UAAU,QAAS,UAAU,UAAU,EAAG;AAChD,YAAM,cACL,KAAK,eACL,OAAO,eACP,OAAO,eACP,QAAQ;AACT,YAAM,cACL,KAAK,eACL,OAAO,eACP,OAAO,eACP,QAAQ;AAET,UAAI,SAAS,OAAO;AACpB,UAAK,aAAc;AAClB,iBAAS,OAAO;AAAA,MACjB,WAAY,aAAc;AACzB,iBAAS,OAAO;AAAA,MACjB;AACA,aAAO;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,eAAe,KAAK;AAAA,QAC7B,WAAW,eAAe,OAAO;AAAA,QACjC,WAAW,eAAe,OAAO;AAAA,QACjC,WAAW,eAAe,QAAQ;AAAA,MACnC;AAAA,IACD;AAAA,IACA,CAAE,kBAAkB,EAAG;AAAA,EACxB;AACD;AAEA,IAAO,mCAAQ;AAER,SAAS,iCACf,UACA,IACC;AACD,aAAY,gDAAgD;AAAA,IAC3D,aAAa;AAAA,IACb,OAAO;AAAA,EACR,CAAE;AACF,SAAO,uBAAwB,UAAU,EAAG;AAC7C;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport deprecated from '@wordpress/deprecated';\nimport warning from '@wordpress/warning';\n\n/**\n * Internal dependencies\n */\nimport { store as coreStore } from '../';\nimport { Status } from './constants';\nimport useQuerySelect from './use-query-select';\n\ninterface GlobalResourcePermissionsResolution {\n\t/** Can the current user create new resources of this type? */\n\tcanCreate: boolean;\n}\ninterface SpecificResourcePermissionsResolution {\n\t/** Can the current user update resources of this type? */\n\tcanUpdate: boolean;\n\t/** Can the current user delete resources of this type? */\n\tcanDelete: boolean;\n}\ninterface ResolutionDetails {\n\t/** Resolution status */\n\tstatus: Status;\n\t/**\n\t * Is the data still being resolved?\n\t */\n\tisResolving: boolean;\n}\n\n/**\n * Is the data resolved by now?\n */\ntype HasResolved = boolean;\n\ntype ResourcePermissionsResolution< IdType > = [\n\tHasResolved,\n\tResolutionDetails &\n\t\tGlobalResourcePermissionsResolution &\n\t\t( IdType extends void ? SpecificResourcePermissionsResolution : {} ),\n];\n\ntype EntityResource = { kind: string; name: string; id?: string | number };\n\nfunction useResourcePermissions< IdType = void >(\n\tresource: string,\n\tid?: IdType\n): ResourcePermissionsResolution< IdType >;\n\nfunction useResourcePermissions< IdType = void >(\n\tresource: EntityResource,\n\tid?: never\n): ResourcePermissionsResolution< IdType >;\n\n/**\n * Resolves resource permissions.\n *\n * @since 6.1.0 Introduced in WordPress core.\n *\n * @param resource Entity resource to check. Accepts entity object `{ kind: 'postType', name: 'attachment', id: 1 }`\n * or REST base as a string - `media`.\n * @param id Optional ID of the resource to check, e.g. 10. Note: This argument is discouraged\n * when using an entity object as a resource to check permissions and will be ignored.\n *\n * @example\n * ```js\n * import { useResourcePermissions } from '@wordpress/core-data';\n *\n * function PagesList() {\n * const { canCreate, isResolving } = useResourcePermissions( { kind: 'postType', name: 'page' } );\n *\n * if ( isResolving ) {\n * return 'Loading ...';\n * }\n *\n * return (\n * <div>\n * {canCreate ? (<button>+ Create a new page</button>) : false}\n * // ...\n * </div>\n * );\n * }\n *\n * // Rendered in the application:\n * // <PagesList />\n * ```\n *\n * @example\n * ```js\n * import { useResourcePermissions } from '@wordpress/core-data';\n *\n * function Page({ pageId }) {\n * const {\n * canCreate,\n * canUpdate,\n * canDelete,\n * isResolving\n * } = useResourcePermissions( { kind: 'postType', name: 'page', id: pageId } );\n *\n * if ( isResolving ) {\n * return 'Loading ...';\n * }\n *\n * return (\n * <div>\n * {canCreate ? (<button>+ Create a new page</button>) : false}\n * {canUpdate ? (<button>Edit page</button>) : false}\n * {canDelete ? (<button>Delete page</button>) : false}\n * // ...\n * </div>\n * );\n * }\n *\n * // Rendered in the application:\n * // <Page pageId={ 15 } />\n * ```\n *\n * In the above example, when `PagesList` is rendered into an\n * application, the appropriate permissions and the resolution details will be retrieved from\n * the store state using `canUser()`, or resolved if missing.\n *\n * @return Entity records data.\n * @template IdType\n */\nfunction useResourcePermissions< IdType = void >(\n\tresource: string | EntityResource,\n\tid?: IdType\n): ResourcePermissionsResolution< IdType > {\n\t// Serialize `resource` to a string that can be safely used as a React dep.\n\t// We can't just pass `resource` as one of the deps, because if it is passed\n\t// as an object literal, then it will be a different object on each call even\n\t// if the values remain the same.\n\tconst isEntity = typeof resource === 'object';\n\tconst resourceAsString = isEntity ? JSON.stringify( resource ) : resource;\n\n\tif ( isEntity && typeof id !== 'undefined' ) {\n\t\twarning(\n\t\t\t`When 'resource' is an entity object, passing 'id' as a separate argument isn't supported.`\n\t\t);\n\t}\n\n\treturn useQuerySelect(\n\t\t( resolve ) => {\n\t\t\tconst hasId = isEntity ? !! resource.id : !! id;\n\t\t\tconst { canUser } = resolve( coreStore );\n\t\t\tconst collectionResource = isEntity\n\t\t\t\t? { kind: resource.kind, name: resource.name }\n\t\t\t\t: resource;\n\t\t\tconst create = canUser( 'create', collectionResource );\n\n\t\t\tif ( ! hasId ) {\n\t\t\t\tconst read = canUser( 'read', collectionResource );\n\n\t\t\t\tconst isResolving = create.isResolving || read.isResolving;\n\t\t\t\tconst hasResolved = create.hasResolved && read.hasResolved;\n\t\t\t\tlet status = Status.Idle;\n\t\t\t\tif ( isResolving ) {\n\t\t\t\t\tstatus = Status.Resolving;\n\t\t\t\t} else if ( hasResolved ) {\n\t\t\t\t\tstatus = Status.Success;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tstatus,\n\t\t\t\t\tisResolving,\n\t\t\t\t\thasResolved,\n\t\t\t\t\tcanCreate: create.hasResolved && create.data,\n\t\t\t\t\tcanRead: read.hasResolved && read.data,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst read = canUser( 'read', resource, id );\n\t\t\tconst update = canUser( 'update', resource, id );\n\t\t\tconst _delete = canUser( 'delete', resource, id );\n\t\t\tconst isResolving =\n\t\t\t\tread.isResolving ||\n\t\t\t\tcreate.isResolving ||\n\t\t\t\tupdate.isResolving ||\n\t\t\t\t_delete.isResolving;\n\t\t\tconst hasResolved =\n\t\t\t\tread.hasResolved &&\n\t\t\t\tcreate.hasResolved &&\n\t\t\t\tupdate.hasResolved &&\n\t\t\t\t_delete.hasResolved;\n\n\t\t\tlet status = Status.Idle;\n\t\t\tif ( isResolving ) {\n\t\t\t\tstatus = Status.Resolving;\n\t\t\t} else if ( hasResolved ) {\n\t\t\t\tstatus = Status.Success;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus,\n\t\t\t\tisResolving,\n\t\t\t\thasResolved,\n\t\t\t\tcanRead: hasResolved && read.data,\n\t\t\t\tcanCreate: hasResolved && create.data,\n\t\t\t\tcanUpdate: hasResolved && update.data,\n\t\t\t\tcanDelete: hasResolved && _delete.data,\n\t\t\t};\n\t\t},\n\t\t[ resourceAsString, id ]\n\t);\n}\n\nexport default useResourcePermissions;\n\nexport function useDeprecatedResourcePermissions(\n\tresource: string,\n\tid?: unknown\n) {\n\tdeprecated( `wp.data.__experimentalUseResourcePermissions`, {\n\t\talternative: 'wp.data.useResourcePermissions',\n\t\tsince: '6.1',\n\t} );\n\treturn useResourcePermissions( resource, id );\n}\n"],
5
+ "mappings": ";AAGA,OAAO,gBAAgB;AACvB,OAAO,aAAa;AAKpB,SAAS,SAAS,iBAAiB;AACnC,SAAS,cAAc;AACvB,OAAO,oBAAoB;AAmH3B,SAAS,uBACR,UACA,IAC0C;AAK1C,QAAM,WAAW,OAAO,aAAa;AACrC,QAAM,mBAAmB,WAAW,KAAK,UAAW,QAAS,IAAI;AAEjE,MAAK,YAAY,OAAO,OAAO,aAAc;AAC5C;AAAA,MACC;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,CAAE,YAAa;AACd,YAAM,QAAQ,WAAW,CAAC,CAAE,SAAS,KAAK,CAAC,CAAE;AAC7C,YAAM,EAAE,QAAQ,IAAI,QAAS,SAAU;AACvC,YAAM,qBAAqB,WACxB,EAAE,MAAM,SAAS,MAAM,MAAM,SAAS,KAAK,IAC3C;AACH,YAAM,SAAS,QAAS,UAAU,kBAAmB;AAErD,UAAK,CAAE,OAAQ;AACd,cAAMA,QAAO,QAAS,QAAQ,kBAAmB;AAEjD,cAAMC,eAAc,OAAO,eAAeD,MAAK;AAC/C,cAAME,eAAc,OAAO,eAAeF,MAAK;AAC/C,YAAIG,UAAS,OAAO;AACpB,YAAKF,cAAc;AAClB,UAAAE,UAAS,OAAO;AAAA,QACjB,WAAYD,cAAc;AACzB,UAAAC,UAAS,OAAO;AAAA,QACjB;AAEA,eAAO;AAAA,UACN,QAAAA;AAAA,UACA,aAAAF;AAAA,UACA,aAAAC;AAAA,UACA,WAAW,OAAO,eAAe,OAAO;AAAA,UACxC,SAASF,MAAK,eAAeA,MAAK;AAAA,QACnC;AAAA,MACD;AAEA,YAAM,OAAO,QAAS,QAAQ,UAAU,EAAG;AAC3C,YAAM,SAAS,QAAS,UAAU,UAAU,EAAG;AAC/C,YAAM,UAAU,QAAS,UAAU,UAAU,EAAG;AAChD,YAAM,cACL,KAAK,eACL,OAAO,eACP,OAAO,eACP,QAAQ;AACT,YAAM,cACL,KAAK,eACL,OAAO,eACP,OAAO,eACP,QAAQ;AAET,UAAI,SAAS,OAAO;AACpB,UAAK,aAAc;AAClB,iBAAS,OAAO;AAAA,MACjB,WAAY,aAAc;AACzB,iBAAS,OAAO;AAAA,MACjB;AACA,aAAO;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,eAAe,KAAK;AAAA,QAC7B,WAAW,eAAe,OAAO;AAAA,QACjC,WAAW,eAAe,OAAO;AAAA,QACjC,WAAW,eAAe,QAAQ;AAAA,MACnC;AAAA,IACD;AAAA,IACA,CAAE,kBAAkB,EAAG;AAAA,EACxB;AACD;AAEA,IAAO,mCAAQ;AAER,SAAS,iCACf,UACA,IACC;AACD,aAAY,gDAAgD;AAAA,IAC3D,aAAa;AAAA,IACb,OAAO;AAAA,EACR,CAAE;AACF,SAAO,uBAAwB,UAAU,EAAG;AAC7C;",
6
6
  "names": ["read", "isResolving", "hasResolved", "status"]
7
7
  }
@@ -16,8 +16,6 @@ import { STORE_NAME } from "./name.mjs";
16
16
  import { unlock } from "./lock-unlock.mjs";
17
17
  import { dynamicActions, dynamicSelectors } from "./dynamic-entities.mjs";
18
18
  import logEntityDeprecation from "./utils/log-entity-deprecation.mjs";
19
- import { SelectionType } from "./utils/crdt-user-selections.mjs";
20
- import { SelectionDirection } from "./types.mjs";
21
19
  import { default as default2 } from "./entity-provider.mjs";
22
20
  export * from "./entity-provider.mjs";
23
21
  export * from "./entity-types/index.mjs";
@@ -116,8 +114,6 @@ unlock(store).registerPrivateActions(privateActions);
116
114
  register(store);
117
115
  export {
118
116
  default2 as EntityProvider,
119
- SelectionDirection,
120
- SelectionType,
121
117
  store
122
118
  };
123
119
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { createReduxStore, register } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport reducer from './reducer';\nimport * as selectors from './selectors';\nimport * as privateSelectors from './private-selectors';\nimport * as actions from './actions';\nimport * as privateActions from './private-actions';\nimport * as resolvers from './resolvers';\nimport createLocksActions from './locks/actions';\nimport {\n\trootEntitiesConfig,\n\tadditionalEntityConfigLoaders,\n\tgetMethodName,\n} from './entities';\nimport { STORE_NAME } from './name';\nimport { unlock } from './lock-unlock';\nimport { dynamicActions, dynamicSelectors } from './dynamic-entities';\nimport logEntityDeprecation from './utils/log-entity-deprecation';\n\n// The entity selectors/resolvers and actions are shortcuts to their generic equivalents\n// (getEntityRecord, getEntityRecords, updateEntityRecord, updateEntityRecords)\n// Instead of getEntityRecord, the consumer could use more user-friendly named selector: getPostType, getTaxonomy...\n// The \"kind\" and the \"name\" of the entity are combined to generate these shortcuts.\nconst entitiesConfig = [\n\t...rootEntitiesConfig,\n\t...additionalEntityConfigLoaders.filter( ( config ) => !! config.name ),\n];\n\nconst entitySelectors = entitiesConfig.reduce( ( result, entity ) => {\n\tconst { kind, name, plural } = entity;\n\n\tconst getEntityRecordMethodName = getMethodName( kind, name );\n\tresult[ getEntityRecordMethodName ] = ( state, key, query ) => {\n\t\tlogEntityDeprecation( kind, name, getEntityRecordMethodName, {\n\t\t\tisShorthandSelector: true,\n\t\t\talternativeFunctionName: 'getEntityRecord',\n\t\t} );\n\t\treturn selectors.getEntityRecord( state, kind, name, key, query );\n\t};\n\n\tif ( plural ) {\n\t\tconst getEntityRecordsMethodName = getMethodName( kind, plural, 'get' );\n\t\tresult[ getEntityRecordsMethodName ] = ( state, query ) => {\n\t\t\tlogEntityDeprecation( kind, name, getEntityRecordsMethodName, {\n\t\t\t\tisShorthandSelector: true,\n\t\t\t\talternativeFunctionName: 'getEntityRecords',\n\t\t\t} );\n\t\t\treturn selectors.getEntityRecords( state, kind, name, query );\n\t\t};\n\t}\n\treturn result;\n}, {} );\n\nconst entityResolvers = entitiesConfig.reduce( ( result, entity ) => {\n\tconst { kind, name, plural } = entity;\n\tconst getEntityRecordMethodName = getMethodName( kind, name );\n\tresult[ getEntityRecordMethodName ] = ( key, query ) => {\n\t\tlogEntityDeprecation( kind, name, getEntityRecordMethodName, {\n\t\t\tisShorthandSelector: true,\n\t\t\talternativeFunctionName: 'getEntityRecord',\n\t\t} );\n\t\treturn resolvers.getEntityRecord( kind, name, key, query );\n\t};\n\n\tif ( plural ) {\n\t\tconst getEntityRecordsMethodName = getMethodName( kind, plural, 'get' );\n\t\tresult[ getEntityRecordsMethodName ] = ( ...args ) => {\n\t\t\tlogEntityDeprecation( kind, plural, getEntityRecordsMethodName, {\n\t\t\t\tisShorthandSelector: true,\n\t\t\t\talternativeFunctionName: 'getEntityRecords',\n\t\t\t} );\n\t\t\treturn resolvers.getEntityRecords( kind, name, ...args );\n\t\t};\n\t\tresult[ getEntityRecordsMethodName ].shouldInvalidate = ( action ) =>\n\t\t\tresolvers.getEntityRecords.shouldInvalidate( action, kind, name );\n\t}\n\treturn result;\n}, {} );\n\nconst entityActions = entitiesConfig.reduce( ( result, entity ) => {\n\tconst { kind, name } = entity;\n\n\tconst saveEntityRecordMethodName = getMethodName( kind, name, 'save' );\n\tresult[ saveEntityRecordMethodName ] = ( record, options ) => {\n\t\tlogEntityDeprecation( kind, name, saveEntityRecordMethodName, {\n\t\t\tisShorthandSelector: true,\n\t\t\talternativeFunctionName: 'saveEntityRecord',\n\t\t} );\n\t\treturn actions.saveEntityRecord( kind, name, record, options );\n\t};\n\n\tconst deleteEntityRecordMethodName = getMethodName( kind, name, 'delete' );\n\tresult[ deleteEntityRecordMethodName ] = ( key, query, options ) => {\n\t\tlogEntityDeprecation( kind, name, deleteEntityRecordMethodName, {\n\t\t\tisShorthandSelector: true,\n\t\t\talternativeFunctionName: 'deleteEntityRecord',\n\t\t} );\n\t\treturn actions.deleteEntityRecord( kind, name, key, query, options );\n\t};\n\n\treturn result;\n}, {} );\n\nconst storeConfig = () => ( {\n\treducer,\n\tactions: {\n\t\t...dynamicActions,\n\t\t...actions,\n\t\t...entityActions,\n\t\t...createLocksActions(),\n\t},\n\tselectors: {\n\t\t...dynamicSelectors,\n\t\t...selectors,\n\t\t...entitySelectors,\n\t},\n\tresolvers: { ...resolvers, ...entityResolvers },\n} );\n\n/**\n * Store definition for the code data namespace.\n *\n * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore\n */\nexport const store = createReduxStore( STORE_NAME, storeConfig() );\nunlock( store ).registerPrivateSelectors( privateSelectors );\nunlock( store ).registerPrivateActions( privateActions );\nregister( store ); // Register store after unlocking private selectors to allow resolvers to use them.\n\n/**\n * Enums cannot be exported private without losing the ability to narrow types\n * based on their values (they blur to string type).\n */\nexport { SelectionType } from './utils/crdt-user-selections';\nexport { SelectionDirection } from './types';\n\nexport { default as EntityProvider } from './entity-provider';\nexport * from './entity-provider';\nexport * from './entity-types';\nexport * from './awareness/types';\nexport * from './fetch';\nexport * from './hooks';\nexport * from './private-apis';\nexport * from './types';\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { createReduxStore, register } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport reducer from './reducer';\nimport * as selectors from './selectors';\nimport * as privateSelectors from './private-selectors';\nimport * as actions from './actions';\nimport * as privateActions from './private-actions';\nimport * as resolvers from './resolvers';\nimport createLocksActions from './locks/actions';\nimport {\n\trootEntitiesConfig,\n\tadditionalEntityConfigLoaders,\n\tgetMethodName,\n} from './entities';\nimport { STORE_NAME } from './name';\nimport { unlock } from './lock-unlock';\nimport { dynamicActions, dynamicSelectors } from './dynamic-entities';\nimport logEntityDeprecation from './utils/log-entity-deprecation';\n\n// The entity selectors/resolvers and actions are shortcuts to their generic equivalents\n// (getEntityRecord, getEntityRecords, updateEntityRecord, updateEntityRecords)\n// Instead of getEntityRecord, the consumer could use more user-friendly named selector: getPostType, getTaxonomy...\n// The \"kind\" and the \"name\" of the entity are combined to generate these shortcuts.\nconst entitiesConfig = [\n\t...rootEntitiesConfig,\n\t...additionalEntityConfigLoaders.filter( ( config ) => !! config.name ),\n];\n\nconst entitySelectors = entitiesConfig.reduce( ( result, entity ) => {\n\tconst { kind, name, plural } = entity;\n\n\tconst getEntityRecordMethodName = getMethodName( kind, name );\n\tresult[ getEntityRecordMethodName ] = ( state, key, query ) => {\n\t\tlogEntityDeprecation( kind, name, getEntityRecordMethodName, {\n\t\t\tisShorthandSelector: true,\n\t\t\talternativeFunctionName: 'getEntityRecord',\n\t\t} );\n\t\treturn selectors.getEntityRecord( state, kind, name, key, query );\n\t};\n\n\tif ( plural ) {\n\t\tconst getEntityRecordsMethodName = getMethodName( kind, plural, 'get' );\n\t\tresult[ getEntityRecordsMethodName ] = ( state, query ) => {\n\t\t\tlogEntityDeprecation( kind, name, getEntityRecordsMethodName, {\n\t\t\t\tisShorthandSelector: true,\n\t\t\t\talternativeFunctionName: 'getEntityRecords',\n\t\t\t} );\n\t\t\treturn selectors.getEntityRecords( state, kind, name, query );\n\t\t};\n\t}\n\treturn result;\n}, {} );\n\nconst entityResolvers = entitiesConfig.reduce( ( result, entity ) => {\n\tconst { kind, name, plural } = entity;\n\tconst getEntityRecordMethodName = getMethodName( kind, name );\n\tresult[ getEntityRecordMethodName ] = ( key, query ) => {\n\t\tlogEntityDeprecation( kind, name, getEntityRecordMethodName, {\n\t\t\tisShorthandSelector: true,\n\t\t\talternativeFunctionName: 'getEntityRecord',\n\t\t} );\n\t\treturn resolvers.getEntityRecord( kind, name, key, query );\n\t};\n\n\tif ( plural ) {\n\t\tconst getEntityRecordsMethodName = getMethodName( kind, plural, 'get' );\n\t\tresult[ getEntityRecordsMethodName ] = ( ...args ) => {\n\t\t\tlogEntityDeprecation( kind, plural, getEntityRecordsMethodName, {\n\t\t\t\tisShorthandSelector: true,\n\t\t\t\talternativeFunctionName: 'getEntityRecords',\n\t\t\t} );\n\t\t\treturn resolvers.getEntityRecords( kind, name, ...args );\n\t\t};\n\t\tresult[ getEntityRecordsMethodName ].shouldInvalidate = ( action ) =>\n\t\t\tresolvers.getEntityRecords.shouldInvalidate( action, kind, name );\n\t}\n\treturn result;\n}, {} );\n\nconst entityActions = entitiesConfig.reduce( ( result, entity ) => {\n\tconst { kind, name } = entity;\n\n\tconst saveEntityRecordMethodName = getMethodName( kind, name, 'save' );\n\tresult[ saveEntityRecordMethodName ] = ( record, options ) => {\n\t\tlogEntityDeprecation( kind, name, saveEntityRecordMethodName, {\n\t\t\tisShorthandSelector: true,\n\t\t\talternativeFunctionName: 'saveEntityRecord',\n\t\t} );\n\t\treturn actions.saveEntityRecord( kind, name, record, options );\n\t};\n\n\tconst deleteEntityRecordMethodName = getMethodName( kind, name, 'delete' );\n\tresult[ deleteEntityRecordMethodName ] = ( key, query, options ) => {\n\t\tlogEntityDeprecation( kind, name, deleteEntityRecordMethodName, {\n\t\t\tisShorthandSelector: true,\n\t\t\talternativeFunctionName: 'deleteEntityRecord',\n\t\t} );\n\t\treturn actions.deleteEntityRecord( kind, name, key, query, options );\n\t};\n\n\treturn result;\n}, {} );\n\nconst storeConfig = () => ( {\n\treducer,\n\tactions: {\n\t\t...dynamicActions,\n\t\t...actions,\n\t\t...entityActions,\n\t\t...createLocksActions(),\n\t},\n\tselectors: {\n\t\t...dynamicSelectors,\n\t\t...selectors,\n\t\t...entitySelectors,\n\t},\n\tresolvers: { ...resolvers, ...entityResolvers },\n} );\n\n/**\n * Store definition for the code data namespace.\n *\n * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore\n */\nexport const store = createReduxStore( STORE_NAME, storeConfig() );\nunlock( store ).registerPrivateSelectors( privateSelectors );\nunlock( store ).registerPrivateActions( privateActions );\nregister( store ); // Register store after unlocking private selectors to allow resolvers to use them.\n\nexport { default as EntityProvider } from './entity-provider';\nexport * from './entity-provider';\nexport * from './entity-types';\nexport * from './awareness/types';\nexport * from './fetch';\nexport * from './hooks';\nexport * from './private-apis';\nexport * from './types';\n"],
5
+ "mappings": "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",
6
6
  "names": ["default"]
7
7
  }
@@ -0,0 +1,10 @@
1
+ // packages/core-data/src/parsed-blocks-cache.js
2
+ var parsedBlocksCache = /* @__PURE__ */ new Map();
3
+ function getCacheKey(kind, name, id) {
4
+ return `${kind}:${name}:${id}`;
5
+ }
6
+ export {
7
+ getCacheKey,
8
+ parsedBlocksCache
9
+ };
10
+ //# sourceMappingURL=parsed-blocks-cache.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/parsed-blocks-cache.js"],
4
+ "sourcesContent": ["/**\n * Shared cache of blocks parsed from an entity's `content` string, keyed by\n * `kind:name:id`. Populated both eagerly by the `getEntityRecord` resolver\n * (when the sync manager parses content for transient edits) and lazily by\n * `useEntityBlockEditor`. The stored `content` string acts as a validator so\n * stale entries are discarded when the underlying record changes.\n */\nexport const parsedBlocksCache = new Map();\n\nexport function getCacheKey( kind, name, id ) {\n\treturn `${ kind }:${ name }:${ id }`;\n}\n"],
5
+ "mappings": ";AAOO,IAAM,oBAAoB,oBAAI,IAAI;AAElC,SAAS,YAAa,MAAM,MAAM,IAAK;AAC7C,SAAO,GAAI,IAAK,IAAK,IAAK,IAAK,EAAG;AACnC;",
6
+ "names": []
7
+ }
@@ -1,6 +1,7 @@
1
1
  // packages/core-data/src/private-actions.js
2
2
  import apiFetch from "@wordpress/api-fetch";
3
3
  import { STORE_NAME } from "./name.mjs";
4
+ import { getSyncManager, hasSyncManager } from "./sync.mjs";
4
5
  function receiveRegisteredPostMeta(postType, registeredPostMeta) {
5
6
  return {
6
7
  type: "RECEIVE_REGISTERED_POST_META",
@@ -90,6 +91,9 @@ function receiveEditorAssets(assets) {
90
91
  }
91
92
  var setCollaborationSupported = (supported) => ({ dispatch }) => {
92
93
  dispatch({ type: "SET_COLLABORATION_SUPPORTED", supported });
94
+ if (!supported && hasSyncManager()) {
95
+ getSyncManager().unloadAll();
96
+ }
93
97
  };
94
98
  function receiveViewConfig(kind, name, config) {
95
99
  return {
@@ -99,12 +103,30 @@ function receiveViewConfig(kind, name, config) {
99
103
  config
100
104
  };
101
105
  }
106
+ function setSyncConnectionStatus(kind, name, key, status) {
107
+ if (!status) {
108
+ return {
109
+ type: "CLEAR_SYNC_CONNECTION_STATUS",
110
+ kind,
111
+ name,
112
+ key
113
+ };
114
+ }
115
+ return {
116
+ type: "SET_SYNC_CONNECTION_STATUS",
117
+ kind,
118
+ name,
119
+ key,
120
+ status
121
+ };
122
+ }
102
123
  export {
103
124
  editMediaEntity,
104
125
  receiveEditorAssets,
105
126
  receiveEditorSettings,
106
127
  receiveRegisteredPostMeta,
107
128
  receiveViewConfig,
108
- setCollaborationSupported
129
+ setCollaborationSupported,
130
+ setSyncConnectionStatus
109
131
  };
110
132
  //# sourceMappingURL=private-actions.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/private-actions.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { STORE_NAME } from './name';\n\n/**\n * Returns an action object used in signalling that the registered post meta\n * fields for a post type have been received.\n *\n * @param {string} postType Post type slug.\n * @param {Object} registeredPostMeta Registered post meta.\n *\n * @return {Object} Action object.\n */\nexport function receiveRegisteredPostMeta( postType, registeredPostMeta ) {\n\treturn {\n\t\ttype: 'RECEIVE_REGISTERED_POST_META',\n\t\tpostType,\n\t\tregisteredPostMeta,\n\t};\n}\n\n/**\n * @typedef {Object} Modifier\n * @property {string} [type] - The type of modifier.\n * @property {Object} [args] - The arguments of the modifier.\n */\n\n/**\n * @typedef {Object} Edits\n * @property {string} [src] - The URL of the media item.\n * @property {Modifier[]} [modifiers] - The modifiers to apply to the media item.\n */\n\n/**\n * Duplicates a media (attachment) entity record and, optionally, modifies it.\n *\n * @param {string} recordId Entity record ID.\n * @param {Edits} edits Edits to apply to the record.\n * @param {Object} options Options object.\n * @param {Function} options.__unstableFetch Custom fetch function.\n * @param {boolean} options.throwOnError Whether to throw an error if the request fails.\n *\n * @return {Promise} Promise resolving to the updated record.\n */\nexport const editMediaEntity =\n\t(\n\t\trecordId,\n\t\tedits = {},\n\t\t{ __unstableFetch = apiFetch, throwOnError = false } = {}\n\t) =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tif ( ! recordId ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst kind = 'postType';\n\t\tconst name = 'attachment';\n\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.kind === kind && config.name === name\n\t\t);\n\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst lock = await dispatch.__unstableAcquireStoreLock(\n\t\t\tSTORE_NAME,\n\t\t\t[ 'entities', 'records', kind, name, recordId ],\n\t\t\t{ exclusive: true }\n\t\t);\n\n\t\tlet updatedRecord;\n\t\tlet error;\n\t\tlet hasError = false;\n\n\t\ttry {\n\t\t\tdispatch( {\n\t\t\t\ttype: 'SAVE_ENTITY_RECORD_START',\n\t\t\t\tkind,\n\t\t\t\tname,\n\t\t\t\trecordId,\n\t\t\t} );\n\n\t\t\ttry {\n\t\t\t\tconst path = `${ entityConfig.baseURL }/${ recordId }/edit`;\n\t\t\t\tconst newRecord = await __unstableFetch( {\n\t\t\t\t\tpath,\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\tdata: {\n\t\t\t\t\t\t...edits,\n\t\t\t\t\t},\n\t\t\t\t} );\n\n\t\t\t\tif ( newRecord ) {\n\t\t\t\t\tdispatch.receiveEntityRecords(\n\t\t\t\t\t\tkind,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tnewRecord,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined\n\t\t\t\t\t);\n\t\t\t\t\tupdatedRecord = newRecord;\n\t\t\t\t}\n\t\t\t} catch ( e ) {\n\t\t\t\terror = e;\n\t\t\t\thasError = true;\n\t\t\t}\n\n\t\t\tdispatch( {\n\t\t\t\ttype: 'SAVE_ENTITY_RECORD_FINISH',\n\t\t\t\tkind,\n\t\t\t\tname,\n\t\t\t\trecordId,\n\t\t\t\terror,\n\t\t\t} );\n\n\t\t\tif ( hasError && throwOnError ) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn updatedRecord;\n\t\t} finally {\n\t\t\tdispatch.__unstableReleaseStoreLock( lock );\n\t\t}\n\t};\n\n/**\n * Returns an action object used to receive editor settings.\n *\n * @param {Object} settings Editor settings object.\n *\n * @return {Object} Action object.\n */\nexport function receiveEditorSettings( settings ) {\n\treturn {\n\t\ttype: 'RECEIVE_EDITOR_SETTINGS',\n\t\tsettings,\n\t};\n}\n\n/**\n * Returns an action object used to receive editor assets.\n *\n * @param {Object} assets Editor assets object.\n *\n * @return {Object} Action object.\n */\nexport function receiveEditorAssets( assets ) {\n\treturn {\n\t\ttype: 'RECEIVE_EDITOR_ASSETS',\n\t\tassets,\n\t};\n}\n\n/**\n * Returns an action object used to set whether collaboration is supported.\n *\n * @param {boolean} supported Whether collaboration is supported.\n *\n * @return {Object} Action object.\n */\nexport const setCollaborationSupported =\n\t( supported ) =>\n\t( { dispatch } ) => {\n\t\tdispatch( { type: 'SET_COLLABORATION_SUPPORTED', supported } );\n\t};\n\n/**\n * Returns an action object used to receive view config.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {Object} config View config object.\n *\n * @return {Object} Action object.\n */\nexport function receiveViewConfig( kind, name, config ) {\n\treturn {\n\t\ttype: 'RECEIVE_VIEW_CONFIG',\n\t\tkind,\n\t\tname,\n\t\tconfig,\n\t};\n}\n"],
5
- "mappings": ";AAGA,OAAO,cAAc;AAKrB,SAAS,kBAAkB;AAWpB,SAAS,0BAA2B,UAAU,oBAAqB;AACzE,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACD;AACD;AAyBO,IAAM,kBACZ,CACC,UACA,QAAQ,CAAC,GACT,EAAE,kBAAkB,UAAU,eAAe,MAAM,IAAI,CAAC,MAEzD,OAAQ,EAAE,UAAU,cAAc,MAAO;AACxC,MAAK,CAAE,UAAW;AACjB;AAAA,EACD;AAEA,QAAM,OAAO;AACb,QAAM,OAAO;AAEb,QAAM,UAAU,MAAM,cAAc,kBAAmB,IAAK;AAC5D,QAAM,eAAe,QAAQ;AAAA,IAC5B,CAAE,WAAY,OAAO,SAAS,QAAQ,OAAO,SAAS;AAAA,EACvD;AAEA,MAAK,CAAE,cAAe;AACrB;AAAA,EACD;AAEA,QAAM,OAAO,MAAM,SAAS;AAAA,IAC3B;AAAA,IACA,CAAE,YAAY,WAAW,MAAM,MAAM,QAAS;AAAA,IAC9C,EAAE,WAAW,KAAK;AAAA,EACnB;AAEA,MAAI;AACJ,MAAI;AACJ,MAAI,WAAW;AAEf,MAAI;AACH,aAAU;AAAA,MACT,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAE;AAEF,QAAI;AACH,YAAM,OAAO,GAAI,aAAa,OAAQ,IAAK,QAAS;AACpD,YAAM,YAAY,MAAM,gBAAiB;AAAA,QACxC;AAAA,QACA,QAAQ;AAAA,QACR,MAAM;AAAA,UACL,GAAG;AAAA,QACJ;AAAA,MACD,CAAE;AAEF,UAAK,WAAY;AAChB,iBAAS;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AACA,wBAAgB;AAAA,MACjB;AAAA,IACD,SAAU,GAAI;AACb,cAAQ;AACR,iBAAW;AAAA,IACZ;AAEA,aAAU;AAAA,MACT,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAE;AAEF,QAAK,YAAY,cAAe;AAC/B,YAAM;AAAA,IACP;AACA,WAAO;AAAA,EACR,UAAE;AACD,aAAS,2BAA4B,IAAK;AAAA,EAC3C;AACD;AASM,SAAS,sBAAuB,UAAW;AACjD,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACD;AACD;AASO,SAAS,oBAAqB,QAAS;AAC7C,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACD;AACD;AASO,IAAM,4BACZ,CAAE,cACF,CAAE,EAAE,SAAS,MAAO;AACnB,WAAU,EAAE,MAAM,+BAA+B,UAAU,CAAE;AAC9D;AAWM,SAAS,kBAAmB,MAAM,MAAM,QAAS;AACvD,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { STORE_NAME } from './name';\nimport { getSyncManager, hasSyncManager } from './sync';\n\n/**\n * Returns an action object used in signalling that the registered post meta\n * fields for a post type have been received.\n *\n * @param {string} postType Post type slug.\n * @param {Object} registeredPostMeta Registered post meta.\n *\n * @return {Object} Action object.\n */\nexport function receiveRegisteredPostMeta( postType, registeredPostMeta ) {\n\treturn {\n\t\ttype: 'RECEIVE_REGISTERED_POST_META',\n\t\tpostType,\n\t\tregisteredPostMeta,\n\t};\n}\n\n/**\n * @typedef {Object} Modifier\n * @property {string} [type] - The type of modifier.\n * @property {Object} [args] - The arguments of the modifier.\n */\n\n/**\n * @typedef {Object} Edits\n * @property {string} [src] - The URL of the media item.\n * @property {Modifier[]} [modifiers] - The modifiers to apply to the media item.\n */\n\n/**\n * Duplicates a media (attachment) entity record and, optionally, modifies it.\n *\n * @param {string} recordId Entity record ID.\n * @param {Edits} edits Edits to apply to the record.\n * @param {Object} options Options object.\n * @param {Function} options.__unstableFetch Custom fetch function.\n * @param {boolean} options.throwOnError Whether to throw an error if the request fails.\n *\n * @return {Promise} Promise resolving to the updated record.\n */\nexport const editMediaEntity =\n\t(\n\t\trecordId,\n\t\tedits = {},\n\t\t{ __unstableFetch = apiFetch, throwOnError = false } = {}\n\t) =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tif ( ! recordId ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst kind = 'postType';\n\t\tconst name = 'attachment';\n\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.kind === kind && config.name === name\n\t\t);\n\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst lock = await dispatch.__unstableAcquireStoreLock(\n\t\t\tSTORE_NAME,\n\t\t\t[ 'entities', 'records', kind, name, recordId ],\n\t\t\t{ exclusive: true }\n\t\t);\n\n\t\tlet updatedRecord;\n\t\tlet error;\n\t\tlet hasError = false;\n\n\t\ttry {\n\t\t\tdispatch( {\n\t\t\t\ttype: 'SAVE_ENTITY_RECORD_START',\n\t\t\t\tkind,\n\t\t\t\tname,\n\t\t\t\trecordId,\n\t\t\t} );\n\n\t\t\ttry {\n\t\t\t\tconst path = `${ entityConfig.baseURL }/${ recordId }/edit`;\n\t\t\t\tconst newRecord = await __unstableFetch( {\n\t\t\t\t\tpath,\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\tdata: {\n\t\t\t\t\t\t...edits,\n\t\t\t\t\t},\n\t\t\t\t} );\n\n\t\t\t\tif ( newRecord ) {\n\t\t\t\t\tdispatch.receiveEntityRecords(\n\t\t\t\t\t\tkind,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tnewRecord,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined\n\t\t\t\t\t);\n\t\t\t\t\tupdatedRecord = newRecord;\n\t\t\t\t}\n\t\t\t} catch ( e ) {\n\t\t\t\terror = e;\n\t\t\t\thasError = true;\n\t\t\t}\n\n\t\t\tdispatch( {\n\t\t\t\ttype: 'SAVE_ENTITY_RECORD_FINISH',\n\t\t\t\tkind,\n\t\t\t\tname,\n\t\t\t\trecordId,\n\t\t\t\terror,\n\t\t\t} );\n\n\t\t\tif ( hasError && throwOnError ) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn updatedRecord;\n\t\t} finally {\n\t\t\tdispatch.__unstableReleaseStoreLock( lock );\n\t\t}\n\t};\n\n/**\n * Returns an action object used to receive editor settings.\n *\n * @param {Object} settings Editor settings object.\n *\n * @return {Object} Action object.\n */\nexport function receiveEditorSettings( settings ) {\n\treturn {\n\t\ttype: 'RECEIVE_EDITOR_SETTINGS',\n\t\tsettings,\n\t};\n}\n\n/**\n * Returns an action object used to receive editor assets.\n *\n * @param {Object} assets Editor assets object.\n *\n * @return {Object} Action object.\n */\nexport function receiveEditorAssets( assets ) {\n\treturn {\n\t\ttype: 'RECEIVE_EDITOR_ASSETS',\n\t\tassets,\n\t};\n}\n\n/**\n * Returns an action object used to set whether collaboration is supported.\n * When set to false, also disconnects all sync entities.\n *\n * @param {boolean} supported Whether collaboration is supported.\n *\n * @return {Object} Action object.\n */\nexport const setCollaborationSupported =\n\t( supported ) =>\n\t( { dispatch } ) => {\n\t\tdispatch( { type: 'SET_COLLABORATION_SUPPORTED', supported } );\n\t\tif ( ! supported && hasSyncManager() ) {\n\t\t\tgetSyncManager().unloadAll();\n\t\t}\n\t};\n\n/**\n * Returns an action object used to receive view config.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {Object} config View config object.\n *\n * @return {Object} Action object.\n */\nexport function receiveViewConfig( kind, name, config ) {\n\treturn {\n\t\ttype: 'RECEIVE_VIEW_CONFIG',\n\t\tkind,\n\t\tname,\n\t\tconfig,\n\t};\n}\n\n/**\n * Returns an action object used to set the sync connection status for an entity or collection.\n *\n * @param {string} kind Kind of the entity.\n * @param {string} name Name of the entity.\n * @param {number|string|null} key The entity key, or null for collections.\n * @param {Object|null} status The connection state object or null on unload.\n *\n * @return {Object} Action object.\n */\nexport function setSyncConnectionStatus( kind, name, key, status ) {\n\tif ( ! status ) {\n\t\treturn {\n\t\t\ttype: 'CLEAR_SYNC_CONNECTION_STATUS',\n\t\t\tkind,\n\t\t\tname,\n\t\t\tkey,\n\t\t};\n\t}\n\n\treturn {\n\t\ttype: 'SET_SYNC_CONNECTION_STATUS',\n\t\tkind,\n\t\tname,\n\t\tkey,\n\t\tstatus,\n\t};\n}\n"],
5
+ "mappings": ";AAGA,OAAO,cAAc;AAKrB,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB,sBAAsB;AAWxC,SAAS,0BAA2B,UAAU,oBAAqB;AACzE,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACD;AACD;AAyBO,IAAM,kBACZ,CACC,UACA,QAAQ,CAAC,GACT,EAAE,kBAAkB,UAAU,eAAe,MAAM,IAAI,CAAC,MAEzD,OAAQ,EAAE,UAAU,cAAc,MAAO;AACxC,MAAK,CAAE,UAAW;AACjB;AAAA,EACD;AAEA,QAAM,OAAO;AACb,QAAM,OAAO;AAEb,QAAM,UAAU,MAAM,cAAc,kBAAmB,IAAK;AAC5D,QAAM,eAAe,QAAQ;AAAA,IAC5B,CAAE,WAAY,OAAO,SAAS,QAAQ,OAAO,SAAS;AAAA,EACvD;AAEA,MAAK,CAAE,cAAe;AACrB;AAAA,EACD;AAEA,QAAM,OAAO,MAAM,SAAS;AAAA,IAC3B;AAAA,IACA,CAAE,YAAY,WAAW,MAAM,MAAM,QAAS;AAAA,IAC9C,EAAE,WAAW,KAAK;AAAA,EACnB;AAEA,MAAI;AACJ,MAAI;AACJ,MAAI,WAAW;AAEf,MAAI;AACH,aAAU;AAAA,MACT,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAE;AAEF,QAAI;AACH,YAAM,OAAO,GAAI,aAAa,OAAQ,IAAK,QAAS;AACpD,YAAM,YAAY,MAAM,gBAAiB;AAAA,QACxC;AAAA,QACA,QAAQ;AAAA,QACR,MAAM;AAAA,UACL,GAAG;AAAA,QACJ;AAAA,MACD,CAAE;AAEF,UAAK,WAAY;AAChB,iBAAS;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AACA,wBAAgB;AAAA,MACjB;AAAA,IACD,SAAU,GAAI;AACb,cAAQ;AACR,iBAAW;AAAA,IACZ;AAEA,aAAU;AAAA,MACT,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAE;AAEF,QAAK,YAAY,cAAe;AAC/B,YAAM;AAAA,IACP;AACA,WAAO;AAAA,EACR,UAAE;AACD,aAAS,2BAA4B,IAAK;AAAA,EAC3C;AACD;AASM,SAAS,sBAAuB,UAAW;AACjD,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACD;AACD;AASO,SAAS,oBAAqB,QAAS;AAC7C,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACD;AACD;AAUO,IAAM,4BACZ,CAAE,cACF,CAAE,EAAE,SAAS,MAAO;AACnB,WAAU,EAAE,MAAM,+BAA+B,UAAU,CAAE;AAC7D,MAAK,CAAE,aAAa,eAAe,GAAI;AACtC,mBAAe,EAAE,UAAU;AAAA,EAC5B;AACD;AAWM,SAAS,kBAAmB,MAAM,MAAM,QAAS;AACvD,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAYO,SAAS,wBAAyB,MAAM,MAAM,KAAK,QAAS;AAClE,MAAK,CAAE,QAAS;AACf,WAAO;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
- // packages/core-data/src/private-apis.js
1
+ // packages/core-data/src/private-apis.ts
2
2
  import { useEntityRecordsWithPermissions } from "./hooks/use-entity-records.mjs";
3
3
  import { RECEIVE_INTERMEDIATE_RESULTS } from "./utils/index.mjs";
4
4
  import {
@@ -10,8 +10,11 @@ import {
10
10
  } from "./hooks/use-post-editor-awareness-state.mjs";
11
11
  import { lock } from "./lock-unlock.mjs";
12
12
  import { retrySyncConnection } from "./sync.mjs";
13
- var privateApis = {};
14
- lock(privateApis, {
13
+ import {
14
+ SelectionType,
15
+ SelectionDirection
16
+ } from "./utils/crdt-user-selections.mjs";
17
+ var lockedApis = {
15
18
  useEntityRecordsWithPermissions,
16
19
  RECEIVE_INTERMEDIATE_RESULTS,
17
20
  retrySyncConnection,
@@ -19,8 +22,12 @@ lock(privateApis, {
19
22
  useResolvedSelection,
20
23
  useOnCollaboratorJoin,
21
24
  useOnCollaboratorLeave,
22
- useOnPostSave
23
- });
25
+ useOnPostSave,
26
+ SelectionType,
27
+ SelectionDirection
28
+ };
29
+ var privateApis = {};
30
+ lock(privateApis, lockedApis);
24
31
  export {
25
32
  privateApis
26
33
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/private-apis.js"],
4
- "sourcesContent": ["/**\n * Internal dependencies\n */\nimport { useEntityRecordsWithPermissions } from './hooks/use-entity-records';\nimport { RECEIVE_INTERMEDIATE_RESULTS } from './utils';\nimport {\n\tuseActiveCollaborators,\n\tuseResolvedSelection,\n\tuseOnCollaboratorJoin,\n\tuseOnCollaboratorLeave,\n\tuseOnPostSave,\n} from './hooks/use-post-editor-awareness-state';\nimport { lock } from './lock-unlock';\nimport { retrySyncConnection } from './sync';\n\nexport const privateApis = {};\nlock( privateApis, {\n\tuseEntityRecordsWithPermissions,\n\tRECEIVE_INTERMEDIATE_RESULTS,\n\tretrySyncConnection,\n\tuseActiveCollaborators,\n\tuseResolvedSelection,\n\tuseOnCollaboratorJoin,\n\tuseOnCollaboratorLeave,\n\tuseOnPostSave,\n} );\n"],
5
- "mappings": ";AAGA,SAAS,uCAAuC;AAChD,SAAS,oCAAoC;AAC7C;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,YAAY;AACrB,SAAS,2BAA2B;AAE7B,IAAM,cAAc,CAAC;AAC5B,KAAM,aAAa;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAE;",
3
+ "sources": ["../src/private-apis.ts"],
4
+ "sourcesContent": ["/**\n * Internal dependencies\n */\nimport { useEntityRecordsWithPermissions } from './hooks/use-entity-records';\nimport { RECEIVE_INTERMEDIATE_RESULTS } from './utils';\nimport {\n\tuseActiveCollaborators,\n\tuseResolvedSelection,\n\tuseOnCollaboratorJoin,\n\tuseOnCollaboratorLeave,\n\tuseOnPostSave,\n} from './hooks/use-post-editor-awareness-state';\nimport { lock } from './lock-unlock';\nimport { retrySyncConnection } from './sync';\nimport {\n\tSelectionType,\n\tSelectionDirection,\n} from './utils/crdt-user-selections';\n\nconst lockedApis = {\n\tuseEntityRecordsWithPermissions,\n\tRECEIVE_INTERMEDIATE_RESULTS,\n\tretrySyncConnection,\n\tuseActiveCollaborators,\n\tuseResolvedSelection,\n\tuseOnCollaboratorJoin,\n\tuseOnCollaboratorLeave,\n\tuseOnPostSave,\n\tSelectionType,\n\tSelectionDirection,\n};\n\nexport type CoreDataPrivateApis = typeof lockedApis;\n\nexport const privateApis = {};\nlock( privateApis, lockedApis );\n"],
5
+ "mappings": ";AAGA,SAAS,uCAAuC;AAChD,SAAS,oCAAoC;AAC7C;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,YAAY;AACrB,SAAS,2BAA2B;AACpC;AAAA,EACC;AAAA,EACA;AAAA,OACM;AAEP,IAAM,aAAa;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAIO,IAAM,cAAc,CAAC;AAC5B,KAAM,aAAa,UAAW;",
6
6
  "names": []
7
7
  }
@@ -177,6 +177,19 @@ function getViewConfig(state, kind, name) {
177
177
  form: void 0
178
178
  };
179
179
  }
180
+ function getSyncConnectionStatus(state) {
181
+ if (!state.syncConnectionStatuses) {
182
+ return void 0;
183
+ }
184
+ const PRIORITIZED_STATUSES = ["disconnected", "connecting", "connected"];
185
+ let coalesced;
186
+ for (const status of Object.values(state.syncConnectionStatuses)) {
187
+ if (!coalesced || PRIORITIZED_STATUSES.indexOf(status.status) < PRIORITIZED_STATUSES.indexOf(coalesced.status)) {
188
+ coalesced = status;
189
+ }
190
+ }
191
+ return coalesced;
192
+ }
180
193
  export {
181
194
  getBlockPatternsForPostType,
182
195
  getEditorAssets,
@@ -187,6 +200,7 @@ export {
187
200
  getNavigationFallbackId,
188
201
  getPostsPageId,
189
202
  getRegisteredPostMeta,
203
+ getSyncConnectionStatus,
190
204
  getTemplateId,
191
205
  getUndoManager,
192
206
  getViewConfig,