react-dragd
v1.0.3
Published
Drag-and-drop page builder and viewer for React.
Downloads
20
Readme
react-dragd
A drag-and-drop page builder and viewer library for React. Build dynamic, editable pages with a visual editor that supports text, images, buttons, shapes, and code blocks.
Features
- Dual Mode Operation - Switch between EDIT mode (full editor) and VIEW mode (read-only display)
- Drag & Drop Positioning - Move elements freely with smart alignment guides
- Multiple Component Types - Text, buttons, images, shapes, HTML/Markdown, and code blocks
- Rotation & Resize - Transform elements with corner handles and rotation controls
- Multi-Select - Shift+click or drag-to-select multiple elements
- Layer Management - Control z-index ordering (bring forward/send backward)
- Undo/Redo - Full history tracking with keyboard shortcuts
- Google Fonts - Access to all Google Fonts for text elements
- Code Editor - Monaco editor integration with syntax highlighting
- State Persistence - Save and load page layouts as JSON
- Mobile Support - Touch-friendly with responsive scaling
Installation
npm install react-dragdQuick Start
import DragDrop from "react-dragd";
import "react-dragd/dist/index.css";
export default function App() {
return (
<div className="App">
<DragDrop
mode="edit"
onChangedCallback={(items) => console.log('Changed:', items)}
saveCallback={(items) => console.log('Saved:', items)}
/>
</div>
);
}Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| mode | 'edit' | 'view' | 'edit' | Editor mode - edit for full editor, view for read-only |
| initialState | object | {} | Load existing page state |
| onChangedCallback | function | - | Called when items are modified (debounced) |
| saveCallback | function | - | Called when user clicks the Save button |
| immutable | boolean | false | Hide the save button when true |
| pending | boolean | false | Show loading state |
Usage Examples
Edit Mode with Auto-Save
<DragDrop
mode="edit"
onChangedCallback={(items) => {
// Auto-save as user makes changes
localStorage.setItem('page-draft', JSON.stringify(items));
}}
saveCallback={(items) => {
// Save to your backend
api.savePage(items);
}}
/>View Mode (Read-Only)
<DragDrop
mode="view"
initialState={savedPageData}
/>Load Existing State
const savedState = JSON.parse(localStorage.getItem('my-page'));
<DragDrop
mode="edit"
initialState={savedState}
saveCallback={(items) => {
localStorage.setItem('my-page', JSON.stringify(items));
}}
/>Available Components
| Component | Description | |-----------|-------------| | Text | Rich text with Google Fonts, sizing, and alignment | | Button | Link buttons or JavaScript action buttons | | Image | Upload images or use URLs | | Square | Colored rectangles with customizable borders | | Circle | Circular shapes with color fills |
Custom Components
You can register custom draggable components using the component registry system.
Creating a Custom Component
import { registerComponent } from "react-dragd/dist/Components";
import EditItem from "react-dragd/dist/Components/DDEditor/EditItem";
function MyCustomComponent(props) {
const { elemData, selected, mode } = props;
// Optional: Define custom control panel for editing
function PanelControls({ onLocalUpdate, elemData }) {
return (
<button onClick={() => onLocalUpdate({ customProp: 'new value' })}>
Update
</button>
);
}
return (
<EditItem
elemData={elemData}
selected={selected}
renderPanel={selected && PanelControls}
mode={mode}
>
{/* Your custom component content */}
<div style={{ width: '100%', height: '100%' }}>
{elemData.customProp || 'Default content'}
</div>
</EditItem>
);
}
// Register the component with a unique type and menu button
registerComponent({
type: 'my-custom',
Component: MyCustomComponent,
button: {
icon: 'fas fa-star',
label: 'Add My Component',
action: 'add',
object: {
type: 'my-custom',
size: { width: 150, height: 100 },
customProp: 'initial value',
},
},
});
export default MyCustomComponent;Component Props
Your custom component receives these props:
| Prop | Type | Description |
|------|------|-------------|
| elemData | object | The item's data (id, pos, size, rot, zIndex, type, and any custom properties) |
| selected | boolean | Whether this item is currently selected |
| mode | 'edit' | 'view' | Current editor mode |
EditItem Wrapper
Wrap your component in EditItem to get drag, resize, and rotation functionality:
| Prop | Type | Description |
|------|------|-------------|
| elemData | object | Pass through from props |
| selected | boolean | Pass through from props |
| mode | string | Pass through from props |
| renderPanel | function | false | Custom control panel component (shown when selected) |
| onLocalUpdate | function | Callback to update item properties |
Button Configuration
The button property in registerComponent adds your component to the editor toolbar:
| Property | Description |
|----------|-------------|
| icon | Font Awesome icon class (e.g., 'fas fa-star') |
| label | Tooltip text shown on hover |
| action | Use 'add' for simple components |
| object | Default properties for new instances (must include type) |
Registering Multiple Types
A single component can handle multiple types:
registerComponent({
type: ['type-a', 'type-b'],
Component: MyComponent
});Example: HTML/Markdown Component
See docs/components/DraggableHtml.js for a full example of a custom component with Monaco editor integration for editing HTML and Markdown content.
State Format
The editor state is a JSON object where each key is an item ID:
{
"item-uuid-123": {
id: "item-uuid-123",
type: "text",
pos: { x: 100, y: 50 },
size: { width: 200, height: 100 },
rot: { deg: 0 },
zIndex: 10000,
text: "Hello World",
style: {
fontFamily: "Arial",
fontSize: "24px",
color: "#000000"
}
}
}Development
Setup
# Install dependencies
npm install
# Start development (watch mode + demo server)
npm run dev
# Build for production
npm run buildProject Structure
react-dragd/
├── src/
│ ├── DragDrop.js # Main component
│ ├── Components/ # Draggable component types
│ ├── EditMenu/ # Editor toolbar and menus
│ └── index.css # Styles
├── docs/ # Next.js demo app
└── dist/ # Built outputRequirements
- React 16.8.0 or higher
- React DOM 16.8.0 or higher
License
ISC
