@json-layout/core
Advanced tools
Comparing version 0.5.0 to 0.6.0
{ | ||
"name": "@json-layout/core", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "Compilation and state management utilities for JSON Layout.", | ||
@@ -50,3 +50,3 @@ "type": "module", | ||
"dependencies": { | ||
"@json-layout/vocabulary": "^0.5.0", | ||
"@json-layout/vocabulary": "^0.6.0", | ||
"@types/markdown-it": "^13.0.1", | ||
@@ -53,0 +53,0 @@ "ajv": "^8.12.0", |
@@ -78,2 +78,4 @@ // import Debug from 'debug' | ||
if (compObject.transformData) pushExpression(expressions, compObject.transformData) | ||
if (isItemsLayout(compObject) && compObject.getItems) { | ||
@@ -80,0 +82,0 @@ if (isGetItemsExpression(compObject.getItems)) pushExpression(expressions, compObject.getItems) |
@@ -8,3 +8,4 @@ // eslint-disable-next-line import/no-named-default | ||
import { Display } from './utils/display.js' | ||
import { isGetItemsExpression, isGetItemsFetch, isItemsLayout } from '@json-layout/vocabulary' | ||
import { isFileLayout, isGetItemsExpression, isGetItemsFetch, isItemsLayout } from '@json-layout/vocabulary' | ||
import { shallowProduceArray } from './utils/immutable.js' | ||
@@ -39,2 +40,3 @@ export { Display } from './utils/display.js' | ||
* @typedef {import('./types.js').ListNode} ListNode | ||
* @typedef {import('./types.js').FileRef} FileRef | ||
*/ | ||
@@ -189,2 +191,7 @@ | ||
/** | ||
* @type {FileRef[]} | ||
*/ | ||
files = [] | ||
/** | ||
* @param {import("../index.js").CompiledLayout} compiledLayout | ||
@@ -253,3 +260,2 @@ * @param {import("../index.js").SkeletonTree} skeletonTree | ||
const createStateTreeContext = { | ||
nodes: [], | ||
activeItems: this.activeItems, | ||
@@ -259,3 +265,5 @@ autofocusTarget: this._autofocusTarget, | ||
cacheKeys: this._lastCreateStateTreeContext?.cacheKeys ?? {}, | ||
rootData: this._data | ||
rootData: this._data, | ||
files: [], | ||
nodes: [] | ||
} | ||
@@ -281,2 +289,3 @@ this._stateTree = createStateTree( | ||
this.activeItems = createStateTreeContext.activeItems | ||
this.files = shallowProduceArray(this.files, createStateTreeContext.files) | ||
} | ||
@@ -315,3 +324,17 @@ | ||
/** | ||
* @private | ||
* @param {StateNode} node | ||
* @param {import('@json-layout/vocabulary').Expression} expression | ||
* @param {any} data | ||
* @returns {any} | ||
*/ | ||
evalNodeExpression = (node, expression, data) => { | ||
// const parentNode = this._stateTree.traverseNode(this._stateTree.root).find(n => n.fullKey === node.parentFullKey) | ||
const parentNode = this._lastCreateStateTreeContext.nodes.find(n => n.fullKey === node.parentFullKey) | ||
const parentData = parentNode ? parentNode.data : null | ||
return evalExpression(this.compiledLayout.expressions, expression, data, node.options, new Display(node.width), parentData, this._data) | ||
} | ||
/** | ||
* @param {StateNode} node | ||
* @param {unknown} data | ||
@@ -322,2 +345,24 @@ * @param {number} [activateKey] | ||
logDataBinding('received input event from node', node, data) | ||
const transformedData = node.layout.transformData && this.evalNodeExpression(node, node.layout.transformData, data) | ||
if (isFileLayout(node.layout)) { | ||
if (transformedData) { | ||
// @ts-ignore | ||
data.toJSON = () => transformedData | ||
} else if (data instanceof File) { | ||
const fileJSON = { name: data.name, size: data.size, type: data.type } | ||
// @ts-ignore | ||
data.toJSON = () => fileJSON | ||
} else if (Array.isArray(data)) { | ||
for (const file of data) { | ||
const fileJSON = { name: file.name, size: file.size, type: file.type } | ||
// @ts-ignore | ||
file.toJSON = () => fileJSON | ||
} | ||
} | ||
} else if (transformedData) { | ||
data = transformedData | ||
} | ||
if (node.options.validateOn === 'input' && !this.validationState.validatedChildren.includes(node.fullKey)) { | ||
@@ -381,17 +426,10 @@ this.validationState = { validatedChildren: this.validationState.validatedChildren.concat([node.fullKey]) } | ||
/** @type {(expression: import('@json-layout/vocabulary').Expression, data: any) => any} */ | ||
const evalSelectExpression = (expression, data) => { | ||
const parentNode = this._lastCreateStateTreeContext.nodes.find(n => n.fullKey === node.parentFullKey) | ||
const parentData = parentNode ? parentNode.data : null | ||
return evalExpression(this.compiledLayout.expressions, expression, data, node.options, new Display(node.width), parentData, this._data) | ||
} | ||
let rawItems | ||
let appliedQ = false | ||
if (node.layout.getItems && isGetItemsExpression(node.layout.getItems)) { | ||
rawItems = evalSelectExpression(node.layout.getItems, null) | ||
rawItems = this.evalNodeExpression(node, node.layout.getItems, null) | ||
if (!Array.isArray(rawItems)) throw new Error('getItems expression didn\'t return an array') | ||
} | ||
if (node.layout.getItems && isGetItemsFetch(node.layout.getItems)) { | ||
const url = new URL(evalSelectExpression(node.layout.getItems.url, null)) | ||
const url = new URL(this.evalNodeExpression(node, node.layout.getItems.url, null)) | ||
let qSearchParam = node.layout.getItems.qSearchParam | ||
@@ -413,3 +451,3 @@ if (!qSearchParam) { | ||
if (node.layout.getItems?.itemsResults) { | ||
rawItems = evalSelectExpression(node.layout.getItems.itemsResults, rawItems) | ||
rawItems = this.evalNodeExpression(node, node.layout.getItems.itemsResults, rawItems) | ||
} | ||
@@ -421,5 +459,5 @@ /** @type {import('@json-layout/vocabulary').SelectItems} */ | ||
if (typeof rawItem === 'object') { | ||
item.value = node.layout.getItems?.itemValue ? evalSelectExpression(node.layout.getItems.itemValue, rawItem) : (node.layout.getItems?.returnObjects ? rawItem : rawItem.value) | ||
item.key = node.layout.getItems?.itemKey ? evalSelectExpression(node.layout.getItems.itemKey, rawItem) : rawItem.key | ||
item.title = node.layout.getItems?.itemTitle ? evalSelectExpression(node.layout.getItems.itemTitle, rawItem) : rawItem.title | ||
item.value = node.layout.getItems?.itemValue ? this.evalNodeExpression(node, node.layout.getItems.itemValue, rawItem) : (node.layout.getItems?.returnObjects ? rawItem : rawItem.value) | ||
item.key = node.layout.getItems?.itemKey ? this.evalNodeExpression(node, node.layout.getItems.itemKey, rawItem) : rawItem.key | ||
item.title = node.layout.getItems?.itemTitle ? this.evalNodeExpression(node, node.layout.getItems.itemTitle, rawItem) : rawItem.title | ||
item.value = item.value ?? item.key | ||
@@ -430,7 +468,7 @@ item.key = item.key ?? item.value + '' | ||
} else { | ||
item.value = node.layout.getItems?.itemValue ? evalSelectExpression(node.layout.getItems.itemValue, rawItem) : rawItem | ||
item.key = node.layout.getItems?.itemKey ? evalSelectExpression(node.layout.getItems.itemKey, rawItem) : item.value | ||
item.title = node.layout.getItems?.itemTitle ? evalSelectExpression(node.layout.getItems.itemTitle, rawItem) : item.value | ||
item.value = node.layout.getItems?.itemValue ? this.evalNodeExpression(node, node.layout.getItems.itemValue, rawItem) : rawItem | ||
item.key = node.layout.getItems?.itemKey ? this.evalNodeExpression(node, node.layout.getItems.itemKey, rawItem) : item.value | ||
item.title = node.layout.getItems?.itemTitle ? this.evalNodeExpression(node, node.layout.getItems.itemTitle, rawItem) : item.value | ||
} | ||
if (node.layout.getItems?.itemIcon) item.icon = evalSelectExpression(node.layout.getItems?.itemIcon, rawItem) | ||
if (node.layout.getItems?.itemIcon) item.icon = this.evalNodeExpression(node, node.layout.getItems?.itemIcon, rawItem) | ||
return item | ||
@@ -437,0 +475,0 @@ }) |
@@ -218,6 +218,3 @@ import { isSwitchStruct, childIsCompObject, isCompositeLayout, isFocusableLayout } from '@json-layout/vocabulary' | ||
cacheKey = [parentOptions, compiledLayout, fullKey, skeleton, childDefinition, parentDisplay.width, validationState, context.activeItems, context.initial, data] | ||
if (context.cacheKeys[fullKey] && shallowEqualArray(context.cacheKeys[fullKey], cacheKey)) { | ||
context.nodes.push(reusedNode) | ||
return reusedNode | ||
} | ||
if (context.cacheKeys[fullKey] && shallowEqualArray(context.cacheKeys[fullKey], cacheKey)) return reusedNode | ||
} | ||
@@ -394,3 +391,2 @@ | ||
context.nodes.push(node) | ||
if (cacheKey) context.cacheKeys[fullKey] = cacheKey | ||
@@ -397,0 +393,0 @@ |
@@ -13,2 +13,17 @@ import { produce } from 'immer' | ||
/** | ||
* @generator | ||
* @param {import('./types.js').StateNode} node | ||
* @yields {import('./types.js').StateNode} | ||
* @returns {Generator<import('./types.js').StateNode>} | ||
*/ | ||
function * traverseNodes (node) { | ||
yield node | ||
if (node.children) { | ||
for (const child of node.children) { | ||
yield * traverseNodes(child) | ||
} | ||
} | ||
} | ||
/** | ||
* @param {import('./types.js').CreateStateTreeContext} context | ||
@@ -60,3 +75,12 @@ * @param {import('./types.js').StatefulLayoutOptions} options | ||
context.nodes = [] | ||
context.files = [] | ||
for (const node of traverseNodes(root)) { | ||
context.nodes.push(node) | ||
if (node.data instanceof File) { | ||
context.files.push({ dataPath: node.dataPath, file: node.data }) | ||
} | ||
} | ||
return produceStateTree(reusedStateTree ?? /** @type {import('./types.js').StateTree} */({}), root, valid) | ||
} |
@@ -55,3 +55,2 @@ import { type ErrorObject } from 'ajv' | ||
valid: boolean | ||
title: string | ||
} | ||
@@ -61,3 +60,3 @@ | ||
errors?: ErrorObject[] | ||
nodes: StateNode[] | ||
files: FileRef[] | ||
activeItems: Record<string, number> | ||
@@ -68,4 +67,10 @@ autofocusTarget: string | null | ||
rootData: unknown | ||
nodes: StateNode[] | ||
} | ||
export interface FileRef { | ||
file: File | ||
dataPath: string | ||
} | ||
// [parentOptions, compiledLayout, fullKey, skeleton, childDefinition, parentWidth, validationState, activeItems, initial, data] | ||
@@ -72,0 +77,0 @@ export type StateNodeCacheKey = [ |
/** | ||
* @template ItemType | ||
* @param {ItemType[]} a1 | ||
* @param {ItemType[]} a2 | ||
* @param {ItemType[]} previousArray | ||
* @param {ItemType[]} newArray | ||
* @returns {ItemType[]} | ||
*/ | ||
export function shallowProduceArray (a1 = [], a2 = []) { | ||
if (!a1 || !a2 || a1.length !== a2.length) return a2 | ||
for (let i = 0; i < a1.length; i++) { if (a1[i] !== a2[i]) return a2 } | ||
return a1 | ||
export function shallowProduceArray (previousArray = [], newArray = []) { | ||
if (!previousArray || !newArray || previousArray.length !== newArray.length) return newArray | ||
for (let i = 0; i < previousArray.length; i++) { if (previousArray[i] !== newArray[i]) return newArray } | ||
return previousArray | ||
} | ||
@@ -12,0 +12,0 @@ |
@@ -28,2 +28,3 @@ export { Display } from "./utils/display.js"; | ||
* @typedef {import('./types.js').ListNode} ListNode | ||
* @typedef {import('./types.js').FileRef} FileRef | ||
*/ | ||
@@ -121,2 +122,6 @@ /** @type {(node: StateNode | undefined) => node is SectionNode} */ | ||
/** | ||
* @type {FileRef[]} | ||
*/ | ||
files: FileRef[]; | ||
/** | ||
* @type {Record<string, number>} | ||
@@ -157,3 +162,11 @@ */ | ||
/** | ||
* @private | ||
* @param {StateNode} node | ||
* @param {import('@json-layout/vocabulary').Expression} expression | ||
* @param {any} data | ||
* @returns {any} | ||
*/ | ||
private evalNodeExpression; | ||
/** | ||
* @param {StateNode} node | ||
* @param {unknown} data | ||
@@ -220,3 +233,4 @@ * @param {number} [activateKey] | ||
export type ListNode = import('./types.js').ListNode; | ||
export type FileRef = import('./types.js').FileRef; | ||
import { Display } from './utils/display.js'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -28,7 +28,6 @@ import { type ErrorObject } from 'ajv'; | ||
valid: boolean; | ||
title: string; | ||
} | ||
export interface CreateStateTreeContext { | ||
errors?: ErrorObject[]; | ||
nodes: StateNode[]; | ||
files: FileRef[]; | ||
activeItems: Record<string, number>; | ||
@@ -39,3 +38,8 @@ autofocusTarget: string | null; | ||
rootData: unknown; | ||
nodes: StateNode[]; | ||
} | ||
export interface FileRef { | ||
file: File; | ||
dataPath: string; | ||
} | ||
export type StateNodeCacheKey = [ | ||
@@ -42,0 +46,0 @@ StateNodeOptions, |
/** | ||
* @template ItemType | ||
* @param {ItemType[]} a1 | ||
* @param {ItemType[]} a2 | ||
* @param {ItemType[]} previousArray | ||
* @param {ItemType[]} newArray | ||
* @returns {ItemType[]} | ||
*/ | ||
export function shallowProduceArray<ItemType>(a1?: ItemType[], a2?: ItemType[]): ItemType[]; | ||
export function shallowProduceArray<ItemType>(previousArray?: ItemType[], newArray?: ItemType[]): ItemType[]; | ||
/** | ||
@@ -9,0 +9,0 @@ * @template ItemType |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
111664
2514
+ Added@json-layout/vocabulary@0.6.0(transitive)
- Removed@json-layout/vocabulary@0.5.0(transitive)