UNPKG

@dndbuilder.com/react

Version:

Drag and drop builder for React

518 lines (402 loc) 14.8 kB
# @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/).