@bluprynt/forms-core 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/README.md +101 -0
- package/dist/form-definition.schema.json +352 -0
- package/dist/index.cjs +2351 -0
- package/dist/index.d.cts +1200 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +1200 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2321 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# @bluprynt/forms-core
|
|
2
|
+
|
|
3
|
+
Framework-agnostic engine for JSON-driven dynamic forms. Given a form schema (JSON), the engine handles field visibility via conditional logic, validates user input against type-specific rules, and produces structured form documents (JSON).
|
|
4
|
+
|
|
5
|
+
## Key Capabilities
|
|
6
|
+
|
|
7
|
+
- **Schema compilation** — validates and compiles a JSON form definition into a runtime engine with dependency analysis and cycle detection.
|
|
8
|
+
- **Conditional visibility** — shows/hides fields and sections dynamically based on other field values, with cascading parent-child visibility and topological evaluation order.
|
|
9
|
+
- **Type-aware validation** — validates form values against per-field rules (required, min/max, pattern, date ranges, array constraints, etc.), skipping hidden fields automatically.
|
|
10
|
+
- **Document compatibility validation** — verifies that a form document's `form.id` and `form.version` match the engine's definition before field validation.
|
|
11
|
+
- **Form definition editing** — fluent builder API (`FormDefinitionEditor`) for programmatically constructing and modifying form schemas.
|
|
12
|
+
- **Form values editing** — fluent editor API (`FormValuesEditor`) for programmatically reading and writing form values against a definition, with array manipulation, validation, and visibility queries.
|
|
13
|
+
- **Relative dates** — date boundaries like `"+7d"` or `"-1m"` are resolved at evaluation time against the form's required `submittedAt` timestamp, enabling dynamic yet reproducible date constraints.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { FormEngine } from '@bluprynt/forms-core'
|
|
19
|
+
|
|
20
|
+
// 1. Compile the form definition
|
|
21
|
+
const engine = new FormEngine(formDefinition)
|
|
22
|
+
|
|
23
|
+
// 2. Create a form document (with optional initial values)
|
|
24
|
+
const doc = engine.createFormDocument({ "1": "Alice", "2": 30 })
|
|
25
|
+
|
|
26
|
+
// 3. Compute visibility
|
|
27
|
+
const visibility = engine.getVisibilityMap(doc)
|
|
28
|
+
|
|
29
|
+
// 4. Validate (checks document compatibility + field rules)
|
|
30
|
+
const result = engine.validate(doc)
|
|
31
|
+
if (!result.valid) {
|
|
32
|
+
result.documentErrors?.forEach(e => console.log(`Document: ${e.message}`))
|
|
33
|
+
for (const [fieldId, errs] of result.fieldErrors) {
|
|
34
|
+
for (const err of errs) {
|
|
35
|
+
console.log(`Field ${fieldId}: ${err.message}`)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Building a Form Definition
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { FormDefinitionEditor } from '@bluprynt/forms-core'
|
|
45
|
+
|
|
46
|
+
const editor = new FormDefinitionEditor({
|
|
47
|
+
id: 'my-form', version: '1.0.0', title: 'My Form', content: [],
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
editor
|
|
51
|
+
.addField({ type: 'string', label: 'Name', validation: { required: true } })
|
|
52
|
+
.addSection({ type: 'section', title: 'Details' })
|
|
53
|
+
.addField({ type: 'number', label: 'Age' }, 2) // into section id=2
|
|
54
|
+
|
|
55
|
+
const definition = editor.toJSON()
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Editing Form Values
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { FormValuesEditor } from '@bluprynt/forms-core'
|
|
62
|
+
|
|
63
|
+
// 1. Create an editor (optionally pre-populate from an existing document)
|
|
64
|
+
const editor = new FormValuesEditor(formDefinition)
|
|
65
|
+
|
|
66
|
+
// 2. Set field values (fluent chaining)
|
|
67
|
+
editor
|
|
68
|
+
.setFieldValue(1, 'Alice')
|
|
69
|
+
.setFieldValue(2, 30)
|
|
70
|
+
.addArrayItem(6, 'TypeScript')
|
|
71
|
+
.addArrayItem(6, 'React')
|
|
72
|
+
.setSubmittedAt('2025-01-01T00:00:00Z')
|
|
73
|
+
|
|
74
|
+
// 3. Validate and extract the document
|
|
75
|
+
const result = editor.validate()
|
|
76
|
+
const doc = editor.toJSON()
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Documentation
|
|
80
|
+
|
|
81
|
+
| Document | Description |
|
|
82
|
+
|----------|-------------|
|
|
83
|
+
| [Architecture](./docs/architecture.md) | Project structure, module dependency graph, key design patterns |
|
|
84
|
+
| [API Reference](./docs/api-reference.md) | Complete public API — classes, methods, types, error handling |
|
|
85
|
+
| [Validation & Conditions](./docs/validation-and-conditions.md) | How validation rules work per field type, condition operators, visibility resolution |
|
|
86
|
+
| [Schema Issue Codes](./docs/schema-issue-codes.md) | All `DocumentError` error codes, validation stages, error handling |
|
|
87
|
+
| [Development Guide](./docs/development-guide.md) | How to build, test, lint, and extend the engine (e.g., adding new field types) |
|
|
88
|
+
|
|
89
|
+
For the complete list of exported classes, types, and utilities, see [API Reference](./docs/api-reference.md).
|
|
90
|
+
|
|
91
|
+
## Supported Field Types
|
|
92
|
+
|
|
93
|
+
| Type | Value | Description |
|
|
94
|
+
|------|-------|-------------|
|
|
95
|
+
| `string` | `string` | Free-text input |
|
|
96
|
+
| `number` | `number` | Numeric input |
|
|
97
|
+
| `boolean` | `boolean` | True/false toggle |
|
|
98
|
+
| `date` | `string` (ISO 8601) | Date picker |
|
|
99
|
+
| `select` | `string \| number` | Single selection from predefined options |
|
|
100
|
+
| `array` | `T[]` | Ordered list of scalar values |
|
|
101
|
+
| `file` | `FileValue` object | File upload metadata (name, mimeType, size, url) |
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "Bluprynt Form Definition",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": ["id", "version", "title", "content"],
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"properties": {
|
|
8
|
+
"id": { "type": "string" },
|
|
9
|
+
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
|
|
10
|
+
"title": { "type": "string" },
|
|
11
|
+
"description": { "type": "string" },
|
|
12
|
+
"content": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"minItems": 1,
|
|
15
|
+
"items": { "$ref": "#/$defs/contentItem" }
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"$defs": {
|
|
19
|
+
"conditionNoValue": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"required": ["field", "op"],
|
|
22
|
+
"properties": {
|
|
23
|
+
"field": { "type": "integer", "minimum": 1 },
|
|
24
|
+
"op": { "type": "string", "enum": ["set", "notset"] }
|
|
25
|
+
},
|
|
26
|
+
"additionalProperties": false
|
|
27
|
+
},
|
|
28
|
+
"conditionWithValue": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"required": ["field", "op", "value"],
|
|
31
|
+
"properties": {
|
|
32
|
+
"field": { "type": "integer", "minimum": 1 },
|
|
33
|
+
"op": { "type": "string", "enum": ["eq", "ne", "lt", "gt", "lte", "gte"] },
|
|
34
|
+
"value": {}
|
|
35
|
+
},
|
|
36
|
+
"additionalProperties": false
|
|
37
|
+
},
|
|
38
|
+
"conditionWithArrayValue": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"required": ["field", "op", "value"],
|
|
41
|
+
"properties": {
|
|
42
|
+
"field": { "type": "integer", "minimum": 1 },
|
|
43
|
+
"op": { "type": "string", "enum": ["in", "notin"] },
|
|
44
|
+
"value": { "type": "array" }
|
|
45
|
+
},
|
|
46
|
+
"additionalProperties": false
|
|
47
|
+
},
|
|
48
|
+
"simpleCondition": {
|
|
49
|
+
"oneOf": [
|
|
50
|
+
{ "$ref": "#/$defs/conditionNoValue" },
|
|
51
|
+
{ "$ref": "#/$defs/conditionWithValue" },
|
|
52
|
+
{ "$ref": "#/$defs/conditionWithArrayValue" }
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"condition": {
|
|
56
|
+
"oneOf": [
|
|
57
|
+
{ "$ref": "#/$defs/simpleCondition" },
|
|
58
|
+
{
|
|
59
|
+
"type": "object",
|
|
60
|
+
"required": ["and"],
|
|
61
|
+
"properties": {
|
|
62
|
+
"and": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/condition" } }
|
|
63
|
+
},
|
|
64
|
+
"additionalProperties": false
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"type": "object",
|
|
68
|
+
"required": ["or"],
|
|
69
|
+
"properties": {
|
|
70
|
+
"or": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/condition" } }
|
|
71
|
+
},
|
|
72
|
+
"additionalProperties": false
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
"stringValidation": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"properties": {
|
|
80
|
+
"required": { "type": "boolean" },
|
|
81
|
+
"minLength": { "type": "integer", "minimum": 0 },
|
|
82
|
+
"maxLength": { "type": "integer", "minimum": 1 },
|
|
83
|
+
"pattern": { "type": "string" },
|
|
84
|
+
"patternMessage": { "type": "string" }
|
|
85
|
+
},
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
},
|
|
88
|
+
"numberValidation": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"properties": {
|
|
91
|
+
"required": { "type": "boolean" },
|
|
92
|
+
"min": { "type": "number" },
|
|
93
|
+
"max": { "type": "number" }
|
|
94
|
+
},
|
|
95
|
+
"additionalProperties": false
|
|
96
|
+
},
|
|
97
|
+
"booleanValidation": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"properties": {
|
|
100
|
+
"required": { "type": "boolean" }
|
|
101
|
+
},
|
|
102
|
+
"additionalProperties": false
|
|
103
|
+
},
|
|
104
|
+
"dateValidation": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"properties": {
|
|
107
|
+
"required": { "type": "boolean" },
|
|
108
|
+
"minDate": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"pattern": "^([+-]\\d+[dwmy]|\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z)$"
|
|
111
|
+
},
|
|
112
|
+
"maxDate": {
|
|
113
|
+
"type": "string",
|
|
114
|
+
"pattern": "^([+-]\\d+[dwmy]|\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z)$"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"additionalProperties": false
|
|
118
|
+
},
|
|
119
|
+
"selectValidation": {
|
|
120
|
+
"type": "object",
|
|
121
|
+
"properties": {
|
|
122
|
+
"required": { "type": "boolean" }
|
|
123
|
+
},
|
|
124
|
+
"additionalProperties": false
|
|
125
|
+
},
|
|
126
|
+
"arrayValidation": {
|
|
127
|
+
"type": "object",
|
|
128
|
+
"properties": {
|
|
129
|
+
"minItems": { "type": "integer", "minimum": 0 },
|
|
130
|
+
"maxItems": { "type": "integer", "minimum": 1 }
|
|
131
|
+
},
|
|
132
|
+
"additionalProperties": false
|
|
133
|
+
},
|
|
134
|
+
"fileValidation": {
|
|
135
|
+
"type": "object",
|
|
136
|
+
"properties": {
|
|
137
|
+
"required": { "type": "boolean" }
|
|
138
|
+
},
|
|
139
|
+
"additionalProperties": false
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
"selectOption": {
|
|
143
|
+
"type": "object",
|
|
144
|
+
"required": ["value", "label"],
|
|
145
|
+
"properties": {
|
|
146
|
+
"value": { "oneOf": [{ "type": "string" }, { "type": "number" }] },
|
|
147
|
+
"label": { "type": "string" }
|
|
148
|
+
},
|
|
149
|
+
"additionalProperties": false
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
"arrayItemString": {
|
|
153
|
+
"type": "object",
|
|
154
|
+
"required": ["type", "label"],
|
|
155
|
+
"properties": {
|
|
156
|
+
"type": { "const": "string" },
|
|
157
|
+
"label": { "type": "string" },
|
|
158
|
+
"description": { "type": "string" },
|
|
159
|
+
"validation": { "$ref": "#/$defs/stringValidation" }
|
|
160
|
+
},
|
|
161
|
+
"additionalProperties": false
|
|
162
|
+
},
|
|
163
|
+
"arrayItemNumber": {
|
|
164
|
+
"type": "object",
|
|
165
|
+
"required": ["type", "label"],
|
|
166
|
+
"properties": {
|
|
167
|
+
"type": { "const": "number" },
|
|
168
|
+
"label": { "type": "string" },
|
|
169
|
+
"description": { "type": "string" },
|
|
170
|
+
"validation": { "$ref": "#/$defs/numberValidation" }
|
|
171
|
+
},
|
|
172
|
+
"additionalProperties": false
|
|
173
|
+
},
|
|
174
|
+
"arrayItemBoolean": {
|
|
175
|
+
"type": "object",
|
|
176
|
+
"required": ["type", "label"],
|
|
177
|
+
"properties": {
|
|
178
|
+
"type": { "const": "boolean" },
|
|
179
|
+
"label": { "type": "string" },
|
|
180
|
+
"description": { "type": "string" },
|
|
181
|
+
"validation": { "$ref": "#/$defs/booleanValidation" }
|
|
182
|
+
},
|
|
183
|
+
"additionalProperties": false
|
|
184
|
+
},
|
|
185
|
+
"arrayItemDate": {
|
|
186
|
+
"type": "object",
|
|
187
|
+
"required": ["type", "label"],
|
|
188
|
+
"properties": {
|
|
189
|
+
"type": { "const": "date" },
|
|
190
|
+
"label": { "type": "string" },
|
|
191
|
+
"description": { "type": "string" },
|
|
192
|
+
"validation": { "$ref": "#/$defs/dateValidation" }
|
|
193
|
+
},
|
|
194
|
+
"additionalProperties": false
|
|
195
|
+
},
|
|
196
|
+
"arrayItemSelect": {
|
|
197
|
+
"type": "object",
|
|
198
|
+
"required": ["type", "label", "options"],
|
|
199
|
+
"properties": {
|
|
200
|
+
"type": { "const": "select" },
|
|
201
|
+
"label": { "type": "string" },
|
|
202
|
+
"description": { "type": "string" },
|
|
203
|
+
"options": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/selectOption" } },
|
|
204
|
+
"validation": { "$ref": "#/$defs/selectValidation" }
|
|
205
|
+
},
|
|
206
|
+
"additionalProperties": false
|
|
207
|
+
},
|
|
208
|
+
"arrayItemFile": {
|
|
209
|
+
"type": "object",
|
|
210
|
+
"required": ["type", "label"],
|
|
211
|
+
"properties": {
|
|
212
|
+
"type": { "const": "file" },
|
|
213
|
+
"label": { "type": "string" },
|
|
214
|
+
"description": { "type": "string" },
|
|
215
|
+
"validation": { "$ref": "#/$defs/fileValidation" }
|
|
216
|
+
},
|
|
217
|
+
"additionalProperties": false
|
|
218
|
+
},
|
|
219
|
+
"arrayItem": {
|
|
220
|
+
"oneOf": [
|
|
221
|
+
{ "$ref": "#/$defs/arrayItemString" },
|
|
222
|
+
{ "$ref": "#/$defs/arrayItemNumber" },
|
|
223
|
+
{ "$ref": "#/$defs/arrayItemBoolean" },
|
|
224
|
+
{ "$ref": "#/$defs/arrayItemDate" },
|
|
225
|
+
{ "$ref": "#/$defs/arrayItemSelect" },
|
|
226
|
+
{ "$ref": "#/$defs/arrayItemFile" }
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
"stringField": {
|
|
231
|
+
"type": "object",
|
|
232
|
+
"required": ["id", "type", "label"],
|
|
233
|
+
"properties": {
|
|
234
|
+
"id": { "type": "integer", "minimum": 1 },
|
|
235
|
+
"type": { "const": "string" },
|
|
236
|
+
"label": { "type": "string" },
|
|
237
|
+
"description": { "type": "string" },
|
|
238
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
239
|
+
"validation": { "$ref": "#/$defs/stringValidation" }
|
|
240
|
+
},
|
|
241
|
+
"additionalProperties": false
|
|
242
|
+
},
|
|
243
|
+
"numberField": {
|
|
244
|
+
"type": "object",
|
|
245
|
+
"required": ["id", "type", "label"],
|
|
246
|
+
"properties": {
|
|
247
|
+
"id": { "type": "integer", "minimum": 1 },
|
|
248
|
+
"type": { "const": "number" },
|
|
249
|
+
"label": { "type": "string" },
|
|
250
|
+
"description": { "type": "string" },
|
|
251
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
252
|
+
"validation": { "$ref": "#/$defs/numberValidation" }
|
|
253
|
+
},
|
|
254
|
+
"additionalProperties": false
|
|
255
|
+
},
|
|
256
|
+
"booleanField": {
|
|
257
|
+
"type": "object",
|
|
258
|
+
"required": ["id", "type", "label"],
|
|
259
|
+
"properties": {
|
|
260
|
+
"id": { "type": "integer", "minimum": 1 },
|
|
261
|
+
"type": { "const": "boolean" },
|
|
262
|
+
"label": { "type": "string" },
|
|
263
|
+
"description": { "type": "string" },
|
|
264
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
265
|
+
"validation": { "$ref": "#/$defs/booleanValidation" }
|
|
266
|
+
},
|
|
267
|
+
"additionalProperties": false
|
|
268
|
+
},
|
|
269
|
+
"dateField": {
|
|
270
|
+
"type": "object",
|
|
271
|
+
"required": ["id", "type", "label"],
|
|
272
|
+
"properties": {
|
|
273
|
+
"id": { "type": "integer", "minimum": 1 },
|
|
274
|
+
"type": { "const": "date" },
|
|
275
|
+
"label": { "type": "string" },
|
|
276
|
+
"description": { "type": "string" },
|
|
277
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
278
|
+
"validation": { "$ref": "#/$defs/dateValidation" }
|
|
279
|
+
},
|
|
280
|
+
"additionalProperties": false
|
|
281
|
+
},
|
|
282
|
+
"selectField": {
|
|
283
|
+
"type": "object",
|
|
284
|
+
"required": ["id", "type", "label", "options"],
|
|
285
|
+
"properties": {
|
|
286
|
+
"id": { "type": "integer", "minimum": 1 },
|
|
287
|
+
"type": { "const": "select" },
|
|
288
|
+
"label": { "type": "string" },
|
|
289
|
+
"description": { "type": "string" },
|
|
290
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
291
|
+
"options": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/selectOption" } },
|
|
292
|
+
"validation": { "$ref": "#/$defs/selectValidation" }
|
|
293
|
+
},
|
|
294
|
+
"additionalProperties": false
|
|
295
|
+
},
|
|
296
|
+
"arrayField": {
|
|
297
|
+
"type": "object",
|
|
298
|
+
"required": ["id", "type", "label", "item"],
|
|
299
|
+
"properties": {
|
|
300
|
+
"id": { "type": "integer", "minimum": 1 },
|
|
301
|
+
"type": { "const": "array" },
|
|
302
|
+
"label": { "type": "string" },
|
|
303
|
+
"description": { "type": "string" },
|
|
304
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
305
|
+
"item": { "$ref": "#/$defs/arrayItem" },
|
|
306
|
+
"validation": { "$ref": "#/$defs/arrayValidation" }
|
|
307
|
+
},
|
|
308
|
+
"additionalProperties": false
|
|
309
|
+
},
|
|
310
|
+
"fileField": {
|
|
311
|
+
"type": "object",
|
|
312
|
+
"required": ["id", "type", "label"],
|
|
313
|
+
"properties": {
|
|
314
|
+
"id": { "type": "integer", "minimum": 1 },
|
|
315
|
+
"type": { "const": "file" },
|
|
316
|
+
"label": { "type": "string" },
|
|
317
|
+
"description": { "type": "string" },
|
|
318
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
319
|
+
"validation": { "$ref": "#/$defs/fileValidation" }
|
|
320
|
+
},
|
|
321
|
+
"additionalProperties": false
|
|
322
|
+
},
|
|
323
|
+
"fieldItem": {
|
|
324
|
+
"oneOf": [
|
|
325
|
+
{ "$ref": "#/$defs/stringField" },
|
|
326
|
+
{ "$ref": "#/$defs/numberField" },
|
|
327
|
+
{ "$ref": "#/$defs/booleanField" },
|
|
328
|
+
{ "$ref": "#/$defs/dateField" },
|
|
329
|
+
{ "$ref": "#/$defs/selectField" },
|
|
330
|
+
{ "$ref": "#/$defs/arrayField" },
|
|
331
|
+
{ "$ref": "#/$defs/fileField" }
|
|
332
|
+
]
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
"section": {
|
|
336
|
+
"type": "object",
|
|
337
|
+
"required": ["id", "type", "title", "content"],
|
|
338
|
+
"properties": {
|
|
339
|
+
"id": { "type": "integer", "minimum": 1 },
|
|
340
|
+
"type": { "const": "section" },
|
|
341
|
+
"title": { "type": "string" },
|
|
342
|
+
"description": { "type": "string" },
|
|
343
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
344
|
+
"content": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/contentItem" } }
|
|
345
|
+
},
|
|
346
|
+
"additionalProperties": false
|
|
347
|
+
},
|
|
348
|
+
"contentItem": {
|
|
349
|
+
"oneOf": [{ "$ref": "#/$defs/fieldItem" }, { "$ref": "#/$defs/section" }]
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|