diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/components/block-editor/block-editor.tsx b/mailpoet/assets/js/src/email_editor_custom/engine/components/block-editor/block-editor.tsx
index 3d777ca24d..0590c9f615 100644
--- a/mailpoet/assets/js/src/email_editor_custom/engine/components/block-editor/block-editor.tsx
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/components/block-editor/block-editor.tsx
@@ -1,6 +1,7 @@
import {
BlockEditorKeyboardShortcuts,
BlockEditorProvider,
+ BlockInspector,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore No types for this exist yet.
BlockTools,
@@ -10,6 +11,8 @@ import {
} from '@wordpress/block-editor';
import { useState } from '@wordpress/element';
+import { Sidebar } from '../sidebar/sidebar';
+
export function BlockEditor() {
const [documentBlocks, updateBlocks] = useState([]);
@@ -33,6 +36,9 @@ export function BlockEditor() {
onChange={(blocks) => updateBlocks(blocks)}
settings={{}}
>
+
+
+
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
{/* @ts-ignore BlockEditorKeyboardShortcuts.Register has no types */}
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/components/header/header.tsx b/mailpoet/assets/js/src/email_editor_custom/engine/components/header/header.tsx
index 277871cada..ef331f76fa 100644
--- a/mailpoet/assets/js/src/email_editor_custom/engine/components/header/header.tsx
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/components/header/header.tsx
@@ -1,3 +1,6 @@
+import { PinnedItems } from '@wordpress/interface';
+import { storeName } from '../../store';
+
export function Header() {
return (
@@ -5,7 +8,9 @@ export function Header() {
Todo Inserter etc.
Todo Email Name
-
Todo Actions
+
);
}
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/components/sidebar/sidebar.tsx b/mailpoet/assets/js/src/email_editor_custom/engine/components/sidebar/sidebar.tsx
new file mode 100644
index 0000000000..74780a8924
--- /dev/null
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/components/sidebar/sidebar.tsx
@@ -0,0 +1,33 @@
+import { createSlotFill, Panel } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+import { ComplementaryArea } from '@wordpress/interface';
+import { ComponentProps } from 'react';
+import { storeName, mainSidebarKey } from 'email_editor_custom/engine/store';
+import { drawerRight } from '@wordpress/icons';
+
+const { Slot: InspectorSlot, Fill: InspectorFill } = createSlotFill(
+ 'EmailEditorBlockInspector',
+);
+
+type Props = ComponentProps;
+
+export function Sidebar(props: Props): JSX.Element {
+ return (
+ Todo header}
+ icon={drawerRight}
+ scope={storeName}
+ smallScreenTitle={__('No title', 'mailpoet')}
+ isActiveByDefault
+ {...props}
+ >
+
+
+
+
+ );
+}
+
+Sidebar.InspectorFill = InspectorFill;
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/editor.tsx b/mailpoet/assets/js/src/email_editor_custom/engine/editor.tsx
index 9b0a3b83a5..f3d2f33939 100644
--- a/mailpoet/assets/js/src/email_editor_custom/engine/editor.tsx
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/editor.tsx
@@ -1,17 +1,38 @@
-import { InterfaceSkeleton } from '@wordpress/interface';
+import classnames from 'classnames';
+import { useSelect } from '@wordpress/data';
+import { InterfaceSkeleton, ComplementaryArea } from '@wordpress/interface';
import { StrictMode, createRoot } from '@wordpress/element';
import { registerCoreBlocks } from '@wordpress/block-library';
import { Popover, SlotFillProvider } from '@wordpress/components';
import { ShortcutProvider } from '@wordpress/keyboard-shortcuts';
import { Header } from './components/header';
import { BlockEditor } from './components/block-editor';
+import { Sidebar } from './components/sidebar/sidebar';
+import { createStore, storeName } from './store';
function Editor() {
+ const { isSidebarOpened } = useSelect(
+ (select) => ({
+ isSidebarOpened: select(storeName).isSidebarOpened(),
+ }),
+ [],
+ );
+
+ const className = classnames('interface-interface-skeleton', {
+ 'is-sidebar-opened': isSidebarOpened,
+ });
+
return (
- } content={} />
+
+ }
+ content={}
+ sidebar={}
+ />
@@ -20,6 +41,7 @@ function Editor() {
}
export function initialize(elementId: string) {
+ createStore();
const container = document.getElementById(elementId);
if (!container) {
return;
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/store/actions.ts b/mailpoet/assets/js/src/email_editor_custom/engine/store/actions.ts
new file mode 100644
index 0000000000..ecfaff42da
--- /dev/null
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/store/actions.ts
@@ -0,0 +1,17 @@
+import { dispatch } from '@wordpress/data';
+import { store as interfaceStore } from '@wordpress/interface';
+import { storeName } from './constants';
+
+export function toggleInserterSidebar() {
+ return {
+ type: 'TOGGLE_INSERTER_SIDEBAR',
+ } as const;
+}
+
+export const openSidebar = () => {
+ dispatch(interfaceStore).enableComplementaryArea(storeName);
+};
+
+export const closeSidebar = () => {
+ dispatch(interfaceStore).disableComplementaryArea(storeName);
+};
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/store/constants.ts b/mailpoet/assets/js/src/email_editor_custom/engine/store/constants.ts
new file mode 100644
index 0000000000..30f2cfe550
--- /dev/null
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/store/constants.ts
@@ -0,0 +1,3 @@
+export const storeName = 'email-editor/editor';
+
+export const mainSidebarKey = 'email-editor/editor/main';
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/store/index.ts b/mailpoet/assets/js/src/email_editor_custom/engine/store/index.ts
new file mode 100644
index 0000000000..d08c8ff609
--- /dev/null
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/store/index.ts
@@ -0,0 +1,3 @@
+export * from './constants';
+export * from './store';
+export * from './types';
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/store/initial_state.ts b/mailpoet/assets/js/src/email_editor_custom/engine/store/initial_state.ts
new file mode 100644
index 0000000000..e51decfa05
--- /dev/null
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/store/initial_state.ts
@@ -0,0 +1,9 @@
+import { State } from './types';
+
+export function getInitialState(): State {
+ return {
+ inserterSidebar: {
+ isOpened: false,
+ },
+ };
+}
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/store/reducer.ts b/mailpoet/assets/js/src/email_editor_custom/engine/store/reducer.ts
new file mode 100644
index 0000000000..db530081b1
--- /dev/null
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/store/reducer.ts
@@ -0,0 +1,16 @@
+import { State } from './types';
+
+export function reducer(state: State, action): State {
+ switch (action.type) {
+ case 'TOGGLE_INSERTER_SIDEBAR':
+ return {
+ ...state,
+ inserterSidebar: {
+ ...state.inserterSidebar,
+ isOpened: !state.inserterSidebar.isOpened,
+ },
+ };
+ default:
+ return state;
+ }
+}
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/store/selectors.ts b/mailpoet/assets/js/src/email_editor_custom/engine/store/selectors.ts
new file mode 100644
index 0000000000..967dee8012
--- /dev/null
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/store/selectors.ts
@@ -0,0 +1,8 @@
+import { createRegistrySelector } from '@wordpress/data';
+import { store as interfaceStore } from '@wordpress/interface';
+import { storeName } from './constants';
+
+export const isSidebarOpened = createRegistrySelector(
+ (select) => (): boolean =>
+ !!select(interfaceStore).getActiveComplementaryArea(storeName),
+);
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/store/store.ts b/mailpoet/assets/js/src/email_editor_custom/engine/store/store.ts
new file mode 100644
index 0000000000..3d515de8d3
--- /dev/null
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/store/store.ts
@@ -0,0 +1,47 @@
+import { createReduxStore, register } from '@wordpress/data';
+import {
+ ReduxStoreConfig,
+ StoreDescriptor as GenericStoreDescriptor,
+} from '@wordpress/data/build-types/types';
+import { controls } from '@wordpress/data-controls';
+import * as actions from './actions';
+import { storeName } from './constants';
+import { getInitialState } from './initial_state';
+import { reducer } from './reducer';
+import * as selectors from './selectors';
+
+const getConfig = () =>
+ ({
+ actions,
+ controls,
+ selectors,
+ reducer,
+ initialState: getInitialState(),
+ } as const);
+
+export type EditorStoreConfig = ReturnType;
+
+export const createStore = () => {
+ const store = createReduxStore(storeName, getConfig());
+ register(store);
+ return store;
+};
+
+export interface EmailEditorStore {
+ getActions(): EditorStoreConfig['actions'];
+ getSelectors(): EditorStoreConfig['selectors'];
+}
+
+declare module '@wordpress/data' {
+ interface StoreMap {
+ [storeName]: GenericStoreDescriptor<
+ ReduxStoreConfig<
+ unknown,
+ ReturnType,
+ ReturnType
+ >
+ >;
+ }
+}
+
+export { actions, selectors };
diff --git a/mailpoet/assets/js/src/email_editor_custom/engine/store/types.ts b/mailpoet/assets/js/src/email_editor_custom/engine/store/types.ts
new file mode 100644
index 0000000000..cbfe98c46a
--- /dev/null
+++ b/mailpoet/assets/js/src/email_editor_custom/engine/store/types.ts
@@ -0,0 +1,5 @@
+export type State = {
+ inserterSidebar: {
+ isOpened: boolean;
+ };
+};
diff --git a/mailpoet/assets/js/src/types/wordpress-modules.ts b/mailpoet/assets/js/src/types/wordpress-modules.ts
index 5cd5029caf..d6d8d6dfed 100644
--- a/mailpoet/assets/js/src/types/wordpress-modules.ts
+++ b/mailpoet/assets/js/src/types/wordpress-modules.ts
@@ -48,9 +48,11 @@ declare module '@wordpress/edit-post' {
// there are no @types/wordpress__interface yet
declare module '@wordpress/interface' {
import { StoreDescriptor } from '@wordpress/data/build-types/types';
+ import * as interfaceActions from '@wordpress/interface/src/store/actions';
export const store: { name: 'core/interface' } & StoreDescriptor<{
reducer: () => unknown;
+ actions: typeof interfaceActions;
selectors: {
getActiveComplementaryArea: (
state: unknown,