@json-layout/vocabulary 0.14.0 → 0.15.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 +92 -53
- 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') {
|
|
@@ -278,7 +276,7 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, markdown, opt
|
|
|
278
276
|
if (!('label' in partial)) partial.label = schemaFragment.title ?? key
|
|
279
277
|
}
|
|
280
278
|
|
|
281
|
-
if (
|
|
279
|
+
if (component.itemsBased && !partial.items) {
|
|
282
280
|
let items
|
|
283
281
|
if (type === 'array') {
|
|
284
282
|
items = getItemsFromSchema(schemaFragment.items)
|
|
@@ -294,7 +292,7 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, markdown, opt
|
|
|
294
292
|
}
|
|
295
293
|
}
|
|
296
294
|
|
|
297
|
-
if (
|
|
295
|
+
if (component.multipleCompat) {
|
|
298
296
|
if (type === 'array' || partial.separator) {
|
|
299
297
|
partial.multiple = true
|
|
300
298
|
}
|
|
@@ -401,36 +399,42 @@ function getCompObject (layoutKeyword, schemaFragment, schemaPath, markdown, opt
|
|
|
401
399
|
if (typeof partial.cols === 'number') partial.cols = { xs: partial.cols }
|
|
402
400
|
if (typeof partial.cols === 'object' && partial.cols.xs === undefined) partial.cols.xs = 12
|
|
403
401
|
|
|
404
|
-
|
|
402
|
+
const validateComponent = getComponentValidate(component)
|
|
403
|
+
if (!validateComponent(partial)) {
|
|
404
|
+
const error = new Error(`component "${component.name}" validation errors`)
|
|
405
|
+
error.cause = lighterValidationErrors(validateComponent.errors)
|
|
406
|
+
throw error
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return /** @type {BaseCompObject} */(partial)
|
|
405
410
|
}
|
|
406
411
|
|
|
407
412
|
/**
|
|
408
413
|
* @param {LayoutKeyword} layoutKeyword
|
|
409
414
|
* @param {SchemaFragment} schemaFragment
|
|
410
415
|
* @param {string} schemaPath
|
|
416
|
+
* @param {Record<string, import('./types.js').ComponentInfo>} components
|
|
411
417
|
* @param {(text: string) => string} markdown
|
|
412
418
|
* @param {string[]} optionsKeys
|
|
413
419
|
* @param {'oneOf'} [arrayChild]
|
|
414
|
-
* @returns {
|
|
420
|
+
* @returns {NormalizedLayout}}
|
|
415
421
|
*/
|
|
416
|
-
function getNormalizedLayout (layoutKeyword, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild) {
|
|
422
|
+
function getNormalizedLayout (layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild) {
|
|
417
423
|
if (isPartialSwitch(layoutKeyword)) {
|
|
418
|
-
/** @type {
|
|
424
|
+
/** @type {BaseCompObject[]} */
|
|
419
425
|
const normalizedSwitchCases = []
|
|
420
|
-
const errors = []
|
|
421
426
|
const switchCases = [...layoutKeyword.switch]
|
|
422
427
|
if (!switchCases.find(s => !s.if)) {
|
|
423
428
|
switchCases.push({})
|
|
424
429
|
}
|
|
425
430
|
for (let i = 0; i < switchCases.length; i++) {
|
|
426
431
|
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}`)
|
|
432
|
+
const compObjectResult = getCompObject(switchCase, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
433
|
+
normalizedSwitchCases.push(compObjectResult)
|
|
430
434
|
}
|
|
431
|
-
return {
|
|
435
|
+
return { switch: normalizedSwitchCases }
|
|
432
436
|
} else {
|
|
433
|
-
return getCompObject(layoutKeyword, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild)
|
|
437
|
+
return getCompObject(layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
434
438
|
}
|
|
435
439
|
}
|
|
436
440
|
|
|
@@ -447,10 +451,11 @@ function matchValidationError (error, fn) {
|
|
|
447
451
|
}
|
|
448
452
|
|
|
449
453
|
/**
|
|
450
|
-
* @param {import('ajv').ErrorObject[]} errors
|
|
454
|
+
* @param {import('ajv').ErrorObject[] | null | undefined} errors
|
|
451
455
|
* @returns {string[]}
|
|
452
456
|
*/
|
|
453
457
|
function lighterValidationErrors (errors) {
|
|
458
|
+
if (!errors) return []
|
|
454
459
|
const compositeErrors = errors.filter(e => matchValidationError(e, (e) => e.keyword === 'anyOf' || e.keyword === 'oneOf'))
|
|
455
460
|
// in case of a anyOf/oneOf error there are some subschemas errors that mostly prevent readability
|
|
456
461
|
for (const compositeError of compositeErrors) {
|
|
@@ -459,7 +464,13 @@ function lighterValidationErrors (errors) {
|
|
|
459
464
|
errors = errors.filter(e => matchValidationError(e, (e) => e.instancePath !== compositeError.instancePath || e.keyword !== 'type'))
|
|
460
465
|
}
|
|
461
466
|
}
|
|
462
|
-
|
|
467
|
+
const messages = []
|
|
468
|
+
for (const error of errors) {
|
|
469
|
+
let message = error.message ?? error.keyword
|
|
470
|
+
if (error.params) message += ' ' + JSON.stringify(error.params)
|
|
471
|
+
messages.push(message)
|
|
472
|
+
}
|
|
473
|
+
return messages
|
|
463
474
|
}
|
|
464
475
|
|
|
465
476
|
const defaultOptionsKeys = ['readOnly', 'summary', 'titleDepth', 'density', 'removeAdditional', 'validateOn', 'updateOne', 'debounceInputMs', 'initialValidation', 'defaultOn', 'readOnlyPropertiesMode']
|
|
@@ -467,12 +478,13 @@ const defaultOptionsKeys = ['readOnly', 'summary', 'titleDepth', 'density', 'rem
|
|
|
467
478
|
/**
|
|
468
479
|
* @param {SchemaFragment} schemaFragment
|
|
469
480
|
* @param {string} schemaPath
|
|
481
|
+
* @param {Record<string, import('./types.js').ComponentInfo>} components
|
|
470
482
|
* @param {(text: string) => string} markdown
|
|
471
483
|
* @param {string[]} [optionsKeys]
|
|
472
484
|
* @param {'oneOf'} [arrayChild]
|
|
473
|
-
* @returns {
|
|
485
|
+
* @returns {NormalizedLayout}
|
|
474
486
|
*/
|
|
475
|
-
|
|
487
|
+
function normalizeValidLayoutFragment (schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild) {
|
|
476
488
|
optionsKeys = optionsKeys ? optionsKeys.concat(defaultOptionsKeys) : defaultOptionsKeys
|
|
477
489
|
let layoutKeyword
|
|
478
490
|
if (arrayChild === 'oneOf') {
|
|
@@ -481,20 +493,47 @@ export function normalizeLayoutFragment (schemaFragment, schemaPath, markdown =
|
|
|
481
493
|
layoutKeyword = schemaFragment.layout ?? {}
|
|
482
494
|
}
|
|
483
495
|
if (!validateLayoutKeyword(layoutKeyword)) {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
errors: lighterValidationErrors(validateLayoutKeyword.errors)
|
|
488
|
-
}
|
|
496
|
+
const error = new Error('layout keyword validation errors at path')
|
|
497
|
+
error.cause = lighterValidationErrors(validateLayoutKeyword.errors)
|
|
498
|
+
throw error
|
|
489
499
|
}
|
|
490
|
-
const normalizedLayout = getNormalizedLayout(layoutKeyword, schemaFragment, schemaPath, markdown, optionsKeys, arrayChild)
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
500
|
+
const normalizedLayout = getNormalizedLayout(layoutKeyword, schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
501
|
+
|
|
502
|
+
if (!validateNormalizedLayout(normalizedLayout)) {
|
|
503
|
+
const error = new Error('normalized layout validation errors at path')
|
|
504
|
+
error.cause = lighterValidationErrors(validateNormalizedLayout.errors)
|
|
505
|
+
throw error
|
|
506
|
+
}
|
|
507
|
+
return normalizedLayout
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* @param {SchemaFragment} schemaFragment
|
|
512
|
+
* @param {string} schemaPath
|
|
513
|
+
* @param {Record<string, import('./types.js').ComponentInfo>} components
|
|
514
|
+
* @param {(text: string) => string} markdown
|
|
515
|
+
* @param {string[]} [optionsKeys]
|
|
516
|
+
* @param {'oneOf'} [arrayChild]
|
|
517
|
+
* @returns {{layout: NormalizedLayout, errors: string[]}}
|
|
518
|
+
*/
|
|
519
|
+
export function normalizeLayoutFragment (schemaFragment, schemaPath, components, markdown = (src) => src, optionsKeys, arrayChild) {
|
|
520
|
+
/** @type {string[]} */
|
|
521
|
+
const errors = []
|
|
522
|
+
try {
|
|
523
|
+
const layout = normalizeValidLayoutFragment(schemaFragment, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
524
|
+
return { layout, errors }
|
|
525
|
+
} catch (/** @type {any} */err) {
|
|
526
|
+
try {
|
|
527
|
+
errors.push(err.message)
|
|
528
|
+
if (err.cause && Array.isArray(err.cause)) errors.push(...err.cause)
|
|
529
|
+
errors.push('failed to normalize layout, use default component')
|
|
530
|
+
const layout = normalizeValidLayoutFragment({ ...schemaFragment, layout: {} }, schemaPath, components, markdown, optionsKeys, arrayChild)
|
|
531
|
+
return { layout, errors }
|
|
532
|
+
} catch (/** @type {any} */err) {
|
|
533
|
+
errors.push(err.message)
|
|
534
|
+
if (err.cause && Array.isArray(err.cause)) errors.push(...err.cause)
|
|
535
|
+
errors.push('failed to produce default layout, hide this fragment')
|
|
536
|
+
return { layout: { comp: 'none' }, errors }
|
|
496
537
|
}
|
|
497
|
-
// throw new Error(`invalid layout at path ${schemaPath}`, { cause: validateNormalizedLayout.errors })
|
|
498
538
|
}
|
|
499
|
-
return { layout: normalizedLayout.normalized, errors: [] }
|
|
500
539
|
}
|
|
@@ -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} */
|