@koumoul/vjsf 3.0.0-beta.5 → 3.0.0-beta.51

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 (164) hide show
  1. package/README.md +21 -0
  2. package/package.json +12 -17
  3. package/src/compat/v2.js +132 -27
  4. package/src/compile/index.js +19 -4
  5. package/src/compile/options.js +4 -9
  6. package/src/compile/v-jsf-compiled.vue.ejs +1 -2
  7. package/src/components/fragments/child-subtitle.vue +25 -0
  8. package/src/components/fragments/help-message.vue +33 -8
  9. package/src/components/fragments/section-header.vue +9 -7
  10. package/src/components/fragments/select-item-icon.vue +2 -2
  11. package/src/components/fragments/select-item.vue +2 -1
  12. package/src/components/fragments/select-selection.vue +2 -1
  13. package/src/components/fragments/selection-group.vue +105 -0
  14. package/src/components/fragments/text-field-menu.vue +16 -7
  15. package/src/components/node.vue +58 -41
  16. package/src/components/nodes/autocomplete.vue +14 -60
  17. package/src/components/nodes/card.vue +39 -0
  18. package/src/components/nodes/checkbox-group.vue +39 -0
  19. package/src/components/nodes/checkbox.vue +31 -26
  20. package/src/components/nodes/color-picker.vue +10 -4
  21. package/src/components/nodes/combobox.vue +17 -40
  22. package/src/components/nodes/date-picker.vue +30 -13
  23. package/src/components/nodes/date-time-picker.vue +83 -3
  24. package/src/components/nodes/expansion-panels.vue +34 -16
  25. package/src/components/nodes/file-input.vue +15 -11
  26. package/src/components/nodes/list.vue +251 -111
  27. package/src/components/nodes/number-combobox.vue +18 -39
  28. package/src/components/nodes/number-field.vue +17 -11
  29. package/src/components/nodes/one-of-select.vue +53 -27
  30. package/src/components/nodes/radio-group.vue +58 -0
  31. package/src/components/nodes/section.vue +4 -1
  32. package/src/components/nodes/select.vue +15 -54
  33. package/src/components/nodes/slider.vue +32 -29
  34. package/src/components/nodes/stepper.vue +10 -2
  35. package/src/components/nodes/switch-group.vue +39 -0
  36. package/src/components/nodes/switch.vue +31 -26
  37. package/src/components/nodes/tabs.vue +20 -8
  38. package/src/components/nodes/text-field.vue +10 -7
  39. package/src/components/nodes/textarea.vue +20 -12
  40. package/src/components/nodes/time-picker.vue +41 -1
  41. package/src/components/nodes/vertical-tabs.vue +16 -6
  42. package/src/components/tree.vue +1 -1
  43. package/src/components/vjsf.vue +11 -1
  44. package/src/composables/use-comp-defaults.js +19 -0
  45. package/src/composables/use-dnd.js +2 -1
  46. package/src/composables/use-get-items.js +53 -0
  47. package/src/composables/use-node.js +136 -0
  48. package/src/composables/use-select-node.js +67 -0
  49. package/src/composables/use-vjsf.js +70 -40
  50. package/src/index.js +5 -2
  51. package/src/options.js +65 -0
  52. package/src/types.ts +64 -33
  53. package/src/utils/arrays.js +37 -6
  54. package/src/utils/build.js +1 -1
  55. package/types/compat/v2.d.ts.map +1 -1
  56. package/types/compile/index.d.ts +2 -2
  57. package/types/compile/index.d.ts.map +1 -1
  58. package/types/compile/options.d.ts +3 -2
  59. package/types/compile/options.d.ts.map +1 -1
  60. package/types/components/fragments/child-subtitle.vue.d.ts +8 -0
  61. package/types/components/fragments/child-subtitle.vue.d.ts.map +1 -0
  62. package/types/components/fragments/help-message.vue.d.ts +2 -2
  63. package/types/components/fragments/node-slot.vue.d.ts +2 -44
  64. package/types/components/fragments/node-slot.vue.d.ts.map +1 -1
  65. package/types/components/fragments/section-header.vue.d.ts +4 -2
  66. package/types/components/fragments/select-item-icon.vue.d.ts +2 -12
  67. package/types/components/fragments/select-item.vue.d.ts +2 -2
  68. package/types/components/fragments/select-selection.vue.d.ts +2 -2
  69. package/types/components/fragments/selection-group.vue.d.ts +5 -0
  70. package/types/components/fragments/selection-group.vue.d.ts.map +1 -0
  71. package/types/components/fragments/text-field-menu.vue.d.ts +2 -2
  72. package/types/components/fragments/text-field-menu.vue.d.ts.map +1 -1
  73. package/types/components/node.vue.d.ts +2 -2
  74. package/types/components/nodes/autocomplete.vue.d.ts +2 -24
  75. package/types/components/nodes/autocomplete.vue.d.ts.map +1 -1
  76. package/types/components/nodes/card.vue.d.ts +10 -0
  77. package/types/components/nodes/card.vue.d.ts.map +1 -0
  78. package/types/components/nodes/checkbox-group.vue.d.ts +5 -0
  79. package/types/components/nodes/checkbox-group.vue.d.ts.map +1 -0
  80. package/types/components/nodes/checkbox.vue.d.ts +3 -8
  81. package/types/components/nodes/color-picker.vue.d.ts +2 -2
  82. package/types/components/nodes/combobox.vue.d.ts +2 -24
  83. package/types/components/nodes/combobox.vue.d.ts.map +1 -1
  84. package/types/components/nodes/date-picker.vue.d.ts +2 -2
  85. package/types/components/nodes/date-time-picker.vue.d.ts +4 -4
  86. package/types/components/nodes/expansion-panels.vue.d.ts +2 -2
  87. package/types/components/nodes/file-input.vue.d.ts +2 -24
  88. package/types/components/nodes/file-input.vue.d.ts.map +1 -1
  89. package/types/components/nodes/list.vue.d.ts +2 -2
  90. package/types/components/nodes/number-combobox.vue.d.ts +2 -24
  91. package/types/components/nodes/number-combobox.vue.d.ts.map +1 -1
  92. package/types/components/nodes/number-field.vue.d.ts +2 -24
  93. package/types/components/nodes/number-field.vue.d.ts.map +1 -1
  94. package/types/components/nodes/one-of-select.vue.d.ts +2 -2
  95. package/types/components/nodes/radio-group.vue.d.ts +5 -0
  96. package/types/components/nodes/radio-group.vue.d.ts.map +1 -0
  97. package/types/components/nodes/section.vue.d.ts +2 -2
  98. package/types/components/nodes/select.vue.d.ts +2 -24
  99. package/types/components/nodes/select.vue.d.ts.map +1 -1
  100. package/types/components/nodes/slider.vue.d.ts +3 -8
  101. package/types/components/nodes/stepper.vue.d.ts +2 -2
  102. package/types/components/nodes/switch-group.vue.d.ts +5 -0
  103. package/types/components/nodes/switch-group.vue.d.ts.map +1 -0
  104. package/types/components/nodes/switch.vue.d.ts +3 -8
  105. package/types/components/nodes/tabs.vue.d.ts +2 -2
  106. package/types/components/nodes/text-field.vue.d.ts +2 -24
  107. package/types/components/nodes/text-field.vue.d.ts.map +1 -1
  108. package/types/components/nodes/textarea.vue.d.ts +2 -24
  109. package/types/components/nodes/textarea.vue.d.ts.map +1 -1
  110. package/types/components/nodes/time-picker.vue.d.ts +8 -1
  111. package/types/components/nodes/vertical-tabs.vue.d.ts +2 -2
  112. package/types/components/options.d.ts +1 -1
  113. package/types/components/options.d.ts.map +1 -1
  114. package/types/components/tree.vue.d.ts +2 -2
  115. package/types/components/vjsf.vue.d.ts +4 -4
  116. package/types/composables/use-comp-defaults.d.ts +8 -0
  117. package/types/composables/use-comp-defaults.d.ts.map +1 -0
  118. package/types/composables/use-dnd.d.ts +3 -3
  119. package/types/composables/use-dnd.d.ts.map +1 -1
  120. package/types/composables/use-field-props.d.ts +30 -0
  121. package/types/composables/use-field-props.d.ts.map +1 -0
  122. package/types/composables/use-field.d.ts +31 -0
  123. package/types/composables/use-field.d.ts.map +1 -0
  124. package/types/composables/use-get-items.d.ts +12 -0
  125. package/types/composables/use-get-items.d.ts.map +1 -0
  126. package/types/composables/use-node.d.ts +32 -0
  127. package/types/composables/use-node.d.ts.map +1 -0
  128. package/types/composables/use-select-field.d.ts +21 -0
  129. package/types/composables/use-select-field.d.ts.map +1 -0
  130. package/types/composables/use-select-node.d.ts +27 -0
  131. package/types/composables/use-select-node.d.ts.map +1 -0
  132. package/types/composables/use-select-props.d.ts +21 -0
  133. package/types/composables/use-select-props.d.ts.map +1 -0
  134. package/types/composables/use-select.d.ts +21 -0
  135. package/types/composables/use-select.d.ts.map +1 -0
  136. package/types/composables/use-vjsf.d.ts +2 -2
  137. package/types/composables/use-vjsf.d.ts.map +1 -1
  138. package/types/iconsets/default-aliases.d.ts +10 -0
  139. package/types/iconsets/default-aliases.d.ts.map +1 -0
  140. package/types/iconsets/mdi-svg.d.ts +3 -0
  141. package/types/iconsets/mdi-svg.d.ts.map +1 -0
  142. package/types/iconsets/mdi.d.ts +3 -0
  143. package/types/iconsets/mdi.d.ts.map +1 -0
  144. package/types/index.d.ts +5 -2
  145. package/types/index.d.ts.map +1 -1
  146. package/types/options.d.ts +9 -0
  147. package/types/options.d.ts.map +1 -0
  148. package/types/types.d.ts +65 -33
  149. package/types/types.d.ts.map +1 -1
  150. package/types/utils/arrays.d.ts +17 -4
  151. package/types/utils/arrays.d.ts.map +1 -1
  152. package/types/utils/build.d.ts +1 -1
  153. package/types/utils/index.d.ts +0 -3
  154. package/types/utils/props.d.ts +8 -2
  155. package/types/utils/props.d.ts.map +1 -1
  156. package/types/utils/slots.d.ts +8 -0
  157. package/types/utils/slots.d.ts.map +1 -1
  158. package/src/components/options.js +0 -27
  159. package/src/utils/global-register.js +0 -13
  160. package/src/utils/index.js +0 -5
  161. package/src/utils/props.js +0 -109
  162. package/src/utils/slots.js +0 -18
  163. package/types/utils/global-register.d.ts +0 -8
  164. package/types/utils/global-register.d.ts.map +0 -1
@@ -1,9 +1,12 @@
1
1
  <script setup>
2
2
  import TextFieldMenu from '../fragments/text-field-menu.vue'
3
3
  import { VDatePicker } from 'vuetify/components/VDatePicker'
4
- import { useDate } from 'vuetify'
5
- import { computed } from 'vue'
6
- import { getCompProps, getDateTimeParts } from '../../utils/index.js'
4
+ import { useDate, useDefaults } from 'vuetify'
5
+ import { computed, ref, toRef } from 'vue'
6
+ import { getDateTimeParts, getDateTimeWithOffset } from '../../utils/dates.js'
7
+ import useNode from '../../composables/use-node.js'
8
+
9
+ useDefaults({}, 'VjsfDatePicker')
7
10
 
8
11
  const props = defineProps({
9
12
  modelValue: {
@@ -20,25 +23,39 @@ const props = defineProps({
20
23
 
21
24
  const vDate = useDate()
22
25
 
26
+ const menuOpened = ref(false)
27
+
28
+ const { compProps, localData } = useNode(toRef(props, 'modelValue'), props.statefulLayout)
29
+
23
30
  const datePickerProps = computed(() => {
24
- const datePickerProps = getCompProps(props.modelValue, 'datePicker', true)
31
+ const datePickerProps = { ...compProps.value }
25
32
  datePickerProps.hideActions = true
26
- if (props.modelValue.data) datePickerProps.modelValue = new Date(props.modelValue.data)
33
+ if (localData.value) datePickerProps.modelValue = new Date(/** @type {string} */(localData.value))
34
+ datePickerProps['onUpdate:modelValue'] = (/** @type {Date} */value) => {
35
+ if (!value) return
36
+ if (props.modelValue.layout.format === 'date-time') {
37
+ props.statefulLayout.input(props.modelValue, getDateTimeWithOffset(value))
38
+ } else {
39
+ props.statefulLayout.input(props.modelValue, getDateTimeParts(/** @type Date */(/** @type unknown */(value)))[0])
40
+ }
41
+ menuOpened.value = false
42
+ }
27
43
  return datePickerProps
28
44
  })
45
+
46
+ const formattedValue = computed(() => {
47
+ return localData.value ? vDate.format(/** @type {string} */(localData.value), 'fullDateWithWeekday') : null
48
+ })
49
+
29
50
  </script>
30
51
 
31
52
  <template>
32
53
  <text-field-menu
33
- :model-value="modelValue"
54
+ v-model:menu-opened="menuOpened"
55
+ :model-value="props.modelValue"
34
56
  :stateful-layout="statefulLayout"
35
- :formatted-value="modelValue.data && vDate.format(modelValue.data, 'fullDateWithWeekday')"
57
+ :formatted-value="formattedValue"
36
58
  >
37
- <template #default="{close}">
38
- <v-date-picker
39
- v-bind="datePickerProps"
40
- @update:model-value="value => {statefulLayout.input(modelValue, value && getDateTimeParts(/** @type Date */(/** @type unknown */(value)))[0]); close()}"
41
- />
42
- </template>
59
+ <v-date-picker v-bind="datePickerProps" />
43
60
  </text-field-menu>
44
61
  </template>
@@ -1,8 +1,20 @@
1
1
  <script setup>
2
+ import TextFieldMenu from '../fragments/text-field-menu.vue'
3
+ import { VDatePicker } from 'vuetify/components/VDatePicker'
4
+ import { VTimePicker } from 'vuetify/labs/VTimePicker'
5
+ import { VTabs, VTab, VTabsWindow, VTabsWindowItem } from 'vuetify/components/VTabs'
6
+ import { VIcon } from 'vuetify/components/VIcon'
7
+ import { VSheet } from 'vuetify/components/VSheet'
8
+ import { useDate, useDefaults } from 'vuetify'
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'
2
12
 
3
- defineProps({
13
+ useDefaults({}, 'VjsfDatePicker')
14
+
15
+ const props = defineProps({
4
16
  modelValue: {
5
- /** @type import('vue').PropType<import('../../types.js').VjsfDateTimePickerNode> */
17
+ /** @type import('vue').PropType<import('../../types.js').VjsfDatePickerNode> */
6
18
  type: Object,
7
19
  required: true
8
20
  },
@@ -13,8 +25,76 @@ defineProps({
13
25
  }
14
26
  })
15
27
 
28
+ const vDate = useDate()
29
+
30
+ const tab = ref('date')
31
+ const menuOpened = ref(false)
32
+ watch(menuOpened, () => { tab.value = 'date' })
33
+
34
+ const { compProps, localData } = useNode(toRef(props, 'modelValue'), props.statefulLayout)
35
+
36
+ const datePickerProps = computed(() => {
37
+ const datePickerProps = { ...compProps.value }
38
+ datePickerProps.hideActions = true
39
+ if (localData.value) datePickerProps.modelValue = new Date(localData.value)
40
+ datePickerProps['onUpdate:modelValue'] = (/** @type {Date} */value) => {
41
+ if (!value) return
42
+
43
+ if (localData.value) {
44
+ // replace date part of current value
45
+ const datePart = value && getDateTimeParts(/** @type Date */(/** @type unknown */(value)))[0]
46
+ props.statefulLayout.input(props.modelValue, datePart + localData.value.slice(10))
47
+ } else {
48
+ props.statefulLayout.input(props.modelValue, getDateTimeWithOffset(value))
49
+ }
50
+ tab.value = 'time'
51
+ }
52
+ return datePickerProps
53
+ })
54
+
55
+ const timePickerProps = computed(() => {
56
+ const timePickerProps = { ...compProps.value }
57
+ timePickerProps['ampm-in-title'] = true
58
+ if (localData.value) timePickerProps.modelValue = getShortTime(localData.value.slice(11))
59
+ timePickerProps['onUpdate:modelValue'] = (/** @type {string} */value) => {
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))
63
+ }
64
+ return timePickerProps
65
+ })
16
66
  </script>
17
67
 
18
68
  <template>
19
- TODO date-time
69
+ <text-field-menu
70
+ v-model:menu-opened="menuOpened"
71
+ :model-value="modelValue"
72
+ :stateful-layout="statefulLayout"
73
+ :formatted-value="modelValue.data && vDate.format(modelValue.data, 'fullDateTime')"
74
+ >
75
+ <v-sheet style="width: 328px">
76
+ <v-tabs
77
+ v-model="tab"
78
+ align-tabs="center"
79
+ >
80
+ <v-tab value="date">
81
+ <v-icon :icon="statefulLayout.options.icons.calendar" />
82
+ </v-tab>
83
+ <v-tab
84
+ value="time"
85
+ :disabled="!modelValue.data"
86
+ >
87
+ <v-icon :icon="statefulLayout.options.icons.clock" />
88
+ </v-tab>
89
+ </v-tabs>
90
+ <v-tabs-window v-model="tab">
91
+ <v-tabs-window-item value="date">
92
+ <v-date-picker v-bind="datePickerProps" />
93
+ </v-tabs-window-item>
94
+ <v-tabs-window-item value="time">
95
+ <v-time-picker v-bind="timePickerProps" />
96
+ </v-tabs-window-item>
97
+ </v-tabs-window>
98
+ </v-sheet>
99
+ </text-field-menu>
20
100
  </template>
@@ -1,10 +1,18 @@
1
1
  <script setup>
2
- import { VExpansionPanels, VExpansionPanel, VExpansionPanelTitle, VContainer, VRow, VIcon } from 'vuetify/components'
2
+ import { toRef } from 'vue'
3
+ import { VExpansionPanels, VExpansionPanel, VExpansionPanelTitle, VExpansionPanelText } from 'vuetify/components/VExpansionPanel'
4
+ import { VContainer, VRow } from 'vuetify/components/VGrid'
5
+ import { VIcon } from 'vuetify/components/VIcon'
3
6
  import { isSection } from '@json-layout/core'
4
7
  import Node from '../node.vue'
5
8
  import SectionHeader from '../fragments/section-header.vue'
9
+ import ChildSubtitle from '../fragments/child-subtitle.vue'
10
+ import useNode from '../../composables/use-node.js'
11
+ import { useDefaults } from 'vuetify'
6
12
 
7
- defineProps({
13
+ useDefaults({}, 'VjsfExpansionPanels')
14
+
15
+ const props = defineProps({
8
16
  modelValue: {
9
17
  /** @type import('vue').PropType<import('../../types.js').VjsfExpansionPanelsNode> */
10
18
  type: Object,
@@ -17,11 +25,13 @@ defineProps({
17
25
  }
18
26
  })
19
27
 
28
+ const { compProps } = useNode(toRef(props, 'modelValue'), props.statefulLayout)
29
+
20
30
  </script>
21
31
 
22
32
  <template>
23
33
  <section-header :node="modelValue" />
24
- <v-expansion-panels>
34
+ <v-expansion-panels v-bind="compProps">
25
35
  <v-expansion-panel
26
36
  v-for="(child, i) of modelValue.children"
27
37
  :key="child.key"
@@ -32,21 +42,29 @@ defineProps({
32
42
  v-if="child.validated && (child.error || child.childError)"
33
43
  color="error"
34
44
  class="mr-2"
35
- >
36
- mdi-alert
37
- </v-icon>
45
+ :icon="statefulLayout.options.icons.alert"
46
+ />
38
47
  {{ child.layout.title ?? child.layout.label }}
39
48
  </v-expansion-panel-title>
40
- <v-container fluid>
41
- <v-row>
42
- <node
43
- v-for="grandChild of isSection(child) ? child.children : [child]"
44
- :key="grandChild.fullKey"
45
- :model-value="/** @type import('../../types.js').VjsfNode */(grandChild)"
46
- :stateful-layout="statefulLayout"
47
- />
48
- </v-row>
49
- </v-container>
49
+ <v-expansion-panel-text>
50
+ <v-container fluid>
51
+ <child-subtitle :model-value="child" />
52
+ <v-row :dense="modelValue.options?.density === 'compact' || modelValue.options?.density === 'comfortable'">
53
+ <node
54
+ v-for="grandChild of isSection(child) ? child.children : [child]"
55
+ :key="grandChild.fullKey"
56
+ :model-value="/** @type import('../../types.js').VjsfNode */(grandChild)"
57
+ :stateful-layout="statefulLayout"
58
+ />
59
+ </v-row>
60
+ </v-container>
61
+ </v-expansion-panel-text>
50
62
  </v-expansion-panel>
51
63
  </v-expansion-panels>
52
64
  </template>
65
+
66
+ <style>
67
+ .vjsf-node-expansion-panels .v-expansion-panel-text__wrapper {
68
+ padding: 0;
69
+ }
70
+ </style>
@@ -1,7 +1,8 @@
1
1
  <script>
2
- import { defineComponent, h, computed } from 'vue'
3
- import { VFileInput } from 'vuetify/components'
4
- import { getInputProps, getCompSlots } from '../../utils/index.js'
2
+ import { defineComponent, h, computed, toRef } from 'vue'
3
+ import { VFileInput } from 'vuetify/components/VFileInput'
4
+ import useNode from '../../composables/use-node.js'
5
+ import { useDefaults } from 'vuetify'
5
6
 
6
7
  export default defineComponent({
7
8
  props: {
@@ -17,20 +18,23 @@ export default defineComponent({
17
18
  }
18
19
  },
19
20
  setup (props) {
21
+ useDefaults({}, 'VjsfFileInput')
22
+
23
+ const { inputProps, localData, compSlots } = useNode(
24
+ toRef(props, 'modelValue'), props.statefulLayout, { layoutPropsMap: ['placeholder', 'accept', 'multiple'] }
25
+ )
26
+
20
27
  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)
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)
27
32
  }
28
33
  return fieldProps
29
34
  })
30
- const fieldSlots = computed(() => getCompSlots(props.modelValue, props.statefulLayout))
31
35
 
32
36
  // @ts-ignore
33
- return () => h(VFileInput, fieldProps.value, fieldSlots.value)
37
+ return () => h(VFileInput, { ...fieldProps.value, modelValue: localData.value }, compSlots.value)
34
38
  }
35
39
  })
36
40