@koumoul/vjsf 3.0.0-beta.43 → 3.0.0-beta.45
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 +12 -18
- package/src/components/fragments/selection-group.vue +11 -10
- package/src/components/fragments/text-field-menu.vue +10 -6
- package/src/components/nodes/autocomplete.vue +6 -6
- package/src/components/nodes/checkbox.vue +29 -27
- package/src/components/nodes/color-picker.vue +6 -4
- package/src/components/nodes/combobox.vue +14 -40
- package/src/components/nodes/date-picker.vue +14 -6
- package/src/components/nodes/date-time-picker.vue +14 -11
- package/src/components/nodes/expansion-panels.vue +6 -3
- package/src/components/nodes/file-input.vue +11 -10
- package/src/components/nodes/list.vue +21 -15
- package/src/components/nodes/number-combobox.vue +16 -40
- package/src/components/nodes/number-field.vue +13 -10
- package/src/components/nodes/one-of-select.vue +14 -10
- package/src/components/nodes/radio-group.vue +8 -5
- package/src/components/nodes/select.vue +8 -8
- package/src/components/nodes/slider.vue +30 -30
- package/src/components/nodes/switch.vue +29 -27
- package/src/components/nodes/text-field.vue +6 -6
- package/src/components/nodes/textarea.vue +16 -11
- package/src/components/nodes/time-picker.vue +9 -6
- package/src/composables/use-dnd.js +1 -1
- package/src/composables/use-get-items.js +12 -7
- package/src/composables/use-node.js +136 -0
- package/src/composables/use-select-node.js +67 -0
- package/src/composables/use-vjsf.js +3 -2
- package/types/components/fragments/child-subtitle.vue.d.ts +1 -1
- package/types/components/fragments/help-message.vue.d.ts +1 -1
- package/types/components/fragments/node-slot.vue.d.ts +4 -4
- package/types/components/fragments/section-header.vue.d.ts +1 -1
- package/types/components/fragments/select-item-icon.vue.d.ts +4 -4
- package/types/components/fragments/select-item.vue.d.ts +3 -3
- package/types/components/fragments/select-selection.vue.d.ts +1 -1
- package/types/components/fragments/selection-group.vue.d.ts +4 -4
- package/types/components/fragments/text-field-menu.vue.d.ts +1 -1
- package/types/components/fragments/text-field-menu.vue.d.ts.map +1 -1
- package/types/components/node.vue.d.ts +1 -1
- package/types/components/nodes/autocomplete.vue.d.ts +4 -4
- package/types/components/nodes/autocomplete.vue.d.ts.map +1 -1
- package/types/components/nodes/card.vue.d.ts +1 -1
- package/types/components/nodes/checkbox-group.vue.d.ts +4 -4
- package/types/components/nodes/checkbox.vue.d.ts +25 -8
- package/types/components/nodes/checkbox.vue.d.ts.map +1 -1
- package/types/components/nodes/color-picker.vue.d.ts +1 -1
- package/types/components/nodes/combobox.vue.d.ts +4 -4
- package/types/components/nodes/combobox.vue.d.ts.map +1 -1
- package/types/components/nodes/date-picker.vue.d.ts +1 -1
- package/types/components/nodes/date-time-picker.vue.d.ts +1 -1
- package/types/components/nodes/expansion-panels.vue.d.ts +1 -1
- package/types/components/nodes/file-input.vue.d.ts +4 -4
- package/types/components/nodes/list.vue.d.ts +1 -1
- package/types/components/nodes/number-combobox.vue.d.ts +4 -4
- package/types/components/nodes/number-combobox.vue.d.ts.map +1 -1
- package/types/components/nodes/number-field.vue.d.ts +4 -4
- package/types/components/nodes/one-of-select.vue.d.ts +1 -1
- package/types/components/nodes/radio-group.vue.d.ts +4 -4
- package/types/components/nodes/section.vue.d.ts +1 -1
- package/types/components/nodes/select.vue.d.ts +4 -4
- package/types/components/nodes/select.vue.d.ts.map +1 -1
- package/types/components/nodes/slider.vue.d.ts +25 -8
- package/types/components/nodes/slider.vue.d.ts.map +1 -1
- package/types/components/nodes/stepper.vue.d.ts +1 -1
- package/types/components/nodes/switch-group.vue.d.ts +4 -4
- package/types/components/nodes/switch.vue.d.ts +25 -8
- package/types/components/nodes/switch.vue.d.ts.map +1 -1
- package/types/components/nodes/tabs.vue.d.ts +1 -1
- package/types/components/nodes/text-field.vue.d.ts +4 -4
- package/types/components/nodes/textarea.vue.d.ts +4 -4
- package/types/components/nodes/time-picker.vue.d.ts +1 -1
- package/types/components/nodes/vertical-tabs.vue.d.ts +1 -1
- package/types/components/tree.vue.d.ts +1 -1
- package/types/components/vjsf.vue.d.ts +1 -1
- package/types/composables/use-dnd.d.ts +3 -3
- package/types/composables/use-field-props.d.ts +30 -0
- package/types/composables/use-field-props.d.ts.map +1 -0
- package/types/composables/use-field.d.ts +31 -0
- package/types/composables/use-field.d.ts.map +1 -0
- package/types/composables/use-get-items.d.ts +7 -8
- package/types/composables/use-get-items.d.ts.map +1 -1
- package/types/composables/use-node.d.ts +32 -0
- package/types/composables/use-node.d.ts.map +1 -0
- package/types/composables/use-select-field.d.ts +21 -0
- package/types/composables/use-select-field.d.ts.map +1 -0
- package/types/composables/use-select-node.d.ts +27 -0
- package/types/composables/use-select-node.d.ts.map +1 -0
- package/types/composables/use-select-props.d.ts +21 -0
- package/types/composables/use-select-props.d.ts.map +1 -0
- package/types/composables/use-select.d.ts +21 -0
- package/types/composables/use-select.d.ts.map +1 -0
- package/types/composables/use-vjsf.d.ts +2 -2
- package/types/composables/use-vjsf.d.ts.map +1 -1
- package/types/utils/index.d.ts +0 -2
- package/src/utils/index.js +0 -4
- package/src/utils/props.js +0 -136
- package/src/utils/slots.js +0 -46
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koumoul/vjsf",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.45",
|
|
4
4
|
"description": "Generate forms for the vuetify UI library (vuejs) based on annotated JSON schemas.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "vitest",
|
|
@@ -29,28 +29,22 @@
|
|
|
29
29
|
"default": "./src/types.js"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
|
-
"./components
|
|
32
|
+
"./components/vjsf.vue": {
|
|
33
33
|
"import": {
|
|
34
|
-
"types": "./types/components
|
|
35
|
-
"default": "./src/components
|
|
34
|
+
"types": "./types/components/vjsf.d.ts",
|
|
35
|
+
"default": "./src/components/vjs.vue"
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
|
-
"./
|
|
38
|
+
"./utils/build.js": {
|
|
39
39
|
"import": {
|
|
40
|
-
"types": "./types/
|
|
41
|
-
"default": "./src/
|
|
40
|
+
"types": "./types/utils/build.d.ts",
|
|
41
|
+
"default": "./src/utils/build.js"
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
-
"./
|
|
44
|
+
"./composables/use-node": {
|
|
45
45
|
"import": {
|
|
46
|
-
"types": "./types/
|
|
47
|
-
"default": "./src/
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
"./utils/*": {
|
|
51
|
-
"import": {
|
|
52
|
-
"types": "./types/utils/*.d.ts",
|
|
53
|
-
"default": "./src/utils/*"
|
|
46
|
+
"types": "./types/composables/use-node.d.ts",
|
|
47
|
+
"default": "./src/composables/use-node.js"
|
|
54
48
|
}
|
|
55
49
|
},
|
|
56
50
|
"./styles/*": {
|
|
@@ -76,7 +70,7 @@
|
|
|
76
70
|
"vuetify": "^3.6.13"
|
|
77
71
|
},
|
|
78
72
|
"dependencies": {
|
|
79
|
-
"@json-layout/core": "0.
|
|
73
|
+
"@json-layout/core": "0.32.1",
|
|
80
74
|
"@vueuse/core": "^10.5.0",
|
|
81
75
|
"debug": "^4.3.4",
|
|
82
76
|
"ejs": "^3.1.9"
|
|
@@ -85,7 +79,7 @@
|
|
|
85
79
|
"@types/debug": "^4.1.8",
|
|
86
80
|
"@types/ejs": "^3.1.2",
|
|
87
81
|
"vitest": "^1.1.1",
|
|
88
|
-
"vue": "^3.
|
|
82
|
+
"vue": "^3.5.6",
|
|
89
83
|
"vue-tsc": "^1.8.27"
|
|
90
84
|
}
|
|
91
85
|
}
|
|
@@ -4,8 +4,8 @@ import { VInput } from 'vuetify/components/VInput'
|
|
|
4
4
|
import { VLabel } from 'vuetify/components/VLabel'
|
|
5
5
|
import { VCheckbox } from 'vuetify/components/VCheckbox'
|
|
6
6
|
import { VSwitch } from 'vuetify/components/VSwitch'
|
|
7
|
-
import { defineComponent, h, computed } from 'vue'
|
|
8
|
-
import
|
|
7
|
+
import { defineComponent, h, computed, toRef } from 'vue'
|
|
8
|
+
import useField from '../../composables/use-node.js'
|
|
9
9
|
import useGetItems from '../../composables/use-get-items.js'
|
|
10
10
|
|
|
11
11
|
export default defineComponent({
|
|
@@ -26,17 +26,19 @@ export default defineComponent({
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
setup (props) {
|
|
29
|
-
const
|
|
29
|
+
const nodeRef = toRef(props, 'modelValue')
|
|
30
|
+
const getItems = useGetItems(nodeRef, props.statefulLayout)
|
|
31
|
+
const { inputProps, compSlots, localData, layout } = useField(nodeRef, props.statefulLayout, { bindData: false })
|
|
30
32
|
|
|
31
33
|
const fieldProps = computed(() => {
|
|
32
|
-
const fieldProps =
|
|
34
|
+
const fieldProps = { ...inputProps.value }
|
|
33
35
|
fieldProps.class.push('v-radio-group') // reuse some styles from radio-group
|
|
34
36
|
fieldProps.class.push('vjsf-selection-group')
|
|
35
37
|
return fieldProps
|
|
36
38
|
})
|
|
37
39
|
|
|
38
40
|
const fieldSlots = computed(() => {
|
|
39
|
-
const slots =
|
|
41
|
+
const slots = { ...compSlots.value }
|
|
40
42
|
|
|
41
43
|
if (!slots.default) {
|
|
42
44
|
slots.default = () => {
|
|
@@ -49,10 +51,10 @@ export default defineComponent({
|
|
|
49
51
|
const checkboxes = []
|
|
50
52
|
for (const item of getItems.items.value) {
|
|
51
53
|
let modelValue = false
|
|
52
|
-
if (
|
|
53
|
-
modelValue =
|
|
54
|
+
if (layout.value.multiple) {
|
|
55
|
+
modelValue = localData.value?.includes(item.value)
|
|
54
56
|
} else {
|
|
55
|
-
modelValue =
|
|
57
|
+
modelValue = localData.value === item.value
|
|
56
58
|
}
|
|
57
59
|
checkboxes.push(h(props.type === 'switch' ? VSwitch : VCheckbox, {
|
|
58
60
|
label: item.title,
|
|
@@ -61,7 +63,7 @@ export default defineComponent({
|
|
|
61
63
|
modelValue,
|
|
62
64
|
onClick: () => {
|
|
63
65
|
let newValue
|
|
64
|
-
if (
|
|
66
|
+
if (layout.value.multiple) {
|
|
65
67
|
newValue = props.modelValue.data ? [...props.modelValue.data] : []
|
|
66
68
|
if (newValue.includes(item.value)) {
|
|
67
69
|
newValue = newValue.filter((/** @type {any} */v) => v !== item.value)
|
|
@@ -88,7 +90,6 @@ export default defineComponent({
|
|
|
88
90
|
return slots
|
|
89
91
|
})
|
|
90
92
|
|
|
91
|
-
// @ts-ignore
|
|
92
93
|
return () => {
|
|
93
94
|
return h(VInput, fieldProps.value, fieldSlots.value)
|
|
94
95
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { VMenu } from 'vuetify/components/VMenu'
|
|
3
3
|
import { VTextField } from 'vuetify/components/VTextField'
|
|
4
|
-
import { computed, ref } from 'vue'
|
|
5
|
-
import
|
|
4
|
+
import { computed, ref, toRef } from 'vue'
|
|
5
|
+
import useField from '../../composables/use-node.js'
|
|
6
6
|
|
|
7
7
|
const props = defineProps({
|
|
8
8
|
modelValue: {
|
|
@@ -22,10 +22,14 @@ const props = defineProps({
|
|
|
22
22
|
}
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
+
const { inputProps, skeleton, compProps, data } = useField(
|
|
26
|
+
toRef(props, 'modelValue'), props.statefulLayout, { isMainComp: false, bindData: false }
|
|
27
|
+
)
|
|
28
|
+
|
|
25
29
|
const fieldProps = computed(() => {
|
|
26
|
-
const fieldProps =
|
|
30
|
+
const fieldProps = { ...inputProps.value }
|
|
27
31
|
fieldProps.readonly = true
|
|
28
|
-
fieldProps.clearable = fieldProps.clearable ?? !
|
|
32
|
+
fieldProps.clearable = fieldProps.clearable ?? !skeleton.value.required
|
|
29
33
|
fieldProps['onClick:clear'] = () => {
|
|
30
34
|
props.statefulLayout.input(props.modelValue, null)
|
|
31
35
|
}
|
|
@@ -33,7 +37,7 @@ const fieldProps = computed(() => {
|
|
|
33
37
|
})
|
|
34
38
|
|
|
35
39
|
const menuProps = computed(() => {
|
|
36
|
-
const menuProps =
|
|
40
|
+
const menuProps = { ...compProps.value }
|
|
37
41
|
menuProps.closeOnContentClick = false
|
|
38
42
|
menuProps.disabled = true
|
|
39
43
|
return menuProps
|
|
@@ -48,7 +52,7 @@ const menuOpened = defineModel('menuOpened', { type: Boolean, default: false })
|
|
|
48
52
|
<v-text-field
|
|
49
53
|
ref="textField"
|
|
50
54
|
v-bind="fieldProps"
|
|
51
|
-
:model-value="formattedValue ??
|
|
55
|
+
:model-value="formattedValue ?? data"
|
|
52
56
|
@click:control="e => {menuOpened = !menuOpened; e.stopPropagation()}"
|
|
53
57
|
>
|
|
54
58
|
<template #prepend-inner>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { VAutocomplete } from 'vuetify/components/VAutocomplete'
|
|
3
3
|
import { useDefaults } from 'vuetify'
|
|
4
|
-
import { defineComponent, computed, h } from 'vue'
|
|
5
|
-
import
|
|
6
|
-
import useGetItems from '../../composables/use-get-items.js'
|
|
4
|
+
import { defineComponent, computed, h, toRef } from 'vue'
|
|
5
|
+
import useSelectNode from '../../composables/use-select-node.js'
|
|
7
6
|
|
|
8
7
|
export default defineComponent({
|
|
9
8
|
props: {
|
|
@@ -21,21 +20,22 @@ export default defineComponent({
|
|
|
21
20
|
setup (props) {
|
|
22
21
|
useDefaults({}, 'VjsfAutocomplete')
|
|
23
22
|
|
|
24
|
-
const getItems =
|
|
23
|
+
const { getItems, selectProps, selectSlots, localData } = useSelectNode(toRef(props, 'modelValue'), props.statefulLayout)
|
|
25
24
|
|
|
26
25
|
const fieldProps = computed(() => {
|
|
27
|
-
const fieldProps =
|
|
26
|
+
const fieldProps = { ...selectProps.value }
|
|
28
27
|
fieldProps.noFilter = true
|
|
29
28
|
fieldProps['onUpdate:search'] = (/** @type string */searchValue) => {
|
|
30
29
|
getItems.search.value = searchValue
|
|
31
30
|
}
|
|
32
31
|
fieldProps.items = getItems.items.value
|
|
33
32
|
fieldProps.loading = getItems.loading.value
|
|
33
|
+
fieldProps.modelValue = localData.value
|
|
34
34
|
return fieldProps
|
|
35
35
|
})
|
|
36
36
|
|
|
37
37
|
// @ts-ignore
|
|
38
|
-
return () => h(VAutocomplete, fieldProps.value,
|
|
38
|
+
return () => h(VAutocomplete, fieldProps.value, selectSlots.value)
|
|
39
39
|
}
|
|
40
40
|
})
|
|
41
41
|
|
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>
|
|
2
|
+
import { defineComponent, h, computed, toRef } from 'vue'
|
|
2
3
|
import { VCheckbox } from 'vuetify/components/VCheckbox'
|
|
3
|
-
import
|
|
4
|
-
import { getInputProps } from '../../utils/index.js'
|
|
4
|
+
import useNode from '../../composables/use-node.js'
|
|
5
5
|
import { useDefaults } from 'vuetify'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
export default defineComponent({
|
|
8
|
+
props: {
|
|
9
|
+
modelValue: {
|
|
10
|
+
/** @type import('vue').PropType<import('../../types.js').VjsfCheckboxNode> */
|
|
11
|
+
type: Object,
|
|
12
|
+
required: true
|
|
13
|
+
},
|
|
14
|
+
statefulLayout: {
|
|
15
|
+
/** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
|
|
16
|
+
type: Object,
|
|
17
|
+
required: true
|
|
18
|
+
}
|
|
14
19
|
},
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
setup (props) {
|
|
21
|
+
useDefaults({}, 'VjsfCheckbox')
|
|
22
|
+
|
|
23
|
+
const { inputProps, localData, compSlots } = useNode(toRef(props, 'modelValue'), props.statefulLayout)
|
|
24
|
+
|
|
25
|
+
const fullProps = computed(() => {
|
|
26
|
+
const fullProps = { ...inputProps.value }
|
|
27
|
+
// it is not very common to show an error below checkboxes and switches and without hide-details=auto they take a lot of space
|
|
28
|
+
if (!('hideDetails' in inputProps)) fullProps.hideDetails = 'auto'
|
|
29
|
+
fullProps.modelValue = localData.value
|
|
30
|
+
return fullProps
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
return () => h(VCheckbox, fullProps.value, compSlots.value)
|
|
19
34
|
}
|
|
20
35
|
})
|
|
21
36
|
|
|
22
|
-
const fieldProps = computed(() => {
|
|
23
|
-
const inputProps = getInputProps(props.modelValue, props.statefulLayout)
|
|
24
|
-
// it is not very common to show an error below checkboxes and switches and without hide-details=auto they take a lot of space
|
|
25
|
-
if (!('hideDetails' in inputProps)) inputProps.hideDetails = 'auto'
|
|
26
|
-
return inputProps
|
|
27
|
-
})
|
|
28
37
|
</script>
|
|
29
|
-
|
|
30
|
-
<template>
|
|
31
|
-
<v-checkbox
|
|
32
|
-
v-bind="fieldProps"
|
|
33
|
-
@update:model-value="value => statefulLayout.input(modelValue, value)"
|
|
34
|
-
/>
|
|
35
|
-
</template>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import TextFieldMenu from '../fragments/text-field-menu.vue'
|
|
3
3
|
import { VColorPicker } from 'vuetify/components/VColorPicker'
|
|
4
|
-
import { computed } from 'vue'
|
|
5
|
-
import
|
|
4
|
+
import { computed, toRef } from 'vue'
|
|
5
|
+
import useNode from '../../composables/use-node.js'
|
|
6
6
|
import { useDefaults } from 'vuetify'
|
|
7
7
|
|
|
8
8
|
useDefaults({}, 'VjsfColorPicker')
|
|
@@ -20,9 +20,11 @@ const props = defineProps({
|
|
|
20
20
|
}
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
+
const { compProps, localData } = useNode(toRef(props, 'modelValue'), props.statefulLayout)
|
|
24
|
+
|
|
23
25
|
const colorPickerProps = computed(() => {
|
|
24
|
-
const colorPickerProps =
|
|
25
|
-
colorPickerProps.modelValue =
|
|
26
|
+
const colorPickerProps = { ...compProps.value }
|
|
27
|
+
colorPickerProps.modelValue = localData.value
|
|
26
28
|
return colorPickerProps
|
|
27
29
|
})
|
|
28
30
|
</script>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { defineComponent, h, computed,
|
|
2
|
+
import { defineComponent, h, computed, toRef } from 'vue'
|
|
3
3
|
import { VCombobox } from 'vuetify/components/VCombobox'
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../../composables/use-node.js'
|
|
5
|
+
import useGetItems from '../../composables/use-get-items.js'
|
|
5
6
|
import { useDefaults } from 'vuetify'
|
|
6
7
|
|
|
7
8
|
export default defineComponent({
|
|
@@ -20,55 +21,28 @@ export default defineComponent({
|
|
|
20
21
|
setup (props) {
|
|
21
22
|
useDefaults({}, 'VjsfCombobox')
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
const loading = ref(false)
|
|
27
|
-
|
|
28
|
-
/** @type import('@json-layout/core').StateTree | null */
|
|
29
|
-
let lastStateTree = null
|
|
30
|
-
/** @type Record<string, any> | null */
|
|
31
|
-
let lastContext = null
|
|
32
|
-
|
|
33
|
-
const hasItems = computed(() => {
|
|
34
|
-
return !!(props.modelValue.layout.items || props.modelValue.layout.getItems)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const refresh = async () => {
|
|
38
|
-
if (props.modelValue.layout.items) return
|
|
39
|
-
if (props.statefulLayout.stateTree === lastStateTree && props.statefulLayout.options.context === lastContext) return
|
|
40
|
-
lastStateTree = props.statefulLayout.stateTree
|
|
41
|
-
lastContext = props.statefulLayout.options.context ?? null
|
|
42
|
-
if (hasItems.value) {
|
|
43
|
-
loading.value = true
|
|
44
|
-
items.value = await props.statefulLayout.getItems(props.modelValue)
|
|
45
|
-
loading.value = false
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (!props.modelValue.layout.items) {
|
|
50
|
-
refresh()
|
|
51
|
-
}
|
|
24
|
+
const nodeRef = toRef(props, 'modelValue')
|
|
25
|
+
const getItems = useGetItems(nodeRef, props.statefulLayout)
|
|
26
|
+
const { inputProps, compSlots, localData, layout, options } = useNode(nodeRef, props.statefulLayout)
|
|
52
27
|
|
|
53
28
|
const fieldProps = computed(() => {
|
|
54
|
-
const fieldProps =
|
|
55
|
-
fieldProps.loading = loading.value
|
|
29
|
+
const fieldProps = { ...inputProps.value }
|
|
56
30
|
fieldProps.returnObject = false
|
|
57
|
-
if (
|
|
58
|
-
if (
|
|
59
|
-
|
|
31
|
+
if (options.value.readOnly) fieldProps.menuProps = { modelValue: false }
|
|
32
|
+
if (getItems.hasItems.value) {
|
|
33
|
+
fieldProps.items = getItems.items.value
|
|
34
|
+
fieldProps.loading = getItems.loading.value
|
|
35
|
+
}
|
|
36
|
+
if (layout.value.multiple) {
|
|
60
37
|
fieldProps.multiple = true
|
|
61
38
|
fieldProps.chips = true
|
|
62
39
|
fieldProps.closableChips = true
|
|
63
40
|
}
|
|
64
|
-
fieldProps['onUpdate:menu'] = () => refresh()
|
|
65
41
|
return fieldProps
|
|
66
42
|
})
|
|
67
43
|
|
|
68
|
-
const fieldSlots = computed(() => getCompSlots(props.modelValue, props.statefulLayout))
|
|
69
|
-
|
|
70
44
|
// @ts-ignore
|
|
71
|
-
return () => h(VCombobox, fieldProps.value,
|
|
45
|
+
return () => h(VCombobox, { ...fieldProps.value, modelValue: localData.value }, compSlots.value)
|
|
72
46
|
}
|
|
73
47
|
})
|
|
74
48
|
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import TextFieldMenu from '../fragments/text-field-menu.vue'
|
|
3
3
|
import { VDatePicker } from 'vuetify/components/VDatePicker'
|
|
4
4
|
import { useDate, useDefaults } from 'vuetify'
|
|
5
|
-
import { computed, ref } from 'vue'
|
|
6
|
-
import {
|
|
5
|
+
import { computed, ref, toRef } from 'vue'
|
|
6
|
+
import { getDateTimeParts, getDateTimeWithOffset } from '../../utils/dates.js'
|
|
7
|
+
import useNode from '../../composables/use-node.js'
|
|
7
8
|
|
|
8
9
|
useDefaults({}, 'VjsfDatePicker')
|
|
9
10
|
|
|
@@ -24,10 +25,12 @@ const vDate = useDate()
|
|
|
24
25
|
|
|
25
26
|
const menuOpened = ref(false)
|
|
26
27
|
|
|
28
|
+
const { compProps, localData } = useNode(toRef(props, 'modelValue'), props.statefulLayout)
|
|
29
|
+
|
|
27
30
|
const datePickerProps = computed(() => {
|
|
28
|
-
const datePickerProps =
|
|
31
|
+
const datePickerProps = { ...compProps.value }
|
|
29
32
|
datePickerProps.hideActions = true
|
|
30
|
-
if (
|
|
33
|
+
if (localData.value) datePickerProps.modelValue = new Date(/** @type {string} */(localData.value))
|
|
31
34
|
datePickerProps['onUpdate:modelValue'] = (/** @type {Date} */value) => {
|
|
32
35
|
if (!value) return
|
|
33
36
|
if (props.modelValue.layout.format === 'date-time') {
|
|
@@ -39,14 +42,19 @@ const datePickerProps = computed(() => {
|
|
|
39
42
|
}
|
|
40
43
|
return datePickerProps
|
|
41
44
|
})
|
|
45
|
+
|
|
46
|
+
const formattedValue = computed(() => {
|
|
47
|
+
return localData.value ? vDate.format(/** @type {string} */(localData.value), 'fullDateWithWeekday') : null
|
|
48
|
+
})
|
|
49
|
+
|
|
42
50
|
</script>
|
|
43
51
|
|
|
44
52
|
<template>
|
|
45
53
|
<text-field-menu
|
|
46
54
|
v-model:menu-opened="menuOpened"
|
|
47
|
-
:model-value="modelValue"
|
|
55
|
+
:model-value="props.modelValue"
|
|
48
56
|
:stateful-layout="statefulLayout"
|
|
49
|
-
:formatted-value="
|
|
57
|
+
:formatted-value="formattedValue"
|
|
50
58
|
>
|
|
51
59
|
<v-date-picker v-bind="datePickerProps" />
|
|
52
60
|
</text-field-menu>
|
|
@@ -6,8 +6,9 @@ import { VTabs, VTab, VTabsWindow, VTabsWindowItem } from 'vuetify/components/VT
|
|
|
6
6
|
import { VIcon } from 'vuetify/components/VIcon'
|
|
7
7
|
import { VSheet } from 'vuetify/components/VSheet'
|
|
8
8
|
import { useDate, useDefaults } from 'vuetify'
|
|
9
|
-
import { computed, ref, watch } from 'vue'
|
|
10
|
-
import {
|
|
9
|
+
import { computed, ref, watch, toRef } from 'vue'
|
|
10
|
+
import { getDateTimeParts, getDateTimeWithOffset, getShortTime } from '../../utils/dates.js'
|
|
11
|
+
import useNode from '../../composables/use-node.js'
|
|
11
12
|
|
|
12
13
|
useDefaults({}, 'VjsfDatePicker')
|
|
13
14
|
|
|
@@ -30,17 +31,19 @@ const tab = ref('date')
|
|
|
30
31
|
const menuOpened = ref(false)
|
|
31
32
|
watch(menuOpened, () => { tab.value = 'date' })
|
|
32
33
|
|
|
34
|
+
const { compProps, localData } = useNode(toRef(props, 'modelValue'), props.statefulLayout)
|
|
35
|
+
|
|
33
36
|
const datePickerProps = computed(() => {
|
|
34
|
-
const datePickerProps =
|
|
37
|
+
const datePickerProps = { ...compProps.value }
|
|
35
38
|
datePickerProps.hideActions = true
|
|
36
|
-
if (
|
|
39
|
+
if (localData.value) datePickerProps.modelValue = new Date(localData.value)
|
|
37
40
|
datePickerProps['onUpdate:modelValue'] = (/** @type {Date} */value) => {
|
|
38
41
|
if (!value) return
|
|
39
42
|
|
|
40
|
-
if (
|
|
43
|
+
if (localData.value) {
|
|
41
44
|
// replace date part of current value
|
|
42
45
|
const datePart = value && getDateTimeParts(/** @type Date */(/** @type unknown */(value)))[0]
|
|
43
|
-
props.statefulLayout.input(props.modelValue, datePart +
|
|
46
|
+
props.statefulLayout.input(props.modelValue, datePart + localData.value.slice(10))
|
|
44
47
|
} else {
|
|
45
48
|
props.statefulLayout.input(props.modelValue, getDateTimeWithOffset(value))
|
|
46
49
|
}
|
|
@@ -50,13 +53,13 @@ const datePickerProps = computed(() => {
|
|
|
50
53
|
})
|
|
51
54
|
|
|
52
55
|
const timePickerProps = computed(() => {
|
|
53
|
-
const timePickerProps =
|
|
56
|
+
const timePickerProps = { ...compProps.value }
|
|
54
57
|
timePickerProps['ampm-in-title'] = true
|
|
55
|
-
if (
|
|
58
|
+
if (localData.value) timePickerProps.modelValue = getShortTime(localData.value.slice(11))
|
|
56
59
|
timePickerProps['onUpdate:modelValue'] = (/** @type {string} */value) => {
|
|
57
|
-
if (!
|
|
58
|
-
console.log('set time', value,
|
|
59
|
-
props.statefulLayout.input(props.modelValue,
|
|
60
|
+
if (!localData.value) return
|
|
61
|
+
console.log('set time', value, localData.value.slice(0, 10), localData.value.slice(15))
|
|
62
|
+
props.statefulLayout.input(props.modelValue, localData.value.slice(0, 11) + value + localData.value.slice(16))
|
|
60
63
|
}
|
|
61
64
|
return timePickerProps
|
|
62
65
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { toRef } from 'vue'
|
|
2
3
|
import { VExpansionPanels, VExpansionPanel, VExpansionPanelTitle, VExpansionPanelText } from 'vuetify/components/VExpansionPanel'
|
|
3
4
|
import { VContainer, VRow } from 'vuetify/components/VGrid'
|
|
4
5
|
import { VIcon } from 'vuetify/components/VIcon'
|
|
@@ -6,12 +7,12 @@ import { isSection } from '@json-layout/core'
|
|
|
6
7
|
import Node from '../node.vue'
|
|
7
8
|
import SectionHeader from '../fragments/section-header.vue'
|
|
8
9
|
import ChildSubtitle from '../fragments/child-subtitle.vue'
|
|
9
|
-
import
|
|
10
|
+
import useNode from '../../composables/use-node.js'
|
|
10
11
|
import { useDefaults } from 'vuetify'
|
|
11
12
|
|
|
12
13
|
useDefaults({}, 'VjsfExpansionPanels')
|
|
13
14
|
|
|
14
|
-
defineProps({
|
|
15
|
+
const props = defineProps({
|
|
15
16
|
modelValue: {
|
|
16
17
|
/** @type import('vue').PropType<import('../../types.js').VjsfExpansionPanelsNode> */
|
|
17
18
|
type: Object,
|
|
@@ -24,11 +25,13 @@ defineProps({
|
|
|
24
25
|
}
|
|
25
26
|
})
|
|
26
27
|
|
|
28
|
+
const { compProps } = useNode(toRef(props, 'modelValue'), props.statefulLayout)
|
|
29
|
+
|
|
27
30
|
</script>
|
|
28
31
|
|
|
29
32
|
<template>
|
|
30
33
|
<section-header :node="modelValue" />
|
|
31
|
-
<v-expansion-panels v-bind="
|
|
34
|
+
<v-expansion-panels v-bind="compProps">
|
|
32
35
|
<v-expansion-panel
|
|
33
36
|
v-for="(child, i) of modelValue.children"
|
|
34
37
|
:key="child.key"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { defineComponent, h, computed } from 'vue'
|
|
2
|
+
import { defineComponent, h, computed, toRef } from 'vue'
|
|
3
3
|
import { VFileInput } from 'vuetify/components/VFileInput'
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../../composables/use-node.js'
|
|
5
5
|
import { useDefaults } from 'vuetify'
|
|
6
6
|
|
|
7
7
|
export default defineComponent({
|
|
@@ -20,20 +20,21 @@ export default defineComponent({
|
|
|
20
20
|
setup (props) {
|
|
21
21
|
useDefaults({}, 'VjsfFileInput')
|
|
22
22
|
|
|
23
|
+
const { inputProps, localData, compSlots } = useNode(
|
|
24
|
+
toRef(props, 'modelValue'), props.statefulLayout, { layoutPropsMap: ['placeholder', 'accept', 'multiple'] }
|
|
25
|
+
)
|
|
26
|
+
|
|
23
27
|
const fieldProps = computed(() => {
|
|
24
|
-
const fieldProps =
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
fieldProps.modelValue = props.modelValue.data ? [props.modelValue.data] : props.modelValue.data
|
|
29
|
-
fieldProps['onUpdate:modelValue'] = (/** @type string */value) => props.statefulLayout.input(props.modelValue, Array.isArray(value) ? value[0] : value)
|
|
28
|
+
const fieldProps = { ...inputProps.value }
|
|
29
|
+
if (fieldProps.multiple) console.error('File input doesn\'t support multiple inputs yet')
|
|
30
|
+
fieldProps['onUpdate:modelValue'] = (/** @type {File} */value) => {
|
|
31
|
+
props.statefulLayout.input(props.modelValue, value)
|
|
30
32
|
}
|
|
31
33
|
return fieldProps
|
|
32
34
|
})
|
|
33
|
-
const fieldSlots = computed(() => getCompSlots(props.modelValue, props.statefulLayout))
|
|
34
35
|
|
|
35
36
|
// @ts-ignore
|
|
36
|
-
return () => h(VFileInput, fieldProps.value,
|
|
37
|
+
return () => h(VFileInput, { ...fieldProps.value, modelValue: localData.value }, compSlots.value)
|
|
37
38
|
}
|
|
38
39
|
})
|
|
39
40
|
|