@bildvitta/quasar-ui-asteroid 3.17.0-beta.4 → 3.17.0-beta.6

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.17.0-beta.4",
4
+ "version": "3.17.0-beta.6",
5
5
  "author": "Bild & Vitta <systemteam@bild.com.br>",
6
6
  "license": "MIT",
7
7
  "main": "dist/asteroid.cjs.min.js",
@@ -72,7 +72,7 @@ const classes = computed(() => {
72
72
  const columnClasses = computed(() => {
73
73
  if (props.useEqualWidth) return 'col-12 col-sm-6'
74
74
 
75
- return props.useFullWidth ? 'col-12' : 'col-12 col-sm-auto'
75
+ return props.useFullWidth ? 'full-width' : 'col-12 col-sm-auto'
76
76
  })
77
77
 
78
78
  const hasPrimarySlot = computed(() => !!slots.primary)
@@ -1,23 +1,25 @@
1
1
  <template>
2
- <qas-header v-if="hasHeader" v-bind="headerProps">
3
- <template #right>
4
- <qas-filters v-bind="chartFiltersProps" />
5
- </template>
6
- </qas-header>
7
-
8
- <div v-bind="parentComponentProps">
9
- <component :is="chartComponent.is" v-if="showChart" v-bind="chartComponent.props" />
10
-
11
- <div v-else-if="!isFetching">
12
- <slot name="empty-results">
13
- <qas-empty-result-text />
14
- </slot>
2
+ <component :is="parentComponent.is" v-bind="parentComponent.props">
3
+ <qas-header v-if="hasHeader" v-bind="headerProps">
4
+ <template #right>
5
+ <qas-filters v-bind="chartFiltersProps" />
6
+ </template>
7
+ </qas-header>
8
+
9
+ <div v-bind="parentComponentProps">
10
+ <component :is="chartComponent.is" v-if="showChart" v-bind="chartComponent.props" />
11
+
12
+ <div v-else-if="!isFetching">
13
+ <slot name="empty-results">
14
+ <qas-empty-result-text />
15
+ </slot>
16
+ </div>
17
+
18
+ <q-inner-loading :showing="isFetching">
19
+ <q-spinner color="grey" size="3em" />
20
+ </q-inner-loading>
15
21
  </div>
16
-
17
- <q-inner-loading :showing="isFetching">
18
- <q-spinner color="grey" size="3em" />
19
- </q-inner-loading>
20
- </div>
22
+ </component>
21
23
  </template>
22
24
 
23
25
  <script>
@@ -69,6 +71,11 @@ export default {
69
71
  type: Function
70
72
  },
71
73
 
74
+ boxProps: {
75
+ default: () => ({}),
76
+ type: Object
77
+ },
78
+
72
79
  colorsList: {
73
80
  type: Array,
74
81
  default: () => []
@@ -124,6 +131,11 @@ export default {
124
131
  type: String
125
132
  },
126
133
 
134
+ useBox: {
135
+ type: Boolean,
136
+ default: true
137
+ },
138
+
127
139
  useFilterButton: {
128
140
  type: Boolean
129
141
  }
@@ -308,6 +320,16 @@ export default {
308
320
  label: this.title
309
321
  }
310
322
  }
323
+ },
324
+
325
+ parentComponent () {
326
+ return {
327
+ is: this.useBox ? 'qas-box' : 'div',
328
+
329
+ props: {
330
+ ...(this.useBox && { ...this.boxProps })
331
+ }
332
+ }
311
333
  }
312
334
  },
313
335
 
@@ -10,6 +10,11 @@ props:
10
10
  type: Function
11
11
  examples: ['beforeFetch({ payload, resolve, done })']
12
12
 
13
+ box-props:
14
+ desc: Propriedades do "QasBox" que envolve o conteúdo.
15
+ default: {}
16
+ type: Object
17
+
13
18
  colors-list:
14
19
  desc: Lista de cores personalizadas para utilizar nos gráficos
15
20
  default: []
@@ -65,6 +70,11 @@ props:
65
70
  desc: Envia como parâmetro para a action "fetchList" do modulo correspondente a "entity".
66
71
  type: String
67
72
 
73
+ use-box:
74
+ desc: Controla se o componente vai ter o QasBox englobando ou não.
75
+ default: true
76
+ type: Boolean
77
+
68
78
  use-filter-button:
69
79
  desc: Controla se o componente vai usar ou não o componente "QasFilters".
70
80
  type: Boolean
@@ -1,10 +1,10 @@
1
1
  <template>
2
2
  <q-dialog ref="dialogRef" class="qas-dialog" :class="classes" data-cy="dialog" v-bind="dialogProps" :persistent="props.persistent" @update:model-value="updateModelValue">
3
- <div class="bg-white q-pa-lg" :style="style">
4
- <header v-if="hasHeader" class="q-mb-lg">
3
+ <div class="bg-white q-pa-md" :style="style">
4
+ <header v-if="hasHeader" class="q-mb-md">
5
5
  <slot name="header">
6
6
  <div class="items-center justify-between row">
7
- <h5 class="text-h5" data-cy="dialog-title">{{ props.card.title }}</h5>
7
+ <qas-label data-cy="dialog-title" :label="props.card.title" margin="none" />
8
8
 
9
9
  <qas-btn v-if="isInfoDialog" v-close-popup color="grey-10" data-cy="dialog-close-btn" icon="sym_r_close" variant="tertiary" />
10
10
  </div>
@@ -160,7 +160,7 @@ export default {
160
160
  const field = { ...this.fields[key], ...this.formattedFieldsProps?.[decamelize(key)] }
161
161
  const value = humanize(field, this.normalizeValues(filters[key], field?.multiple))
162
162
 
163
- if (!value) continue
163
+ if (!value || (Array.isArray(value) && !value.length)) continue
164
164
 
165
165
  const { label, name } = field
166
166
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
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" self="top right" v-bind="menuProps">
3
+ <q-menu ref="menu" anchor="center right" class="full-width" max-width="270px" v-bind="menuProps" no-refocus self="top right">
4
4
  <div v-if="loading" class="q-pa-xl text-center">
5
5
  <q-spinner color="grey" size="2em" />
6
6
  </div>
@@ -2,7 +2,7 @@
2
2
  <div :class="fieldsetClasses">
3
3
  <div v-for="(fieldsetItem, fieldsetItemKey) in normalizedFields" :key="fieldsetItemKey" :class="getFieldSetColumnClass(fieldsetItem.column)">
4
4
  <component :is="containerComponent.is" v-bind="containerComponent.props">
5
- <slot v-if="hasFieldsetItem(fieldsetItem)" :name="`legend-${fieldsetItemKey}`">
5
+ <slot v-if="fieldsetItem.__isFieldset" :name="`legend-${fieldsetItemKey}`">
6
6
  <qas-header v-bind="getHeaderProps(fieldsetItem)" />
7
7
  </slot>
8
8
 
@@ -97,7 +97,7 @@ provide('isFormGenerator', true)
97
97
  // composables
98
98
  const { classes, getFieldClass, getFieldSetColumnClass } = useGenerator({ props })
99
99
 
100
- const { fieldsetClasses, hasFieldset, hasFieldsetItem } = useFieldset({ props })
100
+ const { fieldsetClasses, hasFieldset } = useFieldset({ props })
101
101
 
102
102
  const screen = useScreen()
103
103
 
@@ -169,7 +169,10 @@ const normalizedFields = computed(() => {
169
169
  column: fieldsetItem.column,
170
170
  buttonProps: fieldsetItem.buttonProps,
171
171
  fields: { hidden: {}, visible: {} },
172
- headerProps: fieldsetItem.headerProps
172
+ headerProps: fieldsetItem.headerProps,
173
+
174
+ // Indica que existe um fieldset para que o QasHeader possa ser renderizado
175
+ __isFieldset: true
173
176
  }
174
177
 
175
178
  fieldsetItem.fields.forEach(fieldName => {
@@ -248,15 +251,9 @@ function useFieldset ({ props }) {
248
251
 
249
252
  const hasFieldset = computed(() => !!Object.keys(props.fieldset).length)
250
253
 
251
- function hasFieldsetItem (fieldset = {}) {
252
- return !!Object.keys(fieldset).length
253
- }
254
-
255
254
  return {
256
255
  fieldsetClasses,
257
- hasFieldset,
258
-
259
- hasFieldsetItem
256
+ hasFieldset
260
257
  }
261
258
  }
262
259
  </script>
@@ -3,9 +3,9 @@
3
3
  <qas-header v-if="hasHeader" v-bind="props.headerProps" />
4
4
 
5
5
  <div :class="classes">
6
- <div v-for="(field, key) in fieldsByResult" :key="key" :class="getContainerClass({ key })">
6
+ <div v-for="(field, key) in fieldsByResult" :key="key" :class="getContainerClassses({ key })">
7
7
  <slot :field="field" :name="`field-${field.name}`">
8
- <qas-grid-item :use-ellipsis="props.useEllipsis" :use-inline="props.useInline">
8
+ <qas-grid-item :use-ellipsis="hasEllipsis(field)" :use-inline="props.useInline">
9
9
  <template #header>
10
10
  <slot :field="field" :name="`header-field-${field.name}`">
11
11
  <slot :field="field" name="header">
@@ -19,7 +19,7 @@
19
19
  <template #content>
20
20
  <slot :field="field" :name="`content-field-${field.name}`">
21
21
  <slot :field="field" name="content">
22
- <div :class="contentClass" :data-cy="`grid-generator-${field.name}-result`" :title="getTitle(field, 'formattedResult')">
22
+ <div :class="getContentClasses(field)" :data-cy="`grid-generator-${field.name}-result`" :title="getTitle(field, 'formattedResult')">
23
23
  {{ field.formattedResult }}
24
24
  </div>
25
25
  </slot>
@@ -105,16 +105,6 @@ const hasResult = computed(() => Object.keys(props.result).length)
105
105
  const hasFields = computed(() => Object.keys(props.fields).length)
106
106
  const hasHeader = computed(() => Object.keys(props.headerProps).length)
107
107
 
108
- const contentClass = computed(() => {
109
- return [
110
- props.contentClass,
111
-
112
- {
113
- ellipsis: !screen.isSmall && props.useEllipsis
114
- }
115
- ]
116
- })
117
-
118
108
  const component = computed(() => {
119
109
  return {
120
110
  is: props.useBox ? 'qas-box' : 'div',
@@ -191,7 +181,7 @@ function setFieldsByResult () {
191
181
  fieldsByResult.value = getFieldsByResult()
192
182
  }
193
183
 
194
- function getContainerClass ({ key }) {
184
+ function getContainerClassses ({ key }) {
195
185
  if (props.useInline) return 'row justify-between col-12'
196
186
 
197
187
  return getFieldClass({ index: key, isGridGenerator: true })
@@ -200,4 +190,21 @@ function getContainerClass ({ key }) {
200
190
  function getTitle (field, key) {
201
191
  return props.useEllipsis ? field[key] : ''
202
192
  }
193
+
194
+ function hasEllipsis (field) {
195
+ /**
196
+ * Para campos do tipo "textarea" vamos sempre exibir o conteúdo por completo.
197
+ */
198
+ return (field.type === 'textarea') && !props.useInline ? false : props.useEllipsis
199
+ }
200
+
201
+ function getContentClasses (field) {
202
+ return [
203
+ props.contentClass,
204
+
205
+ {
206
+ ellipsis: !screen.isSmall && this.hasEllipsis(field)
207
+ }
208
+ ]
209
+ }
203
210
  </script>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :class="containerClasses">
3
- <div v-if="hasLabelSection" class="items-center justify-between no-wrap row" :class="labelSectionClasses">
3
+ <div v-if="hasLabelSection" class="full-width items-center justify-between no-wrap row" :class="labelSectionClasses">
4
4
  <div class="items-center q-col-gutter-sm row">
5
5
  <slot name="label">
6
6
  <qas-label v-if="hasLabel" v-bind="defaultLabelProps" />
@@ -14,13 +14,15 @@
14
14
  </div>
15
15
 
16
16
  <slot name="actions">
17
- <qas-actions-menu v-if="hasDefaultActionsMenu" v-bind="props.actionsMenuProps" />
17
+ <div class="q-mt-xs text-right">
18
+ <qas-actions-menu v-if="hasDefaultActionsMenu" v-bind="props.actionsMenuProps" />
18
19
 
19
- <qas-btn v-if="hasDefaultButton" :use-label-on-small-screen="false" v-bind="props.buttonProps" />
20
+ <qas-btn v-if="hasDefaultButton" :use-label-on-small-screen="false" v-bind="props.buttonProps" />
21
+ </div>
20
22
  </slot>
21
23
  </div>
22
24
 
23
- <div class="items-start justify-between no-wrap q-col-gutter-sm row">
25
+ <div class="items-start no-wrap q-col-gutter-sm row" :class="descriptionSectionClasses">
24
26
  <div v-if="hasDescriptionSection" class="text-body1 text-grey-8">
25
27
  <slot name="description">
26
28
  {{ props.description }}
@@ -90,13 +92,21 @@ const labelSectionClasses = computed(() => {
90
92
  }
91
93
  })
92
94
 
95
+ const descriptionSectionClasses = computed(() => {
96
+ return {
97
+ 'justify-between': hasDescriptionSection.value,
98
+ 'justify-end': hasActionsSection.value && !hasDescriptionSection.value
99
+ }
100
+ })
101
+
93
102
  const defaultLabelProps = computed(() => {
94
103
  return {
95
- margin: hasBadges.value ? 'none' : 'xs',
104
+ margin: 'none',
96
105
  ...props.labelProps
97
106
  }
98
107
  })
99
108
 
109
+ const hasActionsSection = computed(() => !!slots.actions || hasDefaultButton.value || hasDefaultActionsMenu.value)
100
110
  const hasBadges = computed(() => !!props.badges.length)
101
111
  const hasLabel = computed(() => !!Object.keys(props.labelProps).length)
102
112
  const hasDefaultButton = computed(() => !!Object.keys(props.buttonProps).length)
@@ -2,24 +2,20 @@
2
2
  <div :id="fieldName" class="qas-nested-fields" :data-cy="`nested-fields-${fieldName}`">
3
3
  <component :is="containerComponent">
4
4
  <div v-if="useSingleLabel" class="text-left">
5
- <qas-label :label="fieldLabel" typography="h5" />
5
+ <qas-label :label="fieldLabel" />
6
6
  </div>
7
7
 
8
8
  <div ref="inputContent">
9
9
  <component :is="componentTag" v-bind="componentProps">
10
10
  <template v-for="(row, index) in nested" :key="`row-${index}`">
11
11
  <div v-if="!row[destroyKey]" :id="`row-${index}`" class="full-width qas-nested-fields__field-item" data-cy="nested-fields-item">
12
- <header v-if="hasHeader" class="flex items-center q-pb-md" :class="headerClasses">
13
- <qas-label v-if="!useSingleLabel" :label="getRowLabel(index)" margin="none" typography="h5" />
14
-
15
- <qas-actions-menu v-if="hasBlockActions(row)" v-bind="getActionsMenuProps(index, row)" :use-label="false" />
16
- </header>
12
+ <qas-header v-if="hasHeader({ row })" class="flex" v-bind="getHeaderProps({ index, row })" />
17
13
 
18
14
  <slot :errors="transformedErrors" :fields="getFields(index, row)" :index="index" :model="nested[index]" name="before-fields" :update-value="updateValuesFromInput" />
19
15
 
20
- <div ref="formGenerator" class="col-12 justify-between q-col-gutter-x-md row">
16
+ <div ref="formGenerator" :class="formGeneratorParentClasses">
21
17
  <slot :errors="transformedErrors" :fields="getFields(index, row)" :index="index" name="fields" :update-value="updateValuesFromInput">
22
- <qas-form-generator v-model="nested[index]" class="col" :columns="formColumns" :disable="isDisabledRow(row)" :errors="transformedErrors[index]" :fields="getFields(index, row)" :fields-props="getFieldsProps(index, row)" :gutter="formGutter" @update:model-value="updateValuesFromInput($event, index)">
18
+ <qas-form-generator v-model="nested[index]" class="col" :columns="formColumns" :common-columns="formCommonColumns" :disable="isDisabledRow(row)" :errors="transformedErrors[index]" :fields="getFields(index, row)" :fields-props="getFieldsProps(index, row)" :gutter="formGutter" @update:model-value="updateValuesFromInput($event, index)">
23
19
  <template v-for="(slot, key) in $slots" #[key]="scope">
24
20
  <slot v-bind="scope" :disabled="isDisabledRow(row)" :errors="transformedErrors" :index="index" :name="key" />
25
21
  </template>
@@ -27,7 +23,7 @@
27
23
  </slot>
28
24
 
29
25
  <div v-if="hasInlineActions(row)" class="flex items-center qas-nested-fields__actions">
30
- <qas-actions-menu v-bind="getActionsMenuProps(index, row)" :use-label="false" />
26
+ <qas-actions-menu v-bind="getInlineActionsMenuProps(index, row)" :use-label="false" />
31
27
  </div>
32
28
  </div>
33
29
 
@@ -36,7 +32,7 @@
36
32
  </template>
37
33
  </component>
38
34
 
39
- <div v-if="useAdd">
35
+ <div v-if="useAdd" :class="addButtonClass">
40
36
  <slot :add="add" name="add-input">
41
37
  <div v-if="showAddFirstInputButton" class="text-left">
42
38
  <qas-btn class="q-px-sm" color="primary" data-cy="nested-fields-add-btn" :label="addFirstInputLabel" variant="tertiary" @click="add()" />
@@ -70,7 +66,7 @@ import QasInput from '../input/QasInput.vue'
70
66
  import QasLabel from '../label/QasLabel.vue'
71
67
 
72
68
  import { constructObject } from '../../helpers'
73
- import { Spacing } from '../../enums/Spacing'
69
+ import { Spacing, SpacingWithNumber } from '../../enums/Spacing'
74
70
 
75
71
  import { TransitionGroup } from 'vue'
76
72
  import debug from 'debug'
@@ -167,12 +163,22 @@ export default {
167
163
  default: () => []
168
164
  },
169
165
 
166
+ formCommonColumns: {
167
+ type: [Object, String],
168
+ default: () => ({})
169
+ },
170
+
170
171
  formGutter: {
171
- default: Spacing.Lg,
172
+ default: Spacing.Md,
172
173
  type: [String, Boolean],
173
174
  validator: value => typeof value === 'boolean' || Object.values(Spacing).includes(value)
174
175
  },
175
176
 
177
+ headerProps: {
178
+ type: Function,
179
+ default: () => {}
180
+ },
181
+
176
182
  identifierItemKey: {
177
183
  type: String,
178
184
  default: 'uuid'
@@ -296,15 +302,14 @@ export default {
296
302
  return this.useFirstInputButton && !this.nested.length
297
303
  },
298
304
 
299
- hasHeader () {
300
- return (this.useSingleLabel && !this.useInlineActions) || !this.useSingleLabel
301
- },
302
-
303
- headerClasses () {
305
+ addButtonClass () {
304
306
  return {
305
- 'justify-end': this.useSingleLabel,
306
- 'justify-between': !this.useSingleLabel
307
+ 'q-mt-md': !!this.nested.length
307
308
  }
309
+ },
310
+
311
+ formGeneratorParentClasses () {
312
+ return this.useInlineActions ? 'col-12 justify-between q-col-gutter-x-md row' : 'full-width'
308
313
  }
309
314
  },
310
315
 
@@ -333,8 +338,8 @@ export default {
333
338
  },
334
339
 
335
340
  methods: {
336
- getActionsMenuProps (index, row) {
337
- if (typeof this.actionsMenuProps === 'function') {
341
+ getInlineActionsMenuProps (index, row) {
342
+ if (typeof this.actionsMenuProps === 'function' && this.useInlineActions) {
338
343
  return this.actionsMenuProps({
339
344
  index,
340
345
  row,
@@ -344,7 +349,7 @@ export default {
344
349
 
345
350
  return {
346
351
  ...this.actionsMenuProps,
347
- list: this.getActionsMenuList(index, row)
352
+ list: this.getActionsMenuList(index, row, this.actionsMenuProps?.list)
348
353
  }
349
354
  },
350
355
 
@@ -368,11 +373,11 @@ export default {
368
373
  return list
369
374
  },
370
375
 
371
- getActionsMenuList (index, row) {
376
+ getActionsMenuList (index, row, defaultList = {}) {
372
377
  const list = this.getDefaultActionsMenuList(index, row)
373
378
 
374
- for (const key in this.actionsMenuProps.list) {
375
- const { handler, ...content } = this.actionsMenuProps.list[key] || {}
379
+ for (const key in defaultList) {
380
+ const { handler, ...content } = defaultList[key] || {}
376
381
 
377
382
  list[key] = {
378
383
  handler: payload => handler?.({ payload, row, index }),
@@ -456,14 +461,32 @@ export default {
456
461
 
457
462
  setScroll () {
458
463
  const elements = this.$refs.inputContent.children
464
+
465
+ // elemento de ação, e não das linhas (rows) de inputs
459
466
  const element = elements[elements.length - 1]
467
+
468
+ // ultima linha (rows) de inputs
469
+ const rowsElement = elements[0]?.children
470
+
471
+ // pegamos a posição do elemento de ação
460
472
  const { top } = element.getBoundingClientRect()
461
- const pageOffset = window.pageYOffset
462
473
 
463
- window.scrollTo({
464
- behavior: 'smooth',
465
- top: pageOffset + top
466
- })
474
+ // pegamos a altura da ultima linha (rows) de inputs
475
+ const lastRowHeight = rowsElement?.[rowsElement.length - 1]?.clientHeight
476
+
477
+ // pegamos a posição da página
478
+ const pageOffset = window.scrollY
479
+
480
+ // 56 é a altura do header no mobile
481
+ const safeScrollSize = this.$qas.screen.isSmall ? 56 + SpacingWithNumber.Lg : SpacingWithNumber.Lg
482
+
483
+ /**
484
+ * É necessário descontar a altura da última linha (rows) de inputs para que o scroll
485
+ * fique no final da última linha (rows) de inputs.
486
+ */
487
+ const scrollTop = pageOffset + top - (lastRowHeight + safeScrollSize)
488
+
489
+ window.scrollTo({ behavior: 'smooth', top: scrollTop })
467
490
  },
468
491
 
469
492
  async setFocus () {
@@ -507,6 +530,41 @@ export default {
507
530
 
508
531
  hasInlineActions (row) {
509
532
  return this.useInlineActions && !this.isDisabledRow(row)
533
+ },
534
+
535
+ hasHeader ({ row }) {
536
+ return this.hasBlockActions(row) || !this.useSingleLabel
537
+ },
538
+
539
+ getHeaderProps ({ index, row }) {
540
+ const hasLabel = !this.useSingleLabel
541
+ const hasActions = this.hasBlockActions(row)
542
+
543
+ const { labelProps, actionsMenuProps, ...payload } = this.headerProps?.({ index, row }) || {}
544
+
545
+ return {
546
+ ...payload,
547
+
548
+ spacing: 'sm',
549
+
550
+ ...(hasActions && {
551
+ actionsMenuProps: {
552
+ useLabel: false,
553
+
554
+ ...actionsMenuProps,
555
+
556
+ list: this.getActionsMenuList(index, row, actionsMenuProps?.list)
557
+ }
558
+ }),
559
+
560
+ ...(hasLabel && {
561
+ labelProps: {
562
+ typography: 'h5',
563
+ label: this.getRowLabel(index),
564
+ ...labelProps
565
+ }
566
+ })
567
+ }
510
568
  }
511
569
  }
512
570
  }
@@ -514,16 +572,13 @@ export default {
514
572
 
515
573
  <style lang="scss">
516
574
  .qas-nested-fields {
575
+ // mesmo tamanho do input
517
576
  &__actions {
518
- height: 56px;
519
- }
520
-
521
- &__field-item {
522
- margin-bottom: var(--qas-spacing-md);
577
+ height: 40px;
523
578
  }
524
579
 
525
580
  &__field-item + &__field-item {
526
- margin-top: var(--qas-spacing-xl);
581
+ margin-top: var(--qas-spacing-lg);
527
582
  }
528
583
  }
529
584
  </style>
@@ -74,12 +74,34 @@ props:
74
74
  type: [Array, String, Object]
75
75
  examples: ["[{ sm: 6, md: 12 }]", "{ name: { sm: 6, md: 12 } }", "12"]
76
76
 
77
+ form-common-columns:
78
+ desc: Colunas do grid comuns.
79
+ default: {}
80
+ type: [String, Object]
81
+ examples: ["{ col: 12, sm: 6}" , "12"]
82
+
77
83
  form-gutter:
78
84
  desc: Espaçamento entre colunas do formulário.
79
85
  default: lg
80
86
  type: [String, Boolean]
81
87
  examples: [xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, false]
82
88
 
89
+ header-props:
90
+ desc: Propriedades do header do nested por linha por callback.
91
+ default: () => {}
92
+ type: Function
93
+ params:
94
+ context:
95
+ desc: Payload da linha (row) -> index/row.
96
+ type: Object
97
+ params:
98
+ index:
99
+ desc: Índice da linha.
100
+ type: Number
101
+ row:
102
+ desc: Valores contendo na linha atual.
103
+ type: Object
104
+
83
105
  identifier-item-key:
84
106
  desc: Define um identificador para o item. O identificador será utilizado para validar exclusão do item, por exemplo.
85
107
  default: uuid
@@ -251,6 +273,7 @@ slots:
251
273
  type: Function
252
274
  examples: ["updateValue({ name: 'novo valor' }, 2)"]
253
275
 
276
+
254
277
  events:
255
278
  '@update:model-value -> function (value)':
256
279
  desc: Dispara toda vez que o model é atualizado, também utilizado para v-model.
@@ -2,7 +2,7 @@
2
2
  <div ref="parent" :class="classes">
3
3
  <div class="no-wrap row text-no-wrap">
4
4
  <div ref="truncate" class="ellipsis">
5
- <slot>{{ displayText }}</slot>
5
+ <slot>{{ formattedText }}</slot>
6
6
  </div>
7
7
 
8
8
  <qas-btn v-if="hasButton" class="q-ml-sm" :label="buttonLabel" @click.stop.prevent="toggle" />
@@ -87,6 +87,11 @@ const props = defineProps({
87
87
 
88
88
  useObjectList: {
89
89
  type: Boolean
90
+ },
91
+
92
+ emptyText: {
93
+ type: String,
94
+ default: '-'
90
95
  }
91
96
  })
92
97
 
@@ -119,6 +124,8 @@ useMutationObserver({ truncate, callbackFn: truncateText })
119
124
 
120
125
  const classes = computed(() => [`text-${props.color}`, `text-${props.typography}`])
121
126
 
127
+ const formattedText = computed(() => props.list.length || props.text ? displayText.value : props.emptyText)
128
+
122
129
  // composable functions
123
130
  function useDialog ({ props, textContent }) {
124
131
  // reactive vars
@@ -51,6 +51,10 @@ props:
51
51
  desc: Utiliza a propriedade "list" como array de objeto contendo label (uso junto a prop list).
52
52
  type: Boolean
53
53
 
54
+ empty-text:
55
+ desc: Texto a ser exibido no caso de não houver itens no "list" ou o "text" for vazio.
56
+ type: String
57
+
54
58
  slots:
55
59
  default:
56
60
  desc: slot padrão que é utilizado para acessar o texto original (tanto o que é truncado quando o de dentro do dialog)
@@ -21,7 +21,7 @@ export const baseProps = {
21
21
  },
22
22
 
23
23
  gutter: {
24
- default: undefined,
24
+ default: Spacing.Md,
25
25
  type: [String, Boolean],
26
26
  validator: gutterValidator
27
27
  }
@@ -46,19 +46,13 @@ export default function ({ props = {} }) {
46
46
  const classes = computed(() => {
47
47
  const classesList = ['row']
48
48
 
49
- if (defaultGutter.value) {
50
- classesList.push(`q-col-gutter-${defaultGutter.value}`)
49
+ if (props.gutter) {
50
+ classesList.push(`q-col-gutter-${props.gutter}`)
51
51
  }
52
52
 
53
53
  return classesList
54
54
  })
55
55
 
56
- const defaultGutter = computed(() => {
57
- if (props.gutter) return props.gutter
58
-
59
- return props.useInline ? Spacing.Md : Spacing.Lg
60
- })
61
-
62
56
  /**
63
57
  * @function
64
58
  * @param {Object} options
@@ -63,3 +63,36 @@ export const SpacingWithUnit = {
63
63
  '4xl': '56px',
64
64
  '5xl': '64px'
65
65
  }
66
+
67
+ /**
68
+ * Todas variáveis utilizadas para espaçamentos, com unidade de medida.
69
+ *
70
+ * @property
71
+ * @name SpacingWithUnit
72
+ * @readonly
73
+ * @enum
74
+ * @type {{
75
+ * None: 0,
76
+ * Xs: 4,
77
+ * Sm: 8,
78
+ * Md: 16,
79
+ * Lg: 24,
80
+ * Xl: 32,
81
+ * '2xl': 40,
82
+ * '3xl': 48,
83
+ * '4xl': 56,
84
+ * '5xl': 64
85
+ * }}
86
+ */
87
+ export const SpacingWithNumber = {
88
+ None: 0,
89
+ Xs: 4,
90
+ Sm: 8,
91
+ Md: 16,
92
+ Lg: 24,
93
+ Xl: 32,
94
+ '2xl': 40,
95
+ '3xl': 48,
96
+ '4xl': 56,
97
+ '5xl': 64
98
+ }