email-builder-pro 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INTEGRATION.md +250 -0
- package/PUBLISH.md +116 -0
- package/README.md +158 -0
- package/app/globals.css +46 -0
- package/components/Canvas.tsx +78 -0
- package/components/ComponentPalette.tsx +297 -0
- package/components/ComponentRenderer.tsx +496 -0
- package/components/DraggableComponent.tsx +84 -0
- package/components/DroppableComponent.tsx +80 -0
- package/components/EmailBuilder.tsx +59 -0
- package/components/ImageUpload.tsx +186 -0
- package/components/NumberInput.tsx +73 -0
- package/components/PreviewPanel.tsx +125 -0
- package/components/PropertiesPanel.tsx +1386 -0
- package/components/TemplateManager.tsx +104 -0
- package/components/Toolbar.tsx +242 -0
- package/lib/store.ts +198 -0
- package/package.json +76 -0
- package/postcss.config.js +8 -0
- package/src/index.tsx +42 -0
- package/tailwind.config.js +29 -0
- package/types/email.ts +22 -0
package/INTEGRATION.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Integration Guide
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install email-builder-pro
|
|
7
|
+
# or
|
|
8
|
+
yarn add email-builder-pro
|
|
9
|
+
# or
|
|
10
|
+
pnpm add email-builder-pro
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
### 1. Install Peer Dependencies
|
|
16
|
+
|
|
17
|
+
The package requires these peer dependencies:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install react react-dom next
|
|
21
|
+
npm install react-dnd react-dnd-html5-backend
|
|
22
|
+
npm install zustand lucide-react
|
|
23
|
+
npm install @react-email/components
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Configure Tailwind CSS
|
|
27
|
+
|
|
28
|
+
Add to your `tailwind.config.js`:
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
module.exports = {
|
|
32
|
+
content: [
|
|
33
|
+
'./node_modules/email-builder-pro/**/*.{js,ts,jsx,tsx}',
|
|
34
|
+
// ... your other content paths
|
|
35
|
+
],
|
|
36
|
+
theme: {
|
|
37
|
+
extend: {
|
|
38
|
+
colors: {
|
|
39
|
+
primary: {
|
|
40
|
+
50: '#f0f9ff',
|
|
41
|
+
100: '#e0f2fe',
|
|
42
|
+
// ... add primary colors
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
plugins: [],
|
|
48
|
+
};
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3. Import Styles
|
|
52
|
+
|
|
53
|
+
In your `app/globals.css` or main CSS file:
|
|
54
|
+
|
|
55
|
+
```css
|
|
56
|
+
@import 'email-builder-pro/app/globals.css';
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or copy the Tailwind directives if needed.
|
|
60
|
+
|
|
61
|
+
## Basic Usage
|
|
62
|
+
|
|
63
|
+
### Simple Integration
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
'use client';
|
|
67
|
+
|
|
68
|
+
import EmailBuilder from 'email-builder-pro';
|
|
69
|
+
import 'email-builder-pro/app/globals.css';
|
|
70
|
+
|
|
71
|
+
export default function EmailBuilderPage() {
|
|
72
|
+
return (
|
|
73
|
+
<div className="h-screen">
|
|
74
|
+
<EmailBuilder />
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### With Callbacks
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
'use client';
|
|
84
|
+
|
|
85
|
+
import EmailBuilder from 'email-builder-pro';
|
|
86
|
+
import { useEmailBuilder } from 'email-builder-pro';
|
|
87
|
+
|
|
88
|
+
export default function EmailBuilderPage() {
|
|
89
|
+
const handleSave = (components: any[]) => {
|
|
90
|
+
console.log('Components saved:', components);
|
|
91
|
+
// Save to your backend
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const handleExport = (type: 'html' | 'react', components: any[]) => {
|
|
95
|
+
console.log(`Exporting as ${type}:`, components);
|
|
96
|
+
// Handle export
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<div className="h-screen">
|
|
101
|
+
<EmailBuilder
|
|
102
|
+
onSave={handleSave}
|
|
103
|
+
onExport={handleExport}
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Advanced Usage with Store
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
'use client';
|
|
114
|
+
|
|
115
|
+
import { useEmailBuilder } from 'email-builder-pro';
|
|
116
|
+
import EmailBuilder from 'email-builder-pro';
|
|
117
|
+
|
|
118
|
+
export default function CustomEmailBuilder() {
|
|
119
|
+
const { components, templates, saveTemplate } = useEmailBuilder();
|
|
120
|
+
|
|
121
|
+
// Access store directly
|
|
122
|
+
React.useEffect(() => {
|
|
123
|
+
console.log('Components updated:', components);
|
|
124
|
+
}, [components]);
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div className="h-screen">
|
|
128
|
+
<EmailBuilder />
|
|
129
|
+
{/* Your custom UI */}
|
|
130
|
+
</div>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Next.js App Router Setup
|
|
136
|
+
|
|
137
|
+
### app/layout.tsx
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import type { Metadata } from 'next';
|
|
141
|
+
import { Inter } from 'next/font/google';
|
|
142
|
+
import 'email-builder-pro/app/globals.css';
|
|
143
|
+
|
|
144
|
+
const inter = Inter({ subsets: ['latin'] });
|
|
145
|
+
|
|
146
|
+
export const metadata: Metadata = {
|
|
147
|
+
title: 'Email Builder',
|
|
148
|
+
description: 'Build email templates',
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export default function RootLayout({
|
|
152
|
+
children,
|
|
153
|
+
}: {
|
|
154
|
+
children: React.ReactNode;
|
|
155
|
+
}) {
|
|
156
|
+
return (
|
|
157
|
+
<html lang="en">
|
|
158
|
+
<body className={inter.className}>{children}</body>
|
|
159
|
+
</html>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### app/page.tsx
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
'use client';
|
|
168
|
+
|
|
169
|
+
import EmailBuilder from 'email-builder-pro';
|
|
170
|
+
|
|
171
|
+
export default function Home() {
|
|
172
|
+
return <EmailBuilder />;
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Customization
|
|
177
|
+
|
|
178
|
+
### Custom Theme
|
|
179
|
+
|
|
180
|
+
Override Tailwind colors in your config:
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
// tailwind.config.js
|
|
184
|
+
module.exports = {
|
|
185
|
+
theme: {
|
|
186
|
+
extend: {
|
|
187
|
+
colors: {
|
|
188
|
+
primary: {
|
|
189
|
+
// Your custom primary colors
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Custom Components
|
|
198
|
+
|
|
199
|
+
You can extend the component library by importing individual components:
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
import { ComponentPalette, Canvas, PropertiesPanel } from 'email-builder-pro';
|
|
203
|
+
|
|
204
|
+
// Build your custom layout
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## API Reference
|
|
208
|
+
|
|
209
|
+
### EmailBuilder Component
|
|
210
|
+
|
|
211
|
+
Props:
|
|
212
|
+
- `onSave?: (components: EmailComponent[]) => void` - Called when template is saved
|
|
213
|
+
- `onExport?: (type: 'html' | 'react', components: EmailComponent[]) => void` - Called on export
|
|
214
|
+
- `initialComponents?: EmailComponent[]` - Initial components to load
|
|
215
|
+
- `className?: string` - Additional CSS classes
|
|
216
|
+
|
|
217
|
+
### useEmailBuilder Hook
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
- `components: EmailComponent[]` - Current components
|
|
221
|
+
- `selectedComponent: string | null` - Selected component ID
|
|
222
|
+
- `templates: EmailTemplate[]` - Saved templates
|
|
223
|
+
- `addComponent()` - Add a component
|
|
224
|
+
- `removeComponent(id)` - Remove a component
|
|
225
|
+
- `updateComponent(id, props)` - Update component props
|
|
226
|
+
- `saveTemplate(name)` - Save current template
|
|
227
|
+
- `loadTemplate(template)` - Load a template
|
|
228
|
+
- And more...
|
|
229
|
+
|
|
230
|
+
## Troubleshooting
|
|
231
|
+
|
|
232
|
+
### Tailwind Styles Not Working
|
|
233
|
+
|
|
234
|
+
Make sure:
|
|
235
|
+
1. Tailwind is configured correctly
|
|
236
|
+
2. Content paths include the package
|
|
237
|
+
3. Styles are imported
|
|
238
|
+
|
|
239
|
+
### Drag and Drop Not Working
|
|
240
|
+
|
|
241
|
+
Ensure `react-dnd` and `react-dnd-html5-backend` are installed.
|
|
242
|
+
|
|
243
|
+
### Build Errors
|
|
244
|
+
|
|
245
|
+
Check that all peer dependencies are installed and compatible versions.
|
|
246
|
+
|
|
247
|
+
## Support
|
|
248
|
+
|
|
249
|
+
For issues or questions, please open an issue on GitHub.
|
|
250
|
+
|
package/PUBLISH.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Publishing Email Builder to npm
|
|
2
|
+
|
|
3
|
+
This guide will help you publish the email-builder package to npm so it can be used in other projects.
|
|
4
|
+
|
|
5
|
+
## Step 1: Update Package Information
|
|
6
|
+
|
|
7
|
+
1. **Update `package.json`** with your information:
|
|
8
|
+
- Change `name` to your desired package name (e.g., `@your-org/email-builder` or `email-builder-pro`)
|
|
9
|
+
- Update `author`, `repository`, and `license` fields
|
|
10
|
+
- Update `version` (start with `1.0.0`)
|
|
11
|
+
|
|
12
|
+
2. **Or use the prepared `package-lib.json`**:
|
|
13
|
+
```bash
|
|
14
|
+
cp package-lib.json package.json
|
|
15
|
+
# Then edit package.json with your details
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Step 2: Create npm Account
|
|
19
|
+
|
|
20
|
+
If you don't have an npm account:
|
|
21
|
+
```bash
|
|
22
|
+
npm adduser
|
|
23
|
+
# Or visit https://www.npmjs.com/signup
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Step 3: Login to npm
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm login
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Step 4: Build the Package
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run build
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Step 5: Publish to npm
|
|
39
|
+
|
|
40
|
+
### For Public Package:
|
|
41
|
+
```bash
|
|
42
|
+
npm publish --access public
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### For Scoped Package (e.g., @your-org/email-builder):
|
|
46
|
+
```bash
|
|
47
|
+
npm publish --access public
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### For Private Package:
|
|
51
|
+
```bash
|
|
52
|
+
npm publish
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Step 6: Using in Other Projects
|
|
56
|
+
|
|
57
|
+
After publishing, install in other projects:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm install @your-org/email-builder
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then use it:
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import EmailBuilder from '@your-org/email-builder';
|
|
67
|
+
import '@your-org/email-builder/dist/globals.css';
|
|
68
|
+
|
|
69
|
+
function App() {
|
|
70
|
+
return (
|
|
71
|
+
<div>
|
|
72
|
+
<EmailBuilder
|
|
73
|
+
onSave={(components) => console.log('Saved:', components)}
|
|
74
|
+
onExport={(type, components) => console.log('Export:', type, components)}
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Version Updates
|
|
82
|
+
|
|
83
|
+
To publish updates:
|
|
84
|
+
|
|
85
|
+
1. Update version in `package.json`:
|
|
86
|
+
```bash
|
|
87
|
+
npm version patch # 1.0.0 -> 1.0.1
|
|
88
|
+
npm version minor # 1.0.0 -> 1.1.0
|
|
89
|
+
npm version major # 1.0.0 -> 2.0.0
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
2. Build and publish:
|
|
93
|
+
```bash
|
|
94
|
+
npm run build
|
|
95
|
+
npm publish
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Important Notes
|
|
99
|
+
|
|
100
|
+
- Make sure `.npmignore` excludes unnecessary files
|
|
101
|
+
- Test the package locally before publishing: `npm pack`
|
|
102
|
+
- The package requires Next.js and React as peer dependencies
|
|
103
|
+
- Users need to configure Tailwind CSS in their projects
|
|
104
|
+
|
|
105
|
+
## Local Testing
|
|
106
|
+
|
|
107
|
+
Test the package locally before publishing:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# In email-builder directory
|
|
111
|
+
npm pack
|
|
112
|
+
|
|
113
|
+
# In another project
|
|
114
|
+
npm install ../email-builder/email-builder-1.0.0.tgz
|
|
115
|
+
```
|
|
116
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Email Builder - Custom Email Template Builder
|
|
2
|
+
|
|
3
|
+
A fully functional, drag-and-drop email template builder built with Next.js, React, and React Email. Create beautiful, responsive email templates with an intuitive visual interface.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install email-builder-pro
|
|
9
|
+
# or
|
|
10
|
+
yarn add email-builder-pro
|
|
11
|
+
# or
|
|
12
|
+
pnpm add email-builder-pro
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
> **Note:** Before publishing, update the package name in `package.json` with your organization/username.
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
See [INTEGRATION.md](./INTEGRATION.md) for detailed integration instructions.
|
|
20
|
+
|
|
21
|
+
## Publishing to npm
|
|
22
|
+
|
|
23
|
+
See [PUBLISH.md](./PUBLISH.md) for instructions on publishing this package to npm.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- 🎨 **Drag & Drop Interface** - Intuitive component-based email building
|
|
28
|
+
- 🧩 **Component Library** - Pre-built components (Text, Heading, Button, Image, Container, Divider, Spacer, Row, Column)
|
|
29
|
+
- 🎯 **Live Preview** - Real-time preview of your email template
|
|
30
|
+
- ⚙️ **Properties Panel** - Customize component properties with a visual editor
|
|
31
|
+
- 💾 **Template Management** - Save and load email templates
|
|
32
|
+
- 📤 **Export Options** - Export as HTML or React Email component
|
|
33
|
+
- 🎨 **Modern UI** - Beautiful, responsive interface built with Tailwind CSS
|
|
34
|
+
|
|
35
|
+
## Getting Started
|
|
36
|
+
|
|
37
|
+
### Prerequisites
|
|
38
|
+
|
|
39
|
+
- Node.js 18+ and npm
|
|
40
|
+
|
|
41
|
+
### Installation
|
|
42
|
+
|
|
43
|
+
1. Install dependencies:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm install
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
2. Run the development server:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm run dev
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
3. Open [http://localhost:3000](http://localhost:3000) in your browser.
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
### Building an Email Template
|
|
60
|
+
|
|
61
|
+
1. **Add Components**: Drag components from the left palette onto the canvas
|
|
62
|
+
2. **Select Components**: Click on any component to select and edit it
|
|
63
|
+
3. **Edit Properties**: Use the right panel to customize component properties
|
|
64
|
+
4. **Preview**: Click the "Preview" button to see a live preview
|
|
65
|
+
5. **Save Template**: Click "Save" to save your template for later use
|
|
66
|
+
6. **Export**: Export your template as HTML or React Email component
|
|
67
|
+
|
|
68
|
+
### Available Components
|
|
69
|
+
|
|
70
|
+
- **Layout Components**
|
|
71
|
+
- Container: Wrapper with customizable background and padding
|
|
72
|
+
- Row: Horizontal layout container
|
|
73
|
+
- Column: Vertical layout container
|
|
74
|
+
- Spacer: Add vertical spacing
|
|
75
|
+
|
|
76
|
+
- **Content Components**
|
|
77
|
+
- Text: Paragraph text with styling options
|
|
78
|
+
- Heading: H1-H4 headings
|
|
79
|
+
- Divider: Horizontal line separator
|
|
80
|
+
|
|
81
|
+
- **Media Components**
|
|
82
|
+
- Image: Image with URL, alt text, and sizing
|
|
83
|
+
|
|
84
|
+
- **Action Components**
|
|
85
|
+
- Button: Call-to-action button with link
|
|
86
|
+
|
|
87
|
+
### Export Options
|
|
88
|
+
|
|
89
|
+
- **HTML Export**: Export as standalone HTML file
|
|
90
|
+
- **React Email Export**: Export as React Email component using @react-email/components
|
|
91
|
+
|
|
92
|
+
## Project Structure
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
email-builder/
|
|
96
|
+
├── app/ # Next.js app directory
|
|
97
|
+
│ ├── layout.tsx # Root layout
|
|
98
|
+
│ ├── page.tsx # Main page
|
|
99
|
+
│ └── globals.css # Global styles
|
|
100
|
+
├── components/ # React components
|
|
101
|
+
│ ├── EmailBuilder.tsx # Main builder component
|
|
102
|
+
│ ├── Canvas.tsx # Drag-and-drop canvas
|
|
103
|
+
│ ├── ComponentPalette.tsx # Component library
|
|
104
|
+
│ ├── PropertiesPanel.tsx # Property editor
|
|
105
|
+
│ ├── PreviewPanel.tsx # Live preview
|
|
106
|
+
│ ├── Toolbar.tsx # Top toolbar
|
|
107
|
+
│ ├── TemplateManager.tsx # Template management
|
|
108
|
+
│ └── ComponentRenderer.tsx # Component renderer
|
|
109
|
+
├── lib/ # Utilities
|
|
110
|
+
│ └── store.ts # Zustand state management
|
|
111
|
+
├── types/ # TypeScript types
|
|
112
|
+
│ └── email.ts # Email component types
|
|
113
|
+
└── emails/ # Email templates (from react-email-starter)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Technologies Used
|
|
117
|
+
|
|
118
|
+
- **Next.js 14** - React framework
|
|
119
|
+
- **React 19** - UI library
|
|
120
|
+
- **TypeScript** - Type safety
|
|
121
|
+
- **Tailwind CSS** - Styling
|
|
122
|
+
- **React DnD** - Drag and drop functionality
|
|
123
|
+
- **Zustand** - State management
|
|
124
|
+
- **React Email** - Email component library
|
|
125
|
+
- **Lucide React** - Icons
|
|
126
|
+
|
|
127
|
+
## Development
|
|
128
|
+
|
|
129
|
+
### Available Scripts
|
|
130
|
+
|
|
131
|
+
- `npm run dev` - Start development server
|
|
132
|
+
- `npm run build` - Build for production
|
|
133
|
+
- `npm run start` - Start production server
|
|
134
|
+
- `npm run lint` - Run ESLint
|
|
135
|
+
- `npm run email:dev` - Start React Email preview server
|
|
136
|
+
- `npm run email:export` - Export email templates
|
|
137
|
+
|
|
138
|
+
## Customization
|
|
139
|
+
|
|
140
|
+
### Adding New Components
|
|
141
|
+
|
|
142
|
+
1. Add component definition to `components/ComponentPalette.tsx`
|
|
143
|
+
2. Add rendering logic to `components/ComponentRenderer.tsx`
|
|
144
|
+
3. Add property editor to `components/PropertiesPanel.tsx`
|
|
145
|
+
|
|
146
|
+
### Styling
|
|
147
|
+
|
|
148
|
+
The project uses Tailwind CSS. Customize colors and styles in `tailwind.config.js`.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT License
|
|
153
|
+
|
|
154
|
+
## Contributing
|
|
155
|
+
|
|
156
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
157
|
+
|
|
158
|
+
|
package/app/globals.css
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
:root {
|
|
6
|
+
--foreground-rgb: 0, 0, 0;
|
|
7
|
+
--background-start-rgb: 214, 219, 220;
|
|
8
|
+
--background-end-rgb: 255, 255, 255;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
body {
|
|
12
|
+
color: rgb(var(--foreground-rgb));
|
|
13
|
+
background: linear-gradient(
|
|
14
|
+
to bottom,
|
|
15
|
+
transparent,
|
|
16
|
+
rgb(var(--background-end-rgb))
|
|
17
|
+
)
|
|
18
|
+
rgb(var(--background-start-rgb));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@layer utilities {
|
|
22
|
+
.text-balance {
|
|
23
|
+
text-wrap: balance;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Custom scrollbar */
|
|
28
|
+
::-webkit-scrollbar {
|
|
29
|
+
width: 8px;
|
|
30
|
+
height: 8px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
::-webkit-scrollbar-track {
|
|
34
|
+
background: #f1f1f1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
::-webkit-scrollbar-thumb {
|
|
38
|
+
background: #888;
|
|
39
|
+
border-radius: 4px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
::-webkit-scrollbar-thumb:hover {
|
|
43
|
+
background: #555;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useDrop } from 'react-dnd';
|
|
4
|
+
import { useEmailBuilder } from '@/lib/store';
|
|
5
|
+
import DraggableComponent from './DraggableComponent';
|
|
6
|
+
import { EmailComponent } from '@/types/email';
|
|
7
|
+
|
|
8
|
+
export default function Canvas() {
|
|
9
|
+
const { components, addComponent, selectedComponent, selectComponent } =
|
|
10
|
+
useEmailBuilder();
|
|
11
|
+
|
|
12
|
+
const [{ isOver }, drop] = useDrop({
|
|
13
|
+
accept: ['component', 'existing-component'],
|
|
14
|
+
drop: (item: { type?: string; defaultProps?: Record<string, any>; id?: string }, monitor) => {
|
|
15
|
+
// Only handle drop if it wasn't handled by a nested droppable
|
|
16
|
+
if (monitor.didDrop()) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// Only handle new component drops (not reordering)
|
|
20
|
+
if (item.type && item.defaultProps) {
|
|
21
|
+
// Generate unique ID with timestamp and random number
|
|
22
|
+
const newComponent: EmailComponent = {
|
|
23
|
+
id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
24
|
+
type: item.type as EmailComponent['type'],
|
|
25
|
+
props: item.defaultProps,
|
|
26
|
+
};
|
|
27
|
+
addComponent(newComponent);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
collect: (monitor) => ({
|
|
31
|
+
isOver: monitor.isOver({ shallow: true }) && !monitor.didDrop(),
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className="flex-1 flex flex-col bg-gray-100">
|
|
37
|
+
<div className="p-4 border-b border-gray-200 bg-white">
|
|
38
|
+
<h2 className="text-sm font-semibold text-gray-700">Canvas</h2>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div
|
|
42
|
+
ref={drop as any}
|
|
43
|
+
className={`flex-1 overflow-y-auto p-8 ${
|
|
44
|
+
isOver ? 'bg-primary-50' : 'bg-gray-50'
|
|
45
|
+
} transition-colors`}
|
|
46
|
+
onClick={(e) => {
|
|
47
|
+
if (e.target === e.currentTarget) {
|
|
48
|
+
selectComponent(null);
|
|
49
|
+
}
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
{components.length === 0 ? (
|
|
53
|
+
<div className="flex items-center justify-center h-full">
|
|
54
|
+
<div className="text-center">
|
|
55
|
+
<p className="text-gray-400 text-lg mb-2">
|
|
56
|
+
Drag components here to start building
|
|
57
|
+
</p>
|
|
58
|
+
<p className="text-gray-300 text-sm">
|
|
59
|
+
Select a component from the left panel
|
|
60
|
+
</p>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
) : (
|
|
64
|
+
<div className="max-w-2xl mx-auto bg-white shadow-lg rounded-lg p-8">
|
|
65
|
+
{components.map((component, index) => (
|
|
66
|
+
<DraggableComponent
|
|
67
|
+
key={component.id}
|
|
68
|
+
component={component}
|
|
69
|
+
index={index}
|
|
70
|
+
/>
|
|
71
|
+
))}
|
|
72
|
+
</div>
|
|
73
|
+
)}
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|