@meddleware/walrus-ui 0.1.1 → 0.1.2

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 (3) hide show
  1. package/package.json +6 -5
  2. package/src/App.vue +108 -92
  3. package/src/main.ts +1 -0
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@meddleware/walrus-ui",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Standalone Vue 3 SPA for uploading blobs to Walrus decentralised storage and managing owned blobs — wallet-connected, NFT-gated relay support.",
5
- "author": "MeddleWare <meddleware@proton.me>",
5
+ "author": "Meddleware <dev@meddleware.co.uk>",
6
6
  "license": "0BSD",
7
7
  "repository": {
8
8
  "type": "git",
@@ -29,10 +29,11 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@meddleware/design-tokens": "^0.1.0",
32
+ "@meddleware/design-tokens": "^0.1.2",
33
33
  "@meddleware/nft-gate-client": "^0.0.3",
34
- "@meddleware/walrus-client": "^0.0.2",
35
- "@meddleware/walrus-relay": "^0.1.0",
34
+ "@meddleware/ui": "^0.1.6",
35
+ "@meddleware/walrus-client": "^0.0.3",
36
+ "@meddleware/walrus-relay": "^0.1.1",
36
37
  "@mysten/sui": "~2.17.0",
37
38
  "@mysten/wallet-standard": "~0.19.9",
38
39
  "@mysten/walrus": "~1.1.7",
package/src/App.vue CHANGED
@@ -10,11 +10,15 @@ import {
10
10
  import type { UploadResult } from '@meddleware/walrus-relay'
11
11
  // Lightweight URL import — just the wasm asset URL (does not pull the walrus client).
12
12
  import walrusWasmUrl from '@mysten/walrus-wasm/web/walrus_wasm_bg.wasm?url'
13
+ import { AppHeader, AppFooter, ColorModeControl, useColorMode } from '@meddleware/ui'
13
14
  import { useWallet, getSuiClient } from './wallet.js'
14
15
  import { NETWORK, OPERATOR_RELAY_HOSTS, relayHosts, accessGate, uploadRelayMaxTipMist } from './config.js'
15
16
  import { runBlobUpload } from './upload-flow.js'
16
17
  import MyBlobs from './components/MyBlobs.vue'
17
18
 
19
+ const isEmbedded = new URLSearchParams(window.location.search).has('embedded')
20
+ const { mode, set } = useColorMode('dark')
21
+
18
22
  type Tab = 'upload' | 'blobs'
19
23
  const activeTab = ref<Tab>('upload')
20
24
 
@@ -85,133 +89,149 @@ function onUploaded(r: UploadResult): void {
85
89
  </script>
86
90
 
87
91
  <template>
88
- <div class="page">
89
- <header class="head">
90
- <div>
91
- <h1>Walrus Assets</h1>
92
- <p class="sub">Upload and manage blobs on Walrus decentralised storage ({{ NETWORK }}).</p>
93
- </div>
94
- <TipConfigBadge :host="OPERATOR_RELAY_HOSTS[NETWORK]" />
95
- </header>
96
-
97
- <nav class="tabs" aria-label="Feature tabs">
98
- <button
99
- type="button"
100
- class="tab"
101
- :class="{ active: activeTab === 'upload' }"
102
- @click="activeTab = 'upload'"
103
- >
104
- Upload
105
- </button>
106
- <button
107
- type="button"
108
- class="tab"
109
- :class="{ active: activeTab === 'blobs' }"
110
- @click="activeTab = 'blobs'"
111
- >
112
- My Blobs
113
- </button>
114
- </nav>
115
-
116
- <section class="wallet">
117
- <template v-if="account">
118
- <span class="addr">{{ account.address.slice(0, 8) }}…{{ account.address.slice(-4) }}</span>
119
- <button type="button" @click="disconnect">Disconnect</button>
92
+ <div class="app" :class="{ 'app--embedded': isEmbedded }">
93
+ <AppHeader v-if="!isEmbedded" variant="dark">
94
+ <template #brand>
95
+ <span>Walrus Assets</span>
96
+ </template>
97
+ <template #actions>
98
+ <TipConfigBadge :host="OPERATOR_RELAY_HOSTS[NETWORK]" />
99
+ <ColorModeControl :model-value="mode" @update:model-value="set" />
120
100
  </template>
121
- <template v-else>
122
- <button type="button" :disabled="!wallets.length" @click="onConnectFirst">
123
- {{ wallets.length ? 'Connect wallet' : 'No wallet detected' }}
101
+ </AppHeader>
102
+
103
+ <div class="page">
104
+ <p class="sub">Upload and manage blobs on Walrus decentralised storage ({{ NETWORK }}).</p>
105
+
106
+ <nav class="tabs" aria-label="Feature tabs">
107
+ <button
108
+ type="button"
109
+ class="tab"
110
+ :class="{ active: activeTab === 'upload' }"
111
+ @click="activeTab = 'upload'"
112
+ >
113
+ Upload
124
114
  </button>
115
+ <button
116
+ type="button"
117
+ class="tab"
118
+ :class="{ active: activeTab === 'blobs' }"
119
+ @click="activeTab = 'blobs'"
120
+ >
121
+ My Blobs
122
+ </button>
123
+ </nav>
124
+
125
+ <section class="wallet">
126
+ <template v-if="account">
127
+ <span class="addr">{{ account.address.slice(0, 8) }}…{{ account.address.slice(-4) }}</span>
128
+ <button type="button" @click="disconnect">Disconnect</button>
129
+ </template>
130
+ <template v-else>
131
+ <button type="button" :disabled="!wallets.length" @click="onConnectFirst">
132
+ {{ wallets.length ? 'Connect wallet' : 'No wallet detected' }}
133
+ </button>
134
+ </template>
135
+ </section>
136
+
137
+ <template v-if="activeTab === 'upload'">
138
+ <AccessGateCta
139
+ :gate-configured="gateState.gateConfigured"
140
+ :has-access="gateState.hasAccess.value"
141
+ :busy="purchasing"
142
+ :price-mist="gate?.priceMist ?? null"
143
+ @purchase="onPurchase"
144
+ />
145
+
146
+ <WalrusUpload
147
+ :hosts="relayHosts(NETWORK)"
148
+ :connected="!!account"
149
+ :access="{ gateConfigured: gateState.gateConfigured, hasAccess: gateState.hasAccess }"
150
+ :perform-upload="performUpload"
151
+ @uploaded="onUploaded"
152
+ />
153
+
154
+ <section v-if="result" class="result">
155
+ <h2>Uploaded ✓</h2>
156
+ <p><strong>Blob ID:</strong> <code>{{ result.blobId }}</code></p>
157
+ <p>
158
+ <strong>URL:</strong>
159
+ <a :href="result.url" target="_blank" rel="noopener">{{ result.url }}</a>
160
+ </p>
161
+ <p v-if="result.digest"><strong>Certify tx:</strong> <code>{{ result.digest }}</code></p>
162
+ </section>
125
163
  </template>
126
- </section>
127
-
128
- <template v-if="activeTab === 'upload'">
129
- <AccessGateCta
130
- :gate-configured="gateState.gateConfigured"
131
- :has-access="gateState.hasAccess.value"
132
- :busy="purchasing"
133
- :price-mist="gate?.priceMist ?? null"
134
- @purchase="onPurchase"
135
- />
136
164
 
137
- <WalrusUpload
138
- :hosts="relayHosts(NETWORK)"
139
- :connected="!!account"
140
- :access="{ gateConfigured: gateState.gateConfigured, hasAccess: gateState.hasAccess }"
141
- :perform-upload="performUpload"
142
- @uploaded="onUploaded"
165
+ <MyBlobs
166
+ v-if="activeTab === 'blobs'"
167
+ :address="account?.address ?? null"
168
+ :build-executor="() => buildExecutor(NETWORK)"
143
169
  />
170
+ </div>
144
171
 
145
- <section v-if="result" class="result">
146
- <h2>Uploaded ✓</h2>
147
- <p><strong>Blob ID:</strong> <code>{{ result.blobId }}</code></p>
148
- <p>
149
- <strong>URL:</strong>
150
- <a :href="result.url" target="_blank" rel="noopener">{{ result.url }}</a>
151
- </p>
152
- <p v-if="result.digest"><strong>Certify tx:</strong> <code>{{ result.digest }}</code></p>
153
- </section>
154
- </template>
155
-
156
- <MyBlobs
157
- v-if="activeTab === 'blobs'"
158
- :address="account?.address ?? null"
159
- :build-executor="() => buildExecutor(NETWORK)"
160
- />
161
-
162
- <footer class="foot">
163
- <p>© MeddleWare · <a href="https://sui.meddleware.co.uk">more SUI tools</a></p>
164
- </footer>
172
+ <AppFooter v-if="!isEmbedded" />
165
173
  </div>
166
174
  </template>
167
175
 
168
176
  <style scoped>
177
+ .app {
178
+ min-height: 100vh;
179
+ display: flex;
180
+ flex-direction: column;
181
+ }
182
+
183
+ .app--embedded {
184
+ min-height: 100%;
185
+ }
186
+
169
187
  .page {
170
188
  max-width: 640px;
171
189
  margin: 0 auto;
172
190
  padding: 2rem 1.25rem 4rem;
191
+ flex: 1;
173
192
  }
174
- .head {
175
- display: flex;
176
- justify-content: space-between;
177
- align-items: flex-start;
178
- gap: 1rem;
179
- flex-wrap: wrap;
180
- }
181
- .head h1 {
182
- margin: 0;
183
- font-size: 1.8rem;
193
+
194
+ .app--embedded .page {
195
+ padding-top: 1rem;
196
+ padding-bottom: 1rem;
184
197
  }
198
+
185
199
  .sub {
186
- color: var(--mw-color-text-muted, #666);
200
+ color: var(--muted);
187
201
  margin: 0.25rem 0 0;
188
202
  }
203
+
189
204
  .wallet {
190
205
  display: flex;
191
206
  align-items: center;
192
207
  gap: 0.75rem;
193
208
  margin: 1.25rem 0;
194
209
  }
210
+
195
211
  .addr {
196
212
  font-family: monospace;
197
213
  font-size: 0.9rem;
198
214
  }
215
+
199
216
  .result {
200
217
  margin-top: 1.5rem;
201
218
  padding: 1rem;
202
- border: 1px solid var(--mw-color-border, #ddd);
219
+ border: 1px solid var(--border);
203
220
  border-radius: 10px;
204
221
  word-break: break-all;
205
222
  }
223
+
206
224
  .result code {
207
225
  font-size: 0.85rem;
208
226
  }
227
+
209
228
  .tabs {
210
229
  display: flex;
211
230
  gap: 0.25rem;
212
231
  margin: 1rem 0 0.5rem;
213
- border-bottom: 2px solid var(--mw-color-border, #ddd);
232
+ border-bottom: 2px solid var(--border);
214
233
  }
234
+
215
235
  .tab {
216
236
  background: none;
217
237
  border: none;
@@ -220,16 +240,12 @@ function onUploaded(r: UploadResult): void {
220
240
  margin-bottom: -2px;
221
241
  cursor: pointer;
222
242
  font-size: 0.95rem;
223
- color: var(--mw-color-text-muted, #666);
243
+ color: var(--muted);
224
244
  }
245
+
225
246
  .tab.active {
226
- border-bottom-color: var(--mw-color-primary, #6c3);
227
- color: var(--mw-color-text, #111);
247
+ border-bottom-color: var(--accent);
248
+ color: var(--text);
228
249
  font-weight: 600;
229
250
  }
230
- .foot {
231
- margin-top: 3rem;
232
- font-size: 0.85rem;
233
- color: var(--mw-color-text-muted, #666);
234
- }
235
251
  </style>
package/src/main.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import '@meddleware/design-tokens/tokens.css'
2
+ import '@meddleware/ui/base.css'
2
3
  import { createApp } from 'vue'
3
4
  import App from './App.vue'
4
5