@bildvitta/quasar-ui-asteroid 3.18.0-beta.1 → 3.18.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 +1 -1
- package/src/components/badge/QasBadge.vue +2 -1
- package/src/components/btn/QasBtn.vue +2 -1
- package/src/components/copy/QasCopy.vue +6 -1
- package/src/components/search-box/QasSearchBox.vue +12 -3
- package/src/components/search-box/QasSearchBox.yml +6 -1
- package/src/components/table-generator/QasTableGenerator.vue +219 -33
- package/src/components/table-generator/QasTableGenerator.yml +25 -0
- package/src/components/table-generator/_components/PvTableGeneratorTd.vue +94 -0
- package/src/components/text-truncate/QasTextTruncate.vue +45 -12
- package/src/components/toggle-visibility/QasToggleVisibility.vue +2 -1
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<!-- "data-table-ignore-hover" é para não habilitar hover no texto no QasTableGenerator -->
|
|
3
|
+
<component :is="component.is" v-bind="component.props" class="q-px-sm qas-badge text-body2" data-table-ignore-hover>
|
|
3
4
|
<slot />
|
|
4
5
|
</component>
|
|
5
6
|
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<!-- "data-table-ignore-tr-hover" é para desabilitar o hover do tr no QasTableGenerator -->
|
|
3
|
+
<q-btn ref="button" class="qas-btn" data-table-ignore-tr-hover v-bind="attributes">
|
|
3
4
|
<slot />
|
|
4
5
|
|
|
5
6
|
<template v-for="(_, name) in nonDefaultSlots" #[name]="context">
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span>
|
|
3
|
-
|
|
3
|
+
<!-- "data-table-hover" é para habilitar hover no texto no QasTableGenerator -->
|
|
4
|
+
<span data-table-hover>
|
|
5
|
+
<slot v-if="props.useText">
|
|
6
|
+
{{ props.text }}
|
|
7
|
+
</slot>
|
|
8
|
+
</span>
|
|
4
9
|
|
|
5
10
|
<qas-btn class="q-ml-xs" color="primary" :icon="props.icon" :loading="isLoading" variant="tertiary" @click.stop.prevent="copy">
|
|
6
11
|
<q-tooltip>Copiar</q-tooltip>
|
|
@@ -58,11 +58,16 @@ export default {
|
|
|
58
58
|
type: Object
|
|
59
59
|
},
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
maxHeight: {
|
|
62
62
|
default: '300px',
|
|
63
63
|
type: String
|
|
64
64
|
},
|
|
65
65
|
|
|
66
|
+
height: {
|
|
67
|
+
default: '',
|
|
68
|
+
type: String
|
|
69
|
+
},
|
|
70
|
+
|
|
66
71
|
list: {
|
|
67
72
|
default: () => [],
|
|
68
73
|
type: Array
|
|
@@ -120,7 +125,11 @@ export default {
|
|
|
120
125
|
},
|
|
121
126
|
|
|
122
127
|
containerStyle () {
|
|
123
|
-
return {
|
|
128
|
+
return {
|
|
129
|
+
// Caso tenha height, deverá ter um tamanho fixo com base no height, portanto não terá max-height.
|
|
130
|
+
maxHeight: this.height ? 'auto' : this.containerHeight,
|
|
131
|
+
...(this.height && { height: this.height })
|
|
132
|
+
}
|
|
124
133
|
},
|
|
125
134
|
|
|
126
135
|
hasNoOptionsOnFirstFetch () {
|
|
@@ -130,7 +139,7 @@ export default {
|
|
|
130
139
|
containerHeight () {
|
|
131
140
|
const hasEmptyList = (!this.list.length && !this.useLazyLoading) || this.hasNoOptionsOnFirstFetch
|
|
132
141
|
|
|
133
|
-
return hasEmptyList ? this.emptyListHeight : this.
|
|
142
|
+
return hasEmptyList ? this.emptyListHeight : this.maxHeight
|
|
134
143
|
},
|
|
135
144
|
|
|
136
145
|
component () {
|
|
@@ -33,7 +33,12 @@ props:
|
|
|
33
33
|
|
|
34
34
|
height:
|
|
35
35
|
desc: Define altura do box quando a lista não está vazia.
|
|
36
|
-
default:
|
|
36
|
+
default: auto
|
|
37
|
+
type: String
|
|
38
|
+
|
|
39
|
+
maxHeight:
|
|
40
|
+
desc: Define altura máxima do box quando a lista não está vazia.
|
|
41
|
+
default: auto
|
|
37
42
|
type: String
|
|
38
43
|
|
|
39
44
|
lazy-loading-props:
|
|
@@ -1,19 +1,33 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<component :is="parentComponent.is">
|
|
2
|
+
<component :is="parentComponent.is" class="qas-table-generator" :class="tableClasses">
|
|
3
3
|
<slot name="parent-header">
|
|
4
4
|
<qas-header v-if="hasHeaderProps" v-bind="headerProps" />
|
|
5
5
|
</slot>
|
|
6
6
|
|
|
7
|
-
<q-table v-show="hasResults" ref="table" class="bg-white
|
|
7
|
+
<q-table v-show="hasResults" ref="table" class="bg-white text-grey-8" v-bind="attributes">
|
|
8
8
|
<template v-for="(_, name) in slots" #[name]="context">
|
|
9
9
|
<slot :name="name" v-bind="context" />
|
|
10
10
|
</template>
|
|
11
11
|
|
|
12
|
+
<template #header-cell="context">
|
|
13
|
+
<q-th v-if="context.col.label" :class="[context.col.headerClasses, context.col.__thClass]">
|
|
14
|
+
<qas-btn v-if="context.col.sortable" color="grey-10" icon-right="sym_r_swap_vert" :label="context.col.label" @click="$refs.table.sort(context.col)" />
|
|
15
|
+
|
|
16
|
+
<span v-else>
|
|
17
|
+
{{ context.col.label }}
|
|
18
|
+
</span>
|
|
19
|
+
</q-th>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
12
22
|
<template v-for="(fieldName, index) in bodyCellNameSlots" :key="index" #[`body-cell-${fieldName}`]="context">
|
|
13
|
-
<q-td>
|
|
14
|
-
<component :is="tdChildComponent" v-bind="getTdChildComponentProps(context.row)">
|
|
23
|
+
<q-td :class="getTdClasses(context.row)">
|
|
24
|
+
<component :is="tdChildComponent" class="qas-table-generator__td-item" v-bind="getTdChildComponentProps(context.row)">
|
|
15
25
|
<slot :name="`body-cell-${fieldName}`" v-bind="context || {}">
|
|
16
|
-
|
|
26
|
+
<pv-table-generator-td v-if="getFieldsProps(context.row, context.rowIndex)[fieldName]" :component-data="getFieldsProps(context.row, context.rowIndex)[fieldName]" :label="fields[fieldName]?.label" :name="fieldName" :row="context.row" />
|
|
27
|
+
|
|
28
|
+
<template v-else>
|
|
29
|
+
{{ context.row?.[fieldName] }}
|
|
30
|
+
</template>
|
|
17
31
|
</slot>
|
|
18
32
|
</component>
|
|
19
33
|
</q-td>
|
|
@@ -25,13 +39,24 @@
|
|
|
25
39
|
</template>
|
|
26
40
|
|
|
27
41
|
<script>
|
|
42
|
+
import PvTableGeneratorTd from './_components/PvTableGeneratorTd.vue'
|
|
43
|
+
|
|
28
44
|
import { extend } from 'quasar'
|
|
29
|
-
import { isEmpty, humanize, setScrollOnGrab } from '../../helpers'
|
|
45
|
+
import { isEmpty, humanize, setScrollOnGrab, setScrollGradient } from '../../helpers'
|
|
30
46
|
|
|
31
47
|
export default {
|
|
32
48
|
name: 'QasTableGenerator',
|
|
33
49
|
|
|
50
|
+
components: {
|
|
51
|
+
PvTableGeneratorTd
|
|
52
|
+
},
|
|
53
|
+
|
|
34
54
|
props: {
|
|
55
|
+
actionsMenuProps: {
|
|
56
|
+
default: undefined,
|
|
57
|
+
type: Function
|
|
58
|
+
},
|
|
59
|
+
|
|
35
60
|
columns: {
|
|
36
61
|
default: () => [],
|
|
37
62
|
type: Array
|
|
@@ -47,6 +72,11 @@ export default {
|
|
|
47
72
|
type: [Array, Object]
|
|
48
73
|
},
|
|
49
74
|
|
|
75
|
+
fieldsProps: {
|
|
76
|
+
default: () => ({}),
|
|
77
|
+
type: [Object, Function]
|
|
78
|
+
},
|
|
79
|
+
|
|
50
80
|
headerProps: {
|
|
51
81
|
default: () => ({}),
|
|
52
82
|
type: Object
|
|
@@ -101,7 +131,8 @@ export default {
|
|
|
101
131
|
scrollableElement: null,
|
|
102
132
|
scrollOnGrab: {},
|
|
103
133
|
elementToObserve: null,
|
|
104
|
-
resizeObserver: null
|
|
134
|
+
resizeObserver: null,
|
|
135
|
+
scrollGradientX: setScrollGradient({ orientation: 'x' })
|
|
105
136
|
}
|
|
106
137
|
},
|
|
107
138
|
|
|
@@ -115,8 +146,8 @@ export default {
|
|
|
115
146
|
bodyCellNameSlots () {
|
|
116
147
|
if (this.hasBodyCellSlot) return []
|
|
117
148
|
|
|
118
|
-
return this.
|
|
119
|
-
? this.
|
|
149
|
+
return this.normalizedColumns.length
|
|
150
|
+
? this.normalizedColumns.map(column => typeof column === 'object' ? column.name : column)
|
|
120
151
|
: Object.keys(this.fields)
|
|
121
152
|
},
|
|
122
153
|
|
|
@@ -145,7 +176,6 @@ export default {
|
|
|
145
176
|
tableClass: {
|
|
146
177
|
'overflow-hidden-y': !this.useStickyHeader && !this.useVirtualScroll
|
|
147
178
|
},
|
|
148
|
-
class: this.tableClass,
|
|
149
179
|
columns: this.columnsByFields,
|
|
150
180
|
flat: true,
|
|
151
181
|
hideBottom: true,
|
|
@@ -164,25 +194,28 @@ export default {
|
|
|
164
194
|
|
|
165
195
|
columnsByFields () {
|
|
166
196
|
if (!this.hasFields) {
|
|
167
|
-
return this.
|
|
197
|
+
return this.normalizedColumns.filter(column => column instanceof Object)
|
|
168
198
|
}
|
|
169
199
|
|
|
170
200
|
const columns = []
|
|
171
201
|
|
|
172
202
|
function columnByField (field) {
|
|
173
|
-
const {
|
|
203
|
+
const { label, name, sortable, sort, rawSort } = field
|
|
174
204
|
|
|
175
205
|
columns.push({
|
|
176
|
-
align:
|
|
206
|
+
align: 'left',
|
|
177
207
|
field: name,
|
|
178
208
|
label,
|
|
179
209
|
name,
|
|
180
|
-
headerClasses: 'text-grey-10'
|
|
210
|
+
headerClasses: 'text-grey-10',
|
|
211
|
+
sortable: sortable ?? true,
|
|
212
|
+
sort,
|
|
213
|
+
rawSort
|
|
181
214
|
})
|
|
182
215
|
}
|
|
183
216
|
|
|
184
217
|
// Automatic columns.
|
|
185
|
-
if (!this.
|
|
218
|
+
if (!this.normalizedColumns.length) {
|
|
186
219
|
for (const index in this.fields) {
|
|
187
220
|
columnByField(this.fields[index])
|
|
188
221
|
}
|
|
@@ -191,9 +224,10 @@ export default {
|
|
|
191
224
|
}
|
|
192
225
|
|
|
193
226
|
// Sorting from the column list.
|
|
194
|
-
this.
|
|
227
|
+
this.normalizedColumns.forEach(column => {
|
|
195
228
|
if (column instanceof Object) {
|
|
196
|
-
|
|
229
|
+
// repassa as props e mergeia com as do field
|
|
230
|
+
columnByField({ ...column, ...this.fields[column.name] })
|
|
197
231
|
} else if (this.fields[column]) {
|
|
198
232
|
columnByField(this.fields[column])
|
|
199
233
|
}
|
|
@@ -202,6 +236,17 @@ export default {
|
|
|
202
236
|
return columns
|
|
203
237
|
},
|
|
204
238
|
|
|
239
|
+
hasActionsMenu () {
|
|
240
|
+
return typeof this.actionsMenuProps === 'function'
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* caso tenha a prop "actionsMenuProps" é adicionado automaticamente a coluna "actions" como ultimo item
|
|
245
|
+
*/
|
|
246
|
+
normalizedColumns () {
|
|
247
|
+
return this.hasActionsMenu ? [...this.columns, { name: 'actions' }] : this.columns
|
|
248
|
+
},
|
|
249
|
+
|
|
205
250
|
hasFields () {
|
|
206
251
|
return Object.keys(this.fields).length
|
|
207
252
|
},
|
|
@@ -230,10 +275,11 @@ export default {
|
|
|
230
275
|
return this.results.length
|
|
231
276
|
},
|
|
232
277
|
|
|
233
|
-
|
|
278
|
+
tableClasses () {
|
|
234
279
|
return {
|
|
235
280
|
'qas-table-generator--mobile': this.$qas.screen.isSmall,
|
|
236
|
-
'qas-table-generator--sticky-header': this.useStickyHeader
|
|
281
|
+
'qas-table-generator--sticky-header': this.useStickyHeader,
|
|
282
|
+
'qas-table-generator--has-actions': this.hasActionsMenu
|
|
237
283
|
}
|
|
238
284
|
},
|
|
239
285
|
|
|
@@ -255,10 +301,24 @@ export default {
|
|
|
255
301
|
|
|
256
302
|
hasHeaderProps () {
|
|
257
303
|
return !!Object.keys(this.headerProps).length
|
|
304
|
+
},
|
|
305
|
+
|
|
306
|
+
hasAutoScrollY () {
|
|
307
|
+
return this.useStickyHeader || this.useVirtualScroll
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
hasRowClick () {
|
|
311
|
+
return typeof this.$attrs.onRowClick === 'function'
|
|
258
312
|
}
|
|
259
313
|
},
|
|
260
314
|
|
|
261
315
|
mounted () {
|
|
316
|
+
if (!this.hasAutoScrollY) {
|
|
317
|
+
const scrollElement = this.getScrollElement()
|
|
318
|
+
|
|
319
|
+
this.scrollGradientX.initializeScrollGradient(scrollElement)
|
|
320
|
+
}
|
|
321
|
+
|
|
262
322
|
if (!this.useScrollOnGrab) return
|
|
263
323
|
|
|
264
324
|
this.setObserver()
|
|
@@ -266,6 +326,12 @@ export default {
|
|
|
266
326
|
},
|
|
267
327
|
|
|
268
328
|
onUnmounted () {
|
|
329
|
+
if (!this.hasAutoScrollY) {
|
|
330
|
+
const scrollElement = this.getScrollElement()
|
|
331
|
+
|
|
332
|
+
this.scrollGradientX.removeScrollGradient(scrollElement)
|
|
333
|
+
}
|
|
334
|
+
|
|
269
335
|
if (!this.hasScrollOnGrab) return
|
|
270
336
|
|
|
271
337
|
this.destroyObserver()
|
|
@@ -277,7 +343,7 @@ export default {
|
|
|
277
343
|
initializeScrollOnGrab () {
|
|
278
344
|
if (this.hasScrollOnGrab) return
|
|
279
345
|
|
|
280
|
-
const element = this.
|
|
346
|
+
const element = this.getScrollElement()
|
|
281
347
|
|
|
282
348
|
this.scrollOnGrab = setScrollOnGrab(element)
|
|
283
349
|
},
|
|
@@ -286,6 +352,10 @@ export default {
|
|
|
286
352
|
return this.$refs?.table?.$el
|
|
287
353
|
},
|
|
288
354
|
|
|
355
|
+
getScrollElement () {
|
|
356
|
+
return this.getTableElementComponent().querySelector('.q-table__middle.scroll')
|
|
357
|
+
},
|
|
358
|
+
|
|
289
359
|
getTableElement () {
|
|
290
360
|
return this.getTableElementComponent()?.querySelector('table')
|
|
291
361
|
},
|
|
@@ -327,11 +397,29 @@ export default {
|
|
|
327
397
|
this.resizeObserver.unobserve(this.elementToObserve)
|
|
328
398
|
},
|
|
329
399
|
|
|
400
|
+
getTdClasses (row) {
|
|
401
|
+
const routePayload = this.rowRouteFn?.(row)
|
|
402
|
+
const isRoutePayloadObject = typeof routePayload === 'object'
|
|
403
|
+
const hasRoutePayload = isRoutePayloadObject ? !!Object.keys(routePayload).length : !!routePayload
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
'qas-table-generator__td--has-action': this.hasRowClick || hasRoutePayload
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
|
|
330
410
|
getTdChildComponentProps (row) {
|
|
331
411
|
if (!this.rowRouteFn) return
|
|
332
412
|
|
|
333
413
|
return {
|
|
334
|
-
class:
|
|
414
|
+
class: [
|
|
415
|
+
'text-no-decoration',
|
|
416
|
+
'text-grey-8',
|
|
417
|
+
'flex',
|
|
418
|
+
'full-width',
|
|
419
|
+
'items-center',
|
|
420
|
+
'full-height'
|
|
421
|
+
],
|
|
422
|
+
|
|
335
423
|
[this.useExternalLink ? 'href' : 'to']: this.rowRouteFn(row),
|
|
336
424
|
...(this.useExternalLink && { target: '_blank' })
|
|
337
425
|
}
|
|
@@ -339,6 +427,25 @@ export default {
|
|
|
339
427
|
|
|
340
428
|
onRowClick () {
|
|
341
429
|
this.$attrs.onRowClick(...arguments)
|
|
430
|
+
},
|
|
431
|
+
|
|
432
|
+
getFieldsProps (row, index) {
|
|
433
|
+
const isFieldsPropsFunction = typeof this.fieldsProps === 'function'
|
|
434
|
+
|
|
435
|
+
return {
|
|
436
|
+
...(isFieldsPropsFunction ? this.fieldsProps(row, index) : this.fieldsProps),
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* caso tenha a prop "actionsMenuProps" é adicionado automaticamente a prop "actionsMenuProps"
|
|
440
|
+
* dentro de "fieldsProps".
|
|
441
|
+
*/
|
|
442
|
+
...(this.hasActionsMenu && {
|
|
443
|
+
actions: {
|
|
444
|
+
component: 'QasActionsMenu',
|
|
445
|
+
props: this.actionsMenuProps?.(row, index)
|
|
446
|
+
}
|
|
447
|
+
})
|
|
448
|
+
}
|
|
342
449
|
}
|
|
343
450
|
}
|
|
344
451
|
}
|
|
@@ -346,6 +453,8 @@ export default {
|
|
|
346
453
|
|
|
347
454
|
<style lang="scss">
|
|
348
455
|
.qas-table-generator {
|
|
456
|
+
$root: &;
|
|
457
|
+
|
|
349
458
|
.q-table {
|
|
350
459
|
thead tr {
|
|
351
460
|
height: 24px;
|
|
@@ -354,8 +463,29 @@ export default {
|
|
|
354
463
|
th {
|
|
355
464
|
@include set-typography($subtitle1);
|
|
356
465
|
|
|
466
|
+
// altera o tamanho do ícone força o botão não quebrar.
|
|
467
|
+
.qas-btn {
|
|
468
|
+
.q-icon {
|
|
469
|
+
font-size: 18px !important;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.q-btn__content {
|
|
473
|
+
flex-wrap: nowrap;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
357
477
|
border: 0 !important;
|
|
358
|
-
padding: 0
|
|
478
|
+
padding-bottom: 0;
|
|
479
|
+
padding-left: 0;
|
|
480
|
+
padding-top: 0;
|
|
481
|
+
|
|
482
|
+
&:not(:last-child) {
|
|
483
|
+
padding-right: var(--qas-spacing-md);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
&:last-child {
|
|
487
|
+
padding-right: 0;
|
|
488
|
+
}
|
|
359
489
|
}
|
|
360
490
|
|
|
361
491
|
td,
|
|
@@ -369,28 +499,84 @@ export default {
|
|
|
369
499
|
@include set-typography($body1);
|
|
370
500
|
|
|
371
501
|
height: 40px;
|
|
372
|
-
padding-
|
|
373
|
-
padding-
|
|
502
|
+
padding-bottom: var(--qas-spacing-sm);
|
|
503
|
+
padding-left: 0;
|
|
504
|
+
padding-top: var(--qas-spacing-sm);
|
|
374
505
|
|
|
375
|
-
&:
|
|
376
|
-
|
|
506
|
+
&:not(:last-child) {
|
|
507
|
+
padding-right: var(--qas-spacing-md);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
&:last-child {
|
|
511
|
+
padding-right: 0;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
&::before {
|
|
515
|
+
display: none;
|
|
377
516
|
}
|
|
378
517
|
}
|
|
379
518
|
|
|
519
|
+
&__middle {
|
|
520
|
+
padding-left: var(--qas-spacing-md);
|
|
521
|
+
padding-right: var(--qas-spacing-md);
|
|
522
|
+
}
|
|
523
|
+
|
|
380
524
|
tr {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
525
|
+
position: relative;
|
|
526
|
+
|
|
527
|
+
&::before {
|
|
528
|
+
background-color: transparent;
|
|
529
|
+
bottom: 0;
|
|
530
|
+
content: '';
|
|
531
|
+
left: calc(var(--qas-spacing-md) * -1);
|
|
532
|
+
pointer-events: none;
|
|
533
|
+
position: absolute;
|
|
534
|
+
right: calc(var(--qas-spacing-md) * -1);
|
|
535
|
+
top: 0;
|
|
536
|
+
transition: background-color var(--qas-generic-transition);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
tbody tr {
|
|
541
|
+
&::before {
|
|
542
|
+
display: block;
|
|
385
543
|
}
|
|
386
544
|
|
|
387
|
-
&:
|
|
388
|
-
|
|
545
|
+
&:hover::before {
|
|
546
|
+
background-color: var(--qas-background-color);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/*
|
|
550
|
+
A regra só é aplicada se nenhum elemento filho com o atributo "data-table-ignore-tr-hover"
|
|
551
|
+
estiver também em estado de hover, impedindo que estilos conflitantes sejam aplicados.
|
|
552
|
+
Especificamente, dentro da célula:
|
|
553
|
+
- Elementos que não possuem filhos com "data-table-ignore-tr-hover" ou "data-table-ignore-hover"
|
|
554
|
+
receberão a cor definida pela variável CSS "--q-primary-contrast".
|
|
555
|
+
- Elementos dentro de células marcadas como tendo ações ("qas-table-generator__td--has-action")
|
|
556
|
+
e também com o atributo "data-table-hover" serão estilizados da mesma maneira.
|
|
557
|
+
*/
|
|
558
|
+
&:hover:not(:has(td *[data-table-ignore-tr-hover]:hover)) {
|
|
559
|
+
td:not(:has(*[data-table-ignore-tr-hover])):not(:has(*[data-table-ignore-hover])).qas-table-generator__td--has-action *,
|
|
560
|
+
td.qas-table-generator__td--has-action *[data-table-hover] {
|
|
561
|
+
color: var(--q-primary-contrast) !important;
|
|
562
|
+
}
|
|
389
563
|
}
|
|
390
564
|
}
|
|
391
565
|
|
|
392
566
|
thead tr:hover {
|
|
393
|
-
background-color: white;
|
|
567
|
+
background-color: white !important;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.q-table__container {
|
|
572
|
+
margin-left: calc(var(--qas-spacing-md) * -1);
|
|
573
|
+
margin-right: calc(var(--qas-spacing-md) * -1);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
&--has-actions {
|
|
577
|
+
td:last-child #{$root}__td-item {
|
|
578
|
+
display: flex;
|
|
579
|
+
justify-content: flex-end;
|
|
394
580
|
}
|
|
395
581
|
}
|
|
396
582
|
|
|
@@ -4,6 +4,18 @@ meta:
|
|
|
4
4
|
desc: Componente para criação de tabela dinâmica usando o `QTable` do quasar.
|
|
5
5
|
|
|
6
6
|
props:
|
|
7
|
+
actions-menu-props:
|
|
8
|
+
desc: Propriedades repassadas para o "QasActionsMenu" que adiciona uma coluna "actions" de forma automática.
|
|
9
|
+
default: undefined
|
|
10
|
+
type: Function
|
|
11
|
+
params:
|
|
12
|
+
row:
|
|
13
|
+
desc: Payload da linha da tabela.
|
|
14
|
+
type: Object
|
|
15
|
+
index:
|
|
16
|
+
desc: Índice da linha da tabela.
|
|
17
|
+
type: Number
|
|
18
|
+
|
|
7
19
|
columns:
|
|
8
20
|
desc: Colunas que vão ter na tabela.
|
|
9
21
|
default: []
|
|
@@ -20,6 +32,19 @@ props:
|
|
|
20
32
|
type: Object
|
|
21
33
|
examples: ["{ email: { name: 'email', type: 'email', label: 'E-mail' } }"]
|
|
22
34
|
|
|
35
|
+
fields-props:
|
|
36
|
+
desc: Propriedade para controlar o uso de componentes dentro das row sem necessidade de abrir slot.
|
|
37
|
+
default: {}
|
|
38
|
+
type: [Object, Function]
|
|
39
|
+
examples: ["{ email: { component: 'QasCopy' } }"]
|
|
40
|
+
params:
|
|
41
|
+
row:
|
|
42
|
+
desc: Payload da linha da tabela.
|
|
43
|
+
type: Object
|
|
44
|
+
index:
|
|
45
|
+
desc: Índice da linha da tabela.
|
|
46
|
+
type: Number
|
|
47
|
+
|
|
23
48
|
header-props:
|
|
24
49
|
desc: Propriedades repassadas para o componente `QasHeader`.
|
|
25
50
|
default: {}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component :is="component.is" v-bind="component.props" />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup>
|
|
6
|
+
import { computed, defineAsyncComponent } from 'vue'
|
|
7
|
+
|
|
8
|
+
defineOptions({ name: 'PvTableGeneratorProps' })
|
|
9
|
+
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
componentData: {
|
|
12
|
+
type: Object,
|
|
13
|
+
default: () => ({})
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
label: {
|
|
17
|
+
type: String,
|
|
18
|
+
default: ''
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
row: {
|
|
22
|
+
type: Object,
|
|
23
|
+
default: () => ({})
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
name: {
|
|
27
|
+
type: String,
|
|
28
|
+
default: ''
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const component = computed(() => {
|
|
33
|
+
const defaultValue = props.row?.[props.name]
|
|
34
|
+
|
|
35
|
+
const componentPaths = {
|
|
36
|
+
QasActionsMenu: {
|
|
37
|
+
component: () => import('../../actions-menu/QasActionsMenu.vue'),
|
|
38
|
+
props: {}
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
QasBadge: {
|
|
42
|
+
component: () => import('../../badge/QasBadge.vue'),
|
|
43
|
+
props: {
|
|
44
|
+
label: defaultValue
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
QasBtn: {
|
|
49
|
+
component: () => import('../../btn/QasBtn.vue'),
|
|
50
|
+
props: {
|
|
51
|
+
label: defaultValue
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
QasCopy: {
|
|
56
|
+
component: () => import('../../copy/QasCopy.vue'),
|
|
57
|
+
props: {
|
|
58
|
+
text: defaultValue
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
QasStatus: {
|
|
63
|
+
component: () => import('../../status/QasStatus.vue'),
|
|
64
|
+
props: {}
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
QasTextTruncate: {
|
|
68
|
+
component: () => import('../../text-truncate/QasTextTruncate.vue'),
|
|
69
|
+
props: {
|
|
70
|
+
dialogTitle: props.label,
|
|
71
|
+
maxWidth: 260,
|
|
72
|
+
|
|
73
|
+
// caso personalize o componente passando "list", não pode enviar "text" senão vai ter erro de tipo
|
|
74
|
+
text: props.componentData.props?.list?.length ? '' : defaultValue
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
QasToggleVisibility: {
|
|
79
|
+
component: () => import('../../toggle-visibility/QasToggleVisibility.vue'),
|
|
80
|
+
props: {
|
|
81
|
+
text: defaultValue
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
is: defineAsyncComponent(componentPaths[props.componentData.component].component),
|
|
88
|
+
props: {
|
|
89
|
+
...componentPaths[props.componentData.component].props,
|
|
90
|
+
...props.componentData.props
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
</script>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div ref="parent" :class="classes">
|
|
3
3
|
<div class="no-wrap row text-no-wrap">
|
|
4
|
-
|
|
4
|
+
<!-- "data-table-hover" habilita o hover no texto dentro do QasTableGenerator -->
|
|
5
|
+
<div ref="truncate" class="ellipsis" data-table-hover>
|
|
5
6
|
<slot>
|
|
6
7
|
<div v-if="hasBadges" class="items-center q-col-gutter-sm row" :class="badgeParentClasses">
|
|
7
8
|
<div v-for="(item, index) in normalizedBadgesList" :key="index">
|
|
@@ -15,20 +16,22 @@
|
|
|
15
16
|
</slot>
|
|
16
17
|
</div>
|
|
17
18
|
|
|
18
|
-
<qas-btn v-if="hasButton" class="q-ml-
|
|
19
|
+
<qas-btn v-if="hasButton" class="q-ml-xs" :label="buttonLabel" @click.stop.prevent="toggle" />
|
|
19
20
|
</div>
|
|
20
21
|
|
|
21
|
-
<qas-dialog v-model="show" v-bind="defaultProps" aria-label="Diálogo de texto completo" role="dialog">
|
|
22
|
+
<qas-dialog v-model="show" v-bind="defaultProps" aria-label="Diálogo de texto completo" max-width="500px" role="dialog" use-full-max-width>
|
|
22
23
|
<template v-if="isCounterMode" #description>
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
v-for="(item, index) in
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
<component :is="dialogComponent.is" v-bind="dialogComponent.props" v-model:results="searchModel">
|
|
25
|
+
<q-list separator>
|
|
26
|
+
<q-item v-for="(item, index) in dialogComponent.list" :key="index" class="q-px-none">
|
|
27
|
+
<q-item-section>
|
|
28
|
+
<div class="text-body1">
|
|
29
|
+
{{ item }}
|
|
30
|
+
</div>
|
|
31
|
+
</q-item-section>
|
|
32
|
+
</q-item>
|
|
33
|
+
</q-list>
|
|
34
|
+
</component>
|
|
32
35
|
</template>
|
|
33
36
|
</qas-dialog>
|
|
34
37
|
</div>
|
|
@@ -135,7 +138,9 @@ const {
|
|
|
135
138
|
|
|
136
139
|
const {
|
|
137
140
|
defaultProps,
|
|
141
|
+
dialogComponent,
|
|
138
142
|
show,
|
|
143
|
+
searchModel,
|
|
139
144
|
toggle
|
|
140
145
|
} = useDialog({ props, textContent })
|
|
141
146
|
|
|
@@ -158,6 +163,7 @@ const formattedText = computed(() => props.list.length || props.text ? displayTe
|
|
|
158
163
|
function useDialog ({ props, textContent }) {
|
|
159
164
|
// reactive vars
|
|
160
165
|
const show = ref(false)
|
|
166
|
+
const searchModel = ref([])
|
|
161
167
|
|
|
162
168
|
// computed
|
|
163
169
|
const description = computed(() => props.text || textContent.value)
|
|
@@ -176,6 +182,31 @@ function useDialog ({ props, textContent }) {
|
|
|
176
182
|
}
|
|
177
183
|
})
|
|
178
184
|
|
|
185
|
+
const normalizedSearchModel = computed(() => {
|
|
186
|
+
return props.useObjectList ? searchModel.value.map(({ label }) => label) : searchModel.value
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
const dialogComponent = computed(() => {
|
|
190
|
+
const hasSearchBox = normalizedList.value.length > 12
|
|
191
|
+
|
|
192
|
+
if (hasSearchBox) {
|
|
193
|
+
return {
|
|
194
|
+
is: 'qas-search-box',
|
|
195
|
+
list: normalizedSearchModel.value,
|
|
196
|
+
props: {
|
|
197
|
+
height: '510px',
|
|
198
|
+
list: props.list,
|
|
199
|
+
...(props.useObjectList && { fuseOptions: { keys: ['label'] } })
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
is: 'div',
|
|
206
|
+
list: normalizedList.value
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
|
|
179
210
|
// functions
|
|
180
211
|
function toggle () {
|
|
181
212
|
show.value = !show.value
|
|
@@ -183,8 +214,10 @@ function useDialog ({ props, textContent }) {
|
|
|
183
214
|
|
|
184
215
|
return {
|
|
185
216
|
defaultProps,
|
|
217
|
+
dialogComponent,
|
|
186
218
|
|
|
187
219
|
show,
|
|
220
|
+
searchModel,
|
|
188
221
|
|
|
189
222
|
toggle
|
|
190
223
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="qas-toggle-visibility">
|
|
3
|
-
|
|
3
|
+
<!-- "data-table-ignore-tr-hover" é para desabilitar o hover do tr no QasTableGenerator -->
|
|
4
|
+
<div :aria-expanded="isVisible" aria-label="Alternar visibilidade do conteúdo" class="cursor-pointer items-center no-wrap qas-toggle-visibility__container row" data-table-ignore-tr-hover role="button" :style @click.prevent.stop="toggleVisibility">
|
|
4
5
|
<div class="ellipsis qas-toggle-visibility__content">
|
|
5
6
|
<div
|
|
6
7
|
v-if="isVisible"
|