From d03bb8cdd09fb245ae474051fb1d10272660cf6e Mon Sep 17 00:00:00 2001
From: Gabe Rodriguez <grod220@gmail.com>
Date: Tue, 30 Apr 2024 14:04:46 +0200
Subject: [PATCH] Connect wallet button [interchain UI part 2] (#1014)

* Add ibc in slice

* Connect wallet

* Update dropdown

* cleanup
---
 apps/minifront/package.json                   |  15 +-
 .../components/ibc/ibc-in/chain-dropdown.tsx  | 165 +++----
 .../components/ibc/ibc-in/chain-picker.tsx    |  13 -
 .../components/ibc/ibc-in/chain-provider.tsx  |   1 +
 .../ibc/ibc-in/cosmos-wallet-connector.tsx    |  30 ++
 .../src/components/ibc/ibc-in/ibc-in-form.tsx |   2 +-
 .../components/ibc/ibc-in/interchain-ui.tsx   |   9 +-
 .../ibc/ibc-in/wallet-addr-card.tsx           |  16 +
 .../ibc/ibc-in/wallet-connect-button.tsx      |  69 +++
 .../src/components/ibc/ibc-loader.ts          |   6 +-
 .../components/ibc/ibc-out/chain-selector.tsx |   4 +-
 .../components/ibc/ibc-out/ibc-out-form.tsx   |   8 +-
 apps/minifront/src/components/ibc/layout.tsx  |   6 +-
 apps/minifront/src/state/ibc-in.ts            |  20 +
 .../state/{ibc.test.ts => ibc-out.test.ts}    |  16 +-
 .../src/state/{ibc.ts => ibc-out.ts}          |  30 +-
 apps/minifront/src/state/index.ts             |   9 +-
 packages/ui/components/ui/avatar.tsx          |  46 ++
 packages/ui/components/ui/command.tsx         | 145 ++++++
 packages/ui/components/ui/popover.tsx         |   4 +-
 packages/ui/package.json                      |   2 +
 pnpm-lock.yaml                                | 433 ++++++++++++++----
 22 files changed, 807 insertions(+), 242 deletions(-)
 delete mode 100644 apps/minifront/src/components/ibc/ibc-in/chain-picker.tsx
 create mode 100644 apps/minifront/src/components/ibc/ibc-in/cosmos-wallet-connector.tsx
 create mode 100644 apps/minifront/src/components/ibc/ibc-in/wallet-addr-card.tsx
 create mode 100644 apps/minifront/src/components/ibc/ibc-in/wallet-connect-button.tsx
 create mode 100644 apps/minifront/src/state/ibc-in.ts
 rename apps/minifront/src/state/{ibc.test.ts => ibc-out.test.ts} (89%)
 rename apps/minifront/src/state/{ibc.ts => ibc-out.ts} (90%)
 create mode 100644 packages/ui/components/ui/avatar.tsx
 create mode 100644 packages/ui/components/ui/command.tsx

diff --git a/apps/minifront/package.json b/apps/minifront/package.json
index 65a4042e53..c030db0eb0 100644
--- a/apps/minifront/package.json
+++ b/apps/minifront/package.json
@@ -20,8 +20,9 @@
     "@bufbuild/protobuf": "^1.9.0",
     "@cosmjs/proto-signing": "^0.32.3",
     "@cosmjs/stargate": "^0.32.3",
-    "@cosmos-kit/react": "^2.11.0",
-    "@interchain-ui/react": "^1.23.3",
+    "@cosmos-kit/core": "^2.9.2",
+    "@cosmos-kit/react": "^2.11.2",
+    "@interchain-ui/react": "^1.23.10",
     "@penumbra-labs/registry": "^5.1.0",
     "@penumbra-zone/bech32m": "workspace:*",
     "@penumbra-zone/client": "workspace:*",
@@ -36,14 +37,14 @@
     "@tanstack/react-query": "^5.28.9",
     "bech32": "^2.0.0",
     "bignumber.js": "^9.1.2",
-    "chain-registry": "^1.41.9",
-    "cosmos-kit": "^2.10.0",
+    "chain-registry": "^1.45.5",
+    "cosmos-kit": "^2.10.2",
     "date-fns": "^3.6.0",
     "framer-motion": "^11.0.22",
     "immer": "^10.0.4",
     "lodash": "^4.17.21",
-    "match-sorter": "^6.3.4",
-    "osmo-query": "^16.11.0",
+    "lucide-react": "^0.363.0",
+    "osmo-query": "^16.12.0",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
     "react-helmet": "^6.1.0",
@@ -55,7 +56,7 @@
     "zustand": "^4.5.2"
   },
   "devDependencies": {
-    "@chain-registry/types": "^0.25.7",
+    "@chain-registry/types": "^0.28.4",
     "@penumbra-zone/polyfills": "workspace:*",
     "@testing-library/jest-dom": "^6.4.2",
     "@testing-library/react": "^14.2.2",
diff --git a/apps/minifront/src/components/ibc/ibc-in/chain-dropdown.tsx b/apps/minifront/src/components/ibc/ibc-in/chain-dropdown.tsx
index 62bff84454..8d20ef047c 100644
--- a/apps/minifront/src/components/ibc/ibc-in/chain-dropdown.tsx
+++ b/apps/minifront/src/components/ibc/ibc-in/chain-dropdown.tsx
@@ -1,13 +1,20 @@
 import * as React from 'react';
 import { useMemo } from 'react';
-import { Avatar, Box, Combobox, Skeleton, Stack, Text } from '@interchain-ui/react';
-import { matchSorter } from 'match-sorter';
 import { useManager } from '@cosmos-kit/react';
-
-interface Option {
-  label: string;
-  value: string;
-}
+import { Popover, PopoverContent, PopoverTrigger } from '@penumbra-zone/ui/components/ui/popover';
+import { ChevronsUpDown } from 'lucide-react';
+import {
+  Command,
+  CommandEmpty,
+  CommandGroup,
+  CommandInput,
+  CommandItem,
+} from '@penumbra-zone/ui/components/ui/command';
+import { Button } from '@penumbra-zone/ui/components/ui/button';
+import { ibcInSelector } from '../../../state/ibc-in';
+import { useStore } from '../../../state';
+import { Avatar, AvatarImage } from '@penumbra-zone/ui/components/ui/avatar';
+import { Identicon } from '@penumbra-zone/ui/components/ui/identicon';
 
 export interface ChainInfo {
   chainName: string;
@@ -16,26 +23,6 @@ export interface ChainInfo {
   icon?: string;
 }
 
-export interface ChooseChainProps {
-  onChange: (selectedItem: Option) => void;
-}
-
-const ChainOption = ({ chainInfo: { label, icon } }: { chainInfo: ChainInfo }) => {
-  return (
-    <Stack aria-label={`Chain option: ${label}`}>
-      <Avatar
-        name={label}
-        className='mr-2'
-        getInitials={name => name[0]!}
-        size='xs'
-        src={icon}
-        fallbackMode='bg'
-      />
-      <Text>{label}</Text>
-    </Stack>
-  );
-};
-
 const useChainInfos = (): ChainInfo[] => {
   const { chainRecords, getChainLogo } = useManager();
   return useMemo(
@@ -54,80 +41,66 @@ const useChainInfos = (): ChainInfo[] => {
 
 // Note the console will display aria-label warnings (despite them being present).
 // The cosmology team has been notified of the issue.
-export const ChainDropdown = ({ onChange }: ChooseChainProps) => {
+export const ChainDropdown = () => {
   const chainInfos = useChainInfos();
+  const { setSelectedChain } = useStore(ibcInSelector);
 
-  const [selectedKey, setSelectedKey] = React.useState<string>();
-  const [filterValue, setFilterValue] = React.useState<string>('');
-
-  const filteredItems = React.useMemo(() => {
-    return matchSorter(chainInfos, filterValue, {
-      keys: ['label', 'value'],
-    });
-  }, [chainInfos, filterValue]);
+  const [open, setOpen] = React.useState(false);
+  const [value, setValue] = React.useState('');
 
-  const avatarUrl = filteredItems.find(i => i.value === selectedKey)?.icon ?? undefined;
+  const selected = chainInfos.find(c => c.value === value);
 
   return (
-    <Box className='flex flex-col items-center justify-center'>
-      <div className='font-bold text-stone-700'>Select chain</div>
-      <Combobox
-        aria-label='Select a chain'
-        items={filteredItems}
-        inputValue={filterValue}
-        openOnFocus
-        onInputChange={value => {
-          setFilterValue(value);
-          if (!value) {
-            setSelectedKey(undefined);
-          }
-        }}
-        selectedKey={selectedKey}
-        onSelectionChange={item => {
-          if (item) {
-            setSelectedKey(item as string);
-
-            const found = chainInfos.find(options => options.value === item) ?? null;
-
-            if (found) {
-              onChange(found);
-              setFilterValue(found.label);
-            }
-          }
-        }}
-        inputAddonStart={
-          selectedKey && avatarUrl ? (
-            <Avatar
-              name={selectedKey.toString()}
-              getInitials={name => name[0]!}
-              size='xs'
-              src={avatarUrl}
-              fallbackMode='bg'
-              className='px-2'
-            />
+    <Popover open={open} onOpenChange={setOpen}>
+      <PopoverTrigger asChild>
+        <Button variant='onLight' role='combobox' aria-expanded={open} className='w-[300px]'>
+          {value ? (
+            <div className='flex gap-2'>
+              <Avatar className='size-6'>
+                <AvatarImage src={selected?.icon} />
+                <Identicon uniqueIdentifier={selected?.label ?? ''} type='gradient' size={22} />
+              </Avatar>
+              <span className='mt-0.5'>{selected?.label}</span>
+            </div>
           ) : (
-            <Box className='flex items-center justify-center px-2'>
-              <Skeleton width='24px' height='24px' className='rounded-full' />
-            </Box>
-          )
-        }
-        styleProps={{
-          width: {
-            mobile: '100%',
-            mdMobile: '350px',
-          },
-        }}
-      >
-        {filteredItems.map(info => (
-          <Combobox.Item
-            key={info.value}
-            textValue={info.label}
-            aria-label={`Select ${info.label}`}
-          >
-            <ChainOption chainInfo={info} />
-          </Combobox.Item>
-        ))}
-      </Combobox>
-    </Box>
+            'Select a chain'
+          )}
+          <ChevronsUpDown className='ml-2 size-4 shrink-0 opacity-50' />
+        </Button>
+      </PopoverTrigger>
+      <PopoverContent className='w-[300px] p-0'>
+        <Command>
+          <CommandInput placeholder='Search chains...' />
+          <CommandEmpty>No framework found.</CommandEmpty>
+          <CommandGroup>
+            {chainInfos.map(chain => (
+              <CommandItem
+                key={chain.value}
+                value={chain.value}
+                onSelect={currentValue => {
+                  setOpen(false);
+
+                  if (currentValue === value) {
+                    setValue('');
+                    setSelectedChain(undefined);
+                  } else {
+                    setValue(currentValue);
+                    const match = chainInfos.find(options => options.value === currentValue);
+                    setSelectedChain(match);
+                  }
+                }}
+                className='flex gap-2'
+              >
+                <Avatar className='size-6'>
+                  <AvatarImage src={chain.icon} />
+                  <Identicon uniqueIdentifier={chain.label} type='gradient' size={22} />
+                </Avatar>
+                {chain.label}
+              </CommandItem>
+            ))}
+          </CommandGroup>
+        </Command>
+      </PopoverContent>
+    </Popover>
   );
 };
diff --git a/apps/minifront/src/components/ibc/ibc-in/chain-picker.tsx b/apps/minifront/src/components/ibc/ibc-in/chain-picker.tsx
deleted file mode 100644
index 5740f06e8f..0000000000
--- a/apps/minifront/src/components/ibc/ibc-in/chain-picker.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { useEffect, useState } from 'react';
-import { ChainName } from 'cosmos-kit';
-import { ChainDropdown } from './chain-dropdown';
-
-export const ChainPicker = () => {
-  // Temp until slices are setup
-  const [chainName, setChainName] = useState<ChainName>();
-  useEffect(() => {
-    console.log(`You chose: ${chainName}`);
-  }, [chainName]);
-
-  return <ChainDropdown onChange={e => setChainName(e.value)} />;
-};
diff --git a/apps/minifront/src/components/ibc/ibc-in/chain-provider.tsx b/apps/minifront/src/components/ibc/ibc-in/chain-provider.tsx
index 919da2ee4d..244a8e3af5 100644
--- a/apps/minifront/src/components/ibc/ibc-in/chain-provider.tsx
+++ b/apps/minifront/src/components/ibc/ibc-in/chain-provider.tsx
@@ -55,6 +55,7 @@ export const IbcChainProvider = ({ registry, children }: IbcProviderProps) => {
         },
       }}
       signerOptions={signerOptions}
+      modalTheme={{ defaultTheme: 'light' }}
     >
       {children}
     </ChainProvider>
diff --git a/apps/minifront/src/components/ibc/ibc-in/cosmos-wallet-connector.tsx b/apps/minifront/src/components/ibc/ibc-in/cosmos-wallet-connector.tsx
new file mode 100644
index 0000000000..810e67de36
--- /dev/null
+++ b/apps/minifront/src/components/ibc/ibc-in/cosmos-wallet-connector.tsx
@@ -0,0 +1,30 @@
+import { useStore } from '../../../state';
+import { ibcInSelector } from '../../../state/ibc-in';
+import { useChain, useManager } from '@cosmos-kit/react';
+import { WalletStatus } from '@cosmos-kit/core';
+import { WalletAddrCard } from './wallet-addr-card';
+import { ConnectWalletButton } from './wallet-connect-button';
+
+export const useChainConnector = () => {
+  const { selectedChain } = useStore(ibcInSelector);
+  const { chainRecords } = useManager();
+  const defaultChain = chainRecords[0]!.name;
+  return useChain(selectedChain?.chainName ?? defaultChain);
+};
+
+export const CosmosWalletConnector = () => {
+  const { selectedChain } = useStore(ibcInSelector);
+  const { username, address, status, message } = useChainConnector();
+
+  return (
+    <div className='flex flex-col items-center justify-center gap-4'>
+      {address && selectedChain && <WalletAddrCard username={username} address={address} />}
+      <div className='w-52'>
+        <ConnectWalletButton />
+      </div>
+      {(status === WalletStatus.Rejected || status === WalletStatus.Error) && (
+        <div className='text-purple-500'>{message}</div>
+      )}
+    </div>
+  );
+};
diff --git a/apps/minifront/src/components/ibc/ibc-in/ibc-in-form.tsx b/apps/minifront/src/components/ibc/ibc-in/ibc-in-form.tsx
index 40958dc8f9..7a185f9f08 100644
--- a/apps/minifront/src/components/ibc/ibc-in/ibc-in-form.tsx
+++ b/apps/minifront/src/components/ibc/ibc-in/ibc-in-form.tsx
@@ -11,7 +11,7 @@ export const IbcInForm = () => {
       }}
     >
       <InterchainUi />
-      <Button type='submit' variant='onLight'>
+      <Button type='submit' variant='onLight' disabled>
         <div className='flex items-center gap-2'>
           <LockClosedIcon />
           <span className='-mb-1'>Shield Assets</span>
diff --git a/apps/minifront/src/components/ibc/ibc-in/interchain-ui.tsx b/apps/minifront/src/components/ibc/ibc-in/interchain-ui.tsx
index 65e3f8a607..97a21dbce5 100644
--- a/apps/minifront/src/components/ibc/ibc-in/interchain-ui.tsx
+++ b/apps/minifront/src/components/ibc/ibc-in/interchain-ui.tsx
@@ -1,6 +1,7 @@
 import { IbcChainProvider } from './chain-provider';
 import { useRegistry } from '../../../fetchers/registry';
-import { ChainPicker } from './chain-picker';
+import { ChainDropdown } from './chain-dropdown';
+import { CosmosWalletConnector } from './cosmos-wallet-connector';
 
 export const InterchainUi = () => {
   const { data, isLoading, error } = useRegistry();
@@ -12,10 +13,10 @@ export const InterchainUi = () => {
   return (
     <IbcChainProvider registry={data}>
       {/* negative margin offsets div inserted by provider */}
-      <div className='-mt-4'>
-        <ChainPicker />
+      <div className='-mt-4 flex justify-center'>
+        <ChainDropdown />
       </div>
-      {/* WalletSection to go here */}
+      <CosmosWalletConnector />
     </IbcChainProvider>
   );
 };
diff --git a/apps/minifront/src/components/ibc/ibc-in/wallet-addr-card.tsx b/apps/minifront/src/components/ibc/ibc-in/wallet-addr-card.tsx
new file mode 100644
index 0000000000..3c34414c6e
--- /dev/null
+++ b/apps/minifront/src/components/ibc/ibc-in/wallet-addr-card.tsx
@@ -0,0 +1,16 @@
+import { Identicon } from '@penumbra-zone/ui/components/ui/identicon';
+
+interface UserInfoProps {
+  address: string;
+  username?: string;
+}
+
+export const WalletAddrCard = ({ address, username }: UserInfoProps) => {
+  return (
+    <div className='flex flex-col items-center gap-2 space-y-1 rounded-lg bg-white p-6'>
+      <Identicon uniqueIdentifier={address} type='gradient' size={42} />
+      <div className='flex items-center justify-center gap-4 text-gray-500'>{address}</div>
+      <span className='text-sm font-semibold text-stone-700 sm:text-xl'>{username}</span>
+    </div>
+  );
+};
diff --git a/apps/minifront/src/components/ibc/ibc-in/wallet-connect-button.tsx b/apps/minifront/src/components/ibc/ibc-in/wallet-connect-button.tsx
new file mode 100644
index 0000000000..a4e51d4855
--- /dev/null
+++ b/apps/minifront/src/components/ibc/ibc-in/wallet-connect-button.tsx
@@ -0,0 +1,69 @@
+import { Button } from '@interchain-ui/react';
+import { WalletStatus } from 'cosmos-kit';
+import { WalletIcon } from '@penumbra-zone/ui/components/ui/icons/wallet';
+import { MouseEventHandler } from 'react';
+import { useStore } from '../../../state';
+import { ibcInSelector } from '../../../state/ibc-in';
+import { useChainConnector } from './cosmos-wallet-connector';
+
+export const ConnectWalletButton = () => {
+  const { connect, openView, status } = useChainConnector();
+  const { selectedChain } = useStore(ibcInSelector);
+
+  if (!selectedChain) {
+    return <WalletButtonBase buttonText='Connect Wallet' isDisabled={true} />;
+  }
+
+  const onClickConnect: MouseEventHandler = e => {
+    e.preventDefault();
+    void connect();
+  };
+
+  const onClickOpenView: MouseEventHandler = e => {
+    e.preventDefault();
+    openView();
+  };
+
+  switch (status) {
+    case WalletStatus.Disconnected:
+      return <WalletButtonBase buttonText='Connect Wallet' onClick={onClickConnect} />;
+    case WalletStatus.Connecting:
+      return <WalletButtonBase isLoading={true} />;
+    case WalletStatus.Connected:
+      return <WalletButtonBase buttonText='My Wallet' onClick={onClickOpenView} />;
+    case WalletStatus.Rejected:
+      return <WalletButtonBase buttonText='Reconnect' onClick={onClickConnect} />;
+    case WalletStatus.Error:
+      return <WalletButtonBase buttonText='Change Wallet' onClick={onClickOpenView} />;
+    case WalletStatus.NotExist:
+      return <WalletButtonBase buttonText='Install Wallet' onClick={onClickOpenView} />;
+    default:
+      return <WalletButtonBase buttonText='Connect Wallet' onClick={onClickConnect} />;
+  }
+};
+
+interface BaseProps {
+  buttonText?: string;
+  isLoading?: boolean;
+  isDisabled?: boolean;
+  onClick?: MouseEventHandler<HTMLButtonElement>;
+}
+
+const WalletButtonBase = ({ buttonText, isLoading, isDisabled, onClick }: BaseProps) => {
+  return (
+    <Button
+      fluidWidth
+      size='md'
+      isLoading={isLoading}
+      disabled={isDisabled}
+      onClick={onClick}
+      className='relative'
+    >
+      <div className='absolute inset-0 z-0 -m-px rounded-lg bg-gradient-to-r from-[rgba(157,75,199,1)] via-[rgba(138,78,201.5,1)] to-[rgba(119,81,204,1)]'></div>
+      <div className='relative z-10 flex items-center justify-center gap-1 rounded p-2'>
+        <WalletIcon />
+        <span className='font-bold'>{buttonText ? buttonText : 'Connect Wallet'}</span>
+      </div>
+    </Button>
+  );
+};
diff --git a/apps/minifront/src/components/ibc/ibc-loader.ts b/apps/minifront/src/components/ibc/ibc-loader.ts
index c98409ff0a..f220273bac 100644
--- a/apps/minifront/src/components/ibc/ibc-loader.ts
+++ b/apps/minifront/src/components/ibc/ibc-loader.ts
@@ -2,11 +2,11 @@ import { LoaderFunction } from 'react-router-dom';
 import { BalancesResponse } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb';
 import { getBalances } from '../../fetchers/balances';
 import { useStore } from '../../state';
-import { filterBalancesPerChain } from '../../state/ibc';
 import { Chain } from '@penumbra-labs/registry';
 import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
 import { getIbcConnections, getStakingTokenMetadata } from '../../fetchers/registry';
 import { getAllAssets } from '../../fetchers/assets';
+import { filterBalancesPerChain } from '../../state/ibc-out';
 
 export interface IbcLoaderResponse {
   balances: BalancesResponse[];
@@ -32,8 +32,8 @@ export const IbcLoader: LoaderFunction = async (): Promise<IbcLoaderResponse> =>
 
     // set initial account if accounts exist and asset if account has asset list
     useStore.setState(state => {
-      state.ibc.selection = initialSelection;
-      state.ibc.chain = initialChain;
+      state.ibcOut.selection = initialSelection;
+      state.ibcOut.chain = initialChain;
     });
   }
 
diff --git a/apps/minifront/src/components/ibc/ibc-out/chain-selector.tsx b/apps/minifront/src/components/ibc/ibc-out/chain-selector.tsx
index ba7f461a33..ef137ab3e7 100644
--- a/apps/minifront/src/components/ibc/ibc-out/chain-selector.tsx
+++ b/apps/minifront/src/components/ibc/ibc-out/chain-selector.tsx
@@ -8,13 +8,13 @@ import {
 import { cn } from '@penumbra-zone/ui/lib/utils';
 import { useState } from 'react';
 import { useStore } from '../../../state';
-import { ibcSelector } from '../../../state/ibc';
+import { ibcOutSelector } from '../../../state/ibc-out';
 import { useLoaderData } from 'react-router-dom';
 import { IbcLoaderResponse } from '../ibc-loader';
 import { Chain } from '@penumbra-labs/registry';
 
 export const ChainSelector = () => {
-  const { chain, setChain } = useStore(ibcSelector);
+  const { chain, setChain } = useStore(ibcOutSelector);
   const { chains: ibcConnections } = useLoaderData() as IbcLoaderResponse;
   const [openSelect, setOpenSelect] = useState(false);
 
diff --git a/apps/minifront/src/components/ibc/ibc-out/ibc-out-form.tsx b/apps/minifront/src/components/ibc/ibc-out/ibc-out-form.tsx
index c519218736..96dc542b5d 100644
--- a/apps/minifront/src/components/ibc/ibc-out/ibc-out-form.tsx
+++ b/apps/minifront/src/components/ibc/ibc-out/ibc-out-form.tsx
@@ -3,7 +3,11 @@ import { Input } from '@penumbra-zone/ui/components/ui/input';
 import { ChainSelector } from './chain-selector';
 import { useLoaderData } from 'react-router-dom';
 import { useStore } from '../../../state';
-import { filterBalancesPerChain, ibcSelector, ibcValidationErrors } from '../../../state/ibc';
+import {
+  filterBalancesPerChain,
+  ibcOutSelector,
+  ibcValidationErrors,
+} from '../../../state/ibc-out';
 import InputToken from '../../shared/input-token';
 import { InputBlock } from '../../shared/input-block';
 import { IbcLoaderResponse } from '../ibc-loader';
@@ -20,7 +24,7 @@ export const IbcOutForm = () => {
     selection,
     setSelection,
     chain,
-  } = useStore(ibcSelector);
+  } = useStore(ibcOutSelector);
   const filteredBalances = filterBalancesPerChain(balances, chain, stakingTokenMetadata, assets);
   const validationErrors = useStore(ibcValidationErrors);
 
diff --git a/apps/minifront/src/components/ibc/layout.tsx b/apps/minifront/src/components/ibc/layout.tsx
index a97afc40c8..1e7bbdcd50 100644
--- a/apps/minifront/src/components/ibc/layout.tsx
+++ b/apps/minifront/src/components/ibc/layout.tsx
@@ -8,12 +8,12 @@ export const IbcLayout = () => {
     <>
       <div className="fixed inset-0 z-[-100] size-full bg-[url('penumbra-logo.svg')] bg-[length:160vmax] bg-fixed bg-[top_50%_left_25vw] bg-no-repeat" />
       <div className='flex flex-1 flex-col gap-4 md:flex-row md:place-content-around'>
-        <Card light className='relative overflow-visible md:self-start'>
+        <Card light className='relative z-10 overflow-visible md:self-start'>
           <LongArrowIcon
             direction='right'
             // Negative calculated margin giving lint issue
             /* eslint-disable-next-line tailwindcss/enforces-negative-arbitrary-values */
-            className='invisible absolute inset-y-0 right-0 my-auto -mr-[calc(30vw-3px)] size-[30vw] text-stone-300 md:visible'
+            className='invisible absolute -top-44 right-0 z-0 -mr-[calc(30vw-3px)] size-[30vw] text-stone-300 md:visible'
           />
           <IbcInForm />
         </Card>
@@ -22,7 +22,7 @@ export const IbcLayout = () => {
             direction='left'
             // Negative calculated margin giving lint issue
             /* eslint-disable-next-line tailwindcss/enforces-negative-arbitrary-values */
-            className='invisible absolute inset-y-0 left-0 my-auto -ml-[calc(30vw-3px)] size-[30vw] text-stone-700 md:visible'
+            className='invisible absolute -bottom-44 left-0 z-0 my-auto -ml-[calc(30vw-3px)] size-[30vw] text-stone-700 md:visible'
           />
           <IbcOutForm />
         </Card>
diff --git a/apps/minifront/src/state/ibc-in.ts b/apps/minifront/src/state/ibc-in.ts
new file mode 100644
index 0000000000..91f3113f50
--- /dev/null
+++ b/apps/minifront/src/state/ibc-in.ts
@@ -0,0 +1,20 @@
+import { AllSlices, SliceCreator } from '.';
+import { ChainInfo } from '../components/ibc/ibc-in/chain-dropdown';
+
+export interface IbcInSlice {
+  selectedChain?: ChainInfo;
+  setSelectedChain: (chain?: ChainInfo) => void;
+}
+
+export const createIbcInSlice = (): SliceCreator<IbcInSlice> => set => {
+  return {
+    selectedChain: undefined,
+    setSelectedChain: chain => {
+      set(state => {
+        state.ibcIn.selectedChain = chain;
+      });
+    },
+  };
+};
+
+export const ibcInSelector = (state: AllSlices) => state.ibcIn;
diff --git a/apps/minifront/src/state/ibc.test.ts b/apps/minifront/src/state/ibc-out.test.ts
similarity index 89%
rename from apps/minifront/src/state/ibc.test.ts
rename to apps/minifront/src/state/ibc-out.test.ts
index 78050c89ab..f9bfdf31eb 100644
--- a/apps/minifront/src/state/ibc.test.ts
+++ b/apps/minifront/src/state/ibc-out.test.ts
@@ -12,7 +12,7 @@ import { produce } from 'immer';
 import { BalancesResponse } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb';
 import { addressFromBech32m } from '@penumbra-zone/bech32m/penumbra';
 import { Chain } from '@penumbra-labs/registry';
-import { currentTimePlusTwoDaysRounded } from './ibc';
+import { currentTimePlusTwoDaysRounded } from './ibc-out';
 
 describe.skip('IBC Slice', () => {
   const selectionExample = new BalancesResponse({
@@ -47,15 +47,15 @@ describe.skip('IBC Slice', () => {
   });
 
   test('the default is empty, false or undefined', () => {
-    expect(useStore.getState().ibc.amount).toBe('');
-    expect(useStore.getState().ibc.selection).toBeUndefined();
-    expect(useStore.getState().ibc.chain).toBeUndefined();
+    expect(useStore.getState().ibcOut.amount).toBe('');
+    expect(useStore.getState().ibcOut.selection).toBeUndefined();
+    expect(useStore.getState().ibcOut.chain).toBeUndefined();
   });
 
   describe('setAmount', () => {
     test('amount can be set', () => {
-      useStore.getState().ibc.setAmount('2');
-      expect(useStore.getState().ibc.amount).toBe('2');
+      useStore.getState().ibcOut.setAmount('2');
+      expect(useStore.getState().ibcOut.amount).toBe('2');
     });
 
     test('validate high enough amount validates', () => {
@@ -94,8 +94,8 @@ describe.skip('IBC Slice', () => {
         addressPrefix: 'osmo',
       } satisfies Chain;
 
-      useStore.getState().ibc.setChain(chain);
-      expect(useStore.getState().ibc.chain).toBe(chain);
+      useStore.getState().ibcOut.setChain(chain);
+      expect(useStore.getState().ibcOut.chain).toBe(chain);
     });
   });
 
diff --git a/apps/minifront/src/state/ibc.ts b/apps/minifront/src/state/ibc-out.ts
similarity index 90%
rename from apps/minifront/src/state/ibc.ts
rename to apps/minifront/src/state/ibc-out.ts
index fa003f351f..950a6421c2 100644
--- a/apps/minifront/src/state/ibc.ts
+++ b/apps/minifront/src/state/ibc-out.ts
@@ -22,7 +22,7 @@ import { errorToast } from '@penumbra-zone/ui/lib/toast/presets';
 import { Chain } from '@penumbra-labs/registry';
 import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
 
-export interface IbcSendSlice {
+export interface IbcOutSlice {
   selection: BalancesResponse | undefined;
   setSelection: (selection: BalancesResponse) => void;
   amount: string;
@@ -35,7 +35,7 @@ export interface IbcSendSlice {
   txInProgress: boolean;
 }
 
-export const createIbcSendSlice = (): SliceCreator<IbcSendSlice> => (set, get) => {
+export const createIbcOutSlice = (): SliceCreator<IbcOutSlice> => (set, get) => {
   return {
     amount: '',
     selection: undefined,
@@ -44,22 +44,22 @@ export const createIbcSendSlice = (): SliceCreator<IbcSendSlice> => (set, get) =
     txInProgress: false,
     setSelection: selection => {
       set(state => {
-        state.ibc.selection = selection;
+        state.ibcOut.selection = selection;
       });
     },
     setAmount: amount => {
       set(state => {
-        state.ibc.amount = amount;
+        state.ibcOut.amount = amount;
       });
     },
     setChain: chain => {
       set(state => {
-        state.ibc.chain = chain;
+        state.ibcOut.chain = chain;
       });
     },
     setDestinationChainAddress: addr => {
       set(state => {
-        state.ibc.destinationChainAddress = addr;
+        state.ibcOut.destinationChainAddress = addr;
       });
     },
     sendIbcWithdraw: async () => {
@@ -68,18 +68,18 @@ export const createIbcSendSlice = (): SliceCreator<IbcSendSlice> => (set, get) =
       });
 
       try {
-        const req = await getPlanRequest(get().ibc);
+        const req = await getPlanRequest(get().ibcOut);
         await planBuildBroadcast('ics20Withdrawal', req);
 
         // Reset form
         set(state => {
-          state.ibc.amount = '';
+          state.ibcOut.amount = '';
         });
       } catch (e) {
         errorToast(e, 'Ics20 withdrawal error').render();
       } finally {
         set(state => {
-          state.ibc.txInProgress = false;
+          state.ibcOut.txInProgress = false;
         });
       }
     },
@@ -154,7 +154,7 @@ const getPlanRequest = async ({
   selection,
   chain,
   destinationChainAddress,
-}: IbcSendSlice): Promise<TransactionPlannerRequest> => {
+}: IbcOutSlice): Promise<TransactionPlannerRequest> => {
   if (!destinationChainAddress) throw new Error('no destination chain address set');
   if (!chain) throw new Error('Chain not set');
   if (!selection) throw new Error('No asset selected');
@@ -184,16 +184,16 @@ const getPlanRequest = async ({
   });
 };
 
-export const ibcSelector = (state: AllSlices) => state.ibc;
+export const ibcOutSelector = (state: AllSlices) => state.ibcOut;
 
 export const ibcValidationErrors = (state: AllSlices) => {
   return {
-    recipientErr: !state.ibc.destinationChainAddress
+    recipientErr: !state.ibcOut.destinationChainAddress
       ? false
-      : !validateUnknownAddress(state.ibc.chain, state.ibc.destinationChainAddress),
-    amountErr: !state.ibc.selection
+      : !validateUnknownAddress(state.ibcOut.chain, state.ibcOut.destinationChainAddress),
+    amountErr: !state.ibcOut.selection
       ? false
-      : amountMoreThanBalance(state.ibc.selection, state.ibc.amount),
+      : amountMoreThanBalance(state.ibcOut.selection, state.ibcOut.amount),
   };
 };
 
diff --git a/apps/minifront/src/state/index.ts b/apps/minifront/src/state/index.ts
index 695b9fe60e..a975e71358 100644
--- a/apps/minifront/src/state/index.ts
+++ b/apps/minifront/src/state/index.ts
@@ -2,11 +2,12 @@ import { create, StateCreator } from 'zustand';
 import { enableMapSet } from 'immer';
 import { immer } from 'zustand/middleware/immer';
 import { createSwapSlice, SwapSlice } from './swap';
-import { createIbcSendSlice, IbcSendSlice } from './ibc';
+import { createIbcOutSlice, IbcOutSlice } from './ibc-out';
 import { createSendSlice, SendSlice } from './send';
 import { createStakingSlice, StakingSlice } from './staking';
 import { createUnclaimedSwapsSlice, UnclaimedSwapsSlice } from './unclaimed-swaps';
 import { createTransactionsSlice, TransactionsSlice } from './transactions';
+import { createIbcInSlice, IbcInSlice } from './ibc-in';
 
 /**
  * Required to enable use of `Map`s in Zustand state when using Immer
@@ -16,7 +17,8 @@ import { createTransactionsSlice, TransactionsSlice } from './transactions';
 enableMapSet();
 
 export interface AllSlices {
-  ibc: IbcSendSlice;
+  ibcIn: IbcInSlice;
+  ibcOut: IbcOutSlice;
   send: SendSlice;
   staking: StakingSlice;
   swap: SwapSlice;
@@ -33,7 +35,8 @@ export type SliceCreator<SliceInterface> = StateCreator<
 
 export const initializeStore = () => {
   return immer((setState, getState: () => AllSlices, store) => ({
-    ibc: createIbcSendSlice()(setState, getState, store),
+    ibcIn: createIbcInSlice()(setState, getState, store),
+    ibcOut: createIbcOutSlice()(setState, getState, store),
     send: createSendSlice()(setState, getState, store),
     staking: createStakingSlice()(setState, getState, store),
     swap: createSwapSlice()(setState, getState, store),
diff --git a/packages/ui/components/ui/avatar.tsx b/packages/ui/components/ui/avatar.tsx
new file mode 100644
index 0000000000..5b6d80ea87
--- /dev/null
+++ b/packages/ui/components/ui/avatar.tsx
@@ -0,0 +1,46 @@
+'use client';
+
+import * as React from 'react';
+import * as AvatarPrimitive from '@radix-ui/react-avatar';
+import { cn } from '../../lib/utils';
+
+const Avatar = React.forwardRef<
+  React.ElementRef<typeof AvatarPrimitive.Root>,
+  React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
+>(({ className, ...props }, ref) => (
+  <AvatarPrimitive.Root
+    ref={ref}
+    className={cn('relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full', className)}
+    {...props}
+  />
+));
+Avatar.displayName = AvatarPrimitive.Root.displayName;
+
+const AvatarImage = React.forwardRef<
+  React.ElementRef<typeof AvatarPrimitive.Image>,
+  React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
+>(({ className, ...props }, ref) => (
+  <AvatarPrimitive.Image
+    ref={ref}
+    className={cn('aspect-square h-full w-full', className)}
+    {...props}
+  />
+));
+AvatarImage.displayName = AvatarPrimitive.Image.displayName;
+
+const AvatarFallback = React.forwardRef<
+  React.ElementRef<typeof AvatarPrimitive.Fallback>,
+  React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
+>(({ className, ...props }, ref) => (
+  <AvatarPrimitive.Fallback
+    ref={ref}
+    className={cn(
+      'flex h-full w-full items-center justify-center rounded-full bg-muted',
+      className,
+    )}
+    {...props}
+  />
+));
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
+
+export { Avatar, AvatarImage, AvatarFallback };
diff --git a/packages/ui/components/ui/command.tsx b/packages/ui/components/ui/command.tsx
new file mode 100644
index 0000000000..d5bb1c872a
--- /dev/null
+++ b/packages/ui/components/ui/command.tsx
@@ -0,0 +1,145 @@
+'use client';
+
+import * as React from 'react';
+import { type DialogProps } from '@radix-ui/react-dialog';
+import { Command as CommandPrimitive } from 'cmdk';
+import { Search } from 'lucide-react';
+import { cn } from '../../lib/utils';
+import { Dialog, DialogContent } from './dialog';
+
+const Command = React.forwardRef<
+  React.ElementRef<typeof CommandPrimitive>,
+  React.ComponentPropsWithoutRef<typeof CommandPrimitive>
+>(({ className, ...props }, ref) => (
+  <CommandPrimitive
+    ref={ref}
+    className={cn(
+      'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
+      className,
+    )}
+    {...props}
+  />
+));
+Command.displayName = CommandPrimitive.displayName;
+
+type CommandDialogProps = DialogProps;
+
+const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
+  return (
+    <Dialog {...props}>
+      <DialogContent>
+        <Command className='[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:size-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:size-5'>
+          {children}
+        </Command>
+      </DialogContent>
+    </Dialog>
+  );
+};
+
+const CommandInput = React.forwardRef<
+  React.ElementRef<typeof CommandPrimitive.Input>,
+  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
+>(({ className, ...props }, ref) => (
+  // eslint-disable-next-line react/no-unknown-property
+  <div className='flex items-center border-b px-3' cmdk-input-wrapper=''>
+    <Search className='mr-2 size-4 shrink-0 opacity-50' />
+    <CommandPrimitive.Input
+      ref={ref}
+      className={cn(
+        'flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
+        className,
+      )}
+      {...props}
+    />
+  </div>
+));
+
+CommandInput.displayName = CommandPrimitive.Input.displayName;
+
+const CommandList = React.forwardRef<
+  React.ElementRef<typeof CommandPrimitive.List>,
+  React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
+>(({ className, ...props }, ref) => (
+  <CommandPrimitive.List
+    ref={ref}
+    className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
+    {...props}
+  />
+));
+
+CommandList.displayName = CommandPrimitive.List.displayName;
+
+const CommandEmpty = React.forwardRef<
+  React.ElementRef<typeof CommandPrimitive.Empty>,
+  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
+>((props, ref) => (
+  <CommandPrimitive.Empty ref={ref} className='py-6 text-center text-sm' {...props} />
+));
+
+CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
+
+const CommandGroup = React.forwardRef<
+  React.ElementRef<typeof CommandPrimitive.Group>,
+  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
+>(({ className, ...props }, ref) => (
+  <CommandPrimitive.Group
+    ref={ref}
+    className={cn(
+      'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',
+      className,
+    )}
+    {...props}
+  />
+));
+
+CommandGroup.displayName = CommandPrimitive.Group.displayName;
+
+const CommandSeparator = React.forwardRef<
+  React.ElementRef<typeof CommandPrimitive.Separator>,
+  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
+>(({ className, ...props }, ref) => (
+  <CommandPrimitive.Separator
+    ref={ref}
+    className={cn('-mx-1 h-px bg-border', className)}
+    {...props}
+  />
+));
+CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
+
+const CommandItem = React.forwardRef<
+  React.ElementRef<typeof CommandPrimitive.Item>,
+  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
+>(({ className, ...props }, ref) => (
+  <CommandPrimitive.Item
+    ref={ref}
+    className={cn(
+      'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
+      className,
+    )}
+    {...props}
+  />
+));
+
+CommandItem.displayName = CommandPrimitive.Item.displayName;
+
+const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
+  return (
+    <span
+      className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}
+      {...props}
+    />
+  );
+};
+CommandShortcut.displayName = 'CommandShortcut';
+
+export {
+  Command,
+  CommandDialog,
+  CommandInput,
+  CommandList,
+  CommandEmpty,
+  CommandGroup,
+  CommandItem,
+  CommandShortcut,
+  CommandSeparator,
+};
diff --git a/packages/ui/components/ui/popover.tsx b/packages/ui/components/ui/popover.tsx
index 7941208a2e..14a71f2cd0 100644
--- a/packages/ui/components/ui/popover.tsx
+++ b/packages/ui/components/ui/popover.tsx
@@ -11,14 +11,14 @@ const PopoverTrigger = PopoverPrimitive.Trigger;
 const PopoverContent = React.forwardRef<
   React.ElementRef<typeof PopoverPrimitive.Content>,
   React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
->(({ className, align = 'start', sideOffset = 4, ...props }, ref) => (
+>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
   <PopoverPrimitive.Portal>
     <PopoverPrimitive.Content
       ref={ref}
       align={align}
       sideOffset={sideOffset}
       className={cn(
-        'z-50 w-[240px] rounded-lg bg-background p-4 text-muted-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:fill-mode-forwards data-[state=open]:fill-mode-forwards',
+        'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
         className,
       )}
       {...props}
diff --git a/packages/ui/package.json b/packages/ui/package.json
index e98f29541f..c47d95e614 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -20,6 +20,7 @@
     "@penumbra-zone/getters": "workspace:*",
     "@penumbra-zone/perspective": "workspace:*",
     "@penumbra-zone/types": "workspace:*",
+    "@radix-ui/react-avatar": "^1.0.4",
     "@radix-ui/react-checkbox": "^1.0.4",
     "@radix-ui/react-dialog": "1.0.5",
     "@radix-ui/react-icons": "^1.3.0",
@@ -37,6 +38,7 @@
     "@textea/json-viewer": "^3.4.0",
     "class-variance-authority": "^0.7.0",
     "clsx": "^2.1.0",
+    "cmdk": "0.2.0",
     "djb2a": "^2.0.0",
     "framer-motion": "^11.0.22",
     "humanize-duration": "^3.31.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bf3ed4ab55..65644311c4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -370,11 +370,14 @@ importers:
       '@cosmjs/stargate':
         specifier: ^0.32.3
         version: 0.32.3
+      '@cosmos-kit/core':
+        specifier: ^2.9.2
+        version: 2.9.2
       '@cosmos-kit/react':
-        specifier: ^2.11.0
+        specifier: ^2.11.2
         version: 2.11.2(@interchain-ui/react@1.23.10)(react-dom@18.3.1)(react@18.3.1)
       '@interchain-ui/react':
-        specifier: ^1.23.3
+        specifier: ^1.23.10
         version: 1.23.10(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
       '@penumbra-labs/registry':
         specifier: ^5.1.0
@@ -419,10 +422,10 @@ importers:
         specifier: ^9.1.2
         version: 9.1.2
       chain-registry:
-        specifier: ^1.41.9
+        specifier: ^1.45.5
         version: 1.45.5
       cosmos-kit:
-        specifier: ^2.10.0
+        specifier: ^2.10.2
         version: 2.10.2(@cosmjs/amino@0.32.3)(@cosmjs/proto-signing@0.32.3)(@terra-money/terra.js@3.1.10)(@walletconnect/types@2.11.0)(axios@0.27.2)(cosmjs-types@0.9.0)(react@18.3.1)
       date-fns:
         specifier: ^3.6.0
@@ -436,11 +439,11 @@ importers:
       lodash:
         specifier: ^4.17.21
         version: 4.17.21
-      match-sorter:
-        specifier: ^6.3.4
-        version: 6.3.4
+      lucide-react:
+        specifier: ^0.363.0
+        version: 0.363.0(react@18.3.1)
       osmo-query:
-        specifier: ^16.11.0
+        specifier: ^16.12.0
         version: 16.12.0
       react:
         specifier: ^18.2.0
@@ -471,8 +474,8 @@ importers:
         version: 4.5.2(@types/react@18.3.1)(immer@10.1.1)(react@18.3.1)
     devDependencies:
       '@chain-registry/types':
-        specifier: ^0.25.7
-        version: 0.25.8
+        specifier: ^0.28.4
+        version: 0.28.4
       '@penumbra-zone/polyfills':
         specifier: workspace:*
         version: link:../../packages/polyfills
@@ -929,6 +932,9 @@ importers:
       '@penumbra-zone/types':
         specifier: workspace:*
         version: link:../types
+      '@radix-ui/react-avatar':
+        specifier: ^1.0.4
+        version: 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
       '@radix-ui/react-checkbox':
         specifier: ^1.0.4
         version: 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
@@ -980,6 +986,9 @@ importers:
       clsx:
         specifier: ^2.1.0
         version: 2.1.1
+      cmdk:
+        specifier: 0.2.0
+        version: 0.2.0(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
       djb2a:
         specifier: ^2.0.0
         version: 2.0.0
@@ -1364,6 +1373,11 @@ packages:
     resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
     engines: {node: '>=6.9.0'}
 
+  /@babel/helper-validator-identifier@7.24.5:
+    resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==}
+    engines: {node: '>=6.9.0'}
+    dev: true
+
   /@babel/helper-validator-option@7.23.5:
     resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
     engines: {node: '>=6.9.0'}
@@ -1406,6 +1420,14 @@ packages:
       '@babel/types': 7.24.0
     dev: true
 
+  /@babel/parser@7.24.5:
+    resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+    dependencies:
+      '@babel/types': 7.24.5
+    dev: true
+
   /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.4(@babel/core@7.24.4):
     resolution: {integrity: sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==}
     engines: {node: '>=6.9.0'}
@@ -2394,6 +2416,12 @@ packages:
     dependencies:
       regenerator-runtime: 0.14.1
 
+  /@babel/runtime@7.24.5:
+    resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      regenerator-runtime: 0.14.1
+
   /@babel/template@7.24.0:
     resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==}
     engines: {node: '>=6.9.0'}
@@ -2429,6 +2457,15 @@ packages:
       '@babel/helper-validator-identifier': 7.22.20
       to-fast-properties: 2.0.0
 
+  /@babel/types@7.24.5:
+    resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/helper-string-parser': 7.24.1
+      '@babel/helper-validator-identifier': 7.24.5
+      to-fast-properties: 2.0.0
+    dev: true
+
   /@base2/pretty-print-object@1.0.1:
     resolution: {integrity: sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==}
     dev: true
@@ -2840,7 +2877,7 @@ packages:
   /@chain-registry/cosmostation@1.26.0:
     resolution: {integrity: sha512-MmjThpQ0U0EJF66UJzPy67iKC9hY7ljrpGtQOPfeYGB/lUlKZTsE/mgF2XkKGUf7wJK8LugOqU5Zul7C1/ZA4Q==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@chain-registry/types': 0.17.1
       '@chain-registry/utils': 1.29.4
       '@cosmostation/extension-client': 0.1.15
@@ -2857,7 +2894,7 @@ packages:
   /@chain-registry/keplr@1.28.0:
     resolution: {integrity: sha512-MRAEgUpafyGLRDQc4SPB+R/If4CL2SREqdbxZMKHX9aeqzKXhJlEM5IPjJTZCWTbUP/eGXC9JNjxPNUYd92PqQ==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@chain-registry/types': 0.17.1
       '@keplr-wallet/cosmos': 0.12.28
       '@keplr-wallet/crypto': 0.12.28
@@ -2867,22 +2904,17 @@ packages:
   /@chain-registry/types@0.17.0:
     resolution: {integrity: sha512-lavACU4oDxioUy8lZOFZN0Vrr2qR+Dg2yEh/mkrPfOldcioavREXJou0elDyyXwq4pGLC5YQ+IISCtQ4Du0bdw==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
     dev: false
 
   /@chain-registry/types@0.17.1:
     resolution: {integrity: sha512-O0CgrtJgIlqXvZm1CqDZe/7jZz068O/uuCIoyDXCegFHK03rdHacKcDGwEIUuI0MNUf8YV3jdE4xHQMSAX+79w==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
     dev: false
 
-  /@chain-registry/types@0.25.8:
-    resolution: {integrity: sha512-5fLZ7hwkBUsH/jfJhg7SxkTrR6cQUGiolnbYqikliEb2UlxJG+PZ2d49R/xEZg3NA7j+j4PqsdaGETwwTsIadg==}
-    dev: true
-
   /@chain-registry/types@0.28.4:
     resolution: {integrity: sha512-nmQFud4YQfT8U3dFjWgIhNgtelvWmGvcCRbrnAaxMs24ePFYWmh+tBnGSseS8bZtYqDaYVRUMEOpl3TRjgUfbQ==}
-    dev: false
 
   /@chain-registry/utils@1.29.4:
     resolution: {integrity: sha512-Da7Qx59ELMV+g7pseg7/HAZclF3T4WZF1UR5anpJJ7WtsKfs51q3ocWYC7J6Z+U2zGg2XmWvJh+AFYydzSav1A==}
@@ -2895,7 +2927,7 @@ packages:
   /@changesets/apply-release-plan@7.0.0:
     resolution: {integrity: sha512-vfi69JR416qC9hWmFGSxj7N6wA5J222XNBmezSVATPWDVPIF7gkd4d8CpbEbXmRWbVrkoli3oerGS6dcL/BGsQ==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@changesets/config': 3.0.0
       '@changesets/get-version-range-type': 0.4.0
       '@changesets/git': 3.0.0
@@ -2913,7 +2945,7 @@ packages:
   /@changesets/assemble-release-plan@6.0.0:
     resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@changesets/errors': 0.2.0
       '@changesets/get-dependents-graph': 2.0.0
       '@changesets/types': 6.0.0
@@ -2996,7 +3028,7 @@ packages:
   /@changesets/get-release-plan@4.0.0:
     resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@changesets/assemble-release-plan': 6.0.0
       '@changesets/config': 3.0.0
       '@changesets/pre': 2.0.0
@@ -3012,7 +3044,7 @@ packages:
   /@changesets/git@3.0.0:
     resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@changesets/errors': 0.2.0
       '@changesets/types': 6.0.0
       '@manypkg/get-packages': 1.1.3
@@ -3037,7 +3069,7 @@ packages:
   /@changesets/pre@2.0.0:
     resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@changesets/errors': 0.2.0
       '@changesets/types': 6.0.0
       '@manypkg/get-packages': 1.1.3
@@ -3047,7 +3079,7 @@ packages:
   /@changesets/read@0.6.0:
     resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@changesets/git': 3.0.0
       '@changesets/logger': 0.1.0
       '@changesets/parse': 0.4.0
@@ -3068,7 +3100,7 @@ packages:
   /@changesets/write@0.3.0:
     resolution: {integrity: sha512-slGLb21fxZVUYbyea+94uFiD6ntQW0M2hIKNznFizDhZPDgn2c/fv1UzzlW43RVzh1BEDuIqW6hzlJ1OflNmcw==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@changesets/types': 6.0.0
       fs-extra: 7.0.1
       human-id: 1.0.2
@@ -4645,7 +4677,7 @@ packages:
     resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==}
     dependencies:
       '@babel/helper-module-imports': 7.24.3
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@emotion/hash': 0.9.1
       '@emotion/memoize': 0.8.1
       '@emotion/serialize': 1.1.4
@@ -5956,7 +5988,7 @@ packages:
   /@manypkg/find-root@1.1.0:
     resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/node': 12.20.55
       find-up: 4.1.0
       fs-extra: 8.1.0
@@ -5965,7 +5997,7 @@ packages:
   /@manypkg/get-packages@1.1.3:
     resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@changesets/types': 4.1.0
       '@manypkg/find-root': 1.1.0
       fs-extra: 8.1.0
@@ -6074,7 +6106,7 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@floating-ui/react-dom': 2.0.9(react-dom@18.3.1)(react@18.3.1)
       '@mui/types': 7.2.14(@types/react@18.3.1)
       '@mui/utils': 5.15.14(@types/react@18.3.1)(react@18.3.1)
@@ -6136,7 +6168,7 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@mui/utils': 5.15.14(@types/react@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
       prop-types: 15.8.1
@@ -6156,7 +6188,7 @@ packages:
       '@emotion/styled':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@emotion/cache': 11.11.0
       '@emotion/react': 11.11.4(@types/react@18.3.1)(react@18.3.1)
       '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.1)(react@18.3.1)
@@ -6181,7 +6213,7 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@emotion/react': 11.11.4(@types/react@18.3.1)(react@18.3.1)
       '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.1)(react@18.3.1)
       '@mui/private-theming': 5.15.14(@types/react@18.3.1)(react@18.3.1)
@@ -6216,7 +6248,7 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/prop-types': 15.7.12
       '@types/react': 18.3.1
       prop-types: 15.8.1
@@ -6505,13 +6537,19 @@ packages:
   /@radix-ui/number@1.0.1:
     resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
+    dev: false
+
+  /@radix-ui/primitive@1.0.0:
+    resolution: {integrity: sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA==}
+    dependencies:
+      '@babel/runtime': 7.24.5
     dev: false
 
   /@radix-ui/primitive@1.0.1:
     resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
     dev: false
 
   /@radix-ui/react-arrow@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
@@ -6527,8 +6565,32 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
+      '@types/react': 18.3.1
+      '@types/react-dom': 18.3.0
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+    dev: false
+
+  /@radix-ui/react-avatar@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0
+      react-dom: ^16.8 || ^17.0 || ^18.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-context': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
+      '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.1)(react@18.3.1)
+      '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
       '@types/react-dom': 18.3.0
       react: 18.3.1
@@ -6576,7 +6638,7 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@radix-ui/react-context': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
@@ -6587,6 +6649,15 @@ packages:
       react-dom: 18.3.1(react@18.3.1)
     dev: false
 
+  /@radix-ui/react-compose-refs@1.0.0(react@18.3.1):
+    resolution: {integrity: sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      react: 18.3.1
+    dev: false
+
   /@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
     peerDependencies:
@@ -6596,10 +6667,19 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/react': 18.3.1
       react: 18.3.1
 
+  /@radix-ui/react-context@1.0.0(react@18.3.1):
+    resolution: {integrity: sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      react: 18.3.1
+    dev: false
+
   /@radix-ui/react-context@1.0.1(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==}
     peerDependencies:
@@ -6609,11 +6689,38 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/react': 18.3.1
       react: 18.3.1
     dev: false
 
+  /@radix-ui/react-dialog@1.0.0(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-Yn9YU+QlHYLWwV1XfKiqnGVpWYWk6MeBVM6x/bcoyPvxgjQGoeT35482viLPctTMWoMw0PoHgqfSox7Ig+957Q==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+      react-dom: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/primitive': 1.0.0
+      '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
+      '@radix-ui/react-context': 1.0.0(react@18.3.1)
+      '@radix-ui/react-dismissable-layer': 1.0.0(react-dom@18.3.1)(react@18.3.1)
+      '@radix-ui/react-focus-guards': 1.0.0(react@18.3.1)
+      '@radix-ui/react-focus-scope': 1.0.0(react-dom@18.3.1)(react@18.3.1)
+      '@radix-ui/react-id': 1.0.0(react@18.3.1)
+      '@radix-ui/react-portal': 1.0.0(react-dom@18.3.1)(react@18.3.1)
+      '@radix-ui/react-presence': 1.0.0(react-dom@18.3.1)(react@18.3.1)
+      '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1)(react@18.3.1)
+      '@radix-ui/react-slot': 1.0.0(react@18.3.1)
+      '@radix-ui/react-use-controllable-state': 1.0.0(react@18.3.1)
+      aria-hidden: 1.2.4
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+      react-remove-scroll: 2.5.4(@types/react@18.3.1)(react@18.3.1)
+    transitivePeerDependencies:
+      - '@types/react'
+    dev: false
+
   /@radix-ui/react-dialog@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==}
     peerDependencies:
@@ -6657,11 +6764,27 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/react': 18.3.1
       react: 18.3.1
     dev: false
 
+  /@radix-ui/react-dismissable-layer@1.0.0(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-n7kDRfx+LB1zLueRDvZ1Pd0bxdJWDUZNQ/GWoxDn2prnuJKRdxsjulejX/ePkOsLi2tTm6P24mDqlMSgQpsT6g==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+      react-dom: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/primitive': 1.0.0
+      '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
+      '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1)(react@18.3.1)
+      '@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1)
+      '@radix-ui/react-use-escape-keydown': 1.0.0(react@18.3.1)
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+    dev: false
+
   /@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==}
     peerDependencies:
@@ -6675,7 +6798,7 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/primitive': 1.0.1
       '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
@@ -6687,6 +6810,15 @@ packages:
       react-dom: 18.3.1(react@18.3.1)
     dev: false
 
+  /@radix-ui/react-focus-guards@1.0.0(react@18.3.1):
+    resolution: {integrity: sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      react: 18.3.1
+    dev: false
+
   /@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==}
     peerDependencies:
@@ -6696,11 +6828,25 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/react': 18.3.1
       react: 18.3.1
     dev: false
 
+  /@radix-ui/react-focus-scope@1.0.0(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-C4SWtsULLGf/2L4oGeIHlvWQx7Rf+7cX/vKOAD2dXW0A1b5QXwi3wWeaEgW+wn+SEVrraMUk05vLU9fZZz5HbQ==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+      react-dom: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
+      '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1)(react@18.3.1)
+      '@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1)
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+    dev: false
+
   /@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==}
     peerDependencies:
@@ -6714,7 +6860,7 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
       '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.1)(react@18.3.1)
@@ -6731,6 +6877,16 @@ packages:
     dependencies:
       react: 18.3.1
 
+  /@radix-ui/react-id@1.0.0(react@18.3.1):
+    resolution: {integrity: sha512-Q6iAB/U7Tq3NTolBBQbHTgclPmGWE3OlktGGqrClPozSw4vkQ1DfQAOtzgRPecKsMdJINE05iaoDUG8tRzCBjw==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-use-layout-effect': 1.0.0(react@18.3.1)
+      react: 18.3.1
+    dev: false
+
   /@radix-ui/react-id@1.0.1(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==}
     peerDependencies:
@@ -6740,7 +6896,7 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
       react: 18.3.1
@@ -6828,7 +6984,7 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@floating-ui/react-dom': 2.0.9(react-dom@18.3.1)(react@18.3.1)
       '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
       '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.1)(react@18.3.1)
@@ -6845,6 +7001,18 @@ packages:
       react-dom: 18.3.1(react@18.3.1)
     dev: false
 
+  /@radix-ui/react-portal@1.0.0(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-a8qyFO/Xb99d8wQdu4o7qnigNjTPG123uADNecz0eX4usnQEj7o+cG4ZX4zkqq98NYekT7UoEQIjxBNWIFuqTA==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+      react-dom: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1)(react@18.3.1)
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+    dev: false
+
   /@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==}
     peerDependencies:
@@ -6858,7 +7026,7 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
       '@types/react-dom': 18.3.0
@@ -6866,6 +7034,19 @@ packages:
       react-dom: 18.3.1(react@18.3.1)
     dev: false
 
+  /@radix-ui/react-presence@1.0.0(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+      react-dom: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
+      '@radix-ui/react-use-layout-effect': 1.0.0(react@18.3.1)
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+    dev: false
+
   /@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
     peerDependencies:
@@ -6879,7 +7060,7 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
@@ -6888,6 +7069,18 @@ packages:
       react-dom: 18.3.1(react@18.3.1)
     dev: false
 
+  /@radix-ui/react-primitive@1.0.0(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-EyXe6mnRlHZ8b6f4ilTDrXmkLShICIuOTTj0GX4w1rp+wSxf3+TD05u1UOITC8VsJ2a9nwHvdXtOXEOl0Cw/zQ==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+      react-dom: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-slot': 1.0.0(react@18.3.1)
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+    dev: false
+
   /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==}
     peerDependencies:
@@ -6901,7 +7094,7 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-slot': 1.0.2(@types/react@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
       '@types/react-dom': 18.3.0
@@ -6944,7 +7137,7 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/primitive': 1.0.1
       '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
       '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.1)(react@18.3.1)
@@ -7001,6 +7194,16 @@ packages:
       react-remove-scroll: 2.5.5(@types/react@18.3.1)(react@18.3.1)
     dev: false
 
+  /@radix-ui/react-slot@1.0.0(react@18.3.1):
+    resolution: {integrity: sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
+      react: 18.3.1
+    dev: false
+
   /@radix-ui/react-slot@1.0.2(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
     peerDependencies:
@@ -7157,6 +7360,15 @@ packages:
       react-dom: 18.3.1(react@18.3.1)
     dev: false
 
+  /@radix-ui/react-use-callback-ref@1.0.0(react@18.3.1):
+    resolution: {integrity: sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      react: 18.3.1
+    dev: false
+
   /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
     peerDependencies:
@@ -7166,11 +7378,21 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/react': 18.3.1
       react: 18.3.1
     dev: false
 
+  /@radix-ui/react-use-controllable-state@1.0.0(react@18.3.1):
+    resolution: {integrity: sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1)
+      react: 18.3.1
+    dev: false
+
   /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==}
     peerDependencies:
@@ -7180,12 +7402,22 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
       react: 18.3.1
     dev: false
 
+  /@radix-ui/react-use-escape-keydown@1.0.0(react@18.3.1):
+    resolution: {integrity: sha512-JwfBCUIfhXRxKExgIqGa4CQsiMemo1Xt0W/B4ei3fpzpvPENKpMKQ8mZSB6Acj3ebrAEgi2xiQvcI1PAAodvyg==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      '@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1)
+      react: 18.3.1
+    dev: false
+
   /@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==}
     peerDependencies:
@@ -7195,12 +7427,21 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
       react: 18.3.1
     dev: false
 
+  /@radix-ui/react-use-layout-effect@1.0.0(react@18.3.1):
+    resolution: {integrity: sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ==}
+    peerDependencies:
+      react: ^16.8 || ^17.0 || ^18.0
+    dependencies:
+      '@babel/runtime': 7.24.5
+      react: 18.3.1
+    dev: false
+
   /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==}
     peerDependencies:
@@ -7210,7 +7451,7 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/react': 18.3.1
       react: 18.3.1
     dev: false
@@ -7224,7 +7465,7 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/react': 18.3.1
       react: 18.3.1
     dev: false
@@ -7238,7 +7479,7 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/rect': 1.0.1
       '@types/react': 18.3.1
       react: 18.3.1
@@ -7253,7 +7494,7 @@ packages:
       '@types/react':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
       react: 18.3.1
@@ -7272,7 +7513,7 @@ packages:
       '@types/react-dom':
         optional: true
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
       '@types/react': 18.3.1
       '@types/react-dom': 18.3.0
@@ -7283,7 +7524,7 @@ packages:
   /@radix-ui/rect@1.0.1:
     resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
     dev: false
 
   /@react-aria/breadcrumbs@3.5.11(react@18.3.1):
@@ -10049,7 +10290,7 @@ packages:
     engines: {node: '>=14'}
     dependencies:
       '@babel/code-frame': 7.24.2
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@types/aria-query': 5.0.4
       aria-query: 5.1.3
       chalk: 4.1.2
@@ -10080,7 +10321,7 @@ packages:
         optional: true
     dependencies:
       '@adobe/css-tools': 4.3.3
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       aria-query: 5.3.0
       chalk: 3.0.0
       css.escape: 1.5.1
@@ -10096,7 +10337,7 @@ packages:
       react: ^18.0.0
       react-dom: ^18.0.0
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       '@testing-library/dom': 9.3.4
       '@types/react-dom': 18.3.0
       react: 18.3.1
@@ -12005,7 +12246,7 @@ packages:
     resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
     engines: {node: '>=10', npm: '>=6'}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       cosmiconfig: 7.1.0
       resolve: 1.22.8
     dev: false
@@ -12320,7 +12561,7 @@ packages:
     hasBin: true
     dependencies:
       caniuse-lite: 1.0.30001614
-      electron-to-chromium: 1.4.750
+      electron-to-chromium: 1.4.751
       node-releases: 2.0.14
       update-browserslist-db: 1.0.13(browserslist@4.23.0)
     dev: true
@@ -12755,6 +12996,20 @@ packages:
     engines: {node: '>=6'}
     dev: false
 
+  /cmdk@0.2.0(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-JQpKvEOb86SnvMZbYaFKYhvzFntWBeSZdyii0rZPhKJj9uwJBxu4DaVYDrRN7r3mPop56oPhRw+JYWTKs66TYw==}
+    peerDependencies:
+      react: ^18.0.0
+      react-dom: ^18.0.0
+    dependencies:
+      '@radix-ui/react-dialog': 1.0.0(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
+      command-score: 0.1.2
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+    transitivePeerDependencies:
+      - '@types/react'
+    dev: false
+
   /color-convert@1.9.3:
     resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
     dependencies:
@@ -12813,6 +13068,10 @@ packages:
     dependencies:
       delayed-stream: 1.0.0
 
+  /command-score@0.1.2:
+    resolution: {integrity: sha512-VtDvQpIJBvBatnONUsPzXYFVKQQAhuf3XTNOAsdBxCNO/QCtUUd8LSgjn0GVarBkCad6aJCZfXgrjYbl/KRr7w==}
+    dev: false
+
   /commander@10.0.1:
     resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
     engines: {node: '>=14'}
@@ -13754,7 +14013,7 @@ packages:
   /dom-helpers@5.2.1:
     resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       csstype: 3.1.3
     dev: false
 
@@ -13867,8 +14126,8 @@ packages:
       jake: 10.8.7
     dev: true
 
-  /electron-to-chromium@1.4.750:
-    resolution: {integrity: sha512-9ItEpeu15hW5m8jKdriL+BQrgwDTXEL9pn4SkillWFu73ZNNNQ2BKKLS+ZHv2vC9UkNhosAeyfxOf/5OSeTCPA==}
+  /electron-to-chromium@1.4.751:
+    resolution: {integrity: sha512-2DEPi++qa89SMGRhufWTiLmzqyuGmNF3SK4+PQetW1JKiZdEpF4XQonJXJCzyuYSA6mauiMhbyVhqYAP45Hvfw==}
     dev: true
 
   /elliptic@6.5.4:
@@ -16793,7 +17052,7 @@ packages:
     engines: {node: '>=12.0.0'}
     hasBin: true
     dependencies:
-      '@babel/parser': 7.24.4
+      '@babel/parser': 7.24.5
       '@jsdoc/salty': 0.2.8
       '@types/markdown-it': 12.2.3
       bluebird: 3.7.2
@@ -17528,13 +17787,6 @@ packages:
     hasBin: true
     dev: true
 
-  /match-sorter@6.3.4:
-    resolution: {integrity: sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==}
-    dependencies:
-      '@babel/runtime': 7.24.4
-      remove-accents: 0.5.0
-    dev: false
-
   /md5.js@1.3.5:
     resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==}
     dependencies:
@@ -17549,7 +17801,7 @@ packages:
   /media-query-parser@2.0.2:
     resolution: {integrity: sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
     dev: false
 
   /media-typer@0.3.0:
@@ -18746,7 +18998,7 @@ packages:
     resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==}
     engines: {node: '>=10'}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
     dev: true
 
   /portfinder@1.0.32:
@@ -19526,6 +19778,25 @@ packages:
       tslib: 2.6.2
     dev: false
 
+  /react-remove-scroll@2.5.4(@types/react@18.3.1)(react@18.3.1):
+    resolution: {integrity: sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==}
+    engines: {node: '>=10'}
+    peerDependencies:
+      '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+    dependencies:
+      '@types/react': 18.3.1
+      react: 18.3.1
+      react-remove-scroll-bar: 2.3.6(@types/react@18.3.1)(react@18.3.1)
+      react-style-singleton: 2.2.1(@types/react@18.3.1)(react@18.3.1)
+      tslib: 2.6.2
+      use-callback-ref: 1.3.2(@types/react@18.3.1)(react@18.3.1)
+      use-sidecar: 1.1.2(@types/react@18.3.1)(react@18.3.1)
+    dev: false
+
   /react-remove-scroll@2.5.5(@types/react@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==}
     engines: {node: '>=10'}
@@ -19630,7 +19901,7 @@ packages:
       react: '>=16.6.0'
       react-dom: '>=16.6.0'
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
       dom-helpers: 5.2.1
       loose-envify: 1.4.0
       prop-types: 15.8.1
@@ -19798,7 +20069,7 @@ packages:
   /regenerator-transform@0.15.2:
     resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==}
     dependencies:
-      '@babel/runtime': 7.24.4
+      '@babel/runtime': 7.24.5
     dev: true
 
   /regexp.prototype.flags@1.5.2:
@@ -19884,10 +20155,6 @@ packages:
     engines: {node: '>= 0.10'}
     dev: true
 
-  /remove-accents@0.5.0:
-    resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==}
-    dev: false
-
   /renderkid@3.0.0:
     resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==}
     dependencies: