inertia-bootstrap-forms 1.0.0 → 1.0.3
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/README.md +46 -0
- package/dist/css/from-select.scss +374 -0
- package/index.js +49 -0
- package/package.json +15 -1
- package/{Inputs → src}/AmountInput.vue +1 -2
- package/{Inputs → src}/CaptchaInput.vue +11 -6
- package/{Inputs/CheckboxInput.vue → src/CheckboxButtonInput.vue} +21 -8
- package/src/CheckboxInput.vue +79 -0
- package/src/CheckboxToggle.vue +109 -0
- package/{Inputs → src}/EditorInput.vue +1 -0
- package/{Inputs → src}/EmailInput.vue +1 -1
- package/{Inputs → src}/FormContainer.vue +22 -9
- package/src/GroupControl.vue +67 -0
- package/src/MultiQuantityInput.vue +68 -0
- package/src/PersianDatePickerInput.vue +176 -0
- package/src/QuantityInput.vue +106 -0
- package/src/SecondarySubmitButton.vue +22 -0
- package/src/Select2Input.vue +190 -0
- package/src/StarRatingInput.vue +158 -0
- package/{Inputs → src}/SubmitButton.vue +4 -2
- package/src/TextAreaInput.vue +44 -0
- package/src/TextInput.vue +51 -0
- package/src/locationInput.vue +124 -0
- package/Bootstrap/InputGroup.vue +0 -9
- package/Bootstrap/InputGroupText.vue +0 -9
- package/Inputs/DatePickerInput.vue +0 -137
- package/Inputs/Select2Input.vue +0 -193
- package/Inputs/TextAreaInput.vue +0 -33
- package/Inputs/TextInput.vue +0 -34
- package/Inputs/locationInput.vue +0 -122
- package/vue-select.css +0 -387
- /package/{Inputs → src}/FileInput.vue +0 -0
- /package/{Inputs → src}/FormLabel.vue +0 -0
- /package/{Inputs → src}/MobileInput.vue +0 -0
- /package/{Inputs → src}/PasswordInput.vue +0 -0
- /package/{Inputs → src}/TelInput.vue +0 -0
- /package/{Inputs → src}/countryCodes.js +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import {computed, inject} from "vue";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
props: {
|
|
6
|
+
name: {
|
|
7
|
+
type: String,
|
|
8
|
+
required: true,
|
|
9
|
+
},
|
|
10
|
+
id: {
|
|
11
|
+
type: String,
|
|
12
|
+
default: '',
|
|
13
|
+
required: false,
|
|
14
|
+
},
|
|
15
|
+
value: {
|
|
16
|
+
type: [String, Number],
|
|
17
|
+
default: 'yes',
|
|
18
|
+
required: false,
|
|
19
|
+
},
|
|
20
|
+
type: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: 'checkbox',
|
|
23
|
+
required: false,
|
|
24
|
+
},
|
|
25
|
+
hideInput: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: true,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
computed: {
|
|
31
|
+
inputID() {
|
|
32
|
+
return this.form.getID(this) + (this.value || '');
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
setup(props) {
|
|
36
|
+
let form = inject('form', {
|
|
37
|
+
errors: {},
|
|
38
|
+
getID(name) {
|
|
39
|
+
return name;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
let group = inject('group', {});
|
|
43
|
+
|
|
44
|
+
const modelValue = computed({
|
|
45
|
+
get() {
|
|
46
|
+
return (group.value && form.value[group.value.name]) ? group.value?.getData(props.name) : form.value[props.name];
|
|
47
|
+
},
|
|
48
|
+
set(value) {
|
|
49
|
+
if (group?.value?.name) {
|
|
50
|
+
group.value.setData(props.name, value);
|
|
51
|
+
} else {
|
|
52
|
+
form.value[props.name] = value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return {modelValue, form, group};
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
</script>
|
|
61
|
+
<template>
|
|
62
|
+
<label class="form-check-toggle" :class="{'form-check-toggle--active': modelValue === value}" :for="inputID">
|
|
63
|
+
<input
|
|
64
|
+
:name="name + (group ? '_' + group?.name + '-'+group?.groupID : '')"
|
|
65
|
+
:id="inputID"
|
|
66
|
+
v-model="modelValue"
|
|
67
|
+
:class="{'is-invalid': form?.errors[name], 'form-check-toggle--input-hide': hideInput}"
|
|
68
|
+
:disabled="form?.processing"
|
|
69
|
+
:type="type"
|
|
70
|
+
:value="value"
|
|
71
|
+
@change="e => $emit('change', e)"
|
|
72
|
+
class="form-check-toggle--input form-check-input">
|
|
73
|
+
<slot/>
|
|
74
|
+
</label>
|
|
75
|
+
</template>
|
|
76
|
+
<style>
|
|
77
|
+
.form-check-toggle {
|
|
78
|
+
position: relative;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
display: block;
|
|
81
|
+
background-color: var(--bs-body-bg, #ffffff);
|
|
82
|
+
border-radius: var(--bs-border-radius, 1rem);
|
|
83
|
+
min-width: 100px;
|
|
84
|
+
width: 100%;
|
|
85
|
+
padding: 0.5rem 0.75rem;
|
|
86
|
+
font-size: 0.97rem;
|
|
87
|
+
font-weight: 400;
|
|
88
|
+
line-height: 1.7;
|
|
89
|
+
color: var(--bs-body-color, #000000);
|
|
90
|
+
-webkit-appearance: none;
|
|
91
|
+
-moz-appearance: none;
|
|
92
|
+
appearance: none;
|
|
93
|
+
background-clip: padding-box;
|
|
94
|
+
border: var(--bs-border-width, 1px) solid var(--bs-border-color, #eeeeee);
|
|
95
|
+
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.form-check-toggle.form-check-toggle--active {
|
|
99
|
+
background-color: var(--bs-warning-bg-subtle, #ffda6a);
|
|
100
|
+
border-color: var(--bs-alert-border-color, #fff0c3);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.form-check-toggle .form-check-toggle--input-hide {
|
|
104
|
+
visibility: hidden;
|
|
105
|
+
position: absolute;
|
|
106
|
+
top: 0;
|
|
107
|
+
right: 0;
|
|
108
|
+
}
|
|
109
|
+
</style>
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import {useForm} from "@inertiajs/vue3";
|
|
3
3
|
import {computed, reactive, toRef} from "vue";
|
|
4
|
-
import
|
|
5
|
-
import Alert from "@/Bootstrap/Alert.vue";
|
|
4
|
+
import {Alert} from "vue3-bootstrap-components";
|
|
6
5
|
|
|
7
6
|
export default {
|
|
8
7
|
components: {Alert},
|
|
@@ -37,8 +36,12 @@ export default {
|
|
|
37
36
|
const formData = reactive(props.modelValue);
|
|
38
37
|
const form = useForm(formData);
|
|
39
38
|
|
|
40
|
-
form.getID = function (
|
|
41
|
-
|
|
39
|
+
form.getID = function (el) {
|
|
40
|
+
if (typeof el === String) {
|
|
41
|
+
return (formEl.value?.id ? formEl.value?.id + '-' : '') + '-' + el;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return (formEl.value?.id ? formEl.value?.id + '-' : '') + ((el.group ? el.group?.name + '-' + el.group?.groupID + '-' : '')) + el.name + (el.value ? '-' + el.value : '');
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
return {form, formData, formEl};
|
|
@@ -70,7 +73,7 @@ export default {
|
|
|
70
73
|
}
|
|
71
74
|
},
|
|
72
75
|
methods: {
|
|
73
|
-
reset(){
|
|
76
|
+
reset() {
|
|
74
77
|
this.form.reset();
|
|
75
78
|
},
|
|
76
79
|
async submit(event) {
|
|
@@ -81,10 +84,20 @@ export default {
|
|
|
81
84
|
} else {
|
|
82
85
|
this.$emit('submit', event);
|
|
83
86
|
await this.form.transform(function (formDataValues) {
|
|
84
|
-
|
|
87
|
+
|
|
88
|
+
let data = JSON.stringify({
|
|
85
89
|
...formValues,
|
|
86
90
|
...formDataValues,
|
|
87
|
-
})
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const persianDigits = [/۰/g, /۱/g, /۲/g, /۳/g, /۴/g, /۵/g, /۶/g, /۷/g, /۸/g, /۹/g];
|
|
94
|
+
const arabicDigits = [/٠/g, /١/g, /٢/g, /٣/g, /٤/g, /٥/g, /٦/g, /٧/g, /٨/g, /٩/g];
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < 10; i++) {
|
|
97
|
+
data = data.replace(persianDigits[i], i).replace(arabicDigits[i], i);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return JSON.parse(data.toLocaleString('en-US'));
|
|
88
101
|
}).submit(this.method.toString(), this.url, {
|
|
89
102
|
only: this.only,
|
|
90
103
|
onStart: () => {
|
|
@@ -119,8 +132,8 @@ export default {
|
|
|
119
132
|
:novalidate="!!Object.values(form.errors).length">
|
|
120
133
|
<slot name="errors" v-if="form.hasErrors" :form="form">
|
|
121
134
|
<Alert type="danger">
|
|
122
|
-
<ul class="list-unstyled p-0 m-0">
|
|
123
|
-
<li v-for="error in form.errors">{{error}}</li>
|
|
135
|
+
<ul class="list-unstyled p-0 m-0 fanum">
|
|
136
|
+
<li v-for="error in form.errors">{{ error }}</li>
|
|
124
137
|
</ul>
|
|
125
138
|
</Alert>
|
|
126
139
|
</slot>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import {getCurrentInstance, computed, inject, ref, toRef, onMounted} from "vue";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
props: {
|
|
6
|
+
name: {
|
|
7
|
+
type: String,
|
|
8
|
+
required: true,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
setup(props, context) {
|
|
12
|
+
let form = inject('form', {
|
|
13
|
+
errors: {},
|
|
14
|
+
getID(name) {
|
|
15
|
+
return name;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return {form};
|
|
20
|
+
},
|
|
21
|
+
provide() {
|
|
22
|
+
return {
|
|
23
|
+
group: computed(() => this)
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
mounted() {
|
|
27
|
+
this.$refs.groupEl?.parentNode?.parentNode.querySelectorAll('.form-control-group').forEach((item, index) => {
|
|
28
|
+
if(item === this.$refs.groupEl){
|
|
29
|
+
this.groupID = (index).toString();
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
},
|
|
33
|
+
methods: {
|
|
34
|
+
setData(fieldName, value) {
|
|
35
|
+
if (!this.form[this.name]) {
|
|
36
|
+
this.form[this.name] = {};
|
|
37
|
+
}
|
|
38
|
+
if (this.groupID && this.form[this.name]?.length >= 0) {
|
|
39
|
+
if(!this.form[this.name][this.groupID]){
|
|
40
|
+
this.form[this.name][this.groupID] = {};
|
|
41
|
+
}
|
|
42
|
+
this.form[this.name][this.groupID][fieldName] = value;
|
|
43
|
+
}else{
|
|
44
|
+
this.form[this.name][fieldName] = value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
},
|
|
48
|
+
getData(fieldName) {
|
|
49
|
+
if (this.groupID && this.form[this.name]?.length >= 0) {
|
|
50
|
+
return this.form[this.name][this.groupID]?.[fieldName] || null;
|
|
51
|
+
}else{
|
|
52
|
+
return this.form[this.name][fieldName];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
data() {
|
|
57
|
+
return {
|
|
58
|
+
groupID: '0',
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
<template>
|
|
64
|
+
<div class="form-control-group" :data-group-id="groupID" ref="groupEl">
|
|
65
|
+
<slot/>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import {Dropdown, DropdownToggle, DropdownMenu, InputGroup, InputGroupText} from 'vue3-bootstrap-components';
|
|
3
|
+
import {inject} from "vue";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
components: {InputGroup, InputGroupText, Dropdown, DropdownToggle, DropdownMenu},
|
|
7
|
+
props: {
|
|
8
|
+
name: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
required: Boolean,
|
|
13
|
+
disabled: Boolean,
|
|
14
|
+
readonly: Boolean,
|
|
15
|
+
unit: {
|
|
16
|
+
type: String,
|
|
17
|
+
default: 'عدد'
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
setup(props) {
|
|
21
|
+
let form = inject('form');
|
|
22
|
+
|
|
23
|
+
if (form === undefined) {
|
|
24
|
+
form = {
|
|
25
|
+
errors: {},
|
|
26
|
+
getID(name) {
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if(!form[props.name]) {
|
|
32
|
+
form[props.name] = 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {form};
|
|
36
|
+
},
|
|
37
|
+
methods: {
|
|
38
|
+
onChange(event) {
|
|
39
|
+
let value = parseFloat(this.$number.toEnglish(event.detail?.unmasked)) || 1;
|
|
40
|
+
this.form[this.name] = value;
|
|
41
|
+
this.$emit('update:modelValue', value);
|
|
42
|
+
},
|
|
43
|
+
increment() {
|
|
44
|
+
if (!this.max || (this.max < this.form[this.name])) {
|
|
45
|
+
this.form[this.name]++;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
decrement() {
|
|
49
|
+
if ((!this.min || (this.min < this.form[this.name])) && this.form[this.name] > 1) {
|
|
50
|
+
this.form[this.name]--;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
data() {
|
|
55
|
+
return {}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
59
|
+
<template>
|
|
60
|
+
<Dropdown>
|
|
61
|
+
<DropdownToggle>adasd</DropdownToggle>
|
|
62
|
+
<DropdownMenu>
|
|
63
|
+
asdasd
|
|
64
|
+
</DropdownMenu>
|
|
65
|
+
</Dropdown>
|
|
66
|
+
</template>
|
|
67
|
+
<style>
|
|
68
|
+
</style>
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Vue3PersianDatetimePicker from 'vue3-persian-datetime-picker';
|
|
3
|
+
import {computed, inject} from "vue";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
components: {Vue3PersianDatetimePicker},
|
|
7
|
+
props: {
|
|
8
|
+
name: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
calendar: {
|
|
13
|
+
type: String,
|
|
14
|
+
default: 'date',
|
|
15
|
+
},
|
|
16
|
+
view: {
|
|
17
|
+
type: String,
|
|
18
|
+
default: 'date',
|
|
19
|
+
},
|
|
20
|
+
min: String,
|
|
21
|
+
max: String,
|
|
22
|
+
range: Boolean,
|
|
23
|
+
locale: {
|
|
24
|
+
default: 'fa',
|
|
25
|
+
},
|
|
26
|
+
format: {
|
|
27
|
+
type: String,
|
|
28
|
+
default: 'jYYYY-jMM-jDD',
|
|
29
|
+
},
|
|
30
|
+
inputFormat: {
|
|
31
|
+
type: String,
|
|
32
|
+
default: null,
|
|
33
|
+
},
|
|
34
|
+
placeholder: String,
|
|
35
|
+
},
|
|
36
|
+
emits: ['update:modelValue'],
|
|
37
|
+
setup(props) {
|
|
38
|
+
let form = inject('form', {
|
|
39
|
+
errors: {},
|
|
40
|
+
getID(name) {
|
|
41
|
+
return name;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
let group = inject('group', {});
|
|
45
|
+
|
|
46
|
+
const modelValue = computed({
|
|
47
|
+
get() {
|
|
48
|
+
return (group.value && form.value[group.value.name]) ? group.value?.getData(props.name) : form.value[props.name];
|
|
49
|
+
},
|
|
50
|
+
set(value) {
|
|
51
|
+
if (group?.value?.name) {
|
|
52
|
+
group.value.setData(props.name, value);
|
|
53
|
+
} else {
|
|
54
|
+
form.value[props.name] = value;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return {modelValue, form, group};
|
|
60
|
+
},
|
|
61
|
+
methods: {
|
|
62
|
+
clear() {
|
|
63
|
+
this.modelValue = null;
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
computed: {
|
|
67
|
+
isSsr() {
|
|
68
|
+
return !window || !document;
|
|
69
|
+
},
|
|
70
|
+
inputID() {
|
|
71
|
+
return this.form.getID(this)
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
data() {
|
|
75
|
+
return {}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<template>
|
|
81
|
+
<div class="input-group">
|
|
82
|
+
<input
|
|
83
|
+
:name="name"
|
|
84
|
+
:id="inputID"
|
|
85
|
+
:value="modelValue"
|
|
86
|
+
:placeholder="(placeholder || 'انتخاب تاریخ')"
|
|
87
|
+
:class="{'is-invalid': form.errors[name]}"
|
|
88
|
+
:disabled="form?.processing"
|
|
89
|
+
type="text" class="form-control form-control--datepicker text-start fanum">
|
|
90
|
+
<button
|
|
91
|
+
type="button"
|
|
92
|
+
@click="clear"
|
|
93
|
+
class="input-group-text input-group-datepicker-delete"
|
|
94
|
+
:class="{'input-group-datepicker-delete-show': modelValue}">
|
|
95
|
+
<svg width="25px" height="25px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
96
|
+
<path d="M14 22H10C6.22876 22 4.34315 22 3.17157 20.8284C2 19.6569 2 17.7712 2 14V12C2 8.22876 2 6.34315 3.17157 5.17157C4.34315 4 6.22876 4 10 4H14C17.7712 4 19.6569 4 20.8284 5.17157C22 6.34315 22 8.22876 22 12V14C22 17.7712 22 19.6569 20.8284 20.8284C20.1752 21.4816 19.3001 21.7706 18 21.8985" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
|
97
|
+
<path d="M7 4V2.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
|
98
|
+
<path d="M17 4V2.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
|
99
|
+
<path d="M21.5 9H16.625H10.75M2 9H5.875" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
|
100
|
+
<path d="M18 17C18 17.5523 17.5523 18 17 18C16.4477 18 16 17.5523 16 17C16 16.4477 16.4477 16 17 16C17.5523 16 18 16.4477 18 17Z" fill="#1C274C"/>
|
|
101
|
+
<path d="M18 13C18 13.5523 17.5523 14 17 14C16.4477 14 16 13.5523 16 13C16 12.4477 16.4477 12 17 12C17.5523 12 18 12.4477 18 13Z" fill="#1C274C"/>
|
|
102
|
+
<path d="M13 17C13 17.5523 12.5523 18 12 18C11.4477 18 11 17.5523 11 17C11 16.4477 11.4477 16 12 16C12.5523 16 13 16.4477 13 17Z" fill="#1C274C"/>
|
|
103
|
+
<path d="M13 13C13 13.5523 12.5523 14 12 14C11.4477 14 11 13.5523 11 13C11 12.4477 11.4477 12 12 12C12.5523 12 13 12.4477 13 13Z" fill="#1C274C"/>
|
|
104
|
+
<path d="M8 17C8 17.5523 7.55228 18 7 18C6.44772 18 6 17.5523 6 17C6 16.4477 6.44772 16 7 16C7.55228 16 8 16.4477 8 17Z" fill="#1C274C"/>
|
|
105
|
+
<path d="M8 13C8 13.5523 7.55228 14 7 14C6.44772 14 6 13.5523 6 13C6 12.4477 6.44772 12 7 12C7.55228 12 8 12.4477 8 13Z" fill="#1C274C"/>
|
|
106
|
+
</svg>
|
|
107
|
+
</button>
|
|
108
|
+
</div>
|
|
109
|
+
<Vue3PersianDatetimePicker
|
|
110
|
+
:type="calendar"
|
|
111
|
+
:view="view"
|
|
112
|
+
:min="min"
|
|
113
|
+
:max="max"
|
|
114
|
+
v-if="!isSsr"
|
|
115
|
+
jumpminute="15"
|
|
116
|
+
:range="range"
|
|
117
|
+
:locale="locale"
|
|
118
|
+
:simple="false"
|
|
119
|
+
:roundminute="true"
|
|
120
|
+
:showNowBtn="true"
|
|
121
|
+
:autoSubmit="true"
|
|
122
|
+
:format="format"
|
|
123
|
+
:inputFormat="(inputFormat ? inputFormat : format)"
|
|
124
|
+
:displayFormat="format"
|
|
125
|
+
v-model="modelValue"
|
|
126
|
+
:custom-input="'#'+inputID"/>
|
|
127
|
+
</template>
|
|
128
|
+
<style>
|
|
129
|
+
.form-control--datepicker {
|
|
130
|
+
direction: rtl;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.input-group-datepicker-delete {
|
|
134
|
+
width: 42px;
|
|
135
|
+
text-align: center;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.input-group-datepicker-delete .fa-times {
|
|
139
|
+
display: none;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.input-group-datepicker-delete-show:hover .fa-times {
|
|
143
|
+
display: block;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.input-group-datepicker-delete-show:hover .fa-calendars {
|
|
147
|
+
display: none;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.vpd-content {
|
|
151
|
+
color: var(--bs-body-color) !important;
|
|
152
|
+
background-color: var(--bs-body-bg) !important;
|
|
153
|
+
-moz-font-feature-settings: "ss01";
|
|
154
|
+
-webkit-font-feature-settings: "ss01";
|
|
155
|
+
font-feature-settings: "ss01";
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.vpd-time .vpd-down-arrow-btn, .vpd-time .vpd-up-arrow-btn {
|
|
159
|
+
text-align: center;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.vpd-time .vpd-down-arrow-btn svg,
|
|
163
|
+
.vpd-time .vpd-up-arrow-btn svg {
|
|
164
|
+
margin: 0 auto;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.vpd-controls button {
|
|
168
|
+
display: flex;
|
|
169
|
+
align-items: center;
|
|
170
|
+
justify-content: center;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.vpd-month-label {
|
|
174
|
+
width: 110px;
|
|
175
|
+
}
|
|
176
|
+
</style>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import {InputGroup, InputGroupText} from 'vue3-bootstrap-components';
|
|
3
|
+
import {inject} from "vue";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
components: {InputGroup, InputGroupText},
|
|
7
|
+
props: {
|
|
8
|
+
name: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
required: Boolean,
|
|
13
|
+
disabled: Boolean,
|
|
14
|
+
readonly: Boolean,
|
|
15
|
+
unit: {
|
|
16
|
+
type: String,
|
|
17
|
+
default: 'عدد'
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
setup(props) {
|
|
21
|
+
let form = inject('form');
|
|
22
|
+
|
|
23
|
+
if (form === undefined) {
|
|
24
|
+
form = {
|
|
25
|
+
errors: {},
|
|
26
|
+
getID(name) {
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if(!form[props.name]) {
|
|
32
|
+
form[props.name] = 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {form};
|
|
36
|
+
},
|
|
37
|
+
methods: {
|
|
38
|
+
onChange(event) {
|
|
39
|
+
let value = parseFloat(this.$number.toEnglish(event.detail?.unmasked)) || 1;
|
|
40
|
+
this.form[this.name] = value;
|
|
41
|
+
this.$emit('update:modelValue', value);
|
|
42
|
+
},
|
|
43
|
+
increment() {
|
|
44
|
+
if (!this.max || (this.max < this.form[this.name])) {
|
|
45
|
+
this.form[this.name]++;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
decrement() {
|
|
49
|
+
if ((!this.min || (this.min < this.form[this.name])) && this.form[this.name] > 1) {
|
|
50
|
+
this.form[this.name]--;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
data() {
|
|
55
|
+
return {}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
59
|
+
<template>
|
|
60
|
+
<InputGroup class="input-group-quantity">
|
|
61
|
+
<button @click="increment" type="button" class="btn">
|
|
62
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
|
63
|
+
<path
|
|
64
|
+
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"/>
|
|
65
|
+
</svg>
|
|
66
|
+
</button>
|
|
67
|
+
<input
|
|
68
|
+
:name="name"
|
|
69
|
+
:value="form[name]"
|
|
70
|
+
v-maska
|
|
71
|
+
data-maska="###,###,###,###,###,###,###"
|
|
72
|
+
data-maska-reversed
|
|
73
|
+
@maska="onChange"
|
|
74
|
+
:class="{'is-invalid': form.errors[name]}"
|
|
75
|
+
:disabled="disabled || form.processing"
|
|
76
|
+
:readonly="readonly"
|
|
77
|
+
type="tel"
|
|
78
|
+
class="form-control fanum text-center">
|
|
79
|
+
<button @click="decrement" type="button" class="btn">
|
|
80
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
|
81
|
+
<path d="M432 256c0 17.7-14.3 32-32 32L48 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l352 0c17.7 0 32 14.3 32 32z"/>
|
|
82
|
+
</svg>
|
|
83
|
+
</button>
|
|
84
|
+
<InputGroupText class="fanum">{{ unit }}</InputGroupText>
|
|
85
|
+
<slot name="suffix"/>
|
|
86
|
+
</InputGroup>
|
|
87
|
+
</template>
|
|
88
|
+
<style>
|
|
89
|
+
|
|
90
|
+
.input-group-quantity .input-group-text,
|
|
91
|
+
.input-group-quantity .btn{
|
|
92
|
+
background-color: var(--bs-body-bg);
|
|
93
|
+
--bs-btn-hover-bg:var(--bs-secondary-bg);
|
|
94
|
+
--bs-btn-active-bg:var(--bs-secondary-bg);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.input-group-quantity input.form-control{
|
|
98
|
+
border: 0 !important;
|
|
99
|
+
box-shadow: none !important;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.input-group-quantity .btn svg {
|
|
103
|
+
width: 14px;
|
|
104
|
+
height: 14px;
|
|
105
|
+
}
|
|
106
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import {Spinner} from "vue3-bootstrap-components";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
components: {
|
|
6
|
+
Spinner
|
|
7
|
+
},
|
|
8
|
+
inject: ['form'],
|
|
9
|
+
props: {},
|
|
10
|
+
}
|
|
11
|
+
</script>
|
|
12
|
+
<template>
|
|
13
|
+
<button
|
|
14
|
+
type="submit"
|
|
15
|
+
:disabled="form?.processing"
|
|
16
|
+
class="btn btn-secondary px-3 px-sm-4">
|
|
17
|
+
<Spinner v-if="form?.processing"/>
|
|
18
|
+
<slot>
|
|
19
|
+
تایید و ثبت اطلاعات
|
|
20
|
+
</slot>
|
|
21
|
+
</button>
|
|
22
|
+
</template>
|