@koumoul/vjsf 2.22.1 → 3.0.0-alpha.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.
Files changed (138) hide show
  1. package/package.json +50 -86
  2. package/src/compat/v2.js +82 -0
  3. package/src/compile/index.js +32 -0
  4. package/src/compile/v-jsf-compiled.vue.ejs +83 -0
  5. package/src/components/fragments/node-slot.vue +49 -0
  6. package/src/components/fragments/section-header.vue +52 -0
  7. package/src/components/fragments/text-field-menu.vue +68 -0
  8. package/src/components/node.vue +60 -0
  9. package/src/components/nodes/checkbox.vue +27 -0
  10. package/src/components/nodes/color-picker.vue +43 -0
  11. package/src/components/nodes/date-picker.vue +45 -0
  12. package/src/components/nodes/date-time-picker.vue +20 -0
  13. package/src/components/nodes/expansion-panels.vue +52 -0
  14. package/src/components/nodes/list.vue +112 -0
  15. package/src/components/nodes/number-field.vue +35 -0
  16. package/src/components/nodes/one-of-select.vue +56 -0
  17. package/src/components/nodes/section.vue +30 -0
  18. package/src/components/nodes/select.vue +59 -0
  19. package/src/components/nodes/slider.vue +34 -0
  20. package/src/components/nodes/switch.vue +29 -0
  21. package/src/components/nodes/tabs.vue +63 -0
  22. package/src/components/nodes/text-field.vue +29 -0
  23. package/src/components/nodes/textarea.vue +29 -0
  24. package/src/components/nodes/time-picker.vue +7 -0
  25. package/src/components/nodes/vertical-tabs.vue +70 -0
  26. package/src/components/options.js +25 -0
  27. package/src/components/tree.vue +25 -0
  28. package/src/components/types.ts +59 -0
  29. package/src/components/vjsf.vue +168 -0
  30. package/src/index.js +2 -0
  31. package/src/utils/clone.js +3 -0
  32. package/src/utils/dates.js +52 -0
  33. package/src/utils/props.js +79 -0
  34. package/src/utils/slots.js +19 -0
  35. package/types/compat/v2.d.ts +10 -0
  36. package/types/compat/v2.d.ts.map +1 -0
  37. package/types/compile/index.d.ts +7 -0
  38. package/types/compile/index.d.ts.map +1 -0
  39. package/types/components/fragments/node-slot.vue.d.ts +47 -0
  40. package/types/components/fragments/node-slot.vue.d.ts.map +1 -0
  41. package/types/components/fragments/section-header.vue.d.ts +8 -0
  42. package/types/components/fragments/section-header.vue.d.ts.map +1 -0
  43. package/types/components/fragments/text-field-menu.vue.d.ts +20 -0
  44. package/types/components/fragments/text-field-menu.vue.d.ts.map +1 -0
  45. package/types/components/node.vue.d.ts +10 -0
  46. package/types/components/node.vue.d.ts.map +1 -0
  47. package/types/components/nodes/checkbox.vue.d.ts +10 -0
  48. package/types/components/nodes/checkbox.vue.d.ts.map +1 -0
  49. package/types/components/nodes/color-picker.vue.d.ts +10 -0
  50. package/types/components/nodes/color-picker.vue.d.ts.map +1 -0
  51. package/types/components/nodes/date-picker.vue.d.ts +10 -0
  52. package/types/components/nodes/date-picker.vue.d.ts.map +1 -0
  53. package/types/components/nodes/date-time-picker.vue.d.ts +10 -0
  54. package/types/components/nodes/date-time-picker.vue.d.ts.map +1 -0
  55. package/types/components/nodes/expansion-panels.vue.d.ts +10 -0
  56. package/types/components/nodes/expansion-panels.vue.d.ts.map +1 -0
  57. package/types/components/nodes/list.vue.d.ts +10 -0
  58. package/types/components/nodes/list.vue.d.ts.map +1 -0
  59. package/types/components/nodes/number-field.vue.d.ts +27 -0
  60. package/types/components/nodes/number-field.vue.d.ts.map +1 -0
  61. package/types/components/nodes/one-of-select.vue.d.ts +10 -0
  62. package/types/components/nodes/one-of-select.vue.d.ts.map +1 -0
  63. package/types/components/nodes/section.vue.d.ts +10 -0
  64. package/types/components/nodes/section.vue.d.ts.map +1 -0
  65. package/types/components/nodes/select.vue.d.ts +10 -0
  66. package/types/components/nodes/select.vue.d.ts.map +1 -0
  67. package/types/components/nodes/slider.vue.d.ts +10 -0
  68. package/types/components/nodes/slider.vue.d.ts.map +1 -0
  69. package/types/components/nodes/switch.vue.d.ts +10 -0
  70. package/types/components/nodes/switch.vue.d.ts.map +1 -0
  71. package/types/components/nodes/tabs.vue.d.ts +10 -0
  72. package/types/components/nodes/tabs.vue.d.ts.map +1 -0
  73. package/types/components/nodes/text-field copy.vue.d.ts +10 -0
  74. package/types/components/nodes/text-field copy.vue.d.ts.map +1 -0
  75. package/types/components/nodes/text-field.vue.d.ts +27 -0
  76. package/types/components/nodes/text-field.vue.d.ts.map +1 -0
  77. package/types/components/nodes/textarea.vue.d.ts +27 -0
  78. package/types/components/nodes/textarea.vue.d.ts.map +1 -0
  79. package/types/components/nodes/time-picker.vue.d.ts +3 -0
  80. package/types/components/nodes/time-picker.vue.d.ts.map +1 -0
  81. package/types/components/nodes/vertical-tabs.vue.d.ts +10 -0
  82. package/types/components/nodes/vertical-tabs.vue.d.ts.map +1 -0
  83. package/types/components/options.d.ts +3 -0
  84. package/types/components/options.d.ts.map +1 -0
  85. package/types/components/tree.vue.d.ts +10 -0
  86. package/types/components/tree.vue.d.ts.map +1 -0
  87. package/types/components/types.d.ts +71 -0
  88. package/types/components/types.d.ts.map +1 -0
  89. package/types/components/v-jsf.vue.d.ts +13 -0
  90. package/types/components/v-jsf.vue.d.ts.map +1 -0
  91. package/types/components/vjsf.vue.d.ts +13 -0
  92. package/types/components/vjsf.vue.d.ts.map +1 -0
  93. package/types/index.d.ts +3 -0
  94. package/types/index.d.ts.map +1 -0
  95. package/types/utils/clone.d.ts +3 -0
  96. package/types/utils/clone.d.ts.map +1 -0
  97. package/types/utils/dates.d.ts +7 -0
  98. package/types/utils/dates.d.ts.map +1 -0
  99. package/types/utils/props.d.ts +20 -0
  100. package/types/utils/props.d.ts.map +1 -0
  101. package/types/utils/slots.d.ts +7 -0
  102. package/types/utils/slots.d.ts.map +1 -0
  103. package/.eslintignore +0 -9
  104. package/.eslintrc.js +0 -38
  105. package/.github/workflows/scrape-doc.yml +0 -14
  106. package/.nvmrc +0 -1
  107. package/CONTRIBUTE.md +0 -61
  108. package/FUNDING.yml +0 -1
  109. package/README.md +0 -19
  110. package/babel.config.js +0 -4
  111. package/dist/main.css +0 -67
  112. package/dist/main.js +0 -2
  113. package/dist/main.js.LICENSE.txt +0 -10
  114. package/dist/third-party.js +0 -8
  115. package/dist/third-party.js.LICENSE.txt +0 -8
  116. package/lib/VJsf.css +0 -67
  117. package/lib/VJsf.js +0 -117
  118. package/lib/VJsfNoDeps.js +0 -517
  119. package/lib/deps/third-party.js +0 -16
  120. package/lib/mixins/ColorProperty.js +0 -45
  121. package/lib/mixins/DateProperty.js +0 -170
  122. package/lib/mixins/Dependent.js +0 -69
  123. package/lib/mixins/EditableArray.js +0 -418
  124. package/lib/mixins/FileProperty.js +0 -81
  125. package/lib/mixins/MarkdownEditor.js +0 -183
  126. package/lib/mixins/ObjectContainer.js +0 -351
  127. package/lib/mixins/SelectProperty.js +0 -400
  128. package/lib/mixins/SimpleProperty.js +0 -165
  129. package/lib/mixins/Tooltip.js +0 -42
  130. package/lib/mixins/Validatable.js +0 -119
  131. package/lib/utils/expr-eval-parser.js +0 -21
  132. package/lib/utils/is-cyclic.js +0 -34
  133. package/lib/utils/json-refs.js +0 -209
  134. package/lib/utils/options.js +0 -328
  135. package/lib/utils/rules.js +0 -81
  136. package/lib/utils/schema.js +0 -100
  137. package/lib/utils/select.js +0 -141
  138. package/webpack.config.js +0 -46
@@ -0,0 +1,25 @@
1
+ /** @type Partial<import("./types.js").VjsfOptions> */
2
+ export const defaultOptions = {
3
+ // matches the density prop found in many vuetify components
4
+ density: 'default',
5
+ titleDepth: 2,
6
+ fieldProps: {},
7
+ fieldPropsCompact: {
8
+ density: 'compact',
9
+ hideDetails: 'auto'
10
+ },
11
+ fieldPropsComfortable: {
12
+ density: 'comfortable'
13
+ },
14
+ fieldPropsReadOnly: { hideDetails: 'auto', variant: 'plain' },
15
+ textfieldProps: {},
16
+ textfieldPropsReadOnly: {},
17
+ textareaProps: {},
18
+ textareaPropsReadOnly: {},
19
+ // it is not very common to show an error below checkboxes and switches and without hide-details=auto they take a lot of space
20
+ checkboxProps: { hideDetails: 'auto' },
21
+ checkboxPropsReadOnly: {},
22
+ switchProps: { hideDetails: 'auto' },
23
+ switchPropsReadOnly: {},
24
+ errorAlertProps: { type: 'error', variant: 'tonal' }
25
+ }
@@ -0,0 +1,25 @@
1
+ <script setup>
2
+ import Node from './node.vue'
3
+
4
+ defineProps({
5
+ modelValue: {
6
+ /** @type import('vue').PropType<import('@json-layout/core').StateTree> */
7
+ type: Object,
8
+ required: true
9
+ },
10
+ statefulLayout: {
11
+ /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
12
+ type: Object,
13
+ required: true
14
+ }
15
+ })
16
+ </script>
17
+
18
+ <template>
19
+ <v-row>
20
+ <node
21
+ :stateful-layout="statefulLayout"
22
+ :model-value="/** @type import('./types.js').VjsfNode */(modelValue.root)"
23
+ />
24
+ </v-row>
25
+ </template>
@@ -0,0 +1,59 @@
1
+ import {
2
+ StatefulLayoutOptions,
3
+ StateNode,
4
+ CheckboxNode,
5
+ ColorPickerNode,
6
+ DatePickerNode,
7
+ DateTimePickerNode,
8
+ TabsNode,
9
+ ExpansionPanelsNode,
10
+ ListNode,
11
+ NumberFieldNode,
12
+ OneOfSelectNode,
13
+ SectionNode,
14
+ SelectNode,
15
+ SliderNode,
16
+ SwitchNode,
17
+ TextFieldNode,
18
+ TextareaNode,
19
+ VerticalTabsNode,
20
+ CompileOptions
21
+ } from '@json-layout/core'
22
+
23
+ export type Density = 'default' | 'comfortable' | 'compact'
24
+
25
+ export type VjsfOptions = StatefulLayoutOptions & CompileOptions & {
26
+ density: Density,
27
+ fieldProps: Record<string, unknown>,
28
+ fieldPropsCompact: Record<string, unknown>,
29
+ fieldPropsComfortable: Record<string, unknown>,
30
+ fieldPropsReadOnly: Record<string, unknown>,
31
+ textfieldProps: Record<string, unknown>,
32
+ textfieldPropsReadOnly: Record<string, unknown>,
33
+ textareaProps: Record<string, unknown>,
34
+ textareaPropsReadOnly: Record<string, unknown>,
35
+ checkboxProps: Record<string, unknown>,
36
+ checkboxPropsReadOnly: Record<string, unknown>,
37
+ switchProps: Record<string, unknown>,
38
+ switchPropsReadOnly: Record<string, unknown>,
39
+ errorAlertProps: Record<string, unknown>,
40
+ vjsfSlots: Record<string, () => unknown>,
41
+ }
42
+
43
+ export type VjsfNode = Omit<StateNode, 'options'> & {options: VjsfOptions}
44
+ export type VjsfTabsNode = Omit<TabsNode, 'options'> & {options: VjsfOptions}
45
+ export type VjsfCheckboxNode = Omit<CheckboxNode, 'options'> & {options: VjsfOptions}
46
+ export type VjsfColorPickerNode = Omit<ColorPickerNode, 'options'> & {options: VjsfOptions}
47
+ export type VjsfDatePickerNode = Omit<DatePickerNode, 'options'> & {options: VjsfOptions}
48
+ export type VjsfDateTimePickerNode = Omit<DateTimePickerNode, 'options'> & {options: VjsfOptions}
49
+ export type VjsfExpansionPanelsNode = Omit<ExpansionPanelsNode, 'options'> & {options: VjsfOptions}
50
+ export type VjsfListNode = Omit<ListNode, 'options'> & {options: VjsfOptions}
51
+ export type VjsfNumberFieldNode = Omit<NumberFieldNode, 'options'> & {options: VjsfOptions}
52
+ export type VjsfOneOfSelectNode = Omit<OneOfSelectNode, 'options'> & {options: VjsfOptions}
53
+ export type VjsfSectionNode = Omit<SectionNode, 'options'> & {options: VjsfOptions}
54
+ export type VjsfSelectNode = Omit<SelectNode, 'options'> & {options: VjsfOptions}
55
+ export type VjsfSliderNode = Omit<SliderNode, 'options'> & {options: VjsfOptions}
56
+ export type VjsfSwitchNode = Omit<SwitchNode, 'options'> & {options: VjsfOptions}
57
+ export type VjsfTextFieldNode = Omit<TextFieldNode, 'options'> & {options: VjsfOptions}
58
+ export type VjsfTextareaNode = Omit<TextareaNode, 'options'> & {options: VjsfOptions}
59
+ export type VjsfVerticalTabsNode = Omit<VerticalTabsNode, 'options'> & {options: VjsfOptions}
@@ -0,0 +1,168 @@
1
+ <script setup>
2
+ import { ref, shallowRef, computed, getCurrentInstance, watch, useSlots, inject } from 'vue'
3
+ import { useElementSize } from '@vueuse/core'
4
+ import { StatefulLayout, compile } from '@json-layout/core'
5
+ import Tree from './tree.vue'
6
+
7
+ import NodeSection from './nodes/section.vue'
8
+ import NodeTextField from './nodes/text-field.vue'
9
+ import NodeTextarea from './nodes/textarea.vue'
10
+ import NodeCheckbox from './nodes/checkbox.vue'
11
+ import NodeSwitch from './nodes/switch.vue'
12
+ import NodeNumberField from './nodes/number-field.vue'
13
+ import NodeSlider from './nodes/slider.vue'
14
+ import NodeDatePicker from './nodes/date-picker.vue'
15
+ import NodeDateTimePicker from './nodes/date-time-picker.vue'
16
+ import NodeColorPicker from './nodes/color-picker.vue'
17
+ import NodeSelect from './nodes/select.vue'
18
+ import NodeOneOfSelect from './nodes/one-of-select.vue'
19
+ import NodeTabs from './nodes/tabs.vue'
20
+ import NodeVerticalTabs from './nodes/vertical-tabs.vue'
21
+ import NodeExpansionPanels from './nodes/expansion-panels.vue'
22
+ import NodeList from './nodes/list.vue'
23
+ import { defaultOptions } from './options.js'
24
+
25
+ const comps = {
26
+ section: NodeSection,
27
+ 'text-field': NodeTextField,
28
+ textarea: NodeTextarea,
29
+ checkbox: NodeCheckbox,
30
+ switch: NodeSwitch,
31
+ 'number-field': NodeNumberField,
32
+ slider: NodeSlider,
33
+ 'date-picker': NodeDatePicker,
34
+ 'date-time-picker': NodeDateTimePicker,
35
+ 'color-picker': NodeColorPicker,
36
+ select: NodeSelect,
37
+ 'one-of-select': NodeOneOfSelect,
38
+ tabs: NodeTabs,
39
+ 'vertical-tabs': NodeVerticalTabs,
40
+ 'expansion-panels': NodeExpansionPanels,
41
+ list: NodeList
42
+ }
43
+
44
+ const instance = getCurrentInstance()
45
+ for (const [name, comp] of Object.entries(comps)) {
46
+ if (!instance?.appContext.app.component(`vjsf-node-${name}`)) {
47
+ instance?.appContext.app.component(`vjsf-node-${name}`, comp)
48
+ }
49
+ }
50
+
51
+ const props = defineProps({
52
+ schema: {
53
+ type: Object,
54
+ required: true
55
+ },
56
+ modelValue: {
57
+ type: [Object, String, Number, Boolean],
58
+ default: null
59
+ },
60
+ options: {
61
+ /** @type import('vue').PropType<Partial<Omit<import('./types.js').VjsfOptions, 'width'>>> */
62
+ type: Object,
63
+ required: true
64
+ }
65
+ })
66
+
67
+ const emit = defineEmits(['update:modelValue', 'update:state'])
68
+
69
+ /** @type import('vue').ShallowRef<StatefulLayout | null> */
70
+ const statefulLayout = shallowRef(null)
71
+ /** @type import('vue').ShallowRef<import('@json-layout/core').StateTree | null> */
72
+ const stateTree = shallowRef(null)
73
+
74
+ // cf https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/composables/form.ts
75
+ const form = inject(Symbol.for('vuetify:form'))
76
+ if (form) {
77
+ form.register({
78
+ id: 'vjsf', // TODO: a unique random id ?
79
+ validate: () => statefulLayout.value?.validate(),
80
+ reset: () => statefulLayout.value?.resetValidation(), // TODO: also empty the data ?
81
+ resetValidation: () => statefulLayout.value?.resetValidation()
82
+ })
83
+ }
84
+
85
+ const el = ref(null)
86
+ const { width } = useElementSize(el)
87
+
88
+ const slots = useSlots()
89
+
90
+ /** @type import('vue').ComputedRef<import('./types.js').VjsfOptions> */
91
+ const fullOptions = computed(() => {
92
+ const options = {
93
+ ...defaultOptions,
94
+ readOnly: form.isDisabled || form.isReadOnly,
95
+ ...props.options,
96
+ context: props.options.context ? JSON.parse(JSON.stringify(props.options.context)) : {},
97
+ width: Math.round(width.value ?? 0),
98
+ vjsfSlots: { ...slots }
99
+ }
100
+ return /** @type import('./types.js').VjsfOptions */ (options)
101
+ })
102
+
103
+ const compiledLayout = computed(() => compile(props.schema, fullOptions.value))
104
+
105
+ const onStatefulLayoutUpdate = () => {
106
+ if (!statefulLayout.value) return
107
+ stateTree.value = statefulLayout.value.stateTree
108
+ emit('update:modelValue', statefulLayout.value.data)
109
+ emit('update:state', statefulLayout.value)
110
+ if (form) {
111
+ // cf https://vuetifyjs.com/en/components/forms/#validation-state
112
+ if (statefulLayout.value.valid) form.update('vjsf', true, [])
113
+ else if (statefulLayout.value.hasHiddenError) form.update('vjsf', null, [])
114
+ else form.update('vjsf', false, [])
115
+ }
116
+ }
117
+
118
+ const initStatefulLayout = () => {
119
+ if (!width.value) return
120
+ const _statefulLayout = new StatefulLayout(compiledLayout.value, compiledLayout.value.skeletonTree, fullOptions.value, props.modelValue)
121
+ statefulLayout.value = _statefulLayout
122
+ onStatefulLayoutUpdate()
123
+ _statefulLayout.events.on('update', () => {
124
+ onStatefulLayoutUpdate()
125
+ })
126
+ emit('update:state', _statefulLayout)
127
+ }
128
+
129
+ watch(fullOptions, (newOptions) => {
130
+ if (statefulLayout.value) {
131
+ statefulLayout.value.options = newOptions
132
+ } else {
133
+ initStatefulLayout()
134
+ }
135
+ })
136
+
137
+ // case where data is updated from outside
138
+ watch(() => props.modelValue, (newData) => {
139
+ if (statefulLayout.value && statefulLayout.value.data !== newData) statefulLayout.value.data = newData
140
+ })
141
+
142
+ // case where schema is updated from outside
143
+ watch(compiledLayout, (newCompiledLayout) => initStatefulLayout())
144
+
145
+ </script>
146
+
147
+ <template>
148
+ <div ref="el">
149
+ <tree
150
+ v-if="statefulLayout && stateTree"
151
+ :model-value="stateTree"
152
+ :stateful-layout="statefulLayout"
153
+ />
154
+ </div>
155
+ </template>
156
+
157
+ <style lang="css">
158
+ /* override vuetify styles to manage readOnly fields more usable than the default disabled fields */
159
+ .vjsf-input--readonly.v-input--disabled.v-text-field .v-field--disabled input {
160
+ pointer-events: auto;
161
+ }
162
+ .vjsf-input--readonly.v-input--disabled .v-field--disabled,
163
+ .vjsf-input--readonly.v-input--disabled .v-input__details,
164
+ .vjsf-input--readonly.v-input--disabled .v-input__append,
165
+ .vjsf-input--readonly.v-input--disabled .v-input__prepend {
166
+ opacity: inherit;
167
+ }
168
+ </style>
package/src/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import Vjsf from './components/vjsf.vue'
2
+ export { Vjsf }
@@ -0,0 +1,3 @@
1
+ import rfdc from 'rfdc'
2
+
3
+ export default rfdc()
@@ -0,0 +1,52 @@
1
+ // TODO: parts of this can probably be replaced by https://vuetifyjs.com/en/features/dates/
2
+
3
+ // 1 => 01, 12 => 12
4
+ export const padTimeComponent = (/** @type number */val) => {
5
+ const s = '' + val
6
+ return s.length === 1 ? '0' + s : s
7
+ }
8
+
9
+ // storing ISO times with the user's timezone offset is more dense in information that always storing the base ISO date
10
+ // this way the application can either use the localized time or the ISO time by chosing to interpret or not the offset part
11
+ // cf https://usefulangle.com/post/30/javascript-get-date-time-with-offset-hours-minutes
12
+ // 2020-04-03T19:07:43.152Z => 2020-04-03T21:07:43+02:00
13
+ export const getDateTimeWithOffset = (/** @type Date */date) => {
14
+ const offsetMinutes = date.getTimezoneOffset()
15
+ const offsetAbs = `${padTimeComponent(Math.abs(offsetMinutes / 60))}:${padTimeComponent(Math.abs(offsetMinutes % 60))}`
16
+ let offset
17
+ if (offsetMinutes < 0) offset = `+${offsetAbs}`
18
+ else if (offsetMinutes > 0) offset = `-${offsetAbs}`
19
+ else offset = 'Z'
20
+ return `${date.getFullYear()}-${padTimeComponent(date.getMonth() + 1)}-${padTimeComponent(date.getDate())}T${padTimeComponent(date.getHours())}:${padTimeComponent(date.getMinutes())}:${padTimeComponent(date.getSeconds())}${offset}`
21
+ }
22
+
23
+ // get the the date and short time components expected by date-time picker from a full date
24
+ // 2020-04-03T21:07:43+02:00 => ['2020-04-03', '19:07']
25
+ export const getDateTimeParts = (/** @type Date */date) => {
26
+ return [`${date.getFullYear()}-${padTimeComponent(date.getMonth() + 1)}-${padTimeComponent(date.getDate())}`, `${padTimeComponent(date.getHours())}:${padTimeComponent(date.getMinutes())}`]
27
+ }
28
+
29
+ // get a full date-time from the date and time parts edited by date-time picker
30
+ // ['2020-04-03', '19:07'] => 2020-04-03T21:07:43+02:00
31
+ export const getDateTime = (/** @type [string, string] */parts) => {
32
+ const date = new Date()
33
+ const dateParts = parts[0].split('-')
34
+ date.setFullYear(Number(dateParts[0]))
35
+ date.setMonth(Number(dateParts[1]) - 1)
36
+ date.setDate(Number(dateParts[2]))
37
+ const timeParts = parts[1].split(':')
38
+ date.setHours(Number(timeParts[0] || '00'))
39
+ date.setMinutes(Number(timeParts[1] || '00'))
40
+ date.setSeconds(0)
41
+ return getDateTimeWithOffset(date)
42
+ }
43
+
44
+ // get the short time representation expected by vuetify from a longer ISO time
45
+ export const getShortTime = (/** @type string | undefined */time) => {
46
+ if (!time) return ''
47
+ return time.slice(0, 5)
48
+ }
49
+
50
+ export const getLongTime = (/** @type string */time) => {
51
+ return time + ':00Z'
52
+ }
@@ -0,0 +1,79 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { camelize } from 'vue'
3
+
4
+ /**
5
+ * @param {(Record<string, any> | undefined)[]} propsLevels
6
+ * @returns Record<string, any>
7
+ */
8
+ export function mergePropsLevels (propsLevels) {
9
+ /** @type Record<string, any> */
10
+ const fullProps = {}
11
+ for (const propsLevel of propsLevels) {
12
+ if (propsLevel) {
13
+ for (const key of Object.keys(propsLevel)) {
14
+ fullProps[camelize(key)] = propsLevel[key]
15
+ }
16
+ }
17
+ }
18
+ return fullProps
19
+ }
20
+
21
+ // calculate the props of a field/input type component (text fields, etc)
22
+ // isMainComp is used to determine if this input component is also the main rendered component or if is mostly a wrapper (date picker, etc.)
23
+ /**
24
+ * @param {import('@json-layout/core').StateNode} node
25
+ * @param {import('@json-layout/core').StatefulLayout} statefulLayout
26
+ * @param {boolean} isMainComp
27
+ * @returns {Record<string, any>}
28
+ */
29
+ export function getInputProps (node, statefulLayout, isMainComp = true) {
30
+ const options = /** @type import('../components/types.js').VjsfOptions */(node.options)
31
+ /** @type {(Record<string, any> | undefined)[]} */
32
+ const propsLevels = [options.fieldProps]
33
+ if (options.density === 'comfortable') propsLevels.push(options.fieldPropsComfortable)
34
+ if (options.density === 'compact') propsLevels.push(options.fieldPropsCompact)
35
+ if (node.options.readOnly) propsLevels.push(options.fieldPropsReadOnly)
36
+ if (isMainComp) {
37
+ propsLevels.push(/** @type Record<string, any> | undefined */(options[`${node.layout.comp}Props`]))
38
+ if (node.options.readOnly) propsLevels.push(/** @type Record<string, any> | undefined */(options[`${node.layout.comp}PropsReadOnly`]))
39
+ propsLevels.push(node.layout.props)
40
+ }
41
+
42
+ const fullProps = mergePropsLevels(propsLevels)
43
+
44
+ fullProps.label = node.layout.label
45
+ if (node.error && node.validated) {
46
+ fullProps.errorMessages = node.error
47
+ }
48
+ fullProps.modelValue = node.data
49
+ if (node.options.readOnly) {
50
+ fullProps.disabled = true
51
+ fullProps.class = 'vjsf-input--readonly'
52
+ }
53
+
54
+ if (isMainComp) {
55
+ fullProps['onUpdate:modelValue'] = (/** @type string */value) => statefulLayout.input(node, value)
56
+ fullProps.onBlur = () => statefulLayout.blur(node)
57
+ }
58
+
59
+ return fullProps
60
+ }
61
+
62
+ // calculate the props of components that are not of the field category
63
+ /**
64
+ * @param {import('@json-layout/core').StateNode} node
65
+ * @param {string} comp
66
+ * @param {boolean} isMainComp
67
+ * @returns {Record<string, any>}
68
+ */
69
+ export function getCompProps (node, comp, isMainComp = true) {
70
+ const options = /** @type import('../components/types.js').VjsfOptions */(node.options)
71
+ /** @type {(Record<string, any> | undefined)[]} */
72
+ const propsLevels = [{ density: options.density }]
73
+ propsLevels.push(/** @type Record<string, any> | undefined */(options[`${comp}Props`]))
74
+ if (node.options.readOnly) propsLevels.push(/** @type Record<string, any> | undefined */(options[`${comp}PropsReadOnly`]))
75
+ if (isMainComp) propsLevels.push(node.layout.props)
76
+ const fullProps = mergePropsLevels(propsLevels)
77
+ if (isMainComp) fullProps.modelValue = node.data
78
+ return fullProps
79
+ }
@@ -0,0 +1,19 @@
1
+ import { h } from 'vue'
2
+ import NodeSlot from '../components/fragments/node-slot.vue'
3
+
4
+ // calculate the slots of components
5
+ /**
6
+ * @param {import('@json-layout/core').StateNode} node
7
+ * @param {import('@json-layout/core').StatefulLayout} statefulLayout
8
+ * @returns {Record<string, any>}
9
+ */
10
+ export function getCompSlots (node, statefulLayout) {
11
+ if (!node.layout.slots) return {}
12
+ // const options = /** @type import('../components/types.js').VjsfOptions */(node.options)
13
+ /** @type {Record<string, any>} */
14
+ const slots = {}
15
+ for (const [key, layoutSlot] of Object.entries(node.layout.slots)) {
16
+ slots[key] = () => h(NodeSlot, { layoutSlot, node, statefulLayout })
17
+ }
18
+ return slots
19
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ *
3
+ * @param {object} _schema
4
+ * @param {import("ajv").default} [_ajv]
5
+ * @param {string} lang
6
+ * @returns
7
+ */
8
+ export function v2compat(_schema: object, _ajv?: ajvModule.default | undefined, lang?: string): ajvModule.SchemaObject;
9
+ import ajvModule from 'ajv';
10
+ //# sourceMappingURL=v2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../src/compat/v2.js"],"names":[],"mappings":"AA2DA;;;;;;GAMG;AACH,kCALW,MAAM,+CAEN,MAAM,0BAkBhB;sBAjFqB,KAAK"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @param {object} schema
3
+ * @param {string} baseImport
4
+ * @returns {string}
5
+ */
6
+ export function compile(schema: object, baseImport?: string): string;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compile/index.js"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,gCAJW,MAAM,eACN,MAAM,GACJ,MAAM,CAgBlB"}
@@ -0,0 +1,47 @@
1
+ declare const _default: import("vue").DefineComponent<{
2
+ layoutSlot: {
3
+ /** @type import('vue').PropType<import('@json-layout/vocabulary').Slot> */
4
+ type: import('vue').PropType<import('@json-layout/vocabulary').Slot>;
5
+ required: true;
6
+ };
7
+ node: {
8
+ /** @type import('vue').PropType<import('../types.js').VjsfNode> */
9
+ type: import('vue').PropType<import('../types.js').VjsfNode>;
10
+ required: true;
11
+ };
12
+ statefulLayout: {
13
+ /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
14
+ type: import('vue').PropType<import('@json-layout/core').StatefulLayout>;
15
+ required: true;
16
+ };
17
+ tag: {
18
+ /** @type import('vue').PropType<string> */
19
+ type: import('vue').PropType<string>;
20
+ default: null;
21
+ };
22
+ }, any, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
23
+ layoutSlot: {
24
+ /** @type import('vue').PropType<import('@json-layout/vocabulary').Slot> */
25
+ type: import('vue').PropType<import('@json-layout/vocabulary').Slot>;
26
+ required: true;
27
+ };
28
+ node: {
29
+ /** @type import('vue').PropType<import('../types.js').VjsfNode> */
30
+ type: import('vue').PropType<import('../types.js').VjsfNode>;
31
+ required: true;
32
+ };
33
+ statefulLayout: {
34
+ /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
35
+ type: import('vue').PropType<import('@json-layout/core').StatefulLayout>;
36
+ required: true;
37
+ };
38
+ tag: {
39
+ /** @type import('vue').PropType<string> */
40
+ type: import('vue').PropType<string>;
41
+ default: null;
42
+ };
43
+ }>>, {
44
+ tag: string;
45
+ }, {}>;
46
+ export default _default;
47
+ //# sourceMappingURL=node-slot.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-slot.vue.d.ts","sourceRoot":"","sources":["../../../src/components/fragments/node-slot.vue.js"],"names":[],"mappings":";;QAUM,2EAA2E;cAAjE,OAAO,KAAK,EAAE,QAAQ,CAAC,OAAO,yBAAyB,EAAE,IAAI,CAAC;;;;QAKxE,mEAAmE;cAAzD,OAAO,KAAK,EAAE,QAAQ,CAAC,OAAO,aAAa,EAAE,QAAQ,CAAC;;;;QAKhE,+EAA+E;cAArE,OAAO,KAAK,EAAE,QAAQ,CAAC,OAAO,mBAAmB,EAAE,cAAc,CAAC;;;;QAK5E,2CAA2C;cAAjC,OAAO,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC;;;;;QAfxC,2EAA2E;cAAjE,OAAO,KAAK,EAAE,QAAQ,CAAC,OAAO,yBAAyB,EAAE,IAAI,CAAC;;;;QAKxE,mEAAmE;cAAzD,OAAO,KAAK,EAAE,QAAQ,CAAC,OAAO,aAAa,EAAE,QAAQ,CAAC;;;;QAKhE,+EAA+E;cAArE,OAAO,KAAK,EAAE,QAAQ,CAAC,OAAO,mBAAmB,EAAE,cAAc,CAAC;;;;QAK5E,2CAA2C;cAAjC,OAAO,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC"}
@@ -0,0 +1,8 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {
2
+ node: import("../types.js").VjsfNode;
3
+ $props: {
4
+ readonly node?: import("../types.js").VjsfNode | undefined;
5
+ };
6
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
7
+ export default _default;
8
+ //# sourceMappingURL=section-header.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"section-header.vue.d.ts","sourceRoot":"","sources":["../../../src/components/fragments/section-header.vue.js"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{}, {
2
+ modelValue: import("../types.js").VjsfNode;
3
+ statefulLayout: import("@json-layout/core").StatefulLayout;
4
+ formattedValue: string | null;
5
+ $props: {
6
+ readonly modelValue?: import("../types.js").VjsfNode | undefined;
7
+ readonly statefulLayout?: import("@json-layout/core").StatefulLayout | undefined;
8
+ readonly formattedValue?: string | null | undefined;
9
+ };
10
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>, {
11
+ "prepend-inner"?(_: {}): any;
12
+ default?(_: {
13
+ close: () => boolean;
14
+ }): any;
15
+ }>;
16
+ export default _default;
17
+ type __VLS_WithTemplateSlots<T, S> = T & (new () => {
18
+ $slots: S;
19
+ });
20
+ //# sourceMappingURL=text-field-menu.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-field-menu.vue.d.ts","sourceRoot":"","sources":["../../../src/components/fragments/text-field-menu.vue.js"],"names":[],"mappings":";;;;;;;;;;6BAmIsC,GAAG;;;QACX,GAAG"}
@@ -0,0 +1,10 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {
2
+ modelValue: import("./types.js").VjsfNode;
3
+ statefulLayout: import("@json-layout/core").StatefulLayout;
4
+ $props: {
5
+ readonly modelValue?: import("./types.js").VjsfNode | undefined;
6
+ readonly statefulLayout?: import("@json-layout/core").StatefulLayout | undefined;
7
+ };
8
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
9
+ export default _default;
10
+ //# sourceMappingURL=node.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.vue.d.ts","sourceRoot":"","sources":["../../src/components/node.vue.js"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {
2
+ modelValue: import("../types.js").VjsfCheckboxNode;
3
+ statefulLayout: import("@json-layout/core").StatefulLayout;
4
+ $props: {
5
+ readonly modelValue?: import("../types.js").VjsfCheckboxNode | undefined;
6
+ readonly statefulLayout?: import("@json-layout/core").StatefulLayout | undefined;
7
+ };
8
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
9
+ export default _default;
10
+ //# sourceMappingURL=checkbox.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.vue.d.ts","sourceRoot":"","sources":["../../../src/components/nodes/checkbox.vue.js"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {
2
+ modelValue: import("../types.js").VjsfColorPickerNode;
3
+ statefulLayout: import("@json-layout/core").StatefulLayout;
4
+ $props: {
5
+ readonly modelValue?: import("../types.js").VjsfColorPickerNode | undefined;
6
+ readonly statefulLayout?: import("@json-layout/core").StatefulLayout | undefined;
7
+ };
8
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
9
+ export default _default;
10
+ //# sourceMappingURL=color-picker.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-picker.vue.d.ts","sourceRoot":"","sources":["../../../src/components/nodes/color-picker.vue.js"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {
2
+ modelValue: import("../types.js").VjsfDatePickerNode;
3
+ statefulLayout: import("@json-layout/core").StatefulLayout;
4
+ $props: {
5
+ readonly modelValue?: import("../types.js").VjsfDatePickerNode | undefined;
6
+ readonly statefulLayout?: import("@json-layout/core").StatefulLayout | undefined;
7
+ };
8
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
9
+ export default _default;
10
+ //# sourceMappingURL=date-picker.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-picker.vue.d.ts","sourceRoot":"","sources":["../../../src/components/nodes/date-picker.vue.js"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {
2
+ modelValue: import("../types.js").VjsfDateTimePickerNode;
3
+ statefulLayout: import("@json-layout/core").StatefulLayout;
4
+ $props: {
5
+ readonly modelValue?: import("../types.js").VjsfDateTimePickerNode | undefined;
6
+ readonly statefulLayout?: import("@json-layout/core").StatefulLayout | undefined;
7
+ };
8
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
9
+ export default _default;
10
+ //# sourceMappingURL=date-time-picker.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-time-picker.vue.d.ts","sourceRoot":"","sources":["../../../src/components/nodes/date-time-picker.vue.js"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {
2
+ modelValue: import("../types.js").VjsfExpansionPanelsNode;
3
+ statefulLayout: import("@json-layout/core").StatefulLayout;
4
+ $props: {
5
+ readonly modelValue?: import("../types.js").VjsfExpansionPanelsNode | undefined;
6
+ readonly statefulLayout?: import("@json-layout/core").StatefulLayout | undefined;
7
+ };
8
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
9
+ export default _default;
10
+ //# sourceMappingURL=expansion-panels.vue.d.ts.map