I'm attempting to create a standalone version of Wordpress' Gutenberg block editor that will work independently of the Wordpress ecosystem. Ideally, I'd like to be able to simply use the Gutenberg editor in an existing React project as a React component.
I noticed the official repository featured a "storybook" directory which housed a React component at "storybook/stories/playground/index.js":
/**
* WordPress dependencies
*/
import "@wordpress/editor"; // This shouldn't be necessary
import { useEffect, useState } from "@wordpress/element";
import { BlockEditorKeyboardShortcuts, BlockEditorProvider, BlockList, BlockInspector, WritingFlow, ObserveTyping } from "@wordpress/block-editor";
import { Popover, SlotFillProvider, DropZoneProvider } from "@wordpress/components";
import { registerCoreBlocks } from "@wordpress/block-library";
import "@wordpress/format-library";
/**
* Internal dependencies
*/
import "./style.scss";
function App() {
const [blocks, updateBlocks] = useState([]);
useEffect(() => {
registerCoreBlocks();
}, []);
return (
<div className="playground">
<SlotFillProvider>
<DropZoneProvider>
<BlockEditorProvider
value={blocks}
onInput={updateBlocks}
onChange={updateBlocks}
>
<div className="playground__sidebar">
<BlockInspector />
</div>
<div className="editor-styles-wrapper">
<BlockEditorKeyboardShortcuts />
<WritingFlow>
<ObserveTyping>
<BlockList />
</ObserveTyping>
</WritingFlow>
</div>
<Popover.Slot />
</BlockEditorProvider>
</DropZoneProvider>
</SlotFillProvider>
</div>
);
}
export default {
title: "Playground|Block Editor"
};
export const _default = () => {
return <App />;
};
This looked like a perfect candidate to modify into a standalone component, so I modified it slightly so it would function in a new create-react-app project:
import React from "react";
import "@wordpress/editor"; // This shouldn't be necessary
import { useEffect, useState } from "@wordpress/element";
import { BlockEditorKeyboardShortcuts, BlockEditorProvider, BlockList, BlockInspector, WritingFlow, ObserveTyping } from "@wordpress/block-editor";
import { Popover, SlotFillProvider, DropZoneProvider } from "@wordpress/components";
import { registerCoreBlocks } from "@wordpress/block-library";
import "@wordpress/format-library";
import "./style.scss";
export default function App() {
const [blocks, updateBlocks] = useState([]);
useEffect(() => {
registerCoreBlocks();
}, []);
return (
<div className="playground">
<SlotFillProvider>
<DropZoneProvider>
<BlockEditorProvider value={blocks} onInput={updateBlocks} onChange={updateBlocks}>
<div className="playground__sidebar">
<BlockInspector />
</div>
<div className="editor-styles-wrapper">
<BlockEditorKeyboardShortcuts />
<WritingFlow>
<ObserveTyping>
<BlockList />
</ObserveTyping>
</WritingFlow>
</div>
<Popover.Slot />
</BlockEditorProvider>
</DropZoneProvider>
</SlotFillProvider>
</div>
);
}
I saw the component referenced a "style.scss" file (which in turn referenced 'editor-styles.scss' and 'reset.scss') so I copied those files into my new React project as well:
I saw in the "package.json" file in the Gutenberg repository that all of the Wordpress dependencies were being referenced via a "packages" directory, e.g.:
"@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma",
"@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot",
"@wordpress/babel-preset-default": "file:packages/babel-preset-default",
"@wordpress/base-styles": "file:packages/base-styles",
So I copied the "packages" directory from Gutenberg into my new React project and then added all of the Wordpress dependencies to my "package.json" file:
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.4.0",
"@testing-library/user-event": "^7.2.1",
"@wordpress/a11y": "file:packages/a11y",
"@wordpress/annotations": "file:packages/annotations",
"@wordpress/api-fetch": "file:packages/api-fetch",
"@wordpress/autop": "file:packages/autop",
"@wordpress/blob": "file:packages/blob",
"@wordpress/block-directory": "file:packages/block-directory",
"@wordpress/block-editor": "file:packages/block-editor",
"@wordpress/block-library": "file:packages/block-library",
"@wordpress/block-serialization-default-parser": "file:packages/block-serialization-default-parser",
"@wordpress/block-serialization-spec-parser": "file:packages/block-serialization-spec-parser",
"@wordpress/blocks": "file:packages/blocks",
"@wordpress/components": "file:packages/components",
"@wordpress/compose": "file:packages/compose",
"@wordpress/core-data": "file:packages/core-data",
"@wordpress/data": "file:packages/data",
"@wordpress/data-controls": "file:packages/data-controls",
"@wordpress/date": "file:packages/date",
"@wordpress/deprecated": "file:packages/deprecated",
"@wordpress/dom": "file:packages/dom",
"@wordpress/dom-ready": "file:packages/dom-ready",
"@wordpress/edit-post": "file:packages/edit-post",
"@wordpress/edit-site": "file:packages/edit-site",
"@wordpress/edit-widgets": "file:packages/edit-widgets",
"@wordpress/editor": "file:packages/editor",
"@wordpress/element": "file:packages/element",
"@wordpress/escape-html": "file:packages/escape-html",
"@wordpress/format-library": "file:packages/format-library",
"@wordpress/hooks": "file:packages/hooks",
"@wordpress/html-entities": "file:packages/html-entities",
"@wordpress/i18n": "file:packages/i18n",
"@wordpress/is-shallow-equal": "file:packages/is-shallow-equal",
"@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts",
"@wordpress/keycodes": "file:packages/keycodes",
"@wordpress/list-reusable-blocks": "file:packages/list-reusable-blocks",
"@wordpress/media-utils": "file:packages/media-utils",
"@wordpress/notices": "file:packages/notices",
"@wordpress/nux": "file:packages/nux",
"@wordpress/plugins": "file:packages/plugins",
"@wordpress/priority-queue": "file:packages/priority-queue",
"@wordpress/redux-routine": "file:packages/redux-routine",
"@wordpress/rich-text": "file:packages/rich-text",
"@wordpress/server-side-render": "file:packages/server-side-render",
"@wordpress/shortcode": "file:packages/shortcode",
"@wordpress/token-list": "file:packages/token-list",
"@wordpress/url": "file:packages/url",
"@wordpress/viewport": "file:packages/viewport",
"@wordpress/wordcount": "file:packages/wordcount",
"concurrently": "^5.0.2",
"css-loader": "^3.4.2",
"node-sass": "^4.13.0",
"node-sass-chokidar": "^1.4.0",
"node-watch": "^0.6.3",
"npm-run-all": "^4.1.5",
"postcss-loader": "^3.0.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-scripts": "3.3.0",
"sass-loader": "^8.0.2",
},
"devDependencies": {
"@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma",
"@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot",
"@wordpress/babel-preset-default": "file:packages/babel-preset-default",
"@wordpress/base-styles": "file:packages/base-styles",
"@wordpress/browserslist-config": "file:packages/browserslist-config",
"@wordpress/custom-templated-path-webpack-plugin": "file:packages/custom-templated-path-webpack-plugin",
"@wordpress/dependency-extraction-webpack-plugin": "file:packages/dependency-extraction-webpack-plugin",
"@wordpress/docgen": "file:packages/docgen",
"@wordpress/e2e-test-utils": "file:packages/e2e-test-utils",
"@wordpress/e2e-tests": "file:packages/e2e-tests",
"@wordpress/env": "file:packages/env",
"@wordpress/eslint-plugin": "file:packages/eslint-plugin",
"@wordpress/jest-console": "file:packages/jest-console",
"@wordpress/jest-preset-default": "file:packages/jest-preset-default",
"@wordpress/jest-puppeteer-axe": "file:packages/jest-puppeteer-axe",
"@wordpress/library-export-default-webpack-plugin": "file:packages/library-export-default-webpack-plugin",
"@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config",
"@wordpress/postcss-themes": "file:packages/postcss-themes",
"@wordpress/scripts": "file:packages/scripts"
},
Then ran "npm i" so that my React application could reference the Wordpress packages via import statements.
Now, when I run "npm start", the React application will launch in my browser, and the Gutenberg editor will be present, but none of the CSS/styles work:
I'm not entirely sure how to proceed. The application seems to function as desired (I can create, edit, and remove blocks), but the styles simply aren't present.
I attempted to compile the existing scss files (in the src, node_modules, and packages directories) via the following commands in packages.json:
"build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules --include-path ./packages src packages node_modules -o src --recursive --watch",
"watch-css": "npm run build-css && node-sass-chokidar --include-path ./src --include-path ./node_modules --include-path ./packages -o src --watch"
But the resulting style.css file, when imported to my index.html file, didn't seem to change anything. Any help would be greatly appreciated.
I discovered that there was another style.scss file in the storybook directory which, when placed into the root directory of my React application, along with updating the package.json scripts to:
"build-css": "node-sass-chokidar style.scss -o public/css",
"watch-css": "npm run build-css && node-sass-chokidar --include-path node_modules style.scss -o public/css --watch"
The styles were compiled correctly.