diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b907cb9..8802aaf 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: Build, Deploy to S3, and Publish to npm +name: Build, Deploy to Azure CDN, and Publish to npm on: push: @@ -12,18 +12,22 @@ jobs: build_and_deploy: name: Build and Deploy runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + env: + AZURE_STORAGE_CONTAINER: "$web" steps: - - name: Checkout main repository and submodules + - name: Checkout repository uses: actions/checkout@v4 - with: - submodules: recursive - token: ${{ secrets.GH_TOKEN }} - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: "20" - registry-url: "https://registry.npmjs.org" + node-version: "22.14.0" + + - name: Use npm with trusted publishing support + run: npm install -g npm@11.5.1 - name: Install dependencies run: npm ci @@ -31,34 +35,56 @@ jobs: - name: Build the project run: npm run build - - name: Upload to S3 + - name: Login to Azure if: github.event_name == 'push' && github.ref == 'refs/heads/main' - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_REGION: ${{ secrets.AWS_REGION }} run: | - # Latest — short cache - aws s3 cp ./dist/app.min.js s3://${{ secrets.S3_BUCKET_NAME }}/public/scripts/app.min.js \ - --region $AWS_REGION --acl public-read \ - --cache-control "public,max-age=3600" + az login --service-principal \ + -u "${{ secrets.AZURE_CLIENT_ID }}" \ + -p "${{ secrets.AZURE_CLIENT_SECRET }}" \ + --tenant "${{ secrets.AZURE_TENANT_ID }}" \ + -o none - # Versioned — immutable cache for pinning + - name: Upload to Azure Storage + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + env: + AZURE_STORAGE_ACCOUNT: ${{ secrets.AZURE_STORAGE_ACCOUNT }} + run: | VERSION=$(node -p "require('./package.json').version") - aws s3 cp ./dist/app.min.js s3://${{ secrets.S3_BUCKET_NAME }}/public/scripts/v${VERSION}/app.min.js \ - --region $AWS_REGION --acl public-read \ - --cache-control "public,max-age=31536000,immutable" - - name: Invalidate CloudFront cache + # Latest - short cache + az storage blob upload \ + --account-name "$AZURE_STORAGE_ACCOUNT" \ + --container-name "$AZURE_STORAGE_CONTAINER" \ + --name "public/scripts/app.min.js" \ + --file "./dist/app.min.js" \ + --content-type "application/javascript" \ + --content-cache-control "public,max-age=3600" \ + --overwrite true \ + --auth-mode login + + # Versioned - immutable cache for pinning + az storage blob upload \ + --account-name "$AZURE_STORAGE_ACCOUNT" \ + --container-name "$AZURE_STORAGE_CONTAINER" \ + --name "public/scripts/v${VERSION}/app.min.js" \ + --file "./dist/app.min.js" \ + --content-type "application/javascript" \ + --content-cache-control "public,max-age=31536000,immutable" \ + --overwrite true \ + --auth-mode login + + - name: Purge Azure CDN cache if: github.event_name == 'push' && github.ref == 'refs/heads/main' env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_REGION: ${{ secrets.AWS_REGION }} + AZURE_CDN_RESOURCE_GROUP: ${{ secrets.AZURE_CDN_RESOURCE_GROUP }} + AZURE_CDN_PROFILE_NAME: ${{ secrets.AZURE_CDN_PROFILE_NAME }} + AZURE_CDN_ENDPOINT_NAME: ${{ secrets.AZURE_CDN_ENDPOINT_NAME }} run: | - aws cloudfront create-invalidation \ - --distribution-id E3SJXANXL6IYCB \ - --paths "/public/scripts/*" + az cdn endpoint purge \ + --resource-group "$AZURE_CDN_RESOURCE_GROUP" \ + --profile-name "$AZURE_CDN_PROFILE_NAME" \ + --name "$AZURE_CDN_ENDPOINT_NAME" \ + --content-paths "/public/scripts/app.min.js" - name: Publish to npm if: github.event_name == 'push' && github.ref == 'refs/heads/main' @@ -68,11 +94,9 @@ jobs: if npm view "${PKG}@${VER}" version 2>/dev/null; then echo "npm: ${PKG}@${VER} already published — skipping" else - npm publish --access public + npm publish --access public --provenance echo "npm: published ${PKG}@${VER}" fi - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} create_release: name: Create Release diff --git a/README.md b/README.md index 34e2082..a683dc1 100644 --- a/README.md +++ b/README.md @@ -57,30 +57,53 @@ Set `window.chatbotConfig` **before** loading the script: assistant_id: "your-assistant-id", token: "your-api-key", - // Optional — API endpoint (defaults to Rapida cloud) + // Optional - API endpoint (defaults to Rapida cloud) api_base: "https://assistant-01.in.rapida.ai", - // Optional — user identity + // Optional - user identity user: { name: "Jane Doe", user_id: "user-123", meta: { plan: "pro" }, }, - // Optional — appearance + // Optional - identity name: "Support Bot", logo_url: "https://example.com/avatar.png", - layout: "floating", // "floating" | "docked-right" | "docked-left" | "inline" - position: "bottom-right", // "bottom-right" | "bottom-left" | "top-right" | "top-left" - showLauncher: true, - // Optional — theme + // Optional - layout section + layout: { + mode: "floating", // "floating" | "docked-right" | "docked-left" | "inline" + position: "bottom-right", // "bottom-right" | "bottom-left" | "top-right" | "top-left" + corners: "square", + showFrame: true, + }, + + // Optional - theme section theme: { mode: "light", // "light" | "dark" | "system" - color: "#2663eb", // primary brand color (hex) + injectTheme: "g10", // "white" | "g10" | "g90" | "g100" + }, + + // Optional - AI Chat sections + aiEnabled: false, + header: { + title: "Support Bot", + showAiLabel: false, + minimizeButtonIconType: "side-panel-right", + }, + launcher: { + isOn: true, + }, + history: { + isOn: false, + }, + messaging: { + messageTimeoutSecs: 150, + messageLoadingIndicatorTimeoutSecs: 1, }, - // Optional — misc + // Optional - misc language: "en", assistant_version: "latest", debug: false, @@ -88,25 +111,281 @@ Set `window.chatbotConfig` **before** loading the script: ``` -### Configuration Reference +### Configuration Model + +The widget has two configuration layers: + +- **Rapida layer**: connection, authentication, user identity, message bridge, and audio controls. +- **UI layer**: native IBM AI Chat configuration exposed directly on `window.chatbotConfig`. + +Rapida always owns `messaging.customSendMessage` because text messages must go through `@rapidaai/react`. Rapida also appends its audio controls through `renderWriteableElements.afterInputElement`; if you provide your own `afterInputElement`, it is preserved and Rapida audio is appended after it. + +Use the sectioned config shape below. Do not use a `carbon` config key. + +### Required Rapida Options + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `assistant_id` | `string` | required | Rapida assistant/deployment ID. | +| `token` | `string` | required | Public web plugin token used to authenticate the widget. | + +### Rapida Options + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `api_base` | `string` | `https://assistant-01.in.rapida.ai` | Rapida API base URL. Use this for local or environment-specific backends. | +| `assistant_version` | `string` | `latest` | Assistant version to load when the backend supports versioned deployments. | +| `user.name` | `string` | `Guest` | Display name for the current user. | +| `user.user_id` | `string` | generated and stored locally | Stable user ID. Provide one if your host app already has an authenticated user ID. | +| `user.meta` | `Record` | `{ source: "web plugin" }` | Extra metadata sent to Rapida with the user session. | +| `language` | `string` | host page language or `en` | Locale/language passed to the UI. The widget also watches ``. | +| `debug` | `boolean` | `false` | Enables additional client logging. Also passed to the UI layer. | +| `name` | `string` | deployment name | Friendly assistant name. Used as the default `assistantName` and `header.title`. | +| `logo_url` | `string` | default assistant avatar | Assistant avatar URL. Used as the default `assistantAvatarUrl`. | + +### Theme Options + +Use `theme` for all theme-level options. + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `theme.mode` | `"light" \| "dark" \| "system"` | `"light"` | Widget color mode. `dark` defaults the UI token injection to `g100`; `light` defaults it to `g10`; `system` lets the host/system decide unless `theme.injectTheme` is set. | +| `theme.injectTheme` | `"white" \| "g10" \| "g90" \| "g100"` | derived from `theme.mode` | UI theme token injected into the chat shadow DOM. Set this when the host page does not already provide compatible theme tokens. | +| `theme.color` | `string` | none | Legacy primary brand color. Prefer `layout.customProperties` for current UI customization. | + +### Layout Options + +`layout` can be a string for old embeds or an object for the current sectioned config. + +```js +window.chatbotConfig = { + layout: { + mode: "floating", + position: "bottom-right", + corners: "square", + showFrame: true, + customProperties: { + width: "420px", + height: "640px", + }, + }, +}; +``` + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `layout` | `string \| object` | `"floating"` | Widget layout. String values are still supported: `"floating"`, `"docked-right"`, `"docked-left"`, `"inline"`. | +| `layout.mode` | `"floating" \| "docked-right" \| "docked-left" \| "inline"` | `"floating"` | Rapida placement mode. | +| `layout.position` | `"bottom-right" \| "bottom-left" \| "top-right" \| "top-left"` | `"bottom-right"` | Floating launcher and panel position. | +| `layout.showLauncher` | `boolean` | `true` for floating | Legacy launcher shortcut inside `layout`. Prefer `launcher.isOn`. | +| `layout.showFrame` | `boolean` | `true` | Keeps the native border and shadow frame. | +| `layout.hasContentMaxWidth` | `boolean` | UI default | Constrains message content to the UI max-width. | +| `layout.corners` | `"round" \| "square" \| object` | `"square"` | Corner style. Use a string for all corners or an object for per-corner control. | +| `layout.customProperties` | `Record` | generated for floating | CSS variable overrides for the chat UI. Values are raw CSS strings. | + +Per-corner `layout.corners` object: + +| Property | Type | Description | +|----------|------|-------------| +| `startStart` | `"round" \| "square"` | Top-left in LTR, top-right in RTL. | +| `startEnd` | `"round" \| "square"` | Top-right in LTR, top-left in RTL. | +| `endStart` | `"round" \| "square"` | Bottom-left in LTR, bottom-right in RTL. | +| `endEnd` | `"round" \| "square"` | Bottom-right in LTR, bottom-left in RTL. | + +Supported `layout.customProperties` keys: + +| Key | Description | +|-----|-------------| +| `height` | Floating chat height. | +| `max-height` | Floating chat maximum height. | +| `width` | Floating chat width. | +| `min-height` | Floating chat minimum height. | +| `max-width` | Floating chat maximum width. | +| `z-index` | Floating chat z-index. | +| `bottom-position` | Floating panel distance from viewport bottom. | +| `right-position` | Floating panel distance from viewport right. | +| `top-position` | Floating panel distance from viewport top. | +| `left-position` | Floating panel distance from viewport left. | +| `launcher-default-size` | Launcher button size. | +| `launcher-position-bottom` | Launcher distance from viewport bottom. | +| `launcher-position-right` | Launcher distance from viewport right. | +| `launcher-extended-width` | Expanded launcher width. | +| `messages-max-width` | Maximum width for message content. | +| `messages-min-width` | Minimum width for message content. | +| `workspace-min-width` | Minimum width for workspace panels. | +| `card-max-width` | Maximum width for card responses. | +| `launcher-color-background` | Launcher background color. | +| `launcher-color-avatar` | Launcher icon/avatar color. | +| `launcher-color-background-hover` | Launcher hover background. | +| `launcher-color-background-active` | Launcher active background. | +| `launcher-color-focus-border` | Launcher focus border color. | +| `launcher-mobile-color-text` | Mobile launcher text color. | +| `launcher-expanded-message-color-text` | Expanded launcher text color. | +| `launcher-expanded-message-color-background` | Expanded launcher background. | +| `launcher-expanded-message-color-background-hover` | Expanded launcher hover background. | +| `launcher-expanded-message-color-background-active` | Expanded launcher active background. | +| `launcher-expanded-message-color-focus-border` | Expanded launcher focus border color. | +| `unread-indicator-color-background` | Unread indicator background color. | +| `unread-indicator-color-text` | Unread indicator text color. | + +### Header Options + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `header.isOn` | `boolean` | `true` | Enables the native chat header. Set `false` for a fully embedded/fullscreen experience with your own app header. | +| `header.title` | `string` | `name` or deployment name | Header title. Set `""` to remove the visible title. | +| `header.name` | `string` | UI default | Secondary name shown after the title. Set `""` to remove it. | +| `header.minimizeButtonIconType` | `"close" \| "minimize" \| "side-panel-left" \| "side-panel-right" \| "side-panel-down"` | side-panel icon based on dock side | Icon for the close/minimize button. | +| `header.hideMinimizeButton` | `boolean` | `false` | Hides the close/minimize button. | +| `header.showRestartButton` | `boolean` | `false` | Shows the restart conversation button. | +| `header.menuOptions` | `Array<{ text: string }>` | none | Custom menu options in the header menu. | +| `header.showAiLabel` | `boolean` | `false` | Shows the AI label in the header. Disabled by default. | +| `header.hideDefaultAiLabelContent` | `boolean` | `true` | Hides the default AI label popover content. | +| `header.hasContentMaxWidth` | `boolean` | `false` | Constrains the header to the message content width. | +| `header.actions` | `ToolbarAction[]` | none | Custom header toolbar actions. | + +### Launcher Options + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `launcher.isOn` | `boolean` | `true` for floating, `false` for docked/inline | Shows the floating launcher button. | +| `launcher.showUnreadIndicator` | `boolean` | UI default | Shows the unread dot on the launcher. | +| `launcher.mobile.avatarUrlOverride` | `string` | none | Custom mobile launcher avatar/icon URL. | +| `launcher.mobile.isOn` | `boolean` | `false` | Deprecated expanded call-to-action launcher state. | +| `launcher.mobile.title` | `string` | translated default | Deprecated expanded launcher title. | +| `launcher.mobile.timeToExpand` | `number` | `15` | Deprecated delay before launcher expansion, in seconds. | +| `launcher.desktop.avatarUrlOverride` | `string` | none | Custom desktop launcher avatar/icon URL. | +| `launcher.desktop.isOn` | `boolean` | `false` | Deprecated expanded call-to-action launcher state. | +| `launcher.desktop.title` | `string` | translated default | Deprecated expanded launcher title. | +| `launcher.desktop.timeToExpand` | `number` | `15` | Deprecated delay before launcher expansion, in seconds. | + +### History Options + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `history.isOn` | `boolean` | `false` | Enables the native history panel. | +| `history.showMobileMenu` | `boolean` | `true` | Shows mobile header menu options for new chat and view chats. | +| `history.startClosed` | `boolean` | `false` | Starts history closed and preserves open/closed state across responsive mode changes. | + +### Messaging Options + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `messaging.skipWelcome` | `boolean` | UI default | Starts new conversations without requesting a welcome message. | +| `messaging.messageTimeoutSecs` | `number` | `150` | Message timeout in seconds. Use `0` to disable automatic timeout. | +| `messaging.messageLoadingIndicatorTimeoutSecs` | `number` | `1` | Delay before the UI shows a loading indicator. Use `0` to prevent the UI from showing one automatically. | +| `messaging.customSendMessage` | function | Rapida bridge | Reserved. Rapida overwrites this so text is sent through `@rapidaai/react`. | +| `messaging.customLoadHistory` | function | none | Optional function that returns native history items for the UI. | +| `messaging.showStopButtonImmediately` | `boolean` | `false` | Shows the stop button as soon as a message request starts. | + +### Input Options + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `input.maxInputCharacters` | `number` | `10000` | Maximum characters allowed in the text input. | +| `input.isVisible` | `boolean` | `true` | Shows or hides the main input surface. | +| `input.isDisabled` | `boolean` | `false` | Disables text input. Rapida also disables text input while audio mode is active. | + +### Home Screen Options + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `homescreen.isOn` | `boolean` | `false` | Enables the native home screen before chat. | +| `homescreen.greeting` | `string` | none | Greeting text on the home screen. | +| `homescreen.starters.isOn` | `boolean` | UI default | Shows starter buttons. | +| `homescreen.starters.buttons` | `Array<{ label: string; isSelected?: boolean }>` | none | Starter utterances displayed as buttons. | +| `homescreen.customContentOnly` | `boolean` | `false` | Hides the built-in greeting and starters so custom content can own the home screen. | +| `homescreen.disableReturn` | `boolean` | `false` | Prevents returning to the home screen after a user has sent a message. | + +### Upload Options + +File upload is experimental in the underlying UI. + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `upload.is_on` | `boolean` | `false` | Enables the attachment button. Requires `upload.onFileUpload`. | +| `upload.accept` | `string` | all file types | Accepted MIME types or extensions, same format as the HTML `accept` attribute. | +| `upload.maxFileSizeBytes` | `number` | none | Client-side maximum file size. | +| `upload.maxFiles` | `number` | none | Maximum number of pending files. | +| `upload.onFileUpload` | function | none | Called once per selected file. Return structured data for the pending message. | + +### Keyboard Shortcut Options + +Keyboard shortcut configuration is experimental in the underlying UI. + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `keyboardShortcuts.messageFocusToggle.is_on` | `boolean` | `true` | Enables the message/input focus toggle shortcut. | +| `keyboardShortcuts.messageFocusToggle.key` | `string` | `"F6"` | Primary shortcut key. | +| `keyboardShortcuts.messageFocusToggle.modifiers.alt` | `boolean` | `false` | Requires Alt. | +| `keyboardShortcuts.messageFocusToggle.modifiers.shift` | `boolean` | `false` | Requires Shift. | +| `keyboardShortcuts.messageFocusToggle.modifiers.ctrl` | `boolean` | `false` | Requires Control. | +| `keyboardShortcuts.messageFocusToggle.modifiers.meta` | `boolean` | `false` | Requires Command/Meta. | + +### Disclaimer Options + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `disclaimer.isOn` | `boolean` | `false` | Shows a disclaimer screen before chat. | +| `disclaimer.disclaimerHTML` | `string` | required when enabled | HTML content for the disclaimer. If this changes after acceptance, the user must accept again. | + +### Service Desk Options + +These are advanced native UI options for human-agent handoff integrations. + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `serviceDeskFactory` | function | none | Factory that creates a service desk integration instance. | +| `serviceDesk.availabilityTimeoutSeconds` | `number` | UI default | Timeout used while checking whether human agents are available. | +| `serviceDesk.skipConnectHumanAgentCard` | `boolean` | `false` | Auto-connects to an available agent after a connect-to-agent response while still showing the card. | +| `serviceDesk.agentJoinTimeoutSeconds` | `number` | none | Timeout while waiting for an agent to join after one is requested. | +| `serviceDesk.allowReconnect` | `boolean` | `true` | Attempts to reconnect the user to a prior human-agent conversation when supported. | + +### Advanced UI Options + +These are passed through to the native UI layer. Use them only when the host page needs lower-level control. | Property | Type | Default | Description | |----------|------|---------|-------------| -| `assistant_id` | `string` | — | **Required.** Your Rapida assistant ID. | -| `token` | `string` | — | **Required.** API key for authentication. | -| `api_base` | `string` | `https://assistant-01.in.rapida.ai` | Custom API endpoint URL. | -| `user.name` | `string` | `"Guest"` | Display name for the user. | -| `user.user_id` | `string` | auto-generated | Unique user identifier. Persisted in localStorage. | -| `user.meta` | `Record` | `{ source: "web plugin" }` | Custom metadata sent with each message. | -| `name` | `string` | deployment name | Bot display name shown in the chat header. | -| `logo_url` | `string` | — | URL to bot avatar image. Falls back to a default icon. | -| `layout` | `string` | `"floating"` | Widget layout mode. | -| `position` | `string` | `"bottom-right"` | Launcher position (floating layout only). | -| `showLauncher` | `boolean` | `true` | Show/hide the launcher button (floating layout only). | -| `theme.mode` | `string` | `"light"` | Color scheme: `"light"`, `"dark"`, or `"system"`. | -| `theme.color` | `string` | `"#2663eb"` | Primary brand color as hex. | -| `language` | `string` | `"en"` | Language code. Automatically follows `` changes. | -| `debug` | `boolean` | `false` | Enable debug logging in the console. | +| `aiEnabled` | `boolean` | `false` | Enables AI visual styling. The widget disables this by default. | +| `assistantName` | `string` | `name` or deployment name | Assistant name used by the UI for accessibility, errors, and defaults. | +| `assistantAvatarUrl` | `string` | `logo_url` | Assistant avatar URL used by native messages. | +| `locale` | `string` | `language` | UI locale. Prefer `language` unless you need to override only the UI. | +| `namespace` | `string` | `"rapida-chat"` | Namespace for DOM IDs, storage keys, and multi-instance isolation. Must be 30 characters or fewer. | +| `openChatByDefault` | `boolean` | `true` for docked/inline, `false` for floating | Opens the chat when it first renders. | +| `shouldSanitizeHTML` | `boolean` | `true` | Sanitizes assistant HTML before rendering. | +| `shouldTakeFocusIfOpensAutomatically` | `boolean` | `false` | Moves focus into the chat when it opens on page load. | +| `disableCustomElementMobileEnhancements` | `boolean` | `false` | Disables mobile enhancements that can conflict with custom element embedding. | +| `isReadonly` | `boolean` | `false` | Puts the chat in read-only mode for viewing old conversations. | +| `persistFeedback` | `boolean` | `false` | Keeps feedback controls visible beyond the latest message. | +| `strings` | partial language pack | UI defaults | Overrides built-in UI strings. | +| `injectCarbonTheme` | `"white" \| "g10" \| "g90" \| "g100"` | derived from `theme` | Raw UI prop. Prefer `theme.injectTheme`. | +| `onError` | function | none | Called for catastrophic UI errors. | + +### Render And Lifecycle Hooks + +| Property | Type | Description | +|----------|------|-------------| +| `onBeforeRender(instance)` | function | Called before the UI renders. Rapida uses this internally, then calls your handler. | +| `onAfterRender(instance)` | function | Called after the UI renders. | +| `onViewPreChange(event, instance)` | function | Called before the chat opens or closes. Can return a promise to delay the view change. | +| `onViewChange(event, instance)` | function | Called after the chat opens or closes. Rapida uses this to track docked/inline shell state, then calls your handler. | +| `renderUserDefinedResponse` | function | Renders custom `user_defined` response items. | +| `renderCustomMessageFooter` | function | Renders custom message footers. | +| `renderWriteableElements` | object | Renders writable slots. Rapida merges `afterInputElement` with its audio controls. | + +### Legacy Shortcuts + +These remain supported for old embeds. Prefer the sectioned config above for new usage. + +| Property | Replacement | +|----------|-------------| +| `layout: "floating"` | `layout: { mode: "floating" }` | +| `layout: "docked-right"` | `layout: { mode: "docked-right" }` | +| `layout: "docked-left"` | `layout: { mode: "docked-left" }` | +| `layout: "inline"` | `layout: { mode: "inline" }` | +| `position` | `layout.position` | +| `showLauncher` | `launcher.isOn` | ## Layout Modes @@ -116,9 +395,13 @@ A fixed-position panel with a launcher FAB. Click the button to open/close the c ```js window.chatbotConfig = { - layout: "floating", - position: "bottom-right", // or "bottom-left", "top-right", "top-left" - showLauncher: true, + layout: { + mode: "floating", + position: "bottom-right", // or "bottom-left", "top-right", "top-left" + }, + launcher: { + isOn: true, + }, }; ``` @@ -128,7 +411,9 @@ Panel fixed to the side of the viewport. Pushes page content to make room. ```js window.chatbotConfig = { - layout: "docked-right", // or "docked-left" + layout: { + mode: "docked-right", // or "docked-left" + }, }; ``` @@ -138,19 +423,21 @@ Flows with the page content. Place the `
` where you wa ```js window.chatbotConfig = { - layout: "inline", + layout: { + mode: "inline", + }, }; ``` ## Features -- **Text + Voice** — type messages or speak with your assistant using WebRTC -- **Markdown rendering** — assistant responses render as rich Markdown -- **Microphone device selector** — choose input device during voice conversations -- **Dark mode** — automatic or manual light/dark theme switching -- **Responsive** — works on desktop and mobile browsers -- **Single file** — one `app.min.js` bundle, no external dependencies to load -- **Versioned CDN** — pin to a specific version or always use the latest +- **Text + Voice** - type messages or speak with your assistant using WebRTC +- **Markdown rendering** - assistant responses render as rich Markdown +- **Microphone device selector** - choose input device during voice conversations +- **Dark mode** - automatic or manual light/dark theme switching +- **Responsive** - works on desktop and mobile browsers +- **Single file** - one `app.min.js` bundle, no external dependencies to load +- **Versioned CDN** - pin to a specific version or always use the latest ## Development @@ -169,7 +456,7 @@ npm install ```bash npm start # Dev mode with watch (serves at webpack-dev-server) -npm run build # Production build → dist/app.min.js +npm run build # Production build -> dist/app.min.js npm test # Run tests npm run test:watch # Run tests in watch mode npm run test:coverage # Run tests with coverage report @@ -181,7 +468,7 @@ npm run test:coverage # Run tests with coverage report src/ ├── index.tsx # Entry point, mounts React app ├── app/ -│ ├── index.tsx # App root — creates VoiceAgent +│ ├── index.tsx # App root, creates VoiceAgent │ └── pages/ │ ├── web-plugin-chat/ # Deployment loader │ └── v3/ @@ -195,7 +482,7 @@ src/ ├── configs/ │ └── index.ts # API base URL + constants ├── styles/ -│ └── index.css # All widget styles (prefixed with rpd-) +│ └── carbon.scss # Theme/component styles and widget style overrides ├── types/ │ ├── globals.d.ts # ChatbotConfig type definition │ └── types.rapida.ts # Shared types @@ -207,10 +494,10 @@ src/ On push to `main`: -1. **Build** — `npm ci && npm run build` -2. **CDN** — uploads `dist/app.min.js` to S3 with CloudFront invalidation -3. **npm** — publishes to npm as `@rapidaai/web-widget` -4. **Release** — creates a GitHub release with a version tag +1. **Build** - `npm ci && npm run build` +2. **CDN** - uploads `dist/app.min.js` to S3 with CloudFront invalidation +3. **npm** - publishes to npm as `@rapidaai/web-widget` +4. **Release** - creates a GitHub release with a version tag Pull requests run the CI pipeline (build + test) without deploying. diff --git a/index.html b/index.html index 51a5e7a..cc6d3eb 100644 --- a/index.html +++ b/index.html @@ -5,45 +5,83 @@ Rapida Chat Widget Demo diff --git a/package-lock.json b/package-lock.json index 03b9761..67df0b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,23 +1,30 @@ { - "name": "react-widget", + "name": "@rapidaai/web-widget", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "@rapidaai/web-widget", + "version": "1.2.0", + "license": "MIT", "dependencies": { + "@carbon/ai-chat": "^1.14.0", + "@carbon/icons-react": "^11.82.0", + "@carbon/react": "^1.104.0", + "@carbon/styles": "^1.103.0", + "@carbon/web-components": "^2.56.0", "@emotion/is-prop-valid": "^1.3.0", "@floating-ui/react": "^0.26.23", "@improbable-eng/grpc-web": "^0.15.0", - "@rapidaai/react": "^1.1.64", + "@rapidaai/react": "^1.1.79", "@tailwindcss/typography": "^0.5.14", "@types/google-protobuf": "^3.15.12", "@uiw/react-markdown-preview": "^5.1.4", "clsx": "^2.1.1", - "framer-motion": "^11.5.4", "google-protobuf": "^3.21.4", "grpc-web": "^1.5.0", "highlight.js": "^11.10.0", - "lucide-react": "^0.479.0", "markdown-to-jsx": "^7.5.0", "moment": "^2.30.1", "react": "^18.3.1", @@ -54,6 +61,8 @@ "postcss-obfuscator": "^1.6.1", "protoc-gen-grpc-web": "^1.5.0", "protoc-gen-ts": "0.8.7", + "sass": "^1.100.0", + "sass-loader": "^17.0.0", "style-loader": "^4.0.0", "terser": "^5.31.6", "ts-jest": "^29.4.6", @@ -2067,7 +2076,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2218,6 +2226,708 @@ "dev": true, "license": "MIT" }, + "node_modules/@carbon/ai-chat": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@carbon/ai-chat/-/ai-chat-1.14.0.tgz", + "integrity": "sha512-hfw1awRXxvoRDo5/XB2HkOv8KGMTHfvjJ/e0TPa9c32wdH3rc8ghvUcvsRjUxCeNZ3u/LYErmMocB0JqU0GGaA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@carbon/ai-chat-components": "^1.4.0", + "@carbon/icons": "^11.53.0", + "@ibm/telemetry-js": "^1.10.2", + "@lit/react": "^1.0.6", + "classnames": "^2.5.0", + "color": "^4.2.3", + "compute-scroll-into-view": "^3.1.0", + "dayjs": "^1.11.10", + "focus-trap-react": "^12.0.0", + "intl-messageformat": "^11.0.0", + "lit": "^3.1.0", + "lodash-es": "^4.18.1", + "tabbable": "^6.2.0", + "tslib": "^2.6.3", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "@carbon/web-components": ">=2.54.0 <3.0.0", + "react": ">=17.0.0 <20.0.0", + "react-dom": ">=17.0.0 <20.0.0" + } + }, + "node_modules/@carbon/ai-chat-components": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@carbon/ai-chat-components/-/ai-chat-components-1.4.0.tgz", + "integrity": "sha512-ZjpiYMBSmWAqxJqwxhXadzpTiviVfB/0ygNAr8Ryl57pfBtPaNGt/XF96LwmajPUe6tSe/6zCZgjbAnJZhoWIA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@carbon/icon-helpers": "^10.47.0", + "@carbon/icons": "^11.53.0", + "@carbon/styles": "^1.106.0", + "@carbon/utilities": "^0.19.0", + "@carbon/web-components": "^2.54.0", + "@codemirror/autocomplete": "^6.20.0", + "@codemirror/commands": "^6.10.1", + "@codemirror/lang-angular": "^0.1.4", + "@codemirror/lang-cpp": "^6.0.3", + "@codemirror/lang-css": "^6.3.1", + "@codemirror/lang-go": "^6.0.1", + "@codemirror/lang-html": "^6.4.11", + "@codemirror/lang-java": "^6.0.2", + "@codemirror/lang-javascript": "^6.2.4", + "@codemirror/lang-jinja": "^6.0.0", + "@codemirror/lang-json": "^6.0.2", + "@codemirror/lang-less": "^6.0.2", + "@codemirror/lang-liquid": "^6.3.0", + "@codemirror/lang-markdown": "^6.5.0", + "@codemirror/lang-php": "^6.0.2", + "@codemirror/lang-python": "^6.2.1", + "@codemirror/lang-rust": "^6.0.2", + "@codemirror/lang-sass": "^6.0.2", + "@codemirror/lang-sql": "^6.10.0", + "@codemirror/lang-vue": "^0.1.3", + "@codemirror/lang-wast": "^6.0.2", + "@codemirror/lang-xml": "^6.1.0", + "@codemirror/lang-yaml": "^6.1.2", + "@codemirror/language": "^6.11.3", + "@codemirror/legacy-modes": "^6.5.2", + "@codemirror/lint": "^6.9.2", + "@codemirror/state": "^6.5.2", + "@codemirror/view": "^6.38.5", + "@ibm/telemetry-js": "^1.10.2", + "@lezer/highlight": "^1.1.6", + "@lit/react": "^1.0.8", + "csv-stringify": "^6.5.2", + "dompurify": "^3.4.0", + "lit": "^3.1.0", + "lodash-es": "^4.18.1", + "markdown-it": "^14.1.0", + "program-language-detector": "^0.0.12", + "tslib": "^2.6.3" + }, + "peerDependencies": { + "react": ">=17.0.0 <20.0.0" + } + }, + "node_modules/@carbon/ai-chat-components/node_modules/@carbon/utilities": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@carbon/utilities/-/utilities-0.19.0.tgz", + "integrity": "sha512-qg4DO/k8Ex4ho66pWXWG3wwVAfc5E9LrJevzBTyQ1Ui2zd5ZJwjFHajD0iEsUBDBmTu2GF246aNPSEy0yp+zGw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1", + "@internationalized/number": "^3.6.1" + } + }, + "node_modules/@carbon/colors": { + "version": "11.52.0", + "resolved": "https://registry.npmjs.org/@carbon/colors/-/colors-11.52.0.tgz", + "integrity": "sha512-T0Jhemrowk1VBsq/iK00bPQ+O43X1ibtBRVxuy+2APBvB35409kgvkfOEMiEpETHa/gZeevpBPFum/6g+iyqIQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.5.0" + } + }, + "node_modules/@carbon/feature-flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@carbon/feature-flags/-/feature-flags-1.3.0.tgz", + "integrity": "sha512-43e+mweVvQhUdhaeAD9WyRrum9n2PfiiBDGKy+HIs6rtmPZSkxISmn7ZWTw2aTPA4AWMTKm0s0EMd2z7DxuhTw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.5.0" + } + }, + "node_modules/@carbon/grid": { + "version": "11.56.0", + "resolved": "https://registry.npmjs.org/@carbon/grid/-/grid-11.56.0.tgz", + "integrity": "sha512-AyfagUzgBt4XkFId5Wz4+P33AiNdyIdge8WvH7i0ck8N7xYyFCvmMRUICcd9vesfyz1j9pRHriHISOme9IAKpg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@carbon/layout": "^11.53.0", + "@ibm/telemetry-js": "^1.5.0" + } + }, + "node_modules/@carbon/icon-helpers": { + "version": "10.76.0", + "resolved": "https://registry.npmjs.org/@carbon/icon-helpers/-/icon-helpers-10.76.0.tgz", + "integrity": "sha512-DLxVV/NtEFauMbmKFW53cGKMs84RRdIp9AzHbasIxlCBjO0P4eZbPdO3gTzYxn02jDMo++2m3MsEAwNydzrzmQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.5.0" + } + }, + "node_modules/@carbon/icons": { + "version": "11.82.0", + "resolved": "https://registry.npmjs.org/@carbon/icons/-/icons-11.82.0.tgz", + "integrity": "sha512-XMJiHEUKd9/4kJKLbzbHX2KizUVb6mrzJbJg9gb03jYVq+tFjxUO8WmT6czmHls0mj3mv0Y2rMeMtl7/v+aQjw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.5.0" + } + }, + "node_modules/@carbon/icons-react": { + "version": "11.82.0", + "resolved": "https://registry.npmjs.org/@carbon/icons-react/-/icons-react-11.82.0.tgz", + "integrity": "sha512-KBax1fqLEFAIebJ/jVt3tSQhW5G0CeliTfbFfrTPJa6aS4S9R8PwpBpKkrwQej8cL8FmspzmZcUgUGZPiOaSpw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@carbon/icon-helpers": "^10.76.0", + "@ibm/telemetry-js": "^1.5.0", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@carbon/layout": { + "version": "11.53.0", + "resolved": "https://registry.npmjs.org/@carbon/layout/-/layout-11.53.0.tgz", + "integrity": "sha512-UZz7KEvLxrNJihp8djOqnW5pRVoAahhdT1NuvffBYy78rT+VJx8mpecTGH1G98ydvbtiQYgfz45c0FGZmti6Tg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.5.0" + } + }, + "node_modules/@carbon/motion": { + "version": "11.46.0", + "resolved": "https://registry.npmjs.org/@carbon/motion/-/motion-11.46.0.tgz", + "integrity": "sha512-b2UQvDfHiAw7UIFbDTMrr/Op2q51xqLOTVdPNsHoQT9Jb8jpBXsDw5y9C14pTQtk07KVcYh0LlZyBoUdTogpRw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.5.0" + } + }, + "node_modules/@carbon/react": { + "version": "1.104.0", + "resolved": "https://registry.npmjs.org/@carbon/react/-/react-1.104.0.tgz", + "integrity": "sha512-IID5Lml0qkg7LCNzUMgSdUAwOmSEpFeRL4nj6LjW7Y6nSRy/OfPn9nDfvc4j40+ITZxTRJ6aV5u6jHg/aIOylA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.27.3", + "@carbon/feature-flags": "^1.2.0", + "@carbon/icons-react": "^11.77.0", + "@carbon/layout": "^11.50.0", + "@carbon/styles": "^1.103.0", + "@carbon/utilities": "^0.18.0", + "@floating-ui/react": "^0.27.4", + "@ibm/telemetry-js": "^1.5.0", + "classnames": "2.5.1", + "copy-to-clipboard": "^3.3.1", + "downshift": "9.0.10", + "es-toolkit": "^1.27.0", + "flatpickr": "4.6.13", + "invariant": "^2.2.3", + "prop-types": "^15.8.1", + "react-fast-compare": "^3.2.2", + "tabbable": "^6.2.0" + }, + "peerDependencies": { + "react": "^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0", + "react-dom": "^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0", + "react-is": "^16.13.1 || ^17.0.2 || ^18.3.1 || ^19.0.0", + "sass": "^1.33.0" + } + }, + "node_modules/@carbon/react/node_modules/@floating-ui/react": { + "version": "0.27.19", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.19.tgz", + "integrity": "sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.8", + "@floating-ui/utils": "^0.2.11", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@carbon/styles": { + "version": "1.108.0", + "resolved": "https://registry.npmjs.org/@carbon/styles/-/styles-1.108.0.tgz", + "integrity": "sha512-OcLWKE2yAKJ7mRLjUwkCBVziswb9t7tWPHoIva6rq322qqSBHwD7fvaxnIycArfy8Pv+UsKOU2H1LXGAycEtNQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@carbon/colors": "^11.52.0", + "@carbon/feature-flags": "^1.3.0", + "@carbon/grid": "^11.56.0", + "@carbon/layout": "^11.53.0", + "@carbon/motion": "^11.46.0", + "@carbon/themes": "^11.75.0", + "@carbon/type": "^11.61.0", + "@ibm/plex": "6.4.1", + "@ibm/plex-mono": "1.1.0", + "@ibm/plex-sans": "1.1.0", + "@ibm/plex-sans-arabic": "1.1.0", + "@ibm/plex-sans-devanagari": "1.1.0", + "@ibm/plex-sans-hebrew": "1.1.0", + "@ibm/plex-sans-thai": "1.1.0", + "@ibm/plex-sans-thai-looped": "1.1.0", + "@ibm/plex-serif": "2.0.0", + "@ibm/telemetry-js": "^1.5.0" + }, + "peerDependencies": { + "sass": "^1.33.0" + }, + "peerDependenciesMeta": { + "sass": { + "optional": true + } + } + }, + "node_modules/@carbon/themes": { + "version": "11.75.0", + "resolved": "https://registry.npmjs.org/@carbon/themes/-/themes-11.75.0.tgz", + "integrity": "sha512-WdNFPVbKuEB1wBAjAJzKLoMYRZi4OypMUvoJbFeP6HrMnUBG+F3pm0ExwCLyyCRMn/EL2c+ICiZyhjIM0ftNnw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@carbon/colors": "^11.52.0", + "@carbon/layout": "^11.53.0", + "@carbon/type": "^11.61.0", + "@ibm/telemetry-js": "^1.5.0", + "color": "^4.0.0" + } + }, + "node_modules/@carbon/type": { + "version": "11.61.0", + "resolved": "https://registry.npmjs.org/@carbon/type/-/type-11.61.0.tgz", + "integrity": "sha512-pCmITzwjDAmHGhg/X+7rsrmTNREWKAI/YD7+TAEdS4RYoNK9qoFM+TOTshLsD3mNflDkqz883bdd/iUZo1tABA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@carbon/grid": "^11.56.0", + "@carbon/layout": "^11.53.0", + "@ibm/telemetry-js": "^1.5.0" + } + }, + "node_modules/@carbon/utilities": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@carbon/utilities/-/utilities-0.18.0.tgz", + "integrity": "sha512-GdeDixFqriPObIShDvU9kjZKM8xXLWL4SgdiIYs4tWsohlT0tfzlE4lLD81E6FBB0hqmC+FkwLEFJN/XXWzROg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1", + "@internationalized/number": "^3.6.1" + } + }, + "node_modules/@carbon/web-components": { + "version": "2.56.0", + "resolved": "https://registry.npmjs.org/@carbon/web-components/-/web-components-2.56.0.tgz", + "integrity": "sha512-56p2MHGmRIqkgtbfrWa70IcTtiPKvIyIZU3X+5lk4qi7+d5o5od+JRJk9Qu0Ypw7Y+uB2o8UtpNLttiOB7UISQ==", + "bundleDependencies": [ + "flatpickr" + ], + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@carbon/icon-helpers": "10.47.0", + "@carbon/icons": "^11.82.0", + "@carbon/styles": "^1.108.0", + "@carbon/utilities": "^0.17.0", + "@floating-ui/dom": "^1.6.3", + "@ibm/telemetry-js": "^1.10.2", + "@lit/context": "^1.1.3", + "flatpickr": "*", + "lit": "^3.1.0", + "lodash-es": "^4.17.21", + "tslib": "^2.6.3" + } + }, + "node_modules/@carbon/web-components/node_modules/@carbon/icon-helpers": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@carbon/icon-helpers/-/icon-helpers-10.47.0.tgz", + "integrity": "sha512-vv2Wkuw7lYkYVKrn5ABzlZD+6ioAYwMuyKi2XPqYY3hrHYoL4CQUnuSFDhlj0DR2HHCB0L5MGRLxHLucx5cc7g==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.2.1" + } + }, + "node_modules/@carbon/web-components/node_modules/@carbon/utilities": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@carbon/utilities/-/utilities-0.17.0.tgz", + "integrity": "sha512-XNpZX7bbwwTzzjZhgufB9fHQH9i8Mec/0KXIULStzYMUlAHhstYMOCp+pLmI53ynyc+/PkCOTnAADXeZcy7Guw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1", + "@internationalized/number": "^3.6.1" + } + }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.3", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.3.tgz", + "integrity": "sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", + "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-angular": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@codemirror/lang-angular/-/lang-angular-0.1.4.tgz", + "integrity": "sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-javascript": "^6.1.2", + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.3" + } + }, + "node_modules/@codemirror/lang-cpp": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.3.tgz", + "integrity": "sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/cpp": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", + "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.1.7" + } + }, + "node_modules/@codemirror/lang-go": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-go/-/lang-go-6.0.1.tgz", + "integrity": "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/go": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.11", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.11.tgz", + "integrity": "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.12" + } + }, + "node_modules/@codemirror/lang-java": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-java/-/lang-java-6.0.2.tgz", + "integrity": "sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/java": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz", + "integrity": "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-jinja": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-jinja/-/lang-jinja-6.0.1.tgz", + "integrity": "sha512-P5kyHLObzjtbGj16h+hyvZTxJhSjBEeSx4wMjbnAf3b0uwTy2+F0zGjMZL4PQOm/mh2eGZ5xUDVZXgwP783Nsw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.2.0", + "@lezer/lr": "^1.4.0" + } + }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-less": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-less/-/lang-less-6.0.2.tgz", + "integrity": "sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-css": "^6.2.0", + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-liquid": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-liquid/-/lang-liquid-6.3.2.tgz", + "integrity": "sha512-6PDVU3ZnfeYyz1at1E/ttorErZvZFXXt1OPhtfe1EZJ2V2iDFa0CwPqPgG5F7NXN0yONGoBogKmFAafKTqlwIw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.1" + } + }, + "node_modules/@codemirror/lang-markdown": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.5.0.tgz", + "integrity": "sha512-0K40bZ35jpHya6FriukbgaleaqzBLZfOh7HuzqbMxBXkbYMJDxfF39c23xOgxFezR+3G+tR2/Mup+Xk865OMvw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.7.1", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.3.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/markdown": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-php": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.2.tgz", + "integrity": "sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/php": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-python": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.2.1.tgz", + "integrity": "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.3.2", + "@codemirror/language": "^6.8.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/python": "^1.1.4" + } + }, + "node_modules/@codemirror/lang-rust": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.2.tgz", + "integrity": "sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/rust": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-sass": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-sass/-/lang-sass-6.0.2.tgz", + "integrity": "sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-css": "^6.2.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/sass": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-sql": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.10.0.tgz", + "integrity": "sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-vue": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-vue/-/lang-vue-0.1.3.tgz", + "integrity": "sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-javascript": "^6.1.2", + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.1" + } + }, + "node_modules/@codemirror/lang-wast": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-wast/-/lang-wast-6.0.2.tgz", + "integrity": "sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-xml": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", + "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-yaml": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.3.tgz", + "integrity": "sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.2.0", + "@lezer/lr": "^1.0.0", + "@lezer/yaml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.3.tgz", + "integrity": "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/legacy-modes": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.5.3.tgz", + "integrity": "sha512-xCsmIzH78MyWkib9jlPaaun57XNkfbMIhagfaZVd0iLTqlpw3jXaIcbZm72MTmmn64eTZpBVNjbyYh+QXnxRsg==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.7.tgz", + "integrity": "sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.42.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", + "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.43.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.1.tgz", + "integrity": "sha512-+BIjw/AG3tDQ4pJgTLPYdAW25eDE66YsvM4LKyVPgGzVgZ4a9Wj1SRX8kPVKgBDdPt8oHtZ15F0qx7p0oOHdHw==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.6.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -2744,6 +3454,27 @@ "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", "license": "MIT" }, + "node_modules/@formatjs/fast-memoize": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.6.tgz", + "integrity": "sha512-H5aexk1Le7T9TPmscacZ+1pR6CTa2n1wq+HDVGXhH8TzUlQQpeXzZs91dRtmFHrbeNbjPFPfQujUqm7MHgVoXQ==", + "license": "MIT" + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.11.tgz", + "integrity": "sha512-NVsuNsc2dUVG9+4HBJ/srScxtA/18LqGgwtop/tuN/OIBjVl6QA+0KhfZQddDD9sEh2LeVjLFPGVU3ixa3blcA==", + "license": "MIT", + "dependencies": { + "@formatjs/icu-skeleton-parser": "2.1.10" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.10.tgz", + "integrity": "sha512-XuSva+8ZGawk8VnD5VD6UeH8KarQ/Z022zgjHDoHmlNiAewstXuuzXc0Hk5pGFSdG+nNw5bfJKXqj1ZXHn9yUA==", + "license": "MIT" + }, "node_modules/@fullhuman/postcss-purgecss": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-6.0.0.tgz", @@ -2788,6 +3519,105 @@ "node": ">=6" } }, + "node_modules/@ibm/plex": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@ibm/plex/-/plex-6.4.1.tgz", + "integrity": "sha512-fnsipQywHt3zWvsnlyYKMikcVI7E2fEwpiPnIHFqlbByXVfQfANAAeJk1IV4mNnxhppUIDlhU0TzwYwL++Rn2g==", + "hasInstallScript": true, + "license": "OFL-1.1", + "dependencies": { + "@ibm/telemetry-js": "^1.5.1" + } + }, + "node_modules/@ibm/plex-mono": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ibm/plex-mono/-/plex-mono-1.1.0.tgz", + "integrity": "sha512-hpsdRxR3BRJkC6wGM4MZcUFD6C8M+mmK76RtAy/hlsfPro9FzpXVdIWC+G3jeQOXof109dxlUvmeKxpeKUG68A==", + "hasInstallScript": true, + "license": "OFL-1.1", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1" + } + }, + "node_modules/@ibm/plex-sans": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ibm/plex-sans/-/plex-sans-1.1.0.tgz", + "integrity": "sha512-WPgvO6Yfj2w5YbhyAr1tv95RUz4LRJlqN+CmYvBglabXteufP1D1E9BABMde+ZIKdRbFJDoKF5eQzfhpnbgZcQ==", + "hasInstallScript": true, + "license": "OFL-1.1", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1" + } + }, + "node_modules/@ibm/plex-sans-arabic": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ibm/plex-sans-arabic/-/plex-sans-arabic-1.1.0.tgz", + "integrity": "sha512-u8wIS6szLAOFvlBjCFZmtpKIqbhuIuniG2N0J+sio8vV6INH58hP0t0QNYrSl9SZtCv2Fwb4oQGuZJY3kJ4+QA==", + "hasInstallScript": true, + "license": "OFL-1.1", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1" + } + }, + "node_modules/@ibm/plex-sans-devanagari": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ibm/plex-sans-devanagari/-/plex-sans-devanagari-1.1.0.tgz", + "integrity": "sha512-IVNV9NxXZDzcGZRao/xj+kiFwkdLkcw5vNiKwY8wEzzkpjApXJnPhJ0a7mIKNAh8oIadTIF68+iGtzRKK3nXAQ==", + "hasInstallScript": true, + "license": "OFL-1.1", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1" + } + }, + "node_modules/@ibm/plex-sans-hebrew": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ibm/plex-sans-hebrew/-/plex-sans-hebrew-1.1.0.tgz", + "integrity": "sha512-iix0rLpUD0E8dE8q+/t3B7u1or7h6gEzoy6TK9NwP41AN31WE55f2cFwQAXomBDwr0Ozc9sHYy97NutEukZXzQ==", + "hasInstallScript": true, + "license": "OFL-1.1", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1" + } + }, + "node_modules/@ibm/plex-sans-thai": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ibm/plex-sans-thai/-/plex-sans-thai-1.1.0.tgz", + "integrity": "sha512-vk7IrjdO69eEElJpFBppCha/wvU48DFyVuDewcfIf5L6Z11s0vbROANCvKipVPRUz1LE4ron8KoitWGcl3AlfA==", + "hasInstallScript": true, + "license": "OFL-1.1", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1" + } + }, + "node_modules/@ibm/plex-sans-thai-looped": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ibm/plex-sans-thai-looped/-/plex-sans-thai-looped-1.1.0.tgz", + "integrity": "sha512-9zbDGzmtscHgBRTF88y3/92zQx6lmKjz5ZxhgcljilwOpj08BAytDc3mzUl9XGUh+DmOMl0Ql1lk6ecsEYYg2w==", + "hasInstallScript": true, + "license": "OFL-1.1", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1" + } + }, + "node_modules/@ibm/plex-serif": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ibm/plex-serif/-/plex-serif-2.0.0.tgz", + "integrity": "sha512-xVu9JsC18tBoQF2M6fofpsWrHj5a94saxlOZbYmXoC0E3UfjgS1JlibgrnaUJjnkLlEyCpMgI2PdhkDxijw0gA==", + "hasInstallScript": true, + "license": "OFL-1.1", + "dependencies": { + "@ibm/telemetry-js": "^1.6.1" + } + }, + "node_modules/@ibm/telemetry-js": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@ibm/telemetry-js/-/telemetry-js-1.11.0.tgz", + "integrity": "sha512-RO/9j+URJnSfseWg9ZkEX9p+a3Ousd33DBU7rOafoZB08RqdzxFVYJ2/iM50dkBuD0o7WX7GYt1sLbNgCoE+pA==", + "license": "Apache-2.0", + "bin": { + "ibmtelemetry": "dist/collect.js" + } + }, "node_modules/@improbable-eng/grpc-web": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz", @@ -2800,6 +3630,15 @@ "google-protobuf": "^3.14.0" } }, + "node_modules/@internationalized/number": { + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.7.tgz", + "integrity": "sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -3668,6 +4507,222 @@ "url": "https://opencollective.com/js-sdsl" } }, + "node_modules/@lezer/common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", + "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==", + "license": "MIT" + }, + "node_modules/@lezer/cpp": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.6.tgz", + "integrity": "sha512-vh9gWWJOXFVY8HBHK3Twzq8MgwG2iN4GSyzBP9sCGTe37P15x2R14VaBQk0VA0ezTRN1KHYBBsHhvpGZ2Xy/pA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/css": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.3.tgz", + "integrity": "sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/go": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.1.tgz", + "integrity": "sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz", + "integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/java": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.3.tgz", + "integrity": "sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", + "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.10.tgz", + "integrity": "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/markdown": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.6.4.tgz", + "integrity": "sha512-N0SxazMj4k65DBfaf1azqtMZd6u7MqluP84/NZnB/io8Td9aleFmAhz9hcbvSfsxT5tdYlJ5qgv5aMJGY4zEtA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@lezer/php": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.5.tgz", + "integrity": "sha512-W7asp9DhM6q0W6DYNwIkLSKOvxlXRrif+UXBMxzsJUuqmhE7oVU+gS3THO4S/Puh7Xzgm858UNaFi6dxTP8dJA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.1.0" + } + }, + "node_modules/@lezer/python": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.19.tgz", + "integrity": "sha512-MhQIURHRytsNzP/YXnqpYKW6la6voAH3kyplTOOiCdjyFY6cWWGFVmYVdHIPrElqSDf4iCDktQCockB9FxuhzQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/rust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz", + "integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/sass": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/sass/-/sass-1.1.0.tgz", + "integrity": "sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/xml": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz", + "integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/yaml": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.4.tgz", + "integrity": "sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.4.0" + } + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.6.0.tgz", + "integrity": "sha512-VHb0ALPMTlgKjM6yIxxoQNnpKyUKLD04VzeQdsiXkMqkvYlAHxq9glGLmgbb889/1GsohSOAjvQYoiBppXFqrQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@lit/context": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.6.tgz", + "integrity": "sha512-M26qDE6UkQbZA2mQ3RjJ3Gzd8TxP+/0obMgE5HfkfLhEEyYE3Bui4A5XHiGPjy0MUGAyxB3QgVuw2ciS0kHn6A==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^1.6.2 || ^2.1.0" + } + }, + "node_modules/@lit/react": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@lit/react/-/react-1.0.8.tgz", + "integrity": "sha512-p2+YcF+JE67SRX3mMlJ1TKCSTsgyOVdAwd/nxp3NuV1+Cb6MWALbN6nT7Ld4tpmYofcE5kcaSY1YBB9erY+6fw==", + "license": "BSD-3-Clause", + "peerDependencies": { + "@types/react": "17 || 18 || 19" + } + }, + "node_modules/@lit/reactive-element": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz", + "integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0" + } + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3690,17 +4745,326 @@ "node": ">= 8" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, + "optional": true, "engines": { - "node": ">= 8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/@pkgjs/parseargs": { @@ -3785,9 +5149,9 @@ "license": "BSD-3-Clause" }, "node_modules/@rapidaai/react": { - "version": "1.1.64", - "resolved": "https://registry.npmjs.org/@rapidaai/react/-/react-1.1.64.tgz", - "integrity": "sha512-WvYNDvPoo/MxQAT3ACqYi2FJKxV0dRkeIz/NBw26EoqqudkJvL1jKUwrOIiKBNAy9dd7TWa+eFNGxJ3nPPC1gw==", + "version": "1.1.79", + "resolved": "https://registry.npmjs.org/@rapidaai/react/-/react-1.1.79.tgz", + "integrity": "sha512-sNbhqeQMwg0Pp6d0FS273cp/V6WqLj7qOBkO5+ZU3VC4fC7n3qmSNKMiZQCNO7Ly8fUvudI9tpLAaJ4Sj2lrzQ==", "license": "MIT", "dependencies": { "@emotion/is-prop-valid": "^1.3.1", @@ -3906,6 +5270,15 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@tailwindcss/node": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.0.12.tgz", @@ -4529,7 +5902,6 @@ "version": "18.3.0", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, "license": "MIT", "dependencies": { "@types/react": "*" @@ -4555,6 +5927,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -5143,7 +6521,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/aria-query": { @@ -6227,6 +7604,12 @@ "dev": true, "license": "MIT" }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -6293,6 +7676,19 @@ "dev": true, "license": "MIT" }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -6311,6 +7707,16 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -6361,6 +7767,12 @@ "dev": true, "license": "ISC" }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -6388,6 +7800,15 @@ "dev": true, "license": "MIT" }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, "node_modules/core-js-compat": { "version": "3.38.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", @@ -6458,6 +7879,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6824,6 +8251,12 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/csv-stringify": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.7.0.tgz", + "integrity": "sha512-UdtziYp5HuTz7e5j8Nvq+a/3HQo+2/aJZ9xntNTpmRRIg/3YYqDVgiS9fvAhtNbnyfbv2ZBe0bqCHqzhE7FqWQ==", + "license": "MIT" + }, "node_modules/data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", @@ -6839,6 +8272,12 @@ "node": ">=12" } }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -7304,6 +8743,15 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.9.tgz", + "integrity": "sha512-4dPSRMRDqHvs0V4YDFCsaIZo4if5u0xM+llyxiM2fwuZFdKArUBAF3VtI2+n8NKg9P870WMdYk0UhqQNoWXbfQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", @@ -7375,6 +8823,28 @@ "node": ">=6" } }, + "node_modules/downshift": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-9.0.10.tgz", + "integrity": "sha512-TP/iqV6bBok6eGD5tZ8boM8Xt7/+DZvnVNr8cNIhbAm2oUBd79Tudiccs2hbcV9p7xAgS/ozE7Hxy3a9QqS6Mw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "compute-scroll-into-view": "^3.1.0", + "prop-types": "^15.8.1", + "react-is": "18.2.0", + "tslib": "^2.6.2" + }, + "peerDependencies": { + "react": ">=16.12.0" + } + }, + "node_modules/downshift/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "license": "MIT" + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -7579,6 +9049,16 @@ "node": ">= 0.4" } }, + "node_modules/es-toolkit": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.0.tgz", + "integrity": "sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/esbuild": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", @@ -8149,6 +9629,37 @@ "flat": "cli.js" } }, + "node_modules/flatpickr": { + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", + "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==", + "license": "MIT" + }, + "node_modules/focus-trap": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-8.2.1.tgz", + "integrity": "sha512-6CxwrrFRquH7pDXb1mWxudkU9LSfYBMRZutpgddb2o6iwCk7cIRrBhyY3c8SGKcmIKdeMTrGSNg4Bedh2RSF/w==", + "license": "MIT", + "dependencies": { + "tabbable": "^6.4.0" + } + }, + "node_modules/focus-trap-react": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-12.0.2.tgz", + "integrity": "sha512-74OXbMiEOEDfynxLwhntTEbBbL+nSvGyBaLQ8tfnDuLPBLR+bgdE4oMaK8DOt/u9YH+9JFKJ+MuIYInSX7Rk5g==", + "license": "MIT", + "dependencies": { + "focus-trap": "^8.2.1", + "tabbable": "^6.4.0" + }, + "peerDependencies": { + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -8224,31 +9735,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/framer-motion": { - "version": "11.5.4", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.5.4.tgz", - "integrity": "sha512-E+tb3/G6SO69POkdJT+3EpdMuhmtCh9EWuK4I1DnIC23L7tFPrl8vxP+LSovwaw6uUr73rUbpb4FgK011wbRJQ==", - "license": "MIT", - "dependencies": { - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0", - "react-dom": "^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, "node_modules/from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -9169,6 +10655,12 @@ ], "license": "BSD-3-Clause" }, + "node_modules/immutable": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.6.tgz", + "integrity": "sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==", + "license": "MIT" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -9285,6 +10777,16 @@ "node": ">=10.13.0" } }, + "node_modules/intl-messageformat": { + "version": "11.2.8", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.8.tgz", + "integrity": "sha512-l323RCl3qJDVQ8U9j74ut/hVMdg3VPsOHpVMDvFfz9qiq4dPO5ooVYFNVUzzrpgG39a+RLzcXyJb8VFgIU+tUA==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/fast-memoize": "3.1.6", + "@formatjs/icu-messageformat-parser": "3.5.11" + } + }, "node_modules/into-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", @@ -9299,6 +10801,15 @@ "node": ">=4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -11897,6 +13408,56 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/linkify-it": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", + "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lit": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.3.tgz", + "integrity": "sha512-fycuvZg/hkpozL00lm1pEJH5nN/lr9ZXd6mJI2HSN4+Bzc+LDNdEApJ6HFbPkdFNHLvOplIIuJvxkS4XUxqirw==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-element": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", + "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-html": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.3.tgz", + "integrity": "sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -11920,9 +13481,9 @@ } }, "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", "license": "MIT" }, "node_modules/lodash.camelcase": { @@ -12018,15 +13579,6 @@ "yallist": "^3.0.2" } }, - "node_modules/lucide-react": { - "version": "0.479.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.479.0.tgz", - "integrity": "sha512-aBhNnveRhorBOK7uA4gDjgaf+YlHMdMhQ/3cupk6exM10hWlEU+2QtWYOfhXhjAsmdb6LeKR+NZnow4UxRRiTQ==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -12088,6 +13640,45 @@ "tmpl": "1.0.5" } }, + "node_modules/markdown-it": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.1", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -12409,6 +14000,12 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -13188,6 +14785,13 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "license": "MIT" }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -14484,6 +16088,12 @@ "dev": true, "license": "MIT" }, + "node_modules/program-language-detector": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/program-language-detector/-/program-language-detector-0.0.12.tgz", + "integrity": "sha512-d/b9ax5G0RjOW4MQl4YJPk3zCNPrvCl01X4QI5DcWBYAUyZU2zclt9DyqcbjW12RSyXVvR9b7gNhxo9+wWf+/w==", + "license": "MIT" + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -14498,6 +16108,23 @@ "node": ">= 6" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, "node_modules/property-information": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz", @@ -14609,6 +16236,15 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -14775,6 +16411,12 @@ "react": "^18.3.1" } }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, "node_modules/react-hook-form": { "version": "7.53.0", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.0.tgz", @@ -14795,7 +16437,6 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, "license": "MIT" }, "node_modules/react-markdown": { @@ -15460,6 +17101,88 @@ "dev": true, "license": "MIT" }, + "node_modules/sass": { + "version": "1.100.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz", + "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass-loader": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-17.0.0.tgz", + "integrity": "sha512-0Ybm8ohBQ9LcrycVrFQp/KQBNX5a3Wda9/smS0mE/xLffzEnwvV8nykOzrbiSWNzTE3IB/jiXx8O4QmDPG2+Gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 22.11.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -15692,6 +17415,21 @@ "dev": true, "license": "ISC" }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, "node_modules/sirv": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", @@ -16026,6 +17764,12 @@ "webpack": "^5.27.0" } }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "license": "MIT" + }, "node_modules/style-to-js": { "version": "1.1.16", "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.16.tgz", @@ -16288,9 +18032,9 @@ "license": "MIT" }, "node_modules/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", "license": "MIT" }, "node_modules/tailwind-merge": { @@ -16608,6 +18352,12 @@ "node": ">=8.0" } }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "license": "MIT" + }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -16871,6 +18621,12 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, "node_modules/uglify-js": { "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", @@ -17235,6 +18991,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", diff --git a/package.json b/package.json index ee95794..fe730fa 100644 --- a/package.json +++ b/package.json @@ -13,19 +13,22 @@ }, "license": "MIT", "dependencies": { + "@carbon/ai-chat": "^1.14.0", + "@carbon/icons-react": "^11.82.0", + "@carbon/react": "^1.104.0", + "@carbon/styles": "^1.103.0", + "@carbon/web-components": "^2.56.0", "@emotion/is-prop-valid": "^1.3.0", "@floating-ui/react": "^0.26.23", "@improbable-eng/grpc-web": "^0.15.0", - "@rapidaai/react": "^1.1.64", + "@rapidaai/react": "^1.1.79", "@tailwindcss/typography": "^0.5.14", "@types/google-protobuf": "^3.15.12", "@uiw/react-markdown-preview": "^5.1.4", "clsx": "^2.1.1", - "framer-motion": "^11.5.4", "google-protobuf": "^3.21.4", "grpc-web": "^1.5.0", "highlight.js": "^11.10.0", - "lucide-react": "^0.479.0", "markdown-to-jsx": "^7.5.0", "moment": "^2.30.1", "react": "^18.3.1", @@ -62,6 +65,8 @@ "postcss-obfuscator": "^1.6.1", "protoc-gen-grpc-web": "^1.5.0", "protoc-gen-ts": "0.8.7", + "sass": "^1.100.0", + "sass-loader": "^17.0.0", "style-loader": "^4.0.0", "terser": "^5.31.6", "ts-jest": "^29.4.6", @@ -80,4 +85,4 @@ "test:watch": "jest --watch", "test:coverage": "jest --coverage" } -} \ No newline at end of file +} diff --git a/src/app/pages/v3/index.tsx b/src/app/pages/v3/index.tsx index a8eed00..783f156 100644 --- a/src/app/pages/v3/index.tsx +++ b/src/app/pages/v3/index.tsx @@ -1,381 +1,511 @@ import { AssistantWebpluginDeployment, + Channel, useAgentMessages, - useConnectAgent, + useInputModeToggleAgent, VoiceAgent, } from "@rapidaai/react"; -import React, { useState, useEffect, FC, useRef, useCallback } from "react"; -import { formatTimeToHHMMPM } from "@/utils/time"; -import MarkdownPreview from "@uiw/react-markdown-preview"; -import { Input } from "@/app/pages/v3/input"; +import { + BusEventViewChange, + CarbonTheme as AiChatTheme, + ChatContainer, + ChatContainerProps, + ChatCustomElement, + ChatInstance, + CornersType, + LayoutCustomProperties, + MessageResponse, + MessageResponseTypes, + MinimizeButtonIconType, + OptionItemPreference, + PublicConfigMessaging, + RenderWriteableElementResponse, +} from "@carbon/ai-chat"; +import { + CSSProperties, + FC, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; +import { AudioControls } from "@/app/pages/v3/input"; import { useEnvironment } from "@/hooks/use-environment"; -/* ================================================================ - Icons — Carbon 16px - ================================================================ */ -const IconMinimize: FC = () => ( - - - -); - -const IconChat: FC = () => ( - - - - -); - -const IconArrowRight: FC = () => ( - - - -); - -const IconChevronLeft: FC = () => ( - - - -); - -const IconChevronRight: FC = () => ( - - - -); - -/** Watson-style bot avatar */ -const BotAvatarIcon: FC = () => ( - - - - - - - - - - - - - - - -); - -/* ================================================================ - Main export - ================================================================ */ +const PANEL_WIDTH = "min(100vw, 450px)"; +const FLOATING_PANEL_WIDTH = "min(calc(100vw - 32px), 450px)"; +const FLOATING_PANEL_HEIGHT = "min(85dvh, calc(100dvh - 96px))"; +const SHELL_OFFSET = "1rem"; +const SHELL_Z_INDEX = 9999; +const AI_CHAT_INPUT_STYLE_ID = "rapida-chat-input-style"; +const AI_CHAT_INPUT_STYLE = ` + .cds-aichat--input-container { + border-radius: 0 !important; + font-size: 12px !important; + } + + .cds-aichat--input-container [contenteditable="true"], + .cds-aichat--input-container textarea { + font-size: inherit !important; + } +`; + +type PendingResponse = { + resolve: () => void; + abortHandler: () => void; + signal: AbortSignal; +}; + +type WidgetLayoutMode = "floating" | "docked-right" | "docked-left" | "inline"; +type WidgetPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left"; +type ThemeSettings = NonNullable["theme"]; +type LayoutSettings = NonNullable["layout"]; + +type ResolvedLayoutSettings = { + mode: WidgetLayoutMode; + position: WidgetPosition; + showLauncher?: boolean; + aiChatLayout?: ChatContainerProps["layout"]; +}; + export const ChatComponent: FC<{ deployment: AssistantWebpluginDeployment; voiceAgent: VoiceAgent; }> = ({ deployment, voiceAgent }) => { const { theme } = useEnvironment(); const config = window.chatbotConfig; - const layout = config?.layout || "floating"; - const position = config?.position || "bottom-right"; - const showLauncher = config?.showLauncher !== false; - const themeMode = theme?.mode || "light"; - const displayName = config?.name || deployment.getName() || "Assistant"; + const { + assistant_id: _assistantId, + assistant_version: _assistantVersion, + api_base: _apiBase, + token: _token, + language, + user: _user, + name, + logo_url: logoUrl, + layout: layoutSettings, + position: legacyPosition, + showLauncher: legacyShowLauncher, + theme: themeSettings, + ...aiChatConfig + } = config ?? {}; + const { + mode: configThemeMode, + color: _configThemeColor, + injectTheme, + } = themeSettings ?? {}; + const { + mode: layout, + position, + showLauncher, + aiChatLayout, + } = resolveLayoutSettings(layoutSettings, legacyPosition, legacyShowLauncher); + const themeMode = theme?.mode || configThemeMode || "light"; + const displayName = name || deployment.getName() || "Assistant"; + const voiceEnabled = + !!deployment.getInputaudio() && !!deployment.getOutputaudio(); const isDocked = layout === "docked-right" || layout === "docked-left"; + const isCustomElement = isDocked || layout === "inline"; const dockSide = layout === "docked-left" ? "left" : "right"; + const { channel } = useInputModeToggleAgent(voiceAgent); + const { messages } = useAgentMessages(voiceAgent); - // Docked starts open, floating starts closed - const [open, setOpen] = useState(isDocked); + const [customElementOpen, setCustomElementOpen] = useState( + aiChatConfig.openChatByDefault ?? isCustomElement, + ); + const [instanceReadyVersion, setInstanceReadyVersion] = useState(0); + const chatInstanceRef = useRef(null); + const seenRapidaMessageIds = useRef>(new Set()); + const pendingResponses = useRef([]); - // Manage body margin for docked layout useEffect(() => { if (!isDocked) return; - const cls = `rpd-body--docked-${dockSide}`; - if (open) { - document.body.classList.add(cls); - } else { - document.body.classList.remove(cls); - } - return () => document.body.classList.remove(cls); - }, [isDocked, dockSide, open]); - - // Shell class - const shellClass = isDocked - ? `rpd-shell rpd-shell--docked rpd-shell--docked-${dockSide}` - : `rpd-shell rpd-shell--${position} ${layout === "inline" ? "rpd-shell--inline" : ""}`; - return ( -
-
- {/* Panel */} -
- {/* Header */} -
-
- -
- - {/* Messages */} - voiceAgent?.onSendText(msg)} - /> - - {/* Input */} - voiceAgent?.onSendText(msg)} - voiceEnabled={ - !!deployment.getInputaudio() && !!deployment.getOutputaudio() - } - /> -
- - {/* Floating launcher */} - {!isDocked && showLauncher && ( - - )} -
- - {/* Docked expand tab — shown when docked + collapsed */} - {isDocked && !open && ( - - )} -
- ); -}; + const marginKey = dockSide === "right" ? "marginRight" : "marginLeft"; + const previousMargin = document.body.style[marginKey]; -/* ================================================================ - Group consecutive messages by role - ================================================================ */ -type MessageItem = { id: string; role: string; time: Date; messages: string[] }; -type MessageGroup = { role: string; items: MessageItem[] }; - -function groupMessages(messages: MessageItem[]): MessageGroup[] { - return messages.reduce((acc, msg) => { - const last = acc[acc.length - 1]; - if (last && last.role === msg.role) { - last.items.push(msg); - } else { - acc.push({ role: msg.role, items: [msg] }); - } - return acc; - }, []); -} + document.body.style[marginKey] = customElementOpen ? PANEL_WIDTH : ""; -/* ================================================================ - Messages area - ================================================================ */ -const MessagesArea: FC<{ - deployment: AssistantWebpluginDeployment; - voiceAgent: VoiceAgent; - botName: string; - logoUrl?: string; - onSendMessage: (txt: string) => void; -}> = ({ deployment, voiceAgent, botName, logoUrl, onSendMessage }) => { - const { messages } = useAgentMessages(voiceAgent); - const scrollRef = useRef(null); + return () => { + document.body.style[marginKey] = previousMargin; + }; + }, [isDocked, dockSide, customElementOpen]); + + const addMessageToChat = useCallback( + async (message: MessageResponse) => { + await chatInstanceRef.current?.messaging.addMessage(message); + const pending = pendingResponses.current.shift(); + if (pending) { + pending.signal.removeEventListener("abort", pending.abortHandler); + pending.resolve(); + } + }, + [], + ); useEffect(() => { - scrollRef.current?.scrollIntoView({ behavior: "smooth" }); - }, [JSON.stringify(messages)]); - const suggestions = deployment.getSuggestionList(); - const greeting = deployment.getGreeting(); + const instance = chatInstanceRef.current; + if (!instance) return; + + messages.forEach((message) => { + if ( + message.role === "user" || + seenRapidaMessageIds.current.has(message.id) + ) { + return; + } + + seenRapidaMessageIds.current.add(message.id); + void addMessageToChat({ + id: message.id, + output: { + generic: message.messages.map((text) => ({ + response_type: MessageResponseTypes.TEXT, + text, + })), + }, + }); + }); + }, [messages, addMessageToChat, instanceReadyVersion]); + + const customSendMessage = useCallback< + NonNullable + >( + async (request, requestOptions, instance) => { + chatInstanceRef.current = instance; + const text = request.input.text?.trim() ?? ""; + + if (!text) { + await addWelcomeMessage(instance, deployment); + return; + } + + await voiceAgent.onSendText(text); + + return new Promise((resolve) => { + if (requestOptions.signal.aborted) { + resolve(); + return; + } + + const abortHandler = () => { + pendingResponses.current = pendingResponses.current.filter( + (pending) => pending.resolve !== resolve, + ); + resolve(); + }; + + pendingResponses.current.push({ + resolve, + abortHandler, + signal: requestOptions.signal, + }); + requestOptions.signal.addEventListener("abort", abortHandler, { + once: true, + }); + }); + }, + [deployment, voiceAgent], + ); + + const onBeforeRender = useCallback( + async (instance: ChatInstance) => { + chatInstanceRef.current = instance; + applyAiChatInputStyle(); + setInstanceReadyVersion((version) => version + 1); + await aiChatConfig.onBeforeRender?.(instance); + }, + [aiChatConfig], + ); + + const onViewChange = useCallback( + (event: BusEventViewChange, instance: ChatInstance) => { + setCustomElementOpen(Boolean(event.newViewState.mainWindow)); + aiChatConfig.onViewChange?.(event, instance); + }, + [aiChatConfig], + ); + + const renderWriteableElements = useMemo( + () => ({ + ...aiChatConfig.renderWriteableElements, + afterInputElement: ( + <> + {aiChatConfig.renderWriteableElements?.afterInputElement} + + + ), + }), + [aiChatConfig.renderWriteableElements, voiceAgent, voiceEnabled], + ); + + const chatProps = useMemo(() => { + const defaultProps: ChatContainerProps = { + aiEnabled: false, + assistantName: displayName, + assistantAvatarUrl: logoUrl, + debug: aiChatConfig.debug, + injectCarbonTheme: + injectTheme ?? + (themeMode === "dark" + ? AiChatTheme.G100 + : themeMode === "light" + ? AiChatTheme.G10 + : undefined), + locale: language, + namespace: "rapida-chat", + openChatByDefault: isCustomElement, + shouldSanitizeHTML: true, + shouldTakeFocusIfOpensAutomatically: false, + header: { + title: displayName, + showAiLabel: false, + hideDefaultAiLabelContent: true, + minimizeButtonIconType: + dockSide === "left" + ? MinimizeButtonIconType.SIDE_PANEL_LEFT + : MinimizeButtonIconType.SIDE_PANEL_RIGHT, + }, + history: { + isOn: false, + }, + launcher: { + isOn: layout === "floating" ? showLauncher !== false : false, + }, + layout: { + corners: CornersType.SQUARE, + showFrame: true, + customProperties: getThemeLayoutProperties(layout, position), + }, + messaging: { + messageTimeoutSecs: 150, + messageLoadingIndicatorTimeoutSecs: 1, + }, + }; + const resolvedInjectTheme = + injectTheme ?? + aiChatConfig.injectCarbonTheme ?? + defaultProps.injectCarbonTheme; + + return { + ...defaultProps, + ...aiChatConfig, + injectCarbonTheme: resolvedInjectTheme, + header: { + ...defaultProps.header, + ...aiChatConfig.header, + }, + history: { + ...defaultProps.history, + ...aiChatConfig.history, + }, + launcher: { + ...defaultProps.launcher, + ...aiChatConfig.launcher, + }, + layout: { + ...defaultProps.layout, + ...aiChatLayout, + customProperties: { + ...defaultProps.layout?.customProperties, + ...aiChatLayout?.customProperties, + }, + }, + input: { + ...aiChatConfig.input, + isDisabled: + channel === Channel.Audio || aiChatConfig.input?.isDisabled, + }, + messaging: { + ...defaultProps.messaging, + ...aiChatConfig.messaging, + customSendMessage, + }, + onBeforeRender, + onViewChange, + renderWriteableElements, + }; + }, [ + aiChatConfig, + channel, + customSendMessage, + displayName, + dockSide, + aiChatLayout, + injectTheme, + isCustomElement, + language, + layout, + logoUrl, + onBeforeRender, + onViewChange, + position, + renderWriteableElements, + showLauncher, + themeMode, + ]); + + if (!isCustomElement) { + return ; + } return ( -
- {/* Greeting */} -
- -
- -
- - {suggestions.length > 0 && ( - <> -
- {suggestions.map((text, idx) => ( - - ))} -
- - )} -
- - {/* Conversation — group consecutive messages by same role */} - {groupMessages(messages).map((group, gi) => - group.role === "user" ? ( -
-
- You - - {formatTimeToHHMMPM(group.items[0].time)} - -
-
- {group.items.map((msg) => - msg.messages.map((m, ix) => ( - - )), - )} -
-
- ) : ( -
- -
- {group.items.map((msg) => - msg.messages.map((m, ix) => ( - - )), - )} -
-
- ), - )} - - {/* Typing */} - {messages.length > 0 && messages[messages.length - 1].role === "user" && ( -
- - - -
- )} - -
+
+
); }; -/* ================================================================ - Shared sub-components - ================================================================ */ -const BotMessageHeader: FC<{ name: string; logoUrl?: string; time?: Date }> = ({ - name, - logoUrl, - time, -}) => ( -
- {logoUrl ? ( - {name} - ) : ( -
- -
- )} - {name} - {time && ( - {formatTimeToHHMMPM(time)} - )} -
-); +async function addWelcomeMessage( + instance: ChatInstance, + deployment: AssistantWebpluginDeployment, +) { + const generic: MessageResponse["output"]["generic"] = []; + const greeting = deployment.getGreeting(); + const suggestions = deployment.getSuggestionList(); + + if (greeting) { + generic.push({ + response_type: MessageResponseTypes.TEXT, + text: greeting, + }); + } + + if (suggestions.length > 0) { + generic.push({ + response_type: MessageResponseTypes.OPTION, + preference: OptionItemPreference.BUTTON, + options: suggestions.map((label) => ({ + label, + value: { + input: { + text: label, + }, + }, + })), + }); + } + + if (generic.length > 0) { + await instance.messaging.addMessage({ + id: "rapida-welcome", + output: { generic }, + }); + } +} + +function applyAiChatInputStyle() { + document.querySelectorAll("cds-aichat-react").forEach((element) => { + const root = element.shadowRoot; + if (!root || root.getElementById(AI_CHAT_INPUT_STYLE_ID)) return; + + const style = document.createElement("style"); + style.id = AI_CHAT_INPUT_STYLE_ID; + style.textContent = AI_CHAT_INPUT_STYLE; + root.appendChild(style); + }); +} + +function resolveLayoutSettings( + settings: LayoutSettings, + legacyPosition?: WidgetPosition, + legacyShowLauncher?: boolean, +): ResolvedLayoutSettings { + const position = legacyPosition ?? "bottom-right"; + + if (!settings) { + return { + mode: "floating", + position, + showLauncher: legacyShowLauncher, + }; + } + + if (typeof settings === "string") { + return { + mode: settings, + position, + showLauncher: legacyShowLauncher, + }; + } + + const { + mode = "floating", + position: layoutPosition, + showLauncher, + ...aiChatLayout + } = settings; + + return { + mode, + position: layoutPosition ?? position, + showLauncher: showLauncher ?? legacyShowLauncher, + aiChatLayout, + }; +} + +function getThemeLayoutProperties( + layout: string, + position: string, +): Partial> | undefined { + if (layout !== "floating") return undefined; + + return { + [LayoutCustomProperties.width]: FLOATING_PANEL_WIDTH, + [LayoutCustomProperties.height]: FLOATING_PANEL_HEIGHT, + [LayoutCustomProperties.max_height]: FLOATING_PANEL_HEIGHT, + [LayoutCustomProperties.bottom_position]: position.startsWith("bottom") + ? SHELL_OFFSET + : "auto", + [LayoutCustomProperties.top_position]: position.startsWith("top") + ? SHELL_OFFSET + : "auto", + [LayoutCustomProperties.right_position]: position.endsWith("right") + ? SHELL_OFFSET + : "auto", + [LayoutCustomProperties.left_position]: position.endsWith("left") + ? SHELL_OFFSET + : "auto", + [LayoutCustomProperties.launcher_position_bottom]: + position.startsWith("bottom") ? SHELL_OFFSET : "auto", + [LayoutCustomProperties.launcher_position_right]: position.endsWith("right") + ? SHELL_OFFSET + : "auto", + }; +} + +function getCustomElementShellStyle( + layout: string, + dockSide: "left" | "right", + open: boolean, +): CSSProperties { + if (layout === "inline") { + return { + width: "100%", + height: "100%", + minHeight: "560px", + }; + } + + return { + position: "fixed", + top: 0, + bottom: 0, + [dockSide]: 0, + width: open ? PANEL_WIDTH : 0, + height: "100dvh", + zIndex: SHELL_Z_INDEX, + } as CSSProperties; +} + +const customElementStyle: CSSProperties = { + display: "block", + width: "100%", + height: "100%", +}; diff --git a/src/app/pages/v3/input.tsx b/src/app/pages/v3/input.tsx index 9585987..3b4202e 100644 --- a/src/app/pages/v3/input.tsx +++ b/src/app/pages/v3/input.tsx @@ -1,179 +1,73 @@ -import { FC, useState, useMemo, useCallback, useRef } from "react"; -import { useForm } from "react-hook-form"; +import { + CSSProperties, + FC, + useCallback, + useMemo, +} from "react"; +import { Button, Dropdown } from "@carbon/react"; import { useConnectAgent, useInputModeToggleAgent, useMuteAgent, useMultibandMicrophoneTrackVolume, useSelectInputDeviceAgent, - MultibandAudioVisualizerComponent, Channel, VoiceAgent, } from "@rapidaai/react"; -import { AnimatePresence, motion } from "framer-motion"; import { - AudioLines, - Check, - ChevronDown, - Loader2, - MessageSquareText, - Mic, - MicOff, - Send, - StopCircle, -} from "lucide-react"; + AudioConsole, + Chat, + InProgress, + Microphone, + MicrophoneOff, + StopFilled, +} from "@carbon/icons-react"; -/* ================================================================ - Main input — mirrors UI's MessagingAction - Stable wrapper div so React reconciles children in-place. - ================================================================ */ -export const Input: FC<{ - onSendMessage: (txt: string) => void; +export const AudioControls: FC<{ voiceAgent: VoiceAgent; voiceEnabled?: boolean; -}> = ({ onSendMessage, voiceAgent, voiceEnabled = false }) => { +}> = ({ voiceAgent, voiceEnabled = false }) => { const { channel } = useInputModeToggleAgent(voiceAgent); + if (!voiceEnabled) return null; + return ( -
- {voiceEnabled && channel === Channel.Audio ? ( +
+ {channel === Channel.Audio ? ( ) : ( - + )}
); }; -/* ================================================================ - Text input — mirrors UI's SimpleMessagingAction - ================================================================ */ -const TextInput: FC<{ - onSendMessage: (txt: string) => void; - voiceAgent: VoiceAgent; - voiceEnabled: boolean; -}> = ({ onSendMessage, voiceAgent, voiceEnabled }) => { +const StartVoiceButton: FC<{ voiceAgent: VoiceAgent }> = ({ voiceAgent }) => { const { handleVoiceToggle } = useInputModeToggleAgent(voiceAgent); - const { handleConnectAgent, handleDisconnectAgent, isConnected, isConnecting } = + const { handleConnectAgent, isConnected, isConnecting } = useConnectAgent(voiceAgent); - const [isFocused, setIsFocused] = useState(false); - const textareaRef = useRef(null); - - const { - register, - handleSubmit, - reset, - formState: { isValid }, - } = useForm({ mode: "onChange" }); - - const onSubmitForm = (data: any) => { - if (isValid) { - onSendMessage(data.message); - reset(); - } - }; - - const handleResize = (e: React.ChangeEvent) => { - e.target.style.height = "auto"; - e.target.style.height = `${Math.min(e.target.scrollHeight, 120)}px`; - }; - return ( -
{ - if ((e.target as HTMLElement).closest("button")) return; - textareaRef.current?.focus(); +