@josercl/form-maker 1.2.0 → 1.3.0
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/dist/index.js +483 -0
- package/dist/index.umd.cjs +1 -0
- package/lib/components/FormMaker.vue +58 -143
- package/lib/components/FormMakerInput.vue +18 -12
- package/lib/components/RuleEvaluator.vue +36 -0
- package/lib/components/SimpleComponent.ts +23 -0
- package/lib/components/inputs/BasicInput.vue +16 -10
- package/lib/components/inputs/CheckboxInput.vue +24 -13
- package/lib/components/inputs/FileInput.vue +14 -4
- package/lib/components/inputs/RadioInput.vue +21 -12
- package/lib/components/inputs/SelectInput.vue +24 -19
- package/lib/components/inputs/TextAreaInput.vue +14 -8
- package/lib/components/texts/FormMakerInputLabel.vue +10 -9
- package/lib/composables/useFormClasses.ts +23 -0
- package/lib/composables/useVModel.ts +14 -0
- package/{index.js → lib/index.js} +11 -11
- package/lib/model.d.ts +48 -0
- package/package.json +39 -25
- package/lib/components/inputs/FormInputMixin.js +0 -37
- package/lib/components/texts/FormMakerInputError.vue +0 -5
- package/lib/components/texts/FormMakerInputHelp.vue +0 -5
- package/lib/composables/useVModel.js +0 -8
- package/lib/utils.js +0 -9
- package/umd/index.umd.js +0 -1
|
@@ -1,87 +1,43 @@
|
|
|
1
|
-
<script setup>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { FormMakerProps, InputType } from 'lib/model';
|
|
2
3
|
import {
|
|
3
|
-
computed,
|
|
4
|
+
computed,
|
|
5
|
+
inject,
|
|
6
|
+
provide,
|
|
7
|
+
type ComputedRef
|
|
4
8
|
} from 'vue';
|
|
5
9
|
|
|
6
|
-
const props = defineProps({
|
|
7
|
-
loading:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
type: Boolean,
|
|
25
|
-
default: false,
|
|
26
|
-
},
|
|
27
|
-
rowClass: {
|
|
28
|
-
type: String,
|
|
29
|
-
default: null,
|
|
30
|
-
},
|
|
31
|
-
columnClass: {
|
|
32
|
-
type: String,
|
|
33
|
-
default: null,
|
|
34
|
-
},
|
|
35
|
-
labelClass: {
|
|
36
|
-
type: String,
|
|
37
|
-
default: null,
|
|
38
|
-
},
|
|
39
|
-
inputGroupClass: {
|
|
40
|
-
type: String,
|
|
41
|
-
default: null,
|
|
42
|
-
},
|
|
43
|
-
inputWrapperClass: {
|
|
44
|
-
type: String,
|
|
45
|
-
default: null,
|
|
46
|
-
},
|
|
47
|
-
inputErrorClass: {
|
|
48
|
-
type: String,
|
|
49
|
-
default: null,
|
|
50
|
-
},
|
|
51
|
-
inputClass: {
|
|
52
|
-
type: String,
|
|
53
|
-
default: null,
|
|
54
|
-
},
|
|
55
|
-
errorClass: {
|
|
56
|
-
type: String,
|
|
57
|
-
default: null,
|
|
58
|
-
},
|
|
59
|
-
helpTextClass: {
|
|
60
|
-
type: String,
|
|
61
|
-
default: null,
|
|
62
|
-
},
|
|
63
|
-
submitButtonClass: {
|
|
64
|
-
type: String,
|
|
65
|
-
default: null,
|
|
66
|
-
},
|
|
67
|
-
submitButtonText: {
|
|
68
|
-
type: String,
|
|
69
|
-
default: 'Submit',
|
|
70
|
-
},
|
|
71
|
-
});
|
|
10
|
+
const props = withDefaults(defineProps<FormMakerProps>(), {
|
|
11
|
+
loading: false,
|
|
12
|
+
hasActions: true,
|
|
13
|
+
modelValue: () => ({}),
|
|
14
|
+
fields: () => [],
|
|
15
|
+
hideDivider: false,
|
|
16
|
+
rowClass: null,
|
|
17
|
+
columnClass: null,
|
|
18
|
+
labelClass: null,
|
|
19
|
+
inputGroupClass: null,
|
|
20
|
+
inputWrapperClass: null,
|
|
21
|
+
inputErrorClass: null,
|
|
22
|
+
inputClass: null,
|
|
23
|
+
errorClass: null,
|
|
24
|
+
helpTextClass: null,
|
|
25
|
+
submitButtonClass: null,
|
|
26
|
+
submitButtonText: 'Submit',
|
|
27
|
+
})
|
|
72
28
|
|
|
73
|
-
const emit = defineEmits([
|
|
29
|
+
const emit = defineEmits(['submit', 'update:modelValue']);
|
|
74
30
|
|
|
75
31
|
const handleSubmit = () => emit('submit');
|
|
76
32
|
|
|
77
|
-
const formFields = computed(() => {
|
|
33
|
+
const formFields: ComputedRef<InputType[][]> = computed(() => {
|
|
78
34
|
if (props.fields.length > 0) {
|
|
79
35
|
return props.fields.map(row => {
|
|
80
|
-
let newRow = row;
|
|
36
|
+
let newRow: InputType[] = row;
|
|
81
37
|
if (!Array.isArray(row)) {
|
|
82
|
-
newRow = [
|
|
38
|
+
newRow = [row];
|
|
83
39
|
}
|
|
84
|
-
return newRow.map(fieldSpec => {
|
|
40
|
+
return newRow.map((fieldSpec: InputType) => {
|
|
85
41
|
if (!fieldSpec.id) {
|
|
86
42
|
return {
|
|
87
43
|
...fieldSpec,
|
|
@@ -93,55 +49,41 @@ const formFields = computed(() => {
|
|
|
93
49
|
});
|
|
94
50
|
}
|
|
95
51
|
|
|
96
|
-
return Object.keys(props.modelValue).map(key => [
|
|
52
|
+
return Object.keys(props.modelValue).map(key => ([
|
|
97
53
|
{
|
|
98
54
|
name: key,
|
|
99
55
|
label: key,
|
|
100
56
|
id: `formMaker_${key}`,
|
|
101
|
-
}
|
|
102
|
-
]);
|
|
57
|
+
}
|
|
58
|
+
]));
|
|
103
59
|
});
|
|
104
60
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
inputClass,
|
|
113
|
-
errorClass,
|
|
114
|
-
helpTextClass,
|
|
115
|
-
submitButtonClass,
|
|
116
|
-
modelValue,
|
|
117
|
-
} = toRefs(props);
|
|
61
|
+
provide('labelClass', props.labelClass || inject('form-label'));
|
|
62
|
+
provide('inputGroupClass', props.inputGroupClass || inject('input-group'));
|
|
63
|
+
provide('inputWrapperClass', props.inputWrapperClass || inject('input-wrapper'));
|
|
64
|
+
provide('inputErrorClass', props.inputErrorClass || inject('input-error'));
|
|
65
|
+
provide('inputClass', props.inputClass || inject('input'));
|
|
66
|
+
provide('errorClass', props.errorClass || inject('error'));
|
|
67
|
+
provide('helpTextClass', props.helpTextClass || inject('help-text'));
|
|
118
68
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
provide('inputErrorClass', inputErrorClass.value || inject('input-error'));
|
|
123
|
-
provide('inputClass', inputClass.value || inject('input'));
|
|
124
|
-
provide('errorClass', errorClass.value || inject('error'));
|
|
125
|
-
provide('helpTextClass', helpTextClass.value || inject('help-text'));
|
|
69
|
+
const realRowClass = props.rowClass || inject('form-row');
|
|
70
|
+
const realColumnClass = props.columnClass || inject('form-column');
|
|
71
|
+
const realSubmitButtonClass = props.submitButtonClass || inject('submit-button');
|
|
126
72
|
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const getObject = fieldName => {
|
|
132
|
-
const fields = fieldName.split('.');
|
|
133
|
-
let result = modelValue.value;
|
|
73
|
+
const getObject = (fieldName: string) => {
|
|
74
|
+
const fields = fieldName.split('.')
|
|
75
|
+
let result = props.modelValue
|
|
134
76
|
for (let i = 0; i < fields.length - 1; i += 1) {
|
|
135
|
-
const candidate = result[fields[i]]
|
|
77
|
+
const candidate = result[fields[i]]
|
|
136
78
|
if (!candidate) {
|
|
137
|
-
break
|
|
79
|
+
break
|
|
138
80
|
}
|
|
139
|
-
result = candidate
|
|
81
|
+
result = candidate
|
|
140
82
|
}
|
|
141
|
-
return result
|
|
83
|
+
return result
|
|
142
84
|
};
|
|
143
85
|
|
|
144
|
-
const getProp = fieldName => {
|
|
86
|
+
const getProp = (fieldName: string) => {
|
|
145
87
|
const fields = fieldName.split('.');
|
|
146
88
|
return fields[fields.length - 1];
|
|
147
89
|
};
|
|
@@ -149,35 +91,15 @@ const getProp = fieldName => {
|
|
|
149
91
|
</script>
|
|
150
92
|
|
|
151
93
|
<template>
|
|
152
|
-
<form
|
|
153
|
-
|
|
154
|
-
@submit.prevent="handleSubmit"
|
|
155
|
-
>
|
|
156
|
-
<slot
|
|
157
|
-
v-if="loading"
|
|
158
|
-
name="loading"
|
|
159
|
-
>
|
|
94
|
+
<form class="form-maker" @submit.prevent="handleSubmit">
|
|
95
|
+
<slot v-if="loading" name="loading">
|
|
160
96
|
Loading...
|
|
161
97
|
</slot>
|
|
162
98
|
<slot>
|
|
163
|
-
<div
|
|
164
|
-
v-for="(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
>
|
|
168
|
-
<div
|
|
169
|
-
v-for="(field, j) in fieldRow"
|
|
170
|
-
:class="[realColumnClass, field.columnClass]"
|
|
171
|
-
:key="`field_${i}_${j}`"
|
|
172
|
-
>
|
|
173
|
-
<slot
|
|
174
|
-
:field="field"
|
|
175
|
-
:name="`${field.name}`"
|
|
176
|
-
>
|
|
177
|
-
<form-maker-input
|
|
178
|
-
v-model="getObject(field.name)[getProp(field.name)]"
|
|
179
|
-
v-bind="field"
|
|
180
|
-
/>
|
|
99
|
+
<div v-for="(fieldRow, i) in formFields" :class="realRowClass" :key="`fieldRow_${i}`">
|
|
100
|
+
<div v-for="(field, j) in fieldRow" :class="[realColumnClass, field.columnClass]" :key="`field_${i}_${j}`">
|
|
101
|
+
<slot :field="field" :name="`${field.name}`">
|
|
102
|
+
<form-maker-input v-model="getObject(field.name)[getProp(field.name)]" v-bind="field" />
|
|
181
103
|
</slot>
|
|
182
104
|
</div>
|
|
183
105
|
</div>
|
|
@@ -186,16 +108,9 @@ const getProp = fieldName => {
|
|
|
186
108
|
<slot name="divider">
|
|
187
109
|
<hr v-if="hasActions && !hideDivider">
|
|
188
110
|
</slot>
|
|
189
|
-
<slot
|
|
190
|
-
v-if="hasActions"
|
|
191
|
-
name="actions"
|
|
192
|
-
>
|
|
111
|
+
<slot v-if="hasActions" name="actions">
|
|
193
112
|
<slot name="submit-button">
|
|
194
|
-
<button
|
|
195
|
-
:class="realSubmitButtonClass"
|
|
196
|
-
:disabled="loading"
|
|
197
|
-
type="submit"
|
|
198
|
-
>
|
|
113
|
+
<button :class="realSubmitButtonClass" :disabled="loading" type="submit">
|
|
199
114
|
{{ submitButtonText }}
|
|
200
115
|
</button>
|
|
201
116
|
</slot>
|
|
@@ -1,23 +1,29 @@
|
|
|
1
|
-
<script setup>
|
|
1
|
+
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue';
|
|
3
|
+
import RuleEvaluator from './RuleEvaluator.vue';
|
|
4
|
+
import useFormClasses from '../composables/useFormClasses';
|
|
3
5
|
import useValidator from '../composables/useValidator';
|
|
4
6
|
import useVModel from '../composables/useVModel';
|
|
5
|
-
import {
|
|
7
|
+
import type { FormMakerInputProps } from 'lib/model';
|
|
6
8
|
|
|
7
9
|
defineOptions({
|
|
8
10
|
inheritAttrs: false,
|
|
9
11
|
});
|
|
10
12
|
|
|
11
|
-
const props = defineProps({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
const props = withDefaults(defineProps<FormMakerInputProps>(), {
|
|
14
|
+
loading: false,
|
|
15
|
+
disabled: false,
|
|
16
|
+
error: undefined,
|
|
17
|
+
helpText: undefined,
|
|
18
|
+
id: undefined,
|
|
19
|
+
label: undefined,
|
|
20
|
+
placeholder: undefined,
|
|
21
|
+
rules: () => [],
|
|
22
|
+
type: 'text'
|
|
23
|
+
})
|
|
24
|
+
const emit = defineEmits([ 'update:modelValue' ]);
|
|
19
25
|
|
|
20
|
-
const value = useVModel(props, emit);
|
|
26
|
+
const value = useVModel(() => props.modelValue, emit);
|
|
21
27
|
|
|
22
28
|
const {
|
|
23
29
|
labelClass,
|
|
@@ -27,7 +33,7 @@ const {
|
|
|
27
33
|
inputErrorClass,
|
|
28
34
|
errorClass,
|
|
29
35
|
helpTextClass,
|
|
30
|
-
} =
|
|
36
|
+
} = useFormClasses();
|
|
31
37
|
|
|
32
38
|
const hasLabel = computed(() => Boolean(props.label));
|
|
33
39
|
const hasHelpText = computed(() => Boolean(props.helpText));
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { RuleValidator } from 'lib/model';
|
|
3
|
+
import { watch } from 'vue';
|
|
4
|
+
|
|
5
|
+
interface RuleEvaluatorProps {
|
|
6
|
+
rules?: RuleValidator[]
|
|
7
|
+
modelValue: any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(defineProps<RuleEvaluatorProps>(), {
|
|
11
|
+
rules: () => ([]),
|
|
12
|
+
modelValue: undefined,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const emit = defineEmits(['update:modelValue'])
|
|
16
|
+
|
|
17
|
+
watch(
|
|
18
|
+
props.modelValue,
|
|
19
|
+
(newVal) => {
|
|
20
|
+
let error = null;
|
|
21
|
+
const nRules = props.rules?.length ?? 0;
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < nRules; i += 1) {
|
|
24
|
+
const rule = props.rules[i];
|
|
25
|
+
const validator = rule.validator(newVal);
|
|
26
|
+
if (!validator) {
|
|
27
|
+
error = rule.message;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
emit('update:modelValue', error);
|
|
32
|
+
},
|
|
33
|
+
{ immediate: true }
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
</script>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { h } from "vue"
|
|
2
|
+
import type { SetupContext } from "vue";
|
|
3
|
+
|
|
4
|
+
type SimpleComponentProps = {
|
|
5
|
+
as?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function SimpleComponent(
|
|
9
|
+
props: SimpleComponentProps,
|
|
10
|
+
context: SetupContext
|
|
11
|
+
) {
|
|
12
|
+
return h(props.as, context.attrs, context.slots);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
SimpleComponent.props = {
|
|
16
|
+
as: {
|
|
17
|
+
type: String,
|
|
18
|
+
required: false,
|
|
19
|
+
default: 'div'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default SimpleComponent
|
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
<script setup>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { FormMakerInputProps } from 'lib/model';
|
|
2
3
|
import useVModel from '../../composables/useVModel';
|
|
3
|
-
import { FormInputMixin } from './FormInputMixin.js';
|
|
4
4
|
|
|
5
|
-
const props = defineProps(
|
|
6
|
-
|
|
5
|
+
const props = withDefaults(defineProps<FormMakerInputProps>(), {
|
|
6
|
+
loading: false,
|
|
7
|
+
disabled: false,
|
|
8
|
+
error: undefined,
|
|
9
|
+
helpText: undefined,
|
|
10
|
+
id: undefined,
|
|
11
|
+
label: undefined,
|
|
12
|
+
placeholder: undefined,
|
|
13
|
+
rules: () => [],
|
|
14
|
+
type: 'text'
|
|
15
|
+
});
|
|
16
|
+
const emit = defineEmits(['update:modelValue']);
|
|
7
17
|
|
|
8
|
-
const value = useVModel(props, emit);
|
|
18
|
+
const value = useVModel(() => props.modelValue, emit);
|
|
9
19
|
</script>
|
|
10
20
|
|
|
11
21
|
<template>
|
|
12
|
-
<input
|
|
13
|
-
v-model="value"
|
|
14
|
-
:type="type"
|
|
15
|
-
v-bind="$props"
|
|
16
|
-
>
|
|
22
|
+
<input v-model="value" :type="type" v-bind="{ ...$props, ...$attrs }">
|
|
17
23
|
</template>
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { computed,
|
|
3
|
-
import {
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, type ComputedRef } from 'vue';
|
|
3
|
+
import type { FormMakerInputProps, SelectOption } from 'lib/model';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
});
|
|
9
|
-
const emit = defineEmits(FormInputMixin.emits);
|
|
5
|
+
interface CheckInputProps extends /* @vue-ignore */ FormMakerInputProps {
|
|
6
|
+
options?: boolean | SelectOption[]
|
|
7
|
+
}
|
|
10
8
|
|
|
11
|
-
const
|
|
9
|
+
const props = withDefaults(defineProps<CheckInputProps>(), {
|
|
10
|
+
loading: false,
|
|
11
|
+
disabled: false,
|
|
12
|
+
error: undefined,
|
|
13
|
+
helpText: undefined,
|
|
14
|
+
id: undefined,
|
|
15
|
+
label: undefined,
|
|
16
|
+
placeholder: undefined,
|
|
17
|
+
rules: () => [],
|
|
18
|
+
options: () => []
|
|
19
|
+
});
|
|
20
|
+
const emit = defineEmits(['update:modelValue'])
|
|
12
21
|
|
|
13
|
-
const isBinary = computed(() =>
|
|
22
|
+
const isBinary = computed(() => {
|
|
23
|
+
return Array.isArray(props.options) && props.options.length === 0
|
|
24
|
+
})
|
|
14
25
|
|
|
15
26
|
const val = computed(() => props.modelValue);
|
|
16
27
|
|
|
@@ -19,13 +30,13 @@ const selectedOptions = computed(() => {
|
|
|
19
30
|
return arr.filter(x => !!x);
|
|
20
31
|
});
|
|
21
32
|
|
|
22
|
-
const fieldOptions = computed(() => {
|
|
33
|
+
const fieldOptions: ComputedRef<SelectOption[]> = computed(() => {
|
|
23
34
|
if (!isBinary.value) {
|
|
24
|
-
return options
|
|
35
|
+
return props.options as SelectOption[];
|
|
25
36
|
}
|
|
26
37
|
return [
|
|
27
38
|
{
|
|
28
|
-
label: label
|
|
39
|
+
label: props.label,
|
|
29
40
|
value: true,
|
|
30
41
|
},
|
|
31
42
|
];
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import {
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { FormMakerInputProps } from 'lib/model';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
withDefaults(defineProps<FormMakerInputProps>(), {
|
|
6
|
+
loading: false,
|
|
7
|
+
disabled: false,
|
|
8
|
+
error: undefined,
|
|
9
|
+
helpText: undefined,
|
|
10
|
+
id: undefined,
|
|
11
|
+
label: undefined,
|
|
12
|
+
placeholder: undefined,
|
|
13
|
+
rules: () => [],
|
|
14
|
+
});
|
|
15
|
+
const emit = defineEmits(['update:modelValue'])
|
|
6
16
|
|
|
7
17
|
const handleFileSelect = event => {
|
|
8
18
|
if (event.target.files.length) {
|
|
@@ -1,17 +1,26 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import {
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { FormMakerInputProps, SelectOption } from 'lib/model';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
type: Array,
|
|
8
|
-
default: () => [],
|
|
9
|
-
},
|
|
10
|
-
});
|
|
4
|
+
interface RadioInputProps extends FormMakerInputProps {
|
|
5
|
+
options?: SelectOption[]
|
|
6
|
+
}
|
|
11
7
|
|
|
12
|
-
|
|
8
|
+
withDefaults(defineProps<RadioInputProps>(), {
|
|
9
|
+
loading: false,
|
|
10
|
+
disabled: false,
|
|
11
|
+
error: undefined,
|
|
12
|
+
helpText: undefined,
|
|
13
|
+
id: undefined,
|
|
14
|
+
label: undefined,
|
|
15
|
+
placeholder: undefined,
|
|
16
|
+
options: () => [],
|
|
17
|
+
rules: () => [],
|
|
18
|
+
});
|
|
19
|
+
const emit = defineEmits(['update:modelValue'])
|
|
13
20
|
|
|
14
|
-
const handleClick =
|
|
21
|
+
const handleClick = (value: any) => {
|
|
22
|
+
emit('update:modelValue', value)
|
|
23
|
+
}
|
|
15
24
|
</script>
|
|
16
25
|
|
|
17
26
|
<template>
|
|
@@ -25,7 +34,7 @@ const handleClick = e => emit('update:modelValue', e.target.value);
|
|
|
25
34
|
:checked="option.value === modelValue"
|
|
26
35
|
:value="option.value"
|
|
27
36
|
type="radio"
|
|
28
|
-
@change="handleClick"
|
|
37
|
+
@change="handleClick(option.value)"
|
|
29
38
|
>
|
|
30
39
|
{{ option.label }}
|
|
31
40
|
</label>
|
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
<script setup>
|
|
1
|
+
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue';
|
|
3
|
-
import { FormInputMixin } from './FormInputMixin.js';
|
|
4
3
|
import useVModel from '../../composables/useVModel';
|
|
4
|
+
import type { FormMakerInputProps, SelectOption } from 'lib/model';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
default: () => [],
|
|
11
|
-
},
|
|
12
|
-
optionGroups: {
|
|
13
|
-
type: Object,
|
|
14
|
-
default: () => ({}),
|
|
15
|
-
},
|
|
16
|
-
});
|
|
6
|
+
interface SelectInputProps extends FormMakerInputProps {
|
|
7
|
+
options?: SelectOption[],
|
|
8
|
+
optionGroups?: Record<string, SelectOption[]>
|
|
9
|
+
}
|
|
17
10
|
|
|
18
|
-
const
|
|
11
|
+
const props = withDefaults(defineProps<SelectInputProps>(), {
|
|
12
|
+
loading: false,
|
|
13
|
+
disabled: false,
|
|
14
|
+
error: undefined,
|
|
15
|
+
helpText: undefined,
|
|
16
|
+
id: undefined,
|
|
17
|
+
label: undefined,
|
|
18
|
+
placeholder: undefined,
|
|
19
|
+
options: () => [],
|
|
20
|
+
optionGroups: () => ({}),
|
|
21
|
+
rules: () => [],
|
|
22
|
+
});
|
|
23
|
+
const emit = defineEmits(['update:modelValue'])
|
|
19
24
|
|
|
20
|
-
const value = useVModel(props, emit);
|
|
25
|
+
const value = useVModel(() => props.modelValue, emit);
|
|
21
26
|
|
|
22
27
|
const hasGroups = Object.keys(props.optionGroups).length > 0;
|
|
23
28
|
|
|
@@ -47,11 +52,11 @@ const fixedOptions = computed(() => props.options.map(o => {
|
|
|
47
52
|
:label="key"
|
|
48
53
|
>
|
|
49
54
|
<option
|
|
50
|
-
v-for="
|
|
51
|
-
:key="`option_${
|
|
52
|
-
:value="
|
|
55
|
+
v-for="opt in opts"
|
|
56
|
+
:key="`option_${opt.value}`"
|
|
57
|
+
:value="opt.value"
|
|
53
58
|
>
|
|
54
|
-
{{
|
|
59
|
+
{{ opt.label }}
|
|
55
60
|
</option>
|
|
56
61
|
</optgroup>
|
|
57
62
|
</template>
|
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
<script setup>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { TextareaHTMLAttributes } from 'vue';
|
|
2
3
|
import useVModel from '../../composables/useVModel';
|
|
3
|
-
import { FormInputMixin } from './FormInputMixin.js';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
interface TextAreaProps extends /* @vue-ignore */ TextareaHTMLAttributes {
|
|
6
|
+
modelValue: any
|
|
7
|
+
}
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
+
const props = withDefaults(defineProps<TextAreaProps>(), {
|
|
10
|
+
disabled: false,
|
|
11
|
+
id: undefined,
|
|
12
|
+
placeholder: undefined,
|
|
13
|
+
});
|
|
14
|
+
const emit = defineEmits([ 'update:modelValue' ]);
|
|
15
|
+
|
|
16
|
+
const value = useVModel(() => props.modelValue, emit);
|
|
9
17
|
</script>
|
|
10
18
|
|
|
11
19
|
<template>
|
|
12
20
|
<textarea
|
|
13
21
|
:id="id"
|
|
14
22
|
v-model="value"
|
|
15
|
-
|
|
16
|
-
:name="name"
|
|
17
|
-
:placeholder="placeholder"
|
|
23
|
+
v-bind="{...$props, ...$attrs}"
|
|
18
24
|
/>
|
|
19
25
|
</template>
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { h } from 'vue';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return () => h('label', { ...attrs, for: props.id }, slots.default());
|
|
4
|
+
function FormMakerInputLabel(props, { slots, attrs }) {
|
|
5
|
+
return h('label', { ...attrs, for: props.id }, slots.default());
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
FormMakerInputLabel.props = {
|
|
9
|
+
id: {
|
|
10
|
+
type: String,
|
|
11
|
+
default: null,
|
|
13
12
|
},
|
|
14
13
|
};
|
|
14
|
+
|
|
15
|
+
export default FormMakerInputLabel;
|
|
15
16
|
</script>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { inject } from 'vue';
|
|
2
|
+
|
|
3
|
+
const useFormClasses = () => {
|
|
4
|
+
const labelClass = inject('labelClass', null);
|
|
5
|
+
const inputClass = inject('inputClass', null);
|
|
6
|
+
const inputWrapperClass = inject('inputWrapperClass', null);
|
|
7
|
+
const inputGroupClass = inject('inputGroupClass', null);
|
|
8
|
+
const inputErrorClass = inject('inputErrorClass', null);
|
|
9
|
+
const errorClass = inject('errorClass', null);
|
|
10
|
+
const helpTextClass = inject('helpTextClass', null);
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
labelClass,
|
|
14
|
+
inputClass,
|
|
15
|
+
inputWrapperClass,
|
|
16
|
+
inputGroupClass,
|
|
17
|
+
inputErrorClass,
|
|
18
|
+
errorClass,
|
|
19
|
+
helpTextClass,
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default useFormClasses;
|