@json-layout/vocabulary 0.14.0 → 0.16.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 +5 -5
- package/src/components/compile-types.js +61 -0
- package/src/components/index.js +226 -0
- package/src/components/types.ts +378 -0
- package/src/index.js +3 -0
- package/src/layout-keyword/index.js +9 -2
- package/src/layout-keyword/schema.js +67 -62
- package/src/layout-keyword/schema.json +35 -50
- package/src/layout-keyword/types.ts +111 -42
- package/src/normalize.js +95 -54
- package/src/normalized-layout/index.js +18 -64
- package/src/normalized-layout/schema.js +235 -762
- package/src/normalized-layout/schema.json +118 -324
- package/src/normalized-layout/types.ts +163 -233
- package/src/types.ts +11 -0
- package/src/validate.js +42 -0
- package/types/components/compile-types.d.ts +13 -0
- package/types/components/compile-types.d.ts.map +1 -0
- package/types/components/index.d.ts +52 -0
- package/types/components/index.d.ts.map +1 -0
- package/types/components/types.d.ts +329 -0
- package/types/components/types.d.ts.map +1 -0
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
- package/types/layout-keyword/index.d.ts +6 -1
- package/types/layout-keyword/index.d.ts.map +1 -1
- package/types/layout-keyword/schema.d.ts +43 -26
- package/types/layout-keyword/types.d.ts +111 -18
- package/types/layout-keyword/types.d.ts.map +1 -1
- package/types/normalize.d.ts +3 -2
- package/types/normalize.d.ts.map +1 -1
- package/types/normalized-layout/index.d.ts +19 -65
- package/types/normalized-layout/index.d.ts.map +1 -1
- package/types/normalized-layout/schema.d.ts +171 -526
- package/types/normalized-layout/types.d.ts +163 -208
- package/types/normalized-layout/types.d.ts.map +1 -1
- package/types/types.d.ts +10 -0
- package/types/types.d.ts.map +1 -1
- package/types/validate.d.ts +8 -0
- package/types/validate.d.ts.map +1 -0
- package/src/layout-keyword/validate.js +0 -2
- package/src/normalized-layout/validate.js +0 -3
- package/types/layout-keyword/validate.d.ts +0 -23
- package/types/layout-keyword/validate.d.ts.map +0 -1
- package/types/normalized-layout/validate.d.ts +0 -23
- package/types/normalized-layout/validate.d.ts.map +0 -1
package/src/normalize.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { validateLayoutKeyword, isComponentName, isPartialCompObject, isPartialChildren, isPartialSwitch, isPartialGetItemsExpr, isPartialGetItemsObj, isPartialSlotMarkdown, isPartialGetItemsFetch } from './layout-keyword/index.js'
|
|
2
|
-
import { validateNormalizedLayout
|
|
1
|
+
import { validateLayoutKeyword, isComponentName, isPartialCompObject, isPartialChildren, isPartialSwitch, isPartialGetItemsExpr, isPartialGetItemsObj, isPartialSlotMarkdown, isPartialGetItemsFetch, isPartialChildComposite } from './layout-keyword/index.js'
|
|
2
|
+
import { validateNormalizedLayout } from './normalized-layout/index.js'
|
|
3
|
+
import { getComponentValidate } from './validate.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* @typedef {import('./index.js').Child} Child
|
|
6
7
|
* @typedef {import('./index.js').Children} Children
|
|
7
|
-
* @typedef {import('./index.js').
|
|
8
|
+
* @typedef {import('./index.js').BaseCompObject} BaseCompObject
|
|
8
9
|
* @typedef {import('./index.js').Expression} Expression
|
|
9
10
|
* @typedef {import('./index.js').NormalizedLayout} NormalizedLayout
|
|
10
11
|
* @typedef {import('./index.js').LayoutKeyword} LayoutKeyword
|
|
@@ -55,20 +56,20 @@ function getChildren (defaultChildren, partialChildren) {
|
|
|
55
56
|
return partialChildren.map(partialChild => {
|
|
56
57
|
if (typeof partialChild === 'string') { // simple string/key referencing a known child
|
|
57
58
|
const matchingDefaultChild = defaultChildren.find(c => c.key === partialChild)
|
|
58
|
-
if (!matchingDefaultChild) throw new Error(`child
|
|
59
|
+
if (!matchingDefaultChild) throw new Error(`unknown child "${partialChild}"`)
|
|
59
60
|
return matchingDefaultChild
|
|
60
61
|
} else {
|
|
61
62
|
if (typeof partialChild.cols === 'number') partialChild.cols = { sm: partialChild.cols }
|
|
62
63
|
if (typeof partialChild.cols === 'object' && partialChild.cols.xs === undefined) partialChild.cols.xs = 12
|
|
63
64
|
if (partialChild.key) { // object referencing known child and overwriting cols
|
|
64
65
|
const matchingDefaultChild = defaultChildren.find(c => c.key === partialChild.key)
|
|
65
|
-
if (!matchingDefaultChild) throw new Error(`child
|
|
66
|
+
if (!matchingDefaultChild) throw new Error(`unknown child "${partialChild.key}"`)
|
|
66
67
|
return /** @type {Child} */ (partialChild)
|
|
67
68
|
} else { // a composite component definition, not directly related to a known child
|
|
68
69
|
const child = partialChild
|
|
69
|
-
if (
|
|
70
|
-
if (!
|
|
71
|
-
child.children = getChildren(defaultChildren,
|
|
70
|
+
if (isPartialChildComposite(child)) {
|
|
71
|
+
if (!child.comp) child.comp = 'section'
|
|
72
|
+
child.children = getChildren(defaultChildren, child.children)
|
|
72
73
|
}
|
|
73
74
|
if (!('key' in partialChild)) {
|
|
74
75
|
child.key = `$comp-${compI}`
|
|
@@ -232,42 +233,39 @@ export const getSchemaFragmentType = (schemaFragment) => {
|
|
|
232
233
|
* @param {LayoutKeyword} layoutKeyword
|
|
233
234
|
* @param {SchemaFragment} schemaFragment
|
|
234
235
|
* @param {string} schemaPath
|
|
236
|
+
* @param {Record<string, import('./types.js').ComponentInfo>} components
|
|
235
237
|
* @param {(text: string) => string} markdown
|
|
236
238
|
* @param {string[]} optionsKeys
|
|
237
239
|
* @param {'oneOf'} [arrayChild]
|
|
238
|
-
* @returns {
|
|
240
|
+
* @returns {BaseCompObject}
|
|
239
241
|
*/
|
|
240
|
-
function getCompObject (layoutKeyword, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild) {
|
|
241
|
-
/** @type {string[]} */
|
|
242
|
-
const errors = []
|
|
242
|
+
function getCompObject (layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild) {
|
|
243
243
|
const key = schemaPath.slice(schemaPath.lastIndexOf('/') + 1)
|
|
244
244
|
|
|
245
245
|
const { type, nullable } = getSchemaFragmentType(schemaFragment)
|
|
246
246
|
|
|
247
|
-
if ('const' in schemaFragment) return {
|
|
248
|
-
if (!type) return {
|
|
247
|
+
if ('const' in schemaFragment) return { comp: 'none' }
|
|
248
|
+
if (!type) return { comp: 'none' }
|
|
249
249
|
|
|
250
250
|
const partial = getPartialCompObject(layoutKeyword)
|
|
251
251
|
|
|
252
252
|
if (type === 'array' && !schemaFragment.items && partial.comp !== 'file-input') {
|
|
253
|
-
return {
|
|
253
|
+
return { comp: 'none' }
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
// chose the default component for a schema fragment
|
|
257
257
|
if (!partial.comp) {
|
|
258
|
-
|
|
259
|
-
partial.comp = getDefaultComp(partial, schemaFragment, arrayChild)
|
|
260
|
-
} catch (/** @type {any} */err) {
|
|
261
|
-
errors.push(err.message)
|
|
262
|
-
partial.comp = 'none'
|
|
263
|
-
}
|
|
258
|
+
partial.comp = getDefaultComp(partial, schemaFragment, arrayChild)
|
|
264
259
|
}
|
|
265
|
-
|
|
260
|
+
const component = components[partial.comp]
|
|
261
|
+
if (!component) {
|
|
262
|
+
throw new Error(`unknown component "${partial.comp}"`)
|
|
263
|
+
}
|
|
264
|
+
if (partial.comp === 'none') return { comp: 'none' }
|
|
266
265
|
|
|
267
266
|
if (nullable) partial.nullable = nullable
|
|
268
267
|
|
|
269
|
-
|
|
270
|
-
if (compositeCompNames.includes(partial.comp)) {
|
|
268
|
+
if (component.composite) {
|
|
271
269
|
if (!('title' in partial)) partial.title = schemaFragment.title ?? null
|
|
272
270
|
partial.children = getChildren(getDefaultChildren(schemaFragment), partial.children)
|
|
273
271
|
} else if (partial.comp === 'list') {
|
|
@@ -275,10 +273,12 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, markdown, opt
|
|
|
275
273
|
partial.listEditMode = partial.listEditMode ?? (schemaFragment.items.type === 'object' ? 'inline-single' : 'inline')
|
|
276
274
|
partial.listActions = partial.listActions ?? ['add', 'edit', 'delete', 'duplicate', 'sort']
|
|
277
275
|
} else {
|
|
278
|
-
if (!('label' in partial)
|
|
276
|
+
if (!('label' in partial) && partial.comp !== 'one-of-select') {
|
|
277
|
+
partial.label = schemaFragment.title ?? key
|
|
278
|
+
}
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
-
if (
|
|
281
|
+
if (component.itemsBased && !partial.items) {
|
|
282
282
|
let items
|
|
283
283
|
if (type === 'array') {
|
|
284
284
|
items = getItemsFromSchema(schemaFragment.items)
|
|
@@ -294,7 +294,7 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, markdown, opt
|
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
-
if (
|
|
297
|
+
if (component.multipleCompat) {
|
|
298
298
|
if (type === 'array' || partial.separator) {
|
|
299
299
|
partial.multiple = true
|
|
300
300
|
}
|
|
@@ -401,36 +401,42 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, markdown, opt
|
|
|
401
401
|
if (typeof partial.cols === 'number') partial.cols = { xs: partial.cols }
|
|
402
402
|
if (typeof partial.cols === 'object' && partial.cols.xs === undefined) partial.cols.xs = 12
|
|
403
403
|
|
|
404
|
-
|
|
404
|
+
const validateComponent = getComponentValidate(component)
|
|
405
|
+
if (!validateComponent(partial)) {
|
|
406
|
+
const error = new Error(`component "${component.name}" validation errors`)
|
|
407
|
+
error.cause = lighterValidationErrors(validateComponent.errors)
|
|
408
|
+
throw error
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return /** @type {BaseCompObject} */(partial)
|
|
405
412
|
}
|
|
406
413
|
|
|
407
414
|
/**
|
|
408
415
|
* @param {LayoutKeyword} layoutKeyword
|
|
409
416
|
* @param {SchemaFragment} schemaFragment
|
|
410
417
|
* @param {string} schemaPath
|
|
418
|
+
* @param {Record<string, import('./types.js').ComponentInfo>} components
|
|
411
419
|
* @param {(text: string) => string} markdown
|
|
412
420
|
* @param {string[]} optionsKeys
|
|
413
421
|
* @param {'oneOf'} [arrayChild]
|
|
414
|
-
* @returns {
|
|
422
|
+
* @returns {NormalizedLayout}}
|
|
415
423
|
*/
|
|
416
|
-
function getNormalizedLayout (layoutKeyword, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild) {
|
|
424
|
+
function getNormalizedLayout (layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild) {
|
|
417
425
|
if (isPartialSwitch(layoutKeyword)) {
|
|
418
|
-
/** @type {
|
|
426
|
+
/** @type {BaseCompObject[]} */
|
|
419
427
|
const normalizedSwitchCases = []
|
|
420
|
-
const errors = []
|
|
421
428
|
const switchCases = [...layoutKeyword.switch]
|
|
422
429
|
if (!switchCases.find(s => !s.if)) {
|
|
423
430
|
switchCases.push({})
|
|
424
431
|
}
|
|
425
432
|
for (let i = 0; i < switchCases.length; i++) {
|
|
426
433
|
const switchCase = switchCases[i]
|
|
427
|
-
const compObjectResult = getCompObject(switchCase, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild)
|
|
428
|
-
normalizedSwitchCases.push(compObjectResult
|
|
429
|
-
for (const error of compObjectResult.errors) errors.push(`switch ${i} - ${error}`)
|
|
434
|
+
const compObjectResult = getCompObject(switchCase, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
435
|
+
normalizedSwitchCases.push(compObjectResult)
|
|
430
436
|
}
|
|
431
|
-
return {
|
|
437
|
+
return { switch: normalizedSwitchCases }
|
|
432
438
|
} else {
|
|
433
|
-
return getCompObject(layoutKeyword, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild)
|
|
439
|
+
return getCompObject(layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
434
440
|
}
|
|
435
441
|
}
|
|
436
442
|
|
|
@@ -447,10 +453,11 @@ function matchValidationError (error, fn) {
|
|
|
447
453
|
}
|
|
448
454
|
|
|
449
455
|
/**
|
|
450
|
-
* @param {import('ajv').ErrorObject[]} errors
|
|
456
|
+
* @param {import('ajv').ErrorObject[] | null | undefined} errors
|
|
451
457
|
* @returns {string[]}
|
|
452
458
|
*/
|
|
453
459
|
function lighterValidationErrors (errors) {
|
|
460
|
+
if (!errors) return []
|
|
454
461
|
const compositeErrors = errors.filter(e => matchValidationError(e, (e) => e.keyword === 'anyOf' || e.keyword === 'oneOf'))
|
|
455
462
|
// in case of a anyOf/oneOf error there are some subschemas errors that mostly prevent readability
|
|
456
463
|
for (const compositeError of compositeErrors) {
|
|
@@ -459,7 +466,13 @@ function lighterValidationErrors (errors) {
|
|
|
459
466
|
errors = errors.filter(e => matchValidationError(e, (e) => e.instancePath !== compositeError.instancePath || e.keyword !== 'type'))
|
|
460
467
|
}
|
|
461
468
|
}
|
|
462
|
-
|
|
469
|
+
const messages = []
|
|
470
|
+
for (const error of errors) {
|
|
471
|
+
let message = error.message ?? error.keyword
|
|
472
|
+
if (error.params) message += ' ' + JSON.stringify(error.params)
|
|
473
|
+
messages.push(message)
|
|
474
|
+
}
|
|
475
|
+
return messages
|
|
463
476
|
}
|
|
464
477
|
|
|
465
478
|
const defaultOptionsKeys = ['readOnly', 'summary', 'titleDepth', 'density', 'removeAdditional', 'validateOn', 'updateOne', 'debounceInputMs', 'initialValidation', 'defaultOn', 'readOnlyPropertiesMode']
|
|
@@ -467,12 +480,13 @@ const defaultOptionsKeys = ['readOnly', 'summary', 'titleDepth', 'density', 'rem
|
|
|
467
480
|
/**
|
|
468
481
|
* @param {SchemaFragment} schemaFragment
|
|
469
482
|
* @param {string} schemaPath
|
|
483
|
+
* @param {Record<string, import('./types.js').ComponentInfo>} components
|
|
470
484
|
* @param {(text: string) => string} markdown
|
|
471
485
|
* @param {string[]} [optionsKeys]
|
|
472
486
|
* @param {'oneOf'} [arrayChild]
|
|
473
|
-
* @returns {
|
|
487
|
+
* @returns {NormalizedLayout}
|
|
474
488
|
*/
|
|
475
|
-
|
|
489
|
+
function normalizeValidLayoutFragment (schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild) {
|
|
476
490
|
optionsKeys = optionsKeys ? optionsKeys.concat(defaultOptionsKeys) : defaultOptionsKeys
|
|
477
491
|
let layoutKeyword
|
|
478
492
|
if (arrayChild === 'oneOf') {
|
|
@@ -481,20 +495,47 @@ export function normalizeLayoutFragment (schemaFragment, schemaPath, markdown =
|
|
|
481
495
|
layoutKeyword = schemaFragment.layout ?? {}
|
|
482
496
|
}
|
|
483
497
|
if (!validateLayoutKeyword(layoutKeyword)) {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
498
|
+
const error = new Error('layout keyword validation errors at path')
|
|
499
|
+
error.cause = lighterValidationErrors(validateLayoutKeyword.errors)
|
|
500
|
+
throw error
|
|
501
|
+
}
|
|
502
|
+
const normalizedLayout = getNormalizedLayout(layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
503
|
+
|
|
504
|
+
if (!validateNormalizedLayout(normalizedLayout)) {
|
|
505
|
+
const error = new Error('normalized layout validation errors at path')
|
|
506
|
+
error.cause = lighterValidationErrors(validateNormalizedLayout.errors)
|
|
507
|
+
throw error
|
|
489
508
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
509
|
+
return normalizedLayout
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* @param {SchemaFragment} schemaFragment
|
|
514
|
+
* @param {string} schemaPath
|
|
515
|
+
* @param {Record<string, import('./types.js').ComponentInfo>} components
|
|
516
|
+
* @param {(text: string) => string} markdown
|
|
517
|
+
* @param {string[]} [optionsKeys]
|
|
518
|
+
* @param {'oneOf'} [arrayChild]
|
|
519
|
+
* @returns {{layout: NormalizedLayout, errors: string[]}}
|
|
520
|
+
*/
|
|
521
|
+
export function normalizeLayoutFragment (schemaFragment, schemaPath, components, markdown = (src) => src, optionsKeys, arrayChild) {
|
|
522
|
+
/** @type {string[]} */
|
|
523
|
+
const errors = []
|
|
524
|
+
try {
|
|
525
|
+
const layout = normalizeValidLayoutFragment(schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
526
|
+
return { layout, errors }
|
|
527
|
+
} catch (/** @type {any} */err) {
|
|
528
|
+
try {
|
|
529
|
+
errors.push(err.message)
|
|
530
|
+
if (err.cause && Array.isArray(err.cause)) errors.push(...err.cause)
|
|
531
|
+
errors.push('failed to normalize layout, use default component')
|
|
532
|
+
const layout = normalizeValidLayoutFragment({ ...schemaFragment, layout: {} }, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
533
|
+
return { layout, errors }
|
|
534
|
+
} catch (/** @type {any} */err) {
|
|
535
|
+
errors.push(err.message)
|
|
536
|
+
if (err.cause && Array.isArray(err.cause)) errors.push(...err.cause)
|
|
537
|
+
errors.push('failed to produce default layout, hide this fragment')
|
|
538
|
+
return { layout: { comp: 'none' }, errors }
|
|
496
539
|
}
|
|
497
|
-
// throw new Error(`invalid layout at path ${schemaPath}`, { cause: validateNormalizedLayout.errors })
|
|
498
540
|
}
|
|
499
|
-
return { layout: normalizedLayout.normalized, errors: [] }
|
|
500
541
|
}
|
|
@@ -1,40 +1,20 @@
|
|
|
1
|
-
import validate from './validate.js'
|
|
2
1
|
import schema from './schema.js'
|
|
2
|
+
import {ajv} from '../validate.js'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {import('./types.js').NormalizedLayout} NormalizedLayout
|
|
6
6
|
* @typedef {import('./types.js').SwitchStruct} SwitchStruct
|
|
7
|
-
* @typedef {import('./types.js').
|
|
8
|
-
* @typedef {import('./types.js').Section} Section
|
|
9
|
-
* @typedef {import('./types.js').GetItems} GetItems
|
|
10
|
-
* @typedef {import('./types.js').Expression} Expression
|
|
11
|
-
* @typedef {import('./types.js').Select} Select
|
|
12
|
-
* @typedef {import('./types.js').Autocomplete} Autocomplete
|
|
7
|
+
* @typedef {import('./types.js').BaseCompObject} BaseCompObject
|
|
13
8
|
* @typedef {import('./types.js').SelectItem} SelectItem
|
|
14
9
|
* @typedef {import('./types.js').SelectItems} SelectItems
|
|
15
10
|
* @typedef {import('./types.js').GetItemsFetch} GetItemsFetch
|
|
16
|
-
* @typedef {import('./types.js').TextField} TextField
|
|
17
|
-
* @typedef {import('./types.js').Textarea} Textarea
|
|
18
|
-
* @typedef {import('./types.js').NumberField} NumberField
|
|
19
|
-
* @typedef {import('./types.js').Slider} Slider
|
|
20
|
-
* @typedef {import('./types.js').Checkbox} Checkbox
|
|
21
|
-
* @typedef {import('./types.js').Switch} Switch
|
|
22
|
-
* @typedef {import('./types.js').DatePicker} DatePicker
|
|
23
|
-
* @typedef {import('./types.js').TimePicker} TimePicker
|
|
24
|
-
* @typedef {import('./types.js').DateTimePicker} DateTimePicker
|
|
25
|
-
* @typedef {import('./types.js').ColorPicker} ColorPicker
|
|
26
|
-
* @typedef {import('./types.js').OneOfSelect} OneOfSelect
|
|
27
11
|
* @typedef {import('./types.js').Child} Child
|
|
28
12
|
* @typedef {import('./types.js').Children} Children
|
|
29
13
|
* @typedef {import('./types.js').CompositeCompObject} CompositeCompObject
|
|
30
|
-
* @typedef {import('./types.js').
|
|
31
|
-
* @typedef {import('./types.js').
|
|
32
|
-
* @typedef {import('./types.js').
|
|
33
|
-
* @typedef {import('./types.js').
|
|
34
|
-
* @typedef {import('./types.js').List} List
|
|
35
|
-
* @typedef {import('./types.js').Combobox} Combobox
|
|
36
|
-
* @typedef {import('./types.js').Markdown} Markdown
|
|
37
|
-
* @typedef {import('./types.js').FileInput} FileInput
|
|
14
|
+
* @typedef {import('./types.js').ItemsBasedCompObject} ItemsBasedCompObject
|
|
15
|
+
* @typedef {import('./types.js').FocusableCompObject} FocusableCompObject
|
|
16
|
+
* @typedef {import('./types.js').GetItems} GetItems
|
|
17
|
+
* @typedef {import('./types.js').Expression} Expression
|
|
38
18
|
* @typedef {import('./types.js').Cols} Cols
|
|
39
19
|
* @typedef {import('./types.js').ColsObj} ColsObj
|
|
40
20
|
* @typedef {import('./types.js').StateNodeOptionsBase} StateNodeOptionsBase
|
|
@@ -43,7 +23,7 @@ import schema from './schema.js'
|
|
|
43
23
|
* @typedef {{ errors: any, (layoutKeyword: any): layoutKeyword is NormalizedLayout }} ValidateNormalizedLayout
|
|
44
24
|
*/
|
|
45
25
|
|
|
46
|
-
export const /** @type {ValidateNormalizedLayout} */ validateNormalizedLayout = /** @type {any} */ (
|
|
26
|
+
export const /** @type {ValidateNormalizedLayout} */ validateNormalizedLayout = /** @type {any} */ (ajv.getSchema(schema.$id))
|
|
47
27
|
|
|
48
28
|
export const normalizedLayoutSchema = /** @type {any} */ (schema)
|
|
49
29
|
|
|
@@ -52,55 +32,29 @@ export function isSwitchStruct (layout) {
|
|
|
52
32
|
return typeof layout === 'object' && 'switch' in layout
|
|
53
33
|
}
|
|
54
34
|
|
|
55
|
-
/** @type {(layout: NormalizedLayout) => layout is
|
|
35
|
+
/** @type {(layout: NormalizedLayout) => layout is BaseCompObject} */
|
|
56
36
|
export function isCompObject (layout) {
|
|
57
37
|
return !isSwitchStruct(layout)
|
|
58
38
|
}
|
|
59
39
|
|
|
60
40
|
/** @type {(child: Child) => child is Child & CompositeCompObject} */
|
|
61
41
|
export function childIsCompObject (child) {
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** @type {(layout: CompObject) => layout is Section} */
|
|
66
|
-
export function isSectionLayout (layout) {
|
|
67
|
-
return layout.comp === 'section'
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export const compositeCompNames = ['section', 'tabs', 'vertical-tabs', 'expansion-panels', 'stepper']
|
|
71
|
-
|
|
72
|
-
// these components can received keybord inputs and emit blur events
|
|
73
|
-
// they will be debounced when validateOn=blur is applicable and data binding will be updated on blur
|
|
74
|
-
export const editableCompNames = ['text-field', 'number-field', 'textarea', 'markdown']
|
|
75
|
-
|
|
76
|
-
/** @type {(layout: CompObject) => layout is CompositeCompObject} */
|
|
77
|
-
export function isCompositeLayout (layout) {
|
|
78
|
-
return compositeCompNames.includes(layout.comp)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** @type {(layout: CompObject) => layout is TextField} */
|
|
82
|
-
export function isTextFieldLayout (layout) {
|
|
83
|
-
return layout.comp === 'text-field'
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** @type {(layout: CompObject) => layout is Select} */
|
|
87
|
-
export function isSelectLayout (layout) {
|
|
88
|
-
return layout.comp === 'select'
|
|
42
|
+
return 'comp' in child
|
|
89
43
|
}
|
|
90
44
|
|
|
91
|
-
/** @type {(layout:
|
|
92
|
-
export function
|
|
93
|
-
return layout.comp
|
|
45
|
+
/** @type {(layout: BaseCompObject, components: Record<string, import('../types.js').ComponentInfo>) => layout is CompositeCompObject} */
|
|
46
|
+
export function isCompositeLayout (layout, components) {
|
|
47
|
+
return !!components[layout.comp]?.composite
|
|
94
48
|
}
|
|
95
49
|
|
|
96
|
-
/** @type {(layout:
|
|
97
|
-
export function isFocusableLayout (layout) {
|
|
98
|
-
return [
|
|
50
|
+
/** @type {(layout: BaseCompObject, components: Record<string, import('../types.js').ComponentInfo>) => layout is FocusableCompObject} */
|
|
51
|
+
export function isFocusableLayout (layout, components) {
|
|
52
|
+
return !!components[layout.comp]?.focusable
|
|
99
53
|
}
|
|
100
54
|
|
|
101
|
-
/** @type {(layout:
|
|
102
|
-
export function isItemsLayout (layout) {
|
|
103
|
-
return layout.comp
|
|
55
|
+
/** @type {(layout: BaseCompObject, components: Record<string, import('../types.js').ComponentInfo>) => layout is ItemsBasedCompObject} */
|
|
56
|
+
export function isItemsLayout (layout, components) {
|
|
57
|
+
return !!components[layout.comp]?.itemsBased
|
|
104
58
|
}
|
|
105
59
|
|
|
106
60
|
/** @type {(getItems: GetItems) => getItems is Expression} */
|