GrapesJS React

repository·main·Indexed 41 days ago

https://github.com/grapesjs/react

An official wrapper for GrapesJS that enables developers to build custom, declarative user interfaces for the GrapesJS editor using React components. It provides the <GjsEditor /> and <Canvas /> components, along with hooks like useEditor() and useEditorMaybe() to interact with the GrapesJS API. The library includes specialized providers such as AssetsProvider and BlocksProvider to synchronize the GrapesJS Asset Manager and Block Manager state with the React lifecycle.

Tokens
10.3K
Snippets
26
Records
38
Agent score
51%

What's inside GrapesJS React

  1. Access the editor instance with useEditor hooks

    main

    To interact with the GrapesJS API from your custom React components, use the provided hooks. Because the editor is initialized asynchronously, you must handle the case where the editor might not be ready yet.

    • useEditor(): Returns the editor instance. Use this inside a component wrapped by <WithEditor /> to ensure the editor is always defined when the component renders.
    • useEditorMaybe(): Returns the editor instance if it exists, or undefined if it hasn't been created yet. Use this for components that need to render immediately regardless of the editor's state.
    • <WithEditor />: A wrapper component that prevents its children from rendering until the GrapesJS editor instance is fully created.
    import GjsEditor, { WithEditor, useEditor, useEditorMaybe } from '@grapesjs/react';
    
    function MyComponentWithUseEditor() {
        // The `editor` is always defined.
        const editor = useEditor();
        return (...);
    }
    
    function MyComponentWithUseEditorMaybe() {
        // The `editor` is not immediately available
        const editor = useEditorMaybe();
        return (
            <div
                <div>I will be rendered immediately</div
                <div
                    Editor: { editor ? 'created' : 'not yet created' }.
                </div
            </div>
        );
    }
    
    export default function CustomEditor() {
      return (
        <GjsEditor ...>
            <WithEditor>
                {/* This component won't be rendered until the editor is created */}
                <MyComponentWithUseEditor/>
            </WithEditor>
            <MyComponentWithUseEditorMaybe/>
        </GjsEditor>
      );
    }
  2. Run GrapesJS React with React 19 in Docker

    main

    To test the project using React 19, build the react19 service and then start the container. Once running, the project is accessible at http://localhost:5174/.

    docker compose build react19
    docker compose up react19
  3. Run GrapesJS React with React 18 in Docker

    main

    To test the project using React 18, build the react18 service and then start the container. Once running, the project is accessible at http://localhost:5173/.

    docker compose build react18
    docker compose up react18
  4. Build the base Docker image

    main

    The Dockerfile.base must be built first. It builds and mounts @grapesjs/react to the specific React version images. Note that the base is built using React 19.

    docker compose build base
  5. Build a Custom UI with <Canvas />

    main

    For full control over the editor's appearance, you can build a declarative UI using React components. By including the <Canvas /> component inside the <GjsEditor /> children, you disable the core default GrapesJS UI and define exactly where the editor canvas should be rendered within your own layout.

    import grapesjs, { Editor } from 'grapesjs';
    import GjsEditor, { Canvas } from '@grapesjs/react';
    
    export default function CustomEditor() {
      const onEditor = (editor: Editor) => {
        console.log('Editor loaded', { editor });
      };
    
      return (
        <GjsEditor
          grapesjs={grapesjs}
          grapesjsCss="https://unpkg.com/grapesjs/dist/css/grapes.min.css"
          onEditor={onEditor}
          options={{
            height: '100vh',
            storageManager: false,
          }}
        >
            <div>
            {/* ... use your UI components */}
                <Canvas /> {/* place the GrapesJS canvas where you wish */}
            {/* ... */}
            </div>
        </GjsEditor>
      );
    }
  6. Use GrapesJS Providers for custom UI components

    main

    The library provides several specialized Providers that allow you to build custom user interfaces by exposing specific parts of the GrapesJS state and API via React Context. Each provider typically offers a ResultProps type defining the shape of the data it exposes.

    Available Providers:

    • AssetsProvider: Accesses asset management data.
    • BlocksProvider: Accesses block manager data.
    • DevicesProvider: Accesses device/breakpoint data.
    • LayersProvider: Accesss layer/component tree data.
    • ModalProvider: Accesses modal management.
    • PagesProvider: Accesses page management.
    • SelectorsProvider: Accesses selector/element selection data.
    • StylesProvider: Accesses CSS/style management.
    • TraitsProvider: Accesses component trait/property data.
  7. Load plugins via CDN in EditorInstance

    main

    The EditorInstance component provides an enhanced plugins prop that allows you to load plugins asynchronously from a CDN, which is useful for reducing your initial bundle size.

    You can pass an array containing three types of plugin definitions:

    1. Asynchronous CDN Plugin: An object containing the plugin's id (the name GrapesJS uses to identify it), the src (the URL to the script), and an optional options object.
    2. Global Plugin: A string representing the name of a plugin that is already loaded in the global scope (e.g., via a <script> tag in your HTML).
    3. Local Plugin: A direct reference to a plugin function imported into your React component.
    plugins: [
      {
        id: 'gjs-blocks-basic',
        src: 'https://unpkg.com/grapesjs-blocks-basic',
        options: {}
      },
      'grapesjs-plugin-forms',
      myPluginFunction,
    ]
    plugins: [
      {
        // The id should be name of the plugin that will be actually loaded
        id: 'gjs-blocks-basic',
        src: 'https://unpkg.com/grapesjs-blocks-basic',
        options: {}
      }
      // plugin already loaded in the global scope (eg. loaded via CND in HTML)
      'grapesjs-plugin-forms',
      // plugin as a function
      myPlugin,
    ]
  8. Use the Default GrapesJS UI

    main

    The simplest way to use the wrapper is to rely on the default UI provided by GrapesJS. In this mode, all UI customization must be handled via the standard GrapesJS configuration and API, rather than through React components.

    Key props for <GjsEditor />:

    • grapesjs: The core GrapesJS library instance (required).
    • grapesjsCss: A URL to the GrapesJS CSS file (optional, can be imported directly in JS).
    • options: GrapesJS initialization options.
    • onEditor: Callback function that receives the Editor instance once loaded.
    import grapesjs, { Editor } from 'grapesjs';
    import GjsEditor from '@grapesjs/react';
    
    export default function DefaultEditor() {
      const onEditor = (editor: Editor) => {
        console.log('Editor loaded', { editor });
      };
    
      return (
        <GjsEditor
          // Pass the core GrapesJS library to the wrapper (required).
          // You can also pass the CDN url (eg. "https://unpkg.com/grapesjs")
          grapesjs={grapesjs}
          // Load the GrapesJS CSS file asynchronously from URL.
          // This is an optional prop, you can always import the CSS directly in your JS if you wish.
          grapesjsCss="https://unpkg.com/grapesjs/dist/css/grapes.min.css"
          // GrapesJS init options
          options={{
            height: '100vh',
            storageManager: false,
          }}
          onEditor={onEditor}
        />
      );
    }
  9. Use the EditorInstance component to embed GrapesJS

    main

    The EditorInstance component is the primary entry point for integrating GrapesJS into a React application. It handles the asynchronous loading of GrapesJS, its CSS, and various plugins, then initializes the editor within a provided container.

    Key Props

    • grapesjs: Either the grapesjs library object (imported from the grapesjs package) or a string URL to load the library via a script tag.
    • options: A standard GrapesJS EditorConfig object used to configure the editor instance.
    • grapesjsCss: A string URL to an external GrapesJS CSS file to be loaded asynchronously.
    • plugins: An array of plugins to load. This supports three formats:
      • CDN URL Object: { id: 'plugin-id', src: 'https://cdn.../plugin.js', options: {} } (the id must match the plugin's registered name).
      • String: The name of a plugin already available in the global scope (e.g., 'grapesjs-plugin-forms').
      • Function: A direct reference to a plugin function.
    • onEditor: Callback function called with the Editor instance immediately after creation.
    • onReady: Callback function called once the editor is fully mounted and data has been loaded from storage.
    • onUpdate: Callback function triggered on every project update. It receives the current ProjectData (JSON) and the Editor instance.
    • waitReady: If true, the component will render the provided ReactNode (or nothing) until the editor is ready. This prevents layout shifts or showing an uninitialized editor.

    Example Usage

    import EditorInstance from 'grapesjs-react/EditorInstance';
    import gjs from 'grapesjs';
    import 'grapesjs/dist/css/grapes.min.css';
    
    function MyEditor() {
      return (
        <EditorInstance
          grapesjs={gjs}
          options={{
            height: '500px',
            // ... other GrapesJS config
          }}
          plugins={[
            {
              id: 'gjs-blocks-basic',
              src: 'https://unpkg.com/grapesjs-blocks-basic',
              options: {}
            },
            'grapesjs-plugin-forms'
          ]}
          onReady={(editor) => {
            console.log('Editor is ready!', editor);
          }}
          onUpdate={(projectData, editor) => {
            console.log('Project updated:', projectData);
          }}
        />
      );
    }
    import EditorInstance from 'grapesjs-react/EditorInstance';
    import gjs from 'grapesjs';
    
    <EditorInstance
      grapesjs={gjs}
      options={{ height: '100%' }}
      plugins={[
        {
          id: 'gjs-blocks-basic',
          src: 'https://unpkg.com/grapesjs-blocks-basic',
          options: {}
        },
        'grapesjs-plugin-forms',
        myPluginFunction
      ]}
      onEditor={(editor) => console.log(editor)}
      onReady={(editor) => console.log(editor)}
      onUpdate={(data, editor) => console.log(data)}
      waitReady={true}
    />