@bildvitta/quasar-ui-asteroid 3.17.0-beta.0 → 3.17.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.17.0-beta.0",
4
+ "version": "3.17.0-beta.2",
5
5
  "author": "Bild & Vitta <systemteam@bild.com.br>",
6
6
  "license": "MIT",
7
7
  "main": "dist/asteroid.cjs.min.js",
@@ -45,7 +45,7 @@ import useDynamicComponents from './composables/use-dynamic-components'
45
45
  import useOk from './composables/use-ok'
46
46
  import { useScreen } from '../../composables'
47
47
 
48
- import { computed, ref, useAttrs, useSlots } from 'vue'
48
+ import { computed, ref, useAttrs, useSlots, provide } from 'vue'
49
49
  import { useDialogPluginComponent } from 'quasar'
50
50
 
51
51
  defineOptions({ name: 'QasDialog' })
@@ -120,6 +120,8 @@ const emit = defineEmits([
120
120
  ...useDialogPluginComponent.emits
121
121
  ])
122
122
 
123
+ provide('isDialog', true)
124
+
123
125
  const attrs = useAttrs()
124
126
  const screen = useScreen()
125
127
  const slots = useSlots()
@@ -2,20 +2,22 @@
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="fieldsetItem.label" :name="`legend-${fieldsetItemKey}`">
6
- <qas-label :label="fieldsetItem.label" :margin="getLabelMargin(fieldsetItem)" />
7
-
8
- <div v-if="fieldsetItem.description" class="q-mb-md text-body1 text-grey-8">{{ fieldsetItem.description }}</div>
5
+ <slot v-if="hasFieldsetItem(fieldsetItem)" :name="`legend-${fieldsetItemKey}`">
6
+ <qas-header v-bind="getHeaderProps(fieldsetItem)" />
9
7
  </slot>
10
8
 
11
9
  <div>
12
10
  <slot :fields="fieldsetItem.fields?.visible" :name="`legend-section-${fieldsetItemKey}`">
13
- <div :class="classes">
14
- <div v-for="(field, key) in fieldsetItem.fields.visible" :key="key" :class="getFieldClass({ index: key, fields: normalizedFields })">
15
- <slot :field="field" :name="`field-${field.name}`">
16
- <qas-field :disable="isFieldDisabled(field)" v-bind="props.fieldsProps[field.name]" :error="props.errors[key]" :field="field" :model-value="props.modelValue[field.name]" @update:model-value="updateModelValue({ key: field.name, value: $event })" />
17
- </slot>
11
+ <div class="items-end justify-end" :class="getRowContainerClasses(fieldsetItem)">
12
+ <div :class="fieldContainerClasses">
13
+ <div v-for="(field, key) in fieldsetItem.fields.visible" :key="key" :class="getFieldClass({ index: key, fields: normalizedFields })">
14
+ <slot :field="field" :name="`field-${field.name}`">
15
+ <qas-field :disable="isFieldDisabled(field)" v-bind="props.fieldsProps[field.name]" :error="props.errors[key]" :field="field" :model-value="props.modelValue[field.name]" @update:model-value="updateModelValue({ key: field.name, value: $event })" />
16
+ </slot>
17
+ </div>
18
18
  </div>
19
+
20
+ <qas-btn v-if="hasButtonProps(fieldsetItem)" class="md:q-mt-none q-ml-md q-mt-md" v-bind="fieldsetItem.buttonProps" />
19
21
  </div>
20
22
 
21
23
  <div v-for="(field, key) in fieldsetItem.fields.hidden" :key="key">
@@ -34,6 +36,7 @@
34
36
  import { gutterValidator } from '../../helpers/private/gutter-validator'
35
37
  import useGenerator, { baseProps } from '../../composables/private/use-generator'
36
38
  import { Spacing } from '../../enums/Spacing'
39
+ import { useScreen } from '../../composables'
37
40
  import { computed, provide, inject } from 'vue'
38
41
 
39
42
  defineOptions({ name: 'QasFormGenerator' })
@@ -94,7 +97,9 @@ provide('isFormGenerator', true)
94
97
  // composables
95
98
  const { classes, getFieldClass, getFieldSetColumnClass } = useGenerator({ props })
96
99
 
97
- const { fieldsetClasses, hasFieldset } = useFieldset({ props })
100
+ const { fieldsetClasses, hasFieldset, hasFieldsetItem } = useFieldset({ props })
101
+
102
+ const screen = useScreen()
98
103
 
99
104
  // constants
100
105
  const hasNestedFormGenerator = inject('isFormGenerator', false)
@@ -162,7 +167,9 @@ const normalizedFields = computed(() => {
162
167
  label: fieldsetItem.label,
163
168
  description: fieldsetItem.description,
164
169
  column: fieldsetItem.column,
165
- fields: { hidden: {}, visible: {} }
170
+ buttonProps: fieldsetItem.buttonProps,
171
+ fields: { hidden: {}, visible: {} },
172
+ headerProps: fieldsetItem.headerProps
166
173
  }
167
174
 
168
175
  fieldsetItem.fields.forEach(fieldName => {
@@ -181,13 +188,31 @@ const normalizedFields = computed(() => {
181
188
  return fields
182
189
  })
183
190
 
191
+ const fieldContainerClasses = computed(() => {
192
+ return [
193
+ ...classes.value,
194
+ {
195
+ col: !screen.isSmall
196
+ }
197
+ ]
198
+ })
199
+
184
200
  // methods
185
201
  function getFieldType ({ type }) {
186
202
  return type === 'hidden' ? 'hidden' : 'visible'
187
203
  }
188
204
 
189
- function getLabelMargin (fieldsetItem) {
190
- return fieldsetItem.description ? 'sm' : 'md'
205
+ function getHeaderProps (fieldsetItem) {
206
+ return {
207
+ description: fieldsetItem.description,
208
+
209
+ labelProps: {
210
+ ...fieldsetItem.headerProps?.labelProps,
211
+ ...(fieldsetItem.label && { label: fieldsetItem.label })
212
+ },
213
+
214
+ ...fieldsetItem.headerProps
215
+ }
191
216
  }
192
217
 
193
218
  function isFieldDisabled ({ disable }) {
@@ -201,6 +226,14 @@ function updateModelValue ({ key, value }) {
201
226
  emit('update:modelValue', models)
202
227
  }
203
228
 
229
+ function hasButtonProps ({ buttonProps = {} }) {
230
+ return !!Object.keys(buttonProps).length
231
+ }
232
+
233
+ function getRowContainerClasses (item) {
234
+ return { row: hasButtonProps(item) }
235
+ }
236
+
204
237
  // composables
205
238
  function useFieldset ({ props }) {
206
239
  const fieldsetClasses = computed(() => {
@@ -215,9 +248,15 @@ function useFieldset ({ props }) {
215
248
 
216
249
  const hasFieldset = computed(() => !!Object.keys(props.fieldset).length)
217
250
 
251
+ function hasFieldsetItem (fieldset = {}) {
252
+ return !!Object.keys(fieldset).length
253
+ }
254
+
218
255
  return {
219
256
  fieldsetClasses,
220
- hasFieldset
257
+ hasFieldset,
258
+
259
+ hasFieldsetItem
221
260
  }
222
261
  }
223
262
  </script>
@@ -3,7 +3,7 @@
3
3
  <div v-if="hasLabelSection" class="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
- <qas-label v-bind="defaultLabelProps" />
6
+ <qas-label v-if="hasLabel" v-bind="defaultLabelProps" />
7
7
  </slot>
8
8
 
9
9
  <div v-if="hasBadges" class="col-auto items-center q-col-gutter-sm row">
@@ -73,7 +73,7 @@ const props = defineProps({
73
73
  },
74
74
 
75
75
  spacing: {
76
- default: Spacing.Xl,
76
+ default: Spacing.Md,
77
77
  type: String,
78
78
  validator: gutterValidator
79
79
  }
@@ -102,5 +102,5 @@ const hasLabel = computed(() => !!Object.keys(props.labelProps).length)
102
102
  const hasDefaultButton = computed(() => !!Object.keys(props.buttonProps).length)
103
103
  const hasDefaultActionsMenu = computed(() => !!Object.keys(props.actionsMenuProps).length)
104
104
  const hasDescriptionSection = computed(() => props.description || slots.description)
105
- const hasLabelSection = computed(() => hasLabel.value || slots.label)
105
+ const hasLabelSection = computed(() => hasLabel.value || slots.label || hasBadges.value)
106
106
  </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <qas-box class="qas-search-input" :use-spacing="false">
2
+ <component :is="component" class="qas-search-input" :class="containerClasses" :use-spacing="false">
3
3
  <qas-input ref="input" v-model="model" class="qas-search-input__input" v-bind="$attrs" data-cy="search-input" :debounce="debounce" dense hide-bottom-space input-class="ellipsis text-grey-8" inputmode="search" outlined type="search">
4
4
  <template #prepend>
5
5
  <q-icon v-if="useSearchOnType" color="grey-8" name="sym_r_search" />
@@ -13,13 +13,18 @@
13
13
  <slot name="after-clear" />
14
14
  </template>
15
15
  </qas-input>
16
- </qas-box>
16
+ </component>
17
17
  </template>
18
18
 
19
19
  <script>
20
20
  export default {
21
21
  name: 'QasSearchInput',
22
22
 
23
+ inject: {
24
+ isBox: { default: false },
25
+ isDialog: { default: false }
26
+ },
27
+
23
28
  inheritAttrs: false,
24
29
 
25
30
  props: {
@@ -46,6 +51,20 @@ export default {
46
51
  ],
47
52
 
48
53
  computed: {
54
+ component () {
55
+ return this.isBoxOrDialog ? 'div' : 'qas-box'
56
+ },
57
+
58
+ containerClasses () {
59
+ return {
60
+ bordered: this.isBoxOrDialog
61
+ }
62
+ },
63
+
64
+ isBoxOrDialog () {
65
+ return this.isBox || this.isDialog
66
+ },
67
+
49
68
  debounce () {
50
69
  return this.useDebounce ? '1200' : ''
51
70
  },
@@ -79,6 +79,10 @@ export default {
79
79
  type: Boolean
80
80
  },
81
81
 
82
+ useAutoSelect: {
83
+ type: Boolean
84
+ },
85
+
82
86
  useFetchOptionsOnCreate: {
83
87
  default: true,
84
88
  type: Boolean
@@ -187,6 +191,10 @@ export default {
187
191
  return getRequiredLabel({ label: this.label, required: this.required })
188
192
  },
189
193
 
194
+ canSetDefaultOption () {
195
+ return (this.required || this.useAutoSelect) && this.options.length === 1 && !this.modelValue
196
+ },
197
+
190
198
  // redesign
191
199
  componentClasses () {
192
200
  return {
@@ -220,15 +228,24 @@ export default {
220
228
  this.togglePopupContentClass(value)
221
229
  },
222
230
 
231
+ required () {
232
+ if (!this.canSetDefaultOption) return
233
+
234
+ this.setDefaultOption()
235
+ },
236
+
223
237
  options: {
224
238
  handler () {
225
239
  if (this.useLazyLoading && this.mx_hasFilteredOptions) return
226
240
 
227
241
  if (this.fuse || this.hasFuse) this.setFuse()
228
242
 
243
+ if (this.canSetDefaultOption) this.setDefaultOption()
244
+
229
245
  this.mx_filteredOptions = [...this.options]
230
246
  },
231
247
 
248
+ deep: true,
232
249
  immediate: true
233
250
  }
234
251
  },
@@ -303,6 +320,14 @@ export default {
303
320
  if (popupContentElement) {
304
321
  popupContentElement.classList.toggle('qas-select__is-fetching', force)
305
322
  }
323
+ },
324
+
325
+ setDefaultOption () {
326
+ const modelValue = this.attributes.emitValue
327
+ ? this.options[0].value
328
+ : this.options[0]
329
+
330
+ this.$emit('update:modelValue', modelValue)
306
331
  }
307
332
  }
308
333
  }
@@ -81,6 +81,10 @@ props:
81
81
  type: String
82
82
  examples: [value-key="uuid"]
83
83
 
84
+ use-auto-select:
85
+ desc: Controla se o select vai auto preencher em casos de ter uma única opção e não for required.
86
+ type: Boolean
87
+
84
88
  use-fetch-options-on-create:
85
89
  desc: Controla se o componente vai fazer um fetch das opções assim que o mesmo é criado (caso tenha lazy loading ativado).
86
90
  default: true
@@ -16,8 +16,9 @@
16
16
  {{ props.description }}
17
17
  </div>
18
18
 
19
- <qas-box
20
- v-if="hasBox"
19
+ <component
20
+ :is="containerListComponent"
21
+ v-if="canShowContainerList"
21
22
  class="q-mt-md relative-position"
22
23
  >
23
24
  <span class="text-grey-10 text-subtitle1">
@@ -42,7 +43,7 @@
42
43
  size="2em"
43
44
  />
44
45
  </q-inner-loading>
45
- </qas-box>
46
+ </component>
46
47
 
47
48
  <span
48
49
  v-if="hasError"
@@ -76,7 +77,7 @@
76
77
  </template>
77
78
 
78
79
  <script setup>
79
- import { computed, ref, watch, useSlots } from 'vue'
80
+ import { computed, ref, watch, useSlots, inject } from 'vue'
80
81
 
81
82
  defineOptions({ name: 'QasSelectListDialog' })
82
83
 
@@ -143,8 +144,11 @@ const emit = defineEmits(['add', 'remove', 'update:modelValue'])
143
144
 
144
145
  const slots = useSlots()
145
146
 
147
+ const isBox = inject('isBox', false)
148
+
146
149
  const hasError = computed(() => Array.isArray(props.error) ? !!props.error.length : !!props.error)
147
150
  const errorMessage = computed(() => Array.isArray(props.error) ? props.error.join(' ') : props.error)
151
+ const containerListComponent = computed(() => isBox ? 'div' : 'qas-box')
148
152
 
149
153
  const {
150
154
  listModel,
@@ -160,7 +164,7 @@ const {
160
164
  const {
161
165
  selectedOptions,
162
166
 
163
- hasBox,
167
+ canShowContainerList,
164
168
 
165
169
  add,
166
170
  removeAll,
@@ -224,7 +228,10 @@ function useList () {
224
228
  filteredOptions.value = [...options]
225
229
  })
226
230
 
227
- const hasBox = computed(() => hasFilteredOptions.value || props.loading)
231
+ /**
232
+ * Valida se tenho opções ou se está carregando para mostrar o container da listagem.
233
+ */
234
+ const canShowContainerList = computed(() => hasFilteredOptions.value || props.loading)
228
235
  const hasFilteredOptions = computed(() => model.value.length)
229
236
 
230
237
  /*
@@ -282,7 +289,7 @@ function useList () {
282
289
  filteredOptions,
283
290
  selectedOptions,
284
291
 
285
- hasBox,
292
+ canShowContainerList,
286
293
  hasFilteredOptions,
287
294
 
288
295
  add,
@@ -1,5 +1,9 @@
1
1
  <template>
2
2
  <component :is="parentComponent.is">
3
+ <slot name="parent-header">
4
+ <qas-header v-if="hasHeaderProps" v-bind="headerProps" />
5
+ </slot>
6
+
3
7
  <q-table ref="table" class="bg-white qas-table-generator text-grey-8" v-bind="attributes">
4
8
  <template v-for="(_, name) in slots" #[name]="context">
5
9
  <slot :name="name" v-bind="context" />
@@ -41,6 +45,11 @@ export default {
41
45
  type: [Array, Object]
42
46
  },
43
47
 
48
+ headerProps: {
49
+ default: () => ({}),
50
+ type: Object
51
+ },
52
+
44
53
  results: {
45
54
  default: () => [],
46
55
  required: true,
@@ -228,6 +237,10 @@ export default {
228
237
  return {
229
238
  is: this.useBox ? 'qas-box' : 'div'
230
239
  }
240
+ },
241
+
242
+ hasHeaderProps () {
243
+ return !!Object.keys(this.headerProps).length
231
244
  }
232
245
  },
233
246
 
@@ -320,8 +333,15 @@ export default {
320
333
  <style lang="scss">
321
334
  .qas-table-generator {
322
335
  .q-table {
336
+ thead tr {
337
+ height: 24px;
338
+ }
339
+
323
340
  th {
324
341
  @include set-typography($subtitle1);
342
+
343
+ border: 0 !important;
344
+ padding: 0 calc(var(--qas-spacing-lg) / 2);
325
345
  }
326
346
 
327
347
  td,
@@ -334,6 +354,10 @@ export default {
334
354
  td {
335
355
  @include set-typography($body1);
336
356
 
357
+ height: 40px;
358
+ padding-left: calc(var(--qas-spacing-lg) / 2);
359
+ padding-right: calc(var(--qas-spacing-lg) / 2);
360
+
337
361
  &:before {
338
362
  transition: background-color var(--qas-generic-transition);
339
363
  }
@@ -345,6 +369,10 @@ export default {
345
369
  background-color: var(--qas-background-color);
346
370
  }
347
371
  }
372
+
373
+ &:last-child td {
374
+ padding-bottom: 0;
375
+ }
348
376
  }
349
377
 
350
378
  thead tr:hover {
@@ -20,6 +20,12 @@ props:
20
20
  type: Object
21
21
  examples: ["{ email: { name: 'email', type: 'email', label: 'E-mail' } }"]
22
22
 
23
+ header-props:
24
+ desc: Propriedades repassadas para o componente `QasHeader`.
25
+ default: {}
26
+ type: Object
27
+ examples: ["{ description: 'Descrição', labelProps: { label: 'Titulo do header'} }"]
28
+
23
29
  results:
24
30
  desc: Lista com resultados para serem mostrados na tabela.
25
31
  default: {}
@@ -70,6 +76,9 @@ slots:
70
76
  default: {}
71
77
  type: Object
72
78
 
79
+ parent-header:
80
+ desc: 'Acesso ao slot do header dentro container'
81
+
73
82
  events:
74
83
  '@row-click -> function(event, row, index)':
75
84
  desc: Dispara ao clicar em uma linha. Não funciona usando slots personalizados (body, row e item).
@@ -35,3 +35,8 @@
35
35
  .border-right {
36
36
  border-right-width: 1px !important;
37
37
  }
38
+
39
+ .bordered {
40
+ border: 1px solid $grey-4;
41
+ border-radius: $generic-border-radius;
42
+ }