@dev.smartpricing/message-composer-layer 1.0.14 → 1.0.16

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.
@@ -142,6 +142,7 @@ defineExpose({ openCreate, openEdit })
142
142
  :placeholder="t('pages.brands.search_placeholder')"
143
143
  type="search"
144
144
  />
145
+ <slot name="actions" />
145
146
  </div>
146
147
 
147
148
  <UCard
@@ -203,7 +203,11 @@ onUnmounted(() => {
203
203
  })
204
204
 
205
205
  // ── Tracking helpers ──────────────────────────────────────────────
206
- const trackPrefix = computed(() => (props.mode === 'create' ? 'email_create' : 'email_edit'))
206
+ function track(suffix: string, data: Record<string, unknown>) {
207
+ const name = props.mode === 'create' ? `email_create.${suffix}` : `email_edit.${suffix}`
208
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
209
+ trackEvent(name as any, data as any)
210
+ }
207
211
 
208
212
  function getEmailBaseProps() {
209
213
  return {
@@ -224,7 +228,7 @@ function getEmailDraftProps() {
224
228
  watch(
225
229
  () => store.activeTab,
226
230
  (tab) => {
227
- trackEvent(`${trackPrefix.value}.change_tab`, { ...getEmailBaseProps(), tab })
231
+ track('change_tab', { ...getEmailBaseProps(), tab })
228
232
  },
229
233
  )
230
234
 
@@ -234,7 +238,7 @@ function syncAllLanguagesBeforeSave() {
234
238
  }
235
239
 
236
240
  async function saveAsDraft() {
237
- trackEvent(`${trackPrefix.value}.save_draft`, getEmailDraftProps())
241
+ track('save_draft', getEmailDraftProps())
238
242
  syncAllLanguagesBeforeSave()
239
243
 
240
244
  if (props.mode === 'create') {
@@ -259,7 +263,7 @@ async function saveAsDraft() {
259
263
  }
260
264
 
261
265
  async function saveTemplate() {
262
- trackEvent(`${trackPrefix.value}.save`, getEmailDraftProps())
266
+ track('save', getEmailDraftProps())
263
267
  syncAllLanguagesBeforeSave()
264
268
 
265
269
  if (props.mode === 'create') {
@@ -359,19 +363,19 @@ async function translateAndSave() {
359
363
 
360
364
  // ── Tracking event forwarders ─────────────────────────────────────
361
365
  function onAddLanguage(lang: string) {
362
- trackEvent(`${trackPrefix.value}.add_language`, { ...getEmailBaseProps(), language: lang })
366
+ track('add_language', { ...getEmailBaseProps(), language: lang })
363
367
  }
364
368
 
365
369
  function onRemoveLanguage(lang: string) {
366
- trackEvent(`${trackPrefix.value}.remove_language`, { ...getEmailBaseProps(), language: lang })
370
+ track('remove_language', { ...getEmailBaseProps(), language: lang })
367
371
  }
368
372
 
369
373
  function onAutoTranslateTracked(lang: string) {
370
- trackEvent(`${trackPrefix.value}.auto_translate`, { ...getEmailBaseProps(), language: lang })
374
+ track('auto_translate', { ...getEmailBaseProps(), language: lang })
371
375
  }
372
376
 
373
377
  function onPreview(lang: string) {
374
- trackEvent(`${trackPrefix.value}.preview`, { ...getEmailBaseProps(), language: lang })
378
+ track('preview', { ...getEmailBaseProps(), language: lang })
375
379
  }
376
380
 
377
381
  function onFiltersChanged(payload: {
@@ -380,11 +384,11 @@ function onFiltersChanged(payload: {
380
384
  show_only_missing: boolean
381
385
  show_only_changes: boolean
382
386
  }) {
383
- trackEvent(`${trackPrefix.value}.translations_filters`, { ...getEmailBaseProps(), ...payload })
387
+ track('translations_filters', { ...getEmailBaseProps(), ...payload })
384
388
  }
385
389
 
386
390
  function onBlockAdded(payload: { type: string; adding_mode: string }) {
387
- trackEvent(`${trackPrefix.value}.add_widget`, {
391
+ track('add_widget', {
388
392
  ...getEmailBaseProps(),
389
393
  widget_type: payload.type,
390
394
  adding_mode: payload.adding_mode,
@@ -392,14 +396,14 @@ function onBlockAdded(payload: { type: string; adding_mode: string }) {
392
396
  }
393
397
 
394
398
  function onBlockDuplicated(payload: { type: string }) {
395
- trackEvent(`${trackPrefix.value}.duplicate_widget`, {
399
+ track('duplicate_widget', {
396
400
  ...getEmailBaseProps(),
397
401
  widget_type: payload.type,
398
402
  })
399
403
  }
400
404
 
401
405
  function onBlockDeleted(payload: { type: string }) {
402
- trackEvent(`${trackPrefix.value}.remove_widget`, {
406
+ track('remove_widget', {
403
407
  ...getEmailBaseProps(),
404
408
  widget_type: payload.type,
405
409
  })
@@ -410,7 +414,7 @@ function onBlockSorted(payload: {
410
414
  before_sort_position: number
411
415
  new_position: number
412
416
  }) {
413
- trackEvent(`${trackPrefix.value}.sort_widget`, {
417
+ track('sort_widget', {
414
418
  ...getEmailBaseProps(),
415
419
  widget_type: payload.type,
416
420
  before_sort_position: payload.before_sort_position,
@@ -419,11 +423,11 @@ function onBlockSorted(payload: {
419
423
  }
420
424
 
421
425
  function onWidgetTabChanged(tab: string) {
422
- trackEvent(`${trackPrefix.value}.change_widget_tab`, { ...getEmailBaseProps(), tab })
426
+ track('change_widget_tab', { ...getEmailBaseProps(), tab })
423
427
  }
424
428
 
425
429
  function onTestSent(payload: { to_recipients: number }, lang?: string) {
426
- trackEvent(`${trackPrefix.value}.send_test`, {
430
+ track('send_test', {
427
431
  ...getEmailBaseProps(),
428
432
  widgets: emailEditorStore.blocks.map((b) => b.type),
429
433
  to_recipients: payload.to_recipients,
@@ -71,7 +71,7 @@ const testIds = computed(() =>
71
71
  :label="$t('common.internal')"
72
72
  v-model="store.isInternal"
73
73
  color="info"
74
- :data-testid="testIds.internalSwitch"
74
+ :data-testid="templateEmailCreateTestIds.internalSwitch"
75
75
  />
76
76
  </div>
77
77
  </template>
@@ -86,7 +86,10 @@ const testIds = computed(() =>
86
86
  @block-duplicated="emit('block-duplicated', $event)"
87
87
  @block-sorted="emit('block-sorted', $event)"
88
88
  @widget-tab-changed="emit('widget-tab-changed', $event)"
89
- @test-sent="(payload, lang) => emit('test-sent', payload, lang)"
89
+ @test-sent="
90
+ (payload: { to_recipients: number }, lang?: string) =>
91
+ emit('test-sent', payload, lang)
92
+ "
90
93
  />
91
94
  </div>
92
95
  </template>
@@ -1,7 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import IncompleteTranslationsDialog from '@/components/Common/IncompleteTranslationsDialog.vue'
3
- import { computed, ref, watch, onUnmounted } from 'vue'
4
- import type { WhatsappMessage, PostEntity } from '@dev.smartpricing/message-composer-utils/types'
3
+ import { computed, ref, watch, onUnmounted, type Ref } from 'vue'
4
+ import type {
5
+ WhatsappMessage,
6
+ PostEntity,
7
+ EmailMessage,
8
+ } from '@dev.smartpricing/message-composer-utils/types'
5
9
  import { useAppContextStore } from '@/stores/appContext'
6
10
  import { useMetaSubmissionStore } from '@/stores/metaSubmission'
7
11
  import { useMessageGroupQuery, useLanguagesQuery } from '~/queries'
@@ -54,7 +58,10 @@ if (props.mode === 'edit') {
54
58
  // Record original states for change tracking
55
59
  for (const message of data.messages) {
56
60
  if (message.render_type === 'whatsapp_v1') {
57
- changeTracking.recordOriginalState(message.language_id, message as WhatsappMessage)
61
+ changeTracking.recordOriginalState(
62
+ message.language_id,
63
+ message as unknown as WhatsappMessage,
64
+ )
58
65
  }
59
66
  }
60
67
  },
@@ -73,13 +80,14 @@ if (props.mode === 'create') {
73
80
  }
74
81
 
75
82
  // ── Validation ────────────────────────────────────────────────────
76
- const messagesRef = computed(() => store.messages)
77
83
  const { formState, draftSchema, validationErrors, validateDraft, validateFull, clearErrors } =
78
84
  useTemplateFormValidation({
79
85
  type: 'whatsapp',
80
86
  name: computed(() => store.name),
81
87
  category: computed(() => store.category),
82
- messages: messagesRef,
88
+ messages: computed(() => store.messages) as Ref<
89
+ Record<string, PostEntity<EmailMessage> | WhatsappMessage>
90
+ >,
83
91
  })
84
92
 
85
93
  // ── Template operations ───────────────────────────────────────────
@@ -131,7 +139,11 @@ onUnmounted(() => {
131
139
  })
132
140
 
133
141
  // ── Tracking helpers ──────────────────────────────────────────────
134
- const trackPrefix = computed(() => (props.mode === 'create' ? 'wa_create' : 'wa_edit'))
142
+ function track(suffix: string, data: Record<string, unknown>) {
143
+ const name = props.mode === 'create' ? `wa_create.${suffix}` : `wa_edit.${suffix}`
144
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
145
+ trackEvent(name as any, data as any)
146
+ }
135
147
 
136
148
  function getWaBaseProps() {
137
149
  return { name: store.name, category: store.category }
@@ -153,7 +165,7 @@ function getWaDraftProps() {
153
165
  watch(
154
166
  () => store.activeTab,
155
167
  (tab) => {
156
- trackEvent(`${trackPrefix.value}.change_tab`, { ...getWaBaseProps(), tab })
168
+ track('change_tab', { ...getWaBaseProps(), tab })
157
169
  },
158
170
  )
159
171
 
@@ -173,7 +185,7 @@ if (props.mode === 'edit') {
173
185
 
174
186
  // ── Save logic ────────────────────────────────────────────────────
175
187
  async function saveDraft() {
176
- trackEvent(`${trackPrefix.value}.save_draft`, getWaDraftProps())
188
+ track('save_draft', getWaDraftProps())
177
189
 
178
190
  if (props.mode === 'create') {
179
191
  const result = await createTemplate(
@@ -198,7 +210,7 @@ async function saveDraft() {
198
210
 
199
211
  async function saveAsNew() {
200
212
  if (!store.messageGroupId) return
201
- trackEvent(`${trackPrefix.value}.save_as_new`, getWaDraftProps())
213
+ track('save_as_new', getWaDraftProps())
202
214
 
203
215
  const cleanedMessages: Record<string, PostEntity<WhatsappMessage>> = {}
204
216
  for (const [languageId, message] of Object.entries(store.messages)) {
@@ -223,7 +235,7 @@ async function saveAsNew() {
223
235
  }
224
236
 
225
237
  async function requestApproval() {
226
- trackEvent(`${trackPrefix.value}.request_approval`, getWaDraftProps())
238
+ track('request_approval', getWaDraftProps())
227
239
 
228
240
  if (props.mode === 'create') {
229
241
  const result = await createTemplate(
@@ -332,19 +344,19 @@ async function translateAndSave() {
332
344
 
333
345
  // ── Tracking event forwarders ─────────────────────────────────────
334
346
  function onAddLanguage(lang: string) {
335
- trackEvent(`${trackPrefix.value}.add_language`, { ...getWaBaseProps(), language: lang })
347
+ track('add_language', { ...getWaBaseProps(), language: lang })
336
348
  }
337
349
 
338
350
  function onRemoveLanguage(lang: string) {
339
- trackEvent(`${trackPrefix.value}.remove_language`, { ...getWaBaseProps(), language: lang })
351
+ track('remove_language', { ...getWaBaseProps(), language: lang })
340
352
  }
341
353
 
342
354
  function onAutoTranslateTracked(lang: string) {
343
- trackEvent(`${trackPrefix.value}.auto_translate`, { ...getWaBaseProps(), language: lang })
355
+ track('auto_translate', { ...getWaBaseProps(), language: lang })
344
356
  }
345
357
 
346
358
  function onPreview(lang: string) {
347
- trackEvent(`${trackPrefix.value}.preview`, { ...getWaBaseProps(), language: lang })
359
+ track('preview', { ...getWaBaseProps(), language: lang })
348
360
  }
349
361
 
350
362
  function onFiltersChanged(payload: {
@@ -353,7 +365,7 @@ function onFiltersChanged(payload: {
353
365
  show_only_missing: boolean
354
366
  show_only_changes: boolean
355
367
  }) {
356
- trackEvent(`${trackPrefix.value}.translations_filters`, { ...getWaBaseProps(), ...payload })
368
+ track('translations_filters', { ...getWaBaseProps(), ...payload })
357
369
  }
358
370
 
359
371
  // ── Expose ────────────────────────────────────────────────────────
@@ -59,7 +59,7 @@ const testIds = computed(() =>
59
59
  v-model="store.isInternal"
60
60
  :label="$t('common.internal')"
61
61
  color="info"
62
- :data-testid="testIds.internalSwitch"
62
+ :data-testid="templateWhatsappCreateTestIds.internalSwitch"
63
63
  />
64
64
  </div>
65
65
  </template>
@@ -74,14 +74,14 @@ const testIds = computed(() =>
74
74
  }}
75
75
  </h2>
76
76
  <WhatsappEditorSyncWrapper
77
- v-model="store.messages[store.language]"
78
- :messages="store.messages"
77
+ v-model="store.messages[store.language] as WhatsappMessage"
78
+ :messages="store.messages as Record<string, WhatsappMessage>"
79
79
  :main-language-id="store.language"
80
80
  :key="store.language"
81
81
  />
82
82
  </div>
83
83
  <div class="col-span-1 overflow-y-auto" v-if="store.currentMessage">
84
- <WhatsappPreview :message="store.currentMessage" />
84
+ <WhatsappPreview :message="store.currentMessage as WhatsappMessage" />
85
85
  </div>
86
86
  </div>
87
87
  </UCard>
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import TranslationEditor from '@/components/Whatsapp/TranslationEditor.vue'
3
3
  import LanguageList from '@/components/Common/LanguageList.vue'
4
+ import type { WhatsappMessage } from '@dev.smartpricing/message-composer-utils/types'
4
5
 
5
6
  const props = defineProps<{
6
7
  mode: 'create' | 'edit'
@@ -52,9 +53,11 @@ const testIds = computed(() =>
52
53
  </div>
53
54
  <div class="overflow-y-auto" v-if="store.currentMessage && store.targetMessage">
54
55
  <TranslationEditor
55
- :base-message="store.messages[store.language] || store.messages['en']"
56
- v-model:target-message="store.messages[store.targetLanguage]"
57
- :messages="store.messages"
56
+ :base-message="
57
+ (store.messages[store.language] || store.messages['en']) as WhatsappMessage
58
+ "
59
+ v-model:target-message="store.messages[store.targetLanguage] as WhatsappMessage"
60
+ :messages="store.messages as Record<string, WhatsappMessage>"
58
61
  :current-language="store.targetLanguage"
59
62
  :base-language="store.language"
60
63
  :message-group-id="store.changeTrackingId"
@@ -4,6 +4,7 @@ import { isEmail } from '@dev.smartpricing/message-composer-utils/utils'
4
4
  import { useQuery } from '@pinia/colada'
5
5
  import { useSendTestEmailMutation } from '~/queries'
6
6
  import { messageGroupsApi, messagesApi } from '~/api'
7
+ import { useEmailEditorStore } from '~/stores/emailEditor'
7
8
  import { z } from 'zod'
8
9
 
9
10
  defineOptions({
@@ -15,6 +16,7 @@ const props = defineProps<{
15
16
  messageId?: string
16
17
  messageGroupId?: string
17
18
  language?: string
19
+ brandId?: string | null
18
20
  }>()
19
21
 
20
22
  const emit = defineEmits<{
@@ -80,6 +82,7 @@ const isResolvingMessage = computed(
80
82
 
81
83
  const { t } = useI18n()
82
84
  const toast = useToast()
85
+ const emailEditorStore = useEmailEditorStore()
83
86
  const { mutate: sendTest, isLoading: isSending, status } = useSendTestEmailMutation()
84
87
 
85
88
  const state = ref<Schema>({
@@ -104,11 +107,14 @@ const schema = z.object({
104
107
 
105
108
  type Schema = z.output<typeof schema>
106
109
 
110
+ const resolvedBrandId = computed(() => props.brandId ?? emailEditorStore.brandId)
111
+
107
112
  function onSubmit() {
108
113
  if (!resolvedMessage.value) return
109
114
  sendTest({
110
115
  message: resolvedMessage.value,
111
116
  to: state.value.to,
117
+ brand_id: resolvedBrandId.value,
112
118
  })
113
119
  }
114
120
 
@@ -19,7 +19,7 @@ interface UseTemplateFormValidationOptions {
19
19
  const draftSchema = z.object({
20
20
  name: z.string().min(1, 'editor.validation.error.nameRequired'),
21
21
  category: z.string().min(1),
22
- messages: z.record(z.string(), z.any()).refine((messages) => 'en' in messages, {
22
+ messages: z.record(z.string(), z.any()).refine((messages) => Object.keys(messages).length > 0, {
23
23
  message: 'editor.validation.error.messageRequired',
24
24
  }),
25
25
  })
@@ -4,7 +4,7 @@ definePageMeta({
4
4
  })
5
5
 
6
6
  const { t } = useI18n()
7
- const brandListRef = ref<InstanceType<typeof ComposerBrandList>>()
7
+ const brandListRef = useTemplateRef('brandListRef')
8
8
  </script>
9
9
 
10
10
  <template>
@@ -6,7 +6,7 @@ definePageMeta({
6
6
  })
7
7
 
8
8
  const route = useRoute()
9
- const composerRef = ref<InstanceType<typeof ComposerEmailComposer>>()
9
+ const composerRef = useTemplateRef('composerRef')
10
10
  const store = useEmailComposerStore()
11
11
  </script>
12
12
 
@@ -5,7 +5,7 @@ definePageMeta({
5
5
  channel: 'email',
6
6
  })
7
7
 
8
- const composerRef = ref<InstanceType<typeof ComposerEmailComposer>>()
8
+ const composerRef = useTemplateRef('composerRef')
9
9
  const store = useEmailComposerStore()
10
10
  </script>
11
11
 
@@ -6,7 +6,7 @@ definePageMeta({
6
6
  })
7
7
 
8
8
  const route = useRoute()
9
- const composerRef = ref<InstanceType<typeof ComposerWhatsappComposer>>()
9
+ const composerRef = useTemplateRef('composerRef')
10
10
  const store = useWhatsappComposerStore()
11
11
  </script>
12
12
 
@@ -5,7 +5,7 @@ definePageMeta({
5
5
  channel: 'whatsapp',
6
6
  })
7
7
 
8
- const composerRef = ref<InstanceType<typeof ComposerWhatsappComposer>>()
8
+ const composerRef = useTemplateRef('composerRef')
9
9
  const store = useWhatsappComposerStore()
10
10
  </script>
11
11
 
@@ -106,7 +106,7 @@ export const useWhatsappComposerStore = defineStore('whatsappComposer', () => {
106
106
  const msgs: Record<string, WhatsappMessage> = {}
107
107
  for (const message of data.messages) {
108
108
  if (message.render_type === 'whatsapp_v1') {
109
- msgs[message.language_id] = structuredClone(message) as WhatsappMessage
109
+ msgs[message.language_id] = structuredClone(message) as unknown as WhatsappMessage
110
110
  }
111
111
  }
112
112
  messages.value = msgs
@@ -397,7 +397,7 @@ Diese Nachrichten müssen funktional sein, nicht werblich.
397
397
  emailRequired: 'Bitte geben Sie eine gültige E-Mail-Adresse ein',
398
398
  nameRequired: 'Name ist erforderlich',
399
399
  headerMediaRequired: 'Header-Mediendatei ist erforderlich',
400
- messageRequired: 'Englische Nachricht ist erforderlich',
400
+ messageRequired: 'Mindestens eine Sprache ist erforderlich',
401
401
  headerTooLong: 'Header-Text überschreitet 60 Zeichen',
402
402
  bodyTooLong: 'Text überschreitet 1024 Zeichen',
403
403
  footerTooLong: 'Footer-Text überschreitet 60 Zeichen',
@@ -390,7 +390,7 @@ These messages must be functional, not promotional.
390
390
  emailInvalid: "Invalid email format. Use email format (e.g., example{'@'}example.com)",
391
391
  emailRequired: 'Please enter a valid email address',
392
392
  nameRequired: 'Name is required',
393
- messageRequired: 'English message is required',
393
+ messageRequired: 'At least one language is required',
394
394
  headerTooLong: 'Header text exceeds 60 characters',
395
395
  headerMediaRequired: 'Header media file is required',
396
396
  bodyTooLong: 'Body text exceeds 1024 characters',
@@ -394,7 +394,7 @@ Estos mensajes deben ser funcionales, no promocionales.
394
394
  "Formato de correo inválido. Usa el formato de correo (p. ej., example{'@'}example.com)",
395
395
  emailRequired: 'Introduce una dirección de correo válida',
396
396
  nameRequired: 'Se requiere el nombre',
397
- messageRequired: 'Se requiere el mensaje en inglés',
397
+ messageRequired: 'Se requiere al menos un idioma',
398
398
  headerTooLong: 'El texto del encabezado supera los 60 caracteres',
399
399
  headerMediaRequired: 'El archivo multimedia del encabezado es obligatorio',
400
400
  bodyTooLong: 'El texto supera los 1024 caracteres',
@@ -394,7 +394,7 @@ Ces messages doivent être fonctionnels, et non promotionnels.
394
394
  "Format d’e-mail invalide. Utilisez le format e-mail (ex. example{'@'}example.com)",
395
395
  emailRequired: 'Veuillez saisir une adresse e-mail valide',
396
396
  nameRequired: 'Le nom est requis',
397
- messageRequired: 'Le message en anglais est requis',
397
+ messageRequired: 'Au moins une langue est requise',
398
398
  headerMediaRequired: "Le fichier média de l'en-tête est requis",
399
399
  headerTooLong: 'Le texte d’en-tête dépasse 60 caractères',
400
400
  bodyTooLong: 'Le texte dépasse 1024 caractères',
@@ -393,7 +393,7 @@ Questi messaggi devono essere funzionali, non promozionali.
393
393
  "Formato email non valido. Usa il formato email (es. example{'@'}example.com)",
394
394
  emailRequired: 'Inserisci un indirizzo email valido',
395
395
  nameRequired: 'Il nome è obbligatorio',
396
- messageRequired: 'Il messaggio in inglese è obbligatorio',
396
+ messageRequired: 'È richiesta almeno una lingua',
397
397
  headerMediaRequired: "Il file multimediale dell'intestazione è obbligatorio",
398
398
  headerTooLong: 'Il testo dell’header supera i 60 caratteri',
399
399
  bodyTooLong: 'Il testo supera i 1024 caratteri',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev.smartpricing/message-composer-layer",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -39,14 +39,15 @@
39
39
  "vue-router": "^5.0.6",
40
40
  "vue3-emoji-picker": "^1.1.8",
41
41
  "zod": "^4.4.1",
42
- "@dev.smartpricing/message-composer-utils": "3.1.14"
42
+ "@dev.smartpricing/message-composer-utils": "3.1.16"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@nuxt/eslint": "^1.15.2",
46
46
  "@nuxt/test-utils": "^4.0.3",
47
47
  "@playwright/test": "^1.59.1",
48
48
  "dotenv": "^17.4.2",
49
- "nuxt-ui-layer": "git+ssh://git@github.com:smartpricing/smartness-nuxt-ui#v1.5.4"
49
+ "nuxt-ui-layer": "git+ssh://git@github.com:smartpricing/smartness-nuxt-ui#v1.5.4",
50
+ "vue-tsc": "^3.2.8"
50
51
  },
51
52
  "peerDependencies": {
52
53
  "nuxt-ui-layer": ">=1.3.0"