@farm-investimentos/front-mfe-components 12.2.2 → 13.0.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",
3
- "version": "12.2.2",
3
+ "version": "13.0.0",
4
4
  "author": "farm investimentos",
5
5
  "private": false,
6
6
  "main": "./dist/front-mfe-components.common.js",
@@ -1,6 +1,14 @@
1
1
  @import '../../../configurations/variables';
2
2
  @import '../../../configurations/mixins';
3
3
  @import '../../../configurations/theme-colors';
4
+ $butonSizes: (
5
+ "xs": 20px,
6
+ "sm": 28px,
7
+ "md": 32px,
8
+ "lg": 48px,
9
+ "xl": 56px,
10
+ 'default': 36px,
11
+ );
4
12
 
5
13
  .farm-btn {
6
14
  font-size: 14px;
@@ -29,9 +37,11 @@
29
37
  width: 100%;
30
38
  }
31
39
 
32
- @each $size, $value in $sizes {
40
+ @each $size,
41
+ $value in $sizes {
33
42
  &#{'.farm-btn[size=' + $size + ']'} {
34
43
  font-size: $value;
44
+ height: map-get($butonSizes, $size);
35
45
  }
36
46
  }
37
47
 
@@ -95,6 +105,7 @@
95
105
 
96
106
  &.farm-btn--plain {
97
107
  background-color: transparent !important;
108
+
98
109
  &:hover {
99
110
  .farm-btn__content {
100
111
  opacity: 0.68;
@@ -125,7 +136,8 @@
125
136
  color: gray;
126
137
  }
127
138
 
128
- @each $size, $value in $sizes {
139
+ @each $size,
140
+ $value in $sizes {
129
141
  &#{'.farm-btn[size=' + $size + ']'} {
130
142
  font-size: $value;
131
143
  }
@@ -165,12 +177,13 @@
165
177
  i.mdi {
166
178
  color: white;
167
179
  }
180
+
168
181
  .farm-btn__content i.mdi {
169
182
  color: black;
170
183
  }
171
184
  }
172
185
  }
173
-
186
+
174
187
  }
175
188
 
176
189
  .farm-btn--extra,
@@ -250,4 +263,4 @@
250
263
  width: 100%;
251
264
  margin: 0;
252
265
  }
253
- }
266
+ }
@@ -225,7 +225,7 @@ export const Rounded = () => ({
225
225
  export const Sizes = () => ({
226
226
  data() {
227
227
  return {
228
- sizes: ['xs', 'sm', 'md', 'lg', 'xl'],
228
+ sizes: ['xs', 'sm', 'md', 'lg', 'xl', 'default'],
229
229
  styles: {
230
230
  display: 'flex',
231
231
  flexDirection: 'row',
@@ -1,14 +1,18 @@
1
1
  <template>
2
2
  <div class="farm-checkbox__container" :color="$props.color">
3
- <span :class="{
4
- 'farm-checkbox': true,
5
- 'farm-checkbox--checked': isChecked,
6
- 'farm-checkbox--disabled': disabled,
7
- 'farm-checkbox--indeterminate': indeterminate,
8
- 'farm-checkbox--lighten': variation === 'lighten',
9
- 'farm-checkbox--darken': variation === 'darken',
10
- 'farm-checkbox--error': showError,
11
- }" :size="$props.size" @click="toggleValue">
3
+ <span
4
+ :class="{
5
+ 'farm-checkbox': true,
6
+ 'farm-checkbox--checked': isChecked,
7
+ 'farm-checkbox--disabled': disabled,
8
+ 'farm-checkbox--indeterminate': indeterminate,
9
+ 'farm-checkbox--lighten': variation === 'lighten',
10
+ 'farm-checkbox--darken': variation === 'darken',
11
+ 'farm-checkbox--error': showError,
12
+ }"
13
+ :size="$props.size"
14
+ @click="toggleValue"
15
+ >
12
16
  <farm-icon :size="$props.size" v-if="innerValue && !indeterminate">check</farm-icon>
13
17
  <farm-icon :size="$props.size" v-if="indeterminate">minus</farm-icon>
14
18
  </span>
@@ -24,6 +28,7 @@ import validateFormStateBuilder from '../../composition/validateFormStateBuilder
24
28
  import validateFormFieldBuilder from '../../composition/validateFormFieldBuilder';
25
29
  import validateFormMethodBuilder from '../../composition/validateFormMethodBuilder';
26
30
  import deepEqual from '../../composition/deepEqual';
31
+ import modelValueWatcher from './modelValueWatcher';
27
32
 
28
33
  export default Vue.extend({
29
34
  name: 'farm-checkbox',
@@ -100,46 +105,15 @@ export default Vue.extend({
100
105
  return false;
101
106
  }
102
107
  isTouched.value = true;
103
- if (isChecked.value) {
104
- innerValue.value = null;
105
- } else {
106
- innerValue.value = props.value;
107
- }
108
+ innerValue.value = isChecked.value ? null : props.value;
108
109
  emit('input', innerValue.value);
109
110
  validate(innerValue.value);
110
111
  };
111
112
 
112
- const isChecked = computed(() => {
113
- return innerValue.value == props.value;
114
- });
115
-
116
- const hasError = computed(() => {
117
- return errorBucket.value.length > 0;
118
- });
119
-
113
+ const isChecked = computed(() => innerValue.value == props.value);
114
+ const hasError = computed(() => errorBucket.value.length > 0);
120
115
  const showError = computed(() => hasError.value && isTouched.value);
121
116
 
122
-
123
- watch(
124
- () => props.modelValue,
125
- (newValue) => {
126
- isTouched.value = true;
127
- innerValue.value = newValue;
128
- validate(innerValue.value);
129
- }
130
- );
131
-
132
-
133
- watch(
134
- () => props.rules,
135
- (newVal, oldVal) => {
136
- if (deepEqual(newVal, oldVal)) return;
137
- fieldValidator = validateFormFieldBuilder(rules.value);
138
- validate = validateFormMethodBuilder(errorBucket, valid, fieldValidator);
139
- validate(innerValue.value);
140
- }
141
- );
142
-
143
117
  const reset = () => {
144
118
  if (disabled.value) {
145
119
  return false;
@@ -160,6 +134,18 @@ export default Vue.extend({
160
134
  isTouched.value = false;
161
135
  };
162
136
 
137
+ modelValueWatcher(props, isTouched, innerValue, validate);
138
+
139
+ watch(
140
+ () => props.rules,
141
+ (newVal, oldVal) => {
142
+ if (deepEqual(newVal, oldVal)) return;
143
+ fieldValidator = validateFormFieldBuilder(rules.value);
144
+ validate = validateFormMethodBuilder(errorBucket, valid, fieldValidator);
145
+ validate(innerValue.value);
146
+ }
147
+ );
148
+
163
149
  return {
164
150
  innerValue,
165
151
  label,
@@ -0,0 +1,43 @@
1
+ import { ref, reactive } from 'vue';
2
+ import modelValueWatcher from '../modelValueWatcher.ts';
3
+
4
+ describe('modelValueWatcher', () => {
5
+ let props;
6
+ let isTouched;
7
+ let innerValue;
8
+ let validate;
9
+
10
+ beforeEach(() => {
11
+ props = reactive({
12
+ modelValue: 'initial value',
13
+ });
14
+ isTouched = ref(false);
15
+ innerValue = ref('');
16
+ validate = jest.fn();
17
+ modelValueWatcher(props, isTouched, innerValue, validate);
18
+ });
19
+
20
+ it('should set isTouched.value to true when props.modelValue changes', done => {
21
+ props.modelValue = 'new value';
22
+ setTimeout(() => {
23
+ expect(isTouched.value).toBe(true);
24
+ done();
25
+ });
26
+ });
27
+
28
+ it('should update innerValue.value with new props.modelValue', done => {
29
+ props.modelValue = 'new value';
30
+ setTimeout(() => {
31
+ expect(innerValue.value).toBe('new value');
32
+ done();
33
+ });
34
+ });
35
+
36
+ it('should call validate function with new innerValue.value', done => {
37
+ props.modelValue = 'new value';
38
+ setTimeout(() => {
39
+ expect(validate).toHaveBeenCalledWith('new value');
40
+ done();
41
+ });
42
+ });
43
+ });
@@ -0,0 +1,12 @@
1
+ import { Ref, watch } from 'vue';
2
+
3
+ export default function (props, isTouched: Ref, innerValue: Ref, validate: Function) {
4
+ watch(
5
+ () => props.modelValue,
6
+ newValue => {
7
+ isTouched.value = true;
8
+ innerValue.value = newValue;
9
+ validate(innerValue.value);
10
+ }
11
+ );
12
+ }
@@ -52,6 +52,13 @@ export default Vue.extend({
52
52
  type: Boolean,
53
53
  default: false,
54
54
  },
55
+ /**
56
+ * Popup Width
57
+ */
58
+ popupWidth: {
59
+ type: [Number, String],
60
+ default: null,
61
+ },
55
62
  },
56
63
  setup(props, { emit }) {
57
64
  const parent = ref(null);
@@ -70,9 +77,10 @@ export default Vue.extend({
70
77
 
71
78
  let hasBeenBoostrapped = false;
72
79
 
73
- const outClick = (event: Record<string, any>) => {
80
+ const outClick = event => {
81
+ const path = event.path || (event.composedPath && event.composedPath());
74
82
  const isInside =
75
- event.path.some((e: HTMLElement) => {
83
+ path.some((e: HTMLElement) => {
76
84
  if (e.classList) {
77
85
  return e.classList.contains('farm-contextmenu__popup--visible');
78
86
  }
@@ -126,10 +134,14 @@ export default Vue.extend({
126
134
 
127
135
  let offsetLeft = activatorBoundingClientRect.left;
128
136
 
129
- styles.minWidth =
130
- (activatorBoundingClientRect.width > 96
131
- ? parseInt(activatorBoundingClientRect.width)
132
- : 96) + 'px';
137
+ if (props.popupWidth) {
138
+ styles.minWidth = props.popupWidth + 'px';
139
+ } else {
140
+ styles.minWidth =
141
+ (activatorBoundingClientRect.width > 96
142
+ ? parseInt(activatorBoundingClientRect.width)
143
+ : 96) + 'px';
144
+ }
133
145
 
134
146
  if (activatorBoundingClientRect.width < 96) {
135
147
  const w = popupClientRect.width < 96 ? 96 : popupClientRect.width;
@@ -0,0 +1,20 @@
1
+ .datepicker :deep(.v-picker__actions) {
2
+ padding: 0;
3
+ margin: 0 16px 16px;
4
+ }
5
+ .datepicker :deep(.v-btn--active) {
6
+ background: var(--farm-primary-base);
7
+ }
8
+ .datepicker :deep(.v-date-picker-table__current) {
9
+ border-color: var(--farm-primary-base);
10
+ color: var(--farm-primary-base);
11
+ }
12
+ .datepicker :deep(.v-date-picker-table__current.v-btn--active) {
13
+ color: white;
14
+ }
15
+ .btn-clean {
16
+ margin: 0 8px;
17
+ }
18
+ .farm-contextmenu {
19
+ width: 100%;
20
+ }
@@ -29,25 +29,40 @@ export const Primary = () => ({
29
29
  });
30
30
 
31
31
  export const InitValue = () => ({
32
- template: `<div style='max-width: 320px'><farm-input-datepicker inputId="input-custom-id-1" value="2021-08-01" /></div>`,
32
+ data() {
33
+ return {
34
+ date: '2023-08-01',
35
+ };
36
+ },
37
+ template: `<div style='max-width: 320px'><farm-input-datepicker inputId="input-custom-id-1" v-model="date" /></div>`,
33
38
  });
34
39
 
35
40
  export const MinMaxDates = () => ({
41
+ data() {
42
+ return {
43
+ date: '',
44
+ };
45
+ },
36
46
  template: `<div style='max-width: 320px'>
37
- <farm-input-datepicker inputId="input-custom-id-2" max="2021-12-02" min="2021-07-01" />
47
+ <farm-input-datepicker inputId="input-custom-id-2" max="2021-12-02" min="2021-07-01" v-model="date" />
38
48
  max="2021-12-02" min="2021-07-01"
39
49
  </div>`,
40
50
  });
41
51
 
42
52
  export const RequiredDates = () => ({
53
+ data() {
54
+ return {
55
+ date: '',
56
+ };
57
+ },
43
58
  template: `<div style='max-width: 320px'>
44
- <farm-input-datepicker inputId="input-custom-id-3" :required="true" />
59
+ <farm-input-datepicker inputId="input-custom-id-3" v-model="date" :required="true" />
45
60
  </div>`,
46
61
  });
47
62
 
48
- export const ReadonlyFalse = () => ({
63
+ export const Readonly = () => ({
49
64
  template: `<div style='max-width: 320px'>
50
- <farm-input-datepicker :readonly="false" inputId="input-custom-id-3"/>
65
+ <farm-input-datepicker :readonly="true" value="2021-08-01" inputId="input-custom-id-3"/>
51
66
  </div>`,
52
67
  });
53
68
 
@@ -1,50 +1,48 @@
1
1
  <template>
2
- <v-menu
3
- ref="menuField"
2
+ <farm-contextmenu
3
+ stay-open
4
4
  v-model="menuField"
5
- :close-on-content-click="false"
6
- :return-value.sync="fieldRange"
7
- transition="scale-transition"
8
- offset-y
9
- min-width="290px"
5
+ ref="contextmenu"
6
+ maxHeight="auto"
7
+ bottom
8
+ popup-width="320"
10
9
  >
11
- <template v-slot:activator="{}">
12
- <farm-textfield-v2
13
- icon="calendar"
14
- v-model="fieldRange"
15
- autocomplete="off"
16
- :readonly="readonly"
17
- :mask="`${readonly ? '' : '##/##/####'}`"
18
- :id="inputId"
19
- :rules="[checkMax, checkMin, checkRequire]"
20
- @keyup="keyUpInput"
21
- @click="openDatepicker"
22
- @onClickIcon="openDatepicker"
23
- />
24
- </template>
25
10
  <v-date-picker
26
11
  v-if="menuField"
27
12
  v-model="dateField"
28
13
  no-title
29
14
  scrollable
30
- color="secondary"
31
15
  locale="pt-br"
16
+ class="datepicker"
32
17
  :max="max"
33
18
  :min="min"
34
19
  >
35
20
  <farm-btn outlined color="secondary" @click="closeDatepicker" title="Fechar">
36
21
  Fechar
37
22
  </farm-btn>
38
- <farm-btn outlined class="ml-2" @click="clear"> Limpar </farm-btn>
23
+ <farm-btn outlined class="btn-clean" @click="clear"> Limpar </farm-btn>
39
24
  <farm-btn class="ml-2" title="Confirmar" :disabled="!dateField.length" @click="save()">
40
25
  Confirmar
41
26
  </farm-btn>
42
27
  </v-date-picker>
43
- </v-menu>
28
+ <template v-slot:activator="{ }">
29
+ <farm-textfield-v2
30
+ icon="calendar"
31
+ v-model="fieldRange"
32
+ autocomplete="off"
33
+ :readonly="readonly"
34
+ :mask="`${readonly ? '' : '##/##/####'}`"
35
+ :id="inputId"
36
+ :rules="[checkMax, checkMin, checkRequire]"
37
+ @keyup="keyUpInput"
38
+ @click="openDatepicker"
39
+ @onClickIcon="openDatepicker"
40
+ />
41
+ </template>
42
+ </farm-contextmenu>
44
43
  </template>
45
44
  <script lang="ts">
46
45
  import Vue from 'vue';
47
- import { VMenu } from 'vuetify/lib/components/VMenu';
48
46
  import { VDatePicker } from 'vuetify/lib/components/VDatePicker';
49
47
  import { defaultFormat as dateDefaultFormatter, convertDate } from '../../helpers/date';
50
48
  /**
@@ -53,7 +51,6 @@ import { defaultFormat as dateDefaultFormatter, convertDate } from '../../helper
53
51
  export default Vue.extend({
54
52
  name: 'farm-input-datepicker',
55
53
  components: {
56
- VMenu,
57
54
  VDatePicker,
58
55
  },
59
56
  props: {
@@ -155,8 +152,10 @@ export default Vue.extend({
155
152
  return dateDefaultFormatter(date);
156
153
  },
157
154
  save() {
158
- this.$refs.menuField.save(this.formatDateRange(this.dateField));
155
+ this.formatDateRange(this.dateField);
159
156
  this.inputVal = this.dateField;
157
+ this.menuField = false;
158
+ this.closeDatepicker();
160
159
  },
161
160
  clear() {
162
161
  this.dateField = '';
@@ -185,6 +184,7 @@ export default Vue.extend({
185
184
  },
186
185
  closeDatepicker() {
187
186
  this.menuField = false;
187
+ this.$refs.contextmenu.inputValue = false;
188
188
  },
189
189
  },
190
190
  computed: {
@@ -200,7 +200,5 @@ export default Vue.extend({
200
200
  });
201
201
  </script>
202
202
  <style lang="scss" scoped>
203
- .theme--light.v-input.v-input--dense.v-text-field.v-text-field--outlined.error--text:after {
204
- content: '' !important;
205
- }
203
+ @import './DatePicker.scss';
206
204
  </style>
@@ -1,27 +1,15 @@
1
1
  <template>
2
- <v-menu
3
- ref="menuField"
2
+ <farm-contextmenu
3
+ stay-open
4
4
  v-model="menuField"
5
- :close-on-content-click="false"
6
- :nudge-right="40"
7
- :return-value.sync="fieldRange"
8
- transition="scale-transition"
9
- offset-y
10
- min-width="290px"
5
+ ref="contextmenu"
6
+ maxHeight="auto"
7
+ bottom
8
+ popup-width="320"
11
9
  >
12
- <template v-slot:activator="{}">
13
- <farm-textfield-v2
14
- v-model="fieldRange"
15
- icon="calendar"
16
- readonly
17
- :id="inputId"
18
- :rules="required ? [requiredRule] : []"
19
- @click="openDatepicker"
20
- @onClickIcon="openDatepicker"
21
- />
22
- </template>
23
10
  <v-date-picker
24
11
  v-if="menuField"
12
+ class="datepicker"
25
13
  v-model="dateField"
26
14
  no-title
27
15
  scrollable
@@ -34,18 +22,27 @@
34
22
  <farm-btn outlined color="secondary" @click="closeDatepicker" title="Fechar">
35
23
  Fechar
36
24
  </farm-btn>
37
- <farm-btn outlined class="ml-2" @click="clear()" title="Limpar"> Limpar</farm-btn>
38
- <farm-btn class="ml-2" :disabled="canConfirm" @click="save()" title="Confirmar">
25
+ <farm-btn outlined class="btn-clean" @click="clear"> Limpar </farm-btn>
26
+ <farm-btn class="ml-2" title="Confirmar" :disabled="!dateField.length" @click="save()">
39
27
  Confirmar
40
28
  </farm-btn>
41
29
  </v-date-picker>
42
- </v-menu>
30
+ <template v-slot:activator="{ }">
31
+ <farm-textfield-v2
32
+ v-model="fieldRange"
33
+ icon="calendar"
34
+ readonly
35
+ :id="inputId"
36
+ :rules="required ? [requiredRule] : []"
37
+ @click="openDatepicker"
38
+ @onClickIcon="openDatepicker"
39
+ />
40
+ </template>
41
+ </farm-contextmenu>
43
42
  </template>
44
43
  <script>
45
44
  import Vue from 'vue';
46
- import { VMenu } from 'vuetify/lib/components/VMenu';
47
45
  import { VDatePicker } from 'vuetify/lib/components/VDatePicker';
48
- import DefaultButton from '../Buttons/DefaultButton';
49
46
  import { defaultFormat as dateDefaultFormatter } from '../../helpers/date';
50
47
  /**
51
48
  * Componente de input com datepicker para range de data
@@ -53,9 +50,7 @@ import { defaultFormat as dateDefaultFormatter } from '../../helpers/date';
53
50
  export default Vue.extend({
54
51
  name: 'farm-input-rangedatepicker',
55
52
  components: {
56
- VMenu,
57
53
  VDatePicker,
58
- 'farm-btn': DefaultButton,
59
54
  },
60
55
  props: {
61
56
  /**
@@ -127,9 +122,10 @@ export default Vue.extend({
127
122
  return dateDefaultFormatter(dateStart) + ' a ' + dateDefaultFormatter(dateEnd);
128
123
  },
129
124
  save() {
130
- this.$refs.menuField.save(this.formatDateRange(this.dateField));
125
+ this.formatDateRange(this.dateField);
131
126
  this.inputVal = this.dateField;
132
127
  this.menuField = false;
128
+ this.closeDatepicker();
133
129
  },
134
130
  clear() {
135
131
  this.dateField = [];
@@ -140,6 +136,7 @@ export default Vue.extend({
140
136
  },
141
137
  closeDatepicker() {
142
138
  this.menuField = false;
139
+ this.$refs.contextmenu.inputValue = false;
143
140
  },
144
141
  },
145
142
  computed: {
@@ -158,7 +155,5 @@ export default Vue.extend({
158
155
  });
159
156
  </script>
160
157
  <style lang="scss" scoped>
161
- .theme--light.v-input.v-input--dense.v-text-field.v-text-field--outlined.error--text:after {
162
- content: '' !important;
163
- }
158
+ @import '../DatePicker/DatePicker.scss';
164
159
  </style>
@@ -1,8 +1,8 @@
1
1
  $colors: primary, secondary, error, accent, info, success, warning, gray, yellow, white;
2
2
  $sizes: (
3
3
  "xs": 12px,
4
- "sm": 16px,
5
- "md": 24px,
4
+ "sm": 14px,
5
+ "md": 20px,
6
6
  "lg": 36px,
7
7
  "xl": 40px
8
8
  );