vue-wswg-editor 0.0.9 → 0.0.11

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.
Files changed (56) hide show
  1. package/README.md +493 -20
  2. package/dist/style.css +1 -1
  3. package/dist/vue-wswg-editor.es.js +2431 -1895
  4. package/package.json +15 -8
  5. package/src/assets/styles/_mixins.scss +12 -17
  6. package/src/components/AddBlockItem/AddBlockItem.vue +5 -5
  7. package/src/components/BlockBrowser/BlockBrowser.vue +33 -3
  8. package/src/components/BlockEditorFieldNode/BlockEditorFieldNode.vue +79 -34
  9. package/src/components/BlockEditorFields/BlockEditorFields.vue +15 -6
  10. package/src/components/BlockImageFieldNode/BlockImageNode.vue +373 -0
  11. package/src/components/BlockMarginFieldNode/BlockMarginNode.vue +6 -4
  12. package/src/components/BlockRepeaterFieldNode/BlockRepeaterNode.vue +4 -2
  13. package/src/components/BrowserNavigation/BrowserNavigation.vue +2 -2
  14. package/src/components/EmptyState/EmptyState.vue +1 -1
  15. package/src/components/PageBlockList/PageBlockList.vue +1 -9
  16. package/src/components/PageBuilderSidebar/PageBuilderSidebar.vue +29 -10
  17. package/src/components/PageBuilderToolbar/PageBuilderToolbar.vue +4 -4
  18. package/src/components/PageRenderer/PageRenderer.vue +76 -24
  19. package/src/components/PageRenderer/blockModules.ts +32 -3
  20. package/src/components/PageRenderer/layoutModules.ts +32 -0
  21. package/src/components/PageSettings/PageSettings.vue +19 -11
  22. package/src/components/ResizeHandle/ResizeHandle.vue +10 -10
  23. package/src/components/WswgJsonEditor/WswgJsonEditor.vue +323 -117
  24. package/src/index.ts +2 -2
  25. package/src/style.css +10 -3
  26. package/src/types/Block.d.ts +1 -1
  27. package/src/util/fieldConfig.ts +29 -0
  28. package/src/util/registry.ts +30 -23
  29. package/src/util/validation.ts +178 -23
  30. package/src/vite-plugin.ts +27 -2
  31. package/types/vue-wswg-editor.d.ts +161 -0
  32. package/dist/types/components/AddBlockItem/AddBlockItem.vue.d.ts +0 -6
  33. package/dist/types/components/BlockBrowser/BlockBrowser.vue.d.ts +0 -2
  34. package/dist/types/components/BlockComponent/BlockComponent.vue.d.ts +0 -15
  35. package/dist/types/components/BlockEditorFieldNode/BlockEditorFieldNode.vue.d.ts +0 -15
  36. package/dist/types/components/BlockEditorFields/BlockEditorFields.vue.d.ts +0 -15
  37. package/dist/types/components/BlockMarginFieldNode/BlockMarginNode.vue.d.ts +0 -23
  38. package/dist/types/components/BlockRepeaterFieldNode/BlockRepeaterNode.vue.d.ts +0 -15
  39. package/dist/types/components/BrowserNavigation/BrowserNavigation.vue.d.ts +0 -5
  40. package/dist/types/components/EmptyState/EmptyState.vue.d.ts +0 -15
  41. package/dist/types/components/PageBlockList/PageBlockList.vue.d.ts +0 -19
  42. package/dist/types/components/PageBuilderSidebar/PageBuilderSidebar.vue.d.ts +0 -30
  43. package/dist/types/components/PageBuilderToolbar/PageBuilderToolbar.vue.d.ts +0 -28
  44. package/dist/types/components/PageRenderer/PageRenderer.vue.d.ts +0 -6
  45. package/dist/types/components/PageRenderer/blockModules.d.ts +0 -1
  46. package/dist/types/components/PageSettings/PageSettings.vue.d.ts +0 -15
  47. package/dist/types/components/ResizeHandle/ResizeHandle.vue.d.ts +0 -6
  48. package/dist/types/components/WswgJsonEditor/WswgJsonEditor.test.d.ts +0 -1
  49. package/dist/types/components/WswgJsonEditor/WswgJsonEditor.vue.d.ts +0 -40
  50. package/dist/types/index.d.ts +0 -7
  51. package/dist/types/util/fieldConfig.d.ts +0 -82
  52. package/dist/types/util/helpers.d.ts +0 -28
  53. package/dist/types/util/registry.d.ts +0 -20
  54. package/dist/types/util/validation.d.ts +0 -15
  55. package/dist/types/vite-plugin.d.ts +0 -9
  56. package/dist/vite-plugin.js +0 -53
package/README.md CHANGED
@@ -1,6 +1,31 @@
1
1
  # vue-wswg-editor
2
2
 
3
- A Vue 3 WYSIWYG JSON Editor component library.
3
+ A powerful Vue 3 WYSIWYG JSON editor component library for building visual page builders. Create, edit, and manage page content through an intuitive drag-and-drop interface with a comprehensive sidebar editor for block configuration.
4
+
5
+ ## Overview
6
+
7
+ `vue-wswg-editor` is a Vue 3 component library that provides a complete page builder solution. It enables developers to create visual editors where users can:
8
+
9
+ - **Drag and drop blocks** to build pages visually
10
+ - **Edit block properties** through a comprehensive sidebar editor
11
+ - **Preview pages** in real-time with responsive viewport controls
12
+ - **Manage page layouts** with customizable layout components
13
+ - **Define custom blocks** with field configurations and validation
14
+
15
+ The library uses a JSON-based data structure, making it easy to store, version, and transfer page configurations.
16
+
17
+ ## Features
18
+
19
+ - 🎨 **Visual Page Builder** - Intuitive drag-and-drop interface for building pages
20
+ - 📝 **Rich Field Editor** - Comprehensive sidebar with support for multiple field types
21
+ - 🎯 **Block Management** - Add, remove, reorder, and configure blocks with ease
22
+ - 📱 **Responsive Preview** - Preview pages in desktop and mobile viewports
23
+ - 🎨 **Customizable Layouts** - Support for multiple page layouts
24
+ - 🔧 **Field Validation** - Built-in validation with custom validator support
25
+ - 🎨 **Tailwind CSS** - Styled with Tailwind CSS for easy customization
26
+ - 📦 **TypeScript** - Full TypeScript support with comprehensive type definitions
27
+ - 🔌 **Vite Plugin** - Automatic block, layout, and field discovery via Vite plugin
28
+ - 🎯 **Zero Config Blocks** - Blocks are automatically discovered from your project structure
4
29
 
5
30
  ## Installation
6
31
 
@@ -8,27 +33,433 @@ A Vue 3 WYSIWYG JSON Editor component library.
8
33
  npm install vue-wswg-editor
9
34
  ```
10
35
 
11
- ## Usage
36
+ ### Peer Dependencies
37
+
38
+ The library requires Vue 3.4.0 or higher:
39
+
40
+ ```bash
41
+ npm install vue@^3.4.0
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ### 1. Install the Vite Plugin
47
+
48
+ The library requires a Vite plugin to automatically discover blocks, layouts, and fields from your project structure.
49
+
50
+ ```typescript
51
+ // vite.config.ts
52
+ import { defineConfig } from "vite";
53
+ import vue from "@vitejs/plugin-vue";
54
+ import { vueWswgEditorPlugin } from "vue-wswg-editor/vite-plugin";
55
+
56
+ export default defineConfig({
57
+ plugins: [
58
+ vue(),
59
+ vueWswgEditorPlugin({
60
+ rootDir: "@page-builder", // Path alias to your page-builder directory
61
+ }),
62
+ ],
63
+ resolve: {
64
+ alias: {
65
+ "@page-builder": fileURLToPath(new URL("./src/page-builder", import.meta.url)),
66
+ },
67
+ },
68
+ });
69
+ ```
70
+
71
+ ### 2. Create the Page Builder Directory Structure
72
+
73
+ Create a `page-builder` directory in your project with the following structure:
74
+
75
+ ```
76
+ src/
77
+ page-builder/
78
+ blocks/ # Block components
79
+ hero/
80
+ Hero.vue
81
+ fields.ts # Optional: Field definitions
82
+ divider/
83
+ Divider.vue
84
+ layout/ # Layout components
85
+ default.vue
86
+ marketing.vue
87
+ ```
88
+
89
+ ### 3. Create a Block Component
90
+
91
+ ```vue
92
+ <!-- src/page-builder/blocks/hero/Hero.vue -->
93
+ <template>
94
+ <section class="hero-section">
95
+ <h1>{{ heading }}</h1>
96
+ <p>{{ description }}</p>
97
+ </section>
98
+ </template>
99
+
100
+ <script setup lang="ts">
101
+ defineProps<{
102
+ heading: string;
103
+ description: string;
104
+ }>();
105
+ </script>
106
+ ```
107
+
108
+ ### 4. Define Block Fields (Optional)
109
+
110
+ ```typescript
111
+ // src/page-builder/blocks/hero/fields.ts
112
+ import { createField } from "vue-wswg-editor";
113
+
114
+ export default {
115
+ heading: createField({
116
+ type: "text",
117
+ label: "Heading",
118
+ required: true,
119
+ default: "Welcome",
120
+ }),
121
+ description: createField({
122
+ type: "textarea",
123
+ label: "Description",
124
+ rows: 4,
125
+ }),
126
+ };
127
+ ```
128
+
129
+ ### 5. Use the Editor Component
12
130
 
13
131
  ```vue
14
132
  <template>
15
- <WswgJsonEditor />
133
+ <WswgJsonEditor
134
+ v-model="pageData"
135
+ blocksKey="blocks"
136
+ settingsKey="settings"
137
+ :url="`/page`"
138
+ :showBrowserBar="true"
139
+ :editable="true"
140
+ defaultBlockMargin="small"
141
+ />
16
142
  </template>
17
143
 
18
144
  <script setup lang="ts">
145
+ import { ref } from "vue";
19
146
  import { WswgJsonEditor } from "vue-wswg-editor";
20
- // Import the CSS file for Tailwind styles
21
147
  import "vue-wswg-editor/style.css";
148
+
149
+ const pageData = ref({
150
+ blocks: [],
151
+ settings: {},
152
+ });
153
+ </script>
154
+ ```
155
+
156
+ ## Project Structure Requirements
157
+
158
+ The library requires a specific directory structure for automatic discovery:
159
+
160
+ ```
161
+ src/
162
+ page-builder/
163
+ blocks/ # Block components (required)
164
+ {blockName}/
165
+ {BlockName}.vue # Block component (PascalCase)
166
+ fields.ts # Field definitions (optional)
167
+ thumbnail.png # Block thumbnail (optional)
168
+ layout/ # Layout components (required)
169
+ {layoutName}.vue # Layout component
170
+ ```
171
+
172
+ ### Block Naming Convention
173
+
174
+ - Block directories should use **kebab-case** (e.g., `hero-section`)
175
+ - Block components should use **PascalCase** matching the directory name (e.g., `HeroSection.vue`)
176
+ - The library automatically matches block types to components using name variations
177
+
178
+ ### Layout Naming Convention
179
+
180
+ - Layout files should use **kebab-case** (e.g., `default.vue`, `marketing.vue`)
181
+ - Layouts are referenced by their filename (without extension)
182
+
183
+ ## API Reference
184
+
185
+ ### WswgJsonEditor Component
186
+
187
+ The main editor component for building and editing pages.
188
+
189
+ #### Props
190
+
191
+ | Prop | Type | Default | Description |
192
+ | ------------------------ | ------------------------------------------ | ------------ | ----------------------------------------------- |
193
+ | `modelValue` / `v-model` | `Record<string, any>` | - | Page data object containing blocks and settings |
194
+ | `editable` | `boolean` | `false` | Enable/disable editing mode |
195
+ | `loading` | `boolean` | `false` | Show loading state |
196
+ | `url` | `string` | `""` | URL displayed in browser navigation bar |
197
+ | `showBrowserBar` | `boolean` | `false` | Show browser navigation bar in preview |
198
+ | `blocksKey` | `string` | `"blocks"` | Key in pageData for blocks array |
199
+ | `settingsKey` | `string` | `"settings"` | Key in pageData for settings object |
200
+ | `defaultBlockMargin` | `"none" \| "small" \| "medium" \| "large"` | `"none"` | Default margin for blocks |
201
+
202
+ #### Slots
203
+
204
+ - `header` - Custom header content above the editor
205
+ - `toolbar` - Custom toolbar content
206
+ - `loading` - Custom loading state
207
+
208
+ #### Events
209
+
210
+ - `update:modelValue` - Emitted when page data changes
211
+
212
+ #### Example
213
+
214
+ ```vue
215
+ <WswgJsonEditor v-model="pageData" :editable="true" :showBrowserBar="true" defaultBlockMargin="small">
216
+ <template #header>
217
+ <div class="custom-header">My Page Editor</div>
218
+ </template>
219
+ <template #toolbar>
220
+ <button @click="save">Save</button>
221
+ </template>
222
+ </WswgJsonEditor>
223
+ ```
224
+
225
+ ### PageRenderer Component
226
+
227
+ Render pages without the editor interface. Useful for displaying pages in production.
228
+
229
+ ```vue
230
+ <template>
231
+ <PageRenderer
232
+ :blocks="pageData.blocks"
233
+ :layout="pageData.settings.layout"
234
+ :settings="pageData.settings"
235
+ :with-layout="true"
236
+ />
237
+ </template>
238
+
239
+ <script setup lang="ts">
240
+ import { PageRenderer } from "vue-wswg-editor";
22
241
  </script>
23
242
  ```
24
243
 
244
+ #### Props
245
+
246
+ | Prop | Type | Default | Description |
247
+ | ------------ | --------------------- | ----------- | ------------------------------------------ |
248
+ | `blocks` | `Block[]` | - | Array of block data |
249
+ | `layout` | `string` | `"default"` | Layout name to use |
250
+ | `settings` | `Record<string, any>` | `{}` | Page settings object |
251
+ | `withLayout` | `boolean` | `true` | Whether to wrap blocks in layout component |
252
+
253
+ ## Field Configuration
254
+
255
+ Fields define the editable properties of blocks. Use `createField` to define field configurations:
256
+
257
+ ```typescript
258
+ import { createField } from "vue-wswg-editor";
259
+
260
+ export default {
261
+ // Text input
262
+ title: createField({
263
+ type: "text",
264
+ label: "Title",
265
+ placeholder: "Enter title",
266
+ required: true,
267
+ }),
268
+
269
+ // Textarea
270
+ description: createField({
271
+ type: "textarea",
272
+ label: "Description",
273
+ rows: 4,
274
+ }),
275
+
276
+ // Number input
277
+ count: createField({
278
+ type: "number",
279
+ label: "Count",
280
+ default: 0,
281
+ min: 0,
282
+ max: 100,
283
+ }),
284
+
285
+ // Select dropdown
286
+ theme: createField({
287
+ type: "select",
288
+ label: "Theme",
289
+ options: [
290
+ { label: "Light", value: "light", id: "light" },
291
+ { label: "Dark", value: "dark", id: "dark" },
292
+ ],
293
+ }),
294
+
295
+ // Color picker
296
+ backgroundColor: createField({
297
+ type: "color",
298
+ label: "Background Color",
299
+ default: "#ffffff",
300
+ }),
301
+
302
+ // Repeater field
303
+ items: createField({
304
+ type: "repeater",
305
+ label: "Items",
306
+ fields: {
307
+ title: createField({ type: "text", label: "Title" }),
308
+ description: createField({ type: "textarea", label: "Description" }),
309
+ },
310
+ }),
311
+
312
+ // Margin field
313
+ margin: createField({
314
+ type: "margin",
315
+ label: "Margin",
316
+ default: { top: "small", bottom: "small" },
317
+ }),
318
+ };
319
+ ```
320
+
321
+ ### Supported Field Types
322
+
323
+ - `text` - Single-line text input
324
+ - `textarea` - Multi-line text input
325
+ - `number` - Number input with min/max/step
326
+ - `boolean` - Checkbox
327
+ - `email` - Email input with validation
328
+ - `url` - URL input with validation
329
+ - `select` - Dropdown select
330
+ - `checkbox` - Checkbox group
331
+ - `radio` - Radio button group
332
+ - `color` - Color picker
333
+ - `range` - Range slider
334
+ - `repeater` - Repeating field groups
335
+ - `margin` - Margin configuration (top/bottom)
336
+ - `info` - Read-only information display
337
+ - `custom` - Custom field component
338
+
339
+ ### Field Options
340
+
341
+ | Option | Type | Description |
342
+ | ------------- | --------------------------- | ---------------------------------- |
343
+ | `type` | `EditorFieldType` | Field type (required) |
344
+ | `label` | `string` | Field label |
345
+ | `description` | `string` | Help text below field |
346
+ | `placeholder` | `string` | Input placeholder |
347
+ | `required` | `boolean` | Whether field is required |
348
+ | `default` | `any` | Default value |
349
+ | `hidden` | `boolean` | Hide field from editor |
350
+ | `group` | `string` | Group field in sidebar |
351
+ | `options` | `Array<{label, value, id}>` | Options for select/radio/checkbox |
352
+ | `min` / `max` | `number` | Min/max for number/range |
353
+ | `step` | `number` | Step for number/range |
354
+ | `rows` | `number` | Rows for textarea |
355
+ | `validator` | `ValidatorFunction` | Custom validation function |
356
+ | `component` | `Component` | Custom component for `custom` type |
357
+
358
+ ## Utilities
359
+
360
+ ### Registry Functions
361
+
362
+ ```typescript
363
+ import { getLayouts, initialiseRegistry } from "vue-wswg-editor";
364
+
365
+ // Get all available layouts
366
+ const layouts = getLayouts();
367
+
368
+ // Initialize registry (called automatically by plugin)
369
+ await initialiseRegistry();
370
+ ```
371
+
372
+ ### Validation Functions
373
+
374
+ ```typescript
375
+ import { validateField, validateAllFields } from "vue-wswg-editor";
376
+
377
+ // Validate a single field
378
+ const result = await validateField(fieldConfig, value);
379
+
380
+ // Validate all fields in a block
381
+ const results = await validateAllFields(blockFields, blockData);
382
+ ```
383
+
384
+ ## Vite Plugin Configuration
385
+
386
+ The `vueWswgEditorPlugin` scans your project for blocks, layouts, and fields. It requires a `rootDir` option pointing to your page-builder directory.
387
+
388
+ ### Plugin Options
389
+
390
+ ```typescript
391
+ interface VueWswgEditorPluginOptions {
392
+ /**
393
+ * Root directory path (can use Vite aliases like "@page-builder")
394
+ * Example: "@/features/homepage" or "@page-builder"
395
+ */
396
+ rootDir: string;
397
+ }
398
+ ```
399
+
400
+ ### How It Works
401
+
402
+ The plugin creates virtual modules that are automatically populated:
403
+
404
+ - `vue-wswg-editor:blocks` - All block components
405
+ - `vue-wswg-editor:layouts` - All layout components
406
+ - `vue-wswg-editor:fields` - All field definition files
407
+ - `vue-wswg-editor:thumbnails` - Block thumbnail images
408
+
409
+ These virtual modules are used internally by the library to discover and load your components.
410
+
411
+ ## Page Data Structure
412
+
413
+ The library expects page data in the following format:
414
+
415
+ ```typescript
416
+ interface PageData {
417
+ blocks: Block[];
418
+ settings: {
419
+ layout?: string;
420
+ [key: string]: any;
421
+ };
422
+ }
423
+
424
+ interface Block {
425
+ id: string;
426
+ type: string;
427
+ [key: string]: any; // Block-specific properties
428
+ }
429
+ ```
430
+
431
+ Example:
432
+
433
+ ```json
434
+ {
435
+ "blocks": [
436
+ {
437
+ "id": "block-1",
438
+ "type": "hero",
439
+ "heading": "Welcome",
440
+ "description": "This is a hero section"
441
+ },
442
+ {
443
+ "id": "block-2",
444
+ "type": "divider"
445
+ }
446
+ ],
447
+ "settings": {
448
+ "layout": "default",
449
+ "title": "My Page"
450
+ }
451
+ }
452
+ ```
453
+
25
454
  ## Development
26
455
 
456
+ ### Setup
457
+
27
458
  ```bash
28
459
  # Install dependencies
29
460
  npm install
30
461
 
31
- # Run development server
462
+ # Run development server (watches for changes)
32
463
  npm run dev
33
464
 
34
465
  # Build library
@@ -37,13 +468,19 @@ npm run build
37
468
  # Run tests
38
469
  npm run test:unit
39
470
 
471
+ # Type check
472
+ npm run tscheck
473
+
474
+ # Lint
475
+ npm run lint
476
+
40
477
  # Format code
41
478
  npm run format-fix
42
479
  ```
43
480
 
44
- ## Local Development with npm link
481
+ ### Local Development with npm link
45
482
 
46
- To use this package locally in another project (e.g., the admin app) during development:
483
+ To use this package locally in another project during development:
47
484
 
48
485
  1. **Build the library** (required before linking):
49
486
 
@@ -51,28 +488,22 @@ To use this package locally in another project (e.g., the admin app) during deve
51
488
  npm run build
52
489
  ```
53
490
 
54
- 2. **Create a global symlink** in the vue-wswg-editor directory:
491
+ 2. **Create a global symlink**:
55
492
 
56
493
  ```bash
57
494
  npm link
58
495
  ```
59
496
 
60
- 3. **Link the package** in your consuming project (e.g., admin app):
497
+ 3. **Link the package** in your consuming project:
61
498
 
62
499
  ```bash
63
500
  cd /path/to/your/project
64
501
  npm link vue-wswg-editor
65
502
  ```
66
503
 
67
- 4. **Use the package** in your project as normal:
68
-
69
- ```vue
70
- <script setup lang="ts">
71
- import { WswgJsonEditor } from "vue-wswg-editor";
72
- </script>
73
- ```
504
+ 4. **Rebuild after changes**:
74
505
 
75
- **Note:** After making changes to the library, you'll need to rebuild (`npm run build`) for changes to be reflected in the consuming project. The development server (`npm run dev`) is useful for testing the library in isolation, but won't automatically update the linked package.
506
+ After making changes to the library, rebuild (`npm run build`) for changes to be reflected in the consuming project.
76
507
 
77
508
  To unlink:
78
509
 
@@ -86,6 +517,48 @@ npm unlink
86
517
 
87
518
  ## Project Structure
88
519
 
89
- - `src/components/` - Vue components
90
- - `src/index.ts` - Library entry point
91
- - `test/` - Test files
520
+ ```
521
+ vue-wswg-editor/
522
+ ├── src/
523
+ │ ├── components/ # Vue components
524
+ │ │ ├── WswgJsonEditor/ # Main editor component
525
+ │ │ ├── PageRenderer/ # Page renderer component
526
+ │ │ ├── BlockComponent/ # Block wrapper component
527
+ │ │ └── ... # Other components
528
+ │ ├── util/ # Utility functions
529
+ │ │ ├── fieldConfig.ts # Field configuration utilities
530
+ │ │ ├── registry.ts # Block/layout registry
531
+ │ │ └── validation.ts # Validation utilities
532
+ │ ├── types/ # TypeScript type definitions
533
+ │ ├── vite-plugin.ts # Vite plugin implementation
534
+ │ └── index.ts # Library entry point
535
+ ├── dist/ # Built library files
536
+ └── test/ # Test files
537
+ ```
538
+
539
+ ## TypeScript Support
540
+
541
+ The library includes comprehensive TypeScript definitions. All components, utilities, and types are fully typed.
542
+
543
+ ```typescript
544
+ import type { EditorFieldConfig, ValidatorFunction, ValidationResult } from "vue-wswg-editor";
545
+ ```
546
+
547
+ ## Browser Support
548
+
549
+ - Chrome (latest)
550
+ - Firefox (latest)
551
+ - Safari (latest)
552
+ - Edge (latest)
553
+
554
+ ## License
555
+
556
+ [Add your license here]
557
+
558
+ ## Contributing
559
+
560
+ [Add contributing guidelines here]
561
+
562
+ ## Related Projects
563
+
564
+ - [vue-wswg-demos](https://github.com/your-org/vue-wswg-demos) - Demo project showing how to use vue-wswg-editor