@rokkit/forms 1.3.2 → 1.3.3
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/dist/lib/builder.svelte.d.ts +6 -0
- package/dist/lib/layout.d.ts +12 -0
- package/package.json +1 -1
- package/src/lib/builder.svelte.js +27 -2
- package/src/lib/layout.js +44 -0
|
@@ -31,6 +31,12 @@ export class FormBuilder {
|
|
|
31
31
|
/**
|
|
32
32
|
* Set the schema
|
|
33
33
|
* @param {Object} value - New schema object
|
|
34
|
+
*
|
|
35
|
+
* When the caller explicitly provides a schema, that schema is the source
|
|
36
|
+
* of truth for which fields exist — the layout may have been derived
|
|
37
|
+
* earlier from empty/partial data and would silently hide those fields.
|
|
38
|
+
* Re-derive the layout from the new schema so the two stay consistent,
|
|
39
|
+
* unless the caller has already installed an explicit non-empty layout.
|
|
34
40
|
*/
|
|
35
41
|
set schema(value: Object);
|
|
36
42
|
/**
|
package/dist/lib/layout.d.ts
CHANGED
|
@@ -5,3 +5,15 @@
|
|
|
5
5
|
* @returns {import('../types').DataLayout}
|
|
6
6
|
*/
|
|
7
7
|
export function deriveLayoutFromValue(value: any, scope?: string): import("../types").DataLayout;
|
|
8
|
+
/**
|
|
9
|
+
* Derive a layout directly from a JSON-Schema definition. Used when a schema
|
|
10
|
+
* is supplied but no explicit layout is — one element per top-level property
|
|
11
|
+
* in declaration order. This is the correct fallback when a schema is
|
|
12
|
+
* present: the schema is the source of truth for which fields exist, not the
|
|
13
|
+
* (possibly-empty) initial data.
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} schema JSON-Schema fragment (object type with `properties`)
|
|
16
|
+
* @param {string} scope Base scope pointer (defaults to root)
|
|
17
|
+
* @returns {import('../types').DataLayout}
|
|
18
|
+
*/
|
|
19
|
+
export function deriveLayoutFromSchema(schema: Object, scope?: string): import("../types").DataLayout;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SvelteMap, SvelteSet } from 'svelte/reactivity'
|
|
2
2
|
import { deriveSchemaFromValue } from './schema.js'
|
|
3
|
-
import { deriveLayoutFromValue } from './layout.js'
|
|
3
|
+
import { deriveLayoutFromValue, deriveLayoutFromSchema } from './layout.js'
|
|
4
4
|
import { getSchemaWithLayout } from './fields.js'
|
|
5
5
|
import { createLookupManager } from './lookup.svelte.js'
|
|
6
6
|
import { evaluateCondition } from './conditions.js'
|
|
@@ -169,9 +169,20 @@ export class FormBuilder {
|
|
|
169
169
|
/**
|
|
170
170
|
* Set the schema
|
|
171
171
|
* @param {Object} value - New schema object
|
|
172
|
+
*
|
|
173
|
+
* When the caller explicitly provides a schema, that schema is the source
|
|
174
|
+
* of truth for which fields exist — the layout may have been derived
|
|
175
|
+
* earlier from empty/partial data and would silently hide those fields.
|
|
176
|
+
* Re-derive the layout from the new schema so the two stay consistent,
|
|
177
|
+
* unless the caller has already installed an explicit non-empty layout.
|
|
172
178
|
*/
|
|
173
179
|
set schema(value) {
|
|
174
180
|
this.#schema = value ?? deriveSchemaFromValue(this.#data)
|
|
181
|
+
const layout = this.#layout
|
|
182
|
+
const hasExplicitLayout = layout && Array.isArray(layout.elements) && layout.elements.length > 0
|
|
183
|
+
if (!hasExplicitLayout) {
|
|
184
|
+
this.#layout = deriveLayoutFromSchema(this.#schema)
|
|
185
|
+
}
|
|
175
186
|
}
|
|
176
187
|
|
|
177
188
|
/**
|
|
@@ -187,7 +198,21 @@ export class FormBuilder {
|
|
|
187
198
|
* @param {Object} value - New layout object
|
|
188
199
|
*/
|
|
189
200
|
set layout(value) {
|
|
190
|
-
|
|
201
|
+
if (value) {
|
|
202
|
+
this.#layout = value
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
// No explicit layout — prefer schema-derived over data-derived so
|
|
206
|
+
// declared fields render even when initial data is `{}` (a common
|
|
207
|
+
// pattern for LLM-generated forms and reset forms).
|
|
208
|
+
const schema = this.#schema
|
|
209
|
+
const hasSchemaProperties =
|
|
210
|
+
schema && typeof schema === 'object' && schema.properties &&
|
|
211
|
+
typeof schema.properties === 'object' &&
|
|
212
|
+
Object.keys(schema.properties).length > 0
|
|
213
|
+
this.#layout = hasSchemaProperties
|
|
214
|
+
? deriveLayoutFromSchema(schema)
|
|
215
|
+
: deriveLayoutFromValue(this.#data)
|
|
191
216
|
}
|
|
192
217
|
|
|
193
218
|
/**
|
package/src/lib/layout.js
CHANGED
|
@@ -60,3 +60,47 @@ export function deriveLayoutFromValue(value, scope = '#') {
|
|
|
60
60
|
}
|
|
61
61
|
return { type: 'vertical', elements: [{ scope }] }
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Build an inner element from a JSON-Schema property. Objects recurse into a
|
|
66
|
+
* nested {title, scope, type:'vertical', elements:[...]} group; primitives
|
|
67
|
+
* yield a scoped leaf. Mirrors `deriveElementLayout` but reads the shape from
|
|
68
|
+
* schema's `properties` rather than from the data value.
|
|
69
|
+
*
|
|
70
|
+
* @param {Object} propSchema
|
|
71
|
+
* @param {string} scope
|
|
72
|
+
* @param {string} label
|
|
73
|
+
* @returns {import('../types').LayoutElement}
|
|
74
|
+
*/
|
|
75
|
+
function deriveElementFromSchema(propSchema, scope, label) {
|
|
76
|
+
const path = `${scope}/${label}`
|
|
77
|
+
if (propSchema && propSchema.type === 'object' && isObject(propSchema.properties)) {
|
|
78
|
+
return {
|
|
79
|
+
title: label,
|
|
80
|
+
scope: path,
|
|
81
|
+
...deriveLayoutFromSchema(propSchema, path)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { label, scope: path }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Derive a layout directly from a JSON-Schema definition. Used when a schema
|
|
89
|
+
* is supplied but no explicit layout is — one element per top-level property
|
|
90
|
+
* in declaration order. This is the correct fallback when a schema is
|
|
91
|
+
* present: the schema is the source of truth for which fields exist, not the
|
|
92
|
+
* (possibly-empty) initial data.
|
|
93
|
+
*
|
|
94
|
+
* @param {Object} schema JSON-Schema fragment (object type with `properties`)
|
|
95
|
+
* @param {string} scope Base scope pointer (defaults to root)
|
|
96
|
+
* @returns {import('../types').DataLayout}
|
|
97
|
+
*/
|
|
98
|
+
export function deriveLayoutFromSchema(schema, scope = '#') {
|
|
99
|
+
if (!isObject(schema) || !isObject(schema.properties)) {
|
|
100
|
+
return { type: 'vertical', elements: [] }
|
|
101
|
+
}
|
|
102
|
+
const elements = Object.entries(schema.properties).map(([label, propSchema]) =>
|
|
103
|
+
deriveElementFromSchema(propSchema, scope, label)
|
|
104
|
+
)
|
|
105
|
+
return { type: 'vertical', elements }
|
|
106
|
+
}
|