@entrypulse/builder 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/LICENCE +684 -0
- package/README.md +330 -0
- package/dist/assets/index-Bg5ec7pY.js +242 -0
- package/dist/assets/index-HF240Dm8.css +2 -0
- package/dist/index.html +15 -0
- package/package.json +92 -0
package/README.md
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
# EntryPulse
|
|
2
|
+
|
|
3
|
+
A customizable React form builder with drag-and-drop functionality and extensible toolbar actions.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install entry-pulse
|
|
9
|
+
# or
|
|
10
|
+
yarn add entry-pulse
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { EntryPulse } from 'entry-pulse';
|
|
17
|
+
import 'entry-pulse/styles.css';
|
|
18
|
+
|
|
19
|
+
function App() {
|
|
20
|
+
return <EntryPulse />;
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Custom Toolbar Actions
|
|
25
|
+
|
|
26
|
+
EntryPulse allows you to customize the toolbar by adding your own actions, overriding built-in actions, or hiding specific functionality.
|
|
27
|
+
|
|
28
|
+
### Adding Custom Actions
|
|
29
|
+
|
|
30
|
+
Use `createToolbarAction` to create custom toolbar buttons:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { EntryPulse, createToolbarAction } from 'entry-pulse';
|
|
34
|
+
import { Save, Globe } from 'lucide-react';
|
|
35
|
+
|
|
36
|
+
// Create a save action
|
|
37
|
+
const saveAction = createToolbarAction({
|
|
38
|
+
id: 'save',
|
|
39
|
+
icon: Save,
|
|
40
|
+
label: 'Save Form',
|
|
41
|
+
position: 'right',
|
|
42
|
+
order: -2, // Negative order places it before built-in right actions
|
|
43
|
+
onClick: (ctx) => {
|
|
44
|
+
// Access the current schema
|
|
45
|
+
const { schema } = ctx;
|
|
46
|
+
|
|
47
|
+
// Save to your backend
|
|
48
|
+
fetch('/api/forms', {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
body: JSON.stringify(schema)
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Create a publish action with dynamic disabled state
|
|
56
|
+
const publishAction = createToolbarAction({
|
|
57
|
+
id: 'publish',
|
|
58
|
+
icon: Globe,
|
|
59
|
+
label: 'Publish Form',
|
|
60
|
+
position: 'right',
|
|
61
|
+
order: -1,
|
|
62
|
+
// Disabled when form is empty
|
|
63
|
+
disabled: (ctx) => ctx.schema.elements.length === 0,
|
|
64
|
+
onClick: async (ctx) => {
|
|
65
|
+
await publishForm(ctx.schema);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
function App() {
|
|
70
|
+
return (
|
|
71
|
+
<EntryPulse
|
|
72
|
+
toolbarActions={[saveAction, publishAction]}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Creating Multiple Actions
|
|
79
|
+
|
|
80
|
+
Use `createToolbarActions` to create multiple actions at once:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { createToolbarActions } from 'entry-pulse';
|
|
84
|
+
import { Cloud, Settings, Share } from 'lucide-react';
|
|
85
|
+
|
|
86
|
+
const actions = createToolbarActions([
|
|
87
|
+
{
|
|
88
|
+
id: 'cloud-sync',
|
|
89
|
+
icon: Cloud,
|
|
90
|
+
label: 'Sync to Cloud',
|
|
91
|
+
position: 'right',
|
|
92
|
+
onClick: (ctx) => syncToCloud(ctx.schema)
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: 'settings',
|
|
96
|
+
icon: Settings,
|
|
97
|
+
label: 'Form Settings',
|
|
98
|
+
position: 'left',
|
|
99
|
+
onClick: (ctx) => openSettings()
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'share',
|
|
103
|
+
icon: Share,
|
|
104
|
+
label: 'Share Form',
|
|
105
|
+
position: 'right',
|
|
106
|
+
onClick: (ctx) => shareForm(ctx.schema.id)
|
|
107
|
+
}
|
|
108
|
+
]);
|
|
109
|
+
|
|
110
|
+
<EntryPulse toolbarActions={actions} />
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Toolbar Action Context
|
|
114
|
+
|
|
115
|
+
Every action receives a context object with access to the form state and actions:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
interface ToolbarActionContext {
|
|
119
|
+
// Current form schema
|
|
120
|
+
schema: FormSchema;
|
|
121
|
+
|
|
122
|
+
// Current mode ('design' or 'preview')
|
|
123
|
+
mode: 'design' | 'preview';
|
|
124
|
+
|
|
125
|
+
// Undo/redo availability
|
|
126
|
+
canUndo: boolean;
|
|
127
|
+
canRedo: boolean;
|
|
128
|
+
|
|
129
|
+
// Available actions
|
|
130
|
+
actions: {
|
|
131
|
+
undo: () => void;
|
|
132
|
+
redo: () => void;
|
|
133
|
+
loadSchema: (schema: FormSchema) => void;
|
|
134
|
+
exportSchema: () => FormSchema;
|
|
135
|
+
setMode: (mode: 'design' | 'preview') => void;
|
|
136
|
+
resetForm: () => void;
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Action Configuration Options
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
interface ToolbarAction {
|
|
145
|
+
// Unique identifier
|
|
146
|
+
id: string;
|
|
147
|
+
|
|
148
|
+
// Icon component (lucide-react or custom)
|
|
149
|
+
icon: LucideIcon | ComponentType<{ className?: string }>;
|
|
150
|
+
|
|
151
|
+
// Tooltip label
|
|
152
|
+
label: string;
|
|
153
|
+
|
|
154
|
+
// Position: 'left' | 'center' | 'right'
|
|
155
|
+
position: ToolbarActionPosition;
|
|
156
|
+
|
|
157
|
+
// Order within position (lower = earlier, default: 0)
|
|
158
|
+
order?: number;
|
|
159
|
+
|
|
160
|
+
// Click handler
|
|
161
|
+
onClick: (context: ToolbarActionContext) => void | Promise<void>;
|
|
162
|
+
|
|
163
|
+
// Static or dynamic disabled state
|
|
164
|
+
disabled?: boolean | ((context: ToolbarActionContext) => boolean);
|
|
165
|
+
|
|
166
|
+
// Visual variant: 'default' | 'ghost' | 'destructive'
|
|
167
|
+
variant?: ToolbarActionVariant;
|
|
168
|
+
|
|
169
|
+
// Static or dynamic hidden state
|
|
170
|
+
hidden?: boolean | ((context: ToolbarActionContext) => boolean);
|
|
171
|
+
|
|
172
|
+
// Override a built-in action
|
|
173
|
+
override?: BuiltinToolbarActionId;
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Overriding Built-in Actions
|
|
178
|
+
|
|
179
|
+
Replace built-in actions with custom implementations:
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
const customExportAction = createToolbarAction({
|
|
183
|
+
id: 'custom-export',
|
|
184
|
+
icon: Download,
|
|
185
|
+
label: 'Export to CSV',
|
|
186
|
+
position: 'right',
|
|
187
|
+
override: 'export', // Replaces the built-in export button
|
|
188
|
+
onClick: (ctx) => {
|
|
189
|
+
// Custom export logic
|
|
190
|
+
exportToCSV(ctx.schema);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Available built-in action IDs to override:
|
|
196
|
+
- `'undo'` - Undo button
|
|
197
|
+
- `'redo'` - Redo button
|
|
198
|
+
- `'export'` - Export button
|
|
199
|
+
- `'import'` - Import button
|
|
200
|
+
- `'reset'` - Reset/trash button
|
|
201
|
+
- `'design-mode'` - Design mode toggle
|
|
202
|
+
- `'preview-mode'` - Preview mode toggle
|
|
203
|
+
|
|
204
|
+
### Advanced Toolbar Configuration
|
|
205
|
+
|
|
206
|
+
Use `toolbarConfig` for more control:
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import { EntryPulse, ToolbarConfig } from 'entry-pulse';
|
|
210
|
+
|
|
211
|
+
const toolbarConfig: ToolbarConfig = {
|
|
212
|
+
// Custom actions
|
|
213
|
+
actions: [saveAction, publishAction],
|
|
214
|
+
|
|
215
|
+
// Hide specific built-in actions
|
|
216
|
+
hideBuiltinActions: ['reset', 'import'],
|
|
217
|
+
|
|
218
|
+
// Or use boolean flags
|
|
219
|
+
showUndoRedo: true, // default: true
|
|
220
|
+
showModeToggle: true, // default: true
|
|
221
|
+
showImportExport: false, // default: true
|
|
222
|
+
showReset: false // default: true
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
<EntryPulse toolbarConfig={toolbarConfig} />
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## EntryPulse Props
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
interface EntryPulseProps {
|
|
232
|
+
// Initial schema to load
|
|
233
|
+
initialSchema?: FormSchema;
|
|
234
|
+
|
|
235
|
+
// Callback when schema changes
|
|
236
|
+
onSchemaChange?: (schema: FormSchema) => void;
|
|
237
|
+
|
|
238
|
+
// Custom toolbar actions (shorthand)
|
|
239
|
+
toolbarActions?: ToolbarAction[];
|
|
240
|
+
|
|
241
|
+
// Full toolbar configuration
|
|
242
|
+
toolbarConfig?: ToolbarConfig;
|
|
243
|
+
|
|
244
|
+
// Callback for form submission in preview mode
|
|
245
|
+
onPreviewSubmit?: (data: Record<string, any>) => void;
|
|
246
|
+
|
|
247
|
+
// Show/hide element sidebar (default: true)
|
|
248
|
+
showElementSidebar?: boolean;
|
|
249
|
+
|
|
250
|
+
// Show/hide property panel (default: true)
|
|
251
|
+
showPropertyPanel?: boolean;
|
|
252
|
+
|
|
253
|
+
// Custom CSS class
|
|
254
|
+
className?: string;
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Examples
|
|
259
|
+
|
|
260
|
+
### Auto-save on Change
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
<EntryPulse
|
|
264
|
+
onSchemaChange={(schema) => {
|
|
265
|
+
localStorage.setItem('form-draft', JSON.stringify(schema));
|
|
266
|
+
}}
|
|
267
|
+
/>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Load Existing Form
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
const existingSchema = await fetch('/api/forms/123').then(r => r.json());
|
|
274
|
+
|
|
275
|
+
<EntryPulse
|
|
276
|
+
initialSchema={existingSchema}
|
|
277
|
+
toolbarActions={[saveAction]}
|
|
278
|
+
/>
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Minimal Interface
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
<EntryPulse
|
|
285
|
+
showElementSidebar={false}
|
|
286
|
+
showPropertyPanel={false}
|
|
287
|
+
toolbarConfig={{
|
|
288
|
+
showImportExport: false,
|
|
289
|
+
showReset: false
|
|
290
|
+
}}
|
|
291
|
+
/>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Using Preview Components Standalone
|
|
295
|
+
|
|
296
|
+
You can use the form preview components independently:
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
import { FormPreview, WizardForm, FormSchema } from 'entry-pulse';
|
|
300
|
+
|
|
301
|
+
// Regular form preview
|
|
302
|
+
<FormPreview
|
|
303
|
+
schema={mySchema}
|
|
304
|
+
onSubmit={(data) => handleSubmit(data)}
|
|
305
|
+
/>
|
|
306
|
+
|
|
307
|
+
// Wizard/multi-step form preview
|
|
308
|
+
<WizardForm
|
|
309
|
+
schema={myWizardSchema}
|
|
310
|
+
onSubmit={(data) => handleSubmit(data)}
|
|
311
|
+
/>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## TypeScript Support
|
|
315
|
+
|
|
316
|
+
EntryPulse is written in TypeScript and exports all types:
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
import type {
|
|
320
|
+
FormSchema,
|
|
321
|
+
FormElement,
|
|
322
|
+
ElementType,
|
|
323
|
+
ToolbarAction,
|
|
324
|
+
ToolbarConfig,
|
|
325
|
+
ToolbarActionContext,
|
|
326
|
+
} from 'entry-pulse';
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## License
|
|
330
|
+
See [LICENSE](LICENCE) for details.
|