@bildvitta/quasar-ui-asteroid 3.20.0-beta.0 → 3.20.0-beta.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,7 +1,7 @@
1
1
  {
2
2
  "name": "@bildvitta/quasar-ui-asteroid",
3
3
  "description": "Asteroid",
4
- "version": "3.20.0-beta.0",
4
+ "version": "3.20.0-beta.2",
5
5
  "author": "Bild & Vitta <systemteam@bild.com.br>",
6
6
  "license": "MIT",
7
7
  "main": "./src/asteroid.js",
@@ -86,6 +86,10 @@ const props = defineProps({
86
86
  type: String
87
87
  },
88
88
 
89
+ useDropdownAlways: {
90
+ type: Boolean
91
+ },
92
+
89
93
  useLabel: {
90
94
  default: true,
91
95
  type: Boolean
@@ -209,7 +213,13 @@ const formattedList = computed(() => {
209
213
  */
210
214
  const payload = { dropdownList: {}, buttonsList: {} }
211
215
 
212
- if ((!hasSplitName.value || screen.isSmall) && !isSingle.value) {
216
+ /**
217
+ * Se a prop "useDropdownAlways" for true, significa que sempre usaremos o dropdown,
218
+ * mesmo que tenha apenas 1 item na lista ou que não tenha splitName.
219
+ * Também se não tiver splitName e a tela for pequena (mobile/tablet) e não for
220
+ * single, usaremos o dropdown.
221
+ */
222
+ if (props.useDropdownAlways || ((!hasSplitName.value || screen.isSmall) && !isSingle.value)) {
213
223
  const { buttonsList } = useOptionsActions({ color: DEFAULT_COLOR, props })
214
224
 
215
225
  payload.buttonsList = buttonsList.value
@@ -49,6 +49,11 @@ props:
49
49
  type: String
50
50
  examples: [visibility]
51
51
 
52
+ use-dropdown-always:
53
+ desc: Força o uso do dropdown mesmo caso tenha apenas 1 item na lista de ações.
54
+ default: false
55
+ type: Boolean
56
+
52
57
  use-tooltip:
53
58
  desc: Controla se vai ter o tooltip caso passe nas regras de exibição de tooltip
54
59
 
@@ -3,8 +3,10 @@
3
3
  <div v-if="hasButtons" :class="classes.list">
4
4
  <div v-for="(buttonProps, key, index) in props.buttonsPropsList" :key="key">
5
5
  <div class="flex no-wrap">
6
- <qas-btn :disable="props.disable" v-bind="buttonProps" no-wrap variant="tertiary" @click="onClick">
7
- <q-menu v-if="hasMenuOnLeftSide" v-model="isMenuOpened" anchor="bottom right" :auto-close="props.useAutoClose" class="qas-menu" self="top right" @update:model-value="onUpdateMenuValue">
6
+ <qas-btn v-bind="buttonProps" :data-btn-dropdown="key" :disable="props.disable" no-wrap variant="tertiary" @click="onClick">
7
+ <slot v-if="hasBtnContentSlot(key)" :name="`btn-content-${key}`" />
8
+
9
+ <q-menu v-else-if="hasMenuOnLeftSide" v-model="isMenuOpened" anchor="bottom right" :auto-close="props.useAutoClose" class="qas-menu" self="top right" @update:model-value="onUpdateMenuValue">
8
10
  <div :class="classes.menuContent">
9
11
  <slot />
10
12
  </div>
@@ -142,6 +144,10 @@ function isLast (index) {
142
144
  function hasSeparator (index) {
143
145
  return props.useSplit || !isLast(index)
144
146
  }
147
+
148
+ function hasBtnContentSlot (name) {
149
+ return !!slots[`btn-content-${name}`]
150
+ }
145
151
  </script>
146
152
 
147
153
  <style lang="scss">
@@ -44,9 +44,13 @@ props:
44
44
  slots:
45
45
  default:
46
46
  desc: Slot para passar o conteúdo do dropdown (menu).
47
+
47
48
  bottom-[buttons-props-list-key]:
48
49
  desc: Slot unitário para acessar abaixo de cada botão (normalmente utilizado para tooltip).
49
50
 
51
+ btn-content-[buttons-props-list-key]:
52
+ desc: Slot para acessar o conteúdo dentro do botão, exemplo de uso QMenu.
53
+
50
54
  events:
51
55
  '@click -> function (event)':
52
56
  desc: Caso não tenha "useSplit", o evento é disparado ao clicar no componente como um todo, caso tenha "useSplit", o evento é disparado ao clicar no botão a esquerda.
@@ -5,9 +5,9 @@
5
5
  <slot :filter="filter" name="search">
6
6
  <q-form v-if="useSearch" @submit.prevent="filter()">
7
7
  <qas-search-input v-model="internalSearch" :placeholder="searchPlaceholder" :use-search-on-type="useSearchOnType" @clear="clearSearch" @filter="filter()" @update:model-value="onSearch">
8
- <template v-if="showFilterButton" #after-clear>
8
+ <template v-if="showFilterActions" #after-clear>
9
9
  <slot :context="mx_context" :filter="filter" :filters="activeFilters" name="filter-button" :remove-filter="removeFilter">
10
- <pv-filters-button v-if="useFilterButton" ref="filtersButton" v-model="internalFilters" v-bind="filterButtonProps" />
10
+ <pv-filters-actions ref="filtersActions" v-model:filtersButton="internalFilters" v-bind="filtersActionsProps" />
11
11
  </slot>
12
12
  </template>
13
13
  </qas-search-input>
@@ -15,14 +15,20 @@
15
15
  </slot>
16
16
  </div>
17
17
 
18
- <div v-else-if="showFilterButton" class="col-12">
18
+ <div v-else-if="showFilterActions" class="col-12">
19
19
  <slot :context="mx_context" :filter="filter" :filters="activeFilters" name="filter-button" :remove-filter="removeFilter">
20
- <pv-filters-button v-if="useFilterButton" ref="filtersButton" v-model="internalFilters" v-bind="filterButtonProps" />
20
+ <pv-filters-actions ref="filtersActions" v-model:filtersButton="internalFilters" v-bind="filtersActionsProps" />
21
21
  </slot>
22
22
  </div>
23
23
  </div>
24
24
 
25
25
  <div v-if="hasChip" class="q-mt-md">
26
+ <qas-badge v-if="hasOrderByChip" color="grey-4" removable text-color="black" @remove="changeOrderBy(undefined)">
27
+ <div class="ellipsis qas-filters__badge-content" :title="orderByLabel">
28
+ Ordenar por: "{{ orderByLabel }}"
29
+ </div>
30
+ </qas-badge>
31
+
26
32
  <qas-badge v-for="(filterItem, key) in activeFilters" :key="key" :data-cy="`filters-${filterItem.value}-chip`" removable @remove="removeFilter(filterItem)">
27
33
  <div class="ellipsis qas-filters__badge-content" :title="getChipValue(filterItem.value)">
28
34
  {{ filterItem.label }}: "{{ getChipValue(filterItem.value) }}"
@@ -37,7 +43,7 @@
37
43
  <script>
38
44
  import QasBadge from '../badge/QasBadge.vue'
39
45
  import QasSearchInput from '../search-input/QasSearchInput.vue'
40
- import PvFiltersButton from './private/PvFiltersButton.vue'
46
+ import PvFiltersActions from './private/PvFiltersActions.vue'
41
47
 
42
48
  import { useOverlayNavigation } from '../../composables'
43
49
 
@@ -54,9 +60,9 @@ export default {
54
60
  name: 'QasFilters',
55
61
 
56
62
  components: {
57
- PvFiltersButton,
58
63
  QasBadge,
59
- QasSearchInput
64
+ QasSearchInput,
65
+ PvFiltersActions
60
66
  },
61
67
 
62
68
  mixins: [contextMixin],
@@ -72,11 +78,21 @@ export default {
72
78
  type: Object
73
79
  },
74
80
 
81
+ fieldsProps: {
82
+ default: () => ({}),
83
+ type: Object
84
+ },
85
+
75
86
  listenerQueryKeys: {
76
87
  type: Array,
77
88
  default: () => []
78
89
  },
79
90
 
91
+ orderByOptions: {
92
+ default: () => ([]),
93
+ type: Array
94
+ },
95
+
80
96
  searchPlaceholder: {
81
97
  default: 'Pesquisar...',
82
98
  type: String
@@ -123,11 +139,6 @@ export default {
123
139
  useUpdateRoute: {
124
140
  default: true,
125
141
  type: Boolean
126
- },
127
-
128
- fieldsProps: {
129
- default: () => ({}),
130
- type: Object
131
142
  }
132
143
  },
133
144
 
@@ -233,25 +244,30 @@ export default {
233
244
  return this.hasActiveFilters ? 'primary' : 'grey-10'
234
245
  },
235
246
 
236
- filterButtonProps () {
247
+ filtersActionsProps () {
237
248
  return {
238
- color: this.filterButtonColor,
239
- error: this.hasFetchError,
240
- fields: this.fields,
241
- fieldsProps: this.formattedFieldsProps,
242
- loading: this.isFetching,
243
- menuProps: {
244
- /**
245
- * O tratamento no onHide do menu é que como o menu é recriado toda vez que o filtro é aberto, ocorre que as
246
- * opções selecionadas anteriormente (e que não foram filtradas) não ficam salvas na memória, ocasionando em
247
- * campos lazy loading um problema de exibir o uuid da opção por não achar essa opção no array de options do field.
248
- * Para solucionar esse problema, sempre ao fechar os filtros as opções não filtradas são removidas,
249
- * voltando o filtro para o seu estado anterior.
250
- */
251
- onHide: this.setInternalFilters
249
+ orderByOptions: this.orderByOptions,
250
+ useOrderBy: this.hasOrderByOptions,
251
+ useFilterButton: this.useFilterButton,
252
+
253
+ filtersButtonProps: {
254
+ color: this.filterButtonColor,
255
+ error: this.hasFetchError,
256
+ fields: this.fields,
257
+ fieldsProps: this.formattedFieldsProps,
258
+ loading: this.isFetching
252
259
  },
253
260
 
254
- onClear: this.clearFilters,
261
+ /**
262
+ * O tratamento no onHide do menu é que como o menu é recriado toda vez que o filtro é aberto, ocorre que as
263
+ * opções selecionadas anteriormente (e que não foram filtradas) não ficam salvas na memória, ocasionando em
264
+ * campos lazy loading um problema de exibir o uuid da opção por não achar essa opção no array de options do field.
265
+ * Para solucionar esse problema, sempre ao fechar os filtros as opções não filtradas são removidas,
266
+ * voltando o filtro para o seu estado anterior.
267
+ */
268
+ onHideFiltersMenu: this.setInternalFilters,
269
+ onClearFilters: this.clearFilters,
270
+ onChangeOrder: this.changeOrderBy,
255
271
  onFilter: () => this.filter()
256
272
  }
257
273
  },
@@ -264,12 +280,12 @@ export default {
264
280
  return !!Object.keys(this.fields || {}).length
265
281
  },
266
282
 
267
- showFilterButton () {
268
- return !!this.$slots.filterButton || this.useFilterButton
283
+ showFilterActions () {
284
+ return !!this.$slots.filterButton || this.useFilterButton || this.hasOrderByOptions
269
285
  },
270
286
 
271
287
  showFilters () {
272
- return this.useFilterButton || this.showSearch
288
+ return this.useFilterButton || this.showSearch || this.hasOrderByOptions
273
289
  },
274
290
 
275
291
  showSearch () {
@@ -277,7 +293,23 @@ export default {
277
293
  },
278
294
 
279
295
  hasChip () {
280
- return this.useChip && this.hasActiveFilters
296
+ return this.useChip && (this.hasActiveFilters || this.orderBy)
297
+ },
298
+
299
+ hasOrderByOptions () {
300
+ return !!this.orderByOptions.length
301
+ },
302
+
303
+ hasOrderByChip () {
304
+ return !!this.orderBy && this.hasOrderByOptions
305
+ },
306
+
307
+ orderBy () {
308
+ return this.$route.query.order_by
309
+ },
310
+
311
+ orderByLabel () {
312
+ return this.orderByOptions.find(option => option.value === this.orderBy)?.label
281
313
  }
282
314
  },
283
315
 
@@ -419,7 +451,7 @@ export default {
419
451
  },
420
452
 
421
453
  hideFiltersMenu () {
422
- this.$refs.filtersButton?.hideMenu()
454
+ this.$refs.filtersActions?.hideFiltersMenu()
423
455
  },
424
456
 
425
457
  setInternalFilters () {
@@ -492,6 +524,10 @@ export default {
492
524
  for (const key in filters) {
493
525
  this.internalFilters[key] = parseValue(this.normalizeValues(filters[key], this.fields[key]?.multiple))
494
526
  }
527
+ },
528
+
529
+ changeOrderBy (value) {
530
+ this.filter({ order_by: value })
495
531
  }
496
532
  }
497
533
  }
@@ -34,6 +34,11 @@ props:
34
34
  default: []
35
35
  type: Array
36
36
 
37
+ order-by-options:
38
+ desc: Opções de ordenação que serão exibidas no botão de ordenar.
39
+ default: []
40
+ type: Array
41
+
37
42
  search-placeholder:
38
43
  desc: Placeholder do campo de busca.
39
44
  default: Pesquisar...
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <qas-btn-dropdown v-bind="btnDropdownProps">
3
+ <!-- Seção do botão de filtrar -->
4
+ <template v-if="props.useFilterButton" #btn-content-filtersButton>
5
+ <q-menu ref="filtersButtonMenu" anchor="center right" class="full-width" max-width="270px" no-refocus self="top right" @hide="emit('hide-filters-menu')">
6
+ <div v-if="props.filtersButtonProps.loading" class="q-pa-xl text-center">
7
+ <q-spinner color="grey" size="2em" />
8
+ </div>
9
+
10
+ <div v-else-if="props.filtersButtonProps.error" class="q-pa-xl text-center">
11
+ <q-icon color="negative" name="sym_r_warning" size="2em" />
12
+ </div>
13
+
14
+ <q-form v-else class="q-gutter-y-md q-pa-md" @submit.prevent="emit('filter')">
15
+ <div v-for="(field, index) in props.filtersButtonProps.fields" :key="index">
16
+ <qas-field v-model="filtersButtonModel[field.name]" :data-cy="`filters-${field.name}-field`" :field="field" v-bind="props.filtersButtonProps.fieldsProps[field.name]" />
17
+ </div>
18
+
19
+ <qas-actions gutter="sm" use-equal-width>
20
+ <template #primary>
21
+ <qas-btn class="full-width" data-cy="filters-submit-btn" label="Filtrar" size="sm" type="submit" variant="primary" />
22
+ </template>
23
+
24
+ <template #secondary>
25
+ <qas-btn class="full-width" data-cy="filters-clear-btn" label="Limpar" size="sm" variant="secondary" @click="emit('clear-filters')" />
26
+ </template>
27
+ </qas-actions>
28
+ </q-form>
29
+ </q-menu>
30
+ </template>
31
+
32
+ <!-- Seção do botão de ordenar -->
33
+ <template v-if="props.useOrderBy" #btn-content-orderBy>
34
+ <q-menu anchor="bottom right" class="qas-menu" self="top right">
35
+ <q-list>
36
+ <q-item v-for="option in props.orderByOptions" :key="option.value" :active="isActive(option.value)" active-class="text-primary" clickable @click="emit('change-order', option.value)">
37
+ <q-item-section>
38
+ <q-item-label>
39
+ {{ option.label }}
40
+ </q-item-label>
41
+ </q-item-section>
42
+ </q-item>
43
+ </q-list>
44
+ </q-menu>
45
+ </template>
46
+ </qas-btn-dropdown>
47
+ </template>
48
+
49
+ <script setup>
50
+ import QasActions from '../../actions/QasActions.vue'
51
+ import QasBtn from '../../btn/QasBtn.vue'
52
+ import QasBtnDropdown from '../../btn-dropdown/QasBtnDropdown.vue'
53
+ import QasField from '../../field/QasField.vue'
54
+
55
+ import { useRoute } from 'vue-router'
56
+ import { computed, ref } from 'vue'
57
+
58
+ defineOptions({ name: 'PvFiltersActions' })
59
+
60
+ const props = defineProps({
61
+ filtersButtonProps: {
62
+ default: () => ({}),
63
+ type: Object
64
+ },
65
+
66
+ orderByOptions: {
67
+ default: () => ([]),
68
+ type: Array
69
+ },
70
+
71
+ useFilterButton: {
72
+ type: Boolean
73
+ },
74
+
75
+ useOrderBy: {
76
+ type: Boolean
77
+ }
78
+ })
79
+
80
+ // models
81
+ const filtersButtonModel = defineModel('filtersButton', { type: Object, default: () => ({}) })
82
+
83
+ // emits
84
+ const emit = defineEmits(['change-order', 'clear-filters', 'filter', 'hide-filters-menu'])
85
+
86
+ // expose
87
+ defineExpose({ hideFiltersMenu })
88
+
89
+ // template refs
90
+ const filtersButtonMenu = ref(null)
91
+
92
+ // composables
93
+ const route = useRoute()
94
+
95
+ // computeds
96
+ const btnDropdownProps = computed(() => {
97
+ return {
98
+ buttonsPropsList: {
99
+ ...(props.useFilterButton && {
100
+ filtersButton: {
101
+ label: 'Filtrar',
102
+ useLabelOnSmallScreen: false,
103
+ icon: 'sym_r_filter_alt',
104
+ 'data-cy': 'filters-btn' // manter compatibilidade
105
+ }
106
+ }),
107
+
108
+ ...(props.useOrderBy && {
109
+ orderBy: {
110
+ color: 'grey-10',
111
+ label: 'Ordenar',
112
+ useLabelOnSmallScreen: false,
113
+ icon: 'sym_r_swap_vert'
114
+ }
115
+ })
116
+ }
117
+ }
118
+ })
119
+
120
+ // functions
121
+ /**
122
+ * Retorna se a opção de ordenação está ativa.
123
+ *
124
+ * @param {string} value
125
+ */
126
+ function isActive (value) {
127
+ return route.query.order_by === value
128
+ }
129
+
130
+ function hideFiltersMenu () {
131
+ filtersButtonMenu.value?.hide()
132
+ }
133
+ </script>
@@ -36,6 +36,14 @@
36
36
  </component>
37
37
  </q-td>
38
38
  </template>
39
+
40
+ <template v-for="(column, index) in columnsWithTooltip" :key="index" #[`header-cell-${column.name}`]="context">
41
+ <q-th :props="context">
42
+ {{ context.col.label }}
43
+
44
+ <qas-tip class="q-pl-xs" :text="column.tooltip" />
45
+ </q-th>
46
+ </template>
39
47
  </q-table>
40
48
 
41
49
  <qas-empty-result-text v-if="!hasResults" />
@@ -45,9 +53,10 @@
45
53
  <script>
46
54
  import PvTableGeneratorTd from './private/PvTableGeneratorTd.vue'
47
55
  import QasBox from '../box/QasBox.vue'
56
+ import QasCheckbox from '../checkbox/QasCheckbox.vue'
48
57
  import QasEmptyResultText from '../empty-result-text/QasEmptyResultText.vue'
49
58
  import QasHeader from '../header/QasHeader.vue'
50
- import QasCheckbox from '../checkbox/QasCheckbox.vue'
59
+ import QasTip from '../tip/QasTip.vue'
51
60
 
52
61
  import { isEmpty, humanize, setScrollOnGrab, setScrollGradient } from '../../helpers'
53
62
 
@@ -61,7 +70,8 @@ export default {
61
70
  QasBox,
62
71
  QasEmptyResultText,
63
72
  QasHeader,
64
- QasCheckbox
73
+ QasCheckbox,
74
+ QasTip
65
75
  },
66
76
 
67
77
  provide () {
@@ -70,7 +80,7 @@ export default {
70
80
  * @see QasBtn.vue - Injetando os valores padrões para o QasBtn.
71
81
  */
72
82
  btnPropsDefaults: {
73
- size: 'md'
83
+ size: 'sm'
74
84
  }
75
85
  }
76
86
  },
@@ -146,6 +156,10 @@ export default {
146
156
  default: true
147
157
  },
148
158
 
159
+ useMultiline: {
160
+ type: Boolean
161
+ },
162
+
149
163
  useObjectSelectedModel: {
150
164
  type: Boolean
151
165
  },
@@ -287,7 +301,11 @@ export default {
287
301
  * caso tenha a prop "actionsMenuProps" é adicionado automaticamente a coluna "actions" como ultimo item
288
302
  */
289
303
  normalizedColumns () {
290
- return this.hasActionsMenu ? [...this.columns, { name: 'actions' }] : this.columns
304
+ return this.hasActionsMenu ? [...this.columns, { name: 'actions', label: 'Ações' }] : this.columns
305
+ },
306
+
307
+ columnsWithTooltip () {
308
+ return this.normalizedColumns.filter(column => column.tooltip)
291
309
  },
292
310
 
293
311
  hasFields () {
@@ -301,6 +319,10 @@ export default {
301
319
 
302
320
  const mappedResults = results.map((result, index) => {
303
321
  for (const key in result) {
322
+ if (this.fields[key]?.type === 'object') {
323
+ continue
324
+ }
325
+
304
326
  const humanizedResult = humanize(this.fields[key], result[key])
305
327
  const formattedResult = isEmpty({ value: humanizedResult }) ? this.emptyResultText : humanizedResult
306
328
 
@@ -322,7 +344,8 @@ export default {
322
344
  return {
323
345
  'qas-table-generator--mobile': this.$qas.screen.isSmall,
324
346
  'qas-table-generator--sticky-header': this.useStickyHeader,
325
- 'qas-table-generator--has-actions': this.hasActionsMenu
347
+ 'qas-table-generator--has-actions': this.hasActionsMenu,
348
+ 'qas-table-generator--multiline': this.useMultiline
326
349
  }
327
350
  },
328
351
 
@@ -539,7 +562,7 @@ export default {
539
562
  }
540
563
 
541
564
  th {
542
- @include set-typography($subtitle1);
565
+ @include set-typography($subtitle2);
543
566
 
544
567
  color: $grey-10;
545
568
 
@@ -554,18 +577,10 @@ export default {
554
577
  }
555
578
  }
556
579
 
557
- border: 0 !important;
558
- padding-bottom: 0;
580
+ padding-bottom: var(--qas-spacing-sm);;
559
581
  padding-left: 0;
560
582
  padding-top: 0;
561
-
562
- &:not(:last-child) {
563
- padding-right: var(--qas-spacing-md);
564
- }
565
-
566
- &:last-child {
567
- padding-right: 0;
568
- }
583
+ padding-right: var(--qas-spacing-md);
569
584
  }
570
585
 
571
586
  td,
@@ -576,7 +591,7 @@ export default {
576
591
  }
577
592
 
578
593
  td {
579
- @include set-typography($body1);
594
+ @include set-typography($body2);
580
595
 
581
596
  height: 40px;
582
597
  padding-bottom: var(--qas-spacing-sm);
@@ -584,14 +599,7 @@ export default {
584
599
  padding-top: var(--qas-spacing-sm);
585
600
  position: relative;
586
601
  z-index: 0;
587
-
588
- &:not(:last-child) {
589
- padding-right: var(--qas-spacing-md);
590
- }
591
-
592
- &:last-child {
593
- padding-right: 0;
594
- }
602
+ padding-right: var(--qas-spacing-md);
595
603
 
596
604
  &::before {
597
605
  position: absolute;
@@ -648,18 +656,22 @@ export default {
648
656
  }
649
657
  }
650
658
 
659
+ &--multiline {
660
+ @media (min-width: $breakpoint-sm) {
661
+ .q-table td {
662
+ *:not(.qas-btn, .qas-btn *, .q-badge, .q-badge *){
663
+ white-space: normal;
664
+ overflow-wrap: anywhere;
665
+ }
666
+ }
667
+ }
668
+ }
669
+
651
670
  .q-table__container {
652
671
  margin-left: calc(var(--qas-spacing-md) * -1);
653
672
  margin-right: calc(var(--qas-spacing-md) * -1);
654
673
  }
655
674
 
656
- &--has-actions {
657
- td:last-child #{$root}__td-item {
658
- display: flex;
659
- justify-content: flex-end;
660
- }
661
- }
662
-
663
675
  &--mobile {
664
676
  margin: 0 -10px;
665
677
 
@@ -99,6 +99,11 @@ props:
99
99
  default: true
100
100
  type: Boolean
101
101
 
102
+ use-multiline:
103
+ desc: Usado para permitir que o conteúdo da célula quebre linha (não permite scroll na tabela a partir de tablet).
104
+ default: false
105
+ type: Boolean
106
+
102
107
  use-object-selected-model:
103
108
  desc: Usado para definir o modelo de seleção como um array de objeto ao invés de um array de string.
104
109
  default: false
@@ -21,12 +21,15 @@
21
21
  </div>
22
22
 
23
23
  <qas-btn class="q-ml-sm qas-toggle-visibility__button" :icon />
24
+
25
+ <qas-tooltip :text="tooltipText" />
24
26
  </div>
25
27
  </div>
26
28
  </template>
27
29
 
28
30
  <script setup>
29
31
  import QasBtn from '../btn/QasBtn.vue'
32
+ import QasTooltip from '../tooltip/QasTooltip.vue'
30
33
 
31
34
  import { useToggleVisibility } from '../../composables/private'
32
35
 
@@ -54,6 +57,16 @@ const props = defineProps({
54
57
  width: {
55
58
  type: String,
56
59
  default: '140px'
60
+ },
61
+
62
+ visibleTooltip: {
63
+ type: String,
64
+ default: 'Ocultar conteúdo'
65
+ },
66
+
67
+ hiddenTooltip: {
68
+ type: String,
69
+ default: 'Visualizar conteúdo'
57
70
  }
58
71
  })
59
72
 
@@ -64,6 +77,7 @@ const {
64
77
 
65
78
  const icon = computed(() => isVisible.value ? 'sym_r_visibility' : 'sym_r_visibility_off')
66
79
  const style = computed(() => ({ width: props.width }))
80
+ const tooltipText = computed(() => isVisible.value ? props.visibleTooltip : props.hiddenTooltip)
67
81
  </script>
68
82
 
69
83
  <style lang="scss">
@@ -25,6 +25,16 @@ props:
25
25
  default: '140px'
26
26
  type: String
27
27
 
28
+ visible-tooltip:
29
+ desc: Texto do tooltip exibido quando o conteúdo está visível.
30
+ default: 'Ocultar conteúdo'
31
+ type: String
32
+
33
+ hidden-tooltip:
34
+ desc: Texto do tooltip exibido quando o conteúdo está oculto.
35
+ default: 'Exibir conteúdo'
36
+ type: String
37
+
28
38
  slots:
29
39
  default:
30
40
  desc: Slot para inserir conteúdo a ser oculto/exibido.
@@ -1,10 +1,12 @@
1
1
  <template>
2
2
  <q-tooltip v-bind="tooltipProps" class="bg-grey-10 text-caption">
3
- {{ props.text }}
3
+ <qas-breakline :text="props.text" />
4
4
  </q-tooltip>
5
5
  </template>
6
6
 
7
7
  <script setup>
8
+ import QasBreakline from '../breakline/QasBreakline.vue'
9
+
8
10
  defineOptions({ name: 'QasTooltip' })
9
11
 
10
12
  const props = defineProps({
@@ -18,6 +20,7 @@ const props = defineProps({
18
20
  const tooltipProps = {
19
21
  anchor: 'center right',
20
22
  self: 'center left',
21
- offset: [5, 5]
23
+ offset: [5, 5],
24
+ maxWidth: '300px'
22
25
  }
23
26
  </script>
@@ -14,7 +14,7 @@
14
14
  padding: var(--qas-spacing-xs) var(--qas-spacing-md) !important;
15
15
 
16
16
  .q-icon {
17
- font-size: 16px !important;
17
+ font-size: 18fpx !important;
18
18
  }
19
19
 
20
20
  &.qas-btn--icon-only.qas-btn--primary,
@@ -88,6 +88,8 @@ function formatCompanyDocument (value) {
88
88
  }
89
89
 
90
90
  function formatDocument (value) {
91
+ if (!value) return ''
92
+
91
93
  return value.length < 12
92
94
  ? formatPersonalDocument(value)
93
95
  : formatCompanyDocument(value)
@@ -1,101 +0,0 @@
1
- <template>
2
- <qas-btn data-cy="filters-btn" icon="sym_r_filter_alt" label="Filtrar" :use-label-on-small-screen="false" variant="tertiary">
3
- <q-menu ref="menu" anchor="center right" class="full-width" max-width="270px" v-bind="menuProps" no-refocus self="top right">
4
- <div v-if="loading" class="q-pa-xl text-center">
5
- <q-spinner color="grey" size="2em" />
6
- </div>
7
-
8
- <div v-else-if="error" class="q-pa-xl text-center">
9
- <q-icon color="negative" name="sym_r_warning" size="2em" />
10
- </div>
11
-
12
- <q-form v-else class="q-gutter-y-md q-pa-md" @submit.prevent="$emit('filter')">
13
- <div v-for="(field, index) in fields" :key="index">
14
- <qas-field v-model="filters[field.name]" :data-cy="`filters-${field.name}-field`" :field="field" v-bind="fieldsProps[field.name]" />
15
- </div>
16
-
17
- <qas-actions gutter="sm" use-equal-width>
18
- <template #primary>
19
- <qas-btn class="full-width" data-cy="filters-submit-btn" label="Filtrar" size="sm" type="submit" variant="primary" />
20
- </template>
21
-
22
- <template #secondary>
23
- <qas-btn class="full-width" data-cy="filters-clear-btn" label="Limpar" size="sm" variant="secondary" @click="$emit('clear')" />
24
- </template>
25
- </qas-actions>
26
- </q-form>
27
- </q-menu>
28
- </qas-btn>
29
- </template>
30
-
31
- <script>
32
- import QasActions from '../../actions/QasActions.vue'
33
- import QasBtn from '../../btn/QasBtn.vue'
34
- import QasField from '../../field/QasField.vue'
35
-
36
- export default {
37
- name: 'PvFiltersButton',
38
-
39
- components: {
40
- QasActions,
41
- QasBtn,
42
- QasField
43
- },
44
-
45
- props: {
46
- color: {
47
- type: String,
48
- default: 'grey-10',
49
- validator: value => ['grey-10', 'primary', 'white'].includes(value)
50
- },
51
-
52
- error: {
53
- type: Boolean
54
- },
55
-
56
- fields: {
57
- default: () => ({}),
58
- type: Object
59
- },
60
-
61
- fieldsProps: {
62
- default: () => ({}),
63
- type: Object
64
- },
65
-
66
- loading: {
67
- type: Boolean
68
- },
69
-
70
- menuProps: {
71
- default: () => ({}),
72
- type: Object
73
- },
74
-
75
- modelValue: {
76
- default: () => ({}),
77
- type: Object
78
- }
79
- },
80
-
81
- emits: ['clear', 'filter', 'update:modelValue'],
82
-
83
- computed: {
84
- filters: {
85
- get () {
86
- return this.modelValue
87
- },
88
-
89
- set (value) {
90
- return this.$emit('update:modelValue', value)
91
- }
92
- }
93
- },
94
-
95
- methods: {
96
- hideMenu () {
97
- this.$refs.menu.hide()
98
- }
99
- }
100
- }
101
- </script>