From 99508db616594083eb74dbe999a7e8b690094349 Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Wed, 21 May 2025 09:14:41 +0100 Subject: [PATCH 01/71] vf-chatbot : Initial code --- components/vf-chatbot-action-prompt/README.md | 107 + .../vf-chatbot-action-prompt/index.scss | 5 + .../vf-chatbot-action-prompt/package.json | 14 + .../vf-chatbot-action-prompt.js | 67 + .../vf-chatbot-action-prompt.njk | 37 + .../vf-chatbot-action-prompt.scss | 59 + .../vf-chatbot-action-prompt.variables.scss | 12 + components/vf-chatbot-fab/README.md | 44 + components/vf-chatbot-fab/package.json | 14 + components/vf-chatbot-fab/vf-chatbot-fab.js | 53 + components/vf-chatbot-fab/vf-chatbot-fab.njk | 20 + components/vf-chatbot-fab/vf-chatbot-fab.scss | 28 + components/vf-chatbot-modal/README.md | 54 + components/vf-chatbot-modal/api-handler.js | 53 + components/vf-chatbot-modal/package.json | 7 + .../vf-chatbot-modal/vf-chatbot-modal.js | 278 +++ .../vf-chatbot-modal/vf-chatbot-modal.njk | 91 + .../vf-chatbot-modal/vf-chatbot-modal.scss | 321 +++ components/vf-chatbot-prompt/package.json | 14 + .../vf-chatbot-prompt/vf-chatbot-prompt.js | 68 + .../vf-chatbot-prompt/vf-chatbot-prompt.njk | 19 + .../vf-chatbot-prompt/vf-chatbot-prompt.scss | 82 + components/vf-chatbot-standalone/README.md | 51 + components/vf-chatbot-standalone/package.json | 15 + .../vf-chatbot-standalone.config.yml | 9 + .../vf-chatbot-standalone.js | 328 +++ .../vf-chatbot-standalone.njk | 121 ++ .../vf-chatbot-standalone.scss | 400 ++++ .../vf-chatbot-welcome/vf-chatbot-welcome.js | 59 + .../vf-chatbot-welcome/vf-chatbot-welcome.njk | 41 + .../vf-chatbot-welcome.scss | 139 ++ .../vf-chatbot/assets/ai-assistant-icon.svg | 67 + components/vf-chatbot/package.json | 16 + components/vf-chatbot/vf-chatbot.js | 102 + components/vf-chatbot/vf-chatbot.njk | 16 + components/vf-chatbot/vf-chatbot.scss | 54 + components/vf-componenet-rollup/index.scss | 14 + .../vf-componenet-rollup/scripts copy.js | 115 ++ components/vf-componenet-rollup/scripts.js | 26 + .../src/site/_includes/layouts/base.njk | 7 + .../src/site/chatbot/index.njk | 58 + tools/vf-component-library/yarn.lock | 1801 ++++++++++------- 42 files changed, 4100 insertions(+), 786 deletions(-) create mode 100644 components/vf-chatbot-action-prompt/README.md create mode 100644 components/vf-chatbot-action-prompt/index.scss create mode 100644 components/vf-chatbot-action-prompt/package.json create mode 100644 components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js create mode 100644 components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk create mode 100644 components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss create mode 100644 components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.variables.scss create mode 100644 components/vf-chatbot-fab/README.md create mode 100644 components/vf-chatbot-fab/package.json create mode 100644 components/vf-chatbot-fab/vf-chatbot-fab.js create mode 100644 components/vf-chatbot-fab/vf-chatbot-fab.njk create mode 100644 components/vf-chatbot-fab/vf-chatbot-fab.scss create mode 100644 components/vf-chatbot-modal/README.md create mode 100644 components/vf-chatbot-modal/api-handler.js create mode 100644 components/vf-chatbot-modal/package.json create mode 100644 components/vf-chatbot-modal/vf-chatbot-modal.js create mode 100644 components/vf-chatbot-modal/vf-chatbot-modal.njk create mode 100644 components/vf-chatbot-modal/vf-chatbot-modal.scss create mode 100644 components/vf-chatbot-prompt/package.json create mode 100644 components/vf-chatbot-prompt/vf-chatbot-prompt.js create mode 100644 components/vf-chatbot-prompt/vf-chatbot-prompt.njk create mode 100644 components/vf-chatbot-prompt/vf-chatbot-prompt.scss create mode 100644 components/vf-chatbot-standalone/README.md create mode 100644 components/vf-chatbot-standalone/package.json create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.js create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.njk create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.scss create mode 100644 components/vf-chatbot-welcome/vf-chatbot-welcome.js create mode 100644 components/vf-chatbot-welcome/vf-chatbot-welcome.njk create mode 100644 components/vf-chatbot-welcome/vf-chatbot-welcome.scss create mode 100644 components/vf-chatbot/assets/ai-assistant-icon.svg create mode 100644 components/vf-chatbot/package.json create mode 100644 components/vf-chatbot/vf-chatbot.js create mode 100644 components/vf-chatbot/vf-chatbot.njk create mode 100644 components/vf-chatbot/vf-chatbot.scss create mode 100644 components/vf-componenet-rollup/scripts copy.js create mode 100644 tools/vf-component-library/src/site/chatbot/index.njk diff --git a/components/vf-chatbot-action-prompt/README.md b/components/vf-chatbot-action-prompt/README.md new file mode 100644 index 0000000000..6d7972145c --- /dev/null +++ b/components/vf-chatbot-action-prompt/README.md @@ -0,0 +1,107 @@ +# Chatbot Action Prompt component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-action-prompt.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-action-prompt) + +## About + +The action prompt component for the Visual Framework chatbot. This component provides interactive links that can be used in the chatbot interface for various purposes such as: + +- Suggestion links in the welcome screen +- Action links within chat messages +- Call-to-action links +- Form submission triggers + +All action prompts are rendered as links with consistent styling, regardless of their function. + +## Usage + +### JavaScript + +```js +import { initVFChatbotActionPrompt } from '@visual-framework/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; +// Or import directly +// import { initVFChatbotActionPrompt } from '../components/raw/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; + +initVFChatbotActionPrompt(); +``` + +### Nunjucks template + +Basic action: +```njk +{% render '@vf-chatbot-action-prompt', { + action_text: "Find workshops near research institutions", + action_data: "find_workshops" +} %} +``` + +External link: +```njk +{% render '@vf-chatbot-action-prompt', { + action_type: "link", + action_text: "Visit our website", + action_url: "https://example.com", + action_target: "_blank" +} %} +``` + +Phone link: +```njk +{% render '@vf-chatbot-action-prompt', { + action_type: "phone", + action_text: "Call support", + action_phone: "+1234567890" +} %} +``` + +Form submit link: +```njk +{% render '@vf-chatbot-action-prompt', { + action_type: "form", + action_text: "Submit", + action_form: "contact-form" +} %} +``` + +## Install + +```bash +yarn add --dev @visual-framework/vf-chatbot-action-prompt +``` + +### Sass/CSS + +The style files included are written in [Sass](https://sass-lang.com/). If you're using a VF-core project, you can import it like this: + +```scss +@import "@visual-framework/vf-chatbot-action-prompt/index.scss"; +``` + +## Options + +| Option | Type | Required | Default | Description | +|--------|------|----------|---------|-------------| +| `action_text` | string | Yes | - | The text to display on the link | +| `action_type` | string | No | "button" | Type of action: "button", "link", "phone", or "form" | +| `action_url` | string | No | - | URL for link type actions | +| `action_target` | string | No | - | Target for link type actions (e.g., "_blank") | +| `action_phone` | string | No | - | Phone number for phone type actions | +| `action_form` | string | No | - | Form ID for form submit actions | +| `action_data` | string | No | - | Custom data to be included in the click event | +| `modifier_class` | string | No | - | Additional CSS classes (e.g., "vf-chatbot-action-prompt--small") | + +## Events + +The component dispatches a custom event when clicked: + +```javascript +document.addEventListener('vf-chatbot-action-prompt:click', function(event) { + console.log('Link text:', event.detail.text); + console.log('Link data:', event.detail.data); + + // Handle the action based on the data + if (event.detail.data === 'find_workshops') { + // Do something specific for this action + } +}); +``` diff --git a/components/vf-chatbot-action-prompt/index.scss b/components/vf-chatbot-action-prompt/index.scss new file mode 100644 index 0000000000..4835d1b007 --- /dev/null +++ b/components/vf-chatbot-action-prompt/index.scss @@ -0,0 +1,5 @@ +// vf-chatbot-action-prompt + +@import 'package.variables.scss'; +@import 'vf-chatbot-action-prompt.variables.scss'; +@import 'vf-chatbot-action-prompt.scss'; \ No newline at end of file diff --git a/components/vf-chatbot-action-prompt/package.json b/components/vf-chatbot-action-prompt/package.json new file mode 100644 index 0000000000..117909d473 --- /dev/null +++ b/components/vf-chatbot-action-prompt/package.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-action-prompt", + "description": "Visual Framework Chatbot Action Prompt component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-action-prompt.css", + "sass": "index.scss", + "main": "vf-chatbot-action-prompt.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} \ No newline at end of file diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js new file mode 100644 index 0000000000..fda8ee90fe --- /dev/null +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js @@ -0,0 +1,67 @@ +// vf-chatbot-action-prompt.js + +class VFChatbotActionPrompt { + constructor(element) { + this.el = element; + this.link = this.el.querySelector(".vf-chatbot-action-prompt__link"); + + if (this.link) { + this.bindEvents(); + } + } + + bindEvents() { + this.link.addEventListener("click", event => { + // If it's a placeholder link or form action + if ( + this.link.getAttribute("href") === "#" || + this.link.hasAttribute("data-vf-js-chatbot-action-form") || + this.link.hasAttribute("data-vf-js-chatbot-standalone-suggestion") + ) { + event.preventDefault(); + + // Handle form submission if needed + const formId = this.link.getAttribute("data-vf-js-chatbot-action-form"); + if (formId) { + const form = document.getElementById(formId); + if (form) { + form.submit(); + return; + } + } + + // Get suggestion text if available + const suggestionText = this.link.getAttribute("data-vf-js-chatbot-standalone-suggestion"); + + // Get action data if available + const actionData = this.link.getAttribute( + "data-vf-js-chatbot-action-data" + ) || suggestionText; + + // Dispatch custom event with action data + this.el.dispatchEvent( + new CustomEvent("vf-chatbot-action-prompt:click", { + bubbles: true, + detail: { + text: suggestionText || this.link.textContent.trim(), + data: actionData + } + }) + ); + } + }); + } +} + +// Initialize component +function initVFChatbotActionPrompt() { + const actionPrompts = document.querySelectorAll( + "[data-vf-js-chatbot-action-prompt]" + ); + + actionPrompts.forEach(actionPrompt => { + new VFChatbotActionPrompt(actionPrompt); + }); +} + +export { VFChatbotActionPrompt, initVFChatbotActionPrompt }; diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk new file mode 100644 index 0000000000..228eabee99 --- /dev/null +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk @@ -0,0 +1,37 @@ +
+ {% if action_type == "link" %} + + {{ action_text }} + + {% elif action_type == "phone" %} + + {{ action_text }} + + {% elif action_type == "form" %} + + {{ action_text }} + + {% else %} + + {{ action_text }} + + {% endif %} +
diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss new file mode 100644 index 0000000000..723d503938 --- /dev/null +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss @@ -0,0 +1,59 @@ +.vf-chatbot-action-prompt { + display: inline-block; + margin: 8px 8px 8px 0; + + &__link { + display: inline-block; + padding: 12px 16px; + border: 1px solid #4b7fd1; // Thin blue border + color: #4b7fd1; // Blue text + background-color: #FFFFFF; + font-size: 16px; + font-weight: 400; // Regular font weight + line-height: 1.2; + text-align: center; + text-decoration: none; // No underline + cursor: pointer; + transition: background-color 0.2s ease; + width: auto; // Width based on content + box-sizing: border-box; + white-space: nowrap; // Prevent text wrapping + + &:hover, &:focus { + background-color: rgba(75, 127, 209, 0.1); // Light blue background on hover + color: #4b7fd1; // Keep text blue on hover + text-decoration: none; // No underline on hover + outline: none; + } + + &:active { + transform: translateY(1px); + } + } + + // Variants + &--small { + .vf-chatbot-action-prompt__link { + padding: 8px 12px; + font-size: 14px; + } + } + + &--large { + .vf-chatbot-action-prompt__link { + padding: 16px 24px; + font-size: 18px; + } + } + + &--full-width { + display: block; + width: 100%; + + .vf-chatbot-action-prompt__link { + display: block; + width: 100%; + white-space: normal; // Allow text wrapping for full-width + } + } +} diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.variables.scss b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.variables.scss new file mode 100644 index 0000000000..5276237c10 --- /dev/null +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.variables.scss @@ -0,0 +1,12 @@ +// vf-chatbot-action-prompt variables + +// Override variables above this line +// -- + +// -- +// Default component variables +// -- + +// -- +// Custom component variables +// -- \ No newline at end of file diff --git a/components/vf-chatbot-fab/README.md b/components/vf-chatbot-fab/README.md new file mode 100644 index 0000000000..ce7a889171 --- /dev/null +++ b/components/vf-chatbot-fab/README.md @@ -0,0 +1,44 @@ +# Chatbot FAB (Floating Action Button) component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-fab.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-fab) + +## About + +The floating action button component for the Visual Framework chatbot. This component provides a persistent button that floats above the page content and allows users to initiate chat interactions. + +## Usage + +### JavaScript + +```js +import { initVFChatbotFab } from '@visual-framework/vf-chatbot-fab/vf-chatbot-fab.js'; +// Or import directly +// import { initVFChatbotFab } from '../components/raw/vf-chatbot-fab/vf-chatbot-fab.js'; + +initVFChatbotFab(); +``` + +### Nunjucks template + +```njk +{% render '@vf-chatbot-fab', { + notification_count: 2, + fab_active: false +} %} +``` + +## Install + +```bash +yarn add --dev @visual-framework/vf-chatbot-fab +``` + +### Sass/CSS + +The style files included are written in [Sass](https://sass-lang.com/). If you're using a VF-core project, you can import it like this: + +```scss +@import "@visual-framework/vf-chatbot-fab/index.scss"; +``` + +Make sure you import Sass requirements along with the modules. You can use a [project boilerplate](https://stable.visual-framework.dev/building/) or the [`vf-sass-starter`](https://stable.visual-framework.dev/components/vf-sass-starter/) \ No newline at end of file diff --git a/components/vf-chatbot-fab/package.json b/components/vf-chatbot-fab/package.json new file mode 100644 index 0000000000..95ddea9e59 --- /dev/null +++ b/components/vf-chatbot-fab/package.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-fab", + "description": "Visual Framework Chatbot Floating Action Button component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-fab.css", + "sass": "index.scss", + "main": "vf-chatbot-fab.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} diff --git a/components/vf-chatbot-fab/vf-chatbot-fab.js b/components/vf-chatbot-fab/vf-chatbot-fab.js new file mode 100644 index 0000000000..f756c5850a --- /dev/null +++ b/components/vf-chatbot-fab/vf-chatbot-fab.js @@ -0,0 +1,53 @@ +// vf-chatbot-fab + +function VFChatbotFab(element) { + this.el = element; + this.chatIcon = this.el.querySelector(".vf-chatbot-fab__icon--chat"); + this.closeIcon = this.el.querySelector(".vf-chatbot-fab__icon--close"); + + this.init(); +} + +VFChatbotFab.prototype = { + init: function() { + this.addEventListeners(); + }, + + addEventListeners: function() { + this.el.addEventListener("click", () => { + this.toggleState(); + }); + }, + + toggleState: function() { + this.el.classList.toggle("vf-chatbot-fab--active"); + + // Toggle icons + if (this.el.classList.contains("vf-chatbot-fab--active")) { + this.chatIcon.style.display = "none"; + this.closeIcon.style.display = "block"; + } else { + this.chatIcon.style.display = "block"; + this.closeIcon.style.display = "none"; + } + + // Dispatch event for parent chatbot component + this.el.dispatchEvent( + new CustomEvent("vf-chatbot-fab:toggle", { + bubbles: true, + detail: { + isActive: this.el.classList.contains("vf-chatbot-fab--active") + } + }) + ); + } +}; + +function initVFChatbotFab() { + const elements = document.querySelectorAll("[data-vf-js-chatbot-fab]"); + for (let i = 0; i < elements.length; i++) { + new VFChatbotFab(elements[i]); + } +} + +export { VFChatbotFab, initVFChatbotFab }; diff --git a/components/vf-chatbot-fab/vf-chatbot-fab.njk b/components/vf-chatbot-fab/vf-chatbot-fab.njk new file mode 100644 index 0000000000..606696a080 --- /dev/null +++ b/components/vf-chatbot-fab/vf-chatbot-fab.njk @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/components/vf-chatbot-fab/vf-chatbot-fab.scss b/components/vf-chatbot-fab/vf-chatbot-fab.scss new file mode 100644 index 0000000000..95f9f09548 --- /dev/null +++ b/components/vf-chatbot-fab/vf-chatbot-fab.scss @@ -0,0 +1,28 @@ +.vf-chatbot-fab { + position: fixed; + bottom: 20px; + right: 20px; + width: 56px; + height: 56px; + border-radius: 50%; + background: #007AFF; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + cursor: pointer; + transition: transform 0.2s ease, background-color 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + border: none; + + &:hover { + transform: scale(1.05); + background: darken(#007AFF, 10%); + } + + &__icon { + width: 24px; + height: 24px; + fill: #ffffff; + } +} diff --git a/components/vf-chatbot-modal/README.md b/components/vf-chatbot-modal/README.md new file mode 100644 index 0000000000..cfaaf35c8b --- /dev/null +++ b/components/vf-chatbot-modal/README.md @@ -0,0 +1,54 @@ +# Chatbot Modal component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-modal.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-modal) + +## About + +The chat modal component for the Visual Framework chatbot. This component provides the main chat interface that appears when users click the floating action button. + +## Features + +- Responsive design that works on both desktop and mobile +- Auto-expanding input field +- Message history with automatic scrolling +- Smooth animations for show/hide +- Event-based communication with parent components +- Optional settings button +- Customizable welcome message + +## Usage + +### JavaScript + +```js +import { initVFChatbotModal } from '@visual-framework/vf-chatbot-modal/vf-chatbot-modal.js'; +// Or import directly +// import { initVFChatbotModal } from '../components/raw/vf-chatbot-modal/vf-chatbot-modal.js'; + +initVFChatbotModal(); +``` + +### Nunjucks template + +```njk +{% render '@vf-chatbot-modal', { + title: "Chat with us", + welcome_message: "Hello! How can I help you today?", + input_placeholder: "Type your message...", + show_settings: true +} %} +``` + +## Install + +```bash +yarn add --dev @visual-framework/vf-chatbot-modal +``` + +### Sass/CSS + +The style files included are written in [Sass](https://sass-lang.com/). If you're using a VF-core project, you can import it like this: + +```scss +@import "@visual-framework/vf-chatbot-modal/index.scss"; +``` \ No newline at end of file diff --git a/components/vf-chatbot-modal/api-handler.js b/components/vf-chatbot-modal/api-handler.js new file mode 100644 index 0000000000..c1ab575abc --- /dev/null +++ b/components/vf-chatbot-modal/api-handler.js @@ -0,0 +1,53 @@ +export class LLMApiHandler { + constructor() { + // You'll need to sign up at Hugging Face and get your API token + // https://huggingface.co/settings/tokens + this.API_TOKEN = "0R6jmdaEMeRFCsUBnrbxhbSQyYhe03Z6"; //"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"; + this.API_URL = "https://api.mistral.ai/v1/chat/completions"; + // "https://api-inference.huggingface.co/models/facebook/blenderbot-400M-distill"; + } + + async generateResponse(message) { + console.log("Generating response for:", message); // Debug log + + try { + const response = await fetch(this.API_URL, { + method: "POST", + headers: { + Authorization: `Bearer ${this.API_TOKEN}`, + "Content-Type": "application/json" + }, + data: JSON.stringify({ + "messages": [{"role": "user", "content": message}], + "model": "mistral-small-latest", + }) + }); + + console.log("API response status:", response.status); // Debug log + + if (!response.ok) { + const errorText = await response.text(); + console.error("API error:", errorText); // Debug log + throw new Error(`API request failed: ${response.status} ${errorText}`); + } + + const data = await response.json(); + console.log("API response data:", data); // Debug log + + return { + html: this.formatResponse(data[0].generated_text) + }; + } catch (error) { + console.error("LLM API Error:", error); // Debug log + throw error; + } + } + + formatResponse(text) { + if (!text) return "

No response generated

"; + return text + .split("\n") + .map(paragraph => `

${paragraph}

`) + .join(""); + } +} diff --git a/components/vf-chatbot-modal/package.json b/components/vf-chatbot-modal/package.json new file mode 100644 index 0000000000..eb9643fb43 --- /dev/null +++ b/components/vf-chatbot-modal/package.json @@ -0,0 +1,7 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-modal", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.js b/components/vf-chatbot-modal/vf-chatbot-modal.js new file mode 100644 index 0000000000..d07564f99d --- /dev/null +++ b/components/vf-chatbot-modal/vf-chatbot-modal.js @@ -0,0 +1,278 @@ +// vf-chatbot-modal + +class VFChatbotModal { + constructor(element) { + console.log("Initializing chatbot modal..."); // Debug log + + // API configuration + this.API_TOKEN = "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"; // Replace with your token + this.API_URL = + "https://api-inference.huggingface.co/models/facebook/blenderbot-400M-distill"; + + // Store DOM elements + this.modal = element; + this.trigger = document.querySelector("[data-vf-js-chatbot-trigger]"); + this.closeBtn = this.modal.querySelector("[data-vf-js-chatbot-close]"); + this.minimizeBtn = this.modal.querySelector( + "[data-vf-js-chatbot-minimize]" + ); + this.input = this.modal.querySelector(".vf-chatbot-modal__input"); + this.sendBtn = this.modal.querySelector("[data-vf-js-chatbot-send]"); + this.messagesContainer = this.modal.querySelector( + ".vf-chatbot-modal__messages" + ); + this.welcomeScreen = this.modal.querySelector( + "[data-vf-js-chatbot-welcome]" + ); + this.suggestionBtns = this.modal.querySelectorAll( + "[data-vf-js-chatbot-suggestion]" + ); + + // State + this.hasInteracted = false; + + this.bindEvents(); + } + + bindEvents() { + console.log("Binding events..."); // Debug log + + // Toggle modal + this.trigger?.addEventListener("click", () => this.toggleModal()); + this.closeBtn?.addEventListener("click", e => { + e.stopPropagation(); + this.closeModal(); + }); + this.minimizeBtn?.addEventListener("click", e => { + e.stopPropagation(); + this.minimize(); + }); + + // Send message events + this.sendBtn?.addEventListener("click", () => this.sendMessage()); + this.input?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendMessage(); + } + }); + + // Welcome screen events + if (this.welcomeScreen) { + this.welcomeScreen.addEventListener("vf-chatbot-welcome:closed", () => { + this.showChatInterface(); + }); + + this.welcomeScreen.addEventListener( + "vf-chatbot-welcome:suggestion", + event => { + const { text } = event.detail; + this.showChatInterface(); + this.sendUserMessage(text); + } + ); + } + + // Suggestion buttons + this.suggestionBtns.forEach(btn => { + btn.addEventListener("click", () => { + const text = + btn.getAttribute("data-vf-js-chatbot-suggestion") || + btn.textContent.trim(); + this.sendUserMessage(text); + }); + }); + } + + showChatInterface() { + if (this.welcomeScreen) { + this.welcomeScreen.style.display = "none"; + } + + this.messagesContainer.style.display = "block"; + this.input.focus(); + this.hasInteracted = true; + } + + resetWelcomeScreen() { + if (this.welcomeScreen && !this.hasInteracted) { + this.welcomeScreen.style.display = "flex"; + this.messagesContainer.style.display = "none"; + } + } + + minimize() { + this.modal.classList.add("vf-chatbot-modal--minimized"); + this.modal.classList.remove("vf-chatbot-modal--active"); + + // Dispatch minimize event + this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:minimize")); + } + + maximize() { + // First remove minimized to ensure smooth transition + this.modal.classList.remove("vf-chatbot-modal--minimized"); + + // Small delay to ensure CSS transition works properly + requestAnimationFrame(() => { + this.modal.classList.add("vf-chatbot-modal--active"); + + // Focus on input if it exists + const input = this.modal.querySelector(".vf-chatbot-modal__input"); + if (input) { + setTimeout(() => input.focus(), 300); + } + }); + + // Dispatch maximize event + this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:maximize")); + + // Focus on input if welcome screen is not shown + if (this.hasInteracted) { + setTimeout(() => this.input.focus(), 300); + } + } + + closeModal() { + this.modal.classList.remove("vf-chatbot-modal--active"); + this.modal.classList.remove("vf-chatbot-modal--minimized"); + + // Reset welcome screen for next open + this.resetWelcomeScreen(); + + // Dispatch close event + this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:close")); + } + + toggleModal() { + const isMinimized = this.modal.classList.contains( + "vf-chatbot-modal--minimized" + ); + const isActive = this.modal.classList.contains("vf-chatbot-modal--active"); + + if (isMinimized || !isActive) { + this.maximize(); + } else { + this.minimize(); + } + } + + sendUserMessage(text) { + // Add user message to UI + const userMessageEl = document.createElement("div"); + userMessageEl.className = "vf-chatbot-message vf-chatbot-message--user"; + userMessageEl.innerHTML = ` +
${text}
+ `; + this.messagesContainer.appendChild(userMessageEl); + + // Clear input if this came from the input field + if (this.input.value === text) { + this.input.value = ""; + } + + this.scrollToBottom(); + + // Process the message (simulate response) + this.processUserMessage(text); + } + + sendMessage() { + const text = this.input.value.trim(); + if (!text) return; + + this.sendUserMessage(text); + } + + async processUserMessage(message) { + // Show loading state + this.setLoadingState(true); + + try { + const response = await this.callAPI(message); + console.log("API Response:", response); // Debug log + this.addMessage(response, "system"); + } catch (error) { + console.error("Error:", error); + this.addMessage( + "Sorry, I encountered an error. Please try again.", + "system" + ); + } + + // // Simulate API call with timeout + setTimeout(() => { + // Add assistant response + this.addAssistantResponse(this.getSimulatedResponse(message)); + this.setLoadingState(false); + }, 1000); + } + + addAssistantResponse(text) { + const assistantMessageEl = document.createElement("div"); + assistantMessageEl.className = + "vf-chatbot-message vf-chatbot-message--assistant"; + assistantMessageEl.innerHTML = ` + AI Assistant +
${text}
+ `; + this.messagesContainer.appendChild(assistantMessageEl); + + this.scrollToBottom(); + } + + getSimulatedResponse(text) { + // Simple response simulation + if (text.toLowerCase().includes("metabolomics")) { + return "Metabolomics is the large-scale study of small molecules,"; + } else if (text.toLowerCase().includes("genomics")) { + return "Genomics is the study of the structure, function, evolution, and mapping of genomes."; + } else if (text.toLowerCase().includes("proteomics")) { + return "Proteomics is the study of the structure, function, and regulation of the proteome."; + } else if (text.toLowerCase().includes("transcriptomics")) { + return "Transcriptomics is the study of the complete set of RNA molecules within a cell."; + } else if (text.toLowerCase().includes("epigenomics")) { + return "Epigenomics is the study of heritable changes in gene function that do not involve changes to the DNA sequence."; + } else if (text.toLowerCase().includes("metabolomics")) { + return "Metabolomics is the large-scale study of small molecules,"; + } else if (text.toLowerCase().includes("genomics")) { + return "Genomics is the study of the structure, function, evolution, and mapping of genomes."; + } else if (text.toLowerCase().includes("proteomics")) { + return "Proteomics is the study of the structure, function, and regulation of the proteome."; + } else if (text.toLowerCase().includes("transcriptomics")) { + return "Transcriptomics is the study of the complete set of RNA molecules within a cell."; + } else if (text.toLowerCase().includes("epigenomics")) { + return "Epigenomics is the study of heritable changes in gene function that do not involve changes to the DNA sequence."; + } else { + return "I'm sorry, I didn't understand that. Could you please provide more context or ask a specific question?"; + } + } + + setLoadingState(isLoading) { + this.input.disabled = isLoading; + this.sendBtn.disabled = isLoading; + this.sendBtn.innerHTML = isLoading ? "Sending..." : "Send"; + } + + scrollToBottom() { + this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + } +} + +// Initialize +function initVFChatbotModal() { + console.log("Looking for chatbot elements..."); // Debug log + const chatbotElements = document.querySelectorAll( + "[data-vf-js-chatbot-modal]" + ); + + if (chatbotElements.length === 0) { + console.warn("No chatbot elements found on page"); + return; + } + + console.log(`Found ${chatbotElements.length} chatbot elements`); // Debug log + chatbotElements.forEach(element => new VFChatbotModal(element)); +} + +export { VFChatbotModal, initVFChatbotModal }; diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.njk b/components/vf-chatbot-modal/vf-chatbot-modal.njk new file mode 100644 index 0000000000..ed46d2558a --- /dev/null +++ b/components/vf-chatbot-modal/vf-chatbot-modal.njk @@ -0,0 +1,91 @@ + +
+
+
+

+ AI Assistant + {{ title | default("AI Assistant") }} +

+
+
+ + +
+
+ +
+ + {% render '@vf-chatbot-welcome', { + welcome_title: welcome_title | default('AI Assistant'), + welcome_description: welcome_description | default('I can help you find information about our research, services, and more. What would you like to know?'), + welcome_features: welcome_features | default([ + 'Finding research publications', + 'Learning about our services', + 'Getting information about events', + 'Understanding scientific concepts' + ]), + welcome_suggestions: welcome_suggestions | default([ + 'What is Metabolomics?', + 'Tell me about your training courses', + 'How can I access your data resources?', + 'What research areas do you focus on?' + ]) + } %} + + +
+ {% if welcome_message %} +
+ AI Assistant +
+ {{ welcome_message | safe }} +
+
+ {% endif %} +
+ +
+
+ + +
+
+ + {% if show_suggestions %} +
+ +
+ {% endif %} +
+
diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.scss b/components/vf-chatbot-modal/vf-chatbot-modal.scss new file mode 100644 index 0000000000..5ad2e9b63e --- /dev/null +++ b/components/vf-chatbot-modal/vf-chatbot-modal.scss @@ -0,0 +1,321 @@ +.vf-chatbot-modal { + display: none; + position: fixed; + bottom: 80px; + right: 20px; + width: 360px; + height: 500px; + background: #ffffff; + border-radius: 16px 16px 0px 16px; // Increased border radius + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + z-index: 999; + overflow: hidden; + transition: all 0.3s ease; + opacity: 0; + transform: translateY(20px); + + &--active { + display: flex; + flex-direction: column; + opacity: 1; + transform: translateY(0); + + .vf-chatbot-modal__content { + display: flex; + flex-direction: column; + flex: 1; + } + } + + &--minimized { + display: flex; + flex-direction: column; + height: 60px; + opacity: 1; + transform: translateY(0); + overflow: hidden; + + .vf-chatbot-modal__content { + visibility: hidden; + height: 0; + } + } + + &__header { + height: 60px; + min-height: 60px; // Add this to prevent header from shrinking + padding: 0 16px; + background: #ffffff; // White background + border-bottom: 1px solid #E5E5E5; + color: #000000; + display: flex; + align-items: center; + justify-content: space-between; + border-radius: 16px 16px 0 0; + + &-left { + display: flex; + align-items: center; + gap: 8px; + } + } + + &__title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + display: flex; + align-items: center; + gap: 8px; + + img { + width: 24px; + height: 24px; + } + } + + &__content { + display: flex; + flex-direction: column; + flex: 1; + transition: visibility 0.3s ease, height 0.3s ease; + } + + &__messages { + flex: 1; + overflow-y: auto; + padding: 16px; + background: #F5F5F5; + } + + &__input-area { + background: #ffffff; + border-top: 1px solid #E5E5E5; + } + + &__input-wrapper { + position: relative; + } + + &__input { + width: 100%; + padding-left: 20px; + padding-right: 44px; // Space for the send button + border: 1px solid #E5E5E5; + font-size: 14px; + line-height: 1.5; + resize: none; + min-height: 44px; + max-height: 120px; + background: #F5F5F5; + + &:focus { + outline: none; + // border-color: #007AFF; + background: #ffffff; + } + + &::placeholder { + color: #666666; + } + } + + &__send-button { + position: absolute; + right: 0px; + height: 100%; + top: 50%; + transform: translateY(-50%); + background: #007AFF; + color: #ffffff; + border: none; + padding: 8px; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + } + + &__controls { + display: flex; + gap: 8px; + + button { + background: none; + border: none; + padding: 8px; + cursor: pointer; + color: #666666; + + &:hover { + color: #1A1A1A; + } + } + } + + // Smooth transition for minimize/maximize + &__content { + transition: all 0.2s ease; + } + + // Add minimized state styles + &--minimized { + height: 60px !important; // Override default height + + .vf-chatbot-modal__content { + display: none; + } + + .vf-chatbot-modal__header { + border-bottom: none; + padding-bottom: 0; + } + + .vf-chatbot-modal__title { + font-size: 1rem; + } + } + + @media (max-width: 480px) { + width: calc(100% - 40px); + height: calc(100vh - 100px); + bottom: 70px; + + &--minimized { + height: 60px; + } + } +} + +.vf-loading-spinner { + animation: rotate 2s linear infinite; + width: 20px; + height: 20px; + + & .path { + stroke: currentColor; + stroke-linecap: round; + animation: dash 1.5s ease-in-out infinite; + } +} + +@keyframes rotate { + 100% { + transform: rotate(360deg); + } +} + +@keyframes dash { + 0% { + stroke-dasharray: 1, 150; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -35; + } + 100% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -124; + } +} + +// Message styles +.vf-chatbot-message { + margin-bottom: 16px; + max-width: 85%; + + &--user { + margin-left: auto; + + .vf-chatbot-message__content { + background: #1A1A1A; + color: #ffffff; + border-radius: 16px 16px 4px 16px; + } + } + + &--assistant { + margin-right: auto; + display: flex; + align-items: flex-start; + gap: 8px; + + .vf-chatbot-message__avatar { + width: 24px; + height: 24px; + border-radius: 50%; + } + + .vf-chatbot-message__content { + background: #ffffff; + color: #1A1A1A; + border-radius: 16px 16px 16px 4px; + } + } + + &__content { + padding: 12px 16px; + font-size: 14px; + line-height: 1.5; + } +} + +// Suggestion area +.vf-chatbot-suggestions { + padding: 16px; + background: #ffffff; + border-top: 1px solid #E5E5E5; + + &__input { + width: 100%; + padding: 12px 16px; + background: #F5F5F5; + border: none; + border-radius: 8px; + color: #666666; + font-size: 14px; + cursor: pointer; + text-align: left; + + &:hover { + background: darken(#F5F5F5, 5%); + } + } +} + +.vf-chatbot-trigger { + position: fixed; + bottom: 20px; + right: 20px; + padding: 12px 24px; + background: var(--vf-color-primary); + color: white; + border: none; + border-radius: 24px; + cursor: pointer; + z-index: 998; + + &:hover { + background: var(--vf-color-primary-dark); + } +} + +.vf-chatbot-modal__title img { + width: 24px; + height: 24px; + margin-right: 8px; + vertical-align: middle; +} + +.vf-chatbot-message--assistant img.vf-chatbot-message__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + background-color: #fff; + object-fit: contain; + padding: 0; + border: 1px solid #eee; +} diff --git a/components/vf-chatbot-prompt/package.json b/components/vf-chatbot-prompt/package.json new file mode 100644 index 0000000000..56b9f25d0d --- /dev/null +++ b/components/vf-chatbot-prompt/package.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-prompt", + "description": "Visual Framework Chatbot Prompt component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-prompt.css", + "sass": "index.scss", + "main": "vf-chatbot-prompt.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} \ No newline at end of file diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.js b/components/vf-chatbot-prompt/vf-chatbot-prompt.js new file mode 100644 index 0000000000..76ce4aa01b --- /dev/null +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.js @@ -0,0 +1,68 @@ +// vf-chatbot-prompt + +function VFChatbotPrompt(element) { + this.el = element; + this.loading = false; +} + +VFChatbotPrompt.prototype = { + setLoading: function(isLoading) { + this.loading = isLoading; + + if (isLoading) { + // Remove existing loading element if any + this.removeLoading(); + + // Create loading element + const loadingEl = document.createElement("div"); + loadingEl.className = "vf-chatbot-prompt__loading"; + loadingEl.innerHTML = ` + + + + `; + + this.el.appendChild(loadingEl); + } else { + this.removeLoading(); + } + }, + + removeLoading: function() { + const loadingEl = this.el.querySelector(".vf-chatbot-prompt__loading"); + if (loadingEl) { + loadingEl.remove(); + } + }, + + setResponse: function(html) { + // Remove loading first + this.setLoading(false); + + // Create response element + const responseEl = document.createElement("div"); + responseEl.className = + "vf-chatbot-prompt__message vf-chatbot-prompt__message--system"; + responseEl.innerHTML = html; + + this.el.appendChild(responseEl); + } +}; + +function initVFChatbotPrompt(message) { + const el = document.createElement("div"); + el.className = "vf-chatbot-prompt"; + el.setAttribute("data-vf-js-chatbot-prompt", ""); + + const messageEl = document.createElement("div"); + messageEl.className = + "vf-chatbot-prompt__message vf-chatbot-prompt__message--user"; + messageEl.textContent = message; + + el.appendChild(messageEl); + + const prompt = new VFChatbotPrompt(el); + return prompt; +} + +export { VFChatbotPrompt, initVFChatbotPrompt }; diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.njk b/components/vf-chatbot-prompt/vf-chatbot-prompt.njk new file mode 100644 index 0000000000..a8c7646190 --- /dev/null +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.njk @@ -0,0 +1,19 @@ +
+
+ {{ message }} +
+ + {% if loading %} +
+ + + +
+ {% endif %} + + {% if response %} +
+ {{ response | safe }} +
+ {% endif %} +
\ No newline at end of file diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.scss b/components/vf-chatbot-prompt/vf-chatbot-prompt.scss new file mode 100644 index 0000000000..5dcd88b387 --- /dev/null +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.scss @@ -0,0 +1,82 @@ +.vf-chatbot-prompt { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 16px; + + &__message { + padding: 12px 16px; + border-radius: 12px; + max-width: 80%; + line-height: 1.4; + + &--user { + background: var(--vf-color-gray-100); + align-self: flex-end; + border-bottom-right-radius: 4px; + } + + &--system { + background: var(--vf-color-primary-light); + align-self: flex-start; + border-bottom-left-radius: 4px; + + // Style for rich text content + p { + margin: 0 0 8px 0; + &:last-child { + margin-bottom: 0; + } + } + + code { + background: rgba(0, 0, 0, 0.05); + padding: 2px 4px; + border-radius: 4px; + } + + pre { + background: rgba(0, 0, 0, 0.05); + padding: 8px; + border-radius: 4px; + overflow-x: auto; + } + } + } + + &__loading { + align-self: flex-start; + display: flex; + gap: 4px; + padding: 12px 16px; + background: var(--vf-color-primary-light); + border-radius: 12px; + border-bottom-left-radius: 4px; + } + + &__dot { + width: 8px; + height: 8px; + background: var(--vf-color-gray-600); + border-radius: 50%; + opacity: 0.3; + animation: dot-flash 1.4s infinite; + + &:nth-child(2) { + animation-delay: 0.2s; + } + + &:nth-child(3) { + animation-delay: 0.4s; + } + } +} + +@keyframes dot-flash { + 0%, 60%, 100% { + opacity: 0.3; + } + 30% { + opacity: 1; + } +} \ No newline at end of file diff --git a/components/vf-chatbot-standalone/README.md b/components/vf-chatbot-standalone/README.md new file mode 100644 index 0000000000..77e522683c --- /dev/null +++ b/components/vf-chatbot-standalone/README.md @@ -0,0 +1,51 @@ +# Chatbot Standalone component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-standalone.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-standalone) + +## About + +A full-page standalone chatbot interface that can be accessed via a direct URL. This component reuses elements from the chatbot modal but is designed to work as a standalone page rather than a popup. + +## Usage + +### JavaScript + +```js +import { initVFChatbotStandalone } from '@visual-framework/vf-chatbot-standalone/vf-chatbot-standalone.js'; +// Or import directly +// import { initVFChatbotStandalone } from '../components/raw/vf-chatbot-standalone/vf-chatbot-standalone.js'; + +initVFChatbotStandalone(); +``` + +### Nunjucks template + +```njk +{% render '@vf-chatbot-standalone', { + title: "AI Assistant", + welcome_message: "Hello! How can I help you today?", + input_placeholder: "Type your message...", + show_suggestions: true, + show_close_button: true +} %} +``` + +## Install + +```bash +yarn add --dev @visual-framework/vf-chatbot-standalone +``` + +### Sass/CSS + +The style files included are written in [Sass](https://sass-lang.com/). If you're using a VF-core project, you can import it like this: + +```scss +@import "@visual-framework/vf-chatbot-standalone/index.scss"; +``` + +## Help + +- [Read the Visual Framework troubleshooting](https://stable.visual-framework.dev/troubleshooting/) +- [Open a ticket](https://github.com/visual-framework/vf-core/issues) +- [Chat on Slack](https://join.slack.com/t/visual-framework/shared_invite/enQtNDAxNzY0NDg4NTY0LWFhMjEwNGY3ZTk3NWYxNWVjOWQ1ZWE4YjViZmY1YjBkMDQxMTNlNjQ0N2ZiMTQ1ZTZiMGM4NjU5Y2E0MjM3ZGQ) \ No newline at end of file diff --git a/components/vf-chatbot-standalone/package.json b/components/vf-chatbot-standalone/package.json new file mode 100644 index 0000000000..b7c35f7d4e --- /dev/null +++ b/components/vf-chatbot-standalone/package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-standalone", + "description": "Visual Framework Standalone Chatbot component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-standalone.css", + "sass": "index.scss", + "main": "vf-chatbot-standalone.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config", + "@visual-framework/vf-chatbot-welcome": "file:../vf-chatbot-welcome" + } +} diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml b/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml new file mode 100644 index 0000000000..12e73a086c --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml @@ -0,0 +1,9 @@ +title: Chatbot Standalone +label: Chatbot Standalone +status: beta +preview: '@preview' +context: + title: AI Assistant + welcome_message: Hello! How can I help you today? + input_placeholder: Type your message... + show_suggestions: true diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.js b/components/vf-chatbot-standalone/vf-chatbot-standalone.js new file mode 100644 index 0000000000..a4a39055f7 --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.js @@ -0,0 +1,328 @@ +// vf-chatbot-standalone.js +class VFChatbotStandalone { + constructor(element) { + console.log("Initializing standalone chatbot..."); // Debug log + + // Store DOM elements + this.container = element; + this.welcomeScreen = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome]" + ); + this.chatInterface = this.container.querySelector( + "[data-vf-js-chatbot-standalone-chat]" + ); + this.messagesContainer = this.container.querySelector( + "[data-vf-js-chatbot-standalone-messages]" + ); + this.loadingIndicator = this.container.querySelector( + "[data-vf-js-chatbot-standalone-loading]" + ); + this.input = this.container.querySelector( + "[data-vf-js-chatbot-standalone-input]" + ); + this.sendBtn = this.container.querySelector( + "[data-vf-js-chatbot-standalone-send]" + ); + this.welcomeInput = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome-input]" + ); + this.welcomeSendBtn = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome-send]" + ); + this.suggestionBtns = this.container.querySelectorAll( + "[data-vf-js-chatbot-standalone-suggestion]" + ); + + // API configuration - reuse from modal component + this.API_TOKEN = "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"; // Replace with your token + this.API_URL = + "https://huggingface.co/facebook/blenderbot-1B-distill"; + + // State + this.hasInteracted = false; + + this.bindEvents(); + this.initAutoResize(); + + console.log("Standalone chatbot initialized successfully"); // Debug log + } + + bindEvents() { + console.log("Binding events for standalone chatbot..."); // Debug log + + // Send message events + this.sendBtn?.addEventListener("click", () => this.sendMessage()); + this.input?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendMessage(); + } + }); + + // Welcome screen input events + this.welcomeSendBtn?.addEventListener("click", () => + this.sendWelcomeMessage() + ); + this.welcomeInput?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendWelcomeMessage(); + } + }); + + // Welcome screen suggestion buttons + this.suggestionBtns.forEach(btn => { + btn.addEventListener("click", () => { + const text = + btn.getAttribute("data-vf-js-chatbot-standalone-suggestion") || + btn.textContent.trim(); + + // Show chat interface + this.showChatInterface(); + + // Update the input field with the suggestion text + if (this.input && text) { + this.input.value = text; + + // Adjust the height of the input field to match content + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + } + + // Send the message to the API + if (text) { + this.sendUserMessage(text); + } + }); + }); + + // Listen for action prompt clicks + this.container.addEventListener("vf-chatbot-action-prompt:click", event => { + const { text, data } = event.detail; + + // Show chat interface + this.showChatInterface(); + + // Update the input field with the suggestion text + if (this.input && text) { + this.input.value = text; + + // Adjust the height of the input field to match content + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + } + + // Send the message to the API + if (text) { + this.sendUserMessage(text); + } + }); + } + + initAutoResize() { + // Auto-resize textarea as user types + if (this.input) { + this.input.addEventListener("input", () => { + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + }); + } + } + + sendMessage() { + if (!this.input || !this.input.value.trim()) return; + + const text = this.input.value.trim(); + this.sendUserMessage(text); + } + + sendWelcomeMessage() { + if (!this.welcomeInput || !this.welcomeInput.value.trim()) return; + + const text = this.welcomeInput.value.trim(); + this.showChatInterface(); + this.sendUserMessage(text); + } + + showChatInterface() { + if (this.welcomeScreen) { + this.welcomeScreen.style.display = "none"; + } + if (this.chatInterface) { + this.chatInterface.style.display = "block"; + } + + // Focus on the input field + if (this.input) { + this.input.focus(); + } + + this.hasInteracted = true; + } + + sendUserMessage(text) { + if (!text || !this.messagesContainer) return; + + // Add user message to UI + const userMessageEl = document.createElement("div"); + userMessageEl.className = "vf-chatbot-message vf-chatbot-message--user"; + userMessageEl.innerHTML = ` +
${text}
+ `; + this.messagesContainer.appendChild(userMessageEl); + + // Clear input if this came from the input field + if (this.input && this.input.value === text) { + this.input.value = ""; + this.input.style.height = "auto"; // Reset height + } + + this.scrollToBottom(); + + // Process the message + this.processUserMessage(text); + } + + processUserMessage(text) { + // Show loading state + this.setLoadingState(true); + + // Call the API + this.callAPI(text) + .then(response => { + this.addAssistantResponse(response.html || response); + this.setLoadingState(false); + }) + .catch(error => { + console.error("API Error:", error); + // Fallback to simulated response if API fails + this.addAssistantResponse(this.getSimulatedResponse(text)); + this.setLoadingState(false); + }); + } + + callAPI(text) { + return new Promise((resolve, reject) => { + fetch(this.API_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${this.API_TOKEN}` + }, + body: JSON.stringify({ inputs: text }) + }) + .then(response => { + if (!response.ok) { + throw new Error(`API error: ${response.status}`); + } + return response.json(); + }) + .then(data => { + if (data && data.generated_text) { + resolve(data.generated_text); + } else { + reject(new Error("Invalid API response")); + } + }) + .catch(error => { + console.error("API call failed:", error); + reject(error); + }); + }); + } + + addAssistantResponse(text) { + if (!text || !this.messagesContainer) return; + + // Add assistant message to UI + const assistantMessageEl = document.createElement("div"); + assistantMessageEl.className = + "vf-chatbot-message vf-chatbot-message--assistant"; + assistantMessageEl.innerHTML = ` +
+ AI Assistant +
+
${text}
+ `; + this.messagesContainer.appendChild(assistantMessageEl); + + this.scrollToBottom(); + } + + setLoadingState(isLoading) { + if (this.loadingIndicator) { + this.loadingIndicator.style.display = isLoading ? "flex" : "none"; + } + + if (this.sendBtn) { + this.sendBtn.disabled = isLoading; + } + + if (this.input) { + this.input.disabled = isLoading; + } + + this.scrollToBottom(); + } + + scrollToBottom() { + if (this.messagesContainer) { + this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + } + } + + getSimulatedResponse(text) { + // Fallback responses when API fails + const fallbackResponses = [ + "I'm sorry, I'm having trouble connecting to my knowledge base right now. Could you try again in a moment?", + "That's an interesting question. Let me think about how to best answer that for you.", + "I understand you're asking about bioinformatics training. We have several resources available. Could you tell me more about your specific interests?", + "Thank you for your question. We offer various workshops and online courses on that topic. Would you like me to provide more specific information?", + "I'd be happy to help with that. We have both introductory and advanced courses available depending on your experience level." + ]; + + return fallbackResponses[ + Math.floor(Math.random() * fallbackResponses.length) + ]; + } +} + +// Initialize +function initVFChatbotStandalone() { + console.log("Looking for standalone chatbot elements..."); // Debug log + const chatbotElements = document.querySelectorAll( + "[data-vf-js-chatbot-standalone]" + ); + + if (chatbotElements.length === 0) { + console.warn("No standalone chatbot elements found on page"); + return; + } + + console.log(`Found ${chatbotElements.length} standalone chatbot elements`); // Debug log + + // Initialize each standalone chatbot element + const instances = []; + chatbotElements.forEach(element => { + instances.push(new VFChatbotStandalone(element)); + }); + + return instances; +} + +// Make initialization function available globally +if (typeof window !== "undefined") { + window.VFChatbotStandalone = VFChatbotStandalone; + window.initVFChatbotStandalone = initVFChatbotStandalone; + + // Also make it available as a global variable without window prefix + if (typeof globalThis !== "undefined") { + globalThis.VFChatbotStandalone = VFChatbotStandalone; + globalThis.initVFChatbotStandalone = initVFChatbotStandalone; + } + + console.log("Exposed initVFChatbotStandalone to global scope"); +} + +// Export both the class and the initialization function +export { VFChatbotStandalone, initVFChatbotStandalone }; diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk new file mode 100644 index 0000000000..1845bdcbd0 --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk @@ -0,0 +1,121 @@ + +
+
+
+
+

+ + AI Assistant + {{ title | default("AI assistant") }} +

+
+
+ +
+ + +
+ +
+ + {% if welcome_message %} + +
+
+ +

{{ welcome_title | default('AI assistant') }}

+

+ {{ welcome_description | default("Welcome! I'm here to help you discover bioinformatics training and resources.") }} +

+ +
+

Try asking me:

+
+ {% for suggestion in welcome_suggestions %} + {% if loop.index == welcome_suggestions.length and welcome_suggestions.length > 2 %} + {% render '@vf-chatbot-action-prompt', { + action_text: suggestion, + action_data: suggestion, + modifier_class: "vf-chatbot-action-prompt--full-width", + data_attribute: "data-vf-js-chatbot-standalone-suggestion=" + suggestion, + data_vf_js_chatbot_action_prompt: true + } %} + {% else %} + {% render '@vf-chatbot-action-prompt', { + action_text: suggestion, + action_data: suggestion, + data_attribute: "data-vf-js-chatbot-standalone-suggestion=" + suggestion, + data_vf_js_chatbot_action_prompt: true + } %} + {% endif %} + {% endfor %} +
+
+
+
+
+
+ AI Assistant +
+
+ {{ welcome_message | default('Hello! How can I help you today?') }} +
+
+ {% endif %} + +
+ + + + + +
+
+ + +
+
+
+
+ + +
+
+
+
+
+
diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss new file mode 100644 index 0000000000..8b33b11082 --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss @@ -0,0 +1,400 @@ +// vf-chatbot-standalone.scss + +.vf-chatbot-standalone { + display: flex; + flex-direction: column; + width: 100%; + height: 100vh; + background: #F5F5F5; + + &__container { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + max-width: 1200px; + margin: 0 auto; + background: #ffffff; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); + + @media (max-width: 1200px) { + max-width: 100%; + } + } + + &__header { + height: 64px; + min-height: 64px; + padding: 0 24px; + background: #ffffff; + border-bottom: 1px solid #E5E5E5; + color: #000000; + display: flex; + align-items: center; + justify-content: space-between; + + @media (max-width: 768px) { + padding: 0 16px; + } + } + + &__header-left { + display: flex; + align-items: center; + gap: 12px; + } + + &__title { + font-size: 18px; + font-weight: 500; + color: #1A1A1A; + display: flex; + align-items: center; + gap: 12px; + margin: 0; + + img { + width: 28px; + height: 28px; + } + } + + &__controls { + display: flex; + gap: 8px; + + button { + background: none; + border: none; + padding: 8px; + cursor: pointer; + color: #666666; + + &:hover { + color: #1A1A1A; + } + } + } + + &__content { + display: flex !important; + flex-direction: column; + flex: 1; + overflow: hidden; + background: #F5F5F5; + justify-content: center; + } + + // Welcome screen styles + &__welcome { + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 24px; + + &-content { + max-width: 65%; + width: 100%; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + } + + &-logo { + margin-bottom: 16px; + + img { + width: 48px; + height: 48px; + } + } + + &-title { + font-size: 24px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 12px 0; + } + + &-description { + font-size: 16px; + line-height: 1.5; + color: #666666; + margin: 0 0 32px 0; + max-width: 450px; + } + + &-suggestions { + margin-top: 16px; + width: 100%; + + &-title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 16px 0; + } + + &-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + + @media (max-width: 480px) { + grid-template-columns: 1fr; + } + } + } + + &-suggestion { + padding: 12px 16px; + background: #FFFFFF; + border: 1px solid #E5E5E5; + border-radius: 8px; + font-size: 14px; + color: #1A1A1A; + cursor: pointer; + transition: background 0.2s ease, border-color 0.2s ease; + text-align: left; + + &:hover { + background: #F0F0F0; + border-color: #CCCCCC; + } + } + + &-input-container { + margin-top: 32px; + width: 100%; + max-width: 500px; + } + + &-input-wrapper { + position: relative; + width: 100%; + display: flex; + align-items: center; + background: #FFFFFF; + border: 1px solid #E5E5E5; + border-radius: 8px; + overflow: hidden; + } + + &-input { + flex: 1; + padding: 16px; + border: none; + font-size: 16px; + line-height: 1.5; + background: transparent; + + &:focus { + outline: none; + } + + &::placeholder { + color: #666666; + } + } + + &-send-button { + background: #007AFF; + color: #ffffff; + border: none; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + + svg { + width: 24px; + height: 24px; + } + } + } + + &__messages { + flex: 1; + overflow-y: auto; + padding: 24px; + background: #F5F5F5; + + @media (max-width: 768px) { + padding: 16px; + } + } + + &__input-area { + padding: 16px 24px; + background: #ffffff; + border-top: 1px solid #E5E5E5; + + @media (max-width: 768px) { + padding: 12px 16px; + } + } + + &__input-wrapper { + position: relative; + max-width: 800px; + margin: 0 auto; + } + + &__input { + width: 100%; + padding: 16px; + padding-right: 56px; // Space for the send button + border: 1px solid #E5E5E5; + border-radius: 8px; + font-size: 16px; + line-height: 1.5; + resize: none; + min-height: 56px; + max-height: 150px; + background: #F5F5F5; + + &:focus { + outline: none; + border-color: #007AFF; + background: #ffffff; + } + + &::placeholder { + color: #666666; + } + } + + &__send-button { + position: absolute; + right: 8px; + top: 50%; + transform: translateY(-50%); + background: #007AFF; + color: #ffffff; + border: none; + border-radius: 8px; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + + svg { + width: 24px; + height: 24px; + } + } + + &__welcome-suggestions { + margin: 24px 0; + + &-title { + font-weight: 500; + margin-bottom: 12px; + } + + &-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + justify-items: center; // Center items horizontally + + // Make the last item span full width if it's the 3rd item + & > *:nth-child(3):last-child { + grid-column: 1 / -1; + justify-self: center; // Center the full-width item + } + + // Ensure each grid cell only takes the width it needs + & > * { + width: auto; + min-width: min-content; + } + } + } +} + +// Reuse message styles from the modal component +.vf-chatbot-message { + margin-bottom: 24px; + max-width: 85%; + + @media (max-width: 768px) { + max-width: 90%; + } + + &--user { + margin-left: auto; + + .vf-chatbot-message__content { + background: #1A1A1A; + color: #ffffff; + border-radius: 16px 16px 4px 16px; + } + } + + &--assistant { + margin-right: auto; + display: flex; + align-items: flex-start; + gap: 12px; + + .vf-chatbot-message__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + } + + .vf-chatbot-message__content { + background: #ffffff; + color: #1A1A1A; + border-radius: 16px 16px 16px 4px; + } + } + + &__content { + padding: 16px; + font-size: 16px; + line-height: 1.5; + } +} + +.vf-chatbot-standalone__title img { + width: 24px; + height: 24px; + margin-right: 8px; + vertical-align: middle; +} + +.vf-chatbot-standalone__welcome-logo img { + width: 64px; + height: 64px; + margin-bottom: 16px; + object-fit: contain; +} + +.vf-chatbot-message--assistant img.vf-chatbot-message__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + background-color: #fff; + object-fit: contain; + padding: 0; + border: 1px solid #eee; +} diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.js b/components/vf-chatbot-welcome/vf-chatbot-welcome.js new file mode 100644 index 0000000000..84856833a7 --- /dev/null +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.js @@ -0,0 +1,59 @@ +// vf-chatbot-welcome.js + +class VFChatbotWelcome { + constructor(element) { + this.el = element; + this.startButton = this.el.querySelector("[data-vf-js-chatbot-start]"); + this.suggestions = this.el.querySelectorAll( + "[data-vf-js-chatbot-suggestion]" + ); + + this.bindEvents(); + } + + bindEvents() { + // Start conversation button + this.startButton?.addEventListener("click", () => { + this.hideWelcomeScreen(); + }); + + // Suggestion buttons + this.suggestions.forEach(suggestion => { + suggestion.addEventListener("click", () => { + const text = suggestion.getAttribute("data-vf-js-chatbot-suggestion"); + this.sendSuggestion(text); + }); + }); + } + + hideWelcomeScreen() { + // Hide welcome screen + this.el.style.display = "none"; + + // Dispatch event to notify that welcome screen is closed + this.el.dispatchEvent(new CustomEvent("vf-chatbot-welcome:closed")); + } + + sendSuggestion(text) { + // Hide welcome screen + this.hideWelcomeScreen(); + + // Dispatch event with the suggestion text + this.el.dispatchEvent( + new CustomEvent("vf-chatbot-welcome:suggestion", { + detail: { text } + }) + ); + } +} + +// Initialize +function initVFChatbotWelcome() { + const welcomeElements = document.querySelectorAll( + "[data-vf-js-chatbot-welcome]" + ); + + welcomeElements.forEach(element => new VFChatbotWelcome(element)); +} + +export { VFChatbotWelcome, initVFChatbotWelcome }; diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.njk b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk new file mode 100644 index 0000000000..4fead6d364 --- /dev/null +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk @@ -0,0 +1,41 @@ +
+
+ AI Assistant +

{{ welcome_title | default('AI Assistant') }}

+
+ +
+

+ {{ welcome_description | default('I can help you find information about our research, services, and more. What would you like to know?') }} +

+ + {% if welcome_features %} +
+

I can help with:

+
    + {% for feature in welcome_features %} +
  • + ✓ + {{ feature }} +
  • + {% endfor %} +
+
+ {% endif %} +
+ +
+

Try asking:

+
+ {% for suggestion in welcome_suggestions %} + + {% endfor %} +
+
+ + +
diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.scss b/components/vf-chatbot-welcome/vf-chatbot-welcome.scss new file mode 100644 index 0000000000..d696e7a14d --- /dev/null +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.scss @@ -0,0 +1,139 @@ +.vf-chatbot-welcome { + display: flex; + flex-direction: column; + height: 100%; + padding: 24px; + background-color: #ffffff; + + &__header { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 24px; + text-align: center; + } + + &__icon { + width: 48px; + height: 48px; + margin-bottom: 16px; + object-fit: contain; + } + + &__title { + font-size: 24px; + font-weight: 600; + color: #1A1A1A; + margin: 0; + } + + &__content { + flex: 1; + margin-bottom: 24px; + } + + &__description { + font-size: 16px; + line-height: 1.5; + color: #666666; + text-align: center; + margin-bottom: 24px; + } + + &__features { + background-color: #F5F5F5; + border-radius: 12px; + padding: 16px; + margin-bottom: 24px; + } + + &__features-title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 12px 0; + } + + &__features-list { + list-style: none; + padding: 0; + margin: 0; + } + + &__feature { + display: flex; + align-items: flex-start; + margin-bottom: 8px; + font-size: 14px; + line-height: 1.5; + color: #1A1A1A; + + &:last-child { + margin-bottom: 0; + } + } + + &__feature-icon { + display: flex; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + margin-right: 8px; + background-color: #007AFF; + color: #ffffff; + border-radius: 50%; + font-size: 12px; + flex-shrink: 0; + } + + &__suggestions { + margin-bottom: 24px; + } + + &__suggestions-title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 12px 0; + } + + &__suggestions-list { + display: flex; + flex-direction: column; + gap: 8px; + } + + &__suggestion { + padding: 12px 16px; + background-color: #F5F5F5; + border: none; + border-radius: 8px; + font-size: 14px; + line-height: 1.5; + color: #1A1A1A; + text-align: left; + cursor: pointer; + transition: background-color 0.2s ease; + + &:hover { + background-color: #E5E5E5; + } + } + + &__start-button { + padding: 12px 24px; + background-color: #007AFF; + color: #ffffff; + border: none; + border-radius: 8px; + font-size: 16px; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s ease; + + &:hover { + background-color: darken(#007AFF, 10%); + } + } +} diff --git a/components/vf-chatbot/assets/ai-assistant-icon.svg b/components/vf-chatbot/assets/ai-assistant-icon.svg new file mode 100644 index 0000000000..a9f68fc555 --- /dev/null +++ b/components/vf-chatbot/assets/ai-assistant-icon.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/vf-chatbot/package.json b/components/vf-chatbot/package.json new file mode 100644 index 0000000000..f3e1cbc3f4 --- /dev/null +++ b/components/vf-chatbot/package.json @@ -0,0 +1,16 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot", + "description": "Visual Framework Chatbot component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot.css", + "sass": "index.scss", + "main": "vf-chatbot.js", + "dependencies": { + "@visual-framework/vf-chatbot-fab": "file:../vf-chatbot-fab", + "@visual-framework/vf-chatbot-modal": "file:../vf-chatbot-modal", + "@visual-framework/vf-sass-config": "^2.7.1" + } +} diff --git a/components/vf-chatbot/vf-chatbot.js b/components/vf-chatbot/vf-chatbot.js new file mode 100644 index 0000000000..f79e35e75c --- /dev/null +++ b/components/vf-chatbot/vf-chatbot.js @@ -0,0 +1,102 @@ +// vf-chatbot +function VFChatbot(element) { + this.el = element; + this.fab = this.el.querySelector("[data-vf-js-chatbot-fab]"); + this.modal = this.el.querySelector("[data-vf-js-chatbot-modal]"); + + this.init(); +} + +VFChatbot.prototype = { + init: function() { + if (!this.fab || !this.modal) return; + + // Handle FAB click + this.fab.addEventListener("click", e => { + e.stopPropagation(); + this.toggleChat(); + }); + + // Handle modal events + this.modal.addEventListener("vf-chatbot-modal:close", () => { + this.fab.classList.remove("vf-chatbot-fab--active"); + }); + + this.modal.addEventListener("vf-chatbot-modal:minimize", () => { + this.fab.classList.remove("vf-chatbot-fab--active"); + }); + + this.modal.addEventListener("vf-chatbot-modal:maximize", () => { + this.fab.classList.add("vf-chatbot-fab--active"); + }); + + // Handle clicks outside modal + document.addEventListener("click", e => { + if ( + !this.modal.classList.contains("vf-chatbot-modal--minimized") && + !this.modal.contains(e.target) && + !this.fab.contains(e.target) + ) { + this.closeChat(); + } + }); + + // Handle escape key + document.addEventListener("keydown", e => { + if ( + e.key === "Escape" && + !this.modal.classList.contains("vf-chatbot-modal--minimized") + ) { + this.closeChat(); + } + }); + }, + + toggleChat: function() { + const isMinimized = this.modal.classList.contains( + "vf-chatbot-modal--minimized" + ); + const isActive = this.modal.classList.contains("vf-chatbot-modal--active"); + + if (isMinimized || !isActive) { + this.openChat(); + } else { + this.minimizeChat(); + } + }, + + openChat: function() { + this.fab.classList.add("vf-chatbot-fab--active"); + this.modal.classList.remove("vf-chatbot-modal--minimized"); + this.modal.classList.add("vf-chatbot-modal--active"); + + // Focus on input if it exists + const input = this.modal.querySelector("[data-vf-js-chatbot-input]"); + if (input) { + setTimeout(() => input.focus(), 300); + } + }, + + minimizeChat: function() { + this.fab.classList.remove("vf-chatbot-fab--active"); + this.modal.classList.add("vf-chatbot-modal--minimized"); + this.modal.classList.remove("vf-chatbot-modal--active"); + }, + + closeChat: function() { + this.fab.classList.remove("vf-chatbot-fab--active"); + this.modal.classList.remove("vf-chatbot-modal--active"); + this.modal.classList.remove("vf-chatbot-modal--minimized"); + }, + + isModalOpen: function() { + return this.modal.classList.contains("vf-chatbot-modal--active"); + } +}; + +function initVFChatbot() { + const elements = document.querySelectorAll("[data-vf-js-chatbot]"); + elements.forEach(element => new VFChatbot(element)); +} + +export { VFChatbot, initVFChatbot }; diff --git a/components/vf-chatbot/vf-chatbot.njk b/components/vf-chatbot/vf-chatbot.njk new file mode 100644 index 0000000000..7c86ef36ca --- /dev/null +++ b/components/vf-chatbot/vf-chatbot.njk @@ -0,0 +1,16 @@ +
+
+ {% render '@vf-chatbot-fab', { + notification_count: notification_count | default(0), + fab_active: fab_active | default(false) + } %} + + {% render '@vf-chatbot-modal', { + title: title | default("Chat with us"), + welcome_message: welcome_message | default("Hello! How can I help you today?"), + input_placeholder: input_placeholder | default("Type your message..."), + show_settings: show_settings | default(true), + ai_icon: "/assets/vf-chatbot/assets/ai-assistant-icon.svg" + } %} +
+
diff --git a/components/vf-chatbot/vf-chatbot.scss b/components/vf-chatbot/vf-chatbot.scss new file mode 100644 index 0000000000..b68e524007 --- /dev/null +++ b/components/vf-chatbot/vf-chatbot.scss @@ -0,0 +1,54 @@ +// vf-chatbot + +@import 'package.variables.scss'; +// @import 'vf-chatbot.variables.scss'; + +.vf-chatbot { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; + + &__container { + position: fixed; + bottom: 20px; + right: 20px; + z-index: 1000; + } + + .vf-chatbot-modal { + position: fixed; + bottom: 90px; // Positioned above the FAB + right: 20px; + width: 360px; + height: 500px; + display: none; + opacity: 0; + transform: translateY(20px); + transition: opacity 0.3s ease, transform 0.3s ease; + + &--active { + display: flex; + flex-direction: column; + opacity: 1; + transform: translateY(0); + } + + @media (max-width: 480px) { + width: calc(100% - 40px); + height: calc(100vh - 120px); + } + } +} + +// Import sub-components +@import '../vf-chatbot-fab/vf-chatbot-fab.scss'; +@import '../vf-chatbot-modal/vf-chatbot-modal.scss'; +@import '../vf-chatbot-prompt/vf-chatbot-prompt.scss'; +// @import '@visual-framework/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss'; +// @import '@visual-framework/vf-chatbot-header/vf-chatbot-header.scss'; +// @import '@visual-framework/vf-chatbot-header-dropdown/vf-chatbot-header-dropdown.scss'; +// @import '@visual-framework/vf-chatbot-dialog/vf-chatbot-dialog.scss'; +// @import '@visual-framework/vf-chatbot-card/vf-chatbot-card.scss'; +// @import '@visual-framework/vf-chatbot-attribution/vf-chatbot-attribution.scss'; +// @import '@visual-framework/vf-chatbot-feedback/vf-chatbot-feedback.scss'; diff --git a/components/vf-componenet-rollup/index.scss b/components/vf-componenet-rollup/index.scss index 7b2f4d2354..1236db66fb 100755 --- a/components/vf-componenet-rollup/index.scss +++ b/components/vf-componenet-rollup/index.scss @@ -144,6 +144,20 @@ button { @import 'vf-mega-menu/vf-mega-menu.scss'; @import 'vf-tree/vf-tree.scss'; +@import 'vf-chatbot/vf-chatbot.scss'; +@import 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss'; +@import 'vf-chatbot-fab/vf-chatbot-fab.scss'; +@import 'vf-chatbot-modal/vf-chatbot-modal.scss'; +@import 'vf-chatbot-prompt/vf-chatbot-prompt.scss'; +@import 'vf-chatbot-standalone/vf-chatbot-standalone.scss'; +@import 'vf-chatbot-welcome/vf-chatbot-welcome.scss'; +// @import 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss'; +// @import 'vf-chatbot-header/vf-chatbot-header.scss'; +// @import 'vf-chatbot-header-dropdown/vf-chatbot-header-dropdown.scss'; +// @import 'vf-chatbot-dialog/vf-chatbot-dialog.scss'; +// @import 'vf-chatbot-card/vf-chatbot-card.scss'; +// @import 'vf-chatbot-attribution/vf-chatbot-attribution.scss'; +// @import 'vf-chatbot-feedback/vf-chatbot-feedback.scss'; /* All Visual Framework Boilerplates */ diff --git a/components/vf-componenet-rollup/scripts copy.js b/components/vf-componenet-rollup/scripts copy.js new file mode 100644 index 0000000000..be17517bbb --- /dev/null +++ b/components/vf-componenet-rollup/scripts copy.js @@ -0,0 +1,115 @@ +/* + * + * scripts.js + * The Visual Framework kitchen sink of JavaScript. + * Import this as a quick way to get *everything*, + * + */ + +// All VF JS +import { vfBanner } from "vf-banner/vf-banner"; +vfBanner(); + +import { vfBannerElixir } from "vf-banner-elixir/vf-banner-elixir"; +vfBannerElixir(); + +// VF Masthead has been deprecated +// https://github.com/visual-framework/vf-core/pull/1406/ +// import { vfMastheadSetStyle } from "vf-masthead/vf-masthead"; +// vfMastheadSetStyle(); + +import { vfGaIndicateLoaded } from "vf-analytics-google/vf-analytics-google"; +let vfGaTrackOptions = { + vfGaTrackPageLoad: true, + // vfGa4MeasurementId: "YourGa4TrackingId" // only required if tracking a custom page-level dimension +}; +vfGaIndicateLoaded(vfGaTrackOptions); + +import { vfTabs } from "vf-tabs/vf-tabs"; +vfTabs(); + +import { vfTree } from "vf-tree/vf-tree"; +vfTree(); + +// import { vfFormFloatLabels } from 'form /assets/vf-form__float-labels.js'; +// vfFormFloatLabels(); + +import { vfSearchClientSide } from "vf-search-client-side/vf-search-client-side"; +// No default invokation + +import { vfShowMore } from "vf-show-more/vf-show-more"; +vfShowMore(); + +import { vfLocationNearest } from "vf-location-nearest/vf-location-nearest"; +// Not invoked by default + +// All EMBL JS +import { emblContentHubLoaderHtmlImports } from "embl-content-hub-loader/embl-content-hub-loader__html-imports"; +import { emblContentHubFetch } from "embl-content-hub-loader/embl-content-hub-loader__fetch"; +import { emblContentHub } from "embl-content-hub-loader/embl-content-hub-loader"; +import { emblConditionalEdit } from "embl-conditional-edit/embl-conditional-edit"; +emblContentHub(); + +import { emblBreadcrumbs } from "embl-breadcrumbs-lookup/embl-breadcrumbs-lookup"; +emblBreadcrumbs(); + +import { vfBackToTop } from "vf-back-to-top/vf-back-to-top.js"; +vfBackToTop(); + +import { vfDropdown } from "vf-dropdown/vf-dropdown.js"; +vfDropdown(); + +import { vfNavigationOnThisPage } from "vf-navigation/vf-navigation.js"; +vfNavigationOnThisPage(); + +import { emblContentMetaProperties_Read } from "embl-content-meta-properties/embl-content-meta-properties"; + +import { emblNotifications } from "embl-notifications/embl-notifications"; +// emblNotifications(); + +import { vfMegaMenu } from 'vf-mega-menu/vf-mega-menu'; +vfMegaMenu(); + +import { vfTable } from 'vf-table/vf-table'; +vfTable(); + +// No default invokation + +// Import chatbot components +import { initVFChatbot } from 'vf-chatbot/vf-chatbot.js'; +import { initVFChatbotModal } from 'vf-chatbot-modal/vf-chatbot-modal.js'; +import { initVFChatbotStandalone } from 'vf-chatbot-standalone/vf-chatbot-standalone.js'; +import { initVFChatbotActionPrompt } from 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; +import { initVFChatbotFab } from 'vf-chatbot-fab/vf-chatbot-fab.js'; +import { initVFChatbotWelcome } from 'vf-chatbot-welcome/vf-chatbot-welcome.js'; +import { initVFChatbotPrompt } from 'vf-chatbot-prompt/vf-chatbot-prompt.js'; + +// Initialize all chatbot components when DOM is loaded +document.addEventListener('DOMContentLoaded', function() { + console.log('Initializing chatbot components...'); + + // Initialize all chatbot components + initVFChatbot(); + initVFChatbotModal(); + initVFChatbotActionPrompt(); + initVFChatbotFab(); + initVFChatbotWelcome(); + initVFChatbotPrompt(); + + // Handle standalone chatbot initialization with error handling + try { + if (typeof window.initVFChatbotStandalone === 'function') { + window.initVFChatbotStandalone(); + } else if (typeof initVFChatbotStandalone === 'function') { + initVFChatbotStandalone(); + } + } catch (error) { + console.warn('Could not initialize standalone chatbot:', error.message); + } +}); + +// Commented out components +// import { initVFChatbotHeader } from 'vf-chatbot-header/vf-chatbot-header.js'; +// import { initVFChatbotHeaderDropdown } from 'vf-chatbot-header-dropdown/vf-chatbot-header-dropdown.js'; +// import { initVFChatbotDialog } from 'vf-chatbot-dialog/vf-chatbot-dialog.js'; +// import { initVFChatbotCard } from 'vf-chatbot-card/vf-chatbot-card.js'; diff --git a/components/vf-componenet-rollup/scripts.js b/components/vf-componenet-rollup/scripts.js index 7629e021ed..3991ed8ab0 100644 --- a/components/vf-componenet-rollup/scripts.js +++ b/components/vf-componenet-rollup/scripts.js @@ -73,4 +73,30 @@ vfMegaMenu(); import { vfTable } from 'vf-table/vf-table'; vfTable(); +import { initVFChatbot } from 'vf-chatbot/vf-chatbot.js'; +import { initVFChatbotModal } from 'vf-chatbot-modal/vf-chatbot-modal.js'; +import { initVFChatbotStandalone } from 'vf-chatbot-standalone/vf-chatbot-standalone.js'; +import { initVFChatbotActionPrompt } from 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; +import { initVFChatbotFab } from 'vf-chatbot-fab/vf-chatbot-fab.js'; +import { initVFChatbotWelcome } from 'vf-chatbot-welcome/vf-chatbot-welcome.js'; +import { initVFChatbotPrompt } from 'vf-chatbot-prompt/vf-chatbot-prompt.js'; + +// Initialize all chatbot components when DOM is loaded +document.addEventListener("DOMContentLoaded", () => { + const chatbotFab = document.querySelector(".vf-chatbot-fab"); + if (chatbotFab) { + chatbotFab.addEventListener("click", () => { + console.log("vf-chatbot-fab clicked"); + initVFChatbot(); + initVFChatbotModal(); + initVFChatbotActionPrompt(); + initVFChatbotFab(); + initVFChatbotWelcome(); + initVFChatbotPrompt(); + }); + } else { + console.error("vf-chatbot-fab button not found in the DOM."); + } +}); + // No default invokation diff --git a/tools/vf-component-library/src/site/_includes/layouts/base.njk b/tools/vf-component-library/src/site/_includes/layouts/base.njk index 37a41700f6..9c69b65fd5 100644 --- a/tools/vf-component-library/src/site/_includes/layouts/base.njk +++ b/tools/vf-component-library/src/site/_includes/layouts/base.njk @@ -359,5 +359,12 @@ Propose a change or discuss it.

{% include "footer.njk" %} + {% render '@vf-chatbot', { + title: "AI Assistant", + welcome_message: "Welcome! How can I help you today?", + notification_count: 0, + fab_active: false, + show_settings: true + } %} diff --git a/tools/vf-component-library/src/site/chatbot/index.njk b/tools/vf-component-library/src/site/chatbot/index.njk new file mode 100644 index 0000000000..4071280c9a --- /dev/null +++ b/tools/vf-component-library/src/site/chatbot/index.njk @@ -0,0 +1,58 @@ + + + + + + AI Assistant | Chatbot + + + + + + + {% render '@vf-chatbot-standalone', { + title: "AI Assistant", + welcome_title: "AI assistant", + welcome_description: "Welcome! I'm here to help you discover bioinformatics training and resources.", + welcome_message: "Hello! How can I help you today?", + input_placeholder: "Ask me about Bioinformatics trainings...", + show_suggestions: true, + show_close_button: true, + ai_icon: "../../assets/vf-chatbot/assets/ai-assistant-icon.svg", + welcome_logo: "../../assets/vf-chatbot/assets/ai-assistant-icon.svg", + welcome_suggestions: [ + 'Find workshops near research institutions', + 'Recommend bioinformatics resources', + 'What prerequisites do I need for advanced advanced courses?' + ] + } %} + + +
+ + diff --git a/tools/vf-component-library/yarn.lock b/tools/vf-component-library/yarn.lock index 368e2e8677..92ff9e8ca6 100644 --- a/tools/vf-component-library/yarn.lock +++ b/tools/vf-component-library/yarn.lock @@ -102,89 +102,89 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.26.2": - version "7.26.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" - integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.26.2", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== dependencies: - "@babel/helper-validator-identifier" "^7.25.9" + "@babel/helper-validator-identifier" "^7.27.1" js-tokens "^4.0.0" - picocolors "^1.0.0" + picocolors "^1.1.1" -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" - integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.8", "@babel/compat-data@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.2.tgz#4183f9e642fd84e74e3eea7ffa93a412e3b102c9" + integrity sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ== "@babel/core@^7.14.6", "@babel/core@^7.16.0": - version "7.26.10" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.10.tgz#5c876f83c8c4dcb233ee4b670c0606f2ac3000f9" - integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.1.tgz#89de51e86bd12246003e3524704c49541b16c3e6" + integrity sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.10" - "@babel/helper-compilation-targets" "^7.26.5" - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.10" - "@babel/parser" "^7.26.10" - "@babel/template" "^7.26.9" - "@babel/traverse" "^7.26.10" - "@babel/types" "^7.26.10" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.27.1" + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helpers" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/template" "^7.27.1" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.26.10", "@babel/generator@^7.27.0": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.0.tgz#764382b5392e5b9aff93cadb190d0745866cbc2c" - integrity sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw== +"@babel/generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.1.tgz#862d4fad858f7208edd487c28b58144036b76230" + integrity sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w== dependencies: - "@babel/parser" "^7.27.0" - "@babel/types" "^7.27.0" + "@babel/parser" "^7.27.1" + "@babel/types" "^7.27.1" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" -"@babel/helper-annotate-as-pure@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" - integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== +"@babel/helper-annotate-as-pure@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz#4345d81a9a46a6486e24d069469f13e60445c05d" + integrity sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow== dependencies: - "@babel/types" "^7.25.9" + "@babel/types" "^7.27.1" -"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz#de0c753b1cd1d9ab55d473c5a5cf7170f0a81880" - integrity sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA== +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.26.5", "@babel/helper-compilation-targets@^7.27.1", "@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== dependencies: - "@babel/compat-data" "^7.26.8" - "@babel/helper-validator-option" "^7.25.9" + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.25.9": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz#518fad6a307c6a96f44af14912b2c20abe9bfc30" - integrity sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/helper-replace-supers" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/traverse" "^7.27.0" +"@babel/helper-create-class-features-plugin@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz#5bee4262a6ea5ddc852d0806199eb17ca3de9281" + integrity sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/traverse" "^7.27.1" semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.25.9": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz#0e41f7d38c2ebe06ebd9cf0e02fb26019c77cd95" - integrity sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ== +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz#05b0882d97ba1d4d03519e4bce615d70afa18c53" + integrity sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-annotate-as-pure" "^7.27.1" regexpu-core "^6.2.0" semver "^6.3.1" @@ -199,146 +199,146 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" -"@babel/helper-member-expression-to-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" - integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ== +"@babel/helper-member-expression-to-functions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz#ea1211276be93e798ce19037da6f06fbb994fa44" + integrity sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA== dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-module-imports@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" - integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== +"@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== +"@babel/helper-module-transforms@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz#e1663b8b71d2de948da5c4fb2a20ca4f3ec27a6f" + integrity sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g== dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-optimise-call-expression@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" - integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ== +"@babel/helper-optimise-call-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200" + integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw== dependencies: - "@babel/types" "^7.25.9" + "@babel/types" "^7.27.1" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.3": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" - integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.3": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== -"@babel/helper-remap-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" - integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== +"@babel/helper-remap-async-to-generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz#4601d5c7ce2eb2aea58328d43725523fcd362ce6" + integrity sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA== dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-wrap-function" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-wrap-function" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-replace-supers@^7.25.9", "@babel/helper-replace-supers@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d" - integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg== +"@babel/helper-replace-supers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz#b1ed2d634ce3bdb730e4b52de30f8cccfd692bc0" + integrity sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA== dependencies: - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/traverse" "^7.26.5" + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-skip-transparent-expression-wrappers@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" - integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA== +"@babel/helper-skip-transparent-expression-wrappers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56" + integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg== dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/helper-validator-identifier@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" - integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== -"@babel/helper-validator-option@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" - integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== +"@babel/helper-validator-option@^7.25.9", "@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== -"@babel/helper-wrap-function@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" - integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g== +"@babel/helper-wrap-function@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz#b88285009c31427af318d4fe37651cd62a142409" + integrity sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ== dependencies: - "@babel/template" "^7.25.9" - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/template" "^7.27.1" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helpers@^7.26.10": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.0.tgz#53d156098defa8243eab0f32fa17589075a1b808" - integrity sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg== +"@babel/helpers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.1.tgz#ffc27013038607cdba3288e692c3611c06a18aa4" + integrity sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ== dependencies: - "@babel/template" "^7.27.0" - "@babel/types" "^7.27.0" + "@babel/template" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/parser@^7.26.10", "@babel/parser@^7.27.0", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.0.tgz#3d7d6ee268e41d2600091cbd4e145ffee85a44ec" - integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg== +"@babel/parser@^7.27.1", "@babel/parser@^7.27.2", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127" + integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw== dependencies: - "@babel/types" "^7.27.0" + "@babel/types" "^7.27.1" "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" - integrity sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz#61dd8a8e61f7eb568268d1b5f129da3eee364bf9" + integrity sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz#af9e4fb63ccb8abcb92375b2fcfe36b60c774d30" - integrity sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz#43f70a6d7efd52370eefbdf55ae03d91b293856d" + integrity sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz#e8dc26fcd616e6c5bf2bd0d5a2c151d4f92a9137" - integrity sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz#beb623bd573b8b6f3047bd04c32506adc3e58a72" + integrity sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz#807a667f9158acac6f6164b4beb85ad9ebc9e1d1" - integrity sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz#e134a5479eb2ba9c02714e8c1ebf1ec9076124fd" + integrity sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/plugin-transform-optional-chaining" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/plugin-transform-optional-chaining" "^7.27.1" "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz#de7093f1e7deaf68eadd7cc6b07f2ab82543269e" - integrity sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz#bb1c25af34d75115ce229a1de7fa44bf8f955670" + integrity sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-proposal-export-namespace-from@^7.14.5": version "7.18.9" @@ -361,18 +361,18 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-import-assertions@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz#620412405058efa56e4a564903b79355020f445f" - integrity sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz#88894aefd2b03b5ee6ad1562a7c8e1587496aecd" + integrity sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-syntax-import-attributes@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz#3b1412847699eea739b4f2602c74ce36f6b0b0f7" - integrity sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" + integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" @@ -383,391 +383,391 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-arrow-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" - integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz#6e2061067ba3ab0266d834a9f94811196f2aba9a" + integrity sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-async-generator-functions@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz#5e3991135e3b9c6eaaf5eff56d1ae5a11df45ff8" - integrity sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz#ca433df983d68e1375398e7ca71bf2a4f6fd89d7" + integrity sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-remap-async-to-generator" "^7.25.9" - "@babel/traverse" "^7.26.8" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-remap-async-to-generator" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-transform-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71" - integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz#9a93893b9379b39466c74474f55af03de78c66e7" + integrity sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA== dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-remap-async-to-generator" "^7.25.9" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-remap-async-to-generator" "^7.27.1" "@babel/plugin-transform-block-scoped-functions@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz#3dc4405d31ad1cbe45293aa57205a6e3b009d53e" - integrity sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz#558a9d6e24cf72802dd3b62a4b51e0d62c0f57f9" + integrity sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-block-scoping@^7.25.9": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz#acc2c0d98a7439bbde4244588ddbd4904701d47f" - integrity sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz#bc0dbe8ac6de5602981ba58ef68c6df8ef9bfbb3" + integrity sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-class-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz#a8ce84fedb9ad512549984101fa84080a9f5f51f" - integrity sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz#dd40a6a370dfd49d32362ae206ddaf2bb082a925" + integrity sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-class-static-block@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz#6c8da219f4eb15cae9834ec4348ff8e9e09664a0" - integrity sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz#7e920d5625b25bbccd3061aefbcc05805ed56ce4" + integrity sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-classes@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" - integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" - "@babel/traverse" "^7.25.9" + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz#03bb04bea2c7b2f711f0db7304a8da46a85cced4" + integrity sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/traverse" "^7.27.1" globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" - integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz#81662e78bf5e734a97982c2b7f0a793288ef3caa" + integrity sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/template" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/template" "^7.27.1" -"@babel/plugin-transform-destructuring@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" - integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== +"@babel/plugin-transform-destructuring@^7.25.9", "@babel/plugin-transform-destructuring@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz#d5916ef7089cb254df0418ae524533c1b72ba656" + integrity sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-dotall-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz#bad7945dd07734ca52fe3ad4e872b40ed09bb09a" - integrity sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz#aa6821de864c528b1fecf286f0a174e38e826f4d" + integrity sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-duplicate-keys@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz#8850ddf57dce2aebb4394bb434a7598031059e6d" - integrity sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz#f1fbf628ece18e12e7b32b175940e68358f546d1" + integrity sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz#6f7259b4de127721a08f1e5165b852fcaa696d31" - integrity sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz#5043854ca620a94149372e69030ff8cb6a9eb0ec" + integrity sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-dynamic-import@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz#23e917de63ed23c6600c5dd06d94669dce79f7b8" - integrity sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz#4c78f35552ac0e06aa1f6e3c573d67695e8af5a4" + integrity sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-exponentiation-operator@^7.26.3": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz#e29f01b6de302c7c2c794277a48f04a9ca7f03bc" - integrity sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz#fc497b12d8277e559747f5a3ed868dd8064f83e1" + integrity sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-export-namespace-from@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz#90745fe55053394f554e40584cda81f2c8a402a2" - integrity sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz#71ca69d3471edd6daa711cf4dfc3400415df9c23" + integrity sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-for-of@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz#27231f79d5170ef33b5111f07fe5cafeb2c96a56" - integrity sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz#bc24f7080e9ff721b63a70ac7b2564ca15b6c40a" + integrity sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" "@babel/plugin-transform-function-name@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" - integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz#4d0bf307720e4dce6d7c30fcb1fd6ca77bdeb3a7" + integrity sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ== dependencies: - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-transform-json-strings@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz#c86db407cb827cded902a90c707d2781aaa89660" - integrity sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz#a2e0ce6ef256376bd527f290da023983527a4f4c" + integrity sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" - integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz#baaefa4d10a1d4206f9dcdda50d7d5827bb70b24" + integrity sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-logical-assignment-operators@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz#b19441a8c39a2fda0902900b306ea05ae1055db7" - integrity sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz#890cb20e0270e0e5bebe3f025b434841c32d5baa" + integrity sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-member-expression-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz#63dff19763ea64a31f5e6c20957e6a25e41ed5de" - integrity sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz#37b88ba594d852418e99536f5612f795f23aeaf9" + integrity sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-modules-amd@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz#49ba478f2295101544abd794486cd3088dddb6c5" - integrity sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz#a4145f9d87c2291fe2d05f994b65dba4e3e7196f" + integrity sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA== dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-modules-commonjs@^7.14.5", "@babel/plugin-transform-modules-commonjs@^7.26.3": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb" - integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz#8e44ed37c2787ecc23bdc367f49977476614e832" + integrity sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw== dependencies: - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-modules-systemjs@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz#8bd1b43836269e3d33307151a114bcf3ba6793f8" - integrity sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz#00e05b61863070d0f3292a00126c16c0e024c4ed" + integrity sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA== dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-transform-modules-umd@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz#6710079cdd7c694db36529a1e8411e49fcbf14c9" - integrity sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz#63f2cf4f6dc15debc12f694e44714863d34cd334" + integrity sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w== dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-named-capturing-groups-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" - integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz#f32b8f7818d8fc0cc46ee20a8ef75f071af976e1" + integrity sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-new-target@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz#42e61711294b105c248336dcb04b77054ea8becd" - integrity sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz#259c43939728cad1706ac17351b7e6a7bea1abeb" + integrity sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-nullish-coalescing-operator@^7.26.6": - version "7.26.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz#fbf6b3c92cb509e7b319ee46e3da89c5bedd31fe" - integrity sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz#4f9d3153bf6782d73dd42785a9d22d03197bc91d" + integrity sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-numeric-separator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz#bfed75866261a8b643468b0ccfd275f2033214a1" - integrity sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz#614e0b15cc800e5997dadd9bd6ea524ed6c819c6" + integrity sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-object-rest-spread@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz#0203725025074164808bcf1a2cfa90c652c99f18" - integrity sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg== + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz#67f9ab822347aa2bcee91e8996763da79bdea973" + integrity sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g== dependencies: - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/plugin-transform-parameters" "^7.25.9" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.27.1" + "@babel/plugin-transform-parameters" "^7.27.1" "@babel/plugin-transform-object-super@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz#385d5de135162933beb4a3d227a2b7e52bb4cf03" - integrity sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz#1c932cd27bf3874c43a5cac4f43ebf970c9871b5" + integrity sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" "@babel/plugin-transform-optional-catch-binding@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz#10e70d96d52bb1f10c5caaac59ac545ea2ba7ff3" - integrity sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz#84c7341ebde35ccd36b137e9e45866825072a30c" + integrity sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-optional-chaining@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz#e142eb899d26ef715435f201ab6e139541eee7dd" - integrity sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A== +"@babel/plugin-transform-optional-chaining@^7.25.9", "@babel/plugin-transform-optional-chaining@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz#874ce3c4f06b7780592e946026eb76a32830454f" + integrity sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" -"@babel/plugin-transform-parameters@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" - integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== +"@babel/plugin-transform-parameters@^7.25.9", "@babel/plugin-transform-parameters@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz#80334b54b9b1ac5244155a0c8304a187a618d5a7" + integrity sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-private-methods@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" - integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz#fdacbab1c5ed81ec70dfdbb8b213d65da148b6af" + integrity sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-private-property-in-object@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" - integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz#4dbbef283b5b2f01a21e81e299f76e35f900fb11" + integrity sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-property-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz#d72d588bd88b0dec8b62e36f6fda91cedfe28e3f" - integrity sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz#07eafd618800591e88073a0af1b940d9a42c6424" + integrity sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-regenerator@^7.25.9": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz#822feebef43d6a59a81f696b2512df5b1682db31" - integrity sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz#0a471df9213416e44cd66bf67176b66f65768401" + integrity sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - regenerator-transform "^0.15.2" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-regexp-modifiers@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz#2f5837a5b5cd3842a919d8147e9903cc7455b850" - integrity sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz#df9ba5577c974e3f1449888b70b76169998a6d09" + integrity sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-reserved-words@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz#0398aed2f1f10ba3f78a93db219b27ef417fb9ce" - integrity sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz#40fba4878ccbd1c56605a4479a3a891ac0274bb4" + integrity sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-shorthand-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" - integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz#532abdacdec87bfee1e0ef8e2fcdee543fe32b90" + integrity sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-spread@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" - integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz#1a264d5fc12750918f50e3fe3e24e437178abb08" + integrity sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" "@babel/plugin-transform-sticky-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" - integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz#18984935d9d2296843a491d78a014939f7dcd280" + integrity sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-template-literals@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz#966b15d153a991172a540a69ad5e1845ced990b5" - integrity sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz#1a0eb35d8bb3e6efc06c9fd40eb0bcef548328b8" + integrity sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-typeof-symbol@^7.26.7": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz#044a0890f3ca694207c7826d0c7a65e5ac008aae" - integrity sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz#70e966bb492e03509cf37eafa6dcc3051f844369" + integrity sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-unicode-escapes@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz#a75ef3947ce15363fccaa38e2dd9bc70b2788b82" - integrity sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz#3e3143f8438aef842de28816ece58780190cf806" + integrity sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-unicode-property-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz#a901e96f2c1d071b0d1bb5dc0d3c880ce8f53dd3" - integrity sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz#bdfe2d3170c78c5691a3c3be934c8c0087525956" + integrity sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-unicode-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" - integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz#25948f5c395db15f609028e370667ed8bae9af97" + integrity sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-unicode-sets-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz#65114c17b4ffc20fa5b163c63c70c0d25621fabe" - integrity sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz#6ab706d10f801b5c72da8bb2548561fa04193cd1" + integrity sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/preset-env@7.26.9": version "7.26.9" @@ -853,42 +853,35 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime@^7.8.4": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.0.tgz#fbee7cf97c709518ecc1f590984481d5460d4762" - integrity sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.27.0": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4" - integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.27.0" - "@babel/types" "^7.27.0" - -"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.27.0": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.0.tgz#11d7e644779e166c0442f9a07274d02cd91d4a70" - integrity sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.27.0" - "@babel/parser" "^7.27.0" - "@babel/template" "^7.27.0" - "@babel/types" "^7.27.0" +"@babel/template@^7.27.1": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291" + integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/template" "^7.27.1" + "@babel/types" "^7.27.1" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.27.0", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.6": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559" - integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg== +"@babel/types@^7.27.1", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.6": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560" + integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q== dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" "@colors/colors@1.5.0": version "1.5.0" @@ -921,9 +914,9 @@ integrity sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg== "@eslint-community/eslint-utils@^4.2.0": - version "4.5.1" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz#b0fc7e06d0c94f801537fd4237edc2706d3b8e4c" - integrity sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w== + version "4.7.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a" + integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw== dependencies: eslint-visitor-keys "^3.4.3" @@ -932,24 +925,24 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint/config-array@^0.19.2": - version "0.19.2" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" - integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== +"@eslint/config-array@^0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.20.0.tgz#7a1232e82376712d3340012a2f561a2764d1988f" + integrity sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ== dependencies: "@eslint/object-schema" "^2.1.6" debug "^4.3.1" minimatch "^3.1.2" -"@eslint/config-helpers@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.0.tgz#12dc8d65c31c4b6c3ebf0758db6601eb7692ce59" - integrity sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ== +"@eslint/config-helpers@^0.2.1": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.2.tgz#3779f76b894de3a8ec4763b79660e6d54d5b1010" + integrity sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg== -"@eslint/core@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.12.0.tgz#5f960c3d57728be9f6c65bd84aa6aa613078798e" - integrity sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg== +"@eslint/core@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.13.0.tgz#bf02f209846d3bf996f9e8009db62df2739b458c" + integrity sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw== dependencies: "@types/json-schema" "^7.0.15" @@ -968,22 +961,22 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.23.0": - version "9.23.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.23.0.tgz#c09ded4f3dc63b40b933bcaeb853fceddb64da30" - integrity sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw== +"@eslint/js@9.26.0": + version "9.26.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.26.0.tgz#1e13126b67a3db15111d2dcc61f69a2acff70bd5" + integrity sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ== "@eslint/object-schema@^2.1.6": version "2.1.6" resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== -"@eslint/plugin-kit@^0.2.7": - version "0.2.7" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz#9901d52c136fb8f375906a73dcc382646c3b6a27" - integrity sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g== +"@eslint/plugin-kit@^0.2.8": + version "0.2.8" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz#47488d8f8171b5d4613e833313f3ce708e3525f8" + integrity sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA== dependencies: - "@eslint/core" "^0.12.0" + "@eslint/core" "^0.13.0" levn "^0.4.1" "@frctl/core@^0.3.5": @@ -1123,9 +1116,9 @@ integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== "@humanwhocodes/retry@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.2.tgz#1860473de7dfa1546767448f333db80cb0ff2161" - integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@iarna/toml@^2.2.5": version "2.2.5" @@ -1195,6 +1188,22 @@ resolved "https://registry.yarnpkg.com/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz#8ace5259254426ccef57f3175bc64ed7095ed919" integrity sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw== +"@modelcontextprotocol/sdk@^1.8.0": + version "1.11.3" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.11.3.tgz#0bcc7b2d74ac1f749d1a7632ec2d674fd7066543" + integrity sha512-rmOWVRUbUJD7iSvJugjUbFZshTAuJ48MXoZ80Osx1GM0K/H1w7rSEvmw8m6vdWxNASgtaHIhAgre4H/E9GJiYQ== + dependencies: + content-type "^1.0.5" + cors "^2.8.5" + cross-spawn "^7.0.5" + eventsource "^3.0.2" + express "^5.0.1" + express-rate-limit "^7.5.0" + pkce-challenge "^5.0.0" + raw-body "^3.0.0" + zod "^3.23.8" + zod-to-json-schema "^3.24.1" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1222,33 +1231,33 @@ integrity sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw== "@octokit/core@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-6.1.4.tgz#f5ccf911cc95b1ce9daf6de425d1664392f867db" - integrity sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg== + version "6.1.5" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-6.1.5.tgz#c2842aae87c2c2130b7dd33e8caa0f642dde2c67" + integrity sha512-vvmsN0r7rguA+FySiCsbaTTobSftpIDIpPW81trAmsv9TGxg3YCujAxRYp/Uy8xmDgYCzzgulG62H7KYUFmeIg== dependencies: "@octokit/auth-token" "^5.0.0" - "@octokit/graphql" "^8.1.2" - "@octokit/request" "^9.2.1" - "@octokit/request-error" "^6.1.7" - "@octokit/types" "^13.6.2" + "@octokit/graphql" "^8.2.2" + "@octokit/request" "^9.2.3" + "@octokit/request-error" "^6.1.8" + "@octokit/types" "^14.0.0" before-after-hook "^3.0.2" universal-user-agent "^7.0.0" -"@octokit/endpoint@^10.1.3": - version "10.1.3" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-10.1.3.tgz#bfe8ff2ec213eb4216065e77654bfbba0fc6d4de" - integrity sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA== +"@octokit/endpoint@^10.1.4": + version "10.1.4" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-10.1.4.tgz#8783be38a32b95af8bcb6523af20ab4eed7a2adb" + integrity sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA== dependencies: - "@octokit/types" "^13.6.2" + "@octokit/types" "^14.0.0" universal-user-agent "^7.0.2" -"@octokit/graphql@^8.1.2": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-8.2.1.tgz#0cb83600e6b4009805acc1c56ae8e07e6c991b78" - integrity sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw== +"@octokit/graphql@^8.2.2": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-8.2.2.tgz#3db48c4ffdf07f99600cee513baf45e73eced4d1" + integrity sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA== dependencies: - "@octokit/request" "^9.2.2" - "@octokit/types" "^13.8.0" + "@octokit/request" "^9.2.3" + "@octokit/types" "^14.0.0" universal-user-agent "^7.0.0" "@octokit/openapi-types@^24.2.0": @@ -1256,6 +1265,11 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-24.2.0.tgz#3d55c32eac0d38da1a7083a9c3b0cca77924f7d3" integrity sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg== +"@octokit/openapi-types@^25.0.0": + version "25.0.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-25.0.0.tgz#adeead36992abf966e89dcd53518d8b0dc910e0d" + integrity sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw== + "@octokit/plugin-paginate-rest@^11.4.2": version "11.6.0" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz#e5e9ff3530e867c3837fdbff94ce15a2468a1f37" @@ -1275,21 +1289,21 @@ dependencies: "@octokit/types" "^13.10.0" -"@octokit/request-error@^6.1.7": - version "6.1.7" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.7.tgz#44fc598f5cdf4593e0e58b5155fe2e77230ff6da" - integrity sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g== +"@octokit/request-error@^6.1.8": + version "6.1.8" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.8.tgz#3c7ce1ca6721eabd43dbddc76b44860de1fdea75" + integrity sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ== dependencies: - "@octokit/types" "^13.6.2" + "@octokit/types" "^14.0.0" -"@octokit/request@^9.2.1", "@octokit/request@^9.2.2": - version "9.2.2" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-9.2.2.tgz#754452ec4692d7fdc32438a14e028eba0e6b2c09" - integrity sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg== +"@octokit/request@^9.2.3": + version "9.2.3" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-9.2.3.tgz#00d023ad690903d952e4dd31e3f5804ef98fcd24" + integrity sha512-Ma+pZU8PXLOEYzsWf0cn/gY+ME57Wq8f49WTXA8FMHp2Ps9djKw//xYJ1je8Hm0pR2lU9FUGeJRWOtxq6olt4w== dependencies: - "@octokit/endpoint" "^10.1.3" - "@octokit/request-error" "^6.1.7" - "@octokit/types" "^13.6.2" + "@octokit/endpoint" "^10.1.4" + "@octokit/request-error" "^6.1.8" + "@octokit/types" "^14.0.0" fast-content-type-parse "^2.0.0" universal-user-agent "^7.0.2" @@ -1303,13 +1317,20 @@ "@octokit/plugin-request-log" "^5.3.1" "@octokit/plugin-rest-endpoint-methods" "^13.3.0" -"@octokit/types@^13.10.0", "@octokit/types@^13.6.2", "@octokit/types@^13.8.0": +"@octokit/types@^13.10.0": version "13.10.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.10.0.tgz#3e7c6b19c0236c270656e4ea666148c2b51fd1a3" integrity sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA== dependencies: "@octokit/openapi-types" "^24.2.0" +"@octokit/types@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-14.0.0.tgz#bbd1d31e2269940789ef143b1c37918aae09adc4" + integrity sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA== + dependencies: + "@octokit/openapi-types" "^25.0.0" + "@one-ini/wasm@0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@one-ini/wasm/-/wasm-0.1.1.tgz#6013659736c9dbfccc96e8a9c2b3de317df39323" @@ -1430,105 +1451,105 @@ "@pnpm/network.ca-file" "^1.0.1" config-chain "^1.1.11" -"@rollup/rollup-android-arm-eabi@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.38.0.tgz#6ba67cc0f3a2d7e3a208256a349c2cb2798f57be" - integrity sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg== - -"@rollup/rollup-android-arm64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.38.0.tgz#c8806f88fd6727d3cf144c4ffb00f40d451b6618" - integrity sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ== - -"@rollup/rollup-darwin-arm64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.38.0.tgz#c4654989b97bba0de7205cf5b3342984d4451d5a" - integrity sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg== - -"@rollup/rollup-darwin-x64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.38.0.tgz#77ee357aeeefe3fe8bee33df18c240e391450476" - integrity sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg== - -"@rollup/rollup-freebsd-arm64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.38.0.tgz#ac8028c99221d1cef22788adda465077d5926911" - integrity sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA== - -"@rollup/rollup-freebsd-x64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.38.0.tgz#64376ff0e1541cd8677e74898782ec4935277e02" - integrity sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg== - -"@rollup/rollup-linux-arm-gnueabihf@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.38.0.tgz#7de1584c09adcac08f90d1e500c679c428b6eb36" - integrity sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg== - -"@rollup/rollup-linux-arm-musleabihf@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.38.0.tgz#1d5d0f28d93cdc37d60c381c6bbe649bed4960d5" - integrity sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg== - -"@rollup/rollup-linux-arm64-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.38.0.tgz#a97f73a43a374e44bef4a9ed84899c26454831ea" - integrity sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA== - -"@rollup/rollup-linux-arm64-musl@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.38.0.tgz#00e3b646a7976752052ebc72d005808b9e7f2801" - integrity sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ== - -"@rollup/rollup-linux-loongarch64-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.38.0.tgz#0d6dcaa3671cf987faace4b34ab7320ee3c18b65" - integrity sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg== - -"@rollup/rollup-linux-powerpc64le-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.38.0.tgz#54c2d7a4d86767001475f0157c408fd042f7fd8f" - integrity sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw== - -"@rollup/rollup-linux-riscv64-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.38.0.tgz#8cb565417b29851a0c549614898bdab689f23187" - integrity sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg== - -"@rollup/rollup-linux-riscv64-musl@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.38.0.tgz#8bc00b75fd07b15c35a54b41a5f052c01dbf925b" - integrity sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA== - -"@rollup/rollup-linux-s390x-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.38.0.tgz#1fe4a88b97e36d64dbf1f01cfa7842d269a094cf" - integrity sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q== - -"@rollup/rollup-linux-x64-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.38.0.tgz#11c32c463e68a86e279cda090a9405a7558f9406" - integrity sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w== - -"@rollup/rollup-linux-x64-musl@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.38.0.tgz#520c2a8547672ec6c56a6833f6d38e9380d63dc7" - integrity sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g== - -"@rollup/rollup-win32-arm64-msvc@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.38.0.tgz#d27ab565009357014c9f2d6393ee58bd63a63cb8" - integrity sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg== - -"@rollup/rollup-win32-ia32-msvc@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.38.0.tgz#6c02847c60fcc7a6d74e00a60f350d079558d84d" - integrity sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA== - -"@rollup/rollup-win32-x64-msvc@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.38.0.tgz#38197da22c1af7b6b5d1cc7541757379193b8e83" - integrity sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw== +"@rollup/rollup-android-arm-eabi@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz#c228d00a41f0dbd6fb8b7ea819bbfbf1c1157a10" + integrity sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg== + +"@rollup/rollup-android-arm64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz#e2b38d0c912169fd55d7e38d723aada208d37256" + integrity sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw== + +"@rollup/rollup-darwin-arm64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz#1fddb3690f2ae33df16d334c613377f05abe4878" + integrity sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w== + +"@rollup/rollup-darwin-x64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz#818298d11c8109e1112590165142f14be24b396d" + integrity sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ== + +"@rollup/rollup-freebsd-arm64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz#91a28dc527d5bed7f9ecf0e054297b3012e19618" + integrity sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ== + +"@rollup/rollup-freebsd-x64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz#28acadefa76b5c7bede1576e065b51d335c62c62" + integrity sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz#819691464179cbcd9a9f9d3dc7617954840c6186" + integrity sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q== + +"@rollup/rollup-linux-arm-musleabihf@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz#d149207039e4189e267e8724050388effc80d704" + integrity sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg== + +"@rollup/rollup-linux-arm64-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz#fa72ebddb729c3c6d88973242f1a2153c83e86ec" + integrity sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg== + +"@rollup/rollup-linux-arm64-musl@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz#2054216e34469ab8765588ebf343d531fc3c9228" + integrity sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg== + +"@rollup/rollup-linux-loongarch64-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz#818de242291841afbfc483a84f11e9c7a11959bc" + integrity sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw== + +"@rollup/rollup-linux-powerpc64le-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz#0bb4cb8fc4a2c635f68c1208c924b2145eb647cb" + integrity sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q== + +"@rollup/rollup-linux-riscv64-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz#4b3b8e541b7b13e447ae07774217d98c06f6926d" + integrity sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg== + +"@rollup/rollup-linux-riscv64-musl@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz#e065405e67d8bd64a7d0126c931bd9f03910817f" + integrity sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg== + +"@rollup/rollup-linux-s390x-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz#dda3265bbbfe16a5d0089168fd07f5ebb2a866fe" + integrity sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ== + +"@rollup/rollup-linux-x64-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz#90993269b8b995b4067b7b9d72ff1c360ef90a17" + integrity sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng== + +"@rollup/rollup-linux-x64-musl@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz#fdf5b09fd121eb8d977ebb0fda142c7c0167b8de" + integrity sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA== + +"@rollup/rollup-win32-arm64-msvc@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz#6397e1e012db64dfecfed0774cb9fcf89503d716" + integrity sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg== + +"@rollup/rollup-win32-ia32-msvc@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz#df0991464a52a35506103fe18d29913bf8798a0c" + integrity sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA== + +"@rollup/rollup-win32-x64-msvc@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz#8dae04d01a2cbd84d6297d99356674c6b993f0fc" + integrity sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA== "@sindresorhus/is@^0.14.0": version "0.14.0" @@ -1574,9 +1595,9 @@ integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== "@types/cors@^2.8.12": - version "2.8.17" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" - integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== + version "2.8.18" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.18.tgz#101e033b3ca06695f3d73c587cd7f9eb348135d1" + integrity sha512-nX3d0sxJW41CqQvfOzVG1NCTXfFDrDWIghCZncpHeWlVFd81zxB/DLhg7avFg6eHLCRX7ckBmoIIcqa++upvJA== dependencies: "@types/node" "*" @@ -1618,11 +1639,11 @@ integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== "@types/node@*", "@types/node@>=10.0.0", "@types/node@>=18": - version "22.13.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.14.tgz#70d84ec91013dcd2ba2de35532a5a14c2b4cc912" - integrity sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w== + version "22.15.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.18.tgz#2f8240f7e932f571c2d45f555ba0b6c3f7a75963" + integrity sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg== dependencies: - undici-types "~6.20.0" + undici-types "~6.21.0" "@types/normalize-package-data@^2.4.3": version "2.4.4" @@ -1659,10 +1680,10 @@ resolved "https://registry.yarnpkg.com/@visual-framework/vf-config/-/vf-config-1.0.1.tgz#d11bdd1a9eae73e49fedfe3e2e8fd8d34c748684" integrity sha512-ZlHMvVGmGxSmgCCcZ59PdaPdif0cZyX99T2LYtjodwvu52Vhri/JxrAFsT46NSVl1bKYyJI+tEXAXBFLBwpt7A== -"@visual-framework/vf-core@^2.2.48": - version "2.2.48" - resolved "https://registry.yarnpkg.com/@visual-framework/vf-core/-/vf-core-2.2.48.tgz#f6f7b7908548d6bf548486759e682bcd05cf4953" - integrity sha512-IaUTzlR+8iASgRiEacePWpMBlKz5bVG/kQensjn0ZdRJouInS7JzyO5lhSFjXg4LIVlpND8WD8iyn1pV6pM4hQ== +"@visual-framework/vf-core@^2.2.49": + version "2.2.49" + resolved "https://registry.yarnpkg.com/@visual-framework/vf-core/-/vf-core-2.2.49.tgz#3d521b227528d2fa7c285695bad109dcde64584a" + integrity sha512-9AhKjycYDhjc12NSZRo8tsMcChSyyiciuDb+0mAarqYnGQqc+Qzsz0YkPd3SGqmnMDHj5mJFe8+2lQKROG2Ufw== dependencies: "@visual-framework/vf-component-generator" "^1.1.7" "@visual-framework/vf-component-initialization" "^1.1.13" @@ -1736,6 +1757,14 @@ abbrev@^2.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== +accepts@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895" + integrity sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng== + dependencies: + mime-types "^3.0.0" + negotiator "^1.0.0" + accepts@~1.3.4, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -2359,6 +2388,21 @@ body-parser@1.20.3: type-is "~1.6.18" unpipe "1.0.0" +body-parser@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.0.tgz#f7a9656de305249a715b549b7b8fd1ab9dfddcfa" + integrity sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg== + dependencies: + bytes "^3.1.2" + content-type "^1.0.5" + debug "^4.4.0" + http-errors "^2.0.0" + iconv-lite "^0.6.3" + on-finished "^2.4.1" + qs "^6.14.0" + raw-body "^3.0.0" + type-is "^2.0.0" + boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -2504,14 +2548,14 @@ browserslist@^2.11.3: electron-to-chromium "^1.3.30" browserslist@^4.24.0, browserslist@^4.24.4: - version "4.24.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" - integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== + version "4.24.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.5.tgz#aa0f5b8560fe81fde84c6dcb38f759bafba0e11b" + integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw== dependencies: - caniuse-lite "^1.0.30001688" - electron-to-chromium "^1.5.73" + caniuse-lite "^1.0.30001716" + electron-to-chromium "^1.5.149" node-releases "^2.0.19" - update-browserslist-db "^1.1.1" + update-browserslist-db "^1.1.3" bs-recipes@1.3.4: version "1.3.4" @@ -2531,7 +2575,7 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -bytes@3.1.2: +bytes@3.1.2, bytes@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== @@ -2564,13 +2608,13 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" -cacheable@^1.8.9: - version "1.8.9" - resolved "https://registry.yarnpkg.com/cacheable/-/cacheable-1.8.9.tgz#f5498999567ae1015761d805bd8bbecd8393fbd4" - integrity sha512-FicwAUyWnrtnd4QqYAoRlNs44/a1jTL7XDKqm5gJ90wz1DQPlC7U2Rd1Tydpv+E7WAr4sQHuw8Q8M3nZMAyecQ== +cacheable@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/cacheable/-/cacheable-1.9.0.tgz#57e3565c311d66371eeb5f2070b6615d43b89711" + integrity sha512-8D5htMCxPDUULux9gFzv30f04Xo3wCnik0oOxKoRTPIBoqA7HtOcJ87uBhQTs3jCfZZTrUBGsYIZOgE0ZRgMAg== dependencies: - hookified "^1.7.1" - keyv "^5.3.1" + hookified "^1.8.2" + keyv "^5.3.3" call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" @@ -2590,7 +2634,7 @@ call-bind@^1.0.8: get-intrinsic "^1.2.4" set-function-length "^1.2.2" -call-bound@^1.0.2, call-bound@^1.0.3: +call-bound@^1.0.2, call-bound@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== @@ -2655,10 +2699,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30001688, caniuse-lite@^1.0.30001702: - version "1.0.30001707" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz#c5e104d199e6f4355a898fcd995a066c7eb9bf41" - integrity sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw== +caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001716: + version "1.0.30001718" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz#dae13a9c80d517c30c6197515a96131c194d8f82" + integrity sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw== capture-stack-trace@^1.0.0: version "1.0.2" @@ -3120,7 +3164,14 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@~1.0.4, content-type@~1.0.5: +content-disposition@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.0.tgz#844426cb398f934caefcbb172200126bc7ceace2" + integrity sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg== + dependencies: + safe-buffer "5.2.1" + +content-type@^1.0.5, content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== @@ -3135,12 +3186,17 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== +cookie-signature@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" + integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== + cookie@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== -cookie@~0.7.2: +cookie@^0.7.1, cookie@~0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -3159,9 +3215,9 @@ copy-props@^4.0.0: is-plain-object "^5.0.0" core-js-compat@^3.40.0: - version "3.41.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.41.0.tgz#4cdfce95f39a8f27759b667cf693d96e5dda3d17" - integrity sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A== + version "3.42.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.42.0.tgz#ce19c29706ee5806e26d3cb3c542d4cfc0ed51bb" + integrity sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ== dependencies: browserslist "^4.24.4" @@ -3175,7 +3231,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cors@~2.8.5: +cors@^2.8.5, cors@~2.8.5: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== @@ -3230,7 +3286,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.3, cross-spawn@^7.0.6: +cross-spawn@^7.0.3, cross-spawn@^7.0.5, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -3365,10 +3421,10 @@ debug@^3.0.0, debug@^3.0.1: dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.7: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.7, debug@^4.4.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== dependencies: ms "^2.1.3" @@ -3476,7 +3532,7 @@ del@^8.0.0: p-map "^7.0.2" slash "^5.1.0" -depd@2.0.0: +depd@2.0.0, depd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -3722,9 +3778,9 @@ easy-transform-stream@^1.0.1: integrity sha512-ktkaa6XR7COAR3oj02CF3IOgz2m1hCaY3SfzvKT4Svt2MhHw9XCt+ncJNWfe2TGz31iqzNGZ8spdKQflj+Rlog== eazy-logger@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-4.0.1.tgz#2e9fe487fb14ed6ac20d5f01d90dff377d403041" - integrity sha512-2GSFtnnC6U4IEKhEI7+PvdxrmjJ04mdsj3wHZTFiw0tUtG4HCWzTr13ZYTk8XOGnA1xQMaDljoBOYlk3D/MMSw== + version "4.1.0" + resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-4.1.0.tgz#d4dae8688b0d730ba1ae6065410b7a51df9990b4" + integrity sha512-+mn7lRm+Zf1UT/YaH8WXtpU6PIV2iOjzP6jgKoiaq/VNrjYKp+OHZGe2znaLgDeFkw8cL9ffuaUm+nNnzcYyGw== dependencies: chalk "4.1.2" @@ -3757,10 +3813,10 @@ ejs@^3.1.10, ejs@^3.1.9: dependencies: jake "^10.8.5" -electron-to-chromium@^1.3.30, electron-to-chromium@^1.5.73: - version "1.5.128" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.128.tgz#8ea537b369c32527b3cc47df7973bffe5d3c2980" - integrity sha512-bo1A4HH/NS522Ws0QNFIzyPcyUUNV/yyy70Ho1xqfGYzPUme2F/xr4tlEOuM6/A538U1vDA7a4XfCd1CKRegKQ== +electron-to-chromium@^1.3.30, electron-to-chromium@^1.5.149: + version "1.5.155" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz#809dd0ae9ae1db87c358e0c0c17c09a2ffc432d1" + integrity sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng== emoji-regex@^10.2.1: version "10.4.0" @@ -3782,16 +3838,16 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +encodeurl@^2.0.0, encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + encodeurl@~1.0.1, encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -encodeurl@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" - integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== - end-of-stream@^1.1.0, end-of-stream@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -3957,7 +4013,7 @@ escape-goat@^2.0.0: resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== -escape-html@~1.0.3: +escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== @@ -4108,21 +4164,22 @@ eslint@^6.0.0: v8-compile-cache "^2.0.3" eslint@^9.0.0: - version "9.23.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.23.0.tgz#b88f3ab6dc83bcb927fdb54407c69ffe5f2441a6" - integrity sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw== + version "9.26.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.26.0.tgz#978fe029adc2aceed28ab437bca876e83461c3b4" + integrity sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.19.2" - "@eslint/config-helpers" "^0.2.0" - "@eslint/core" "^0.12.0" + "@eslint/config-array" "^0.20.0" + "@eslint/config-helpers" "^0.2.1" + "@eslint/core" "^0.13.0" "@eslint/eslintrc" "^3.3.1" - "@eslint/js" "9.23.0" - "@eslint/plugin-kit" "^0.2.7" + "@eslint/js" "9.26.0" + "@eslint/plugin-kit" "^0.2.8" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/retry" "^0.4.2" + "@modelcontextprotocol/sdk" "^1.8.0" "@types/estree" "^1.0.6" "@types/json-schema" "^7.0.15" ajv "^6.12.4" @@ -4147,6 +4204,7 @@ eslint@^9.0.0: minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.3" + zod "^3.24.2" esniff@^2.0.1: version "2.0.1" @@ -4249,6 +4307,18 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== +eventsource-parser@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.2.tgz#0fea1abd26eca8201099ff5212f6c4e7ca2fd5d3" + integrity sha512-6RxOBZ/cYgd8usLwsEl+EC09Au/9BcmCKYF2/xbml6DNczf7nv0MQb+7BA2F+li6//I+28VNlQR37XfQtcAJuA== + +eventsource@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-3.0.7.tgz#1157622e2f5377bb6aef2114372728ba0c156989" + integrity sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA== + dependencies: + eventsource-parser "^3.0.1" + execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -4338,6 +4408,11 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +express-rate-limit@^7.5.0: + version "7.5.0" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.0.tgz#6a67990a724b4fbbc69119419feef50c51e8b28f" + integrity sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg== + express@^4.17.1: version "4.21.2" resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32" @@ -4375,6 +4450,39 @@ express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" +express@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/express/-/express-5.1.0.tgz#d31beaf715a0016f0d53f47d3b4d7acf28c75cc9" + integrity sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA== + dependencies: + accepts "^2.0.0" + body-parser "^2.2.0" + content-disposition "^1.0.0" + content-type "^1.0.5" + cookie "^0.7.1" + cookie-signature "^1.2.1" + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + finalhandler "^2.1.0" + fresh "^2.0.0" + http-errors "^2.0.0" + merge-descriptors "^2.0.0" + mime-types "^3.0.0" + on-finished "^2.4.1" + once "^1.4.0" + parseurl "^1.3.3" + proxy-addr "^2.0.7" + qs "^6.14.0" + range-parser "^1.2.1" + router "^2.2.0" + send "^1.1.0" + serve-static "^2.2.0" + statuses "^2.0.1" + type-is "^2.0.1" + vary "^1.1.2" + ext@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" @@ -4532,12 +4640,12 @@ file-entry-cache@^1.1.1: flat-cache "^1.2.1" object-assign "^4.0.1" -file-entry-cache@^10.0.7: - version "10.0.7" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-10.0.7.tgz#e0ac34d4b8c44bea8a0a27ceb4dae982f2d32749" - integrity sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw== +file-entry-cache@^10.0.8: + version "10.1.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-10.1.0.tgz#54c0117fe76425e9f08a44a3a08bedde0cd93fe8" + integrity sha512-Et/ex6smi3wOOB+n5mek+Grf7P2AxZR5ueqRUvAAn4qkyatXi3cUC1cuQXVkX0VlzBVsN4BkWJFmY/fYiRTdww== dependencies: - flat-cache "^6.1.7" + flat-cache "^6.1.9" file-entry-cache@^2.0.0: version "2.0.0" @@ -4627,6 +4735,18 @@ finalhandler@1.3.1, finalhandler@^1.2.0: statuses "2.0.1" unpipe "~1.0.0" +finalhandler@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.0.tgz#72306373aa89d05a8242ed569ed86a1bff7c561f" + integrity sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q== + dependencies: + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + on-finished "^2.4.1" + parseurl "^1.3.3" + statuses "^2.0.1" + find-up-simple@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/find-up-simple/-/find-up-simple-1.0.1.tgz#18fb90ad49e45252c4d7fca56baade04fa3fca1e" @@ -4743,14 +4863,14 @@ flat-cache@^4.0.0: flatted "^3.2.9" keyv "^4.5.4" -flat-cache@^6.1.7: - version "6.1.7" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-6.1.7.tgz#c04b08316739ad7ef997e1b9ea363443fc2fcb38" - integrity sha512-qwZ4xf1v1m7Rc9XiORly31YaChvKt6oNVHuqqZcoED/7O+ToyNVGobKsIAopY9ODcWpEDKEBAbrSOCBHtNQvew== +flat-cache@^6.1.9: + version "6.1.9" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-6.1.9.tgz#6f512c4ab81c2057577fdb30c2f64022d43db2e7" + integrity sha512-DUqiKkTlAfhtl7g78IuwqYM+YqvT+as0mY+EVk6mfimy19U79pJCzDZQsnqk3Ou/T6hFXWLGbwbADzD/c8Tydg== dependencies: - cacheable "^1.8.9" + cacheable "^1.9.0" flatted "^3.3.3" - hookified "^1.7.1" + hookified "^1.8.2" flatted@^2.0.0: version "2.0.2" @@ -4816,6 +4936,11 @@ fresh@0.5.2, fresh@^0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" + integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== + from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" @@ -5599,10 +5724,10 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" -hookified@^1.7.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.8.1.tgz#74a8c97d36e5f8004d230ee2156a607cc84c358c" - integrity sha512-GrO2l93P8xCWBSTBX9l2BxI78VU/MAAYag+pG8curS3aBGy0++ZlxrQ7PdUOUVMbn5BwkGb6+eRrnf43ipnFEA== +hookified@^1.8.2: + version "1.9.0" + resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.9.0.tgz#271211f61c63b3a68a8ead9d9fddd72b5806c004" + integrity sha512-2yEEGqphImtKIe1NXWEhu6yD3hlFR4Mxk4Mtp3XEyScpSt4pQ4ymmXA1zzxZpj99QkFK+nN0nzjeb2+RUi/6CQ== hosted-git-info@^2.1.4: version "2.8.9" @@ -5672,16 +5797,16 @@ htmlparser2@^7.1.1: entities "^3.0.1" http-cache-semantics@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + version "4.2.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#205f4db64f8562b76a4ff9235aa5279839a09dd5" + integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ== http-equiv-refresh@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-equiv-refresh/-/http-equiv-refresh-1.0.0.tgz#8ec538866042be5f3f7afa737d198d94beb1b07b" integrity sha512-TScO04soylRN9i/QdOdgZyhydXg9z6XdaGzEyOgDKycePeDeTT4KvigjBcI+tgfTlieLWauGORMq5F1eIDa+1w== -http-errors@2.0.0: +http-errors@2.0.0, http-errors@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== @@ -5728,7 +5853,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.6.3: +iconv-lite@0.6.3, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -5756,9 +5881,9 @@ ignore@^5.2.0: integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== ignore@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.3.tgz#397ef9315dfe0595671eefe8b633fec6943ab733" - integrity sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA== + version "7.0.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.4.tgz#a12c70d0f2607c5bf508fb65a40c75f037d7a078" + integrity sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A== immutable@^3: version "3.8.2" @@ -5766,9 +5891,9 @@ immutable@^3: integrity sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg== immutable@^5.0.2: - version "5.1.1" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.1.tgz#d4cb552686f34b076b3dcf23c4384c04424d8354" - integrity sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg== + version "5.1.2" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.2.tgz#e8169476414505e5a4fa650107b65e1227d16d4b" + integrity sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ== import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.1" @@ -5813,10 +5938,10 @@ indent-string@^3.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ== -index-to-position@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/index-to-position/-/index-to-position-1.0.0.tgz#baca236eb6e8c2b750b9225313c31751f84ef357" - integrity sha512-sCO7uaLVhRJ25vz1o8s9IFM3nVS4DkuQnyjMwiQPKvQuBYBDmb8H7zx8ki7nVh4HJQOdVWebyvLE0qt+clruxA== +index-to-position@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/index-to-position/-/index-to-position-1.1.0.tgz#2e50bd54c8040bdd6d9b3d95ec2a8fedf86b4d44" + integrity sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg== indexes-of@^1.0.1: version "1.0.1" @@ -6256,6 +6381,11 @@ is-promise@^2.0.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== +is-promise@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" + integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== + is-property@^1.0.0, is-property@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" @@ -6531,12 +6661,12 @@ json-stable-stringify-without-jsonify@^1.0.1: integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.2.1.tgz#addb683c2b78014d0b78d704c2fcbdf0695a60e2" - integrity sha512-Lp6HbbBgosLmJbjx0pBLbgvx68FaFU1sdkmBuckmhhJ88kL13OA51CDtR2yJB50eCNMH9wRqtQNNiAqQH4YXnA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz#8903cfac42ea1a0f97f35d63a4ce0518f0cc6a70" + integrity sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg== dependencies: call-bind "^1.0.8" - call-bound "^1.0.3" + call-bound "^1.0.4" isarray "^2.0.5" jsonify "^0.0.1" object-keys "^1.1.1" @@ -6607,10 +6737,10 @@ keyv@^4.5.4: dependencies: json-buffer "3.0.1" -keyv@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.3.2.tgz#32edd461b51d44d42926eb72946236d79c71ae78" - integrity sha512-Lji2XRxqqa5Wg+CHLVfFKBImfJZ4pCSccu9eVWK6w4c2SDFLd8JAn1zqTuSFnsxb7ope6rMsnIHfp+eBbRBRZQ== +keyv@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.3.3.tgz#ec2d723fbd7b908de5ee7f56b769d46dbbeaf8ba" + integrity sha512-Rwu4+nXI9fqcxiEHtbkvoes2X+QfkTRo1TMkPfwzipGsJlJO/z69vqB4FNl9xJ3xCpAcbkvmEabZfPzrwN3+gQ== dependencies: "@keyv/serialize" "^1.0.3" @@ -6648,10 +6778,10 @@ known-css-properties@^0.3.0: resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.3.0.tgz#a3d135bbfc60ee8c6eacf2f7e7e6f2d4755e49a4" integrity sha512-QMQcnKAiQccfQTqtBh/qwquGZ2XK/DXND1jrcN9M8gMMy99Gwla7GQjndVUsEqIaRyP6bsFRuhwRj5poafBGJQ== -known-css-properties@^0.35.0: - version "0.35.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.35.0.tgz#f6f8e40ab4e5700fa32f5b2ef5218a56bc853bd6" - integrity sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A== +known-css-properties@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.36.0.tgz#5c4365f3c9549ca2e813d2e729e6c47ef6a6cb60" + integrity sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA== known-css-properties@^0.5.0: version "0.5.0" @@ -6659,9 +6789,9 @@ known-css-properties@^0.5.0: integrity sha512-LOS0CoS8zcZnB1EjLw4LLqDXw8nvt3AGH5dXLQP3D9O1nLLA+9GC5GnPl5mmF+JiQAtSX4VyZC7KvEtcA4kUtA== ky@^1.2.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/ky/-/ky-1.8.0.tgz#0f4c83be590555a2b435d11459b460324b0038fc" - integrity sha512-DoKGmG27nT8t/1F9gV8vNzggJ3mLAyD49J8tTMWHeZvS8qLc7GlyTieicYtFzvDznMe/q2u38peOjkWc5/pjvw== + version "1.8.1" + resolved "https://registry.yarnpkg.com/ky/-/ky-1.8.1.tgz#b1adaa473bc30aced2bab4c408ec177b78d198f0" + integrity sha512-7Bp3TpsE+L+TARSnnDpk3xg8Idi8RwSLdj6CMbNWoOARIrGrbuLGusV0dYwbZOm4bB3jHNxSw8Wk/ByDqJEnDw== last-run@^2.0.0: version "2.0.0" @@ -6755,9 +6885,9 @@ linkify-it@^4.0.1: uc.micro "^1.0.1" liquidjs@^10.7.0: - version "10.21.0" - resolved "https://registry.yarnpkg.com/liquidjs/-/liquidjs-10.21.0.tgz#d3e43df2144bf6fc12c3ee1f3e6dcabd65b22ba9" - integrity sha512-DouqxNU2jfoZzb1LinVjOc/f6ssitGIxiDJT+kEKyYqPSSSd+WmGOAhtWbVm1/n75svu4aQ+FyQ3ctd3wh1bbw== + version "10.21.1" + resolved "https://registry.yarnpkg.com/liquidjs/-/liquidjs-10.21.1.tgz#5867dac16f1a74552e1ca5fdc976c0fa4bcdf527" + integrity sha512-NZXmCwv3RG5nire3fmIn9HsOyJX3vo+ptp0yaXUHAMzSNBhx74Hm+dAGJvscUA6lNqbLuYfXgNavRQ9UbUJhQQ== dependencies: commander "^10.0.0" @@ -7245,10 +7375,10 @@ mdn-data@2.12.2: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.12.2.tgz#9ae6c41a9e65adf61318b32bff7b64fbfb13f8cf" integrity sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA== -mdn-data@^2.15.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.18.0.tgz#518adc4811817a8b8c88e0e67d985b8f42e968d5" - integrity sha512-gtCy1yim/vpHF/tq3B4Z43x3zKWpYeb4IM3d/Mf4oMYcNuoXOYEaqtoFlLHw9zd7+WNN3jNh6/WXyUrD3OIiwQ== +mdn-data@^2.21.0: + version "2.21.0" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.21.0.tgz#f3a495e8b1e60cb4fbeaf9136aefba2f987a56e1" + integrity sha512-+ZKPQezM5vYJIkCxaC+4DTnRrVZR1CgsKLu5zsQERQx6Tea8Y+wMx5A24rq8A8NepCeatIQufVAekKNgiBMsGQ== mdurl@^1.0.1: version "1.0.1" @@ -7260,6 +7390,11 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== +media-typer@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" + integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== + mem-fs-editor@^11.0.1: version "11.1.4" resolved "https://registry.yarnpkg.com/mem-fs-editor/-/mem-fs-editor-11.1.4.tgz#ddfe705f3b0110cb96a40a3cad290ca21f0d1900" @@ -7325,6 +7460,11 @@ merge-descriptors@1.0.3: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== +merge-descriptors@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz#ea922f660635a2249ee565e0449f951e6b603808" + integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -7396,6 +7536,18 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +mime-db@^1.54.0: + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + +mime-types@^3.0.0, mime-types@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.1.tgz#b1d94d6997a9b32fd69ebaed0db73de8acb519ce" + integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== + dependencies: + mime-db "^1.54.0" + mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" @@ -7534,9 +7686,9 @@ moo@^0.5.2: integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q== morphdom@^2.7.0: - version "2.7.4" - resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.7.4.tgz#c61d511e935cc25ca588dfaa752461f27865865e" - integrity sha512-ATTbWMgGa+FaMU3FhnFYB6WgulCqwf6opOll4CBzmVDTLvPMmUPrEv8CudmLPK0MESa64+6B89fWOxP3+YIlxQ== + version "2.7.5" + resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.7.5.tgz#1f3942c85df3745a28674c41ddad572910259c05" + integrity sha512-z6bfWFMra7kBqDjQGHud1LSXtq5JJC060viEkQFMBX6baIecpkNr2Ywrn2OQfWP3rXiNFQRPoFjD8/TvJcWcDg== ms@2.0.0: version "2.0.0" @@ -7632,6 +7784,11 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" + integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== + neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -7868,7 +8025,7 @@ object.pick@^1.2.0, object.pick@^1.3.0: dependencies: isobject "^3.0.1" -on-finished@2.4.1: +on-finished@2.4.1, on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== @@ -8120,13 +8277,13 @@ parse-json@^5.2.0: lines-and-columns "^1.1.6" parse-json@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-8.2.0.tgz#794a590dcf54588ec2282ce6065f15121fa348a0" - integrity sha512-eONBZy4hm2AgxjNFd8a4nyDJnzUAH0g34xSQAwWEVGCjdZ4ZL7dKZBfq267GWP/JaS9zW62Xs2FeAdDvpHHJGQ== + version "8.3.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-8.3.0.tgz#88a195a2157025139a2317a4f2f9252b61304ed5" + integrity sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ== dependencies: "@babel/code-frame" "^7.26.2" - index-to-position "^1.0.0" - type-fest "^4.37.0" + index-to-position "^1.1.0" + type-fest "^4.39.1" parse-node-version@^1.0.0: version "1.0.1" @@ -8143,7 +8300,7 @@ parse-srcset@^1.0.2: resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" integrity sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q== -parseurl@~1.3.2, parseurl@~1.3.3: +parseurl@^1.3.3, parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== @@ -8230,6 +8387,11 @@ path-to-regexp@^6.2.0, path-to-regexp@^6.2.1: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== +path-to-regexp@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.2.0.tgz#73990cc29e57a3ff2a0d914095156df5db79e8b4" + integrity sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ== + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -8300,6 +8462,11 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== +pkce-challenge@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkce-challenge/-/pkce-challenge-5.0.0.tgz#c3a405cb49e272094a38e890a2b51da0228c4d97" + integrity sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ== + pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -8607,7 +8774,7 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== -proxy-addr@~2.0.7: +proxy-addr@^2.0.7, proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -8755,6 +8922,13 @@ qs@6.13.0: dependencies: side-channel "^1.0.6" +qs@^6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== + dependencies: + side-channel "^1.1.0" + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -8774,7 +8948,7 @@ randomatic@^3.0.0: kind-of "^6.0.0" math-random "^1.0.1" -range-parser@~1.2.0, range-parser@~1.2.1: +range-parser@^1.2.1, range-parser@~1.2.0, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== @@ -8789,6 +8963,16 @@ raw-body@2.5.2, raw-body@^2.3.2: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.0.tgz#25b3476f07a51600619dae3fe82ddc28a36e5e0f" + integrity sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.6.3" + unpipe "1.0.0" + rc@1.2.8, rc@^1.0.1, rc@^1.1.6, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -8973,18 +9157,6 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regenerator-transform@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" - integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== - dependencies: - "@babel/runtime" "^7.8.4" - regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" @@ -9324,34 +9496,45 @@ rollup-plugin-includepaths@^0.2.4: integrity sha512-iZen+XKVExeCzk7jeSZPJKL7B67slZNr8GXSC5ROBXtDGXDBH8wdjMfdNW5hf9kPt+tHyIvWh3wlE9bPrZL24g== rollup@^4.0.0: - version "4.38.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.38.0.tgz#e1ef4939aef0e1295f750ae4f73d1c8b7fc3abb8" - integrity sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw== + version "4.40.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.40.2.tgz#778e88b7a197542682b3e318581f7697f55f0619" + integrity sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg== dependencies: "@types/estree" "1.0.7" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.38.0" - "@rollup/rollup-android-arm64" "4.38.0" - "@rollup/rollup-darwin-arm64" "4.38.0" - "@rollup/rollup-darwin-x64" "4.38.0" - "@rollup/rollup-freebsd-arm64" "4.38.0" - "@rollup/rollup-freebsd-x64" "4.38.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.38.0" - "@rollup/rollup-linux-arm-musleabihf" "4.38.0" - "@rollup/rollup-linux-arm64-gnu" "4.38.0" - "@rollup/rollup-linux-arm64-musl" "4.38.0" - "@rollup/rollup-linux-loongarch64-gnu" "4.38.0" - "@rollup/rollup-linux-powerpc64le-gnu" "4.38.0" - "@rollup/rollup-linux-riscv64-gnu" "4.38.0" - "@rollup/rollup-linux-riscv64-musl" "4.38.0" - "@rollup/rollup-linux-s390x-gnu" "4.38.0" - "@rollup/rollup-linux-x64-gnu" "4.38.0" - "@rollup/rollup-linux-x64-musl" "4.38.0" - "@rollup/rollup-win32-arm64-msvc" "4.38.0" - "@rollup/rollup-win32-ia32-msvc" "4.38.0" - "@rollup/rollup-win32-x64-msvc" "4.38.0" + "@rollup/rollup-android-arm-eabi" "4.40.2" + "@rollup/rollup-android-arm64" "4.40.2" + "@rollup/rollup-darwin-arm64" "4.40.2" + "@rollup/rollup-darwin-x64" "4.40.2" + "@rollup/rollup-freebsd-arm64" "4.40.2" + "@rollup/rollup-freebsd-x64" "4.40.2" + "@rollup/rollup-linux-arm-gnueabihf" "4.40.2" + "@rollup/rollup-linux-arm-musleabihf" "4.40.2" + "@rollup/rollup-linux-arm64-gnu" "4.40.2" + "@rollup/rollup-linux-arm64-musl" "4.40.2" + "@rollup/rollup-linux-loongarch64-gnu" "4.40.2" + "@rollup/rollup-linux-powerpc64le-gnu" "4.40.2" + "@rollup/rollup-linux-riscv64-gnu" "4.40.2" + "@rollup/rollup-linux-riscv64-musl" "4.40.2" + "@rollup/rollup-linux-s390x-gnu" "4.40.2" + "@rollup/rollup-linux-x64-gnu" "4.40.2" + "@rollup/rollup-linux-x64-musl" "4.40.2" + "@rollup/rollup-win32-arm64-msvc" "4.40.2" + "@rollup/rollup-win32-ia32-msvc" "4.40.2" + "@rollup/rollup-win32-x64-msvc" "4.40.2" fsevents "~2.3.2" +router@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef" + integrity sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ== + dependencies: + debug "^4.4.0" + depd "^2.0.0" + is-promise "^4.0.0" + parseurl "^1.3.3" + path-to-regexp "^8.0.0" + run-async@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" @@ -9496,9 +9679,9 @@ semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.3.4, semver@^7.3.5, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0: - version "7.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" - integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== send@0.16.2: version "0.16.2" @@ -9538,6 +9721,23 @@ send@0.19.0: range-parser "~1.2.1" statuses "2.0.1" +send@^1.1.0, send@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/send/-/send-1.2.0.tgz#32a7554fb777b831dfa828370f773a3808d37212" + integrity sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw== + dependencies: + debug "^4.3.5" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + fresh "^2.0.0" + http-errors "^2.0.0" + mime-types "^3.0.1" + ms "^2.1.3" + on-finished "^2.4.1" + range-parser "^1.2.1" + statuses "^2.0.1" + serve-index@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -9571,6 +9771,16 @@ serve-static@1.16.2: parseurl "~1.3.3" send "0.19.0" +serve-static@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.0.tgz#9c02564ee259bdd2251b82d659a2e7e1938d66f9" + integrity sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ== + dependencies: + encodeurl "^2.0.0" + escape-html "^1.0.3" + parseurl "^1.3.3" + send "^1.2.0" + server-destroy@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" @@ -9666,7 +9876,7 @@ side-channel-weakmap@^1.0.2: object-inspect "^1.13.3" side-channel-map "^1.0.1" -side-channel@^1.0.6: +side-channel@^1.0.6, side-channel@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== @@ -9943,7 +10153,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -statuses@2.0.1: +statuses@2.0.1, statuses@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== @@ -10208,23 +10418,23 @@ stylelint-order@^6.0.0: postcss-sorting "^8.0.2" stylelint-scss@^6.11.1: - version "6.11.1" - resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.11.1.tgz#03860aab250112825b2deb77ca7ff1e2ba3a5414" - integrity sha512-e4rYo0UY+BIMtGeGanghrvHTjcryxgZbyFxUedp8dLFqC4P70aawNdYjRrQxbnKhu3BNr4+lt5e/53tcKXiwFA== + version "6.12.0" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.12.0.tgz#38cf41c3b8a76f34cd7267e4c30e7e66d35619c2" + integrity sha512-U7CKhi1YNkM1pXUXl/GMUXi8xKdhl4Ayxdyceie1nZ1XNIdaUgMV6OArpooWcDzEggwgYD0HP/xIgVJo9a655w== dependencies: css-tree "^3.0.1" is-plain-object "^5.0.0" - known-css-properties "^0.35.0" - mdn-data "^2.15.0" + known-css-properties "^0.36.0" + mdn-data "^2.21.0" postcss-media-query-parser "^0.2.3" postcss-resolve-nested-selector "^0.1.6" postcss-selector-parser "^7.1.0" postcss-value-parser "^4.2.0" stylelint@^16.0.0: - version "16.17.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.17.0.tgz#12f31389283883d8d15bb5c019830af8176998a1" - integrity sha512-I9OwVIWRMqVm2Br5iTbrfSqGRPWQUlvm6oXO1xZuYYu0Gpduy67N8wXOZv15p6E/JdlZiAtQaIoLKZEWk5hrjw== + version "16.19.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.19.1.tgz#486b95fa7518a3077ee2802bc6dda2174bc097bb" + integrity sha512-C1SlPZNMKl+d/C867ZdCRthrS+6KuZ3AoGW113RZCOL0M8xOGpgx7G70wq7lFvqvm4dcfdGFVLB/mNaLFChRKw== dependencies: "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" @@ -10239,7 +10449,7 @@ stylelint@^16.0.0: debug "^4.3.7" fast-glob "^3.3.3" fastest-levenshtein "^1.0.16" - file-entry-cache "^10.0.7" + file-entry-cache "^10.0.8" global-modules "^2.0.0" globby "^11.1.0" globjoin "^0.1.4" @@ -10247,7 +10457,7 @@ stylelint@^16.0.0: ignore "^7.0.3" imurmurhash "^0.1.4" is-plain-object "^5.0.0" - known-css-properties "^0.35.0" + known-css-properties "^0.36.0" mathml-tag-names "^2.1.3" meow "^13.2.0" micromatch "^4.0.8" @@ -10650,10 +10860,19 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-fest@^4.37.0, type-fest@^4.6.0: - version "4.38.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.38.0.tgz#659fa14d1a71c2811400aa3b5272627e0c1e6b96" - integrity sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg== +type-fest@^4.39.1, type-fest@^4.6.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + +type-is@^2.0.0, type-is@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.0.1.tgz#64f6cf03f92fce4015c2b224793f6bdd4b068c97" + integrity sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw== + dependencies: + content-type "^1.0.5" + media-typer "^1.1.0" + mime-types "^3.0.0" type-is@~1.6.18: version "1.6.18" @@ -10720,10 +10939,10 @@ undertaker@^2.0.0: last-run "^2.0.0" undertaker-registry "^2.0.0" -undici-types@~6.20.0: - version "6.20.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" - integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== unherit@^1.0.4: version "1.1.3" @@ -10846,9 +11065,9 @@ unist-util-visit@^1.1.0: unist-util-visit-parents "^2.0.0" universal-user-agent@^7.0.0, universal-user-agent@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-7.0.2.tgz#52e7d0e9b3dc4df06cc33cb2b9fd79041a54827e" - integrity sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q== + version "7.0.3" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-7.0.3.tgz#c05870a58125a2dc00431f2df815a77fe69736be" + integrity sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A== universalify@^0.1.0: version "0.1.2" @@ -10878,7 +11097,7 @@ unzip-response@^2.0.1: resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" integrity sha512-N0XH6lqDtFH84JxptQoZYmloF4nzrQqqrAymNj+/gW60AO2AZgOcf4O/nUXJcYfyQkqvMo9lSupBZmmgvuVXlw== -update-browserslist-db@^1.1.1: +update-browserslist-db@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== @@ -11010,7 +11229,7 @@ value-or-function@^4.0.0: resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-4.0.0.tgz#70836b6a876a010dc3a2b884e7902e9db064378d" integrity sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg== -vary@^1, vary@~1.1.2: +vary@^1, vary@^1.1.2, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== @@ -11287,9 +11506,9 @@ write@^0.2.1: mkdirp "^0.5.1" ws@^8.13.0: - version "8.18.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" - integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w== + version "8.18.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.2.tgz#42738b2be57ced85f46154320aabb51ab003705a" + integrity sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ== ws@~8.17.1: version "8.17.1" @@ -11431,3 +11650,13 @@ yosay@^3.0.0: string-width "^6.1.0" strip-ansi "^7.1.0" wrap-ansi "^8.1.0" + +zod-to-json-schema@^3.24.1: + version "3.24.5" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz#d1095440b147fb7c2093812a53c54df8d5df50a3" + integrity sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g== + +zod@^3.23.8, zod@^3.24.2: + version "3.24.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.4.tgz#e2e2cca5faaa012d76e527d0d36622e0a90c315f" + integrity sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg== From 58347fa4ad64424912fa56f82df045c5e3b7ba84 Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Wed, 21 May 2025 14:05:31 +0100 Subject: [PATCH 02/71] VF - Chatbot initial code --- components/vf-chatbot-modal/api-handler.js | 53 +++ .../vf-chatbot-modal/vf-chatbot-modal.scss | 321 ++++++++++++++ .../vf-chatbot-prompt/vf-chatbot-prompt.scss | 80 ++++ .../vf-chatbot-standalone.js | 334 +++++++++++++++ .../vf-chatbot-standalone.njk | 121 ++++++ .../vf-chatbot-standalone.scss | 405 ++++++++++++++++++ 6 files changed, 1314 insertions(+) create mode 100644 components/vf-chatbot-modal/api-handler.js create mode 100644 components/vf-chatbot-modal/vf-chatbot-modal.scss create mode 100644 components/vf-chatbot-prompt/vf-chatbot-prompt.scss create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.js create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.njk create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.scss diff --git a/components/vf-chatbot-modal/api-handler.js b/components/vf-chatbot-modal/api-handler.js new file mode 100644 index 0000000000..66c0044978 --- /dev/null +++ b/components/vf-chatbot-modal/api-handler.js @@ -0,0 +1,53 @@ +export class LLMApiHandler { + constructor() { + // You'll need to sign up at Hugging Face and get your API token + // https://huggingface.co/settings/tokens + this.API_TOKEN = ""; + this.API_URL = "https://api.mistral.ai/v1/chat/completions"; + // "https://api-inference.huggingface.co/models/facebook/blenderbot-400M-distill"; + } + + async generateResponse(message) { + console.log("Generating response for:", message); // Debug log + + try { + const response = await fetch(this.API_URL, { + method: "POST", + headers: { + Authorization: `Bearer ${this.API_TOKEN}`, + "Content-Type": "application/json" + }, + data: JSON.stringify({ + "messages": [{"role": "user", "content": message}], + "model": "mistral-small-latest", + }) + }); + + console.log("API response status:", response.status); // Debug log + + if (!response.ok) { + const errorText = await response.text(); + console.error("API error:", errorText); // Debug log + throw new Error(`API request failed: ${response.status} ${errorText}`); + } + + const data = await response.json(); + console.log("API response data:", data); // Debug log + + return { + html: this.formatResponse(data[0].generated_text) + }; + } catch (error) { + console.error("LLM API Error:", error); // Debug log + throw error; + } + } + + formatResponse(text) { + if (!text) return "

No response generated

"; + return text + .split("\n") + .map(paragraph => `

${paragraph}

`) + .join(""); + } +} diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.scss b/components/vf-chatbot-modal/vf-chatbot-modal.scss new file mode 100644 index 0000000000..d55b4d1b6d --- /dev/null +++ b/components/vf-chatbot-modal/vf-chatbot-modal.scss @@ -0,0 +1,321 @@ +.vf-chatbot-modal { + display: none; + position: fixed; + bottom: 80px; + right: 20px; + width: 360px; + height: 500px; + background: #ffffff; + border-radius: 16px 16px 0px 16px; // Increased border radius + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + z-index: 999; + overflow: hidden; + transition: all 0.3s ease; + opacity: 0; + transform: translateY(20px); + + &--active { + display: flex; + flex-direction: column; + opacity: 1; + transform: translateY(0); + + .vf-chatbot-modal__content { + display: flex; + flex-direction: column; + flex: 1; + } + } + + &--minimized { + display: flex; + flex-direction: column; + height: 60px; + opacity: 1; + transform: translateY(0); + overflow: hidden; + + .vf-chatbot-modal__content { + visibility: hidden; + height: 0; + } + } + + &__header { + height: 60px; + min-height: 60px; // Add this to prevent header from shrinking + padding: 0 16px; + background: #ffffff; // White background + border-bottom: 1px solid #E5E5E5; + color: #000000; + display: flex; + align-items: center; + justify-content: space-between; + border-radius: 16px 16px 0 0; + + &-left { + display: flex; + align-items: center; + gap: 8px; + } + } + + &__title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + display: flex; + align-items: center; + gap: 8px; + + img { + width: 24px; + height: 24px; + } + } + + &__content { + display: flex; + flex-direction: column; + flex: 1; + transition: visibility 0.3s ease, height 0.3s ease; + } + + &__messages { + flex: 1; + overflow-y: auto; + padding: 16px; + background: #F5F5F5; + } + + &__input-area { + background: #ffffff; + border-top: 1px solid #E5E5E5; + } + + &__input-wrapper { + position: relative; + } + + &__input { + width: 100%; + padding-left: 20px; + padding-right: 44px; // Space for the send button + border: 1px solid #E5E5E5; + font-size: 14px; + line-height: 1.5; + resize: none; + min-height: 44px; + max-height: 120px; + background: #F5F5F5; + + &:focus { + outline: none; + // border-color: #007AFF; + background: #ffffff; + } + + &::placeholder { + color: #666666; + } + } + + &__send-button { + position: absolute; + right: 0px; + height: 100%; + top: 50%; + transform: translateY(-50%); + background: #007AFF; + color: #ffffff; + border: none; + padding: 8px; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + } + + &__controls { + display: flex; + gap: 8px; + + button { + background: none; + border: none; + padding: 8px; + cursor: pointer; + color: #666666; + + &:hover { + color: #1A1A1A; + } + } + } + + // Smooth transition for minimize/maximize + &__content { + transition: all 0.2s ease; + } + + // Add minimized state styles + &--minimized { + height: 60px !important; // Override default height + + .vf-chatbot-modal__content { + display: none; + } + + .vf-chatbot-modal__header { + border-bottom: none; + padding-bottom: 0; + } + + .vf-chatbot-modal__title { + font-size: 1rem; + } + } + + @media (max-width: 480px) { + width: calc(100% - 40px); + height: calc(100vh - 100px); + bottom: 70px; + + &--minimized { + height: 60px; + } + } +} + +.vf-loading-spinner { + animation: rotate 2s linear infinite; + width: 20px; + height: 20px; + + & .path { + stroke: currentColor; + stroke-linecap: round; + animation: dash 1.5s ease-in-out infinite; + } +} + +@keyframes rotate { + 100% { + transform: rotate(360deg); + } +} + +@keyframes dash { + 0% { + stroke-dasharray: 1, 150; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -35; + } + 100% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -124; + } +} + +// Message styles +.vf-chatbot-message { + margin-bottom: 16px; + max-width: 85%; + + &--user { + margin-left: auto; + + .vf-chatbot-message__content { + background: #1A1A1A; + color: #ffffff; + border-radius: 16px 16px 16px 16px; + } + } + + &--assistant { + margin-right: auto; + display: flex; + align-items: flex-start; + gap: 8px; + + .vf-chatbot-message__avatar { + width: 24px; + height: 24px; + border-radius: 50%; + } + + .vf-chatbot-message__content { + background: #ffffff; + color: #1A1A1A; + border-radius: 16px 16px 16px 16px; + } + } + + &__content { + padding: 12px 16px; + font-size: 14px; + line-height: 1.5; + } +} + +// Suggestion area +.vf-chatbot-suggestions { + padding: 16px; + background: #ffffff; + border-top: 1px solid #E5E5E5; + + &__input { + width: 100%; + padding: 12px 16px; + background: #F5F5F5; + border: none; + border-radius: 8px; + color: #666666; + font-size: 14px; + cursor: pointer; + text-align: left; + + &:hover { + background: darken(#F5F5F5, 5%); + } + } +} + +.vf-chatbot-trigger { + position: fixed; + bottom: 20px; + right: 20px; + padding: 12px 24px; + background: var(--vf-color-primary); + color: white; + border: none; + border-radius: 24px; + cursor: pointer; + z-index: 998; + + &:hover { + background: var(--vf-color-primary-dark); + } +} + +.vf-chatbot-modal__title img { + width: 24px; + height: 24px; + margin-right: 8px; + vertical-align: middle; +} + +.vf-chatbot-message--assistant img.vf-chatbot-message__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + background-color: #fff; + object-fit: contain; + padding: 0; + border: 1px solid #eee; +} diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.scss b/components/vf-chatbot-prompt/vf-chatbot-prompt.scss new file mode 100644 index 0000000000..7f31a20a2f --- /dev/null +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.scss @@ -0,0 +1,80 @@ +.vf-chatbot-prompt { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 16px; + + &__message { + padding: 12px 16px; + border-radius: 12px; + max-width: 80%; + line-height: 1.4; + + &--user { + background: var(--vf-color-gray-100); + align-self: flex-end; + } + + &--system { + background: var(--vf-color-primary-light); + align-self: flex-start; + + // Style for rich text content + p { + margin: 0 0 8px 0; + &:last-child { + margin-bottom: 0; + } + } + + code { + background: rgba(0, 0, 0, 0.05); + padding: 2px 4px; + border-radius: 4px; + } + + pre { + background: rgba(0, 0, 0, 0.05); + padding: 8px; + border-radius: 4px; + overflow-x: auto; + } + } + } + + &__loading { + align-self: flex-start; + display: flex; + gap: 4px; + padding: 12px 16px; + background: var(--vf-color-primary-light); + border-radius: 12px; + border-bottom-left-radius: 4px; + } + + &__dot { + width: 8px; + height: 8px; + background: var(--vf-color-gray-600); + border-radius: 50%; + opacity: 0.3; + animation: dot-flash 1.4s infinite; + + &:nth-child(2) { + animation-delay: 0.2s; + } + + &:nth-child(3) { + animation-delay: 0.4s; + } + } +} + +@keyframes dot-flash { + 0%, 60%, 100% { + opacity: 0.3; + } + 30% { + opacity: 1; + } +} diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.js b/components/vf-chatbot-standalone/vf-chatbot-standalone.js new file mode 100644 index 0000000000..ad264ed360 --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.js @@ -0,0 +1,334 @@ +// vf-chatbot-standalone.js +class VFChatbotStandalone { + constructor(element) { + console.log("Initializing standalone chatbot..."); // Debug log + + // Store DOM elements + this.container = element; + this.welcomeScreen = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome]" + ); + this.chatInterface = this.container.querySelector( + "[data-vf-js-chatbot-standalone-chat]" + ); + this.messagesContainer = this.container.querySelector( + "[data-vf-js-chatbot-standalone-messages]" + ); + this.loadingIndicator = this.container.querySelector( + "[data-vf-js-chatbot-standalone-loading]" + ); + this.input = this.container.querySelector( + "[data-vf-js-chatbot-standalone-input]" + ); + this.sendBtn = this.container.querySelector( + "[data-vf-js-chatbot-standalone-send]" + ); + this.welcomeInput = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome-input]" + ); + this.welcomeSendBtn = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome-send]" + ); + this.suggestionBtns = this.container.querySelectorAll( + "[data-vf-js-chatbot-standalone-suggestion]" + ); + + // API configuration - Mistral AI + this.API_TOKEN = ""; + this.API_URL = "https://api.mistral.ai/v1/chat/completions"; + + // State + this.hasInteracted = false; + + this.bindEvents(); + this.initAutoResize(); + + console.log("Standalone chatbot initialized successfully"); // Debug log + } + + bindEvents() { + console.log("Binding events for standalone chatbot..."); // Debug log + + // Send message events + this.sendBtn?.addEventListener("click", () => this.sendMessage()); + this.input?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendMessage(); + } + }); + + // Welcome screen input events + this.welcomeSendBtn?.addEventListener("click", () => + this.sendWelcomeMessage() + ); + this.welcomeInput?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendWelcomeMessage(); + } + }); + + // Welcome screen suggestion buttons + this.suggestionBtns.forEach(btn => { + btn.addEventListener("click", () => { + const text = + btn.getAttribute("data-vf-js-chatbot-standalone-suggestion") || + btn.textContent.trim(); + + // Show chat interface + this.showChatInterface(); + + // Update the input field with the suggestion text + if (this.input && text) { + this.input.value = text; + + // Adjust the height of the input field to match content + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + } + + // Send the message to the API + if (text) { + this.sendUserMessage(text); + } + }); + }); + + // Listen for action prompt clicks + this.container.addEventListener("vf-chatbot-action-prompt:click", event => { + const { text, data } = event.detail; + + // Show chat interface + this.showChatInterface(); + + // Update the input field with the suggestion text + if (this.input && text) { + this.input.value = text; + + // Adjust the height of the input field to match content + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + } + + // Send the message to the API + if (text) { + this.sendUserMessage(text); + } + }); + } + + initAutoResize() { + // Auto-resize textarea as user types + if (this.input) { + this.input.addEventListener("input", () => { + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + }); + } + } + + sendMessage() { + if (!this.input || !this.input.value.trim()) return; + + const text = this.input.value.trim(); + this.sendUserMessage(text); + } + + sendWelcomeMessage() { + if (!this.welcomeInput || !this.welcomeInput.value.trim()) return; + + const text = this.welcomeInput.value.trim(); + this.showChatInterface(); + this.sendUserMessage(text); + } + + showChatInterface() { + if (this.welcomeScreen) { + this.welcomeScreen.style.display = "none"; + } + if (this.chatInterface) { + this.chatInterface.style.display = "block"; + } + + // Focus on the input field + if (this.input) { + this.input.focus(); + } + + this.hasInteracted = true; + } + + sendUserMessage(text) { + if (!text || !this.messagesContainer) return; + + // Add user message to UI + const userMessageEl = document.createElement("div"); + userMessageEl.className = "vf-chatbot-message vf-chatbot-message--user"; + userMessageEl.innerHTML = ` +
${text}
+ `; + this.messagesContainer.appendChild(userMessageEl); + + // Clear input if this came from the input field + if (this.input && this.input.value === text) { + this.input.value = ""; + this.input.style.height = "auto"; // Reset height + } + + this.scrollToBottom(); + + // Process the message + this.processUserMessage(text); + } + + processUserMessage(text) { + // Show loading state + this.setLoadingState(true); + + // Call the API + this.callAPI(text) + .then(response => { + this.addAssistantResponse(response.html || response); + this.setLoadingState(false); + }) + .catch(error => { + console.error("API Error:", error); + // Fallback to simulated response if API fails + this.addAssistantResponse(this.getSimulatedResponse(text)); + this.setLoadingState(false); + }); + } + + callAPI(text) { + return new Promise((resolve, reject) => { + fetch(this.API_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${this.API_TOKEN}` + }, + body: JSON.stringify({ + model: "mistral-tiny", // or another available model + messages: [ + { role: "system", content: "You are a helpful assistant." }, + { role: "user", content: text } + ] + }) + }) + .then(response => { + if (!response.ok) { + throw new Error(`API error: ${response.status}`); + } + return response.json(); + }) + .then(data => { + // Mistral returns: { choices: [{ message: { content: "..." } }] } + if (data && data.choices && data.choices[0] && data.choices[0].message && data.choices[0].message.content) { + resolve(data.choices[0].message.content); + } else { + reject(new Error("Invalid API response")); + } + }) + .catch(error => { + console.error("API call failed:", error); + reject(error); + }); + }); + } + + addAssistantResponse(text) { + if (!text || !this.messagesContainer) return; + + // Add assistant message to UI + const assistantMessageEl = document.createElement("div"); + assistantMessageEl.className = + "vf-chatbot-message vf-chatbot-message--assistant"; + assistantMessageEl.innerHTML = ` +
+ AI Assistant +
+
${text}
+ `; + this.messagesContainer.appendChild(assistantMessageEl); + + this.scrollToBottom(); + } + + setLoadingState(isLoading) { + if (this.loadingIndicator) { + this.loadingIndicator.style.display = isLoading ? "flex" : "none"; + } + + if (this.sendBtn) { + this.sendBtn.disabled = isLoading; + } + + if (this.input) { + this.input.disabled = isLoading; + } + + this.scrollToBottom(); + } + + scrollToBottom() { + if (this.messagesContainer) { + this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + } + } + + getSimulatedResponse(text) { + // Fallback responses when API fails + const fallbackResponses = [ + "I'm sorry, I'm having trouble connecting to my knowledge base right now. Could you try again in a moment?", + "That's an interesting question. Let me think about how to best answer that for you.", + "I understand you're asking about bioinformatics training. We have several resources available. Could you tell me more about your specific interests?", + "Thank you for your question. We offer various workshops and online courses on that topic. Would you like me to provide more specific information?", + "I'd be happy to help with that. We have both introductory and advanced courses available depending on your experience level." + ]; + + return fallbackResponses[ + Math.floor(Math.random() * fallbackResponses.length) + ]; + } +} + +// Initialize +function initVFChatbotStandalone() { + console.log("Looking for standalone chatbot elements..."); // Debug log + const chatbotElements = document.querySelectorAll( + "[data-vf-js-chatbot-standalone]" + ); + + if (chatbotElements.length === 0) { + console.warn("No standalone chatbot elements found on page"); + return; + } + + console.log(`Found ${chatbotElements.length} standalone chatbot elements`); // Debug log + + // Initialize each standalone chatbot element + const instances = []; + chatbotElements.forEach(element => { + instances.push(new VFChatbotStandalone(element)); + }); + + return instances; +} + +// Make initialization function available globally +if (typeof window !== "undefined") { + window.VFChatbotStandalone = VFChatbotStandalone; + window.initVFChatbotStandalone = initVFChatbotStandalone; + + // Also make it available as a global variable without window prefix + if (typeof globalThis !== "undefined") { + globalThis.VFChatbotStandalone = VFChatbotStandalone; + globalThis.initVFChatbotStandalone = initVFChatbotStandalone; + } + + console.log("Exposed initVFChatbotStandalone to global scope"); +} + +// Export both the class and the initialization function +export { VFChatbotStandalone, initVFChatbotStandalone }; diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk new file mode 100644 index 0000000000..2493219f95 --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk @@ -0,0 +1,121 @@ + +
+
+
+
+

+ + AI Assistant + {{ title | default("AI assistant") }} +

+
+
+ +
+ + +
+ +
+ + {% if welcome_message %} + +
+
+ +

{{ welcome_title | default('AI assistant') }}

+

+ {{ welcome_description | default("Welcome! I'm here to help you discover bioinformatics training and resources.") }} +

+ +
+

Try asking me:

+
+ {% for suggestion in welcome_suggestions %} + {% if loop.index == welcome_suggestions.length and welcome_suggestions.length > 2 %} + {% render '@vf-chatbot-action-prompt', { + action_text: suggestion, + action_data: suggestion, + modifier_class: "vf-chatbot-action-prompt--full-width", + data_attribute: "data-vf-js-chatbot-standalone-suggestion=" + suggestion, + data_vf_js_chatbot_action_prompt: true + } %} + {% else %} + {% render '@vf-chatbot-action-prompt', { + action_text: suggestion, + action_data: suggestion, + data_attribute: "data-vf-js-chatbot-standalone-suggestion=" + suggestion, + data_vf_js_chatbot_action_prompt: true + } %} + {% endif %} + {% endfor %} +
+
+
+
+ {#
+
+ AI Assistant +
+
+ {{ welcome_message | default('Hello! How can I help you today?') }} +
+
#} + {% endif %} + +
+ + + + + + {#
+
+ + +
+
#} +
+
+ + +
+
+
+
+
+
diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss new file mode 100644 index 0000000000..fc6a67d3e5 --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss @@ -0,0 +1,405 @@ +// vf-chatbot-standalone.scss + +.vf-chatbot-standalone { + display: flex; + flex-direction: column; + width: 100%; + height: 100vh; + + &__container { + display: flex; + flex-direction: column; + height: 100%; + margin: 10px; + background: #ffffff; + + @media (max-width: 1200px) { + max-width: 100%; + } + } + + &__header { + height: 64px; + min-height: 64px; + background: #ffffff; + color: #000000; + display: flex; + align-items: center; + justify-content: space-between; + + @media (max-width: 768px) { + padding: 0 16px; + } + } + + &__header-left { + display: flex; + align-items: center; + gap: 12px; + } + + &__title { + font-size: 18px; + font-weight: 500; + color: #1A1A1A; + display: flex; + align-items: center; + gap: 12px; + margin: 0; + + img { + width: 28px; + height: 28px; + } + } + + &__controls { + display: flex; + gap: 8px; + + button { + background: none; + border: none; + padding: 8px; + cursor: pointer; + color: #666666; + + &:hover { + color: #1A1A1A; + } + } + } + + &__content { + display: flex !important; + flex-direction: column; + flex: 1; + overflow: hidden; + background: #F5F5F5; + justify-content: center; + border-radius: 16px 16px 16px 16px; + } + + // Welcome screen styles + &__welcome { + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 24px; + + &-content { + max-width: 65%; + width: 100%; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + } + + &-logo { + margin-bottom: 16px; + + img { + width: 48px; + height: 48px; + } + } + + &-title { + font-size: 24px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 12px 0; + } + + &-description { + font-size: 16px; + line-height: 1.5; + color: #666666; + margin: 0 0 32px 0; + max-width: 450px; + } + + &-suggestions { + margin-top: 16px; + width: 100%; + + &-title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 16px 0; + } + + &-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + + @media (max-width: 480px) { + grid-template-columns: 1fr; + } + } + } + + &-suggestion { + padding: 12px 16px; + background: #FFFFFF; + border: 1px solid #E5E5E5; + border-radius: 8px; + font-size: 14px; + color: #1A1A1A; + cursor: pointer; + transition: background 0.2s ease, border-color 0.2s ease; + text-align: left; + + &:hover { + background: #F0F0F0; + border-color: #CCCCCC; + } + } + + &-input-container { + margin-top: 32px; + width: 100%; + max-width: 500px; + } + + &-input-wrapper { + position: relative; + width: 100%; + display: flex; + align-items: center; + background: #FFFFFF; + border: 1px solid #E5E5E5; + border-radius: 8px; + overflow: hidden; + } + + &-input { + flex: 1; + padding: 16px; + border: none; + font-size: 16px; + line-height: 1.5; + background: transparent; + + &:focus { + outline: none; + } + + &::placeholder { + color: #666666; + } + } + + &-send-button { + background: #007AFF; + color: #ffffff; + border: none; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + + svg { + width: 24px; + height: 24px; + } + } + } + + &__messages { + flex: 1; + overflow-y: auto; + padding: 24px; + background: #F5F5F5; + + @media (max-width: 768px) { + padding: 16px; + } + } + + &__input-area { + padding: 16px 24px; + background: #ffffff; + border-top: 1px solid #E5E5E5; + + @media (max-width: 768px) { + padding: 12px 16px; + } + } + + &__input-wrapper { + position: relative; + width: 70%; + margin: 0 auto; + } + + &__input { + width: 100%; + padding: 0px; + border: none; + font-size: 16px; + line-height: 1.5; + resize: none; + min-height: 40px; + max-height: 150px; + background: #FFFFFF; + + &::placeholder { + color: #666666; + } + } + + &__send-button { + position: absolute; + right: 0px; + top: 50%; + transform: translateY(-50%); + background: #007AFF; + color: #ffffff; + border: none; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + + svg { + width: 24px; + height: 24px; + } + } + + &__welcome-suggestions { + margin: 24px 0; + + &-title { + font-weight: 500; + margin-bottom: 12px; + } + + &-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + justify-items: center; // Center items horizontally + + // Make the last item span full width if it's the 3rd item + & > *:nth-child(3):last-child { + grid-column: 1 / -1; + justify-self: center; // Center the full-width item + } + + // Ensure each grid cell only takes the width it needs + & > * { + width: auto; + min-width: min-content; + } + } + } + + &__chat { + display: flex; + flex-direction: column; + height: 80vh; /* Or use: calc(100vh - [header+footer heights]) for more precise fit */ + max-height: 80vh; + min-height: 400px; + // background: #fff; + // border-radius: 1rem; + // box-shadow: 0 2px 8px rgba(0,0,0,0.04); + // overflow: hidden; + } + + &__messages { + flex: 1 1 auto; + overflow-y: auto; + padding: 1rem; + min-height: 0; /* Required for flex children to scroll */ + } +} + +// Reuse message styles from the modal component +.vf-chatbot-message { + margin-bottom: 24px; + max-width: 85%; + + @media (max-width: 768px) { + max-width: 90%; + } + + &--user { + margin-left: auto; + + .vf-chatbot-message__content { + background: #1A1A1A; + color: #ffffff; + border-radius: 16px 16px 16px 16px; + } + } + + &--assistant { + margin-right: auto; + display: flex; + align-items: flex-start; + gap: 12px; + + .vf-chatbot-message__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + } + + .vf-chatbot-message__content { + background: #ffffff; + color: #1A1A1A; + border-radius: 16px 16px 16px 16px; + } + } + + &__content { + padding: 16px; + font-size: 16px; + line-height: 1.5; + } +} + +.vf-chatbot-standalone__title img { + width: 24px; + height: 24px; + margin-right: 8px; + vertical-align: middle; +} + +.vf-chatbot-standalone__welcome-logo img { + width: 64px; + height: 64px; + margin-bottom: 16px; + object-fit: contain; +} + +.vf-chatbot-message--assistant img.vf-chatbot-message__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + background-color: #fff; + object-fit: contain; + padding: 0; + border: 1px solid #eee; +} From 817515721936f8d97043fb7b77b2dae470ac131f Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Wed, 21 May 2025 14:09:10 +0100 Subject: [PATCH 03/71] VF - Chatbot initial code --- .../vf-chatbot-modal/vf-chatbot-modal.js | 278 ++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 components/vf-chatbot-modal/vf-chatbot-modal.js diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.js b/components/vf-chatbot-modal/vf-chatbot-modal.js new file mode 100644 index 0000000000..bc2f5c7f28 --- /dev/null +++ b/components/vf-chatbot-modal/vf-chatbot-modal.js @@ -0,0 +1,278 @@ +// vf-chatbot-modal + +class VFChatbotModal { + constructor(element) { + console.log("Initializing chatbot modal..."); // Debug log + + // API configuration + this.API_TOKEN = ""; + this.API_URL = + "https://api-inference.huggingface.co/models/facebook/blenderbot-400M-distill"; + + // Store DOM elements + this.modal = element; + this.trigger = document.querySelector("[data-vf-js-chatbot-trigger]"); + this.closeBtn = this.modal.querySelector("[data-vf-js-chatbot-close]"); + this.minimizeBtn = this.modal.querySelector( + "[data-vf-js-chatbot-minimize]" + ); + this.input = this.modal.querySelector(".vf-chatbot-modal__input"); + this.sendBtn = this.modal.querySelector("[data-vf-js-chatbot-send]"); + this.messagesContainer = this.modal.querySelector( + ".vf-chatbot-modal__messages" + ); + this.welcomeScreen = this.modal.querySelector( + "[data-vf-js-chatbot-welcome]" + ); + this.suggestionBtns = this.modal.querySelectorAll( + "[data-vf-js-chatbot-suggestion]" + ); + + // State + this.hasInteracted = false; + + this.bindEvents(); + } + + bindEvents() { + console.log("Binding events..."); // Debug log + + // Toggle modal + this.trigger?.addEventListener("click", () => this.toggleModal()); + this.closeBtn?.addEventListener("click", e => { + e.stopPropagation(); + this.closeModal(); + }); + this.minimizeBtn?.addEventListener("click", e => { + e.stopPropagation(); + this.minimize(); + }); + + // Send message events + this.sendBtn?.addEventListener("click", () => this.sendMessage()); + this.input?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendMessage(); + } + }); + + // Welcome screen events + if (this.welcomeScreen) { + this.welcomeScreen.addEventListener("vf-chatbot-welcome:closed", () => { + this.showChatInterface(); + }); + + this.welcomeScreen.addEventListener( + "vf-chatbot-welcome:suggestion", + event => { + const { text } = event.detail; + this.showChatInterface(); + this.sendUserMessage(text); + } + ); + } + + // Suggestion buttons + this.suggestionBtns.forEach(btn => { + btn.addEventListener("click", () => { + const text = + btn.getAttribute("data-vf-js-chatbot-suggestion") || + btn.textContent.trim(); + this.sendUserMessage(text); + }); + }); + } + + showChatInterface() { + if (this.welcomeScreen) { + this.welcomeScreen.style.display = "none"; + } + + this.messagesContainer.style.display = "block"; + this.input.focus(); + this.hasInteracted = true; + } + + resetWelcomeScreen() { + if (this.welcomeScreen && !this.hasInteracted) { + this.welcomeScreen.style.display = "flex"; + this.messagesContainer.style.display = "none"; + } + } + + minimize() { + this.modal.classList.add("vf-chatbot-modal--minimized"); + this.modal.classList.remove("vf-chatbot-modal--active"); + + // Dispatch minimize event + this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:minimize")); + } + + maximize() { + // First remove minimized to ensure smooth transition + this.modal.classList.remove("vf-chatbot-modal--minimized"); + + // Small delay to ensure CSS transition works properly + requestAnimationFrame(() => { + this.modal.classList.add("vf-chatbot-modal--active"); + + // Focus on input if it exists + const input = this.modal.querySelector(".vf-chatbot-modal__input"); + if (input) { + setTimeout(() => input.focus(), 300); + } + }); + + // Dispatch maximize event + this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:maximize")); + + // Focus on input if welcome screen is not shown + if (this.hasInteracted) { + setTimeout(() => this.input.focus(), 300); + } + } + + closeModal() { + this.modal.classList.remove("vf-chatbot-modal--active"); + this.modal.classList.remove("vf-chatbot-modal--minimized"); + + // Reset welcome screen for next open + this.resetWelcomeScreen(); + + // Dispatch close event + this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:close")); + } + + toggleModal() { + const isMinimized = this.modal.classList.contains( + "vf-chatbot-modal--minimized" + ); + const isActive = this.modal.classList.contains("vf-chatbot-modal--active"); + + if (isMinimized || !isActive) { + this.maximize(); + } else { + this.minimize(); + } + } + + sendUserMessage(text) { + // Add user message to UI + const userMessageEl = document.createElement("div"); + userMessageEl.className = "vf-chatbot-message vf-chatbot-message--user"; + userMessageEl.innerHTML = ` +
${text}
+ `; + this.messagesContainer.appendChild(userMessageEl); + + // Clear input if this came from the input field + if (this.input.value === text) { + this.input.value = ""; + } + + this.scrollToBottom(); + + // Process the message (simulate response) + this.processUserMessage(text); + } + + sendMessage() { + const text = this.input.value.trim(); + if (!text) return; + + this.sendUserMessage(text); + } + + async processUserMessage(message) { + // Show loading state + this.setLoadingState(true); + + try { + const response = await this.callAPI(message); + console.log("API Response:", response); // Debug log + this.addMessage(response, "system"); + } catch (error) { + console.error("Error:", error); + this.addMessage( + "Sorry, I encountered an error. Please try again.", + "system" + ); + } + + // // Simulate API call with timeout + setTimeout(() => { + // Add assistant response + this.addAssistantResponse(this.getSimulatedResponse(message)); + this.setLoadingState(false); + }, 1000); + } + + addAssistantResponse(text) { + const assistantMessageEl = document.createElement("div"); + assistantMessageEl.className = + "vf-chatbot-message vf-chatbot-message--assistant"; + assistantMessageEl.innerHTML = ` + AI Assistant +
${text}
+ `; + this.messagesContainer.appendChild(assistantMessageEl); + + this.scrollToBottom(); + } + + getSimulatedResponse(text) { + // Simple response simulation + if (text.toLowerCase().includes("metabolomics")) { + return "Metabolomics is the large-scale study of small molecules,"; + } else if (text.toLowerCase().includes("genomics")) { + return "Genomics is the study of the structure, function, evolution, and mapping of genomes."; + } else if (text.toLowerCase().includes("proteomics")) { + return "Proteomics is the study of the structure, function, and regulation of the proteome."; + } else if (text.toLowerCase().includes("transcriptomics")) { + return "Transcriptomics is the study of the complete set of RNA molecules within a cell."; + } else if (text.toLowerCase().includes("epigenomics")) { + return "Epigenomics is the study of heritable changes in gene function that do not involve changes to the DNA sequence."; + } else if (text.toLowerCase().includes("metabolomics")) { + return "Metabolomics is the large-scale study of small molecules,"; + } else if (text.toLowerCase().includes("genomics")) { + return "Genomics is the study of the structure, function, evolution, and mapping of genomes."; + } else if (text.toLowerCase().includes("proteomics")) { + return "Proteomics is the study of the structure, function, and regulation of the proteome."; + } else if (text.toLowerCase().includes("transcriptomics")) { + return "Transcriptomics is the study of the complete set of RNA molecules within a cell."; + } else if (text.toLowerCase().includes("epigenomics")) { + return "Epigenomics is the study of heritable changes in gene function that do not involve changes to the DNA sequence."; + } else { + return "I'm sorry, I didn't understand that. Could you please provide more context or ask a specific question?"; + } + } + + setLoadingState(isLoading) { + this.input.disabled = isLoading; + this.sendBtn.disabled = isLoading; + this.sendBtn.innerHTML = isLoading ? "Sending..." : "Send"; + } + + scrollToBottom() { + this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + } +} + +// Initialize +function initVFChatbotModal() { + console.log("Looking for chatbot elements..."); // Debug log + const chatbotElements = document.querySelectorAll( + "[data-vf-js-chatbot-modal]" + ); + + if (chatbotElements.length === 0) { + console.warn("No chatbot elements found on page"); + return; + } + + console.log(`Found ${chatbotElements.length} chatbot elements`); // Debug log + chatbotElements.forEach(element => new VFChatbotModal(element)); +} + +export { VFChatbotModal, initVFChatbotModal }; From 993243455f7d29548dc3af7a5cad2af7922c3743 Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Wed, 21 May 2025 14:24:19 +0100 Subject: [PATCH 04/71] Vf chatbot --- components/vf-chatbot-action-prompt/README.md | 107 + .../vf-chatbot-action-prompt/index.scss | 5 + .../vf-chatbot-action-prompt/package.json | 14 + .../vf-chatbot-action-prompt.js | 67 + .../vf-chatbot-action-prompt.njk | 37 + .../vf-chatbot-action-prompt.scss | 59 + .../vf-chatbot-action-prompt.variables.scss | 12 + components/vf-chatbot-fab/README.md | 44 + components/vf-chatbot-fab/package.json | 14 + components/vf-chatbot-fab/vf-chatbot-fab.js | 53 + components/vf-chatbot-fab/vf-chatbot-fab.njk | 20 + components/vf-chatbot-fab/vf-chatbot-fab.scss | 28 + components/vf-chatbot-modal/README.md | 54 + components/vf-chatbot-modal/api-handler.js | 53 + components/vf-chatbot-modal/package.json | 7 + .../vf-chatbot-modal/vf-chatbot-modal.js | 278 +++ .../vf-chatbot-modal/vf-chatbot-modal.njk | 91 + .../vf-chatbot-modal/vf-chatbot-modal.scss | 321 +++ components/vf-chatbot-prompt/package.json | 14 + .../vf-chatbot-prompt/vf-chatbot-prompt.js | 68 + .../vf-chatbot-prompt/vf-chatbot-prompt.njk | 19 + .../vf-chatbot-prompt/vf-chatbot-prompt.scss | 80 + components/vf-chatbot-standalone/README.md | 51 + components/vf-chatbot-standalone/package.json | 15 + .../vf-chatbot-standalone.config.yml | 9 + .../vf-chatbot-standalone.js | 333 +++ .../vf-chatbot-standalone.njk | 121 ++ .../vf-chatbot-standalone.scss | 404 ++++ .../vf-chatbot-welcome/vf-chatbot-welcome.js | 59 + .../vf-chatbot-welcome/vf-chatbot-welcome.njk | 41 + .../vf-chatbot-welcome.scss | 139 ++ .../vf-chatbot/assets/ai-assistant-icon.svg | 67 + components/vf-chatbot/package.json | 16 + components/vf-chatbot/vf-chatbot.js | 102 + components/vf-chatbot/vf-chatbot.njk | 16 + components/vf-chatbot/vf-chatbot.scss | 54 + components/vf-componenet-rollup/index.scss | 14 + .../vf-componenet-rollup/scripts copy.js | 115 ++ components/vf-componenet-rollup/scripts.js | 26 + .../src/site/_includes/layouts/base.njk | 7 + .../src/site/chatbot/index.njk | 58 + tools/vf-component-library/yarn.lock | 1801 ++++++++++------- 42 files changed, 4107 insertions(+), 786 deletions(-) create mode 100644 components/vf-chatbot-action-prompt/README.md create mode 100644 components/vf-chatbot-action-prompt/index.scss create mode 100644 components/vf-chatbot-action-prompt/package.json create mode 100644 components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js create mode 100644 components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk create mode 100644 components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss create mode 100644 components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.variables.scss create mode 100644 components/vf-chatbot-fab/README.md create mode 100644 components/vf-chatbot-fab/package.json create mode 100644 components/vf-chatbot-fab/vf-chatbot-fab.js create mode 100644 components/vf-chatbot-fab/vf-chatbot-fab.njk create mode 100644 components/vf-chatbot-fab/vf-chatbot-fab.scss create mode 100644 components/vf-chatbot-modal/README.md create mode 100644 components/vf-chatbot-modal/api-handler.js create mode 100644 components/vf-chatbot-modal/package.json create mode 100644 components/vf-chatbot-modal/vf-chatbot-modal.js create mode 100644 components/vf-chatbot-modal/vf-chatbot-modal.njk create mode 100644 components/vf-chatbot-modal/vf-chatbot-modal.scss create mode 100644 components/vf-chatbot-prompt/package.json create mode 100644 components/vf-chatbot-prompt/vf-chatbot-prompt.js create mode 100644 components/vf-chatbot-prompt/vf-chatbot-prompt.njk create mode 100644 components/vf-chatbot-prompt/vf-chatbot-prompt.scss create mode 100644 components/vf-chatbot-standalone/README.md create mode 100644 components/vf-chatbot-standalone/package.json create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.js create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.njk create mode 100644 components/vf-chatbot-standalone/vf-chatbot-standalone.scss create mode 100644 components/vf-chatbot-welcome/vf-chatbot-welcome.js create mode 100644 components/vf-chatbot-welcome/vf-chatbot-welcome.njk create mode 100644 components/vf-chatbot-welcome/vf-chatbot-welcome.scss create mode 100644 components/vf-chatbot/assets/ai-assistant-icon.svg create mode 100644 components/vf-chatbot/package.json create mode 100644 components/vf-chatbot/vf-chatbot.js create mode 100644 components/vf-chatbot/vf-chatbot.njk create mode 100644 components/vf-chatbot/vf-chatbot.scss create mode 100644 components/vf-componenet-rollup/scripts copy.js create mode 100644 tools/vf-component-library/src/site/chatbot/index.njk diff --git a/components/vf-chatbot-action-prompt/README.md b/components/vf-chatbot-action-prompt/README.md new file mode 100644 index 0000000000..6d7972145c --- /dev/null +++ b/components/vf-chatbot-action-prompt/README.md @@ -0,0 +1,107 @@ +# Chatbot Action Prompt component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-action-prompt.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-action-prompt) + +## About + +The action prompt component for the Visual Framework chatbot. This component provides interactive links that can be used in the chatbot interface for various purposes such as: + +- Suggestion links in the welcome screen +- Action links within chat messages +- Call-to-action links +- Form submission triggers + +All action prompts are rendered as links with consistent styling, regardless of their function. + +## Usage + +### JavaScript + +```js +import { initVFChatbotActionPrompt } from '@visual-framework/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; +// Or import directly +// import { initVFChatbotActionPrompt } from '../components/raw/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; + +initVFChatbotActionPrompt(); +``` + +### Nunjucks template + +Basic action: +```njk +{% render '@vf-chatbot-action-prompt', { + action_text: "Find workshops near research institutions", + action_data: "find_workshops" +} %} +``` + +External link: +```njk +{% render '@vf-chatbot-action-prompt', { + action_type: "link", + action_text: "Visit our website", + action_url: "https://example.com", + action_target: "_blank" +} %} +``` + +Phone link: +```njk +{% render '@vf-chatbot-action-prompt', { + action_type: "phone", + action_text: "Call support", + action_phone: "+1234567890" +} %} +``` + +Form submit link: +```njk +{% render '@vf-chatbot-action-prompt', { + action_type: "form", + action_text: "Submit", + action_form: "contact-form" +} %} +``` + +## Install + +```bash +yarn add --dev @visual-framework/vf-chatbot-action-prompt +``` + +### Sass/CSS + +The style files included are written in [Sass](https://sass-lang.com/). If you're using a VF-core project, you can import it like this: + +```scss +@import "@visual-framework/vf-chatbot-action-prompt/index.scss"; +``` + +## Options + +| Option | Type | Required | Default | Description | +|--------|------|----------|---------|-------------| +| `action_text` | string | Yes | - | The text to display on the link | +| `action_type` | string | No | "button" | Type of action: "button", "link", "phone", or "form" | +| `action_url` | string | No | - | URL for link type actions | +| `action_target` | string | No | - | Target for link type actions (e.g., "_blank") | +| `action_phone` | string | No | - | Phone number for phone type actions | +| `action_form` | string | No | - | Form ID for form submit actions | +| `action_data` | string | No | - | Custom data to be included in the click event | +| `modifier_class` | string | No | - | Additional CSS classes (e.g., "vf-chatbot-action-prompt--small") | + +## Events + +The component dispatches a custom event when clicked: + +```javascript +document.addEventListener('vf-chatbot-action-prompt:click', function(event) { + console.log('Link text:', event.detail.text); + console.log('Link data:', event.detail.data); + + // Handle the action based on the data + if (event.detail.data === 'find_workshops') { + // Do something specific for this action + } +}); +``` diff --git a/components/vf-chatbot-action-prompt/index.scss b/components/vf-chatbot-action-prompt/index.scss new file mode 100644 index 0000000000..4835d1b007 --- /dev/null +++ b/components/vf-chatbot-action-prompt/index.scss @@ -0,0 +1,5 @@ +// vf-chatbot-action-prompt + +@import 'package.variables.scss'; +@import 'vf-chatbot-action-prompt.variables.scss'; +@import 'vf-chatbot-action-prompt.scss'; \ No newline at end of file diff --git a/components/vf-chatbot-action-prompt/package.json b/components/vf-chatbot-action-prompt/package.json new file mode 100644 index 0000000000..117909d473 --- /dev/null +++ b/components/vf-chatbot-action-prompt/package.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-action-prompt", + "description": "Visual Framework Chatbot Action Prompt component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-action-prompt.css", + "sass": "index.scss", + "main": "vf-chatbot-action-prompt.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} \ No newline at end of file diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js new file mode 100644 index 0000000000..fda8ee90fe --- /dev/null +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js @@ -0,0 +1,67 @@ +// vf-chatbot-action-prompt.js + +class VFChatbotActionPrompt { + constructor(element) { + this.el = element; + this.link = this.el.querySelector(".vf-chatbot-action-prompt__link"); + + if (this.link) { + this.bindEvents(); + } + } + + bindEvents() { + this.link.addEventListener("click", event => { + // If it's a placeholder link or form action + if ( + this.link.getAttribute("href") === "#" || + this.link.hasAttribute("data-vf-js-chatbot-action-form") || + this.link.hasAttribute("data-vf-js-chatbot-standalone-suggestion") + ) { + event.preventDefault(); + + // Handle form submission if needed + const formId = this.link.getAttribute("data-vf-js-chatbot-action-form"); + if (formId) { + const form = document.getElementById(formId); + if (form) { + form.submit(); + return; + } + } + + // Get suggestion text if available + const suggestionText = this.link.getAttribute("data-vf-js-chatbot-standalone-suggestion"); + + // Get action data if available + const actionData = this.link.getAttribute( + "data-vf-js-chatbot-action-data" + ) || suggestionText; + + // Dispatch custom event with action data + this.el.dispatchEvent( + new CustomEvent("vf-chatbot-action-prompt:click", { + bubbles: true, + detail: { + text: suggestionText || this.link.textContent.trim(), + data: actionData + } + }) + ); + } + }); + } +} + +// Initialize component +function initVFChatbotActionPrompt() { + const actionPrompts = document.querySelectorAll( + "[data-vf-js-chatbot-action-prompt]" + ); + + actionPrompts.forEach(actionPrompt => { + new VFChatbotActionPrompt(actionPrompt); + }); +} + +export { VFChatbotActionPrompt, initVFChatbotActionPrompt }; diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk new file mode 100644 index 0000000000..228eabee99 --- /dev/null +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk @@ -0,0 +1,37 @@ +
+ {% if action_type == "link" %} + + {{ action_text }} + + {% elif action_type == "phone" %} + + {{ action_text }} + + {% elif action_type == "form" %} + + {{ action_text }} + + {% else %} + + {{ action_text }} + + {% endif %} +
diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss new file mode 100644 index 0000000000..723d503938 --- /dev/null +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss @@ -0,0 +1,59 @@ +.vf-chatbot-action-prompt { + display: inline-block; + margin: 8px 8px 8px 0; + + &__link { + display: inline-block; + padding: 12px 16px; + border: 1px solid #4b7fd1; // Thin blue border + color: #4b7fd1; // Blue text + background-color: #FFFFFF; + font-size: 16px; + font-weight: 400; // Regular font weight + line-height: 1.2; + text-align: center; + text-decoration: none; // No underline + cursor: pointer; + transition: background-color 0.2s ease; + width: auto; // Width based on content + box-sizing: border-box; + white-space: nowrap; // Prevent text wrapping + + &:hover, &:focus { + background-color: rgba(75, 127, 209, 0.1); // Light blue background on hover + color: #4b7fd1; // Keep text blue on hover + text-decoration: none; // No underline on hover + outline: none; + } + + &:active { + transform: translateY(1px); + } + } + + // Variants + &--small { + .vf-chatbot-action-prompt__link { + padding: 8px 12px; + font-size: 14px; + } + } + + &--large { + .vf-chatbot-action-prompt__link { + padding: 16px 24px; + font-size: 18px; + } + } + + &--full-width { + display: block; + width: 100%; + + .vf-chatbot-action-prompt__link { + display: block; + width: 100%; + white-space: normal; // Allow text wrapping for full-width + } + } +} diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.variables.scss b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.variables.scss new file mode 100644 index 0000000000..5276237c10 --- /dev/null +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.variables.scss @@ -0,0 +1,12 @@ +// vf-chatbot-action-prompt variables + +// Override variables above this line +// -- + +// -- +// Default component variables +// -- + +// -- +// Custom component variables +// -- \ No newline at end of file diff --git a/components/vf-chatbot-fab/README.md b/components/vf-chatbot-fab/README.md new file mode 100644 index 0000000000..ce7a889171 --- /dev/null +++ b/components/vf-chatbot-fab/README.md @@ -0,0 +1,44 @@ +# Chatbot FAB (Floating Action Button) component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-fab.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-fab) + +## About + +The floating action button component for the Visual Framework chatbot. This component provides a persistent button that floats above the page content and allows users to initiate chat interactions. + +## Usage + +### JavaScript + +```js +import { initVFChatbotFab } from '@visual-framework/vf-chatbot-fab/vf-chatbot-fab.js'; +// Or import directly +// import { initVFChatbotFab } from '../components/raw/vf-chatbot-fab/vf-chatbot-fab.js'; + +initVFChatbotFab(); +``` + +### Nunjucks template + +```njk +{% render '@vf-chatbot-fab', { + notification_count: 2, + fab_active: false +} %} +``` + +## Install + +```bash +yarn add --dev @visual-framework/vf-chatbot-fab +``` + +### Sass/CSS + +The style files included are written in [Sass](https://sass-lang.com/). If you're using a VF-core project, you can import it like this: + +```scss +@import "@visual-framework/vf-chatbot-fab/index.scss"; +``` + +Make sure you import Sass requirements along with the modules. You can use a [project boilerplate](https://stable.visual-framework.dev/building/) or the [`vf-sass-starter`](https://stable.visual-framework.dev/components/vf-sass-starter/) \ No newline at end of file diff --git a/components/vf-chatbot-fab/package.json b/components/vf-chatbot-fab/package.json new file mode 100644 index 0000000000..95ddea9e59 --- /dev/null +++ b/components/vf-chatbot-fab/package.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-fab", + "description": "Visual Framework Chatbot Floating Action Button component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-fab.css", + "sass": "index.scss", + "main": "vf-chatbot-fab.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} diff --git a/components/vf-chatbot-fab/vf-chatbot-fab.js b/components/vf-chatbot-fab/vf-chatbot-fab.js new file mode 100644 index 0000000000..f756c5850a --- /dev/null +++ b/components/vf-chatbot-fab/vf-chatbot-fab.js @@ -0,0 +1,53 @@ +// vf-chatbot-fab + +function VFChatbotFab(element) { + this.el = element; + this.chatIcon = this.el.querySelector(".vf-chatbot-fab__icon--chat"); + this.closeIcon = this.el.querySelector(".vf-chatbot-fab__icon--close"); + + this.init(); +} + +VFChatbotFab.prototype = { + init: function() { + this.addEventListeners(); + }, + + addEventListeners: function() { + this.el.addEventListener("click", () => { + this.toggleState(); + }); + }, + + toggleState: function() { + this.el.classList.toggle("vf-chatbot-fab--active"); + + // Toggle icons + if (this.el.classList.contains("vf-chatbot-fab--active")) { + this.chatIcon.style.display = "none"; + this.closeIcon.style.display = "block"; + } else { + this.chatIcon.style.display = "block"; + this.closeIcon.style.display = "none"; + } + + // Dispatch event for parent chatbot component + this.el.dispatchEvent( + new CustomEvent("vf-chatbot-fab:toggle", { + bubbles: true, + detail: { + isActive: this.el.classList.contains("vf-chatbot-fab--active") + } + }) + ); + } +}; + +function initVFChatbotFab() { + const elements = document.querySelectorAll("[data-vf-js-chatbot-fab]"); + for (let i = 0; i < elements.length; i++) { + new VFChatbotFab(elements[i]); + } +} + +export { VFChatbotFab, initVFChatbotFab }; diff --git a/components/vf-chatbot-fab/vf-chatbot-fab.njk b/components/vf-chatbot-fab/vf-chatbot-fab.njk new file mode 100644 index 0000000000..606696a080 --- /dev/null +++ b/components/vf-chatbot-fab/vf-chatbot-fab.njk @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/components/vf-chatbot-fab/vf-chatbot-fab.scss b/components/vf-chatbot-fab/vf-chatbot-fab.scss new file mode 100644 index 0000000000..95f9f09548 --- /dev/null +++ b/components/vf-chatbot-fab/vf-chatbot-fab.scss @@ -0,0 +1,28 @@ +.vf-chatbot-fab { + position: fixed; + bottom: 20px; + right: 20px; + width: 56px; + height: 56px; + border-radius: 50%; + background: #007AFF; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + cursor: pointer; + transition: transform 0.2s ease, background-color 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + border: none; + + &:hover { + transform: scale(1.05); + background: darken(#007AFF, 10%); + } + + &__icon { + width: 24px; + height: 24px; + fill: #ffffff; + } +} diff --git a/components/vf-chatbot-modal/README.md b/components/vf-chatbot-modal/README.md new file mode 100644 index 0000000000..cfaaf35c8b --- /dev/null +++ b/components/vf-chatbot-modal/README.md @@ -0,0 +1,54 @@ +# Chatbot Modal component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-modal.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-modal) + +## About + +The chat modal component for the Visual Framework chatbot. This component provides the main chat interface that appears when users click the floating action button. + +## Features + +- Responsive design that works on both desktop and mobile +- Auto-expanding input field +- Message history with automatic scrolling +- Smooth animations for show/hide +- Event-based communication with parent components +- Optional settings button +- Customizable welcome message + +## Usage + +### JavaScript + +```js +import { initVFChatbotModal } from '@visual-framework/vf-chatbot-modal/vf-chatbot-modal.js'; +// Or import directly +// import { initVFChatbotModal } from '../components/raw/vf-chatbot-modal/vf-chatbot-modal.js'; + +initVFChatbotModal(); +``` + +### Nunjucks template + +```njk +{% render '@vf-chatbot-modal', { + title: "Chat with us", + welcome_message: "Hello! How can I help you today?", + input_placeholder: "Type your message...", + show_settings: true +} %} +``` + +## Install + +```bash +yarn add --dev @visual-framework/vf-chatbot-modal +``` + +### Sass/CSS + +The style files included are written in [Sass](https://sass-lang.com/). If you're using a VF-core project, you can import it like this: + +```scss +@import "@visual-framework/vf-chatbot-modal/index.scss"; +``` \ No newline at end of file diff --git a/components/vf-chatbot-modal/api-handler.js b/components/vf-chatbot-modal/api-handler.js new file mode 100644 index 0000000000..66c0044978 --- /dev/null +++ b/components/vf-chatbot-modal/api-handler.js @@ -0,0 +1,53 @@ +export class LLMApiHandler { + constructor() { + // You'll need to sign up at Hugging Face and get your API token + // https://huggingface.co/settings/tokens + this.API_TOKEN = ""; + this.API_URL = "https://api.mistral.ai/v1/chat/completions"; + // "https://api-inference.huggingface.co/models/facebook/blenderbot-400M-distill"; + } + + async generateResponse(message) { + console.log("Generating response for:", message); // Debug log + + try { + const response = await fetch(this.API_URL, { + method: "POST", + headers: { + Authorization: `Bearer ${this.API_TOKEN}`, + "Content-Type": "application/json" + }, + data: JSON.stringify({ + "messages": [{"role": "user", "content": message}], + "model": "mistral-small-latest", + }) + }); + + console.log("API response status:", response.status); // Debug log + + if (!response.ok) { + const errorText = await response.text(); + console.error("API error:", errorText); // Debug log + throw new Error(`API request failed: ${response.status} ${errorText}`); + } + + const data = await response.json(); + console.log("API response data:", data); // Debug log + + return { + html: this.formatResponse(data[0].generated_text) + }; + } catch (error) { + console.error("LLM API Error:", error); // Debug log + throw error; + } + } + + formatResponse(text) { + if (!text) return "

No response generated

"; + return text + .split("\n") + .map(paragraph => `

${paragraph}

`) + .join(""); + } +} diff --git a/components/vf-chatbot-modal/package.json b/components/vf-chatbot-modal/package.json new file mode 100644 index 0000000000..eb9643fb43 --- /dev/null +++ b/components/vf-chatbot-modal/package.json @@ -0,0 +1,7 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-modal", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.js b/components/vf-chatbot-modal/vf-chatbot-modal.js new file mode 100644 index 0000000000..bc2f5c7f28 --- /dev/null +++ b/components/vf-chatbot-modal/vf-chatbot-modal.js @@ -0,0 +1,278 @@ +// vf-chatbot-modal + +class VFChatbotModal { + constructor(element) { + console.log("Initializing chatbot modal..."); // Debug log + + // API configuration + this.API_TOKEN = ""; + this.API_URL = + "https://api-inference.huggingface.co/models/facebook/blenderbot-400M-distill"; + + // Store DOM elements + this.modal = element; + this.trigger = document.querySelector("[data-vf-js-chatbot-trigger]"); + this.closeBtn = this.modal.querySelector("[data-vf-js-chatbot-close]"); + this.minimizeBtn = this.modal.querySelector( + "[data-vf-js-chatbot-minimize]" + ); + this.input = this.modal.querySelector(".vf-chatbot-modal__input"); + this.sendBtn = this.modal.querySelector("[data-vf-js-chatbot-send]"); + this.messagesContainer = this.modal.querySelector( + ".vf-chatbot-modal__messages" + ); + this.welcomeScreen = this.modal.querySelector( + "[data-vf-js-chatbot-welcome]" + ); + this.suggestionBtns = this.modal.querySelectorAll( + "[data-vf-js-chatbot-suggestion]" + ); + + // State + this.hasInteracted = false; + + this.bindEvents(); + } + + bindEvents() { + console.log("Binding events..."); // Debug log + + // Toggle modal + this.trigger?.addEventListener("click", () => this.toggleModal()); + this.closeBtn?.addEventListener("click", e => { + e.stopPropagation(); + this.closeModal(); + }); + this.minimizeBtn?.addEventListener("click", e => { + e.stopPropagation(); + this.minimize(); + }); + + // Send message events + this.sendBtn?.addEventListener("click", () => this.sendMessage()); + this.input?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendMessage(); + } + }); + + // Welcome screen events + if (this.welcomeScreen) { + this.welcomeScreen.addEventListener("vf-chatbot-welcome:closed", () => { + this.showChatInterface(); + }); + + this.welcomeScreen.addEventListener( + "vf-chatbot-welcome:suggestion", + event => { + const { text } = event.detail; + this.showChatInterface(); + this.sendUserMessage(text); + } + ); + } + + // Suggestion buttons + this.suggestionBtns.forEach(btn => { + btn.addEventListener("click", () => { + const text = + btn.getAttribute("data-vf-js-chatbot-suggestion") || + btn.textContent.trim(); + this.sendUserMessage(text); + }); + }); + } + + showChatInterface() { + if (this.welcomeScreen) { + this.welcomeScreen.style.display = "none"; + } + + this.messagesContainer.style.display = "block"; + this.input.focus(); + this.hasInteracted = true; + } + + resetWelcomeScreen() { + if (this.welcomeScreen && !this.hasInteracted) { + this.welcomeScreen.style.display = "flex"; + this.messagesContainer.style.display = "none"; + } + } + + minimize() { + this.modal.classList.add("vf-chatbot-modal--minimized"); + this.modal.classList.remove("vf-chatbot-modal--active"); + + // Dispatch minimize event + this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:minimize")); + } + + maximize() { + // First remove minimized to ensure smooth transition + this.modal.classList.remove("vf-chatbot-modal--minimized"); + + // Small delay to ensure CSS transition works properly + requestAnimationFrame(() => { + this.modal.classList.add("vf-chatbot-modal--active"); + + // Focus on input if it exists + const input = this.modal.querySelector(".vf-chatbot-modal__input"); + if (input) { + setTimeout(() => input.focus(), 300); + } + }); + + // Dispatch maximize event + this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:maximize")); + + // Focus on input if welcome screen is not shown + if (this.hasInteracted) { + setTimeout(() => this.input.focus(), 300); + } + } + + closeModal() { + this.modal.classList.remove("vf-chatbot-modal--active"); + this.modal.classList.remove("vf-chatbot-modal--minimized"); + + // Reset welcome screen for next open + this.resetWelcomeScreen(); + + // Dispatch close event + this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:close")); + } + + toggleModal() { + const isMinimized = this.modal.classList.contains( + "vf-chatbot-modal--minimized" + ); + const isActive = this.modal.classList.contains("vf-chatbot-modal--active"); + + if (isMinimized || !isActive) { + this.maximize(); + } else { + this.minimize(); + } + } + + sendUserMessage(text) { + // Add user message to UI + const userMessageEl = document.createElement("div"); + userMessageEl.className = "vf-chatbot-message vf-chatbot-message--user"; + userMessageEl.innerHTML = ` +
${text}
+ `; + this.messagesContainer.appendChild(userMessageEl); + + // Clear input if this came from the input field + if (this.input.value === text) { + this.input.value = ""; + } + + this.scrollToBottom(); + + // Process the message (simulate response) + this.processUserMessage(text); + } + + sendMessage() { + const text = this.input.value.trim(); + if (!text) return; + + this.sendUserMessage(text); + } + + async processUserMessage(message) { + // Show loading state + this.setLoadingState(true); + + try { + const response = await this.callAPI(message); + console.log("API Response:", response); // Debug log + this.addMessage(response, "system"); + } catch (error) { + console.error("Error:", error); + this.addMessage( + "Sorry, I encountered an error. Please try again.", + "system" + ); + } + + // // Simulate API call with timeout + setTimeout(() => { + // Add assistant response + this.addAssistantResponse(this.getSimulatedResponse(message)); + this.setLoadingState(false); + }, 1000); + } + + addAssistantResponse(text) { + const assistantMessageEl = document.createElement("div"); + assistantMessageEl.className = + "vf-chatbot-message vf-chatbot-message--assistant"; + assistantMessageEl.innerHTML = ` + AI Assistant +
${text}
+ `; + this.messagesContainer.appendChild(assistantMessageEl); + + this.scrollToBottom(); + } + + getSimulatedResponse(text) { + // Simple response simulation + if (text.toLowerCase().includes("metabolomics")) { + return "Metabolomics is the large-scale study of small molecules,"; + } else if (text.toLowerCase().includes("genomics")) { + return "Genomics is the study of the structure, function, evolution, and mapping of genomes."; + } else if (text.toLowerCase().includes("proteomics")) { + return "Proteomics is the study of the structure, function, and regulation of the proteome."; + } else if (text.toLowerCase().includes("transcriptomics")) { + return "Transcriptomics is the study of the complete set of RNA molecules within a cell."; + } else if (text.toLowerCase().includes("epigenomics")) { + return "Epigenomics is the study of heritable changes in gene function that do not involve changes to the DNA sequence."; + } else if (text.toLowerCase().includes("metabolomics")) { + return "Metabolomics is the large-scale study of small molecules,"; + } else if (text.toLowerCase().includes("genomics")) { + return "Genomics is the study of the structure, function, evolution, and mapping of genomes."; + } else if (text.toLowerCase().includes("proteomics")) { + return "Proteomics is the study of the structure, function, and regulation of the proteome."; + } else if (text.toLowerCase().includes("transcriptomics")) { + return "Transcriptomics is the study of the complete set of RNA molecules within a cell."; + } else if (text.toLowerCase().includes("epigenomics")) { + return "Epigenomics is the study of heritable changes in gene function that do not involve changes to the DNA sequence."; + } else { + return "I'm sorry, I didn't understand that. Could you please provide more context or ask a specific question?"; + } + } + + setLoadingState(isLoading) { + this.input.disabled = isLoading; + this.sendBtn.disabled = isLoading; + this.sendBtn.innerHTML = isLoading ? "Sending..." : "Send"; + } + + scrollToBottom() { + this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + } +} + +// Initialize +function initVFChatbotModal() { + console.log("Looking for chatbot elements..."); // Debug log + const chatbotElements = document.querySelectorAll( + "[data-vf-js-chatbot-modal]" + ); + + if (chatbotElements.length === 0) { + console.warn("No chatbot elements found on page"); + return; + } + + console.log(`Found ${chatbotElements.length} chatbot elements`); // Debug log + chatbotElements.forEach(element => new VFChatbotModal(element)); +} + +export { VFChatbotModal, initVFChatbotModal }; diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.njk b/components/vf-chatbot-modal/vf-chatbot-modal.njk new file mode 100644 index 0000000000..ed46d2558a --- /dev/null +++ b/components/vf-chatbot-modal/vf-chatbot-modal.njk @@ -0,0 +1,91 @@ + +
+
+
+

+ AI Assistant + {{ title | default("AI Assistant") }} +

+
+
+ + +
+
+ +
+ + {% render '@vf-chatbot-welcome', { + welcome_title: welcome_title | default('AI Assistant'), + welcome_description: welcome_description | default('I can help you find information about our research, services, and more. What would you like to know?'), + welcome_features: welcome_features | default([ + 'Finding research publications', + 'Learning about our services', + 'Getting information about events', + 'Understanding scientific concepts' + ]), + welcome_suggestions: welcome_suggestions | default([ + 'What is Metabolomics?', + 'Tell me about your training courses', + 'How can I access your data resources?', + 'What research areas do you focus on?' + ]) + } %} + + +
+ {% if welcome_message %} +
+ AI Assistant +
+ {{ welcome_message | safe }} +
+
+ {% endif %} +
+ +
+
+ + +
+
+ + {% if show_suggestions %} +
+ +
+ {% endif %} +
+
diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.scss b/components/vf-chatbot-modal/vf-chatbot-modal.scss new file mode 100644 index 0000000000..d55b4d1b6d --- /dev/null +++ b/components/vf-chatbot-modal/vf-chatbot-modal.scss @@ -0,0 +1,321 @@ +.vf-chatbot-modal { + display: none; + position: fixed; + bottom: 80px; + right: 20px; + width: 360px; + height: 500px; + background: #ffffff; + border-radius: 16px 16px 0px 16px; // Increased border radius + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + z-index: 999; + overflow: hidden; + transition: all 0.3s ease; + opacity: 0; + transform: translateY(20px); + + &--active { + display: flex; + flex-direction: column; + opacity: 1; + transform: translateY(0); + + .vf-chatbot-modal__content { + display: flex; + flex-direction: column; + flex: 1; + } + } + + &--minimized { + display: flex; + flex-direction: column; + height: 60px; + opacity: 1; + transform: translateY(0); + overflow: hidden; + + .vf-chatbot-modal__content { + visibility: hidden; + height: 0; + } + } + + &__header { + height: 60px; + min-height: 60px; // Add this to prevent header from shrinking + padding: 0 16px; + background: #ffffff; // White background + border-bottom: 1px solid #E5E5E5; + color: #000000; + display: flex; + align-items: center; + justify-content: space-between; + border-radius: 16px 16px 0 0; + + &-left { + display: flex; + align-items: center; + gap: 8px; + } + } + + &__title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + display: flex; + align-items: center; + gap: 8px; + + img { + width: 24px; + height: 24px; + } + } + + &__content { + display: flex; + flex-direction: column; + flex: 1; + transition: visibility 0.3s ease, height 0.3s ease; + } + + &__messages { + flex: 1; + overflow-y: auto; + padding: 16px; + background: #F5F5F5; + } + + &__input-area { + background: #ffffff; + border-top: 1px solid #E5E5E5; + } + + &__input-wrapper { + position: relative; + } + + &__input { + width: 100%; + padding-left: 20px; + padding-right: 44px; // Space for the send button + border: 1px solid #E5E5E5; + font-size: 14px; + line-height: 1.5; + resize: none; + min-height: 44px; + max-height: 120px; + background: #F5F5F5; + + &:focus { + outline: none; + // border-color: #007AFF; + background: #ffffff; + } + + &::placeholder { + color: #666666; + } + } + + &__send-button { + position: absolute; + right: 0px; + height: 100%; + top: 50%; + transform: translateY(-50%); + background: #007AFF; + color: #ffffff; + border: none; + padding: 8px; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + } + + &__controls { + display: flex; + gap: 8px; + + button { + background: none; + border: none; + padding: 8px; + cursor: pointer; + color: #666666; + + &:hover { + color: #1A1A1A; + } + } + } + + // Smooth transition for minimize/maximize + &__content { + transition: all 0.2s ease; + } + + // Add minimized state styles + &--minimized { + height: 60px !important; // Override default height + + .vf-chatbot-modal__content { + display: none; + } + + .vf-chatbot-modal__header { + border-bottom: none; + padding-bottom: 0; + } + + .vf-chatbot-modal__title { + font-size: 1rem; + } + } + + @media (max-width: 480px) { + width: calc(100% - 40px); + height: calc(100vh - 100px); + bottom: 70px; + + &--minimized { + height: 60px; + } + } +} + +.vf-loading-spinner { + animation: rotate 2s linear infinite; + width: 20px; + height: 20px; + + & .path { + stroke: currentColor; + stroke-linecap: round; + animation: dash 1.5s ease-in-out infinite; + } +} + +@keyframes rotate { + 100% { + transform: rotate(360deg); + } +} + +@keyframes dash { + 0% { + stroke-dasharray: 1, 150; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -35; + } + 100% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -124; + } +} + +// Message styles +.vf-chatbot-message { + margin-bottom: 16px; + max-width: 85%; + + &--user { + margin-left: auto; + + .vf-chatbot-message__content { + background: #1A1A1A; + color: #ffffff; + border-radius: 16px 16px 16px 16px; + } + } + + &--assistant { + margin-right: auto; + display: flex; + align-items: flex-start; + gap: 8px; + + .vf-chatbot-message__avatar { + width: 24px; + height: 24px; + border-radius: 50%; + } + + .vf-chatbot-message__content { + background: #ffffff; + color: #1A1A1A; + border-radius: 16px 16px 16px 16px; + } + } + + &__content { + padding: 12px 16px; + font-size: 14px; + line-height: 1.5; + } +} + +// Suggestion area +.vf-chatbot-suggestions { + padding: 16px; + background: #ffffff; + border-top: 1px solid #E5E5E5; + + &__input { + width: 100%; + padding: 12px 16px; + background: #F5F5F5; + border: none; + border-radius: 8px; + color: #666666; + font-size: 14px; + cursor: pointer; + text-align: left; + + &:hover { + background: darken(#F5F5F5, 5%); + } + } +} + +.vf-chatbot-trigger { + position: fixed; + bottom: 20px; + right: 20px; + padding: 12px 24px; + background: var(--vf-color-primary); + color: white; + border: none; + border-radius: 24px; + cursor: pointer; + z-index: 998; + + &:hover { + background: var(--vf-color-primary-dark); + } +} + +.vf-chatbot-modal__title img { + width: 24px; + height: 24px; + margin-right: 8px; + vertical-align: middle; +} + +.vf-chatbot-message--assistant img.vf-chatbot-message__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + background-color: #fff; + object-fit: contain; + padding: 0; + border: 1px solid #eee; +} diff --git a/components/vf-chatbot-prompt/package.json b/components/vf-chatbot-prompt/package.json new file mode 100644 index 0000000000..56b9f25d0d --- /dev/null +++ b/components/vf-chatbot-prompt/package.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-prompt", + "description": "Visual Framework Chatbot Prompt component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-prompt.css", + "sass": "index.scss", + "main": "vf-chatbot-prompt.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} \ No newline at end of file diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.js b/components/vf-chatbot-prompt/vf-chatbot-prompt.js new file mode 100644 index 0000000000..76ce4aa01b --- /dev/null +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.js @@ -0,0 +1,68 @@ +// vf-chatbot-prompt + +function VFChatbotPrompt(element) { + this.el = element; + this.loading = false; +} + +VFChatbotPrompt.prototype = { + setLoading: function(isLoading) { + this.loading = isLoading; + + if (isLoading) { + // Remove existing loading element if any + this.removeLoading(); + + // Create loading element + const loadingEl = document.createElement("div"); + loadingEl.className = "vf-chatbot-prompt__loading"; + loadingEl.innerHTML = ` + + + + `; + + this.el.appendChild(loadingEl); + } else { + this.removeLoading(); + } + }, + + removeLoading: function() { + const loadingEl = this.el.querySelector(".vf-chatbot-prompt__loading"); + if (loadingEl) { + loadingEl.remove(); + } + }, + + setResponse: function(html) { + // Remove loading first + this.setLoading(false); + + // Create response element + const responseEl = document.createElement("div"); + responseEl.className = + "vf-chatbot-prompt__message vf-chatbot-prompt__message--system"; + responseEl.innerHTML = html; + + this.el.appendChild(responseEl); + } +}; + +function initVFChatbotPrompt(message) { + const el = document.createElement("div"); + el.className = "vf-chatbot-prompt"; + el.setAttribute("data-vf-js-chatbot-prompt", ""); + + const messageEl = document.createElement("div"); + messageEl.className = + "vf-chatbot-prompt__message vf-chatbot-prompt__message--user"; + messageEl.textContent = message; + + el.appendChild(messageEl); + + const prompt = new VFChatbotPrompt(el); + return prompt; +} + +export { VFChatbotPrompt, initVFChatbotPrompt }; diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.njk b/components/vf-chatbot-prompt/vf-chatbot-prompt.njk new file mode 100644 index 0000000000..a8c7646190 --- /dev/null +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.njk @@ -0,0 +1,19 @@ +
+
+ {{ message }} +
+ + {% if loading %} +
+ + + +
+ {% endif %} + + {% if response %} +
+ {{ response | safe }} +
+ {% endif %} +
\ No newline at end of file diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.scss b/components/vf-chatbot-prompt/vf-chatbot-prompt.scss new file mode 100644 index 0000000000..7f31a20a2f --- /dev/null +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.scss @@ -0,0 +1,80 @@ +.vf-chatbot-prompt { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 16px; + + &__message { + padding: 12px 16px; + border-radius: 12px; + max-width: 80%; + line-height: 1.4; + + &--user { + background: var(--vf-color-gray-100); + align-self: flex-end; + } + + &--system { + background: var(--vf-color-primary-light); + align-self: flex-start; + + // Style for rich text content + p { + margin: 0 0 8px 0; + &:last-child { + margin-bottom: 0; + } + } + + code { + background: rgba(0, 0, 0, 0.05); + padding: 2px 4px; + border-radius: 4px; + } + + pre { + background: rgba(0, 0, 0, 0.05); + padding: 8px; + border-radius: 4px; + overflow-x: auto; + } + } + } + + &__loading { + align-self: flex-start; + display: flex; + gap: 4px; + padding: 12px 16px; + background: var(--vf-color-primary-light); + border-radius: 12px; + border-bottom-left-radius: 4px; + } + + &__dot { + width: 8px; + height: 8px; + background: var(--vf-color-gray-600); + border-radius: 50%; + opacity: 0.3; + animation: dot-flash 1.4s infinite; + + &:nth-child(2) { + animation-delay: 0.2s; + } + + &:nth-child(3) { + animation-delay: 0.4s; + } + } +} + +@keyframes dot-flash { + 0%, 60%, 100% { + opacity: 0.3; + } + 30% { + opacity: 1; + } +} diff --git a/components/vf-chatbot-standalone/README.md b/components/vf-chatbot-standalone/README.md new file mode 100644 index 0000000000..77e522683c --- /dev/null +++ b/components/vf-chatbot-standalone/README.md @@ -0,0 +1,51 @@ +# Chatbot Standalone component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-standalone.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-standalone) + +## About + +A full-page standalone chatbot interface that can be accessed via a direct URL. This component reuses elements from the chatbot modal but is designed to work as a standalone page rather than a popup. + +## Usage + +### JavaScript + +```js +import { initVFChatbotStandalone } from '@visual-framework/vf-chatbot-standalone/vf-chatbot-standalone.js'; +// Or import directly +// import { initVFChatbotStandalone } from '../components/raw/vf-chatbot-standalone/vf-chatbot-standalone.js'; + +initVFChatbotStandalone(); +``` + +### Nunjucks template + +```njk +{% render '@vf-chatbot-standalone', { + title: "AI Assistant", + welcome_message: "Hello! How can I help you today?", + input_placeholder: "Type your message...", + show_suggestions: true, + show_close_button: true +} %} +``` + +## Install + +```bash +yarn add --dev @visual-framework/vf-chatbot-standalone +``` + +### Sass/CSS + +The style files included are written in [Sass](https://sass-lang.com/). If you're using a VF-core project, you can import it like this: + +```scss +@import "@visual-framework/vf-chatbot-standalone/index.scss"; +``` + +## Help + +- [Read the Visual Framework troubleshooting](https://stable.visual-framework.dev/troubleshooting/) +- [Open a ticket](https://github.com/visual-framework/vf-core/issues) +- [Chat on Slack](https://join.slack.com/t/visual-framework/shared_invite/enQtNDAxNzY0NDg4NTY0LWFhMjEwNGY3ZTk3NWYxNWVjOWQ1ZWE4YjViZmY1YjBkMDQxMTNlNjQ0N2ZiMTQ1ZTZiMGM4NjU5Y2E0MjM3ZGQ) \ No newline at end of file diff --git a/components/vf-chatbot-standalone/package.json b/components/vf-chatbot-standalone/package.json new file mode 100644 index 0000000000..b7c35f7d4e --- /dev/null +++ b/components/vf-chatbot-standalone/package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-standalone", + "description": "Visual Framework Standalone Chatbot component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-standalone.css", + "sass": "index.scss", + "main": "vf-chatbot-standalone.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config", + "@visual-framework/vf-chatbot-welcome": "file:../vf-chatbot-welcome" + } +} diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml b/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml new file mode 100644 index 0000000000..12e73a086c --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml @@ -0,0 +1,9 @@ +title: Chatbot Standalone +label: Chatbot Standalone +status: beta +preview: '@preview' +context: + title: AI Assistant + welcome_message: Hello! How can I help you today? + input_placeholder: Type your message... + show_suggestions: true diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.js b/components/vf-chatbot-standalone/vf-chatbot-standalone.js new file mode 100644 index 0000000000..df6ac22b2f --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.js @@ -0,0 +1,333 @@ +// vf-chatbot-standalone.js +class VFChatbotStandalone { + constructor(element) { + console.log("Initializing standalone chatbot..."); // Debug log + + // Store DOM elements + this.container = element; + this.welcomeScreen = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome]" + ); + this.chatInterface = this.container.querySelector( + "[data-vf-js-chatbot-standalone-chat]" + ); + this.messagesContainer = this.container.querySelector( + "[data-vf-js-chatbot-standalone-messages]" + ); + this.loadingIndicator = this.container.querySelector( + "[data-vf-js-chatbot-standalone-loading]" + ); + this.input = this.container.querySelector( + "[data-vf-js-chatbot-standalone-input]" + ); + this.sendBtn = this.container.querySelector( + "[data-vf-js-chatbot-standalone-send]" + ); + this.welcomeInput = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome-input]" + ); + this.welcomeSendBtn = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome-send]" + ); + this.suggestionBtns = this.container.querySelectorAll( + "[data-vf-js-chatbot-standalone-suggestion]" + ); + // API configuration - Mistral AI + this.API_TOKEN = ""; + this.API_URL = "https://api.mistral.ai/v1/chat/completions"; + + // State + this.hasInteracted = false; + + this.bindEvents(); + this.initAutoResize(); + + console.log("Standalone chatbot initialized successfully"); // Debug log + } + + bindEvents() { + console.log("Binding events for standalone chatbot..."); // Debug log + + // Send message events + this.sendBtn?.addEventListener("click", () => this.sendMessage()); + this.input?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendMessage(); + } + }); + + // Welcome screen input events + this.welcomeSendBtn?.addEventListener("click", () => + this.sendWelcomeMessage() + ); + this.welcomeInput?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendWelcomeMessage(); + } + }); + + // Welcome screen suggestion buttons + this.suggestionBtns.forEach(btn => { + btn.addEventListener("click", () => { + const text = + btn.getAttribute("data-vf-js-chatbot-standalone-suggestion") || + btn.textContent.trim(); + + // Show chat interface + this.showChatInterface(); + + // Update the input field with the suggestion text + if (this.input && text) { + this.input.value = text; + + // Adjust the height of the input field to match content + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + } + + // Send the message to the API + if (text) { + this.sendUserMessage(text); + } + }); + }); + + // Listen for action prompt clicks + this.container.addEventListener("vf-chatbot-action-prompt:click", event => { + const { text, data } = event.detail; + + // Show chat interface + this.showChatInterface(); + + // Update the input field with the suggestion text + if (this.input && text) { + this.input.value = text; + + // Adjust the height of the input field to match content + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + } + + // Send the message to the API + if (text) { + this.sendUserMessage(text); + } + }); + } + + initAutoResize() { + // Auto-resize textarea as user types + if (this.input) { + this.input.addEventListener("input", () => { + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + }); + } + } + + sendMessage() { + if (!this.input || !this.input.value.trim()) return; + + const text = this.input.value.trim(); + this.sendUserMessage(text); + } + + sendWelcomeMessage() { + if (!this.welcomeInput || !this.welcomeInput.value.trim()) return; + + const text = this.welcomeInput.value.trim(); + this.showChatInterface(); + this.sendUserMessage(text); + } + + showChatInterface() { + if (this.welcomeScreen) { + this.welcomeScreen.style.display = "none"; + } + if (this.chatInterface) { + this.chatInterface.style.display = "block"; + } + + // Focus on the input field + if (this.input) { + this.input.focus(); + } + + this.hasInteracted = true; + } + + sendUserMessage(text) { + if (!text || !this.messagesContainer) return; + + // Add user message to UI + const userMessageEl = document.createElement("div"); + userMessageEl.className = "vf-chatbot-message vf-chatbot-message--user"; + userMessageEl.innerHTML = ` +
${text}
+ `; + this.messagesContainer.appendChild(userMessageEl); + + // Clear input if this came from the input field + if (this.input && this.input.value === text) { + this.input.value = ""; + this.input.style.height = "auto"; // Reset height + } + + this.scrollToBottom(); + + // Process the message + this.processUserMessage(text); + } + + processUserMessage(text) { + // Show loading state + this.setLoadingState(true); + + // Call the API + this.callAPI(text) + .then(response => { + this.addAssistantResponse(response.html || response); + this.setLoadingState(false); + }) + .catch(error => { + console.error("API Error:", error); + // Fallback to simulated response if API fails + this.addAssistantResponse(this.getSimulatedResponse(text)); + this.setLoadingState(false); + }); + } + + callAPI(text) { + return new Promise((resolve, reject) => { + fetch(this.API_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${this.API_TOKEN}` + }, + body: JSON.stringify({ + model: "mistral-tiny", // or another available model + messages: [ + { role: "system", content: "You are a helpful assistant." }, + { role: "user", content: text } + ] + }) + }) + .then(response => { + if (!response.ok) { + throw new Error(`API error: ${response.status}`); + } + return response.json(); + }) + .then(data => { + // Mistral returns: { choices: [{ message: { content: "..." } }] } + if (data && data.choices && data.choices[0] && data.choices[0].message && data.choices[0].message.content) { + resolve(data.choices[0].message.content); + } else { + reject(new Error("Invalid API response")); + } + }) + .catch(error => { + console.error("API call failed:", error); + reject(error); + }); + }); + } + + addAssistantResponse(text) { + if (!text || !this.messagesContainer) return; + + // Add assistant message to UI + const assistantMessageEl = document.createElement("div"); + assistantMessageEl.className = + "vf-chatbot-message vf-chatbot-message--assistant"; + assistantMessageEl.innerHTML = ` +
+ AI Assistant +
+
${text}
+ `; + this.messagesContainer.appendChild(assistantMessageEl); + + this.scrollToBottom(); + } + + setLoadingState(isLoading) { + if (this.loadingIndicator) { + this.loadingIndicator.style.display = isLoading ? "flex" : "none"; + } + + if (this.sendBtn) { + this.sendBtn.disabled = isLoading; + } + + if (this.input) { + this.input.disabled = isLoading; + } + + this.scrollToBottom(); + } + + scrollToBottom() { + if (this.messagesContainer) { + this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + } + } + + getSimulatedResponse(text) { + // Fallback responses when API fails + const fallbackResponses = [ + "I'm sorry, I'm having trouble connecting to my knowledge base right now. Could you try again in a moment?", + "That's an interesting question. Let me think about how to best answer that for you.", + "I understand you're asking about bioinformatics training. We have several resources available. Could you tell me more about your specific interests?", + "Thank you for your question. We offer various workshops and online courses on that topic. Would you like me to provide more specific information?", + "I'd be happy to help with that. We have both introductory and advanced courses available depending on your experience level." + ]; + + return fallbackResponses[ + Math.floor(Math.random() * fallbackResponses.length) + ]; + } +} + +// Initialize +function initVFChatbotStandalone() { + console.log("Looking for standalone chatbot elements..."); // Debug log + const chatbotElements = document.querySelectorAll( + "[data-vf-js-chatbot-standalone]" + ); + + if (chatbotElements.length === 0) { + console.warn("No standalone chatbot elements found on page"); + return; + } + + console.log(`Found ${chatbotElements.length} standalone chatbot elements`); // Debug log + + // Initialize each standalone chatbot element + const instances = []; + chatbotElements.forEach(element => { + instances.push(new VFChatbotStandalone(element)); + }); + + return instances; +} + +// Make initialization function available globally +if (typeof window !== "undefined") { + window.VFChatbotStandalone = VFChatbotStandalone; + window.initVFChatbotStandalone = initVFChatbotStandalone; + + // Also make it available as a global variable without window prefix + if (typeof globalThis !== "undefined") { + globalThis.VFChatbotStandalone = VFChatbotStandalone; + globalThis.initVFChatbotStandalone = initVFChatbotStandalone; + } + + console.log("Exposed initVFChatbotStandalone to global scope"); +} + +// Export both the class and the initialization function +export { VFChatbotStandalone, initVFChatbotStandalone }; diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk new file mode 100644 index 0000000000..2493219f95 --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk @@ -0,0 +1,121 @@ + +
+
+
+
+

+ + AI Assistant + {{ title | default("AI assistant") }} +

+
+
+ +
+ + +
+ +
+ + {% if welcome_message %} + +
+
+ +

{{ welcome_title | default('AI assistant') }}

+

+ {{ welcome_description | default("Welcome! I'm here to help you discover bioinformatics training and resources.") }} +

+ +
+

Try asking me:

+
+ {% for suggestion in welcome_suggestions %} + {% if loop.index == welcome_suggestions.length and welcome_suggestions.length > 2 %} + {% render '@vf-chatbot-action-prompt', { + action_text: suggestion, + action_data: suggestion, + modifier_class: "vf-chatbot-action-prompt--full-width", + data_attribute: "data-vf-js-chatbot-standalone-suggestion=" + suggestion, + data_vf_js_chatbot_action_prompt: true + } %} + {% else %} + {% render '@vf-chatbot-action-prompt', { + action_text: suggestion, + action_data: suggestion, + data_attribute: "data-vf-js-chatbot-standalone-suggestion=" + suggestion, + data_vf_js_chatbot_action_prompt: true + } %} + {% endif %} + {% endfor %} +
+
+
+
+ {#
+
+ AI Assistant +
+
+ {{ welcome_message | default('Hello! How can I help you today?') }} +
+
#} + {% endif %} + +
+ + + + + + {#
+
+ + +
+
#} +
+
+ + +
+
+
+
+
+
diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss new file mode 100644 index 0000000000..30fb763091 --- /dev/null +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss @@ -0,0 +1,404 @@ +// vf-chatbot-standalone.scss + +.vf-chatbot-standalone { + display: flex; + flex-direction: column; + width: 100%; + height: 100vh; + + &__container { + display: flex; + flex-direction: column; + height: 100%; + margin: 10px; + background: #ffffff; + + @media (max-width: 1200px) { + max-width: 100%; + } + } + + &__header { + height: 64px; + background: #ffffff; + color: #000000; + display: flex; + align-items: center; + justify-content: space-between; + + @media (max-width: 768px) { + padding: 0 16px; + } + } + + &__header-left { + display: flex; + align-items: center; + gap: 12px; + } + + &__title { + font-size: 18px; + font-weight: 500; + color: #1A1A1A; + display: flex; + align-items: center; + gap: 12px; + margin: 0; + + img { + width: 28px; + height: 28px; + } + } + + &__controls { + display: flex; + gap: 8px; + + button { + background: none; + border: none; + padding: 8px; + cursor: pointer; + color: #666666; + + &:hover { + color: #1A1A1A; + } + } + } + + &__content { + display: flex !important; + flex-direction: column; + flex: 1; + overflow: hidden; + background: #F5F5F5; + justify-content: center; + border-radius: 16px 16px 16px 16px; + } + + // Welcome screen styles + &__welcome { + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 24px; + + &-content { + max-width: 65%; + width: 100%; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + } + + &-logo { + margin-bottom: 16px; + + img { + width: 48px; + height: 48px; + } + } + + &-title { + font-size: 24px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 12px 0; + } + + &-description { + font-size: 16px; + line-height: 1.5; + color: #666666; + margin: 0 0 32px 0; + max-width: 450px; + } + + &-suggestions { + margin-top: 16px; + width: 100%; + + &-title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 16px 0; + } + + &-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + + @media (max-width: 480px) { + grid-template-columns: 1fr; + } + } + } + + &-suggestion { + padding: 12px 16px; + background: #FFFFFF; + border: 1px solid #E5E5E5; + border-radius: 8px; + font-size: 14px; + color: #1A1A1A; + cursor: pointer; + transition: background 0.2s ease, border-color 0.2s ease; + text-align: left; + + &:hover { + background: #F0F0F0; + border-color: #CCCCCC; + } + } + + &-input-container { + margin-top: 32px; + width: 100%; + max-width: 500px; + } + + &-input-wrapper { + position: relative; + width: 100%; + display: flex; + align-items: center; + background: #FFFFFF; + border: 1px solid #E5E5E5; + border-radius: 8px; + overflow: hidden; + } + + &-input { + flex: 1; + padding: 16px; + border: none; + font-size: 16px; + line-height: 1.5; + background: transparent; + + &:focus { + outline: none; + } + + &::placeholder { + color: #666666; + } + } + + &-send-button { + background: #007AFF; + color: #ffffff; + border: none; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + + svg { + width: 24px; + height: 24px; + } + } + } + + &__messages { + flex: 1; + overflow-y: auto; + padding: 24px; + background: #F5F5F5; + + @media (max-width: 768px) { + padding: 16px; + } + } + + &__input-area { + padding: 16px 24px; + background: #ffffff; + border-top: 1px solid #E5E5E5; + + @media (max-width: 768px) { + padding: 12px 16px; + } + } + + &__input-wrapper { + position: relative; + width: 70%; + margin: 0 auto; + } + + &__input { + width: 100%; + padding: 0px; + border: none; + font-size: 16px; + line-height: 1.5; + resize: none; + min-height: 40px; + max-height: 150px; + background: #FFFFFF; + + &::placeholder { + color: #666666; + } + } + + &__send-button { + position: absolute; + right: 0px; + top: 50%; + transform: translateY(-50%); + background: #007AFF; + color: #ffffff; + border: none; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + + svg { + width: 24px; + height: 24px; + } + } + + &__welcome-suggestions { + margin: 24px 0; + + &-title { + font-weight: 500; + margin-bottom: 12px; + } + + &-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + justify-items: center; // Center items horizontally + + // Make the last item span full width if it's the 3rd item + & > *:nth-child(3):last-child { + grid-column: 1 / -1; + justify-self: center; // Center the full-width item + } + + // Ensure each grid cell only takes the width it needs + & > * { + width: auto; + min-width: min-content; + } + } + } + + &__chat { + display: flex; + flex-direction: column; + height: 80vh; /* Or use: calc(100vh - [header+footer heights]) for more precise fit */ + max-height: 80vh; + min-height: 400px; + // background: #fff; + // border-radius: 1rem; + // box-shadow: 0 2px 8px rgba(0,0,0,0.04); + // overflow: hidden; + } + + &__messages { + flex: 1 1 auto; + overflow-y: auto; + padding: 1rem; + min-height: 0; /* Required for flex children to scroll */ + } +} + +// Reuse message styles from the modal component +.vf-chatbot-message { + margin-bottom: 24px; + max-width: 85%; + + @media (max-width: 768px) { + max-width: 90%; + } + + &--user { + margin-left: auto; + + .vf-chatbot-message__content { + background: #1A1A1A; + color: #ffffff; + border-radius: 16px 16px 16px 16px; + } + } + + &--assistant { + margin-right: auto; + display: flex; + align-items: flex-start; + gap: 12px; + + .vf-chatbot-message__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + } + + .vf-chatbot-message__content { + background: #ffffff; + color: #1A1A1A; + border-radius: 16px 16px 16px 16px; + } + } + + &__content { + padding: 16px; + font-size: 16px; + line-height: 1.5; + } +} + +.vf-chatbot-standalone__title img { + width: 24px; + height: 24px; + margin-right: 8px; + vertical-align: middle; +} + +.vf-chatbot-standalone__welcome-logo img { + width: 64px; + height: 64px; + margin-bottom: 16px; + object-fit: contain; +} + +.vf-chatbot-message--assistant img.vf-chatbot-message__avatar { + width: 32px; + height: 32px; + border-radius: 50%; + background-color: #fff; + object-fit: contain; + padding: 0; + border: 1px solid #eee; +} diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.js b/components/vf-chatbot-welcome/vf-chatbot-welcome.js new file mode 100644 index 0000000000..84856833a7 --- /dev/null +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.js @@ -0,0 +1,59 @@ +// vf-chatbot-welcome.js + +class VFChatbotWelcome { + constructor(element) { + this.el = element; + this.startButton = this.el.querySelector("[data-vf-js-chatbot-start]"); + this.suggestions = this.el.querySelectorAll( + "[data-vf-js-chatbot-suggestion]" + ); + + this.bindEvents(); + } + + bindEvents() { + // Start conversation button + this.startButton?.addEventListener("click", () => { + this.hideWelcomeScreen(); + }); + + // Suggestion buttons + this.suggestions.forEach(suggestion => { + suggestion.addEventListener("click", () => { + const text = suggestion.getAttribute("data-vf-js-chatbot-suggestion"); + this.sendSuggestion(text); + }); + }); + } + + hideWelcomeScreen() { + // Hide welcome screen + this.el.style.display = "none"; + + // Dispatch event to notify that welcome screen is closed + this.el.dispatchEvent(new CustomEvent("vf-chatbot-welcome:closed")); + } + + sendSuggestion(text) { + // Hide welcome screen + this.hideWelcomeScreen(); + + // Dispatch event with the suggestion text + this.el.dispatchEvent( + new CustomEvent("vf-chatbot-welcome:suggestion", { + detail: { text } + }) + ); + } +} + +// Initialize +function initVFChatbotWelcome() { + const welcomeElements = document.querySelectorAll( + "[data-vf-js-chatbot-welcome]" + ); + + welcomeElements.forEach(element => new VFChatbotWelcome(element)); +} + +export { VFChatbotWelcome, initVFChatbotWelcome }; diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.njk b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk new file mode 100644 index 0000000000..4fead6d364 --- /dev/null +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk @@ -0,0 +1,41 @@ +
+
+ AI Assistant +

{{ welcome_title | default('AI Assistant') }}

+
+ +
+

+ {{ welcome_description | default('I can help you find information about our research, services, and more. What would you like to know?') }} +

+ + {% if welcome_features %} +
+

I can help with:

+
    + {% for feature in welcome_features %} +
  • + ✓ + {{ feature }} +
  • + {% endfor %} +
+
+ {% endif %} +
+ +
+

Try asking:

+
+ {% for suggestion in welcome_suggestions %} + + {% endfor %} +
+
+ + +
diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.scss b/components/vf-chatbot-welcome/vf-chatbot-welcome.scss new file mode 100644 index 0000000000..d696e7a14d --- /dev/null +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.scss @@ -0,0 +1,139 @@ +.vf-chatbot-welcome { + display: flex; + flex-direction: column; + height: 100%; + padding: 24px; + background-color: #ffffff; + + &__header { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 24px; + text-align: center; + } + + &__icon { + width: 48px; + height: 48px; + margin-bottom: 16px; + object-fit: contain; + } + + &__title { + font-size: 24px; + font-weight: 600; + color: #1A1A1A; + margin: 0; + } + + &__content { + flex: 1; + margin-bottom: 24px; + } + + &__description { + font-size: 16px; + line-height: 1.5; + color: #666666; + text-align: center; + margin-bottom: 24px; + } + + &__features { + background-color: #F5F5F5; + border-radius: 12px; + padding: 16px; + margin-bottom: 24px; + } + + &__features-title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 12px 0; + } + + &__features-list { + list-style: none; + padding: 0; + margin: 0; + } + + &__feature { + display: flex; + align-items: flex-start; + margin-bottom: 8px; + font-size: 14px; + line-height: 1.5; + color: #1A1A1A; + + &:last-child { + margin-bottom: 0; + } + } + + &__feature-icon { + display: flex; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + margin-right: 8px; + background-color: #007AFF; + color: #ffffff; + border-radius: 50%; + font-size: 12px; + flex-shrink: 0; + } + + &__suggestions { + margin-bottom: 24px; + } + + &__suggestions-title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 12px 0; + } + + &__suggestions-list { + display: flex; + flex-direction: column; + gap: 8px; + } + + &__suggestion { + padding: 12px 16px; + background-color: #F5F5F5; + border: none; + border-radius: 8px; + font-size: 14px; + line-height: 1.5; + color: #1A1A1A; + text-align: left; + cursor: pointer; + transition: background-color 0.2s ease; + + &:hover { + background-color: #E5E5E5; + } + } + + &__start-button { + padding: 12px 24px; + background-color: #007AFF; + color: #ffffff; + border: none; + border-radius: 8px; + font-size: 16px; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s ease; + + &:hover { + background-color: darken(#007AFF, 10%); + } + } +} diff --git a/components/vf-chatbot/assets/ai-assistant-icon.svg b/components/vf-chatbot/assets/ai-assistant-icon.svg new file mode 100644 index 0000000000..a9f68fc555 --- /dev/null +++ b/components/vf-chatbot/assets/ai-assistant-icon.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/vf-chatbot/package.json b/components/vf-chatbot/package.json new file mode 100644 index 0000000000..f3e1cbc3f4 --- /dev/null +++ b/components/vf-chatbot/package.json @@ -0,0 +1,16 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot", + "description": "Visual Framework Chatbot component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot.css", + "sass": "index.scss", + "main": "vf-chatbot.js", + "dependencies": { + "@visual-framework/vf-chatbot-fab": "file:../vf-chatbot-fab", + "@visual-framework/vf-chatbot-modal": "file:../vf-chatbot-modal", + "@visual-framework/vf-sass-config": "^2.7.1" + } +} diff --git a/components/vf-chatbot/vf-chatbot.js b/components/vf-chatbot/vf-chatbot.js new file mode 100644 index 0000000000..f79e35e75c --- /dev/null +++ b/components/vf-chatbot/vf-chatbot.js @@ -0,0 +1,102 @@ +// vf-chatbot +function VFChatbot(element) { + this.el = element; + this.fab = this.el.querySelector("[data-vf-js-chatbot-fab]"); + this.modal = this.el.querySelector("[data-vf-js-chatbot-modal]"); + + this.init(); +} + +VFChatbot.prototype = { + init: function() { + if (!this.fab || !this.modal) return; + + // Handle FAB click + this.fab.addEventListener("click", e => { + e.stopPropagation(); + this.toggleChat(); + }); + + // Handle modal events + this.modal.addEventListener("vf-chatbot-modal:close", () => { + this.fab.classList.remove("vf-chatbot-fab--active"); + }); + + this.modal.addEventListener("vf-chatbot-modal:minimize", () => { + this.fab.classList.remove("vf-chatbot-fab--active"); + }); + + this.modal.addEventListener("vf-chatbot-modal:maximize", () => { + this.fab.classList.add("vf-chatbot-fab--active"); + }); + + // Handle clicks outside modal + document.addEventListener("click", e => { + if ( + !this.modal.classList.contains("vf-chatbot-modal--minimized") && + !this.modal.contains(e.target) && + !this.fab.contains(e.target) + ) { + this.closeChat(); + } + }); + + // Handle escape key + document.addEventListener("keydown", e => { + if ( + e.key === "Escape" && + !this.modal.classList.contains("vf-chatbot-modal--minimized") + ) { + this.closeChat(); + } + }); + }, + + toggleChat: function() { + const isMinimized = this.modal.classList.contains( + "vf-chatbot-modal--minimized" + ); + const isActive = this.modal.classList.contains("vf-chatbot-modal--active"); + + if (isMinimized || !isActive) { + this.openChat(); + } else { + this.minimizeChat(); + } + }, + + openChat: function() { + this.fab.classList.add("vf-chatbot-fab--active"); + this.modal.classList.remove("vf-chatbot-modal--minimized"); + this.modal.classList.add("vf-chatbot-modal--active"); + + // Focus on input if it exists + const input = this.modal.querySelector("[data-vf-js-chatbot-input]"); + if (input) { + setTimeout(() => input.focus(), 300); + } + }, + + minimizeChat: function() { + this.fab.classList.remove("vf-chatbot-fab--active"); + this.modal.classList.add("vf-chatbot-modal--minimized"); + this.modal.classList.remove("vf-chatbot-modal--active"); + }, + + closeChat: function() { + this.fab.classList.remove("vf-chatbot-fab--active"); + this.modal.classList.remove("vf-chatbot-modal--active"); + this.modal.classList.remove("vf-chatbot-modal--minimized"); + }, + + isModalOpen: function() { + return this.modal.classList.contains("vf-chatbot-modal--active"); + } +}; + +function initVFChatbot() { + const elements = document.querySelectorAll("[data-vf-js-chatbot]"); + elements.forEach(element => new VFChatbot(element)); +} + +export { VFChatbot, initVFChatbot }; diff --git a/components/vf-chatbot/vf-chatbot.njk b/components/vf-chatbot/vf-chatbot.njk new file mode 100644 index 0000000000..7c86ef36ca --- /dev/null +++ b/components/vf-chatbot/vf-chatbot.njk @@ -0,0 +1,16 @@ +
+
+ {% render '@vf-chatbot-fab', { + notification_count: notification_count | default(0), + fab_active: fab_active | default(false) + } %} + + {% render '@vf-chatbot-modal', { + title: title | default("Chat with us"), + welcome_message: welcome_message | default("Hello! How can I help you today?"), + input_placeholder: input_placeholder | default("Type your message..."), + show_settings: show_settings | default(true), + ai_icon: "/assets/vf-chatbot/assets/ai-assistant-icon.svg" + } %} +
+
diff --git a/components/vf-chatbot/vf-chatbot.scss b/components/vf-chatbot/vf-chatbot.scss new file mode 100644 index 0000000000..b68e524007 --- /dev/null +++ b/components/vf-chatbot/vf-chatbot.scss @@ -0,0 +1,54 @@ +// vf-chatbot + +@import 'package.variables.scss'; +// @import 'vf-chatbot.variables.scss'; + +.vf-chatbot { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; + + &__container { + position: fixed; + bottom: 20px; + right: 20px; + z-index: 1000; + } + + .vf-chatbot-modal { + position: fixed; + bottom: 90px; // Positioned above the FAB + right: 20px; + width: 360px; + height: 500px; + display: none; + opacity: 0; + transform: translateY(20px); + transition: opacity 0.3s ease, transform 0.3s ease; + + &--active { + display: flex; + flex-direction: column; + opacity: 1; + transform: translateY(0); + } + + @media (max-width: 480px) { + width: calc(100% - 40px); + height: calc(100vh - 120px); + } + } +} + +// Import sub-components +@import '../vf-chatbot-fab/vf-chatbot-fab.scss'; +@import '../vf-chatbot-modal/vf-chatbot-modal.scss'; +@import '../vf-chatbot-prompt/vf-chatbot-prompt.scss'; +// @import '@visual-framework/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss'; +// @import '@visual-framework/vf-chatbot-header/vf-chatbot-header.scss'; +// @import '@visual-framework/vf-chatbot-header-dropdown/vf-chatbot-header-dropdown.scss'; +// @import '@visual-framework/vf-chatbot-dialog/vf-chatbot-dialog.scss'; +// @import '@visual-framework/vf-chatbot-card/vf-chatbot-card.scss'; +// @import '@visual-framework/vf-chatbot-attribution/vf-chatbot-attribution.scss'; +// @import '@visual-framework/vf-chatbot-feedback/vf-chatbot-feedback.scss'; diff --git a/components/vf-componenet-rollup/index.scss b/components/vf-componenet-rollup/index.scss index 7b2f4d2354..1236db66fb 100755 --- a/components/vf-componenet-rollup/index.scss +++ b/components/vf-componenet-rollup/index.scss @@ -144,6 +144,20 @@ button { @import 'vf-mega-menu/vf-mega-menu.scss'; @import 'vf-tree/vf-tree.scss'; +@import 'vf-chatbot/vf-chatbot.scss'; +@import 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss'; +@import 'vf-chatbot-fab/vf-chatbot-fab.scss'; +@import 'vf-chatbot-modal/vf-chatbot-modal.scss'; +@import 'vf-chatbot-prompt/vf-chatbot-prompt.scss'; +@import 'vf-chatbot-standalone/vf-chatbot-standalone.scss'; +@import 'vf-chatbot-welcome/vf-chatbot-welcome.scss'; +// @import 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss'; +// @import 'vf-chatbot-header/vf-chatbot-header.scss'; +// @import 'vf-chatbot-header-dropdown/vf-chatbot-header-dropdown.scss'; +// @import 'vf-chatbot-dialog/vf-chatbot-dialog.scss'; +// @import 'vf-chatbot-card/vf-chatbot-card.scss'; +// @import 'vf-chatbot-attribution/vf-chatbot-attribution.scss'; +// @import 'vf-chatbot-feedback/vf-chatbot-feedback.scss'; /* All Visual Framework Boilerplates */ diff --git a/components/vf-componenet-rollup/scripts copy.js b/components/vf-componenet-rollup/scripts copy.js new file mode 100644 index 0000000000..be17517bbb --- /dev/null +++ b/components/vf-componenet-rollup/scripts copy.js @@ -0,0 +1,115 @@ +/* + * + * scripts.js + * The Visual Framework kitchen sink of JavaScript. + * Import this as a quick way to get *everything*, + * + */ + +// All VF JS +import { vfBanner } from "vf-banner/vf-banner"; +vfBanner(); + +import { vfBannerElixir } from "vf-banner-elixir/vf-banner-elixir"; +vfBannerElixir(); + +// VF Masthead has been deprecated +// https://github.com/visual-framework/vf-core/pull/1406/ +// import { vfMastheadSetStyle } from "vf-masthead/vf-masthead"; +// vfMastheadSetStyle(); + +import { vfGaIndicateLoaded } from "vf-analytics-google/vf-analytics-google"; +let vfGaTrackOptions = { + vfGaTrackPageLoad: true, + // vfGa4MeasurementId: "YourGa4TrackingId" // only required if tracking a custom page-level dimension +}; +vfGaIndicateLoaded(vfGaTrackOptions); + +import { vfTabs } from "vf-tabs/vf-tabs"; +vfTabs(); + +import { vfTree } from "vf-tree/vf-tree"; +vfTree(); + +// import { vfFormFloatLabels } from 'form /assets/vf-form__float-labels.js'; +// vfFormFloatLabels(); + +import { vfSearchClientSide } from "vf-search-client-side/vf-search-client-side"; +// No default invokation + +import { vfShowMore } from "vf-show-more/vf-show-more"; +vfShowMore(); + +import { vfLocationNearest } from "vf-location-nearest/vf-location-nearest"; +// Not invoked by default + +// All EMBL JS +import { emblContentHubLoaderHtmlImports } from "embl-content-hub-loader/embl-content-hub-loader__html-imports"; +import { emblContentHubFetch } from "embl-content-hub-loader/embl-content-hub-loader__fetch"; +import { emblContentHub } from "embl-content-hub-loader/embl-content-hub-loader"; +import { emblConditionalEdit } from "embl-conditional-edit/embl-conditional-edit"; +emblContentHub(); + +import { emblBreadcrumbs } from "embl-breadcrumbs-lookup/embl-breadcrumbs-lookup"; +emblBreadcrumbs(); + +import { vfBackToTop } from "vf-back-to-top/vf-back-to-top.js"; +vfBackToTop(); + +import { vfDropdown } from "vf-dropdown/vf-dropdown.js"; +vfDropdown(); + +import { vfNavigationOnThisPage } from "vf-navigation/vf-navigation.js"; +vfNavigationOnThisPage(); + +import { emblContentMetaProperties_Read } from "embl-content-meta-properties/embl-content-meta-properties"; + +import { emblNotifications } from "embl-notifications/embl-notifications"; +// emblNotifications(); + +import { vfMegaMenu } from 'vf-mega-menu/vf-mega-menu'; +vfMegaMenu(); + +import { vfTable } from 'vf-table/vf-table'; +vfTable(); + +// No default invokation + +// Import chatbot components +import { initVFChatbot } from 'vf-chatbot/vf-chatbot.js'; +import { initVFChatbotModal } from 'vf-chatbot-modal/vf-chatbot-modal.js'; +import { initVFChatbotStandalone } from 'vf-chatbot-standalone/vf-chatbot-standalone.js'; +import { initVFChatbotActionPrompt } from 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; +import { initVFChatbotFab } from 'vf-chatbot-fab/vf-chatbot-fab.js'; +import { initVFChatbotWelcome } from 'vf-chatbot-welcome/vf-chatbot-welcome.js'; +import { initVFChatbotPrompt } from 'vf-chatbot-prompt/vf-chatbot-prompt.js'; + +// Initialize all chatbot components when DOM is loaded +document.addEventListener('DOMContentLoaded', function() { + console.log('Initializing chatbot components...'); + + // Initialize all chatbot components + initVFChatbot(); + initVFChatbotModal(); + initVFChatbotActionPrompt(); + initVFChatbotFab(); + initVFChatbotWelcome(); + initVFChatbotPrompt(); + + // Handle standalone chatbot initialization with error handling + try { + if (typeof window.initVFChatbotStandalone === 'function') { + window.initVFChatbotStandalone(); + } else if (typeof initVFChatbotStandalone === 'function') { + initVFChatbotStandalone(); + } + } catch (error) { + console.warn('Could not initialize standalone chatbot:', error.message); + } +}); + +// Commented out components +// import { initVFChatbotHeader } from 'vf-chatbot-header/vf-chatbot-header.js'; +// import { initVFChatbotHeaderDropdown } from 'vf-chatbot-header-dropdown/vf-chatbot-header-dropdown.js'; +// import { initVFChatbotDialog } from 'vf-chatbot-dialog/vf-chatbot-dialog.js'; +// import { initVFChatbotCard } from 'vf-chatbot-card/vf-chatbot-card.js'; diff --git a/components/vf-componenet-rollup/scripts.js b/components/vf-componenet-rollup/scripts.js index 7629e021ed..3991ed8ab0 100644 --- a/components/vf-componenet-rollup/scripts.js +++ b/components/vf-componenet-rollup/scripts.js @@ -73,4 +73,30 @@ vfMegaMenu(); import { vfTable } from 'vf-table/vf-table'; vfTable(); +import { initVFChatbot } from 'vf-chatbot/vf-chatbot.js'; +import { initVFChatbotModal } from 'vf-chatbot-modal/vf-chatbot-modal.js'; +import { initVFChatbotStandalone } from 'vf-chatbot-standalone/vf-chatbot-standalone.js'; +import { initVFChatbotActionPrompt } from 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; +import { initVFChatbotFab } from 'vf-chatbot-fab/vf-chatbot-fab.js'; +import { initVFChatbotWelcome } from 'vf-chatbot-welcome/vf-chatbot-welcome.js'; +import { initVFChatbotPrompt } from 'vf-chatbot-prompt/vf-chatbot-prompt.js'; + +// Initialize all chatbot components when DOM is loaded +document.addEventListener("DOMContentLoaded", () => { + const chatbotFab = document.querySelector(".vf-chatbot-fab"); + if (chatbotFab) { + chatbotFab.addEventListener("click", () => { + console.log("vf-chatbot-fab clicked"); + initVFChatbot(); + initVFChatbotModal(); + initVFChatbotActionPrompt(); + initVFChatbotFab(); + initVFChatbotWelcome(); + initVFChatbotPrompt(); + }); + } else { + console.error("vf-chatbot-fab button not found in the DOM."); + } +}); + // No default invokation diff --git a/tools/vf-component-library/src/site/_includes/layouts/base.njk b/tools/vf-component-library/src/site/_includes/layouts/base.njk index 37a41700f6..9c69b65fd5 100644 --- a/tools/vf-component-library/src/site/_includes/layouts/base.njk +++ b/tools/vf-component-library/src/site/_includes/layouts/base.njk @@ -359,5 +359,12 @@ Propose a change or discuss it.

{% include "footer.njk" %} + {% render '@vf-chatbot', { + title: "AI Assistant", + welcome_message: "Welcome! How can I help you today?", + notification_count: 0, + fab_active: false, + show_settings: true + } %} diff --git a/tools/vf-component-library/src/site/chatbot/index.njk b/tools/vf-component-library/src/site/chatbot/index.njk new file mode 100644 index 0000000000..4071280c9a --- /dev/null +++ b/tools/vf-component-library/src/site/chatbot/index.njk @@ -0,0 +1,58 @@ + + + + + + AI Assistant | Chatbot + + + + + + + {% render '@vf-chatbot-standalone', { + title: "AI Assistant", + welcome_title: "AI assistant", + welcome_description: "Welcome! I'm here to help you discover bioinformatics training and resources.", + welcome_message: "Hello! How can I help you today?", + input_placeholder: "Ask me about Bioinformatics trainings...", + show_suggestions: true, + show_close_button: true, + ai_icon: "../../assets/vf-chatbot/assets/ai-assistant-icon.svg", + welcome_logo: "../../assets/vf-chatbot/assets/ai-assistant-icon.svg", + welcome_suggestions: [ + 'Find workshops near research institutions', + 'Recommend bioinformatics resources', + 'What prerequisites do I need for advanced advanced courses?' + ] + } %} + + +
+ + diff --git a/tools/vf-component-library/yarn.lock b/tools/vf-component-library/yarn.lock index 368e2e8677..92ff9e8ca6 100644 --- a/tools/vf-component-library/yarn.lock +++ b/tools/vf-component-library/yarn.lock @@ -102,89 +102,89 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.26.2": - version "7.26.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" - integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.26.2", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== dependencies: - "@babel/helper-validator-identifier" "^7.25.9" + "@babel/helper-validator-identifier" "^7.27.1" js-tokens "^4.0.0" - picocolors "^1.0.0" + picocolors "^1.1.1" -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" - integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.8", "@babel/compat-data@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.2.tgz#4183f9e642fd84e74e3eea7ffa93a412e3b102c9" + integrity sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ== "@babel/core@^7.14.6", "@babel/core@^7.16.0": - version "7.26.10" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.10.tgz#5c876f83c8c4dcb233ee4b670c0606f2ac3000f9" - integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.1.tgz#89de51e86bd12246003e3524704c49541b16c3e6" + integrity sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.10" - "@babel/helper-compilation-targets" "^7.26.5" - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.10" - "@babel/parser" "^7.26.10" - "@babel/template" "^7.26.9" - "@babel/traverse" "^7.26.10" - "@babel/types" "^7.26.10" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.27.1" + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helpers" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/template" "^7.27.1" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.26.10", "@babel/generator@^7.27.0": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.0.tgz#764382b5392e5b9aff93cadb190d0745866cbc2c" - integrity sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw== +"@babel/generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.1.tgz#862d4fad858f7208edd487c28b58144036b76230" + integrity sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w== dependencies: - "@babel/parser" "^7.27.0" - "@babel/types" "^7.27.0" + "@babel/parser" "^7.27.1" + "@babel/types" "^7.27.1" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" -"@babel/helper-annotate-as-pure@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" - integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== +"@babel/helper-annotate-as-pure@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz#4345d81a9a46a6486e24d069469f13e60445c05d" + integrity sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow== dependencies: - "@babel/types" "^7.25.9" + "@babel/types" "^7.27.1" -"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz#de0c753b1cd1d9ab55d473c5a5cf7170f0a81880" - integrity sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA== +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.26.5", "@babel/helper-compilation-targets@^7.27.1", "@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== dependencies: - "@babel/compat-data" "^7.26.8" - "@babel/helper-validator-option" "^7.25.9" + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.25.9": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz#518fad6a307c6a96f44af14912b2c20abe9bfc30" - integrity sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/helper-replace-supers" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/traverse" "^7.27.0" +"@babel/helper-create-class-features-plugin@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz#5bee4262a6ea5ddc852d0806199eb17ca3de9281" + integrity sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/traverse" "^7.27.1" semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.25.9": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz#0e41f7d38c2ebe06ebd9cf0e02fb26019c77cd95" - integrity sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ== +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz#05b0882d97ba1d4d03519e4bce615d70afa18c53" + integrity sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-annotate-as-pure" "^7.27.1" regexpu-core "^6.2.0" semver "^6.3.1" @@ -199,146 +199,146 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" -"@babel/helper-member-expression-to-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" - integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ== +"@babel/helper-member-expression-to-functions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz#ea1211276be93e798ce19037da6f06fbb994fa44" + integrity sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA== dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-module-imports@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" - integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== +"@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== +"@babel/helper-module-transforms@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz#e1663b8b71d2de948da5c4fb2a20ca4f3ec27a6f" + integrity sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g== dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-optimise-call-expression@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" - integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ== +"@babel/helper-optimise-call-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200" + integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw== dependencies: - "@babel/types" "^7.25.9" + "@babel/types" "^7.27.1" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.3": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" - integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.3": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== -"@babel/helper-remap-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" - integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== +"@babel/helper-remap-async-to-generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz#4601d5c7ce2eb2aea58328d43725523fcd362ce6" + integrity sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA== dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-wrap-function" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-wrap-function" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-replace-supers@^7.25.9", "@babel/helper-replace-supers@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d" - integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg== +"@babel/helper-replace-supers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz#b1ed2d634ce3bdb730e4b52de30f8cccfd692bc0" + integrity sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA== dependencies: - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/traverse" "^7.26.5" + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-skip-transparent-expression-wrappers@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" - integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA== +"@babel/helper-skip-transparent-expression-wrappers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56" + integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg== dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/helper-validator-identifier@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" - integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== -"@babel/helper-validator-option@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" - integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== +"@babel/helper-validator-option@^7.25.9", "@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== -"@babel/helper-wrap-function@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" - integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g== +"@babel/helper-wrap-function@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz#b88285009c31427af318d4fe37651cd62a142409" + integrity sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ== dependencies: - "@babel/template" "^7.25.9" - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/template" "^7.27.1" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helpers@^7.26.10": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.0.tgz#53d156098defa8243eab0f32fa17589075a1b808" - integrity sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg== +"@babel/helpers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.1.tgz#ffc27013038607cdba3288e692c3611c06a18aa4" + integrity sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ== dependencies: - "@babel/template" "^7.27.0" - "@babel/types" "^7.27.0" + "@babel/template" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/parser@^7.26.10", "@babel/parser@^7.27.0", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.0.tgz#3d7d6ee268e41d2600091cbd4e145ffee85a44ec" - integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg== +"@babel/parser@^7.27.1", "@babel/parser@^7.27.2", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127" + integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw== dependencies: - "@babel/types" "^7.27.0" + "@babel/types" "^7.27.1" "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" - integrity sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz#61dd8a8e61f7eb568268d1b5f129da3eee364bf9" + integrity sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz#af9e4fb63ccb8abcb92375b2fcfe36b60c774d30" - integrity sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz#43f70a6d7efd52370eefbdf55ae03d91b293856d" + integrity sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz#e8dc26fcd616e6c5bf2bd0d5a2c151d4f92a9137" - integrity sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz#beb623bd573b8b6f3047bd04c32506adc3e58a72" + integrity sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz#807a667f9158acac6f6164b4beb85ad9ebc9e1d1" - integrity sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz#e134a5479eb2ba9c02714e8c1ebf1ec9076124fd" + integrity sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/plugin-transform-optional-chaining" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/plugin-transform-optional-chaining" "^7.27.1" "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz#de7093f1e7deaf68eadd7cc6b07f2ab82543269e" - integrity sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz#bb1c25af34d75115ce229a1de7fa44bf8f955670" + integrity sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-proposal-export-namespace-from@^7.14.5": version "7.18.9" @@ -361,18 +361,18 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-import-assertions@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz#620412405058efa56e4a564903b79355020f445f" - integrity sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz#88894aefd2b03b5ee6ad1562a7c8e1587496aecd" + integrity sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-syntax-import-attributes@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz#3b1412847699eea739b4f2602c74ce36f6b0b0f7" - integrity sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" + integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" @@ -383,391 +383,391 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-arrow-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" - integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz#6e2061067ba3ab0266d834a9f94811196f2aba9a" + integrity sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-async-generator-functions@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz#5e3991135e3b9c6eaaf5eff56d1ae5a11df45ff8" - integrity sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz#ca433df983d68e1375398e7ca71bf2a4f6fd89d7" + integrity sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-remap-async-to-generator" "^7.25.9" - "@babel/traverse" "^7.26.8" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-remap-async-to-generator" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-transform-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71" - integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz#9a93893b9379b39466c74474f55af03de78c66e7" + integrity sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA== dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-remap-async-to-generator" "^7.25.9" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-remap-async-to-generator" "^7.27.1" "@babel/plugin-transform-block-scoped-functions@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz#3dc4405d31ad1cbe45293aa57205a6e3b009d53e" - integrity sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz#558a9d6e24cf72802dd3b62a4b51e0d62c0f57f9" + integrity sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-block-scoping@^7.25.9": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz#acc2c0d98a7439bbde4244588ddbd4904701d47f" - integrity sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz#bc0dbe8ac6de5602981ba58ef68c6df8ef9bfbb3" + integrity sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-class-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz#a8ce84fedb9ad512549984101fa84080a9f5f51f" - integrity sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz#dd40a6a370dfd49d32362ae206ddaf2bb082a925" + integrity sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-class-static-block@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz#6c8da219f4eb15cae9834ec4348ff8e9e09664a0" - integrity sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz#7e920d5625b25bbccd3061aefbcc05805ed56ce4" + integrity sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-classes@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" - integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" - "@babel/traverse" "^7.25.9" + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz#03bb04bea2c7b2f711f0db7304a8da46a85cced4" + integrity sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/traverse" "^7.27.1" globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" - integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz#81662e78bf5e734a97982c2b7f0a793288ef3caa" + integrity sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/template" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/template" "^7.27.1" -"@babel/plugin-transform-destructuring@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" - integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== +"@babel/plugin-transform-destructuring@^7.25.9", "@babel/plugin-transform-destructuring@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz#d5916ef7089cb254df0418ae524533c1b72ba656" + integrity sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-dotall-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz#bad7945dd07734ca52fe3ad4e872b40ed09bb09a" - integrity sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz#aa6821de864c528b1fecf286f0a174e38e826f4d" + integrity sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-duplicate-keys@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz#8850ddf57dce2aebb4394bb434a7598031059e6d" - integrity sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz#f1fbf628ece18e12e7b32b175940e68358f546d1" + integrity sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz#6f7259b4de127721a08f1e5165b852fcaa696d31" - integrity sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz#5043854ca620a94149372e69030ff8cb6a9eb0ec" + integrity sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-dynamic-import@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz#23e917de63ed23c6600c5dd06d94669dce79f7b8" - integrity sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz#4c78f35552ac0e06aa1f6e3c573d67695e8af5a4" + integrity sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-exponentiation-operator@^7.26.3": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz#e29f01b6de302c7c2c794277a48f04a9ca7f03bc" - integrity sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz#fc497b12d8277e559747f5a3ed868dd8064f83e1" + integrity sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-export-namespace-from@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz#90745fe55053394f554e40584cda81f2c8a402a2" - integrity sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz#71ca69d3471edd6daa711cf4dfc3400415df9c23" + integrity sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-for-of@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz#27231f79d5170ef33b5111f07fe5cafeb2c96a56" - integrity sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz#bc24f7080e9ff721b63a70ac7b2564ca15b6c40a" + integrity sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" "@babel/plugin-transform-function-name@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" - integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz#4d0bf307720e4dce6d7c30fcb1fd6ca77bdeb3a7" + integrity sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ== dependencies: - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-transform-json-strings@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz#c86db407cb827cded902a90c707d2781aaa89660" - integrity sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz#a2e0ce6ef256376bd527f290da023983527a4f4c" + integrity sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" - integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz#baaefa4d10a1d4206f9dcdda50d7d5827bb70b24" + integrity sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-logical-assignment-operators@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz#b19441a8c39a2fda0902900b306ea05ae1055db7" - integrity sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz#890cb20e0270e0e5bebe3f025b434841c32d5baa" + integrity sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-member-expression-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz#63dff19763ea64a31f5e6c20957e6a25e41ed5de" - integrity sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz#37b88ba594d852418e99536f5612f795f23aeaf9" + integrity sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-modules-amd@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz#49ba478f2295101544abd794486cd3088dddb6c5" - integrity sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz#a4145f9d87c2291fe2d05f994b65dba4e3e7196f" + integrity sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA== dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-modules-commonjs@^7.14.5", "@babel/plugin-transform-modules-commonjs@^7.26.3": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb" - integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz#8e44ed37c2787ecc23bdc367f49977476614e832" + integrity sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw== dependencies: - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-modules-systemjs@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz#8bd1b43836269e3d33307151a114bcf3ba6793f8" - integrity sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz#00e05b61863070d0f3292a00126c16c0e024c4ed" + integrity sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA== dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.1" "@babel/plugin-transform-modules-umd@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz#6710079cdd7c694db36529a1e8411e49fcbf14c9" - integrity sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz#63f2cf4f6dc15debc12f694e44714863d34cd334" + integrity sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w== dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-named-capturing-groups-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" - integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz#f32b8f7818d8fc0cc46ee20a8ef75f071af976e1" + integrity sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-new-target@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz#42e61711294b105c248336dcb04b77054ea8becd" - integrity sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz#259c43939728cad1706ac17351b7e6a7bea1abeb" + integrity sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-nullish-coalescing-operator@^7.26.6": - version "7.26.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz#fbf6b3c92cb509e7b319ee46e3da89c5bedd31fe" - integrity sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz#4f9d3153bf6782d73dd42785a9d22d03197bc91d" + integrity sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-numeric-separator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz#bfed75866261a8b643468b0ccfd275f2033214a1" - integrity sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz#614e0b15cc800e5997dadd9bd6ea524ed6c819c6" + integrity sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-object-rest-spread@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz#0203725025074164808bcf1a2cfa90c652c99f18" - integrity sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg== + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz#67f9ab822347aa2bcee91e8996763da79bdea973" + integrity sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g== dependencies: - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/plugin-transform-parameters" "^7.25.9" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.27.1" + "@babel/plugin-transform-parameters" "^7.27.1" "@babel/plugin-transform-object-super@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz#385d5de135162933beb4a3d227a2b7e52bb4cf03" - integrity sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz#1c932cd27bf3874c43a5cac4f43ebf970c9871b5" + integrity sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" "@babel/plugin-transform-optional-catch-binding@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz#10e70d96d52bb1f10c5caaac59ac545ea2ba7ff3" - integrity sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz#84c7341ebde35ccd36b137e9e45866825072a30c" + integrity sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-optional-chaining@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz#e142eb899d26ef715435f201ab6e139541eee7dd" - integrity sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A== +"@babel/plugin-transform-optional-chaining@^7.25.9", "@babel/plugin-transform-optional-chaining@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz#874ce3c4f06b7780592e946026eb76a32830454f" + integrity sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" -"@babel/plugin-transform-parameters@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" - integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== +"@babel/plugin-transform-parameters@^7.25.9", "@babel/plugin-transform-parameters@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz#80334b54b9b1ac5244155a0c8304a187a618d5a7" + integrity sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-private-methods@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" - integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz#fdacbab1c5ed81ec70dfdbb8b213d65da148b6af" + integrity sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-private-property-in-object@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" - integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz#4dbbef283b5b2f01a21e81e299f76e35f900fb11" + integrity sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-property-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz#d72d588bd88b0dec8b62e36f6fda91cedfe28e3f" - integrity sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz#07eafd618800591e88073a0af1b940d9a42c6424" + integrity sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-regenerator@^7.25.9": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz#822feebef43d6a59a81f696b2512df5b1682db31" - integrity sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz#0a471df9213416e44cd66bf67176b66f65768401" + integrity sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - regenerator-transform "^0.15.2" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-regexp-modifiers@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz#2f5837a5b5cd3842a919d8147e9903cc7455b850" - integrity sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz#df9ba5577c974e3f1449888b70b76169998a6d09" + integrity sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-reserved-words@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz#0398aed2f1f10ba3f78a93db219b27ef417fb9ce" - integrity sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz#40fba4878ccbd1c56605a4479a3a891ac0274bb4" + integrity sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-shorthand-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" - integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz#532abdacdec87bfee1e0ef8e2fcdee543fe32b90" + integrity sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-spread@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" - integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz#1a264d5fc12750918f50e3fe3e24e437178abb08" + integrity sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" "@babel/plugin-transform-sticky-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" - integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz#18984935d9d2296843a491d78a014939f7dcd280" + integrity sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-template-literals@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz#966b15d153a991172a540a69ad5e1845ced990b5" - integrity sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz#1a0eb35d8bb3e6efc06c9fd40eb0bcef548328b8" + integrity sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-typeof-symbol@^7.26.7": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz#044a0890f3ca694207c7826d0c7a65e5ac008aae" - integrity sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz#70e966bb492e03509cf37eafa6dcc3051f844369" + integrity sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw== dependencies: - "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-unicode-escapes@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz#a75ef3947ce15363fccaa38e2dd9bc70b2788b82" - integrity sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz#3e3143f8438aef842de28816ece58780190cf806" + integrity sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-unicode-property-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz#a901e96f2c1d071b0d1bb5dc0d3c880ce8f53dd3" - integrity sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz#bdfe2d3170c78c5691a3c3be934c8c0087525956" + integrity sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-unicode-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" - integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz#25948f5c395db15f609028e370667ed8bae9af97" + integrity sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-unicode-sets-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz#65114c17b4ffc20fa5b163c63c70c0d25621fabe" - integrity sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz#6ab706d10f801b5c72da8bb2548561fa04193cd1" + integrity sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/preset-env@7.26.9": version "7.26.9" @@ -853,42 +853,35 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime@^7.8.4": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.0.tgz#fbee7cf97c709518ecc1f590984481d5460d4762" - integrity sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.27.0": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4" - integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.27.0" - "@babel/types" "^7.27.0" - -"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.27.0": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.0.tgz#11d7e644779e166c0442f9a07274d02cd91d4a70" - integrity sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.27.0" - "@babel/parser" "^7.27.0" - "@babel/template" "^7.27.0" - "@babel/types" "^7.27.0" +"@babel/template@^7.27.1": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291" + integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/template" "^7.27.1" + "@babel/types" "^7.27.1" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.27.0", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.6": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559" - integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg== +"@babel/types@^7.27.1", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.6": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560" + integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q== dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" "@colors/colors@1.5.0": version "1.5.0" @@ -921,9 +914,9 @@ integrity sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg== "@eslint-community/eslint-utils@^4.2.0": - version "4.5.1" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz#b0fc7e06d0c94f801537fd4237edc2706d3b8e4c" - integrity sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w== + version "4.7.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a" + integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw== dependencies: eslint-visitor-keys "^3.4.3" @@ -932,24 +925,24 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint/config-array@^0.19.2": - version "0.19.2" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" - integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== +"@eslint/config-array@^0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.20.0.tgz#7a1232e82376712d3340012a2f561a2764d1988f" + integrity sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ== dependencies: "@eslint/object-schema" "^2.1.6" debug "^4.3.1" minimatch "^3.1.2" -"@eslint/config-helpers@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.0.tgz#12dc8d65c31c4b6c3ebf0758db6601eb7692ce59" - integrity sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ== +"@eslint/config-helpers@^0.2.1": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.2.tgz#3779f76b894de3a8ec4763b79660e6d54d5b1010" + integrity sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg== -"@eslint/core@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.12.0.tgz#5f960c3d57728be9f6c65bd84aa6aa613078798e" - integrity sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg== +"@eslint/core@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.13.0.tgz#bf02f209846d3bf996f9e8009db62df2739b458c" + integrity sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw== dependencies: "@types/json-schema" "^7.0.15" @@ -968,22 +961,22 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.23.0": - version "9.23.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.23.0.tgz#c09ded4f3dc63b40b933bcaeb853fceddb64da30" - integrity sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw== +"@eslint/js@9.26.0": + version "9.26.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.26.0.tgz#1e13126b67a3db15111d2dcc61f69a2acff70bd5" + integrity sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ== "@eslint/object-schema@^2.1.6": version "2.1.6" resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== -"@eslint/plugin-kit@^0.2.7": - version "0.2.7" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz#9901d52c136fb8f375906a73dcc382646c3b6a27" - integrity sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g== +"@eslint/plugin-kit@^0.2.8": + version "0.2.8" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz#47488d8f8171b5d4613e833313f3ce708e3525f8" + integrity sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA== dependencies: - "@eslint/core" "^0.12.0" + "@eslint/core" "^0.13.0" levn "^0.4.1" "@frctl/core@^0.3.5": @@ -1123,9 +1116,9 @@ integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== "@humanwhocodes/retry@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.2.tgz#1860473de7dfa1546767448f333db80cb0ff2161" - integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@iarna/toml@^2.2.5": version "2.2.5" @@ -1195,6 +1188,22 @@ resolved "https://registry.yarnpkg.com/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz#8ace5259254426ccef57f3175bc64ed7095ed919" integrity sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw== +"@modelcontextprotocol/sdk@^1.8.0": + version "1.11.3" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.11.3.tgz#0bcc7b2d74ac1f749d1a7632ec2d674fd7066543" + integrity sha512-rmOWVRUbUJD7iSvJugjUbFZshTAuJ48MXoZ80Osx1GM0K/H1w7rSEvmw8m6vdWxNASgtaHIhAgre4H/E9GJiYQ== + dependencies: + content-type "^1.0.5" + cors "^2.8.5" + cross-spawn "^7.0.5" + eventsource "^3.0.2" + express "^5.0.1" + express-rate-limit "^7.5.0" + pkce-challenge "^5.0.0" + raw-body "^3.0.0" + zod "^3.23.8" + zod-to-json-schema "^3.24.1" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1222,33 +1231,33 @@ integrity sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw== "@octokit/core@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-6.1.4.tgz#f5ccf911cc95b1ce9daf6de425d1664392f867db" - integrity sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg== + version "6.1.5" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-6.1.5.tgz#c2842aae87c2c2130b7dd33e8caa0f642dde2c67" + integrity sha512-vvmsN0r7rguA+FySiCsbaTTobSftpIDIpPW81trAmsv9TGxg3YCujAxRYp/Uy8xmDgYCzzgulG62H7KYUFmeIg== dependencies: "@octokit/auth-token" "^5.0.0" - "@octokit/graphql" "^8.1.2" - "@octokit/request" "^9.2.1" - "@octokit/request-error" "^6.1.7" - "@octokit/types" "^13.6.2" + "@octokit/graphql" "^8.2.2" + "@octokit/request" "^9.2.3" + "@octokit/request-error" "^6.1.8" + "@octokit/types" "^14.0.0" before-after-hook "^3.0.2" universal-user-agent "^7.0.0" -"@octokit/endpoint@^10.1.3": - version "10.1.3" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-10.1.3.tgz#bfe8ff2ec213eb4216065e77654bfbba0fc6d4de" - integrity sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA== +"@octokit/endpoint@^10.1.4": + version "10.1.4" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-10.1.4.tgz#8783be38a32b95af8bcb6523af20ab4eed7a2adb" + integrity sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA== dependencies: - "@octokit/types" "^13.6.2" + "@octokit/types" "^14.0.0" universal-user-agent "^7.0.2" -"@octokit/graphql@^8.1.2": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-8.2.1.tgz#0cb83600e6b4009805acc1c56ae8e07e6c991b78" - integrity sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw== +"@octokit/graphql@^8.2.2": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-8.2.2.tgz#3db48c4ffdf07f99600cee513baf45e73eced4d1" + integrity sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA== dependencies: - "@octokit/request" "^9.2.2" - "@octokit/types" "^13.8.0" + "@octokit/request" "^9.2.3" + "@octokit/types" "^14.0.0" universal-user-agent "^7.0.0" "@octokit/openapi-types@^24.2.0": @@ -1256,6 +1265,11 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-24.2.0.tgz#3d55c32eac0d38da1a7083a9c3b0cca77924f7d3" integrity sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg== +"@octokit/openapi-types@^25.0.0": + version "25.0.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-25.0.0.tgz#adeead36992abf966e89dcd53518d8b0dc910e0d" + integrity sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw== + "@octokit/plugin-paginate-rest@^11.4.2": version "11.6.0" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz#e5e9ff3530e867c3837fdbff94ce15a2468a1f37" @@ -1275,21 +1289,21 @@ dependencies: "@octokit/types" "^13.10.0" -"@octokit/request-error@^6.1.7": - version "6.1.7" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.7.tgz#44fc598f5cdf4593e0e58b5155fe2e77230ff6da" - integrity sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g== +"@octokit/request-error@^6.1.8": + version "6.1.8" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.8.tgz#3c7ce1ca6721eabd43dbddc76b44860de1fdea75" + integrity sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ== dependencies: - "@octokit/types" "^13.6.2" + "@octokit/types" "^14.0.0" -"@octokit/request@^9.2.1", "@octokit/request@^9.2.2": - version "9.2.2" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-9.2.2.tgz#754452ec4692d7fdc32438a14e028eba0e6b2c09" - integrity sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg== +"@octokit/request@^9.2.3": + version "9.2.3" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-9.2.3.tgz#00d023ad690903d952e4dd31e3f5804ef98fcd24" + integrity sha512-Ma+pZU8PXLOEYzsWf0cn/gY+ME57Wq8f49WTXA8FMHp2Ps9djKw//xYJ1je8Hm0pR2lU9FUGeJRWOtxq6olt4w== dependencies: - "@octokit/endpoint" "^10.1.3" - "@octokit/request-error" "^6.1.7" - "@octokit/types" "^13.6.2" + "@octokit/endpoint" "^10.1.4" + "@octokit/request-error" "^6.1.8" + "@octokit/types" "^14.0.0" fast-content-type-parse "^2.0.0" universal-user-agent "^7.0.2" @@ -1303,13 +1317,20 @@ "@octokit/plugin-request-log" "^5.3.1" "@octokit/plugin-rest-endpoint-methods" "^13.3.0" -"@octokit/types@^13.10.0", "@octokit/types@^13.6.2", "@octokit/types@^13.8.0": +"@octokit/types@^13.10.0": version "13.10.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.10.0.tgz#3e7c6b19c0236c270656e4ea666148c2b51fd1a3" integrity sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA== dependencies: "@octokit/openapi-types" "^24.2.0" +"@octokit/types@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-14.0.0.tgz#bbd1d31e2269940789ef143b1c37918aae09adc4" + integrity sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA== + dependencies: + "@octokit/openapi-types" "^25.0.0" + "@one-ini/wasm@0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@one-ini/wasm/-/wasm-0.1.1.tgz#6013659736c9dbfccc96e8a9c2b3de317df39323" @@ -1430,105 +1451,105 @@ "@pnpm/network.ca-file" "^1.0.1" config-chain "^1.1.11" -"@rollup/rollup-android-arm-eabi@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.38.0.tgz#6ba67cc0f3a2d7e3a208256a349c2cb2798f57be" - integrity sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg== - -"@rollup/rollup-android-arm64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.38.0.tgz#c8806f88fd6727d3cf144c4ffb00f40d451b6618" - integrity sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ== - -"@rollup/rollup-darwin-arm64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.38.0.tgz#c4654989b97bba0de7205cf5b3342984d4451d5a" - integrity sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg== - -"@rollup/rollup-darwin-x64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.38.0.tgz#77ee357aeeefe3fe8bee33df18c240e391450476" - integrity sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg== - -"@rollup/rollup-freebsd-arm64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.38.0.tgz#ac8028c99221d1cef22788adda465077d5926911" - integrity sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA== - -"@rollup/rollup-freebsd-x64@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.38.0.tgz#64376ff0e1541cd8677e74898782ec4935277e02" - integrity sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg== - -"@rollup/rollup-linux-arm-gnueabihf@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.38.0.tgz#7de1584c09adcac08f90d1e500c679c428b6eb36" - integrity sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg== - -"@rollup/rollup-linux-arm-musleabihf@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.38.0.tgz#1d5d0f28d93cdc37d60c381c6bbe649bed4960d5" - integrity sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg== - -"@rollup/rollup-linux-arm64-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.38.0.tgz#a97f73a43a374e44bef4a9ed84899c26454831ea" - integrity sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA== - -"@rollup/rollup-linux-arm64-musl@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.38.0.tgz#00e3b646a7976752052ebc72d005808b9e7f2801" - integrity sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ== - -"@rollup/rollup-linux-loongarch64-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.38.0.tgz#0d6dcaa3671cf987faace4b34ab7320ee3c18b65" - integrity sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg== - -"@rollup/rollup-linux-powerpc64le-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.38.0.tgz#54c2d7a4d86767001475f0157c408fd042f7fd8f" - integrity sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw== - -"@rollup/rollup-linux-riscv64-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.38.0.tgz#8cb565417b29851a0c549614898bdab689f23187" - integrity sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg== - -"@rollup/rollup-linux-riscv64-musl@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.38.0.tgz#8bc00b75fd07b15c35a54b41a5f052c01dbf925b" - integrity sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA== - -"@rollup/rollup-linux-s390x-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.38.0.tgz#1fe4a88b97e36d64dbf1f01cfa7842d269a094cf" - integrity sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q== - -"@rollup/rollup-linux-x64-gnu@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.38.0.tgz#11c32c463e68a86e279cda090a9405a7558f9406" - integrity sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w== - -"@rollup/rollup-linux-x64-musl@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.38.0.tgz#520c2a8547672ec6c56a6833f6d38e9380d63dc7" - integrity sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g== - -"@rollup/rollup-win32-arm64-msvc@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.38.0.tgz#d27ab565009357014c9f2d6393ee58bd63a63cb8" - integrity sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg== - -"@rollup/rollup-win32-ia32-msvc@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.38.0.tgz#6c02847c60fcc7a6d74e00a60f350d079558d84d" - integrity sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA== - -"@rollup/rollup-win32-x64-msvc@4.38.0": - version "4.38.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.38.0.tgz#38197da22c1af7b6b5d1cc7541757379193b8e83" - integrity sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw== +"@rollup/rollup-android-arm-eabi@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz#c228d00a41f0dbd6fb8b7ea819bbfbf1c1157a10" + integrity sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg== + +"@rollup/rollup-android-arm64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz#e2b38d0c912169fd55d7e38d723aada208d37256" + integrity sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw== + +"@rollup/rollup-darwin-arm64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz#1fddb3690f2ae33df16d334c613377f05abe4878" + integrity sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w== + +"@rollup/rollup-darwin-x64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz#818298d11c8109e1112590165142f14be24b396d" + integrity sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ== + +"@rollup/rollup-freebsd-arm64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz#91a28dc527d5bed7f9ecf0e054297b3012e19618" + integrity sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ== + +"@rollup/rollup-freebsd-x64@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz#28acadefa76b5c7bede1576e065b51d335c62c62" + integrity sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz#819691464179cbcd9a9f9d3dc7617954840c6186" + integrity sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q== + +"@rollup/rollup-linux-arm-musleabihf@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz#d149207039e4189e267e8724050388effc80d704" + integrity sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg== + +"@rollup/rollup-linux-arm64-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz#fa72ebddb729c3c6d88973242f1a2153c83e86ec" + integrity sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg== + +"@rollup/rollup-linux-arm64-musl@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz#2054216e34469ab8765588ebf343d531fc3c9228" + integrity sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg== + +"@rollup/rollup-linux-loongarch64-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz#818de242291841afbfc483a84f11e9c7a11959bc" + integrity sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw== + +"@rollup/rollup-linux-powerpc64le-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz#0bb4cb8fc4a2c635f68c1208c924b2145eb647cb" + integrity sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q== + +"@rollup/rollup-linux-riscv64-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz#4b3b8e541b7b13e447ae07774217d98c06f6926d" + integrity sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg== + +"@rollup/rollup-linux-riscv64-musl@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz#e065405e67d8bd64a7d0126c931bd9f03910817f" + integrity sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg== + +"@rollup/rollup-linux-s390x-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz#dda3265bbbfe16a5d0089168fd07f5ebb2a866fe" + integrity sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ== + +"@rollup/rollup-linux-x64-gnu@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz#90993269b8b995b4067b7b9d72ff1c360ef90a17" + integrity sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng== + +"@rollup/rollup-linux-x64-musl@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz#fdf5b09fd121eb8d977ebb0fda142c7c0167b8de" + integrity sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA== + +"@rollup/rollup-win32-arm64-msvc@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz#6397e1e012db64dfecfed0774cb9fcf89503d716" + integrity sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg== + +"@rollup/rollup-win32-ia32-msvc@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz#df0991464a52a35506103fe18d29913bf8798a0c" + integrity sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA== + +"@rollup/rollup-win32-x64-msvc@4.40.2": + version "4.40.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz#8dae04d01a2cbd84d6297d99356674c6b993f0fc" + integrity sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA== "@sindresorhus/is@^0.14.0": version "0.14.0" @@ -1574,9 +1595,9 @@ integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== "@types/cors@^2.8.12": - version "2.8.17" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" - integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== + version "2.8.18" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.18.tgz#101e033b3ca06695f3d73c587cd7f9eb348135d1" + integrity sha512-nX3d0sxJW41CqQvfOzVG1NCTXfFDrDWIghCZncpHeWlVFd81zxB/DLhg7avFg6eHLCRX7ckBmoIIcqa++upvJA== dependencies: "@types/node" "*" @@ -1618,11 +1639,11 @@ integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== "@types/node@*", "@types/node@>=10.0.0", "@types/node@>=18": - version "22.13.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.14.tgz#70d84ec91013dcd2ba2de35532a5a14c2b4cc912" - integrity sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w== + version "22.15.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.18.tgz#2f8240f7e932f571c2d45f555ba0b6c3f7a75963" + integrity sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg== dependencies: - undici-types "~6.20.0" + undici-types "~6.21.0" "@types/normalize-package-data@^2.4.3": version "2.4.4" @@ -1659,10 +1680,10 @@ resolved "https://registry.yarnpkg.com/@visual-framework/vf-config/-/vf-config-1.0.1.tgz#d11bdd1a9eae73e49fedfe3e2e8fd8d34c748684" integrity sha512-ZlHMvVGmGxSmgCCcZ59PdaPdif0cZyX99T2LYtjodwvu52Vhri/JxrAFsT46NSVl1bKYyJI+tEXAXBFLBwpt7A== -"@visual-framework/vf-core@^2.2.48": - version "2.2.48" - resolved "https://registry.yarnpkg.com/@visual-framework/vf-core/-/vf-core-2.2.48.tgz#f6f7b7908548d6bf548486759e682bcd05cf4953" - integrity sha512-IaUTzlR+8iASgRiEacePWpMBlKz5bVG/kQensjn0ZdRJouInS7JzyO5lhSFjXg4LIVlpND8WD8iyn1pV6pM4hQ== +"@visual-framework/vf-core@^2.2.49": + version "2.2.49" + resolved "https://registry.yarnpkg.com/@visual-framework/vf-core/-/vf-core-2.2.49.tgz#3d521b227528d2fa7c285695bad109dcde64584a" + integrity sha512-9AhKjycYDhjc12NSZRo8tsMcChSyyiciuDb+0mAarqYnGQqc+Qzsz0YkPd3SGqmnMDHj5mJFe8+2lQKROG2Ufw== dependencies: "@visual-framework/vf-component-generator" "^1.1.7" "@visual-framework/vf-component-initialization" "^1.1.13" @@ -1736,6 +1757,14 @@ abbrev@^2.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== +accepts@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895" + integrity sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng== + dependencies: + mime-types "^3.0.0" + negotiator "^1.0.0" + accepts@~1.3.4, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -2359,6 +2388,21 @@ body-parser@1.20.3: type-is "~1.6.18" unpipe "1.0.0" +body-parser@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.0.tgz#f7a9656de305249a715b549b7b8fd1ab9dfddcfa" + integrity sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg== + dependencies: + bytes "^3.1.2" + content-type "^1.0.5" + debug "^4.4.0" + http-errors "^2.0.0" + iconv-lite "^0.6.3" + on-finished "^2.4.1" + qs "^6.14.0" + raw-body "^3.0.0" + type-is "^2.0.0" + boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -2504,14 +2548,14 @@ browserslist@^2.11.3: electron-to-chromium "^1.3.30" browserslist@^4.24.0, browserslist@^4.24.4: - version "4.24.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" - integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== + version "4.24.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.5.tgz#aa0f5b8560fe81fde84c6dcb38f759bafba0e11b" + integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw== dependencies: - caniuse-lite "^1.0.30001688" - electron-to-chromium "^1.5.73" + caniuse-lite "^1.0.30001716" + electron-to-chromium "^1.5.149" node-releases "^2.0.19" - update-browserslist-db "^1.1.1" + update-browserslist-db "^1.1.3" bs-recipes@1.3.4: version "1.3.4" @@ -2531,7 +2575,7 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -bytes@3.1.2: +bytes@3.1.2, bytes@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== @@ -2564,13 +2608,13 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" -cacheable@^1.8.9: - version "1.8.9" - resolved "https://registry.yarnpkg.com/cacheable/-/cacheable-1.8.9.tgz#f5498999567ae1015761d805bd8bbecd8393fbd4" - integrity sha512-FicwAUyWnrtnd4QqYAoRlNs44/a1jTL7XDKqm5gJ90wz1DQPlC7U2Rd1Tydpv+E7WAr4sQHuw8Q8M3nZMAyecQ== +cacheable@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/cacheable/-/cacheable-1.9.0.tgz#57e3565c311d66371eeb5f2070b6615d43b89711" + integrity sha512-8D5htMCxPDUULux9gFzv30f04Xo3wCnik0oOxKoRTPIBoqA7HtOcJ87uBhQTs3jCfZZTrUBGsYIZOgE0ZRgMAg== dependencies: - hookified "^1.7.1" - keyv "^5.3.1" + hookified "^1.8.2" + keyv "^5.3.3" call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" @@ -2590,7 +2634,7 @@ call-bind@^1.0.8: get-intrinsic "^1.2.4" set-function-length "^1.2.2" -call-bound@^1.0.2, call-bound@^1.0.3: +call-bound@^1.0.2, call-bound@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== @@ -2655,10 +2699,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30001688, caniuse-lite@^1.0.30001702: - version "1.0.30001707" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz#c5e104d199e6f4355a898fcd995a066c7eb9bf41" - integrity sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw== +caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001716: + version "1.0.30001718" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz#dae13a9c80d517c30c6197515a96131c194d8f82" + integrity sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw== capture-stack-trace@^1.0.0: version "1.0.2" @@ -3120,7 +3164,14 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@~1.0.4, content-type@~1.0.5: +content-disposition@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.0.tgz#844426cb398f934caefcbb172200126bc7ceace2" + integrity sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg== + dependencies: + safe-buffer "5.2.1" + +content-type@^1.0.5, content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== @@ -3135,12 +3186,17 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== +cookie-signature@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" + integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== + cookie@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== -cookie@~0.7.2: +cookie@^0.7.1, cookie@~0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -3159,9 +3215,9 @@ copy-props@^4.0.0: is-plain-object "^5.0.0" core-js-compat@^3.40.0: - version "3.41.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.41.0.tgz#4cdfce95f39a8f27759b667cf693d96e5dda3d17" - integrity sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A== + version "3.42.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.42.0.tgz#ce19c29706ee5806e26d3cb3c542d4cfc0ed51bb" + integrity sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ== dependencies: browserslist "^4.24.4" @@ -3175,7 +3231,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cors@~2.8.5: +cors@^2.8.5, cors@~2.8.5: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== @@ -3230,7 +3286,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.3, cross-spawn@^7.0.6: +cross-spawn@^7.0.3, cross-spawn@^7.0.5, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -3365,10 +3421,10 @@ debug@^3.0.0, debug@^3.0.1: dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.7: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.7, debug@^4.4.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== dependencies: ms "^2.1.3" @@ -3476,7 +3532,7 @@ del@^8.0.0: p-map "^7.0.2" slash "^5.1.0" -depd@2.0.0: +depd@2.0.0, depd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -3722,9 +3778,9 @@ easy-transform-stream@^1.0.1: integrity sha512-ktkaa6XR7COAR3oj02CF3IOgz2m1hCaY3SfzvKT4Svt2MhHw9XCt+ncJNWfe2TGz31iqzNGZ8spdKQflj+Rlog== eazy-logger@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-4.0.1.tgz#2e9fe487fb14ed6ac20d5f01d90dff377d403041" - integrity sha512-2GSFtnnC6U4IEKhEI7+PvdxrmjJ04mdsj3wHZTFiw0tUtG4HCWzTr13ZYTk8XOGnA1xQMaDljoBOYlk3D/MMSw== + version "4.1.0" + resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-4.1.0.tgz#d4dae8688b0d730ba1ae6065410b7a51df9990b4" + integrity sha512-+mn7lRm+Zf1UT/YaH8WXtpU6PIV2iOjzP6jgKoiaq/VNrjYKp+OHZGe2znaLgDeFkw8cL9ffuaUm+nNnzcYyGw== dependencies: chalk "4.1.2" @@ -3757,10 +3813,10 @@ ejs@^3.1.10, ejs@^3.1.9: dependencies: jake "^10.8.5" -electron-to-chromium@^1.3.30, electron-to-chromium@^1.5.73: - version "1.5.128" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.128.tgz#8ea537b369c32527b3cc47df7973bffe5d3c2980" - integrity sha512-bo1A4HH/NS522Ws0QNFIzyPcyUUNV/yyy70Ho1xqfGYzPUme2F/xr4tlEOuM6/A538U1vDA7a4XfCd1CKRegKQ== +electron-to-chromium@^1.3.30, electron-to-chromium@^1.5.149: + version "1.5.155" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz#809dd0ae9ae1db87c358e0c0c17c09a2ffc432d1" + integrity sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng== emoji-regex@^10.2.1: version "10.4.0" @@ -3782,16 +3838,16 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +encodeurl@^2.0.0, encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + encodeurl@~1.0.1, encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -encodeurl@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" - integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== - end-of-stream@^1.1.0, end-of-stream@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -3957,7 +4013,7 @@ escape-goat@^2.0.0: resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== -escape-html@~1.0.3: +escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== @@ -4108,21 +4164,22 @@ eslint@^6.0.0: v8-compile-cache "^2.0.3" eslint@^9.0.0: - version "9.23.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.23.0.tgz#b88f3ab6dc83bcb927fdb54407c69ffe5f2441a6" - integrity sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw== + version "9.26.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.26.0.tgz#978fe029adc2aceed28ab437bca876e83461c3b4" + integrity sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.19.2" - "@eslint/config-helpers" "^0.2.0" - "@eslint/core" "^0.12.0" + "@eslint/config-array" "^0.20.0" + "@eslint/config-helpers" "^0.2.1" + "@eslint/core" "^0.13.0" "@eslint/eslintrc" "^3.3.1" - "@eslint/js" "9.23.0" - "@eslint/plugin-kit" "^0.2.7" + "@eslint/js" "9.26.0" + "@eslint/plugin-kit" "^0.2.8" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/retry" "^0.4.2" + "@modelcontextprotocol/sdk" "^1.8.0" "@types/estree" "^1.0.6" "@types/json-schema" "^7.0.15" ajv "^6.12.4" @@ -4147,6 +4204,7 @@ eslint@^9.0.0: minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.3" + zod "^3.24.2" esniff@^2.0.1: version "2.0.1" @@ -4249,6 +4307,18 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== +eventsource-parser@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.2.tgz#0fea1abd26eca8201099ff5212f6c4e7ca2fd5d3" + integrity sha512-6RxOBZ/cYgd8usLwsEl+EC09Au/9BcmCKYF2/xbml6DNczf7nv0MQb+7BA2F+li6//I+28VNlQR37XfQtcAJuA== + +eventsource@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-3.0.7.tgz#1157622e2f5377bb6aef2114372728ba0c156989" + integrity sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA== + dependencies: + eventsource-parser "^3.0.1" + execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -4338,6 +4408,11 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +express-rate-limit@^7.5.0: + version "7.5.0" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.0.tgz#6a67990a724b4fbbc69119419feef50c51e8b28f" + integrity sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg== + express@^4.17.1: version "4.21.2" resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32" @@ -4375,6 +4450,39 @@ express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" +express@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/express/-/express-5.1.0.tgz#d31beaf715a0016f0d53f47d3b4d7acf28c75cc9" + integrity sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA== + dependencies: + accepts "^2.0.0" + body-parser "^2.2.0" + content-disposition "^1.0.0" + content-type "^1.0.5" + cookie "^0.7.1" + cookie-signature "^1.2.1" + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + finalhandler "^2.1.0" + fresh "^2.0.0" + http-errors "^2.0.0" + merge-descriptors "^2.0.0" + mime-types "^3.0.0" + on-finished "^2.4.1" + once "^1.4.0" + parseurl "^1.3.3" + proxy-addr "^2.0.7" + qs "^6.14.0" + range-parser "^1.2.1" + router "^2.2.0" + send "^1.1.0" + serve-static "^2.2.0" + statuses "^2.0.1" + type-is "^2.0.1" + vary "^1.1.2" + ext@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" @@ -4532,12 +4640,12 @@ file-entry-cache@^1.1.1: flat-cache "^1.2.1" object-assign "^4.0.1" -file-entry-cache@^10.0.7: - version "10.0.7" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-10.0.7.tgz#e0ac34d4b8c44bea8a0a27ceb4dae982f2d32749" - integrity sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw== +file-entry-cache@^10.0.8: + version "10.1.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-10.1.0.tgz#54c0117fe76425e9f08a44a3a08bedde0cd93fe8" + integrity sha512-Et/ex6smi3wOOB+n5mek+Grf7P2AxZR5ueqRUvAAn4qkyatXi3cUC1cuQXVkX0VlzBVsN4BkWJFmY/fYiRTdww== dependencies: - flat-cache "^6.1.7" + flat-cache "^6.1.9" file-entry-cache@^2.0.0: version "2.0.0" @@ -4627,6 +4735,18 @@ finalhandler@1.3.1, finalhandler@^1.2.0: statuses "2.0.1" unpipe "~1.0.0" +finalhandler@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.0.tgz#72306373aa89d05a8242ed569ed86a1bff7c561f" + integrity sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q== + dependencies: + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + on-finished "^2.4.1" + parseurl "^1.3.3" + statuses "^2.0.1" + find-up-simple@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/find-up-simple/-/find-up-simple-1.0.1.tgz#18fb90ad49e45252c4d7fca56baade04fa3fca1e" @@ -4743,14 +4863,14 @@ flat-cache@^4.0.0: flatted "^3.2.9" keyv "^4.5.4" -flat-cache@^6.1.7: - version "6.1.7" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-6.1.7.tgz#c04b08316739ad7ef997e1b9ea363443fc2fcb38" - integrity sha512-qwZ4xf1v1m7Rc9XiORly31YaChvKt6oNVHuqqZcoED/7O+ToyNVGobKsIAopY9ODcWpEDKEBAbrSOCBHtNQvew== +flat-cache@^6.1.9: + version "6.1.9" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-6.1.9.tgz#6f512c4ab81c2057577fdb30c2f64022d43db2e7" + integrity sha512-DUqiKkTlAfhtl7g78IuwqYM+YqvT+as0mY+EVk6mfimy19U79pJCzDZQsnqk3Ou/T6hFXWLGbwbADzD/c8Tydg== dependencies: - cacheable "^1.8.9" + cacheable "^1.9.0" flatted "^3.3.3" - hookified "^1.7.1" + hookified "^1.8.2" flatted@^2.0.0: version "2.0.2" @@ -4816,6 +4936,11 @@ fresh@0.5.2, fresh@^0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" + integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== + from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" @@ -5599,10 +5724,10 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" -hookified@^1.7.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.8.1.tgz#74a8c97d36e5f8004d230ee2156a607cc84c358c" - integrity sha512-GrO2l93P8xCWBSTBX9l2BxI78VU/MAAYag+pG8curS3aBGy0++ZlxrQ7PdUOUVMbn5BwkGb6+eRrnf43ipnFEA== +hookified@^1.8.2: + version "1.9.0" + resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.9.0.tgz#271211f61c63b3a68a8ead9d9fddd72b5806c004" + integrity sha512-2yEEGqphImtKIe1NXWEhu6yD3hlFR4Mxk4Mtp3XEyScpSt4pQ4ymmXA1zzxZpj99QkFK+nN0nzjeb2+RUi/6CQ== hosted-git-info@^2.1.4: version "2.8.9" @@ -5672,16 +5797,16 @@ htmlparser2@^7.1.1: entities "^3.0.1" http-cache-semantics@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + version "4.2.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#205f4db64f8562b76a4ff9235aa5279839a09dd5" + integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ== http-equiv-refresh@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-equiv-refresh/-/http-equiv-refresh-1.0.0.tgz#8ec538866042be5f3f7afa737d198d94beb1b07b" integrity sha512-TScO04soylRN9i/QdOdgZyhydXg9z6XdaGzEyOgDKycePeDeTT4KvigjBcI+tgfTlieLWauGORMq5F1eIDa+1w== -http-errors@2.0.0: +http-errors@2.0.0, http-errors@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== @@ -5728,7 +5853,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.6.3: +iconv-lite@0.6.3, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -5756,9 +5881,9 @@ ignore@^5.2.0: integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== ignore@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.3.tgz#397ef9315dfe0595671eefe8b633fec6943ab733" - integrity sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA== + version "7.0.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.4.tgz#a12c70d0f2607c5bf508fb65a40c75f037d7a078" + integrity sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A== immutable@^3: version "3.8.2" @@ -5766,9 +5891,9 @@ immutable@^3: integrity sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg== immutable@^5.0.2: - version "5.1.1" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.1.tgz#d4cb552686f34b076b3dcf23c4384c04424d8354" - integrity sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg== + version "5.1.2" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.2.tgz#e8169476414505e5a4fa650107b65e1227d16d4b" + integrity sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ== import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.1" @@ -5813,10 +5938,10 @@ indent-string@^3.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ== -index-to-position@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/index-to-position/-/index-to-position-1.0.0.tgz#baca236eb6e8c2b750b9225313c31751f84ef357" - integrity sha512-sCO7uaLVhRJ25vz1o8s9IFM3nVS4DkuQnyjMwiQPKvQuBYBDmb8H7zx8ki7nVh4HJQOdVWebyvLE0qt+clruxA== +index-to-position@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/index-to-position/-/index-to-position-1.1.0.tgz#2e50bd54c8040bdd6d9b3d95ec2a8fedf86b4d44" + integrity sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg== indexes-of@^1.0.1: version "1.0.1" @@ -6256,6 +6381,11 @@ is-promise@^2.0.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== +is-promise@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" + integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== + is-property@^1.0.0, is-property@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" @@ -6531,12 +6661,12 @@ json-stable-stringify-without-jsonify@^1.0.1: integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.2.1.tgz#addb683c2b78014d0b78d704c2fcbdf0695a60e2" - integrity sha512-Lp6HbbBgosLmJbjx0pBLbgvx68FaFU1sdkmBuckmhhJ88kL13OA51CDtR2yJB50eCNMH9wRqtQNNiAqQH4YXnA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz#8903cfac42ea1a0f97f35d63a4ce0518f0cc6a70" + integrity sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg== dependencies: call-bind "^1.0.8" - call-bound "^1.0.3" + call-bound "^1.0.4" isarray "^2.0.5" jsonify "^0.0.1" object-keys "^1.1.1" @@ -6607,10 +6737,10 @@ keyv@^4.5.4: dependencies: json-buffer "3.0.1" -keyv@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.3.2.tgz#32edd461b51d44d42926eb72946236d79c71ae78" - integrity sha512-Lji2XRxqqa5Wg+CHLVfFKBImfJZ4pCSccu9eVWK6w4c2SDFLd8JAn1zqTuSFnsxb7ope6rMsnIHfp+eBbRBRZQ== +keyv@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.3.3.tgz#ec2d723fbd7b908de5ee7f56b769d46dbbeaf8ba" + integrity sha512-Rwu4+nXI9fqcxiEHtbkvoes2X+QfkTRo1TMkPfwzipGsJlJO/z69vqB4FNl9xJ3xCpAcbkvmEabZfPzrwN3+gQ== dependencies: "@keyv/serialize" "^1.0.3" @@ -6648,10 +6778,10 @@ known-css-properties@^0.3.0: resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.3.0.tgz#a3d135bbfc60ee8c6eacf2f7e7e6f2d4755e49a4" integrity sha512-QMQcnKAiQccfQTqtBh/qwquGZ2XK/DXND1jrcN9M8gMMy99Gwla7GQjndVUsEqIaRyP6bsFRuhwRj5poafBGJQ== -known-css-properties@^0.35.0: - version "0.35.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.35.0.tgz#f6f8e40ab4e5700fa32f5b2ef5218a56bc853bd6" - integrity sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A== +known-css-properties@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.36.0.tgz#5c4365f3c9549ca2e813d2e729e6c47ef6a6cb60" + integrity sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA== known-css-properties@^0.5.0: version "0.5.0" @@ -6659,9 +6789,9 @@ known-css-properties@^0.5.0: integrity sha512-LOS0CoS8zcZnB1EjLw4LLqDXw8nvt3AGH5dXLQP3D9O1nLLA+9GC5GnPl5mmF+JiQAtSX4VyZC7KvEtcA4kUtA== ky@^1.2.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/ky/-/ky-1.8.0.tgz#0f4c83be590555a2b435d11459b460324b0038fc" - integrity sha512-DoKGmG27nT8t/1F9gV8vNzggJ3mLAyD49J8tTMWHeZvS8qLc7GlyTieicYtFzvDznMe/q2u38peOjkWc5/pjvw== + version "1.8.1" + resolved "https://registry.yarnpkg.com/ky/-/ky-1.8.1.tgz#b1adaa473bc30aced2bab4c408ec177b78d198f0" + integrity sha512-7Bp3TpsE+L+TARSnnDpk3xg8Idi8RwSLdj6CMbNWoOARIrGrbuLGusV0dYwbZOm4bB3jHNxSw8Wk/ByDqJEnDw== last-run@^2.0.0: version "2.0.0" @@ -6755,9 +6885,9 @@ linkify-it@^4.0.1: uc.micro "^1.0.1" liquidjs@^10.7.0: - version "10.21.0" - resolved "https://registry.yarnpkg.com/liquidjs/-/liquidjs-10.21.0.tgz#d3e43df2144bf6fc12c3ee1f3e6dcabd65b22ba9" - integrity sha512-DouqxNU2jfoZzb1LinVjOc/f6ssitGIxiDJT+kEKyYqPSSSd+WmGOAhtWbVm1/n75svu4aQ+FyQ3ctd3wh1bbw== + version "10.21.1" + resolved "https://registry.yarnpkg.com/liquidjs/-/liquidjs-10.21.1.tgz#5867dac16f1a74552e1ca5fdc976c0fa4bcdf527" + integrity sha512-NZXmCwv3RG5nire3fmIn9HsOyJX3vo+ptp0yaXUHAMzSNBhx74Hm+dAGJvscUA6lNqbLuYfXgNavRQ9UbUJhQQ== dependencies: commander "^10.0.0" @@ -7245,10 +7375,10 @@ mdn-data@2.12.2: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.12.2.tgz#9ae6c41a9e65adf61318b32bff7b64fbfb13f8cf" integrity sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA== -mdn-data@^2.15.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.18.0.tgz#518adc4811817a8b8c88e0e67d985b8f42e968d5" - integrity sha512-gtCy1yim/vpHF/tq3B4Z43x3zKWpYeb4IM3d/Mf4oMYcNuoXOYEaqtoFlLHw9zd7+WNN3jNh6/WXyUrD3OIiwQ== +mdn-data@^2.21.0: + version "2.21.0" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.21.0.tgz#f3a495e8b1e60cb4fbeaf9136aefba2f987a56e1" + integrity sha512-+ZKPQezM5vYJIkCxaC+4DTnRrVZR1CgsKLu5zsQERQx6Tea8Y+wMx5A24rq8A8NepCeatIQufVAekKNgiBMsGQ== mdurl@^1.0.1: version "1.0.1" @@ -7260,6 +7390,11 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== +media-typer@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" + integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== + mem-fs-editor@^11.0.1: version "11.1.4" resolved "https://registry.yarnpkg.com/mem-fs-editor/-/mem-fs-editor-11.1.4.tgz#ddfe705f3b0110cb96a40a3cad290ca21f0d1900" @@ -7325,6 +7460,11 @@ merge-descriptors@1.0.3: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== +merge-descriptors@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz#ea922f660635a2249ee565e0449f951e6b603808" + integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -7396,6 +7536,18 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +mime-db@^1.54.0: + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + +mime-types@^3.0.0, mime-types@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.1.tgz#b1d94d6997a9b32fd69ebaed0db73de8acb519ce" + integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== + dependencies: + mime-db "^1.54.0" + mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" @@ -7534,9 +7686,9 @@ moo@^0.5.2: integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q== morphdom@^2.7.0: - version "2.7.4" - resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.7.4.tgz#c61d511e935cc25ca588dfaa752461f27865865e" - integrity sha512-ATTbWMgGa+FaMU3FhnFYB6WgulCqwf6opOll4CBzmVDTLvPMmUPrEv8CudmLPK0MESa64+6B89fWOxP3+YIlxQ== + version "2.7.5" + resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.7.5.tgz#1f3942c85df3745a28674c41ddad572910259c05" + integrity sha512-z6bfWFMra7kBqDjQGHud1LSXtq5JJC060viEkQFMBX6baIecpkNr2Ywrn2OQfWP3rXiNFQRPoFjD8/TvJcWcDg== ms@2.0.0: version "2.0.0" @@ -7632,6 +7784,11 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" + integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== + neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -7868,7 +8025,7 @@ object.pick@^1.2.0, object.pick@^1.3.0: dependencies: isobject "^3.0.1" -on-finished@2.4.1: +on-finished@2.4.1, on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== @@ -8120,13 +8277,13 @@ parse-json@^5.2.0: lines-and-columns "^1.1.6" parse-json@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-8.2.0.tgz#794a590dcf54588ec2282ce6065f15121fa348a0" - integrity sha512-eONBZy4hm2AgxjNFd8a4nyDJnzUAH0g34xSQAwWEVGCjdZ4ZL7dKZBfq267GWP/JaS9zW62Xs2FeAdDvpHHJGQ== + version "8.3.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-8.3.0.tgz#88a195a2157025139a2317a4f2f9252b61304ed5" + integrity sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ== dependencies: "@babel/code-frame" "^7.26.2" - index-to-position "^1.0.0" - type-fest "^4.37.0" + index-to-position "^1.1.0" + type-fest "^4.39.1" parse-node-version@^1.0.0: version "1.0.1" @@ -8143,7 +8300,7 @@ parse-srcset@^1.0.2: resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" integrity sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q== -parseurl@~1.3.2, parseurl@~1.3.3: +parseurl@^1.3.3, parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== @@ -8230,6 +8387,11 @@ path-to-regexp@^6.2.0, path-to-regexp@^6.2.1: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== +path-to-regexp@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.2.0.tgz#73990cc29e57a3ff2a0d914095156df5db79e8b4" + integrity sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ== + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -8300,6 +8462,11 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== +pkce-challenge@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkce-challenge/-/pkce-challenge-5.0.0.tgz#c3a405cb49e272094a38e890a2b51da0228c4d97" + integrity sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ== + pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -8607,7 +8774,7 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== -proxy-addr@~2.0.7: +proxy-addr@^2.0.7, proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -8755,6 +8922,13 @@ qs@6.13.0: dependencies: side-channel "^1.0.6" +qs@^6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== + dependencies: + side-channel "^1.1.0" + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -8774,7 +8948,7 @@ randomatic@^3.0.0: kind-of "^6.0.0" math-random "^1.0.1" -range-parser@~1.2.0, range-parser@~1.2.1: +range-parser@^1.2.1, range-parser@~1.2.0, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== @@ -8789,6 +8963,16 @@ raw-body@2.5.2, raw-body@^2.3.2: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.0.tgz#25b3476f07a51600619dae3fe82ddc28a36e5e0f" + integrity sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.6.3" + unpipe "1.0.0" + rc@1.2.8, rc@^1.0.1, rc@^1.1.6, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -8973,18 +9157,6 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regenerator-transform@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" - integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== - dependencies: - "@babel/runtime" "^7.8.4" - regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" @@ -9324,34 +9496,45 @@ rollup-plugin-includepaths@^0.2.4: integrity sha512-iZen+XKVExeCzk7jeSZPJKL7B67slZNr8GXSC5ROBXtDGXDBH8wdjMfdNW5hf9kPt+tHyIvWh3wlE9bPrZL24g== rollup@^4.0.0: - version "4.38.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.38.0.tgz#e1ef4939aef0e1295f750ae4f73d1c8b7fc3abb8" - integrity sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw== + version "4.40.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.40.2.tgz#778e88b7a197542682b3e318581f7697f55f0619" + integrity sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg== dependencies: "@types/estree" "1.0.7" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.38.0" - "@rollup/rollup-android-arm64" "4.38.0" - "@rollup/rollup-darwin-arm64" "4.38.0" - "@rollup/rollup-darwin-x64" "4.38.0" - "@rollup/rollup-freebsd-arm64" "4.38.0" - "@rollup/rollup-freebsd-x64" "4.38.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.38.0" - "@rollup/rollup-linux-arm-musleabihf" "4.38.0" - "@rollup/rollup-linux-arm64-gnu" "4.38.0" - "@rollup/rollup-linux-arm64-musl" "4.38.0" - "@rollup/rollup-linux-loongarch64-gnu" "4.38.0" - "@rollup/rollup-linux-powerpc64le-gnu" "4.38.0" - "@rollup/rollup-linux-riscv64-gnu" "4.38.0" - "@rollup/rollup-linux-riscv64-musl" "4.38.0" - "@rollup/rollup-linux-s390x-gnu" "4.38.0" - "@rollup/rollup-linux-x64-gnu" "4.38.0" - "@rollup/rollup-linux-x64-musl" "4.38.0" - "@rollup/rollup-win32-arm64-msvc" "4.38.0" - "@rollup/rollup-win32-ia32-msvc" "4.38.0" - "@rollup/rollup-win32-x64-msvc" "4.38.0" + "@rollup/rollup-android-arm-eabi" "4.40.2" + "@rollup/rollup-android-arm64" "4.40.2" + "@rollup/rollup-darwin-arm64" "4.40.2" + "@rollup/rollup-darwin-x64" "4.40.2" + "@rollup/rollup-freebsd-arm64" "4.40.2" + "@rollup/rollup-freebsd-x64" "4.40.2" + "@rollup/rollup-linux-arm-gnueabihf" "4.40.2" + "@rollup/rollup-linux-arm-musleabihf" "4.40.2" + "@rollup/rollup-linux-arm64-gnu" "4.40.2" + "@rollup/rollup-linux-arm64-musl" "4.40.2" + "@rollup/rollup-linux-loongarch64-gnu" "4.40.2" + "@rollup/rollup-linux-powerpc64le-gnu" "4.40.2" + "@rollup/rollup-linux-riscv64-gnu" "4.40.2" + "@rollup/rollup-linux-riscv64-musl" "4.40.2" + "@rollup/rollup-linux-s390x-gnu" "4.40.2" + "@rollup/rollup-linux-x64-gnu" "4.40.2" + "@rollup/rollup-linux-x64-musl" "4.40.2" + "@rollup/rollup-win32-arm64-msvc" "4.40.2" + "@rollup/rollup-win32-ia32-msvc" "4.40.2" + "@rollup/rollup-win32-x64-msvc" "4.40.2" fsevents "~2.3.2" +router@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef" + integrity sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ== + dependencies: + debug "^4.4.0" + depd "^2.0.0" + is-promise "^4.0.0" + parseurl "^1.3.3" + path-to-regexp "^8.0.0" + run-async@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" @@ -9496,9 +9679,9 @@ semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.3.4, semver@^7.3.5, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0: - version "7.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" - integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== send@0.16.2: version "0.16.2" @@ -9538,6 +9721,23 @@ send@0.19.0: range-parser "~1.2.1" statuses "2.0.1" +send@^1.1.0, send@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/send/-/send-1.2.0.tgz#32a7554fb777b831dfa828370f773a3808d37212" + integrity sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw== + dependencies: + debug "^4.3.5" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + fresh "^2.0.0" + http-errors "^2.0.0" + mime-types "^3.0.1" + ms "^2.1.3" + on-finished "^2.4.1" + range-parser "^1.2.1" + statuses "^2.0.1" + serve-index@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -9571,6 +9771,16 @@ serve-static@1.16.2: parseurl "~1.3.3" send "0.19.0" +serve-static@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.0.tgz#9c02564ee259bdd2251b82d659a2e7e1938d66f9" + integrity sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ== + dependencies: + encodeurl "^2.0.0" + escape-html "^1.0.3" + parseurl "^1.3.3" + send "^1.2.0" + server-destroy@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" @@ -9666,7 +9876,7 @@ side-channel-weakmap@^1.0.2: object-inspect "^1.13.3" side-channel-map "^1.0.1" -side-channel@^1.0.6: +side-channel@^1.0.6, side-channel@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== @@ -9943,7 +10153,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -statuses@2.0.1: +statuses@2.0.1, statuses@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== @@ -10208,23 +10418,23 @@ stylelint-order@^6.0.0: postcss-sorting "^8.0.2" stylelint-scss@^6.11.1: - version "6.11.1" - resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.11.1.tgz#03860aab250112825b2deb77ca7ff1e2ba3a5414" - integrity sha512-e4rYo0UY+BIMtGeGanghrvHTjcryxgZbyFxUedp8dLFqC4P70aawNdYjRrQxbnKhu3BNr4+lt5e/53tcKXiwFA== + version "6.12.0" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.12.0.tgz#38cf41c3b8a76f34cd7267e4c30e7e66d35619c2" + integrity sha512-U7CKhi1YNkM1pXUXl/GMUXi8xKdhl4Ayxdyceie1nZ1XNIdaUgMV6OArpooWcDzEggwgYD0HP/xIgVJo9a655w== dependencies: css-tree "^3.0.1" is-plain-object "^5.0.0" - known-css-properties "^0.35.0" - mdn-data "^2.15.0" + known-css-properties "^0.36.0" + mdn-data "^2.21.0" postcss-media-query-parser "^0.2.3" postcss-resolve-nested-selector "^0.1.6" postcss-selector-parser "^7.1.0" postcss-value-parser "^4.2.0" stylelint@^16.0.0: - version "16.17.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.17.0.tgz#12f31389283883d8d15bb5c019830af8176998a1" - integrity sha512-I9OwVIWRMqVm2Br5iTbrfSqGRPWQUlvm6oXO1xZuYYu0Gpduy67N8wXOZv15p6E/JdlZiAtQaIoLKZEWk5hrjw== + version "16.19.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.19.1.tgz#486b95fa7518a3077ee2802bc6dda2174bc097bb" + integrity sha512-C1SlPZNMKl+d/C867ZdCRthrS+6KuZ3AoGW113RZCOL0M8xOGpgx7G70wq7lFvqvm4dcfdGFVLB/mNaLFChRKw== dependencies: "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" @@ -10239,7 +10449,7 @@ stylelint@^16.0.0: debug "^4.3.7" fast-glob "^3.3.3" fastest-levenshtein "^1.0.16" - file-entry-cache "^10.0.7" + file-entry-cache "^10.0.8" global-modules "^2.0.0" globby "^11.1.0" globjoin "^0.1.4" @@ -10247,7 +10457,7 @@ stylelint@^16.0.0: ignore "^7.0.3" imurmurhash "^0.1.4" is-plain-object "^5.0.0" - known-css-properties "^0.35.0" + known-css-properties "^0.36.0" mathml-tag-names "^2.1.3" meow "^13.2.0" micromatch "^4.0.8" @@ -10650,10 +10860,19 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-fest@^4.37.0, type-fest@^4.6.0: - version "4.38.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.38.0.tgz#659fa14d1a71c2811400aa3b5272627e0c1e6b96" - integrity sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg== +type-fest@^4.39.1, type-fest@^4.6.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + +type-is@^2.0.0, type-is@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.0.1.tgz#64f6cf03f92fce4015c2b224793f6bdd4b068c97" + integrity sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw== + dependencies: + content-type "^1.0.5" + media-typer "^1.1.0" + mime-types "^3.0.0" type-is@~1.6.18: version "1.6.18" @@ -10720,10 +10939,10 @@ undertaker@^2.0.0: last-run "^2.0.0" undertaker-registry "^2.0.0" -undici-types@~6.20.0: - version "6.20.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" - integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== unherit@^1.0.4: version "1.1.3" @@ -10846,9 +11065,9 @@ unist-util-visit@^1.1.0: unist-util-visit-parents "^2.0.0" universal-user-agent@^7.0.0, universal-user-agent@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-7.0.2.tgz#52e7d0e9b3dc4df06cc33cb2b9fd79041a54827e" - integrity sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q== + version "7.0.3" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-7.0.3.tgz#c05870a58125a2dc00431f2df815a77fe69736be" + integrity sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A== universalify@^0.1.0: version "0.1.2" @@ -10878,7 +11097,7 @@ unzip-response@^2.0.1: resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" integrity sha512-N0XH6lqDtFH84JxptQoZYmloF4nzrQqqrAymNj+/gW60AO2AZgOcf4O/nUXJcYfyQkqvMo9lSupBZmmgvuVXlw== -update-browserslist-db@^1.1.1: +update-browserslist-db@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== @@ -11010,7 +11229,7 @@ value-or-function@^4.0.0: resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-4.0.0.tgz#70836b6a876a010dc3a2b884e7902e9db064378d" integrity sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg== -vary@^1, vary@~1.1.2: +vary@^1, vary@^1.1.2, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== @@ -11287,9 +11506,9 @@ write@^0.2.1: mkdirp "^0.5.1" ws@^8.13.0: - version "8.18.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" - integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w== + version "8.18.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.2.tgz#42738b2be57ced85f46154320aabb51ab003705a" + integrity sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ== ws@~8.17.1: version "8.17.1" @@ -11431,3 +11650,13 @@ yosay@^3.0.0: string-width "^6.1.0" strip-ansi "^7.1.0" wrap-ansi "^8.1.0" + +zod-to-json-schema@^3.24.1: + version "3.24.5" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz#d1095440b147fb7c2093812a53c54df8d5df50a3" + integrity sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g== + +zod@^3.23.8, zod@^3.24.2: + version "3.24.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.4.tgz#e2e2cca5faaa012d76e527d0d36622e0a90c315f" + integrity sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg== From 518d5cd07fa783b45bde8fff453ff2a30a11c800 Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Fri, 30 May 2025 23:24:56 +0100 Subject: [PATCH 05/71] VF chatbot- More components added --- .../vf-chatbot-action-prompt.scss | 3 +- components/vf-chatbot-feedback/README.md | 36 +++ components/vf-chatbot-feedback/package.json | 15 + .../vf-chatbot-feedback.config.yml | 14 + .../vf-chatbot-feedback.js | 229 +++++++++++++++ .../vf-chatbot-feedback.njk | 15 + .../vf-chatbot-feedback.scss | 155 ++++++++++ .../vf-chatbot-modal/vf-chatbot-modal.scss | 7 +- components/vf-chatbot-router/README.md | 55 ++++ components/vf-chatbot-router/package.json | 14 + .../vf-chatbot-router.config.yml | 43 +++ .../vf-chatbot-router/vf-chatbot-router.js | 220 +++++++++++++++ .../vf-chatbot-router/vf-chatbot-router.njk | 36 +++ .../vf-chatbot-router/vf-chatbot-router.scss | 155 ++++++++++ components/vf-chatbot-sources/package.json | 14 + .../vf-chatbot-sources/vf-chatbot-sources.js | 62 ++++ .../vf-chatbot-sources/vf-chatbot-sources.njk | 10 + .../vf-chatbot-sources.scss | 104 +++++++ components/vf-chatbot-standalone/package.json | 3 +- .../vf-chatbot-standalone.config.yml | 1 + .../vf-chatbot-standalone.js | 192 ++++++++++++- .../vf-chatbot-standalone.njk | 145 ++++++++-- .../vf-chatbot-standalone.scss | 267 ++++++++++++------ .../vf-chatbot/assets/vf-icon--avatar.svg | 1 + components/vf-chatbot/vf-chatbot.scss | 1 + components/vf-componenet-rollup/index.scss | 9 +- components/vf-componenet-rollup/scripts.js | 7 +- 27 files changed, 1678 insertions(+), 135 deletions(-) create mode 100644 components/vf-chatbot-feedback/README.md create mode 100644 components/vf-chatbot-feedback/package.json create mode 100644 components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml create mode 100644 components/vf-chatbot-feedback/vf-chatbot-feedback.js create mode 100644 components/vf-chatbot-feedback/vf-chatbot-feedback.njk create mode 100644 components/vf-chatbot-feedback/vf-chatbot-feedback.scss create mode 100644 components/vf-chatbot-router/README.md create mode 100644 components/vf-chatbot-router/package.json create mode 100644 components/vf-chatbot-router/vf-chatbot-router.config.yml create mode 100644 components/vf-chatbot-router/vf-chatbot-router.js create mode 100644 components/vf-chatbot-router/vf-chatbot-router.njk create mode 100644 components/vf-chatbot-router/vf-chatbot-router.scss create mode 100644 components/vf-chatbot-sources/package.json create mode 100644 components/vf-chatbot-sources/vf-chatbot-sources.js create mode 100644 components/vf-chatbot-sources/vf-chatbot-sources.njk create mode 100644 components/vf-chatbot-sources/vf-chatbot-sources.scss create mode 100644 components/vf-chatbot/assets/vf-icon--avatar.svg diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss index 723d503938..b9536a163c 100644 --- a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss @@ -1,10 +1,9 @@ .vf-chatbot-action-prompt { display: inline-block; - margin: 8px 8px 8px 0; &__link { display: inline-block; - padding: 12px 16px; + padding: 10px 10px; border: 1px solid #4b7fd1; // Thin blue border color: #4b7fd1; // Blue text background-color: #FFFFFF; diff --git a/components/vf-chatbot-feedback/README.md b/components/vf-chatbot-feedback/README.md new file mode 100644 index 0000000000..b0a6b3a763 --- /dev/null +++ b/components/vf-chatbot-feedback/README.md @@ -0,0 +1,36 @@ +# Chatbot Feedback component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-feedback.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-feedback) + +## About + +A feedback component for the Visual Framework chatbot that allows users to: +- Provide thumbs up/down feedback on responses +- Select specific feedback options based on their response +- Add custom comments +- See success/error states with closeable banners + +## Usage + +### JavaScript + +```js +import { initVFChatbotFeedback } from '@visual-framework/vf-chatbot-feedback/vf-chatbot-feedback.js'; +// Or import directly +// import { initVFChatbotFeedback } from '../components/raw/vf-chatbot-feedback/vf-chatbot-feedback.js'; + +initVFChatbotFeedback(); +``` + +### Features + +1. Dynamic feedback options based on thumbs up/down selection +2. Smooth scroll behavior for feedback form visibility +3. Success and error states with closeable banners +4. Visual feedback with solid state thumb icons +5. Comment section for detailed feedback + +### Dependencies + +- @visual-framework/vf-sass-config +- @visual-framework/vf-banner diff --git a/components/vf-chatbot-feedback/package.json b/components/vf-chatbot-feedback/package.json new file mode 100644 index 0000000000..2b3250c4cb --- /dev/null +++ b/components/vf-chatbot-feedback/package.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-feedback", + "description": "Visual Framework Chatbot Feedback component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-feedback.css", + "sass": "index.scss", + "main": "vf-chatbot-feedback.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config", + "@visual-framework/vf-banner": "^2.0.5" + } +} diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml b/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml new file mode 100644 index 0000000000..979884b8f1 --- /dev/null +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml @@ -0,0 +1,14 @@ +title: Chatbot Feedback Component +label: Chatbot Feedback +status: alpha +context: + positiveFeedbackOptions: + - 'Accurate answer' + - 'Easy to understand' + - 'Well formatted' + - 'Helpful' + negativeFeedbackOptions: + - 'Inaccurate answer' + - 'Did not use context' + - 'Poorly formatted' + - 'Not helpful' diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.js b/components/vf-chatbot-feedback/vf-chatbot-feedback.js new file mode 100644 index 0000000000..74d16e9634 --- /dev/null +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.js @@ -0,0 +1,229 @@ +export class VFChatbotFeedback { + constructor(element, responseId) { + if (!element) { + console.error("Feedback element is required"); + return; + } + + this.el = element; + this.responseId = responseId; + this.selectedFeedback = null; + this.positiveFeedbackOptions = [ + "Accurate answer", + "Easy to understand", + "Well formatted", + "Helpful" + ]; + this.negativeFeedbackOptions = [ + "Inaccurate answer", + "Did not use context", + "Poorly formatted", + "Not helpful" + ]; + + // API configuration - Mistral AI + this.API_TOKEN = ""; + this.API_URL = "https://api.mistral.ai/v1/chat/completions"; + + // Initialize after ensuring element exists + this.init(); + } + + init() { + // Ensure element exists before querying + if (!this.el) return; + + const thumbsUp = this.el.querySelector("[data-vf-js-feedback-thumbs-up]"); + const thumbsDown = this.el.querySelector( + "[data-vf-js-feedback-thumbs-down]" + ); + + if (thumbsUp) { + thumbsUp.addEventListener("click", () => + this.handleThumbsClick("positive") + ); + } + + if (thumbsDown) { + thumbsDown.addEventListener("click", () => + this.handleThumbsClick("negative") + ); + } + } + + handleThumbsClick(type) { + // First remove solid class from both thumbs + const thumbsUp = this.el.querySelector("[data-vf-js-feedback-thumbs-up]"); + const thumbsDown = this.el.querySelector( + "[data-vf-js-feedback-thumbs-down]" + ); + thumbsUp?.classList.remove("vf-chatbot-feedback__thumb--solid"); + thumbsDown?.classList.remove("vf-chatbot-feedback__thumb--solid"); + + // Make the clicked thumb solid + const selectedThumb = this.el.querySelector( + type === "positive" + ? "[data-vf-js-feedback-thumbs-up]" + : "[data-vf-js-feedback-thumbs-down]" + ); + selectedThumb?.classList.add("vf-chatbot-feedback__thumb--solid"); + + this.selectedFeedback = type; + this.showFeedbackForm(type); + } + + showFeedbackForm(type) { + const formContainer = this.el.querySelector(".vf-chatbot-feedback__form"); + + // Clear any existing content (form or banners) + formContainer.innerHTML = ""; + + const feedbackOptions = + type === "positive" + ? this.positiveFeedbackOptions + : this.negativeFeedbackOptions; + const formTitle = "Tell us more about your response"; + + const formEl = document.createElement("div"); + formEl.className = "vf-chatbot-feedback__form-content"; + formEl.innerHTML = ` +

${formTitle}

+
+ ${feedbackOptions + .map( + option => ` + + ` + ) + .join("")} +
+

Comments

+ + + `; + + // Add event listeners for options + const options = formEl.querySelectorAll(".vf-chatbot-feedback__option"); + options.forEach(option => { + option.addEventListener("click", e => { + // Remove selected class from all options + options.forEach(opt => + opt.classList.remove("vf-chatbot-feedback__option--selected") + ); + // Add selected class to clicked option + e.target.classList.add("vf-chatbot-feedback__option--selected"); + }); + }); + + // Add submit handler + const submitBtn = formEl.querySelector(".vf-chatbot-feedback__submit"); + submitBtn.addEventListener("click", () => this.submitFeedback()); + + formContainer.appendChild(formEl); + // Scroll the form into view + formEl.scrollIntoView({ behavior: "smooth", block: "nearest" }); + + // // Ensure the feedback form is visible + // setTimeout(() => { + // formContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + // }, 100); + } + + async submitFeedback() { + // const selectedOption = this.el.querySelector( + // ".vf-chatbot-action-prompt--selected" + // ); + // const comment = this.el.querySelector(".vf-chatbot-feedback__comment") + // .value; + + // if (response.ok) { + this.showSuccess(); + // } else { + // this.showError(); + // } + // } catch (error) { + // this.showError(); + // } + } + + showSuccess() { + const formContainer = this.el.querySelector(".vf-chatbot-feedback__form"); + formContainer.innerHTML = ` +
+
+

Thank you for the feedback!

+ +
+
+ `; + + // Add close button event listener + const closeBtn = formContainer.querySelector(".vf-banner__close"); + if (closeBtn) { + closeBtn.addEventListener("click", () => { + formContainer.innerHTML = ""; + }); + } + + // Hide the unselected thumb by setting display: none + const otherThumb = this.el.querySelector( + this.selectedFeedback === "positive" + ? "[data-vf-js-feedback-thumbs-down]" + : "[data-vf-js-feedback-thumbs-up]" + ); + if (otherThumb) { + otherThumb.style.display = "none"; + } + + // Add solid class only to the selected thumb + const selectedThumb = this.el.querySelector( + this.selectedFeedback === "positive" + ? "[data-vf-js-feedback-thumbs-up]" + : "[data-vf-js-feedback-thumbs-down]" + ); + selectedThumb?.classList.add("vf-chatbot-feedback__thumb--solid"); + } + + showError() { + const formContainer = this.el.querySelector(".vf-chatbot-feedback__form"); + formContainer.innerHTML = ` +
+
+

Failed to submit feedback. Please try again.

+ +
+
+ `; + + // On error, remove solid class from both thumbs to restore original state + const thumbsUp = this.el.querySelector("[data-vf-js-feedback-thumbs-up]"); + const thumbsDown = this.el.querySelector( + "[data-vf-js-feedback-thumbs-down]" + ); + thumbsUp?.classList.remove("vf-chatbot-feedback__thumb--solid"); + thumbsDown?.classList.remove("vf-chatbot-feedback__thumb--solid"); + + // Add close button event listener + const closeBtn = formContainer.querySelector(".vf-banner__close"); + if (closeBtn) { + closeBtn.addEventListener("click", () => { + formContainer.innerHTML = ""; + }); + } + } +} diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.njk b/components/vf-chatbot-feedback/vf-chatbot-feedback.njk new file mode 100644 index 0000000000..fce5b37081 --- /dev/null +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.njk @@ -0,0 +1,15 @@ +
+
+ + +
+
+
\ No newline at end of file diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.scss b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss new file mode 100644 index 0000000000..100bb77a77 --- /dev/null +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss @@ -0,0 +1,155 @@ +.vf-chatbot-feedback { + margin-top: 1rem; + font-family: inherit; + + &__actions { + display: flex; + gap: 0.5rem; + } + + &__thumb { + background: none; + border: none; + padding: 0.5rem; + cursor: pointer; + color: #666; + transition: color 0.2s, transform 0.2s; + display: inline-flex; + align-items: center; + + &:hover { + color: #000; + transform: scale(1.1); + } + + &--solid { + color: #000; + + svg { + fill: currentColor; + } + } + + svg { + width: 24px; + height: 24px; + display: block; + } + } + + &__form { + margin-top: 1rem; + + &-content { + background: #ffffff; + border: 1px solid #e5e5e5; + padding: 1rem; + } + } + + &__title { + font-size: 0.875rem; + font-weight: bold; + color: #1a1a1a; + margin: 0 0 1rem 0; + } + + &__options { + display: inline-flex; + gap: 0.5rem; + flex-direction: row; + margin-bottom: 1rem; + + @media (max-width: 480px) { + grid-template-columns: 1fr; + } + } + + &__option { + @extend .vf-chatbot-action-prompt; + width: 100%; + text-align: left; + padding: 0.75rem 1rem; + background-color: #ffffff; + color: #3B6FB6; + border-radius: 0px; + border: 1px solid #224B9A; + + &--selected { + background: #D1E3F6; + } + } + + &__comment { + width: 100%; + margin-bottom: 1rem; + font-family: inherit; + font-size: 0.875rem; + background: #ffffff; + + // &::placeholder { + // color: #666; + // } + + // &:focus { + // outline: none; + // border-color: #007c82; + // } + } + + &__submit { + padding: 0.75rem; + background: #FFFFFF; + color: #3B6FB6; + border: 2px solid #3B6FB6; + font-weight: 500; + cursor: pointer; + transition: background 0.2s; + + // &:hover { + // background: #005e62; + // } + } + + .vf-banner { + position: relative; + padding: 1rem; + border-radius: 4px; + margin-top: 1rem; + + &__content { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + } + + &__close { + background: none; + border: none; + padding: 0.25rem; + cursor: pointer; + color: currentColor; + opacity: 0.7; + transition: opacity 0.2s ease; + + &:hover { + opacity: 1; + } + + svg { + display: block; + } + } + + &--success { + background-color: #ffffff; + color: #1A1C1A; + } + + &--error { + background-color: #ffffff; + color: #1A1C1A; + } + } +} diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.scss b/components/vf-chatbot-modal/vf-chatbot-modal.scss index d55b4d1b6d..7c7904df4b 100644 --- a/components/vf-chatbot-modal/vf-chatbot-modal.scss +++ b/components/vf-chatbot-modal/vf-chatbot-modal.scss @@ -83,7 +83,7 @@ &__messages { flex: 1; - overflow-y: auto; + overflow-y: scroll; padding: 16px; background: #F5F5F5; } @@ -225,7 +225,6 @@ // Message styles .vf-chatbot-message { margin-bottom: 16px; - max-width: 85%; &--user { margin-left: auto; @@ -233,7 +232,7 @@ .vf-chatbot-message__content { background: #1A1A1A; color: #ffffff; - border-radius: 16px 16px 16px 16px; + border-radius: 4px 4px 4px 4px; } } @@ -252,7 +251,7 @@ .vf-chatbot-message__content { background: #ffffff; color: #1A1A1A; - border-radius: 16px 16px 16px 16px; + border-radius: 4px 4px 4px 4px; } } diff --git a/components/vf-chatbot-router/README.md b/components/vf-chatbot-router/README.md new file mode 100644 index 0000000000..2fb3d0a0f4 --- /dev/null +++ b/components/vf-chatbot-router/README.md @@ -0,0 +1,55 @@ +# Chatbot Router Component + +[![npm version](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-router.svg)](https://badge.fury.io/js/%40visual-framework%2Fvf-chatbot-router) + +## About + +A configurable router component for the Visual Framework chatbot that provides: +- Single/Multi-select functionality for different chatbot services +- Searchable dropdown list for 10+ items +- Visual feedback for selected items +- Clear all functionality for multi-select mode +- Configurable through YAML + +## Usage + +### JavaScript + +```js +import { initVFChatbotRouter } from '@visual-framework/vf-chatbot-router/vf-chatbot-router.js'; +// Or import directly +// import { initVFChatbotRouter } from '../components/raw/vf-chatbot-router/vf-chatbot-router.js'; + +// Initialize with config from vf-chatbot-router.config.yml +initVFChatbotRouter(); +``` + +### Configuration (vf-chatbot-router.config.yml) + +```yaml +chatbotRoutes: + multiselect: false # Set to true for multi-selection mode + maxMultiSelect: 3 # Maximum items that can be selected in multiselect mode + showSearch: true # Show search box if items > 10 + routes: + - id: general + title: General Assistant + description: General purpose AI assistant + selected: true + - id: code + title: Code Assistant + description: Specialized in code and development +``` + +### Features + +1. Configurable single/multi-select mode +2. Search functionality for large lists (10+ items) +3. Clear visual feedback for selected items +4. Responsive dropdown design +5. Clear all functionality for multi-select mode +6. Chevron indicator for dropdown state + +### Dependencies + +- @visual-framework/vf-sass-config diff --git a/components/vf-chatbot-router/package.json b/components/vf-chatbot-router/package.json new file mode 100644 index 0000000000..8366545b87 --- /dev/null +++ b/components/vf-chatbot-router/package.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-router", + "description": "Visual Framework Chatbot Router component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-router.css", + "sass": "index.scss", + "main": "vf-chatbot-router.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} diff --git a/components/vf-chatbot-router/vf-chatbot-router.config.yml b/components/vf-chatbot-router/vf-chatbot-router.config.yml new file mode 100644 index 0000000000..aed32b629c --- /dev/null +++ b/components/vf-chatbot-router/vf-chatbot-router.config.yml @@ -0,0 +1,43 @@ +title: Chatbot Router Component +label: Chatbot Router +preview: '@preview--components' +status: alpha +context: + component-type: element + # Component configuration + chatbotRoutes: + multiselect: false # Set to true for multi-selection mode + maxMultiSelect: 3 # Maximum items that can be selected in multiselect mode + showSearch: true # Show search box if items > 10 + routes: + - id: general + title: General Assistant + description: General purpose AI assistant for your queries + selected: true + - id: code + title: Code Assistant + description: Specialized in helping with code and development tasks + - id: science + title: Science Assistant + description: Expert in scientific and research-related queries + - id: data + title: Data Analysis Assistant + description: Specialized in data analysis and visualization + - id: writing + title: Writing Assistant + description: Helps with writing and content creation +variants: + - name: multiselect + context: + chatbotRoutes: + multiselect: true + routes: + - id: general + title: General Assistant + description: General purpose AI assistant for your queries + - id: code + title: Code Assistant + description: Specialized in helping with code and development tasks + - id: science + title: Science Assistant + description: Expert in scientific and research-related queries diff --git a/components/vf-chatbot-router/vf-chatbot-router.js b/components/vf-chatbot-router/vf-chatbot-router.js new file mode 100644 index 0000000000..b8a23bbdc7 --- /dev/null +++ b/components/vf-chatbot-router/vf-chatbot-router.js @@ -0,0 +1,220 @@ +export class VFChatbotRouter { + constructor(element) { + if (!element) { + console.error("Router element is required"); + return; + } + + this.el = element; + this.isMultiselect = this.el.hasAttribute("data-multiselect"); + this.maxMultiSelect = parseInt( + this.el.getAttribute("data-max-multiselect") || "3", + 10 + ); + this.selectedItems = new Set(); + + this.init(); + } + + init() { + // Ensure element exists before querying + if (!this.el) return; + + // Get DOM elements + this.titleEl = this.el.querySelector("[data-vf-js-router-toggle]"); + this.dropdownEl = this.el.querySelector("[data-vf-js-router-dropdown]"); + this.searchEl = this.el.querySelector("[data-vf-js-router-search]"); + this.clearEl = this.el.querySelector("[data-vf-js-router-clear]"); + this.selectedTextEl = this.el.querySelector(".vf-chatbot-router__selected"); + this.listItems = this.el.querySelectorAll("[data-vf-js-router-item]"); + + // Initialize dropdown as closed + if (this.dropdownEl) { + this.dropdownEl.style.display = 'none'; + } + + // Bind events + this.bindEvents(); + + // Initialize selected items + this.listItems.forEach(item => { + if (item.classList.contains("vf-chatbot-router__item--selected")) { + this.selectedItems.add(item.getAttribute("data-route-id")); + this.updateSelectionDisplay(); + } + }); + } + + bindEvents() { + // Toggle dropdown + if (this.titleEl) { + this.titleEl.addEventListener("click", (e) => { + e.stopPropagation(); + this.toggleDropdown(); + }); + } + + // Search functionality + if (this.searchEl) { + this.searchEl.addEventListener("input", (e) => { + e.stopPropagation(); + this.handleSearch(e.target.value); + }); + } + + // Clear all selections + if (this.clearEl) { + this.clearEl.addEventListener("click", (e) => { + e.preventDefault(); + e.stopPropagation(); + this.clearAllSelections(); + }); + } + + // List item selection + this.listItems.forEach(item => { + item.addEventListener("click", (e) => { + e.stopPropagation(); + this.handleItemSelection(item); + }); + }); + + // Close dropdown when clicking outside + document.addEventListener("click", (e) => { + if (!this.el.contains(e.target)) { + this.closeDropdown(); + } + }); + + // Prevent dropdown from closing when clicking inside + this.dropdownEl?.addEventListener("click", (e) => { + e.stopPropagation(); + }); + } + + toggleDropdown() { + const isExpanded = this.dropdownEl.style.display === 'block'; + if (isExpanded) { + this.closeDropdown(); + } else { + this.openDropdown(); + } + } + + openDropdown() { + this.dropdownEl.style.display = 'block'; + this.titleEl.classList.add("vf-chatbot-router__title--expanded"); + } + + closeDropdown() { + this.dropdownEl.style.display = 'none'; + this.titleEl.classList.remove("vf-chatbot-router__title--expanded"); + } + + handleSearch(query) { + const searchQuery = query.toLowerCase(); + this.listItems.forEach(item => { + const title = item + .querySelector(".vf-chatbot-router__item-title") + .textContent.toLowerCase(); + const description = item + .querySelector(".vf-chatbot-router__item-description") + .textContent.toLowerCase(); + const matches = + title.includes(searchQuery) || description.includes(searchQuery); + item.style.display = matches ? "flex" : "none"; + }); + } + + handleItemSelection(item) { + const itemId = item.getAttribute("data-route-id"); + + if (this.isMultiselect) { + if (this.selectedItems.has(itemId)) { + this.selectedItems.delete(itemId); + item.classList.remove("vf-chatbot-router__item--selected"); + } else if (this.selectedItems.size < this.maxMultiSelect) { + this.selectedItems.add(itemId); + item.classList.add("vf-chatbot-router__item--selected"); + } + } else { + // Single select mode + this.listItems.forEach(listItem => { + listItem.classList.remove("vf-chatbot-router__item--selected"); + }); + this.selectedItems.clear(); + this.selectedItems.add(itemId); + item.classList.add("vf-chatbot-router__item--selected"); + this.closeDropdown(); + } + + this.updateSelectionDisplay(); + this.updateClearButton(); + + // Dispatch custom event + this.el.dispatchEvent( + new CustomEvent("routeselection", { + detail: { + selectedItems: Array.from(this.selectedItems), + isMultiselect: this.isMultiselect + } + }) + ); + } + + clearAllSelections() { + this.selectedItems.clear(); + this.listItems.forEach(item => { + item.classList.remove("vf-chatbot-router__item--selected"); + }); + this.updateSelectionDisplay(); + this.updateClearButton(); + } + + updateSelectionDisplay() { + if (!this.selectedTextEl) return; + + if (this.selectedItems.size === 0) { + this.selectedTextEl.textContent = ""; + // Reset title to default in single select mode + if (!this.isMultiselect) { + const titleText = this.el.querySelector('.vf-chatbot-router__title-text'); + if (titleText) { + titleText.textContent = "AI Assistant"; + } + } + return; + } + + if (this.isMultiselect) { + this.selectedTextEl.textContent = `${this.selectedItems.size} selected`; + } else { + const selectedId = Array.from(this.selectedItems)[0]; + const selectedItem = this.el.querySelector(`[data-route-id="${selectedId}"]`); + if (selectedItem) { + const title = selectedItem.querySelector('.vf-chatbot-router__item-title').textContent; + // For single select, update both the selection text and the title + const titleText = this.el.querySelector('.vf-chatbot-router__title-text'); + if (titleText) { + titleText.textContent = title; + } + this.selectedTextEl.textContent = ""; + } + } + } + + updateClearButton() { + if (this.clearEl) { + if (this.selectedItems.size > 0) { + this.clearEl.classList.add("vf-chatbot-router__clear--active"); + } else { + this.clearEl.classList.remove("vf-chatbot-router__clear--active"); + } + } + } +} + +// Function to initialize the component +export function initVFChatbotRouter(element) { + return new VFChatbotRouter(element); +} diff --git a/components/vf-chatbot-router/vf-chatbot-router.njk b/components/vf-chatbot-router/vf-chatbot-router.njk new file mode 100644 index 0000000000..0dab6d57e3 --- /dev/null +++ b/components/vf-chatbot-router/vf-chatbot-router.njk @@ -0,0 +1,36 @@ +
+ +
+ +
+ {% if context.chatbotRoutes.multiselect %} +
+ Select up to {{ context.chatbotRoutes.maxMultiSelect }} services + Clear all +
+ {% endif %} + + {% if context.chatbotRoutes.showSearch and (context.chatbotRoutes.routes | length > 10) %} + + {% endif %} + +
    + {% for route in context.chatbotRoutes.routes %} +
  • +
    +
    {{ route.title }}
    +
    {{ route.description }}
    +
    + ✓ +
  • + {% endfor %} +
+
+
diff --git a/components/vf-chatbot-router/vf-chatbot-router.scss b/components/vf-chatbot-router/vf-chatbot-router.scss new file mode 100644 index 0000000000..eb549da77c --- /dev/null +++ b/components/vf-chatbot-router/vf-chatbot-router.scss @@ -0,0 +1,155 @@ +// vf-chatbot-router + +@import 'package.variables.scss'; + +.vf-chatbot-router { + position: relative; + display: inline-block; + font-family: var(--vf-font-family); +} + +.vf-chatbot-router__title { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background: none; + border: none; + cursor: pointer; + font-size: 16px; + color: var(--vf-text-color); + + &:hover { + background-color: var(--vf-color-gray-5); + } + + &--expanded { + .vf-chatbot-router__chevron { + transform: rotate(180deg); + } + } +} + +.vf-chatbot-router__title-text { + font-weight: 500; +} + +.vf-chatbot-router__selected { + color: var(--vf-color-gray-60); + margin-left: 4px; +} + +.vf-chatbot-router__chevron { + transition: transform 0.2s ease; +} + +.vf-chatbot-router__dropdown { + display: none; + position: absolute; + top: 100%; + left: 0; + min-width: 300px; + max-width: 400px; + background: var(--vf-color-white); + border: 1px solid var(--vf-color-gray-20); + border-radius: 4px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + margin-top: 4px; + z-index: 1000; + + &--expanded { + display: block; + } +} + +.vf-chatbot-router__header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 12px 16px; + border-bottom: 1px solid var(--vf-color-gray-20); + font-size: 14px; +} + +.vf-chatbot-router__clear { + color: var(--vf-color-gray-60); + text-decoration: none; + pointer-events: none; + opacity: 0.5; + + &--active { + color: var(--vf-link-color); + pointer-events: auto; + opacity: 1; + } +} + +.vf-chatbot-router__search { + padding: 12px 16px; + border-bottom: 1px solid var(--vf-color-gray-20); + + input { + width: 100%; + padding: 8px 12px; + border: 1px solid var(--vf-color-gray-20); + border-radius: 4px; + font-size: 14px; + + &:focus { + outline: none; + border-color: var(--vf-color-gray-40); + } + } +} + +.vf-chatbot-router__list { + max-height: 400px; + overflow-y: auto; + margin: 0; + padding: 8px 0; + list-style: none; +} + +.vf-chatbot-router__item { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 12px 16px; + cursor: pointer; + transition: background-color 0.2s ease; + + &:hover { + background-color: var(--vf-color-gray-5); + } + + &--selected { + background-color: var(--vf-color-gray-10); + + .vf-chatbot-router__tick { + opacity: 1; + } + } +} + +.vf-chatbot-router__item-content { + flex: 1; + padding-right: 16px; +} + +.vf-chatbot-router__item-title { + font-weight: 500; + margin-bottom: 4px; +} + +.vf-chatbot-router__item-description { + font-size: 14px; + color: var(--vf-color-gray-60); + line-height: 1.4; +} + +.vf-chatbot-router__tick { + opacity: 0; + color: var(--vf-color-green); + font-weight: bold; + transition: opacity 0.2s ease; +} diff --git a/components/vf-chatbot-sources/package.json b/components/vf-chatbot-sources/package.json new file mode 100644 index 0000000000..b1f26cd306 --- /dev/null +++ b/components/vf-chatbot-sources/package.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0", + "name": "@visual-framework/vf-chatbot-sources", + "description": "Visual Framework Chatbot Sources component", + "homepage": "https://stable.visual-framework.dev/", + "author": "VF", + "license": "Apache 2.0", + "style": "vf-chatbot-sources.css", + "sass": "index.scss", + "main": "vf-chatbot-sources.js", + "dependencies": { + "@visual-framework/vf-sass-config": "file:../vf-sass-config" + } +} diff --git a/components/vf-chatbot-sources/vf-chatbot-sources.js b/components/vf-chatbot-sources/vf-chatbot-sources.js new file mode 100644 index 0000000000..26f9e24067 --- /dev/null +++ b/components/vf-chatbot-sources/vf-chatbot-sources.js @@ -0,0 +1,62 @@ +// vf-chatbot-sources + +function VFChatbotSources(element) { + this.el = element; +} + +function initVFChatbotSources(messages) { + if (!messages) { + console.error("Message is required for VFChatbotSources"); + return null; + } + + const sourceHTML = messages + .map( + message => ` +
  • +
    ${message.domain}
    + + ${message.title} + +
    ${message.description}
    +
  • + ` + ) + .join(""); + + const el = document.createElement("div"); + el.className = "vf-chatbot-sources-toggle"; + el.innerHTML = ` + +
    +
    + +
    +
      ${sourceHTML}
    +
    + `; + + // Toggle logic + const toggleBtn = el.querySelector("[data-vf-js-chatbot-sources-toggle]"); + const sourcesDiv = el.querySelector("[data-vf-js-chatbot-sources]"); + const hideBtn = el.querySelector("[data-vf-js-chatbot-sources-hide]"); + + toggleBtn.addEventListener("click", () => { + sourcesDiv.classList.remove("vf-chatbot-sources--collapsed"); + toggleBtn.style.display = "none"; + }); + hideBtn.addEventListener("click", () => { + sourcesDiv.classList.add("vf-chatbot-sources--collapsed"); + toggleBtn.style.display = ""; + }); + + return new VFChatbotSources(el); +} + +export { VFChatbotSources, initVFChatbotSources }; diff --git a/components/vf-chatbot-sources/vf-chatbot-sources.njk b/components/vf-chatbot-sources/vf-chatbot-sources.njk new file mode 100644 index 0000000000..840a7c81ea --- /dev/null +++ b/components/vf-chatbot-sources/vf-chatbot-sources.njk @@ -0,0 +1,10 @@ +
    +

    Sources

    + +
    diff --git a/components/vf-chatbot-sources/vf-chatbot-sources.scss b/components/vf-chatbot-sources/vf-chatbot-sources.scss new file mode 100644 index 0000000000..d6b4a6c9fe --- /dev/null +++ b/components/vf-chatbot-sources/vf-chatbot-sources.scss @@ -0,0 +1,104 @@ +.vf-chatbot-sources-toggle { + width: 100%; + text-align: left; +} + +.vf-chatbot-sources__toggle-link { + @extend .vf-link; + background: #fff; + border-radius: 2rem; + padding: 0.5rem 1.25rem; + font-size: 1rem; + font-weight: 500; + cursor: pointer; + display: inline-flex; + align-items: center; + border: none; + box-shadow: 0 1px 4px rgba(0,0,0,0.04); + transition: background 0.2s; + align-items: flex-start; +} + +.vf-chatbot-sources__toggle-chevron { + font-size: 1.1em; + margin-left: 0.5em; + display: inline-block; + vertical-align: middle; +} + +.vf-chatbot-sources { + font-family: inherit; + background: #ffffff; + color: #666; + border-radius: 8px; + padding: 1rem 1rem; + border: 1px solid #E5E5E5; + transition: max-height 0.3s, opacity 0.3s; + opacity: 1; + max-height: 500px; + overflow: hidden; + + &--collapsed { + opacity: 0; + max-height: 0; + padding: 0 1rem; + pointer-events: none; + } + + &__header { + display: flex; + justify-content: flex-start; + margin-bottom: 0.5rem; + } + + &__hide-link { + @extend .vf-link; + background: none; + border: none; + font-size: 0.95rem; + font-weight: 500; + cursor: pointer; + display: inline-flex; + align-items: center; + box-shadow: none; + padding: 0; + margin: 0; + align-items: flex-start; + } + + &__hide-chevron { + font-size: 1.1em; + margin-left: 0.5em; + display: inline-block; + vertical-align: middle; + } + + &__list { + overflow-y: auto; + height: 25vh; + list-style: none; + padding: 0; + margin: 0; + } + + &__item { + line-height: 1.5; + padding: 1rem 0; + border-bottom: 1px solid #E5E5E5; + + &:last-child { + padding-bottom: 0; + border-bottom: none; + } + } + + &__description { + font-size: 0.875em; + margin-top: 0.5rem; + } + + &__title { + font-size: 1em; + word-break: break-word; + } +} diff --git a/components/vf-chatbot-standalone/package.json b/components/vf-chatbot-standalone/package.json index b7c35f7d4e..7594b6c3fd 100644 --- a/components/vf-chatbot-standalone/package.json +++ b/components/vf-chatbot-standalone/package.json @@ -10,6 +10,7 @@ "main": "vf-chatbot-standalone.js", "dependencies": { "@visual-framework/vf-sass-config": "file:../vf-sass-config", - "@visual-framework/vf-chatbot-welcome": "file:../vf-chatbot-welcome" + "@visual-framework/vf-chatbot-welcome": "file:../vf-chatbot-welcome", + "@visual-framework/vf-banner": "^2.0.5" } } diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml b/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml index 12e73a086c..b0cfa50ef1 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.config.yml @@ -7,3 +7,4 @@ context: welcome_message: Hello! How can I help you today? input_placeholder: Type your message... show_suggestions: true + disclaimer: 'Disclaimer: This chatbot is designed to assist you with general information and basic inquiries. See our disclaimer notes.' diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.js b/components/vf-chatbot-standalone/vf-chatbot-standalone.js index df6ac22b2f..2dd8de3c35 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.js +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.js @@ -1,16 +1,20 @@ // vf-chatbot-standalone.js +import { initVFChatbotSources } from "../vf-chatbot-sources/vf-chatbot-sources"; +import { VFChatbotFeedback } from "../vf-chatbot-feedback/vf-chatbot-feedback.js"; +import { initVFChatbotRouter } from "../vf-chatbot-router/vf-chatbot-router.js"; + class VFChatbotStandalone { constructor(element) { console.log("Initializing standalone chatbot..."); // Debug log // Store DOM elements this.container = element; - this.welcomeScreen = this.container.querySelector( - "[data-vf-js-chatbot-standalone-welcome]" - ); this.chatInterface = this.container.querySelector( "[data-vf-js-chatbot-standalone-chat]" ); + this.welcomeScreen = this.container.querySelector( + "[data-vf-js-chatbot-standalone-welcome]" + ); this.messagesContainer = this.container.querySelector( "[data-vf-js-chatbot-standalone-messages]" ); @@ -32,19 +36,53 @@ class VFChatbotStandalone { this.suggestionBtns = this.container.querySelectorAll( "[data-vf-js-chatbot-standalone-suggestion]" ); + this.disclaimer = this.container.querySelector( + "[data-vf-js-chatbot-standalone-disclaimer]" + ); + this.disclaimerCloseBtn = this.disclaimer.querySelector( + ".vf-button--dismiss" + ); + + // Router element + this.routerEl = this.container.querySelector("[data-vf-js-chatbot-router]"); + // API configuration - Mistral AI this.API_TOKEN = ""; this.API_URL = "https://api.mistral.ai/v1/chat/completions"; // State this.hasInteracted = false; + this.currentAssistant = "general"; // Default assistant + + // Initialize the UI + this.init(); + } + init() { + // Initialize router if present + if (this.routerEl) { + const router = initVFChatbotRouter(this.routerEl); + this.routerEl.addEventListener('routeselection', (e) => { + this.handleRouteSelection(e.detail); + }); + } + + // Bind other events this.bindEvents(); this.initAutoResize(); console.log("Standalone chatbot initialized successfully"); // Debug log } + handleRouteSelection(detail) { + const { selectedItems } = detail; + if (selectedItems && selectedItems.length > 0) { + this.currentAssistant = selectedItems[0]; + // You can add logic here to change the assistant's behavior based on selection + console.log(`Switched to ${this.currentAssistant} assistant`); + } + } + bindEvents() { console.log("Binding events for standalone chatbot..."); // Debug log @@ -96,7 +134,7 @@ class VFChatbotStandalone { // Listen for action prompt clicks this.container.addEventListener("vf-chatbot-action-prompt:click", event => { - const { text, data } = event.detail; + const { text } = event.detail; // Show chat interface this.showChatInterface(); @@ -115,6 +153,12 @@ class VFChatbotStandalone { this.sendUserMessage(text); } }); + // Listen for dismiss button click + if (this.disclaimer && this.disclaimerCloseBtn) { + this.disclaimerCloseBtn.addEventListener("click", () => { + this.disclaimer.classList.add("vf-u-display-none"); + }); + } } initAutoResize() { @@ -146,8 +190,8 @@ class VFChatbotStandalone { if (this.welcomeScreen) { this.welcomeScreen.style.display = "none"; } - if (this.chatInterface) { - this.chatInterface.style.display = "block"; + if (this.messagesContainer) { + this.messagesContainer.style.display = "flex"; } // Focus on the input field @@ -165,9 +209,13 @@ class VFChatbotStandalone { const userMessageEl = document.createElement("div"); userMessageEl.className = "vf-chatbot-message vf-chatbot-message--user"; userMessageEl.innerHTML = ` +
    + You + You +
    ${text}
    `; - this.messagesContainer.appendChild(userMessageEl); + this.messagesContainer.insertBefore(userMessageEl, this.loadingIndicator); // Clear input if this came from the input field if (this.input && this.input.value === text) { @@ -188,7 +236,55 @@ class VFChatbotStandalone { // Call the API this.callAPI(text) .then(response => { - this.addAssistantResponse(response.html || response); + // Extract sources if available, otherwise use the original response text + const sources = response.sources || [ + { + domain: "re3data.org", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "MetaboLights is a public repository for metabolomics data, including raw and processed data, metadata, and analysis results." + }, + { + domain: "academic.oup.com", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "16 November 2024 - MetaboLights is a global, open-access database for metabolomics studies, providing raw experimental data and metadata. It supports multiple species and techniques, offering structured metabolite ..." + }, + { + domain: "re3data.org", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "MetaboLights is a public repository for metabolomics data, including raw and processed data, metadata, and analysis results." + }, + { + domain: "academic.oup.com", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "16 November 2024 - MetaboLights is a global, open-access database for metabolomics studies, providing raw experimental data and metadata. It supports multiple species and techniques, offering structured metabolite ..." + }, + { + domain: "re3data.org", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "MetaboLights is a public repository for metabolomics data, including raw and processed data, metadata, and analysis results." + }, + { + domain: "academic.oup.com", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "16 November 2024 - MetaboLights is a global, open-access database for metabolomics studies, providing raw experimental data and metadata. It supports multiple species and techniques, offering structured metabolite ..." + } + ]; + const responseText = response.html || response; + // Add assistant response to UI + this.addAssistantResponse(responseText, sources); + // Hide loading state this.setLoadingState(false); }) .catch(error => { @@ -205,7 +301,7 @@ class VFChatbotStandalone { method: "POST", headers: { "Content-Type": "application/json", - "Authorization": `Bearer ${this.API_TOKEN}` + Authorization: `Bearer ${this.API_TOKEN}` }, body: JSON.stringify({ model: "mistral-tiny", // or another available model @@ -223,7 +319,13 @@ class VFChatbotStandalone { }) .then(data => { // Mistral returns: { choices: [{ message: { content: "..." } }] } - if (data && data.choices && data.choices[0] && data.choices[0].message && data.choices[0].message.content) { + if ( + data && + data.choices && + data.choices[0] && + data.choices[0].message && + data.choices[0].message.content + ) { resolve(data.choices[0].message.content); } else { reject(new Error("Invalid API response")); @@ -236,7 +338,8 @@ class VFChatbotStandalone { }); } - addAssistantResponse(text) { + addAssistantResponse(text, sources = []) { + // Remove loading indicator if (!text || !this.messagesContainer) return; // Add assistant message to UI @@ -246,10 +349,73 @@ class VFChatbotStandalone { assistantMessageEl.innerHTML = `
    AI Assistant + AI Assistant
    ${text}
    `; - this.messagesContainer.appendChild(assistantMessageEl); + if (sources && sources.length > 0) { + // Add sources + const sourcesEl = initVFChatbotSources(sources); + + // Enhance: scroll to bottom when sources are expanded + const toggleBtn = sourcesEl.el.querySelector( + "[data-vf-js-chatbot-sources-toggle]" + ); + const sourcesDiv = sourcesEl.el.querySelector( + "[data-vf-js-chatbot-sources]" + ); + + if (toggleBtn && sourcesDiv) { + toggleBtn.addEventListener("click", () => { + // Wait for the sources div to expand, then scroll + setTimeout(() => { + if (this.messagesContainer) { + this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + } + }, 100); + }); + } + + assistantMessageEl.appendChild(sourcesEl.el); + } + // Create feedback element with template + const feedbackTemplate = ` +
    +
    + + +
    +
    +
    + `; + + const feedbackEl = document.createElement("div"); + feedbackEl.innerHTML = feedbackTemplate; + + // Append feedback element to message + assistantMessageEl.appendChild(feedbackEl.firstElementChild); + + // Initialize feedback after element is in DOM + const feedbackComponent = assistantMessageEl.querySelector( + "[data-vf-js-chatbot-feedback]" + ); + if (feedbackComponent) { + new VFChatbotFeedback(feedbackComponent, `response-${Date.now()}`); + } + + // Insert before loading indicator + this.messagesContainer.insertBefore( + assistantMessageEl, + this.loadingIndicator + ); this.scrollToBottom(); } @@ -276,7 +442,7 @@ class VFChatbotStandalone { } } - getSimulatedResponse(text) { + getSimulatedResponse() { // Fallback responses when API fails const fallbackResponses = [ "I'm sorry, I'm having trouble connecting to my knowledge base right now. Could you try again in a moment?", diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk index 2493219f95..60042cc616 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk @@ -6,17 +6,90 @@

    AI Assistant - {{ title | default("AI assistant") }} + {% set isMultiselect = true %} + {% set routerContext = { + context: { + chatbotRoutes: { + multiselect: isMultiselect, + showSearch: true, + routes: [ + { + id: "general", + title: "General Assistant", + description: "General purpose AI assistant", + selected: true + }, + { + id: "code", + title: "Code Assistant", + description: "Specialized in code and development" + }, + { + id: "science", + title: "Science Assistant", + description: "Expert in scientific queries" + }, + { + id: "general", + title: "General Assistant", + description: "General purpose AI assistant", + selected: true + }, + { + id: "code", + title: "Code Assistant", + description: "Specialized in code and development" + }, + { + id: "science", + title: "Science Assistant", + description: "Expert in scientific queries" + }, + { + id: "general", + title: "General Assistant", + description: "General purpose AI assistant", + selected: true + }, + { + id: "code", + title: "Code Assistant", + description: "Specialized in code and development" + }, + { + id: "science", + title: "Science Assistant", + description: "Expert in scientific queries" + }, + { + id: "general", + title: "General Assistant", + description: "General purpose AI assistant", + selected: true + }, + { + id: "code", + title: "Code Assistant", + description: "Specialized in code and development" + }, + { + id: "science", + title: "Science Assistant", + description: "Expert in scientific queries" + } + ] + } + } + } %} + {% render '@vf-chatbot-router', routerContext %}

    -
    +
    - -
    {% if welcome_message %} @@ -64,15 +137,21 @@
    #} {% endif %} + +
    -
    - -
    #} -
    -
    - -
    + {% if disclaimer %} +
    +
    +
    +

    {{ disclaimer }}

    +
    + {% endif %} + {#
    #} +
    + + +
    + {#
    #}
    diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss index 30fb763091..e0b76e4b19 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss @@ -1,16 +1,17 @@ // vf-chatbot-standalone.scss +@import '../vf-banner/vf-banner.scss'; +@import '../vf-chatbot-sources/vf-chatbot-sources.scss'; +@import '../vf-chatbot-router/vf-chatbot-router.scss'; .vf-chatbot-standalone { display: flex; flex-direction: column; - width: 100%; - height: 100vh; + margin: auto 15px; &__container { display: flex; flex-direction: column; height: 100%; - margin: 10px; background: #ffffff; @media (max-width: 1200px) { @@ -70,26 +71,27 @@ } &__content { - display: flex !important; - flex-direction: column; - flex: 1; - overflow: hidden; - background: #F5F5F5; - justify-content: center; - border-radius: 16px 16px 16px 16px; + // display: flex !important; + // flex-direction: column; + // flex: 1; + // overflow: hidden; + // background: #F5F5F5; + // justify-content: center; + border-radius: 4px 4px 4px 4px; } // Welcome screen styles &__welcome { - flex: 1; - display: flex; - flex-direction: column; + width: 100%; justify-content: center; - align-items: center; - padding: 24px; + // flex: 1; + display: flex; + // flex-direction: column; + // justify-content: center; + // align-items: center; + padding-top: 24px; &-content { - max-width: 65%; width: 100%; text-align: center; display: flex; @@ -117,7 +119,7 @@ font-size: 16px; line-height: 1.5; color: #666666; - margin: 0 0 32px 0; + height: 25vh; max-width: 450px; } @@ -135,8 +137,20 @@ &-grid { display: grid; grid-template-columns: 1fr 1fr; - gap: 16px; + justify-items: center; // Center items horizontally + gap: 8px; + + // Make the last item span full width if it's the 3rd item + & > *:nth-child(3):last-child { + grid-column: 1 / -1; + justify-self: center; // Center the full-width item + } + // Ensure each grid cell only takes the width it needs + & > * { + width: auto; + min-width: min-content; + } @media (max-width: 480px) { grid-template-columns: 1fr; } @@ -217,14 +231,20 @@ } } - &__messages { - flex: 1; - overflow-y: auto; - padding: 24px; - background: #F5F5F5; - - @media (max-width: 768px) { - padding: 16px; + &__loading { + min-height: 50vh; + flex-direction: column; + justify-items: flex-start; + &-dots { + width: 30px; + background: #ffffff; + border-radius: 4px 4px 4px 4px; + display: flex; + align-items: center; + justify-content: center; + height: 40px; + font-size: 24px; + color: #666666; } } @@ -239,14 +259,18 @@ } &__input-wrapper { + display: flex; + align-items: center; + height: 10vh; position: relative; - width: 70%; + width: 50%; margin: 0 auto; } &__input { + align-content: center; width: 100%; - padding: 0px; + padding-left: 16px; border: none; font-size: 16px; line-height: 1.5; @@ -265,7 +289,7 @@ right: 0px; top: 50%; transform: translateY(-50%); - background: #007AFF; + background: #3A77BC; color: #ffffff; border: none; width: 40px; @@ -277,7 +301,7 @@ transition: background 0.2s ease; &:hover { - background: darken(#007AFF, 10%); + background: darken(#3A77BC, 10%); } svg { @@ -286,58 +310,74 @@ } } - &__welcome-suggestions { - margin: 24px 0; + &__chat { + width: 50%; + margin: 0 auto; + display: flex; + flex-direction: column; + align-items: center; + height: 75vh; // or use: calc(100vh - [header+footer heights]) for more precise fit + min-height: 400px; - &-title { - font-weight: 500; - margin-bottom: 12px; + @media (max-width: 900px) { + width: 95%; } + @media (max-width: 600px) { + width: 100%; + min-height: 300px; + } + } - &-grid { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 12px; - justify-items: center; // Center items horizontally - - // Make the last item span full width if it's the 3rd item - & > *:nth-child(3):last-child { - grid-column: 1 / -1; - justify-self: center; // Center the full-width item - } + &__messages { + display: flex; + flex-direction: column; + flex: 1 1 auto; + overflow-y: auto; + width: 100%; + padding-top: 16px; + min-height: 0; // Required for flexbox scroll + max-height: 100%; // Ensures it doesn't overflow the parent - // Ensure each grid cell only takes the width it needs - & > * { - width: auto; - min-width: min-content; - } + @media (max-width: 768px) { + padding: 16px; } } - &__chat { + // &__messages { + // flex: 1 1 auto; + // overflow-y: auto; + // width: 100%; + // padding-top: 16px; + // min-height: 0; // Required for flexbox scroll + // max-height: 100%; // Ensures it doesn't overflow the parent + + // @media (max-width: 768px) { + // padding: 16px; + // } + // // padding: 1rem; + // // min-height: 0; /* Required for flex children to scroll */ + // } + + &__disclaimer { + width: 98%; display: flex; + justify-content: flex-end; flex-direction: column; - height: 80vh; /* Or use: calc(100vh - [header+footer heights]) for more precise fit */ - max-height: 80vh; - min-height: 400px; - // background: #fff; - // border-radius: 1rem; - // box-shadow: 0 2px 8px rgba(0,0,0,0.04); - // overflow: hidden; - } + align-items: center; + position: absolute; + bottom: 0px; + z-index: 1000; + height: 97vh; + padding-bottom: 3%; - &__messages { - flex: 1 1 auto; - overflow-y: auto; - padding: 1rem; - min-height: 0; /* Required for flex children to scroll */ + .vf-banner { + width: 50%; + } } } // Reuse message styles from the modal component .vf-chatbot-message { - margin-bottom: 24px; - max-width: 85%; @media (max-width: 768px) { max-width: 90%; @@ -349,26 +389,26 @@ .vf-chatbot-message__content { background: #1A1A1A; color: #ffffff; - border-radius: 16px 16px 16px 16px; + border-radius: 4px 4px 4px 4px; } } &--assistant { margin-right: auto; - display: flex; + display: grid; align-items: flex-start; gap: 12px; .vf-chatbot-message__avatar { - width: 32px; - height: 32px; + width: 24px; + height: 24px; border-radius: 50%; } .vf-chatbot-message__content { background: #ffffff; color: #1A1A1A; - border-radius: 16px 16px 16px 16px; + border-radius: 4px 4px 4px 4px; } } @@ -393,12 +433,79 @@ object-fit: contain; } -.vf-chatbot-message--assistant img.vf-chatbot-message__avatar { - width: 32px; - height: 32px; - border-radius: 50%; - background-color: #fff; - object-fit: contain; - padding: 0; - border: 1px solid #eee; +.vf-chatbot-message--user { + max-width: 85%; + + .vf-chatbot-message__avatar { + width: 100%; + display: flex; + align-items: center; + gap: 8px; + + .vf-chatbot-message__avatar-name { + font-size: 14px; + font-weight: 500; + color: #1A1A1A; + } + + .vf-chatbot-message__avatar img { + width: 24px; + height: 24px; + border-radius: 50%; + } + } } + +.vf-chatbot-message--assistant { + margin-right: auto; + display: grid; + align-items: flex-start; + gap: 12px; + + .vf-chatbot-message__avatar { + width: 100%; + display: flex; + align-items: center; + gap: 8px; + + img { + width: 24px; + height: 24px; + border-radius: 50%; + } + + .vf-chatbot-message__avatar-name { + font-size: 14px; + font-weight: 500; + color: #1A1A1A; + } + } + } + + + +.vf-chatbot-message--user { + display: grid; + align-items: flex-start; + gap: 12px; + + .vf-chatbot-message__avatar { + flex-direction: row; + justify-content: flex-end; + display: flex; + align-items: center; + gap: 8px; + + img { + width: 24px; + height: 24px; + border-radius: 50%; + } + + .vf-chatbot-message__avatar-name { + font-size: 14px; + font-weight: 500; + color: #1A1A1A; + } + } + } diff --git a/components/vf-chatbot/assets/vf-icon--avatar.svg b/components/vf-chatbot/assets/vf-icon--avatar.svg new file mode 100644 index 0000000000..175518a40f --- /dev/null +++ b/components/vf-chatbot/assets/vf-icon--avatar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/vf-chatbot/vf-chatbot.scss b/components/vf-chatbot/vf-chatbot.scss index b68e524007..6fd298ac81 100644 --- a/components/vf-chatbot/vf-chatbot.scss +++ b/components/vf-chatbot/vf-chatbot.scss @@ -45,6 +45,7 @@ @import '../vf-chatbot-fab/vf-chatbot-fab.scss'; @import '../vf-chatbot-modal/vf-chatbot-modal.scss'; @import '../vf-chatbot-prompt/vf-chatbot-prompt.scss'; +@import '../vf-chatbot-feedback/vf-chatbot-feedback.scss'; // @import '@visual-framework/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss'; // @import '@visual-framework/vf-chatbot-header/vf-chatbot-header.scss'; // @import '@visual-framework/vf-chatbot-header-dropdown/vf-chatbot-header-dropdown.scss'; diff --git a/components/vf-componenet-rollup/index.scss b/components/vf-componenet-rollup/index.scss index 1236db66fb..559359eea5 100755 --- a/components/vf-componenet-rollup/index.scss +++ b/components/vf-componenet-rollup/index.scss @@ -151,13 +151,8 @@ button { @import 'vf-chatbot-prompt/vf-chatbot-prompt.scss'; @import 'vf-chatbot-standalone/vf-chatbot-standalone.scss'; @import 'vf-chatbot-welcome/vf-chatbot-welcome.scss'; -// @import 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss'; -// @import 'vf-chatbot-header/vf-chatbot-header.scss'; -// @import 'vf-chatbot-header-dropdown/vf-chatbot-header-dropdown.scss'; -// @import 'vf-chatbot-dialog/vf-chatbot-dialog.scss'; -// @import 'vf-chatbot-card/vf-chatbot-card.scss'; -// @import 'vf-chatbot-attribution/vf-chatbot-attribution.scss'; -// @import 'vf-chatbot-feedback/vf-chatbot-feedback.scss'; +@import 'vf-chatbot-feedback/vf-chatbot-feedback.scss'; +@import 'vf-chatbot-router/vf-chatbot-router.scss'; /* All Visual Framework Boilerplates */ diff --git a/components/vf-componenet-rollup/scripts.js b/components/vf-componenet-rollup/scripts.js index 3991ed8ab0..f188cd2bd4 100644 --- a/components/vf-componenet-rollup/scripts.js +++ b/components/vf-componenet-rollup/scripts.js @@ -80,7 +80,8 @@ import { initVFChatbotActionPrompt } from 'vf-chatbot-action-prompt/vf-chatbot-a import { initVFChatbotFab } from 'vf-chatbot-fab/vf-chatbot-fab.js'; import { initVFChatbotWelcome } from 'vf-chatbot-welcome/vf-chatbot-welcome.js'; import { initVFChatbotPrompt } from 'vf-chatbot-prompt/vf-chatbot-prompt.js'; - +import { VFChatbotFeedback } from 'vf-chatbot-feedback/vf-chatbot-feedback.js'; +import { initVFChatbotRouter } from 'vf-chatbot-router/vf-chatbot-router.js'; // Initialize all chatbot components when DOM is loaded document.addEventListener("DOMContentLoaded", () => { const chatbotFab = document.querySelector(".vf-chatbot-fab"); @@ -93,6 +94,10 @@ document.addEventListener("DOMContentLoaded", () => { initVFChatbotFab(); initVFChatbotWelcome(); initVFChatbotPrompt(); + const routerEl = document.querySelector('[data-vf-js-chatbot-router]'); + if (routerEl) { + initVFChatbotRouter(routerEl); + } }); } else { console.error("vf-chatbot-fab button not found in the DOM."); From 56f889e2fd44d144b0bb1632aafb6de8e8a06f68 Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Mon, 2 Jun 2025 15:04:20 +0100 Subject: [PATCH 06/71] VF chatbot- Standalone chatbot fixes --- .../vf-chatbot-router/vf-chatbot-router.js | 72 +++-- .../vf-chatbot-router/vf-chatbot-router.njk | 26 +- .../vf-chatbot-router/vf-chatbot-router.scss | 78 +++-- .../vf-chatbot-standalone.js | 42 +-- .../vf-chatbot-standalone.njk | 305 +++++++++++++----- .../vf-chatbot-standalone.scss | 7 - 6 files changed, 326 insertions(+), 204 deletions(-) diff --git a/components/vf-chatbot-router/vf-chatbot-router.js b/components/vf-chatbot-router/vf-chatbot-router.js index b8a23bbdc7..42a594964f 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.js +++ b/components/vf-chatbot-router/vf-chatbot-router.js @@ -25,30 +25,35 @@ export class VFChatbotRouter { this.dropdownEl = this.el.querySelector("[data-vf-js-router-dropdown]"); this.searchEl = this.el.querySelector("[data-vf-js-router-search]"); this.clearEl = this.el.querySelector("[data-vf-js-router-clear]"); - this.selectedTextEl = this.el.querySelector(".vf-chatbot-router__selected"); this.listItems = this.el.querySelectorAll("[data-vf-js-router-item]"); // Initialize dropdown as closed if (this.dropdownEl) { - this.dropdownEl.style.display = 'none'; + this.dropdownEl.style.display = "none"; } // Bind events this.bindEvents(); - // Initialize selected items + // Initialize selected items and update display + let initSelection = false; this.listItems.forEach(item => { if (item.classList.contains("vf-chatbot-router__item--selected")) { this.selectedItems.add(item.getAttribute("data-route-id")); - this.updateSelectionDisplay(); + initSelection = true; } }); + + // Update display after initial selection + if (initSelection) { + this.updateSelectionDisplay(); + } } bindEvents() { // Toggle dropdown if (this.titleEl) { - this.titleEl.addEventListener("click", (e) => { + this.titleEl.addEventListener("click", e => { e.stopPropagation(); this.toggleDropdown(); }); @@ -56,7 +61,7 @@ export class VFChatbotRouter { // Search functionality if (this.searchEl) { - this.searchEl.addEventListener("input", (e) => { + this.searchEl.addEventListener("input", e => { e.stopPropagation(); this.handleSearch(e.target.value); }); @@ -64,7 +69,7 @@ export class VFChatbotRouter { // Clear all selections if (this.clearEl) { - this.clearEl.addEventListener("click", (e) => { + this.clearEl.addEventListener("click", e => { e.preventDefault(); e.stopPropagation(); this.clearAllSelections(); @@ -73,27 +78,27 @@ export class VFChatbotRouter { // List item selection this.listItems.forEach(item => { - item.addEventListener("click", (e) => { + item.addEventListener("click", e => { e.stopPropagation(); this.handleItemSelection(item); }); }); // Close dropdown when clicking outside - document.addEventListener("click", (e) => { + document.addEventListener("click", e => { if (!this.el.contains(e.target)) { this.closeDropdown(); } }); // Prevent dropdown from closing when clicking inside - this.dropdownEl?.addEventListener("click", (e) => { + this.dropdownEl?.addEventListener("click", e => { e.stopPropagation(); }); } toggleDropdown() { - const isExpanded = this.dropdownEl.style.display === 'block'; + const isExpanded = this.dropdownEl.style.display === "block"; if (isExpanded) { this.closeDropdown(); } else { @@ -102,12 +107,12 @@ export class VFChatbotRouter { } openDropdown() { - this.dropdownEl.style.display = 'block'; + this.dropdownEl.style.display = "block"; this.titleEl.classList.add("vf-chatbot-router__title--expanded"); } closeDropdown() { - this.dropdownEl.style.display = 'none'; + this.dropdownEl.style.display = "none"; this.titleEl.classList.remove("vf-chatbot-router__title--expanded"); } @@ -145,6 +150,14 @@ export class VFChatbotRouter { this.selectedItems.clear(); this.selectedItems.add(itemId); item.classList.add("vf-chatbot-router__item--selected"); + + // Update title text immediately + const title = item.querySelector(".vf-chatbot-router__item-title").textContent; + const titleText = this.el.querySelector(".vf-chatbot-router__title-text"); + if (titleText) { + titleText.textContent = title; + } + this.closeDropdown(); } @@ -172,34 +185,27 @@ export class VFChatbotRouter { } updateSelectionDisplay() { - if (!this.selectedTextEl) return; + const titleText = this.el.querySelector(".vf-chatbot-router__title-text"); + if (!titleText) return; if (this.selectedItems.size === 0) { - this.selectedTextEl.textContent = ""; - // Reset title to default in single select mode - if (!this.isMultiselect) { - const titleText = this.el.querySelector('.vf-chatbot-router__title-text'); - if (titleText) { - titleText.textContent = "AI Assistant"; - } - } + titleText.textContent = "Select services"; return; } - if (this.isMultiselect) { - this.selectedTextEl.textContent = `${this.selectedItems.size} selected`; - } else { + if (!this.isMultiselect) { const selectedId = Array.from(this.selectedItems)[0]; - const selectedItem = this.el.querySelector(`[data-route-id="${selectedId}"]`); + const selectedItem = this.el.querySelector( + `[data-route-id="${selectedId}"]` + ); if (selectedItem) { - const title = selectedItem.querySelector('.vf-chatbot-router__item-title').textContent; - // For single select, update both the selection text and the title - const titleText = this.el.querySelector('.vf-chatbot-router__title-text'); - if (titleText) { - titleText.textContent = title; - } - this.selectedTextEl.textContent = ""; + const title = selectedItem.querySelector( + ".vf-chatbot-router__item-title" + ).textContent; + titleText.textContent = title; } + } else { + titleText.textContent = `${this.selectedItems.size} selected`; } } diff --git a/components/vf-chatbot-router/vf-chatbot-router.njk b/components/vf-chatbot-router/vf-chatbot-router.njk index 0dab6d57e3..3549395b09 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.njk +++ b/components/vf-chatbot-router/vf-chatbot-router.njk @@ -1,21 +1,25 @@ -
    +
    -
    - {% if context.chatbotRoutes.multiselect %} -
    - Select up to {{ context.chatbotRoutes.maxMultiSelect }} services - Clear all + + {% if context.chatbotRoutes.showSearch and (context.chatbotRoutes.routes | length > context.chatbotRoutes.showSearchThreshold) %} + {% endif %} - {% if context.chatbotRoutes.showSearch and (context.chatbotRoutes.routes | length > 10) %} - - ✓ + {% endfor %} diff --git a/components/vf-chatbot-router/vf-chatbot-router.scss b/components/vf-chatbot-router/vf-chatbot-router.scss index eb549da77c..f857dc8134 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.scss +++ b/components/vf-chatbot-router/vf-chatbot-router.scss @@ -4,23 +4,24 @@ .vf-chatbot-router { position: relative; - display: inline-block; + display: block; font-family: var(--vf-font-family); + width: 100%; } .vf-chatbot-router__title { display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; + justify-content: space-between; + width: 100%; + padding: 0px; background: none; border: none; cursor: pointer; - font-size: 16px; color: var(--vf-text-color); + text-align: left; &:hover { - background-color: var(--vf-color-gray-5); + // background-color: var(--vf-color--grey--lightest); } &--expanded { @@ -30,17 +31,39 @@ } } -.vf-chatbot-router__title-text { + +.vf-chatbot-router__title img { + position: relative; + top: 10px; + width: 24px; + height: 24px; + margin-right: 8px; + vertical-align: middle; +} + +.vf-chatbot-router__title-content { + display: flex; + flex-direction: column; + gap: 2px; +} + +.vf-chatbot-router__main-text { font-weight: 500; + font-size: 20px; + line-height: 1.2; } -.vf-chatbot-router__selected { - color: var(--vf-color-gray-60); - margin-left: 4px; +.vf-chatbot-router__title-text { + font-size: 14px; + color: var(--vf-color--grey-dark); + font-weight: 400; + display: block; } .vf-chatbot-router__chevron { transition: transform 0.2s ease; + margin-left: 8px; + font-size: 16px; } .vf-chatbot-router__dropdown { @@ -50,12 +73,9 @@ left: 0; min-width: 300px; max-width: 400px; - background: var(--vf-color-white); - border: 1px solid var(--vf-color-gray-20); - border-radius: 4px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + background: var(--vf-color--neutral--0); + box-shadow: 0 4px 6px var(--vf-color--grey--light); margin-top: 4px; - z-index: 1000; &--expanded { display: block; @@ -67,38 +87,30 @@ justify-content: space-between; align-items: center; padding: 12px 16px; - border-bottom: 1px solid var(--vf-color-gray-20); + border-bottom: 1px solid var(--vf-color--grey--light); font-size: 14px; } .vf-chatbot-router__clear { - color: var(--vf-color-gray-60); + color: var(--vf-color--grey--dark); text-decoration: none; pointer-events: none; opacity: 0.5; &--active { - color: var(--vf-link-color); + color: $vf-link--color; pointer-events: auto; opacity: 1; } } .vf-chatbot-router__search { - padding: 12px 16px; - border-bottom: 1px solid var(--vf-color-gray-20); input { - width: 100%; - padding: 8px 12px; - border: 1px solid var(--vf-color-gray-20); - border-radius: 4px; + width: 94%; + padding: 8px 0px 8px 16px; + border: 1px solid #333; font-size: 14px; - - &:focus { - outline: none; - border-color: var(--vf-color-gray-40); - } } } @@ -119,11 +131,11 @@ transition: background-color 0.2s ease; &:hover { - background-color: var(--vf-color-gray-5); + // background-color: var(--vf-color--grey--lightest); } &--selected { - background-color: var(--vf-color-gray-10); + // background-color: var(--vf-color--grey--light); .vf-chatbot-router__tick { opacity: 1; @@ -143,13 +155,13 @@ .vf-chatbot-router__item-description { font-size: 14px; - color: var(--vf-color-gray-60); + color: var(--vf-color--grey--dark); line-height: 1.4; } .vf-chatbot-router__tick { opacity: 0; - color: var(--vf-color-green); + color: var(--vf-color--grey--dark); font-weight: bold; transition: opacity 0.2s ease; } diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.js b/components/vf-chatbot-standalone/vf-chatbot-standalone.js index 2dd8de3c35..e751c0b9c5 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.js +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.js @@ -1,7 +1,6 @@ // vf-chatbot-standalone.js import { initVFChatbotSources } from "../vf-chatbot-sources/vf-chatbot-sources"; import { VFChatbotFeedback } from "../vf-chatbot-feedback/vf-chatbot-feedback.js"; -import { initVFChatbotRouter } from "../vf-chatbot-router/vf-chatbot-router.js"; class VFChatbotStandalone { constructor(element) { @@ -43,46 +42,19 @@ class VFChatbotStandalone { ".vf-button--dismiss" ); - // Router element - this.routerEl = this.container.querySelector("[data-vf-js-chatbot-router]"); - // API configuration - Mistral AI this.API_TOKEN = ""; this.API_URL = "https://api.mistral.ai/v1/chat/completions"; // State this.hasInteracted = false; - this.currentAssistant = "general"; // Default assistant - - // Initialize the UI - this.init(); - } - - init() { - // Initialize router if present - if (this.routerEl) { - const router = initVFChatbotRouter(this.routerEl); - this.routerEl.addEventListener('routeselection', (e) => { - this.handleRouteSelection(e.detail); - }); - } - // Bind other events this.bindEvents(); this.initAutoResize(); console.log("Standalone chatbot initialized successfully"); // Debug log } - handleRouteSelection(detail) { - const { selectedItems } = detail; - if (selectedItems && selectedItems.length > 0) { - this.currentAssistant = selectedItems[0]; - // You can add logic here to change the assistant's behavior based on selection - console.log(`Switched to ${this.currentAssistant} assistant`); - } - } - bindEvents() { console.log("Binding events for standalone chatbot..."); // Debug log @@ -482,15 +454,19 @@ function initVFChatbotStandalone() { } // Make initialization function available globally +const global = ( + typeof globalThis !== "undefined" ? globalThis : + typeof window !== "undefined" ? window : + typeof global !== "undefined" ? global : + typeof self !== "undefined" ? self : {} +); if (typeof window !== "undefined") { window.VFChatbotStandalone = VFChatbotStandalone; window.initVFChatbotStandalone = initVFChatbotStandalone; - // Also make it available as a global variable without window prefix - if (typeof globalThis !== "undefined") { - globalThis.VFChatbotStandalone = VFChatbotStandalone; - globalThis.initVFChatbotStandalone = initVFChatbotStandalone; - } + // Also make it available as a global variable + global.VFChatbotStandalone = VFChatbotStandalone; + global.initVFChatbotStandalone = initVFChatbotStandalone; console.log("Exposed initVFChatbotStandalone to global scope"); } diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk index 60042cc616..d1bcda6805 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk @@ -1,88 +1,218 @@ - -
    -
    -
    -
    -

    - - AI Assistant - {% set isMultiselect = true %} - {% set routerContext = { - context: { - chatbotRoutes: { - multiselect: isMultiselect, +{% set llm_selector = { + context: { + chatbotRoutes: + { + multiSelect: false, showSearch: true, + showSearchThreshold: 5, routes: [ { - id: "general", - title: "General Assistant", - description: "General purpose AI assistant", + id: "gpt4-turbo", + title: "GPT-4 Turbo", + description: "Advanced language model with broader context window and improved capabilities", selected: true }, { - id: "code", - title: "Code Assistant", - description: "Specialized in code and development" + id: "claude3-opus", + title: "Claude 3 Opus", + description: "Anthropic's most powerful model with enhanced reasoning and analysis capabilities" }, { - id: "science", - title: "Science Assistant", - description: "Expert in scientific queries" + id: "gemini-ultra", + title: "Gemini Ultra", + description: "Google's most capable model for complex tasks and multitask reasoning" }, { - id: "general", - title: "General Assistant", - description: "General purpose AI assistant", - selected: true + id: "llama3", + title: "LLaMA 3", + description: "Meta's open foundation model with strong performance across various tasks" + }, + { + id: "mixtral", + title: "Mixtral 8x7B", + description: "Mistral AI's mixture-of-experts model combining multiple specialized networks" }, { - id: "code", - title: "Code Assistant", - description: "Specialized in code and development" + id: "palm3", + title: "PaLM 3", + description: "Google's latest PaLM model optimized for reasoning and multilingual tasks" }, { - id: "science", - title: "Science Assistant", - description: "Expert in scientific queries" + id: "gpt4-vision", + title: "GPT-4 Vision", + description: "Specialized version of GPT-4 for multimodal tasks including image understanding" }, { - id: "general", - title: "General Assistant", - description: "General purpose AI assistant", + id: "claude3-sonnet", + title: "Claude 3 Sonnet", + description: "Balanced model offering strong performance with improved efficiency" + } + ] + } + } + } +%} +{% set services_single_selector = { + context: { + chatbotRoutes: { + multiSelect: false, + showSearch: true, + showSearchThreshold: 5, + routes: [ + { + id: "ensembl", + title: "Ensembl", + description: "Genome browser for vertebrate genomes with comparative genomics tools", selected: true }, { - id: "code", - title: "Code Assistant", - description: "Specialized in code and development" + id: "uniprot", + title: "UniProt", + description: "Comprehensive resource for protein sequence and annotation data" }, { - id: "science", - title: "Science Assistant", - description: "Expert in scientific queries" + id: "pfam", + title: "Pfam", + description: "Database of protein families and domains with HMM models" }, { - id: "general", - title: "General Assistant", - description: "General purpose AI assistant", - selected: true + id: "interpro", + title: "InterPro", + description: "Integrated database of protein families, domains and functional sites" + }, + { + id: "chembl", + title: "ChEMBL", + description: "Database of bioactive drug-like small molecules and their targets" + }, + { + id: "pdbe", + title: "PDBe", + description: "European resource for 3D biological macromolecular structure data" + }, + { + id: "expression-atlas", + title: "Expression Atlas", + description: "Gene expression data across species and biological conditions" + }, + { + id: "pride", + title: "PRIDE", + description: "Repository of mass spectrometry-based proteomics data" + }, + { + id: "arrayexpress", + title: "ArrayExpress", + description: "Archive of functional genomics experiments" + }, + { + id: "intact", + title: "IntAct", + description: "Molecular interaction database derived from literature curation" + }, + { + id: "reactome", + title: "Reactome", + description: "Curated database of biological pathways and reactions" + }, + { + id: "metabolights", + title: "MetaboLights", + description: "Database for metabolomics experiments and derived information" + } + ] + } + } + } +%} +{% set services_multi_selector = { + context: { + chatbotRoutes: + { + multiSelect: true, + maxMultiSelect: 3, + showSearch: true, + showSearchThreshold: 5, + routes: [ + { + id: "ensembl", + title: "Ensembl", + description: "Genome browser for vertebrate genomes with comparative genomics tools", + "selected": true + }, + { + id: "uniprot", + title: "UniProt", + description: "Comprehensive resource for protein sequence and annotation data" + }, + { + id: "pfam", + title: "Pfam", + description: "Database of protein families and domains with HMM models" + }, + { + id: "interpro", + title: "InterPro", + description: "Integrated database of protein families, domains and functional sites" + }, + { + id: "chembl", + title: "ChEMBL", + description: "Database of bioactive drug-like small molecules and their targets" + }, + { + id: "pdbe", + title: "PDBe", + description: "European resource for 3D biological macromolecular structure data" + }, + { + id: "expression-atlas", + title: "Expression Atlas", + description: "Gene expression data across species and biological conditions" }, { - id: "code", - title: "Code Assistant", - description: "Specialized in code and development" + id: "pride", + title: "PRIDE", + description: "Repository of mass spectrometry-based proteomics data" }, { - id: "science", - title: "Science Assistant", - description: "Expert in scientific queries" + id: "arrayexpress", + title: "ArrayExpress", + description: "Archive of functional genomics experiments" + }, + { + id: "intact", + title: "IntAct", + description: "Molecular interaction database derived from literature curation" + }, + { + id: "reactome", + title: "Reactome", + description: "Curated database of biological pathways and reactions" + }, + { + id: "metabolights", + title: "MetaboLights", + description: "Database for metabolomics experiments and derived information" } ] } } - } %} - {% render '@vf-chatbot-router', routerContext %} -

    + } +%} +{% set routerContext = llm_selector %} +{# {% set routerContext = services_single_selector %} +{% set routerContext = services_multi_selector %} #} + +
    +
    +
    +
    + {#
    #} + + {# AI Assistant #} + {% render "@vf-chatbot-router", routerContext %} + {#
    #}
    @@ -90,45 +220,45 @@
    - - {% if welcome_message %} - -
    -
    - -

    {{ welcome_title | default('AI assistant') }}

    -

    - {{ welcome_description | default("Welcome! I'm here to help you discover bioinformatics training and resources.") }} -

    + + {% if welcome_message %} + +
    +
    + +

    {{ welcome_title | default('AI assistant') }}

    +

    + {{ welcome_description | default("Welcome! I'm here to help you discover bioinformatics training and resources.") }} +

    -
    -

    Try asking me:

    -
    - {% for suggestion in welcome_suggestions %} - {% if loop.index == welcome_suggestions.length and welcome_suggestions.length > 2 %} - {% render '@vf-chatbot-action-prompt', { +
    +

    Try asking me:

    +
    + {% for suggestion in welcome_suggestions %} + {% if loop.index == welcome_suggestions.length and welcome_suggestions.length > 2 %} + {% render '@vf-chatbot-action-prompt', { action_text: suggestion, action_data: suggestion, modifier_class: "vf-chatbot-action-prompt--full-width", data_attribute: "data-vf-js-chatbot-standalone-suggestion=" + suggestion, data_vf_js_chatbot_action_prompt: true } %} - {% else %} - {% render '@vf-chatbot-action-prompt', { + {% else %} + {% render '@vf-chatbot-action-prompt', { action_text: suggestion, action_data: suggestion, data_attribute: "data-vf-js-chatbot-standalone-suggestion=" + suggestion, data_vf_js_chatbot_action_prompt: true } %} - {% endif %} - {% endfor %} -
    + {% endif %} + {% endfor %}
    - {#
    +
    + {#
    AI Assistant
    @@ -136,7 +266,7 @@ {{ welcome_message | default('Hello! How can I help you today?') }}
    #} - {% endif %} + {% endif %}
    @@ -177,16 +307,17 @@
    #}
    {% if disclaimer %} -
    -
    -
    -

    {{ disclaimer }}

    - +
    +
    +
    +

    {{ disclaimer }}

    + +
    -
    {% endif %} {#
    #}
    diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss index e0b76e4b19..494988fd8c 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss @@ -419,13 +419,6 @@ } } -.vf-chatbot-standalone__title img { - width: 24px; - height: 24px; - margin-right: 8px; - vertical-align: middle; -} - .vf-chatbot-standalone__welcome-logo img { width: 64px; height: 64px; From f9a6721bd7d39189c372b122cd9de071aa7c781f Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Mon, 2 Jun 2025 15:35:30 +0100 Subject: [PATCH 07/71] VF chatbot- Standalone chatbot fixes --- .../vf-chatbot-router/vf-chatbot-router.njk | 4 +- .../vf-chatbot-standalone.js | 53 ++++++++++++++++--- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/components/vf-chatbot-router/vf-chatbot-router.njk b/components/vf-chatbot-router/vf-chatbot-router.njk index 3549395b09..15c9076168 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.njk +++ b/components/vf-chatbot-router/vf-chatbot-router.njk @@ -1,4 +1,4 @@ -
    +
    +
    + +
    +

    {{ message | default('Are you sure you want to close the chat?') }}

    +

    {{ submessage | default('Your current conversation history will be permanently deleted.') }}

    +
    + +
    + + +
    +
    +
    diff --git a/components/vf-chatbot-dialog/vf-chatbot-dialog.scss b/components/vf-chatbot-dialog/vf-chatbot-dialog.scss new file mode 100644 index 0000000000..bb9a49e1d7 --- /dev/null +++ b/components/vf-chatbot-dialog/vf-chatbot-dialog.scss @@ -0,0 +1,102 @@ +.vf-chatbot-dialog { + position: absolute; // Change from fixed to absolute + top: 0; + left: 0; + padding: 5%; + width: 90%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: none; + justify-content: center; + align-items: center; + z-index: 9999; // Increase z-index to be above other modal elements + + &__content { + background: white; + padding: 24px; + width: 100%; + max-width: 480px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + position: relative; + margin: auto; + animation: dialogFadeIn 0.2s ease-out; + } + + &__header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + } + + &__title { + font-size: 24px; + font-weight: 500; + margin: 0; + } + + &__close { + background: none; + border: none; + cursor: pointer; + padding: 4px; + + &:hover { + opacity: 0.7; + } + } + + &__body { + margin-bottom: 24px; + + p { + margin: 8px 0; + color: #666; + } + } + + &__actions { + display: flex; + gap: 16px; + justify-content: flex-end; + } + + &__button { + padding: 8px 16px; + border-radius: 4px; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s; + + &--outline { + background: none; + border: 1px solid #1a73e8; + color: #1a73e8; + + &:hover { + background: rgba(26, 115, 232, 0.04); + } + } + + &--primary { + background: #1a73e8; + border: none; + color: white; + + &:hover { + background: #1557b0; + } + } + } +} + +@keyframes dialogFadeIn { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} diff --git a/components/vf-chatbot-fab/vf-chatbot-fab.js b/components/vf-chatbot-fab/vf-chatbot-fab.js index f756c5850a..3031537224 100644 --- a/components/vf-chatbot-fab/vf-chatbot-fab.js +++ b/components/vf-chatbot-fab/vf-chatbot-fab.js @@ -3,7 +3,7 @@ function VFChatbotFab(element) { this.el = element; this.chatIcon = this.el.querySelector(".vf-chatbot-fab__icon--chat"); - this.closeIcon = this.el.querySelector(".vf-chatbot-fab__icon--close"); + // this.closeIcon = this.el.querySelector(".vf-chatbot-fab__icon--close"); this.init(); } @@ -25,10 +25,6 @@ VFChatbotFab.prototype = { // Toggle icons if (this.el.classList.contains("vf-chatbot-fab--active")) { this.chatIcon.style.display = "none"; - this.closeIcon.style.display = "block"; - } else { - this.chatIcon.style.display = "block"; - this.closeIcon.style.display = "none"; } // Dispatch event for parent chatbot component diff --git a/components/vf-chatbot-fab/vf-chatbot-fab.njk b/components/vf-chatbot-fab/vf-chatbot-fab.njk index 606696a080..7f63cde9d1 100644 --- a/components/vf-chatbot-fab/vf-chatbot-fab.njk +++ b/components/vf-chatbot-fab/vf-chatbot-fab.njk @@ -1,20 +1,34 @@ - \ No newline at end of file + diff --git a/components/vf-chatbot-fab/vf-chatbot-fab.scss b/components/vf-chatbot-fab/vf-chatbot-fab.scss index 95f9f09548..3cfba7b4e8 100644 --- a/components/vf-chatbot-fab/vf-chatbot-fab.scss +++ b/components/vf-chatbot-fab/vf-chatbot-fab.scss @@ -1,23 +1,25 @@ .vf-chatbot-fab { position: fixed; - bottom: 20px; - right: 20px; - width: 56px; - height: 56px; - border-radius: 50%; - background: #007AFF; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); - cursor: pointer; - transition: transform 0.2s ease, background-color 0.2s ease; + bottom: 2rem; + right: 2rem; + z-index: 5000; display: flex; align-items: center; justify-content: center; - z-index: 1000; + width: 3.5rem; + height: 3.5rem; + padding: 0; border: none; + border-radius: 50%; + border-bottom-right-radius: 10%; + background: #18974C; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + cursor: pointer; + transition: all 0.3s ease; &:hover { transform: scale(1.05); - background: darken(#007AFF, 10%); + background: darken(#18974C, 10%); } &__icon { @@ -25,4 +27,8 @@ height: 24px; fill: #ffffff; } + + &--active { + display: none; + } } diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.js b/components/vf-chatbot-feedback/vf-chatbot-feedback.js index 74d16e9634..818317a3f3 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.js +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.js @@ -39,16 +39,23 @@ export class VFChatbotFeedback { ); if (thumbsUp) { - thumbsUp.addEventListener("click", () => - this.handleThumbsClick("positive") - ); + thumbsUp.addEventListener("click", e => { + e.stopPropagation(); // Prevent bubbling + this.handleThumbsClick("positive"); + }); } if (thumbsDown) { - thumbsDown.addEventListener("click", () => - this.handleThumbsClick("negative") - ); + thumbsDown.addEventListener("click", e => { + e.stopPropagation(); // Prevent bubbling + this.handleThumbsClick("negative"); + }); } + + // Stop propagation on the entire feedback component + this.el.addEventListener("click", e => { + e.stopPropagation(); + }); } handleThumbsClick(type) { @@ -109,10 +116,11 @@ export class VFChatbotFeedback { `; - // Add event listeners for options + // Add event listeners for options with stopPropagation const options = formEl.querySelectorAll(".vf-chatbot-feedback__option"); options.forEach(option => { option.addEventListener("click", e => { + e.stopPropagation(); // Prevent bubbling // Remove selected class from all options options.forEach(opt => opt.classList.remove("vf-chatbot-feedback__option--selected") @@ -122,18 +130,16 @@ export class VFChatbotFeedback { }); }); - // Add submit handler + // Add submit handler with stopPropagation const submitBtn = formEl.querySelector(".vf-chatbot-feedback__submit"); - submitBtn.addEventListener("click", () => this.submitFeedback()); + submitBtn.addEventListener("click", e => { + e.stopPropagation(); // Prevent bubbling + this.submitFeedback(); + }); formContainer.appendChild(formEl); // Scroll the form into view formEl.scrollIntoView({ behavior: "smooth", block: "nearest" }); - - // // Ensure the feedback form is visible - // setTimeout(() => { - // formContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); - // }, 100); } async submitFeedback() { @@ -168,15 +174,16 @@ export class VFChatbotFeedback {
    `; - // Add close button event listener + // Add close button event listener with stopPropagation const closeBtn = formContainer.querySelector(".vf-banner__close"); if (closeBtn) { - closeBtn.addEventListener("click", () => { + closeBtn.addEventListener("click", e => { + e.stopPropagation(); // Prevent bubbling formContainer.innerHTML = ""; }); } - // Hide the unselected thumb by setting display: none + // Hide the unselected thumb const otherThumb = this.el.querySelector( this.selectedFeedback === "positive" ? "[data-vf-js-feedback-thumbs-down]" @@ -186,7 +193,7 @@ export class VFChatbotFeedback { otherThumb.style.display = "none"; } - // Add solid class only to the selected thumb + // Add solid class to selected thumb const selectedThumb = this.el.querySelector( this.selectedFeedback === "positive" ? "[data-vf-js-feedback-thumbs-up]" @@ -210,7 +217,7 @@ export class VFChatbotFeedback {
    `; - // On error, remove solid class from both thumbs to restore original state + // Reset thumbs state const thumbsUp = this.el.querySelector("[data-vf-js-feedback-thumbs-up]"); const thumbsDown = this.el.querySelector( "[data-vf-js-feedback-thumbs-down]" @@ -218,10 +225,11 @@ export class VFChatbotFeedback { thumbsUp?.classList.remove("vf-chatbot-feedback__thumb--solid"); thumbsDown?.classList.remove("vf-chatbot-feedback__thumb--solid"); - // Add close button event listener + // Add close button event listener with stopPropagation const closeBtn = formContainer.querySelector(".vf-banner__close"); if (closeBtn) { - closeBtn.addEventListener("click", () => { + closeBtn.addEventListener("click", e => { + e.stopPropagation(); // Prevent bubbling formContainer.innerHTML = ""; }); } diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.scss b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss index 100bb77a77..c6b62d6cd6 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.scss +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss @@ -59,6 +59,7 @@ gap: 0.5rem; flex-direction: row; margin-bottom: 1rem; + flex-wrap: wrap; @media (max-width: 480px) { grid-template-columns: 1fr; @@ -74,6 +75,7 @@ color: #3B6FB6; border-radius: 0px; border: 1px solid #224B9A; + flex: 1 1 150px; &--selected { background: #D1E3F6; diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.config.yml b/components/vf-chatbot-modal/vf-chatbot-modal.config.yml new file mode 100644 index 0000000000..7ed722d66a --- /dev/null +++ b/components/vf-chatbot-modal/vf-chatbot-modal.config.yml @@ -0,0 +1,10 @@ +title: Chatbot Modal +label: Chatbot Modal +status: beta +preview: '@preview' +context: + title: AI Assistant + welcome_message: Hello! How can I help you today? + input_placeholder: Type your message... + show_suggestions: true + disclaimer: 'Disclaimer: This chatbot is designed to assist you with general information and basic inquiries. See our disclaimer notes.' diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.js b/components/vf-chatbot-modal/vf-chatbot-modal.js index bc2f5c7f28..d505b7cfdb 100644 --- a/components/vf-chatbot-modal/vf-chatbot-modal.js +++ b/components/vf-chatbot-modal/vf-chatbot-modal.js @@ -1,53 +1,115 @@ // vf-chatbot-modal +import { initVFChatbotSources } from "../vf-chatbot-sources/vf-chatbot-sources"; +import { VFChatbotFeedback } from "../vf-chatbot-feedback/vf-chatbot-feedback.js"; +import { initVFChatbotRouter } from "../vf-chatbot-router/vf-chatbot-router.js"; +import { initVFChatbotDialog } from "../vf-chatbot-dialog/vf-chatbot-dialog.js"; class VFChatbotModal { constructor(element) { - console.log("Initializing chatbot modal..."); // Debug log - - // API configuration - this.API_TOKEN = ""; - this.API_URL = - "https://api-inference.huggingface.co/models/facebook/blenderbot-400M-distill"; + // console.log("Initializing chatbot modal..."); // UNUSED: Debug log // Store DOM elements - this.modal = element; - this.trigger = document.querySelector("[data-vf-js-chatbot-trigger]"); - this.closeBtn = this.modal.querySelector("[data-vf-js-chatbot-close]"); - this.minimizeBtn = this.modal.querySelector( - "[data-vf-js-chatbot-minimize]" + this.container = element; + this.chatInterface = this.container.querySelector( + "[data-vf-js-chatbot-modal-chat]" + ); + this.welcomeScreen = this.container.querySelector( + "[data-vf-js-chatbot-modal-welcome]" + ); + this.messagesContainer = this.container.querySelector( + "[data-vf-js-chatbot-modal-messages]" + ); + this.loadingIndicator = this.container.querySelector( + "[data-vf-js-chatbot-modal-loading]" ); - this.input = this.modal.querySelector(".vf-chatbot-modal__input"); - this.sendBtn = this.modal.querySelector("[data-vf-js-chatbot-send]"); - this.messagesContainer = this.modal.querySelector( - ".vf-chatbot-modal__messages" + this.input = this.container.querySelector( + "[data-vf-js-chatbot-modal-input]" ); - this.welcomeScreen = this.modal.querySelector( - "[data-vf-js-chatbot-welcome]" + this.sendBtn = this.container.querySelector( + "[data-vf-js-chatbot-modal-send]" ); - this.suggestionBtns = this.modal.querySelectorAll( + this.welcomeInput = this.container.querySelector( + "[data-vf-js-chatbot-welcome-input]" + ); + this.welcomeSendBtn = this.container.querySelector( + "[data-vf-js-chatbot-welcome-send]" + ); + this.suggestionBtns = this.container.querySelectorAll( "[data-vf-js-chatbot-suggestion]" ); + this.closeBtn = this.container.querySelector("[data-vf-js-chatbot-close]"); + this.dialog = document.querySelector("[data-vf-js-chatbot-dialog]"); + + if (this.dialog) { + this.dialogComponent = initVFChatbotDialog(this.dialog); + this.dialog.addEventListener("vf-chatbot-dialog:confirm", () => { + this.resetAndClose(); + }); + } + + // Router element + this.routerEl = this.container.querySelector("[data-vf-js-chatbot-router]"); + + // API configuration - Mistral AI + this.API_TOKEN = ""; + this.API_URL = "https://api.mistral.ai/v1/chat/completions"; + + // Disclaimer elements + this.disclaimerEl = this.container.querySelector( + "[data-vf-js-chatbot-modal-disclaimer]" + ); + this.disclaimerCloseBtn = this.container.querySelector( + "[data-vf-js-chatbot-disclaimer-close]" + ); // State this.hasInteracted = false; + this.currentAssistant = "general"; // Default assistant - this.bindEvents(); + // Initialize the UI + this.init(); } - bindEvents() { - console.log("Binding events..."); // Debug log + init() { + // Initialize router if present + if (this.routerEl) { + const router = initVFChatbotRouter(this.routerEl); + this.routerEl.addEventListener("routeselection", e => { + this.handleRouteSelection(e.detail); + }); - // Toggle modal - this.trigger?.addEventListener("click", () => this.toggleModal()); - this.closeBtn?.addEventListener("click", e => { - e.stopPropagation(); - this.closeModal(); - }); - this.minimizeBtn?.addEventListener("click", e => { - e.stopPropagation(); - this.minimize(); - }); + // Set initial route selection based on variant + if (this.routerEl.dataset.variant) { + const variantRoutes = this.routerEl.querySelectorAll( + "[data-vf-js-router-item]" + ); + variantRoutes.forEach(item => { + if (item.dataset.routeId === this.routerEl.dataset.variant) { + router.handleItemSelection(item); + } + }); + } + } + + // Initialize disclaimer if present + if (this.disclaimerEl && this.disclaimerCloseBtn) { + this.bindDisclaimerEvents(); + } + + // Bind events + this.bindEvents(); + this.initAutoResize(); + } + + handleRouteSelection(detail) { + const { selectedItems } = detail; + if (selectedItems && selectedItems.length > 0) { + this.currentAssistant = selectedItems[0]; + console.log(`Switched to ${this.currentAssistant} assistant`); + } + } + bindEvents() { // Send message events this.sendBtn?.addEventListener("click", () => this.sendMessage()); this.input?.addEventListener("keypress", e => { @@ -58,39 +120,117 @@ class VFChatbotModal { }); // Welcome screen events - if (this.welcomeScreen) { - this.welcomeScreen.addEventListener("vf-chatbot-welcome:closed", () => { - this.showChatInterface(); - }); - - this.welcomeScreen.addEventListener( - "vf-chatbot-welcome:suggestion", - event => { - const { text } = event.detail; - this.showChatInterface(); - this.sendUserMessage(text); - } - ); - } + this.welcomeSendBtn?.addEventListener("click", () => + this.sendWelcomeMessage() + ); + this.welcomeInput?.addEventListener("keypress", e => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this.sendWelcomeMessage(); + } + }); - // Suggestion buttons + // Welcome screen suggestion buttons this.suggestionBtns.forEach(btn => { btn.addEventListener("click", () => { const text = btn.getAttribute("data-vf-js-chatbot-suggestion") || btn.textContent.trim(); - this.sendUserMessage(text); + + // Show chat interface + this.showChatInterface(); + + // Update the input field with the suggestion text + if (this.input && text) { + this.input.value = text; + + // Adjust the height of the input field to match content + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + } + + // Send the message to the API + if (text) { + this.sendUserMessage(text); + } }); }); + + // Modal controls + this.closeBtn?.addEventListener("click", e => { + e.preventDefault(); + e.stopPropagation(); + this.dialogComponent?.show(); + }); + + // Listen for action prompt clicks + this.container.addEventListener("vf-chatbot-action-prompt:click", event => { + const { text } = event.detail; + + // Show chat interface + this.showChatInterface(); + + // Update the input field with the suggestion text + if (this.input && text) { + this.input.value = text; + + // Adjust the height of the input field to match content + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + } + + // Send the message to the API + if (text) { + this.sendUserMessage(text); + } + }); + } + + bindDisclaimerEvents() { + this.disclaimerCloseBtn.addEventListener("click", e => { + e.stopPropagation(); // Prevent event from bubbling to modal + this.disclaimerEl.style.display = "none"; + }); + } + + initAutoResize() { + // Auto-resize textarea as user types + if (this.input) { + this.input.addEventListener("input", () => { + this.input.style.height = "auto"; + this.input.style.height = this.input.scrollHeight + "px"; + }); + } + } + + sendMessage() { + if (!this.input || !this.input.value.trim()) return; + + const text = this.input.value.trim(); + this.sendUserMessage(text); + } + + sendWelcomeMessage() { + if (!this.welcomeInput || !this.welcomeInput.value.trim()) return; + + const text = this.welcomeInput.value.trim(); + this.showChatInterface(); + this.sendUserMessage(text); } showChatInterface() { if (this.welcomeScreen) { this.welcomeScreen.style.display = "none"; } + if (this.messagesContainer) { + this.messagesContainer.style.display = "flex"; + } + + // Focus on the input field + if (this.input) { + this.input.focus(); + } - this.messagesContainer.style.display = "block"; - this.input.focus(); this.hasInteracted = true; } @@ -102,53 +242,58 @@ class VFChatbotModal { } minimize() { - this.modal.classList.add("vf-chatbot-modal--minimized"); - this.modal.classList.remove("vf-chatbot-modal--active"); - - // Dispatch minimize event - this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:minimize")); + console.log("Modal minimizing, dispatching hide event"); // Debug log + this.container.classList.remove("vf-chatbot-modal--active"); + document.dispatchEvent(new CustomEvent('vf-chatbot-modal:hide')); } + // UNUSED: maximize() is not needed since we use simple show/hide + /* maximize() { // First remove minimized to ensure smooth transition - this.modal.classList.remove("vf-chatbot-modal--minimized"); + this.container.classList.remove("vf-chatbot-modal--minimized"); // Small delay to ensure CSS transition works properly requestAnimationFrame(() => { - this.modal.classList.add("vf-chatbot-modal--active"); + this.container.classList.add("vf-chatbot-modal--active"); // Focus on input if it exists - const input = this.modal.querySelector(".vf-chatbot-modal__input"); + const input = this.container.querySelector(".vf-chatbot-modal__input"); if (input) { setTimeout(() => input.focus(), 300); } }); // Dispatch maximize event - this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:maximize")); + this.container.dispatchEvent(new CustomEvent("vf-chatbot-modal:maximize")); // Focus on input if welcome screen is not shown if (this.hasInteracted) { setTimeout(() => this.input.focus(), 300); } } + */ closeModal() { - this.modal.classList.remove("vf-chatbot-modal--active"); - this.modal.classList.remove("vf-chatbot-modal--minimized"); + this.container.classList.remove("vf-chatbot-modal--active"); + this.container.classList.remove("vf-chatbot-modal--minimized"); // Reset welcome screen for next open this.resetWelcomeScreen(); // Dispatch close event - this.modal.dispatchEvent(new CustomEvent("vf-chatbot-modal:close")); + this.container.dispatchEvent(new CustomEvent("vf-chatbot-modal:close")); } + // UNUSED: toggleModal() is not needed with simplified show/hide + /* toggleModal() { - const isMinimized = this.modal.classList.contains( + const isMinimized = this.container.classList.contains( "vf-chatbot-modal--minimized" ); - const isActive = this.modal.classList.contains("vf-chatbot-modal--active"); + const isActive = this.container.classList.contains( + "vf-chatbot-modal--active" + ); if (isMinimized || !isActive) { this.maximize(); @@ -156,71 +301,229 @@ class VFChatbotModal { this.minimize(); } } + */ sendUserMessage(text) { + if (!text || !this.messagesContainer) return; + // Add user message to UI const userMessageEl = document.createElement("div"); userMessageEl.className = "vf-chatbot-message vf-chatbot-message--user"; userMessageEl.innerHTML = ` +
    + You + You +
    ${text}
    `; - this.messagesContainer.appendChild(userMessageEl); + this.messagesContainer.insertBefore(userMessageEl, this.loadingIndicator); // Clear input if this came from the input field - if (this.input.value === text) { + if (this.input && this.input.value === text) { this.input.value = ""; + this.input.style.height = "auto"; // Reset height } this.scrollToBottom(); - // Process the message (simulate response) + // Process the message this.processUserMessage(text); } - sendMessage() { - const text = this.input.value.trim(); - if (!text) return; - - this.sendUserMessage(text); - } - - async processUserMessage(message) { + processUserMessage(text) { // Show loading state this.setLoadingState(true); - try { - const response = await this.callAPI(message); - console.log("API Response:", response); // Debug log - this.addMessage(response, "system"); - } catch (error) { - console.error("Error:", error); - this.addMessage( - "Sorry, I encountered an error. Please try again.", - "system" - ); - } + // Call the API + this.callAPI(text) + .then(response => { + // Extract sources if available, otherwise use the original response text + const sources = response.sources || [ + { + domain: "re3data.org", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "MetaboLights is a public repository for metabolomics data, including raw and processed data, metadata, and analysis results." + }, + { + domain: "academic.oup.com", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "16 November 2024 - MetaboLights is a global, open-access database for metabolomics studies, providing raw experimental data and metadata. It supports multiple species and techniques, offering structured metabolite ..." + }, + { + domain: "re3data.org", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "MetaboLights is a public repository for metabolomics data, including raw and processed data, metadata, and analysis results." + }, + { + domain: "academic.oup.com", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "16 November 2024 - MetaboLights is a global, open-access database for metabolomics studies, providing raw experimental data and metadata. It supports multiple species and techniques, offering structured metabolite ..." + }, + { + domain: "re3data.org", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "MetaboLights is a public repository for metabolomics data, including raw and processed data, metadata, and analysis results." + }, + { + domain: "academic.oup.com", + title: "MetaboLights: open data repository for metabolomics", + url: "#", + description: + "16 November 2024 - MetaboLights is a global, open-access database for metabolomics studies, providing raw experimental data and metadata. It supports multiple species and techniques, offering structured metabolite ..." + } + ]; + const responseText = response.html || response; + + // Add assistant response to UI + this.addAssistantResponse(responseText, sources); + + // Hide loading state + this.setLoadingState(false); + }) + .catch(error => { + console.error("API Error:", error); + // Fallback to simulated response if API fails + this.addAssistantResponse(this.getSimulatedResponse(text)); + this.setLoadingState(false); + }); + } - // // Simulate API call with timeout - setTimeout(() => { - // Add assistant response - this.addAssistantResponse(this.getSimulatedResponse(message)); - this.setLoadingState(false); - }, 1000); + callAPI(text) { + return new Promise((resolve, reject) => { + fetch(this.API_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${this.API_TOKEN}` + }, + body: JSON.stringify({ + model: "mistral-tiny", + messages: [ + { role: "system", content: "You are a helpful assistant." }, + { role: "user", content: text } + ] + }) + }) + .then(response => { + if (!response.ok) { + throw new Error(`API error: ${response.status}`); + } + return response.json(); + }) + .then(data => { + if ( + data && + data.choices && + data.choices[0] && + data.choices[0].message && + data.choices[0].message.content + ) { + resolve(data.choices[0].message.content); + } else { + reject(new Error("Invalid API response")); + } + }) + .catch(error => { + console.error("API call failed:", error); + reject(error); + }); + }); } - addAssistantResponse(text) { + addAssistantResponse(text, sources = []) { + if (!text || !this.messagesContainer) return; + + // Add assistant message to UI const assistantMessageEl = document.createElement("div"); assistantMessageEl.className = "vf-chatbot-message vf-chatbot-message--assistant"; assistantMessageEl.innerHTML = ` - AI Assistant +
    +
    + AI Assistant +
    + AI Assistant +
    ${text}
    `; - this.messagesContainer.appendChild(assistantMessageEl); + // Add sources if available + if (sources && sources.length > 0) { + const sourcesEl = initVFChatbotSources(sources); + + // Enhance: scroll to bottom when sources are expanded + const toggleBtn = sourcesEl.el.querySelector( + "[data-vf-js-chatbot-sources-toggle]" + ); + const sourcesDiv = sourcesEl.el.querySelector( + "[data-vf-js-chatbot-sources]" + ); + + if (toggleBtn && sourcesDiv) { + toggleBtn.addEventListener("click", () => { + // Wait for the sources div to expand, then scroll + setTimeout(() => { + if (this.messagesContainer) { + this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + } + }, 100); + }); + } + + assistantMessageEl.appendChild(sourcesEl.el); + } + + // Add feedback + const feedbackTemplate = ` +
    +
    + + +
    +
    +
    + `; + + const feedbackEl = document.createElement("div"); + feedbackEl.innerHTML = feedbackTemplate; + assistantMessageEl.appendChild(feedbackEl.firstElementChild); + + // Initialize feedback after element is in DOM + const feedbackComponent = assistantMessageEl.querySelector( + "[data-vf-js-chatbot-feedback]" + ); + if (feedbackComponent) { + new VFChatbotFeedback(feedbackComponent, `response-${Date.now()}`); + } + + // Insert before loading indicator + this.messagesContainer.insertBefore( + assistantMessageEl, + this.loadingIndicator + ); this.scrollToBottom(); } + // UNUSED: Old version of getSimulatedResponse can be removed + /* getSimulatedResponse(text) { // Simple response simulation if (text.toLowerCase().includes("metabolomics")) { @@ -247,21 +550,63 @@ class VFChatbotModal { return "I'm sorry, I didn't understand that. Could you please provide more context or ask a specific question?"; } } + */ setLoadingState(isLoading) { - this.input.disabled = isLoading; - this.sendBtn.disabled = isLoading; - this.sendBtn.innerHTML = isLoading ? "Sending..." : "Send"; + if (this.loadingIndicator) { + this.loadingIndicator.style.display = isLoading ? "flex" : "none"; + } + + if (this.sendBtn) { + this.sendBtn.disabled = isLoading; + } + + if (this.input) { + this.input.disabled = isLoading; + } + + this.scrollToBottom(); } scrollToBottom() { - this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + if (this.messagesContainer) { + this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; + } + } + + getSimulatedResponse() { + // Fallback responses when API fails + const fallbackResponses = [ + "I'm sorry, I'm having trouble connecting to my knowledge base right now. Could you try again in a moment?", + "That's an interesting question. Let me think about how to best answer that for you.", + "I understand you're asking about bioinformatics training. We have several resources available. Could you tell me more about your specific interests?", + "Thank you for your question. We offer various workshops and online courses on that topic. Would you like me to provide more specific information?", + "I'd be happy to help with that. We have both introductory and advanced courses available depending on your experience level." + ]; + + return fallbackResponses[ + Math.floor(Math.random() * fallbackResponses.length) + ]; + } + + resetAndClose() { + // Clear chat history + this.messagesContainer.innerHTML = ""; + + // Reset to welcome screen + // this.showWelcomeScreen(); + + // Close modal + this.close(); + + // Dispatch event + this.container.dispatchEvent(new CustomEvent("vf-chatbot-modal:reset")); } } // Initialize function initVFChatbotModal() { - console.log("Looking for chatbot elements..."); // Debug log + // console.log("Looking for chatbot elements..."); // UNUSED: Debug log const chatbotElements = document.querySelectorAll( "[data-vf-js-chatbot-modal]" ); @@ -271,8 +616,20 @@ function initVFChatbotModal() { return; } - console.log(`Found ${chatbotElements.length} chatbot elements`); // Debug log - chatbotElements.forEach(element => new VFChatbotModal(element)); + // console.log(`Found ${chatbotElements.length} chatbot elements`); // UNUSED: Debug log + + const instances = []; + chatbotElements.forEach(element => { + instances.push(new VFChatbotModal(element)); + }); + + return instances; +} + +// REDUNDANT: Simplify global assignments +if (typeof window !== "undefined") { + window.VFChatbotModal = VFChatbotModal; + window.initVFChatbotModal = initVFChatbotModal; } export { VFChatbotModal, initVFChatbotModal }; diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.njk b/components/vf-chatbot-modal/vf-chatbot-modal.njk index ed46d2558a..6d87f8801e 100644 --- a/components/vf-chatbot-modal/vf-chatbot-modal.njk +++ b/components/vf-chatbot-modal/vf-chatbot-modal.njk @@ -1,91 +1,348 @@ +{% set llm_selector = { + context: { + chatbotRoutes: + { + multiSelect: false, + showSearch: true, + showSearchThreshold: 5, + routes: [ + { + id: "gpt4-turbo", + title: "GPT-4 Turbo", + description: "Advanced language model with broader context window and improved capabilities", + selected: true + }, + { + id: "claude3-opus", + title: "Claude 3 Opus", + description: "Anthropic's most powerful model with enhanced reasoning and analysis capabilities" + }, + { + id: "gemini-ultra", + title: "Gemini Ultra", + description: "Google's most capable model for complex tasks and multitask reasoning" + }, + { + id: "llama3", + title: "LLaMA 3", + description: "Meta's open foundation model with strong performance across various tasks" + }, + { + id: "mixtral", + title: "Mixtral 8x7B", + description: "Mistral AI's mixture-of-experts model combining multiple specialized networks" + }, + { + id: "palm3", + title: "PaLM 3", + description: "Google's latest PaLM model optimized for reasoning and multilingual tasks" + }, + { + id: "gpt4-vision", + title: "GPT-4 Vision", + description: "Specialized version of GPT-4 for multimodal tasks including image understanding" + }, + { + id: "claude3-sonnet", + title: "Claude 3 Sonnet", + description: "Balanced model offering strong performance with improved efficiency" + } + ] + } + } + } +%} +{% set services_single_selector = { + context: { + chatbotRoutes: { + multiSelect: false, + showSearch: true, + showSearchThreshold: 5, + routes: [ + { + id: "ensembl", + title: "Ensembl", + description: "Genome browser for vertebrate genomes with comparative genomics tools", + selected: true + }, + { + id: "uniprot", + title: "UniProt", + description: "Comprehensive resource for protein sequence and annotation data" + }, + { + id: "pfam", + title: "Pfam", + description: "Database of protein families and domains with HMM models" + }, + { + id: "interpro", + title: "InterPro", + description: "Integrated database of protein families, domains and functional sites" + }, + { + id: "chembl", + title: "ChEMBL", + description: "Database of bioactive drug-like small molecules and their targets" + }, + { + id: "pdbe", + title: "PDBe", + description: "European resource for 3D biological macromolecular structure data" + }, + { + id: "expression-atlas", + title: "Expression Atlas", + description: "Gene expression data across species and biological conditions" + }, + { + id: "pride", + title: "PRIDE", + description: "Repository of mass spectrometry-based proteomics data" + }, + { + id: "arrayexpress", + title: "ArrayExpress", + description: "Archive of functional genomics experiments" + }, + { + id: "intact", + title: "IntAct", + description: "Molecular interaction database derived from literature curation" + }, + { + id: "reactome", + title: "Reactome", + description: "Curated database of biological pathways and reactions" + }, + { + id: "metabolights", + title: "MetaboLights", + description: "Database for metabolomics experiments and derived information" + } + ] + } + } + } +%} +{% set services_multi_selector = { + context: { + chatbotRoutes: + { + multiSelect: true, + maxMultiSelect: 3, + showSearch: true, + showSearchThreshold: 5, + routes: [ + { + id: "ensembl", + title: "Ensembl", + description: "Genome browser for vertebrate genomes with comparative genomics tools", + "selected": true + }, + { + id: "uniprot", + title: "UniProt", + description: "Comprehensive resource for protein sequence and annotation data" + }, + { + id: "pfam", + title: "Pfam", + description: "Database of protein families and domains with HMM models" + }, + { + id: "interpro", + title: "InterPro", + description: "Integrated database of protein families, domains and functional sites" + }, + { + id: "chembl", + title: "ChEMBL", + description: "Database of bioactive drug-like small molecules and their targets" + }, + { + id: "pdbe", + title: "PDBe", + description: "European resource for 3D biological macromolecular structure data" + }, + { + id: "expression-atlas", + title: "Expression Atlas", + description: "Gene expression data across species and biological conditions" + }, + { + id: "pride", + title: "PRIDE", + description: "Repository of mass spectrometry-based proteomics data" + }, + { + id: "arrayexpress", + title: "ArrayExpress", + description: "Archive of functional genomics experiments" + }, + { + id: "intact", + title: "IntAct", + description: "Molecular interaction database derived from literature curation" + }, + { + id: "reactome", + title: "Reactome", + description: "Curated database of biological pathways and reactions" + }, + { + id: "metabolights", + title: "MetaboLights", + description: "Database for metabolomics experiments and derived information" + } + ] + } + } + } +%} +{# {% set routerContext = llm_selector %} #} +{# {% set routerContext = services_single_selector %} #} +{% set routerContext = services_multi_selector %} +
    -
    -
    -

    - AI Assistant - {{ title | default("AI Assistant") }} -

    -
    -
    - - +
    +
    +
    + {% render "@vf-chatbot-router", routerContext %} +
    +
    + + +
    -
    -
    - - {% render '@vf-chatbot-welcome', { - welcome_title: welcome_title | default('AI Assistant'), - welcome_description: welcome_description | default('I can help you find information about our research, services, and more. What would you like to know?'), - welcome_features: welcome_features | default([ - 'Finding research publications', - 'Learning about our services', - 'Getting information about events', - 'Understanding scientific concepts' - ]), - welcome_suggestions: welcome_suggestions | default([ - 'What is Metabolomics?', - 'Tell me about your training courses', - 'How can I access your data resources?', - 'What research areas do you focus on?' - ]) - } %} +
    + +
    + + {% if welcome_message %} + +
    +
    + +

    {{ welcome_title | default('AI assistant') }}

    +

    + {{ welcome_description | default("Welcome! I'm here to help you discover bioinformatics training and resources.") }} +

    - -
    - {% if welcome_message %} -
    - AI Assistant -
    - {{ welcome_message | safe }} +
    +

    Try asking me:

    +
    + {% set welcome_suggestions = [ + 'Find workshops near research institutions', + 'Recommend bioinformatics resources', + 'What prerequisites do I need for advanced advanced courses?' + ] + %} + {% for suggestion in welcome_suggestions %} + {% + render '@vf-chatbot-action-prompt', { + action_text: suggestion, + action_data: suggestion, + data_attribute: "data-vf-js-chatbot-modal-suggestion=" + suggestion, + data_vf_js_chatbot_action_prompt: true + } + %} + {% endfor %} +
    +
    +
    +
    + {#
    +
    + AI Assistant +
    +
    + {{ welcome_message | default('Hello! How can I help you today?') }} +
    +
    #} + {% endif %} + +
    + + + +
    + + + {% if disclaimer %} +
    +
    +
    +

    {{ disclaimer }}

    + +
    +
    +
    {% endif %} -
    -
    + {% render "@vf-chatbot-dialog", { + title: "Close chat and delete conversation?", + message: "Are you sure you want to close the chat?", + submessage: "Your current conversation history will be permanently deleted.", + cancelLabel: "Keep chat open", + confirmLabel: "Close and delete" + } %} + +
    - - {% if show_suggestions %} -
    - -
    - {% endif %}
    diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.scss b/components/vf-chatbot-modal/vf-chatbot-modal.scss index 7c7904df4b..9b57824123 100644 --- a/components/vf-chatbot-modal/vf-chatbot-modal.scss +++ b/components/vf-chatbot-modal/vf-chatbot-modal.scss @@ -4,21 +4,22 @@ bottom: 80px; right: 20px; width: 360px; - height: 500px; + // height: 600px; + height: 515px; background: #ffffff; - border-radius: 16px 16px 0px 16px; // Increased border radius - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + border-radius: 8px 8px 0px 8px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); z-index: 999; overflow: hidden; transition: all 0.3s ease; - opacity: 0; - transform: translateY(20px); + // opacity: 0; + // transform: translateY(20px); &--active { - display: flex; - flex-direction: column; - opacity: 1; - transform: translateY(0); + // display: flex; + // flex-direction: column; + // opacity: 1; + // transform: translateY(0); .vf-chatbot-modal__content { display: flex; @@ -41,79 +42,313 @@ } } + &__container { + display: flex; + flex-direction: column; + // height: 470px; + background: #ffffff; + + @media (max-width: 1200px) { + max-width: 100%; + } + } + &__header { - height: 60px; - min-height: 60px; // Add this to prevent header from shrinking - padding: 0 16px; - background: #ffffff; // White background + height: 45px; + min-height: 45px; + padding: 0 12px; + background: #ffffff; border-bottom: 1px solid #E5E5E5; color: #000000; display: flex; align-items: center; justify-content: space-between; - border-radius: 16px 16px 0 0; + // border-radius: 8px 8px 0 0; + position: sticky; + top: 0; + z-index: 2; &-left { display: flex; align-items: center; - gap: 8px; + gap: 12px; + + img { + width: 20px; + height: 20px; + } + } + + @media (max-width: 768px) { + padding: 0 16px; } } &__title { - font-size: 16px; + font-size: 18px; font-weight: 500; color: #1A1A1A; display: flex; align-items: center; - gap: 8px; + gap: 12px; + margin: 0; img { - width: 24px; - height: 24px; + width: 28px; + height: 28px; + } + } + + &__controls { + display: flex; + gap: 8px; + + button { + background: none; + border: none; + padding: 8px; + cursor: pointer; + color: #666666; + + &:hover { + color: #1A1A1A; + } } } &__content { + // overflow-y: scroll; + // border-radius: 4px 4px 4px 4px; + } + // Welcome screen styles + &__welcome { + width: 100%; + justify-content: center; + // flex: 1; display: flex; - flex-direction: column; - flex: 1; - transition: visibility 0.3s ease, height 0.3s ease; + // flex-direction: column; + // justify-content: center; + // align-items: center; + padding-top: 24px; + margin-bottom: 20px; + + &-content { + width: 100%; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + } + + &-logo { + + img { + width: 64px; + height: 62px; + } + } + + &-title { + font-size: 24px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 12px 0; + } + + &-description { + font-size: 16px; + line-height: 1.5; + color: #666666; + // height: 25vh; + // max-width: 450px; + } + + &-suggestions { + justify-items: left; + margin-top: 16px; + width: 87%; + + &-title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 16px 0; + } + + &-grid { + display: grid; + justify-items: inherit; // Center items horizontally + gap: 8px; + + // Ensure each grid cell only takes the width it needs + & > * { + width: auto; + min-width: min-content; + } + @media (max-width: 480px) { + grid-template-columns: 1fr; + } + } + } + + &-suggestion { + padding: 12px 16px; + background: #FFFFFF; + border: 1px solid #E5E5E5; + // border-radius: 8px; + font-size: 14px; + color: #1A1A1A; + cursor: pointer; + transition: background 0.2s ease, border-color 0.2s ease; + text-align: left; + + &:hover { + background: #F0F0F0; + border-color: #CCCCCC; + } + } + + &-input-container { + margin-top: 32px; + width: 100%; + max-width: 500px; + } + + &-input-wrapper { + position: relative; + width: 100%; + display: flex; + align-items: center; + background: #FFFFFF; + border: 1px solid #E5E5E5; + // border-radius: 8px; + overflow: hidden; + } + + &-input { + flex: 1; + padding: 16px; + border: none; + font-size: 16px; + line-height: 1.5; + background: transparent; + + &:focus { + outline: none; + } + + &::placeholder { + color: #666666; + } + } + + &-send-button { + background: #007AFF; + color: #ffffff; + border: none; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: darken(#007AFF, 10%); + } + + svg { + width: 24px; + height: 24px; + } + } } - &__messages { - flex: 1; - overflow-y: scroll; - padding: 16px; - background: #F5F5F5; + + + // &__suggestions { + // margin-top: 24px; + + // h3 { + // font-size: 14px; + // font-weight: 500; + // color: #666; + // margin: 0 0 16px; + // text-align: left; + // } + + // .suggestion-box { + // background: #EBF3FF; + // border: none; + // border-radius: 4px; + // padding: 12px 16px; + // color: #0066CC; + // font-size: 14px; + // line-height: 1.4; + // text-align: left; + // width: 100%; + // margin-bottom: 8px; + // cursor: pointer; + // transition: background 0.2s ease; + + // &:hover { + // background: darken(#EBF3FF, 5%); + // } + // } + // } + + &__loading { + width: 85%; + min-height: 50vh; + flex-direction: column; + justify-items: flex-start; + &-dots { + width: 30px; + background: #ffffff; + border-radius: 4px 4px 4px 4px; + display: flex; + align-items: center; + justify-content: center; + height: 40px; + font-size: 24px; + color: #666666; + } } &__input-area { + padding: 16px 24px; background: #ffffff; border-top: 1px solid #E5E5E5; + + @media (max-width: 768px) { + padding: 12px 16px; + } } &__input-wrapper { - position: relative; + display: flex; + border-top: 2px solid #707372; + // align-items: center; + height: 0px; + // position: relative; + // width: 100%; + // margin: 0 auto; } &__input { - width: 100%; - padding-left: 20px; - padding-right: 44px; // Space for the send button - border: 1px solid #E5E5E5; - font-size: 14px; + align-content: center; + width: 85%; + padding: 0 0 0 16px; + border: none; + outline: none; + font-size: 16px; line-height: 1.5; resize: none; - min-height: 44px; - max-height: 120px; - background: #F5F5F5; - - &:focus { - outline: none; - // border-color: #007AFF; - background: #ffffff; - } + height: 47px; + min-height: 47px; + max-height: 250px; + background: #FFFFFF; &::placeholder { color: #666666; @@ -121,37 +356,51 @@ } &__send-button { - position: absolute; - right: 0px; - height: 100%; - top: 50%; - transform: translateY(-50%); - background: #007AFF; + width: 15%; + height: 46px; + // position: absolute; + // position: relative; + // left: 90%; + // top: -23px; + // right: 0px; + // top: 50%; + // transform: translateY(-50%); + background: #3A77BC; color: #ffffff; border: none; - padding: 8px; - cursor: pointer; - transition: background 0.2s ease; + // width: 40px; + // height: 40px; + // display: flex; + // align-items: center; + // justify-content: center; + // cursor: pointer; + // transition: background 0.2s ease; &:hover { - background: darken(#007AFF, 10%); + background: darken(#3A77BC, 10%); } - } - &__controls { + svg { + width: 30px; + height: 40px; + } + } + &__chat { + // width: 50%; + overflow-y: auto; + margin: 0 auto; display: flex; - gap: 8px; - - button { - background: none; - border: none; - padding: 8px; - cursor: pointer; - color: #666666; + flex-direction: column; + align-items: center; + height: 435px; // or use: calc(100vh - [header+footer heights]) for more precise fit + // min-height: 400px; - &:hover { - color: #1A1A1A; - } + @media (max-width: 900px) { + width: 95%; + } + @media (max-width: 600px) { + width: 100%; + min-height: 300px; } } @@ -177,7 +426,59 @@ font-size: 1rem; } } - +&__messages { + display: flex; + flex-direction: column; + flex: 1 1 auto; + // overflow-y: auto; + width: 90%; + // padding-top: 16px; + // min-height: 0; // Required for flexbox scroll + // max-height: 100%; // Ensures it doesn't overflow the parent + + @media (max-width: 768px) { + padding: 16px; + } + } + &__disclaimer { + position: absolute; + bottom: 50px; + // margin: 16px; + // border-radius: 4px; + // overflow: hidden; + + // .vf-banner { + // margin: 0; + // padding: 12px; + // background-color: #E5F2FA; + // border: 1px solid #0066CC; + // border-radius: 4px; + + // &__content { + // display: flex; + // align-items: center; + // gap: 12px; + // } + + // &__text { + // margin: 0; + // color: #1A1A1A; + // font-size: 14px; + // line-height: 1.4; + // } + // } + + // width: 100%; + // display: flex; + // justify-content: flex-end; + // flex-direction: column; + // align-items: center; + // position: absolute; + // bottom: 0px; + // z-index: 1000; + // height: 75vh; + // padding-bottom: 12%; + } @media (max-width: 480px) { width: calc(100% - 40px); height: calc(100vh - 100px); @@ -224,7 +525,10 @@ // Message styles .vf-chatbot-message { - margin-bottom: 16px; + + @media (max-width: 768px) { + max-width: 90%; + } &--user { margin-left: auto; @@ -238,9 +542,9 @@ &--assistant { margin-right: auto; - display: flex; + display: grid; align-items: flex-start; - gap: 8px; + gap: 12px; .vf-chatbot-message__avatar { width: 24px; @@ -256,12 +560,75 @@ } &__content { - padding: 12px 16px; - font-size: 14px; + padding: 16px; + font-size: 16px; line-height: 1.5; } } +.vf-chatbot-standalone__welcome-logo img { + width: 64px; + height: 64px; + margin-bottom: 16px; + object-fit: contain; +} + +.vf-chatbot-message--user { + max-width: 85%; + + .vf-chatbot-message__avatar { + width: 100%; + display: flex; + align-items: center; + gap: 8px; + + .vf-chatbot-message__avatar-name { + font-size: 14px; + font-weight: 500; + color: #1A1A1A; + } + + .vf-chatbot-message__avatar img { + width: 24px; + height: 24px; + border-radius: 50%; + } + } +} + +.vf-chatbot-message--assistant { + margin-right: auto; + display: grid; + align-items: flex-start; + gap: 12px; + + .vf-chatbot-message__avatar { + width: 100%; + display: flex; + align-items: center; + gap: 8px; + + &-image { + display: flex; + justify-content: center; + align-items: center; + width: 24px; + height: 24px; + border: 1px solid #707372; + border-radius: 50%; + background-color: #FFFFFF; + img { + width: 16px; + height: 16px; + } + } + &-name { + font-size: 14px; + font-weight: 500; + color: #1A1A1A; + } + } + } // Suggestion area .vf-chatbot-suggestions { padding: 16px; @@ -309,12 +676,37 @@ vertical-align: middle; } -.vf-chatbot-message--assistant img.vf-chatbot-message__avatar { - width: 32px; - height: 32px; - border-radius: 50%; - background-color: #fff; - object-fit: contain; - padding: 0; - border: 1px solid #eee; -} +// .vf-chatbot-message--assistant img.vf-chatbot-message__avatar { +// width: 32px; +// height: 32px; +// border-radius: 50%; +// background-color: #fff; +// object-fit: contain; +// padding: 0; +// border: 1px solid #eee; +// } +.vf-chatbot-message--user { + display: grid; + align-items: flex-start; + gap: 12px; + + .vf-chatbot-message__avatar { + flex-direction: row; + justify-content: flex-end; + display: flex; + align-items: center; + gap: 8px; + + img { + width: 24px; + height: 24px; + border-radius: 50%; + } + + .vf-chatbot-message__avatar-name { + font-size: 14px; + font-weight: 500; + color: #1A1A1A; + } + } + } diff --git a/components/vf-chatbot-router/vf-chatbot-router.config.yml b/components/vf-chatbot-router/vf-chatbot-router.config.yml index aed32b629c..8948ea29e9 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.config.yml +++ b/components/vf-chatbot-router/vf-chatbot-router.config.yml @@ -6,8 +6,7 @@ context: component-type: element # Component configuration chatbotRoutes: - multiselect: false # Set to true for multi-selection mode - maxMultiSelect: 3 # Maximum items that can be selected in multiselect mode + multiSelect: false # Set to true for multi-selection mode showSearch: true # Show search box if items > 10 routes: - id: general @@ -27,10 +26,11 @@ context: title: Writing Assistant description: Helps with writing and content creation variants: - - name: multiselect + - name: multiSelect context: chatbotRoutes: - multiselect: true + multiSelect: true + maxMultiSelect: 3 # Maximum items that can be selected in multiSelect mode routes: - id: general title: General Assistant diff --git a/components/vf-chatbot-router/vf-chatbot-router.js b/components/vf-chatbot-router/vf-chatbot-router.js index 42a594964f..ddddb64067 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.js +++ b/components/vf-chatbot-router/vf-chatbot-router.js @@ -53,10 +53,18 @@ export class VFChatbotRouter { bindEvents() { // Toggle dropdown if (this.titleEl) { - this.titleEl.addEventListener("click", e => { - e.stopPropagation(); + // Remove any existing listeners first + this.titleEl.removeEventListener("click", this.toggleDropdownHandler); + + // Create a bound handler that we can reference later + this.toggleDropdownHandler = e => { + e.preventDefault(); // Prevent default behavior + e.stopImmediatePropagation(); // Stop multiple event triggers this.toggleDropdown(); - }); + }; + + // Add the new listener + this.titleEl.addEventListener("click", this.toggleDropdownHandler); } // Search functionality diff --git a/components/vf-chatbot-router/vf-chatbot-router.njk b/components/vf-chatbot-router/vf-chatbot-router.njk index 15c9076168..bda3018147 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.njk +++ b/components/vf-chatbot-router/vf-chatbot-router.njk @@ -1,6 +1,6 @@ -
    +
    - -
    - - {% if context.chatbotRoutes.showSearch and (context.chatbotRoutes.routes | length > context.chatbotRoutes.showSearchThreshold) %} - - {% endif %} - - {% if context.chatbotRoutes.multiSelect %} - {% set maxSelect = context.chatbotRoutes.maxMultiSelect | default(3) %} - -
    - Select up to {{ maxSelect }} services - Clear all -
    - {% endif %} - -
      - {% for route in context.chatbotRoutes.routes %} -
    • -
      -
      {{ route.title }}
      -
      {{ route.description }}
      -
      - -
    • - {% endfor %} -
    -
    -
    diff --git a/components/vf-chatbot-router/vf-chatbot-router.scss b/components/vf-chatbot-router/vf-chatbot-router.scss index 12a4ed8292..d6816673fd 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.scss +++ b/components/vf-chatbot-router/vf-chatbot-router.scss @@ -1,15 +1,15 @@ -// vf-chatbot-router +// vf-chatbot-selector @import 'package.variables.scss'; -.vf-chatbot-router { +.vf-chatbot-selector { position: relative; display: block; font-family: var(--vf-font-family); width: 100%; } -.vf-chatbot-router__title { +.vf-chatbot-selector__title { display: flex; justify-content: space-between; width: 100%; @@ -25,14 +25,14 @@ } &--expanded { - .vf-chatbot-router__chevron { + .vf-chatbot-selector__chevron { transform: rotate(180deg); } } } -.vf-chatbot-router__title img { +.vf-chatbot-selector__title img { position: relative; top: 10px; width: 24px; @@ -41,33 +41,33 @@ vertical-align: middle; } -.vf-chatbot-router__title-content { +.vf-chatbot-selector__title-content { display: flex; flex-direction: column; gap: 2px; } -.vf-chatbot-router__main-text { +.vf-chatbot-selector__main-text { font-weight: 500; font-size: 20px; line-height: 1.2; } -.vf-chatbot-router__title-text { +.vf-chatbot-selector__title-text { font-size: 14px; color: var(--vf-color--grey-dark); font-weight: 400; display: block; } -.vf-chatbot-router__chevron { +.vf-chatbot-selector__chevron { height: 25px; transition: transform 0.2s ease; margin-left: 8px; font-size: 16px; } -.vf-chatbot-router__dropdown { +.vf-chatbot-selector__dropdown { display: none; position: absolute; top: 100%; @@ -83,7 +83,7 @@ } } -.vf-chatbot-router__header { +.vf-chatbot-selector__header { display: flex; justify-content: space-between; align-items: center; @@ -92,7 +92,7 @@ font-size: 14px; } -.vf-chatbot-router__clear { +.vf-chatbot-selector__clear { color: var(--vf-color--grey--dark); text-decoration: none; pointer-events: none; @@ -105,7 +105,7 @@ } } -.vf-chatbot-router__search { +.vf-chatbot-selector__search { input { width: 94%; @@ -115,7 +115,7 @@ } } -.vf-chatbot-router__list { +.vf-chatbot-selector__list { max-height: 400px; overflow-y: auto; margin: 0; @@ -123,7 +123,7 @@ list-style: none; } -.vf-chatbot-router__item { +.vf-chatbot-selector__item { display: flex; align-items: flex-start; justify-content: space-between; @@ -138,29 +138,29 @@ &--selected { // background-color: var(--vf-color--grey--light); - .vf-chatbot-router__tick { + .vf-chatbot-selector__tick { opacity: 1; } } } -.vf-chatbot-router__item-content { +.vf-chatbot-selector__item-content { flex: 1; padding-right: 16px; } -.vf-chatbot-router__item-title { +.vf-chatbot-selector__item-title { font-weight: 500; margin-bottom: 4px; } -.vf-chatbot-router__item-description { +.vf-chatbot-selector__item-description { font-size: 14px; color: var(--vf-color--grey--dark); line-height: 1.4; } -.vf-chatbot-router__tick { +.vf-chatbot-selector__tick { opacity: 0; color: var(--vf-color--grey--dark); font-weight: bold; diff --git a/components/vf-chatbot-router/README.md b/components/vf-chatbot-selector/README.md similarity index 100% rename from components/vf-chatbot-router/README.md rename to components/vf-chatbot-selector/README.md diff --git a/components/vf-chatbot-router/package.json b/components/vf-chatbot-selector/package.json similarity index 55% rename from components/vf-chatbot-router/package.json rename to components/vf-chatbot-selector/package.json index 8366545b87..876d8cc9db 100644 --- a/components/vf-chatbot-router/package.json +++ b/components/vf-chatbot-selector/package.json @@ -1,13 +1,13 @@ { "version": "1.0.0", - "name": "@visual-framework/vf-chatbot-router", - "description": "Visual Framework Chatbot Router component", + "name": "@visual-framework/vf-chatbot-selector", + "description": "Visual Framework Chatbot Selector component", "homepage": "https://stable.visual-framework.dev/", "author": "VF", "license": "Apache 2.0", - "style": "vf-chatbot-router.css", + "style": "vf-chatbot-selector.css", "sass": "index.scss", - "main": "vf-chatbot-router.js", + "main": "vf-chatbot-selector.js", "dependencies": { "@visual-framework/vf-sass-config": "file:../vf-sass-config" } diff --git a/components/vf-chatbot-router/vf-chatbot-router.config.yml b/components/vf-chatbot-selector/vf-chatbot-selector.config.yml similarity index 96% rename from components/vf-chatbot-router/vf-chatbot-router.config.yml rename to components/vf-chatbot-selector/vf-chatbot-selector.config.yml index 8948ea29e9..80f70e8b43 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.config.yml +++ b/components/vf-chatbot-selector/vf-chatbot-selector.config.yml @@ -1,5 +1,5 @@ -title: Chatbot Router Component -label: Chatbot Router +title: Chatbot Selector Component +label: Chatbot Selector preview: '@preview--components' status: alpha context: diff --git a/components/vf-chatbot-router/vf-chatbot-router.js b/components/vf-chatbot-selector/vf-chatbot-selector.js similarity index 54% rename from components/vf-chatbot-router/vf-chatbot-router.js rename to components/vf-chatbot-selector/vf-chatbot-selector.js index 1f2b6a05f6..753a952c46 100644 --- a/components/vf-chatbot-router/vf-chatbot-router.js +++ b/components/vf-chatbot-selector/vf-chatbot-selector.js @@ -1,7 +1,7 @@ -export class VFChatbotRouter { +export class VFChatbotSelector { constructor(element) { if (!element) { - console.error("Router element is required"); + console.error("Selector element is required"); return; } @@ -12,6 +12,7 @@ export class VFChatbotRouter { 10 ); this.selectedItems = new Set(); + // this.allServicesSelected = true; // Track "All services" state this.init(); } @@ -21,11 +22,14 @@ export class VFChatbotRouter { if (!this.el) return; // Get DOM elements - this.titleEl = this.el.querySelector("[data-vf-js-router-toggle]"); - this.dropdownEl = this.el.querySelector("[data-vf-js-router-dropdown]"); - this.searchEl = this.el.querySelector("[data-vf-js-router-search]"); - this.clearEl = this.el.querySelector("[data-vf-js-router-clear]"); - this.listItems = this.el.querySelectorAll("[data-vf-js-router-item]"); + this.titleEl = this.el.querySelector("[data-vf-js-selector-toggle]"); + this.dropdownEl = this.el.querySelector("[data-vf-js-selector-dropdown]"); + this.searchEl = this.el.querySelector("[data-vf-js-selector-search]"); + this.clearEl = this.el.querySelector("[data-vf-js-selector-clear]"); + this.listItems = this.el.querySelectorAll("[data-vf-js-selector-item]"); + this.allServicesItem = this.el.querySelector( + '[data-route-id="all"]' + ); // "All services" item // Initialize dropdown as closed if (this.dropdownEl) { @@ -38,17 +42,24 @@ export class VFChatbotRouter { // Initialize selected items and update display let initSelection = false; this.listItems.forEach(item => { - if (item.classList.contains("vf-chatbot-router__item--selected")) { + if (item.classList.contains("vf-chatbot-selector__item--selected")) { this.selectedItems.add(item.getAttribute("data-route-id")); initSelection = true; } }); - // Update display after initial selection - if (initSelection) { - this.updateSelectionDisplay(); + // Initialize with "All services" if no selection + const hasSelectedItems = Array.from(this.listItems).some( + item => item !== this.allServicesItem && + item.classList.contains("vf-chatbot-selector__item--selected") + ); + + if (!hasSelectedItems) { + this.selectAllServices(); } + // Update display after initial selection + this.updateSelectionDisplay(); this.updateClearButton(); } @@ -118,22 +129,22 @@ export class VFChatbotRouter { openDropdown() { this.dropdownEl.style.display = "block"; - this.titleEl.classList.add("vf-chatbot-router__title--expanded"); + this.titleEl.classList.add("vf-chatbot-selector__title--expanded"); } closeDropdown() { this.dropdownEl.style.display = "none"; - this.titleEl.classList.remove("vf-chatbot-router__title--expanded"); + this.titleEl.classList.remove("vf-chatbot-selector__title--expanded"); } handleSearch(query) { const searchQuery = query.toLowerCase(); this.listItems.forEach(item => { const title = item - .querySelector(".vf-chatbot-router__item-title") + .querySelector(".vf-chatbot-selector__item-title") .textContent.toLowerCase(); const description = item - .querySelector(".vf-chatbot-router__item-description") + .querySelector(".vf-chatbot-selector__item-description") .textContent.toLowerCase(); const matches = title.includes(searchQuery) || description.includes(searchQuery); @@ -143,27 +154,47 @@ export class VFChatbotRouter { handleItemSelection(item) { const itemId = item.getAttribute("data-route-id"); + const isAllServices = itemId === 'all'; if (this.isMultiselect) { - if (this.selectedItems.has(itemId)) { - this.selectedItems.delete(itemId); - item.classList.remove("vf-chatbot-router__item--selected"); - } else if (this.selectedItems.size < this.maxMultiSelect) { - this.selectedItems.add(itemId); - item.classList.add("vf-chatbot-router__item--selected"); + if (isAllServices) { + // If "All services" is clicked, deselect everything else + this.selectAllServices(); + } else { + // If other service is clicked + if (this.selectedItems.has(itemId)) { + // Deselect the item + this.selectedItems.delete(itemId); + item.classList.remove("vf-chatbot-selector__item--selected"); + + // If nothing else is selected, select "All services" + if (this.selectedItems.size === 0) { + this.selectAllServices(); + } + } else { + // Select the item and deselect "All services" + if (this.allServicesSelected) { + this.allServicesItem?.classList.remove("vf-chatbot-selector__item--selected"); + this.allServicesSelected = false; + } + if (this.selectedItems.size < this.maxMultiSelect) { + this.selectedItems.add(itemId); + item.classList.add("vf-chatbot-selector__item--selected"); + } + } } } else { // Single select mode this.listItems.forEach(listItem => { - listItem.classList.remove("vf-chatbot-router__item--selected"); + listItem.classList.remove("vf-chatbot-selector__item--selected"); }); this.selectedItems.clear(); this.selectedItems.add(itemId); - item.classList.add("vf-chatbot-router__item--selected"); + item.classList.add("vf-chatbot-selector__item--selected"); // Update title text immediately - const title = item.querySelector(".vf-chatbot-router__item-title").textContent; - const titleText = this.el.querySelector(".vf-chatbot-router__title-text"); + const title = item.querySelector(".vf-chatbot-selector__item-title").textContent; + const titleText = this.el.querySelector(".vf-chatbot-selector__title-text"); if (titleText) { titleText.textContent = title; } @@ -173,44 +204,45 @@ export class VFChatbotRouter { this.updateSelectionDisplay(); this.updateClearButton(); - - // Dispatch custom event - this.el.dispatchEvent( - new CustomEvent("routeselection", { - detail: { - selectedItems: Array.from(this.selectedItems), - isMultiselect: this.isMultiselect - } - }) - ); + this.dispatchSelectionEvent(); } - clearAllSelections() { + selectAllServices() { + // Clear all selections this.selectedItems.clear(); this.listItems.forEach(item => { - item.classList.remove("vf-chatbot-router__item--selected"); + item.classList.remove("vf-chatbot-selector__item--selected"); }); + + // Select "All services" + this.allServicesSelected = true; + this.allServicesItem?.classList.add("vf-chatbot-selector__item--selected"); + } + + clearAllSelections() { + // Clear everything and select "All services" + this.selectAllServices(); this.updateSelectionDisplay(); this.updateClearButton(); + this.dispatchSelectionEvent(); } updateSelectionDisplay() { - const titleText = this.el.querySelector(".vf-chatbot-router__title-text"); + const titleText = this.el.querySelector(".vf-chatbot-selector__title-text"); if (!titleText) return; - if (this.selectedItems.size === 0) { + if (this.allServicesSelected) { + titleText.textContent = "All services"; + } else if (this.selectedItems.size === 0) { titleText.textContent = "Select services"; - return; - } - - if (!this.isMultiselect) { + } else if (!this.isMultiselect) { const selectedId = Array.from(this.selectedItems)[0]; const selectedItem = this.el.querySelector( `[data-route-id="${selectedId}"]` ); if (selectedItem) { const title = selectedItem.querySelector( - ".vf-chatbot-router__item-title" + ".vf-chatbot-selector__item-title" ).textContent; titleText.textContent = title; } @@ -219,18 +251,32 @@ export class VFChatbotRouter { } } + dispatchSelectionEvent() { + this.el.dispatchEvent( + new CustomEvent("routeselection", { + detail: { + selectedItems: this.allServicesSelected + ? ['all'] + : Array.from(this.selectedItems), + isMultiselect: this.isMultiselect, + isAllServices: this.allServicesSelected + } + }) + ); + } + updateClearButton() { if (this.clearEl) { if (this.selectedItems.size > 0) { - this.clearEl.classList.add("vf-chatbot-router__clear--active"); + this.clearEl.classList.add("vf-chatbot-selector__clear--active"); } else { - this.clearEl.classList.remove("vf-chatbot-router__clear--active"); + this.clearEl.classList.remove("vf-chatbot-selector__clear--active"); } } } } // Function to initialize the component -export function initVFChatbotRouter(element) { - return new VFChatbotRouter(element); +export function initVFChatbotSelector(element) { + return new VFChatbotSelector(element); } diff --git a/components/vf-chatbot-selector/vf-chatbot-selector.njk b/components/vf-chatbot-selector/vf-chatbot-selector.njk new file mode 100644 index 0000000000..f2b0fe7ef7 --- /dev/null +++ b/components/vf-chatbot-selector/vf-chatbot-selector.njk @@ -0,0 +1,54 @@ +
    + + +
    + + {% if context.chatbotRoutes.showSearch and (context.chatbotRoutes.routes | length > context.chatbotRoutes.showSearchThreshold) %} + + {% endif %} + + {% if context.chatbotRoutes.multiSelect %} + {% set maxSelect = context.chatbotRoutes.maxMultiSelect | default(3) %} + +
    + Select up to {{ maxSelect }} services + Clear all +
    + {% endif %} + +
      + + {% if context.chatbotRoutes.showAllServices %} +
    • +
      +
      All services
      +
      This would select all services
      +
      + +
    • + {% endif %} + {% for route in context.chatbotRoutes.routes %} +
    • +
      +
      {{ route.title }}
      +
      {{ route.description }}
      +
      + +
    • + {% endfor %} +
    +
    +
    diff --git a/components/vf-chatbot-selector/vf-chatbot-selector.scss b/components/vf-chatbot-selector/vf-chatbot-selector.scss new file mode 100644 index 0000000000..d6816673fd --- /dev/null +++ b/components/vf-chatbot-selector/vf-chatbot-selector.scss @@ -0,0 +1,168 @@ +// vf-chatbot-selector + +@import 'package.variables.scss'; + +.vf-chatbot-selector { + position: relative; + display: block; + font-family: var(--vf-font-family); + width: 100%; +} + +.vf-chatbot-selector__title { + display: flex; + justify-content: space-between; + width: 100%; + padding: 0px; + background: none; + border: none; + cursor: pointer; + color: var(--vf-text-color); + text-align: left; + + &:hover { + // background-color: var(--vf-color--grey--lightest); + } + + &--expanded { + .vf-chatbot-selector__chevron { + transform: rotate(180deg); + } + } +} + + +.vf-chatbot-selector__title img { + position: relative; + top: 10px; + width: 24px; + height: 24px; + margin-right: 8px; + vertical-align: middle; +} + +.vf-chatbot-selector__title-content { + display: flex; + flex-direction: column; + gap: 2px; +} + +.vf-chatbot-selector__main-text { + font-weight: 500; + font-size: 20px; + line-height: 1.2; +} + +.vf-chatbot-selector__title-text { + font-size: 14px; + color: var(--vf-color--grey-dark); + font-weight: 400; + display: block; +} + +.vf-chatbot-selector__chevron { + height: 25px; + transition: transform 0.2s ease; + margin-left: 8px; + font-size: 16px; +} + +.vf-chatbot-selector__dropdown { + display: none; + position: absolute; + top: 100%; + left: 0; + min-width: 300px; + max-width: 400px; + background: var(--vf-color--neutral--0); + box-shadow: 0 4px 6px var(--vf-color--grey--light); + margin-top: 4px; + + &--expanded { + display: block; + } +} + +.vf-chatbot-selector__header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 12px 16px; + border-bottom: 1px solid var(--vf-color--grey--light); + font-size: 14px; +} + +.vf-chatbot-selector__clear { + color: var(--vf-color--grey--dark); + text-decoration: none; + pointer-events: none; + opacity: 0.5; + + &--active { + color: $vf-link--color; + pointer-events: auto; + opacity: 1; + } +} + +.vf-chatbot-selector__search { + + input { + width: 94%; + padding: 8px 0px 8px 16px; + border: 1px solid #333; + font-size: 14px; + } +} + +.vf-chatbot-selector__list { + max-height: 400px; + overflow-y: auto; + margin: 0; + padding: 8px 0; + list-style: none; +} + +.vf-chatbot-selector__item { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 12px 16px; + cursor: pointer; + transition: background-color 0.2s ease; + + &:hover { + // background-color: var(--vf-color--grey--lightest); + } + + &--selected { + // background-color: var(--vf-color--grey--light); + + .vf-chatbot-selector__tick { + opacity: 1; + } + } +} + +.vf-chatbot-selector__item-content { + flex: 1; + padding-right: 16px; +} + +.vf-chatbot-selector__item-title { + font-weight: 500; + margin-bottom: 4px; +} + +.vf-chatbot-selector__item-description { + font-size: 14px; + color: var(--vf-color--grey--dark); + line-height: 1.4; +} + +.vf-chatbot-selector__tick { + opacity: 0; + color: var(--vf-color--grey--dark); + font-weight: bold; + transition: opacity 0.2s ease; +} diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.js b/components/vf-chatbot-standalone/vf-chatbot-standalone.js index 0368048971..f98cf0e22e 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.js +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.js @@ -1,7 +1,7 @@ // vf-chatbot-standalone.js import { initVFChatbotSources } from "../vf-chatbot-sources/vf-chatbot-sources"; import { VFChatbotFeedback } from "../vf-chatbot-feedback/vf-chatbot-feedback.js"; -import { initVFChatbotRouter } from "../vf-chatbot-router/vf-chatbot-router.js"; +import { initVFChatbotSelector } from "../vf-chatbot-selector/vf-chatbot-selector.js"; import { VFChatbotActionPrompt } from "../vf-chatbot-action-prompt/vf-chatbot-action-prompt.js"; class VFChatbotStandalone { @@ -44,8 +44,8 @@ class VFChatbotStandalone { ".vf-button--dismiss" ); - // Router element - this.routerEl = this.container.querySelector("[data-vf-js-chatbot-router]"); + // Selector element + this.selectorEl = this.container.querySelector("[data-vf-js-chatbot-selector]"); // API configuration - Mistral AI this.API_TOKEN = ""; @@ -85,9 +85,9 @@ class VFChatbotStandalone { // Populate suggestions grid if (this.suggestionsGrid) { randomQuestions.forEach((question, index) => { - const isLastAndOdd = index === 2 && randomQuestions.length === 3; + // const isLastAndOdd = index === 2 && randomQuestions.length === 3; const promptHtml = ` -
    { + // Initialize selector if present + if (this.selectorEl) { + const selector = initVFChatbotSelector(this.selectorEl); + this.selectorEl.addEventListener("routeselection", e => { this.handleRouteSelection(e.detail); }); // Set initial route selection based on variant - if (this.routerEl.dataset.variant) { - const variantRoutes = this.routerEl.querySelectorAll( - "[data-vf-js-router-item]" + if (this.selectorEl.dataset.variant) { + const variantRoutes = this.selectorEl.querySelectorAll( + "[data-vf-js-selector-item]" ); variantRoutes.forEach(item => { - if (item.dataset.routeId === this.routerEl.dataset.variant) { - router.handleItemSelection(item); + if (item.dataset.routeId === this.selectorEl.dataset.variant) { + selector.handleItemSelection(item); } }); } @@ -151,15 +151,15 @@ class VFChatbotStandalone { this.messagesContainer.style.display = "flex"; // Initialize input and bind events - if (this.input) { - // Bind input events - this.input.addEventListener("keypress", (e) => { - if (e.key === "Enter" && !e.shiftKey) { - e.preventDefault(); - this.sendMessage(); - } - }); - } + // if (this.input) { + // // Bind input events + // this.input.addEventListener("keypress", (e) => { + // if (e.key === "Enter" && !e.shiftKey) { + // e.preventDefault(); + // this.sendMessage(); + // } + // }); + // } if (this.sendBtn) { this.sendBtn.addEventListener("click", () => this.sendMessage()); @@ -186,12 +186,12 @@ class VFChatbotStandalone { // Send message events this.sendBtn?.addEventListener("click", () => this.sendMessage()); - this.input?.addEventListener("keypress", e => { - if (e.key === "Enter" && !e.shiftKey) { - e.preventDefault(); - this.sendMessage(); - } - }); + // this.input?.addEventListener("keypress", e => { + // if (e.key === "Enter" && !e.shiftKey) { + // e.preventDefault(); + // this.sendMessage(); + // } + // }); // Welcome screen input events this.welcomeSendBtn?.addEventListener("click", () => @@ -352,7 +352,7 @@ class VFChatbotStandalone { const fallbackResponse = this.fallbackResponses[ Math.floor(Math.random() * this.fallbackResponses.length) ]; - this.addAssistantResponse(fallbackResponse); + this.addAssistantResponse(fallbackResponse["answer"],[], fallbackResponse["prompts"] || []); this.setLoadingState(false); return; diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk index abfbe5658e..25fa38ff8d 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk @@ -132,6 +132,8 @@ multiSelect: true, maxMultiSelect: 3, showSearch: true, + showAllServices: true, + showAllServicesSelected: true, showSearchThreshold: 5, routes: [ { @@ -200,9 +202,9 @@ } } %} -{# {% set routerContext = llm_selector %} #} -{# {% set routerContext = services_single_selector %} #} -{% set routerContext = services_multi_selector %} +{# {% set selectorContext = llm_selector %} #} +{# {% set selectorContext = services_single_selector %} #} +{% set selectorContext = services_multi_selector %}
    @@ -211,7 +213,7 @@ {#
    #} {# AI Assistant #} - {% render "@vf-chatbot-router", routerContext %} + {% render "@vf-chatbot-selector", selectorContext %} {#
    #}
    diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss index b8623fd380..5353f4962f 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss @@ -1,7 +1,7 @@ // vf-chatbot-standalone.scss @import '../vf-banner/vf-banner.scss'; @import '../vf-chatbot-sources/vf-chatbot-sources.scss'; -@import '../vf-chatbot-router/vf-chatbot-router.scss'; +@import '../vf-chatbot-selector/vf-chatbot-selector.scss'; .vf-chatbot-standalone { display: flex; @@ -78,6 +78,7 @@ // background: #F5F5F5; // justify-content: center; border-radius: 4px 4px 4px 4px; + height: 85vh; } // Welcome screen styles @@ -119,7 +120,7 @@ font-size: 16px; line-height: 1.5; color: #666666; - height: 25vh; + height: 20vh; max-width: 450px; } @@ -137,18 +138,18 @@ &-grid { display: grid; grid-template-columns: 1fr 1fr; - justify-items: center; // Center items horizontally + justify-items: left; // Center items horizontally gap: 8px; // Make the last item span full width if it's the 3rd item - & > *:nth-child(3):last-child { - grid-column: 1 / -1; - justify-self: center; // Center the full-width item - } + // & > *:nth-child(3):last-child { + // grid-column: 1 / -1; + // justify-self: center; // Center the full-width item + // } // Ensure each grid cell only takes the width it needs & > * { - width: auto; + width: 100%; min-width: min-content; } @media (max-width: 480px) { @@ -369,7 +370,7 @@ bottom: 0px; z-index: 1000; // height: 97vh; - padding-bottom: 5%; + padding-bottom: 4%; .vf-banner { width: 50%; diff --git a/components/vf-chatbot/assets/vf-chatbot-qa.json b/components/vf-chatbot/assets/vf-chatbot-qa.json index 79b0658a63..c48e99e7a2 100644 --- a/components/vf-chatbot/assets/vf-chatbot-qa.json +++ b/components/vf-chatbot/assets/vf-chatbot-qa.json @@ -29,16 +29,6 @@ "url": "https://www.ebi.ac.uk/training/online/courses/toolsuite/", "description": "Learn how to use EMBL-EBI tools effectively with our detailed guides and tutorials." } - ], - "prompts": [ - { - "action_text": "Contact our tools support team", - "action_url": "tel:+44 1223 494 444" - }, - { - "action_text": "Submit a support request", - "action_url": "https://www.ebi.ac.uk/about/contact/support/" - } ] }, "What is UniProt and how can I use it?": { @@ -95,16 +85,6 @@ "url": "https://www.ebi.ac.uk/training/online/courses/chembl-quick-tour/", "description": "Get started with ChEMBL through our interactive tutorial." } - ], - "prompts": [ - { - "action_text": "Contact ChEMBL team", - "action_url": "tel:+44 1223 494 444" - }, - { - "action_text": "Submit ChEMBL help request", - "action_url": "https://www.ebi.ac.uk/about/contact/support/" - } ] }, "How do I perform a BLAST search?": { @@ -166,9 +146,37 @@ } }, "fallbackResponses": [ - "I'm sorry, I'm having trouble connecting to my knowledge base right now. Could you try again in a moment?", - "That's an interesting question. Let me think about how to best answer that for you.", - "Thank you for your question. We offer various workshops and online courses on that topic. Would you like me to provide more specific information?", - "I'd be happy to help with that. Can you please elaborate a bit more on it?" + { + "answer": "I'm sorry, I'm having trouble connecting to my knowledge base right now. Could you try again in a moment?", + "prompts": [ + { + "action_text": "Contact our tools support team", + "action_url": "tel:+44 1223 494 444" + }, + { + "action_text": "Submit a support request", + "action_url": "https://www.ebi.ac.uk/about/contact/support/" + } + ] + }, + { + "answer": "That's an interesting question. Let me think about how to best answer that for you." + }, + { + "answer": "Thank you for your question. We offer various workshops and online courses on that topic. Would you like me to provide more specific information?", + "prompts": [ + { + "action_text": "Contact our tools support team", + "action_url": "tel:+44 1223 494 444" + }, + { + "action_text": "Submit a support request", + "action_url": "https://www.ebi.ac.uk/about/contact/support/" + } + ] + }, + { + "answer": "I'd be happy to help with that. Can you please elaborate a bit more on it?" + } ] } diff --git a/components/vf-componenet-rollup/index.scss b/components/vf-componenet-rollup/index.scss index 559359eea5..c91623b0d8 100755 --- a/components/vf-componenet-rollup/index.scss +++ b/components/vf-componenet-rollup/index.scss @@ -152,7 +152,7 @@ button { @import 'vf-chatbot-standalone/vf-chatbot-standalone.scss'; @import 'vf-chatbot-welcome/vf-chatbot-welcome.scss'; @import 'vf-chatbot-feedback/vf-chatbot-feedback.scss'; -@import 'vf-chatbot-router/vf-chatbot-router.scss'; +@import 'vf-chatbot-selector/vf-chatbot-selector.scss'; /* All Visual Framework Boilerplates */ diff --git a/components/vf-componenet-rollup/scripts.js b/components/vf-componenet-rollup/scripts.js index ccc1aa80cc..b6c555f997 100644 --- a/components/vf-componenet-rollup/scripts.js +++ b/components/vf-componenet-rollup/scripts.js @@ -81,7 +81,7 @@ import { initVFChatbotFab } from 'vf-chatbot-fab/vf-chatbot-fab.js'; import { initVFChatbotWelcome } from 'vf-chatbot-welcome/vf-chatbot-welcome.js'; import { initVFChatbotPrompt } from 'vf-chatbot-prompt/vf-chatbot-prompt.js'; import { VFChatbotFeedback } from 'vf-chatbot-feedback/vf-chatbot-feedback.js'; -import { initVFChatbotRouter } from 'vf-chatbot-router/vf-chatbot-router.js'; +import { initVFChatbotSelector } from 'vf-chatbot-selector/vf-chatbot-selector.js'; // Initialize all chatbot components when DOM is loaded // Initialize all chatbot components once when the DOM is loaded document.addEventListener("DOMContentLoaded", () => { @@ -91,9 +91,9 @@ document.addEventListener("DOMContentLoaded", () => { initVFChatbotFab(); initVFChatbotWelcome(); initVFChatbotPrompt(); - const routerEl = document.querySelector('[data-vf-js-chatbot-router]'); - if (routerEl) { - initVFChatbotRouter(routerEl); + const selectorEl = document.querySelector('[data-vf-js-chatbot-selector]'); + if (selectorEl) { + initVFChatbotSelector(selectorEl); } }); From 488d0376bf8d033af8acecbc1ec9c997fc7c6408 Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Mon, 16 Jun 2025 00:14:08 +0100 Subject: [PATCH 12/71] VF Chatbot : Changes from internal demo feedback --- .../vf-chatbot-action-prompt.scss | 7 +- .../vf-chatbot-feedback.scss | 3 +- .../vf-chatbot-modal/vf-chatbot-modal.js | 2 +- .../vf-chatbot-modal/vf-chatbot-modal.njk | 10 +- .../vf-chatbot-modal/vf-chatbot-modal.scss | 22 +-- .../vf-chatbot-router/vf-chatbot-router.scss | 168 ------------------ .../vf-chatbot-selector.js | 24 +-- .../vf-chatbot-selector.njk | 2 +- .../vf-chatbot-selector.scss | 16 +- .../vf-chatbot-standalone.js | 2 +- .../vf-chatbot-standalone.njk | 82 +++++---- .../vf-chatbot-standalone.scss | 15 +- .../vf-chatbot-welcome/vf-chatbot-welcome.njk | 2 +- .../vf-chatbot--icon-16x16-dark-green.svg | 4 + .../vf-chatbot--icon-24x24-dark-green.svg | 4 + .../vf-chatbot--icon-32x32-dark-green.svg | 4 + .../vf-chatbot--icon-64x64-dark-green.svg | 11 ++ components/vf-chatbot/vf-chatbot.njk | 2 +- .../src/site/chatbot/index.njk | 21 ++- 19 files changed, 150 insertions(+), 251 deletions(-) delete mode 100644 components/vf-chatbot-router/vf-chatbot-router.scss create mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg create mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-24x24-dark-green.svg create mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-32x32-dark-green.svg create mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-64x64-dark-green.svg diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss index 111eb3c7f7..5d537bdf75 100644 --- a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss @@ -2,6 +2,7 @@ display: inline-block; &__link { + border-radius: 4px; display: inline-block; padding: 10px 10px; border: 1px solid #4b7fd1; // Thin blue border @@ -31,7 +32,7 @@ } @media (max-width:$vf-breakpoint--md) { - white-space: nowrap; + width: auto; } } @@ -60,4 +61,8 @@ // white-space: normal; // Allow text wrapping for full-width // } } + + @media (max-width:$vf-breakpoint--md) { + display: contents; + } } diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.scss b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss index 3a127f1a5b..9b31fdf18a 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.scss +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss @@ -73,9 +73,10 @@ padding: 10px; background-color: #ffffff; color: #3B6FB6; - border-radius: 0px; + border-radius: 4px; border: 1px solid #224B9A; min-width: fit-content; + cursor: pointer; // flex: 1 1 150px; &--selected { diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.js b/components/vf-chatbot-modal/vf-chatbot-modal.js index 7335ed82ac..4520cdcc69 100644 --- a/components/vf-chatbot-modal/vf-chatbot-modal.js +++ b/components/vf-chatbot-modal/vf-chatbot-modal.js @@ -555,7 +555,7 @@ class VFChatbotModal { assistantMessageEl.innerHTML = `
    - AI Assistant + AI Assistant
    AI Assistant
    diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.njk b/components/vf-chatbot-modal/vf-chatbot-modal.njk index 3e1259c5e0..850b27e495 100644 --- a/components/vf-chatbot-modal/vf-chatbot-modal.njk +++ b/components/vf-chatbot-modal/vf-chatbot-modal.njk @@ -206,7 +206,7 @@
    -
    + {#
    #}
    {% render "@vf-chatbot-selector", selectorContext %} @@ -242,7 +242,7 @@

    {{ welcome_title | default('AI assistant') }}

    @@ -275,7 +275,7 @@

    - AI Assistant + AI Assistant
    AI Assistant
    @@ -287,6 +287,7 @@
    +
    {% if disclaimer %}
    @@ -329,6 +330,5 @@
    -
    -
    + {#
    #}
    diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.scss b/components/vf-chatbot-modal/vf-chatbot-modal.scss index 80bbb3f9a7..a9c3231800 100644 --- a/components/vf-chatbot-modal/vf-chatbot-modal.scss +++ b/components/vf-chatbot-modal/vf-chatbot-modal.scss @@ -42,16 +42,16 @@ } } - &__container { - display: flex; - flex-direction: column; - // height: 470px; - background: #ffffff; - - @media (max-width: 1200px) { - max-width: 100%; - } - } + // &__container { + // display: flex; + // flex-direction: column; + // // height: 470px; + // background: #ffffff; + + // @media (max-width: 1200px) { + // max-width: 100%; + // } + // } &__header { height: 45px; @@ -370,7 +370,7 @@ resize: none; height: 47px; min-height: 47px; - max-height: 250px; + max-height: 125px; background: #FFFFFF; &::placeholder { diff --git a/components/vf-chatbot-router/vf-chatbot-router.scss b/components/vf-chatbot-router/vf-chatbot-router.scss deleted file mode 100644 index d6816673fd..0000000000 --- a/components/vf-chatbot-router/vf-chatbot-router.scss +++ /dev/null @@ -1,168 +0,0 @@ -// vf-chatbot-selector - -@import 'package.variables.scss'; - -.vf-chatbot-selector { - position: relative; - display: block; - font-family: var(--vf-font-family); - width: 100%; -} - -.vf-chatbot-selector__title { - display: flex; - justify-content: space-between; - width: 100%; - padding: 0px; - background: none; - border: none; - cursor: pointer; - color: var(--vf-text-color); - text-align: left; - - &:hover { - // background-color: var(--vf-color--grey--lightest); - } - - &--expanded { - .vf-chatbot-selector__chevron { - transform: rotate(180deg); - } - } -} - - -.vf-chatbot-selector__title img { - position: relative; - top: 10px; - width: 24px; - height: 24px; - margin-right: 8px; - vertical-align: middle; -} - -.vf-chatbot-selector__title-content { - display: flex; - flex-direction: column; - gap: 2px; -} - -.vf-chatbot-selector__main-text { - font-weight: 500; - font-size: 20px; - line-height: 1.2; -} - -.vf-chatbot-selector__title-text { - font-size: 14px; - color: var(--vf-color--grey-dark); - font-weight: 400; - display: block; -} - -.vf-chatbot-selector__chevron { - height: 25px; - transition: transform 0.2s ease; - margin-left: 8px; - font-size: 16px; -} - -.vf-chatbot-selector__dropdown { - display: none; - position: absolute; - top: 100%; - left: 0; - min-width: 300px; - max-width: 400px; - background: var(--vf-color--neutral--0); - box-shadow: 0 4px 6px var(--vf-color--grey--light); - margin-top: 4px; - - &--expanded { - display: block; - } -} - -.vf-chatbot-selector__header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 12px 16px; - border-bottom: 1px solid var(--vf-color--grey--light); - font-size: 14px; -} - -.vf-chatbot-selector__clear { - color: var(--vf-color--grey--dark); - text-decoration: none; - pointer-events: none; - opacity: 0.5; - - &--active { - color: $vf-link--color; - pointer-events: auto; - opacity: 1; - } -} - -.vf-chatbot-selector__search { - - input { - width: 94%; - padding: 8px 0px 8px 16px; - border: 1px solid #333; - font-size: 14px; - } -} - -.vf-chatbot-selector__list { - max-height: 400px; - overflow-y: auto; - margin: 0; - padding: 8px 0; - list-style: none; -} - -.vf-chatbot-selector__item { - display: flex; - align-items: flex-start; - justify-content: space-between; - padding: 12px 16px; - cursor: pointer; - transition: background-color 0.2s ease; - - &:hover { - // background-color: var(--vf-color--grey--lightest); - } - - &--selected { - // background-color: var(--vf-color--grey--light); - - .vf-chatbot-selector__tick { - opacity: 1; - } - } -} - -.vf-chatbot-selector__item-content { - flex: 1; - padding-right: 16px; -} - -.vf-chatbot-selector__item-title { - font-weight: 500; - margin-bottom: 4px; -} - -.vf-chatbot-selector__item-description { - font-size: 14px; - color: var(--vf-color--grey--dark); - line-height: 1.4; -} - -.vf-chatbot-selector__tick { - opacity: 0; - color: var(--vf-color--grey--dark); - font-weight: bold; - transition: opacity 0.2s ease; -} diff --git a/components/vf-chatbot-selector/vf-chatbot-selector.js b/components/vf-chatbot-selector/vf-chatbot-selector.js index 753a952c46..b797a6c2dd 100644 --- a/components/vf-chatbot-selector/vf-chatbot-selector.js +++ b/components/vf-chatbot-selector/vf-chatbot-selector.js @@ -27,9 +27,7 @@ export class VFChatbotSelector { this.searchEl = this.el.querySelector("[data-vf-js-selector-search]"); this.clearEl = this.el.querySelector("[data-vf-js-selector-clear]"); this.listItems = this.el.querySelectorAll("[data-vf-js-selector-item]"); - this.allServicesItem = this.el.querySelector( - '[data-route-id="all"]' - ); // "All services" item + this.allServicesItem = this.el.querySelector('[data-route-id="all"]'); // "All services" item // Initialize dropdown as closed if (this.dropdownEl) { @@ -50,8 +48,9 @@ export class VFChatbotSelector { // Initialize with "All services" if no selection const hasSelectedItems = Array.from(this.listItems).some( - item => item !== this.allServicesItem && - item.classList.contains("vf-chatbot-selector__item--selected") + item => + item !== this.allServicesItem && + item.classList.contains("vf-chatbot-selector__item--selected") ); if (!hasSelectedItems) { @@ -154,7 +153,7 @@ export class VFChatbotSelector { handleItemSelection(item) { const itemId = item.getAttribute("data-route-id"); - const isAllServices = itemId === 'all'; + const isAllServices = itemId === "all"; if (this.isMultiselect) { if (isAllServices) { @@ -174,7 +173,9 @@ export class VFChatbotSelector { } else { // Select the item and deselect "All services" if (this.allServicesSelected) { - this.allServicesItem?.classList.remove("vf-chatbot-selector__item--selected"); + this.allServicesItem?.classList.remove( + "vf-chatbot-selector__item--selected" + ); this.allServicesSelected = false; } if (this.selectedItems.size < this.maxMultiSelect) { @@ -193,8 +194,11 @@ export class VFChatbotSelector { item.classList.add("vf-chatbot-selector__item--selected"); // Update title text immediately - const title = item.querySelector(".vf-chatbot-selector__item-title").textContent; - const titleText = this.el.querySelector(".vf-chatbot-selector__title-text"); + const title = item.querySelector(".vf-chatbot-selector__item-title") + .textContent; + const titleText = this.el.querySelector( + ".vf-chatbot-selector__title-text" + ); if (titleText) { titleText.textContent = title; } @@ -256,7 +260,7 @@ export class VFChatbotSelector { new CustomEvent("routeselection", { detail: { selectedItems: this.allServicesSelected - ? ['all'] + ? ["all"] : Array.from(this.selectedItems), isMultiselect: this.isMultiselect, isAllServices: this.allServicesSelected diff --git a/components/vf-chatbot-selector/vf-chatbot-selector.njk b/components/vf-chatbot-selector/vf-chatbot-selector.njk index f2b0fe7ef7..d5120d784b 100644 --- a/components/vf-chatbot-selector/vf-chatbot-selector.njk +++ b/components/vf-chatbot-selector/vf-chatbot-selector.njk @@ -1,6 +1,6 @@
    -
    + + {#
    #} +
    + {% if disclaimer %} +
    +
    +
    +

    {{ disclaimer }}

    +
    - {% endif %} - {#
    #} -
    - -
    - {#
    #} + {% endif %} + {#
    #} +
    + +
    -
    + {#
    #}
    diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss index 5353f4962f..0c0be6bf8e 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss @@ -6,7 +6,7 @@ .vf-chatbot-standalone { display: flex; flex-direction: column; - margin: auto 15px; + margin: 16px 36px !important; &__container { display: flex; @@ -20,7 +20,7 @@ } &__header { - height: 64px; + // height: 64px; background: #ffffff; color: #000000; display: flex; @@ -78,7 +78,7 @@ // background: #F5F5F5; // justify-content: center; border-radius: 4px 4px 4px 4px; - height: 85vh; + // height: 85vh; } // Welcome screen styles @@ -233,7 +233,7 @@ } &__loading { - min-height: 50vh; + // min-height: 50vh; flex-direction: column; justify-items: flex-start; &-dots { @@ -266,6 +266,11 @@ position: relative; width: 50%; margin: 0 auto; + + + @media (max-width:$vf-breakpoint--md) { + width: 100%; + } } &__input { @@ -277,7 +282,7 @@ line-height: 1.5; resize: none; min-height: 40px; - max-height: 150px; + max-height: 125px; background: #FFFFFF; &::placeholder { diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.njk b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk index c15cfc958d..d4079dee5c 100644 --- a/components/vf-chatbot-welcome/vf-chatbot-welcome.njk +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk @@ -1,6 +1,6 @@
    - AI Assistant + AI Assistant

    {{ welcome_title | default('AI Assistant') }}

    diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg b/components/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg new file mode 100644 index 0000000000..1bd078f189 --- /dev/null +++ b/components/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-24x24-dark-green.svg b/components/vf-chatbot/assets/vf-chatbot--icon-24x24-dark-green.svg new file mode 100644 index 0000000000..0bb0697c2c --- /dev/null +++ b/components/vf-chatbot/assets/vf-chatbot--icon-24x24-dark-green.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-32x32-dark-green.svg b/components/vf-chatbot/assets/vf-chatbot--icon-32x32-dark-green.svg new file mode 100644 index 0000000000..6388d34c09 --- /dev/null +++ b/components/vf-chatbot/assets/vf-chatbot--icon-32x32-dark-green.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-64x64-dark-green.svg b/components/vf-chatbot/assets/vf-chatbot--icon-64x64-dark-green.svg new file mode 100644 index 0000000000..ddfe3b11a5 --- /dev/null +++ b/components/vf-chatbot/assets/vf-chatbot--icon-64x64-dark-green.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/components/vf-chatbot/vf-chatbot.njk b/components/vf-chatbot/vf-chatbot.njk index 45bc81cabe..5a07d53c75 100644 --- a/components/vf-chatbot/vf-chatbot.njk +++ b/components/vf-chatbot/vf-chatbot.njk @@ -10,7 +10,7 @@ welcome_message: welcome_message | default("Hello! How can I help you today?"), input_placeholder: input_placeholder | default("Type your message..."), show_settings: show_settings | default(true), - ai_icon: "/assets/vf-chatbot/assets/vf-chatbot--icon-large.svg", + ai_icon: "/assets/vf-chatbot/assets/vf-chatbot--icon-64x64-dark-green.svg", disclaimer: 'Disclaimer: This chatbot is designed to assist you with general information and basic inquiries. See our
    disclaimer notes.' } %} {# {% render '@vf-chatbot-modal', { diff --git a/tools/vf-component-library/src/site/chatbot/index.njk b/tools/vf-component-library/src/site/chatbot/index.njk index 2b92442978..0da658e9a9 100644 --- a/tools/vf-component-library/src/site/chatbot/index.njk +++ b/tools/vf-component-library/src/site/chatbot/index.njk @@ -35,6 +35,23 @@ + +
    +
    +

    AI Assistant

    + +

    +
    +
    {% render '@vf-chatbot-standalone', { title: "AI Assistant", welcome_title: "AI assistant", @@ -43,8 +60,8 @@ input_placeholder: "Ask me about Bioinformatics trainings...", show_suggestions: true, show_close_button: true, - ai_icon: "../../assets/vf-chatbot/assets/vf-chatbot--icon-x-small.svg", - welcome_logo: "../../assets/vf-chatbot/assets/vf-chatbot--icon-large.svg", + ai_icon: "../../assets/vf-chatbot/assets/vf-chatbot--icon-16x16-dark-green.svg", + welcome_logo: "../../assets/vf-chatbot/assets/vf-chatbot--icon-64x64-dark-green.svg", welcome_suggestions: [ 'Find workshops near research institutions', 'Recommend bioinformatics resources', From 239d474434c29a876b52e58d73ab53e44383fc05 Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Fri, 20 Jun 2025 12:10:07 +0100 Subject: [PATCH 13/71] VF Chatbot : Changes from internal demo feedback --- .../vf-chatbot-action-prompt.js | 109 ++-- .../vf-chatbot-action-prompt.njk | 23 +- .../vf-chatbot-action-prompt.scss | 26 +- .../vf-chatbot-feedback.config.yml | 36 +- .../vf-chatbot-feedback.js | 302 ++++------- .../vf-chatbot-feedback.njk | 41 +- .../vf-chatbot-feedback.scss | 55 +- .../vf-chatbot-modal/vf-chatbot-modal.js | 20 +- .../vf-chatbot-modal/vf-chatbot-modal.njk | 4 +- .../vf-chatbot-modal/vf-chatbot-modal.scss | 156 +++--- .../vf-chatbot-prompt/vf-chatbot-prompt.njk | 47 +- .../vf-chatbot-selector.config.yml | 82 +-- .../vf-chatbot-selector.js | 77 ++- .../vf-chatbot-selector.njk | 52 +- .../vf-chatbot-sources/vf-chatbot-sources.js | 30 +- .../vf-chatbot-sources.scss | 35 +- .../vf-chatbot-standalone.js | 470 ++++-------------- .../vf-chatbot-standalone.njk | 435 +++++----------- .../vf-chatbot-standalone.scss | 245 ++------- .../vf-chatbot-welcome/vf-chatbot-welcome.js | 126 +++-- .../vf-chatbot-welcome/vf-chatbot-welcome.njk | 40 +- .../vf-chatbot-welcome.scss | 176 +++---- .../assets/vf-chatbot--avatar-user.svg | 4 +- .../assets/vf-chatbot--icon-large.svg | 1 - .../assets/vf-chatbot--icon-medium.svg | 1 - .../assets/vf-chatbot--icon-send.svg | 4 + .../assets/vf-chatbot--icon-small.svg | 1 - .../assets/vf-chatbot--icon-thumbs-down.svg | 3 + .../assets/vf-chatbot--icon-thumbs-up.svg | 3 + .../assets/vf-chatbot--icon-x-small.svg | 1 - .../assets/vf-chatbot-selector-llms.json | 45 ++ .../assets/vf-chatbot-selector-services.json | 65 +++ components/vf-chatbot/vf-chatbot.njk | 2 +- .../vf-componenet-rollup/scripts copy.js | 115 ----- .../src/site/chatbot/index.njk | 19 +- 35 files changed, 1153 insertions(+), 1698 deletions(-) delete mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-large.svg delete mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-medium.svg create mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-send.svg delete mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-small.svg create mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-thumbs-down.svg create mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-thumbs-up.svg delete mode 100644 components/vf-chatbot/assets/vf-chatbot--icon-x-small.svg create mode 100644 components/vf-chatbot/assets/vf-chatbot-selector-llms.json create mode 100644 components/vf-chatbot/assets/vf-chatbot-selector-services.json delete mode 100644 components/vf-componenet-rollup/scripts copy.js diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js index fda8ee90fe..5f664a484b 100644 --- a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.js @@ -1,67 +1,78 @@ -// vf-chatbot-action-prompt.js - -class VFChatbotActionPrompt { +export class VFChatbotActionPrompt { constructor(element) { this.el = element; this.link = this.el.querySelector(".vf-chatbot-action-prompt__link"); - if (this.link) { - this.bindEvents(); - } - } - - bindEvents() { - this.link.addEventListener("click", event => { - // If it's a placeholder link or form action - if ( - this.link.getAttribute("href") === "#" || - this.link.hasAttribute("data-vf-js-chatbot-action-form") || - this.link.hasAttribute("data-vf-js-chatbot-standalone-suggestion") - ) { - event.preventDefault(); - - // Handle form submission if needed - const formId = this.link.getAttribute("data-vf-js-chatbot-action-form"); - if (formId) { - const form = document.getElementById(formId); - if (form) { - form.submit(); - return; - } - } - - // Get suggestion text if available - const suggestionText = this.link.getAttribute("data-vf-js-chatbot-standalone-suggestion"); - - // Get action data if available - const actionData = this.link.getAttribute( - "data-vf-js-chatbot-action-data" - ) || suggestionText; - - // Dispatch custom event with action data + if (this.link && !this.link.hasAttribute("href")) { + this.link.addEventListener("click", e => { + e.preventDefault(); this.el.dispatchEvent( new CustomEvent("vf-chatbot-action-prompt:click", { bubbles: true, detail: { - text: suggestionText || this.link.textContent.trim(), - data: actionData + text: this.link.textContent.trim() } }) ); - } - }); + }); + } } } -// Initialize component -function initVFChatbotActionPrompt() { - const actionPrompts = document.querySelectorAll( - "[data-vf-js-chatbot-action-prompt]" - ); +/** + * Creates and returns a fully functional action prompts component. + * @param {Array} prompts - Array of prompt objects, e.g., [{ action_text: 'Click me', action_url: '...' }] + * @returns {HTMLElement|null} - The action prompts component element or null if no prompts. + */ +function initVFChatbotActionPrompt(prompts) { + if (!prompts || prompts.length === 0) { + return null; + } + + // Create the main container + const promptsContainer = document.createElement('div'); + promptsContainer.className = 'vf-chatbot-action-prompts'; + + // Create the list container + const promptsList = document.createElement('div'); + promptsList.className = 'vf-chatbot-action-prompts__list'; + + // Create and append each prompt + prompts.forEach(prompt => { + const promptEl = document.createElement('div'); + promptEl.className = 'vf-chatbot-action-prompt'; + + const link = document.createElement('a'); + link.className = 'vf-chatbot-action-prompt__link'; + link.href = prompt.action_url || '#'; + link.textContent = prompt.action_text; + + // Set target attribute for external links + if (prompt.action_url && !prompt.action_url.startsWith('tel:')) { + link.target = '_blank'; + } - actionPrompts.forEach(actionPrompt => { - new VFChatbotActionPrompt(actionPrompt); + // If no URL is provided, the prompt can dispatch an event on click + if (!prompt.action_url) { + link.addEventListener('click', (e) => { + e.preventDefault(); + const event = new CustomEvent('vf-chatbot-action-prompt:click', { + bubbles: true, + detail: { + text: prompt.action_text + } + }); + link.dispatchEvent(event); + }); + } + + promptEl.appendChild(link); + promptsList.appendChild(promptEl); }); + + promptsContainer.appendChild(promptsList); + + return promptsContainer; } -export { VFChatbotActionPrompt, initVFChatbotActionPrompt }; +export { initVFChatbotActionPrompt }; diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk index f1a5b73747..4887cf1f4b 100644 --- a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.njk @@ -1,24 +1,13 @@ -
    +
    {% if action_url %} - + {{ action_text }} {% else %} - + {% endif %}
    diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss index 5d537bdf75..a65b77c3e7 100644 --- a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss @@ -1,10 +1,18 @@ +.vf-chatbot-action-prompts { + &__list{ + margin-top: 16px; + display: flex; + flex-direction: row; + gap: 8px; + } +} .vf-chatbot-action-prompt { display: inline-block; &__link { border-radius: 4px; display: inline-block; - padding: 10px 10px; + padding: 10px; border: 1px solid #4b7fd1; // Thin blue border color: #4b7fd1; // Blue text background-color: #FFFFFF; @@ -18,7 +26,11 @@ width: 100%; // Width based on content height: 100%; box-sizing: border-box; - white-space: normal; // Prevent text wrapping + // white-space: nowrap; + + @media (max-width: $vf-breakpoint--sm) { + white-space: normal; + } &:hover, &:focus { background-color: rgba(75, 127, 209, 0.1); // Light blue background on hover @@ -30,10 +42,6 @@ &:active { transform: translateY(1px); } - - @media (max-width:$vf-breakpoint--md) { - width: auto; - } } // Variants @@ -54,12 +62,6 @@ &--full-width { display: block; width: 100%; - - // .vf-chatbot-action-prompt__link { - // display: block; - // width: 100%; - // white-space: normal; // Allow text wrapping for full-width - // } } @media (max-width:$vf-breakpoint--md) { diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml b/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml index 979884b8f1..8050ebdb2d 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml @@ -1,14 +1,22 @@ -title: Chatbot Feedback Component -label: Chatbot Feedback -status: alpha -context: - positiveFeedbackOptions: - - 'Accurate answer' - - 'Easy to understand' - - 'Well formatted' - - 'Helpful' - negativeFeedbackOptions: - - 'Inaccurate answer' - - 'Did not use context' - - 'Poorly formatted' - - 'Not helpful' +title: Chatbot Feedback Form +variants: + - name: positive + context: + title: "What did you like about this response?" + options: + - id: "accurate" + label: "It's accurate" + - id: "helpful" + label: "It's helpful" + - id: "clear" + label: "It's clear" + - name: negative + context: + title: "What was the issue with this response?" + options: + - id: "inaccurate" + label: "It's inaccurate" + - id: "unhelpful" + label: "It's not helpful" + - id: "offensive" + label: "It's offensive or unsafe" diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.js b/components/vf-chatbot-feedback/vf-chatbot-feedback.js index 2dc607a6a4..a64f332c7f 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.js +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.js @@ -1,236 +1,132 @@ export class VFChatbotFeedback { - constructor(element, responseId) { - if (!element) { - console.error("Feedback element is required"); - return; - } - - this.el = element; - this.responseId = responseId; - this.selectedFeedback = null; - this.positiveFeedbackOptions = [ - "Accurate answer", - "Easy to understand", - "Well formatted", - "Helpful" - ]; - this.negativeFeedbackOptions = [ - "Inaccurate answer", - "Did not use context", - "Poorly formatted", - "Not helpful" - ]; - - // API configuration - Mistral AI - this.API_TOKEN = ""; - this.API_URL = "https://api.mistral.ai/v1/chat/completions"; - - // Initialize after ensuring element exists - this.init(); + constructor(container, messageId) { + this.container = container; + this.messageId = messageId; + this.positiveTemplate = document.querySelector('#feedback-positive-template'); + this.negativeTemplate = document.querySelector('#feedback-negative-template'); + this.renderInitialState(); + this.selectedThumb = ''; } - init() { - // Ensure element exists before querying - if (!this.el) return; - - const thumbsUp = this.el.querySelector("[data-vf-js-feedback-thumbs-up]"); - const thumbsDown = this.el.querySelector( - "[data-vf-js-feedback-thumbs-down]" - ); + renderInitialState() { + this.container.innerHTML = ` +
    + + +
    +
    + `; + this.bindThumbEvents(); + } - if (thumbsUp) { - thumbsUp.addEventListener("click", e => { - e.stopPropagation(); // Prevent bubbling - this.handleThumbsClick("positive"); - }); - } + bindThumbEvents() { + const upThumb = this.container.querySelector('[data-vf-js-feedback-thumb="up"]'); + const downThumb = this.container.querySelector('[data-vf-js-feedback-thumb="down"]'); + const formContainer = this.container.querySelector('.vf-chatbot-feedback__form-container'); - if (thumbsDown) { - thumbsDown.addEventListener("click", e => { - e.stopPropagation(); // Prevent bubbling - this.handleThumbsClick("negative"); - }); - } + upThumb?.addEventListener("click", () => { + upThumb.classList.add("vf-chatbot-feedback__thumb--solid"); + downThumb.classList.remove("vf-chatbot-feedback__thumb--solid"); + this.showForm("positive", formContainer); + }); - // Stop propagation on the entire feedback component - this.el.addEventListener("click", e => { - e.stopPropagation(); + downThumb?.addEventListener("click", () => { + downThumb.classList.add("vf-chatbot-feedback__thumb--solid"); + upThumb.classList.remove("vf-chatbot-feedback__thumb--solid"); + this.showForm("negative", formContainer); }); } - handleThumbsClick(type) { - // First remove solid class from both thumbs - const thumbsUp = this.el.querySelector("[data-vf-js-feedback-thumbs-up]"); - const thumbsDown = this.el.querySelector( - "[data-vf-js-feedback-thumbs-down]" - ); - thumbsUp?.classList.remove("vf-chatbot-feedback__thumb--solid"); - thumbsDown?.classList.remove("vf-chatbot-feedback__thumb--solid"); - - // Make the clicked thumb solid - const selectedThumb = this.el.querySelector( - type === "positive" - ? "[data-vf-js-feedback-thumbs-up]" - : "[data-vf-js-feedback-thumbs-down]" - ); - selectedThumb?.classList.add("vf-chatbot-feedback__thumb--solid"); + showForm(type, formContainer) { + if (!formContainer) { + formContainer = this.container.querySelector('.vf-chatbot-feedback__form-container'); + } + formContainer.innerHTML = ''; + const template = type === 'positive' ? this.positiveTemplate : this.negativeTemplate; + if (template) { + const formContent = template.content.cloneNode(true); + formContainer.appendChild(formContent); + this.bindFormEvents(formContainer); + } - this.selectedFeedback = type; - this.showFeedbackForm(type); + // Scroll chat window to bottom + const chatMessages = document.querySelector('[data-vf-js-chatbot-standalone-messages]'); + if (chatMessages) { + chatMessages.scrollTop = chatMessages.scrollHeight; + } } - showFeedbackForm(type) { - const formContainer = this.el.querySelector(".vf-chatbot-feedback__form"); - - // Clear any existing content (form or banners) - formContainer.innerHTML = ""; - - const feedbackOptions = - type === "positive" - ? this.positiveFeedbackOptions - : this.negativeFeedbackOptions; - const formTitle = "Tell us more about your response (optional)"; - - const formEl = document.createElement("div"); - formEl.className = "vf-chatbot-feedback__form-content"; - formEl.innerHTML = ` -

    ${formTitle}

    -
    - ${feedbackOptions - .map( - option => ` - - ` - ) - .join("")} -
    -

    Comments

    - - - `; - - // Add event listeners for options with stopPropagation - const options = formEl.querySelectorAll(".vf-chatbot-feedback__option"); - options.forEach(option => { - option.addEventListener("click", e => { - e.stopPropagation(); // Prevent bubbling - // Remove selected class from all options - options.forEach(opt => - opt.classList.remove("vf-chatbot-feedback__option--selected") - ); - // Add selected class to clicked option - e.target.classList.add("vf-chatbot-feedback__option--selected"); + bindFormEvents(formContainer) { + // Option button selection logic (if needed) + const optionButtons = formContainer.querySelectorAll('.vf-chatbot-feedback__option'); + optionButtons.forEach(btn => { + btn.addEventListener('click', () => { + optionButtons.forEach(b => b.classList.remove('vf-chatbot-feedback__option--selected')); + btn.classList.add('vf-chatbot-feedback__option--selected'); }); }); - // Add submit handler with stopPropagation - const submitBtn = formEl.querySelector(".vf-chatbot-feedback__submit"); - submitBtn.addEventListener("click", e => { - e.stopPropagation(); // Prevent bubbling - this.submitFeedback(); - }); - - formContainer.appendChild(formEl); - // Scroll the form into view - formEl.scrollIntoView({ behavior: "smooth", block: "nearest" }); - } - - async submitFeedback() { - // const selectedOption = this.el.querySelector( - // ".vf-chatbot-action-prompt--selected" - // ); - // const comment = this.el.querySelector(".vf-chatbot-feedback__comment") - // .value; + // Submit button logic + const submitBtn = formContainer.querySelector('[data-vf-js-feedback-submit]'); + submitBtn?.addEventListener('click', () => this.submitFeedback(formContainer)); - // if (response.ok) { - this.showSuccess(); - // } else { - // this.showError(); - // } - // } catch (error) { - // this.showError(); - // } - } - - showSuccess() { - const formContainer = this.el.querySelector(".vf-chatbot-feedback__form"); - formContainer.innerHTML = ` -
    -
    -

    Thank you for the feedback!

    - -
    -
    - `; - - // Add close button event listener with stopPropagation - const closeBtn = formContainer.querySelector(".vf-banner__close"); + // Close icon logic + const closeBtn = formContainer.querySelector('[data-vf-js-feedback-form-close]'); if (closeBtn) { - closeBtn.addEventListener("click", e => { - e.stopPropagation(); // Prevent bubbling - formContainer.innerHTML = ""; + closeBtn.addEventListener('click', () => { + // Remove the feedback form + formContainer.innerHTML = ''; + + // Remove solid class from both thumbs + const upThumb = this.container.querySelector('[data-vf-js-feedback-thumb="up"]'); + const downThumb = this.container.querySelector('[data-vf-js-feedback-thumb="down"]'); + upThumb?.classList.remove('vf-chatbot-feedback__thumb--solid'); + downThumb?.classList.remove('vf-chatbot-feedback__thumb--solid'); }); } - - // Hide the unselected thumb - const otherThumb = this.el.querySelector( - this.selectedFeedback === "positive" - ? "[data-vf-js-feedback-thumbs-down]" - : "[data-vf-js-feedback-thumbs-up]" - ); - if (otherThumb) { - otherThumb.style.display = "none"; - } - - // Add solid class to selected thumb - const selectedThumb = this.el.querySelector( - this.selectedFeedback === "positive" - ? "[data-vf-js-feedback-thumbs-up]" - : "[data-vf-js-feedback-thumbs-down]" - ); - selectedThumb?.classList.add("vf-chatbot-feedback__thumb--solid"); } - showError() { - const formContainer = this.el.querySelector(".vf-chatbot-feedback__form"); + submitFeedback(formContainer) { + // Show thank you message using vf-banner (dismissible) formContainer.innerHTML = ` -
    +
    -

    Failed to submit feedback. Please try again.

    -
    `; - // Reset thumbs state - const thumbsUp = this.el.querySelector("[data-vf-js-feedback-thumbs-up]"); - const thumbsDown = this.el.querySelector( - "[data-vf-js-feedback-thumbs-down]" - ); - thumbsUp?.classList.remove("vf-chatbot-feedback__thumb--solid"); - thumbsDown?.classList.remove("vf-chatbot-feedback__thumb--solid"); + // Hide the unselected thumb and disable the selected one + const upThumb = this.container.querySelector('[data-vf-js-feedback-thumb="up"]'); + const downThumb = this.container.querySelector('[data-vf-js-feedback-thumb="down"]'); + if (upThumb.classList.contains('vf-chatbot-feedback__thumb--solid')) { + downThumb.style.display = 'none'; + upThumb.disabled = true; // Disable the clicked thumb + } else if (downThumb.classList.contains('vf-chatbot-feedback__thumb--solid')) { + upThumb.style.display = 'none'; + downThumb.disabled = true; // Disable the clicked thumb + } - // Add close button event listener with stopPropagation - const closeBtn = formContainer.querySelector(".vf-banner__close"); - if (closeBtn) { - closeBtn.addEventListener("click", e => { - e.stopPropagation(); // Prevent bubbling - formContainer.innerHTML = ""; + // Add dismiss functionality + const banner = formContainer.querySelector('[data-vf-js-banner]'); + const closeBtn = formContainer.querySelector('.vf-button--dismiss'); + if (banner && closeBtn) { + closeBtn.addEventListener('click', () => { + banner.remove(); }); } } diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.njk b/components/vf-chatbot-feedback/vf-chatbot-feedback.njk index fce5b37081..29e48360c8 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.njk +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.njk @@ -1,15 +1,28 @@ -
    -
    - - +
    +
    +
    +
    Tell us more (optional)
    + +
    +
    + {% for option in options %} + + {% endfor %} +
    +
    Comments
    + +
    -
    -
    \ No newline at end of file +
    diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.scss b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss index 9b31fdf18a..0cdc4f151e 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.scss +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss @@ -8,9 +8,11 @@ } &__thumb { + padding: 0; + justify-content: center; background: none; border: none; - padding: 0.5rem; + padding: 10px; cursor: pointer; color: #666; transition: color 0.2s, transform 0.2s; @@ -18,8 +20,7 @@ align-items: center; &:hover { - color: #000; - transform: scale(1.1); + background-color: #E4E4E4; } &--solid { @@ -31,8 +32,6 @@ } svg { - width: 24px; - height: 24px; display: block; } } @@ -44,14 +43,22 @@ background: #ffffff; border: 1px solid #e5e5e5; padding: 1rem; + + &-header { + display: flex; + flex-direction: row; + justify-content: center; + margin-bottom: 24px; + } } } &__title { - font-size: 0.875rem; - font-weight: bold; - color: #1a1a1a; - margin: 0 0 1rem 0; + color: #1A1C1A; + font-size: 19px; + font-weight: 500; + line-height: 28.50px; + word-wrap: break-word; } &__options { @@ -78,27 +85,31 @@ min-width: fit-content; cursor: pointer; // flex: 1 1 150px; + transition: background 0.2s; + font-size: 14px; + font-weight: 400; + line-height: 22.40px; + word-wrap: break-word; &--selected { - background: #D1E3F6; + background-color: #D1E3F6; } } + &__comment-title { + color: #1A1C1A; + font-size: 16px; + font-weight: 400; + line-height: 27.20px; + word-wrap: break-word + } + &__comment { width: 99%; - margin-bottom: 1rem; + margin-bottom: 24px; font-family: inherit; font-size: 0.875rem; background: #ffffff; - - // &::placeholder { - // color: #666; - // } - - // &:focus { - // outline: none; - // border-color: #007c82; - // } } &__submit { @@ -109,10 +120,6 @@ font-weight: 500; cursor: pointer; transition: background 0.2s; - - // &:hover { - // background: #005e62; - // } } .vf-banner { diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.js b/components/vf-chatbot-modal/vf-chatbot-modal.js index 4520cdcc69..8e712ab2ee 100644 --- a/components/vf-chatbot-modal/vf-chatbot-modal.js +++ b/components/vf-chatbot-modal/vf-chatbot-modal.js @@ -1,4 +1,3 @@ -// vf-chatbot-modal import { initVFChatbotSources } from "../vf-chatbot-sources/vf-chatbot-sources"; import { VFChatbotFeedback } from "../vf-chatbot-feedback/vf-chatbot-feedback.js"; import { initVFChatbotSelector } from "../vf-chatbot-selector/vf-chatbot-selector.js"; @@ -7,7 +6,6 @@ import { VFChatbotActionPrompt } from "../vf-chatbot-action-prompt/vf-chatbot-ac class VFChatbotModal { constructor(element) { - // console.log("Initializing chatbot modal..."); // UNUSED: Debug log // Store DOM elements this.container = element; @@ -60,7 +58,9 @@ class VFChatbotModal { } // Selector element - this.selectorEl = this.container.querySelector("[data-vf-js-chatbot-selector]"); + this.selectorEl = this.container.querySelector( + "[data-vf-js-chatbot-selector]" + ); // API configuration - Mistral AI this.API_TOKEN = ""; @@ -469,7 +469,11 @@ class VFChatbotModal { const fallbackResponse = this.fallbackResponses[ Math.floor(Math.random() * this.fallbackResponses.length) ]; - this.addAssistantResponse(fallbackResponse["answer"],[], fallbackResponse["prompts"] || []); + this.addAssistantResponse( + fallbackResponse["answer"], + [], + fallbackResponse["prompts"] || [] + ); this.setLoadingState(false); return; // Check if we have a predefined answer @@ -594,7 +598,9 @@ class VFChatbotModal { promptsEl.className = "vf-chatbot-action-prompts"; promptsEl.innerHTML = `
    - ${prompts.map(prompt => ` + ${prompts + .map( + prompt => ` - `).join("")} + ` + ) + .join("")}
    `; assistantMessageEl.appendChild(promptsEl); diff --git a/components/vf-chatbot-modal/vf-chatbot-modal.njk b/components/vf-chatbot-modal/vf-chatbot-modal.njk index 850b27e495..1c7bbdb77f 100644 --- a/components/vf-chatbot-modal/vf-chatbot-modal.njk +++ b/components/vf-chatbot-modal/vf-chatbot-modal.njk @@ -246,7 +246,7 @@

    {{ welcome_title | default('AI assistant') }}

    - {{ welcome_description | default("Welcome! I'm here to help you discover bioinformatics training and resources.") }} + {{ welcome_description | default("Welcome! I'm here to help you.") }}

    @@ -315,7 +315,7 @@
    - +
    +
    + + +
    + + + + + + + + + + + {% if prompts and prompts.length > 0 %} +
    +
    + {% for prompt in prompts %} + {% render "@vf-chatbot-action-prompt", { + action_text: prompt.action_text, + action_url: prompt.action_url, + action_target: "_blank" if prompt.action_url and not prompt.action_url.startswith("tel:") else "_self" + } %} + {% endfor %} +
    - {#
    #} + {% endif %} +
    diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss index 0c0be6bf8e..2ccf4f5034 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss @@ -5,8 +5,10 @@ .vf-chatbot-standalone { display: flex; + border-radius: 4px 4px 4px 4px; flex-direction: column; - margin: 16px 36px !important; + height: 91vh; + margin: 8px 36px 16px 36px; &__container { display: flex; @@ -20,8 +22,9 @@ } &__header { + margin: 16px 36px !important; // height: 64px; - background: #ffffff; + // background: #ffffff; color: #000000; display: flex; align-items: center; @@ -71,25 +74,30 @@ } &__content { - // display: flex !important; - // flex-direction: column; - // flex: 1; - // overflow: hidden; - // background: #F5F5F5; - // justify-content: center; - border-radius: 4px 4px 4px 4px; - // height: 85vh; + justify-content: space-evenly; + height: 80vh; + + width: 55%; + margin: 0 auto; + display: flex; + flex-direction: column; + align-items: center; + + @media (max-width:$vf-breakpoint--md) { + width: 95%; + } + @media (max-width: 600px) { + justify-content: flex-end; + width: 88%; + min-height: 300px; + } } // Welcome screen styles &__welcome { width: 100%; justify-content: center; - // flex: 1; display: flex; - // flex-direction: column; - // justify-content: center; - // align-items: center; padding-top: 24px; &-content { @@ -141,12 +149,6 @@ justify-items: left; // Center items horizontally gap: 8px; - // Make the last item span full width if it's the 3rd item - // & > *:nth-child(3):last-child { - // grid-column: 1 / -1; - // justify-self: center; // Center the full-width item - // } - // Ensure each grid cell only takes the width it needs & > * { width: 100%; @@ -157,85 +159,12 @@ } } } - - &-suggestion { - padding: 12px 16px; - background: #FFFFFF; - border: 1px solid #E5E5E5; - border-radius: 8px; - font-size: 14px; - color: #1A1A1A; - cursor: pointer; - transition: background 0.2s ease, border-color 0.2s ease; - text-align: left; - - &:hover { - background: #F0F0F0; - border-color: #CCCCCC; - } - } - - &-input-container { - margin-top: 32px; - width: 100%; - max-width: 500px; - } - - &-input-wrapper { - position: relative; - width: 100%; - display: flex; - align-items: center; - background: #FFFFFF; - border: 1px solid #E5E5E5; - border-radius: 8px; - overflow: hidden; - } - - &-input { - flex: 1; - padding: 16px; - border: none; - font-size: 16px; - line-height: 1.5; - background: transparent; - - &:focus { - outline: none; - } - - &::placeholder { - color: #666666; - } - } - - &-send-button { - background: #007AFF; - color: #ffffff; - border: none; - width: 48px; - height: 48px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: background 0.2s ease; - - &:hover { - background: darken(#007AFF, 10%); - } - - svg { - width: 24px; - height: 24px; - } - } } &__loading { - // min-height: 50vh; flex-direction: column; justify-items: flex-start; + margin-top: 16px; &-dots { width: 30px; background: #ffffff; @@ -261,22 +190,20 @@ &__input-wrapper { display: flex; - align-items: center; - height: 10vh; - position: relative; - width: 50%; - margin: 0 auto; - - + width: 55%; + margin: 16px auto; @media (max-width:$vf-breakpoint--md) { - width: 100%; + width: 95%; + } + @media (max-width: 600px) { + width: 88%; } } &__input { align-content: center; width: 100%; - padding-left: 16px; + padding-left: 24px; border: none; font-size: 16px; line-height: 1.5; @@ -291,18 +218,9 @@ } &__send-button { - position: absolute; - right: 0px; - top: 50%; - transform: translateY(-50%); background: #3A77BC; - color: #ffffff; border: none; - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; + padding-inline: 0px; cursor: pointer; transition: background 0.2s ease; @@ -316,27 +234,8 @@ } } - &__chat { - width: 50%; - margin: 0 auto; - display: flex; - flex-direction: column; - justify-content: flex-end; - align-items: center; - height: 75vh; // or use: calc(100vh - [header+footer heights]) for more precise fit - min-height: 400px; - - @media (max-width: 900px) { - width: 95%; - } - @media (max-width: 600px) { - width: 100%; - min-height: 300px; - } - } - &__messages { - display: flex; + // display: flex; flex-direction: column; // flex: 1 1 auto; overflow-y: auto; @@ -350,23 +249,9 @@ } } - // &__messages { - // flex: 1 1 auto; - // overflow-y: auto; - // width: 100%; - // padding-top: 16px; - // min-height: 0; // Required for flexbox scroll - // max-height: 100%; // Ensures it doesn't overflow the parent - - // @media (max-width: 768px) { - // padding: 16px; - // } - // // padding: 1rem; - // // min-height: 0; /* Required for flex children to scroll */ - // } - &__disclaimer { - width: 98%; + max-width: 51%; + width: max-content; display: flex; justify-content: flex-end; flex-direction: column; @@ -374,11 +259,12 @@ position: absolute; bottom: 0px; z-index: 1000; - // height: 97vh; padding-bottom: 4%; - - .vf-banner { - width: 50%; + @media (max-width:$vf-breakpoint--md) { + max-width: 85%; + } + @media (max-width: 600px) { + max-width: 75%; } } } @@ -409,18 +295,16 @@ .vf-chatbot-message__avatar { width: 24px; height: 24px; - border-radius: 50%; } .vf-chatbot-message__content { background: #ffffff; color: #1A1A1A; - border-radius: 4px 4px 4px 4px; } } &__content { - padding: 16px; + padding: 8px 16px; font-size: 16px; line-height: 1.5; } @@ -434,13 +318,18 @@ } .vf-chatbot-message--user { - max-width: 85%; + max-width: 85%; + display: grid; + align-items: flex-start; + gap: 8px; .vf-chatbot-message__avatar { width: 100%; - display: flex; - align-items: center; - gap: 8px; + flex-direction: row; + justify-content: flex-end; + display: flex; + align-items: center; + gap: 8px; .vf-chatbot-message__avatar-name { font-size: 14px; @@ -451,16 +340,15 @@ .vf-chatbot-message__avatar img { width: 24px; height: 24px; - border-radius: 50%; } } } .vf-chatbot-message--assistant { - margin-right: auto; + margin-right: 8px; display: grid; align-items: flex-start; - gap: 12px; + gap: 8px; .vf-chatbot-message__avatar { width: 100%; @@ -471,9 +359,6 @@ &-image { width: 24px; height: 24px; - // border: 1px solid #707372; - // border-radius: 50%; - // background-color: #FFFFFF; img { width: 16px; height: 16px; @@ -486,31 +371,3 @@ } } } - - - -.vf-chatbot-message--user { - display: grid; - align-items: flex-start; - gap: 12px; - - .vf-chatbot-message__avatar { - flex-direction: row; - justify-content: flex-end; - display: flex; - align-items: center; - gap: 8px; - - img { - width: 24px; - height: 24px; - border-radius: 50%; - } - - .vf-chatbot-message__avatar-name { - font-size: 14px; - font-weight: 500; - color: #1A1A1A; - } - } - } diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.js b/components/vf-chatbot-welcome/vf-chatbot-welcome.js index 84856833a7..b7adf1e3b2 100644 --- a/components/vf-chatbot-welcome/vf-chatbot-welcome.js +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.js @@ -1,59 +1,115 @@ // vf-chatbot-welcome.js -class VFChatbotWelcome { +export class VFChatbotWelcome { constructor(element) { this.el = element; - this.startButton = this.el.querySelector("[data-vf-js-chatbot-start]"); - this.suggestions = this.el.querySelectorAll( - "[data-vf-js-chatbot-suggestion]" + this.suggestionsGrid = this.el.querySelector( + "[data-vf-js-chatbot-welcome-suggestions-grid]" ); + this.qaData = null; + this.boundHandleSuggestionClick = this.handleSuggestionClick.bind(this); + } - this.bindEvents(); + async init() { + try { + await this.loadQAData(); + this.populateSuggestions(); + this.bindEvents(); + return Promise.resolve(); + } catch (error) { + console.error("Failed to initialize welcome component:", error); + return Promise.reject(error); + } } - bindEvents() { - // Start conversation button - this.startButton?.addEventListener("click", () => { - this.hideWelcomeScreen(); - }); + async loadQAData() { + try { + const response = await fetch( + "../../assets/vf-chatbot/assets/vf-chatbot-qa.json" + ); + const data = await response.json(); + this.qaData = data.predefinedQA; + } catch (error) { + console.error("Failed to load Q&A data:", error); + } + } + + populateSuggestions() { + if (!this.qaData || !this.suggestionsGrid) return; - // Suggestion buttons - this.suggestions.forEach(suggestion => { - suggestion.addEventListener("click", () => { - const text = suggestion.getAttribute("data-vf-js-chatbot-suggestion"); - this.sendSuggestion(text); - }); + // Clear existing suggestions + this.suggestionsGrid.innerHTML = ""; + + // Get random questions + const questions = Object.keys(this.qaData); + const randomQuestions = questions + .sort(() => 0.5 - Math.random()) + .slice(0, 3); + + // Create suggestion elements + randomQuestions.forEach((question, index) => { + const suggestionEl = document.createElement("div"); + suggestionEl.className = `vf-chatbot-action-prompt`; + suggestionEl.setAttribute( + "data-vf-js-chatbot-welcome-suggestion", + question + ); + + suggestionEl.innerHTML = ` + ${question} + `; + + this.suggestionsGrid.appendChild(suggestionEl); }); } - hideWelcomeScreen() { - // Hide welcome screen - this.el.style.display = "none"; + bindEvents() { + // Remove existing event listener if any + this.suggestionsGrid?.removeEventListener( + "click", + this.boundHandleSuggestionClick + ); - // Dispatch event to notify that welcome screen is closed - this.el.dispatchEvent(new CustomEvent("vf-chatbot-welcome:closed")); + // Add single event listener using event delegation + this.suggestionsGrid?.addEventListener( + "click", + this.boundHandleSuggestionClick + ); } - sendSuggestion(text) { - // Hide welcome screen - this.hideWelcomeScreen(); + handleSuggestionClick(e) { + e.preventDefault(); - // Dispatch event with the suggestion text + const suggestionEl = e.target.closest( + "[data-vf-js-chatbot-welcome-suggestion]" + ); + if (!suggestionEl) return; + + const question = suggestionEl.getAttribute( + "data-vf-js-chatbot-welcome-suggestion" + ); + if (!question || !this.qaData[question]) return; + + // Get answer data + const answer = this.qaData[question]; + + // Dispatch event only once this.el.dispatchEvent( - new CustomEvent("vf-chatbot-welcome:suggestion", { - detail: { text } + new CustomEvent("vf-chatbot-welcome:suggestion-click", { + bubbles: true, + detail: { + question, + answer: answer.answer || answer.html, + sources: answer.sources || [], + prompts: answer.prompts || [] + } }) ); } } // Initialize -function initVFChatbotWelcome() { - const welcomeElements = document.querySelectorAll( - "[data-vf-js-chatbot-welcome]" - ); - - welcomeElements.forEach(element => new VFChatbotWelcome(element)); +export function initVFChatbotWelcome() { + const elements = document.querySelectorAll("[data-vf-js-chatbot-welcome]"); + elements.forEach(element => new VFChatbotWelcome(element)); } - -export { VFChatbotWelcome, initVFChatbotWelcome }; diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.njk b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk index d4079dee5c..6e6ec117bd 100644 --- a/components/vf-chatbot-welcome/vf-chatbot-welcome.njk +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk @@ -1,41 +1,17 @@
    -
    - AI Assistant -

    {{ welcome_title | default('AI Assistant') }}

    -
    -
    + +

    {{ welcome_title | default('AI assistant') }}

    - {{ welcome_description | default('I can help you find information about our research, services, and more. What would you like to know?') }} + {{ welcome_description | default("Welcome! I'm here to help you.") }}

    - - {% if welcome_features %} -
    -

    I can help with:

    -
      - {% for feature in welcome_features %} -
    • - ✓ - {{ feature }} -
    • - {% endfor %} -
    -
    - {% endif %}
    -
    -

    Try asking:

    -
    - {% for suggestion in welcome_suggestions %} - - {% endfor %} +

    Try asking me:

    +
    +
    - -
    diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.scss b/components/vf-chatbot-welcome/vf-chatbot-welcome.scss index d696e7a14d..bf53958ae3 100644 --- a/components/vf-chatbot-welcome/vf-chatbot-welcome.scss +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.scss @@ -1,139 +1,125 @@ .vf-chatbot-welcome { - display: flex; - flex-direction: column; - height: 100%; - padding: 24px; - background-color: #ffffff; + width: 100%; - &__header { + &__content { + // width: 100%; + text-align: center; display: flex; flex-direction: column; align-items: center; - margin-bottom: 24px; - text-align: center; + justify-content: center; + height: 100%; } - &__icon { - width: 48px; - height: 48px; - margin-bottom: 16px; - object-fit: contain; + &__logo { + // margin-bottom: 16px; + + img { + width: 64px; + height: 64px; + margin-bottom: 16px; + object-fit: contain; + } } &__title { font-size: 24px; - font-weight: 600; + font-weight: 500; color: #1A1A1A; - margin: 0; - } - - &__content { - flex: 1; - margin-bottom: 24px; + margin: 0 0 12px 0; } &__description { font-size: 16px; - line-height: 1.5; color: #666666; - text-align: center; - margin-bottom: 24px; } - &__features { - background-color: #F5F5F5; - border-radius: 12px; - padding: 16px; - margin-bottom: 24px; - } + &__suggestions { + // margin-top: 16px; + width: 100%; + + &-title { + font-size: 16px; + font-weight: 500; + color: #1A1A1A; + margin: 0 0 16px 0; + } - &__features-title { - font-size: 16px; - font-weight: 500; - color: #1A1A1A; - margin: 0 0 12px 0; - } + &-grid { + display: grid; + grid-template-columns: 1fr 1fr; + justify-items: left; + gap: 8px; - &__features-list { - list-style: none; - padding: 0; - margin: 0; - } + & > * { + width: 100%; + min-width: min-content; + } - &__feature { - display: flex; - align-items: flex-start; - margin-bottom: 8px; - font-size: 14px; - line-height: 1.5; - color: #1A1A1A; - - &:last-child { - margin-bottom: 0; + @media (max-width: 480px) { + grid-template-columns: 1fr; + } } } - &__feature-icon { - display: flex; - align-items: center; - justify-content: center; - width: 20px; - height: 20px; - margin-right: 8px; - background-color: #007AFF; - color: #ffffff; - border-radius: 50%; - font-size: 12px; - flex-shrink: 0; + &__input-container { + margin-top: 32px; + width: 100%; + max-width: 500px; } - &__suggestions { - margin-bottom: 24px; - } - - &__suggestions-title { - font-size: 16px; - font-weight: 500; - color: #1A1A1A; - margin: 0 0 12px 0; - } - - &__suggestions-list { + &__input-wrapper { + position: relative; + width: 100%; display: flex; - flex-direction: column; - gap: 8px; + align-items: center; + background: #FFFFFF; + border: 1px solid #E5E5E5; + border-radius: 8px; + overflow: hidden; } - &__suggestion { - padding: 12px 16px; - background-color: #F5F5F5; + &__input { + flex: 1; + padding: 16px; border: none; - border-radius: 8px; - font-size: 14px; + font-size: 16px; line-height: 1.5; - color: #1A1A1A; - text-align: left; - cursor: pointer; - transition: background-color 0.2s ease; + background: transparent; - &:hover { - background-color: #E5E5E5; + &:focus { + outline: none; + } + + &::placeholder { + color: #666666; } } - &__start-button { - padding: 12px 24px; - background-color: #007AFF; + &__send-button { + background: #007AFF; color: #ffffff; border: none; - border-radius: 8px; - font-size: 16px; - font-weight: 500; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; cursor: pointer; - transition: background-color 0.2s ease; + transition: background 0.2s ease; &:hover { - background-color: darken(#007AFF, 10%); + background: darken(#007AFF, 10%); + } + + svg { + width: 24px; + height: 24px; } } + + @media (max-width: 600px) { + display: flex; + flex-direction: column; + } } diff --git a/components/vf-chatbot/assets/vf-chatbot--avatar-user.svg b/components/vf-chatbot/assets/vf-chatbot--avatar-user.svg index 175518a40f..e972e405e2 100644 --- a/components/vf-chatbot/assets/vf-chatbot--avatar-user.svg +++ b/components/vf-chatbot/assets/vf-chatbot--avatar-user.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-large.svg b/components/vf-chatbot/assets/vf-chatbot--icon-large.svg deleted file mode 100644 index 2dfaefee5d..0000000000 --- a/components/vf-chatbot/assets/vf-chatbot--icon-large.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-medium.svg b/components/vf-chatbot/assets/vf-chatbot--icon-medium.svg deleted file mode 100644 index 4a271ba854..0000000000 --- a/components/vf-chatbot/assets/vf-chatbot--icon-medium.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-send.svg b/components/vf-chatbot/assets/vf-chatbot--icon-send.svg new file mode 100644 index 0000000000..0849ecc5ea --- /dev/null +++ b/components/vf-chatbot/assets/vf-chatbot--icon-send.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-small.svg b/components/vf-chatbot/assets/vf-chatbot--icon-small.svg deleted file mode 100644 index 0581d00392..0000000000 --- a/components/vf-chatbot/assets/vf-chatbot--icon-small.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-thumbs-down.svg b/components/vf-chatbot/assets/vf-chatbot--icon-thumbs-down.svg new file mode 100644 index 0000000000..ea0a47eca3 --- /dev/null +++ b/components/vf-chatbot/assets/vf-chatbot--icon-thumbs-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-thumbs-up.svg b/components/vf-chatbot/assets/vf-chatbot--icon-thumbs-up.svg new file mode 100644 index 0000000000..6992bba678 --- /dev/null +++ b/components/vf-chatbot/assets/vf-chatbot--icon-thumbs-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/components/vf-chatbot/assets/vf-chatbot--icon-x-small.svg b/components/vf-chatbot/assets/vf-chatbot--icon-x-small.svg deleted file mode 100644 index d72bccb9eb..0000000000 --- a/components/vf-chatbot/assets/vf-chatbot--icon-x-small.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/components/vf-chatbot/assets/vf-chatbot-selector-llms.json b/components/vf-chatbot/assets/vf-chatbot-selector-llms.json new file mode 100644 index 0000000000..44e0a42e57 --- /dev/null +++ b/components/vf-chatbot/assets/vf-chatbot-selector-llms.json @@ -0,0 +1,45 @@ +{ + "routes": [ + { + "id": "gpt4-turbo", + "title": "GPT-4 Turbo", + "description": "Advanced language model with broader context window and improved capabilities", + "selected": true + }, + { + "id": "claude3-opus", + "title": "Claude 3 Opus", + "description": "Anthropic's most powerful model with enhanced reasoning and analysis capabilities" + }, + { + "id": "gemini-ultra", + "title": "Gemini Ultra", + "description": "Google's most capable model for complex tasks and multitask reasoning" + }, + { + "id": "llama3", + "title": "LLaMA 3", + "description": "Meta's open foundation model with strong performance across various tasks" + }, + { + "id": "mixtral", + "title": "Mixtral 8x7B", + "description": "Mistral AI's mixture-of-experts model combining multiple specialized networks" + }, + { + "id": "palm3", + "title": "PaLM 3", + "description": "Google's latest PaLM model optimized for reasoning and multilingual tasks" + }, + { + "id": "gpt4-vision", + "title": "GPT-4 Vision", + "description": "Specialized version of GPT-4 for multimodal tasks including image understanding" + }, + { + "id": "claude3-sonnet", + "title": "Claude 3 Sonnet", + "description": "Balanced model offering strong performance with improved efficiency" + } + ] +} diff --git a/components/vf-chatbot/assets/vf-chatbot-selector-services.json b/components/vf-chatbot/assets/vf-chatbot-selector-services.json new file mode 100644 index 0000000000..4379df59e4 --- /dev/null +++ b/components/vf-chatbot/assets/vf-chatbot-selector-services.json @@ -0,0 +1,65 @@ +{ + "routes": [ + { + "id": "ensembl", + "title": "Ensembl", + "description": "Genome browser for vertebrate genomes with comparative genomics tools", + "selected": true + }, + { + "id": "uniprot", + "title": "UniProt", + "description": "Comprehensive resource for protein sequence and annotation data" + }, + { + "id": "pfam", + "title": "Pfam", + "description": "Database of protein families and domains with HMM models" + }, + { + "id": "interpro", + "title": "InterPro", + "description": "Integrated database of protein families, domains and functional sites" + }, + { + "id": "chembl", + "title": "ChEMBL", + "description": "Database of bioactive drug-like small molecules and their targets" + }, + { + "id": "pdbe", + "title": "PDBe", + "description": "European resource for 3D biological macromolecular structure data" + }, + { + "id": "expression-atlas", + "title": "Expression Atlas", + "description": "Gene expression data across species and biological conditions" + }, + { + "id": "pride", + "title": "PRIDE", + "description": "Repository of mass spectrometry-based proteomics data" + }, + { + "id": "arrayexpress", + "title": "ArrayExpress", + "description": "Archive of functional genomics experiments" + }, + { + "id": "intact", + "title": "IntAct", + "description": "Molecular interaction database derived from literature curation" + }, + { + "id": "reactome", + "title": "Reactome", + "description": "Curated database of biological pathways and reactions" + }, + { + "id": "metabolights", + "title": "MetaboLights", + "description": "Database for metabolomics experiments and derived information" + } + ] +} diff --git a/components/vf-chatbot/vf-chatbot.njk b/components/vf-chatbot/vf-chatbot.njk index 5a07d53c75..d10e2c13ca 100644 --- a/components/vf-chatbot/vf-chatbot.njk +++ b/components/vf-chatbot/vf-chatbot.njk @@ -15,7 +15,7 @@ } %} {# {% render '@vf-chatbot-modal', { welcome_title: "AI Assistant", - welcome_description: "Welcome! I'm here to help you discover bioinformatics training and resources.", + welcome_description: "Welcome! I'm here to help you.", input_placeholder: "Ask me about Bioinformatics trainings...", disclaimer: "This chatbot is designed to assist you with general information and basic inquiries. See our disclaimer notes." } %} #} diff --git a/components/vf-componenet-rollup/scripts copy.js b/components/vf-componenet-rollup/scripts copy.js deleted file mode 100644 index be17517bbb..0000000000 --- a/components/vf-componenet-rollup/scripts copy.js +++ /dev/null @@ -1,115 +0,0 @@ -/* - * - * scripts.js - * The Visual Framework kitchen sink of JavaScript. - * Import this as a quick way to get *everything*, - * - */ - -// All VF JS -import { vfBanner } from "vf-banner/vf-banner"; -vfBanner(); - -import { vfBannerElixir } from "vf-banner-elixir/vf-banner-elixir"; -vfBannerElixir(); - -// VF Masthead has been deprecated -// https://github.com/visual-framework/vf-core/pull/1406/ -// import { vfMastheadSetStyle } from "vf-masthead/vf-masthead"; -// vfMastheadSetStyle(); - -import { vfGaIndicateLoaded } from "vf-analytics-google/vf-analytics-google"; -let vfGaTrackOptions = { - vfGaTrackPageLoad: true, - // vfGa4MeasurementId: "YourGa4TrackingId" // only required if tracking a custom page-level dimension -}; -vfGaIndicateLoaded(vfGaTrackOptions); - -import { vfTabs } from "vf-tabs/vf-tabs"; -vfTabs(); - -import { vfTree } from "vf-tree/vf-tree"; -vfTree(); - -// import { vfFormFloatLabels } from 'form /assets/vf-form__float-labels.js'; -// vfFormFloatLabels(); - -import { vfSearchClientSide } from "vf-search-client-side/vf-search-client-side"; -// No default invokation - -import { vfShowMore } from "vf-show-more/vf-show-more"; -vfShowMore(); - -import { vfLocationNearest } from "vf-location-nearest/vf-location-nearest"; -// Not invoked by default - -// All EMBL JS -import { emblContentHubLoaderHtmlImports } from "embl-content-hub-loader/embl-content-hub-loader__html-imports"; -import { emblContentHubFetch } from "embl-content-hub-loader/embl-content-hub-loader__fetch"; -import { emblContentHub } from "embl-content-hub-loader/embl-content-hub-loader"; -import { emblConditionalEdit } from "embl-conditional-edit/embl-conditional-edit"; -emblContentHub(); - -import { emblBreadcrumbs } from "embl-breadcrumbs-lookup/embl-breadcrumbs-lookup"; -emblBreadcrumbs(); - -import { vfBackToTop } from "vf-back-to-top/vf-back-to-top.js"; -vfBackToTop(); - -import { vfDropdown } from "vf-dropdown/vf-dropdown.js"; -vfDropdown(); - -import { vfNavigationOnThisPage } from "vf-navigation/vf-navigation.js"; -vfNavigationOnThisPage(); - -import { emblContentMetaProperties_Read } from "embl-content-meta-properties/embl-content-meta-properties"; - -import { emblNotifications } from "embl-notifications/embl-notifications"; -// emblNotifications(); - -import { vfMegaMenu } from 'vf-mega-menu/vf-mega-menu'; -vfMegaMenu(); - -import { vfTable } from 'vf-table/vf-table'; -vfTable(); - -// No default invokation - -// Import chatbot components -import { initVFChatbot } from 'vf-chatbot/vf-chatbot.js'; -import { initVFChatbotModal } from 'vf-chatbot-modal/vf-chatbot-modal.js'; -import { initVFChatbotStandalone } from 'vf-chatbot-standalone/vf-chatbot-standalone.js'; -import { initVFChatbotActionPrompt } from 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; -import { initVFChatbotFab } from 'vf-chatbot-fab/vf-chatbot-fab.js'; -import { initVFChatbotWelcome } from 'vf-chatbot-welcome/vf-chatbot-welcome.js'; -import { initVFChatbotPrompt } from 'vf-chatbot-prompt/vf-chatbot-prompt.js'; - -// Initialize all chatbot components when DOM is loaded -document.addEventListener('DOMContentLoaded', function() { - console.log('Initializing chatbot components...'); - - // Initialize all chatbot components - initVFChatbot(); - initVFChatbotModal(); - initVFChatbotActionPrompt(); - initVFChatbotFab(); - initVFChatbotWelcome(); - initVFChatbotPrompt(); - - // Handle standalone chatbot initialization with error handling - try { - if (typeof window.initVFChatbotStandalone === 'function') { - window.initVFChatbotStandalone(); - } else if (typeof initVFChatbotStandalone === 'function') { - initVFChatbotStandalone(); - } - } catch (error) { - console.warn('Could not initialize standalone chatbot:', error.message); - } -}); - -// Commented out components -// import { initVFChatbotHeader } from 'vf-chatbot-header/vf-chatbot-header.js'; -// import { initVFChatbotHeaderDropdown } from 'vf-chatbot-header-dropdown/vf-chatbot-header-dropdown.js'; -// import { initVFChatbotDialog } from 'vf-chatbot-dialog/vf-chatbot-dialog.js'; -// import { initVFChatbotCard } from 'vf-chatbot-card/vf-chatbot-card.js'; diff --git a/tools/vf-component-library/src/site/chatbot/index.njk b/tools/vf-component-library/src/site/chatbot/index.njk index 0da658e9a9..4e8af01a8a 100644 --- a/tools/vf-component-library/src/site/chatbot/index.njk +++ b/tools/vf-component-library/src/site/chatbot/index.njk @@ -16,9 +16,9 @@ window.initVFChatbotStandalone(); // Initialize supporting components only once - ["initVFChatbotActionPrompt", "initVFChatbotWelcome", "initVFChatbotPrompt"].forEach(fn => { - if (typeof window[fn] === "function") window[fn](); - }); + //["initVFChatbotActionPrompt", "initVFChatbotWelcome", "initVFChatbotPrompt"].forEach(fn => { + // if (typeof window[fn] === "function") window[fn](); + //}); return true; } @@ -34,7 +34,7 @@ }); - +
    +{% if allowFeedback and allowFeedback == true > 0 %} +
    +{% endif %} diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.js b/components/vf-chatbot-standalone/vf-chatbot-standalone.js index f74632566f..319604c2c2 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.js +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.js @@ -46,10 +46,6 @@ class VFChatbotStandalone { "#loading-indicator-template" ); - // // API configuration - Mistral AI - // this.API_TOKEN = ""; - // this.API_URL = "https://api.mistral.ai/v1/chat/completions"; - // State this.currentAssistant = ""; // Default assistant // Load Q&A data diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk index 285c2e8f67..5f02f132e3 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk @@ -138,7 +138,8 @@ }, content: "How can I help you?", sources: sources, - prompts: prompts + prompts: prompts, + allowFeedback: true } %} From 33b0ea0e7b69ae17d2cd876bd6506f93ed3ddf88 Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Sat, 21 Jun 2025 19:24:35 +0100 Subject: [PATCH 15/71] VF Chatbot : Updates as per feedback --- .../vf-chatbot-action-prompt.scss | 4 +- .../vf-chatbot-selector.scss | 15 +- .../vf-chatbot-standalone.js | 8 +- .../vf-chatbot-standalone.njk | 150 +++++++++--------- .../vf-chatbot-standalone.scss | 133 ++-------------- .../vf-chatbot-welcome.scss | 13 +- .../src/site/chatbot/index.njk | 9 +- 7 files changed, 107 insertions(+), 225 deletions(-) diff --git a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss index a65b77c3e7..e38f69646f 100644 --- a/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss +++ b/components/vf-chatbot-action-prompt/vf-chatbot-action-prompt.scss @@ -13,8 +13,8 @@ border-radius: 4px; display: inline-block; padding: 10px; - border: 1px solid #4b7fd1; // Thin blue border - color: #4b7fd1; // Blue text + border: 1px solid var(--vf-color__link); // Thin blue border + color: var(--vf-color__link); // Blue text background-color: #FFFFFF; font-size: 14px; font-weight: 400; // Regular font weight diff --git a/components/vf-chatbot-selector/vf-chatbot-selector.scss b/components/vf-chatbot-selector/vf-chatbot-selector.scss index 6ff7e65747..d17388301f 100644 --- a/components/vf-chatbot-selector/vf-chatbot-selector.scss +++ b/components/vf-chatbot-selector/vf-chatbot-selector.scss @@ -34,7 +34,7 @@ .vf-chatbot-selector__title img { width: 32px; - margin: 6px; + margin: 10px; vertical-align: middle; } @@ -46,18 +46,13 @@ } .vf-chatbot-selector__main-text { - color: #1A1C1A; - font-size: 21px; - font-weight: 500; - line-height: 1.3em; - word-wrap: break-word + @include set-type(text-heading--5); + margin-bottom: 0; } .vf-chatbot-selector__title-text { - font-size: 21px; - color: var(--vf-color--grey-dark); - font-weight: 400; - display: block; + @include set-type(text-body--5); + margin-bottom: 0; } .vf-chatbot-selector__chevron { diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.js b/components/vf-chatbot-standalone/vf-chatbot-standalone.js index 319604c2c2..1fd8a2d6c6 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.js +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.js @@ -39,12 +39,8 @@ class VFChatbotStandalone { ); this.userTemplate = this.container.querySelector("#user-message-template"); - this.assistantTemplate = this.container.querySelector( - "#assistant-message-template" - ); - this.loadingTemplate = this.container.querySelector( - "#loading-indicator-template" - ); + this.assistantTemplate = this.container.querySelector( "#assistant-message-template"); + this.loadingTemplate = this.container.querySelector("#loading-indicator-template"); // State this.currentAssistant = ""; // Default assistant diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk index 5f02f132e3..6c8a14780a 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk @@ -32,92 +32,92 @@ {# {% set selectorContext = services_single_selector %} #} {% set selectorContext = services_multi_selector %} -
    -
    -
    - {% if selectorContext %} - {% render "@vf-chatbot-selector", selectorContext %} - {% else %} -
    -
    - AI Assistant -
    - AI Assistant +
    +
    +
    + {% if selectorContext %} + {% render "@vf-chatbot-selector", selectorContext %} + {% else %} +
    +
    + AI Assistant +
    + AI Assistant +
    -
    - {% endif %} + {% endif %} +
    -
    -
    +
    -
    +
    - - - {% if welcome_message %} - {% render "@vf-chatbot-welcome", { + + + {% if welcome_message %} + {% render "@vf-chatbot-welcome", { welcome_title: welcome_title, welcome_description: welcome_description, welcome_message: welcome_message } %} - {% endif %} - -
    - + {% endif %} + +
    + - -
    diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss index 2ccf4f5034..58d1dc8415 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.scss +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.scss @@ -5,10 +5,10 @@ .vf-chatbot-standalone { display: flex; + justify-content: end; border-radius: 4px 4px 4px 4px; flex-direction: column; - height: 91vh; - margin: 8px 36px 16px 36px; + height: 90vh; &__container { display: flex; @@ -22,9 +22,7 @@ } &__header { - margin: 16px 36px !important; - // height: 64px; - // background: #ffffff; + margin-bottom: 24px; color: #000000; display: flex; align-items: center; @@ -74,91 +72,7 @@ } &__content { - justify-content: space-evenly; - height: 80vh; - - width: 55%; - margin: 0 auto; - display: flex; - flex-direction: column; - align-items: center; - - @media (max-width:$vf-breakpoint--md) { - width: 95%; - } - @media (max-width: 600px) { - justify-content: flex-end; - width: 88%; - min-height: 300px; - } - } - - // Welcome screen styles - &__welcome { - width: 100%; - justify-content: center; - display: flex; - padding-top: 24px; - - &-content { - width: 100%; - text-align: center; - display: flex; - flex-direction: column; - align-items: center; - } - - &-logo { - margin-bottom: 16px; - - img { - width: 48px; - height: 48px; - } - } - - &-title { - font-size: 24px; - font-weight: 500; - color: #1A1A1A; - margin: 0 0 12px 0; - } - - &-description { - font-size: 16px; - line-height: 1.5; - color: #666666; - height: 20vh; - max-width: 450px; - } - - &-suggestions { - margin-top: 16px; - width: 100%; - - &-title { - font-size: 16px; - font-weight: 500; - color: #1A1A1A; - margin: 0 0 16px 0; - } - - &-grid { - display: grid; - grid-template-columns: 1fr 1fr; - justify-items: left; // Center items horizontally - gap: 8px; - - // Ensure each grid cell only takes the width it needs - & > * { - width: 100%; - min-width: min-content; - } - @media (max-width: 480px) { - grid-template-columns: 1fr; - } - } - } + display: contents; } &__loading { @@ -235,36 +149,26 @@ } &__messages { - // display: flex; + margin: 0 auto; flex-direction: column; - // flex: 1 1 auto; overflow-y: auto; - width: 100%; - padding-top: 16px; - min-height: 0; // Required for flexbox scroll - max-height: 100%; // Ensures it doesn't overflow the parent - - @media (max-width: 768px) { - padding: 16px; + width: 55%; + @media (max-width:$vf-breakpoint--md) { + width: 95%; + } + @media (max-width: 600px) { + width: 88%; } } &__disclaimer { - max-width: 51%; - width: max-content; - display: flex; - justify-content: flex-end; - flex-direction: column; - align-items: center; - position: absolute; - bottom: 0px; - z-index: 1000; - padding-bottom: 4%; + margin: 0 auto; + width: 55%; @media (max-width:$vf-breakpoint--md) { - max-width: 85%; + width: 95%; } @media (max-width: 600px) { - max-width: 75%; + width: 88%; } } } @@ -310,13 +214,6 @@ } } -.vf-chatbot-standalone__welcome-logo img { - width: 64px; - height: 64px; - margin-bottom: 16px; - object-fit: contain; -} - .vf-chatbot-message--user { max-width: 85%; display: grid; diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.scss b/components/vf-chatbot-welcome/vf-chatbot-welcome.scss index bf53958ae3..bb22047b3c 100644 --- a/components/vf-chatbot-welcome/vf-chatbot-welcome.scss +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.scss @@ -1,18 +1,17 @@ .vf-chatbot-welcome { - width: 100%; + margin: 0 auto; + width: 55%; &__content { - // width: 100%; text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; - height: 100%; + min-height: 40vh; } &__logo { - // margin-bottom: 16px; img { width: 64px; @@ -118,8 +117,10 @@ } } + @media (max-width:$vf-breakpoint--md) { + width: 95%; + } @media (max-width: 600px) { - display: flex; - flex-direction: column; + width: 88%; } } diff --git a/tools/vf-component-library/src/site/chatbot/index.njk b/tools/vf-component-library/src/site/chatbot/index.njk index 4e8af01a8a..1d9a6597cd 100644 --- a/tools/vf-component-library/src/site/chatbot/index.njk +++ b/tools/vf-component-library/src/site/chatbot/index.njk @@ -34,7 +34,7 @@ }); - + -
    -
    -

    AI Assistant

    - -

    -
    -
    {% render '@vf-chatbot-standalone', { title: "AI Assistant", welcome_title: "AI assistant", From 1a53e32933584fabbd553bd62062e0c0e8625d0b Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Sat, 21 Jun 2025 23:40:51 +0100 Subject: [PATCH 16/71] VF Chatbot : Updates as per feedback --- .../vf-chatbot-feedback.config.yml | 24 +- .../vf-chatbot-feedback.njk | 2 +- .../vf-chatbot-selector.js | 256 ++++++++++++++---- .../vf-chatbot-selector.njk | 1 + .../vf-chatbot-standalone.config.yml | 1 + .../vf-chatbot-standalone.njk | 8 +- .../vf-chatbot-standalone.scss | 13 + .../assets/vf-chatbot-selector-services.json | 37 +-- 8 files changed, 251 insertions(+), 91 deletions(-) diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml b/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml index 8050ebdb2d..8419b4958d 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.config.yml @@ -2,21 +2,23 @@ title: Chatbot Feedback Form variants: - name: positive context: - title: "What did you like about this response?" options: - id: "accurate" - label: "It's accurate" + label: "Accurate answer" + - id: "easy" + label: "Easy to understand" + - id: "formatted" + label: "Well formatted" - id: "helpful" - label: "It's helpful" - - id: "clear" - label: "It's clear" + label: "Helpful" - name: negative context: - title: "What was the issue with this response?" options: - id: "inaccurate" - label: "It's inaccurate" - - id: "unhelpful" - label: "It's not helpful" - - id: "offensive" - label: "It's offensive or unsafe" + label: "Inaccurate answer" + - id: "nocontext" + label: "Did not use context" + - id: "poorformat" + label: "Poorly formatted" + - id: "nothelpful" + label: "Not helpful" diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.njk b/components/vf-chatbot-feedback/vf-chatbot-feedback.njk index 29e48360c8..d85aaa23c2 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.njk +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.njk @@ -11,7 +11,7 @@
    {% for option in options %} - {% endfor %} diff --git a/components/vf-chatbot-selector/vf-chatbot-selector.js b/components/vf-chatbot-selector/vf-chatbot-selector.js index c92beb3f1b..0963169662 100644 --- a/components/vf-chatbot-selector/vf-chatbot-selector.js +++ b/components/vf-chatbot-selector/vf-chatbot-selector.js @@ -47,7 +47,7 @@ export class VFChatbotSelector { this.searchEl = this.el.querySelector("[data-vf-js-selector-search]"); this.clearEl = this.el.querySelector("[data-vf-js-selector-clear]"); this.listItems = this.el.querySelectorAll("[data-vf-js-selector-item]"); - this.allServicesItem = this.el.querySelector('[data-route-id="all"]'); // "All services" item + this.allServicesItem = this.el.querySelector('[data-route-id="all"]'); // Initialize dropdown as closed if (this.dropdownEl) { @@ -57,24 +57,36 @@ export class VFChatbotSelector { // Bind events this.bindEvents(); - // Initialize selected items and update display - let initSelection = false; + // Check if any items are pre-selected (not including "All services") + let hasPreSelectedItems = false; this.listItems.forEach(item => { + const itemId = item.getAttribute("data-route-id"); if (item.classList.contains("vf-chatbot-selector__item--selected")) { - this.selectedItems.add(item.getAttribute("data-route-id")); - initSelection = true; + if (itemId !== "all") { + // Only count non-"All services" items as pre-selected + this.selectedItems.add(itemId); + hasPreSelectedItems = true; + } } }); - // Initialize with "All services" if no selection - const hasSelectedItems = Array.from(this.listItems).some( - item => - item !== this.allServicesItem && - item.classList.contains("vf-chatbot-selector__item--selected") - ); - - if (!hasSelectedItems) { + // If no items are pre-selected, default to "All services" + if (!hasPreSelectedItems && this.showAllServices) { this.selectAllServices(); + } else if (!hasPreSelectedItems && !this.showAllServices) { + // If no "All services" option and no pre-selection, select first item for single-select + if (!this.isMultiselect && this.listItems.length > 0) { + const firstItem = this.listItems[0]; + const firstItemId = firstItem.getAttribute("data-route-id"); + this.selectedItems.add(firstItemId); + firstItem.classList.add("vf-chatbot-selector__item--selected"); + } + } else if (hasPreSelectedItems) { + // If items are pre-selected, ensure "All services" is not selected + this.allServicesSelected = false; + if (this.allServicesItem) { + this.allServicesItem.classList.remove("vf-chatbot-selector__item--selected"); + } } // Update display after initial selection @@ -88,6 +100,10 @@ export class VFChatbotSelector { // Clear existing list listEl.innerHTML = ""; + + // Check if any routes have pre-selected state + const hasPreSelectedRoutes = this.routes.some(route => route.selected); + // Add "All services" option if enabled if (this.showAllServices) { const allServicesItem = document.createElement("li"); @@ -95,24 +111,33 @@ export class VFChatbotSelector { allServicesItem.setAttribute("data-vf-js-selector-item", ""); allServicesItem.setAttribute("data-route-id", "all"); allServicesItem.setAttribute("data-title", "All services"); - if (this.showAllServicesSelected) { + + if (!hasPreSelectedRoutes && this.showAllServicesSelected) { allServicesItem.className += " vf-chatbot-selector__item--selected"; allServicesItem.setAttribute("data-selected", "true"); } + allServicesItem.innerHTML = `
    All services
    This would select all services
    - `; + + + + + `; listEl.appendChild(allServicesItem); } + // Add route items this.routes.forEach(route => { const item = document.createElement("li"); item.className = "vf-chatbot-selector__item"; - if (!this.showAllServices && route.selected) { + + if (route.selected) { item.className += " vf-chatbot-selector__item--selected"; } + item.setAttribute("data-vf-js-selector-item", ""); item.setAttribute("data-route-id", route.id); item.setAttribute("data-title", route.title); @@ -126,70 +151,128 @@ export class VFChatbotSelector { : "" }
    - `; + + + + + `; listEl.appendChild(item); }); - // Re-bind events after updating list + // Update references and re-bind events ONCE this.listItems = this.el.querySelectorAll("[data-vf-js-selector-item]"); this.allServicesItem = this.el.querySelector('[data-route-id="all"]'); - this.bindEvents(); + + // Only bind list item events (don't call full bindEvents or init) + this.bindListItemEvents(); + + // Handle initial selections for loaded routes + this.handleInitialSelections(); + } + + // New method to bind only list item events + bindListItemEvents() { + this.listItems.forEach(item => { + // Remove any existing listeners first + item.removeEventListener("click", this.itemClickHandler); + + // Create bound handler + this.itemClickHandler = (e) => { + e.stopPropagation(); + this.handleItemSelection(item); + }; + + // Add new listener + item.addEventListener("click", this.itemClickHandler); + }); } + // New method to handle initial selections without re-binding events + handleInitialSelections() { + // Don't reset the selectedItems Set here - it may already have pre-selected items + let hasPreSelectedItems = this.selectedItems.size > 0; // Check existing selectedItems first + + // Also check DOM for any additional pre-selected items + this.listItems.forEach(item => { + const itemId = item.getAttribute("data-route-id"); + if (item.classList.contains("vf-chatbot-selector__item--selected")) { + if (itemId !== "all") { + this.selectedItems.add(itemId); + hasPreSelectedItems = true; + } + } + }); + + // Set default selections only if no items are pre-selected + if (!hasPreSelectedItems && this.showAllServices && this.showAllServicesSelected) { + this.selectAllServices(); + } else if (hasPreSelectedItems) { + // If items are pre-selected, ensure "All services" is not selected + this.allServicesSelected = false; + if (this.allServicesItem) { + this.allServicesItem.classList.remove("vf-chatbot-selector__item--selected"); + } + } + + // Update display + this.updateSelectionDisplay(); + this.updateClearButton(); + } + + // Update bindEvents to store handlers for cleanup bindEvents() { // Toggle dropdown if (this.titleEl) { - // Remove any existing listeners first this.titleEl.removeEventListener("click", this.toggleDropdownHandler); - - // Create a bound handler that we can reference later this.toggleDropdownHandler = e => { - e.preventDefault(); // Prevent default behavior - e.stopImmediatePropagation(); // Stop multiple event triggers + e.preventDefault(); + e.stopImmediatePropagation(); this.toggleDropdown(); }; - - // Add the new listener this.titleEl.addEventListener("click", this.toggleDropdownHandler); } // Search functionality if (this.searchEl) { - this.searchEl.addEventListener("input", e => { + this.searchEl.removeEventListener("input", this.searchHandler); + this.searchHandler = e => { e.stopPropagation(); this.handleSearch(e.target.value); - }); + }; + this.searchEl.addEventListener("input", this.searchHandler); } // Clear all selections if (this.clearEl) { - this.clearEl.addEventListener("click", e => { + this.clearEl.removeEventListener("click", this.clearHandler); + this.clearHandler = e => { e.preventDefault(); e.stopPropagation(); this.clearAllSelections(); - }); + }; + this.clearEl.addEventListener("click", this.clearHandler); } - // List item selection - this.listItems.forEach(item => { - item.addEventListener("click", e => { - e.stopPropagation(); - this.handleItemSelection(item); - }); - }); + // Bind list items + this.bindListItemEvents(); - // Close dropdown when clicking outside - document.addEventListener("click", e => { - if (!this.el.contains(e.target)) { - this.closeDropdown(); - } - }); + // Document click handler (only add once) + if (!this.documentClickHandler) { + this.documentClickHandler = e => { + if (!this.el.contains(e.target)) { + this.closeDropdown(); + } + }; + document.addEventListener("click", this.documentClickHandler); + } - // Prevent dropdown from closing when clicking inside - this.dropdownEl?.addEventListener("click", e => { - e.stopPropagation(); - }); + // Dropdown click handler + if (this.dropdownEl) { + this.dropdownEl.removeEventListener("click", this.dropdownClickHandler); + this.dropdownClickHandler = e => e.stopPropagation(); + this.dropdownEl.addEventListener("click", this.dropdownClickHandler); + } } toggleDropdown() { @@ -217,9 +300,10 @@ export class VFChatbotSelector { const title = item .querySelector(".vf-chatbot-selector__item-title") .textContent.toLowerCase(); - const description = item - .querySelector(".vf-chatbot-selector__item-description") - .textContent.toLowerCase(); + + const descriptionEl = item.querySelector(".vf-chatbot-selector__item-description"); + const description = descriptionEl ? descriptionEl.textContent.toLowerCase() : ""; + const matches = title.includes(searchQuery) || description.includes(searchQuery); item.style.display = matches ? "flex" : "none"; @@ -286,16 +370,82 @@ export class VFChatbotSelector { this.dispatchSelectionEvent(); } + handleItemClick(item) { + const itemId = item.getAttribute("data-route-id"); + + if (itemId === "all") { + // Handle "All services" selection + this.selectAllServices(); + } else { + // Handle individual item selection + if (this.isMultiselect) { + // Multi-select logic + if (this.selectedItems.has(itemId)) { + // Deselect item + this.selectedItems.delete(itemId); + item.classList.remove("vf-chatbot-selector__item--selected"); + } else { + // Select item and ensure we don't exceed max selection + if (this.selectedItems.size < this.maxMultiSelect) { + this.selectedItems.add(itemId); + item.classList.add("vf-chatbot-selector__item--selected"); + } + } + + // If we deselected all individual items, select "All services" + if (this.selectedItems.size === 0 && this.showAllServices) { + this.selectAllServices(); + } else { + // Deselect "All services" when individual items are selected + this.allServicesSelected = false; + if (this.allServicesItem) { + this.allServicesItem.classList.remove("vf-chatbot-selector__item--selected"); + } + } + } else { + // Single-select logic + // Clear all previous selections + this.selectedItems.clear(); + this.listItems.forEach(li => { + li.classList.remove("vf-chatbot-selector__item--selected"); + }); + + // Select the clicked item + this.selectedItems.add(itemId); + item.classList.add("vf-chatbot-selector__item--selected"); + + // Deselect "All services" + this.allServicesSelected = false; + + // Close dropdown for single-select + this.closeDropdown(); + } + } + + // Update display and clear button + this.updateSelectionDisplay(); + this.updateClearButton(); + } + selectAllServices() { - // Clear all selections + if (!this.showAllServices) return; + + // Clear individual selections this.selectedItems.clear(); + + // Remove selected class from all individual items this.listItems.forEach(item => { - item.classList.remove("vf-chatbot-selector__item--selected"); + const itemId = item.getAttribute("data-route-id"); + if (itemId !== "all") { + item.classList.remove("vf-chatbot-selector__item--selected"); + } }); // Select "All services" this.allServicesSelected = true; - this.allServicesItem?.classList.add("vf-chatbot-selector__item--selected"); + if (this.allServicesItem) { + this.allServicesItem.classList.add("vf-chatbot-selector__item--selected"); + } } clearAllSelections() { diff --git a/components/vf-chatbot-selector/vf-chatbot-selector.njk b/components/vf-chatbot-selector/vf-chatbot-selector.njk index 056d8c2d58..d201d77767 100644 --- a/components/vf-chatbot-selector/vf-chatbot-selector.njk +++ b/components/vf-chatbot-selector/vf-chatbot-selector.njk @@ -7,6 +7,7 @@ data-max-multiselect="{{ chatbotRoutes.maxMultiSelect | default(1) }}" data-show-search="{{ chatbotRoutes.showSearch | default(true) }}" data-show-all-services="{{ chatbotRoutes.showAllServices | default(false) }}" + data-show-all-services-selected="{{ chatbotRoutes.showAllServicesSelected | default(false)}}" {% endif %} >
    + {% if footnote %} +
    + {{ footnote }} +
    + {% endif %} + - {% if prompts and prompts.length > 0 %} + + +
    diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.js b/components/vf-chatbot-welcome/vf-chatbot-welcome.js index b7adf1e3b2..851d051e72 100644 --- a/components/vf-chatbot-welcome/vf-chatbot-welcome.js +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.js @@ -46,20 +46,23 @@ export class VFChatbotWelcome { .sort(() => 0.5 - Math.random()) .slice(0, 3); - // Create suggestion elements + // Create suggestion elements using template-based rendering randomQuestions.forEach((question, index) => { - const suggestionEl = document.createElement("div"); - suggestionEl.className = `vf-chatbot-action-prompt`; - suggestionEl.setAttribute( - "data-vf-js-chatbot-welcome-suggestion", - question - ); + const suggestionTemplate = document.querySelector('#welcome-suggestion-template'); + if (suggestionTemplate) { + const suggestionEl = suggestionTemplate.content.cloneNode(true); + const link = suggestionEl.querySelector('.vf-chatbot-action-prompt__link'); + const wrapper = suggestionEl.querySelector('.vf-chatbot-action-prompt'); - suggestionEl.innerHTML = ` - ${question} - `; + if (link && wrapper) { + link.textContent = question; + wrapper.setAttribute('data-vf-js-chatbot-welcome-suggestion', question); - this.suggestionsGrid.appendChild(suggestionEl); + this.suggestionsGrid.appendChild(suggestionEl); + } + } else { + console.warn('Welcome suggestion template not found'); + } }); } @@ -99,7 +102,7 @@ export class VFChatbotWelcome { bubbles: true, detail: { question, - answer: answer.answer || answer.html, + answer: answer.answer || '', sources: answer.sources || [], prompts: answer.prompts || [] } diff --git a/components/vf-chatbot-welcome/vf-chatbot-welcome.njk b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk index 6e6ec117bd..283593eff0 100644 --- a/components/vf-chatbot-welcome/vf-chatbot-welcome.njk +++ b/components/vf-chatbot-welcome/vf-chatbot-welcome.njk @@ -11,7 +11,15 @@

    Try asking me:

    - +
    + + +
    diff --git a/components/vf-chatbot/assets/vf-chatbot-qa.json b/components/vf-chatbot/assets/vf-chatbot-qa.json index c48e99e7a2..1b07dbdaf5 100644 --- a/components/vf-chatbot/assets/vf-chatbot-qa.json +++ b/components/vf-chatbot/assets/vf-chatbot-qa.json @@ -1,7 +1,7 @@ { "predefinedQA": { "What is Metabolights?": { - "html": "
    MetaboLights is an open access repository for metabolomics studies, including raw experimental data and associated metadata.
    \n
    To know more:
    \n
      \n
    1. \n Methods and resources for omics studies: A curated collection of EMBL-EBI on-demand training.\n
    2. \n
    3. \n MetaboLights: Quick tour.\n
    4. \n
    5. \n Chemical biology: A curated set of EMBL-EBI online courses.\n
    6. \n
    " + "answer": "
    MetaboLights is an open access repository for metabolomics studies, including raw experimental data and associated metadata.
    \n
    To know more:
    \n
      \n
    1. \n Methods and resources for omics studies: A curated collection of EMBL-EBI on-demand training.\n
    2. \n
    3. \n MetaboLights: Quick tour.\n
    4. \n
    5. \n Chemical biology: A curated set of EMBL-EBI online courses.\n
    6. \n
    " }, "What training courses are available for metabolomics?": { "answer": "Metabolomics Training Courses\n\nWe offer comprehensive metabolomics training courses ranging from introductory to advanced levels:\n\n- Data analysis workshops\n- Practical lab sessions\n- Online self-paced modules", diff --git a/components/vf-componenet-rollup/scripts.js b/components/vf-componenet-rollup/scripts.js index b6c555f997..4f91415e11 100644 --- a/components/vf-componenet-rollup/scripts.js +++ b/components/vf-componenet-rollup/scripts.js @@ -76,7 +76,6 @@ vfTable(); import { initVFChatbot } from 'vf-chatbot/vf-chatbot.js'; import { initVFChatbotModal } from 'vf-chatbot-modal/vf-chatbot-modal.js'; import { initVFChatbotStandalone } from 'vf-chatbot-standalone/vf-chatbot-standalone.js'; -import { initVFChatbotActionPrompt } from 'vf-chatbot-action-prompt/vf-chatbot-action-prompt.js'; import { initVFChatbotFab } from 'vf-chatbot-fab/vf-chatbot-fab.js'; import { initVFChatbotWelcome } from 'vf-chatbot-welcome/vf-chatbot-welcome.js'; import { initVFChatbotPrompt } from 'vf-chatbot-prompt/vf-chatbot-prompt.js'; @@ -87,7 +86,6 @@ import { initVFChatbotSelector } from 'vf-chatbot-selector/vf-chatbot-selector.j document.addEventListener("DOMContentLoaded", () => { initVFChatbot(); initVFChatbotModal(); - initVFChatbotActionPrompt(); initVFChatbotFab(); initVFChatbotWelcome(); initVFChatbotPrompt(); diff --git a/tools/vf-component-library/src/site/chatbot/index.njk b/tools/vf-component-library/src/site/chatbot/index.njk index 1d9a6597cd..ae03980d96 100644 --- a/tools/vf-component-library/src/site/chatbot/index.njk +++ b/tools/vf-component-library/src/site/chatbot/index.njk @@ -15,11 +15,6 @@ if (typeof window.initVFChatbotStandalone === "function") { window.initVFChatbotStandalone(); - // Initialize supporting components only once - //["initVFChatbotActionPrompt", "initVFChatbotWelcome", "initVFChatbotPrompt"].forEach(fn => { - // if (typeof window[fn] === "function") window[fn](); - //}); - return true; } return false; @@ -59,5 +54,6 @@
    + From 38877ee2608be66ca8f3f60e085467c38439bdc9 Mon Sep 17 00:00:00 2001 From: Bhushan Palsapure Date: Sun, 22 Jun 2025 18:16:01 +0100 Subject: [PATCH 18/71] VF Chatbot : Updates as per feedback --- .../vf-chatbot-feedback.scss | 1 - components/vf-chatbot-prompt/package.json | 3 +- .../vf-chatbot-prompt/vf-chatbot-prompt.js | 108 ++++++++--------- .../vf-chatbot-prompt/vf-chatbot-prompt.njk | 26 ++-- .../vf-chatbot-prompt/vf-chatbot-prompt.scss | 93 +++++--------- .../vf-chatbot-sources/vf-chatbot-sources.js | 19 ++- .../vf-chatbot-sources.scss | 63 +++------- .../vf-chatbot-standalone.js | 81 ++++++++----- .../vf-chatbot-standalone.njk | 26 ++-- .../vf-chatbot-standalone.scss | 113 ------------------ .../vf-chatbot/assets/vf-chatbot-qa.json | 2 +- components/vf-componenet-rollup/index.scss | 4 +- components/vf-componenet-rollup/scripts.js | 5 +- 13 files changed, 190 insertions(+), 354 deletions(-) diff --git a/components/vf-chatbot-feedback/vf-chatbot-feedback.scss b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss index 0cdc4f151e..a8b8c8bb4d 100644 --- a/components/vf-chatbot-feedback/vf-chatbot-feedback.scss +++ b/components/vf-chatbot-feedback/vf-chatbot-feedback.scss @@ -1,5 +1,4 @@ .vf-chatbot-feedback { - margin-top: 1rem; font-family: inherit; &__actions { diff --git a/components/vf-chatbot-prompt/package.json b/components/vf-chatbot-prompt/package.json index 56b9f25d0d..96a229ffdc 100644 --- a/components/vf-chatbot-prompt/package.json +++ b/components/vf-chatbot-prompt/package.json @@ -7,8 +7,7 @@ "license": "Apache 2.0", "style": "vf-chatbot-prompt.css", "sass": "index.scss", - "main": "vf-chatbot-prompt.js", "dependencies": { "@visual-framework/vf-sass-config": "file:../vf-sass-config" } -} \ No newline at end of file +} diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.js b/components/vf-chatbot-prompt/vf-chatbot-prompt.js index 76ce4aa01b..f0aa436da7 100644 --- a/components/vf-chatbot-prompt/vf-chatbot-prompt.js +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.js @@ -1,68 +1,68 @@ -// vf-chatbot-prompt +// // vf-chatbot-prompt -function VFChatbotPrompt(element) { - this.el = element; - this.loading = false; -} +// function VFChatbotPrompt(element) { +// this.el = element; +// this.loading = false; +// } -VFChatbotPrompt.prototype = { - setLoading: function(isLoading) { - this.loading = isLoading; +// VFChatbotPrompt.prototype = { +// setLoading: function(isLoading) { +// this.loading = isLoading; - if (isLoading) { - // Remove existing loading element if any - this.removeLoading(); +// if (isLoading) { +// // Remove existing loading element if any +// this.removeLoading(); - // Create loading element - const loadingEl = document.createElement("div"); - loadingEl.className = "vf-chatbot-prompt__loading"; - loadingEl.innerHTML = ` - - - - `; +// // Create loading element +// const loadingEl = document.createElement("div"); +// loadingEl.className = "vf-chatbot-prompt__loading"; +// loadingEl.innerHTML = ` +// +// +// +// `; - this.el.appendChild(loadingEl); - } else { - this.removeLoading(); - } - }, +// this.el.appendChild(loadingEl); +// } else { +// this.removeLoading(); +// } +// }, - removeLoading: function() { - const loadingEl = this.el.querySelector(".vf-chatbot-prompt__loading"); - if (loadingEl) { - loadingEl.remove(); - } - }, +// removeLoading: function() { +// const loadingEl = this.el.querySelector(".vf-chatbot-prompt__loading"); +// if (loadingEl) { +// loadingEl.remove(); +// } +// }, - setResponse: function(html) { - // Remove loading first - this.setLoading(false); +// setResponse: function(html) { +// // Remove loading first +// this.setLoading(false); - // Create response element - const responseEl = document.createElement("div"); - responseEl.className = - "vf-chatbot-prompt__message vf-chatbot-prompt__message--system"; - responseEl.innerHTML = html; +// // Create response element +// const responseEl = document.createElement("div"); +// responseEl.className = +// "vf-chatbot-prompt__message vf-chatbot-prompt__message--system"; +// responseEl.innerHTML = html; - this.el.appendChild(responseEl); - } -}; +// this.el.appendChild(responseEl); +// } +// }; -function initVFChatbotPrompt(message) { - const el = document.createElement("div"); - el.className = "vf-chatbot-prompt"; - el.setAttribute("data-vf-js-chatbot-prompt", ""); +// function initVFChatbotPrompt(message) { +// const el = document.createElement("div"); +// el.className = "vf-chatbot-prompt"; +// el.setAttribute("data-vf-js-chatbot-prompt", ""); - const messageEl = document.createElement("div"); - messageEl.className = - "vf-chatbot-prompt__message vf-chatbot-prompt__message--user"; - messageEl.textContent = message; +// const messageEl = document.createElement("div"); +// messageEl.className = +// "vf-chatbot-prompt__message vf-chatbot-prompt__message--user"; +// messageEl.textContent = message; - el.appendChild(messageEl); +// el.appendChild(messageEl); - const prompt = new VFChatbotPrompt(el); - return prompt; -} +// const prompt = new VFChatbotPrompt(el); +// return prompt; +// } -export { VFChatbotPrompt, initVFChatbotPrompt }; +// export { VFChatbotPrompt, initVFChatbotPrompt }; diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.njk b/components/vf-chatbot-prompt/vf-chatbot-prompt.njk index e0565a2bc0..dbb051d534 100644 --- a/components/vf-chatbot-prompt/vf-chatbot-prompt.njk +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.njk @@ -1,33 +1,23 @@
    - {% if type == "user" and avatar and avatar.name %} + {% if avatar and avatar.name and type === 'user' %} {{ avatar.name }} {% endif %} {% if avatar and avatar.src %} {{ avatar.alt }} {% endif %} - {% if type == "assistant" and avatar and avatar.name %} + {% if avatar and avatar.name and type === 'assistant' %} {{ avatar.name }} {% endif %}
    -
    +
    {% if isLoading %} -
    +
    + ... +
    {% else %} - {{ content | safe }} - {% endif %} - - {# Render sources if present #} - {% if sources and sources.length > 0 %} - {% render "@vf-chatbot-sources", { sources: sources } %} - {% endif %} - - {# Render prompts if present #} - {% if prompts and prompts.length > 0 %} -
    - {% for prompt in prompts %} - {% render "@vf-chatbot-prompt", prompt %} - {% endfor %} +
    + {{ content | safe }}
    {% endif %}
    diff --git a/components/vf-chatbot-prompt/vf-chatbot-prompt.scss b/components/vf-chatbot-prompt/vf-chatbot-prompt.scss index 7f31a20a2f..7b3f5926bc 100644 --- a/components/vf-chatbot-prompt/vf-chatbot-prompt.scss +++ b/components/vf-chatbot-prompt/vf-chatbot-prompt.scss @@ -1,80 +1,41 @@ -.vf-chatbot-prompt { - display: flex; - flex-direction: column; - gap: 8px; - margin-bottom: 16px; +.vf-chatbot-message { - &__message { - padding: 12px 16px; - border-radius: 12px; - max-width: 80%; - line-height: 1.4; - - &--user { - background: var(--vf-color-gray-100); - align-self: flex-end; - } - - &--system { - background: var(--vf-color-primary-light); - align-self: flex-start; - - // Style for rich text content - p { - margin: 0 0 8px 0; - &:last-child { - margin-bottom: 0; - } - } - - code { - background: rgba(0, 0, 0, 0.05); - padding: 2px 4px; - border-radius: 4px; - } - - pre { - background: rgba(0, 0, 0, 0.05); - padding: 8px; - border-radius: 4px; - overflow-x: auto; - } - } + &__avatar { + @include set-type(text-body--5); + display: flex; + align-items: center; + gap: 8px; } - &__loading { - align-self: flex-start; - display: flex; - gap: 4px; - padding: 12px 16px; - background: var(--vf-color-primary-light); - border-radius: 12px; - border-bottom-left-radius: 4px; + &__content { + @include set-type(text-body--3); + width: fit-content; + border-radius: $vf-radius--xs; } - &__dot { - width: 8px; - height: 8px; - background: var(--vf-color-gray-600); - border-radius: 50%; - opacity: 0.3; - animation: dot-flash 1.4s infinite; + &--user { + margin-left: auto; - &:nth-child(2) { - animation-delay: 0.2s; + .vf-chatbot-message__avatar { + justify-content: flex-end; } - &:nth-child(3) { - animation-delay: 0.4s; + .vf-chatbot-message__content { + background-color: var(--vf-color__text--primary); + color: var(--vf-color--neutral--0); } } -} -@keyframes dot-flash { - 0%, 60%, 100% { - opacity: 0.3; + &--assistant { + margin-right: auto; + + .vf-chatbot-message__content { + background-color: var(--vf-color--neutral--0); + color: var(--vf-color__text--primary); + } } - 30% { - opacity: 1; + + @media (max-width: 768px) { + max-width: 90%; } } diff --git a/components/vf-chatbot-sources/vf-chatbot-sources.js b/components/vf-chatbot-sources/vf-chatbot-sources.js index bb751be366..a2bf965664 100644 --- a/components/vf-chatbot-sources/vf-chatbot-sources.js +++ b/components/vf-chatbot-sources/vf-chatbot-sources.js @@ -14,7 +14,7 @@ function initVFChatbotSources(messages) {
  • ${message.domain}
    - ${message.title} + ${message.title}
    ${message.description}
  • @@ -62,6 +62,16 @@ function initVFChatbotSources(messages) {
    `; + // Helper function to scroll chat to bottom + function scrollChatToBottom() { + const messagesContainer = document.querySelector('[data-vf-js-chatbot-standalone-messages]'); + if (messagesContainer) { + setTimeout(() => { + messagesContainer.scrollTop = messagesContainer.scrollHeight; + }, 100); // Small delay to allow DOM updates + } + } + // Toggle logic const toggleBtn = el.querySelector("[data-vf-js-chatbot-sources-toggle]"); const sourcesDiv = el.querySelector("[data-vf-js-chatbot-sources]"); @@ -70,10 +80,17 @@ function initVFChatbotSources(messages) { toggleBtn.addEventListener("click", () => { sourcesDiv.classList.remove("vf-chatbot-sources--collapsed"); toggleBtn.style.display = "none"; + + // Scroll to bottom after expanding sources + scrollChatToBottom(); }); + hideBtn.addEventListener("click", () => { sourcesDiv.classList.add("vf-chatbot-sources--collapsed"); toggleBtn.style.display = ""; + + // Optional: scroll to bottom after collapsing as well + scrollChatToBottom(); }); return new VFChatbotSources(el); diff --git a/components/vf-chatbot-sources/vf-chatbot-sources.scss b/components/vf-chatbot-sources/vf-chatbot-sources.scss index 84544e304e..bb84bc9057 100644 --- a/components/vf-chatbot-sources/vf-chatbot-sources.scss +++ b/components/vf-chatbot-sources/vf-chatbot-sources.scss @@ -1,41 +1,30 @@ .vf-chatbot-sources-toggle { + @include set-type(text-body--4); width: 100%; text-align: left; - margin-top: 16px; } .vf-chatbot-sources__toggle-link { @extend .vf-link; + @include set-type(text-body--4); + margin-bottom: 0; gap: 10px; - line-height: 27.20px; background: #fff; border-radius: 2rem; padding: 2px 14px; - padding: 0.5rem 1.25rem; - font-size: 14px; - font-weight: 500; cursor: pointer; display: inline-flex; - // align-items: center; - border: none; - box-shadow: 0 1px 4px rgba(0,0,0,0.04); + border: 1px solid var(--vf-color--neutral--400) !important; transition: background 0.2s; align-items: flex-start; } -.vf-chatbot-sources__toggle-chevron { - font-size: 1.1em; - margin-left: 0.5em; - display: inline-block; - vertical-align: middle; -} - .vf-chatbot-sources { font-family: inherit; background: #ffffff; color: #666; - border-radius: 8px; - border: 1px solid #E5E5E5; + border-radius: $vf-radius--sm; + border: 1px solid var(--vf-color--neutral--400); transition: max-height 0.3s, opacity 0.3s; opacity: 1; max-height: 500px; @@ -52,15 +41,15 @@ padding: 8px 16px; display: flex; justify-content: flex-start; - margin-bottom: 0.5rem; } &__hide-link { @extend .vf-link; + @include set-type(text-body--4); + display: flex; + gap: 10px; background: none; border: none; - font-size: 0.95rem; - font-weight: 500; cursor: pointer; display: inline-flex; align-items: center; @@ -70,26 +59,17 @@ align-items: flex-start; } - &__hide-chevron { - font-size: 1.1em; - margin-left: 0.5em; - display: inline-block; - vertical-align: middle; - } - &__list { overflow-y: auto; - height: 20vh; list-style: none; padding: 0; margin: 0; } &__item { - padding: 16px; - padding-top: 0px; + padding: 0 16px; line-height: 1.5; - border-bottom: 1px solid #E5E5E5; + border-bottom: 1px solid var(--vf-color--neutral--400); word-wrap: break-word; &:last-child { @@ -99,27 +79,20 @@ } &__label { - color: #1A1C1A; - font-size: 14px; - font-weight: 400; + @include set-type(text-body--5); + margin-bottom: 0px; line-height: 27.20px; } &__link { - color: #3B6FB6; - font-size: 16px; - font-weight: 500; + @include set-type(text-body--3); + margin-bottom: 0; line-height: 22px; } &__description { - color: #373A36; - font-size: 14px; - font-weight: 400; - } - - &__title { - font-size: 1em; - word-break: break-word; + @include set-type(text-body--5); + color: var(--vf-color--neutral--800); + line-height: 22px; } } diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.js b/components/vf-chatbot-standalone/vf-chatbot-standalone.js index 457adfef65..59d085830c 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.js +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.js @@ -16,9 +16,6 @@ class VFChatbotStandalone { this.messagesContainer = this.container.querySelector( "[data-vf-js-chatbot-standalone-messages]" ); - this.loadingIndicator = this.container.querySelector( - "[data-vf-js-chatbot-standalone-loading]" - ); this.input = this.container.querySelector( "[data-vf-js-chatbot-standalone-input]" ); @@ -28,9 +25,7 @@ class VFChatbotStandalone { this.disclaimer = this.container.querySelector( "[data-vf-js-chatbot-standalone-disclaimer]" ); - this.disclaimerCloseBtn = this.disclaimer.querySelector( - ".vf-button--dismiss" - ); + this.disclaimerCloseBtn = this.disclaimer?.querySelector(".vf-button--dismiss"); // Selector element this.selectorEl = this.container.querySelector( @@ -165,7 +160,7 @@ class VFChatbotStandalone { sendUserMessage(text) { if (!text || !this.messagesContainer) return; const userMessage = this.userTemplate.content.cloneNode(true); - const content = userMessage.querySelector(".vf-chatbot-message__content"); + const content = userMessage.querySelector(".vf-chatbot-message__content-prompt"); // Set text content content.textContent = text; @@ -183,19 +178,22 @@ class VFChatbotStandalone { } processUserMessage(text) { - // Show loading state + // Show loading state immediately this.setLoadingState(true); // Check if we have a predefined answer if (this.qaData && this.qaData[text]) { - const response = this.qaData[text]; - this.addAssistantResponse( - response.answer || '', - response.sources || [], - response.prompts || [] - ); - this.setLoadingState(false); - this.scrollToBottom(); + // Add delay even for predefined answers to show loading indicator + setTimeout(() => { + const answer = this.qaData[text]; + this.addAssistantResponse( + answer.answer || answer.html, + answer.sources || [], + answer.prompts || [] + ); + this.setLoadingState(false); + this.scrollToBottom(); + }, 800); // 800ms delay for predefined answers return; } else if (this.callExternalAPI) { // Send custom event for external API call @@ -261,19 +259,22 @@ class VFChatbotStandalone { this.scrollToBottom(); } }, 10000); // 10 second timeout + } else { + // Add delay for fallback response as well + setTimeout(() => { + // Use random fallback response when API is not available + const fallbackResponse = this.fallbackResponses[ + Math.floor(Math.random() * this.fallbackResponses.length) + ]; + this.addAssistantResponse( + fallbackResponse["answer"], + [], + fallbackResponse["prompts"] || [] + ); + this.setLoadingState(false); + this.scrollToBottom(); + }, 600); // 600ms delay for fallback responses } - // Use random fallback response - const fallbackResponse = this.fallbackResponses[ - Math.floor(Math.random() * this.fallbackResponses.length) - ]; - this.addAssistantResponse( - fallbackResponse["answer"], - [], - fallbackResponse["prompts"] || [] - ); - this.setLoadingState(false); - this.scrollToBottom(); - return; } // Fix the addAssistantResponse method to avoid Nunjucks in JS @@ -281,7 +282,7 @@ class VFChatbotStandalone { if (!this.assistantTemplate || !this.messagesContainer) return; const assistantMessage = this.assistantTemplate.content.cloneNode(true); - const content = assistantMessage.querySelector(".vf-chatbot-message__content"); + const content = assistantMessage.querySelector(".vf-chatbot-message__content-prompt"); content.innerHTML = text; // Initialize the feedback component for this message @@ -344,10 +345,28 @@ class VFChatbotStandalone { } setLoadingState(isLoading) { - if (this.loadingIndicator) { - this.loadingIndicator.style.display = isLoading ? "flex" : "none"; + if (isLoading) { + // Create loading indicator from template if it doesn't exist + if (!this.loadingIndicator) { + const loadingTemplate = this.container.querySelector('#loading-indicator-template'); + if (loadingTemplate) { + const loadingContent = loadingTemplate.content.cloneNode(true); + this.loadingIndicator = loadingContent.firstElementChild; + this.messagesContainer.appendChild(this.loadingIndicator); + } else { + console.warn('Loading indicator template not found'); + return; + } + } + this.loadingIndicator.style.display = 'block'; + } else { + // Hide loading indicator + if (this.loadingIndicator) { + this.loadingIndicator.style.display = 'none'; + } } + // Disable/enable input controls if (this.sendBtn) { this.sendBtn.disabled = isLoading; } diff --git a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk index 6c8b93f242..e9eeb6b862 100644 --- a/components/vf-chatbot-standalone/vf-chatbot-standalone.njk +++ b/components/vf-chatbot-standalone/vf-chatbot-standalone.njk @@ -65,19 +65,7 @@
    - - - +
    {% if disclaimer %}
    @@ -151,10 +139,14 @@