@bildvitta/quasar-ui-asteroid 3.17.0 → 3.18.0-beta.1

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.
Files changed (65) hide show
  1. package/package.json +1 -1
  2. package/src/components/actions-menu/QasActionsMenu.vue +3 -3
  3. package/src/components/alert/QasAlert.vue +187 -60
  4. package/src/components/alert/QasAlert.yml +27 -5
  5. package/src/components/app-bar/QasAppBar.vue +2 -0
  6. package/src/components/app-menu/QasAppMenu.vue +127 -68
  7. package/src/components/app-menu/QasAppMenu.yml +10 -0
  8. package/src/components/app-user/QasAppUser.vue +12 -8
  9. package/src/components/app-user/QasAppUser.yml +5 -0
  10. package/src/components/badge/QasBadge.vue +1 -1
  11. package/src/components/checkbox/QasCheckbox.vue +97 -32
  12. package/src/components/date-time-input/QasDateTimeInput.vue +2 -2
  13. package/src/components/error-message/QasErrorMessage.vue +23 -0
  14. package/src/components/error-message/QasErrorMessage.yml +9 -0
  15. package/src/components/expansion-item/QasExpansionItem.vue +14 -16
  16. package/src/components/filters/QasFilters.vue +51 -30
  17. package/src/components/filters/QasFilters.yml +9 -0
  18. package/src/components/gallery/QasGallery.vue +2 -3
  19. package/src/components/gallery-card/QasGalleryCard.vue +43 -12
  20. package/src/components/gallery-card/QasGalleryCard.yml +22 -6
  21. package/src/components/input/QasInput.vue +3 -3
  22. package/src/components/label/QasLabel.vue +1 -1
  23. package/src/components/list-view/QasListView.vue +6 -1
  24. package/src/components/list-view/QasListView.yml +5 -0
  25. package/src/components/nested-fields/QasNestedFields.vue +10 -2
  26. package/src/components/nested-fields/QasNestedFields.yml +18 -3
  27. package/src/components/password-input/QasPasswordInput.vue +6 -2
  28. package/src/components/radio/QasRadio.vue +56 -10
  29. package/src/components/radio/QasRadio.yml +8 -1
  30. package/src/components/search-input/QasSearchInput.vue +14 -29
  31. package/src/components/select/QasSelect.vue +31 -21
  32. package/src/components/select-filter/QasSelectFilter.vue +33 -6
  33. package/src/components/select-filter/QasSelectFilter.yml +5 -0
  34. package/src/components/select-list/QasSelectList.vue +6 -6
  35. package/src/components/select-list/private/PvSelectListCheckbox.vue +1 -1
  36. package/src/components/table-generator/QasTableGenerator.vue +10 -5
  37. package/src/components/table-generator/QasTableGenerator.yml +9 -4
  38. package/src/components/toggle/QasToggle.vue +26 -1
  39. package/src/components/toggle-visibility/QasToggleVisibility.vue +15 -6
  40. package/src/components/tree-generator/QasTreeGenerator.vue +10 -2
  41. package/src/components/uploader/QasUploader.vue +7 -14
  42. package/src/components/uploader/private/PvUploaderGalleryCard.vue +2 -2
  43. package/src/composables/private/index.js +3 -2
  44. package/src/composables/private/use-error-message.js +28 -0
  45. package/src/composables/use-default-filters.js +47 -15
  46. package/src/css/components/field.scss +69 -2
  47. package/src/css/components/index.scss +1 -3
  48. package/src/css/components/item.scss +3 -2
  49. package/src/css/components/menu.scss +21 -0
  50. package/src/css/mixins/index.scss +1 -0
  51. package/src/css/mixins/set-error-message.scss +8 -0
  52. package/src/css/plugins/notify.scss +37 -37
  53. package/src/css/variables/scrollbar.scss +1 -1
  54. package/src/enums/Status.js +3 -3
  55. package/src/helpers/colors.js +137 -0
  56. package/src/helpers/index.js +1 -0
  57. package/src/helpers/set-scroll-gradient.js +261 -0
  58. package/src/plugins/notify-error/NotifyError.js +2 -1
  59. package/src/plugins/notify-success/NotifySuccess.js +2 -1
  60. package/src/vue-plugin.js +3 -3
  61. package/src/components/info/QasInfo.vue +0 -155
  62. package/src/components/info/QasInfo.yml +0 -34
  63. package/src/css/components/checkbox.scss +0 -14
  64. package/src/css/components/radio.scss +0 -18
  65. package/src/css/components/toggle.scss +0 -13
@@ -1,10 +1,11 @@
1
1
  <template>
2
2
  <div class="qas-app-menu">
3
- <q-drawer :key="reRenderCount" v-model="model" :behavior="behavior" class="shadow-2" :mini="isMiniMode" :mini-width="88" show-if-above :width="drawerWidth" @mouseenter="onMouseEvent" @mouseleave="onMouseEvent">
3
+ <q-drawer :key="reRenderCount" v-model="model" :behavior="behavior" class="shadow-2" :mini="isMiniMode" :mini-width="88" show-if-above :width="drawerWidth">
4
4
  <div class="column full-height justify-between no-wrap">
5
- <div class="full-width">
5
+ <!-- logo + select de módulos -->
6
+ <div class="full-width q-pb-lg" @mouseenter="onMouseEvent" @mouseleave="onMouseEvent">
6
7
  <!-- Brand -->
7
- <div v-if="!screen.untilLarge" class="q-mb-xl q-pt-xl qas-app-menu__label" :class="classes.spacedItem">
8
+ <div v-if="!screen.untilLarge" class="q-mb-lg q-pt-lg qas-app-menu__label" :class="classes.spacedItem">
8
9
  <router-link class="column flex items-center justify-center relative-position text-no-decoration" :to="rootRoute">
9
10
  <q-img v-if="normalizedBrand" :alt="props.title" class="qas-app-menu__brand qas-app-menu__label" fit="contain" height="27px" img-class="qas-app-menu__brand-img" no-spinner :src="normalizedBrand" />
10
11
 
@@ -18,76 +19,81 @@
18
19
  <q-separator />
19
20
  </div>
20
21
 
21
- <div v-if="screen.untilLarge" class="q-pr-xl q-pt-md text-right">
22
+ <div v-if="screen.untilLarge" class="flex itens-center justify-between q-pt-md q-px-xl text-right">
23
+ <div>
24
+ <q-img v-if="normalizedBrand" :alt="props.title" class="qas-app-menu__brand qas-app-menu__label" fit="contain" height="27px" img-class="qas-app-menu__brand-img" no-spinner :src="props.miniBrand" />
25
+ </div>
26
+
22
27
  <qas-btn color="grey-10" icon="sym_r_close" variant="tertiary" @click="closeDrawer" />
23
28
  </div>
24
29
 
25
30
  <!-- Module -->
26
- <div v-if="showAppMenuDropdown" class="items-center justify-between no-wrap q-mt-xl qas-app-menu__label qas-app-menu__module row" :class="classes.spacedItem">
31
+ <div v-if="showAppMenuDropdown" class="items-center justify-between no-wrap q-mt-lg qas-app-menu__label qas-app-menu__module row" :class="classes.spacedItem">
27
32
  <div class="full-width text-center">
28
33
  <pv-app-menu-dropdown v-bind="appMenuDropdownProps" />
29
34
  </div>
30
35
  </div>
36
+ </div>
31
37
 
32
- <!-- List -->
33
- <q-list v-if="props.items.length" class="q-mt-xl qas-app-menu__menu text-grey-10" :class="menuClasses">
34
- <template v-for="(menuItem, index) in props.items">
35
- <div v-if="hasChildren(menuItem)" :key="`children-${index}`" class="qas-app-menu__content" :class="classes.content">
36
- <q-item class="ellipsis items-center q-py-none qas-app-menu__item qas-app-menu__item--label-mini text-weight-bold">
37
- <div class="ellipsis qas-app-menu__label text-grey-10 text-subtitle2" :class="classes.spacedItem">
38
- {{ menuItem.label }}
39
- </div>
40
- </q-item>
41
-
42
- <q-item v-for="(menuChildItem, childIndex) in menuItem.children" :key="childIndex" :active="isActive(menuChildItem)" class="qas-app-menu__children qas-app-menu__item qas-app-menu__item--children" :to="getRouterRedirect(menuChildItem)">
43
- <q-item-section v-if="menuChildItem.icon" avatar>
44
- <q-icon :name="menuChildItem.icon" />
45
- </q-item-section>
46
-
47
- <q-item-section>
48
- <q-item-label>
49
- <div class="ellipsis text-subtitle2">
50
- {{ menuChildItem.label }}
51
- </div>
52
- </q-item-label>
53
- </q-item-section>
54
- </q-item>
55
-
56
- <div v-if="hasSeparator(index)" class="qas-app-menu__label" :class="classes.spacedItem">
57
- <q-separator spaced />
38
+ <!-- lista do menu -->
39
+ <q-list v-if="normalizedItems.length" ref="list" class="qas-app-menu__menu text-grey-10" @mouseleave="onMouseEvent" @mousemove="onMouseMoveList">
40
+ <template v-for="(menuItem, index) in normalizedItems">
41
+ <div v-if="hasChildren(menuItem)" :key="`children-${index}`" class="qas-app-menu__content" :class="classes.content">
42
+ <q-item class="ellipsis items-center q-py-none qas-app-menu__item qas-app-menu__item--label-mini text-weight-bold">
43
+ <div class="ellipsis qas-app-menu__label text-grey-10 text-subtitle2" :class="classes.spacedItem">
44
+ {{ menuItem.label }}
58
45
  </div>
59
- </div>
46
+ </q-item>
60
47
 
61
- <!-- quando tem children vazio, não deve mostrar label do item, e a label do item
62
- não tem "to", então validar se tem "to" para mostrar o item -->
63
- <q-item v-else-if="menuItem.to" :key="index" :active="isActive(menuItem)" active-class="q-router-link--active" class="qas-app-menu__item" :to="getRouterRedirect(menuItem)">
64
- <q-item-section v-if="menuItem.icon" avatar>
65
- <q-icon :name="menuItem.icon" />
48
+ <q-item v-for="(menuChildItem, childIndex) in menuItem.children" :key="childIndex" :active="isActive(menuChildItem)" class="qas-app-menu__children qas-app-menu__item qas-app-menu__item--children" :to="getRouterRedirect(menuChildItem)">
49
+ <q-item-section v-if="menuChildItem.icon" avatar>
50
+ <q-icon :name="menuChildItem.icon" />
66
51
  </q-item-section>
67
52
 
68
53
  <q-item-section>
69
54
  <q-item-label>
70
55
  <div class="ellipsis text-subtitle2">
71
- {{ menuItem.label }}
56
+ {{ menuChildItem.label }}
72
57
  </div>
73
58
  </q-item-label>
74
59
  </q-item-section>
75
60
  </q-item>
76
- </template>
77
- </q-list>
78
- </div>
79
61
 
80
- <div v-if="showAppUser">
62
+ <div v-if="hasSeparator(index)" class="qas-app-menu__label" :class="classes.spacedItem">
63
+ <q-separator spaced />
64
+ </div>
65
+ </div>
66
+
67
+ <!-- quando tem children vazio, não deve mostrar label do item, e a label do item
68
+ não tem "to", então validar se tem "to" para mostrar o item -->
69
+ <q-item v-else-if="menuItem.to" :key="index" :active="isActive(menuItem)" active-class="q-router-link--active" class="qas-app-menu__item" :to="getRouterRedirect(menuItem)">
70
+ <q-item-section v-if="menuItem.icon" avatar>
71
+ <q-icon :name="menuItem.icon" />
72
+ </q-item-section>
73
+
74
+ <q-item-section>
75
+ <q-item-label>
76
+ <div class="ellipsis text-subtitle2">
77
+ {{ menuItem.label }}
78
+ </div>
79
+ </q-item-label>
80
+ </q-item-section>
81
+ </q-item>
82
+ </template>
83
+ </q-list>
84
+
85
+ <!-- usuário + chat ajuda -->
86
+ <div v-if="showAppUser" class="q-mt-auto" @mouseenter="onMouseEvent" @mouseleave="onMouseEvent">
81
87
  <!-- Chat Ajuda -->
82
- <q-list v-if="useChat" class="q-mt-xl">
83
- <q-item class="q-mb-md text-primary" clickable @click="toggleChat">
88
+ <q-list v-if="useChat" class="q-mt-md">
89
+ <q-item class="q-pb-none" clickable @click="toggleChat">
84
90
  <q-item-section avatar>
85
- <q-icon name="sym_r_chat" />
91
+ <q-icon color="primary" name="sym_r_chat" />
86
92
  </q-item-section>
87
93
 
88
94
  <q-item-section>
89
95
  <q-item-label>
90
- <div class="ellipsis text-subtitle2">
96
+ <div class="ellipsis text-primary text-subtitle2">
91
97
  Solicitar ajuda
92
98
  </div>
93
99
  </q-item-label>
@@ -96,7 +102,7 @@
96
102
  </q-list>
97
103
 
98
104
  <!-- User -->
99
- <div class="full-width q-pb-lg q-px-lg">
105
+ <div class="full-width q-mt-md q-pb-lg q-px-lg">
100
106
  <qas-app-user v-bind="defaultAppUserProps" />
101
107
  </div>
102
108
  </div>
@@ -115,10 +121,10 @@ import useDevelopmentBadge from './composables/use-development-badge'
115
121
  import { useScreen } from '../../composables'
116
122
  import { useAuthUser } from '../../composables/private'
117
123
 
118
- import { handleProcess } from '../../helpers'
124
+ import { handleProcess, setScrollGradient } from '../../helpers'
119
125
 
120
126
  import Gleap from 'gleap'
121
- import { ref, computed, watch, onMounted } from 'vue'
127
+ import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
122
128
  import { useRouter } from 'vue-router'
123
129
 
124
130
  defineOptions({
@@ -139,6 +145,11 @@ const props = defineProps({
139
145
  type: String
140
146
  },
141
147
 
148
+ homeRoute: {
149
+ type: [String, Object],
150
+ default: undefined
151
+ },
152
+
142
153
  items: {
143
154
  default: () => [],
144
155
  type: Array
@@ -172,22 +183,32 @@ const props = defineProps({
172
183
 
173
184
  useChat: {
174
185
  type: Boolean
186
+ },
187
+
188
+ useHomeItem: {
189
+ type: Boolean,
190
+ default: true
175
191
  }
176
192
  })
177
193
 
194
+ // emits
178
195
  const emit = defineEmits(['sign-out', 'update:modelValue', 'toggle-notifications'])
179
196
 
197
+ // composables
180
198
  const screen = useScreen()
181
199
  const router = useRouter()
182
200
 
183
201
  const { toggleChat } = useChatMenu()
184
202
 
185
- const rootRoute = router.hasRoute('Root') ? { name: 'Root' } : { path: '/' }
186
-
203
+ // refs
187
204
  const hasOpenedMenu = ref(false)
188
205
  const hasOpenedHelpChat = ref(false)
189
206
  const isMini = ref(screen.isLarge)
190
207
  const reRenderCount = ref(0)
208
+ const list = ref(null)
209
+
210
+ // consts
211
+ const rootRoute = router.hasRoute('Root') ? { name: 'Root' } : { path: '/' }
191
212
 
192
213
  const composableParams = {
193
214
  props,
@@ -196,10 +217,14 @@ const composableParams = {
196
217
  onToggleNotifications: () => emit('toggle-notifications')
197
218
  }
198
219
 
220
+ // composables
199
221
  const { defaultAppUserProps, showAppUser } = useAppUser(composableParams)
200
222
  const { appMenuDropdownProps, showAppMenuDropdown } = useAppMenuDropdown(composableParams)
201
223
  const { developmentBadgeLabel, hasDevelopmentBadge } = useDevelopmentBadge()
202
224
 
225
+ const { initializeScrollGradient } = setScrollGradient()
226
+
227
+ // computeds
203
228
  const model = computed({
204
229
  get () {
205
230
  return props.modelValue
@@ -210,6 +235,21 @@ const model = computed({
210
235
  }
211
236
  })
212
237
 
238
+ const normalizedItems = computed(() => {
239
+ if (props.useHomeItem) {
240
+ return [
241
+ {
242
+ label: 'Início',
243
+ icon: 'sym_r_home',
244
+ to: props.homeRoute || rootRoute
245
+ },
246
+ ...props.items
247
+ ]
248
+ }
249
+
250
+ return props.items
251
+ })
252
+
213
253
  const behavior = computed(() => screen.untilLarge ? 'mobile' : 'desktop')
214
254
  const drawerWidth = computed(() => screen.untilLarge ? 320 : 280)
215
255
  const normalizedBrand = computed(() => isMini.value ? props.miniBrand : props.brand)
@@ -218,8 +258,6 @@ const isMiniMode = computed(() => {
218
258
  return screen.isLarge && isMini.value && !hasOpenedMenu.value && !hasOpenedHelpChat.value
219
259
  })
220
260
 
221
- const menuClasses = computed(() => ({ 'qas-app-menu__menu--spaced': !props.useChat }))
222
-
223
261
  const classes = computed(() => {
224
262
  return {
225
263
  content: {
@@ -250,7 +288,11 @@ watch(() => behavior.value, value => {
250
288
  }
251
289
  })
252
290
 
253
- // métodos
291
+ // hooks
292
+ onMounted(() => initializeScrollGradient(list.value.$el))
293
+ onBeforeUnmount(() => initializeScrollGradient(list.value.$el))
294
+
295
+ // functions
254
296
  function closeDrawer () {
255
297
  emit('update:modelValue', false)
256
298
  }
@@ -276,7 +318,7 @@ function hasChildren ({ children }) {
276
318
  }
277
319
 
278
320
  function hasSeparator (index) {
279
- return !!props.items[index + 1]
321
+ return !!normalizedItems.value[index + 1]
280
322
  }
281
323
 
282
324
  function isActive ({ to }) {
@@ -289,16 +331,41 @@ function isActive ({ to }) {
289
331
  return currentPath === itemPath
290
332
  }
291
333
 
292
- function onMouseEvent ({ type }) {
334
+ function onMouseEvent (event) {
293
335
  if (!screen.isLarge) return
294
336
 
295
- const isMouseLeave = type === 'mouseleave'
337
+ // Se o mouse estiver fora do QList
338
+ const isMouseLeave = event.type === 'mouseleave'
296
339
 
297
340
  isMini.value = isMouseLeave
298
341
 
299
342
  model.value = false
300
343
  }
301
344
 
345
+ function onMouseMoveList (event) {
346
+ // Se o menu já estiver aberto ou não for tela grande, não deve alterar o estado do menu.
347
+ if (!screen.isLarge || !isMini.value) return
348
+
349
+ const listElement = list.value.$el
350
+
351
+ // Obter a posição do QList na viewport
352
+ const { left, width } = listElement.getBoundingClientRect()
353
+
354
+ // Obter a posição do mouse relativa ao QList
355
+ const mouseRelativeX = event.clientX - left
356
+
357
+ // Calcular a largura do scrollbar do QList
358
+ const scrollbarWidth = listElement.offsetWidth - listElement.clientWidth
359
+
360
+ // Se o mouse estiver na faixa do scrollbar (última parte do QList)
361
+ const isOverScrollbar = mouseRelativeX > width - scrollbarWidth
362
+
363
+ // Se o mouse estiver sobre o scrollbar, não deve alterar o estado do menu
364
+ if (isOverScrollbar) return
365
+
366
+ onMouseEvent(event)
367
+ }
368
+
302
369
  function setHasOpenedMenu (value) {
303
370
  hasOpenedMenu.value = value
304
371
  }
@@ -378,12 +445,12 @@ function useChatMenu () {
378
445
 
379
446
  &__item {
380
447
  &:not(&--label) + &:not(&--label) {
381
- margin-top: var(--qas-spacing-sm);
448
+ margin-top: var(--qas-spacing-xs);
382
449
  }
383
450
 
384
451
  &--children.q-item {
385
452
  & + & {
386
- margin-top: var(--qas-spacing-sm);
453
+ margin-top: var(--qas-spacing-xs);
387
454
  }
388
455
  }
389
456
  }
@@ -419,7 +486,7 @@ function useChatMenu () {
419
486
  &__content + &__content,
420
487
  &__content + &__item,
421
488
  &__item + &__content {
422
- margin-top: var(--qas-spacing-sm);
489
+ margin-top: var(--qas-spacing-xs);
423
490
  }
424
491
 
425
492
  // User
@@ -431,14 +498,6 @@ function useChatMenu () {
431
498
  @media (min-width: $breakpoint-sm-max) {
432
499
  &__menu {
433
500
  overflow-x: hidden;
434
-
435
- &:not(&--spaced) {
436
- max-height: calc(100vh - 365px);
437
- }
438
- }
439
-
440
- &__menu--spaced {
441
- max-height: calc(100vh - 310px);
442
501
  }
443
502
  }
444
503
  }
@@ -15,6 +15,11 @@ props:
15
15
  type: String
16
16
  required: true
17
17
 
18
+ home-route:
19
+ desc: Rota do item de "home/inicio".
20
+ type: [String, Object]
21
+ default: undefined
22
+
18
23
  items:
19
24
  desc: Itens do menu.
20
25
  type: Array
@@ -49,6 +54,11 @@ props:
49
54
  type: Boolean
50
55
  default: true
51
56
 
57
+ use-home-item:
58
+ desc: Propriedade que adiciona item no menu de "inicio", forçando padronização.
59
+ type: Boolean
60
+ default: true
61
+
52
62
  slots:
53
63
  user:
54
64
  desc: Slot para acessar o menu de usuário.
@@ -1,12 +1,12 @@
1
1
  <template>
2
- <div class="cursor-pointer items-center no-wrap q-gutter-sm qas-app-user row" data-cy="app-user">
2
+ <div class="cursor-pointer items-center no-wrap q-gutter-x-sm qas-app-user row" data-cy="app-user">
3
3
  <div class="relative-position">
4
4
  <qas-avatar :image="props.user.photo" :size="props.avatarSize" :title="userName" />
5
5
 
6
6
  <qas-avatar v-if="hasNotificationInUserAvatar" v-bind="avatarNotificationCountProps" />
7
7
  </div>
8
8
 
9
- <div class="ellipsis qas-app-user__data">
9
+ <div v-if="displayData" class="ellipsis qas-app-user__data">
10
10
  <div class="ellipsis qas-app-user__name text-grey-10">
11
11
  {{ userName }}
12
12
  </div>
@@ -73,6 +73,8 @@ import QasAvatar from '../avatar/QasAvatar.vue'
73
73
 
74
74
  import useNotifications from '../../composables/use-notifications'
75
75
  import useQueryCache from '../../composables/use-query-cache'
76
+ import useScreen from '../../composables/use-screen'
77
+
76
78
  import { NotifySuccess, NotifyError } from '../../plugins'
77
79
 
78
80
  import { ref, computed, watch, inject } from 'vue'
@@ -105,6 +107,11 @@ const props = defineProps({
105
107
  default: () => ({}),
106
108
  required: true,
107
109
  type: Object
110
+ },
111
+
112
+ useDataOnSmallScreen: {
113
+ type: Boolean,
114
+ default: true
108
115
  }
109
116
  })
110
117
 
@@ -115,6 +122,7 @@ const emit = defineEmits(['sign-out', 'toggle-notifications'])
115
122
  const axios = inject('axios')
116
123
 
117
124
  // composables
125
+ const screen = useScreen()
118
126
  const router = useRouter()
119
127
 
120
128
  const { isNotificationsEnabled, unreadNotificationsCount } = useNotifications()
@@ -149,6 +157,8 @@ const hasNotificationInUserAvatar = computed(() => isNotificationsEnabled && has
149
157
  const unreadNotificationsToString = computed(() => String(unreadNotificationsCount.value))
150
158
  const userName = computed(() => props.user.name || props.user.givenName)
151
159
 
160
+ const displayData = computed(() => props.useDataOnSmallScreen || screen.isMedium)
161
+
152
162
  // watch
153
163
  watch(() => props.companyProps.modelValue, value => {
154
164
  companiesModel.value = value
@@ -280,11 +290,5 @@ function useAvatarNotifications () {
280
290
  margin-top: var(--qas-spacing-sm);
281
291
  }
282
292
  }
283
-
284
- @media (max-width: $breakpoint-xs) {
285
- &__data {
286
- display: none;
287
- }
288
- }
289
293
  }
290
294
  </style>
@@ -39,6 +39,11 @@ props:
39
39
  "
40
40
  ]
41
41
 
42
+ use-data-on-small-screen:
43
+ desc: Habilita os dados do usuário como nome/email em telas pequenas/ (mobile).
44
+ type: Boolean
45
+ default: true
46
+
42
47
  events:
43
48
  '@sign-out -> function()':
44
49
  desc: Dispara quando o botão de "sair" é clicado.
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <component :is="component.is" v-bind="component.props" class="q-px-sm qas-badge text-caption">
2
+ <component :is="component.is" v-bind="component.props" class="q-px-sm qas-badge text-body2">
3
3
  <slot />
4
4
  </component>
5
5
  </template>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="qas-checkbox">
2
+ <div class="qas-checkbox" :class="classes">
3
3
  <!-- Single -->
4
4
  <q-checkbox v-if="isSingle" v-model="model" v-bind="singleAttributes" dense>
5
5
  <slot />
@@ -7,32 +7,32 @@
7
7
 
8
8
  <!-- Group -->
9
9
  <div v-else>
10
- <div v-if="hasCheckboxLabel" class="q-mb-sm text-body1" :class="checkboxLabelClasses">
11
- {{ formattedLabel }}
12
- </div>
10
+ <qas-label v-if="props.label" :color="labelColor" :label="formattedLabel" margin="sm" typography="h5" />
13
11
 
14
- <div :class="classes">
12
+ <div class="flex q-col-gutter-md" :class="contentClasses">
15
13
  <div v-for="(option, index) in props.options" :key="index">
16
14
  <!-- Com children -->
17
- <q-checkbox v-if="hasChildren(option)" :class="getCheckboxClass(option)" dense :indeterminate-value="false" :label="option.label" :model-value="getModelValue(index)" @update:model-value="updateCheckbox($event, option, index)" />
15
+ <q-checkbox v-if="hasChildren(option)" :class="getCheckboxClass(option)" dense :disable="props.disable" :indeterminate-value="false" :label="option.label" :model-value="getModelValue(index)" @update:model-value="updateCheckbox($event, option, index)" />
18
16
 
19
17
  <!-- Com children -->
20
- <q-option-group v-if="hasChildren(option)" class="q-ml-xs q-mt-xs" dense :inline="props.inline" :model-value="props.modelValue" :options="option.children" type="checkbox" @update:model-value="updateChildren($event, option, index)" />
18
+ <q-option-group v-if="hasChildren(option)" class="q-ml-sm q-mt-sm" :class="gutterClasses" dense :disable="props.disable" :inline="isInline" :model-value="props.modelValue" :options="option.children" type="checkbox" @update:model-value="updateChildren($event, option, index)" />
21
19
 
22
20
  <!-- Sem children -->
23
- <q-option-group v-else v-model="model" v-bind="attrs" dense :options="[option]" type="checkbox" />
21
+ <q-option-group v-else v-model="model" v-bind="attrs" dense :disable="props.disable" inline :options="[option]" type="checkbox" />
24
22
  </div>
25
23
  </div>
26
24
  </div>
27
25
 
28
- <div v-if="props.errorMessage" class="q-pt-sm qas-checkbox__error-message text-negative">
29
- {{ props.errorMessage }}
30
- </div>
26
+ <qas-error-message v-if="hasErrorMessage" :message="props.errorMessage" />
31
27
  </div>
32
28
  </template>
33
29
 
34
30
  <script setup>
31
+ import useErrorMessage, { baseErrorProps } from '../../composables/private/use-error-message'
32
+ import useScreen from '../../composables/use-screen'
33
+
35
34
  import { getRequiredLabel } from '../../helpers'
35
+
36
36
  import { watch, computed, ref, onMounted, useAttrs } from 'vue'
37
37
 
38
38
  defineOptions({
@@ -41,6 +41,12 @@ defineOptions({
41
41
  })
42
42
 
43
43
  const props = defineProps({
44
+ ...baseErrorProps,
45
+
46
+ disable: {
47
+ type: Boolean
48
+ },
49
+
44
50
  label: {
45
51
  default: '',
46
52
  type: String
@@ -61,34 +67,49 @@ const props = defineProps({
61
67
  type: Boolean
62
68
  },
63
69
 
64
- errorMessage: {
65
- type: String,
66
- default: ''
67
- },
68
-
69
- error: {
70
+ required: {
70
71
  type: Boolean
71
72
  },
72
73
 
73
- required: {
74
- type: Boolean
74
+ useAsTitle: {
75
+ type: Boolean,
76
+ default: false
75
77
  }
76
78
  })
77
79
 
80
+ // emits
78
81
  const emit = defineEmits(['update:modelValue'])
79
82
 
83
+ // globals
80
84
  const attrs = useAttrs()
81
85
 
86
+ // composables
87
+ const { color } = useErrorMessage(props)
88
+ const screen = useScreen()
89
+
82
90
  // refs
83
91
  const group = ref({})
84
92
 
85
- // lifecycle
93
+ // hooks
86
94
  onMounted(handleParent)
87
95
 
88
96
  // computed
89
- const classes = computed(() => props.inline && 'flex q-gutter-x-sm')
97
+ const isInline = computed(() => !screen.isSmall)
98
+ const isSingle = computed(() => !props.options.length)
99
+ const isTitleMode = computed(() => props.useAsTitle && isSingle.value)
90
100
 
91
- const hasCheckboxLabel = computed(() => !!props.label)
101
+ const classes = computed(() => {
102
+ return {
103
+ 'qas-checkbox--title': isTitleMode.value,
104
+ 'qas-checkbox--error': props.error && isSingle.value
105
+ }
106
+ })
107
+
108
+ const labelColor = computed(() => props.disable ? 'grey-6' : color.value)
109
+ const contentClasses = computed(() => !isInline.value && 'column')
110
+ const gutterClasses = computed(() => isInline.value ? 'q-gutter-x-md' : 'q-gutter-y-md')
111
+
112
+ const hasErrorMessage = computed(() => props.errorMessage && !isSingle.value)
92
113
 
93
114
  const model = computed({
94
115
  get () {
@@ -100,20 +121,14 @@ const model = computed({
100
121
  }
101
122
  })
102
123
 
103
- const isSingle = computed(() => !props.options.length)
104
-
105
124
  const singleAttributes = computed(() => {
106
125
  return {
107
126
  ...attrs,
108
-
127
+ disable: props.disable,
109
128
  label: props.label
110
129
  }
111
130
  })
112
131
 
113
- const checkboxLabelClasses = computed(() => {
114
- return { 'text-negative': props.error }
115
- })
116
-
117
132
  const formattedLabel = computed(() => {
118
133
  return getRequiredLabel({ label: props.label, required: props.required })
119
134
  })
@@ -177,9 +192,59 @@ function getModelValue (index) {
177
192
 
178
193
  <style lang="scss">
179
194
  .qas-checkbox {
180
- &__error-message {
181
- // Tamanho da fonte utilizada nos errors no q-field.
182
- font-size: 11px;
195
+ $root: &;
196
+
197
+ // aplica pra todos que não for title, uma vez que title tem tipografia própria
198
+ &:not(&--title) {
199
+ color: $grey-8;
200
+
201
+ .q-checkbox__label {
202
+ @include set-typography($body1);
203
+ }
204
+ }
205
+
206
+ .q-checkbox {
207
+ &__label {
208
+ padding-left: var(--qas-spacing-sm) !important;
209
+ }
210
+
211
+ &__inner {
212
+ width: 18px;
213
+ height: 18px;
214
+ min-width: 18px;
215
+ }
216
+
217
+ &.disabled {
218
+ opacity: 1 !important;
219
+
220
+ .q-checkbox__label,
221
+ .q-checkbox__bg,
222
+ .q-checkbox__inner {
223
+ color: $grey-6;
224
+ }
225
+ }
226
+ }
227
+
228
+ &--title {
229
+ color: $grey-10;
230
+
231
+ &:not(#{$root}--error) {
232
+ .q-checkbox__inner--falsy .q-checkbox__bg {
233
+ border-color: $grey-10;
234
+ }
235
+ }
236
+
237
+ .q-checkbox__label {
238
+ @include set-typography($h5);
239
+ }
240
+ }
241
+
242
+ &--error {
243
+ color: $negative;
244
+
245
+ .q-checkbox__bg {
246
+ color: $negative;
247
+ }
183
248
  }
184
249
  }
185
250
  </style>