diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml
new file mode 100644
index 000000000..61df3717a
--- /dev/null
+++ b/.github/workflows/deploy-demo.yml
@@ -0,0 +1,103 @@
+name: Deploy Demo
+
+on:
+ push:
+ branches:
+ - '**'
+ delete:
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+concurrency:
+ group: pages-${{ github.ref_name }}
+ cancel-in-progress: true
+
+jobs:
+ build-and-deploy:
+ if: github.event_name != 'delete'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: pnpm/action-setup@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: pnpm
+
+ - run: pnpm install --frozen-lockfile
+
+ - name: Set environment variables
+ env:
+ BRANCH: ${{ github.ref_name }}
+ REPO_NAME: ${{ github.event.repository.name }}
+ OWNER: ${{ github.repository_owner }}
+ run: |
+ # Base path: /repo/ for main, /repo/branch/ for other branches
+ if [ "$BRANCH" = "main" ]; then
+ BASE_PATH="/${REPO_NAME}/"
+ DEST_DIR="."
+ else
+ BASE_PATH="/${REPO_NAME}/${BRANCH}/"
+ DEST_DIR="${BRANCH}"
+ fi
+
+ # Full URL for manifest
+ APP_URL="https://${OWNER}.github.io${BASE_PATH}"
+
+ echo "VITE_BASE_PATH=${BASE_PATH}" >> $GITHUB_ENV
+ echo "VITE_APP_URL=${APP_URL}" >> $GITHUB_ENV
+ echo "DEST_DIR=${DEST_DIR}" >> $GITHUB_ENV
+
+ echo "Building for: ${APP_URL}"
+ echo "Destination: ${DEST_DIR}"
+
+ - name: Build demo
+ run: pnpm build --filter tonconnect-demo
+ env:
+ VITE_APP_URL: ${{ env.VITE_APP_URL }}
+ VITE_BASE_PATH: ${{ env.VITE_BASE_PATH }}
+
+ - name: Deploy to GitHub Pages
+ uses: peaceiris/actions-gh-pages@v4
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: ./apps/tonconnect-demo/dist
+ destination_dir: ${{ env.DEST_DIR }}
+ keep_files: true
+
+ cleanup:
+ if: github.event_name == 'delete' && github.event.ref_type == 'branch'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: gh-pages
+ continue-on-error: true
+
+ - name: Remove stale deployment
+ env:
+ BRANCH: ${{ github.event.ref }}
+ run: |
+ # Skip if gh-pages doesn't exist or branch dir doesn't exist
+ if [ ! -d "$BRANCH" ]; then
+ echo "No deployment found for branch: $BRANCH"
+ exit 0
+ fi
+
+ # Don't delete root
+ if [ "$BRANCH" = "." ] || [ "$BRANCH" = "" ]; then
+ echo "Skipping invalid branch name"
+ exit 0
+ fi
+
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+
+ rm -rf "$BRANCH"
+ git add -A
+ git commit -m "Cleanup: remove deployment for deleted branch $BRANCH" || echo "No changes to commit"
+ git push origin gh-pages
diff --git a/apps/tonconnect-demo/.gitignore b/apps/tonconnect-demo/.gitignore
new file mode 100644
index 000000000..a547bf36d
--- /dev/null
+++ b/apps/tonconnect-demo/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/apps/tonconnect-demo/README.md b/apps/tonconnect-demo/README.md
new file mode 100644
index 000000000..fa297a4fc
--- /dev/null
+++ b/apps/tonconnect-demo/README.md
@@ -0,0 +1,84 @@
+# TonConnect Demo
+
+A demo application for testing and demonstrating TonConnect wallet integration features.
+
+## Features
+
+- **Transaction**: Send transactions with customizable parameters
+- **Sign Data**: Test data signing capabilities (text, cell, binary)
+- **Subscription**: Manage wallet subscriptions
+- **Ton Proof**: Authenticate using TON Proof
+- **Settings**: Configure TonConnect UI appearance and behavior
+
+## Getting Started
+
+```bash
+# Install dependencies
+pnpm install
+
+# Start development server
+pnpm dev --filter tonconnect-demo
+
+# Build for production
+VITE_APP_URL=https://your-domain.com pnpm build --filter tonconnect-demo
+```
+
+## Deployment
+
+The `tonconnect-manifest.json` is generated at build time based on the `VITE_APP_URL` environment variable.
+
+```bash
+# Local build
+VITE_APP_URL=https://your-domain.com pnpm build --filter tonconnect-demo
+
+# Or set in CI/CD environment variables (Vercel, GitHub Actions, etc.)
+```
+
+If `VITE_APP_URL` is not set, it defaults to `http://localhost:5173`.
+
+## DevTools
+
+The demo includes hidden developer tools for testing and debugging.
+
+### How to Activate
+
+1. Click on the "TonConnect Demo" title **5 times quickly** (within 2 seconds)
+2. A toast notification will confirm "DevTools unlocked!"
+3. A new "DevTools" tab will appear
+
+### Available Features
+
+#### QA Mode
+
+Enables testing mode from `@tonconnect/sdk`:
+
+- Disables strict validations (errors become console warnings)
+- Allows cross-network transactions (e.g., mainnet tx when wallet is on testnet)
+- Uses staging wallets list instead of production
+- Shows injected wallets in the list
+
+**Note**: Changing QA Mode requires a page reload to take full effect.
+
+#### Mobile Console (Eruda)
+
+Enables [Eruda](https://github.com/liriliri/eruda) - a mobile-friendly developer console:
+
+- Console logs viewer
+- Network requests inspector
+- DOM elements explorer
+- Storage viewer (localStorage, sessionStorage, cookies)
+
+Useful for debugging on mobile devices where browser DevTools are not available.
+
+### Hiding DevTools
+
+Click "Lock DevTools" button in the DevTools tab to hide it again. You can always re-activate it using the secret tap.
+
+## Tech Stack
+
+- React 19
+- TypeScript
+- Vite
+- Tailwind CSS
+- shadcn/ui components
+- MSW (Mock Service Worker) for API mocking
diff --git a/apps/tonconnect-demo/components.json b/apps/tonconnect-demo/components.json
new file mode 100644
index 000000000..1537d5030
--- /dev/null
+++ b/apps/tonconnect-demo/components.json
@@ -0,0 +1,22 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "new-york",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.js",
+ "css": "src/index.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "iconLibrary": "lucide",
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "registries": {}
+}
diff --git a/apps/tonconnect-demo/eslint.config.js b/apps/tonconnect-demo/eslint.config.js
new file mode 100644
index 000000000..38d3b9d55
--- /dev/null
+++ b/apps/tonconnect-demo/eslint.config.js
@@ -0,0 +1,43 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import tseslint from 'typescript-eslint'
+import { defineConfig, globalIgnores } from 'eslint/config'
+
+export default defineConfig([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ js.configs.recommended,
+ tseslint.configs.recommended,
+ reactHooks.configs.flat.recommended,
+ reactRefresh.configs.vite,
+ ],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ rules: {
+ // React Compiler rules are too strict for demo app patterns
+ 'react-hooks/set-state-in-effect': 'off',
+ 'react-hooks/preserve-manual-memoization': 'off',
+ },
+ },
+ // shadcn/ui components - allow non-component exports and empty interfaces
+ {
+ files: ['src/components/ui/**/*.{ts,tsx}'],
+ rules: {
+ 'react-refresh/only-export-components': 'off',
+ '@typescript-eslint/no-empty-object-type': 'off',
+ },
+ },
+ // Context files - allow exporting context + provider together
+ {
+ files: ['src/context/**/*.{ts,tsx}'],
+ rules: {
+ 'react-refresh/only-export-components': 'off',
+ },
+ },
+])
diff --git a/apps/tonconnect-demo/index.html b/apps/tonconnect-demo/index.html
new file mode 100644
index 000000000..dfa141770
--- /dev/null
+++ b/apps/tonconnect-demo/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+ TonConnect Demo
+
+
+
+
+
+
+
diff --git a/apps/tonconnect-demo/package.json b/apps/tonconnect-demo/package.json
new file mode 100644
index 000000000..9765cee86
--- /dev/null
+++ b/apps/tonconnect-demo/package.json
@@ -0,0 +1,82 @@
+{
+ "name": "tonconnect-demo",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@codemirror/lang-javascript": "^6.2.4",
+ "@codemirror/lang-json": "^6.0.2",
+ "@codemirror/language": "^6.12.1",
+ "@codemirror/view": "^6.39.11",
+ "@hookform/resolvers": "^5.2.2",
+ "@lezer/highlight": "^1.2.3",
+ "@radix-ui/react-checkbox": "^1.3.3",
+ "@radix-ui/react-collapsible": "^1.1.12",
+ "@radix-ui/react-dialog": "^1.1.15",
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
+ "@radix-ui/react-label": "^2.1.8",
+ "@radix-ui/react-scroll-area": "^1.2.10",
+ "@radix-ui/react-select": "^2.2.6",
+ "@radix-ui/react-slot": "^1.2.4",
+ "@radix-ui/react-switch": "^1.2.6",
+ "@radix-ui/react-tabs": "^1.1.13",
+ "@radix-ui/react-toast": "^1.2.15",
+ "@tailwindcss/typography": "^0.5.19",
+ "@tailwindcss/vite": "^4.1.18",
+ "@ton/core": "^0.62.1",
+ "@ton/crypto": "3.3.0",
+ "@ton/ton": "^16.1.0",
+ "@tonconnect/sdk": "workspace:*",
+ "@tonconnect/ui-react": "workspace:*",
+ "@uiw/react-codemirror": "^4.25.4",
+ "ajv": "^8.17.1",
+ "ajv-formats": "^3.0.1",
+ "autoprefixer": "^10.4.23",
+ "buffer": "^6.0.3",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "crc-32": "^1.2.2",
+ "eruda": "^3.4.3",
+ "jose": "^6.1.3",
+ "lucide-react": "^0.562.0",
+ "msw": "^2.12.7",
+ "next-themes": "^0.4.6",
+ "postcss": "^8.5.6",
+ "react": "^19.2.3",
+ "react-dom": "^19.2.3",
+ "react-markdown": "^10.1.0",
+ "remark-gfm": "^4.0.1",
+ "sonner": "^2.0.7",
+ "tailwind-merge": "^3.4.0",
+ "tailwindcss": "^4.1.18",
+ "tailwindcss-animate": "^1.0.7",
+ "tweetnacl": "^1.0.3",
+ "yaml": "^2.8.2",
+ "zod": "^4.3.5"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.39.1",
+ "@types/node": "^24.10.8",
+ "@types/react": "^19.2.5",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^5.1.1",
+ "eslint": "^9.39.1",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.4.24",
+ "globals": "^16.5.0",
+ "typescript": "~5.9.3",
+ "typescript-eslint": "^8.46.4",
+ "vite": "^7.2.4"
+ },
+ "msw": {
+ "workerDirectory": [
+ "public"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/apps/tonconnect-demo/public/favicon.png b/apps/tonconnect-demo/public/favicon.png
new file mode 100644
index 000000000..0f2afc34e
Binary files /dev/null and b/apps/tonconnect-demo/public/favicon.png differ
diff --git a/apps/tonconnect-demo/public/mockServiceWorker.js b/apps/tonconnect-demo/public/mockServiceWorker.js
new file mode 100644
index 000000000..9f6b16be1
--- /dev/null
+++ b/apps/tonconnect-demo/public/mockServiceWorker.js
@@ -0,0 +1,360 @@
+/* eslint-disable */
+/* tslint:disable */
+
+/**
+ * Mock Service Worker.
+ * @see https://github.com/mswjs/msw
+ * - Please do NOT modify this file.
+ */
+
+const PACKAGE_VERSION = '2.12.7'
+const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82'
+const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
+const activeClientIds = new Set()
+
+addEventListener('install', function () {
+ self.skipWaiting()
+})
+
+addEventListener('activate', function (event) {
+ event.waitUntil(self.clients.claim())
+})
+
+addEventListener('message', async function (event) {
+ const clientId = Reflect.get(event.source || {}, 'id')
+
+ if (!clientId || !self.clients) {
+ return
+ }
+
+ const client = await self.clients.get(clientId)
+
+ if (!client) {
+ return
+ }
+
+ const allClients = await self.clients.matchAll({
+ type: 'window',
+ })
+
+ switch (event.data) {
+ case 'KEEPALIVE_REQUEST': {
+ sendToClient(client, {
+ type: 'KEEPALIVE_RESPONSE',
+ })
+ break
+ }
+
+ case 'INTEGRITY_CHECK_REQUEST': {
+ sendToClient(client, {
+ type: 'INTEGRITY_CHECK_RESPONSE',
+ payload: {
+ packageVersion: PACKAGE_VERSION,
+ checksum: INTEGRITY_CHECKSUM,
+ },
+ })
+ break
+ }
+
+ case 'MOCK_ACTIVATE': {
+ activeClientIds.add(clientId)
+
+ sendToClient(client, {
+ type: 'MOCKING_ENABLED',
+ payload: {
+ client: {
+ id: client.id,
+ frameType: client.frameType,
+ },
+ },
+ })
+ break
+ }
+
+ case 'CLIENT_CLOSED': {
+ activeClientIds.delete(clientId)
+
+ const remainingClients = allClients.filter((client) => {
+ return client.id !== clientId
+ })
+
+ // Unregister itself when there are no more clients
+ if (remainingClients.length === 0) {
+ self.registration.unregister()
+ }
+
+ break
+ }
+ }
+})
+
+addEventListener('fetch', function (event) {
+ const requestInterceptedAt = Date.now()
+
+ // Bypass navigation requests.
+ if (event.request.mode === 'navigate') {
+ return
+ }
+
+ // Opening the DevTools triggers the "only-if-cached" request
+ // that cannot be handled by the worker. Bypass such requests.
+ if (
+ event.request.cache === 'only-if-cached' &&
+ event.request.mode !== 'same-origin'
+ ) {
+ return
+ }
+
+ // Bypass all requests when there are no active clients.
+ // Prevents the self-unregistered worked from handling requests
+ // after it's been terminated (still remains active until the next reload).
+ if (activeClientIds.size === 0) {
+ return
+ }
+
+ // Bypass event source requests (TonConnect SSE).
+ const url = new URL(event.request.url)
+ if (url.pathname.endsWith('/events')) {
+ return
+ }
+
+ // Bypass cross-origin requests except /api/*
+ if (url.origin !== location.origin && !url.pathname.startsWith('/api')) {
+ return
+ }
+
+ const requestId = crypto.randomUUID()
+ event.respondWith(handleRequest(event, requestId, requestInterceptedAt))
+})
+
+/**
+ * @param {FetchEvent} event
+ * @param {string} requestId
+ * @param {number} requestInterceptedAt
+ */
+async function handleRequest(event, requestId, requestInterceptedAt) {
+ const client = await resolveMainClient(event)
+ const requestCloneForEvents = event.request.clone()
+ const response = await getResponse(
+ event,
+ client,
+ requestId,
+ requestInterceptedAt,
+ )
+
+ // Send back the response clone for the "response:*" life-cycle events.
+ // Ensure MSW is active and ready to handle the message, otherwise
+ // this message will pend indefinitely.
+ if (client && activeClientIds.has(client.id)) {
+ const serializedRequest = await serializeRequest(requestCloneForEvents)
+
+ // Clone the response so both the client and the library could consume it.
+ const responseClone = response.clone()
+
+ sendToClient(
+ client,
+ {
+ type: 'RESPONSE',
+ payload: {
+ isMockedResponse: IS_MOCKED_RESPONSE in response,
+ request: {
+ id: requestId,
+ ...serializedRequest,
+ },
+ response: {
+ type: responseClone.type,
+ status: responseClone.status,
+ statusText: responseClone.statusText,
+ headers: Object.fromEntries(responseClone.headers.entries()),
+ body: responseClone.body,
+ },
+ },
+ },
+ responseClone.body ? [serializedRequest.body, responseClone.body] : [],
+ )
+ }
+
+ return response
+}
+
+/**
+ * Resolve the main client for the given event.
+ * Client that issues a request doesn't necessarily equal the client
+ * that registered the worker. It's with the latter the worker should
+ * communicate with during the response resolving phase.
+ * @param {FetchEvent} event
+ * @returns {Promise}
+ */
+async function resolveMainClient(event) {
+ const client = await self.clients.get(event.clientId)
+
+ if (activeClientIds.has(event.clientId)) {
+ return client
+ }
+
+ if (client?.frameType === 'top-level') {
+ return client
+ }
+
+ const allClients = await self.clients.matchAll({
+ type: 'window',
+ })
+
+ return allClients
+ .filter((client) => {
+ // Get only those clients that are currently visible.
+ return client.visibilityState === 'visible'
+ })
+ .find((client) => {
+ // Find the client ID that's recorded in the
+ // set of clients that have registered the worker.
+ return activeClientIds.has(client.id)
+ })
+}
+
+/**
+ * @param {FetchEvent} event
+ * @param {Client | undefined} client
+ * @param {string} requestId
+ * @param {number} requestInterceptedAt
+ * @returns {Promise}
+ */
+async function getResponse(event, client, requestId, requestInterceptedAt) {
+ // Clone the request because it might've been already used
+ // (i.e. its body has been read and sent to the client).
+ const requestClone = event.request.clone()
+
+ function passthrough() {
+ // Cast the request headers to a new Headers instance
+ // so the headers can be manipulated with.
+ const headers = new Headers(requestClone.headers)
+
+ // Remove the "accept" header value that marked this request as passthrough.
+ // This prevents request alteration and also keeps it compliant with the
+ // user-defined CORS policies.
+ const acceptHeader = headers.get('accept')
+ if (acceptHeader) {
+ const values = acceptHeader.split(',').map((value) => value.trim())
+ const filteredValues = values.filter(
+ (value) => value !== 'msw/passthrough',
+ )
+
+ if (filteredValues.length > 0) {
+ headers.set('accept', filteredValues.join(', '))
+ } else {
+ headers.delete('accept')
+ }
+ }
+
+ return fetch(requestClone, { headers })
+ }
+
+ // Bypass mocking when the client is not active.
+ if (!client) {
+ return passthrough()
+ }
+
+ // Bypass initial page load requests (i.e. static assets).
+ // The absence of the immediate/parent client in the map of the active clients
+ // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
+ // and is not ready to handle requests.
+ if (!activeClientIds.has(client.id)) {
+ return passthrough()
+ }
+
+ // Notify the client that a request has been intercepted.
+ const serializedRequest = await serializeRequest(event.request)
+ const clientMessage = await sendToClient(
+ client,
+ {
+ type: 'REQUEST',
+ payload: {
+ id: requestId,
+ interceptedAt: requestInterceptedAt,
+ ...serializedRequest,
+ },
+ },
+ [serializedRequest.body],
+ )
+
+ switch (clientMessage.type) {
+ case 'MOCK_RESPONSE': {
+ return respondWithMock(clientMessage.data)
+ }
+
+ case 'PASSTHROUGH': {
+ return passthrough()
+ }
+ }
+
+ return passthrough()
+}
+
+/**
+ * @param {Client} client
+ * @param {any} message
+ * @param {Array} transferrables
+ * @returns {Promise}
+ */
+function sendToClient(client, message, transferrables = []) {
+ return new Promise((resolve, reject) => {
+ const channel = new MessageChannel()
+
+ channel.port1.onmessage = (event) => {
+ if (event.data && event.data.error) {
+ return reject(event.data.error)
+ }
+
+ resolve(event.data)
+ }
+
+ client.postMessage(message, [
+ channel.port2,
+ ...transferrables.filter(Boolean),
+ ])
+ })
+}
+
+/**
+ * @param {Response} response
+ * @returns {Response}
+ */
+function respondWithMock(response) {
+ // Setting response status code to 0 is a no-op.
+ // However, when responding with a "Response.error()", the produced Response
+ // instance will have status code set to 0. Since it's not possible to create
+ // a Response instance with status code 0, handle that use-case separately.
+ if (response.status === 0) {
+ return Response.error()
+ }
+
+ const mockedResponse = new Response(response.body, response)
+
+ Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {
+ value: true,
+ enumerable: true,
+ })
+
+ return mockedResponse
+}
+
+/**
+ * @param {Request} request
+ */
+async function serializeRequest(request) {
+ return {
+ url: request.url,
+ mode: request.mode,
+ method: request.method,
+ headers: Object.fromEntries(request.headers.entries()),
+ cache: request.cache,
+ credentials: request.credentials,
+ destination: request.destination,
+ integrity: request.integrity,
+ redirect: request.redirect,
+ referrer: request.referrer,
+ referrerPolicy: request.referrerPolicy,
+ body: await request.arrayBuffer(),
+ keepalive: request.keepalive,
+ }
+}
diff --git a/apps/tonconnect-demo/public/privacy-policy.txt b/apps/tonconnect-demo/public/privacy-policy.txt
new file mode 100644
index 000000000..72e27fee3
--- /dev/null
+++ b/apps/tonconnect-demo/public/privacy-policy.txt
@@ -0,0 +1,10 @@
+This is a demonstration file for the TonConnect manifest.
+
+In a real application, this file may contain your Privacy Policy, for example:
+- What data you collect
+- How you use and store this data
+- User rights
+- etc.
+
+The privacyPolicyUrl field in tonconnect-manifest.json points to this file.
+Wallets may display this link to users during connection.
diff --git a/apps/tonconnect-demo/public/terms-of-use.txt b/apps/tonconnect-demo/public/terms-of-use.txt
new file mode 100644
index 000000000..578007bd4
--- /dev/null
+++ b/apps/tonconnect-demo/public/terms-of-use.txt
@@ -0,0 +1,10 @@
+This is a demonstration file for the TonConnect manifest.
+
+In a real application, this file may contain your Terms of Use, for example:
+- Service description and usage rules
+- User responsibilities
+- Liability limitations
+- etc.
+
+The termsOfUseUrl field in tonconnect-manifest.json points to this file.
+Wallets may display this link to users during connection.
diff --git a/apps/tonconnect-demo/src/App.tsx b/apps/tonconnect-demo/src/App.tsx
new file mode 100644
index 000000000..1c7d9cfe5
--- /dev/null
+++ b/apps/tonconnect-demo/src/App.tsx
@@ -0,0 +1,15 @@
+import { TonConnectUIProvider } from '@tonconnect/ui-react'
+import { DevToolsProvider } from '@/context/DevToolsContext'
+import { DemoContent } from '@/components/DemoContent'
+
+function App() {
+ return (
+
+
+
+
+
+ )
+}
+
+export default App
diff --git a/apps/tonconnect-demo/src/components/DemoContent.tsx b/apps/tonconnect-demo/src/components/DemoContent.tsx
new file mode 100644
index 000000000..e8c234e43
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/DemoContent.tsx
@@ -0,0 +1,94 @@
+import { useMemo } from "react"
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
+import { Toaster } from "@/components/ui/sonner"
+import { SettingsProvider } from "@/context/SettingsContext"
+import { useDevToolsContext } from "@/context/DevToolsContext"
+import { useHashTab } from "@/hooks/useHashTab"
+import { useSdkLogs } from "@/hooks/useSdkLogs"
+import { Header } from "./Header"
+import { RpcLogViewer } from "./shared/RpcLogViewer"
+import { TransactionTab, SignDataTab, SubscriptionTab, ConnectTab, SettingsTab, DevToolsTab } from "./tabs"
+
+const ALL_TABS = ["transaction", "sign", "subscription", "connect", "settings", "devtools"] as const
+const PUBLIC_TABS = ALL_TABS.filter(t => t !== "devtools")
+const DEFAULT_TAB = "transaction"
+
+function DemoContentInner() {
+ const { isUnlocked, rpcLogsEnabled } = useDevToolsContext()
+
+ // SDK RPC logs (only active when toggle is enabled)
+ const { logs, clearLogs } = useSdkLogs(rpcLogsEnabled)
+
+ // Valid tabs depend on DevTools unlock state
+ const validTabs = useMemo(
+ () => (isUnlocked ? [...ALL_TABS] : [...PUBLIC_TABS]),
+ [isUnlocked]
+ )
+
+ // Sync tab with URL hash, auto-redirect if tab becomes invalid
+ const [tab, setTab] = useHashTab(validTabs, DEFAULT_TAB)
+
+ return (
+
+
+
+
+
+
+ Transaction
+ Sign Data
+ Subscription
+ Connect
+ Settings
+ {isUnlocked && (
+ DevTools
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {isUnlocked && (
+
+
+
+ )}
+
+
+
+ {/* RPC Logs footer - visible on all tabs when enabled */}
+ {rpcLogsEnabled && (
+
+ )}
+
+
+
+ )
+}
+
+export function DemoContent() {
+ return (
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/Header.tsx b/apps/tonconnect-demo/src/components/Header.tsx
new file mode 100644
index 000000000..7d9a1ed5b
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/Header.tsx
@@ -0,0 +1,103 @@
+import { TonConnectButton } from "@tonconnect/ui-react"
+import { useSettingsContext } from "@/context/SettingsContext"
+import { useDevToolsContext } from "@/context/DevToolsContext"
+import { Monitor, Sun, Moon } from "lucide-react"
+import { useRef, useCallback } from "react"
+import { toast } from "sonner"
+import type { ThemeOption } from "@/hooks/useSettings"
+
+const SECRET_TAP_COUNT = 5
+const SECRET_TAP_TIMEOUT = 2000 // 2 seconds window for taps
+
+export function Header() {
+ const { theme, setTheme } = useSettingsContext()
+ const { isUnlocked, unlockDevTools } = useDevToolsContext()
+
+ const tapCountRef = useRef(0)
+ const tapTimeoutRef = useRef | null>(null)
+
+ const handleTitleClick = useCallback(() => {
+ if (isUnlocked) return // Already unlocked
+
+ tapCountRef.current += 1
+
+ // Clear existing timeout
+ if (tapTimeoutRef.current) {
+ clearTimeout(tapTimeoutRef.current)
+ }
+
+ // Check if reached required taps
+ if (tapCountRef.current >= SECRET_TAP_COUNT) {
+ tapCountRef.current = 0
+ unlockDevTools()
+ toast.success("DevTools unlocked!", {
+ description: "Check the DevTools tab to configure debug options"
+ })
+ return
+ }
+
+ // Reset counter after timeout
+ tapTimeoutRef.current = setTimeout(() => {
+ tapCountRef.current = 0
+ }, SECRET_TAP_TIMEOUT)
+ }, [isUnlocked, unlockDevTools])
+
+ const themes: { value: ThemeOption; icon: typeof Monitor; label: string }[] = [
+ { value: "system", icon: Monitor, label: "System" },
+ { value: "light", icon: Sun, label: "Light" },
+ { value: "dark", icon: Moon, label: "Dark" },
+ ]
+
+ const currentThemeIndex = themes.findIndex(t => t.value === theme)
+ const CurrentIcon = themes[currentThemeIndex]?.icon || Monitor
+
+ const cycleTheme = useCallback(() => {
+ const nextIndex = (currentThemeIndex + 1) % themes.length
+ setTheme(themes[nextIndex].value)
+ }, [currentThemeIndex, setTheme])
+
+ return (
+
+
+
+
+ TonConnect Demo
+
+
+ Test and demonstrate wallet integration
+
+
+
+ {/* Theme toggle - single button on mobile, segmented on desktop */}
+
+
+
+
+ {themes.map(({ value, icon: Icon, label }) => (
+ setTheme(value)}
+ title={label}
+ className={`flex items-center justify-center h-8 w-8 rounded-sm transition-colors ${
+ theme === value
+ ? "bg-background text-foreground shadow-sm"
+ : "text-muted-foreground hover:text-foreground"
+ }`}
+ >
+
+
+ ))}
+
+
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/NetworkPicker.tsx b/apps/tonconnect-demo/src/components/NetworkPicker.tsx
new file mode 100644
index 000000000..9dc8e252a
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/NetworkPicker.tsx
@@ -0,0 +1,67 @@
+import { useEffect } from "react"
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
+import { Label } from "@/components/ui/label"
+import { useSettingsContext } from "@/context/SettingsContext"
+import { useTonConnectUI, useTonWallet } from "@tonconnect/ui-react"
+
+function getNetworkLabel(chain: string): string {
+ switch (chain) {
+ case "-239": return "Mainnet"
+ case "-3": return "Testnet"
+ default: return chain
+ }
+}
+
+export function NetworkPicker() {
+ const { selectedNetwork, setSelectedNetwork } = useSettingsContext()
+ const [tonConnectUI] = useTonConnectUI()
+ const wallet = useTonWallet()
+
+ const isConnected = !!wallet
+ const walletNetwork = wallet?.account?.chain
+
+ // Sync selected network with TonConnect SDK (only when not connected)
+ useEffect(() => {
+ if (!isConnected) {
+ const chainId = selectedNetwork || undefined
+ tonConnectUI.setConnectionNetwork(chainId)
+ }
+ }, [selectedNetwork, tonConnectUI, isConnected])
+
+ // When connected, show wallet's network
+ // When not connected, show selected network or "any"
+ const displayValue = isConnected && walletNetwork ? walletNetwork : (selectedNetwork || "any")
+ const handleChange = (v: string) => setSelectedNetwork(v === "any" ? "" : v)
+
+ return (
+
+
Network
+
+
+
+ {isConnected && walletNetwork
+ ? `${getNetworkLabel(walletNetwork)} (connected)`
+ : displayValue === "any"
+ ? "Any Network"
+ : getNetworkLabel(displayValue)
+ }
+
+
+
+ Any Network
+ Mainnet
+ Testnet
+
+
+ {isConnected && (
+
+ Network is determined by connected wallet
+
+ )}
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/BaseResultCard.tsx b/apps/tonconnect-demo/src/components/shared/BaseResultCard.tsx
new file mode 100644
index 000000000..da321e0da
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/BaseResultCard.tsx
@@ -0,0 +1,95 @@
+import type { ReactNode } from "react"
+import { Button } from "@/components/ui/button"
+import { JsonViewer } from "./JsonViewer"
+import { X, RotateCcw } from "lucide-react"
+
+/** Base result data that all result types share */
+export interface BaseResultData {
+ id: string
+ timestamp: number
+ requestSnapshot: string
+ response: string
+ status: "success" | "error"
+}
+
+/** JsonViewer configuration options */
+export interface JsonViewerConfig {
+ maxHeight?: number
+ defaultExpanded?: boolean
+ inlineThreshold?: number
+}
+
+/** Props for BaseResultCard */
+export interface BaseResultCardProps {
+ result: BaseResultData
+ statusBar: ReactNode
+ responseFooter?: ReactNode
+ onDismiss?: () => void
+ onLoadToForm?: () => void
+ requestViewerProps?: JsonViewerConfig
+ responseViewerProps?: JsonViewerConfig
+}
+
+export function BaseResultCard({
+ result,
+ statusBar,
+ responseFooter,
+ onDismiss,
+ onLoadToForm,
+ requestViewerProps = {},
+ responseViewerProps = {},
+}: BaseResultCardProps) {
+ return (
+
+ {/* Header: timestamp + dismiss */}
+
+
+ {new Date(result.timestamp).toLocaleTimeString()}
+
+ {onDismiss && (
+
+
+
+ )}
+
+
+ {/* Status Bar */}
+ {statusBar}
+
+ {/* Content: 2-column layout on desktop */}
+
+ {/* Left column: Request Sent */}
+
+
+
+
+ {/* Right column: Response + optional footer */}
+
+
+ {responseFooter}
+
+
+
+ {/* Footer: Load to form button */}
+ {onLoadToForm && (
+
+
+
+ Load Request to Form
+
+
+ )}
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/ConnectedWalletCard.tsx b/apps/tonconnect-demo/src/components/shared/ConnectedWalletCard.tsx
new file mode 100644
index 000000000..99d13f486
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/ConnectedWalletCard.tsx
@@ -0,0 +1,260 @@
+import { useState, useMemo } from "react"
+import { Card, CardContent } from "@/components/ui/card"
+import { Button } from "@/components/ui/button"
+import { Badge } from "@/components/ui/badge"
+import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
+import { JsonViewer } from "./JsonViewer"
+import { Circle, Unplug, ChevronRight, Copy, Check, Smartphone, Monitor, Package, Link } from "lucide-react"
+import { toast } from "sonner"
+import { toUserFriendlyAddress, CHAIN, type Feature } from "@tonconnect/sdk"
+import type { Wallet } from "@tonconnect/ui-react"
+
+interface ConnectedWalletCardProps {
+ wallet: Wallet | null
+ isAuthenticated?: boolean // kept for API compatibility, not used in UI
+ onDisconnect: () => void
+}
+
+function getNetworkName(chain: string): string {
+ return chain === '-239' ? 'Mainnet' : 'Testnet'
+}
+
+function getPlatformIcon(platform: string) {
+ if (['iphone', 'ipad', 'android'].includes(platform)) {
+ return
+ }
+ return
+}
+
+// Deduplicate and format features
+function processFeatures(features: Feature[]): string[] {
+ const seen = new Map()
+
+ for (const feature of features) {
+ if (typeof feature === 'string') {
+ if (!seen.has(feature)) {
+ seen.set(feature, feature)
+ }
+ } else {
+ const f = feature as { name: string; maxMessages?: number; extraCurrencySupported?: boolean; types?: string[] }
+ let formatted = f.name
+
+ if (f.name === 'SendTransaction') {
+ const details: string[] = []
+ if (f.maxMessages) details.push(`${f.maxMessages}`)
+ if (f.extraCurrencySupported) details.push('extra')
+ formatted = details.length > 0 ? `SendTx(${details.join(',')})` : 'SendTx'
+ } else if (f.name === 'SignData' && f.types) {
+ const types = f.types.map(t => t === 'binary' ? 'bin' : t)
+ formatted = `SignData(${types.join(',')})`
+ }
+
+ seen.set(f.name, formatted)
+ }
+ }
+
+ return Array.from(seen.values())
+}
+
+// Truncate address showing start and end (e.g., "UQDa...bfef")
+function truncateAddress(address: string, startChars = 8, endChars = 4): string {
+ if (address.length <= startChars + endChars + 3) return address
+ return `${address.slice(0, startChars)}...${address.slice(-endChars)}`
+}
+
+function CopyButton({ text, label = "Copied" }: { text: string; label?: string }) {
+ const [copied, setCopied] = useState(false)
+
+ const handleCopy = async () => {
+ await navigator.clipboard.writeText(text)
+ setCopied(true)
+ toast.success(label)
+ setTimeout(() => setCopied(false), 2000)
+ }
+
+ return (
+
+ {copied ? : }
+
+ )
+}
+
+export function ConnectedWalletCard({ wallet, onDisconnect }: ConnectedWalletCardProps) {
+ const isConnected = !!wallet
+ const hasProof = wallet?.connectItems?.tonProof && !('error' in wallet.connectItems.tonProof)
+
+ const friendlyAddress = isConnected
+ ? toUserFriendlyAddress(wallet.account.address, wallet.account.chain === CHAIN.TESTNET)
+ : ''
+
+ const deviceFeatures = wallet?.device.features
+ const features = useMemo(() => {
+ if (!deviceFeatures) return []
+ return processFeatures(deviceFeatures)
+ }, [deviceFeatures])
+
+ // Responsive address display
+ const shortAddress = truncateAddress(friendlyAddress, 10, 6)
+ const mediumAddress = truncateAddress(friendlyAddress, 16, 8)
+
+ return (
+
+
+ {isConnected ? (
+ <>
+ {/* Row 1: Status + Info (left) | Disconnect (right, fixed) */}
+
+ {/* Left side - wraps as needed */}
+
+ {/* Status */}
+
+
+ Connected
+
+
+ {/* Address - truncated with visible end */}
+
+
+ {shortAddress}
+ {mediumAddress}
+ {friendlyAddress}
+
+
+
+
+ {/* Network + TonProof (wrap together) */}
+
+
+ {getNetworkName(wallet.account.chain)}
+
+ {hasProof && (
+
+ TonProof
+
+ )}
+
+
+
+ {/* Right side - Disconnect ALWAYS top-right */}
+
+
+ Disconnect
+
+
+
+ {/* Row 2: Wallet details + Features + Raw toggle */}
+
+ {/* Wallet info row - with Features inline on lg+ */}
+
+
+ {/* Wallet name */}
+
{wallet.device.appName}
+
•
+
+ {/* Platform */}
+
+ {getPlatformIcon(wallet.device.platform)}
+ Platform:
+ {wallet.device.platform}
+
+
•
+
+ {/* Version */}
+
+
+
Version:
+
{wallet.device.appVersion}
+
+
•
+
+ {/* Provider */}
+
+
+ Provider:
+ {wallet.provider}
+
+
+ {/* Features - inline on lg+ */}
+ {features.length > 0 && (
+ <>
+
•
+
+ Features:
+ {features.map((feature, i) => (
+
+ {feature}
+
+ ))}
+
+ >
+ )}
+
+
+ {/* Raw toggle - on lg+ stays on this row, right side */}
+
+
+ Raw
+
+
+
+ {/* Features + Raw toggle row - ONLY on smaller screens (< lg) */}
+
+ {/* Features */}
+ {features.length > 0 ? (
+
+ Features:
+ {features.map((feature, i) => (
+
+ {feature}
+
+ ))}
+
+ ) : (
+
+ )}
+
+ {/* Raw toggle */}
+
+
+ Raw
+
+
+
+ {/* Raw JSON content */}
+
+
+
+
+ >
+ ) : (
+
+
+
+ No wallet connected — use the options below
+
+
+ )}
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/ConnectionEventsCard.tsx b/apps/tonconnect-demo/src/components/shared/ConnectionEventsCard.tsx
new file mode 100644
index 000000000..0d25440a7
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/ConnectionEventsCard.tsx
@@ -0,0 +1,549 @@
+import { useState, useMemo } from "react"
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from "@/components/ui/collapsible"
+import { Button } from "@/components/ui/button"
+import { Badge } from "@/components/ui/badge"
+import { JsonViewer } from "./JsonViewer"
+import {
+ ChevronRight,
+ ChevronDown,
+ Plug,
+ Unplug,
+ RefreshCw,
+ XCircle,
+ Copy,
+ Trash2,
+} from "lucide-react"
+import { cn } from "@/lib/utils"
+import { toast } from "sonner"
+import type { ConnectionOperation } from "@/types/connection-events"
+import {
+ formatOperationTime,
+ formatAddress,
+ formatChainName,
+ formatPlatformName,
+ formatProvider,
+ formatProofTimestamp,
+ processFeatures,
+} from "@/utils/connection-formatters"
+
+// ============ SECTION CONFIG ============
+
+const SECTION_CONFIG = {
+ connect: {
+ showRequested: true,
+ responseTitle: 'WALLET RESPONSE'
+ },
+ disconnect: {
+ showRequested: false,
+ responseTitle: 'DISCONNECT EVENT'
+ },
+ restore_session: {
+ showRequested: false,
+ responseTitle: 'RESTORED SESSION'
+ }
+} as const
+
+// ============ HELPER COMPONENTS ============
+
+function Section({ title, children }: { title: string; children: React.ReactNode }) {
+ return (
+
+
+ {title}
+
+ {children}
+
+ )
+}
+
+function CopyButton({ text, label }: { text: string; label: string }) {
+ const handleCopy = async (e: React.MouseEvent) => {
+ e.stopPropagation()
+ try {
+ await navigator.clipboard.writeText(text)
+ toast.success(`${label} copied`)
+ } catch {
+ toast.error("Failed to copy")
+ }
+ }
+
+ return (
+
+
+
+ )
+}
+
+// ============ RAW DATA SECTION ============
+
+interface RawDataSectionProps {
+ request?: unknown
+ response?: unknown
+}
+
+function RawDataSection({ request, response }: RawDataSectionProps) {
+ const [tab, setTab] = useState<'request' | 'response' | 'both'>('both')
+
+ const hasRequest = request !== undefined && request !== null
+ const hasResponse = response !== undefined && response !== null
+
+ if (!hasRequest && !hasResponse) return null
+
+ const getContent = () => {
+ if (tab === 'request') return JSON.stringify(request, null, 2)
+ if (tab === 'response') return JSON.stringify(response, null, 2)
+ return JSON.stringify({ request, response }, null, 2)
+ }
+
+ const countLines = (obj: unknown) => JSON.stringify(obj, null, 2).split('\n').length
+
+ const handleCopyAll = async () => {
+ try {
+ await navigator.clipboard.writeText(getContent())
+ toast.success("Copied to clipboard")
+ } catch {
+ toast.error("Failed to copy")
+ }
+ }
+
+ return (
+
+
+ {/* Tab buttons */}
+
+
+ {hasRequest && (
+ setTab('request')}
+ >
+ Request ({countLines(request)})
+
+ )}
+ {hasResponse && (
+ setTab('response')}
+ >
+ Response ({countLines(response)})
+
+ )}
+ {hasRequest && hasResponse && (
+ setTab('both')}
+ >
+ Both
+
+ )}
+
+
+
+ Copy
+
+
+
+
+
+
+ )
+}
+
+// ============ OPERATION ROW ============
+
+interface OperationRowProps {
+ operation: ConnectionOperation
+ onDelete?: () => void
+}
+
+function OperationRow({ operation, onDelete }: OperationRowProps) {
+ const [expanded, setExpanded] = useState(false)
+
+ const isConnect = operation.type === 'connect'
+ const isDisconnect = operation.type === 'disconnect'
+ const isSuccess = operation.response?.success !== false
+ const hasError = operation.response?.error
+ const wallet = operation.response?.wallet
+
+ // Check if TonProof data exists in response (more reliable than checking request)
+ const hasTonProofData = !!wallet?.tonProof
+
+ const config = SECTION_CONFIG[operation.type]
+
+ // Format features using the shared utility
+ const features = wallet?.device.features
+ const formattedFeatures = useMemo(() => {
+ if (!features) return []
+ return processFeatures(features)
+ }, [features])
+
+ // Determine icon and color
+ let Icon = Plug
+ let iconColor = 'text-green-500'
+ let labelColor = 'text-green-600 dark:text-green-400'
+
+ if (isDisconnect) {
+ Icon = Unplug
+ iconColor = 'text-muted-foreground'
+ labelColor = 'text-muted-foreground'
+ } else if (hasError) {
+ Icon = XCircle
+ iconColor = 'text-red-500'
+ labelColor = 'text-red-600 dark:text-red-400'
+ } else if (operation.type === 'restore_session') {
+ Icon = RefreshCw
+ iconColor = 'text-blue-500'
+ labelColor = 'text-blue-600 dark:text-blue-400'
+ }
+
+ return (
+
+ {/* Collapsed Header */}
+
setExpanded(!expanded)}
+ className="w-full flex items-center gap-2 px-4 py-3 sm:p-3 text-left hover:bg-muted/50 transition-colors"
+ >
+ {expanded ? (
+
+ ) : (
+
+ )}
+
+ {/* Time */}
+
+ {formatOperationTime(operation.timestamp)}
+
+
+ {/* Icon */}
+
+
+ {/* Type label */}
+
+ {operation.type.replace('_', ' ')}
+
+
+ {/* Items (for connect) */}
+ {isConnect && operation.request?.items && (
+
+ [{operation.request.items.join(', ')}]
+
+ )}
+
+ {/* Arrow and wallet name */}
+ {isConnect && wallet && (
+ <>
+ →
+
+ {wallet.device.appName}
+
+ >
+ )}
+
+ {/* Disconnect initiator */}
+ {isDisconnect && (
+
+ by {operation.initiator || 'wallet'}
+
+ )}
+
+ {/* Address */}
+ {wallet?.account.address && (
+
+ {formatAddress(wallet.account.address)}
+
+ )}
+
+ {/* Previous address for disconnect */}
+ {isDisconnect && operation.previousAddress && (
+
+ ({formatAddress(operation.previousAddress)})
+
+ )}
+
+ {/* Success/Error indicator */}
+ {isConnect && (
+
+ {isSuccess ? "✓" : "✗"}
+
+ )}
+
+
+ {/* Expanded Content - VERTICAL LAYOUT */}
+ {expanded && (
+
+
+ {/* REQUESTED Section - only for connect */}
+ {config.showRequested && operation.request && (
+
+
+
+ Items:
+ {operation.request.items.join(', ')}
+
+ {operation.request.payload && (
+
+ Challenge:
+
+ {operation.request.payload}
+
+
+
+ )}
+
+
+ )}
+
+ {/* RESPONSE Section with adaptive title */}
+
+ {hasError ? (
+ // Error state
+
+
+
+ Error
+
+
+ Code:
+ {operation.response!.error!.code}
+ Message:
+ {operation.response!.error!.message}
+
+
+ ) : wallet ? (
+ // Success - 3 column grid
+
+ {/* Account Column */}
+
+
Account
+
+
+
Address
+
+
+ {formatAddress(wallet.account.address, 10, 8)}
+
+
+
+
+
+ Network
+
+ {formatChainName(wallet.account.chain)}
+
+
+ {wallet.account.publicKey && (
+
+
Public Key
+
+
+ {formatAddress(wallet.account.publicKey, 10, 8)}
+
+
+
+
+ )}
+
+
+
+ {/* Device Column */}
+
+
Device
+
+
+ Wallet
+ {wallet.device.appName} {wallet.device.appVersion}
+
+
+ Platform
+ {formatPlatformName(wallet.device.platform)}
+
+
+ Provider
+
+ {formatProvider(wallet.provider)}
+
+
+ {formattedFeatures.length > 0 && (
+
+
Features
+
+ {formattedFeatures.map((f, i) => (
+
+ {f}
+
+ ))}
+
+
+ )}
+
+
+
+ {/* TonProof Column - only if TonProof data exists */}
+ {hasTonProofData && (
+
+
TonProof
+ {wallet.tonProof ? (
+
+
+ Domain
+
+ {wallet.tonProof.domain}
+
+
+
+ Timestamp
+
+ {formatProofTimestamp(wallet.tonProof.timestamp)}
+
+
+
+
Signature
+
+
+ {formatAddress(wallet.tonProof.signature, 10, 8)}
+
+
+
+
+
+ ) : (
+
+ Requested but not provided
+
+ )}
+
+ )}
+
+ ) : isDisconnect ? (
+ // Disconnect info
+
+
+ Initiated by
+
+ {operation.initiator || 'wallet'}
+
+ {operation.previousWalletName && (
+ <>
+ Wallet was
+ {operation.previousWalletName}
+ >
+ )}
+ {operation.previousAddress && (
+ <>
+ Address was
+
+ {formatAddress(operation.previousAddress, 8, 6)}
+
+ >
+ )}
+
+
+ ) : (
+ No response data
+ )}
+
+
+ {/* RAW DATA Section */}
+
+
+ {/* Delete button */}
+ {onDelete && (
+
+
+
+ Remove
+
+
+ )}
+
+ )}
+
+ )
+}
+
+// ============ MAIN COMPONENT ============
+
+interface ConnectionEventsCardProps {
+ operations: ConnectionOperation[]
+ onClear?: () => void
+ onDelete?: (id: string) => void
+}
+
+export function ConnectionEventsCard({
+ operations,
+ onClear,
+ onDelete,
+}: ConnectionEventsCardProps) {
+ const [isOpen, setIsOpen] = useState(false)
+
+ if (operations.length === 0) return null
+
+ return (
+
+ {/* Header */}
+
+
+
+ Connection Events
+ ({operations.length})
+
+
+ {onClear && (
+
+
+ Clear
+
+ )}
+
+
+
+
+ {operations.map((op) => (
+ onDelete(op.id) : undefined}
+ />
+ ))}
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/FieldInfoModal.tsx b/apps/tonconnect-demo/src/components/shared/FieldInfoModal.tsx
new file mode 100644
index 000000000..9864a738e
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/FieldInfoModal.tsx
@@ -0,0 +1,48 @@
+import ReactMarkdown from "react-markdown"
+import remarkGfm from "remark-gfm"
+import {
+ Dialog,
+ DialogContent,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
+import type { FieldInfo } from "@/data/field-info"
+
+interface FieldInfoModalProps {
+ open: boolean
+ onOpenChange: (open: boolean) => void
+ info: FieldInfo
+}
+
+export function FieldInfoModal({ open, onOpenChange, info }: FieldInfoModalProps) {
+ return (
+
+
+
+ {info.name}
+ {info.summary}
+
+
+
+ {info.content}
+
+
+ {info.links && info.links.length > 0 && (
+
+ )}
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/FieldLabel.tsx b/apps/tonconnect-demo/src/components/shared/FieldLabel.tsx
new file mode 100644
index 000000000..b0ef822d3
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/FieldLabel.tsx
@@ -0,0 +1,35 @@
+import { useState, type ReactNode } from "react"
+import { Label } from "@/components/ui/label"
+import { FieldInfoModal } from "./FieldInfoModal"
+import { getFieldInfo } from "@/data/field-info"
+import { Info } from "lucide-react"
+
+interface FieldLabelProps {
+ htmlFor?: string
+ fieldId: string
+ children: ReactNode
+ className?: string
+}
+
+export function FieldLabel({ htmlFor, fieldId, children, className }: FieldLabelProps) {
+ const [open, setOpen] = useState(false)
+ const info = getFieldInfo(fieldId)
+
+ return (
+ <>
+
+ {children}
+ {info && (
+ setOpen(true)}
+ className="text-muted-foreground hover:text-foreground transition-colors"
+ >
+
+
+ )}
+
+ {info && }
+ >
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/FormContainer.tsx b/apps/tonconnect-demo/src/components/shared/FormContainer.tsx
new file mode 100644
index 000000000..90136a766
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/FormContainer.tsx
@@ -0,0 +1,384 @@
+import { useState, useEffect, useMemo } from "react"
+import type { ReactNode } from "react"
+import CodeMirror from "@uiw/react-codemirror"
+import { json } from "@codemirror/lang-json"
+import { Card, CardContent, CardHeader } from "@/components/ui/card"
+import { Button } from "@/components/ui/button"
+import { Alert, AlertDescription } from "@/components/ui/alert"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+import { JsonViewer } from "./JsonViewer"
+import { AlertCircle, AlertTriangle, Copy, ChevronDown, RotateCcw, Loader2 } from "lucide-react"
+import { toast } from "sonner"
+import { useSettingsContext } from "@/context/SettingsContext"
+import { createTonConnectTheme } from "@/lib/codemirror-theme"
+import type { ValidationResult } from "@/utils/validator"
+
+export interface PresetOption {
+ id: string
+ name: string
+ description: string
+}
+
+type EditorMode = "form" | "raw"
+
+interface FormContainerProps {
+ // Metadata
+ title: string
+ submitButtonText?: string
+ codeEditorHeight?: string
+
+ // Content
+ formContent: ReactNode
+ requestJson: string
+
+ // Callbacks
+ onJsonChange?: (json: string) => void
+ onSend: () => void
+ onSendRaw?: (json: string) => void
+
+ // Validation
+ validateJson?: (json: string) => ValidationResult
+
+ // State
+ isConnected: boolean
+ isLoading?: boolean
+
+ // Presets
+ presets?: PresetOption[]
+ onPresetSelect?: (presetId: string) => void
+}
+
+function isValidJson(str: string): boolean {
+ try {
+ JSON.parse(str)
+ return true
+ } catch {
+ return false
+ }
+}
+
+export function FormContainer({
+ title,
+ submitButtonText = "Send Transaction",
+ codeEditorHeight = "400px",
+ formContent,
+ requestJson,
+ onJsonChange,
+ onSend,
+ onSendRaw,
+ validateJson,
+ isConnected,
+ isLoading = false,
+ presets,
+ onPresetSelect,
+}: FormContainerProps) {
+ const [mode, setMode] = useState("form")
+ const [editedJson, setEditedJson] = useState(requestJson)
+ const [validationResult, setValidationResult] = useState(null)
+
+ const { theme } = useSettingsContext()
+
+ // Determine if dark mode based on theme setting
+ const isDark = useMemo(() => {
+ if (theme === "system") {
+ return typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches
+ }
+ return theme === "dark"
+ }, [theme])
+
+ // Create reactive CodeMirror theme
+ const codemirrorTheme = useMemo(() => createTonConnectTheme(isDark), [isDark])
+
+ // Sync JSON when in form mode or when requestJson changes
+ useEffect(() => {
+ if (mode === "form") {
+ setEditedJson(requestJson)
+ setValidationResult(null) // Clear validation when switching to form
+ }
+ }, [requestJson, mode])
+
+ // Handle mode switch
+ const handleModeChange = (newMode: EditorMode) => {
+ if (newMode === mode) return
+
+ if (mode === "raw" && newMode === "form") {
+ // Code → Form: check validity first
+ if (!isValidJson(editedJson)) {
+ // Syntax error - confirm discard
+ if (!confirm("Invalid JSON syntax. Discard changes and switch to Form?")) {
+ return
+ }
+ setEditedJson(requestJson)
+ setValidationResult(null)
+ setMode("form")
+ return
+ }
+
+ // Check schema validation
+ if (validateJson) {
+ const result = validateJson(editedJson)
+ if (!result.valid) {
+ // Schema warnings - confirm discard
+ if (!confirm("JSON has validation errors. Some data may be lost. Switch to Form anyway?")) {
+ return
+ }
+ }
+ }
+
+ // Apply changes
+ onJsonChange?.(editedJson)
+ setValidationResult(null)
+ }
+
+ if (mode === "form" && newMode === "raw") {
+ // Form → Code: sync JSON
+ setEditedJson(requestJson)
+ setValidationResult(null)
+ }
+
+ setMode(newMode)
+ }
+
+ // Reset editor to form state
+ const handleReset = () => {
+ setEditedJson(requestJson)
+ setValidationResult(null)
+ toast.success("Reset to form state")
+ }
+
+ // Actually send the transaction (internal)
+ const doSend = () => {
+ if (onSendRaw) {
+ onSendRaw(editedJson)
+ } else {
+ onJsonChange?.(editedJson)
+ onSend()
+ }
+ }
+
+ // Handle send - validates first in Code mode
+ const handleSend = () => {
+ if (mode === "form") {
+ onSend()
+ } else {
+ // Code mode - validate before sending
+ if (!isValidJson(editedJson)) {
+ setValidationResult({ valid: false, errors: [{ path: "root", message: "Invalid JSON syntax" }] })
+ return
+ }
+
+ // Run schema validation
+ if (validateJson) {
+ const result = validateJson(editedJson)
+ if (!result.valid) {
+ // Show warnings and DON'T send - user must click "Send Anyway"
+ setValidationResult(result)
+ return
+ }
+ }
+
+ // All validation passed - send
+ doSend()
+ }
+ }
+
+ // Send anyway - bypasses schema validation (but still checks syntax)
+ const handleSendAnyway = () => {
+ if (!isValidJson(editedJson)) {
+ return // Syntax errors still block
+ }
+ setValidationResult(null)
+ doSend()
+ }
+
+ // Determine validation state (only shown after Send click)
+ const hasSyntaxError = validationResult?.errors.some(e => e.message === "Invalid JSON syntax")
+ const hasSchemaWarnings = validationResult && !validationResult.valid && !hasSyntaxError
+
+ // Send button disabled state - disabled if not connected or loading
+ const sendDisabled = !isConnected || isLoading
+
+ return (
+
+
+ {/* Header: Title + Toggle + Send */}
+
+ {title}
+
+
+ {/* Presets Dropdown */}
+ {presets && presets.length > 0 && (
+
+
+
+ Presets
+
+
+
+
+ {presets.map((preset) => (
+ onPresetSelect?.(preset.id)}
+ className="flex flex-col items-start gap-0.5 cursor-pointer"
+ >
+ {preset.name}
+ {preset.description}
+
+ ))}
+
+
+ )}
+
+ {/* Segmented Toggle */}
+
+ handleModeChange("form")}
+ >
+ Form
+
+ handleModeChange("raw")}
+ >
+ Raw
+
+
+
+ {/* Send Button */}
+
+ {isLoading && }
+ {submitButtonText}
+ Send
+
+
+
+
+
+ {mode === "form" ? (
+ // Form mode: 2 columns in one card
+
+ {/* LEFT: Form */}
+
+
Configure
+ {formContent}
+
+
+ {/* RIGHT: Preview (with left border on lg) */}
+
+
+
Request Preview
+ {
+ navigator.clipboard.writeText(requestJson)
+ toast.success("Copied to clipboard")
+ }}
+ >
+
+ Copy
+
+
+
+
+
+ ) : (
+ // Code mode: Full width editor with toolbar
+
+ {/* Toolbar */}
+
+
+
+ Reset
+
+ {
+ navigator.clipboard.writeText(editedJson)
+ toast.success("Copied to clipboard")
+ }}
+ >
+
+ Copy
+
+
+
+
{
+ setEditedJson(value)
+ // Clear validation when user edits
+ if (validationResult) {
+ setValidationResult(null)
+ }
+ }}
+ extensions={[json(), ...codemirrorTheme]}
+ theme="none"
+ height={codeEditorHeight}
+ className="rounded-md border overflow-hidden"
+ />
+
+ {/* Syntax Error (shown after Send attempt) */}
+ {hasSyntaxError && (
+
+
+ Invalid JSON syntax. Please fix before sending.
+
+ )}
+
+ {/* Schema Warnings (shown after Send attempt, blocks until "Send Anyway") */}
+ {hasSchemaWarnings && (
+
+
+
+
+ {validationResult!.errors.map(e => `${e.path}: ${e.message}`).join("; ")}
+
+
+ Send Anyway
+
+
+
+ )}
+
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/HistoryList.tsx b/apps/tonconnect-demo/src/components/shared/HistoryList.tsx
new file mode 100644
index 000000000..3a93c38fb
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/HistoryList.tsx
@@ -0,0 +1,426 @@
+import { useState, useMemo, useCallback } from "react"
+import { fromNano } from "@ton/core"
+import { Button } from "@/components/ui/button"
+import { Label } from "@/components/ui/label"
+import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from "@/components/ui/collapsible"
+import { JsonViewer } from "./JsonViewer"
+import { useHistory, type HistoryEntry } from "@/hooks/useHistory"
+import {
+ ChevronDown,
+ ChevronRight,
+ CheckCircle,
+ XCircle,
+ Clock,
+ RotateCcw,
+ Copy,
+ Trash2,
+ History,
+ ExternalLink,
+ Search,
+ Loader2,
+} from "lucide-react"
+import { toast } from "sonner"
+import { getExplorerUrl } from "@/utils/explorer-utils"
+import { getNormalizedExtMessageHash } from "@/utils/transaction-utils"
+
+interface HistoryListProps {
+ currentWallet: string | null
+ onLoadToForm: (requestRaw: string) => void
+}
+
+function formatTime(timestamp: number): string {
+ const now = Date.now()
+ const diff = now - timestamp
+
+ // Less than 1 minute ago
+ if (diff < 60000) {
+ return "just now"
+ }
+
+ // Less than 1 hour ago
+ if (diff < 3600000) {
+ const mins = Math.floor(diff / 60000)
+ return `${mins}m ago`
+ }
+
+ // Today - show time
+ const date = new Date(timestamp)
+ const today = new Date()
+ if (date.toDateString() === today.toDateString()) {
+ return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
+ }
+
+ // Yesterday
+ const yesterday = new Date(today)
+ yesterday.setDate(yesterday.getDate() - 1)
+ if (date.toDateString() === yesterday.toDateString()) {
+ return "yesterday"
+ }
+
+ // Older - show date
+ return date.toLocaleDateString([], { month: "short", day: "numeric" })
+}
+
+function formatAmount(request: Record): string {
+ try {
+ const messages = request.messages as Array<{ amount?: string }> | undefined
+ if (messages && messages.length > 0) {
+ const totalNano = messages.reduce((sum, msg) => {
+ return sum + BigInt(msg.amount || "0")
+ }, BigInt(0))
+ const ton = fromNano(totalNano)
+ const num = parseFloat(ton)
+ if (num >= 1) {
+ return `${num.toFixed(2)} TON`
+ }
+ if (num >= 0.01) {
+ return `${num.toFixed(3)} TON`
+ }
+ return `${ton} TON`
+ }
+ } catch {
+ // Ignore
+ }
+ return ""
+}
+
+function getMessageCount(request: Record): number {
+ const messages = request.messages as Array | undefined
+ return messages?.length || 0
+}
+
+function StatusIcon({ status }: { status: HistoryEntry["status"] }) {
+ switch (status) {
+ case "confirmed":
+ return
+ case "success":
+ return
+ case "error":
+ return
+ case "expired":
+ return
+ default:
+ return
+ }
+}
+
+function statusLabel(status: HistoryEntry["status"]): string {
+ switch (status) {
+ case "confirmed":
+ return "Confirmed"
+ case "success":
+ return "Sent"
+ case "error":
+ return "Error"
+ case "expired":
+ return "Expired"
+ default:
+ return status
+ }
+}
+
+interface HistoryEntryRowProps {
+ entry: HistoryEntry
+ expanded: boolean
+ onToggle: () => void
+ onLoadToForm: () => void
+ onDelete: () => void
+}
+
+interface TransactionDetails {
+ lt: string
+ hash: string
+ fee: string
+ timestamp: number
+}
+
+function HistoryEntryRow({
+ entry,
+ expanded,
+ onToggle,
+ onLoadToForm,
+ onDelete,
+}: HistoryEntryRowProps) {
+ const amount = formatAmount(entry.request)
+ const msgCount = getMessageCount(entry.request)
+
+ // Compute hash from BOC (only if boc exists)
+ const hash = useMemo(() => {
+ if (!entry.boc) return null
+ try {
+ return getNormalizedExtMessageHash(entry.boc)
+ } catch {
+ return null
+ }
+ }, [entry.boc])
+
+ // Blockchain check state
+ const [checkLoading, setCheckLoading] = useState(false)
+ const [txDetails, setTxDetails] = useState(null)
+ const [checkError, setCheckError] = useState(null)
+
+ const checkBlockchain = useCallback(async () => {
+ if (!hash) return
+
+ setCheckLoading(true)
+ setCheckError(null)
+
+ const endpoint = entry.network === "testnet"
+ ? "https://testnet.toncenter.com/api/v3"
+ : "https://toncenter.com/api/v3"
+
+ try {
+ const response = await fetch(
+ `${endpoint}/transactionsByMessage?msg_hash=${hash}&direction=in`
+ )
+ const data = await response.json()
+
+ if (data.transactions?.length > 0) {
+ const tx = data.transactions[0]
+ setTxDetails({
+ lt: tx.lt,
+ hash: tx.hash,
+ fee: tx.total_fees,
+ timestamp: tx.now,
+ })
+ } else {
+ setCheckError("Transaction not found in blockchain")
+ }
+ } catch (err) {
+ setCheckError(err instanceof Error ? err.message : "Network error")
+ } finally {
+ setCheckLoading(false)
+ }
+ }, [hash, entry.network])
+
+ return (
+
+ {/* Collapsed row - clickable header */}
+
+ {expanded ? (
+
+ ) : (
+
+ )}
+
+
+ {formatTime(entry.timestamp)}
+
+
+
+ {amount}
+
+
+
+
+ {statusLabel(entry.status)}
+
+
+ {msgCount > 1 && (
+
+ {msgCount} msgs
+
+ )}
+
+ {hash && (
+
+ {hash.slice(0, 8)}...
+
+ )}
+
+
+ {/* Expanded content */}
+ {expanded && (
+
+ {/* 2-column layout for Request / Response+Hash */}
+
+ {/* Left column: Request */}
+
+
+
+
+ {/* Right column: Response + Hash + Blockchain */}
+
+
+
+ {/* Hash with explorer link */}
+ {hash && (
+
+
+
Hash (TEP-467)
+
+
{
+ navigator.clipboard.writeText(hash)
+ toast.success("Hash copied")
+ }}
+ >
+
+
+
+
+
+
+
+
+
+
+ {hash}
+
+
+ {/* Check blockchain button */}
+ {!txDetails && (
+
+ {checkLoading ? (
+
+ ) : (
+
+ )}
+ {checkLoading ? "Checking..." : "Check in blockchain"}
+
+ )}
+
+ {/* Error */}
+ {checkError && (
+
{checkError}
+ )}
+
+ {/* Transaction details */}
+ {txDetails && (
+
+
+ Transaction Confirmed
+
+ LT: {txDetails.lt} • Fee: {txDetails.fee} nanotons • {new Date(txDetails.timestamp * 1000).toLocaleString()}
+
+
+ )}
+
+ )}
+
+
+
+ {/* Actions */}
+
+
+
+ Load to Form
+
+
+
+ Delete
+
+
+
+ )}
+
+ )
+}
+
+export function HistoryList({ currentWallet, onLoadToForm }: HistoryListProps) {
+ const history = useHistory()
+ const [expanded, setExpanded] = useState>({})
+ const [sectionOpen, setSectionOpen] = useState(false)
+
+ const entries = useMemo(() => {
+ return currentWallet ? history.getByWallet(currentWallet) : []
+ }, [currentWallet, history])
+
+ if (!currentWallet || entries.length === 0) {
+ return null
+ }
+
+ const toggleEntry = (id: string) => {
+ setExpanded(prev => ({ ...prev, [id]: !prev[id] }))
+ }
+
+ const handleClear = () => {
+ if (currentWallet) {
+ history.clearWallet(currentWallet)
+ }
+ }
+
+ return (
+
+ {/* Section header */}
+
+
+ {sectionOpen ? (
+
+ ) : (
+
+ )}
+
+ HISTORY ({entries.length})
+
+
+
+
+ Clear
+
+
+
+
+
+ {entries.map(entry => (
+ toggleEntry(entry.id)}
+ onLoadToForm={() => onLoadToForm(entry.requestRaw)}
+ onDelete={() => history.deleteEntry(entry.id)}
+ />
+ ))}
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/HowItWorksCard.tsx b/apps/tonconnect-demo/src/components/shared/HowItWorksCard.tsx
new file mode 100644
index 000000000..594100713
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/HowItWorksCard.tsx
@@ -0,0 +1,174 @@
+import { useMemo } from "react"
+import ReactMarkdown from "react-markdown"
+import remarkGfm from "remark-gfm"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+import { ExternalLink, Check } from "lucide-react"
+import { getSectionInfo } from "@/data/field-info"
+import { useDevToolsContext } from "@/context/DevToolsContext"
+
+// Feature lists for each section
+const SECTION_FEATURES: Record = {
+ connect: [
+ "Simple or authenticated connection",
+ "TonProof cryptographic verification",
+ "Domain-bound ownership proof",
+ "Replay attack protection",
+ ],
+ transaction: [
+ "Multiple messages per transaction",
+ "Custom payloads for smart contracts",
+ "Contract deployment support",
+ "Batch operations",
+ ],
+ signData: [
+ "Text, binary, cell formats",
+ "Domain-bound signatures",
+ "Timestamp protection",
+ "Off-chain verification",
+ ],
+}
+
+interface HowItWorksCardProps {
+ sectionId: string
+}
+
+export function HowItWorksCard({ sectionId }: HowItWorksCardProps) {
+ const { docsHidden } = useDevToolsContext()
+ const info = getSectionInfo(sectionId)
+ const features = SECTION_FEATURES[sectionId] || []
+
+ // Extract h2 headings from markdown for navigation
+ const content = info?.content
+ const headings = useMemo(() => {
+ if (!content) return []
+ const matches = content.match(/^## (.+)$/gm)
+ return matches?.map(h => h.replace("## ", "")) || []
+ }, [content])
+
+ // Hide if docs are hidden or no info available
+ if (docsHidden || !info) return null
+
+ const scrollToHeading = (heading: string) => {
+ // Find the heading element and scroll to it
+ const slug = heading.toLowerCase().replace(/\s+/g, "-").replace(/[^\w-]/g, "")
+ const element = document.getElementById(slug)
+ element?.scrollIntoView({ behavior: "smooth", block: "start" })
+ }
+
+ return (
+
+
+ {info.name}
+
+
+
+
+ {/* LEFT: Summary - hidden on mobile */}
+
+ {/* Summary */}
+
{info.summary}
+
+ {/* Features checklist */}
+ {features.length > 0 && (
+
+
Key Features
+
+ {features.map((feature, i) => (
+
+
+ {feature}
+
+ ))}
+
+
+ )}
+
+ {/* Navigation */}
+ {headings.length > 0 && (
+
+ Jump to
+
+ {headings.map((heading, i) => (
+
+ scrollToHeading(heading)}
+ className="text-sm text-muted-foreground hover:text-foreground transition-colors text-left"
+ >
+ → {heading}
+
+
+ ))}
+
+
+ )}
+
+ {/* Links */}
+ {info.links && info.links.length > 0 && (
+
+ )}
+
+
+ {/* RIGHT: Full markdown content */}
+
+ {
+ const text = String(children)
+ const id = text.toLowerCase().replace(/\s+/g, "-").replace(/[^\w-]/g, "")
+ return {children}
+ }
+ }}
+ >
+ {info.content}
+
+
+
+
+
+ {/* Links on mobile - shown only on mobile */}
+ {info.links && info.links.length > 0 && (
+
+ )}
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/JsonViewer.tsx b/apps/tonconnect-demo/src/components/shared/JsonViewer.tsx
new file mode 100644
index 000000000..02a2700d0
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/JsonViewer.tsx
@@ -0,0 +1,214 @@
+import { useMemo, useState } from "react"
+import CodeMirror from "@uiw/react-codemirror"
+import { json } from "@codemirror/lang-json"
+import { javascript } from "@codemirror/lang-javascript"
+import { EditorView } from "@codemirror/view"
+import { Button } from "@/components/ui/button"
+import { Label } from "@/components/ui/label"
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from "@/components/ui/collapsible"
+import { Copy, ChevronRight, ChevronDown } from "lucide-react"
+import { useSettingsContext } from "@/context/SettingsContext"
+import { copyToClipboard } from "@/utils/clipboard"
+import { createTonConnectTheme } from "@/lib/codemirror-theme"
+
+interface JsonViewerProps {
+ title: string
+ json: string
+ /** Default expanded state */
+ defaultExpanded?: boolean
+ /** Max height for long JSON (default 200px) */
+ maxHeight?: number
+ /** Show inline for short JSON (default 80 chars) */
+ inlineThreshold?: number
+ /** Allow collapsing (default true) */
+ collapsible?: boolean
+ /** Language for syntax highlighting (default json) */
+ language?: "json" | "typescript"
+}
+
+export function JsonViewer({
+ title,
+ json: jsonString,
+ defaultExpanded = true,
+ maxHeight = 200,
+ inlineThreshold = 80,
+ collapsible = true,
+ language = "json",
+}: JsonViewerProps) {
+ const [expanded, setExpanded] = useState(defaultExpanded)
+ const { theme } = useSettingsContext()
+
+ const isDark = useMemo(() => {
+ if (theme === "system") {
+ return typeof window !== "undefined" &&
+ window.matchMedia("(prefers-color-scheme: dark)").matches
+ }
+ return theme === "dark"
+ }, [theme])
+
+ const codemirrorTheme = useMemo(() => createTonConnectTheme(isDark), [isDark])
+
+ // Language extension for syntax highlighting
+ const langExtension = useMemo(() => {
+ return language === "typescript"
+ ? javascript({ jsx: true, typescript: true })
+ : json()
+ }, [language])
+
+ // Parse and format content
+ const { formatted, lineCount, isShort } = useMemo(() => {
+ // For TypeScript/JS, don't try to parse as JSON
+ if (language === "typescript") {
+ const lines = jsonString.split("\n")
+ return {
+ formatted: jsonString,
+ lineCount: lines.length,
+ isShort: false, // Never show inline for code
+ }
+ }
+
+ // For JSON, try to parse and pretty-print
+ try {
+ const parsed = JSON.parse(jsonString)
+ const formatted = JSON.stringify(parsed, null, 2)
+ const lines = formatted.split("\n")
+ return {
+ formatted,
+ lineCount: lines.length,
+ isShort: formatted.length <= inlineThreshold && lines.length <= 2,
+ }
+ } catch {
+ return { formatted: jsonString, lineCount: 1, isShort: jsonString.length <= inlineThreshold }
+ }
+ }, [jsonString, inlineThreshold, language])
+
+ const handleCopy = async (e: React.MouseEvent) => {
+ e.stopPropagation() // Don't toggle collapsible
+ await copyToClipboard(formatted)
+ }
+
+ // Calculate height: line-height ~18px + padding
+ const calculatedHeight = useMemo(() => {
+ const lineHeight = 18
+ const padding = 16
+ const naturalHeight = lineCount * lineHeight + padding
+ return Math.min(naturalHeight, maxHeight)
+ }, [lineCount, maxHeight])
+
+ // Short JSON - show inline without collapsible
+ if (isShort) {
+ return (
+
+
+ {title}
+
+
+ Copy
+
+
+
+ {formatted}
+
+
+ )
+ }
+
+ // Non-collapsible mode - just show CodeMirror with optional header
+ if (!collapsible) {
+ return (
+
+ {title && (
+
+ {title}
+
+
+ Copy
+
+
+ )}
+
+
+ )
+ }
+
+ // Long content - collapsible with CodeMirror
+ return (
+
+
+
+ {expanded ? (
+
+ ) : (
+
+ )}
+ {title}
+ {!expanded && (
+
+ ({lineCount} lines)
+
+ )}
+
+
+
+ Copy
+
+
+
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/ResultCard.tsx b/apps/tonconnect-demo/src/components/shared/ResultCard.tsx
new file mode 100644
index 000000000..01b37f722
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/ResultCard.tsx
@@ -0,0 +1,125 @@
+import { useTonWallet, CHAIN } from "@tonconnect/ui-react"
+import { BaseResultCard } from "./BaseResultCard"
+import { StatusBar, type StatusVariant } from "./StatusBar"
+import { TransactionDetails } from "./TransactionDetails"
+import { useTransactionTracker, type TransactionStatus } from "@/hooks/useTransactionTracker"
+import { CheckCircle, XCircle, Loader2 } from "lucide-react"
+import type { OperationResult } from "@/hooks/useTransaction"
+
+interface ResultCardProps {
+ result: OperationResult
+ onDismiss?: () => void
+ onLoadToForm?: () => void
+}
+
+/** Maps transaction status to StatusBar variant */
+function getVariant(status: TransactionStatus, isError: boolean): StatusVariant {
+ if (isError) return "error"
+ switch (status) {
+ case "confirmed":
+ return "success"
+ case "expired":
+ return "error"
+ default:
+ return "pending"
+ }
+}
+
+/** Gets icon for status */
+function getIcon(status: TransactionStatus, isError: boolean) {
+ if (isError) return
+ switch (status) {
+ case "confirmed":
+ return
+ case "expired":
+ return
+ default:
+ return
+ }
+}
+
+/** Gets title for status */
+function getTitle(status: TransactionStatus, isError: boolean, hasBoc: boolean): string {
+ if (isError) return "Error"
+ switch (status) {
+ case "confirmed":
+ return "Confirmed"
+ case "expired":
+ return "Expired"
+ case "pending":
+ case "idle":
+ return hasBoc ? "Pending" : "Sent"
+ }
+}
+
+/** Gets subtitle for confirmed transactions */
+function getConfirmedSubtitle(transaction: { lt: string; fee: string; timestamp: number }): string {
+ const time = new Date(transaction.timestamp * 1000).toLocaleTimeString()
+ const feeInTon = (parseInt(transaction.fee) / 1e9).toFixed(6)
+ return `LT: ${transaction.lt} • Fee: ${feeInTon} TON • ${time}`
+}
+
+export function ResultCard({ result, onDismiss, onLoadToForm }: ResultCardProps) {
+ const wallet = useTonWallet()
+ const network = wallet?.account.chain === CHAIN.TESTNET ? "testnet" : "mainnet"
+
+ // Transaction tracking (if we have boc)
+ const tracking = useTransactionTracker({
+ boc: result.boc || null,
+ validUntil: result.validUntil || 0,
+ network,
+ })
+
+ const isError = result.status === "error"
+ const hasBoc = !!result.boc
+ const effectiveStatus = isError ? "idle" : tracking.status
+
+ // Build subtitle
+ let subtitle: string | undefined
+ if (isError) {
+ // Try to extract error message from response
+ try {
+ const parsed = JSON.parse(result.response)
+ subtitle = parsed.message || parsed.error || undefined
+ } catch {
+ subtitle = undefined
+ }
+ } else if (effectiveStatus === "confirmed" && tracking.transaction) {
+ subtitle = getConfirmedSubtitle(tracking.transaction)
+ } else if (effectiveStatus === "expired") {
+ subtitle = "Transaction not found before validUntil"
+ } else if (effectiveStatus === "pending" && tracking.error) {
+ subtitle = `${tracking.error}, retrying...`
+ } else if (effectiveStatus === "pending") {
+ subtitle = "Waiting for confirmation..."
+ }
+
+ const statusBar = (
+
+ )
+
+ const responseFooter = hasBoc ? (
+
+ ) : undefined
+
+ return (
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/RpcLogCard.tsx b/apps/tonconnect-demo/src/components/shared/RpcLogCard.tsx
new file mode 100644
index 000000000..5e9d4a8f7
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/RpcLogCard.tsx
@@ -0,0 +1,161 @@
+import { useState, useMemo } from "react"
+import { Card } from "@/components/ui/card"
+import { Badge } from "@/components/ui/badge"
+import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
+import { ChevronDown, Clock, CheckCircle2, XCircle } from "lucide-react"
+import { cn } from "@/lib/utils"
+import { JsonViewer } from "./JsonViewer"
+import type { RpcLogEntry, RpcLogStatus } from "@/hooks/useSdkLogs"
+
+interface RpcLogCardProps {
+ entry: RpcLogEntry
+ defaultOpen?: boolean
+}
+
+const statusConfig: Record = {
+ pending: { icon: Clock, color: "text-yellow-500", label: "Pending" },
+ success: { icon: CheckCircle2, color: "text-green-500", label: "Success" },
+ error: { icon: XCircle, color: "text-red-500", label: "Error" },
+}
+
+function formatTime(timestamp: number): string {
+ return new Date(timestamp).toLocaleTimeString("en-US", {
+ hour12: false,
+ hour: "2-digit",
+ minute: "2-digit",
+ second: "2-digit",
+ })
+}
+
+function formatDuration(start: number, end?: number): string {
+ if (!end) {
+ const elapsed = Math.floor((Date.now() - start) / 1000)
+ return `${elapsed}s`
+ }
+ const ms = end - start
+ if (ms < 1000) return `${ms}ms`
+ return `${(ms / 1000).toFixed(1)}s`
+}
+
+/** Parse params array - each element may be a JSON string */
+function parseParams(params: unknown): unknown[] {
+ if (!Array.isArray(params)) return []
+
+ return params.map(param => {
+ if (typeof param === 'string') {
+ try {
+ return JSON.parse(param)
+ } catch {
+ return param
+ }
+ }
+ return param
+ })
+}
+
+export function RpcLogCard({ entry, defaultOpen = false }: RpcLogCardProps) {
+ const [isOpen, setIsOpen] = useState(defaultOpen)
+ const { icon: StatusIcon, color, label } = statusConfig[entry.status]
+
+ // Parse params from request
+ const parsedParams = useMemo(() => {
+ const req = entry.request as Record
+ return parseParams(req.params)
+ }, [entry.request])
+
+ return (
+
+
+
+
+ {/* Status Icon */}
+
+
+ {/* Method */}
+
+ {entry.method}
+
+
+ {/* ID */}
+
+ #{entry.id}
+
+
+ {/* Provider Badge */}
+
+ {entry.provider}
+
+
+ {/* Spacer */}
+
+
+ {/* Status / Timing */}
+
+ {entry.status === "pending" ? (
+ {label}
+ ) : (
+ {formatDuration(entry.requestTimestamp, entry.responseTimestamp)}
+ )}
+ {formatTime(entry.requestTimestamp)}
+
+
+ {/* Expand Icon */}
+
+
+
+
+
+
+
+ {/* Left column: Request + Parsed Params */}
+
+
+ {/* Parsed Params */}
+ {parsedParams.length > 0 && (
+
+ {parsedParams.map((param, i) => (
+
+ ))}
+
+ )}
+
+
+ {/* Right column: Response */}
+ {entry.response ? (
+
+ ) : (
+
+
Response
+
+ Waiting...
+
+
+ )}
+
+
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/RpcLogViewer.tsx b/apps/tonconnect-demo/src/components/shared/RpcLogViewer.tsx
new file mode 100644
index 000000000..0e42af862
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/RpcLogViewer.tsx
@@ -0,0 +1,68 @@
+import { useMemo } from "react"
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Button } from "@/components/ui/button"
+import { Radio, Trash2 } from "lucide-react"
+import { RpcLogCard } from "./RpcLogCard"
+import type { RpcLogEntry } from "@/hooks/useSdkLogs"
+
+interface RpcLogViewerProps {
+ logs: RpcLogEntry[]
+ onClear: () => void
+}
+
+export function RpcLogViewer({ logs, onClear }: RpcLogViewerProps) {
+ const pendingCount = useMemo(
+ () => logs.filter(l => l.status === "pending").length,
+ [logs]
+ )
+ const hasLogs = logs.length > 0
+
+ return (
+
+
+
+
+
+ RPC Logs
+ {pendingCount > 0 && (
+
+ {pendingCount}
+
+ )}
+
+ {hasLogs && (
+
+
+ Clear
+
+ )}
+
+
+ Raw JSON-RPC requests and responses from SDK
+
+
+
+ {hasLogs ? (
+
+ {logs.map((entry, index) => (
+
+ ))}
+
+ ) : (
+
+
+
No RPC logs yet
+
+ Send a transaction or sign data to see logs here
+
+
+ )}
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/SignDataResultCard.tsx b/apps/tonconnect-demo/src/components/shared/SignDataResultCard.tsx
new file mode 100644
index 000000000..dc81f3759
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/SignDataResultCard.tsx
@@ -0,0 +1,113 @@
+import { BaseResultCard } from "./BaseResultCard"
+import { StatusBar } from "./StatusBar"
+import { VerificationResult } from "./VerificationResult"
+import { Button } from "@/components/ui/button"
+import { CheckCircle, XCircle, Loader2, ShieldCheck, Server } from "lucide-react"
+import type { SignDataOperationResult } from "@/hooks/useSignData"
+import type { VerificationResult as VerificationResultType } from "@/utils/sign-data-verification"
+
+interface SignDataResultCardProps {
+ result: SignDataOperationResult
+ onDismiss?: () => void
+ onLoadToForm?: () => void
+ // Verification
+ canVerify: boolean
+ onVerifyClient: () => void
+ onVerifyServer: () => void
+ isVerifyingClient: boolean
+ isVerifyingServer: boolean
+ clientResult: VerificationResultType | null
+ serverResult: VerificationResultType | null
+}
+
+export function SignDataResultCard({
+ result,
+ onDismiss,
+ onLoadToForm,
+ canVerify,
+ onVerifyClient,
+ onVerifyServer,
+ isVerifyingClient,
+ isVerifyingServer,
+ clientResult,
+ serverResult,
+}: SignDataResultCardProps) {
+ const isSuccess = result.status === "success"
+ const isError = result.status === "error"
+
+ // Build subtitle for error
+ let subtitle: string | undefined
+ if (isError) {
+ try {
+ const parsed = JSON.parse(result.response)
+ subtitle = parsed.message || parsed.error || undefined
+ } catch {
+ subtitle = undefined
+ }
+ }
+
+ // Verification buttons (only for success)
+ const verificationActions = isSuccess ? (
+
+
+ {isVerifyingClient ? (
+
+ ) : (
+
+ )}
+ Client
+
+
+ {isVerifyingServer ? (
+
+ ) : (
+
+ )}
+ Server
+
+
+ ) : undefined
+
+ // Verification results (inline under StatusBar)
+ const hasVerificationResults = clientResult || serverResult
+ const verificationContent = hasVerificationResults ? (
+
+ {clientResult && }
+ {serverResult && }
+
+ ) : undefined
+
+ const statusBar = (
+ : }
+ title={isSuccess ? "Signed" : "Error"}
+ subtitle={subtitle}
+ actions={verificationActions}
+ >
+ {verificationContent}
+
+ )
+
+ return (
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/StatusBar.tsx b/apps/tonconnect-demo/src/components/shared/StatusBar.tsx
new file mode 100644
index 000000000..d47b3f7c1
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/StatusBar.tsx
@@ -0,0 +1,64 @@
+import type { ReactNode } from "react"
+import { cn } from "@/lib/utils"
+
+export type StatusVariant = "pending" | "success" | "error"
+
+export interface StatusBarProps {
+ variant: StatusVariant
+ icon: ReactNode
+ title: string
+ subtitle?: string
+ timer?: string
+ actions?: ReactNode
+ children?: ReactNode
+}
+
+const variantStyles: Record = {
+ pending: "bg-yellow-50 border-yellow-200 text-yellow-900 dark:bg-yellow-950 dark:border-yellow-800 dark:text-yellow-100",
+ success: "bg-green-50 border-green-200 text-green-900 dark:bg-green-950 dark:border-green-800 dark:text-green-100",
+ error: "bg-red-50 border-red-200 text-red-900 dark:bg-red-950 dark:border-red-800 dark:text-red-100",
+}
+
+export function StatusBar({
+ variant,
+ icon,
+ title,
+ subtitle,
+ timer,
+ actions,
+ children,
+}: StatusBarProps) {
+ return (
+
+ {/* Main row: icon + title + timer/actions */}
+
+
+ {icon}
+ {title}
+
+
+ {timer && (
+ {timer}
+ )}
+ {actions}
+
+
+
+ {/* Subtitle if present */}
+ {subtitle && (
+
+ {subtitle}
+
+ )}
+
+ {/* Children (BOC/Hash, verification results) */}
+ {children && (
+
+ )}
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/TransactionDetails.tsx b/apps/tonconnect-demo/src/components/shared/TransactionDetails.tsx
new file mode 100644
index 000000000..4d44c2e82
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/TransactionDetails.tsx
@@ -0,0 +1,78 @@
+import { Button } from "@/components/ui/button"
+import { Label } from "@/components/ui/label"
+import { Copy, ExternalLink } from "lucide-react"
+import { getExplorerUrl } from "@/utils/explorer-utils"
+import { copyToClipboard } from "@/utils/clipboard"
+
+interface TransactionDetailsProps {
+ boc: string
+ hash: string | null
+ network: "mainnet" | "testnet"
+}
+
+export function TransactionDetails({ boc, hash, network }: TransactionDetailsProps) {
+ return (
+
+ {/* BOC - truncated with length indicator */}
+
+
+ BOC ({boc.length} chars)
+
+
+ copyToClipboard(boc)}
+ title="Click to copy full BOC"
+ >
+ {boc.slice(0, 50)}...
+
+ copyToClipboard(boc)}
+ >
+
+
+
+
+
+ {/* Hash - full display with word-break */}
+ {hash && (
+
+
+
Hash (TEP-467)
+
+
+
+
+
+
+
copyToClipboard(hash)}
+ >
+
+
+
+
+
+ {hash}
+
+
+ )}
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/shared/VerificationResult.tsx b/apps/tonconnect-demo/src/components/shared/VerificationResult.tsx
new file mode 100644
index 000000000..d7d7335e8
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/shared/VerificationResult.tsx
@@ -0,0 +1,36 @@
+import { CheckCircle, XCircle } from "lucide-react"
+import type { VerificationResult as VerificationResultType } from "@/utils/sign-data-verification"
+
+interface VerificationResultProps {
+ title: string // "Client" | "Server"
+ result: VerificationResultType
+}
+
+export function VerificationResult({ title, result }: VerificationResultProps) {
+ const isValid = result.valid
+
+ return (
+
+ {/* Title + status */}
+
+ {isValid ? (
+
+ ) : (
+
+ )}
+
+ {title}: {isValid ? "Valid" : "Invalid"}
+
+
+
+ {/* Details */}
+ {result.details && (
+
+ Address {result.details.addressMatch ? "✓" : "✗"} •{" "}
+ Public key {result.details.publicKeyMatch ? "✓" : "✗"} •{" "}
+ Signature {result.details.signatureValid ? "✓" : "✗"}
+
+ )}
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/tabs/ConnectTab.tsx b/apps/tonconnect-demo/src/components/tabs/ConnectTab.tsx
new file mode 100644
index 000000000..dae864ec8
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/tabs/ConnectTab.tsx
@@ -0,0 +1,562 @@
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Button } from "@/components/ui/button"
+import { Alert, AlertDescription } from "@/components/ui/alert"
+import { Badge } from "@/components/ui/badge"
+import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
+import { useConnect } from "@/hooks/useConnect"
+import { ConnectedWalletCard } from "@/components/shared/ConnectedWalletCard"
+import { ConnectionEventsCard } from "@/components/shared/ConnectionEventsCard"
+import { JsonViewer } from "@/components/shared/JsonViewer"
+import { HowItWorksCard } from "@/components/shared/HowItWorksCard"
+import { FieldLabel } from "@/components/shared/FieldLabel"
+import {
+ Plug,
+ RefreshCw,
+ Key,
+ ShieldCheck,
+ User,
+ Loader2,
+ XCircle,
+ AlertCircle,
+ ChevronRight,
+ Copy,
+ Check
+} from "lucide-react"
+import { useState } from "react"
+import { copyToClipboard } from "@/utils/clipboard"
+
+// Inline copy button for text flow
+function InlineCopyButton({ text }: { text: string }) {
+ const [copied, setCopied] = useState(false)
+
+ const handleCopy = async () => {
+ await copyToClipboard(text)
+ setCopied(true)
+ setTimeout(() => setCopied(false), 2000)
+ }
+
+ return (
+
+ {copied ? : }
+
+ )
+}
+
+// Verification checks from backend
+interface VerifyChecks {
+ jwtValid: boolean
+ payloadMatch: boolean
+ publicKeyMatch: boolean
+ addressMatch: boolean
+ domainAllowed: boolean
+ timestampValid: boolean
+ signatureValid: boolean
+}
+
+
+// Display proof data from wallet
+interface TonProof {
+ timestamp: number
+ domain: { lengthBytes: number; value: string }
+ payload: string
+ signature: string
+ state_init?: string
+}
+
+interface WalletResponseDisplayProps {
+ proof: TonProof | null
+ address: string | null
+ publicKey: string | null
+ checks: VerifyChecks | null
+ payloadToken: string | null
+}
+
+function CheckMark({ valid }: { valid: boolean }) {
+ return valid ? (
+ ✓
+ ) : (
+ ✗
+ )
+}
+
+function WalletResponseDisplay({ proof, address, publicKey, checks, payloadToken }: WalletResponseDisplayProps) {
+ return (
+
+
Wallet Response
+
+
+ {/* timestamp */}
+
+ timestamp
+ {proof ? (
+ <>
+ {proof.timestamp}
+
+ ({new Date(proof.timestamp * 1000).toLocaleTimeString('en-US', { hour12: false })})
+
+ {checks && }
+ >
+ ) : (
+ signing time (unix)
+ )}
+
+
+ {/* domain */}
+
+ domain
+ {proof ? (
+ <>
+ {proof.domain.value}
+ {checks && }
+ >
+ ) : (
+ requesting domain
+ )}
+
+
+ {/* payload */}
+
+ payload
+ {proof ? (
+ <>
+ copyToClipboard(proof.payload)}
+ className="font-mono bg-primary/10 py-0.5 rounded break-all cursor-pointer hover:bg-primary/20 transition-colors [box-decoration-break:clone] [-webkit-box-decoration-break:clone]"
+ title="Click to copy"
+ >
+ {proof.payload}
+
+ {checks && }
+ >
+ ) : (
+ your challenge
+ )}
+
+
+ {/* signature */}
+
+ signature
+ {proof ? (
+ <>
+ copyToClipboard(proof.signature)}
+ className="font-mono bg-primary/10 py-0.5 rounded break-all cursor-pointer hover:bg-primary/20 transition-colors [box-decoration-break:clone] [-webkit-box-decoration-break:clone]"
+ title="Click to copy"
+ >
+ {proof.signature}
+
+ {checks && }
+ >
+ ) : (
+ Ed25519 signature
+ )}
+
+
+
+ {/* Account data (from wallet.account) */}
+
+ {/* address */}
+
+ address
+ {address ? (
+ <>
+ copyToClipboard(address)}
+ className="font-mono bg-primary/10 py-0.5 rounded break-all cursor-pointer hover:bg-primary/20 transition-colors [box-decoration-break:clone] [-webkit-box-decoration-break:clone]"
+ title="Click to copy"
+ >
+ {address}
+
+ {checks && }
+ >
+ ) : (
+ wallet address
+ )}
+
+
+ {/* public key */}
+
+ public key
+ {publicKey ? (
+ <>
+ copyToClipboard(publicKey)}
+ className="font-mono bg-primary/10 py-0.5 rounded break-all cursor-pointer hover:bg-primary/20 transition-colors [box-decoration-break:clone] [-webkit-box-decoration-break:clone]"
+ title="Click to copy"
+ >
+ {publicKey}
+
+ {checks && }
+ >
+ ) : (
+ Ed25519 public key
+ )}
+
+
+
+ {/* Implementation details */}
+
+
+
+ Implementation details
+
+
+
+ JWT
+ {payloadToken ? (
+ <>
+ copyToClipboard(payloadToken)}
+ className="font-mono bg-primary/10 py-0.5 rounded break-all cursor-pointer hover:bg-primary/20 transition-colors [box-decoration-break:clone] [-webkit-box-decoration-break:clone]"
+ title="Click to copy"
+ >
+ {payloadToken}
+
+ {checks && }
+ >
+ ) : (
+ stateless auth token
+ )}
+
+
+
+
+ )
+}
+
+function PayloadDisplay({ response }: { response: Record }) {
+ const payloadToken = String(response.payloadToken || '')
+ const payloadTokenHash = String(response.payloadTokenHash || '')
+
+ return (
+
+ {/* Challenge - inline text flow */}
+
+ Challenge {' '}
+
+ {payloadTokenHash}
+
+
+
+
+ {/* Implementation detail */}
+
+
+
+ Implementation details (JWT)
+
+
+
+
+ payloadToken
+
+
+ {payloadToken}
+
+
+ This demo uses JWT to create a stateless backend. Your implementation may differ.
+
+
+
+
+
+ )
+}
+
+export function ConnectTab() {
+ const {
+ wallet,
+ hasProof,
+ isAuthenticated,
+
+ operations,
+ clearOperations,
+ deleteOperation,
+
+ isGeneratingPayload,
+ isConnecting,
+ isVerifying,
+ isFetchingAccount,
+
+ connect,
+ disconnect,
+ generatePayload,
+ connectWithProof,
+ verifyProof,
+ getAccountInfo,
+
+ payloadResult,
+ verifyResult,
+ accountResult,
+
+ canConnect,
+ canConnectWithProof,
+ canVerify,
+ canGetAccount
+ } = useConnect()
+
+ return (
+
+ {/* Connected Wallet Card - TOP */}
+
+
+ {/* Two columns: 1fr / 2fr */}
+
+ {/* Left: Simple Connection */}
+
+
+
+
+ Simple Connection
+
+
+ Connect wallet without TonProof
+
+
+
+
+ {isConnecting && !hasProof ? (
+
+ ) : (
+
+ )}
+ Connect
+
+
+
+
+ {/* Right: TonProof Connect */}
+
+
+
+
+ TonProof Connect
+
+
+ Connect with cryptographic proof of wallet ownership
+
+
+
+ {/* Step 1: Backend Challenge */}
+
+
+
+ 1
+
+
+
+
+ Backend Challenge
+
+
+ {isGeneratingPayload ? (
+
+ ) : (
+
+ )}
+
+
+
Your backend generates a challenge for wallet to sign
+
+ {payloadResult?.status === 'error' && (
+
+ )}
+
+
+
+ {/* Loading state */}
+ {isGeneratingPayload && !payloadResult && (
+
+
+ Generating challenge...
+
+ )}
+
+ {/* Payload Data */}
+ {payloadResult?.status === 'success' && payloadResult.response != null && (
+
} />
+ )}
+
+ {/* Error */}
+ {payloadResult?.status === 'error' && (
+
+
+ {payloadResult.error}
+
+ )}
+
+
+
+ {/* Step 2: Connect with Proof */}
+
+
+
+ 2
+
+
+
+
+ Connect with Proof
+
+
+ {isConnecting ? (
+
+ ) : (
+
+ )}
+ Connect
+
+
+
Opens wallet with TonProof request
+
+
+
+
+ {/* Step 3: Verify Proof */}
+
+
+
+ 3
+
+
+
+
+ Verify Proof
+
+
+ {isVerifying ? (
+
+ ) : isAuthenticated ? (
+
+ ) : (
+
+ )}
+ {isAuthenticated ? "Verified" : "Verify"}
+
+
+
+ Send proof to backend for cryptographic verification
+
+
+
+
+
+
+ {/* Wallet Response */}
+
+
+
+ {/* Example: Using Auth Token (collapsible, only after verification) */}
+ {isAuthenticated && (
+
+
+
+ Example: Using the Auth Token
+ Optional
+
+
+
+
+ After successful verification, your backend returns an auth token.
+ This example shows how to use it for authenticated API calls.
+
+
+ {isFetchingAccount ? (
+
+ ) : (
+
+ )}
+ Get Account Info
+
+ {accountResult && (
+
+ {accountResult.status === 'error' && (
+
+
+ {accountResult.error}
+
+ )}
+ {accountResult.request != null && (
+
+ )}
+ {accountResult.status === 'success' && accountResult.response != null && (
+
+ )}
+
+ )}
+
+
+
+ )}
+
+
+
+
+ {/* Connection Events */}
+
+
+ {/* How It Works */}
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/tabs/DevToolsTab.tsx b/apps/tonconnect-demo/src/components/tabs/DevToolsTab.tsx
new file mode 100644
index 000000000..420489f33
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/tabs/DevToolsTab.tsx
@@ -0,0 +1,283 @@
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Label } from "@/components/ui/label"
+import { Switch } from "@/components/ui/switch"
+import { Button } from "@/components/ui/button"
+import { Badge } from "@/components/ui/badge"
+import { useDevToolsContext } from "@/context/DevToolsContext"
+import { AlertTriangle, Lock, RotateCcw, Terminal, Bug, Radio, BookOpen } from "lucide-react"
+
+export function DevToolsTab() {
+ const {
+ qaMode,
+ setQaMode,
+ erudaEnabled,
+ setErudaEnabled,
+ rpcLogsEnabled,
+ setRpcLogsEnabled,
+ docsHidden,
+ setDocsHidden,
+ showDeprecated,
+ setShowDeprecated,
+ showExperimental,
+ setShowExperimental,
+ lockDevTools,
+ resetAll,
+ } = useDevToolsContext()
+
+ return (
+
+ {/* Warning Banner */}
+
+
+
+
Developer Tools
+
+ These settings are for development and testing only. Do not use in production.
+
+
+
+
+
+ {/* QA Mode */}
+
+
+
+
+ QA Mode
+ SDK
+
+
+ SDK development mode: disables validations and uses staging wallets list
+
+
+
+
+
+
Enable QA Mode
+
+ Page will reload when changed
+
+
+
+
+
+
+
When enabled:
+
+ Validation errors become console warnings
+ Cross-network transactions allowed
+ Uses staging wallets list
+ Shows injected wallets
+
+
+
+
+
+ {/* Eruda Console */}
+
+
+
+
+ Mobile Console
+
+
+ Eruda console for mobile debugging
+
+
+
+
+
+
Enable Eruda
+
+ Shows debug console on screen
+
+
+
+
+
+
+
Eruda provides:
+
+ Console logs viewer
+ Network requests inspector
+ DOM elements explorer
+ Storage viewer
+
+
+
+
+
+ {/* RPC Logs */}
+
+
+
+
+ RPC Logs
+
+
+ Capture raw SDK requests and responses
+
+
+
+
+
+
Enable RPC Logs
+
+ Intercepts console.debug from SDK
+
+
+
+
+
+
+
Shows raw JSON-RPC data:
+
+ Request payloads with id
+ Response payloads
+ Request/response timing
+ Error details
+
+
+
+
+
+ {/* Documentation */}
+
+
+
+
+ Documentation
+
+
+ Show or hide inline documentation
+
+
+
+
+
+
Hide Documentation
+
+ Hides "How it works" sections
+
+
+
+
+
+
+
When hidden:
+
+ HowItWorks cards are hidden
+ Cleaner interface for demos
+ Field tooltips remain visible
+
+
+
+
+
+
+
+ {/* Actions, Info & Deprecated */}
+
+
+
+ Actions
+ Manage DevTools settings
+
+
+
+
+ Lock DevTools
+
+
+
+ Reset All
+
+
+
+
+
+
+ Information
+ Current DevTools state
+
+
+
+
localStorage keys:
+
+ devtools:qa-mode: {localStorage.getItem('devtools:qa-mode') ?? 'null'}
+ devtools:eruda: {localStorage.getItem('devtools:eruda') ?? 'null'}
+ devtools:rpc-logs: {localStorage.getItem('devtools:rpc-logs') ?? 'null'}
+ devtools:docs-hidden: {localStorage.getItem('devtools:docs-hidden') ?? 'null'}
+ devtools:show-deprecated: {localStorage.getItem('devtools:show-deprecated') ?? 'null'}
+ devtools:show-experimental: {localStorage.getItem('devtools:show-experimental') ?? 'null'}
+ devtools:unlocked: {localStorage.getItem('devtools:unlocked') ?? 'null'}
+
+
+
+
+
+
+
+
+
+ Deprecated / Experimental
+
+ Show hidden options in Settings
+
+
+
+
+
Deprecated
+
+ skipRedirectToWallet
+
+
+
+
+
+
+
Experimental
+
+ Configuration Export
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/tabs/SettingsTab.tsx b/apps/tonconnect-demo/src/components/tabs/SettingsTab.tsx
new file mode 100644
index 000000000..0f6fbbe78
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/tabs/SettingsTab.tsx
@@ -0,0 +1,512 @@
+import { useState } from "react"
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Label } from "@/components/ui/label"
+import { Input } from "@/components/ui/input"
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
+import { Switch } from "@/components/ui/switch"
+import { Button } from "@/components/ui/button"
+import { Checkbox } from "@/components/ui/checkbox"
+import { useSettingsContext } from "@/context/SettingsContext"
+import { useDevToolsContext } from "@/context/DevToolsContext"
+import { NetworkPicker } from "@/components/NetworkPicker"
+import { FieldLabel } from "@/components/shared/FieldLabel"
+import { JsonViewer } from "@/components/shared/JsonViewer"
+import { TabsList, TabsTrigger } from "@/components/ui/tabs"
+import { RotateCcw, AlertTriangle, Copy } from "lucide-react"
+import { toast } from "sonner"
+import type { ThemeOption, LanguageOption, ColorsConfig, FeaturesMode, ExportFormat } from "@/hooks/useSettings"
+
+function ColorInput({
+ label,
+ value,
+ onChange
+}: {
+ label: string
+ value: string
+ onChange: (value: string) => void
+}) {
+ return (
+
+ )
+}
+
+function ColorsCard({
+ title,
+ description,
+ colors,
+ onUpdate
+}: {
+ title: string
+ description: string
+ colors: ColorsConfig
+ onUpdate: (key: keyof ColorsConfig, value: string) => void
+}) {
+ return (
+
+
+ {title}
+ {description}
+
+
+
+
Constants
+
onUpdate("constantBlack", v)} />
+ onUpdate("constantWhite", v)} />
+
+
+
Connect Button
+
onUpdate("connectButtonBg", v)} />
+ onUpdate("connectButtonFg", v)} />
+
+
+
General
+
onUpdate("accent", v)} />
+ onUpdate("telegramButton", v)} />
+
+
+
Icons
+
onUpdate("iconPrimary", v)} />
+ onUpdate("iconSecondary", v)} />
+ onUpdate("iconTertiary", v)} />
+ onUpdate("iconSuccess", v)} />
+ onUpdate("iconError", v)} />
+
+
+
Background
+
onUpdate("backgroundPrimary", v)} />
+ onUpdate("backgroundSecondary", v)} />
+ onUpdate("backgroundSegment", v)} />
+ onUpdate("backgroundTint", v)} />
+ onUpdate("backgroundQr", v)} />
+
+
+
Text
+
onUpdate("textPrimary", v)} />
+ onUpdate("textSecondary", v)} />
+
+
+
+ )
+}
+
+export function SettingsTab() {
+ const {
+ manifestUrl, setManifestUrl,
+ buildConfiguration,
+ formatConfiguration,
+ language, setLanguage,
+ theme, setTheme,
+ borderRadius, setBorderRadius,
+ darkColors, updateDarkColor,
+ lightColors, updateLightColor,
+ resetColors,
+ modalsBefore, setModalsBefore,
+ modalsSuccess, setModalsSuccess,
+ modalsError, setModalsError,
+ notificationsBefore, setNotificationsBefore,
+ notificationsSuccess, setNotificationsSuccess,
+ notificationsError, setNotificationsError,
+ returnStrategy, setReturnStrategy,
+ twaReturnUrl, setTwaReturnUrl,
+ skipRedirect, setSkipRedirect,
+ enableAndroidBackHandler, setEnableAndroidBackHandler,
+ featuresMode, setFeaturesMode,
+ minMessages, setMinMessages,
+ extraCurrencyRequired, setExtraCurrencyRequired,
+ signDataTypes, setSignDataTypes,
+ } = useSettingsContext()
+
+ const { showDeprecated, showExperimental } = useDevToolsContext()
+ const [showFullConfig, setShowFullConfig] = useState(false)
+ const [exportFormat, setExportFormat] = useState("json")
+ const [includeDeprecatedInExport, setIncludeDeprecatedInExport] = useState(false)
+
+ const handleSignDataTypeChange = (type: string, checked: boolean) => {
+ if (checked) {
+ setSignDataTypes([...signDataTypes, type])
+ } else {
+ setSignDataTypes(signDataTypes.filter(t => t !== type))
+ }
+ }
+
+ return (
+
+ {/* Manifest URL */}
+
+
+
+ Manifest URL
+ {""}
+
+ Your dApp manifest for wallet identification
+
+
+ setManifestUrl(e.target.value)}
+ placeholder="https://your-app.com/tonconnect-manifest.json"
+ />
+
+
+
+ {/* Row 1: Connection Settings + Modals + Notifications */}
+
+
+
+ Connection Settings
+ Network and wallet filtering
+
+
+
+
+
+ Wallet Features Filter
+ setFeaturesMode(v as FeaturesMode)}>
+
+
+ None (show all wallets)
+ Required (disable unsupported)
+ Preferred (move to end)
+
+
+
+
+ {featuresMode !== "none" && (
+
+
+ Min Messages
+ setMinMessages(e.target.value ? parseInt(e.target.value) : undefined)}
+ />
+
+
+ Extra Currency
+
+
+
+
Sign Data Types
+
+ {["text", "cell", "binary"].map(type => (
+
+ handleSignDataTypeChange(type, !!checked)}
+ />
+ {type}
+
+ ))}
+
+
+
+ )}
+
+
+
+
+
+ Modals
+ Show modal dialogs for actions
+
+
+
+ Before
+
+
+
+ Success
+
+
+
+ Error
+
+
+
+
+
+
+
+ Notifications
+ Show toast notifications
+
+
+
+ Before
+
+
+
+ Success
+
+
+
+ Error
+
+
+
+
+
+
+ {/* Row 2: UI Settings + Redirect Settings */}
+
+
+
+ UI Settings
+ TonConnect UI appearance
+
+
+
+ Language
+ setLanguage(v as LanguageOption)}>
+
+
+ System (auto-detect)
+ English
+ Русский
+
+
+
+
+ Theme
+ setTheme(v as ThemeOption)}>
+
+
+ Dark
+ Light
+ System
+
+
+
+
+ Border Radius
+ setBorderRadius(v as "s" | "m" | "none")}>
+
+
+ Medium
+ Small
+ None
+
+
+
+
+
+
+
+
+ Redirect Settings
+ Configure wallet redirect behavior
+
+
+
+ Return Strategy
+ setReturnStrategy(v as "back" | "none")}>
+
+
+ Back
+ None
+
+
+
+
+
TWA Return URL
+
setTwaReturnUrl(e.target.value)}
+ placeholder="tg://resolve?domain=..."
+ />
+
+ Return URL for Telegram Web App connections
+
+
+
+
+
+
+ {/* Row 3: Android Settings */}
+
+
+ Android Settings
+ Android-specific behavior
+
+
+
+
+
Enable Back Handler
+
+ Use Android back button to close modals
+
+
+
+
+
+
+
+ {/* Row 4: Colors */}
+
+
+
Colors
+
+
+ Reset to Defaults
+
+
+
+
+
+
+
+
+ {/* Deprecated Options - only shown when enabled in DevTools */}
+ {showDeprecated && (
+
+
+
+
+ Deprecated Options
+
+
+ These options are deprecated and may be removed in future SDK versions
+
+
+
+
+
Skip Redirect to Wallet
+
setSkipRedirect(v as "never" | "always" | "ios")}>
+
+
+ iOS only
+ Never
+ Always
+
+
+
+ Deprecated: SDK now auto-detects for TWA connections. In TMA this is always forced to "never".
+
+
+
+
+ )}
+
+ {/* Configuration Export - Experimental */}
+ {showExperimental && (
+
+
+ Configuration Export
+
+
+ {/* Combined controls: Tabs + Options */}
+
+
+ setExportFormat("json")}
+ data-state={exportFormat === "json" ? "active" : "inactive"}
+ >
+ JSON
+
+ setExportFormat("react")}
+ data-state={exportFormat === "react" ? "active" : "inactive"}
+ >
+ React
+
+ setExportFormat("vanilla")}
+ data-state={exportFormat === "vanilla" ? "active" : "inactive"}
+ >
+ Vanilla JS
+
+
+
+
+
+ setShowFullConfig(!!checked)}
+ />
+ All
+
+ {showDeprecated && (
+
+ setIncludeDeprecatedInExport(!!checked)}
+ />
+ Deprecated
+
+ )}
+ {
+ const content = formatConfiguration(buildConfiguration(showFullConfig, includeDeprecatedInExport), exportFormat)
+ await navigator.clipboard.writeText(content)
+ toast.success("Copied to clipboard")
+ }}
+ >
+
+ Copy
+
+
+
+
+
+
+
+ )}
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/tabs/SignDataTab.tsx b/apps/tonconnect-demo/src/components/tabs/SignDataTab.tsx
new file mode 100644
index 000000000..fd7fa047f
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/tabs/SignDataTab.tsx
@@ -0,0 +1,145 @@
+import { useRef, useEffect } from "react"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Textarea } from "@/components/ui/textarea"
+import { FormContainer } from "@/components/shared/FormContainer"
+import { SignDataResultCard } from "@/components/shared/SignDataResultCard"
+import { HowItWorksCard } from "@/components/shared/HowItWorksCard"
+import { FieldLabel } from "@/components/shared/FieldLabel"
+import { useSignData } from "@/hooks/useSignData"
+import { useSettingsContext } from "@/context/SettingsContext"
+import { validateSignDataJson } from "@/utils/validator"
+
+export function SignDataTab() {
+ const resultRef = useRef(null)
+ const { notificationsBefore, notificationsSuccess, notificationsError } = useSettingsContext()
+ const {
+ dataType, setDataType,
+ dataText, setDataText,
+ schema, setSchema,
+ requestJson,
+ sign,
+ setFromJson,
+ isConnected,
+ isSigning,
+ // Result
+ lastResult,
+ clearResult,
+ loadResultToForm,
+ // Verification
+ canVerify,
+ verify,
+ verificationResult,
+ isVerifying,
+ verifyOnServer,
+ serverVerificationResult,
+ isVerifyingOnServer,
+ } = useSignData(notificationsBefore, notificationsSuccess, notificationsError)
+
+ // Scroll to result when it appears
+ useEffect(() => {
+ if (lastResult && resultRef.current) {
+ const rect = resultRef.current.getBoundingClientRect()
+ // Scroll if result is not fully visible
+ if (rect.top < 0 || rect.bottom > window.innerHeight) {
+ resultRef.current.scrollIntoView({ behavior: "smooth", block: "start" })
+ }
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- trigger only on new result id
+ }, [lastResult?.id])
+
+ const formContent = (
+ <>
+
+
Data Type
+
+ setDataType("text")}
+ className="flex-1 h-8 rounded-md text-sm"
+ >
+ Text
+
+ setDataType("binary")}
+ className="flex-1 h-8 rounded-md text-sm"
+ >
+ Binary
+
+ setDataType("cell")}
+ className="flex-1 h-8 rounded-md text-sm"
+ >
+ Cell
+
+
+
+
+ {dataType === "cell" && (
+
+ Schema (TL-B)
+ setSchema(e.target.value)}
+ placeholder="e.g. transfer#123abc amount:Coins"
+ />
+
+ )}
+
+
+
+ {dataType === "text" ? "Text" : dataType === "binary" ? "Data (base64)" : "Cell (BOC)"}
+
+
+ >
+ )
+
+ return (
+
+
+
+ {lastResult && (
+
+
+
+ )}
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/tabs/SubscriptionTab.tsx b/apps/tonconnect-demo/src/components/tabs/SubscriptionTab.tsx
new file mode 100644
index 000000000..9e5110b48
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/tabs/SubscriptionTab.tsx
@@ -0,0 +1,18 @@
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+
+export function SubscriptionTab() {
+ return (
+
+
+ Subscription
+ Set up recurring payment subscriptions
+
+
+ Coming soon
+
+ This feature will allow you to create and manage recurring payment subscriptions.
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/tabs/TransactionTab.tsx b/apps/tonconnect-demo/src/components/tabs/TransactionTab.tsx
new file mode 100644
index 000000000..43b02248b
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/tabs/TransactionTab.tsx
@@ -0,0 +1,373 @@
+import { useState, useEffect, useMemo, useRef } from "react"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Textarea } from "@/components/ui/textarea"
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
+import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
+import { FormContainer } from "@/components/shared/FormContainer"
+import { ResultCard } from "@/components/shared/ResultCard"
+import { HistoryList } from "@/components/shared/HistoryList"
+import { HowItWorksCard } from "@/components/shared/HowItWorksCard"
+import { FieldLabel } from "@/components/shared/FieldLabel"
+import { useTransaction, PRESETS } from "@/hooks/useTransaction"
+import { useSettingsContext } from "@/context/SettingsContext"
+import { validateTransactionJson } from "@/utils/validator"
+import { Plus, Trash2, ChevronRight, ChevronDown } from "lucide-react"
+import type { AmountUnit, PresetKey } from "@/hooks/useTransaction"
+
+export function TransactionTab() {
+ const { modalsBefore, modalsSuccess, modalsError } = useSettingsContext()
+ const {
+ validUntil, setValidUntil,
+ addTimeToValidUntil,
+ network, setNetwork,
+ from, setFrom,
+ messages,
+ getDisplayAmount,
+ setMessageAmount,
+ getAmountUnit,
+ setAmountUnit,
+ requestJson,
+ loadPreset,
+ addMessage,
+ removeMessage,
+ updateMessage,
+ send,
+ sendRaw,
+ setFromJson,
+ isConnected,
+ isSending,
+ lastResult,
+ clearResult,
+ loadResultToForm,
+ currentWalletAddress,
+ loadHistoryToForm,
+ isConnectionRestored,
+ walletNetwork,
+ } = useTransaction(modalsBefore, modalsSuccess, modalsError)
+
+ // Convert PRESETS to array format for FormContainer
+ const presetOptions = useMemo(() =>
+ Object.entries(PRESETS).map(([id, preset]) => ({
+ id,
+ name: preset.name,
+ description: preset.description,
+ })),
+ []
+ )
+
+ const handlePresetSelect = (presetId: string) => {
+ loadPreset(presetId as PresetKey)
+ }
+
+ // UI state for payload collapsibles
+ const [expandedPayloads, setExpandedPayloads] = useState>({})
+
+ // Result scroll ref
+ const resultRef = useRef(null)
+
+ // Live countdown timer (combined state to reduce re-renders)
+ const [timerState, setTimerState] = useState({
+ displayTime: "",
+ hoverTime: "",
+ status: "ok" as "ok" | "warning" | "danger" | "expired"
+ })
+ const [isHoveringTimer, setIsHoveringTimer] = useState(false)
+
+ useEffect(() => {
+ // Format compact time with smart date context
+ const formatCompactTime = (timestamp: number) => {
+ const date = new Date(timestamp * 1000)
+ const now = new Date()
+ const isToday = date.toDateString() === now.toDateString()
+ const tomorrow = new Date(now)
+ tomorrow.setDate(tomorrow.getDate() + 1)
+ const isTomorrow = date.toDateString() === tomorrow.toDateString()
+
+ const time = date.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false })
+
+ if (isToday) return time
+ if (isTomorrow) return `tmrw ${time}`
+ return date.toLocaleDateString('en-GB', { day: 'numeric', month: 'short' }) + ` ${time}`
+ }
+
+ // Format full datetime for hover (local time, ISO-like format)
+ const formatFullTime = (timestamp: number) => {
+ const date = new Date(timestamp * 1000)
+ const year = date.getFullYear()
+ const month = String(date.getMonth() + 1).padStart(2, '0')
+ const day = String(date.getDate()).padStart(2, '0')
+ const hours = String(date.getHours()).padStart(2, '0')
+ const mins = String(date.getMinutes()).padStart(2, '0')
+ const secs = String(date.getSeconds()).padStart(2, '0')
+ return `${year}-${month}-${day} ${hours}:${mins}:${secs}`
+ }
+
+ // Format countdown as Xh Ym Zs
+ const formatCountdown = (diff: number) => {
+ const hours = Math.floor(diff / 3600)
+ const mins = Math.floor((diff % 3600) / 60)
+ const secs = diff % 60
+ if (hours > 0) return `${hours}h ${mins}m ${secs}s`
+ if (mins > 0) return `${mins}m ${secs}s`
+ return `${secs}s`
+ }
+
+ const updateTimer = () => {
+ const now = Math.floor(Date.now() / 1000)
+ const diff = validUntil - now
+
+ if (diff <= 0) {
+ setTimerState({ displayTime: "Expired", hoverTime: "Expired", status: "expired" })
+ } else if (diff < 120) {
+ // <2m: countdown + time, danger
+ setTimerState({
+ displayTime: `${diff}s · ${formatCompactTime(validUntil)}`,
+ hoverTime: `${formatCountdown(diff)} · ${formatFullTime(validUntil)}`,
+ status: "danger"
+ })
+ } else if (diff < 600) {
+ // 2-10m: just time, warning
+ setTimerState({
+ displayTime: formatCompactTime(validUntil),
+ hoverTime: `${formatCountdown(diff)} · ${formatFullTime(validUntil)}`,
+ status: "warning"
+ })
+ } else {
+ // >10m: just time, ok
+ setTimerState({
+ displayTime: formatCompactTime(validUntil),
+ hoverTime: `${formatCountdown(diff)} · ${formatFullTime(validUntil)}`,
+ status: "ok"
+ })
+ }
+ }
+
+ updateTimer()
+ const interval = setInterval(updateTimer, 1000)
+ return () => clearInterval(interval)
+ }, [validUntil])
+
+ // Toggle payload section for a message
+ const togglePayload = (index: number) => {
+ setExpandedPayloads(prev => ({ ...prev, [index]: !prev[index] }))
+ }
+
+ // Scroll to result when it appears
+ useEffect(() => {
+ if (lastResult && resultRef.current) {
+ const rect = resultRef.current.getBoundingClientRect()
+ if (rect.top < 0 || rect.bottom > window.innerHeight) {
+ resultRef.current.scrollIntoView({ behavior: "smooth", block: "start" })
+ }
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- trigger only on new result id
+ }, [lastResult?.id])
+
+ const formContent = (
+ <>
+ {/* Valid Until - unix timestamp with quick buttons */}
+
+
setIsHoveringTimer(true)}
+ onMouseLeave={() => setIsHoveringTimer(false)}
+ >
+ Valid Until
+
+
+
+ {isHoveringTimer ? timerState.hoverTime : timerState.displayTime}
+
+
+
+
+
setValidUntil(parseInt(e.target.value) || 0)}
+ className="flex-1 min-w-[120px] font-mono"
+ />
+
+ addTimeToValidUntil(60)}>+1m
+ addTimeToValidUntil(300)}>+5m
+ addTimeToValidUntil(43200)}>+12h
+
+
+
+
+ {/* Network + From */}
+
+
+
Network (optional)
+ {!isConnectionRestored ? (
+
+ ) : (
+
setNetwork(e.target.value)}
+ placeholder={walletNetwork || "e.g. -239 for mainnet"}
+ disabled={!!walletNetwork}
+ />
+ )}
+
+
+ From (optional)
+ setFrom(e.target.value)}
+ placeholder="Sender address"
+ />
+
+
+
+ {/* Messages */}
+
+
+
+ {messages.map((message, index) => (
+
+ {/* Header with delete button */}
+
+ Message {index + 1}
+ {messages.length > 1 && (
+ removeMessage(index)} aria-label="Remove message">
+
+
+ )}
+
+
+ {/* Address */}
+
+ Address
+ updateMessage(index, "address", e.target.value)}
+ placeholder="Recipient address"
+ className="h-9"
+ />
+
+
+ {/* Amount with unit selector */}
+
+
Amount
+
+ setMessageAmount(index, e.target.value, getAmountUnit(index))}
+ placeholder={getAmountUnit(index) === "TON" ? "0.001" : "1000000"}
+ className="h-9 flex-1"
+ />
+ setAmountUnit(index, v as AmountUnit)}
+ >
+
+
+
+
+ TON
+ nano
+
+
+
+
+
+ {/* Payload + StateInit (collapsible, auto-open when has content) */}
+ {(() => {
+ const hasContent = !!message.payload || !!message.stateInit
+ const isOpen = hasContent || expandedPayloads[index]
+ return (
+
!hasContent && togglePayload(index)}>
+
+ {isOpen ? : }
+ Payload, State Init
+
+
+
+ Payload
+
+
+ State Init
+
+
+
+ )
+ })()}
+
+ ))}
+
+ >
+ )
+
+ return (
+
+
+
+ {lastResult && (
+
+
+
+ )}
+
+
+
+
+
+ )
+}
diff --git a/apps/tonconnect-demo/src/components/tabs/index.ts b/apps/tonconnect-demo/src/components/tabs/index.ts
new file mode 100644
index 000000000..38e4f9b63
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/tabs/index.ts
@@ -0,0 +1,6 @@
+export { TransactionTab } from "./TransactionTab"
+export { SignDataTab } from "./SignDataTab"
+export { SubscriptionTab } from "./SubscriptionTab"
+export { ConnectTab } from "./ConnectTab"
+export { SettingsTab } from "./SettingsTab"
+export { DevToolsTab } from "./DevToolsTab"
diff --git a/apps/tonconnect-demo/src/components/ui/alert.tsx b/apps/tonconnect-demo/src/components/ui/alert.tsx
new file mode 100644
index 000000000..33fa48849
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/alert.tsx
@@ -0,0 +1,61 @@
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const alertVariants = cva(
+ "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
+ {
+ variants: {
+ variant: {
+ default: "bg-background text-foreground",
+ destructive:
+ "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
+ success:
+ "border-success/50 text-success dark:border-success [&>svg]:text-success",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+)
+
+const Alert = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes & VariantProps
+>(({ className, variant, ...props }, ref) => (
+
+))
+Alert.displayName = "Alert"
+
+const AlertTitle = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+AlertTitle.displayName = "AlertTitle"
+
+const AlertDescription = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+AlertDescription.displayName = "AlertDescription"
+
+export { Alert, AlertTitle, AlertDescription }
diff --git a/apps/tonconnect-demo/src/components/ui/badge.tsx b/apps/tonconnect-demo/src/components/ui/badge.tsx
new file mode 100644
index 000000000..e87d62bf1
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/badge.tsx
@@ -0,0 +1,36 @@
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const badgeVariants = cva(
+ "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
+ {
+ variants: {
+ variant: {
+ default:
+ "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
+ secondary:
+ "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ destructive:
+ "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
+ outline: "text-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+)
+
+export interface BadgeProps
+ extends React.HTMLAttributes,
+ VariantProps {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+ return (
+
+ )
+}
+
+export { Badge, badgeVariants }
diff --git a/apps/tonconnect-demo/src/components/ui/button.tsx b/apps/tonconnect-demo/src/components/ui/button.tsx
new file mode 100644
index 000000000..5673bc459
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/button.tsx
@@ -0,0 +1,57 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-auto disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
+ {
+ variants: {
+ variant: {
+ default:
+ "bg-primary text-primary-foreground shadow hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
+ outline:
+ "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-9 px-4 py-2",
+ sm: "h-8 rounded-md px-3 text-xs",
+ lg: "h-10 rounded-md px-8",
+ icon: "h-9 w-9",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button"
+ return (
+
+ )
+ }
+)
+Button.displayName = "Button"
+
+export { Button, buttonVariants }
diff --git a/apps/tonconnect-demo/src/components/ui/card.tsx b/apps/tonconnect-demo/src/components/ui/card.tsx
new file mode 100644
index 000000000..6a9716640
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/card.tsx
@@ -0,0 +1,76 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+Card.displayName = "Card"
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardHeader.displayName = "CardHeader"
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardTitle.displayName = "CardTitle"
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardDescription.displayName = "CardDescription"
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardContent.displayName = "CardContent"
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardFooter.displayName = "CardFooter"
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/apps/tonconnect-demo/src/components/ui/checkbox.tsx b/apps/tonconnect-demo/src/components/ui/checkbox.tsx
new file mode 100644
index 000000000..90b71e413
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/checkbox.tsx
@@ -0,0 +1,28 @@
+import * as React from "react"
+import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
+import { Check } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const Checkbox = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+
+
+))
+Checkbox.displayName = CheckboxPrimitive.Root.displayName
+
+export { Checkbox }
diff --git a/apps/tonconnect-demo/src/components/ui/collapsible.tsx b/apps/tonconnect-demo/src/components/ui/collapsible.tsx
new file mode 100644
index 000000000..a23e7a281
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/collapsible.tsx
@@ -0,0 +1,9 @@
+import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
+
+const Collapsible = CollapsiblePrimitive.Root
+
+const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
+
+const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
+
+export { Collapsible, CollapsibleTrigger, CollapsibleContent }
diff --git a/apps/tonconnect-demo/src/components/ui/dialog.tsx b/apps/tonconnect-demo/src/components/ui/dialog.tsx
new file mode 100644
index 000000000..df80f9d32
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/dialog.tsx
@@ -0,0 +1,119 @@
+import * as React from "react"
+import * as DialogPrimitive from "@radix-ui/react-dialog"
+import { X } from "lucide-react"
+import { cn } from "@/lib/utils"
+
+const Dialog = DialogPrimitive.Root
+
+const DialogTrigger = DialogPrimitive.Trigger
+
+const DialogPortal = DialogPrimitive.Portal
+
+const DialogClose = DialogPrimitive.Close
+
+const DialogOverlay = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
+
+const DialogContent = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+ Close
+
+
+
+))
+DialogContent.displayName = DialogPrimitive.Content.displayName
+
+const DialogHeader = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DialogHeader.displayName = "DialogHeader"
+
+const DialogFooter = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DialogFooter.displayName = "DialogFooter"
+
+const DialogTitle = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogTitle.displayName = DialogPrimitive.Title.displayName
+
+const DialogDescription = React.forwardRef<
+ React.ComponentRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogDescription.displayName = DialogPrimitive.Description.displayName
+
+export {
+ Dialog,
+ DialogPortal,
+ DialogOverlay,
+ DialogClose,
+ DialogTrigger,
+ DialogContent,
+ DialogHeader,
+ DialogFooter,
+ DialogTitle,
+ DialogDescription,
+}
diff --git a/apps/tonconnect-demo/src/components/ui/dropdown-menu.tsx b/apps/tonconnect-demo/src/components/ui/dropdown-menu.tsx
new file mode 100644
index 000000000..20bb7956c
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/dropdown-menu.tsx
@@ -0,0 +1,201 @@
+"use client"
+
+import * as React from "react"
+import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
+import { ChevronRight, Check, Circle } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const DropdownMenu = DropdownMenuPrimitive.Root
+
+const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
+
+const DropdownMenuGroup = DropdownMenuPrimitive.Group
+
+const DropdownMenuPortal = DropdownMenuPrimitive.Portal
+
+const DropdownMenuSub = DropdownMenuPrimitive.Sub
+
+const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
+
+const DropdownMenuSubTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, children, ...props }, ref) => (
+
+ {children}
+
+
+))
+DropdownMenuSubTrigger.displayName =
+ DropdownMenuPrimitive.SubTrigger.displayName
+
+const DropdownMenuSubContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSubContent.displayName =
+ DropdownMenuPrimitive.SubContent.displayName
+
+const DropdownMenuContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+
+
+))
+DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
+
+const DropdownMenuItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+ svg]:size-4 [&>svg]:shrink-0",
+ inset && "pl-8",
+ className
+ )}
+ {...props}
+ />
+))
+DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
+
+const DropdownMenuCheckboxItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, checked, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+DropdownMenuCheckboxItem.displayName =
+ DropdownMenuPrimitive.CheckboxItem.displayName
+
+const DropdownMenuRadioItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
+
+const DropdownMenuLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
+
+const DropdownMenuSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
+
+const DropdownMenuShortcut = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => {
+ return (
+
+ )
+}
+DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
+
+export {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuGroup,
+ DropdownMenuPortal,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuRadioGroup,
+}
diff --git a/apps/tonconnect-demo/src/components/ui/input.tsx b/apps/tonconnect-demo/src/components/ui/input.tsx
new file mode 100644
index 000000000..d5431d669
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/input.tsx
@@ -0,0 +1,24 @@
+import * as React from 'react';
+
+import { cn } from '@/lib/utils';
+
+export interface InputProps extends React.InputHTMLAttributes {}
+
+const Input = React.forwardRef(
+ ({ className, type, ...props }, ref) => {
+ return (
+
+ );
+ }
+);
+Input.displayName = 'Input';
+
+export { Input };
diff --git a/apps/tonconnect-demo/src/components/ui/label.tsx b/apps/tonconnect-demo/src/components/ui/label.tsx
new file mode 100644
index 000000000..683faa793
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/label.tsx
@@ -0,0 +1,24 @@
+import * as React from "react"
+import * as LabelPrimitive from "@radix-ui/react-label"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const labelVariants = cva(
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
+)
+
+const Label = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef &
+ VariantProps
+>(({ className, ...props }, ref) => (
+
+))
+Label.displayName = LabelPrimitive.Root.displayName
+
+export { Label }
diff --git a/apps/tonconnect-demo/src/components/ui/scroll-area.tsx b/apps/tonconnect-demo/src/components/ui/scroll-area.tsx
new file mode 100644
index 000000000..cf253cf17
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/scroll-area.tsx
@@ -0,0 +1,46 @@
+import * as React from "react"
+import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
+
+import { cn } from "@/lib/utils"
+
+const ScrollArea = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+ {children}
+
+
+
+
+))
+ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
+
+const ScrollBar = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, orientation = "vertical", ...props }, ref) => (
+
+
+
+))
+ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
+
+export { ScrollArea, ScrollBar }
diff --git a/apps/tonconnect-demo/src/components/ui/select.tsx b/apps/tonconnect-demo/src/components/ui/select.tsx
new file mode 100644
index 000000000..2ca1df8d1
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/select.tsx
@@ -0,0 +1,157 @@
+import * as React from "react"
+import * as SelectPrimitive from "@radix-ui/react-select"
+import { Check, ChevronDown, ChevronUp } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const Select = SelectPrimitive.Root
+
+const SelectGroup = SelectPrimitive.Group
+
+const SelectValue = SelectPrimitive.Value
+
+const SelectTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+ span]:line-clamp-1",
+ className
+ )}
+ {...props}
+ >
+ {children}
+
+
+
+
+))
+SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
+
+const SelectScrollUpButton = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+))
+SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
+
+const SelectScrollDownButton = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+))
+SelectScrollDownButton.displayName =
+ SelectPrimitive.ScrollDownButton.displayName
+
+const SelectContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, position = "popper", ...props }, ref) => (
+
+
+
+
+ {children}
+
+
+
+
+))
+SelectContent.displayName = SelectPrimitive.Content.displayName
+
+const SelectLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+SelectLabel.displayName = SelectPrimitive.Label.displayName
+
+const SelectItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+SelectItem.displayName = SelectPrimitive.Item.displayName
+
+const SelectSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+SelectSeparator.displayName = SelectPrimitive.Separator.displayName
+
+export {
+ Select,
+ SelectGroup,
+ SelectValue,
+ SelectTrigger,
+ SelectContent,
+ SelectLabel,
+ SelectItem,
+ SelectSeparator,
+ SelectScrollUpButton,
+ SelectScrollDownButton,
+}
diff --git a/apps/tonconnect-demo/src/components/ui/sonner.tsx b/apps/tonconnect-demo/src/components/ui/sonner.tsx
new file mode 100644
index 000000000..4d4376106
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/sonner.tsx
@@ -0,0 +1,40 @@
+import { Toaster as Sonner } from "sonner"
+import { useEffect, useState } from "react"
+
+type ToasterProps = React.ComponentProps
+
+const Toaster = ({ ...props }: ToasterProps) => {
+ const [theme, setTheme] = useState<"light" | "dark">("light")
+
+ useEffect(() => {
+ const updateTheme = () => {
+ setTheme(document.documentElement.classList.contains("dark") ? "dark" : "light")
+ }
+ updateTheme()
+
+ const observer = new MutationObserver(updateTheme)
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] })
+ return () => observer.disconnect()
+ }, [])
+
+ return (
+
+ )
+}
+
+export { Toaster }
diff --git a/apps/tonconnect-demo/src/components/ui/switch.tsx b/apps/tonconnect-demo/src/components/ui/switch.tsx
new file mode 100644
index 000000000..5f4117f0f
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/switch.tsx
@@ -0,0 +1,29 @@
+"use client"
+
+import * as React from "react"
+import * as SwitchPrimitives from "@radix-ui/react-switch"
+
+import { cn } from "@/lib/utils"
+
+const Switch = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+))
+Switch.displayName = SwitchPrimitives.Root.displayName
+
+export { Switch }
diff --git a/apps/tonconnect-demo/src/components/ui/tabs.tsx b/apps/tonconnect-demo/src/components/ui/tabs.tsx
new file mode 100644
index 000000000..764f0b7f9
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/tabs.tsx
@@ -0,0 +1,53 @@
+import * as React from 'react';
+import * as TabsPrimitive from '@radix-ui/react-tabs';
+
+import { cn } from '@/lib/utils';
+
+const Tabs = TabsPrimitive.Root;
+
+const TabsList = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsList.displayName = TabsPrimitive.List.displayName;
+
+const TabsTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
+
+const TabsContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsContent.displayName = TabsPrimitive.Content.displayName;
+
+export { Tabs, TabsList, TabsTrigger, TabsContent };
diff --git a/apps/tonconnect-demo/src/components/ui/textarea.tsx b/apps/tonconnect-demo/src/components/ui/textarea.tsx
new file mode 100644
index 000000000..167657add
--- /dev/null
+++ b/apps/tonconnect-demo/src/components/ui/textarea.tsx
@@ -0,0 +1,23 @@
+import * as React from 'react';
+
+import { cn } from '@/lib/utils';
+
+export interface TextareaProps extends React.TextareaHTMLAttributes {}
+
+const Textarea = React.forwardRef(
+ ({ className, ...props }, ref) => {
+ return (
+
+ );
+ }
+);
+Textarea.displayName = 'Textarea';
+
+export { Textarea };
diff --git a/apps/tonconnect-demo/src/context/DevToolsContext.tsx b/apps/tonconnect-demo/src/context/DevToolsContext.tsx
new file mode 100644
index 000000000..2684bbced
--- /dev/null
+++ b/apps/tonconnect-demo/src/context/DevToolsContext.tsx
@@ -0,0 +1,24 @@
+import { createContext, useContext } from "react"
+import type { ReactNode } from "react"
+import { useDevTools } from "@/hooks/useDevTools"
+
+type DevToolsContextType = ReturnType
+
+const DevToolsContext = createContext(null)
+
+export function DevToolsProvider({ children }: { children: ReactNode }) {
+ const devTools = useDevTools()
+ return (
+
+ {children}
+
+ )
+}
+
+export function useDevToolsContext() {
+ const context = useContext(DevToolsContext)
+ if (!context) {
+ throw new Error("useDevToolsContext must be used within DevToolsProvider")
+ }
+ return context
+}
diff --git a/apps/tonconnect-demo/src/context/SettingsContext.tsx b/apps/tonconnect-demo/src/context/SettingsContext.tsx
new file mode 100644
index 000000000..889cdb7f1
--- /dev/null
+++ b/apps/tonconnect-demo/src/context/SettingsContext.tsx
@@ -0,0 +1,24 @@
+import { createContext, useContext } from "react"
+import type { ReactNode } from "react"
+import { useSettings } from "@/hooks/useSettings"
+
+type SettingsContextType = ReturnType
+
+const SettingsContext = createContext(null)
+
+export function SettingsProvider({ children }: { children: ReactNode }) {
+ const settings = useSettings()
+ return (
+
+ {children}
+
+ )
+}
+
+export function useSettingsContext() {
+ const context = useContext(SettingsContext)
+ if (!context) {
+ throw new Error("useSettingsContext must be used within SettingsProvider")
+ }
+ return context
+}
diff --git a/apps/tonconnect-demo/src/data/field-info.ts b/apps/tonconnect-demo/src/data/field-info.ts
new file mode 100644
index 000000000..45ee18980
--- /dev/null
+++ b/apps/tonconnect-demo/src/data/field-info.ts
@@ -0,0 +1,71 @@
+import YAML from 'yaml'
+
+export interface FieldInfo {
+ id: string
+ name: string
+ summary: string
+ content: string
+ links?: { title: string; url: string }[]
+}
+
+// Vite glob import - load all markdown files at build time
+const transactionDocs = import.meta.glob('../docs/fields/transaction/*.md', {
+ query: '?raw',
+ import: 'default',
+ eager: true
+}) as Record
+
+const signDataDocs = import.meta.glob('../docs/fields/sign-data/*.md', {
+ query: '?raw',
+ import: 'default',
+ eager: true
+}) as Record
+
+const connectDocs = import.meta.glob('../docs/fields/connect/*.md', {
+ query: '?raw',
+ import: 'default',
+ eager: true
+}) as Record
+
+const settingsDocs = import.meta.glob('../docs/fields/settings/*.md', {
+ query: '?raw',
+ import: 'default',
+ eager: true
+}) as Record
+
+// Section-level documentation
+const sectionDocs = import.meta.glob('../docs/sections/*.md', {
+ query: '?raw',
+ import: 'default',
+ eager: true
+}) as Record
+
+function parseMarkdownWithFrontmatter(content: string): FieldInfo {
+ const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/)
+ if (!match) throw new Error('Invalid frontmatter in markdown file')
+
+ const meta = YAML.parse(match[1])
+ return {
+ id: meta.id,
+ name: meta.name,
+ summary: meta.summary,
+ content: match[2].trim(),
+ links: meta.links || []
+ }
+}
+
+export const transactionFields: FieldInfo[] = Object.values(transactionDocs).map(parseMarkdownWithFrontmatter)
+export const signDataFields: FieldInfo[] = Object.values(signDataDocs).map(parseMarkdownWithFrontmatter)
+export const connectFields: FieldInfo[] = Object.values(connectDocs).map(parseMarkdownWithFrontmatter)
+export const settingsFields: FieldInfo[] = Object.values(settingsDocs).map(parseMarkdownWithFrontmatter)
+export const sections: FieldInfo[] = Object.values(sectionDocs).map(parseMarkdownWithFrontmatter)
+
+const allFields = [...transactionFields, ...signDataFields, ...connectFields, ...settingsFields]
+
+export function getFieldInfo(fieldId: string): FieldInfo | undefined {
+ return allFields.find(f => f.id === fieldId)
+}
+
+export function getSectionInfo(sectionId: string): FieldInfo | undefined {
+ return sections.find(s => s.id === sectionId)
+}
diff --git a/apps/tonconnect-demo/src/docs/fields/connect/backend-challenge.md b/apps/tonconnect-demo/src/docs/fields/connect/backend-challenge.md
new file mode 100644
index 000000000..d764338ca
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/connect/backend-challenge.md
@@ -0,0 +1,31 @@
+---
+id: backendChallenge
+name: Backend Challenge
+summary: Server-generated random data for wallet to sign.
+links:
+ - title: TonProof Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#address-proof-signature-ton_proof
+---
+
+## What it is
+
+Random bytes generated by your backend, sent to wallet as `payload` parameter. Wallet includes this payload in the signed proof.
+
+## Why it matters
+
+- **Proves freshness** — Signature was created for this specific request
+- **Prevents replay** — Can't reuse old proofs, each challenge is unique
+- **Time-bounded** — Expired challenges rejected (typically 15 min TTL)
+
+## Requirements
+
+| Requirement | Why |
+|-------------|-----|
+| Cryptographically random | Predictable values can be pre-computed |
+| Unique per request | Prevents replay attacks |
+| Short TTL | Limits window for attacks |
+| Verifiable | Backend must confirm it issued this challenge |
+
+## This demo
+
+Uses JWT to create stateless challenges: random bytes signed into token, SHA256 hash sent as payload. On verification, JWT signature proves the challenge is authentic and not expired.
diff --git a/apps/tonconnect-demo/src/docs/fields/connect/connect-with-proof.md b/apps/tonconnect-demo/src/docs/fields/connect/connect-with-proof.md
new file mode 100644
index 000000000..cafa8adc8
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/connect/connect-with-proof.md
@@ -0,0 +1,29 @@
+---
+id: connectWithProof
+name: Connect with Proof
+summary: Open wallet modal requesting TonProof signature.
+links:
+ - title: Protocol Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md
+---
+
+## What happens
+
+Wallet modal opens with connection + signature request. User approves → wallet signs the challenge from Step 1.
+
+## Key constraint
+
+**Proof can only be requested at connection time.**
+
+Already connected? Disconnect first, then reconnect with proof. Cannot add proof to existing connection.
+
+## What you receive
+
+| Field | Description |
+|-------|-------------|
+| `account.address` | Wallet address (raw format) |
+| `account.publicKey` | Ed25519 public key |
+| `tonProof.proof.timestamp` | When signature was created |
+| `tonProof.proof.domain` | Domain that requested proof |
+| `tonProof.proof.payload` | Your original challenge |
+| `tonProof.proof.signature` | Base64 Ed25519 signature |
\ No newline at end of file
diff --git a/apps/tonconnect-demo/src/docs/fields/connect/payload-token.md b/apps/tonconnect-demo/src/docs/fields/connect/payload-token.md
new file mode 100644
index 000000000..73df601f5
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/connect/payload-token.md
@@ -0,0 +1,38 @@
+---
+id: payloadToken
+name: Payload Token
+summary: Implementation-specific token for stateless challenge verification.
+---
+
+## Purpose
+
+Payload token is this demo's approach to stateless backend verification.
+Your implementation may differ.
+
+## This demo's approach
+
+- JWT containing random bytes + expiration
+- SHA256 hash sent to wallet as challenge
+- On verification: JWT signature proves authenticity
+
+## Token structure
+
+```json
+{
+ "payload": "",
+ "exp": 1234567890
+}
+```
+
+## Alternatives
+
+- Database-stored nonces
+- Redis cache with TTL
+- Session-based storage
+
+## Why JWT?
+
+- Stateless — no database required
+- Self-contained expiration
+- Cryptographically secure
+- Easy to verify authenticity
diff --git a/apps/tonconnect-demo/src/docs/fields/connect/simple-connection.md b/apps/tonconnect-demo/src/docs/fields/connect/simple-connection.md
new file mode 100644
index 000000000..e682f1c38
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/connect/simple-connection.md
@@ -0,0 +1,33 @@
+---
+id: simpleConnection
+name: Simple Connection
+summary: Connect wallet without cryptographic proof of ownership.
+links:
+ - title: TON Connect Overview
+ url: https://docs.ton.org/ecosystem/ton-connect/overview
+---
+
+## Purpose
+
+Simple connection establishes a link to user's wallet and retrieves their address.
+No backend verification required — useful for read-only dApps.
+
+## What you get
+
+- Wallet address (raw format)
+- Public key
+- Network (mainnet/testnet)
+- Wallet metadata (name, version, platform)
+
+## Limitations
+
+- No proof user controls the wallet
+- Address could be spoofed in theory
+- Not suitable for sensitive operations
+
+## When to use
+
+- Display wallet balance
+- Show transaction history
+- Read-only dashboards
+- Non-critical operations
diff --git a/apps/tonconnect-demo/src/docs/fields/connect/tonproof.md b/apps/tonconnect-demo/src/docs/fields/connect/tonproof.md
new file mode 100644
index 000000000..3c1aa3d47
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/connect/tonproof.md
@@ -0,0 +1,37 @@
+---
+id: tonproof
+name: TonProof
+summary: Cryptographic proof of wallet ownership using Ed25519 signature.
+links:
+ - title: TonProof Specification
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#address-proof-signature-ton_proof
+ - title: Demo Backend (Go)
+ url: https://github.com/ton-connect/demo-dapp-backend
+---
+
+## Purpose
+
+TonProof is a cryptographic challenge-response protocol that proves
+user controls the wallet's private key.
+
+## How it works
+
+1. Backend generates random challenge (payload)
+2. Wallet signs: `timestamp || domain || payload`
+3. Backend verifies Ed25519 signature
+
+## Signed message format
+
+```
+message = "ton-proof-item-v2/" ||
+ Address ||
+ AppDomain ||
+ Timestamp ||
+ Payload
+```
+
+## Security
+
+- Timestamp prevents replay (15 min window)
+- Domain binding prevents cross-site reuse
+- Unique payload prevents replay attacks
diff --git a/apps/tonconnect-demo/src/docs/fields/connect/verify-proof.md b/apps/tonconnect-demo/src/docs/fields/connect/verify-proof.md
new file mode 100644
index 000000000..153a4e31d
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/connect/verify-proof.md
@@ -0,0 +1,28 @@
+---
+id: verifyProof
+name: Verify Proof
+summary: Backend cryptographic verification of wallet signature.
+links:
+ - title: TonProof Specification
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#address-proof-signature-ton_proof
+---
+
+## What happens
+
+Frontend sends proof from Step 2 to your backend. Backend verifies the Ed25519 signature and all supporting data.
+
+## What to verify
+
+All must pass: public key matches StateInit, address is correct hash, domain is whitelisted, timestamp is fresh (15 min), payload matches your challenge, signature is valid.
+
+## Signature formula
+
+```
+message = "ton-proof-item-v2/" || address || domain || timestamp || payload
+fullMessage = 0xffff || "ton-connect" || sha256(message)
+valid = ed25519.verify(signature, sha256(fullMessage), publicKey)
+```
+
+## On success
+
+Issue auth token (JWT, session, cookie) for subsequent API calls. User is now authenticated.
diff --git a/apps/tonconnect-demo/src/docs/fields/settings/manifest-url.md b/apps/tonconnect-demo/src/docs/fields/settings/manifest-url.md
new file mode 100644
index 000000000..fa5d2a322
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/settings/manifest-url.md
@@ -0,0 +1,39 @@
+---
+id: manifestUrl
+name: Manifest URL
+summary: URL to your dApp manifest file for wallet identification
+links:
+ - title: TON Connect Manifest Documentation
+ url: https://docs.ton.org/ecosystem/ton-connect/manifest
+---
+
+The manifest URL points to a JSON file that contains metadata about your dApp. Wallets use this information to identify and display your dApp to users.
+
+## Required Fields
+
+- **url** - Your dApp URL (used as unique identifier)
+- **name** - Human-readable name shown in wallets
+- **iconUrl** - URL to your dApp icon (PNG, 180x180 recommended)
+
+## Optional Fields
+
+- **termsOfUseUrl** - Link to your terms of service
+- **privacyPolicyUrl** - Link to your privacy policy
+
+## Example Manifest
+
+```json
+{
+ "url": "https://your-app.com",
+ "name": "My dApp",
+ "iconUrl": "https://your-app.com/icon-180x180.png",
+ "termsOfUseUrl": "https://your-app.com/terms",
+ "privacyPolicyUrl": "https://your-app.com/privacy"
+}
+```
+
+## Requirements
+
+- The manifest must be publicly accessible via HTTPS
+- The icon should be a square PNG image (180x180 pixels recommended)
+- The URL in the manifest should match your dApp's actual URL
diff --git a/apps/tonconnect-demo/src/docs/fields/sign-data/bytes.md b/apps/tonconnect-demo/src/docs/fields/sign-data/bytes.md
new file mode 100644
index 000000000..4426332a5
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/sign-data/bytes.md
@@ -0,0 +1,14 @@
+---
+id: bytes
+name: Data
+summary: Arbitrary binary data (base64-encoded).
+---
+
+Wallet shows warning — user cannot verify content.
+
+Use only when:
+- Data cannot be represented as text
+- Document hashes, file references
+- User understands what they sign
+
+**Less safe** — prefer text type when possible.
diff --git a/apps/tonconnect-demo/src/docs/fields/sign-data/cell.md b/apps/tonconnect-demo/src/docs/fields/sign-data/cell.md
new file mode 100644
index 000000000..e1fb4ac58
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/sign-data/cell.md
@@ -0,0 +1,20 @@
+---
+id: cell
+name: Cell
+summary: Structured blockchain data (BOC) for signing.
+links:
+ - title: Cell & BoC
+ url: https://docs.ton.org/foundations/serialization/boc
+---
+
+Base64-encoded BOC (Bag of Cells). Requires TL-B schema for wallet to parse and display structure.
+
+## Format
+- Must start with `te6cc...`
+- Must match the specified schema
+- One root cell
+
+If schema is valid — wallet shows parsed structure.
+If schema invalid — wallet shows warning like binary type.
+
+Use for: on-chain contract verification, structured data signing.
diff --git a/apps/tonconnect-demo/src/docs/fields/sign-data/data-type.md b/apps/tonconnect-demo/src/docs/fields/sign-data/data-type.md
new file mode 100644
index 000000000..967bd4ade
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/sign-data/data-type.md
@@ -0,0 +1,44 @@
+---
+id: dataType
+name: Data Type
+summary: Format of data to sign.
+links:
+ - title: Sign Data Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#sign-data
+ - title: Sign Data Guide
+ url: https://docs.tonconsole.com/academy/sign-data
+---
+
+## Purpose
+
+Sign data without sending transaction. Used for additional confirmations after wallet connect.
+
+Wallet uses Ed25519 key (same as for transactions) but grants no fund access.
+
+Use cases:
+- Action confirmation (terms acceptance, critical operations)
+- Vote delegation
+- Data for on-chain contract verification
+
+## Types
+
+**text** — human-readable message
+- Wallet shows text directly to user
+- Safe — user sees exactly what they sign
+- Best for: confirmations, agreements
+
+**binary** — arbitrary bytes (Base64)
+- Wallet shows warning (content not readable)
+- User cannot verify what they sign
+- Best for: document hashes, file references
+
+**cell** — structured blockchain data (BOC + TL-B schema)
+- Wallet parses using schema and displays structure
+- If schema invalid → warning like binary
+- Best for: on-chain contract validation
+
+## Security
+
+- **Timestamp** — prevents replay attacks
+- **Domain binding** — prevents cross-site signature reuse
+- **Address verification** — always verify response address matches expected wallet
diff --git a/apps/tonconnect-demo/src/docs/fields/sign-data/from.md b/apps/tonconnect-demo/src/docs/fields/sign-data/from.md
new file mode 100644
index 000000000..45ec97ddb
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/sign-data/from.md
@@ -0,0 +1,36 @@
+---
+id: signDataFrom
+name: From Address
+summary: Restrict which wallet address can sign.
+links:
+ - title: Sign Data Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#sign-data
+---
+
+## Purpose
+
+Specifies expected signer address. Prevents address substitution attacks
+where user switches to different wallet mid-session.
+
+## Format
+
+Raw TON address format:
+```
+0:abc123...def456
+```
+
+## When to use
+
+- Multi-wallet scenarios
+- After verifying specific wallet ownership
+- When signature must come from known address
+
+## Validation
+
+If specified, wallet must use matching address.
+Request fails if connected wallet doesn't match.
+
+## Security
+
+Always verify `response.address` matches expected address,
+even if you specified `from` parameter — defense in depth.
diff --git a/apps/tonconnect-demo/src/docs/fields/sign-data/network.md b/apps/tonconnect-demo/src/docs/fields/sign-data/network.md
new file mode 100644
index 000000000..eef8727fd
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/sign-data/network.md
@@ -0,0 +1,32 @@
+---
+id: signDataNetwork
+name: Network
+summary: Target blockchain network for signature validation.
+links:
+ - title: Sign Data Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#sign-data
+---
+
+## Purpose
+
+Restricts signing to a specific network (mainnet/testnet).
+Prevents network mismatch attacks where a signature valid on testnet
+could be misused on mainnet.
+
+## Values
+
+| Value | Network |
+|-------|---------|
+| `-239` | Mainnet |
+| `-3` | Testnet |
+
+## When to use
+
+- Always specify when network matters for your use case
+- Required for on-chain signature verification
+- Prevents cross-network replay attacks
+
+## Validation
+
+If specified, wallet must be connected to matching network.
+Wallet will reject if networks don't match.
diff --git a/apps/tonconnect-demo/src/docs/fields/sign-data/schema.md b/apps/tonconnect-demo/src/docs/fields/sign-data/schema.md
new file mode 100644
index 000000000..e58d2ec62
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/sign-data/schema.md
@@ -0,0 +1,32 @@
+---
+id: schema
+name: Schema
+summary: TL-B schema describing cell structure.
+links:
+ - title: TL-B Language
+ url: https://docs.ton.org/languages/tl-b/overview
+---
+
+## Purpose
+
+TL-B schema describes cell structure. Wallet uses it to parse and display data to user.
+
+SDK validates that schema is non-empty string, but does NOT validate TL-B syntax.
+
+## Format
+
+```
+TypeName#Selector field:Type = ResultType;
+```
+
+Examples:
+- `message#_ text:string = Message;`
+- `transfer#0f8a7ea5 amount:Coins dest:MsgAddress = Transfer;`
+
+## If schema is invalid
+
+Wallet shows "Unknown content" warning (like binary type). User can still sign, but won't see parsed data.
+
+## Verification
+
+Schema is hashed (CRC-32) during signing. Any change to schema string breaks signature verification.
diff --git a/apps/tonconnect-demo/src/docs/fields/sign-data/text.md b/apps/tonconnect-demo/src/docs/fields/sign-data/text.md
new file mode 100644
index 000000000..18bac9f8e
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/sign-data/text.md
@@ -0,0 +1,13 @@
+---
+id: text
+name: Text
+summary: Human-readable text for signing.
+---
+
+Wallet displays this text directly to user before signing. User sees exactly what they sign.
+
+**Safest option** — recommended for most use cases.
+
+Use for:
+- Action confirmations
+- Terms acceptance
diff --git a/apps/tonconnect-demo/src/docs/fields/transaction/address.md b/apps/tonconnect-demo/src/docs/fields/transaction/address.md
new file mode 100644
index 000000000..1897e5dbc
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/transaction/address.md
@@ -0,0 +1,43 @@
+---
+id: address
+name: Address
+summary: Recipient address in TON format.
+links:
+ - title: TON Addresses
+ url: https://docs.ton.org/foundations/addresses/formats
+---
+
+## Format
+
+Only **user-friendly** format accepted (Base64 with checksum).
+
+Raw format (`0:abc...`) is valid for `from` field, but **not for message addresses**.
+
+## Prefixes
+
+| Prefix | Type | Network |
+|--------|------|---------|
+| `EQ` | bounceable | mainnet |
+| `UQ` | non-bounceable | mainnet |
+| `kQ` | bounceable | testnet |
+| `0Q` | non-bounceable | testnet |
+
+Masterchain: `Ef`, `Uf`, `kf`, `0f` — only for system contracts.
+
+## Validation
+
+SDK checks:
+- **Checksum (CRC16)** — typo in any character fails validation
+- **Workchain** — only 0 or -1
+
+SDK does **not** verify testnet/mainnet match with `network` field — wallet handles this.
+
+## Bounceable vs Non-bounceable
+
+**Bounceable (EQ, kQ):**
+- Contract doesn't exist → funds bounce back (minus gas)
+- Use for: existing contracts
+
+**Non-bounceable (UQ, 0Q):**
+- Contract doesn't exist → account created, funds stay
+- Use for: new accounts, exchange deposits
diff --git a/apps/tonconnect-demo/src/docs/fields/transaction/amount.md b/apps/tonconnect-demo/src/docs/fields/transaction/amount.md
new file mode 100644
index 000000000..d81ccb23d
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/transaction/amount.md
@@ -0,0 +1,38 @@
+---
+id: amount
+name: Amount
+summary: Transfer amount in nanotons.
+links:
+ - title: Transaction Fees
+ url: https://docs.ton.org/contract-dev/gas
+---
+
+## Conversion
+
+- 1 TON = 1,000,000,000 nano (10^9)
+- 0.1 TON = 100,000,000 nano
+- 0.001 TON = 1,000,000 nano
+
+## Format
+
+String with digits only (not a number!). This avoids JavaScript precision issues for large values.
+
+```ts
+// Correct
+amount: "1000000000"
+
+// Wrong
+amount: 1000000000 // number
+amount: "1.5" // decimal
+amount: "1e9" // scientific
+```
+
+## What gets deducted
+
+Each message has its own `amount` — TON attached to that message. Wallet deducts **sum of all amounts + wallet contract fee**.
+
+Note: recipient may receive less than `amount` — part can be consumed by recipient contract execution or forwarded further.
+
+## Zero amount
+
+Valid for contract calls without TON transfer. Wallet contract fee still applies.
diff --git a/apps/tonconnect-demo/src/docs/fields/transaction/from.md b/apps/tonconnect-demo/src/docs/fields/transaction/from.md
new file mode 100644
index 000000000..8d9a8c615
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/transaction/from.md
@@ -0,0 +1,23 @@
+---
+id: from
+name: From
+summary: Sender address. Rarely needed.
+---
+
+## Default behavior
+
+If not specified, uses the connected wallet's address. This is what you want in 99% of cases.
+
+## When to specify
+
+Reserved for advanced scenarios:
+- Wallets managing multiple accounts internally
+- Future multi-wallet connections
+
+## In practice
+
+Most DApps don't use this field. If you specify an address different from the connected wallet, the wallet will likely reject the request.
+
+## Format
+
+Raw: `0:abc123...` or user-friendly: `EQBxxx...`
diff --git a/apps/tonconnect-demo/src/docs/fields/transaction/messages.md b/apps/tonconnect-demo/src/docs/fields/transaction/messages.md
new file mode 100644
index 000000000..8a25ecc5b
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/transaction/messages.md
@@ -0,0 +1,36 @@
+---
+id: messages
+name: Messages
+summary: Array of outgoing messages. Min 1, max depends on wallet.
+links:
+ - title: Wallet Contracts
+ url: https://docs.ton.org/standard/wallets/comparison
+ - title: Transaction Fees
+ url: https://docs.ton.org/contract-dev/gas
+---
+
+## Limits
+
+**Minimum:** 1 message (required)
+
+**Maximum:** returned by wallet at connection via `maxMessages`:
+- Most wallets: **4 messages**
+- Modern wallets: **up to 255**
+- Some wallets/hardware devices: **1 message**
+
+Always check actual value from connection — hardware devices may have stricter limits than their contract supports.
+
+## Atomicity
+
+Wallet should ensure all messages are sent or none. Messages are processed sequentially (1 → 2 → 3...).
+
+If wallet doesn't verify gas beforehand, **later messages may not be sent** — no rollback for earlier ones.
+
+## Use cases
+
+- **DApp fee** — main action + service fee in one request
+- **Batch transfers** — send to multiple recipients in one transaction
+
+## Filtering wallets
+
+If your DApp requires multiple messages, you can filter out unsupported wallets at connection time using `walletsRequiredFeatures` option.
diff --git a/apps/tonconnect-demo/src/docs/fields/transaction/network.md b/apps/tonconnect-demo/src/docs/fields/transaction/network.md
new file mode 100644
index 000000000..23a79aed6
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/transaction/network.md
@@ -0,0 +1,38 @@
+---
+id: network
+name: Network
+summary: TON workchain ID where the transaction should be sent.
+links:
+ - title: TonConnect Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md
+---
+
+## Values
+
+- `-239` — mainnet
+- `-3` — testnet
+
+These are TON workchain IDs (not chain IDs like in Ethereum).
+
+## How validation works
+
+**SDK level:**
+- Compares with wallet's connected network
+- Throws `WalletWrongNetworkError` on mismatch
+
+**Wallet level:**
+- Must show alert on mismatch
+- Must NOT allow sending to wrong network
+
+## If not specified
+
+Falls back to wallet's current network. The official spec explicitly states this is **unsafe** — always set the network explicitly.
+
+## Setting at connection time
+
+```ts
+// Enforce network before connecting
+tonConnectUI.setConnectionNetwork(CHAIN.MAINNET)
+```
+
+If wallet connects with different network → connection rejected.
diff --git a/apps/tonconnect-demo/src/docs/fields/transaction/payload.md b/apps/tonconnect-demo/src/docs/fields/transaction/payload.md
new file mode 100644
index 000000000..74766d846
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/transaction/payload.md
@@ -0,0 +1,28 @@
+---
+id: payload
+name: Payload
+summary: Message body sent to recipient contract.
+links:
+ - title: Cell & BoC
+ url: https://docs.ton.org/foundations/serialization/boc
+---
+
+## Purpose
+
+Payload is Base64-encoded BOC (Bag of Cells) — message body delivered to recipient contract. Contract parses it and executes logic based on content.
+
+First 32 bits are typically **op code** — tells contract what operation to perform. Rest is operation-specific data.
+
+Without payload, contract receives empty message (just TON transfer).
+
+## Validation
+
+**SDK level:**
+- Must be valid Base64
+- Must start with `te6cc...` (BOC signature)
+- Error: `"Invalid 'payload' in message at index N"`
+
+**Contract level:**
+- Parses cell structure
+- Validates op code and parameters
+- Can reject with exit code if malformed
diff --git a/apps/tonconnect-demo/src/docs/fields/transaction/state-init.md b/apps/tonconnect-demo/src/docs/fields/transaction/state-init.md
new file mode 100644
index 000000000..13611e754
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/transaction/state-init.md
@@ -0,0 +1,34 @@
+---
+id: stateInit
+name: State Init
+summary: Contract initialization for deployment.
+links:
+ - title: Contract Deployment
+ url: https://docs.ton.org/foundations/status
+---
+
+## Purpose
+
+StateInit deploys new contract to the blockchain. Contains:
+- **code** — contract bytecode
+- **data** — initial state
+
+Contract address is derived from code + data. Same code + data = same address.
+
+## Validation
+
+**SDK level:**
+- Must be valid Base64, start with `te6cc...`
+- Error: `"Invalid 'stateInit' in message at index N"`
+
+**Wallet level:**
+- No specific requirements in TonConnect spec
+- Wallet may or may not show deployment warning (implementation-dependent)
+- Does NOT check if contract already exists
+
+**Blockchain level:**
+- If contract already deployed → transaction fails, gas consumed
+
+## When to use
+
+Only for new contract deployment. Not needed for regular transfers.
diff --git a/apps/tonconnect-demo/src/docs/fields/transaction/valid-until.md b/apps/tonconnect-demo/src/docs/fields/transaction/valid-until.md
new file mode 100644
index 000000000..c9dffd4d5
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/fields/transaction/valid-until.md
@@ -0,0 +1,45 @@
+---
+id: validUntil
+name: Valid Until
+summary: Unix timestamp (seconds) — deadline after which the transaction will be rejected.
+links:
+ - title: TonConnect Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md
+ - title: Wallet Contracts
+ url: https://docs.ton.org/standard/wallets/comparison
+---
+
+## How it works
+
+**Wallet app level:**
+- Shows countdown until expiration
+- May reject if expired before user confirmation
+- Can override this value with a smaller one for security
+
+**Blockchain level (smart contract):**
+- Wallet v2+ checks `now() <= valid_until`
+- If expired → **exit code 35**
+- Protection against replay attacks together with seqno
+
+## Recommended values
+
+**5 minutes** is the standard.
+
+- Shorter — time-sensitive conditions (DEX swaps, limited offers)
+- Longer — user needs time to review complex transactions
+
+**Note:** This only affects acceptance of the first external message. Once accepted, all internal messages execute regardless of this value.
+
+## Technical details
+
+- Type: `number` (Unix seconds, not ms!)
+- Required field
+- SDK warns if > 5 minutes
+
+```ts
+// Correct
+validUntil: Math.floor(Date.now() / 1000) + 300
+
+// Wrong (milliseconds!)
+validUntil: Date.now() + 300000
+```
diff --git a/apps/tonconnect-demo/src/docs/sections/connect.md b/apps/tonconnect-demo/src/docs/sections/connect.md
new file mode 100644
index 000000000..c00ea8841
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/sections/connect.md
@@ -0,0 +1,111 @@
+---
+id: connect
+name: Wallet Connection
+summary: Connect wallets with optional TonProof for cryptographic ownership verification.
+links:
+ - title: TonProof Specification
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#address-proof-signature-ton_proof
+ - title: Protocol Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md
+ - title: Demo Backend (Go)
+ url: https://github.com/ton-connect/demo-dapp-backend
+---
+
+## When to Use What
+
+**Quick decision:** Does your backend need to trust that the user owns this wallet?
+
+- **Yes** → Use TonProof
+- **No** → Use Simple Connection
+
+### Simple Connection
+
+Use when your dApp only accesses publicly available data:
+
+- **On-chain** — balance, transaction history, NFT collections, token holdings
+- **Off-chain** — public profiles, leaderboards, activity stats (data anyone can see by address)
+- **Transactions** — wallet signs each one separately, no pre-verification needed
+
+**Rule:** If anyone can access this data knowing just the wallet address, and you're not granting private data or special permissions — Simple Connection is enough.
+
+### TonProof Connection
+
+Use when your backend must verify wallet ownership:
+
+- **Authentication** — wallet-based login, user sessions
+- **Private data** — personal settings, purchase history, private API endpoints
+- **Permissions** — token-gated content, premium access, whitelist membership
+- **Irreversible actions** — airdrops, rewards, one-time claims
+
+**Rule:** If your backend stores private data for this address, grants special permissions, or performs actions that can't be undone — verify ownership with TonProof first.
+
+## How It Works
+
+### Simple Connection
+
+1. User clicks connect
+2. Wallet approves
+3. You receive: address, public key, network
+
+No backend required. No cryptographic verification.
+
+### TonProof Connection
+
+A challenge-response flow that cryptographically proves wallet ownership:
+
+```
+FRONTEND BACKEND WALLET
+ │ │ │
+ │ 1. Request challenge │ │
+ │──────────────────────>│ │
+ │ │ │
+ │ 2. Return payload │ │
+ │<──────────────────────│ │
+ │ │ │
+ │ 3. Connect with ton_proof request │
+ │──────────────────────────────────────────────>│
+ │ │ │
+ │ 4. User approves, wallet signs proof │
+ │<──────────────────────────────────────────────│
+ │ │ │
+ │ 5. Send proof │ │
+ │──────────────────────>│ │
+ │ │ │
+ │ │ 6. Verify all checks │
+ │ │ (see table below) │
+ │ │ │
+ │ 7. Return auth token │ │
+ │<──────────────────────│ │
+ │ │ │
+```
+
+**What gets signed:** `timestamp + domain + payload`
+
+## Backend Verification
+
+All 6 checks must pass:
+
+| Check | What to Verify |
+|-------|----------------|
+| Public key | Matches key extracted from StateInit |
+| Address | Equals hash of StateInit |
+| Domain | In your allowed whitelist |
+| Timestamp | Within 15 minutes of current time |
+| Payload | Matches the challenge you generated |
+| Signature | Valid Ed25519 signature |
+
+## Security
+
+| Protection | How It Works |
+|------------|--------------|
+| Replay prevention | Proof expires after 15 minutes |
+| Domain binding | Signature includes requesting domain |
+| Challenge uniqueness | Each payload used only once |
+| Address spoofing | StateInit verification ensures address authenticity |
+
+## Error Codes
+
+| Code | Meaning |
+|------|---------|
+| 0 | Unknown error |
+| 400 | Wallet doesn't support TonProof |
diff --git a/apps/tonconnect-demo/src/docs/sections/sign-data.md b/apps/tonconnect-demo/src/docs/sections/sign-data.md
new file mode 100644
index 000000000..b48912d91
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/sections/sign-data.md
@@ -0,0 +1,76 @@
+---
+id: signData
+name: Sign Data
+summary: Sign data cryptographically without sending a blockchain transaction.
+links:
+ - title: Sign Data Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#sign-data
+ - title: Sign Data Guide
+ url: https://docs.tonconsole.com/academy/sign-data
+---
+
+## What it does
+
+Sign Data requests a cryptographic signature from the wallet **without** sending any transaction to the blockchain. The wallet uses its Ed25519 private key to sign, proving ownership of the address.
+
+## Data types
+
+**Text** — Human-readable message
+- Wallet shows the exact text to user
+- Safest option — user sees what they sign
+
+**Binary** — Raw bytes (Base64)
+- Wallet shows a warning
+- User cannot verify content
+- Use for document hashes, file references
+
+**Cell** — Structured blockchain data
+- Requires TL-B schema for parsing
+- Wallet can display structured content
+- Use for on-chain contract verification
+
+## Use cases
+
+- **Authentication** — Prove wallet ownership after connection
+- **Action confirmation** — Terms acceptance, critical operations
+- **Vote delegation** — Sign voting data for on-chain verification
+- **Off-chain messaging** — Signed messages without blockchain fees
+
+## Security features
+
+- **Timestamp** — Prevents replay attacks
+- **Domain binding** — Signature tied to requesting domain
+- **No fund access** — Signing grants no access to wallet funds
+
+## Response structure
+
+Successful response contains:
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `signature` | string | Base64-encoded Ed25519 signature |
+| `address` | string | Signer's wallet address (raw format) |
+| `timestamp` | number | Unix timestamp when signed |
+| `domain` | string | Domain that requested the signature |
+| `payload` | object | Original request payload echoed back |
+
+## Error codes
+
+| Code | Name | When |
+|------|------|------|
+| 0 | UNKNOWN_ERROR | Unexpected wallet error |
+| 1 | BAD_REQUEST | Malformed request payload |
+| 100 | UNKNOWN_APP | Wallet doesn't recognize app |
+| 300 | USER_REJECTS | User declined to sign |
+| 400 | METHOD_NOT_SUPPORTED | Wallet doesn't support SignData |
+
+## Verification
+
+**Client-side verification:**
+- Reconstruct signed message from response
+- Verify Ed25519 signature using wallet's public key
+- Check timestamp freshness (15 min window recommended)
+
+**Server-side verification:**
+- Same as client, plus domain whitelist check
+- Store used timestamps to prevent replay
diff --git a/apps/tonconnect-demo/src/docs/sections/transaction.md b/apps/tonconnect-demo/src/docs/sections/transaction.md
new file mode 100644
index 000000000..0680ff615
--- /dev/null
+++ b/apps/tonconnect-demo/src/docs/sections/transaction.md
@@ -0,0 +1,51 @@
+---
+id: transaction
+name: Transaction Request
+summary: Request the connected wallet to sign and broadcast a transaction to the TON blockchain.
+links:
+ - title: Sending Messages Guide
+ url: https://docs.ton.org/ecosystem/ton-connect/dapp
+ - title: Protocol Spec
+ url: https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#sign-and-send-transaction
+---
+
+## What it does
+
+A Transaction Request instructs the connected wallet to:
+1. Build an external message with your specified parameters
+2. Sign it with the wallet's private key
+3. Broadcast it to the TON blockchain
+
+## Message structure
+
+Each transaction contains one or more **messages**. Each message specifies:
+- **Address** — recipient smart contract or wallet
+- **Amount** — TON to attach (in nanotons)
+- **Payload** — optional data for smart contract calls
+- **State Init** — optional code for contract deployment
+
+## Flow
+
+```
+DApp → Wallet → Blockchain
+ ↓
+ DApp (result BOC)
+```
+
+1. DApp sends transaction request via TonConnect
+2. Wallet shows confirmation UI to user
+3. User approves → wallet signs and broadcasts to blockchain
+4. Wallet returns signed BOC (base64) to DApp
+
+## Result handling
+
+- **Success** — Wallet returns `{ result: "" }`
+- **User rejected** — Error with code `300`
+- **Timeout** — Error with code `400`
+
+## Common use cases
+
+- Transfer TON between wallets
+- Call smart contract methods (Jetton transfers, NFT operations)
+- Deploy new contracts
+- Batch multiple operations in one transaction
diff --git a/apps/tonconnect-demo/src/hooks/useConnect.ts b/apps/tonconnect-demo/src/hooks/useConnect.ts
new file mode 100644
index 000000000..83fa8296f
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useConnect.ts
@@ -0,0 +1,537 @@
+import { useState, useCallback, useRef, useEffect } from "react"
+import { useTonConnectUI, useTonWallet } from "@tonconnect/ui-react"
+import type { Wallet } from "@tonconnect/ui-react"
+import { toast } from "sonner"
+import { useConnectionHistory } from "./useConnectionHistory"
+import type { ConnectionRequest, ConnectionResponse, ConnectionOperation } from "@/types/connection-events"
+
+// Step result for tracking request/response
+export interface StepResult {
+ id: string
+ timestamp: number
+ status: 'success' | 'error'
+ request?: unknown
+ response?: unknown
+ error?: string
+}
+
+// Re-export ConnectionOperation for external use
+export type { ConnectionOperation }
+
+export function useConnect() {
+ const [tonConnectUI] = useTonConnectUI()
+ const wallet = useTonWallet()
+
+ // Connection history (persisted to localStorage)
+ const connectionHistory = useConnectionHistory()
+
+ // Refs
+ const payloadTokenRef = useRef(null)
+ const expectingProofRef = useRef(false)
+ const prevWalletRef = useRef(null)
+ const initializedRef = useRef(false)
+ const lastRequestRef = useRef(null)
+ const disconnectInitiatorRef = useRef<'dapp' | 'wallet'>('wallet')
+
+ // Last full wallet response
+ const [lastWalletResponse, setLastWalletResponse] = useState(null)
+
+ // Loading states
+ const [isGeneratingPayload, setIsGeneratingPayload] = useState(false)
+ const [isConnecting, setIsConnecting] = useState(false)
+ const [isVerifying, setIsVerifying] = useState(false)
+ const [isFetchingAccount, setIsFetchingAccount] = useState(false)
+
+ // Step results
+ const [payloadResult, setPayloadResult] = useState(null)
+ const [verifyResult, setVerifyResult] = useState(null)
+ const [accountResult, setAccountResult] = useState(null)
+
+ // Derived state
+ const isConnected = !!wallet
+ const hasPayload = payloadResult?.status === 'success'
+ const hasProof = wallet?.connectItems?.tonProof && !('error' in wallet.connectItems.tonProof)
+ const isAuthenticated = verifyResult?.status === 'success'
+
+ // Extract wallet snapshot for operation log
+ const extractWalletSnapshot = useCallback((w: Wallet): ConnectionResponse['wallet'] => {
+ const tonProof = w.connectItems?.tonProof
+ const hasProofData = tonProof && !('error' in tonProof)
+ const proofData = hasProofData ? tonProof.proof : null
+
+ return {
+ account: {
+ address: w.account.address,
+ chain: w.account.chain,
+ publicKey: w.account.publicKey,
+ walletStateInit: w.account.walletStateInit
+ },
+ device: {
+ appName: w.device.appName,
+ appVersion: w.device.appVersion,
+ platform: w.device.platform,
+ features: w.device.features || [] // Preserve raw features, format at display time
+ },
+ provider: w.provider as 'http' | 'injected',
+ tonProof: proofData ? {
+ timestamp: proofData.timestamp,
+ domain: proofData.domain.value,
+ payload: proofData.payload,
+ signature: proofData.signature
+ } : undefined
+ }
+ }, [])
+
+ // ========== STEP 1: Generate Payload ==========
+
+ const generatePayload = useCallback(async () => {
+ setIsGeneratingPayload(true)
+
+ const request = {
+ method: 'POST',
+ url: '/api/generate_payload'
+ }
+
+ try {
+ const response = await fetch('/api/generate_payload', { method: 'POST' })
+ const data = await response.json()
+
+ if (!response.ok) {
+ throw new Error(data.error || 'Failed to generate payload')
+ }
+
+ payloadTokenRef.current = data.payloadToken
+
+ setPayloadResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ status: 'success',
+ request,
+ response: data
+ })
+
+ // Set tonProof payload for future connection
+ tonConnectUI.setConnectRequestParameters({
+ state: 'ready',
+ value: { tonProof: data.payloadTokenHash }
+ })
+
+ return data
+ } catch (error) {
+ const message = error instanceof Error ? error.message : 'Failed to generate payload'
+ setPayloadResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ status: 'error',
+ request,
+ error: message
+ })
+ toast.error(message)
+ return null
+ } finally {
+ setIsGeneratingPayload(false)
+ }
+ }, [tonConnectUI])
+
+ // Auto-generate payload on mount
+ useEffect(() => {
+ if (!initializedRef.current) {
+ initializedRef.current = true
+ generatePayload()
+ }
+ }, [generatePayload])
+
+ // Track wallet connection changes
+ useEffect(() => {
+ const prevWallet = prevWalletRef.current
+
+ if (!prevWallet && wallet) {
+ // Connected - log the operation with request/response
+ const rawResponse = {
+ account: wallet.account,
+ device: wallet.device,
+ connectItems: wallet.connectItems,
+ provider: wallet.provider
+ }
+ setLastWalletResponse(rawResponse)
+
+ connectionHistory.addOperation({
+ timestamp: Date.now(),
+ type: 'connect',
+ request: lastRequestRef.current,
+ response: {
+ success: true,
+ wallet: extractWalletSnapshot(wallet)
+ },
+ rawRequest: lastRequestRef.current,
+ rawResponse
+ })
+
+ expectingProofRef.current = false
+ lastRequestRef.current = null
+ setIsConnecting(false)
+ } else if (prevWallet && !wallet) {
+ // Disconnected - log with previous wallet info
+ connectionHistory.addOperation({
+ timestamp: Date.now(),
+ type: 'disconnect',
+ request: null,
+ response: null,
+ initiator: disconnectInitiatorRef.current,
+ previousAddress: prevWallet.account.address,
+ previousWalletName: prevWallet.device.appName
+ })
+
+ disconnectInitiatorRef.current = 'wallet' // Reset to default
+ setLastWalletResponse(null)
+ // Clear TonProof-related state and regenerate payload for next connection
+ setVerifyResult(null)
+ setAccountResult(null)
+ generatePayload()
+ } else if (prevWallet && wallet && prevWallet.account.address !== wallet.account.address) {
+ // Reconnected to different wallet
+ const rawResponse = {
+ account: wallet.account,
+ device: wallet.device,
+ connectItems: wallet.connectItems,
+ provider: wallet.provider
+ }
+ setLastWalletResponse(rawResponse)
+
+ connectionHistory.addOperation({
+ timestamp: Date.now(),
+ type: 'connect',
+ request: lastRequestRef.current,
+ response: {
+ success: true,
+ wallet: extractWalletSnapshot(wallet)
+ },
+ rawRequest: lastRequestRef.current,
+ rawResponse
+ })
+
+ lastRequestRef.current = null
+ // Clear TonProof-related state on reconnect
+ setVerifyResult(null)
+ setAccountResult(null)
+ }
+
+ prevWalletRef.current = wallet
+ }, [wallet, generatePayload, connectionHistory, extractWalletSnapshot])
+
+ // ========== SIMPLE CONNECT ==========
+
+ const connect = useCallback(async () => {
+ if (wallet) {
+ toast.error('Already connected')
+ return
+ }
+
+ setIsConnecting(true)
+
+ // Clear proof expectation for simple connect
+ tonConnectUI.setConnectRequestParameters(null)
+ expectingProofRef.current = false
+
+ // Save request for operation log
+ lastRequestRef.current = {
+ items: ['ton_addr']
+ }
+
+ try {
+ await tonConnectUI.openModal()
+ } catch (error) {
+ setIsConnecting(false)
+ // Log failed connection attempt
+ connectionHistory.addOperation({
+ timestamp: Date.now(),
+ type: 'connect',
+ request: lastRequestRef.current,
+ response: {
+ success: false,
+ error: {
+ code: 0,
+ message: error instanceof Error ? error.message : 'Connection failed'
+ }
+ },
+ rawRequest: lastRequestRef.current
+ })
+ lastRequestRef.current = null
+ toast.error(error instanceof Error ? error.message : 'Connection failed')
+ }
+ }, [tonConnectUI, wallet, connectionHistory])
+
+ // ========== STEP 2: Connect with Proof ==========
+
+ const connectWithProof = useCallback(async () => {
+ if (wallet) {
+ toast.error('Disconnect first')
+ return
+ }
+
+ if (!payloadResult || payloadResult.status !== 'success') {
+ toast.error('Generate payload first')
+ return
+ }
+
+ setIsConnecting(true)
+ expectingProofRef.current = true
+
+ // Ensure payload is set
+ const payloadResponse = payloadResult.response as { payloadTokenHash?: string }
+ if (payloadResponse?.payloadTokenHash) {
+ tonConnectUI.setConnectRequestParameters({
+ state: 'ready',
+ value: { tonProof: payloadResponse.payloadTokenHash }
+ })
+ }
+
+ // Save request for operation log
+ lastRequestRef.current = {
+ items: ['ton_addr', 'ton_proof'],
+ payload: payloadResponse?.payloadTokenHash
+ }
+
+ try {
+ await tonConnectUI.openModal()
+ } catch (error) {
+ setIsConnecting(false)
+ expectingProofRef.current = false
+ // Log failed connection attempt
+ connectionHistory.addOperation({
+ timestamp: Date.now(),
+ type: 'connect',
+ request: lastRequestRef.current,
+ response: {
+ success: false,
+ error: {
+ code: 0,
+ message: error instanceof Error ? error.message : 'Connection failed'
+ }
+ },
+ rawRequest: lastRequestRef.current
+ })
+ lastRequestRef.current = null
+ toast.error(error instanceof Error ? error.message : 'Connection failed')
+ }
+ }, [tonConnectUI, wallet, payloadResult, connectionHistory])
+
+ // ========== DISCONNECT ==========
+
+ const disconnect = useCallback(async () => {
+ if (!wallet) {
+ toast.error('Not connected')
+ return
+ }
+
+ // Mark that dApp initiated the disconnect
+ disconnectInitiatorRef.current = 'dapp'
+
+ try {
+ await tonConnectUI.disconnect()
+ } catch (error) {
+ disconnectInitiatorRef.current = 'wallet' // Reset on error
+ toast.error(error instanceof Error ? error.message : 'Disconnect failed')
+ }
+ }, [tonConnectUI, wallet])
+
+ // ========== STEP 3: Verify Proof ==========
+
+ const verifyProof = useCallback(async () => {
+ if (!wallet) {
+ toast.error('Not connected')
+ return
+ }
+
+ const tonProof = wallet.connectItems?.tonProof
+ if (!tonProof || 'error' in tonProof) {
+ toast.error('No valid proof')
+ return
+ }
+
+ if (!payloadTokenRef.current) {
+ toast.error('No payload token - regenerate payload and reconnect')
+ return
+ }
+
+ setIsVerifying(true)
+ setAccountResult(null)
+
+ const requestBody = {
+ address: wallet.account.address,
+ network: wallet.account.chain,
+ public_key: wallet.account.publicKey,
+ proof: {
+ ...tonProof.proof,
+ state_init: wallet.account.walletStateInit
+ },
+ payloadToken: payloadTokenRef.current
+ }
+
+ const request = {
+ method: 'POST',
+ url: '/api/check_proof',
+ body: requestBody
+ }
+
+ try {
+ const response = await fetch('/api/check_proof', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(requestBody)
+ })
+
+ const data = await response.json()
+
+ // New response format: { valid, checks, token?, error? }
+ if (data.valid) {
+ setVerifyResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ status: 'success',
+ request,
+ response: data
+ })
+ payloadTokenRef.current = null
+ toast.success('Proof verified!')
+ } else {
+ setVerifyResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ status: 'error',
+ request,
+ response: data,
+ error: data.error || 'Verification failed'
+ })
+ toast.error(data.error || 'Verification failed')
+ }
+ } catch (error) {
+ const message = error instanceof Error ? error.message : 'Verification failed'
+ setVerifyResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ status: 'error',
+ request,
+ error: message
+ })
+ toast.error(message)
+ } finally {
+ setIsVerifying(false)
+ }
+ }, [wallet])
+
+ // ========== STEP 4: Get Account Info ==========
+
+ const getAccountInfo = useCallback(async () => {
+ if (!verifyResult || verifyResult.status !== 'success') {
+ toast.error('Verify proof first')
+ return
+ }
+
+ const token = (verifyResult.response as { token?: string })?.token
+ if (!token) {
+ toast.error('No auth token')
+ return
+ }
+
+ setIsFetchingAccount(true)
+
+ const request = {
+ method: 'GET',
+ url: '/api/get_account_info',
+ headers: { Authorization: 'Bearer ' }
+ }
+
+ try {
+ const response = await fetch('/api/get_account_info', {
+ headers: { 'Authorization': `Bearer ${token}` }
+ })
+
+ const data = await response.json()
+
+ if (!response.ok) {
+ throw new Error(data.error || 'Failed to fetch account')
+ }
+
+ setAccountResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ status: 'success',
+ request,
+ response: data
+ })
+
+ toast.success('Account info fetched')
+ } catch (error) {
+ const message = error instanceof Error ? error.message : 'Failed to fetch account'
+ setAccountResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ status: 'error',
+ request,
+ error: message
+ })
+ toast.error(message)
+ } finally {
+ setIsFetchingAccount(false)
+ }
+ }, [verifyResult])
+
+ // ========== RESET ==========
+
+ const resetTonProof = useCallback(() => {
+ setVerifyResult(null)
+ setAccountResult(null)
+ payloadTokenRef.current = null
+ // Regenerate payload
+ generatePayload()
+ }, [generatePayload])
+
+ // Computed flags
+ const canConnect = !wallet && !isConnecting
+ const canDisconnect = !!wallet
+ const canConnectWithProof = !wallet && !isConnecting && hasPayload
+ const canVerify = isConnected && hasProof && !isAuthenticated && !isVerifying
+ const canGetAccount = isAuthenticated && !isFetchingAccount
+
+ return {
+ // Wallet
+ wallet,
+ isConnected,
+ hasProof,
+ isAuthenticated,
+
+ // Connection operations log
+ operations: connectionHistory.operations,
+ clearOperations: connectionHistory.clearAll,
+ deleteOperation: connectionHistory.deleteOperation,
+ lastWalletResponse,
+
+ // Loading states
+ isGeneratingPayload,
+ isConnecting,
+ isVerifying,
+ isFetchingAccount,
+
+ // Actions
+ connect,
+ disconnect,
+ generatePayload,
+ connectWithProof,
+ verifyProof,
+ getAccountInfo,
+ resetTonProof,
+
+ // Step results
+ payloadResult,
+ verifyResult,
+ accountResult,
+
+ // Flags
+ canConnect,
+ canDisconnect,
+ canConnectWithProof,
+ canVerify,
+ canGetAccount
+ }
+}
diff --git a/apps/tonconnect-demo/src/hooks/useConnectionHistory.ts b/apps/tonconnect-demo/src/hooks/useConnectionHistory.ts
new file mode 100644
index 000000000..ca3266c2f
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useConnectionHistory.ts
@@ -0,0 +1,62 @@
+import { useState, useEffect, useCallback } from "react"
+import type { ConnectionOperation } from "@/types/connection-events"
+import { CONNECTION_HISTORY_KEY, MAX_OPERATIONS } from "@/types/connection-events"
+
+function loadFromStorage(): ConnectionOperation[] {
+ try {
+ const data = localStorage.getItem(CONNECTION_HISTORY_KEY)
+ if (data) {
+ return JSON.parse(data)
+ }
+ } catch {
+ // Invalid or missing data
+ }
+ return []
+}
+
+function saveToStorage(operations: ConnectionOperation[]) {
+ try {
+ localStorage.setItem(CONNECTION_HISTORY_KEY, JSON.stringify(operations))
+ } catch {
+ // Storage full - try to trim
+ const trimmed = operations.slice(0, 20)
+ try {
+ localStorage.setItem(CONNECTION_HISTORY_KEY, JSON.stringify(trimmed))
+ } catch {
+ // Give up
+ }
+ }
+}
+
+export function useConnectionHistory() {
+ const [operations, setOperations] = useState(() => loadFromStorage())
+
+ // Persist on change
+ useEffect(() => {
+ saveToStorage(operations)
+ }, [operations])
+
+ // Add operation
+ const addOperation = useCallback((op: Omit) => {
+ const newOp: ConnectionOperation = { ...op, id: crypto.randomUUID() }
+ setOperations(prev => [newOp, ...prev].slice(0, MAX_OPERATIONS))
+ return newOp.id
+ }, [])
+
+ // Delete operation
+ const deleteOperation = useCallback((id: string) => {
+ setOperations(prev => prev.filter(o => o.id !== id))
+ }, [])
+
+ // Clear all
+ const clearAll = useCallback(() => {
+ setOperations([])
+ }, [])
+
+ return {
+ operations,
+ addOperation,
+ deleteOperation,
+ clearAll
+ }
+}
diff --git a/apps/tonconnect-demo/src/hooks/useDevTools.ts b/apps/tonconnect-demo/src/hooks/useDevTools.ts
new file mode 100644
index 000000000..fb14339b0
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useDevTools.ts
@@ -0,0 +1,163 @@
+import { useState, useCallback, useEffect } from 'react'
+
+const STORAGE_KEYS = {
+ QA_MODE: 'devtools:qa-mode',
+ ERUDA: 'devtools:eruda',
+ RPC_LOGS: 'devtools:rpc-logs',
+ DOCS_HIDDEN: 'devtools:docs-hidden',
+ SHOW_DEPRECATED: 'devtools:show-deprecated',
+ SHOW_EXPERIMENTAL: 'devtools:show-experimental',
+ UNLOCKED: 'devtools:unlocked',
+} as const
+
+export function useDevTools() {
+ // DevTools visibility (persisted in localStorage)
+ const [isUnlocked, setIsUnlockedState] = useState(() => {
+ return localStorage.getItem(STORAGE_KEYS.UNLOCKED) === 'true'
+ })
+
+ // QA Mode state (read from localStorage, set triggers reload)
+ const [qaMode] = useState(() => {
+ return localStorage.getItem(STORAGE_KEYS.QA_MODE) === 'true'
+ })
+
+ // Eruda state
+ const [erudaEnabled, setErudaEnabledState] = useState(() => {
+ return localStorage.getItem(STORAGE_KEYS.ERUDA) === 'true'
+ })
+
+ // RPC Logs state
+ const [rpcLogsEnabled, setRpcLogsEnabledState] = useState(() => {
+ return localStorage.getItem(STORAGE_KEYS.RPC_LOGS) === 'true'
+ })
+
+ // Docs hidden state
+ const [docsHidden, setDocsHiddenState] = useState(() => {
+ return localStorage.getItem(STORAGE_KEYS.DOCS_HIDDEN) === 'true'
+ })
+
+ // Show deprecated options state
+ const [showDeprecated, setShowDeprecatedState] = useState(() => {
+ return localStorage.getItem(STORAGE_KEYS.SHOW_DEPRECATED) === 'true'
+ })
+
+ // Show experimental features state
+ const [showExperimental, setShowExperimentalState] = useState(() => {
+ return localStorage.getItem(STORAGE_KEYS.SHOW_EXPERIMENTAL) === 'true'
+ })
+
+ // Unlock DevTools (called from secret tap)
+ const unlockDevTools = useCallback(() => {
+ localStorage.setItem(STORAGE_KEYS.UNLOCKED, 'true')
+ setIsUnlockedState(true)
+ }, [])
+
+ // Lock DevTools (hide the tab)
+ const lockDevTools = useCallback(() => {
+ localStorage.removeItem(STORAGE_KEYS.UNLOCKED)
+ setIsUnlockedState(false)
+ }, [])
+
+ // Set QA Mode (triggers page reload)
+ const setQaMode = useCallback((enabled: boolean) => {
+ if (enabled) {
+ localStorage.setItem(STORAGE_KEYS.QA_MODE, 'true')
+ } else {
+ localStorage.removeItem(STORAGE_KEYS.QA_MODE)
+ }
+ // Reload is required for QA Mode to take effect
+ window.location.reload()
+ }, [])
+
+ // Set Eruda (dynamic load/destroy)
+ const setErudaEnabled = useCallback(async (enabled: boolean) => {
+ if (enabled) {
+ localStorage.setItem(STORAGE_KEYS.ERUDA, 'true')
+ const eruda = await import('eruda')
+ eruda.default.init()
+ } else {
+ localStorage.removeItem(STORAGE_KEYS.ERUDA)
+ const eruda = await import('eruda')
+ eruda.default.destroy()
+ }
+ setErudaEnabledState(enabled)
+ }, [])
+
+ // Set RPC Logs
+ const setRpcLogsEnabled = useCallback((enabled: boolean) => {
+ if (enabled) {
+ localStorage.setItem(STORAGE_KEYS.RPC_LOGS, 'true')
+ } else {
+ localStorage.removeItem(STORAGE_KEYS.RPC_LOGS)
+ }
+ setRpcLogsEnabledState(enabled)
+ }, [])
+
+ // Set Docs Hidden
+ const setDocsHidden = useCallback((hidden: boolean) => {
+ if (hidden) {
+ localStorage.setItem(STORAGE_KEYS.DOCS_HIDDEN, 'true')
+ } else {
+ localStorage.removeItem(STORAGE_KEYS.DOCS_HIDDEN)
+ }
+ setDocsHiddenState(hidden)
+ }, [])
+
+ // Set Show Deprecated
+ const setShowDeprecated = useCallback((enabled: boolean) => {
+ if (enabled) {
+ localStorage.setItem(STORAGE_KEYS.SHOW_DEPRECATED, 'true')
+ } else {
+ localStorage.removeItem(STORAGE_KEYS.SHOW_DEPRECATED)
+ }
+ setShowDeprecatedState(enabled)
+ }, [])
+
+ // Set Show Experimental
+ const setShowExperimental = useCallback((enabled: boolean) => {
+ if (enabled) {
+ localStorage.setItem(STORAGE_KEYS.SHOW_EXPERIMENTAL, 'true')
+ } else {
+ localStorage.removeItem(STORAGE_KEYS.SHOW_EXPERIMENTAL)
+ }
+ setShowExperimentalState(enabled)
+ }, [])
+
+ // Initialize eruda on mount if enabled
+ useEffect(() => {
+ if (erudaEnabled) {
+ import('eruda').then(eruda => eruda.default.init())
+ }
+ }, []) // eslint-disable-line react-hooks/exhaustive-deps
+
+ // Reset all DevTools settings
+ const resetAll = useCallback(() => {
+ localStorage.removeItem(STORAGE_KEYS.QA_MODE)
+ localStorage.removeItem(STORAGE_KEYS.ERUDA)
+ localStorage.removeItem(STORAGE_KEYS.RPC_LOGS)
+ localStorage.removeItem(STORAGE_KEYS.DOCS_HIDDEN)
+ localStorage.removeItem(STORAGE_KEYS.SHOW_DEPRECATED)
+ localStorage.removeItem(STORAGE_KEYS.SHOW_EXPERIMENTAL)
+ localStorage.removeItem(STORAGE_KEYS.UNLOCKED)
+ window.location.reload()
+ }, [])
+
+ return {
+ isUnlocked,
+ unlockDevTools,
+ lockDevTools,
+ qaMode,
+ setQaMode,
+ erudaEnabled,
+ setErudaEnabled,
+ rpcLogsEnabled,
+ setRpcLogsEnabled,
+ docsHidden,
+ setDocsHidden,
+ showDeprecated,
+ setShowDeprecated,
+ showExperimental,
+ setShowExperimental,
+ resetAll,
+ }
+}
diff --git a/apps/tonconnect-demo/src/hooks/useHashTab.ts b/apps/tonconnect-demo/src/hooks/useHashTab.ts
new file mode 100644
index 000000000..cb15486e2
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useHashTab.ts
@@ -0,0 +1,55 @@
+import { useState, useEffect, useCallback } from "react"
+
+/**
+ * Hook for syncing tab state with URL hash.
+ * Enables direct links like /#sign and browser back/forward navigation.
+ *
+ * @param validTabs - Array of valid tab values
+ * @param defaultTab - Default tab when hash is empty or invalid
+ * @returns [currentTab, setTab] tuple
+ */
+export function useHashTab(validTabs: string[], defaultTab: string) {
+ // Read hash synchronously to avoid flicker
+ const getValidTab = useCallback(() => {
+ if (typeof window === "undefined") return defaultTab
+ const hash = window.location.hash.slice(1)
+ return validTabs.includes(hash) ? hash : defaultTab
+ }, [validTabs, defaultTab])
+
+ const [tab, setTabState] = useState(getValidTab)
+
+ // Set initial hash if empty (for clean URLs like /)
+ useEffect(() => {
+ if (!window.location.hash) {
+ window.history.replaceState(null, "", `#${tab}`)
+ }
+ }, []) // eslint-disable-line react-hooks/exhaustive-deps
+
+ // Redirect to default if current tab becomes invalid (e.g., DevTools locked)
+ useEffect(() => {
+ if (!validTabs.includes(tab)) {
+ const newTab = defaultTab
+ setTabState(newTab)
+ window.history.replaceState(null, "", `#${newTab}`)
+ }
+ }, [validTabs, tab, defaultTab])
+
+ // Sync hash → state (back/forward buttons + programmatic changes)
+ useEffect(() => {
+ const onHashChange = () => {
+ const newTab = getValidTab()
+ setTabState(newTab)
+ }
+ window.addEventListener("hashchange", onHashChange)
+ return () => window.removeEventListener("hashchange", onHashChange)
+ }, [getValidTab])
+
+ // Set tab by updating hash (let hashchange listener update state)
+ const setTab = useCallback((newTab: string) => {
+ if (validTabs.includes(newTab)) {
+ window.location.hash = newTab
+ }
+ }, [validTabs])
+
+ return [tab, setTab] as const
+}
diff --git a/apps/tonconnect-demo/src/hooks/useHistory.ts b/apps/tonconnect-demo/src/hooks/useHistory.ts
new file mode 100644
index 000000000..4050c97a2
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useHistory.ts
@@ -0,0 +1,128 @@
+import { useState, useEffect, useCallback } from "react"
+
+const HISTORY_KEY = "tc-demo-history"
+const MAX_ENTRIES_PER_WALLET = 20
+
+export interface HistoryEntry {
+ id: string
+ timestamp: number
+ walletAddress: string
+ network: "mainnet" | "testnet"
+ request: Record
+ requestRaw: string
+ status: "success" | "error" | "confirmed" | "expired"
+ response?: Record
+ boc?: string
+}
+
+interface HistoryStore {
+ entries: Record
+}
+
+function loadFromStorage(): HistoryStore {
+ try {
+ const data = localStorage.getItem(HISTORY_KEY)
+ if (data) {
+ return JSON.parse(data)
+ }
+ } catch {
+ // Invalid data - start fresh
+ }
+ return { entries: {} }
+}
+
+function saveToStorage(store: HistoryStore) {
+ try {
+ localStorage.setItem(HISTORY_KEY, JSON.stringify(store))
+ } catch {
+ // Storage full or unavailable
+ }
+}
+
+export function useHistory() {
+ const [store, setStore] = useState(() => loadFromStorage())
+
+ // Save to localStorage when store changes
+ useEffect(() => {
+ saveToStorage(store)
+ }, [store])
+
+ const addEntry = useCallback((entry: Omit): string => {
+ const id = crypto.randomUUID()
+ const newEntry: HistoryEntry = { ...entry, id }
+
+ setStore(prev => {
+ const wallet = entry.walletAddress
+ const walletEntries = prev.entries[wallet] || []
+
+ // Add new entry at the beginning, limit to MAX_ENTRIES_PER_WALLET
+ const updatedEntries = [newEntry, ...walletEntries].slice(0, MAX_ENTRIES_PER_WALLET)
+
+ return {
+ ...prev,
+ entries: {
+ ...prev.entries,
+ [wallet]: updatedEntries,
+ },
+ }
+ })
+
+ return id
+ }, [])
+
+ const updateEntry = useCallback((id: string, updates: Partial) => {
+ setStore(prev => {
+ const newEntries = { ...prev.entries }
+
+ for (const wallet of Object.keys(newEntries)) {
+ const idx = newEntries[wallet].findIndex(e => e.id === id)
+ if (idx !== -1) {
+ newEntries[wallet] = [...newEntries[wallet]]
+ newEntries[wallet][idx] = { ...newEntries[wallet][idx], ...updates }
+ break
+ }
+ }
+
+ return { ...prev, entries: newEntries }
+ })
+ }, [])
+
+ const getByWallet = useCallback((walletAddress: string): HistoryEntry[] => {
+ return store.entries[walletAddress] || []
+ }, [store.entries])
+
+ const clearWallet = useCallback((walletAddress: string) => {
+ setStore(prev => {
+ const { [walletAddress]: _removed, ...rest } = prev.entries
+ void _removed // intentionally unused
+ return { entries: rest }
+ })
+ }, [])
+
+ const deleteEntry = useCallback((id: string) => {
+ setStore(prev => {
+ const newEntries = { ...prev.entries }
+ for (const wallet of Object.keys(newEntries)) {
+ const filtered = newEntries[wallet].filter(e => e.id !== id)
+ if (filtered.length !== newEntries[wallet].length) {
+ newEntries[wallet] = filtered
+ break
+ }
+ }
+ return { entries: newEntries }
+ })
+ }, [])
+
+ const clearAll = useCallback(() => {
+ setStore({ entries: {} })
+ }, [])
+
+ return {
+ addEntry,
+ updateEntry,
+ getByWallet,
+ clearWallet,
+ deleteEntry,
+ clearAll,
+ }
+}
diff --git a/apps/tonconnect-demo/src/hooks/useSdkLogs.ts b/apps/tonconnect-demo/src/hooks/useSdkLogs.ts
new file mode 100644
index 000000000..94f952745
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useSdkLogs.ts
@@ -0,0 +1,130 @@
+import { useState, useEffect, useCallback, useRef } from 'react'
+
+export type RpcLogStatus = 'pending' | 'success' | 'error'
+export type RpcProvider = 'bridge' | 'injected' | 'unknown'
+
+export interface RpcLogEntry {
+ id: string
+ method: string
+ provider: RpcProvider
+ requestTimestamp: number
+ request: object
+ response?: object
+ responseTimestamp?: number
+ status: RpcLogStatus
+}
+
+// SDK log format: console.debug('[TON_CONNECT_SDK]', message, data)
+const SDK_PREFIX = '[TON_CONNECT_SDK]'
+const REQUEST_PATTERN = /Send ([\w-]+) request:/i // space before "request"
+const RESPONSE_PATTERN = /Wallet message received:/i
+
+/**
+ * Hook for intercepting SDK console.debug logs and collecting RPC request/response pairs.
+ * Only active when enabled.
+ */
+export function useSdkLogs(enabled: boolean) {
+ const [logs, setLogs] = useState([])
+ const originalDebugRef = useRef(null)
+
+ // Use ref for handler to avoid re-creating interceptor on every render
+ const handleSdkLogRef = useRef<(message: string, data: unknown) => void>(() => {})
+
+ // Parse provider from log message
+ const parseProvider = useCallback((message: string): RpcProvider => {
+ const lower = message.toLowerCase()
+ if (lower.includes('http-bridge')) return 'bridge'
+ if (lower.includes('injected')) return 'injected'
+ return 'unknown'
+ }, [])
+
+ // Extract method name from request object
+ const extractMethod = useCallback((request: Record): string => {
+ if (typeof request.method === 'string') return request.method
+ return 'unknown'
+ }, [])
+
+ // Update handler ref when dependencies change
+ useEffect(() => {
+ handleSdkLogRef.current = (message: string, data: unknown) => {
+ const timestamp = Date.now()
+
+ // Check for request
+ const requestMatch = message.match(REQUEST_PATTERN)
+ if (requestMatch && data && typeof data === 'object') {
+ const requestData = data as Record
+ const id = String(requestData.id ?? timestamp)
+ const method = extractMethod(requestData)
+ const provider = parseProvider(message)
+
+ setLogs(prev => [{
+ id,
+ method,
+ provider,
+ requestTimestamp: timestamp,
+ request: requestData,
+ status: 'pending',
+ }, ...prev])
+ return
+ }
+
+ // Check for response
+ if (RESPONSE_PATTERN.test(message) && data && typeof data === 'object') {
+ const responseData = data as Record
+ const responseId = String(responseData.id ?? '')
+
+ if (!responseId) return
+
+ setLogs(prev => prev.map(entry => {
+ if (entry.id === responseId && entry.status === 'pending') {
+ const hasError = 'error' in responseData
+ return {
+ ...entry,
+ response: responseData,
+ responseTimestamp: timestamp,
+ status: hasError ? 'error' : 'success',
+ }
+ }
+ return entry
+ }))
+ }
+ }
+ }, [extractMethod, parseProvider])
+
+ // Setup console.debug interception - only depends on enabled
+ useEffect(() => {
+ if (!enabled) return
+
+ // Store original
+ originalDebugRef.current = console.debug
+
+ // Create interceptor
+ console.debug = (...args: unknown[]) => {
+ // Always call original
+ originalDebugRef.current?.apply(console, args)
+
+ // SDK format: console.debug('[TON_CONNECT_SDK]', message, data)
+ // args[0] = '[TON_CONNECT_SDK]'
+ // args[1] = 'Send http-bridge request:' (message)
+ // args[2] = { method, params, id } (data)
+ if (args.length >= 3 && args[0] === SDK_PREFIX && typeof args[1] === 'string') {
+ handleSdkLogRef.current(args[1], args[2])
+ }
+ }
+
+ // Cleanup
+ return () => {
+ if (originalDebugRef.current) {
+ console.debug = originalDebugRef.current
+ originalDebugRef.current = null
+ }
+ }
+ }, [enabled])
+
+ // Clear logs
+ const clearLogs = useCallback(() => {
+ setLogs([])
+ }, [])
+
+ return { logs, clearLogs }
+}
diff --git a/apps/tonconnect-demo/src/hooks/useSettings.ts b/apps/tonconnect-demo/src/hooks/useSettings.ts
new file mode 100644
index 000000000..d44cca7d1
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useSettings.ts
@@ -0,0 +1,622 @@
+import { useState, useEffect, useCallback } from "react"
+import { useTonConnectUI, THEME } from "@tonconnect/ui-react"
+
+// Default colors for each theme - matches SDK defaults from packages/ui/src/app/styles/default-colors.ts
+const DEFAULT_COLORS = {
+ [THEME.DARK]: {
+ constant: { black: "#000000", white: "#FFFFFF" },
+ connectButton: { background: "#0098EA", foreground: "#FFFFFF" },
+ accent: "#E5E5EA",
+ telegramButton: "#31A6F5",
+ icon: { primary: "#E5E5EA", secondary: "#909099", tertiary: "#434347", success: "#29CC6A", error: "#F5A73B" },
+ background: { primary: "#121214", secondary: "#18181A", segment: "#262629", tint: "#222224", qr: "#FFFFFF" },
+ text: { primary: "#E5E5EA", secondary: "#7D7D85" }
+ },
+ [THEME.LIGHT]: {
+ constant: { black: "#000000", white: "#FFFFFF" },
+ connectButton: { background: "#0098EA", foreground: "#FFFFFF" },
+ accent: "#0098EA",
+ telegramButton: "#0098EA",
+ icon: { primary: "#0F0F0F", secondary: "#7A8999", tertiary: "#C1CAD2", success: "#29CC6A", error: "#F5A73B" },
+ background: { primary: "#FFFFFF", secondary: "#F1F3F5", segment: "#FFFFFF", tint: "#F1F3F5", qr: "#F1F3F5" },
+ text: { primary: "#0F0F0F", secondary: "#6A7785" }
+ }
+}
+
+export type ThemeOption = "light" | "dark" | "system"
+export type LanguageOption = "en" | "ru" | "system"
+
+export interface ColorsConfig {
+ // Constant
+ constantBlack: string
+ constantWhite: string
+ // Connect Button
+ connectButtonBg: string
+ connectButtonFg: string
+ // General
+ accent: string
+ telegramButton: string
+ // Icon
+ iconPrimary: string
+ iconSecondary: string
+ iconTertiary: string
+ iconSuccess: string
+ iconError: string
+ // Background
+ backgroundPrimary: string
+ backgroundSecondary: string
+ backgroundSegment: string
+ backgroundTint: string
+ backgroundQr: string
+ // Text
+ textPrimary: string
+ textSecondary: string
+}
+
+export type FeaturesMode = "none" | "required" | "preferred"
+export type ExportFormat = "json" | "react" | "vanilla"
+
+// Helper to convert SDK color structure to flat ColorsConfig
+function colorsFromTheme(theme: THEME): ColorsConfig {
+ const colors = DEFAULT_COLORS[theme]
+ return {
+ constantBlack: colors.constant.black,
+ constantWhite: colors.constant.white,
+ connectButtonBg: colors.connectButton.background,
+ connectButtonFg: colors.connectButton.foreground,
+ accent: colors.accent,
+ telegramButton: colors.telegramButton,
+ iconPrimary: colors.icon.primary,
+ iconSecondary: colors.icon.secondary,
+ iconTertiary: colors.icon.tertiary,
+ iconSuccess: colors.icon.success,
+ iconError: colors.icon.error,
+ backgroundPrimary: colors.background.primary,
+ backgroundSecondary: colors.background.secondary,
+ backgroundSegment: colors.background.segment,
+ backgroundTint: colors.background.tint,
+ backgroundQr: colors.background.qr,
+ textPrimary: colors.text.primary,
+ textSecondary: colors.text.secondary,
+ }
+}
+
+export function useSettings() {
+ const [, setOptions] = useTonConnectUI()
+
+ // Manifest URL (for configuration export)
+ const [manifestUrl, setManifestUrl] = useState(
+ `${window.location.origin}${import.meta.env.BASE_URL}tonconnect-manifest.json`
+ )
+
+ // UI Settings
+ const [language, setLanguage] = useState("system")
+ const [theme, setThemeState] = useState(() => {
+ const stored = localStorage.getItem("tonconnect-demo-theme")
+ return (stored as ThemeOption) || "system"
+ })
+ const [borderRadius, setBorderRadius] = useState<"s" | "m" | "none">("m")
+
+ // Persist theme to localStorage
+ const setTheme = useCallback((newTheme: ThemeOption) => {
+ setThemeState(newTheme)
+ localStorage.setItem("tonconnect-demo-theme", newTheme)
+ }, [])
+
+ // Colors - initialized from SDK defaults
+ const [darkColors, setDarkColors] = useState(() => colorsFromTheme(THEME.DARK))
+ const [lightColors, setLightColors] = useState(() => colorsFromTheme(THEME.LIGHT))
+
+ // Modals
+ const [modalsBefore, setModalsBefore] = useState(true)
+ const [modalsSuccess, setModalsSuccess] = useState(false)
+ const [modalsError, setModalsError] = useState(false)
+
+ // Notifications
+ const [notificationsBefore, setNotificationsBefore] = useState(true)
+ const [notificationsSuccess, setNotificationsSuccess] = useState(true)
+ const [notificationsError, setNotificationsError] = useState(true)
+
+ // Redirect
+ const [returnStrategy, setReturnStrategy] = useState<"back" | "none">("back")
+ const [twaReturnUrl, setTwaReturnUrl] = useState("")
+
+ // Deprecated options
+ const [skipRedirect, setSkipRedirect] = useState<"never" | "always" | "ios">("ios")
+
+ // Android
+ const [enableAndroidBackHandler, setEnableAndroidBackHandler] = useState(true)
+
+ // Network selection (for transactions)
+ // "" = Any, "-239" = Mainnet, "-3" = Testnet
+ const [selectedNetwork, setSelectedNetwork] = useState("")
+
+ // Features Filter (Required и Preferred взаимоисключающие)
+ const [featuresMode, setFeaturesMode] = useState("none")
+ const [minMessages, setMinMessages] = useState()
+ const [extraCurrencyRequired, setExtraCurrencyRequired] = useState(false)
+ const [signDataTypes, setSignDataTypes] = useState([])
+
+ // Helper to get effective theme (resolve "system")
+ const getEffectiveTheme = useCallback((): "light" | "dark" => {
+ if (theme === "system") {
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
+ }
+ return theme
+ }, [theme])
+
+ // Apply theme to document
+ useEffect(() => {
+ const effectiveTheme = getEffectiveTheme()
+ document.documentElement.classList.toggle("dark", effectiveTheme === "dark")
+
+ // Listen for system theme changes when in "system" mode
+ if (theme === "system") {
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
+ const handler = (e: MediaQueryListEvent) => {
+ document.documentElement.classList.toggle("dark", e.matches)
+ }
+ mediaQuery.addEventListener("change", handler)
+ return () => mediaQuery.removeEventListener("change", handler)
+ }
+ }, [theme, getEffectiveTheme])
+
+ // Build features object for TonConnect
+ const buildFeatures = useCallback((minMsg?: number, extraCurrency?: boolean, signTypes?: string[]) => {
+ const features: Record = {}
+ if (minMsg || extraCurrency) {
+ features.sendTransaction = {
+ ...(minMsg ? { minMessages: minMsg } : {}),
+ ...(extraCurrency ? { extraCurrencyRequired: true } : {})
+ }
+ }
+ if (signTypes?.length) {
+ features.signData = { types: signTypes }
+ }
+ return Object.keys(features).length > 0 ? features : undefined
+ }, [])
+
+ // Apply settings to TonConnect UI
+ useEffect(() => {
+ const tcTheme = theme === "system" ? "SYSTEM" : theme === "dark" ? THEME.DARK : THEME.LIGHT
+
+ // Build modals array
+ const modals: ("before" | "success" | "error")[] = []
+ if (modalsBefore) modals.push("before")
+ if (modalsSuccess) modals.push("success")
+ if (modalsError) modals.push("error")
+
+ // Build notifications array
+ const notifications: ("before" | "success" | "error")[] = []
+ if (notificationsBefore) notifications.push("before")
+ if (notificationsSuccess) notifications.push("success")
+ if (notificationsError) notifications.push("error")
+
+ // Build features based on mode
+ const features = buildFeatures(minMessages, extraCurrencyRequired, signDataTypes)
+
+ setOptions({
+ // Only set language if explicitly chosen (not "system" = auto-detect)
+ language: language !== "system" ? language : undefined,
+ walletsRequiredFeatures: featuresMode === "required" ? features : undefined,
+ walletsPreferredFeatures: featuresMode === "preferred" ? features : undefined,
+ uiPreferences: {
+ theme: tcTheme,
+ borderRadius,
+ colorsSet: {
+ [THEME.DARK]: {
+ constant: { black: darkColors.constantBlack, white: darkColors.constantWhite },
+ connectButton: { background: darkColors.connectButtonBg, foreground: darkColors.connectButtonFg },
+ accent: darkColors.accent,
+ telegramButton: darkColors.telegramButton,
+ icon: {
+ primary: darkColors.iconPrimary,
+ secondary: darkColors.iconSecondary,
+ tertiary: darkColors.iconTertiary,
+ success: darkColors.iconSuccess,
+ error: darkColors.iconError
+ },
+ background: {
+ primary: darkColors.backgroundPrimary,
+ secondary: darkColors.backgroundSecondary,
+ segment: darkColors.backgroundSegment,
+ tint: darkColors.backgroundTint,
+ qr: darkColors.backgroundQr
+ },
+ text: { primary: darkColors.textPrimary, secondary: darkColors.textSecondary }
+ },
+ [THEME.LIGHT]: {
+ constant: { black: lightColors.constantBlack, white: lightColors.constantWhite },
+ connectButton: { background: lightColors.connectButtonBg, foreground: lightColors.connectButtonFg },
+ accent: lightColors.accent,
+ telegramButton: lightColors.telegramButton,
+ icon: {
+ primary: lightColors.iconPrimary,
+ secondary: lightColors.iconSecondary,
+ tertiary: lightColors.iconTertiary,
+ success: lightColors.iconSuccess,
+ error: lightColors.iconError
+ },
+ background: {
+ primary: lightColors.backgroundPrimary,
+ secondary: lightColors.backgroundSecondary,
+ segment: lightColors.backgroundSegment,
+ tint: lightColors.backgroundTint,
+ qr: lightColors.backgroundQr
+ },
+ text: { primary: lightColors.textPrimary, secondary: lightColors.textSecondary }
+ }
+ }
+ },
+ actionsConfiguration: {
+ modals: modals.length > 0 ? modals : undefined,
+ notifications: notifications.length > 0 ? notifications : undefined,
+ returnStrategy,
+ skipRedirectToWallet: skipRedirect,
+ twaReturnUrl: twaReturnUrl ? twaReturnUrl as `${string}://${string}` : undefined
+ },
+ enableAndroidBackHandler
+ })
+ }, [
+ setOptions, language, theme, borderRadius,
+ darkColors, lightColors,
+ modalsBefore, modalsSuccess, modalsError,
+ notificationsBefore, notificationsSuccess, notificationsError,
+ returnStrategy, skipRedirect, twaReturnUrl,
+ enableAndroidBackHandler,
+ featuresMode, minMessages, extraCurrencyRequired, signDataTypes, buildFeatures
+ ])
+
+ // Helper to update a single dark color
+ const updateDarkColor = useCallback((key: keyof ColorsConfig, value: string) => {
+ setDarkColors(prev => ({ ...prev, [key]: value }))
+ }, [])
+
+ // Helper to update a single light color
+ const updateLightColor = useCallback((key: keyof ColorsConfig, value: string) => {
+ setLightColors(prev => ({ ...prev, [key]: value }))
+ }, [])
+
+ // Reset colors to defaults
+ const resetColors = useCallback(() => {
+ setDarkColors(colorsFromTheme(THEME.DARK))
+ setLightColors(colorsFromTheme(THEME.LIGHT))
+ }, [])
+
+ // Build exportable configuration object
+ const buildConfiguration = useCallback((showFull: boolean, includeDeprecated: boolean = false) => {
+ const config: Record = {
+ manifestUrl
+ }
+
+ // Language - only if not "system" (auto-detect)
+ if (language !== "system") {
+ config.language = language
+ } else if (showFull) {
+ // In full mode, show that it's auto-detected
+ config.language = undefined
+ }
+
+ // Wallet Features (Required or Preferred)
+ if (featuresMode !== "none") {
+ const features: Record = {}
+
+ // sendTransaction features
+ if (minMessages || extraCurrencyRequired) {
+ const sendTx: Record = {}
+ if (minMessages) sendTx.minMessages = minMessages
+ if (extraCurrencyRequired) sendTx.extraCurrencyRequired = true
+ features.sendTransaction = sendTx
+ }
+
+ // signData features
+ if (signDataTypes.length > 0) {
+ features.signData = { types: signDataTypes }
+ }
+
+ if (Object.keys(features).length > 0) {
+ if (featuresMode === "required") {
+ config.walletsRequiredFeatures = features
+ } else {
+ config.walletsPreferredFeatures = features
+ }
+ }
+ }
+
+ // UI Preferences
+ const uiPrefs: Record = {}
+ const tcTheme = theme === "system" ? "SYSTEM" : theme === "dark" ? "DARK" : "LIGHT"
+
+ if (showFull || tcTheme !== "SYSTEM") {
+ uiPrefs.theme = tcTheme
+ }
+
+ if (showFull || borderRadius !== "m") {
+ uiPrefs.borderRadius = borderRadius
+ }
+
+ // Colors - compare with SDK defaults
+ const colorsSet: Record> = {}
+ const defaultDark = colorsFromTheme(THEME.DARK)
+ const defaultLight = colorsFromTheme(THEME.LIGHT)
+
+ const buildColorsDiff = (current: ColorsConfig, defaults: ColorsConfig) => {
+ const diff: Record = {}
+
+ // Check each color group
+ if (showFull || current.constantBlack !== defaults.constantBlack || current.constantWhite !== defaults.constantWhite) {
+ const constant: Record = {}
+ if (showFull || current.constantBlack !== defaults.constantBlack) constant.black = current.constantBlack
+ if (showFull || current.constantWhite !== defaults.constantWhite) constant.white = current.constantWhite
+ if (Object.keys(constant).length > 0) diff.constant = constant
+ }
+
+ if (showFull || current.connectButtonBg !== defaults.connectButtonBg || current.connectButtonFg !== defaults.connectButtonFg) {
+ const connectButton: Record = {}
+ if (showFull || current.connectButtonBg !== defaults.connectButtonBg) connectButton.background = current.connectButtonBg
+ if (showFull || current.connectButtonFg !== defaults.connectButtonFg) connectButton.foreground = current.connectButtonFg
+ if (Object.keys(connectButton).length > 0) diff.connectButton = connectButton
+ }
+
+ if (showFull || current.accent !== defaults.accent) diff.accent = current.accent
+ if (showFull || current.telegramButton !== defaults.telegramButton) diff.telegramButton = current.telegramButton
+
+ // Icon colors
+ const iconDiff: Record = {}
+ if (showFull || current.iconPrimary !== defaults.iconPrimary) iconDiff.primary = current.iconPrimary
+ if (showFull || current.iconSecondary !== defaults.iconSecondary) iconDiff.secondary = current.iconSecondary
+ if (showFull || current.iconTertiary !== defaults.iconTertiary) iconDiff.tertiary = current.iconTertiary
+ if (showFull || current.iconSuccess !== defaults.iconSuccess) iconDiff.success = current.iconSuccess
+ if (showFull || current.iconError !== defaults.iconError) iconDiff.error = current.iconError
+ if (Object.keys(iconDiff).length > 0) diff.icon = iconDiff
+
+ // Background colors
+ const bgDiff: Record = {}
+ if (showFull || current.backgroundPrimary !== defaults.backgroundPrimary) bgDiff.primary = current.backgroundPrimary
+ if (showFull || current.backgroundSecondary !== defaults.backgroundSecondary) bgDiff.secondary = current.backgroundSecondary
+ if (showFull || current.backgroundSegment !== defaults.backgroundSegment) bgDiff.segment = current.backgroundSegment
+ if (showFull || current.backgroundTint !== defaults.backgroundTint) bgDiff.tint = current.backgroundTint
+ if (showFull || current.backgroundQr !== defaults.backgroundQr) bgDiff.qr = current.backgroundQr
+ if (Object.keys(bgDiff).length > 0) diff.background = bgDiff
+
+ // Text colors
+ const textDiff: Record = {}
+ if (showFull || current.textPrimary !== defaults.textPrimary) textDiff.primary = current.textPrimary
+ if (showFull || current.textSecondary !== defaults.textSecondary) textDiff.secondary = current.textSecondary
+ if (Object.keys(textDiff).length > 0) diff.text = textDiff
+
+ return diff
+ }
+
+ const darkDiff = buildColorsDiff(darkColors, defaultDark)
+ const lightDiff = buildColorsDiff(lightColors, defaultLight)
+
+ if (Object.keys(darkDiff).length > 0) colorsSet.DARK = darkDiff
+ if (Object.keys(lightDiff).length > 0) colorsSet.LIGHT = lightDiff
+ if (Object.keys(colorsSet).length > 0) uiPrefs.colorsSet = colorsSet
+
+ if (Object.keys(uiPrefs).length > 0) {
+ config.uiPreferences = uiPrefs
+ }
+
+ // Actions Configuration
+ const actions: Record = {}
+
+ const modals = [
+ modalsBefore && "before",
+ modalsSuccess && "success",
+ modalsError && "error"
+ ].filter(Boolean) as string[]
+
+ const isDefaultModals = modals.length === 1 && modals[0] === "before"
+ if (showFull || !isDefaultModals) {
+ actions.modals = modals.length > 0 ? modals : []
+ }
+
+ const notifications = [
+ notificationsBefore && "before",
+ notificationsSuccess && "success",
+ notificationsError && "error"
+ ].filter(Boolean) as string[]
+
+ const isDefaultNotifications = notifications.length === 3
+ if (showFull || !isDefaultNotifications) {
+ actions.notifications = notifications.length > 0 ? notifications : []
+ }
+
+ if (showFull || returnStrategy !== "back") {
+ actions.returnStrategy = returnStrategy
+ }
+
+ if (twaReturnUrl) {
+ actions.twaReturnUrl = twaReturnUrl
+ }
+
+ // Deprecated: skipRedirectToWallet
+ if (includeDeprecated && skipRedirect !== "ios") {
+ actions.skipRedirectToWallet = skipRedirect
+ }
+
+ if (Object.keys(actions).length > 0) {
+ config.actionsConfiguration = actions
+ }
+
+ // Android
+ if (showFull || !enableAndroidBackHandler) {
+ config.enableAndroidBackHandler = enableAndroidBackHandler
+ }
+
+ // Clean up undefined values for cleaner output
+ if (config.language === undefined) {
+ delete config.language
+ }
+
+ return config
+ }, [
+ manifestUrl, language, theme, borderRadius,
+ darkColors, lightColors,
+ modalsBefore, modalsSuccess, modalsError,
+ notificationsBefore, notificationsSuccess, notificationsError,
+ returnStrategy, twaReturnUrl, skipRedirect,
+ enableAndroidBackHandler,
+ featuresMode, minMessages, extraCurrencyRequired, signDataTypes
+ ])
+
+ // Format configuration for different export targets
+ const formatConfiguration = useCallback((
+ config: Record,
+ format: ExportFormat
+ ): string => {
+ if (format === "json") {
+ return JSON.stringify(config, null, 2)
+ }
+
+ // Check if config uses theme constants
+ const configStr = JSON.stringify(config)
+ const needsTheme = configStr.includes('"DARK"') || configStr.includes('"LIGHT"') || configStr.includes('"SYSTEM"')
+
+ // Helper to format a value for JS/TSX code
+ const formatValue = (value: unknown, indent: number = 0): string => {
+ const pad = " ".repeat(indent)
+ const padInner = " ".repeat(indent + 1)
+
+ if (value === null || value === undefined) {
+ return String(value)
+ }
+ if (typeof value === "string") {
+ // Convert theme strings to THEME constants
+ if (value === "DARK" || value === "LIGHT" || value === "SYSTEM") {
+ return `THEME.${value}`
+ }
+ return `'${value.replace(/'/g, "\\'")}'`
+ }
+ if (typeof value === "number" || typeof value === "boolean") {
+ return String(value)
+ }
+ if (Array.isArray(value)) {
+ if (value.length === 0) return "[]"
+ const items = value.map(v => formatValue(v, 0)).join(", ")
+ return `[${items}]`
+ }
+ if (typeof value === "object") {
+ const entries = Object.entries(value)
+ if (entries.length === 0) return "{}"
+ const lines = entries.map(([k, v]) => {
+ // Use [THEME.X] syntax for DARK/LIGHT keys in colorsSet
+ let key: string
+ if (k === "DARK" || k === "LIGHT") {
+ key = `[THEME.${k}]`
+ } else if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k)) {
+ key = k
+ } else {
+ key = `'${k}'`
+ }
+ return `${padInner}${key}: ${formatValue(v, indent + 1)}`
+ })
+ return `{\n${lines.join(",\n")}\n${pad}}`
+ }
+ return String(value)
+ }
+
+ // Build JSX props for React
+ const buildJsxProps = (cfg: Record, indent: number): string => {
+ const pad = " ".repeat(indent)
+ const lines: string[] = []
+
+ for (const [key, value] of Object.entries(cfg)) {
+ if (value === undefined) continue
+ const formatted = formatValue(value, indent)
+ // Simple values don't need braces in JSX
+ if (typeof value === "string" && value !== "DARK" && value !== "LIGHT" && value !== "SYSTEM") {
+ lines.push(`${pad}${key}="${value}"`)
+ } else {
+ lines.push(`${pad}${key}={${formatted}}`)
+ }
+ }
+
+ return lines.join("\n")
+ }
+
+ // Build object properties for Vanilla JS
+ const buildObjectProps = (cfg: Record, indent: number): string => {
+ const pad = " ".repeat(indent)
+ const lines: string[] = []
+
+ for (const [key, value] of Object.entries(cfg)) {
+ if (value === undefined) continue
+ lines.push(`${pad}${key}: ${formatValue(value, indent)}`)
+ }
+
+ return lines.join(",\n")
+ }
+
+ if (format === "react") {
+ const propsStr = buildJsxProps(config, 3)
+ const imports = needsTheme
+ ? "import { TonConnectUIProvider, THEME } from '@tonconnect/ui-react'"
+ : "import { TonConnectUIProvider } from '@tonconnect/ui-react'"
+
+ return `${imports}
+
+function App({ children }) {
+ return (
+
+ {children}
+
+ )
+}`
+ }
+
+ // Vanilla JS
+ const optionsStr = buildObjectProps(config, 2)
+ const imports = needsTheme
+ ? "import { TonConnectUI, THEME } from '@tonconnect/ui'"
+ : "import { TonConnectUI } from '@tonconnect/ui'"
+
+ return `${imports}
+
+const tonConnectUI = new TonConnectUI({
+${optionsStr}
+})`
+ }, [])
+
+ return {
+ // Manifest
+ manifestUrl, setManifestUrl,
+ // Configuration export
+ buildConfiguration,
+ formatConfiguration,
+ // UI
+ language, setLanguage,
+ theme, setTheme,
+ borderRadius, setBorderRadius,
+ // Colors
+ darkColors, updateDarkColor,
+ lightColors, updateLightColor,
+ resetColors,
+ // Modals
+ modalsBefore, setModalsBefore,
+ modalsSuccess, setModalsSuccess,
+ modalsError, setModalsError,
+ // Notifications
+ notificationsBefore, setNotificationsBefore,
+ notificationsSuccess, setNotificationsSuccess,
+ notificationsError, setNotificationsError,
+ // Redirect
+ returnStrategy, setReturnStrategy,
+ twaReturnUrl, setTwaReturnUrl,
+ // Deprecated
+ skipRedirect, setSkipRedirect,
+ // Android
+ enableAndroidBackHandler, setEnableAndroidBackHandler,
+ // Network
+ selectedNetwork, setSelectedNetwork,
+ // Features Filter
+ featuresMode, setFeaturesMode,
+ minMessages, setMinMessages,
+ extraCurrencyRequired, setExtraCurrencyRequired,
+ signDataTypes, setSignDataTypes,
+ }
+}
diff --git a/apps/tonconnect-demo/src/hooks/useSignData.ts b/apps/tonconnect-demo/src/hooks/useSignData.ts
new file mode 100644
index 000000000..40c955c0c
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useSignData.ts
@@ -0,0 +1,282 @@
+import { useState, useEffect, useCallback } from "react"
+import { useTonConnectUI, useTonWallet } from "@tonconnect/ui-react"
+import { toast } from "sonner"
+import { verifySignData } from "@/utils/sign-data-verification"
+import type { VerificationResult } from "@/utils/sign-data-verification"
+
+export type SignDataType = "text" | "binary" | "cell"
+
+export interface SignDataOperationResult {
+ id: string
+ timestamp: number
+ requestSnapshot: string
+ response: string
+ status: 'success' | 'error'
+ errorMessage?: string
+ signatureData?: SignDataResponse
+}
+
+// Default values for each data type
+const DEFAULTS: Record = {
+ text: { data: "Hello, TON!" },
+ binary: { data: "SGVsbG8sIFRPTiE=" }, // base64 of "Hello, TON!"
+ cell: { data: "te6cckEBAQEAEQAAHgAAAABIZWxsbywgVE9OIb7WCx4=", schema: "message#_ text:string = Message;" },
+}
+
+interface SignDataResponse {
+ signature: string
+ timestamp: number
+ domain: string
+ payload: {
+ type: "text" | "binary" | "cell"
+ text?: string
+ bytes?: string
+ schema?: string
+ cell?: string
+ }
+}
+
+export function useSignData(showToastBefore = true, showToastSuccess = true, showToastError = true) {
+ const [tonConnectUI] = useTonConnectUI()
+ const wallet = useTonWallet()
+
+ const [dataType, setDataTypeInternal] = useState("text")
+ const [dataText, setDataText] = useState(DEFAULTS.text.data)
+ const [schema, setSchema] = useState("")
+
+ // When changing data type, set default values for that type
+ const setDataType = (newType: SignDataType) => {
+ if (newType !== dataType) {
+ setDataTypeInternal(newType)
+ setDataText(DEFAULTS[newType].data)
+ setSchema(DEFAULTS[newType].schema || "")
+ }
+ }
+
+ const [requestJson, setRequestJson] = useState("")
+
+ // Operation result with snapshot
+ const [lastResult, setLastResult] = useState(null)
+
+ // Loading state
+ const [isSigning, setIsSigning] = useState(false)
+
+ // For verification (keeping lastResponse for internal use)
+ const [lastResponse, setLastResponse] = useState(null)
+ const [verificationResult, setVerificationResult] = useState(null)
+ const [isVerifying, setIsVerifying] = useState(false)
+
+ // Build request JSON
+ useEffect(() => {
+ let payload: Record
+ if (dataType === "text") {
+ payload = { type: "text", text: dataText }
+ } else if (dataType === "binary") {
+ payload = { type: "binary", bytes: dataText }
+ } else {
+ payload = { type: "cell", schema, cell: dataText }
+ }
+ setRequestJson(JSON.stringify({ method: "signData", params: [payload] }, null, 2))
+ }, [dataType, dataText, schema])
+
+ // Set form state from JSON (for edit mode)
+ const setFromJson = useCallback((json: string) => {
+ try {
+ const data = JSON.parse(json)
+ const payload = data.params?.[0] || data
+
+ if (payload.type === "text" && payload.text !== undefined) {
+ setDataTypeInternal("text")
+ setDataText(payload.text)
+ setSchema("")
+ } else if (payload.type === "binary" && payload.bytes !== undefined) {
+ setDataTypeInternal("binary")
+ setDataText(payload.bytes)
+ setSchema("")
+ } else if (payload.type === "cell" && payload.cell !== undefined) {
+ setDataTypeInternal("cell")
+ setDataText(payload.cell)
+ if (payload.schema) setSchema(payload.schema)
+ }
+ } catch {
+ // Invalid JSON - ignore
+ }
+ }, [])
+
+ const sign = async () => {
+ if (!wallet) {
+ toast.error("Please connect wallet first")
+ return
+ }
+
+ // Reset previous state
+ setLastResponse(null)
+ setVerificationResult(null)
+ setServerVerificationResult(null)
+
+ // Freeze request snapshot BEFORE sending
+ const requestSnapshot = requestJson
+
+ setIsSigning(true)
+ try {
+ let payload: Record
+ if (dataType === "text") {
+ payload = { type: "text", text: dataText }
+ } else if (dataType === "binary") {
+ payload = { type: "binary", bytes: dataText }
+ } else {
+ payload = { type: "cell", schema, cell: dataText }
+ }
+
+ if (showToastBefore) toast.info("Please confirm in your wallet")
+
+ const result = await tonConnectUI.signData(payload as Parameters[0])
+
+ const responseJson = JSON.stringify(result, null, 2)
+ setLastResponse(result as unknown as SignDataResponse)
+
+ // Save result with snapshot
+ setLastResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ requestSnapshot,
+ response: responseJson,
+ status: 'success',
+ signatureData: result as unknown as SignDataResponse,
+ })
+
+ if (showToastSuccess) toast.success("Data signed successfully")
+ } catch (error) {
+ const message = error instanceof Error ? error.message : "Signing failed"
+
+ // Save error result
+ setLastResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ requestSnapshot,
+ response: JSON.stringify({ error: message }, null, 2),
+ status: 'error',
+ errorMessage: message,
+ })
+
+ if (showToastError) toast.error(message)
+ } finally {
+ setIsSigning(false)
+ }
+ }
+
+ const verify = async () => {
+ if (!lastResponse || !wallet) {
+ toast.error("No signature to verify")
+ return
+ }
+
+ setIsVerifying(true)
+ try {
+ const result = await verifySignData({
+ response: lastResponse,
+ address: wallet.account.address,
+ publicKey: wallet.account.publicKey || "",
+ walletStateInit: wallet.account.walletStateInit || ""
+ })
+
+ setVerificationResult(result)
+
+ if (result.valid) {
+ toast.success("Signature is valid")
+ } else {
+ toast.error(result.message)
+ }
+ } catch (error) {
+ const message = error instanceof Error ? error.message : "Verification failed"
+ setVerificationResult({ valid: false, message })
+ toast.error(message)
+ } finally {
+ setIsVerifying(false)
+ }
+ }
+
+ const [serverVerificationResult, setServerVerificationResult] = useState(null)
+ const [isVerifyingOnServer, setIsVerifyingOnServer] = useState(false)
+
+ const verifyOnServer = async () => {
+ if (!lastResponse || !wallet) {
+ toast.error("No signature to verify")
+ return
+ }
+
+ setIsVerifyingOnServer(true)
+ setServerVerificationResult(null)
+
+ try {
+ const requestBody = {
+ address: wallet.account.address,
+ network: wallet.account.chain,
+ public_key: wallet.account.publicKey,
+ signature: lastResponse.signature,
+ timestamp: lastResponse.timestamp,
+ domain: lastResponse.domain,
+ payload: lastResponse.payload,
+ walletStateInit: wallet.account.walletStateInit
+ }
+
+ const response = await fetch('/api/check_sign_data', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(requestBody)
+ })
+
+ const data = await response.json() as VerificationResult
+ setServerVerificationResult(data)
+
+ if (data.valid) {
+ toast.success("Server verification: Signature is valid")
+ } else {
+ toast.error(`Server verification failed: ${data.message}`)
+ }
+ } catch (error) {
+ const message = error instanceof Error ? error.message : "Server verification failed"
+ setServerVerificationResult({ valid: false, message })
+ toast.error(message)
+ } finally {
+ setIsVerifyingOnServer(false)
+ }
+ }
+
+ const clearResult = useCallback(() => {
+ setLastResult(null)
+ setLastResponse(null)
+ setVerificationResult(null)
+ setServerVerificationResult(null)
+ }, [])
+
+ const loadResultToForm = useCallback(() => {
+ if (lastResult) {
+ setFromJson(lastResult.requestSnapshot)
+ }
+ }, [lastResult, setFromJson])
+
+ return {
+ dataType, setDataType,
+ dataText, setDataText,
+ schema, setSchema,
+ requestJson,
+ sign,
+ setFromJson,
+ isConnected: !!wallet,
+ isSigning,
+ // Operation result with snapshot
+ lastResult,
+ clearResult,
+ loadResultToForm,
+ // Client verification
+ canVerify: !!lastResponse && !!wallet,
+ verify,
+ verificationResult,
+ isVerifying,
+ // Server verification
+ verifyOnServer,
+ serverVerificationResult,
+ isVerifyingOnServer,
+ }
+}
diff --git a/apps/tonconnect-demo/src/hooks/useTransaction.ts b/apps/tonconnect-demo/src/hooks/useTransaction.ts
new file mode 100644
index 000000000..e8619bdc9
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useTransaction.ts
@@ -0,0 +1,384 @@
+import { useState, useEffect, useCallback, useMemo } from "react"
+import { useTonConnectUI, useTonWallet, useIsConnectionRestored, CHAIN } from "@tonconnect/ui-react"
+import { toNano, fromNano } from "@ton/core"
+import { toast } from "sonner"
+import { useHistory } from "./useHistory"
+
+export interface TransactionMessage {
+ address: string
+ amount: string // Always stored in nanotons
+ stateInit?: string
+ payload?: string
+}
+
+export type AmountUnit = "TON" | "nano"
+
+export interface OperationResult {
+ id: string
+ timestamp: number
+ requestSnapshot: string // Frozen JSON at send time
+ response: string
+ status: 'success' | 'error'
+ errorMessage?: string
+ boc?: string
+ validUntil?: number
+}
+
+export const PRESETS = {
+ simple: {
+ name: "Simple Transfer",
+ description: "Basic TON transfer to any address",
+ validUntil: 600,
+ from: "",
+ messages: [{ address: "EQCKWpx7cNMpvmcN5ObM5lLUZHZRFKqYA4xmw9jOry0ZsF9M", amount: "5000000" }],
+ },
+ withPayload: {
+ name: "Transfer with Comment",
+ description: "Include a text message with your transfer",
+ validUntil: 600,
+ from: "",
+ messages: [{ address: "EQCKWpx7cNMpvmcN5ObM5lLUZHZRFKqYA4xmw9jOry0ZsF9M", amount: "10000000", payload: "te6cckEBAQEADAAMABQAAAAASGVsbG8h" }],
+ },
+ multiMessage: {
+ name: "Multiple Messages",
+ description: "Send TON to 2+ recipients in one transaction",
+ validUntil: 600,
+ from: "",
+ messages: [
+ { address: "EQCKWpx7cNMpvmcN5ObM5lLUZHZRFKqYA4xmw9jOry0ZsF9M", amount: "5000000" },
+ { address: "EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N", amount: "3000000" },
+ ],
+ },
+ jetton: {
+ name: "Jetton Transfer",
+ description: "Send fungible tokens (Jettons)",
+ validUntil: 600,
+ from: "",
+ messages: [{ address: "EQCKWpx7cNMpvmcN5ObM5lLUZHZRFKqYA4xmw9jOry0ZsF9M", amount: "50000000", payload: "te6cckEBAgEAqwAB4YgBQzYIKlMZvqYGaO2k3+YDIZGkqnSBfSYvklMpBnmOTLbgIUMWCCpTGb6mBmjtpN/mAyGRpKp0gX0mL5JTKQZJjky2wAAAAAAAAAAAAAAAAAEBAGRURVNUIFRSQU5TRkVSIFRPIEpFVFRPTiBXQUxMRVQgV0lUSCBDT01NRU5U" }],
+ },
+} as const
+
+export type PresetKey = keyof typeof PRESETS
+
+export function useTransaction(showToastBefore = true, showToastSuccess = true, showToastError = true) {
+ const [tonConnectUI] = useTonConnectUI()
+ const wallet = useTonWallet()
+ const isConnectionRestored = useIsConnectionRestored()
+ const history = useHistory()
+
+ // Valid until as unix timestamp
+ const [validUntil, setValidUntil] = useState(() =>
+ Math.floor(Date.now() / 1000) + 86400 // Default: +1 day
+ )
+ const [network, setNetwork] = useState("")
+ const [from, setFrom] = useState("")
+ const [messages, setMessages] = useState([
+ { address: "EQCKWpx7cNMpvmcN5ObM5lLUZHZRFKqYA4xmw9jOry0ZsF9M", amount: "5000000", stateInit: "", payload: "" },
+ ])
+
+ // Amount units per message (for display)
+ const [amountUnits, setAmountUnits] = useState>({})
+
+ const [requestJson, setRequestJson] = useState("")
+
+ // Operation result with snapshot
+ const [lastResult, setLastResult] = useState(null)
+
+ // Loading state
+ const [isSending, setIsSending] = useState(false)
+
+ // Helper to add time to validUntil
+ const addTimeToValidUntil = useCallback((seconds: number) => {
+ setValidUntil(Math.floor(Date.now() / 1000) + seconds)
+ }, [])
+
+ // Get display amount (converted based on unit)
+ const getDisplayAmount = useCallback((index: number): string => {
+ const unit = amountUnits[index] || "TON"
+ const nanoAmount = messages[index]?.amount || "0"
+ if (unit === "TON") {
+ return fromNano(nanoAmount)
+ }
+ return nanoAmount
+ }, [messages, amountUnits])
+
+ // Set amount with unit conversion
+ const setMessageAmount = useCallback((index: number, displayValue: string, unit: AmountUnit) => {
+ const updated = [...messages]
+ try {
+ const nanoValue = unit === "TON" ? toNano(displayValue || "0").toString() : displayValue
+ updated[index] = { ...updated[index], amount: nanoValue }
+ setMessages(updated)
+ } catch {
+ // Invalid number - keep as is
+ }
+ }, [messages])
+
+ // Get/set unit for message
+ const getAmountUnit = useCallback((index: number): AmountUnit => {
+ return amountUnits[index] || "TON"
+ }, [amountUnits])
+
+ const setAmountUnit = useCallback((index: number, unit: AmountUnit) => {
+ setAmountUnits(prev => ({ ...prev, [index]: unit }))
+ }, [])
+
+ // Wallet's network (only after connection is restored to prevent flicker)
+ const walletNetwork = useMemo(
+ () => isConnectionRestored && wallet?.account?.chain ? String(wallet.account.chain) : "",
+ [isConnectionRestored, wallet?.account?.chain]
+ )
+
+ // Build request JSON
+ useEffect(() => {
+ const builtMessages = messages.map((msg) => {
+ const m: Record = { address: msg.address, amount: msg.amount }
+ if (msg.stateInit) m.stateInit = msg.stateInit
+ if (msg.payload) m.payload = msg.payload
+ return m
+ })
+
+ const effectiveNetwork = network || walletNetwork
+
+ const tx: Record = {
+ validUntil,
+ messages: builtMessages,
+ }
+ if (effectiveNetwork) tx.network = effectiveNetwork
+ if (from) tx.from = from
+
+ setRequestJson(JSON.stringify(tx, null, 2))
+ }, [validUntil, network, from, messages, walletNetwork])
+
+ const loadPreset = (key: PresetKey) => {
+ const preset = PRESETS[key]
+ setValidUntil(Math.floor(Date.now() / 1000) + preset.validUntil)
+ setNetwork("") // Reset to empty - will use wallet's network
+ setFrom(preset.from)
+ setMessages(preset.messages.map((msg) => ({
+ address: msg.address,
+ amount: msg.amount,
+ stateInit: "",
+ payload: "payload" in msg ? msg.payload : "",
+ })))
+ // Reset all amount units to TON
+ setAmountUnits({})
+ }
+
+ const addMessage = () => {
+ setMessages([...messages, { address: "", amount: toNano("0.001").toString(), stateInit: "", payload: "" }])
+ }
+
+ const removeMessage = (index: number) => {
+ if (messages.length > 1) setMessages(messages.filter((_, i) => i !== index))
+ }
+
+ const updateMessage = (index: number, field: keyof TransactionMessage, value: string) => {
+ const updated = [...messages]
+ updated[index] = { ...updated[index], [field]: value }
+ setMessages(updated)
+ }
+
+ // Set form state from JSON (for edit mode)
+ const setFromJson = useCallback((json: string) => {
+ try {
+ const data = JSON.parse(json)
+
+ // Set validUntil directly (it's a unix timestamp)
+ if (data.validUntil) {
+ setValidUntil(data.validUntil)
+ }
+
+ if (data.network !== undefined) setNetwork(data.network)
+ if (data.from !== undefined) setFrom(data.from)
+
+ if (Array.isArray(data.messages)) {
+ setMessages(data.messages.map((msg: Record) => ({
+ address: msg.address || "",
+ amount: msg.amount || "0",
+ stateInit: msg.stateInit || "",
+ payload: msg.payload || "",
+ })))
+ // Reset units to nano since JSON has nanotons
+ const newUnits: Record = {}
+ data.messages.forEach((_: unknown, i: number) => {
+ newUnits[i] = "nano"
+ })
+ setAmountUnits(newUnits)
+ }
+ } catch {
+ // Invalid JSON - ignore
+ }
+ }, [])
+
+ // Internal send implementation - used by both send() and sendRaw()
+ const sendInternal = async (requestSnapshot: string, txValidUntil: number, txMessages: Array<{ address: string; amount: string; stateInit?: string; payload?: string }>) => {
+ if (!wallet) {
+ toast.error("Please connect wallet first")
+ return
+ }
+
+ const walletAddress = wallet.account.address
+ const walletNetwork = wallet.account.chain === CHAIN.TESTNET ? "testnet" as const : "mainnet" as const
+
+ setIsSending(true)
+ try {
+ if (showToastBefore) toast.info("Please confirm in your wallet")
+
+ const result = await tonConnectUI.sendTransaction({
+ validUntil: txValidUntil,
+ messages: txMessages,
+ })
+
+ const operationId = crypto.randomUUID()
+
+ // Save result with frozen request snapshot
+ setLastResult({
+ id: operationId,
+ timestamp: Date.now(),
+ requestSnapshot,
+ response: JSON.stringify(result, null, 2),
+ status: 'success',
+ boc: result.boc,
+ validUntil: txValidUntil,
+ })
+
+ // Save to localStorage history
+ history.addEntry({
+ timestamp: Date.now(),
+ walletAddress,
+ network: walletNetwork,
+ request: JSON.parse(requestSnapshot),
+ requestRaw: requestSnapshot,
+ status: "success",
+ response: JSON.parse(JSON.stringify(result)),
+ boc: result.boc,
+ })
+
+ if (showToastSuccess) toast.success("Transaction sent successfully")
+ } catch (error) {
+ const message = error instanceof Error ? error.message : "Transaction failed"
+
+ // Save error result with frozen request snapshot
+ setLastResult({
+ id: crypto.randomUUID(),
+ timestamp: Date.now(),
+ requestSnapshot,
+ response: JSON.stringify({ error: message }, null, 2),
+ status: 'error',
+ errorMessage: message,
+ })
+
+ // Save error to localStorage history
+ history.addEntry({
+ timestamp: Date.now(),
+ walletAddress,
+ network: walletNetwork,
+ request: JSON.parse(requestSnapshot),
+ requestRaw: requestSnapshot,
+ status: "error",
+ response: { error: message },
+ })
+
+ if (showToastError) toast.error(message)
+ } finally {
+ setIsSending(false)
+ }
+ }
+
+ const send = async () => {
+ if (!wallet) {
+ toast.error("Please connect wallet first")
+ return
+ }
+
+ const builtMessages = messages.map((msg) => {
+ const m: Record = { address: msg.address, amount: msg.amount }
+ if (msg.stateInit) m.stateInit = msg.stateInit
+ if (msg.payload) m.payload = msg.payload
+ return m
+ })
+
+ await sendInternal(
+ requestJson,
+ validUntil,
+ builtMessages as Array<{ address: string; amount: string; stateInit?: string; payload?: string }>
+ )
+ }
+
+ // Send raw JSON directly (bypasses form state)
+ const sendRaw = async (rawJson: string) => {
+ if (!wallet) {
+ toast.error("Please connect wallet first")
+ return
+ }
+
+ try {
+ const data = JSON.parse(rawJson)
+
+ const txValidUntil = data.validUntil || Math.floor(Date.now() / 1000) + 300
+ const txMessages = (data.messages || []).map((msg: Record) => {
+ const m: Record = { address: msg.address, amount: msg.amount }
+ if (msg.stateInit) m.stateInit = msg.stateInit
+ if (msg.payload) m.payload = msg.payload
+ return m
+ })
+
+ await sendInternal(rawJson, txValidUntil, txMessages)
+ } catch {
+ toast.error("Invalid JSON")
+ }
+ }
+
+ const clearResult = useCallback(() => {
+ setLastResult(null)
+ }, [])
+
+ const loadResultToForm = useCallback(() => {
+ if (lastResult) {
+ setFromJson(lastResult.requestSnapshot)
+ }
+ }, [lastResult, setFromJson])
+
+ // Load history entry to form
+ const loadHistoryToForm = useCallback((requestRaw: string) => {
+ setFromJson(requestRaw)
+ clearResult() // Clear current result when loading from history
+ }, [setFromJson, clearResult])
+
+ // Current wallet address for history selector
+ const currentWalletAddress = wallet?.account.address || null
+
+ return {
+ validUntil, setValidUntil,
+ addTimeToValidUntil,
+ network, setNetwork,
+ from, setFrom,
+ messages,
+ // Amount helpers
+ getDisplayAmount,
+ setMessageAmount,
+ getAmountUnit,
+ setAmountUnit,
+ requestJson,
+ loadPreset,
+ addMessage,
+ removeMessage,
+ updateMessage,
+ send,
+ sendRaw,
+ setFromJson,
+ isConnected: !!wallet,
+ isSending,
+ // Operation result with snapshot
+ lastResult,
+ clearResult,
+ loadResultToForm,
+ // History
+ currentWalletAddress,
+ loadHistoryToForm,
+ // Connection state (for UI loading states)
+ isConnectionRestored,
+ walletNetwork,
+ }
+}
diff --git a/apps/tonconnect-demo/src/hooks/useTransactionTracker.ts b/apps/tonconnect-demo/src/hooks/useTransactionTracker.ts
new file mode 100644
index 000000000..0f501c694
--- /dev/null
+++ b/apps/tonconnect-demo/src/hooks/useTransactionTracker.ts
@@ -0,0 +1,127 @@
+import { useState, useEffect, useCallback } from "react"
+import { getNormalizedExtMessageHash } from "@/utils/transaction-utils"
+
+export interface TransactionDetails {
+ lt: string
+ hash: string
+ fee: string
+ timestamp: number
+}
+
+export type TransactionStatus = "idle" | "pending" | "confirmed" | "expired"
+
+interface UseTransactionTrackerOptions {
+ boc: string | null
+ validUntil: number // Unix timestamp
+ network: "mainnet" | "testnet"
+}
+
+export function useTransactionTracker({ boc, validUntil, network }: UseTransactionTrackerOptions) {
+ const [status, setStatus] = useState("idle")
+ const [transaction, setTransaction] = useState(null)
+ const [hash, setHash] = useState(null)
+ const [remainingTime, setRemainingTime] = useState(0)
+ const [error, setError] = useState(null)
+
+ // Reset state when boc changes
+ useEffect(() => {
+ if (boc) {
+ setStatus("pending")
+ setTransaction(null)
+ setError(null)
+ try {
+ const normalizedHash = getNormalizedExtMessageHash(boc)
+ setHash(normalizedHash)
+ } catch (err) {
+ setError(err instanceof Error ? err.message : "Failed to calculate hash")
+ setStatus("idle")
+ }
+ } else {
+ setStatus("idle")
+ setHash(null)
+ setTransaction(null)
+ }
+ }, [boc])
+
+ // Countdown timer
+ useEffect(() => {
+ if (!boc || status !== "pending") return
+
+ const updateRemaining = () => {
+ const remaining = validUntil - Math.floor(Date.now() / 1000)
+ setRemainingTime(Math.max(0, remaining))
+
+ if (remaining <= 0) {
+ setStatus("expired")
+ }
+ }
+
+ updateRemaining()
+ const interval = setInterval(updateRemaining, 1000)
+
+ return () => clearInterval(interval)
+ }, [boc, validUntil, status])
+
+ // Polling for transaction confirmation
+ useEffect(() => {
+ if (!hash || status !== "pending") return
+
+ const endpoint = network === "testnet"
+ ? "https://testnet.toncenter.com/api/v3"
+ : "https://toncenter.com/api/v3"
+
+ const poll = async () => {
+ if (Date.now() / 1000 > validUntil) {
+ setStatus("expired")
+ return
+ }
+
+ try {
+ const response = await fetch(
+ `${endpoint}/transactionsByMessage?msg_hash=${hash}&direction=in`
+ )
+ const data = await response.json()
+
+ if (data.transactions?.length > 0) {
+ const tx = data.transactions[0]
+ setTransaction({
+ lt: tx.lt,
+ hash: tx.hash,
+ fee: tx.total_fees,
+ timestamp: tx.now,
+ })
+ setStatus("confirmed")
+ }
+ setError(null)
+ } catch (err) {
+ setError(err instanceof Error ? err.message : "Network error")
+ }
+ }
+
+ poll()
+ const pollInterval = setInterval(poll, 3000)
+
+ return () => clearInterval(pollInterval)
+ }, [hash, validUntil, network, status])
+
+ const reset = useCallback(() => {
+ setStatus("idle")
+ setHash(null)
+ setTransaction(null)
+ setError(null)
+ setRemainingTime(0)
+ }, [])
+
+ // Format time as M:SS
+ const formattedTime = `${Math.floor(remainingTime / 60)}:${(remainingTime % 60).toString().padStart(2, "0")}`
+
+ return {
+ hash,
+ status,
+ transaction,
+ remainingTime,
+ formattedTime,
+ error,
+ reset,
+ }
+}
diff --git a/apps/tonconnect-demo/src/index.css b/apps/tonconnect-demo/src/index.css
new file mode 100644
index 000000000..b11a602c8
--- /dev/null
+++ b/apps/tonconnect-demo/src/index.css
@@ -0,0 +1,266 @@
+@import 'tailwindcss';
+
+@plugin 'tailwindcss-animate';
+@plugin '@tailwindcss/typography';
+
+@custom-variant dark (&:is(.dark *));
+
+:root {
+ --background: #ffffff;
+ --foreground: #0f0f0f;
+ --card: #ffffff;
+ --card-foreground: #0f0f0f;
+ --popover: #ffffff;
+ --popover-foreground: #0f0f0f;
+ --primary: #0098EA;
+ --primary-foreground: #ffffff;
+ --secondary: #f1f3f5;
+ --secondary-foreground: #0f0f0f;
+ --muted: #f1f3f5;
+ --muted-foreground: #6a7785;
+ --accent: #f1f3f5;
+ --accent-foreground: #0f0f0f;
+ --destructive: #ff3b30;
+ --destructive-foreground: #ffffff;
+ --success: #34c759;
+ --success-foreground: #ffffff;
+ --warning: #ff9500;
+ --warning-foreground: #ffffff;
+ --border: #e5e5e5;
+ --input: #e5e5e5;
+ --ring: #0098EA;
+ --chart-1: #0098EA;
+ --chart-2: #34c759;
+ --chart-3: #ff9500;
+ --chart-4: #af52de;
+ --chart-5: #ff2d55;
+ --radius: 0.625rem;
+ --sidebar: #f1f3f5;
+ --sidebar-foreground: #0f0f0f;
+ --sidebar-primary: #0098EA;
+ --sidebar-primary-foreground: #ffffff;
+ --sidebar-accent: #e5e5e5;
+ --sidebar-accent-foreground: #0f0f0f;
+ --sidebar-border: #e5e5e5;
+ --sidebar-ring: #0098EA;
+}
+
+.dark {
+ --background: #121214;
+ --foreground: #f5f5f5;
+ --card: #1c1c1e;
+ --card-foreground: #f5f5f5;
+ --popover: #1c1c1e;
+ --popover-foreground: #f5f5f5;
+ --primary: #0098EA;
+ --primary-foreground: #ffffff;
+ --secondary: #222224;
+ --secondary-foreground: #f5f5f5;
+ --muted: #222224;
+ --muted-foreground: #8e8e93;
+ --accent: #222224;
+ --accent-foreground: #f5f5f5;
+ --destructive: #ff453a;
+ --destructive-foreground: #ffffff;
+ --success: #30d158;
+ --success-foreground: #ffffff;
+ --warning: #ff9f0a;
+ --warning-foreground: #ffffff;
+ --border: #2e2e2e;
+ --input: #2e2e2e;
+ --ring: #0098EA;
+ --chart-1: #0098EA;
+ --chart-2: #30d158;
+ --chart-3: #ff9f0a;
+ --chart-4: #bf5af2;
+ --chart-5: #ff375f;
+ --sidebar: #1c1c1e;
+ --sidebar-foreground: #f5f5f5;
+ --sidebar-primary: #0098EA;
+ --sidebar-primary-foreground: #ffffff;
+ --sidebar-accent: #2e2e2e;
+ --sidebar-accent-foreground: #f5f5f5;
+ --sidebar-border: #2e2e2e;
+ --sidebar-ring: #0098EA;
+}
+
+@theme inline {
+ --font-sans: ui-sans-serif, system-ui, sans-serif;
+ --font-mono: ui-monospace, monospace;
+ --color-background: var(--background);
+ --color-foreground: var(--foreground);
+ --color-card: var(--card);
+ --color-card-foreground: var(--card-foreground);
+ --color-popover: var(--popover);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-primary: var(--primary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-secondary: var(--secondary);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-muted: var(--muted);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-accent: var(--accent);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-destructive: var(--destructive);
+ --color-destructive-foreground: var(--destructive-foreground);
+ --color-success: var(--success);
+ --color-success-foreground: var(--success-foreground);
+ --color-warning: var(--warning);
+ --color-warning-foreground: var(--warning-foreground);
+ --color-border: var(--border);
+ --color-input: var(--input);
+ --color-ring: var(--ring);
+ --color-chart-1: var(--chart-1);
+ --color-chart-2: var(--chart-2);
+ --color-chart-3: var(--chart-3);
+ --color-chart-4: var(--chart-4);
+ --color-chart-5: var(--chart-5);
+ --radius-sm: calc(var(--radius) - 4px);
+ --radius-md: calc(var(--radius) - 2px);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) + 4px);
+ --color-sidebar-ring: var(--sidebar-ring);
+ --color-sidebar-border: var(--sidebar-border);
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+ --color-sidebar-accent: var(--sidebar-accent);
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+ --color-sidebar-primary: var(--sidebar-primary);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --color-sidebar: var(--sidebar);
+ --radius-2xl: calc(var(--radius) + 8px);
+ --radius-3xl: calc(var(--radius) + 12px);
+ --radius-4xl: calc(var(--radius) + 16px);
+}
+
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
+
+/* Header scroll-driven animations */
+@keyframes header-shadow {
+ from {
+ box-shadow: 0 0 0 transparent;
+ }
+ to {
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+ }
+}
+
+@keyframes header-padding {
+ from {
+ padding-top: 24px;
+ padding-bottom: 24px;
+ }
+ to {
+ padding-top: 12px;
+ padding-bottom: 12px;
+ }
+}
+
+@keyframes title-shrink {
+ from {
+ transform: scale(1);
+ }
+ to {
+ transform: scale(0.78);
+ }
+}
+
+@keyframes subtitle-hide {
+ 0% {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ height: 20px;
+ margin-top: 4px;
+ }
+ /* Текст исчезает быстро за первые 30% скролла */
+ 30% {
+ opacity: 0;
+ transform: translateY(-6px) scale(0.96);
+ height: 20px;
+ margin-top: 4px;
+ }
+ /* Остальные 70% — схлопываем уже невидимое пространство */
+ 100% {
+ opacity: 0;
+ transform: translateY(-6px) scale(0.96);
+ height: 0px;
+ margin-top: 0px;
+ }
+}
+
+@keyframes button-shrink {
+ from {
+ transform: scale(1);
+ }
+ to {
+ transform: scale(0.9);
+ }
+}
+
+.header-animated {
+ animation: header-shadow linear both;
+ animation-timeline: scroll(root);
+ animation-range: 0px 100px;
+}
+
+.header-animated::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: -3px;
+ height: 3px;
+ background: linear-gradient(to bottom, var(--background), transparent);
+ pointer-events: none;
+}
+
+.header-content {
+ /* Fallback padding when scroll-timeline not available or no scroll */
+ padding-top: 24px;
+ padding-bottom: 24px;
+ animation: header-padding linear both;
+ animation-timeline: scroll(root);
+ animation-range: 0px 100px;
+}
+
+.header-title {
+ /* Fallback when scroll-timeline not available or no scroll */
+ transform: scale(1);
+ transform-origin: left center;
+ animation: title-shrink linear both;
+ animation-timeline: scroll(root);
+ animation-range: 0px 100px;
+}
+
+.header-subtitle {
+ /* Fallback when scroll-timeline not available or no scroll */
+ opacity: 1;
+ height: 20px;
+ margin-top: 4px;
+ animation: subtitle-hide linear both;
+ animation-timeline: scroll(root);
+ animation-range: 0px 70px;
+}
+
+.header-button {
+ /* Fallback when scroll-timeline not available or no scroll */
+ transform: scale(1);
+ animation: button-shrink linear both;
+ animation-timeline: scroll(root);
+ animation-range: 0px 100px;
+}
+
+/* Hide scrollbar for horizontal scroll tabs */
+.scrollbar-hide {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
+.scrollbar-hide::-webkit-scrollbar {
+ display: none;
+}
diff --git a/apps/tonconnect-demo/src/lib/codemirror-theme.ts b/apps/tonconnect-demo/src/lib/codemirror-theme.ts
new file mode 100644
index 000000000..b74b35c0c
--- /dev/null
+++ b/apps/tonconnect-demo/src/lib/codemirror-theme.ts
@@ -0,0 +1,121 @@
+import { EditorView } from "@codemirror/view"
+import { HighlightStyle, syntaxHighlighting } from "@codemirror/language"
+import { tags } from "@lezer/highlight"
+
+// TonConnect color palette
+const palette = {
+ dark: {
+ background: "#121214",
+ backgroundSecondary: "#1c1c1e",
+ text: "#f5f5f5",
+ textSecondary: "#8e8e93",
+ accent: "#0098EA",
+ string: "#98c379",
+ number: "#d19a66",
+ boolean: "#56b6c2",
+ null: "#c678dd",
+ // JSX specific
+ tagName: "#e06c75",
+ attributeName: "#d19a66",
+ angleBracket: "#abb2bf",
+ className: "#e5c07b",
+ function: "#61afef",
+ },
+ light: {
+ background: "#ffffff",
+ backgroundSecondary: "#f1f3f5",
+ text: "#0f0f0f",
+ textSecondary: "#6a7785",
+ accent: "#0098EA",
+ string: "#50a14f",
+ number: "#c18401",
+ boolean: "#0184bc",
+ null: "#a626a4",
+ // JSX specific
+ tagName: "#e45649",
+ attributeName: "#986801",
+ angleBracket: "#383a42",
+ className: "#c18401",
+ function: "#4078f2",
+ },
+}
+
+function createBaseTheme(isDark: boolean) {
+ const colors = isDark ? palette.dark : palette.light
+
+ return EditorView.theme(
+ {
+ "&": {
+ backgroundColor: colors.background,
+ color: colors.text,
+ },
+ ".cm-content": {
+ caretColor: colors.accent,
+ },
+ ".cm-cursor, .cm-dropCursor": {
+ borderLeftColor: colors.accent,
+ },
+ "&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection":
+ {
+ backgroundColor: isDark ? "#264f78" : "#add6ff",
+ },
+ ".cm-gutters": {
+ backgroundColor: colors.backgroundSecondary,
+ color: colors.textSecondary,
+ border: "none",
+ },
+ ".cm-activeLineGutter": {
+ backgroundColor: isDark ? "#2c313c" : "#e8e8e8",
+ },
+ ".cm-activeLine": {
+ backgroundColor: isDark ? "#2c313c40" : "#f0f0f0",
+ },
+ ".cm-foldPlaceholder": {
+ backgroundColor: colors.backgroundSecondary,
+ color: colors.textSecondary,
+ border: "none",
+ },
+ ".cm-tooltip": {
+ backgroundColor: colors.backgroundSecondary,
+ border: `1px solid ${isDark ? "#3e4451" : "#ddd"}`,
+ },
+ ".cm-tooltip-autocomplete": {
+ "& > ul > li[aria-selected]": {
+ backgroundColor: isDark ? "#2c313c" : "#e8e8e8",
+ },
+ },
+ },
+ { dark: isDark }
+ )
+}
+
+function createHighlightStyle(isDark: boolean) {
+ const colors = isDark ? palette.dark : palette.light
+
+ return HighlightStyle.define([
+ // General
+ { tag: tags.keyword, color: colors.accent },
+ { tag: tags.string, color: colors.string },
+ { tag: tags.number, color: colors.number },
+ { tag: tags.bool, color: colors.boolean },
+ { tag: tags.null, color: colors.null },
+ { tag: tags.propertyName, color: colors.accent },
+ { tag: tags.punctuation, color: colors.textSecondary },
+ { tag: tags.bracket, color: colors.text },
+ { tag: tags.comment, color: colors.textSecondary, fontStyle: "italic" },
+ // JSX/TSX
+ { tag: tags.tagName, color: colors.tagName },
+ { tag: tags.attributeName, color: colors.attributeName },
+ { tag: tags.angleBracket, color: colors.angleBracket },
+ { tag: tags.className, color: colors.className },
+ { tag: tags.function(tags.variableName), color: colors.function },
+ { tag: tags.definition(tags.variableName), color: colors.function },
+ // TypeScript
+ { tag: tags.typeName, color: colors.className },
+ { tag: tags.namespace, color: colors.className },
+ ])
+}
+
+export function createTonConnectTheme(isDark: boolean) {
+ return [createBaseTheme(isDark), syntaxHighlighting(createHighlightStyle(isDark))]
+}
diff --git a/apps/tonconnect-demo/src/lib/utils.ts b/apps/tonconnect-demo/src/lib/utils.ts
new file mode 100644
index 000000000..bd0c391dd
--- /dev/null
+++ b/apps/tonconnect-demo/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
diff --git a/apps/tonconnect-demo/src/main.tsx b/apps/tonconnect-demo/src/main.tsx
new file mode 100644
index 000000000..8a5eb1d31
--- /dev/null
+++ b/apps/tonconnect-demo/src/main.tsx
@@ -0,0 +1,29 @@
+import "./polyfills"
+import { enableQaMode } from '@tonconnect/ui-react'
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import './index.css'
+import App from './App.tsx'
+
+// Initialize QA Mode before App renders (critical for WalletsListManager)
+if (localStorage.getItem('devtools:qa-mode') === 'true') {
+ enableQaMode()
+}
+
+async function startApp() {
+ // Start MSW mock server (non-blocking - app works without it)
+ try {
+ const { startMockServer } = await import('./server')
+ await startMockServer()
+ } catch (e) {
+ console.warn('[MSW] Failed to start mock server:', e)
+ }
+
+ createRoot(document.getElementById('root')!).render(
+
+
+ ,
+ )
+}
+
+startApp()
diff --git a/apps/tonconnect-demo/src/polyfills.ts b/apps/tonconnect-demo/src/polyfills.ts
new file mode 100644
index 000000000..142407dca
--- /dev/null
+++ b/apps/tonconnect-demo/src/polyfills.ts
@@ -0,0 +1,11 @@
+import { Buffer } from "buffer"
+
+declare global {
+ interface Window {
+ Buffer: typeof Buffer
+ }
+}
+
+if (typeof window !== "undefined" && !window.Buffer) {
+ window.Buffer = Buffer
+}
diff --git a/apps/tonconnect-demo/src/schemas/sign-data.schema.json b/apps/tonconnect-demo/src/schemas/sign-data.schema.json
new file mode 100644
index 000000000..fa09c0655
--- /dev/null
+++ b/apps/tonconnect-demo/src/schemas/sign-data.schema.json
@@ -0,0 +1,33 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "oneOf": [
+ {
+ "type": "object",
+ "required": ["type", "text"],
+ "properties": {
+ "type": { "const": "text" },
+ "text": { "type": "string", "minLength": 1 }
+ },
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "required": ["type", "bytes"],
+ "properties": {
+ "type": { "const": "binary" },
+ "bytes": { "type": "string", "pattern": "^[A-Za-z0-9+/=]*$" }
+ },
+ "additionalProperties": false
+ },
+ {
+ "type": "object",
+ "required": ["type", "schema", "cell"],
+ "properties": {
+ "type": { "const": "cell" },
+ "schema": { "type": "string", "minLength": 1 },
+ "cell": { "type": "string", "pattern": "^[A-Za-z0-9+/=]*$" }
+ },
+ "additionalProperties": false
+ }
+ ]
+}
diff --git a/apps/tonconnect-demo/src/schemas/transaction.schema.json b/apps/tonconnect-demo/src/schemas/transaction.schema.json
new file mode 100644
index 000000000..9bb1fc584
--- /dev/null
+++ b/apps/tonconnect-demo/src/schemas/transaction.schema.json
@@ -0,0 +1,53 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "object",
+ "required": ["validUntil", "messages"],
+ "properties": {
+ "validUntil": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Unix timestamp until which the transaction is valid"
+ },
+ "network": {
+ "type": "string",
+ "enum": ["-239", "-3"],
+ "description": "Network: -239 for mainnet, -3 for testnet"
+ },
+ "from": {
+ "type": "string",
+ "description": "Sender address (optional)"
+ },
+ "messages": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 4,
+ "items": {
+ "type": "object",
+ "required": ["address", "amount"],
+ "properties": {
+ "address": {
+ "type": "string",
+ "pattern": "^(EQ|UQ|0:|kQ|Ef|-1:)[a-zA-Z0-9_-]{46,64}$",
+ "description": "Recipient address"
+ },
+ "amount": {
+ "type": "string",
+ "pattern": "^\\d+$",
+ "description": "Amount in nanotons"
+ },
+ "payload": {
+ "type": "string",
+ "description": "Base64 encoded payload (optional)"
+ },
+ "stateInit": {
+ "type": "string",
+ "description": "Base64 encoded state init (optional)"
+ }
+ },
+ "additionalProperties": false
+ },
+ "description": "Array of messages to send"
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/apps/tonconnect-demo/src/server/handlers/check-proof.ts b/apps/tonconnect-demo/src/server/handlers/check-proof.ts
new file mode 100644
index 000000000..b3726ddc4
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/handlers/check-proof.ts
@@ -0,0 +1,83 @@
+import { http, HttpResponse } from 'msw';
+import { sha256 } from '@ton/crypto';
+import { checkProofDetailed } from '../services/ton-proof.service';
+import type { CheckProofPayload, ProofChecks } from '../services/ton-proof.service';
+import { TonApiService } from '../services/ton-api.service';
+import { createAuthToken, verifyToken } from '../utils/jwt';
+
+interface CheckProofRequest extends CheckProofPayload {
+ network: string;
+ payloadToken: string;
+}
+
+export interface VerifyChecks extends ProofChecks {
+ jwtValid: boolean;
+ payloadMatch: boolean;
+}
+
+export interface CheckProofResponse {
+ valid: boolean;
+ checks: VerifyChecks;
+ token?: string;
+ error?: string;
+}
+
+export const checkProofHandler = http.post('/api/check_proof', async ({ request }) => {
+ const checks: VerifyChecks = {
+ jwtValid: false,
+ payloadMatch: false,
+ publicKeyMatch: false,
+ addressMatch: false,
+ domainAllowed: false,
+ timestampValid: false,
+ signatureValid: false
+ };
+
+ try {
+ const body = await request.json() as CheckProofRequest;
+
+ // 1. Verify JWT payload token
+ checks.jwtValid = (await verifyToken(body.payloadToken)) !== null;
+
+ // 2. Check payload token hash matches what wallet signed
+ const payloadTokenHash = (await sha256(body.payloadToken)).toString('hex');
+ checks.payloadMatch = payloadTokenHash === body.proof.payload;
+
+ // 3. Verify cryptographic proof (signature, address, public key, domain, timestamp)
+ const tonApi = new TonApiService(body.network);
+ const proofResult = await checkProofDetailed(body, (address) => tonApi.getWalletPublicKey(address));
+
+ // Merge proof checks
+ checks.publicKeyMatch = proofResult.checks.publicKeyMatch;
+ checks.addressMatch = proofResult.checks.addressMatch;
+ checks.domainAllowed = proofResult.checks.domainAllowed;
+ checks.timestampValid = proofResult.checks.timestampValid;
+ checks.signatureValid = proofResult.checks.signatureValid;
+
+ // Determine overall validity
+ const valid = Object.values(checks).every(Boolean);
+
+ if (!valid) {
+ let error = 'Verification failed';
+ if (!checks.jwtValid) error = 'Invalid JWT token';
+ else if (!checks.payloadMatch) error = 'Payload hash mismatch';
+ else if (proofResult.error) error = proofResult.error;
+
+ return HttpResponse.json({ valid: false, checks, error } satisfies CheckProofResponse);
+ }
+
+ // Create auth token
+ const token = await createAuthToken({
+ address: body.address,
+ network: body.network
+ });
+
+ return HttpResponse.json({ valid: true, checks, token } satisfies CheckProofResponse);
+ } catch (e) {
+ console.error('check_proof error:', e);
+ return HttpResponse.json(
+ { valid: false, checks, error: 'Invalid request' } satisfies CheckProofResponse,
+ { status: 400 }
+ );
+ }
+});
diff --git a/apps/tonconnect-demo/src/server/handlers/check-sign-data.ts b/apps/tonconnect-demo/src/server/handlers/check-sign-data.ts
new file mode 100644
index 000000000..f0d9b0486
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/handlers/check-sign-data.ts
@@ -0,0 +1,48 @@
+import { http, HttpResponse } from 'msw';
+import { verifySignData } from '@/utils/sign-data-verification';
+import type { VerificationResult } from '@/utils/sign-data-verification';
+
+interface SignDataRequest {
+ address: string;
+ network: string;
+ public_key: string;
+ signature: string;
+ timestamp: number;
+ domain: string;
+ payload: {
+ type: 'text' | 'binary' | 'cell';
+ text?: string;
+ bytes?: string;
+ schema?: string;
+ cell?: string;
+ };
+ walletStateInit: string;
+}
+
+export const checkSignDataHandler = http.post('/api/check_sign_data', async ({ request }) => {
+ try {
+ const body = await request.json() as SignDataRequest;
+
+ // Use the same verifier as client
+ const result: VerificationResult = await verifySignData({
+ response: {
+ signature: body.signature,
+ timestamp: body.timestamp,
+ domain: body.domain,
+ payload: body.payload
+ },
+ address: body.address,
+ publicKey: body.public_key,
+ walletStateInit: body.walletStateInit
+ });
+
+ // Return same format as client verification
+ return HttpResponse.json(result);
+ } catch (e) {
+ console.error('[check_sign_data] Error:', e);
+ return HttpResponse.json({
+ valid: false,
+ message: e instanceof Error ? e.message : 'Verification failed'
+ } as VerificationResult);
+ }
+});
diff --git a/apps/tonconnect-demo/src/server/handlers/find-transaction.ts b/apps/tonconnect-demo/src/server/handlers/find-transaction.ts
new file mode 100644
index 000000000..7a5ec015c
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/handlers/find-transaction.ts
@@ -0,0 +1,49 @@
+import { http, HttpResponse } from 'msw';
+
+const ENDPOINTS: Record = {
+ '-239': 'https://mainnet.tonhubapi.com/jsonRPC',
+ '-3': 'https://testnet.tonhubapi.com/jsonRPC'
+};
+
+interface FindTransactionRequest {
+ messageHash: string;
+ network: string;
+}
+
+export const findTransactionHandler = http.post('/api/find_transaction', async ({ request }) => {
+ try {
+ const body = await request.json() as FindTransactionRequest;
+
+ const endpoint = ENDPOINTS[body.network];
+ if (!endpoint) {
+ return HttpResponse.json(
+ { error: 'Unknown network' },
+ { status: 400 }
+ );
+ }
+
+ // This is a simplified implementation for demo purposes.
+ // In production, you would use an indexer service like toncenter.com or tonapi.io
+ // to search for transactions by normalized hash (TEP-467).
+ //
+ // The normalized hash is computed from the external message by:
+ // 1. Removing the init (stateInit)
+ // 2. Setting importFee to 0
+ // 3. Removing the src address
+ // 4. Storing with forceRef: true
+ // 5. Computing cell hash
+
+ return HttpResponse.json({
+ found: false,
+ message: 'Transaction search by normalized hash is not fully implemented in demo. Use an indexer service like toncenter.com or tonapi.io for production.',
+ searchedHash: body.messageHash,
+ network: body.network
+ });
+ } catch (e) {
+ console.error('find_transaction error:', e);
+ return HttpResponse.json(
+ { error: 'Failed to find transaction' },
+ { status: 500 }
+ );
+ }
+});
diff --git a/apps/tonconnect-demo/src/server/handlers/generate-payload.ts b/apps/tonconnect-demo/src/server/handlers/generate-payload.ts
new file mode 100644
index 000000000..a6cc0a22d
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/handlers/generate-payload.ts
@@ -0,0 +1,24 @@
+import { http, HttpResponse } from 'msw';
+import { sha256 } from '@ton/crypto';
+import { generateRandomBytes } from '../services/ton-proof.service';
+import { createPayloadToken } from '../utils/jwt';
+
+export const generatePayloadHandler = http.post('/api/generate_payload', async () => {
+ try {
+ const randomBytes = await generateRandomBytes();
+ const payloadToken = await createPayloadToken({
+ randomBytes: randomBytes.toString('hex')
+ });
+ const payloadTokenHash = (await sha256(payloadToken)).toString('hex');
+
+ return HttpResponse.json({
+ payloadToken,
+ payloadTokenHash
+ });
+ } catch {
+ return HttpResponse.json(
+ { error: 'Failed to generate payload' },
+ { status: 500 }
+ );
+ }
+});
diff --git a/apps/tonconnect-demo/src/server/handlers/get-account-info.ts b/apps/tonconnect-demo/src/server/handlers/get-account-info.ts
new file mode 100644
index 000000000..195520793
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/handlers/get-account-info.ts
@@ -0,0 +1,48 @@
+import { http, HttpResponse } from 'msw';
+import { verifyToken, decodeAuthToken } from '../utils/jwt';
+import { TonApiService } from '../services/ton-api.service';
+
+export const getAccountInfoHandler = http.get('/api/get_account_info', async ({ request }) => {
+ try {
+ // Get token from Authorization header
+ const authHeader = request.headers.get('Authorization');
+ if (!authHeader?.startsWith('Bearer ')) {
+ return HttpResponse.json(
+ { error: 'Missing authorization token' },
+ { status: 401 }
+ );
+ }
+
+ const token = authHeader.slice(7);
+
+ // Verify token
+ const isValid = await verifyToken(token);
+ if (!isValid) {
+ return HttpResponse.json(
+ { error: 'Invalid or expired token' },
+ { status: 401 }
+ );
+ }
+
+ // Decode token to get address and network
+ const decoded = decodeAuthToken(token);
+ if (!decoded) {
+ return HttpResponse.json(
+ { error: 'Could not decode token' },
+ { status: 401 }
+ );
+ }
+
+ // Get account info
+ const tonApi = new TonApiService(decoded.network);
+ const accountInfo = await tonApi.getAccountInfo(decoded.address);
+
+ return HttpResponse.json(accountInfo);
+ } catch (e) {
+ console.error('get_account_info error:', e);
+ return HttpResponse.json(
+ { error: 'Failed to get account info' },
+ { status: 500 }
+ );
+ }
+});
diff --git a/apps/tonconnect-demo/src/server/handlers/index.ts b/apps/tonconnect-demo/src/server/handlers/index.ts
new file mode 100644
index 000000000..13ce45b65
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/handlers/index.ts
@@ -0,0 +1,13 @@
+import { generatePayloadHandler } from './generate-payload';
+import { checkProofHandler } from './check-proof';
+import { checkSignDataHandler } from './check-sign-data';
+import { getAccountInfoHandler } from './get-account-info';
+import { findTransactionHandler } from './find-transaction';
+
+export const handlers = [
+ generatePayloadHandler,
+ checkProofHandler,
+ checkSignDataHandler,
+ getAccountInfoHandler,
+ findTransactionHandler
+];
diff --git a/apps/tonconnect-demo/src/server/index.ts b/apps/tonconnect-demo/src/server/index.ts
new file mode 100644
index 000000000..e81077f2e
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/index.ts
@@ -0,0 +1,15 @@
+import { setupWorker } from 'msw/browser';
+import { handlers } from './handlers';
+
+export const worker = setupWorker(...handlers);
+
+export async function startMockServer(): Promise {
+ await worker.start({
+ serviceWorker: {
+ url: `${import.meta.env.BASE_URL}mockServiceWorker.js`,
+ },
+ onUnhandledRequest: 'bypass',
+ quiet: true,
+ });
+ console.log('[MSW] Mock server started');
+}
diff --git a/apps/tonconnect-demo/src/server/services/ton-api.service.ts b/apps/tonconnect-demo/src/server/services/ton-api.service.ts
new file mode 100644
index 000000000..4e119c424
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/services/ton-api.service.ts
@@ -0,0 +1,40 @@
+import { Address, TonClient4 } from '@ton/ton';
+import { CHAIN } from '@tonconnect/ui-react';
+import { Buffer } from 'buffer';
+
+const ENDPOINTS: Record = {
+ [CHAIN.MAINNET]: 'https://mainnet-v4.tonhubapi.com',
+ [CHAIN.TESTNET]: 'https://testnet-v4.tonhubapi.com'
+};
+
+export class TonApiService {
+ private readonly client: TonClient4;
+
+ constructor(network: string) {
+ const endpoint = ENDPOINTS[network];
+ if (!endpoint) {
+ throw new Error(`Unknown network: ${network}`);
+ }
+ this.client = new TonClient4({ endpoint });
+ }
+
+ async getWalletPublicKey(address: string): Promise {
+ try {
+ const masterAt = await this.client.getLastBlock();
+ const result = await this.client.runMethod(
+ masterAt.last.seqno,
+ Address.parse(address),
+ 'get_public_key',
+ []
+ );
+ return Buffer.from(result.reader.readBigNumber().toString(16).padStart(64, '0'), 'hex');
+ } catch {
+ return null;
+ }
+ }
+
+ async getAccountInfo(address: string) {
+ const masterAt = await this.client.getLastBlock();
+ return await this.client.getAccount(masterAt.last.seqno, Address.parse(address));
+ }
+}
diff --git a/apps/tonconnect-demo/src/server/services/ton-proof.service.ts b/apps/tonconnect-demo/src/server/services/ton-proof.service.ts
new file mode 100644
index 000000000..0b42827a5
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/services/ton-proof.service.ts
@@ -0,0 +1,146 @@
+import { getSecureRandomBytes, sha256 } from '@ton/crypto';
+import { Address, Cell, contractAddress, loadStateInit } from '@ton/ton';
+import { Buffer } from 'buffer';
+import { sign } from 'tweetnacl';
+import { tryParsePublicKey } from '../utils/wallet-parsers';
+
+const tonProofPrefix = 'ton-proof-item-v2/';
+const tonConnectPrefix = 'ton-connect';
+
+// For demo - allow any domain (in production you should whitelist specific domains)
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+const isAllowedDomain = (_domain: string): boolean => {
+ return true;
+};
+
+const validAuthTime = 15 * 60; // 15 minutes
+
+export interface CheckProofPayload {
+ address: string;
+ public_key: string;
+ proof: {
+ timestamp: number;
+ domain: {
+ lengthBytes: number;
+ value: string;
+ };
+ payload: string;
+ signature: string;
+ state_init: string;
+ };
+}
+
+export async function generateRandomBytes(): Promise {
+ return await getSecureRandomBytes(32);
+}
+
+export interface ProofChecks {
+ publicKeyMatch: boolean
+ addressMatch: boolean
+ domainAllowed: boolean
+ timestampValid: boolean
+ signatureValid: boolean
+}
+
+export interface CheckProofResult {
+ valid: boolean
+ checks: ProofChecks
+ error?: string
+}
+
+export async function checkProof(
+ payload: CheckProofPayload,
+ getWalletPublicKey: (address: string) => Promise
+): Promise {
+ const result = await checkProofDetailed(payload, getWalletPublicKey);
+ return result.valid;
+}
+
+export async function checkProofDetailed(
+ payload: CheckProofPayload,
+ getWalletPublicKey: (address: string) => Promise
+): Promise {
+ const checks: ProofChecks = {
+ publicKeyMatch: false,
+ addressMatch: false,
+ domainAllowed: false,
+ timestampValid: false,
+ signatureValid: false
+ };
+
+ try {
+ const stateInit = loadStateInit(Cell.fromBase64(payload.proof.state_init).beginParse());
+
+ // Try to get public key from stateInit first, then from blockchain
+ const publicKey = tryParsePublicKey(stateInit) ?? (await getWalletPublicKey(payload.address));
+ if (!publicKey) {
+ return { valid: false, checks, error: 'Could not get public key' };
+ }
+
+ // Check public key matches
+ const wantedPublicKey = Buffer.from(payload.public_key, 'hex');
+ checks.publicKeyMatch = publicKey.equals(wantedPublicKey);
+
+ // Check address matches stateInit
+ const wantedAddress = Address.parse(payload.address);
+ const address = contractAddress(wantedAddress.workChain, stateInit);
+ checks.addressMatch = address.equals(wantedAddress);
+
+ // Check domain is allowed
+ checks.domainAllowed = isAllowedDomain(payload.proof.domain.value);
+
+ // Check timestamp
+ const now = Math.floor(Date.now() / 1000);
+ checks.timestampValid = now - validAuthTime <= payload.proof.timestamp;
+
+ // Build message for verification
+ const wc = Buffer.alloc(4);
+ wc.writeUInt32BE(address.workChain, 0);
+
+ const ts = Buffer.alloc(8);
+ ts.writeBigUInt64LE(BigInt(payload.proof.timestamp), 0);
+
+ const dl = Buffer.alloc(4);
+ dl.writeUInt32LE(payload.proof.domain.lengthBytes, 0);
+
+ const msg = Buffer.concat([
+ Buffer.from(tonProofPrefix),
+ wc,
+ address.hash,
+ dl,
+ Buffer.from(payload.proof.domain.value),
+ ts,
+ Buffer.from(payload.proof.payload)
+ ]);
+
+ const msgHash = Buffer.from(await sha256(msg));
+
+ const fullMsg = Buffer.concat([
+ Buffer.from([0xff, 0xff]),
+ Buffer.from(tonConnectPrefix),
+ msgHash
+ ]);
+
+ const result = Buffer.from(await sha256(fullMsg));
+ const signature = Buffer.from(payload.proof.signature, 'base64');
+
+ checks.signatureValid = sign.detached.verify(result, signature, publicKey);
+
+ // Determine overall validity and error message
+ const valid = Object.values(checks).every(Boolean);
+ let error: string | undefined;
+
+ if (!valid) {
+ if (!checks.publicKeyMatch) error = 'Public key mismatch';
+ else if (!checks.addressMatch) error = 'Address mismatch';
+ else if (!checks.domainAllowed) error = 'Domain not allowed';
+ else if (!checks.timestampValid) error = 'Proof expired (older than 15 minutes)';
+ else if (!checks.signatureValid) error = 'Invalid signature';
+ }
+
+ return { valid, checks, error };
+ } catch (e) {
+ console.error('checkProof error:', e);
+ return { valid: false, checks, error: 'Verification failed' };
+ }
+}
diff --git a/apps/tonconnect-demo/src/server/utils/jwt.ts b/apps/tonconnect-demo/src/server/utils/jwt.ts
new file mode 100644
index 000000000..344f8e43e
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/utils/jwt.ts
@@ -0,0 +1,49 @@
+import { decodeJwt, jwtVerify, SignJWT } from 'jose';
+import type { JWTPayload } from 'jose';
+
+const JWT_SECRET_KEY = 'demo-secret-key';
+
+export type AuthToken = {
+ address: string;
+ network: string;
+};
+
+export type PayloadToken = {
+ randomBytes: string;
+};
+
+const encoder = new TextEncoder();
+const key = encoder.encode(JWT_SECRET_KEY);
+
+export async function createAuthToken(payload: AuthToken): Promise {
+ return new SignJWT(payload as unknown as JWTPayload)
+ .setProtectedHeader({ alg: 'HS256' })
+ .setIssuedAt()
+ .setExpirationTime('1Y')
+ .sign(key);
+}
+
+export async function createPayloadToken(payload: PayloadToken): Promise {
+ return new SignJWT(payload as unknown as JWTPayload)
+ .setProtectedHeader({ alg: 'HS256' })
+ .setIssuedAt()
+ .setExpirationTime('15m')
+ .sign(key);
+}
+
+export async function verifyToken(token: string): Promise {
+ try {
+ const { payload } = await jwtVerify(token, key);
+ return payload;
+ } catch {
+ return null;
+ }
+}
+
+export function decodeAuthToken(token: string): AuthToken | null {
+ try {
+ return decodeJwt(token) as unknown as AuthToken;
+ } catch {
+ return null;
+ }
+}
diff --git a/apps/tonconnect-demo/src/server/utils/wallet-parsers.ts b/apps/tonconnect-demo/src/server/utils/wallet-parsers.ts
new file mode 100644
index 000000000..4d6a54b14
--- /dev/null
+++ b/apps/tonconnect-demo/src/server/utils/wallet-parsers.ts
@@ -0,0 +1,115 @@
+import {
+ Cell,
+ contractAddress,
+ WalletContractV1R1,
+ WalletContractV1R2,
+ WalletContractV1R3,
+ WalletContractV2R1,
+ WalletContractV2R2,
+ WalletContractV3R1,
+ WalletContractV3R2,
+ WalletContractV4 as WalletContractV4R2,
+ WalletContractV5Beta,
+ WalletContractV5R1
+} from '@ton/ton';
+import type { Slice, StateInit } from '@ton/ton';
+import { Buffer } from 'buffer';
+
+// V4R1 wallet with custom code
+class WalletContractV4R1 {
+ static create(args: { workchain: number; publicKey: Buffer; walletId?: number | null }) {
+ const wallet = WalletContractV4R2.create(args);
+ const { data } = wallet.init;
+ const code = Cell.fromBoc(
+ Buffer.from(
+ 'B5EE9C72410215010002F5000114FF00F4A413F4BCF2C80B010201200203020148040504F8F28308D71820D31FD31FD31F02F823BBF263ED44D0D31FD31FD3FFF404D15143BAF2A15151BAF2A205F901541064F910F2A3F80024A4C8CB1F5240CB1F5230CBFF5210F400C9ED54F80F01D30721C0009F6C519320D74A96D307D402FB00E830E021C001E30021C002E30001C0039130E30D03A4C8CB1F12CB1FCBFF1112131403EED001D0D3030171B0915BE021D749C120915BE001D31F218210706C7567BD228210626C6E63BDB022821064737472BDB0925F03E002FA403020FA4401C8CA07CBFFC9D0ED44D0810140D721F404305C810108F40A6FA131B3925F05E004D33FC8258210706C7567BA9131E30D248210626C6E63BAE30004060708020120090A005001FA00F404308210706C7567831EB17080185005CB0527CF165003FA02F40012CB69CB1F5210CB3F0052F8276F228210626C6E63831EB17080185005CB0527CF1624FA0214CB6A13CB1F5230CB3F01FA02F4000092821064737472BA8E3504810108F45930ED44D0810140D720C801CF16F400C9ED54821064737472831EB17080185004CB0558CF1622FA0212CB6ACB1FCB3F9410345F04E2C98040FB000201200B0C0059BD242B6F6A2684080A06B90FA0218470D4080847A4937D29910CE6903E9FF9837812801B7810148987159F31840201580D0E0011B8C97ED44D0D70B1F8003DB29DFB513420405035C87D010C00B23281F2FFF274006040423D029BE84C600201200F100019ADCE76A26840206B90EB85FFC00019AF1DF6A26840106B90EB858FC0006ED207FA00D4D422F90005C8CA0715CBFFC9D077748018C8CB05CB0222CF165005FA0214CB6B12CCCCC971FB00C84014810108F451F2A702006C810108D718C8542025810108F451F2A782106E6F746570748018C8CB05CB025004CF16821005F5E100FA0213CB6A12CB1FC971FB00020072810108D718305202810108F459F2A7F82582106473747270748018C8CB05CB025005CF16821005F5E100FA0214CB6A13CB1F12CB3FC973FB00000AF400C9ED5446A9F34F',
+ 'hex'
+ )
+ )[0]!;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ (wallet as any).init = { data, code };
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ (wallet as any).address = contractAddress(args.workchain, wallet.init);
+ return wallet;
+ }
+}
+
+function loadWalletV1Data(cs: Slice) {
+ const seqno = cs.loadUint(32);
+ const publicKey = cs.loadBuffer(32);
+ return { seqno, publicKey };
+}
+
+function loadWalletV2Data(cs: Slice) {
+ const seqno = cs.loadUint(32);
+ const publicKey = cs.loadBuffer(32);
+ return { seqno, publicKey };
+}
+
+function loadWalletV3Data(cs: Slice) {
+ const seqno = cs.loadUint(32);
+ const walletId = cs.loadUint(32);
+ const publicKey = cs.loadBuffer(32);
+ return { seqno, publicKey, walletId };
+}
+
+function loadWalletV4Data(cs: Slice) {
+ const seqno = cs.loadUint(32);
+ const walletId = cs.loadUint(32);
+ const publicKey = cs.loadBuffer(32);
+ const plugins = cs.loadMaybeRef();
+ return { seqno, publicKey, walletId, plugins };
+}
+
+function loadWalletV5BetaData(cs: Slice) {
+ const isSignatureAuthAllowed = cs.loadBoolean();
+ const seqno = cs.loadUint(32);
+ const walletId = cs.loadUintBig(80);
+ const publicKey = cs.loadBuffer(32);
+ const plugins = cs.loadMaybeRef();
+ return { isSignatureAuthAllowed, seqno, publicKey, walletId, plugins };
+}
+
+function loadWalletV5Data(cs: Slice) {
+ const isSignatureAuthAllowed = cs.loadBoolean();
+ const seqno = cs.loadUint(32);
+ const walletId = cs.loadUint(32);
+ const publicKey = cs.loadBuffer(32);
+ const plugins = cs.loadMaybeRef();
+ return { isSignatureAuthAllowed, seqno, publicKey, walletId, plugins };
+}
+
+const knownWallets = [
+ { contract: WalletContractV1R1, loadData: loadWalletV1Data },
+ { contract: WalletContractV1R2, loadData: loadWalletV1Data },
+ { contract: WalletContractV1R3, loadData: loadWalletV1Data },
+ { contract: WalletContractV2R1, loadData: loadWalletV2Data },
+ { contract: WalletContractV2R2, loadData: loadWalletV2Data },
+ { contract: WalletContractV3R1, loadData: loadWalletV3Data },
+ { contract: WalletContractV3R2, loadData: loadWalletV3Data },
+ { contract: WalletContractV4R1, loadData: loadWalletV4Data },
+ { contract: WalletContractV4R2, loadData: loadWalletV4Data },
+ { contract: WalletContractV5Beta, loadData: loadWalletV5BetaData },
+ { contract: WalletContractV5R1, loadData: loadWalletV5Data }
+].map(({ contract, loadData }) => ({
+ loadData,
+ wallet: contract.create({ workchain: 0, publicKey: Buffer.alloc(32) })
+}));
+
+export function tryParsePublicKey(stateInit: StateInit): Buffer | null {
+ if (!stateInit.code || !stateInit.data) {
+ return null;
+ }
+
+ for (const { wallet, loadData } of knownWallets) {
+ try {
+ if (wallet.init.code.equals(stateInit.code)) {
+ return loadData(stateInit.data.beginParse()).publicKey;
+ }
+ } catch {
+ // continue to next wallet type
+ }
+ }
+
+ return null;
+}
diff --git a/apps/tonconnect-demo/src/types/connection-events.ts b/apps/tonconnect-demo/src/types/connection-events.ts
new file mode 100644
index 000000000..64b08df3c
--- /dev/null
+++ b/apps/tonconnect-demo/src/types/connection-events.ts
@@ -0,0 +1,74 @@
+// Connection operation types for the operations log
+
+import type { Feature } from "@tonconnect/sdk"
+
+export type ConnectionOperationType = 'connect' | 'disconnect' | 'restore_session'
+
+// What dApp requested
+export interface ConnectionRequest {
+ items: ('ton_addr' | 'ton_proof')[]
+ payload?: string // Challenge for TonProof
+}
+
+// Wallet account snapshot
+export interface AccountSnapshot {
+ address: string
+ chain: string // '-239' (mainnet) | '-3' (testnet)
+ publicKey?: string
+ walletStateInit?: string
+}
+
+// Wallet device snapshot
+export interface DeviceSnapshot {
+ appName: string
+ appVersion: string
+ platform: string
+ features: Feature[] // Raw SDK features, formatted at display time
+}
+
+// TonProof data from wallet
+export interface TonProofSnapshot {
+ timestamp: number
+ domain: string
+ payload: string
+ signature: string
+}
+
+// What wallet returned
+export interface ConnectionResponse {
+ success: boolean
+ wallet?: {
+ account: AccountSnapshot
+ device: DeviceSnapshot
+ provider: 'http' | 'injected'
+ tonProof?: TonProofSnapshot
+ }
+ error?: {
+ code: number
+ message: string
+ }
+}
+
+// Full connection operation
+export interface ConnectionOperation {
+ id: string
+ timestamp: number
+ type: ConnectionOperationType
+
+ // Request/Response pair
+ request: ConnectionRequest | null
+ response: ConnectionResponse | null
+
+ // For disconnect
+ initiator?: 'dapp' | 'wallet'
+ previousAddress?: string
+ previousWalletName?: string
+
+ // Raw data for JsonViewer
+ rawRequest?: unknown
+ rawResponse?: unknown
+}
+
+// Storage constants
+export const CONNECTION_HISTORY_KEY = 'tc-demo-connection-history'
+export const MAX_OPERATIONS = 50
diff --git a/apps/tonconnect-demo/src/utils/clipboard.ts b/apps/tonconnect-demo/src/utils/clipboard.ts
new file mode 100644
index 000000000..868fd176e
--- /dev/null
+++ b/apps/tonconnect-demo/src/utils/clipboard.ts
@@ -0,0 +1,16 @@
+import { toast } from "sonner"
+
+export async function copyToClipboard(text: string, showToast = true): Promise {
+ try {
+ await navigator.clipboard.writeText(text)
+ if (showToast) {
+ toast.success("Copied to clipboard")
+ }
+ return true
+ } catch {
+ if (showToast) {
+ toast.error("Failed to copy")
+ }
+ return false
+ }
+}
diff --git a/apps/tonconnect-demo/src/utils/connection-formatters.ts b/apps/tonconnect-demo/src/utils/connection-formatters.ts
new file mode 100644
index 000000000..067563663
--- /dev/null
+++ b/apps/tonconnect-demo/src/utils/connection-formatters.ts
@@ -0,0 +1,126 @@
+// Formatters for connection operations log
+
+import type { Feature } from "@tonconnect/sdk"
+
+// ============ FEATURES FORMATTER ============
+
+/**
+ * Deduplicate and format wallet features for display
+ * Converts raw SDK features to human-readable format like "SendTx(4)" or "SignData(text,bin,cell)"
+ */
+export function processFeatures(features: Feature[]): string[] {
+ const seen = new Map()
+
+ for (const feature of features) {
+ if (typeof feature === 'string') {
+ if (!seen.has(feature)) {
+ seen.set(feature, feature)
+ }
+ } else {
+ const f = feature as { name: string; maxMessages?: number; extraCurrencySupported?: boolean; types?: string[] }
+ let formatted = f.name
+
+ if (f.name === 'SendTransaction') {
+ const details: string[] = []
+ if (f.maxMessages) details.push(`${f.maxMessages}`)
+ if (f.extraCurrencySupported) details.push('extra')
+ formatted = details.length > 0 ? `SendTx(${details.join(',')})` : 'SendTx'
+ } else if (f.name === 'SignData' && f.types) {
+ const types = f.types.map(t => t === 'binary' ? 'bin' : t)
+ formatted = `SignData(${types.join(',')})`
+ }
+
+ seen.set(f.name, formatted)
+ }
+ }
+
+ return Array.from(seen.values())
+}
+
+// ============ TIME FORMATTERS ============
+
+export function formatOperationTime(timestamp: number): string {
+ return new Date(timestamp).toLocaleTimeString('en-US', {
+ hour12: false,
+ hour: '2-digit',
+ minute: '2-digit',
+ second: '2-digit'
+ })
+}
+
+export function formatRelativeTime(timestamp: number): string {
+ const now = Date.now()
+ const diff = now - timestamp
+
+ if (diff < 60000) return 'just now'
+ if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`
+ if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`
+
+ return new Date(timestamp).toLocaleDateString([], { month: 'short', day: 'numeric' })
+}
+
+// ============ ADDRESS FORMATTERS ============
+
+export function formatAddress(address: string, prefixLen = 6, suffixLen = 4): string {
+ if (!address) return ''
+ if (address.length <= prefixLen + suffixLen + 3) return address
+ return `${address.slice(0, prefixLen)}...${address.slice(-suffixLen)}`
+}
+
+// ============ CHAIN/NETWORK FORMATTERS ============
+
+export function formatChainName(chain: string): string {
+ const chains: Record = {
+ '-239': 'Mainnet',
+ '-3': 'Testnet'
+ }
+ return chains[chain] || `Chain ${chain}`
+}
+
+export function formatChainShort(chain: string): string {
+ return chain === '-239' ? 'mainnet' : chain === '-3' ? 'testnet' : chain
+}
+
+export function isTestnet(chain: string): boolean {
+ return chain === '-3'
+}
+
+// ============ DEVICE FORMATTERS ============
+
+export function formatPlatformName(platform: string): string {
+ const platforms: Record = {
+ 'iphone': 'iOS',
+ 'ipad': 'iOS',
+ 'android': 'Android',
+ 'windows': 'Windows',
+ 'mac': 'macOS',
+ 'linux': 'Linux',
+ 'browser': 'Browser'
+ }
+ return platforms[platform] || platform
+}
+
+export function formatProvider(provider: 'http' | 'injected'): string {
+ return provider === 'injected' ? 'Extension' : 'Bridge'
+}
+
+// ============ PROOF TIMESTAMP ============
+
+export function formatProofTimestamp(timestamp: number): string {
+ return new Date(timestamp * 1000).toLocaleString('en-US', {
+ hour12: false,
+ hour: '2-digit',
+ minute: '2-digit',
+ second: '2-digit'
+ })
+}
+
+// ============ ITEMS FORMATTER ============
+
+export function formatItems(items: string[]): string {
+ return items.map(item => {
+ if (item === 'ton_addr') return 'ton_addr'
+ if (item === 'ton_proof') return 'ton_proof'
+ return item
+ }).join(', ')
+}
diff --git a/apps/tonconnect-demo/src/utils/explorer-utils.ts b/apps/tonconnect-demo/src/utils/explorer-utils.ts
new file mode 100644
index 000000000..15a7f1ce9
--- /dev/null
+++ b/apps/tonconnect-demo/src/utils/explorer-utils.ts
@@ -0,0 +1,4 @@
+export function getExplorerUrl(hash: string, network: "mainnet" | "testnet"): string {
+ const prefix = network === "testnet" ? "testnet." : ""
+ return `https://${prefix}tonviewer.com/transaction/${hash}`
+}
diff --git a/apps/tonconnect-demo/src/utils/sign-data-verification.ts b/apps/tonconnect-demo/src/utils/sign-data-verification.ts
new file mode 100644
index 000000000..cdce004b6
--- /dev/null
+++ b/apps/tonconnect-demo/src/utils/sign-data-verification.ts
@@ -0,0 +1,175 @@
+import { Address, Cell, beginCell, loadStateInit, contractAddress } from "@ton/core"
+import { sha256 } from "@ton/crypto"
+import nacl from "tweetnacl"
+import crc32 from "crc-32"
+import { tryParsePublicKey } from "@/server/utils/wallet-parsers"
+
+interface SignDataResponse {
+ signature: string
+ timestamp: number
+ domain: string
+ payload: {
+ type: "text" | "binary" | "cell"
+ text?: string
+ bytes?: string
+ schema?: string
+ cell?: string
+ }
+}
+
+interface VerificationParams {
+ response: SignDataResponse
+ address: string
+ publicKey: string
+ walletStateInit: string
+}
+
+export interface VerificationResult {
+ valid: boolean
+ message: string
+ details?: {
+ addressMatch: boolean
+ publicKeyMatch: boolean
+ signatureValid: boolean
+ }
+}
+
+/**
+ * Client-side verification of sign-data response.
+ * Note: For production, verification should be done on the server.
+ */
+export async function verifySignData(params: VerificationParams): Promise {
+ try {
+ const { response, address, publicKey, walletStateInit } = params
+ const { signature, timestamp, domain, payload } = response
+
+ // Parse address
+ const parsedAddr = Address.parse(address)
+
+ // Parse stateInit and verify address
+ const stateInit = loadStateInit(Cell.fromBase64(walletStateInit).beginParse())
+ const computedAddress = contractAddress(parsedAddr.workChain, stateInit)
+ const addressMatch = computedAddress.equals(parsedAddr)
+
+ if (!addressMatch) {
+ return {
+ valid: false,
+ message: "Address does not match wallet state init",
+ details: { addressMatch: false, publicKeyMatch: false, signatureValid: false }
+ }
+ }
+
+ // Get public key from stateInit
+ const extractedPublicKey = tryParsePublicKey(stateInit)
+ const providedPublicKey = Buffer.from(publicKey, "hex")
+
+ const publicKeyMatch = extractedPublicKey
+ ? extractedPublicKey.equals(providedPublicKey)
+ : true // If we can't extract, trust the provided key
+
+ // Build hash based on payload type
+ let hash: Buffer
+ if (payload.type === "cell" && payload.schema && payload.cell) {
+ hash = createCellHash(payload as { type: "cell"; schema: string; cell: string }, parsedAddr, domain, timestamp)
+ } else {
+ hash = await createTextBinaryHash(payload, parsedAddr, domain, timestamp)
+ }
+
+ // Verify signature
+ const signatureValid = nacl.sign.detached.verify(
+ new Uint8Array(hash),
+ new Uint8Array(Buffer.from(signature, "base64")),
+ new Uint8Array(providedPublicKey)
+ )
+
+ return {
+ valid: addressMatch && signatureValid,
+ message: signatureValid ? "Signature verified successfully" : "Invalid signature",
+ details: { addressMatch, publicKeyMatch, signatureValid }
+ }
+ } catch (error) {
+ return {
+ valid: false,
+ message: error instanceof Error ? error.message : "Verification failed"
+ }
+ }
+}
+
+async function createTextBinaryHash(
+ payload: { type: "text" | "binary" | "cell"; text?: string; bytes?: string },
+ parsedAddr: Address,
+ domain: string,
+ timestamp: number
+): Promise {
+ // Workchain buffer
+ const wcBuffer = Buffer.alloc(4)
+ wcBuffer.writeInt32BE(parsedAddr.workChain)
+
+ // Domain buffer
+ const domainBuffer = Buffer.from(domain, "utf8")
+ const domainLenBuffer = Buffer.alloc(4)
+ domainLenBuffer.writeUInt32BE(domainBuffer.length)
+
+ // Timestamp buffer
+ const tsBuffer = Buffer.alloc(8)
+ tsBuffer.writeBigUInt64BE(BigInt(timestamp))
+
+ // Payload buffer
+ const typePrefix = payload.type === "text" ? "txt" : "bin"
+ const content = payload.type === "text" ? payload.text || "" : payload.bytes || ""
+ const encoding = payload.type === "text" ? "utf8" : "base64"
+
+ const payloadPrefix = Buffer.from(typePrefix)
+ const payloadBuffer = Buffer.from(content, encoding as BufferEncoding)
+ const payloadLenBuffer = Buffer.alloc(4)
+ payloadLenBuffer.writeUInt32BE(payloadBuffer.length)
+
+ // Build message
+ const message = Buffer.concat([
+ Buffer.from([0xff, 0xff]),
+ Buffer.from("ton-connect/sign-data/"),
+ wcBuffer,
+ parsedAddr.hash,
+ domainLenBuffer,
+ domainBuffer,
+ tsBuffer,
+ payloadPrefix,
+ payloadLenBuffer,
+ payloadBuffer
+ ])
+
+ const hash = await sha256(message)
+ return Buffer.from(hash)
+}
+
+function createCellHash(
+ payload: { type: "cell"; schema: string; cell: string },
+ parsedAddr: Address,
+ domain: string,
+ timestamp: number
+): Buffer {
+ const cell = Cell.fromBase64(payload.cell)
+ const schemaHash = crc32.buf(Buffer.from(payload.schema, "utf8")) >>> 0
+
+ // Encode domain DNS-like
+ const parts = domain.split(".").reverse()
+ const encoded: number[] = []
+ for (const part of parts) {
+ for (let i = 0; i < part.length; i++) {
+ encoded.push(part.charCodeAt(i))
+ }
+ encoded.push(0)
+ }
+ const encodedDomain = Buffer.from(encoded)
+
+ const message = beginCell()
+ .storeUint(0x75569022, 32)
+ .storeUint(schemaHash, 32)
+ .storeUint(timestamp, 64)
+ .storeAddress(parsedAddr)
+ .storeStringRefTail(encodedDomain.toString("utf8"))
+ .storeRef(cell)
+ .endCell()
+
+ return Buffer.from(message.hash())
+}
diff --git a/apps/tonconnect-demo/src/utils/transaction-utils.ts b/apps/tonconnect-demo/src/utils/transaction-utils.ts
new file mode 100644
index 000000000..002947ed3
--- /dev/null
+++ b/apps/tonconnect-demo/src/utils/transaction-utils.ts
@@ -0,0 +1,27 @@
+import { Cell, loadMessage, beginCell, storeMessage } from "@ton/core"
+
+/**
+ * Generates a normalized hash of an "external-in" message for comparison.
+ * Follows TEP-467.
+ */
+export function getNormalizedExtMessageHash(boc: string): string {
+ const cell = Cell.fromBase64(boc)
+ const message = loadMessage(cell.beginParse())
+
+ if (message.info.type !== "external-in") {
+ throw new Error(`Message must be "external-in", got ${message.info.type}`)
+ }
+
+ const info = { ...message.info, src: undefined, importFee: 0n }
+ const normalizedMessage = {
+ ...message,
+ init: null,
+ info: info,
+ }
+
+ return beginCell()
+ .store(storeMessage(normalizedMessage, { forceRef: true }))
+ .endCell()
+ .hash()
+ .toString("hex")
+}
diff --git a/apps/tonconnect-demo/src/utils/validator.ts b/apps/tonconnect-demo/src/utils/validator.ts
new file mode 100644
index 000000000..cf552343c
--- /dev/null
+++ b/apps/tonconnect-demo/src/utils/validator.ts
@@ -0,0 +1,74 @@
+import Ajv from "ajv"
+import transactionSchema from "@/schemas/transaction.schema.json"
+import signDataSchema from "@/schemas/sign-data.schema.json"
+
+const ajv = new Ajv({ allErrors: true, verbose: true })
+
+// Compile schemas
+const validateTransaction = ajv.compile(transactionSchema)
+const validateSignData = ajv.compile(signDataSchema)
+
+export interface ValidationError {
+ path: string
+ message: string
+}
+
+export interface ValidationResult {
+ valid: boolean
+ errors: ValidationError[]
+}
+
+function formatErrors(errors: typeof validateTransaction.errors): ValidationError[] {
+ if (!errors) return []
+
+ return errors.map((error) => ({
+ path: error.instancePath || "/",
+ message: error.message || "Invalid value",
+ }))
+}
+
+export function validateTransactionJson(json: string): ValidationResult {
+ try {
+ const data = JSON.parse(json)
+ const valid = validateTransaction(data)
+
+ return {
+ valid: !!valid,
+ errors: formatErrors(validateTransaction.errors),
+ }
+ } catch {
+ return {
+ valid: false,
+ errors: [{ path: "/", message: "Invalid JSON syntax" }],
+ }
+ }
+}
+
+export function validateSignDataJson(json: string): ValidationResult {
+ try {
+ const data = JSON.parse(json)
+
+ // Extract payload from method/params wrapper if present
+ const payload = data.params?.[0] ?? data
+
+ const valid = validateSignData(payload)
+
+ return {
+ valid: !!valid,
+ errors: formatErrors(validateSignData.errors),
+ }
+ } catch {
+ return {
+ valid: false,
+ errors: [{ path: "/", message: "Invalid JSON syntax" }],
+ }
+ }
+}
+
+export function parseJsonSafe(json: string): { data: T | null; error: string | null } {
+ try {
+ return { data: JSON.parse(json) as T, error: null }
+ } catch {
+ return { data: null, error: "Invalid JSON syntax" }
+ }
+}
diff --git a/apps/tonconnect-demo/tailwind.config.js b/apps/tonconnect-demo/tailwind.config.js
new file mode 100644
index 000000000..3468bbbde
--- /dev/null
+++ b/apps/tonconnect-demo/tailwind.config.js
@@ -0,0 +1,76 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ darkMode: ['class'],
+ content: [
+ './pages/**/*.{ts,tsx}',
+ './components/**/*.{ts,tsx}',
+ './app/**/*.{ts,tsx}',
+ './src/**/*.{ts,tsx}'
+ ],
+ theme: {
+ container: {
+ center: true,
+ padding: '2rem',
+ screens: {
+ '2xl': '1400px'
+ }
+ },
+ extend: {
+ colors: {
+ border: 'hsl(var(--border))',
+ input: 'hsl(var(--input))',
+ ring: 'hsl(var(--ring))',
+ background: 'hsl(var(--background))',
+ foreground: 'hsl(var(--foreground))',
+ primary: {
+ DEFAULT: 'hsl(var(--primary))',
+ foreground: 'hsl(var(--primary-foreground))'
+ },
+ secondary: {
+ DEFAULT: 'hsl(var(--secondary))',
+ foreground: 'hsl(var(--secondary-foreground))'
+ },
+ destructive: {
+ DEFAULT: 'hsl(var(--destructive))',
+ foreground: 'hsl(var(--destructive-foreground))'
+ },
+ muted: {
+ DEFAULT: 'hsl(var(--muted))',
+ foreground: 'hsl(var(--muted-foreground))'
+ },
+ accent: {
+ DEFAULT: 'hsl(var(--accent))',
+ foreground: 'hsl(var(--accent-foreground))'
+ },
+ popover: {
+ DEFAULT: 'hsl(var(--popover))',
+ foreground: 'hsl(var(--popover-foreground))'
+ },
+ card: {
+ DEFAULT: 'hsl(var(--card))',
+ foreground: 'hsl(var(--card-foreground))'
+ }
+ },
+ borderRadius: {
+ lg: 'var(--radius)',
+ md: 'calc(var(--radius) - 2px)',
+ sm: 'calc(var(--radius) - 4px)'
+ },
+ keyframes: {
+ 'accordion-down': {
+ from: { height: '0' },
+ to: { height: 'var(--radix-accordion-content-height)' }
+ },
+ 'accordion-up': {
+ from: { height: 'var(--radix-accordion-content-height)' },
+ to: { height: '0' }
+ }
+ },
+ animation: {
+ 'accordion-down': 'accordion-down 0.2s ease-out',
+ 'accordion-up': 'accordion-up 0.2s ease-out'
+ }
+ }
+ },
+ plugins: [require('tailwindcss-animate')]
+};
diff --git a/apps/tonconnect-demo/tsconfig.app.json b/apps/tonconnect-demo/tsconfig.app.json
new file mode 100644
index 000000000..54f0bdf49
--- /dev/null
+++ b/apps/tonconnect-demo/tsconfig.app.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "types": ["vite/client"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true,
+
+ /* Paths */
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["src"]
+}
diff --git a/apps/tonconnect-demo/tsconfig.json b/apps/tonconnect-demo/tsconfig.json
new file mode 100644
index 000000000..fec8c8e5c
--- /dev/null
+++ b/apps/tonconnect-demo/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ],
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ }
+}
diff --git a/apps/tonconnect-demo/tsconfig.node.json b/apps/tonconnect-demo/tsconfig.node.json
new file mode 100644
index 000000000..8a67f62f4
--- /dev/null
+++ b/apps/tonconnect-demo/tsconfig.node.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2023",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "types": ["node"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/apps/tonconnect-demo/vite.config.ts b/apps/tonconnect-demo/vite.config.ts
new file mode 100644
index 000000000..3e1d90fbc
--- /dev/null
+++ b/apps/tonconnect-demo/vite.config.ts
@@ -0,0 +1,67 @@
+import { defineConfig, type Plugin } from 'vite';
+import react from '@vitejs/plugin-react';
+import tailwindcss from '@tailwindcss/vite';
+import path from 'path';
+import fs from 'fs';
+
+/**
+ * Generates tonconnect-manifest.json at build time.
+ *
+ * Environment variables:
+ * VITE_APP_URL - Full URL (e.g., https://user.github.io/repo/)
+ *
+ * For local development, defaults to http://localhost:5173
+ */
+function generateManifest(): Plugin {
+ const createManifest = (appUrl: string) => ({
+ url: appUrl,
+ name: 'TonConnect Demo',
+ iconUrl: `${appUrl}/favicon.png`,
+ termsOfUseUrl: `${appUrl}/terms-of-use.txt`,
+ privacyPolicyUrl: `${appUrl}/privacy-policy.txt`
+ });
+
+ return {
+ name: 'generate-tonconnect-manifest',
+ // Serve dynamic manifest in dev mode
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === '/tonconnect-manifest.json') {
+ const manifest = createManifest('http://localhost:5173');
+ res.setHeader('Content-Type', 'application/json');
+ res.end(JSON.stringify(manifest, null, 2));
+ return;
+ }
+ next();
+ });
+ },
+ // Generate manifest file at build time
+ writeBundle(options) {
+ const appUrl = (process.env.VITE_APP_URL || 'http://localhost:5173').replace(/\/$/, '');
+ const outDir = options.dir || 'dist';
+
+ fs.writeFileSync(
+ path.join(outDir, 'tonconnect-manifest.json'),
+ JSON.stringify(createManifest(appUrl), null, 2)
+ );
+
+ console.log(`Generated tonconnect-manifest.json for ${appUrl}`);
+ }
+ };
+}
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ // Base path for GitHub Pages deployment (e.g., /repo/ or /repo/branch/)
+ base: process.env.VITE_BASE_PATH || '/',
+ plugins: [react(), tailwindcss(), generateManifest()],
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './src')
+ },
+ dedupe: ['react', 'react-dom']
+ },
+ server: {
+ allowedHosts: true
+ }
+});
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 63a697d9e..dd7656f1d 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -25,7 +25,7 @@ export default [
// Ignore patterns
{
- ignores: ['**/*.js', '**/node_modules/**', '**/dist/**', '**/lib/**', '**/types/**'],
+ ignores: ['**/*.js', '**/node_modules/**', '**/dist/**', '**/lib/**', '**/types/**', 'apps/tonconnect-demo/**'],
},
// Base JavaScript configuration
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8ae2485c8..0a00a7fb3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -13,7 +13,7 @@ importers:
version: 2.29.5
'@eslint/compat':
specifier: ^1.3.1
- version: 1.3.1(eslint@9.32.0)
+ version: 1.3.1(eslint@9.32.0(jiti@2.6.1))
'@microsoft/api-extractor':
specifier: ^7.52.10
version: 7.52.10(@types/node@24.2.0)
@@ -22,34 +22,34 @@ importers:
version: 24.2.0
'@typescript-eslint/eslint-plugin':
specifier: ^8.39.0
- version: 8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint@9.32.0)(typescript@5.9.2)
+ version: 8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
'@typescript-eslint/parser':
specifier: ^8.39.0
- version: 8.39.0(eslint@9.32.0)(typescript@5.9.2)
+ version: 8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
eslint:
specifier: 9.32.0
- version: 9.32.0
+ version: 9.32.0(jiti@2.6.1)
eslint-import-resolver-typescript:
specifier: ^4.4.4
- version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0))(eslint-plugin-import@2.32.0)(eslint@9.32.0)
+ version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.53.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.6.1))
eslint-plugin-import:
specifier: ^2.26.0
- version: 2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0)
+ version: 2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.32.0))(eslint@9.32.0)(prettier@3.6.2)
+ version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.32.0(jiti@2.6.1)))(eslint@9.32.0(jiti@2.6.1))(prettier@3.6.2)
eslint-plugin-react:
specifier: ^7.37.5
- version: 7.37.5(eslint@9.32.0)
+ version: 7.37.5(eslint@9.32.0(jiti@2.6.1))
eslint-plugin-react-hooks:
specifier: ^5.2.0
- version: 5.2.0(eslint@9.32.0)
+ version: 5.2.0(eslint@9.32.0(jiti@2.6.1))
eslint-plugin-solid:
specifier: ^0.14.5
- version: 0.14.5(eslint@9.32.0)(typescript@5.9.2)
+ version: 0.14.5(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
eslint-plugin-unused-imports:
specifier: ^4.1.4
- version: 4.1.4(@typescript-eslint/eslint-plugin@8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint@9.32.0)(typescript@5.9.2))(eslint@9.32.0)
+ version: 4.1.4(@typescript-eslint/eslint-plugin@8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.6.1))
prettier:
specifier: ^3.6.2
version: 3.6.2
@@ -134,7 +134,7 @@ importers:
version: 19.1.7(@types/react@19.1.9)
'@vitejs/plugin-react':
specifier: ^4.7.0
- version: 4.7.0(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ version: 4.7.0(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
sass:
specifier: ^1.90.0
version: 1.90.0
@@ -143,7 +143,194 @@ importers:
version: 5.9.2
vite:
specifier: ^7.0.6
- version: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ version: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+
+ apps/tonconnect-demo:
+ dependencies:
+ '@codemirror/lang-javascript':
+ specifier: ^6.2.4
+ version: 6.2.4
+ '@codemirror/lang-json':
+ specifier: ^6.0.2
+ version: 6.0.2
+ '@codemirror/language':
+ specifier: ^6.12.1
+ version: 6.12.1
+ '@codemirror/view':
+ specifier: ^6.39.11
+ version: 6.39.11
+ '@hookform/resolvers':
+ specifier: ^5.2.2
+ version: 5.2.2(react-hook-form@7.71.1(react@19.2.3))
+ '@lezer/highlight':
+ specifier: ^1.2.3
+ version: 1.2.3
+ '@radix-ui/react-checkbox':
+ specifier: ^1.3.3
+ version: 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-collapsible':
+ specifier: ^1.1.12
+ version: 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-dialog':
+ specifier: ^1.1.15
+ version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-dropdown-menu':
+ specifier: ^2.1.16
+ version: 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-label':
+ specifier: ^2.1.8
+ version: 2.1.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-scroll-area':
+ specifier: ^1.2.10
+ version: 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-select':
+ specifier: ^2.2.6
+ version: 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-slot':
+ specifier: ^1.2.4
+ version: 1.2.4(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-switch':
+ specifier: ^1.2.6
+ version: 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-tabs':
+ specifier: ^1.1.13
+ version: 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-toast':
+ specifier: ^1.2.15
+ version: 1.2.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@tailwindcss/typography':
+ specifier: ^0.5.19
+ version: 0.5.19(tailwindcss@4.1.18)
+ '@tailwindcss/vite':
+ specifier: ^4.1.18
+ version: 4.1.18(vite@7.3.1(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
+ '@ton/core':
+ specifier: ^0.62.1
+ version: 0.62.1(@ton/crypto@3.3.0)
+ '@ton/crypto':
+ specifier: 3.3.0
+ version: 3.3.0
+ '@ton/ton':
+ specifier: ^16.1.0
+ version: 16.1.0(@ton/core@0.62.1(@ton/crypto@3.3.0))(@ton/crypto@3.3.0)
+ '@tonconnect/sdk':
+ specifier: workspace:*
+ version: link:../../packages/sdk
+ '@tonconnect/ui-react':
+ specifier: workspace:*
+ version: link:../../packages/ui-react
+ '@uiw/react-codemirror':
+ specifier: ^4.25.4
+ version: 4.25.4(@babel/runtime@7.28.6)(@codemirror/autocomplete@6.20.0)(@codemirror/language@6.12.1)(@codemirror/lint@6.9.2)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.39.11)(codemirror@6.0.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ ajv:
+ specifier: ^8.17.1
+ version: 8.17.1
+ ajv-formats:
+ specifier: ^3.0.1
+ version: 3.0.1(ajv@8.17.1)
+ autoprefixer:
+ specifier: ^10.4.23
+ version: 10.4.23(postcss@8.5.6)
+ buffer:
+ specifier: ^6.0.3
+ version: 6.0.3
+ class-variance-authority:
+ specifier: ^0.7.1
+ version: 0.7.1
+ clsx:
+ specifier: ^2.1.1
+ version: 2.1.1
+ crc-32:
+ specifier: ^1.2.2
+ version: 1.2.2
+ eruda:
+ specifier: ^3.4.3
+ version: 3.4.3
+ jose:
+ specifier: ^6.1.3
+ version: 6.1.3
+ lucide-react:
+ specifier: ^0.562.0
+ version: 0.562.0(react@19.2.3)
+ msw:
+ specifier: ^2.12.7
+ version: 2.12.7(@types/node@24.10.8)(typescript@5.9.3)
+ next-themes:
+ specifier: ^0.4.6
+ version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ postcss:
+ specifier: ^8.5.6
+ version: 8.5.6
+ react:
+ specifier: ^19.2.3
+ version: 19.2.3
+ react-dom:
+ specifier: ^19.2.3
+ version: 19.2.3(react@19.2.3)
+ react-markdown:
+ specifier: ^10.1.0
+ version: 10.1.0(@types/react@19.2.8)(react@19.2.3)
+ remark-gfm:
+ specifier: ^4.0.1
+ version: 4.0.1
+ sonner:
+ specifier: ^2.0.7
+ version: 2.0.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ tailwind-merge:
+ specifier: ^3.4.0
+ version: 3.4.0
+ tailwindcss:
+ specifier: ^4.1.18
+ version: 4.1.18
+ tailwindcss-animate:
+ specifier: ^1.0.7
+ version: 1.0.7(tailwindcss@4.1.18)
+ tweetnacl:
+ specifier: ^1.0.3
+ version: 1.0.3
+ yaml:
+ specifier: ^2.8.2
+ version: 2.8.2
+ zod:
+ specifier: ^4.3.5
+ version: 4.3.5
+ devDependencies:
+ '@eslint/js':
+ specifier: ^9.39.1
+ version: 9.39.2
+ '@types/node':
+ specifier: ^24.10.8
+ version: 24.10.8
+ '@types/react':
+ specifier: ^19.2.5
+ version: 19.2.8
+ '@types/react-dom':
+ specifier: ^19.2.3
+ version: 19.2.3(@types/react@19.2.8)
+ '@vitejs/plugin-react':
+ specifier: ^5.1.1
+ version: 5.1.2(vite@7.3.1(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
+ eslint:
+ specifier: ^9.39.1
+ version: 9.39.2(jiti@2.6.1)
+ eslint-plugin-react-hooks:
+ specifier: ^7.0.1
+ version: 7.0.1(eslint@9.39.2(jiti@2.6.1))
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.24
+ version: 0.4.26(eslint@9.39.2(jiti@2.6.1))
+ globals:
+ specifier: ^16.5.0
+ version: 16.5.0
+ typescript:
+ specifier: ~5.9.3
+ version: 5.9.3
+ typescript-eslint:
+ specifier: ^8.46.4
+ version: 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ vite:
+ specifier: ^7.2.4
+ version: 7.3.1(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
packages/isomorphic-eventsource:
dependencies:
@@ -172,7 +359,7 @@ importers:
devDependencies:
'@rollup/plugin-typescript':
specifier: ^12.1.4
- version: 12.1.4(rollup@4.46.2)(tslib@2.8.1)(typescript@5.9.2)
+ version: 12.1.4(rollup@4.46.2)(tslib@2.8.1)(typescript@5.9.3)
'@types/jest':
specifier: ^30.0.0
version: 30.0.0
@@ -181,13 +368,13 @@ importers:
version: 24.2.0
jest:
specifier: ^30.0.5
- version: 30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2))
+ version: 30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3))
rollup:
specifier: ^4.46.2
version: 4.46.2
ts-jest:
specifier: ^29.0.3
- version: 29.4.1(@babel/core@7.28.0)(@jest/transform@30.0.5)(@jest/types@30.0.5)(babel-jest@30.0.5(@babel/core@7.28.0))(jest-util@30.0.5)(jest@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2)))(typescript@5.9.2)
+ version: 29.4.1(@babel/core@7.28.6)(@jest/transform@30.0.5)(@jest/types@30.0.5)(babel-jest@30.0.5(@babel/core@7.28.6))(jest-util@30.0.5)(jest@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3)))(typescript@5.9.3)
packages/sdk:
dependencies:
@@ -206,37 +393,37 @@ importers:
version: 6.0.2(rollup@4.46.2)
'@rollup/plugin-typescript':
specifier: ^12.1.4
- version: 12.1.4(rollup@4.46.2)(tslib@2.8.1)(typescript@5.9.2)
+ version: 12.1.4(rollup@4.46.2)(tslib@2.8.1)(typescript@5.9.3)
'@types/node':
specifier: ^24.2.0
version: 24.2.0
'@vitest/coverage-istanbul':
specifier: 3.2.4
- version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
rollup:
specifier: ^4.46.2
version: 4.46.2
ts-loader:
specifier: ^9.4.1
- version: 9.5.2(typescript@5.9.2)(webpack@5.101.0)
+ version: 9.5.2(typescript@5.9.3)(webpack@5.101.0)
ts-patch:
specifier: ^3.3.0
version: 3.3.0
typescript-transform-paths:
specifier: ^3.3.1
- version: 3.5.5(typescript@5.9.2)
+ version: 3.5.5(typescript@5.9.3)
vite:
specifier: ^7.0.6
- version: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ version: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
vite-tsconfig-paths:
specifier: ^5.1.4
- version: 5.1.4(typescript@5.9.2)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ version: 5.1.4(typescript@5.9.3)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
vitest:
specifier: ^3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
vitest-fetch-mock:
specifier: ^0.4.5
- version: 0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ version: 0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
webpack:
specifier: ^5.75.0
version: 5.101.0(webpack-cli@5.1.4)
@@ -294,7 +481,7 @@ importers:
version: 6.2.1(rollup@4.46.2)(typescript@5.9.2)
solid-devtools:
specifier: ^0.24.7
- version: 0.24.7(@solidjs/meta@0.28.7(solid-js@1.9.7))(@solidjs/router@0.8.4(solid-js@1.9.7))(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ version: 0.24.7(@solidjs/meta@0.28.7(solid-js@1.9.7))(@solidjs/router@0.8.4(solid-js@1.9.7))(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
solid-floating-ui:
specifier: ^0.3.1
version: 0.3.1(@floating-ui/dom@1.7.3)(solid-js@1.9.7)
@@ -312,13 +499,13 @@ importers:
version: 5.9.2
vite:
specifier: ^7.0.6
- version: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ version: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
vite-plugin-solid:
specifier: ^2.11.8
- version: 2.11.8(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ version: 2.11.8(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
vitest:
specifier: ^3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
packages/ui-react:
dependencies:
@@ -340,25 +527,25 @@ importers:
version: 19.1.7(@types/react@19.1.9)
'@vitejs/plugin-react':
specifier: ^4.3.4
- version: 4.7.0(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ version: 4.7.0(vite@7.0.6(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
csstype:
specifier: ^3.1.3
version: 3.1.3
eslint-plugin-react:
specifier: ^7.37.4
- version: 7.37.5(eslint@9.32.0)
+ version: 7.37.5(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react-hooks:
specifier: ^5.2.0
- version: 5.2.0(eslint@9.32.0)
+ version: 5.2.0(eslint@9.39.2(jiti@2.6.1))
typescript:
specifier: ^5.9.2
version: 5.9.2
vite:
specifier: ^7.0.6
- version: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ version: 7.0.6(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
vite-plugin-dts:
specifier: ^4.5.4
- version: 4.5.4(@types/node@24.2.0)(rollup@4.46.2)(typescript@5.9.2)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ version: 4.5.4(@types/node@24.10.8)(rollup@4.46.2)(typescript@5.9.2)(vite@7.0.6(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
packages:
@@ -536,18 +723,34 @@ packages:
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
engines: {node: '>=6.9.0'}
+ '@babel/code-frame@7.28.6':
+ resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==}
+ engines: {node: '>=6.9.0'}
+
'@babel/compat-data@7.28.0':
resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==}
engines: {node: '>=6.9.0'}
+ '@babel/compat-data@7.28.6':
+ resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/core@7.28.0':
resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==}
engines: {node: '>=6.9.0'}
+ '@babel/core@7.28.6':
+ resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/generator@7.28.0':
resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==}
engines: {node: '>=6.9.0'}
+ '@babel/generator@7.28.6':
+ resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-annotate-as-pure@7.27.3':
resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
engines: {node: '>=6.9.0'}
@@ -556,6 +759,10 @@ packages:
resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-compilation-targets@7.28.6':
+ resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-create-class-features-plugin@7.27.1':
resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==}
engines: {node: '>=6.9.0'}
@@ -589,12 +796,22 @@ packages:
resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-module-imports@7.28.6':
+ resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-module-transforms@7.27.3':
resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/helper-module-transforms@7.28.6':
+ resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/helper-optimise-call-expression@7.27.1':
resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==}
engines: {node: '>=6.9.0'}
@@ -627,6 +844,10 @@ packages:
resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-validator-identifier@7.28.5':
+ resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-validator-option@7.27.1':
resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
engines: {node: '>=6.9.0'}
@@ -639,11 +860,20 @@ packages:
resolution: {integrity: sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==}
engines: {node: '>=6.9.0'}
+ '@babel/helpers@7.28.6':
+ resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/parser@7.28.0':
resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==}
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/parser@7.28.6':
+ resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1':
resolution: {integrity: sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==}
engines: {node: '>=6.9.0'}
@@ -1128,18 +1358,34 @@ packages:
resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==}
engines: {node: '>=6.9.0'}
+ '@babel/runtime@7.28.6':
+ resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/template@7.27.2':
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
engines: {node: '>=6.9.0'}
+ '@babel/template@7.28.6':
+ resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
+ engines: {node: '>=6.9.0'}
+
'@babel/traverse@7.28.0':
resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==}
engines: {node: '>=6.9.0'}
+ '@babel/traverse@7.28.6':
+ resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/types@7.28.2':
resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==}
engines: {node: '>=6.9.0'}
+ '@babel/types@7.28.6':
+ resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==}
+ engines: {node: '>=6.9.0'}
+
'@base-org/account@2.4.0':
resolution: {integrity: sha512-A4Umpi8B9/pqR78D1Yoze4xHyQaujioVRqqO3d6xuDFw9VRtjg6tK3bPlwE0aW+nVH/ntllCpPa2PbI8Rnjcug==}
@@ -1210,6 +1456,36 @@ packages:
'@changesets/write@0.4.0':
resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==}
+ '@codemirror/autocomplete@6.20.0':
+ resolution: {integrity: sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==}
+
+ '@codemirror/commands@6.10.1':
+ resolution: {integrity: sha512-uWDWFypNdQmz2y1LaNJzK7fL7TYKLeUAU0npEC685OKTF3KcQ2Vu3klIM78D7I6wGhktme0lh3CuQLv0ZCrD9Q==}
+
+ '@codemirror/lang-javascript@6.2.4':
+ resolution: {integrity: sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==}
+
+ '@codemirror/lang-json@6.0.2':
+ resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==}
+
+ '@codemirror/language@6.12.1':
+ resolution: {integrity: sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ==}
+
+ '@codemirror/lint@6.9.2':
+ resolution: {integrity: sha512-sv3DylBiIyi+xKwRCJAAsBZZZWo82shJ/RTMymLabAdtbkV5cSKwWDeCgtUq3v8flTaXS2y1kKkICuRYtUswyQ==}
+
+ '@codemirror/search@6.6.0':
+ resolution: {integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==}
+
+ '@codemirror/state@6.5.4':
+ resolution: {integrity: sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw==}
+
+ '@codemirror/theme-one-dark@6.1.3':
+ resolution: {integrity: sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==}
+
+ '@codemirror/view@6.39.11':
+ resolution: {integrity: sha512-bWdeR8gWM87l4DB/kYSF9A+dVackzDb/V56Tq7QVrQ7rn86W0rgZFtlL3g3pem6AeGcb9NQNoy3ao4WpW4h5tQ==}
+
'@coinbase/cdp-sdk@1.38.5':
resolution: {integrity: sha512-j8mvx1wMox/q2SjB7C09HtdRXVOpGpfkP7nG4+OjdowPj8pmQ03rigzycd86L8mawl6TUPXdm41YSQVmtc8SzQ==}
@@ -1270,6 +1546,12 @@ packages:
cpu: [ppc64]
os: [aix]
+ '@esbuild/aix-ppc64@0.27.2':
+ resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
'@esbuild/android-arm64@0.17.19':
resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
engines: {node: '>=12'}
@@ -1282,6 +1564,12 @@ packages:
cpu: [arm64]
os: [android]
+ '@esbuild/android-arm64@0.27.2':
+ resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
'@esbuild/android-arm@0.17.19':
resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
engines: {node: '>=12'}
@@ -1294,6 +1582,12 @@ packages:
cpu: [arm]
os: [android]
+ '@esbuild/android-arm@0.27.2':
+ resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
'@esbuild/android-x64@0.17.19':
resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
engines: {node: '>=12'}
@@ -1306,6 +1600,12 @@ packages:
cpu: [x64]
os: [android]
+ '@esbuild/android-x64@0.27.2':
+ resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
'@esbuild/darwin-arm64@0.17.19':
resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
engines: {node: '>=12'}
@@ -1318,6 +1618,12 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@esbuild/darwin-arm64@0.27.2':
+ resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
'@esbuild/darwin-x64@0.17.19':
resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
engines: {node: '>=12'}
@@ -1330,6 +1636,12 @@ packages:
cpu: [x64]
os: [darwin]
+ '@esbuild/darwin-x64@0.27.2':
+ resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
'@esbuild/freebsd-arm64@0.17.19':
resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
engines: {node: '>=12'}
@@ -1342,6 +1654,12 @@ packages:
cpu: [arm64]
os: [freebsd]
+ '@esbuild/freebsd-arm64@0.27.2':
+ resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
'@esbuild/freebsd-x64@0.17.19':
resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
engines: {node: '>=12'}
@@ -1354,6 +1672,12 @@ packages:
cpu: [x64]
os: [freebsd]
+ '@esbuild/freebsd-x64@0.27.2':
+ resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
'@esbuild/linux-arm64@0.17.19':
resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
engines: {node: '>=12'}
@@ -1366,6 +1690,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@esbuild/linux-arm64@0.27.2':
+ resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
'@esbuild/linux-arm@0.17.19':
resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
engines: {node: '>=12'}
@@ -1378,6 +1708,12 @@ packages:
cpu: [arm]
os: [linux]
+ '@esbuild/linux-arm@0.27.2':
+ resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
'@esbuild/linux-ia32@0.17.19':
resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
engines: {node: '>=12'}
@@ -1390,6 +1726,12 @@ packages:
cpu: [ia32]
os: [linux]
+ '@esbuild/linux-ia32@0.27.2':
+ resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
'@esbuild/linux-loong64@0.17.19':
resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
engines: {node: '>=12'}
@@ -1402,6 +1744,12 @@ packages:
cpu: [loong64]
os: [linux]
+ '@esbuild/linux-loong64@0.27.2':
+ resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
'@esbuild/linux-mips64el@0.17.19':
resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
engines: {node: '>=12'}
@@ -1414,6 +1762,12 @@ packages:
cpu: [mips64el]
os: [linux]
+ '@esbuild/linux-mips64el@0.27.2':
+ resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
'@esbuild/linux-ppc64@0.17.19':
resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
engines: {node: '>=12'}
@@ -1426,6 +1780,12 @@ packages:
cpu: [ppc64]
os: [linux]
+ '@esbuild/linux-ppc64@0.27.2':
+ resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
'@esbuild/linux-riscv64@0.17.19':
resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
engines: {node: '>=12'}
@@ -1438,6 +1798,12 @@ packages:
cpu: [riscv64]
os: [linux]
+ '@esbuild/linux-riscv64@0.27.2':
+ resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
'@esbuild/linux-s390x@0.17.19':
resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
engines: {node: '>=12'}
@@ -1450,6 +1816,12 @@ packages:
cpu: [s390x]
os: [linux]
+ '@esbuild/linux-s390x@0.27.2':
+ resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
'@esbuild/linux-x64@0.17.19':
resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
engines: {node: '>=12'}
@@ -1462,12 +1834,24 @@ packages:
cpu: [x64]
os: [linux]
+ '@esbuild/linux-x64@0.27.2':
+ resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
'@esbuild/netbsd-arm64@0.25.8':
resolution: {integrity: sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
+ '@esbuild/netbsd-arm64@0.27.2':
+ resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
'@esbuild/netbsd-x64@0.17.19':
resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
engines: {node: '>=12'}
@@ -1480,12 +1864,24 @@ packages:
cpu: [x64]
os: [netbsd]
+ '@esbuild/netbsd-x64@0.27.2':
+ resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
'@esbuild/openbsd-arm64@0.25.8':
resolution: {integrity: sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
+ '@esbuild/openbsd-arm64@0.27.2':
+ resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
'@esbuild/openbsd-x64@0.17.19':
resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
engines: {node: '>=12'}
@@ -1498,12 +1894,24 @@ packages:
cpu: [x64]
os: [openbsd]
+ '@esbuild/openbsd-x64@0.27.2':
+ resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/openharmony-arm64@0.25.8':
resolution: {integrity: sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
+ '@esbuild/openharmony-arm64@0.27.2':
+ resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
'@esbuild/sunos-x64@0.17.19':
resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
engines: {node: '>=12'}
@@ -1516,6 +1924,12 @@ packages:
cpu: [x64]
os: [sunos]
+ '@esbuild/sunos-x64@0.27.2':
+ resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
'@esbuild/win32-arm64@0.17.19':
resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
engines: {node: '>=12'}
@@ -1528,6 +1942,12 @@ packages:
cpu: [arm64]
os: [win32]
+ '@esbuild/win32-arm64@0.27.2':
+ resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
'@esbuild/win32-ia32@0.17.19':
resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
engines: {node: '>=12'}
@@ -1540,6 +1960,12 @@ packages:
cpu: [ia32]
os: [win32]
+ '@esbuild/win32-ia32@0.27.2':
+ resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
'@esbuild/win32-x64@0.17.19':
resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
engines: {node: '>=12'}
@@ -1552,16 +1978,32 @@ packages:
cpu: [x64]
os: [win32]
+ '@esbuild/win32-x64@0.27.2':
+ resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
'@eslint-community/eslint-utils@4.7.0':
resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+ '@eslint-community/eslint-utils@4.9.1':
+ resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+
'@eslint-community/regexpp@4.12.1':
resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+ '@eslint-community/regexpp@4.12.2':
+ resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+
'@eslint/compat@1.3.1':
resolution: {integrity: sha512-k8MHony59I5EPic6EQTCNOuPoVBnoYXkP+20xvwFjN7t0qI3ImyvyBgg+hIVPwC8JaxVjjUZld+cLfBLFDLucg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1575,14 +2017,26 @@ packages:
resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/config-array@0.21.1':
+ resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@eslint/config-helpers@0.3.0':
resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/config-helpers@0.4.2':
+ resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@eslint/core@0.15.1':
resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/core@0.17.0':
+ resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@eslint/eslintrc@3.3.1':
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1591,14 +2045,26 @@ packages:
resolution: {integrity: sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/js@9.39.2':
+ resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@eslint/object-schema@2.1.6':
resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/object-schema@2.1.7':
+ resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@eslint/plugin-kit@0.3.4':
resolution: {integrity: sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/plugin-kit@0.4.1':
+ resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@fastify/busboy@2.1.1':
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
engines: {node: '>=14'}
@@ -1609,6 +2075,15 @@ packages:
'@floating-ui/dom@1.7.3':
resolution: {integrity: sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==}
+ '@floating-ui/dom@1.7.4':
+ resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==}
+
+ '@floating-ui/react-dom@2.1.6':
+ resolution: {integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==}
+ peerDependencies:
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
+
'@floating-ui/utils@0.2.10':
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
@@ -1621,6 +2096,11 @@ packages:
'@hapi/topo@5.1.0':
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
+ '@hookform/resolvers@5.2.2':
+ resolution: {integrity: sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==}
+ peerDependencies:
+ react-hook-form: ^7.55.0
+
'@humanfs/core@0.19.1':
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
engines: {node: '>=18.18.0'}
@@ -1777,6 +2257,9 @@ packages:
'@jridgewell/gen-mapping@0.3.12':
resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==}
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
@@ -1787,12 +2270,30 @@ packages:
'@jridgewell/sourcemap-codec@1.5.4':
resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==}
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
'@jridgewell/trace-mapping@0.3.29':
resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+ '@lezer/common@1.5.0':
+ resolution: {integrity: sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA==}
+
+ '@lezer/highlight@1.2.3':
+ resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==}
+
+ '@lezer/javascript@1.5.4':
+ resolution: {integrity: sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==}
+
+ '@lezer/json@1.0.3':
+ resolution: {integrity: sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==}
+
+ '@lezer/lr@1.4.7':
+ resolution: {integrity: sha512-wNIFWdSUfX9Jc6ePMzxSPVgTVB4EOfDIwLQLWASyiUdHKaMsiilj9bYiGkGQCKVodd0x6bgQCV207PILGFCF9Q==}
+
'@lit-labs/ssr-dom-shim@1.4.0':
resolution: {integrity: sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==}
@@ -1810,6 +2311,9 @@ packages:
'@manypkg/get-packages@1.1.3':
resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
+ '@marijn/find-cluster-break@1.0.2':
+ resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
+
'@microsoft/api-extractor-model@7.30.7':
resolution: {integrity: sha512-TBbmSI2/BHpfR9YhQA7nH0nqVmGgJ0xH0Ex4D99/qBDAUpnhA2oikGmdXanbw9AWWY/ExBYIpkmY8dBHdla3YQ==}
@@ -1831,6 +2335,10 @@ packages:
resolution: {integrity: sha512-B9nHSJYtsv79uo7QdkZ/b/WoKm20IkVSmTc/WCKarmDtFwM0dRx2ouEniqwNkzCSLn3fydzKmnMzjtfdOWt3VQ==}
engines: {node: '>=18'}
+ '@mswjs/interceptors@0.40.0':
+ resolution: {integrity: sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==}
+ engines: {node: '>=18'}
+
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
@@ -1986,29 +2494,459 @@ packages:
'@polka/url@1.0.0-next.29':
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
- '@reown/appkit-common@1.8.14':
- resolution: {integrity: sha512-0dRNtmy2e7f89Vvx3NCA09PD24DFT6S0nO6a/MBeFOj7SlvkvIh4SjBWG2x2F4L8KxCSCtQ5x6dWREmTONZjMA==}
-
- '@reown/appkit-controllers@1.8.14':
- resolution: {integrity: sha512-1EF3xzwMwNfzZp1yd2InwA01EEDSylwHfX6MuGa1t5M6HevY4p1QnbnZISpYAQxN1xklCQsT3Zq5pQh6Ofg+Cg==}
-
- '@reown/appkit-pay@1.8.14':
- resolution: {integrity: sha512-6ReXMGV47quXax8v1RQ8wFgclSd6M7MhX/WHJGwsjNHjFttQ6xWbPlYmjZxKgZ+k+K2TG/wo7oU0pF5Qu/L7Tw==}
+ '@radix-ui/number@1.1.1':
+ resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
- '@reown/appkit-polyfills@1.8.14':
- resolution: {integrity: sha512-bMMdJpzxni6+FQpMqQomKvXoDy+t9uCunswuKCN33fMRXtXX0A3ui0WMGUFbQ4BKGmQcyUSt/MWid9hZ6KG8Fw==}
+ '@radix-ui/primitive@1.1.3':
+ resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
- '@reown/appkit-scaffold-ui@1.8.14':
- resolution: {integrity: sha512-dhD9vodp1xsVs0yWP2V+b3XkcksHEHNzjNQvXBmTrfDDDpUYiScBTvjKmMRu/MgUxYRrFdxoMDIfAzjYUAwZuw==}
+ '@radix-ui/react-arrow@1.1.7':
+ resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
- '@reown/appkit-ui@1.8.14':
- resolution: {integrity: sha512-vExTPCA8QghLaUG3mM2ghUN7IvTGy/dUbVxGYbCrIG/Y7Srshqp8O/vwnWk5RhktRwMNQuOXCRGXf2lWPiuNWQ==}
+ '@radix-ui/react-checkbox@1.3.3':
+ resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
- '@reown/appkit-universal-connector@1.8.14':
- resolution: {integrity: sha512-Z7aegr4A5T2Bz6A/DEn25eZeXJhxBlj7UqlbXfxX8+SaAjCWSx4WuTAsJFMPQwtGDPGdEIVSe0EAWAHOAX9wqA==}
+ '@radix-ui/react-collapsible@1.1.12':
+ resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
- '@reown/appkit-utils@1.8.14':
- resolution: {integrity: sha512-SuXtX2pr8yilaAdTq7nEj2/ulKMUJAKUbtldAcsl3/acsqfD4oKHi13VJEKsHcGx/43sb1uDXA9yB60/g2+NAQ==}
+ '@radix-ui/react-collection@1.1.7':
+ resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-compose-refs@1.1.2':
+ resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-context@1.1.2':
+ resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-dialog@1.1.15':
+ resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-direction@1.1.1':
+ resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-dismissable-layer@1.1.11':
+ resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-dropdown-menu@2.1.16':
+ resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-focus-guards@1.1.3':
+ resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-focus-scope@1.1.7':
+ resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-id@1.1.1':
+ resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-label@2.1.8':
+ resolution: {integrity: sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-menu@2.1.16':
+ resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-popper@1.2.8':
+ resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-portal@1.1.9':
+ resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-presence@1.1.5':
+ resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-primitive@2.1.3':
+ resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-primitive@2.1.4':
+ resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-roving-focus@1.1.11':
+ resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-scroll-area@1.2.10':
+ resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-select@2.2.6':
+ resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-slot@1.2.3':
+ resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-slot@1.2.4':
+ resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-switch@1.2.6':
+ resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-tabs@1.1.13':
+ resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-toast@1.2.15':
+ resolution: {integrity: sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-use-callback-ref@1.1.1':
+ resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-controllable-state@1.2.2':
+ resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-effect-event@0.0.2':
+ resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-escape-keydown@1.1.1':
+ resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-layout-effect@1.1.1':
+ resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-previous@1.1.1':
+ resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-rect@1.1.1':
+ resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-size@1.1.1':
+ resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-visually-hidden@1.2.3':
+ resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/rect@1.1.1':
+ resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
+
+ '@reown/appkit-common@1.8.14':
+ resolution: {integrity: sha512-0dRNtmy2e7f89Vvx3NCA09PD24DFT6S0nO6a/MBeFOj7SlvkvIh4SjBWG2x2F4L8KxCSCtQ5x6dWREmTONZjMA==}
+
+ '@reown/appkit-controllers@1.8.14':
+ resolution: {integrity: sha512-1EF3xzwMwNfzZp1yd2InwA01EEDSylwHfX6MuGa1t5M6HevY4p1QnbnZISpYAQxN1xklCQsT3Zq5pQh6Ofg+Cg==}
+
+ '@reown/appkit-pay@1.8.14':
+ resolution: {integrity: sha512-6ReXMGV47quXax8v1RQ8wFgclSd6M7MhX/WHJGwsjNHjFttQ6xWbPlYmjZxKgZ+k+K2TG/wo7oU0pF5Qu/L7Tw==}
+
+ '@reown/appkit-polyfills@1.8.14':
+ resolution: {integrity: sha512-bMMdJpzxni6+FQpMqQomKvXoDy+t9uCunswuKCN33fMRXtXX0A3ui0WMGUFbQ4BKGmQcyUSt/MWid9hZ6KG8Fw==}
+
+ '@reown/appkit-scaffold-ui@1.8.14':
+ resolution: {integrity: sha512-dhD9vodp1xsVs0yWP2V+b3XkcksHEHNzjNQvXBmTrfDDDpUYiScBTvjKmMRu/MgUxYRrFdxoMDIfAzjYUAwZuw==}
+
+ '@reown/appkit-ui@1.8.14':
+ resolution: {integrity: sha512-vExTPCA8QghLaUG3mM2ghUN7IvTGy/dUbVxGYbCrIG/Y7Srshqp8O/vwnWk5RhktRwMNQuOXCRGXf2lWPiuNWQ==}
+
+ '@reown/appkit-universal-connector@1.8.14':
+ resolution: {integrity: sha512-Z7aegr4A5T2Bz6A/DEn25eZeXJhxBlj7UqlbXfxX8+SaAjCWSx4WuTAsJFMPQwtGDPGdEIVSe0EAWAHOAX9wqA==}
+
+ '@reown/appkit-utils@1.8.14':
+ resolution: {integrity: sha512-SuXtX2pr8yilaAdTq7nEj2/ulKMUJAKUbtldAcsl3/acsqfD4oKHi13VJEKsHcGx/43sb1uDXA9yB60/g2+NAQ==}
peerDependencies:
valtio: 2.1.7
@@ -2021,6 +2959,9 @@ packages:
'@rolldown/pluginutils@1.0.0-beta.27':
resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
+ '@rolldown/pluginutils@1.0.0-beta.53':
+ resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==}
+
'@rollup/plugin-replace@6.0.2':
resolution: {integrity: sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ==}
engines: {node: '>=14.0.0'}
@@ -2822,6 +3763,9 @@ packages:
peerDependencies:
solid-js: ^1.5.3
+ '@standard-schema/utils@0.3.0':
+ resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
+
'@swc/core-darwin-arm64@1.5.29':
resolution: {integrity: sha512-6F/sSxpHaq3nzg2ADv9FHLi4Fu2A8w8vP8Ich8gIl16D2htStlwnaPmCLjRswO+cFkzgVqy/l01gzNGWd4DFqA==}
engines: {node: '>=10'}
@@ -2897,8 +3841,103 @@ packages:
'@swc/helpers@0.5.17':
resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
- '@swc/types@0.1.23':
- resolution: {integrity: sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==}
+ '@swc/types@0.1.25':
+ resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==}
+
+ '@tailwindcss/node@4.1.18':
+ resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==}
+
+ '@tailwindcss/oxide-android-arm64@4.1.18':
+ resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@tailwindcss/oxide-darwin-arm64@4.1.18':
+ resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-darwin-x64@4.1.18':
+ resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-freebsd-x64@4.1.18':
+ resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
+ resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
+ resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.18':
+ resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.18':
+ resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-musl@4.1.18':
+ resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-wasm32-wasi@4.1.18':
+ resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+ bundledDependencies:
+ - '@napi-rs/wasm-runtime'
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ - '@tybys/wasm-util'
+ - '@emnapi/wasi-threads'
+ - tslib
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
+ resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.18':
+ resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@tailwindcss/oxide@4.1.18':
+ resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==}
+ engines: {node: '>= 10'}
+
+ '@tailwindcss/typography@0.5.19':
+ resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==}
+ peerDependencies:
+ tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
+
+ '@tailwindcss/vite@4.1.18':
+ resolution: {integrity: sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==}
+ peerDependencies:
+ vite: ^5.2.0 || ^6 || ^7
'@ton-community/assets-sdk@0.0.5':
resolution: {integrity: sha512-ayu+wVO2497L+O1x2QFZSX3dTQjsfh0ae6wb1ENIGgpjVVXsnPUQJ8s4YTwYTlrC3O1ghltkMCHhtxlaRvS9oA==}
@@ -2913,6 +3952,11 @@ packages:
peerDependencies:
'@ton/crypto': '>=3.2.0'
+ '@ton/core@0.62.1':
+ resolution: {integrity: sha512-RaEGBo9gCf6ZHyS8SKq1K53pswvYW9E5A6vwUuzFBTRX14g4qMDlB9F+fq4aBE5kN7XyVr8ScQtOJfQj41usCw==}
+ peerDependencies:
+ '@ton/crypto': '>=3.2.0'
+
'@ton/crypto-primitives@2.1.0':
resolution: {integrity: sha512-PQesoyPgqyI6vzYtCXw4/ZzevePc4VGcJtFwf08v10OevVJHVfW238KBdpj1kEDQkxWLeuNHEpTECNFKnP6tow==}
@@ -2925,8 +3969,14 @@ packages:
'@ton/core': '>=0.60.0'
'@ton/crypto': '>=3.2.0'
- '@tsconfig/node10@1.0.11':
- resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
+ '@ton/ton@16.1.0':
+ resolution: {integrity: sha512-vRlMZVJ0/JABFDTFInyLh3C4LRP6AF3VtOl2iwCEcPfqRxdPcHW4r+bJLkKvo5fCknaGS8CEVdBeu6ziXHv2Ig==}
+ peerDependencies:
+ '@ton/core': '>=0.62.0 <1.0.0'
+ '@ton/crypto': '>=3.2.0'
+
+ '@tsconfig/node10@1.0.12':
+ resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==}
'@tsconfig/node12@1.0.11':
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
@@ -2979,6 +4029,9 @@ packages:
'@types/eslint@9.6.1':
resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
+ '@types/estree-jsx@1.0.5':
+ resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
+
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
@@ -3006,12 +4059,18 @@ packages:
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+ '@types/mdast@4.0.4':
+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
'@types/node@12.20.55':
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
+ '@types/node@24.10.8':
+ resolution: {integrity: sha512-r0bBaXu5Swb05doFYO2kTWHMovJnNVbCsII0fhesM8bNRlLhXIuckley4a2DaD+vOdmm5G+zGkQZAPZsF80+YQ==}
+
'@types/node@24.2.0':
resolution: {integrity: sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==}
@@ -3023,9 +4082,17 @@ packages:
peerDependencies:
'@types/react': ^19.0.0
+ '@types/react-dom@19.2.3':
+ resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
+ peerDependencies:
+ '@types/react': ^19.2.0
+
'@types/react@19.1.9':
resolution: {integrity: sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==}
+ '@types/react@19.2.8':
+ resolution: {integrity: sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==}
+
'@types/stack-utils@2.0.3':
resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
@@ -3041,6 +4108,9 @@ packages:
'@types/ua-parser-js@0.7.39':
resolution: {integrity: sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg==}
+ '@types/unist@2.0.11':
+ resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
+
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
@@ -3070,6 +4140,14 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
+ '@typescript-eslint/eslint-plugin@8.53.0':
+ resolution: {integrity: sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^8.53.0
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
'@typescript-eslint/parser@8.39.0':
resolution: {integrity: sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3077,22 +4155,45 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
+ '@typescript-eslint/parser@8.53.0':
+ resolution: {integrity: sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
'@typescript-eslint/project-service@8.39.0':
resolution: {integrity: sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
+ '@typescript-eslint/project-service@8.53.0':
+ resolution: {integrity: sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
'@typescript-eslint/scope-manager@8.39.0':
resolution: {integrity: sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@typescript-eslint/scope-manager@8.53.0':
+ resolution: {integrity: sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@typescript-eslint/tsconfig-utils@8.39.0':
resolution: {integrity: sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
+ '@typescript-eslint/tsconfig-utils@8.53.0':
+ resolution: {integrity: sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
'@typescript-eslint/type-utils@8.39.0':
resolution: {integrity: sha512-6B3z0c1DXVT2vYA9+z9axjtc09rqKUPRmijD5m9iv8iQpHBRYRMBcgxSiKTZKm6FwWw1/cI4v6em35OsKCiN5Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3100,16 +4201,33 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
+ '@typescript-eslint/type-utils@8.53.0':
+ resolution: {integrity: sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
'@typescript-eslint/types@8.39.0':
resolution: {integrity: sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@typescript-eslint/types@8.53.0':
+ resolution: {integrity: sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@typescript-eslint/typescript-estree@8.39.0':
resolution: {integrity: sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
+ '@typescript-eslint/typescript-estree@8.53.0':
+ resolution: {integrity: sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
'@typescript-eslint/utils@8.39.0':
resolution: {integrity: sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3117,10 +4235,43 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
+ '@typescript-eslint/utils@8.53.0':
+ resolution: {integrity: sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
'@typescript-eslint/visitor-keys@8.39.0':
resolution: {integrity: sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@typescript-eslint/visitor-keys@8.53.0':
+ resolution: {integrity: sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@uiw/codemirror-extensions-basic-setup@4.25.4':
+ resolution: {integrity: sha512-YzNwkm0AbPv1EXhCHYR5v0nqfemG2jEB0Z3Att4rBYqKrlG7AA9Rhjc3IyBaOzsBu18wtrp9/+uhTyu7TXSRng==}
+ peerDependencies:
+ '@codemirror/autocomplete': '>=6.0.0'
+ '@codemirror/commands': '>=6.0.0'
+ '@codemirror/language': '>=6.0.0'
+ '@codemirror/lint': '>=6.0.0'
+ '@codemirror/search': '>=6.0.0'
+ '@codemirror/state': '>=6.0.0'
+ '@codemirror/view': '>=6.0.0'
+
+ '@uiw/react-codemirror@4.25.4':
+ resolution: {integrity: sha512-ipO067oyfUw+DVaXhQCxkB0ZD9b7RnY+ByrprSYSKCHaULvJ3sqWYC/Zen6zVQ8/XC4o5EPBfatGiX20kC7XGA==}
+ peerDependencies:
+ '@babel/runtime': '>=7.11.0'
+ '@codemirror/state': '>=6.0.0'
+ '@codemirror/theme-one-dark': '>=6.0.0'
+ '@codemirror/view': '>=6.0.0'
+ codemirror: '>=6.0.0'
+ react: '>=17.0.0'
+ react-dom: '>=17.0.0'
+
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
@@ -3225,6 +4376,12 @@ packages:
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+ '@vitejs/plugin-react@5.1.2':
+ resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+
'@vitest/coverage-istanbul@3.2.4':
resolution: {integrity: sha512-IDlpuFJiWU9rhcKLkpzj8mFu/lpe64gVgnV15ZOrYx1iFzxxrxCzbExiUEKtwwXRvEiEMUS6iZeYgnMxgbqbxQ==}
peerDependencies:
@@ -3590,6 +4747,10 @@ packages:
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ aria-hidden@1.2.6:
+ resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
+ engines: {node: '>=10'}
+
array-buffer-byte-length@1.0.2:
resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
engines: {node: '>= 0.4'}
@@ -3644,6 +4805,13 @@ packages:
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
engines: {node: '>=8.0.0'}
+ autoprefixer@10.4.23:
+ resolution: {integrity: sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+
available-typed-arrays@1.0.7:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
@@ -3719,6 +4887,9 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0
+ bail@2.0.2:
+ resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
+
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -3734,6 +4905,10 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+ baseline-browser-mapping@2.9.14:
+ resolution: {integrity: sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==}
+ hasBin: true
+
better-path-resolve@1.0.0:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
engines: {node: '>=4'}
@@ -3794,6 +4969,11 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ browserslist@4.28.1:
+ resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
bs-logger@0.2.6:
resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==}
engines: {node: '>= 6'}
@@ -3859,6 +5039,12 @@ packages:
caniuse-lite@1.0.30001731:
resolution: {integrity: sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==}
+ caniuse-lite@1.0.30001764:
+ resolution: {integrity: sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==}
+
+ ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+
chai@5.2.1:
resolution: {integrity: sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==}
engines: {node: '>=18'}
@@ -3875,6 +5061,18 @@ packages:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
+ character-entities-html4@2.1.0:
+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+ character-entities-legacy@3.0.0:
+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
+ character-entities@2.0.2:
+ resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+
+ character-reference-invalid@2.0.1:
+ resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+
chardet@0.7.0:
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
@@ -3921,6 +5119,9 @@ packages:
class-is@1.1.0:
resolution: {integrity: sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==}
+ class-variance-authority@0.7.1:
+ resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
+
classnames@2.5.1:
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
@@ -3963,10 +5164,17 @@ packages:
resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==}
engines: {node: '>=6'}
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
co@4.6.0:
resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
+ codemirror@6.0.2:
+ resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==}
+
collect-v8-coverage@1.0.2:
resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==}
@@ -3984,6 +5192,9 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
+ comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
commander@10.0.1:
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
@@ -4056,6 +5267,9 @@ packages:
create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
+ crelt@1.0.6:
+ resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
+
cross-fetch@3.2.0:
resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==}
@@ -4077,6 +5291,11 @@ packages:
resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==}
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+ cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
cssstyle@5.3.1:
resolution: {integrity: sha512-g5PC9Aiph9eiczFpcgUhd9S4UUO3F+LHGRIi5NUMZ+4xtoIYbHNZwZnWA2JsFGe8OU8nl4WyaEFiZuGuxlutJQ==}
engines: {node: '>=20'}
@@ -4087,6 +5306,9 @@ packages:
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
data-urls@6.0.0:
resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==}
engines: {node: '>=20'}
@@ -4137,6 +5359,15 @@ packages:
supports-color:
optional: true
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
decamelize@1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
@@ -4144,6 +5375,9 @@ packages:
decimal.js@10.6.0:
resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
+ decode-named-character-reference@1.2.0:
+ resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==}
+
dedent@1.6.0:
resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==}
peerDependencies:
@@ -4220,10 +5454,20 @@ packages:
engines: {node: '>=0.10'}
hasBin: true
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
detect-newline@3.1.0:
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
engines: {node: '>=8'}
+ detect-node-es@1.1.0:
+ resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
+
+ devlop@1.1.0:
+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
diff@4.0.2:
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
engines: {node: '>=0.3.1'}
@@ -4256,6 +5500,9 @@ packages:
electron-to-chromium@1.5.195:
resolution: {integrity: sha512-URclP0iIaDUzqcAyV1v2PgduJ9N0IdXmWsnPzPfelvBmjmZzEy6xJcjb1cXj+TbYqXgtLrjHEoaSIdTYhw4ezg==}
+ electron-to-chromium@1.5.267:
+ resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
+
emittery@0.13.1:
resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==}
engines: {node: '>=12'}
@@ -4277,6 +5524,10 @@ packages:
resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==}
engines: {node: '>=10.13.0'}
+ enhanced-resolve@5.18.4:
+ resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==}
+ engines: {node: '>=10.13.0'}
+
enquirer@2.4.1:
resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
engines: {node: '>=8.6'}
@@ -4363,6 +5614,11 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ esbuild@0.27.2:
+ resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
+ engines: {node: '>=18'}
+ hasBin: true
+
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
@@ -4382,6 +5638,10 @@ packages:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
+ escape-string-regexp@5.0.0:
+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
+ engines: {node: '>=12'}
+
eslint-config-prettier@10.1.8:
resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
hasBin: true
@@ -4477,6 +5737,17 @@ packages:
peerDependencies:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+ eslint-plugin-react-hooks@7.0.1:
+ resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+
+ eslint-plugin-react-refresh@0.4.26:
+ resolution: {integrity: sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==}
+ peerDependencies:
+ eslint: '>=8.40'
+
eslint-plugin-react@7.37.5:
resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
engines: {node: '>=4'}
@@ -4525,6 +5796,16 @@ packages:
jiti:
optional: true
+ eslint@9.39.2:
+ resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ hasBin: true
+ peerDependencies:
+ jiti: '*'
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+
espree@10.4.0:
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -4550,6 +5831,9 @@ packages:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'}
+ estree-util-is-identifier-name@3.0.0:
+ resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
+
estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
@@ -4594,6 +5878,9 @@ packages:
exsolve@1.0.7:
resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
+ extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
extendable-error@0.1.7:
resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==}
@@ -4665,6 +5952,15 @@ packages:
picomatch:
optional: true
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
figures@3.2.0:
resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
engines: {node: '>=8'}
@@ -4737,6 +6033,9 @@ packages:
resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
engines: {node: '>= 6'}
+ fraction.js@5.3.4:
+ resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
+
fs-extra@11.3.0:
resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==}
engines: {node: '>=14.14'}
@@ -4779,6 +6078,10 @@ packages:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
+ get-nonce@1.0.1:
+ resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
+ engines: {node: '>=6'}
+
get-package-type@0.1.0:
resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
engines: {node: '>=8.0.0'}
@@ -4834,6 +6137,10 @@ packages:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'}
+ globals@16.5.0:
+ resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==}
+ engines: {node: '>=18'}
+
globalthis@1.0.4:
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
engines: {node: '>= 0.4'}
@@ -4867,6 +6174,10 @@ packages:
resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==}
engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
+ graphql@16.12.0:
+ resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==}
+ engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
+
h3@1.15.4:
resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==}
@@ -4904,6 +6215,12 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
+ hast-util-to-jsx-runtime@2.3.6:
+ resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
+
+ hast-util-whitespace@3.0.0:
+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
he@1.2.0:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true
@@ -4911,6 +6228,12 @@ packages:
headers-polyfill@4.0.3:
resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==}
+ hermes-estree@0.25.1:
+ resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
+
+ hermes-parser@0.25.1:
+ resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
+
html-encoding-sniffer@4.0.0:
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
engines: {node: '>=18'}
@@ -4925,6 +6248,9 @@ packages:
resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==}
engines: {node: '>=8'}
+ html-url-attributes@3.0.1:
+ resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
+
http-proxy-agent@7.0.2:
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
engines: {node: '>= 14'}
@@ -5010,6 +6336,9 @@ packages:
inline-style-parser@0.2.4:
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
+ inline-style-parser@0.2.7:
+ resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
+
inquirer@8.2.6:
resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==}
engines: {node: '>=12.0.0'}
@@ -5029,6 +6358,12 @@ packages:
iron-webcrypto@1.2.1:
resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}
+ is-alphabetical@2.0.1:
+ resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
+
+ is-alphanumerical@2.0.1:
+ resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
+
is-array-buffer@3.0.5:
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
engines: {node: '>= 0.4'}
@@ -5078,6 +6413,9 @@ packages:
resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
engines: {node: '>= 0.4'}
+ is-decimal@2.0.1:
+ resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
+
is-docker@2.2.1:
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
engines: {node: '>=8'}
@@ -5112,6 +6450,9 @@ packages:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
+ is-hexadecimal@2.0.1:
+ resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+
is-html@2.0.0:
resolution: {integrity: sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==}
engines: {node: '>=8'}
@@ -5151,6 +6492,10 @@ packages:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
+ is-plain-obj@4.1.0:
+ resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+ engines: {node: '>=12'}
+
is-plain-object@2.0.4:
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
engines: {node: '>=0.10.0'}
@@ -5429,6 +6774,10 @@ packages:
node-notifier:
optional: true
+ jiti@2.6.1:
+ resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
+ hasBin: true
+
jju@1.4.0:
resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
@@ -5438,6 +6787,9 @@ packages:
jose@6.0.12:
resolution: {integrity: sha512-T8xypXs8CpmiIi78k0E+Lk7T2zlK4zDyg+o1CZ4AkOHgDg98ogdP2BeZ61lTFKFyoEwJ9RgAgN+SdM3iPgNonQ==}
+ jose@6.1.3:
+ resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==}
+
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -5511,32 +6863,102 @@ packages:
resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==}
engines: {node: '>=4.0'}
- kebab-case@1.0.2:
- resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==}
+ kebab-case@1.0.2:
+ resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==}
+
+ keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+ keyvaluestorage-interface@1.0.0:
+ resolution: {integrity: sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==}
+
+ kind-of@6.0.3:
+ resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+ engines: {node: '>=0.10.0'}
+
+ known-css-properties@0.30.0:
+ resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==}
+
+ kolorist@1.8.0:
+ resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
+
+ leven@3.1.0:
+ resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
+ engines: {node: '>=6'}
+
+ levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+
+ lightningcss-android-arm64@1.30.2:
+ resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ lightningcss-darwin-arm64@1.30.2:
+ resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.30.2:
+ resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-freebsd-x64@1.30.2:
+ resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.30.2:
+ resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
- keyv@4.5.4:
- resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+ lightningcss-linux-arm64-gnu@1.30.2:
+ resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
- keyvaluestorage-interface@1.0.0:
- resolution: {integrity: sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==}
+ lightningcss-linux-arm64-musl@1.30.2:
+ resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
- kind-of@6.0.3:
- resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
- engines: {node: '>=0.10.0'}
+ lightningcss-linux-x64-gnu@1.30.2:
+ resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
- known-css-properties@0.30.0:
- resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==}
+ lightningcss-linux-x64-musl@1.30.2:
+ resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
- kolorist@1.8.0:
- resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
+ lightningcss-win32-arm64-msvc@1.30.2:
+ resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
- leven@3.1.0:
- resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
- engines: {node: '>=6'}
+ lightningcss-win32-x64-msvc@1.30.2:
+ resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
- levn@0.4.1:
- resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
- engines: {node: '>= 0.8.0'}
+ lightningcss@1.30.2:
+ resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
+ engines: {node: '>= 12.0.0'}
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
@@ -5594,6 +7016,9 @@ packages:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
+ longest-streak@3.1.0:
+ resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
+
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
@@ -5619,6 +7044,11 @@ packages:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
+ lucide-react@0.562.0:
+ resolution: {integrity: sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==}
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
lunr@2.3.9:
resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==}
@@ -5628,6 +7058,9 @@ packages:
magic-string@0.30.17:
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
magicast@0.3.5:
resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
@@ -5645,6 +7078,9 @@ packages:
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
hasBin: true
+ markdown-table@3.0.4:
+ resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
+
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
@@ -5652,6 +7088,51 @@ packages:
md5@2.3.0:
resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==}
+ mdast-util-find-and-replace@3.0.2:
+ resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
+
+ mdast-util-from-markdown@2.0.2:
+ resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
+
+ mdast-util-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
+
+ mdast-util-gfm-table@2.0.0:
+ resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
+
+ mdast-util-gfm@3.1.0:
+ resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
+
+ mdast-util-mdx-expression@2.0.1:
+ resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
+
+ mdast-util-mdx-jsx@3.2.0:
+ resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
+
+ mdast-util-mdxjs-esm@2.0.1:
+ resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
+
+ mdast-util-phrasing@4.1.0:
+ resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
+
+ mdast-util-to-hast@13.2.1:
+ resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
+
+ mdast-util-to-markdown@2.1.2:
+ resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
+
+ mdast-util-to-string@4.0.0:
+ resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
+
mdn-data@2.12.2:
resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==}
@@ -5669,6 +7150,90 @@ packages:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
+ micromark-core-commonmark@2.0.3:
+ resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
+
+ micromark-extension-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
+
+ micromark-extension-gfm-table@2.1.1:
+ resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
+
+ micromark-extension-gfm@3.0.0:
+ resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
+
+ micromark-factory-destination@2.0.1:
+ resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
+
+ micromark-factory-label@2.0.1:
+ resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
+
+ micromark-factory-space@2.0.1:
+ resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
+
+ micromark-factory-title@2.0.1:
+ resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
+
+ micromark-factory-whitespace@2.0.1:
+ resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
+
+ micromark-util-character@2.1.1:
+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+ micromark-util-chunked@2.0.1:
+ resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
+
+ micromark-util-classify-character@2.0.1:
+ resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
+
+ micromark-util-combine-extensions@2.0.1:
+ resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
+
+ micromark-util-decode-string@2.0.1:
+ resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
+
+ micromark-util-encode@2.0.1:
+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+ micromark-util-html-tag-name@2.0.1:
+ resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
+
+ micromark-util-normalize-identifier@2.0.1:
+ resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
+
+ micromark-util-resolve-all@2.0.1:
+ resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
+
+ micromark-util-sanitize-uri@2.0.1:
+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+ micromark-util-subtokenize@2.1.0:
+ resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
+
+ micromark-util-symbol@2.0.1:
+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+ micromark-util-types@2.0.2:
+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
+ micromark@4.0.2:
+ resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
+
micromatch@4.0.5:
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
engines: {node: '>=8.6'}
@@ -5697,6 +7262,10 @@ packages:
resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==}
engines: {node: 20 || >=22}
+ minimatch@10.1.1:
+ resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
+ engines: {node: 20 || >=22}
+
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -5741,6 +7310,16 @@ packages:
typescript:
optional: true
+ msw@2.12.7:
+ resolution: {integrity: sha512-retd5i3xCZDVWMYjHEVuKTmhqY8lSsxujjVrZiGbbdoxxIBg5S7rCuYy/YQpfrTYIxpd/o0Kyb/3H+1udBMoYg==}
+ engines: {node: '>=18'}
+ hasBin: true
+ peerDependencies:
+ typescript: '>= 4.8.x'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
muggle-string@0.4.1:
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
@@ -5802,6 +7381,12 @@ packages:
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+ next-themes@0.4.6:
+ resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
+ peerDependencies:
+ react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
+
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
@@ -5830,6 +7415,9 @@ packages:
node-releases@2.0.19:
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
+ node-releases@2.0.27:
+ resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
+
normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
@@ -5992,6 +7580,9 @@ packages:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
+ parse-entities@4.0.2:
+ resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
+
parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
@@ -6103,6 +7694,13 @@ packages:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
+ postcss-selector-parser@6.0.10:
+ resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
+ engines: {node: '>=4'}
+
+ postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
postcss@8.5.6:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
@@ -6145,6 +7743,9 @@ packages:
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ property-information@7.1.0:
+ resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+
proxy-compare@3.0.1:
resolution: {integrity: sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==}
@@ -6202,6 +7803,17 @@ packages:
peerDependencies:
react: ^19.1.1
+ react-dom@19.2.3:
+ resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
+ peerDependencies:
+ react: ^19.2.3
+
+ react-hook-form@7.71.1:
+ resolution: {integrity: sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ react: ^16.8.0 || ^17 || ^18 || ^19
+
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@@ -6217,10 +7829,40 @@ packages:
react-lifecycles-compat@3.0.4:
resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
+ react-markdown@10.1.0:
+ resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==}
+ peerDependencies:
+ '@types/react': '>=18'
+ react: '>=18'
+
react-refresh@0.17.0:
resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
engines: {node: '>=0.10.0'}
+ react-refresh@0.18.0:
+ resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
+ engines: {node: '>=0.10.0'}
+
+ react-remove-scroll-bar@2.3.8:
+ resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react-remove-scroll@2.7.2:
+ resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
react-router-dom@7.9.4:
resolution: {integrity: sha512-f30P6bIkmYvnHHa5Gcu65deIXoA2+r3Eb6PJIAddvsT9aGlchMatJ51GgpU470aSqRRbFX22T70yQNUGuW3DfA==}
engines: {node: '>=20.0.0'}
@@ -6238,6 +7880,16 @@ packages:
react-dom:
optional: true
+ react-style-singleton@2.2.3:
+ resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
react-textarea-autosize@8.5.9:
resolution: {integrity: sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==}
engines: {node: '>=10'}
@@ -6248,6 +7900,10 @@ packages:
resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==}
engines: {node: '>=0.10.0'}
+ react@19.2.3:
+ resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
+ engines: {node: '>=0.10.0'}
+
read-yaml-file@1.1.0:
resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==}
engines: {node: '>=6'}
@@ -6298,6 +7954,18 @@ packages:
resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==}
hasBin: true
+ remark-gfm@4.0.1:
+ resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
+
+ remark-parse@11.0.0:
+ resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
+
+ remark-rehype@11.1.2:
+ resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+
+ remark-stringify@11.0.0:
+ resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
+
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
@@ -6332,6 +8000,11 @@ packages:
engines: {node: '>= 0.4'}
hasBin: true
+ resolve@1.22.11:
+ resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+
resolve@2.0.0-next.5:
resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
hasBin: true
@@ -6340,6 +8013,9 @@ packages:
resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
engines: {node: '>=8'}
+ rettime@0.7.0:
+ resolution: {integrity: sha512-LPRKoHnLKd/r3dVxcwO7vhCW+orkOGj9ViueosEBK6ie89CijnfRlhaDhHq/3Hxu4CkWQtxwlBG0mzTQY6uQjw==}
+
reusify@1.0.4:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -6450,6 +8126,9 @@ packages:
scheduler@0.26.0:
resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==}
+ scheduler@0.27.0:
+ resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+
schema-utils@4.3.2:
resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==}
engines: {node: '>= 10.13.0'}
@@ -6473,6 +8152,11 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ semver@7.7.3:
+ resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
+ engines: {node: '>=10'}
+ hasBin: true
+
serialize-javascript@6.0.2:
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
@@ -6625,6 +8309,12 @@ packages:
sonic-boom@4.2.0:
resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==}
+ sonner@2.0.7:
+ resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==}
+ peerDependencies:
+ react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@@ -6643,6 +8333,9 @@ packages:
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
engines: {node: '>= 8'}
+ space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
spawndamnit@3.0.1:
resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==}
@@ -6726,6 +8419,9 @@ packages:
string_decoder@1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+ stringify-entities@4.0.4:
+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
@@ -6760,6 +8456,15 @@ packages:
strnum@2.1.1:
resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==}
+ style-mod@4.1.3:
+ resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==}
+
+ style-to-js@1.1.21:
+ resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
+
+ style-to-object@1.0.14:
+ resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
+
style-to-object@1.0.9:
resolution: {integrity: sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==}
@@ -6789,6 +8494,21 @@ packages:
resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==}
engines: {node: ^14.18.0 || >=16.0.0}
+ tagged-tag@1.0.0:
+ resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
+ engines: {node: '>=20'}
+
+ tailwind-merge@3.4.0:
+ resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==}
+
+ tailwindcss-animate@1.0.7:
+ resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==}
+ peerDependencies:
+ tailwindcss: '>=3.0.0 || insiders'
+
+ tailwindcss@4.1.18:
+ resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==}
+
tapable@2.2.2:
resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==}
engines: {node: '>=6'}
@@ -6848,6 +8568,10 @@ packages:
resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
engines: {node: '>=12.0.0'}
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
tinypool@1.1.1:
resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -6901,12 +8625,24 @@ packages:
resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==}
engines: {node: '>=20'}
+ trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
+ trough@2.2.0:
+ resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
+
ts-api-utils@2.1.0:
resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
engines: {node: '>=18.12'}
peerDependencies:
typescript: '>=4.8.4'
+ ts-api-utils@2.4.0:
+ resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==}
+ engines: {node: '>=18.12'}
+ peerDependencies:
+ typescript: '>=4.8.4'
+
ts-jest@29.4.1:
resolution: {integrity: sha512-SaeUtjfpg9Uqu8IbeDKtdaS0g8lS6FT6OzM3ezrDfErPJPHNDo/Ey+VFGP1bQIDfagYDLyRpd7O15XpG1Es2Uw==}
engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0}
@@ -7042,6 +8778,10 @@ packages:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
+ type-fest@5.4.1:
+ resolution: {integrity: sha512-xygQcmneDyzsEuKZrFbRMne5HDqMs++aFzefrJTgEIKjQ3rekM+RPfFCVq2Gp1VIDqddoYeppCj4Pcb+RZW0GQ==}
+ engines: {node: '>=20'}
+
typed-array-buffer@1.0.3:
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
engines: {node: '>= 0.4'}
@@ -7065,6 +8805,13 @@ packages:
peerDependencies:
typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x
+ typescript-eslint@8.53.0:
+ resolution: {integrity: sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
typescript-transform-paths@3.5.5:
resolution: {integrity: sha512-RMK86wKe/4+ad+3kMT9SKAs3K0tUHLe7hF+MLbD6VpC9VUmFuKorhf3pHz+qO5GdS4mUp2ncNUo14j6ws9UvBQ==}
peerDependencies:
@@ -7080,6 +8827,11 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
ua-parser-js@1.0.40:
resolution: {integrity: sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==}
hasBin: true
@@ -7131,6 +8883,24 @@ packages:
resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==}
engines: {node: '>=4'}
+ unified@11.0.5:
+ resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
+
+ unist-util-is@6.0.1:
+ resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
+
+ unist-util-position@5.0.0:
+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
+ unist-util-stringify-position@4.0.0:
+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+ unist-util-visit-parents@6.0.2:
+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
+
+ unist-util-visit@5.0.0:
+ resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
+
universalify@0.1.2:
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
engines: {node: '>= 4.0.0'}
@@ -7212,6 +8982,9 @@ packages:
uploadthing:
optional: true
+ until-async@3.0.2:
+ resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==}
+
untildify@4.0.0:
resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
engines: {node: '>=8'}
@@ -7222,12 +8995,28 @@ packages:
peerDependencies:
browserslist: '>= 4.21.0'
+ update-browserslist-db@1.2.3:
+ resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
+ use-callback-ref@1.3.3:
+ resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
use-composed-ref@1.4.0:
resolution: {integrity: sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==}
peerDependencies:
@@ -7255,6 +9044,16 @@ packages:
'@types/react':
optional: true
+ use-sidecar@1.1.3:
+ resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
utf-8-validate@5.0.10:
resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==}
engines: {node: '>=6.14.2'}
@@ -7306,6 +9105,12 @@ packages:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
+ vfile-message@4.0.3:
+ resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
+
+ vfile@6.0.3:
+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
viem@2.38.5:
resolution: {integrity: sha512-EU2olUnWd5kBK1t3BicwaamPHGUANRYetoDLSVzDy7XQ8o8UswItnkQbufe3xTcdRCtb2JYMwjlgHZZ7fUoLdA==}
peerDependencies:
@@ -7396,6 +9201,46 @@ packages:
yaml:
optional: true
+ vite@7.3.1:
+ resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^20.19.0 || >=22.12.0
+ jiti: '>=1.21.0'
+ less: ^4.0.0
+ lightningcss: ^1.21.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: '>=0.54.8'
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
vitefu@1.1.1:
resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==}
peerDependencies:
@@ -7441,6 +9286,9 @@ packages:
vscode-uri@3.1.0:
resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
+ w3c-keyname@2.2.8:
+ resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
+
w3c-xmlserializer@5.0.0:
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
engines: {node: '>=18'}
@@ -7505,6 +9353,7 @@ packages:
whatwg-encoding@3.1.1:
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
engines: {node: '>=18'}
+ deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation
whatwg-fetch@3.6.20:
resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==}
@@ -7640,6 +9489,11 @@ packages:
engines: {node: '>= 14.6'}
hasBin: true
+ yaml@2.8.2:
+ resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
+ engines: {node: '>= 14.6'}
+ hasBin: true
+
yargs-parser@18.1.3:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
@@ -7668,6 +9522,12 @@ packages:
resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
engines: {node: '>=18'}
+ zod-validation-error@4.0.2:
+ resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ zod: ^3.25.0 || ^4.0.0
+
zod@3.22.4:
resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
@@ -7677,6 +9537,9 @@ packages:
zod@4.0.15:
resolution: {integrity: sha512-2IVHb9h4Mt6+UXkyMs0XbfICUh1eUrlJJAOupBHUhLRnKkruawyDddYRCs0Eizt900ntIMk9/4RksYl+FgSpcQ==}
+ zod@4.3.5:
+ resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==}
+
zustand@5.0.3:
resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==}
engines: {node: '>=12.20.0'}
@@ -7695,6 +9558,9 @@ packages:
use-sync-external-store:
optional: true
+ zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+
snapshots:
'@adraffy/ens-normalize@1.11.1': {}
@@ -8197,8 +10063,16 @@ snapshots:
js-tokens: 4.0.0
picocolors: 1.1.1
+ '@babel/code-frame@7.28.6':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.28.5
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
'@babel/compat-data@7.28.0': {}
+ '@babel/compat-data@7.28.6': {}
+
'@babel/core@7.28.0':
dependencies:
'@ampproject/remapping': 2.3.0
@@ -8219,6 +10093,26 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/core@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
+ '@babel/helpers': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/generator@7.28.0':
dependencies:
'@babel/parser': 7.28.0
@@ -8227,9 +10121,17 @@ snapshots:
'@jridgewell/trace-mapping': 0.3.29
jsesc: 3.1.0
+ '@babel/generator@7.28.6':
+ dependencies:
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+ '@jridgewell/gen-mapping': 0.3.12
+ '@jridgewell/trace-mapping': 0.3.29
+ jsesc: 3.1.0
+
'@babel/helper-annotate-as-pure@7.27.3':
dependencies:
- '@babel/types': 7.28.2
+ '@babel/types': 7.28.6
optional: true
'@babel/helper-compilation-targets@7.27.2':
@@ -8240,34 +10142,42 @@ snapshots:
lru-cache: 5.1.1
semver: 6.3.1
- '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.0)':
+ '@babel/helper-compilation-targets@7.28.6':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/compat-data': 7.28.6
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.28.1
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
'@babel/helper-annotate-as-pure': 7.27.3
'@babel/helper-member-expression-to-functions': 7.27.1
'@babel/helper-optimise-call-expression': 7.27.1
- '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0)
+ '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.6)
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/traverse': 7.28.0
+ '@babel/traverse': 7.28.6
semver: 6.3.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.0)':
+ '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-annotate-as-pure': 7.27.3
regexpu-core: 6.2.0
semver: 6.3.1
optional: true
- '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.0)':
+ '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-compilation-targets': 7.27.2
+ '@babel/core': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- debug: 4.4.1
+ debug: 4.4.3
lodash.debounce: 4.0.8
resolve: 1.22.10
transitivePeerDependencies:
@@ -8278,8 +10188,8 @@ snapshots:
'@babel/helper-member-expression-to-functions@7.27.1':
dependencies:
- '@babel/traverse': 7.28.0
- '@babel/types': 7.28.2
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
@@ -8295,6 +10205,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-module-imports@7.28.6':
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)':
dependencies:
'@babel/core': 7.28.0
@@ -8304,37 +10221,46 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-imports': 7.28.6
+ '@babel/helper-validator-identifier': 7.28.5
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/helper-optimise-call-expression@7.27.1':
dependencies:
- '@babel/types': 7.28.2
+ '@babel/types': 7.28.6
optional: true
'@babel/helper-plugin-utils@7.27.1': {}
- '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.0)':
+ '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-annotate-as-pure': 7.27.3
'@babel/helper-wrap-function': 7.27.1
- '@babel/traverse': 7.28.0
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.0)':
+ '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-member-expression-to-functions': 7.27.1
'@babel/helper-optimise-call-expression': 7.27.1
- '@babel/traverse': 7.28.0
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
'@babel/helper-skip-transparent-expression-wrappers@7.27.1':
dependencies:
- '@babel/traverse': 7.28.0
- '@babel/types': 7.28.2
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
@@ -8343,13 +10269,15 @@ snapshots:
'@babel/helper-validator-identifier@7.27.1': {}
+ '@babel/helper-validator-identifier@7.28.5': {}
+
'@babel/helper-validator-option@7.27.1': {}
'@babel/helper-wrap-function@7.27.1':
dependencies:
- '@babel/template': 7.27.2
- '@babel/traverse': 7.28.0
- '@babel/types': 7.28.2
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
@@ -8359,94 +10287,103 @@ snapshots:
'@babel/template': 7.27.2
'@babel/types': 7.28.2
+ '@babel/helpers@7.28.6':
+ dependencies:
+ '@babel/template': 7.28.6
+ '@babel/types': 7.28.6
+
'@babel/parser@7.28.0':
dependencies:
'@babel/types': 7.28.2
- '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.28.0)':
+ '@babel/parser@7.28.6':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/types': 7.28.6
+
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/traverse': 7.28.0
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.0)
+ '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.6)
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/traverse': 7.28.0
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.0)':
+ '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
optional: true
- '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)':
@@ -8454,44 +10391,49 @@ snapshots:
'@babel/core': 7.28.0
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)':
@@ -8499,315 +10441,320 @@ snapshots:
'@babel/core': 7.28.0
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.0)':
+ '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.0)':
+ '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.0)
- '@babel/traverse': 7.28.0
+ '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6)
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-module-imports': 7.27.1
+ '@babel/core': 7.28.6
+ '@babel/helper-module-imports': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.0)
+ '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6)
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-block-scoping@7.28.0(@babel/core@7.28.0)':
+ '@babel/plugin-transform-block-scoping@7.28.0(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-class-static-block@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-class-static-block@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-classes@7.28.0(@babel/core@7.28.0)':
+ '@babel/plugin-transform-classes@7.28.0(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-compilation-targets': 7.27.2
+ '@babel/helper-compilation-targets': 7.28.6
'@babel/helper-globals': 7.28.0
'@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0)
- '@babel/traverse': 7.28.0
+ '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.6)
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/template': 7.27.2
+ '@babel/template': 7.28.6
optional: true
- '@babel/plugin-transform-destructuring@7.28.0(@babel/core@7.28.0)':
+ '@babel/plugin-transform-destructuring@7.28.0(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/traverse': 7.28.0
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.0)':
+ '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0)
+ '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.6)
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-compilation-targets': 7.27.2
+ '@babel/core': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/traverse': 7.28.0
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-validator-identifier': 7.27.1
- '@babel/traverse': 7.28.0
+ '@babel/helper-validator-identifier': 7.28.5
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-object-rest-spread@7.28.0(@babel/core@7.28.0)':
+ '@babel/plugin-transform-object-rest-spread@7.28.0(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-compilation-targets': 7.27.2
+ '@babel/core': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0)
- '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.0)
- '@babel/traverse': 7.28.0
+ '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6)
+ '@babel/traverse': 7.28.6
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0)
+ '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.6)
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.0)':
+ '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
@@ -8816,207 +10763,225 @@ snapshots:
'@babel/core': 7.28.0
'@babel/helper-plugin-utils': 7.27.1
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.27.1
+
'@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.0)':
dependencies:
'@babel/core': 7.28.0
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-regenerator@7.28.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-regenerator@7.28.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.0)':
+ '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0)
+ '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.6)
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.0)':
+ '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6)
'@babel/helper-plugin-utils': 7.27.1
optional: true
- '@babel/preset-env@7.28.0(@babel/core@7.28.0)':
+ '@babel/preset-env@7.28.0(@babel/core@7.28.6)':
dependencies:
'@babel/compat-data': 7.28.0
- '@babel/core': 7.28.0
- '@babel/helper-compilation-targets': 7.27.2
+ '@babel/core': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-validator-option': 7.27.1
- '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.0)
- '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.0)
- '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.0)
- '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-block-scoping': 7.28.0(@babel/core@7.28.0)
- '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-classes': 7.28.0(@babel/core@7.28.0)
- '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0)
- '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.0)
- '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.0)
- '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.0)
- '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-regenerator': 7.28.1(@babel/core@7.28.0)
- '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.0)
- '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.0)
- babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.0)
- babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.0)
- babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.0)
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.6)
+ '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.6)
+ '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-block-scoping': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-classes': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.6)
+ '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-regenerator': 7.28.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.6)
+ '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.6)
+ babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.6)
+ babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.6)
+ babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.6)
core-js-compat: 3.45.0
semver: 6.3.1
transitivePeerDependencies:
- supports-color
optional: true
- '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.0)':
+ '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
- '@babel/types': 7.28.2
+ '@babel/types': 7.28.6
esutils: 2.0.3
optional: true
- '@babel/preset-typescript@7.27.1(@babel/core@7.28.0)':
+ '@babel/preset-typescript@7.27.1(@babel/core@7.28.6)':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-validator-option': 7.27.1
- '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.0)
+ '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.6)
transitivePeerDependencies:
- supports-color
optional: true
'@babel/runtime@7.28.2': {}
+ '@babel/runtime@7.28.6': {}
+
'@babel/template@7.27.2':
dependencies:
'@babel/code-frame': 7.27.1
'@babel/parser': 7.28.0
'@babel/types': 7.28.2
+ '@babel/template@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+
'@babel/traverse@7.28.0':
dependencies:
'@babel/code-frame': 7.27.1
@@ -9029,11 +10994,28 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/traverse@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/types': 7.28.6
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/types@7.28.2':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
+ '@babel/types@7.28.6':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
+
'@base-org/account@2.4.0(@types/react@19.1.9)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.1.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.0.15)':
dependencies:
'@coinbase/cdp-sdk': 1.38.5(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))
@@ -9217,6 +11199,74 @@ snapshots:
human-id: 4.1.1
prettier: 2.8.8
+ '@codemirror/autocomplete@6.20.0':
+ dependencies:
+ '@codemirror/language': 6.12.1
+ '@codemirror/state': 6.5.4
+ '@codemirror/view': 6.39.11
+ '@lezer/common': 1.5.0
+
+ '@codemirror/commands@6.10.1':
+ dependencies:
+ '@codemirror/language': 6.12.1
+ '@codemirror/state': 6.5.4
+ '@codemirror/view': 6.39.11
+ '@lezer/common': 1.5.0
+
+ '@codemirror/lang-javascript@6.2.4':
+ dependencies:
+ '@codemirror/autocomplete': 6.20.0
+ '@codemirror/language': 6.12.1
+ '@codemirror/lint': 6.9.2
+ '@codemirror/state': 6.5.4
+ '@codemirror/view': 6.39.11
+ '@lezer/common': 1.5.0
+ '@lezer/javascript': 1.5.4
+
+ '@codemirror/lang-json@6.0.2':
+ dependencies:
+ '@codemirror/language': 6.12.1
+ '@lezer/json': 1.0.3
+
+ '@codemirror/language@6.12.1':
+ dependencies:
+ '@codemirror/state': 6.5.4
+ '@codemirror/view': 6.39.11
+ '@lezer/common': 1.5.0
+ '@lezer/highlight': 1.2.3
+ '@lezer/lr': 1.4.7
+ style-mod: 4.1.3
+
+ '@codemirror/lint@6.9.2':
+ dependencies:
+ '@codemirror/state': 6.5.4
+ '@codemirror/view': 6.39.11
+ crelt: 1.0.6
+
+ '@codemirror/search@6.6.0':
+ dependencies:
+ '@codemirror/state': 6.5.4
+ '@codemirror/view': 6.39.11
+ crelt: 1.0.6
+
+ '@codemirror/state@6.5.4':
+ dependencies:
+ '@marijn/find-cluster-break': 1.0.2
+
+ '@codemirror/theme-one-dark@6.1.3':
+ dependencies:
+ '@codemirror/language': 6.12.1
+ '@codemirror/state': 6.5.4
+ '@codemirror/view': 6.39.11
+ '@lezer/highlight': 1.2.3
+
+ '@codemirror/view@6.39.11':
+ dependencies:
+ '@codemirror/state': 6.5.4
+ crelt: 1.0.6
+ style-mod: 4.1.3
+ w3c-keyname: 2.2.8
+
'@coinbase/cdp-sdk@1.38.5(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))':
dependencies:
'@solana-program/system': 0.8.1(@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)))
@@ -9226,7 +11276,7 @@ snapshots:
abitype: 1.0.6(typescript@5.9.2)(zod@3.25.76)
axios: 1.13.2
axios-retry: 4.5.0(axios@1.13.2)
- jose: 6.0.12
+ jose: 6.1.3
md5: 2.3.0
uncrypto: 0.1.3
viem: 2.38.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)
@@ -9291,157 +11341,248 @@ snapshots:
'@esbuild/aix-ppc64@0.25.8':
optional: true
+ '@esbuild/aix-ppc64@0.27.2':
+ optional: true
+
'@esbuild/android-arm64@0.17.19':
optional: true
'@esbuild/android-arm64@0.25.8':
optional: true
+ '@esbuild/android-arm64@0.27.2':
+ optional: true
+
'@esbuild/android-arm@0.17.19':
optional: true
'@esbuild/android-arm@0.25.8':
optional: true
+ '@esbuild/android-arm@0.27.2':
+ optional: true
+
'@esbuild/android-x64@0.17.19':
optional: true
'@esbuild/android-x64@0.25.8':
optional: true
+ '@esbuild/android-x64@0.27.2':
+ optional: true
+
'@esbuild/darwin-arm64@0.17.19':
optional: true
'@esbuild/darwin-arm64@0.25.8':
optional: true
+ '@esbuild/darwin-arm64@0.27.2':
+ optional: true
+
'@esbuild/darwin-x64@0.17.19':
optional: true
'@esbuild/darwin-x64@0.25.8':
optional: true
+ '@esbuild/darwin-x64@0.27.2':
+ optional: true
+
'@esbuild/freebsd-arm64@0.17.19':
optional: true
'@esbuild/freebsd-arm64@0.25.8':
optional: true
+ '@esbuild/freebsd-arm64@0.27.2':
+ optional: true
+
'@esbuild/freebsd-x64@0.17.19':
optional: true
'@esbuild/freebsd-x64@0.25.8':
optional: true
+ '@esbuild/freebsd-x64@0.27.2':
+ optional: true
+
'@esbuild/linux-arm64@0.17.19':
optional: true
'@esbuild/linux-arm64@0.25.8':
optional: true
+ '@esbuild/linux-arm64@0.27.2':
+ optional: true
+
'@esbuild/linux-arm@0.17.19':
optional: true
'@esbuild/linux-arm@0.25.8':
optional: true
+ '@esbuild/linux-arm@0.27.2':
+ optional: true
+
'@esbuild/linux-ia32@0.17.19':
optional: true
'@esbuild/linux-ia32@0.25.8':
optional: true
+ '@esbuild/linux-ia32@0.27.2':
+ optional: true
+
'@esbuild/linux-loong64@0.17.19':
optional: true
'@esbuild/linux-loong64@0.25.8':
optional: true
+ '@esbuild/linux-loong64@0.27.2':
+ optional: true
+
'@esbuild/linux-mips64el@0.17.19':
optional: true
'@esbuild/linux-mips64el@0.25.8':
optional: true
+ '@esbuild/linux-mips64el@0.27.2':
+ optional: true
+
'@esbuild/linux-ppc64@0.17.19':
optional: true
'@esbuild/linux-ppc64@0.25.8':
optional: true
+ '@esbuild/linux-ppc64@0.27.2':
+ optional: true
+
'@esbuild/linux-riscv64@0.17.19':
optional: true
'@esbuild/linux-riscv64@0.25.8':
optional: true
+ '@esbuild/linux-riscv64@0.27.2':
+ optional: true
+
'@esbuild/linux-s390x@0.17.19':
optional: true
'@esbuild/linux-s390x@0.25.8':
optional: true
+ '@esbuild/linux-s390x@0.27.2':
+ optional: true
+
'@esbuild/linux-x64@0.17.19':
optional: true
'@esbuild/linux-x64@0.25.8':
optional: true
+ '@esbuild/linux-x64@0.27.2':
+ optional: true
+
'@esbuild/netbsd-arm64@0.25.8':
optional: true
+ '@esbuild/netbsd-arm64@0.27.2':
+ optional: true
+
'@esbuild/netbsd-x64@0.17.19':
optional: true
'@esbuild/netbsd-x64@0.25.8':
optional: true
+ '@esbuild/netbsd-x64@0.27.2':
+ optional: true
+
'@esbuild/openbsd-arm64@0.25.8':
optional: true
+ '@esbuild/openbsd-arm64@0.27.2':
+ optional: true
+
'@esbuild/openbsd-x64@0.17.19':
optional: true
'@esbuild/openbsd-x64@0.25.8':
optional: true
+ '@esbuild/openbsd-x64@0.27.2':
+ optional: true
+
'@esbuild/openharmony-arm64@0.25.8':
optional: true
+ '@esbuild/openharmony-arm64@0.27.2':
+ optional: true
+
'@esbuild/sunos-x64@0.17.19':
optional: true
'@esbuild/sunos-x64@0.25.8':
optional: true
+ '@esbuild/sunos-x64@0.27.2':
+ optional: true
+
'@esbuild/win32-arm64@0.17.19':
optional: true
'@esbuild/win32-arm64@0.25.8':
optional: true
+ '@esbuild/win32-arm64@0.27.2':
+ optional: true
+
'@esbuild/win32-ia32@0.17.19':
optional: true
'@esbuild/win32-ia32@0.25.8':
optional: true
+ '@esbuild/win32-ia32@0.27.2':
+ optional: true
+
'@esbuild/win32-x64@0.17.19':
optional: true
'@esbuild/win32-x64@0.25.8':
optional: true
- '@eslint-community/eslint-utils@4.7.0(eslint@9.32.0)':
+ '@esbuild/win32-x64@0.27.2':
+ optional: true
+
+ '@eslint-community/eslint-utils@4.7.0(eslint@9.32.0(jiti@2.6.1))':
+ dependencies:
+ eslint: 9.32.0(jiti@2.6.1)
+ eslint-visitor-keys: 3.4.3
+
+ '@eslint-community/eslint-utils@4.9.1(eslint@9.32.0(jiti@2.6.1))':
+ dependencies:
+ eslint: 9.32.0(jiti@2.6.1)
+ eslint-visitor-keys: 3.4.3
+ optional: true
+
+ '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))':
dependencies:
- eslint: 9.32.0
+ eslint: 9.39.2(jiti@2.6.1)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
- '@eslint/compat@1.3.1(eslint@9.32.0)':
+ '@eslint-community/regexpp@4.12.2': {}
+
+ '@eslint/compat@1.3.1(eslint@9.32.0(jiti@2.6.1))':
optionalDependencies:
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
'@eslint/config-array@0.21.0':
dependencies:
@@ -9451,12 +11592,28 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@eslint/config-array@0.21.1':
+ dependencies:
+ '@eslint/object-schema': 2.1.7
+ debug: 4.4.3
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+
'@eslint/config-helpers@0.3.0': {}
+ '@eslint/config-helpers@0.4.2':
+ dependencies:
+ '@eslint/core': 0.17.0
+
'@eslint/core@0.15.1':
dependencies:
'@types/json-schema': 7.0.15
+ '@eslint/core@0.17.0':
+ dependencies:
+ '@types/json-schema': 7.0.15
+
'@eslint/eslintrc@3.3.1':
dependencies:
ajv: 6.12.6
@@ -9473,13 +11630,22 @@ snapshots:
'@eslint/js@9.32.0': {}
+ '@eslint/js@9.39.2': {}
+
'@eslint/object-schema@2.1.6': {}
+ '@eslint/object-schema@2.1.7': {}
+
'@eslint/plugin-kit@0.3.4':
dependencies:
'@eslint/core': 0.15.1
levn: 0.4.1
+ '@eslint/plugin-kit@0.4.1':
+ dependencies:
+ '@eslint/core': 0.17.0
+ levn: 0.4.1
+
'@fastify/busboy@2.1.1':
optional: true
@@ -9492,6 +11658,17 @@ snapshots:
'@floating-ui/core': 1.7.3
'@floating-ui/utils': 0.2.10
+ '@floating-ui/dom@1.7.4':
+ dependencies:
+ '@floating-ui/core': 1.7.3
+ '@floating-ui/utils': 0.2.10
+
+ '@floating-ui/react-dom@2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@floating-ui/dom': 1.7.4
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+
'@floating-ui/utils@0.2.10': {}
'@gerrit0/mini-shiki@3.9.2':
@@ -9510,6 +11687,11 @@ snapshots:
'@hapi/hoek': 9.3.0
optional: true
+ '@hookform/resolvers@5.2.2(react-hook-form@7.71.1(react@19.2.3))':
+ dependencies:
+ '@standard-schema/utils': 0.3.0
+ react-hook-form: 7.71.1(react@19.2.3)
+
'@humanfs/core@0.19.1': {}
'@humanfs/node@0.16.6':
@@ -9523,6 +11705,13 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {}
+ '@inquirer/confirm@5.1.14(@types/node@24.10.8)':
+ dependencies:
+ '@inquirer/core': 10.1.15(@types/node@24.10.8)
+ '@inquirer/type': 3.0.8(@types/node@24.10.8)
+ optionalDependencies:
+ '@types/node': 24.10.8
+
'@inquirer/confirm@5.1.14(@types/node@24.2.0)':
dependencies:
'@inquirer/core': 10.1.15(@types/node@24.2.0)
@@ -9530,6 +11719,19 @@ snapshots:
optionalDependencies:
'@types/node': 24.2.0
+ '@inquirer/core@10.1.15(@types/node@24.10.8)':
+ dependencies:
+ '@inquirer/figures': 1.0.13
+ '@inquirer/type': 3.0.8(@types/node@24.10.8)
+ ansi-escapes: 4.3.2
+ cli-width: 4.1.0
+ mute-stream: 2.0.0
+ signal-exit: 4.1.0
+ wrap-ansi: 6.2.0
+ yoctocolors-cjs: 2.1.2
+ optionalDependencies:
+ '@types/node': 24.10.8
+
'@inquirer/core@10.1.15(@types/node@24.2.0)':
dependencies:
'@inquirer/figures': 1.0.13
@@ -9545,6 +11747,10 @@ snapshots:
'@inquirer/figures@1.0.13': {}
+ '@inquirer/type@3.0.8(@types/node@24.10.8)':
+ optionalDependencies:
+ '@types/node': 24.10.8
+
'@inquirer/type@3.0.8(@types/node@24.2.0)':
optionalDependencies:
'@types/node': 24.2.0
@@ -9577,13 +11783,13 @@ snapshots:
'@jest/console@30.0.5':
dependencies:
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
chalk: 4.1.2
jest-message-util: 30.0.5
jest-util: 30.0.5
slash: 3.0.0
- '@jest/core@30.0.5(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2))':
+ '@jest/core@30.0.5(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3))':
dependencies:
'@jest/console': 30.0.5
'@jest/pattern': 30.0.1
@@ -9591,14 +11797,14 @@ snapshots:
'@jest/test-result': 30.0.5
'@jest/transform': 30.0.5
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
ansi-escapes: 4.3.2
chalk: 4.1.2
ci-info: 4.3.0
exit-x: 0.2.2
graceful-fs: 4.2.11
jest-changed-files: 30.0.5
- jest-config: 30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2))
+ jest-config: 30.0.5(@types/node@24.10.8)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3))
jest-haste-map: 30.0.5
jest-message-util: 30.0.5
jest-regex-util: 30.0.1
@@ -9625,7 +11831,7 @@ snapshots:
dependencies:
'@jest/fake-timers': 30.0.5
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
jest-mock: 30.0.5
'@jest/expect-utils@30.0.5':
@@ -9643,7 +11849,7 @@ snapshots:
dependencies:
'@jest/types': 30.0.5
'@sinonjs/fake-timers': 13.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
jest-message-util: 30.0.5
jest-mock: 30.0.5
jest-util: 30.0.5
@@ -9661,7 +11867,7 @@ snapshots:
'@jest/pattern@30.0.1':
dependencies:
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
jest-regex-util: 30.0.1
'@jest/reporters@30.0.5':
@@ -9672,7 +11878,7 @@ snapshots:
'@jest/transform': 30.0.5
'@jest/types': 30.0.5
'@jridgewell/trace-mapping': 0.3.29
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
chalk: 4.1.2
collect-v8-coverage: 1.0.2
exit-x: 0.2.2
@@ -9725,7 +11931,7 @@ snapshots:
'@jest/transform@30.0.5':
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@jest/types': 30.0.5
'@jridgewell/trace-mapping': 0.3.29
babel-plugin-istanbul: 7.0.0
@@ -9749,7 +11955,7 @@ snapshots:
'@jest/schemas': 30.0.5
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
'@types/yargs': 17.0.33
chalk: 4.1.2
@@ -9758,6 +11964,11 @@ snapshots:
'@jridgewell/sourcemap-codec': 1.5.4
'@jridgewell/trace-mapping': 0.3.29
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.12
+ '@jridgewell/trace-mapping': 0.3.29
+
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/source-map@0.3.10':
@@ -9767,6 +11978,8 @@ snapshots:
'@jridgewell/sourcemap-codec@1.5.4': {}
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
'@jridgewell/trace-mapping@0.3.29':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
@@ -9775,9 +11988,31 @@ snapshots:
'@jridgewell/trace-mapping@0.3.9':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.5.4
+ '@jridgewell/sourcemap-codec': 1.5.5
optional: true
+ '@lezer/common@1.5.0': {}
+
+ '@lezer/highlight@1.2.3':
+ dependencies:
+ '@lezer/common': 1.5.0
+
+ '@lezer/javascript@1.5.4':
+ dependencies:
+ '@lezer/common': 1.5.0
+ '@lezer/highlight': 1.2.3
+ '@lezer/lr': 1.4.7
+
+ '@lezer/json@1.0.3':
+ dependencies:
+ '@lezer/common': 1.5.0
+ '@lezer/highlight': 1.2.3
+ '@lezer/lr': 1.4.7
+
+ '@lezer/lr@1.4.7':
+ dependencies:
+ '@lezer/common': 1.5.0
+
'@lit-labs/ssr-dom-shim@1.4.0': {}
'@lit/react@1.0.8(@types/react@19.1.9)':
@@ -9805,6 +12040,16 @@ snapshots:
globby: 11.1.0
read-yaml-file: 1.1.0
+ '@marijn/find-cluster-break@1.0.2': {}
+
+ '@microsoft/api-extractor-model@7.30.7(@types/node@24.10.8)':
+ dependencies:
+ '@microsoft/tsdoc': 0.15.1
+ '@microsoft/tsdoc-config': 0.17.1
+ '@rushstack/node-core-library': 5.14.0(@types/node@24.10.8)
+ transitivePeerDependencies:
+ - '@types/node'
+
'@microsoft/api-extractor-model@7.30.7(@types/node@24.2.0)':
dependencies:
'@microsoft/tsdoc': 0.15.1
@@ -9813,6 +12058,24 @@ snapshots:
transitivePeerDependencies:
- '@types/node'
+ '@microsoft/api-extractor@7.52.10(@types/node@24.10.8)':
+ dependencies:
+ '@microsoft/api-extractor-model': 7.30.7(@types/node@24.10.8)
+ '@microsoft/tsdoc': 0.15.1
+ '@microsoft/tsdoc-config': 0.17.1
+ '@rushstack/node-core-library': 5.14.0(@types/node@24.10.8)
+ '@rushstack/rig-package': 0.5.3
+ '@rushstack/terminal': 0.15.4(@types/node@24.10.8)
+ '@rushstack/ts-command-line': 5.0.2(@types/node@24.10.8)
+ lodash: 4.17.21
+ minimatch: 10.0.3
+ resolve: 1.22.10
+ semver: 7.5.4
+ source-map: 0.6.1
+ typescript: 5.8.2
+ transitivePeerDependencies:
+ - '@types/node'
+
'@microsoft/api-extractor@7.52.10(@types/node@24.2.0)':
dependencies:
'@microsoft/api-extractor-model': 7.30.7(@types/node@24.2.0)
@@ -9851,6 +12114,15 @@ snapshots:
outvariant: 1.4.3
strict-event-emitter: 0.5.1
+ '@mswjs/interceptors@0.40.0':
+ dependencies:
+ '@open-draft/deferred-promise': 2.2.0
+ '@open-draft/logger': 0.3.0
+ '@open-draft/until': 2.1.0
+ is-node-process: 1.2.0
+ outvariant: 1.4.3
+ strict-event-emitter: 0.5.1
+
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
'@emnapi/core': 1.4.5
@@ -9988,6 +12260,439 @@ snapshots:
'@polka/url@1.0.0-next.29':
optional: true
+ '@radix-ui/number@1.1.1': {}
+
+ '@radix-ui/primitive@1.1.3': {}
+
+ '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-context@1.1.2(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ aria-hidden: 1.2.6
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ react-remove-scroll: 2.7.2(@types/react@19.2.8)(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-direction@1.1.1(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-id@1.1.1(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-label@2.1.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ aria-hidden: 1.2.6
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ react-remove-scroll: 2.7.2(@types/react@19.2.8)(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@floating-ui/react-dom': 2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/rect': 1.1.1
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-slot': 1.2.4(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/number': 1.1.1
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/number': 1.1.1
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ aria-hidden: 1.2.6
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ react-remove-scroll: 2.7.2(@types/react@19.2.8)(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-slot@1.2.3(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-slot@1.2.4(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-toast@1.2.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.3
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.8)(react@19.2.3)
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ '@radix-ui/rect': 1.1.1
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-use-size@1.1.1(@types/react@19.2.8)(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3)
+ react: 19.2.3
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+ '@types/react-dom': 19.2.3(@types/react@19.2.8)
+
+ '@radix-ui/rect@1.1.1': {}
+
'@reown/appkit-common@1.8.14(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.22.4)':
dependencies:
big.js: 6.2.2
@@ -10319,6 +13024,8 @@ snapshots:
'@rolldown/pluginutils@1.0.0-beta.27': {}
+ '@rolldown/pluginutils@1.0.0-beta.53': {}
+
'@rollup/plugin-replace@6.0.2(rollup@4.46.2)':
dependencies:
'@rollup/pluginutils': 5.2.0(rollup@4.46.2)
@@ -10326,11 +13033,11 @@ snapshots:
optionalDependencies:
rollup: 4.46.2
- '@rollup/plugin-typescript@12.1.4(rollup@4.46.2)(tslib@2.8.1)(typescript@5.9.2)':
+ '@rollup/plugin-typescript@12.1.4(rollup@4.46.2)(tslib@2.8.1)(typescript@5.9.3)':
dependencies:
'@rollup/pluginutils': 5.2.0(rollup@4.46.2)
resolve: 1.22.10
- typescript: 5.9.2
+ typescript: 5.9.3
optionalDependencies:
rollup: 4.46.2
tslib: 2.8.1
@@ -10414,6 +13121,19 @@ snapshots:
'@rtsao/scc@1.1.0': {}
+ '@rushstack/node-core-library@5.14.0(@types/node@24.10.8)':
+ dependencies:
+ ajv: 8.13.0
+ ajv-draft-04: 1.0.0(ajv@8.13.0)
+ ajv-formats: 3.0.1(ajv@8.13.0)
+ fs-extra: 11.3.0
+ import-lazy: 4.0.0
+ jju: 1.4.0
+ resolve: 1.22.10
+ semver: 7.5.4
+ optionalDependencies:
+ '@types/node': 24.10.8
+
'@rushstack/node-core-library@5.14.0(@types/node@24.2.0)':
dependencies:
ajv: 8.13.0
@@ -10432,6 +13152,13 @@ snapshots:
resolve: 1.22.10
strip-json-comments: 3.1.1
+ '@rushstack/terminal@0.15.4(@types/node@24.10.8)':
+ dependencies:
+ '@rushstack/node-core-library': 5.14.0(@types/node@24.10.8)
+ supports-color: 8.1.1
+ optionalDependencies:
+ '@types/node': 24.10.8
+
'@rushstack/terminal@0.15.4(@types/node@24.2.0)':
dependencies:
'@rushstack/node-core-library': 5.14.0(@types/node@24.2.0)
@@ -10439,6 +13166,15 @@ snapshots:
optionalDependencies:
'@types/node': 24.2.0
+ '@rushstack/ts-command-line@5.0.2(@types/node@24.10.8)':
+ dependencies:
+ '@rushstack/terminal': 0.15.4(@types/node@24.10.8)
+ '@types/argparse': 1.0.38
+ argparse: 1.0.10
+ string-argv: 0.3.2
+ transitivePeerDependencies:
+ - '@types/node'
+
'@rushstack/ts-command-line@5.0.2(@types/node@24.2.0)':
dependencies:
'@rushstack/terminal': 0.15.4(@types/node@24.2.0)
@@ -11463,6 +14199,8 @@ snapshots:
solid-js: 1.9.7
optional: true
+ '@standard-schema/utils@0.3.0': {}
+
'@swc/core-darwin-arm64@1.5.29':
optional: true
@@ -11496,7 +14234,7 @@ snapshots:
'@swc/core@1.5.29(@swc/helpers@0.5.17)':
dependencies:
'@swc/counter': 0.1.3
- '@swc/types': 0.1.23
+ '@swc/types': 0.1.25
optionalDependencies:
'@swc/core-darwin-arm64': 1.5.29
'@swc/core-darwin-x64': 1.5.29
@@ -11519,11 +14257,84 @@ snapshots:
tslib: 2.8.1
optional: true
- '@swc/types@0.1.23':
+ '@swc/types@0.1.25':
dependencies:
'@swc/counter': 0.1.3
optional: true
+ '@tailwindcss/node@4.1.18':
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ enhanced-resolve: 5.18.4
+ jiti: 2.6.1
+ lightningcss: 1.30.2
+ magic-string: 0.30.21
+ source-map-js: 1.2.1
+ tailwindcss: 4.1.18
+
+ '@tailwindcss/oxide-android-arm64@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-arm64@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-x64@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-freebsd-x64@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-musl@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-wasm32-wasi@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.18':
+ optional: true
+
+ '@tailwindcss/oxide@4.1.18':
+ optionalDependencies:
+ '@tailwindcss/oxide-android-arm64': 4.1.18
+ '@tailwindcss/oxide-darwin-arm64': 4.1.18
+ '@tailwindcss/oxide-darwin-x64': 4.1.18
+ '@tailwindcss/oxide-freebsd-x64': 4.1.18
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18
+ '@tailwindcss/oxide-linux-arm64-musl': 4.1.18
+ '@tailwindcss/oxide-linux-x64-gnu': 4.1.18
+ '@tailwindcss/oxide-linux-x64-musl': 4.1.18
+ '@tailwindcss/oxide-wasm32-wasi': 4.1.18
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18
+ '@tailwindcss/oxide-win32-x64-msvc': 4.1.18
+
+ '@tailwindcss/typography@0.5.19(tailwindcss@4.1.18)':
+ dependencies:
+ postcss-selector-parser: 6.0.10
+ tailwindcss: 4.1.18
+
+ '@tailwindcss/vite@4.1.18(vite@7.3.1(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))':
+ dependencies:
+ '@tailwindcss/node': 4.1.18
+ '@tailwindcss/oxide': 4.1.18
+ tailwindcss: 4.1.18
+ vite: 7.3.1(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+
'@ton-community/assets-sdk@0.0.5(@ton/core@0.61.0(@ton/crypto@3.3.0))(@ton/crypto@3.3.0)(@ton/ton@15.3.1(@ton/core@0.61.0(@ton/crypto@3.3.0))(@ton/crypto@3.3.0))':
dependencies:
'@aws-sdk/client-s3': 3.859.0
@@ -11547,6 +14358,10 @@ snapshots:
'@ton/crypto': 3.3.0
symbol.inspect: 1.0.1
+ '@ton/core@0.62.1(@ton/crypto@3.3.0)':
+ dependencies:
+ '@ton/crypto': 3.3.0
+
'@ton/crypto-primitives@2.1.0':
dependencies:
jssha: 3.2.0
@@ -11569,7 +14384,19 @@ snapshots:
transitivePeerDependencies:
- debug
- '@tsconfig/node10@1.0.11':
+ '@ton/ton@16.1.0(@ton/core@0.62.1(@ton/crypto@3.3.0))(@ton/crypto@3.3.0)':
+ dependencies:
+ '@ton/core': 0.62.1(@ton/crypto@3.3.0)
+ '@ton/crypto': 3.3.0
+ axios: 1.13.2
+ dataloader: 2.2.3
+ symbol.inspect: 1.0.1
+ teslabot: 1.5.0
+ zod: 3.25.76
+ transitivePeerDependencies:
+ - debug
+
+ '@tsconfig/node10@1.0.12':
optional: true
'@tsconfig/node12@1.0.11':
@@ -11615,7 +14442,7 @@ snapshots:
'@types/connect@3.4.38':
dependencies:
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
optional: true
'@types/cookie@0.5.4':
@@ -11626,7 +14453,6 @@ snapshots:
'@types/debug@4.1.12':
dependencies:
'@types/ms': 2.1.0
- optional: true
'@types/deep-eql@4.0.2': {}
@@ -11635,10 +14461,14 @@ snapshots:
'@types/eslint': 9.6.1
'@types/estree': 1.0.8
- '@types/eslint@9.6.1':
+ '@types/eslint@9.6.1':
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/json-schema': 7.0.15
+
+ '@types/estree-jsx@1.0.5':
dependencies:
'@types/estree': 1.0.8
- '@types/json-schema': 7.0.15
'@types/estree@1.0.8': {}
@@ -11667,11 +14497,18 @@ snapshots:
'@types/json5@0.0.29': {}
- '@types/ms@2.1.0':
- optional: true
+ '@types/mdast@4.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/ms@2.1.0': {}
'@types/node@12.20.55': {}
+ '@types/node@24.10.8':
+ dependencies:
+ undici-types: 7.16.0
+
'@types/node@24.2.0':
dependencies:
undici-types: 7.10.0
@@ -11683,10 +14520,18 @@ snapshots:
dependencies:
'@types/react': 19.1.9
+ '@types/react-dom@19.2.3(@types/react@19.2.8)':
+ dependencies:
+ '@types/react': 19.2.8
+
'@types/react@19.1.9':
dependencies:
csstype: 3.1.1
+ '@types/react@19.2.8':
+ dependencies:
+ csstype: 3.2.3
+
'@types/stack-utils@2.0.3': {}
'@types/statuses@2.0.6': {}
@@ -11697,6 +14542,8 @@ snapshots:
'@types/ua-parser-js@0.7.39': {}
+ '@types/unist@2.0.11': {}
+
'@types/unist@3.0.3': {}
'@types/uuid@8.3.4':
@@ -11706,12 +14553,12 @@ snapshots:
'@types/ws@7.4.7':
dependencies:
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
optional: true
'@types/ws@8.18.1':
dependencies:
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
optional: true
'@types/yargs-parser@21.0.3': {}
@@ -11720,15 +14567,15 @@ snapshots:
dependencies:
'@types/yargs-parser': 21.0.3
- '@typescript-eslint/eslint-plugin@8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint@9.32.0)(typescript@5.9.2)':
+ '@typescript-eslint/eslint-plugin@8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.39.0(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/parser': 8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
'@typescript-eslint/scope-manager': 8.39.0
- '@typescript-eslint/type-utils': 8.39.0(eslint@9.32.0)(typescript@5.9.2)
- '@typescript-eslint/utils': 8.39.0(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/type-utils': 8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
'@typescript-eslint/visitor-keys': 8.39.0
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
graphemer: 1.4.0
ignore: 7.0.5
natural-compare: 1.4.0
@@ -11737,18 +14584,46 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2)':
+ '@typescript-eslint/eslint-plugin@8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
+ dependencies:
+ '@eslint-community/regexpp': 4.12.2
+ '@typescript-eslint/parser': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/scope-manager': 8.53.0
+ '@typescript-eslint/type-utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.53.0
+ eslint: 9.39.2(jiti@2.6.1)
+ ignore: 7.0.5
+ natural-compare: 1.4.0
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)':
dependencies:
'@typescript-eslint/scope-manager': 8.39.0
'@typescript-eslint/types': 8.39.0
'@typescript-eslint/typescript-estree': 8.39.0(typescript@5.9.2)
'@typescript-eslint/visitor-keys': 8.39.0
debug: 4.4.1
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
typescript: 5.9.2
transitivePeerDependencies:
- supports-color
+ '@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/scope-manager': 8.53.0
+ '@typescript-eslint/types': 8.53.0
+ '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.53.0
+ debug: 4.4.3
+ eslint: 9.39.2(jiti@2.6.1)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
'@typescript-eslint/project-service@8.39.0(typescript@5.9.2)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.39.0(typescript@5.9.2)
@@ -11758,29 +14633,76 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@typescript-eslint/project-service@8.53.0(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/tsconfig-utils': 8.53.0(typescript@5.9.2)
+ '@typescript-eslint/types': 8.53.0
+ debug: 4.4.3
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ '@typescript-eslint/project-service@8.53.0(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/tsconfig-utils': 8.53.0(typescript@5.9.3)
+ '@typescript-eslint/types': 8.53.0
+ debug: 4.4.3
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
'@typescript-eslint/scope-manager@8.39.0':
dependencies:
'@typescript-eslint/types': 8.39.0
'@typescript-eslint/visitor-keys': 8.39.0
+ '@typescript-eslint/scope-manager@8.53.0':
+ dependencies:
+ '@typescript-eslint/types': 8.53.0
+ '@typescript-eslint/visitor-keys': 8.53.0
+
'@typescript-eslint/tsconfig-utils@8.39.0(typescript@5.9.2)':
dependencies:
typescript: 5.9.2
- '@typescript-eslint/type-utils@8.39.0(eslint@9.32.0)(typescript@5.9.2)':
+ '@typescript-eslint/tsconfig-utils@8.53.0(typescript@5.9.2)':
+ dependencies:
+ typescript: 5.9.2
+ optional: true
+
+ '@typescript-eslint/tsconfig-utils@8.53.0(typescript@5.9.3)':
+ dependencies:
+ typescript: 5.9.3
+
+ '@typescript-eslint/type-utils@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)':
dependencies:
'@typescript-eslint/types': 8.39.0
'@typescript-eslint/typescript-estree': 8.39.0(typescript@5.9.2)
- '@typescript-eslint/utils': 8.39.0(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
debug: 4.4.1
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
ts-api-utils: 2.1.0(typescript@5.9.2)
typescript: 5.9.2
transitivePeerDependencies:
- supports-color
+ '@typescript-eslint/type-utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/types': 8.53.0
+ '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ debug: 4.4.3
+ eslint: 9.39.2(jiti@2.6.1)
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
'@typescript-eslint/types@8.39.0': {}
+ '@typescript-eslint/types@8.53.0': {}
+
'@typescript-eslint/typescript-estree@8.39.0(typescript@5.9.2)':
dependencies:
'@typescript-eslint/project-service': 8.39.0(typescript@5.9.2)
@@ -11797,22 +14719,108 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.39.0(eslint@9.32.0)(typescript@5.9.2)':
+ '@typescript-eslint/typescript-estree@8.53.0(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/project-service': 8.53.0(typescript@5.9.2)
+ '@typescript-eslint/tsconfig-utils': 8.53.0(typescript@5.9.2)
+ '@typescript-eslint/types': 8.53.0
+ '@typescript-eslint/visitor-keys': 8.53.0
+ debug: 4.4.3
+ minimatch: 9.0.5
+ semver: 7.7.3
+ tinyglobby: 0.2.15
+ ts-api-utils: 2.4.0(typescript@5.9.2)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ '@typescript-eslint/typescript-estree@8.53.0(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/project-service': 8.53.0(typescript@5.9.3)
+ '@typescript-eslint/tsconfig-utils': 8.53.0(typescript@5.9.3)
+ '@typescript-eslint/types': 8.53.0
+ '@typescript-eslint/visitor-keys': 8.53.0
+ debug: 4.4.3
+ minimatch: 9.0.5
+ semver: 7.7.3
+ tinyglobby: 0.2.15
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)':
dependencies:
- '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0)
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0(jiti@2.6.1))
'@typescript-eslint/scope-manager': 8.39.0
'@typescript-eslint/types': 8.39.0
'@typescript-eslint/typescript-estree': 8.39.0(typescript@5.9.2)
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@8.53.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@9.32.0(jiti@2.6.1))
+ '@typescript-eslint/scope-manager': 8.53.0
+ '@typescript-eslint/types': 8.53.0
+ '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.2)
+ eslint: 9.32.0(jiti@2.6.1)
typescript: 5.9.2
transitivePeerDependencies:
- supports-color
+ optional: true
+
+ '@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1))
+ '@typescript-eslint/scope-manager': 8.53.0
+ '@typescript-eslint/types': 8.53.0
+ '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3)
+ eslint: 9.39.2(jiti@2.6.1)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
'@typescript-eslint/visitor-keys@8.39.0':
dependencies:
'@typescript-eslint/types': 8.39.0
eslint-visitor-keys: 4.2.1
+ '@typescript-eslint/visitor-keys@8.53.0':
+ dependencies:
+ '@typescript-eslint/types': 8.53.0
+ eslint-visitor-keys: 4.2.1
+
+ '@uiw/codemirror-extensions-basic-setup@4.25.4(@codemirror/autocomplete@6.20.0)(@codemirror/commands@6.10.1)(@codemirror/language@6.12.1)(@codemirror/lint@6.9.2)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/view@6.39.11)':
+ dependencies:
+ '@codemirror/autocomplete': 6.20.0
+ '@codemirror/commands': 6.10.1
+ '@codemirror/language': 6.12.1
+ '@codemirror/lint': 6.9.2
+ '@codemirror/search': 6.6.0
+ '@codemirror/state': 6.5.4
+ '@codemirror/view': 6.39.11
+
+ '@uiw/react-codemirror@4.25.4(@babel/runtime@7.28.6)(@codemirror/autocomplete@6.20.0)(@codemirror/language@6.12.1)(@codemirror/lint@6.9.2)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.39.11)(codemirror@6.0.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@babel/runtime': 7.28.6
+ '@codemirror/commands': 6.10.1
+ '@codemirror/state': 6.5.4
+ '@codemirror/theme-one-dark': 6.1.3
+ '@codemirror/view': 6.39.11
+ '@uiw/codemirror-extensions-basic-setup': 4.25.4(@codemirror/autocomplete@6.20.0)(@codemirror/commands@6.10.1)(@codemirror/language@6.12.1)(@codemirror/lint@6.9.2)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/view@6.39.11)
+ codemirror: 6.0.2
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ transitivePeerDependencies:
+ - '@codemirror/autocomplete'
+ - '@codemirror/language'
+ - '@codemirror/lint'
+ - '@codemirror/search'
+
'@ungap/structured-clone@1.3.0': {}
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
@@ -11874,7 +14882,19 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
- '@vitejs/plugin-react@4.7.0(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))':
+ '@vitejs/plugin-react@4.7.0(vite@7.0.6(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))':
+ dependencies:
+ '@babel/core': 7.28.0
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.0)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.0)
+ '@rolldown/pluginutils': 1.0.0-beta.27
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.17.0
+ vite: 7.0.6(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@vitejs/plugin-react@4.7.0(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))':
dependencies:
'@babel/core': 7.28.0
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.0)
@@ -11882,11 +14902,23 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-beta.27
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ vite: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@vitejs/plugin-react@5.1.2(vite@7.3.1(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.6)
+ '@rolldown/pluginutils': 1.0.0-beta.53
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.18.0
+ vite: 7.3.1(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
transitivePeerDependencies:
- supports-color
- '@vitest/coverage-istanbul@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))':
+ '@vitest/coverage-istanbul@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))':
dependencies:
'@istanbuljs/schema': 0.1.3
debug: 4.4.1
@@ -11898,7 +14930,7 @@ snapshots:
magicast: 0.3.5
test-exclude: 7.0.1
tinyrainbow: 2.0.0
- vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
transitivePeerDependencies:
- supports-color
@@ -11910,14 +14942,23 @@ snapshots:
chai: 5.2.1
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.4(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))':
+ '@vitest/mocker@3.2.4(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.2))(vite@7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))':
+ dependencies:
+ '@vitest/spy': 3.2.4
+ estree-walker: 3.0.3
+ magic-string: 0.30.17
+ optionalDependencies:
+ msw: 2.12.7(@types/node@24.2.0)(typescript@5.9.2)
+ vite: 7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+
+ '@vitest/mocker@3.2.4(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(vite@7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
- msw: 2.10.4(@types/node@24.2.0)(typescript@5.9.2)
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ msw: 2.12.7(@types/node@24.2.0)(typescript@5.9.3)
+ vite: 7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -12467,6 +15508,10 @@ snapshots:
optionalDependencies:
ajv: 8.13.0
+ ajv-formats@3.0.1(ajv@8.17.1):
+ optionalDependencies:
+ ajv: 8.17.1
+
ajv-keywords@5.1.0(ajv@8.17.1):
dependencies:
ajv: 8.17.1
@@ -12538,6 +15583,10 @@ snapshots:
argparse@2.0.1: {}
+ aria-hidden@1.2.6:
+ dependencies:
+ tslib: 2.8.1
+
array-buffer-byte-length@1.0.2:
dependencies:
call-bound: 1.0.4
@@ -12617,6 +15666,15 @@ snapshots:
atomic-sleep@1.0.0: {}
+ autoprefixer@10.4.23(postcss@8.5.6):
+ dependencies:
+ browserslist: 4.28.1
+ caniuse-lite: 1.0.30001764
+ fraction.js: 5.3.4
+ picocolors: 1.1.1
+ postcss: 8.5.6
+ postcss-value-parser: 4.2.0
+
available-typed-arrays@1.0.7:
dependencies:
possible-typed-array-names: 1.1.0
@@ -12629,20 +15687,20 @@ snapshots:
axios@0.21.4:
dependencies:
- follow-redirects: 1.15.11(debug@4.4.1)
+ follow-redirects: 1.15.11(debug@4.4.3)
transitivePeerDependencies:
- debug
- axios@0.25.0(debug@4.4.1):
+ axios@0.25.0(debug@4.4.3):
dependencies:
- follow-redirects: 1.15.11(debug@4.4.1)
+ follow-redirects: 1.15.11(debug@4.4.3)
transitivePeerDependencies:
- debug
optional: true
axios@1.11.0:
dependencies:
- follow-redirects: 1.15.11(debug@4.4.1)
+ follow-redirects: 1.15.11(debug@4.4.3)
form-data: 4.0.4
proxy-from-env: 1.1.0
transitivePeerDependencies:
@@ -12650,20 +15708,19 @@ snapshots:
axios@1.13.2:
dependencies:
- follow-redirects: 1.15.11(debug@4.4.1)
+ follow-redirects: 1.15.11(debug@4.4.3)
form-data: 4.0.4
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
- optional: true
- babel-jest@30.0.5(@babel/core@7.28.0):
+ babel-jest@30.0.5(@babel/core@7.28.6):
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@jest/transform': 30.0.5
'@types/babel__core': 7.20.5
babel-plugin-istanbul: 7.0.0
- babel-preset-jest: 30.0.1(@babel/core@7.28.0)
+ babel-preset-jest: 30.0.1(@babel/core@7.28.6)
chalk: 4.1.2
graceful-fs: 4.2.11
slash: 3.0.0
@@ -12682,8 +15739,8 @@ snapshots:
babel-plugin-jest-hoist@30.0.1:
dependencies:
- '@babel/template': 7.27.2
- '@babel/types': 7.28.2
+ '@babel/template': 7.28.6
+ '@babel/types': 7.28.6
'@types/babel__core': 7.20.5
babel-plugin-jsx-dom-expressions@0.39.8(@babel/core@7.28.0):
@@ -12696,70 +15753,89 @@ snapshots:
parse5: 7.3.0
validate-html-nesting: 1.2.3
+ babel-plugin-jsx-dom-expressions@0.39.8(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-imports': 7.18.6
+ '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.6)
+ '@babel/types': 7.28.2
+ html-entities: 2.3.3
+ parse5: 7.3.0
+ validate-html-nesting: 1.2.3
+ optional: true
+
babel-plugin-macros@3.1.0:
dependencies:
- '@babel/runtime': 7.28.2
+ '@babel/runtime': 7.28.6
cosmiconfig: 7.1.0
- resolve: 1.22.10
+ resolve: 1.22.11
optional: true
- babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.0):
+ babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.6):
dependencies:
'@babel/compat-data': 7.28.0
- '@babel/core': 7.28.0
- '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6)
semver: 6.3.1
transitivePeerDependencies:
- supports-color
optional: true
- babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.0):
+ babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.6):
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6)
core-js-compat: 3.45.0
transitivePeerDependencies:
- supports-color
optional: true
- babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.0):
+ babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.6):
dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6)
transitivePeerDependencies:
- supports-color
optional: true
- babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.0):
- dependencies:
- '@babel/core': 7.28.0
- '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.0)
- '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0)
- '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.0)
- '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.0)
- '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.0)
- '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.0)
- '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.0)
- '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.0)
- '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.0)
- '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.0)
- '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.0)
- '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.0)
- '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.0)
- '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.0)
-
- babel-preset-jest@30.0.1(@babel/core@7.28.0):
- dependencies:
- '@babel/core': 7.28.0
+ babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.6)
+ '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.6)
+ '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.6)
+ '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.6)
+ '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.6)
+ '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.6)
+ '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6)
+ '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.6)
+ '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.6)
+
+ babel-preset-jest@30.0.1(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
babel-plugin-jest-hoist: 30.0.1
- babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.0)
+ babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.6)
babel-preset-solid@1.9.6(@babel/core@7.28.0):
dependencies:
'@babel/core': 7.28.0
babel-plugin-jsx-dom-expressions: 0.39.8(@babel/core@7.28.0)
+ babel-preset-solid@1.9.6(@babel/core@7.28.6):
+ dependencies:
+ '@babel/core': 7.28.6
+ babel-plugin-jsx-dom-expressions: 0.39.8(@babel/core@7.28.6)
+ optional: true
+
+ bail@2.0.2: {}
+
balanced-match@1.0.2: {}
base-x@3.0.11:
@@ -12772,6 +15848,8 @@ snapshots:
base64-js@1.5.1: {}
+ baseline-browser-mapping@2.9.14: {}
+
better-path-resolve@1.0.0:
dependencies:
is-windows: 1.0.2
@@ -12848,6 +15926,14 @@ snapshots:
node-releases: 2.0.19
update-browserslist-db: 1.1.3(browserslist@4.25.1)
+ browserslist@4.28.1:
+ dependencies:
+ baseline-browser-mapping: 2.9.14
+ caniuse-lite: 1.0.30001764
+ electron-to-chromium: 1.5.267
+ node-releases: 2.0.27
+ update-browserslist-db: 1.2.3(browserslist@4.28.1)
+
bs-logger@0.2.6:
dependencies:
fast-json-stable-stringify: 2.1.0
@@ -12916,6 +16002,10 @@ snapshots:
caniuse-lite@1.0.30001731: {}
+ caniuse-lite@1.0.30001764: {}
+
+ ccount@2.0.1: {}
+
chai@5.2.1:
dependencies:
assertion-error: 2.0.1
@@ -12934,6 +16024,14 @@ snapshots:
char-regex@1.0.2: {}
+ character-entities-html4@2.1.0: {}
+
+ character-entities-legacy@3.0.0: {}
+
+ character-entities@2.0.2: {}
+
+ character-reference-invalid@2.0.1: {}
+
chardet@0.7.0: {}
charenc@0.0.2:
@@ -12984,6 +16082,10 @@ snapshots:
class-is@1.1.0: {}
+ class-variance-authority@0.7.1:
+ dependencies:
+ clsx: 2.1.1
+
classnames@2.5.1: {}
cli-boxes@2.2.1: {}
@@ -13021,8 +16123,20 @@ snapshots:
clsx@1.2.1:
optional: true
+ clsx@2.1.1: {}
+
co@4.6.0: {}
+ codemirror@6.0.2:
+ dependencies:
+ '@codemirror/autocomplete': 6.20.0
+ '@codemirror/commands': 6.10.1
+ '@codemirror/language': 6.12.1
+ '@codemirror/lint': 6.9.2
+ '@codemirror/search': 6.6.0
+ '@codemirror/state': 6.5.4
+ '@codemirror/view': 6.39.11
+
collect-v8-coverage@1.0.2: {}
color-convert@2.0.1:
@@ -13037,6 +16151,8 @@ snapshots:
dependencies:
delayed-stream: 1.0.0
+ comma-separated-tokens@2.0.3: {}
+
commander@10.0.1: {}
commander@14.0.0:
@@ -13096,7 +16212,7 @@ snapshots:
core-js-compat@3.45.0:
dependencies:
- browserslist: 4.25.1
+ browserslist: 4.28.1
optional: true
cosmiconfig@7.1.0:
@@ -13113,6 +16229,8 @@ snapshots:
create-require@1.1.1:
optional: true
+ crelt@1.0.6: {}
+
cross-fetch@3.2.0:
dependencies:
node-fetch: 2.7.0
@@ -13143,6 +16261,8 @@ snapshots:
mdn-data: 2.12.2
source-map-js: 1.2.1
+ cssesc@3.0.0: {}
+
cssstyle@5.3.1(postcss@8.5.6):
dependencies:
'@asamuzakjp/css-color': 4.0.5
@@ -13155,6 +16275,8 @@ snapshots:
csstype@3.1.3: {}
+ csstype@3.2.3: {}
+
data-urls@6.0.0:
dependencies:
whatwg-mimetype: 4.0.0
@@ -13197,10 +16319,18 @@ snapshots:
dependencies:
ms: 2.1.3
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
decamelize@1.2.0: {}
decimal.js@10.6.0: {}
+ decode-named-character-reference@1.2.0:
+ dependencies:
+ character-entities: 2.0.2
+
dedent@1.6.0(babel-plugin-macros@3.1.0):
optionalDependencies:
babel-plugin-macros: 3.1.0
@@ -13254,8 +16384,7 @@ snapshots:
delayed-stream@1.0.0: {}
- dequal@2.0.3:
- optional: true
+ dequal@2.0.3: {}
destr@2.0.5: {}
@@ -13266,8 +16395,16 @@ snapshots:
detect-libc@1.0.3:
optional: true
+ detect-libc@2.1.2: {}
+
detect-newline@3.1.0: {}
+ detect-node-es@1.1.0: {}
+
+ devlop@1.1.0:
+ dependencies:
+ dequal: 2.0.3
+
diff@4.0.2:
optional: true
@@ -13296,6 +16433,8 @@ snapshots:
electron-to-chromium@1.5.195: {}
+ electron-to-chromium@1.5.267: {}
+
emittery@0.13.1: {}
emoji-regex@8.0.0: {}
@@ -13312,6 +16451,11 @@ snapshots:
graceful-fs: 4.2.10
tapable: 2.2.2
+ enhanced-resolve@5.18.4:
+ dependencies:
+ graceful-fs: 4.2.11
+ tapable: 2.2.2
+
enquirer@2.4.1:
dependencies:
ansi-colors: 4.1.3
@@ -13447,9 +16591,9 @@ snapshots:
esbuild-plugin-solid@0.5.0(esbuild@0.17.19)(solid-js@1.9.7):
dependencies:
- '@babel/core': 7.28.0
- '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0)
- babel-preset-solid: 1.9.6(@babel/core@7.28.0)
+ '@babel/core': 7.28.6
+ '@babel/preset-typescript': 7.27.1(@babel/core@7.28.6)
+ babel-preset-solid: 1.9.6(@babel/core@7.28.6)
esbuild: 0.17.19
solid-js: 1.9.7
transitivePeerDependencies:
@@ -13511,6 +16655,35 @@ snapshots:
'@esbuild/win32-ia32': 0.25.8
'@esbuild/win32-x64': 0.25.8
+ esbuild@0.27.2:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.27.2
+ '@esbuild/android-arm': 0.27.2
+ '@esbuild/android-arm64': 0.27.2
+ '@esbuild/android-x64': 0.27.2
+ '@esbuild/darwin-arm64': 0.27.2
+ '@esbuild/darwin-x64': 0.27.2
+ '@esbuild/freebsd-arm64': 0.27.2
+ '@esbuild/freebsd-x64': 0.27.2
+ '@esbuild/linux-arm': 0.27.2
+ '@esbuild/linux-arm64': 0.27.2
+ '@esbuild/linux-ia32': 0.27.2
+ '@esbuild/linux-loong64': 0.27.2
+ '@esbuild/linux-mips64el': 0.27.2
+ '@esbuild/linux-ppc64': 0.27.2
+ '@esbuild/linux-riscv64': 0.27.2
+ '@esbuild/linux-s390x': 0.27.2
+ '@esbuild/linux-x64': 0.27.2
+ '@esbuild/netbsd-arm64': 0.27.2
+ '@esbuild/netbsd-x64': 0.27.2
+ '@esbuild/openbsd-arm64': 0.27.2
+ '@esbuild/openbsd-x64': 0.27.2
+ '@esbuild/openharmony-arm64': 0.27.2
+ '@esbuild/sunos-x64': 0.27.2
+ '@esbuild/win32-arm64': 0.27.2
+ '@esbuild/win32-ia32': 0.27.2
+ '@esbuild/win32-x64': 0.27.2
+
escalade@3.2.0: {}
escape-html@1.0.3:
@@ -13522,9 +16695,11 @@ snapshots:
escape-string-regexp@4.0.0: {}
- eslint-config-prettier@10.1.8(eslint@9.32.0):
+ escape-string-regexp@5.0.0: {}
+
+ eslint-config-prettier@10.1.8(eslint@9.32.0(jiti@2.6.1)):
dependencies:
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
optional: true
eslint-import-context@0.1.9(unrs-resolver@1.11.1):
@@ -13542,10 +16717,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0))(eslint-plugin-import@2.32.0)(eslint@9.32.0):
+ eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.53.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.6.1)):
dependencies:
debug: 4.4.1
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
get-tsconfig: 4.10.1
is-bun-module: 2.0.0
@@ -13553,42 +16728,42 @@ snapshots:
tinyglobby: 0.2.14
unrs-resolver: 1.11.1
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0)
- eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0)
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0(jiti@2.6.1))
+ eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.53.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 8.39.0(eslint@9.32.0)(typescript@5.9.2)
- eslint: 9.32.0
+ '@typescript-eslint/parser': 8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
+ eslint: 9.32.0(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0))(eslint-plugin-import@2.32.0)(eslint@9.32.0)
+ eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.53.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
- eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0):
+ eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.53.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.32.0(jiti@2.6.1)):
dependencies:
- '@typescript-eslint/types': 8.39.0
+ '@typescript-eslint/types': 8.53.0
comment-parser: 1.4.1
- debug: 4.4.1
- eslint: 9.32.0
+ debug: 4.4.3
+ eslint: 9.32.0(jiti@2.6.1)
eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
is-glob: 4.0.3
- minimatch: 10.0.3
- semver: 7.7.2
+ minimatch: 10.1.1
+ semver: 7.7.3
stable-hash-x: 0.2.0
unrs-resolver: 1.11.1
optionalDependencies:
- '@typescript-eslint/utils': 8.39.0(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.53.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
optional: true
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -13597,9 +16772,9 @@ snapshots:
array.prototype.flatmap: 1.3.3
debug: 3.2.7
doctrine: 2.1.0
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0)
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.32.0(jiti@2.6.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -13611,27 +16786,68 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.39.0(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/parser': 8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.32.0))(eslint@9.32.0)(prettier@3.6.2):
+ eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.32.0(jiti@2.6.1)))(eslint@9.32.0(jiti@2.6.1))(prettier@3.6.2):
dependencies:
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
prettier: 3.6.2
prettier-linter-helpers: 1.0.0
synckit: 0.11.11
optionalDependencies:
'@types/eslint': 9.6.1
- eslint-config-prettier: 10.1.8(eslint@9.32.0)
+ eslint-config-prettier: 10.1.8(eslint@9.32.0(jiti@2.6.1))
+
+ eslint-plugin-react-hooks@5.2.0(eslint@9.32.0(jiti@2.6.1)):
+ dependencies:
+ eslint: 9.32.0(jiti@2.6.1)
+
+ eslint-plugin-react-hooks@5.2.0(eslint@9.39.2(jiti@2.6.1)):
+ dependencies:
+ eslint: 9.39.2(jiti@2.6.1)
+
+ eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/parser': 7.28.6
+ eslint: 9.39.2(jiti@2.6.1)
+ hermes-parser: 0.25.1
+ zod: 4.3.5
+ zod-validation-error: 4.0.2(zod@4.3.5)
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint-plugin-react-refresh@0.4.26(eslint@9.39.2(jiti@2.6.1)):
+ dependencies:
+ eslint: 9.39.2(jiti@2.6.1)
- eslint-plugin-react-hooks@5.2.0(eslint@9.32.0):
+ eslint-plugin-react@7.37.5(eslint@9.32.0(jiti@2.6.1)):
dependencies:
- eslint: 9.32.0
+ array-includes: 3.1.9
+ array.prototype.findlast: 1.2.5
+ array.prototype.flatmap: 1.3.3
+ array.prototype.tosorted: 1.1.4
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.2.1
+ eslint: 9.32.0(jiti@2.6.1)
+ estraverse: 5.3.0
+ hasown: 2.0.2
+ jsx-ast-utils: 3.3.3
+ minimatch: 3.1.2
+ object.entries: 1.1.9
+ object.fromentries: 2.0.8
+ object.values: 1.2.1
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 6.3.1
+ string.prototype.matchall: 4.0.12
+ string.prototype.repeat: 1.0.0
- eslint-plugin-react@7.37.5(eslint@9.32.0):
+ eslint-plugin-react@7.37.5(eslint@9.39.2(jiti@2.6.1)):
dependencies:
array-includes: 3.1.9
array.prototype.findlast: 1.2.5
@@ -13639,7 +16855,7 @@ snapshots:
array.prototype.tosorted: 1.1.4
doctrine: 2.1.0
es-iterator-helpers: 1.2.1
- eslint: 9.32.0
+ eslint: 9.39.2(jiti@2.6.1)
estraverse: 5.3.0
hasown: 2.0.2
jsx-ast-utils: 3.3.3
@@ -13653,10 +16869,10 @@ snapshots:
string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0
- eslint-plugin-solid@0.14.5(eslint@9.32.0)(typescript@5.9.2):
+ eslint-plugin-solid@0.14.5(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2):
dependencies:
- '@typescript-eslint/utils': 8.39.0(eslint@9.32.0)(typescript@5.9.2)
- eslint: 9.32.0
+ '@typescript-eslint/utils': 8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
+ eslint: 9.32.0(jiti@2.6.1)
estraverse: 5.3.0
is-html: 2.0.0
kebab-case: 1.0.2
@@ -13666,11 +16882,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint@9.32.0)(typescript@5.9.2))(eslint@9.32.0):
+ eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.6.1)):
dependencies:
- eslint: 9.32.0
+ eslint: 9.32.0(jiti@2.6.1)
optionalDependencies:
- '@typescript-eslint/eslint-plugin': 8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0)(typescript@5.9.2))(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/eslint-plugin': 8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.6.1))(typescript@5.9.2)
eslint-scope@5.1.1:
dependencies:
@@ -13686,9 +16902,9 @@ snapshots:
eslint-visitor-keys@4.2.1: {}
- eslint@9.32.0:
+ eslint@9.32.0(jiti@2.6.1):
dependencies:
- '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0)
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0(jiti@2.6.1))
'@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.21.0
'@eslint/config-helpers': 0.3.0
@@ -13723,6 +16939,49 @@ snapshots:
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.4
+ optionalDependencies:
+ jiti: 2.6.1
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint@9.39.2(jiti@2.6.1):
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1))
+ '@eslint-community/regexpp': 4.12.2
+ '@eslint/config-array': 0.21.1
+ '@eslint/config-helpers': 0.4.2
+ '@eslint/core': 0.17.0
+ '@eslint/eslintrc': 3.3.1
+ '@eslint/js': 9.39.2
+ '@eslint/plugin-kit': 0.4.1
+ '@humanfs/node': 0.16.6
+ '@humanwhocodes/module-importer': 1.0.1
+ '@humanwhocodes/retry': 0.4.3
+ '@types/estree': 1.0.8
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.6
+ debug: 4.4.3
+ escape-string-regexp: 4.0.0
+ eslint-scope: 8.4.0
+ eslint-visitor-keys: 4.2.1
+ espree: 10.4.0
+ esquery: 1.6.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 8.0.0
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ ignore: 5.3.2
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ json-stable-stringify-without-jsonify: 1.0.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.4
+ optionalDependencies:
+ jiti: 2.6.1
transitivePeerDependencies:
- supports-color
@@ -13746,6 +17005,8 @@ snapshots:
estraverse@5.3.0: {}
+ estree-util-is-identifier-name@3.0.0: {}
+
estree-walker@2.0.2: {}
estree-walker@3.0.3:
@@ -13800,6 +17061,8 @@ snapshots:
exsolve@1.0.7: {}
+ extend@3.0.2: {}
+
extendable-error@0.1.7: {}
external-editor@3.1.0:
@@ -13881,6 +17144,10 @@ snapshots:
optionalDependencies:
picomatch: 4.0.3
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
figures@3.2.0:
dependencies:
escape-string-regexp: 1.0.5
@@ -13937,9 +17204,9 @@ snapshots:
transitivePeerDependencies:
- encoding
- follow-redirects@1.15.11(debug@4.4.1):
+ follow-redirects@1.15.11(debug@4.4.3):
optionalDependencies:
- debug: 4.4.1
+ debug: 4.4.3
for-each@0.3.3:
dependencies:
@@ -13971,6 +17238,8 @@ snapshots:
hasown: 2.0.2
mime-types: 2.1.35
+ fraction.js@5.3.4: {}
+
fs-extra@11.3.0:
dependencies:
graceful-fs: 4.2.11
@@ -14024,6 +17293,8 @@ snapshots:
hasown: 2.0.2
math-intrinsics: 1.1.0
+ get-nonce@1.0.1: {}
+
get-package-type@0.1.0: {}
get-port@6.1.2:
@@ -14091,6 +17362,8 @@ snapshots:
globals@14.0.0: {}
+ globals@16.5.0: {}
+
globalthis@1.0.4:
dependencies:
define-properties: 1.2.1
@@ -14121,6 +17394,8 @@ snapshots:
graphql@16.11.0: {}
+ graphql@16.12.0: {}
+
h3@1.15.4:
dependencies:
cookie-es: 1.2.2
@@ -14162,16 +17437,46 @@ snapshots:
has-tostringtag@1.0.2:
dependencies:
- has-symbols: 1.1.0
+ has-symbols: 1.1.0
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ hast-util-to-jsx-runtime@2.3.6:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ hast-util-whitespace: 3.0.0
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ style-to-js: 1.1.21
+ unist-util-position: 5.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
- hasown@2.0.2:
+ hast-util-whitespace@3.0.0:
dependencies:
- function-bind: 1.1.2
+ '@types/hast': 3.0.4
he@1.2.0: {}
headers-polyfill@4.0.3: {}
+ hermes-estree@0.25.1: {}
+
+ hermes-parser@0.25.1:
+ dependencies:
+ hermes-estree: 0.25.1
+
html-encoding-sniffer@4.0.0:
dependencies:
whatwg-encoding: 3.1.1
@@ -14182,6 +17487,8 @@ snapshots:
html-tags@3.3.1: {}
+ html-url-attributes@3.0.1: {}
+
http-proxy-agent@7.0.2:
dependencies:
agent-base: 7.1.4
@@ -14256,6 +17563,8 @@ snapshots:
inline-style-parser@0.2.4: {}
+ inline-style-parser@0.2.7: {}
+
inquirer@8.2.6:
dependencies:
ansi-escapes: 4.3.2
@@ -14286,6 +17595,13 @@ snapshots:
iron-webcrypto@1.2.1: {}
+ is-alphabetical@2.0.1: {}
+
+ is-alphanumerical@2.0.1:
+ dependencies:
+ is-alphabetical: 2.0.1
+ is-decimal: 2.0.1
+
is-array-buffer@3.0.5:
dependencies:
call-bind: 1.0.8
@@ -14344,6 +17660,8 @@ snapshots:
call-bound: 1.0.4
has-tostringtag: 1.0.2
+ is-decimal@2.0.1: {}
+
is-docker@2.2.1:
optional: true
@@ -14371,6 +17689,8 @@ snapshots:
dependencies:
is-extglob: 2.1.1
+ is-hexadecimal@2.0.1: {}
+
is-html@2.0.0:
dependencies:
html-tags: 3.3.1
@@ -14408,6 +17728,8 @@ snapshots:
is-number@7.0.0: {}
+ is-plain-obj@4.1.0: {}
+
is-plain-object@2.0.4:
dependencies:
isobject: 3.0.1
@@ -14587,7 +17909,7 @@ snapshots:
'@jest/expect': 30.0.5
'@jest/test-result': 30.0.5
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
chalk: 4.1.2
co: 4.6.0
dedent: 1.6.0(babel-plugin-macros@3.1.0)
@@ -14607,15 +17929,15 @@ snapshots:
- babel-plugin-macros
- supports-color
- jest-cli@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2)):
+ jest-cli@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3)):
dependencies:
- '@jest/core': 30.0.5(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2))
+ '@jest/core': 30.0.5(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3))
'@jest/test-result': 30.0.5
'@jest/types': 30.0.5
chalk: 4.1.2
exit-x: 0.2.2
import-local: 3.2.0
- jest-config: 30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2))
+ jest-config: 30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3))
jest-util: 30.0.5
jest-validate: 30.0.5
yargs: 17.7.2
@@ -14626,14 +17948,47 @@ snapshots:
- supports-color
- ts-node
- jest-config@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2)):
+ jest-config@30.0.5(@types/node@24.10.8)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3)):
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
+ '@jest/get-type': 30.0.1
+ '@jest/pattern': 30.0.1
+ '@jest/test-sequencer': 30.0.5
+ '@jest/types': 30.0.5
+ babel-jest: 30.0.5(@babel/core@7.28.6)
+ chalk: 4.1.2
+ ci-info: 4.3.0
+ deepmerge: 4.3.1
+ glob: 10.4.5
+ graceful-fs: 4.2.11
+ jest-circus: 30.0.5(babel-plugin-macros@3.1.0)
+ jest-docblock: 30.0.1
+ jest-environment-node: 30.0.5
+ jest-regex-util: 30.0.1
+ jest-resolve: 30.0.5
+ jest-runner: 30.0.5
+ jest-util: 30.0.5
+ jest-validate: 30.0.5
+ micromatch: 4.0.8
+ parse-json: 5.2.0
+ pretty-format: 30.0.5
+ slash: 3.0.0
+ strip-json-comments: 3.1.1
+ optionalDependencies:
+ '@types/node': 24.10.8
+ ts-node: 10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3)
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
+ jest-config@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3)):
+ dependencies:
+ '@babel/core': 7.28.6
'@jest/get-type': 30.0.1
'@jest/pattern': 30.0.1
'@jest/test-sequencer': 30.0.5
'@jest/types': 30.0.5
- babel-jest: 30.0.5(@babel/core@7.28.0)
+ babel-jest: 30.0.5(@babel/core@7.28.6)
chalk: 4.1.2
ci-info: 4.3.0
deepmerge: 4.3.1
@@ -14654,7 +18009,7 @@ snapshots:
strip-json-comments: 3.1.1
optionalDependencies:
'@types/node': 24.2.0
- ts-node: 10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2)
+ ts-node: 10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3)
transitivePeerDependencies:
- babel-plugin-macros
- supports-color
@@ -14683,7 +18038,7 @@ snapshots:
'@jest/environment': 30.0.5
'@jest/fake-timers': 30.0.5
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
jest-mock: 30.0.5
jest-util: 30.0.5
jest-validate: 30.0.5
@@ -14691,7 +18046,7 @@ snapshots:
jest-haste-map@30.0.5:
dependencies:
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
anymatch: 3.1.3
fb-watchman: 2.0.2
graceful-fs: 4.2.11
@@ -14730,7 +18085,7 @@ snapshots:
jest-mock@30.0.5:
dependencies:
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
jest-util: 30.0.5
jest-pnp-resolver@1.2.3(jest-resolve@30.0.5):
@@ -14764,7 +18119,7 @@ snapshots:
'@jest/test-result': 30.0.5
'@jest/transform': 30.0.5
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
chalk: 4.1.2
emittery: 0.13.1
exit-x: 0.2.2
@@ -14793,7 +18148,7 @@ snapshots:
'@jest/test-result': 30.0.5
'@jest/transform': 30.0.5
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
chalk: 4.1.2
cjs-module-lexer: 2.1.0
collect-v8-coverage: 1.0.2
@@ -14813,17 +18168,17 @@ snapshots:
jest-snapshot@30.0.5:
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/generator': 7.28.0
- '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0)
- '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0)
+ '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.6)
'@babel/types': 7.28.2
'@jest/expect-utils': 30.0.5
'@jest/get-type': 30.0.1
'@jest/snapshot-utils': 30.0.5
'@jest/transform': 30.0.5
'@jest/types': 30.0.5
- babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.0)
+ babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.6)
chalk: 4.1.2
expect: 30.0.5
graceful-fs: 4.2.11
@@ -14840,7 +18195,7 @@ snapshots:
jest-util@30.0.5:
dependencies:
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
chalk: 4.1.2
ci-info: 4.3.0
graceful-fs: 4.2.11
@@ -14859,7 +18214,7 @@ snapshots:
dependencies:
'@jest/test-result': 30.0.5
'@jest/types': 30.0.5
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.13.1
@@ -14868,24 +18223,24 @@ snapshots:
jest-worker@27.5.1:
dependencies:
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
merge-stream: 2.0.0
supports-color: 8.1.1
jest-worker@30.0.5:
dependencies:
- '@types/node': 24.2.0
+ '@types/node': 24.10.8
'@ungap/structured-clone': 1.3.0
jest-util: 30.0.5
merge-stream: 2.0.0
supports-color: 8.1.1
- jest@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2)):
+ jest@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3)):
dependencies:
- '@jest/core': 30.0.5(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2))
+ '@jest/core': 30.0.5(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3))
'@jest/types': 30.0.5
import-local: 3.2.0
- jest-cli: 30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2))
+ jest-cli: 30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3))
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
@@ -14893,6 +18248,8 @@ snapshots:
- supports-color
- ts-node
+ jiti@2.6.1: {}
+
jju@1.4.0: {}
joi@17.13.3:
@@ -14906,6 +18263,8 @@ snapshots:
jose@6.0.12: {}
+ jose@6.1.3: {}
+
js-tokens@4.0.0: {}
js-tokens@9.0.1: {}
@@ -15009,6 +18368,55 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
+ lightningcss-android-arm64@1.30.2:
+ optional: true
+
+ lightningcss-darwin-arm64@1.30.2:
+ optional: true
+
+ lightningcss-darwin-x64@1.30.2:
+ optional: true
+
+ lightningcss-freebsd-x64@1.30.2:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.30.2:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.30.2:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.30.2:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.30.2:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.30.2:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.30.2:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.30.2:
+ optional: true
+
+ lightningcss@1.30.2:
+ dependencies:
+ detect-libc: 2.1.2
+ optionalDependencies:
+ lightningcss-android-arm64: 1.30.2
+ lightningcss-darwin-arm64: 1.30.2
+ lightningcss-darwin-x64: 1.30.2
+ lightningcss-freebsd-x64: 1.30.2
+ lightningcss-linux-arm-gnueabihf: 1.30.2
+ lightningcss-linux-arm64-gnu: 1.30.2
+ lightningcss-linux-arm64-musl: 1.30.2
+ lightningcss-linux-x64-gnu: 1.30.2
+ lightningcss-linux-x64-musl: 1.30.2
+ lightningcss-win32-arm64-msvc: 1.30.2
+ lightningcss-win32-x64-msvc: 1.30.2
+
lines-and-columns@1.2.4: {}
linkify-it@5.0.0:
@@ -15067,6 +18475,8 @@ snapshots:
chalk: 4.1.2
is-unicode-supported: 0.1.0
+ longest-streak@3.1.0: {}
+
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
@@ -15087,6 +18497,10 @@ snapshots:
dependencies:
yallist: 4.0.0
+ lucide-react@0.562.0(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+
lunr@2.3.9: {}
mafmt@7.1.0:
@@ -15097,6 +18511,10 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.4
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
magicast@0.3.5:
dependencies:
'@babel/parser': 7.28.0
@@ -15122,6 +18540,8 @@ snapshots:
punycode.js: 2.3.1
uc.micro: 2.1.0
+ markdown-table@3.0.4: {}
+
math-intrinsics@1.1.0: {}
md5@2.3.0:
@@ -15131,6 +18551,159 @@ snapshots:
is-buffer: 1.1.6
optional: true
+ mdast-util-find-and-replace@3.0.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ escape-string-regexp: 5.0.0
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ mdast-util-from-markdown@2.0.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ decode-named-character-reference: 1.2.0
+ devlop: 1.1.0
+ mdast-util-to-string: 4.0.0
+ micromark: 4.0.2
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-decode-string: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-stringify-position: 4.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-find-and-replace: 3.0.2
+ micromark-util-character: 2.1.1
+
+ mdast-util-gfm-footnote@2.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ micromark-util-normalize-identifier: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-table@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ markdown-table: 3.0.4
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm@3.1.0:
+ dependencies:
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-gfm-autolink-literal: 2.0.1
+ mdast-util-gfm-footnote: 2.1.0
+ mdast-util-gfm-strikethrough: 2.0.0
+ mdast-util-gfm-table: 2.0.0
+ mdast-util-gfm-task-list-item: 2.0.0
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-expression@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-jsx@3.2.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ parse-entities: 4.0.2
+ stringify-entities: 4.0.4
+ unist-util-stringify-position: 4.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdxjs-esm@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.2
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-phrasing@4.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ unist-util-is: 6.0.1
+
+ mdast-util-to-hast@13.2.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@ungap/structured-clone': 1.3.0
+ devlop: 1.1.0
+ micromark-util-sanitize-uri: 2.0.1
+ trim-lines: 3.0.1
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.0.0
+ vfile: 6.0.3
+
+ mdast-util-to-markdown@2.1.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ longest-streak: 3.1.0
+ mdast-util-phrasing: 4.1.0
+ mdast-util-to-string: 4.0.0
+ micromark-util-classify-character: 2.0.1
+ micromark-util-decode-string: 2.0.1
+ unist-util-visit: 5.0.0
+ zwitch: 2.0.4
+
+ mdast-util-to-string@4.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+
mdn-data@2.12.2: {}
mdurl@2.0.0: {}
@@ -15143,6 +18716,197 @@ snapshots:
merge2@1.4.1: {}
+ micromark-core-commonmark@2.0.3:
+ dependencies:
+ decode-named-character-reference: 1.2.0
+ devlop: 1.1.0
+ micromark-factory-destination: 2.0.1
+ micromark-factory-label: 2.0.1
+ micromark-factory-space: 2.0.1
+ micromark-factory-title: 2.0.1
+ micromark-factory-whitespace: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-html-tag-name: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-footnote@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-table@2.1.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm@3.0.0:
+ dependencies:
+ micromark-extension-gfm-autolink-literal: 2.1.0
+ micromark-extension-gfm-footnote: 2.1.0
+ micromark-extension-gfm-strikethrough: 2.1.0
+ micromark-extension-gfm-table: 2.1.1
+ micromark-extension-gfm-tagfilter: 2.0.0
+ micromark-extension-gfm-task-list-item: 2.1.0
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-destination@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-label@2.0.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-space@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-title@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-whitespace@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-character@2.1.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-chunked@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-classify-character@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-combine-extensions@2.0.1:
+ dependencies:
+ micromark-util-chunked: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-decode-string@2.0.1:
+ dependencies:
+ decode-named-character-reference: 1.2.0
+ micromark-util-character: 2.1.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-encode@2.0.1: {}
+
+ micromark-util-html-tag-name@2.0.1: {}
+
+ micromark-util-normalize-identifier@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-resolve-all@2.0.1:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-util-sanitize-uri@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-encode: 2.0.1
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-subtokenize@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-symbol@2.0.1: {}
+
+ micromark-util-types@2.0.2: {}
+
+ micromark@4.0.2:
+ dependencies:
+ '@types/debug': 4.1.12
+ debug: 4.4.3
+ decode-named-character-reference: 1.2.0
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-encode: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
micromatch@4.0.5:
dependencies:
braces: 3.0.2
@@ -15168,6 +18932,11 @@ snapshots:
dependencies:
'@isaacs/brace-expansion': 5.0.0
+ minimatch@10.1.1:
+ dependencies:
+ '@isaacs/brace-expansion': 5.0.0
+ optional: true
+
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
@@ -15192,37 +18961,114 @@ snapshots:
mrmime@2.0.1:
optional: true
- ms@2.0.0:
+ ms@2.0.0:
+ optional: true
+
+ ms@2.1.2: {}
+
+ ms@2.1.3: {}
+
+ msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2):
+ dependencies:
+ '@bundled-es-modules/cookie': 2.0.1
+ '@bundled-es-modules/statuses': 1.0.1
+ '@bundled-es-modules/tough-cookie': 0.1.6
+ '@inquirer/confirm': 5.1.14(@types/node@24.2.0)
+ '@mswjs/interceptors': 0.39.5
+ '@open-draft/deferred-promise': 2.2.0
+ '@open-draft/until': 2.1.0
+ '@types/cookie': 0.6.0
+ '@types/statuses': 2.0.6
+ graphql: 16.11.0
+ headers-polyfill: 4.0.3
+ is-node-process: 1.2.0
+ outvariant: 1.4.3
+ path-to-regexp: 6.3.0
+ picocolors: 1.1.1
+ strict-event-emitter: 0.5.1
+ type-fest: 4.41.0
+ yargs: 17.7.2
+ optionalDependencies:
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - '@types/node'
+
+ msw@2.12.7(@types/node@24.10.8)(typescript@5.9.3):
+ dependencies:
+ '@inquirer/confirm': 5.1.14(@types/node@24.10.8)
+ '@mswjs/interceptors': 0.40.0
+ '@open-draft/deferred-promise': 2.2.0
+ '@types/statuses': 2.0.6
+ cookie: 1.0.2
+ graphql: 16.12.0
+ headers-polyfill: 4.0.3
+ is-node-process: 1.2.0
+ outvariant: 1.4.3
+ path-to-regexp: 6.3.0
+ picocolors: 1.1.1
+ rettime: 0.7.0
+ statuses: 2.0.2
+ strict-event-emitter: 0.5.1
+ tough-cookie: 6.0.0
+ type-fest: 5.4.1
+ until-async: 3.0.2
+ yargs: 17.7.2
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - '@types/node'
+
+ msw@2.12.7(@types/node@24.2.0)(typescript@5.9.2):
+ dependencies:
+ '@inquirer/confirm': 5.1.14(@types/node@24.2.0)
+ '@mswjs/interceptors': 0.40.0
+ '@open-draft/deferred-promise': 2.2.0
+ '@types/statuses': 2.0.6
+ cookie: 1.0.2
+ graphql: 16.12.0
+ headers-polyfill: 4.0.3
+ is-node-process: 1.2.0
+ outvariant: 1.4.3
+ path-to-regexp: 6.3.0
+ picocolors: 1.1.1
+ rettime: 0.7.0
+ statuses: 2.0.2
+ strict-event-emitter: 0.5.1
+ tough-cookie: 6.0.0
+ type-fest: 5.4.1
+ until-async: 3.0.2
+ yargs: 17.7.2
+ optionalDependencies:
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - '@types/node'
optional: true
- ms@2.1.2: {}
-
- ms@2.1.3: {}
-
- msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2):
+ msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3):
dependencies:
- '@bundled-es-modules/cookie': 2.0.1
- '@bundled-es-modules/statuses': 1.0.1
- '@bundled-es-modules/tough-cookie': 0.1.6
'@inquirer/confirm': 5.1.14(@types/node@24.2.0)
- '@mswjs/interceptors': 0.39.5
+ '@mswjs/interceptors': 0.40.0
'@open-draft/deferred-promise': 2.2.0
- '@open-draft/until': 2.1.0
- '@types/cookie': 0.6.0
'@types/statuses': 2.0.6
- graphql: 16.11.0
+ cookie: 1.0.2
+ graphql: 16.12.0
headers-polyfill: 4.0.3
is-node-process: 1.2.0
outvariant: 1.4.3
path-to-regexp: 6.3.0
picocolors: 1.1.1
+ rettime: 0.7.0
+ statuses: 2.0.2
strict-event-emitter: 0.5.1
- type-fest: 4.41.0
+ tough-cookie: 6.0.0
+ type-fest: 5.4.1
+ until-async: 3.0.2
yargs: 17.7.2
optionalDependencies:
- typescript: 5.9.2
+ typescript: 5.9.3
transitivePeerDependencies:
- '@types/node'
+ optional: true
muggle-string@0.4.1: {}
@@ -15284,6 +19130,11 @@ snapshots:
neo-async@2.6.2: {}
+ next-themes@0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+
node-addon-api@7.1.1:
optional: true
@@ -15302,6 +19153,8 @@ snapshots:
node-releases@2.0.19: {}
+ node-releases@2.0.27: {}
+
normalize-path@3.0.0: {}
npm-run-path@4.0.1:
@@ -15542,9 +19395,19 @@ snapshots:
dependencies:
callsites: 3.1.0
+ parse-entities@4.0.2:
+ dependencies:
+ '@types/unist': 2.0.11
+ character-entities-legacy: 3.0.0
+ character-reference-invalid: 2.0.1
+ decode-named-character-reference: 1.2.0
+ is-alphanumerical: 2.0.1
+ is-decimal: 2.0.1
+ is-hexadecimal: 2.0.1
+
parse-json@5.2.0:
dependencies:
- '@babel/code-frame': 7.27.1
+ '@babel/code-frame': 7.28.6
error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
@@ -15649,6 +19512,13 @@ snapshots:
possible-typed-array-names@1.1.0: {}
+ postcss-selector-parser@6.0.10:
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ postcss-value-parser@4.2.0: {}
+
postcss@8.5.6:
dependencies:
nanoid: 3.3.11
@@ -15688,6 +19558,8 @@ snapshots:
object-assign: 4.1.1
react-is: 16.13.1
+ property-information@7.1.0: {}
+
proxy-compare@3.0.1: {}
proxy-from-env@1.1.0: {}
@@ -15739,6 +19611,15 @@ snapshots:
react: 19.1.1
scheduler: 0.26.0
+ react-dom@19.2.3(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ scheduler: 0.27.0
+
+ react-hook-form@7.71.1(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+
react-is@16.13.1: {}
react-is@18.3.1: {}
@@ -15757,8 +19638,47 @@ snapshots:
react-lifecycles-compat@3.0.4: {}
+ react-markdown@10.1.0(@types/react@19.2.8)(react@19.2.3):
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@types/react': 19.2.8
+ devlop: 1.1.0
+ hast-util-to-jsx-runtime: 2.3.6
+ html-url-attributes: 3.0.1
+ mdast-util-to-hast: 13.2.1
+ react: 19.2.3
+ remark-parse: 11.0.0
+ remark-rehype: 11.1.2
+ unified: 11.0.5
+ unist-util-visit: 5.0.0
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
react-refresh@0.17.0: {}
+ react-refresh@0.18.0: {}
+
+ react-remove-scroll-bar@2.3.8(@types/react@19.2.8)(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ react-style-singleton: 2.2.3(@types/react@19.2.8)(react@19.2.3)
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ react-remove-scroll@2.7.2(@types/react@19.2.8)(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ react-remove-scroll-bar: 2.3.8(@types/react@19.2.8)(react@19.2.3)
+ react-style-singleton: 2.2.3(@types/react@19.2.8)(react@19.2.3)
+ tslib: 2.8.1
+ use-callback-ref: 1.3.3(@types/react@19.2.8)(react@19.2.3)
+ use-sidecar: 1.1.3(@types/react@19.2.8)(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.8
+
react-router-dom@7.9.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
dependencies:
react: 19.1.1
@@ -15773,6 +19693,14 @@ snapshots:
optionalDependencies:
react-dom: 19.1.1(react@19.1.1)
+ react-style-singleton@2.2.3(@types/react@19.2.8)(react@19.2.3):
+ dependencies:
+ get-nonce: 1.0.1
+ react: 19.2.3
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.2.8
+
react-textarea-autosize@8.5.9(@types/react@19.1.9)(react@19.1.1):
dependencies:
'@babel/runtime': 7.28.2
@@ -15784,6 +19712,8 @@ snapshots:
react@19.1.1: {}
+ react@19.2.3: {}
+
read-yaml-file@1.1.0:
dependencies:
graceful-fs: 4.2.11
@@ -15856,6 +19786,40 @@ snapshots:
jsesc: 3.0.2
optional: true
+ remark-gfm@4.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-gfm: 3.1.0
+ micromark-extension-gfm: 3.0.0
+ remark-parse: 11.0.0
+ remark-stringify: 11.0.0
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-parse@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.2
+ micromark-util-types: 2.0.2
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-rehype@11.1.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ mdast-util-to-hast: 13.2.1
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ remark-stringify@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-to-markdown: 2.1.2
+ unified: 11.0.5
+
require-directory@2.1.1: {}
require-from-string@2.0.2: {}
@@ -15880,6 +19844,13 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ resolve@1.22.11:
+ dependencies:
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ optional: true
+
resolve@2.0.0-next.5:
dependencies:
is-core-module: 2.16.1
@@ -15891,6 +19862,8 @@ snapshots:
onetime: 5.1.2
signal-exit: 3.0.7
+ rettime@0.7.0: {}
+
reusify@1.0.4: {}
rimraf@6.0.1:
@@ -16033,6 +20006,8 @@ snapshots:
scheduler@0.26.0: {}
+ scheduler@0.27.0: {}
+
schema-utils@4.3.2:
dependencies:
'@types/json-schema': 7.0.15
@@ -16052,6 +20027,8 @@ snapshots:
semver@7.7.2: {}
+ semver@7.7.3: {}
+
serialize-javascript@6.0.2:
dependencies:
randombytes: 2.1.0
@@ -16145,7 +20122,7 @@ snapshots:
slow-redact@0.3.2: {}
- solid-devtools@0.24.7(@solidjs/meta@0.28.7(solid-js@1.9.7))(@solidjs/router@0.8.4(solid-js@1.9.7))(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)):
+ solid-devtools@0.24.7(@solidjs/meta@0.28.7(solid-js@1.9.7))(@solidjs/router@0.8.4(solid-js@1.9.7))(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)):
dependencies:
'@babel/core': 7.28.0
'@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0)
@@ -16155,9 +20132,9 @@ snapshots:
'@solid-primitives/utils': 4.0.1(solid-js@1.9.7)
solid-js: 1.9.7
type-fest: 3.13.1
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ vite: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
optionalDependencies:
- solid-start: 0.2.32(@solidjs/meta@0.28.7(solid-js@1.9.7))(@solidjs/router@0.8.4(solid-js@1.9.7))(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ solid-start: 0.2.32(@solidjs/meta@0.28.7(solid-js@1.9.7))(@solidjs/router@0.8.4(solid-js@1.9.7))(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
transitivePeerDependencies:
- '@nuxt/kit'
- '@solidjs/meta'
@@ -16194,13 +20171,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- solid-start@0.2.32(@solidjs/meta@0.28.7(solid-js@1.9.7))(@solidjs/router@0.8.4(solid-js@1.9.7))(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)):
+ solid-start@0.2.32(@solidjs/meta@0.28.7(solid-js@1.9.7))(@solidjs/router@0.8.4(solid-js@1.9.7))(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)):
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@babel/generator': 7.28.0
- '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0)
- '@babel/preset-env': 7.28.0(@babel/core@7.28.0)
- '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0)
+ '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.6)
+ '@babel/preset-env': 7.28.0(@babel/core@7.28.6)
+ '@babel/preset-typescript': 7.27.1(@babel/core@7.28.6)
'@babel/template': 7.27.2
'@solidjs/meta': 0.28.7(solid-js@1.9.7)
'@solidjs/router': 0.8.4(solid-js@1.9.7)
@@ -16209,7 +20186,7 @@ snapshots:
chokidar: 3.6.0
compression: 1.8.1
connect: 3.7.0
- debug: 4.4.1
+ debug: 4.4.3
dequal: 2.0.3
dotenv: 16.6.1
es-module-lexer: 1.7.0
@@ -16228,10 +20205,10 @@ snapshots:
solid-js: 1.9.7
terser: 5.43.1
undici: 5.29.0
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
- vite-plugin-inspect: 0.7.42(rollup@3.29.5)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
- vite-plugin-solid: 2.11.8(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
- wait-on: 6.0.1(debug@4.4.1)
+ vite: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+ vite-plugin-inspect: 0.7.42(rollup@3.29.5)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
+ vite-plugin-solid: 2.11.8(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
+ wait-on: 6.0.1(debug@4.4.3)
transitivePeerDependencies:
- '@nuxt/kit'
- '@testing-library/jest-dom'
@@ -16255,6 +20232,11 @@ snapshots:
dependencies:
atomic-sleep: 1.0.0
+ sonner@2.0.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+
source-map-js@1.2.1: {}
source-map-support@0.5.13:
@@ -16271,6 +20253,8 @@ snapshots:
source-map@0.7.4: {}
+ space-separated-tokens@2.0.2: {}
+
spawndamnit@3.0.1:
dependencies:
cross-spawn: 7.0.6
@@ -16377,6 +20361,11 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
+ stringify-entities@4.0.4:
+ dependencies:
+ character-entities-html4: 2.1.0
+ character-entities-legacy: 3.0.0
+
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
@@ -16402,6 +20391,16 @@ snapshots:
strnum@2.1.1: {}
+ style-mod@4.1.3: {}
+
+ style-to-js@1.1.21:
+ dependencies:
+ style-to-object: 1.0.14
+
+ style-to-object@1.0.14:
+ dependencies:
+ inline-style-parser: 0.2.7
+
style-to-object@1.0.9:
dependencies:
inline-style-parser: 0.2.4
@@ -16427,6 +20426,16 @@ snapshots:
dependencies:
'@pkgr/core': 0.2.9
+ tagged-tag@1.0.0: {}
+
+ tailwind-merge@3.4.0: {}
+
+ tailwindcss-animate@1.0.7(tailwindcss@4.1.18):
+ dependencies:
+ tailwindcss: 4.1.18
+
+ tailwindcss@4.1.18: {}
+
tapable@2.2.2: {}
term-size@2.2.1: {}
@@ -16479,6 +20488,11 @@ snapshots:
fdir: 6.4.6(picomatch@4.0.3)
picomatch: 4.0.3
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
tinypool@1.1.1: {}
tinyrainbow@2.0.0: {}
@@ -16524,44 +20538,57 @@ snapshots:
dependencies:
punycode: 2.3.1
+ trim-lines@3.0.1: {}
+
+ trough@2.2.0: {}
+
ts-api-utils@2.1.0(typescript@5.9.2):
dependencies:
typescript: 5.9.2
- ts-jest@29.4.1(@babel/core@7.28.0)(@jest/transform@30.0.5)(@jest/types@30.0.5)(babel-jest@30.0.5(@babel/core@7.28.0))(jest-util@30.0.5)(jest@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2)))(typescript@5.9.2):
+ ts-api-utils@2.4.0(typescript@5.9.2):
+ dependencies:
+ typescript: 5.9.2
+ optional: true
+
+ ts-api-utils@2.4.0(typescript@5.9.3):
+ dependencies:
+ typescript: 5.9.3
+
+ ts-jest@29.4.1(@babel/core@7.28.6)(@jest/transform@30.0.5)(@jest/types@30.0.5)(babel-jest@30.0.5(@babel/core@7.28.6))(jest-util@30.0.5)(jest@30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3)))(typescript@5.9.3):
dependencies:
bs-logger: 0.2.6
fast-json-stable-stringify: 2.1.0
handlebars: 4.7.8
- jest: 30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2))
+ jest: 30.0.5(@types/node@24.2.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3))
json5: 2.2.3
lodash.memoize: 4.1.2
make-error: 1.3.6
semver: 7.7.2
type-fest: 4.41.0
- typescript: 5.9.2
+ typescript: 5.9.3
yargs-parser: 21.1.1
optionalDependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.6
'@jest/transform': 30.0.5
'@jest/types': 30.0.5
- babel-jest: 30.0.5(@babel/core@7.28.0)
+ babel-jest: 30.0.5(@babel/core@7.28.6)
jest-util: 30.0.5
- ts-loader@9.5.2(typescript@5.9.2)(webpack@5.101.0):
+ ts-loader@9.5.2(typescript@5.9.3)(webpack@5.101.0):
dependencies:
chalk: 4.1.2
enhanced-resolve: 5.18.2
micromatch: 4.0.5
semver: 7.3.8
source-map: 0.7.4
- typescript: 5.9.2
+ typescript: 5.9.3
webpack: 5.101.0(webpack-cli@5.1.4)
- ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.2):
+ ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.9.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
- '@tsconfig/node10': 1.0.11
+ '@tsconfig/node10': 1.0.12
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
@@ -16572,7 +20599,7 @@ snapshots:
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
- typescript: 5.9.2
+ typescript: 5.9.3
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
optionalDependencies:
@@ -16588,9 +20615,9 @@ snapshots:
semver: 7.7.2
strip-ansi: 6.0.1
- tsconfck@3.1.6(typescript@5.9.2):
+ tsconfck@3.1.6(typescript@5.9.3):
optionalDependencies:
- typescript: 5.9.2
+ typescript: 5.9.3
tsconfig-paths@3.15.0:
dependencies:
@@ -16648,6 +20675,10 @@ snapshots:
type-fest@4.41.0: {}
+ type-fest@5.4.1:
+ dependencies:
+ tagged-tag: 1.0.0
+
typed-array-buffer@1.0.3:
dependencies:
call-bound: 1.0.4
@@ -16690,15 +20721,28 @@ snapshots:
typescript: 5.9.2
yaml: 2.8.0
- typescript-transform-paths@3.5.5(typescript@5.9.2):
+ typescript-eslint@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.39.2(jiti@2.6.1)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ typescript-transform-paths@3.5.5(typescript@5.9.3):
dependencies:
minimatch: 9.0.5
- typescript: 5.9.2
+ typescript: 5.9.3
typescript@5.8.2: {}
typescript@5.9.2: {}
+ typescript@5.9.3: {}
+
ua-parser-js@1.0.40: {}
uc.micro@2.1.0: {}
@@ -16723,8 +20767,7 @@ snapshots:
undici-types@7.10.0: {}
- undici-types@7.16.0:
- optional: true
+ undici-types@7.16.0: {}
undici@5.29.0:
dependencies:
@@ -16746,6 +20789,39 @@ snapshots:
unicode-property-aliases-ecmascript@2.1.0:
optional: true
+ unified@11.0.5:
+ dependencies:
+ '@types/unist': 3.0.3
+ bail: 2.0.2
+ devlop: 1.1.0
+ extend: 3.0.2
+ is-plain-obj: 4.1.0
+ trough: 2.2.0
+ vfile: 6.0.3
+
+ unist-util-is@6.0.1:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-stringify-position@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-parents@6.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
+ unist-util-visit@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
universalify@0.1.2: {}
universalify@0.2.0: {}
@@ -16792,6 +20868,8 @@ snapshots:
optionalDependencies:
idb-keyval: 6.2.2
+ until-async@3.0.2: {}
+
untildify@4.0.0:
optional: true
@@ -16801,6 +20879,12 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
+ update-browserslist-db@1.2.3(browserslist@4.28.1):
+ dependencies:
+ browserslist: 4.28.1
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
uri-js@4.4.1:
dependencies:
punycode: 2.3.1
@@ -16810,6 +20894,13 @@ snapshots:
querystringify: 2.2.0
requires-port: 1.0.0
+ use-callback-ref@1.3.3(@types/react@19.2.8)(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.2.8
+
use-composed-ref@1.4.0(@types/react@19.1.9)(react@19.1.1):
dependencies:
react: 19.1.1
@@ -16829,6 +20920,14 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.9
+ use-sidecar@1.1.3(@types/react@19.2.8)(react@19.2.3):
+ dependencies:
+ detect-node-es: 1.1.0
+ react: 19.2.3
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.2.8
+
utf-8-validate@5.0.10:
dependencies:
node-gyp-build: 4.8.4
@@ -16871,6 +20970,16 @@ snapshots:
vary@1.1.2:
optional: true
+ vfile-message@4.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-stringify-position: 4.0.0
+
+ vfile@6.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile-message: 4.0.3
+
viem@2.38.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.22.4):
dependencies:
'@noble/curves': 1.9.1
@@ -16923,13 +21032,13 @@ snapshots:
- utf-8-validate
- zod
- vite-node@3.2.4(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0):
+ vite-node@3.2.4(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2):
dependencies:
cac: 6.7.14
- debug: 4.4.1
+ debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ vite: 7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -16944,9 +21053,9 @@ snapshots:
- tsx
- yaml
- vite-plugin-dts@4.5.4(@types/node@24.2.0)(rollup@4.46.2)(typescript@5.9.2)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)):
+ vite-plugin-dts@4.5.4(@types/node@24.10.8)(rollup@4.46.2)(typescript@5.9.2)(vite@7.0.6(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)):
dependencies:
- '@microsoft/api-extractor': 7.52.10(@types/node@24.2.0)
+ '@microsoft/api-extractor': 7.52.10(@types/node@24.10.8)
'@rollup/pluginutils': 5.2.0(rollup@4.46.2)
'@volar/typescript': 2.4.22
'@vue/language-core': 2.2.0(typescript@5.9.2)
@@ -16957,29 +21066,29 @@ snapshots:
magic-string: 0.30.17
typescript: 5.9.2
optionalDependencies:
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ vite: 7.0.6(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
transitivePeerDependencies:
- '@types/node'
- rollup
- supports-color
- vite-plugin-inspect@0.7.42(rollup@3.29.5)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)):
+ vite-plugin-inspect@0.7.42(rollup@3.29.5)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)):
dependencies:
'@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.2.0(rollup@3.29.5)
- debug: 4.4.1
+ debug: 4.4.3
error-stack-parser-es: 0.1.5
fs-extra: 11.3.0
open: 9.1.0
picocolors: 1.1.1
sirv: 2.0.4
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ vite: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
transitivePeerDependencies:
- rollup
- supports-color
optional: true
- vite-plugin-solid@2.11.8(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)):
+ vite-plugin-solid@2.11.8(solid-js@1.9.7)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)):
dependencies:
'@babel/core': 7.28.0
'@types/babel__core': 7.20.5
@@ -16987,23 +21096,40 @@ snapshots:
merge-anything: 5.1.7
solid-js: 1.9.7
solid-refresh: 0.6.3(solid-js@1.9.7)
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
- vitefu: 1.1.1(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ vite: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+ vitefu: 1.1.1(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
transitivePeerDependencies:
- supports-color
- vite-tsconfig-paths@5.1.4(typescript@5.9.2)(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)):
+ vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)):
dependencies:
debug: 4.4.1
globrex: 0.1.2
- tsconfck: 3.1.6(typescript@5.9.2)
+ tsconfck: 3.1.6(typescript@5.9.3)
optionalDependencies:
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ vite: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
transitivePeerDependencies:
- supports-color
- typescript
- vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0):
+ vite@7.0.6(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2):
+ dependencies:
+ esbuild: 0.25.8
+ fdir: 6.4.6(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.46.2
+ tinyglobby: 0.2.14
+ optionalDependencies:
+ '@types/node': 24.10.8
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.2
+ sass: 1.90.0
+ terser: 5.43.1
+ yaml: 2.8.2
+
+ vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2):
dependencies:
esbuild: 0.25.8
fdir: 6.4.6(picomatch@4.0.3)
@@ -17014,23 +21140,102 @@ snapshots:
optionalDependencies:
'@types/node': 24.2.0
fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.2
sass: 1.90.0
terser: 5.43.1
- yaml: 2.8.0
+ yaml: 2.8.2
- vitefu@1.1.1(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)):
+ vite@7.3.1(@types/node@24.10.8)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2):
+ dependencies:
+ esbuild: 0.27.2
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.46.2
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 24.10.8
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.2
+ sass: 1.90.0
+ terser: 5.43.1
+ yaml: 2.8.2
+
+ vite@7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2):
+ dependencies:
+ esbuild: 0.27.2
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.46.2
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 24.2.0
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.2
+ sass: 1.90.0
+ terser: 5.43.1
+ yaml: 2.8.2
+
+ vitefu@1.1.1(vite@7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)):
optionalDependencies:
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ vite: 7.0.6(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+
+ vitest-fetch-mock@0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)):
+ dependencies:
+ vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
- vitest-fetch-mock@0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)):
+ vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2):
dependencies:
- vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ '@types/chai': 5.2.2
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.2))(vite@7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.2.1
+ debug: 4.4.1
+ expect-type: 1.2.2
+ magic-string: 0.30.17
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 3.9.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.14
+ tinypool: 1.1.1
+ tinyrainbow: 2.0.0
+ vite: 7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+ vite-node: 3.2.4(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/debug': 4.1.12
+ '@types/node': 24.2.0
+ jsdom: 27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10)
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
- vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0):
+ vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0)(jiti@2.6.1)(jsdom@27.0.1(bufferutil@4.0.9)(postcss@8.5.6)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2):
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(msw@2.10.4(@types/node@24.2.0)(typescript@5.9.2))(vite@7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0))
+ '@vitest/mocker': 3.2.4(msw@2.12.7(@types/node@24.2.0)(typescript@5.9.3))(vite@7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -17048,8 +21253,8 @@ snapshots:
tinyglobby: 0.2.14
tinypool: 1.1.1
tinyrainbow: 2.0.0
- vite: 7.0.6(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
- vite-node: 3.2.4(@types/node@24.2.0)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.0)
+ vite: 7.3.1(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
+ vite-node: 3.2.4(@types/node@24.2.0)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.90.0)(terser@5.43.1)(yaml@2.8.2)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/debug': 4.1.12
@@ -17071,13 +21276,15 @@ snapshots:
vscode-uri@3.1.0: {}
+ w3c-keyname@2.2.8: {}
+
w3c-xmlserializer@5.0.0:
dependencies:
xml-name-validator: 5.0.0
- wait-on@6.0.1(debug@4.4.1):
+ wait-on@6.0.1(debug@4.4.3):
dependencies:
- axios: 0.25.0(debug@4.4.1)
+ axios: 0.25.0(debug@4.4.3)
joi: 17.13.3
lodash: 4.17.21
minimist: 1.2.8
@@ -17298,6 +21505,8 @@ snapshots:
yaml@2.8.0: {}
+ yaml@2.8.2: {}
+
yargs-parser@18.1.3:
dependencies:
camelcase: 5.3.1
@@ -17336,14 +21545,22 @@ snapshots:
yoctocolors-cjs@2.1.2: {}
+ zod-validation-error@4.0.2(zod@4.3.5):
+ dependencies:
+ zod: 4.3.5
+
zod@3.22.4: {}
zod@3.25.76: {}
zod@4.0.15: {}
+ zod@4.3.5: {}
+
zustand@5.0.3(@types/react@19.1.9)(react@19.1.1):
optionalDependencies:
'@types/react': 19.1.9
react: 19.1.1
optional: true
+
+ zwitch@2.0.4: {}