@farm-investimentos/front-mfe-components-vue3 1.1.0 → 1.1.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farm-investimentos/front-mfe-components-vue3",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,8 +22,8 @@
22
22
  "serve": "vue-cli-service serve",
23
23
  "serve:storybook": "http-server ./storybook-static/",
24
24
  "storybook": "storybook dev -p 6006",
25
- "test:coverage": "jest --coverage",
26
- "test:unit": "jest",
25
+ "test:coverage": "jest --coverage --runInBand",
26
+ "test:unit": "jest --runInBand",
27
27
  "prepare": "husky"
28
28
  },
29
29
  "browserslist": [
@@ -39,7 +39,7 @@
39
39
  "v-mask": "2.3.0",
40
40
  "v-money3": "^3.24.0",
41
41
  "vuetify": "3.5.7",
42
- "webpack": "5.89.0"
42
+ "webpack": "5.94.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@babel/core": "7.17.9",
@@ -1,5 +1,19 @@
1
1
  <template>
2
+ <farm-textfield-v2
3
+ v-if="readonly || disabled"
4
+ icon="calendar"
5
+ v-model="fieldRange"
6
+ autocomplete="off"
7
+ :readonly="readonly"
8
+ :ellipsed="multiple"
9
+ :mask="`${isReadonly ? '' : '##/##/####'}`"
10
+ :requiredMessage="requiredMessage"
11
+ :id="inputId"
12
+ :rules="rules"
13
+ :disabled="disabled"
14
+ />
2
15
  <farm-contextmenu
16
+ v-else
3
17
  stay-open
4
18
  v-model="menuField"
5
19
  ref="contextmenu"
@@ -24,7 +38,6 @@
24
38
  :start-date="internalPickerDate"
25
39
  :multi-dates="multiple"
26
40
  />
27
-
28
41
  <div class="picker__actions">
29
42
  <farm-btn
30
43
  plain
@@ -65,7 +78,7 @@
65
78
  :requiredMessage="requiredMessage"
66
79
  :id="inputId"
67
80
  :rules="rules"
68
- :disabled="true"
81
+ :disabled="disabled || readonly"
69
82
  @keyup="keyUpInput"
70
83
  />
71
84
  </template>
@@ -3,7 +3,7 @@
3
3
  <farm-btn v-if="hasCancel" color="primary" plain @click="$emit('onClose')">
4
4
  {{ closeLabel }}
5
5
  </farm-btn>
6
-
6
+
7
7
  <farm-btn
8
8
  v-for="button in extraButtons"
9
9
  :key="button.label"
@@ -11,16 +11,17 @@
11
11
  :outlined="button.outlined"
12
12
  :disabled="button.disabled"
13
13
  :title="button.label"
14
- @click="$emit(button.listener ? button.listener : '')"
14
+ @click="emitExtraButtonListener(button)"
15
15
  >
16
16
  {{ button.label }}
17
17
  </farm-btn>
18
+
18
19
  <farm-btn
19
20
  v-if="hasConfirm"
20
21
  :color="confirmColor"
21
22
  :disabled="isConfirmDisabled"
22
23
  :title="confirmLabel"
23
- @click="$emit('onConfirm')"
24
+ @click="emitConfirm"
24
25
  >
25
26
  <farm-icon v-if="confirmIcon">{{ confirmIcon }}</farm-icon>
26
27
  {{ confirmLabel }}
@@ -28,76 +29,70 @@
28
29
  </div>
29
30
  </template>
30
31
 
31
- <script lang="ts">
32
- import { PropType } from 'vue';
32
+ <script setup lang="ts">
33
+ import { PropType, defineEmits } from 'vue';
33
34
 
34
- import IExtraButton from './IExtraButton';
35
+ interface IExtraButton {
36
+ label: string;
37
+ color: string;
38
+ outlined: boolean;
39
+ disabled: boolean;
40
+ listener: Function | null;
41
+ }
35
42
 
36
- /**
37
- * Footer de dialog/modal
38
- */
39
- export default {
43
+ defineOptions({
40
44
  name: 'farm-dialog-footer',
41
- props: {
42
- /**
43
- * Label do botão de confirmação
44
- */
45
- confirmLabel: {
46
- type: String,
47
- default: 'Confirmar',
48
- },
49
- /**
50
- * Label do botão de fechar
51
- */
52
- closeLabel: {
53
- type: String,
54
- default: 'Fechar',
55
- },
56
- /**
57
- * Exibe/esconde botão de confirmação
58
- */
59
- hasConfirm: {
60
- type: Boolean,
61
- default: true,
62
- },
63
- /**
64
- * Exibe/esconde botão de cancelar
65
- */
66
- hasCancel: {
67
- type: Boolean,
68
- default: true,
69
- },
70
- /**
71
- * Cor do botão de confirmação - usa as do tema do vuetify
72
- */
73
- confirmColor: {
74
- type: String,
75
- default: 'primary',
76
- },
77
- /**
78
- * Ícone no botão Confirmar
79
- */
80
- confirmIcon: {
81
- type: String,
82
- default: null,
83
- },
84
- /**
85
- * Desabilita botão de confirmação
86
- */
87
- isConfirmDisabled: {
88
- type: Boolean,
89
- default: false,
90
- },
91
- /**
92
- * lista de botões extra (IExtraButton)
93
- */
94
- extraButtons: {
95
- type: Array as PropType<Array<IExtraButton>>,
96
- default: () => [],
97
- },
45
+ });
46
+
47
+ defineProps({
48
+ confirmLabel: {
49
+ type: String,
50
+ default: 'Confirmar',
51
+ },
52
+ closeLabel: {
53
+ type: String,
54
+ default: 'Fechar',
55
+ },
56
+ hasConfirm: {
57
+ type: Boolean,
58
+ default: true,
59
+ },
60
+ hasCancel: {
61
+ type: Boolean,
62
+ default: true,
63
+ },
64
+ confirmColor: {
65
+ type: String,
66
+ default: 'primary',
67
+ },
68
+ confirmIcon: {
69
+ type: String,
70
+ default: null,
98
71
  },
72
+ isConfirmDisabled: {
73
+ type: Boolean,
74
+ default: false,
75
+ },
76
+ extraButtons: {
77
+ type: Array as PropType<IExtraButton[]>,
78
+ default: () => [],
79
+ },
80
+ });
81
+
82
+ const emit = defineEmits(['onClose', 'onConfirm']);
83
+
84
+ const emitConfirm = () => {
85
+ emit('onConfirm');
86
+ };
87
+
88
+
89
+ const emitExtraButtonListener = (button: IExtraButton) => {
90
+ if (button.listener) {
91
+ emit(button.listener);
92
+ }
99
93
  };
100
94
  </script>
95
+
101
96
  <style lang="scss" scoped>
102
97
  @import 'DialogFooter';
103
98
  </style>
@@ -1,37 +1,66 @@
1
1
  <template>
2
- <section ref="container" id="droparea-container">
2
+ <section
3
+ ref="container"
4
+ id="droparea-container"
5
+ >
3
6
  <input
4
7
  type="file"
5
8
  name="file"
6
9
  multiple
7
10
  ref="upload"
8
- :accept="acceptedFileTypes"
9
- @change="fileChange($event.target.files)"
11
+ :accept="props.acceptedFileTypes"
12
+ @change="handleFileChange"
10
13
  />
11
- <div v-if="!hasFiles" class="selectfile-container">
12
- <farm-icon class="upload-icon" color="primary" size="lg" @click="addMoreFiles">
14
+
15
+ <div
16
+ v-if="!hasFiles"
17
+ class="selectfile-container"
18
+ >
19
+ <farm-icon
20
+ class="upload-icon"
21
+ color="primary"
22
+ size="lg"
23
+ @click="addMoreFiles"
24
+ >
13
25
  cloud-upload-outline
14
26
  </farm-icon>
15
- <farm-subtitle :type="2" variation="regular" color="primary">
27
+ <farm-subtitle
28
+ :type="2"
29
+ variation="regular"
30
+ color="primary"
31
+ >
16
32
  Arraste e solte o arquivo <br />
17
33
  ou clique aqui
18
34
  </farm-subtitle>
19
35
  </div>
20
36
 
21
37
  <ul
22
- v-if="downloadFiles.length"
38
+ v-if="props.downloadFiles.length"
23
39
  class="listFilesStyled listFilesStyled--download"
24
40
  :class="{
25
41
  'listFilesStyled--margin-bottom': files.length === 0,
26
42
  }"
27
43
  >
28
- <li class="itemFilesStyled" v-for="file in downloadFiles" :key="file.id">
44
+ <li
45
+ class="itemFilesStyled"
46
+ v-for="file in props.downloadFiles"
47
+ :key="file.id"
48
+ >
29
49
  <div class="itemFilesContentStyled">
30
50
  <div class="fileDocumentStyled">
31
- <farm-icon color="black" variation="50" size="sm">attachment</farm-icon>
51
+ <farm-icon
52
+ color="black"
53
+ variation="50"
54
+ size="sm"
55
+ >
56
+ attachment
57
+ </farm-icon>
32
58
  </div>
33
59
  <div>
34
- <farm-bodysmall color="black" color-variation="50">
60
+ <farm-bodysmall
61
+ color="black"
62
+ color-variation="50"
63
+ >
35
64
  Arquivo selecionado: {{ file.name }} ({{ sizeOf(file.size) }})
36
65
  </farm-bodysmall>
37
66
  </div>
@@ -45,24 +74,42 @@
45
74
  title="Baixar Arquivo"
46
75
  @click.prevent="onDownload(file.id)"
47
76
  >
48
- <farm-icon class="download-button__icon mr-sm-3" size="md"
49
- >download</farm-icon
77
+ <farm-icon
78
+ class="download-button__icon mr-sm-3"
79
+ size="md"
50
80
  >
51
-
81
+ download
82
+ </farm-icon>
52
83
  <span class="download-button__text">Baixar Arquivo</span>
53
84
  </farm-btn>
54
85
  </div>
55
86
  </li>
56
87
  </ul>
57
88
 
58
- <ul class="listFilesStyled" v-if="files.length > 0">
59
- <li class="itemFilesStyled" v-for="(file, index) in files" :key="index">
89
+ <ul
90
+ class="listFilesStyled"
91
+ v-if="files.length > 0"
92
+ >
93
+ <li
94
+ class="itemFilesStyled"
95
+ v-for="(file, index) in files"
96
+ :key="index"
97
+ >
60
98
  <div class="itemFilesContentStyled">
61
99
  <div class="fileDocumentStyled">
62
- <farm-icon color="black" variation="50" size="sm">attachment</farm-icon>
100
+ <farm-icon
101
+ color="black"
102
+ variation="50"
103
+ size="sm"
104
+ >
105
+ attachment
106
+ </farm-icon>
63
107
  </div>
64
108
  <div>
65
- <farm-bodysmall color="black" color-variation="50">
109
+ <farm-bodysmall
110
+ color="black"
111
+ color-variation="50"
112
+ >
66
113
  Arquivo selecionado: {{ file.name }} ({{ sizeOf(file.size) }})
67
114
  </farm-bodysmall>
68
115
  </div>
@@ -78,10 +125,17 @@
78
125
  >
79
126
  <farm-icon size="md">close</farm-icon>
80
127
  </farm-btn>
81
- <farm-icon size="md" color="neutral" v-if="file.success">check</farm-icon>
128
+ <farm-icon
129
+ size="md"
130
+ color="neutral"
131
+ v-if="file.success === true"
132
+ >
133
+ check
134
+ </farm-icon>
82
135
  </div>
83
136
  </li>
84
137
  </ul>
138
+
85
139
  <farm-btn
86
140
  v-if="canAddMoreFiles && hasFiles"
87
141
  outlined
@@ -94,169 +148,102 @@
94
148
  </farm-btn>
95
149
  </section>
96
150
  </template>
97
- <script lang="ts">
98
- import { PropType } from 'vue';
151
+
152
+ <script setup lang="ts">
153
+ import { ref, computed, watch, defineEmits } from 'vue';
99
154
 
100
155
  import { sizeOf } from '@farm-investimentos/front-mfe-libs-ts';
101
156
 
102
- export type DownloadFiles = {
157
+ type DownloadFiles = {
103
158
  id: number | string;
104
159
  name: string;
105
160
  size: number;
106
161
  };
107
162
 
108
- export default {
109
- name: 'farm-multiple-filepicker',
110
-
111
- props: {
112
- /*
113
- * Accepted file types
114
- */
115
- acceptedFileTypes: {
116
- type: String,
117
- default: '*',
118
- },
119
- /**
120
- * Max file size (in MB)
121
- */
122
- maxFileSize: {
123
- default: 0,
124
- },
125
- /**
126
- * Max files number
127
- */
128
- maxFilesNumber: {
129
- type: Number,
130
- default: 0,
131
- },
132
- /**
133
- * File List from files who could be download
134
- */
135
- downloadFiles: {
136
- type: Array as PropType<Array<DownloadFiles>>,
137
- default: () => [],
138
- },
139
- },
140
- data() {
141
- return {
142
- dropArea: null,
143
- files: [],
144
- sizeOf,
145
- };
146
- },
147
- computed: {
148
- hasFiles(): boolean {
149
- return this.files.length > 0 || this.downloadFiles.length > 0;
150
- },
151
- canAddMoreFiles(): boolean {
152
- return this.filesLength < this.maxFilesNumber;
153
- },
154
- filesLength(): number {
155
- return this.files.length + this.downloadFiles.length;
156
- },
157
- disabledButton(): boolean {
158
- if (this.maxFilesNumber === 0) return false;
159
- return this.filesLength >= this.maxFilesNumber;
160
- },
161
- },
162
- mounted() {
163
- this.dropArea = this.$refs.container;
164
- this.addListeners();
165
- },
166
- methods: {
167
- addMoreFiles(): void {
168
- this.$refs.container.querySelector('input').click();
169
- },
170
- reset(): void {
171
- this.$refs.container.querySelector('input').value = '';
172
- this.files = [];
173
- },
174
- fileChange(fileList): void {
175
- this.files.push(...fileList);
176
- },
177
- handlerFunctionHighlight(): void {
178
- this.dropArea.classList.add('highlight');
179
- },
180
- handlerFunctionUnhighlight(): void {
181
- this.dropArea.classList.remove('highlight');
182
- },
183
- addListeners(): void {
184
- this.dropArea.addEventListener('dragenter', this.handlerFunctionHighlight, false);
185
- this.dropArea.addEventListener('dragleave', this.handlerFunctionUnhighlight, false);
186
- this.dropArea.addEventListener('dragover', this.handlerFunctionHighlight, false);
187
- this.dropArea.addEventListener('drop', this.handlerFunctionUnhighlight, false);
188
- },
189
-
190
- remove(index: number): void {
191
- if (this.files.length === 1) this.reset();
192
- this.files.splice(index, 1);
193
- },
194
-
195
- onDownload(id: number): void {
196
- this.$emit('onDownload', id);
197
- },
198
- },
199
- watch: {
200
- files(newValue) {
201
- if (newValue.length === 0 && this.downloadFiles.length === 0) {
202
- this.$emit('onFileChange', newValue);
203
- return;
204
- }
205
- const invalidTypeArray = newValue.filter(file => {
206
- const type = file.type;
207
-
208
- return (
209
- this.acceptedFileTypes !== '*' &&
210
- (this.acceptedFileTypes.indexOf(file.type) === -1 || !type)
211
- );
212
- });
213
-
214
- if (invalidTypeArray.length > 0) {
215
- const validTypeArray = newValue.filter(file => {
216
- const type = file.type;
217
- if (this.acceptedFileTypes.indexOf(file.type) === -1 || !type) {
218
- return false;
219
- }
220
- return true;
221
- });
222
- this.$emit('onInvalidFiles', [...invalidTypeArray]);
223
- this.files = validTypeArray;
224
- return;
225
- }
163
+ type ExtendedFile = {
164
+ name: string;
165
+ size: number;
166
+ success?: boolean;
167
+ };
226
168
 
227
- if (
228
- !!this.maxFilesNumber &&
229
- newValue.length + this.downloadFiles.length > this.maxFilesNumber
230
- ) {
231
- this.files = newValue.slice(0, this.maxFilesNumber - this.downloadFiles.length);
232
- this.$emit('onMaxFilesNumberWarning');
233
- return;
234
- }
169
+ defineOptions({
170
+ name: 'farm-multiple-filepicker',
171
+ });
172
+
173
+ const props = defineProps({
174
+ acceptedFileTypes: { type: String, default: '*' },
175
+ maxFileSize: { type: Number, default: 0 },
176
+ maxFilesNumber: { type: Number, default: 0 },
177
+ downloadFiles: { type: Array as () => DownloadFiles[], default: () => [] },
178
+ });
179
+
180
+ const emit = defineEmits([
181
+ 'onFileChange',
182
+ 'onInvalidFiles',
183
+ 'onMaxFilesNumberWarning',
184
+ 'onDownload',
185
+ 'onReset',
186
+ ]);
187
+
188
+ const files = ref<ExtendedFile[]>([]);
189
+ const dropArea = ref<HTMLElement | null>(null);
190
+ const container = ref<HTMLElement | null>(null);
191
+
192
+ const hasFiles = computed(() => files.value.length > 0 || props.downloadFiles.length > 0);
193
+ const canAddMoreFiles = computed(() => files.value.length < props.maxFilesNumber);
194
+ const disabledButton = computed(() =>
195
+ props.maxFilesNumber === 0 ? false : files.value.length >= props.maxFilesNumber
196
+ );
197
+
198
+ const addMoreFiles = () => {
199
+ const input = dropArea.value?.querySelector('input[type="file"]') as HTMLInputElement;
200
+ if (input) input.click();
201
+ };
235
202
 
236
- if (this.maxFileSize > 0) {
237
- const files = newValue.filter(file => {
238
- const sizeInMB = file.size / (1024 * 1024);
239
- if (sizeInMB > this.maxFileSize) return true;
203
+ // const reset = () => {
204
+ // const input = container.value?.querySelector('input[type="file"]') as HTMLInputElement;
205
+ // if (input) input.value = '';
206
+ // files.value = [];
207
+ // emit('onReset');
208
+ // };
240
209
 
241
- return false;
242
- });
243
- if (files.length > 0) {
244
- this.files = newValue.filter(file => {
245
- const sizeInMB = file.size / (1024 * 1024);
246
- if (sizeInMB < this.maxFileSize) return true;
210
+ const remove = (index: number) => {
211
+ files.value.splice(index, 1);
212
+ emit('onFileChange', files.value);
213
+ };
247
214
 
248
- return false;
249
- });
215
+ const handleFileChange = (event: Event) => {
216
+ const target = event.target as HTMLInputElement;
217
+ const fileList = target.files ? Array.from(target.files) : [];
218
+ if (fileList.length) {
219
+ files.value = [...files.value, ...fileList];
220
+ emit('onFileChange', files.value);
221
+ }
222
+ };
250
223
 
251
- this.$emit('onMaxFileSizeWarning');
252
- return;
253
- }
254
- }
255
- this.$emit('onFileChange', this.files);
256
- },
257
- },
224
+ const onDownload = (id: number | string) => {
225
+ emit('onDownload', id);
258
226
  };
227
+
228
+ watch(files, newValue => {
229
+ if (newValue.length > props.maxFilesNumber && props.maxFilesNumber > 0) {
230
+ files.value = newValue.slice(0, props.maxFilesNumber);
231
+ emit('onMaxFilesNumberWarning');
232
+ }
233
+
234
+ if (props.maxFileSize > 0) {
235
+ const validFiles = newValue.filter(file => file.size / (1024 * 1024) <= props.maxFileSize);
236
+ if (validFiles.length !== newValue.length) {
237
+ emit(
238
+ 'onInvalidFiles',
239
+ newValue.filter(file => !validFiles.includes(file))
240
+ );
241
+ files.value = validFiles;
242
+ }
243
+ }
244
+ });
259
245
  </script>
246
+
260
247
  <style scoped lang="scss">
261
248
  @import './MultipleFilePicker.scss';
262
249
  </style>