@koumoul/vjsf 3.0.0-alpha.1 → 3.0.0-alpha.11

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 (123) hide show
  1. package/package.json +37 -16
  2. package/src/compat/v2.js +1 -4
  3. package/src/compile/index.js +18 -4
  4. package/src/compile/options.js +19 -0
  5. package/src/compile/v-jsf-compiled.vue.ejs +36 -58
  6. package/src/components/fragments/help-message.vue +3 -2
  7. package/src/components/fragments/node-slot.vue +3 -3
  8. package/src/components/fragments/section-header.vue +2 -1
  9. package/src/components/fragments/text-field-menu.vue +3 -3
  10. package/src/components/node.vue +27 -10
  11. package/src/components/nodes/autocomplete.vue +3 -10
  12. package/src/components/nodes/checkbox.vue +3 -3
  13. package/src/components/nodes/color-picker.vue +3 -3
  14. package/src/components/nodes/combobox.vue +4 -5
  15. package/src/components/nodes/date-picker.vue +3 -4
  16. package/src/components/nodes/date-time-picker.vue +2 -2
  17. package/src/components/nodes/expansion-panels.vue +4 -4
  18. package/src/components/nodes/file-input.vue +43 -0
  19. package/src/components/nodes/list.vue +177 -91
  20. package/src/components/nodes/number-combobox.vue +3 -4
  21. package/src/components/nodes/number-field.vue +4 -5
  22. package/src/components/nodes/one-of-select.vue +4 -4
  23. package/src/components/nodes/section.vue +4 -3
  24. package/src/components/nodes/select.vue +3 -4
  25. package/src/components/nodes/slider.vue +3 -3
  26. package/src/components/nodes/stepper.vue +96 -0
  27. package/src/components/nodes/switch.vue +3 -3
  28. package/src/components/nodes/tabs.vue +4 -4
  29. package/src/components/nodes/text-field.vue +10 -5
  30. package/src/components/nodes/textarea.vue +26 -6
  31. package/src/components/nodes/vertical-tabs.vue +4 -4
  32. package/src/components/options.js +27 -2
  33. package/src/components/tree.vue +2 -2
  34. package/src/components/vjsf.vue +26 -115
  35. package/src/composables/use-dnd.js +69 -0
  36. package/src/composables/use-vjsf.js +122 -0
  37. package/src/index.js +1 -0
  38. package/src/styles/vjsf.css +14 -0
  39. package/src/{components/types.ts → types.ts} +22 -1
  40. package/src/utils/arrays.js +15 -0
  41. package/src/utils/build.js +1 -0
  42. package/src/utils/global-register.js +13 -0
  43. package/src/utils/index.js +5 -0
  44. package/src/utils/props.js +20 -9
  45. package/src/utils/slots.js +2 -3
  46. package/types/compat/v2.d.ts.map +1 -1
  47. package/types/compile/index.d.ts +3 -2
  48. package/types/compile/index.d.ts.map +1 -1
  49. package/types/compile/options.d.ts +4 -0
  50. package/types/compile/options.d.ts.map +1 -0
  51. package/types/components/fragments/help-message.vue.d.ts +3 -3
  52. package/types/components/fragments/node-slot.vue.d.ts +9 -9
  53. package/types/components/fragments/node-slot.vue.d.ts.map +1 -1
  54. package/types/components/fragments/section-header.vue.d.ts +3 -3
  55. package/types/components/fragments/select-item-icon.vue.d.ts +1 -1
  56. package/types/components/fragments/select-item.vue.d.ts +3 -3
  57. package/types/components/fragments/select-selection.vue.d.ts +3 -3
  58. package/types/components/fragments/text-field-menu.vue.d.ts +5 -5
  59. package/types/components/fragments/text-field-menu.vue.d.ts.map +1 -1
  60. package/types/components/global-register.d.ts +8 -0
  61. package/types/components/global-register.d.ts.map +1 -0
  62. package/types/components/node.vue.d.ts +5 -5
  63. package/types/components/nodes/autocomplete.vue.d.ts +9 -9
  64. package/types/components/nodes/autocomplete.vue.d.ts.map +1 -1
  65. package/types/components/nodes/checkbox.vue.d.ts +5 -5
  66. package/types/components/nodes/color-picker.vue.d.ts +5 -5
  67. package/types/components/nodes/combobox.vue.d.ts +9 -9
  68. package/types/components/nodes/combobox.vue.d.ts.map +1 -1
  69. package/types/components/nodes/date-picker.vue.d.ts +5 -5
  70. package/types/components/nodes/date-time-picker.vue.d.ts +5 -5
  71. package/types/components/nodes/expansion-panels.vue.d.ts +5 -5
  72. package/types/components/nodes/file-input.vue.d.ts +27 -0
  73. package/types/components/nodes/file-input.vue.d.ts.map +1 -0
  74. package/types/components/nodes/list.vue.d.ts +5 -5
  75. package/types/components/nodes/markdown.vue.d.ts.map +1 -1
  76. package/types/components/nodes/number-combobox.vue.d.ts +9 -9
  77. package/types/components/nodes/number-combobox.vue.d.ts.map +1 -1
  78. package/types/components/nodes/number-field.vue.d.ts +9 -9
  79. package/types/components/nodes/number-field.vue.d.ts.map +1 -1
  80. package/types/components/nodes/one-of-select.vue.d.ts +5 -5
  81. package/types/components/nodes/section.vue.d.ts +5 -5
  82. package/types/components/nodes/select.vue.d.ts +9 -9
  83. package/types/components/nodes/select.vue.d.ts.map +1 -1
  84. package/types/components/nodes/slider.vue.d.ts +5 -5
  85. package/types/components/nodes/stepper.vue.d.ts +10 -0
  86. package/types/components/nodes/stepper.vue.d.ts.map +1 -0
  87. package/types/components/nodes/switch.vue.d.ts +5 -5
  88. package/types/components/nodes/tabs.vue.d.ts +5 -5
  89. package/types/components/nodes/text-field.vue.d.ts +9 -9
  90. package/types/components/nodes/text-field.vue.d.ts.map +1 -1
  91. package/types/components/nodes/textarea.vue.d.ts +9 -9
  92. package/types/components/nodes/textarea.vue.d.ts.map +1 -1
  93. package/types/components/nodes/time-picker.vue.d.ts +1 -1
  94. package/types/components/nodes/vertical-tabs.vue.d.ts +5 -5
  95. package/types/components/options.d.ts +3 -2
  96. package/types/components/options.d.ts.map +1 -1
  97. package/types/components/tree.vue.d.ts +5 -5
  98. package/types/components/types.d.ts +18 -2
  99. package/types/components/types.d.ts.map +1 -1
  100. package/types/components/vjsf.vue.d.ts +8 -9
  101. package/types/components/vjsf.vue.d.ts.map +1 -1
  102. package/types/composables/use-dnd.d.ts +25 -0
  103. package/types/composables/use-dnd.d.ts.map +1 -0
  104. package/types/composables/use-vjsf.d.ts +16 -0
  105. package/types/composables/use-vjsf.d.ts.map +1 -0
  106. package/types/index.d.ts +1 -0
  107. package/types/index.d.ts.map +1 -1
  108. package/types/types.d.ts +96 -0
  109. package/types/types.d.ts.map +1 -0
  110. package/types/utils/arrays.d.ts +9 -0
  111. package/types/utils/arrays.d.ts.map +1 -0
  112. package/types/utils/build.d.ts +2 -0
  113. package/types/utils/build.d.ts.map +1 -0
  114. package/types/utils/global-register.d.ts +8 -0
  115. package/types/utils/global-register.d.ts.map +1 -0
  116. package/types/utils/index.d.ts +6 -0
  117. package/types/utils/index.d.ts.map +1 -0
  118. package/types/utils/props.d.ts +7 -5
  119. package/types/utils/props.d.ts.map +1 -1
  120. package/types/utils/slots.d.ts +3 -3
  121. package/types/utils/slots.d.ts.map +1 -1
  122. package/src/components/nodes/markdown.vue +0 -29
  123. package/src/utils/clone.js +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koumoul/vjsf",
3
- "version": "3.0.0-alpha.1",
3
+ "version": "3.0.0-alpha.11",
4
4
  "description": "Generate forms for the vuetify UI library (vuejs) based on annotated JSON schemas.",
5
5
  "scripts": {
6
6
  "test": "vitest",
@@ -22,12 +22,41 @@
22
22
  "types": "./types/index.d.ts"
23
23
  }
24
24
  },
25
+ "./types.js": {
26
+ "import": {
27
+ "default": "./src/types.js",
28
+ "types": "./types/types.d.ts"
29
+ }
30
+ },
25
31
  "./components/*": {
26
32
  "import": {
27
33
  "default": "./src/components/*",
28
34
  "types": "./types/components/*.d.ts"
29
35
  }
30
36
  },
37
+ "./composables/*": {
38
+ "import": {
39
+ "default": "./src/composables/*",
40
+ "types": "./types/composables/*.d.ts"
41
+ }
42
+ },
43
+ "./utils": {
44
+ "import": {
45
+ "default": "./src/utils/index.js",
46
+ "types": "./types/utils/index.d.ts"
47
+ }
48
+ },
49
+ "./utils/*": {
50
+ "import": {
51
+ "default": "./src/utils/*",
52
+ "types": "./types/utils/*.d.ts"
53
+ }
54
+ },
55
+ "./styles/*": {
56
+ "import": {
57
+ "default": "./src/styles/*"
58
+ }
59
+ },
31
60
  "./compile": {
32
61
  "import": {
33
62
  "default": "./src/compile/index.js",
@@ -42,28 +71,20 @@
42
71
  }
43
72
  },
44
73
  "peerDependencies": {
45
- "vue": "^3.3.4",
46
- "vuetify": "^3.4.2"
74
+ "vue": "^3.4.3",
75
+ "vuetify": "^3.4.9"
47
76
  },
48
77
  "dependencies": {
49
- "@json-layout/core": "0.2.0",
50
- "@json-layout/vocabulary": "0.2.0",
78
+ "@json-layout/core": "0.8.1",
51
79
  "@vueuse/core": "^10.5.0",
52
80
  "debug": "^4.3.4",
53
- "easymde": "^2.18.0",
54
- "ejs": "^3.1.9",
55
- "rfdc": "^1.3.0"
81
+ "ejs": "^3.1.9"
56
82
  },
57
83
  "devDependencies": {
58
84
  "@types/debug": "^4.1.8",
59
85
  "@types/ejs": "^3.1.2",
60
- "relative-deps": "^1.0.7",
61
- "vitest": "^0.34.5",
62
- "vue": "^3.3.4",
63
- "vue-tsc": "^1.8.15"
64
- },
65
- "relativeDependencies": {
66
- "@json-layout/core": "../../json-layout/core/",
67
- "@json-layout/vocabulary": "../../json-layout/vocabulary/"
86
+ "vitest": "^1.1.1",
87
+ "vue": "^3.4.3",
88
+ "vue-tsc": "^1.8.27"
68
89
  }
69
90
  }
package/src/compat/v2.js CHANGED
@@ -1,14 +1,11 @@
1
1
  import ajvModule from 'ajv'
2
- import rfdc from 'rfdc'
3
2
  import addFormats from 'ajv-formats'
4
- import { resolveRefs } from '@json-layout/core'
3
+ import { resolveRefs, clone } from '@json-layout/core'
5
4
  import { isPartialGetItemsObj } from '@json-layout/vocabulary'
6
5
 
7
6
  // @ts-ignore
8
7
  const Ajv = /** @type {typeof ajvModule.default} */ (ajvModule)
9
8
 
10
- const clone = rfdc()
11
-
12
9
  const processFragment = (/** @type {import("ajv").SchemaObject} */schema) => {
13
10
  if (!schema.layout) {
14
11
  /** @type import('@json-layout/vocabulary').PartialCompObject */
@@ -5,6 +5,7 @@ import ejs from 'ejs'
5
5
  import { compile as compileLayout } from '@json-layout/core'
6
6
  import { serialize as serializeCompiledLayout } from '@json-layout/core/src/compile/serialize'
7
7
  import { childIsCompObject, isCompObject, isSwitchStruct } from '@json-layout/vocabulary'
8
+ import { getFullOptions } from './options.js'
8
9
 
9
10
  const __dirname = path.dirname(fileURLToPath(import.meta.url))
10
11
 
@@ -34,11 +35,13 @@ function listComps (comps, layout) {
34
35
 
35
36
  /**
36
37
  * @param {object} schema
37
- * @param {string} baseImport
38
+ * @param {import('../types.js').PartialVjsfCompileOptions} [options]
39
+ * @param {string} [baseImport]
38
40
  * @returns {string}
39
41
  */
40
- export function compile (schema, baseImport = '@koumoul/vjsf/components') {
41
- const compiledLayout = compileLayout(schema, { code: true })
42
+ export function compile (schema, options = {}, baseImport = '@koumoul/vjsf') {
43
+ const fullOptions = getFullOptions(options)
44
+ const compiledLayout = compileLayout(schema, { ...fullOptions, code: true })
42
45
  const compiledLayoutCode = serializeCompiledLayout(compiledLayout)
43
46
  /** @type Set<string> */
44
47
  const comps = new Set([])
@@ -46,6 +49,17 @@ export function compile (schema, baseImport = '@koumoul/vjsf/components') {
46
49
  listComps(comps, layout)
47
50
  }
48
51
  comps.delete('none')
49
- const code = ejs.render(template, { compiledLayoutCode, comps, baseImport })
52
+
53
+ const compImports = [...comps].map(comp => {
54
+ const compName = comp.replace(/-/g, '') + 'Node'
55
+ const compImport = fullOptions.nodeComponentImports[comp] ?? `${baseImport}/components/nodes/${comp}.vue`
56
+ return {
57
+ comp,
58
+ compName,
59
+ compImport
60
+ }
61
+ })
62
+
63
+ const code = ejs.render(template, { compiledLayoutCode, compImports, baseImport })
50
64
  return code
51
65
  }
@@ -0,0 +1,19 @@
1
+ /** @type import("../types.js").PartialVjsfCompileOptions */
2
+ export const defaultOptions = {
3
+ nodeComponentImports: {
4
+ markdown: '@koumoul/vjsf-markdown/components/nodes/markdown.vue'
5
+ }
6
+ }
7
+
8
+ /**
9
+ *
10
+ * @param {import("../types.js").PartialVjsfCompileOptions} options
11
+ * @returns
12
+ */
13
+ export const getFullOptions = (options) => {
14
+ const fullOptions = {
15
+ ...defaultOptions,
16
+ nodeComponentImports: { ...defaultOptions.nodeComponentImports, ...options.nodeComponentImports }
17
+ }
18
+ return /** @type import('../types.js').VjsfCompileOptions */ (fullOptions)
19
+ }
@@ -2,78 +2,56 @@
2
2
  // @ts-nocheck
3
3
 
4
4
  import { StatefulLayout } from '@json-layout/core'
5
- import { ref, shallowRef, getCurrentInstance, useSlots } from 'vue'
5
+ import { ref, shallowRef, getCurrentInstance, useSlots, computed } from 'vue'
6
6
  import { useElementSize } from '@vueuse/core'
7
7
 
8
- import { defaultOptions } from '<%- baseImport %>/options.js'
9
- import Tree from '<%- baseImport %>/tree.vue'
10
- <% comps.forEach(function(comp){ %>
11
- import <%= comp.replace(/-/g, '') %>Node from '<%- baseImport %>/nodes/<%= comp %>.vue'
12
- <% }); %>
13
-
14
- <%- compiledLayoutCode %>
8
+ import { defaultOptions } from '<%- baseImport %>/components/options.js'
9
+ import Tree from '<%- baseImport %>/components/tree.vue'
10
+ import { useVjsf, emits } from '<%- baseImport %>/composables/use-vjsf.js'
11
+ import '<%- baseImport %>/styles/vjsf.css'
15
12
 
16
- const vueInstance = getCurrentInstance()
17
- <% comps.forEach(function(comp){ %>
18
- if (!vueInstance?.appContext.app.component('vjsf-node-<%= comp %>')) {
19
- vueInstance.appContext.app.component('vjsf-node-<%= comp %>', <%= comp.replace(/-/g, '') %>Node)
20
- }
13
+ <% compImports.forEach(function({compName, compImport}){ %>
14
+ import <%= compName %> from '<%- compImport %>'
21
15
  <% }); %>
22
16
 
23
- const props = defineProps(['modelValue', 'options'])
24
- const emit = defineEmits(['update:modelValue', 'update:state'])
25
-
26
- const statefulLayout = shallowRef(null)
27
- const stateTree = shallowRef(null)
28
-
29
- const el = ref(null)
30
- const { width } = useElementSize(el)
31
-
32
- const slots = useSlots()
33
-
34
- const fullOptions = computed(() => {
35
- if (!width.value) return null
36
- return {
37
- ...defaultOptions,
38
- ...props.options,
39
- context: props.options.context ? JSON.parse(JSON.stringify(props.options.context)) : {},
40
- width: Math.round(width.value),
41
- vjsfSlots: { ...slots }
42
- }
43
- })
17
+ <%- compiledLayoutCode %>
44
18
 
45
- const initStatefulLayout = () => {
46
- if (!fullOptions.value) return
47
- const _statefulLayout = new StatefulLayout(compiledLayout, compiledLayout.skeletonTree, fullOptions.value, props.modelValue)
48
- statefulLayout.value = _statefulLayout
49
- stateTree.value = _statefulLayout.stateTree
50
- _statefulLayout.events.on('update', () => {
51
- stateTree.value = _statefulLayout.stateTree
52
- emit('update:modelValue', _statefulLayout.data)
53
- emit('update:state', _statefulLayout)
54
- })
55
- emit('update:state', _statefulLayout)
19
+ const nodeComponents = {
20
+ <% compImports.forEach(function({comp, compName}){ %>
21
+ "<%= comp %>": <%= compName %>,
22
+ <% }); %>
56
23
  }
57
24
 
58
- watch(fullOptions, (newOptions) => {
59
- if (!newOptions) {
60
- statefulLayout.value = null
61
- } else if (statefulLayout.value) {
62
- statefulLayout.value.options = newOptions
63
- } else {
64
- initStatefulLayout()
25
+ const props = defineProps({
26
+ modelValue: {
27
+ type: null,
28
+ default: null
29
+ },
30
+ options: {
31
+ /** @type import('vue').PropType<import('<%- baseImport %>/types.js').PartialVjsfOptions | null> */
32
+ type: Object,
33
+ default: null
65
34
  }
66
35
  })
67
36
 
68
- // case where data is updated from outside
69
- watch(() => props.modelValue, (newData) => {
70
- if (statefulLayout.value && statefulLayout.value.data !== newData) statefulLayout.value.data = newData
71
- })
72
-
37
+ const emit = defineEmits(emits)
38
+
39
+ const { el, statefulLayout, stateTree } = useVjsf(
40
+ null,
41
+ computed(() => props.modelValue),
42
+ computed(() => props.options),
43
+ nodeComponents,
44
+ emit,
45
+ null,
46
+ computed(() => compiledLayout)
47
+ )
73
48
  </script>
74
49
 
75
50
  <template>
76
- <div ref="el">
51
+ <div
52
+ ref="el"
53
+ class="vjsf"
54
+ >
77
55
  <tree
78
56
  v-if="statefulLayout && stateTree"
79
57
  :model-value="stateTree"
@@ -20,12 +20,12 @@
20
20
  </template>
21
21
 
22
22
  <script setup>
23
- import { VAlert, VBtn } from 'vuetify/components'
23
+ import { VAlert, VBtn, VSlideXReverseTransition } from 'vuetify/components'
24
24
  import { ref } from 'vue'
25
25
 
26
26
  defineProps({
27
27
  node: {
28
- /** @type import('vue').PropType<import('../types.js').VjsfNode> */
28
+ /** @type import('vue').PropType<import('../../types.js').VjsfNode> */
29
29
  type: Object,
30
30
  required: true
31
31
  }
@@ -46,3 +46,4 @@ const show = ref(false)
46
46
  z-index: 1;
47
47
  }
48
48
  </style>
49
+ ../../../types.js
@@ -12,12 +12,12 @@ export default {
12
12
  required: true
13
13
  },
14
14
  node: {
15
- /** @type import('vue').PropType<import('../types.js').VjsfNode> */
15
+ /** @type import('vue').PropType<import('../../types.js').VjsfNode> */
16
16
  type: Object,
17
17
  required: true
18
18
  },
19
19
  statefulLayout: {
20
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
20
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
21
21
  type: Object,
22
22
  required: true
23
23
  },
@@ -38,7 +38,7 @@ export default {
38
38
  }
39
39
  if (isNameSlot(this.layoutSlot)) {
40
40
  if (!this.statefulLayout.options.vjsfSlots[this.layoutSlot.name]) {
41
- console.error(`layout references a code slot "${this.layoutSlot.name}" that was not provided.`)
41
+ console.error(`vjsf: layout references a code slot "${this.layoutSlot.name}" that was not provided.`)
42
42
  } else {
43
43
  return h(renderTag, this.statefulLayout.options.vjsfSlots[this.layoutSlot.name]({ node: this.node, statefulLayout: this.statefulLayout }))
44
44
  }
@@ -4,7 +4,7 @@ import { computed } from 'vue'
4
4
 
5
5
  const props = defineProps({
6
6
  node: {
7
- /** @type import('vue').PropType<import('../types.js').VjsfNode> */
7
+ /** @type import('vue').PropType<import('../../types.js').VjsfNode> */
8
8
  type: Object,
9
9
  required: true
10
10
  }
@@ -53,3 +53,4 @@ const titleClass = computed(() => {
53
53
  </v-alert>
54
54
  </div>
55
55
  </template>
56
+ ../../../types.js
@@ -1,16 +1,16 @@
1
1
  <script setup>
2
2
  import { VMenu, VTextField } from 'vuetify/components'
3
3
  import { computed, ref } from 'vue'
4
- import { getCompProps, getInputProps } from '../../utils/props.js'
4
+ import { getCompProps, getInputProps } from '../../utils/index.js'
5
5
 
6
6
  const props = defineProps({
7
7
  modelValue: {
8
- /** @type import('vue').PropType<import('../types.js').VjsfNode> */
8
+ /** @type import('vue').PropType<import('../../types.js').VjsfNode> */
9
9
  type: Object,
10
10
  required: true
11
11
  },
12
12
  statefulLayout: {
13
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
13
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
14
14
  type: Object,
15
15
  required: true
16
16
  },
@@ -1,33 +1,50 @@
1
1
  <script setup>
2
+ import { computed } from 'vue'
3
+ import { useTheme } from 'vuetify'
2
4
  import { VCol } from 'vuetify/components'
3
5
  import NodeSlot from './fragments/node-slot.vue'
4
6
  import HelpMessage from './fragments/help-message.vue'
5
7
 
6
- defineProps({
8
+ const props = defineProps({
7
9
  modelValue: {
8
- /** @type import('vue').PropType<import('./types.js').VjsfNode> */
10
+ /** @type import('vue').PropType<import('../types.js').VjsfNode> */
9
11
  type: Object,
10
12
  required: true
11
13
  },
12
14
  statefulLayout: {
13
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
15
+ /** @type import('vue').PropType<import('../types.js').VjsfStatefulLayout> */
14
16
  type: Object,
15
17
  required: true
16
18
  }
17
19
  })
18
20
 
19
- /** @type Record<import('./types.js').Density, string> */
21
+ /** @type Record<import('../types.js').Density, string> */
20
22
  const beforeAfterClasses = {
21
23
  compact: 'my-1',
22
24
  comfortable: 'my-2',
23
25
  default: 'my-3'
24
26
  }
27
+
28
+ const theme = useTheme()
29
+
30
+ const nodeClasses = computed(() => {
31
+ let classes = `vjsf-node vjsf-node-${props.modelValue.layout.comp} vjsf-density-${props.modelValue.options.density}`
32
+ if (props.modelValue.options.readOnly) classes += ' vjsf-readonly'
33
+ if (props.modelValue.options.summary) classes += ' vjsf-summary'
34
+ if (theme.current.value.dark) classes += ' vjsf-dark'
35
+ return classes
36
+ })
37
+
38
+ if (!props.statefulLayout.options.nodeComponents[props.modelValue.layout.comp]) {
39
+ console.error(`vjsf: missing component to render vjsf node "${props.modelValue.layout.comp}", maybe you forgot to register a component from a plugin ?`)
40
+ }
41
+
25
42
  </script>
26
43
 
27
44
  <template>
28
45
  <v-col
29
46
  :cols="modelValue.cols"
30
- :class="`vjsf-node vjsf-node-${modelValue.layout.comp}`"
47
+ :class="nodeClasses"
31
48
  >
32
49
  <node-slot
33
50
  v-if="modelValue.layout.slots?.before"
@@ -35,13 +52,13 @@ const beforeAfterClasses = {
35
52
  :layout-slot="modelValue.layout.slots?.before"
36
53
  :node="modelValue"
37
54
  :stateful-layout="statefulLayout"
38
- :class="beforeAfterClasses[/** @type import('./types.js').VjsfOptions */(modelValue.options).density]"
55
+ :class="beforeAfterClasses[modelValue.options.density]"
39
56
  />
40
57
 
41
58
  <help-message
42
59
  v-if="modelValue.layout.help"
43
60
  :node="modelValue"
44
- :class="beforeAfterClasses[/** @type import('./types.js').VjsfOptions */(modelValue.options).density]"
61
+ :class="beforeAfterClasses[modelValue.options.density]"
45
62
  />
46
63
  <node-slot
47
64
  v-if="modelValue.layout.slots?.component"
@@ -51,8 +68,8 @@ const beforeAfterClasses = {
51
68
  :stateful-layout="statefulLayout"
52
69
  />
53
70
  <component
54
- :is="`vjsf-node-${modelValue.layout.comp}`"
55
- v-else-if="modelValue.layout.comp !== 'none'"
71
+ :is="props.statefulLayout.options.nodeComponents[modelValue.layout.comp]"
72
+ v-else-if="modelValue.layout.comp !== 'none' "
56
73
  :model-value="modelValue"
57
74
  :stateful-layout="statefulLayout"
58
75
  />
@@ -63,7 +80,7 @@ const beforeAfterClasses = {
63
80
  :layout-slot="modelValue.layout.slots?.after"
64
81
  :node="modelValue"
65
82
  :stateful-layout="statefulLayout"
66
- :class="beforeAfterClasses[/** @type import('./types.js').VjsfOptions */(modelValue.options).density]"
83
+ :class="beforeAfterClasses[modelValue.options.density]"
67
84
  />
68
85
  </v-col>
69
86
  </template>
@@ -1,20 +1,19 @@
1
1
  <script>
2
2
  import { VAutocomplete } from 'vuetify/components'
3
3
  import { defineComponent, computed, ref, shallowRef, h } from 'vue'
4
- import { getInputProps } from '../../utils/props.js'
5
- import { getCompSlots } from '../../utils/slots.js'
4
+ import { getInputProps, getCompSlots } from '../../utils/index.js'
6
5
  import SelectItem from '../fragments/select-item.vue'
7
6
  import SelectSelection from '../fragments/select-selection.vue'
8
7
 
9
8
  export default defineComponent({
10
9
  props: {
11
10
  modelValue: {
12
- /** @type import('vue').PropType<import('../types.js').VjsfSelectNode> */
11
+ /** @type import('vue').PropType<import('../../types.js').VjsfSelectNode> */
13
12
  type: Object,
14
13
  required: true
15
14
  },
16
15
  statefulLayout: {
17
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
16
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
18
17
  type: Object,
19
18
  required: true
20
19
  }
@@ -87,9 +86,3 @@ export default defineComponent({
87
86
  })
88
87
 
89
88
  </script>
90
-
91
- <template>
92
- <v-select
93
- v-bind="fieldProps"
94
- />
95
- </template>
@@ -1,16 +1,16 @@
1
1
  <script setup>
2
2
  import { VCheckbox } from 'vuetify/components'
3
3
  import { computed } from 'vue'
4
- import { getInputProps } from '../../utils/props.js'
4
+ import { getInputProps } from '../../utils/index.js'
5
5
 
6
6
  const props = defineProps({
7
7
  modelValue: {
8
- /** @type import('vue').PropType<import('../types.js').VjsfCheckboxNode> */
8
+ /** @type import('vue').PropType<import('../../types.js').VjsfCheckboxNode> */
9
9
  type: Object,
10
10
  required: true
11
11
  },
12
12
  statefulLayout: {
13
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
13
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
14
14
  type: Object,
15
15
  required: true
16
16
  }
@@ -2,16 +2,16 @@
2
2
  import TextFieldMenu from '../fragments/text-field-menu.vue'
3
3
  import { VColorPicker } from 'vuetify/components'
4
4
  import { computed } from 'vue'
5
- import { getCompProps } from '../../utils/props.js'
5
+ import { getCompProps } from '../../utils/index.js'
6
6
 
7
7
  const props = defineProps({
8
8
  modelValue: {
9
- /** @type import('vue').PropType<import('../types.js').VjsfColorPickerNode> */
9
+ /** @type import('vue').PropType<import('../../types.js').VjsfColorPickerNode> */
10
10
  type: Object,
11
11
  required: true
12
12
  },
13
13
  statefulLayout: {
14
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
14
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
15
15
  type: Object,
16
16
  required: true
17
17
  }
@@ -1,18 +1,17 @@
1
1
  <script>
2
2
  import { defineComponent, h, computed, shallowRef, ref } from 'vue'
3
3
  import { VCombobox } from 'vuetify/components'
4
- import { getInputProps } from '../../utils/props.js'
5
- import { getCompSlots } from '../../utils/slots.js'
4
+ import { getInputProps, getCompSlots } from '../../utils/index.js'
6
5
 
7
6
  export default defineComponent({
8
7
  props: {
9
8
  modelValue: {
10
- /** @type import('vue').PropType<import('../types.js').VjsfComboboxNode> */
9
+ /** @type import('vue').PropType<import('../../types.js').VjsfComboboxNode> */
11
10
  type: Object,
12
11
  required: true
13
12
  },
14
13
  statefulLayout: {
15
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
14
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
16
15
  type: Object,
17
16
  required: true
18
17
  }
@@ -37,7 +36,6 @@ export default defineComponent({
37
36
  if (props.statefulLayout.stateTree === lastStateTree && props.statefulLayout.options.context === lastContext) return
38
37
  lastStateTree = props.statefulLayout.stateTree
39
38
  lastContext = props.statefulLayout.options.context ?? null
40
- console.log('HAS ITEMS ?', hasItems.value)
41
39
  if (hasItems.value) {
42
40
  loading.value = true
43
41
  items.value = await props.statefulLayout.getItems(props.modelValue)
@@ -52,6 +50,7 @@ export default defineComponent({
52
50
  const fieldProps = computed(() => {
53
51
  const fieldProps = getInputProps(props.modelValue, props.statefulLayout)
54
52
  fieldProps.loading = loading.value
53
+ fieldProps.returnObject = false
55
54
  if (hasItems.value) fieldProps.items = items.value
56
55
  if (props.modelValue.options.readOnly) fieldProps.menuProps = { modelValue: false }
57
56
  if (props.modelValue.layout.multiple) {
@@ -3,17 +3,16 @@ import TextFieldMenu from '../fragments/text-field-menu.vue'
3
3
  import { VDatePicker } from 'vuetify/components/VDatePicker'
4
4
  import { useDate } from 'vuetify'
5
5
  import { computed } from 'vue'
6
- import { getCompProps } from '../../utils/props.js'
7
- import { getDateTimeParts } from '../../utils/dates.js'
6
+ import { getCompProps, getDateTimeParts } from '../../utils/index.js'
8
7
 
9
8
  const props = defineProps({
10
9
  modelValue: {
11
- /** @type import('vue').PropType<import('../types.js').VjsfDatePickerNode> */
10
+ /** @type import('vue').PropType<import('../../types.js').VjsfDatePickerNode> */
12
11
  type: Object,
13
12
  required: true
14
13
  },
15
14
  statefulLayout: {
16
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
15
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
17
16
  type: Object,
18
17
  required: true
19
18
  }
@@ -2,12 +2,12 @@
2
2
 
3
3
  defineProps({
4
4
  modelValue: {
5
- /** @type import('vue').PropType<import('../types.js').VjsfDateTimePickerNode> */
5
+ /** @type import('vue').PropType<import('../../types.js').VjsfDateTimePickerNode> */
6
6
  type: Object,
7
7
  required: true
8
8
  },
9
9
  statefulLayout: {
10
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
10
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
11
11
  type: Object,
12
12
  required: true
13
13
  }
@@ -1,17 +1,17 @@
1
1
  <script setup>
2
- import { VExpansionPanels, VExpansionPanel, VExpansionPanelTitle, VContainer } from 'vuetify/components'
2
+ import { VExpansionPanels, VExpansionPanel, VExpansionPanelTitle, VContainer, VRow, VIcon } from 'vuetify/components'
3
3
  import { isSection } from '@json-layout/core'
4
4
  import Node from '../node.vue'
5
5
  import SectionHeader from '../fragments/section-header.vue'
6
6
 
7
7
  defineProps({
8
8
  modelValue: {
9
- /** @type import('vue').PropType<import('../types.js').VjsfExpansionPanelsNode> */
9
+ /** @type import('vue').PropType<import('../../types.js').VjsfExpansionPanelsNode> */
10
10
  type: Object,
11
11
  required: true
12
12
  },
13
13
  statefulLayout: {
14
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
14
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
15
15
  type: Object,
16
16
  required: true
17
17
  }
@@ -42,7 +42,7 @@ defineProps({
42
42
  <node
43
43
  v-for="grandChild of isSection(child) ? child.children : [child]"
44
44
  :key="grandChild.fullKey"
45
- :model-value="/** @type import('../types.js').VjsfNode */(grandChild)"
45
+ :model-value="/** @type import('../../types.js').VjsfNode */(grandChild)"
46
46
  :stateful-layout="statefulLayout"
47
47
  />
48
48
  </v-row>