@dmitryvim/form-builder 0.1.29 → 0.1.33

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/README.md CHANGED
@@ -39,10 +39,11 @@ npm install @dmitryvim/form-builder
39
39
 
40
40
  - **🎯 Schema-driven forms**: JSON Schema v0.3 → Interactive forms with live preview
41
41
  - **📁 Advanced file handling**: Images, videos, documents with drag-and-drop and grid preview
42
- - **✅ Real-time validation**: Client-side validation with visual feedback and error display
42
+ - **✅ Real-time validation**: Client-side validation with visual feedback and error display
43
43
  - **🌍 Internationalization**: Built-in English/Russian support with extensible translation system
44
44
  - **🎨 Rich field types**: Text, textarea, number, select, file, files, and nested groups
45
45
  - **👁️ Read-only mode**: Display form data without editing capabilities
46
+ - **🔘 Action buttons**: Configurable buttons in readonly mode for custom interactions
46
47
  - **💾 Draft saving**: Save incomplete forms without validation
47
48
  - **🔧 Framework agnostic**: Works with any web stack (React, Vue, Angular, vanilla JS)
48
49
  - **📦 Zero dependencies**: Self-contained HTML/CSS/JavaScript
@@ -51,6 +52,7 @@ npm install @dmitryvim/form-builder
51
52
  ## Quick Examples
52
53
 
53
54
  ### Simple Contact Form
55
+
54
56
  ```json
55
57
  {
56
58
  "version": "0.3",
@@ -87,7 +89,8 @@ npm install @dmitryvim/form-builder
87
89
  }
88
90
  ```
89
91
 
90
- ### Advanced Product Form with Groups
92
+ ### Advanced Product Form with Actions
93
+
91
94
  ```json
92
95
  {
93
96
  "version": "0.3",
@@ -100,7 +103,12 @@ npm install @dmitryvim/form-builder
100
103
  "required": true,
101
104
  "accept": {
102
105
  "extensions": ["jpg", "png", "webp"]
103
- }
106
+ },
107
+ "actions": [
108
+ { "value": "enhance", "label": "Enhance Quality" },
109
+ { "value": "crop", "label": "Auto Crop" },
110
+ { "value": "retry", "label": "Try Again" }
111
+ ]
104
112
  },
105
113
  {
106
114
  "type": "group",
@@ -129,24 +137,30 @@ npm install @dmitryvim/form-builder
129
137
  ## Integration Methods
130
138
 
131
139
  ### 1. NPM Package (Recommended)
140
+
132
141
  ```bash
133
142
  npm install @dmitryvim/form-builder
134
143
  ```
135
144
 
136
145
  ```javascript
137
146
  // ES6 imports
138
- import FormBuilder from '@dmitryvim/form-builder';
147
+ import FormBuilder from "@dmitryvim/form-builder";
139
148
 
140
149
  // Configure and use
141
- FormBuilder.setFormRoot(document.getElementById('form-container'));
150
+ FormBuilder.setFormRoot(document.getElementById("form-container"));
142
151
  FormBuilder.setUploadHandler(async (file) => {
143
152
  // Your upload logic - return resource ID
144
- return 'resource-123';
153
+ return "resource-123";
154
+ });
155
+ FormBuilder.setActionHandler((value) => {
156
+ // Handle action button clicks
157
+ console.log("Action clicked:", value);
145
158
  });
146
159
  FormBuilder.renderForm(schema, prefillData);
147
160
  ```
148
161
 
149
162
  ### 2. CDN Integration
163
+
150
164
  ```html
151
165
  <!-- Direct script include (npm CDN) -->
152
166
  <script src="https://cdn.jsdelivr.net/npm/@dmitryvim/form-builder@latest/dist/form-builder.js"></script>
@@ -160,11 +174,15 @@ FormBuilder.renderForm(schema, prefillData);
160
174
  <!-- Embed complete demo -->
161
175
  <iframe
162
176
  src="https://picaz-form-builder.website.yandexcloud.net/form-builder/latest/index.html"
163
- width="100%" height="600px" frameborder="0">
177
+ width="100%"
178
+ height="600px"
179
+ frameborder="0"
180
+ >
164
181
  </iframe>
165
182
  ```
166
183
 
167
184
  ### 3. Self-Hosted Deployment
185
+
168
186
  Download and serve the `dist/` folder contents.
169
187
 
170
188
  See [Integration Guide](docs/integration.md) for detailed setup instructions.
@@ -172,6 +190,7 @@ See [Integration Guide](docs/integration.md) for detailed setup instructions.
172
190
  ## Complete Feature Set
173
191
 
174
192
  ### Field Types
193
+
175
194
  - **Text**: Single-line with pattern validation, length limits
176
195
  - **Textarea**: Multi-line with configurable rows
177
196
  - **Number**: Numeric input with min/max/step/decimals
@@ -181,6 +200,7 @@ See [Integration Guide](docs/integration.md) for detailed setup instructions.
181
200
  - **Group**: Nested objects with repeatable array support
182
201
 
183
202
  ### File Handling
203
+
184
204
  - **Supported formats**: Images (jpg, png, gif, webp), Videos (mp4, webm, mov), Documents (pdf, docx, etc.)
185
205
  - **Preview system**: Thumbnails for images, video players, document icons
186
206
  - **Drag-and-drop**: Visual feedback and multi-file support
@@ -188,12 +208,14 @@ See [Integration Guide](docs/integration.md) for detailed setup instructions.
188
208
  - **Resource management**: Metadata tracking and automatic cleanup
189
209
 
190
210
  ### Validation & UX
211
+
191
212
  - **Real-time validation**: As-you-type with visual feedback
192
213
  - **Schema validation**: Comprehensive error reporting
193
214
  - **Internationalization**: English/Russian built-in, extensible
194
215
  - **Tooltips**: Field descriptions and hints
195
216
  - **Responsive design**: Mobile-friendly interface
196
217
  - **Read-only mode**: Display data without editing
218
+ - **Action buttons**: Custom buttons in readonly mode with configurable handlers
197
219
 
198
220
  ## Documentation
199
221
 
@@ -209,6 +231,7 @@ See [Integration Guide](docs/integration.md) for detailed setup instructions.
209
231
  **Version Index**: [https://picaz-form-builder.website.yandexcloud.net/index.html](https://picaz-form-builder.website.yandexcloud.net/index.html)
210
232
 
211
233
  Features a 3-column interface:
234
+
212
235
  - **Schema Editor**: Edit JSON schema with validation
213
236
  - **Live Preview**: See form render in real-time
214
237
  - **Data Output**: View/export form data as JSON
package/dist/demo.js CHANGED
@@ -18,20 +18,26 @@ const EXAMPLE_SCHEMA = {
18
18
  mime: ["image/png", "image/jpeg", "image/gif"],
19
19
  },
20
20
  maxSizeMB: 10,
21
+ actions: [
22
+ { value: "cover1.retry", label: "А давай ещё разок" },
23
+ { value: "cover1.enhance", label: "Улучшить качество" },
24
+ { value: "cover1.crop", label: "Обрезать изображение" },
25
+ ],
21
26
  },
22
27
  {
23
- type: "files",
28
+ type: "file",
24
29
  key: "assets",
25
30
  label: "Другие изображения",
26
31
  description:
27
32
  "Additional images that provide context, show different angles, or demonstrate product usage. These will be used to enhance the infographic composition.",
28
33
  required: false,
34
+ multiple: true,
35
+ minCount: 0,
36
+ maxCount: 10,
29
37
  accept: {
30
38
  extensions: ["png", "jpg", "gif"],
31
39
  mime: ["image/png", "image/jpeg", "image/gif"],
32
40
  },
33
- minCount: 0,
34
- maxCount: 10,
35
41
  maxSizeMB: 5,
36
42
  },
37
43
  {
@@ -42,6 +48,9 @@ const EXAMPLE_SCHEMA = {
42
48
  description:
43
49
  "The exact product name as it should appear on the infographic. Use the official product name without marketing terms or decorative elements.",
44
50
  required: true,
51
+ multiple: true,
52
+ minCount: 1,
53
+ maxCount: 4,
45
54
  minLength: 1,
46
55
  maxLength: 100,
47
56
  pattern: "^[A-Za-zА-Яа-я0-9 _*-]+$",
@@ -92,6 +101,68 @@ const EXAMPLE_SCHEMA = {
92
101
  step: 0.01,
93
102
  default: 0.5,
94
103
  },
104
+ {
105
+ type: "text",
106
+ key: "tags",
107
+ label: "Теги товара",
108
+ description: "Добавьте ключевые теги для лучшего описания товара",
109
+ placeholder: "Введите тег",
110
+ required: false,
111
+ multiple: true,
112
+ minCount: 1,
113
+ maxCount: 5,
114
+ minLength: 2,
115
+ maxLength: 20,
116
+ default: "popular"
117
+ },
118
+ {
119
+ type: "textarea",
120
+ key: "features",
121
+ label: "Особенности товара",
122
+ description: "Опишите ключевые особенности и преимущества товара",
123
+ placeholder: "Опишите особенность...",
124
+ required: false,
125
+ multiple: true,
126
+ minCount: 2,
127
+ maxCount: 4,
128
+ minLength: 10,
129
+ maxLength: 200,
130
+ rows: 3
131
+ },
132
+ {
133
+ type: "number",
134
+ key: "dimensions",
135
+ label: "Размеры (см)",
136
+ description: "Укажите размеры товара в сантиметрах: длина, ширина, высота",
137
+ placeholder: "0",
138
+ required: false,
139
+ multiple: true,
140
+ minCount: 2,
141
+ maxCount: 3,
142
+ min: 0,
143
+ max: 500,
144
+ step: 0.1,
145
+ decimals: 1
146
+ },
147
+ {
148
+ type: "select",
149
+ key: "colors",
150
+ label: "Доступные цвета",
151
+ description: "Выберите доступные цветовые варианты товара",
152
+ required: false,
153
+ multiple: true,
154
+ minCount: 1,
155
+ maxCount: 3,
156
+ options: [
157
+ { value: "white", label: "Белый" },
158
+ { value: "black", label: "Черный" },
159
+ { value: "red", label: "Красный" },
160
+ { value: "blue", label: "Синий" },
161
+ { value: "green", label: "Зеленый" },
162
+ { value: "gray", label: "Серый" }
163
+ ],
164
+ default: "white"
165
+ },
95
166
  {
96
167
  type: "file",
97
168
  key: "video",
@@ -106,12 +177,14 @@ const EXAMPLE_SCHEMA = {
106
177
  maxSizeMB: 50,
107
178
  },
108
179
  {
109
- type: "group",
180
+ type: "container",
110
181
  key: "slides",
111
182
  label: "Слайды",
112
183
  description:
113
184
  "Additional slides to showcase different aspects of your product. Each slide can have its own main image and decorative elements to create a comprehensive infographic presentation.",
114
- repeat: { min: 1, max: 5 },
185
+ multiple: true,
186
+ minCount: 1,
187
+ maxCount: 5,
115
188
  elements: [
116
189
  {
117
190
  type: "text",
@@ -135,6 +208,14 @@ const EXAMPLE_SCHEMA = {
135
208
  },
136
209
  ],
137
210
  },
211
+ {
212
+ type: "text",
213
+ key: "session_id",
214
+ label: "Session ID",
215
+ description: "Hidden session identifier for tracking purposes",
216
+ hidden: true,
217
+ default: "session_" + Math.random().toString(36).substr(2, 9),
218
+ },
138
219
  ],
139
220
  };
140
221
 
@@ -241,6 +322,39 @@ class InMemoryFileStorage {
241
322
  // Initialize file storage
242
323
  const fileStorage = new InMemoryFileStorage();
243
324
 
325
+ // Cache for action value -> label mapping for efficient lookup
326
+ let actionLabelMap = new Map();
327
+
328
+ // Build action value -> label mapping from schema for efficient lookup
329
+ function buildActionLabelMap(schema) {
330
+ const map = new Map();
331
+
332
+ function processElements(elements) {
333
+ if (!Array.isArray(elements)) return;
334
+
335
+ for (const element of elements) {
336
+ if (element.actions && Array.isArray(element.actions)) {
337
+ for (const action of element.actions) {
338
+ if (action.value && action.label) {
339
+ map.set(action.value, action.label);
340
+ }
341
+ }
342
+ }
343
+
344
+ // Process nested group elements
345
+ if (element.elements && Array.isArray(element.elements)) {
346
+ processElements(element.elements);
347
+ }
348
+ }
349
+ }
350
+
351
+ if (schema && schema.elements) {
352
+ processElements(schema.elements);
353
+ }
354
+
355
+ return map;
356
+ }
357
+
244
358
  // DOM element references
245
359
  const el = {
246
360
  schemaInput: document.getElementById("schemaInput"),
@@ -322,7 +436,24 @@ function setupFormBuilder() {
322
436
  return thumbnailUrl;
323
437
  });
324
438
 
325
- console.log("FormBuilder configured with in-memory file handlers");
439
+ // Action handler - display message when action button is clicked
440
+ FormBuilder.setActionHandler((value) => {
441
+ // Use cached action map for O(1) lookup instead of re-parsing schema
442
+ const actionLabel = actionLabelMap.get(value) || value; // fallback to value
443
+
444
+ console.log("Action clicked:", { label: actionLabel, value });
445
+
446
+ // Show message to user (compatible with all environments)
447
+ if (typeof window !== "undefined" && window.alert) {
448
+ window.alert(`${actionLabel} clicked: ${value}`);
449
+ } else {
450
+ console.log(`Demo action: ${actionLabel} clicked: ${value}`);
451
+ }
452
+ });
453
+
454
+ console.log(
455
+ "FormBuilder configured with in-memory file handlers and action handler",
456
+ );
326
457
  }
327
458
 
328
459
  // Schema management functions
@@ -342,6 +473,9 @@ function applyCurrentSchema() {
342
473
  return false;
343
474
  }
344
475
 
476
+ // Build action value -> label map for efficient lookup
477
+ actionLabelMap = buildActionLabelMap(schema);
478
+
345
479
  // Set mode based on toggle
346
480
  const isReadOnly = el.readOnlyToggle.checked;
347
481
  FormBuilder.setMode(isReadOnly ? "readonly" : "edit");