@koumoul/vjsf 3.0.0-alpha.4 → 3.0.0-alpha.6

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 (107) hide show
  1. package/package.json +27 -6
  2. package/src/compile/index.js +18 -4
  3. package/src/compile/options.js +19 -0
  4. package/src/compile/v-jsf-compiled.vue.ejs +28 -10
  5. package/src/components/fragments/help-message.vue +2 -1
  6. package/src/components/fragments/node-slot.vue +3 -3
  7. package/src/components/fragments/section-header.vue +2 -1
  8. package/src/components/fragments/text-field-menu.vue +3 -3
  9. package/src/components/node.vue +12 -8
  10. package/src/components/nodes/autocomplete.vue +3 -4
  11. package/src/components/nodes/checkbox.vue +3 -3
  12. package/src/components/nodes/color-picker.vue +3 -3
  13. package/src/components/nodes/combobox.vue +3 -4
  14. package/src/components/nodes/date-picker.vue +3 -4
  15. package/src/components/nodes/date-time-picker.vue +2 -2
  16. package/src/components/nodes/expansion-panels.vue +3 -3
  17. package/src/components/nodes/file-input.vue +43 -0
  18. package/src/components/nodes/list.vue +4 -4
  19. package/src/components/nodes/number-combobox.vue +3 -4
  20. package/src/components/nodes/number-field.vue +3 -4
  21. package/src/components/nodes/one-of-select.vue +3 -3
  22. package/src/components/nodes/section.vue +3 -3
  23. package/src/components/nodes/select.vue +3 -4
  24. package/src/components/nodes/slider.vue +3 -3
  25. package/src/components/nodes/stepper.vue +3 -5
  26. package/src/components/nodes/switch.vue +3 -3
  27. package/src/components/nodes/tabs.vue +3 -3
  28. package/src/components/nodes/text-field.vue +3 -4
  29. package/src/components/nodes/textarea.vue +3 -4
  30. package/src/components/nodes/vertical-tabs.vue +3 -3
  31. package/src/components/options.js +9 -6
  32. package/src/components/tree.vue +2 -2
  33. package/src/components/vjsf.vue +9 -13
  34. package/src/composables/use-dnd.js +1 -1
  35. package/src/composables/use-vjsf.js +9 -8
  36. package/src/index.js +1 -0
  37. package/src/{components/types.ts → types.ts} +18 -2
  38. package/src/utils/global-register.js +10 -0
  39. package/src/utils/index.js +5 -0
  40. package/src/utils/props.js +4 -4
  41. package/src/utils/slots.js +2 -3
  42. package/types/compile/index.d.ts +3 -2
  43. package/types/compile/index.d.ts.map +1 -1
  44. package/types/compile/options.d.ts +4 -0
  45. package/types/compile/options.d.ts.map +1 -0
  46. package/types/components/fragments/help-message.vue.d.ts +2 -2
  47. package/types/components/fragments/node-slot.vue.d.ts +8 -8
  48. package/types/components/fragments/node-slot.vue.d.ts.map +1 -1
  49. package/types/components/fragments/section-header.vue.d.ts +2 -2
  50. package/types/components/fragments/select-item.vue.d.ts +2 -2
  51. package/types/components/fragments/text-field-menu.vue.d.ts +4 -4
  52. package/types/components/fragments/text-field-menu.vue.d.ts.map +1 -1
  53. package/types/components/global-register.d.ts +8 -0
  54. package/types/components/global-register.d.ts.map +1 -0
  55. package/types/components/node.vue.d.ts +4 -4
  56. package/types/components/nodes/autocomplete.vue.d.ts +8 -8
  57. package/types/components/nodes/autocomplete.vue.d.ts.map +1 -1
  58. package/types/components/nodes/checkbox.vue.d.ts +4 -4
  59. package/types/components/nodes/color-picker.vue.d.ts +4 -4
  60. package/types/components/nodes/combobox.vue.d.ts +8 -8
  61. package/types/components/nodes/combobox.vue.d.ts.map +1 -1
  62. package/types/components/nodes/date-picker.vue.d.ts +4 -4
  63. package/types/components/nodes/date-time-picker.vue.d.ts +4 -4
  64. package/types/components/nodes/expansion-panels.vue.d.ts +4 -4
  65. package/types/components/nodes/file-input.vue.d.ts +27 -0
  66. package/types/components/nodes/file-input.vue.d.ts.map +1 -0
  67. package/types/components/nodes/list.vue.d.ts +4 -4
  68. package/types/components/nodes/number-combobox.vue.d.ts +8 -8
  69. package/types/components/nodes/number-combobox.vue.d.ts.map +1 -1
  70. package/types/components/nodes/number-field.vue.d.ts +8 -8
  71. package/types/components/nodes/number-field.vue.d.ts.map +1 -1
  72. package/types/components/nodes/one-of-select.vue.d.ts +4 -4
  73. package/types/components/nodes/section.vue.d.ts +4 -4
  74. package/types/components/nodes/select.vue.d.ts +8 -8
  75. package/types/components/nodes/select.vue.d.ts.map +1 -1
  76. package/types/components/nodes/slider.vue.d.ts +4 -4
  77. package/types/components/nodes/stepper.vue.d.ts +4 -4
  78. package/types/components/nodes/switch.vue.d.ts +4 -4
  79. package/types/components/nodes/tabs.vue.d.ts +4 -4
  80. package/types/components/nodes/text-field.vue.d.ts +8 -8
  81. package/types/components/nodes/text-field.vue.d.ts.map +1 -1
  82. package/types/components/nodes/textarea.vue.d.ts +8 -8
  83. package/types/components/nodes/textarea.vue.d.ts.map +1 -1
  84. package/types/components/nodes/vertical-tabs.vue.d.ts +4 -4
  85. package/types/components/options.d.ts +3 -3
  86. package/types/components/options.d.ts.map +1 -1
  87. package/types/components/tree.vue.d.ts +2 -2
  88. package/types/components/types.d.ts +14 -2
  89. package/types/components/types.d.ts.map +1 -1
  90. package/types/components/vjsf.vue.d.ts +3 -3
  91. package/types/composables/use-dnd.d.ts +5 -1
  92. package/types/composables/use-dnd.d.ts.map +1 -1
  93. package/types/composables/use-vjsf.d.ts +4 -5
  94. package/types/composables/use-vjsf.d.ts.map +1 -1
  95. package/types/index.d.ts +1 -0
  96. package/types/index.d.ts.map +1 -1
  97. package/types/types.d.ts +95 -0
  98. package/types/types.d.ts.map +1 -0
  99. package/types/utils/global-register.d.ts +8 -0
  100. package/types/utils/global-register.d.ts.map +1 -0
  101. package/types/utils/index.d.ts +6 -0
  102. package/types/utils/index.d.ts.map +1 -0
  103. package/types/utils/props.d.ts +3 -3
  104. package/types/utils/props.d.ts.map +1 -1
  105. package/types/utils/slots.d.ts +3 -3
  106. package/types/utils/slots.d.ts.map +1 -1
  107. package/src/components/nodes/markdown.vue +0 -341
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koumoul/vjsf",
3
- "version": "3.0.0-alpha.4",
3
+ "version": "3.0.0-alpha.6",
4
4
  "description": "Generate forms for the vuetify UI library (vuejs) based on annotated JSON schemas.",
5
5
  "scripts": {
6
6
  "test": "vitest",
@@ -22,6 +22,12 @@
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/*",
@@ -34,6 +40,23 @@
34
40
  "types": "./types/composables/*.d.ts"
35
41
  }
36
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
+ },
37
60
  "./compile": {
38
61
  "import": {
39
62
  "default": "./src/compile/index.js",
@@ -49,15 +72,13 @@
49
72
  },
50
73
  "peerDependencies": {
51
74
  "vue": "^3.3.4",
52
- "vuetify": "^3.4.2"
75
+ "vuetify": "^3.4.8"
53
76
  },
54
77
  "dependencies": {
55
- "@json-layout/core": "0.5.0",
78
+ "@json-layout/core": "0.7.0",
56
79
  "@vueuse/core": "^10.5.0",
57
80
  "debug": "^4.3.4",
58
- "easymde": "^2.18.0",
59
- "ejs": "^3.1.9",
60
- "rfdc": "^1.3.0"
81
+ "ejs": "^3.1.9"
61
82
  },
62
83
  "devDependencies": {
63
84
  "@types/debug": "^4.1.8",
@@ -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') {
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') {
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
+ }
@@ -8,26 +8,41 @@ import { useElementSize } from '@vueuse/core'
8
8
  import { defaultOptions } from '<%- baseImport %>/components/options.js'
9
9
  import Tree from '<%- baseImport %>/components/tree.vue'
10
10
  import { useVjsf, emits } from '<%- baseImport %>/composables/use-vjsf.js'
11
- <% comps.forEach(function(comp){ %>
12
- import <%= comp.replace(/-/g, '') %>Node from '<%- baseImport %>/components/nodes/<%= comp %>.vue'
11
+ import '<%- baseImport %>/styles/vjsf.css'
12
+ import { registeredNodeComponents } from '<%- baseImport %>/utils'
13
+
14
+ <% compImports.forEach(function({compName, compImport}){ %>
15
+ import <%= compName %> from '<%- compImport %>'
13
16
  <% }); %>
14
17
 
15
18
  <%- compiledLayoutCode %>
16
19
 
17
- const vueInstance = getCurrentInstance()
18
- <% comps.forEach(function(comp){ %>
19
- if (!vueInstance?.appContext.app.component('vjsf-node-<%= comp %>')) {
20
- vueInstance.appContext.app.component('vjsf-node-<%= comp %>', <%= comp.replace(/-/g, '') %>Node)
20
+ const nodeComponents = {
21
+ <% compImports.forEach(function({comp, compName}){ %>
22
+ "<%= comp %>": <%= compName %>,
23
+ <% }); %>
24
+ ...registeredNodeComponents
21
25
  }
22
- <% }); %>
23
26
 
24
- const props = defineProps(['modelValue', 'options'])
25
- const emit = defineEmits(Object.keys(emits))
27
+ const props = defineProps({
28
+ modelValue: {
29
+ type: null,
30
+ default: null
31
+ },
32
+ options: {
33
+ /** @type import('vue').PropType<import('<%- baseImport %>/types.js').PartialVjsfOptions> */
34
+ type: Object,
35
+ required: true
36
+ }
37
+ })
38
+
39
+ const emit = defineEmits(emits)
26
40
 
27
41
  const { el, statefulLayout, stateTree } = useVjsf(
28
42
  null,
29
43
  computed(() => props.modelValue),
30
44
  computed(() => props.options),
45
+ nodeComponents,
31
46
  emit,
32
47
  null,
33
48
  computed(() => compiledLayout)
@@ -35,7 +50,10 @@ const { el, statefulLayout, stateTree } = useVjsf(
35
50
  </script>
36
51
 
37
52
  <template>
38
- <div ref="el">
53
+ <div
54
+ ref="el"
55
+ class="vjsf"
56
+ >
39
57
  <tree
40
58
  v-if="statefulLayout && stateTree"
41
59
  :model-value="stateTree"
@@ -25,7 +25,7 @@ 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
  },
@@ -7,18 +7,18 @@ import HelpMessage from './fragments/help-message.vue'
7
7
 
8
8
  const props = defineProps({
9
9
  modelValue: {
10
- /** @type import('vue').PropType<import('./types.js').VjsfNode> */
10
+ /** @type import('vue').PropType<import('../types.js').VjsfNode> */
11
11
  type: Object,
12
12
  required: true
13
13
  },
14
14
  statefulLayout: {
15
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
15
+ /** @type import('vue').PropType<import('../types.js').VjsfStatefulLayout> */
16
16
  type: Object,
17
17
  required: true
18
18
  }
19
19
  })
20
20
 
21
- /** @type Record<import('./types.js').Density, string> */
21
+ /** @type Record<import('../types.js').Density, string> */
22
22
  const beforeAfterClasses = {
23
23
  compact: 'my-1',
24
24
  comfortable: 'my-2',
@@ -35,6 +35,10 @@ const nodeClasses = computed(() => {
35
35
  return classes
36
36
  })
37
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
+
38
42
  </script>
39
43
 
40
44
  <template>
@@ -48,13 +52,13 @@ const nodeClasses = computed(() => {
48
52
  :layout-slot="modelValue.layout.slots?.before"
49
53
  :node="modelValue"
50
54
  :stateful-layout="statefulLayout"
51
- :class="beforeAfterClasses[/** @type import('./types.js').VjsfOptions */(modelValue.options).density]"
55
+ :class="beforeAfterClasses[modelValue.options.density]"
52
56
  />
53
57
 
54
58
  <help-message
55
59
  v-if="modelValue.layout.help"
56
60
  :node="modelValue"
57
- :class="beforeAfterClasses[/** @type import('./types.js').VjsfOptions */(modelValue.options).density]"
61
+ :class="beforeAfterClasses[modelValue.options.density]"
58
62
  />
59
63
  <node-slot
60
64
  v-if="modelValue.layout.slots?.component"
@@ -64,8 +68,8 @@ const nodeClasses = computed(() => {
64
68
  :stateful-layout="statefulLayout"
65
69
  />
66
70
  <component
67
- :is="`vjsf-node-${modelValue.layout.comp}`"
68
- v-else-if="modelValue.layout.comp !== 'none'"
71
+ :is="props.statefulLayout.options.nodeComponents[modelValue.layout.comp]"
72
+ v-else-if="modelValue.layout.comp !== 'none' "
69
73
  :model-value="modelValue"
70
74
  :stateful-layout="statefulLayout"
71
75
  />
@@ -76,7 +80,7 @@ const nodeClasses = computed(() => {
76
80
  :layout-slot="modelValue.layout.slots?.after"
77
81
  :node="modelValue"
78
82
  :stateful-layout="statefulLayout"
79
- :class="beforeAfterClasses[/** @type import('./types.js').VjsfOptions */(modelValue.options).density]"
83
+ :class="beforeAfterClasses[modelValue.options.density]"
80
84
  />
81
85
  </v-col>
82
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
  }
@@ -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
  }
@@ -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
  }
@@ -6,12 +6,12 @@ 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>
@@ -0,0 +1,43 @@
1
+ <script>
2
+ import { defineComponent, h, computed } from 'vue'
3
+ import { VFileInput } from 'vuetify/components'
4
+ import { getInputProps, getCompSlots } from '../../utils/index.js'
5
+
6
+ export default defineComponent({
7
+ props: {
8
+ modelValue: {
9
+ /** @type import('vue').PropType<import('../../types.js').VjsfFileInputNode> */
10
+ type: Object,
11
+ required: true
12
+ },
13
+ statefulLayout: {
14
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
15
+ type: Object,
16
+ required: true
17
+ }
18
+ },
19
+ setup (props) {
20
+ const fieldProps = computed(() => {
21
+ const fieldProps = getInputProps(props.modelValue, props.statefulLayout, ['placeholder', 'accept'])
22
+ if (props.modelValue.layout.multiple) {
23
+ fieldProps.multiple = true
24
+ } else {
25
+ fieldProps.modelValue = props.modelValue.data ? [props.modelValue.data] : props.modelValue.data
26
+ fieldProps['onUpdate:modelValue'] = (/** @type string */value) => props.statefulLayout.input(props.modelValue, Array.isArray(value) ? value[0] : value)
27
+ }
28
+ return fieldProps
29
+ })
30
+ const fieldSlots = computed(() => getCompSlots(props.modelValue, props.statefulLayout))
31
+
32
+ // @ts-ignore
33
+ return () => h(VFileInput, fieldProps.value, fieldSlots.value)
34
+ }
35
+ })
36
+
37
+ </script>
38
+
39
+ <style>
40
+ .vjsf-node-text-field.vjsf-readonly.vjsf-summary input {
41
+ text-overflow: ellipsis;
42
+ }
43
+ </style>
@@ -3,17 +3,17 @@ import { watch, computed, ref } from 'vue'
3
3
  import { VList, VListItem, VListItemAction, VBtn, VMenu, VIcon, VSheet, VSpacer, VDivider, VRow, VListSubheader } from 'vuetify/components'
4
4
  import { isSection, clone } from '@json-layout/core'
5
5
  import Node from '../node.vue'
6
- import { moveArrayItem } from '../../utils/arrays.js'
6
+ import { moveArrayItem } from '../../utils/index.js'
7
7
  import useDnd from '../../composables/use-dnd.js'
8
8
 
9
9
  const props = defineProps({
10
10
  modelValue: {
11
- /** @type import('vue').PropType<import('../types.js').VjsfListNode> */
11
+ /** @type import('vue').PropType<import('../../types.js').VjsfListNode> */
12
12
  type: Object,
13
13
  required: true
14
14
  },
15
15
  statefulLayout: {
16
- /** @type import('vue').PropType<import('@json-layout/core').StatefulLayout> */
16
+ /** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
17
17
  type: Object,
18
18
  required: true
19
19
  }
@@ -71,7 +71,7 @@ const buttonDensity = computed(() => {
71
71
  <node
72
72
  v-for="grandChild of isSection(child) ? child.children : [child]"
73
73
  :key="grandChild.fullKey"
74
- :model-value="/** @type import('../types.js').VjsfNode */(grandChild)"
74
+ :model-value="/** @type import('../../types.js').VjsfNode */(grandChild)"
75
75
  :stateful-layout="statefulLayout"
76
76
  />
77
77
  </v-row>
@@ -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
  }
@@ -1,18 +1,17 @@
1
1
  <script>
2
2
  import { defineComponent, h, computed } from 'vue'
3
3
  import { VTextField } 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').VjsfNumberFieldNode> */
9
+ /** @type import('vue').PropType<import('../../types.js').VjsfNumberFieldNode> */
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
  }
@@ -6,12 +6,12 @@ import Node from '../node.vue'
6
6
 
7
7
  const props = defineProps({
8
8
  modelValue: {
9
- /** @type import('vue').PropType<import('../types.js').VjsfOneOfSelectNode> */
9
+ /** @type import('vue').PropType<import('../../types.js').VjsfOneOfSelectNode> */
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
  }
@@ -49,7 +49,7 @@ const onChange = (/** @type import('@json-layout/core').SkeletonTree */childTree
49
49
  <node
50
50
  v-for="grandChild of isSection(modelValue.children?.[0]) ? modelValue.children?.[0].children : modelValue.children"
51
51
  :key="grandChild.fullKey"
52
- :model-value="/** @type import('../types.js').VjsfNode */(grandChild)"
52
+ :model-value="/** @type import('../../types.js').VjsfNode */(grandChild)"
53
53
  :stateful-layout="statefulLayout"
54
54
  />
55
55
  </v-row>