@saasmakers/ui 0.1.60 → 0.1.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/bases/BaseAvatar.vue +5 -5
- package/app/components/bases/BaseButton.vue +15 -1
- package/app/components/bases/BaseIcon.vue +15 -1
- package/app/components/bases/BaseQuote.vue +15 -1
- package/app/components/bases/BaseTags.vue +5 -1
- package/app/components/fields/FieldCheckbox.vue +98 -0
- package/app/components/fields/FieldDays.vue +109 -0
- package/app/components/fields/FieldEmojis.vue +104 -0
- package/app/components/fields/FieldInput.vue +209 -0
- package/app/components/fields/FieldLabel.vue +64 -0
- package/app/components/fields/FieldMessage.vue +209 -0
- package/app/components/fields/FieldSelect.vue +291 -0
- package/app/components/fields/FieldTabs.vue +100 -0
- package/app/components/fields/FieldTextarea.vue +123 -0
- package/app/components/fields/FieldTime.vue +73 -0
- package/app/composables/useDevice.ts +11 -0
- package/app/composables/useUtils.ts +7 -0
- package/app/types/fields.d.ts +179 -0
- package/app/types/global.d.ts +10 -0
- package/nuxt.config.ts +8 -4
- package/package.json +7 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import type { FieldTextarea } from '../../types/fields'
|
|
3
|
+
|
|
4
|
+
const props = withDefaults(defineProps<FieldTextarea>(), {
|
|
5
|
+
autofocus: false,
|
|
6
|
+
background: 'gray',
|
|
7
|
+
border: true,
|
|
8
|
+
description: '',
|
|
9
|
+
disabled: false,
|
|
10
|
+
fullWidth: true,
|
|
11
|
+
hideError: false,
|
|
12
|
+
label: '',
|
|
13
|
+
labelIcon: undefined,
|
|
14
|
+
loading: false,
|
|
15
|
+
modelValue: '',
|
|
16
|
+
padding: true,
|
|
17
|
+
placeholder: '',
|
|
18
|
+
required: false,
|
|
19
|
+
resize: false,
|
|
20
|
+
rows: 3,
|
|
21
|
+
size: 'base',
|
|
22
|
+
validation: undefined,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const emit = defineEmits<{
|
|
26
|
+
'blur': [event: FocusEvent, value: string]
|
|
27
|
+
'click': [event: MouseEvent, value: string]
|
|
28
|
+
'update:modelValue': [value: string]
|
|
29
|
+
}>()
|
|
30
|
+
|
|
31
|
+
const textarea = ref<HTMLTextAreaElement>()
|
|
32
|
+
const uuid = ref(`${Math.floor((1 + Math.random()) * 0x100000)}`)
|
|
33
|
+
|
|
34
|
+
const { isDesktopBrowser } = useDevice()
|
|
35
|
+
|
|
36
|
+
const value = computed({
|
|
37
|
+
get() {
|
|
38
|
+
return `${props.modelValue}`
|
|
39
|
+
},
|
|
40
|
+
set(value) {
|
|
41
|
+
emit('update:modelValue', value)
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
onMounted(() => {
|
|
46
|
+
if (props.autofocus && textarea.value && isDesktopBrowser.value) {
|
|
47
|
+
textarea.value.focus()
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
function onFieldBlur(event: FocusEvent) {
|
|
52
|
+
const value = textarea.value?.value || ''
|
|
53
|
+
|
|
54
|
+
emit('blur', event, value)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function onFieldClick(event: MouseEvent) {
|
|
58
|
+
const value = textarea.value?.value || ''
|
|
59
|
+
|
|
60
|
+
emit('click', event, value)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function onFieldInput() {
|
|
64
|
+
const value = textarea.value?.value || ''
|
|
65
|
+
|
|
66
|
+
emit('update:modelValue', value)
|
|
67
|
+
}
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<template>
|
|
71
|
+
<div
|
|
72
|
+
class="relative flex flex-col"
|
|
73
|
+
:class="{ 'w-full': fullWidth }"
|
|
74
|
+
>
|
|
75
|
+
<FieldLabel
|
|
76
|
+
v-if="label"
|
|
77
|
+
:disabled="disabled"
|
|
78
|
+
:for-field="uuid"
|
|
79
|
+
has-margin-bottom
|
|
80
|
+
:icon="labelIcon"
|
|
81
|
+
:label="label"
|
|
82
|
+
:required="required"
|
|
83
|
+
:size="size"
|
|
84
|
+
/>
|
|
85
|
+
|
|
86
|
+
<textarea
|
|
87
|
+
:id="uuid"
|
|
88
|
+
ref="textarea"
|
|
89
|
+
v-model="value"
|
|
90
|
+
class="w-full flex-1 appearance-none rounded-lg text-gray-900 font-medium tracking-tight uppercase outline-none dark:text-gray-100 placeholder-gray-600 dark:placeholder-gray-400 focus:placeholder-gray-900 hover:placeholder-gray-900 dark:focus:placeholder-gray-100 dark:hover:placeholder-gray-100"
|
|
91
|
+
:class="{
|
|
92
|
+
'p-2.5': padding,
|
|
93
|
+
'p-0': !padding,
|
|
94
|
+
'resize-none': !resize,
|
|
95
|
+
|
|
96
|
+
'bg-gray-100 dark:bg-gray-900': background === 'gray',
|
|
97
|
+
'bg-white dark:bg-gray-900': background === 'white',
|
|
98
|
+
|
|
99
|
+
'border shadow-sm border-gray-200 dark:border-gray-800 hover:border-gray-300 dark:hover:border-gray-700 focus:border-gray-400 dark:focus:border-gray-600': border,
|
|
100
|
+
'border-0': !border,
|
|
101
|
+
|
|
102
|
+
'text-xs': size === 'xs',
|
|
103
|
+
'text-sm': size === 'sm',
|
|
104
|
+
'text-base': size === 'base',
|
|
105
|
+
'text-lg': size === 'lg',
|
|
106
|
+
}"
|
|
107
|
+
data-enable-grammarly="false"
|
|
108
|
+
:placeholder="placeholder"
|
|
109
|
+
:rows="rows"
|
|
110
|
+
spellcheck="false"
|
|
111
|
+
@blur="onFieldBlur"
|
|
112
|
+
@click="onFieldClick"
|
|
113
|
+
@input="onFieldInput"
|
|
114
|
+
/>
|
|
115
|
+
|
|
116
|
+
<FieldMessage
|
|
117
|
+
:description="description"
|
|
118
|
+
:hide-error="hideError"
|
|
119
|
+
:size="size"
|
|
120
|
+
:validation="validation"
|
|
121
|
+
/>
|
|
122
|
+
</div>
|
|
123
|
+
</template>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import type { FieldTime } from '../../types/fields'
|
|
3
|
+
|
|
4
|
+
const props = withDefaults(defineProps<FieldTime>(), {
|
|
5
|
+
background: 'gray',
|
|
6
|
+
description: '',
|
|
7
|
+
disabled: false,
|
|
8
|
+
hideError: true,
|
|
9
|
+
icon: undefined,
|
|
10
|
+
id: undefined,
|
|
11
|
+
label: '',
|
|
12
|
+
labelIcon: undefined,
|
|
13
|
+
modelValue: '',
|
|
14
|
+
name: undefined,
|
|
15
|
+
required: false,
|
|
16
|
+
size: 'base',
|
|
17
|
+
validation: undefined,
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const emit = defineEmits<{
|
|
21
|
+
'blur': [event: FocusEvent, value: string, name?: string]
|
|
22
|
+
'update:modelValue': [value: string, name?: string]
|
|
23
|
+
}>()
|
|
24
|
+
|
|
25
|
+
const root = ref<HTMLDivElement>()
|
|
26
|
+
const uuid = ref(`${Math.floor((1 + Math.random()) * 0x100000)}`)
|
|
27
|
+
|
|
28
|
+
function onFieldBlur(event: FocusEvent) {
|
|
29
|
+
emit('blur', event, props.modelValue, props.name)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function onFieldInput() {
|
|
33
|
+
const value = root.value?.querySelector('input')?.value || ''
|
|
34
|
+
|
|
35
|
+
emit('update:modelValue', value, props.name)
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<div ref="root">
|
|
41
|
+
<FieldLabel
|
|
42
|
+
v-if="label"
|
|
43
|
+
:disabled="disabled"
|
|
44
|
+
:for-field="uuid"
|
|
45
|
+
has-margin-bottom
|
|
46
|
+
:icon="labelIcon"
|
|
47
|
+
:label="label"
|
|
48
|
+
:required="required"
|
|
49
|
+
:size="size"
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
<div class="item-center h-[42px] flex overflow-hidden border border-gray-200 rounded-lg pl-3 pr-2 dark:border-gray-800 focus-within:border-gray-400 hover:border-gray-300 dark:focus-within:border-gray-600 dark:hover:border-gray-700">
|
|
53
|
+
<input
|
|
54
|
+
:id="`${id}`"
|
|
55
|
+
class="text-sm outline-none"
|
|
56
|
+
:class="{
|
|
57
|
+
'bg-gray-100 dark:bg-gray-900': background === 'gray',
|
|
58
|
+
'bg-white dark:bg-gray-900': background === 'white',
|
|
59
|
+
}"
|
|
60
|
+
type="time"
|
|
61
|
+
@blur="onFieldBlur"
|
|
62
|
+
@input="onFieldInput"
|
|
63
|
+
>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<FieldMessage
|
|
67
|
+
:description="description"
|
|
68
|
+
:hide-error="hideError"
|
|
69
|
+
:size="size"
|
|
70
|
+
:validation="validation"
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
</template>
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import numbroLib from 'numbro'
|
|
2
2
|
|
|
3
|
+
export function normalizeText(text: string) {
|
|
4
|
+
return text
|
|
5
|
+
.toLowerCase()
|
|
6
|
+
.normalize('NFD')
|
|
7
|
+
.replace(/[\u0300-\u036F]/g, '')
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
export function numbro(number: '∞' | number | undefined, format?: string) {
|
|
4
11
|
if (!number && number !== 0) {
|
|
5
12
|
return ''
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
export type FieldBackground = 'gray' | 'white'
|
|
2
|
+
|
|
3
|
+
export type FieldSize = 'base' | 'lg' | 'sm' | 'xs'
|
|
4
|
+
|
|
5
|
+
export type FieldStatus = 'default' | 'error' | 'info' | 'success' | 'warning'
|
|
6
|
+
|
|
7
|
+
export interface FieldCheckbox {
|
|
8
|
+
description?: BaseTextText
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
fullWidth?: boolean
|
|
11
|
+
hideError?: boolean
|
|
12
|
+
label?: BaseTextText
|
|
13
|
+
labelIcon?: BaseIconValue
|
|
14
|
+
lineThrough?: boolean
|
|
15
|
+
loading?: boolean
|
|
16
|
+
modelValue?: boolean
|
|
17
|
+
required?: boolean
|
|
18
|
+
size?: FieldSize
|
|
19
|
+
truncate?: boolean
|
|
20
|
+
uppercase?: boolean
|
|
21
|
+
validation?: VuelidateValidation
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface FieldDays {
|
|
25
|
+
modelValue?: number[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface FieldEmojis {
|
|
29
|
+
modelValue?: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface FieldInput {
|
|
33
|
+
alignment?: FieldInputAlignment
|
|
34
|
+
autocomplete?: boolean
|
|
35
|
+
autofocus?: boolean
|
|
36
|
+
background?: FieldBackground
|
|
37
|
+
border?: FieldInputBorder
|
|
38
|
+
description?: BaseTextText
|
|
39
|
+
disabled?: boolean
|
|
40
|
+
fullWidth?: boolean
|
|
41
|
+
hideError?: boolean
|
|
42
|
+
label?: BaseTextText
|
|
43
|
+
labelIcon?: BaseIconValue
|
|
44
|
+
lineThrough?: boolean
|
|
45
|
+
loading?: boolean
|
|
46
|
+
lowercaseOnly?: boolean
|
|
47
|
+
max?: number
|
|
48
|
+
min?: number
|
|
49
|
+
modelValue?: number | string
|
|
50
|
+
placeholder?: string
|
|
51
|
+
required?: boolean
|
|
52
|
+
size?: FieldSize
|
|
53
|
+
type?: FieldInputType
|
|
54
|
+
uppercase?: boolean
|
|
55
|
+
validation?: VuelidateValidation
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type FieldInputAlignment = 'center' | 'left' | 'right'
|
|
59
|
+
|
|
60
|
+
export type FieldInputBorder = 'bottom' | 'full' | 'none'
|
|
61
|
+
|
|
62
|
+
export type FieldInputType = 'currency' | 'date' | 'datetime-local' | 'email' | 'month' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'time' | 'url' | 'week'
|
|
63
|
+
|
|
64
|
+
export interface FieldLabel {
|
|
65
|
+
disabled?: boolean
|
|
66
|
+
forField?: string
|
|
67
|
+
hasMarginBottom?: boolean
|
|
68
|
+
hasMarginLeft?: boolean
|
|
69
|
+
icon?: BaseIconValue
|
|
70
|
+
label: BaseTextText
|
|
71
|
+
lineThrough?: boolean
|
|
72
|
+
loading?: boolean
|
|
73
|
+
required?: boolean
|
|
74
|
+
size?: FieldSize
|
|
75
|
+
truncate?: boolean
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface FieldMessage {
|
|
79
|
+
description?: BaseTextText
|
|
80
|
+
hideError?: boolean
|
|
81
|
+
size?: FieldSize
|
|
82
|
+
validation?: VuelidateValidation
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface FieldSelect {
|
|
86
|
+
border?: FieldSelectBorder
|
|
87
|
+
caret?: boolean
|
|
88
|
+
columns?: FieldSelectColumn[]
|
|
89
|
+
description?: BaseTextText
|
|
90
|
+
direction?: FieldSelectDirection
|
|
91
|
+
disabled?: boolean
|
|
92
|
+
hideError?: boolean
|
|
93
|
+
label?: BaseTextText
|
|
94
|
+
labelIcon?: BaseIconValue
|
|
95
|
+
maxHeight?: FieldSelectMaxHeight
|
|
96
|
+
modelValue?: number | string
|
|
97
|
+
openOnHover?: boolean
|
|
98
|
+
options?: FieldSelectOption[]
|
|
99
|
+
padding?: boolean
|
|
100
|
+
placeholder?: string
|
|
101
|
+
required?: boolean
|
|
102
|
+
size?: FieldSize
|
|
103
|
+
validation?: VuelidateValidation
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface FieldSelectColumn {
|
|
107
|
+
options: FieldSelectOption[]
|
|
108
|
+
title?: string
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface FieldSelectOption {
|
|
112
|
+
icon?: BaseIconValue
|
|
113
|
+
text: string
|
|
114
|
+
value: number | string
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export type FieldSelectBorder = 'bottom' | 'full' | 'none'
|
|
118
|
+
|
|
119
|
+
export type FieldSelectDirection = 'bottom' | 'top'
|
|
120
|
+
|
|
121
|
+
export type FieldSelectMaxHeight = 'lg' | 'md' | 'sm' | 'xs'
|
|
122
|
+
|
|
123
|
+
export interface FieldTabs {
|
|
124
|
+
minimizeOnMobile?: boolean
|
|
125
|
+
modelValue?: Array<number | string> | number | string
|
|
126
|
+
multiple?: boolean
|
|
127
|
+
size?: FieldSize
|
|
128
|
+
tabs: FieldTabsTab[]
|
|
129
|
+
theme?: FieldTabsTheme
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface FieldTabsTab {
|
|
133
|
+
activeColor?: BaseColor
|
|
134
|
+
icon?: BaseIconValue
|
|
135
|
+
label: string
|
|
136
|
+
to?: RouteLocationNamedI18n
|
|
137
|
+
value: number | string
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export type FieldTabsAction = 'added' | 'removed'
|
|
141
|
+
|
|
142
|
+
export type FieldTabsTheme = 'border' | 'rounded'
|
|
143
|
+
|
|
144
|
+
export interface FieldTextarea {
|
|
145
|
+
autofocus?: boolean
|
|
146
|
+
background?: FieldBackground
|
|
147
|
+
border?: boolean
|
|
148
|
+
description?: BaseTextText
|
|
149
|
+
disabled?: boolean
|
|
150
|
+
fullWidth?: boolean
|
|
151
|
+
hideError?: boolean
|
|
152
|
+
label?: BaseTextText
|
|
153
|
+
labelIcon?: BaseIconValue
|
|
154
|
+
loading?: boolean
|
|
155
|
+
modelValue?: string
|
|
156
|
+
padding?: boolean
|
|
157
|
+
placeholder?: string
|
|
158
|
+
required?: boolean
|
|
159
|
+
resize?: boolean
|
|
160
|
+
rows?: number
|
|
161
|
+
size?: FieldSize
|
|
162
|
+
validation?: VuelidateValidation
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface FieldTime {
|
|
166
|
+
background?: FieldBackground
|
|
167
|
+
description?: BaseTextText
|
|
168
|
+
disabled?: boolean
|
|
169
|
+
hideError?: boolean
|
|
170
|
+
icon?: BaseIconValue
|
|
171
|
+
id: number | string
|
|
172
|
+
label?: BaseTextText
|
|
173
|
+
labelIcon?: BaseIconValue
|
|
174
|
+
modelValue?: string
|
|
175
|
+
name?: string
|
|
176
|
+
required?: boolean
|
|
177
|
+
size?: FieldSize
|
|
178
|
+
validation?: VuelidateValidation
|
|
179
|
+
}
|
package/app/types/global.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ declare global {
|
|
|
7
7
|
type ChartistOptions = import('chartist').Options
|
|
8
8
|
type ChartistPieChartData = import('chartist').PieChartData
|
|
9
9
|
type RouteLocationNamedI18n = import('vue-router').RouteLocationNamedI18n
|
|
10
|
+
type VuelidateValidation = import('@vuelidate/core').BaseValidation
|
|
10
11
|
|
|
11
12
|
// Bases
|
|
12
13
|
type BaseAlert = Bases.BaseAlert
|
|
@@ -55,6 +56,15 @@ declare global {
|
|
|
55
56
|
type BaseToast = Bases.BaseToast
|
|
56
57
|
type BaseToasts = Bases.BaseToasts
|
|
57
58
|
type BaseToastsAlignment = Bases.BaseToastsAlignment
|
|
59
|
+
|
|
60
|
+
// Navigator
|
|
61
|
+
interface Navigator {
|
|
62
|
+
userAgentData?: {
|
|
63
|
+
brands?: Array<{ brand: string, version: string }>
|
|
64
|
+
mobile?: boolean
|
|
65
|
+
platform?: string
|
|
66
|
+
}
|
|
67
|
+
}
|
|
58
68
|
}
|
|
59
69
|
|
|
60
70
|
export * from './bases'
|
package/nuxt.config.ts
CHANGED
|
@@ -21,6 +21,10 @@ export default defineNuxtConfig({
|
|
|
21
21
|
path: 'components/bases',
|
|
22
22
|
pathPrefix: false,
|
|
23
23
|
},
|
|
24
|
+
{
|
|
25
|
+
path: 'components/fields',
|
|
26
|
+
pathPrefix: false,
|
|
27
|
+
},
|
|
24
28
|
{
|
|
25
29
|
path: 'components/layout',
|
|
26
30
|
pathPrefix: false,
|
|
@@ -35,14 +39,15 @@ export default defineNuxtConfig({
|
|
|
35
39
|
],
|
|
36
40
|
|
|
37
41
|
modules: [
|
|
42
|
+
'@nuxt/icon',
|
|
38
43
|
'@nuxtjs/color-mode',
|
|
39
44
|
'@nuxtjs/i18n',
|
|
40
|
-
'@nuxt/icon',
|
|
41
|
-
'@pinia/nuxt',
|
|
42
|
-
'@unocss/nuxt',
|
|
43
45
|
'@nuxtjs/plausible',
|
|
44
46
|
'@nuxtjs/robots',
|
|
45
47
|
'@nuxtjs/sitemap',
|
|
48
|
+
'@pinia/nuxt',
|
|
49
|
+
'@unocss/nuxt',
|
|
50
|
+
'@vueuse/nuxt',
|
|
46
51
|
'floating-vue/nuxt',
|
|
47
52
|
'motion-v/nuxt',
|
|
48
53
|
],
|
|
@@ -75,7 +80,6 @@ export default defineNuxtConfig({
|
|
|
75
80
|
plausible: {
|
|
76
81
|
apiHost: 'https://plausible.saasmakers.dev',
|
|
77
82
|
autoOutboundTracking: true,
|
|
78
|
-
domain: 'resilience.club',
|
|
79
83
|
ignoreSubDomains: true,
|
|
80
84
|
proxy: true,
|
|
81
85
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saasmakers/ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.61",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Reusable Nuxt UI components for SaaS Makers projects",
|
|
7
7
|
"license": "MIT",
|
|
@@ -39,8 +39,14 @@
|
|
|
39
39
|
"@nuxtjs/robots": "5.5.6",
|
|
40
40
|
"@nuxtjs/sitemap": "7.4.7",
|
|
41
41
|
"@pinia/nuxt": "0.11.2",
|
|
42
|
+
"@saasmakers/shared": "workspace:*",
|
|
42
43
|
"@unocss/nuxt": "66.5.4",
|
|
43
44
|
"@unocss/reset": "66.5.10",
|
|
45
|
+
"@vuelidate/core": "2.0.3",
|
|
46
|
+
"@vuelidate/validators": "2.0.4",
|
|
47
|
+
"@vueuse/components": "14.0.0",
|
|
48
|
+
"@vueuse/core": "14.1.0",
|
|
49
|
+
"@vueuse/nuxt": "14.0.0",
|
|
44
50
|
"chartist": "1.5.0",
|
|
45
51
|
"floating-vue": "5.2.2",
|
|
46
52
|
"lottie-web": "5.13.0",
|