@koumoul/vjsf 3.0.0-beta.44 → 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
|
@@ -12,12 +12,13 @@ import { VMenu } from 'vuetify/components/VMenu'
|
|
|
12
12
|
import { VForm } from 'vuetify/components/VForm'
|
|
13
13
|
import { isSection, clone, getRegexp } from '@json-layout/core'
|
|
14
14
|
import Node from '../node.vue'
|
|
15
|
-
import { moveDataItem } from '../../utils/
|
|
15
|
+
import { moveDataItem } from '../../utils/arrays.js'
|
|
16
16
|
import useDnd from '../../composables/use-dnd.js'
|
|
17
17
|
import useCompDefaults from '../../composables/use-comp-defaults.js'
|
|
18
18
|
|
|
19
19
|
useDefaults({}, 'VjsfList')
|
|
20
20
|
const vSheetProps = useCompDefaults('VjsfList-VSheet', { border: true })
|
|
21
|
+
const theme = useTheme()
|
|
21
22
|
|
|
22
23
|
const props = defineProps({
|
|
23
24
|
modelValue: {
|
|
@@ -32,27 +33,32 @@ const props = defineProps({
|
|
|
32
33
|
}
|
|
33
34
|
})
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
// we access vjsfNode properties through computeds so that the parts without mutations do not trigger reactivity
|
|
37
|
+
// this is to leverage the immutability provided by immer in json-layout
|
|
38
|
+
const options = computed(() => props.modelValue.options)
|
|
39
|
+
const layout = computed(() => props.modelValue.layout)
|
|
40
|
+
const children = computed(() => props.modelValue.children)
|
|
36
41
|
|
|
37
42
|
/* use composable for drag and drop */
|
|
38
43
|
const { activeDnd, sortableArray, draggable, hovered, dragging, itemBind, handleBind } = useDnd(props.modelValue.children, () => {
|
|
39
|
-
const newData =
|
|
44
|
+
const newData = layout.value.indexed
|
|
40
45
|
? sortableArray.value.reduce((a, child) => { a[child.key] = child.data; return a }, /** @type {Record<string, any>} */({}))
|
|
41
46
|
: sortableArray.value.map((child) => child.data)
|
|
42
|
-
console.log(newData)
|
|
43
47
|
props.statefulLayout.input(props.modelValue, newData)
|
|
44
48
|
})
|
|
45
|
-
watch(
|
|
49
|
+
watch(children, (array) => { sortableArray.value = array })
|
|
46
50
|
|
|
47
51
|
/* manage hovered and edited items */
|
|
52
|
+
// const editedItem = computed(() => activatedItems.value[fullKey.value])
|
|
48
53
|
const editedItem = computed(() => {
|
|
49
54
|
return props.statefulLayout.activatedItems[props.modelValue.fullKey]
|
|
50
55
|
})
|
|
56
|
+
|
|
51
57
|
const menuOpened = ref(-1)
|
|
52
58
|
const activeItem = computed(() => {
|
|
53
59
|
if (
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
layout.value.listActions.includes('edit') &&
|
|
61
|
+
layout.value.listEditMode === 'inline-single' &&
|
|
56
62
|
editedItem.value !== undefined
|
|
57
63
|
) {
|
|
58
64
|
return editedItem.value
|
|
@@ -63,14 +69,14 @@ const activeItem = computed(() => {
|
|
|
63
69
|
})
|
|
64
70
|
|
|
65
71
|
const buttonDensity = computed(() => {
|
|
66
|
-
if (
|
|
67
|
-
return
|
|
72
|
+
if (options.value.density === 'default') return 'comfortable'
|
|
73
|
+
return options.value.density
|
|
68
74
|
})
|
|
69
75
|
|
|
70
76
|
const pushEmptyItem = () => {
|
|
71
77
|
const newData = (props.modelValue.data ?? []).concat([undefined])
|
|
72
78
|
props.statefulLayout.input(props.modelValue, newData)
|
|
73
|
-
if (
|
|
79
|
+
if (layout.value.listEditMode === 'inline-single') {
|
|
74
80
|
props.statefulLayout.activateItem(props.modelValue, newData.length - 1)
|
|
75
81
|
}
|
|
76
82
|
}
|
|
@@ -84,7 +90,7 @@ const pushEmptyIndexedItem = () => {
|
|
|
84
90
|
if (!newKeyForm.value.isValid) return
|
|
85
91
|
const newData = { ...(props.modelValue.data ?? {}), [newKey.value]: null }
|
|
86
92
|
props.statefulLayout.input(props.modelValue, newData)
|
|
87
|
-
if (
|
|
93
|
+
if (layout.value.listEditMode === 'inline-single') {
|
|
88
94
|
props.statefulLayout.activateItem(props.modelValue, Object.keys(newData).length - 1)
|
|
89
95
|
}
|
|
90
96
|
newKey.value = ''
|
|
@@ -95,7 +101,7 @@ const pushEmptyIndexedItem = () => {
|
|
|
95
101
|
* @param {number} childIndex
|
|
96
102
|
*/
|
|
97
103
|
const deleteItem = (childIndex) => {
|
|
98
|
-
if (
|
|
104
|
+
if (layout.value.indexed) {
|
|
99
105
|
const oldData = /** @type {Record<string, any>} */(props.modelValue.data)
|
|
100
106
|
const keys = Object.keys(props.modelValue.data)
|
|
101
107
|
/** @type {Record<string, any>} */
|
|
@@ -119,7 +125,7 @@ const deleteItem = (childIndex) => {
|
|
|
119
125
|
const duplicateItem = (child, childIndex) => {
|
|
120
126
|
const newData = [...props.modelValue.data.slice(0, childIndex), clone(child.data), ...props.modelValue.data.slice(childIndex)]
|
|
121
127
|
props.statefulLayout.input(props.modelValue, newData)
|
|
122
|
-
if (
|
|
128
|
+
if (layout.value.listEditMode === 'inline-single') {
|
|
123
129
|
props.statefulLayout.activateItem(props.modelValue, childIndex + 1)
|
|
124
130
|
}
|
|
125
131
|
menuOpened.value = -1
|
|
@@ -128,7 +134,7 @@ const duplicateItem = (child, childIndex) => {
|
|
|
128
134
|
const itemBorderColor = computed(() => (/** @type {import('@json-layout/core').StateNode} */child, /** @type {number} */childIndex) => {
|
|
129
135
|
if (editedItem.value === childIndex) return theme.current.value.colors.primary
|
|
130
136
|
if (child.validated && (child.error || child.childError)) return theme.current.value.colors.error
|
|
131
|
-
if (
|
|
137
|
+
if (options.value.readOnly) return 'transparent'
|
|
132
138
|
if (activeItem.value === childIndex) return theme.current.value.colors.primary
|
|
133
139
|
return 'transparent'
|
|
134
140
|
})
|
|
@@ -143,7 +149,7 @@ const itemBorderColor = computed(() => (/** @type {import('@json-layout/core').S
|
|
|
143
149
|
</v-list-subheader>
|
|
144
150
|
<template
|
|
145
151
|
v-for="(child, childIndex) of sortableArray"
|
|
146
|
-
:key="
|
|
152
|
+
:key="children.findIndex(c => c === child)"
|
|
147
153
|
>
|
|
148
154
|
<v-list-item
|
|
149
155
|
v-bind="itemBind(childIndex)"
|
|
@@ -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({
|
|
@@ -18,57 +19,32 @@ export default defineComponent({
|
|
|
18
19
|
}
|
|
19
20
|
},
|
|
20
21
|
setup (props) {
|
|
21
|
-
useDefaults({}, '
|
|
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, { bindData: false, layoutPropsMap: ['step', 'min', 'max'] })
|
|
52
27
|
|
|
53
28
|
const fieldProps = computed(() => {
|
|
54
|
-
const fieldProps =
|
|
29
|
+
const fieldProps = { ...inputProps.value }
|
|
55
30
|
fieldProps.type = 'number'
|
|
56
|
-
fieldProps.
|
|
57
|
-
if (
|
|
58
|
-
if (
|
|
59
|
-
|
|
31
|
+
fieldProps.returnObject = false
|
|
32
|
+
if (options.value.readOnly) fieldProps.menuProps = { modelValue: false }
|
|
33
|
+
if (getItems.hasItems.value) {
|
|
34
|
+
fieldProps.items = getItems.items.value
|
|
35
|
+
fieldProps.loading = getItems.loading.value
|
|
36
|
+
}
|
|
37
|
+
if (layout.value.multiple) {
|
|
60
38
|
fieldProps.multiple = true
|
|
61
39
|
fieldProps.chips = true
|
|
62
40
|
fieldProps.closableChips = true
|
|
63
41
|
}
|
|
64
|
-
fieldProps['onUpdate:menu'] = () => refresh()
|
|
65
42
|
fieldProps['onUpdate:modelValue'] = (/** @type string[] */value) => props.statefulLayout.input(props.modelValue, value && value.map(Number))
|
|
66
43
|
return fieldProps
|
|
67
44
|
})
|
|
68
|
-
const fieldSlots = computed(() => getCompSlots(props.modelValue, props.statefulLayout))
|
|
69
45
|
|
|
70
46
|
// @ts-ignore
|
|
71
|
-
return () => h(VCombobox, fieldProps.value,
|
|
47
|
+
return () => h(VCombobox, { ...fieldProps.value, modelValue: localData.value }, compSlots.value)
|
|
72
48
|
}
|
|
73
49
|
})
|
|
74
50
|
|
|
@@ -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 { VTextField } from 'vuetify/components/VTextField'
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../../composables/use-node.js'
|
|
5
5
|
import { useDefaults } from 'vuetify'
|
|
6
6
|
|
|
7
7
|
export default defineComponent({
|
|
@@ -20,16 +20,19 @@ export default defineComponent({
|
|
|
20
20
|
setup (props) {
|
|
21
21
|
useDefaults({}, 'VjsfNumberField')
|
|
22
22
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
const { inputProps, localData, compSlots } = useNode(
|
|
24
|
+
toRef(props, 'modelValue'), props.statefulLayout, { layoutPropsMap: ['step', 'min', 'max', 'placeholder'], bindData: false }
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
const fullProps = computed(() => {
|
|
28
|
+
const fullProps = { ...inputProps.value }
|
|
29
|
+
fullProps.type = 'number'
|
|
30
|
+
fullProps['onUpdate:modelValue'] = (/** @type string */value) => props.statefulLayout.input(props.modelValue, value && Number(value))
|
|
31
|
+
fullProps.modelValue = localData.value
|
|
32
|
+
return fullProps
|
|
28
33
|
})
|
|
29
|
-
const fieldSlots = computed(() => getCompSlots(props.modelValue, props.statefulLayout))
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
return () => h(VTextField, fieldProps.value, fieldSlots.value)
|
|
35
|
+
return () => h(VTextField, fullProps.value, compSlots.value)
|
|
33
36
|
}
|
|
34
37
|
})
|
|
35
38
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { VRow, VCol } from 'vuetify/components/VGrid'
|
|
3
3
|
import { VSelect } from 'vuetify/components/VSelect'
|
|
4
|
-
import { ref, watch, computed,
|
|
4
|
+
import { ref, watch, computed, toRef } from 'vue'
|
|
5
5
|
import { isSection } from '@json-layout/core'
|
|
6
6
|
import { isCompObject } from '@json-layout/vocabulary'
|
|
7
|
-
import
|
|
7
|
+
import useNode from '../../composables/use-node.js'
|
|
8
8
|
import Node from '../node.vue'
|
|
9
9
|
import { useDefaults } from 'vuetify'
|
|
10
10
|
|
|
@@ -23,12 +23,16 @@ const props = defineProps({
|
|
|
23
23
|
}
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
+
const { inputProps, localData, skeleton, children } = useNode(
|
|
27
|
+
toRef(props, 'modelValue'), props.statefulLayout, { bindData: false }
|
|
28
|
+
)
|
|
29
|
+
|
|
26
30
|
/** @type import('vue').Ref<string | undefined> */
|
|
27
31
|
const activeChildTree = ref(undefined)
|
|
28
|
-
watch(() =>
|
|
32
|
+
watch(() => children.value?.[0]?.key, () => {
|
|
29
33
|
if (props.modelValue.children?.length === 1) {
|
|
30
34
|
if (typeof props.modelValue.children[0].key === 'number') {
|
|
31
|
-
activeChildTree.value =
|
|
35
|
+
activeChildTree.value = skeleton.value.childrenTrees?.[props.modelValue.children[0].key]
|
|
32
36
|
}
|
|
33
37
|
} else {
|
|
34
38
|
activeChildTree.value = undefined
|
|
@@ -36,19 +40,18 @@ watch(() => props.modelValue, () => {
|
|
|
36
40
|
}, { immediate: true })
|
|
37
41
|
|
|
38
42
|
const onChange = (/** @type {string} */childTree) => {
|
|
39
|
-
if (!
|
|
40
|
-
props.statefulLayout.activateItem(props.modelValue,
|
|
43
|
+
if (!skeleton.value.childrenTrees) return
|
|
44
|
+
props.statefulLayout.activateItem(props.modelValue, skeleton.value.childrenTrees.indexOf(childTree))
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
const fieldProps = computed(() => {
|
|
44
|
-
const fieldProps =
|
|
45
|
-
fieldProps.modelValue = activeChildTree.value
|
|
48
|
+
const fieldProps = { ...inputProps.value }
|
|
46
49
|
fieldProps['onUpdate:modelValue'] = onChange
|
|
47
50
|
const items = []
|
|
48
|
-
for (const childTreePointer of
|
|
51
|
+
for (const childTreePointer of skeleton.value.childrenTrees || []) {
|
|
49
52
|
const childTree = props.statefulLayout.compiledLayout.skeletonTrees[childTreePointer]
|
|
50
53
|
const childLayout = props.statefulLayout.compiledLayout.normalizedLayouts[childTree.root]
|
|
51
|
-
if (!isCompObject(childLayout) || !childLayout.if || !!props.statefulLayout.evalNodeExpression(props.modelValue, childLayout.if,
|
|
54
|
+
if (!isCompObject(childLayout) || !childLayout.if || !!props.statefulLayout.evalNodeExpression(props.modelValue, childLayout.if, localData.value)) {
|
|
52
55
|
items.push(childTree)
|
|
53
56
|
}
|
|
54
57
|
}
|
|
@@ -64,6 +67,7 @@ const fieldProps = computed(() => {
|
|
|
64
67
|
<v-col v-if="modelValue.skeleton.childrenTrees">
|
|
65
68
|
<v-select
|
|
66
69
|
v-bind="fieldProps"
|
|
70
|
+
:model-value="activeChildTree"
|
|
67
71
|
/>
|
|
68
72
|
</v-col>
|
|
69
73
|
<template v-if="modelValue.children?.[0]">
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { VRadio } from 'vuetify/components/VRadio'
|
|
3
3
|
import { VRadioGroup } from 'vuetify/components/VRadioGroup'
|
|
4
4
|
import { VSkeletonLoader } from 'vuetify/components/VSkeletonLoader'
|
|
5
|
-
import { defineComponent, h, computed } from 'vue'
|
|
6
|
-
import
|
|
5
|
+
import { defineComponent, h, computed, toRef } from 'vue'
|
|
6
|
+
import useNode from '../../composables/use-node.js'
|
|
7
7
|
import useGetItems from '../../composables/use-get-items.js'
|
|
8
8
|
import { useDefaults } from 'vuetify'
|
|
9
9
|
|
|
@@ -23,15 +23,18 @@ export default defineComponent({
|
|
|
23
23
|
setup (props) {
|
|
24
24
|
useDefaults({}, 'VjsfRadioGroup')
|
|
25
25
|
|
|
26
|
-
const
|
|
26
|
+
const nodeRef = toRef(props, 'modelValue')
|
|
27
|
+
const getItems = useGetItems(nodeRef, props.statefulLayout)
|
|
28
|
+
const { inputProps, compSlots, localData } = useNode(nodeRef, props.statefulLayout)
|
|
27
29
|
|
|
28
30
|
const fieldProps = computed(() => {
|
|
29
|
-
const fieldProps =
|
|
31
|
+
const fieldProps = { ...inputProps.value }
|
|
32
|
+
fieldProps.modelValue = localData.value
|
|
30
33
|
return fieldProps
|
|
31
34
|
})
|
|
32
35
|
|
|
33
36
|
const fieldSlots = computed(() => {
|
|
34
|
-
const slots =
|
|
37
|
+
const slots = { ...compSlots.value }
|
|
35
38
|
/** @type {import('vue').VNode[]} */
|
|
36
39
|
const children = []
|
|
37
40
|
if (getItems.loading.value) {
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { VSelect } from 'vuetify/components/VSelect'
|
|
3
|
-
import { defineComponent, h, computed } from 'vue'
|
|
4
|
-
import
|
|
5
|
-
import useGetItems from '../../composables/use-get-items.js'
|
|
3
|
+
import { defineComponent, h, computed, toRef } from 'vue'
|
|
4
|
+
import useSelectNode from '../../composables/use-select-node.js'
|
|
6
5
|
|
|
7
6
|
import { useDefaults } from 'vuetify'
|
|
8
7
|
|
|
9
8
|
export default defineComponent({
|
|
10
9
|
props: {
|
|
11
10
|
modelValue: {
|
|
12
|
-
|
|
11
|
+
/** @type import('vue').PropType<import('../../types.js').VjsfSelectNode> */
|
|
13
12
|
type: Object,
|
|
14
13
|
required: true
|
|
15
14
|
},
|
|
16
15
|
statefulLayout: {
|
|
17
|
-
|
|
16
|
+
/** @type import('vue').PropType<import('../../types.js').VjsfStatefulLayout> */
|
|
18
17
|
type: Object,
|
|
19
18
|
required: true
|
|
20
19
|
}
|
|
@@ -22,17 +21,18 @@ export default defineComponent({
|
|
|
22
21
|
setup (props) {
|
|
23
22
|
useDefaults({}, 'VjsfSelect')
|
|
24
23
|
|
|
25
|
-
const getItems =
|
|
24
|
+
const { getItems, selectProps, selectSlots, localData } = useSelectNode(toRef(props, 'modelValue'), props.statefulLayout)
|
|
26
25
|
|
|
27
26
|
const fieldProps = computed(() => {
|
|
28
|
-
const fieldProps =
|
|
27
|
+
const fieldProps = { ...selectProps.value }
|
|
29
28
|
fieldProps.loading = getItems.loading.value
|
|
30
29
|
fieldProps.items = getItems.items.value
|
|
30
|
+
fieldProps.modelValue = localData.value
|
|
31
31
|
return fieldProps
|
|
32
32
|
})
|
|
33
33
|
|
|
34
34
|
// @ts-ignore
|
|
35
|
-
return () => h(VSelect, fieldProps.value,
|
|
35
|
+
return () => h(VSelect, fieldProps.value, selectSlots.value)
|
|
36
36
|
}
|
|
37
37
|
})
|
|
38
38
|
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>
|
|
2
2
|
import { VSlider } from 'vuetify/components/VSlider'
|
|
3
|
-
import { computed } from 'vue'
|
|
4
|
-
import
|
|
3
|
+
import { defineComponent, computed, toRef, h } from 'vue'
|
|
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').VjsfSliderNode> */
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
setup (props) {
|
|
21
|
+
useDefaults({}, 'VjsfSlider')
|
|
22
|
+
|
|
23
|
+
const { inputProps, localData, compSlots } = useNode(
|
|
24
|
+
toRef(props, 'modelValue'), props.statefulLayout, { layoutPropsMap: ['step', 'min', 'max'] }
|
|
25
|
+
)
|
|
21
26
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
const fullProps = computed(() => {
|
|
28
|
+
const fullProps = { ...inputProps.value }
|
|
29
|
+
fullProps.modelValue = localData.value
|
|
30
|
+
fullProps['onUpdate:modelValue'] = (/** @type string */value) => props.statefulLayout.input(props.modelValue, value && Number(value))
|
|
31
|
+
return fullProps
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
return () => h(VSlider, fullProps.value, compSlots.value)
|
|
35
|
+
}
|
|
28
36
|
})
|
|
29
37
|
</script>
|
|
30
|
-
|
|
31
|
-
<template>
|
|
32
|
-
<v-slider
|
|
33
|
-
type="number"
|
|
34
|
-
v-bind="fieldProps"
|
|
35
|
-
@update:model-value="value => statefulLayout.input(modelValue, value && Number(value))"
|
|
36
|
-
/>
|
|
37
|
-
</template>
|
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>
|
|
2
|
+
import { defineComponent, h, computed, toRef } from 'vue'
|
|
2
3
|
import { VSwitch } from 'vuetify/components/VSwitch'
|
|
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').VjsfSwitchNode> */
|
|
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({}, 'VjsfSwitch')
|
|
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(VSwitch, 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-switch
|
|
32
|
-
v-bind="fieldProps"
|
|
33
|
-
@update:model-value="value => statefulLayout.input(modelValue, value)"
|
|
34
|
-
/>
|
|
35
|
-
</template>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { defineComponent, h,
|
|
2
|
+
import { defineComponent, h, toRef } from 'vue'
|
|
3
3
|
import { VTextField } from 'vuetify/components/VTextField'
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../../composables/use-node.js'
|
|
5
5
|
import { useDefaults } from 'vuetify'
|
|
6
6
|
|
|
7
7
|
export default defineComponent({
|
|
@@ -20,11 +20,11 @@ export default defineComponent({
|
|
|
20
20
|
setup (props) {
|
|
21
21
|
useDefaults({}, 'VjsfTextField')
|
|
22
22
|
|
|
23
|
-
const
|
|
24
|
-
|
|
23
|
+
const { inputProps, localData, compSlots } = useNode(
|
|
24
|
+
toRef(props, 'modelValue'), props.statefulLayout, { layoutPropsMap: ['placeholder'] }
|
|
25
|
+
)
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
return () => h(VTextField, fieldProps.value, fieldSlots.value)
|
|
27
|
+
return () => h(VTextField, { ...inputProps.value, modelValue: localData.value }, compSlots.value)
|
|
28
28
|
}
|
|
29
29
|
})
|
|
30
30
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { defineComponent, h, computed, ref, watch } from 'vue'
|
|
2
|
+
import { defineComponent, h, computed, ref, watch, toRef } from 'vue'
|
|
3
3
|
import { VTextarea } from 'vuetify/components/VTextarea'
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../../composables/use-node.js'
|
|
5
5
|
import { useDefaults } from 'vuetify'
|
|
6
6
|
|
|
7
7
|
export default defineComponent({
|
|
@@ -23,22 +23,27 @@ export default defineComponent({
|
|
|
23
23
|
/** @type {import('vue').Ref<null | HTMLElement>} */
|
|
24
24
|
const textarea = ref(null)
|
|
25
25
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
const { inputProps, localData, compSlots, options } = useNode(
|
|
27
|
+
toRef(props, 'modelValue'), props.statefulLayout, { layoutPropsMap: ['placeholder'] }
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
const rows = computed(() => options.value.readOnly && options.value.summary ? 3 : undefined)
|
|
31
|
+
|
|
32
|
+
const fullProps = computed(() => {
|
|
33
|
+
const fullProps = { ...inputProps.value }
|
|
34
|
+
fullProps.ref = textarea
|
|
35
|
+
fullProps.rows = rows.value
|
|
36
|
+
fullProps.modelValue = localData.value
|
|
37
|
+
return fullProps
|
|
31
38
|
})
|
|
32
|
-
const fieldSlots = computed(() => getCompSlots(props.modelValue, props.statefulLayout))
|
|
33
39
|
|
|
34
|
-
watch(() =>
|
|
40
|
+
watch(() => options.value.readOnly, (readOnly) => {
|
|
35
41
|
if (readOnly && textarea.value) {
|
|
36
42
|
textarea.value.scrollTop = 0
|
|
37
43
|
}
|
|
38
44
|
})
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
return () => h(VTextarea, fieldProps.value, fieldSlots.value)
|
|
46
|
+
return () => h(VTextarea, fullProps.value, compSlots.value)
|
|
42
47
|
}
|
|
43
48
|
})
|
|
44
49
|
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import TextFieldMenu from '../fragments/text-field-menu.vue'
|
|
3
3
|
import { VTimePicker } from 'vuetify/labs/VTimePicker'
|
|
4
4
|
import { useDate, useDefaults } from 'vuetify'
|
|
5
|
-
import { computed } from 'vue'
|
|
6
|
-
import {
|
|
5
|
+
import { computed, toRef } from 'vue'
|
|
6
|
+
import { getShortTime, getLongTime } from '../../utils/dates.js'
|
|
7
|
+
import useNode from '../../composables/use-node.js'
|
|
7
8
|
|
|
8
9
|
useDefaults({}, 'VjsfDatePicker')
|
|
9
10
|
|
|
@@ -22,23 +23,25 @@ const props = defineProps({
|
|
|
22
23
|
|
|
23
24
|
const vDate = useDate()
|
|
24
25
|
|
|
26
|
+
const { compProps, localData } = useNode(toRef(props, 'modelValue'), props.statefulLayout)
|
|
27
|
+
|
|
25
28
|
const timePickerProps = computed(() => {
|
|
26
|
-
const timePickerProps =
|
|
29
|
+
const timePickerProps = { ...compProps.value }
|
|
27
30
|
timePickerProps['ampm-in-title'] = true
|
|
28
|
-
if (
|
|
31
|
+
if (localData.value) timePickerProps.modelValue = getShortTime(localData.value)
|
|
29
32
|
return timePickerProps
|
|
30
33
|
})
|
|
31
34
|
</script>
|
|
32
35
|
|
|
33
36
|
<template>
|
|
34
37
|
<text-field-menu
|
|
35
|
-
:model-value="modelValue"
|
|
38
|
+
:model-value="props.modelValue"
|
|
36
39
|
:stateful-layout="statefulLayout"
|
|
37
40
|
:formatted-value="timePickerProps.modelValue && vDate.format('2010-04-13T' + timePickerProps.modelValue, 'fullTime')"
|
|
38
41
|
>
|
|
39
42
|
<v-time-picker
|
|
40
43
|
v-bind="timePickerProps"
|
|
41
|
-
@update:model-value="value => {statefulLayout.input(modelValue, value && getLongTime(value))}"
|
|
44
|
+
@update:model-value="value => {statefulLayout.input(props.modelValue, value && getLongTime(value))}"
|
|
42
45
|
/>
|
|
43
46
|
</text-field-menu>
|
|
44
47
|
</template>
|