@farm-investimentos/front-mfe-components-vue3 0.4.1 → 0.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farm-investimentos/front-mfe-components-vue3",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,7 +34,8 @@
34
34
  "core-js": "3.33.1",
35
35
  "text-mask-addons": "^3.8.0",
36
36
  "v-mask": "2.3.0",
37
- "vuetify": "3.3.23",
37
+ "v-money3": "^3.24.0",
38
+ "vuetify": "3.4.0",
38
39
  "webpack": "5.89.0"
39
40
  },
40
41
  "devDependencies": {
@@ -8,7 +8,7 @@
8
8
  position: absolute;
9
9
  right: -20px;
10
10
  top: -1px;
11
- transition: transform 0.8s ease-in-out;
11
+ transition: transform 0.5s ease-in-out;
12
12
 
13
13
  &.farm-icon--asc {
14
14
  transform: rotateX(180deg);
@@ -18,15 +18,14 @@
18
18
 
19
19
  th.sortable {
20
20
  cursor: pointer;
21
+
21
22
  .farm-icon::before {
22
23
  transition: all 0.3s linear;
23
24
  }
24
-
25
+
25
26
  &:not(.active) {
26
- &:hover {
27
- .farm-icon::before {
28
- color: var(--farm-bw-black-10) !important;
29
- }
27
+ .farm-icon::before {
28
+ color: var(--farm-bw-black-10) !important;
30
29
  }
31
30
  }
32
31
  }
@@ -29,7 +29,7 @@
29
29
  {{ item.text }}
30
30
 
31
31
  <farm-icon
32
- v-if="item.sortable && sortClick[$index].show"
32
+ v-show="item.sortable"
33
33
  v-bind:class="[
34
34
  sortClick[$index][item.value] ? 'farm-icon--desc' : 'farm-icon--asc',
35
35
  ]"
@@ -42,7 +42,10 @@
42
42
  </farm-icon>
43
43
  </span>
44
44
 
45
- <span v-if="isTHDataTableSelect(item) && showCheckbox" class="span-checkbox">
45
+ <span
46
+ v-if="isTHDataTableSelect(item) && showCheckbox"
47
+ class="span-checkbox"
48
+ >
46
49
  <farm-checkbox
47
50
  size="sm"
48
51
  v-model="inputVal"
@@ -59,7 +62,6 @@
59
62
  <script lang="ts">
60
63
  /* eslint-disable */
61
64
 
62
-
63
65
  export default {
64
66
  name: 'farm-datatable-header',
65
67
  props: {
@@ -0,0 +1,96 @@
1
+ @import '../../configurations/mixins';
2
+
3
+ .farm-input-money {
4
+ height: 64px;
5
+
6
+ &--hiddendetails {
7
+ height: 40px;
8
+ }
9
+
10
+ &--input {
11
+ display: flex;
12
+ align-items: center;
13
+ gap: 8px;
14
+ border: 1px solid;
15
+ border-color: var(--farm-bw-black-10);
16
+ height: 36px;
17
+ border-radius: 5px;
18
+ padding: 8px;
19
+ margin-bottom: 4px;
20
+ background-color: white;
21
+
22
+ >button {
23
+ display: flex;
24
+ }
25
+
26
+ &>input {
27
+ flex: 1;
28
+ outline: none;
29
+ color: var(--farm-bw-black-50);
30
+ font-size: 12px;
31
+ font-weight: 400;
32
+ max-width: 100%;
33
+ }
34
+
35
+ &--iconed>input {
36
+ max-width: calc(100% - 32px);
37
+ }
38
+
39
+ width: 100%;
40
+ }
41
+
42
+ &--focused .farm-input-money--input {
43
+ border-color: var(--farm-bw-black-30);
44
+ }
45
+
46
+ &--disabled {
47
+ input {
48
+ color: var(--farm-bw-black-30);
49
+ }
50
+
51
+ .farm-icon {
52
+ color: var(--farm-bw-black-30);
53
+ cursor: default;
54
+ }
55
+ }
56
+
57
+ .farm-caption {
58
+ line-height: 12px;
59
+ }
60
+
61
+ &__hint-text {
62
+ @include hintText;
63
+ }
64
+ }
65
+
66
+ .farm-input-money--touched.farm-input-money--blured.farm-input-money--validatable {
67
+ &.farm-input-money--error {
68
+ .farm-input-money {
69
+ &--input {
70
+ border-color: var(--farm-error-base);
71
+
72
+ &>input {
73
+ color: var(--farm-neutral-darken);
74
+ }
75
+
76
+ .farm-icon {
77
+ color: var(--farm-error-base);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ .farm-input-money--blured.farm-input-money--validatable:not(.farm-input-money--error) {
85
+ .farm-input-money--input {
86
+ border-color: var(--farm-primary-base);
87
+
88
+ &>input {
89
+ color: var(--farm-neutral-darken);
90
+ }
91
+
92
+ .farm-icon {
93
+ color: var(--farm-primary-base);
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,123 @@
1
+
2
+ import InputMoney from './InputMoney.vue';
3
+
4
+
5
+ export default {
6
+ title: 'Form/InputMoney',
7
+ component: InputMoney,
8
+ // decorators: [withDesign],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component: `Input Money<br />
13
+ selector: <em>farm-input-money</em><br />
14
+ <span style="color: var(--farm-primary-base);">ready for use</span>
15
+ `,
16
+ },
17
+ },
18
+ design: {
19
+ type: 'figma',
20
+ url: '',
21
+ },
22
+ viewMode: 'docs',
23
+ },
24
+ };
25
+
26
+ export const Default = () => ({
27
+ data() {
28
+ return {
29
+ v: '1.200,00',
30
+ };
31
+ },
32
+ template: `<div style="width: 480px;">
33
+ <farm-label for="input-money">
34
+ label
35
+ </farm-label>
36
+ <farm-input-money id="input-money-default" v-model="v" />
37
+ <span>{{v}}</span>
38
+ </div>`,
39
+ });
40
+
41
+
42
+ export const Prefix = () => ({
43
+ data() {
44
+ return {
45
+ v: '1.200,00',
46
+ };
47
+ },
48
+ template: `<div style="width: 480px;">
49
+ <farm-label for="input-money">
50
+ label
51
+ </farm-label>
52
+ <farm-input-money prefix="R$ " id="input-money-prefix" v-model="v" />
53
+ <span>{{v}}</span>
54
+ </div>`,
55
+ });
56
+
57
+
58
+ export const Sufix = () => ({
59
+ data() {
60
+ return {
61
+ v: '1.200,00',
62
+ };
63
+ },
64
+ template: `<div style="width: 480px;">
65
+ <farm-label for="input-money">
66
+ label
67
+ </farm-label>
68
+ <farm-input-money suffix="%" id="input-money-prefix" v-model="v" />
69
+ <span>{{v}}</span>
70
+ </div>`,
71
+ });
72
+
73
+
74
+ export const Precision = () => ({
75
+ data() {
76
+ return {
77
+ v: '3,14159265358979323846',
78
+ };
79
+ },
80
+ template: `<div style="width: 480px;">
81
+ <farm-label for="input-money">
82
+ label
83
+ </farm-label>
84
+ <farm-input-money :precision="20" id="input-money-prefix" v-model="v" />
85
+ <span>{{v}}</span>
86
+ </div>`,
87
+ });
88
+
89
+
90
+ export const Icon = () => ({
91
+ data() {
92
+ return {
93
+ v: '1.200,00',
94
+ };
95
+ },
96
+ template: `<div style="width: 480px;">
97
+ <farm-label for="input-money">
98
+ label
99
+ </farm-label>
100
+ <farm-input-money id="input-money" v-model="v" icon="currency-usd" />
101
+ <span>{{v}}</span>
102
+ </div>`,
103
+ });
104
+
105
+ export const Required = () => ({
106
+ data() {
107
+
108
+ return {
109
+ v: '0,00',
110
+ rules: {
111
+ required: value => value !== "0,00" || 'Required field',
112
+ }
113
+ };
114
+ },
115
+ template: `<div style="width: 480px;">
116
+ <farm-label for="input-money">
117
+ label
118
+ </farm-label>
119
+ <farm-input-money id="input-money" v-model="v" :rules="[rules.required]" />
120
+ <span>{{v}}</span>
121
+ </div>`,
122
+ });
123
+
@@ -0,0 +1,316 @@
1
+ <template>
2
+ <div
3
+ class="farm-input-money"
4
+ :class="{
5
+ 'farm-input-money': true,
6
+ 'farm-input-money--validatable': rules.length > 0,
7
+ 'farm-input-money--touched': isTouched,
8
+ 'farm-input-money--blured': isBlured,
9
+ 'farm-input-money--error': hasError,
10
+ 'farm-input-money--focused': isFocus && !readonly,
11
+ 'farm-input-money--disabled': disabled,
12
+ 'farm-input-money--hiddendetails': hideDetails,
13
+ }"
14
+ :id="customId"
15
+ >
16
+ <div
17
+ :class="{
18
+ 'farm-input-money--input': true,
19
+ 'farm-input-money--input--iconed': icon,
20
+ }"
21
+ >
22
+ <button
23
+ type="button"
24
+ v-if="icon && iconPosition === 'left'"
25
+ @click="$emit('onClickIcon')"
26
+ >
27
+ <farm-icon
28
+ color="gray"
29
+ size="20px"
30
+ >{{ icon }}</farm-icon
31
+ >
32
+ </button>
33
+ <input
34
+ v-bind="$attrs"
35
+ v-model.lazy="innerValue"
36
+ v-money3="{
37
+ decimal,
38
+ thousands,
39
+ prefix,
40
+ suffix,
41
+ precision,
42
+ masked: false,
43
+ }"
44
+ :id="$props.id"
45
+ :disabled="disabled"
46
+ :readonly="readonly"
47
+ :model-modifiers="{ number: true }"
48
+ @click="$emit('click')"
49
+ @keyup="onKeyUp"
50
+ @blur="onBlur"
51
+ @focusin="onFocus(true)"
52
+ @focusout="onFocus(false)"
53
+ />
54
+ <button
55
+ type="button"
56
+ v-if="icon && iconPosition === 'right'"
57
+ @click="$emit('onClickIcon')"
58
+ >
59
+ <farm-icon
60
+ color="gray"
61
+ size="20px"
62
+ >{{ icon }}</farm-icon
63
+ >
64
+ </button>
65
+ </div>
66
+ <farm-caption
67
+ v-if="!hideDetails && showErrorText"
68
+ color="error"
69
+ variation="regular"
70
+ >
71
+ {{ errorBucket[0] }}
72
+ </farm-caption>
73
+ <farm-caption
74
+ v-if="!hideDetails && hint && !showErrorText"
75
+ class="farm-input-money__hint-text"
76
+ :class="{
77
+ 'farm-input-money__hint-text--show': persistentHint || isFocus,
78
+ }"
79
+ color="gray"
80
+ variation="regular"
81
+ >
82
+ {{ hint }}
83
+ </farm-caption>
84
+ </div>
85
+ </template>
86
+
87
+ <script lang="ts">
88
+ import { computed, onBeforeMount, PropType, ref, toRefs, watch } from 'vue';
89
+
90
+ import deepEqual from '../../composition/deepEqual';
91
+ import validateFormFieldBuilder from '../../composition/validateFormFieldBuilder';
92
+ import validateFormMethodBuilder from '../../composition/validateFormMethodBuilder';
93
+ import validateFormStateBuilder from '../../composition/validateFormStateBuilder';
94
+ import randomId from '../../helpers/randomId';
95
+
96
+ export default {
97
+ name: 'farm-input-money',
98
+ inheritAttrs: false,
99
+ props: {
100
+ /**
101
+ * v-model binding
102
+ */
103
+ modelValue: { type: [String, Number], default: '' },
104
+ /**
105
+ * Show icon?
106
+ */
107
+ icon: {
108
+ type: String,
109
+ default: null,
110
+ },
111
+ /**
112
+ * Icon position
113
+ */
114
+ iconPosition: { type: String as PropType<'left' | 'right'>, default: 'right' },
115
+ /**
116
+ * Show hint text
117
+ */
118
+ hint: {
119
+ type: String,
120
+ default: null,
121
+ },
122
+ /**
123
+ * Always show hint text
124
+ */
125
+ persistentHint: {
126
+ type: Boolean,
127
+ default: false,
128
+ },
129
+ /**
130
+ * Disabled the input
131
+ */
132
+ disabled: {
133
+ type: Boolean,
134
+ default: false,
135
+ },
136
+ /**
137
+ * Puts input in readonly state
138
+ */
139
+ readonly: {
140
+ type: Boolean,
141
+ default: false,
142
+ },
143
+
144
+ errorMessage: String,
145
+ /**
146
+ * Array of rules used for validation
147
+ */
148
+ rules: {
149
+ type: Array as PropType<Array<Function>>,
150
+ default: () => [],
151
+ },
152
+ /**
153
+ * Hides hint and validation errors
154
+ */
155
+ hideDetails: {
156
+ type: Boolean,
157
+ default: false,
158
+ },
159
+ /**
160
+ * Input id
161
+ */
162
+ id: {
163
+ type: String,
164
+ default: '',
165
+ },
166
+
167
+ /**
168
+ * Emitted when any key is pressed<br />
169
+ * _event_
170
+ */
171
+ keyup: {
172
+ type: Function,
173
+ // eslint-disable-next-line
174
+ default: (event: Event) => {},
175
+ },
176
+
177
+ /**
178
+ * Currency symbol followed by a Space, like "R$ "
179
+ */
180
+ prefix: {
181
+ type: String,
182
+ default: '',
183
+ },
184
+
185
+ /**
186
+ * Percentage for example: " %"
187
+ */
188
+ suffix: {
189
+ type: String,
190
+ default: '',
191
+ },
192
+ /**
193
+ * Thousands separator
194
+ */
195
+ thousands: {
196
+ type: String,
197
+ default: '.',
198
+ },
199
+ /**
200
+ * Decimal separator
201
+ */
202
+ decimal: {
203
+ type: String,
204
+ default: ',',
205
+ },
206
+ /**
207
+ * How many decimal places
208
+ */
209
+ precision: {
210
+ type: Number,
211
+ default: 2,
212
+ },
213
+ },
214
+ setup(props, { emit }) {
215
+ const { rules } = toRefs(props);
216
+ const innerValue = ref(props.modelValue);
217
+ const isTouched = ref(false);
218
+ const isBlured = ref(false);
219
+ const isFocus = ref(false);
220
+
221
+ const { errorBucket, valid, validatable } = validateFormStateBuilder();
222
+
223
+ let fieldValidator = validateFormFieldBuilder(rules.value);
224
+
225
+ const hasError = computed(() => {
226
+ return errorBucket.value.length > 0;
227
+ });
228
+ const customId = 'farm-input-money-' + (props.id || randomId(2));
229
+
230
+ const showErrorText = computed(() => hasError.value && isTouched.value && isBlured.value);
231
+
232
+ watch(
233
+ () => props.modelValue,
234
+ () => {
235
+ innerValue.value = props.modelValue;
236
+ validate(innerValue.value);
237
+ }
238
+ );
239
+
240
+ watch(
241
+ () => innerValue.value,
242
+ () => {
243
+ emit('update:modelValue', innerValue.value);
244
+ validate(innerValue.value);
245
+ }
246
+ );
247
+
248
+ watch(
249
+ () => props.rules,
250
+ (newVal, oldVal) => {
251
+ if (deepEqual(newVal, oldVal)) return;
252
+ fieldValidator = validateFormFieldBuilder(rules.value);
253
+ validate = validateFormMethodBuilder(errorBucket, valid, fieldValidator);
254
+ validate(innerValue.value);
255
+ }
256
+ );
257
+
258
+ onBeforeMount(() => {
259
+ validate(innerValue.value);
260
+ });
261
+
262
+ let validate = validateFormMethodBuilder(errorBucket, valid, fieldValidator);
263
+
264
+ const onKeyUp = (event: Event) => {
265
+ isTouched.value = true;
266
+ emit('keyup', event);
267
+
268
+ setTimeout(() => {
269
+ emit('change', innerValue.value);
270
+ }, 100);
271
+ };
272
+
273
+ const onBlur = (event: Event) => {
274
+ isBlured.value = true;
275
+ emit('blur', event);
276
+ };
277
+
278
+ const onFocus = (focus: boolean) => {
279
+ isFocus.value = focus;
280
+ };
281
+
282
+ const reset = () => {
283
+ innerValue.value = '';
284
+ isTouched.value = true;
285
+ emit('update:modelValue', innerValue.value);
286
+ };
287
+
288
+ const makePristine = () => {
289
+ isTouched.value = false;
290
+ isBlured.value = false;
291
+ };
292
+
293
+ return {
294
+ innerValue,
295
+ errorBucket,
296
+ valid,
297
+ validatable,
298
+ hasError,
299
+ customId,
300
+ isTouched,
301
+ isBlured,
302
+ isFocus,
303
+ showErrorText,
304
+ validate,
305
+ onKeyUp,
306
+ onBlur,
307
+ onFocus,
308
+ reset,
309
+ makePristine,
310
+ };
311
+ },
312
+ };
313
+ </script>
314
+ <style lang="scss" scoped>
315
+ @import 'InputMoney';
316
+ </style>
@@ -0,0 +1,53 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+
3
+ import InputMoney from '../InputMoney';
4
+
5
+ describe('InputMoney component', () => {
6
+ let wrapper;
7
+ let component;
8
+
9
+ beforeEach(() => {
10
+ wrapper = shallowMount(InputMoney, {
11
+ directives: {
12
+ mask: () => { },
13
+ },
14
+ });
15
+ component = wrapper.vm;
16
+ });
17
+
18
+ test('Created hook', () => {
19
+ expect(wrapper).toBeDefined();
20
+ });
21
+
22
+ describe('mount component', () => {
23
+ it('renders correctly', () => {
24
+ expect(wrapper.element).toBeDefined();
25
+ });
26
+ });
27
+
28
+ describe('methods', () => {
29
+ it('reset', () => {
30
+ component.reset();
31
+ expect(component.isTouched).toBeTruthy();
32
+ expect(component.innerValue).toEqual('');
33
+ });
34
+
35
+ it('onKeyUp', () => {
36
+ component.onKeyUp();
37
+ expect(component.isTouched).toBeTruthy();
38
+ });
39
+
40
+ it('onBlur', () => {
41
+ component.onBlur();
42
+ expect(component.isBlured).toBeTruthy();
43
+ });
44
+
45
+ it('makePristine', () => {
46
+ component.isTouched = true;
47
+ component.isBlured = true;
48
+ component.makePristine();
49
+ expect(component.isTouched).toBeFalsy();
50
+ expect(component.isBlured).toBeFalsy();
51
+ });
52
+ });
53
+ });
@@ -0,0 +1,4 @@
1
+ import InputMoney from './InputMoney.vue';
2
+
3
+ export { InputMoney };
4
+ export default InputMoney;
@@ -40,10 +40,10 @@ export const Primary = () => ({
40
40
  };
41
41
  },
42
42
  template: `<div style="width: 480px;">
43
- <farm-label for="select_label">
43
+ <farm-label for="input-primary">
44
44
  label
45
45
  </farm-label>
46
- <farm-textfield-v2 id="select_label" v-model="v" />
46
+ <farm-textfield-v2 id="input-primary" v-model="v" />
47
47
  v-model: {{ v }}
48
48
  </div>`,
49
49
  });
@@ -219,11 +219,11 @@ export const Mask = () => ({
219
219
  },
220
220
  template: `<div style="width: 480px">
221
221
  <farm-label>CPF Mask ({{ mask }})</farm-label>
222
- <farm-textfield-v2 v-model="v" :mask="mask" />
222
+ <farm-textfield-v2 id="input-mask-cpf" v-model="v" :mask="mask" />
223
223
  v-model: {{ v }}
224
224
 
225
225
  <farm-label>Number Mask (R$ ##.###.###,##)</farm-label>
226
- <farm-textfield-v2 v-model="v2" :mask="currencyMask" />
226
+ <farm-textfield-v2 id="input-mask-number" v-model="v2" :mask="currencyMask" />
227
227
  v-model: {{ v2 }}
228
228
 
229
229
  </div>`,
@@ -242,7 +242,7 @@ export const ToggleVisibility = () => ({
242
242
  },
243
243
  },
244
244
  template: `<div style="width: 480px">
245
- <farm-textfield-v2 v-model="v" :type="visible ? 'text' : 'password'" :icon="visible ? 'eye-off' : 'eye'" @onClickIcon="toggle" />
245
+ <farm-textfield-v2 id="input-visibility" v-model="v" :type="visible ? 'text' : 'password'" :icon="visible ? 'eye-off' : 'eye'" @onClickIcon="toggle" />
246
246
  </div>`,
247
247
  });
248
248
 
@@ -253,9 +253,10 @@ export const Uppercase = () => ({
253
253
  };
254
254
  },
255
255
  template: `<div style="width: 480px;">
256
- <farm-label for="select_label">
256
+ <farm-label for="input-uppercase">
257
257
  label
258
258
  </farm-label>
259
- <farm-textfield-v2 id="select_label" v-model="v" uppercase/>
259
+ <farm-textfield-v2 id="input-uppercase" v-model="v" uppercase/>
260
260
  </div>`,
261
261
  });
262
+