diff --git a/eslint.config.mjs b/eslint.config.mjs index a9fb714..8d99876 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -7,7 +7,7 @@ import reactHooksPlugin from 'eslint-plugin-react-hooks'; export default tseslint.config( { - ignores: ['**/node_modules/**', '**/build/**', '**/dist/**'], + ignores: ['**/node_modules', '**/build', '**/dist'], }, { name: 'default', @@ -97,6 +97,7 @@ export default tseslint.config( '@typescript-eslint/no-explicit-any': 'off', 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'error', + 'jsx-quotes': 'off', // deprecated rule, handled by prettier anyway }, }, ); diff --git a/examples/react-example/eslint.config.js b/examples/react-example/eslint.config.js deleted file mode 100644 index ea46802..0000000 --- a/examples/react-example/eslint.config.js +++ /dev/null @@ -1,23 +0,0 @@ -import js from '@eslint/js'; -import globals from 'globals'; -import reactHooks from 'eslint-plugin-react-hooks'; -import reactRefresh from 'eslint-plugin-react-refresh'; -import tseslint from 'typescript-eslint'; -import { defineConfig, globalIgnores } from 'eslint/config'; - -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs['recommended-latest'], - reactRefresh.configs.vite, - ], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - }, -]); diff --git a/examples/react-example/package.json b/examples/react-example/package.json index 6172415..24dc055 100644 --- a/examples/react-example/package.json +++ b/examples/react-example/package.json @@ -10,21 +10,23 @@ "preview": "vite preview" }, "dependencies": { + "@stream-io/ai-chat-react": "workspace:^", + "clsx": "^2.1.1", + "material-symbols": "^0.40.0", + "nanoid": "^5.1.6", "react": "^19.1.1", - "react-dom": "^19.1.1" + "react-dom": "^19.1.1", + "stream-chat": "^9.25.0", + "stream-chat-react": "^13.10.0" }, "devDependencies": { - "@eslint/js": "^9.36.0", "@types/node": "^24.6.0", "@types/react": "^19.1.16", "@types/react-dom": "^19.1.9", "@vitejs/plugin-react": "^5.0.4", - "eslint": "^9.36.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.22", "globals": "^16.4.0", - "typescript": "~5.9.3", - "typescript-eslint": "^8.45.0", + "sass-embedded": "^1.93.2", + "typescript": "catalog:", "vite": "catalog:" } } diff --git a/examples/react-example/public/vite.svg b/examples/react-example/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/examples/react-example/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/examples/react-example/src/App.css b/examples/react-example/src/App.css deleted file mode 100644 index b9d355d..0000000 --- a/examples/react-example/src/App.css +++ /dev/null @@ -1,42 +0,0 @@ -#root { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} diff --git a/examples/react-example/src/App.tsx b/examples/react-example/src/App.tsx deleted file mode 100644 index d0aac25..0000000 --- a/examples/react-example/src/App.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { useState } from 'react'; -import reactLogo from './assets/react.svg'; -import viteLogo from '/vite.svg'; -import './App.css'; - -function App() { - const [count, setCount] = useState(0); - - return ( - <> -
- - Vite logo - - - React logo - -
-

Vite + React

-
- -

- Edit src/App.tsx and save to test HMR -

-
-

- Click on the Vite and React logos to learn more -

- - ); -} - -export default App; diff --git a/examples/react-example/src/Root.tsx b/examples/react-example/src/Root.tsx new file mode 100644 index 0000000..eeb6d7b --- /dev/null +++ b/examples/react-example/src/Root.tsx @@ -0,0 +1,244 @@ +import { AIMessageComposer, StreamingMessage } from '@stream-io/ai-chat-react'; +import type { + ChannelFilters, + ChannelOptions, + ChannelSort, + LocalMessage, +} from 'stream-chat'; +import { + AIStateIndicator, + Channel, + ChannelList, + Chat, + useCreateChatClient, + MessageList, + Window, + type ChannelPreviewProps, + ChannelPreview, + useChannelStateContext, + useChatContext, + MessageInput, + useChannelActionContext, + useMessageComposer, + useMessageContext, + Attachment, + messageHasAttachments, + MessageErrorIcon, +} from 'stream-chat-react'; + +import { customAlphabet } from 'nanoid'; +import { useEffect, useMemo } from 'react'; +import clsx from 'clsx'; + +const nanoId = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 10); + +const params = new Proxy(new URLSearchParams(window.location.search), { + get: (searchParams, property) => searchParams.get(property as string), +}) as unknown as Record; + +const parseUserIdFromToken = (token: string) => { + const [, payload] = token.split('.'); + + if (!payload) throw new Error('Token is missing'); + + return JSON.parse(atob(payload))?.user_id; +}; + +const apiKey = params.key ?? (import.meta.env.VITE_STREAM_KEY as string); +const userToken = params.ut ?? (import.meta.env.VITE_USER_TOKEN as string); +const userId = parseUserIdFromToken(userToken); + +const filters: ChannelFilters = { + members: { $in: [userId] }, + type: 'messaging', + archived: false, +}; +const options: ChannelOptions = { limit: 5, presence: true, state: true }; +const sort: ChannelSort = { pinned_at: 1, last_message_at: -1, updated_at: -1 }; + +// @ts-ignore +const isMessageAIGenerated = (message: LocalMessage) => !!message?.ai_generated; + +const InputComponent = () => { + const { updateMessage, sendMessage } = useChannelActionContext(); + const { channel } = useChannelStateContext(); + const composer = useMessageComposer(); + + return ( + { + const event = e; + const target = (event.currentTarget ?? + event.target) as HTMLFormElement | null; + event.preventDefault(); + + const formData = new FormData(event.currentTarget); + + const t = formData.get('message'); + const model = formData.get('model'); + + composer.textComposer.setText(t as string); + + const d = await composer.compose(); + + if (!d) return; + + target?.reset(); + composer.clear(); + + if (channel.initialized) { + await sendMessage(d); + } else { + updateMessage(d?.localMessage); + + await channel.watch(); + + // TODO: wrap in retry (in case channel creation takes longer) + await fetch('http://localhost:3000/start-ai-agent', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + channel_id: channel.id, + channel_type: channel.type, + platform: 'openai', + model: model, + }), + }); + + await sendMessage(d); + } + }} + /> + ); +}; + +const CustomPreview = (p: ChannelPreviewProps) => { + const { setActiveChannel } = useChatContext(); + return ( +
setActiveChannel(p.channel)}> + {/* @ts-expect-error */} + {p.channel.data.summary ?? p.channel.id} +
+ ); +}; + +const EmptyPlaceholder = () => { + const { channel, setActiveChannel, client } = useChatContext(); + + useEffect(() => { + if (!channel) { + setActiveChannel( + client.channel('messaging', `ai-${nanoId()}`, { + members: [client.userID as string], + }), + ); + } + }, [channel, client, setActiveChannel]); + + return ( +
+
+ Start a conversation! +
+
+ ); +}; + +const CustomMessage = () => { + const { message, isMyMessage, highlighted, handleAction } = + useMessageContext(); + + const hasAttachment = messageHasAttachments(message); + const finalAttachments = useMemo( + () => + !message.shared_location && !message.attachments + ? [] + : !message.shared_location + ? message.attachments + : [message.shared_location, ...(message.attachments ?? [])], + [message], + ); + + const rootClassName = clsx( + 'str-chat__message str-chat__message-simple', + `str-chat__message--${message.type}`, + `str-chat__message--${message.status}`, + { + 'str-chat__message--me str-chat__message-simple--me': isMyMessage(), + 'str-chat__message--other': !isMyMessage(), + 'str-chat__message--has-text': !!message.text, + 'has-no-text': !message.text, + 'str-chat__message--has-attachment': hasAttachment, + 'str-chat__message--highlighted': highlighted, + 'str-chat__message-send-can-be-retried': + message?.status === 'failed' && message?.error?.status !== 403, + }, + ); + + return ( +
+
+
+ {finalAttachments?.length ? ( + + ) : null} + + + + +
+
+
+ ); +}; + +const App = () => { + const chatClient = useCreateChatClient({ + apiKey, + tokenOrProvider: userToken, + userData: { id: userId }, + }); + + if (!chatClient) return <>Loading...; + + return ( + + ( + + )} + filters={filters} + options={options} + sort={sort} + /> + } + Message={CustomMessage} + > + + + +
+ +
+
+
+ {/* */} +
+ ); +}; + +export default App; diff --git a/examples/react-example/src/assets/react.svg b/examples/react-example/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/examples/react-example/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/examples/react-example/src/index.css b/examples/react-example/src/index.css deleted file mode 100644 index 08a3ac9..0000000 --- a/examples/react-example/src/index.css +++ /dev/null @@ -1,68 +0,0 @@ -:root { - font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} diff --git a/examples/react-example/src/index.scss b/examples/react-example/src/index.scss new file mode 100644 index 0000000..8ba1153 --- /dev/null +++ b/examples/react-example/src/index.scss @@ -0,0 +1,72 @@ +@layer material-rounded, stream, stream-overrides, ai-chat; + +@import 'stream-chat-react/dist/css/v2/index.css' layer(stream); +@import 'material-symbols/rounded.css' layer(material-rounded); +@import '@stream-io/ai-chat-react/styles/index.css' layer(ai-chat); + +@layer stream-overrides { + .str-chat__channel { + flex-grow: 1; + } + + .str-chat__channel-list { + flex-shrink: 0; + max-width: 300px; + } + + .str-chat__message--other { + .str-chat__message-inner { + margin-inline-end: 0; + } + } + .str-chat__message--other { + .str-chat__message-bubble { + max-width: unset; + background-color: transparent; + } + } + + .str-chat__message--me { + .str-chat__message-inner { + margin-inline-start: 0; + } + } +} + +.material-symbols-outlined { + font-variation-settings: + 'FILL' 1, + 'wght' 300, + 'GRAD' 0, + 'opsz' 40; +} + +:root { + margin: 0; + padding: 0; + font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + margin: 0; + padding: 0; + width: 100vw; + height: 100vh; +} + +#root { + width: 100%; + height: 100%; + display: flex; +} diff --git a/examples/react-example/src/main.tsx b/examples/react-example/src/main.tsx index 2239905..abc6bd3 100644 --- a/examples/react-example/src/main.tsx +++ b/examples/react-example/src/main.tsx @@ -1,10 +1,10 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; -import './index.css'; -import App from './App.tsx'; +import './index.scss'; +import Root from './Root.tsx'; createRoot(document.getElementById('root')!).render( - + , ); diff --git a/examples/react-example/tsconfig.app.json b/examples/react-example/tsconfig.app.json index a9b5a59..253126d 100644 --- a/examples/react-example/tsconfig.app.json +++ b/examples/react-example/tsconfig.app.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "rootDir": "./src", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "ES2022", "useDefineForClassFields": true, diff --git a/examples/react-example/tsconfig.node.json b/examples/react-example/tsconfig.node.json index 8a67f62..a76cfab 100644 --- a/examples/react-example/tsconfig.node.json +++ b/examples/react-example/tsconfig.node.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "rootDir": ".", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2023", "lib": ["ES2023"], diff --git a/package.json b/package.json index 8070665..4ff517f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "@stream-io/ai-components-js", + "name": "@stream-io/ai-js", "private": true, - "description": "AI Components Monorepo", + "description": "JS AI Monorepo", "scripts": { "packages:build:all": "pnpm -r --filter './packages/**' run build", "packages:test:all": "pnpm -r --filter './packages/**' run test", diff --git a/packages/react-sdk/package.json b/packages/react-sdk/package.json index 20901a4..b75e98f 100644 --- a/packages/react-sdk/package.json +++ b/packages/react-sdk/package.json @@ -1,15 +1,15 @@ { - "name": "@stream-io/ai-components-react", + "name": "@stream-io/ai-chat-react", "version": "1.0.0", "private": true, - "description": "React SDK for AI Components", + "description": "React Chat SDK for AI Components", "main": "./dist/cjs/index.js", "types": "./dist/types/index.d.ts", "exports": { ".": { "types": "./dist/types/index.d.ts", "browser": { - "import": "./dist/esm/index.mjs", + "import": "./dist/es/index.mjs", "require": "./dist/cjs/index.js" }, "default": "./dist/cjs/index.js" @@ -17,10 +17,13 @@ "./stream": { "types": "./dist/types/stream/index.d.ts", "browser": { - "import": "./dist/esm/stream/index.mjs", + "import": "./dist/es/stream/index.mjs", "require": "./dist/cjs/stream/index.js" }, "default": "./dist/cjs/stream/index.js" + }, + "./styles/*": { + "default": "./dist/styles/*" } }, "files": [ @@ -29,9 +32,11 @@ "!src/*.test.ts" ], "scripts": { - "build": "rimraf ./dist && concurrently 'vite build' 'tsc -p ./tsconfig.lib.json'", - "prepare": "pnpm run build", - "test": "vitest" + "build": "rimraf ./dist && concurrently 'vite build' 'tsc -p ./tsconfig.lib.json' 'pnpm run build:styles'", + "build:styles": "sass src/styles:dist/styles --no-source-map --style=compressed", + "dev": "concurrently 'vite build --watch' 'tsc -p ./tsconfig.lib.json --watch' 'sass --watch src/styles:dist/styles'", + "prepublishOnly": "pnpm run build", + "test": "" }, "keywords": [ "ai", @@ -50,13 +55,26 @@ "react-dom": "^17 || ^18 || ^19" }, "devDependencies": { - "@types/react": "^17", - "@types/react-dom": "^17", "@types/node": "^24", - "concurrently": "catalog:", - "vite": "catalog:", + "@types/react": "^18.3.26", + "@types/react-dom": "^18.3.7", + "@types/react-syntax-highlighter": "^15.5.13", "rimraf": "^6.0.1", + "sass": "^1.94.2", + "concurrently": "catalog:", "typescript": "catalog:", + "vite": "catalog:", "vitest": "catalog:" + }, + "dependencies": { + "@stream-io/state-store": "^1.1.6", + "chart.js": "^4.5.1", + "clsx": "^2.1.1", + "nanoid": "^5.1.6", + "react-chartjs-2": "^5.3.1", + "react-markdown": "^10.1.0", + "react-syntax-highlighter": "15.5.0", + "remark-gfm": "^4.0.1", + "zod": "^4.1.12" } } diff --git a/packages/react-sdk/src/components/ai-markdown.tsx b/packages/react-sdk/src/components/ai-markdown.tsx new file mode 100644 index 0000000..74a6d36 --- /dev/null +++ b/packages/react-sdk/src/components/ai-markdown.tsx @@ -0,0 +1,206 @@ +import React, { + Children, + type ComponentProps, + type ComponentType, + type ElementType, + isValidElement, + useContext, + useMemo, +} from 'react'; +import ReactMarkdown, { + type Components, + type ExtraProps, +} from 'react-markdown'; +import remarkGfm from 'remark-gfm'; +import { Prism, type SyntaxHighlighterProps } from 'react-syntax-highlighter'; +import { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism'; +import clsx from 'clsx'; + +import { SuspendedChart } from './tools/charts/suspended'; + +const SyntaxHighlighter = + Prism as unknown as ComponentType; + +const getToolOrLanguage = (className: string = '') => { + return className.match(/language-(?[\w-]+)/)?.groups?.['tool']; +}; + +type ToolComponents = { + [key in string]?: ComponentType<{ + data: string; + fallback: React.ReactNode; + }>; +}; + +type ToolComponent = NonNullable; + +export type ToolComponentProps = + ToolComponent extends ComponentType ? P : never; + +type MarkdownComponents = Components; + +const AIMarkdownContext = React.createContext<{ + toolComponents: ToolComponents; +}>({ toolComponents: {} }); + +type BaseDefaultPreProps = ComponentProps<'pre'> & ExtraProps; + +type DefaultPreProps = BaseDefaultPreProps & { + Pre?: ComponentType | ElementType; +}; + +const DefaultPre = (props: DefaultPreProps) => { + const { children, className, Pre = 'pre', ...restProps } = props; + + const { toolComponents } = useContext(AIMarkdownContext); + + const [codeElement] = Children.toArray(children); + + if ( + isValidElement(codeElement) && + codeElement.props.node.tagName === 'code' + ) { + const toolOrLanguage = getToolOrLanguage(codeElement.props.className); + + const fallback = <>{children}; + + // grab from pre-registered component set and render + const Component = + typeof toolOrLanguage === 'string' + ? toolComponents[toolOrLanguage] + : null; + + if (Component) { + // TODO: forward metadata + + return ( + + ); + } + + // render just a fragment with the code content + // which gets replaced by SyntaxHighlighter (it itself renders pre too) + if (toolOrLanguage) { + return fallback; + } + } + + // treat as regular pre/code block if there's no tool/language + return ( +
+      {children}
+    
+ ); +}; + +const DefaultSyntaxHighlighter = ({ + children, + language, +}: BaseDefaultCodeProps) => { + return ( + + {children as string} + + ); +}; + +type BaseDefaultCodeProps = ComponentProps<'code'> & + ExtraProps & { language?: string; inline?: boolean }; + +type DefaultCodeProps = BaseDefaultCodeProps & { + Code?: ComponentType | ElementType; + SyntaxHighlighter?: ComponentType; +}; + +const DefaultCode = (props: DefaultCodeProps) => { + const { + node, + className, + children, + SyntaxHighlighter = DefaultSyntaxHighlighter, + Code = 'code', + ...restProps + } = props; + + const language = getToolOrLanguage(className); + const inline = !language; + + const Component = inline ? Code : SyntaxHighlighter; + + return ( + + {children} + + ); +}; + +const DefaultComponents = { + pre: DefaultPre, + code: DefaultCode, +} as const; + +interface AIMarkdown { + (props: { + children: string; + toolComponents?: ToolComponents; + markdownComponents?: MarkdownComponents; + }): JSX.Element; + default: typeof DefaultComponents; +} + +export const AIMarkdown: AIMarkdown = (props) => { + const mergedMarkdownComponents: MarkdownComponents = useMemo( + () => ({ + ...DefaultComponents, + ...props.markdownComponents, + }), + [props.markdownComponents], + ); + + const mergedToolComponents: ToolComponents = useMemo( + () => ({ + chartjs: SuspendedChart, + ...props.toolComponents, + }), + [props.toolComponents], + ); + + return ( + + + {props.children} + + + ); +}; + +AIMarkdown.default = DefaultComponents; diff --git a/packages/react-sdk/src/components/composer/ai-message-composer.tsx b/packages/react-sdk/src/components/composer/ai-message-composer.tsx new file mode 100644 index 0000000..6cbbdfc --- /dev/null +++ b/packages/react-sdk/src/components/composer/ai-message-composer.tsx @@ -0,0 +1,302 @@ +import { + createContext, + useCallback, + useContext, + useEffect, + useMemo, + useRef, + useState, + type ComponentProps, + type ComponentPropsWithoutRef, + type ReactNode, +} from 'react'; +import { customAlphabet } from 'nanoid'; +import { StateStore } from '@stream-io/state-store'; +import { useStateStore } from '@stream-io/state-store/react-bindings'; + +import { FilePreview } from './file-preview'; +import { useSpeechToText } from './use-speech-to-text'; +import { useStableCallback } from '../../hooks/use-stable-callback'; + +const nanoId = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 15); + +const FileInput = () => { + return ( + + {({ id }) => ( + <> + + + + )} + + ); +}; + +const FileInputBase = ({ + children, +}: { + children?: ReactNode | (({ id }: { id: string }) => ReactNode); +}) => { + const id = useMemo(() => `file-input-${nanoId()}`, []); + + return <>{typeof children === 'function' ? children({ id }) : children}; +}; + +FileInput.Base = FileInputBase; + +export type AIMessageComposerStore = { + attachments: { + id: string; + file: File; + source: string | null; + state: 'uploading' | 'uploaded' | 'failed' | 'pending'; + meta?: Record; + }[]; + text: string; +}; + +const initialStoreState: AIMessageComposerStore = { + attachments: [], + text: '', +}; + +const AIMessageComposerContext = createContext< + StateStore +>(new StateStore(initialStoreState)); + +export const useAIMessageComposerContext = () => + useContext(AIMessageComposerContext); + +export const useAttachments = () => { + const store = useAIMessageComposerContext(); + + const removeAttachment = useCallback( + (idOrFile: string | File) => { + store.next((currentState) => ({ + ...currentState, + attachments: currentState.attachments.filter((attachment) => { + if (typeof idOrFile === 'string') { + return attachment.id !== idOrFile; + } + + return attachment.file !== idOrFile; + }), + })); + }, + [store], + ); + + const selector = useCallback( + (currentState: AIMessageComposerStore) => ({ + attachments: currentState.attachments, + }), + [], + ); + + const { attachments } = useStateStore(store, selector); + + return { attachments, removeAttachment }; +}; + +export const useText = () => { + const store = useAIMessageComposerContext(); + + const selector = useCallback( + (currentState: AIMessageComposerStore) => ({ + text: currentState.text, + }), + [], + ); + + const setText = useCallback( + (text: string) => { + store.next((currentState) => { + if (currentState.text === text) { + return currentState; + } + + return { + ...currentState, + text, + }; + }); + }, + [store], + ); + + const { text } = useStateStore(store, selector); + + return { text, setText }; +}; + +export const AIMessageComposerBase = ({ + children, + onChange, + onReset, + ...restProps +}: ComponentPropsWithoutRef<'form'>) => { + const [stateStore] = useState( + () => new StateStore(initialStoreState), + ); + + const handleChange = useStableCallback( + (e: React.ChangeEvent) => { + onChange?.(e); + + const inputElement = e.target as unknown as HTMLInputElement; + + const files = inputElement.name === 'files' ? inputElement.files : null; + const text = inputElement.name === 'message' ? inputElement.value : null; + + stateStore.next((currentState) => { + const newState = { ...currentState }; + + if (files && files.length > 0) { + const newFiles = Array.from(files).map( + (file) => + ({ + id: nanoId(), + file, + source: null, + state: 'pending' as const, + }) satisfies AIMessageComposerStore['attachments'][number], + ); + + newState.attachments = newState.attachments.concat(newFiles); + } + + if (text !== null) { + newState.text = text; + } + + if ( + newState.attachments !== currentState.attachments || + newState.text !== currentState.text + ) { + return newState; + } + + return currentState; + }); + }, + ); + + return ( + +
{ + onReset?.(e); + stateStore.next(initialStoreState); + }} + {...restProps} + > + {children} +
+
+ ); +}; + +const noop = () => {}; + +const Input = () => { + const { text } = useText(); + + return ( + + ); +}; + +const SpeechToTextButton = () => { + const { setText } = useText(); + + const { startListening, stopListening, isListening } = useSpeechToText({ + onTranscript: setText, + onError: console.error, + }); + + return ( + + ); +}; + +export const AIMessageComposer = ( + props: Omit, 'children'>, +) => { + return ( + + + +
+
+ + + + {/* */} +
+ + +
+
+ ); +}; + +AIMessageComposer.Base = AIMessageComposerBase; diff --git a/packages/react-sdk/src/components/composer/file-preview.tsx b/packages/react-sdk/src/components/composer/file-preview.tsx new file mode 100644 index 0000000..82c0949 --- /dev/null +++ b/packages/react-sdk/src/components/composer/file-preview.tsx @@ -0,0 +1,122 @@ +import { + useEffect, + useState, + type ComponentPropsWithoutRef, + type CSSProperties, + type ElementType, + type PropsWithChildren, +} from 'react'; +import { + useAttachments, + type AIMessageComposerStore, +} from './ai-message-composer'; +import clsx from 'clsx'; + +const FilePreviewItem = ({ + children, + file, + component: Component = 'div', +}: PropsWithChildren<{ + file: AIMessageComposerStore['attachments'][number]; + component?: ElementType; +}> & + (ComponentPropsWithoutRef extends { + style?: CSSProperties; + className?: string; + } + ? ComponentPropsWithoutRef + : never)) => { + const [[localSource, localSourceFile], setLocalSource] = useState< + [string, File] + >([URL.createObjectURL(file.file), file.file]); + + useEffect(() => { + if (localSourceFile === file.file) + return () => { + URL.revokeObjectURL(localSource); + }; + + const newLocalSource = URL.createObjectURL(file.file); + setLocalSource([newLocalSource, file.file]); + }, [file.file, localSource, localSourceFile]); + + return ( + + {children} + + ); +}; + +const byteValueNumberFormatter = Intl.NumberFormat('en', { + notation: 'compact', + style: 'unit', + unit: 'byte', + unitDisplay: 'narrow', +}); + +export const FilePreview = () => { + const { attachments, removeAttachment } = useAttachments(); + + const filesToUpload = attachments.filter( + (attachment) => attachment.state === 'pending', + ); + + if (attachments.length === 0) return null; + + return ( +
+ {attachments.map((attachment) => { + const isImage = attachment.file.type.startsWith('image/'); + const fileName = attachment.file.name ?? 'File'; + const readableFileSize = + typeof attachment.file.size === 'number' + ? byteValueNumberFormatter.format(attachment.file.size) + : 'Unknown size'; + + return ( + + + + {!isImage && ( +
+ + description + +
+
+ {fileName} +
+
+ {readableFileSize} +
+
+
+ )} +
+ ); + })} +
+ ); +}; diff --git a/packages/react-sdk/src/components/composer/use-speech-to-text.ts b/packages/react-sdk/src/components/composer/use-speech-to-text.ts new file mode 100644 index 0000000..5d2184c --- /dev/null +++ b/packages/react-sdk/src/components/composer/use-speech-to-text.ts @@ -0,0 +1,228 @@ +import { useEffect, useRef, useState } from 'react'; +import { useStableCallback } from '../../hooks/use-stable-callback'; + +// TypeScript declarations for Web Speech API +interface SpeechRecognition extends EventTarget { + lang: string; + continuous: boolean; + interimResults: boolean; + maxAlternatives: number; + start(): void; + stop(): void; + abort(): void; + onerror: + | ((this: SpeechRecognition, ev: SpeechRecognitionErrorEvent) => any) + | null; + onresult: + | ((this: SpeechRecognition, ev: SpeechRecognitionEvent) => any) + | null; + onstart: ((this: SpeechRecognition, ev: Event) => any) | null; + onend: ((this: SpeechRecognition, ev: Event) => any) | null; +} + +interface SpeechRecognitionErrorEvent extends Event { + error: + | 'no-speech' + | 'aborted' + | 'audio-capture' + | 'network' + | 'not-allowed' + | 'service-not-allowed' + | 'bad-grammar' + | 'language-not-supported'; + message: string; +} + +interface SpeechRecognitionEvent extends Event { + resultIndex: number; + results: SpeechRecognitionResultList; +} + +interface SpeechRecognitionResultList { + length: number; + item(index: number): SpeechRecognitionResult; + [index: number]: SpeechRecognitionResult; +} + +interface SpeechRecognitionResult { + isFinal: boolean; + length: number; + item(index: number): SpeechRecognitionAlternative; + [index: number]: SpeechRecognitionAlternative; +} + +interface SpeechRecognitionAlternative { + transcript: string; + confidence: number; +} + +declare global { + interface Window { + SpeechRecognition: new () => SpeechRecognition; + webkitSpeechRecognition: new () => SpeechRecognition; + } +} + +interface UseSpeechToTextOptions { + /** + * Language for speech recognition (e.g., 'en-US', 'es-ES') + * @default 'en-US' + */ + lang?: string; + /** + * Whether to return interim (partial) results + * @default true + */ + interimResults?: boolean; + /** + * Maximum number of alternative transcriptions + * @default 1 + */ + maxAlternatives?: number; + /** + * Whether recognition should continue after user stops speaking + * @default false + */ + continuous?: boolean; + /** + * Callback when transcription text changes + */ + onTranscript?: (text: string) => void; + /** + * Callback when an error occurs + */ + onError?: (error: string) => void; +} + +export const useSpeechToText = (options: UseSpeechToTextOptions = {}) => { + const { + lang = 'en-US', + interimResults = true, + maxAlternatives = 1, + continuous = false, + onTranscript, + onError, + } = options; + + const [isListening, setIsListening] = useState(false); + const recognitionRef = useRef(null); + + // Check if Web Speech API is supported + const isSupported = + typeof window !== 'undefined' && + ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window); + + // Initialize speech recognition + useEffect(() => { + if (!isSupported) { + return; + } + + const SpeechRecognition = + window.SpeechRecognition || window.webkitSpeechRecognition; + + const recognition = new SpeechRecognition(); + recognitionRef.current = recognition; + recognition.lang = lang; + recognition.interimResults = interimResults; + recognition.maxAlternatives = maxAlternatives; + recognition.continuous = continuous; + + recognition.onresult = (event: SpeechRecognitionEvent) => { + const results = Array.from(event.results); + + const text = results.reduce((accumulatedText, result) => { + const transcript = result[0]?.transcript || ''; + + if (result.isFinal) { + accumulatedText = transcript; + } else { + accumulatedText += transcript; + } + + return accumulatedText; + }, ''); + + onTranscript?.(text); + }; + + recognition.onerror = (event: SpeechRecognitionErrorEvent) => { + let errorMessage = 'Speech recognition error'; + + switch (event.error) { + case 'no-speech': + errorMessage = 'No speech detected. Please try again.'; + break; + case 'audio-capture': + errorMessage = + 'No microphone found. Please ensure a microphone is connected.'; + break; + case 'not-allowed': + errorMessage = + 'Microphone access denied. Please grant permission to use the microphone.'; + break; + case 'network': + errorMessage = 'Network error occurred during speech recognition.'; + break; + case 'aborted': + errorMessage = 'Speech recognition was aborted.'; + break; + default: + errorMessage = `Speech recognition error: ${event.error}`; + } + + onError?.(errorMessage); + }; + + recognition.onend = () => { + setIsListening(false); + }; + + recognition.onstart = () => { + setIsListening(true); + }; + + return () => { + recognition.stop(); + recognition.onresult = null; + recognition.onerror = null; + recognition.onend = null; + recognition.onstart = null; + }; + }, [ + isSupported, + lang, + interimResults, + maxAlternatives, + continuous, + onTranscript, + onError, + ]); + + const startListening = useStableCallback(() => { + if (!isSupported) { + throw new Error('Speech recognition is not supported in this browser'); + } + + if (recognitionRef.current && !isListening) { + try { + recognitionRef.current.start(); + } catch { + onError?.('Failed to start speech recognition'); + } + } + }); + + const stopListening = useStableCallback(() => { + if (recognitionRef.current && isListening) { + recognitionRef.current.stop(); + } + }); + + return { + isListening, + isSupported, + startListening, + stopListening, + } as const; +}; diff --git a/packages/react-sdk/src/components/error-boundary.tsx b/packages/react-sdk/src/components/error-boundary.tsx new file mode 100644 index 0000000..8f3955c --- /dev/null +++ b/packages/react-sdk/src/components/error-boundary.tsx @@ -0,0 +1,30 @@ +import { Component, type PropsWithChildren, type ReactNode } from 'react'; + +type ErrorBoundaryProps = PropsWithChildren<{ + fallback: ReactNode; + onError?: (error: unknown) => void; +}>; + +export default class ErrorBoundary extends Component< + ErrorBoundaryProps, + { hasError: boolean } +> { + constructor(props: ErrorBoundaryProps) { + super(props); + this.state = { hasError: false }; + } + + static getDerivedStateFromError(error: unknown) { + // Update state so the next render will show the fallback UI. + return { hasError: true }; + } + + override render() { + if (this.state.hasError) { + // You can render any custom fallback UI + return this.props.fallback; + } + + return this.props.children; + } +} diff --git a/packages/react-sdk/src/components/streaming-message.tsx b/packages/react-sdk/src/components/streaming-message.tsx new file mode 100644 index 0000000..41eef30 --- /dev/null +++ b/packages/react-sdk/src/components/streaming-message.tsx @@ -0,0 +1,62 @@ +import { AIMarkdown } from './ai-markdown'; + +import { useEffect, useRef, useState } from 'react'; + +export type UseMessageTextStreamingProps = { + streamingLetterIntervalMs?: number; + renderingLetterCount?: number; + text: string; +}; + +const DEFAULT_LETTER_INTERVAL = 30; +const DEFAULT_RENDERING_LETTER_COUNT = 2; + +/** + * A hook that returns text in a streamed, typewriter fashion. The speed of streaming is + * configurable. + * @param {number} [streamingLetterIntervalMs=30] - The timeout between each typing animation in milliseconds. + * @param {number} [renderingLetterCount=2] - The number of letters to be rendered each time we update. + * @param {string} text - The text that we want to render in a typewriter fashion. + * @returns {{ streamedMessageText: string }} - A substring of the text property, up until we've finished rendering the typewriter animation. + */ +export const useMessageTextStreaming = ({ + renderingLetterCount = DEFAULT_RENDERING_LETTER_COUNT, + streamingLetterIntervalMs = DEFAULT_LETTER_INTERVAL, + text, +}: UseMessageTextStreamingProps): { streamedMessageText: string } => { + const [streamedMessageText, setStreamedMessageText] = useState(text); + const textCursor = useRef(text.length); + + useEffect(() => { + const textLength = text.length; + const interval = setInterval(() => { + if (!text || textCursor.current >= textLength) { + clearInterval(interval); + } + const newCursorValue = textCursor.current + renderingLetterCount; + const newText = text.substring(0, newCursorValue); + textCursor.current += newText.length - textCursor.current; + setStreamedMessageText(newText); + }, streamingLetterIntervalMs); + + return () => { + clearInterval(interval); + }; + }, [streamingLetterIntervalMs, renderingLetterCount, text]); + + return { streamedMessageText }; +}; + +export const StreamingMessage = ({ text }: { text: string }) => { + const streamedText = useMessageTextStreaming({ + text, + renderingLetterCount: 3, + streamingLetterIntervalMs: 20, + }).streamedMessageText; + + return ( +
+ {streamedText} +
+ ); +}; diff --git a/packages/react-sdk/src/components/tools/charts/chartJsSchema.ts b/packages/react-sdk/src/components/tools/charts/chartJsSchema.ts new file mode 100644 index 0000000..563e975 --- /dev/null +++ b/packages/react-sdk/src/components/tools/charts/chartJsSchema.ts @@ -0,0 +1,124 @@ +import * as zod from 'zod'; + +export const chartJsSchema = zod.object({ + type: zod.enum([ + 'pie', + 'bar', + 'line', + 'bubble', + 'doughnut', + 'polarArea', + 'radar', + 'scatter', + ]), + data: zod.object({ + labels: zod.array(zod.string()).optional(), + datasets: zod.array( + zod.object({ + label: zod.string().optional(), + data: zod.array( + zod.union([ + zod.number(), + zod.object({ + x: zod.number(), + y: zod.number(), + r: zod.number().optional(), // for bubble charts + }), + ]), + ), + backgroundColor: zod + .union([zod.string(), zod.array(zod.string())]) + .optional(), + borderColor: zod + .union([zod.string(), zod.array(zod.string())]) + .optional(), + borderWidth: zod.number().optional(), + fill: zod.boolean().optional(), + tension: zod.number().optional(), // for line charts + pointRadius: zod.number().optional(), + pointBackgroundColor: zod + .union([zod.string(), zod.array(zod.string())]) + .optional(), + hoverBackgroundColor: zod + .union([zod.string(), zod.array(zod.string())]) + .optional(), + hoverBorderColor: zod + .union([zod.string(), zod.array(zod.string())]) + .optional(), + }), + ), + }), + options: zod + .object({ + responsive: zod.boolean().optional(), + maintainAspectRatio: zod.boolean().optional(), + aspectRatio: zod.number().optional(), + plugins: zod + .object({ + title: zod + .object({ + display: zod.boolean().optional(), + text: zod.string().optional(), + align: zod.enum(['start', 'center', 'end']).optional(), + font: zod + .object({ + size: zod.number().optional(), + weight: zod.union([zod.string(), zod.number()]).optional(), + family: zod.string().optional(), + }) + .optional(), + }) + .optional(), + legend: zod + .object({ + display: zod.boolean().optional(), + position: zod.enum(['top', 'left', 'bottom', 'right']).optional(), + }) + .optional(), + tooltip: zod + .object({ + enabled: zod.boolean().optional(), + }) + .optional(), + }) + .optional(), + scales: zod + .object({ + x: zod + .object({ + display: zod.boolean().optional(), + title: zod + .object({ + display: zod.boolean().optional(), + text: zod.string().optional(), + }) + .optional(), + grid: zod + .object({ + display: zod.boolean().optional(), + }) + .optional(), + }) + .optional(), + y: zod + .object({ + display: zod.boolean().optional(), + title: zod + .object({ + display: zod.boolean().optional(), + text: zod.string().optional(), + }) + .optional(), + grid: zod + .object({ + display: zod.boolean().optional(), + }) + .optional(), + beginAtZero: zod.boolean().optional(), + }) + .optional(), + }) + .optional(), + }) + .optional(), +}); diff --git a/packages/react-sdk/src/components/tools/charts/charts.tsx b/packages/react-sdk/src/components/tools/charts/charts.tsx new file mode 100644 index 0000000..8c35473 --- /dev/null +++ b/packages/react-sdk/src/components/tools/charts/charts.tsx @@ -0,0 +1,82 @@ +import { type ComponentProps, useMemo } from 'react'; +import { + ArcElement, + BarElement, + CategoryScale, + Chart as ChartJS, + Legend, + LinearScale, + LineElement, + PointElement, + Title as TitlePlugin, + Tooltip, +} from 'chart.js'; +import { + Bar, + Bubble, + Doughnut, + Line, + Pie, + PolarArea, + Radar, + Scatter, +} from 'react-chartjs-2'; +import type { ToolComponentProps } from '../../ai-markdown'; + +ChartJS.register( + ArcElement, + Tooltip, + Legend, + CategoryScale, + LinearScale, + BarElement, + LineElement, + PointElement, + TitlePlugin, +); + +const components = { + pie: Pie, + bar: Bar, + line: Line, + bubble: Bubble, + doughnut: Doughnut, + polarArea: PolarArea, + radar: Radar, + scatter: Scatter, + unknown: () =>
Unknown chart type
, +} as const; + +const Chart = ({ data, fallback }: ToolComponentProps) => { + const parsedData = useMemo(() => { + try { + return JSON.parse(data); + } catch { + return new Error('Invalid JSON data for Chart.js'); + } + }, [data]); + + if (parsedData instanceof Error) { + return fallback; + } + + const Component = + components[parsedData.type as keyof typeof components] ?? + components.unknown; + + return ( +
+ +
+ ); +}; + +export type ChartProps = ComponentProps; + +export default Chart; + +// Context for usage: +// the application rendering these messages is capable of rendering charts using Chart.js, to render a chart return a markdown code block with language "chartjs" which contains JSON of Chart.js compatible data diff --git a/packages/react-sdk/src/components/tools/charts/suspended.tsx b/packages/react-sdk/src/components/tools/charts/suspended.tsx new file mode 100644 index 0000000..99a08ee --- /dev/null +++ b/packages/react-sdk/src/components/tools/charts/suspended.tsx @@ -0,0 +1,14 @@ +import { lazy, Suspense } from 'react'; +import type { ToolComponentProps } from '../../ai-markdown'; + +const Chart = lazy(() => import('./charts')); + +export const SuspendedChart = (props: ToolComponentProps) => { + return ( + Loading chart...} + > + + + ); +}; diff --git a/packages/react-sdk/src/components/tools/index.ts b/packages/react-sdk/src/components/tools/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/react-sdk/src/hooks/use-stable-callback.ts b/packages/react-sdk/src/hooks/use-stable-callback.ts new file mode 100644 index 0000000..8ef86ff --- /dev/null +++ b/packages/react-sdk/src/hooks/use-stable-callback.ts @@ -0,0 +1,37 @@ +import { useCallback, useRef } from 'react'; + +export type StableCallback = (...args: A) => R; + +/** + * A utility hook implementing a stable callback. It takes in an unstable method that + * is supposed to be invoked somewhere deeper in the DOM tree without making it + * change its reference every time the parent component rerenders. It will also return + * the value of the callback if it does return one. + * A common use-case would be having a function whose invocation depends on state + * somewhere high up in the DOM tree and wanting to use the same function deeper + * down, for example in a leaf node and simply using useCallback results in + * cascading dependency hell. If we wrap it in useStableCallback, we would be able + * to: + * - Use the same function as a dependency of another hook (since it is stable) + * - Still invoke it and get the latest state + * + * **Caveats:** + * - Never wrap a function that is supposed to return a React.ReactElement in + * useStableCallback, since React will not know that the DOM needs to be updated + * whenever the callback value changes (for example, renderItem from FlatList must + * never be wrapped in this hook) + * - Always prefer using a standard useCallback/stable function wherever possible + * (the purpose of useStableCallback is to bridge the gap between top level contexts + * and cascading rereders in downstream components - **not** as an escape hatch) + * @param callback - the callback we want to stabilize + */ +export const useStableCallback = ( + callback: StableCallback, +): StableCallback => { + const ref = useRef(callback); + ref.current = callback; + + return useCallback>((...args) => { + return ref.current(...args); + }, []); +}; diff --git a/packages/react-sdk/src/index.ts b/packages/react-sdk/src/index.ts index e69de29..0c9999b 100644 --- a/packages/react-sdk/src/index.ts +++ b/packages/react-sdk/src/index.ts @@ -0,0 +1,3 @@ +export * from './components/ai-markdown'; +export * from './components/composer/ai-message-composer'; +export * from './components/streaming-message'; diff --git a/packages/react-sdk/src/styles/ai-message-composer.scss b/packages/react-sdk/src/styles/ai-message-composer.scss new file mode 100644 index 0000000..b5a207f --- /dev/null +++ b/packages/react-sdk/src/styles/ai-message-composer.scss @@ -0,0 +1,62 @@ +.aicr__ai-message-composer__form { + display: flex; + padding: 0.75rem; + flex-direction: column; + gap: 1rem; + border: 1px solid #ccc; + border-radius: 1.5rem; + max-width: 600px; + flex-grow: 1; + + .aicr__ai-message-composer__round-button { + all: unset; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + padding: 0.25rem; + border-radius: 9999px; + + transition: background-color 0.1s ease-in-out; + + > span { + font-size: 1.5rem; + } + + &:hover:not(:disabled) { + background-color: #e8e8e8; + } + + &:disabled { + cursor: not-allowed; + opacity: 0.5; + } + + &[aria-pressed='true'] { + background-color: #d1eaff; + } + } + + .aicr__ai-message-composer__text-input { + all: unset; + flex-grow: 1; + font-size: 16px; + padding-inline: 0.25rem; + } + + .aicr__ai-message-composer__select { + all: unset; + display: flex; + font-size: 14px; + border: 1px solid #ccc; + border-radius: 0.5rem; + padding: 0.25rem 1rem 0.25rem 0.25rem; + + background-color: transparent; + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' height='10px' width='15px'%3E%3Ctext x='0' y='10' fill='black'%3E%E2%96%BE%3C/text%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-size: 0.75rem 0.75rem; + background-position: right center; + background-clip: border-box; + } +} diff --git a/packages/react-sdk/src/styles/file-preview.scss b/packages/react-sdk/src/styles/file-preview.scss new file mode 100644 index 0000000..b764da0 --- /dev/null +++ b/packages/react-sdk/src/styles/file-preview.scss @@ -0,0 +1,102 @@ +.aicr__file-preview { + display: flex; + gap: 0.75rem; + overflow-x: auto; + max-width: 100%; + padding-block: 0.25rem; + + &::-webkit-scrollbar { + height: 0.25rem; + } + + &::-webkit-scrollbar-track { + background: #f1f1f1; + border-radius: 0.25rem; + } + + &::-webkit-scrollbar-thumb { + background: #ddd; + border-radius: 0.25rem; + } + + &::-webkit-scrollbar-thumb:hover { + background: #ccc; + } +} + +.aicr__file-preview__item { + display: flex; + height: 4rem; + border: 1px solid #ccc; + border-radius: 0.5rem; + position: relative; + padding: 0.25rem; + + flex-grow: 0; + flex-shrink: 0; + + &--file { + flex-basis: 10rem; + } + + &--image { + flex-basis: 4rem; + background-image: var(--background-image); + background-repeat: no-repeat; + background-size: cover; + background-position: center; + } + + .aicr__file-preview__delete-button { + all: unset; + position: absolute; + top: -0.25rem; + right: -0.25rem; + display: flex; + align-items: center; + justify-content: center; + width: 1rem; + height: 1rem; + border-radius: 9999px; + background: #e8e8e8; + + transition: background 0.1s ease-in; + + &:hover:not(:disabled) { + background: #ccc; + cursor: pointer; + } + + .material-symbols-rounded { + font-size: 1rem; + font-weight: bold; + } + } + + .aicr__file-preview__item-content { + display: flex; + gap: 0.25rem; + justify-content: flex-start; + align-items: center; + width: 100%; + + .aicr__file-preview__file-metadata { + display: flex; + flex-direction: column; + flex-grow: 1; + width: 0; + + .aicr__file-preview__file-name { + font-size: 0.75rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + } + + .aicr__file-preview__file-size { + font-size: 0.5rem; + } + } + } +} diff --git a/packages/react-sdk/src/styles/index.scss b/packages/react-sdk/src/styles/index.scss new file mode 100644 index 0000000..8080afc --- /dev/null +++ b/packages/react-sdk/src/styles/index.scss @@ -0,0 +1,3 @@ +@use './file-preview.scss'; +@use './streaming-message.scss'; +@use './ai-message-composer.scss'; diff --git a/packages/react-sdk/src/styles/streaming-message.scss b/packages/react-sdk/src/styles/streaming-message.scss new file mode 100644 index 0000000..548b8f5 --- /dev/null +++ b/packages/react-sdk/src/styles/streaming-message.scss @@ -0,0 +1,79 @@ +.aicr__streaming-message { + padding: 0.5rem 0.75rem; + display: flex; + flex-direction: column; + gap: 0.5rem; + + > table { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + overflow-x: auto; + border-radius: 0.5rem; + + thead { + background-color: #f8f9fa; + border-bottom: 2px solid #dee2e6; + + th { + padding: 0.75rem; + text-align: left; + font-weight: 600; + color: #212529; + border-bottom: 2px solid #dee2e6; + } + } + + tbody { + tr { + border-bottom: 1px solid #e9ecef; + + &:hover { + background-color: #f8f9fa; + } + + &:last-child { + border-bottom: none; + } + } + + td { + padding: 0.75rem; + color: #495057; + } + } + } + + .aicr__syntax-highlighter { + font-size: 0.85rem; + + // hide last line number if it's not followed by any other elements + .linenumber:last-child { + display: none !important; + } + } + + .aicr__chart { + max-height: 20rem; + } + + > pre { + background-color: #f5f5f5; + padding: 0.5rem !important; + margin: 0 !important; + border-radius: 0.5rem; + overflow-x: auto; + } + + > p { + margin: 0; + + .aicr__code { + font-size: 0.85rem; + background-color: #f5f5f5; + padding: 0.1rem 0.25rem; + border-radius: 0.5rem; + font-family: monospace; + } + } +} diff --git a/packages/react-sdk/tsconfig.lib.json b/packages/react-sdk/tsconfig.lib.json index a3ae812..ed3e136 100644 --- a/packages/react-sdk/tsconfig.lib.json +++ b/packages/react-sdk/tsconfig.lib.json @@ -1,11 +1,13 @@ { "extends": "../../tsconfig.root.json", "compilerOptions": { + "jsx": "react-jsx", + "moduleResolution": "bundler", "rootDir": "./src", "outDir": "./dist/types", "emitDeclarationOnly": true, "declarationMap": true, - "verbatimModuleSyntax": false + "verbatimModuleSyntax": true }, "include": ["src"], "exclude": ["src/**/*.test.{ts,tsx}"] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f3e71f..2bfa9e5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,7 +52,7 @@ importers: version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) vitest: specifier: ^4.0.6 - version: 4.0.6(@types/debug@4.1.12)(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1) + version: 4.0.6(@types/debug@4.1.12)(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1) examples/nextjs-ai-chatbot: dependencies: @@ -76,7 +76,7 @@ importers: version: 0.5.19(tailwindcss@4.1.16) ai: specifier: ^5.0.76 - version: 5.0.81(zod@4.1.12) + version: 5.0.86(zod@4.1.12) animate.css: specifier: ^4.1.1 version: 4.1.1 @@ -88,7 +88,7 @@ importers: version: 0.546.0(react@19.2.0) next: specifier: 16.0.0 - version: 16.0.0(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 16.0.0(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.94.2) react: specifier: 19.2.0 version: 19.2.0 @@ -144,16 +144,31 @@ importers: examples/react-example: dependencies: + '@stream-io/ai-chat-react': + specifier: workspace:^ + version: link:../../packages/react-sdk + clsx: + specifier: ^2.1.1 + version: 2.1.1 + material-symbols: + specifier: ^0.40.0 + version: 0.40.0 + nanoid: + specifier: ^5.1.6 + version: 5.1.6 react: specifier: ^19.1.1 version: 19.2.0 react-dom: specifier: ^19.1.1 version: 19.2.0(react@19.2.0) + stream-chat: + specifier: ^9.25.0 + version: 9.25.0 + stream-chat-react: + specifier: ^13.10.0 + version: 13.12.0(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(stream-chat@9.25.0)(typescript@5.9.3) devDependencies: - '@eslint/js': - specifier: ^9.36.0 - version: 9.38.0 '@types/node': specifier: ^24.6.0 version: 24.9.1 @@ -165,34 +180,25 @@ importers: version: 19.2.2(@types/react@19.2.2) '@vitejs/plugin-react': specifier: ^5.0.4 - version: 5.0.4(vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1)) - eslint: - specifier: ^9.36.0 - version: 9.38.0(jiti@2.6.1) - eslint-plugin-react-hooks: - specifier: ^5.2.0 - version: 5.2.0(eslint@9.38.0(jiti@2.6.1)) - eslint-plugin-react-refresh: - specifier: ^0.4.22 - version: 0.4.24(eslint@9.38.0(jiti@2.6.1)) + version: 5.0.4(vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1)) globals: specifier: ^16.4.0 version: 16.4.0 + sass-embedded: + specifier: ^1.93.2 + version: 1.93.3 typescript: - specifier: ~5.9.3 + specifier: 'catalog:' version: 5.9.3 - typescript-eslint: - specifier: ^8.45.0 - version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) vite: specifier: 'catalog:' - version: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1) + version: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1) packages/node-sdk: dependencies: ai: specifier: ^5.0.0 - version: 5.0.81(zod@4.1.12) + version: 5.0.86(zod@4.1.12) stream-chat: specifier: ^9.24.0 version: 9.25.0 @@ -281,41 +287,74 @@ importers: version: 41.20.2(@shopify/react-native-skia@2.3.10(react-native-reanimated@4.1.3(@babel/core@7.28.4)(react-native-worklets@0.5.2(@babel/core@7.28.4)(react-native@0.82.1(@babel/core@7.28.4)(@types/react@19.2.2)(react@19.2.0))(react@19.2.0))(react-native@0.82.1(@babel/core@7.28.4)(@types/react@19.2.2)(react@19.2.0))(react@19.2.0))(react-native@0.82.1(@babel/core@7.28.4)(@types/react@19.2.2)(react@19.2.0))(react@19.2.0))(@types/react@19.2.2)(react-native-gesture-handler@2.29.0(react-native@0.82.1(@babel/core@7.28.4)(@types/react@19.2.2)(react@19.2.0))(react@19.2.0))(react-native-reanimated@4.1.3(@babel/core@7.28.4)(react-native-worklets@0.5.2(@babel/core@7.28.4)(react-native@0.82.1(@babel/core@7.28.4)(@types/react@19.2.2)(react@19.2.0))(react@19.2.0))(react-native@0.82.1(@babel/core@7.28.4)(@types/react@19.2.2)(react@19.2.0))(react@19.2.0))(react-native@0.82.1(@babel/core@7.28.4)(@types/react@19.2.2)(react@19.2.0))(react@19.2.0) vitest: specifier: 'catalog:' - version: 4.0.6(@types/debug@4.1.12)(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1) + version: 4.0.6(@types/debug@4.1.12)(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1) packages/react-sdk: dependencies: + '@stream-io/state-store': + specifier: ^1.1.6 + version: 1.1.6(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0)) + chart.js: + specifier: ^4.5.1 + version: 4.5.1 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + nanoid: + specifier: ^5.1.6 + version: 5.1.6 react: specifier: ^17 || ^18 || ^19 version: 19.2.0 + react-chartjs-2: + specifier: ^5.3.1 + version: 5.3.1(chart.js@4.5.1)(react@19.2.0) react-dom: specifier: ^17 || ^18 || ^19 version: 19.2.0(react@19.2.0) + react-markdown: + specifier: ^10.1.0 + version: 10.1.0(@types/react@18.3.26)(react@19.2.0) + react-syntax-highlighter: + specifier: 15.5.0 + version: 15.5.0(react@19.2.0) + remark-gfm: + specifier: ^4.0.1 + version: 4.0.1 + zod: + specifier: ^4.1.12 + version: 4.1.12 devDependencies: '@types/node': specifier: ^24 version: 24.9.1 '@types/react': - specifier: ^17 - version: 17.0.89 + specifier: ^18.3.26 + version: 18.3.26 '@types/react-dom': - specifier: ^17 - version: 17.0.26(@types/react@17.0.89) + specifier: ^18.3.7 + version: 18.3.7(@types/react@18.3.26) + '@types/react-syntax-highlighter': + specifier: ^15.5.13 + version: 15.5.13 concurrently: specifier: 'catalog:' version: 9.2.1 rimraf: specifier: ^6.0.1 version: 6.0.1 + sass: + specifier: ^1.94.2 + version: 1.94.2 typescript: specifier: 'catalog:' version: 5.9.3 vite: specifier: 'catalog:' - version: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1) + version: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1) vitest: specifier: 'catalog:' - version: 4.0.6(@types/debug@4.1.12)(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1) + version: 4.0.6(@types/debug@4.1.12)(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1) packages: @@ -327,12 +366,6 @@ packages: graphql: optional: true - '@ai-sdk/gateway@2.0.2': - resolution: {integrity: sha512-25F1qPqZxOw9IcV9OQCL29hV4HAFLw5bFWlzQLBi5aDhEZsTMT2rMi3umSqNaUxrrw+dLRtjOL7RbHC+WjbA/A==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/gateway@2.0.5': resolution: {integrity: sha512-5TTDSl0USWY6YGnb4QmJGplFZhk+p9OT7hZevAaER6OGiZ17LB1GypsGYDpNo/MiVMklk8kX4gk6p1/R/EiJ8Q==} engines: {node: '>=18'} @@ -357,12 +390,6 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@3.0.13': - resolution: {integrity: sha512-aXFLBLRPTUYA853MJliItefSXeJPl+mg0KSjbToP41kJ+banBmHO8ZPGLJhNqGlCU82o11TYN7G05EREKX8CkA==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@3.0.15': resolution: {integrity: sha512-kOc6Pxb7CsRlNt+sLZKL7/VGQUd7ccl3/tIK+Bqf5/QhHR0Qm3qRBMz1IwU1RmjJEZA73x+KB5cUckbDl2WF7Q==} engines: {node: '>=18'} @@ -406,10 +433,6 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.4': - resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} - engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.5': resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} @@ -418,10 +441,6 @@ packages: resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.3': - resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} - engines: {node: '>=6.9.0'} - '@babel/generator@7.28.5': resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} @@ -497,10 +516,6 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} @@ -521,11 +536,6 @@ packages: resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.4': - resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} - engines: {node: '>=6.0.0'} - hasBin: true - '@babel/parser@7.28.5': resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} @@ -1102,22 +1112,20 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.4': - resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} - engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.5': resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.4': - resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} - engines: {node: '>=6.9.0'} - '@babel/types@7.28.5': resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} + '@braintree/sanitize-url@6.0.4': + resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} + + '@bufbuild/protobuf@2.10.1': + resolution: {integrity: sha512-ckS3+vyJb5qGpEYv/s1OebUHDi/xSNtfgw1wqKZo7MR9F2z+qXr0q5XagafAG/9O0QPVIUfST0smluYSTpYFkg==} + '@changesets/apply-release-plan@7.0.13': resolution: {integrity: sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg==} @@ -1493,6 +1501,27 @@ packages: resolution: {integrity: sha512-ReZxZ8pdnoI3tP/dNnJdnmAk7uLT4FjsKDGW7YeDdvdOMz2XCQSmSCM9IWlrXuWtMF9zeSB6WJtEhCQ41gQOfw==} hasBin: true + '@floating-ui/core@1.7.3': + resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} + + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} + + '@floating-ui/react-dom@2.1.6': + resolution: {integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/react@0.27.16': + resolution: {integrity: sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==} + peerDependencies: + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -1724,6 +1753,9 @@ packages: react: ^18.2.0 react-dom: ^18.2.0 + '@kurkle/color@0.3.4': + resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -1807,10 +1839,116 @@ packages: resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} + '@parcel/watcher-android-arm64@2.5.1': + resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.1': + resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-win32-arm64@2.5.1': + resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.1': + resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.1': + resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.1': + resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} + engines: {node: '>= 10.0.0'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@react-aria/focus@3.21.2': + resolution: {integrity: sha512-JWaCR7wJVggj+ldmM/cb/DXFg47CXR55lznJhZBh4XVqJjMKwaOOqpT5vNN7kpC1wUpXicGNuDnJDN1S/+6dhQ==} + peerDependencies: + 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 + + '@react-aria/interactions@3.25.6': + resolution: {integrity: sha512-5UgwZmohpixwNMVkMvn9K1ceJe6TzlRlAfuYoQDUuOkk62/JVJNDLAPKIf5YMRc7d2B0rmfgaZLMtbREb0Zvkw==} + peerDependencies: + 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 + + '@react-aria/ssr@3.9.10': + resolution: {integrity: sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==} + engines: {node: '>= 12'} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-aria/utils@3.31.0': + resolution: {integrity: sha512-ABOzCsZrWzf78ysswmguJbx3McQUja7yeGj6/vZo4JVsZNlxAN+E9rs381ExBRI0KzVo6iBTeX5De8eMZPJXig==} + peerDependencies: + 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 + '@react-native/assets-registry@0.82.1': resolution: {integrity: sha512-B1SRwpntaAcckiatxbjzylvNK562Ayza05gdJCjDQHTiDafa1OABmyB5LHt7qWDOpNkaluD+w11vHF7pBmTpzQ==} engines: {node: '>= 20.19.4'} @@ -1894,6 +2032,19 @@ packages: '@types/react': optional: true + '@react-stately/flags@3.1.2': + resolution: {integrity: sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==} + + '@react-stately/utils@3.10.8': + resolution: {integrity: sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-types/shared@3.32.1': + resolution: {integrity: sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + '@rolldown/pluginutils@1.0.0-beta.38': resolution: {integrity: sha512-N/ICGKleNhA5nc9XXQG/kkKHJ7S55u0x0XUJbbkmdCnFuoRkM1Il12q9q0eX19+M7KKUEPw/daUPIRnxhcxAIw==} @@ -2056,6 +2207,10 @@ packages: '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + '@stream-io/escape-string-regexp@5.0.1': + resolution: {integrity: sha512-qIaSrzJXieZqo2fZSYTdzwSbZgHHsT3tkd646vvZhh4fr+9nO4NlvqGmPF43Y+OfZiWf+zYDFgNiPGG5+iZulQ==} + engines: {node: '>=12'} + '@stream-io/state-store@1.1.6': resolution: {integrity: sha512-4jZ7vub9EBh+zrNsA8cyW/4U2EuiCkO3T9FgZrbgorO2iBE4k8gP9GAl6w8Ikv+ZcO5jR53CeG+AA48UG3LOVQ==} peerDependencies: @@ -2067,6 +2222,10 @@ packages: use-sync-external-store: optional: true + '@stream-io/transliterate@1.5.5': + resolution: {integrity: sha512-r6Qp0HylAZhHNWHxU1nGfRI2Dtkbs1iqLCnOp1bvKhv8yj0/sEUigN0dk0LGPbE4I7zDO3tppyd7PaTPBvvJkg==} + engines: {node: '>=12'} + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -2244,10 +2403,10 @@ packages: '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - '@types/react-dom@17.0.26': - resolution: {integrity: sha512-Z+2VcYXJwOqQ79HreLU/1fyQ88eXSSFh6I3JdrEHQIfYSI0kCQpTGvOrbE6jFGGYXKsHuwY9tBa/w5Uo6KzrEg==} + '@types/react-dom@18.3.7': + resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} peerDependencies: - '@types/react': ^17.0.0 + '@types/react': ^18.0.0 '@types/react-dom@19.2.2': resolution: {integrity: sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==} @@ -2262,15 +2421,12 @@ packages: '@types/react-syntax-highlighter@15.5.13': resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==} - '@types/react@17.0.89': - resolution: {integrity: sha512-I98SaDCar5lvEYl80ClRIUztH/hyWHR+I2f+5yTVp/MQ205HgYkA2b5mVdry/+nsEIrf8I65KA5V/PASx68MsQ==} + '@types/react@18.3.26': + resolution: {integrity: sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==} '@types/react@19.2.2': resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==} - '@types/scheduler@0.16.8': - resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} - '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -2458,6 +2614,15 @@ packages: resolution: {integrity: sha512-yNEQvPcVrK9sIe637+I0jD6leluPxzwJKx/Haw6F4H77CdDsszUn5V3o96LPziXkSNE2B83+Z3mjqGKBK/R6Gg==} engines: {node: '>= 20'} + '@virtuoso.dev/react-urx@0.2.13': + resolution: {integrity: sha512-MY0ugBDjFb5Xt8v2HY7MKcRGqw/3gTpMlLXId2EwQvYJoC8sP7nnXjAxcBtTB50KTZhO0SbzsFimaZ7pSdApwA==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16' + + '@virtuoso.dev/urx@0.2.13': + resolution: {integrity: sha512-iirJNv92A1ZWxoOHHDYW/1KPoi83939o83iUBQHIim0i3tMeSKEh+bxhJdTHQ86Mr4uXx9xGUTq69cp52ZP8Xw==} + '@vitejs/plugin-react@5.0.4': resolution: {integrity: sha512-La0KD0vGkVkSk6K+piWDKRUyg8Rl5iAIKRMH0vMJI0Eg47bq1eOxmoObAaQG37WMW9MSyk7Cs8EIWwJC1PtzKA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2526,12 +2691,6 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ai@5.0.81: - resolution: {integrity: sha512-SB7oMC9QSpIu1VLswFTZuhhpfQfrGtFBUbWLtHBkhjWZIQskjtcdEhB+N4yO9hscdc2wYtjw/tacgoxX93QWFw==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - ai@5.0.86: resolution: {integrity: sha512-ooHwNTkLdedFf98iQhtSc5btc/P4UuXuOpYneoifq0190vqosLunNdW8Hs6CiE0Am7YOGNplDK56JIPlHZIL4w==} engines: {node: '>=18'} @@ -2665,6 +2824,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + attr-accept@2.2.5: + resolution: {integrity: sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==} + engines: {node: '>=4'} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -2807,6 +2970,9 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + buffer-builder@0.2.0: + resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==} + buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} @@ -2889,6 +3055,14 @@ packages: chardet@2.1.0: resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==} + chart.js@4.5.1: + resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==} + engines: {pnpm: '>=8'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + chownr@3.0.0: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} @@ -2931,6 +3105,10 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -2944,6 +3122,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorjs.io@0.5.2: + resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -3106,6 +3287,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + dayjs@1.11.19: + resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -3187,6 +3371,11 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -3412,11 +3601,6 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - eslint-plugin-react-refresh@0.4.24: - resolution: {integrity: sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==} - peerDependencies: - eslint: '>=8.40' - eslint-plugin-react@7.37.5: resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} engines: {node: '>=4'} @@ -3625,6 +3809,10 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + file-selector@2.1.2: + resolution: {integrity: sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==} + engines: {node: '>= 12'} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -3641,6 +3829,9 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} + fix-webm-duration@1.0.6: + resolution: {integrity: sha512-zVAqi4gE+8ywxJuAyV/rlJVX6CMtvyapEbQx6jyoeX9TMjdqAlt/FdG5d7rXSSkDVzTvS0H7CtwzHcH/vh4FPA==} + flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} @@ -3843,6 +4034,12 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hast-util-find-and-replace@5.0.1: + resolution: {integrity: sha512-S12fTskO3Hf2IGCBWXs1UcXT8GEJ3jmvmPZJctkRwfl3a8jnGi8aFYT8kd2zcEH+VE0qcGgKF0ewt5BPAsfIhw==} + + hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + hast-util-parse-selector@2.2.5: resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==} @@ -3917,6 +4114,14 @@ packages: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} engines: {node: '>=8.12.0'} + i18next@25.6.3: + resolution: {integrity: sha512-AEQvoPDljhp67a1+NsnG/Wb1Nh6YoSvtrmeEd24sfGn3uujCtXCF3cXpr7ulhMywKNFF7p3TX1u2j7y+caLOJg==} + peerDependencies: + typescript: ^5 + peerDependenciesMeta: + typescript: + optional: true + iconv-lite@0.7.0: resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} engines: {node: '>=0.10.0'} @@ -3937,6 +4142,9 @@ packages: engines: {node: '>=16.x'} hasBin: true + immutable@5.1.4: + resolution: {integrity: sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==} + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -4403,6 +4611,9 @@ packages: linkifyjs@4.3.2: resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==} + load-script@1.0.0: + resolution: {integrity: sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -4414,6 +4625,12 @@ packages: lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + lodash.deburr@4.1.0: + resolution: {integrity: sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==} + + lodash.defaultsdeep@4.6.1: + resolution: {integrity: sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==} + lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} @@ -4435,6 +4652,9 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} @@ -4444,6 +4664,9 @@ packages: lodash.throttle@4.1.1: resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + lodash.uniqby@4.7.0: + resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -4488,6 +4711,9 @@ packages: marky@1.3.0: resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==} + material-symbols@0.40.0: + resolution: {integrity: sha512-sz2x2x2Ealg33LB//d6dnkgsUQsdTz7a2D2Af7rH0vxFtZWDceE50iCT9L6gClTEl7YJXkAt6LFA6SN6//hFzQ==} + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -4824,6 +5050,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@5.1.6: + resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==} + engines: {node: ^18 || >=20} + hasBin: true + napi-postinstall@0.3.4: resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -4864,6 +5095,9 @@ packages: sass: optional: true + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + node-forge@1.3.1: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} @@ -5206,6 +5440,12 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true + react-chartjs-2@5.3.1: + resolution: {integrity: sha512-h5IPXKg9EXpjoBzUfyWJvllMjG2mQ4EiuHQFhms/AjUm0XSZHhyRy2xVmLXHKrtcdrPO4mnGqRtYoD0vp95A0A==} + peerDependencies: + chart.js: ^4.1.1 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-devtools-core@6.1.5: resolution: {integrity: sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==} @@ -5214,9 +5454,20 @@ packages: peerDependencies: react: ^19.2.0 + react-dropzone@14.3.8: + resolution: {integrity: sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug==} + engines: {node: '>= 10.13'} + peerDependencies: + react: '>= 16.8 || 18.0.0' + react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + react-image-gallery@1.2.12: + resolution: {integrity: sha512-JIh85lh0Av/yewseGJb/ycg00Y/weQiZEC/BQueC2Z5jnYILGB6mkxnrOevNhsM2NdZJpvcDekCluhy6uzEoTA==} + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -5229,6 +5480,12 @@ packages: '@types/react': '>=18' react: '>=18' + react-markdown@9.1.0: + resolution: {integrity: sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw==} + peerDependencies: + '@types/react': '>=18' + react: '>=18' + react-native-builder-bob@0.40.14: resolution: {integrity: sha512-NvFFehDDVT1FqZHDDriX3mm4aQVSLXz2uuLPKD2g7OIwxGvWw1BJ7vRElS03/fnpOHAY6y7vF0JEjrytEF1BRQ==} engines: {node: ^20.19.0 || ^22.12.0 || >= 23.4.0} @@ -5287,6 +5544,11 @@ packages: '@types/react': optional: true + react-player@2.10.1: + resolution: {integrity: sha512-ova0jY1Y1lqLYxOehkzbNEju4rFXYVkr5rdGD71nsiG4UKPzRXQPTd3xjoDssheoMNjZ51mjT5ysTrdQ2tEvsg==} + peerDependencies: + react: '>=16.6.0' + react-reconciler@0.31.0: resolution: {integrity: sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ==} engines: {node: '>=0.10.0'} @@ -5306,6 +5568,19 @@ packages: peerDependencies: react: '>= 0.14.0' + react-textarea-autosize@8.5.9: + resolution: {integrity: sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==} + engines: {node: '>=10'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + react-virtuoso@2.19.1: + resolution: {integrity: sha512-zF6MAwujNGy2nJWCx/Df92ay/RnV2Kj4glUZfdyadI4suAn0kAZHB1BeI7yPFVp2iSccLzFlszhakWyr+fJ4Dw==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16 || >=17 || >= 18' + react-dom: '>=16 || >=17 || >= 18' + react@19.2.0: resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} engines: {node: '>=0.10.0'} @@ -5314,6 +5589,10 @@ packages: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -5460,47 +5739,166 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sax@1.4.1: - resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} - - scheduler@0.25.0: - resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} + sass-embedded-all-unknown@1.93.3: + resolution: {integrity: sha512-3okGgnE41eg+CPLtAPletu6nQ4N0ij7AeW+Sl5Km4j29XcmqZQeFwYjHe1AlKTEgLi/UAONk1O8i8/lupeKMbw==} + cpu: ['!arm', '!arm64', '!riscv64', '!x64'] - scheduler@0.26.0: - resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + sass-embedded-android-arm64@1.93.3: + resolution: {integrity: sha512-uqUl3Kt1IqdGVAcAdbmC+NwuUJy8tM+2ZnB7/zrt6WxWVShVCRdFnWR9LT8HJr7eJN7AU8kSXxaVX/gedanPsg==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [android] - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + sass-embedded-android-arm@1.93.3: + resolution: {integrity: sha512-8xOw9bywfOD6Wv24BgCmgjkk6tMrsOTTHcb28KDxeJtFtoxiUyMbxo0vChpPAfp2Hyg2tFFKS60s0s4JYk+Raw==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [android] - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true + sass-embedded-android-riscv64@1.93.3: + resolution: {integrity: sha512-2jNJDmo+3qLocjWqYbXiBDnfgwrUeZgZFHJIwAefU7Fn66Ot7rsXl+XPwlokaCbTpj7eMFIqsRAZ/uDueXNCJg==} + engines: {node: '>=14.0.0'} + cpu: [riscv64] + os: [android] - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} - engines: {node: '>=10'} - hasBin: true + sass-embedded-android-x64@1.93.3: + resolution: {integrity: sha512-y0RoAU6ZenQFcjM9PjQd3cRqRTjqwSbtWLL/p68y2oFyh0QGN0+LQ826fc0ZvU/AbqCsAizkqjzOn6cRZJxTTQ==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [android] - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} - engines: {node: '>=10'} - hasBin: true + sass-embedded-darwin-arm64@1.93.3: + resolution: {integrity: sha512-7zb/hpdMOdKteK17BOyyypemglVURd1Hdz6QGsggy60aUFfptTLQftLRg8r/xh1RbQAUKWFbYTNaM47J9yPxYg==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [darwin] - send@0.19.0: - resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} - engines: {node: '>= 0.8.0'} + sass-embedded-darwin-x64@1.93.3: + resolution: {integrity: sha512-Ek1Vp8ZDQEe327Lz0b7h3hjvWH3u9XjJiQzveq74RPpJQ2q6d9LfWpjiRRohM4qK6o4XOHw1X10OMWPXJtdtWg==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [darwin] - serialize-error@2.1.0: - resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==} - engines: {node: '>=0.10.0'} + sass-embedded-linux-arm64@1.93.3: + resolution: {integrity: sha512-RBrHWgfd8Dd8w4fbmdRVXRrhh8oBAPyeWDTKAWw8ZEmuXfVl4ytjDuyxaVilh6rR1xTRTNpbaA/YWApBlLrrNw==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [linux] - serve-static@1.16.2: - resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} - engines: {node: '>= 0.8.0'} + sass-embedded-linux-arm@1.93.3: + resolution: {integrity: sha512-yeiv2y+dp8B4wNpd3+JsHYD0mvpXSfov7IGyQ1tMIR40qv+ROkRqYiqQvAOXf76Qwh4Y9OaYZtLpnsPjfeq6mA==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [linux] - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} + sass-embedded-linux-musl-arm64@1.93.3: + resolution: {integrity: sha512-PS829l+eUng+9W4PFclXGb4uA2+965NHV3/Sa5U7qTywjeeUUYTZg70dJHSqvhrBEfCc2XJABeW3adLJbyQYkw==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [linux] + + sass-embedded-linux-musl-arm@1.93.3: + resolution: {integrity: sha512-fU0fwAwbp7sBE3h5DVU5UPzvaLg7a4yONfFWkkcCp6ZrOiPuGRHXXYriWQ0TUnWy4wE+svsVuWhwWgvlb/tkKg==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [linux] + + sass-embedded-linux-musl-riscv64@1.93.3: + resolution: {integrity: sha512-cK1oBY+FWQquaIGEeQ5H74KTO8cWsSWwXb/WaildOO9U6wmUypTgUYKQ0o5o/29nZbWWlM1PHuwVYTSnT23Jjg==} + engines: {node: '>=14.0.0'} + cpu: [riscv64] + os: [linux] + + sass-embedded-linux-musl-x64@1.93.3: + resolution: {integrity: sha512-A7wkrsHu2/I4Zpa0NMuPGkWDVV7QGGytxGyUq3opSXgAexHo/vBPlGoDXoRlSdex0cV+aTMRPjoGIfdmNlHwyg==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] + + sass-embedded-linux-riscv64@1.93.3: + resolution: {integrity: sha512-vWkW1+HTF5qcaHa6hO80gx/QfB6GGjJUP0xLbnAoY4pwEnw5ulGv6RM8qYr8IDhWfVt/KH+lhJ2ZFxnJareisQ==} + engines: {node: '>=14.0.0'} + cpu: [riscv64] + os: [linux] + + sass-embedded-linux-x64@1.93.3: + resolution: {integrity: sha512-k6uFxs+e5jSuk1Y0niCwuq42F9ZC5UEP7P+RIOurIm8w/5QFa0+YqeW+BPWEW5M1FqVOsNZH3qGn4ahqvAEjPA==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] + + sass-embedded-unknown-all@1.93.3: + resolution: {integrity: sha512-o5wj2rLpXH0C+GJKt/VpWp6AnMsCCbfFmnMAttcrsa+U3yrs/guhZ3x55KAqqUsE8F47e3frbsDL+1OuQM5DAA==} + os: ['!android', '!darwin', '!linux', '!win32'] + + sass-embedded-win32-arm64@1.93.3: + resolution: {integrity: sha512-0dOfT9moy9YmBolodwYYXtLwNr4jL4HQC9rBfv6mVrD7ud8ue2kDbn+GVzj1hEJxvEexVSmDCf7MHUTLcGs9xQ==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [win32] + + sass-embedded-win32-x64@1.93.3: + resolution: {integrity: sha512-wHFVfxiS9hU/sNk7KReD+lJWRp3R0SLQEX4zfOnRP2zlvI2X4IQR5aZr9GNcuMP6TmNpX0nQPZTegS8+h9RrEg==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [win32] + + sass-embedded@1.93.3: + resolution: {integrity: sha512-+VUy01yfDqNmIVMd/LLKl2TTtY0ovZN0rTonh+FhKr65mFwIYgU9WzgIZKS7U9/SPCQvWTsTGx9jyt+qRm/XFw==} + engines: {node: '>=16.0.0'} + hasBin: true + + sass@1.93.3: + resolution: {integrity: sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg==} + engines: {node: '>=14.0.0'} + hasBin: true + + sass@1.94.2: + resolution: {integrity: sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==} + engines: {node: '>=14.0.0'} + hasBin: true + + sax@1.4.1: + resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + + scheduler@0.25.0: + resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} + + scheduler@0.26.0: + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + serialize-error@2.1.0: + resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==} + engines: {node: '>=0.10.0'} + + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} set-function-name@2.0.2: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} @@ -5635,6 +6033,26 @@ packages: resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==} engines: {node: '>= 0.10.0'} + stream-chat-react@13.12.0: + resolution: {integrity: sha512-Rst5l8035eBx4hSBA8m97gyrtoiKOoTvRo1nO/femr18QbHoGDnGE5qxZlSyiAotp1E9Rl0rOmQr1U86yTiG0A==} + peerDependencies: + '@breezystack/lamejs': ^1.2.7 + '@emoji-mart/data': ^1.1.0 + '@emoji-mart/react': ^1.1.0 + emoji-mart: ^5.4.0 + react: ^19.0.0 || ^18.0.0 || ^17.0.0 + react-dom: ^19.0.0 || ^18.0.0 || ^17.0.0 + stream-chat: ^9.25.0 + peerDependenciesMeta: + '@breezystack/lamejs': + optional: true + '@emoji-mart/data': + optional: true + '@emoji-mart/react': + optional: true + emoji-mart: + optional: true + stream-chat@9.25.0: resolution: {integrity: sha512-i5ZrTT2s1UIpHgHHUKDPFG8qtkjAffZYKiItS4wdj+rqWL3ovNt1X/P35QUvFRAFrawppfPDwpWp3StkpSm8oA==} engines: {node: '>=18'} @@ -5753,6 +6171,17 @@ packages: peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + sync-child-process@1.0.2: + resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==} + engines: {node: '>=16.0.0'} + + sync-message-port@1.1.3: + resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==} + engines: {node: '>=16.0.0'} + + tabbable@6.3.0: + resolution: {integrity: sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==} + tailwindcss@4.1.16: resolution: {integrity: sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==} @@ -5934,6 +6363,9 @@ packages: resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} engines: {node: '>=8'} + unist-builder@4.0.0: + resolution: {integrity: sha512-wmRFnH+BLpZnTKpc5L7O67Kac89s9HMrtELpnNaE6TAobq5DTZZs5YaTQfAZBA9bFPECx2uVAPO31c+GVug8mg==} + unist-util-is@6.0.1: resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} @@ -5973,6 +6405,33 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-composed-ref@1.4.0: + resolution: {integrity: sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + use-isomorphic-layout-effect@1.2.1: + resolution: {integrity: sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + use-latest@1.3.0: + resolution: {integrity: sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + use-sync-external-store@1.6.0: resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} peerDependencies: @@ -5993,6 +6452,9 @@ packages: resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + varint@6.0.0: + resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -6264,13 +6726,6 @@ snapshots: '@0no-co/graphql.web@1.2.0': {} - '@ai-sdk/gateway@2.0.2(zod@4.1.12)': - dependencies: - '@ai-sdk/provider': 2.0.0 - '@ai-sdk/provider-utils': 3.0.13(zod@4.1.12) - '@vercel/oidc': 3.0.3 - zod: 4.1.12 - '@ai-sdk/gateway@2.0.5(zod@4.1.12)': dependencies: '@ai-sdk/provider': 2.0.0 @@ -6296,13 +6751,6 @@ snapshots: '@ai-sdk/provider-utils': 3.0.15(zod@4.1.12) zod: 4.1.12 - '@ai-sdk/provider-utils@3.0.13(zod@4.1.12)': - dependencies: - '@ai-sdk/provider': 2.0.0 - '@standard-schema/spec': 1.0.0 - eventsource-parser: 3.0.6 - zod: 4.1.12 - '@ai-sdk/provider-utils@3.0.15(zod@4.1.12)': dependencies: '@ai-sdk/provider': 2.0.0 @@ -6345,25 +6793,23 @@ snapshots: '@babel/code-frame@7.27.1': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.4': {} - '@babel/compat-data@7.28.5': {} '@babel/core@7.28.4': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -6373,14 +6819,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.28.3': - dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - '@babel/generator@7.28.5': dependencies: '@babel/parser': 7.28.5 @@ -6391,11 +6829,11 @@ snapshots: '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.28.4 + '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 browserslist: 4.27.0 lru-cache: 5.1.1 @@ -6443,8 +6881,8 @@ snapshots: '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color @@ -6452,8 +6890,8 @@ snapshots: dependencies: '@babel/core': 7.28.4 '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.4 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color @@ -6468,7 +6906,7 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-wrap-function': 7.28.3 - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color @@ -6477,21 +6915,19 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-member-expression-to-functions': 7.28.5 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.27.1': {} - '@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-option@7.27.1': {} @@ -6499,7 +6935,7 @@ snapshots: '@babel/helper-wrap-function@7.28.3': dependencies: '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color @@ -6507,19 +6943,15 @@ snapshots: '@babel/helpers@7.28.4': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@babel/highlight@7.25.9': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 chalk: 2.4.2 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/parser@7.28.4': - dependencies: - '@babel/types': 7.28.4 - '@babel/parser@7.28.5': dependencies: '@babel/types': 7.28.5 @@ -6703,7 +7135,7 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.4) - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color @@ -6750,7 +7182,7 @@ snapshots: '@babel/helper-globals': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color @@ -6827,7 +7259,7 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color @@ -6913,7 +7345,7 @@ snapshots: '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.4) '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.4) - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color @@ -6994,7 +7426,7 @@ snapshots: '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4) - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color @@ -7210,20 +7642,8 @@ snapshots: '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 - - '@babel/traverse@7.28.4': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.4 - '@babel/template': 7.27.2 - '@babel/types': 7.28.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@babel/traverse@7.28.5': dependencies: @@ -7237,16 +7657,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/types@7.28.4': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@braintree/sanitize-url@6.0.4': {} + + '@bufbuild/protobuf@2.10.1': {} + '@changesets/apply-release-plan@7.0.13': dependencies: '@changesets/config': 3.1.1 @@ -7833,6 +8252,31 @@ snapshots: find-up: 5.0.0 js-yaml: 4.1.0 + '@floating-ui/core@1.7.3': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.4': + dependencies: + '@floating-ui/core': 1.7.3 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/react-dom@2.1.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@floating-ui/dom': 1.7.4 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + + '@floating-ui/react@0.27.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@floating-ui/react-dom': 2.1.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@floating-ui/utils': 0.2.10 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + tabbable: 6.3.0 + + '@floating-ui/utils@0.2.10': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -8056,6 +8500,8 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) + '@kurkle/color@0.3.4': {} + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.28.4 @@ -8125,14 +8571,111 @@ snapshots: '@opentelemetry/api@1.9.0': {} + '@parcel/watcher-android-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-x64@2.5.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.1': + optional: true + + '@parcel/watcher-win32-arm64@2.5.1': + optional: true + + '@parcel/watcher-win32-ia32@2.5.1': + optional: true + + '@parcel/watcher-win32-x64@2.5.1': + optional: true + + '@parcel/watcher@2.5.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.1 + '@parcel/watcher-darwin-arm64': 2.5.1 + '@parcel/watcher-darwin-x64': 2.5.1 + '@parcel/watcher-freebsd-x64': 2.5.1 + '@parcel/watcher-linux-arm-glibc': 2.5.1 + '@parcel/watcher-linux-arm-musl': 2.5.1 + '@parcel/watcher-linux-arm64-glibc': 2.5.1 + '@parcel/watcher-linux-arm64-musl': 2.5.1 + '@parcel/watcher-linux-x64-glibc': 2.5.1 + '@parcel/watcher-linux-x64-musl': 2.5.1 + '@parcel/watcher-win32-arm64': 2.5.1 + '@parcel/watcher-win32-ia32': 2.5.1 + '@parcel/watcher-win32-x64': 2.5.1 + optional: true + '@pkgjs/parseargs@0.11.0': optional: true + '@react-aria/focus@3.21.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@react-aria/interactions': 3.25.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-aria/utils': 3.31.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-types/shared': 3.32.1(react@19.2.0) + '@swc/helpers': 0.5.15 + clsx: 2.1.1 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + + '@react-aria/interactions@3.25.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@react-aria/ssr': 3.9.10(react@19.2.0) + '@react-aria/utils': 3.31.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-stately/flags': 3.1.2 + '@react-types/shared': 3.32.1(react@19.2.0) + '@swc/helpers': 0.5.15 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + + '@react-aria/ssr@3.9.10(react@19.2.0)': + dependencies: + '@swc/helpers': 0.5.15 + react: 19.2.0 + + '@react-aria/utils@3.31.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@react-aria/ssr': 3.9.10(react@19.2.0) + '@react-stately/flags': 3.1.2 + '@react-stately/utils': 3.10.8(react@19.2.0) + '@react-types/shared': 3.32.1(react@19.2.0) + '@swc/helpers': 0.5.15 + clsx: 2.1.1 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + '@react-native/assets-registry@0.82.1': {} '@react-native/babel-plugin-codegen@0.81.5(@babel/core@7.28.4)': dependencies: - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 '@react-native/codegen': 0.81.5(@babel/core@7.28.4) transitivePeerDependencies: - '@babel/core' @@ -8201,7 +8744,7 @@ snapshots: '@react-native/codegen@0.82.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 glob: 7.2.3 hermes-parser: 0.32.0 invariant: 2.2.4 @@ -8285,6 +8828,19 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 + '@react-stately/flags@3.1.2': + dependencies: + '@swc/helpers': 0.5.15 + + '@react-stately/utils@3.10.8(react@19.2.0)': + dependencies: + '@swc/helpers': 0.5.15 + react: 19.2.0 + + '@react-types/shared@3.32.1(react@19.2.0)': + dependencies: + react: 19.2.0 + '@rolldown/pluginutils@1.0.0-beta.38': {} '@rollup/rollup-android-arm-eabi@4.52.5': @@ -8409,11 +8965,20 @@ snapshots: '@standard-schema/spec@1.0.0': {} + '@stream-io/escape-string-regexp@5.0.1': + optional: true + '@stream-io/state-store@1.1.6(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0))': optionalDependencies: react: 19.2.0 use-sync-external-store: 1.6.0(react@19.2.0) + '@stream-io/transliterate@1.5.5': + dependencies: + '@stream-io/escape-string-regexp': 5.0.1 + lodash.deburr: 4.1.0 + optional: true + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -8499,24 +9064,24 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 '@types/chai@5.2.3': dependencies: @@ -8588,9 +9153,9 @@ snapshots: '@types/prop-types@15.7.15': {} - '@types/react-dom@17.0.26(@types/react@17.0.89)': + '@types/react-dom@18.3.7(@types/react@18.3.26)': dependencies: - '@types/react': 17.0.89 + '@types/react': 18.3.26 '@types/react-dom@19.2.2(@types/react@19.2.2)': dependencies: @@ -8604,18 +9169,15 @@ snapshots: dependencies: '@types/react': 19.2.2 - '@types/react@17.0.89': + '@types/react@18.3.26': dependencies: '@types/prop-types': 15.7.15 - '@types/scheduler': 0.16.8 csstype: 3.1.3 '@types/react@19.2.2': dependencies: csstype: 3.1.3 - '@types/scheduler@0.16.8': {} - '@types/stack-utils@2.0.3': {} '@types/unist@2.0.11': {} @@ -8800,7 +9362,14 @@ snapshots: '@vercel/oidc@3.0.3': {} - '@vitejs/plugin-react@5.0.4(vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))': + '@virtuoso.dev/react-urx@0.2.13(react@19.2.0)': + dependencies: + '@virtuoso.dev/urx': 0.2.13 + react: 19.2.0 + + '@virtuoso.dev/urx@0.2.13': {} + + '@vitejs/plugin-react@5.0.4(vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.4 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4) @@ -8808,7 +9377,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.38 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -8821,13 +9390,13 @@ snapshots: chai: 6.2.0 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.6(vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))': + '@vitest/mocker@4.0.6(vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1))': dependencies: '@vitest/spy': 4.0.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1) '@vitest/pretty-format@4.0.6': dependencies: @@ -8877,14 +9446,6 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ai@5.0.81(zod@4.1.12): - dependencies: - '@ai-sdk/gateway': 2.0.2(zod@4.1.12) - '@ai-sdk/provider': 2.0.0 - '@ai-sdk/provider-utils': 3.0.13(zod@4.1.12) - '@opentelemetry/api': 1.9.0 - zod: 4.1.12 - ai@5.0.86(zod@4.1.12): dependencies: '@ai-sdk/gateway': 2.0.5(zod@4.1.12) @@ -9036,6 +9597,8 @@ snapshots: asynckit@0.4.0: {} + attr-accept@2.2.5: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -9084,7 +9647,7 @@ snapshots: babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.4): dependencies: - '@babel/compat-data': 7.28.4 + '@babel/compat-data': 7.28.5 '@babel/core': 7.28.4 '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.4) semver: 6.3.1 @@ -9244,6 +9807,8 @@ snapshots: dependencies: node-int64: 0.4.0 + buffer-builder@0.2.0: {} + buffer-equal-constant-time@1.0.1: {} buffer-from@1.1.2: {} @@ -9315,6 +9880,14 @@ snapshots: chardet@2.1.0: {} + chart.js@4.5.1: + dependencies: + '@kurkle/color': 0.3.4 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + chownr@3.0.0: {} chrome-launcher@0.15.2: @@ -9359,6 +9932,8 @@ snapshots: clone@1.0.4: {} + clsx@2.1.1: {} + color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -9371,6 +9946,8 @@ snapshots: color-name@1.1.4: {} + colorjs.io@0.5.2: {} + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -9542,6 +10119,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + dayjs@1.11.19: {} + debug@2.6.9: dependencies: ms: 2.0.0 @@ -9605,6 +10184,9 @@ snapshots: detect-indent@6.1.0: {} + detect-libc@1.0.3: + optional: true + detect-libc@2.1.2: {} devlop@1.1.0: @@ -9950,10 +10532,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-react-refresh@0.4.24(eslint@9.38.0(jiti@2.6.1)): - dependencies: - eslint: 9.38.0(jiti@2.6.1) - eslint-plugin-react@7.37.5(eslint@9.38.0(jiti@2.6.1)): dependencies: array-includes: 3.1.9 @@ -10220,6 +10798,10 @@ snapshots: dependencies: flat-cache: 4.0.1 + file-selector@2.1.2: + dependencies: + tslib: 2.8.1 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -10246,6 +10828,8 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 + fix-webm-duration@1.0.6: {} + flat-cache@4.0.1: dependencies: flatted: 3.3.3 @@ -10455,6 +11039,17 @@ snapshots: dependencies: function-bind: 1.1.2 + hast-util-find-and-replace@5.0.1: + dependencies: + '@types/hast': 3.0.4 + escape-string-regexp: 5.0.0 + hast-util-is-element: 3.0.0 + unist-util-visit-parents: 6.0.2 + + hast-util-is-element@3.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-parse-selector@2.2.5: {} hast-util-to-html@9.0.5: @@ -10562,6 +11157,12 @@ snapshots: human-signals@1.1.1: {} + i18next@25.6.3(typescript@5.9.3): + dependencies: + '@babel/runtime': 7.28.4 + optionalDependencies: + typescript: 5.9.3 + iconv-lite@0.7.0: dependencies: safer-buffer: 2.1.2 @@ -10576,6 +11177,8 @@ snapshots: dependencies: queue: 6.0.2 + immutable@5.1.4: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -11062,6 +11665,8 @@ snapshots: linkifyjs@4.3.2: {} + load-script@1.0.0: {} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -11072,6 +11677,11 @@ snapshots: lodash.debounce@4.0.8: {} + lodash.deburr@4.1.0: + optional: true + + lodash.defaultsdeep@4.6.1: {} + lodash.includes@4.3.0: {} lodash.isboolean@3.0.3: {} @@ -11086,12 +11696,16 @@ snapshots: lodash.merge@4.6.2: {} + lodash.mergewith@4.6.2: {} + lodash.once@4.1.1: {} lodash.startcase@4.4.0: {} lodash.throttle@4.1.1: {} + lodash.uniqby@4.7.0: {} + lodash@4.17.21: {} log-symbols@2.2.0: @@ -11133,6 +11747,8 @@ snapshots: marky@1.3.0: {} + material-symbols@0.40.0: {} + math-intrinsics@1.1.0: {} mdast-util-find-and-replace@3.0.2: @@ -11440,7 +12056,7 @@ snapshots: metro-source-map@0.83.2: dependencies: - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 '@babel/traverse--for-generate-function-map': '@babel/traverse@7.28.5' '@babel/types': 7.28.5 flow-enums-runtime: 0.0.6 @@ -11455,9 +12071,9 @@ snapshots: metro-source-map@0.83.3: dependencies: - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 '@babel/traverse--for-generate-function-map': '@babel/traverse@7.28.5' - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 flow-enums-runtime: 0.0.6 invariant: 2.2.4 metro-symbolicate: 0.83.3 @@ -11495,7 +12111,7 @@ snapshots: '@babel/core': 7.28.4 '@babel/generator': 7.28.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 flow-enums-runtime: 0.0.6 nullthrows: 1.1.1 transitivePeerDependencies: @@ -11506,7 +12122,7 @@ snapshots: '@babel/core': 7.28.4 '@babel/generator': 7.28.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 flow-enums-runtime: 0.0.6 nullthrows: 1.1.1 transitivePeerDependencies: @@ -11559,7 +12175,7 @@ snapshots: '@babel/generator': 7.28.5 '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 + '@babel/traverse': 7.28.5 '@babel/types': 7.28.5 accepts: 1.3.8 chalk: 4.1.2 @@ -11603,11 +12219,11 @@ snapshots: dependencies: '@babel/code-frame': 7.27.1 '@babel/core': 7.28.4 - '@babel/generator': 7.28.3 - '@babel/parser': 7.28.4 + '@babel/generator': 7.28.5 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 accepts: 1.3.8 chalk: 4.1.2 ci-info: 2.0.0 @@ -11894,6 +12510,8 @@ snapshots: nanoid@3.3.11: {} + nanoid@5.1.6: {} + napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} @@ -11904,7 +12522,7 @@ snapshots: nested-error-stacks@2.0.1: {} - next@16.0.0(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + next@16.0.0(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.94.2): dependencies: '@next/env': 16.0.0 '@swc/helpers': 0.5.15 @@ -11924,11 +12542,15 @@ snapshots: '@next/swc-win32-x64-msvc': 16.0.0 '@opentelemetry/api': 1.9.0 babel-plugin-react-compiler: 1.0.0 + sass: 1.94.2 sharp: 0.34.4 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros + node-addon-api@7.1.1: + optional: true + node-forge@1.3.1: {} node-int64@0.4.0: {} @@ -12272,6 +12894,11 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 + react-chartjs-2@5.3.1(chart.js@4.5.1)(react@19.2.0): + dependencies: + chart.js: 4.5.1 + react: 19.2.0 + react-devtools-core@6.1.5: dependencies: shell-quote: 1.8.3 @@ -12285,12 +12912,41 @@ snapshots: react: 19.2.0 scheduler: 0.27.0 + react-dropzone@14.3.8(react@19.2.0): + dependencies: + attr-accept: 2.2.5 + file-selector: 2.1.2 + prop-types: 15.8.1 + react: 19.2.0 + react-fast-compare@3.2.2: {} + react-image-gallery@1.2.12(react@19.2.0): + dependencies: + react: 19.2.0 + react-is@16.13.1: {} react-is@18.3.1: {} + react-markdown@10.1.0(@types/react@18.3.26)(react@19.2.0): + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/react': 18.3.26 + devlop: 1.1.0 + hast-util-to-jsx-runtime: 2.3.6 + html-url-attributes: 3.0.1 + mdast-util-to-hast: 13.2.0 + react: 19.2.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + unified: 11.0.5 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + react-markdown@10.1.0(@types/react@19.2.2)(react@19.2.0): dependencies: '@types/hast': 3.0.4 @@ -12309,6 +12965,24 @@ snapshots: transitivePeerDependencies: - supports-color + react-markdown@9.1.0(@types/react@19.2.2)(react@19.2.0): + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/react': 19.2.2 + devlop: 1.1.0 + hast-util-to-jsx-runtime: 2.3.6 + html-url-attributes: 3.0.1 + mdast-util-to-hast: 13.2.0 + react: 19.2.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + unified: 11.0.5 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + react-native-builder-bob@0.40.14: dependencies: '@babel/core': 7.28.4 @@ -12443,6 +13117,15 @@ snapshots: - supports-color - utf-8-validate + react-player@2.10.1(react@19.2.0): + dependencies: + deepmerge: 4.3.1 + load-script: 1.0.0 + memoize-one: 5.2.1 + prop-types: 15.8.1 + react: 19.2.0 + react-fast-compare: 3.2.2 + react-reconciler@0.31.0(react@19.2.0): dependencies: react: 19.2.0 @@ -12461,6 +13144,22 @@ snapshots: react: 19.2.0 refractor: 3.6.0 + react-textarea-autosize@8.5.9(@types/react@19.2.2)(react@19.2.0): + dependencies: + '@babel/runtime': 7.28.4 + react: 19.2.0 + use-composed-ref: 1.4.0(@types/react@19.2.2)(react@19.2.0) + use-latest: 1.3.0(@types/react@19.2.2)(react@19.2.0) + transitivePeerDependencies: + - '@types/react' + + react-virtuoso@2.19.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + dependencies: + '@virtuoso.dev/react-urx': 0.2.13(react@19.2.0) + '@virtuoso.dev/urx': 0.2.13 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react@19.2.0: {} read-yaml-file@1.1.0: @@ -12470,6 +13169,8 @@ snapshots: pify: 4.0.1 strip-bom: 3.0.0 + readdirp@4.1.2: {} + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -12678,6 +13379,111 @@ snapshots: safer-buffer@2.1.2: {} + sass-embedded-all-unknown@1.93.3: + dependencies: + sass: 1.93.3 + optional: true + + sass-embedded-android-arm64@1.93.3: + optional: true + + sass-embedded-android-arm@1.93.3: + optional: true + + sass-embedded-android-riscv64@1.93.3: + optional: true + + sass-embedded-android-x64@1.93.3: + optional: true + + sass-embedded-darwin-arm64@1.93.3: + optional: true + + sass-embedded-darwin-x64@1.93.3: + optional: true + + sass-embedded-linux-arm64@1.93.3: + optional: true + + sass-embedded-linux-arm@1.93.3: + optional: true + + sass-embedded-linux-musl-arm64@1.93.3: + optional: true + + sass-embedded-linux-musl-arm@1.93.3: + optional: true + + sass-embedded-linux-musl-riscv64@1.93.3: + optional: true + + sass-embedded-linux-musl-x64@1.93.3: + optional: true + + sass-embedded-linux-riscv64@1.93.3: + optional: true + + sass-embedded-linux-x64@1.93.3: + optional: true + + sass-embedded-unknown-all@1.93.3: + dependencies: + sass: 1.93.3 + optional: true + + sass-embedded-win32-arm64@1.93.3: + optional: true + + sass-embedded-win32-x64@1.93.3: + optional: true + + sass-embedded@1.93.3: + dependencies: + '@bufbuild/protobuf': 2.10.1 + buffer-builder: 0.2.0 + colorjs.io: 0.5.2 + immutable: 5.1.4 + rxjs: 7.8.2 + supports-color: 8.1.1 + sync-child-process: 1.0.2 + varint: 6.0.0 + optionalDependencies: + sass-embedded-all-unknown: 1.93.3 + sass-embedded-android-arm: 1.93.3 + sass-embedded-android-arm64: 1.93.3 + sass-embedded-android-riscv64: 1.93.3 + sass-embedded-android-x64: 1.93.3 + sass-embedded-darwin-arm64: 1.93.3 + sass-embedded-darwin-x64: 1.93.3 + sass-embedded-linux-arm: 1.93.3 + sass-embedded-linux-arm64: 1.93.3 + sass-embedded-linux-musl-arm: 1.93.3 + sass-embedded-linux-musl-arm64: 1.93.3 + sass-embedded-linux-musl-riscv64: 1.93.3 + sass-embedded-linux-musl-x64: 1.93.3 + sass-embedded-linux-riscv64: 1.93.3 + sass-embedded-linux-x64: 1.93.3 + sass-embedded-unknown-all: 1.93.3 + sass-embedded-win32-arm64: 1.93.3 + sass-embedded-win32-x64: 1.93.3 + + sass@1.93.3: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.4 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + optional: true + + sass@1.94.2: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.4 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + sax@1.4.1: {} scheduler@0.25.0: {} @@ -12889,6 +13695,46 @@ snapshots: stream-buffers@2.2.0: {} + stream-chat-react@13.12.0(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(stream-chat@9.25.0)(typescript@5.9.3): + dependencies: + '@braintree/sanitize-url': 6.0.4 + '@floating-ui/react': 0.27.16(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-aria/focus': 3.21.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + clsx: 2.1.1 + dayjs: 1.11.19 + emoji-regex: 9.2.2 + fix-webm-duration: 1.0.6 + hast-util-find-and-replace: 5.0.1 + i18next: 25.6.3(typescript@5.9.3) + linkifyjs: 4.3.2 + lodash.debounce: 4.0.8 + lodash.defaultsdeep: 4.6.1 + lodash.mergewith: 4.6.2 + lodash.throttle: 4.1.1 + lodash.uniqby: 4.7.0 + nanoid: 3.3.11 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-dropzone: 14.3.8(react@19.2.0) + react-fast-compare: 3.2.2 + react-image-gallery: 1.2.12(react@19.2.0) + react-markdown: 9.1.0(@types/react@19.2.2)(react@19.2.0) + react-player: 2.10.1(react@19.2.0) + react-textarea-autosize: 8.5.9(@types/react@19.2.2)(react@19.2.0) + react-virtuoso: 2.19.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + remark-gfm: 4.0.1 + stream-chat: 9.25.0 + tslib: 2.8.1 + unist-builder: 4.0.0 + unist-util-visit: 5.0.0 + use-sync-external-store: 1.6.0(react@19.2.0) + optionalDependencies: + '@stream-io/transliterate': 1.5.5 + transitivePeerDependencies: + - '@types/react' + - supports-color + - typescript + stream-chat@9.25.0: dependencies: '@types/jsonwebtoken': 9.0.10 @@ -13042,6 +13888,14 @@ snapshots: react: 19.2.0 use-sync-external-store: 1.6.0(react@19.2.0) + sync-child-process@1.0.2: + dependencies: + sync-message-port: 1.1.3 + + sync-message-port@1.1.3: {} + + tabbable@6.3.0: {} + tailwindcss@4.1.16: {} tapable@2.3.0: {} @@ -13224,6 +14078,10 @@ snapshots: dependencies: crypto-random-string: 2.0.0 + unist-builder@4.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is@6.0.1: dependencies: '@types/unist': 3.0.3 @@ -13287,6 +14145,25 @@ snapshots: dependencies: punycode: 2.3.1 + use-composed-ref@1.4.0(@types/react@19.2.2)(react@19.2.0): + dependencies: + react: 19.2.0 + optionalDependencies: + '@types/react': 19.2.2 + + use-isomorphic-layout-effect@1.2.1(@types/react@19.2.2)(react@19.2.0): + dependencies: + react: 19.2.0 + optionalDependencies: + '@types/react': 19.2.2 + + use-latest@1.3.0(@types/react@19.2.2)(react@19.2.0): + dependencies: + react: 19.2.0 + use-isomorphic-layout-effect: 1.2.1(@types/react@19.2.2)(react@19.2.0) + optionalDependencies: + '@types/react': 19.2.2 + use-sync-external-store@1.6.0(react@19.2.0): dependencies: react: 19.2.0 @@ -13299,6 +14176,8 @@ snapshots: validate-npm-package-name@5.0.1: {} + varint@6.0.0: {} + vary@1.1.2: {} vfile-message@4.0.3: @@ -13326,7 +14205,7 @@ snapshots: transitivePeerDependencies: - '@types/react' - vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1): + vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1): dependencies: esbuild: 0.25.11 fdir: 6.5.0(picomatch@4.0.3) @@ -13339,13 +14218,15 @@ snapshots: fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 + sass: 1.94.2 + sass-embedded: 1.93.3 terser: 5.44.0 yaml: 2.8.1 - vitest@4.0.6(@types/debug@4.1.12)(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1): + vitest@4.0.6(@types/debug@4.1.12)(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1): dependencies: '@vitest/expect': 4.0.6 - '@vitest/mocker': 4.0.6(vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1)) + '@vitest/mocker': 4.0.6(vite@7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1)) '@vitest/pretty-format': 4.0.6 '@vitest/runner': 4.0.6 '@vitest/snapshot': 4.0.6 @@ -13362,7 +14243,7 @@ snapshots: tinyexec: 0.3.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.11(@types/node@24.9.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass-embedded@1.93.3)(sass@1.94.2)(terser@5.44.0)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12