@meddleware/token-deployer-ui 0.0.2 → 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.
@@ -14,8 +14,7 @@ import {
14
14
  } from '../lib/accessGate.js'
15
15
  import type { WalrusNetwork } from '../lib/walrus.js'
16
16
  import type { Network } from '../lib/types.js'
17
- import AppNotice from './AppNotice.vue'
18
- import FieldHint from './FieldHint.vue'
17
+ import { UiNotice, UiFieldHint, UiSegmentedControl } from '@meddleware/ui'
19
18
  import WalrusBlobBrowser from './WalrusBlobBrowser.vue'
20
19
  import walrusWasmUrl from '@mysten/walrus-wasm/web/walrus_wasm_bg.wasm?url'
21
20
 
@@ -77,7 +76,7 @@ async function purchaseAccess(): Promise<void> {
77
76
  }
78
77
  }
79
78
 
80
- const tab = ref<'url' | 'upload' | 'browse'>('url')
79
+ const tab = ref('url')
81
80
 
82
81
  // Upload state
83
82
  const uploading = ref(false)
@@ -229,26 +228,16 @@ function onBrowseSelect(url: string): void {
229
228
  <fieldset class="icon-picker">
230
229
  <legend>Icon <span class="hint">(optional)</span></legend>
231
230
 
232
- <div class="icon-tabs" role="group" aria-label="Icon source">
233
- <label :class="{ active: tab === 'url' }">
234
- <input type="radio" v-model="tab" value="url" />
235
- URL
236
- </label>
237
- <label
238
- :class="{ active: tab === 'upload', disabled: !isWalrusNetwork }"
239
- :title="isWalrusNetwork ? undefined : 'Not available on localnet'"
240
- >
241
- <input type="radio" v-model="tab" value="upload" :disabled="!isWalrusNetwork" />
242
- Upload to Walrus
243
- </label>
244
- <label
245
- :class="{ active: tab === 'browse', disabled: !isWalrusNetwork }"
246
- :title="isWalrusNetwork ? undefined : 'Not available on localnet'"
247
- >
248
- <input type="radio" v-model="tab" value="browse" :disabled="!isWalrusNetwork" />
249
- My Walrus blobs
250
- </label>
251
- </div>
231
+ <UiSegmentedControl
232
+ v-model="tab"
233
+ :options="[
234
+ { id: 'url', label: 'URL' },
235
+ { id: 'upload', label: 'Upload to Walrus', disabled: !isWalrusNetwork, title: isWalrusNetwork ? undefined : 'Not available on localnet' },
236
+ { id: 'browse', label: 'My Walrus blobs', disabled: !isWalrusNetwork, title: isWalrusNetwork ? undefined : 'Not available on localnet' },
237
+ ]"
238
+ aria-label="Icon source"
239
+ style="margin-bottom: 0.75rem"
240
+ />
252
241
 
253
242
  <!-- URL panel -->
254
243
  <div v-show="tab === 'url'" class="icon-panel">
@@ -286,11 +275,11 @@ function onBrowseSelect(url: string): void {
286
275
  <label class="permanent-toggle">
287
276
  <input type="checkbox" v-model="permanent" />
288
277
  Permanent blob <span class="hint">(cannot be deleted)</span>
289
- <FieldHint field-id="blob-permanent">
278
+ <UiFieldHint field-id="blob-permanent">
290
279
  A permanent blob cannot be deleted once registered, even within its storage period.
291
280
  Deletable blobs can be removed early by the owner to reclaim unused storage fees (WAL).
292
281
  Permanent is the safer default for a token icon that should remain available indefinitely.
293
- </FieldHint>
282
+ </UiFieldHint>
294
283
  </label>
295
284
 
296
285
  <fieldset v-if="fileName && availableRelays.length > 1" style="margin: 0.5rem 0">
@@ -312,13 +301,13 @@ function onBrowseSelect(url: string): void {
312
301
  </div>
313
302
  </fieldset>
314
303
 
315
- <AppNotice v-if="fileName && estimatedCost" style="margin: 0.5rem 0">
304
+ <UiNotice v-if="fileName && estimatedCost" style="margin: 0.5rem 0">
316
305
  <strong>Estimated cost:</strong> {{ estimatedCost.label }}
317
- </AppNotice>
306
+ </UiNotice>
318
307
 
319
308
  <!-- NFT-gated relay: the operator relay is live but this wallet lacks the access NFT.
320
309
  The public relay is still available; purchasing unlocks the operator relay. -->
321
- <AppNotice v-if="fileName && purchaseAccessAvailable" style="margin: 0.5rem 0">
310
+ <UiNotice v-if="fileName && purchaseAccessAvailable" style="margin: 0.5rem 0">
322
311
  <p style="margin: 0 0 0.5rem">
323
312
  The operator relay requires an access NFT. You can keep using the public relay, or
324
313
  purchase access to support this app’s relay.
@@ -326,7 +315,7 @@ function onBrowseSelect(url: string): void {
326
315
  <button type="button" :disabled="purchasing || !connected" @click="purchaseAccess">
327
316
  {{ purchasing ? 'Purchasing…' : 'Purchase relay access' }}
328
317
  </button>
329
- </AppNotice>
318
+ </UiNotice>
330
319
 
331
320
  <p v-if="showFreeRelayTip" class="hint" style="margin: 0.5rem 0">
332
321
  Tip: select the public relay above to avoid the relay fee.
@@ -337,7 +326,7 @@ function onBrowseSelect(url: string): void {
337
326
  <strong>SUI</strong> (gas + relay fee) in your wallet; two approvals. Stored for
338
327
  ~{{ ICON_YEARS }} years. <span v-if="status">{{ status }}</span>
339
328
  </p>
340
- <AppNotice v-if="uploadError" type="error">{{ uploadError }}</AppNotice>
329
+ <UiNotice v-if="uploadError" type="error">{{ uploadError }}</UiNotice>
341
330
  </div>
342
331
 
343
332
  <!-- Browse panel -->
@@ -348,49 +337,6 @@ function onBrowseSelect(url: string): void {
348
337
  </template>
349
338
 
350
339
  <style scoped>
351
- .icon-tabs {
352
- display: flex;
353
- border: 1px solid var(--border);
354
- border-radius: 6px;
355
- overflow: hidden;
356
- width: fit-content;
357
- margin-bottom: 0.75rem;
358
- }
359
-
360
- .icon-tabs label {
361
- display: flex;
362
- align-items: center;
363
- padding: 0.4rem 0.75rem;
364
- cursor: pointer;
365
- font-size: 0.875rem;
366
- background: transparent;
367
- border-right: 1px solid var(--border);
368
- transition: background 0.15s, color 0.15s;
369
- user-select: none;
370
- }
371
-
372
- .icon-tabs label:last-child {
373
- border-right: none;
374
- }
375
-
376
- .icon-tabs label.active {
377
- background: var(--accent);
378
- color: var(--accent-contrast);
379
- }
380
-
381
- .icon-tabs label.disabled {
382
- opacity: 0.5;
383
- cursor: not-allowed;
384
- pointer-events: none;
385
- }
386
-
387
- .icon-tabs input[type='radio'] {
388
- position: absolute;
389
- opacity: 0;
390
- width: 0;
391
- height: 0;
392
- }
393
-
394
340
  .icon-panel {
395
341
  padding-top: 0.5rem;
396
342
  }
@@ -2,9 +2,7 @@
2
2
  import { computed, onMounted, ref } from 'vue'
3
3
  import { fetchLicenseList, fetchLicenseText, NO_LICENSE } from '../lib/licenses.js'
4
4
  import type { SpdxLicense } from '../lib/licenses.js'
5
- import FormSelect from './FormSelect.vue'
6
- import FieldHint from './FieldHint.vue'
7
- import AppNotice from './AppNotice.vue'
5
+ import { UiSelect, UiFieldHint, UiNotice } from '@meddleware/ui'
8
6
 
9
7
  const props = defineProps<{ modelValue: string }>()
10
8
  const emit = defineEmits<{
@@ -73,14 +71,14 @@ async function openLicenseModal(): Promise<void> {
73
71
  <div>
74
72
  <label for="license-select">
75
73
  License
76
- <FieldHint field-id="license-select">
74
+ <UiFieldHint field-id="license-select">
77
75
  Applies only to the downloadable Move source package — embedded in the LICENSE file and
78
76
  source headers. Has <b>no effect on the on-chain token</b> or its transferability.
79
77
  Choose <b>CC0-1.0</b> (default) for public domain. Choose <b>None</b> to retain all rights.
80
- </FieldHint>
78
+ </UiFieldHint>
81
79
  </label>
82
80
  <div class="license-row">
83
- <FormSelect
81
+ <UiSelect
84
82
  id="license-select"
85
83
  v-model="selectModel"
86
84
  :disabled="loading || Boolean(error)"
@@ -103,7 +101,7 @@ async function openLicenseModal(): Promise<void> {
103
101
  :title="`${l.id} — ${l.name}`"
104
102
  >{{ l.id }}</option>
105
103
  </optgroup>
106
- </FormSelect>
104
+ </UiSelect>
107
105
  <button type="button" class="view-btn" :disabled="loading" @click="openLicenseModal">
108
106
  View
109
107
  </button>
@@ -127,7 +125,7 @@ async function openLicenseModal(): Promise<void> {
127
125
  <div v-if="licenseLoading" style="padding: 1rem 0">
128
126
  <span class="spinner" aria-hidden="true"></span> Loading…
129
127
  </div>
130
- <AppNotice v-else-if="licenseError" type="error">{{ licenseError }}</AppNotice>
128
+ <UiNotice v-else-if="licenseError" type="error">{{ licenseError }}</UiNotice>
131
129
  <template v-else-if="modelValue === NO_LICENSE.id">
132
130
  <p>No LICENSE file will be generated. All rights are reserved by the author.</p>
133
131
  </template>
@@ -154,7 +152,7 @@ async function openLicenseModal(): Promise<void> {
154
152
  align-items: center;
155
153
  }
156
154
 
157
- .license-row :deep(.select-wrapper) {
155
+ .license-row :deep(.mw-select) {
158
156
  flex: 1;
159
157
  }
160
158
 
@@ -5,7 +5,7 @@ import { explorerObjectUrl } from '../config.js'
5
5
  import { generatePackageZip } from '../lib/generatePackage.js'
6
6
  import { fetchLicenseText } from '../lib/licenses.js'
7
7
  import GithubPush from './GithubPush.vue'
8
- import AppNotice from './AppNotice.vue'
8
+ import { UiNotice } from '@meddleware/ui'
9
9
 
10
10
  const props = defineProps<{ result: PublishResult; config: TokenConfig }>()
11
11
  defineEmits<{ (e: 'restart'): void }>()
@@ -70,7 +70,7 @@ async function downloadPackage(): Promise<void> {
70
70
  </button>
71
71
  <button type="button" @click="$emit('restart')">Deploy another</button>
72
72
  </div>
73
- <AppNotice v-if="downloadError" type="error">{{ downloadError }}</AppNotice>
73
+ <UiNotice v-if="downloadError" type="error">{{ downloadError }}</UiNotice>
74
74
 
75
75
  <div style="margin-top: 1rem">
76
76
  <GithubPush :config="config" :result="result" />
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { TokenConfig, Network } from '../lib/types.js'
3
3
  import { FEE_MIST } from '../config.js'
4
- import AppNotice from './AppNotice.vue'
4
+ import { UiNotice } from '@meddleware/ui'
5
5
 
6
6
  const props = defineProps<{ config: TokenConfig; network: Network }>()
7
7
  defineEmits<{ (e: 'back'): void; (e: 'confirm'): void }>()
@@ -13,7 +13,7 @@ const feeSui = Number(FEE_MIST) / 1e9
13
13
  <section class="card" aria-labelledby="review-h">
14
14
  <h2 id="review-h">Review — deploying to {{ props.network }}</h2>
15
15
 
16
- <AppNotice>
16
+ <UiNotice>
17
17
  These values are <strong>permanent</strong> once published: symbol
18
18
  <span class="mono">{{ config.symbol }}</span
19
19
  >, name <span class="mono">{{ config.name }}</span
@@ -21,7 +21,7 @@ const feeSui = Number(FEE_MIST) / 1e9
21
21
  >, and the coin type
22
22
  <span class="mono">&lt;package&gt;::{{ config.moduleName }}::{{ config.structName }}</span
23
23
  >.
24
- </AppNotice>
24
+ </UiNotice>
25
25
 
26
26
  <dl class="grid2" v-once>
27
27
  <div>
@@ -1,14 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, reactive, ref } from 'vue'
3
3
  import { useWallet, useNetwork, WalletGuard } from '@meddleware/wallet-adapter'
4
- import ConfigForm from './ConfigForm.vue'
4
+ import ConfigForm, { type ConfigFormStep } from './ConfigForm.vue'
5
5
  import ReviewPanel from './ReviewPanel.vue'
6
6
  import DeployProgress from './DeployProgress.vue'
7
7
  import ResultPanel from './ResultPanel.vue'
8
8
  import TermsDialog from './TermsDialog.vue'
9
- import AppNotice from './AppNotice.vue'
9
+ import { UiNotice, UiStepper, type StepperStep } from '@meddleware/ui'
10
10
  import { emptyForm, toTokenConfig } from '../lib/form.js'
11
- import { validateForm, isValid } from '../lib/validation.js'
11
+ import { validateForm } from '../lib/validation.js'
12
+ import type { FormErrors } from '../lib/validation.js'
12
13
  import { deployToken } from '../lib/deploy.js'
13
14
  import type { DeployStep } from '../lib/deploy.js'
14
15
  import { buildDeployExecutor } from '../lib/deployExecutor.js'
@@ -16,13 +17,23 @@ import { FEE_MIST, FEE_TREASURY, PUBLISH_GAS_BUDGET, isFeeConfigured } from '../
16
17
  import { extractErrorMessage } from '../lib/errors.js'
17
18
  import type { Network, PublishResult } from '../lib/types.js'
18
19
 
19
- type Step = 'form' | 'review' | 'deploying' | 'done'
20
+ type Step = 'identity' | 'token' | 'settings' | 'review' | 'deploying' | 'done'
21
+
22
+ const STEPS: StepperStep[] = [
23
+ { id: 'identity', label: 'Identity' },
24
+ { id: 'token', label: 'Token' },
25
+ { id: 'settings', label: 'Settings' },
26
+ { id: 'review', label: 'Review' },
27
+ { id: 'done', label: 'Done' },
28
+ ]
29
+
30
+ const CONFIG_STEPS: ConfigFormStep[] = ['identity', 'token', 'settings']
20
31
 
21
32
  const { account } = useWallet()
22
33
  const { network } = useNetwork()
23
34
 
24
35
  const form = reactive(emptyForm())
25
- const step = ref<Step>('form')
36
+ const step = ref<Step>('identity')
26
37
  const deployStep = ref<DeployStep | null>(null)
27
38
  const deployError = ref<string | null>(null)
28
39
  const result = ref<PublishResult | null>(null)
@@ -32,12 +43,65 @@ const showTerms = ref(false)
32
43
  const errors = computed(() => validateForm(form))
33
44
  const config = computed(() => toTokenConfig(form))
34
45
  const connected = computed(() => Boolean(account.value))
35
- const canProceed = computed(() => isValid(errors.value) && connected.value)
36
46
 
37
- function goReview(): void {
47
+ const IDENTITY_KEYS: (keyof FormErrors)[] = ['packageName', 'moduleName']
48
+ const TOKEN_KEYS: (keyof FormErrors)[] = ['name', 'symbol', 'description', 'iconUrl', 'decimals']
49
+ const SETTINGS_KEYS: (keyof FormErrors)[] = ['initialSupply', 'recipient']
50
+
51
+ function stepHasErrors(keys: (keyof FormErrors)[]): boolean {
52
+ return keys.some((k) => Boolean(errors.value[k]))
53
+ }
54
+
55
+ const canProceed = computed((): boolean => {
56
+ if (!connected.value) return false
57
+ switch (step.value) {
58
+ case 'identity': return !stepHasErrors(IDENTITY_KEYS)
59
+ case 'token': return !stepHasErrors(TOKEN_KEYS)
60
+ case 'settings': return !stepHasErrors(SETTINGS_KEYS)
61
+ default: return true
62
+ }
63
+ })
64
+
65
+ const formStep = computed((): ConfigFormStep => {
66
+ if (step.value === 'token') return 'token'
67
+ if (step.value === 'settings') return 'settings'
68
+ return 'identity'
69
+ })
70
+
71
+ const stepIndex = computed((): number => {
72
+ const map: Record<Step, number> = {
73
+ identity: 0,
74
+ token: 1,
75
+ settings: 2,
76
+ review: 3,
77
+ deploying: 3,
78
+ done: 4,
79
+ }
80
+ return map[step.value]
81
+ })
82
+
83
+ function onStepperBack(i: number): void {
84
+ const configStepAt = CONFIG_STEPS[i]
85
+ if (configStepAt && step.value === 'review') step.value = configStepAt
86
+ if (i < stepIndex.value && CONFIG_STEPS.includes(step.value as ConfigFormStep)) {
87
+ step.value = CONFIG_STEPS[i] ?? 'identity'
88
+ }
89
+ }
90
+
91
+ function goNext(): void {
38
92
  if (!canProceed.value) return
39
- if (!termsAccepted.value) { showTerms.value = true; return }
40
- step.value = 'review'
93
+ if (step.value === 'identity') { step.value = 'token'; return }
94
+ if (step.value === 'token') { step.value = 'settings'; return }
95
+ if (step.value === 'settings') {
96
+ if (!termsAccepted.value) { showTerms.value = true; return }
97
+ step.value = 'review'
98
+ }
99
+ }
100
+
101
+ function goBack(): void {
102
+ if (step.value === 'token') { step.value = 'identity'; return }
103
+ if (step.value === 'settings') { step.value = 'token'; return }
104
+ if (step.value === 'review') { step.value = 'settings'; return }
41
105
  }
42
106
 
43
107
  function onTermsAccept(): void {
@@ -80,26 +144,29 @@ async function confirmDeploy(): Promise<void> {
80
144
  function restart(): void {
81
145
  result.value = null
82
146
  deployError.value = null
83
- step.value = 'form'
147
+ step.value = 'identity'
84
148
  }
85
149
  </script>
86
150
 
87
151
  <template>
88
152
  <WalletGuard message="Connect a Sui wallet to deploy your token.">
153
+ <UiStepper :steps="STEPS" :model-value="stepIndex" @update:model-value="onStepperBack" />
89
154
  <ConfigForm
90
- v-if="step === 'form'"
155
+ v-if="step === 'identity' || step === 'token' || step === 'settings'"
91
156
  :form="form"
92
157
  :errors="errors"
93
158
  :can-proceed="canProceed"
94
159
  :network="network"
95
160
  :connected="connected"
96
- @submit="goReview"
161
+ :form-step="formStep"
162
+ @next="goNext"
163
+ @back="goBack"
97
164
  />
98
165
  <ReviewPanel
99
166
  v-if="step === 'review'"
100
167
  :config="config"
101
168
  :network="network"
102
- @back="step = 'form'"
169
+ @back="goBack"
103
170
  @confirm="confirmDeploy"
104
171
  />
105
172
  <DeployProgress v-if="step === 'deploying'" :step="deployStep" />
@@ -109,7 +176,7 @@ function restart(): void {
109
176
  :config="config"
110
177
  @restart="restart"
111
178
  />
112
- <AppNotice v-if="deployError" type="error">{{ deployError }}</AppNotice>
179
+ <UiNotice v-if="deployError" type="error">{{ deployError }}</UiNotice>
113
180
  <TermsDialog :open="showTerms" @accept="onTermsAccept" @cancel="onTermsCancel" />
114
181
  </WalletGuard>
115
182
  </template>
@@ -3,8 +3,7 @@ import { computed, ref, watch } from 'vue'
3
3
  import { useWallet, useNetwork } from '@meddleware/wallet-adapter'
4
4
  import { SELECTABLE_NETWORKS } from '../config.js'
5
5
  import type { Network } from '../lib/types.js'
6
- import FormSelect from './FormSelect.vue'
7
- import AppNotice from './AppNotice.vue'
6
+ import { UiSelect, UiNotice } from '@meddleware/ui'
8
7
 
9
8
  const { wallets, currentWallet, account, connecting, error, connect, disconnect } = useWallet()
10
9
  const { network, setNetwork } = useNetwork()
@@ -42,9 +41,9 @@ watch(() => account.value, (acc) => {
42
41
  <div class="row" style="justify-content: space-between">
43
42
  <div class="row">
44
43
  <label for="network-select" style="margin: 0">Network</label>
45
- <FormSelect id="network-select" v-model="networkModel">
44
+ <UiSelect id="network-select" v-model="networkModel">
46
45
  <option v-for="n in SELECTABLE_NETWORKS" :key="n" :value="n">{{ n }}</option>
47
- </FormSelect>
46
+ </UiSelect>
48
47
  </div>
49
48
 
50
49
  <div class="row">
@@ -68,7 +67,7 @@ watch(() => account.value, (acc) => {
68
67
  </div>
69
68
  </template>
70
69
 
71
- <AppNotice v-if="error" type="error" style="margin-top: 0.75rem">{{ error }}</AppNotice>
70
+ <UiNotice v-if="error" type="error" style="margin-top: 0.75rem">{{ error }}</UiNotice>
72
71
  </div>
73
72
 
74
73
  <dialog ref="dialogEl" aria-labelledby="wallet-dialog-title" @click.self="closeDialog">
@@ -86,9 +85,9 @@ watch(() => account.value, (acc) => {
86
85
 
87
86
  <div>
88
87
  <label for="dialog-network-select">Network</label>
89
- <FormSelect id="dialog-network-select" v-model="networkModel">
88
+ <UiSelect id="dialog-network-select" v-model="networkModel">
90
89
  <option v-for="n in SELECTABLE_NETWORKS" :key="n" :value="n">{{ n }}</option>
91
- </FormSelect>
90
+ </UiSelect>
92
91
  </div>
93
92
 
94
93
  <div class="wallet-list">
@@ -4,7 +4,7 @@ import { useWallet } from '@meddleware/wallet-adapter'
4
4
  import { getReadClient } from '../lib/readClient.js'
5
5
  import type { OwnedBlob, WalrusNetwork } from '../lib/walrus.js'
6
6
  import type { Network } from '../lib/types.js'
7
- import AppNotice from './AppNotice.vue'
7
+ import { UiNotice } from '@meddleware/ui'
8
8
 
9
9
  const props = defineProps<{ network: WalrusNetwork; connected: boolean }>()
10
10
  const emit = defineEmits<{ (e: 'select', url: string): void }>()
@@ -84,7 +84,7 @@ function selectBlob(item: BlobItem): void {
84
84
  </div>
85
85
  <p class="hint">Browse Walrus blobs owned by this address. Only image blobs show a preview.</p>
86
86
 
87
- <AppNotice v-if="loadError" type="error">{{ loadError }}</AppNotice>
87
+ <UiNotice v-if="loadError" type="error">{{ loadError }}</UiNotice>
88
88
 
89
89
  <p v-if="hasLoaded && blobs.length === 0 && !loading" class="hint">
90
90
  No Walrus blobs found at this address.
@@ -7,7 +7,7 @@ import { ICON_EPOCHS } from '../lib/walrus-constants.js'
7
7
  import { ICON_MAX_BYTES, validateIconFile } from '../config.js'
8
8
  import type { WalrusNetwork } from '../lib/walrus.js'
9
9
  import type { Network } from '../lib/types.js'
10
- import AppNotice from './AppNotice.vue'
10
+ import { UiNotice } from '@meddleware/ui'
11
11
  // Vite serves the Walrus wasm as an asset URL (lightweight import — just the URL).
12
12
  import walrusWasmUrl from '@mysten/walrus-wasm/web/walrus_wasm_bg.wasm?url'
13
13
 
@@ -185,9 +185,9 @@ async function upload(): Promise<void> {
185
185
  </fieldset>
186
186
 
187
187
  <!-- Cost estimation (shown after file selection) -->
188
- <AppNotice v-if="fileName && estimatedCost" style="margin: 0.75rem 0">
188
+ <UiNotice v-if="fileName && estimatedCost" style="margin: 0.75rem 0">
189
189
  <strong>Estimated cost:</strong> {{ estimatedCost.label }}
190
- </AppNotice>
190
+ </UiNotice>
191
191
 
192
192
  <!-- Public relay notice -->
193
193
  <p v-if="showFreeRelayTip" class="hint" style="margin: 0.75rem 0">
@@ -200,6 +200,6 @@ async function upload(): Promise<void> {
200
200
  stored for ~{{ ICON_YEARS }} years.
201
201
  <span v-if="status">{{ status }}</span>
202
202
  </p>
203
- <AppNotice v-if="error" type="error">{{ error }}</AppNotice>
203
+ <UiNotice v-if="error" type="error">{{ error }}</UiNotice>
204
204
  </div>
205
205
  </template>
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
+ import './component-styles.css'
1
2
  export { default as TokenDeployerView } from './components/TokenDeployerView.vue'
package/src/main.ts CHANGED
@@ -1,8 +1,12 @@
1
+ import '@meddleware/design-tokens/tokens.css'
2
+ import '@meddleware/design-tokens/seasons.css'
3
+ import '@meddleware/ui/base.css'
1
4
  import { createApp } from 'vue'
2
5
  import App from './App.vue'
3
6
  import './styles.css'
7
+ import './component-styles.css'
4
8
  import { configureWasm } from './lib/template.js'
5
- import { useColorMode } from './composables/useColorMode.js'
9
+ import { useColorMode } from '@meddleware/ui'
6
10
 
7
11
  // Apply the colour mode before mount so there is no theme flash. Defaults to
8
12
  // `system` (follows the OS) while enabling the in-app light/dark/system control.