@visualizevalue/mint-app-base 0.0.1 → 0.0.4
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/.env.example +3 -0
- package/app/assets/styles/index.css +1 -0
- package/app/assets/styles/theme.css +4 -0
- package/app/assets/styles/variables.css +15 -17
- package/app/components/Collection/Intro.vue +2 -2
- package/app/components/Collection/OverviewCard.vue +3 -2
- package/app/components/Image.client.vue +2 -3
- package/app/components/Token/Detail.client.vue +7 -15
- package/app/components/Token/OverviewCard.vue +7 -8
- package/app/composables/priceFeed.ts +4 -4
- package/app/pages/[id]/[collection]/mint.vue +69 -62
- package/app/plugins/2.wagmi.ts +11 -7
- package/nuxt.config.ts +3 -0
- package/package.json +3 -3
package/.env.example
CHANGED
|
@@ -18,6 +18,9 @@ NUXT_PUBLIC_CREATOR_ADDRESS=0xc8f8e2F59Dd95fF67c3d39109ecA2e2A017D4c8a
|
|
|
18
18
|
# =========================
|
|
19
19
|
NUXT_PUBLIC_BLOCK_EXPLORER=https://etherscan.io
|
|
20
20
|
NUXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=
|
|
21
|
+
NUXT_PUBLIC_RPC1=
|
|
22
|
+
NUXT_PUBLIC_RPC2=
|
|
23
|
+
NUXT_PUBLIC_RPC3=
|
|
21
24
|
|
|
22
25
|
# =========================
|
|
23
26
|
# ONCHAIN
|
|
@@ -30,25 +30,25 @@
|
|
|
30
30
|
--black-semi: rgba(0, 0, 0, 0.7);
|
|
31
31
|
|
|
32
32
|
/* COLORS */
|
|
33
|
-
--red:
|
|
33
|
+
--red: #EF4444;
|
|
34
34
|
--green: #94E337;
|
|
35
35
|
|
|
36
36
|
/* PRESET COLORS */
|
|
37
|
-
--error:
|
|
37
|
+
--error: var(--red);
|
|
38
38
|
--success: var(--green);
|
|
39
39
|
|
|
40
40
|
/* SIZES */
|
|
41
|
-
--100vh:
|
|
42
|
-
--size-0:
|
|
43
|
-
--size-1:
|
|
44
|
-
--size-2:
|
|
45
|
-
--size-3:
|
|
46
|
-
--size-4:
|
|
47
|
-
--size-5:
|
|
48
|
-
--size-6:
|
|
49
|
-
--size-7:
|
|
50
|
-
--size-8:
|
|
51
|
-
--size-9:
|
|
41
|
+
--100vh: 100dvh;
|
|
42
|
+
--size-0: 0.125rem;
|
|
43
|
+
--size-1: 0.25rem;
|
|
44
|
+
--size-2: 0.5rem;
|
|
45
|
+
--size-3: 0.75rem;
|
|
46
|
+
--size-4: 1rem;
|
|
47
|
+
--size-5: 1.25rem;
|
|
48
|
+
--size-6: 1.5rem;
|
|
49
|
+
--size-7: 2rem;
|
|
50
|
+
--size-8: 3rem;
|
|
51
|
+
--size-9: 4.5rem;
|
|
52
52
|
--size-10: 6rem;
|
|
53
53
|
|
|
54
54
|
--spacer-xs: var(--size-0);
|
|
@@ -107,16 +107,13 @@
|
|
|
107
107
|
--border-color-dark: var(--gray-z-1);
|
|
108
108
|
--border: 1px solid var(--border-color);
|
|
109
109
|
--border-dark: 1px solid var(--border-color-dark);
|
|
110
|
+
--border-shadow: 0 0 0 1px var(--border-color);
|
|
110
111
|
|
|
111
112
|
/* SHADOWS */
|
|
112
113
|
--shadow:
|
|
113
114
|
0 var(--size-0) var(--size-2) var(--gray-z-1-semi),
|
|
114
115
|
0 var(--size-2) var(--size-7) calc(-1 * var(--size-5)) var(--gray-z-3-semi);
|
|
115
116
|
|
|
116
|
-
--shadow-xl:
|
|
117
|
-
0 var(--size-3) var(--size-8) var(--gray-z-3-semi),
|
|
118
|
-
0 var(--size-8) var(--size-6) calc(-1 * var(--size-8)) var(--gray-z-6-semi);
|
|
119
|
-
|
|
120
117
|
/* BACKGROUNDS */
|
|
121
118
|
--blur: blur(var(--size-1));
|
|
122
119
|
}
|
|
@@ -193,3 +190,4 @@
|
|
|
193
190
|
--font-sm: calc(var(--size-3) + var(--size-0));
|
|
194
191
|
}
|
|
195
192
|
}
|
|
193
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<header>
|
|
2
|
+
<header class="collection-intro">
|
|
3
3
|
<figure v-if="collection.image">
|
|
4
4
|
<Image :src="collection.image" :alt="collection.name" />
|
|
5
5
|
</figure>
|
|
@@ -49,7 +49,7 @@ const ownedByMe = useIsMeCheck(collection.owner)
|
|
|
49
49
|
</script>
|
|
50
50
|
|
|
51
51
|
<style scoped>
|
|
52
|
-
header {
|
|
52
|
+
header.collection-intro {
|
|
53
53
|
display: grid;
|
|
54
54
|
gap: var(--spacer);
|
|
55
55
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<article>
|
|
2
|
+
<article class="collection-overview-card">
|
|
3
3
|
<Image v-if="collection.image" :src="collection.image" :alt="collection.name" />
|
|
4
4
|
<div class="text">
|
|
5
5
|
<div>
|
|
@@ -27,11 +27,12 @@ const shortDescription = computed(() => shortString(collection.description, 40,
|
|
|
27
27
|
</script>
|
|
28
28
|
|
|
29
29
|
<style scoped>
|
|
30
|
-
article {
|
|
30
|
+
article.collection-overview-card {
|
|
31
31
|
display: grid;
|
|
32
32
|
padding: var(--spacer);
|
|
33
33
|
gap: var(--spacer);
|
|
34
34
|
transition: all var(--speed);
|
|
35
|
+
border: var(--card-border);
|
|
35
36
|
|
|
36
37
|
&:has(> a:--highlight) {
|
|
37
38
|
background: var(--gray-z-0);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<article class="token">
|
|
2
|
+
<article class="token-detail">
|
|
3
3
|
<div class="artifact">
|
|
4
|
-
<div
|
|
5
|
-
<Image :src="token.artifact" :alt="token.name"
|
|
4
|
+
<div>
|
|
5
|
+
<Image :src="token.artifact" :alt="token.name" />
|
|
6
6
|
</div>
|
|
7
7
|
</div>
|
|
8
8
|
|
|
@@ -64,18 +64,15 @@ const { token } = defineProps<{
|
|
|
64
64
|
token: Token
|
|
65
65
|
}>()
|
|
66
66
|
|
|
67
|
-
const breakpoints = useBreakpoints()
|
|
68
|
-
const shaded = computed(() => breakpoints.greater('sm').value && ! isDark.value)
|
|
69
|
-
|
|
70
67
|
const store = useOnchainStore()
|
|
71
68
|
const collection = computed(() => store.collection(token.collection))
|
|
72
69
|
|
|
73
70
|
const mintCount = ref('1')
|
|
74
|
-
const ownedBalance = computed(() => store.tokenBalance(collection.value.address, token.tokenId))
|
|
71
|
+
const ownedBalance = computed(() => collection.value && store.tokenBalance(collection.value.address, token.tokenId))
|
|
75
72
|
</script>
|
|
76
73
|
|
|
77
74
|
<style scoped>
|
|
78
|
-
.token {
|
|
75
|
+
.token-detail {
|
|
79
76
|
position: relative;
|
|
80
77
|
container-type: inline-size;
|
|
81
78
|
|
|
@@ -116,7 +113,7 @@ const ownedBalance = computed(() => store.tokenBalance(collection.value.address,
|
|
|
116
113
|
@media (--lg) {
|
|
117
114
|
--padding-top: var(--spacer-xl);
|
|
118
115
|
--padding-x: var(--spacer-xl);
|
|
119
|
-
--padding-bottom: calc(var(--spacer-xl) + var(--spacer
|
|
116
|
+
--padding-bottom: calc(var(--spacer-xl) + var(--spacer));
|
|
120
117
|
}
|
|
121
118
|
|
|
122
119
|
height: var(--height);
|
|
@@ -139,13 +136,8 @@ const ownedBalance = computed(() => store.tokenBalance(collection.value.address,
|
|
|
139
136
|
@media (--md) {
|
|
140
137
|
border-bottom: none !important;
|
|
141
138
|
}
|
|
142
|
-
|
|
143
|
-
&.shaded {
|
|
144
|
-
box-shadow: var(--shadow-xl);
|
|
145
|
-
transform: translateY(calc(-1 * var(--size-2))) scale(1.001);
|
|
146
|
-
}
|
|
147
139
|
}
|
|
148
|
-
|
|
140
|
+
}
|
|
149
141
|
|
|
150
142
|
.details {
|
|
151
143
|
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
transactionFlowConfig
|
|
13
13
|
}"
|
|
14
14
|
>
|
|
15
|
-
<article class="token">
|
|
15
|
+
<article class="token-overview-card">
|
|
16
16
|
<div class="content">
|
|
17
17
|
<header>
|
|
18
18
|
<h1>
|
|
19
19
|
<span>{{ token.name }} <span class="muted">#{{ token.tokenId }}</span></span>
|
|
20
|
-
<span v-if="token.description">{{ shortString(token.description,
|
|
20
|
+
<span v-if="token.description">{{ shortString(token.description, 60, 30) }}</span>
|
|
21
21
|
</h1>
|
|
22
22
|
<p v-if="mintOpen" class="muted">Closes in {{ blocksRemaining }} {{ pluralize('block', Number(blocksRemaining))}}</p>
|
|
23
23
|
<p v-else class="muted">Closed at block {{ token.untilBlock }}</p>
|
|
24
24
|
</header>
|
|
25
|
-
<Image :src="token.artifact" :alt="token.name" />
|
|
25
|
+
<Image :src="token.artifact" :alt="token.name" class="bordered" />
|
|
26
26
|
<CardLink :to="{
|
|
27
27
|
name: 'id-collection-tokenId',
|
|
28
28
|
params: { id: collection.owner, collection: token.collection, tokenId: `${token.tokenId}` }
|
|
@@ -60,17 +60,16 @@ const ownedBalance = computed(() => store.tokenBalance(collection.value.address,
|
|
|
60
60
|
</script>
|
|
61
61
|
|
|
62
62
|
<style scoped>
|
|
63
|
-
.token,
|
|
64
|
-
.token > .content {
|
|
63
|
+
.token-overview-card,
|
|
64
|
+
.token-overview-card > .content {
|
|
65
65
|
display: flex;
|
|
66
66
|
flex-direction: column;
|
|
67
67
|
justify-content: center;
|
|
68
68
|
gap: var(--spacer);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
.token {
|
|
71
|
+
.token-overview-card {
|
|
72
72
|
padding: var(--spacer-xl) var(--spacer) !important;
|
|
73
|
-
border: 0 !important;
|
|
74
73
|
|
|
75
74
|
/* Tokens should be at min the screen height. */
|
|
76
75
|
&:not(:first-of-type) {
|
|
@@ -88,7 +87,7 @@ const ownedBalance = computed(() => store.tokenBalance(collection.value.address,
|
|
|
88
87
|
}
|
|
89
88
|
}
|
|
90
89
|
|
|
91
|
-
.token > .content {
|
|
90
|
+
.token-overview-card > .content {
|
|
92
91
|
display: flex;
|
|
93
92
|
flex-direction: column;
|
|
94
93
|
justify-content: center;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readContract } from '@wagmi/core'
|
|
2
2
|
|
|
3
3
|
const CHAINLINK_PRICE_FEED_ABI = [
|
|
4
4
|
{
|
|
@@ -45,17 +45,17 @@ export const usePriceFeedStore = () => {
|
|
|
45
45
|
|
|
46
46
|
actions: {
|
|
47
47
|
async fetchEthUsdPrice () {
|
|
48
|
-
const client = getPublicClient($wagmi, { chainId: 1 })
|
|
49
48
|
|
|
50
49
|
if (nowInSeconds() - this.lastUpdated < 3_600) {
|
|
51
50
|
return this.ethUSD
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
try {
|
|
55
|
-
const [, answer] = await
|
|
54
|
+
const [, answer] = await readContract($wagmi, {
|
|
56
55
|
address: PRICE_FEED_ADDRESS,
|
|
57
56
|
abi: CHAINLINK_PRICE_FEED_ABI,
|
|
58
|
-
functionName: 'latestRoundData'
|
|
57
|
+
functionName: 'latestRoundData',
|
|
58
|
+
chainId: 1,
|
|
59
59
|
})
|
|
60
60
|
|
|
61
61
|
this.ethUSDRaw = answer
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<Authenticated>
|
|
3
3
|
<PageFrame :title="breadcrumb" class="inset wide" id="mint-token">
|
|
4
4
|
<article class="preview">
|
|
5
|
-
<Image v-if="image" :src="image" alt="Preview" />
|
|
5
|
+
<Image v-if="image" :src="image" alt="Preview" class="bordered" />
|
|
6
6
|
<VisualImagePreview v-else />
|
|
7
7
|
<h1 :class="{ 'muted-light': !name }">{{ name || 'Token' }}</h1>
|
|
8
8
|
<p :class="{ 'muted-light': !description }">
|
|
@@ -90,10 +90,11 @@ const isSmall = computed(() => imageSize.value / 1024 < 10)
|
|
|
90
90
|
const setImage = async (file) => {
|
|
91
91
|
try {
|
|
92
92
|
image.value = await imageFileToDataUri(file)
|
|
93
|
+
imageSize.value = file.size
|
|
93
94
|
} catch (e) {
|
|
94
95
|
image.value = ''
|
|
96
|
+
imageSize.value = 0
|
|
95
97
|
}
|
|
96
|
-
imageSize.value = file.size
|
|
97
98
|
}
|
|
98
99
|
watch(ipfsCid, () => {
|
|
99
100
|
const validated = validateCID(ipfsCid.value)
|
|
@@ -115,68 +116,72 @@ const mint = async () => {
|
|
|
115
116
|
|
|
116
117
|
minting.value = true
|
|
117
118
|
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
|
|
119
|
+
try {
|
|
120
|
+
if (multiTransactionPrepare) {
|
|
121
|
+
if (! confirm(`Due to the large artifact size, we have to split it into ${artifactChunks.length} chunks and store them in separate transactions. You will be prompted with multiple transaction requests before minting the final token.`)) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// On the first iteration we want to clear existing artifact data
|
|
126
|
+
let clearExisting = true
|
|
127
|
+
|
|
128
|
+
for (const chunk of artifactChunks) {
|
|
129
|
+
await txFlow.value.initializeRequest(() => writeContract($wagmi, {
|
|
130
|
+
abi: MINT_ABI,
|
|
131
|
+
chainId,
|
|
132
|
+
address: collection.value.address,
|
|
133
|
+
functionName: 'prepareArtifact',
|
|
134
|
+
args: [
|
|
135
|
+
collection.value.latestTokenId + 1n,
|
|
136
|
+
chunk,
|
|
137
|
+
clearExisting
|
|
138
|
+
],
|
|
139
|
+
}))
|
|
140
|
+
|
|
141
|
+
// Make sure to rerender the tx flow component
|
|
142
|
+
txFlowKey.value ++
|
|
143
|
+
|
|
144
|
+
// On following iterations we want to keep existing artifact data
|
|
145
|
+
clearExisting = false
|
|
146
|
+
}
|
|
121
147
|
}
|
|
122
148
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
const receipt = await txFlow.value.initializeRequest(() => writeContract($wagmi, {
|
|
150
|
+
abi: MINT_ABI,
|
|
151
|
+
chainId,
|
|
152
|
+
address: collection.value.address,
|
|
153
|
+
functionName: 'create',
|
|
154
|
+
args: [
|
|
155
|
+
name.value,
|
|
156
|
+
description.value,
|
|
157
|
+
multiTransactionPrepare ? [] : artifact,
|
|
158
|
+
0,
|
|
159
|
+
0n,
|
|
160
|
+
],
|
|
161
|
+
}))
|
|
162
|
+
|
|
163
|
+
const logs = receipt.logs.map(log => decodeEventLog({
|
|
164
|
+
abi: MINT_ABI,
|
|
165
|
+
data: log.data,
|
|
166
|
+
topics: log.topics,
|
|
167
|
+
strict: false,
|
|
168
|
+
}))
|
|
169
|
+
|
|
170
|
+
const mintedEvent = logs.find(log => log.eventName === 'TransferSingle')
|
|
171
|
+
|
|
172
|
+
await store.fetchToken(collection.value.address, mintedEvent.args.id)
|
|
173
|
+
|
|
174
|
+
// Force update the collection mint ID
|
|
175
|
+
store.collections[collection.value.address].latestTokenId = mintedEvent.args.id
|
|
176
|
+
|
|
177
|
+
await navigateTo({
|
|
178
|
+
name: 'id-collection-tokenId',
|
|
179
|
+
params: { id: id.value, collection: collection.value.address, tokenId: mintedEvent.args.id }
|
|
180
|
+
})
|
|
181
|
+
} catch (e) {
|
|
182
|
+
console.error(e)
|
|
145
183
|
}
|
|
146
184
|
|
|
147
|
-
const receipt = await txFlow.value.initializeRequest(() => writeContract($wagmi, {
|
|
148
|
-
abi: MINT_ABI,
|
|
149
|
-
chainId,
|
|
150
|
-
address: collection.value.address,
|
|
151
|
-
functionName: 'create',
|
|
152
|
-
args: [
|
|
153
|
-
name.value,
|
|
154
|
-
description.value,
|
|
155
|
-
multiTransactionPrepare ? [] : artifact,
|
|
156
|
-
0,
|
|
157
|
-
0n,
|
|
158
|
-
],
|
|
159
|
-
}))
|
|
160
|
-
|
|
161
|
-
const logs = receipt.logs.map(log => decodeEventLog({
|
|
162
|
-
abi: MINT_ABI,
|
|
163
|
-
data: log.data,
|
|
164
|
-
topics: log.topics,
|
|
165
|
-
strict: false,
|
|
166
|
-
}))
|
|
167
|
-
|
|
168
|
-
const mintedEvent = logs.find(log => log.eventName === 'TransferSingle')
|
|
169
|
-
|
|
170
|
-
await store.fetchToken(collection.value.address, mintedEvent.args.id)
|
|
171
|
-
|
|
172
|
-
// Force update the collection mint ID
|
|
173
|
-
store.collections[collection.value.address].latestTokenId = mintedEvent.args.id
|
|
174
|
-
|
|
175
|
-
await navigateTo({
|
|
176
|
-
name: 'id-collection-tokenId',
|
|
177
|
-
params: { id: id.value, collection: collection.value.address, tokenId: mintedEvent.args.id }
|
|
178
|
-
})
|
|
179
|
-
|
|
180
185
|
minting.value = false
|
|
181
186
|
}
|
|
182
187
|
|
|
@@ -227,12 +232,14 @@ useMetaData({
|
|
|
227
232
|
|
|
228
233
|
.image,
|
|
229
234
|
svg {
|
|
230
|
-
border-radius: var(--border-radius);
|
|
231
|
-
border: var(--border);
|
|
232
235
|
margin-bottom: var(--spacer-sm);
|
|
233
236
|
width: 100%;
|
|
234
237
|
}
|
|
235
238
|
|
|
239
|
+
svg {
|
|
240
|
+
box-shadow: var(--border-shadow);
|
|
241
|
+
}
|
|
242
|
+
|
|
236
243
|
h1 {
|
|
237
244
|
display: flex;
|
|
238
245
|
gap: var(--spacer-sm);
|
package/app/plugins/2.wagmi.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
// import { custom, fallback } from 'viem'
|
|
2
2
|
import { VueQueryPlugin } from '@tanstack/vue-query'
|
|
3
|
-
import { http, cookieStorage, createConfig, createStorage, WagmiPlugin } from '@wagmi/vue'
|
|
3
|
+
import { http, cookieStorage, createConfig, createStorage, WagmiPlugin, fallback, custom } from '@wagmi/vue'
|
|
4
4
|
import { mainnet, sepolia, holesky, localhost } from '@wagmi/vue/chains'
|
|
5
5
|
import { coinbaseWallet, injected, metaMask, walletConnect } from '@wagmi/vue/connectors'
|
|
6
|
-
|
|
7
|
-
// const isBrowser = typeof window !== 'undefined' && window !== null
|
|
8
|
-
// const transports = isBrowser && window.ethereum
|
|
9
|
-
// ? fallback([ custom(window.ethereum!), http() ])
|
|
10
|
-
// : http()
|
|
11
|
-
const transports = http()
|
|
6
|
+
import type { CustomTransport, Transport } from 'viem'
|
|
12
7
|
|
|
13
8
|
export default defineNuxtPlugin(nuxtApp => {
|
|
14
9
|
const title = nuxtApp.$config.public.title || 'Mint'
|
|
15
10
|
|
|
11
|
+
const transportDefinitions: CustomTransport|Transport[] = []
|
|
12
|
+
|
|
13
|
+
if (nuxtApp.$config.public.rpc1) transportDefinitions.push(http(nuxtApp.$config.public.rpc1 as string))
|
|
14
|
+
if (nuxtApp.$config.public.rpc2) transportDefinitions.push(http(nuxtApp.$config.public.rpc2 as string))
|
|
15
|
+
if (nuxtApp.$config.public.rpc3) transportDefinitions.push(http(nuxtApp.$config.public.rpc3 as string))
|
|
16
|
+
transportDefinitions.push(http())
|
|
17
|
+
|
|
18
|
+
const transports = fallback(transportDefinitions)
|
|
19
|
+
|
|
16
20
|
const wagmiConfig = createConfig({
|
|
17
21
|
chains: [mainnet, sepolia, holesky, localhost],
|
|
18
22
|
batch: {
|
package/nuxt.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visualizevalue/mint-app-base",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./nuxt.config.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
"@tanstack/vue-query": ">=5.45.0",
|
|
11
11
|
"@visualizevalue/mint-utils": "npm:@visualizevalue/mint-utils@^0.0.1",
|
|
12
12
|
"@vueuse/components": "^10.11.0",
|
|
13
|
+
"@vueuse/core": "^11.0.3",
|
|
14
|
+
"@vueuse/nuxt": "^11.0.3",
|
|
13
15
|
"@wagmi/vue": "^0.0.40",
|
|
14
16
|
"buffer": "^6.0.3",
|
|
15
17
|
"eventemitter3": "^5.0.1",
|
|
@@ -27,8 +29,6 @@
|
|
|
27
29
|
"devDependencies": {
|
|
28
30
|
"@types/node": "^22.5.4",
|
|
29
31
|
"@vue/devtools-api": "^6.6.3",
|
|
30
|
-
"@vueuse/core": "^11.0.3",
|
|
31
|
-
"@vueuse/nuxt": "^11.0.3",
|
|
32
32
|
"eventemitter3": "^5.0.1",
|
|
33
33
|
"nuxt": "latest",
|
|
34
34
|
"typescript": "^5.5.4",
|