@bildvitta/quasar-ui-asteroid 3.12.0-beta.1 → 3.12.0-beta.10

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.12.0-beta.1",
4
+ "version": "3.12.0-beta.10",
5
5
  "author": "Bild & Vitta <systemteam@bild.com.br>",
6
6
  "license": "MIT",
7
7
  "main": "dist/asteroid.cjs.min.js",
@@ -1,87 +1,110 @@
1
1
  <template>
2
- <div v-if="model" class="bg-white q-pa-lg qas-alert relative-position rounded-borders" :class="classes">
3
- <qas-btn class="absolute-top-right q-mr-md q-mt-sm" color="grey-9" icon="sym_r_close" variant="tertiary" @click="close" />
2
+ <div v-if="show" class="inline-block">
3
+ <div class="bg-dark flex justify-between no-wrap q-pa-md qas-alert relative-position">
4
+ <div class="qas-alert__border-left" :class="borderClass" />
4
5
 
5
- <div class="q-gutter-md q-mr-lg">
6
- <slot name="header">
7
- <h5 v-if="title" class="text-bold text-h5" data-test="alert-title">{{ title }}</h5>
8
- </slot>
6
+ <div class="text-body1 text-white">
7
+ <slot>
8
+ {{ text }}
9
+ </slot>
10
+ </div>
9
11
 
10
- <slot>
11
- <qas-breakline tag="p" :text="text" />
12
- </slot>
12
+ <qas-btn
13
+ class="q-ml-xs qas-alert__close"
14
+ color="white"
15
+ icon="sym_r_close"
16
+ :use-hover-on-white-color="false"
17
+ @click="close"
18
+ />
13
19
  </div>
14
20
  </div>
15
21
  </template>
16
22
 
17
- <script>
18
- import QasBreakline from '../breakline/QasBreakline.vue'
19
- import QasBtn from '../btn/QasBtn.vue'
23
+ <script setup>
24
+ import { LocalStorage } from 'quasar'
25
+ import { Status, StatusColor } from '../../enums/Status'
26
+ import { computed, watch, ref } from 'vue'
20
27
 
21
- export default {
22
- name: 'QasAlert',
28
+ defineOptions({ name: 'QasAlert' })
23
29
 
24
- components: {
25
- QasBreakline,
26
- QasBtn
30
+ const props = defineProps({
31
+ modelValue: {
32
+ type: Boolean,
33
+ default: true
27
34
  },
28
35
 
29
- props: {
30
- modelValue: {
31
- default: true,
32
- type: Boolean
33
- },
34
-
35
- text: {
36
- default: '',
37
- type: String
38
- },
39
-
40
- color: {
41
- type: String,
42
- default: 'primary'
43
- },
44
-
45
- title: {
46
- default: '',
47
- type: String
48
- }
36
+ text: {
37
+ type: String,
38
+ default: ''
49
39
  },
50
40
 
51
- emits: ['update:modelValue'],
52
-
53
- data () {
54
- return {
55
- model: true
56
- }
41
+ storageKey: {
42
+ type: String,
43
+ default: ''
57
44
  },
58
45
 
59
- computed: {
60
- classes () {
61
- return `text-${this.color}`
62
- }
46
+ status: {
47
+ type: String,
48
+ default: Status.Info,
49
+ validator: value => Object.values(Status).includes(value)
63
50
  },
64
51
 
65
- watch: {
66
- modelValue: {
67
- handler (value) {
68
- this.model = value
69
- },
70
- immediate: true
71
- }
72
- },
52
+ usePersistentModelOnClose: {
53
+ type: Boolean
54
+ }
55
+ })
56
+
57
+ const emit = defineEmits(['update:modelValue'])
58
+
59
+ const model = ref(props.modelValue)
60
+
61
+ watch(() => props.modelValue, value => {
62
+ model.value = value
63
+ })
64
+
65
+ const colorByStatus = computed(() => {
66
+ const status = Object.keys(Status).find(key => Status[key] === props.status)
67
+ return StatusColor[status]
68
+ })
69
+
70
+ const borderClass = computed(() => `bg-${colorByStatus.value}`)
71
+
72
+ const storageClosedKey = computed(() => `alert-${props.storageKey}-closed`)
73
73
 
74
- methods: {
75
- close () {
76
- this.$emit('update:modelValue', false)
77
- }
74
+ const isClosed = computed(() => {
75
+ return props.usePersistentModelOnClose && LocalStorage.getItem(storageClosedKey.value)
76
+ })
77
+
78
+ const show = computed(() => !isClosed.value && model.value)
79
+
80
+ function close () {
81
+ if (props.usePersistentModelOnClose) {
82
+ LocalStorage.set(storageClosedKey.value, true)
78
83
  }
84
+
85
+ model.value = false
86
+
87
+ emit('update:modelValue', model.value)
79
88
  }
89
+
80
90
  </script>
81
91
 
82
92
  <style lang="scss">
83
93
  .qas-alert {
84
- border-style: solid;
85
- border-width: 0 10px;
94
+ border-radius: var(--qas-generic-border-radius);
95
+
96
+ &__border-left {
97
+ border-radius: var(--qas-generic-border-radius) 0 0 var(--qas-generic-border-radius);
98
+ bottom: 0;
99
+ content: '';
100
+ left: 0;
101
+ position: absolute;
102
+ top: 0;
103
+ width: 4px;
104
+ }
105
+
106
+ &__close {
107
+ top: calc(var(--qas-spacing-sm) * -1);
108
+ }
86
109
  }
87
110
  </style>
@@ -9,21 +9,27 @@ props:
9
9
  default: true
10
10
  type: Boolean
11
11
 
12
- title:
13
- desc: Título do componente.
14
- type: String
15
-
16
12
  text:
17
13
  desc: Texto do componente.
18
14
  type: String
19
15
 
16
+ status:
17
+ desc: Status do alerta.
18
+ type: String
19
+ examples: ['error', 'info']
20
+
21
+ storage-key:
22
+ desc: Chave a ser salva no localStorage, necessário caso esteja usando mais de um QasAlert na aplicação e ambos estejam com a prop "use-persist-model-on-close" ativada.
23
+ type: String
24
+
25
+ use-persistent-model-on-close:
26
+ desc: Habilita salvar o model em localStorage ao fechar o alerta para não aparecer novamente.
27
+ type: Boolean
28
+
20
29
  slots:
21
30
  default:
22
31
  desc: 'Slot para acessar o conteúdo gerado pela prop "text"'
23
32
 
24
- header:
25
- desc: 'Slot para acessar o conteúdo gerado pela prop "title"'
26
-
27
33
  events:
28
34
  '@update:model-value -> function(value)':
29
35
  desc: Dispara quando o model-value altera, também usado para v-model.
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="text-h4" :class="classes">
2
+ <div :class="classes">
3
3
  <slot :label-with-suffix="formattedLabel">{{ formattedLabel }}</slot>
4
4
  </div>
5
5
  </template>
@@ -39,6 +39,16 @@ export default {
39
39
 
40
40
  required: {
41
41
  type: Boolean
42
+ },
43
+
44
+ typography: {
45
+ default: 'h4',
46
+ type: String,
47
+ validator: value => {
48
+ const availableTypography = ['h4', 'h5']
49
+
50
+ return availableTypography.includes(value)
51
+ }
42
52
  }
43
53
  },
44
54
 
@@ -54,7 +64,8 @@ export default {
54
64
  classes () {
55
65
  return [
56
66
  `q-mb-${this.margin}`,
57
- `text-${this.color}`
67
+ `text-${this.color}`,
68
+ `text-${this.typography}`
58
69
  ]
59
70
  }
60
71
  }
@@ -4,6 +4,11 @@ meta:
4
4
  desc: Componente para controlar textos que separam conteúdos, formatando com um sufixo quando existe um contador.
5
5
 
6
6
  props:
7
+ color:
8
+ desc: Cor do texto.
9
+ default: grey-9
10
+ type: String
11
+
7
12
  count:
8
13
  desc: Contador que vai ficar ao lado do texto.
9
14
  default: 0
@@ -20,14 +25,15 @@ props:
20
25
  examples: [xs, sm, md, lg, xl]
21
26
 
22
27
  required:
23
- desc: Controla label do campo, se for "true" adiciona sufixo "*".
28
+ desc: Controla se exibirá o sufixo "*" ao lado do texto.
24
29
  default: false
25
30
  type: Boolean
26
31
 
27
- color:
28
- desc: Cor da label.
29
- default: grey-9
32
+ typography:
33
+ desc: Controla qual a tipografia do texto.
34
+ default: h4
30
35
  type: String
36
+ examples: [h4, h5]
31
37
 
32
38
  slots:
33
39
  default:
@@ -1,16 +1,16 @@
1
1
  <template>
2
2
  <div :id="fieldName" class="qas-nested-fields">
3
3
  <div v-if="useSingleLabel" class="text-left">
4
- <qas-label :label="fieldLabel" margin="lg" />
4
+ <qas-label :label="fieldLabel" typography="h5" />
5
5
  </div>
6
6
 
7
7
  <div ref="inputContent">
8
8
  <component :is="componentTag" v-bind="componentProps">
9
9
  <template v-for="(row, index) in nested" :key="`row-${index}`">
10
- <div v-if="!row[destroyKey]" :id="`row-${index}`" class="full-width q-mt-md qas-nested-fields__field-item">
10
+ <div v-if="!row[destroyKey]" :id="`row-${index}`" class="full-width qas-nested-fields__field-item">
11
11
  <header v-if="hasHeader" class="flex items-center q-pb-md" :class="headerClasses">
12
- <qas-label v-if="!useSingleLabel" :label="getRowLabel(index)" margin="none" />
13
- <qas-actions-menu v-if="hasBlockActions(row)" v-bind="actionsMenuProps" :list="getActionsList(index, row)" />
12
+ <qas-label v-if="!useSingleLabel" :label="getRowLabel(index)" margin="none" typography="h5" />
13
+ <qas-actions-menu v-if="hasBlockActions(row)" v-bind="getActionsMenuProps(index, row)" />
14
14
  </header>
15
15
 
16
16
  <div ref="formGenerator" class="col-12 justify-between q-col-gutter-x-md row">
@@ -23,7 +23,7 @@
23
23
  </slot>
24
24
 
25
25
  <div v-if="hasInlineActions(row)" class="flex items-center qas-nested-fields__actions">
26
- <qas-actions-menu v-bind="actionsMenuProps" :list="getActionsList(index, row)" />
26
+ <qas-actions-menu v-bind="getActionsMenuProps(index, row)" />
27
27
  </div>
28
28
  </div>
29
29
 
@@ -34,7 +34,7 @@
34
34
  </template>
35
35
  </component>
36
36
 
37
- <div v-if="useAdd" class="q-mt-md">
37
+ <div v-if="useAdd">
38
38
  <slot :add="add" name="add-input">
39
39
  <div v-if="showAddFirstInputButton" class="text-left">
40
40
  <qas-btn class="q-px-sm" color="primary" variant="tertiary" @click="add()">{{ addFirstInputLabel }}</qas-btn>
@@ -86,7 +86,7 @@ export default {
86
86
 
87
87
  props: {
88
88
  actionsMenuProps: {
89
- type: Object,
89
+ type: [Object, Function],
90
90
  default: () => ({})
91
91
  },
92
92
 
@@ -130,7 +130,7 @@ export default {
130
130
  },
131
131
 
132
132
  disabledRows: {
133
- type: [Array, Boolean],
133
+ type: [Array, Boolean, Function],
134
134
  default: false
135
135
  },
136
136
 
@@ -327,7 +327,22 @@ export default {
327
327
  },
328
328
 
329
329
  methods: {
330
- getActionsList (index, row) {
330
+ getActionsMenuProps (index, row) {
331
+ if (typeof this.actionsMenuProps === 'function') {
332
+ return this.actionsMenuProps({
333
+ index,
334
+ row,
335
+ list: this.getDefaultActionsMenuList(index, row)
336
+ })
337
+ }
338
+
339
+ return {
340
+ ...this.actionsMenuProps,
341
+ list: this.getActionsMenuList(index, row)
342
+ }
343
+ },
344
+
345
+ getDefaultActionsMenuList (index, row) {
331
346
  const list = {}
332
347
 
333
348
  if (this.useDuplicate) {
@@ -344,6 +359,12 @@ export default {
344
359
  }
345
360
  }
346
361
 
362
+ return list
363
+ },
364
+
365
+ getActionsMenuList (index, row) {
366
+ const list = this.getDefaultActionsMenuList(index, row)
367
+
347
368
  for (const key in this.actionsMenuProps.list) {
348
369
  const { handler, ...content } = this.actionsMenuProps.list[key] || {}
349
370
 
@@ -449,6 +470,8 @@ export default {
449
470
  isDisabledRow (row) {
450
471
  if (!this.disabledRows) return false
451
472
 
473
+ if (typeof this.disabledRows === 'function') return this.disabledRows(row)
474
+
452
475
  if (typeof this.disabledRows === 'boolean') return true
453
476
 
454
477
  return this.disabledRows.includes(row[this.identifierItemKey])
@@ -471,6 +494,10 @@ export default {
471
494
  height: 56px;
472
495
  }
473
496
 
497
+ &__field-item {
498
+ margin-bottom: var(--qas-spacing-md);
499
+ }
500
+
474
501
  &__field-item + &__field-item {
475
502
  margin-top: var(--qas-spacing-xl);
476
503
  }
@@ -5,9 +5,9 @@ meta:
5
5
 
6
6
  props:
7
7
  actions-menu-props:
8
- desc: Repassa as propriedades para o componente QasActionsMenu.
8
+ desc: Repassa as propriedades para o componente QasActionsMenu. É possível passar um objeto com as propriedades ou uma função que recebe o 'index', 'row' e 'list' como parâmetro e retorna um objeto com as propriedades.
9
9
  default: {}
10
- type: Object
10
+ type: [Object, Function]
11
11
 
12
12
  add-first-input-label:
13
13
  desc: Rótulo do input para adicionar o primeiro campo.
@@ -37,10 +37,10 @@ props:
37
37
  type: String
38
38
 
39
39
  disabled-rows:
40
- desc: Com esta propriedade é possível desabilitar rows (linhas) especificas passando um array com chaves identificadoras, ou caso queira desativar todas passando um boolean "true" (isto vai remover todos os botões da linha, duplicar e excluir).
40
+ desc: Com esta propriedade é possível desabilitar rows (linhas) especificas passando um array com chaves identificadoras, caso queira desativar todas passe um valor boolean "true", ou também é possível utilizar uma função de callback, que receberá a "row" como parâmetro. (Isto vai remover todos os botões da linha, como por exemplo, o duplicar e excluir).
41
41
  default: "false"
42
- type: [Array, Boolean]
43
- examples: ["['my-uuid-from-row-1']", true]
42
+ type: [Array, Boolean, Function]
43
+ examples: ["['my-uuid-from-row-1']", true, "row => row.disable"]
44
44
 
45
45
  errors:
46
46
  desc: Propriedade de erros para mostrar nos campos gerados.
@@ -178,6 +178,12 @@ export default {
178
178
  if (this.hasFuse) this.setFuse()
179
179
  },
180
180
 
181
+ mx_isFetching (value) {
182
+ if (!this.isPopupContentOpen || !this.useLazyLoading) return
183
+
184
+ this.togglePopupContentClass(value)
185
+ },
186
+
181
187
  options: {
182
188
  handler () {
183
189
  if (this.useLazyLoading && this.mx_hasFilteredOptions) return
@@ -193,7 +199,6 @@ export default {
193
199
 
194
200
  created () {
195
201
  this.setSearchMethod()
196
- this.setIsFetchingWatcher()
197
202
  },
198
203
 
199
204
  methods: {
@@ -238,16 +243,6 @@ export default {
238
243
  }
239
244
  },
240
245
 
241
- setIsFetchingWatcher () {
242
- if (this.useLazyLoading) {
243
- this.$watch('mx_isFetching', value => {
244
- if (!this.isPopupContentOpen) return
245
-
246
- this.togglePopupContentClass(value)
247
- })
248
- }
249
- },
250
-
251
246
  setLazyLoading () {
252
247
  this.mx_setCachedOptions('options')
253
248
 
@@ -132,6 +132,10 @@ const props = defineProps({
132
132
  selectListProps: {
133
133
  type: Object,
134
134
  default: () => ({})
135
+ },
136
+
137
+ useLazyLoading: {
138
+ type: Boolean
135
139
  }
136
140
  })
137
141
 
@@ -184,7 +188,9 @@ const labelProps = computed(() => {
184
188
  }
185
189
  })
186
190
 
187
- const hasLazyLoading = computed(() => !!props.selectListProps?.searchBoxProps?.useLazyLoading)
191
+ const hasLazyLoading = computed(() => {
192
+ return props.useLazyLoading || !!props.selectListProps?.searchBoxProps?.useLazyLoading
193
+ })
188
194
 
189
195
  watch(() => props.modelValue, newValue => {
190
196
  model.value = [...newValue]
@@ -237,7 +243,7 @@ function useList () {
237
243
 
238
244
  model.value.push(...newModel)
239
245
 
240
- emit('add', newModel)
246
+ emit('add', normalizedItems)
241
247
 
242
248
  updateModel()
243
249
  }
@@ -322,6 +328,7 @@ function useSelectDialog () {
322
328
  ...props.selectListProps,
323
329
 
324
330
  searchBoxProps: {
331
+ useLazyLoading: props.useLazyLoading,
325
332
  list: props.options,
326
333
  height: '160px',
327
334
  optionsToExclude: model.value,
@@ -60,6 +60,11 @@ props:
60
60
  default: []
61
61
  type: Array
62
62
 
63
+ use-lazy-loading:
64
+ desc: O componente precisa saber se o lazy-loading esta habilitado para este componente, e caso esteja usando customização pelos slots do "dialog-description", é necessário informar por esta prop.
65
+ default: false
66
+ type: Boolean
67
+
63
68
  slots:
64
69
  dialog-actions:
65
70
  desc: Slot para substituir ações do dialog.
@@ -71,21 +76,21 @@ slots:
71
76
  desc: Slot para substituir cabeçalho do dialog.
72
77
 
73
78
  events:
74
- 'add -> function(list)':
79
+ '@add -> function(items)':
75
80
  desc: Dispara toda vez que é adicionado novos itens.
76
81
  params:
77
- list:
82
+ items:
78
83
  desc: Lista de itens adicionados.
79
84
  type: Array
80
85
 
81
- 'remove -> function(value)':
86
+ '@remove -> function(value)':
82
87
  desc: Dispara toda vez que é removido um item.
83
88
  params:
84
89
  value:
85
90
  desc: Valor do item (uuid/id/slug).
86
91
  type: String
87
92
 
88
- 'update:model-value -> function(list)':
93
+ '@update:model-value -> function(list)':
89
94
  desc: Dispara toda vez que o model é atualizado.
90
95
  params:
91
96
  list:
@@ -154,6 +154,11 @@ export default {
154
154
  type: Number
155
155
  },
156
156
 
157
+ uploadCredentialsParams: {
158
+ type: Object,
159
+ default: () => ({})
160
+ },
161
+
157
162
  uploading: {
158
163
  type: Boolean
159
164
  },
@@ -170,6 +175,11 @@ export default {
170
175
  useResize: {
171
176
  default: true,
172
177
  type: Boolean
178
+ },
179
+
180
+ useUrlPath: {
181
+ type: Boolean,
182
+ default: true
173
183
  }
174
184
  },
175
185
 
@@ -366,7 +376,8 @@ export default {
366
376
  try {
367
377
  const { data } = await this.$axios.post('/upload-credentials/', {
368
378
  entity: this.entity,
369
- filename
379
+ filename,
380
+ ...this.uploadCredentialsParams
370
381
  })
371
382
 
372
383
  return data
@@ -377,7 +388,7 @@ export default {
377
388
  uploadedFiles = uploadedFiles.map((file, indexToDelete) => {
378
389
  return {
379
390
  isUploaded: true,
380
- url: file.xhr ? file.xhr.responseURL.split('?').shift() : '',
391
+ url: file.xhr ? this.getURLValue(file.xhr) : '',
381
392
  name: file.name,
382
393
  indexToDelete,
383
394
  isFailed: this.isFailed(file)
@@ -421,6 +432,16 @@ export default {
421
432
  return value.split('/').pop()
422
433
  },
423
434
 
435
+ /**
436
+ * Caso useUrlPath seja true, retorna de responseURL, senão tenta retornar o response
437
+ * que pode ser um base64, caso não tenha o response, retorna a responseURL.
438
+ */
439
+ getURLValue (xhr) {
440
+ const responseURL = xhr.responseURL.split('?').shift()
441
+
442
+ return this.useUrlPath ? responseURL : (xhr.response || responseURL)
443
+ },
444
+
424
445
  getModelValue (index) {
425
446
  if (!this.useObjectModel) return {}
426
447
 
@@ -571,7 +592,7 @@ export default {
571
592
  uploaded (response) {
572
593
  this.hasError = false
573
594
 
574
- const fullPath = response.xhr.responseURL.split('?').shift()
595
+ const fullPath = this.getURLValue(response.xhr)
575
596
 
576
597
  const objectValue = {
577
598
  format: response.files[0].type,
@@ -33,7 +33,7 @@ props:
33
33
  'image/webp',
34
34
  'image/jpg'
35
35
  ]
36
-
36
+
37
37
  columns:
38
38
  desc: Seta as colunas (grid cols), valor default depende se o componente é múltiplo ou não.
39
39
  default:
@@ -118,6 +118,11 @@ props:
118
118
  default: 1280
119
119
  type: Number
120
120
 
121
+ upload-credentials-params:
122
+ desc: Parâmetros enviados para a API do `/upload-credentials/`.
123
+ default: {}
124
+ type: Object
125
+
121
126
  uploading:
122
127
  desc: Model que retorna se o componente está fazendo algum upload.
123
128
  type: Boolean
@@ -139,6 +144,11 @@ props:
139
144
  default: true
140
145
  type: Boolean
141
146
 
147
+ use-url-path:
148
+ desc: Controla se o componente vai salvar o path url no model ou por exemplo um base64.
149
+ default: true
150
+ type: Boolean
151
+
142
152
  slots:
143
153
  header:
144
154
  desc: Acesso ao header do <q-uploader />.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Cores por status
3
+ *
4
+ * @property
5
+ * @name Spacing
6
+ * @readonly
7
+ * @enum
8
+ * @type {{
9
+ * Info: 'yellow-14',
10
+ * Error: 'red-14'
11
+ * }}
12
+ */
13
+ export const StatusColor = {
14
+ Info: 'yellow-14',
15
+ Error: 'red-14'
16
+ }
17
+
18
+ /**
19
+ * Status
20
+ *
21
+ * @property
22
+ * @name Spacing
23
+ * @readonly
24
+ * @enum
25
+ * @type {{
26
+ * Info: 'info',
27
+ * Error: 'error'
28
+ * }}
29
+ */
30
+ export const Status = {
31
+ Info: 'info',
32
+ Error: 'error'
33
+ }