create-lightning-scaffold 1.0.1 → 1.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/README.md +2 -1
- package/package.json +1 -1
- package/templates/mobile/components/History.tsx.ejs +56 -51
- package/templates/mobile/components/Recovery.tsx.ejs +70 -65
- package/templates/mobile/components/Swap.tsx.ejs +132 -121
- package/templates/vite/src/components/History.tsx.ejs +15 -15
- package/templates/vite/src/components/Recovery.tsx.ejs +16 -16
- package/templates/vite/src/components/Swap.tsx.ejs +39 -39
- package/templates/web/components/History.tsx.ejs +16 -16
- package/templates/web/components/Recovery.tsx.ejs +17 -17
- package/templates/web/components/Swap.tsx.ejs +37 -37
|
@@ -49,35 +49,42 @@ const JUPITER_API = 'https://api.jup.ag/swap/v1';
|
|
|
49
49
|
<% if (styling !== 'nativewind') { %>
|
|
50
50
|
const styles = StyleSheet.create({
|
|
51
51
|
container: { flex: 1, backgroundColor: '#fff', padding: 24, paddingTop: 60 },
|
|
52
|
+
card: { backgroundColor: '#0a0a0a', borderRadius: 16, padding: 20 },
|
|
52
53
|
header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 24 },
|
|
53
|
-
title: { fontSize: 18, fontWeight: '600', color: '#
|
|
54
|
-
address: { fontSize: 12, color: '#
|
|
55
|
-
|
|
56
|
-
label: { fontSize: 12, color: '#
|
|
54
|
+
title: { fontSize: 18, fontWeight: '600', color: '#fafafa' },
|
|
55
|
+
address: { fontSize: 12, color: '#737373' },
|
|
56
|
+
inputCard: { backgroundColor: '#171717', borderWidth: 1, borderColor: '#262626', borderRadius: 12, padding: 16 },
|
|
57
|
+
label: { fontSize: 12, color: '#737373', marginBottom: 8 },
|
|
57
58
|
labelRow: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 },
|
|
58
|
-
switchText: { fontSize: 12, color: '#
|
|
59
|
+
switchText: { fontSize: 12, color: '#737373' },
|
|
59
60
|
inputRow: { flexDirection: 'row', alignItems: 'center' },
|
|
60
|
-
input: { flex: 1, fontSize: 24, fontWeight: '500', color: '#
|
|
61
|
-
outputText: { flex: 1, fontSize: 24, fontWeight: '500', color: '#
|
|
61
|
+
input: { flex: 1, fontSize: 24, fontWeight: '500', color: '#fafafa' },
|
|
62
|
+
outputText: { flex: 1, fontSize: 24, fontWeight: '500', color: '#737373' },
|
|
62
63
|
arrow: { alignItems: 'center', marginVertical: 8 },
|
|
63
|
-
arrowBox: { width: 32, height: 32, borderWidth: 1, borderColor: '#
|
|
64
|
-
arrowText: { color: '#
|
|
65
|
-
tokenBtn: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#
|
|
66
|
-
tokenText: { fontSize: 14, fontWeight: '500', color: '#
|
|
67
|
-
tokenArrow: { fontSize: 10, color: '#
|
|
68
|
-
button: { marginTop: 16, backgroundColor: '#
|
|
69
|
-
buttonSecondary: { marginTop: 8, backgroundColor: 'transparent', borderWidth: 1, borderColor: '#
|
|
64
|
+
arrowBox: { width: 32, height: 32, backgroundColor: '#171717', borderWidth: 1, borderColor: '#262626', borderRadius: 8, alignItems: 'center', justifyContent: 'center' },
|
|
65
|
+
arrowText: { color: '#737373', fontSize: 16 },
|
|
66
|
+
tokenBtn: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#262626', paddingHorizontal: 12, paddingVertical: 8, borderRadius: 8, gap: 6 },
|
|
67
|
+
tokenText: { fontSize: 14, fontWeight: '500', color: '#fafafa' },
|
|
68
|
+
tokenArrow: { fontSize: 10, color: '#737373' },
|
|
69
|
+
button: { marginTop: 16, backgroundColor: '#fafafa', paddingVertical: 14, borderRadius: 12, alignItems: 'center' },
|
|
70
|
+
buttonSecondary: { marginTop: 8, backgroundColor: 'transparent', borderWidth: 1, borderColor: '#262626', paddingVertical: 12, borderRadius: 12, alignItems: 'center' },
|
|
70
71
|
buttonDisabled: { opacity: 0.5 },
|
|
71
|
-
buttonText: { color: '#
|
|
72
|
-
buttonTextSecondary: { color: '#
|
|
72
|
+
buttonText: { color: '#0a0a0a', fontSize: 14, fontWeight: '500' },
|
|
73
|
+
buttonTextSecondary: { color: '#fafafa', fontSize: 13, fontWeight: '500' },
|
|
73
74
|
result: { marginTop: 12, fontSize: 14, textAlign: 'center' },
|
|
74
|
-
footer: { marginTop: 16, fontSize: 12, color: '#
|
|
75
|
+
footer: { marginTop: 16, fontSize: 12, color: '#737373', textAlign: 'center' },
|
|
75
76
|
quote: { fontSize: 12, color: '#737373', marginTop: 8 },
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
slippageRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginTop: 12 },
|
|
78
|
+
slippageLabel: { fontSize: 12, color: '#737373' },
|
|
79
|
+
slippageBtn: { paddingHorizontal: 8, paddingVertical: 4, borderRadius: 4, backgroundColor: '#262626' },
|
|
80
|
+
slippageBtnActive: { backgroundColor: '#fafafa' },
|
|
81
|
+
slippageBtnText: { fontSize: 12, color: '#a3a3a3' },
|
|
82
|
+
slippageBtnTextActive: { color: '#0a0a0a' },
|
|
83
|
+
modal: { flex: 1, justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0.5)' },
|
|
84
|
+
modalContent: { backgroundColor: '#171717', borderTopLeftRadius: 16, borderTopRightRadius: 16, padding: 16, paddingBottom: 32 },
|
|
85
|
+
modalTitle: { fontSize: 16, fontWeight: '600', marginBottom: 16, textAlign: 'center', color: '#fafafa' },
|
|
86
|
+
modalItem: { paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: '#262626' },
|
|
87
|
+
modalItemText: { fontSize: 16, color: '#fafafa' },
|
|
81
88
|
});
|
|
82
89
|
<% } %>
|
|
83
90
|
export function Swap() {
|
|
@@ -153,74 +160,76 @@ export function Swap() {
|
|
|
153
160
|
return (
|
|
154
161
|
<% if (styling === 'nativewind') { %>
|
|
155
162
|
<View className="flex-1 bg-white p-6 pt-16">
|
|
156
|
-
<View className="
|
|
157
|
-
<
|
|
158
|
-
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
</View>
|
|
162
|
-
|
|
163
|
-
<View className="border border-neutral-200 rounded-xl p-4">
|
|
164
|
-
<View className="flex-row justify-between mb-2">
|
|
165
|
-
<Text className="text-xs text-neutral-400">From</Text>
|
|
166
|
-
<Text className="text-xs text-neutral-400">Balance: {(balances[fromToken.symbol] ?? 0).toFixed(4)}</Text>
|
|
167
|
-
</View>
|
|
168
|
-
<View className="flex-row items-center">
|
|
169
|
-
<TextInput className="flex-1 text-2xl font-medium text-black" placeholder="0.00" placeholderTextColor="#d4d4d4" value={amount} onChangeText={setAmount} keyboardType="numeric" />
|
|
170
|
-
<TouchableOpacity className="flex-row items-center bg-neutral-100 px-3 py-2 rounded-lg" onPress={() => setShowPicker('from')}>
|
|
171
|
-
<Text className="text-sm font-medium mr-1">{fromToken.symbol}</Text><Text className="text-xs text-neutral-400">▼</Text>
|
|
163
|
+
<View className="bg-neutral-900 rounded-2xl p-5">
|
|
164
|
+
<View className="flex-row items-center justify-between mb-6">
|
|
165
|
+
<Text className="text-lg font-semibold text-white">Swap</Text>
|
|
166
|
+
<TouchableOpacity onPress={() => disconnect()}>
|
|
167
|
+
<Text className="text-xs text-neutral-500">{addr.slice(0, 6)}...{addr.slice(-4)}</Text>
|
|
172
168
|
</TouchableOpacity>
|
|
173
169
|
</View>
|
|
174
|
-
<TouchableOpacity onPress={() => setAmount(String(balances[fromToken.symbol] ?? 0))}><Text className="text-xs text-neutral-400 mt-1">Max</Text></TouchableOpacity>
|
|
175
|
-
</View>
|
|
176
|
-
|
|
177
|
-
<View className="items-center my-2">
|
|
178
|
-
<TouchableOpacity onPress={switchTokens} className="w-8 h-8 border border-neutral-200 rounded-lg items-center justify-center"><Text className="text-neutral-400">↓</Text></TouchableOpacity>
|
|
179
|
-
</View>
|
|
180
170
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
171
|
+
<View className="bg-neutral-800 border border-neutral-700 rounded-xl p-4">
|
|
172
|
+
<View className="flex-row justify-between mb-2">
|
|
173
|
+
<Text className="text-xs text-neutral-500">From</Text>
|
|
174
|
+
<Text className="text-xs text-neutral-500">Balance: {(balances[fromToken.symbol] ?? 0).toFixed(4)}</Text>
|
|
175
|
+
</View>
|
|
176
|
+
<View className="flex-row items-center">
|
|
177
|
+
<TextInput className="flex-1 text-2xl font-medium text-white" placeholder="0.00" placeholderTextColor="#737373" value={amount} onChangeText={setAmount} keyboardType="numeric" />
|
|
178
|
+
<TouchableOpacity className="flex-row items-center bg-neutral-700 px-3 py-2 rounded-lg" onPress={() => setShowPicker('from')}>
|
|
179
|
+
<Text className="text-sm font-medium text-white mr-1">{fromToken.symbol}</Text><Text className="text-xs text-neutral-400">▼</Text>
|
|
180
|
+
</TouchableOpacity>
|
|
181
|
+
</View>
|
|
182
|
+
<TouchableOpacity onPress={() => setAmount(String(balances[fromToken.symbol] ?? 0))}><Text className="text-xs text-neutral-500 mt-1">Max</Text></TouchableOpacity>
|
|
185
183
|
</View>
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
<TouchableOpacity className="
|
|
189
|
-
<Text className="text-sm font-medium mr-1">{toToken.symbol}</Text><Text className="text-xs text-neutral-400">▼</Text>
|
|
190
|
-
</TouchableOpacity>
|
|
184
|
+
|
|
185
|
+
<View className="items-center my-2">
|
|
186
|
+
<TouchableOpacity onPress={switchTokens} className="w-8 h-8 bg-neutral-800 border border-neutral-700 rounded-lg items-center justify-center"><Text className="text-neutral-500">↓</Text></TouchableOpacity>
|
|
191
187
|
</View>
|
|
192
|
-
{quote && <Text className="text-xs text-neutral-400 mt-2">via Jupiter · {quote.routePlan?.[0]?.swapInfo?.label || 'Best route'}</Text>}
|
|
193
|
-
</View>
|
|
194
188
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
189
|
+
<View className="bg-neutral-800 border border-neutral-700 rounded-xl p-4">
|
|
190
|
+
<View className="flex-row justify-between mb-2">
|
|
191
|
+
<Text className="text-xs text-neutral-500">To</Text>
|
|
192
|
+
<Text className="text-xs text-neutral-500">Balance: {(balances[toToken.symbol] ?? 0).toFixed(4)}</Text>
|
|
193
|
+
</View>
|
|
194
|
+
<View className="flex-row items-center">
|
|
195
|
+
<Text className="flex-1 text-2xl font-medium text-neutral-500">{outputAmount}</Text>
|
|
196
|
+
<TouchableOpacity className="flex-row items-center bg-neutral-700 px-3 py-2 rounded-lg" onPress={() => setShowPicker('to')}>
|
|
197
|
+
<Text className="text-sm font-medium text-white mr-1">{toToken.symbol}</Text><Text className="text-xs text-neutral-400">▼</Text>
|
|
201
198
|
</TouchableOpacity>
|
|
202
|
-
|
|
199
|
+
</View>
|
|
200
|
+
{quote && <Text className="text-xs text-neutral-500 mt-2">via Jupiter · {quote.routePlan?.[0]?.swapInfo?.label || 'Best route'}</Text>}
|
|
201
|
+
</View>
|
|
202
|
+
|
|
203
|
+
<View className="flex-row items-center justify-between mt-3">
|
|
204
|
+
<Text className="text-xs text-neutral-500">Slippage</Text>
|
|
205
|
+
<View className="flex-row gap-1">
|
|
206
|
+
{SLIPPAGE_OPTIONS.map((s) => (
|
|
207
|
+
<TouchableOpacity key={s} onPress={() => setSlippage(s)} className={`px-2 py-1 rounded ${slippage === s ? 'bg-white' : 'bg-neutral-700'}`}>
|
|
208
|
+
<Text className={`text-xs ${slippage === s ? 'text-black' : 'text-neutral-400'}`}>{s / 100}%</Text>
|
|
209
|
+
</TouchableOpacity>
|
|
210
|
+
))}
|
|
211
|
+
</View>
|
|
203
212
|
</View>
|
|
204
|
-
</View>
|
|
205
213
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
214
|
+
<TouchableOpacity className={`mt-4 bg-white py-3.5 rounded-xl items-center ${loading || !quote ? 'opacity-50' : ''}`} onPress={handleSwap} disabled={loading || !quote}>
|
|
215
|
+
{loading ? <ActivityIndicator color="#0a0a0a" size="small" /> : <Text className="text-black text-sm font-medium">Swap</Text>}
|
|
216
|
+
</TouchableOpacity>
|
|
209
217
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
218
|
+
<TouchableOpacity className={`mt-2 border border-neutral-700 py-3 rounded-xl items-center ${signing ? 'opacity-50' : ''}`} onPress={handleSignMessage} disabled={signing}>
|
|
219
|
+
{signing ? <ActivityIndicator color="#fafafa" size="small" /> : <Text className="text-white text-sm font-medium">Sign Message</Text>}
|
|
220
|
+
</TouchableOpacity>
|
|
213
221
|
|
|
214
|
-
|
|
215
|
-
|
|
222
|
+
{result && <Text className={`mt-3 text-sm text-center ${result.success ? 'text-neutral-400' : 'text-red-400'}`}>{result.message}</Text>}
|
|
223
|
+
<Text className="mt-4 text-xs text-center text-neutral-500">Gas sponsored · Powered by LazorKit + Jupiter</Text>
|
|
224
|
+
</View>
|
|
216
225
|
|
|
217
226
|
<Modal visible={!!showPicker} transparent animationType="slide" onRequestClose={() => setShowPicker(null)}>
|
|
218
|
-
<TouchableOpacity className="flex-1 justify-end bg-black/
|
|
219
|
-
<View className="bg-
|
|
220
|
-
<Text className="text-base font-semibold text-center mb-4">Select Token</Text>
|
|
227
|
+
<TouchableOpacity className="flex-1 justify-end bg-black/50" activeOpacity={1} onPress={() => setShowPicker(null)}>
|
|
228
|
+
<View className="bg-neutral-800 rounded-t-2xl p-4 pb-8">
|
|
229
|
+
<Text className="text-base font-semibold text-center mb-4 text-white">Select Token</Text>
|
|
221
230
|
{TOKENS.filter(t => t.symbol !== (showPicker === 'from' ? toToken.symbol : fromToken.symbol)).map(t => (
|
|
222
|
-
<TouchableOpacity key={t.symbol} className="py-3.5 border-b border-neutral-
|
|
223
|
-
<Text className="text-base">{t.symbol}</Text>
|
|
231
|
+
<TouchableOpacity key={t.symbol} className="py-3.5 border-b border-neutral-700" onPress={() => { showPicker === 'from' ? setFromToken(t) : setToToken(t); setShowPicker(null); }}>
|
|
232
|
+
<Text className="text-base text-white">{t.symbol}</Text>
|
|
224
233
|
</TouchableOpacity>
|
|
225
234
|
))}
|
|
226
235
|
</View>
|
|
@@ -229,62 +238,64 @@ export function Swap() {
|
|
|
229
238
|
</View>
|
|
230
239
|
<% } else { %>
|
|
231
240
|
<View style={styles.container}>
|
|
232
|
-
<View style={styles.header}>
|
|
233
|
-
<Text style={styles.title}>Swap</Text>
|
|
234
|
-
<TouchableOpacity onPress={() => disconnect()}><Text style={styles.address}>{addr.slice(0, 6)}...{addr.slice(-4)}</Text></TouchableOpacity>
|
|
235
|
-
</View>
|
|
236
|
-
|
|
237
241
|
<View style={styles.card}>
|
|
238
|
-
<View style={styles.
|
|
239
|
-
<Text style={styles.
|
|
240
|
-
<Text style={styles.
|
|
242
|
+
<View style={styles.header}>
|
|
243
|
+
<Text style={styles.title}>Swap</Text>
|
|
244
|
+
<TouchableOpacity onPress={() => disconnect()}><Text style={styles.address}>{addr.slice(0, 6)}...{addr.slice(-4)}</Text></TouchableOpacity>
|
|
241
245
|
</View>
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
<
|
|
245
|
-
<Text style={styles.
|
|
246
|
-
|
|
246
|
+
|
|
247
|
+
<View style={styles.inputCard}>
|
|
248
|
+
<View style={styles.labelRow}>
|
|
249
|
+
<Text style={styles.label}>From</Text>
|
|
250
|
+
<Text style={styles.label}>Balance: {(balances[fromToken.symbol] ?? 0).toFixed(4)}</Text>
|
|
251
|
+
</View>
|
|
252
|
+
<View style={styles.inputRow}>
|
|
253
|
+
<TextInput style={styles.input} placeholder="0.00" placeholderTextColor="#737373" value={amount} onChangeText={setAmount} keyboardType="numeric" />
|
|
254
|
+
<TouchableOpacity style={styles.tokenBtn} onPress={() => setShowPicker('from')}>
|
|
255
|
+
<Text style={styles.tokenText}>{fromToken.symbol}</Text><Text style={styles.tokenArrow}>▼</Text>
|
|
256
|
+
</TouchableOpacity>
|
|
257
|
+
</View>
|
|
258
|
+
<TouchableOpacity onPress={() => setAmount(String(balances[fromToken.symbol] ?? 0))}><Text style={styles.switchText}>Max</Text></TouchableOpacity>
|
|
247
259
|
</View>
|
|
248
|
-
<TouchableOpacity onPress={() => setAmount(String(balances[fromToken.symbol] ?? 0))}><Text style={styles.switchText}>Max</Text></TouchableOpacity>
|
|
249
|
-
</View>
|
|
250
260
|
|
|
251
|
-
|
|
261
|
+
<View style={styles.arrow}><TouchableOpacity onPress={switchTokens} style={styles.arrowBox}><Text style={styles.arrowText}>↓</Text></TouchableOpacity></View>
|
|
252
262
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
+
<View style={styles.inputCard}>
|
|
264
|
+
<View style={styles.labelRow}>
|
|
265
|
+
<Text style={styles.label}>To</Text>
|
|
266
|
+
<Text style={styles.label}>Balance: {(balances[toToken.symbol] ?? 0).toFixed(4)}</Text>
|
|
267
|
+
</View>
|
|
268
|
+
<View style={styles.inputRow}>
|
|
269
|
+
<Text style={styles.outputText}>{outputAmount}</Text>
|
|
270
|
+
<TouchableOpacity style={styles.tokenBtn} onPress={() => setShowPicker('to')}>
|
|
271
|
+
<Text style={styles.tokenText}>{toToken.symbol}</Text><Text style={styles.tokenArrow}>▼</Text>
|
|
272
|
+
</TouchableOpacity>
|
|
273
|
+
</View>
|
|
274
|
+
{quote && <Text style={styles.quote}>via Jupiter · {quote.routePlan?.[0]?.swapInfo?.label || 'Best route'}</Text>}
|
|
263
275
|
</View>
|
|
264
|
-
{quote && <Text style={styles.quote}>via Jupiter · {quote.routePlan?.[0]?.swapInfo?.label || 'Best route'}</Text>}
|
|
265
|
-
</View>
|
|
266
276
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
277
|
+
<View style={styles.slippageRow}>
|
|
278
|
+
<Text style={styles.slippageLabel}>Slippage</Text>
|
|
279
|
+
<View style={{ flexDirection: 'row', gap: 4 }}>
|
|
280
|
+
{SLIPPAGE_OPTIONS.map((s) => (
|
|
281
|
+
<TouchableOpacity key={s} onPress={() => setSlippage(s)} style={[styles.slippageBtn, slippage === s && styles.slippageBtnActive]}>
|
|
282
|
+
<Text style={[styles.slippageBtnText, slippage === s && styles.slippageBtnTextActive]}>{s / 100}%</Text>
|
|
283
|
+
</TouchableOpacity>
|
|
284
|
+
))}
|
|
285
|
+
</View>
|
|
275
286
|
</View>
|
|
276
|
-
</View>
|
|
277
287
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
288
|
+
<TouchableOpacity style={[styles.button, (loading || !quote) && styles.buttonDisabled]} onPress={handleSwap} disabled={loading || !quote}>
|
|
289
|
+
{loading ? <ActivityIndicator color="#0a0a0a" size="small" /> : <Text style={styles.buttonText}>Swap</Text>}
|
|
290
|
+
</TouchableOpacity>
|
|
281
291
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
292
|
+
<TouchableOpacity style={[styles.buttonSecondary, signing && styles.buttonDisabled]} onPress={handleSignMessage} disabled={signing}>
|
|
293
|
+
{signing ? <ActivityIndicator color="#fafafa" size="small" /> : <Text style={styles.buttonTextSecondary}>Sign Message</Text>}
|
|
294
|
+
</TouchableOpacity>
|
|
285
295
|
|
|
286
|
-
|
|
287
|
-
|
|
296
|
+
{result && <Text style={[styles.result, { color: result.success ? '#737373' : '#ef4444' }]}>{result.message}</Text>}
|
|
297
|
+
<Text style={styles.footer}>Gas sponsored · Powered by LazorKit + Jupiter</Text>
|
|
298
|
+
</View>
|
|
288
299
|
|
|
289
300
|
<Modal visible={!!showPicker} transparent animationType="slide" onRequestClose={() => setShowPicker(null)}>
|
|
290
301
|
<TouchableOpacity style={styles.modal} activeOpacity={1} onPress={() => setShowPicker(null)}>
|
|
@@ -3,18 +3,18 @@ import { useWallet } from "@lazorkit/wallet";
|
|
|
3
3
|
import { Connection, PublicKey } from "@solana/web3.js";
|
|
4
4
|
<% if (styling !== 'tailwind') { %>
|
|
5
5
|
const styles: Record<string, React.CSSProperties> = {
|
|
6
|
-
container: { width: '100%', maxWidth: 360 },
|
|
6
|
+
container: { width: '100%', maxWidth: 360, background: '#0a0a0a', borderRadius: 16, padding: 24, color: '#fafafa' },
|
|
7
7
|
header: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 },
|
|
8
|
-
title: { fontSize: 18, fontWeight: 600, margin: 0 },
|
|
8
|
+
title: { fontSize: 18, fontWeight: 600, margin: 0, color: '#fafafa' },
|
|
9
9
|
list: { display: 'flex', flexDirection: 'column', gap: 8 },
|
|
10
|
-
item: { border: '1px solid #
|
|
10
|
+
item: { border: '1px solid #262626', borderRadius: 12, padding: 12, textDecoration: 'none', color: '#fafafa', background: '#171717' },
|
|
11
11
|
row: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' },
|
|
12
|
-
sig: { fontFamily: 'monospace', fontSize: 13, color: '#
|
|
13
|
-
time: { fontSize: 12, color: '#
|
|
12
|
+
sig: { fontFamily: 'monospace', fontSize: 13, color: '#fafafa' },
|
|
13
|
+
time: { fontSize: 12, color: '#737373', marginTop: 4 },
|
|
14
14
|
status: { fontSize: 11, padding: '2px 6px', borderRadius: 4 },
|
|
15
|
-
success: { backgroundColor: '#
|
|
16
|
-
failed: { backgroundColor: '#
|
|
17
|
-
empty: { textAlign: 'center', padding: 32, color: '#
|
|
15
|
+
success: { backgroundColor: '#14532d', color: '#4ade80' },
|
|
16
|
+
failed: { backgroundColor: '#7f1d1d', color: '#f87171' },
|
|
17
|
+
empty: { textAlign: 'center', padding: 32, color: '#737373', fontSize: 14 },
|
|
18
18
|
back: { fontSize: 13, color: '#737373', background: 'none', border: 'none', cursor: 'pointer' },
|
|
19
19
|
};
|
|
20
20
|
<% } %>
|
|
@@ -56,26 +56,26 @@ export function History({ onBack }: Props) {
|
|
|
56
56
|
|
|
57
57
|
return (
|
|
58
58
|
<% if (styling === 'tailwind') { %>
|
|
59
|
-
<div className="w-full max-w-sm">
|
|
59
|
+
<div className="w-full max-w-sm bg-neutral-900 rounded-2xl p-6 text-white">
|
|
60
60
|
<div className="flex items-center justify-between mb-4">
|
|
61
61
|
<h1 className="text-lg font-semibold">History</h1>
|
|
62
|
-
<button onClick={onBack} className="text-sm text-neutral-500 hover:text-
|
|
62
|
+
<button onClick={onBack} className="text-sm text-neutral-500 hover:text-white">← Back</button>
|
|
63
63
|
</div>
|
|
64
64
|
{loading ? (
|
|
65
|
-
<p className="text-center py-8 text-neutral-
|
|
65
|
+
<p className="text-center py-8 text-neutral-500">Loading...</p>
|
|
66
66
|
) : txs.length === 0 ? (
|
|
67
|
-
<p className="text-center py-8 text-neutral-
|
|
67
|
+
<p className="text-center py-8 text-neutral-500">No transactions yet</p>
|
|
68
68
|
) : (
|
|
69
69
|
<div className="space-y-2">
|
|
70
70
|
{txs.map((tx) => (
|
|
71
|
-
<a key={tx.signature} href={explorerUrl(tx.signature)} target="_blank" rel="noopener noreferrer" className="block border border-neutral-
|
|
71
|
+
<a key={tx.signature} href={explorerUrl(tx.signature)} target="_blank" rel="noopener noreferrer" className="block border border-neutral-700 rounded-xl p-3 bg-neutral-800 hover:bg-neutral-700">
|
|
72
72
|
<div className="flex justify-between items-center">
|
|
73
73
|
<span className="font-mono text-sm">{tx.signature.slice(0, 8)}...{tx.signature.slice(-8)}</span>
|
|
74
|
-
<span className={`text-xs px-2 py-0.5 rounded ${tx.err ? "bg-red-
|
|
74
|
+
<span className={`text-xs px-2 py-0.5 rounded ${tx.err ? "bg-red-900 text-red-400" : "bg-green-900 text-green-400"}`}>
|
|
75
75
|
{tx.err ? "Failed" : "Success"}
|
|
76
76
|
</span>
|
|
77
77
|
</div>
|
|
78
|
-
<p className="text-xs text-neutral-
|
|
78
|
+
<p className="text-xs text-neutral-500 mt-1">{formatTime(tx.blockTime)}</p>
|
|
79
79
|
</a>
|
|
80
80
|
))}
|
|
81
81
|
</div>
|
|
@@ -2,15 +2,15 @@ import { useState } from "react";
|
|
|
2
2
|
import { useWallet } from "@lazorkit/wallet";
|
|
3
3
|
<% if (styling !== 'tailwind') { %>
|
|
4
4
|
const styles: Record<string, React.CSSProperties> = {
|
|
5
|
-
container: { width: '100%', maxWidth: 360 },
|
|
6
|
-
title: { fontSize: 18, fontWeight: 600, margin: 0 },
|
|
5
|
+
container: { width: '100%', maxWidth: 360, background: '#0a0a0a', borderRadius: 16, padding: 24, color: '#fafafa' },
|
|
6
|
+
title: { fontSize: 18, fontWeight: 600, margin: 0, color: '#fafafa' },
|
|
7
7
|
subtitle: { marginTop: 8, fontSize: 14, color: '#737373', lineHeight: 1.5 },
|
|
8
|
-
card: { marginTop: 16, border: '1px solid #
|
|
9
|
-
cardTitle: { fontSize: 14, fontWeight: 500, margin: 0 },
|
|
8
|
+
card: { marginTop: 16, border: '1px solid #262626', borderRadius: 12, padding: 16, background: '#171717' },
|
|
9
|
+
cardTitle: { fontSize: 14, fontWeight: 500, margin: 0, color: '#fafafa' },
|
|
10
10
|
cardDesc: { marginTop: 4, fontSize: 13, color: '#737373' },
|
|
11
|
-
button: { marginTop: 12, width: '100%', backgroundColor: '#
|
|
12
|
-
buttonSecondary: { marginTop: 12, width: '100%', backgroundColor: 'transparent', color: '#
|
|
13
|
-
info: { marginTop: 16, padding: 12, backgroundColor: '#
|
|
11
|
+
button: { marginTop: 12, width: '100%', backgroundColor: '#fafafa', color: '#0a0a0a', padding: '12px 16px', borderRadius: 10, border: 'none', fontSize: 14, fontWeight: 500, cursor: 'pointer' },
|
|
12
|
+
buttonSecondary: { marginTop: 12, width: '100%', backgroundColor: 'transparent', color: '#fafafa', padding: '12px 16px', borderRadius: 10, border: '1px solid #262626', fontSize: 14, fontWeight: 500, cursor: 'pointer' },
|
|
13
|
+
info: { marginTop: 16, padding: 12, backgroundColor: '#171717', borderRadius: 8, fontSize: 12, color: '#a3a3a3' },
|
|
14
14
|
back: { marginTop: 16, fontSize: 13, color: '#737373', background: 'none', border: 'none', cursor: 'pointer' },
|
|
15
15
|
};
|
|
16
16
|
<% } %>
|
|
@@ -41,36 +41,36 @@ export function Recovery({ onBack }: Props) {
|
|
|
41
41
|
|
|
42
42
|
return (
|
|
43
43
|
<% if (styling === 'tailwind') { %>
|
|
44
|
-
<div className="w-full max-w-sm">
|
|
44
|
+
<div className="w-full max-w-sm bg-neutral-900 rounded-2xl p-6 text-white">
|
|
45
45
|
<h1 className="text-lg font-semibold">Recovery & Backup</h1>
|
|
46
46
|
<p className="mt-2 text-sm text-neutral-500">
|
|
47
47
|
Add backup passkeys from other devices to ensure you never lose access.
|
|
48
48
|
</p>
|
|
49
|
-
<div className="mt-4 border border-neutral-
|
|
49
|
+
<div className="mt-4 border border-neutral-700 rounded-xl p-4 bg-neutral-800">
|
|
50
50
|
<h3 className="text-sm font-medium">Add Backup Device</h3>
|
|
51
51
|
<p className="mt-1 text-xs text-neutral-500">
|
|
52
52
|
Register a passkey from another phone, tablet, or computer.
|
|
53
53
|
</p>
|
|
54
|
-
<button onClick={handleAddDevice} className="mt-3 w-full py-3 bg-
|
|
54
|
+
<button onClick={handleAddDevice} className="mt-3 w-full py-3 bg-white text-black text-sm font-medium rounded-lg hover:opacity-90">
|
|
55
55
|
Add Device
|
|
56
56
|
</button>
|
|
57
57
|
</div>
|
|
58
|
-
<div className="mt-3 border border-neutral-
|
|
58
|
+
<div className="mt-3 border border-neutral-700 rounded-xl p-4 bg-neutral-800">
|
|
59
59
|
<h3 className="text-sm font-medium">Manage Devices</h3>
|
|
60
60
|
<p className="mt-1 text-xs text-neutral-500">
|
|
61
61
|
View and remove registered passkeys.
|
|
62
62
|
</p>
|
|
63
|
-
<button onClick={handleManageDevices} className="mt-3 w-full py-3 bg-transparent text-
|
|
63
|
+
<button onClick={handleManageDevices} className="mt-3 w-full py-3 bg-transparent text-white text-sm font-medium rounded-lg border border-neutral-700 hover:bg-neutral-700">
|
|
64
64
|
View Devices
|
|
65
65
|
</button>
|
|
66
66
|
</div>
|
|
67
|
-
<div className="mt-4 p-3 bg-neutral-
|
|
68
|
-
<p className="text-xs text-neutral-
|
|
67
|
+
<div className="mt-4 p-3 bg-neutral-800 rounded-lg">
|
|
68
|
+
<p className="text-xs text-neutral-400">
|
|
69
69
|
<strong>Wallet:</strong>{" "}
|
|
70
|
-
<button onClick={copyAddress} className="font-mono hover:text-
|
|
70
|
+
<button onClick={copyAddress} className="font-mono hover:text-white">
|
|
71
71
|
{wallet?.smartWallet?.slice(0, 8)}...{wallet?.smartWallet?.slice(-8)}
|
|
72
72
|
</button>
|
|
73
|
-
{copied && <span className="ml-2 text-green-
|
|
73
|
+
{copied && <span className="ml-2 text-green-400">Copied!</span>}
|
|
74
74
|
</p>
|
|
75
75
|
</div>
|
|
76
76
|
<button onClick={onBack} className="mt-4 text-sm text-neutral-500 hover:text-black">
|