@koumoul/vjsf 3.0.0-beta.7 → 3.0.0-beta.8

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koumoul/vjsf",
3
- "version": "3.0.0-beta.7",
3
+ "version": "3.0.0-beta.8",
4
4
  "description": "Generate forms for the vuetify UI library (vuejs) based on annotated JSON schemas.",
5
5
  "scripts": {
6
6
  "test": "vitest",
@@ -75,7 +75,7 @@
75
75
  "vuetify": "^3.4.9"
76
76
  },
77
77
  "dependencies": {
78
- "@json-layout/core": "0.12.0",
78
+ "@json-layout/core": "0.13.0",
79
79
  "@vueuse/core": "^10.5.0",
80
80
  "debug": "^4.3.4",
81
81
  "ejs": "^3.1.9"
package/src/compat/v2.js CHANGED
@@ -11,6 +11,12 @@ const processFragment = (/** @type {import("ajv").SchemaObject} */schema) => {
11
11
  /** @type import('@json-layout/vocabulary').PartialCompObject */
12
12
  const layout = {}
13
13
 
14
+ if (schema.separator || schema['x-separator']) {
15
+ layout.separator = schema.separator || schema['x-separator']
16
+ delete schema.separator
17
+ delete schema['x-separator']
18
+ }
19
+
14
20
  if (schema['x-display'] === 'icon' && (schema.enum || schema.items?.enum)) {
15
21
  layout.getItems = { itemIcon: schema['x-itemIcon'] || 'data.value' }
16
22
  delete schema['x-display']
@@ -28,7 +28,7 @@ const fieldProps = computed(() => {
28
28
  })
29
29
 
30
30
  const menuProps = computed(() => {
31
- const menuProps = getCompProps(props.modelValue, 'menu', false)
31
+ const menuProps = getCompProps(props.modelValue)
32
32
  menuProps.closeOnContentClick = false
33
33
  menuProps.disabled = true
34
34
  return menuProps
@@ -18,7 +18,8 @@ const props = defineProps({
18
18
  })
19
19
 
20
20
  const colorPickerProps = computed(() => {
21
- const colorPickerProps = getCompProps(props.modelValue, 'colorPicker', true)
21
+ const colorPickerProps = getCompProps(props.modelValue, true)
22
+ colorPickerProps.modelValue = props.modelValue.data
22
23
  return colorPickerProps
23
24
  })
24
25
  </script>
@@ -21,7 +21,7 @@ const props = defineProps({
21
21
  const vDate = useDate()
22
22
 
23
23
  const datePickerProps = computed(() => {
24
- const datePickerProps = getCompProps(props.modelValue, 'datePicker', true)
24
+ const datePickerProps = getCompProps(props.modelValue, true)
25
25
  datePickerProps.hideActions = true
26
26
  if (props.modelValue.data) datePickerProps.modelValue = new Date(props.modelValue.data)
27
27
  return datePickerProps
@@ -1,8 +1,10 @@
1
1
  <script setup>
2
- import { VExpansionPanels, VExpansionPanel, VExpansionPanelTitle, VContainer, VRow, VIcon } from 'vuetify/components'
2
+ import { VExpansionPanels, VExpansionPanel, VExpansionPanelTitle, VExpansionPanelText, VContainer, VRow, VIcon } from 'vuetify/components'
3
+ import { computed } from 'vue'
3
4
  import { isSection } from '@json-layout/core'
4
5
  import Node from '../node.vue'
5
6
  import SectionHeader from '../fragments/section-header.vue'
7
+ import { getCompProps } from '../../utils/index.js'
6
8
 
7
9
  defineProps({
8
10
  modelValue: {
@@ -21,7 +23,7 @@ defineProps({
21
23
 
22
24
  <template>
23
25
  <section-header :node="modelValue" />
24
- <v-expansion-panels>
26
+ <v-expansion-panels v-bind="getCompProps(modelValue, true)">
25
27
  <v-expansion-panel
26
28
  v-for="(child, i) of modelValue.children"
27
29
  :key="child.key"
@@ -37,16 +39,24 @@ defineProps({
37
39
  </v-icon>
38
40
  {{ child.layout.title ?? child.layout.label }}
39
41
  </v-expansion-panel-title>
40
- <v-container fluid>
41
- <v-row>
42
- <node
43
- v-for="grandChild of isSection(child) ? child.children : [child]"
44
- :key="grandChild.fullKey"
45
- :model-value="/** @type import('../../types.js').VjsfNode */(grandChild)"
46
- :stateful-layout="statefulLayout"
47
- />
48
- </v-row>
49
- </v-container>
42
+ <v-expansion-panel-text>
43
+ <v-container fluid>
44
+ <v-row>
45
+ <node
46
+ v-for="grandChild of isSection(child) ? child.children : [child]"
47
+ :key="grandChild.fullKey"
48
+ :model-value="/** @type import('../../types.js').VjsfNode */(grandChild)"
49
+ :stateful-layout="statefulLayout"
50
+ />
51
+ </v-row>
52
+ </v-container>
53
+ </v-expansion-panel-text>
50
54
  </v-expansion-panel>
51
55
  </v-expansion-panels>
52
56
  </template>
57
+
58
+ <style>
59
+ .vjsf-node-expansion-panels .v-expansion-panel-text__wrapper {
60
+ padding: 0;
61
+ }
62
+ </style>
@@ -48,6 +48,12 @@ const buttonDensity = computed(() => {
48
48
  return props.modelValue.options.density
49
49
  })
50
50
 
51
+ const pushEmptyItem = () => {
52
+ const newData = (props.modelValue.data ?? []).concat([undefined])
53
+ props.statefulLayout.input(props.modelValue, newData)
54
+ props.statefulLayout.activateItem(props.modelValue, newData.length - 1)
55
+ }
56
+
51
57
  </script>
52
58
 
53
59
  <template>
@@ -180,7 +186,7 @@ const buttonDensity = computed(() => {
180
186
  <v-btn
181
187
  color="primary"
182
188
  :density="modelValue.options.density"
183
- @click="statefulLayout.input(modelValue, (modelValue.data ?? []).concat([undefined]))"
189
+ @click="pushEmptyItem"
184
190
  >
185
191
  {{ modelValue.messages.addItem }}
186
192
  </v-btn>
@@ -1,5 +1,5 @@
1
1
  import { StatefulLayout, produceCompileOptions } from '@json-layout/core'
2
- import { inject, shallowRef, computed, ref, watch, useSlots } from 'vue'
2
+ import { inject, toRaw, shallowRef, computed, ref, watch, useSlots } from 'vue'
3
3
  import { useElementSize } from '@vueuse/core'
4
4
  import { getFullOptions } from '../components/options.js'
5
5
  import { registeredNodeComponents } from '../utils/index.js'
@@ -53,7 +53,7 @@ export const useVjsf = (schema, modelValue, options, nodeComponents, emit, compi
53
53
 
54
54
  const slots = useSlots()
55
55
 
56
- const fullOptions = computed(() => getFullOptions(options.value, form, width.value, slots, { ...nodeComponents, ...registeredNodeComponents.value }))
56
+ const fullOptions = computed(() => getFullOptions(options.value, form, width.value, slots, { ...nodeComponents, ...toRaw(registeredNodeComponents.value) }))
57
57
 
58
58
  // do not use a simple computed here as we want to prevent recompiling the layout when the options are the same
59
59
  /** @type {import('vue').Ref<import('@json-layout/core').PartialCompileOptions>} */
@@ -89,10 +89,10 @@ export const useVjsf = (schema, modelValue, options, nodeComponents, emit, compi
89
89
 
90
90
  // @ts-ignore
91
91
  const _statefulLayout = /** @type {import('../types.js').VjsfStatefulLayout} */(new StatefulLayout(
92
- compiledLayout.value,
93
- compiledLayout.value.skeletonTree,
94
- fullOptions.value,
95
- modelValue.value
92
+ toRaw(compiledLayout.value),
93
+ toRaw(compiledLayout.value.skeletonTree),
94
+ toRaw(fullOptions.value),
95
+ toRaw(modelValue.value)
96
96
  ))
97
97
  statefulLayout.value = _statefulLayout
98
98
  onStatefulLayoutUpdate()
@@ -122,7 +122,7 @@ export const useVjsf = (schema, modelValue, options, nodeComponents, emit, compi
122
122
 
123
123
  // case where data is updated from outside
124
124
  watch(modelValue, (newData) => {
125
- if (statefulLayout.value && statefulLayout.value.data !== newData) statefulLayout.value.data = newData
125
+ if (statefulLayout.value && statefulLayout.value.data !== newData) statefulLayout.value.data = toRaw(newData)
126
126
  })
127
127
 
128
128
  // case where schema or compile options are updated from outside
@@ -1 +1 @@
1
- export { commonjsDeps } from '@json-layout/core/utils/build'
1
+ export { commonjsDeps, commonjsDepsPaths } from '@json-layout/core/utils/build'
@@ -65,7 +65,7 @@ export function getInputProps (node, statefulLayout, layoutPropsMap, isMainComp
65
65
  if (node.error && node.validated) {
66
66
  fullProps.errorMessages = node.error
67
67
  }
68
- fullProps.modelValue = node.data
68
+ fullProps.modelValue = (typeof node.data === 'string' && node.layout.separator) ? node.data.split(/** @type {string} */(node.layout.separator)) : node.data
69
69
  if (node.options.readOnly) {
70
70
  fullProps.disabled = true
71
71
  fullProps.class.push('vjsf-input--readonly')
@@ -82,7 +82,9 @@ export function getInputProps (node, statefulLayout, layoutPropsMap, isMainComp
82
82
  }
83
83
 
84
84
  if (isMainComp) {
85
- fullProps['onUpdate:modelValue'] = (/** @type string */value) => statefulLayout.input(node, value)
85
+ fullProps['onUpdate:modelValue'] = (/** @type string */value) => {
86
+ return statefulLayout.input(node, (Array.isArray(value) && node.layout.separator) ? value.join(/** @type {string} */(node.layout.separator)) : value)
87
+ }
86
88
  fullProps.onBlur = () => statefulLayout.blur(node)
87
89
  }
88
90
 
@@ -92,18 +94,14 @@ export function getInputProps (node, statefulLayout, layoutPropsMap, isMainComp
92
94
  // calculate the props of components that are not of the field category
93
95
  /**
94
96
  * @param {import('@json-layout/core').StateNode} node
95
- * @param {string} comp
96
97
  * @param {boolean} isMainComp
97
98
  * @returns {Record<string, any>}
98
99
  */
99
- export function getCompProps (node, comp, isMainComp = true) {
100
+ export function getCompProps (node, isMainComp = true) {
100
101
  const options = /** @type import('../types.js').VjsfOptions */(node.options)
101
102
  /** @type {(Record<string, any> | undefined)[]} */
102
103
  const propsLevels = [{ density: options.density }]
103
- propsLevels.push(/** @type Record<string, any> | undefined */(options[`${comp}Props`]))
104
- if (node.options.readOnly) propsLevels.push(/** @type Record<string, any> | undefined */(options[`${comp}PropsReadOnly`]))
105
104
  if (isMainComp) propsLevels.push(node.layout.props)
106
105
  const fullProps = mergePropsLevels(propsLevels)
107
- if (isMainComp) fullProps.modelValue = node.data
108
106
  return fullProps
109
107
  }
@@ -1 +1 @@
1
- {"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../src/compat/v2.js"],"names":[],"mappings":"AA8FA;;;;;;GAMG;AACH,kCALW,MAAM,+CAEN,MAAM,0BAkBhB;sBApHqB,KAAK"}
1
+ {"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../src/compat/v2.js"],"names":[],"mappings":"AAoGA;;;;;;GAMG;AACH,kCALW,MAAM,+CAEN,MAAM,0BAkBhB;sBA1HqB,KAAK"}
@@ -1,2 +1,2 @@
1
- export { commonjsDeps } from "@json-layout/core/utils/build";
1
+ export { commonjsDeps, commonjsDepsPaths } from "@json-layout/core/utils/build";
2
2
  //# sourceMappingURL=build.d.ts.map
@@ -15,9 +15,8 @@ export function mergePropsLevels(propsLevels: (Record<string, any> | undefined)[
15
15
  export function getInputProps(node: import('../types.js').VjsfNode, statefulLayout: import('../types.js').VjsfStatefulLayout, layoutPropsMap?: (string | [string, string])[] | undefined, isMainComp?: boolean | undefined): Record<string, any>;
16
16
  /**
17
17
  * @param {import('@json-layout/core').StateNode} node
18
- * @param {string} comp
19
18
  * @param {boolean} isMainComp
20
19
  * @returns {Record<string, any>}
21
20
  */
22
- export function getCompProps(node: import('@json-layout/core').StateNode, comp: string, isMainComp?: boolean): Record<string, any>;
21
+ export function getCompProps(node: import('@json-layout/core').StateNode, isMainComp?: boolean): Record<string, any>;
23
22
  //# sourceMappingURL=props.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../src/utils/props.js"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,8CAHW,CAAC,OAAO,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC,EAAE,GACjC,OAAO,MAAM,EAAE,GAAG,CAAC,GAAG;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAqBnD;AAID;;;;;;GAMG;AACH,oCANW,OAAO,aAAa,EAAE,QAAQ,kBAC9B,OAAO,aAAa,EAAE,kBAAkB,iGAGtC,OAAO,MAAM,EAAE,GAAG,CAAC,CAuC/B;AAGD;;;;;GAKG;AACH,mCALW,OAAO,mBAAmB,EAAE,SAAS,QACrC,MAAM,eACN,OAAO,GACL,OAAO,MAAM,EAAE,GAAG,CAAC,CAY/B"}
1
+ {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../src/utils/props.js"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,8CAHW,CAAC,OAAO,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC,EAAE,GACjC,OAAO,MAAM,EAAE,GAAG,CAAC,GAAG;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAC,CAqBnD;AAID;;;;;;GAMG;AACH,oCANW,OAAO,aAAa,EAAE,QAAQ,kBAC9B,OAAO,aAAa,EAAE,kBAAkB,iGAGtC,OAAO,MAAM,EAAE,GAAG,CAAC,CAyC/B;AAGD;;;;GAIG;AACH,mCAJW,OAAO,mBAAmB,EAAE,SAAS,eACrC,OAAO,GACL,OAAO,MAAM,EAAE,GAAG,CAAC,CAS/B"}