UNPKG

@wordpress/editor

Version:
1,283 lines (1,174 loc) 32.4 kB
/** * WordPress dependencies */ import { speak } from '@wordpress/a11y'; import apiFetch from '@wordpress/api-fetch'; import deprecated from '@wordpress/deprecated'; import { parse, synchronizeBlocksWithTemplate, __unstableSerializeAndClean, } from '@wordpress/blocks'; import { store as noticesStore } from '@wordpress/notices'; import { store as coreStore } from '@wordpress/core-data'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { applyFilters, applyFiltersAsync, doActionAsync, } from '@wordpress/hooks'; import { store as preferencesStore } from '@wordpress/preferences'; import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies */ import { localAutosaveSet } from './local-autosave'; import { getNotificationArgumentsForSaveSuccess, getNotificationArgumentsForSaveFail, getNotificationArgumentsForTrashFail, } from './utils/notice-builder'; import { unlock } from '../lock-unlock'; /** * Returns an action generator used in signalling that editor has initialized with * the specified post object and editor settings. * * @param {Object} post Post object. * @param {Object} edits Initial edited attributes object. * @param {Array} [template] Block Template. */ export const setupEditor = ( post, edits, template ) => ( { dispatch } ) => { dispatch.setEditedPost( post.type, post.id ); // Apply a template for new posts only, if exists. const isNewPost = post.status === 'auto-draft'; if ( isNewPost && template ) { // In order to ensure maximum of a single parse during setup, edits are // included as part of editor setup action. Assume edited content as // canonical if provided, falling back to post. let content; if ( 'content' in edits ) { content = edits.content; } else { content = post.content.raw; } let blocks = parse( content ); blocks = synchronizeBlocksWithTemplate( blocks, template ); dispatch.resetEditorBlocks( blocks, { __unstableShouldCreateUndoLevel: false, } ); } if ( edits && Object.entries( edits ).some( ( [ key, edit ] ) => edit !== ( post[ key ]?.raw ?? post[ key ] ) ) ) { dispatch.editPost( edits ); } }; /** * Returns an action object signalling that the editor is being destroyed and * that any necessary state or side-effect cleanup should occur. * * @deprecated * * @return {Object} Action object. */ export function __experimentalTearDownEditor() { deprecated( "wp.data.dispatch( 'core/editor' ).__experimentalTearDownEditor", { since: '6.5', } ); return { type: 'DO_NOTHING' }; } /** * Returns an action object used in signalling that the latest version of the * post has been received, either by initialization or save. * * @deprecated Since WordPress 6.0. */ export function resetPost() { deprecated( "wp.data.dispatch( 'core/editor' ).resetPost", { since: '6.0', version: '6.3', alternative: 'Initialize the editor with the setupEditorState action', } ); return { type: 'DO_NOTHING' }; } /** * Returns an action object used in signalling that a patch of updates for the * latest version of the post have been received. * * @return {Object} Action object. * @deprecated since Gutenberg 9.7.0. */ export function updatePost() { deprecated( "wp.data.dispatch( 'core/editor' ).updatePost", { since: '5.7', alternative: 'Use the core entities store instead', } ); return { type: 'DO_NOTHING', }; } /** * Setup the editor state. * * @deprecated * * @param {Object} post Post object. */ export function setupEditorState( post ) { deprecated( "wp.data.dispatch( 'core/editor' ).setupEditorState", { since: '6.5', alternative: "wp.data.dispatch( 'core/editor' ).setEditedPost", } ); return setEditedPost( post.type, post.id ); } /** * Returns an action that sets the current post Type and post ID. * * @param {string} postType Post Type. * @param {string} postId Post ID. * * @return {Object} Action object. */ export function setEditedPost( postType, postId ) { return { type: 'SET_EDITED_POST', postType, postId, }; } /** * Returns an action object used in signalling that attributes of the post have * been edited. * * @param {Object} edits Post attributes to edit. * @param {Object} [options] Options for the edit. * * @example * ```js * // Update the post title * wp.data.dispatch( 'core/editor' ).editPost( { title: `${ newTitle }` } ); * ``` * * @return {Object} Action object */ export const editPost = ( edits, options ) => ( { select, registry } ) => { const { id, type } = select.getCurrentPost(); registry .dispatch( coreStore ) .editEntityRecord( 'postType', type, id, edits, options ); }; /** * Action for saving the current post in the editor. * * @param {Object} [options] */ export const savePost = ( options = {} ) => async ( { select, dispatch, registry } ) => { if ( ! select.isEditedPostSaveable() ) { return; } const content = select.getEditedPostContent(); dispatch.editPost( { content }, { undoIgnore: true } ); const previousRecord = select.getCurrentPost(); let edits = { id: previousRecord.id, ...registry .select( coreStore ) .getEntityRecordNonTransientEdits( 'postType', previousRecord.type, previousRecord.id ), content, }; dispatch( { type: 'REQUEST_POST_UPDATE_START', options } ); let error = false; try { edits = await applyFiltersAsync( 'editor.preSavePost', edits, options ); } catch ( err ) { error = err; } if ( ! error ) { try { await registry .dispatch( coreStore ) .saveEntityRecord( 'postType', previousRecord.type, edits, options ); } catch ( err ) { error = err.message && err.code !== 'unknown_error' ? err.message : __( 'An error occurred while updating.' ); } } if ( ! error ) { error = registry .select( coreStore ) .getLastEntitySaveError( 'postType', previousRecord.type, previousRecord.id ); } // Run the hook with legacy unstable name for backward compatibility if ( ! error ) { try { await applyFilters( 'editor.__unstableSavePost', Promise.resolve(), options ); } catch ( err ) { error = err; } } if ( ! error ) { try { await doActionAsync( 'editor.savePost', { id: previousRecord.id, type: previousRecord.type }, options ); } catch ( err ) { error = err; } } dispatch( { type: 'REQUEST_POST_UPDATE_FINISH', options } ); if ( typeof window !== 'undefined' && window.__experimentalTemplateActivate && ! options.isAutosave && previousRecord.type === 'wp_template' && ( typeof previousRecord.id === 'number' || /^\d+$/.test( previousRecord.id ) ) ) { templateActivationNotice( { select, dispatch, registry } ); } if ( error ) { const args = getNotificationArgumentsForSaveFail( { post: previousRecord, edits, error, } ); if ( args.length ) { registry.dispatch( noticesStore ).createErrorNotice( ...args ); } } else { const updatedRecord = select.getCurrentPost(); const args = getNotificationArgumentsForSaveSuccess( { previousPost: previousRecord, post: updatedRecord, postType: await registry .resolveSelect( coreStore ) .getPostType( updatedRecord.type ), options, } ); if ( args.length ) { registry .dispatch( noticesStore ) .createSuccessNotice( ...args ); } // Make sure that any edits after saving create an undo level and are // considered for change detection. if ( ! options.isAutosave ) { registry .dispatch( blockEditorStore ) .__unstableMarkLastChangeAsPersistent(); } } }; async function templateActivationNotice( { select, registry } ) { const editorSettings = select.getEditorSettings(); // Don't open for focused entity. if ( editorSettings.onNavigateToPreviousEntityRecord ) { return; } const { id, slug } = select.getCurrentPost(); const site = await registry .select( coreStore ) .getEntityRecord( 'root', 'site' ); // Already active. if ( site.active_templates[ slug ] === id ) { return; } const currentTheme = await registry .resolveSelect( coreStore ) .getCurrentTheme(); const templateType = currentTheme?.default_template_types.find( ( type ) => type.slug === slug ); await registry.dispatch( noticesStore ).createNotice( 'info', sprintf( // translators: %s: The name (or slug) of the type of template. __( 'Do you want to activate this "%s" template?' ), templateType?.title ?? slug ), { id: 'template-activate-notice', actions: [ { label: __( 'Activate' ), onClick: async () => { await registry .dispatch( noticesStore ) .createNotice( 'info', __( 'Activating template…' ), { id: 'template-activate-notice' } ); try { const currentSite = await registry .select( coreStore ) .getEntityRecord( 'root', 'site' ); await registry .dispatch( coreStore ) .saveEntityRecord( 'root', 'site', { active_templates: { ...currentSite.active_templates, [ slug ]: id, }, }, { throwOnError: true } ); await registry .dispatch( noticesStore ) .createSuccessNotice( __( 'Template activated.' ), { id: 'template-activate-notice' } ); } catch ( error ) { await registry .dispatch( noticesStore ) .createErrorNotice( __( 'Template activation failed.' ), { id: 'template-activate-notice' } ); // Rethrow for debugging. throw error; } }, }, ], } ); } /** * Action for refreshing the current post. * * @deprecated Since WordPress 6.0. */ export function refreshPost() { deprecated( "wp.data.dispatch( 'core/editor' ).refreshPost", { since: '6.0', version: '6.3', alternative: 'Use the core entities store instead', } ); return { type: 'DO_NOTHING' }; } /** * Action for trashing the current post in the editor. */ export const trashPost = () => async ( { select, dispatch, registry } ) => { const postTypeSlug = select.getCurrentPostType(); const postType = await registry .resolveSelect( coreStore ) .getPostType( postTypeSlug ); const { rest_base: restBase, rest_namespace: restNamespace = 'wp/v2' } = postType; dispatch( { type: 'REQUEST_POST_DELETE_START' } ); try { const post = select.getCurrentPost(); await apiFetch( { path: `/${ restNamespace }/${ restBase }/${ post.id }`, method: 'DELETE', } ); await dispatch.savePost(); } catch ( error ) { registry .dispatch( noticesStore ) .createErrorNotice( ...getNotificationArgumentsForTrashFail( { error } ) ); } dispatch( { type: 'REQUEST_POST_DELETE_FINISH' } ); }; /** * Action that autosaves the current post. This * includes server-side autosaving (default) and client-side (a.k.a. local) * autosaving (e.g. on the Web, the post might be committed to Session * Storage). * * @param {Object} [options] Extra flags to identify the autosave. * @param {boolean} [options.local] Whether to perform a local autosave. */ export const autosave = ( { local = false, ...options } = {} ) => async ( { select, dispatch } ) => { const post = select.getCurrentPost(); if ( local ) { const isPostNew = select.isEditedPostNew(); const title = select.getEditedPostAttribute( 'title' ); const content = select.getEditedPostAttribute( 'content' ); const excerpt = select.getEditedPostAttribute( 'excerpt' ); localAutosaveSet( post.id, isPostNew, title, content, excerpt ); } else { await dispatch.savePost( { isAutosave: true, ...options } ); } }; /** * Save for preview. * * @param {Object} options Options object. * @param {boolean} options.forceIsAutosaveable Whether to force the post to be autosaveable. * * @return {Function} Thunk that saves for preview and returns the preview link. */ export const __unstableSaveForPreview = ( { forceIsAutosaveable } = {} ) => async ( { select, dispatch } ) => { if ( ( forceIsAutosaveable || select.isEditedPostAutosaveable() ) && ! select.isPostLocked() ) { const isDraft = [ 'draft', 'auto-draft' ].includes( select.getEditedPostAttribute( 'status' ) ); if ( isDraft ) { await dispatch.savePost( { isPreview: true } ); } else { await dispatch.autosave( { isPreview: true } ); } } return select.getEditedPostPreviewLink(); }; /** * Action that restores last popped state in undo history. */ export const redo = () => ( { registry } ) => { registry.dispatch( coreStore ).redo(); }; /** * Action that pops a record from undo history and undoes the edit. */ export const undo = () => ( { registry } ) => { registry.dispatch( coreStore ).undo(); }; /** * Action that creates an undo history record. * * @deprecated Since WordPress 6.0 */ export function createUndoLevel() { deprecated( "wp.data.dispatch( 'core/editor' ).createUndoLevel", { since: '6.0', version: '6.3', alternative: 'Use the core entities store instead', } ); return { type: 'DO_NOTHING' }; } /** * Action that locks the editor. * * @param {Object} lock Details about the post lock status, user, and nonce. * @return {Object} Action object. */ export function updatePostLock( lock ) { return { type: 'UPDATE_POST_LOCK', lock, }; } /** * Enable the publish sidebar. */ export const enablePublishSidebar = () => ( { registry } ) => { registry .dispatch( preferencesStore ) .set( 'core', 'isPublishSidebarEnabled', true ); }; /** * Disables the publish sidebar. */ export const disablePublishSidebar = () => ( { registry } ) => { registry .dispatch( preferencesStore ) .set( 'core', 'isPublishSidebarEnabled', false ); }; /** * Action that locks post saving. * * @param {string} lockName The lock name. * * @example * ``` * const { subscribe } = wp.data; * * const initialPostStatus = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'status' ); * * // Only allow publishing posts that are set to a future date. * if ( 'publish' !== initialPostStatus ) { * * // Track locking. * let locked = false; * * // Watch for the publish event. * let unssubscribe = subscribe( () => { * const currentPostStatus = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'status' ); * if ( 'publish' !== currentPostStatus ) { * * // Compare the post date to the current date, lock the post if the date isn't in the future. * const postDate = new Date( wp.data.select( 'core/editor' ).getEditedPostAttribute( 'date' ) ); * const currentDate = new Date(); * if ( postDate.getTime() <= currentDate.getTime() ) { * if ( ! locked ) { * locked = true; * wp.data.dispatch( 'core/editor' ).lockPostSaving( 'futurelock' ); * } * } else { * if ( locked ) { * locked = false; * wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'futurelock' ); * } * } * } * } ); * } * ``` * * @return {Object} Action object */ export function lockPostSaving( lockName ) { return { type: 'LOCK_POST_SAVING', lockName, }; } /** * Action that unlocks post saving. * * @param {string} lockName The lock name. * * @example * ``` * // Unlock post saving with the lock key `mylock`: * wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'mylock' ); * ``` * * @return {Object} Action object */ export function unlockPostSaving( lockName ) { return { type: 'UNLOCK_POST_SAVING', lockName, }; } /** * Action that locks post autosaving. * * @param {string} lockName The lock name. * * @example * ``` * // Lock post autosaving with the lock key `mylock`: * wp.data.dispatch( 'core/editor' ).lockPostAutosaving( 'mylock' ); * ``` * * @return {Object} Action object */ export function lockPostAutosaving( lockName ) { return { type: 'LOCK_POST_AUTOSAVING', lockName, }; } /** * Action that unlocks post autosaving. * * @param {string} lockName The lock name. * * @example * ``` * // Unlock post saving with the lock key `mylock`: * wp.data.dispatch( 'core/editor' ).unlockPostAutosaving( 'mylock' ); * ``` * * @return {Object} Action object */ export function unlockPostAutosaving( lockName ) { return { type: 'UNLOCK_POST_AUTOSAVING', lockName, }; } /** * Returns an action object used to signal that the blocks have been updated. * * @param {Array} blocks Block Array. * @param {Object} [options] Optional options. */ export const resetEditorBlocks = ( blocks, options = {} ) => ( { select, dispatch, registry } ) => { const { __unstableShouldCreateUndoLevel, selection } = options; const edits = { blocks, selection }; if ( __unstableShouldCreateUndoLevel !== false ) { const { id, type } = select.getCurrentPost(); const noChange = registry .select( coreStore ) .getEditedEntityRecord( 'postType', type, id ).blocks === edits.blocks; if ( noChange ) { registry .dispatch( coreStore ) .__unstableCreateUndoLevel( 'postType', type, id ); return; } // We create a new function here on every persistent edit // to make sure the edit makes the post dirty and creates // a new undo level. edits.content = ( { blocks: blocksForSerialization = [] } ) => __unstableSerializeAndClean( blocksForSerialization ); } dispatch.editPost( edits ); }; /* * Returns an action object used in signalling that the post editor settings have been updated. * * @param {Object} settings Updated settings * * @return {Object} Action object */ export function updateEditorSettings( settings ) { return { type: 'UPDATE_EDITOR_SETTINGS', settings, }; } /** * Returns an action used to set the rendering mode of the post editor. We support multiple rendering modes: * * - `post-only`: This mode extracts the post blocks from the template and renders only those. The idea is to allow the user to edit the post/page in isolation without the wrapping template. * - `template-locked`: This mode renders both the template and the post blocks but the template blocks are locked and can't be edited. The post blocks are editable. * * @param {string} mode Mode (one of 'post-only' or 'template-locked'). */ export const setRenderingMode = ( mode ) => ( { dispatch, registry, select } ) => { if ( select.__unstableIsEditorReady() && ! select.getEditorSettings().isPreviewMode ) { registry.dispatch( blockEditorStore ).clearSelectedBlock(); } dispatch( { type: 'SET_RENDERING_MODE', mode, } ); }; /** * Action that changes the width of the editing canvas. * * @param {string} deviceType * * @return {Object} Action object. */ export function setDeviceType( deviceType ) { return { type: 'SET_DEVICE_TYPE', deviceType, }; } /** * Returns an action object used to enable or disable a panel in the editor. * * @param {string} panelName A string that identifies the panel to enable or disable. * * @return {Object} Action object. */ export const toggleEditorPanelEnabled = ( panelName ) => ( { registry } ) => { const inactivePanels = registry .select( preferencesStore ) .get( 'core', 'inactivePanels' ) ?? []; const isPanelInactive = !! inactivePanels?.includes( panelName ); // If the panel is inactive, remove it to enable it, else add it to // make it inactive. let updatedInactivePanels; if ( isPanelInactive ) { updatedInactivePanels = inactivePanels.filter( ( invactivePanelName ) => invactivePanelName !== panelName ); } else { updatedInactivePanels = [ ...inactivePanels, panelName ]; } registry .dispatch( preferencesStore ) .set( 'core', 'inactivePanels', updatedInactivePanels ); }; /** * Opens a closed panel and closes an open panel. * * @param {string} panelName A string that identifies the panel to open or close. */ export const toggleEditorPanelOpened = ( panelName ) => ( { registry } ) => { const openPanels = registry.select( preferencesStore ).get( 'core', 'openPanels' ) ?? []; const isPanelOpen = !! openPanels?.includes( panelName ); // If the panel is open, remove it to close it, else add it to // make it open. let updatedOpenPanels; if ( isPanelOpen ) { updatedOpenPanels = openPanels.filter( ( openPanelName ) => openPanelName !== panelName ); } else { updatedOpenPanels = [ ...openPanels, panelName ]; } registry .dispatch( preferencesStore ) .set( 'core', 'openPanels', updatedOpenPanels ); }; /** * Returns an action object used to remove a panel from the editor. * * @param {string} panelName A string that identifies the panel to remove. * * @return {Object} Action object. */ export function removeEditorPanel( panelName ) { return { type: 'REMOVE_PANEL', panelName, }; } /** * Returns an action object used to open/close the inserter. * * @param {boolean|Object} value Whether the inserter should be * opened (true) or closed (false). * To specify an insertion point, * use an object. * @param {string} value.rootClientId The root client ID to insert at. * @param {number} value.insertionIndex The index to insert at. * @param {string} value.filterValue A query to filter the inserter results. * @param {Function} value.onSelect A callback when an item is selected. * @param {string} value.tab The tab to open in the inserter. * @param {string} value.category The category to initialize in the inserter. * * @return {Object} Action object. */ export const setIsInserterOpened = ( value ) => ( { dispatch, registry } ) => { if ( typeof value === 'object' && value.hasOwnProperty( 'rootClientId' ) && value.hasOwnProperty( 'insertionIndex' ) ) { unlock( registry.dispatch( blockEditorStore ) ).setInsertionPoint( { rootClientId: value.rootClientId, index: value.insertionIndex, } ); } dispatch( { type: 'SET_IS_INSERTER_OPENED', value, } ); }; /** * Returns an action object used to open/close the list view. * * @param {boolean} isOpen A boolean representing whether the list view should be opened or closed. * @return {Object} Action object. */ export function setIsListViewOpened( isOpen ) { return { type: 'SET_IS_LIST_VIEW_OPENED', isOpen, }; } /** * Action that toggles Distraction free mode. * Distraction free mode expects there are no sidebars, as due to the * z-index values set, you can't close sidebars. * * @param {Object} [options={}] Optional configuration object * @param {boolean} [options.createNotice=true] Whether to create a notice */ export const toggleDistractionFree = ( { createNotice = true } = {} ) => ( { dispatch, registry } ) => { const isDistractionFree = registry .select( preferencesStore ) .get( 'core', 'distractionFree' ); if ( isDistractionFree ) { registry .dispatch( preferencesStore ) .set( 'core', 'fixedToolbar', false ); } if ( ! isDistractionFree ) { registry.batch( () => { registry .dispatch( preferencesStore ) .set( 'core', 'fixedToolbar', true ); dispatch.setIsInserterOpened( false ); dispatch.setIsListViewOpened( false ); unlock( registry.dispatch( blockEditorStore ) ).resetZoomLevel(); } ); } registry.batch( () => { registry .dispatch( preferencesStore ) .set( 'core', 'distractionFree', ! isDistractionFree ); if ( createNotice ) { registry .dispatch( noticesStore ) .createInfoNotice( isDistractionFree ? __( 'Distraction free mode deactivated.' ) : __( 'Distraction free mode activated.' ), { id: 'core/editor/distraction-free-mode/notice', type: 'snackbar', actions: [ { label: __( 'Undo' ), onClick: () => { registry.batch( () => { registry .dispatch( preferencesStore ) .set( 'core', 'fixedToolbar', isDistractionFree ); registry .dispatch( preferencesStore ) .toggle( 'core', 'distractionFree' ); } ); }, }, ], } ); } } ); }; /** * Action that toggles the Spotlight Mode view option. */ export const toggleSpotlightMode = () => ( { registry } ) => { registry.dispatch( preferencesStore ).toggle( 'core', 'focusMode' ); const isFocusMode = registry .select( preferencesStore ) .get( 'core', 'focusMode' ); registry .dispatch( noticesStore ) .createInfoNotice( isFocusMode ? __( 'Spotlight mode activated.' ) : __( 'Spotlight mode deactivated.' ), { id: 'core/editor/toggle-spotlight-mode/notice', type: 'snackbar', actions: [ { label: __( 'Undo' ), onClick: () => { registry .dispatch( preferencesStore ) .toggle( 'core', 'focusMode' ); }, }, ], } ); }; /** * Action that toggles the Top Toolbar view option. */ export const toggleTopToolbar = () => ( { registry } ) => { registry.dispatch( preferencesStore ).toggle( 'core', 'fixedToolbar' ); const isTopToolbar = registry .select( preferencesStore ) .get( 'core', 'fixedToolbar' ); registry .dispatch( noticesStore ) .createInfoNotice( isTopToolbar ? __( 'Top toolbar activated.' ) : __( 'Top toolbar deactivated.' ), { id: 'core/editor/toggle-top-toolbar/notice', type: 'snackbar', actions: [ { label: __( 'Undo' ), onClick: () => { registry .dispatch( preferencesStore ) .toggle( 'core', 'fixedToolbar' ); }, }, ], } ); }; /** * Triggers an action used to switch editor mode. * * @param {string} mode The editor mode. */ export const switchEditorMode = ( mode ) => ( { dispatch, registry } ) => { registry.dispatch( preferencesStore ).set( 'core', 'editorMode', mode ); if ( mode !== 'visual' ) { // Unselect blocks when we switch to a non visual mode. registry.dispatch( blockEditorStore ).clearSelectedBlock(); // Exit zoom out state when switching to a non visual mode. unlock( registry.dispatch( blockEditorStore ) ).resetZoomLevel(); } if ( mode === 'visual' ) { speak( __( 'Visual editor selected' ), 'assertive' ); } else if ( mode === 'text' ) { const isDistractionFree = registry .select( preferencesStore ) .get( 'core', 'distractionFree' ); if ( isDistractionFree ) { dispatch.toggleDistractionFree(); } speak( __( 'Code editor selected' ), 'assertive' ); } }; /** * Returns an action object used in signalling that the user opened the publish * sidebar. * * @return {Object} Action object */ export function openPublishSidebar() { return { type: 'OPEN_PUBLISH_SIDEBAR', }; } /** * Returns an action object used in signalling that the user closed the * publish sidebar. * * @return {Object} Action object. */ export function closePublishSidebar() { return { type: 'CLOSE_PUBLISH_SIDEBAR', }; } /** * Returns an action object used in signalling that the user toggles the publish sidebar. * * @return {Object} Action object */ export function togglePublishSidebar() { return { type: 'TOGGLE_PUBLISH_SIDEBAR', }; } /** * Backward compatibility */ const getBlockEditorAction = ( name ) => ( ...args ) => ( { registry } ) => { deprecated( "`wp.data.dispatch( 'core/editor' )." + name + '`', { since: '5.3', alternative: "`wp.data.dispatch( 'core/block-editor' )." + name + '`', version: '6.2', } ); registry.dispatch( blockEditorStore )[ name ]( ...args ); }; /** * @see resetBlocks in core/block-editor store. */ export const resetBlocks = getBlockEditorAction( 'resetBlocks' ); /** * @see receiveBlocks in core/block-editor store. */ export const receiveBlocks = getBlockEditorAction( 'receiveBlocks' ); /** * @see updateBlock in core/block-editor store. */ export const updateBlock = getBlockEditorAction( 'updateBlock' ); /** * @see updateBlockAttributes in core/block-editor store. */ export const updateBlockAttributes = getBlockEditorAction( 'updateBlockAttributes' ); /** * @see selectBlock in core/block-editor store. */ export const selectBlock = getBlockEditorAction( 'selectBlock' ); /** * @see startMultiSelect in core/block-editor store. */ export const startMultiSelect = getBlockEditorAction( 'startMultiSelect' ); /** * @see stopMultiSelect in core/block-editor store. */ export const stopMultiSelect = getBlockEditorAction( 'stopMultiSelect' ); /** * @see multiSelect in core/block-editor store. */ export const multiSelect = getBlockEditorAction( 'multiSelect' ); /** * @see clearSelectedBlock in core/block-editor store. */ export const clearSelectedBlock = getBlockEditorAction( 'clearSelectedBlock' ); /** * @see toggleSelection in core/block-editor store. */ export const toggleSelection = getBlockEditorAction( 'toggleSelection' ); /** * @see replaceBlocks in core/block-editor store. */ export const replaceBlocks = getBlockEditorAction( 'replaceBlocks' ); /** * @see replaceBlock in core/block-editor store. */ export const replaceBlock = getBlockEditorAction( 'replaceBlock' ); /** * @see moveBlocksDown in core/block-editor store. */ export const moveBlocksDown = getBlockEditorAction( 'moveBlocksDown' ); /** * @see moveBlocksUp in core/block-editor store. */ export const moveBlocksUp = getBlockEditorAction( 'moveBlocksUp' ); /** * @see moveBlockToPosition in core/block-editor store. */ export const moveBlockToPosition = getBlockEditorAction( 'moveBlockToPosition' ); /** * @see insertBlock in core/block-editor store. */ export const insertBlock = getBlockEditorAction( 'insertBlock' ); /** * @see insertBlocks in core/block-editor store. */ export const insertBlocks = getBlockEditorAction( 'insertBlocks' ); /** * @see showInsertionPoint in core/block-editor store. */ export const showInsertionPoint = getBlockEditorAction( 'showInsertionPoint' ); /** * @see hideInsertionPoint in core/block-editor store. */ export const hideInsertionPoint = getBlockEditorAction( 'hideInsertionPoint' ); /** * @see setTemplateValidity in core/block-editor store. */ export const setTemplateValidity = getBlockEditorAction( 'setTemplateValidity' ); /** * @see synchronizeTemplate in core/block-editor store. */ export const synchronizeTemplate = getBlockEditorAction( 'synchronizeTemplate' ); /** * @see mergeBlocks in core/block-editor store. */ export const mergeBlocks = getBlockEditorAction( 'mergeBlocks' ); /** * @see removeBlocks in core/block-editor store. */ export const removeBlocks = getBlockEditorAction( 'removeBlocks' ); /** * @see removeBlock in core/block-editor store. */ export const removeBlock = getBlockEditorAction( 'removeBlock' ); /** * @see toggleBlockMode in core/block-editor store. */ export const toggleBlockMode = getBlockEditorAction( 'toggleBlockMode' ); /** * @see startTyping in core/block-editor store. */ export const startTyping = getBlockEditorAction( 'startTyping' ); /** * @see stopTyping in core/block-editor store. */ export const stopTyping = getBlockEditorAction( 'stopTyping' ); /** * @see enterFormattedText in core/block-editor store. */ export const enterFormattedText = getBlockEditorAction( 'enterFormattedText' ); /** * @see exitFormattedText in core/block-editor store. */ export const exitFormattedText = getBlockEditorAction( 'exitFormattedText' ); /** * @see insertDefaultBlock in core/block-editor store. */ export const insertDefaultBlock = getBlockEditorAction( 'insertDefaultBlock' ); /** * @see updateBlockListSettings in core/block-editor store. */ export const updateBlockListSettings = getBlockEditorAction( 'updateBlockListSettings' );