diff --git a/.github/workflows/client.yml b/.github/workflows/client.yml index 1f0e2fd86d..6b97a1e61d 100644 --- a/.github/workflows/client.yml +++ b/.github/workflows/client.yml @@ -1,6 +1,11 @@ name: Publish `@librechat/client` to NPM on: + push: + branches: + - main + paths: + - 'packages/client/package.json' workflow_dispatch: inputs: reason: @@ -17,16 +22,37 @@ jobs: - name: Use Node.js uses: actions/setup-node@v4 with: - node-version: '18.x' - - - name: Check if client package exists + node-version: '20.x' + + - name: Install client dependencies + run: cd packages/client && npm ci + + - name: Build client + run: cd packages/client && npm run build + + - name: Set up npm authentication + run: echo "//registry.npmjs.org/:_authToken=${{ secrets.PUBLISH_NPM_TOKEN }}" > ~/.npmrc + + - name: Check version change + id: check + working-directory: packages/client run: | - if [ -d "packages/client" ]; then - echo "Client package directory found" + PACKAGE_VERSION=$(node -p "require('./package.json').version") + PUBLISHED_VERSION=$(npm view @librechat/client version 2>/dev/null || echo "0.0.0") + if [ "$PACKAGE_VERSION" = "$PUBLISHED_VERSION" ]; then + echo "No version change, skipping publish" + echo "skip=true" >> $GITHUB_OUTPUT else - echo "Client package directory not found - workflow ready for future use" - exit 0 + echo "Version changed, proceeding with publish" + echo "skip=false" >> $GITHUB_OUTPUT fi - - - name: Placeholder for future publishing - run: echo "Client package publishing workflow is ready" \ No newline at end of file + + - name: Pack package + if: steps.check.outputs.skip != 'true' + working-directory: packages/client + run: npm pack + + - name: Publish + if: steps.check.outputs.skip != 'true' + working-directory: packages/client + run: npm publish *.tgz --access public \ No newline at end of file diff --git a/.github/workflows/i18n-unused-keys.yml b/.github/workflows/i18n-unused-keys.yml index 07cc77a1ae..9fb2fd6833 100644 --- a/.github/workflows/i18n-unused-keys.yml +++ b/.github/workflows/i18n-unused-keys.yml @@ -6,6 +6,7 @@ on: - "client/src/**" - "api/**" - "packages/data-provider/src/**" + - "packages/client/**" jobs: detect-unused-i18n-keys: @@ -23,7 +24,7 @@ jobs: # Define paths I18N_FILE="client/src/locales/en/translation.json" - SOURCE_DIRS=("client/src" "api" "packages/data-provider/src") + SOURCE_DIRS=("client/src" "api" "packages/data-provider/src" "packages/client") # Check if translation file exists if [[ ! -f "$I18N_FILE" ]]; then diff --git a/.github/workflows/unused-packages.yml b/.github/workflows/unused-packages.yml index 5429a1abde..442925b69b 100644 --- a/.github/workflows/unused-packages.yml +++ b/.github/workflows/unused-packages.yml @@ -7,6 +7,7 @@ on: - 'package-lock.json' - 'client/**' - 'api/**' + - 'packages/client/**' jobs: detect-unused-packages: @@ -28,7 +29,7 @@ jobs: - name: Validate JSON files run: | - for FILE in package.json client/package.json api/package.json; do + for FILE in package.json client/package.json api/package.json packages/client/package.json; do if [[ -f "$FILE" ]]; then jq empty "$FILE" || (echo "::error title=Invalid JSON::$FILE is invalid" && exit 1) fi @@ -63,12 +64,31 @@ jobs: local folder=$1 local output_file=$2 if [[ -d "$folder" ]]; then - grep -rEho "require\\(['\"]([a-zA-Z0-9@/._-]+)['\"]\\)" "$folder" --include=\*.{js,ts,mjs,cjs} | \ + # Extract require() statements + grep -rEho "require\\(['\"]([a-zA-Z0-9@/._-]+)['\"]\\)" "$folder" --include=\*.{js,ts,tsx,jsx,mjs,cjs} | \ sed -E "s/require\\(['\"]([a-zA-Z0-9@/._-]+)['\"]\\)/\1/" > "$output_file" - grep -rEho "import .* from ['\"]([a-zA-Z0-9@/._-]+)['\"]" "$folder" --include=\*.{js,ts,mjs,cjs} | \ + # Extract ES6 imports - various patterns + # import x from 'module' + grep -rEho "import .* from ['\"]([a-zA-Z0-9@/._-]+)['\"]" "$folder" --include=\*.{js,ts,tsx,jsx,mjs,cjs} | \ sed -E "s/import .* from ['\"]([a-zA-Z0-9@/._-]+)['\"]/\1/" >> "$output_file" + + # import 'module' (side-effect imports) + grep -rEho "import ['\"]([a-zA-Z0-9@/._-]+)['\"]" "$folder" --include=\*.{js,ts,tsx,jsx,mjs,cjs} | \ + sed -E "s/import ['\"]([a-zA-Z0-9@/._-]+)['\"]/\1/" >> "$output_file" + + # export { x } from 'module' or export * from 'module' + grep -rEho "export .* from ['\"]([a-zA-Z0-9@/._-]+)['\"]" "$folder" --include=\*.{js,ts,tsx,jsx,mjs,cjs} | \ + sed -E "s/export .* from ['\"]([a-zA-Z0-9@/._-]+)['\"]/\1/" >> "$output_file" + + # import type { x } from 'module' (TypeScript) + grep -rEho "import type .* from ['\"]([a-zA-Z0-9@/._-]+)['\"]" "$folder" --include=\*.{ts,tsx} | \ + sed -E "s/import type .* from ['\"]([a-zA-Z0-9@/._-]+)['\"]/\1/" >> "$output_file" + # Remove subpath imports but keep the base package + # e.g., '@tanstack/react-query/devtools' becomes '@tanstack/react-query' + sed -i -E 's|^(@?[a-zA-Z0-9-]+(/[a-zA-Z0-9-]+)?)/.*|\1|' "$output_file" + sort -u "$output_file" -o "$output_file" else touch "$output_file" @@ -78,6 +98,33 @@ jobs: extract_deps_from_code "." root_used_code.txt extract_deps_from_code "client" client_used_code.txt extract_deps_from_code "api" api_used_code.txt + + # Extract dependencies used by @librechat/client package + extract_deps_from_code "packages/client" packages_client_used_code.txt + + - name: Get @librechat/client dependencies + id: get-librechat-client-deps + run: | + if [[ -f "packages/client/package.json" ]]; then + # Get all dependencies from @librechat/client (dependencies, devDependencies, and peerDependencies) + DEPS=$(jq -r '.dependencies // {} | keys[]' packages/client/package.json 2>/dev/null || echo "") + DEV_DEPS=$(jq -r '.devDependencies // {} | keys[]' packages/client/package.json 2>/dev/null || echo "") + PEER_DEPS=$(jq -r '.peerDependencies // {} | keys[]' packages/client/package.json 2>/dev/null || echo "") + + # Combine all dependencies + echo "$DEPS" > librechat_client_deps.txt + echo "$DEV_DEPS" >> librechat_client_deps.txt + echo "$PEER_DEPS" >> librechat_client_deps.txt + + # Also include dependencies that are imported in packages/client + cat packages_client_used_code.txt >> librechat_client_deps.txt + + # Remove empty lines and sort + grep -v '^$' librechat_client_deps.txt | sort -u > temp_deps.txt + mv temp_deps.txt librechat_client_deps.txt + else + touch librechat_client_deps.txt + fi - name: Extract Workspace Dependencies id: extract-workspace-deps diff --git a/bun.lockb b/bun.lockb index 61118178fd..77b01df558 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/client/package.json b/client/package.json index d0c7c54e12..f1d68d27e5 100644 --- a/client/package.json +++ b/client/package.json @@ -34,6 +34,7 @@ "@dicebear/collection": "^9.2.2", "@dicebear/core": "^9.2.2", "@headlessui/react": "^2.1.2", + "@librechat/client": "*", "@marsidev/react-turnstile": "^1.1.0", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-alert-dialog": "^1.0.2", @@ -56,8 +57,8 @@ "@react-spring/web": "^9.7.5", "@tanstack/react-query": "^4.28.0", "@tanstack/react-table": "^8.11.7", - "class-variance-authority": "^0.6.0", - "clsx": "^1.2.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "copy-to-clipboard": "^3.3.3", "cross-env": "^7.0.3", "date-fns": "^3.3.1", @@ -70,11 +71,12 @@ "i18next": "^24.2.2", "i18next-browser-languagedetector": "^8.0.3", "input-otp": "^1.4.2", + "jotai": "^2.12.5", "js-cookie": "^3.0.5", "librechat-data-provider": "*", "lodash": "^4.17.21", "lucide-react": "^0.394.0", - "match-sorter": "^6.3.4", + "match-sorter": "^8.1.0", "micromark-extension-llm-math": "^3.1.0", "qrcode.react": "^4.2.0", "rc-input-number": "^7.4.2", diff --git a/client/src/App.jsx b/client/src/App.jsx index 38e568e422..d329bdd9b3 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -4,10 +4,10 @@ import { RouterProvider } from 'react-router-dom'; import * as RadixToast from '@radix-ui/react-toast'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; +import { Toast, ThemeProvider, ToastProvider } from '@librechat/client'; import { QueryClient, QueryClientProvider, QueryCache } from '@tanstack/react-query'; -import { ScreenshotProvider, ThemeProvider, useApiErrorBoundary } from './hooks'; -import { ToastProvider } from './Providers'; -import Toast from './components/ui/Toast'; +import { ScreenshotProvider, useApiErrorBoundary } from './hooks'; +import { getThemeFromEnv } from './utils/getThemeFromEnv'; import { LiveAnnouncer } from '~/a11y'; import { router } from './routes'; @@ -24,11 +24,23 @@ const App = () => { }), }); + // Load theme from environment variables if available + const envTheme = getThemeFromEnv(); + return ( - + + {/* The ThemeProvider will automatically: + 1. Apply dark/light mode classes + 2. Apply custom theme colors if envTheme is provided + 3. Otherwise use stored theme preferences from localStorage + 4. Fall back to default theme colors if nothing is stored */} diff --git a/client/src/Providers/index.ts b/client/src/Providers/index.ts index caf5b82b73..7300813aec 100644 --- a/client/src/Providers/index.ts +++ b/client/src/Providers/index.ts @@ -1,11 +1,9 @@ export { default as AssistantsProvider } from './AssistantsContext'; export { default as AgentsProvider } from './AgentsContext'; -export { default as ToastProvider } from './ToastContext'; export * from './ActivePanelContext'; export * from './AgentPanelContext'; export * from './ChatContext'; export * from './ShareContext'; -export * from './ToastContext'; export * from './FileMapContext'; export * from './AddedChatContext'; export * from './EditorContext'; diff --git a/client/src/a11y/LiveAnnouncer.tsx b/client/src/a11y/LiveAnnouncer.tsx index 29912b49af..9a02711556 100644 --- a/client/src/a11y/LiveAnnouncer.tsx +++ b/client/src/a11y/LiveAnnouncer.tsx @@ -1,8 +1,7 @@ -// client/src/a11y/LiveAnnouncer.tsx import React, { useState, useCallback, useRef, useEffect, useMemo } from 'react'; import type { AnnounceOptions } from '~/common'; import AnnouncerContext from '~/Providers/AnnouncerContext'; -import useLocalize from '~/hooks/useLocalize'; +import { useLocalize } from '~/hooks'; import Announcer from './Announcer'; interface LiveAnnouncerProps { diff --git a/client/src/common/menus.ts b/client/src/common/menus.ts index c46ad3f8bb..4d70f282c2 100644 --- a/client/src/common/menus.ts +++ b/client/src/common/menus.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ export type RenderProp< P = React.HTMLAttributes & { ref?: React.Ref; diff --git a/client/src/common/types.ts b/client/src/common/types.ts index a222cb29b4..214dc349b5 100644 --- a/client/src/common/types.ts +++ b/client/src/common/types.ts @@ -206,7 +206,9 @@ export type AgentPanelProps = { setActivePanel: React.Dispatch>; setMcp: React.Dispatch>; setAction: React.Dispatch>; + endpointsConfig?: t.TEndpointsConfig; setCurrentAgentId: React.Dispatch>; + agentsConfig?: t.TAgentsEndpoint | null; }; export type AgentPanelContextType = { @@ -217,14 +219,12 @@ export type AgentPanelContextType = { mcps?: t.MCP[]; setMcp: React.Dispatch>; setMcps: React.Dispatch>; + groupedTools: Record; tools: t.AgentToolType[]; activePanel?: string; setActivePanel: React.Dispatch>; setCurrentAgentId: React.Dispatch>; - groupedTools?: Record; agent_id?: string; - agentsConfig?: t.TAgentsEndpoint | null; - endpointsConfig?: t.TEndpointsConfig | null; }; export type AgentModelPanelProps = { @@ -336,16 +336,13 @@ export type TAskProps = { export type TOptions = { editedMessageId?: string | null; editedText?: string | null; - editedContent?: { - index: number; - text: string; - type: 'text' | 'think'; - }; isRegenerate?: boolean; isContinued?: boolean; isEdited?: boolean; overrideMessages?: t.TMessage[]; - /** Currently only utilized when resubmitting user-created message, uses that message's currently attached files */ + /** This value is only true when the user submits a message with "Save & Submit" for a user-created message */ + isResubmission?: boolean; + /** Currently only utilized when `isResubmission === true`, uses that message's currently attached files */ overrideFiles?: t.TMessage['files']; }; diff --git a/client/src/components/Artifacts/Artifacts.tsx b/client/src/components/Artifacts/Artifacts.tsx index 4268ef5fe3..41c6201025 100644 --- a/client/src/components/Artifacts/Artifacts.tsx +++ b/client/src/components/Artifacts/Artifacts.tsx @@ -6,9 +6,9 @@ import type { SandpackPreviewRef, CodeEditorRef } from '@codesandbox/sandpack-re import useArtifacts from '~/hooks/Artifacts/useArtifacts'; import DownloadArtifact from './DownloadArtifact'; import { useEditorContext } from '~/Providers'; -import useLocalize from '~/hooks/useLocalize'; import ArtifactTabs from './ArtifactTabs'; import { CopyCodeButton } from './Code'; +import { useLocalize } from '~/hooks'; import store from '~/store'; export default function Artifacts() { diff --git a/client/src/components/Artifacts/Code.tsx b/client/src/components/Artifacts/Code.tsx index 21db2055d7..4b6d1a0065 100644 --- a/client/src/components/Artifacts/Code.tsx +++ b/client/src/components/Artifacts/Code.tsx @@ -1,12 +1,11 @@ import React, { memo, useEffect, useRef, useState } from 'react'; +import copy from 'copy-to-clipboard'; import rehypeKatex from 'rehype-katex'; import ReactMarkdown from 'react-markdown'; import rehypeHighlight from 'rehype-highlight'; -import copy from 'copy-to-clipboard'; +import { Clipboard, CheckMark } from '@librechat/client'; import { handleDoubleClick, langSubset } from '~/utils'; -import Clipboard from '~/components/svg/Clipboard'; -import CheckMark from '~/components/svg/CheckMark'; -import useLocalize from '~/hooks/useLocalize'; +import { useLocalize } from '~/hooks'; type TCodeProps = { inline: boolean; diff --git a/client/src/components/Artifacts/DownloadArtifact.tsx b/client/src/components/Artifacts/DownloadArtifact.tsx index a4b6f5031c..afced5a37f 100644 --- a/client/src/components/Artifacts/DownloadArtifact.tsx +++ b/client/src/components/Artifacts/DownloadArtifact.tsx @@ -1,9 +1,9 @@ import React, { useState } from 'react'; import { Download } from 'lucide-react'; import type { Artifact } from '~/common'; +import { CheckMark } from '@librechat/client'; import useArtifactProps from '~/hooks/Artifacts/useArtifactProps'; import { useEditorContext } from '~/Providers'; -import { CheckMark } from '~/components/svg'; import { useLocalize } from '~/hooks'; const DownloadArtifact = ({ diff --git a/client/src/components/Artifacts/Mermaid.tsx b/client/src/components/Artifacts/Mermaid.tsx index 551a5a5a78..f7291998a4 100644 --- a/client/src/components/Artifacts/Mermaid.tsx +++ b/client/src/components/Artifacts/Mermaid.tsx @@ -1,8 +1,7 @@ import React, { useEffect, useRef, useState } from 'react'; import mermaid from 'mermaid'; +import { Button } from '@librechat/client'; import { TransformWrapper, TransformComponent, ReactZoomPanPinchRef } from 'react-zoom-pan-pinch'; -// import { Button } from '/components/ui/Button'; // Live component -import { Button } from '~/components/ui/Button'; import { ZoomIn, ZoomOut, RefreshCw } from 'lucide-react'; interface MermaidDiagramProps { diff --git a/client/src/components/Audio/TTS.tsx b/client/src/components/Audio/TTS.tsx index 9343b483d2..0d9351703e 100644 --- a/client/src/components/Audio/TTS.tsx +++ b/client/src/components/Audio/TTS.tsx @@ -2,8 +2,8 @@ import { useEffect } from 'react'; import { useRecoilValue } from 'recoil'; import type { TMessageAudio } from '~/common'; +import { VolumeIcon, VolumeMuteIcon, Spinner } from '@librechat/client'; import { useLocalize, useTTSBrowser, useTTSExternal } from '~/hooks'; -import { VolumeIcon, VolumeMuteIcon, Spinner } from '~/components'; import { logger } from '~/utils'; import store from '~/store'; diff --git a/client/src/components/Audio/Voices.tsx b/client/src/components/Audio/Voices.tsx index 985e5e32d8..6064a16624 100644 --- a/client/src/components/Audio/Voices.tsx +++ b/client/src/components/Audio/Voices.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { useRecoilState } from 'recoil'; +import { Dropdown } from '@librechat/client'; import type { Option } from '~/common'; import { useLocalize, useTTSBrowser, useTTSExternal } from '~/hooks'; -import { Dropdown } from '~/components/ui'; import { logger } from '~/utils'; import store from '~/store'; diff --git a/client/src/components/Auth/AuthLayout.tsx b/client/src/components/Auth/AuthLayout.tsx index 02b3802917..c49ba2a7da 100644 --- a/client/src/components/Auth/AuthLayout.tsx +++ b/client/src/components/Auth/AuthLayout.tsx @@ -1,9 +1,9 @@ -import { TranslationKeys, useLocalize } from '~/hooks'; +import { ThemeSelector } from '@librechat/client'; import { TStartupConfig } from 'librechat-data-provider'; import { ErrorMessage } from '~/components/Auth/ErrorMessage'; +import { TranslationKeys, useLocalize } from '~/hooks'; import SocialLoginRender from './SocialLoginRender'; import { BlinkAnimation } from './BlinkAnimation'; -import { ThemeSelector } from '~/components'; import { Banner } from '../Banners'; import Footer from './Footer'; diff --git a/client/src/components/Auth/Login.tsx b/client/src/components/Auth/Login.tsx index ee0b87246c..39406e300f 100644 --- a/client/src/components/Auth/Login.tsx +++ b/client/src/components/Auth/Login.tsx @@ -1,10 +1,10 @@ import { useOutletContext, useSearchParams } from 'react-router-dom'; import { useEffect, useState } from 'react'; -import { useAuthContext } from '~/hooks/AuthContext'; +import { OpenIDIcon } from '@librechat/client'; import type { TLoginLayoutContext } from '~/common'; import { ErrorMessage } from '~/components/Auth/ErrorMessage'; import SocialButton from '~/components/Auth/SocialButton'; -import { OpenIDIcon } from '~/components'; +import { useAuthContext } from '~/hooks/AuthContext'; import { getLoginError } from '~/utils'; import { useLocalize } from '~/hooks'; import LoginForm from './LoginForm'; diff --git a/client/src/components/Auth/LoginForm.tsx b/client/src/components/Auth/LoginForm.tsx index c13535db23..c7a469fc2e 100644 --- a/client/src/components/Auth/LoginForm.tsx +++ b/client/src/components/Auth/LoginForm.tsx @@ -1,11 +1,11 @@ -import { useForm } from 'react-hook-form'; import React, { useState, useEffect, useContext } from 'react'; +import { useForm } from 'react-hook-form'; import { Turnstile } from '@marsidev/react-turnstile'; +import { ThemeContext, Spinner, Button } from '@librechat/client'; import type { TLoginUser, TStartupConfig } from 'librechat-data-provider'; import type { TAuthContext } from '~/common'; import { useResendVerificationEmail, useGetStartupConfig } from '~/data-provider'; -import { ThemeContext, useLocalize } from '~/hooks'; -import { Spinner, Button } from '~/components'; +import { useLocalize } from '~/hooks'; type TLoginFormProps = { onSubmit: (data: TLoginUser) => void; diff --git a/client/src/components/Auth/Registration.tsx b/client/src/components/Auth/Registration.tsx index b193cff11c..2e915e0137 100644 --- a/client/src/components/Auth/Registration.tsx +++ b/client/src/components/Auth/Registration.tsx @@ -1,12 +1,12 @@ import { useForm } from 'react-hook-form'; import React, { useContext, useState } from 'react'; import { Turnstile } from '@marsidev/react-turnstile'; +import { ThemeContext, Spinner, Button } from '@librechat/client'; import { useNavigate, useOutletContext, useLocation } from 'react-router-dom'; import { useRegisterUserMutation } from 'librechat-data-provider/react-query'; import type { TRegisterUser, TError } from 'librechat-data-provider'; -import { useLocalize, TranslationKeys, ThemeContext } from '~/hooks'; import type { TLoginLayoutContext } from '~/common'; -import { Spinner, Button } from '~/components'; +import { useLocalize, TranslationKeys } from '~/hooks'; import { ErrorMessage } from './ErrorMessage'; const Registration: React.FC = () => { diff --git a/client/src/components/Auth/RequestPasswordReset.tsx b/client/src/components/Auth/RequestPasswordReset.tsx index c0ef5751ca..9f50a7e42c 100644 --- a/client/src/components/Auth/RequestPasswordReset.tsx +++ b/client/src/components/Auth/RequestPasswordReset.tsx @@ -1,11 +1,11 @@ import { useForm } from 'react-hook-form'; import { useState, ReactNode } from 'react'; +import { Spinner, Button } from '@librechat/client'; import { useOutletContext } from 'react-router-dom'; import { useRequestPasswordResetMutation } from 'librechat-data-provider/react-query'; import type { TRequestPasswordReset, TRequestPasswordResetResponse } from 'librechat-data-provider'; -import type { FC } from 'react'; import type { TLoginLayoutContext } from '~/common'; -import { Spinner, Button } from '~/components'; +import type { FC } from 'react'; import { useLocalize } from '~/hooks'; const BodyTextWrapper: FC<{ children: ReactNode }> = ({ children }) => { diff --git a/client/src/components/Auth/ResetPassword.tsx b/client/src/components/Auth/ResetPassword.tsx index 231c501cb8..2882e1dc53 100644 --- a/client/src/components/Auth/ResetPassword.tsx +++ b/client/src/components/Auth/ResetPassword.tsx @@ -1,10 +1,10 @@ import { useForm } from 'react-hook-form'; +import { Spinner, Button } from '@librechat/client'; import { useOutletContext } from 'react-router-dom'; import { useNavigate, useSearchParams } from 'react-router-dom'; import { useResetPasswordMutation } from 'librechat-data-provider/react-query'; import type { TResetPassword } from 'librechat-data-provider'; import type { TLoginLayoutContext } from '~/common'; -import { Spinner, Button } from '~/components'; import { useLocalize } from '~/hooks'; function ResetPassword() { diff --git a/client/src/components/Auth/SocialLoginRender.tsx b/client/src/components/Auth/SocialLoginRender.tsx index 55a8ade6ba..ad76354a53 100644 --- a/client/src/components/Auth/SocialLoginRender.tsx +++ b/client/src/components/Auth/SocialLoginRender.tsx @@ -6,7 +6,7 @@ import { DiscordIcon, AppleIcon, SamlIcon, -} from '~/components'; +} from '@librechat/client'; import SocialButton from './SocialButton'; diff --git a/client/src/components/Auth/TwoFactorScreen.tsx b/client/src/components/Auth/TwoFactorScreen.tsx index 04f89d7cea..11eab660c7 100644 --- a/client/src/components/Auth/TwoFactorScreen.tsx +++ b/client/src/components/Auth/TwoFactorScreen.tsx @@ -1,10 +1,10 @@ import React, { useState, useCallback } from 'react'; import { useSearchParams } from 'react-router-dom'; +import { useToastContext } from '@librechat/client'; import { useForm, Controller } from 'react-hook-form'; import { REGEXP_ONLY_DIGITS, REGEXP_ONLY_DIGITS_AND_CHARS } from 'input-otp'; -import { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Label } from '~/components'; +import { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Label } from '@librechat/client'; import { useVerifyTwoFactorTempMutation } from '~/data-provider'; -import { useToastContext } from '~/Providers'; import { useLocalize } from '~/hooks'; interface VerifyPayload { diff --git a/client/src/components/Auth/VerifyEmail.tsx b/client/src/components/Auth/VerifyEmail.tsx index 9c143224b2..fb5c787196 100644 --- a/client/src/components/Auth/VerifyEmail.tsx +++ b/client/src/components/Auth/VerifyEmail.tsx @@ -1,8 +1,7 @@ -import { useSearchParams, useNavigate } from 'react-router-dom'; import { useState, useEffect, useMemo, useCallback } from 'react'; +import { Spinner, ThemeSelector } from '@librechat/client'; +import { useSearchParams, useNavigate } from 'react-router-dom'; import { useVerifyEmailMutation, useResendVerificationEmail } from '~/data-provider'; -import { ThemeSelector } from '~/components/ui'; -import { Spinner } from '~/components/svg'; import { useLocalize } from '~/hooks'; function RequestPasswordReset() { diff --git a/client/src/components/Bookmarks/BookmarkEditDialog.tsx b/client/src/components/Bookmarks/BookmarkEditDialog.tsx index ae81c3b81e..7c0b494d7d 100644 --- a/client/src/components/Bookmarks/BookmarkEditDialog.tsx +++ b/client/src/components/Bookmarks/BookmarkEditDialog.tsx @@ -1,10 +1,8 @@ import React, { useRef, Dispatch, SetStateAction } from 'react'; import { TConversationTag } from 'librechat-data-provider'; -import OGDialogTemplate from '~/components/ui/OGDialogTemplate'; +import { OGDialogTemplate, OGDialog, Button, Spinner, useToastContext } from '@librechat/client'; import { useConversationTagMutation } from '~/data-provider'; -import { OGDialog, Button, Spinner } from '~/components'; import { NotificationSeverity } from '~/common'; -import { useToastContext } from '~/Providers'; import BookmarkForm from './BookmarkForm'; import { useLocalize } from '~/hooks'; import { logger } from '~/utils'; diff --git a/client/src/components/Bookmarks/BookmarkForm.tsx b/client/src/components/Bookmarks/BookmarkForm.tsx index c866216be0..857eacb10c 100644 --- a/client/src/components/Bookmarks/BookmarkForm.tsx +++ b/client/src/components/Bookmarks/BookmarkForm.tsx @@ -2,11 +2,10 @@ import React, { useEffect } from 'react'; import { QueryKeys } from 'librechat-data-provider'; import { Controller, useForm } from 'react-hook-form'; import { useQueryClient } from '@tanstack/react-query'; +import { Checkbox, Label, TextareaAutosize, Input, useToastContext } from '@librechat/client'; import type { TConversationTag, TConversationTagRequest } from 'librechat-data-provider'; -import { Checkbox, Label, TextareaAutosize, Input } from '~/components'; import { useBookmarkContext } from '~/Providers/BookmarkContext'; import { useConversationTagMutation } from '~/data-provider'; -import { useToastContext } from '~/Providers'; import { useLocalize } from '~/hooks'; import { cn, logger } from '~/utils'; diff --git a/client/src/components/Bookmarks/BookmarkItem.tsx b/client/src/components/Bookmarks/BookmarkItem.tsx index 60698a3165..b12a5b5ac5 100644 --- a/client/src/components/Bookmarks/BookmarkItem.tsx +++ b/client/src/components/Bookmarks/BookmarkItem.tsx @@ -1,8 +1,8 @@ import { useState } from 'react'; +import { Spinner } from '@librechat/client'; import { MenuItem } from '@headlessui/react'; import { BookmarkFilledIcon, BookmarkIcon } from '@radix-ui/react-icons'; import type { FC } from 'react'; -import { Spinner } from '~/components/svg'; type MenuItemProps = { tag: string | React.ReactNode; diff --git a/client/src/components/Bookmarks/DeleteBookmarkButton.tsx b/client/src/components/Bookmarks/DeleteBookmarkButton.tsx index 911659de74..e63feb7621 100644 --- a/client/src/components/Bookmarks/DeleteBookmarkButton.tsx +++ b/client/src/components/Bookmarks/DeleteBookmarkButton.tsx @@ -1,10 +1,17 @@ import { useCallback, useState } from 'react'; +import { + Button, + TrashIcon, + Label, + OGDialog, + OGDialogTrigger, + TooltipAnchor, + OGDialogTemplate, + useToastContext, +} from '@librechat/client'; import type { FC } from 'react'; -import { Button, TrashIcon, Label, OGDialog, OGDialogTrigger, TooltipAnchor } from '~/components'; import { useDeleteConversationTagMutation } from '~/data-provider'; -import OGDialogTemplate from '~/components/ui/OGDialogTemplate'; import { NotificationSeverity } from '~/common'; -import { useToastContext } from '~/Providers'; import { useLocalize } from '~/hooks'; const DeleteBookmarkButton: FC<{ diff --git a/client/src/components/Bookmarks/EditBookmarkButton.tsx b/client/src/components/Bookmarks/EditBookmarkButton.tsx index 6e976a53cf..7c4355be81 100644 --- a/client/src/components/Bookmarks/EditBookmarkButton.tsx +++ b/client/src/components/Bookmarks/EditBookmarkButton.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; -import type { FC } from 'react'; +import { TooltipAnchor, OGDialogTrigger, EditIcon, Button } from '@librechat/client'; import type { TConversationTag } from 'librechat-data-provider'; -import { TooltipAnchor, OGDialogTrigger, EditIcon, Button } from '~/components'; +import type { FC } from 'react'; import BookmarkEditDialog from './BookmarkEditDialog'; import { useLocalize } from '~/hooks'; diff --git a/client/src/components/Chat/AddMultiConvo.tsx b/client/src/components/Chat/AddMultiConvo.tsx index 79131dfdb0..26395c7a6f 100644 --- a/client/src/components/Chat/AddMultiConvo.tsx +++ b/client/src/components/Chat/AddMultiConvo.tsx @@ -1,8 +1,8 @@ import { PlusCircle } from 'lucide-react'; +import { TooltipAnchor } from '@librechat/client'; import { isAssistantsEndpoint } from 'librechat-data-provider'; import type { TConversation } from 'librechat-data-provider'; import { useChatContext, useAddedChatContext } from '~/Providers'; -import { TooltipAnchor } from '~/components'; import { mainTextareaId } from '~/common'; import { useLocalize } from '~/hooks'; diff --git a/client/src/components/Chat/ChatView.tsx b/client/src/components/Chat/ChatView.tsx index a554c5f7d1..f488d76b27 100644 --- a/client/src/components/Chat/ChatView.tsx +++ b/client/src/components/Chat/ChatView.tsx @@ -1,6 +1,7 @@ import { memo, useCallback } from 'react'; import { useRecoilValue } from 'recoil'; import { useForm } from 'react-hook-form'; +import { Spinner } from '@librechat/client'; import { useParams } from 'react-router-dom'; import { Constants } from 'librechat-data-provider'; import type { TMessage } from 'librechat-data-provider'; @@ -10,7 +11,6 @@ import { useChatHelpers, useAddedResponse, useSSE } from '~/hooks'; import ConversationStarters from './Input/ConversationStarters'; import { useGetMessagesByConvoId } from '~/data-provider'; import MessagesView from './Messages/MessagesView'; -import { Spinner } from '~/components/svg'; import Presentation from './Presentation'; import { buildTree, cn } from '~/utils'; import ChatForm from './Input/ChatForm'; diff --git a/client/src/components/Chat/ExportAndShareMenu.tsx b/client/src/components/Chat/ExportAndShareMenu.tsx index aa9ee8be9b..207efcbc8d 100644 --- a/client/src/components/Chat/ExportAndShareMenu.tsx +++ b/client/src/components/Chat/ExportAndShareMenu.tsx @@ -2,11 +2,11 @@ import { useState, useId, useRef } from 'react'; import { useRecoilValue } from 'recoil'; import * as Ariakit from '@ariakit/react'; import { Upload, Share2 } from 'lucide-react'; +import { DropdownPopup, TooltipAnchor, useMediaQuery } from '@librechat/client'; import type * as t from '~/common'; import ExportModal from '~/components/Nav/ExportConversation/ExportModal'; import { ShareButton } from '~/components/Conversations/ConvoOptions'; -import { DropdownPopup, TooltipAnchor } from '~/components/ui'; -import { useMediaQuery, useLocalize } from '~/hooks'; +import { useLocalize } from '~/hooks'; import store from '~/store'; export default function ExportAndShareMenu({ diff --git a/client/src/components/Chat/Header.tsx b/client/src/components/Chat/Header.tsx index 93a265f4a2..d252e58df3 100644 --- a/client/src/components/Chat/Header.tsx +++ b/client/src/components/Chat/Header.tsx @@ -1,4 +1,5 @@ import { useMemo } from 'react'; +import { useMediaQuery } from '@librechat/client'; import { useOutletContext } from 'react-router-dom'; import { getConfigDefaults, PermissionTypes, Permissions } from 'librechat-data-provider'; import type { ContextType } from '~/common'; @@ -6,10 +7,10 @@ import ModelSelector from './Menus/Endpoints/ModelSelector'; import { PresetsMenu, HeaderNewChat, OpenSidebar } from './Menus'; import { useGetStartupConfig } from '~/data-provider'; import ExportAndShareMenu from './ExportAndShareMenu'; -import { useMediaQuery, useHasAccess } from '~/hooks'; import BookmarkMenu from './Menus/BookmarkMenu'; import { TemporaryChat } from './TemporaryChat'; import AddMultiConvo from './AddMultiConvo'; +import { useHasAccess } from '~/hooks'; const defaultInterface = getConfigDefaults().interface; diff --git a/client/src/components/Chat/Input/Artifacts.tsx b/client/src/components/Chat/Input/Artifacts.tsx index eb2c49572f..493f126e3c 100644 --- a/client/src/components/Chat/Input/Artifacts.tsx +++ b/client/src/components/Chat/Input/Artifacts.tsx @@ -1,8 +1,8 @@ import React, { memo, useState, useCallback, useMemo } from 'react'; import * as Ariakit from '@ariakit/react'; +import { CheckboxButton } from '@librechat/client'; import { ArtifactModes } from 'librechat-data-provider'; import { WandSparkles, ChevronDown } from 'lucide-react'; -import CheckboxButton from '~/components/ui/CheckboxButton'; import { useBadgeRowContext } from '~/Providers'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/ArtifactsSubMenu.tsx b/client/src/components/Chat/Input/ArtifactsSubMenu.tsx index 944ecb66c7..654c129fba 100644 --- a/client/src/components/Chat/Input/ArtifactsSubMenu.tsx +++ b/client/src/components/Chat/Input/ArtifactsSubMenu.tsx @@ -1,8 +1,8 @@ import React from 'react'; import * as Ariakit from '@ariakit/react'; +import { PinIcon } from '@librechat/client'; import { ChevronRight, WandSparkles } from 'lucide-react'; import { ArtifactModes } from 'librechat-data-provider'; -import { PinIcon } from '~/components/svg'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/AudioRecorder.tsx b/client/src/components/Chat/Input/AudioRecorder.tsx index eae7c266cf..ae4252f4f9 100644 --- a/client/src/components/Chat/Input/AudioRecorder.tsx +++ b/client/src/components/Chat/Input/AudioRecorder.tsx @@ -1,8 +1,7 @@ import { useCallback } from 'react'; -import { useChatFormContext, useToastContext } from '~/Providers'; -import { ListeningIcon, Spinner } from '~/components/svg'; +import { useToastContext, TooltipAnchor, ListeningIcon, Spinner } from '@librechat/client'; import { useLocalize, useSpeechToText } from '~/hooks'; -import { TooltipAnchor } from '~/components/ui'; +import { useChatFormContext } from '~/Providers'; import { globalAudioId } from '~/common'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/BadgeRow.tsx b/client/src/components/Chat/Input/BadgeRow.tsx index d77fc5426c..5036dcd5e4 100644 --- a/client/src/components/Chat/Input/BadgeRow.tsx +++ b/client/src/components/Chat/Input/BadgeRow.tsx @@ -8,6 +8,7 @@ import React, { useReducer, useCallback, } from 'react'; +import { Badge } from '@librechat/client'; import { useRecoilValue, useRecoilCallback } from 'recoil'; import type { LucideIcon } from 'lucide-react'; import CodeInterpreter from './CodeInterpreter'; @@ -15,7 +16,6 @@ import { BadgeRowProvider } from '~/Providers'; import ToolsDropdown from './ToolsDropdown'; import type { BadgeItem } from '~/common'; import { useChatBadges } from '~/hooks'; -import { Badge } from '~/components/ui'; import ToolDialogs from './ToolDialogs'; import FileSearch from './FileSearch'; import Artifacts from './Artifacts'; diff --git a/client/src/components/Chat/Input/ChatForm.tsx b/client/src/components/Chat/Input/ChatForm.tsx index 0ca6448094..50fa318b3e 100644 --- a/client/src/components/Chat/Input/ChatForm.tsx +++ b/client/src/components/Chat/Input/ChatForm.tsx @@ -1,5 +1,6 @@ import { memo, useRef, useMemo, useEffect, useState, useCallback } from 'react'; import { useWatch } from 'react-hook-form'; +import { TextareaAutosize } from '@librechat/client'; import { useRecoilState, useRecoilValue } from 'recoil'; import { Constants, isAssistantsEndpoint, isAgentsEndpoint } from 'librechat-data-provider'; import { @@ -20,7 +21,6 @@ import { import { mainTextareaId, BadgeItem } from '~/common'; import AttachFileChat from './Files/AttachFileChat'; import FileFormChat from './Files/FileFormChat'; -import { TextareaAutosize } from '~/components'; import { cn, removeFocusRings } from '~/utils'; import TextareaHeader from './TextareaHeader'; import PromptsCommand from './PromptsCommand'; diff --git a/client/src/components/Chat/Input/CircleRender.tsx b/client/src/components/Chat/Input/CircleRender.tsx index 88b7947633..5b46f65744 100644 --- a/client/src/components/Chat/Input/CircleRender.tsx +++ b/client/src/components/Chat/Input/CircleRender.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { CircleIcon, CircleDotsIcon } from '~/components/svg'; import { ECallState } from 'librechat-data-provider'; +import { CircleIcon, CircleDotsIcon } from '@librechat/client'; const CircleRender = ({ rmsLevel, isCameraOn, state }) => { const getIconComponent = (state) => { diff --git a/client/src/components/Chat/Input/CodeInterpreter.tsx b/client/src/components/Chat/Input/CodeInterpreter.tsx index f2d9760cca..6805c3300c 100644 --- a/client/src/components/Chat/Input/CodeInterpreter.tsx +++ b/client/src/components/Chat/Input/CodeInterpreter.tsx @@ -1,7 +1,7 @@ import React, { memo } from 'react'; import { TerminalSquareIcon } from 'lucide-react'; +import { CheckboxButton } from '@librechat/client'; import { PermissionTypes, Permissions } from 'librechat-data-provider'; -import CheckboxButton from '~/components/ui/CheckboxButton'; import { useLocalize, useHasAccess } from '~/hooks'; import { useBadgeRowContext } from '~/Providers'; diff --git a/client/src/components/Chat/Input/CollapseChat.tsx b/client/src/components/Chat/Input/CollapseChat.tsx index 1bec592177..1ae0caf794 100644 --- a/client/src/components/Chat/Input/CollapseChat.tsx +++ b/client/src/components/Chat/Input/CollapseChat.tsx @@ -1,6 +1,6 @@ import React from 'react'; +import { TooltipAnchor } from '@librechat/client'; import { ChevronDown, ChevronUp } from 'lucide-react'; -import { TooltipAnchor } from '~/components/ui'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/EditBadges.tsx b/client/src/components/Chat/Input/EditBadges.tsx index 0c9c0b5b22..821fdd4b31 100644 --- a/client/src/components/Chat/Input/EditBadges.tsx +++ b/client/src/components/Chat/Input/EditBadges.tsx @@ -1,9 +1,9 @@ import React, { useCallback } from 'react'; import { Edit3, Check, X } from 'lucide-react'; +import { Button, Badge } from '@librechat/client'; import type { LucideIcon } from 'lucide-react'; import type { BadgeItem } from '~/common'; import { useChatBadges, useLocalize } from '~/hooks'; -import { Button, Badge } from '~/components/ui'; interface EditBadgesProps { isEditingChatBadges: boolean; diff --git a/client/src/components/Chat/Input/FileSearch.tsx b/client/src/components/Chat/Input/FileSearch.tsx index 4de6c35b6b..b5106dd054 100644 --- a/client/src/components/Chat/Input/FileSearch.tsx +++ b/client/src/components/Chat/Input/FileSearch.tsx @@ -1,9 +1,8 @@ import React, { memo } from 'react'; +import { CheckboxButton, VectorIcon } from '@librechat/client'; import { PermissionTypes, Permissions } from 'librechat-data-provider'; -import CheckboxButton from '~/components/ui/CheckboxButton'; import { useLocalize, useHasAccess } from '~/hooks'; import { useBadgeRowContext } from '~/Providers'; -import { VectorIcon } from '~/components/svg'; function FileSearch() { const localize = useLocalize(); diff --git a/client/src/components/Chat/Input/Files/AttachFile.tsx b/client/src/components/Chat/Input/Files/AttachFile.tsx index fe8c03c80a..c896109abb 100644 --- a/client/src/components/Chat/Input/Files/AttachFile.tsx +++ b/client/src/components/Chat/Input/Files/AttachFile.tsx @@ -1,5 +1,5 @@ import React, { useRef } from 'react'; -import { FileUpload, TooltipAnchor, AttachmentIcon } from '~/components'; +import { FileUpload, TooltipAnchor, AttachmentIcon } from '@librechat/client'; import { useLocalize, useFileHandling } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/Files/AttachFileMenu.tsx b/client/src/components/Chat/Input/Files/AttachFileMenu.tsx index 9fe2988606..5e42dd063a 100644 --- a/client/src/components/Chat/Input/Files/AttachFileMenu.tsx +++ b/client/src/components/Chat/Input/Files/AttachFileMenu.tsx @@ -1,11 +1,11 @@ -import { useSetRecoilState } from 'recoil'; -import * as Ariakit from '@ariakit/react'; import React, { useRef, useState, useMemo } from 'react'; +import * as Ariakit from '@ariakit/react'; +import { useSetRecoilState } from 'recoil'; import { FileSearch, ImageUpIcon, TerminalSquareIcon, FileType2Icon } from 'lucide-react'; +import { FileUpload, TooltipAnchor, DropdownPopup, AttachmentIcon } from '@librechat/client'; import { EToolResources, EModelEndpoint, defaultAgentCapabilities } from 'librechat-data-provider'; import type { EndpointFileConfig } from 'librechat-data-provider'; import { useLocalize, useGetAgentsConfig, useFileHandling, useAgentCapabilities } from '~/hooks'; -import { FileUpload, TooltipAnchor, DropdownPopup, AttachmentIcon } from '~/components'; import { ephemeralAgentByConvoId } from '~/store'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/Files/DragDropModal.tsx b/client/src/components/Chat/Input/Files/DragDropModal.tsx index f80af70def..c3b337b42d 100644 --- a/client/src/components/Chat/Input/Files/DragDropModal.tsx +++ b/client/src/components/Chat/Input/Files/DragDropModal.tsx @@ -1,8 +1,8 @@ import React, { useMemo } from 'react'; +import { OGDialog, OGDialogTemplate } from '@librechat/client'; import { ImageUpIcon, FileSearch, TerminalSquareIcon, FileType2Icon } from 'lucide-react'; import { EToolResources, defaultAgentCapabilities } from 'librechat-data-provider'; import { useLocalize, useGetAgentsConfig, useAgentCapabilities } from '~/hooks'; -import { OGDialog, OGDialogTemplate } from '~/components/ui'; interface DragDropModalProps { onOptionSelect: (option: EToolResources | undefined) => void; diff --git a/client/src/components/Chat/Input/Files/FilePreview.tsx b/client/src/components/Chat/Input/Files/FilePreview.tsx index 400834a5b5..6000922786 100644 --- a/client/src/components/Chat/Input/Files/FilePreview.tsx +++ b/client/src/components/Chat/Input/Files/FilePreview.tsx @@ -1,7 +1,7 @@ +import { Spinner } from '@librechat/client'; import type { TFile } from 'librechat-data-provider'; import type { ExtendedFile } from '~/common'; -import FileIcon from '~/components/svg/Files/FileIcon'; -import { Spinner } from '~/components'; +import { FileIcon } from '~/components/svg'; import SourceIcon from './SourceIcon'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/Files/FileRow.tsx b/client/src/components/Chat/Input/Files/FileRow.tsx index 67d687eefd..47da77bbf9 100644 --- a/client/src/components/Chat/Input/Files/FileRow.tsx +++ b/client/src/components/Chat/Input/Files/FileRow.tsx @@ -1,11 +1,11 @@ import { useEffect } from 'react'; +import { useToastContext } from '@librechat/client'; import { EToolResources } from 'librechat-data-provider'; import type { ExtendedFile } from '~/common'; import { useDeleteFilesMutation } from '~/data-provider'; -import { useToastContext } from '~/Providers'; -import { useLocalize } from '~/hooks'; import { useFileDeletion } from '~/hooks/Files'; import FileContainer from './FileContainer'; +import { useLocalize } from '~/hooks'; import { logger } from '~/utils'; import Image from './Image'; diff --git a/client/src/components/Chat/Input/Files/FilesView.tsx b/client/src/components/Chat/Input/Files/FilesView.tsx index afffa34c19..13a378b93d 100644 --- a/client/src/components/Chat/Input/Files/FilesView.tsx +++ b/client/src/components/Chat/Input/Files/FilesView.tsx @@ -1,6 +1,6 @@ import { FileSources, FileContext } from 'librechat-data-provider'; import type { TFile } from 'librechat-data-provider'; -import { OGDialog, OGDialogContent, OGDialogHeader, OGDialogTitle } from '~/components'; +import { OGDialog, OGDialogContent, OGDialogHeader, OGDialogTitle } from '@librechat/client'; import { useGetFiles } from '~/data-provider'; import { DataTable, columns } from './Table'; import { useLocalize } from '~/hooks'; diff --git a/client/src/components/Chat/Input/Files/ImagePreview.tsx b/client/src/components/Chat/Input/Files/ImagePreview.tsx index fe761da862..37d4e79008 100644 --- a/client/src/components/Chat/Input/Files/ImagePreview.tsx +++ b/client/src/components/Chat/Input/Files/ImagePreview.tsx @@ -1,7 +1,7 @@ import { useState, useEffect, useCallback } from 'react'; import { Maximize2 } from 'lucide-react'; -import { OGDialog, OGDialogContent } from '~/components/ui'; import { FileSources } from 'librechat-data-provider'; +import { OGDialog, OGDialogContent } from '@librechat/client'; import ProgressCircle from './ProgressCircle'; import SourceIcon from './SourceIcon'; import { cn } from '~/utils'; @@ -93,9 +93,9 @@ const ImagePreview = ({ const style: styleProps = imageUrl ? { - ...baseStyle, - backgroundImage: `url(${imageUrl})`, - } + ...baseStyle, + backgroundImage: `url(${imageUrl})`, + } : baseStyle; if (typeof style.backgroundImage !== 'string' || style.backgroundImage.length === 0) { diff --git a/client/src/components/Chat/Input/Files/Table/Columns.tsx b/client/src/components/Chat/Input/Files/Table/Columns.tsx index bc60de361f..fb0eccee67 100644 --- a/client/src/components/Chat/Input/Files/Table/Columns.tsx +++ b/client/src/components/Chat/Input/Files/Table/Columns.tsx @@ -1,14 +1,19 @@ /* eslint-disable react-hooks/rules-of-hooks */ - import { ArrowUpDown, Database } from 'lucide-react'; import { FileSources, FileContext } from 'librechat-data-provider'; +import { + Button, + Checkbox, + OpenAIMinimalIcon, + AzureMinimalIcon, + useMediaQuery, +} from '@librechat/client'; import type { ColumnDef } from '@tanstack/react-table'; import type { TFile } from 'librechat-data-provider'; -import { Button, Checkbox, OpenAIMinimalIcon, AzureMinimalIcon } from '~/components'; import ImagePreview from '~/components/Chat/Input/Files/ImagePreview'; import FilePreview from '~/components/Chat/Input/Files/FilePreview'; +import { TranslationKeys, useLocalize } from '~/hooks'; import { SortFilterHeader } from './SortFilterHeader'; -import { TranslationKeys, useLocalize, useMediaQuery } from '~/hooks'; import { formatDate, getFileType } from '~/utils'; const contextMap: Record = { diff --git a/client/src/components/Chat/Input/Files/Table/DataTable.tsx b/client/src/components/Chat/Input/Files/Table/DataTable.tsx index c8c3190bcb..ffb3e2825b 100644 --- a/client/src/components/Chat/Input/Files/Table/DataTable.tsx +++ b/client/src/components/Chat/Input/Files/Table/DataTable.tsx @@ -16,8 +16,6 @@ import type { ColumnFiltersState, } from '@tanstack/react-table'; import { FileContext } from 'librechat-data-provider'; -import type { AugmentedColumnDef } from '~/common'; -import type { TFile } from 'librechat-data-provider'; import { Button, Input, @@ -31,11 +29,14 @@ import { DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger, -} from '~/components/ui'; + TrashIcon, + Spinner, + useMediaQuery, +} from '@librechat/client'; +import type { TFile } from 'librechat-data-provider'; +import type { AugmentedColumnDef } from '~/common'; import { useDeleteFilesFromTable } from '~/hooks/Files'; -import { TrashIcon, Spinner } from '~/components/svg'; -import useLocalize from '~/hooks/useLocalize'; -import { useMediaQuery } from '~/hooks'; +import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; import store from '~/store'; diff --git a/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx b/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx index bb9247c15a..d275044eef 100644 --- a/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx +++ b/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx @@ -2,13 +2,13 @@ import { Column } from '@tanstack/react-table'; import { ListFilter, FilterX } from 'lucide-react'; import { ArrowDownIcon, ArrowUpIcon, CaretSortIcon } from '@radix-ui/react-icons'; import { + Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, -} from '~/components/ui/DropdownMenu'; -import { Button } from '~/components/ui/Button'; +} from '@librechat/client'; import { useLocalize, TranslationKeys } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/Files/Table/TemplateTable.tsx b/client/src/components/Chat/Input/Files/Table/TemplateTable.tsx index dc288c73a9..9f6b78f91c 100644 --- a/client/src/components/Chat/Input/Files/Table/TemplateTable.tsx +++ b/client/src/components/Chat/Input/Files/Table/TemplateTable.tsx @@ -1,4 +1,4 @@ -import { DotsIcon, TrashIcon } from '~/components/svg'; +import { DotsIcon, TrashIcon } from '@librechat/client'; export default function Template() { return ( diff --git a/client/src/components/Chat/Input/HeaderOptions.tsx b/client/src/components/Chat/Input/HeaderOptions.tsx index ac4b039768..5ba2639412 100644 --- a/client/src/components/Chat/Input/HeaderOptions.tsx +++ b/client/src/components/Chat/Input/HeaderOptions.tsx @@ -2,12 +2,12 @@ import { useRecoilState } from 'recoil'; import { Settings2 } from 'lucide-react'; import { useState, useEffect, useMemo } from 'react'; import { Root, Anchor } from '@radix-ui/react-popover'; -import { EModelEndpoint, isParamEndpoint, tConvoUpdateSchema } from 'librechat-data-provider'; +import { PluginStoreDialog, TooltipAnchor } from '@librechat/client'; import { useUserKeyQuery } from 'librechat-data-provider/react-query'; +import { EModelEndpoint, isParamEndpoint, tConvoUpdateSchema } from 'librechat-data-provider'; import type { TPreset, TInterfaceConfig } from 'librechat-data-provider'; import { EndpointSettings, SaveAsPresetDialog, AlternativeSettings } from '~/components/Endpoints'; -import { useSetIndexOptions, useMediaQuery, useLocalize } from '~/hooks'; -import { PluginStoreDialog, TooltipAnchor } from '~/components'; +import { useSetIndexOptions, useLocalize } from '~/hooks'; import { useGetEndpointsQuery } from '~/data-provider'; import OptionsPopover from './OptionsPopover'; import PopoverButtons from './PopoverButtons'; diff --git a/client/src/components/Chat/Input/MCPConfigDialog.tsx b/client/src/components/Chat/Input/MCPConfigDialog.tsx new file mode 100644 index 0000000000..5cb2170869 --- /dev/null +++ b/client/src/components/Chat/Input/MCPConfigDialog.tsx @@ -0,0 +1,121 @@ +import React, { useEffect } from 'react'; +import { useForm, Controller } from 'react-hook-form'; +import { Button, Input, Label, OGDialog, OGDialogTemplate } from '@librechat/client'; +import { useLocalize } from '~/hooks'; + +export interface ConfigFieldDetail { + title: string; + description: string; +} + +interface MCPConfigDialogProps { + isOpen: boolean; + onOpenChange: (isOpen: boolean) => void; + fieldsSchema: Record; + initialValues: Record; + onSave: (updatedValues: Record) => void; + isSubmitting?: boolean; + onRevoke?: () => void; + serverName: string; +} + +export default function MCPConfigDialog({ + isOpen, + onOpenChange, + fieldsSchema, + initialValues, + onSave, + isSubmitting = false, + onRevoke, + serverName, +}: MCPConfigDialogProps) { + const localize = useLocalize(); + const { + control, + handleSubmit, + reset, + formState: { errors, _ }, + } = useForm>({ + defaultValues: initialValues, + }); + + useEffect(() => { + if (isOpen) { + reset(initialValues); + } + }, [isOpen, initialValues, reset]); + + const onFormSubmit = (data: Record) => { + onSave(data); + }; + + const handleRevoke = () => { + if (onRevoke) { + onRevoke(); + } + }; + + const dialogTitle = localize('com_ui_configure_mcp_variables_for', { 0: serverName }); + const dialogDescription = localize('com_ui_mcp_dialog_desc'); + + return ( + + + {Object.entries(fieldsSchema).map(([key, details]) => ( +
+ + ( + + )} + /> + {details.description && ( +

+ )} + {errors[key] &&

{errors[key]?.message}

} +
+ ))} + + } + selection={{ + selectHandler: handleSubmit(onFormSubmit), + selectClasses: 'bg-green-500 hover:bg-green-600 text-white', + selectText: isSubmitting ? localize('com_ui_saving') : localize('com_ui_save'), + }} + buttons={ + onRevoke && ( + + ) + } + footerClassName="flex justify-end gap-2 px-6 pb-6 pt-2" + showCancelButton={true} + /> +
+ ); +} diff --git a/client/src/components/Chat/Input/MCPSelect.tsx b/client/src/components/Chat/Input/MCPSelect.tsx index 2f9b4071c8..8160cdd2f9 100644 --- a/client/src/components/Chat/Input/MCPSelect.tsx +++ b/client/src/components/Chat/Input/MCPSelect.tsx @@ -1,9 +1,8 @@ import React, { memo, useCallback } from 'react'; -import MCPConfigDialog from '~/components/ui/MCP/MCPConfigDialog'; -import MCPServerStatusIcon from '~/components/ui/MCP/MCPServerStatusIcon'; -import MultiSelect from '~/components/ui/MultiSelect'; -import { MCPIcon } from '~/components/svg'; +import { MultiSelect, MCPIcon } from '@librechat/client'; +import MCPServerStatusIcon from '~/components/MCP/MCPServerStatusIcon'; import { useMCPServerManager } from '~/hooks/MCP/useMCPServerManager'; +import MCPConfigDialog from '~/components/MCP/MCPConfigDialog'; function MCPSelect() { const { @@ -80,7 +79,6 @@ function MCPSelect() { items={configuredServers} selectedValues={mcpValues ?? []} setSelectedValues={batchToggleServers} - defaultSelectedValues={mcpValues ?? []} renderSelectedValues={renderSelectedValues} renderItemContent={renderItemContent} placeholder={placeholderText} diff --git a/client/src/components/Chat/Input/MCPSubMenu.tsx b/client/src/components/Chat/Input/MCPSubMenu.tsx index 8f271c0b6c..1d704f2a6d 100644 --- a/client/src/components/Chat/Input/MCPSubMenu.tsx +++ b/client/src/components/Chat/Input/MCPSubMenu.tsx @@ -1,10 +1,10 @@ import React from 'react'; import * as Ariakit from '@ariakit/react'; import { ChevronRight } from 'lucide-react'; -import { PinIcon, MCPIcon } from '~/components/svg'; -import MCPConfigDialog from '~/components/ui/MCP/MCPConfigDialog'; -import MCPServerStatusIcon from '~/components/ui/MCP/MCPServerStatusIcon'; +import { PinIcon, MCPIcon } from '@librechat/client'; +import MCPServerStatusIcon from '~/components/MCP/MCPServerStatusIcon'; import { useMCPServerManager } from '~/hooks/MCP/useMCPServerManager'; +import MCPConfigDialog from '~/components/MCP/MCPConfigDialog'; import { cn } from '~/utils'; interface MCPSubMenuProps { diff --git a/client/src/components/Chat/Input/Mention.tsx b/client/src/components/Chat/Input/Mention.tsx index 067383711e..e3472a2aa0 100644 --- a/client/src/components/Chat/Input/Mention.tsx +++ b/client/src/components/Chat/Input/Mention.tsx @@ -1,12 +1,13 @@ import { useState, useRef, useEffect } from 'react'; +import { useCombobox } from '@librechat/client'; import { AutoSizer, List } from 'react-virtualized'; import { EModelEndpoint } from 'librechat-data-provider'; -import type { SetterOrUpdater } from 'recoil'; import type { MentionOption, ConvoGenerator } from '~/common'; +import type { SetterOrUpdater } from 'recoil'; import useSelectMention from '~/hooks/Input/useSelectMention'; +import { useLocalize, TranslationKeys } from '~/hooks'; import { useAssistantsMapContext } from '~/Providers'; import useMentions from '~/hooks/Input/useMentions'; -import { useLocalize, useCombobox, TranslationKeys } from '~/hooks'; import { removeCharIfLast } from '~/utils'; import MentionItem from './MentionItem'; diff --git a/client/src/components/Chat/Input/OptionsPopover.tsx b/client/src/components/Chat/Input/OptionsPopover.tsx index a49d31f334..f3102bd27c 100644 --- a/client/src/components/Chat/Input/OptionsPopover.tsx +++ b/client/src/components/Chat/Input/OptionsPopover.tsx @@ -1,11 +1,10 @@ import { useRef } from 'react'; import { Save } from 'lucide-react'; import { Portal, Content } from '@radix-ui/react-popover'; +import { Button, CrossIcon, useOnClickOutside } from '@librechat/client'; import type { ReactNode } from 'react'; -import { useLocalize, useOnClickOutside } from '~/hooks'; import { cn, removeFocusOutlines } from '~/utils'; -import { CrossIcon } from '~/components/svg'; -import { Button } from '~/components/ui'; +import { useLocalize } from '~/hooks'; type TOptionsPopoverProps = { children: ReactNode; diff --git a/client/src/components/Chat/Input/PopoverButtons.tsx b/client/src/components/Chat/Input/PopoverButtons.tsx index fa2211ecc6..31bb6ee2f6 100644 --- a/client/src/components/Chat/Input/PopoverButtons.tsx +++ b/client/src/components/Chat/Input/PopoverButtons.tsx @@ -1,9 +1,8 @@ import { useRecoilState } from 'recoil'; import { EModelEndpoint, SettingsViews } from 'librechat-data-provider'; +import { Button, MessagesSquared, GPTIcon, AssistantIcon, DataIcon } from '@librechat/client'; import type { ReactNode } from 'react'; -import { MessagesSquared, GPTIcon, AssistantIcon, DataIcon } from '~/components/svg'; import { useChatContext } from '~/Providers'; -import { Button } from '~/components/ui'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils/'; import store from '~/store'; diff --git a/client/src/components/Chat/Input/PromptsCommand.tsx b/client/src/components/Chat/Input/PromptsCommand.tsx index 835c7cd31d..0756be17e8 100644 --- a/client/src/components/Chat/Input/PromptsCommand.tsx +++ b/client/src/components/Chat/Input/PromptsCommand.tsx @@ -1,5 +1,6 @@ import { useState, useRef, useEffect, useMemo, memo, useCallback } from 'react'; import { AutoSizer, List } from 'react-virtualized'; +import { Spinner, useCombobox } from '@librechat/client'; import { useSetRecoilState, useRecoilValue } from 'recoil'; import { PermissionTypes, Permissions } from 'librechat-data-provider'; import type { TPromptGroup } from 'librechat-data-provider'; @@ -7,9 +8,8 @@ import type { PromptOption } from '~/common'; import { removeCharIfLast, mapPromptGroups, detectVariables } from '~/utils'; import VariableDialog from '~/components/Prompts/Groups/VariableDialog'; import CategoryIcon from '~/components/Prompts/Groups/CategoryIcon'; -import { useLocalize, useCombobox, useHasAccess } from '~/hooks'; +import { useLocalize, useHasAccess } from '~/hooks'; import { useGetAllPromptGroups } from '~/data-provider'; -import { Spinner } from '~/components/svg'; import MentionItem from './MentionItem'; import store from '~/store'; diff --git a/client/src/components/Chat/Input/SendButton.tsx b/client/src/components/Chat/Input/SendButton.tsx index 52a2b4bed4..14c21f0586 100644 --- a/client/src/components/Chat/Input/SendButton.tsx +++ b/client/src/components/Chat/Input/SendButton.tsx @@ -1,8 +1,7 @@ import React, { forwardRef } from 'react'; import { useWatch } from 'react-hook-form'; import type { Control } from 'react-hook-form'; -import { TooltipAnchor } from '~/components/ui'; -import { SendIcon } from '~/components/svg'; +import { SendIcon, TooltipAnchor } from '@librechat/client'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/StopButton.tsx b/client/src/components/Chat/Input/StopButton.tsx index 6c785811cd..4a058777f1 100644 --- a/client/src/components/Chat/Input/StopButton.tsx +++ b/client/src/components/Chat/Input/StopButton.tsx @@ -1,4 +1,4 @@ -import { TooltipAnchor } from '~/components/ui'; +import { TooltipAnchor } from '@librechat/client'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Input/ToolsDropdown.tsx b/client/src/components/Chat/Input/ToolsDropdown.tsx index 159fe455d6..60ad0156f1 100644 --- a/client/src/components/Chat/Input/ToolsDropdown.tsx +++ b/client/src/components/Chat/Input/ToolsDropdown.tsx @@ -1,6 +1,7 @@ import React, { useState, useMemo, useCallback } from 'react'; import * as Ariakit from '@ariakit/react'; import { Globe, Settings, Settings2, TerminalSquareIcon } from 'lucide-react'; +import { TooltipAnchor, DropdownPopup, PinIcon, VectorIcon } from '@librechat/client'; import type { MenuItemProps } from '~/common'; import { AuthType, @@ -9,11 +10,9 @@ import { PermissionTypes, defaultAgentCapabilities, } from 'librechat-data-provider'; -import { TooltipAnchor, DropdownPopup } from '~/components'; import { useLocalize, useHasAccess, useAgentCapabilities } from '~/hooks'; import ArtifactsSubMenu from '~/components/Chat/Input/ArtifactsSubMenu'; import MCPSubMenu from '~/components/Chat/Input/MCPSubMenu'; -import { PinIcon, VectorIcon } from '~/components/svg'; import { useBadgeRowContext } from '~/Providers'; import { cn } from '~/utils'; @@ -317,7 +316,7 @@ const ToolsDropdown = ({ disabled }: ToolsDropdownProps) => { return ( { const localize = useLocalize(); diff --git a/client/src/components/Chat/Menus/UI/TitleButton.tsx b/client/src/components/Chat/Menus/UI/TitleButton.tsx index c23fdeb3ab..d6f7dec095 100644 --- a/client/src/components/Chat/Menus/UI/TitleButton.tsx +++ b/client/src/components/Chat/Menus/UI/TitleButton.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { ChevronDown } from 'lucide-react'; import { Trigger } from '@radix-ui/react-popover'; -import useLocalize from '~/hooks/useLocalize'; +import { useLocalize } from '~/hooks'; export default function TitleButton({ primaryText = '', secondaryText = '' }) { const localize = useLocalize(); diff --git a/client/src/components/Chat/Messages/Content/ContentParts.tsx b/client/src/components/Chat/Messages/Content/ContentParts.tsx index 49f6be255a..9c38dd92d9 100644 --- a/client/src/components/Chat/Messages/Content/ContentParts.tsx +++ b/client/src/components/Chat/Messages/Content/ContentParts.tsx @@ -11,9 +11,9 @@ import { ThinkingButton } from '~/components/Artifacts/Thinking'; import { MessageContext, SearchContext } from '~/Providers'; import MemoryArtifacts from './MemoryArtifacts'; import Sources from '~/components/Web/Sources'; -import useLocalize from '~/hooks/useLocalize'; import { mapAttachments } from '~/utils/map'; import { EditTextPart } from './Parts'; +import { useLocalize } from '~/hooks'; import store from '~/store'; import Part from './Part'; diff --git a/client/src/components/Chat/Messages/Content/DialogImage.tsx b/client/src/components/Chat/Messages/Content/DialogImage.tsx index 0711757df1..9eb5f9e71f 100644 --- a/client/src/components/Chat/Messages/Content/DialogImage.tsx +++ b/client/src/components/Chat/Messages/Content/DialogImage.tsx @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback, useRef } from 'react'; +import { Button, OGDialog, OGDialogContent, TooltipAnchor } from '@librechat/client'; import { X, ArrowDownToLine, PanelLeftOpen, PanelLeftClose, RotateCcw } from 'lucide-react'; -import { Button, OGDialog, OGDialogContent, TooltipAnchor } from '~/components'; import { useLocalize } from '~/hooks'; const getQualityStyles = (quality: string): string => { diff --git a/client/src/components/Chat/Messages/Content/EditMessage.tsx b/client/src/components/Chat/Messages/Content/EditMessage.tsx index e2781aaa5f..e873210901 100644 --- a/client/src/components/Chat/Messages/Content/EditMessage.tsx +++ b/client/src/components/Chat/Messages/Content/EditMessage.tsx @@ -1,10 +1,10 @@ import { useRef, useEffect, useCallback } from 'react'; -import { useRecoilState, useRecoilValue } from 'recoil'; import { useForm } from 'react-hook-form'; +import { useRecoilState, useRecoilValue } from 'recoil'; +import { TextareaAutosize, TooltipAnchor } from '@librechat/client'; import { useUpdateMessageMutation } from 'librechat-data-provider/react-query'; import type { TEditProps } from '~/common'; import { useChatContext, useAddedChatContext } from '~/Providers'; -import { TextareaAutosize, TooltipAnchor } from '~/components/ui'; import { cn, removeFocusRings } from '~/utils'; import { useLocalize } from '~/hooks'; import Container from './Container'; diff --git a/client/src/components/Chat/Messages/Content/Image.tsx b/client/src/components/Chat/Messages/Content/Image.tsx index ba4f65671a..450ed0fc22 100644 --- a/client/src/components/Chat/Messages/Content/Image.tsx +++ b/client/src/components/Chat/Messages/Content/Image.tsx @@ -1,8 +1,8 @@ import React, { useState, useRef, useMemo } from 'react'; +import { Skeleton } from '@librechat/client'; import { LazyLoadImage } from 'react-lazy-load-image-component'; import { cn, scaleImage } from '~/utils'; import DialogImage from './DialogImage'; -import { Skeleton } from '~/components'; const Image = ({ imagePath, diff --git a/client/src/components/Chat/Messages/Content/MarkdownComponents.tsx b/client/src/components/Chat/Messages/Content/MarkdownComponents.tsx index e0a381ff52..de1e82443e 100644 --- a/client/src/components/Chat/Messages/Content/MarkdownComponents.tsx +++ b/client/src/components/Chat/Messages/Content/MarkdownComponents.tsx @@ -1,12 +1,13 @@ import React, { memo, useMemo, useRef, useEffect } from 'react'; import { useRecoilValue } from 'recoil'; +import { useToastContext } from '@librechat/client'; import { PermissionTypes, Permissions } from 'librechat-data-provider'; -import { useToastContext, useCodeBlockContext } from '~/Providers'; import CodeBlock from '~/components/Messages/Content/CodeBlock'; import useHasAccess from '~/hooks/Roles/useHasAccess'; import { useFileDownload } from '~/data-provider'; -import useLocalize from '~/hooks/useLocalize'; +import { useCodeBlockContext } from '~/Providers'; import { handleDoubleClick } from '~/utils'; +import { useLocalize } from '~/hooks'; import store from '~/store'; type TCodeProps = { diff --git a/client/src/components/Chat/Messages/Content/MessageContent.tsx b/client/src/components/Chat/Messages/Content/MessageContent.tsx index f70a15b779..dd3433d564 100644 --- a/client/src/components/Chat/Messages/Content/MessageContent.tsx +++ b/client/src/components/Chat/Messages/Content/MessageContent.tsx @@ -1,10 +1,10 @@ import { memo, Suspense, useMemo } from 'react'; import { useRecoilValue } from 'recoil'; +import { DelayedRender } from '@librechat/client'; import type { TMessage } from 'librechat-data-provider'; import type { TMessageContentProps, TDisplayProps } from '~/common'; import Error from '~/components/Messages/Content/Error'; import Thinking from '~/components/Artifacts/Thinking'; -import { DelayedRender } from '~/components/ui'; import { useChatContext } from '~/Providers'; import MarkdownLite from './MarkdownLite'; import EditMessage from './EditMessage'; diff --git a/client/src/components/Chat/Messages/Content/Parts/EditTextPart.tsx b/client/src/components/Chat/Messages/Content/Parts/EditTextPart.tsx index ab15355d1e..1898920eaf 100644 --- a/client/src/components/Chat/Messages/Content/Parts/EditTextPart.tsx +++ b/client/src/components/Chat/Messages/Content/Parts/EditTextPart.tsx @@ -1,5 +1,6 @@ import { useRef, useEffect, useCallback, useMemo } from 'react'; import { useForm } from 'react-hook-form'; +import { TextareaAutosize } from '@librechat/client'; import { ContentTypes } from 'librechat-data-provider'; import { useRecoilState, useRecoilValue } from 'recoil'; import { useUpdateMessageContentMutation } from 'librechat-data-provider/react-query'; @@ -7,7 +8,6 @@ import type { Agents } from 'librechat-data-provider'; import type { TEditProps } from '~/common'; import Container from '~/components/Chat/Messages/Content/Container'; import { useChatContext, useAddedChatContext } from '~/Providers'; -import { TextareaAutosize } from '~/components/ui'; import { cn, removeFocusRings } from '~/utils'; import { useLocalize } from '~/hooks'; import store from '~/store'; diff --git a/client/src/components/Chat/Messages/Content/Parts/LogLink.tsx b/client/src/components/Chat/Messages/Content/Parts/LogLink.tsx index 590b6d7b8a..d328f202ee 100644 --- a/client/src/components/Chat/Messages/Content/Parts/LogLink.tsx +++ b/client/src/components/Chat/Messages/Content/Parts/LogLink.tsx @@ -1,6 +1,6 @@ import React from 'react'; +import { useToastContext } from '@librechat/client'; import { useCodeOutputDownload } from '~/data-provider'; -import { useToastContext } from '~/Providers'; interface LogLinkProps { href: string; diff --git a/client/src/components/Chat/Messages/Content/Parts/OpenAIImageGen/OpenAIImageGen.tsx b/client/src/components/Chat/Messages/Content/Parts/OpenAIImageGen/OpenAIImageGen.tsx index ef24c3553e..c0f77b14f2 100644 --- a/client/src/components/Chat/Messages/Content/Parts/OpenAIImageGen/OpenAIImageGen.tsx +++ b/client/src/components/Chat/Messages/Content/Parts/OpenAIImageGen/OpenAIImageGen.tsx @@ -1,8 +1,8 @@ import { useState, useEffect, useRef, useCallback } from 'react'; +import { PixelCard } from '@librechat/client'; import type { TAttachment, TFile, TAttachmentMetadata } from 'librechat-data-provider'; import Image from '~/components/Chat/Messages/Content/Image'; import ProgressText from './ProgressText'; -import { PixelCard } from '~/components'; import { scaleImage } from '~/utils'; export default function OpenAIImageGen({ diff --git a/client/src/components/Chat/Messages/Content/ProgressText.tsx b/client/src/components/Chat/Messages/Content/ProgressText.tsx index 1d80309071..e131579f6d 100644 --- a/client/src/components/Chat/Messages/Content/ProgressText.tsx +++ b/client/src/components/Chat/Messages/Content/ProgressText.tsx @@ -1,8 +1,8 @@ import * as Popover from '@radix-ui/react-popover'; +import { Spinner } from '@librechat/client'; import { ChevronDown, ChevronUp } from 'lucide-react'; import CancelledIcon from './CancelledIcon'; import FinishedIcon from './FinishedIcon'; -import { Spinner } from '~/components'; import { cn } from '~/utils'; const wrapperClass = diff --git a/client/src/components/Chat/Messages/Content/SearchContent.tsx b/client/src/components/Chat/Messages/Content/SearchContent.tsx index 8b409804bf..81752ddf9c 100644 --- a/client/src/components/Chat/Messages/Content/SearchContent.tsx +++ b/client/src/components/Chat/Messages/Content/SearchContent.tsx @@ -1,5 +1,6 @@ import { Suspense, useMemo } from 'react'; import { useRecoilValue } from 'recoil'; +import { DelayedRender } from '@librechat/client'; import { ContentTypes } from 'librechat-data-provider'; import type { Agents, @@ -9,7 +10,6 @@ import type { TMessageContentParts, } from 'librechat-data-provider'; import { UnfinishedMessage } from './MessageContent'; -import { DelayedRender } from '~/components/ui'; import Sources from '~/components/Web/Sources'; import { cn, mapAttachments } from '~/utils'; import { SearchContext } from '~/Providers'; diff --git a/client/src/components/Chat/Messages/Content/ToolCall.tsx b/client/src/components/Chat/Messages/Content/ToolCall.tsx index 3408ba5a58..84fc8cdf74 100644 --- a/client/src/components/Chat/Messages/Content/ToolCall.tsx +++ b/client/src/components/Chat/Messages/Content/ToolCall.tsx @@ -1,4 +1,5 @@ import { useMemo, useState, useEffect, useRef, useLayoutEffect } from 'react'; +import { Button } from '@librechat/client'; import { TriangleAlert } from 'lucide-react'; import { actionDelimiter, actionDomainSeparator, Constants } from 'librechat-data-provider'; import type { TAttachment } from 'librechat-data-provider'; @@ -6,7 +7,6 @@ import { useLocalize, useProgress } from '~/hooks'; import { AttachmentGroup } from './Parts'; import ToolCallInfo from './ToolCallInfo'; import ProgressText from './ProgressText'; -import { Button } from '~/components'; import { logger, cn } from '~/utils'; export default function ToolCall({ diff --git a/client/src/components/Chat/Messages/Feedback.tsx b/client/src/components/Chat/Messages/Feedback.tsx index 4879808d90..a43b9700ee 100644 --- a/client/src/components/Chat/Messages/Feedback.tsx +++ b/client/src/components/Chat/Messages/Feedback.tsx @@ -1,6 +1,14 @@ import React, { useState, useCallback, useMemo, useEffect } from 'react'; import * as Ariakit from '@ariakit/react'; import { TFeedback, TFeedbackTag, getTagsForRating } from 'librechat-data-provider'; +import { + Button, + OGDialog, + OGDialogContent, + OGDialogTitle, + ThumbUpIcon, + ThumbDownIcon, +} from '@librechat/client'; import { AlertCircle, PenTool, @@ -11,14 +19,6 @@ import { Lightbulb, Search, } from 'lucide-react'; -import { - Button, - OGDialog, - OGDialogContent, - OGDialogTitle, - ThumbUpIcon, - ThumbDownIcon, -} from '~/components'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Chat/Messages/Fork.tsx b/client/src/components/Chat/Messages/Fork.tsx index 0a0c0a1141..810692c328 100644 --- a/client/src/components/Chat/Messages/Fork.tsx +++ b/client/src/components/Chat/Messages/Fork.tsx @@ -3,11 +3,11 @@ import { useRecoilState } from 'recoil'; import * as Ariakit from '@ariakit/react'; import { VisuallyHidden } from '@ariakit/react'; import { GitFork, InfoIcon } from 'lucide-react'; +import { useToastContext } from '@librechat/client'; import { ForkOptions } from 'librechat-data-provider'; import { GitCommit, GitBranchPlus, ListTree } from 'lucide-react'; import { TranslationKeys, useLocalize, useNavigateToConvo } from '~/hooks'; import { useForkConvoMutation } from '~/data-provider'; -import { useToastContext } from '~/Providers'; import { cn } from '~/utils'; import store from '~/store'; diff --git a/client/src/components/Chat/Messages/HoverButtons.tsx b/client/src/components/Chat/Messages/HoverButtons.tsx index a13266f04c..8c90673747 100644 --- a/client/src/components/Chat/Messages/HoverButtons.tsx +++ b/client/src/components/Chat/Messages/HoverButtons.tsx @@ -1,7 +1,7 @@ import React, { useState, useMemo, memo } from 'react'; import { useRecoilState } from 'recoil'; import type { TConversation, TMessage, TFeedback } from 'librechat-data-provider'; -import { EditIcon, Clipboard, CheckMark, ContinueIcon, RegenerateIcon } from '~/components'; +import { EditIcon, Clipboard, CheckMark, ContinueIcon, RegenerateIcon } from '@librechat/client'; import { useGenerationsByLatest, useLocalize } from '~/hooks'; import { Fork } from '~/components/Conversations'; import MessageAudio from './MessageAudio'; diff --git a/client/src/components/Chat/Messages/MessageParts.tsx b/client/src/components/Chat/Messages/MessageParts.tsx index 889e75d4eb..d53522e641 100644 --- a/client/src/components/Chat/Messages/MessageParts.tsx +++ b/client/src/components/Chat/Messages/MessageParts.tsx @@ -6,7 +6,6 @@ import { useMessageHelpers, useLocalize, useAttachments } from '~/hooks'; import MessageIcon from '~/components/Chat/Messages/MessageIcon'; import ContentParts from './Content/ContentParts'; import SiblingSwitch from './SiblingSwitch'; - import MultiMessage from './MultiMessage'; import HoverButtons from './HoverButtons'; import SubRow from './SubRow'; diff --git a/client/src/components/Chat/Messages/MinimalHoverButtons.tsx b/client/src/components/Chat/Messages/MinimalHoverButtons.tsx index 150cc59f7c..3f4e1711a6 100644 --- a/client/src/components/Chat/Messages/MinimalHoverButtons.tsx +++ b/client/src/components/Chat/Messages/MinimalHoverButtons.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; +import { Clipboard, CheckMark } from '@librechat/client'; import type { TMessage, TAttachment, SearchResultData } from 'librechat-data-provider'; import { useLocalize, useCopyToClipboard } from '~/hooks'; -import { Clipboard, CheckMark } from '~/components/svg'; type THoverButtons = { message: TMessage; diff --git a/client/src/components/Chat/Messages/MultiMessage.tsx b/client/src/components/Chat/Messages/MultiMessage.tsx index 9050a6149f..99733143f3 100644 --- a/client/src/components/Chat/Messages/MultiMessage.tsx +++ b/client/src/components/Chat/Messages/MultiMessage.tsx @@ -3,11 +3,8 @@ import { useEffect, useCallback } from 'react'; import { isAssistantsEndpoint } from 'librechat-data-provider'; import type { TMessage } from 'librechat-data-provider'; import type { TMessageProps } from '~/common'; - import MessageContent from '~/components/Messages/MessageContent'; - import MessageParts from './MessageParts'; - import Message from './Message'; import store from '~/store'; diff --git a/client/src/components/Chat/TemporaryChat.tsx b/client/src/components/Chat/TemporaryChat.tsx index 69e39a1a6c..a134379497 100644 --- a/client/src/components/Chat/TemporaryChat.tsx +++ b/client/src/components/Chat/TemporaryChat.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { motion } from 'framer-motion'; +import { TooltipAnchor } from '@librechat/client'; import { MessageCircleDashed } from 'lucide-react'; import { useRecoilState, useRecoilCallback } from 'recoil'; -import { TooltipAnchor } from '~/components/ui'; import { useChatContext } from '~/Providers'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Conversations/Conversations.tsx b/client/src/components/Conversations/Conversations.tsx index 46f217a83c..10203c89e3 100644 --- a/client/src/components/Conversations/Conversations.tsx +++ b/client/src/components/Conversations/Conversations.tsx @@ -1,11 +1,11 @@ import { useMemo, memo, type FC, useCallback } from 'react'; import throttle from 'lodash/throttle'; import { parseISO, isToday } from 'date-fns'; +import { Spinner, useMediaQuery } from '@librechat/client'; import { List, AutoSizer, CellMeasurer, CellMeasurerCache } from 'react-virtualized'; -import { useLocalize, TranslationKeys, useMediaQuery } from '~/hooks'; import { TConversation } from 'librechat-data-provider'; +import { useLocalize, TranslationKeys } from '~/hooks'; import { groupConversationsByDate } from '~/utils'; -import { Spinner } from '~/components/svg'; import Convo from './Convo'; interface ConversationsProps { diff --git a/client/src/components/Conversations/Convo.tsx b/client/src/components/Conversations/Convo.tsx index afd14a4cb5..3804cbf2bc 100644 --- a/client/src/components/Conversations/Convo.tsx +++ b/client/src/components/Conversations/Convo.tsx @@ -2,14 +2,14 @@ import React, { useState, useEffect, useRef, useMemo } from 'react'; import { useRecoilValue } from 'recoil'; import { useParams } from 'react-router-dom'; import { Constants } from 'librechat-data-provider'; +import { useToastContext, useMediaQuery } from '@librechat/client'; import type { TConversation } from 'librechat-data-provider'; -import { useNavigateToConvo, useMediaQuery, useLocalize } from '~/hooks'; import { useUpdateConversationMutation } from '~/data-provider'; import EndpointIcon from '~/components/Endpoints/EndpointIcon'; +import { useNavigateToConvo, useLocalize } from '~/hooks'; import { useGetEndpointsQuery } from '~/data-provider'; import { NotificationSeverity } from '~/common'; import { ConvoOptions } from './ConvoOptions'; -import { useToastContext } from '~/Providers'; import RenameForm from './RenameForm'; import ConvoLink from './ConvoLink'; import { cn } from '~/utils'; diff --git a/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx b/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx index 87211c1a66..7affbd8e93 100644 --- a/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx +++ b/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx @@ -1,6 +1,7 @@ import { useState, useId, useRef, memo, useCallback, useMemo } from 'react'; import * as Menu from '@ariakit/react/menu'; import { useParams, useNavigate } from 'react-router-dom'; +import { DropdownPopup, Spinner, useToastContext } from '@librechat/client'; import { Ellipsis, Share2, Copy, Archive, Pen, Trash } from 'lucide-react'; import type { MouseEvent } from 'react'; import { @@ -9,9 +10,8 @@ import { useArchiveConvoMutation, } from '~/data-provider'; import { useLocalize, useNavigateToConvo, useNewConvo } from '~/hooks'; -import { useToastContext, useChatContext } from '~/Providers'; -import { DropdownPopup, Spinner } from '~/components'; import { NotificationSeverity } from '~/common'; +import { useChatContext } from '~/Providers'; import DeleteButton from './DeleteButton'; import ShareButton from './ShareButton'; import { cn } from '~/utils'; diff --git a/client/src/components/Conversations/ConvoOptions/DeleteButton.tsx b/client/src/components/Conversations/ConvoOptions/DeleteButton.tsx index c40ca52959..3c34cb8c3c 100644 --- a/client/src/components/Conversations/ConvoOptions/DeleteButton.tsx +++ b/client/src/components/Conversations/ConvoOptions/DeleteButton.tsx @@ -2,7 +2,6 @@ import React, { useCallback, useState } from 'react'; import { QueryKeys } from 'librechat-data-provider'; import { useQueryClient } from '@tanstack/react-query'; import { useParams, useNavigate } from 'react-router-dom'; -import type { TMessage } from 'librechat-data-provider'; import { Button, Spinner, @@ -10,11 +9,12 @@ import { OGDialogTitle, OGDialogHeader, OGDialogContent, -} from '~/components'; + useToastContext, +} from '@librechat/client'; +import type { TMessage } from 'librechat-data-provider'; import { useDeleteConversationMutation } from '~/data-provider'; import { useLocalize, useNewConvo } from '~/hooks'; import { NotificationSeverity } from '~/common'; -import { useToastContext } from '~/Providers'; type DeleteButtonProps = { conversationId: string; diff --git a/client/src/components/Conversations/ConvoOptions/ShareButton.tsx b/client/src/components/Conversations/ConvoOptions/ShareButton.tsx index c979019f01..177dd5ae5f 100644 --- a/client/src/components/Conversations/ConvoOptions/ShareButton.tsx +++ b/client/src/components/Conversations/ConvoOptions/ShareButton.tsx @@ -2,9 +2,8 @@ import React, { useState, useEffect } from 'react'; import { QRCodeSVG } from 'qrcode.react'; import { Copy, CopyCheck } from 'lucide-react'; import { useGetSharedLinkQuery } from 'librechat-data-provider/react-query'; -import OGDialogTemplate from '~/components/ui/OGDialogTemplate'; +import { OGDialogTemplate, Button, Spinner, OGDialog } from '@librechat/client'; import { useLocalize, useCopyToClipboard } from '~/hooks'; -import { Button, Spinner, OGDialog } from '~/components'; import SharedLinkButton from './SharedLinkButton'; import { cn } from '~/utils'; diff --git a/client/src/components/Conversations/ConvoOptions/SharedLinkButton.tsx b/client/src/components/Conversations/ConvoOptions/SharedLinkButton.tsx index 4255515745..35609ba5ec 100644 --- a/client/src/components/Conversations/ConvoOptions/SharedLinkButton.tsx +++ b/client/src/components/Conversations/ConvoOptions/SharedLinkButton.tsx @@ -1,15 +1,21 @@ import { useState, useCallback } from 'react'; import { QrCode, RotateCw, Trash2 } from 'lucide-react'; +import { + Button, + OGDialog, + Spinner, + TooltipAnchor, + Label, + OGDialogTemplate, + useToastContext, +} from '@librechat/client'; import type { TSharedLinkGetResponse } from 'librechat-data-provider'; import { useCreateSharedLinkMutation, useUpdateSharedLinkMutation, useDeleteSharedLinkMutation, } from '~/data-provider'; -import { Button, OGDialog, Spinner, TooltipAnchor, Label } from '~/components'; -import OGDialogTemplate from '~/components/ui/OGDialogTemplate'; import { NotificationSeverity } from '~/common'; -import { useToastContext } from '~/Providers'; import { useLocalize } from '~/hooks'; export default function SharedLinkButton({ diff --git a/client/src/components/Endpoints/Icon.tsx b/client/src/components/Endpoints/Icon.tsx index aa9f4d16c3..acc6027697 100644 --- a/client/src/components/Endpoints/Icon.tsx +++ b/client/src/components/Endpoints/Icon.tsx @@ -1,11 +1,11 @@ import React, { memo, useState } from 'react'; +import { UserIcon } from '@librechat/client'; import type { TUser } from 'librechat-data-provider'; import type { IconProps } from '~/common'; import MessageEndpointIcon from './MessageEndpointIcon'; import { useAuthContext } from '~/hooks/AuthContext'; import useAvatar from '~/hooks/Messages/useAvatar'; -import useLocalize from '~/hooks/useLocalize'; -import { UserIcon } from '~/components/svg'; +import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; type UserAvatarProps = { @@ -48,15 +48,15 @@ const UserAvatar = memo(({ size, user, avatarSrc, username, className }: UserAva > {(!(user?.avatar ?? '') && (!(user?.username ?? '') || user?.username.trim() === '')) || imageError ? ( - renderDefaultAvatar() - ) : ( - avatar - )} + renderDefaultAvatar() + ) : ( + avatar + )} ); }); diff --git a/client/src/components/Endpoints/MessageEndpointIcon.tsx b/client/src/components/Endpoints/MessageEndpointIcon.tsx index e405c01d31..1eb859c069 100644 --- a/client/src/components/Endpoints/MessageEndpointIcon.tsx +++ b/client/src/components/Endpoints/MessageEndpointIcon.tsx @@ -12,7 +12,7 @@ import { AnthropicIcon, AzureMinimalIcon, CustomMinimalIcon, -} from '~/components/svg'; +} from '@librechat/client'; import UnknownIcon from '~/hooks/Endpoint/UnknownIcon'; import { IconProps } from '~/common'; import { cn } from '~/utils'; diff --git a/client/src/components/Endpoints/MinimalIcon.tsx b/client/src/components/Endpoints/MinimalIcon.tsx index 953859c43a..f21cad1e08 100644 --- a/client/src/components/Endpoints/MinimalIcon.tsx +++ b/client/src/components/Endpoints/MinimalIcon.tsx @@ -10,7 +10,7 @@ import { AnthropicIcon, BedrockIcon, Sparkles, -} from '~/components/svg'; +} from '@librechat/client'; import UnknownIcon from '~/hooks/Endpoint/UnknownIcon'; import { IconProps } from '~/common'; import { cn } from '~/utils'; diff --git a/client/src/components/Endpoints/SaveAsPresetDialog.tsx b/client/src/components/Endpoints/SaveAsPresetDialog.tsx index b827a2d8c2..6467a4a408 100644 --- a/client/src/components/Endpoints/SaveAsPresetDialog.tsx +++ b/client/src/components/Endpoints/SaveAsPresetDialog.tsx @@ -1,11 +1,9 @@ import React, { useEffect, useState } from 'react'; import { useCreatePresetMutation } from 'librechat-data-provider/react-query'; +import { OGDialogTemplate, OGDialog, Input, Label, useToastContext } from '@librechat/client'; import type { TEditPresetProps } from '~/common'; -import { cn, removeFocusOutlines, cleanupPreset, defaultTextProps } from '~/utils/'; -import OGDialogTemplate from '~/components/ui/OGDialogTemplate'; -import { OGDialog, Input, Label } from '~/components/ui/'; +import { cn, removeFocusOutlines, cleanupPreset, defaultTextProps } from '~/utils'; import { NotificationSeverity } from '~/common'; -import { useToastContext } from '~/Providers'; import { useLocalize } from '~/hooks'; const SaveAsPresetDialog = ({ open, onOpenChange, preset }: TEditPresetProps) => { @@ -23,7 +21,7 @@ const SaveAsPresetDialog = ({ open, onOpenChange, preset }: TEditPresetProps) => }); const toastTitle = - _preset.title ?? '' ? `\`${_preset.title}\`` : localize('com_endpoint_preset_title'); + (_preset.title ?? '') ? `\`${_preset.title}\`` : localize('com_endpoint_preset_title'); createPresetMutation.mutate(_preset, { onSuccess: () => { @@ -76,7 +74,7 @@ const SaveAsPresetDialog = ({ open, onOpenChange, preset }: TEditPresetProps) => aria-label={localize('com_endpoint_preset_name')} className={cn( defaultTextProps, - 'flex h-10 max-h-10 w-full resize-none border-border-medium px-3 py-2 ', + 'flex h-10 max-h-10 w-full resize-none border-border-medium px-3 py-2', removeFocusOutlines, )} /> diff --git a/client/src/components/Endpoints/Settings/Advanced.tsx b/client/src/components/Endpoints/Settings/Advanced.tsx index 601e9a675c..d0beaa9020 100644 --- a/client/src/components/Endpoints/Settings/Advanced.tsx +++ b/client/src/components/Endpoints/Settings/Advanced.tsx @@ -1,7 +1,5 @@ import TextareaAutosize from 'react-textarea-autosize'; import { ImageDetail, imageDetailNumeric, imageDetailValue } from 'librechat-data-provider'; -import type { ValueType } from '@rc-component/mini-decimal'; -import type { TModelSelectProps } from '~/common'; import { Input, Label, @@ -10,8 +8,10 @@ import { HoverCard, InputNumber, HoverCardTrigger, -} from '~/components/ui'; -import { cn, defaultTextProps, optionText, removeFocusOutlines } from '~/utils/'; +} from '@librechat/client'; +import type { ValueType } from '@rc-component/mini-decimal'; +import type { TModelSelectProps } from '~/common'; +import { cn, defaultTextProps, optionText, removeFocusOutlines } from '~/utils'; import { useLocalize, useDebouncedInput } from '~/hooks'; import OptionHover from './OptionHover'; import { ESide } from '~/common'; @@ -109,7 +109,7 @@ export default function Settings({ placeholder={localize('com_endpoint_openai_prompt_prefix_placeholder')} className={cn( defaultTextProps, - 'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2 ', + 'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2', )} /> diff --git a/client/src/components/Endpoints/Settings/AgentSettings.tsx b/client/src/components/Endpoints/Settings/AgentSettings.tsx index 8ba20f2508..f41a8bc19e 100644 --- a/client/src/components/Endpoints/Settings/AgentSettings.tsx +++ b/client/src/components/Endpoints/Settings/AgentSettings.tsx @@ -1,4 +1,3 @@ -import type { TModelSelectProps } from '~/common'; import { Switch, Label, @@ -7,7 +6,8 @@ import { InputNumber, SelectDropDown, HoverCardTrigger, -} from '~/components'; +} from '@librechat/client'; +import type { TModelSelectProps } from '~/common'; import { cn, optionText, defaultTextProps, removeFocusRings } from '~/utils'; import OptionHover from './OptionHover'; import { useLocalize } from '~/hooks'; diff --git a/client/src/components/Endpoints/Settings/Assistants.tsx b/client/src/components/Endpoints/Settings/Assistants.tsx index a35f9f7eb3..1ae0f8cb41 100644 --- a/client/src/components/Endpoints/Settings/Assistants.tsx +++ b/client/src/components/Endpoints/Settings/Assistants.tsx @@ -1,5 +1,6 @@ import { useState, useMemo, useEffect } from 'react'; import TextareaAutosize from 'react-textarea-autosize'; +import { Label, HoverCard, SelectDropDown, HoverCardTrigger } from '@librechat/client'; import type { Assistant, TPreset } from 'librechat-data-provider'; import type { TModelSelectProps, Option } from '~/common'; import { @@ -9,7 +10,6 @@ import { mapAssistants, createDropdownSetter, } from '~/utils'; -import { Label, HoverCard, SelectDropDown, HoverCardTrigger } from '~/components/ui'; import { useLocalize, useDebouncedInput, useAssistantListMap } from '~/hooks'; import OptionHover from './OptionHover'; import { ESide } from '~/common'; @@ -121,6 +121,7 @@ export default function Settings({ conversation, setOption, models, readonly }:
@@ -178,7 +179,7 @@ export default function Settings({ conversation, setOption, models, readonly }: placeholder={localize('com_endpoint_instructions_assistants_placeholder')} className={cn( defaultTextProps, - 'flex max-h-[240px] min-h-[80px] w-full resize-none px-3 py-2 ', + 'flex max-h-[240px] min-h-[80px] w-full resize-none px-3 py-2', )} /> diff --git a/client/src/components/Endpoints/Settings/Examples.tsx b/client/src/components/Endpoints/Settings/Examples.tsx index 98dac9ea94..10f6236855 100644 --- a/client/src/components/Endpoints/Settings/Examples.tsx +++ b/client/src/components/Endpoints/Settings/Examples.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { Plus, Minus } from 'lucide-react'; +import { Button, Label } from '@librechat/client'; import TextareaAutosize from 'react-textarea-autosize'; import type { TExample } from 'librechat-data-provider'; import type { TSetExample } from '~/common'; -import { Button, Label } from '~/components/ui'; import { cn, defaultTextProps } from '~/utils/'; import { useLocalize } from '~/hooks'; @@ -42,7 +42,7 @@ function Examples({ readonly, examples, setExample, addExample, removeExample }: placeholder="Set example input. Example is ignored if empty." className={cn( defaultTextProps, - 'flex max-h-[138px] min-h-[75px] w-full resize-none px-3 py-2 ', + 'flex max-h-[138px] min-h-[75px] w-full resize-none px-3 py-2', )} /> @@ -67,7 +67,7 @@ function Examples({ readonly, examples, setExample, addExample, removeExample }: placeholder={'Set example output. Example is ignored if empty.'} className={cn( defaultTextProps, - 'flex max-h-[300px] min-h-[75px] w-full resize-none px-3 py-2 ', + 'flex max-h-[300px] min-h-[75px] w-full resize-none px-3 py-2', )} /> diff --git a/client/src/components/Endpoints/Settings/Google.tsx b/client/src/components/Endpoints/Settings/Google.tsx index 063d5f098e..6e513c1791 100644 --- a/client/src/components/Endpoints/Settings/Google.tsx +++ b/client/src/components/Endpoints/Settings/Google.tsx @@ -1,6 +1,5 @@ import TextareaAutosize from 'react-textarea-autosize'; import { EModelEndpoint, endpointSettings } from 'librechat-data-provider'; -import type { TModelSelectProps, OnInputNumberChange } from '~/common'; import { Input, Label, @@ -9,7 +8,8 @@ import { InputNumber, SelectDropDown, HoverCardTrigger, -} from '~/components/ui'; +} from '@librechat/client'; +import type { TModelSelectProps, OnInputNumberChange } from '~/common'; import { cn, defaultTextProps, optionText, removeFocusOutlines, removeFocusRings } from '~/utils'; import OptionHoverAlt from '~/components/SidePanel/Parameters/OptionHover'; import { useLocalize, useDebouncedInput } from '~/hooks'; @@ -55,6 +55,7 @@ export default function Settings({ conversation, setOption, models, readonly }:
@@ -221,7 +222,7 @@ export default function Settings({ conversation, setOption, models, readonly }: {localize('com_endpoint_max_output_tokens')}{' '} - ({localize('com_endpoint_default_with_num', { 0: google.maxOutputTokens.default + '' })}) + ( + {localize('com_endpoint_default_with_num', { + 0: google.maxOutputTokens.default + '', + })} + )
diff --git a/client/src/components/Files/ActionButton.tsx b/client/src/components/Files/ActionButton.tsx index 03f58da6c8..0d4c59f8d7 100644 --- a/client/src/components/Files/ActionButton.tsx +++ b/client/src/components/Files/ActionButton.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Button } from '~/components/ui'; +import { Button } from '@librechat/client'; import { useLocalize } from '~/hooks'; type ActionButtonProps = { diff --git a/client/src/components/Files/DeleteIconButton.tsx b/client/src/components/Files/DeleteIconButton.tsx index 50ac461bab..0173a3d577 100644 --- a/client/src/components/Files/DeleteIconButton.tsx +++ b/client/src/components/Files/DeleteIconButton.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { CrossIcon, TrashIcon } from '~/components/svg'; -import { Button } from '~/components/ui'; +import { Button, TrashIcon } from '@librechat/client'; type DeleteIconButtonProps = { onClick: () => void; diff --git a/client/src/components/Files/FileList/DataTableFile.tsx b/client/src/components/Files/FileList/DataTableFile.tsx index d64699e2ea..269001d0a3 100644 --- a/client/src/components/Files/FileList/DataTableFile.tsx +++ b/client/src/components/Files/FileList/DataTableFile.tsx @@ -16,27 +16,28 @@ import type { ColumnFiltersState, } from '@tanstack/react-table'; import { FileContext } from 'librechat-data-provider'; -import type { AugmentedColumnDef } from '~/common'; -import type { TFile } from 'librechat-data-provider'; import { Input, Table, Button, + Spinner, TableRow, TableBody, TableCell, TableHead, + TrashIcon, TableHeader, DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, DropdownMenuCheckboxItem, -} from '~/components/ui'; +} from '@librechat/client'; +import type { TFile } from 'librechat-data-provider'; +import type { AugmentedColumnDef } from '~/common'; import ActionButton from '~/components/Files/ActionButton'; import { useDeleteFilesFromTable } from '~/hooks/Files'; -import { TrashIcon, Spinner } from '~/components/svg'; import UploadFileButton from './UploadFileButton'; -import useLocalize from '~/hooks/useLocalize'; +import { useLocalize } from '~/hooks'; import store from '~/store'; interface DataTableProps { diff --git a/client/src/components/Files/FileList/FileListItem.tsx b/client/src/components/Files/FileList/FileListItem.tsx index 5760b2917b..e7ee5d1d29 100644 --- a/client/src/components/Files/FileList/FileListItem.tsx +++ b/client/src/components/Files/FileList/FileListItem.tsx @@ -1,7 +1,6 @@ -import type { TFile } from 'librechat-data-provider'; import React from 'react'; -import { TrashIcon } from '~/components/svg'; -import { Button } from '~/components/ui'; +import { Button, TrashIcon } from '@librechat/client'; +import type { TFile } from 'librechat-data-provider'; type FileListItemProps = { file: TFile; diff --git a/client/src/components/Files/FileList/FileListItem2.tsx b/client/src/components/Files/FileList/FileListItem2.tsx index 2b8ff1d6a9..b692a69625 100644 --- a/client/src/components/Files/FileList/FileListItem2.tsx +++ b/client/src/components/Files/FileList/FileListItem2.tsx @@ -1,9 +1,8 @@ -import type { TFile } from 'librechat-data-provider'; -import { FileIcon, PlusIcon } from 'lucide-react'; import React from 'react'; +import { FileIcon, PlusIcon } from 'lucide-react'; +import { Button, DotsIcon, TrashIcon } from '@librechat/client'; +import type { TFile } from 'librechat-data-provider'; import { useNavigate } from 'react-router-dom'; -import { DotsIcon, TrashIcon } from '~/components/svg'; -import { Button } from '~/components/ui'; type FileListItemProps = { file: TFile; diff --git a/client/src/components/Files/FileList/FilePreview.tsx b/client/src/components/Files/FileList/FilePreview.tsx index e0c2624b34..0b416fa704 100644 --- a/client/src/components/Files/FileList/FilePreview.tsx +++ b/client/src/components/Files/FileList/FilePreview.tsx @@ -1,11 +1,10 @@ -import { TFile } from 'librechat-data-provider/dist/types'; import React, { useState } from 'react'; -import { TThread, TVectorStore } from '~/common'; -import { CheckMark, TrashIcon } from '~/components/svg'; -import { Button } from '~/components/ui'; -import DeleteIconButton from '../DeleteIconButton'; +import { TFile } from 'librechat-data-provider/dist/types'; +import { CheckMark, TrashIcon, Button } from '@librechat/client'; import VectorStoreButton from '../VectorStore/VectorStoreButton'; import { CircleIcon, Clock3Icon, InfoIcon } from 'lucide-react'; +import DeleteIconButton from '../DeleteIconButton'; +import { TThread, TVectorStore } from '~/common'; import { useParams } from 'react-router-dom'; const tempFile: TFile = { diff --git a/client/src/components/Files/FileList/FileSidePanel.tsx b/client/src/components/Files/FileList/FileSidePanel.tsx index e1552d2a8d..5b59678426 100644 --- a/client/src/components/Files/FileList/FileSidePanel.tsx +++ b/client/src/components/Files/FileList/FileSidePanel.tsx @@ -1,10 +1,9 @@ import React from 'react'; import FileList from './FileList'; +import { Button, Input } from '@librechat/client'; import { TFile } from 'librechat-data-provider/dist/types'; -import FilesSectionSelector from '../FilesSectionSelector'; -import { Button, Input } from '~/components/ui'; -import { ListFilter } from 'lucide-react'; import UploadFileButton from './UploadFileButton'; +import { ListFilter } from 'lucide-react'; import { useLocalize } from '~/hooks'; const fakeFiles = [ diff --git a/client/src/components/Files/FileList/FileTableColumns.tsx b/client/src/components/Files/FileList/FileTableColumns.tsx index 8e670aa805..754cb061db 100644 --- a/client/src/components/Files/FileList/FileTableColumns.tsx +++ b/client/src/components/Files/FileList/FileTableColumns.tsx @@ -1,13 +1,10 @@ /* eslint-disable react-hooks/rules-of-hooks */ -import { FileSources, FileContext } from 'librechat-data-provider'; +import { PlusIcon } from 'lucide-react'; +import { Button, Checkbox, DotsIcon, FileIcon } from '@librechat/client'; import type { ColumnDef } from '@tanstack/react-table'; import type { TFile } from 'librechat-data-provider'; -import { CrossIcon, DotsIcon } from '~/components/svg'; -import { Button, Checkbox } from '~/components/ui'; import { formatDate, getFileType } from '~/utils'; -import useLocalize from '~/hooks/useLocalize'; -import FileIcon from '~/components/svg/Files/FileIcon'; -import { PlusIcon } from 'lucide-react'; +import { useLocalize } from '~/hooks'; export const fileTableColumns: ColumnDef[] = [ { diff --git a/client/src/components/Files/FileList/UploadFileButton.tsx b/client/src/components/Files/FileList/UploadFileButton.tsx index e2b8acdd09..0823f706e3 100644 --- a/client/src/components/Files/FileList/UploadFileButton.tsx +++ b/client/src/components/Files/FileList/UploadFileButton.tsx @@ -1,6 +1,6 @@ -import { PlusIcon } from 'lucide-react'; import React from 'react'; -import { Button } from '~/components/ui'; +import { PlusIcon } from 'lucide-react'; +import { Button } from '@librechat/client'; type UploadFileProps = { onClick: () => void; diff --git a/client/src/components/Files/FileList/UploadFileModal.tsx b/client/src/components/Files/FileList/UploadFileModal.tsx index 4e2e31e278..7be59184a5 100644 --- a/client/src/components/Files/FileList/UploadFileModal.tsx +++ b/client/src/components/Files/FileList/UploadFileModal.tsx @@ -1,6 +1,5 @@ import React, { useState, ChangeEvent } from 'react'; -import AttachFile from '~/components/Chat/Input/Files/AttachFile'; -import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, Input } from '~/components/ui'; +import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, Input } from '@librechat/client'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; diff --git a/client/src/components/Files/VectorStore/VectorStoreButton.tsx b/client/src/components/Files/VectorStore/VectorStoreButton.tsx index dc3e34c4f2..6eb0f35a26 100644 --- a/client/src/components/Files/VectorStore/VectorStoreButton.tsx +++ b/client/src/components/Files/VectorStore/VectorStoreButton.tsx @@ -1,6 +1,6 @@ -import { PlusIcon } from 'lucide-react'; import React from 'react'; -import { Button } from '~/components/ui'; +import { PlusIcon } from 'lucide-react'; +import { Button } from '@librechat/client'; type VectorStoreButtonProps = { onClick: () => void; diff --git a/client/src/components/Files/VectorStore/VectorStoreListItem.tsx b/client/src/components/Files/VectorStore/VectorStoreListItem.tsx index 720ebd0afe..66a54b1593 100644 --- a/client/src/components/Files/VectorStore/VectorStoreListItem.tsx +++ b/client/src/components/Files/VectorStore/VectorStoreListItem.tsx @@ -1,8 +1,7 @@ import React from 'react'; import { useNavigate } from 'react-router-dom'; +import { Button, DotsIcon, TrashIcon } from '@librechat/client'; import { TVectorStore } from '~/common'; -import { DotsIcon, TrashIcon } from '~/components/svg'; -import { Button } from '~/components/ui'; type VectorStoreListItemProps = { vectorStore: TVectorStore; diff --git a/client/src/components/Files/VectorStore/VectorStorePreview.tsx b/client/src/components/Files/VectorStore/VectorStorePreview.tsx index c1d70107fa..d75a827425 100644 --- a/client/src/components/Files/VectorStore/VectorStorePreview.tsx +++ b/client/src/components/Files/VectorStore/VectorStorePreview.tsx @@ -1,7 +1,6 @@ import React, { useState } from 'react'; import DeleteIconButton from '../DeleteIconButton'; -import { Button } from '~/components/ui'; -import { TrashIcon } from '~/components/svg'; +import { TrashIcon, Button } from '@librechat/client'; import { TFile } from 'librechat-data-provider/dist/types'; import UploadFileButton from '../FileList/UploadFileButton'; import UploadFileModal from '../FileList/UploadFileModal'; @@ -99,7 +98,7 @@ export default function VectorStorePreview() { const params = useParams(); return ( -
+
VECTOR STORE diff --git a/client/src/components/Files/VectorStore/VectorStoreSidePanel.tsx b/client/src/components/Files/VectorStore/VectorStoreSidePanel.tsx index b1d0fe166a..0616bcc7ba 100644 --- a/client/src/components/Files/VectorStore/VectorStoreSidePanel.tsx +++ b/client/src/components/Files/VectorStore/VectorStoreSidePanel.tsx @@ -1,12 +1,9 @@ import React from 'react'; +import { ListFilter } from 'lucide-react'; +import { Button, Input } from '@librechat/client'; +import VectorStoreButton from './VectorStoreButton'; import VectorStoreList from './VectorStoreList'; import { TVectorStore } from '~/common'; -import VectorStoreButton from './VectorStoreButton'; -import { Button, Input } from '~/components/ui'; -import FilesSectionSelector from '../FilesSectionSelector'; -import ActionButton from '../ActionButton'; -import DeleteIconButton from '../DeleteIconButton'; -import { ListFilter } from 'lucide-react'; import { useLocalize } from '~/hooks'; const fakeVectorStores: TVectorStore[] = [ diff --git a/client/src/components/Input/Generations/Regenerate.tsx b/client/src/components/Input/Generations/Regenerate.tsx index 83eabf493f..715168cb92 100644 --- a/client/src/components/Input/Generations/Regenerate.tsx +++ b/client/src/components/Input/Generations/Regenerate.tsx @@ -1,7 +1,7 @@ +import { RegenerateIcon } from '@librechat/client'; import type { TGenButtonProps } from '~/common'; -import { RegenerateIcon } from '~/components/svg'; -import Button from './Button'; import { useLocalize } from '~/hooks'; +import Button from './Button'; export default function Regenerate({ onClick }: TGenButtonProps) { const localize = useLocalize(); diff --git a/client/src/components/Input/Generations/Stop.tsx b/client/src/components/Input/Generations/Stop.tsx index 8214152c47..d66baa9450 100644 --- a/client/src/components/Input/Generations/Stop.tsx +++ b/client/src/components/Input/Generations/Stop.tsx @@ -1,14 +1,14 @@ +import { StopGeneratingIcon } from '@librechat/client'; import type { TGenButtonProps } from '~/common'; -import { StopGeneratingIcon } from '~/components/svg'; -import Button from './Button'; import { useLocalize } from '~/hooks'; +import Button from './Button'; export default function Stop({ onClick }: TGenButtonProps) { const localize = useLocalize(); return ( ); diff --git a/client/src/components/Input/ModelSelect/Anthropic.tsx b/client/src/components/Input/ModelSelect/Anthropic.tsx index bbe634478b..38669871ea 100644 --- a/client/src/components/Input/ModelSelect/Anthropic.tsx +++ b/client/src/components/Input/ModelSelect/Anthropic.tsx @@ -1,4 +1,4 @@ -import { SelectDropDown, SelectDropDownPop } from '~/components/ui'; +import { SelectDropDown, SelectDropDownPop } from '@librechat/client'; import type { TModelSelectProps } from '~/common'; import { cn, cardStyle } from '~/utils/'; diff --git a/client/src/components/Input/ModelSelect/ChatGPT.tsx b/client/src/components/Input/ModelSelect/ChatGPT.tsx index 89c884429e..1405bcdbd6 100644 --- a/client/src/components/Input/ModelSelect/ChatGPT.tsx +++ b/client/src/components/Input/ModelSelect/ChatGPT.tsx @@ -1,4 +1,4 @@ -import { SelectDropDown, SelectDropDownPop } from '~/components/ui'; +import { SelectDropDown, SelectDropDownPop } from '@librechat/client'; import type { TModelSelectProps } from '~/common'; import { cn, cardStyle } from '~/utils/'; diff --git a/client/src/components/Input/ModelSelect/Google.tsx b/client/src/components/Input/ModelSelect/Google.tsx index eab7f95393..eb04adc9e4 100644 --- a/client/src/components/Input/ModelSelect/Google.tsx +++ b/client/src/components/Input/ModelSelect/Google.tsx @@ -1,4 +1,4 @@ -import { SelectDropDown, SelectDropDownPop } from '~/components/ui'; +import { SelectDropDown, SelectDropDownPop } from '@librechat/client'; import type { TModelSelectProps } from '~/common'; import { cn, cardStyle } from '~/utils/'; diff --git a/client/src/components/ui/MultiSelectDropDown.tsx b/client/src/components/Input/ModelSelect/MultiSelectDropDown.tsx similarity index 97% rename from client/src/components/ui/MultiSelectDropDown.tsx rename to client/src/components/Input/ModelSelect/MultiSelectDropDown.tsx index 0e2724dcf8..6a1deee152 100644 --- a/client/src/components/ui/MultiSelectDropDown.tsx +++ b/client/src/components/Input/ModelSelect/MultiSelectDropDown.tsx @@ -1,4 +1,6 @@ import React, { useState, useRef } from 'react'; +import { Wrench, ArrowRight } from 'lucide-react'; +import { CheckMark, useOnClickOutside, useMultiSearch } from '@librechat/client'; import { Listbox, ListboxButton, @@ -7,12 +9,8 @@ import { ListboxOption, Transition, } from '@headlessui/react'; -import { Wrench, ArrowRight } from 'lucide-react'; -import { CheckMark } from '~/components/svg'; -import useOnClickOutside from '~/hooks/useOnClickOutside'; -import { useMultiSearch } from './MultiSearch'; -import { cn } from '~/utils/'; import type { TPlugin } from 'librechat-data-provider'; +import { cn } from '~/utils/'; export type TMultiSelectDropDownProps = { title?: string; @@ -142,7 +140,7 @@ function MultiSelectDropDown({ viewBox="0 0 24 24" strokeLinecap="round" strokeLinejoin="round" - className="h-4 w-4 text-gray-400" + className="h-4 w-4 text-gray-400" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg" diff --git a/client/src/components/ui/MultiSelectPop.tsx b/client/src/components/Input/ModelSelect/MultiSelectPop.tsx similarity index 95% rename from client/src/components/ui/MultiSelectPop.tsx rename to client/src/components/Input/ModelSelect/MultiSelectPop.tsx index 3f43772915..8421c673ae 100644 --- a/client/src/components/ui/MultiSelectPop.tsx +++ b/client/src/components/Input/ModelSelect/MultiSelectPop.tsx @@ -1,8 +1,8 @@ import { Wrench } from 'lucide-react'; +import { useMultiSearch } from '@librechat/client'; import { Root, Trigger, Content, Portal } from '@radix-ui/react-popover'; import type { TPlugin } from 'librechat-data-provider'; import MenuItem from '~/components/Chat/Menus/UI/MenuItem'; -import { useMultiSearch } from './MultiSearch'; import { cn } from '~/utils/'; type SelectDropDownProps = { @@ -32,8 +32,6 @@ function MultiSelectPop({ optionValueKey = 'value', searchPlaceholder, }: SelectDropDownProps) { - // const localize = useLocalize(); - const title = _title; const excludeIds = ['select-plugin', 'plugins-label', 'selected-plugins']; @@ -54,14 +52,14 @@ function MultiSelectPop({ - -
- )} -
-
-
- setIsHovering(true)} - onMouseLeave={() => setIsHovering(false)} - className={`slider-thumb h-2 w-full appearance-none rounded-lg bg-gradient-to-r from-gray-500 to-gray-500 bg-no-repeat focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 ${ - disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer' - }`} - tabIndex={0} - style={{ - backgroundSize: '50% 100%', - backgroundPosition: 'left', - }} - aria-valuemin={min} - aria-valuemax={max} - aria-valuenow={value} - aria-valuetext={`${value.toFixed(decimalPlaces).replace('-0.00', '0.00')}`} - disabled={disabled} - /> - {isHovering ? ( -
- {min} - {max} -
- ) : ( -
- )} -
-
- ); -}; - -export default React.memo(ModelParameters); diff --git a/client/src/components/ui/Prompt.tsx b/client/src/components/ui/Prompt.tsx deleted file mode 100644 index 3453ce436a..0000000000 --- a/client/src/components/ui/Prompt.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { useLocalize } from '~/hooks'; - -export default function Prompt({ title, prompt }: { title: string; prompt: string }) { - const localize = useLocalize(); - - return ( -
-

- {title} -

- - {localize('com_ui_use_prompt')} → -
- ); -} diff --git a/client/src/components/ui/Slider.tsx b/client/src/components/ui/Slider.tsx deleted file mode 100644 index 74908b4e62..0000000000 --- a/client/src/components/ui/Slider.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import * as React from 'react'; -import * as SliderPrimitive from '@radix-ui/react-slider'; -import { cn } from '~/utils'; - -const Slider = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { onDoubleClick?: () => void } - >(({ className, onDoubleClick, ...props }, ref) => ( - - - - - - - )); -Slider.displayName = SliderPrimitive.Root.displayName; - -export { Slider }; diff --git a/client/src/components/ui/TermsAndConditionsModal.tsx b/client/src/components/ui/TermsAndConditionsModal.tsx index bdf6e8fb3e..0736e422f1 100644 --- a/client/src/components/ui/TermsAndConditionsModal.tsx +++ b/client/src/components/ui/TermsAndConditionsModal.tsx @@ -1,10 +1,8 @@ import { useMemo } from 'react'; +import { OGDialog, DialogTemplate, useToastContext } from '@librechat/client'; import type { TTermsOfService } from 'librechat-data-provider'; import MarkdownLite from '~/components/Chat/Messages/Content/MarkdownLite'; -import DialogTemplate from '~/components/ui/DialogTemplate'; import { useAcceptTermsMutation } from '~/data-provider'; -import { useToastContext } from '~/Providers'; -import { OGDialog } from '~/components/ui'; import { useLocalize } from '~/hooks'; const TermsAndConditionsModal = ({ @@ -73,7 +71,7 @@ const TermsAndConditionsModal = ({ main={
{ const localize = useLocalize(); diff --git a/client/src/hooks/Files/useFileHandling.ts b/client/src/hooks/Files/useFileHandling.ts index 3438417769..8c8f33e57e 100644 --- a/client/src/hooks/Files/useFileHandling.ts +++ b/client/src/hooks/Files/useFileHandling.ts @@ -1,5 +1,6 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { v4 } from 'uuid'; +import { useToastContext } from '@librechat/client'; import { useQueryClient } from '@tanstack/react-query'; import { QueryKeys, @@ -17,7 +18,6 @@ import { useGetFileConfig, useUploadFileMutation } from '~/data-provider'; import useLocalize, { TranslationKeys } from '~/hooks/useLocalize'; import { useDelayedUploadToast } from './useDelayedUploadToast'; import { processFileForUpload } from '~/utils/heicConverter'; -import { useToastContext } from '~/Providers/ToastContext'; import { useChatContext } from '~/Providers/ChatContext'; import { logger, validateFiles } from '~/utils'; import useClientResize from './useClientResize'; diff --git a/client/src/hooks/Input/index.ts b/client/src/hooks/Input/index.ts index bfc40ebb3e..dc959e3577 100644 --- a/client/src/hooks/Input/index.ts +++ b/client/src/hooks/Input/index.ts @@ -2,7 +2,6 @@ export * from './useAutoSave'; export { default as useUserKey } from './useUserKey'; export { default as useDebounce } from './useDebounce'; export { default as useTextarea } from './useTextarea'; -export { default as useCombobox } from './useCombobox'; export { default as useQueryParams } from './useQueryParams'; export { default as useHandleKeyUp } from './useHandleKeyUp'; export { default as useRequiresKey } from './useRequiresKey'; diff --git a/client/src/hooks/Input/useSpeechToTextBrowser.ts b/client/src/hooks/Input/useSpeechToTextBrowser.ts index 1d31c3348d..d4c301367f 100644 --- a/client/src/hooks/Input/useSpeechToTextBrowser.ts +++ b/client/src/hooks/Input/useSpeechToTextBrowser.ts @@ -1,8 +1,8 @@ import { useEffect, useRef, useMemo } from 'react'; import { useRecoilState } from 'recoil'; +import { useToastContext } from '@librechat/client'; import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition'; import useGetAudioSettings from './useGetAudioSettings'; -import { useToastContext } from '~/Providers'; import store from '~/store'; const useSpeechToTextBrowser = ( diff --git a/client/src/hooks/Input/useSpeechToTextExternal.ts b/client/src/hooks/Input/useSpeechToTextExternal.ts index 3160696e9c..6571a0911d 100644 --- a/client/src/hooks/Input/useSpeechToTextExternal.ts +++ b/client/src/hooks/Input/useSpeechToTextExternal.ts @@ -1,8 +1,8 @@ import { useState, useEffect, useRef } from 'react'; import { useRecoilState } from 'recoil'; +import { useToastContext } from '@librechat/client'; import { useSpeechToTextMutation } from '~/data-provider'; import useGetAudioSettings from './useGetAudioSettings'; -import { useToastContext } from '~/Providers'; import store from '~/store'; const useSpeechToTextExternal = ( @@ -107,7 +107,7 @@ const useSpeechToTextExternal = ( }); setPermission(true); audioStream.current = streamData ?? null; - } catch (err) { + } catch { setPermission(false); } }; @@ -268,6 +268,7 @@ const useSpeechToTextExternal = ( return () => { window.removeEventListener('keydown', handleKeyDown); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isListening]); return { diff --git a/client/src/hooks/Input/useTextToSpeechExternal.ts b/client/src/hooks/Input/useTextToSpeechExternal.ts index cf8edb0382..99c1a2344e 100644 --- a/client/src/hooks/Input/useTextToSpeechExternal.ts +++ b/client/src/hooks/Input/useTextToSpeechExternal.ts @@ -1,8 +1,8 @@ -import { useRecoilValue } from 'recoil'; import { useState, useMemo, useRef, useCallback, useEffect } from 'react'; +import { useRecoilValue } from 'recoil'; +import { useToastContext } from '@librechat/client'; import { useTextToSpeechMutation, useVoicesQuery } from '~/data-provider'; -import { useToastContext } from '~/Providers/ToastContext'; -import useLocalize from '~/hooks/useLocalize'; +import { useLocalize } from '~/hooks'; import store from '~/store'; const createFormData = (text: string, voice: string) => { diff --git a/client/src/hooks/Input/useTextarea.ts b/client/src/hooks/Input/useTextarea.ts index 7a0711e7ae..7d32cbbe02 100644 --- a/client/src/hooks/Input/useTextarea.ts +++ b/client/src/hooks/Input/useTextarea.ts @@ -16,8 +16,8 @@ import useGetSender from '~/hooks/Conversations/useGetSender'; import useFileHandling from '~/hooks/Files/useFileHandling'; import { useInteractionHealthCheck } from '~/data-provider'; import { useChatContext } from '~/Providers/ChatContext'; -import useLocalize from '~/hooks/useLocalize'; import { globalAudioId } from '~/common'; +import { useLocalize } from '~/hooks'; import store from '~/store'; type KeyEvent = KeyboardEvent; diff --git a/client/src/hooks/MCP/useMCPServerInitialization.ts b/client/src/hooks/MCP/useMCPServerInitialization.ts index ec5ab2cc05..8a73c7d490 100644 --- a/client/src/hooks/MCP/useMCPServerInitialization.ts +++ b/client/src/hooks/MCP/useMCPServerInitialization.ts @@ -1,12 +1,12 @@ import { useCallback, useState, useEffect, useMemo } from 'react'; -import { useQueryClient } from '@tanstack/react-query'; +import { useToastContext } from '@librechat/client'; import { QueryKeys } from 'librechat-data-provider'; +import { useQueryClient } from '@tanstack/react-query'; import { useReinitializeMCPServerMutation, useCancelMCPOAuthMutation, } from 'librechat-data-provider/react-query'; import { useMCPConnectionStatusQuery } from '~/data-provider/Tools/queries'; -import { useToastContext } from '~/Providers'; import { useLocalize } from '~/hooks'; import { logger } from '~/utils'; diff --git a/client/src/hooks/MCP/useMCPServerManager.ts b/client/src/hooks/MCP/useMCPServerManager.ts index 95891b47e5..a7d2c7c98c 100644 --- a/client/src/hooks/MCP/useMCPServerManager.ts +++ b/client/src/hooks/MCP/useMCPServerManager.ts @@ -1,12 +1,12 @@ +import { useCallback, useState, useMemo, useRef } from 'react'; +import { useToastContext } from '@librechat/client'; import { useQueryClient } from '@tanstack/react-query'; import { Constants, QueryKeys } from 'librechat-data-provider'; -import { useCallback, useState, useMemo, useRef } from 'react'; import { useUpdateUserPluginsMutation } from 'librechat-data-provider/react-query'; -import { useMCPServerInitialization } from '~/hooks/MCP/useMCPServerInitialization'; -import type { ConfigFieldDetail } from '~/components/ui/MCP/MCPConfigDialog'; import type { TUpdateUserPlugins, TPlugin } from 'librechat-data-provider'; -import { useToastContext, useBadgeRowContext } from '~/Providers'; -import { useLocalize } from '~/hooks'; +import type { ConfigFieldDetail } from '~/components/MCP/MCPConfigDialog'; +import { useLocalize, useMCPServerInitialization } from '~/hooks'; +import { useBadgeRowContext } from '~/Providers'; export function useMCPServerManager() { const localize = useLocalize(); diff --git a/client/src/hooks/Nav/useSideNavLinks.ts b/client/src/hooks/Nav/useSideNavLinks.ts index 728b856735..7345415215 100644 --- a/client/src/hooks/Nav/useSideNavLinks.ts +++ b/client/src/hooks/Nav/useSideNavLinks.ts @@ -1,4 +1,5 @@ import { useMemo } from 'react'; +import { Blocks, MCPIcon, AttachmentIcon } from '@librechat/client'; import { MessageSquareQuote, ArrowRightToLine, Settings2, Database, Bookmark } from 'lucide-react'; import { isAssistantsEndpoint, @@ -15,7 +16,6 @@ import BookmarkPanel from '~/components/SidePanel/Bookmarks/BookmarkPanel'; import MemoryViewer from '~/components/SidePanel/Memories/MemoryViewer'; import PanelSwitch from '~/components/SidePanel/Builder/PanelSwitch'; import PromptsAccordion from '~/components/Prompts/PromptsAccordion'; -import { Blocks, MCPIcon, AttachmentIcon } from '~/components/svg'; import Parameters from '~/components/SidePanel/Parameters/Panel'; import FilesPanel from '~/components/SidePanel/Files/Panel'; import MCPPanel from '~/components/SidePanel/MCP/MCPPanel'; diff --git a/client/src/hooks/Plugins/useAuthCodeTool.ts b/client/src/hooks/Plugins/useAuthCodeTool.ts index b33e05c169..f523fd01ef 100644 --- a/client/src/hooks/Plugins/useAuthCodeTool.ts +++ b/client/src/hooks/Plugins/useAuthCodeTool.ts @@ -2,10 +2,8 @@ import { useCallback } from 'react'; import { useQueryClient } from '@tanstack/react-query'; import { AuthType, Tools, QueryKeys } from 'librechat-data-provider'; import { useUpdateUserPluginsMutation } from 'librechat-data-provider/react-query'; -// import { useToastContext } from '~/Providers'; const useAuthCodeTool = (options?: { isEntityTool: boolean }) => { - // const { showToast } = useToastContext(); const queryClient = useQueryClient(); const isEntityTool = options?.isEntityTool ?? true; const updateUserPlugins = useUpdateUserPluginsMutation({ diff --git a/client/src/hooks/Prompts/useCategories.tsx b/client/src/hooks/Prompts/useCategories.tsx index a5083f8ed0..b4611e8dcc 100644 --- a/client/src/hooks/Prompts/useCategories.tsx +++ b/client/src/hooks/Prompts/useCategories.tsx @@ -1,6 +1,6 @@ import { useGetCategories } from '~/data-provider'; import CategoryIcon from '~/components/Prompts/Groups/CategoryIcon'; -import useLocalize, { TranslationKeys } from '~/hooks/useLocalize'; +import { useLocalize, TranslationKeys } from '~/hooks'; const loadingCategories: { label: TranslationKeys; value: string }[] = [ { diff --git a/client/src/hooks/ScreenshotContext.tsx b/client/src/hooks/ScreenshotContext.tsx index 2f9069c5f1..435327e571 100644 --- a/client/src/hooks/ScreenshotContext.tsx +++ b/client/src/hooks/ScreenshotContext.tsx @@ -1,6 +1,6 @@ import { createContext, useRef, useContext, RefObject } from 'react'; import { toCanvas } from 'html-to-image'; -import { ThemeContext } from '~/hooks/ThemeContext'; +import { ThemeContext } from '@librechat/client'; type ScreenshotContextType = { ref?: RefObject; diff --git a/client/src/hooks/index.ts b/client/src/hooks/index.ts index 83cdb7fbc4..92fd39e370 100644 --- a/client/src/hooks/index.ts +++ b/client/src/hooks/index.ts @@ -8,30 +8,26 @@ export * from './Nav'; export * from './Files'; export * from './Generic'; export * from './Input'; +export * from './MCP'; export * from './Messages'; export * from './Plugins'; export * from './Prompts'; export * from './Roles'; export * from './SSE'; export * from './AuthContext'; -export * from './ThemeContext'; export * from './ScreenshotContext'; export * from './ApiErrorBoundaryContext'; export * from './Endpoint'; export type { TranslationKeys } from './useLocalize'; -export { default as useToast } from './useToast'; export { default as useTimeout } from './useTimeout'; export { default as useNewConvo } from './useNewConvo'; export { default as useLocalize } from './useLocalize'; -export { default as useMediaQuery } from './useMediaQuery'; export { default as useChatBadges } from './useChatBadges'; export { default as useScrollToRef } from './useScrollToRef'; export { default as useLocalStorage } from './useLocalStorage'; export { default as useDocumentTitle } from './useDocumentTitle'; -export { default as useDelayedRender } from './useDelayedRender'; -export { default as useOnClickOutside } from './useOnClickOutside'; export { default as useSpeechToText } from './Input/useSpeechToText'; export { default as useTextToSpeech } from './Input/useTextToSpeech'; export { default as useGenerationsByLatest } from './useGenerationsByLatest'; diff --git a/client/src/locales/Translation.spec.ts b/client/src/locales/Translation.spec.ts index 89c7b1d7b7..6c6e1b7ac8 100644 --- a/client/src/locales/Translation.spec.ts +++ b/client/src/locales/Translation.spec.ts @@ -1,9 +1,8 @@ -// Translation.spec.ts - import i18n from './i18n'; import English from './en/translation.json'; import French from './fr/translation.json'; import Spanish from './es/translation.json'; +import { TranslationKeys } from '~/hooks'; describe('i18next translation tests', () => { // Ensure i18next is initialized before any tests run @@ -36,7 +35,7 @@ describe('i18next translation tests', () => { it('should return the key itself for an invalid key', () => { i18n.changeLanguage('en'); - expect(i18n.t('invalid-key')).toBe('invalid-key'); // Returns the key itself + expect(i18n.t('invalid-key' as TranslationKeys)).toBe('invalid-key'); // Returns the key itself }); it('should correctly format placeholders in the translation', () => { @@ -46,4 +45,4 @@ describe('i18next translation tests', () => { i18n.changeLanguage('fr'); expect(i18n.t('com_endpoint_default_with_num', { 0: 'Marie' })).toBe('par défaut : Marie'); }); -}); \ No newline at end of file +}); diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json index 95aa05fee2..444f869ddb 100644 --- a/client/src/locales/en/translation.json +++ b/client/src/locales/en/translation.json @@ -1072,7 +1072,6 @@ "com_ui_use_backup_code": "Use Backup Code Instead", "com_ui_use_memory": "Use memory", "com_ui_use_micrphone": "Use microphone", - "com_ui_use_prompt": "Use prompt", "com_ui_used": "Used", "com_ui_value": "Value", "com_ui_variables": "Variables", @@ -1110,4 +1109,4 @@ "com_ui_yes": "Yes", "com_ui_zoom": "Zoom", "com_user_message": "You" -} \ No newline at end of file +} diff --git a/client/src/routes/ChatRoute.tsx b/client/src/routes/ChatRoute.tsx index 77c6d73976..d81cbc075c 100644 --- a/client/src/routes/ChatRoute.tsx +++ b/client/src/routes/ChatRoute.tsx @@ -1,4 +1,5 @@ import { useEffect } from 'react'; +import { Spinner } from '@librechat/client'; import { useParams } from 'react-router-dom'; import { Constants, EModelEndpoint } from 'librechat-data-provider'; import { useGetModelsQuery } from 'librechat-data-provider/react-query'; @@ -10,7 +11,6 @@ import { ToolCallsMapProvider } from '~/Providers'; import ChatView from '~/components/Chat/ChatView'; import useAuthRedirect from './useAuthRedirect'; import temporaryStore from '~/store/temporary'; -import { Spinner } from '~/components/svg'; import { useRecoilCallback } from 'recoil'; import store from '~/store'; diff --git a/client/src/routes/Layouts/DashBreadcrumb.tsx b/client/src/routes/Layouts/DashBreadcrumb.tsx index 0138e63abc..c6db3a18bc 100644 --- a/client/src/routes/Layouts/DashBreadcrumb.tsx +++ b/client/src/routes/Layouts/DashBreadcrumb.tsx @@ -14,7 +14,7 @@ import { // DropdownMenuItem, // DropdownMenuContent, // DropdownMenuTrigger, -} from '~/components/ui'; +} from '@librechat/client'; import { useLocalize, useCustomLink, useAuthContext } from '~/hooks'; import AdvancedSwitch from '~/components/Prompts/AdvancedSwitch'; // import { RightPanel } from '../../components/Prompts/RightPanel'; diff --git a/client/src/routes/Root.tsx b/client/src/routes/Root.tsx index 42ef88c344..bede0ba54f 100644 --- a/client/src/routes/Root.tsx +++ b/client/src/routes/Root.tsx @@ -14,8 +14,8 @@ import { FileMapContext, SetConvoProvider, } from '~/Providers'; -import TermsAndConditionsModal from '~/components/ui/TermsAndConditionsModal'; import { useUserTermsQuery, useGetStartupConfig } from '~/data-provider'; +import { TermsAndConditionsModal } from '~/components/ui'; import { Nav, MobileNav } from '~/components/Nav'; import { useHealthCheck } from '~/data-provider'; import { Banner } from '~/components/Banners'; diff --git a/client/src/routes/RouteErrorBoundary.tsx b/client/src/routes/RouteErrorBoundary.tsx index 6221ab25b8..f112e29d7d 100644 --- a/client/src/routes/RouteErrorBoundary.tsx +++ b/client/src/routes/RouteErrorBoundary.tsx @@ -1,5 +1,6 @@ +/* eslint-disable i18next/no-literal-string */ +import { Button } from '@librechat/client'; import { useRouteError } from 'react-router-dom'; -import { Button } from '~/components/ui'; import logger from '~/utils/logger'; interface UserAgentData { diff --git a/client/src/routes/Search.tsx b/client/src/routes/Search.tsx index 9508806dfc..f7992745cd 100644 --- a/client/src/routes/Search.tsx +++ b/client/src/routes/Search.tsx @@ -1,11 +1,11 @@ import { useEffect, useMemo } from 'react'; import { useRecoilValue } from 'recoil'; +import { Spinner, useToastContext } from '@librechat/client'; import MinimalMessagesWrapper from '~/components/Chat/Messages/MinimalMessages'; import { useNavScrolling, useLocalize, useAuthContext } from '~/hooks'; import SearchMessage from '~/components/Chat/Messages/SearchMessage'; -import { useToastContext, useFileMapContext } from '~/Providers'; import { useMessagesInfiniteQuery } from '~/data-provider'; -import { Spinner } from '~/components'; +import { useFileMapContext } from '~/Providers'; import { buildTree } from '~/utils'; import store from '~/store'; @@ -23,7 +23,7 @@ export default function Search() { isError, fetchNextPage, isFetchingNextPage, - hasNextPage, + hasNextPage: _hasNextPage, } = useMessagesInfiniteQuery( { search: searchQuery || undefined, diff --git a/client/src/style.css b/client/src/style.css index 4139dfd043..d401bf5a12 100644 --- a/client/src/style.css +++ b/client/src/style.css @@ -51,6 +51,7 @@ --amber-800: #92400e; --amber-900: #78350f; --amber-950: #451a03; + --brand-purple: #ab68ff; --gizmo-gray-500: #999; --gizmo-gray-600: #666; --gizmo-gray-950: #0f0f0f; @@ -61,6 +62,7 @@ --font-size-xl: 1.25rem; } html { + --brand-purple: #ab68ff; --presentation: var(--white); --text-primary: var(--gray-800); --text-secondary: var(--gray-600); @@ -121,6 +123,7 @@ html { --switch-unchecked: 0 0% 58%; } .dark { + --brand-purple: #ab68ff; --presentation: var(--gray-800); --text-primary: var(--gray-100); --text-secondary: var(--gray-300); diff --git a/client/src/utils/files.ts b/client/src/utils/files.ts index 3ca07e51d0..e989090127 100644 --- a/client/src/utils/files.ts +++ b/client/src/utils/files.ts @@ -1,3 +1,4 @@ +import { SheetPaths, TextPaths, FilePaths, CodePaths } from '~/components/svg'; import { megabyte, QueryKeys, @@ -8,10 +9,6 @@ import { import type { TFile, EndpointFileConfig } from 'librechat-data-provider'; import type { QueryClient } from '@tanstack/react-query'; import type { ExtendedFile } from '~/common'; -import SheetPaths from '~/components/svg/Files/SheetPaths'; -import TextPaths from '~/components/svg/Files/TextPaths'; -import FilePaths from '~/components/svg/Files/FilePaths'; -import CodePaths from '~/components/svg/Files/CodePaths'; export const partialTypes = ['text/x-']; diff --git a/client/src/utils/getThemeFromEnv.js b/client/src/utils/getThemeFromEnv.js new file mode 100644 index 0000000000..b294d799a6 --- /dev/null +++ b/client/src/utils/getThemeFromEnv.js @@ -0,0 +1,58 @@ +/** + * Loads theme configuration from environment variables + * @returns {import('@librechat/client').IThemeRGB | undefined} + */ +export function getThemeFromEnv() { + // Check if any theme environment variables are set + const hasThemeEnvVars = Object.keys(process.env).some((key) => + key.startsWith('REACT_APP_THEME_'), + ); + + if (!hasThemeEnvVars) { + return undefined; // Use default themes + } + + // Build theme object from environment variables + const theme = {}; + + // Helper to get env value with prefix + const getEnv = (key) => process.env[`REACT_APP_THEME_${key}`]; + + // Text colors + if (getEnv('TEXT_PRIMARY')) theme['rgb-text-primary'] = getEnv('TEXT_PRIMARY'); + if (getEnv('TEXT_SECONDARY')) theme['rgb-text-secondary'] = getEnv('TEXT_SECONDARY'); + if (getEnv('TEXT_TERTIARY')) theme['rgb-text-tertiary'] = getEnv('TEXT_TERTIARY'); + if (getEnv('TEXT_WARNING')) theme['rgb-text-warning'] = getEnv('TEXT_WARNING'); + + // Surface colors + if (getEnv('SURFACE_PRIMARY')) theme['rgb-surface-primary'] = getEnv('SURFACE_PRIMARY'); + if (getEnv('SURFACE_SECONDARY')) theme['rgb-surface-secondary'] = getEnv('SURFACE_SECONDARY'); + if (getEnv('SURFACE_TERTIARY')) theme['rgb-surface-tertiary'] = getEnv('SURFACE_TERTIARY'); + if (getEnv('SURFACE_SUBMIT')) theme['rgb-surface-submit'] = getEnv('SURFACE_SUBMIT'); + if (getEnv('SURFACE_SUBMIT_HOVER')) + theme['rgb-surface-submit-hover'] = getEnv('SURFACE_SUBMIT_HOVER'); + if (getEnv('SURFACE_DESTRUCTIVE')) + theme['rgb-surface-destructive'] = getEnv('SURFACE_DESTRUCTIVE'); + if (getEnv('SURFACE_DESTRUCTIVE_HOVER')) + theme['rgb-surface-destructive-hover'] = getEnv('SURFACE_DESTRUCTIVE_HOVER'); + if (getEnv('SURFACE_DIALOG')) theme['rgb-surface-dialog'] = getEnv('SURFACE_DIALOG'); + if (getEnv('SURFACE_CHAT')) theme['rgb-surface-chat'] = getEnv('SURFACE_CHAT'); + + // Border colors + if (getEnv('BORDER_LIGHT')) theme['rgb-border-light'] = getEnv('BORDER_LIGHT'); + if (getEnv('BORDER_MEDIUM')) theme['rgb-border-medium'] = getEnv('BORDER_MEDIUM'); + if (getEnv('BORDER_HEAVY')) theme['rgb-border-heavy'] = getEnv('BORDER_HEAVY'); + if (getEnv('BORDER_XHEAVY')) theme['rgb-border-xheavy'] = getEnv('BORDER_XHEAVY'); + + // Brand colors + if (getEnv('BRAND_PURPLE')) theme['rgb-brand-purple'] = getEnv('BRAND_PURPLE'); + + // Header colors + if (getEnv('HEADER_PRIMARY')) theme['rgb-header-primary'] = getEnv('HEADER_PRIMARY'); + if (getEnv('HEADER_HOVER')) theme['rgb-header-hover'] = getEnv('HEADER_HOVER'); + + // Presentation + if (getEnv('PRESENTATION')) theme['rgb-presentation'] = getEnv('PRESENTATION'); + + return Object.keys(theme).length > 0 ? theme : undefined; +} diff --git a/client/src/utils/index.ts b/client/src/utils/index.ts index 82bf1f8a49..b86676a48a 100644 --- a/client/src/utils/index.ts +++ b/client/src/utils/index.ts @@ -4,7 +4,6 @@ export * from './map'; export * from './json'; export * from './files'; export * from './latex'; -export * from './theme'; export * from './forms'; export * from './drafts'; export * from './convos'; @@ -25,6 +24,7 @@ export { default as cleanupPreset } from './cleanupPreset'; export { default as buildDefaultConvo } from './buildDefaultConvo'; export { default as getDefaultEndpoint } from './getDefaultEndpoint'; export { default as createChatSearchParams } from './createChatSearchParams'; +export { getThemeFromEnv } from './getThemeFromEnv'; export const languages = [ 'java', diff --git a/client/tailwind.config.cjs b/client/tailwind.config.cjs index f114a87334..e2f493ad60 100644 --- a/client/tailwind.config.cjs +++ b/client/tailwind.config.cjs @@ -2,7 +2,11 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: ['./src/**/*.{js,jsx,ts,tsx}'], + content: [ + './src/**/*.{js,jsx,ts,tsx}', + // Include component library files + '../packages/client/src/**/*.{js,jsx,ts,tsx}', + ], // darkMode: 'class', darkMode: ['class'], theme: { @@ -61,8 +65,8 @@ module.exports = { 800: '#06373e', 900: '#031f29', }, - 'brand-purple': '#ab68ff', - 'presentation': 'var(--presentation)', + 'brand-purple': 'var(--brand-purple)', + presentation: 'var(--presentation)', 'text-primary': 'var(--text-primary)', 'text-secondary': 'var(--text-secondary)', 'text-secondary-alt': 'var(--text-secondary-alt)', @@ -135,7 +139,7 @@ module.exports = { }, plugins: [ require('tailwindcss-animate'), - require('tailwindcss-radix')(), + require('tailwindcss-radix'), // require('@tailwindcss/typography'), ], }; diff --git a/client/test/setupTests.js b/client/test/setupTests.js index 043c7cdf67..c489fc8b5b 100644 --- a/client/test/setupTests.js +++ b/client/test/setupTests.js @@ -20,6 +20,21 @@ import 'jest-canvas-mock'; // Mock ResizeObserver import './resizeObserver.mock'; +// Mock window.matchMedia +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // deprecated + removeListener: jest.fn(), // deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); + beforeEach(() => { jest.clearAllMocks(); }); diff --git a/client/tsconfig.json b/client/tsconfig.json index ba00b0d24c..59ea7f46cd 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -35,5 +35,5 @@ "test/setupTests.js", "env.d.ts", "../config/translations/**/*.ts" - ] +, "../packages/client/src/hooks/useDelayedRender.tsx" ] } diff --git a/config/update.js b/config/update.js index e0dba111e5..d6ffd55904 100644 --- a/config/update.js +++ b/config/update.js @@ -19,6 +19,7 @@ const directories = [ rootDir, path.resolve(rootDir, 'packages', 'data-provider'), path.resolve(rootDir, 'packages', 'data-schemas'), + path.resolve(rootDir, 'packages', 'client'), path.resolve(rootDir, 'packages', 'api'), path.resolve(rootDir, 'client'), path.resolve(rootDir, 'api'), diff --git a/package-lock.json b/package-lock.json index 97df522f40..9cef1c6644 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2744,6 +2744,7 @@ "@dicebear/collection": "^9.2.2", "@dicebear/core": "^9.2.2", "@headlessui/react": "^2.1.2", + "@librechat/client": "*", "@marsidev/react-turnstile": "^1.1.0", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-alert-dialog": "^1.0.2", @@ -2766,8 +2767,8 @@ "@react-spring/web": "^9.7.5", "@tanstack/react-query": "^4.28.0", "@tanstack/react-table": "^8.11.7", - "class-variance-authority": "^0.6.0", - "clsx": "^1.2.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "copy-to-clipboard": "^3.3.3", "cross-env": "^7.0.3", "date-fns": "^3.3.1", @@ -2780,11 +2781,12 @@ "i18next": "^24.2.2", "i18next-browser-languagedetector": "^8.0.3", "input-otp": "^1.4.2", + "jotai": "^2.12.5", "js-cookie": "^3.0.5", "librechat-data-provider": "*", "lodash": "^4.17.21", "lucide-react": "^0.394.0", - "match-sorter": "^6.3.4", + "match-sorter": "^8.1.0", "micromark-extension-llm-math": "^3.1.0", "qrcode.react": "^4.2.0", "rc-input-number": "^7.4.2", @@ -2860,58 +2862,6 @@ "vite-plugin-pwa": "^0.21.2" } }, - "client/node_modules/@ariakit/react": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.15.tgz", - "integrity": "sha512-0V2LkNPFrGRT+SEIiObx/LQjR6v3rR+mKEDUu/3tq7jfCZ+7+6Q6EMR1rFaK+XMkaRY1RWUcj/rRDWAUWnsDww==", - "dependencies": { - "@ariakit/react-core": "0.4.15" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ariakit" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "client/node_modules/@ariakit/react-core": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.17.tgz", - "integrity": "sha512-kFF6n+gC/5CRQIyaMTFoBPio2xUe0k9rZhMNdUobWRmc/twfeLVkODx+8UVYaNyKilTge8G0JFqwvFKku/jKEw==", - "license": "MIT", - "dependencies": { - "@ariakit/core": "0.4.15", - "@floating-ui/dom": "^1.0.0", - "use-sync-external-store": "^1.2.0" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "client/node_modules/@ariakit/react-core/node_modules/@ariakit/core": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.15.tgz", - "integrity": "sha512-vvxmZvkNhiisKM+Y1TbGMUfVVchV/sWu9F0xw0RYADXcimWPK31dd9JnIZs/OQ5pwAryAHmERHwuGQVESkSjwQ==", - "license": "MIT" - }, - "client/node_modules/@ariakit/react/node_modules/@ariakit/react-core": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.15.tgz", - "integrity": "sha512-Up8+U97nAPJdyUh9E8BCEhJYTA+eVztWpHoo1R9zZfHd4cnBWAg5RHxEmMH+MamlvuRxBQA71hFKY/735fDg+A==", - "license": "MIT", - "dependencies": { - "@ariakit/core": "0.4.14", - "@floating-ui/dom": "^1.0.0", - "use-sync-external-store": "^1.2.0" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "client/node_modules/@babel/compat-data": { "version": "7.26.8", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", @@ -4612,6 +4562,22 @@ "@dicebear/core": "^9.0.0" } }, + "client/node_modules/@react-spring/web": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.5.tgz", + "integrity": "sha512-lmvqGwpe+CSttsWNZVr+Dg62adtKhauGwLyGE/RRyZ8AAMLgb9x3NDMA5RMElXo+IMyTkPp7nxTB8ZQlmhb6JQ==", + "license": "MIT", + "dependencies": { + "@react-spring/animated": "~9.7.5", + "@react-spring/core": "~9.7.5", + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "client/node_modules/@types/jest": { "version": "29.5.14", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", @@ -4811,6 +4777,33 @@ "node": ">=6" } }, + "client/node_modules/framer-motion": { + "version": "11.18.2", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz", + "integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==", + "license": "MIT", + "dependencies": { + "motion-dom": "^11.18.1", + "motion-utils": "^11.18.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "client/node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -4821,6 +4814,15 @@ "node": ">=4" } }, + "client/node_modules/lucide-react": { + "version": "0.394.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.394.0.tgz", + "integrity": "sha512-PzTbJ0bsyXRhH59k5qe7MpTd5MxlpYZUcM9kGSwvPGAfnn0J6FElDwu2EX6Vuh//F7y60rcVJiFQ7EK9DCMgfw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + } + }, "client/node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -4843,16 +4845,6 @@ "node": ">=0.10.0" } }, - "client/node_modules/react-resizable-panels": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-3.0.2.tgz", - "integrity": "sha512-j4RNII75fnHkLnbsTb5G5YsDvJsSEZrJK2XSF2z0Tc2jIonYlIVir/Yh/5LvcUFCfs1HqrMAoiBFmIrRjC4XnA==", - "license": "MIT", - "peerDependencies": { - "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", - "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - } - }, "client/node_modules/ts-jest": { "version": "29.2.5", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", @@ -5027,9 +5019,42 @@ } }, "node_modules/@ariakit/core": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.14.tgz", - "integrity": "sha512-hpzZvyYzGhP09S9jW1XGsU/FD5K3BKsH1eG/QJ8rfgEeUdPS7BvHPt5lHbOeJ2cMrRzBEvsEzLi1ivfDifHsVA==" + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.15.tgz", + "integrity": "sha512-vvxmZvkNhiisKM+Y1TbGMUfVVchV/sWu9F0xw0RYADXcimWPK31dd9JnIZs/OQ5pwAryAHmERHwuGQVESkSjwQ==", + "license": "MIT" + }, + "node_modules/@ariakit/react": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.17.tgz", + "integrity": "sha512-HQaIboE2axtlncJz1hRTaiQfJ1GGjhdtNcAnPwdjvl2RybfmlHowIB+HTVBp36LzroKPs/M4hPCxk7XTaqRZGg==", + "license": "MIT", + "dependencies": { + "@ariakit/react-core": "0.4.17" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ariakit" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@ariakit/react-core": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.17.tgz", + "integrity": "sha512-kFF6n+gC/5CRQIyaMTFoBPio2xUe0k9rZhMNdUobWRmc/twfeLVkODx+8UVYaNyKilTge8G0JFqwvFKku/jKEw==", + "license": "MIT", + "dependencies": { + "@ariakit/core": "0.4.15", + "@floating-ui/dom": "^1.0.0", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } }, "node_modules/@aws-crypto/crc32": { "version": "3.0.0", @@ -17750,6 +17775,25 @@ "tslib": "^2.4.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", @@ -19028,21 +19072,23 @@ } }, "node_modules/@headlessui/react": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.1.2.tgz", - "integrity": "sha512-Kb3hgk9gRNRcTZktBrKdHhF3xFhYkca1Rk6e1/im2ENf83dgN54orMW0uSKTXFnUpZOUFZ+wcY05LlipwgZIFQ==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.4.tgz", + "integrity": "sha512-lz+OGcAH1dK93rgSMzXmm1qKOJkBUqZf1L4M8TWLNplftQD3IkoEDdUFNfAn4ylsN6WOTVtWaLmvmaHOUk1dTA==", + "license": "MIT", "dependencies": { "@floating-ui/react": "^0.26.16", - "@react-aria/focus": "^3.17.1", - "@react-aria/interactions": "^3.21.3", - "@tanstack/react-virtual": "^3.8.1" + "@react-aria/focus": "^3.20.2", + "@react-aria/interactions": "^3.25.0", + "@tanstack/react-virtual": "^3.13.9", + "use-sync-external-store": "^1.5.0" }, "engines": { "node": ">=10" }, "peerDependencies": { - "react": "^18", - "react-dom": "^18" + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "node_modules/@humanfs/core": { @@ -22143,6 +22189,10 @@ "resolved": "api", "link": true }, + "node_modules/@librechat/client": { + "resolved": "packages/client", + "link": true + }, "node_modules/@librechat/data-schemas": { "resolved": "packages/data-schemas", "link": true @@ -22872,12 +22922,10 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@radix-ui/number": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", - "integrity": "sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==", - "dependencies": { - "@babel/runtime": "^7.13.10" - } + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" }, "node_modules/@radix-ui/primitive": { "version": "1.0.1", @@ -22888,26 +22936,26 @@ } }, "node_modules/@radix-ui/react-accordion": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.1.2.tgz", - "integrity": "sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.11.tgz", + "integrity": "sha512-l3W5D54emV2ues7jjeG1xcyN7S3jnK3zE2zHqgn0CmMsy9lNJwmgcrmaxS+7ipw15FAivzKNzH3d5EcGoFKw0A==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collapsible": "1.0.3", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collapsible": "1.1.11", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -22918,6 +22966,176 @@ } } }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/primitive": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-alert-dialog": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.5.tgz", @@ -23000,25 +23218,25 @@ } }, "node_modules/@radix-ui/react-collapsible": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz", - "integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.11.tgz", + "integrity": "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -23029,6 +23247,159 @@ } } }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/primitive": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-presence": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz", + "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", @@ -23441,18 +23812,18 @@ } }, "node_modules/@radix-ui/react-label": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz", - "integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -23463,6 +23834,62 @@ } } }, + "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-menu": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.1.tgz", @@ -24183,27 +24610,27 @@ } }, "node_modules/@radix-ui/react-radio-group": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.1.3.tgz", - "integrity": "sha512-x+yELayyefNeKeTx4fjK6j99Fs6c4qKm3aY38G3swQVTN6xMpsrbigC0uHs2L//g8q4qR7qOcww8430jJmi2ag==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.7.tgz", + "integrity": "sha512-9w5XhD0KPOrm92OTTE0SysH3sYzHsSTHNvZgUBo/VZ80VdYyB5RneDbc0dKpURS24IxkoFRu/hI0i4XyfFwY6g==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-roving-focus": "1.0.4", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-use-previous": "1.0.1", - "@radix-ui/react-use-size": "1.0.1" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -24214,6 +24641,279 @@ } } }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/primitive": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-presence": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz", + "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz", + "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", @@ -24246,38 +24946,38 @@ } }, "node_modules/@radix-ui/react-select": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.0.0.tgz", - "integrity": "sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.5.tgz", + "integrity": "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/number": "1.0.1", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-focus-guards": "1.0.1", - "@radix-ui/react-focus-scope": "1.0.4", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-popper": "1.1.3", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-previous": "1.0.1", - "@radix-ui/react-visually-hidden": "1.0.3", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.5" + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -24288,19 +24988,473 @@ } } }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/primitive": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz", + "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz", + "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-popper": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz", + "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-select/node_modules/react-remove-scroll": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-separator": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.0.3.tgz", - "integrity": "sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -24311,29 +25465,34 @@ } } }, - "node_modules/@radix-ui/react-slider": { + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.1.2.tgz", - "integrity": "sha512-NKs15MJylfzVsCagVSWKhGGLNR1W9qWs+HtgbmjjVUB3B9+lb3PYoXxVju3kOrpf0VKyVCtZp+iTwVoqpa1Chw==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/number": "1.0.1", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-previous": "1.0.1", - "@radix-ui/react-use-size": "1.0.1" + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -24344,6 +25503,242 @@ } } }, + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.5.tgz", + "integrity": "sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/primitive": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", @@ -24363,24 +25758,24 @@ } }, "node_modules/@radix-ui/react-switch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz", - "integrity": "sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.5.tgz", + "integrity": "sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-use-previous": "1.0.1", - "@radix-ui/react-use-size": "1.0.1" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -24391,6 +25786,150 @@ } } }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/primitive": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-tabs": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.4.tgz", @@ -24490,6 +26029,39 @@ } } }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-escape-keydown": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", @@ -24621,49 +26193,43 @@ } }, "node_modules/@react-aria/focus": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.17.1.tgz", - "integrity": "sha512-FLTySoSNqX++u0nWZJPPN5etXY0WBxaIe/YuL/GTEeuqUIuC/2bJSaw5hlsM6T2yjy6Y/VAxBcKSdAFUlU6njQ==", + "version": "3.20.5", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.5.tgz", + "integrity": "sha512-JpFtXmWQ0Oca7FcvkqgjSyo6xEP7v3oQOLUId6o0xTvm4AD5W0mU2r3lYrbhsJ+XxdUUX4AVR5473sZZ85kU4A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.21.3", - "@react-aria/utils": "^3.24.1", - "@react-types/shared": "^3.23.1", + "@react-aria/interactions": "^3.25.3", + "@react-aria/utils": "^3.29.1", + "@react-types/shared": "^3.30.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" - } - }, - "node_modules/@react-aria/focus/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/interactions": { - "version": "3.21.3", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.21.3.tgz", - "integrity": "sha512-BWIuf4qCs5FreDJ9AguawLVS0lV9UU+sK4CCnbCNNmYqOWY+1+gRXCsnOM32K+oMESBxilAjdHW5n1hsMqYMpA==", + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.3.tgz", + "integrity": "sha512-J1bhlrNtjPS/fe5uJQ+0c7/jiXniwa4RQlP+Emjfc/iuqpW2RhbF9ou5vROcLzWIyaW8tVMZ468J68rAs/aZ5A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/ssr": "^3.9.4", - "@react-aria/utils": "^3.24.1", - "@react-types/shared": "^3.23.1", + "@react-aria/ssr": "^3.9.9", + "@react-aria/utils": "^3.29.1", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.30.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/ssr": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.4.tgz", - "integrity": "sha512-4jmAigVq409qcJvQyuorsmBR4+9r3+JEC60wC+Y0MZV0HCtTmm8D9guYXlJMdx0SSkgj0hHAyFm/HvPNFofCoQ==", + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.9.tgz", + "integrity": "sha512-2P5thfjfPy/np18e5wD4WPt8ydNXhij1jwA8oehxZTFqlgVMGXzcWKxTb4RtJrLFsqPO7RUQTiY8QJk0M4Vy2g==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -24672,32 +26238,25 @@ "node": ">= 12" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/utils": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.24.1.tgz", - "integrity": "sha512-O3s9qhPMd6n42x9sKeJ3lhu5V1Tlnzhu6Yk8QOvDuXf7UGuUjXf9mzfHJt1dYzID4l9Fwm8toczBzPM9t0jc8Q==", + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.29.1.tgz", + "integrity": "sha512-yXMFVJ73rbQ/yYE/49n5Uidjw7kh192WNN9PNQGV0Xoc7EJUlSOxqhnpHmYTyO0EotJ8fdM1fMH8durHjUSI8g==", "license": "Apache-2.0", "dependencies": { - "@react-aria/ssr": "^3.9.4", - "@react-stately/utils": "^3.10.1", - "@react-types/shared": "^3.23.1", + "@react-aria/ssr": "^3.9.9", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.7", + "@react-types/shared": "^3.30.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" - } - }, - "node_modules/@react-aria/utils/node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-dnd/asap": { @@ -24792,40 +26351,111 @@ "license": "MIT" }, "node_modules/@react-spring/web": { - "version": "9.7.5", - "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.5.tgz", - "integrity": "sha512-lmvqGwpe+CSttsWNZVr+Dg62adtKhauGwLyGE/RRyZ8AAMLgb9x3NDMA5RMElXo+IMyTkPp7nxTB8ZQlmhb6JQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-10.0.1.tgz", + "integrity": "sha512-FgQk02OqFrYyJBTTnBTWAU0WPzkHkKXauc6aeexcvATvLapUxwnfGuLlsLYF8BYjEVfkivPT04ziAue6zyRBtQ==", "license": "MIT", + "peer": true, "dependencies": { - "@react-spring/animated": "~9.7.5", - "@react-spring/core": "~9.7.5", - "@react-spring/shared": "~9.7.5", - "@react-spring/types": "~9.7.5" + "@react-spring/animated": "~10.0.1", + "@react-spring/core": "~10.0.1", + "@react-spring/shared": "~10.0.1", + "@react-spring/types": "~10.0.1" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-spring/web/node_modules/@react-spring/animated": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-10.0.1.tgz", + "integrity": "sha512-BGL3hA66Y8Qm3KmRZUlfG/mFbDPYajgil2/jOP0VXf2+o2WPVmcDps/eEgdDqgf5Pv9eBbyj7LschLMuSjlW3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@react-spring/shared": "~10.0.1", + "@react-spring/types": "~10.0.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-spring/web/node_modules/@react-spring/core": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-10.0.1.tgz", + "integrity": "sha512-KaMMsN1qHuVTsFpg/5ajAVye7OEqhYbCq0g4aKM9bnSZlDBBYpO7Uf+9eixyXN8YEbF+YXaYj9eoWDs+npZ+sA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@react-spring/animated": "~10.0.1", + "@react-spring/shared": "~10.0.1", + "@react-spring/types": "~10.0.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-spring/web/node_modules/@react-spring/rafz": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-10.0.1.tgz", + "integrity": "sha512-UrzG/d6Is+9i0aCAjsjWRqIlFFiC4lFqFHrH63zK935z2YDU95TOFio4VKGISJ5SG0xq4ULy7c1V3KU+XvL+Yg==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-spring/web/node_modules/@react-spring/shared": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-10.0.1.tgz", + "integrity": "sha512-KR2tmjDShPruI/GGPfAZOOLvDgkhFseabjvxzZFFggJMPkyICLjO0J6mCIoGtdJSuHywZyc4Mmlgi+C88lS00g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@react-spring/rafz": "~10.0.1", + "@react-spring/types": "~10.0.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-spring/web/node_modules/@react-spring/types": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-10.0.1.tgz", + "integrity": "sha512-Fk1wYVAKL+ZTYK+4YFDpHf3Slsy59pfFFvnnTfRjQQFGlyIo4VejPtDs3CbDiuBjM135YztRyZjIH2VbycB+ZQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-stately/flags": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.2.tgz", + "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" } }, "node_modules/@react-stately/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-VS/EHRyicef25zDZcM/ClpzYMC5i2YGN6uegOeQawmgfGjb02yaCX0F0zR69Pod9m2Hr3wunTbtpgVXvYbZItg==", + "version": "3.10.7", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.7.tgz", + "integrity": "sha512-cWvjGAocvy4abO9zbr6PW6taHgF24Mwy/LbQ4TC4Aq3tKdKDntxyD+sh7AkSRfJRT2ccMVaHVv2+FfHThd3PKQ==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/shared": { - "version": "3.23.1", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.23.1.tgz", - "integrity": "sha512-5d+3HbFDxGZjhbMBeFHRQhexMFt4pUce3okyRtUVKbbedQFUrtXSBg9VszgF2RTeQDKDkMCIQDtz5ccP/Lk1gw==", + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.30.0.tgz", + "integrity": "sha512-COIazDAx1ncDg046cTJ8SFYsX8aS3lB/08LDnbkH/SkdYrFPWDlXMrO/sUam8j1WWM+PJ+4d1mj7tODIKNiFog==", "license": "Apache-2.0", "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@redis/bloom": { @@ -27082,12 +28712,12 @@ } }, "node_modules/@swc/helpers": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.11.tgz", - "integrity": "sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==", + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", "license": "Apache-2.0", "dependencies": { - "tslib": "^2.4.0" + "tslib": "^2.8.0" } }, "node_modules/@tanstack/match-sorter-utils": { @@ -27181,20 +28811,20 @@ } }, "node_modules/@tanstack/react-virtual": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.8.2.tgz", - "integrity": "sha512-g78+DA29K0ByAfDkuibfLQqDshf8Aha/zcyEZ+huAX/yS/TWj/CUiEY4IJfDrFacdxIFmsLm0u4VtsLSKTngRw==", + "version": "3.13.12", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz", + "integrity": "sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==", "license": "MIT", "dependencies": { - "@tanstack/virtual-core": "3.8.2" + "@tanstack/virtual-core": "3.13.12" }, "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/@tanstack/table-core": { @@ -27210,9 +28840,9 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.8.2.tgz", - "integrity": "sha512-ffpN6kTaPGwQPoWMcBAHbdv2ZCpj1SugldoYAcY0C4xH+Pej1KCOEUisNeEgbUnXOp8Y/4q6wGPu2tFHthOIQw==", + "version": "3.13.12", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz", + "integrity": "sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==", "license": "MIT", "funding": { "type": "github", @@ -27350,6 +28980,16 @@ "node": ">= 10" } }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -28540,9 +30180,10 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/aria-hidden": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", - "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, @@ -29629,6 +31270,19 @@ "node": ">= 6" } }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001706", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz", @@ -29857,14 +31511,15 @@ "dev": true }, "node_modules/class-variance-authority": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.6.1.tgz", - "integrity": "sha512-eurOEGc7YVx3majOrOb099PNKgO3KnKSApOprXI4BTq6bcfbqbQXPN2u+rPPmIJ2di23bMwhk0SxCCthBmszEQ==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", "dependencies": { - "clsx": "1.2.1" + "clsx": "^2.1.1" }, "funding": { - "url": "https://joebell.co.uk" + "url": "https://polar.sh/cva" } }, "node_modules/classnames": { @@ -30020,9 +31675,10 @@ } }, "node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -30177,6 +31833,13 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true, + "license": "MIT" + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -30235,6 +31898,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/common-tags": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", @@ -30306,6 +31979,16 @@ "node": ">= 6" } }, + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "license": "ISC", + "dependencies": { + "source-map": "^0.6.1" + } + }, "node_modules/console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -30656,6 +32339,19 @@ "postcss": "^8.4" } }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, "node_modules/css-has-pseudo": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-5.0.2.tgz", @@ -30709,6 +32405,20 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", @@ -30760,6 +32470,108 @@ "integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==", "dev": true }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/cssom": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", @@ -33425,17 +35237,20 @@ } }, "node_modules/framer-motion": { - "version": "11.5.4", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.5.4.tgz", - "integrity": "sha512-E+tb3/G6SO69POkdJT+3EpdMuhmtCh9EWuK4I1DnIC23L7tFPrl8vxP+LSovwaw6uUr73rUbpb4FgK011wbRJQ==", + "version": "12.23.9", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.9.tgz", + "integrity": "sha512-TqEHXj8LWfQSKqfdr5Y4mYltYLw96deu6/K9kGDd+ysqRJPNwF9nb5mZcrLmybHbU7gcJ+HQar41U3UTGanbbQ==", "license": "MIT", + "peer": true, "dependencies": { + "motion-dom": "^12.23.9", + "motion-utils": "^12.23.6", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/is-prop-valid": { @@ -33449,6 +35264,23 @@ } } }, + "node_modules/framer-motion/node_modules/motion-dom": { + "version": "12.23.9", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.9.tgz", + "integrity": "sha512-6Sv++iWS8XMFCgU1qwKj9l4xuC47Hp4+2jvPfyTXkqDg2tTzSgX6nWKD4kNFXk0k7llO59LZTPuJigza4A2K1A==", + "license": "MIT", + "peer": true, + "dependencies": { + "motion-utils": "^12.23.6" + } + }, + "node_modules/framer-motion/node_modules/motion-utils": { + "version": "12.23.6", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", + "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", + "license": "MIT", + "peer": true + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -33591,6 +35423,16 @@ "node": ">=12" } }, + "node_modules/generic-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", + "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^3.2.0" + } + }, "node_modules/generic-pool": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", @@ -33977,7 +35819,8 @@ "node_modules/hamt_plus": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz", - "integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA==" + "integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA==", + "license": "MIT" }, "node_modules/handlebars": { "version": "4.7.8", @@ -34586,9 +36429,9 @@ } }, "node_modules/i18next-browser-languagedetector": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.3.tgz", - "integrity": "sha512-beOOLArattPBc2YZG5IXGJytdYFgUR7cS8Wd6HT4IczIoWKgmTspOQ2yasaGklelVo5seLPmnEKvLHR+E/MdWQ==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.0.tgz", + "integrity": "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.2" @@ -34706,6 +36549,26 @@ "node": ">=0.10.0" } }, + "node_modules/icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==", + "dev": true, + "license": "ISC" + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", @@ -34757,6 +36620,19 @@ "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", "dev": true }, + "node_modules/import-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", + "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-from": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -34773,6 +36649,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", + "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-from/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -34860,14 +36759,6 @@ "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.10.0.tgz", "integrity": "sha512-fn4bQ0Xq8FTej09YC/jqKZwtijpvARlRp6wxL5WTA6yPe2YWSJ5RJh7Nm79rK2qB0wr6iDQzH60XGq5V/7u8YQ==" }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/ioredis": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", @@ -36425,6 +38316,27 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/jotai": { + "version": "2.12.5", + "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.12.5.tgz", + "integrity": "sha512-G8m32HW3lSmcz/4mbqx0hgJIQ0ekndKWiYP7kWVKi0p6saLXdSoye+FZiOFyonnd7Q482LCzm8sMDl7Ar1NWDw==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=17.0.0", + "react": ">=17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/js-base64": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.2.tgz", @@ -37347,6 +39259,16 @@ "node": ">=6.11.5" } }, + "node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -37451,6 +39373,13 @@ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true, + "license": "MIT" + }, "node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", @@ -37785,11 +39714,13 @@ "license": "ISC" }, "node_modules/lucide-react": { - "version": "0.394.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.394.0.tgz", - "integrity": "sha512-PzTbJ0bsyXRhH59k5qe7MpTd5MxlpYZUcM9kGSwvPGAfnn0J6FElDwu2EX6Vuh//F7y60rcVJiFQ7EK9DCMgfw==", + "version": "0.525.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.525.0.tgz", + "integrity": "sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ==", + "license": "ISC", + "peer": true, "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/lz-string": { @@ -37805,6 +39736,7 @@ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } @@ -37849,9 +39781,10 @@ } }, "node_modules/match-sorter": { - "version": "6.3.4", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz", - "integrity": "sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-8.1.0.tgz", + "integrity": "sha512-0HX3BHPixkbECX+Vt7nS1vJ6P2twPgGTU3PMXjWrl1eyVCL24tFHeyYN1FN5RKLzve0TyzNI9qntqQGbebnfPQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.8", "remove-accents": "0.5.0" @@ -37860,7 +39793,8 @@ "node_modules/match-sorter/node_modules/remove-accents": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", - "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" + "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==", + "license": "MIT" }, "node_modules/math-intrinsics": { "version": "1.1.0", @@ -38486,6 +40420,13 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -39466,6 +41407,21 @@ "color-name": "^1.1.4" } }, + "node_modules/motion-dom": { + "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", + "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==", + "license": "MIT", + "dependencies": { + "motion-utils": "^11.18.1" + } + }, + "node_modules/motion-utils": { + "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", + "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", + "license": "MIT" + }, "node_modules/mpath": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", @@ -39890,6 +41846,19 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -40769,6 +42738,19 @@ "node": ">=0.10" } }, + "node_modules/pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -40949,6 +42931,20 @@ "postcss": "^8.4" } }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, "node_modules/postcss-clamp": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", @@ -41034,6 +43030,42 @@ "postcss": "^8.4" } }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/postcss-custom-media": { "version": "9.1.5", "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-9.1.5.tgz", @@ -41137,6 +43169,58 @@ "postcss": "^8.4" } }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/postcss-double-position-gradients": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-4.0.4.tgz", @@ -41405,6 +43489,221 @@ "postcss": "^8.4" } }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.3.1.tgz", + "integrity": "sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "generic-names": "^4.0.0", + "icss-replace-symbols": "^1.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dev": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/postcss-nested": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", @@ -41449,6 +43748,149 @@ "postcss": "^8.4" } }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dev": true, + "license": "MIT", + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/postcss-opacity-percentage": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-2.0.0.tgz", @@ -41471,6 +43913,23 @@ "postcss": "^8.2" } }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/postcss-overflow-shorthand": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-4.0.1.tgz", @@ -41617,6 +44076,39 @@ "postcss": "^8.4" } }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/postcss-replace-overflow-wrap": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", @@ -41657,6 +44149,39 @@ "node": ">=4" } }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -42225,6 +44750,16 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/promise.series": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", + "integrity": "sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -42841,19 +45376,20 @@ } }, "node_modules/react-remove-scroll-bar": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", - "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", "dependencies": { - "react-style-singleton": "^2.2.1", + "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "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" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -42861,6 +45397,16 @@ } } }, + "node_modules/react-resizable-panels": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-3.0.3.tgz", + "integrity": "sha512-7HA8THVBHTzhDK4ON0tvlGXyMAJN1zBeRpuyyremSikgYh2ku6ltD7tsGQOcXx4NKPrZtYCm/5CBr+dkruTGQw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/react-router": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.0.tgz", @@ -42900,20 +45446,20 @@ } }, "node_modules/react-style-singleton": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", - "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", "dependencies": { "get-nonce": "^1.0.0", - "invariant": "^2.2.4", "tslib": "^2.0.0" }, "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" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -42970,6 +45516,15 @@ "react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/react-virtualized/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -43074,6 +45629,7 @@ "version": "0.7.7", "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.7.tgz", "integrity": "sha512-8Og5KPQW9LwC577Vc7Ug2P0vQshkv1y3zG3tSSkWMqkWSwHmE+by06L8JtnGocjW6gcCvfwB3YtrJG6/tWivNQ==", + "license": "MIT", "dependencies": { "hamt_plus": "1.0.2" }, @@ -44161,6 +46717,74 @@ "rollup": "*" } }, + "node_modules/rollup-plugin-postcss": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz", + "integrity": "sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "concat-with-sourcemaps": "^1.1.0", + "cssnano": "^5.0.1", + "import-cwd": "^3.0.0", + "p-queue": "^6.6.2", + "pify": "^5.0.0", + "postcss-load-config": "^3.0.0", + "postcss-modules": "^4.0.0", + "promise.series": "^0.2.0", + "resolve": "^1.19.0", + "rollup-pluginutils": "^2.8.2", + "safe-identifier": "^0.4.2", + "style-inject": "^0.3.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "postcss": "8.x" + } + }, + "node_modules/rollup-plugin-postcss/node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/rollup-plugin-postcss/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/rollup-plugin-typescript2": { "version": "0.35.0", "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.35.0.tgz", @@ -44226,6 +46850,23 @@ "node": ">= 10.0.0" } }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/rollup-pluginutils/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true, + "license": "MIT" + }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -44322,6 +46963,13 @@ } ] }, + "node_modules/safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", + "dev": true, + "license": "ISC" + }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -44901,6 +47549,14 @@ "integrity": "sha512-I7zYndqOOkNpz9KIdFZ8c8A7zs1YazNewBr8Nsi/tqThfJkVPuP1q7UE2h4B0RwoWZxbBYpd06uoW3NI3SaZXg==", "license": "Apache-2.0" }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", + "dev": true, + "license": "MIT" + }, "node_modules/stable-hash": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", @@ -45082,6 +47738,13 @@ "node": ">=0.6.19" } }, + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -45397,6 +48060,13 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/style-inject": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", + "integrity": "sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==", + "dev": true, + "license": "MIT" + }, "node_modules/style-mod": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", @@ -45410,6 +48080,23 @@ "inline-style-parser": "0.2.3" } }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -45565,6 +48252,101 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/svgo/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -46910,9 +49692,10 @@ } }, "node_modules/use-sidecar": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", - "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" @@ -46921,8 +49704,8 @@ "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -46931,11 +49714,12 @@ } }, "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/utf8": { @@ -48720,6 +51504,304 @@ "url": "https://github.com/sponsors/isaacs" } }, + "packages/client": { + "name": "@librechat/client", + "version": "0.1.9", + "devDependencies": { + "@rollup/plugin-alias": "^5.1.0", + "@rollup/plugin-commonjs": "^25.0.2", + "@rollup/plugin-node-resolve": "^15.0.0", + "@rollup/plugin-replace": "^5.0.5", + "@rollup/plugin-terser": "^0.4.4", + "@tanstack/react-query": "^4.28.0", + "@testing-library/react": "^14.0.0", + "@types/react": "^18.2.11", + "@types/react-dom": "^18.2.4", + "concat-with-sourcemaps": "^1.1.0", + "i18next": "^24.2.3", + "jotai": "^2.12.5", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-i18next": "^15.4.0", + "rimraf": "^5.0.1", + "rollup": "^4.0.0", + "rollup-plugin-peer-deps-external": "^2.2.4", + "rollup-plugin-postcss": "^4.0.2", + "rollup-plugin-typescript2": "^0.35.0", + "tailwindcss-radix": "^2.8.0", + "typescript": "^5.0.0" + }, + "peerDependencies": { + "@ariakit/react": "^0.4.16", + "@ariakit/react-core": "^0.4.17", + "@headlessui/react": "^2.1.2", + "@radix-ui/react-accordion": "^1.2.11", + "@radix-ui/react-alert-dialog": "^1.0.2", + "@radix-ui/react-checkbox": "^1.0.3", + "@radix-ui/react-collapsible": "^1.1.11", + "@radix-ui/react-dialog": "^1.0.2", + "@radix-ui/react-dropdown-menu": "^2.1.1", + "@radix-ui/react-hover-card": "^1.0.5", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-progress": "^1.1.2", + "@radix-ui/react-radio-group": "^1.3.7", + "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-slider": "^1.3.5", + "@radix-ui/react-slot": "^1.0.0", + "@radix-ui/react-switch": "^1.2.5", + "@radix-ui/react-tabs": "^1.0.3", + "@radix-ui/react-toast": "^1.1.5", + "@react-spring/web": "^10.0.1", + "@tanstack/react-query": "^4.28.0 || ^5.0.0", + "@tanstack/react-table": "^8.11.7", + "@tanstack/react-virtual": "^3.0.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "framer-motion": "^12.23.6", + "i18next": "^24.2.2 || ^25.3.2", + "i18next-browser-languagedetector": "^8.2.0", + "input-otp": "^1.4.2", + "jotai": "^2.12.5", + "lucide-react": "^0.525.0", + "match-sorter": "^8.1.0", + "rc-input-number": "^7.4.2", + "react": "^18.2.0 || ^19.1.0", + "react-dom": "^18.2.0 || ^19.1.0", + "react-hook-form": "^7.56.4", + "react-i18next": "^15.4.0 || ^15.6.0", + "react-resizable-panels": "^3.0.2", + "react-textarea-autosize": "^8.4.0", + "tailwind-merge": "^1.9.1" + } + }, + "packages/client/node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "packages/client/node_modules/@testing-library/react": { + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz", + "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "packages/client/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "packages/client/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "packages/client/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "packages/client/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/client/node_modules/i18next": { + "version": "24.2.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.3.tgz", + "integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/client/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "packages/client/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/client/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "packages/client/node_modules/react-hook-form": { + "version": "7.60.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.60.0.tgz", + "integrity": "sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "packages/client/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "packages/client/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "packages/data-provider": { "name": "librechat-data-provider", "version": "0.7.902", diff --git a/package.json b/package.json index 1aad42eb6e..36327241a2 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,9 @@ "build:data-provider": "cd packages/data-provider && npm run build", "build:api": "cd packages/api && npm run build", "build:data-schemas": "cd packages/data-schemas && npm run build", - "frontend": "npm run build:data-provider && npm run build:data-schemas && npm run build:api && cd client && npm run build", - "frontend:ci": "npm run build:data-provider && cd client && npm run build:ci", + "build:client-package": "cd packages/client && npm run build", + "frontend": "npm run build:data-provider && npm run build:data-schemas && npm run build:api && npm run build:client-package && cd client && npm run build", + "frontend:ci": "npm run build:data-provider && npm run build:client-package && cd client && npm run build:ci", "frontend:dev": "cd client && npm run dev", "e2e": "playwright test --config=e2e/playwright.config.local.ts", "e2e:headed": "playwright test --config=e2e/playwright.config.local.ts --headed", diff --git a/packages/client/package.json b/packages/client/package.json new file mode 100644 index 0000000000..5edd6505cf --- /dev/null +++ b/packages/client/package.json @@ -0,0 +1,92 @@ +{ + "name": "@librechat/client", + "version": "0.1.9", + "description": "React components for LibreChat", + "main": "dist/index.js", + "module": "dist/index.es.js", + "types": "dist/types/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.es.js", + "require": "./dist/index.js", + "types": "./dist/types/index.d.ts" + } + }, + "files": [ + "dist" + ], + "scripts": { + "clean": "rimraf dist", + "build": "npm run clean && rollup -c --bundleConfigAsCjs", + "build:watch": "rollup -c -w --bundleConfigAsCjs", + "dev": "rollup -c -w --bundleConfigAsCjs" + }, + "peerDependencies": { + "@tanstack/react-query": "^4.28.0 || ^5.0.0", + "i18next": "^24.2.2 || ^25.3.2", + "jotai": "^2.12.5", + "react": "^18.2.0 || ^19.1.0", + "react-dom": "^18.2.0 || ^19.1.0", + "react-i18next": "^15.4.0 || ^15.6.0", + "@tanstack/react-table": "^8.11.7", + "@tanstack/react-virtual": "^3.0.0", + "@ariakit/react": "^0.4.16", + "@ariakit/react-core": "^0.4.17", + "@headlessui/react": "^2.1.2", + "@radix-ui/react-accordion": "^1.2.11", + "@radix-ui/react-alert-dialog": "^1.0.2", + "@radix-ui/react-checkbox": "^1.0.3", + "@radix-ui/react-collapsible": "^1.1.11", + "@radix-ui/react-dialog": "^1.0.2", + "@radix-ui/react-dropdown-menu": "^2.1.1", + "@radix-ui/react-hover-card": "^1.0.5", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-progress": "^1.1.2", + "@radix-ui/react-radio-group": "^1.3.7", + "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-slider": "^1.3.5", + "@radix-ui/react-slot": "^1.0.0", + "@radix-ui/react-switch": "^1.2.5", + "@radix-ui/react-tabs": "^1.0.3", + "@radix-ui/react-toast": "^1.1.5", + "@react-spring/web": "^10.0.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "framer-motion": "^12.23.6", + "i18next-browser-languagedetector": "^8.2.0", + "input-otp": "^1.4.2", + "lucide-react": "^0.525.0", + "match-sorter": "^8.1.0", + "rc-input-number": "^7.4.2", + "react-hook-form": "^7.56.4", + "react-resizable-panels": "^3.0.2", + "react-textarea-autosize": "^8.4.0", + "tailwind-merge": "^1.9.1" + }, + "devDependencies": { + "@rollup/plugin-alias": "^5.1.0", + "@rollup/plugin-commonjs": "^25.0.2", + "@rollup/plugin-node-resolve": "^15.0.0", + "@rollup/plugin-replace": "^5.0.5", + "@rollup/plugin-terser": "^0.4.4", + "@tanstack/react-query": "^4.28.0", + "@testing-library/react": "^14.0.0", + "@types/react": "^18.2.11", + "@types/react-dom": "^18.2.4", + "concat-with-sourcemaps": "^1.1.0", + "i18next": "^24.2.3", + "jotai": "^2.12.5", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-i18next": "^15.4.0", + "rimraf": "^5.0.1", + "rollup": "^4.0.0", + "rollup-plugin-peer-deps-external": "^2.2.4", + "rollup-plugin-postcss": "^4.0.2", + "rollup-plugin-typescript2": "^0.35.0", + "tailwindcss-radix": "^2.8.0", + "typescript": "^5.0.0" + } +} diff --git a/packages/client/rollup.config.js b/packages/client/rollup.config.js new file mode 100644 index 0000000000..1523ca9f77 --- /dev/null +++ b/packages/client/rollup.config.js @@ -0,0 +1,84 @@ +// ESM bundler config for React components +import { fileURLToPath } from 'url'; +import alias from '@rollup/plugin-alias'; +import terser from '@rollup/plugin-terser'; +import postcss from 'rollup-plugin-postcss'; +import replace from '@rollup/plugin-replace'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import typescript from 'rollup-plugin-typescript2'; +import { dirname, resolve as pathResolve } from 'path'; +import peerDepsExternal from 'rollup-plugin-peer-deps-external'; +import pkg from './package.json'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const plugins = [ + peerDepsExternal(), + alias({ + entries: [{ find: '~', replacement: pathResolve(__dirname, 'src') }], + }), + resolve({ + extensions: ['.js', '.jsx', '.ts', '.tsx'], + browser: true, + preferBuiltins: false, + }), + replace({ + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production'), + preventAssignment: true, + }), + commonjs(), + postcss({ + extract: false, + inject: true, + minimize: process.env.NODE_ENV === 'production', + modules: false, + config: { + path: './postcss.config.js', + }, + }), + typescript({ + tsconfig: './tsconfig.json', + useTsconfigDeclarationDir: true, + clean: true, + check: false, + }), + terser({ + compress: { + directives: false, + }, + }), +]; + +export default { + input: 'src/index.ts', + output: [ + { + file: pkg.main, + format: 'cjs', + sourcemap: true, + exports: 'named', + }, + { + file: pkg.module, + format: 'esm', + sourcemap: true, + exports: 'named', + }, + ], + external: [ + ...Object.keys(pkg.peerDependencies || {}), + 'react/jsx-runtime', + 'react/jsx-dev-runtime', + ], + preserveSymlinks: true, + plugins, + onwarn(warning, warn) { + // Ignore "use client" directive warnings + if (warning.code === 'MODULE_LEVEL_DIRECTIVE') { + return; + } + warn(warning); + }, +}; diff --git a/client/src/Providers/ToastContext.tsx b/packages/client/src/Providers/ToastContext.tsx similarity index 77% rename from client/src/Providers/ToastContext.tsx rename to packages/client/src/Providers/ToastContext.tsx index 2f0e5efcf6..afe24995d2 100644 --- a/client/src/Providers/ToastContext.tsx +++ b/packages/client/src/Providers/ToastContext.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext } from 'react'; +import { createContext, useContext, ReactNode } from 'react'; import type { TShowToast } from '~/common'; import useToast from '~/hooks/useToast'; @@ -14,7 +14,7 @@ export function useToastContext() { return useContext(ToastContext); } -export default function ToastProvider({ children }) { +export default function ToastProvider({ children }: { children: ReactNode }) { const { showToast } = useToast(); return {children}; diff --git a/packages/client/src/Providers/index.ts b/packages/client/src/Providers/index.ts new file mode 100644 index 0000000000..41cb62ae9c --- /dev/null +++ b/packages/client/src/Providers/index.ts @@ -0,0 +1,2 @@ +export { default as ToastProvider } from './ToastContext'; +export * from './ToastContext'; diff --git a/packages/client/src/common/index.ts b/packages/client/src/common/index.ts new file mode 100644 index 0000000000..7a855f3c17 --- /dev/null +++ b/packages/client/src/common/index.ts @@ -0,0 +1,11 @@ +export type { + TShowToast, + Option, + OptionWithIcon, + DropdownValueSetter, + MentionOption, +} from './types'; + +export { NotificationSeverity } from './types'; + +export type { MenuItemProps } from './menus'; diff --git a/packages/client/src/common/menus.ts b/packages/client/src/common/menus.ts new file mode 100644 index 0000000000..c46ad3f8bb --- /dev/null +++ b/packages/client/src/common/menus.ts @@ -0,0 +1,24 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +export type RenderProp< + P = React.HTMLAttributes & { + ref?: React.Ref; + }, +> = (props: P) => React.ReactNode; + +export interface MenuItemProps { + id?: string; + label?: string; + onClick?: (e: React.MouseEvent) => void; + icon?: React.ReactNode; + kbd?: string; + show?: boolean; + disabled?: boolean; + separate?: boolean; + hideOnClick?: boolean; + dialog?: React.ReactElement; + ref?: React.Ref; + render?: + | RenderProp & { ref?: React.Ref | undefined }> + | React.ReactElement> + | undefined; +} diff --git a/packages/client/src/common/types.ts b/packages/client/src/common/types.ts new file mode 100644 index 0000000000..aaeb5f524b --- /dev/null +++ b/packages/client/src/common/types.ts @@ -0,0 +1,33 @@ +export enum NotificationSeverity { + INFO = 'info', + SUCCESS = 'success', + WARNING = 'warning', + ERROR = 'error', +} + +export type TShowToast = { + message: string; + severity?: NotificationSeverity; + showIcon?: boolean; + duration?: number; + status?: 'error' | 'success' | 'warning' | 'info'; +}; + +export type Option = Record & { + label?: string; + value: string | number | null; +}; + +export type OptionWithIcon = Option & { icon?: React.ReactNode }; +export type DropdownValueSetter = (value: string | Option | OptionWithIcon) => void; +export type MentionOption = OptionWithIcon & { + type: string; + value: string; + description?: string; +}; + +export interface SelectedValues { + endpoint: string | null; + model: string | null; + modelSpec: string | null; +} diff --git a/client/src/components/ui/Accordion.tsx b/packages/client/src/components/Accordion.tsx similarity index 94% rename from client/src/components/ui/Accordion.tsx rename to packages/client/src/components/Accordion.tsx index 5c8ed39a75..a969531e88 100644 --- a/client/src/components/ui/Accordion.tsx +++ b/packages/client/src/components/Accordion.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import * as AccordionPrimitive from '@radix-ui/react-accordion'; import { ChevronDownIcon } from '@radix-ui/react-icons'; - import { cn } from '~/utils'; const Accordion = AccordionPrimitive.Root; @@ -28,7 +27,7 @@ const AccordionTrigger = React.forwardRef< {...props} > {children} - + )); diff --git a/client/src/components/ui/AlertDialog.tsx b/packages/client/src/components/AlertDialog.tsx similarity index 99% rename from client/src/components/ui/AlertDialog.tsx rename to packages/client/src/components/AlertDialog.tsx index 6a5a2dbfc1..4e78fda211 100644 --- a/client/src/components/ui/AlertDialog.tsx +++ b/packages/client/src/components/AlertDialog.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'; - -import { cn } from '../../utils'; +import { cn } from '~/utils'; const AlertDialog = AlertDialogPrimitive.Root; diff --git a/packages/client/src/components/AnimatedSearchInput.tsx b/packages/client/src/components/AnimatedSearchInput.tsx new file mode 100644 index 0000000000..66af0c102d --- /dev/null +++ b/packages/client/src/components/AnimatedSearchInput.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { Search } from 'lucide-react'; +import { cn } from '~/utils'; + +const AnimatedSearchInput = ({ + value, + onChange, + isSearching: searching, + placeholder, +}: { + value?: string; + onChange: (e: React.ChangeEvent) => void; + isSearching?: boolean; + placeholder: string; +}) => { + const isSearching = searching === true; + const hasValue = value != null && value.length > 0; + + return ( +
+
+
+ {/* Icon on the left */} +
+ +
+ + {/* Input field */} + + + {/* Gradient overlay */} +
+ + {/* Animated loading indicator */} +
+
+
+
+
+
+
+
+ + {/* Outer glow effect */} +
+
+
+
+
+
+
+
+ ); +}; + +export default AnimatedSearchInput; diff --git a/client/src/components/ui/AnimatedTabs.css b/packages/client/src/components/AnimatedTabs.css similarity index 96% rename from client/src/components/ui/AnimatedTabs.css rename to packages/client/src/components/AnimatedTabs.css index 808f5c4ac8..4f16a965ca 100644 --- a/client/src/components/ui/AnimatedTabs.css +++ b/packages/client/src/components/AnimatedTabs.css @@ -26,7 +26,7 @@ position: relative; } -.animated-tab[data-state="active"] { +.animated-tab[data-state='active'] { border-bottom-color: transparent !important; } diff --git a/client/src/components/ui/AnimatedTabs.tsx b/packages/client/src/components/AnimatedTabs.tsx similarity index 93% rename from client/src/components/ui/AnimatedTabs.tsx rename to packages/client/src/components/AnimatedTabs.tsx index 809699f30d..131d871aaf 100644 --- a/client/src/components/ui/AnimatedTabs.tsx +++ b/packages/client/src/components/AnimatedTabs.tsx @@ -1,13 +1,13 @@ import * as Ariakit from '@ariakit/react'; -import { ReactNode, forwardRef, useEffect, useRef } from 'react'; +import { forwardRef, useEffect, useRef } from 'react'; import type { ElementRef } from 'react'; import { cn } from '~/utils'; import './AnimatedTabs.css'; export interface TabItem { id?: string; - label: ReactNode; - content: ReactNode; + label: React.ReactNode; + content: React.ReactNode; disabled?: boolean; } @@ -23,7 +23,7 @@ export interface AnimatedTabsProps { } function usePrevious(value: T) { - const ref = useRef(); + const ref = useRef(undefined); useEffect(() => { ref.current = value; }, [value]); @@ -132,6 +132,7 @@ export function AnimatedTabs({ className={tabClassName} data-state={tabIds[index] === firstTabId ? 'active' : 'inactive'} > + {/* TypeScript workaround for React i18next children type compatibility */} {tab.label} ))} @@ -150,6 +151,7 @@ export function AnimatedTabs({ tabId={tabIds[index]} className={tabPanelClassName} > + {/* TypeScript workaround for React i18next children type compatibility */} {tab.content} ))} diff --git a/client/src/components/ui/Badge.tsx b/packages/client/src/components/Badge.tsx similarity index 92% rename from client/src/components/ui/Badge.tsx rename to packages/client/src/components/Badge.tsx index d99017c73f..2469eccb26 100644 --- a/client/src/components/ui/Badge.tsx +++ b/packages/client/src/components/Badge.tsx @@ -1,12 +1,15 @@ import type React from 'react'; - import { X, Plus } from 'lucide-react'; import { motion } from 'framer-motion'; import type { ButtonHTMLAttributes } from 'react'; import type { LucideIcon } from 'lucide-react'; import { cn } from '~/utils'; -interface BadgeProps extends ButtonHTMLAttributes { +interface BadgeProps + extends Omit< + ButtonHTMLAttributes, + 'onAnimationStart' | 'onDragStart' | 'onDragEnd' | 'onDrag' + > { icon?: LucideIcon; label: string; id?: string; @@ -71,7 +74,7 @@ export default function Badge({ }} whileTap={{ scale: isDragging ? 1.1 : isDisabled ? 1 : 0.97 }} transition={{ type: 'tween', duration: 0.1, ease: 'easeOut' }} - {...props} + {...(props as React.ComponentProps)} > {Icon && } {label} diff --git a/client/src/components/ui/Breadcrumb.tsx b/packages/client/src/components/Breadcrumb.tsx similarity index 91% rename from client/src/components/ui/Breadcrumb.tsx rename to packages/client/src/components/Breadcrumb.tsx index 08082e51b2..f1026a8305 100644 --- a/client/src/components/ui/Breadcrumb.tsx +++ b/packages/client/src/components/Breadcrumb.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { Slot } from '@radix-ui/react-slot'; import { ChevronRight, MoreHorizontal } from 'lucide-react'; - import { cn } from '~/utils'; const Breadcrumb = React.forwardRef< @@ -17,7 +16,7 @@ const BreadcrumbList = React.forwardRef ); @@ -58,7 +57,7 @@ const BreadcrumbPage = React.forwardRef ), diff --git a/client/src/components/ui/Button.tsx b/packages/client/src/components/Button.tsx similarity index 100% rename from client/src/components/ui/Button.tsx rename to packages/client/src/components/Button.tsx diff --git a/client/src/components/ui/Checkbox.tsx b/packages/client/src/components/Checkbox.tsx similarity index 96% rename from client/src/components/ui/Checkbox.tsx rename to packages/client/src/components/Checkbox.tsx index a28af18c7f..36a81ac736 100644 --- a/client/src/components/ui/Checkbox.tsx +++ b/packages/client/src/components/Checkbox.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; -import * as CheckboxPrimitive from '@radix-ui/react-checkbox'; import { Check } from 'lucide-react'; -import { cn } from '../../utils'; +import * as CheckboxPrimitive from '@radix-ui/react-checkbox'; +import { cn } from '~/utils'; const Checkbox = React.forwardRef< React.ElementRef, diff --git a/client/src/components/ui/CheckboxButton.tsx b/packages/client/src/components/CheckboxButton.tsx similarity index 98% rename from client/src/components/ui/CheckboxButton.tsx rename to packages/client/src/components/CheckboxButton.tsx index d71ee71b45..1858b7b68d 100644 --- a/client/src/components/ui/CheckboxButton.tsx +++ b/packages/client/src/components/CheckboxButton.tsx @@ -1,7 +1,7 @@ +import * as React from 'react'; import { useEffect } from 'react'; import { Checkbox, useStoreState, useCheckboxStore } from '@ariakit/react'; import { cn } from '~/utils'; -import * as React from 'react'; const CheckboxButton = React.forwardRef< HTMLInputElement, @@ -63,7 +63,7 @@ const CheckboxButton = React.forwardRef< render={ @@ -211,12 +200,11 @@ export default function DataTable({ onFilterChange, filterValue, isLoading, + enableSearch = true, }: DataTableProps) { - const localize = useLocalize(); const isSmallScreen = useMediaQuery('(max-width: 768px)'); const tableContainerRef = useRef(null); - const search = useRecoilValue(store.search); const [isDeleting, setIsDeleting] = useState(false); const [rowSelection, setRowSelection] = useState>({}); const [sorting, setSorting] = useState(defaultSort); @@ -371,16 +359,15 @@ export default function DataTable({ isDeleting={isDeleting} disabled={!table.getFilteredSelectedRowModel().rows.length || isDeleting} isSmallScreen={isSmallScreen} - localize={localize} /> )} - {filterColumn !== undefined && table.getColumn(filterColumn) && search.enabled && ( + {filterColumn !== undefined && table.getColumn(filterColumn) && enableSearch && (
setSearchTerm(e.target.value)} isSearching={isSearching} - placeholder={`${localize('com_ui_search')}...`} + placeholder="Search..." />
)} @@ -448,7 +435,7 @@ export default function DataTable({ {!virtualRows.length && ( - {localize('com_ui_no_data')} + No data available )} diff --git a/client/src/components/ui/DataTableColumnHeader.tsx b/packages/client/src/components/DataTableColumnHeader.tsx similarity index 83% rename from client/src/components/ui/DataTableColumnHeader.tsx rename to packages/client/src/components/DataTableColumnHeader.tsx index 01d335a0e0..606f10b121 100644 --- a/client/src/components/ui/DataTableColumnHeader.tsx +++ b/packages/client/src/components/DataTableColumnHeader.tsx @@ -1,8 +1,5 @@ -import { ArrowDownIcon, ArrowUpIcon, CaretSortIcon, EyeNoneIcon } from '@radix-ui/react-icons'; import { Column } from '@tanstack/react-table'; - -import { cn } from '~/utils'; -import { Button } from './Button'; +import { ArrowDownIcon, ArrowUpIcon, CaretSortIcon, EyeNoneIcon } from '@radix-ui/react-icons'; import { DropdownMenu, DropdownMenuContent, @@ -10,6 +7,8 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from './DropdownMenu'; +import { Button } from './Button'; +import { cn } from '~/utils'; interface DataTableColumnHeaderProps extends React.HTMLAttributes { column: Column; @@ -29,7 +28,7 @@ export function DataTableColumnHeader({
- diff --git a/client/src/components/ui/MultiSelect.tsx b/packages/client/src/components/MultiSelect.tsx similarity index 92% rename from client/src/components/ui/MultiSelect.tsx rename to packages/client/src/components/MultiSelect.tsx index 20e2512794..d7798e810d 100644 --- a/client/src/components/ui/MultiSelect.tsx +++ b/packages/client/src/components/MultiSelect.tsx @@ -14,7 +14,6 @@ interface MultiSelectProps { items: T[]; label?: string; placeholder?: string; - defaultSelectedValues?: T[]; onSelectedValuesChange?: (values: T[]) => void; renderSelectedValues?: (values: T[], placeholder?: string) => React.ReactNode; className?: string; @@ -47,7 +46,6 @@ export default function MultiSelect({ items, label, placeholder = 'Select...', - defaultSelectedValues = [], onSelectedValuesChange, renderSelectedValues = defaultRender, className, @@ -89,7 +87,7 @@ export default function MultiSelect({ )} onChange={(e) => e.stopPropagation()} > - {selectIcon && selectIcon} + {selectIcon && {selectIcon as React.JSX.Element}} {renderSelectedValues(selectedValues, placeholder)} @@ -132,8 +130,12 @@ export default function MultiSelect({ )} > {renderItemContent - ? renderItemContent(value, defaultContent, isCurrentItemSelected) - : defaultContent} + ? (renderItemContent( + value, + defaultContent, + isCurrentItemSelected, + ) as React.JSX.Element) + : (defaultContent as React.JSX.Element)} ); })} diff --git a/client/src/components/ui/OGDialogTemplate.tsx b/packages/client/src/components/OGDialogTemplate.tsx similarity index 93% rename from client/src/components/ui/OGDialogTemplate.tsx rename to packages/client/src/components/OGDialogTemplate.tsx index 8595c13ac9..fe2e919a4e 100644 --- a/client/src/components/ui/OGDialogTemplate.tsx +++ b/packages/client/src/components/OGDialogTemplate.tsx @@ -9,7 +9,7 @@ import { } from './OriginalDialog'; import { useLocalize } from '~/hooks'; import { Button } from './Button'; -import { Spinner } from '../svg'; +import { Spinner } from '~/svgs'; import { cn } from '~/utils/'; type SelectionProps = { @@ -97,7 +97,11 @@ const OGDialogTemplate = forwardRef((props: DialogTemplateProps, ref: Ref - {isLoading === true ? : selectText} + {isLoading === true ? ( + + ) : ( + (selectText as React.JSX.Element) + )} ) : null}
diff --git a/client/src/components/ui/OriginalDialog.tsx b/packages/client/src/components/OriginalDialog.tsx similarity index 100% rename from client/src/components/ui/OriginalDialog.tsx rename to packages/client/src/components/OriginalDialog.tsx diff --git a/client/src/components/ui/Pagination.tsx b/packages/client/src/components/Pagination.tsx similarity index 100% rename from client/src/components/ui/Pagination.tsx rename to packages/client/src/components/Pagination.tsx diff --git a/client/src/components/ui/PixelCard.tsx b/packages/client/src/components/PixelCard.tsx similarity index 96% rename from client/src/components/ui/PixelCard.tsx rename to packages/client/src/components/PixelCard.tsx index 141a3ee55c..c1f3d8971a 100644 --- a/client/src/components/ui/PixelCard.tsx +++ b/packages/client/src/components/PixelCard.tsx @@ -173,7 +173,7 @@ export default function PixelCard({ const containerRef = useRef(null); const canvasRef = useRef(null); const pixelsRef = useRef([]); - const animationRef = useRef(); + const animationRef = useRef(undefined); const timePrevRef = useRef(performance.now()); const progressRef = useRef(progress); const reducedMotion = useRef( @@ -221,9 +221,11 @@ export default function PixelCard({ let idle = true; for (const p of pixelsRef.current) { if (method === 'appearWithProgress') { - progressRef.current !== undefined - ? p.appearWithProgress(progressRef.current) - : (p.isIdle = true); + if (progressRef.current !== undefined) { + p.appearWithProgress(progressRef.current); + } else { + p.isIdle = true; + } } else { // @ts-ignore dynamic dispatch p[method](); @@ -312,7 +314,9 @@ export default function PixelCard({ useEffect(() => { initPixels(); const obs = new ResizeObserver(initPixels); - containerRef.current && obs.observe(containerRef.current); + if (containerRef.current) { + obs.observe(containerRef.current); + } return () => { obs.disconnect(); cancelAnimationFrame(animationRef.current!); diff --git a/client/src/components/ui/Progress.tsx b/packages/client/src/components/Progress.tsx similarity index 100% rename from client/src/components/ui/Progress.tsx rename to packages/client/src/components/Progress.tsx diff --git a/client/src/components/ui/QuestionMark.tsx b/packages/client/src/components/QuestionMark.tsx similarity index 99% rename from client/src/components/ui/QuestionMark.tsx rename to packages/client/src/components/QuestionMark.tsx index 89785837a0..f018226f19 100644 --- a/client/src/components/ui/QuestionMark.tsx +++ b/packages/client/src/components/QuestionMark.tsx @@ -1,4 +1,5 @@ import { cn } from '~/utils'; + export const QuestionMark = ({ className = '' }) => { return ( diff --git a/client/src/components/ui/Resizable.tsx b/packages/client/src/components/Resizable.tsx similarity index 75% rename from client/src/components/ui/Resizable.tsx rename to packages/client/src/components/Resizable.tsx index fc9a32df82..19d3c50e34 100644 --- a/client/src/components/ui/Resizable.tsx +++ b/packages/client/src/components/Resizable.tsx @@ -24,13 +24,13 @@ const ResizableHandle = ({ }) => ( div]:rotate-90', + 'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90', className, )} {...props} > {withHandle && ( -
+
)} @@ -46,13 +46,13 @@ const ResizableHandleAlt = ({ }) => ( div]:rotate-90', + 'group relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90', className, )} {...props} > {withHandle && ( -
+
)} diff --git a/client/src/components/ui/Select.tsx b/packages/client/src/components/Select.tsx similarity index 97% rename from client/src/components/ui/Select.tsx rename to packages/client/src/components/Select.tsx index 671bae4438..3301e3577c 100644 --- a/client/src/components/ui/Select.tsx +++ b/packages/client/src/components/Select.tsx @@ -4,12 +4,15 @@ import { CaretSortIcon, CheckIcon, ChevronDownIcon, ChevronUpIcon } from '@radix import { cn } from '~/utils'; +// @ts-ignore - Radix UI type conflicts with React types const Select = SelectPrimitive.Root; +// @ts-ignore - Radix UI type conflicts with React types const SelectGroup = SelectPrimitive.Group; const SelectValue = SelectPrimitive.Value; +// @ts-ignore - Radix UI type conflicts with React types const SelectTrigger = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef diff --git a/client/src/components/ui/SelectDropDown.tsx b/packages/client/src/components/SelectDropDown.tsx similarity index 96% rename from client/src/components/ui/SelectDropDown.tsx rename to packages/client/src/components/SelectDropDown.tsx index 4547991925..e9a6027bc1 100644 --- a/client/src/components/ui/SelectDropDown.tsx +++ b/packages/client/src/components/SelectDropDown.tsx @@ -8,10 +8,9 @@ import { ListboxOptions, } from '@headlessui/react'; import type { Option, OptionWithIcon, DropdownValueSetter } from '~/common'; -import CheckMark from '~/components/svg/CheckMark'; import { useMultiSearch } from './MultiSearch'; -import { useLocalize } from '~/hooks'; -import { cn } from '~/utils/'; +import { CheckMark } from '~/svgs'; +import { cn } from '~/utils'; type SelectDropDownProps = { id?: string; @@ -75,7 +74,6 @@ function SelectDropDown({ searchPlaceholder, showOptionIcon = false, }: SelectDropDownProps) { - const localize = useLocalize(); const transitionProps = { className: 'top-full mt-3' }; if (showAbove) { transitionProps.className = 'bottom-full mb-3'; @@ -84,9 +82,8 @@ function SelectDropDown({ let title = _title; if (emptyTitle) { title = ''; - } else if (!(title ?? '')) { - title = localize('com_ui_model'); } + const values = availableValues ?? []; // Enable searchable select if enough items are provided. @@ -186,7 +183,7 @@ function SelectDropDown({ - {renderOption()} + {renderOption() as React.JSX.Element} )} - {searchRender} + {searchRender as React.JSX.Element} {options.map((option: string | Option, i: number) => { if (!option) { return null; diff --git a/client/src/components/ui/Separator.tsx b/packages/client/src/components/Separator.tsx similarity index 67% rename from client/src/components/ui/Separator.tsx rename to packages/client/src/components/Separator.tsx index f95d48a793..7ba6d38096 100644 --- a/client/src/components/ui/Separator.tsx +++ b/packages/client/src/components/Separator.tsx @@ -5,18 +5,22 @@ import { cn } from '~/utils'; const Separator = React.forwardRef< React.ElementRef, - React.ComponentPropsWithoutRef + React.ComponentPropsWithoutRef & { + className?: string; + } >(({ className = '', orientation = 'horizontal', decorative = true, ...props }, ref) => ( )); Separator.displayName = SeparatorPrimitive.Root.displayName; diff --git a/client/src/components/ui/Skeleton.tsx b/packages/client/src/components/Skeleton.tsx similarity index 100% rename from client/src/components/ui/Skeleton.tsx rename to packages/client/src/components/Skeleton.tsx diff --git a/packages/client/src/components/Slider.tsx b/packages/client/src/components/Slider.tsx new file mode 100644 index 0000000000..4be0f20039 --- /dev/null +++ b/packages/client/src/components/Slider.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; +import * as SliderPrimitive from '@radix-ui/react-slider'; +import { cn } from '~/utils'; + +const Slider = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + className?: string; + onDoubleClick?: () => void; + } +>(({ className, onDoubleClick, ...props }, ref) => ( + + + + + + +)); +Slider.displayName = SliderPrimitive.Root.displayName; + +export { Slider }; diff --git a/client/src/components/ui/SplitText.spec.tsx b/packages/client/src/components/SplitText.spec.tsx similarity index 100% rename from client/src/components/ui/SplitText.spec.tsx rename to packages/client/src/components/SplitText.spec.tsx diff --git a/client/src/components/ui/SplitText.tsx b/packages/client/src/components/SplitText.tsx similarity index 77% rename from client/src/components/ui/SplitText.tsx rename to packages/client/src/components/SplitText.tsx index cde04eb8a1..46dd757365 100644 --- a/client/src/components/ui/SplitText.tsx +++ b/packages/client/src/components/SplitText.tsx @@ -1,6 +1,36 @@ import { useSprings, animated, SpringConfig } from '@react-spring/web'; import { useEffect, useRef, useState } from 'react'; +interface SegmenterOptions { + granularity?: 'grapheme' | 'word' | 'sentence'; + localeMatcher?: 'lookup' | 'best fit'; +} + +interface SegmentData { + segment: string; + index: number; + input: string; + isWordLike?: boolean; +} + +interface Segments { + [Symbol.iterator](): IterableIterator; +} + +interface IntlSegmenter { + segment(input: string): Segments; +} + +interface IntlSegmenterConstructor { + new (locales?: string | string[], options?: SegmenterOptions): IntlSegmenter; +} + +declare global { + interface Intl { + Segmenter: IntlSegmenterConstructor; + } +} + interface SplitTextProps { text?: string; className?: string; @@ -16,12 +46,14 @@ interface SplitTextProps { } const splitGraphemes = (text: string): string[] => { - if (typeof Intl !== 'undefined' && Intl.Segmenter) { - const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' }); + if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) { + const segmenter = new (Intl as typeof Intl & { Segmenter: IntlSegmenterConstructor }).Segmenter( + 'en', + { granularity: 'grapheme' }, + ); const segments = segmenter.segment(text); - return Array.from(segments).map((s) => s.segment); + return Array.from(segments).map((s: SegmentData) => s.segment); } else { - // Fallback for browsers without Intl.Segmenter return [...text]; } }; @@ -45,12 +77,12 @@ const SplitText: React.FC = ({ const ref = useRef(null); const animatedCount = useRef(0); - const springs = useSprings( + const [springs] = useSprings( letters.length, - letters.map((_, i) => ({ + (i) => ({ from: animationFrom, to: inView - ? async (next: (props: any) => Promise) => { + ? async (next) => { await next(animationTo); animatedCount.current += 1; if (animatedCount.current === letters.length && onLetterAnimationComplete) { @@ -60,7 +92,8 @@ const SplitText: React.FC = ({ : animationFrom, delay: i * delay, config: { easing }, - })), + }), + [inView, text, delay, animationFrom, animationTo, easing, onLetterAnimationComplete], ); useEffect(() => { @@ -118,7 +151,7 @@ const SplitText: React.FC = ({ return ( {letter} diff --git a/client/src/components/ui/Switch.tsx b/packages/client/src/components/Switch.tsx similarity index 100% rename from client/src/components/ui/Switch.tsx rename to packages/client/src/components/Switch.tsx diff --git a/client/src/components/ui/Table.tsx b/packages/client/src/components/Table.tsx similarity index 100% rename from client/src/components/ui/Table.tsx rename to packages/client/src/components/Table.tsx diff --git a/client/src/components/ui/Tabs.tsx b/packages/client/src/components/Tabs.tsx similarity index 100% rename from client/src/components/ui/Tabs.tsx rename to packages/client/src/components/Tabs.tsx diff --git a/client/src/components/ui/Tag.tsx b/packages/client/src/components/Tag.tsx similarity index 76% rename from client/src/components/ui/Tag.tsx rename to packages/client/src/components/Tag.tsx index 38660d11c4..4d17617d65 100644 --- a/client/src/components/ui/Tag.tsx +++ b/packages/client/src/components/Tag.tsx @@ -30,17 +30,17 @@ const TagPrimitiveRoot = React.forwardRef( {CancelButton ? CancelButton : onRemove && ( - - )} + + )}
), ); diff --git a/client/src/components/ui/Textarea.tsx b/packages/client/src/components/Textarea.tsx similarity index 96% rename from client/src/components/ui/Textarea.tsx rename to packages/client/src/components/Textarea.tsx index a738bc8b7c..f9167e91c1 100644 --- a/client/src/components/ui/Textarea.tsx +++ b/packages/client/src/components/Textarea.tsx @@ -1,8 +1,7 @@ /* eslint-disable */ import * as React from 'react'; import TextareaAutosize from 'react-textarea-autosize'; - -import { cn } from '../../utils'; +import { cn } from '~/utils'; export interface TextareaProps extends React.TextareaHTMLAttributes {} diff --git a/client/src/components/ui/TextareaAutosize.tsx b/packages/client/src/components/TextareaAutosize.tsx similarity index 75% rename from client/src/components/ui/TextareaAutosize.tsx rename to packages/client/src/components/TextareaAutosize.tsx index eeaa94d4aa..78083ab7a5 100644 --- a/client/src/components/ui/TextareaAutosize.tsx +++ b/packages/client/src/components/TextareaAutosize.tsx @@ -1,13 +1,13 @@ -import { useRecoilValue } from 'recoil'; +import { useAtomValue } from 'jotai'; import { forwardRef, useLayoutEffect, useState } from 'react'; import ReactTextareaAutosize from 'react-textarea-autosize'; import type { TextareaAutosizeProps } from 'react-textarea-autosize'; -import store from '~/store'; +import { chatDirectionAtom } from '~/store'; export const TextareaAutosize = forwardRef( (props, ref) => { const [, setIsRerendered] = useState(false); - const chatDirection = useRecoilValue(store.chatDirection).toLowerCase(); + const chatDirection = useAtomValue(chatDirectionAtom).toLowerCase(); useLayoutEffect(() => setIsRerendered(true), []); return ; }, diff --git a/client/src/components/ui/ThemeSelector.tsx b/packages/client/src/components/ThemeSelector.tsx similarity index 91% rename from client/src/components/ui/ThemeSelector.tsx rename to packages/client/src/components/ThemeSelector.tsx index e643f05d87..5954b96e78 100644 --- a/client/src/components/ui/ThemeSelector.tsx +++ b/packages/client/src/components/ThemeSelector.tsx @@ -1,6 +1,6 @@ -import React, { useContext, useCallback, useEffect, useState } from 'react'; +import { useContext, useCallback, useEffect, useState } from 'react'; import { Sun, Moon, Monitor } from 'lucide-react'; -import { ThemeContext } from '~/hooks'; +import { ThemeContext } from '../theme'; declare global { interface Window { @@ -8,8 +8,10 @@ declare global { } } +type ThemeType = 'system' | 'dark' | 'light'; + const Theme = ({ theme, onChange }: { theme: string; onChange: (value: string) => void }) => { - const themeIcons = { + const themeIcons: Record = { system: , dark: , light: , @@ -45,7 +47,7 @@ const Theme = ({ theme, onChange }: { theme: string; onChange: (value: string) = } }} > - {themeIcons[theme]} + {themeIcons[theme as ThemeType]} ); }; diff --git a/client/src/components/ui/Toast.tsx b/packages/client/src/components/Toast.tsx similarity index 98% rename from client/src/components/ui/Toast.tsx rename to packages/client/src/components/Toast.tsx index 54dcc4ed0e..34ca1a0531 100644 --- a/client/src/components/ui/Toast.tsx +++ b/packages/client/src/components/Toast.tsx @@ -2,7 +2,7 @@ import * as RadixToast from '@radix-ui/react-toast'; import { NotificationSeverity } from '~/common/types'; import { useToast } from '~/hooks'; -export default function Toast() { +export function Toast() { const { toast, onOpenChange } = useToast(); const severityClassName = { [NotificationSeverity.INFO]: 'border-gray-500 bg-gray-500', diff --git a/client/src/components/ui/Tooltip.tsx b/packages/client/src/components/Tooltip.tsx similarity index 100% rename from client/src/components/ui/Tooltip.tsx rename to packages/client/src/components/Tooltip.tsx diff --git a/packages/client/src/components/index.ts b/packages/client/src/components/index.ts new file mode 100644 index 0000000000..edaf240dc4 --- /dev/null +++ b/packages/client/src/components/index.ts @@ -0,0 +1,51 @@ +export * from './Accordion'; +export * from './AnimatedTabs'; +export * from './AlertDialog'; +export * from './Breadcrumb'; +export * from './Button'; +export * from './Checkbox'; +export * from './DataTableColumnHeader'; +export * from './Dialog'; +export * from './DropdownMenu'; +export * from './HoverCard'; +export * from './Input'; +export * from './InputNumber'; +export * from './Label'; +export * from './OriginalDialog'; +export * from './QuestionMark'; +export * from './Slider'; +export * from './Separator'; +export * from './InputCombobox'; +export * from './Skeleton'; +export * from './Switch'; +export * from './Table'; +export * from './Tabs'; +export * from './Tag'; +export * from './Textarea'; +export * from './TextareaAutosize'; +export * from './Toast'; +export * from './Tooltip'; +export * from './Pagination'; +export * from './Progress'; +export * from './InputOTP'; +export * from './MultiSearch'; +export * from './Resizable'; +export { default as Badge } from './Badge'; +export { default as Combobox } from './Combobox'; +export { default as Dropdown } from './Dropdown'; +export { default as SplitText } from './SplitText'; +export { default as DataTable } from './DataTable'; +export { default as FormInput } from './FormInput'; +export { default as PixelCard } from './PixelCard'; +export { default as FileUpload } from './FileUpload'; +export { default as MultiSelect } from './MultiSelect'; +export { default as DropdownPopup } from './DropdownPopup'; +export { default as DelayedRender } from './DelayedRender'; +export { default as ThemeSelector } from './ThemeSelector'; +export { default as CheckboxButton } from './CheckboxButton'; +export { default as DialogTemplate } from './DialogTemplate'; +export { default as SelectDropDown } from './SelectDropDown'; +export { default as ControlCombobox } from './ControlCombobox'; +export { default as OGDialogTemplate } from './OGDialogTemplate'; +export { default as InputWithDropdown } from './InputWithDropDown'; +export { default as AnimatedSearchInput } from './AnimatedSearchInput'; diff --git a/client/src/hooks/ThemeContext.tsx b/packages/client/src/hooks/ThemeContext.old.tsx similarity index 89% rename from client/src/hooks/ThemeContext.tsx rename to packages/client/src/hooks/ThemeContext.old.tsx index 76b2725980..74516fcab0 100644 --- a/client/src/hooks/ThemeContext.tsx +++ b/packages/client/src/hooks/ThemeContext.old.tsx @@ -1,9 +1,9 @@ //ThemeContext.js // source: https://plainenglish.io/blog/light-and-dark-mode-in-react-web-application-with-tailwind-css-89674496b942 -import { useSetRecoilState } from 'recoil'; +import { useSetAtom } from 'jotai'; import React, { createContext, useState, useEffect } from 'react'; import { getInitialTheme, applyFontSize } from '~/utils'; -import store from '~/store'; +import { fontSizeAtom } from '~/store'; type ProviderValue = { theme: string; @@ -26,9 +26,15 @@ export const isDark = (theme: string): boolean => { export const ThemeContext = createContext(defaultContextValue); -export const ThemeProvider = ({ initialTheme, children }) => { +export const ThemeProvider = ({ + initialTheme, + children, +}: { + initialTheme?: string; + children: React.ReactNode; +}) => { const [theme, setTheme] = useState(getInitialTheme); - const setFontSize = useSetRecoilState(store.fontSize); + const setFontSize = useSetAtom(fontSizeAtom); const rawSetTheme = (rawTheme: string) => { const root = window.document.documentElement; diff --git a/packages/client/src/hooks/index.ts b/packages/client/src/hooks/index.ts new file mode 100644 index 0000000000..019dae0ee4 --- /dev/null +++ b/packages/client/src/hooks/index.ts @@ -0,0 +1,10 @@ +// Theme exports are now handled by the theme module in the main index.ts + +export type { TranslationKeys } from './useLocalize'; + +export { default as useToast } from './useToast'; +export { default as useCombobox } from './useCombobox'; +export { default as useLocalize } from './useLocalize'; +export { default as useMediaQuery } from './useMediaQuery'; +export { default as useDelayedRender } from './useDelayedRender'; +export { default as useOnClickOutside } from './useOnClickOutside'; diff --git a/client/src/hooks/Input/useCombobox.ts b/packages/client/src/hooks/useCombobox.ts similarity index 100% rename from client/src/hooks/Input/useCombobox.ts rename to packages/client/src/hooks/useCombobox.ts diff --git a/client/src/hooks/useDelayedRender.tsx b/packages/client/src/hooks/useDelayedRender.tsx similarity index 100% rename from client/src/hooks/useDelayedRender.tsx rename to packages/client/src/hooks/useDelayedRender.tsx diff --git a/packages/client/src/hooks/useLocalize.ts b/packages/client/src/hooks/useLocalize.ts new file mode 100644 index 0000000000..83366cff16 --- /dev/null +++ b/packages/client/src/hooks/useLocalize.ts @@ -0,0 +1,21 @@ +import { useEffect } from 'react'; +import { TOptions } from 'i18next'; +import { useAtomValue } from 'jotai'; +import { useTranslation } from 'react-i18next'; +import { resources } from '~/locales/i18n'; +import { langAtom } from '~/store'; + +export type TranslationKeys = keyof typeof resources.en.translation; + +export default function useLocalize() { + const lang = useAtomValue(langAtom); + const { t, i18n } = useTranslation(); + + useEffect(() => { + if (i18n.language !== lang) { + i18n.changeLanguage(lang); + } + }, [lang, i18n]); + + return (phraseKey: TranslationKeys, options?: TOptions) => t(phraseKey, options); +} diff --git a/client/src/hooks/useMediaQuery.tsx b/packages/client/src/hooks/useMediaQuery.tsx similarity index 100% rename from client/src/hooks/useMediaQuery.tsx rename to packages/client/src/hooks/useMediaQuery.tsx diff --git a/client/src/hooks/useOnClickOutside.ts b/packages/client/src/hooks/useOnClickOutside.ts similarity index 100% rename from client/src/hooks/useOnClickOutside.ts rename to packages/client/src/hooks/useOnClickOutside.ts diff --git a/client/src/hooks/useToast.ts b/packages/client/src/hooks/useToast.ts similarity index 87% rename from client/src/hooks/useToast.ts rename to packages/client/src/hooks/useToast.ts index 92f7bbfe17..9937c640dd 100644 --- a/client/src/hooks/useToast.ts +++ b/packages/client/src/hooks/useToast.ts @@ -1,11 +1,11 @@ -import { useRecoilState } from 'recoil'; +import { useAtom } from 'jotai'; import { useRef, useEffect } from 'react'; import type { TShowToast } from '~/common'; import { NotificationSeverity } from '~/common'; -import store from '~/store'; +import { toastState, type ToastState } from '~/store'; export default function useToast(showDelay = 100) { - const [toast, setToast] = useRecoilState(store.toastState); + const [toast, setToast] = useAtom(toastState); const showTimerRef = useRef(null); const hideTimerRef = useRef(null); @@ -45,7 +45,7 @@ export default function useToast(showDelay = 100) { }); // Hides the toast after the specified duration hideTimerRef.current = window.setTimeout(() => { - setToast((prevToast) => ({ ...prevToast, open: false })); + setToast((prevToast: ToastState) => ({ ...prevToast, open: false })); }, duration); }, showDelay); }; diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts new file mode 100644 index 0000000000..709697c99f --- /dev/null +++ b/packages/client/src/index.ts @@ -0,0 +1,24 @@ +// Components +export * from './components'; + +// Hooks +export * from './hooks'; + +// Common +export * from './common'; +export * from './common/types'; + +// Store +export * from './store'; + +// SVGs +export * from './svgs'; + +// Utils +export * from './utils'; + +// Providers +export * from './Providers'; + +// Theme +export * from './theme'; diff --git a/packages/client/src/locales/Translation.spec.ts b/packages/client/src/locales/Translation.spec.ts new file mode 100644 index 0000000000..fc3de6e0ef --- /dev/null +++ b/packages/client/src/locales/Translation.spec.ts @@ -0,0 +1,47 @@ +import i18n from './i18n'; +import English from './en/translation.json'; +import French from './fr/translation.json'; +import Spanish from './es/translation.json'; + +describe('i18next translation tests', () => { + // Ensure i18next is initialized before any tests run + beforeAll(async () => { + if (!i18n.isInitialized) { + await i18n.init(); + } + }); + + it('should return the correct translation for a valid key in English', () => { + i18n.changeLanguage('en'); + expect(i18n.t('com_ui_examples')).toBe(English.com_ui_examples); + }); + + it('should return the correct translation for a valid key in French', () => { + i18n.changeLanguage('fr'); + expect(i18n.t('com_ui_examples')).toBe(French.com_ui_examples); + }); + + it('should return the correct translation for a valid key in Spanish', () => { + i18n.changeLanguage('es'); + expect(i18n.t('com_ui_examples')).toBe(Spanish.com_ui_examples); + }); + + it('should fallback to English for an invalid language code', () => { + // When an invalid language is provided, i18next should fallback to English + i18n.changeLanguage('invalid-code'); + expect(i18n.t('com_ui_examples')).toBe(English.com_ui_examples); + }); + + it('should return the key itself for an invalid key', () => { + i18n.changeLanguage('en'); + expect(i18n.t('invalid-key')).toBe('invalid-key'); // Returns the key itself + }); + + it('should correctly format placeholders in the translation', () => { + i18n.changeLanguage('en'); + expect(i18n.t('com_endpoint_default_with_num', { 0: 'John' })).toBe('default: John'); + + i18n.changeLanguage('fr'); + expect(i18n.t('com_endpoint_default_with_num', { 0: 'Marie' })).toBe('par défaut : Marie'); + }); +}); diff --git a/packages/client/src/locales/ar/translation.json b/packages/client/src/locales/ar/translation.json new file mode 100644 index 0000000000..aa03723635 --- /dev/null +++ b/packages/client/src/locales/ar/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "إلغاء" +} diff --git a/packages/client/src/locales/ca/translation.json b/packages/client/src/locales/ca/translation.json new file mode 100644 index 0000000000..8c42ae78f9 --- /dev/null +++ b/packages/client/src/locales/ca/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Cancel·la" +} diff --git a/packages/client/src/locales/cs/translation.json b/packages/client/src/locales/cs/translation.json new file mode 100644 index 0000000000..4d34a884c6 --- /dev/null +++ b/packages/client/src/locales/cs/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Zrušit" +} diff --git a/packages/client/src/locales/da/translation.json b/packages/client/src/locales/da/translation.json new file mode 100644 index 0000000000..796263989e --- /dev/null +++ b/packages/client/src/locales/da/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Annuller" +} diff --git a/packages/client/src/locales/de/translation.json b/packages/client/src/locales/de/translation.json new file mode 100644 index 0000000000..b1d8645611 --- /dev/null +++ b/packages/client/src/locales/de/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Abbrechen" +} diff --git a/packages/client/src/locales/en/translation.json b/packages/client/src/locales/en/translation.json new file mode 100644 index 0000000000..de39a30059 --- /dev/null +++ b/packages/client/src/locales/en/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Cancel" +} diff --git a/packages/client/src/locales/es/translation.json b/packages/client/src/locales/es/translation.json new file mode 100644 index 0000000000..c831d5737b --- /dev/null +++ b/packages/client/src/locales/es/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Cancelar" +} diff --git a/packages/client/src/locales/et/translation.json b/packages/client/src/locales/et/translation.json new file mode 100644 index 0000000000..fffcde4163 --- /dev/null +++ b/packages/client/src/locales/et/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Tühista" +} diff --git a/packages/client/src/locales/fa/translation.json b/packages/client/src/locales/fa/translation.json new file mode 100644 index 0000000000..73e57d028e --- /dev/null +++ b/packages/client/src/locales/fa/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "لغو کنید" +} diff --git a/packages/client/src/locales/fi/translation.json b/packages/client/src/locales/fi/translation.json new file mode 100644 index 0000000000..00797137b6 --- /dev/null +++ b/packages/client/src/locales/fi/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Peruuta" +} diff --git a/packages/client/src/locales/fr/translation.json b/packages/client/src/locales/fr/translation.json new file mode 100644 index 0000000000..1d6265d6c4 --- /dev/null +++ b/packages/client/src/locales/fr/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Annuler" +} diff --git a/packages/client/src/locales/he/translation.json b/packages/client/src/locales/he/translation.json new file mode 100644 index 0000000000..5bf5a86d95 --- /dev/null +++ b/packages/client/src/locales/he/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "בטל" +} diff --git a/packages/client/src/locales/hu/translation.json b/packages/client/src/locales/hu/translation.json new file mode 100644 index 0000000000..8616ee9274 --- /dev/null +++ b/packages/client/src/locales/hu/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Mégse" +} diff --git a/packages/client/src/locales/i18n.ts b/packages/client/src/locales/i18n.ts new file mode 100644 index 0000000000..f463723a4f --- /dev/null +++ b/packages/client/src/locales/i18n.ts @@ -0,0 +1,87 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; + +import translationEn from './en/translation.json'; +import translationAr from './ar/translation.json'; +import translationCa from './ca/translation.json'; +import translationCs from './cs/translation.json'; +import translationDa from './da/translation.json'; +import translationDe from './de/translation.json'; +import translationEs from './es/translation.json'; +import translationEt from './et/translation.json'; +import translationFa from './fa/translation.json'; +import translationFr from './fr/translation.json'; +import translationIt from './it/translation.json'; +import translationPl from './pl/translation.json'; +import translationPt_BR from './pt-BR/translation.json'; +import translationPt_PT from './pt-PT/translation.json'; +import translationRu from './ru/translation.json'; +import translationJa from './ja/translation.json'; +import translationKa from './ka/translation.json'; +import translationSv from './sv/translation.json'; +import translationKo from './ko/translation.json'; +import translationTh from './th/translation.json'; +import translationTr from './tr/translation.json'; +import translationVi from './vi/translation.json'; +import translationNl from './nl/translation.json'; +import translationId from './id/translation.json'; +import translationHe from './he/translation.json'; +import translationHu from './hu/translation.json'; +import translationFi from './fi/translation.json'; +import translationZh_Hans from './zh-Hans/translation.json'; +import translationZh_Hant from './zh-Hant/translation.json'; + +export const defaultNS = 'translation'; + +export const resources = { + en: { translation: translationEn }, + ar: { translation: translationAr }, + ca: { translation: translationCa }, + cs: { translation: translationCs }, + 'zh-Hans': { translation: translationZh_Hans }, + 'zh-Hant': { translation: translationZh_Hant }, + da: { translation: translationDa }, + de: { translation: translationDe }, + es: { translation: translationEs }, + et: { translation: translationEt }, + fa: { translation: translationFa }, + fr: { translation: translationFr }, + it: { translation: translationIt }, + pl: { translation: translationPl }, + 'pt-BR': { translation: translationPt_BR }, + 'pt-PT': { translation: translationPt_PT }, + ru: { translation: translationRu }, + ja: { translation: translationJa }, + ka: { translation: translationKa }, + sv: { translation: translationSv }, + ko: { translation: translationKo }, + th: { translation: translationTh }, + tr: { translation: translationTr }, + vi: { translation: translationVi }, + nl: { translation: translationNl }, + id: { translation: translationId }, + he: { translation: translationHe }, + hu: { translation: translationHu }, + fi: { translation: translationFi }, +} as const; + +i18n + .use(LanguageDetector) + .use(initReactI18next) + .init({ + fallbackLng: { + 'zh-TW': ['zh-Hant', 'en'], + 'zh-HK': ['zh-Hant', 'en'], + zh: ['zh-Hans', 'en'], + default: ['en'], + }, + fallbackNS: 'translation', + ns: ['translation'], + debug: false, + defaultNS, + resources, + interpolation: { escapeValue: false }, + }); + +export default i18n; diff --git a/packages/client/src/locales/id/translation.json b/packages/client/src/locales/id/translation.json new file mode 100644 index 0000000000..24d3467bd2 --- /dev/null +++ b/packages/client/src/locales/id/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Batal" +} diff --git a/packages/client/src/locales/it/translation.json b/packages/client/src/locales/it/translation.json new file mode 100644 index 0000000000..cc082b4a2b --- /dev/null +++ b/packages/client/src/locales/it/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Annulla" +} diff --git a/packages/client/src/locales/ja/translation.json b/packages/client/src/locales/ja/translation.json new file mode 100644 index 0000000000..4400b02827 --- /dev/null +++ b/packages/client/src/locales/ja/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "キャンセル" +} diff --git a/packages/client/src/locales/ka/translation.json b/packages/client/src/locales/ka/translation.json new file mode 100644 index 0000000000..0c90d6bf7d --- /dev/null +++ b/packages/client/src/locales/ka/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "გაუქმება" +} diff --git a/packages/client/src/locales/ko/translation.json b/packages/client/src/locales/ko/translation.json new file mode 100644 index 0000000000..96650ed6a8 --- /dev/null +++ b/packages/client/src/locales/ko/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "취소" +} diff --git a/packages/client/src/locales/nl/translation.json b/packages/client/src/locales/nl/translation.json new file mode 100644 index 0000000000..2ec1fb8c6e --- /dev/null +++ b/packages/client/src/locales/nl/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Annuleren" +} diff --git a/packages/client/src/locales/pl/translation.json b/packages/client/src/locales/pl/translation.json new file mode 100644 index 0000000000..9c05e4cd79 --- /dev/null +++ b/packages/client/src/locales/pl/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Anuluj" +} diff --git a/packages/client/src/locales/pt-BR/translation.json b/packages/client/src/locales/pt-BR/translation.json new file mode 100644 index 0000000000..c831d5737b --- /dev/null +++ b/packages/client/src/locales/pt-BR/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Cancelar" +} diff --git a/packages/client/src/locales/pt-PT/translation.json b/packages/client/src/locales/pt-PT/translation.json new file mode 100644 index 0000000000..c831d5737b --- /dev/null +++ b/packages/client/src/locales/pt-PT/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Cancelar" +} diff --git a/packages/client/src/locales/ru/translation.json b/packages/client/src/locales/ru/translation.json new file mode 100644 index 0000000000..e3f16ae66e --- /dev/null +++ b/packages/client/src/locales/ru/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Отмена" +} diff --git a/packages/client/src/locales/sv/translation.json b/packages/client/src/locales/sv/translation.json new file mode 100644 index 0000000000..c606ec621d --- /dev/null +++ b/packages/client/src/locales/sv/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Avbryt" +} diff --git a/packages/client/src/locales/th/translation.json b/packages/client/src/locales/th/translation.json new file mode 100644 index 0000000000..b78cd2cc27 --- /dev/null +++ b/packages/client/src/locales/th/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "ยกเลิก" +} diff --git a/packages/client/src/locales/tr/translation.json b/packages/client/src/locales/tr/translation.json new file mode 100644 index 0000000000..10468437fe --- /dev/null +++ b/packages/client/src/locales/tr/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "İptal" +} diff --git a/packages/client/src/locales/vi/translation.json b/packages/client/src/locales/vi/translation.json new file mode 100644 index 0000000000..64634b0dff --- /dev/null +++ b/packages/client/src/locales/vi/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "Hủy" +} diff --git a/packages/client/src/locales/zh-Hans/translation.json b/packages/client/src/locales/zh-Hans/translation.json new file mode 100644 index 0000000000..d763c638ca --- /dev/null +++ b/packages/client/src/locales/zh-Hans/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "取消" +} diff --git a/packages/client/src/locales/zh-Hant/translation.json b/packages/client/src/locales/zh-Hant/translation.json new file mode 100644 index 0000000000..d763c638ca --- /dev/null +++ b/packages/client/src/locales/zh-Hant/translation.json @@ -0,0 +1,3 @@ +{ + "com_ui_cancel": "取消" +} diff --git a/packages/client/src/store.ts b/packages/client/src/store.ts new file mode 100644 index 0000000000..6e23be6e04 --- /dev/null +++ b/packages/client/src/store.ts @@ -0,0 +1,20 @@ +import { atom } from 'jotai'; +import { NotificationSeverity } from '~/common'; + +export const langAtom = atom('en'); +export const chatDirectionAtom = atom('ltr'); +export const fontSizeAtom = atom('text-base'); + +export type ToastState = { + open: boolean; + message: string; + severity: NotificationSeverity; + showIcon: boolean; +}; + +export const toastState = atom({ + open: false, + message: '', + severity: NotificationSeverity.SUCCESS, + showIcon: true, +}); diff --git a/client/src/components/svg/AnthropicIcon.tsx b/packages/client/src/svgs/AnthropicIcon.tsx similarity index 100% rename from client/src/components/svg/AnthropicIcon.tsx rename to packages/client/src/svgs/AnthropicIcon.tsx diff --git a/client/src/components/svg/AnthropicMinimalIcon.tsx b/packages/client/src/svgs/AnthropicMinimalIcon.tsx similarity index 100% rename from client/src/components/svg/AnthropicMinimalIcon.tsx rename to packages/client/src/svgs/AnthropicMinimalIcon.tsx diff --git a/client/src/components/svg/AppleIcon.tsx b/packages/client/src/svgs/AppleIcon.tsx similarity index 99% rename from client/src/components/svg/AppleIcon.tsx rename to packages/client/src/svgs/AppleIcon.tsx index 4f1ff404d1..e84b703864 100644 --- a/client/src/components/svg/AppleIcon.tsx +++ b/packages/client/src/svgs/AppleIcon.tsx @@ -15,4 +15,4 @@ export default function AppleIcon() { /> ); -} \ No newline at end of file +} diff --git a/client/src/components/svg/ArchiveIcon.tsx b/packages/client/src/svgs/ArchiveIcon.tsx similarity index 100% rename from client/src/components/svg/ArchiveIcon.tsx rename to packages/client/src/svgs/ArchiveIcon.tsx diff --git a/client/src/components/svg/AssistantIcon.tsx b/packages/client/src/svgs/AssistantIcon.tsx similarity index 100% rename from client/src/components/svg/AssistantIcon.tsx rename to packages/client/src/svgs/AssistantIcon.tsx diff --git a/client/src/components/svg/AttachmentIcon.tsx b/packages/client/src/svgs/AttachmentIcon.tsx similarity index 100% rename from client/src/components/svg/AttachmentIcon.tsx rename to packages/client/src/svgs/AttachmentIcon.tsx diff --git a/client/src/components/svg/AzureMinimalIcon.tsx b/packages/client/src/svgs/AzureMinimalIcon.tsx similarity index 99% rename from client/src/components/svg/AzureMinimalIcon.tsx rename to packages/client/src/svgs/AzureMinimalIcon.tsx index 171a0c1eb5..bd73c5d132 100644 --- a/client/src/components/svg/AzureMinimalIcon.tsx +++ b/packages/client/src/svgs/AzureMinimalIcon.tsx @@ -1,4 +1,3 @@ - import { cn } from '~/utils/'; export default function AzureMinimalIcon({ diff --git a/client/src/components/svg/BedrockIcon.tsx b/packages/client/src/svgs/BedrockIcon.tsx similarity index 100% rename from client/src/components/svg/BedrockIcon.tsx rename to packages/client/src/svgs/BedrockIcon.tsx diff --git a/client/src/components/svg/BirthdayIcon.tsx b/packages/client/src/svgs/BirthdayIcon.tsx similarity index 100% rename from client/src/components/svg/BirthdayIcon.tsx rename to packages/client/src/svgs/BirthdayIcon.tsx diff --git a/client/src/components/svg/Blocks.tsx b/packages/client/src/svgs/Blocks.tsx similarity index 100% rename from client/src/components/svg/Blocks.tsx rename to packages/client/src/svgs/Blocks.tsx diff --git a/client/src/components/svg/CautionIcon.tsx b/packages/client/src/svgs/CautionIcon.tsx similarity index 100% rename from client/src/components/svg/CautionIcon.tsx rename to packages/client/src/svgs/CautionIcon.tsx diff --git a/client/src/components/svg/ChatGPTMinimalIcon.tsx b/packages/client/src/svgs/ChatGPTMinimalIcon.tsx similarity index 100% rename from client/src/components/svg/ChatGPTMinimalIcon.tsx rename to packages/client/src/svgs/ChatGPTMinimalIcon.tsx diff --git a/client/src/components/svg/ChatIcon.tsx b/packages/client/src/svgs/ChatIcon.tsx similarity index 100% rename from client/src/components/svg/ChatIcon.tsx rename to packages/client/src/svgs/ChatIcon.tsx diff --git a/client/src/components/svg/CheckMark.tsx b/packages/client/src/svgs/CheckMark.tsx similarity index 100% rename from client/src/components/svg/CheckMark.tsx rename to packages/client/src/svgs/CheckMark.tsx diff --git a/client/src/components/svg/CircleHelpIcon.tsx b/packages/client/src/svgs/CircleHelpIcon.tsx similarity index 100% rename from client/src/components/svg/CircleHelpIcon.tsx rename to packages/client/src/svgs/CircleHelpIcon.tsx diff --git a/client/src/components/svg/Clipboard.tsx b/packages/client/src/svgs/Clipboard.tsx similarity index 100% rename from client/src/components/svg/Clipboard.tsx rename to packages/client/src/svgs/Clipboard.tsx diff --git a/client/src/components/svg/CodeyIcon.tsx b/packages/client/src/svgs/CodeyIcon.tsx similarity index 100% rename from client/src/components/svg/CodeyIcon.tsx rename to packages/client/src/svgs/CodeyIcon.tsx diff --git a/client/src/components/svg/ContinueIcon.tsx b/packages/client/src/svgs/ContinueIcon.tsx similarity index 100% rename from client/src/components/svg/ContinueIcon.tsx rename to packages/client/src/svgs/ContinueIcon.tsx diff --git a/client/src/components/svg/ConvoIcon.tsx b/packages/client/src/svgs/ConvoIcon.tsx similarity index 100% rename from client/src/components/svg/ConvoIcon.tsx rename to packages/client/src/svgs/ConvoIcon.tsx diff --git a/client/src/components/svg/CrossIcon.tsx b/packages/client/src/svgs/CrossIcon.tsx similarity index 100% rename from client/src/components/svg/CrossIcon.tsx rename to packages/client/src/svgs/CrossIcon.tsx diff --git a/client/src/components/svg/CustomMinimalIcon.tsx b/packages/client/src/svgs/CustomMinimalIcon.tsx similarity index 100% rename from client/src/components/svg/CustomMinimalIcon.tsx rename to packages/client/src/svgs/CustomMinimalIcon.tsx diff --git a/client/src/components/svg/DarkModeIcon.tsx b/packages/client/src/svgs/DarkModeIcon.tsx similarity index 100% rename from client/src/components/svg/DarkModeIcon.tsx rename to packages/client/src/svgs/DarkModeIcon.tsx diff --git a/client/src/components/svg/DataIcon.tsx b/packages/client/src/svgs/DataIcon.tsx similarity index 100% rename from client/src/components/svg/DataIcon.tsx rename to packages/client/src/svgs/DataIcon.tsx diff --git a/client/src/components/svg/DiscordIcon.tsx b/packages/client/src/svgs/DiscordIcon.tsx similarity index 100% rename from client/src/components/svg/DiscordIcon.tsx rename to packages/client/src/svgs/DiscordIcon.tsx diff --git a/client/src/components/svg/DislikeIcon.tsx b/packages/client/src/svgs/DislikeIcon.tsx similarity index 100% rename from client/src/components/svg/DislikeIcon.tsx rename to packages/client/src/svgs/DislikeIcon.tsx diff --git a/client/src/components/svg/DotsIcon.tsx b/packages/client/src/svgs/DotsIcon.tsx similarity index 100% rename from client/src/components/svg/DotsIcon.tsx rename to packages/client/src/svgs/DotsIcon.tsx diff --git a/client/src/components/svg/EditIcon.tsx b/packages/client/src/svgs/EditIcon.tsx similarity index 100% rename from client/src/components/svg/EditIcon.tsx rename to packages/client/src/svgs/EditIcon.tsx diff --git a/client/src/components/svg/ExperimentIcon.tsx b/packages/client/src/svgs/ExperimentIcon.tsx similarity index 100% rename from client/src/components/svg/ExperimentIcon.tsx rename to packages/client/src/svgs/ExperimentIcon.tsx diff --git a/client/src/components/svg/FacebookIcon.tsx b/packages/client/src/svgs/FacebookIcon.tsx similarity index 100% rename from client/src/components/svg/FacebookIcon.tsx rename to packages/client/src/svgs/FacebookIcon.tsx diff --git a/client/src/components/svg/GPTIcon.tsx b/packages/client/src/svgs/GPTIcon.tsx similarity index 100% rename from client/src/components/svg/GPTIcon.tsx rename to packages/client/src/svgs/GPTIcon.tsx diff --git a/client/src/components/svg/GearIcon.tsx b/packages/client/src/svgs/GearIcon.tsx similarity index 100% rename from client/src/components/svg/GearIcon.tsx rename to packages/client/src/svgs/GearIcon.tsx diff --git a/client/src/components/svg/GeminiIcon.tsx b/packages/client/src/svgs/GeminiIcon.tsx similarity index 100% rename from client/src/components/svg/GeminiIcon.tsx rename to packages/client/src/svgs/GeminiIcon.tsx diff --git a/client/src/components/svg/GithubIcon.tsx b/packages/client/src/svgs/GithubIcon.tsx similarity index 100% rename from client/src/components/svg/GithubIcon.tsx rename to packages/client/src/svgs/GithubIcon.tsx diff --git a/client/src/components/svg/GoogleIcon.tsx b/packages/client/src/svgs/GoogleIcon.tsx similarity index 100% rename from client/src/components/svg/GoogleIcon.tsx rename to packages/client/src/svgs/GoogleIcon.tsx diff --git a/client/src/components/svg/GoogleIconChat.tsx b/packages/client/src/svgs/GoogleIconChat.tsx similarity index 100% rename from client/src/components/svg/GoogleIconChat.tsx rename to packages/client/src/svgs/GoogleIconChat.tsx diff --git a/client/src/components/svg/GoogleMinimalIcon.tsx b/packages/client/src/svgs/GoogleMinimalIcon.tsx similarity index 100% rename from client/src/components/svg/GoogleMinimalIcon.tsx rename to packages/client/src/svgs/GoogleMinimalIcon.tsx diff --git a/client/src/components/svg/LightModeIcon.tsx b/packages/client/src/svgs/LightModeIcon.tsx similarity index 100% rename from client/src/components/svg/LightModeIcon.tsx rename to packages/client/src/svgs/LightModeIcon.tsx diff --git a/client/src/components/svg/LightningIcon.tsx b/packages/client/src/svgs/LightningIcon.tsx similarity index 100% rename from client/src/components/svg/LightningIcon.tsx rename to packages/client/src/svgs/LightningIcon.tsx diff --git a/client/src/components/svg/LikeIcon.tsx b/packages/client/src/svgs/LikeIcon.tsx similarity index 100% rename from client/src/components/svg/LikeIcon.tsx rename to packages/client/src/svgs/LikeIcon.tsx diff --git a/client/src/components/svg/LinkIcon.tsx b/packages/client/src/svgs/LinkIcon.tsx similarity index 100% rename from client/src/components/svg/LinkIcon.tsx rename to packages/client/src/svgs/LinkIcon.tsx diff --git a/client/src/components/svg/ListeningIcon.tsx b/packages/client/src/svgs/ListeningIcon.tsx similarity index 78% rename from client/src/components/svg/ListeningIcon.tsx rename to packages/client/src/svgs/ListeningIcon.tsx index e81c7e37e9..ef8de6a4ed 100644 --- a/client/src/components/svg/ListeningIcon.tsx +++ b/packages/client/src/svgs/ListeningIcon.tsx @@ -1,6 +1,10 @@ import { cn } from '~/utils/'; -export default function ListeningIcon({ className }) { +type ListeningIconProps = { + className?: string; +}; + +export default function ListeningIcon({ className }: ListeningIconProps) { return ( + + + ); +} +``` + +### 3. Set Up Your Base CSS + +Ensure your app has CSS variables defined as fallbacks: + +```css +/* style.css */ +:root { + --white: #fff; + --gray-800: #212121; + --gray-100: #ececec; + /* ... other color definitions */ +} + +html { + --text-primary: var(--gray-800); + --surface-primary: var(--white); + /* ... other theme variables */ +} + +.dark { + --text-primary: var(--gray-100); + --surface-primary: var(--gray-900); + /* ... other dark theme variables */ +} +``` + +### 4. Configure Tailwind + +Update your `tailwind.config.js`: + +```js +module.exports = { + content: [ + './src/**/*.{js,jsx,ts,tsx}', + // Include component library files + './node_modules/@librechat/client/dist/**/*.js', + ], + darkMode: ['class'], + theme: { + extend: { + colors: { + // Map CSS variables to Tailwind colors + 'text-primary': 'var(--text-primary)', + 'surface-primary': 'var(--surface-primary)', + 'brand-purple': 'var(--brand-purple)', + // ... other colors + }, + }, + }, +}; +``` + +### 5. Use Theme Colors in Components + +```tsx +function MyComponent() { + return ( +
+

Hello World

+ +
+ ); +} +``` + +## Available Theme Colors + +### Text Colors +- `text-text-primary` - Primary text color +- `text-text-secondary` - Secondary text color +- `text-text-secondary-alt` - Alternative secondary text +- `text-text-tertiary` - Tertiary text color +- `text-text-warning` - Warning text color + +### Surface Colors +- `bg-surface-primary` - Primary background +- `bg-surface-secondary` - Secondary background +- `bg-surface-tertiary` - Tertiary background +- `bg-surface-submit` - Submit button background +- `bg-surface-destructive` - Destructive action background +- `bg-surface-dialog` - Dialog/modal background +- `bg-surface-chat` - Chat interface background + +### Border Colors +- `border-border-light` - Light border +- `border-border-medium` - Medium border +- `border-border-heavy` - Heavy border +- `border-border-xheavy` - Extra heavy border + +### Other Colors +- `bg-brand-purple` - Brand purple color +- `bg-presentation` - Presentation background +- `ring-ring-primary` - Focus ring color + +## Creating Custom Themes + +### 1. Define Your Theme + +```tsx +import { IThemeRGB } from '@librechat/client'; + +export const customTheme: IThemeRGB = { + 'rgb-text-primary': '0 0 0', // Black + 'rgb-text-secondary': '100 100 100', // Gray + 'rgb-surface-primary': '255 255 255', // White + 'rgb-surface-submit': '0 128 0', // Green + 'rgb-brand-purple': '138 43 226', // Blue Violet + // ... define other colors +}; +``` + +### 2. Use Your Custom Theme + +```tsx +import { ThemeProvider } from '@librechat/client'; +import { customTheme } from './themes/custom'; + +function App() { + return ( + + + + ); +} +``` + +## Environment Variable Themes + +Load theme colors from environment variables: + +### 1. Create Environment Variables + +```env +# .env.local +REACT_APP_THEME_BRAND_PURPLE=171 104 255 +REACT_APP_THEME_TEXT_PRIMARY=33 33 33 +REACT_APP_THEME_TEXT_SECONDARY=66 66 66 +REACT_APP_THEME_SURFACE_PRIMARY=255 255 255 +REACT_APP_THEME_SURFACE_SUBMIT=4 120 87 +``` + +### 2. Create a Theme Loader + +```tsx +function getThemeFromEnv(): IThemeRGB | undefined { + // Check if any theme environment variables are set + const hasThemeEnvVars = Object.keys(process.env).some(key => + key.startsWith('REACT_APP_THEME_') + ); + + if (!hasThemeEnvVars) { + return undefined; // Use default themes + } + + return { + 'rgb-text-primary': process.env.REACT_APP_THEME_TEXT_PRIMARY || '33 33 33', + 'rgb-brand-purple': process.env.REACT_APP_THEME_BRAND_PURPLE || '171 104 255', + // ... other colors + }; +} +``` + +### 3. Apply Environment Theme + +```tsx + + + +``` + +## Dark/Light Mode + +The ThemeProvider handles dark/light mode automatically: + +### Using the Theme Hook + +```tsx +import { useTheme } from '@librechat/client'; + +function ThemeToggle() { + const { theme, setTheme } = useTheme(); + + return ( + + ); +} +``` + +### Theme Options +- `'light'` - Force light mode +- `'dark'` - Force dark mode +- `'system'` - Follow system preference + +## Migration Guide + +If you're migrating from an older theme system: + +### 1. Update Imports + +**Before:** +```tsx +import { ThemeContext, ThemeProvider } from '~/hooks/ThemeContext'; +``` + +**After:** +```tsx +import { ThemeContext, ThemeProvider } from '@librechat/client'; +``` + +### 2. Update ThemeProvider Usage + +The new ThemeProvider is backward compatible but adds new capabilities: + +```tsx + + + +``` + +### 3. Existing Components + +Components using ThemeContext continue to work without changes: + +```tsx +// This still works! +const { theme, setTheme } = useContext(ThemeContext); +``` + +## Implementation Details + +### File Structure +``` +packages/client/src/theme/ +├── context/ +│ └── ThemeProvider.tsx # Main theme provider +├── types/ +│ └── index.ts # TypeScript interfaces +├── themes/ +│ ├── default.ts # Light theme colors +│ ├── dark.ts # Dark theme colors +│ └── index.ts # Theme exports +├── utils/ +│ ├── applyTheme.ts # Apply CSS variables +│ ├── tailwindConfig.ts # Tailwind helpers +│ └── createTailwindColors.js +├── README.md # This documentation +└── index.ts # Main exports +``` + +### CSS Variable Format + +The theme system uses RGB values in CSS variables: +- CSS Variable: `--text-primary: rgb(33 33 33)` +- Theme Definition: `'rgb-text-primary': '33 33 33'` +- Tailwind Usage: `text-text-primary` + +### RGB Format Requirements + +All color values must be in space-separated RGB format: +- ✅ Correct: `'255 255 255'` +- ❌ Incorrect: `'#ffffff'` or `'rgb(255, 255, 255)'` + +This format allows Tailwind to apply opacity modifiers like `bg-surface-primary/50`. + +## Troubleshooting + +### Common Issues + +#### 1. Colors Not Applying +- **Issue**: Custom theme colors aren't showing +- **Solution**: Ensure you're passing the `themeRGB` prop to ThemeProvider +- **Check**: CSS variables in DevTools should show `rgb(R G B)` format + +#### 2. Circular Reference Errors +- **Issue**: `--brand-purple: var(--brand-purple)` creates infinite loop +- **Solution**: Use direct color values: `--brand-purple: #ab68ff` + +#### 3. Dark Mode Not Working +- **Issue**: Dark mode doesn't switch +- **Solution**: Ensure `darkMode: ['class']` is in your Tailwind config +- **Check**: The `` element should have `class="dark"` in dark mode + +#### 4. TypeScript Errors +- **Issue**: Type errors when defining themes +- **Solution**: Import and use the `IThemeRGB` interface: +```tsx +import { IThemeRGB } from '@librechat/client'; +``` + +### Debugging Tips + +1. **Check CSS Variables**: Use browser DevTools to inspect computed CSS variables +2. **Verify Theme Application**: Look for inline styles on the root element +3. **Console Errors**: Check for validation errors in the console +4. **Test Isolation**: Try a minimal theme to isolate issues + +## Examples + +### Dynamic Theme Switching + +```tsx +import { ThemeProvider, defaultTheme, darkTheme } from '@librechat/client'; +import { useState } from 'react'; + +function App() { + const [isDark, setIsDark] = useState(false); + + return ( + + + + + ); +} +``` + +### Multi-Theme Selector + +```tsx +const themes = { + default: undefined, // Use CSS defaults + ocean: { + 'rgb-brand-purple': '0 119 190', + 'rgb-surface-primary': '240 248 255', + // ... ocean theme colors + }, + forest: { + 'rgb-brand-purple': '34 139 34', + 'rgb-surface-primary': '245 255 250', + // ... forest theme colors + }, +}; + +function App() { + const [selectedTheme, setSelectedTheme] = useState('default'); + + return ( + + + + + ); +} +``` + +### Using with the Main Application + +When using the ThemeProvider in your main application with localStorage persistence: + +```tsx +import { ThemeProvider } from '@librechat/client'; +import { getThemeFromEnv } from './utils'; + +function App() { + const envTheme = getThemeFromEnv(); + + return ( + + {/* Your app content */} + + ); +} +``` + +**Important**: Props passed to ThemeProvider will override stored values on initial mount. Only pass props when you explicitly want to override the user's saved preferences. + +## Contributing + +When adding new theme colors: + +1. Add the type definition in `types/index.ts` +2. Add the color to default and dark themes +3. Update the applyTheme mapping +4. Add to Tailwind configuration +5. Document in this README + +## License + +This theme system is part of the @librechat/client package. \ No newline at end of file diff --git a/packages/client/src/theme/atoms/themeAtoms.ts b/packages/client/src/theme/atoms/themeAtoms.ts new file mode 100644 index 0000000000..316d092fb0 --- /dev/null +++ b/packages/client/src/theme/atoms/themeAtoms.ts @@ -0,0 +1,36 @@ +import { atomWithStorage } from 'jotai/utils'; +import { IThemeRGB } from '../types'; + +/** + * Atom for storing the theme mode (light/dark/system) in localStorage + * Key: 'color-theme' + */ +export const themeModeAtom = atomWithStorage('color-theme', 'system', undefined, { + getOnInit: true, +}); + +/** + * Atom for storing custom theme colors in localStorage + * Key: 'theme-colors' + */ +export const themeColorsAtom = atomWithStorage( + 'theme-colors', + undefined, + undefined, + { + getOnInit: true, + }, +); + +/** + * Atom for storing the theme name in localStorage + * Key: 'theme-name' + */ +export const themeNameAtom = atomWithStorage( + 'theme-name', + undefined, + undefined, + { + getOnInit: true, + }, +); diff --git a/packages/client/src/theme/context/ThemeProvider.tsx b/packages/client/src/theme/context/ThemeProvider.tsx new file mode 100644 index 0000000000..c803796164 --- /dev/null +++ b/packages/client/src/theme/context/ThemeProvider.tsx @@ -0,0 +1,165 @@ +import React, { createContext, useContext, useEffect, useMemo, useCallback, useRef } from 'react'; +import { useAtom } from 'jotai'; +import { IThemeRGB } from '../types'; +import applyTheme from '../utils/applyTheme'; +import { themeModeAtom, themeColorsAtom, themeNameAtom } from '../atoms/themeAtoms'; + +type ThemeContextType = { + theme: string; // 'light' | 'dark' | 'system' + setTheme: (theme: string) => void; + themeRGB?: IThemeRGB; + setThemeRGB: (colors?: IThemeRGB) => void; + themeName?: string; + setThemeName: (name?: string) => void; + resetTheme: () => void; +}; + +// Export ThemeContext so it can be imported from hooks +export const ThemeContext = createContext({ + theme: 'system', + setTheme: () => undefined, + setThemeRGB: () => undefined, + setThemeName: () => undefined, + resetTheme: () => undefined, +}); + +export interface ThemeProviderProps { + children: React.ReactNode; + themeRGB?: IThemeRGB; + themeName?: string; + initialTheme?: string; +} + +/** + * Check if theme is dark + */ +export const isDark = (theme: string): boolean => { + if (theme === 'system') { + return window.matchMedia('(prefers-color-scheme: dark)').matches; + } + return theme === 'dark'; +}; + +/** + * ThemeProvider component that handles both dark/light mode switching + * and dynamic color themes via CSS variables with localStorage persistence + */ +export function ThemeProvider({ + children, + themeRGB: propThemeRGB, + themeName: propThemeName, + initialTheme, +}: ThemeProviderProps) { + // Use jotai atoms for persistent state + const [theme, setTheme] = useAtom(themeModeAtom); + const [storedThemeRGB, setStoredThemeRGB] = useAtom(themeColorsAtom); + const [storedThemeName, setStoredThemeName] = useAtom(themeNameAtom); + + // Track if props have been initialized + const propsInitialized = useRef(false); + + // Initialize from props only once on mount + useEffect(() => { + if (!propsInitialized.current) { + propsInitialized.current = true; + + // Set initial theme if provided + if (initialTheme) { + setTheme(initialTheme); + } + + // Set initial theme colors if provided + if (propThemeRGB) { + setStoredThemeRGB(propThemeRGB); + } + + // Set initial theme name if provided + if (propThemeName) { + setStoredThemeName(propThemeName); + } + } + }, [initialTheme, propThemeRGB, propThemeName, setTheme, setStoredThemeRGB, setStoredThemeName]); + + // Apply class-based dark mode + const applyThemeMode = useCallback((rawTheme: string) => { + const root = window.document.documentElement; + const darkMode = isDark(rawTheme); + + root.classList.remove(darkMode ? 'light' : 'dark'); + root.classList.add(darkMode ? 'dark' : 'light'); + }, []); + + // Handle system theme changes + useEffect(() => { + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + const changeThemeOnSystemChange = () => { + if (theme === 'system') { + applyThemeMode('system'); + } + }; + + mediaQuery.addEventListener('change', changeThemeOnSystemChange); + return () => { + mediaQuery.removeEventListener('change', changeThemeOnSystemChange); + }; + }, [theme, applyThemeMode]); + + // Apply dark/light mode class + useEffect(() => { + applyThemeMode(theme); + }, [theme, applyThemeMode]); + + // Apply dynamic color theme + useEffect(() => { + if (storedThemeRGB) { + applyTheme(storedThemeRGB); + } + }, [storedThemeRGB]); + + // Reset theme function + const resetTheme = useCallback(() => { + setTheme('system'); + setStoredThemeRGB(undefined); + setStoredThemeName(undefined); + // Remove any custom CSS variables + const root = document.documentElement; + const customProps = Array.from(root.style).filter((prop) => prop.startsWith('--')); + customProps.forEach((prop) => root.style.removeProperty(prop)); + }, [setTheme, setStoredThemeRGB, setStoredThemeName]); + + const value = useMemo( + () => ({ + theme, + setTheme, + themeRGB: storedThemeRGB, + setThemeRGB: setStoredThemeRGB, + themeName: storedThemeName, + setThemeName: setStoredThemeName, + resetTheme, + }), + [ + theme, + setTheme, + storedThemeRGB, + setStoredThemeRGB, + storedThemeName, + setStoredThemeName, + resetTheme, + ], + ); + + return {children}; +} + +/** + * Hook to access the current theme context + */ +export function useTheme() { + const context = useContext(ThemeContext); + if (!context) { + throw new Error('useTheme must be used within a ThemeProvider'); + } + return context; +} + +export default ThemeProvider; diff --git a/packages/client/src/theme/index.ts b/packages/client/src/theme/index.ts new file mode 100644 index 0000000000..18d02ed1e1 --- /dev/null +++ b/packages/client/src/theme/index.ts @@ -0,0 +1,14 @@ +// Export types +export * from './types'; + +// Export ThemeProvider, ThemeContext, useTheme hook, and isDark +export { ThemeProvider, ThemeContext, useTheme, isDark } from './context/ThemeProvider'; + +// Export utility functions +export { default as applyTheme } from './utils/applyTheme'; + +// Export theme atoms for persistence +export { themeModeAtom, themeColorsAtom, themeNameAtom } from './atoms/themeAtoms'; + +// Export predefined themes +export * from './themes'; diff --git a/packages/client/src/theme/themes/dark.ts b/packages/client/src/theme/themes/dark.ts new file mode 100644 index 0000000000..150fee69c7 --- /dev/null +++ b/packages/client/src/theme/themes/dark.ts @@ -0,0 +1,72 @@ +import { IThemeRGB } from '../types'; + +/** + * Dark theme + * RGB values extracted from the existing dark mode CSS variables + */ +export const darkTheme: IThemeRGB = { + // Text colors + 'rgb-text-primary': '236 236 236', // #ececec (gray-100) + 'rgb-text-secondary': '205 205 205', // #cdcdcd (gray-300) + 'rgb-text-secondary-alt': '153 150 150', // #999696 (gray-400) + 'rgb-text-tertiary': '89 89 89', // #595959 (gray-500) + 'rgb-text-warning': '245 158 11', // #f59e0b (amber-500) + + // Ring colors (not defined in dark mode, using default) + 'rgb-ring-primary': '89 89 89', // #595959 (gray-500) + + // Header colors + 'rgb-header-primary': '47 47 47', // #2f2f2f (gray-700) + 'rgb-header-hover': '66 66 66', // #424242 (gray-600) + 'rgb-header-button-hover': '47 47 47', // #2f2f2f (gray-700) + + // Surface colors + 'rgb-surface-active': '89 89 89', // #595959 (gray-500) + 'rgb-surface-active-alt': '47 47 47', // #2f2f2f (gray-700) + 'rgb-surface-hover': '66 66 66', // #424242 (gray-600) + 'rgb-surface-hover-alt': '66 66 66', // #424242 (gray-600) + 'rgb-surface-primary': '13 13 13', // #0d0d0d (gray-900) + 'rgb-surface-primary-alt': '23 23 23', // #171717 (gray-850) + 'rgb-surface-primary-contrast': '23 23 23', // #171717 (gray-850) + 'rgb-surface-secondary': '33 33 33', // #212121 (gray-800) + 'rgb-surface-secondary-alt': '33 33 33', // #212121 (gray-800) + 'rgb-surface-tertiary': '47 47 47', // #2f2f2f (gray-700) + 'rgb-surface-tertiary-alt': '47 47 47', // #2f2f2f (gray-700) + 'rgb-surface-dialog': '23 23 23', // #171717 (gray-850) + 'rgb-surface-submit': '4 120 87', // #047857 (green-700) + 'rgb-surface-submit-hover': '6 95 70', // #065f46 (green-800) + 'rgb-surface-destructive': '153 27 27', // #991b1b (red-800) + 'rgb-surface-destructive-hover': '127 29 29', // #7f1d1d (red-900) + 'rgb-surface-chat': '47 47 47', // #2f2f2f (gray-700) + + // Border colors + 'rgb-border-light': '47 47 47', // #2f2f2f (gray-700) + 'rgb-border-medium': '66 66 66', // #424242 (gray-600) + 'rgb-border-medium-alt': '66 66 66', // #424242 (gray-600) + 'rgb-border-heavy': '89 89 89', // #595959 (gray-500) + 'rgb-border-xheavy': '153 150 150', // #999696 (gray-400) + + // Brand colors + 'rgb-brand-purple': '171 104 255', // #ab68ff + + // Presentation + 'rgb-presentation': '33 33 33', // #212121 (gray-800) + + // Utility colors (mapped to existing colors for backwards compatibility) + 'rgb-background': '33 33 33', // Same as surface-primary + 'rgb-foreground': '255 255 255', // Same as text-primary + 'rgb-primary': '66 66 66', // Same as surface-active + 'rgb-primary-foreground': '255 255 255', // Same as surface-primary-contrast + 'rgb-secondary': '42 42 42', // Same as surface-secondary + 'rgb-secondary-foreground': '193 193 193', // Same as text-secondary + 'rgb-muted': '56 56 56', // Same as surface-tertiary + 'rgb-muted-foreground': '140 140 140', // Same as text-tertiary + 'rgb-accent': '82 82 82', // Same as surface-active-alt + 'rgb-accent-foreground': '255 255 255', // Same as text-primary + 'rgb-destructive-foreground': '255 255 255', // Same as text-primary + 'rgb-border': '82 82 82', // Same as border-medium + 'rgb-input': '66 66 66', // Same as border-light + 'rgb-ring': '255 255 255', // Same as ring-primary + 'rgb-card': '42 42 42', // Same as surface-secondary + 'rgb-card-foreground': '255 255 255', // Same as text-primary +}; diff --git a/packages/client/src/theme/themes/default.ts b/packages/client/src/theme/themes/default.ts new file mode 100644 index 0000000000..d636cc0c2e --- /dev/null +++ b/packages/client/src/theme/themes/default.ts @@ -0,0 +1,72 @@ +import { IThemeRGB } from '../types'; + +/** + * Default light theme + * RGB values extracted from the existing CSS variables + */ +export const defaultTheme: IThemeRGB = { + // Text colors + 'rgb-text-primary': '33 33 33', // #212121 (gray-800) + 'rgb-text-secondary': '66 66 66', // #424242 (gray-600) + 'rgb-text-secondary-alt': '89 89 89', // #595959 (gray-500) + 'rgb-text-tertiary': '89 89 89', // #595959 (gray-500) + 'rgb-text-warning': '245 158 11', // #f59e0b (amber-500) + + // Ring colors + 'rgb-ring-primary': '89 89 89', // #595959 (gray-500) + + // Header colors + 'rgb-header-primary': '255 255 255', // #fff (white) + 'rgb-header-hover': '247 247 248', // #f7f7f8 (gray-50) + 'rgb-header-button-hover': '247 247 248', // #f7f7f8 (gray-50) + + // Surface colors + 'rgb-surface-active': '236 236 236', // #ececec (gray-100) + 'rgb-surface-active-alt': '227 227 227', // #e3e3e3 (gray-200) + 'rgb-surface-hover': '227 227 227', // #e3e3e3 (gray-200) + 'rgb-surface-hover-alt': '205 205 205', // #cdcdcd (gray-300) + 'rgb-surface-primary': '255 255 255', // #fff (white) + 'rgb-surface-primary-alt': '247 247 248', // #f7f7f8 (gray-50) + 'rgb-surface-primary-contrast': '236 236 236', // #ececec (gray-100) + 'rgb-surface-secondary': '247 247 248', // #f7f7f8 (gray-50) + 'rgb-surface-secondary-alt': '227 227 227', // #e3e3e3 (gray-200) + 'rgb-surface-tertiary': '236 236 236', // #ececec (gray-100) + 'rgb-surface-tertiary-alt': '255 255 255', // #fff (white) + 'rgb-surface-dialog': '255 255 255', // #fff (white) + 'rgb-surface-submit': '4 120 87', // #047857 (green-700) + 'rgb-surface-submit-hover': '6 95 70', // #065f46 (green-800) + 'rgb-surface-destructive': '185 28 28', // #b91c1c (red-700) + 'rgb-surface-destructive-hover': '153 27 27', // #991b1b (red-800) + 'rgb-surface-chat': '255 255 255', // #fff (white) + + // Border colors + 'rgb-border-light': '227 227 227', // #e3e3e3 (gray-200) + 'rgb-border-medium': '205 205 205', // #cdcdcd (gray-300) + 'rgb-border-medium-alt': '205 205 205', // #cdcdcd (gray-300) + 'rgb-border-heavy': '153 150 150', // #999696 (gray-400) + 'rgb-border-xheavy': '89 89 89', // #595959 (gray-500) + + // Brand colors + 'rgb-brand-purple': '171 104 255', // #ab68ff + + // Presentation + 'rgb-presentation': '255 255 255', // #fff (white) + + // Utility colors (mapped to existing colors for backwards compatibility) + 'rgb-background': '255 255 255', // Same as surface-primary + 'rgb-foreground': '17 17 17', // Same as text-primary + 'rgb-primary': '235 235 235', // Same as surface-active + 'rgb-primary-foreground': '0 0 0', // Same as surface-primary-contrast + 'rgb-secondary': '247 247 248', // Same as surface-secondary + 'rgb-secondary-foreground': '66 66 66', // Same as text-secondary + 'rgb-muted': '250 250 250', // Same as surface-tertiary + 'rgb-muted-foreground': '120 120 120', // Same as text-tertiary + 'rgb-accent': '245 245 245', // Same as surface-active-alt + 'rgb-accent-foreground': '17 17 17', // Same as text-primary + 'rgb-destructive-foreground': '17 17 17', // Same as text-primary + 'rgb-border': '215 215 215', // Same as border-medium + 'rgb-input': '230 230 230', // Same as border-light + 'rgb-ring': '180 180 180', // Same as ring-primary + 'rgb-card': '247 247 248', // Same as surface-secondary + 'rgb-card-foreground': '17 17 17', // Same as text-primary +}; diff --git a/packages/client/src/theme/themes/index.ts b/packages/client/src/theme/themes/index.ts new file mode 100644 index 0000000000..89b1b0e251 --- /dev/null +++ b/packages/client/src/theme/themes/index.ts @@ -0,0 +1,2 @@ +export { defaultTheme } from './default'; +export { darkTheme } from './dark'; diff --git a/packages/client/src/theme/types/index.ts b/packages/client/src/theme/types/index.ts new file mode 100644 index 0000000000..47ab88d6b8 --- /dev/null +++ b/packages/client/src/theme/types/index.ts @@ -0,0 +1,189 @@ +/** + * Defines the color channels. Passed to the context from each app. + * RGB values should be in format "255 255 255" (space-separated) + */ +export interface IThemeRGB { + // Text colors + 'rgb-text-primary'?: string; + 'rgb-text-secondary'?: string; + 'rgb-text-secondary-alt'?: string; + 'rgb-text-tertiary'?: string; + 'rgb-text-warning'?: string; + + // Ring colors + 'rgb-ring-primary'?: string; + + // Header colors + 'rgb-header-primary'?: string; + 'rgb-header-hover'?: string; + 'rgb-header-button-hover'?: string; + + // Surface colors + 'rgb-surface-active'?: string; + 'rgb-surface-active-alt'?: string; + 'rgb-surface-hover'?: string; + 'rgb-surface-hover-alt'?: string; + 'rgb-surface-primary'?: string; + 'rgb-surface-primary-alt'?: string; + 'rgb-surface-primary-contrast'?: string; + 'rgb-surface-secondary'?: string; + 'rgb-surface-secondary-alt'?: string; + 'rgb-surface-tertiary'?: string; + 'rgb-surface-tertiary-alt'?: string; + 'rgb-surface-dialog'?: string; + 'rgb-surface-submit'?: string; + 'rgb-surface-submit-hover'?: string; + 'rgb-surface-destructive'?: string; + 'rgb-surface-destructive-hover'?: string; + 'rgb-surface-chat'?: string; + + // Border colors + 'rgb-border-light'?: string; + 'rgb-border-medium'?: string; + 'rgb-border-medium-alt'?: string; + 'rgb-border-heavy'?: string; + 'rgb-border-xheavy'?: string; + + // Brand colors + 'rgb-brand-purple'?: string; + + // Presentation + 'rgb-presentation'?: string; + + // Utility colors + 'rgb-background'?: string; + 'rgb-foreground'?: string; + 'rgb-primary'?: string; + 'rgb-primary-foreground'?: string; + 'rgb-secondary'?: string; + 'rgb-secondary-foreground'?: string; + 'rgb-muted'?: string; + 'rgb-muted-foreground'?: string; + 'rgb-accent'?: string; + 'rgb-accent-foreground'?: string; + 'rgb-destructive-foreground'?: string; + 'rgb-border'?: string; + 'rgb-input'?: string; + 'rgb-ring'?: string; + 'rgb-card'?: string; + 'rgb-card-foreground'?: string; +} + +/** + * Name of the CSS variables used in tailwind.config + */ +export interface IThemeVariables { + '--text-primary': string; + '--text-secondary': string; + '--text-secondary-alt': string; + '--text-tertiary': string; + '--text-warning': string; + '--ring-primary': string; + '--header-primary': string; + '--header-hover': string; + '--header-button-hover': string; + '--surface-active': string; + '--surface-active-alt': string; + '--surface-hover': string; + '--surface-hover-alt': string; + '--surface-primary': string; + '--surface-primary-alt': string; + '--surface-primary-contrast': string; + '--surface-secondary': string; + '--surface-secondary-alt': string; + '--surface-tertiary': string; + '--surface-tertiary-alt': string; + '--surface-dialog': string; + '--surface-submit': string; + '--surface-submit-hover': string; + '--surface-destructive': string; + '--surface-destructive-hover': string; + '--surface-chat': string; + '--border-light': string; + '--border-medium': string; + '--border-medium-alt': string; + '--border-heavy': string; + '--border-xheavy': string; + '--brand-purple': string; + '--presentation': string; + + // Utility variables + '--background': string; + '--foreground': string; + '--primary': string; + '--primary-foreground': string; + '--secondary': string; + '--secondary-foreground': string; + '--muted': string; + '--muted-foreground': string; + '--accent': string; + '--accent-foreground': string; + '--destructive-foreground': string; + '--border': string; + '--input': string; + '--ring': string; + '--card': string; + '--card-foreground': string; +} + +/** + * Name of the defined colors in the Tailwind theme + */ +export interface IThemeColors { + 'text-primary'?: string; + 'text-secondary'?: string; + 'text-secondary-alt'?: string; + 'text-tertiary'?: string; + 'text-warning'?: string; + 'ring-primary'?: string; + 'header-primary'?: string; + 'header-hover'?: string; + 'header-button-hover'?: string; + 'surface-active'?: string; + 'surface-active-alt'?: string; + 'surface-hover'?: string; + 'surface-hover-alt'?: string; + 'surface-primary'?: string; + 'surface-primary-alt'?: string; + 'surface-primary-contrast'?: string; + 'surface-secondary'?: string; + 'surface-secondary-alt'?: string; + 'surface-tertiary'?: string; + 'surface-tertiary-alt'?: string; + 'surface-dialog'?: string; + 'surface-submit'?: string; + 'surface-submit-hover'?: string; + 'surface-destructive'?: string; + 'surface-destructive-hover'?: string; + 'surface-chat'?: string; + 'border-light'?: string; + 'border-medium'?: string; + 'border-medium-alt'?: string; + 'border-heavy'?: string; + 'border-xheavy'?: string; + 'brand-purple'?: string; + presentation?: string; + + // Utility colors + background?: string; + foreground?: string; + primary?: string; + 'primary-foreground'?: string; + secondary?: string; + 'secondary-foreground'?: string; + muted?: string; + 'muted-foreground'?: string; + accent?: string; + 'accent-foreground'?: string; + 'destructive-foreground'?: string; + border?: string; + input?: string; + ring?: string; + card?: string; + 'card-foreground'?: string; +} + +export interface Theme { + name: string; + colors: IThemeRGB; +} diff --git a/packages/client/src/theme/utils/applyTheme.ts b/packages/client/src/theme/utils/applyTheme.ts new file mode 100644 index 0000000000..f98db54dd8 --- /dev/null +++ b/packages/client/src/theme/utils/applyTheme.ts @@ -0,0 +1,115 @@ +import { IThemeRGB, IThemeVariables } from '../types'; + +/** + * Validates RGB string format (e.g., "255 255 255") + */ +function validateRGB(rgb: string): boolean { + if (!rgb) return true; + const rgbRegex = /^(\d{1,3})\s+(\d{1,3})\s+(\d{1,3})$/; + const match = rgb.match(rgbRegex); + + if (!match) return false; + + // Check that each value is between 0-255 + const [, r, g, b] = match; + return [r, g, b].every((val) => { + const num = parseInt(val, 10); + return num >= 0 && num <= 255; + }); +} + +/** + * Maps theme RGB values to CSS variables + */ +function mapTheme(rgb: IThemeRGB): Partial { + const variables: Partial = {}; + + // Map each RGB value to its corresponding CSS variable + const mappings: Record = { + 'rgb-text-primary': '--text-primary', + 'rgb-text-secondary': '--text-secondary', + 'rgb-text-secondary-alt': '--text-secondary-alt', + 'rgb-text-tertiary': '--text-tertiary', + 'rgb-text-warning': '--text-warning', + 'rgb-ring-primary': '--ring-primary', + 'rgb-header-primary': '--header-primary', + 'rgb-header-hover': '--header-hover', + 'rgb-header-button-hover': '--header-button-hover', + 'rgb-surface-active': '--surface-active', + 'rgb-surface-active-alt': '--surface-active-alt', + 'rgb-surface-hover': '--surface-hover', + 'rgb-surface-hover-alt': '--surface-hover-alt', + 'rgb-surface-primary': '--surface-primary', + 'rgb-surface-primary-alt': '--surface-primary-alt', + 'rgb-surface-primary-contrast': '--surface-primary-contrast', + 'rgb-surface-secondary': '--surface-secondary', + 'rgb-surface-secondary-alt': '--surface-secondary-alt', + 'rgb-surface-tertiary': '--surface-tertiary', + 'rgb-surface-tertiary-alt': '--surface-tertiary-alt', + 'rgb-surface-dialog': '--surface-dialog', + 'rgb-surface-submit': '--surface-submit', + 'rgb-surface-submit-hover': '--surface-submit-hover', + 'rgb-surface-destructive': '--surface-destructive', + 'rgb-surface-destructive-hover': '--surface-destructive-hover', + 'rgb-surface-chat': '--surface-chat', + 'rgb-border-light': '--border-light', + 'rgb-border-medium': '--border-medium', + 'rgb-border-medium-alt': '--border-medium-alt', + 'rgb-border-heavy': '--border-heavy', + 'rgb-border-xheavy': '--border-xheavy', + 'rgb-brand-purple': '--brand-purple', + 'rgb-presentation': '--presentation', + + // Utility colors + 'rgb-background': '--background', + 'rgb-foreground': '--foreground', + 'rgb-primary': '--primary', + 'rgb-primary-foreground': '--primary-foreground', + 'rgb-secondary': '--secondary', + 'rgb-secondary-foreground': '--secondary-foreground', + 'rgb-muted': '--muted', + 'rgb-muted-foreground': '--muted-foreground', + 'rgb-accent': '--accent', + 'rgb-accent-foreground': '--accent-foreground', + 'rgb-destructive-foreground': '--destructive-foreground', + 'rgb-border': '--border', + 'rgb-input': '--input', + 'rgb-ring': '--ring', + 'rgb-card': '--card', + 'rgb-card-foreground': '--card-foreground', + }; + + Object.entries(mappings).forEach(([rgbKey, cssVar]) => { + const value = rgb[rgbKey as keyof IThemeRGB]; + if (value) { + variables[cssVar] = value; + } + }); + + return variables; +} + +/** + * Applies theme to the document root + * Sets CSS variables as rgb() values for compatibility with existing CSS + */ +export default function applyTheme(themeRGB?: IThemeRGB) { + if (!themeRGB) return; + + const themeObject = mapTheme(themeRGB); + const root = document.documentElement; + + Object.entries(themeObject).forEach(([cssVar, value]) => { + if (!value) return; + + const validation = validateRGB(value); + if (!validation) { + console.error(`Invalid RGB value for ${cssVar}: ${value}`); + return; + } + + // Set the CSS variable as rgb() value for compatibility + // This ensures existing CSS that expects color values (not space-separated RGB) continues to work + root.style.setProperty(cssVar, `rgb(${value})`); + }); +} diff --git a/packages/client/src/theme/utils/createTailwindColors.js b/packages/client/src/theme/utils/createTailwindColors.js new file mode 100644 index 0000000000..de110ac18e --- /dev/null +++ b/packages/client/src/theme/utils/createTailwindColors.js @@ -0,0 +1,86 @@ +/** + * Helper function to create a color value that uses CSS variables with alpha support + * This is a CommonJS version for use in tailwind.config.js + */ +function withOpacity(variableName) { + return ({ opacityValue }) => { + if (opacityValue !== undefined) { + // The CSS variable already contains rgb() so we need to extract the values + return `rgba(var(${variableName}), ${opacityValue})`.replace('rgb(', '').replace(')', ''); + } + return `var(${variableName})`; + }; +} + +/** + * Creates Tailwind color configuration that uses CSS variables + * This allows dynamic theme switching by changing CSS variable values + */ +function createTailwindColors() { + return { + 'text-primary': withOpacity('--text-primary'), + 'text-secondary': withOpacity('--text-secondary'), + 'text-secondary-alt': withOpacity('--text-secondary-alt'), + 'text-tertiary': withOpacity('--text-tertiary'), + 'text-warning': withOpacity('--text-warning'), + 'ring-primary': withOpacity('--ring-primary'), + 'header-primary': withOpacity('--header-primary'), + 'header-hover': withOpacity('--header-hover'), + 'header-button-hover': withOpacity('--header-button-hover'), + 'surface-active': withOpacity('--surface-active'), + 'surface-active-alt': withOpacity('--surface-active-alt'), + 'surface-hover': withOpacity('--surface-hover'), + 'surface-hover-alt': withOpacity('--surface-hover-alt'), + 'surface-primary': withOpacity('--surface-primary'), + 'surface-primary-alt': withOpacity('--surface-primary-alt'), + 'surface-primary-contrast': withOpacity('--surface-primary-contrast'), + 'surface-secondary': withOpacity('--surface-secondary'), + 'surface-secondary-alt': withOpacity('--surface-secondary-alt'), + 'surface-tertiary': withOpacity('--surface-tertiary'), + 'surface-tertiary-alt': withOpacity('--surface-tertiary-alt'), + 'surface-dialog': withOpacity('--surface-dialog'), + 'surface-submit': withOpacity('--surface-submit'), + 'surface-submit-hover': withOpacity('--surface-submit-hover'), + 'surface-destructive': withOpacity('--surface-destructive'), + 'surface-destructive-hover': withOpacity('--surface-destructive-hover'), + 'surface-chat': withOpacity('--surface-chat'), + 'border-light': withOpacity('--border-light'), + 'border-medium': withOpacity('--border-medium'), + 'border-medium-alt': withOpacity('--border-medium-alt'), + 'border-heavy': withOpacity('--border-heavy'), + 'border-xheavy': withOpacity('--border-xheavy'), + 'brand-purple': withOpacity('--brand-purple'), + presentation: withOpacity('--presentation'), + background: withOpacity('--background'), + foreground: withOpacity('--foreground'), + primary: { + DEFAULT: withOpacity('--primary'), + foreground: withOpacity('--primary-foreground'), + }, + secondary: { + DEFAULT: withOpacity('--secondary'), + foreground: withOpacity('--secondary-foreground'), + }, + muted: { + DEFAULT: withOpacity('--muted'), + foreground: withOpacity('--muted-foreground'), + }, + accent: { + DEFAULT: withOpacity('--accent'), + foreground: withOpacity('--accent-foreground'), + }, + destructive: { + DEFAULT: withOpacity('--surface-destructive'), + foreground: withOpacity('--destructive-foreground'), + }, + border: withOpacity('--border'), + input: withOpacity('--input'), + ring: withOpacity('--ring'), + card: { + DEFAULT: withOpacity('--card'), + foreground: withOpacity('--card-foreground'), + }, + }; +} + +module.exports = { createTailwindColors }; diff --git a/packages/client/src/utils/index.ts b/packages/client/src/utils/index.ts new file mode 100644 index 0000000000..94696af633 --- /dev/null +++ b/packages/client/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from './utils'; +export * from './theme'; diff --git a/client/src/utils/theme.ts b/packages/client/src/utils/theme.ts similarity index 95% rename from client/src/utils/theme.ts rename to packages/client/src/utils/theme.ts index d389dea576..a5bc645a07 100644 --- a/client/src/utils/theme.ts +++ b/packages/client/src/utils/theme.ts @@ -34,5 +34,5 @@ export const getInitialTheme = () => { } } - return 'light'; // light theme as the default; + return 'light'; }; diff --git a/packages/client/src/utils/utils.ts b/packages/client/src/utils/utils.ts new file mode 100644 index 0000000000..fad4c32a09 --- /dev/null +++ b/packages/client/src/utils/utils.ts @@ -0,0 +1,7 @@ +// ESM utility functions +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export const cn = (...inputs: ClassValue[]): string => { + return twMerge(clsx(inputs)); +}; diff --git a/packages/client/tailwind.config.js b/packages/client/tailwind.config.js new file mode 100644 index 0000000000..df7ee31c61 --- /dev/null +++ b/packages/client/tailwind.config.js @@ -0,0 +1,13 @@ +const { createTailwindColors } = require('./src/theme/utils/createTailwindColors.js'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./src/**/*.{js,jsx,ts,tsx}'], + darkMode: ['class'], + theme: { + extend: { + colors: createTailwindColors(), + }, + }, + plugins: [], +}; diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json new file mode 100644 index 0000000000..447cb1e66a --- /dev/null +++ b/packages/client/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "node", + "jsx": "react-jsx", + "jsxImportSource": "react", + "declaration": true, + "declarationMap": true, + "declarationDir": "./dist/types", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./dist", + "rootDir": "./src", + "baseUrl": "./src", + "paths": { + "~/*": ["./*"] + }, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "resolveJsonModule": true + }, + "include": ["src/**/*"], + "exclude": [ + "dist", + "node_modules", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" + ] +}