@json-layout/core 0.4.0 → 0.5.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/package.json +2 -2
- package/src/compile/index.js +3 -2
- package/src/compile/skeleton-node.js +24 -18
- package/src/compile/types.ts +3 -2
- package/src/state/index.js +11 -5
- package/src/state/state-node.js +62 -33
- package/src/state/state-tree.js +1 -0
- package/src/state/types.ts +27 -6
- package/src/state/utils/immutable.js +13 -1
- package/types/compile/index.d.ts.map +1 -1
- package/types/compile/skeleton-node.d.ts.map +1 -1
- package/types/compile/types.d.ts +3 -2
- package/types/compile/types.d.ts.map +1 -1
- package/types/state/index.d.ts.map +1 -1
- package/types/state/state-node.d.ts +7 -4
- package/types/state/state-node.d.ts.map +1 -1
- package/types/state/state-tree.d.ts.map +1 -1
- package/types/state/types.d.ts +22 -5
- package/types/state/types.d.ts.map +1 -1
- package/types/state/utils/immutable.d.ts +8 -1
- package/types/state/utils/immutable.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@json-layout/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Compilation and state management utilities for JSON Layout.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"homepage": "https://github.com/json-layout/json-layout#readme",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@json-layout/vocabulary": "^0.
|
|
50
|
+
"@json-layout/vocabulary": "^0.5.0",
|
|
51
51
|
"@types/markdown-it": "^13.0.1",
|
|
52
52
|
"ajv": "^8.12.0",
|
|
53
53
|
"ajv-errors": "^3.0.0",
|
package/src/compile/index.js
CHANGED
|
@@ -27,8 +27,6 @@ const Ajv = /** @type {typeof ajvModule.default} */ (ajvModule)
|
|
|
27
27
|
// @ts-ignore
|
|
28
28
|
const ajvLocalize = /** @type {typeof ajvLocalizeModule.default} */ (ajvLocalizeModule)
|
|
29
29
|
|
|
30
|
-
const expressionsParams = ['data', 'options', 'context', 'display']
|
|
31
|
-
|
|
32
30
|
// const exprEvalParser = new ExprEvalParser()
|
|
33
31
|
|
|
34
32
|
/**
|
|
@@ -114,6 +112,9 @@ export function compile (_schema, partialOptions = {}) {
|
|
|
114
112
|
const expressions = []
|
|
115
113
|
|
|
116
114
|
for (const expression of expressionsDefinitions) {
|
|
115
|
+
const expressionsParams = expression.pure
|
|
116
|
+
? ['data', 'options', 'context', 'display']
|
|
117
|
+
: ['data', 'options', 'context', 'display', 'parentData', 'rootData']
|
|
117
118
|
/* if (expression.type === 'expr-eval') {
|
|
118
119
|
expressions.push(exprEvalParser.parse(expression.expr).toJSFunction(expressionsParams.join(',')))
|
|
119
120
|
} */
|
|
@@ -2,20 +2,6 @@
|
|
|
2
2
|
import { normalizeLayoutFragment, isSwitchStruct, isGetItemsExpression, isGetItemsFetch, isItemsLayout } from '@json-layout/vocabulary'
|
|
3
3
|
import { makeSkeletonTree } from './skeleton-tree.js'
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* @param {import('@json-layout/vocabulary').Expression[]} expressions
|
|
7
|
-
* @param {import('@json-layout/vocabulary').Expression} expression
|
|
8
|
-
*/
|
|
9
|
-
const pushExpression = (expressions, expression) => {
|
|
10
|
-
const index = expressions.findIndex(e => e.type === expression.type && e.expr === expression.expr)
|
|
11
|
-
if (index !== -1) {
|
|
12
|
-
expression.ref = index
|
|
13
|
-
} else {
|
|
14
|
-
expression.ref = expressions.length
|
|
15
|
-
expressions.push(expression)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
5
|
/**
|
|
20
6
|
* @param {any} schema
|
|
21
7
|
* @param {import('./index.js').CompileOptions} options
|
|
@@ -62,15 +48,31 @@ export function makeSkeletonNode (
|
|
|
62
48
|
if (schema.type === 'array') defaultData = []
|
|
63
49
|
}
|
|
64
50
|
|
|
51
|
+
let pure = true
|
|
52
|
+
/**
|
|
53
|
+
* @param {import('@json-layout/vocabulary').Expression[]} expressions
|
|
54
|
+
* @param {import('@json-layout/vocabulary').Expression} expression
|
|
55
|
+
*/
|
|
56
|
+
const pushExpression = (expressions, expression) => {
|
|
57
|
+
if (!expression.pure) pure = false
|
|
58
|
+
const index = expressions.findIndex(e => e.type === expression.type && e.expr === expression.expr)
|
|
59
|
+
if (index !== -1) {
|
|
60
|
+
expression.ref = index
|
|
61
|
+
} else {
|
|
62
|
+
expression.ref = expressions.length
|
|
63
|
+
expressions.push(expression)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
65
67
|
const compObjects = isSwitchStruct(normalizedLayout) ? normalizedLayout.switch : [normalizedLayout]
|
|
66
68
|
for (const compObject of compObjects) {
|
|
67
69
|
if (schema.description && !compObject.help) compObject.help = schema.description
|
|
68
70
|
if (compObject.if) pushExpression(expressions, compObject.if)
|
|
69
71
|
|
|
70
|
-
if ('const' in schema) compObject.constData = { type: 'js-eval', expr: JSON.stringify(schema.const) }
|
|
72
|
+
if ('const' in schema) compObject.constData = { type: 'js-eval', expr: JSON.stringify(schema.const), pure: true }
|
|
71
73
|
if (compObject.constData) pushExpression(expressions, compObject.constData)
|
|
72
74
|
|
|
73
|
-
if (defaultData && !compObject.defaultData) compObject.defaultData = { type: 'js-eval', expr: JSON.stringify(defaultData) }
|
|
75
|
+
if (defaultData && !compObject.defaultData) compObject.defaultData = { type: 'js-eval', expr: JSON.stringify(defaultData), pure: true }
|
|
74
76
|
if (compObject.defaultData) pushExpression(expressions, compObject.defaultData)
|
|
75
77
|
|
|
76
78
|
if (isItemsLayout(compObject) && compObject.getItems) {
|
|
@@ -85,7 +87,7 @@ export function makeSkeletonNode (
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
/** @type {import('./types.js').SkeletonNode} */
|
|
88
|
-
const node = { key: key ?? '', pointer, parentPointer }
|
|
90
|
+
const node = { key: key ?? '', pointer, parentPointer, pure }
|
|
89
91
|
if (schema.type === 'object') {
|
|
90
92
|
if (schema.properties) {
|
|
91
93
|
node.children = node.children ?? []
|
|
@@ -152,7 +154,7 @@ export function makeSkeletonNode (
|
|
|
152
154
|
))
|
|
153
155
|
}
|
|
154
156
|
node.children = node.children ?? []
|
|
155
|
-
node.children.push({ key: '$oneOf', pointer: `${pointer}/oneOf`, parentPointer: pointer, childrenTrees })
|
|
157
|
+
node.children.push({ key: '$oneOf', pointer: `${pointer}/oneOf`, parentPointer: pointer, childrenTrees, pure: childrenTrees[0].root.pure })
|
|
156
158
|
|
|
157
159
|
schema.errorMessage.oneOf = options.messages.errorOneOf
|
|
158
160
|
}
|
|
@@ -189,5 +191,9 @@ export function makeSkeletonNode (
|
|
|
189
191
|
]
|
|
190
192
|
}
|
|
191
193
|
}
|
|
194
|
+
|
|
195
|
+
for (const child of node.children || []) if (!child.pure) node.pure = false
|
|
196
|
+
for (const childTree of node.childrenTrees || []) if (!childTree.root.pure) node.pure = false
|
|
197
|
+
|
|
192
198
|
return node
|
|
193
199
|
}
|
package/src/compile/types.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type ajvModule from 'ajv'
|
|
2
2
|
import type MarkdownIt from 'markdown-it'
|
|
3
|
-
import { type NormalizedLayout, type
|
|
3
|
+
import { type NormalizedLayout, type StateNodeOptionsBase } from '@json-layout/vocabulary'
|
|
4
4
|
import { type ValidateFunction, type SchemaObject, type ErrorObject } from 'ajv'
|
|
5
5
|
import { type Display } from '../state/utils/display.js'
|
|
6
6
|
import { type LocaleMessages } from '../i18n/types.js'
|
|
7
7
|
|
|
8
|
-
export type CompiledExpression = (data: any, options:
|
|
8
|
+
export type CompiledExpression = (data: any, options: StateNodeOptionsBase, context: object, display: Display, rootData?: unknown, parentData?: unknown) => any
|
|
9
9
|
|
|
10
10
|
export interface CompileOptions {
|
|
11
11
|
ajv: ajvModule.default
|
|
@@ -44,6 +44,7 @@ export interface SkeletonNode {
|
|
|
44
44
|
key: string | number
|
|
45
45
|
pointer: string
|
|
46
46
|
parentPointer: string | null
|
|
47
|
+
pure: boolean
|
|
47
48
|
children?: SkeletonNode[] // optional children in the case of arrays and object nodes
|
|
48
49
|
childrenTrees?: SkeletonTree[] // other trees that can be instantiated with separate validation (for example in the case of new array items of oneOfs, etc)
|
|
49
50
|
}
|
package/src/state/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// eslint-disable-next-line import/no-named-default
|
|
2
2
|
import mittModule from 'mitt'
|
|
3
3
|
import debug from 'debug'
|
|
4
|
+
import { produce } from 'immer'
|
|
4
5
|
import { evalExpression, producePatchedData } from './state-node.js'
|
|
5
6
|
import { createStateTree } from './state-tree.js'
|
|
6
7
|
import { Display } from './utils/display.js'
|
|
@@ -249,7 +250,9 @@ export class StatefulLayout {
|
|
|
249
250
|
nodes: [],
|
|
250
251
|
activeItems: this.activeItems,
|
|
251
252
|
autofocusTarget: this._autofocusTarget,
|
|
252
|
-
initial: !this._lastCreateStateTreeContext
|
|
253
|
+
initial: !this._lastCreateStateTreeContext,
|
|
254
|
+
cacheKeys: this._lastCreateStateTreeContext?.cacheKeys ?? {},
|
|
255
|
+
rootData: this._data
|
|
253
256
|
}
|
|
254
257
|
this._stateTree = createStateTree(
|
|
255
258
|
createStateTreeContext,
|
|
@@ -269,6 +272,7 @@ export class StatefulLayout {
|
|
|
269
272
|
validatedChildren: createStateTreeContext.nodes.filter(n => n.validated).map(n => n.fullKey)
|
|
270
273
|
}
|
|
271
274
|
}
|
|
275
|
+
this.activeItems = createStateTreeContext.activeItems
|
|
272
276
|
}
|
|
273
277
|
|
|
274
278
|
validate () {
|
|
@@ -312,7 +316,7 @@ export class StatefulLayout {
|
|
|
312
316
|
this.validationState = { validatedChildren: this.validationState.validatedChildren.concat([node.fullKey]) }
|
|
313
317
|
}
|
|
314
318
|
if (activateKey !== undefined) {
|
|
315
|
-
this.activeItems[node.fullKey] = activateKey
|
|
319
|
+
this.activeItems = produce(this.activeItems, draft => { draft[node.fullKey] = activateKey })
|
|
316
320
|
this._autofocusTarget = node.fullKey + '/' + activateKey
|
|
317
321
|
}
|
|
318
322
|
if (node.parentFullKey === null) {
|
|
@@ -368,7 +372,9 @@ export class StatefulLayout {
|
|
|
368
372
|
|
|
369
373
|
/** @type {(expression: import('@json-layout/vocabulary').Expression, data: any) => any} */
|
|
370
374
|
const evalSelectExpression = (expression, data) => {
|
|
371
|
-
|
|
375
|
+
const parentNode = this._lastCreateStateTreeContext.nodes.find(n => n.fullKey === node.parentFullKey)
|
|
376
|
+
const parentData = parentNode ? parentNode.data : null
|
|
377
|
+
return evalExpression(this.compiledLayout.expressions, expression, data, node.options, new Display(node.width), parentData, this._data)
|
|
372
378
|
}
|
|
373
379
|
|
|
374
380
|
let rawItems
|
|
@@ -443,7 +449,7 @@ export class StatefulLayout {
|
|
|
443
449
|
* @param {number} key
|
|
444
450
|
*/
|
|
445
451
|
activateItem (node, key) {
|
|
446
|
-
this.activeItems[node.fullKey] = key
|
|
452
|
+
this.activeItems = produce(this.activeItems, draft => { draft[node.fullKey] = key })
|
|
447
453
|
this._autofocusTarget = node.fullKey + '/' + key
|
|
448
454
|
if (node.key === '$oneOf') {
|
|
449
455
|
this.input(node, undefined)
|
|
@@ -457,7 +463,7 @@ export class StatefulLayout {
|
|
|
457
463
|
* @param {StateNode} node
|
|
458
464
|
*/
|
|
459
465
|
deactivateItem (node) {
|
|
460
|
-
|
|
466
|
+
this.activeItems = produce(this.activeItems, draft => { delete draft[node.fullKey] })
|
|
461
467
|
this.updateState()
|
|
462
468
|
}
|
|
463
469
|
|
package/src/state/state-node.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isSwitchStruct, childIsCompObject, isCompositeLayout, isFocusableLayout } from '@json-layout/vocabulary'
|
|
2
2
|
import { produce } from 'immer'
|
|
3
3
|
import { getChildDisplay } from './utils/display.js'
|
|
4
|
-
import {
|
|
4
|
+
import { shallowEqualArray, shallowProduceArray } from './utils/immutable.js'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @param {unknown} data
|
|
@@ -17,7 +17,7 @@ const isDataEmpty = (data) => {
|
|
|
17
17
|
/**
|
|
18
18
|
* @param {unknown} data
|
|
19
19
|
* @param {import('@json-layout/vocabulary').CompObject} layout
|
|
20
|
-
* @param {import('./types.js').
|
|
20
|
+
* @param {import('./types.js').StateNodeOptions} options
|
|
21
21
|
* @returns {boolean}
|
|
22
22
|
*/
|
|
23
23
|
const useDefaultData = (data, layout, options) => {
|
|
@@ -27,8 +27,8 @@ const useDefaultData = (data, layout, options) => {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// use Immer for efficient updating with immutability and no-op detection
|
|
30
|
-
/** @type {(draft: import('./types.js').StateNode, key: string | number, fullKey: string, parentFullKey: string | null, dataPath: string, parentDataPath: string | null, skeleton: import('../index.js').SkeletonNode, layout: import('@json-layout/vocabulary').CompObject, cols: number, data: unknown, error: string | undefined, validated: boolean, options: import('./types.js').
|
|
31
|
-
const produceStateNode = produce((draft, key, fullKey, parentFullKey, dataPath, parentDataPath, skeleton, layout, cols, data, error, validated, options, autofocus, children) => {
|
|
30
|
+
/** @type {(draft: import('./types.js').StateNode, key: string | number, fullKey: string, parentFullKey: string | null, dataPath: string, parentDataPath: string | null, skeleton: import('../index.js').SkeletonNode, layout: import('@json-layout/vocabulary').CompObject, width: number, cols: number, data: unknown, error: string | undefined, validated: boolean, options: import('./types.js').StateNodeOptions, autofocus: boolean, children: import('../index.js').StateNode[] | undefined) => import('../index.js').StateNode} */
|
|
31
|
+
const produceStateNode = produce((draft, key, fullKey, parentFullKey, dataPath, parentDataPath, skeleton, layout, width, cols, data, error, validated, options, autofocus, children) => {
|
|
32
32
|
draft.messages = layout.messages ? produceStateNodeMessages(draft.messages || {}, layout.messages, options) : options.messages
|
|
33
33
|
|
|
34
34
|
draft.key = key
|
|
@@ -38,6 +38,7 @@ const produceStateNode = produce((draft, key, fullKey, parentFullKey, dataPath,
|
|
|
38
38
|
draft.parentDataPath = parentDataPath
|
|
39
39
|
draft.skeleton = skeleton
|
|
40
40
|
draft.layout = layout
|
|
41
|
+
draft.width = width
|
|
41
42
|
draft.options = options
|
|
42
43
|
draft.cols = cols
|
|
43
44
|
draft.data = data
|
|
@@ -57,7 +58,7 @@ const produceStateNode = produce((draft, key, fullKey, parentFullKey, dataPath,
|
|
|
57
58
|
draft.children = children
|
|
58
59
|
})
|
|
59
60
|
|
|
60
|
-
/** @type {(draft: import('../i18n/types.js').LocaleMessages, layoutMessages: Partial<import('../i18n/types.js').LocaleMessages>, options: import('./types.js').
|
|
61
|
+
/** @type {(draft: import('../i18n/types.js').LocaleMessages, layoutMessages: Partial<import('../i18n/types.js').LocaleMessages>, options: import('./types.js').StateNodeOptions) => import('../i18n/types.js').LocaleMessages} */
|
|
61
62
|
const produceStateNodeMessages = produce((draft, layoutMessages, options) => {
|
|
62
63
|
Object.assign(draft, options.messages, layoutMessages)
|
|
63
64
|
})
|
|
@@ -76,10 +77,10 @@ const produceStateNodeData = produce((draft, parentDataPath, children) => {
|
|
|
76
77
|
}
|
|
77
78
|
})
|
|
78
79
|
|
|
79
|
-
/** @type {(draft: import('./types.js').
|
|
80
|
-
const produceNodeOptions = produce((draft, parentNodeOptions, nodeOptions = {}
|
|
80
|
+
/** @type {(draft: import('./types.js').StateNodeOptions, parentNodeOptions: import('./types.js').StateNodeOptions, nodeOptions: Partial<import('./types.js').StateNodeOptions> | undefined) => import('./types.js').StateNodeOptions} */
|
|
81
|
+
const produceNodeOptions = produce((draft, parentNodeOptions, nodeOptions = {}) => {
|
|
81
82
|
for (const key in parentNodeOptions) {
|
|
82
|
-
draft[key] = parentNodeOptions[key]
|
|
83
|
+
draft[key] = nodeOptions[key] ?? parentNodeOptions[key]
|
|
83
84
|
}
|
|
84
85
|
for (const key in nodeOptions) {
|
|
85
86
|
draft[key] = nodeOptions[key]
|
|
@@ -90,16 +91,15 @@ const produceNodeOptions = produce((draft, parentNodeOptions, nodeOptions = {},
|
|
|
90
91
|
delete draft[key]
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
|
-
draft.width = width
|
|
94
94
|
})
|
|
95
95
|
|
|
96
|
-
/** @type {(draft: import('./types.js').
|
|
96
|
+
/** @type {(draft: import('./types.js').StateNodeOptions) => import('./types.js').StateNodeOptions} */
|
|
97
97
|
const produceReadonlyArrayItemOptions = produce((draft) => {
|
|
98
98
|
draft.readOnly = true
|
|
99
99
|
draft.summary = true
|
|
100
100
|
})
|
|
101
101
|
|
|
102
|
-
/** @type {(draft: import('./types.js').
|
|
102
|
+
/** @type {(draft: import('./types.js').StateNodeOptions, section: import('@json-layout/vocabulary').CompositeCompObject) => import('./types.js').StateNodeOptions} */
|
|
103
103
|
const produceCompositeChildrenOptions = produce((draft, section) => {
|
|
104
104
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
105
105
|
if (section.title && draft.titleDepth < 6) draft.titleDepth += 1
|
|
@@ -134,42 +134,51 @@ const matchChildError = (error, skeleton, dataPath) => {
|
|
|
134
134
|
* @param {import('../index.js').CompiledExpression[]} expressions
|
|
135
135
|
* @param {import('@json-layout/vocabulary').Expression} expression
|
|
136
136
|
* @param {any} data
|
|
137
|
-
* @param {import('./types.js').
|
|
137
|
+
* @param {import('./types.js').StateNodeOptions} options
|
|
138
138
|
* @param {import('./utils/display.js').Display} display
|
|
139
|
+
* @param {unknown} rootData
|
|
140
|
+
* @param {unknown} parentData
|
|
139
141
|
* @returns {any}
|
|
140
142
|
*/
|
|
141
|
-
export function evalExpression (expressions, expression, data, options, display) {
|
|
143
|
+
export function evalExpression (expressions, expression, data, options, display, rootData, parentData) {
|
|
142
144
|
if (expression.ref === undefined) throw new Error('expression was not compiled : ' + JSON.stringify(expression))
|
|
143
145
|
const compiledExpression = expressions[expression.ref]
|
|
144
|
-
|
|
145
|
-
return compiledExpression(data, options, options.context, display)
|
|
146
|
+
return expression.pure ? compiledExpression(data, options, options.context, display) : compiledExpression(data, options, options.context, display, rootData, parentData)
|
|
146
147
|
}
|
|
147
148
|
|
|
148
149
|
/**
|
|
149
150
|
* @param {import('@json-layout/vocabulary').NormalizedLayout} normalizedLayout
|
|
150
|
-
* @param {import('./types.js').
|
|
151
|
+
* @param {import('./types.js').StateNodeOptions} options
|
|
151
152
|
* @param {import('../index.js').CompiledLayout} compiledLayout
|
|
152
153
|
* @param {import('./utils/display.js').Display} display
|
|
153
154
|
* @param {unknown} data
|
|
155
|
+
* @param {unknown} rootData
|
|
156
|
+
* @param {unknown} parentData
|
|
154
157
|
* @returns {import('@json-layout/vocabulary').CompObject}
|
|
155
158
|
*/
|
|
156
|
-
const getCompObject = (normalizedLayout, options, compiledLayout, display, data) => {
|
|
159
|
+
const getCompObject = (normalizedLayout, options, compiledLayout, display, data, rootData, parentData) => {
|
|
157
160
|
if (isSwitchStruct(normalizedLayout)) {
|
|
158
161
|
for (const compObject of normalizedLayout.switch) {
|
|
159
|
-
if (!compObject.if || !!evalExpression(compiledLayout.expressions, compObject.if, data, options, display)) {
|
|
162
|
+
if (!compObject.if || !!evalExpression(compiledLayout.expressions, compObject.if, data, options, display, parentData, rootData)) {
|
|
160
163
|
return compObject
|
|
161
164
|
}
|
|
162
165
|
}
|
|
163
166
|
} else {
|
|
164
|
-
|
|
167
|
+
if (normalizedLayout.if) {
|
|
168
|
+
if (evalExpression(compiledLayout.expressions, normalizedLayout.if, data, options, display, parentData, rootData)) {
|
|
169
|
+
return normalizedLayout
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
return normalizedLayout
|
|
173
|
+
}
|
|
165
174
|
}
|
|
166
|
-
|
|
175
|
+
return { comp: 'none' }
|
|
167
176
|
}
|
|
168
177
|
|
|
169
178
|
/**
|
|
170
179
|
*
|
|
171
180
|
* @param {import('./types.js').CreateStateTreeContext} context
|
|
172
|
-
* @param {import('./types.js').
|
|
181
|
+
* @param {import('./types.js').StateNodeOptions} parentOptions
|
|
173
182
|
* @param {import('../index.js').CompiledLayout} compiledLayout
|
|
174
183
|
* @param {string | number} key
|
|
175
184
|
* @param {string} fullKey
|
|
@@ -180,6 +189,7 @@ const getCompObject = (normalizedLayout, options, compiledLayout, display, data)
|
|
|
180
189
|
* @param {import('@json-layout/vocabulary').Child | null} childDefinition
|
|
181
190
|
* @param {import('./utils/display.js').Display} parentDisplay
|
|
182
191
|
* @param {unknown} data
|
|
192
|
+
* @param {unknown} parentData
|
|
183
193
|
* @param {import('./types.js').ValidationState} validationState
|
|
184
194
|
* @param {import('./types.js').StateNode} [reusedNode]
|
|
185
195
|
* @returns {import('./types.js').StateNode}
|
|
@@ -197,23 +207,35 @@ export function createStateNode (
|
|
|
197
207
|
childDefinition,
|
|
198
208
|
parentDisplay,
|
|
199
209
|
data,
|
|
210
|
+
parentData,
|
|
200
211
|
validationState,
|
|
201
212
|
reusedNode
|
|
202
213
|
) {
|
|
214
|
+
/** @type {import('./types.js').StateNodeCacheKey | null} */
|
|
215
|
+
let cacheKey = null
|
|
216
|
+
if (skeleton.pure && reusedNode) {
|
|
217
|
+
cacheKey = [parentOptions, compiledLayout, fullKey, skeleton, childDefinition, parentDisplay.width, validationState, context.activeItems, context.initial, data]
|
|
218
|
+
if (context.cacheKeys[fullKey] && shallowEqualArray(context.cacheKeys[fullKey], cacheKey)) {
|
|
219
|
+
context.nodes.push(reusedNode)
|
|
220
|
+
return reusedNode
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
203
224
|
const normalizedLayout = childDefinition && childIsCompObject(childDefinition)
|
|
204
225
|
? childDefinition
|
|
205
226
|
: compiledLayout.normalizedLayouts[skeleton.pointer]
|
|
206
|
-
const layout = getCompObject(normalizedLayout, parentOptions, compiledLayout, parentDisplay, data)
|
|
227
|
+
const layout = getCompObject(normalizedLayout, parentOptions, compiledLayout, parentDisplay, data, context.rootData, parentData)
|
|
207
228
|
const [display, cols] = getChildDisplay(parentDisplay, childDefinition?.cols ?? layout.cols)
|
|
208
229
|
|
|
209
|
-
const options =
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
const options = layout.options
|
|
231
|
+
? produceNodeOptions(
|
|
232
|
+
reusedNode?.options ?? /** @type {import('./types.js').StateNodeOptions} */({}),
|
|
233
|
+
parentOptions,
|
|
234
|
+
layout.options
|
|
235
|
+
)
|
|
236
|
+
: parentOptions
|
|
215
237
|
|
|
216
|
-
if (context.initial && parentOptions.autofocus && layout.autofocus) {
|
|
238
|
+
if (context.initial && parentOptions.autofocus && layout.autofocus && layout.comp !== 'none') {
|
|
217
239
|
context.autofocusTarget = fullKey
|
|
218
240
|
}
|
|
219
241
|
|
|
@@ -244,6 +266,7 @@ export function createStateNode (
|
|
|
244
266
|
childLayout,
|
|
245
267
|
display,
|
|
246
268
|
isSameData ? objectData : objectData[childLayout.key],
|
|
269
|
+
objectData,
|
|
247
270
|
validationState,
|
|
248
271
|
reusedNode?.children?.[i]
|
|
249
272
|
)
|
|
@@ -257,7 +280,7 @@ export function createStateNode (
|
|
|
257
280
|
/** @type {number} */
|
|
258
281
|
const activeChildTreeIndex = fullKey in context.activeItems ? context.activeItems[fullKey] : skeleton.childrenTrees?.findIndex((childTree) => compiledLayout.validates[childTree.root.pointer](data))
|
|
259
282
|
if (activeChildTreeIndex !== -1) {
|
|
260
|
-
context.activeItems[fullKey] = activeChildTreeIndex
|
|
283
|
+
context.activeItems = produce(context.activeItems, draft => { draft[fullKey] = activeChildTreeIndex })
|
|
261
284
|
const activeChildKey = `${fullKey}/${activeChildTreeIndex}`
|
|
262
285
|
if (context.autofocusTarget === fullKey) context.autofocusTarget = activeChildKey
|
|
263
286
|
const activeChildTree = skeleton.childrenTrees[activeChildTreeIndex]
|
|
@@ -275,6 +298,7 @@ export function createStateNode (
|
|
|
275
298
|
null,
|
|
276
299
|
display,
|
|
277
300
|
data,
|
|
301
|
+
data,
|
|
278
302
|
validationState,
|
|
279
303
|
reusedNode?.children?.[0]
|
|
280
304
|
)
|
|
@@ -305,6 +329,7 @@ export function createStateNode (
|
|
|
305
329
|
null,
|
|
306
330
|
display,
|
|
307
331
|
itemData,
|
|
332
|
+
arrayData,
|
|
308
333
|
validationState,
|
|
309
334
|
reusedNode?.children?.[0]
|
|
310
335
|
)
|
|
@@ -325,10 +350,10 @@ export function createStateNode (
|
|
|
325
350
|
|
|
326
351
|
let nodeData = children ? produceStateNodeData(/** @type {Record<string, unknown>} */(data ?? {}), dataPath, children) : data
|
|
327
352
|
if (layout.constData) {
|
|
328
|
-
nodeData = evalExpression(compiledLayout.expressions, layout.constData, nodeData, options, display)
|
|
353
|
+
nodeData = evalExpression(compiledLayout.expressions, layout.constData, nodeData, options, display, context.rootData, parentData)
|
|
329
354
|
} else {
|
|
330
355
|
if (layout.defaultData && useDefaultData(nodeData, layout, options)) {
|
|
331
|
-
nodeData = evalExpression(compiledLayout.expressions, layout.defaultData, nodeData, options, display)
|
|
356
|
+
nodeData = evalExpression(compiledLayout.expressions, layout.defaultData, nodeData, options, display, context.rootData, parentData)
|
|
332
357
|
} else {
|
|
333
358
|
if (isDataEmpty(nodeData)) {
|
|
334
359
|
if (layout.nullable) {
|
|
@@ -355,15 +380,19 @@ export function createStateNode (
|
|
|
355
380
|
parentDataPath,
|
|
356
381
|
skeleton,
|
|
357
382
|
layout,
|
|
383
|
+
display.width,
|
|
358
384
|
cols,
|
|
359
385
|
nodeData,
|
|
360
386
|
error?.message,
|
|
361
387
|
validated,
|
|
362
388
|
options,
|
|
363
389
|
autofocus,
|
|
364
|
-
children &&
|
|
390
|
+
children && shallowProduceArray(reusedNode?.children, children)
|
|
365
391
|
)
|
|
392
|
+
|
|
366
393
|
context.nodes.push(node)
|
|
394
|
+
if (cacheKey) context.cacheKeys[fullKey] = cacheKey
|
|
395
|
+
|
|
367
396
|
return node
|
|
368
397
|
}
|
|
369
398
|
|
package/src/state/state-tree.js
CHANGED
package/src/state/types.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type ErrorObject } from 'ajv'
|
|
|
2
2
|
import {
|
|
3
3
|
type CompObject,
|
|
4
4
|
type Cols,
|
|
5
|
-
type
|
|
5
|
+
type StateNodeOptionsBase,
|
|
6
6
|
type TextField,
|
|
7
7
|
type Textarea,
|
|
8
8
|
type NumberField,
|
|
@@ -22,9 +22,10 @@ import {
|
|
|
22
22
|
type ExpansionPanels,
|
|
23
23
|
type Stepper,
|
|
24
24
|
type List,
|
|
25
|
-
type Combobox
|
|
25
|
+
type Combobox,
|
|
26
|
+
type Child
|
|
26
27
|
} from '@json-layout/vocabulary'
|
|
27
|
-
import { type SkeletonTree, type SkeletonNode, type StatefulLayout } from '../index.js'
|
|
28
|
+
import { type SkeletonTree, type SkeletonNode, type StatefulLayout, type CompiledLayout } from '../index.js'
|
|
28
29
|
import { type LocaleMessages } from '../i18n/types.js'
|
|
29
30
|
|
|
30
31
|
export interface StateNode {
|
|
@@ -40,7 +41,8 @@ export interface StateNode {
|
|
|
40
41
|
error: string | undefined
|
|
41
42
|
childError: boolean | undefined
|
|
42
43
|
validated: boolean
|
|
43
|
-
|
|
44
|
+
width: number
|
|
45
|
+
options: StateNodeOptions
|
|
44
46
|
messages: LocaleMessages
|
|
45
47
|
autofocus?: boolean
|
|
46
48
|
autofocusChild?: string | number
|
|
@@ -59,8 +61,24 @@ export interface CreateStateTreeContext {
|
|
|
59
61
|
activeItems: Record<string, number>
|
|
60
62
|
autofocusTarget: string | null
|
|
61
63
|
initial: boolean
|
|
64
|
+
cacheKeys: Record<string, StateNodeCacheKey>
|
|
65
|
+
rootData: unknown
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
// [parentOptions, compiledLayout, fullKey, skeleton, childDefinition, parentWidth, validationState, activeItems, initial, data]
|
|
69
|
+
export type StateNodeCacheKey = [
|
|
70
|
+
StateNodeOptions,
|
|
71
|
+
CompiledLayout,
|
|
72
|
+
string,
|
|
73
|
+
SkeletonNode,
|
|
74
|
+
Child | null,
|
|
75
|
+
number,
|
|
76
|
+
ValidationState,
|
|
77
|
+
Record<string, number>,
|
|
78
|
+
boolean,
|
|
79
|
+
unknown
|
|
80
|
+
]
|
|
81
|
+
|
|
64
82
|
export interface ValidationState {
|
|
65
83
|
initialized: boolean
|
|
66
84
|
validatedForm: boolean
|
|
@@ -75,14 +93,17 @@ export type StatefulLayoutEvents = {
|
|
|
75
93
|
autofocus: string
|
|
76
94
|
}
|
|
77
95
|
|
|
78
|
-
export type
|
|
96
|
+
export type StateNodeOptions = Required<StateNodeOptionsBase & {
|
|
79
97
|
context: Record<string, any>
|
|
80
|
-
width: number
|
|
81
98
|
validateOn: 'input' | 'blur' | 'submit'
|
|
82
99
|
initialValidation: 'never' | 'always' | 'withData'
|
|
83
100
|
defaultOn: 'missing' | 'empty' | 'never'
|
|
84
101
|
messages: LocaleMessages
|
|
85
102
|
autofocus: boolean
|
|
103
|
+
}>
|
|
104
|
+
|
|
105
|
+
export type StatefulLayoutOptions = StateNodeOptions & {
|
|
106
|
+
width: number
|
|
86
107
|
}
|
|
87
108
|
|
|
88
109
|
export type TextFieldNode = Omit<StateNode, 'children'> & { layout: TextField, data: string | undefined | null }
|
|
@@ -4,8 +4,20 @@
|
|
|
4
4
|
* @param {ItemType[]} a2
|
|
5
5
|
* @returns {ItemType[]}
|
|
6
6
|
*/
|
|
7
|
-
export function
|
|
7
|
+
export function shallowProduceArray (a1 = [], a2 = []) {
|
|
8
8
|
if (!a1 || !a2 || a1.length !== a2.length) return a2
|
|
9
9
|
for (let i = 0; i < a1.length; i++) { if (a1[i] !== a2[i]) return a2 }
|
|
10
10
|
return a1
|
|
11
11
|
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @template ItemType
|
|
15
|
+
* @param {any[]} a1
|
|
16
|
+
* @param {any[]} a2
|
|
17
|
+
* @returns {boolean}
|
|
18
|
+
*/
|
|
19
|
+
export function shallowEqualArray (a1 = [], a2 = []) {
|
|
20
|
+
if (a1.length !== a2.length) return false
|
|
21
|
+
for (let i = 0; i < a1.length; i++) { if (a1[i] !== a2[i]) return false }
|
|
22
|
+
return true
|
|
23
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compile/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compile/index.js"],"names":[],"mappings":"AAmEA;;;;GAIG;AACH,iCAJW,MAAM,4EAEJ,cAAc,CA6E1B;;2BAnIY,OAAO,YAAY,EAAE,YAAY;2BACjC,OAAO,YAAY,EAAE,YAAY;6BACjC,OAAO,YAAY,EAAE,cAAc;6BACnC,OAAO,YAAY,EAAE,cAAc;oCACnC,OAAO,YAAY,EAAE,qBAAqB;iCAC1C,OAAO,YAAY,EAAE,kBAAkB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skeleton-node.d.ts","sourceRoot":"","sources":["../../src/compile/skeleton-node.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"skeleton-node.d.ts","sourceRoot":"","sources":["../../src/compile/skeleton-node.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,yCAZW,GAAG,WACH,OAAO,YAAY,EAAE,cAAc,aACnC,MAAM,EAAE,oBACR,OAAO,MAAM,EAAE,MAAM,EAAE,CAAC,qBACxB,OAAO,MAAM,EAAE,OAAO,yBAAyB,EAAE,gBAAgB,CAAC,eAClE,OAAO,yBAAyB,EAAE,UAAU,EAAE,OAC9C,MAAM,GAAG,MAAM,WACf,MAAM,iBACN,MAAM,GAAG,IAAI,YACb,OAAO,GACL,OAAO,YAAY,EAAE,YAAY,CAuL7C"}
|
package/types/compile/types.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type ajvModule from 'ajv';
|
|
2
2
|
import type MarkdownIt from 'markdown-it';
|
|
3
|
-
import { type NormalizedLayout, type
|
|
3
|
+
import { type NormalizedLayout, type StateNodeOptionsBase } from '@json-layout/vocabulary';
|
|
4
4
|
import { type ValidateFunction, type SchemaObject } from 'ajv';
|
|
5
5
|
import { type Display } from '../state/utils/display.js';
|
|
6
6
|
import { type LocaleMessages } from '../i18n/types.js';
|
|
7
|
-
export type CompiledExpression = (data: any, options:
|
|
7
|
+
export type CompiledExpression = (data: any, options: StateNodeOptionsBase, context: object, display: Display, rootData?: unknown, parentData?: unknown) => any;
|
|
8
8
|
export interface CompileOptions {
|
|
9
9
|
ajv: ajvModule.default;
|
|
10
10
|
code: boolean;
|
|
@@ -36,6 +36,7 @@ export interface SkeletonNode {
|
|
|
36
36
|
key: string | number;
|
|
37
37
|
pointer: string;
|
|
38
38
|
parentPointer: string | null;
|
|
39
|
+
pure: boolean;
|
|
39
40
|
children?: SkeletonNode[];
|
|
40
41
|
childrenTrees?: SkeletonTree[];
|
|
41
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/compile/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,KAAK,CAAA;AAChC,OAAO,KAAK,UAAU,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/compile/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,KAAK,CAAA;AAChC,OAAO,KAAK,UAAU,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC1F,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAoB,MAAM,KAAK,CAAA;AAChF,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,OAAO,KAAK,GAAG,CAAA;AAE/J,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,SAAS,CAAC,OAAO,CAAA;IACtB,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IAClC,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAA;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,cAAc,CAAA;CACzB;AAED,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;CAAE,CAAA;AAEtH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,YAAY,EAAE,YAAY,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IAC3C,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAC1C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACnD,WAAW,EAAE,kBAAkB,EAAE,CAAA;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,cAAc,CAAA;IACxB,cAAc,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,WAAW,EAAE,KAAK,IAAI,CAAA;CAC1D;AAID,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,YAAY,CAAA;CACnB;AAID,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAA;IACzB,aAAa,CAAC,EAAE,YAAY,EAAE,CAAA;CAC/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.js"],"names":[],"mappings":";AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,mEAAmE;AACnE,+BADkB,SAAS,GAAG,SAAS,8CACoC;AAE3E,oGAAoG;AACpG,iCADkB,SAAS,GAAG,SAAS,yHACkC;AA+BzE;IA+GE;;;;;OAKG;IACH,4BALW,OAAO,aAAa,EAAE,cAAc,gBACpC,OAAO,aAAa,EAAE,YAAY,WAClC,QAAQ,qBAAqB,CAAC,SAC9B,OAAO,EAejB;IAjID;;;OAGG;IACH,iBAFU,OAAO,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAEhD;IAEN;;;;OAIG;IACH,iCAAe;IACf,mEAAqD;IAErD;;;OAGG;IAEH,mBAAU;IACV,gDAA2C;IAE3C;;;OAGG;IACH,uBAFU,OAAO,aAAa,EAAE,YAAY,CAEhC;IAEZ;;;OAGG;IAEH,iBAAQ;IACR,uBAAuC;IAEvC;;;OAGG;IAEH,yBAAgB;IAQhB;;;OAGG;IACH,+DAOC;IAlBD;;OAEG;IACH,4DAEC;IAeD;;;OAGG;IAEH,iBAAQ;IAKR;;OAEG;IACH,6DAGC;IAVD;;OAEG;IACH,0DAAuC;IASvC;;;OAGG;IACH,cAAK;IAEL,uBAIC;IALD,oBAAiC;IAOjC;;;OAGG;IAEH,oCAA2B;IAE3B;;;OAGG;IACH,yBAAgB;IAChB;;;OAGG;IACH,iCAAwB;IAkQxB;;OAEG;IACH,aAFU,OAAO,MAAM,EAAE,MAAM,CAAC,CAErB;IA9OX;;;OAGG;IACH,uBAGC;IAED;;OAEG;IACH,4BAOC;IAED;;OAEG;IACH,oBAWC;IAED;;OAEG;IACH,wBA6BC;IAED,iBAEC;IAED,wBAGC;IAED;;OAEG;IACH,qBAEC;IAED;;OAEG;IACH,uBAEC;IAED;;OAEG;IACH,8BAEC;IAED;;;;OAIG;IACH,YAJW,SAAS,QACT,OAAO,0CAyBjB;IAED;;OAEG;IACH,WAFW,SAAS,QAUnB;IAED;;OAEG;IACH,0BAFW,SAAS,QASnB;IAED;;;;;OAKG;IACH,uBA6DC;IAED;;;;OAIG;IACH,eAJW,SAAS,MACT,MAAM,GACJ,QAAQ,OAAO,yBAAyB,EAAE,WAAW,CAAC,CAMlE;IAOD;;;OAGG;IACH,mBAHW,SAAS,OACT,MAAM,QAWhB;IAED;;OAEG;IACH,qBAFW,SAAS,QAKnB;IAED,wBASC;CACF;wBAndY,OAAO,YAAY,EAAE,SAAS;wBAC9B,OAAO,YAAY,EAAE,SAAS;oCAC9B,OAAO,YAAY,EAAE,qBAAqB;mCAC1C,OAAO,YAAY,EAAE,oBAAoB;qCACzC,OAAO,YAAY,EAAE,sBAAsB;4BAC3C,OAAO,YAAY,EAAE,aAAa;2BAClC,OAAO,YAAY,EAAE,YAAY;8BACjC,OAAO,YAAY,EAAE,eAAe;yBACpC,OAAO,YAAY,EAAE,UAAU;0BAC/B,OAAO,YAAY,EAAE,WAAW;yBAChC,OAAO,YAAY,EAAE,UAAU;+BAC/B,OAAO,YAAY,EAAE,gBAAgB;2BACrC,OAAO,YAAY,EAAE,YAAY;2BACjC,OAAO,YAAY,EAAE,YAAY;yBACjC,OAAO,YAAY,EAAE,UAAU;8BAC/B,OAAO,YAAY,EAAE,eAAe;6BACpC,OAAO,YAAY,EAAE,cAAc;iCACnC,OAAO,YAAY,EAAE,kBAAkB;6BACvC,OAAO,YAAY,EAAE,cAAc;kCACnC,OAAO,YAAY,EAAE,mBAAmB;uBACxC,OAAO,YAAY,EAAE,QAAQ;+BAC7B,OAAO,YAAY,EAAE,gBAAgB;0BACrC,OAAO,YAAY,EAAE,WAAW;8BAChC,OAAO,YAAY,EAAE,eAAe;uBACpC,OAAO,YAAY,EAAE,QAAQ;wBA9BlB,oBAAoB"}
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
* @param {import('../index.js').CompiledExpression[]} expressions
|
|
3
3
|
* @param {import('@json-layout/vocabulary').Expression} expression
|
|
4
4
|
* @param {any} data
|
|
5
|
-
* @param {import('./types.js').
|
|
5
|
+
* @param {import('./types.js').StateNodeOptions} options
|
|
6
6
|
* @param {import('./utils/display.js').Display} display
|
|
7
|
+
* @param {unknown} rootData
|
|
8
|
+
* @param {unknown} parentData
|
|
7
9
|
* @returns {any}
|
|
8
10
|
*/
|
|
9
|
-
export function evalExpression(expressions: import('../index.js').CompiledExpression[], expression: import('@json-layout/vocabulary').Expression, data: any, options: import('./types.js').
|
|
11
|
+
export function evalExpression(expressions: import('../index.js').CompiledExpression[], expression: import('@json-layout/vocabulary').Expression, data: any, options: import('./types.js').StateNodeOptions, display: import('./utils/display.js').Display, rootData: unknown, parentData: unknown): any;
|
|
10
12
|
/**
|
|
11
13
|
*
|
|
12
14
|
* @param {import('./types.js').CreateStateTreeContext} context
|
|
13
|
-
* @param {import('./types.js').
|
|
15
|
+
* @param {import('./types.js').StateNodeOptions} parentOptions
|
|
14
16
|
* @param {import('../index.js').CompiledLayout} compiledLayout
|
|
15
17
|
* @param {string | number} key
|
|
16
18
|
* @param {string} fullKey
|
|
@@ -21,11 +23,12 @@ export function evalExpression(expressions: import('../index.js').CompiledExpres
|
|
|
21
23
|
* @param {import('@json-layout/vocabulary').Child | null} childDefinition
|
|
22
24
|
* @param {import('./utils/display.js').Display} parentDisplay
|
|
23
25
|
* @param {unknown} data
|
|
26
|
+
* @param {unknown} parentData
|
|
24
27
|
* @param {import('./types.js').ValidationState} validationState
|
|
25
28
|
* @param {import('./types.js').StateNode} [reusedNode]
|
|
26
29
|
* @returns {import('./types.js').StateNode}
|
|
27
30
|
*/
|
|
28
|
-
export function createStateNode(context: import('./types.js').CreateStateTreeContext, parentOptions: import('./types.js').
|
|
31
|
+
export function createStateNode(context: import('./types.js').CreateStateTreeContext, parentOptions: import('./types.js').StateNodeOptions, compiledLayout: import('../index.js').CompiledLayout, key: string | number, fullKey: string, parentFullKey: string | null, dataPath: string, parentDataPath: string | null, skeleton: import('../index.js').SkeletonNode, childDefinition: import('@json-layout/vocabulary').Child | null, parentDisplay: import('./utils/display.js').Display, data: unknown, parentData: unknown, validationState: import('./types.js').ValidationState, reusedNode?: import("./types.js").StateNode | undefined): import('./types.js').StateNode;
|
|
29
32
|
/** @type {(draft: any, node: import('./types.js').StateNode, data: unknown) => any} */
|
|
30
33
|
export const producePatchedData: (draft: any, node: import('./types.js').StateNode, data: unknown) => any;
|
|
31
34
|
//# sourceMappingURL=state-node.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-node.d.ts","sourceRoot":"","sources":["../../src/state/state-node.js"],"names":[],"mappings":"AAoIA
|
|
1
|
+
{"version":3,"file":"state-node.d.ts","sourceRoot":"","sources":["../../src/state/state-node.js"],"names":[],"mappings":"AAoIA;;;;;;;;;GASG;AACH,4CATW,OAAO,aAAa,EAAE,kBAAkB,EAAE,cAC1C,OAAO,yBAAyB,EAAE,UAAU,QAC5C,GAAG,WACH,OAAO,YAAY,EAAE,gBAAgB,WACrC,OAAO,oBAAoB,EAAE,OAAO,YACpC,OAAO,cACP,OAAO,GACL,GAAG,CAMf;AA+BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,yCAjBW,OAAO,YAAY,EAAE,sBAAsB,iBAC3C,OAAO,YAAY,EAAE,gBAAgB,kBACrC,OAAO,aAAa,EAAE,cAAc,OACpC,MAAM,GAAG,MAAM,WACf,MAAM,iBACN,MAAM,GAAG,IAAI,YACb,MAAM,kBACN,MAAM,GAAG,IAAI,YACb,OAAO,aAAa,EAAE,YAAY,mBAClC,OAAO,yBAAyB,EAAE,KAAK,GAAG,IAAI,iBAC9C,OAAO,oBAAoB,EAAE,OAAO,QACpC,OAAO,cACP,OAAO,mBACP,OAAO,YAAY,EAAE,eAAe,4DAElC,OAAO,YAAY,EAAE,SAAS,CA0M1C;AAED,uFAAuF;AACvF,yCADmB,GAAG,QAAQ,OAAO,YAAY,EAAE,SAAS,QAAQ,OAAO,KAAK,GAAG,CAOjF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-tree.d.ts","sourceRoot":"","sources":["../../src/state/state-tree.js"],"names":[],"mappings":"AAWA;;;;;;;;;;GAUG;AACH,yCAVW,OAAO,YAAY,EAAE,sBAAsB,WAC3C,OAAO,YAAY,EAAE,qBAAqB,kBAC1C,OAAO,aAAa,EAAE,cAAc,YACpC,OAAO,aAAa,EAAE,YAAY,WAClC,OAAO,oBAAoB,EAAE,OAAO,QACpC,OAAO,mBACP,OAAO,YAAY,EAAE,eAAe,iEAElC,OAAO,YAAY,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"state-tree.d.ts","sourceRoot":"","sources":["../../src/state/state-tree.js"],"names":[],"mappings":"AAWA;;;;;;;;;;GAUG;AACH,yCAVW,OAAO,YAAY,EAAE,sBAAsB,WAC3C,OAAO,YAAY,EAAE,qBAAqB,kBAC1C,OAAO,aAAa,EAAE,cAAc,YACpC,OAAO,aAAa,EAAE,YAAY,WAClC,OAAO,oBAAoB,EAAE,OAAO,QACpC,OAAO,mBACP,OAAO,YAAY,EAAE,eAAe,iEAElC,OAAO,YAAY,EAAE,SAAS,CAuC1C"}
|
package/types/state/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ErrorObject } from 'ajv';
|
|
2
|
-
import { type CompObject, type Cols, type
|
|
3
|
-
import { type SkeletonTree, type SkeletonNode, type StatefulLayout } from '../index.js';
|
|
2
|
+
import { type CompObject, type Cols, type StateNodeOptionsBase, type TextField, type Textarea, type NumberField, type Slider, type Checkbox, type Switch, type DatePicker, type DateTimePicker, type TimePicker, type ColorPicker, type Section, type OneOfSelect, type Select, type Autocomplete, type Tabs, type VerticalTabs, type ExpansionPanels, type Stepper, type List, type Combobox, type Child } from '@json-layout/vocabulary';
|
|
3
|
+
import { type SkeletonTree, type SkeletonNode, type StatefulLayout, type CompiledLayout } from '../index.js';
|
|
4
4
|
import { type LocaleMessages } from '../i18n/types.js';
|
|
5
5
|
export interface StateNode {
|
|
6
6
|
key: string | number;
|
|
@@ -15,7 +15,8 @@ export interface StateNode {
|
|
|
15
15
|
error: string | undefined;
|
|
16
16
|
childError: boolean | undefined;
|
|
17
17
|
validated: boolean;
|
|
18
|
-
|
|
18
|
+
width: number;
|
|
19
|
+
options: StateNodeOptions;
|
|
19
20
|
messages: LocaleMessages;
|
|
20
21
|
autofocus?: boolean;
|
|
21
22
|
autofocusChild?: string | number;
|
|
@@ -32,7 +33,21 @@ export interface CreateStateTreeContext {
|
|
|
32
33
|
activeItems: Record<string, number>;
|
|
33
34
|
autofocusTarget: string | null;
|
|
34
35
|
initial: boolean;
|
|
36
|
+
cacheKeys: Record<string, StateNodeCacheKey>;
|
|
37
|
+
rootData: unknown;
|
|
35
38
|
}
|
|
39
|
+
export type StateNodeCacheKey = [
|
|
40
|
+
StateNodeOptions,
|
|
41
|
+
CompiledLayout,
|
|
42
|
+
string,
|
|
43
|
+
SkeletonNode,
|
|
44
|
+
Child | null,
|
|
45
|
+
number,
|
|
46
|
+
ValidationState,
|
|
47
|
+
Record<string, number>,
|
|
48
|
+
boolean,
|
|
49
|
+
unknown
|
|
50
|
+
];
|
|
36
51
|
export interface ValidationState {
|
|
37
52
|
initialized: boolean;
|
|
38
53
|
validatedForm: boolean;
|
|
@@ -43,14 +58,16 @@ export type StatefulLayoutEvents = {
|
|
|
43
58
|
'update': StatefulLayout;
|
|
44
59
|
autofocus: string;
|
|
45
60
|
};
|
|
46
|
-
export type
|
|
61
|
+
export type StateNodeOptions = Required<StateNodeOptionsBase & {
|
|
47
62
|
context: Record<string, any>;
|
|
48
|
-
width: number;
|
|
49
63
|
validateOn: 'input' | 'blur' | 'submit';
|
|
50
64
|
initialValidation: 'never' | 'always' | 'withData';
|
|
51
65
|
defaultOn: 'missing' | 'empty' | 'never';
|
|
52
66
|
messages: LocaleMessages;
|
|
53
67
|
autofocus: boolean;
|
|
68
|
+
}>;
|
|
69
|
+
export type StatefulLayoutOptions = StateNodeOptions & {
|
|
70
|
+
width: number;
|
|
54
71
|
};
|
|
55
72
|
export type TextFieldNode = Omit<StateNode, 'children'> & {
|
|
56
73
|
layout: TextField;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/state/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,KAAK,CAAA;AACtC,OAAO,EACL,KAAK,UAAU,EACf,KAAK,IAAI,EACT,KAAK,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/state/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,5 +4,12 @@
|
|
|
4
4
|
* @param {ItemType[]} a2
|
|
5
5
|
* @returns {ItemType[]}
|
|
6
6
|
*/
|
|
7
|
-
export function
|
|
7
|
+
export function shallowProduceArray<ItemType>(a1?: ItemType[], a2?: ItemType[]): ItemType[];
|
|
8
|
+
/**
|
|
9
|
+
* @template ItemType
|
|
10
|
+
* @param {any[]} a1
|
|
11
|
+
* @param {any[]} a2
|
|
12
|
+
* @returns {boolean}
|
|
13
|
+
*/
|
|
14
|
+
export function shallowEqualArray<ItemType>(a1?: any[], a2?: any[]): boolean;
|
|
8
15
|
//# sourceMappingURL=immutable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"immutable.d.ts","sourceRoot":"","sources":["../../../src/state/utils/immutable.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,
|
|
1
|
+
{"version":3,"file":"immutable.d.ts","sourceRoot":"","sources":["../../../src/state/utils/immutable.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,4FAIC;AAED;;;;;GAKG;AACH,iDAJW,GAAG,EAAE,OACL,GAAG,EAAE,GACH,OAAO,CAMnB"}
|