@meddleware/token-deployer-ui 0.0.1 → 0.0.3
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/.github/workflows/publish.yml +367 -0
- package/Dockerfile +96 -0
- package/package.json +5 -3
- package/scripts/sync-template-src.sh +1 -1
- package/src/App.vue +1 -2
- package/src/component-styles.css +257 -0
- package/src/components/ConfigForm.vue +42 -41
- package/src/components/GithubPush.vue +4 -4
- package/src/components/IconPicker.vue +8 -9
- package/src/components/LicensePicker.vue +7 -9
- package/src/components/ResultPanel.vue +2 -2
- package/src/components/ReviewPanel.vue +3 -3
- package/src/components/TokenDeployerView.vue +2 -2
- package/src/components/WalletBar.vue +6 -7
- package/src/components/WalrusBlobBrowser.vue +2 -2
- package/src/components/WalrusIconUpload.vue +4 -4
- package/src/index.ts +1 -0
- package/src/main.ts +5 -1
- package/src/styles.css +3 -335
- package/tests/templateParity.test.ts +1 -1
- package/.env.production +0 -7
- package/src/components/AppNotice.vue +0 -15
- package/src/components/ColorModeControl.vue +0 -81
- package/src/components/FieldHint.vue +0 -79
- package/src/components/FormField.vue +0 -28
- package/src/components/FormSelect.vue +0 -43
- package/src/composables/useColorMode.ts +0 -76
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/* Component utility styles for TokenDeployerView and its sub-components.
|
|
2
|
+
Imported by index.ts so these are available in both standalone and library (dashboard) mode.
|
|
3
|
+
Relies on design-token CSS variables (--bg, --surface, --border, etc.) provided by the
|
|
4
|
+
consumer — either @meddleware/design-tokens (standalone) or the dashboard's own import. */
|
|
5
|
+
|
|
6
|
+
.card {
|
|
7
|
+
background: var(--surface);
|
|
8
|
+
border: 1px solid var(--border);
|
|
9
|
+
border-radius: var(--radius);
|
|
10
|
+
padding: 1.25rem;
|
|
11
|
+
margin: 1.5rem 0 1rem;
|
|
12
|
+
border-top: 2px solid var(--border);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
label {
|
|
16
|
+
display: block;
|
|
17
|
+
font-weight: 600;
|
|
18
|
+
margin: 0.9rem 0 0.3rem;
|
|
19
|
+
}
|
|
20
|
+
.hint {
|
|
21
|
+
color: var(--muted);
|
|
22
|
+
font-weight: 400;
|
|
23
|
+
font-size: 0.9rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
input,
|
|
27
|
+
select,
|
|
28
|
+
textarea {
|
|
29
|
+
width: 100%;
|
|
30
|
+
padding: 0.6rem 0.7rem;
|
|
31
|
+
font: inherit;
|
|
32
|
+
color: var(--text);
|
|
33
|
+
background: var(--bg);
|
|
34
|
+
border: 1px solid var(--border);
|
|
35
|
+
border-radius: 8px;
|
|
36
|
+
}
|
|
37
|
+
textarea {
|
|
38
|
+
min-height: 4rem;
|
|
39
|
+
resize: vertical;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
input[aria-invalid='true'],
|
|
43
|
+
select[aria-invalid='true'],
|
|
44
|
+
textarea[aria-invalid='true'] {
|
|
45
|
+
border-color: var(--danger);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.field-error {
|
|
49
|
+
color: var(--danger);
|
|
50
|
+
font-size: 0.88rem;
|
|
51
|
+
margin-top: 0.3rem;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
button {
|
|
55
|
+
font: inherit;
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
padding: 0.6rem 1rem;
|
|
58
|
+
border-radius: 8px;
|
|
59
|
+
border: 1px solid var(--border);
|
|
60
|
+
background: var(--surface);
|
|
61
|
+
color: var(--text);
|
|
62
|
+
cursor: pointer;
|
|
63
|
+
}
|
|
64
|
+
button.primary {
|
|
65
|
+
background: var(--accent);
|
|
66
|
+
color: var(--accent-contrast);
|
|
67
|
+
border-color: transparent;
|
|
68
|
+
}
|
|
69
|
+
button:disabled {
|
|
70
|
+
opacity: 0.55;
|
|
71
|
+
cursor: not-allowed;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.row {
|
|
75
|
+
display: flex;
|
|
76
|
+
gap: 0.75rem;
|
|
77
|
+
flex-wrap: wrap;
|
|
78
|
+
align-items: center;
|
|
79
|
+
}
|
|
80
|
+
.grid2 {
|
|
81
|
+
display: grid;
|
|
82
|
+
grid-template-columns: 1fr;
|
|
83
|
+
gap: 0 1rem;
|
|
84
|
+
}
|
|
85
|
+
@media (min-width: 520px) {
|
|
86
|
+
.grid2 {
|
|
87
|
+
grid-template-columns: 1fr 1fr;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fieldset {
|
|
92
|
+
background: var(--lift);
|
|
93
|
+
border: 1px solid var(--border);
|
|
94
|
+
border-radius: 8px;
|
|
95
|
+
padding: 0.5rem 1rem 1rem;
|
|
96
|
+
margin: 1rem 0;
|
|
97
|
+
}
|
|
98
|
+
legend {
|
|
99
|
+
font-weight: 700;
|
|
100
|
+
padding: 0 0.4rem;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
details {
|
|
104
|
+
margin: 1rem 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
details > summary {
|
|
108
|
+
color: var(--accent);
|
|
109
|
+
font-weight: 700;
|
|
110
|
+
margin: 0.5rem 0;
|
|
111
|
+
padding: 0.75rem;
|
|
112
|
+
background: var(--lift);
|
|
113
|
+
border-radius: 8px;
|
|
114
|
+
border: 1px solid transparent;
|
|
115
|
+
transition: border-color 0.2s ease;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
details > summary:hover {
|
|
119
|
+
border-color: var(--border);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
details[open] > summary {
|
|
123
|
+
border-color: var(--border);
|
|
124
|
+
margin-bottom: 1rem;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
details > fieldset {
|
|
128
|
+
margin-top: 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.permanent {
|
|
132
|
+
color: var(--danger);
|
|
133
|
+
font-weight: 600;
|
|
134
|
+
}
|
|
135
|
+
.mono {
|
|
136
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
137
|
+
word-break: break-all;
|
|
138
|
+
}
|
|
139
|
+
.badge {
|
|
140
|
+
display: inline-block;
|
|
141
|
+
font-size: 0.8rem;
|
|
142
|
+
padding: 0.15rem 0.5rem;
|
|
143
|
+
border-radius: 999px;
|
|
144
|
+
background: var(--border);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.visually-hidden {
|
|
148
|
+
position: absolute;
|
|
149
|
+
width: 1px;
|
|
150
|
+
height: 1px;
|
|
151
|
+
padding: 0;
|
|
152
|
+
margin: -1px;
|
|
153
|
+
overflow: hidden;
|
|
154
|
+
clip: rect(0 0 0 0);
|
|
155
|
+
white-space: nowrap;
|
|
156
|
+
border: 0;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.skip-link {
|
|
160
|
+
position: absolute;
|
|
161
|
+
left: 0.5rem;
|
|
162
|
+
top: -3rem;
|
|
163
|
+
z-index: 100;
|
|
164
|
+
background: var(--accent);
|
|
165
|
+
color: #fff;
|
|
166
|
+
padding: 0.5rem 0.9rem;
|
|
167
|
+
border-radius: 6px;
|
|
168
|
+
text-decoration: none;
|
|
169
|
+
transition: top 0.15s ease;
|
|
170
|
+
}
|
|
171
|
+
.skip-link:focus {
|
|
172
|
+
top: 0.5rem;
|
|
173
|
+
}
|
|
174
|
+
@media (prefers-reduced-motion: reduce) {
|
|
175
|
+
.skip-link {
|
|
176
|
+
transition: none;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.steps {
|
|
181
|
+
list-style: none;
|
|
182
|
+
padding: 0;
|
|
183
|
+
}
|
|
184
|
+
.steps li {
|
|
185
|
+
padding: 0.35rem 0;
|
|
186
|
+
color: var(--muted);
|
|
187
|
+
}
|
|
188
|
+
.steps li[data-state='active'] {
|
|
189
|
+
color: var(--text);
|
|
190
|
+
font-weight: 600;
|
|
191
|
+
}
|
|
192
|
+
.steps li[data-state='done'] {
|
|
193
|
+
color: var(--ok);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.spinner {
|
|
197
|
+
width: 1em;
|
|
198
|
+
height: 1em;
|
|
199
|
+
border: 2px solid currentColor;
|
|
200
|
+
border-right-color: transparent;
|
|
201
|
+
border-radius: 50%;
|
|
202
|
+
display: inline-block;
|
|
203
|
+
animation: spin 0.7s linear infinite;
|
|
204
|
+
vertical-align: -0.15em;
|
|
205
|
+
}
|
|
206
|
+
@keyframes spin {
|
|
207
|
+
to {
|
|
208
|
+
transform: rotate(360deg);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
@media (prefers-reduced-motion: reduce) {
|
|
212
|
+
.spinner {
|
|
213
|
+
animation: none;
|
|
214
|
+
}
|
|
215
|
+
* {
|
|
216
|
+
scroll-behavior: auto;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
dialog {
|
|
221
|
+
background: var(--surface);
|
|
222
|
+
border: 1px solid var(--border);
|
|
223
|
+
border-radius: var(--radius);
|
|
224
|
+
padding: 1.5rem;
|
|
225
|
+
width: min(420px, 90vw);
|
|
226
|
+
max-height: 90vh;
|
|
227
|
+
overflow-y: auto;
|
|
228
|
+
color: var(--text);
|
|
229
|
+
}
|
|
230
|
+
dialog::backdrop {
|
|
231
|
+
background: rgba(0, 0, 0, 0.45);
|
|
232
|
+
-webkit-backdrop-filter: blur(2px);
|
|
233
|
+
backdrop-filter: blur(2px);
|
|
234
|
+
}
|
|
235
|
+
.dialog-header {
|
|
236
|
+
display: flex;
|
|
237
|
+
justify-content: space-between;
|
|
238
|
+
align-items: center;
|
|
239
|
+
margin-bottom: 1.25rem;
|
|
240
|
+
}
|
|
241
|
+
.dialog-header h2 {
|
|
242
|
+
margin: 0;
|
|
243
|
+
font-size: 1.1rem;
|
|
244
|
+
}
|
|
245
|
+
.wallet-list {
|
|
246
|
+
display: flex;
|
|
247
|
+
flex-direction: column;
|
|
248
|
+
gap: 0.5rem;
|
|
249
|
+
margin-top: 1rem;
|
|
250
|
+
}
|
|
251
|
+
.wallet-list button {
|
|
252
|
+
display: flex;
|
|
253
|
+
align-items: center;
|
|
254
|
+
gap: 0.6rem;
|
|
255
|
+
width: 100%;
|
|
256
|
+
justify-content: flex-start;
|
|
257
|
+
}
|
|
@@ -6,9 +6,10 @@ import { deriveStructName } from '../lib/validation.js'
|
|
|
6
6
|
import type { Network } from '../lib/types.js'
|
|
7
7
|
import LicensePicker from './LicensePicker.vue'
|
|
8
8
|
import IconPicker from './IconPicker.vue'
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import { UiFormField, UiSelect, UiFieldHint } from '@meddleware/ui'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
12
13
|
|
|
13
14
|
const props = defineProps<{
|
|
14
15
|
form: FormModel
|
|
@@ -45,12 +46,12 @@ function onBlur(key: string): void {
|
|
|
45
46
|
<fieldset>
|
|
46
47
|
<legend>Package identity <span class="permanent">(permanent)</span></legend>
|
|
47
48
|
<div class="grid2">
|
|
48
|
-
<
|
|
49
|
+
<UiFormField id="package" label="Package name" :error="visibleError('packageName')" v-slot="{ attrs }">
|
|
49
50
|
<input v-bind="attrs" v-model="form.packageName" placeholder="my_token" autocomplete="off" @blur="onBlur('packageName')" />
|
|
50
|
-
</
|
|
51
|
-
<
|
|
51
|
+
</UiFormField>
|
|
52
|
+
<UiFormField id="module" label="Module name" :error="visibleError('moduleName')" v-slot="{ attrs }">
|
|
52
53
|
<input v-bind="attrs" v-model="form.moduleName" placeholder="mytoken" autocomplete="off" @blur="onBlur('moduleName')" />
|
|
53
|
-
</
|
|
54
|
+
</UiFormField>
|
|
54
55
|
</div>
|
|
55
56
|
<p class="hint" aria-live="polite">
|
|
56
57
|
<template v-if="identifierError">
|
|
@@ -68,27 +69,27 @@ function onBlur(key: string): void {
|
|
|
68
69
|
<legend>Token details</legend>
|
|
69
70
|
|
|
70
71
|
<div class="grid2">
|
|
71
|
-
<
|
|
72
|
+
<UiFormField id="name" label="Token name" :error="visibleError('name')" v-slot="{ attrs }">
|
|
72
73
|
<input v-bind="attrs" v-model="form.name" autocomplete="off" @blur="onBlur('name')" />
|
|
73
|
-
</
|
|
74
|
-
<
|
|
74
|
+
</UiFormField>
|
|
75
|
+
<UiFormField id="symbol" label="Symbol" :error="visibleError('symbol')" v-slot="{ attrs }">
|
|
75
76
|
<input v-bind="attrs" v-model="form.symbol" autocomplete="off" @blur="onBlur('symbol')" />
|
|
76
|
-
</
|
|
77
|
+
</UiFormField>
|
|
77
78
|
</div>
|
|
78
79
|
|
|
79
|
-
<
|
|
80
|
+
<UiFormField id="description" label="Description" :error="visibleError('description')">
|
|
80
81
|
<template #label-suffix> <span class="hint">(optional)</span></template>
|
|
81
82
|
<template #default="{ attrs }">
|
|
82
83
|
<textarea v-bind="attrs" v-model="form.description" @blur="onBlur('description')" />
|
|
83
84
|
</template>
|
|
84
|
-
</
|
|
85
|
+
</UiFormField>
|
|
85
86
|
|
|
86
|
-
<
|
|
87
|
+
<UiFormField id="decimals" label="Decimals" :error="visibleError('decimals')">
|
|
87
88
|
<template #label-suffix> <span class="permanent">(permanent)</span></template>
|
|
88
89
|
<template #default="{ attrs }">
|
|
89
90
|
<input v-bind="attrs" v-model="form.decimals" inputmode="numeric" @blur="onBlur('decimals')" />
|
|
90
91
|
</template>
|
|
91
|
-
</
|
|
92
|
+
</UiFormField>
|
|
92
93
|
|
|
93
94
|
<IconPicker
|
|
94
95
|
v-model="form.iconUrl"
|
|
@@ -104,82 +105,82 @@ function onBlur(key: string): void {
|
|
|
104
105
|
<fieldset>
|
|
105
106
|
<legend class="visually-hidden">Advanced options</legend>
|
|
106
107
|
|
|
107
|
-
<
|
|
108
|
+
<UiFormField id="supply" label="Initial supply" :error="visibleError('initialSupply')">
|
|
108
109
|
<template #label-suffix>
|
|
109
|
-
<
|
|
110
|
+
<UiFieldHint field-id="supply">
|
|
110
111
|
The number of whole tokens to mint and send to the recipient at deployment.
|
|
111
112
|
Uses your chosen decimal precision — with 9 decimals, 1 token = 1,000,000,000 base units on-chain.
|
|
112
113
|
Enter <b>0</b> or leave blank for no initial supply.
|
|
113
114
|
You can mint more later if you choose the Mintable supply policy.
|
|
114
|
-
</
|
|
115
|
+
</UiFieldHint>
|
|
115
116
|
</template>
|
|
116
117
|
<template #default="{ attrs }">
|
|
117
118
|
<input v-bind="attrs" v-model="form.initialSupply" inputmode="numeric" placeholder="0" @blur="onBlur('initialSupply')" />
|
|
118
119
|
</template>
|
|
119
|
-
</
|
|
120
|
+
</UiFormField>
|
|
120
121
|
|
|
121
122
|
<div class="grid2">
|
|
122
|
-
<
|
|
123
|
+
<UiFormField id="supply-policy" label="Supply">
|
|
123
124
|
<template #label-suffix>
|
|
124
|
-
<
|
|
125
|
+
<UiFieldHint field-id="supply-policy">
|
|
125
126
|
<b>Mintable</b>: you keep the TreasuryCap and can mint more tokens at any time.<br />
|
|
126
127
|
<b>Fixed</b>: the TreasuryCap is frozen — the total supply is sealed at deployment.
|
|
127
|
-
</
|
|
128
|
+
</UiFieldHint>
|
|
128
129
|
</template>
|
|
129
130
|
<template #default="{ attrs }">
|
|
130
|
-
<
|
|
131
|
+
<UiSelect v-bind="attrs" v-model="form.supplyPolicy">
|
|
131
132
|
<option value="mintable">Mintable</option>
|
|
132
133
|
<option value="fixed">Fixed</option>
|
|
133
|
-
</
|
|
134
|
+
</UiSelect>
|
|
134
135
|
</template>
|
|
135
|
-
</
|
|
136
|
-
<
|
|
136
|
+
</UiFormField>
|
|
137
|
+
<UiFormField id="metadata-policy" label="Metadata">
|
|
137
138
|
<template #label-suffix>
|
|
138
|
-
<
|
|
139
|
+
<UiFieldHint field-id="metadata-policy">
|
|
139
140
|
<b>Updatable</b>: you keep the MetadataCap and can later change the name, symbol,
|
|
140
141
|
description, or icon.<br />
|
|
141
142
|
<b>Frozen</b>: the MetadataCap is discarded — all metadata is permanently locked.
|
|
142
|
-
</
|
|
143
|
+
</UiFieldHint>
|
|
143
144
|
</template>
|
|
144
145
|
<template #default="{ attrs }">
|
|
145
|
-
<
|
|
146
|
+
<UiSelect v-bind="attrs" v-model="form.metadataPolicy">
|
|
146
147
|
<option value="updatable">Updatable</option>
|
|
147
148
|
<option value="frozen">Frozen</option>
|
|
148
|
-
</
|
|
149
|
+
</UiSelect>
|
|
149
150
|
</template>
|
|
150
|
-
</
|
|
151
|
+
</UiFormField>
|
|
151
152
|
</div>
|
|
152
153
|
|
|
153
|
-
<
|
|
154
|
+
<UiFormField id="package-policy" label="Package code">
|
|
154
155
|
<template #label-suffix>
|
|
155
|
-
<
|
|
156
|
+
<UiFieldHint field-id="package-policy">
|
|
156
157
|
<b>Immutable</b>: the UpgradeCap is burned — the on-chain code is sealed.
|
|
157
158
|
Recommended for trust and auditability.<br />
|
|
158
159
|
<b>Upgradeable</b>: you keep the UpgradeCap and can push code changes to the package
|
|
159
160
|
after deployment.
|
|
160
|
-
</
|
|
161
|
+
</UiFieldHint>
|
|
161
162
|
</template>
|
|
162
163
|
<template #default="{ attrs }">
|
|
163
|
-
<
|
|
164
|
+
<UiSelect v-bind="attrs" v-model="form.packagePolicy">
|
|
164
165
|
<option value="immutable">Immutable</option>
|
|
165
166
|
<option value="upgradeable">Upgradeable</option>
|
|
166
|
-
</
|
|
167
|
+
</UiSelect>
|
|
167
168
|
</template>
|
|
168
|
-
</
|
|
169
|
+
</UiFormField>
|
|
169
170
|
|
|
170
|
-
<
|
|
171
|
+
<UiFormField id="recipient" label="Recipient" :error="visibleError('recipient')">
|
|
171
172
|
<template #label-suffix>
|
|
172
|
-
<
|
|
173
|
+
<UiFieldHint field-id="recipient">
|
|
173
174
|
The Sui address that receives the TreasuryCap, MetadataCap, UpgradeCap (if kept),
|
|
174
175
|
and any initial supply minted at deployment.
|
|
175
176
|
Leave blank to send everything to the connected wallet.
|
|
176
177
|
Enter a different address to separate the deployer wallet from the custody wallet.
|
|
177
|
-
</
|
|
178
|
+
</UiFieldHint>
|
|
178
179
|
</template>
|
|
179
180
|
<template #default="{ attrs }">
|
|
180
181
|
<input v-bind="attrs" v-model="form.recipient" placeholder="0x…" autocomplete="off" @blur="onBlur('recipient')" />
|
|
181
182
|
</template>
|
|
182
|
-
</
|
|
183
|
+
</UiFormField>
|
|
183
184
|
|
|
184
185
|
<LicensePicker v-model="form.license" @name="form.licenseName = $event" />
|
|
185
186
|
</fieldset>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref } from 'vue'
|
|
3
3
|
import type { PublishResult, TokenConfig } from '../lib/types.js'
|
|
4
|
-
import
|
|
4
|
+
import { UiNotice } from '@meddleware/ui'
|
|
5
5
|
import { buildPackageFiles } from '../lib/generatePackage.js'
|
|
6
6
|
import { fetchLicenseText } from '../lib/licenses.js'
|
|
7
7
|
import { createRepoAndPush } from '../lib/github.js'
|
|
@@ -91,10 +91,10 @@ async function push(): Promise<void> {
|
|
|
91
91
|
<span v-if="progress" class="hint" aria-live="polite">{{ progress }}</span>
|
|
92
92
|
</div>
|
|
93
93
|
|
|
94
|
-
<
|
|
95
|
-
<
|
|
94
|
+
<UiNotice v-if="error" type="error">{{ error }}</UiNotice>
|
|
95
|
+
<UiNotice v-if="doneUrl" type="ok">
|
|
96
96
|
Pushed: <a :href="doneUrl" target="_blank" rel="noopener noreferrer">{{ doneUrl }}</a>
|
|
97
|
-
</
|
|
97
|
+
</UiNotice>
|
|
98
98
|
</div>
|
|
99
99
|
</div>
|
|
100
100
|
</template>
|
|
@@ -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
|
|
18
|
-
import FieldHint from './FieldHint.vue'
|
|
17
|
+
import { UiNotice, UiFieldHint } 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
|
|
|
@@ -286,11 +285,11 @@ function onBrowseSelect(url: string): void {
|
|
|
286
285
|
<label class="permanent-toggle">
|
|
287
286
|
<input type="checkbox" v-model="permanent" />
|
|
288
287
|
Permanent blob <span class="hint">(cannot be deleted)</span>
|
|
289
|
-
<
|
|
288
|
+
<UiFieldHint field-id="blob-permanent">
|
|
290
289
|
A permanent blob cannot be deleted once registered, even within its storage period.
|
|
291
290
|
Deletable blobs can be removed early by the owner to reclaim unused storage fees (WAL).
|
|
292
291
|
Permanent is the safer default for a token icon that should remain available indefinitely.
|
|
293
|
-
</
|
|
292
|
+
</UiFieldHint>
|
|
294
293
|
</label>
|
|
295
294
|
|
|
296
295
|
<fieldset v-if="fileName && availableRelays.length > 1" style="margin: 0.5rem 0">
|
|
@@ -312,13 +311,13 @@ function onBrowseSelect(url: string): void {
|
|
|
312
311
|
</div>
|
|
313
312
|
</fieldset>
|
|
314
313
|
|
|
315
|
-
<
|
|
314
|
+
<UiNotice v-if="fileName && estimatedCost" style="margin: 0.5rem 0">
|
|
316
315
|
<strong>Estimated cost:</strong> {{ estimatedCost.label }}
|
|
317
|
-
</
|
|
316
|
+
</UiNotice>
|
|
318
317
|
|
|
319
318
|
<!-- NFT-gated relay: the operator relay is live but this wallet lacks the access NFT.
|
|
320
319
|
The public relay is still available; purchasing unlocks the operator relay. -->
|
|
321
|
-
<
|
|
320
|
+
<UiNotice v-if="fileName && purchaseAccessAvailable" style="margin: 0.5rem 0">
|
|
322
321
|
<p style="margin: 0 0 0.5rem">
|
|
323
322
|
The operator relay requires an access NFT. You can keep using the public relay, or
|
|
324
323
|
purchase access to support this app’s relay.
|
|
@@ -326,7 +325,7 @@ function onBrowseSelect(url: string): void {
|
|
|
326
325
|
<button type="button" :disabled="purchasing || !connected" @click="purchaseAccess">
|
|
327
326
|
{{ purchasing ? 'Purchasing…' : 'Purchase relay access' }}
|
|
328
327
|
</button>
|
|
329
|
-
</
|
|
328
|
+
</UiNotice>
|
|
330
329
|
|
|
331
330
|
<p v-if="showFreeRelayTip" class="hint" style="margin: 0.5rem 0">
|
|
332
331
|
Tip: select the public relay above to avoid the relay fee.
|
|
@@ -337,7 +336,7 @@ function onBrowseSelect(url: string): void {
|
|
|
337
336
|
<strong>SUI</strong> (gas + relay fee) in your wallet; two approvals. Stored for
|
|
338
337
|
~{{ ICON_YEARS }} years. <span v-if="status">{{ status }}</span>
|
|
339
338
|
</p>
|
|
340
|
-
<
|
|
339
|
+
<UiNotice v-if="uploadError" type="error">{{ uploadError }}</UiNotice>
|
|
341
340
|
</div>
|
|
342
341
|
|
|
343
342
|
<!-- Browse panel -->
|
|
@@ -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
|
|
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
|
-
<
|
|
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
|
-
</
|
|
78
|
+
</UiFieldHint>
|
|
81
79
|
</label>
|
|
82
80
|
<div class="license-row">
|
|
83
|
-
<
|
|
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
|
-
</
|
|
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
|
-
<
|
|
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
|
|
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
|
|
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
|
-
<
|
|
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
|
|
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
|
-
<
|
|
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"><package>::{{ config.moduleName }}::{{ config.structName }}</span
|
|
23
23
|
>.
|
|
24
|
-
</
|
|
24
|
+
</UiNotice>
|
|
25
25
|
|
|
26
26
|
<dl class="grid2" v-once>
|
|
27
27
|
<div>
|
|
@@ -6,7 +6,7 @@ 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
|
|
9
|
+
import { UiNotice } from '@meddleware/ui'
|
|
10
10
|
import { emptyForm, toTokenConfig } from '../lib/form.js'
|
|
11
11
|
import { validateForm, isValid } from '../lib/validation.js'
|
|
12
12
|
import { deployToken } from '../lib/deploy.js'
|
|
@@ -109,7 +109,7 @@ function restart(): void {
|
|
|
109
109
|
:config="config"
|
|
110
110
|
@restart="restart"
|
|
111
111
|
/>
|
|
112
|
-
<
|
|
112
|
+
<UiNotice v-if="deployError" type="error">{{ deployError }}</UiNotice>
|
|
113
113
|
<TermsDialog :open="showTerms" @accept="onTermsAccept" @cancel="onTermsCancel" />
|
|
114
114
|
</WalletGuard>
|
|
115
115
|
</template>
|