diff --git a/src/edit.js b/src/edit.js
index 4bf015d0..bd509981 100644
--- a/src/edit.js
+++ b/src/edit.js
@@ -1,15 +1,21 @@
-import { TextControl } from "@wordpress/components";
+// This import is needed to ensure that the `wp.blockEditor` global is available
+// by the time this component gets loaded. The `Title` component consumes the
+// global but cannot import it because it shouldn't be loaded on the frontend of
+// the site.
+import "@wordpress/block-editor";
+
import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
+import Title from "./frontend/title";
export default function Edit({ attributes, setAttributes }) {
const blockProps = useBlockProps();
return (
<>
- setAttributes({ message: val })}
+ placeholder="Enter the Title"
/>
diff --git a/src/framework/view.js b/src/framework/view.js
index 8303fd1a..13a3c6f8 100644
--- a/src/framework/view.js
+++ b/src/framework/view.js
@@ -1,4 +1,4 @@
-import { hydrate } from "./wordpress-element";
+import { hydrate, EnvContext } from "./wordpress-element";
const blockTypes = new Map();
@@ -30,16 +30,18 @@ class GutenbergBlock extends HTMLElement {
const innerBlocks = this.querySelector("gutenberg-inner-blocks");
const Comp = blockTypes.get(blockType);
hydrate(
-
-
+
- ,
+ >
+
+
+ ,
this
);
});
diff --git a/src/framework/wordpress-blockeditor.js b/src/framework/wordpress-blockeditor.js
new file mode 100644
index 00000000..042ec3c8
--- /dev/null
+++ b/src/framework/wordpress-blockeditor.js
@@ -0,0 +1,9 @@
+import { useBlockEnvironment } from "./wordpress-element";
+
+export const RichText = ({ tagName: Tag, children, ...props }) => {
+ return useBlockEnvironment() === "edit" ? (
+
+ ) : (
+ {children}
+ );
+};
diff --git a/src/framework/wordpress-element.js b/src/framework/wordpress-element.js
index 4b8af41f..06a189f0 100644
--- a/src/framework/wordpress-element.js
+++ b/src/framework/wordpress-element.js
@@ -1,14 +1,36 @@
import {
useState as useReactState,
useEffect as useReactEffect,
+ useContext as useReactContext,
+ createContext,
} from "@wordpress/element";
export { hydrate } from "react-dom";
-// Dirty dirty trick
-export const isView = !window.wp.blockEditor;
+export const EnvContext = createContext(null);
+
+/**
+ * A React hook that returns the name of the environment.
+ *
+ * This is still a bit hacky. Ideally, Save components should support React
+ * hooks and all the environments (Edit, Save and Frontend) should populate a
+ * normal context. Also, more environments could be added in the future.
+ *
+ * @returns {"edit" | "save" | "frontend"}
+ */
+export const useBlockEnvironment = () => {
+ try {
+ const env = useReactContext(EnvContext);
+ if (env === "frontend") return "frontend";
+ return "edit";
+ } catch (e) {
+ return "save";
+ }
+};
const noop = () => {};
-export const useState = (init) => (isView ? useReactState(init) : [init, noop]);
+export const useState = (init) =>
+ useBlockEnvironment() !== "save" ? useReactState(init) : [init, noop];
-export const useEffect = (...args) => (isView ? useReactEffect(...args) : noop);
+export const useEffect = (...args) =>
+ useBlockEnvironment() !== "save" ? useReactEffect(...args) : noop;
diff --git a/src/frontend/title.js b/src/frontend/title.js
index 729fdc06..8433daff 100644
--- a/src/frontend/title.js
+++ b/src/frontend/title.js
@@ -1,3 +1,9 @@
-const Title = ({ message }) => {message}
;
+import { RichText } from "../framework/wordpress-blockeditor";
+
+const Title = ({ message, ...props }) => (
+
+ {message}
+
+);
export default Title;