# @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.

[![Version](https://img.shields.io/npm/v/@dndbuilder.com/react)](https://www.npmjs.com/package/@dndbuilder.com/react)
[![License](https://img.shields.io/npm/l/@dndbuilder.com/react)](https://github.com/dndbuilder/project/blob/main/LICENSE)

## 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)
  - [Advanced Usage](#advanced-usage)
    - [Server-Side Rendering](#server-side-rendering)
  - [Troubleshooting](#troubleshooting)
    - [Common Issues](#common-issues)

## 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

## Installation

```bash
# Using npm
npm install @dndbuilder.com/react

# Using yarn
yarn add @dndbuilder.com/react

# Using pnpm
pnpm add @dndbuilder.com/react
```

## 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

```jsx
import {
  useContent,
  useBuilderSelector,
  useBuilderDispatch,
  useSettings,
  useFieldName,
} 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",
        },
      },
    };
  },
});
```

## 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.

For more information, visit [dndbuilder.com](https://dndbuilder.com/).
