@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.
- package/.github/workflows/artifacts.yml +33 -0
- package/.github/workflows/ci.yml +68 -0
- package/.github/workflows/publish-sdk.yml +35 -0
- package/.nvmrc +1 -0
- package/.prettierignore +5 -0
- package/.prettierrc +8 -0
- package/LICENSE +22 -0
- package/README.md +117 -0
- package/extension/background/index.ts +1500 -0
- package/extension/content/index.ts +59 -0
- package/extension/icons/rose.svg +27 -0
- package/extension/icons/rose128.png +0 -0
- package/extension/icons/rose16.png +0 -0
- package/extension/icons/rose256.png +0 -0
- package/extension/icons/rose32.png +0 -0
- package/extension/icons/rose48.png +0 -0
- package/extension/icons/rose512.png +0 -0
- package/extension/inpage/index.ts +86 -0
- package/extension/manifest.json +48 -0
- package/extension/popup/Popup.tsx +94 -0
- package/extension/popup/Router.tsx +121 -0
- package/extension/popup/assets/arrow-down-icon.svg +3 -0
- package/extension/popup/assets/arrow-left-icon.svg +3 -0
- package/extension/popup/assets/arrow-right-icon.svg +3 -0
- package/extension/popup/assets/arrow-up-icon.svg +3 -0
- package/extension/popup/assets/arrow-up-right-icon.svg +3 -0
- package/extension/popup/assets/checkmark-icon.svg +3 -0
- package/extension/popup/assets/checkmark-pencil-icon.svg +3 -0
- package/extension/popup/assets/checkmark-success-icon.svg +3 -0
- package/extension/popup/assets/clock-icon.svg +3 -0
- package/extension/popup/assets/close-x-icon.svg +3 -0
- package/extension/popup/assets/copy-icon.svg +6 -0
- package/extension/popup/assets/explorer-icon.svg +3 -0
- package/extension/popup/assets/eye-off-icon.svg +3 -0
- package/extension/popup/assets/eye-open-icon.svg +4 -0
- package/extension/popup/assets/feedback-icon.svg +3 -0
- package/extension/popup/assets/green-status-dot.svg +3 -0
- package/extension/popup/assets/info-icon.svg +3 -0
- package/extension/popup/assets/iris-logo-40.svg +27 -0
- package/extension/popup/assets/iris-logo-96.svg +27 -0
- package/extension/popup/assets/iris-logo-blue.svg +27 -0
- package/extension/popup/assets/iris-logo-no-eye.svg +27 -0
- package/extension/popup/assets/iris-logo-orange.svg +27 -0
- package/extension/popup/assets/iris-logo.svg +27 -0
- package/extension/popup/assets/key-icon.svg +3 -0
- package/extension/popup/assets/lock-icon-yellow.svg +3 -0
- package/extension/popup/assets/lock-icon.svg +3 -0
- package/extension/popup/assets/pencil-edit-icon.svg +3 -0
- package/extension/popup/assets/permissions-icon.svg +3 -0
- package/extension/popup/assets/receipt-icon.svg +5 -0
- package/extension/popup/assets/refresh-icon.svg +3 -0
- package/extension/popup/assets/settings-gear-icon.svg +8 -0
- package/extension/popup/assets/settings-icon.svg +3 -0
- package/extension/popup/assets/theme-icon.svg +3 -0
- package/extension/popup/assets/trash-bin-icon.svg +3 -0
- package/extension/popup/assets/trend-down-arrow.svg +5 -0
- package/extension/popup/assets/trend-up-arrow.svg +5 -0
- package/extension/popup/assets/user-account-icon.svg +3 -0
- package/extension/popup/assets/vector-bottom-left.svg +9 -0
- package/extension/popup/assets/vector-left.svg +9 -0
- package/extension/popup/assets/vector-right.svg +9 -0
- package/extension/popup/assets/vector-top-right-rotated.svg +8 -0
- package/extension/popup/assets/vector-top-right.svg +9 -0
- package/extension/popup/assets/wallet-dropdown-arrow.svg +5 -0
- package/extension/popup/assets/wallet-icon-style-1.svg +6 -0
- package/extension/popup/assets/wallet-icon-style-10.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-11.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-12.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-13.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-14.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-15.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-2.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-3.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-4.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-5.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-6.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-7.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-8.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-9.svg +8 -0
- package/extension/popup/components/AccountIcon.tsx +78 -0
- package/extension/popup/components/AccountSelector.tsx +246 -0
- package/extension/popup/components/Alert.tsx +48 -0
- package/extension/popup/components/ConfirmModal.tsx +81 -0
- package/extension/popup/components/PasswordInput.tsx +49 -0
- package/extension/popup/components/ScreenContainer.tsx +17 -0
- package/extension/popup/components/SiteIcon.tsx +60 -0
- package/extension/popup/components/ThemeToggle.tsx +44 -0
- package/extension/popup/components/icons/ArrowDownLeftIcon.tsx +20 -0
- package/extension/popup/components/icons/ArrowUpRightIcon.tsx +20 -0
- package/extension/popup/components/icons/CheckIcon.tsx +20 -0
- package/extension/popup/components/icons/ChevronDownIcon.tsx +15 -0
- package/extension/popup/components/icons/ChevronLeftIcon.tsx +15 -0
- package/extension/popup/components/icons/ChevronRightIcon.tsx +15 -0
- package/extension/popup/components/icons/ChevronUpIcon.tsx +15 -0
- package/extension/popup/components/icons/CloseIcon.tsx +26 -0
- package/extension/popup/components/icons/CopyIcon.tsx +20 -0
- package/extension/popup/components/icons/EditIcon.tsx +20 -0
- package/extension/popup/components/icons/EyeIcon.tsx +13 -0
- package/extension/popup/components/icons/EyeOffIcon.tsx +13 -0
- package/extension/popup/components/icons/InfoIcon.tsx +20 -0
- package/extension/popup/components/icons/LockIcon.tsx +20 -0
- package/extension/popup/components/icons/PlusIcon.tsx +15 -0
- package/extension/popup/components/icons/ReceiveArrowIcon.tsx +14 -0
- package/extension/popup/components/icons/ReceiveCircleIcon.tsx +20 -0
- package/extension/popup/components/icons/SendPaperPlaneIcon.tsx +18 -0
- package/extension/popup/components/icons/SentArrowIcon.tsx +21 -0
- package/extension/popup/components/icons/SettingsIcon.tsx +26 -0
- package/extension/popup/components/icons/ShieldIcon.tsx +20 -0
- package/extension/popup/components/icons/UploadIcon.tsx +20 -0
- package/extension/popup/components/icons/WalletIcon.tsx +20 -0
- package/extension/popup/contexts/ThemeContext.tsx +105 -0
- package/extension/popup/hooks/useApprovalDetection.ts +128 -0
- package/extension/popup/hooks/useAutoFocus.ts +36 -0
- package/extension/popup/hooks/useAutoRejectOnClose.ts +25 -0
- package/extension/popup/hooks/useClickOutside.ts +33 -0
- package/extension/popup/hooks/useCopyToClipboard.ts +33 -0
- package/extension/popup/hooks/useFavicon.ts +64 -0
- package/extension/popup/hooks/useNumericInput.ts +93 -0
- package/extension/popup/index.html +13 -0
- package/extension/popup/index.tsx +24 -0
- package/extension/popup/screens/AboutScreen.tsx +118 -0
- package/extension/popup/screens/HomeScreen.tailwind.css +85 -0
- package/extension/popup/screens/HomeScreen.tsx +902 -0
- package/extension/popup/screens/KeySettingsPasswordScreen.tsx +164 -0
- package/extension/popup/screens/LockTimeScreen.tsx +155 -0
- package/extension/popup/screens/ReceiveScreen.tsx +149 -0
- package/extension/popup/screens/RecoveryPhraseScreen.tsx +183 -0
- package/extension/popup/screens/SendReviewScreen.tsx +308 -0
- package/extension/popup/screens/SendScreen.tsx +825 -0
- package/extension/popup/screens/SendSubmittedScreen.tsx +193 -0
- package/extension/popup/screens/SettingsScreen.tsx +116 -0
- package/extension/popup/screens/ThemeSettingsScreen.tsx +107 -0
- package/extension/popup/screens/TransactionDetailsScreen.tsx +346 -0
- package/extension/popup/screens/ViewSecretPhraseScreen.tsx +212 -0
- package/extension/popup/screens/WalletPermissionsScreen.tsx +123 -0
- package/extension/popup/screens/WalletSettingsScreen.tsx +381 -0
- package/extension/popup/screens/WalletStylingScreen.tsx +306 -0
- package/extension/popup/screens/approvals/ConnectApprovalScreen.tsx +136 -0
- package/extension/popup/screens/approvals/SignMessageScreen.tsx +140 -0
- package/extension/popup/screens/approvals/SignRawTxScreen.tsx +320 -0
- package/extension/popup/screens/approvals/TransactionApprovalScreen.tsx +167 -0
- package/extension/popup/screens/onboarding/BackupScreen.tsx +254 -0
- package/extension/popup/screens/onboarding/CreateScreen.tsx +273 -0
- package/extension/popup/screens/onboarding/ImportScreen.tsx +676 -0
- package/extension/popup/screens/onboarding/ImportScreenV0.tsx +678 -0
- package/extension/popup/screens/onboarding/ImportSuccessScreen.tsx +236 -0
- package/extension/popup/screens/onboarding/ResumeBackupScreen.tsx +166 -0
- package/extension/popup/screens/onboarding/StartScreen.tsx +142 -0
- package/extension/popup/screens/onboarding/SuccessScreen.tsx +193 -0
- package/extension/popup/screens/onboarding/VerifyScreen.tsx +220 -0
- package/extension/popup/screens/system/LockedScreen.tsx +288 -0
- package/extension/popup/screens/transactions/ReceiveScreen.tsx +84 -0
- package/extension/popup/screens/transactions/SentScreen.tsx +138 -0
- package/extension/popup/store.ts +482 -0
- package/extension/popup/styles.css +246 -0
- package/extension/popup/utils/format.ts +58 -0
- package/extension/popup/utils/formatWalletError.ts +36 -0
- package/extension/popup/utils/memo.ts +299 -0
- package/extension/popup/utils/messaging.ts +16 -0
- package/extension/shared/address-encoding.ts +69 -0
- package/extension/shared/balance-query.ts +123 -0
- package/extension/shared/constants.ts +386 -0
- package/extension/shared/currency.ts +128 -0
- package/extension/shared/first-name-derivation.ts +128 -0
- package/extension/shared/keyfile.ts +58 -0
- package/extension/shared/onboarding.ts +78 -0
- package/extension/shared/price-api.ts +79 -0
- package/extension/shared/rpc-client-browser.ts +315 -0
- package/extension/shared/transaction-builder.ts +443 -0
- package/extension/shared/types.ts +450 -0
- package/extension/shared/utxo-diff.ts +212 -0
- package/extension/shared/utxo-store.ts +548 -0
- package/extension/shared/utxo-sync.ts +343 -0
- package/extension/shared/validators.ts +26 -0
- package/extension/shared/vault.ts +1580 -0
- package/extension/shared/wallet-crypto.ts +77 -0
- package/extension/shared/wasm-utils.ts +76 -0
- package/extension/shared/webcrypto.ts +67 -0
- package/extension/types/wasm.d.ts +13 -0
- package/package.json +39 -0
- package/postcss.config.js +6 -0
- package/rose-extension-dist.zip +0 -0
- package/sdk/README.md +88 -0
- package/sdk/examples/app.ts +166 -0
- package/sdk/examples/index.html +51 -0
- package/sdk/examples/tsconfig.json +15 -0
- package/sdk/examples/tx-builder.html +532 -0
- package/sdk/examples/tx-builder.ts +1766 -0
- package/sdk/package-lock.json +424 -0
- package/sdk/package.json +68 -0
- package/sdk/src/constants.ts +28 -0
- package/sdk/src/errors.ts +74 -0
- package/sdk/src/hooks/index.ts +1 -0
- package/sdk/src/hooks/use-rose.ts +94 -0
- package/sdk/src/index.ts +12 -0
- package/sdk/src/provider.ts +396 -0
- package/sdk/src/transaction.ts +163 -0
- package/sdk/src/types/rose-wasm.d.ts +14 -0
- package/sdk/src/types.ts +97 -0
- package/sdk/src/wasm.ts +13 -0
- package/sdk/tsconfig.json +20 -0
- package/sdk/vite.config.examples.ts +32 -0
- package/tailwind.config.ts +38 -0
- package/tsconfig.json +20 -0
- package/vite.config.ts +60 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SiteIcon - Display site favicon with fallback to letter avatar
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useFavicon } from '../hooks/useFavicon';
|
|
6
|
+
|
|
7
|
+
interface SiteIconProps {
|
|
8
|
+
origin: string;
|
|
9
|
+
domain: string;
|
|
10
|
+
size?: 'sm' | 'md' | 'lg';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function SiteIcon({ origin, domain, size = 'lg' }: SiteIconProps) {
|
|
14
|
+
const faviconUrl = useFavicon(origin);
|
|
15
|
+
|
|
16
|
+
// Size mappings
|
|
17
|
+
const sizeClasses = {
|
|
18
|
+
sm: 'w-8 h-8',
|
|
19
|
+
md: 'w-12 h-12',
|
|
20
|
+
lg: 'w-16 h-16',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const textSizes = {
|
|
24
|
+
sm: 'text-lg',
|
|
25
|
+
md: 'text-xl',
|
|
26
|
+
lg: 'text-2xl',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const surface = 'var(--color-surface-800)';
|
|
30
|
+
const textPrimary = 'var(--color-text-primary)';
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div className="relative inline-block">
|
|
34
|
+
<div
|
|
35
|
+
className={`inline-flex items-center justify-center rounded-full ${sizeClasses[size]} overflow-hidden`}
|
|
36
|
+
style={{ backgroundColor: surface }}
|
|
37
|
+
>
|
|
38
|
+
{faviconUrl ? (
|
|
39
|
+
<img
|
|
40
|
+
src={faviconUrl}
|
|
41
|
+
alt={`${domain} favicon`}
|
|
42
|
+
className="w-full h-full object-cover"
|
|
43
|
+
onError={e => {
|
|
44
|
+
// Hide broken image, show letter fallback
|
|
45
|
+
e.currentTarget.style.display = 'none';
|
|
46
|
+
const parent = e.currentTarget.parentElement;
|
|
47
|
+
if (parent) {
|
|
48
|
+
parent.innerHTML = `<span class="${textSizes[size]} font-bold" style="color: ${textPrimary}">${domain.charAt(0).toUpperCase()}</span>`;
|
|
49
|
+
}
|
|
50
|
+
}}
|
|
51
|
+
/>
|
|
52
|
+
) : (
|
|
53
|
+
<span className={`${textSizes[size]} font-bold`} style={{ color: textPrimary }}>
|
|
54
|
+
{domain.charAt(0).toUpperCase()}
|
|
55
|
+
</span>
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Toggle Component
|
|
3
|
+
* Allows users to switch between dark and light modes
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useTheme } from '../contexts/ThemeContext';
|
|
7
|
+
|
|
8
|
+
export function ThemeToggle() {
|
|
9
|
+
const { theme, toggleTheme } = useTheme();
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<button
|
|
13
|
+
onClick={toggleTheme}
|
|
14
|
+
className="flex items-center gap-2 px-4 py-2 rounded-lg bg-gray-800 hover:bg-gray-700 transition-colors"
|
|
15
|
+
aria-label={`Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`}
|
|
16
|
+
>
|
|
17
|
+
{theme === 'dark' ? (
|
|
18
|
+
<>
|
|
19
|
+
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
20
|
+
<path
|
|
21
|
+
strokeLinecap="round"
|
|
22
|
+
strokeLinejoin="round"
|
|
23
|
+
strokeWidth={2}
|
|
24
|
+
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
|
|
25
|
+
/>
|
|
26
|
+
</svg>
|
|
27
|
+
<span className="text-sm">Light Mode</span>
|
|
28
|
+
</>
|
|
29
|
+
) : (
|
|
30
|
+
<>
|
|
31
|
+
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
32
|
+
<path
|
|
33
|
+
strokeLinecap="round"
|
|
34
|
+
strokeLinejoin="round"
|
|
35
|
+
strokeWidth={2}
|
|
36
|
+
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
|
|
37
|
+
/>
|
|
38
|
+
</svg>
|
|
39
|
+
<span className="text-sm">Dark Mode</span>
|
|
40
|
+
</>
|
|
41
|
+
)}
|
|
42
|
+
</button>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ArrowDownLeftIcon - Incoming/received transaction icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ArrowDownLeftIcon({ className = 'w-6 h-6' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
strokeWidth={2}
|
|
16
|
+
d="M17 7L7 17M7 17H17M7 17V7"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ArrowUpRightIcon - Simple diagonal arrow pointing up-right
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ArrowUpRightIcon({ className = 'w-6 h-6' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
className={className}
|
|
13
|
+
viewBox="0 0 11 11"
|
|
14
|
+
fill="currentColor"
|
|
15
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
16
|
+
>
|
|
17
|
+
<path d="M1.16667 10.8333L9.16667 2.83333L9.16667 10L10.8333 10V0H0.833333L0.833334 1.66667H8L0 9.66667L1.16667 10.8333Z" />
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CheckIcon - Success/checkmark icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function CheckIcon({ className = 'w-5 h-5', style }: IconProps) {
|
|
11
|
+
return (
|
|
12
|
+
<svg className={className} style={style} viewBox="0 0 20 20" fill="currentColor">
|
|
13
|
+
<path
|
|
14
|
+
fillRule="evenodd"
|
|
15
|
+
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
|
16
|
+
clipRule="evenodd"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChevronDownIcon - Dropdown arrow icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ChevronDownIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
13
|
+
</svg>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChevronLeftIcon - Back/left arrow icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ChevronLeftIcon({ className = 'w-6 h-6' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
|
13
|
+
</svg>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChevronRightIcon - Right arrow icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ChevronRightIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
13
|
+
</svg>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChevronUpIcon - Up arrow icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ChevronUpIcon({ className = 'w-6 h-6' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 15l7-7 7 7" />
|
|
13
|
+
</svg>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CloseIcon - Close/X icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function CloseIcon({ className = '' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
className={className}
|
|
13
|
+
viewBox="0 0 16 16"
|
|
14
|
+
fill="none"
|
|
15
|
+
width="16"
|
|
16
|
+
height="16"
|
|
17
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
18
|
+
stroke="currentColor"
|
|
19
|
+
>
|
|
20
|
+
<path
|
|
21
|
+
d="M14.4141 3L9.41406 8L14.4141 13L13 14.4141L8 9.41406L3 14.4141L1.58594 13L6.58594 8L1.58594 3L3 1.58594L8 6.58594L13 1.58594L14.4141 3Z"
|
|
22
|
+
fill="currentColor"
|
|
23
|
+
/>
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CopyIcon - Copy to clipboard icon (overlapping documents)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function CopyIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
strokeWidth={2}
|
|
16
|
+
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EditIcon - Edit/pencil icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function EditIcon({ className = 'w-4 h-4' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
strokeWidth={2}
|
|
16
|
+
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import EyeOpenIconSvg from '../../assets/eye-open-icon.svg';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EyeIcon - View/show icon
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
interface IconProps {
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function EyeIcon({ className = 'w-4 h-4' }: IconProps) {
|
|
12
|
+
return <img src={EyeOpenIconSvg} alt="" className={className} />;
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import EyeOffIconSvg from '../../assets/eye-off-icon.svg';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EyeOffIcon - Hide/conceal icon
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
interface IconProps {
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function EyeOffIcon({ className = 'w-4 h-4' }: IconProps) {
|
|
12
|
+
return <img src={EyeOffIconSvg} alt="" className={className} />;
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InfoIcon - Information icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function InfoIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
strokeWidth={2}
|
|
16
|
+
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LockIcon - Lock/security icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function LockIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
strokeWidth={2}
|
|
16
|
+
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlusIcon - Add/create new icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function PlusIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
|
|
13
|
+
</svg>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReceiveArrowIcon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import ArrowDownIcon from '../../assets/arrow-down-icon.svg';
|
|
6
|
+
|
|
7
|
+
interface IconProps {
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: React.CSSProperties;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function ReceiveArrowIcon({ className = 'w-4 h-4', style }: IconProps) {
|
|
13
|
+
return <img src={ArrowDownIcon} alt="" className={className} style={style} />;
|
|
14
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReceiveCircleIcon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ReceiveCircleIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
12
|
+
<path
|
|
13
|
+
fillRule="evenodd"
|
|
14
|
+
clipRule="evenodd"
|
|
15
|
+
d="M10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10C0 4.47715 4.47715 0 10 0ZM10 5.8252C9.53884 5.8252 9.16504 6.199 9.16504 6.66016V11.3232L7.25098 9.40918C6.92489 9.08309 6.39542 9.08309 6.06934 9.40918C5.74325 9.73527 5.74325 10.2647 6.06934 10.5908L9.40918 13.9307C9.73527 14.2568 10.2647 14.2568 10.5908 13.9307L13.9307 10.5908C14.2568 10.2647 14.2568 9.73527 13.9307 9.40918C13.6046 9.08309 13.0751 9.08309 12.749 9.40918L10.835 11.3232V6.66016C10.835 6.199 10.4612 5.8252 10 5.8252Z"
|
|
16
|
+
fill="currentColor"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SendPaperPlaneIcon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function SendPaperPlaneIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
12
|
+
<path
|
|
13
|
+
d="M0.682286 6.74231C-0.228035 6.43728 -0.227221 5.14941 0.683484 4.84554L15.0466 0.0529811C15.8097 -0.201652 16.5459 0.503244 16.3245 1.27669L12.1665 15.8069C11.9098 16.7041 10.673 16.7918 10.2922 15.9399L8.02397 10.8654C7.87575 10.5338 7.91899 10.1479 8.13692 9.85734L9.0263 8.6715C9.72014 7.74639 8.55142 6.57766 7.6263 7.2715L6.38962 8.19901C6.12666 8.39623 5.78358 8.45163 5.47191 8.3472L0.682286 6.74231Z"
|
|
14
|
+
fill="currentColor"
|
|
15
|
+
/>
|
|
16
|
+
</svg>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SentArrowIcon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import ArrowUpIcon from '../../assets/arrow-up-icon.svg';
|
|
6
|
+
|
|
7
|
+
interface IconProps {
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: React.CSSProperties;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function SentArrowIcon({ className = 'w-4 h-4', style }: IconProps) {
|
|
13
|
+
return (
|
|
14
|
+
<div
|
|
15
|
+
className={className}
|
|
16
|
+
style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', ...style }}
|
|
17
|
+
>
|
|
18
|
+
<img src={ArrowUpIcon} alt="" style={{ width: '68%', height: '68%' }} />
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SettingsIcon - Gear/settings icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function SettingsIcon({ className = 'w-6 h-6' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
strokeWidth={2}
|
|
16
|
+
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
|
|
17
|
+
/>
|
|
18
|
+
<path
|
|
19
|
+
strokeLinecap="round"
|
|
20
|
+
strokeLinejoin="round"
|
|
21
|
+
strokeWidth={2}
|
|
22
|
+
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
|
|
23
|
+
/>
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShieldIcon - Security/protection icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ShieldIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
strokeWidth={2}
|
|
16
|
+
d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UploadIcon - Import/upload icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function UploadIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
strokeWidth={2}
|
|
16
|
+
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WalletIcon - Wallet/card icon
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function WalletIcon({ className = 'w-5 h-5' }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12
|
+
<path
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
strokeWidth={2}
|
|
16
|
+
d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Context - Manages dark/light mode switching with system theme support
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createContext, useContext, useEffect, useState, ReactNode } from 'react';
|
|
6
|
+
|
|
7
|
+
type Theme = 'dark' | 'light' | 'system';
|
|
8
|
+
|
|
9
|
+
interface ThemeContextType {
|
|
10
|
+
theme: Theme;
|
|
11
|
+
toggleTheme: () => void;
|
|
12
|
+
setTheme: (theme: Theme) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
|
|
16
|
+
|
|
17
|
+
const STORAGE_KEY = 'rose-theme';
|
|
18
|
+
|
|
19
|
+
// Detect system theme preference
|
|
20
|
+
function getSystemTheme(): 'dark' | 'light' {
|
|
21
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function ThemeProvider({ children }: { children: ReactNode }) {
|
|
25
|
+
const [theme, setThemeState] = useState<Theme>('light');
|
|
26
|
+
const [mounted, setMounted] = useState(false);
|
|
27
|
+
|
|
28
|
+
// Load theme from storage on mount
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
chrome.storage.local.get([STORAGE_KEY], result => {
|
|
31
|
+
const savedTheme = result[STORAGE_KEY] as Theme | undefined;
|
|
32
|
+
if (savedTheme) {
|
|
33
|
+
setThemeState(savedTheme);
|
|
34
|
+
applyTheme(savedTheme);
|
|
35
|
+
} else {
|
|
36
|
+
// No saved theme, default to light theme
|
|
37
|
+
setThemeState('light');
|
|
38
|
+
applyTheme('light');
|
|
39
|
+
chrome.storage.local.set({ [STORAGE_KEY]: 'light' });
|
|
40
|
+
}
|
|
41
|
+
setMounted(true);
|
|
42
|
+
});
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
45
|
+
// Listen for system theme changes when using system theme
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (theme !== 'system') return;
|
|
48
|
+
|
|
49
|
+
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
50
|
+
const handleChange = () => {
|
|
51
|
+
applyTheme('system');
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Modern browsers
|
|
55
|
+
mediaQuery.addEventListener('change', handleChange);
|
|
56
|
+
|
|
57
|
+
return () => {
|
|
58
|
+
mediaQuery.removeEventListener('change', handleChange);
|
|
59
|
+
};
|
|
60
|
+
}, [theme]);
|
|
61
|
+
|
|
62
|
+
// Apply theme to document
|
|
63
|
+
const applyTheme = (newTheme: Theme) => {
|
|
64
|
+
const root = document.documentElement;
|
|
65
|
+
const effectiveTheme = newTheme === 'system' ? getSystemTheme() : newTheme;
|
|
66
|
+
|
|
67
|
+
if (effectiveTheme === 'light') {
|
|
68
|
+
root.classList.add('light');
|
|
69
|
+
} else {
|
|
70
|
+
root.classList.remove('light');
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Set theme and persist
|
|
75
|
+
const setTheme = (newTheme: Theme) => {
|
|
76
|
+
setThemeState(newTheme);
|
|
77
|
+
applyTheme(newTheme);
|
|
78
|
+
chrome.storage.local.set({ [STORAGE_KEY]: newTheme });
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Toggle between dark and light (skip system)
|
|
82
|
+
const toggleTheme = () => {
|
|
83
|
+
const newTheme = theme === 'dark' ? 'light' : 'dark';
|
|
84
|
+
setTheme(newTheme);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Prevent flash of wrong theme
|
|
88
|
+
if (!mounted) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<ThemeContext.Provider value={{ theme, toggleTheme, setTheme }}>
|
|
94
|
+
{children}
|
|
95
|
+
</ThemeContext.Provider>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function useTheme() {
|
|
100
|
+
const context = useContext(ThemeContext);
|
|
101
|
+
if (!context) {
|
|
102
|
+
throw new Error('useTheme must be used within ThemeProvider');
|
|
103
|
+
}
|
|
104
|
+
return context;
|
|
105
|
+
}
|