Add basic monochrome popup UI with Tailwind CSS
All checks were successful
check / check (push) Successful in 11s
All checks were successful
check / check (push) Successful in 11s
Black-on-white, monospace, Universal Paperclips aesthetic. All views: lock, setup/create/import, main account, send, receive, add token, settings, and approval. Vanilla JS view switching with stub state. README updated with full UI design philosophy, external services documentation, and view descriptions.
This commit is contained in:
parent
065f0eaa81
commit
d9eda1d503
@ -1,3 +1,4 @@
|
||||
node_modules/
|
||||
yarn.lock
|
||||
dist/
|
||||
.claude/
|
||||
|
||||
97
README.md
97
README.md
@ -55,7 +55,7 @@ src/
|
||||
index.html
|
||||
index.js
|
||||
components/ — UI components (account list, send form, etc.)
|
||||
styles/ — CSS
|
||||
styles/ — CSS (Tailwind)
|
||||
content/ — content script injected into web pages
|
||||
index.js — injects the provider into page context
|
||||
inpage.js — the window.ethereum provider object
|
||||
@ -69,6 +69,85 @@ manifest/
|
||||
firefox.json — Manifest V2/V3 for Firefox
|
||||
```
|
||||
|
||||
### UI Design Philosophy
|
||||
|
||||
The UI follows a "Universal Paperclips" aesthetic — a deliberately spartan,
|
||||
almost brutalist approach:
|
||||
|
||||
- **Monochrome**: Black text on white background. No brand colors, no gradients,
|
||||
no color-coding. Color may be introduced later for specific semantic purposes
|
||||
(e.g. error states) but the baseline is monochrome.
|
||||
- **Text-first**: Every piece of information is presented as text. Balances are
|
||||
numbers. Addresses are hex strings. Status is a sentence. No progress spinners
|
||||
with animations — a text status line is sufficient.
|
||||
- **Monospace font**: All text is rendered in the system monospace font.
|
||||
Ethereum addresses, transaction hashes, and balances are inherently
|
||||
fixed-width data. Rather than mixing proportional and monospace fonts, we use
|
||||
monospace everywhere for visual consistency and alignment.
|
||||
- **Icon fonts only**: Where icons are needed (copy, send, settings, etc.) we
|
||||
use an icon font (no SVGs, no PNGs, no image assets). This keeps the extension
|
||||
size tiny and the build simple.
|
||||
- **No images**: Zero image assets in the entire extension. No logos, no
|
||||
illustrations, no token icons. Token identity is conveyed by symbol text (ETH,
|
||||
USDC, etc.).
|
||||
- **Tailwind CSS**: Utility-first CSS via Tailwind. No custom CSS classes for
|
||||
styling. Tailwind is configured with a minimal monochrome palette. This keeps
|
||||
the styling co-located with the markup and eliminates CSS file management.
|
||||
- **Vanilla JS**: No framework (React, Vue, Svelte, etc.). The popup UI is small
|
||||
enough that vanilla JS with simple view switching is sufficient. A framework
|
||||
would add bundle size, build complexity, and attack surface for no benefit at
|
||||
this scale.
|
||||
- **360x600 popup**: Standard browser extension popup dimensions. The UI is
|
||||
designed for this fixed viewport — no responsive breakpoints needed.
|
||||
|
||||
### UI Views
|
||||
|
||||
The popup has the following views, switched via simple show/hide:
|
||||
|
||||
1. **Lock screen**: Password input + unlock button. Shown when the wallet is
|
||||
locked or on first open after browser restart.
|
||||
2. **Setup / Onboarding**: Shown on first use. Create a new wallet (generates
|
||||
BIP-39 mnemonic, user confirms backup, sets password) or import an existing
|
||||
seed phrase.
|
||||
3. **Main / Account view**: The default view after unlock. Shows the current
|
||||
account address (truncated, click to copy), ETH balance, list of added ERC-20
|
||||
tokens with balances, and action buttons (Send, Receive, Settings).
|
||||
4. **Send**: Form with To address, amount, token selector (ETH or any added
|
||||
ERC-20), and a Send button. Shows gas estimate before confirming.
|
||||
5. **Receive**: Displays the current account address in full (copyable). That's
|
||||
it.
|
||||
6. **Settings**: Configure RPC endpoint URL, manage wallets (add/remove seed
|
||||
phrases), derive additional accounts, view/export seed phrase (requires
|
||||
password re-entry), manage added ERC-20 tokens.
|
||||
7. **Approval popups**: When a connected site requests a transaction signature
|
||||
or message signature, an approval view shows the details and Approve/Reject
|
||||
buttons.
|
||||
|
||||
### External Services
|
||||
|
||||
AutistMask is not a fully self-contained offline tool. It necessarily
|
||||
communicates with external services to function as a wallet:
|
||||
|
||||
- **Ethereum JSON-RPC endpoint**: The extension needs an Ethereum node to query
|
||||
balances (`eth_getBalance`), read ERC-20 token contracts (`eth_call`),
|
||||
estimate gas (`eth_estimateGas`), fetch nonces (`eth_getTransactionCount`),
|
||||
broadcast transactions (`eth_sendRawTransaction`), and check transaction
|
||||
receipts. The default endpoint is a public RPC (configurable by the user to
|
||||
any endpoint they prefer, including a local node). This is the only external
|
||||
service the extension talks to.
|
||||
|
||||
What the extension does NOT do:
|
||||
|
||||
- No analytics or telemetry services
|
||||
- No token list APIs (user adds tokens manually by contract address)
|
||||
- No price feed APIs (balances are shown in token units, not fiat)
|
||||
- No phishing/blocklist APIs
|
||||
- No Infura/Alchemy dependency (any JSON-RPC endpoint works)
|
||||
- No backend servers operated by the developer
|
||||
|
||||
The user's RPC endpoint is the single point of external communication. Users who
|
||||
want maximum privacy can point it at their own Ethereum node.
|
||||
|
||||
### Key Decisions
|
||||
|
||||
- **No framework**: The popup UI is vanilla JS and HTML. The extension is small
|
||||
@ -85,9 +164,6 @@ manifest/
|
||||
- **Minimal RPC**: The extension communicates with Ethereum nodes via JSON-RPC.
|
||||
The default endpoint is configurable. No Infura dependency — users can point
|
||||
it at any Ethereum JSON-RPC endpoint.
|
||||
- **No external services**: No analytics, no tracking, no telemetry, no ads, no
|
||||
phishing lists, no token price feeds. The extension only talks to the
|
||||
configured Ethereum RPC endpoint.
|
||||
|
||||
### Supported Functionality
|
||||
|
||||
@ -109,24 +185,29 @@ manifest/
|
||||
### Non-Goals
|
||||
|
||||
- Token swaps (use a DEX in the browser)
|
||||
- Portfolio/price tracking
|
||||
- Portfolio/price tracking (balances shown in token units only, no fiat)
|
||||
- NFT display or management
|
||||
- Multi-chain support (Ethereum mainnet only, for now)
|
||||
- Analytics, telemetry, or tracking of any kind
|
||||
- Advertisements or promotions
|
||||
- Phishing detection (use your brain)
|
||||
- Hardware wallet support (maybe later)
|
||||
- Token list auto-discovery (user adds tokens manually)
|
||||
- Fiat on/off ramps
|
||||
- Browser notifications
|
||||
- Transaction history (use Etherscan)
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] Set up build system (webpack/esbuild) for Chrome and Firefox targets
|
||||
- [x] Project scaffolding (Makefile, Dockerfile, CI, manifests)
|
||||
- [ ] Set up Tailwind CSS build pipeline
|
||||
- [ ] Build popup UI views (lock, setup, main, send, receive, settings)
|
||||
- [ ] Implement BIP-39 mnemonic generation and validation
|
||||
- [ ] Implement BIP-32/BIP-44 HD key derivation for Ethereum
|
||||
- [ ] Implement encrypted storage for seed phrases
|
||||
- [ ] Build popup UI: lock screen, account list, send/receive views
|
||||
- [ ] Implement background wallet manager
|
||||
- [ ] Implement EIP-1193 provider and content script injection
|
||||
- [ ] Implement ETH send/receive
|
||||
- [ ] Implement ETH balance lookup and send
|
||||
- [ ] Implement ERC-20 token management (add by contract, view balance, send)
|
||||
- [ ] Implement site connection approval flow
|
||||
- [ ] Implement transaction signing approval flow
|
||||
|
||||
45
build.js
45
build.js
@ -1,21 +1,26 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { execSync } = require("child_process");
|
||||
|
||||
const DIST_CHROME = path.join(__dirname, "dist", "chrome");
|
||||
const DIST_FIREFOX = path.join(__dirname, "dist", "firefox");
|
||||
const SRC = path.join(__dirname, "src");
|
||||
|
||||
function ensureDir(dir) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
function copyDir(src, dest) {
|
||||
function copyDir(src, dest, opts = {}) {
|
||||
ensureDir(dest);
|
||||
const entries = fs.readdirSync(src, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const srcPath = path.join(src, entry.name);
|
||||
const destPath = path.join(dest, entry.name);
|
||||
if (opts.skip && opts.skip.includes(entry.name)) {
|
||||
continue;
|
||||
}
|
||||
if (entry.isDirectory()) {
|
||||
copyDir(srcPath, destPath);
|
||||
copyDir(srcPath, destPath, opts);
|
||||
} else {
|
||||
fs.copyFileSync(srcPath, destPath);
|
||||
}
|
||||
@ -25,12 +30,40 @@ function copyDir(src, dest) {
|
||||
function build() {
|
||||
console.log("Building AutistMask extension...");
|
||||
|
||||
ensureDir(DIST_CHROME);
|
||||
ensureDir(DIST_FIREFOX);
|
||||
// compile tailwind CSS
|
||||
console.log("Compiling Tailwind CSS...");
|
||||
const tailwindInput = path.join(SRC, "popup", "styles", "main.css");
|
||||
const tailwindOutput = path.join(__dirname, "dist", "styles.css");
|
||||
ensureDir(path.join(__dirname, "dist"));
|
||||
execSync(
|
||||
`npx @tailwindcss/cli -i ${tailwindInput} -o ${tailwindOutput} --minify`,
|
||||
{ stdio: "inherit" },
|
||||
);
|
||||
|
||||
copyDir(path.join(__dirname, "src"), path.join(DIST_CHROME, "src"));
|
||||
copyDir(path.join(__dirname, "src"), path.join(DIST_FIREFOX, "src"));
|
||||
// copy source files (skip the styles dir, we compiled it)
|
||||
for (const distDir of [DIST_CHROME, DIST_FIREFOX]) {
|
||||
ensureDir(distDir);
|
||||
copyDir(path.join(SRC, "popup"), path.join(distDir, "src", "popup"), {
|
||||
skip: ["styles"],
|
||||
});
|
||||
copyDir(
|
||||
path.join(SRC, "background"),
|
||||
path.join(distDir, "src", "background"),
|
||||
);
|
||||
copyDir(
|
||||
path.join(SRC, "content"),
|
||||
path.join(distDir, "src", "content"),
|
||||
);
|
||||
copyDir(path.join(SRC, "shared"), path.join(distDir, "src", "shared"));
|
||||
|
||||
// place compiled CSS next to popup HTML
|
||||
fs.copyFileSync(
|
||||
tailwindOutput,
|
||||
path.join(distDir, "src", "popup", "styles.css"),
|
||||
);
|
||||
}
|
||||
|
||||
// copy manifests
|
||||
fs.copyFileSync(
|
||||
path.join(__dirname, "manifest", "chrome.json"),
|
||||
path.join(DIST_CHROME, "manifest.json"),
|
||||
|
||||
@ -13,8 +13,10 @@
|
||||
"fmt-check": "prettier --check ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/cli": "^4.2.1",
|
||||
"jest": "^30.2.0",
|
||||
"prettier": "^3.8.1"
|
||||
"prettier": "^3.8.1",
|
||||
"tailwindcss": "^4.2.1"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
||||
@ -4,10 +4,471 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>AutistMask</title>
|
||||
<link rel="stylesheet" href="styles/main.css" />
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<body class="bg-bg text-fg font-mono text-sm">
|
||||
<div id="app" class="p-2">
|
||||
<!-- ============ LOCK SCREEN ============ -->
|
||||
<div id="view-lock" class="view hidden">
|
||||
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
||||
AutistMask [locked]
|
||||
</h1>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1">Password:</label>
|
||||
<input
|
||||
type="password"
|
||||
id="unlock-password"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="enter password to unlock"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
id="btn-unlock"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
unlock
|
||||
</button>
|
||||
<div
|
||||
id="unlock-error"
|
||||
class="mt-2 border border-border border-dashed p-1 hidden"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- ============ SETUP: WELCOME ============ -->
|
||||
<div id="view-setup" class="view hidden">
|
||||
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
||||
AutistMask [setup]
|
||||
</h1>
|
||||
<p class="mb-3">No wallet found. Create or import one.</p>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
id="btn-setup-create"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
create new wallet
|
||||
</button>
|
||||
<button
|
||||
id="btn-setup-import"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
import seed phrase
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ SETUP: CREATE ============ -->
|
||||
<div id="view-create" class="view hidden">
|
||||
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
||||
AutistMask [create wallet]
|
||||
</h1>
|
||||
<p class="mb-2">
|
||||
Write down this seed phrase and store it safely. It is the
|
||||
only way to recover your wallet.
|
||||
</p>
|
||||
<div
|
||||
id="create-mnemonic"
|
||||
class="border border-border p-2 mb-3 font-mono break-all select-all"
|
||||
></div>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1">Set password:</label>
|
||||
<input
|
||||
type="password"
|
||||
id="create-password"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="password"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1">Confirm password:</label>
|
||||
<input
|
||||
type="password"
|
||||
id="create-password-confirm"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="confirm password"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
id="btn-create-confirm"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
i backed it up, create wallet
|
||||
</button>
|
||||
<button
|
||||
id="btn-create-back"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
back
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
id="create-error"
|
||||
class="mt-2 border border-border border-dashed p-1 hidden"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- ============ SETUP: IMPORT ============ -->
|
||||
<div id="view-import" class="view hidden">
|
||||
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
||||
AutistMask [import wallet]
|
||||
</h1>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1"
|
||||
>Seed phrase (12 or 24 words):</label
|
||||
>
|
||||
<textarea
|
||||
id="import-mnemonic"
|
||||
rows="3"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg resize-y"
|
||||
placeholder="word1 word2 word3 ..."
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1">Set password:</label>
|
||||
<input
|
||||
type="password"
|
||||
id="import-password"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="password"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1">Confirm password:</label>
|
||||
<input
|
||||
type="password"
|
||||
id="import-password-confirm"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="confirm password"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
id="btn-import-confirm"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
import wallet
|
||||
</button>
|
||||
<button
|
||||
id="btn-import-back"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
back
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
id="import-error"
|
||||
class="mt-2 border border-border border-dashed p-1 hidden"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- ============ MAIN / ACCOUNT VIEW ============ -->
|
||||
<div id="view-main" class="view hidden">
|
||||
<div
|
||||
class="flex justify-between items-center border-b border-border pb-1 mb-2"
|
||||
>
|
||||
<h1 class="font-bold">AutistMask</h1>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
id="btn-settings"
|
||||
class="border border-border px-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
title="settings"
|
||||
>
|
||||
[=]
|
||||
</button>
|
||||
<button
|
||||
id="btn-lock"
|
||||
class="border border-border px-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
title="lock"
|
||||
>
|
||||
[x]
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- account selector -->
|
||||
<div class="mb-2">
|
||||
<div class="flex justify-between items-center">
|
||||
<select
|
||||
id="account-selector"
|
||||
class="border border-border p-1 font-mono text-sm bg-bg text-fg flex-1 mr-2"
|
||||
></select>
|
||||
<button
|
||||
id="btn-copy-address"
|
||||
class="border border-border px-1 hover:bg-fg hover:text-bg cursor-pointer text-xs"
|
||||
title="copy address"
|
||||
>
|
||||
[cp]
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
id="current-address"
|
||||
class="text-xs text-muted mt-1 break-all"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- balance -->
|
||||
<div class="border-b border-border-light pb-2 mb-2">
|
||||
<div class="text-base font-bold">
|
||||
<span id="eth-balance">0.0000</span> ETH
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- action buttons -->
|
||||
<div class="flex gap-2 mb-3">
|
||||
<button
|
||||
id="btn-send"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer flex-1"
|
||||
>
|
||||
send
|
||||
</button>
|
||||
<button
|
||||
id="btn-receive"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer flex-1"
|
||||
>
|
||||
receive
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- tokens -->
|
||||
<div>
|
||||
<div
|
||||
class="flex justify-between items-center border-b border-border pb-1 mb-1"
|
||||
>
|
||||
<h2 class="font-bold">Tokens</h2>
|
||||
<button
|
||||
id="btn-add-token"
|
||||
class="border border-border px-1 hover:bg-fg hover:text-bg cursor-pointer text-xs"
|
||||
>
|
||||
[+]
|
||||
</button>
|
||||
</div>
|
||||
<div id="token-list">
|
||||
<div class="text-muted text-xs py-1">
|
||||
no tokens added
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ SEND VIEW ============ -->
|
||||
<div id="view-send" class="view hidden">
|
||||
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
||||
AutistMask [send]
|
||||
</h1>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1">Token:</label>
|
||||
<select
|
||||
id="send-token"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
>
|
||||
<option value="ETH">ETH</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1">To address:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="send-to"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="0x..."
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1">Amount:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="send-amount"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="0.0"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id="send-gas-estimate"
|
||||
class="text-xs text-muted mb-2 hidden"
|
||||
></div>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
id="btn-send-confirm"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
send
|
||||
</button>
|
||||
<button
|
||||
id="btn-send-back"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
back
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
id="send-status"
|
||||
class="mt-2 border border-border p-1 hidden"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- ============ RECEIVE VIEW ============ -->
|
||||
<div id="view-receive" class="view hidden">
|
||||
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
||||
AutistMask [receive]
|
||||
</h1>
|
||||
<p class="mb-2">Your address:</p>
|
||||
<div
|
||||
id="receive-address"
|
||||
class="border border-border p-2 font-mono break-all select-all mb-3"
|
||||
></div>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
id="btn-receive-copy"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
copy to clipboard
|
||||
</button>
|
||||
<button
|
||||
id="btn-receive-back"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ ADD TOKEN VIEW ============ -->
|
||||
<div id="view-add-token" class="view hidden">
|
||||
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
||||
AutistMask [add token]
|
||||
</h1>
|
||||
<div class="mb-2">
|
||||
<label class="block mb-1">Token contract address:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="add-token-address"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="0x..."
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id="add-token-info"
|
||||
class="text-xs text-muted mb-2 hidden"
|
||||
></div>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
id="btn-add-token-confirm"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
add token
|
||||
</button>
|
||||
<button
|
||||
id="btn-add-token-back"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
back
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
id="add-token-error"
|
||||
class="mt-2 border border-border border-dashed p-1 hidden"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- ============ SETTINGS VIEW ============ -->
|
||||
<div id="view-settings" class="view hidden">
|
||||
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
||||
AutistMask [settings]
|
||||
</h1>
|
||||
|
||||
<h2 class="font-bold mb-1">RPC Endpoint</h2>
|
||||
<div class="mb-3">
|
||||
<input
|
||||
type="text"
|
||||
id="settings-rpc"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="https://..."
|
||||
/>
|
||||
<button
|
||||
id="btn-save-rpc"
|
||||
class="border border-border px-2 py-1 mt-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
save
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h2 class="font-bold mb-1">Accounts</h2>
|
||||
<div class="mb-3">
|
||||
<button
|
||||
id="btn-derive-account"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
derive next account
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h2 class="font-bold mb-1">Wallets</h2>
|
||||
<div class="mb-3">
|
||||
<button
|
||||
id="btn-show-seed"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
show seed phrase
|
||||
</button>
|
||||
<button
|
||||
id="btn-import-additional"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
import another wallet
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
id="settings-seed-display"
|
||||
class="border border-border p-2 font-mono break-all mb-3 hidden"
|
||||
></div>
|
||||
|
||||
<h2 class="font-bold mb-1">Tokens</h2>
|
||||
<div id="settings-token-list" class="mb-3">
|
||||
<div class="text-muted text-xs">no tokens added</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-border pt-2">
|
||||
<button
|
||||
id="btn-settings-back"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ APPROVAL VIEW ============ -->
|
||||
<div id="view-approve" class="view hidden">
|
||||
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
||||
AutistMask [approve request]
|
||||
</h1>
|
||||
<div class="mb-2">
|
||||
<div class="text-xs text-muted mb-1">
|
||||
Site: <span id="approve-origin"></span>
|
||||
</div>
|
||||
<div class="font-bold mb-1" id="approve-type"></div>
|
||||
</div>
|
||||
<pre
|
||||
id="approve-details"
|
||||
class="border border-border p-2 text-xs overflow-auto mb-3 max-h-64"
|
||||
></pre>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
id="btn-approve"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
approve
|
||||
</button>
|
||||
<button
|
||||
id="btn-reject"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
reject
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -1,2 +1,372 @@
|
||||
// AutistMask popup UI
|
||||
// TODO: lock screen, account list, send/receive views
|
||||
// AutistMask popup UI — view management and event wiring
|
||||
// All wallet logic will live in background/; this file is purely UI.
|
||||
|
||||
const views = [
|
||||
"lock",
|
||||
"setup",
|
||||
"create",
|
||||
"import",
|
||||
"main",
|
||||
"send",
|
||||
"receive",
|
||||
"add-token",
|
||||
"settings",
|
||||
"approve",
|
||||
];
|
||||
|
||||
function showView(name) {
|
||||
for (const v of views) {
|
||||
const el = document.getElementById(`view-${v}`);
|
||||
if (el) {
|
||||
el.classList.toggle("hidden", v !== name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- mock state (will be replaced by background messaging) --
|
||||
const state = {
|
||||
locked: true,
|
||||
hasWallet: false,
|
||||
password: null,
|
||||
accounts: [],
|
||||
selectedAccount: 0,
|
||||
tokens: [],
|
||||
rpcUrl: "https://eth.llamarpc.com",
|
||||
mnemonic: null,
|
||||
};
|
||||
|
||||
// -- helpers --
|
||||
function $(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
function showError(id, msg) {
|
||||
const el = $(id);
|
||||
el.textContent = msg;
|
||||
el.classList.remove("hidden");
|
||||
}
|
||||
|
||||
function hideError(id) {
|
||||
$(id).classList.add("hidden");
|
||||
}
|
||||
|
||||
function truncateAddress(addr) {
|
||||
if (!addr) return "";
|
||||
return addr.slice(0, 6) + "..." + addr.slice(-4);
|
||||
}
|
||||
|
||||
function updateAccountSelector() {
|
||||
const sel = $("account-selector");
|
||||
sel.innerHTML = "";
|
||||
state.accounts.forEach((acct, i) => {
|
||||
const opt = document.createElement("option");
|
||||
opt.value = i;
|
||||
opt.textContent = `Account ${i}: ${truncateAddress(acct.address)}`;
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
sel.value = state.selectedAccount;
|
||||
$("current-address").textContent =
|
||||
state.accounts[state.selectedAccount]?.address || "";
|
||||
$("eth-balance").textContent =
|
||||
state.accounts[state.selectedAccount]?.balance || "0.0000";
|
||||
}
|
||||
|
||||
function updateTokenList() {
|
||||
const list = $("token-list");
|
||||
if (state.tokens.length === 0) {
|
||||
list.innerHTML =
|
||||
'<div class="text-muted text-xs py-1">no tokens added</div>';
|
||||
return;
|
||||
}
|
||||
list.innerHTML = state.tokens
|
||||
.map(
|
||||
(t) =>
|
||||
`<div class="py-1 border-b border-border-light flex justify-between">` +
|
||||
`<span>${t.symbol}</span>` +
|
||||
`<span>${t.balance || "0.0000"}</span>` +
|
||||
`</div>`,
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
function updateSendTokenSelect() {
|
||||
const sel = $("send-token");
|
||||
sel.innerHTML = '<option value="ETH">ETH</option>';
|
||||
state.tokens.forEach((t) => {
|
||||
const opt = document.createElement("option");
|
||||
opt.value = t.address;
|
||||
opt.textContent = t.symbol;
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
}
|
||||
|
||||
// -- init --
|
||||
function init() {
|
||||
// For now, always show setup (no wallet exists yet).
|
||||
// Once background messaging is wired, this will check actual state.
|
||||
if (!state.hasWallet) {
|
||||
showView("setup");
|
||||
} else if (state.locked) {
|
||||
showView("lock");
|
||||
} else {
|
||||
showView("main");
|
||||
}
|
||||
|
||||
// -- Lock screen --
|
||||
$("btn-unlock").addEventListener("click", () => {
|
||||
const pw = $("unlock-password").value;
|
||||
if (!pw) {
|
||||
showError("unlock-error", "enter a password");
|
||||
return;
|
||||
}
|
||||
hideError("unlock-error");
|
||||
// TODO: send unlock message to background
|
||||
state.locked = false;
|
||||
updateAccountSelector();
|
||||
updateTokenList();
|
||||
showView("main");
|
||||
});
|
||||
|
||||
// -- Setup --
|
||||
$("btn-setup-create").addEventListener("click", () => {
|
||||
// TODO: request mnemonic generation from background
|
||||
$("create-mnemonic").textContent =
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
|
||||
showView("create");
|
||||
});
|
||||
|
||||
$("btn-setup-import").addEventListener("click", () => {
|
||||
showView("import");
|
||||
});
|
||||
|
||||
// -- Create wallet --
|
||||
$("btn-create-confirm").addEventListener("click", () => {
|
||||
const pw = $("create-password").value;
|
||||
const pw2 = $("create-password-confirm").value;
|
||||
if (!pw) {
|
||||
showError("create-error", "enter a password");
|
||||
return;
|
||||
}
|
||||
if (pw !== pw2) {
|
||||
showError("create-error", "passwords do not match");
|
||||
return;
|
||||
}
|
||||
hideError("create-error");
|
||||
// TODO: send create wallet message to background
|
||||
state.hasWallet = true;
|
||||
state.locked = false;
|
||||
state.password = pw;
|
||||
state.mnemonic = $("create-mnemonic").textContent;
|
||||
state.accounts = [
|
||||
{
|
||||
address: "0x0000000000000000000000000000000000000001",
|
||||
balance: "0.0000",
|
||||
},
|
||||
];
|
||||
state.selectedAccount = 0;
|
||||
updateAccountSelector();
|
||||
updateTokenList();
|
||||
showView("main");
|
||||
});
|
||||
|
||||
$("btn-create-back").addEventListener("click", () => {
|
||||
showView("setup");
|
||||
});
|
||||
|
||||
// -- Import wallet --
|
||||
$("btn-import-confirm").addEventListener("click", () => {
|
||||
const mnemonic = $("import-mnemonic").value.trim();
|
||||
const pw = $("import-password").value;
|
||||
const pw2 = $("import-password-confirm").value;
|
||||
if (!mnemonic) {
|
||||
showError("import-error", "enter a seed phrase");
|
||||
return;
|
||||
}
|
||||
if (!pw) {
|
||||
showError("import-error", "enter a password");
|
||||
return;
|
||||
}
|
||||
if (pw !== pw2) {
|
||||
showError("import-error", "passwords do not match");
|
||||
return;
|
||||
}
|
||||
hideError("import-error");
|
||||
// TODO: validate mnemonic and send to background
|
||||
state.hasWallet = true;
|
||||
state.locked = false;
|
||||
state.password = pw;
|
||||
state.mnemonic = mnemonic;
|
||||
state.accounts = [
|
||||
{
|
||||
address: "0x0000000000000000000000000000000000000001",
|
||||
balance: "0.0000",
|
||||
},
|
||||
];
|
||||
state.selectedAccount = 0;
|
||||
updateAccountSelector();
|
||||
updateTokenList();
|
||||
showView("main");
|
||||
});
|
||||
|
||||
$("btn-import-back").addEventListener("click", () => {
|
||||
showView("setup");
|
||||
});
|
||||
|
||||
// -- Main view --
|
||||
$("btn-lock").addEventListener("click", () => {
|
||||
state.locked = true;
|
||||
$("unlock-password").value = "";
|
||||
showView("lock");
|
||||
});
|
||||
|
||||
$("btn-settings").addEventListener("click", () => {
|
||||
$("settings-rpc").value = state.rpcUrl;
|
||||
showView("settings");
|
||||
});
|
||||
|
||||
$("account-selector").addEventListener("change", (e) => {
|
||||
state.selectedAccount = parseInt(e.target.value, 10);
|
||||
$("current-address").textContent =
|
||||
state.accounts[state.selectedAccount]?.address || "";
|
||||
$("eth-balance").textContent =
|
||||
state.accounts[state.selectedAccount]?.balance || "0.0000";
|
||||
});
|
||||
|
||||
$("btn-copy-address").addEventListener("click", () => {
|
||||
const addr = state.accounts[state.selectedAccount]?.address;
|
||||
if (addr) {
|
||||
navigator.clipboard.writeText(addr);
|
||||
}
|
||||
});
|
||||
|
||||
$("btn-send").addEventListener("click", () => {
|
||||
updateSendTokenSelect();
|
||||
$("send-to").value = "";
|
||||
$("send-amount").value = "";
|
||||
$("send-gas-estimate").classList.add("hidden");
|
||||
$("send-status").classList.add("hidden");
|
||||
showView("send");
|
||||
});
|
||||
|
||||
$("btn-receive").addEventListener("click", () => {
|
||||
$("receive-address").textContent =
|
||||
state.accounts[state.selectedAccount]?.address || "";
|
||||
showView("receive");
|
||||
});
|
||||
|
||||
$("btn-add-token").addEventListener("click", () => {
|
||||
$("add-token-address").value = "";
|
||||
$("add-token-info").classList.add("hidden");
|
||||
hideError("add-token-error");
|
||||
showView("add-token");
|
||||
});
|
||||
|
||||
// -- Send --
|
||||
$("btn-send-confirm").addEventListener("click", () => {
|
||||
const to = $("send-to").value.trim();
|
||||
const amount = $("send-amount").value.trim();
|
||||
if (!to) {
|
||||
showError("send-status", "enter a recipient address");
|
||||
$("send-status").classList.remove("hidden");
|
||||
return;
|
||||
}
|
||||
if (!amount || isNaN(parseFloat(amount))) {
|
||||
showError("send-status", "enter a valid amount");
|
||||
$("send-status").classList.remove("hidden");
|
||||
return;
|
||||
}
|
||||
// TODO: construct and send transaction via background
|
||||
const el = $("send-status");
|
||||
el.textContent = "transaction sent (stub)";
|
||||
el.classList.remove("hidden");
|
||||
});
|
||||
|
||||
$("btn-send-back").addEventListener("click", () => {
|
||||
showView("main");
|
||||
});
|
||||
|
||||
// -- Receive --
|
||||
$("btn-receive-copy").addEventListener("click", () => {
|
||||
const addr = $("receive-address").textContent;
|
||||
if (addr) {
|
||||
navigator.clipboard.writeText(addr);
|
||||
}
|
||||
});
|
||||
|
||||
$("btn-receive-back").addEventListener("click", () => {
|
||||
showView("main");
|
||||
});
|
||||
|
||||
// -- Add Token --
|
||||
$("btn-add-token-confirm").addEventListener("click", () => {
|
||||
const addr = $("add-token-address").value.trim();
|
||||
if (!addr || !addr.startsWith("0x")) {
|
||||
showError("add-token-error", "enter a valid contract address");
|
||||
return;
|
||||
}
|
||||
hideError("add-token-error");
|
||||
// TODO: look up token name/symbol/decimals from contract via background
|
||||
state.tokens.push({
|
||||
address: addr,
|
||||
symbol: "TKN",
|
||||
decimals: 18,
|
||||
balance: "0.0000",
|
||||
});
|
||||
updateTokenList();
|
||||
showView("main");
|
||||
});
|
||||
|
||||
$("btn-add-token-back").addEventListener("click", () => {
|
||||
showView("main");
|
||||
});
|
||||
|
||||
// -- Settings --
|
||||
$("btn-save-rpc").addEventListener("click", () => {
|
||||
state.rpcUrl = $("settings-rpc").value.trim();
|
||||
// TODO: persist via background
|
||||
});
|
||||
|
||||
$("btn-derive-account").addEventListener("click", () => {
|
||||
const idx = state.accounts.length;
|
||||
// TODO: derive from seed via background
|
||||
state.accounts.push({
|
||||
address: `0x${idx.toString(16).padStart(40, "0")}`,
|
||||
balance: "0.0000",
|
||||
});
|
||||
updateAccountSelector();
|
||||
});
|
||||
|
||||
$("btn-show-seed").addEventListener("click", () => {
|
||||
const display = $("settings-seed-display");
|
||||
if (display.classList.contains("hidden")) {
|
||||
// TODO: require password re-entry, get from background
|
||||
display.textContent = state.mnemonic || "(no seed loaded)";
|
||||
display.classList.remove("hidden");
|
||||
} else {
|
||||
display.classList.add("hidden");
|
||||
}
|
||||
});
|
||||
|
||||
$("btn-import-additional").addEventListener("click", () => {
|
||||
showView("import");
|
||||
});
|
||||
|
||||
$("btn-settings-back").addEventListener("click", () => {
|
||||
updateAccountSelector();
|
||||
updateTokenList();
|
||||
showView("main");
|
||||
});
|
||||
|
||||
// -- Approval --
|
||||
$("btn-approve").addEventListener("click", () => {
|
||||
// TODO: send approval to background
|
||||
showView("main");
|
||||
});
|
||||
|
||||
$("btn-reject").addEventListener("click", () => {
|
||||
// TODO: send rejection to background
|
||||
showView("main");
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
@import "tailwindcss";
|
||||
|
||||
@theme {
|
||||
--font-mono:
|
||||
ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
|
||||
"Liberation Mono", monospace;
|
||||
--color-bg: #ffffff;
|
||||
--color-fg: #000000;
|
||||
--color-muted: #666666;
|
||||
--color-border: #000000;
|
||||
--color-border-light: #cccccc;
|
||||
--color-hover: #eeeeee;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 360px;
|
||||
min-height: 600px;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
background: #1a1a2e;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
#app {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
361
yarn.lock
361
yarn.lock
@ -270,7 +270,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@emnapi/core@^1.4.3":
|
||||
"@emnapi/core@^1.4.3", "@emnapi/core@^1.7.1", "@emnapi/core@^1.8.1":
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.8.1.tgz#fd9efe721a616288345ffee17a1f26ac5dd01349"
|
||||
integrity sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==
|
||||
@ -278,14 +278,14 @@
|
||||
"@emnapi/wasi-threads" "1.1.0"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@emnapi/runtime@^1.4.3":
|
||||
"@emnapi/runtime@^1.4.3", "@emnapi/runtime@^1.7.1", "@emnapi/runtime@^1.8.1":
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.8.1.tgz#550fa7e3c0d49c5fb175a116e8cd70614f9a22a5"
|
||||
integrity sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@emnapi/wasi-threads@1.1.0":
|
||||
"@emnapi/wasi-threads@1.1.0", "@emnapi/wasi-threads@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf"
|
||||
integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==
|
||||
@ -561,7 +561,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
|
||||
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0":
|
||||
"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5":
|
||||
version "1.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba"
|
||||
integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==
|
||||
@ -583,6 +583,104 @@
|
||||
"@emnapi/runtime" "^1.4.3"
|
||||
"@tybys/wasm-util" "^0.10.0"
|
||||
|
||||
"@napi-rs/wasm-runtime@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz#c3705ab549d176b8dc5172723d6156c3dc426af2"
|
||||
integrity sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==
|
||||
dependencies:
|
||||
"@emnapi/core" "^1.7.1"
|
||||
"@emnapi/runtime" "^1.7.1"
|
||||
"@tybys/wasm-util" "^0.10.1"
|
||||
|
||||
"@parcel/watcher-android-arm64@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz#5f32e0dba356f4ac9a11068d2a5c134ca3ba6564"
|
||||
integrity sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==
|
||||
|
||||
"@parcel/watcher-darwin-arm64@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz#88d3e720b59b1eceffce98dac46d7c40e8be5e8e"
|
||||
integrity sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==
|
||||
|
||||
"@parcel/watcher-darwin-x64@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz#bf05d76a78bc15974f15ec3671848698b0838063"
|
||||
integrity sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==
|
||||
|
||||
"@parcel/watcher-freebsd-x64@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz#8bc26e9848e7303ac82922a5ae1b1ef1bdb48a53"
|
||||
integrity sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==
|
||||
|
||||
"@parcel/watcher-linux-arm-glibc@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz#1328fee1deb0c2d7865079ef53a2ba4cc2f8b40a"
|
||||
integrity sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==
|
||||
|
||||
"@parcel/watcher-linux-arm-musl@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz#bad0f45cb3e2157746db8b9d22db6a125711f152"
|
||||
integrity sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==
|
||||
|
||||
"@parcel/watcher-linux-arm64-glibc@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz#b75913fbd501d9523c5f35d420957bf7d0204809"
|
||||
integrity sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==
|
||||
|
||||
"@parcel/watcher-linux-arm64-musl@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz#da5621a6a576070c8c0de60dea8b46dc9c3827d4"
|
||||
integrity sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==
|
||||
|
||||
"@parcel/watcher-linux-x64-glibc@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz#ce437accdc4b30f93a090b4a221fd95cd9b89639"
|
||||
integrity sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==
|
||||
|
||||
"@parcel/watcher-linux-x64-musl@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz#02400c54b4a67efcc7e2327b249711920ac969e2"
|
||||
integrity sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==
|
||||
|
||||
"@parcel/watcher-win32-arm64@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz#caae3d3c7583ca0a7171e6bd142c34d20ea1691e"
|
||||
integrity sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==
|
||||
|
||||
"@parcel/watcher-win32-ia32@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz#9ac922550896dfe47bfc5ae3be4f1bcaf8155d6d"
|
||||
integrity sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==
|
||||
|
||||
"@parcel/watcher-win32-x64@2.5.6":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz#73fdafba2e21c448f0e456bbe13178d8fe11739d"
|
||||
integrity sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==
|
||||
|
||||
"@parcel/watcher@^2.5.1":
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.6.tgz#3f932828c894f06d0ad9cfefade1756ecc6ef1f1"
|
||||
integrity sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==
|
||||
dependencies:
|
||||
detect-libc "^2.0.3"
|
||||
is-glob "^4.0.3"
|
||||
node-addon-api "^7.0.0"
|
||||
picomatch "^4.0.3"
|
||||
optionalDependencies:
|
||||
"@parcel/watcher-android-arm64" "2.5.6"
|
||||
"@parcel/watcher-darwin-arm64" "2.5.6"
|
||||
"@parcel/watcher-darwin-x64" "2.5.6"
|
||||
"@parcel/watcher-freebsd-x64" "2.5.6"
|
||||
"@parcel/watcher-linux-arm-glibc" "2.5.6"
|
||||
"@parcel/watcher-linux-arm-musl" "2.5.6"
|
||||
"@parcel/watcher-linux-arm64-glibc" "2.5.6"
|
||||
"@parcel/watcher-linux-arm64-musl" "2.5.6"
|
||||
"@parcel/watcher-linux-x64-glibc" "2.5.6"
|
||||
"@parcel/watcher-linux-x64-musl" "2.5.6"
|
||||
"@parcel/watcher-win32-arm64" "2.5.6"
|
||||
"@parcel/watcher-win32-ia32" "2.5.6"
|
||||
"@parcel/watcher-win32-x64" "2.5.6"
|
||||
|
||||
"@pkgjs/parseargs@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
@ -612,7 +710,118 @@
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^3.0.1"
|
||||
|
||||
"@tybys/wasm-util@^0.10.0":
|
||||
"@tailwindcss/cli@^4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/cli/-/cli-4.2.1.tgz#a61addb3c4935e3a3f6169cd3e5fb941a6404632"
|
||||
integrity sha512-b7MGn51IA80oSG+7fuAgzfQ+7pZBgjzbqwmiv6NO7/+a1sev32cGqnwhscT7h0EcAvMa9r7gjRylqOH8Xhc4DA==
|
||||
dependencies:
|
||||
"@parcel/watcher" "^2.5.1"
|
||||
"@tailwindcss/node" "4.2.1"
|
||||
"@tailwindcss/oxide" "4.2.1"
|
||||
enhanced-resolve "^5.19.0"
|
||||
mri "^1.2.0"
|
||||
picocolors "^1.1.1"
|
||||
tailwindcss "4.2.1"
|
||||
|
||||
"@tailwindcss/node@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.2.1.tgz#e963ac242a885353a4660e7e3e9c695cde7d3fc9"
|
||||
integrity sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==
|
||||
dependencies:
|
||||
"@jridgewell/remapping" "^2.3.5"
|
||||
enhanced-resolve "^5.19.0"
|
||||
jiti "^2.6.1"
|
||||
lightningcss "1.31.1"
|
||||
magic-string "^0.30.21"
|
||||
source-map-js "^1.2.1"
|
||||
tailwindcss "4.2.1"
|
||||
|
||||
"@tailwindcss/oxide-android-arm64@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz#a7c24919b607e7f884e6ab97799d12c7fb5b47bd"
|
||||
integrity sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==
|
||||
|
||||
"@tailwindcss/oxide-darwin-arm64@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz#6f6e91ff0e1b5476cc0dad0da1ea8474f4563212"
|
||||
integrity sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==
|
||||
|
||||
"@tailwindcss/oxide-darwin-x64@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz#1e59ef0665f6cb9e658bf0ebcb3cb50f21b2c175"
|
||||
integrity sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==
|
||||
|
||||
"@tailwindcss/oxide-freebsd-x64@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz#6b0c75e9dac7f1a241cb9a5eaa89f0d9664835b6"
|
||||
integrity sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==
|
||||
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz#717044d8fe746b1f0760485946c0c9a900174f7b"
|
||||
integrity sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-gnu@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz#f544b0faf166d80791347911b2dd4372a893129d"
|
||||
integrity sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-musl@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz#9fbaf8dc00b858a2b955526abb15d88f5678d1ef"
|
||||
integrity sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-gnu@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz#6ab4e6b8d308d037a1155b8443df5941dbfa6aa1"
|
||||
integrity sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-musl@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz#52c55593394dff85f1fa88172f69f8fdcde182b6"
|
||||
integrity sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz#7401e35f881d3654b6180badd1243d75a2702ea5"
|
||||
integrity sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==
|
||||
dependencies:
|
||||
"@emnapi/core" "^1.8.1"
|
||||
"@emnapi/runtime" "^1.8.1"
|
||||
"@emnapi/wasi-threads" "^1.1.0"
|
||||
"@napi-rs/wasm-runtime" "^1.1.1"
|
||||
"@tybys/wasm-util" "^0.10.1"
|
||||
tslib "^2.8.1"
|
||||
|
||||
"@tailwindcss/oxide-win32-arm64-msvc@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz#63a502e7b696dcd976aa356b94ce0f4f8f832c44"
|
||||
integrity sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==
|
||||
|
||||
"@tailwindcss/oxide-win32-x64-msvc@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz#8cc59b28ebc4dc866c0c14d7057f07f0ed04c4a8"
|
||||
integrity sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==
|
||||
|
||||
"@tailwindcss/oxide@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.2.1.tgz#43ae4217268a7e8b4736f1c056d0ef6f393c79d3"
|
||||
integrity sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==
|
||||
optionalDependencies:
|
||||
"@tailwindcss/oxide-android-arm64" "4.2.1"
|
||||
"@tailwindcss/oxide-darwin-arm64" "4.2.1"
|
||||
"@tailwindcss/oxide-darwin-x64" "4.2.1"
|
||||
"@tailwindcss/oxide-freebsd-x64" "4.2.1"
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf" "4.2.1"
|
||||
"@tailwindcss/oxide-linux-arm64-gnu" "4.2.1"
|
||||
"@tailwindcss/oxide-linux-arm64-musl" "4.2.1"
|
||||
"@tailwindcss/oxide-linux-x64-gnu" "4.2.1"
|
||||
"@tailwindcss/oxide-linux-x64-musl" "4.2.1"
|
||||
"@tailwindcss/oxide-wasm32-wasi" "4.2.1"
|
||||
"@tailwindcss/oxide-win32-arm64-msvc" "4.2.1"
|
||||
"@tailwindcss/oxide-win32-x64-msvc" "4.2.1"
|
||||
|
||||
"@tybys/wasm-util@^0.10.0", "@tybys/wasm-util@^0.10.1":
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414"
|
||||
integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==
|
||||
@ -1076,6 +1285,11 @@ deepmerge@^4.3.1:
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
|
||||
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
|
||||
|
||||
detect-libc@^2.0.3:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad"
|
||||
integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==
|
||||
|
||||
detect-newline@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
||||
@ -1106,6 +1320,14 @@ emoji-regex@^9.2.2:
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
|
||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||
|
||||
enhanced-resolve@^5.19.0:
|
||||
version "5.19.0"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz#6687446a15e969eaa63c2fa2694510e17ae6d97c"
|
||||
integrity sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.3.0"
|
||||
|
||||
error-ex@^1.3.1:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414"
|
||||
@ -1249,7 +1471,7 @@ glob@^7.1.4:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
graceful-fs@^4.2.11:
|
||||
graceful-fs@^4.2.11, graceful-fs@^4.2.4:
|
||||
version "4.2.11"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||
@ -1300,6 +1522,11 @@ is-arrayish@^0.2.1:
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
@ -1310,6 +1537,13 @@ is-generator-fn@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
|
||||
integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
|
||||
|
||||
is-glob@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
|
||||
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
|
||||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-number@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
@ -1732,6 +1966,11 @@ jest@^30.2.0:
|
||||
import-local "^3.2.0"
|
||||
jest-cli "30.2.0"
|
||||
|
||||
jiti@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.1.tgz#178ef2fc9a1a594248c20627cd820187a4d78d92"
|
||||
integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
@ -1765,6 +2004,80 @@ leven@^3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
|
||||
integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
|
||||
|
||||
lightningcss-android-arm64@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz#609ff48332adff452a8157a7c2842fd692a8eac4"
|
||||
integrity sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==
|
||||
|
||||
lightningcss-darwin-arm64@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz#a13da040a7929582bab3ace9a67bdc146e99fc2d"
|
||||
integrity sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==
|
||||
|
||||
lightningcss-darwin-x64@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz#f7482c311273571ec0c2bd8277c1f5f6e90e03a4"
|
||||
integrity sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==
|
||||
|
||||
lightningcss-freebsd-x64@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz#91df1bb290f1cb7bb2af832d7d0d8809225e0124"
|
||||
integrity sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==
|
||||
|
||||
lightningcss-linux-arm-gnueabihf@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz#c3cad5ae8b70045f21600dc95295ab6166acf57e"
|
||||
integrity sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==
|
||||
|
||||
lightningcss-linux-arm64-gnu@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz#a5c4f6a5ac77447093f61b209c0bd7fef1f0a3e3"
|
||||
integrity sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==
|
||||
|
||||
lightningcss-linux-arm64-musl@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz#af26ab8f829b727ada0a200938a6c8796ff36900"
|
||||
integrity sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==
|
||||
|
||||
lightningcss-linux-x64-gnu@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz#a891d44e84b71c0d88959feb9a7522bbf61450ee"
|
||||
integrity sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==
|
||||
|
||||
lightningcss-linux-x64-musl@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz#8c8b21def851f4d477fa897b80cb3db2b650bc6e"
|
||||
integrity sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz#79000fb8c57e94a91b8fc643e74d5a54407d7080"
|
||||
integrity sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==
|
||||
|
||||
lightningcss-win32-x64-msvc@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz#7f025274c81c7d659829731e09c8b6f442209837"
|
||||
integrity sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==
|
||||
|
||||
lightningcss@1.31.1:
|
||||
version "1.31.1"
|
||||
resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.31.1.tgz#1a19dd327b547a7eda1d5c296ebe1e72df5a184b"
|
||||
integrity sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==
|
||||
dependencies:
|
||||
detect-libc "^2.0.3"
|
||||
optionalDependencies:
|
||||
lightningcss-android-arm64 "1.31.1"
|
||||
lightningcss-darwin-arm64 "1.31.1"
|
||||
lightningcss-darwin-x64 "1.31.1"
|
||||
lightningcss-freebsd-x64 "1.31.1"
|
||||
lightningcss-linux-arm-gnueabihf "1.31.1"
|
||||
lightningcss-linux-arm64-gnu "1.31.1"
|
||||
lightningcss-linux-arm64-musl "1.31.1"
|
||||
lightningcss-linux-x64-gnu "1.31.1"
|
||||
lightningcss-linux-x64-musl "1.31.1"
|
||||
lightningcss-win32-arm64-msvc "1.31.1"
|
||||
lightningcss-win32-x64-msvc "1.31.1"
|
||||
|
||||
lines-and-columns@^1.1.6:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
@ -1789,6 +2102,13 @@ lru-cache@^5.1.1:
|
||||
dependencies:
|
||||
yallist "^3.0.2"
|
||||
|
||||
magic-string@^0.30.21:
|
||||
version "0.30.21"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91"
|
||||
integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==
|
||||
dependencies:
|
||||
"@jridgewell/sourcemap-codec" "^1.5.5"
|
||||
|
||||
make-dir@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e"
|
||||
@ -1840,6 +2160,11 @@ minimatch@^9.0.4:
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b"
|
||||
integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==
|
||||
|
||||
mri@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
|
||||
integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==
|
||||
|
||||
ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
@ -1855,6 +2180,11 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
node-addon-api@^7.0.0:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558"
|
||||
integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
|
||||
|
||||
node-int64@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
||||
@ -1965,7 +2295,7 @@ picomatch@^2.0.4, picomatch@^2.3.1:
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
picomatch@^4.0.2:
|
||||
picomatch@^4.0.2, picomatch@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042"
|
||||
integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==
|
||||
@ -2060,6 +2390,11 @@ slash@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
source-map-js@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
|
||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||
|
||||
source-map-support@0.5.13:
|
||||
version "0.5.13"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
|
||||
@ -2177,6 +2512,16 @@ synckit@^0.11.8:
|
||||
dependencies:
|
||||
"@pkgr/core" "^0.2.9"
|
||||
|
||||
tailwindcss@4.2.1, tailwindcss@^4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.2.1.tgz#018c4720b58baf98a6bf56b0a12aa797c6cfef1d"
|
||||
integrity sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==
|
||||
|
||||
tapable@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.0.tgz#7e3ea6d5ca31ba8e078b560f0d83ce9a14aa8be6"
|
||||
integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==
|
||||
|
||||
test-exclude@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
|
||||
@ -2198,7 +2543,7 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
tslib@^2.4.0:
|
||||
tslib@^2.4.0, tslib@^2.8.1:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
|
||||
Loading…
Reference in New Issue
Block a user