diff --git a/packages/js/product-editor/changelog/update-handle-modal-editor-from-store b/packages/js/product-editor/changelog/update-handle-modal-editor-from-store new file mode 100644 index 00000000000..13287682bd5 --- /dev/null +++ b/packages/js/product-editor/changelog/update-handle-modal-editor-from-store @@ -0,0 +1,4 @@ +Significance: patch +Type: add + +[Product Block Editor]: introduce UI state diff --git a/packages/js/product-editor/src/blocks/product-fields/description/edit.tsx b/packages/js/product-editor/src/blocks/product-fields/description/edit.tsx index edc33457ee5..4e2e1078000 100644 --- a/packages/js/product-editor/src/blocks/product-fields/description/edit.tsx +++ b/packages/js/product-editor/src/blocks/product-fields/description/edit.tsx @@ -2,13 +2,14 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; -import { createElement, useState } from '@wordpress/element'; +import { createElement } from '@wordpress/element'; import { BlockAttributes, BlockInstance, parse, serialize, } from '@wordpress/blocks'; +import { useSelect, useDispatch } from '@wordpress/data'; import { Button } from '@wordpress/components'; import { useWooBlockProps } from '@woocommerce/block-templates'; import { recordEvent } from '@woocommerce/tracks'; @@ -21,6 +22,7 @@ import { ContentPreview } from '../../../components/content-preview'; import { ModalEditor } from '../../../components/modal-editor'; import { ProductEditorBlockEditProps } from '../../../types'; import ModalEditorWelcomeGuide from '../../../components/modal-editor-welcome-guide'; +import { store as productEditorUiStore } from '../../../store/product-editor-ui'; /** * Internal dependencies @@ -50,19 +52,26 @@ export function DescriptionBlockEdit( { attributes, }: ProductEditorBlockEditProps< BlockAttributes > ) { const blockProps = useWooBlockProps( attributes ); - const [ isModalOpen, setIsModalOpen ] = useState( false ); const [ description, setDescription ] = useEntityProp< string >( 'postType', 'product', 'description' ); + // Check if the Modal editor is open from the store. + const isModalEditorOpen = useSelect( ( select ) => { + return select( productEditorUiStore ).isModalEditorOpen(); + }, [] ); + + const { openModalEditor, closeModalEditor } = + useDispatch( productEditorUiStore ); + return (
- { isModalOpen && ( + + { isModalEditorOpen && ( { @@ -79,14 +89,16 @@ export function DescriptionBlockEdit( { ); setDescription( html ); } } - onClose={ () => setIsModalOpen( false ) } + onClose={ closeModalEditor } title={ __( 'Edit description', 'woocommerce' ) } /> ) } + { !! description.length && ( ) } - { isModalOpen && } + + { isModalEditorOpen && }
); } diff --git a/packages/js/product-editor/src/index.ts b/packages/js/product-editor/src/index.ts index ad5ae2a28fb..55964e55a03 100644 --- a/packages/js/product-editor/src/index.ts +++ b/packages/js/product-editor/src/index.ts @@ -1,3 +1,8 @@ +/** + * Internal dependencies + */ +import registerProductEditorUiStore from './store/product-editor-ui'; + export * from './components'; export { DETAILS_SECTION_ID, @@ -16,6 +21,11 @@ export * from './types'; */ export * from './utils'; +/* + * Store + */ +export * from './store/product-editor-ui'; + /** * Hooks */ @@ -23,3 +33,6 @@ export * from './hooks'; export { PostTypeContext } from './contexts/post-type-context'; export { useValidation, useValidations } from './contexts/validation-context'; export * from './contexts/validation-context/types'; + +// Init the store +registerProductEditorUiStore(); diff --git a/packages/js/product-editor/src/store/product-editor-ui/Readme.md b/packages/js/product-editor/src/store/product-editor-ui/Readme.md new file mode 100644 index 00000000000..e11c8b40b13 --- /dev/null +++ b/packages/js/product-editor/src/store/product-editor-ui/Readme.md @@ -0,0 +1,29 @@ +# WooCommerce Product Editor UI Store + +This module provides a @wordpress/data store for managing the UI state of a WooCommerce Product Editor. + +## Structure + +Defines action types for the UI state: +- `ACTION_MODAL_EDITOR_OPEN` +- `ACTION_MODAL_EDITOR_CLOSE` + +### Actions + +- `openModalEditor` +- `closeModalEditor` + +### Selectors + +Selector function: + +- `isModalEditorOpen` + + +### Store + +Registers the WooCommerce Product Editor UI store with the following: + +- Store Name: `woo/product-editor-ui` + +## Usage diff --git a/packages/js/product-editor/src/store/product-editor-ui/actions.ts b/packages/js/product-editor/src/store/product-editor-ui/actions.ts new file mode 100644 index 00000000000..3e1c44fe03e --- /dev/null +++ b/packages/js/product-editor/src/store/product-editor-ui/actions.ts @@ -0,0 +1,20 @@ +/** + * Internal dependencies + */ +import { + ACTION_MODAL_EDITOR_CLOSE, + ACTION_MODAL_EDITOR_OPEN, +} from './constants'; + +const modalEditorActions = { + openModalEditor: () => ( { + type: ACTION_MODAL_EDITOR_OPEN, + } ), + closeModalEditor: () => ( { + type: ACTION_MODAL_EDITOR_CLOSE, + } ), +}; + +export default { + ...modalEditorActions, +}; diff --git a/packages/js/product-editor/src/store/product-editor-ui/constants.ts b/packages/js/product-editor/src/store/product-editor-ui/constants.ts new file mode 100644 index 00000000000..5fe6baa0ee0 --- /dev/null +++ b/packages/js/product-editor/src/store/product-editor-ui/constants.ts @@ -0,0 +1,5 @@ +/** + * Full editor actions + */ +export const ACTION_MODAL_EDITOR_OPEN = 'MODAL_EDITOROPEN'; +export const ACTION_MODAL_EDITOR_CLOSE = 'MODAL_EDITORCLOSE'; diff --git a/packages/js/product-editor/src/store/product-editor-ui/index.ts b/packages/js/product-editor/src/store/product-editor-ui/index.ts new file mode 100644 index 00000000000..d3029a0be3a --- /dev/null +++ b/packages/js/product-editor/src/store/product-editor-ui/index.ts @@ -0,0 +1,26 @@ +/** + * External dependencies + */ +import { createReduxStore, register } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import actions from './actions'; +import selectors from './selectors'; +import reducer from './reducer'; +/** + * Types + */ + +export const store = 'woo/product-editor-ui'; + +const wooProductEditorUiStore = createReduxStore( store, { + actions, + selectors, + reducer, +} ); + +export default function registerProductEditorUiStore() { + register( wooProductEditorUiStore ); +} diff --git a/packages/js/product-editor/src/store/product-editor-ui/reducer.ts b/packages/js/product-editor/src/store/product-editor-ui/reducer.ts new file mode 100644 index 00000000000..8f48c3fb27f --- /dev/null +++ b/packages/js/product-editor/src/store/product-editor-ui/reducer.ts @@ -0,0 +1,44 @@ +/** + * Internal dependencies + */ +import { + ACTION_MODAL_EDITOR_CLOSE, + ACTION_MODAL_EDITOR_OPEN, +} from './constants'; +import type { + ProductEditorModalEditorAction, + ProductEditorUIStateProps, +} from './types'; + +/** + * Types & Constants + */ +const INITIAL_STATE: ProductEditorUIStateProps = { + modalEditor: { + isOpen: false, + }, +}; + +export default function reducer( + state = INITIAL_STATE, + action: ProductEditorModalEditorAction +) { + switch ( action.type ) { + case ACTION_MODAL_EDITOR_OPEN: + return { + ...state, + modalEditor: { + isOpen: true, + }, + }; + case ACTION_MODAL_EDITOR_CLOSE: + return { + ...state, + modalEditor: { + isOpen: false, + }, + }; + } + + return state; +} diff --git a/packages/js/product-editor/src/store/product-editor-ui/selectors.ts b/packages/js/product-editor/src/store/product-editor-ui/selectors.ts new file mode 100644 index 00000000000..bced6734a3b --- /dev/null +++ b/packages/js/product-editor/src/store/product-editor-ui/selectors.ts @@ -0,0 +1,13 @@ +/** + * Internal dependencies + */ + +import type { ProductEditorUIStateProps } from './types'; + +export default { + isModalEditorOpen: function isModalEditorOpen( + state: ProductEditorUIStateProps + ) { + return state.modalEditor.isOpen; + }, +}; diff --git a/packages/js/product-editor/src/store/product-editor-ui/types.ts b/packages/js/product-editor/src/store/product-editor-ui/types.ts new file mode 100644 index 00000000000..1ef8c1a8e04 --- /dev/null +++ b/packages/js/product-editor/src/store/product-editor-ui/types.ts @@ -0,0 +1,17 @@ +/** + * Internal dependencies + */ +import { + ACTION_MODAL_EDITOR_CLOSE, + ACTION_MODAL_EDITOR_OPEN, +} from './constants'; + +export type ProductEditorUIStateProps = { + modalEditor: { + isOpen: boolean; + }; +}; + +export type ProductEditorModalEditorAction = { + type: typeof ACTION_MODAL_EDITOR_OPEN | typeof ACTION_MODAL_EDITOR_CLOSE; +};