@bildvitta/quasar-ui-asteroid 3.13.0-beta.8 → 3.13.0

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/QasActions.vue +54 -47
  3. package/src/components/actions-menu/QasActionsMenu.vue +147 -149
  4. package/src/components/actions-menu/QasActionsMenu.yml +13 -0
  5. package/src/components/app-bar/QasAppBar.vue +59 -87
  6. package/src/components/app-menu/QasAppMenu.vue +128 -256
  7. package/src/components/app-menu/composables/use-app-menu-dropdown.js +71 -0
  8. package/src/components/app-menu/composables/use-app-user.js +46 -0
  9. package/src/components/app-menu/composables/use-development-badge.js +23 -0
  10. package/src/components/app-menu/private/PvAppMenuDropdown.vue +33 -39
  11. package/src/components/app-user/QasAppUser.vue +94 -92
  12. package/src/components/avatar/QasAvatar.vue +67 -85
  13. package/src/components/avatar/enums/AvatarColors.js +9 -0
  14. package/src/components/badge/QasBadge.vue +21 -22
  15. package/src/components/badge/QasBadge.yml +1 -1
  16. package/src/components/box/QasBox.vue +17 -19
  17. package/src/components/btn/QasBtn.vue +132 -135
  18. package/src/components/btn/QasBtn.yml +3 -3
  19. package/src/components/btn-dropdown/QasBtnDropdown.vue +2 -2
  20. package/src/components/chart-view/QasChartView.vue +2 -2
  21. package/src/components/date/QasDate.vue +3 -3
  22. package/src/components/date-time-input/QasDateTimeInput.vue +2 -2
  23. package/src/components/delete/QasDelete.vue +1 -1
  24. package/src/components/dialog/QasDialog.vue +135 -244
  25. package/src/components/dialog/composables/use-cancel.js +40 -0
  26. package/src/components/dialog/composables/use-dynamic-components.js +86 -0
  27. package/src/components/dialog/composables/use-ok.js +45 -0
  28. package/src/components/filters/QasFilters.vue +1 -1
  29. package/src/components/filters/private/PvFiltersButton.vue +2 -2
  30. package/src/components/form-generator/QasFormGenerator.yml +1 -1
  31. package/src/components/gallery/QasGallery.vue +1 -1
  32. package/src/components/gallery/private/PvGalleryCarouselDialog.vue +2 -2
  33. package/src/components/gallery-card/QasGalleryCard.vue +2 -2
  34. package/src/components/label/QasLabel.vue +1 -1
  35. package/src/components/label/QasLabel.yml +1 -1
  36. package/src/components/nested-fields/QasNestedFields.vue +37 -14
  37. package/src/components/nested-fields/QasNestedFields.yml +63 -17
  38. package/src/components/page-header/QasPageHeader.vue +1 -11
  39. package/src/components/pagination/QasPagination.vue +1 -1
  40. package/src/components/search-input/QasSearchInput.vue +2 -2
  41. package/src/components/select-list-dialog/QasSelectListDialog.vue +3 -3
  42. package/src/components/table-generator/QasTableGenerator.vue +8 -4
  43. package/src/components/tabs-generator/QasTabsGenerator.vue +1 -1
  44. package/src/components/timeline/QasTimeline.vue +2 -2
  45. package/src/components/tree-generator/QasTreeGenerator.vue +1 -1
  46. package/src/components/uploader/QasUploader.vue +1 -1
  47. package/src/components/uploader/private/PvUploaderGalleryCard.vue +1 -1
  48. package/src/components/welcome/QasWelcome.vue +2 -2
  49. package/src/composables/use-history.js +4 -4
  50. package/src/css/components/base.scss +1 -0
  51. package/src/css/components/button.scss +2 -2
  52. package/src/css/components/checkbox.scss +12 -0
  53. package/src/css/components/editor.scss +7 -0
  54. package/src/css/components/field.scss +23 -3
  55. package/src/css/components/index.scss +3 -0
  56. package/src/css/components/item.scss +1 -1
  57. package/src/css/components/radio.scss +15 -2
  58. package/src/css/components/toggle.scss +11 -0
  59. package/src/css/variables/typography.scss +11 -1
  60. package/src/enums/Align.js +7 -0
  61. package/src/index.scss +4 -4
  62. package/src/pages/ErrorComponent.vue +1 -2
  63. package/src/plugins/dialog/Dialog.js +1 -1
  64. package/src/shared/notify-config.js +1 -1
  65. package/src/vue-plugin.js +4 -0
@@ -4,37 +4,37 @@
4
4
  <div class="column full-height justify-between no-wrap">
5
5
  <div class="full-width">
6
6
  <!-- Brand -->
7
- <div v-if="!isUntilLarge" class="q-mb-xl q-pt-xl qas-app-menu__label" :class="spacedItemClass">
8
- <router-link class="flex relative-position text-no-decoration" :class="brandPositionClass" :to="rootRoute">
9
- <q-img v-if="normalizedBrand" :alt="title" class="qas-app-menu__brand qas-app-menu__label" :class="brandClass" height="40px" no-spinner :src="normalizedBrand" />
7
+ <div v-if="!screen.untilLarge" class="q-mb-xl q-pt-xl qas-app-menu__label" :class="classes.spacedItem">
8
+ <router-link class="column flex items-center justify-center relative-position text-no-decoration" :to="rootRoute">
9
+ <q-img v-if="normalizedBrand" :alt="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
10
 
11
11
  <span v-else-if="!isMiniMode" class="ellipsis text-bold text-primary text-subtitle2">{{ title }}</span>
12
12
 
13
- <q-badge v-if="hasDevelopmentBadge" color="red" floating :label="developmentBadgeLabel" />
13
+ <q-badge v-if="hasDevelopmentBadge" class="q-mt-sm" color="red" :label="developmentBadgeLabel" />
14
14
  </router-link>
15
15
  </div>
16
16
 
17
- <div v-if="normalizedBrand" class="qas-app-menu__label" :class="spacedItemClass">
17
+ <div v-if="normalizedBrand" class="qas-app-menu__label" :class="classes.spacedItem">
18
18
  <q-separator />
19
19
  </div>
20
20
 
21
- <div v-if="isUntilLarge" class="q-pr-xl q-pt-md text-right">
22
- <qas-btn color="grey-9" icon="sym_r_close" variant="tertiary" @click="closeDrawer" />
21
+ <div v-if="screen.untilLarge" class="q-pr-xl q-pt-md text-right">
22
+ <qas-btn color="grey-10" icon="sym_r_close" variant="tertiary" @click="closeDrawer" />
23
23
  </div>
24
24
 
25
25
  <!-- Module -->
26
- <div v-if="displayModuleSection" class="items-center justify-between no-wrap q-mt-xl qas-app-menu__label qas-app-menu__module row" :class="spacedItemClass">
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">
27
27
  <div class="full-width text-center">
28
28
  <pv-app-menu-dropdown v-bind="appMenuDropdownProps" />
29
29
  </div>
30
30
  </div>
31
31
 
32
32
  <!-- List -->
33
- <q-list v-if="items.length" class="q-mt-xl qas-app-menu__menu text-grey-9">
33
+ <q-list v-if="items.length" class="q-mt-xl qas-app-menu__menu text-grey-10">
34
34
  <template v-for="(menuItem, index) in items">
35
- <div v-if="hasChildren(menuItem)" :key="`children-${index}`" class="qas-app-menu__content" :class="contentClass">
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">
37
- <div class="ellipsis qas-app-menu__label text-grey-9 text-subtitle2" :class="spacedItemClass">
37
+ <div class="ellipsis qas-app-menu__label text-grey-10 text-subtitle2" :class="classes.spacedItem">
38
38
  {{ menuItem.label }}
39
39
  </div>
40
40
  </q-item>
@@ -53,7 +53,7 @@
53
53
  </q-item-section>
54
54
  </q-item>
55
55
 
56
- <div v-if="hasSeparator(index)" class="qas-app-menu__label" :class="spacedItemClass">
56
+ <div v-if="hasSeparator(index)" class="qas-app-menu__label" :class="classes.spacedItem">
57
57
  <q-separator spaced />
58
58
  </div>
59
59
  </div>
@@ -84,289 +84,163 @@
84
84
  </div>
85
85
  </template>
86
86
 
87
- <script>
87
+ <script setup>
88
88
  import PvAppMenuDropdown from './private/PvAppMenuDropdown.vue'
89
-
90
89
  import QasAppUser from '../app-user/QasAppUser.vue'
91
90
 
92
- import { isLocalDevelopment } from '../../helpers'
91
+ import useAppMenuDropdown from './composables/use-app-menu-dropdown'
92
+ import useAppUser from './composables/use-app-user'
93
+ import useDevelopmentBadge from './composables/use-development-badge'
94
+ import { useScreen } from '../../composables'
93
95
 
94
- export default {
95
- name: 'QasAppMenu',
96
+ import { ref, computed } from 'vue'
97
+ import { useRouter } from 'vue-router'
96
98
 
97
- components: {
98
- PvAppMenuDropdown,
99
- QasAppUser
99
+ defineOptions({
100
+ name: 'QasAppMenu',
101
+ inheritAttrs: false
102
+ })
103
+
104
+ const props = defineProps({
105
+ appUserProps: {
106
+ type: Object,
107
+ required: true,
108
+ default: () => ({})
100
109
  },
101
110
 
102
- inheritAttrs: false,
103
-
104
- props: {
105
- appUserProps: {
106
- type: Object,
107
- required: true,
108
- default: () => ({})
109
- },
110
-
111
- brand: {
112
- default: '',
113
- required: true,
114
- type: String
115
- },
116
-
117
- items: {
118
- default: () => [],
119
- type: Array
120
- },
121
-
122
- miniBrand: {
123
- type: String,
124
- required: true,
125
- default: ''
126
- },
127
-
128
- modelValue: {
129
- default: true,
130
- type: Boolean
131
- },
132
-
133
- modules: {
134
- default: () => [],
135
- type: Array
136
- },
137
-
138
- notifications: {
139
- default: () => ({}),
140
- type: Object
141
- },
142
-
143
- title: {
144
- default: '',
145
- type: String
146
- }
111
+ brand: {
112
+ default: '',
113
+ required: true,
114
+ type: String
147
115
  },
148
116
 
149
- emits: ['sign-out', 'update:modelValue'],
150
-
151
- data () {
152
- return {
153
- hasOpenedMenu: false,
154
- isMini: this.$qas.screen.isLarge,
155
- module: ''
156
- }
117
+ items: {
118
+ default: () => [],
119
+ type: Array
157
120
  },
158
121
 
159
- computed: {
160
- appMenuDropdownProps () {
161
- return {
162
- buttonDropdownProps: {
163
- 'onUpdate:menu': this.setHasOpenedMenu
164
- },
165
-
166
- currentModule: this.currentModelOption,
167
- modules: this.defaultModules
168
- }
169
- },
170
-
171
- behavior () {
172
- return this.isUntilLarge ? 'mobile' : 'desktop'
173
- },
174
-
175
- brandClass () {
176
- return {
177
- 'qas-app-menu__brand--spaced': !this.isMiniMode
178
- }
179
- },
180
-
181
- brandPositionClass () {
182
- return {
183
- 'justify-center': this.isMiniMode
184
- }
185
- },
186
-
187
- contentClass () {
188
- return {
189
- 'qas-app-menu__content--spaced': !this.isMiniMode
190
- }
191
- },
192
-
193
- currentModelOption () {
194
- return this.defaultModules.find(module => module?.value === this.module)
195
- },
196
-
197
- currentModule () {
198
- const hostname = window.location.hostname
199
- return this.defaultModules.find(module => module?.value.includes(hostname))?.value
200
- },
201
-
202
- defaultAppUserProps () {
203
- return {
204
- avatarSize: '40px',
205
-
206
- menuProps: {
207
- 'onUpdate:modelValue': this.setHasOpenedMenu
208
- },
209
-
210
- // eventos
211
- onSignOut: this.signOut,
212
- ...this.appUserProps
213
- }
214
- },
215
-
216
- defaultModules () {
217
- if (!isLocalDevelopment()) return this.modules
218
-
219
- const defaultModules = [...this.modules]
220
- const { host, protocol } = window.location
221
- const value = `${protocol}//${host}`
222
-
223
- // Add a default module called "Localhost" when app is running in local development.
224
- defaultModules.unshift({
225
- label: `Localhost ${this.title ? `(${this.title})` : ''}`,
226
- icon: 'sym_r_home',
227
- value
228
- })
229
-
230
- return defaultModules
231
- },
232
-
233
- developmentBadgeLabel () {
234
- const hosts = {
235
- localhost: 'Local',
236
- '.dev.': 'Develop'
237
- }
122
+ miniBrand: {
123
+ type: String,
124
+ required: true,
125
+ default: ''
126
+ },
238
127
 
239
- if (process.env.DEV) {
240
- return hosts.localhost
241
- }
128
+ modelValue: {
129
+ default: true,
130
+ type: Boolean
131
+ },
242
132
 
243
- const current = Object.keys(hosts).find(
244
- host => location.hostname.includes(host)
245
- )
133
+ modules: {
134
+ default: () => [],
135
+ type: Array
136
+ },
246
137
 
247
- return current ? hosts[current] : ''
248
- },
138
+ notifications: {
139
+ default: () => ({}),
140
+ type: Object
141
+ },
249
142
 
250
- displayModuleSection () {
251
- return this.defaultModules.length
252
- },
143
+ title: {
144
+ default: '',
145
+ type: String
146
+ }
147
+ })
253
148
 
254
- drawerWidth () {
255
- return this.isUntilLarge ? 320 : 280
256
- },
149
+ const emits = defineEmits(['sign-out', 'update:modelValue'])
257
150
 
258
- hasDevelopmentBadge () {
259
- return !!this.developmentBadgeLabel
260
- },
151
+ const screen = useScreen()
152
+ const router = useRouter()
261
153
 
262
- isLargeScreen () {
263
- return this.$qas.screen.isLarge
264
- },
154
+ const rootRoute = router.hasRoute('Root') ? { name: 'Root' } : { path: '/' }
265
155
 
266
- isMiniMode () {
267
- return this.isLargeScreen && this.isMini && !this.hasOpenedMenu
268
- },
156
+ const hasOpenedMenu = ref(false)
157
+ const isMini = ref(screen.isLarge)
269
158
 
270
- isUntilLarge () {
271
- return this.$qas.screen.untilLarge
272
- },
159
+ const composableParams = {
160
+ props,
161
+ onMenuUpdate: setHasOpenedMenu,
162
+ onSignOut: () => emits('sign-out')
163
+ }
273
164
 
274
- model: {
275
- get () {
276
- return this.modelValue
277
- },
165
+ const { defaultAppUserProps, showAppUser } = useAppUser(composableParams)
166
+ const { appMenuDropdownProps, showAppMenuDropdown } = useAppMenuDropdown(composableParams)
167
+ const { developmentBadgeLabel, hasDevelopmentBadge } = useDevelopmentBadge()
278
168
 
279
- set (value) {
280
- return this.$emit('update:modelValue', value)
281
- }
282
- },
169
+ const model = computed({
170
+ get () {
171
+ return props.modelValue
172
+ },
283
173
 
284
- normalizedBrand () {
285
- return this.isMiniMode ? this.miniBrand : this.brand
286
- },
174
+ set (value) {
175
+ emits('update:modelValue', value)
176
+ }
177
+ })
287
178
 
288
- rootRoute () {
289
- return this.$router.hasRoute('Root') ? { name: 'Root' } : { path: '/' }
290
- },
179
+ const behavior = computed(() => screen.untilLarge ? 'mobile' : 'desktop')
180
+ const drawerWidth = computed(() => screen.untilLarge ? 320 : 280)
181
+ const isMiniMode = computed(() => screen.isLarge && isMini.value && !hasOpenedMenu.value)
182
+ const normalizedBrand = computed(() => isMini.value ? props.miniBrand : props.brand)
291
183
 
292
- showAppUser () {
293
- return this.hasUser && !this.isUntilLarge
184
+ const classes = computed(() => {
185
+ return {
186
+ content: {
187
+ 'qas-app-menu__content--spaced': !isMiniMode.value
294
188
  },
295
189
 
296
- spacedItemClass () {
297
- return {
298
- 'qas-app-menu__label--spaced': !this.isMiniMode
299
- }
300
- }
301
- },
302
-
303
- watch: {
304
- currentModule: {
305
- handler (value) {
306
- this.module = value
307
- },
308
-
309
- immediate: true
190
+ spacedItem: {
191
+ 'qas-app-menu__label--spaced': !isMiniMode.value
310
192
  }
311
- },
193
+ }
194
+ })
312
195
 
313
- methods: {
314
- closeDrawer () {
315
- this.$emit('update:modelValue', false)
316
- },
196
+ // métodos
197
+ function closeDrawer () {
198
+ emits('update:modelValue', false)
199
+ }
317
200
 
318
- getNormalizedPath (path) {
319
- return path.split('/').filter(Boolean)?.[0]
320
- },
201
+ function getNormalizedPath (path) {
202
+ return path.split('/').filter(Boolean)?.[0]
203
+ }
321
204
 
322
- getPathFromObject ({ path, name }) {
323
- if (path) return this.getNormalizedPath(path)
205
+ function getPathFromObject ({ path, name }) {
206
+ if (path) return getNormalizedPath(path)
324
207
 
325
- const resolvedRoute = this.$router.resolve({ name })
326
- return this.getNormalizedPath(resolvedRoute.path)
327
- },
208
+ const resolvedRoute = router.resolve({ name })
328
209
 
329
- getRouterRedirect ({ to }) {
330
- return to || ''
331
- },
332
-
333
- hasChildren ({ children }) {
334
- return !!(children || []).length
335
- },
210
+ return getNormalizedPath(resolvedRoute.path)
211
+ }
336
212
 
337
- hasSeparator (index) {
338
- return !!this.items[index + 1]
339
- },
213
+ function getRouterRedirect ({ to }) {
214
+ return to || ''
215
+ }
340
216
 
341
- hasUser () {
342
- return !!Object.keys(this.defaultAppUserProps.user || {}).length
343
- },
217
+ function hasChildren ({ children }) {
218
+ return !!(children || []).length
219
+ }
344
220
 
345
- isActive ({ to }) {
346
- const currentPath = this.getNormalizedPath(this.$route.path)
347
- const itemPath = typeof to === 'string' ? this.getNormalizedPath(to) : this.getPathFromObject(to)
221
+ function hasSeparator (index) {
222
+ return !!props.items[index + 1]
223
+ }
348
224
 
349
- return currentPath === itemPath
350
- },
225
+ function isActive ({ to }) {
226
+ const currentPath = getNormalizedPath(router.currentRoute.value.path)
227
+ const itemPath = typeof to === 'string' ? getNormalizedPath(to) : getPathFromObject(to)
351
228
 
352
- onMouseEvent ({ type }) {
353
- if (!this.isLargeScreen) return
229
+ return currentPath === itemPath
230
+ }
354
231
 
355
- const isMouseLeave = type === 'mouseleave'
232
+ function onMouseEvent ({ type }) {
233
+ if (!screen.isLarge) return
356
234
 
357
- this.isMini = isMouseLeave
235
+ const isMouseLeave = type === 'mouseleave'
358
236
 
359
- this.model = false
360
- },
237
+ isMini.value = isMouseLeave
361
238
 
362
- signOut () {
363
- this.$emit('sign-out')
364
- },
239
+ model.value = false
240
+ }
365
241
 
366
- setHasOpenedMenu (value) {
367
- this.hasOpenedMenu = value
368
- }
369
- }
242
+ function setHasOpenedMenu (value) {
243
+ hasOpenedMenu.value = value
370
244
  }
371
245
  </script>
372
246
 
@@ -412,10 +286,8 @@ export default {
412
286
  }
413
287
 
414
288
  &__brand {
415
- width: 40px;
416
-
417
- &--spaced {
418
- width: 208px;
289
+ :deep(.qas-app-menu__brand-img) {
290
+ transition: opacity 120ms ease-in; // 120ms é o mesmo tempo utilizado na abertura do QDrawer.
419
291
  }
420
292
  }
421
293
 
@@ -0,0 +1,71 @@
1
+ import { isLocalDevelopment } from '../../../helpers'
2
+
3
+ import { computed, watch, ref } from 'vue'
4
+
5
+ /**
6
+ * @param {{
7
+ * props: { modules: [], title: string },
8
+ * onMenuUpdate: () => void
9
+ * }} config
10
+ */
11
+ export default function useAppMenuDropdown (config = {}) {
12
+ const {
13
+ props,
14
+ onMenuUpdate
15
+ } = config
16
+
17
+ const { hostname } = window.location
18
+
19
+ const module = ref('')
20
+
21
+ const defaultModules = computed(() => {
22
+ if (!isLocalDevelopment()) return props.modules
23
+
24
+ const normalizedModules = [...props.modules]
25
+
26
+ const { host, protocol } = location
27
+ const value = `${protocol}//${host}`
28
+
29
+ /**
30
+ * Adiciona um módulo padrão chamado "Localhost" quando o aplicativo está sendo
31
+ * executado em desenvolvimento local.
32
+ */
33
+ normalizedModules.unshift({
34
+ label: `Localhost ${props.title ? `(${props.title})` : ''}`,
35
+ icon: 'sym_r_home',
36
+ value
37
+ })
38
+
39
+ return normalizedModules
40
+ })
41
+
42
+ const currentModelOption = computed(() => {
43
+ return defaultModules.value.find(moduleOption => moduleOption?.value === module.value)
44
+ })
45
+
46
+ const appMenuDropdownProps = computed(() => {
47
+ return {
48
+ buttonDropdownProps: {
49
+ 'onUpdate:menu': onMenuUpdate
50
+ },
51
+
52
+ currentModule: currentModelOption.value,
53
+ modules: defaultModules.value
54
+ }
55
+ })
56
+
57
+ const currentModule = computed(() => {
58
+ return defaultModules.value.find(module => module?.value.includes(hostname))?.value
59
+ })
60
+
61
+ const showAppMenuDropdown = computed(() => !!currentModule.value)
62
+
63
+ watch(() => currentModule.value, value => {
64
+ module.value = value
65
+ }, { immediate: true })
66
+
67
+ return {
68
+ appMenuDropdownProps,
69
+ showAppMenuDropdown
70
+ }
71
+ }
@@ -0,0 +1,46 @@
1
+ import { useScreen } from '../../../composables'
2
+
3
+ import { computed } from 'vue'
4
+
5
+ /**
6
+ * @param {{
7
+ * props: { appUserProps: {} }
8
+ * onSignOut: () => void
9
+ * onMenuUpdate: () => void
10
+ * }} config
11
+ */
12
+ export default function useAppUser (config = {}) {
13
+ const {
14
+ props,
15
+
16
+ onSignOut,
17
+ onMenuUpdate
18
+ } = config
19
+
20
+ const screen = useScreen()
21
+
22
+ const defaultAppUserProps = computed(() => {
23
+ return {
24
+ avatarSize: '40px',
25
+
26
+ menuProps: {
27
+ 'onUpdate:modelValue': onMenuUpdate()
28
+ },
29
+
30
+ // eventos
31
+ onSignOut,
32
+ ...props.appUserProps
33
+ }
34
+ })
35
+
36
+ const showAppUser = computed(() => {
37
+ const hasAppUser = !!Object.keys(defaultAppUserProps.value.user || {}).length
38
+
39
+ return hasAppUser && !screen.isUntilLarge
40
+ })
41
+
42
+ return {
43
+ defaultAppUserProps,
44
+ showAppUser
45
+ }
46
+ }
@@ -0,0 +1,23 @@
1
+ import { computed } from 'vue'
2
+
3
+ export default function useDevelopmentBadge () {
4
+ const developmentBadgeLabel = computed(() => {
5
+ const hosts = {
6
+ localhost: 'Local',
7
+ '.dev.': 'Develop'
8
+ }
9
+
10
+ if (process.env.DEV) return hosts.localhost
11
+
12
+ const current = Object.keys(hosts).find(host => window.location.hostname.includes(host))
13
+
14
+ return current ? hosts[current] : ''
15
+ })
16
+
17
+ const hasDevelopmentBadge = computed(() => !!developmentBadgeLabel.value)
18
+
19
+ return {
20
+ developmentBadgeLabel,
21
+ hasDevelopmentBadge
22
+ }
23
+ }