@bildvitta/quasar-ui-asteroid 3.16.0-beta.0 → 3.16.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.
Files changed (31) hide show
  1. package/package.json +2 -1
  2. package/src/components/actions/QasActions.vue +7 -0
  3. package/src/components/actions-menu/QasActionsMenu.vue +3 -2
  4. package/src/components/app-menu/QasAppMenu.vue +50 -6
  5. package/src/components/app-menu/QasAppMenu.yml +5 -0
  6. package/src/components/app-menu/private/PvAppMenuHelpChat.vue +222 -0
  7. package/src/components/btn-dropdown/QasBtnDropdown.vue +3 -3
  8. package/src/components/expansion-item/QasExpansionItem.vue +117 -12
  9. package/src/components/expansion-item/QasExpansionItem.yml +8 -0
  10. package/src/components/form-generator/QasFormGenerator.yml +4 -3
  11. package/src/components/form-view/QasFormView.vue +3 -1
  12. package/src/components/form-view/QasFormView.yml +3 -0
  13. package/src/components/grid-generator/QasGridGenerator.vue +2 -10
  14. package/src/components/grid-generator/QasGridGenerator.yml +4 -3
  15. package/src/components/header-actions/QasHeaderActions.vue +17 -4
  16. package/src/components/header-actions/QasHeaderActions.yml +6 -0
  17. package/src/components/label/QasLabel.vue +2 -2
  18. package/src/components/list-view/QasListView.vue +3 -1
  19. package/src/components/list-view/QasListView.yml +3 -0
  20. package/src/components/single-view/QasSingleView.vue +132 -81
  21. package/src/components/single-view/QasSingleView.yml +8 -0
  22. package/src/components/table-generator/QasTableGenerator.vue +16 -2
  23. package/src/components/table-generator/QasTableGenerator.yml +5 -0
  24. package/src/components/toggle-visibility/QasToggleVisibility.vue +79 -0
  25. package/src/components/toggle-visibility/QasToggleVisibility.yml +30 -0
  26. package/src/composables/private/index.js +3 -0
  27. package/src/composables/private/use-generator.js +26 -18
  28. package/src/composables/private/use-toggle-visibility.js +48 -0
  29. package/src/composables/private/use-view.js +186 -0
  30. package/src/mixins/view.js +12 -1
  31. package/src/vue-plugin.js +6 -2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bildvitta/quasar-ui-asteroid",
3
3
  "description": "Asteroid",
4
- "version": "3.16.0-beta.0",
4
+ "version": "3.16.0-beta.10",
5
5
  "author": "Bild & Vitta <systemteam@bild.com.br>",
6
6
  "license": "MIT",
7
7
  "main": "dist/asteroid.cjs.min.js",
@@ -43,6 +43,7 @@
43
43
  "sass": "^1.62.1"
44
44
  },
45
45
  "dependencies": {
46
+ "@bildvitta/composables": "^1.0.0-beta.7",
46
47
  "@bildvitta/store-adapter": "^1.0.0",
47
48
  "autonumeric": "^4.9.0",
48
49
  "axios": "^1.4.0",
@@ -1,5 +1,9 @@
1
1
  <template>
2
2
  <div class="q-mt-sm" :class="classes">
3
+ <div v-if="hasTertiarySlot" :class="columnClasses">
4
+ <slot name="tertiary" />
5
+ </div>
6
+
3
7
  <div v-if="hasSecondarySlot" :class="columnClasses">
4
8
  <slot name="secondary" />
5
9
  </div>
@@ -52,6 +56,8 @@ const classes = computed(() => {
52
56
  const isSmallOrFullWidth = screen.isSmall || props.useFullWidth
53
57
 
54
58
  return [
59
+ 'items-center',
60
+
55
61
  // alinhamento
56
62
  `justify-${props.align}`,
57
63
 
@@ -71,4 +77,5 @@ const columnClasses = computed(() => {
71
77
 
72
78
  const hasPrimarySlot = computed(() => !!slots.primary)
73
79
  const hasSecondarySlot = computed(() => !!slots.secondary)
80
+ const hasTertiarySlot = computed(() => !!slots.tertiary)
74
81
  </script>
@@ -3,7 +3,7 @@
3
3
  <qas-btn-dropdown v-bind="btnDropdownProps">
4
4
  <q-list data-cy="actions-menu-list">
5
5
  <slot v-for="(item, key) in formattedList.dropdownList" :item="item" :name="key">
6
- <q-item v-bind="getItemProps(item)" :key="key" clickable data-cy="actions-menu-list-item" @click="setClickHandler(item)">
6
+ <q-item v-bind="getItemProps(item)" :key="key" active-class="primary" clickable data-cy="actions-menu-list-item" @click="setClickHandler(item)">
7
7
  <q-item-section avatar>
8
8
  <q-icon :name="item.icon" />
9
9
  </q-item-section>
@@ -240,10 +240,11 @@ const { showTooltip, tooltipLabels } = useTooltips({ formattedList, fullList, pr
240
240
 
241
241
  // functions
242
242
  function getItemProps (item) {
243
- const { disable, props: itemProps } = item
243
+ const { disable, props: itemProps, to } = item
244
244
 
245
245
  return {
246
246
  disable,
247
+ to,
247
248
  ...itemProps
248
249
  }
249
250
  }
@@ -30,7 +30,7 @@
30
30
  </div>
31
31
 
32
32
  <!-- List -->
33
- <q-list v-if="props.items.length" class="q-mt-xl qas-app-menu__menu text-grey-10">
33
+ <q-list v-if="props.items.length" class="q-mt-xl qas-app-menu__menu text-grey-10" :class="menuClasses">
34
34
  <template v-for="(menuItem, index) in props.items">
35
35
  <div v-if="hasChildren(menuItem)" :key="`children-${index}`" class="qas-app-menu__content" :class="classes.content">
36
36
  <q-item class="ellipsis items-center q-py-none qas-app-menu__item qas-app-menu__item--label-mini text-weight-bold">
@@ -75,9 +75,30 @@
75
75
  </q-list>
76
76
  </div>
77
77
 
78
- <!-- User -->
79
- <div v-if="showAppUser" class="full-width q-pb-lg q-px-lg">
80
- <qas-app-user v-bind="defaultAppUserProps" />
78
+ <div v-if="showAppUser">
79
+ <!-- Chat Ajuda -->
80
+ <q-list v-if="helpChatLink" class="q-mt-xl">
81
+ <q-item class="q-mb-md text-primary" clickable>
82
+ <q-item-section avatar>
83
+ <q-icon name="sym_r_chat" />
84
+ </q-item-section>
85
+
86
+ <q-item-section>
87
+ <q-item-label>
88
+ <div class="ellipsis text-subtitle2">
89
+ Solicitar ajuda
90
+ </div>
91
+ </q-item-label>
92
+ </q-item-section>
93
+
94
+ <pv-app-menu-help-chat :link="props.helpChatLink" :mini-brand="props.miniBrand" @update:model-value="setHasOpenedHelpChat" />
95
+ </q-item>
96
+ </q-list>
97
+
98
+ <!-- User -->
99
+ <div class="full-width q-pb-lg q-px-lg">
100
+ <qas-app-user v-bind="defaultAppUserProps" />
101
+ </div>
81
102
  </div>
82
103
  </div>
83
104
  </q-drawer>
@@ -85,6 +106,7 @@
85
106
  </template>
86
107
 
87
108
  <script setup>
109
+ import PvAppMenuHelpChat from './private/PvAppMenuHelpChat.vue'
88
110
  import PvAppMenuDropdown from './private/PvAppMenuDropdown.vue'
89
111
  import QasAppUser from '../app-user/QasAppUser.vue'
90
112
 
@@ -114,6 +136,11 @@ const props = defineProps({
114
136
  type: String
115
137
  },
116
138
 
139
+ helpChatLink: {
140
+ type: String,
141
+ default: ''
142
+ },
143
+
117
144
  items: {
118
145
  default: () => [],
119
146
  type: Array
@@ -154,6 +181,7 @@ const router = useRouter()
154
181
  const rootRoute = router.hasRoute('Root') ? { name: 'Root' } : { path: '/' }
155
182
 
156
183
  const hasOpenedMenu = ref(false)
184
+ const hasOpenedHelpChat = ref(false)
157
185
  const isMini = ref(screen.isLarge)
158
186
  const reRenderCount = ref(0)
159
187
 
@@ -180,9 +208,14 @@ const model = computed({
180
208
 
181
209
  const behavior = computed(() => screen.untilLarge ? 'mobile' : 'desktop')
182
210
  const drawerWidth = computed(() => screen.untilLarge ? 320 : 280)
183
- const isMiniMode = computed(() => screen.isLarge && isMini.value && !hasOpenedMenu.value)
184
211
  const normalizedBrand = computed(() => isMini.value ? props.miniBrand : props.brand)
185
212
 
213
+ const isMiniMode = computed(() => {
214
+ return screen.isLarge && isMini.value && !hasOpenedMenu.value && !hasOpenedHelpChat.value
215
+ })
216
+
217
+ const menuClasses = computed(() => ({ 'qas-app-menu__menu--spaced': !props.helpChatLink }))
218
+
186
219
  const classes = computed(() => {
187
220
  return {
188
221
  content: {
@@ -262,6 +295,10 @@ function onMouseEvent ({ type }) {
262
295
  function setHasOpenedMenu (value) {
263
296
  hasOpenedMenu.value = value
264
297
  }
298
+
299
+ function setHasOpenedHelpChat (value) {
300
+ hasOpenedHelpChat.value = value
301
+ }
265
302
  </script>
266
303
 
267
304
  <style lang="scss" scoped>
@@ -335,8 +372,15 @@ function setHasOpenedMenu (value) {
335
372
  // Media: untilLarge
336
373
  @media (min-width: $breakpoint-sm-max) {
337
374
  &__menu {
375
+ overflow-x: hidden;
376
+
377
+ &:not(&--spaced) {
378
+ max-height: calc(100vh - 365px);
379
+ }
380
+ }
381
+
382
+ &__menu--spaced {
338
383
  max-height: calc(100vh - 310px);
339
- overflow-x: auto;
340
384
  }
341
385
  }
342
386
  }
@@ -15,6 +15,11 @@ props:
15
15
  type: String
16
16
  required: true
17
17
 
18
+ help-chat-link:
19
+ desc: Link para ser usado no iframe do chat, caso não passe nada, o chat não será exibido.
20
+ type: String
21
+ default: ''
22
+
18
23
  items:
19
24
  desc: Itens do menu.
20
25
  type: Array
@@ -0,0 +1,222 @@
1
+ <!-- O chat em si é renderizado em um iframe, o que QMenu, toda vez que fecha se auto destroy, então não podemos usar o
2
+ iframe dentro do QMenu, pois toda vez que um iframe é destruído ele perde o seu estado, e teria que iniciar um novo chat,
3
+ pra isto é criado um iframe no body, e posicionado com JS + CSS para ficar sobre o QMenu. -->
4
+
5
+ <template>
6
+ <q-menu class="pv-app-menu-help-chat shadow-2" v-bind="menuProps">
7
+ <header class="q-pa-md">
8
+ <q-img class="q-mb-md" :src="props.miniBrand" width="36px" />
9
+
10
+ <h3 class="text-h3">
11
+ Bem-vindo!
12
+ </h3>
13
+
14
+ <div class="text-body1">
15
+ Deixe a sua mensagem para o suporte técnico da Nave.
16
+ </div>
17
+ </header>
18
+
19
+ <qas-box class="full-width pv-app-menu-help-chat__content relative-position" :class="boxClasses">
20
+ <div v-if="showIframe" ref="chatContent" class="full-width" />
21
+
22
+ <div v-else class="full-width self-end">
23
+ <div class="q-mb-sm text-subtitle2">
24
+ Estamos conectados
25
+ </div>
26
+
27
+ <div class="text-body2">
28
+ Normalmente responde em alguns minutos
29
+ </div>
30
+
31
+ <qas-btn class="full-width q-mt-lg" label="Iniciar conversa" variant="primary" @click="initializeChat" />
32
+ </div>
33
+
34
+ <q-inner-loading :showing="showInnerLoading">
35
+ <q-spinner color="grey" size="2rem" />
36
+ </q-inner-loading>
37
+ </qas-box>
38
+ </q-menu>
39
+ </template>
40
+
41
+ <script setup>
42
+ import { useScreen } from '../../../composables'
43
+
44
+ import { onMounted, onUnmounted, ref, nextTick, computed } from 'vue'
45
+
46
+ defineOptions({ name: 'PvAppMenuHelpChat' })
47
+
48
+ const props = defineProps({
49
+ link: {
50
+ type: String,
51
+ default: ''
52
+ },
53
+
54
+ miniBrand: {
55
+ type: String,
56
+ default: ''
57
+ }
58
+ })
59
+
60
+ const screen = useScreen()
61
+
62
+ // refs
63
+ const chatContent = ref(null)
64
+ const isOpened = ref(false)
65
+ const showIframe = ref(false)
66
+ const showInnerLoading = ref(false)
67
+
68
+ // computed
69
+ const boxClasses = computed(() => {
70
+ return {
71
+ flex: !showIframe.value,
72
+ 'pv-app-menu-help-chat__content--is-opened': showIframe.value
73
+ }
74
+ })
75
+
76
+ const menuProps = computed(() => {
77
+ return {
78
+ anchor: screen.isSmall ? 'top middle' : 'top right',
79
+ maxWidth: screen.isSmall ? '300px' : '400px',
80
+ self: screen.isSmall ? 'bottom middle' : 'top left',
81
+ touchPosition: !screen.isSmall,
82
+
83
+ onBeforeHide: hideIframe,
84
+ onShow
85
+ }
86
+ })
87
+
88
+ // hooks
89
+
90
+ /**
91
+ * Toda vez que a prop "behavior" do componente "QasAppMenu" é alterada, este componente
92
+ * é renderizado novamente, então é necessário esconder o iframe caso ele ja esteja aberto.
93
+ */
94
+ onMounted(hideIframe)
95
+
96
+ onUnmounted(() => {
97
+ if (showIframe.value) {
98
+ window.removeEventListener('scroll', onScroll)
99
+ window.removeEventListener('resize', onScroll)
100
+ }
101
+ })
102
+
103
+ // functions
104
+
105
+ /**
106
+ * Define o estilo do iframe de acordo com a posição do "chatContent" dentro
107
+ * do QMenu.
108
+ */
109
+ async function setIframeStyle () {
110
+ await nextTick()
111
+
112
+ const iframe = getIframe()
113
+
114
+ if (!iframe || !chatContent.value) return
115
+
116
+ const { bottom, left, top } = chatContent.value.getBoundingClientRect()
117
+
118
+ const width = chatContent.value.offsetWidth
119
+
120
+ const styles = {
121
+ display: 'block',
122
+ top: `${bottom + window.scrollY}px`,
123
+ left: `${left + window.scrollX}px`,
124
+ bottom: `${top}px`,
125
+ width: `${width}px`
126
+ }
127
+
128
+ Object.assign(iframe.style, styles)
129
+ }
130
+
131
+ function onShow () {
132
+ isOpened.value = true
133
+
134
+ if (showIframe.value) setIframeStyle()
135
+ }
136
+
137
+ function hideIframe () {
138
+ isOpened.value = false
139
+
140
+ const iframe = getIframe()
141
+
142
+ if (!iframe) return
143
+
144
+ iframe.style.display = 'none'
145
+ }
146
+
147
+ function onScroll () {
148
+ if (isOpened.value) setIframeStyle()
149
+ }
150
+
151
+ function createIframe () {
152
+ const iframe = document.createElement('iframe')
153
+
154
+ iframe.id = 'chat-iframe'
155
+ iframe.className = 'pv-app-menu-help-chat__iframe'
156
+ iframe.style.display = 'none'
157
+ iframe.src = props.link
158
+
159
+ document.body.appendChild(iframe)
160
+ }
161
+
162
+ function getIframe () {
163
+ return document.getElementById('chat-iframe')
164
+ }
165
+
166
+ function initializeChat () {
167
+ createIframe()
168
+
169
+ window.addEventListener('scroll', onScroll)
170
+ window.addEventListener('resize', onScroll)
171
+
172
+ toggleIframe()
173
+ }
174
+
175
+ function toggleIframe () {
176
+ showIframe.value = !showIframe.value
177
+
178
+ showInnerLoading.value = true
179
+
180
+ /**
181
+ * É adicionado um loading por 3 motivos:
182
+ * - o iframe demora um pouco para ser carregado
183
+ * - o loading é um feedback visual para o usuário enquanto o iframe é carregado
184
+ * - não é possível adicionar uma animação aparecendo o iframe, então desta
185
+ * forma fica suavizado
186
+ */
187
+ setTimeout(async () => {
188
+ showInnerLoading.value = false
189
+
190
+ await nextTick()
191
+
192
+ onShow()
193
+ }, 2000)
194
+ }
195
+ </script>
196
+
197
+ <style lang="scss">
198
+ .pv-app-menu-help-chat {
199
+ overflow-y: hidden;
200
+
201
+ &__content {
202
+ height: 260px;
203
+ background-color: var(--qas-background-color) !important;
204
+ }
205
+
206
+ &__iframe {
207
+ border: 0;
208
+ border-radius: var(--qas-generic-border-radius);
209
+ outline: none;
210
+ position: absolute;
211
+ height: calc(260px - calc(var(--qas-spacing-md) * 2));
212
+ z-index: 9999;
213
+ }
214
+
215
+ // Media: isSmall
216
+ @media (max-width: $breakpoint-sm-min) {
217
+ &__content--is-opened {
218
+ padding: var(--qas-spacing-sm) !important;
219
+ }
220
+ }
221
+ }
222
+ </style>
@@ -2,8 +2,8 @@
2
2
  <div class="qas-btn-dropdown" :class="classes.parent">
3
3
  <div v-if="hasButtons" :class="classes.list">
4
4
  <div v-for="(buttonProps, key, index) in props.buttonsPropsList" :key="key">
5
- <div class="flex">
6
- <qas-btn :disable="props.disable" v-bind="buttonProps" variant="tertiary" @click="onClick">
5
+ <div class="flex no-wrap">
6
+ <qas-btn :disable="props.disable" v-bind="buttonProps" no-wrap variant="tertiary" @click="onClick">
7
7
  <q-menu v-if="hasMenuOnLeftSide" v-model="isMenuOpened" anchor="bottom right" auto-close self="top right" @update:model-value="onUpdateMenuValue">
8
8
  <div :class="classes.menuContent">
9
9
  <slot />
@@ -91,7 +91,7 @@ const classes = computed(() => {
91
91
  },
92
92
 
93
93
  list: {
94
- flex: !isSingleButton.value
94
+ 'flex no-wrap': !isSingleButton.value
95
95
  }
96
96
  }
97
97
  })
@@ -1,13 +1,13 @@
1
1
  <template>
2
- <div class="qas-expansion-item" :class="errorClasses">
3
- <qas-box class="qas-expansion-item__box">
4
- <q-expansion-item header-class="text-bold q-mt-sm q-pa-none" :label="props.label">
2
+ <div ref="expansionItem" class="full-width qas-expansion-item" :class="errorClasses" v-bind="expansionProps.parent">
3
+ <component :is="component.is" class="qas-expansion-item__box">
4
+ <q-expansion-item header-class="text-bold q-mt-sm q-pa-none qas-expansion-item__header" :label="props.label" v-bind="expansionProps.item">
5
5
  <template #header>
6
6
  <slot name="header">
7
7
  <div class="full-width">
8
8
  <div class="items-center q-col-gutter-sm row">
9
9
  <slot name="label">
10
- <h5 class="col-auto text-h5 text-weight-medium">
10
+ <h5 class="col-auto text-h5">
11
11
  {{ props.label }}
12
12
  </h5>
13
13
  </slot>
@@ -18,17 +18,25 @@
18
18
  </div>
19
19
  </div>
20
20
  </div>
21
+
22
+ <div v-if="hasHeaderBottom" class="q-mt-sm">
23
+ <slot name="header-bottom" />
24
+ </div>
21
25
  </div>
22
26
  </slot>
23
27
  </template>
24
28
 
25
- <q-separator class="q-my-md" />
29
+ <q-separator v-if="hasHeaderSeparator" class="q-my-md" />
30
+
31
+ <div :class="contentClasses">
32
+ <slot name="content">
33
+ <qas-grid-generator v-if="hasGridGenerator" use-inline v-bind="gridGeneratorProps" />
34
+ </slot>
35
+ </div>
26
36
 
27
- <slot name="content">
28
- <qas-grid-generator v-if="hasGridGenerator" v-bind="gridGeneratorProps" use-inline />
29
- </slot>
37
+ <q-separator v-if="hasBottomSeparator" class="q-mt-md" />
30
38
  </q-expansion-item>
31
- </qas-box>
39
+ </component>
32
40
 
33
41
  <div v-if="hasError" class="q-pt-sm qas-expansion-item__error-message text-caption text-negative">
34
42
  {{ props.errorMessage }}
@@ -37,9 +45,14 @@
37
45
  </template>
38
46
 
39
47
  <script setup>
40
- import { computed } from 'vue'
48
+ import QasBox from '../box/QasBox.vue'
41
49
 
42
- defineOptions({ name: 'QasExpansionItem' })
50
+ import { computed, provide, inject, onMounted, ref, useAttrs } from 'vue'
51
+
52
+ defineOptions({
53
+ name: 'QasExpansionItem',
54
+ inheritAttrs: false
55
+ })
43
56
 
44
57
  const props = defineProps({
45
58
  badges: {
@@ -64,20 +77,112 @@ const props = defineProps({
64
77
  gridGeneratorProps: {
65
78
  type: Object,
66
79
  default: () => ({})
80
+ },
81
+
82
+ useHeaderSeparator: {
83
+ type: Boolean,
84
+ default: undefined
67
85
  }
68
86
  })
69
87
 
88
+ const attrs = useAttrs()
89
+
90
+ provide('isExpansionItem', true)
91
+
92
+ // slots
93
+ const slots = defineSlots()
94
+
95
+ // refs
96
+ const expansionItem = ref(null)
97
+ const hasNextSibling = ref(false)
98
+
99
+ onMounted(setHasNextSibling)
100
+
101
+ // constants
102
+ const isNestedExpansionItem = inject('isExpansionItem', false)
103
+ const component = {
104
+ is: isNestedExpansionItem ? 'div' : QasBox
105
+ }
106
+
107
+ // computed
70
108
  const hasError = computed(() => props.error || !!props.errorMessage)
109
+ const hasGridGenerator = computed(() => !!Object.keys(props.gridGeneratorProps).length)
110
+ const hasBottomSeparator = computed(() => isNestedExpansionItem && hasNextSibling.value)
111
+ const hasHeaderBottom = computed(() => !!slots['header-bottom'])
112
+
113
+ /**
114
+ * Verifica se o componente deve adicionar um separador no header.
115
+ *
116
+ * - Se a propriedade useHeaderSeparator for true, retorna separador.
117
+ * - Se a propriedade useHeaderSeparator for undefined, retorna separador apenas se não for um componente aninhado.
118
+ * - Se a propriedade useHeaderSeparator for false, não retorna separador.
119
+ */
120
+ const hasHeaderSeparator = computed(() => {
121
+ return typeof props.useHeaderSeparator === 'undefined' ? !isNestedExpansionItem : props.useHeaderSeparator
122
+ })
71
123
 
72
124
  const errorClasses = computed(() => ({ 'qas-expansion-item--error': hasError.value }))
73
125
 
74
- const hasGridGenerator = computed(() => !!Object.keys(props.gridGeneratorProps).length)
126
+ const contentClasses = computed(() => {
127
+ return {
128
+ 'q-mt-sm': isNestedExpansionItem,
129
+ 'q-mt-md': !isNestedExpansionItem && !props.useHeaderSeparator
130
+ }
131
+ })
132
+
133
+ const expansionProps = computed(() => {
134
+ const {
135
+ 'onUpdate:modelValue': onUpdateModelValue,
136
+ onShow,
137
+ onBeforeShow,
138
+ onBeforeHide,
139
+ onAfterShow,
140
+ onAfterHide,
141
+ ...propsPayload
142
+ } = attrs
143
+
144
+ return {
145
+ parent: {
146
+ ...propsPayload
147
+ },
148
+
149
+ item: {
150
+ onUpdateModelValue,
151
+ onShow,
152
+ onBeforeShow,
153
+ onBeforeHide,
154
+ onAfterShow,
155
+ onAfterHide
156
+ }
157
+ }
158
+ })
159
+
160
+ // functions
161
+
162
+ /**
163
+ * Caso o componente esteja dentro de um QasExpansionItem, verifica se existe um próximo irmão
164
+ * para adicionar um separador.
165
+ */
166
+ function setHasNextSibling (value) {
167
+ if (!isNestedExpansionItem) return
168
+
169
+ const hasTextContentSibling = !!expansionItem.value.nextSibling?.textContent?.trim?.()
170
+ const hasElementSibling = !!expansionItem.value.nextElementSibling
171
+
172
+ hasNextSibling.value = hasElementSibling || hasTextContentSibling
173
+ }
75
174
  </script>
76
175
 
77
176
  <style lang="scss">
78
177
  .qas-expansion-item {
79
178
  $root: &;
80
179
 
180
+ // em alguns casos quando usado com grid, o espaçamento afetava o header, com z-index o problema é resolvido
181
+ &__header {
182
+ position: relative;
183
+ z-index: 1;
184
+ }
185
+
81
186
  &--error {
82
187
  #{$root}__box {
83
188
  border: 2px solid $negative;
@@ -24,10 +24,18 @@ props:
24
24
  desc: Propriedades que serão repassadas para o QasGridGenerator.
25
25
  type: Object
26
26
 
27
+ use-header-separator:
28
+ desc: Propriedade para forçar o QSeparator no header.
29
+ type: Boolean
30
+ default: undefined
31
+
27
32
  slots:
28
33
  header:
29
34
  desc: 'Slot para substituir o conteúdo do header'
30
35
 
36
+ header-bottom:
37
+ desc: 'Slot para acessar o conteúdo que fica abaixo do header.'
38
+
31
39
  label:
32
40
  desc: 'Slot para substituir o conteúdo da label do header.'
33
41
 
@@ -10,6 +10,10 @@ props:
10
10
  type: [Array, String, Object]
11
11
  examples: ["[{ sm: 6, md: 12 }]", "{ name: { sm: 6, md: 12 } }", "12", "{ sm: 6, md: 12 }"]
12
12
 
13
+ common-columns:
14
+ desc: Usado quando precisa passar o mesmo valor para todas as colunas, sem especificar cada uma, ela é feita como um merge com a prop "columns".
15
+ examples: ["{ name: { sm: 6, md: 12 } }", "12"]
16
+
13
17
  disable:
14
18
  desc: Deixa os campos desabilitados enviando a prop "disable" para cada campo.
15
19
  default: "false"
@@ -63,9 +67,6 @@ props:
63
67
  default: []
64
68
  type: Array
65
69
 
66
- use-common-columns:
67
- desc: Utilizado quando passar a estrutura da prop "columns" sendo um objeto onde seus breakpoints serão replicados para todos fields.
68
-
69
70
  slots:
70
71
  'field-[nome-da-chave]':
71
72
  desc: Acessa o slot de um campo especifico.
@@ -5,7 +5,9 @@
5
5
  </header>
6
6
 
7
7
  <q-form ref="form" v-bind="defaultFormProps">
8
- <slot />
8
+ <slot v-if="mx_canShowFetchErrorSlot" name="fetch-error" />
9
+
10
+ <slot v-else />
9
11
 
10
12
  <slot v-if="useActions" name="actions">
11
13
  <qas-actions>
@@ -155,6 +155,9 @@ slots:
155
155
  default:
156
156
  desc: Slot para ter o conteúdo principal (dentro do main).
157
157
 
158
+ fetch-error:
159
+ desc: Slot disponibilizado em caso de fetchError.
160
+
158
161
  footer:
159
162
  desc: Slot para acessar o footer.
160
163