diff --git a/.gitignore b/.gitignore index de1ffa74a50..c9fac529838 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,8 @@ docs/content/references/framework/** lcov.info **/venv/ +*storybook.log + # iota-private-network docker/iota-private-network/data docker/iota-private-network/configs/validators/validator* diff --git a/Cargo.lock b/Cargo.lock index fddd01ef0ea..34b996b3f2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6509,6 +6509,7 @@ dependencies = [ "camino", "clap", "fastcrypto", + "flate2", "fs_extra", "insta", "iota-adapter-v0", @@ -6537,6 +6538,7 @@ dependencies = [ "rand_regex", "rand_seeder", "regex", + "reqwest", "schemars", "serde", "serde_json", diff --git a/apps/ui-kit/.prettierignore b/apps/ui-kit/.prettierignore new file mode 100644 index 00000000000..1591a0dd4c4 --- /dev/null +++ b/apps/ui-kit/.prettierignore @@ -0,0 +1 @@ +storybook-static/ diff --git a/apps/ui-kit/.storybook/main.ts b/apps/ui-kit/.storybook/main.ts new file mode 100644 index 00000000000..8e73c471ae3 --- /dev/null +++ b/apps/ui-kit/.storybook/main.ts @@ -0,0 +1,31 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { dirname, join } from 'path'; +import type { StorybookConfig } from '@storybook/react-vite'; + +function getAbsolutePath(value: string): any { + return dirname(require.resolve(join(value, 'package.json'))); +} + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + getAbsolutePath('@storybook/addon-a11y'), + getAbsolutePath('@storybook/addon-links'), + getAbsolutePath('@storybook/addon-essentials'), + getAbsolutePath('@storybook/addon-interactions'), + '@chromatic-com/storybook', + ], + + framework: { + name: getAbsolutePath('@storybook/react-vite'), + options: {}, + }, + typescript: { + reactDocgen: 'react-docgen-typescript', + }, + docs: {}, +}; + +export default config; diff --git a/apps/ui-kit/.storybook/preview.ts b/apps/ui-kit/.storybook/preview.ts new file mode 100644 index 00000000000..7f0f85f2101 --- /dev/null +++ b/apps/ui-kit/.storybook/preview.ts @@ -0,0 +1,17 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import type { Preview } from '@storybook/react'; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + }, +}; + +export default preview; diff --git a/apps/ui-kit/package.json b/apps/ui-kit/package.json new file mode 100644 index 00000000000..cebc4ed5766 --- /dev/null +++ b/apps/ui-kit/package.json @@ -0,0 +1,44 @@ +{ + "name": "@iota/apps-ui-kit", + "private": true, + "sideEffects": false, + "repository": { + "type": "git", + "url": "github.com:iotaledger/iota.git" + }, + "license": "Apache-2.0", + "scripts": { + "prettier:check": "prettier -c --ignore-unknown .", + "prettier:fix": "prettier -w --ignore-unknown .", + "eslint:check": "eslint --max-warnings=0 .", + "eslint:fix": "pnpm run eslint:check --fix", + "lint": "pnpm run eslint:check && pnpm run prettier:check", + "lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build", + "dev": "pnpm run storybook" + }, + "dependencies": { + "@iota/core": "workspace:*", + "@iota/icons": "workspace:*", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@chromatic-com/storybook": "^1.6.0", + "@storybook/addon-essentials": "^7.1.0", + "@storybook/addon-interactions": "^7.1.0", + "@storybook/addon-links": "^7.1.0", + "@storybook/addon-onboarding": "^8.1.11", + "@storybook/blocks": "^7.1.0", + "@storybook/react": "^7.1.0", + "@storybook/react-vite": "^7.1.0", + "@storybook/test": "^8.1.11", + "@types/react": "^18.2.15", + "storybook": "^7.1.0", + "tailwindcss": "^3.3.3", + "typescript": "^5.3.3", + "vite": "^4.4.4", + "vite-tsconfig-paths": "^4.2.0" + } +} diff --git a/apps/ui-kit/postcss.config.js b/apps/ui-kit/postcss.config.js new file mode 100644 index 00000000000..0fa3edd478d --- /dev/null +++ b/apps/ui-kit/postcss.config.js @@ -0,0 +1,9 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/apps/ui-kit/src/lib/components/Button.tsx b/apps/ui-kit/src/lib/components/Button.tsx new file mode 100644 index 00000000000..eab48eae204 --- /dev/null +++ b/apps/ui-kit/src/lib/components/Button.tsx @@ -0,0 +1,12 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import React from 'react'; + +export interface ButtonProps { + label: string; +} + +export function Button({ label }: ButtonProps): React.JSX.Element { + return ; +} diff --git a/apps/ui-kit/src/lib/components/index.ts b/apps/ui-kit/src/lib/components/index.ts new file mode 100644 index 00000000000..0ecf88b8b19 --- /dev/null +++ b/apps/ui-kit/src/lib/components/index.ts @@ -0,0 +1,4 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +export * from './Button'; diff --git a/apps/ui-kit/src/stories/Button.stories.tsx b/apps/ui-kit/src/stories/Button.stories.tsx new file mode 100644 index 00000000000..ffd96ebd7e0 --- /dev/null +++ b/apps/ui-kit/src/stories/Button.stories.tsx @@ -0,0 +1,26 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import type { Meta, StoryObj } from '@storybook/react'; + +import { Button } from '@/components'; + +const meta = { + component: Button, + tags: ['autodocs'], + render: (props) => { + return ( +
+ +
+ ); + }, +} satisfies Meta; +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + label: 'Button', + }, +}; diff --git a/apps/ui-kit/tailwind.config.ts b/apps/ui-kit/tailwind.config.ts new file mode 100644 index 00000000000..1da8bc2e585 --- /dev/null +++ b/apps/ui-kit/tailwind.config.ts @@ -0,0 +1,9 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import preset from '@iota/core/tailwind.config'; +import { type Config } from 'tailwindcss'; + +export default { + presets: [preset], +} satisfies Partial; diff --git a/apps/ui-kit/tsconfig.json b/apps/ui-kit/tsconfig.json new file mode 100644 index 00000000000..dd80012ff07 --- /dev/null +++ b/apps/ui-kit/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "esnext", + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "noEmit": true, + "isolatedModules": true, + "sourceMap": true, + "jsx": "react-jsx", + "paths": { + "@/*": ["./src/*"], + "@/components": ["./src/lib/components"], + "@/components/*": ["./src/lib/components/*"] + } + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/apps/ui-kit/vite.config.ts b/apps/ui-kit/vite.config.ts new file mode 100644 index 00000000000..6e71ecba210 --- /dev/null +++ b/apps/ui-kit/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite'; +import tsconfigPaths from 'vite-tsconfig-paths'; + +export default defineConfig({ + plugins: [ + tsconfigPaths({ + root: __dirname, + }), + ], +}); diff --git a/apps/wallet/src/background/accounts/Account.ts b/apps/wallet/src/background/accounts/Account.ts index fb4a186b118..abbfbc8a5b3 100644 --- a/apps/wallet/src/background/accounts/Account.ts +++ b/apps/wallet/src/background/accounts/Account.ts @@ -22,8 +22,8 @@ import { accountsEvents } from './events'; export enum AccountType { MnemonicDerived = 'mnemonic-derived', SeedDerived = 'seed-derived', - Imported = 'imported', - Ledger = 'ledger', + PrivateKeyDerived = 'private-key-derived', + LedgerDerived = 'ledger-derived', } export abstract class Account< diff --git a/apps/wallet/src/background/accounts/ImportedAccount.ts b/apps/wallet/src/background/accounts/ImportedAccount.ts index 719fd9bbe8b..97d9bc06ac4 100644 --- a/apps/wallet/src/background/accounts/ImportedAccount.ts +++ b/apps/wallet/src/background/accounts/ImportedAccount.ts @@ -19,20 +19,20 @@ type SessionStorageData = { keyPair: string }; type EncryptedData = { keyPair: string }; export interface ImportedAccountSerialized extends SerializedAccount { - type: AccountType.Imported; + type: AccountType.PrivateKeyDerived; encrypted: string; publicKey: string; } export interface ImportedAccountSerializedUI extends SerializedUIAccount { - type: AccountType.Imported; + type: AccountType.PrivateKeyDerived; publicKey: string; } export function isImportedAccountSerializedUI( account: SerializedUIAccount, ): account is ImportedAccountSerializedUI { - return account.type === AccountType.Imported; + return account.type === AccountType.PrivateKeyDerived; } export class ImportedAccount @@ -52,7 +52,7 @@ export class ImportedAccount keyPair: inputs.keyPair, }; return { - type: AccountType.Imported, + type: AccountType.PrivateKeyDerived, address: keyPair.getPublicKey().toIotaAddress(), publicKey: keyPair.getPublicKey().toBase64(), encrypted: await encrypt(inputs.password, dataToEncrypt), @@ -64,11 +64,11 @@ export class ImportedAccount } static isOfType(serialized: SerializedAccount): serialized is ImportedAccountSerialized { - return serialized.type === AccountType.Imported; + return serialized.type === AccountType.PrivateKeyDerived; } constructor({ id, cachedData }: { id: string; cachedData?: ImportedAccountSerialized }) { - super({ type: AccountType.Imported, id, cachedData }); + super({ type: AccountType.PrivateKeyDerived, id, cachedData }); } async lock(allowRead = false): Promise { diff --git a/apps/wallet/src/background/accounts/LedgerAccount.ts b/apps/wallet/src/background/accounts/LedgerAccount.ts index 48508a40169..fbb8ca111c2 100644 --- a/apps/wallet/src/background/accounts/LedgerAccount.ts +++ b/apps/wallet/src/background/accounts/LedgerAccount.ts @@ -13,21 +13,21 @@ import { } from './Account'; export interface LedgerAccountSerialized extends SerializedAccount { - type: AccountType.Ledger; + type: AccountType.LedgerDerived; derivationPath: string; // just used for authentication nothing is stored here at the moment encrypted: string; } export interface LedgerAccountSerializedUI extends SerializedUIAccount { - type: AccountType.Ledger; + type: AccountType.LedgerDerived; derivationPath: string; } export function isLedgerAccountSerializedUI( account: SerializedUIAccount, ): account is LedgerAccountSerializedUI { - return account.type === AccountType.Ledger; + return account.type === AccountType.LedgerDerived; } type EphemeralData = { @@ -52,7 +52,7 @@ export class LedgerAccount derivationPath: string; }): Promise> { return { - type: AccountType.Ledger, + type: AccountType.LedgerDerived, address, publicKey, encrypted: await encrypt(password, {}), @@ -65,11 +65,11 @@ export class LedgerAccount } static isOfType(serialized: SerializedAccount): serialized is LedgerAccountSerialized { - return serialized.type === AccountType.Ledger; + return serialized.type === AccountType.LedgerDerived; } constructor({ id, cachedData }: { id: string; cachedData?: LedgerAccountSerialized }) { - super({ type: AccountType.Ledger, id, cachedData }); + super({ type: AccountType.LedgerDerived, id, cachedData }); } async lock(allowRead = false): Promise { diff --git a/apps/wallet/src/background/accounts/index.ts b/apps/wallet/src/background/accounts/index.ts index 3984aa1f9e3..880ef5dfef5 100644 --- a/apps/wallet/src/background/accounts/index.ts +++ b/apps/wallet/src/background/accounts/index.ts @@ -221,9 +221,9 @@ export async function accountsHandleUIMessage(msg: Message, uiConnection: UiConn throw new Error(`Invalid account source type`); } newSerializedAccounts.push(await accountSource.deriveAccount()); - } else if (type === AccountType.Imported) { + } else if (type === AccountType.PrivateKeyDerived) { newSerializedAccounts.push(await ImportedAccount.createNew(payload.args)); - } else if (type === AccountType.Ledger) { + } else if (type === AccountType.LedgerDerived) { const { password, accounts } = payload.args; for (const aLedgerAccount of accounts) { newSerializedAccounts.push( diff --git a/apps/wallet/src/shared/analytics/ampli/index.ts b/apps/wallet/src/shared/analytics/ampli/index.ts index b9d4451dad9..09de5bb945d 100644 --- a/apps/wallet/src/shared/analytics/ampli/index.ts +++ b/apps/wallet/src/shared/analytics/ampli/index.ts @@ -109,9 +109,9 @@ export interface AddedAccountsProperties { * * | Rule | Value | * |---|---| - * | Enum Values | Ledger, Derived, Imported| + * | Enum Values | Ledger, Derived, Private Key| */ - accountType: 'Ledger' | 'Derived' | 'Imported'; + accountType: 'Ledger' | 'Derived' | 'Private Key'; /** * The number of accounts imported. * diff --git a/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts b/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts index d7665467a44..a95b531c51a 100644 --- a/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts +++ b/apps/wallet/src/shared/messaging/messages/payloads/MethodPayload.ts @@ -46,9 +46,9 @@ type MethodPayloads = { createAccounts: | { type: AccountType.MnemonicDerived; sourceID: string } | { type: AccountType.SeedDerived; sourceID: string } - | { type: AccountType.Imported; keyPair: string; password: string } + | { type: AccountType.PrivateKeyDerived; keyPair: string; password: string } | { - type: AccountType.Ledger; + type: AccountType.LedgerDerived; accounts: { publicKey: string; derivationPath: string; address: string }[]; password: string; }; diff --git a/apps/wallet/src/ui/app/ApiProvider.ts b/apps/wallet/src/ui/app/ApiProvider.ts index 618fc1b97ab..676316f5b87 100644 --- a/apps/wallet/src/ui/app/ApiProvider.ts +++ b/apps/wallet/src/ui/app/ApiProvider.ts @@ -14,7 +14,7 @@ import { type WalletSigner } from './WalletSigner'; const ACCOUNT_TYPES_WITH_BACKGROUND_SIGNER: AccountType[] = [ AccountType.MnemonicDerived, AccountType.SeedDerived, - AccountType.Imported, + AccountType.PrivateKeyDerived, ]; export default class ApiProvider { @@ -60,7 +60,7 @@ export default class ApiProvider { if (ACCOUNT_TYPES_WITH_BACKGROUND_SIGNER.includes(account.type)) { return this.getBackgroundSignerInstance(account, backgroundClient); } - if (AccountType.Ledger === account.type) { + if (AccountType.LedgerDerived === account.type) { // Ideally, Ledger transactions would be signed in the background // and exist as an asynchronous keypair; however, this isn't possible // because you can't connect to a Ledger device from the background diff --git a/apps/wallet/src/ui/app/components/AccountBadge.tsx b/apps/wallet/src/ui/app/components/AccountBadge.tsx index b142cb6db6c..27cbf22188b 100644 --- a/apps/wallet/src/ui/app/components/AccountBadge.tsx +++ b/apps/wallet/src/ui/app/components/AccountBadge.tsx @@ -11,8 +11,8 @@ interface AccountBadgeProps { } const TYPE_TO_TEXT: Record = { - [AccountType.Ledger]: 'Ledger', - [AccountType.Imported]: 'Imported', + [AccountType.LedgerDerived]: 'Ledger', + [AccountType.PrivateKeyDerived]: 'Private Key', [AccountType.MnemonicDerived]: null, [AccountType.SeedDerived]: null, }; diff --git a/apps/wallet/src/ui/app/components/accounts/AccountIcon.tsx b/apps/wallet/src/ui/app/components/accounts/AccountIcon.tsx index 7a9d7532985..e200c0e5888 100644 --- a/apps/wallet/src/ui/app/components/accounts/AccountIcon.tsx +++ b/apps/wallet/src/ui/app/components/accounts/AccountIcon.tsx @@ -18,7 +18,7 @@ interface AccountIconProps { } export function AccountIcon({ account }: AccountIconProps) { - if (account.type === AccountType.Ledger) { + if (account.type === AccountType.LedgerDerived) { return ; } return ; diff --git a/apps/wallet/src/ui/app/components/accounts/AccountsFormContext.tsx b/apps/wallet/src/ui/app/components/accounts/AccountsFormContext.tsx index 01f2b3db65a..099c72e2f05 100644 --- a/apps/wallet/src/ui/app/components/accounts/AccountsFormContext.tsx +++ b/apps/wallet/src/ui/app/components/accounts/AccountsFormContext.tsx @@ -2,7 +2,6 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import type { AccountType } from '_src/background/accounts/Account'; import { createContext, useCallback, @@ -13,21 +12,25 @@ import { type ReactNode, } from 'react'; -export enum CreateAccountType { +export enum AccountsFormType { NewMnemonic = 'new-mnemonic', ImportMnemonic = 'import-mnemonic', ImportSeed = 'import-seed', + ImportPrivateKey = 'import-private-key', + ImportLedger = 'import-ledger', + MnemonicSource = 'mnemonic-source', + SeedSource = 'seed-source', } export type AccountsFormValues = - | { type: CreateAccountType.NewMnemonic } - | { type: CreateAccountType.ImportMnemonic; entropy: string } - | { type: CreateAccountType.ImportSeed; seed: string } - | { type: AccountType.MnemonicDerived; sourceID: string } - | { type: AccountType.SeedDerived; sourceID: string } - | { type: AccountType.Imported; keyPair: string } + | { type: AccountsFormType.NewMnemonic } + | { type: AccountsFormType.ImportMnemonic; entropy: string } + | { type: AccountsFormType.ImportSeed; seed: string } + | { type: AccountsFormType.MnemonicSource; sourceID: string } + | { type: AccountsFormType.SeedSource; sourceID: string } + | { type: AccountsFormType.ImportPrivateKey; keyPair: string } | { - type: AccountType.Ledger; + type: AccountsFormType.ImportLedger; accounts: { publicKey: string; derivationPath: string; address: string }[]; } | null; diff --git a/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts b/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts index 0203444ccc7..d3f593461a7 100644 --- a/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts +++ b/apps/wallet/src/ui/app/components/ledger/useDeriveLedgerAccounts.ts @@ -48,7 +48,7 @@ async function deriveAccountsFromLedger( const publicKey = new Ed25519PublicKey(publicKeyResult.publicKey); const iotaAddress = publicKey.toIotaAddress(); ledgerAccounts.push({ - type: AccountType.Ledger, + type: AccountType.LedgerDerived, address: iotaAddress, derivationPath, publicKey: publicKey.toBase64(), diff --git a/apps/wallet/src/ui/app/helpers/accounts.ts b/apps/wallet/src/ui/app/helpers/accounts.ts index 4bf2a04bb7f..8dc6853d316 100644 --- a/apps/wallet/src/ui/app/helpers/accounts.ts +++ b/apps/wallet/src/ui/app/helpers/accounts.ts @@ -15,8 +15,8 @@ function getKey(account: SerializedUIAccount): string { export const DEFAULT_SORT_ORDER: AccountType[] = [ AccountType.MnemonicDerived, AccountType.SeedDerived, - AccountType.Imported, - AccountType.Ledger, + AccountType.PrivateKeyDerived, + AccountType.LedgerDerived, ]; export function groupByType(accounts: SerializedUIAccount[]) { diff --git a/apps/wallet/src/ui/app/hooks/useCreateAccountMutation.ts b/apps/wallet/src/ui/app/hooks/useCreateAccountMutation.ts index 1a5a2b1b7c3..299051a6b05 100644 --- a/apps/wallet/src/ui/app/hooks/useCreateAccountMutation.ts +++ b/apps/wallet/src/ui/app/hooks/useCreateAccountMutation.ts @@ -6,16 +6,14 @@ import { ampli, type AddedAccountsProperties } from '_src/shared/analytics/ampli import { useMutation } from '@tanstack/react-query'; import { - CreateAccountType, useAccountsFormContext, + AccountsFormType, type AccountsFormValues, } from '../components/accounts/AccountsFormContext'; import { useBackgroundClient } from './useBackgroundClient'; import { AccountType } from '_src/background/accounts/Account'; -export type CreateType = NonNullable['type']; - -function validateAccountFormValues( +function validateAccountFormValues( createType: T, values: AccountsFormValues, password?: string, @@ -27,8 +25,8 @@ function validateAccountFormValues( throw new Error('Account data values type mismatch'); } if ( - values.type !== AccountType.MnemonicDerived && - values.type !== AccountType.SeedDerived && + values.type !== AccountsFormType.MnemonicSource && + values.type !== AccountsFormType.SeedSource && !password ) { throw new Error('Missing password'); @@ -37,17 +35,20 @@ function validateAccountFormValues( } enum AmpliAccountType { Derived = 'Derived', - Imported = 'Imported', + ImportPrivateKey = 'Private Key', Ledger = 'Ledger', } -const CREATE_TYPE_TO_AMPLI_ACCOUNT: Record = { - [CreateAccountType.NewMnemonic]: AmpliAccountType.Derived, - [CreateAccountType.ImportMnemonic]: AmpliAccountType.Derived, - [CreateAccountType.ImportSeed]: AmpliAccountType.Derived, - [AccountType.MnemonicDerived]: AmpliAccountType.Derived, - [AccountType.SeedDerived]: AmpliAccountType.Derived, - [AccountType.Imported]: AmpliAccountType.Imported, - [AccountType.Ledger]: AmpliAccountType.Ledger, +const CREATE_TYPE_TO_AMPLI_ACCOUNT: Record< + AccountsFormType, + AddedAccountsProperties['accountType'] +> = { + [AccountsFormType.NewMnemonic]: AmpliAccountType.Derived, + [AccountsFormType.ImportMnemonic]: AmpliAccountType.Derived, + [AccountsFormType.ImportSeed]: AmpliAccountType.Derived, + [AccountsFormType.MnemonicSource]: AmpliAccountType.Derived, + [AccountsFormType.SeedSource]: AmpliAccountType.Derived, + [AccountsFormType.ImportPrivateKey]: AmpliAccountType.ImportPrivateKey, + [AccountsFormType.ImportLedger]: AmpliAccountType.Ledger, }; export function useCreateAccountsMutation() { @@ -55,12 +56,12 @@ export function useCreateAccountsMutation() { const [accountsFormValuesRef, setAccountFormValues] = useAccountsFormContext(); return useMutation({ mutationKey: ['create accounts'], - mutationFn: async ({ type, password }: { type: CreateType; password?: string }) => { + mutationFn: async ({ type, password }: { type: AccountsFormType; password?: string }) => { let createdAccounts; const accountsFormValues = accountsFormValuesRef.current; if ( - (type === CreateAccountType.NewMnemonic || - type === CreateAccountType.ImportMnemonic) && + (type === AccountsFormType.NewMnemonic || + type === AccountsFormType.ImportMnemonic) && validateAccountFormValues(type, accountsFormValues, password) ) { const accountSource = await backgroundClient.createMnemonicAccountSource({ @@ -78,7 +79,7 @@ export function useCreateAccountsMutation() { sourceID: accountSource.id, }); } else if ( - type === AccountType.MnemonicDerived && + type === AccountsFormType.MnemonicSource && validateAccountFormValues(type, accountsFormValues, password) ) { if (password) { @@ -92,7 +93,7 @@ export function useCreateAccountsMutation() { sourceID: accountsFormValues.sourceID, }); } else if ( - type === CreateAccountType.ImportSeed && + type === AccountsFormType.ImportSeed && validateAccountFormValues(type, accountsFormValues, password) ) { const accountSource = await backgroundClient.createSeedAccountSource({ @@ -109,7 +110,7 @@ export function useCreateAccountsMutation() { sourceID: accountSource.id, }); } else if ( - type === AccountType.SeedDerived && + type === AccountsFormType.SeedSource && validateAccountFormValues(type, accountsFormValues, password) ) { if (password) { @@ -123,20 +124,20 @@ export function useCreateAccountsMutation() { sourceID: accountsFormValues.sourceID, }); } else if ( - type === AccountType.Imported && + type === AccountsFormType.ImportPrivateKey && validateAccountFormValues(type, accountsFormValues, password) ) { createdAccounts = await backgroundClient.createAccounts({ - type: AccountType.Imported, + type: AccountType.PrivateKeyDerived, keyPair: accountsFormValues.keyPair, password: password!, }); } else if ( - type === AccountType.Ledger && + type === AccountsFormType.ImportLedger && validateAccountFormValues(type, accountsFormValues, password) ) { createdAccounts = await backgroundClient.createAccounts({ - type: AccountType.Ledger, + type: AccountType.LedgerDerived, accounts: accountsFormValues.accounts, password: password!, }); diff --git a/apps/wallet/src/ui/app/pages/accounts/AddAccountPage.tsx b/apps/wallet/src/ui/app/pages/accounts/AddAccountPage.tsx index ab5fecc7dd6..b3e3cd1bd7e 100644 --- a/apps/wallet/src/ui/app/pages/accounts/AddAccountPage.tsx +++ b/apps/wallet/src/ui/app/pages/accounts/AddAccountPage.tsx @@ -13,7 +13,7 @@ import { useNavigate, useSearchParams } from 'react-router-dom'; import Browser from 'webextension-polyfill'; import { - CreateAccountType, + AccountsFormType, useAccountsFormContext, } from '../../components/accounts/AccountsFormContext'; import { ConnectLedgerModal } from '../../components/ledger/ConnectLedgerModal'; @@ -71,9 +71,9 @@ export function AddAccountPage() { variant="outline" size="tall" text="Create a new Passphrase Account" - to="/accounts/protect-account?accountType=new-mnemonic" + to={`/accounts/protect-account?accountsFormType=${AccountsFormType.NewMnemonic}`} onClick={() => { - setAccountsFormValues({ type: CreateAccountType.NewMnemonic }); + setAccountsFormValues({ type: AccountsFormType.NewMnemonic }); ampli.clickedCreateNewAccount({ sourceFlow }); }} disabled={createAccountsMutation.isPending} diff --git a/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx b/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx index a5cdd52874f..1356be5039d 100644 --- a/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx +++ b/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx @@ -14,7 +14,10 @@ import { useCallback, useEffect, useState } from 'react'; import toast from 'react-hot-toast'; import { useNavigate, useSearchParams } from 'react-router-dom'; -import { useAccountsFormContext } from '../../components/accounts/AccountsFormContext'; +import { + AccountsFormType, + useAccountsFormContext, +} from '../../components/accounts/AccountsFormContext'; import { LedgerAccountList, type SelectableLedgerAccount, @@ -26,7 +29,6 @@ import { import Overlay from '../../components/overlay'; import { getIotaApplicationErrorMessage } from '../../helpers/errorMessages'; import { useAccounts } from '../../hooks/useAccounts'; -import { AccountType } from '_src/background/accounts/Account'; const NUM_LEDGER_ACCOUNTS_TO_DERIVE_BY_DEFAULT = 10; @@ -158,7 +160,7 @@ export function ImportLedgerAccountsPage() { disabled={isUnlockButtonDisabled} onClick={() => { setAccountsFormValues({ - type: AccountType.Ledger, + type: AccountsFormType.ImportLedger, accounts: selectedLedgerAccounts.map( ({ address, derivationPath, publicKey }) => ({ address, @@ -169,7 +171,7 @@ export function ImportLedgerAccountsPage() { }); navigate( `/accounts/protect-account?${new URLSearchParams({ - accountType: AccountType.Ledger, + accountsFormType: AccountsFormType.ImportLedger, successRedirect, }).toString()}`, ); diff --git a/apps/wallet/src/ui/app/pages/accounts/ImportPassphrasePage.tsx b/apps/wallet/src/ui/app/pages/accounts/ImportPassphrasePage.tsx index e6ccf75596e..1ee8be8028a 100644 --- a/apps/wallet/src/ui/app/pages/accounts/ImportPassphrasePage.tsx +++ b/apps/wallet/src/ui/app/pages/accounts/ImportPassphrasePage.tsx @@ -7,7 +7,7 @@ import { entropyToSerialized, mnemonicToEntropy } from '_src/shared/utils/bip39' import { useNavigate } from 'react-router-dom'; import { - CreateAccountType, + AccountsFormType, useAccountsFormContext, } from '../../components/accounts/AccountsFormContext'; import { ImportRecoveryPhraseForm } from '../../components/accounts/ImportRecoveryPhraseForm'; @@ -37,12 +37,16 @@ export function ImportPassphrasePage() { submitButtonText="Add Account" onSubmit={({ recoveryPhrase }) => { setFormValues({ - type: CreateAccountType.ImportMnemonic, + type: AccountsFormType.ImportMnemonic, entropy: entropyToSerialized( mnemonicToEntropy(recoveryPhrase.join(' ')), ), }); - navigate('/accounts/protect-account?accountType=import-mnemonic'); + navigate( + `/accounts/protect-account?${new URLSearchParams({ + accountsFormType: AccountsFormType.ImportMnemonic, + }).toString()}`, + ); }} /> diff --git a/apps/wallet/src/ui/app/pages/accounts/ImportPrivateKeyPage.tsx b/apps/wallet/src/ui/app/pages/accounts/ImportPrivateKeyPage.tsx index ecc51ec04f7..c1e519e495d 100644 --- a/apps/wallet/src/ui/app/pages/accounts/ImportPrivateKeyPage.tsx +++ b/apps/wallet/src/ui/app/pages/accounts/ImportPrivateKeyPage.tsx @@ -5,10 +5,12 @@ import { Text } from '_app/shared/text'; import { useNavigate } from 'react-router-dom'; -import { useAccountsFormContext } from '../../components/accounts/AccountsFormContext'; +import { + AccountsFormType, + useAccountsFormContext, +} from '../../components/accounts/AccountsFormContext'; import { ImportPrivateKeyForm } from '../../components/accounts/ImportPrivateKeyForm'; import { Heading } from '../../shared/heading'; -import { AccountType } from '_src/background/accounts/Account'; export function ImportPrivateKeyPage() { const navigate = useNavigate(); @@ -28,10 +30,14 @@ export function ImportPrivateKeyPage() { { setAccountsFormValues({ - type: AccountType.Imported, + type: AccountsFormType.ImportPrivateKey, keyPair: privateKey, }); - navigate('/accounts/protect-account?accountType=imported'); + navigate( + `/accounts/protect-account?${new URLSearchParams({ + accountsFormType: AccountsFormType.ImportPrivateKey, + }).toString()}`, + ); }} /> diff --git a/apps/wallet/src/ui/app/pages/accounts/ImportSeedPage.tsx b/apps/wallet/src/ui/app/pages/accounts/ImportSeedPage.tsx index 894107cd625..b367ed055f1 100644 --- a/apps/wallet/src/ui/app/pages/accounts/ImportSeedPage.tsx +++ b/apps/wallet/src/ui/app/pages/accounts/ImportSeedPage.tsx @@ -5,7 +5,7 @@ import { Text } from '_app/shared/text'; import { useNavigate } from 'react-router-dom'; import { - CreateAccountType, + AccountsFormType, useAccountsFormContext, } from '../../components/accounts/AccountsFormContext'; import { ImportSeedForm } from '../../components/accounts/ImportSeedForm'; @@ -29,10 +29,14 @@ export function ImportSeedPage() { { setAccountsFormValues({ - type: CreateAccountType.ImportSeed, + type: AccountsFormType.ImportSeed, seed, }); - navigate('/accounts/protect-account?accountType=import-seed'); + navigate( + `/accounts/protect-account?${new URLSearchParams({ + accountsFormType: AccountsFormType.ImportSeed, + }).toString()}`, + ); }} /> diff --git a/apps/wallet/src/ui/app/pages/accounts/ProtectAccountPage.tsx b/apps/wallet/src/ui/app/pages/accounts/ProtectAccountPage.tsx index f8d820c43a1..95ba770db2a 100644 --- a/apps/wallet/src/ui/app/pages/accounts/ProtectAccountPage.tsx +++ b/apps/wallet/src/ui/app/pages/accounts/ProtectAccountPage.tsx @@ -15,35 +15,34 @@ import Loading from '../../components/loading'; import { useAccounts } from '../../hooks/useAccounts'; import { autoLockDataToMinutes } from '../../hooks/useAutoLockMinutes'; import { useAutoLockMinutesMutation } from '../../hooks/useAutoLockMinutesMutation'; -import { useCreateAccountsMutation, type CreateType } from '../../hooks/useCreateAccountMutation'; +import { useCreateAccountsMutation } from '../../hooks/useCreateAccountMutation'; import { Heading } from '../../shared/heading'; -import { CreateAccountType } from '../../components/accounts/AccountsFormContext'; -import { AccountType } from '_src/background/accounts/Account'; +import { AccountsFormType } from '../../components/accounts/AccountsFormContext'; -const ALLOWED_ACCOUNT_TYPES: CreateType[] = [ - CreateAccountType.NewMnemonic, - CreateAccountType.ImportMnemonic, - CreateAccountType.ImportSeed, - AccountType.MnemonicDerived, - AccountType.SeedDerived, - AccountType.Imported, - AccountType.Ledger, +const ALLOWED_ACCOUNT_TYPES: AccountsFormType[] = [ + AccountsFormType.NewMnemonic, + AccountsFormType.ImportMnemonic, + AccountsFormType.ImportSeed, + AccountsFormType.MnemonicSource, + AccountsFormType.SeedSource, + AccountsFormType.ImportPrivateKey, + AccountsFormType.ImportLedger, ]; -const REDIRECT_TO_ACCOUNTS_FINDER: CreateType[] = [ - CreateAccountType.ImportMnemonic, - CreateAccountType.ImportSeed, +const REDIRECT_TO_ACCOUNTS_FINDER: AccountsFormType[] = [ + AccountsFormType.ImportMnemonic, + AccountsFormType.ImportSeed, ]; type AllowedAccountTypes = (typeof ALLOWED_ACCOUNT_TYPES)[number]; function isAllowedAccountType(accountType: string): accountType is AllowedAccountTypes { - return ALLOWED_ACCOUNT_TYPES.includes(accountType as CreateType); + return ALLOWED_ACCOUNT_TYPES.includes(accountType as AccountsFormType); } export function ProtectAccountPage() { const [searchParams] = useSearchParams(); - const accountType = searchParams.get('accountType') || ''; + const accountsFormType = searchParams.get('accountsFormType') || ''; const successRedirect = searchParams.get('successRedirect') || '/tokens'; const navigate = useNavigate(); const { data: accounts } = useAccounts(); @@ -62,14 +61,14 @@ export function ProtectAccountPage() { } }, [hasPasswordAccounts, createMutation.isSuccess, createMutation.isPending]); const createAccountCallback = useCallback( - async (password: string, type: CreateType) => { + async (password: string, type: AccountsFormType) => { try { const createdAccounts = await createMutation.mutateAsync({ type, password, }); if ( - type === CreateAccountType.NewMnemonic && + type === AccountsFormType.NewMnemonic && isMnemonicSerializedUiAccount(createdAccounts[0]) ) { navigate(`/accounts/backup/${createdAccounts[0].sourceID}`, { @@ -100,7 +99,7 @@ export function ProtectAccountPage() { [createMutation, navigate, successRedirect], ); const autoLockMutation = useAutoLockMinutesMutation(); - if (!isAllowedAccountType(accountType)) { + if (!isAllowedAccountType(accountsFormType)) { return ; } @@ -111,7 +110,7 @@ export function ProtectAccountPage() { navigate(-1)} - onVerify={(password) => createAccountCallback(password, accountType)} + onVerify={(password) => createAccountCallback(password, accountsFormType)} /> ) : ( <> @@ -131,7 +130,7 @@ export function ProtectAccountPage() { await autoLockMutation.mutateAsync({ minutes: autoLockDataToMinutes(autoLock), }); - await createAccountCallback(password.input, accountType); + await createAccountCallback(password.input, accountsFormType); }} /> diff --git a/apps/wallet/src/ui/app/pages/accounts/manage/AccountGroup.tsx b/apps/wallet/src/ui/app/pages/accounts/manage/AccountGroup.tsx index 509f09f5af9..42730e177a1 100644 --- a/apps/wallet/src/ui/app/pages/accounts/manage/AccountGroup.tsx +++ b/apps/wallet/src/ui/app/pages/accounts/manage/AccountGroup.tsx @@ -5,7 +5,10 @@ import { AccountType, type SerializedUIAccount } from '_src/background/accounts/Account'; import { AccountIcon } from '_src/ui/app/components/accounts/AccountIcon'; import { AccountItem } from '_src/ui/app/components/accounts/AccountItem'; -import { useAccountsFormContext } from '_src/ui/app/components/accounts/AccountsFormContext'; +import { + AccountsFormType, + useAccountsFormContext, +} from '_src/ui/app/components/accounts/AccountsFormContext'; import { NicknameDialog } from '_src/ui/app/components/accounts/NicknameDialog'; import { VerifyPasswordModal } from '_src/ui/app/components/accounts/VerifyPasswordModal'; import { useAccounts } from '_src/ui/app/hooks/useAccounts'; @@ -34,13 +37,13 @@ import { useNavigate } from 'react-router-dom'; const ACCOUNT_TYPE_TO_LABEL: Record = { [AccountType.MnemonicDerived]: 'Passphrase Derived', [AccountType.SeedDerived]: 'Seed Derived', - [AccountType.Imported]: 'Imported', - [AccountType.Ledger]: 'Ledger', + [AccountType.PrivateKeyDerived]: 'Private Key', + [AccountType.LedgerDerived]: 'Ledger', }; const ACCOUNTS_WITH_ENABLED_BALANCE_FINDER: AccountType[] = [ AccountType.MnemonicDerived, AccountType.SeedDerived, - AccountType.Ledger, + AccountType.LedgerDerived, ]; export function getGroupTitle(aGroupAccount: SerializedUIAccount) { @@ -174,6 +177,18 @@ export function AccountGroup({ {getGroupTitle(accounts[0])}
+ {ACCOUNTS_WITH_ENABLED_BALANCE_FINDER.includes(type) ? ( + { + navigate( + `/accounts/manage/accounts-finder/${accountSourceID}`, + ); + }} + > + + + ) : null} {(isMnemonicDerivedGroup || isSeedDerivedGroup) && accountSource ? ( <> { // prevent the collapsible from closing when clicking the "new" button e.stopPropagation(); + const accountsFormType = isMnemonicDerivedGroup + ? AccountsFormType.MnemonicSource + : AccountsFormType.SeedSource; setAccountsFormValues({ - type, + type: accountsFormType, sourceID: accountSource.id, }); if (accountSource.isLocked) { setPasswordModalVisible(true); } else { - createAccountMutation.mutate({ type }); + createAccountMutation.mutate({ + type: accountsFormType, + }); } }} className="flex cursor-pointer appearance-none items-center justify-center gap-0.5 border-0 bg-transparent uppercase text-hero outline-none hover:text-hero-darkest" @@ -200,18 +220,6 @@ export function AccountGroup({ ) : null} - {ACCOUNTS_WITH_ENABLED_BALANCE_FINDER.includes(type) ? ( - { - navigate( - `/accounts/manage/accounts-finder/${accountSourceID}`, - ); - }} - > - - - ) : null}
diff --git a/crates/iota-genesis-builder/Cargo.toml b/crates/iota-genesis-builder/Cargo.toml index 4c830b1a1cb..ebf6ea68f9e 100644 --- a/crates/iota-genesis-builder/Cargo.toml +++ b/crates/iota-genesis-builder/Cargo.toml @@ -12,6 +12,7 @@ bcs.workspace = true camino.workspace = true clap.workspace = true fastcrypto.workspace = true +flate2.workspace = true itertools.workspace = true move-binary-format.workspace = true move-compiler.workspace = true @@ -22,6 +23,7 @@ prometheus.workspace = true rand = { workspace = true, features = ["std_rng"] } rand_regex.workspace = true regex.workspace = true +reqwest.workspace = true serde.workspace = true serde_json.workspace = true serde_with.workspace = true diff --git a/crates/iota-genesis-builder/examples/build_stardust_genesis_from_s3.rs b/crates/iota-genesis-builder/examples/build_stardust_genesis_from_s3.rs new file mode 100644 index 00000000000..9ad5b9c229a --- /dev/null +++ b/crates/iota-genesis-builder/examples/build_stardust_genesis_from_s3.rs @@ -0,0 +1,55 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +//! Creating a genesis blob out of a remote stardust objects snapshots. + +use iota_genesis_builder::{ + Builder, SnapshotUrl, IOTA_OBJECT_SNAPSHOT_URL, SHIMMER_OBJECT_SNAPSHOT_URL, +}; +use iota_swarm_config::genesis_config::ValidatorGenesisConfigBuilder; +use rand::rngs::OsRng; +use tracing::{info, Level}; +use tracing_subscriber::FmtSubscriber; + +fn main() -> anyhow::Result<()> { + // Initialize tracing + let subscriber = FmtSubscriber::builder() + .with_max_level(Level::INFO) + .finish(); + tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed"); + + info!("Reading IOTA snapshot from {}", IOTA_OBJECT_SNAPSHOT_URL); + let iota_snapshot_reader = Builder::read_snapshot_from_s3(SnapshotUrl::Iota)?; + + info!( + "Reading Shimmer snapshot from {}", + SHIMMER_OBJECT_SNAPSHOT_URL + ); + let shimmer_snapshot_reader = Builder::read_snapshot_from_s3(SnapshotUrl::Shimmer)?; + + // Start building + info!("Building the genesis.."); + let mut builder = Builder::new() + .add_migration_objects(iota_snapshot_reader)? + .add_migration_objects(shimmer_snapshot_reader)?; + + let mut key_pairs = Vec::new(); + let mut rng = OsRng; + for i in 0..4 { + let validator_config = ValidatorGenesisConfigBuilder::default().build(&mut rng); + let validator_info = validator_config.to_validator_info(format!("validator-{i}")); + builder = builder.add_validator(validator_info.info, validator_info.proof_of_possession); + key_pairs.push(validator_config.key_pair); + } + + for key in &key_pairs { + builder = builder.add_validator_signature(key); + } + + let genesis = builder.build(); + println!("{:?}", genesis); + + info!("Genesis built successfully"); + + Ok(()) +} diff --git a/crates/iota-genesis-builder/src/lib.rs b/crates/iota-genesis-builder/src/lib.rs index ee7ec922183..be5c93925cb 100644 --- a/crates/iota-genesis-builder/src/lib.rs +++ b/crates/iota-genesis-builder/src/lib.rs @@ -5,7 +5,7 @@ use std::{ collections::{BTreeMap, HashSet}, fs, - io::prelude::Read, + io::{prelude::Read, BufReader}, path::Path, sync::Arc, }; @@ -13,6 +13,7 @@ use std::{ use anyhow::{bail, Context}; use camino::Utf8Path; use fastcrypto::{hash::HashFunction, traits::KeyPair}; +use flate2::bufread::GzDecoder; use iota_config::genesis::{ Genesis, GenesisCeremonyParameters, GenesisChainParameters, TokenDistributionSchedule, UnsignedGenesis, @@ -20,6 +21,7 @@ use iota_config::genesis::{ use iota_execution::{self, Executor}; use iota_framework::{BuiltInFramework, SystemPackage}; use iota_protocol_config::{Chain, ProtocolConfig, ProtocolVersion}; +use iota_sdk::Url; use iota_types::{ base_types::{ ExecutionDigests, IotaAddress, ObjectID, SequenceNumber, TransactionDigest, TxContext, @@ -70,8 +72,9 @@ pub const BROTLI_COMPRESSOR_BUFFER_SIZE: usize = 4096; pub const BROTLI_COMPRESSOR_QUALITY: u32 = 11; /// The LZ77 window size (0, 10-24) where bigger windows size improves density. pub const BROTLI_COMPRESSOR_LG_WINDOW_SIZE: u32 = 22; - pub const OBJECT_SNAPSHOT_FILE_PATH: &str = "stardust_object_snapshot.bin"; +pub const IOTA_OBJECT_SNAPSHOT_URL: &str = "https://stardust-objects.s3.eu-central-1.amazonaws.com/iota/alphanet/latest/stardust_object_snapshot.bin.gz"; +pub const SHIMMER_OBJECT_SNAPSHOT_URL: &str = "https://stardust-objects.s3.eu-central-1.amazonaws.com/shimmer/alphanet/latest/stardust_object_snapshot.bin.gz"; pub struct Builder { parameters: GenesisCeremonyParameters, @@ -180,6 +183,13 @@ impl Builder { Ok(self.add_objects(bcs::from_reader(reader)?)) } + /// Reads a gzip compressed object snapshot from the S3. + pub fn read_snapshot_from_s3(url: SnapshotUrl) -> anyhow::Result { + Ok(GzDecoder::new(BufReader::new(reqwest::blocking::get( + url.to_url(), + )?))) + } + pub fn unsigned_genesis_checkpoint(&self) -> Option { self.built_genesis.clone() } @@ -1158,6 +1168,23 @@ pub fn generate_genesis_system_object( Ok(()) } +/// The URLs to download Iota or Shimmer object snapshots. +#[derive(Debug, Clone)] +pub enum SnapshotUrl { + Iota, + Shimmer, +} + +impl SnapshotUrl { + /// Returns the Iota or Shimmer object snapshot download URL. + pub fn to_url(&self) -> Url { + match self { + Self::Iota => Url::parse(IOTA_OBJECT_SNAPSHOT_URL).expect("should be valid URL"), + Self::Shimmer => Url::parse(SHIMMER_OBJECT_SNAPSHOT_URL).expect("should be valid URL"), + } + } +} + #[cfg(test)] mod test { use fastcrypto::traits::KeyPair; diff --git a/package.json b/package.json index a0459b69613..0d6e6a119fe 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "explorer-dev": "turbo --filter iota-explorer --filter apps-backend dev", "wallet-dev": "turbo --filter ./apps/wallet --filter apps-backend dev", "wallet-dashboard-dev": "turbo --filter ./apps/wallet-dashboard --filter apps-backend dev", + "ui-kit": "turbo --filter ./apps/ui-kit", "explorer": "turbo --filter iota-explorer", "wallet": "turbo --filter ./apps/wallet", "wallet-dashboard": "turbo --filter ./apps/wallet-dashboard", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3704a6f1676..da14b56973c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -631,6 +631,67 @@ importers: specifier: ^5.3.3 version: 5.3.3 + apps/ui-kit: + dependencies: + '@iota/core': + specifier: workspace:* + version: link:../core + '@iota/icons': + specifier: workspace:* + version: link:../icons + react: + specifier: ^18.2.0 + version: 18.2.0 + react-dom: + specifier: ^18.2.0 + version: 18.2.0(react@18.2.0) + devDependencies: + '@chromatic-com/storybook': + specifier: ^1.6.0 + version: 1.6.0(react@18.2.0) + '@storybook/addon-essentials': + specifier: ^7.1.0 + version: 7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@storybook/addon-interactions': + specifier: ^7.1.0 + version: 7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@storybook/addon-links': + specifier: ^7.1.0 + version: 7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@storybook/addon-onboarding': + specifier: ^8.1.11 + version: 8.1.11(react@18.2.0) + '@storybook/blocks': + specifier: ^7.1.0 + version: 7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@storybook/react': + specifier: ^7.1.0 + version: 7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5) + '@storybook/react-vite': + specifier: ^7.1.0 + version: 7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@3.29.4)(typescript@5.4.5)(vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0)) + '@storybook/test': + specifier: ^8.1.11 + version: 8.1.11(@jest/globals@29.7.0)(@types/jest@29.5.3)(jest@29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)))(vitest@0.33.0(sass@1.63.6)(terser@5.31.0)) + '@types/react': + specifier: ^18.2.15 + version: 18.2.15 + storybook: + specifier: ^7.1.0 + version: 7.1.0 + tailwindcss: + specifier: ^3.3.3 + version: 3.3.3(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + typescript: + specifier: ^5.3.3 + version: 5.4.5 + vite: + specifier: ^4.4.4 + version: 4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0) + vite-tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0(typescript@5.4.5)(vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0)) + apps/wallet: dependencies: '@amplitude/analytics-browser': @@ -1890,6 +1951,9 @@ packages: '@adobe/css-tools@4.2.0': resolution: {integrity: sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==} + '@adobe/css-tools@4.4.0': + resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -3051,6 +3115,10 @@ packages: '@changesets/write@0.3.1': resolution: {integrity: sha512-SyGtMXzH3qFqlHKcvFY2eX+6b0NGiFcNav8AFsYwy5l8hejOeoeTDemu5Yjmke2V5jpzY+pBvM0vCCQ3gdZpfw==} + '@chromatic-com/storybook@1.6.0': + resolution: {integrity: sha512-6sHj0l194KMBIZ0D5SeJ+Ys+zslehKHcC2d6Hd/YEn4cCl7p9mLuxrZjvf8xharGKy8vf9Q1tKrU2YdldzUBoQ==} + engines: {node: '>=16.0.0', yarn: '>=1.22.18'} + '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -5720,6 +5788,9 @@ packages: react-dom: optional: true + '@storybook/addon-onboarding@8.1.11': + resolution: {integrity: sha512-oU9Tfnu3PlF71SC0chcDJs/i1MnpfQlB8GTN3TrlMzHXTwKJGz8XTdk2DQ0DB+YPo44Mhg2EavBXeBw6W2EF2g==} + '@storybook/addon-outline@7.1.0': resolution: {integrity: sha512-cOcyxcc80oGOm53xFInCQW1kJjX/jcrS3VQXoVUkIXf2NmwnOTp7MbkDqjCiiE0h/Za9QIqkbsTk/DrJvl905Q==} peerDependencies: @@ -5810,6 +5881,9 @@ packages: '@storybook/channels@7.1.0': resolution: {integrity: sha512-8uzjWdVG2IK18P8n6H+olAs+jnZr+HeYs1t2xiRy4NVSLhBffB71ut5F+pcWZfdDe3gyX8Tfvy68NloTNt9POg==} + '@storybook/channels@8.1.11': + resolution: {integrity: sha512-fu5FTqo6duOqtJFa6gFzKbiSLJoia+8Tibn3xFfB6BeifWrH81hc+AZq0lTmHo5qax2G5t8ZN8JooHjMw6k2RA==} + '@storybook/cli@7.1.0': resolution: {integrity: sha512-HYHPQJ59fcHlW3tljuxtL/zN/+iJHWvS0XC9vIk/s+SzY4foy0T+OId8tmUgU0w93UznkoX6f/3y47rZ2d3ozQ==} hasBin: true @@ -5820,6 +5894,9 @@ packages: '@storybook/client-logger@7.1.0': resolution: {integrity: sha512-br5GNTxNFmDZA4ESaCMn2VJ9ZW3ejbILEGoadOJjP2ZD40luSRNtTtWjeNiA+7762OvHMYVGwG0tnqk98f5nfg==} + '@storybook/client-logger@8.1.11': + resolution: {integrity: sha512-DVMh2usz3yYmlqCLCiCKy5fT8/UR9aTh+gSqwyNFkGZrIM4otC5A8eMXajXifzotQLT5SaOEnM3WzHwmpvMIEA==} + '@storybook/codemod@7.1.0': resolution: {integrity: sha512-ZDoJo1hqHbqR1arPwmm5n2qxROfTiigYDBpQCAEjVehFgT1eF1qAjiEjG/MBD0cpgj2pJ1GZTEIs52DU8sm3OQ==} @@ -5838,6 +5915,9 @@ packages: '@storybook/core-events@7.1.0': resolution: {integrity: sha512-b0kZ5ElPZj3NPqWhGsHHuLn0riA4wJXJ5mNBOe2scd8Cw52ELQr5rVHOMROhONOgpOaZBZ+QZd/MDvJDRyxTQw==} + '@storybook/core-events@8.1.11': + resolution: {integrity: sha512-vXaNe2KEW9BGlLrg0lzmf5cJ0xt+suPjWmEODH5JqBbrdZ67X6ApA2nb6WcxDQhykesWCuFN5gp1l+JuDOBi7A==} + '@storybook/core-server@7.1.0': resolution: {integrity: sha512-CELvm5RAAvBtXVnxLpF9n6VD4HXsf+f/5KKcojMVq5zh0WSeF4lOokPAXYqmflcToVP1SNWBKtQgVPaMI6y1Nw==} @@ -5853,6 +5933,9 @@ packages: '@storybook/csf@0.1.1': resolution: {integrity: sha512-4hE3AlNVxR60Wc5KSC68ASYzUobjPqtSKyhV6G+ge0FIXU55N5nTY7dXGRZHQGDBPq+XqchMkIdlkHPRs8nTHg==} + '@storybook/csf@0.1.11': + resolution: {integrity: sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==} + '@storybook/docs-mdx@0.1.0': resolution: {integrity: sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==} @@ -5865,6 +5948,9 @@ packages: '@storybook/instrumenter@7.1.0': resolution: {integrity: sha512-vsJzxGo6IN0iS0Ro/8b2qA0x+uRLZ5JIhoN+n9fwTkHDxil/u5t7HPuNMXKkgXFKQYxVX9VlehQEu2DRz3mORQ==} + '@storybook/instrumenter@8.1.11': + resolution: {integrity: sha512-r/U9hcqnodNMHuzRt1g56mWrVsDazR85Djz64M3KOwBhrTj5d46DF4/EE80w/5zR5JOrT7p8WmjJRowiVteOCQ==} + '@storybook/manager-api@7.1.0': resolution: {integrity: sha512-a4UtzWcN/a12Kr4Z5B0KO05t3w3BtXapLRUERxiwB769ab/XJ6MmIyFY7mybKty3RZhmBWaO/oSfgrOwCeP/Gw==} peerDependencies: @@ -5900,6 +5986,9 @@ packages: '@storybook/preview-api@7.1.0': resolution: {integrity: sha512-uLVCUCQKhZDWCfl7dW8+zhbqz0X41K0/nbyFpMtS7PxAveTFFOirAq0Pqtmb7JaeAYGGxkQqCYJJDdE9ZbAlYA==} + '@storybook/preview-api@8.1.11': + resolution: {integrity: sha512-8ZChmFV56GKppCJ0hnBd/kNTfGn2gWVq1242kuet13pbJtBpvOhyq4W01e/Yo14tAPXvgz8dSnMvWLbJx4QfhQ==} + '@storybook/preview@7.1.0': resolution: {integrity: sha512-Jw5VhtxL45aw4DBGwFmGoRcqUxSaWc/OexvF8LnCZct8MIL2FKdzMwjQZfqD0GN52KqRo7yMU5V43bZcXKqP6w==} @@ -5960,6 +6049,9 @@ packages: '@storybook/telemetry@7.1.0': resolution: {integrity: sha512-Vy4MvaBzD1pu+eRLHUswd3buFYzr5eUjgpFWwXF6vNGN9WHuceVr/430sFwWRzhrqKnbu4tY8CwekqKeE1uaSg==} + '@storybook/test@8.1.11': + resolution: {integrity: sha512-k+V3HemF2/I8fkRxRqM8uH8ULrpBSAAdBOtWSHWLvHguVcb2YA4g4kKo6tXBB9256QfyDW4ZiaAj0/9TMxmJPQ==} + '@storybook/testing-library@0.2.0': resolution: {integrity: sha512-Ff6jNnrsosmDshgCf0Eb5Cz7IA34p/1Ps5N3Kp3598kfXpBSccSkQQvVFUXC3kIHw/isIXWPqntZuKqnWUz7Gw==} @@ -5972,6 +6064,9 @@ packages: '@storybook/types@7.1.0': resolution: {integrity: sha512-ify1+BypgEFefkKCqBfh9fTWnkZcEqeDvLlOxbEV82C2ozg0yPlDP9VLe1eN5XM5Biigs6ZQ6WuQysl0VlCaEw==} + '@storybook/types@8.1.11': + resolution: {integrity: sha512-k9N5iRuY2+t7lVRL6xeu6diNsxO3YI3lS4Juv3RZ2K4QsE/b3yG5ElfJB8DjHDSHwRH4ORyrU71KkOCUVfvtnw==} + '@suchipi/femver@1.0.0': resolution: {integrity: sha512-bprE8+K5V+DPX7q2e2K57ImqNBdfGHDIWaGI5xHxZoxbKOuQZn4wzPiUxOAHnsUr3w3xHrWXwN7gnG/iIuEMIg==} @@ -6219,6 +6314,10 @@ packages: '@tanstack/virtual-core@3.5.0': resolution: {integrity: sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==} + '@testing-library/dom@10.1.0': + resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==} + engines: {node: '>=18'} + '@testing-library/dom@9.3.1': resolution: {integrity: sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==} engines: {node: '>=14'} @@ -6227,6 +6326,27 @@ packages: resolution: {integrity: sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==} engines: {node: '>=8', npm: '>=6', yarn: '>=1'} + '@testing-library/jest-dom@6.4.5': + resolution: {integrity: sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + peerDependencies: + '@jest/globals': '>= 28' + '@types/bun': latest + '@types/jest': '>= 28' + jest: '>= 28' + vitest: '>= 0.32' + peerDependenciesMeta: + '@jest/globals': + optional: true + '@types/bun': + optional: true + '@types/jest': + optional: true + jest: + optional: true + vitest: + optional: true + '@testing-library/react@14.0.0': resolution: {integrity: sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==} engines: {node: '>=14'} @@ -6240,6 +6360,12 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' + '@testing-library/user-event@14.5.2': + resolution: {integrity: sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -6905,6 +7031,9 @@ packages: '@vitest/expect@0.33.0': resolution: {integrity: sha512-sVNf+Gla3mhTCxNJx+wJLDPp/WcstOe0Ksqz4Vec51MmgMth/ia0MGFEkIZmVGeTL5HtjYR4Wl/ZxBxBXZJTzQ==} + '@vitest/expect@1.6.0': + resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} + '@vitest/runner@0.33.0': resolution: {integrity: sha512-UPfACnmCB6HKRHTlcgCoBh6ppl6fDn+J/xR8dTufWiKt/74Y9bHci5CKB8tESSV82zKYtkBJo9whU3mNvfaisg==} @@ -6914,6 +7043,9 @@ packages: '@vitest/spy@0.33.0': resolution: {integrity: sha512-Kv+yZ4hnH1WdiAkPUQTpRxW8kGtH8VRTnus7ZTGovFYM1ZezJpvGtb9nPIjPnptHbsyIAxYZsEpVPYgtpjGnrg==} + '@vitest/spy@1.6.0': + resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} + '@vitest/ui@0.33.0': resolution: {integrity: sha512-7gbAjLqt30R4bodkJAutdpy4ncv+u5IKTHYTow1c2q+FOxZUC9cKOSqMUxjwaaTwLN+EnDnmXYPtg3CoahaUzQ==} peerDependencies: @@ -6922,6 +7054,9 @@ packages: '@vitest/utils@0.33.0': resolution: {integrity: sha512-pF1w22ic965sv+EN6uoePkAOTkAPWM03Ri/jXNyMIKBb/XHLDPfhLvf/Fa9g0YECevAIz56oVYXhodLvLQ/awA==} + '@vitest/utils@1.6.0': + resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} + '@volar/language-core@2.2.4': resolution: {integrity: sha512-7As47GndxGxsqqYnbreLrfB5NDUeQioPM2LJKUuB4/34c0NpEJ2byVl3c9KYdjIdiEstWZ9JLtLKNTaPWb5jtA==} @@ -7827,6 +7962,10 @@ packages: resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} engines: {node: '>=4'} + chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + engines: {node: '>=4'} + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -7863,6 +8002,9 @@ packages: check-error@1.0.2: resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} + check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + check-more-types@2.24.0: resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} engines: {node: '>= 0.8.0'} @@ -7889,6 +8031,18 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + chromatic@11.5.4: + resolution: {integrity: sha512-+J+CopeUSyGUIQJsU6X7CfvSmeVBs0j6LZ9AgF4+XTjI4pFmUiUXsTc00rH9x9W1jCppOaqDXv2kqJJXGDK3mA==} + hasBin: true + peerDependencies: + '@chromatic-com/cypress': ^0.*.* || ^1.0.0 + '@chromatic-com/playwright': ^0.*.* || ^1.0.0 + peerDependenciesMeta: + '@chromatic-com/cypress': + optional: true + '@chromatic-com/playwright': + optional: true + chrome-launcher@0.15.1: resolution: {integrity: sha512-UugC8u59/w2AyX5sHLZUHoxBAiSiunUhZa3zZwMH6zPVis0C3dDKiRWyUGIo14tTbZHGVviWxv3PQWZ7taZ4fg==} engines: {node: '>=12.13.0'} @@ -8664,6 +8818,9 @@ packages: dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + dom-converter@0.2.0: resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} @@ -9174,6 +9331,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -9358,6 +9518,10 @@ packages: filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + filesize@10.1.2: + resolution: {integrity: sha512-Dx770ai81ohflojxhU+oG+Z2QGvKdYxgEr9OSA8UVrqhwNHjfH9A8f5NKfg83fEH8ZFA5N5llJo5T3PIoZ4CRA==} + engines: {node: '>= 10.4.0'} + filesize@6.4.0: resolution: {integrity: sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ==} engines: {node: '>= 0.4.0'} @@ -9600,6 +9764,9 @@ packages: get-func-name@2.0.0: resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + get-intrinsic@1.2.1: resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} @@ -11009,6 +11176,9 @@ packages: loupe@2.3.6: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + lower-case-first@2.0.2: resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==} @@ -12499,6 +12669,12 @@ packages: react: '>=16.8.0' react-dom: '>=16.8.0' + react-confetti@6.1.0: + resolution: {integrity: sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==} + engines: {node: '>=10.18'} + peerDependencies: + react: ^16.3.0 || ^17.0.1 || ^18.0.0 + react-docgen-typescript@2.2.2: resolution: {integrity: sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==} peerDependencies: @@ -13626,6 +13802,9 @@ packages: telejson@7.1.0: resolution: {integrity: sha512-jFJO4P5gPebZAERPkJsqMAQ0IMA1Hi0AoSfxpnUaV6j6R2SZqlpkbS20U6dEUtA3RUYt2Ak/mTlkQzHH9Rv/hA==} + telejson@7.2.0: + resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==} + temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} @@ -13755,6 +13934,10 @@ packages: resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==} engines: {node: '>=14.0.0'} + tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + title-case@3.0.3: resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} @@ -13979,6 +14162,9 @@ packages: resolution: {integrity: sha512-lmPKkeRMC/3gjTVxICt93A8zAzjGjbZINdekjzivn4g/rOjpHVNuOuVANU5L4H4R1bzQr8FFvZNQeQaElOjz/Q==} hasBin: true + tween-functions@1.2.0: + resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==} + tweetnacl@0.14.5: resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} @@ -14871,6 +15057,8 @@ snapshots: '@adobe/css-tools@4.2.0': {} + '@adobe/css-tools@4.4.0': {} + '@alloc/quick-lru@5.2.0': {} '@amplitude/ampli@1.31.5': @@ -17076,6 +17264,18 @@ snapshots: human-id: 1.0.2 prettier: 2.8.8 + '@chromatic-com/storybook@1.6.0(react@18.2.0)': + dependencies: + chromatic: 11.5.4 + filesize: 10.1.2 + jsonfile: 6.1.0 + react-confetti: 6.1.0(react@18.2.0) + strip-ansi: 7.1.0 + transitivePeerDependencies: + - '@chromatic-com/cypress' + - '@chromatic-com/playwright' + - react + '@colors/colors@1.5.0': optional: true @@ -18161,6 +18361,42 @@ snapshots: - supports-color - ts-node + '@jest/core@29.7.0(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5))': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0(node-notifier@10.0.0) + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.4.2 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.8.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + optional: true + '@jest/environment@29.7.0': dependencies: '@jest/fake-timers': 29.7.0 @@ -18338,6 +18574,16 @@ snapshots: optionalDependencies: typescript: 5.3.3 + '@joshwooding/vite-plugin-react-docgen-typescript@0.2.1(typescript@5.4.5)(vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0))': + dependencies: + glob: 7.2.3 + glob-promise: 4.2.2(glob@7.2.3) + magic-string: 0.27.0 + react-docgen-typescript: 2.2.2(typescript@5.4.5) + vite: 4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0) + optionalDependencies: + typescript: 5.4.5 + '@jridgewell/gen-mapping@0.3.3': dependencies: '@jridgewell/set-array': 1.1.2 @@ -20381,6 +20627,12 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + '@storybook/addon-onboarding@8.1.11(react@18.2.0)': + dependencies: + react-confetti: 6.1.0(react@18.2.0) + transitivePeerDependencies: + - react + '@storybook/addon-outline@7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@storybook/client-logger': 7.1.0 @@ -20546,6 +20798,34 @@ snapshots: - encoding - supports-color + '@storybook/builder-vite@7.1.0(typescript@5.4.5)(vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0))': + dependencies: + '@storybook/channels': 7.1.0 + '@storybook/client-logger': 7.1.0 + '@storybook/core-common': 7.1.0 + '@storybook/csf-plugin': 7.1.0 + '@storybook/mdx2-csf': 1.1.0 + '@storybook/node-logger': 7.1.0 + '@storybook/preview': 7.1.0 + '@storybook/preview-api': 7.1.0 + '@storybook/types': 7.1.0 + '@types/find-cache-dir': 3.2.1 + browser-assert: 1.2.1 + es-module-lexer: 0.9.3 + express: 4.18.2 + find-cache-dir: 3.3.2 + fs-extra: 11.1.1 + magic-string: 0.30.1 + remark-external-links: 8.0.0 + remark-slug: 6.1.0 + rollup: 3.29.4 + vite: 4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - encoding + - supports-color + '@storybook/builder-webpack5@7.1.0(@swc/helpers@0.5.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.3.3)(webpack-cli@5.0.1(webpack@5.79.0))': dependencies: '@babel/core': 7.22.9 @@ -20620,6 +20900,14 @@ snapshots: telejson: 7.1.0 tiny-invariant: 1.3.1 + '@storybook/channels@8.1.11': + dependencies: + '@storybook/client-logger': 8.1.11 + '@storybook/core-events': 8.1.11 + '@storybook/global': 5.0.0 + telejson: 7.2.0 + tiny-invariant: 1.3.1 + '@storybook/cli@7.1.0': dependencies: '@babel/core': 7.22.9 @@ -20676,6 +20964,10 @@ snapshots: dependencies: '@storybook/global': 5.0.0 + '@storybook/client-logger@8.1.11': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/codemod@7.1.0': dependencies: '@babel/core': 7.23.9 @@ -20743,6 +21035,11 @@ snapshots: '@storybook/core-events@7.1.0': {} + '@storybook/core-events@8.1.11': + dependencies: + '@storybook/csf': 0.1.11 + ts-dedent: 2.2.0 + '@storybook/core-server@7.1.0': dependencies: '@aw-web-design/x-default-browser': 1.4.126 @@ -20829,6 +21126,10 @@ snapshots: dependencies: type-fest: 2.19.0 + '@storybook/csf@0.1.11': + dependencies: + type-fest: 2.19.0 + '@storybook/docs-mdx@0.1.0': {} '@storybook/docs-tools@7.1.0': @@ -20853,6 +21154,16 @@ snapshots: '@storybook/global': 5.0.0 '@storybook/preview-api': 7.1.0 + '@storybook/instrumenter@8.1.11': + dependencies: + '@storybook/channels': 8.1.11 + '@storybook/client-logger': 8.1.11 + '@storybook/core-events': 8.1.11 + '@storybook/global': 5.0.0 + '@storybook/preview-api': 8.1.11 + '@vitest/utils': 1.6.0 + util: 0.12.5 + '@storybook/manager-api@7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@storybook/channels': 7.1.0 @@ -20936,6 +21247,23 @@ snapshots: ts-dedent: 2.2.0 util-deprecate: 1.0.2 + '@storybook/preview-api@8.1.11': + dependencies: + '@storybook/channels': 8.1.11 + '@storybook/client-logger': 8.1.11 + '@storybook/core-events': 8.1.11 + '@storybook/csf': 0.1.11 + '@storybook/global': 5.0.0 + '@storybook/types': 8.1.11 + '@types/qs': 6.9.7 + dequal: 2.0.3 + lodash: 4.17.21 + memoizerific: 1.11.3 + qs: 6.11.2 + tiny-invariant: 1.3.1 + ts-dedent: 2.2.0 + util-deprecate: 1.0.2 + '@storybook/preview@7.1.0': {} '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.3.3)(webpack@5.79.0(@swc/core@1.3.92(@swc/helpers@0.5.5))(webpack-cli@5.0.1(webpack@5.79.0)))': @@ -20999,6 +21327,27 @@ snapshots: - typescript - vite-plugin-glimmerx + '@storybook/react-vite@7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@3.29.4)(typescript@5.4.5)(vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0))': + dependencies: + '@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1(typescript@5.4.5)(vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0)) + '@rollup/pluginutils': 5.0.2(rollup@3.29.4) + '@storybook/builder-vite': 7.1.0(typescript@5.4.5)(vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0)) + '@storybook/react': 7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5) + '@vitejs/plugin-react': 3.1.0(vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0)) + ast-types: 0.14.2 + magic-string: 0.30.1 + react: 18.2.0 + react-docgen: 6.0.0-alpha.3 + react-dom: 18.2.0(react@18.2.0) + vite: 4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0) + transitivePeerDependencies: + - '@preact/preset-vite' + - encoding + - rollup + - supports-color + - typescript + - vite-plugin-glimmerx + '@storybook/react-webpack5@7.1.0(@babel/core@7.23.9)(@swc/core@1.3.92(@swc/helpers@0.5.5))(@swc/helpers@0.5.5)(@types/webpack@5.28.1(@swc/core@1.3.92(@swc/helpers@0.5.5))(webpack-cli@5.0.1(webpack@5.79.0)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(type-fest@3.13.1)(typescript@5.3.3)(webpack-cli@5.0.1(webpack@5.79.0))(webpack-hot-middleware@2.25.4)': dependencies: '@storybook/builder-webpack5': 7.1.0(@swc/helpers@0.5.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.3.3)(webpack-cli@5.0.1(webpack@5.79.0)) @@ -21056,6 +21405,37 @@ snapshots: - encoding - supports-color + '@storybook/react@7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5)': + dependencies: + '@storybook/client-logger': 7.1.0 + '@storybook/core-client': 7.1.0 + '@storybook/docs-tools': 7.1.0 + '@storybook/global': 5.0.0 + '@storybook/preview-api': 7.1.0 + '@storybook/react-dom-shim': 7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@storybook/types': 7.1.0 + '@types/escodegen': 0.0.6 + '@types/estree': 0.0.51 + '@types/node': 16.18.38 + acorn: 7.4.1 + acorn-jsx: 5.3.2(acorn@7.4.1) + acorn-walk: 7.2.0 + escodegen: 2.1.0 + html-tags: 3.3.1 + lodash: 4.17.21 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-element-to-jsx-string: 15.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + ts-dedent: 2.2.0 + type-fest: 3.13.1 + util-deprecate: 1.0.2 + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - encoding + - supports-color + '@storybook/router@7.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@storybook/client-logger': 7.1.0 @@ -21083,6 +21463,25 @@ snapshots: - encoding - supports-color + '@storybook/test@8.1.11(@jest/globals@29.7.0)(@types/jest@29.5.3)(jest@29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)))(vitest@0.33.0(sass@1.63.6)(terser@5.31.0))': + dependencies: + '@storybook/client-logger': 8.1.11 + '@storybook/core-events': 8.1.11 + '@storybook/instrumenter': 8.1.11 + '@storybook/preview-api': 8.1.11 + '@testing-library/dom': 10.1.0 + '@testing-library/jest-dom': 6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.3)(jest@29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)))(vitest@0.33.0(sass@1.63.6)(terser@5.31.0)) + '@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0) + '@vitest/expect': 1.6.0 + '@vitest/spy': 1.6.0 + util: 0.12.5 + transitivePeerDependencies: + - '@jest/globals' + - '@types/bun' + - '@types/jest' + - jest + - vitest + '@storybook/testing-library@0.2.0': dependencies: '@testing-library/dom': 9.3.1 @@ -21105,6 +21504,12 @@ snapshots: '@types/express': 4.17.17 file-system-cache: 2.3.0 + '@storybook/types@8.1.11': + dependencies: + '@storybook/channels': 8.1.11 + '@types/express': 4.17.17 + file-system-cache: 2.3.0 + '@suchipi/femver@1.0.0': {} '@svgr/babel-plugin-add-jsx-attribute@7.0.0(@babel/core@7.22.9)': @@ -21339,6 +21744,17 @@ snapshots: '@tanstack/virtual-core@3.5.0': {} + '@testing-library/dom@10.1.0': + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/runtime': 7.23.9 + '@types/aria-query': 5.0.1 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + '@testing-library/dom@9.3.1': dependencies: '@babel/code-frame': 7.22.5 @@ -21362,6 +21778,22 @@ snapshots: lodash: 4.17.21 redent: 3.0.0 + '@testing-library/jest-dom@6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.3)(jest@29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)))(vitest@0.33.0(sass@1.63.6)(terser@5.31.0))': + dependencies: + '@adobe/css-tools': 4.4.0 + '@babel/runtime': 7.23.9 + aria-query: 5.3.0 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + optionalDependencies: + '@jest/globals': 29.7.0 + '@types/jest': 29.5.3 + jest: 29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + vitest: 0.33.0(@vitest/ui@0.33.0)(happy-dom@10.5.1)(jsdom@23.0.0)(sass@1.63.6)(terser@5.31.0) + '@testing-library/react@14.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.6 @@ -21374,6 +21806,10 @@ snapshots: dependencies: '@testing-library/dom': 9.3.1 + '@testing-library/user-event@14.5.2(@testing-library/dom@10.1.0)': + dependencies: + '@testing-library/dom': 10.1.0 + '@trysound/sax@0.2.0': {} '@tsconfig/node10@1.0.9': {} @@ -22371,6 +22807,12 @@ snapshots: '@vitest/utils': 0.33.0 chai: 4.3.7 + '@vitest/expect@1.6.0': + dependencies: + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + chai: 4.4.1 + '@vitest/runner@0.33.0': dependencies: '@vitest/utils': 0.33.0 @@ -22387,6 +22829,10 @@ snapshots: dependencies: tinyspy: 2.1.1 + '@vitest/spy@1.6.0': + dependencies: + tinyspy: 2.2.1 + '@vitest/ui@0.33.0(vitest@0.33.0)': dependencies: '@vitest/utils': 0.33.0 @@ -22404,6 +22850,13 @@ snapshots: loupe: 2.3.6 pretty-format: 29.6.1 + '@vitest/utils@1.6.0': + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + '@volar/language-core@2.2.4': dependencies: '@volar/source-map': 2.2.4 @@ -23555,6 +24008,16 @@ snapshots: pathval: 1.1.1 type-detect: 4.0.8 + chai@4.4.1: + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.3 + get-func-name: 2.0.2 + loupe: 2.3.6 + pathval: 1.1.1 + type-detect: 4.0.8 + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 @@ -23612,6 +24075,10 @@ snapshots: check-error@1.0.2: {} + check-error@1.0.3: + dependencies: + get-func-name: 2.0.2 + check-more-types@2.24.0: {} cheerio-select@2.1.0: @@ -23661,6 +24128,8 @@ snapshots: chownr@2.0.0: {} + chromatic@11.5.4: {} + chrome-launcher@0.15.1: dependencies: '@types/node': 20.4.2 @@ -24044,6 +24513,22 @@ snapshots: - supports-color - ts-node + create-jest@29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + optional: true + create-require@1.1.1: {} cron@3.1.7: @@ -24471,6 +24956,8 @@ snapshots: dom-accessibility-api@0.5.16: {} + dom-accessibility-api@0.6.3: {} + dom-converter@0.2.0: dependencies: utila: 0.4.0 @@ -25478,6 +25965,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + esutils@2.0.3: {} etag@1.8.1: {} @@ -25768,6 +26259,8 @@ snapshots: dependencies: minimatch: 5.1.6 + filesize@10.1.2: {} + filesize@6.4.0: {} fill-range@7.1.1: @@ -26066,6 +26559,8 @@ snapshots: get-func-name@2.0.0: {} + get-func-name@2.0.2: {} + get-intrinsic@1.2.1: dependencies: function-bind: 1.1.1 @@ -27127,6 +27622,26 @@ snapshots: - supports-color - ts-node + jest-cli@29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)): + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + optional: true + jest-config@29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.4.2)(typescript@5.3.3)): dependencies: '@babel/core': 7.23.9 @@ -27158,6 +27673,38 @@ snapshots: - babel-plugin-macros - supports-color + jest-config@29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)): + dependencies: + '@babel/core': 7.23.9 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.23.9) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.7 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.4.2 + ts-node: 10.9.1(@types/node@20.4.2)(typescript@5.4.5) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + optional: true + jest-diff@29.6.1: dependencies: chalk: 4.1.2 @@ -27468,6 +28015,19 @@ snapshots: - supports-color - ts-node + jest@29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)): + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@20.4.2)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + optional: true + jiti@1.19.1: {} jiti@1.21.0: {} @@ -27866,6 +28426,10 @@ snapshots: dependencies: get-func-name: 2.0.0 + loupe@2.3.7: + dependencies: + get-func-name: 2.0.2 + lower-case-first@2.0.2: dependencies: tslib: 2.6.2 @@ -28925,6 +29489,14 @@ snapshots: postcss: 8.4.31 ts-node: 10.9.1(@swc/core@1.3.92(@swc/helpers@0.5.5))(@types/node@20.4.2)(typescript@5.3.3) + postcss-load-config@4.0.1(postcss@8.4.31)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)): + dependencies: + lilconfig: 2.1.0 + yaml: 2.3.1 + optionalDependencies: + postcss: 8.4.31 + ts-node: 10.9.1(@types/node@20.4.2)(typescript@5.4.5) + postcss-loader@7.3.3(postcss@8.4.31)(webpack@5.79.0(@swc/core@1.3.92(@swc/helpers@0.5.5))(webpack-cli@5.0.1(webpack@5.79.0))): dependencies: cosmiconfig: 8.2.0 @@ -29299,10 +29871,19 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + react-confetti@6.1.0(react@18.2.0): + dependencies: + react: 18.2.0 + tween-functions: 1.2.0 + react-docgen-typescript@2.2.2(typescript@5.3.3): dependencies: typescript: 5.3.3 + react-docgen-typescript@2.2.2(typescript@5.4.5): + dependencies: + typescript: 5.4.5 + react-docgen@5.4.3: dependencies: '@babel/core': 7.23.9 @@ -30582,6 +31163,33 @@ snapshots: transitivePeerDependencies: - ts-node + tailwindcss@3.3.3(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)): + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.0 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.19.1 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.31 + postcss-import: 15.1.0(postcss@8.4.31) + postcss-js: 4.0.1(postcss@8.4.31) + postcss-load-config: 4.0.1(postcss@8.4.31)(ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5)) + postcss-nested: 6.0.1(postcss@8.4.31) + postcss-selector-parser: 6.0.13 + resolve: 1.22.2 + sucrase: 3.33.0 + transitivePeerDependencies: + - ts-node + tapable@2.2.1: {} tar-fs@2.1.1: @@ -30612,6 +31220,10 @@ snapshots: dependencies: memoizerific: 1.11.3 + telejson@7.2.0: + dependencies: + memoizerific: 1.11.3 + temp-dir@2.0.0: {} temp@0.8.4: @@ -30725,6 +31337,8 @@ snapshots: tinyspy@2.1.1: {} + tinyspy@2.2.1: {} + title-case@3.0.3: dependencies: tslib: 2.6.2 @@ -30883,12 +31497,35 @@ snapshots: optionalDependencies: '@swc/core': 1.3.92(@swc/helpers@0.5.5) + ts-node@10.9.1(@types/node@20.4.2)(typescript@5.4.5): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.3 + '@types/node': 20.4.2 + acorn: 8.8.2 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.4.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optional: true + ts-retry-promise@0.7.0: {} tsconfck@2.1.1(typescript@5.3.3): optionalDependencies: typescript: 5.3.3 + tsconfck@2.1.1(typescript@5.4.5): + optionalDependencies: + typescript: 5.4.5 + tsconfig-paths-webpack-plugin@4.1.0: dependencies: chalk: 4.1.2 @@ -30965,6 +31602,8 @@ snapshots: turbo-windows-64: 1.10.8 turbo-windows-arm64: 1.10.8 + tween-functions@1.2.0: {} + tweetnacl@0.14.5: {} tweetnacl@1.0.3: {} @@ -31246,8 +31885,8 @@ snapshots: inherits: 2.0.4 is-arguments: 1.1.1 is-generator-function: 1.0.10 - is-typed-array: 1.1.10 - which-typed-array: 1.1.10 + is-typed-array: 1.1.13 + which-typed-array: 1.1.15 utila@0.4.0: {} @@ -31354,6 +31993,17 @@ snapshots: - supports-color - typescript + vite-tsconfig-paths@4.2.0(typescript@5.4.5)(vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0)): + dependencies: + debug: 4.3.4(supports-color@8.1.1) + globrex: 0.1.2 + tsconfck: 2.1.1(typescript@5.4.5) + optionalDependencies: + vite: 4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0) + transitivePeerDependencies: + - supports-color + - typescript + vite@4.4.11(@types/node@20.4.2)(sass@1.63.6)(terser@5.31.0): dependencies: esbuild: 0.18.14