@dndbuilder.com/react
Version:
Drag and drop builder for React
518 lines (402 loc) • 14.8 kB
Markdown
# @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
- [@dndbuilder.com/react](#dndbuildercomreact)
- [Table of Contents](#table-of-contents)
- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Core Concepts](#core-concepts)
- [Editor](#editor)
- [Blocks](#blocks)
- [Controls](#controls)
- [Store](#store)
- [API Reference](#api-reference)
- [Components](#components)
- [Server Components](#server-components)
- [Hooks](#hooks)
- [Utilities](#utilities)
- [Working with Content](#working-with-content)
- [Saving Content](#saving-content)
- [Rendering Content](#rendering-content)
- [Customization](#customization)
- [Creating Custom Blocks](#creating-custom-blocks)
- [Overriding Existing Blocks](#overriding-existing-blocks)
- [Styling](#styling)
- [Theming](#theming)
- [Theme Structure](#theme-structure)
- [Using Themes](#using-themes)
- [Saving Themes](#saving-themes)
- [Advanced Usage](#advanced-usage)
- [Server-Side Rendering](#server-side-rendering)
- [Troubleshooting](#troubleshooting)
- [Common Issues](#common-issues)
- [Support](#support)
- [Getting Help](#getting-help)
## 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
This package is published to npm and can be installed directly without any additional authentication.
### Install the Package
Simply run one of the following commands in your project:
```bash
# Using npm
npm install @dndbuilder.com/react
# Using yarn
yarn add @dndbuilder.com/react
# Using pnpm
pnpm add @dndbuilder.com/react
```
No additional configuration or authentication tokens are required.
## Quick Start
```jsx
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
```jsx
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
```jsx
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
```jsx
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
```jsx
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:
```jsx
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:
```jsx
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:
```jsx
// 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:
```jsx
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
```jsx
// 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:
```jsx
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:
```jsx
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.
```jsx
// 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
- **Documentation**: Start with this README and visit our [comprehensive documentation](https://dndbuilder.com/docs)
- **Email Support**: Reach out to our support team at support@dndbuilder.com
- **Bug Reports**: Report issues through our [Github Repo](https://github.com/dndbuilder/project)
For more information, visit [dndbuilder.com](https://dndbuilder.com/).