@nockchain/rose 0.1.4-nightly.5

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 (205) hide show
  1. package/.github/workflows/artifacts.yml +33 -0
  2. package/.github/workflows/ci.yml +68 -0
  3. package/.github/workflows/publish-sdk.yml +35 -0
  4. package/.nvmrc +1 -0
  5. package/.prettierignore +5 -0
  6. package/.prettierrc +8 -0
  7. package/LICENSE +22 -0
  8. package/README.md +117 -0
  9. package/extension/background/index.ts +1500 -0
  10. package/extension/content/index.ts +59 -0
  11. package/extension/icons/rose.svg +27 -0
  12. package/extension/icons/rose128.png +0 -0
  13. package/extension/icons/rose16.png +0 -0
  14. package/extension/icons/rose256.png +0 -0
  15. package/extension/icons/rose32.png +0 -0
  16. package/extension/icons/rose48.png +0 -0
  17. package/extension/icons/rose512.png +0 -0
  18. package/extension/inpage/index.ts +86 -0
  19. package/extension/manifest.json +48 -0
  20. package/extension/popup/Popup.tsx +94 -0
  21. package/extension/popup/Router.tsx +121 -0
  22. package/extension/popup/assets/arrow-down-icon.svg +3 -0
  23. package/extension/popup/assets/arrow-left-icon.svg +3 -0
  24. package/extension/popup/assets/arrow-right-icon.svg +3 -0
  25. package/extension/popup/assets/arrow-up-icon.svg +3 -0
  26. package/extension/popup/assets/arrow-up-right-icon.svg +3 -0
  27. package/extension/popup/assets/checkmark-icon.svg +3 -0
  28. package/extension/popup/assets/checkmark-pencil-icon.svg +3 -0
  29. package/extension/popup/assets/checkmark-success-icon.svg +3 -0
  30. package/extension/popup/assets/clock-icon.svg +3 -0
  31. package/extension/popup/assets/close-x-icon.svg +3 -0
  32. package/extension/popup/assets/copy-icon.svg +6 -0
  33. package/extension/popup/assets/explorer-icon.svg +3 -0
  34. package/extension/popup/assets/eye-off-icon.svg +3 -0
  35. package/extension/popup/assets/eye-open-icon.svg +4 -0
  36. package/extension/popup/assets/feedback-icon.svg +3 -0
  37. package/extension/popup/assets/green-status-dot.svg +3 -0
  38. package/extension/popup/assets/info-icon.svg +3 -0
  39. package/extension/popup/assets/iris-logo-40.svg +27 -0
  40. package/extension/popup/assets/iris-logo-96.svg +27 -0
  41. package/extension/popup/assets/iris-logo-blue.svg +27 -0
  42. package/extension/popup/assets/iris-logo-no-eye.svg +27 -0
  43. package/extension/popup/assets/iris-logo-orange.svg +27 -0
  44. package/extension/popup/assets/iris-logo.svg +27 -0
  45. package/extension/popup/assets/key-icon.svg +3 -0
  46. package/extension/popup/assets/lock-icon-yellow.svg +3 -0
  47. package/extension/popup/assets/lock-icon.svg +3 -0
  48. package/extension/popup/assets/pencil-edit-icon.svg +3 -0
  49. package/extension/popup/assets/permissions-icon.svg +3 -0
  50. package/extension/popup/assets/receipt-icon.svg +5 -0
  51. package/extension/popup/assets/refresh-icon.svg +3 -0
  52. package/extension/popup/assets/settings-gear-icon.svg +8 -0
  53. package/extension/popup/assets/settings-icon.svg +3 -0
  54. package/extension/popup/assets/theme-icon.svg +3 -0
  55. package/extension/popup/assets/trash-bin-icon.svg +3 -0
  56. package/extension/popup/assets/trend-down-arrow.svg +5 -0
  57. package/extension/popup/assets/trend-up-arrow.svg +5 -0
  58. package/extension/popup/assets/user-account-icon.svg +3 -0
  59. package/extension/popup/assets/vector-bottom-left.svg +9 -0
  60. package/extension/popup/assets/vector-left.svg +9 -0
  61. package/extension/popup/assets/vector-right.svg +9 -0
  62. package/extension/popup/assets/vector-top-right-rotated.svg +8 -0
  63. package/extension/popup/assets/vector-top-right.svg +9 -0
  64. package/extension/popup/assets/wallet-dropdown-arrow.svg +5 -0
  65. package/extension/popup/assets/wallet-icon-style-1.svg +6 -0
  66. package/extension/popup/assets/wallet-icon-style-10.svg +8 -0
  67. package/extension/popup/assets/wallet-icon-style-11.svg +8 -0
  68. package/extension/popup/assets/wallet-icon-style-12.svg +8 -0
  69. package/extension/popup/assets/wallet-icon-style-13.svg +8 -0
  70. package/extension/popup/assets/wallet-icon-style-14.svg +8 -0
  71. package/extension/popup/assets/wallet-icon-style-15.svg +8 -0
  72. package/extension/popup/assets/wallet-icon-style-2.svg +8 -0
  73. package/extension/popup/assets/wallet-icon-style-3.svg +8 -0
  74. package/extension/popup/assets/wallet-icon-style-4.svg +8 -0
  75. package/extension/popup/assets/wallet-icon-style-5.svg +8 -0
  76. package/extension/popup/assets/wallet-icon-style-6.svg +8 -0
  77. package/extension/popup/assets/wallet-icon-style-7.svg +8 -0
  78. package/extension/popup/assets/wallet-icon-style-8.svg +8 -0
  79. package/extension/popup/assets/wallet-icon-style-9.svg +8 -0
  80. package/extension/popup/components/AccountIcon.tsx +78 -0
  81. package/extension/popup/components/AccountSelector.tsx +246 -0
  82. package/extension/popup/components/Alert.tsx +48 -0
  83. package/extension/popup/components/ConfirmModal.tsx +81 -0
  84. package/extension/popup/components/PasswordInput.tsx +49 -0
  85. package/extension/popup/components/ScreenContainer.tsx +17 -0
  86. package/extension/popup/components/SiteIcon.tsx +60 -0
  87. package/extension/popup/components/ThemeToggle.tsx +44 -0
  88. package/extension/popup/components/icons/ArrowDownLeftIcon.tsx +20 -0
  89. package/extension/popup/components/icons/ArrowUpRightIcon.tsx +20 -0
  90. package/extension/popup/components/icons/CheckIcon.tsx +20 -0
  91. package/extension/popup/components/icons/ChevronDownIcon.tsx +15 -0
  92. package/extension/popup/components/icons/ChevronLeftIcon.tsx +15 -0
  93. package/extension/popup/components/icons/ChevronRightIcon.tsx +15 -0
  94. package/extension/popup/components/icons/ChevronUpIcon.tsx +15 -0
  95. package/extension/popup/components/icons/CloseIcon.tsx +26 -0
  96. package/extension/popup/components/icons/CopyIcon.tsx +20 -0
  97. package/extension/popup/components/icons/EditIcon.tsx +20 -0
  98. package/extension/popup/components/icons/EyeIcon.tsx +13 -0
  99. package/extension/popup/components/icons/EyeOffIcon.tsx +13 -0
  100. package/extension/popup/components/icons/InfoIcon.tsx +20 -0
  101. package/extension/popup/components/icons/LockIcon.tsx +20 -0
  102. package/extension/popup/components/icons/PlusIcon.tsx +15 -0
  103. package/extension/popup/components/icons/ReceiveArrowIcon.tsx +14 -0
  104. package/extension/popup/components/icons/ReceiveCircleIcon.tsx +20 -0
  105. package/extension/popup/components/icons/SendPaperPlaneIcon.tsx +18 -0
  106. package/extension/popup/components/icons/SentArrowIcon.tsx +21 -0
  107. package/extension/popup/components/icons/SettingsIcon.tsx +26 -0
  108. package/extension/popup/components/icons/ShieldIcon.tsx +20 -0
  109. package/extension/popup/components/icons/UploadIcon.tsx +20 -0
  110. package/extension/popup/components/icons/WalletIcon.tsx +20 -0
  111. package/extension/popup/contexts/ThemeContext.tsx +105 -0
  112. package/extension/popup/hooks/useApprovalDetection.ts +128 -0
  113. package/extension/popup/hooks/useAutoFocus.ts +36 -0
  114. package/extension/popup/hooks/useAutoRejectOnClose.ts +25 -0
  115. package/extension/popup/hooks/useClickOutside.ts +33 -0
  116. package/extension/popup/hooks/useCopyToClipboard.ts +33 -0
  117. package/extension/popup/hooks/useFavicon.ts +64 -0
  118. package/extension/popup/hooks/useNumericInput.ts +93 -0
  119. package/extension/popup/index.html +13 -0
  120. package/extension/popup/index.tsx +24 -0
  121. package/extension/popup/screens/AboutScreen.tsx +118 -0
  122. package/extension/popup/screens/HomeScreen.tailwind.css +85 -0
  123. package/extension/popup/screens/HomeScreen.tsx +902 -0
  124. package/extension/popup/screens/KeySettingsPasswordScreen.tsx +164 -0
  125. package/extension/popup/screens/LockTimeScreen.tsx +155 -0
  126. package/extension/popup/screens/ReceiveScreen.tsx +149 -0
  127. package/extension/popup/screens/RecoveryPhraseScreen.tsx +183 -0
  128. package/extension/popup/screens/SendReviewScreen.tsx +308 -0
  129. package/extension/popup/screens/SendScreen.tsx +825 -0
  130. package/extension/popup/screens/SendSubmittedScreen.tsx +193 -0
  131. package/extension/popup/screens/SettingsScreen.tsx +116 -0
  132. package/extension/popup/screens/ThemeSettingsScreen.tsx +107 -0
  133. package/extension/popup/screens/TransactionDetailsScreen.tsx +346 -0
  134. package/extension/popup/screens/ViewSecretPhraseScreen.tsx +212 -0
  135. package/extension/popup/screens/WalletPermissionsScreen.tsx +123 -0
  136. package/extension/popup/screens/WalletSettingsScreen.tsx +381 -0
  137. package/extension/popup/screens/WalletStylingScreen.tsx +306 -0
  138. package/extension/popup/screens/approvals/ConnectApprovalScreen.tsx +136 -0
  139. package/extension/popup/screens/approvals/SignMessageScreen.tsx +140 -0
  140. package/extension/popup/screens/approvals/SignRawTxScreen.tsx +320 -0
  141. package/extension/popup/screens/approvals/TransactionApprovalScreen.tsx +167 -0
  142. package/extension/popup/screens/onboarding/BackupScreen.tsx +254 -0
  143. package/extension/popup/screens/onboarding/CreateScreen.tsx +273 -0
  144. package/extension/popup/screens/onboarding/ImportScreen.tsx +676 -0
  145. package/extension/popup/screens/onboarding/ImportScreenV0.tsx +678 -0
  146. package/extension/popup/screens/onboarding/ImportSuccessScreen.tsx +236 -0
  147. package/extension/popup/screens/onboarding/ResumeBackupScreen.tsx +166 -0
  148. package/extension/popup/screens/onboarding/StartScreen.tsx +142 -0
  149. package/extension/popup/screens/onboarding/SuccessScreen.tsx +193 -0
  150. package/extension/popup/screens/onboarding/VerifyScreen.tsx +220 -0
  151. package/extension/popup/screens/system/LockedScreen.tsx +288 -0
  152. package/extension/popup/screens/transactions/ReceiveScreen.tsx +84 -0
  153. package/extension/popup/screens/transactions/SentScreen.tsx +138 -0
  154. package/extension/popup/store.ts +482 -0
  155. package/extension/popup/styles.css +246 -0
  156. package/extension/popup/utils/format.ts +58 -0
  157. package/extension/popup/utils/formatWalletError.ts +36 -0
  158. package/extension/popup/utils/memo.ts +299 -0
  159. package/extension/popup/utils/messaging.ts +16 -0
  160. package/extension/shared/address-encoding.ts +69 -0
  161. package/extension/shared/balance-query.ts +123 -0
  162. package/extension/shared/constants.ts +386 -0
  163. package/extension/shared/currency.ts +128 -0
  164. package/extension/shared/first-name-derivation.ts +128 -0
  165. package/extension/shared/keyfile.ts +58 -0
  166. package/extension/shared/onboarding.ts +78 -0
  167. package/extension/shared/price-api.ts +79 -0
  168. package/extension/shared/rpc-client-browser.ts +315 -0
  169. package/extension/shared/transaction-builder.ts +443 -0
  170. package/extension/shared/types.ts +450 -0
  171. package/extension/shared/utxo-diff.ts +212 -0
  172. package/extension/shared/utxo-store.ts +548 -0
  173. package/extension/shared/utxo-sync.ts +343 -0
  174. package/extension/shared/validators.ts +26 -0
  175. package/extension/shared/vault.ts +1580 -0
  176. package/extension/shared/wallet-crypto.ts +77 -0
  177. package/extension/shared/wasm-utils.ts +76 -0
  178. package/extension/shared/webcrypto.ts +67 -0
  179. package/extension/types/wasm.d.ts +13 -0
  180. package/package.json +39 -0
  181. package/postcss.config.js +6 -0
  182. package/rose-extension-dist.zip +0 -0
  183. package/sdk/README.md +88 -0
  184. package/sdk/examples/app.ts +166 -0
  185. package/sdk/examples/index.html +51 -0
  186. package/sdk/examples/tsconfig.json +15 -0
  187. package/sdk/examples/tx-builder.html +532 -0
  188. package/sdk/examples/tx-builder.ts +1766 -0
  189. package/sdk/package-lock.json +424 -0
  190. package/sdk/package.json +68 -0
  191. package/sdk/src/constants.ts +28 -0
  192. package/sdk/src/errors.ts +74 -0
  193. package/sdk/src/hooks/index.ts +1 -0
  194. package/sdk/src/hooks/use-rose.ts +94 -0
  195. package/sdk/src/index.ts +12 -0
  196. package/sdk/src/provider.ts +396 -0
  197. package/sdk/src/transaction.ts +163 -0
  198. package/sdk/src/types/rose-wasm.d.ts +14 -0
  199. package/sdk/src/types.ts +97 -0
  200. package/sdk/src/wasm.ts +13 -0
  201. package/sdk/tsconfig.json +20 -0
  202. package/sdk/vite.config.examples.ts +32 -0
  203. package/tailwind.config.ts +38 -0
  204. package/tsconfig.json +20 -0
  205. package/vite.config.ts +60 -0
@@ -0,0 +1,193 @@
1
+ import { useStore } from '../store';
2
+ import { ChevronLeftIcon } from '../components/icons/ChevronLeftIcon';
3
+ import { SendPaperPlaneIcon } from '../components/icons/SendPaperPlaneIcon';
4
+ import { PlusIcon } from '../components/icons/PlusIcon';
5
+
6
+ export function SendSubmittedScreen() {
7
+ const { navigate, lastTransaction, priceUsd } = useStore();
8
+
9
+ function handleBack() {
10
+ navigate('home');
11
+ }
12
+ function handleViewActivity() {
13
+ navigate('home'); // show transactions on home
14
+ }
15
+
16
+ // Dev function: Download transaction protobuf for debugging
17
+ function handleDownloadTx() {
18
+ if (!lastTransaction?.protobufTx) {
19
+ console.warn('[SendSubmitted] No transaction data available to download');
20
+ return;
21
+ }
22
+
23
+ try {
24
+ // Convert protobuf object to JSON string
25
+ const txJson = JSON.stringify(lastTransaction.protobufTx, null, 2);
26
+ const blob = new Blob([txJson], { type: 'application/json' });
27
+ const url = URL.createObjectURL(blob);
28
+ const a = document.createElement('a');
29
+ a.href = url;
30
+ a.download = `tx-${lastTransaction.txid || 'unsigned'}.json`;
31
+ a.click();
32
+ URL.revokeObjectURL(url);
33
+ } catch (err) {
34
+ console.error('[SendSubmitted] Failed to download transaction:', err);
35
+ }
36
+ }
37
+
38
+ // Get real transaction data
39
+ const sentAmount =
40
+ lastTransaction?.amount.toLocaleString('en-US', {
41
+ maximumFractionDigits: 0,
42
+ }) || '0';
43
+
44
+ // Calculate USD value based on amount and current price
45
+ const amountInNock = lastTransaction?.amount || 0;
46
+ const usdValue = amountInNock * priceUsd;
47
+ const sentUsdValue =
48
+ usdValue > 0
49
+ ? `$${usdValue.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
50
+ : '$0.00';
51
+
52
+ return (
53
+ <div
54
+ className="w-[357px] h-[600px] flex flex-col"
55
+ style={{ backgroundColor: 'var(--color-bg)' }}
56
+ >
57
+ {/* Header */}
58
+ <header
59
+ className="flex items-center justify-between px-4 py-3 min-h-[64px]"
60
+ style={{ backgroundColor: 'var(--color-bg)' }}
61
+ >
62
+ <button
63
+ type="button"
64
+ onClick={handleBack}
65
+ aria-label="Back"
66
+ className="w-8 h-8 p-2 rounded-lg flex items-center justify-center hover:opacity-70 transition-opacity"
67
+ style={{ color: 'var(--color-text-primary)' }}
68
+ >
69
+ <ChevronLeftIcon className="w-5 h-5" />
70
+ </button>
71
+ <h1
72
+ className="m-0 text-base font-medium leading-[22px] tracking-[0.16px]"
73
+ style={{ color: 'var(--color-text-primary)' }}
74
+ >
75
+ Submitted
76
+ </h1>
77
+ <div className="w-8 h-8" />
78
+ </header>
79
+
80
+ {/* Content */}
81
+ <div className="flex flex-col h-[536px]" style={{ backgroundColor: 'var(--color-bg)' }}>
82
+ <div className="flex flex-col gap-8 px-4 py-2 flex-1">
83
+ {/* Success Section */}
84
+ <div className="flex flex-col items-center gap-3 w-full">
85
+ <div
86
+ className="w-10 h-10 flex items-center justify-center"
87
+ style={{ color: 'var(--color-primary)' }}
88
+ >
89
+ <SendPaperPlaneIcon className="w-10 h-10" />
90
+ </div>
91
+ <div className="flex flex-col items-center gap-2 w-full text-center">
92
+ <h2
93
+ className="m-0 font-[Lora] text-2xl font-medium leading-7 tracking-[-0.48px]"
94
+ style={{ color: 'var(--color-text-primary)' }}
95
+ >
96
+ Your transaction
97
+ <br />
98
+ was submitted
99
+ </h2>
100
+ <p
101
+ className="m-0 text-[13px] leading-[18px] tracking-[0.26px]"
102
+ style={{ color: 'var(--color-text-muted)' }}
103
+ >
104
+ Check the transaction activity below
105
+ </p>
106
+ </div>
107
+ </div>
108
+
109
+ {/* Transaction Summary */}
110
+ <div className="flex flex-col gap-2 w-full">
111
+ <div
112
+ className="rounded-lg p-3 flex items-start justify-between gap-2.5"
113
+ style={{ backgroundColor: 'var(--color-surface-900)' }}
114
+ >
115
+ <div
116
+ className="text-sm font-medium leading-[18px] tracking-[0.14px]"
117
+ style={{ color: 'var(--color-text-primary)' }}
118
+ >
119
+ You sent
120
+ </div>
121
+ <div className="flex flex-col items-end gap-1 text-right">
122
+ <div
123
+ className="text-sm font-medium leading-[18px] tracking-[0.14px] whitespace-nowrap"
124
+ style={{ color: 'var(--color-text-primary)' }}
125
+ >
126
+ {sentAmount} NOCK
127
+ </div>
128
+ <div
129
+ className="text-[13px] leading-[18px] tracking-[0.26px]"
130
+ style={{ color: 'var(--color-text-muted)' }}
131
+ >
132
+ {sentUsdValue}
133
+ </div>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ </div>
138
+
139
+ {/* Activity Log Button (commented out - not in use) */}
140
+ {/* <div className="px-4 pb-2">
141
+ <button
142
+ type="button"
143
+ onClick={handleViewActivity}
144
+ className="w-full rounded-lg p-3 flex items-center justify-between transition-opacity hover:opacity-80"
145
+ style={{ backgroundColor: 'var(--color-surface-800)' }}
146
+ >
147
+ <span
148
+ className="text-sm font-medium leading-[18px] tracking-[0.14px]"
149
+ style={{ color: 'var(--color-text-primary)' }}
150
+ >
151
+ Activity log
152
+ </span>
153
+ <PlusIcon className="w-4 h-4" />
154
+ </button>
155
+ </div> */}
156
+
157
+ {/* DEV: Download transaction button */}
158
+ {/* {lastTransaction?.protobufTx && (
159
+ <div className="px-4 pb-2">
160
+ <button
161
+ type="button"
162
+ onClick={handleDownloadTx}
163
+ className="w-full rounded-lg p-3 flex items-center justify-center transition-opacity hover:opacity-80"
164
+ style={{ backgroundColor: 'var(--color-surface-800)' }}
165
+ >
166
+ <span
167
+ className="text-sm font-medium leading-[18px] tracking-[0.14px]"
168
+ style={{ color: 'var(--color-text-primary)' }}
169
+ >
170
+ Download Transaction (Dev)
171
+ </span>
172
+ </button>
173
+ </div>
174
+ )} */}
175
+
176
+ {/* Action Buttons */}
177
+ <div className="flex gap-3 px-4 py-3 w-full">
178
+ <button
179
+ type="button"
180
+ onClick={handleViewActivity}
181
+ className="flex-1 h-12 inline-flex items-center justify-center rounded-lg text-sm font-medium leading-[18px] tracking-[0.14px] transition-opacity hover:opacity-90 active:opacity-80"
182
+ style={{
183
+ color: 'var(--color-bg)',
184
+ backgroundColor: 'var(--color-text-primary)',
185
+ }}
186
+ >
187
+ Back to overview
188
+ </button>
189
+ </div>
190
+ </div>
191
+ </div>
192
+ );
193
+ }
@@ -0,0 +1,116 @@
1
+ import { useStore } from '../store';
2
+ import RoseLogo from '../assets/iris-logo.svg';
3
+ import ThemeIcon from '../assets/theme-icon.svg';
4
+ import KeyIcon from '../assets/key-icon.svg';
5
+ import ClockIcon from '../assets/clock-icon.svg';
6
+ import { CloseIcon } from '../components/icons/CloseIcon';
7
+ import { ChevronRightIcon } from '../components/icons/ChevronRightIcon';
8
+ import AboutIcon from '../assets/settings-gear-icon.svg';
9
+ import { version } from '../../../package-lock.json';
10
+
11
+ export function SettingsScreen() {
12
+ const { navigate } = useStore();
13
+
14
+ function handleClose() {
15
+ navigate('home');
16
+ }
17
+ function handleThemeSettings() {
18
+ navigate('theme-settings');
19
+ }
20
+ function handleKeySettings() {
21
+ navigate('key-settings');
22
+ }
23
+ function handleLockTime() {
24
+ navigate('lock-time');
25
+ }
26
+ function handleV0Migration() {
27
+ navigate('onboarding-import-v0');
28
+ }
29
+ function handleAbout() {
30
+ navigate('about');
31
+ }
32
+
33
+ const Row = ({ icon, label, onClick }: { icon: string; label: string; onClick: () => void }) => (
34
+ <button
35
+ type="button"
36
+ onClick={onClick}
37
+ className="flex items-center justify-between p-2 rounded-lg transition-colors focus:outline-none focus-visible:ring-2"
38
+ onMouseEnter={e => (e.currentTarget.style.backgroundColor = 'var(--color-surface-800)')}
39
+ onMouseLeave={e => (e.currentTarget.style.backgroundColor = 'transparent')}
40
+ >
41
+ <div className="flex items-center gap-2.5 flex-1">
42
+ <div
43
+ className="w-8 h-8 rounded-lg flex items-center justify-center shrink-0"
44
+ style={{ backgroundColor: 'var(--color-surface-800)' }}
45
+ >
46
+ <img src={icon} alt="" className="w-5 h-5 object-contain" />
47
+ </div>
48
+ <span
49
+ className="text-sm font-medium leading-[18px] tracking-[0.14px]"
50
+ style={{ color: 'var(--color-text-primary)' }}
51
+ >
52
+ {label}
53
+ </span>
54
+ </div>
55
+ <div className="w-4 h-4 p-1 shrink-0">
56
+ <ChevronRightIcon className="w-4 h-4" />
57
+ </div>
58
+ </button>
59
+ );
60
+
61
+ return (
62
+ <div
63
+ className="w-[357px] h-[600px] flex flex-col overflow-y-auto"
64
+ style={{ backgroundColor: 'var(--color-bg)', color: 'var(--color-text-primary)' }}
65
+ >
66
+ {/* Header */}
67
+ <header
68
+ className="flex items-center justify-between px-4 py-3 min-h-[64px]"
69
+ style={{ backgroundColor: 'var(--color-bg)' }}
70
+ >
71
+ <div className="w-8 h-8 flex items-center justify-center shrink-0">
72
+ <img src={RoseLogo} alt="Rose" className="w-6 h-6" />
73
+ </div>
74
+ <h1 className="m-0 text-base font-medium leading-[22px] tracking-[0.16px]">Settings</h1>
75
+ <button
76
+ type="button"
77
+ onClick={handleClose}
78
+ aria-label="Close"
79
+ className="w-8 h-8 rounded-lg flex items-center justify-center transition-colors focus:outline-none focus-visible:ring-2 shrink-0"
80
+ style={{ color: 'var(--color-text-primary)' }}
81
+ onMouseEnter={e => (e.currentTarget.style.backgroundColor = 'var(--color-surface-800)')}
82
+ onMouseLeave={e => (e.currentTarget.style.backgroundColor = 'transparent')}
83
+ >
84
+ <CloseIcon />
85
+ </button>
86
+ </header>
87
+
88
+ {/* Content */}
89
+ <div className="flex flex-col justify-between flex-1 h-[536px]">
90
+ {/* Menu */}
91
+ <div className="flex flex-col gap-2 px-3 py-2">
92
+ {/* <Row icon={ThemeIcon} label="Theme settings" onClick={handleThemeSettings} /> */}
93
+ <Row icon={KeyIcon} label="Key settings" onClick={handleKeySettings} />
94
+ <Row icon={ClockIcon} label="Lock time" onClick={handleLockTime} />
95
+ <Row icon={KeyIcon} label="Upgrade v0 → v1" onClick={handleV0Migration} />
96
+ <Row icon={AboutIcon} label="About" onClick={handleAbout} />
97
+ </div>
98
+
99
+ {/* Footer */}
100
+ <div className="px-4">
101
+ <div
102
+ className="flex flex-col items-center justify-center gap-2 py-4"
103
+ style={{ borderTop: '1px solid var(--color-divider)' }}
104
+ >
105
+ <p
106
+ className="m-0 text-[12px] leading-4 tracking-[0.24px] text-center"
107
+ style={{ color: 'var(--color-text-muted)' }}
108
+ >
109
+ Version {version}
110
+ </p>
111
+ </div>
112
+ </div>
113
+ </div>
114
+ </div>
115
+ );
116
+ }
@@ -0,0 +1,107 @@
1
+ import { useStore } from '../store';
2
+ import { useTheme } from '../contexts/ThemeContext';
3
+ import { ChevronLeftIcon } from '../components/icons/ChevronLeftIcon';
4
+
5
+ export function ThemeSettingsScreen() {
6
+ const { navigate } = useStore();
7
+ const { theme, setTheme } = useTheme();
8
+
9
+ function handleBack() {
10
+ navigate('settings');
11
+ }
12
+ function handleThemeSelect(newTheme: 'light' | 'dark' | 'system') {
13
+ setTheme(newTheme);
14
+ }
15
+
16
+ const Option = ({
17
+ label,
18
+ selected,
19
+ onClick,
20
+ disabled = false,
21
+ }: {
22
+ label: string;
23
+ selected?: boolean;
24
+ onClick?: () => void;
25
+ disabled?: boolean;
26
+ }) => (
27
+ <button
28
+ type="button"
29
+ onClick={onClick}
30
+ disabled={disabled}
31
+ className={`flex items-center justify-between p-3 rounded-lg transition-colors text-left w-full focus:outline-none focus-visible:ring-2 ${
32
+ disabled ? 'opacity-60 cursor-not-allowed' : 'cursor-pointer'
33
+ }`}
34
+ style={{
35
+ backgroundColor: disabled ? 'transparent' : 'transparent',
36
+ }}
37
+ onMouseEnter={e => {
38
+ if (!disabled) {
39
+ e.currentTarget.style.backgroundColor = 'var(--color-surface-800)';
40
+ }
41
+ }}
42
+ onMouseLeave={e => {
43
+ e.currentTarget.style.backgroundColor = 'transparent';
44
+ }}
45
+ role="radio"
46
+ aria-checked={!!selected}
47
+ >
48
+ <span className="text-sm font-medium leading-[18px] tracking-[0.14px] flex-1">{label}</span>
49
+ <span
50
+ className="w-6 h-6 rounded-full flex items-center justify-center shrink-0 transition-all"
51
+ style={{
52
+ border: `1px solid ${selected ? 'var(--color-primary)' : 'var(--color-surface-700)'}`,
53
+ backgroundColor: selected ? 'var(--color-primary)' : 'var(--color-bg)',
54
+ }}
55
+ >
56
+ {selected && <span className="w-3 h-3 rounded-full" style={{ backgroundColor: '#000' }} />}
57
+ </span>
58
+ </button>
59
+ );
60
+
61
+ return (
62
+ <div
63
+ className="w-[357px] h-[600px] flex flex-col overflow-y-auto"
64
+ style={{ backgroundColor: 'var(--color-bg)', color: 'var(--color-text-primary)' }}
65
+ >
66
+ {/* Header */}
67
+ <header
68
+ className="flex items-center justify-between px-4 py-3 min-h-[64px]"
69
+ style={{ backgroundColor: 'var(--color-bg)' }}
70
+ >
71
+ <button
72
+ type="button"
73
+ onClick={handleBack}
74
+ aria-label="Back"
75
+ className="w-8 h-8 bg-transparent rounded-lg p-2 flex items-center justify-center shrink-0 transition-colors focus:outline-none focus-visible:ring-2"
76
+ onMouseEnter={e => (e.currentTarget.style.backgroundColor = 'var(--color-surface-800)')}
77
+ onMouseLeave={e => (e.currentTarget.style.backgroundColor = 'transparent')}
78
+ >
79
+ <ChevronLeftIcon className="w-5 h-5" />
80
+ </button>
81
+ <h1 className="m-0 text-base font-medium leading-[22px] tracking-[0.16px]">
82
+ Theme settings
83
+ </h1>
84
+ <div className="w-8 h-8 shrink-0" />
85
+ </header>
86
+
87
+ {/* Options */}
88
+ <div className="flex flex-col gap-2 px-3 py-2" role="radiogroup" aria-label="Theme">
89
+ <Option
90
+ label="Light"
91
+ selected={theme === 'light'}
92
+ onClick={() => handleThemeSelect('light')}
93
+ />
94
+ <Option
95
+ label="Dark"
96
+ selected={theme === 'dark'}
97
+ onClick={() => handleThemeSelect('dark')}
98
+ />
99
+ <Option
100
+ label="System"
101
+ selected={theme === 'system'}
102
+ onClick={() => handleThemeSelect('system')}
103
+ />
104
+ </div>
105
+ </div>
106
+ );
107
+ }