@dndbuilder.com/react
TypeScript icon, indicating that this package has built-in type declarations

0.2.1 • Public • Published

@dndbuilder.com/react

A powerful drag-and-drop page builder for React applications. This package provides a comprehensive set of components, hooks, and utilities for building customizable page editors with a block-based approach.

Table of Contents

Features

  • 🧩 Block-Based Architecture: Build pages using pre-defined or custom blocks
  • 🖱️ Drag and Drop Interface: Intuitive drag-and-drop functionality using React DND
  • 🔄 Undo/Redo Support: Built-in history management with Redux Undo
  • 📱 Responsive Design: Create responsive layouts that work across devices
  • 🎨 Customizable UI: Extensive styling options with Tailwind CSS
  • 🧰 Extensible API: Easily extend with custom blocks and functionality
  • 🔌 Plugin System: Support for third-party plugins and extensions
  • 📦 Tree-Shakable: Import only what you need
  • 🌐 Server-Side Rendering: Compatible with Next.js for SSR
  • 🔍 TypeScript Support: Fully typed with TypeScript for better development experience
  • 🎨 Theme Support: Built-in theming system for consistent styling across your application

Installation

# Using npm
npm install @dndbuilder.com/react

# Using yarn
yarn add @dndbuilder.com/react

# Using pnpm
pnpm add @dndbuilder.com/react

Quick Start

import React, { useState } from "react";
import { Editor, BuilderProvider } from "@dndbuilder.com/react";
import { store } from "@dndbuilder.com/react";
import "@dndbuilder.com/react/dist/style.css";

// Basic editor configuration
const editorConfig = {
  blocks: [], // Your blocks will go here
  // Other configuration options
};

function App() {
  // Optional: Initial content for the editor
  const [initialContent, setInitialContent] = useState({});

  return (
    <BuilderProvider store={store}>
      <Editor content={initialContent} builderConfig={editorConfig} />
    </BuilderProvider>
  );
}

export default App;

Core Concepts

Editor

The Editor is the main component that provides the drag-and-drop interface for building pages. It manages the state of the page content and provides tools for editing blocks.

Blocks

Blocks are the building blocks of pages. Each block represents a specific type of content, such as headings, paragraphs, images, or more complex components like testimonials or pricing tables.

Controls

Controls are UI components that allow users to configure block settings. They provide interfaces for adjusting properties like text, colors, spacing, and other styling options.

Store

The store manages the state of the editor, including the content structure, selected blocks, and undo/redo history. It's built on Redux and provides a predictable state container.

API Reference

Components

The package exports several components for building and rendering pages:

  • Editor: The main editor component
  • BuilderProvider: Provider component for the editor state
import { Editor, BuilderProvider } from "@dndbuilder.com/react";

Server Components

For server-side rendering, you can use the RenderContent component to render content fetched from your backend

import { RenderContent } from "@dndbuilder.com/react/components/server";

Hooks

Custom hooks for accessing and manipulating the editor state:

  • useContent: Access and update the content state
  • useBuilderSelector: Select blocks and manage selection state
  • useBuilderDispatch: Dispatch actions to the editor store
  • useSettings: Access and update editor settings
  • useFieldName: Generate settings field names
  • useAction: Access editor actions like save, copy, paste, undo, redo, and panel management
  • useTheme: Access and update the current theme
import {
  useContent,
  useBuilderSelector,
  useBuilderDispatch,
  useSettings,
  useFieldName,
  useTheme,
} from "@dndbuilder.com/react/hooks";

Utilities

Utility functions for working with blocks and content:

  • createBlockConfig: Create a block configuration
  • createId: Generate unique IDs for blocks
  • generateResponsiveStyles: Generate responsive styles for blocks
  • generatePsuedoStyles: Generate pseudo styles for blocks
  • generateTypography: Generate typography styles
  • generateSpacing: Generate spacing styles
  • generateUnitValue: Generate unit values for styles
  • generateBoxShadow: Generate box shadow styles
  • generateBackground: Generate background styles
import {
  createBlockConfig,
  createId,
  generateResponsiveStyles,
  generatePsuedoStyles,
  generateTypography,
  generateSpacing,
  generateUnitValue,
  generateBoxShadow,
  generateBackground,
} from "@dndbuilder.com/react/utils";

Working with Content

Saving Content

To save content, you can use the useContent hook to access the editor state:

import { useContent } from "@dndbuilder.com/react/hooks";

function SaveButton() {
  const { content, saveContent } = useContent();

  const handleSave = async () => {
    // Save content to your backend or local storage
    try {
      await fetch("/api/save-content", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ content }),
      });
      saveContent(); // Mark content as saved
    } catch (error) {
      console.error("Failed to save content:", error);
    }
  };

  return <button onClick={handleSave}>Save Content</button>;
}

Rendering Content

To render content on the frontend, use the RenderContent component:

import { RenderContent } from "@dndbuilder.com/react/components/server";
import { editorConfig } from "./editorConfig"; // Your editor configuration

async function ContentPage() {
  // Fetch content from your backend
  const response = await fetch("/api/get-content");
  const { content } = await response.json();

  return (
    <div className="page-container">
      <RenderContent content={content} builderConfig={editorConfig} />
    </div>
  );
}

Customization

Creating Custom Blocks

To create a custom block, you need to:

  1. Create a component for your block
  2. Define the block configuration using createBlockConfig utility
  3. Include the block in your editor configuration

Here's a simplified example of creating a custom block:

// 1. Create your block component (my-block.tsx)
import React from "react";
import { BlockProps } from "@dndbuilder.com/react/types";

const MyBlock = ({ settings, meta }: BlockProps) => {
  return (
    <div className="my-custom-block">
      <h3>{settings.title}</h3>
      <p>{settings.description}</p>
    </div>
  );
};

export default MyBlock;

// 2. Create a control component (my-block-control.tsx)
import React from "react";
import { ControlProps } from "@dndbuilder.com/react/types";
import { TextInput } from "@dndbuilder.com/react/components";

const MyBlockControl = ({ settings, updateSettings }: ControlProps) => {
  return (
    <div className="control-panel">
      <TextInput
        label="Title"
        value={settings.title || ""}
        onChange={(value) => updateSettings({ title: value })}
      />
      <TextInput
        label="Description"
        value={settings.description || ""}
        onChange={(value) => updateSettings({ description: value })}
      />
    </div>
  );
};

export default MyBlockControl;

// 3. Define your block configuration (my-block.config.ts)
import { createBlockConfig } from "@dndbuilder.com/react/utils";
import { lazy } from "react";
import { FiBox } from "react-icons/fi";

const MyBlockConfig = createBlockConfig({
  type: "my-block",
  label: "My Custom Block",
  icon: FiBox,
  component: lazy(() => import("./my-block")),
  isVisible: () => true,
  group: "Custom",
  settings: {
    title: "Default Title",
    description: "Default description text",
  },
  controls: [
    {
      label: "Content",
      component: lazy(() => import("./my-block-control")),
    },
  ],
});

export default MyBlockConfig;

// 4. Include the block in your editor configuration
import MyBlockConfig from "./blocks/my-block/my-block.config";

export const editorConfig = {
  blocks: [
    MyBlockConfig,
    // Other blocks...
  ],
};

Overriding Existing Blocks

You can override the configuration of an existing block by extending it:

import { BlockType } from "@dndbuilder.com/react/types";
import { createBlockConfig } from "@dndbuilder.com/react/utils";
import { lazy } from "react";

// Override the Heading block configuration
const CustomHeadingConfig = createBlockConfig({
  type: BlockType.HEADING, // Use the existing block type
  component: lazy(() => import("./components/custom-heading.block")),
  // Override other properties as needed
  controls: [
    {
      label: "Custom Style",
      component: lazy(() => import("./components/custom-heading-style.control")),
    },
  ],
});

// Include the overridden block in your editor configuration
export const editorConfig = {
  blocks: [
    CustomHeadingConfig,
    // Other blocks...
  ],
};

Styling

You can customize the appearance of blocks by:

  1. Using the built-in style controls
  2. Providing custom CSS classes
  3. Implementing custom style functions
// Custom style function example
const MyBlockConfig = createBlockConfig({
  // ...other configuration
  style: ({ settings, breakpoints }) => {
    return {
      "& .my-custom-block": {
        backgroundColor: settings.backgroundColor,
        padding: `${settings.padding}px`,
        borderRadius: `${settings.borderRadius}px`,
        // Add responsive styles
        [breakpoints.md]: {
          flexDirection: "row",
        },
        [breakpoints.sm]: {
          flexDirection: "column",
        },
      },
    };
  },
});

Theming

The package provides a comprehensive theming system that allows you to customize the appearance of your application. Themes can be used to define colors, typography, spacing, and other visual aspects of your application.

Theme Structure

A theme consists of the following properties:

  • id: A unique identifier for the theme
  • name: A human-readable name for the theme
  • settings: An object containing the theme settings

The theme settings include:

  • layout: Container width, padding, and gap settings
  • color: Accent color, background color, text color, and color presets
  • typography: Typography settings for body text and headings
  • button: Button styling including typography, colors, borders, and shadows
  • link: Link styling including colors and typography
  • form: Form element styling including labels and inputs
  • customCss: Custom CSS to be applied globally

Using Themes

You can access and update the current theme using the useTheme hook:

import { useTheme } from "@dndbuilder.com/react/hooks";

function ThemeToggle() {
  const [theme, setTheme] = useTheme();

  const toggleDarkMode = () => {
    setTheme({
      ...theme,
      settings: {
        ...theme.settings,
        color: {
          ...theme.settings.color,
          backgroundColor:
            theme.settings.color.backgroundColor === "#ffffff" ? "#1a1a1a" : "#ffffff",
          textColor: theme.settings.color.textColor === "#1a1a1a" ? "#ffffff" : "#1a1a1a",
        },
      },
    });
  };

  return <button onClick={toggleDarkMode}>Toggle Dark Mode</button>;
}

Saving Themes

To save a theme, you can use the same approach as saving content:

import { useTheme } from "@dndbuilder.com/react/hooks";

function SaveThemeButton() {
  const [theme] = useTheme();

  const handleSave = async () => {
    try {
      await fetch("/api/save-theme", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ theme }),
      });
      console.log("Theme saved successfully");
    } catch (error) {
      console.error("Failed to save theme:", error);
    }
  };

  return <button onClick={handleSave}>Save Theme</button>;
}

Advanced Usage

Server-Side Rendering

The package supports server-side rendering (SSR) with Next.js.

// Next.js page component
import { RenderContent } from "@dndbuilder.com/react/components/server";
import { editorConfig } from "../editorConfig"; // Your editor configuration

export default function Page({ content }) {
  return <RenderContent content={content} builderConfig={editorConfig} />;
}

// Server-side data fetching
export async function getServerSideProps() {
  const response = await fetch("https://api.example.com/content");
  const content = await response.json();

  return {
    props: { content },
  };
}

Troubleshooting

Common Issues

  1. Block not rendering: Ensure the block component is correctly registered in the editor configuration.
  2. Styling issues: Check your CSS classes and ensure they are applied correctly.
  3. Type errors: Verify that your TypeScript types match the expected interfaces.

Support

Need help with @dndbuilder.com/react? We're here to assist you.

Getting Help

For more information, visit dndbuilder.com.

Package Sidebar

Install

npm i @dndbuilder.com/react

Weekly Downloads

1

Version

0.2.1

License

MIT

Unpacked Size

37.4 MB

Total Files

2947

Last publish

Collaborators

  • mostafizurhimself