@wordpress/core-data 7.52.0 → 7.53.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.
- package/CHANGELOG.md +16 -0
- package/README.md +1 -0
- package/build/actions.cjs +18 -9
- package/build/actions.cjs.map +2 -2
- package/build/awareness/awareness-state.cjs.map +2 -2
- package/build/awareness/base-awareness.cjs.map +2 -2
- package/build/awareness/block-lookup.cjs.map +2 -2
- package/build/awareness/post-editor-awareness.cjs +7 -0
- package/build/awareness/post-editor-awareness.cjs.map +2 -2
- package/build/awareness/typed-awareness.cjs.map +2 -2
- package/build/awareness/types.cjs.map +1 -1
- package/build/awareness/utils.cjs.map +2 -2
- package/build/batch/create-batch.cjs.map +2 -2
- package/build/batch/default-processor.cjs.map +2 -2
- package/build/components/entities-saved-states/entity-record-item.cjs.map +2 -2
- package/build/components/entities-saved-states/entity-type-list.cjs.map +2 -2
- package/build/components/entities-saved-states/hooks/use-is-dirty.cjs +4 -0
- package/build/components/entities-saved-states/hooks/use-is-dirty.cjs.map +2 -2
- package/build/components/entities-saved-states/index.cjs.map +2 -2
- package/build/dynamic-entities.cjs.map +2 -2
- package/build/entities.cjs.map +2 -2
- package/build/entity-context.cjs.map +2 -2
- package/build/entity-provider.cjs.map +2 -2
- package/build/entity-types/attachment.cjs.map +1 -1
- package/build/entity-types/base.cjs.map +1 -1
- package/build/entity-types/comment.cjs.map +1 -1
- package/build/entity-types/font-collection.cjs.map +1 -1
- package/build/entity-types/font-family.cjs.map +1 -1
- package/build/entity-types/global-styles-revision.cjs.map +1 -1
- package/build/entity-types/helpers.cjs.map +1 -1
- package/build/entity-types/icon.cjs.map +1 -1
- package/build/entity-types/index.cjs.map +1 -1
- package/build/entity-types/menu-location.cjs.map +1 -1
- package/build/entity-types/nav-menu-item.cjs.map +1 -1
- package/build/entity-types/nav-menu.cjs.map +1 -1
- package/build/entity-types/page.cjs.map +1 -1
- package/build/entity-types/plugin.cjs.map +1 -1
- package/build/entity-types/post-revision.cjs.map +1 -1
- package/build/entity-types/post-status.cjs.map +1 -1
- package/build/entity-types/post.cjs.map +1 -1
- package/build/entity-types/settings.cjs.map +1 -1
- package/build/entity-types/sidebar.cjs.map +1 -1
- package/build/entity-types/taxonomy.cjs.map +1 -1
- package/build/entity-types/term.cjs.map +1 -1
- package/build/entity-types/theme.cjs.map +1 -1
- package/build/entity-types/type.cjs.map +1 -1
- package/build/entity-types/user.cjs.map +1 -1
- package/build/entity-types/widget-type.cjs.map +1 -1
- package/build/entity-types/widget.cjs.map +1 -1
- package/build/entity-types/wp-template-part.cjs.map +1 -1
- package/build/entity-types/wp-template.cjs.map +1 -1
- package/build/fetch/__experimental-fetch-link-suggestions.cjs.map +2 -2
- package/build/fetch/__experimental-fetch-url-data.cjs.map +2 -2
- package/build/fetch/index.cjs.map +2 -2
- package/build/footnotes/get-footnotes-order.cjs.map +2 -2
- package/build/footnotes/get-rich-text-values-cached.cjs.map +2 -2
- package/build/footnotes/index.cjs +12 -1
- package/build/footnotes/index.cjs.map +3 -3
- package/build/hooks/index.cjs.map +2 -2
- package/build/hooks/use-entity-block-editor.cjs.map +2 -2
- package/build/hooks/use-entity-id.cjs.map +2 -2
- package/build/hooks/use-entity-prop.cjs.map +2 -2
- package/build/hooks/use-entity-record.cjs.map +2 -2
- package/build/hooks/use-entity-records.cjs +2 -2
- package/build/hooks/use-entity-records.cjs.map +2 -2
- package/build/hooks/use-post-editor-awareness-state.cjs.map +2 -2
- package/build/hooks/use-query-select.cjs.map +2 -2
- package/build/hooks/use-resource-permissions.cjs.map +2 -2
- package/build/hooks/utils.cjs.map +2 -2
- package/build/index.cjs.map +2 -2
- package/build/lock-unlock.cjs.map +2 -2
- package/build/locks/actions.cjs.map +2 -2
- package/build/locks/engine.cjs.map +2 -2
- package/build/locks/reducer.cjs.map +2 -2
- package/build/locks/selectors.cjs.map +2 -2
- package/build/private-actions.cjs +54 -7
- package/build/private-actions.cjs.map +2 -2
- package/build/private-apis.cjs +3 -0
- package/build/private-apis.cjs.map +2 -2
- package/build/private-selectors.cjs +5 -0
- package/build/private-selectors.cjs.map +2 -2
- package/build/queried-data/get-query-parts.cjs.map +2 -2
- package/build/queried-data/reducer.cjs.map +2 -2
- package/build/queried-data/selectors.cjs.map +2 -2
- package/build/reducer.cjs.map +2 -2
- package/build/resolvers.cjs +21 -26
- package/build/resolvers.cjs.map +2 -2
- package/build/selectors.cjs.map +2 -2
- package/build/sync.cjs +26 -0
- package/build/sync.cjs.map +2 -2
- package/build/types.cjs.map +1 -1
- package/build/utils/block-selection-history.cjs.map +2 -2
- package/build/utils/clear-unchanged-edits.cjs.map +2 -2
- package/build/utils/conservative-map-item.cjs.map +2 -2
- package/build/utils/crdt-blocks.cjs.map +2 -2
- package/build/utils/crdt-selection.cjs.map +2 -2
- package/build/utils/crdt-text.cjs.map +2 -2
- package/build/utils/crdt-user-selections.cjs +43 -16
- package/build/utils/crdt-user-selections.cjs.map +3 -3
- package/build/utils/crdt-utils.cjs.map +2 -2
- package/build/utils/crdt.cjs.map +2 -2
- package/build/utils/get-template-info.cjs.map +2 -2
- package/build/utils/get-template-part-icon.cjs.map +2 -2
- package/build/utils/log-entity-deprecation.cjs.map +2 -2
- package/build/utils/save-crdt-doc.cjs.map +2 -2
- package/build-module/actions.mjs +19 -9
- package/build-module/actions.mjs.map +2 -2
- package/build-module/awareness/awareness-state.mjs.map +2 -2
- package/build-module/awareness/base-awareness.mjs.map +2 -2
- package/build-module/awareness/block-lookup.mjs.map +2 -2
- package/build-module/awareness/post-editor-awareness.mjs +7 -0
- package/build-module/awareness/post-editor-awareness.mjs.map +2 -2
- package/build-module/awareness/typed-awareness.mjs.map +2 -2
- package/build-module/awareness/utils.mjs.map +2 -2
- package/build-module/batch/create-batch.mjs.map +2 -2
- package/build-module/batch/default-processor.mjs.map +2 -2
- package/build-module/components/entities-saved-states/entity-record-item.mjs.map +2 -2
- package/build-module/components/entities-saved-states/entity-type-list.mjs.map +2 -2
- package/build-module/components/entities-saved-states/hooks/use-is-dirty.mjs +4 -0
- package/build-module/components/entities-saved-states/hooks/use-is-dirty.mjs.map +2 -2
- package/build-module/components/entities-saved-states/index.mjs.map +2 -2
- package/build-module/dynamic-entities.mjs.map +2 -2
- package/build-module/entities.mjs.map +2 -2
- package/build-module/entity-context.mjs.map +2 -2
- package/build-module/entity-provider.mjs.map +2 -2
- package/build-module/fetch/__experimental-fetch-link-suggestions.mjs.map +2 -2
- package/build-module/fetch/__experimental-fetch-url-data.mjs.map +2 -2
- package/build-module/fetch/index.mjs.map +2 -2
- package/build-module/footnotes/get-footnotes-order.mjs.map +2 -2
- package/build-module/footnotes/get-rich-text-values-cached.mjs.map +2 -2
- package/build-module/footnotes/index.mjs +12 -1
- package/build-module/footnotes/index.mjs.map +2 -2
- package/build-module/hooks/index.mjs.map +2 -2
- package/build-module/hooks/use-entity-block-editor.mjs.map +2 -2
- package/build-module/hooks/use-entity-id.mjs.map +2 -2
- package/build-module/hooks/use-entity-prop.mjs.map +2 -2
- package/build-module/hooks/use-entity-record.mjs.map +2 -2
- package/build-module/hooks/use-entity-records.mjs +2 -2
- package/build-module/hooks/use-entity-records.mjs.map +2 -2
- package/build-module/hooks/use-post-editor-awareness-state.mjs.map +2 -2
- package/build-module/hooks/use-query-select.mjs.map +2 -2
- package/build-module/hooks/use-resource-permissions.mjs.map +2 -2
- package/build-module/hooks/utils.mjs.map +2 -2
- package/build-module/index.mjs.map +2 -2
- package/build-module/lock-unlock.mjs.map +2 -2
- package/build-module/locks/actions.mjs.map +2 -2
- package/build-module/locks/engine.mjs.map +2 -2
- package/build-module/locks/reducer.mjs.map +2 -2
- package/build-module/locks/selectors.mjs.map +2 -2
- package/build-module/private-actions.mjs +54 -7
- package/build-module/private-actions.mjs.map +2 -2
- package/build-module/private-apis.mjs +9 -1
- package/build-module/private-apis.mjs.map +2 -2
- package/build-module/private-selectors.mjs +4 -0
- package/build-module/private-selectors.mjs.map +2 -2
- package/build-module/queried-data/get-query-parts.mjs.map +2 -2
- package/build-module/queried-data/reducer.mjs.map +2 -2
- package/build-module/queried-data/selectors.mjs.map +2 -2
- package/build-module/reducer.mjs.map +2 -2
- package/build-module/resolvers.mjs +21 -26
- package/build-module/resolvers.mjs.map +2 -2
- package/build-module/selectors.mjs.map +2 -2
- package/build-module/sync.mjs +23 -0
- package/build-module/sync.mjs.map +2 -2
- package/build-module/utils/block-selection-history.mjs.map +2 -2
- package/build-module/utils/clear-unchanged-edits.mjs.map +2 -2
- package/build-module/utils/conservative-map-item.mjs.map +2 -2
- package/build-module/utils/crdt-blocks.mjs.map +2 -2
- package/build-module/utils/crdt-selection.mjs.map +2 -2
- package/build-module/utils/crdt-text.mjs.map +2 -2
- package/build-module/utils/crdt-user-selections.mjs +43 -16
- package/build-module/utils/crdt-user-selections.mjs.map +3 -3
- package/build-module/utils/crdt-utils.mjs.map +2 -2
- package/build-module/utils/crdt.mjs.map +2 -2
- package/build-module/utils/get-template-info.mjs.map +2 -2
- package/build-module/utils/get-template-part-icon.mjs.map +2 -2
- package/build-module/utils/log-entity-deprecation.mjs.map +2 -2
- package/build-module/utils/save-crdt-doc.mjs.map +2 -2
- package/build-types/actions.d.ts +4 -0
- package/build-types/actions.d.ts.map +1 -1
- package/build-types/awareness/awareness-state.d.ts.map +1 -1
- package/build-types/awareness/base-awareness.d.ts +0 -3
- package/build-types/awareness/base-awareness.d.ts.map +1 -1
- package/build-types/awareness/block-lookup.d.ts +0 -3
- package/build-types/awareness/block-lookup.d.ts.map +1 -1
- package/build-types/awareness/post-editor-awareness.d.ts +0 -3
- package/build-types/awareness/post-editor-awareness.d.ts.map +1 -1
- package/build-types/awareness/typed-awareness.d.ts +0 -3
- package/build-types/awareness/typed-awareness.d.ts.map +1 -1
- package/build-types/awareness/types.d.ts +0 -6
- package/build-types/awareness/types.d.ts.map +1 -1
- package/build-types/awareness/utils.d.ts +0 -3
- package/build-types/awareness/utils.d.ts.map +1 -1
- package/build-types/batch/create-batch.d.ts.map +1 -1
- package/build-types/batch/default-processor.d.ts.map +1 -1
- package/build-types/components/entities-saved-states/entity-record-item.d.ts.map +1 -1
- package/build-types/components/entities-saved-states/entity-type-list.d.ts.map +1 -1
- package/build-types/components/entities-saved-states/hooks/use-is-dirty.d.ts.map +1 -1
- package/build-types/components/entities-saved-states/index.d.ts.map +1 -1
- package/build-types/dynamic-entities.d.ts +0 -3
- package/build-types/dynamic-entities.d.ts.map +1 -1
- package/build-types/entities.d.ts.map +1 -1
- package/build-types/entity-context.d.ts.map +1 -1
- package/build-types/entity-provider.d.ts.map +1 -1
- package/build-types/entity-types/attachment.d.ts +0 -3
- package/build-types/entity-types/attachment.d.ts.map +1 -1
- package/build-types/entity-types/base.d.ts +0 -3
- package/build-types/entity-types/base.d.ts.map +1 -1
- package/build-types/entity-types/comment.d.ts +0 -3
- package/build-types/entity-types/comment.d.ts.map +1 -1
- package/build-types/entity-types/font-collection.d.ts +0 -3
- package/build-types/entity-types/font-collection.d.ts.map +1 -1
- package/build-types/entity-types/font-family.d.ts +0 -3
- package/build-types/entity-types/font-family.d.ts.map +1 -1
- package/build-types/entity-types/global-styles-revision.d.ts +0 -3
- package/build-types/entity-types/global-styles-revision.d.ts.map +1 -1
- package/build-types/entity-types/helpers.d.ts +0 -3
- package/build-types/entity-types/helpers.d.ts.map +1 -1
- package/build-types/entity-types/icon.d.ts +0 -3
- package/build-types/entity-types/icon.d.ts.map +1 -1
- package/build-types/entity-types/index.d.ts +0 -3
- package/build-types/entity-types/index.d.ts.map +1 -1
- package/build-types/entity-types/menu-location.d.ts +0 -3
- package/build-types/entity-types/menu-location.d.ts.map +1 -1
- package/build-types/entity-types/nav-menu-item.d.ts +0 -3
- package/build-types/entity-types/nav-menu-item.d.ts.map +1 -1
- package/build-types/entity-types/nav-menu.d.ts +0 -3
- package/build-types/entity-types/nav-menu.d.ts.map +1 -1
- package/build-types/entity-types/page.d.ts +0 -3
- package/build-types/entity-types/page.d.ts.map +1 -1
- package/build-types/entity-types/plugin.d.ts +0 -3
- package/build-types/entity-types/plugin.d.ts.map +1 -1
- package/build-types/entity-types/post-revision.d.ts +0 -3
- package/build-types/entity-types/post-revision.d.ts.map +1 -1
- package/build-types/entity-types/post-status.d.ts +0 -3
- package/build-types/entity-types/post-status.d.ts.map +1 -1
- package/build-types/entity-types/post.d.ts +0 -3
- package/build-types/entity-types/post.d.ts.map +1 -1
- package/build-types/entity-types/settings.d.ts +0 -3
- package/build-types/entity-types/settings.d.ts.map +1 -1
- package/build-types/entity-types/sidebar.d.ts +0 -3
- package/build-types/entity-types/sidebar.d.ts.map +1 -1
- package/build-types/entity-types/taxonomy.d.ts +0 -3
- package/build-types/entity-types/taxonomy.d.ts.map +1 -1
- package/build-types/entity-types/term.d.ts +0 -3
- package/build-types/entity-types/term.d.ts.map +1 -1
- package/build-types/entity-types/test/attachment.test.d.ts +0 -8
- package/build-types/entity-types/test/attachment.test.d.ts.map +1 -1
- package/build-types/entity-types/theme.d.ts +0 -3
- package/build-types/entity-types/theme.d.ts.map +1 -1
- package/build-types/entity-types/type.d.ts +0 -3
- package/build-types/entity-types/type.d.ts.map +1 -1
- package/build-types/entity-types/user.d.ts +0 -3
- package/build-types/entity-types/user.d.ts.map +1 -1
- package/build-types/entity-types/widget-type.d.ts +0 -3
- package/build-types/entity-types/widget-type.d.ts.map +1 -1
- package/build-types/entity-types/widget.d.ts +0 -3
- package/build-types/entity-types/widget.d.ts.map +1 -1
- package/build-types/entity-types/wp-template-part.d.ts +0 -3
- package/build-types/entity-types/wp-template-part.d.ts.map +1 -1
- package/build-types/entity-types/wp-template.d.ts +0 -3
- package/build-types/entity-types/wp-template.d.ts.map +1 -1
- package/build-types/fetch/__experimental-fetch-link-suggestions.d.ts.map +1 -1
- package/build-types/fetch/__experimental-fetch-url-data.d.ts.map +1 -1
- package/build-types/fetch/index.d.ts.map +1 -1
- package/build-types/footnotes/get-footnotes-order.d.ts.map +1 -1
- package/build-types/footnotes/get-rich-text-values-cached.d.ts.map +1 -1
- package/build-types/footnotes/index.d.ts.map +1 -1
- package/build-types/hooks/index.d.ts +0 -3
- package/build-types/hooks/index.d.ts.map +1 -1
- package/build-types/hooks/use-entity-block-editor.d.ts.map +1 -1
- package/build-types/hooks/use-entity-id.d.ts.map +1 -1
- package/build-types/hooks/use-entity-prop.d.ts.map +1 -1
- package/build-types/hooks/use-entity-record.d.ts.map +1 -1
- package/build-types/hooks/use-entity-records.d.ts.map +1 -1
- package/build-types/hooks/use-post-editor-awareness-state.d.ts.map +1 -1
- package/build-types/hooks/use-query-select.d.ts.map +1 -1
- package/build-types/hooks/use-resource-permissions.d.ts.map +1 -1
- package/build-types/hooks/utils.d.ts +0 -6
- package/build-types/hooks/utils.d.ts.map +1 -1
- package/build-types/index.d.ts +1 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/lock-unlock.d.ts.map +1 -1
- package/build-types/locks/actions.d.ts.map +1 -1
- package/build-types/locks/engine.d.ts.map +1 -1
- package/build-types/locks/reducer.d.ts.map +1 -1
- package/build-types/locks/selectors.d.ts.map +1 -1
- package/build-types/private-actions.d.ts +1 -1
- package/build-types/private-actions.d.ts.map +1 -1
- package/build-types/private-apis.d.ts +4 -3
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/private-selectors.d.ts +12 -3
- package/build-types/private-selectors.d.ts.map +1 -1
- package/build-types/queried-data/get-query-parts.d.ts.map +1 -1
- package/build-types/queried-data/reducer.d.ts.map +1 -1
- package/build-types/queried-data/selectors.d.ts.map +1 -1
- package/build-types/reducer.d.ts.map +1 -1
- package/build-types/resolvers.d.ts +1 -2
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/selectors.d.ts.map +1 -1
- package/build-types/sync.d.ts +31 -3
- package/build-types/sync.d.ts.map +1 -1
- package/build-types/types.d.ts +9 -8
- package/build-types/types.d.ts.map +1 -1
- package/build-types/utils/block-selection-history.d.ts +0 -6
- package/build-types/utils/block-selection-history.d.ts.map +1 -1
- package/build-types/utils/clear-unchanged-edits.d.ts.map +1 -1
- package/build-types/utils/conservative-map-item.d.ts.map +1 -1
- package/build-types/utils/crdt-blocks.d.ts +0 -3
- package/build-types/utils/crdt-blocks.d.ts.map +1 -1
- package/build-types/utils/crdt-selection.d.ts +0 -3
- package/build-types/utils/crdt-selection.d.ts.map +1 -1
- package/build-types/utils/crdt-text.d.ts +0 -3
- package/build-types/utils/crdt-text.d.ts.map +1 -1
- package/build-types/utils/crdt-user-selections.d.ts.map +1 -1
- package/build-types/utils/crdt-utils.d.ts +0 -6
- package/build-types/utils/crdt-utils.d.ts.map +1 -1
- package/build-types/utils/crdt.d.ts.map +1 -1
- package/build-types/utils/get-template-info.d.ts.map +1 -1
- package/build-types/utils/get-template-part-icon.d.ts.map +1 -1
- package/build-types/utils/log-entity-deprecation.d.ts.map +1 -1
- package/build-types/utils/save-crdt-doc.d.ts.map +1 -1
- package/package.json +24 -23
- package/src/actions.js +45 -29
- package/src/awareness/awareness-state.ts +0 -3
- package/src/awareness/base-awareness.ts +0 -8
- package/src/awareness/block-lookup.ts +1 -8
- package/src/awareness/post-editor-awareness.ts +13 -10
- package/src/awareness/test/awareness-state.ts +0 -11
- package/src/awareness/test/base-awareness.ts +0 -7
- package/src/awareness/test/block-lookup.ts +0 -8
- package/src/awareness/test/post-editor-awareness.ts +0 -7
- package/src/awareness/test/typed-awareness.ts +0 -11
- package/src/awareness/test/utils.ts +0 -3
- package/src/awareness/typed-awareness.ts +0 -7
- package/src/awareness/types.ts +0 -7
- package/src/awareness/utils.ts +0 -3
- package/src/batch/create-batch.js +0 -3
- package/src/batch/default-processor.js +0 -4
- package/src/batch/test/create-batch.js +0 -3
- package/src/batch/test/default-processor.js +0 -7
- package/src/components/entities-saved-states/entity-record-item.js +0 -7
- package/src/components/entities-saved-states/entity-type-list.js +0 -7
- package/src/components/entities-saved-states/hooks/use-is-dirty.js +4 -7
- package/src/components/entities-saved-states/index.js +0 -11
- package/src/components/entities-saved-states/test/use-is-dirty.js +70 -11
- package/src/dynamic-entities.ts +0 -3
- package/src/entities.js +0 -11
- package/src/entity-context.js +0 -3
- package/src/entity-provider.js +0 -7
- package/src/entity-types/attachment.ts +0 -4
- package/src/entity-types/base.ts +0 -3
- package/src/entity-types/comment.ts +0 -3
- package/src/entity-types/font-collection.ts +0 -3
- package/src/entity-types/font-family.ts +0 -3
- package/src/entity-types/global-styles-revision.ts +0 -4
- package/src/entity-types/helpers.ts +0 -3
- package/src/entity-types/icon.ts +0 -4
- package/src/entity-types/index.ts +0 -3
- package/src/entity-types/menu-location.ts +0 -4
- package/src/entity-types/nav-menu-item.ts +0 -4
- package/src/entity-types/nav-menu.ts +0 -4
- package/src/entity-types/page.ts +0 -4
- package/src/entity-types/plugin.ts +0 -4
- package/src/entity-types/post-revision.ts +0 -4
- package/src/entity-types/post-status.ts +0 -3
- package/src/entity-types/post.ts +0 -4
- package/src/entity-types/settings.ts +0 -4
- package/src/entity-types/sidebar.ts +0 -4
- package/src/entity-types/taxonomy.ts +0 -4
- package/src/entity-types/term.ts +0 -4
- package/src/entity-types/test/attachment.test.ts +0 -4
- package/src/entity-types/theme.ts +0 -4
- package/src/entity-types/type.ts +0 -4
- package/src/entity-types/user.ts +0 -4
- package/src/entity-types/widget-type.ts +0 -4
- package/src/entity-types/widget.ts +0 -4
- package/src/entity-types/wp-template-part.ts +0 -4
- package/src/entity-types/wp-template.ts +0 -4
- package/src/fetch/__experimental-fetch-link-suggestions.ts +0 -3
- package/src/fetch/__experimental-fetch-url-data.js +0 -3
- package/src/fetch/index.js +0 -7
- package/src/fetch/test/__experimental-fetch-link-suggestions.js +0 -3
- package/src/fetch/test/__experimental-fetch-url-data.js +1 -7
- package/src/footnotes/get-footnotes-order.js +0 -3
- package/src/footnotes/get-rich-text-values-cached.js +0 -7
- package/src/footnotes/index.js +21 -8
- package/src/footnotes/test/index.js +57 -0
- package/src/hooks/index.ts +0 -3
- package/src/hooks/test/use-entity-record.js +0 -12
- package/src/hooks/test/use-entity-records.js +0 -12
- package/src/hooks/test/use-post-editor-awareness-state.ts +0 -7
- package/src/hooks/test/use-query-select.js +0 -11
- package/src/hooks/test/use-resource-permissions.js +0 -12
- package/src/hooks/use-entity-block-editor.js +0 -7
- package/src/hooks/use-entity-id.js +0 -7
- package/src/hooks/use-entity-prop.js +0 -7
- package/src/hooks/use-entity-record.ts +0 -7
- package/src/hooks/use-entity-records.ts +2 -9
- package/src/hooks/use-post-editor-awareness-state.ts +0 -7
- package/src/hooks/use-query-select.ts +0 -7
- package/src/hooks/use-resource-permissions.ts +0 -7
- package/src/hooks/utils.ts +0 -7
- package/src/index.js +0 -7
- package/src/lock-unlock.ts +0 -3
- package/src/locks/actions.js +0 -3
- package/src/locks/engine.js +0 -3
- package/src/locks/reducer.js +0 -3
- package/src/locks/selectors.js +0 -3
- package/src/locks/test/engine.js +0 -3
- package/src/locks/test/reducer.js +0 -7
- package/src/locks/test/selectors.js +0 -7
- package/src/locks/test/utils.js +0 -7
- package/src/private-actions.js +63 -15
- package/src/private-apis.ts +9 -4
- package/src/private-selectors.ts +22 -7
- package/src/queried-data/get-query-parts.js +0 -7
- package/src/queried-data/reducer.js +0 -7
- package/src/queried-data/selectors.js +0 -7
- package/src/queried-data/test/actions.js +0 -3
- package/src/queried-data/test/get-query-parts.js +0 -3
- package/src/queried-data/test/reducer.js +0 -7
- package/src/queried-data/test/selectors.js +0 -3
- package/src/reducer.js +0 -11
- package/src/resolvers.js +23 -40
- package/src/selectors.ts +0 -7
- package/src/sync.ts +64 -7
- package/src/test/actions.js +256 -8
- package/src/test/deprecated-entity-logging.js +0 -7
- package/src/test/entities.js +0 -8
- package/src/test/entity-provider.js +0 -11
- package/src/test/private-actions.js +297 -7
- package/src/test/private-selectors.js +0 -3
- package/src/test/reducer.js +0 -7
- package/src/test/resolvers.js +0 -12
- package/src/test/rtc-rich-text-offset-space.test.js +0 -12
- package/src/test/selectors.js +0 -7
- package/src/test/store.js +8 -15
- package/src/types.ts +14 -12
- package/src/utils/block-selection-history.ts +0 -10
- package/src/utils/clear-unchanged-edits.ts +0 -3
- package/src/utils/conservative-map-item.js +0 -3
- package/src/utils/crdt-blocks.ts +0 -11
- package/src/utils/crdt-selection.ts +0 -7
- package/src/utils/crdt-text.ts +0 -3
- package/src/utils/crdt-user-selections.ts +85 -23
- package/src/utils/crdt-utils.ts +0 -7
- package/src/utils/crdt.ts +0 -11
- package/src/utils/get-template-info.js +0 -6
- package/src/utils/get-template-part-icon.js +0 -3
- package/src/utils/log-entity-deprecation.ts +0 -7
- package/src/utils/save-crdt-doc.js +0 -7
- package/src/utils/test/block-selection-history.test.ts +0 -7
- package/src/utils/test/clear-unchanged-edits.js +0 -3
- package/src/utils/test/conservative-map-item.js +0 -3
- package/src/utils/test/crdt-blocks.ts +0 -17
- package/src/utils/test/crdt-user-selections.ts +107 -30
- package/src/utils/test/crdt-utils.ts +0 -7
- package/src/utils/test/crdt.ts +0 -16
- package/src/utils/test/get-nested-value.js +0 -3
- package/src/utils/test/get-normalized-comma-separable.js +0 -3
- package/src/utils/test/get-template-info.js +0 -6
- package/src/utils/test/if-matching-action.js +0 -7
- package/src/utils/test/is-numeric-id.js +0 -3
- package/src/utils/test/log-entity-deprecation.js +0 -7
- package/src/utils/test/replace-action.js +0 -3
- package/src/utils/test/rtc-rich-text-cursor-scope.test.js +0 -14
- package/src/utils/test/rtc-rich-text-offset-space.test.js +0 -14
- package/src/utils/test/save-crdt-doc.js +0 -7
- package/src/utils/test/set-nested-value.js +0 -3
- package/src/utils/test/with-weak-map-cache.js +0 -3
- package/build-types/utils/on-sub-key.d.ts +0 -4
- package/build-types/utils/on-sub-key.d.ts.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/awareness/awareness-state.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Internal dependencies\n */\nimport { REMOVAL_DELAY_IN_MS } from './config';\nimport { TypedAwareness } from './typed-awareness';\nimport type { EnhancedState, EqualityFieldCheck } from './types';\nimport { getTypedKeys, areMapsEqual } from './utils';\n\ntype AwarenessClientID = number;\n\ninterface AwarenessStateChange {\n\tadded: AwarenessClientID[];\n\tupdated: AwarenessClientID[];\n\tremoved: AwarenessClientID[];\n}\n\nabstract class AwarenessWithEqualityChecks<\n\tState extends object,\n> extends TypedAwareness< State > {\n\t/** OVERRIDDEN METHODS */\n\n\t/**\n\t * Set a local state field on an awareness document. Calling this method may\n\t * trigger rerenders of any subscribed components.\n\t *\n\t * Equality checks are provided by the abstract `equalityFieldChecks` property.\n\t * @param field - The field to set.\n\t * @param value - The value to set.\n\t */\n\tpublic setLocalStateField< FieldName extends string & keyof State >(\n\t\tfield: FieldName,\n\t\tvalue: State[ FieldName ]\n\t): void {\n\t\tif (\n\t\t\tthis.isFieldEqual(\n\t\t\t\tfield,\n\t\t\t\tvalue,\n\t\t\t\tthis.getLocalStateField( field ) ?? undefined\n\t\t\t)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tsuper.setLocalStateField( field, value );\n\t}\n\n\t/** ABSTRACT PROPERTIES */\n\n\t/**\n\t * Extending classes must implement equality checks for each awareness state\n\t * field they manage.\n\t */\n\tprotected abstract equalityFieldChecks: {\n\t\t[ FieldName in keyof State ]: EqualityFieldCheck< State, FieldName >;\n\t};\n\n\t/** CUSTOM METHODS */\n\n\t/**\n\t * Determine if a field value has changed using the provided equality checks.\n\t * @param field - The field to check.\n\t * @param value1 - The first value to compare.\n\t * @param value2 - The second value to compare.\n\t */\n\tprotected isFieldEqual< FieldName extends keyof State >(\n\t\tfield: FieldName,\n\t\tvalue1?: State[ FieldName ],\n\t\tvalue2?: State[ FieldName ]\n\t): boolean {\n\t\tif (\n\t\t\t[ 'clientId', 'isConnected', 'isMe' ].includes( field as string )\n\t\t) {\n\t\t\treturn value1 === value2;\n\t\t}\n\n\t\tif ( field in this.equalityFieldChecks ) {\n\t\t\tconst fn = this.equalityFieldChecks[ field ];\n\t\t\treturn fn( value1, value2 );\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`No equality check implemented for awareness state field \"${ field.toString() }\".`\n\t\t);\n\t}\n\n\t/**\n\t * Determine if two states are equal by comparing each field using the\n\t * provided equality checks.\n\t * @param state1 - The first state to compare.\n\t * @param state2 - The second state to compare.\n\t */\n\tprotected isStateEqual( state1: State, state2: State ): boolean {\n\t\treturn [\n\t\t\t...new Set< keyof State >( [\n\t\t\t\t...getTypedKeys( state1 ),\n\t\t\t\t...getTypedKeys( state2 ),\n\t\t\t] ),\n\t\t].every( ( field ) => {\n\t\t\tconst value1 = state1[ field ];\n\t\t\tconst value2 = state2[ field ];\n\n\t\t\treturn this.isFieldEqual( field, value1, value2 );\n\t\t} );\n\t}\n}\n\n/**\n * Abstract class to manage awareness and allow external code to subscribe to\n * state updates.\n */\nexport abstract class AwarenessState<\n\tState extends object = {},\n> extends AwarenessWithEqualityChecks< State > {\n\t/** CUSTOM PROPERTIES */\n\n\t/**\n\t * Whether the setUp method has been called, to avoid running it multiple\n\t * times.\n\t */\n\tprivate hasSetupRun = false;\n\n\t/**\n\t * We keep track of all seen states during the current session for two reasons:\n\t *\n\t * 1. So that we can represent recently disconnected collaborators in our UI, even\n\t * after they have been removed from the awareness document.\n\t * 2. So that we can provide debug information about all collaborators seen during\n\t * the session.\n\t */\n\tprivate disconnectedCollaborators: Set< number > = new Set();\n\tprivate seenStates: Map< number, State > = new Map();\n\n\t/**\n\t * Hold a snapshot of the previous awareness state allows us to compare the\n\t * state values and avoid unnecessary updates to subscribers.\n\t */\n\tprivate previousSnapshot = new Map< number, EnhancedState< State > >();\n\tprivate stateSubscriptions: Array<\n\t\t( newState: EnhancedState< State >[] ) => void\n\t> = [];\n\n\t/**\n\t * In some cases, we may want to throttle setting local state fields to avoid\n\t * overwhelming the awareness document with rapid updates. At the same time, we\n\t * want to ensure that when we read our own state locally, we get the latest\n\t * value -- even if it hasn't yet been set on the awareness instance.\n\t */\n\tprivate myThrottledState: Partial< State > = {};\n\tprivate throttleTimeouts: Map< string, NodeJS.Timeout > = new Map();\n\n\t/** CUSTOM METHODS */\n\n\t/**\n\t * Set up the awareness state. This method is idempotent and will only run\n\t * once. Subclasses should override `onSetUp()` instead of this method to\n\t * add their own setup logic.\n\t *\n\t * This is defined as a readonly arrow function property to prevent\n\t * subclasses from overriding it.\n\t */\n\tpublic readonly setUp = (): void => {\n\t\tif ( this.hasSetupRun ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.hasSetupRun = true;\n\n\t\tthis.onSetUp();\n\n\t\tthis.on(\n\t\t\t'change',\n\t\t\t( { added, removed, updated }: AwarenessStateChange ) => {\n\t\t\t\t[ ...added, ...updated ].forEach( ( id ) => {\n\t\t\t\t\tthis.disconnectedCollaborators.delete( id );\n\t\t\t\t} );\n\n\t\t\t\tremoved.forEach( ( id ) => {\n\t\t\t\t\tthis.disconnectedCollaborators.add( id );\n\n\t\t\t\t\tsetTimeout( () => {\n\t\t\t\t\t\tthis.disconnectedCollaborators.delete( id );\n\t\t\t\t\t\tthis.updateSubscribers( true /* force update */ );\n\t\t\t\t\t}, REMOVAL_DELAY_IN_MS );\n\t\t\t\t} );\n\n\t\t\t\t// Do not force-update the store here, since this change handler can be\n\t\t\t\t// called even when there are no actual state changes.\n\t\t\t\tthis.updateSubscribers();\n\t\t\t}\n\t\t);\n\t};\n\n\t/**\n\t * Hook method for subclasses to add their own setup logic. This is called\n\t * once after the base class setup completes. All subclasses must implement\n\t * this method. If extending a class that already implements `onSetUp()`,\n\t * call `super.onSetUp()` to ensure parent setup runs.\n\t */\n\tprotected abstract onSetUp(): void;\n\n\t/**\n\t * Get the most recent state from the last processed change event.\n\t *\n\t * @return An array of EnhancedState< State >.\n\t */\n\tpublic getCurrentState(): EnhancedState< State >[] {\n\t\treturn Array.from( this.previousSnapshot.values() );\n\t}\n\n\t/**\n\t * Get all seen states in this session to enable debug reporting.\n\t */\n\tpublic getSeenStates(): Map< number, State > {\n\t\treturn this.seenStates;\n\t}\n\n\t/**\n\t * Allow external code to subscribe to awareness state changes.\n\t * @param callback - The callback to subscribe to.\n\t */\n\tpublic onStateChange(\n\t\tcallback: ( newState: EnhancedState< State >[] ) => void\n\t): () => void {\n\t\tthis.stateSubscriptions.push( callback );\n\n\t\treturn () => {\n\t\t\tthis.stateSubscriptions = this.stateSubscriptions.filter(\n\t\t\t\t( cb ) => cb !== callback\n\t\t\t);\n\t\t};\n\t}\n\n\t/**\n\t * Set a local state field on an awareness document with throttle. See caveats\n\t * of this.setLocalStateField.\n\t * @param field - The field to set.\n\t * @param value - The value to set.\n\t * @param wait - The wait time in milliseconds.\n\t */\n\tpublic setThrottledLocalStateField<\n\t\tFieldName extends string & keyof State,\n\t>( field: FieldName, value: State[ FieldName ], wait: number ): void {\n\t\tthis.setLocalStateField( field, value );\n\n\t\tthis.throttleTimeouts.set(\n\t\t\tfield,\n\t\t\tsetTimeout( () => {\n\t\t\t\tthis.throttleTimeouts.delete( field );\n\t\t\t\tif ( this.myThrottledState[ field ] ) {\n\t\t\t\t\tthis.setLocalStateField(\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tthis.myThrottledState[ field ]\n\t\t\t\t\t);\n\n\t\t\t\t\tdelete this.myThrottledState[ field ];\n\t\t\t\t}\n\t\t\t}, wait )\n\t\t);\n\t}\n\n\t/**\n\t * Set the current collaborator's connection status as awareness state.\n\t * @param isConnected - The connection status.\n\t */\n\tpublic setConnectionStatus( isConnected: boolean ): void {\n\t\tif ( isConnected ) {\n\t\t\tthis.disconnectedCollaborators.delete( this.clientID );\n\t\t} else {\n\t\t\tthis.disconnectedCollaborators.add( this.clientID );\n\t\t}\n\n\t\tthis.updateSubscribers( true /* force update */ );\n\t}\n\n\t/**\n\t * Update all subscribed listeners with the latest awareness state.\n\t * @param forceUpdate - Whether to force an update.\n\t */\n\tprotected updateSubscribers( forceUpdate = false ): void {\n\t\tif ( ! this.stateSubscriptions.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst states = this.getStates();\n\n\t\tthis.seenStates = new Map< number, State >( [\n\t\t\t...this.seenStates.entries(),\n\t\t\t...states.entries(),\n\t\t] );\n\n\t\tconst updatedStates = new Map< number, EnhancedState< State > >(\n\t\t\t[ ...this.disconnectedCollaborators, ...states.keys() ]\n\t\t\t\t.filter( ( clientId ) => {\n\t\t\t\t\t// Exclude any collaborators with empty awareness state. This can happen from\n\t\t\t\t\t// the Yjs inspector.\n\t\t\t\t\treturn (\n\t\t\t\t\t\tObject.keys( this.seenStates.get( clientId ) ?? {} )\n\t\t\t\t\t\t\t.length > 0\n\t\t\t\t\t);\n\t\t\t\t} )\n\t\t\t\t.map( ( clientId ) => {\n\t\t\t\t\t// The filter above ensures that seenStates has the clientId.\n\t\t\t\t\tconst rawState: State = this.seenStates.get( clientId )!;\n\n\t\t\t\t\tconst isConnected =\n\t\t\t\t\t\t! this.disconnectedCollaborators.has( clientId );\n\t\t\t\t\tconst isMe = clientId === this.clientID;\n\t\t\t\t\tconst myState: Partial< State > = isMe\n\t\t\t\t\t\t? this.myThrottledState\n\t\t\t\t\t\t: {};\n\t\t\t\t\tconst state: EnhancedState< State > = {\n\t\t\t\t\t\t...rawState,\n\t\t\t\t\t\t...myState,\n\t\t\t\t\t\tclientId,\n\t\t\t\t\t\tisConnected,\n\t\t\t\t\t\tisMe,\n\t\t\t\t\t};\n\n\t\t\t\t\treturn [ clientId, state ];\n\t\t\t\t} )\n\t\t);\n\n\t\tif ( ! forceUpdate ) {\n\t\t\tif (\n\t\t\t\tareMapsEqual(\n\t\t\t\t\tthis.previousSnapshot,\n\t\t\t\t\tupdatedStates,\n\t\t\t\t\tthis.isStateEqual.bind( this )\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\t// Awareness state unchanged, do not update subscribers.\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Update subscribers.\n\t\tthis.previousSnapshot = updatedStates;\n\t\tthis.stateSubscriptions.forEach( ( callback ) => {\n\t\t\tcallback( Array.from( updatedStates.values() ) );\n\t\t} );\n\t}\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import { REMOVAL_DELAY_IN_MS } from './config';\nimport { TypedAwareness } from './typed-awareness';\nimport type { EnhancedState, EqualityFieldCheck } from './types';\nimport { getTypedKeys, areMapsEqual } from './utils';\n\ntype AwarenessClientID = number;\n\ninterface AwarenessStateChange {\n\tadded: AwarenessClientID[];\n\tupdated: AwarenessClientID[];\n\tremoved: AwarenessClientID[];\n}\n\nabstract class AwarenessWithEqualityChecks<\n\tState extends object,\n> extends TypedAwareness< State > {\n\t/** OVERRIDDEN METHODS */\n\n\t/**\n\t * Set a local state field on an awareness document. Calling this method may\n\t * trigger rerenders of any subscribed components.\n\t *\n\t * Equality checks are provided by the abstract `equalityFieldChecks` property.\n\t * @param field - The field to set.\n\t * @param value - The value to set.\n\t */\n\tpublic setLocalStateField< FieldName extends string & keyof State >(\n\t\tfield: FieldName,\n\t\tvalue: State[ FieldName ]\n\t): void {\n\t\tif (\n\t\t\tthis.isFieldEqual(\n\t\t\t\tfield,\n\t\t\t\tvalue,\n\t\t\t\tthis.getLocalStateField( field ) ?? undefined\n\t\t\t)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tsuper.setLocalStateField( field, value );\n\t}\n\n\t/** ABSTRACT PROPERTIES */\n\n\t/**\n\t * Extending classes must implement equality checks for each awareness state\n\t * field they manage.\n\t */\n\tprotected abstract equalityFieldChecks: {\n\t\t[ FieldName in keyof State ]: EqualityFieldCheck< State, FieldName >;\n\t};\n\n\t/** CUSTOM METHODS */\n\n\t/**\n\t * Determine if a field value has changed using the provided equality checks.\n\t * @param field - The field to check.\n\t * @param value1 - The first value to compare.\n\t * @param value2 - The second value to compare.\n\t */\n\tprotected isFieldEqual< FieldName extends keyof State >(\n\t\tfield: FieldName,\n\t\tvalue1?: State[ FieldName ],\n\t\tvalue2?: State[ FieldName ]\n\t): boolean {\n\t\tif (\n\t\t\t[ 'clientId', 'isConnected', 'isMe' ].includes( field as string )\n\t\t) {\n\t\t\treturn value1 === value2;\n\t\t}\n\n\t\tif ( field in this.equalityFieldChecks ) {\n\t\t\tconst fn = this.equalityFieldChecks[ field ];\n\t\t\treturn fn( value1, value2 );\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`No equality check implemented for awareness state field \"${ field.toString() }\".`\n\t\t);\n\t}\n\n\t/**\n\t * Determine if two states are equal by comparing each field using the\n\t * provided equality checks.\n\t * @param state1 - The first state to compare.\n\t * @param state2 - The second state to compare.\n\t */\n\tprotected isStateEqual( state1: State, state2: State ): boolean {\n\t\treturn [\n\t\t\t...new Set< keyof State >( [\n\t\t\t\t...getTypedKeys( state1 ),\n\t\t\t\t...getTypedKeys( state2 ),\n\t\t\t] ),\n\t\t].every( ( field ) => {\n\t\t\tconst value1 = state1[ field ];\n\t\t\tconst value2 = state2[ field ];\n\n\t\t\treturn this.isFieldEqual( field, value1, value2 );\n\t\t} );\n\t}\n}\n\n/**\n * Abstract class to manage awareness and allow external code to subscribe to\n * state updates.\n */\nexport abstract class AwarenessState<\n\tState extends object = {},\n> extends AwarenessWithEqualityChecks< State > {\n\t/** CUSTOM PROPERTIES */\n\n\t/**\n\t * Whether the setUp method has been called, to avoid running it multiple\n\t * times.\n\t */\n\tprivate hasSetupRun = false;\n\n\t/**\n\t * We keep track of all seen states during the current session for two reasons:\n\t *\n\t * 1. So that we can represent recently disconnected collaborators in our UI, even\n\t * after they have been removed from the awareness document.\n\t * 2. So that we can provide debug information about all collaborators seen during\n\t * the session.\n\t */\n\tprivate disconnectedCollaborators: Set< number > = new Set();\n\tprivate seenStates: Map< number, State > = new Map();\n\n\t/**\n\t * Hold a snapshot of the previous awareness state allows us to compare the\n\t * state values and avoid unnecessary updates to subscribers.\n\t */\n\tprivate previousSnapshot = new Map< number, EnhancedState< State > >();\n\tprivate stateSubscriptions: Array<\n\t\t( newState: EnhancedState< State >[] ) => void\n\t> = [];\n\n\t/**\n\t * In some cases, we may want to throttle setting local state fields to avoid\n\t * overwhelming the awareness document with rapid updates. At the same time, we\n\t * want to ensure that when we read our own state locally, we get the latest\n\t * value -- even if it hasn't yet been set on the awareness instance.\n\t */\n\tprivate myThrottledState: Partial< State > = {};\n\tprivate throttleTimeouts: Map< string, NodeJS.Timeout > = new Map();\n\n\t/** CUSTOM METHODS */\n\n\t/**\n\t * Set up the awareness state. This method is idempotent and will only run\n\t * once. Subclasses should override `onSetUp()` instead of this method to\n\t * add their own setup logic.\n\t *\n\t * This is defined as a readonly arrow function property to prevent\n\t * subclasses from overriding it.\n\t */\n\tpublic readonly setUp = (): void => {\n\t\tif ( this.hasSetupRun ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.hasSetupRun = true;\n\n\t\tthis.onSetUp();\n\n\t\tthis.on(\n\t\t\t'change',\n\t\t\t( { added, removed, updated }: AwarenessStateChange ) => {\n\t\t\t\t[ ...added, ...updated ].forEach( ( id ) => {\n\t\t\t\t\tthis.disconnectedCollaborators.delete( id );\n\t\t\t\t} );\n\n\t\t\t\tremoved.forEach( ( id ) => {\n\t\t\t\t\tthis.disconnectedCollaborators.add( id );\n\n\t\t\t\t\tsetTimeout( () => {\n\t\t\t\t\t\tthis.disconnectedCollaborators.delete( id );\n\t\t\t\t\t\tthis.updateSubscribers( true /* force update */ );\n\t\t\t\t\t}, REMOVAL_DELAY_IN_MS );\n\t\t\t\t} );\n\n\t\t\t\t// Do not force-update the store here, since this change handler can be\n\t\t\t\t// called even when there are no actual state changes.\n\t\t\t\tthis.updateSubscribers();\n\t\t\t}\n\t\t);\n\t};\n\n\t/**\n\t * Hook method for subclasses to add their own setup logic. This is called\n\t * once after the base class setup completes. All subclasses must implement\n\t * this method. If extending a class that already implements `onSetUp()`,\n\t * call `super.onSetUp()` to ensure parent setup runs.\n\t */\n\tprotected abstract onSetUp(): void;\n\n\t/**\n\t * Get the most recent state from the last processed change event.\n\t *\n\t * @return An array of EnhancedState< State >.\n\t */\n\tpublic getCurrentState(): EnhancedState< State >[] {\n\t\treturn Array.from( this.previousSnapshot.values() );\n\t}\n\n\t/**\n\t * Get all seen states in this session to enable debug reporting.\n\t */\n\tpublic getSeenStates(): Map< number, State > {\n\t\treturn this.seenStates;\n\t}\n\n\t/**\n\t * Allow external code to subscribe to awareness state changes.\n\t * @param callback - The callback to subscribe to.\n\t */\n\tpublic onStateChange(\n\t\tcallback: ( newState: EnhancedState< State >[] ) => void\n\t): () => void {\n\t\tthis.stateSubscriptions.push( callback );\n\n\t\treturn () => {\n\t\t\tthis.stateSubscriptions = this.stateSubscriptions.filter(\n\t\t\t\t( cb ) => cb !== callback\n\t\t\t);\n\t\t};\n\t}\n\n\t/**\n\t * Set a local state field on an awareness document with throttle. See caveats\n\t * of this.setLocalStateField.\n\t * @param field - The field to set.\n\t * @param value - The value to set.\n\t * @param wait - The wait time in milliseconds.\n\t */\n\tpublic setThrottledLocalStateField<\n\t\tFieldName extends string & keyof State,\n\t>( field: FieldName, value: State[ FieldName ], wait: number ): void {\n\t\tthis.setLocalStateField( field, value );\n\n\t\tthis.throttleTimeouts.set(\n\t\t\tfield,\n\t\t\tsetTimeout( () => {\n\t\t\t\tthis.throttleTimeouts.delete( field );\n\t\t\t\tif ( this.myThrottledState[ field ] ) {\n\t\t\t\t\tthis.setLocalStateField(\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tthis.myThrottledState[ field ]\n\t\t\t\t\t);\n\n\t\t\t\t\tdelete this.myThrottledState[ field ];\n\t\t\t\t}\n\t\t\t}, wait )\n\t\t);\n\t}\n\n\t/**\n\t * Set the current collaborator's connection status as awareness state.\n\t * @param isConnected - The connection status.\n\t */\n\tpublic setConnectionStatus( isConnected: boolean ): void {\n\t\tif ( isConnected ) {\n\t\t\tthis.disconnectedCollaborators.delete( this.clientID );\n\t\t} else {\n\t\t\tthis.disconnectedCollaborators.add( this.clientID );\n\t\t}\n\n\t\tthis.updateSubscribers( true /* force update */ );\n\t}\n\n\t/**\n\t * Update all subscribed listeners with the latest awareness state.\n\t * @param forceUpdate - Whether to force an update.\n\t */\n\tprotected updateSubscribers( forceUpdate = false ): void {\n\t\tif ( ! this.stateSubscriptions.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst states = this.getStates();\n\n\t\tthis.seenStates = new Map< number, State >( [\n\t\t\t...this.seenStates.entries(),\n\t\t\t...states.entries(),\n\t\t] );\n\n\t\tconst updatedStates = new Map< number, EnhancedState< State > >(\n\t\t\t[ ...this.disconnectedCollaborators, ...states.keys() ]\n\t\t\t\t.filter( ( clientId ) => {\n\t\t\t\t\t// Exclude any collaborators with empty awareness state. This can happen from\n\t\t\t\t\t// the Yjs inspector.\n\t\t\t\t\treturn (\n\t\t\t\t\t\tObject.keys( this.seenStates.get( clientId ) ?? {} )\n\t\t\t\t\t\t\t.length > 0\n\t\t\t\t\t);\n\t\t\t\t} )\n\t\t\t\t.map( ( clientId ) => {\n\t\t\t\t\t// The filter above ensures that seenStates has the clientId.\n\t\t\t\t\tconst rawState: State = this.seenStates.get( clientId )!;\n\n\t\t\t\t\tconst isConnected =\n\t\t\t\t\t\t! this.disconnectedCollaborators.has( clientId );\n\t\t\t\t\tconst isMe = clientId === this.clientID;\n\t\t\t\t\tconst myState: Partial< State > = isMe\n\t\t\t\t\t\t? this.myThrottledState\n\t\t\t\t\t\t: {};\n\t\t\t\t\tconst state: EnhancedState< State > = {\n\t\t\t\t\t\t...rawState,\n\t\t\t\t\t\t...myState,\n\t\t\t\t\t\tclientId,\n\t\t\t\t\t\tisConnected,\n\t\t\t\t\t\tisMe,\n\t\t\t\t\t};\n\n\t\t\t\t\treturn [ clientId, state ];\n\t\t\t\t} )\n\t\t);\n\n\t\tif ( ! forceUpdate ) {\n\t\t\tif (\n\t\t\t\tareMapsEqual(\n\t\t\t\t\tthis.previousSnapshot,\n\t\t\t\t\tupdatedStates,\n\t\t\t\t\tthis.isStateEqual.bind( this )\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\t// Awareness state unchanged, do not update subscribers.\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Update subscribers.\n\t\tthis.previousSnapshot = updatedStates;\n\t\tthis.stateSubscriptions.forEach( ( callback ) => {\n\t\t\tcallback( Array.from( updatedStates.values() ) );\n\t\t} );\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/awareness/base-awareness.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import { resolveSelect } from '@wordpress/data';\nimport { AwarenessState } from './awareness-state';\nimport { STORE_NAME as coreStore } from '../name';\nimport { generateCollaboratorInfo, areCollaboratorInfosEqual } from './utils';\nimport type { BaseState } from './types';\n\nexport abstract class BaseAwarenessState<\n\tState extends BaseState,\n> extends AwarenessState< State > {\n\tprotected onSetUp(): void {\n\t\tvoid this.setCurrentCollaboratorInfo();\n\t}\n\n\t/**\n\t * Set the current collaborator info in the local state.\n\t */\n\tprivate async setCurrentCollaboratorInfo(): Promise< void > {\n\t\tconst currentUser = await resolveSelect( coreStore ).getCurrentUser();\n\t\tconst collaboratorInfo = generateCollaboratorInfo( currentUser );\n\t\tthis.setLocalStateField( 'collaboratorInfo', collaboratorInfo );\n\t}\n}\n\nexport const baseEqualityFieldChecks = {\n\tcollaboratorInfo: areCollaboratorInfosEqual,\n};\n\nexport class BaseAwareness extends BaseAwarenessState< BaseState > {\n\tprotected equalityFieldChecks = baseEqualityFieldChecks;\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,cAAc,iBAAiB;AACxC,SAAS,0BAA0B,iCAAiC;AAG7D,IAAe,qBAAf,cAEG,eAAwB;AAAA,EACvB,UAAgB;AACzB,SAAK,KAAK,2BAA2B;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,6BAA8C;AAC3D,UAAM,cAAc,MAAM,cAAe,SAAU,EAAE,eAAe;AACpE,UAAM,mBAAmB,yBAA0B,WAAY;AAC/D,SAAK,mBAAoB,oBAAoB,gBAAiB;AAAA,EAC/D;AACD;AAEO,IAAM,0BAA0B;AAAA,EACtC,kBAAkB;AACnB;AAEO,IAAM,gBAAN,cAA4B,mBAAgC;AAAA,EACxD,sBAAsB;AACjC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/awareness/block-lookup.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import { useSelect } from '@wordpress/data';\nimport { Y } from '@wordpress/sync';\n// @ts-expect-error `@wordpress/block-editor` does not expose type declarations for its entry point.\nimport { store as blockEditorStore } from '@wordpress/block-editor';\nimport type { AbsoluteBlockIndexPath } from '../types';\nimport { unlock } from '../lock-unlock';\n\n/**\n * A block as represented in the block-editor store's client ID tree.\n *\n * This is a minimal interface covering only the fields used by RTC awareness.\n */\nexport type EditorStoreBlock = {\n\tclientId: string;\n\tinnerBlocks: EditorStoreBlock[];\n};\n\n/**\n * Find the block Y.Map that contains a nested Yjs type.\n *\n * Rich-text attributes are often stored directly at attributes.content, but\n * blocks can also store rich text deeper inside object or array attributes.\n * Walk upward until we find the block map instead of assuming a fixed parent\n * depth.\n *\n * @param yType - The nested Yjs type to start from.\n * @return The containing block Y.Map, or null if no block ancestor exists.\n */\nexport function getContainingBlockYMap(\n\tyType: Y.AbstractType< any >\n): Y.Map< unknown > | null {\n\tlet current: Y.AbstractType< any > | null = yType;\n\n\twhile ( current ) {\n\t\tconst parent = current.parent;\n\n\t\tif (\n\t\t\tparent instanceof Y.Map &&\n\t\t\tparent.parent instanceof Y.Array &&\n\t\t\tparent.get( 'clientId' ) !== undefined &&\n\t\t\tparent.get( 'innerBlocks' ) instanceof Y.Array\n\t\t) {\n\t\t\treturn parent;\n\t\t}\n\n\t\tcurrent = parent instanceof Y.AbstractType ? parent : null;\n\t}\n\n\treturn null;\n}\n\n/**\n * Given a Y.Map within a Ydoc, traverse up the Yjs block tree to compute the\n * index path from the root.\n *\n * For example, the second inner block of the first root block returns [0, 1].\n *\n * @param yType - The Yjs block Y.Map to start from.\n * @return The index path from root, or null if traversal fails.\n */\nexport function getBlockPathInYdoc(\n\tyType: Y.Map< unknown >\n): AbsoluteBlockIndexPath | null {\n\tconst path: AbsoluteBlockIndexPath = [];\n\tlet current: Y.Map< unknown > = yType;\n\n\twhile ( current ) {\n\t\tconst parentArray = current.parent;\n\n\t\tif ( ! parentArray || ! ( parentArray instanceof Y.Array ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Find index of current block in its parent array.\n\t\tlet index = -1;\n\t\tfor ( let i = 0; i < parentArray.length; i++ ) {\n\t\t\tif ( parentArray.get( i ) === current ) {\n\t\t\t\tindex = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( index === -1 ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tpath.unshift( index );\n\n\t\t// Walk up: is the parent array's parent a block Y.Map or the root?\n\t\tconst grandparent = parentArray.parent;\n\t\tif (\n\t\t\tgrandparent instanceof Y.Map &&\n\t\t\tgrandparent.get( 'clientId' ) !== undefined\n\t\t) {\n\t\t\tcurrent = grandparent; // It's a block, keep going.\n\t\t} else {\n\t\t\tbreak; // It's the root map, done.\n\t\t}\n\t}\n\n\treturn path;\n}\n\n/**\n * Navigate the block-editor store's block tree by an index path\n * and return the local block's clientId.\n *\n * @param path - The index path, e.g. [0, 1] for blocks[0].innerBlocks[1].\n * @param blocks - The tree of block-editor store post contentblocks.\n * @return The local block clientId, or null if the path is invalid.\n */\nexport function resolveBlockClientIdByPath(\n\tpath: AbsoluteBlockIndexPath,\n\tblocks: EditorStoreBlock[]\n): string | null {\n\tif ( path.length === 0 ) {\n\t\treturn null;\n\t}\n\n\tfor ( let i = 0; i < path.length; i++ ) {\n\t\tconst block = blocks[ path[ i ] ];\n\t\tif ( ! block ) {\n\t\t\treturn null;\n\t\t}\n\t\tif ( i === path.length - 1 ) {\n\t\t\treturn block.clientId;\n\t\t}\n\t\tblocks = block.innerBlocks;\n\t}\n\treturn null;\n}\n\n/**\n * Find the post content blocks to use as the navigation root.\n *\n * In template mode, the block tree contains template parts wrapping a\n * core/post-content block. The Yjs document only stores the post content\n * blocks, so we need to find the core/post-content block and use\n * getClientIdsTree(clientId) to retrieve its inner blocks from the store.\n *\n * Uses the private getClientIdsTree selector which depends only on\n * state.blocks.order, avoiding unnecessary re-renders when block\n * attributes change (which would happen with getBlocks()).\n *\n * @return The blocks that correspond to the Yjs document root.\n */\nexport function usePostContentBlocks(): EditorStoreBlock[] {\n\treturn useSelect( ( select ) => {\n\t\tconst { getBlocksByName, getClientIdsTree } = unlock(\n\t\t\tselect( blockEditorStore )\n\t\t);\n\t\tconst [ postContentClientId ] = getBlocksByName( 'core/post-content' );\n\t\treturn getClientIdsTree( postContentClientId ?? '' );\n\t}, [] );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,iBAAiB;AAC1B,SAAS,SAAS;AAElB,SAAS,SAAS,wBAAwB;AAE1C,SAAS,cAAc;AAuBhB,SAAS,uBACf,OAC0B;AAC1B,MAAI,UAAwC;AAE5C,SAAQ,SAAU;AACjB,UAAM,SAAS,QAAQ;AAEvB,QACC,kBAAkB,EAAE,OACpB,OAAO,kBAAkB,EAAE,SAC3B,OAAO,IAAK,UAAW,MAAM,UAC7B,OAAO,IAAK,aAAc,aAAa,EAAE,OACxC;AACD,aAAO;AAAA,IACR;AAEA,cAAU,kBAAkB,EAAE,eAAe,SAAS;AAAA,EACvD;AAEA,SAAO;AACR;AAWO,SAAS,mBACf,OACgC;AAChC,QAAM,OAA+B,CAAC;AACtC,MAAI,UAA4B;AAEhC,SAAQ,SAAU;AACjB,UAAM,cAAc,QAAQ;AAE5B,QAAK,CAAE,eAAe,EAAI,uBAAuB,EAAE,QAAU;AAC5D,aAAO;AAAA,IACR;AAGA,QAAI,QAAQ;AACZ,aAAU,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAM;AAC9C,UAAK,YAAY,IAAK,CAAE,MAAM,SAAU;AACvC,gBAAQ;AACR;AAAA,MACD;AAAA,IACD;AAEA,QAAK,UAAU,IAAK;AACnB,aAAO;AAAA,IACR;AAEA,SAAK,QAAS,KAAM;AAGpB,UAAM,cAAc,YAAY;AAChC,QACC,uBAAuB,EAAE,OACzB,YAAY,IAAK,UAAW,MAAM,QACjC;AACD,gBAAU;AAAA,IACX,OAAO;AACN;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAUO,SAAS,2BACf,MACA,QACgB;AAChB,MAAK,KAAK,WAAW,GAAI;AACxB,WAAO;AAAA,EACR;AAEA,WAAU,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAM;AACvC,UAAM,QAAQ,OAAQ,KAAM,CAAE,CAAE;AAChC,QAAK,CAAE,OAAQ;AACd,aAAO;AAAA,IACR;AACA,QAAK,MAAM,KAAK,SAAS,GAAI;AAC5B,aAAO,MAAM;AAAA,IACd;AACA,aAAS,MAAM;AAAA,EAChB;AACA,SAAO;AACR;AAgBO,SAAS,uBAA2C;AAC1D,SAAO,UAAW,CAAE,WAAY;AAC/B,UAAM,EAAE,iBAAiB,iBAAiB,IAAI;AAAA,MAC7C,OAAQ,gBAAiB;AAAA,IAC1B;AACA,UAAM,CAAE,mBAAoB,IAAI,gBAAiB,mBAAoB;AACrE,WAAO,iBAAkB,uBAAuB,EAAG;AAAA,EACpD,GAAG,CAAC,CAAE;AACP;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -182,6 +182,13 @@ var PostEditorAwareness = class extends BaseAwarenessState {
|
|
|
182
182
|
attributeKey: null
|
|
183
183
|
};
|
|
184
184
|
}
|
|
185
|
+
if (selection.type === SelectionType.SelectionInMultipleBlocks) {
|
|
186
|
+
return {
|
|
187
|
+
richTextOffset: null,
|
|
188
|
+
localClientId: null,
|
|
189
|
+
attributeKey: null
|
|
190
|
+
};
|
|
191
|
+
}
|
|
185
192
|
const cursorPos = "cursorPosition" in selection ? selection.cursorPosition : selection.cursorStartPosition;
|
|
186
193
|
const absolutePosition = Y.createAbsolutePositionFromRelativePosition(
|
|
187
194
|
cursorPos.relativePosition,
|
|
@@ -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 {\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 { EditorStoreBlock } from './block-lookup';\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 * @param blocks - The tree of block-editor store post content blocks.\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\tblocks: EditorStoreBlock[]\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, blocks )\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\n\t\t\t? resolveBlockClientIdByPath( path, blocks )\n\t\t\t: 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": ";
|
|
4
|
+
"sourcesContent": ["import { dispatch, select, subscribe } from '@wordpress/data';\nimport { Y } from '@wordpress/sync';\n// @ts-expect-error `@wordpress/block-editor` does not expose type declarations for its entry point.\nimport { store as blockEditorStore } from '@wordpress/block-editor';\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';\nimport type {\n\tResolvedSelection,\n\tSelectionState,\n\tWPBlockSelection,\n} from '../types';\nimport type { YBlocks } from '../utils/crdt-blocks';\nimport type { EditorStoreBlock } from './block-lookup';\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-expect-error Types are not provided when using the store name instead of the 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 * @param blocks - The tree of block-editor store post content blocks.\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\tblocks: EditorStoreBlock[]\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, blocks )\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// SelectionInMultipleBlocks is decomposed by the caller into per-endpoint\n\t\t// Cursor / WholeBlock calls and should never arrive here directly.\n\t\tif ( selection.type === SelectionType.SelectionInMultipleBlocks ) {\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\t// Text-based selections: resolve cursor position and navigate up.\n\t\t// SelectionCursor → cursorPosition; SelectionInOneBlock → cursorStartPosition.\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\n\t\t\t? resolveBlockClientIdByPath( path, blocks )\n\t\t\t: 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
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/awareness/typed-awareness.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import { Awareness } from '@wordpress/sync';\nimport { getRecordValue } from './utils';\n\n/**\n * Extended Awareness class with typed state accessors.\n */\nexport class TypedAwareness< State extends object > extends Awareness {\n\t/**\n\t * Get the states from an awareness document.\n\t */\n\tpublic getStates(): Map< number, State > {\n\t\treturn super.getStates() as Map< number, State >;\n\t}\n\n\t/**\n\t * Get a local state field from an awareness document.\n\t * @param field\n\t */\n\tpublic getLocalStateField< FieldName extends keyof State >(\n\t\tfield: FieldName\n\t): State[ FieldName ] | null {\n\t\tconst state: State | null = this.getLocalState() as State | null;\n\t\treturn getRecordValue< State, FieldName >( state, field );\n\t}\n\n\t/**\n\t * Set a local state field on an awareness document.\n\t * @param field\n\t * @param value\n\t */\n\tpublic setLocalStateField< FieldName extends string & keyof State >(\n\t\tfield: FieldName,\n\t\tvalue: State[ FieldName ]\n\t): void {\n\t\tsuper.setLocalStateField( field, value );\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAKxB,IAAM,iBAAN,cAAqD,UAAU;AAAA;AAAA;AAAA;AAAA,EAI9D,YAAkC;AACxC,WAAO,MAAM,UAAU;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,mBACN,OAC4B;AAC5B,UAAM,QAAsB,KAAK,cAAc;AAC/C,WAAO,eAAoC,OAAO,KAAM;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,mBACN,OACA,OACO;AACP,UAAM,mBAAoB,OAAO,KAAM;AAAA,EACxC;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/awareness/utils.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import type { User } from '../entity-types';\nimport type { CollaboratorInfo } from './types';\n\n/**\n * Get the browser name from the user agent.\n * @return The browser name.\n */\nfunction getBrowserName(): string {\n\tconst userAgent = window.navigator.userAgent;\n\tlet browserName = 'Unknown';\n\n\tif ( userAgent.includes( 'Firefox' ) ) {\n\t\tbrowserName = 'Firefox';\n\t} else if ( userAgent.includes( 'Edg' ) ) {\n\t\tbrowserName = 'Microsoft Edge';\n\t} else if (\n\t\tuserAgent.includes( 'Chrome' ) &&\n\t\t! userAgent.includes( 'Edg' )\n\t) {\n\t\tbrowserName = 'Chrome';\n\t} else if (\n\t\tuserAgent.includes( 'Safari' ) &&\n\t\t! userAgent.includes( 'Chrome' )\n\t) {\n\t\tbrowserName = 'Safari';\n\t} else if (\n\t\tuserAgent.includes( 'MSIE' ) ||\n\t\tuserAgent.includes( 'Trident' )\n\t) {\n\t\tbrowserName = 'Internet Explorer';\n\t} else if ( userAgent.includes( 'Opera' ) || userAgent.includes( 'OPR' ) ) {\n\t\tbrowserName = 'Opera';\n\t}\n\n\treturn browserName;\n}\n\nexport function areMapsEqual< Key, Value >(\n\tmap1: Map< Key, Value >,\n\tmap2: Map< Key, Value >,\n\tcomparatorFn: ( value1: Value, value2: Value ) => boolean\n): boolean {\n\tif ( map1.size !== map2.size ) {\n\t\treturn false;\n\t}\n\n\tfor ( const [ key, value1 ] of map1.entries() ) {\n\t\tif ( ! map2.has( key ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( ! comparatorFn( value1, map2.get( key )! ) ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Check if two collaborator infos are equal.\n *\n * @param collaboratorInfo1 - The first collaborator info.\n * @param collaboratorInfo2 - The second collaborator info.\n * @return True if the collaborator infos are equal, false otherwise.\n */\nexport function areCollaboratorInfosEqual(\n\tcollaboratorInfo1?: CollaboratorInfo,\n\tcollaboratorInfo2?: CollaboratorInfo\n): boolean {\n\tif ( ! collaboratorInfo1 || ! collaboratorInfo2 ) {\n\t\treturn collaboratorInfo1 === collaboratorInfo2;\n\t}\n\n\tif (\n\t\tObject.keys( collaboratorInfo1 ).length !==\n\t\tObject.keys( collaboratorInfo2 ).length\n\t) {\n\t\treturn false;\n\t}\n\n\treturn Object.entries( collaboratorInfo1 ).every( ( [ key, value ] ) => {\n\t\t// Update this function with any non-primitive fields added to CollaboratorInfo.\n\t\treturn value === collaboratorInfo2[ key as keyof CollaboratorInfo ];\n\t} );\n}\n\n/**\n * Generate a collaborator info object from a current collaborator.\n *\n * @param currentCollaborator - The current collaborator.\n * @return The collaborator info object.\n */\nexport function generateCollaboratorInfo(\n\tcurrentCollaborator: User< 'view' >\n): CollaboratorInfo {\n\t// eslint-disable-next-line camelcase\n\tconst { avatar_urls, id, name, slug } = currentCollaborator;\n\treturn {\n\t\tavatar_urls, // eslint-disable-line camelcase\n\t\tbrowserType: getBrowserName(),\n\t\tenteredAt: Date.now(),\n\t\tid,\n\t\tname,\n\t\tslug,\n\t};\n}\n\nexport function getRecordValue< RecordType, Key extends keyof RecordType >(\n\tobj: unknown,\n\tkey: Key\n): RecordType[ Key ] | null {\n\tif ( 'object' === typeof obj && null !== obj && key in obj ) {\n\t\treturn ( obj as RecordType )[ key ];\n\t}\n\n\treturn null;\n}\n\nexport function getTypedKeys< T extends object >( obj: T ): Array< keyof T > {\n\treturn Object.keys( obj ) as Array< keyof T >;\n}\n"],
|
|
5
|
+
"mappings": ";AAOA,SAAS,iBAAyB;AACjC,QAAM,YAAY,OAAO,UAAU;AACnC,MAAI,cAAc;AAElB,MAAK,UAAU,SAAU,SAAU,GAAI;AACtC,kBAAc;AAAA,EACf,WAAY,UAAU,SAAU,KAAM,GAAI;AACzC,kBAAc;AAAA,EACf,WACC,UAAU,SAAU,QAAS,KAC7B,CAAE,UAAU,SAAU,KAAM,GAC3B;AACD,kBAAc;AAAA,EACf,WACC,UAAU,SAAU,QAAS,KAC7B,CAAE,UAAU,SAAU,QAAS,GAC9B;AACD,kBAAc;AAAA,EACf,WACC,UAAU,SAAU,MAAO,KAC3B,UAAU,SAAU,SAAU,GAC7B;AACD,kBAAc;AAAA,EACf,WAAY,UAAU,SAAU,OAAQ,KAAK,UAAU,SAAU,KAAM,GAAI;AAC1E,kBAAc;AAAA,EACf;AAEA,SAAO;AACR;AAEO,SAAS,aACf,MACA,MACA,cACU;AACV,MAAK,KAAK,SAAS,KAAK,MAAO;AAC9B,WAAO;AAAA,EACR;AAEA,aAAY,CAAE,KAAK,MAAO,KAAK,KAAK,QAAQ,GAAI;AAC/C,QAAK,CAAE,KAAK,IAAK,GAAI,GAAI;AACxB,aAAO;AAAA,IACR;AAEA,QAAK,CAAE,aAAc,QAAQ,KAAK,IAAK,GAAI,CAAG,GAAI;AACjD,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AASO,SAAS,0BACf,mBACA,mBACU;AACV,MAAK,CAAE,qBAAqB,CAAE,mBAAoB;AACjD,WAAO,sBAAsB;AAAA,EAC9B;AAEA,MACC,OAAO,KAAM,iBAAkB,EAAE,WACjC,OAAO,KAAM,iBAAkB,EAAE,QAChC;AACD,WAAO;AAAA,EACR;AAEA,SAAO,OAAO,QAAS,iBAAkB,EAAE,MAAO,CAAE,CAAE,KAAK,KAAM,MAAO;AAEvE,WAAO,UAAU,kBAAmB,GAA8B;AAAA,EACnE,CAAE;AACH;AAQO,SAAS,yBACf,qBACmB;AAEnB,QAAM,EAAE,aAAa,IAAI,MAAM,KAAK,IAAI;AACxC,SAAO;AAAA,IACN;AAAA;AAAA,IACA,aAAa,eAAe;AAAA,IAC5B,WAAW,KAAK,IAAI;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAEO,SAAS,eACf,KACA,KAC2B;AAC3B,MAAK,aAAa,OAAO,OAAO,SAAS,OAAO,OAAO,KAAM;AAC5D,WAAS,IAAqB,GAAI;AAAA,EACnC;AAEA,SAAO;AACR;AAEO,SAAS,aAAkC,KAA2B;AAC5E,SAAO,OAAO,KAAM,GAAI;AACzB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/batch/create-batch.js"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import defaultProcessor from './default-processor';\n\n/**\n * Creates a batch, which can be used to combine multiple API requests into one\n * API request using the WordPress batch processing API (/v1/batch).\n *\n * ```\n * const batch = createBatch();\n * const dunePromise = batch.add( {\n * path: '/v1/books',\n * method: 'POST',\n * data: { title: 'Dune' }\n * } );\n * const lotrPromise = batch.add( {\n * path: '/v1/books',\n * method: 'POST',\n * data: { title: 'Lord of the Rings' }\n * } );\n * const isSuccess = await batch.run(); // Sends one POST to /v1/batch.\n * if ( isSuccess ) {\n * console.log(\n * 'Saved two books:',\n * await dunePromise,\n * await lotrPromise\n * );\n * }\n * ```\n *\n * @param {Function} [processor] Processor function. Can be used to replace the\n * default functionality which is to send an API\n * request to /v1/batch. Is given an array of\n * inputs and must return a promise that\n * resolves to an array of objects containing\n * either `output` or `error`.\n */\nexport default function createBatch( processor = defaultProcessor ) {\n\tlet lastId = 0;\n\t/** @type {Array<{ input: any; resolve: ( value: any ) => void; reject: ( error: any ) => void }>} */\n\tlet queue = [];\n\tconst pending = new ObservableSet();\n\n\treturn {\n\t\t/**\n\t\t * Adds an input to the batch and returns a promise that is resolved or\n\t\t * rejected when the input is processed by `batch.run()`.\n\t\t *\n\t\t * You may also pass a thunk which allows inputs to be added\n\t\t * asynchronously.\n\t\t *\n\t\t * ```\n\t\t * // Both are allowed:\n\t\t * batch.add( { path: '/v1/books', ... } );\n\t\t * batch.add( ( add ) => add( { path: '/v1/books', ... } ) );\n\t\t * ```\n\t\t *\n\t\t * If a thunk is passed, `batch.run()` will pause until either:\n\t\t *\n\t\t * - The thunk calls its `add` argument, or;\n\t\t * - The thunk returns a promise and that promise resolves, or;\n\t\t * - The thunk returns a non-promise.\n\t\t *\n\t\t * @param {any|Function} inputOrThunk Input to add or thunk to execute.\n\t\t *\n\t\t * @return {Promise|any} If given an input, returns a promise that\n\t\t * is resolved or rejected when the batch is\n\t\t * processed. If given a thunk, returns the return\n\t\t * value of that thunk.\n\t\t */\n\t\tadd( inputOrThunk ) {\n\t\t\tconst id = ++lastId;\n\t\t\tpending.add( id );\n\n\t\t\tconst add = ( input ) =>\n\t\t\t\tnew Promise( ( resolve, reject ) => {\n\t\t\t\t\tqueue.push( {\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\tresolve,\n\t\t\t\t\t\treject,\n\t\t\t\t\t} );\n\t\t\t\t\tpending.delete( id );\n\t\t\t\t} );\n\n\t\t\tif ( typeof inputOrThunk === 'function' ) {\n\t\t\t\treturn Promise.resolve( inputOrThunk( add ) ).finally( () => {\n\t\t\t\t\tpending.delete( id );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn add( inputOrThunk );\n\t\t},\n\n\t\t/**\n\t\t * Runs the batch. This calls `batchProcessor` and resolves or rejects\n\t\t * all promises returned by `add()`.\n\t\t *\n\t\t * @return {Promise<boolean>} A promise that resolves to a boolean that is true\n\t\t * if the processor returned no errors.\n\t\t */\n\t\tasync run() {\n\t\t\tif ( pending.size ) {\n\t\t\t\tawait new Promise( ( resolve ) => {\n\t\t\t\t\tconst unsubscribe = pending.subscribe( () => {\n\t\t\t\t\t\tif ( ! pending.size ) {\n\t\t\t\t\t\t\tunsubscribe();\n\t\t\t\t\t\t\tresolve( undefined );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tlet results;\n\n\t\t\ttry {\n\t\t\t\tresults = await processor(\n\t\t\t\t\tqueue.map( ( { input } ) => input )\n\t\t\t\t);\n\n\t\t\t\tif ( results.length !== queue.length ) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'run: Array returned by processor must be same size as input array.'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch ( error ) {\n\t\t\t\tfor ( const { reject } of queue ) {\n\t\t\t\t\treject( error );\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tlet isSuccess = true;\n\n\t\t\tresults.forEach( ( result, key ) => {\n\t\t\t\tconst queueItem = queue[ key ];\n\n\t\t\t\tif ( result?.error ) {\n\t\t\t\t\tqueueItem?.reject( result.error );\n\t\t\t\t\tisSuccess = false;\n\t\t\t\t} else {\n\t\t\t\t\tqueueItem?.resolve( result?.output ?? result );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tqueue = [];\n\n\t\t\treturn isSuccess;\n\t\t},\n\t};\n}\n\nclass ObservableSet {\n\tconstructor( ...args ) {\n\t\tthis.set = new Set( ...args );\n\t\tthis.subscribers = new Set();\n\t}\n\n\tget size() {\n\t\treturn this.set.size;\n\t}\n\n\tadd( value ) {\n\t\tthis.set.add( value );\n\t\tthis.subscribers.forEach( ( subscriber ) => subscriber() );\n\t\treturn this;\n\t}\n\n\tdelete( value ) {\n\t\tconst isSuccess = this.set.delete( value );\n\t\tthis.subscribers.forEach( ( subscriber ) => subscriber() );\n\t\treturn isSuccess;\n\t}\n\n\tsubscribe( subscriber ) {\n\t\tthis.subscribers.add( subscriber );\n\t\treturn () => {\n\t\t\tthis.subscribers.delete( subscriber );\n\t\t};\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,OAAO,sBAAsB;AAmCd,SAAR,YAA8B,YAAY,kBAAmB;AACnE,MAAI,SAAS;AAEb,MAAI,QAAQ,CAAC;AACb,QAAM,UAAU,IAAI,cAAc;AAElC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA2BN,IAAK,cAAe;AACnB,YAAM,KAAK,EAAE;AACb,cAAQ,IAAK,EAAG;AAEhB,YAAM,MAAM,CAAE,UACb,IAAI,QAAS,CAAE,SAAS,WAAY;AACnC,cAAM,KAAM;AAAA,UACX;AAAA,UACA;AAAA,UACA;AAAA,QACD,CAAE;AACF,gBAAQ,OAAQ,EAAG;AAAA,MACpB,CAAE;AAEH,UAAK,OAAO,iBAAiB,YAAa;AACzC,eAAO,QAAQ,QAAS,aAAc,GAAI,CAAE,EAAE,QAAS,MAAM;AAC5D,kBAAQ,OAAQ,EAAG;AAAA,QACpB,CAAE;AAAA,MACH;AAEA,aAAO,IAAK,YAAa;AAAA,IAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,MAAM,MAAM;AACX,UAAK,QAAQ,MAAO;AACnB,cAAM,IAAI,QAAS,CAAE,YAAa;AACjC,gBAAM,cAAc,QAAQ,UAAW,MAAM;AAC5C,gBAAK,CAAE,QAAQ,MAAO;AACrB,0BAAY;AACZ,sBAAS,MAAU;AAAA,YACpB;AAAA,UACD,CAAE;AAAA,QACH,CAAE;AAAA,MACH;AAEA,UAAI;AAEJ,UAAI;AACH,kBAAU,MAAM;AAAA,UACf,MAAM,IAAK,CAAE,EAAE,MAAM,MAAO,KAAM;AAAA,QACnC;AAEA,YAAK,QAAQ,WAAW,MAAM,QAAS;AACtC,gBAAM,IAAI;AAAA,YACT;AAAA,UACD;AAAA,QACD;AAAA,MACD,SAAU,OAAQ;AACjB,mBAAY,EAAE,OAAO,KAAK,OAAQ;AACjC,iBAAQ,KAAM;AAAA,QACf;AAEA,cAAM;AAAA,MACP;AAEA,UAAI,YAAY;AAEhB,cAAQ,QAAS,CAAE,QAAQ,QAAS;AACnC,cAAM,YAAY,MAAO,GAAI;AAE7B,YAAK,QAAQ,OAAQ;AACpB,qBAAW,OAAQ,OAAO,KAAM;AAChC,sBAAY;AAAA,QACb,OAAO;AACN,qBAAW,QAAS,QAAQ,UAAU,MAAO;AAAA,QAC9C;AAAA,MACD,CAAE;AAEF,cAAQ,CAAC;AAET,aAAO;AAAA,IACR;AAAA,EACD;AACD;AAEA,IAAM,gBAAN,MAAoB;AAAA,EACnB,eAAgB,MAAO;AACtB,SAAK,MAAM,IAAI,IAAK,GAAG,IAAK;AAC5B,SAAK,cAAc,oBAAI,IAAI;AAAA,EAC5B;AAAA,EAEA,IAAI,OAAO;AACV,WAAO,KAAK,IAAI;AAAA,EACjB;AAAA,EAEA,IAAK,OAAQ;AACZ,SAAK,IAAI,IAAK,KAAM;AACpB,SAAK,YAAY,QAAS,CAAE,eAAgB,WAAW,CAAE;AACzD,WAAO;AAAA,EACR;AAAA,EAEA,OAAQ,OAAQ;AACf,UAAM,YAAY,KAAK,IAAI,OAAQ,KAAM;AACzC,SAAK,YAAY,QAAS,CAAE,eAAgB,WAAW,CAAE;AACzD,WAAO;AAAA,EACR;AAAA,EAEA,UAAW,YAAa;AACvB,SAAK,YAAY,IAAK,UAAW;AACjC,WAAO,MAAM;AACZ,WAAK,YAAY,OAAQ,UAAW;AAAA,IACrC;AAAA,EACD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/batch/default-processor.js"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import apiFetch from '@wordpress/api-fetch';\n\n/**\n * Maximum number of requests to place in a single batch request. Obtained by\n * sending a preflight OPTIONS request to /batch/v1/.\n *\n * @type {number?}\n */\nlet maxItems = null;\n\nfunction chunk( arr, chunkSize ) {\n\tconst tmp = [ ...arr ];\n\tconst cache = [];\n\twhile ( tmp.length ) {\n\t\tcache.push( tmp.splice( 0, chunkSize ) );\n\t}\n\n\treturn cache;\n}\n\n/**\n * Default batch processor. Sends its input requests to /batch/v1.\n *\n * @param {Array} requests List of API requests to perform at once.\n *\n * @return {Promise} Promise that resolves to a list of objects containing\n * either `output` (if that request was successful) or `error`\n * (if not ).\n */\nexport default async function defaultProcessor( requests ) {\n\tif ( maxItems === null ) {\n\t\tconst preflightResponse = await apiFetch( {\n\t\t\tpath: '/batch/v1',\n\t\t\tmethod: 'OPTIONS',\n\t\t} );\n\t\tmaxItems = preflightResponse.endpoints[ 0 ].args.requests.maxItems;\n\t}\n\n\tconst results = [];\n\n\tfor ( const batchRequests of chunk( requests, maxItems ) ) {\n\t\tconst batchResponse = await apiFetch( {\n\t\t\tpath: '/batch/v1',\n\t\t\tmethod: 'POST',\n\t\t\tdata: {\n\t\t\t\tvalidation: 'require-all-validate',\n\t\t\t\trequests: batchRequests.map( ( request ) => ( {\n\t\t\t\t\tpath: request.path,\n\t\t\t\t\tbody: request.data, // Rename 'data' to 'body'.\n\t\t\t\t\tmethod: request.method,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t} ) ),\n\t\t\t},\n\t\t} );\n\n\t\tlet batchResults;\n\n\t\tif ( batchResponse.failed ) {\n\t\t\tbatchResults = batchResponse.responses.map( ( response ) => ( {\n\t\t\t\terror: response?.body,\n\t\t\t} ) );\n\t\t} else {\n\t\t\tbatchResults = batchResponse.responses.map( ( response ) => {\n\t\t\t\tconst result = {};\n\t\t\t\tif ( response.status >= 200 && response.status < 300 ) {\n\t\t\t\t\tresult.output = response.body;\n\t\t\t\t} else {\n\t\t\t\t\tresult.error = response.body;\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t} );\n\t\t}\n\n\t\tresults.push( ...batchResults );\n\t}\n\n\treturn results;\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,OAAO,cAAc;AAQrB,IAAI,WAAW;AAEf,SAAS,MAAO,KAAK,WAAY;AAChC,QAAM,MAAM,CAAE,GAAG,GAAI;AACrB,QAAM,QAAQ,CAAC;AACf,SAAQ,IAAI,QAAS;AACpB,UAAM,KAAM,IAAI,OAAQ,GAAG,SAAU,CAAE;AAAA,EACxC;AAEA,SAAO;AACR;AAWA,eAAO,iBAAyC,UAAW;AAC1D,MAAK,aAAa,MAAO;AACxB,UAAM,oBAAoB,MAAM,SAAU;AAAA,MACzC,MAAM;AAAA,MACN,QAAQ;AAAA,IACT,CAAE;AACF,eAAW,kBAAkB,UAAW,CAAE,EAAE,KAAK,SAAS;AAAA,EAC3D;AAEA,QAAM,UAAU,CAAC;AAEjB,aAAY,iBAAiB,MAAO,UAAU,QAAS,GAAI;AAC1D,UAAM,gBAAgB,MAAM,SAAU;AAAA,MACrC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,MAAM;AAAA,QACL,YAAY;AAAA,QACZ,UAAU,cAAc,IAAK,CAAE,aAAe;AAAA,UAC7C,MAAM,QAAQ;AAAA,UACd,MAAM,QAAQ;AAAA;AAAA,UACd,QAAQ,QAAQ;AAAA,UAChB,SAAS,QAAQ;AAAA,QAClB,EAAI;AAAA,MACL;AAAA,IACD,CAAE;AAEF,QAAI;AAEJ,QAAK,cAAc,QAAS;AAC3B,qBAAe,cAAc,UAAU,IAAK,CAAE,cAAgB;AAAA,QAC7D,OAAO,UAAU;AAAA,MAClB,EAAI;AAAA,IACL,OAAO;AACN,qBAAe,cAAc,UAAU,IAAK,CAAE,aAAc;AAC3D,cAAM,SAAS,CAAC;AAChB,YAAK,SAAS,UAAU,OAAO,SAAS,SAAS,KAAM;AACtD,iBAAO,SAAS,SAAS;AAAA,QAC1B,OAAO;AACN,iBAAO,QAAQ,SAAS;AAAA,QACzB;AACA,eAAO;AAAA,MACR,CAAE;AAAA,IACH;AAEA,YAAQ,KAAM,GAAG,YAAa;AAAA,EAC/B;AAEA,SAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/entities-saved-states/entity-record-item.js"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import { CheckboxControl, PanelRow } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\nimport { useSelect } from '@wordpress/data';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { STORE_NAME } from '../../name';\nimport { getTemplateInfo } from '../../utils/get-template-info';\n\nexport default function EntityRecordItem( { record, checked, onChange } ) {\n\tconst { name, kind, title, key } = record;\n\n\t// Handle templates that might use default descriptive titles.\n\tconst { entityRecordTitle } = useSelect(\n\t\t( select ) => {\n\t\t\tif ( 'postType' !== kind || 'wp_template' !== name ) {\n\t\t\t\treturn {\n\t\t\t\t\tentityRecordTitle: title,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst template = select( STORE_NAME ).getEditedEntityRecord(\n\t\t\t\tkind,\n\t\t\t\tname,\n\t\t\t\tkey\n\t\t\t);\n\n\t\t\tconst { default_template_types: templateTypes = [] } =\n\t\t\t\tselect( STORE_NAME ).getCurrentTheme() ?? {};\n\n\t\t\treturn {\n\t\t\t\tentityRecordTitle: getTemplateInfo( {\n\t\t\t\t\ttemplate,\n\t\t\t\t\ttemplateTypes,\n\t\t\t\t} ).title,\n\t\t\t};\n\t\t},\n\t\t[ name, kind, title, key ]\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t<PanelRow>\n\t\t\t\t<CheckboxControl\n\t\t\t\t\tlabel={\n\t\t\t\t\t\tdecodeEntities( entityRecordTitle ) || __( 'Untitled' )\n\t\t\t\t\t}\n\t\t\t\t\tchecked={ checked }\n\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\tclassName=\"entities-saved-states__change-control\"\n\t\t\t\t/>\n\t\t\t</PanelRow>\n\t\t</>\n\t);\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,iBAAiB,gBAAgB;AAC1C,SAAS,UAAU;AACnB,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAkC9B,mBAEE,WAFF;AAhCa,SAAR,iBAAmC,EAAE,QAAQ,SAAS,SAAS,GAAI;AACzE,QAAM,EAAE,MAAM,MAAM,OAAO,IAAI,IAAI;AAGnC,QAAM,EAAE,kBAAkB,IAAI;AAAA,IAC7B,CAAE,WAAY;AACb,UAAK,eAAe,QAAQ,kBAAkB,MAAO;AACpD,eAAO;AAAA,UACN,mBAAmB;AAAA,QACpB;AAAA,MACD;AAEA,YAAM,WAAW,OAAQ,UAAW,EAAE;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAEA,YAAM,EAAE,wBAAwB,gBAAgB,CAAC,EAAE,IAClD,OAAQ,UAAW,EAAE,gBAAgB,KAAK,CAAC;AAE5C,aAAO;AAAA,QACN,mBAAmB,gBAAiB;AAAA,UACnC;AAAA,UACA;AAAA,QACD,CAAE,EAAE;AAAA,MACL;AAAA,IACD;AAAA,IACA,CAAE,MAAM,MAAM,OAAO,GAAI;AAAA,EAC1B;AAEA,SACC,gCACC,8BAAC,YACA;AAAA,IAAC;AAAA;AAAA,MACA,OACC,eAAgB,iBAAkB,KAAK,GAAI,UAAW;AAAA,MAEvD;AAAA,MACA;AAAA,MACA,WAAU;AAAA;AAAA,EACX,GACD,GACD;AAEF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/entities-saved-states/entity-type-list.js"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import { __ } from '@wordpress/i18n';\nimport { useSelect } from '@wordpress/data';\nimport { PanelBody, PanelRow } from '@wordpress/components';\nimport { getGlobalStylesChanges } from '@wordpress/global-styles-engine';\nimport EntityRecordItem from './entity-record-item';\nimport { STORE_NAME } from '../../name';\n\nfunction getEntityDescription( entity, count ) {\n\tswitch ( entity ) {\n\t\tcase 'site':\n\t\t\treturn 1 === count\n\t\t\t\t? __( 'This change will affect your whole site.' )\n\t\t\t\t: __( 'These changes will affect your whole site.' );\n\t\tcase 'wp_template':\n\t\t\treturn __(\n\t\t\t\t'This change will affect other parts of your site that use this template.'\n\t\t\t);\n\t\tcase 'page':\n\t\tcase 'post':\n\t\t\treturn __( 'The following has been modified.' );\n\t}\n}\n\nfunction GlobalStylesDescription( { record } ) {\n\tconst { editedRecord, savedRecord } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getEditedEntityRecord, getEntityRecord } =\n\t\t\t\tselect( STORE_NAME );\n\t\t\treturn {\n\t\t\t\teditedRecord: getEditedEntityRecord(\n\t\t\t\t\trecord.kind,\n\t\t\t\t\trecord.name,\n\t\t\t\t\trecord.key\n\t\t\t\t),\n\t\t\t\tsavedRecord: getEntityRecord(\n\t\t\t\t\trecord.kind,\n\t\t\t\t\trecord.name,\n\t\t\t\t\trecord.key\n\t\t\t\t),\n\t\t\t};\n\t\t},\n\t\t[ record.kind, record.name, record.key ]\n\t);\n\n\tconst globalStylesChanges = getGlobalStylesChanges(\n\t\teditedRecord,\n\t\tsavedRecord,\n\t\t{\n\t\t\tmaxResults: 10,\n\t\t}\n\t);\n\treturn globalStylesChanges.length ? (\n\t\t<ul className=\"entities-saved-states__changes\">\n\t\t\t{ globalStylesChanges.map( ( change ) => (\n\t\t\t\t<li key={ change }>{ change }</li>\n\t\t\t) ) }\n\t\t</ul>\n\t) : null;\n}\n\nfunction EntityDescription( { record, count } ) {\n\tif ( 'globalStyles' === record?.name ) {\n\t\treturn null;\n\t}\n\tconst description = getEntityDescription( record?.name, count );\n\treturn description ? <PanelRow>{ description }</PanelRow> : null;\n}\n\nexport default function EntityTypeList( {\n\tlist,\n\tunselectedEntities,\n\tsetUnselectedEntities,\n} ) {\n\tconst count = list.length;\n\tconst firstRecord = list[ 0 ];\n\tconst entityConfig = useSelect(\n\t\t( select ) =>\n\t\t\tselect( STORE_NAME ).getEntityConfig(\n\t\t\t\tfirstRecord.kind,\n\t\t\t\tfirstRecord.name\n\t\t\t),\n\t\t[ firstRecord.kind, firstRecord.name ]\n\t);\n\n\tlet entityLabel = entityConfig.label;\n\tif ( firstRecord?.name === 'wp_template_part' ) {\n\t\tentityLabel =\n\t\t\t1 === count ? __( 'Template Part' ) : __( 'Template Parts' );\n\t}\n\n\treturn (\n\t\t<PanelBody\n\t\t\ttitle={ entityLabel }\n\t\t\tinitialOpen\n\t\t\tclassName=\"entities-saved-states__panel-body\"\n\t\t>\n\t\t\t<EntityDescription record={ firstRecord } count={ count } />\n\t\t\t{ list.map( ( record ) => {\n\t\t\t\treturn (\n\t\t\t\t\t<EntityRecordItem\n\t\t\t\t\t\tkey={ record.key || record.property }\n\t\t\t\t\t\trecord={ record }\n\t\t\t\t\t\tchecked={\n\t\t\t\t\t\t\t! unselectedEntities.some(\n\t\t\t\t\t\t\t\t( elt ) =>\n\t\t\t\t\t\t\t\t\telt.kind === record.kind &&\n\t\t\t\t\t\t\t\t\telt.name === record.name &&\n\t\t\t\t\t\t\t\t\telt.key === record.key &&\n\t\t\t\t\t\t\t\t\telt.property === record.property\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonChange={ ( value ) =>\n\t\t\t\t\t\t\tsetUnselectedEntities( record, value )\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t} ) }\n\t\t\t{ 'globalStyles' === firstRecord?.name && (\n\t\t\t\t<GlobalStylesDescription record={ firstRecord } />\n\t\t\t) }\n\t\t</PanelBody>\n\t);\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,UAAU;AACnB,SAAS,iBAAiB;AAC1B,SAAS,WAAW,gBAAgB;AACpC,SAAS,8BAA8B;AACvC,OAAO,sBAAsB;AAC7B,SAAS,kBAAkB;AAiDvB,cAqCF,YArCE;AA/CJ,SAAS,qBAAsB,QAAQ,OAAQ;AAC9C,UAAS,QAAS;AAAA,IACjB,KAAK;AACJ,aAAO,MAAM,QACV,GAAI,0CAA2C,IAC/C,GAAI,4CAA6C;AAAA,IACrD,KAAK;AACJ,aAAO;AAAA,QACN;AAAA,MACD;AAAA,IACD,KAAK;AAAA,IACL,KAAK;AACJ,aAAO,GAAI,kCAAmC;AAAA,EAChD;AACD;AAEA,SAAS,wBAAyB,EAAE,OAAO,GAAI;AAC9C,QAAM,EAAE,cAAc,YAAY,IAAI;AAAA,IACrC,CAAE,WAAY;AACb,YAAM,EAAE,uBAAuB,gBAAgB,IAC9C,OAAQ,UAAW;AACpB,aAAO;AAAA,QACN,cAAc;AAAA,UACb,OAAO;AAAA,UACP,OAAO;AAAA,UACP,OAAO;AAAA,QACR;AAAA,QACA,aAAa;AAAA,UACZ,OAAO;AAAA,UACP,OAAO;AAAA,UACP,OAAO;AAAA,QACR;AAAA,MACD;AAAA,IACD;AAAA,IACA,CAAE,OAAO,MAAM,OAAO,MAAM,OAAO,GAAI;AAAA,EACxC;AAEA,QAAM,sBAAsB;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,MACC,YAAY;AAAA,IACb;AAAA,EACD;AACA,SAAO,oBAAoB,SAC1B,oBAAC,QAAG,WAAU,kCACX,8BAAoB,IAAK,CAAE,WAC5B,oBAAC,QAAoB,oBAAX,MAAmB,CAC5B,GACH,IACG;AACL;AAEA,SAAS,kBAAmB,EAAE,QAAQ,MAAM,GAAI;AAC/C,MAAK,mBAAmB,QAAQ,MAAO;AACtC,WAAO;AAAA,EACR;AACA,QAAM,cAAc,qBAAsB,QAAQ,MAAM,KAAM;AAC9D,SAAO,cAAc,oBAAC,YAAW,uBAAa,IAAc;AAC7D;AAEe,SAAR,eAAiC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AACD,GAAI;AACH,QAAM,QAAQ,KAAK;AACnB,QAAM,cAAc,KAAM,CAAE;AAC5B,QAAM,eAAe;AAAA,IACpB,CAAE,WACD,OAAQ,UAAW,EAAE;AAAA,MACpB,YAAY;AAAA,MACZ,YAAY;AAAA,IACb;AAAA,IACD,CAAE,YAAY,MAAM,YAAY,IAAK;AAAA,EACtC;AAEA,MAAI,cAAc,aAAa;AAC/B,MAAK,aAAa,SAAS,oBAAqB;AAC/C,kBACC,MAAM,QAAQ,GAAI,eAAgB,IAAI,GAAI,gBAAiB;AAAA,EAC7D;AAEA,SACC;AAAA,IAAC;AAAA;AAAA,MACA,OAAQ;AAAA,MACR,aAAW;AAAA,MACX,WAAU;AAAA,MAEV;AAAA,4BAAC,qBAAkB,QAAS,aAAc,OAAgB;AAAA,QACxD,KAAK,IAAK,CAAE,WAAY;AACzB,iBACC;AAAA,YAAC;AAAA;AAAA,cAEA;AAAA,cACA,SACC,CAAE,mBAAmB;AAAA,gBACpB,CAAE,QACD,IAAI,SAAS,OAAO,QACpB,IAAI,SAAS,OAAO,QACpB,IAAI,QAAQ,OAAO,OACnB,IAAI,aAAa,OAAO;AAAA,cAC1B;AAAA,cAED,UAAW,CAAE,UACZ,sBAAuB,QAAQ,KAAM;AAAA;AAAA,YAZhC,OAAO,OAAO,OAAO;AAAA,UAc5B;AAAA,QAEF,CAAE;AAAA,QACA,mBAAmB,aAAa,QACjC,oBAAC,2BAAwB,QAAS,aAAc;AAAA;AAAA;AAAA,EAElD;AAEF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -24,11 +24,15 @@ var useIsDirty = () => {
|
|
|
24
24
|
);
|
|
25
25
|
const siteEntityLabels = siteEntityConfig?.meta?.labels ?? {};
|
|
26
26
|
const {
|
|
27
|
+
title: siteTitleEdit,
|
|
28
|
+
description: siteDescriptionEdit,
|
|
27
29
|
site_logo: siteLogoEdit,
|
|
28
30
|
site_icon: siteIconEdit,
|
|
29
31
|
...otherSiteEdits
|
|
30
32
|
} = siteEdits ?? {};
|
|
31
33
|
const orderedSiteProperties = [
|
|
34
|
+
siteTitleEdit !== void 0 && "title",
|
|
35
|
+
siteDescriptionEdit !== void 0 && "description",
|
|
32
36
|
siteLogoEdit !== void 0 && "site_logo",
|
|
33
37
|
siteIconEdit !== void 0 && "site_icon",
|
|
34
38
|
...Object.keys(otherSiteEdits)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/entities-saved-states/hooks/use-is-dirty.js"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import { useSelect } from '@wordpress/data';\nimport { useMemo, useState } from '@wordpress/element';\nimport { STORE_NAME } from '../../../name';\n\n/**\n * Custom hook that determines if any entities are dirty (edited) and provides a way to manage selected/unselected entities.\n *\n * @return {Object} An object containing the following properties:\n * - dirtyEntityRecords: An array of dirty entity records.\n * - isDirty: A boolean indicating if there are any dirty entity records.\n * - setUnselectedEntities: A function to set the unselected entities.\n * - unselectedEntities: An array of unselected entities.\n */\nexport const useIsDirty = () => {\n\tconst { editedEntities, siteEdits, siteEntityConfig } = useSelect(\n\t\t( select ) => {\n\t\t\tconst {\n\t\t\t\t__experimentalGetDirtyEntityRecords,\n\t\t\t\tgetEntityRecordEdits,\n\t\t\t\tgetEntityConfig,\n\t\t\t} = select( STORE_NAME );\n\n\t\t\treturn {\n\t\t\t\teditedEntities: __experimentalGetDirtyEntityRecords(),\n\t\t\t\tsiteEdits: getEntityRecordEdits( 'root', 'site' ),\n\t\t\t\tsiteEntityConfig: getEntityConfig( 'root', 'site' ),\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\tconst dirtyEntityRecords = useMemo( () => {\n\t\t// Remove site object and decouple into its edited pieces.\n\t\tconst editedEntitiesWithoutSite = editedEntities.filter(\n\t\t\t( record ) => ! ( record.kind === 'root' && record.name === 'site' )\n\t\t);\n\n\t\tconst siteEntityLabels = siteEntityConfig?.meta?.labels ?? {};\n\t\tconst {\n\t\t\ttitle: siteTitleEdit,\n\t\t\tdescription: siteDescriptionEdit,\n\t\t\tsite_logo: siteLogoEdit,\n\t\t\tsite_icon: siteIconEdit,\n\t\t\t...otherSiteEdits\n\t\t} = siteEdits ?? {};\n\t\tconst orderedSiteProperties = [\n\t\t\tsiteTitleEdit !== undefined && 'title',\n\t\t\tsiteDescriptionEdit !== undefined && 'description',\n\t\t\tsiteLogoEdit !== undefined && 'site_logo',\n\t\t\tsiteIconEdit !== undefined && 'site_icon',\n\t\t\t...Object.keys( otherSiteEdits ),\n\t\t].filter( Boolean );\n\t\tconst editedSiteEntities = orderedSiteProperties.map(\n\t\t\t( property ) => ( {\n\t\t\t\tkind: 'root',\n\t\t\t\tname: 'site',\n\t\t\t\ttitle: siteEntityLabels[ property ] || property,\n\t\t\t\tproperty,\n\t\t\t} )\n\t\t);\n\n\t\treturn [ ...editedEntitiesWithoutSite, ...editedSiteEntities ];\n\t}, [ editedEntities, siteEdits, siteEntityConfig ] );\n\n\t// Unchecked entities to be ignored by save function.\n\tconst [ unselectedEntities, _setUnselectedEntities ] = useState( [] );\n\n\tconst setUnselectedEntities = (\n\t\t{ kind, name, key, property },\n\t\tchecked\n\t) => {\n\t\tif ( checked ) {\n\t\t\t_setUnselectedEntities(\n\t\t\t\tunselectedEntities.filter(\n\t\t\t\t\t( elt ) =>\n\t\t\t\t\t\telt.kind !== kind ||\n\t\t\t\t\t\telt.name !== name ||\n\t\t\t\t\t\telt.key !== key ||\n\t\t\t\t\t\telt.property !== property\n\t\t\t\t)\n\t\t\t);\n\t\t} else {\n\t\t\t_setUnselectedEntities( [\n\t\t\t\t...unselectedEntities,\n\t\t\t\t{ kind, name, key, property },\n\t\t\t] );\n\t\t}\n\t};\n\n\tconst isDirty = dirtyEntityRecords.length - unselectedEntities.length > 0;\n\n\treturn {\n\t\tdirtyEntityRecords,\n\t\tisDirty,\n\t\tsetUnselectedEntities,\n\t\tunselectedEntities,\n\t};\n};\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,iBAAiB;AAC1B,SAAS,SAAS,gBAAgB;AAClC,SAAS,kBAAkB;AAWpB,IAAM,aAAa,MAAM;AAC/B,QAAM,EAAE,gBAAgB,WAAW,iBAAiB,IAAI;AAAA,IACvD,CAAE,WAAY;AACb,YAAM;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACD,IAAI,OAAQ,UAAW;AAEvB,aAAO;AAAA,QACN,gBAAgB,oCAAoC;AAAA,QACpD,WAAW,qBAAsB,QAAQ,MAAO;AAAA,QAChD,kBAAkB,gBAAiB,QAAQ,MAAO;AAAA,MACnD;AAAA,IACD;AAAA,IACA,CAAC;AAAA,EACF;AAEA,QAAM,qBAAqB,QAAS,MAAM;AAEzC,UAAM,4BAA4B,eAAe;AAAA,MAChD,CAAE,WAAY,EAAI,OAAO,SAAS,UAAU,OAAO,SAAS;AAAA,IAC7D;AAEA,UAAM,mBAAmB,kBAAkB,MAAM,UAAU,CAAC;AAC5D,UAAM;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,WAAW;AAAA,MACX,GAAG;AAAA,IACJ,IAAI,aAAa,CAAC;AAClB,UAAM,wBAAwB;AAAA,MAC7B,kBAAkB,UAAa;AAAA,MAC/B,wBAAwB,UAAa;AAAA,MACrC,iBAAiB,UAAa;AAAA,MAC9B,iBAAiB,UAAa;AAAA,MAC9B,GAAG,OAAO,KAAM,cAAe;AAAA,IAChC,EAAE,OAAQ,OAAQ;AAClB,UAAM,qBAAqB,sBAAsB;AAAA,MAChD,CAAE,cAAgB;AAAA,QACjB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO,iBAAkB,QAAS,KAAK;AAAA,QACvC;AAAA,MACD;AAAA,IACD;AAEA,WAAO,CAAE,GAAG,2BAA2B,GAAG,kBAAmB;AAAA,EAC9D,GAAG,CAAE,gBAAgB,WAAW,gBAAiB,CAAE;AAGnD,QAAM,CAAE,oBAAoB,sBAAuB,IAAI,SAAU,CAAC,CAAE;AAEpE,QAAM,wBAAwB,CAC7B,EAAE,MAAM,MAAM,KAAK,SAAS,GAC5B,YACI;AACJ,QAAK,SAAU;AACd;AAAA,QACC,mBAAmB;AAAA,UAClB,CAAE,QACD,IAAI,SAAS,QACb,IAAI,SAAS,QACb,IAAI,QAAQ,OACZ,IAAI,aAAa;AAAA,QACnB;AAAA,MACD;AAAA,IACD,OAAO;AACN,6BAAwB;AAAA,QACvB,GAAG;AAAA,QACH,EAAE,MAAM,MAAM,KAAK,SAAS;AAAA,MAC7B,CAAE;AAAA,IACH;AAAA,EACD;AAEA,QAAM,UAAU,mBAAmB,SAAS,mBAAmB,SAAS;AAExE,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/entities-saved-states/index.js"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import clsx from 'clsx';\nimport { Button, Flex, FlexItem } from '@wordpress/components';\nimport { __, _n, sprintf } from '@wordpress/i18n';\nimport {\n\tuseCallback,\n\tuseRef,\n\tcreateInterpolateElement,\n} from '@wordpress/element';\nimport {\n\t__experimentalUseDialog as useDialog,\n\tuseInstanceId,\n} from '@wordpress/compose';\nimport { useDispatch } from '@wordpress/data';\nimport EntityTypeList from './entity-type-list';\nimport { useIsDirty } from './hooks/use-is-dirty';\nimport { unlock } from '../../lock-unlock';\nimport { STORE_NAME } from '../../name';\n\n/**\n * Renders the component for managing saved states of entities.\n *\n * @param {Object} props The component props.\n * @param {Function} props.close The function to close the dialog.\n * @param {boolean=} props.renderDialog Whether to render the component with modal dialog behavior.\n * @param {string} props.variant Changes the layout of the component. When an `inline` value is provided, the action buttons are rendered at the end of the component instead of at the start.\n *\n * @return {React.ReactNode} The rendered component.\n */\nexport default function EntitiesSavedStates( {\n\tclose,\n\trenderDialog,\n\tvariant,\n} ) {\n\tconst isDirtyProps = useIsDirty();\n\treturn (\n\t\t<EntitiesSavedStatesExtensible\n\t\t\tclose={ close }\n\t\t\trenderDialog={ renderDialog }\n\t\t\tvariant={ variant }\n\t\t\t{ ...isDirtyProps }\n\t\t/>\n\t);\n}\n\n/**\n * Renders a panel for saving entities with dirty records.\n *\n * @param {Object} props The component props.\n * @param {string} props.additionalPrompt Additional prompt to display.\n * @param {Function} props.close Function to close the panel.\n * @param {Function} props.onSave Function to call when saving entities.\n * @param {boolean} props.saveEnabled Flag indicating if save is enabled.\n * @param {string} props.saveLabel Label for the save button.\n * @param {boolean} props.renderDialog Whether to render the component with modal dialog behavior.\n * @param {Array} props.dirtyEntityRecords Array of dirty entity records.\n * @param {boolean} props.isDirty Flag indicating if there are dirty entities.\n * @param {Function} props.setUnselectedEntities Function to set unselected entities.\n * @param {Array} props.unselectedEntities Array of unselected entities.\n * @param {string} props.variant Changes the layout of the component. When an `inline` value is provided, the action buttons are rendered at the end of the component instead of at the start.\n * @param {string} props.successNoticeContent Optional custom success notice content.\n *\n * @return {React.ReactNode} The rendered component.\n */\nexport function EntitiesSavedStatesExtensible( {\n\tadditionalPrompt = undefined,\n\tclose,\n\tonSave = undefined,\n\tsaveEnabled: saveEnabledProp = undefined,\n\tsaveLabel = __( 'Save' ),\n\trenderDialog,\n\tdirtyEntityRecords,\n\tisDirty,\n\tsetUnselectedEntities,\n\tunselectedEntities,\n\tvariant = 'default',\n\tsuccessNoticeContent,\n} ) {\n\tconst saveButtonRef = useRef();\n\tconst { saveDirtyEntities } = unlock( useDispatch( STORE_NAME ) );\n\t// To group entities by type.\n\tconst partitionedSavables = dirtyEntityRecords.reduce( ( acc, record ) => {\n\t\tconst { name } = record;\n\t\tif ( ! acc[ name ] ) {\n\t\t\tacc[ name ] = [];\n\t\t}\n\t\tacc[ name ].push( record );\n\t\treturn acc;\n\t}, {} );\n\n\t// Sort entity groups.\n\tconst {\n\t\tsite: siteSavables,\n\t\twp_template: templateSavables,\n\t\twp_template_part: templatePartSavables,\n\t\t...contentSavables\n\t} = partitionedSavables;\n\tconst sortedPartitionedSavables = [\n\t\tsiteSavables,\n\t\ttemplateSavables,\n\t\ttemplatePartSavables,\n\t\t...Object.values( contentSavables ),\n\t].filter( Array.isArray );\n\n\tconst saveEnabled = saveEnabledProp ?? isDirty;\n\t// Explicitly define this with no argument passed. Using `close` on\n\t// its own will use the event object in place of the expected saved entities.\n\tconst dismissPanel = useCallback( () => close(), [ close ] );\n\n\tconst [ saveDialogRef, saveDialogProps ] = useDialog( {\n\t\tonClose: () => dismissPanel(),\n\t} );\n\tconst dialogLabelId = useInstanceId(\n\t\tEntitiesSavedStatesExtensible,\n\t\t'entities-saved-states__panel-label'\n\t);\n\tconst dialogDescriptionId = useInstanceId(\n\t\tEntitiesSavedStatesExtensible,\n\t\t'entities-saved-states__panel-description'\n\t);\n\n\tconst selectItemsToSaveDescription = !! dirtyEntityRecords.length\n\t\t? __( 'Select the items you want to save.' )\n\t\t: undefined;\n\n\tconst isInline = variant === 'inline';\n\n\tconst actionButtons = (\n\t\t<>\n\t\t\t<FlexItem\n\t\t\t\tisBlock={ isInline ? false : true }\n\t\t\t\tas={ Button }\n\t\t\t\tvariant={ isInline ? 'tertiary' : 'secondary' }\n\t\t\t\tsize={ isInline ? undefined : 'compact' }\n\t\t\t\tonClick={ dismissPanel }\n\t\t\t>\n\t\t\t\t{ __( 'Cancel' ) }\n\t\t\t</FlexItem>\n\t\t\t<FlexItem\n\t\t\t\tisBlock={ isInline ? false : true }\n\t\t\t\tas={ Button }\n\t\t\t\tref={ saveButtonRef }\n\t\t\t\tvariant=\"primary\"\n\t\t\t\tsize={ isInline ? undefined : 'compact' }\n\t\t\t\tdisabled={ ! saveEnabled }\n\t\t\t\taccessibleWhenDisabled\n\t\t\t\tonClick={ () =>\n\t\t\t\t\tsaveDirtyEntities( {\n\t\t\t\t\t\tonSave,\n\t\t\t\t\t\tdirtyEntityRecords,\n\t\t\t\t\t\tentitiesToSkip: unselectedEntities,\n\t\t\t\t\t\tclose,\n\t\t\t\t\t\tsuccessNoticeContent,\n\t\t\t\t\t} )\n\t\t\t\t}\n\t\t\t\tclassName=\"entities-saved-states__save-button\"\n\t\t\t>\n\t\t\t\t{ saveLabel }\n\t\t\t</FlexItem>\n\t\t</>\n\t);\n\n\treturn (\n\t\t<div\n\t\t\tref={ renderDialog ? saveDialogRef : undefined }\n\t\t\t{ ...( renderDialog && saveDialogProps ) }\n\t\t\tclassName={ clsx( 'entities-saved-states__panel', {\n\t\t\t\t'is-inline': isInline,\n\t\t\t} ) }\n\t\t\trole={ renderDialog ? 'dialog' : undefined }\n\t\t\taria-labelledby={ renderDialog ? dialogLabelId : undefined }\n\t\t\taria-describedby={ renderDialog ? dialogDescriptionId : undefined }\n\t\t>\n\t\t\t{ ! isInline && (\n\t\t\t\t<Flex className=\"entities-saved-states__panel-header\" gap={ 2 }>\n\t\t\t\t\t{ actionButtons }\n\t\t\t\t</Flex>\n\t\t\t) }\n\n\t\t\t<div className=\"entities-saved-states__text-prompt\">\n\t\t\t\t<div className=\"entities-saved-states__text-prompt--header-wrapper\">\n\t\t\t\t\t<strong\n\t\t\t\t\t\tid={ renderDialog ? dialogLabelId : undefined }\n\t\t\t\t\t\tclassName=\"entities-saved-states__text-prompt--header\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{ __( 'Are you ready to save?' ) }\n\t\t\t\t\t</strong>\n\t\t\t\t</div>\n\t\t\t\t<div id={ renderDialog ? dialogDescriptionId : undefined }>\n\t\t\t\t\t{ additionalPrompt }\n\t\t\t\t\t<p className=\"entities-saved-states__text-prompt--changes-count\">\n\t\t\t\t\t\t{ isDirty\n\t\t\t\t\t\t\t? createInterpolateElement(\n\t\t\t\t\t\t\t\t\tsprintf(\n\t\t\t\t\t\t\t\t\t\t/* translators: %d: number of site changes waiting to be saved. */\n\t\t\t\t\t\t\t\t\t\t_n(\n\t\t\t\t\t\t\t\t\t\t\t'There is <strong>%d site change</strong> waiting to be saved.',\n\t\t\t\t\t\t\t\t\t\t\t'There are <strong>%d site changes</strong> waiting to be saved.',\n\t\t\t\t\t\t\t\t\t\t\tdirtyEntityRecords.length\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\tdirtyEntityRecords.length\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t{ strong: <strong /> }\n\t\t\t\t\t\t\t )\n\t\t\t\t\t\t\t: selectItemsToSaveDescription }\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{ sortedPartitionedSavables.map( ( list ) => {\n\t\t\t\treturn (\n\t\t\t\t\t<EntityTypeList\n\t\t\t\t\t\tkey={ list[ 0 ].name }\n\t\t\t\t\t\tlist={ list }\n\t\t\t\t\t\tunselectedEntities={ unselectedEntities }\n\t\t\t\t\t\tsetUnselectedEntities={ setUnselectedEntities }\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t} ) }\n\n\t\t\t{ isInline && (\n\t\t\t\t<Flex\n\t\t\t\t\tdirection=\"row\"\n\t\t\t\t\tjustify=\"flex-end\"\n\t\t\t\t\tclassName=\"entities-saved-states__panel-footer\"\n\t\t\t\t>\n\t\t\t\t\t{ actionButtons }\n\t\t\t\t</Flex>\n\t\t\t) }\n\t\t</div>\n\t);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/dynamic-entities.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import type { GetRecordsHttpQuery, State } from './selectors';\nimport type * as ET from './entity-types';\n\nexport type WPEntityTypes< C extends ET.Context = 'edit' > = {\n\tComment: ET.Comment< C >;\n\tGlobalStyles: ET.GlobalStylesRevision< C >;\n\tMedia: ET.Attachment< C >;\n\tMenu: ET.NavMenu< C >;\n\tMenuItem: ET.NavMenuItem< C >;\n\tMenuLocation: ET.MenuLocation< C >;\n\tPlugin: ET.Plugin< C >;\n\tPostType: ET.Type< C >;\n\tRevision: ET.PostRevision< C >;\n\tSidebar: ET.Sidebar< C >;\n\tSite: ET.Settings< C >;\n\tStatus: ET.PostStatusObject< C >;\n\tTaxonomy: ET.Taxonomy< C >;\n\tTerm: ET.Term< C >;\n\tTheme: ET.Theme< C >;\n\tUnstableBase: ET.UnstableBase< C >;\n\tUser: ET.User< C >;\n\tWidget: ET.Widget< C >;\n\tWidgetType: ET.WidgetType< C >;\n};\n\n/**\n * A simple utility that pluralizes a string.\n * Converts:\n * - \"post\" to \"posts\"\n * - \"taxonomy\" to \"taxonomies\"\n * - \"media\" to \"mediaItems\"\n * - \"status\" to \"statuses\"\n *\n * It does not pluralize \"GlobalStyles\" due to lack of clarity about it at time of writing.\n */\ntype PluralizeEntity< T extends string > = T extends 'GlobalStyles'\n\t? never\n\t: T extends 'Media'\n\t? 'MediaItems'\n\t: T extends 'Status'\n\t? 'Statuses'\n\t: T extends `${ infer U }y`\n\t? `${ U }ies`\n\t: `${ T }s`;\n\n/**\n * A simple utility that singularizes a string.\n *\n * Converts:\n * - \"posts\" to \"post\"\n * - \"taxonomies\" to \"taxonomy\"\n * - \"mediaItems\" to \"media\"\n * - \"statuses\" to \"status\"\n */\ntype SingularizeEntity< T extends string > = T extends 'MediaItems'\n\t? 'Media'\n\t: T extends 'Statuses'\n\t? 'Status'\n\t: T extends `${ infer U }ies`\n\t? `${ U }y`\n\t: T extends `${ infer U }s`\n\t? U\n\t: T;\n\nexport type SingularGetters = {\n\t[ Key in `get${ keyof WPEntityTypes }` ]: (\n\t\tstate: State,\n\t\tid: number | string,\n\t\tquery?: GetRecordsHttpQuery\n\t) => WPEntityTypes[ Key extends `get${ infer E }` ? E : never ] | undefined;\n};\n\nexport type PluralGetters = {\n\t[ Key in `get${ PluralizeEntity< keyof WPEntityTypes > }` ]: (\n\t\tstate: State,\n\t\tquery?: GetRecordsHttpQuery\n\t) => Array<\n\t\tWPEntityTypes[ Key extends `get${ infer E }`\n\t\t\t? SingularizeEntity< E >\n\t\t\t: never ]\n\t> | null;\n};\n\ntype ActionOptions = {\n\tthrowOnError?: boolean;\n};\n\ntype DeleteRecordsHttpQuery = Record< string, any >;\n\nexport type SaveActions = {\n\t[ Key in `save${ keyof WPEntityTypes }` ]: (\n\t\tdata: Partial<\n\t\t\tWPEntityTypes[ Key extends `save${ infer E }` ? E : never ]\n\t\t>,\n\t\toptions?: ActionOptions\n\t) => Promise< void >;\n};\n\nexport type DeleteActions = {\n\t[ Key in `delete${ keyof WPEntityTypes }` ]: (\n\t\tid: number | string,\n\t\tquery?: DeleteRecordsHttpQuery,\n\t\toptions?: ActionOptions\n\t) => Promise< void >;\n};\n\nexport let dynamicActions: SaveActions & DeleteActions;\n\nexport let dynamicSelectors: SingularGetters & PluralGetters;\n"],
|
|
5
|
+
"mappings": ";AA0GO,IAAI;AAEJ,IAAI;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|