inertia-bootstrap-forms 1.0.34 → 1.0.35

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.
@@ -1,9 +1,9 @@
1
1
  <script>
2
2
  import './css/from-select.scss';
3
3
  import Choices from 'choices.js';
4
- import {computed, inject} from "vue";
4
+ import {computed, defineComponent, inject} from "vue";
5
5
 
6
- export default {
6
+ export default defineComponent({
7
7
  emits: ['update:modelValue', 'search', 'change', 'selected'],
8
8
  props: {
9
9
  name: {
@@ -188,7 +188,7 @@ export default {
188
188
  },
189
189
  }
190
190
  }
191
- }
191
+ })
192
192
  </script>
193
193
  <template>
194
194
  <div class="select2-controller" :class="{
@@ -0,0 +1,144 @@
1
+ <script>
2
+ import {defineComponent, inject} from "vue";
3
+
4
+ export default defineComponent({
5
+ props: {
6
+ modelValue: '',
7
+ name: {
8
+ type: String,
9
+ required: true,
10
+ },
11
+ multiple: {
12
+ type: Boolean,
13
+ default: false,
14
+ },
15
+ endpoint: {
16
+ type: String,
17
+ default: '/upload',
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
+ return {form};
32
+ },
33
+ computed: {
34
+ allFiles() {
35
+ return this.files
36
+ },
37
+ },
38
+ methods: {
39
+ addFile(file) {
40
+ let uploadedFile = {
41
+ id: crypto.randomUUID(),
42
+ percent: 0,
43
+ error: 0,
44
+ file: file,
45
+ };
46
+
47
+ if (this.multiple) {
48
+ this.files.push(uploadedFile);
49
+ } else {
50
+ this.files = [uploadedFile];
51
+ }
52
+
53
+ this.uploadFile(uploadedFile);
54
+ this.$refs.input.value = '';
55
+ },
56
+ calculatePercent(event, file) {
57
+ if (event.lengthComputable) {
58
+ this.files.find(item => item.id === file.id)['percent'] = Math.round((event.loaded / event.total) * 100);
59
+ }
60
+ },
61
+ addFileToInputValue(file, res) {
62
+ this.files.find(item => item.id === file.id).path = res.data.path;
63
+
64
+ this.form[this.name] = this.multiple ? this.files.map(item => item.path) : this.files[0].path;
65
+ this.$emit('update:modelValue', this.form[this.name]);
66
+ },
67
+ async uploadFile(file) {
68
+ let _this = this;
69
+ let formData = new FormData();
70
+ formData.append('file', file.file);
71
+ _this.files.find(item => item.id === file.id)['error'] = '';
72
+
73
+ await fetch(this.endpoint,
74
+ {
75
+ method: 'POST',
76
+ headers: {
77
+ 'Accept': 'application/json',
78
+ },
79
+ body: formData,
80
+ },
81
+ )
82
+ .then(response => response.json())
83
+ .then(function (res) {
84
+ _this.addFileToInputValue(file, res)
85
+ }).catch(function (err) {
86
+ console.error('error on uploader', err);
87
+ _this.files.find(item => item.id === file.id)['error'] = (err.response?.data?.message || err.message);
88
+ });
89
+ },
90
+ async deleteFile(file) {
91
+ this.files = this.files.filter(item => item.id !== file.id);
92
+ await fetch(this.endpoint, {
93
+ method: 'DELETE',
94
+ body: file.path
95
+ });
96
+ },
97
+ fileSelected(e) {
98
+ Array.from(e.target.files).forEach(file => this.addFile(file));
99
+ }
100
+ },
101
+ data() {
102
+ return {
103
+ files: [],
104
+ }
105
+ }
106
+ })
107
+ </script>
108
+ <template>
109
+ <div class="file-input-uploader">
110
+ <input
111
+ ref="input"
112
+ :name="name"
113
+ :class="{'is-invalid': form?.errors[name] !== undefined}"
114
+ :disabled="form?.processing"
115
+ type="file"
116
+ :multiple="multiple"
117
+ @change="fileSelected"
118
+ class="form-control">
119
+ <div class="file-input-uploader--list">
120
+ <div :id="'file-'+file.id" class="file-input-uploader--list-item" v-for="file in allFiles">
121
+ <div class="file-input-uploader--progress" v-if="file.percent && file.percent< 100">
122
+ <div :style="{width: file.percent + '%'}"></div>
123
+ </div>
124
+ <div>{{ file.file.name }}</div>
125
+ <div class="file-input-uploader--list-error" v-if="file.error">{{ file.error }}</div>
126
+ <div class="file-input-uploader--list-item--size" dir="ltr">{{ Math.round(file.file.size / 1024) }}Kb</div>
127
+ <div class="file-input-uploader--list-item--actions">
128
+ <button @click="uploadFile(file)" type="button" class="file-input-uploader--list-item--btn" v-if="file.error">
129
+ <svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
130
+ <path
131
+ d="M1,12A11,11,0,0,1,17.882,2.7l1.411-1.41A1,1,0,0,1,21,2V6a1,1,0,0,1-1,1H16a1,1,0,0,1-.707-1.707l1.128-1.128A8.994,8.994,0,0,0,3,12a1,1,0,0,1-2,0Zm21-1a1,1,0,0,0-1,1,9.01,9.01,0,0,1-9,9,8.9,8.9,0,0,1-4.42-1.166l1.127-1.127A1,1,0,0,0,8,17H4a1,1,0,0,0-1,1v4a1,1,0,0,0,.617.924A.987.987,0,0,0,4,23a1,1,0,0,0,.707-.293L6.118,21.3A10.891,10.891,0,0,0,12,23,11.013,11.013,0,0,0,23,12,1,1,0,0,0,22,11Z"/>
132
+ </svg>
133
+ </button>
134
+ <button @click="deleteFile(file)" type="button" class="file-input-uploader--list-item--btn" v-if="file.path || file.error">
135
+ <svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
136
+ <path
137
+ d="M12,23A11,11,0,1,0,1,12,11.013,11.013,0,0,0,12,23ZM12,3a9,9,0,1,1-9,9A9.01,9.01,0,0,1,12,3ZM8.293,14.293,10.586,12,8.293,9.707A1,1,0,0,1,9.707,8.293L12,10.586l2.293-2.293a1,1,0,0,1,1.414,1.414L13.414,12l2.293,2.293a1,1,0,1,1-1.414,1.414L12,13.414,9.707,15.707a1,1,0,0,1-1.414-1.414Z"/>
138
+ </svg>
139
+ </button>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ </template>
@@ -1,7 +1,7 @@
1
1
  <script>
2
- import {inject} from 'vue';
2
+ import {defineComponent, inject} from 'vue';
3
3
 
4
- export default {
4
+ export default defineComponent({
5
5
  emits: ['update:modelValue'],
6
6
  props: {
7
7
  name: {
@@ -98,7 +98,7 @@ export default {
98
98
  isRTL: false,
99
99
  }
100
100
  }
101
- }
101
+ })
102
102
  </script>
103
103
  <template>
104
104
  <div class="star-rating">
@@ -1,13 +1,14 @@
1
1
  <script>
2
2
  import {Spinner} from 'vue3-bootstrap-components';
3
+ import {defineComponent} from "vue";
3
4
 
4
- export default {
5
+ export default defineComponent({
5
6
  components: {
6
7
  Spinner
7
8
  },
8
9
  inject: ['form'],
9
10
  props: {},
10
- }
11
+ })
11
12
  </script>
12
13
  <template>
13
14
  <button
package/src/TelInput.vue CHANGED
@@ -1,9 +1,9 @@
1
1
  <script>
2
2
  import {VueTelInput} from 'vue-tel-input';
3
3
  import 'vue-tel-input/vue-tel-input.css';
4
- import {inject} from "vue";
4
+ import {defineComponent, inject} from "vue";
5
5
 
6
- export default {
6
+ export default defineComponent({
7
7
  components: {
8
8
  VueTelInput
9
9
  },
@@ -44,7 +44,7 @@ export default {
44
44
  valid: null,
45
45
  }
46
46
  }
47
- }
47
+ })
48
48
  </script>
49
49
  <template>
50
50
  <div class="telephone-input input-group fanum" dir="ltr">
@@ -1,7 +1,7 @@
1
1
  <script>
2
- import {computed, inject} from "vue";
2
+ import {computed, defineComponent, inject} from "vue";
3
3
 
4
- export default {
4
+ export default defineComponent({
5
5
  props: {
6
6
  name: {
7
7
  type: String,
@@ -32,7 +32,7 @@ export default {
32
32
 
33
33
  return {modelValue, form, group};
34
34
  },
35
- }
35
+ })
36
36
  </script>
37
37
  <template>
38
38
  <textarea
package/src/TextInput.vue CHANGED
@@ -1,7 +1,7 @@
1
1
  <script>
2
- import {computed, inject} from "vue";
2
+ import {computed, inject, defineComponent} from "vue";
3
3
 
4
- export default {
4
+ export default defineComponent({
5
5
  props: {
6
6
  name: {
7
7
  type: String,
@@ -37,7 +37,7 @@ export default {
37
37
 
38
38
  return {modelValue, form, group};
39
39
  },
40
- }
40
+ })
41
41
  </script>
42
42
  <template>
43
43
  <input
@@ -0,0 +1,44 @@
1
+ .location-map-container {
2
+ position: relative;
3
+ width: 100%;
4
+ height: 300px;
5
+ overflow: hidden;
6
+ border-radius: var(--bs-border-radius);
7
+ }
8
+
9
+ .location-map-container.is-invalid {
10
+ border: 1px solid var(--bs-form-invalid-border-color);
11
+ }
12
+
13
+ .location-map-container[disabled],
14
+ .location-map-container.disabled:before {
15
+ content: "";
16
+ background-color: rgba(var(--bs-light-rgb), 0.4);
17
+ display: block;
18
+ position: absolute;
19
+ top: 0;
20
+ right: 0;
21
+ left: 0;
22
+ bottom: 0;
23
+ z-index: 9999;
24
+ }
25
+
26
+ .location-map-container {
27
+ .leaflet-pane,
28
+ .leaflet-tile,
29
+ .leaflet-marker-icon,
30
+ .leaflet-marker-shadow,
31
+ .leaflet-tile-container,
32
+ .leaflet-pane > svg,
33
+ .leaflet-pane > canvas,
34
+ .leaflet-zoom-box,
35
+ .leaflet-image-layer,
36
+ .leaflet-layer {
37
+ left: auto;
38
+ right: 0;
39
+ }
40
+
41
+ .leaflet-control-attribution.leaflet-control {
42
+ display: none;
43
+ }
44
+ }
@@ -0,0 +1,54 @@
1
+ .file-input-uploader .file-input-uploader--list .file-input-uploader--list-item {
2
+ background-color: var(--bs-secondary-bg);
3
+ border-radius: var(--bs-border-radius);
4
+ position: relative;
5
+ display: flex;
6
+ align-items: center;
7
+ margin: 5px 0;
8
+ padding: 5px 10px;
9
+ }
10
+
11
+ .file-input-uploader .file-input-uploader--list .file-input-uploader--list-item--size {
12
+ margin-left: auto;
13
+ font-size: 90%;
14
+ padding: 0 5px;
15
+ color: var(--bs-secondary-color);
16
+ }
17
+
18
+ .file-input-uploader .file-input-uploader--list-item--btn {
19
+ display: inline-block;
20
+ outline: none;
21
+ border: 0;
22
+ padding: 7px 2px;
23
+ }
24
+
25
+ .file-input-uploader .file-input-uploader--list-item--btn:not(:last-child){
26
+ margin-right: 5px;
27
+ }
28
+
29
+ .file-input-uploader .file-input-uploader--list-item--btn > svg {
30
+ height: 20px;
31
+ width: 20px;
32
+ vertical-align: middle;
33
+ }
34
+
35
+ .file-input-uploader .file-input-uploader--progress {
36
+ position: absolute;
37
+ top: 2px;
38
+ left: 5px;
39
+ right: 5px;
40
+ }
41
+
42
+ .file-input-uploader .file-input-uploader--progress > div {
43
+ background-color: #de0021;
44
+ height: 7px;
45
+ width: 0;
46
+ min-width: 1%;
47
+ border-radius: var(--bs-border-radius)
48
+ }
49
+
50
+ .file-input-uploader .file-input-uploader--list-error {
51
+ font-size: 90%;
52
+ margin: 0 5px;
53
+ color: var(--bs-danger, #de0021);
54
+ }
package/src/index.js CHANGED
@@ -22,6 +22,8 @@ import SubmitButton from "./SubmitButton.vue";
22
22
  import TelInput from "./TelInput.vue";
23
23
  import TextAreaInput from "./TextAreaInput.vue";
24
24
  import TextInput from "./TextInput.vue";
25
+ import DropzoneInput from "./DropzoneInput.vue";
26
+ import SimpleUploader from "./SimpleUploader.vue";
25
27
 
26
28
  export {
27
29
  AmountInput,
@@ -33,6 +35,8 @@ export {
33
35
  EmailInput,
34
36
  PersianDatePickerInput,
35
37
  EditorInput,
38
+ DropzoneInput,
39
+ SimpleUploader,
36
40
  GroupControl,
37
41
  FormContainer,
38
42
  LocationInput,
@@ -1,196 +0,0 @@
1
- <script>
2
- import {inject} from "vue";
3
-
4
- export default {
5
- props: {
6
- modelValue: '',
7
- name: {
8
- type: String,
9
- required: true,
10
- },
11
- multiple: {
12
- type: Boolean,
13
- default: false,
14
- },
15
- endpoint: {
16
- type: String,
17
- default: '/upload',
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
- return {form};
32
- },
33
- computed: {
34
- allFiles() {
35
- return this.files
36
- },
37
- },
38
- methods: {
39
- addFile(file) {
40
- let uploadedFile = {
41
- id: crypto.randomUUID(),
42
- percent: 0,
43
- error: 0,
44
- file: file,
45
- };
46
-
47
- if (this.multiple) {
48
- this.files.push(uploadedFile);
49
- } else {
50
- this.files = [uploadedFile];
51
- }
52
-
53
- this.uploadFile(uploadedFile);
54
- this.$refs.input.value = '';
55
- },
56
- calculatePercent(event, file) {
57
- if (event.lengthComputable) {
58
- this.files.find(item => item.id === file.id)['percent'] = Math.round((event.loaded / event.total) * 100);
59
- }
60
- },
61
- addFileToInputValue(file, res) {
62
- this.files.find(item => item.id === file.id).path = res.data.path;
63
-
64
- this.form[this.name] = this.multiple ? this.files.map(item => item.path) : this.files[0].path;
65
- this.$emit('update:modelValue', this.form[this.name]);
66
- },
67
- async uploadFile(file) {
68
- let _this = this;
69
- let formData = new FormData();
70
- formData.append('file', file.file);
71
-
72
- _this.files.find(item => item.id === file.id)['error'] = '';
73
-
74
- await axios.post(this.endpoint,
75
- formData, {
76
- headers: {
77
- 'Content-Type': 'multipart/form-data'
78
- },
79
- onUploadProgress: progressEvent => _this.calculatePercent(progressEvent, file)
80
- }
81
- ).then(function (res) {
82
- _this.addFileToInputValue(file, res)
83
- }).catch(function (err) {
84
- _this.files.find(item => item.id === file.id)['error'] = (err.response?.data?.message || err.message);
85
- });
86
- },
87
- async deleteFile(file) {
88
- this.files = this.files.filter(item => item.id !== file.id);
89
- await axios.delete(this.endpoint, {
90
- data: file.path
91
- });
92
- },
93
- fileSelected(e) {
94
- Array.from(e.target.files).forEach(file => this.addFile(file));
95
- }
96
- },
97
- data() {
98
- return {
99
- files: [],
100
- }
101
- }
102
- }
103
- </script>
104
- <template>
105
- <div class="file-input-uploader">
106
- <input
107
- ref="input"
108
- :name="name"
109
- :class="{'is-invalid': form?.errors[name] !== undefined}"
110
- :disabled="form?.processing"
111
- type="file"
112
- :multiple="multiple"
113
- @change="fileSelected"
114
- class="form-control">
115
- <div class="file-input-uploader--list">
116
- <div :id="'file-'+file.id" class="file-input-uploader--list-item" v-for="file in allFiles">
117
- <div class="file-input-uploader--progress" v-if="file.percent && file.percent< 100">
118
- <div :style="{width: file.percent + '%'}"></div>
119
- </div>
120
- <div>{{ file.file.name }}</div>
121
- <div class="file-input-uploader--list-error" v-if="file.error">{{ file.error }}</div>
122
- <div class="file-input-uploader--list-item--size" dir="ltr">{{ Math.round(file.file.size / 1024) }}Kb</div>
123
- <div class="file-input-uploader--list-item--actions">
124
- <button @click="uploadFile(file)" type="button" class="file-input-uploader--list-item--btn" v-if="file.error">
125
- <svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
126
- <path
127
- d="M1,12A11,11,0,0,1,17.882,2.7l1.411-1.41A1,1,0,0,1,21,2V6a1,1,0,0,1-1,1H16a1,1,0,0,1-.707-1.707l1.128-1.128A8.994,8.994,0,0,0,3,12a1,1,0,0,1-2,0Zm21-1a1,1,0,0,0-1,1,9.01,9.01,0,0,1-9,9,8.9,8.9,0,0,1-4.42-1.166l1.127-1.127A1,1,0,0,0,8,17H4a1,1,0,0,0-1,1v4a1,1,0,0,0,.617.924A.987.987,0,0,0,4,23a1,1,0,0,0,.707-.293L6.118,21.3A10.891,10.891,0,0,0,12,23,11.013,11.013,0,0,0,23,12,1,1,0,0,0,22,11Z"/>
128
- </svg>
129
- </button>
130
- <button @click="deleteFile(file)" type="button" class="file-input-uploader--list-item--btn" v-if="file.path || file.error">
131
- <svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
132
- <path
133
- d="M12,23A11,11,0,1,0,1,12,11.013,11.013,0,0,0,12,23ZM12,3a9,9,0,1,1-9,9A9.01,9.01,0,0,1,12,3ZM8.293,14.293,10.586,12,8.293,9.707A1,1,0,0,1,9.707,8.293L12,10.586l2.293-2.293a1,1,0,0,1,1.414,1.414L13.414,12l2.293,2.293a1,1,0,1,1-1.414,1.414L12,13.414,9.707,15.707a1,1,0,0,1-1.414-1.414Z"/>
134
- </svg>
135
- </button>
136
- </div>
137
- </div>
138
- </div>
139
- </div>
140
- </template>
141
- <style>
142
- .file-input-uploader .file-input-uploader--list .file-input-uploader--list-item {
143
- background-color: var(--bs-secondary-bg);
144
- border-radius: var(--bs-border-radius);
145
- position: relative;
146
- display: flex;
147
- align-items: center;
148
- margin: 5px 0;
149
- padding: 5px 10px;
150
- }
151
-
152
- .file-input-uploader .file-input-uploader--list .file-input-uploader--list-item--size {
153
- margin-left: auto;
154
- font-size: 90%;
155
- padding: 0 5px;
156
- color: var(--bs-secondary-color);
157
- }
158
-
159
- .file-input-uploader .file-input-uploader--list-item--btn {
160
- display: inline-block;
161
- outline: none;
162
- border: 0;
163
- padding: 7px 2px;
164
- }
165
-
166
- .file-input-uploader .file-input-uploader--list-item--btn:not(:last-child){
167
- margin-right: 5px;
168
- }
169
-
170
- .file-input-uploader .file-input-uploader--list-item--btn > svg {
171
- height: 20px;
172
- width: 20px;
173
- vertical-align: middle;
174
- }
175
-
176
- .file-input-uploader .file-input-uploader--progress {
177
- position: absolute;
178
- top: 2px;
179
- left: 5px;
180
- right: 5px;
181
- }
182
-
183
- .file-input-uploader .file-input-uploader--progress > div {
184
- background-color: #de0021;
185
- height: 7px;
186
- width: 0;
187
- min-width: 1%;
188
- border-radius: var(--bs-border-radius)
189
- }
190
-
191
- .file-input-uploader .file-input-uploader--list-error {
192
- font-size: 90%;
193
- margin: 0 5px;
194
- color: var(--bs-danger, #de0021);
195
- }
196
- </style>