From 404246000b6756761a3e3a664a9d192f1e2de07e Mon Sep 17 00:00:00 2001 From: Hamza Agar Date: Mon, 27 Jul 2026 20:15:35 +0300 Subject: [PATCH 1/2] feat(react): add @chativa/react wrapper package React wrapper for the Chativa chat widget: ChativaProvider, ChatIva, ChatBotButton, and GenUIMessage components built on @lit/react's createComponent, lazily loading @chativa/ui / @chativa/genui on the client only so the package is SSR-safe (no window/document at module scope, "use client" preserved through the bundler). Adds examples/react-vite as a living usage doc: ChativaProvider + a custom ChatBotButton launcher element, plus two custom GenUI components (a display-only weather card and an interactive poll using sendEvent) to demonstrate the component authoring pattern. Closes #1 Co-Authored-By: Claude Sonnet 5 --- .github/workflows/release.yml | 6 + examples/react-vite/index.html | 12 + examples/react-vite/package.json | 28 + examples/react-vite/src/App.tsx | 139 ++++ examples/react-vite/src/CustomPollCard.ts | 118 ++++ examples/react-vite/src/CustomWeatherCard.ts | 122 ++++ examples/react-vite/src/index.css | 59 ++ examples/react-vite/src/main.tsx | 13 + examples/react-vite/src/vite-env.d.ts | 1 + examples/react-vite/tsconfig.json | 14 + examples/react-vite/vite.config.ts | 19 + packages/react/package.json | 72 ++ packages/react/src/ChatBotButton.tsx | 48 ++ packages/react/src/ChatIva.tsx | 135 ++++ packages/react/src/ChativaProvider.tsx | 80 +++ packages/react/src/GenUIMessage.tsx | 57 ++ packages/react/src/__tests__/ChatIva.test.tsx | 116 ++++ .../src/__tests__/ChativaProvider.test.tsx | 97 +++ packages/react/src/hooks/useChativaEvent.ts | 31 + packages/react/src/index.ts | 42 ++ .../internal/createLazyElementComponent.tsx | 42 ++ packages/react/src/internal/loadChativaUi.ts | 21 + .../react/src/internal/resolveConnector.ts | 19 + packages/react/src/vite-env.d.ts | 1 + packages/react/tsconfig.json | 20 + packages/react/vite.config.ts | 36 + packages/react/vitest.config.ts | 24 + pnpm-lock.yaml | 642 +++++++++++++----- pnpm-workspace.yaml | 1 + tsconfig.json | 3 + 30 files changed, 1862 insertions(+), 156 deletions(-) create mode 100644 examples/react-vite/index.html create mode 100644 examples/react-vite/package.json create mode 100644 examples/react-vite/src/App.tsx create mode 100644 examples/react-vite/src/CustomPollCard.ts create mode 100644 examples/react-vite/src/CustomWeatherCard.ts create mode 100644 examples/react-vite/src/index.css create mode 100644 examples/react-vite/src/main.tsx create mode 100644 examples/react-vite/src/vite-env.d.ts create mode 100644 examples/react-vite/tsconfig.json create mode 100644 examples/react-vite/vite.config.ts create mode 100644 packages/react/package.json create mode 100644 packages/react/src/ChatBotButton.tsx create mode 100644 packages/react/src/ChatIva.tsx create mode 100644 packages/react/src/ChativaProvider.tsx create mode 100644 packages/react/src/GenUIMessage.tsx create mode 100644 packages/react/src/__tests__/ChatIva.test.tsx create mode 100644 packages/react/src/__tests__/ChativaProvider.test.tsx create mode 100644 packages/react/src/hooks/useChativaEvent.ts create mode 100644 packages/react/src/index.ts create mode 100644 packages/react/src/internal/createLazyElementComponent.tsx create mode 100644 packages/react/src/internal/loadChativaUi.ts create mode 100644 packages/react/src/internal/resolveConnector.ts create mode 100644 packages/react/src/vite-env.d.ts create mode 100644 packages/react/tsconfig.json create mode 100644 packages/react/vite.config.ts create mode 100644 packages/react/vitest.config.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5a4eedf..ad462ee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -100,6 +100,12 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Publish @chativa/react + run: pnpm publish --access public --no-git-checks + working-directory: packages/react + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: diff --git a/examples/react-vite/index.html b/examples/react-vite/index.html new file mode 100644 index 0000000..39b544e --- /dev/null +++ b/examples/react-vite/index.html @@ -0,0 +1,12 @@ + + + + + + @chativa/react example + + +
+ + + diff --git a/examples/react-vite/package.json b/examples/react-vite/package.json new file mode 100644 index 0000000..e249cce --- /dev/null +++ b/examples/react-vite/package.json @@ -0,0 +1,28 @@ +{ + "name": "chativa-example-react-vite", + "private": true, + "version": "0.0.0", + "type": "module", + "description": "Living usage doc for @chativa/react — + wired to @chativa/connector-dummy.", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@chativa/connector-dummy": "workspace:*", + "@chativa/core": "workspace:*", + "@chativa/genui": "workspace:*", + "@chativa/react": "workspace:*", + "react": "^19.2.8", + "react-dom": "^19.2.8" + }, + "devDependencies": { + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^4.7.0", + "typescript": "~5.8.3", + "vite": "^7.0.3" + } +} diff --git a/examples/react-vite/src/App.tsx b/examples/react-vite/src/App.tsx new file mode 100644 index 0000000..7c2768a --- /dev/null +++ b/examples/react-vite/src/App.tsx @@ -0,0 +1,139 @@ +import { useCallback, useMemo } from "react"; +import { ChativaProvider, ChatIva, ChatBotButton } from "@chativa/react"; +import { DummyConnector } from "@chativa/connector-dummy"; +import { EventBus, chatStore, type ConnectorStatus } from "@chativa/core"; +// Side-effect imports: register the custom GenUI components (see those +// files for why they're plain HTMLElement, not Lit or React). +import "./CustomWeatherCard"; +import "./CustomPollCard"; + +/** + * `` is only the chat *panel* — it has no launcher of its own. + * `` is the toggle, and its default slot lets you swap the + * built-in gradient circle for a fully custom element. This is the "custom + * chatbot element" pattern: whatever you put inside `` becomes + * the launcher, while `` itself still handles positioning and + * the open/close click — you don't have to reimplement that part. + */ +function CustomLauncher() { + return ( + + ); +} + +export default function App() { + // A stable instance — re-creating the connector on every render would + // register a new one each time and throw ("already registered"). + // connectDelay: 0 skips DummyConnector's default 2s fake-handshake delay, + // since this demo's trigger button already waits for a real "connected" + // status rather than guessing at a timeout. + const dummy = useMemo(() => new DummyConnector({ replyDelay: 500, connectDelay: 0 }), []); + + // The chat engine only connects (and DummyConnector only registers its + // GenUI handler) once the panel has been opened at least once — that's + // when `` lazily calls `connector.connect()`. Open the panel and + // wait for `connector_status_changed: "connected"` before running `fn`, + // instead of guessing at a delay. + const runOnceConnected = useCallback((fn: () => void) => { + if (chatStore.getState().connectorStatus === "connected") { + fn(); + chatStore.getState().open(); + return; + } + const onStatus = (payload: { status: ConnectorStatus }) => { + if (payload.status !== "connected") return; + EventBus.off("connector_status_changed", onStatus); + fn(); + }; + EventBus.on("connector_status_changed", onStatus); + chatStore.getState().open(); + }, []); + + const triggerWeatherDemo = useCallback(() => { + runOnceConnected(() => dummy.triggerGenUI("weather")); + }, [dummy, runOnceConnected]); + + // Unlike the weather demo (DummyConnector's own built-in stream), this + // builds the GenUI chunk list by hand and injects it directly — the + // question/options *payload* is passed in at the call site below, not + // hardcoded inside the component or a connector method. + const triggerPollDemo = useCallback( + (payload: { question: string; options: string[] }) => { + runOnceConnected(() => { + dummy.injectMessage({ + type: "genui", + from: "bot", + data: { + chunks: [{ type: "ui", component: "poll", props: payload, id: 1 }], + streamingComplete: true, + }, + }); + }); + }, + [dummy, runOnceConnected], + ); + + return ( + +
+

@chativa/react example

+

+ ChativaProvider registers the connector + theme once; + ChatBotButton renders a custom launcher element (see{" "} + CustomLauncher below) instead of the default icon;{" "} + ChatIva is the panel it opens. +

+

+ CustomWeatherCard is a custom GenUI component — a + plain Custom Element (no Lit, no React) registered via{" "} + GenUIRegistry.register("weather", ...). + Click below to open the chat and stream one in. +

+ +

+ CustomPollCard is a second, interactive custom GenUI + component — clicking an option calls the injected{" "} + sendEvent(), which reaches the connector via{" "} + ChatEngine.receiveComponentEvent(). +

+ +
+ + + + + + console.log("[chativa] message received:", message)} + onMessageSent={(message) => console.log("[chativa] message sent:", message)} + onWidgetOpen={() => console.log("[chativa] widget opened")} + onWidgetClose={() => console.log("[chativa] widget closed")} + /> +
+ ); +} diff --git a/examples/react-vite/src/CustomPollCard.ts b/examples/react-vite/src/CustomPollCard.ts new file mode 100644 index 0000000..fa753f6 --- /dev/null +++ b/examples/react-vite/src/CustomPollCard.ts @@ -0,0 +1,118 @@ +import { GenUIRegistry } from "@chativa/genui"; + +/** + * A second, distinct custom GenUI component — interactive rather than + * display-only like `CustomWeatherCard`. Demonstrates `sendEvent`, which + * `` injects onto every GenUI component instance right after + * constructing it (before props are assigned): calling it dispatches a + * `genui-send-event` DOM event that bubbles up through `` to + * `ChatEngine.receiveComponentEvent()` → `connector.receiveComponentEvent()` + * — the same path a real backend-driven form submit or button click uses. + * + * Also plain `HTMLElement` — see `CustomWeatherCard.ts` for why. + */ + +const STYLE = ` + :host { display: block; } + .card { + max-width: 280px; + padding: 16px 18px; + border-radius: 14px; + background: #ffffff; + border: 1px solid #e2e8f0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + } + .question { font-size: 0.9375rem; font-weight: 600; color: #0f172a; margin-bottom: 12px; } + .options { display: flex; flex-direction: column; gap: 8px; } + button.option { + text-align: left; + border: 1px solid #c7d2fe; + border-radius: 8px; + padding: 8px 12px; + background: #eef2ff; + color: #4338ca; + font-size: 0.875rem; + cursor: pointer; + } + button.option:hover { background: #e0e7ff; } + .voted { font-size: 0.875rem; color: #4338ca; } + .voted strong { color: #0f172a; } +`; + +/** Props assigned onto the instance — same shape as the `AIChunkUI.props` sent for this component. */ +interface PollProps { + question: string; + options: string[]; +} + +const DEFAULTS: PollProps = { question: "", options: [] }; + +export class CustomPollCard extends HTMLElement { + #state: PollProps = { ...DEFAULTS }; + #votedOption: string | null = null; + #root: ShadowRoot; + + /** Injected by `` right after construction — see the file doc comment. */ + sendEvent?: (type: string, payload: unknown) => void; + + constructor() { + super(); + this.#root = this.attachShadow({ mode: "open" }); + + for (const key of Object.keys(DEFAULTS) as (keyof PollProps)[]) { + Object.defineProperty(this, key, { + get: () => this.#state[key], + set: (value) => { + (this.#state[key] as unknown) = value; + this.#render(); + }, + }); + } + } + + connectedCallback() { + this.#render(); + } + + #vote(option: string) { + if (this.#votedOption) return; + this.#votedOption = option; + this.sendEvent?.("poll_vote", { option }); + this.#render(); + } + + #render() { + const { question, options } = this.#state; + + if (this.#votedOption) { + this.#root.innerHTML = `
Thanks for voting:
`; + this.#root.querySelector("strong")!.textContent = this.#votedOption; + return; + } + + this.#root.innerHTML = ` + +
+
+
+
+ `; + this.#root.querySelector(".question")!.textContent = question; + + const optionsEl = this.#root.querySelector(".options")!; + for (const option of options) { + const button = document.createElement("button"); + button.className = "option"; + button.type = "button"; + button.textContent = option; + button.addEventListener("click", () => this.#vote(option)); + optionsEl.appendChild(button); + } + } +} + +if (!customElements.get("demo-poll-card")) { + customElements.define("demo-poll-card", CustomPollCard); +} + +GenUIRegistry.register("poll", CustomPollCard); diff --git a/examples/react-vite/src/CustomWeatherCard.ts b/examples/react-vite/src/CustomWeatherCard.ts new file mode 100644 index 0000000..e85f760 --- /dev/null +++ b/examples/react-vite/src/CustomWeatherCard.ts @@ -0,0 +1,122 @@ +import { GenUIRegistry } from "@chativa/genui"; + +/** + * A custom Generative UI component written as a plain Custom Element — no + * Lit, no React. `GenUIRegistry.register()` only requires a `typeof + * HTMLElement`; the host (``, inside ``) constructs + * it with `new Ctor()` and assigns props as plain JS properties + * (`el.city = "Istanbul"`), not HTML attributes — so any class with that + * shape works, regardless of what framework (if any) built it. That's the + * point of this file: a GenUI component is authored once and renders the + * same way no matter what the *host* app is. + * + * `DummyConnector.triggerGenUI("weather")` (and the `/genui-weather` chat + * command) streams a `{ component: "weather", props: {...} }` chunk with + * exactly this shape, matching what a real backend would send. + */ + +const STYLE = ` + :host { display: block; } + .card { + max-width: 280px; + padding: 18px 20px; + border-radius: 14px; + background: linear-gradient(135deg, #0ea5e9 0%, #6366f1 100%); + color: white; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + box-shadow: 0 8px 24px rgba(14, 165, 233, 0.35); + } + .location { font-size: 0.8125rem; opacity: 0.85; margin-bottom: 8px; } + .temp { font-size: 2.75rem; font-weight: 700; line-height: 1; } + .condition { margin-top: 4px; font-size: 0.9375rem; opacity: 0.9; } + .stats { margin-top: 12px; display: flex; gap: 16px; font-size: 0.75rem; opacity: 0.85; } +`; + +interface WeatherProps { + city: string; + country: string; + temp: number; + unit: string; + condition: string; + humidity: number; + wind: number; +} + +const DEFAULTS: WeatherProps = { + city: "", + country: "", + temp: 0, + unit: "C", + condition: "", + humidity: 0, + wind: 0, +}; + +export class CustomWeatherCard extends HTMLElement { + #state: WeatherProps = { ...DEFAULTS }; + #els: { location: HTMLElement; temp: HTMLElement; condition: HTMLElement; humidity: HTMLElement; wind: HTMLElement }; + + constructor() { + super(); + const root = this.attachShadow({ mode: "open" }); + root.innerHTML = ` + +
+
+
+
+
+
+ `; + // Query once — re-used by every #render() call. Text is always set via + // `textContent` below (never innerHTML) so nothing here needs escaping, + // even though this demo's data happens to be trusted. + this.#els = { + location: root.querySelector(".location")!, + temp: root.querySelector(".temp")!, + condition: root.querySelector(".condition")!, + humidity: root.querySelector(".humidity")!, + wind: root.querySelector(".wind")!, + }; + + // Define an accessor per prop so `Object.assign(el, chunk.props)` — + // exactly what `` does to apply/update props — re-renders + // on every assignment, including later updates to an already-connected + // instance (e.g. a progressively streamed component, unlike this one-shot + // weather card). + for (const key of Object.keys(DEFAULTS) as (keyof WeatherProps)[]) { + Object.defineProperty(this, key, { + get: () => this.#state[key], + set: (value) => { + (this.#state[key] as unknown) = value; + this.#render(); + }, + }); + } + } + + connectedCallback() { + this.#render(); + } + + #render() { + const { city, country, temp, unit, condition, humidity, wind } = this.#state; + this.#els.location.textContent = `📍 ${city}${country ? `, ${country}` : ""}`; + this.#els.temp.textContent = `${temp}°${unit}`; + this.#els.condition.textContent = condition; + this.#els.humidity.textContent = `💧 ${humidity}%`; + this.#els.wind.textContent = `💨 ${wind} km/h`; + } +} + +// A class extending HTMLElement can only be constructed with `new` — which +// is exactly what does — once it's been registered via +// customElements.define(); that part isn't optional, even though the tag +// name itself is never used in markup here. (`GenUIRegistry.register`'s key +// — "weather" — is a separate, unrelated name: what a GenUI chunk's +// `component` field must match, not a tag name.) +if (!customElements.get("demo-weather-card")) { + customElements.define("demo-weather-card", CustomWeatherCard); +} + +GenUIRegistry.register("weather", CustomWeatherCard); diff --git a/examples/react-vite/src/index.css b/examples/react-vite/src/index.css new file mode 100644 index 0000000..945521e --- /dev/null +++ b/examples/react-vite/src/index.css @@ -0,0 +1,59 @@ +html, +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + background: #f8fafc; + color: #0f172a; +} + +.page { + max-width: 640px; + margin: 0 auto; + padding: 3rem 1.5rem; +} + +.page code { + background: #e2e8f0; + padding: 0.1em 0.4em; + border-radius: 4px; + font-size: 0.9em; +} + +.custom-launcher { + display: flex; + align-items: center; + gap: 0.5rem; + border: none; + border-radius: 999px; + padding: 0.75rem 1.25rem; + background: linear-gradient(135deg, #7c3aed 0%, #4f46e5 100%); + color: white; + font-size: 0.9375rem; + font-weight: 600; + cursor: pointer; + box-shadow: 0 8px 24px rgba(124, 58, 237, 0.35); +} + +.custom-launcher:hover { + filter: brightness(1.08); +} + +.custom-launcher-icon { + font-size: 1.1em; +} + +.trigger-genui { + margin-top: 0.5rem; + border: 1px solid #c7d2fe; + border-radius: 8px; + padding: 0.6rem 1rem; + background: white; + color: #4f46e5; + font-size: 0.875rem; + font-weight: 600; + cursor: pointer; +} + +.trigger-genui:hover { + background: #eef2ff; +} diff --git a/examples/react-vite/src/main.tsx b/examples/react-vite/src/main.tsx new file mode 100644 index 0000000..94c679d --- /dev/null +++ b/examples/react-vite/src/main.tsx @@ -0,0 +1,13 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import App from "./App"; +import "./index.css"; +// Side-effect import: registers the custom "weather" GenUI component before +// any chat message could try to render one. +import "./CustomWeatherCard"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/examples/react-vite/src/vite-env.d.ts b/examples/react-vite/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/examples/react-vite/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react-vite/tsconfig.json b/examples/react-vite/tsconfig.json new file mode 100644 index 0000000..9f7aef3 --- /dev/null +++ b/examples/react-vite/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react-jsx", + "paths": { + "@chativa/react": ["../../packages/react/src/index.ts"], + "@chativa/core": ["../../packages/core/src/index.ts"], + "@chativa/ui": ["../../packages/ui/src/index.ts"], + "@chativa/genui": ["../../packages/genui/src/index.ts"], + "@chativa/connector-dummy": ["../../packages/connector-dummy/src/index.ts"] + } + }, + "include": ["src"] +} diff --git a/examples/react-vite/vite.config.ts b/examples/react-vite/vite.config.ts new file mode 100644 index 0000000..9931706 --- /dev/null +++ b/examples/react-vite/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import { resolve } from "path"; + +// Aliases resolve every @chativa/* package to its *source*, matching +// apps/sandbox's convention — lets this example run against local changes +// without a build step for any of them first. +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "@chativa/react": resolve(__dirname, "../../packages/react/src/index.ts"), + "@chativa/core": resolve(__dirname, "../../packages/core/src/index.ts"), + "@chativa/ui": resolve(__dirname, "../../packages/ui/src/index.ts"), + "@chativa/genui": resolve(__dirname, "../../packages/genui/src/index.ts"), + "@chativa/connector-dummy": resolve(__dirname, "../../packages/connector-dummy/src/index.ts"), + }, + }, +}); diff --git a/packages/react/package.json b/packages/react/package.json new file mode 100644 index 0000000..afb8607 --- /dev/null +++ b/packages/react/package.json @@ -0,0 +1,72 @@ +{ + "name": "@chativa/react", + "version": "0.0.1", + "description": "Chativa React — typed React components (ChatIva, ChatBotButton, ChativaProvider) wrapping the Chativa chat widget for React/Next.js apps.", + "author": "Hamza Agar", + "license": "MIT", + "type": "module", + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs" + } + }, + "files": [ + "dist" + ], + "keywords": [ + "chativa", + "chat", + "react", + "nextjs", + "web-component", + "wrapper" + ], + "homepage": "https://github.com/AimTune/chativa#readme", + "bugs": { + "url": "https://github.com/AimTune/chativa/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/AimTune/chativa.git" + }, + "scripts": { + "build": "vite build", + "test": "vitest run --passWithNoTests", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@chativa/core": "workspace:*", + "@chativa/ui": "workspace:*", + "@lit/react": "^1.0.8" + }, + "peerDependencies": { + "@chativa/core": ">=0.0.1", + "@chativa/genui": ">=0.0.1", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@chativa/genui": { + "optional": true + } + }, + "devDependencies": { + "@chativa/genui": "workspace:*", + "@testing-library/react": "^16.3.2", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "jsdom": "^28.1.0", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "terser": "^5.46.0", + "typescript": "~5.8.3", + "vite": "^7.0.3", + "vite-plugin-dts": "^4.5.4", + "vitest": "^4.0.18" + } +} diff --git a/packages/react/src/ChatBotButton.tsx b/packages/react/src/ChatBotButton.tsx new file mode 100644 index 0000000..36c428b --- /dev/null +++ b/packages/react/src/ChatBotButton.tsx @@ -0,0 +1,48 @@ +"use client"; + +import * as React from "react"; +import { loadChativaUi } from "./internal/loadChativaUi"; +import { createLazyElementComponent } from "./internal/createLazyElementComponent"; + +export interface ChatBotButtonProps { + className?: string; + style?: React.CSSProperties; + /** Custom launcher content — rendered into the default slot. Omit for the built-in gradient circle + animated icons. */ + children?: React.ReactNode; +} + +let cachedChatBotButton: React.ComponentType< + ChatBotButtonProps & React.RefAttributes +> | null = null; + +async function loadChatBotButtonElement() { + if (cachedChatBotButton) return cachedChatBotButton; + const [{ createComponent }, { ChatBotButton: ChatBotButtonElement }] = await Promise.all([ + import("@lit/react"), + loadChativaUi(), + ]); + cachedChatBotButton = createComponent({ + react: React, + tagName: "chat-bot-button", + elementClass: ChatBotButtonElement, + }) as unknown as React.ComponentType>; + return cachedChatBotButton; +} + +const LazyChatBotButton = createLazyElementComponent( + loadChatBotButtonElement, + "LazyChatBotButton", +); + +/** + * React wrapper for `` — the floating launcher button. + * `` is only the chat panel; it has no launcher of its own, so a + * normal popup setup renders `` alongside it to toggle the + * shared `chatStore`'s open state. Pass children to replace the default + * gradient-circle icon with a fully custom launcher element. + */ +export const ChatBotButton = React.forwardRef( + function ChatBotButton(props, ref) { + return ; + }, +); diff --git a/packages/react/src/ChatIva.tsx b/packages/react/src/ChatIva.tsx new file mode 100644 index 0000000..3ec6aea --- /dev/null +++ b/packages/react/src/ChatIva.tsx @@ -0,0 +1,135 @@ +"use client"; + +import * as React from "react"; +import { chatStore } from "@chativa/core"; +import type { + IConnector, + IncomingMessage, + OutgoingMessage, + SurveyPayload, + ConnectorStatus, +} from "@chativa/core"; +import { loadChativaUi } from "./internal/loadChativaUi"; +import { createLazyElementComponent } from "./internal/createLazyElementComponent"; +import { resolveConnectorName } from "./internal/resolveConnector"; +import { useChativaEvent } from "./hooks/useChativaEvent"; + +export interface ChatIvaProps { + /** Connector name (already registered elsewhere) or an `IConnector` instance to auto-register and use. Defaults to whatever `` (or `window.chativaSettings`) has activated. */ + connector?: string | IConnector; + /** + * Start in fullscreen and hide the fullscreen toggle. Equivalent to the + * `fullscreen-only` HTML attribute on ``. + */ + fullscreenOnly?: boolean; + className?: string; + style?: React.CSSProperties; + children?: React.ReactNode; + /** A bot/connector message was delivered. */ + onMessage?: (message: IncomingMessage) => void; + /** The user sent a message. */ + onMessageSent?: (message: OutgoingMessage) => void; + /** The connector transitioned to `"connected"`. */ + onConnect?: () => void; + /** The connector transitioned to `"disconnected"` or `"error"`. */ + onDisconnect?: (payload: { status: ConnectorStatus }) => void; + /** The end-of-conversation survey was submitted. */ + onSurveySubmit?: (payload: SurveyPayload) => void; + /** The chat panel opened. */ + onWidgetOpen?: () => void; + /** The chat panel closed. */ + onWidgetClose?: () => void; +} + +interface ChatIvaElementProps { + connector?: string; + fulllscreenOnly?: boolean; + className?: string; + style?: React.CSSProperties; + children?: React.ReactNode; +} + +let cachedChatIva: React.ComponentType< + ChatIvaElementProps & React.RefAttributes +> | null = null; + +async function loadChatIvaElement() { + if (cachedChatIva) return cachedChatIva; + const [{ createComponent }, { ChatWidget }] = await Promise.all([ + import("@lit/react"), + loadChativaUi(), + ]); + cachedChatIva = createComponent({ + react: React, + tagName: "chat-iva", + elementClass: ChatWidget, + }) as unknown as React.ComponentType>; + return cachedChatIva; +} + +const LazyChatIva = createLazyElementComponent( + loadChatIvaElement, + "LazyChatIva", +); + +/** + * React wrapper for `` — the main Chativa chat widget (launcher + + * panel). Renders nothing until the underlying `@chativa/ui` module has + * loaded on the client, so it's safe to render from a Server Component tree. + * + * @example + * ```tsx + * import { ChatIva } from "@chativa/react"; + * import { DummyConnector } from "@chativa/connector-dummy"; + * + * const dummy = new DummyConnector(); + * + * console.log(m)} /> + * ``` + */ +export const ChatIva = React.forwardRef(function ChatIva( + { + connector, + fullscreenOnly, + onMessage, + onMessageSent, + onConnect, + onDisconnect, + onSurveySubmit, + onWidgetOpen, + onWidgetClose, + ...rest + }, + ref, +) { + // Idempotent registry write — safe during render (mirrors how + // ChatWidget.connectedCallback itself resolves the active connector), and + // must complete before the underlying element connects. + const connectorName = resolveConnectorName(connector); + + // `@lit/react` sets element properties via a ref, which React only runs + // *after* the DOM node is inserted — but `ChatWidget.connectedCallback` + // reads `this.connector` synchronously at connect time, before that ref + // fires. Pushing the resolved name into the shared `chatStore` instead + // works: `ChatWidget` prefers `themeState.activeConnector` over its own + // `connector` property whenever the former isn't the default "dummy". + if (connectorName !== undefined && chatStore.getState().activeConnector !== connectorName) { + chatStore.getState().setConnector(connectorName); + } + + useChativaEvent("message_received", onMessage); + useChativaEvent("message_sent", onMessageSent); + useChativaEvent("survey_submitted", onSurveySubmit); + useChativaEvent("widget_opened", onWidgetOpen); + useChativaEvent("widget_closed", onWidgetClose); + useChativaEvent("connector_status_changed", (payload) => { + if (payload.status === "connected") onConnect?.(); + else if (payload.status === "disconnected" || payload.status === "error") onDisconnect?.(payload); + }); + + const elementProps: ChatIvaElementProps = { ...rest }; + if (connectorName !== undefined) elementProps.connector = connectorName; + if (fullscreenOnly !== undefined) elementProps.fulllscreenOnly = fullscreenOnly; + + return ; +}); diff --git a/packages/react/src/ChativaProvider.tsx b/packages/react/src/ChativaProvider.tsx new file mode 100644 index 0000000..aeef728 --- /dev/null +++ b/packages/react/src/ChativaProvider.tsx @@ -0,0 +1,80 @@ +"use client"; + +import * as React from "react"; +import { + ExtensionRegistry, + chatStore, + i18next, + type IConnector, + type IExtension, + type DeepPartial, + type ThemeConfig, +} from "@chativa/core"; +import { resolveConnectorName } from "./internal/resolveConnector"; + +export interface ChativaProviderProps { + /** Connector name (already registered elsewhere) or an `IConnector` instance to auto-register and activate as the default. */ + connector?: string | IConnector; + /** Extensions to install once, before any child widget mounts. */ + extensions?: IExtension[]; + /** Theme overrides, deep-merged over the default theme. Reactive — updates re-apply. */ + theme?: DeepPartial; + /** Initial locale override (e.g. `"tr"`, `"en"`), skipping browser detection. */ + locale?: string; + /** Flat i18n translation overrides, applied to every registered language — see `ChativaSettings.i18n` in `@chativa/core` for the full per-language format. */ + i18n?: Record; + children?: React.ReactNode; +} + +/** + * Registers a shared connector + extensions once, and applies theme/locale/ + * i18n overrides, for every Chativa widget rendered underneath it. This is + * the React-idiomatic equivalent of setting `window.chativaSettings` before + * `` connects — no global object required. + * + * Connector/extension registration happens synchronously during the first + * render (not inside a `useEffect`) so it's guaranteed to complete before + * any nested `` / `` mounts its underlying custom + * element and reads from `ConnectorRegistry` / `ExtensionRegistry`. + */ +export function ChativaProvider({ + connector, + extensions, + theme, + locale, + i18n, + children, +}: ChativaProviderProps): React.ReactElement { + React.useState(() => { + const name = resolveConnectorName(connector); + if (name) chatStore.getState().setConnector(name); + + extensions?.forEach((extension) => { + if (!ExtensionRegistry.has(extension.name)) { + ExtensionRegistry.install(extension); + } + }); + + return null; + }); + + React.useEffect(() => { + if (theme) chatStore.getState().setTheme(theme); + }, [theme]); + + React.useEffect(() => { + if (!locale) return; + const apply = () => i18next.changeLanguage(locale); + if (i18next.isInitialized) apply(); + else i18next.on("initialized", apply); + }, [locale]); + + React.useEffect(() => { + if (!i18n) return; + for (const lng of Object.keys(i18next.store.data)) { + i18next.addResourceBundle(lng, "translation", i18n, true, true); + } + }, [i18n]); + + return <>{children}; +} diff --git a/packages/react/src/GenUIMessage.tsx b/packages/react/src/GenUIMessage.tsx new file mode 100644 index 0000000..dab5917 --- /dev/null +++ b/packages/react/src/GenUIMessage.tsx @@ -0,0 +1,57 @@ +"use client"; + +import * as React from "react"; +import { loadChativaGenUi } from "./internal/loadChativaUi"; +import { createLazyElementComponent } from "./internal/createLazyElementComponent"; + +export interface GenUIMessageProps { + /** The streaming GenUI message payload (`GenUIStreamState`), as delivered by `onGenUIChunk`/stored on the message. */ + messageData?: Record; + sender?: "user" | "bot"; + messageId?: string; + timestamp?: number; + hideAvatar?: boolean; + status?: string; + /** Show developer diagnostics (e.g. the unknown-component fallback). Off by default. */ + debug?: boolean; + className?: string; + style?: React.CSSProperties; +} + +let cachedGenUIMessage: React.ComponentType< + GenUIMessageProps & React.RefAttributes +> | null = null; + +async function loadGenUIMessageElement() { + if (cachedGenUIMessage) return cachedGenUIMessage; + const [{ createComponent }, { GenUIMessage: GenUIMessageElement }] = await Promise.all([ + import("@lit/react"), + loadChativaGenUi(), + ]); + cachedGenUIMessage = createComponent({ + react: React, + tagName: "genui-message", + elementClass: GenUIMessageElement, + }) as unknown as React.ComponentType>; + return cachedGenUIMessage; +} + +const LazyGenUIMessage = createLazyElementComponent( + loadGenUIMessageElement, + "LazyGenUIMessage", +); + +/** + * React wrapper for `` — renders a streaming Generative UI + * message (text + registered GenUI components) outside of ``'s own + * message list, e.g. to embed a single AI reply in a custom layout. + * + * Requires `@chativa/genui` to be installed — it is an optional peer + * dependency of `@chativa/react` (already pulled in transitively by + * `@chativa/ui` for ``, but not otherwise). + */ +export const GenUIMessage = React.forwardRef( + function GenUIMessage(props, ref) { + return ; + }, +); diff --git a/packages/react/src/__tests__/ChatIva.test.tsx b/packages/react/src/__tests__/ChatIva.test.tsx new file mode 100644 index 0000000..50fc7f7 --- /dev/null +++ b/packages/react/src/__tests__/ChatIva.test.tsx @@ -0,0 +1,116 @@ +import { describe, it, expect, afterEach, vi } from "vitest"; +import { render, cleanup, waitFor } from "@testing-library/react"; +import { + EventBus, + ConnectorRegistry, + chatStore, + type IConnector, + type IncomingMessage, +} from "@chativa/core"; +import { ChatIva } from "../ChatIva"; + +afterEach(() => { + cleanup(); +}); + +function makeFakeConnector(name: string): IConnector { + return { + name, + async connect() {}, + async disconnect() {}, + async sendMessage() {}, + onMessage() {}, + }; +} + +describe("ChatIva", () => { + it("renders nothing synchronously (SSR-safe: no window/document use before mount)", () => { + const connector = makeFakeConnector("chativa-test-connector-1"); + const { container } = render(); + expect(container.querySelector("chat-iva")).toBeNull(); + }); + + it("lazily mounts the underlying element and activates the resolved connector", async () => { + const connector = makeFakeConnector("chativa-test-connector-2"); + + render(); + + await waitFor(() => { + expect(document.querySelector("chat-iva")).not.toBeNull(); + }); + + expect(ConnectorRegistry.has("chativa-test-connector-2")).toBe(true); + // `ChatWidget.connectedCallback` reads `chatStore.activeConnector` (in + // preference to its own `connector` property, which `@lit/react` only + // applies post-mount via a ref) — this is what actually determines which + // connector the widget connects to. + expect(chatStore.getState().activeConnector).toBe("chativa-test-connector-2"); + }); + + it("accepts a plain connector name string without auto-registering anything", async () => { + const connector = makeFakeConnector("chativa-test-connector-3"); + ConnectorRegistry.register(connector); + + render(); + + await waitFor(() => { + expect(document.querySelector("chat-iva")).not.toBeNull(); + }); + + expect(chatStore.getState().activeConnector).toBe("chativa-test-connector-3"); + + ConnectorRegistry.unregister("chativa-test-connector-3"); + }); + + it("maps EventBus events to onMessage / onWidgetOpen / onWidgetClose props", async () => { + const connector = makeFakeConnector("chativa-test-connector-4"); + const onMessage = vi.fn(); + const onWidgetOpen = vi.fn(); + const onWidgetClose = vi.fn(); + + render( + , + ); + + await waitFor(() => { + expect(document.querySelector("chat-iva")).not.toBeNull(); + }); + + const message: IncomingMessage = { + id: "m1", + type: "text", + data: { text: "hi" }, + timestamp: Date.now(), + }; + EventBus.emit("message_received", message); + EventBus.emit("widget_opened", undefined); + EventBus.emit("widget_closed", undefined); + + expect(onMessage).toHaveBeenCalledWith(message); + expect(onWidgetOpen).toHaveBeenCalledTimes(1); + expect(onWidgetClose).toHaveBeenCalledTimes(1); + }); + + it("maps connector_status_changed to onConnect / onDisconnect", async () => { + const connector = makeFakeConnector("chativa-test-connector-5"); + const onConnect = vi.fn(); + const onDisconnect = vi.fn(); + + render(); + + await waitFor(() => { + expect(document.querySelector("chat-iva")).not.toBeNull(); + }); + + EventBus.emit("connector_status_changed", { status: "connected" }); + EventBus.emit("connector_status_changed", { status: "disconnected" }); + + expect(onConnect).toHaveBeenCalledTimes(1); + expect(onDisconnect).toHaveBeenCalledWith({ status: "disconnected" }); + }); +}); diff --git a/packages/react/src/__tests__/ChativaProvider.test.tsx b/packages/react/src/__tests__/ChativaProvider.test.tsx new file mode 100644 index 0000000..8c0dad1 --- /dev/null +++ b/packages/react/src/__tests__/ChativaProvider.test.tsx @@ -0,0 +1,97 @@ +import { describe, it, expect, afterEach } from "vitest"; +import { render, cleanup } from "@testing-library/react"; +import { + ConnectorRegistry, + ExtensionRegistry, + chatStore, + type IConnector, + type IExtension, +} from "@chativa/core"; +import { ChativaProvider } from "../ChativaProvider"; + +afterEach(() => { + cleanup(); +}); + +function makeFakeConnector(name: string): IConnector { + return { + name, + async connect() {}, + async disconnect() {}, + async sendMessage() {}, + onMessage() {}, + }; +} + +describe("ChativaProvider", () => { + it("renders its children synchronously", () => { + const { getByText } = render( + +
hello
+
, + ); + expect(getByText("hello")).toBeTruthy(); + }); + + it("auto-registers an IConnector instance and activates it in chatStore", () => { + const connector = makeFakeConnector("provider-test-connector"); + + render( + +
+ , + ); + + expect(ConnectorRegistry.has("provider-test-connector")).toBe(true); + expect(chatStore.getState().activeConnector).toBe("provider-test-connector"); + + ConnectorRegistry.unregister("provider-test-connector"); + }); + + it("does not re-register an already-registered connector name", () => { + const connector = makeFakeConnector("provider-test-connector-2"); + ConnectorRegistry.register(connector); + + expect(() => + render( + +
+ , + ), + ).not.toThrow(); + + ConnectorRegistry.unregister("provider-test-connector-2"); + }); + + it("installs extensions once", () => { + let installCount = 0; + const extension: IExtension = { + name: "provider-test-extension", + version: "1.0.0", + install() { + installCount++; + }, + }; + + render( + +
+ , + ); + + expect(installCount).toBe(1); + expect(ExtensionRegistry.has("provider-test-extension")).toBe(true); + + ExtensionRegistry.uninstall("provider-test-extension"); + }); + + it("applies theme overrides", () => { + render( + +
+ , + ); + + expect(chatStore.getState().theme.colors.primary).toBe("#123456"); + }); +}); diff --git a/packages/react/src/hooks/useChativaEvent.ts b/packages/react/src/hooks/useChativaEvent.ts new file mode 100644 index 0000000..edfd1b7 --- /dev/null +++ b/packages/react/src/hooks/useChativaEvent.ts @@ -0,0 +1,31 @@ +"use client"; + +import { useEffect, useRef } from "react"; +import { EventBus, type EventBusEventName, type EventBusPayloadMap } from "@chativa/core"; + +/** + * Subscribe to a Chativa `EventBus` event for the lifetime of the calling + * component. The subscription is created once per `event` name — passing a + * new `handler` identity on every render (the common case for inline arrow + * functions) does not tear down and re-create it; the latest `handler` is + * always the one invoked. + * + * @example + * ```tsx + * useChativaEvent("message_received", (message) => console.log(message)); + * ``` + */ +export function useChativaEvent( + event: K, + handler: ((payload: EventBusPayloadMap[K]) => void) | undefined, +): void { + const handlerRef = useRef(handler); + handlerRef.current = handler; + + useEffect(() => { + if (!handler) return; + const listener = (payload: EventBusPayloadMap[K]) => handlerRef.current?.(payload); + EventBus.on(event, listener); + return () => EventBus.off(event, listener); + }, [event, !!handler]); +} diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts new file mode 100644 index 0000000..ca5d45a --- /dev/null +++ b/packages/react/src/index.ts @@ -0,0 +1,42 @@ +// @chativa/react — React wrapper components for the Chativa chat widget + +export { ChativaProvider } from "./ChativaProvider"; +export type { ChativaProviderProps } from "./ChativaProvider"; + +export { ChatIva } from "./ChatIva"; +export type { ChatIvaProps } from "./ChatIva"; + +export { ChatBotButton } from "./ChatBotButton"; +export type { ChatBotButtonProps } from "./ChatBotButton"; + +export { GenUIMessage } from "./GenUIMessage"; +export type { GenUIMessageProps } from "./GenUIMessage"; + +export { useChativaEvent } from "./hooks/useChativaEvent"; + +// ── Re-exported `@chativa/core` types for consumer apps ────────────────────── +// (`@chativa/core` is a required peer dependency, so this adds no extra install.) +export type { + IConnector, + IExtension, + ExtensionContext, + MessageTransformer, + ThemeConfig, + ThemeColors, + LayoutConfig, + AvatarConfig, + ButtonPosition, + ButtonSize, + SpaceLevel, + WindowMode, + DeepPartial, + EndOfConversationSurveyConfig, + IncomingMessage, + OutgoingMessage, + MessageSender, + MessageStatus, + SurveyPayload, + ConnectorStatus, + EventBusEventName, + EventBusPayloadMap, +} from "@chativa/core"; diff --git a/packages/react/src/internal/createLazyElementComponent.tsx b/packages/react/src/internal/createLazyElementComponent.tsx new file mode 100644 index 0000000..23e941d --- /dev/null +++ b/packages/react/src/internal/createLazyElementComponent.tsx @@ -0,0 +1,42 @@ +"use client"; + +import * as React from "react"; + +/** + * Wraps an async `load()` — a dynamic `import()` of the LitElement module + * plus `@lit/react`'s `createComponent()` — into a React component that + * mounts once that module has resolved on the client. + * + * Renders `null` until then, including for the entire server render: `load` + * only ever runs inside `useEffect`, which React never executes during SSR. + * That keeps this package free of `window`/`document`/`customElements` + * references at module-evaluation time, so it builds cleanly with `next + * build` and `vite build` and is safe to import from a Server Component + * tree (the actual widget still only renders client-side). + */ +export function createLazyElementComponent

( + load: () => Promise>>, + displayName: string, +): React.ComponentType

> { + const LazyElement = React.forwardRef(function LazyElement(props, ref) { + const [Component, setComponent] = React.useState + > | null>(null); + + React.useEffect(() => { + let cancelled = false; + load().then((Loaded) => { + if (!cancelled) setComponent(() => Loaded); + }); + return () => { + cancelled = true; + }; + }, []); + + if (!Component) return null; + return ; + }); + + LazyElement.displayName = displayName; + return LazyElement as unknown as React.ComponentType

>; +} diff --git a/packages/react/src/internal/loadChativaUi.ts b/packages/react/src/internal/loadChativaUi.ts new file mode 100644 index 0000000..c69fcdc --- /dev/null +++ b/packages/react/src/internal/loadChativaUi.ts @@ -0,0 +1,21 @@ +/** + * Client-only, memoized loaders for `@chativa/ui` / `@chativa/genui`. + * + * Both packages register custom elements (and touch `customElements` / + * `document`) as *module-level side effects*, so they must never be + * imported eagerly from a module that a server bundler evaluates during + * SSR. Every load is routed through `import()` inside a browser-only + * effect — see `createLazyElementComponent`. + */ + +let uiPromise: Promise | null = null; +export function loadChativaUi(): Promise { + if (!uiPromise) uiPromise = import("@chativa/ui"); + return uiPromise; +} + +let genuiPromise: Promise | null = null; +export function loadChativaGenUi(): Promise { + if (!genuiPromise) genuiPromise = import("@chativa/genui"); + return genuiPromise; +} diff --git a/packages/react/src/internal/resolveConnector.ts b/packages/react/src/internal/resolveConnector.ts new file mode 100644 index 0000000..875a705 --- /dev/null +++ b/packages/react/src/internal/resolveConnector.ts @@ -0,0 +1,19 @@ +import { ConnectorRegistry, type IConnector } from "@chativa/core"; + +/** + * Accepts either a registered connector name or an `IConnector` instance. + * Instances are auto-registered (idempotent — safe to call on every render/ + * effect) so `` works without a separate + * `ConnectorRegistry.register(dummy)` call. Returns the resolved name to + * hand down to the underlying `` attribute. + */ +export function resolveConnectorName( + connector: string | IConnector | undefined, +): string | undefined { + if (connector === undefined) return undefined; + if (typeof connector === "string") return connector; + if (!ConnectorRegistry.has(connector.name)) { + ConnectorRegistry.register(connector); + } + return connector.name; +} diff --git a/packages/react/src/vite-env.d.ts b/packages/react/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/packages/react/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json new file mode 100644 index 0000000..70e7f90 --- /dev/null +++ b/packages/react/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react-jsx", + "paths": { + "@chativa/core": [ + "../core/src/index.ts" + ], + "@chativa/ui": [ + "../ui/src/index.ts" + ], + "@chativa/genui": [ + "../genui/src/index.ts" + ] + } + }, + "include": [ + "src" + ] +} diff --git a/packages/react/vite.config.ts b/packages/react/vite.config.ts new file mode 100644 index 0000000..18bb2a2 --- /dev/null +++ b/packages/react/vite.config.ts @@ -0,0 +1,36 @@ +import { defineConfig } from "vite"; +import dts from "vite-plugin-dts"; +import { resolve } from "path"; + +export default defineConfig({ + esbuild: { + jsx: "automatic", + }, + build: { + lib: { + entry: resolve(__dirname, "src/index.ts"), + formats: ["es", "cjs"], + fileName: (fmt) => `index.${fmt === "es" ? "js" : "cjs"}`, + }, + rollupOptions: { + external: [ + "react", + "react-dom", + "react/jsx-runtime", + "@lit/react", + "@chativa/core", + "@chativa/ui", + "@chativa/genui", + ], + output: { + // Rollup drops per-module "use client" directives once everything is + // merged into one chunk — re-add it as a banner so Next.js App + // Router still treats every export here as a Client Component + // without consumers needing their own 'use client' wrapper. + banner: '"use client";', + }, + }, + sourcemap: true, + }, + plugins: [dts({ rollupTypes: true })], +}); diff --git a/packages/react/vitest.config.ts b/packages/react/vitest.config.ts new file mode 100644 index 0000000..259af12 --- /dev/null +++ b/packages/react/vitest.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from "vitest/config"; +import path from "path"; + +export default defineConfig({ + resolve: { + alias: { + // Resolve workspace packages from source so tests don't need a pre-built dist + "@chativa/core": path.resolve(__dirname, "../core/src/index.ts"), + "@chativa/ui": path.resolve(__dirname, "../ui/src/index.ts"), + "@chativa/genui": path.resolve(__dirname, "../genui/src/index.ts"), + }, + }, + test: { + environment: "jsdom", + include: ["src/**/__tests__/**/*.test.tsx", "src/**/__tests__/**/*.test.ts"], + coverage: { + provider: "v8", + reporter: ["text", "html", "lcov", "json-summary"], + include: ["src/**/*.{ts,tsx}"], + exclude: ["src/**/__tests__/**", "src/**/*.test.{ts,tsx}", "src/index.ts"], + thresholds: { lines: 30, functions: 30, branches: 20, statements: 30 }, + }, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f150982..8b3240c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: version: 5.8.3 vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) apps/chrome-extension: dependencies: @@ -41,7 +41,7 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) apps/sandbox: dependencies: @@ -66,7 +66,44 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) + + examples/react-vite: + dependencies: + '@chativa/connector-dummy': + specifier: workspace:* + version: link:../../packages/connector-dummy + '@chativa/core': + specifier: workspace:* + version: link:../../packages/core + '@chativa/genui': + specifier: workspace:* + version: link:../../packages/genui + '@chativa/react': + specifier: workspace:* + version: link:../../packages/react + react: + specifier: ^19.2.8 + version: 19.2.8 + react-dom: + specifier: ^19.2.8 + version: 19.2.8(react@19.2.8) + devDependencies: + '@types/react': + specifier: ^19.2.17 + version: 19.2.17 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.17) + '@vitejs/plugin-react': + specifier: ^4.7.0 + version: 4.7.0(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) + typescript: + specifier: ~5.8.3 + version: 5.8.3 + vite: + specifier: ^7.0.3 + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/connector-directline: dependencies: @@ -85,13 +122,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/connector-dummy: devDependencies: @@ -100,7 +137,7 @@ importers: version: link:../core '@vitest/coverage-v8': specifier: ^4.0.18 - version: 4.0.18(vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.0.18(vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) jsdom: specifier: ^28.1.0 version: 28.1.0 @@ -112,13 +149,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/connector-http: devDependencies: @@ -133,13 +170,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/connector-mekik: devDependencies: @@ -154,13 +191,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/connector-signalr: dependencies: @@ -179,13 +216,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/connector-sse: devDependencies: @@ -200,13 +237,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/connector-websocket: devDependencies: @@ -221,13 +258,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/core: dependencies: @@ -243,7 +280,7 @@ importers: devDependencies: '@vitest/coverage-v8': specifier: ^4.0.18 - version: 4.0.18(vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.0.18(vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) jsdom: specifier: ^28.1.0 version: 28.1.0 @@ -255,13 +292,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/genui: dependencies: @@ -277,10 +314,59 @@ importers: devDependencies: '@vitest/coverage-v8': specifier: ^4.0.18 - version: 4.0.18(vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.0.18(vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) + jsdom: + specifier: ^28.1.0 + version: 28.1.0 + terser: + specifier: ^5.46.0 + version: 5.46.0 + typescript: + specifier: ~5.8.3 + version: 5.8.3 + vite: + specifier: ^7.0.3 + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) + vite-plugin-dts: + specifier: ^4.5.4 + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) + vitest: + specifier: ^4.0.18 + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) + + packages/react: + dependencies: + '@chativa/core': + specifier: workspace:* + version: link:../core + '@chativa/ui': + specifier: workspace:* + version: link:../ui + '@lit/react': + specifier: ^1.0.8 + version: 1.0.8(@types/react@19.2.17) + devDependencies: + '@chativa/genui': + specifier: workspace:* + version: link:../genui + '@testing-library/react': + specifier: ^16.3.2 + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@types/react': + specifier: ^19.2.17 + version: 19.2.17 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.17) jsdom: specifier: ^28.1.0 version: 28.1.0 + react: + specifier: ^19.2.8 + version: 19.2.8 + react-dom: + specifier: ^19.2.8 + version: 19.2.8(react@19.2.8) terser: specifier: ^5.46.0 version: 5.46.0 @@ -289,13 +375,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) packages/ui: dependencies: @@ -332,13 +418,13 @@ importers: version: 5.8.3 vite: specifier: ^7.0.3 - version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + version: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + version: 4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) vitest: specifier: ^4.0.18 - version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + version: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) website: dependencies: @@ -489,6 +575,10 @@ packages: resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.29.3': resolution: {integrity: sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==} engines: {node: '>=6.9.0'} @@ -548,8 +638,8 @@ packages: resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} engines: {node: '>=6.9.0'} '@babel/helper-remap-async-to-generator@7.27.1': @@ -576,6 +666,10 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} @@ -922,6 +1016,18 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-jsx-self@7.29.7': + resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.29.7': + resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-jsx@7.28.6': resolution: {integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==} engines: {node: '>=6.9.0'} @@ -1958,6 +2064,11 @@ packages: '@lit-labs/virtualizer@2.1.1': resolution: {integrity: sha512-JWxMwnlouLdwpw8spLTuax53WMnSP3xt0dCyxAS7GJr5Otda9MGgR/ghAdfwhSY75TmjbE1T2TqChwoGCw3ggw==} + '@lit/react@1.0.8': + resolution: {integrity: sha512-p2+YcF+JE67SRX3mMlJ1TKCSTsgyOVdAwd/nxp3NuV1+Cb6MWALbN6nT7Ld4tpmYofcE5kcaSY1YBB9erY+6fw==} + peerDependencies: + '@types/react': 17 || 18 || 19 + '@lit/reactive-element@2.1.2': resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} @@ -2075,6 +2186,9 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + '@rollup/pluginutils@5.3.0': resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} engines: {node: '>=14.0.0'} @@ -2609,12 +2723,46 @@ packages: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/react@16.3.2': + resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/body-parser@1.19.6': resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} @@ -2726,6 +2874,11 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + '@types/react-router-config@5.0.11': resolution: {integrity: sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==} @@ -2738,6 +2891,9 @@ packages: '@types/react@19.2.14': resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + '@types/react@19.2.17': + resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} + '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} @@ -2784,6 +2940,12 @@ packages: resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} deprecated: Potential CWE-502 - Update to 1.3.1 or higher + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitest/coverage-v8@4.0.18': resolution: {integrity: sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==} peerDependencies: @@ -3017,6 +3179,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} @@ -3038,6 +3204,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} @@ -3692,6 +3861,9 @@ packages: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dom-converter@0.2.0: resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} @@ -4026,6 +4198,10 @@ packages: resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} engines: {node: '>=14.14'} + fs-extra@11.4.0: + resolution: {integrity: sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==} + engines: {node: '>=14.14'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -4725,6 +4901,10 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -5674,6 +5854,10 @@ packages: pretty-error@4.0.0: resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-time@1.1.0: resolution: {integrity: sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==} engines: {node: '>=4'} @@ -5770,12 +5954,20 @@ packages: peerDependencies: react: ^19.2.5 + react-dom@19.2.8: + resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==} + peerDependencies: + react: ^19.2.8 + react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-json-view-lite@2.5.0: resolution: {integrity: sha512-tk7o7QG9oYyELWHL8xiMQ8x4WzjCzbWNyig3uexmkLb54r8jO0yH3WCWx8UZS0c49eSA4QUmG5caiRJ8fAn58g==} engines: {node: '>=18'} @@ -5789,6 +5981,10 @@ packages: react-loadable: '*' webpack: '>=4.41.1 || 5.x' + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} + react-router-config@5.1.1: resolution: {integrity: sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==} peerDependencies: @@ -5809,6 +6005,10 @@ packages: resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} engines: {node: '>=0.10.0'} + react@19.2.8: + resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} + engines: {node: '>=0.10.0'} + readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -6801,6 +7001,11 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + yocto-queue@1.2.2: resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} engines: {node: '>=12.20'} @@ -6984,6 +7189,12 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.29.3': {} '@babel/core@7.29.0': @@ -7050,7 +7261,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.11 @@ -7086,7 +7297,7 @@ snapshots: dependencies: '@babel/types': 7.29.0 - '@babel/helper-plugin-utils@7.28.6': {} + '@babel/helper-plugin-utils@7.29.7': {} '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': dependencies: @@ -7117,6 +7328,8 @@ snapshots: '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.29.7': {} + '@babel/helper-validator-option@7.27.1': {} '@babel/helper-wrap-function@7.28.6': @@ -7139,7 +7352,7 @@ snapshots: '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -7147,17 +7360,17 @@ snapshots: '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color @@ -7165,7 +7378,7 @@ snapshots: '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: @@ -7174,7 +7387,7 @@ snapshots: '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -7186,43 +7399,43 @@ snapshots: '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) '@babel/traverse': 7.29.0 transitivePeerDependencies: @@ -7232,7 +7445,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) transitivePeerDependencies: - supports-color @@ -7240,18 +7453,18 @@ snapshots: '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-class-features-plugin': 7.29.3(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -7259,7 +7472,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-create-class-features-plugin': 7.29.3(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -7269,7 +7482,7 @@ snapshots: '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-globals': 7.28.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) '@babel/traverse': 7.29.0 transitivePeerDependencies: @@ -7278,13 +7491,13 @@ snapshots: '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/template': 7.28.6 '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -7293,28 +7506,28 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) transitivePeerDependencies: - supports-color @@ -7322,17 +7535,17 @@ snapshots: '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color @@ -7341,7 +7554,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -7349,28 +7562,28 @@ snapshots: '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -7378,7 +7591,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -7386,7 +7599,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-identifier': 7.28.5 '@babel/traverse': 7.29.0 transitivePeerDependencies: @@ -7396,7 +7609,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -7404,28 +7617,28 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) '@babel/traverse': 7.29.0 @@ -7435,7 +7648,7 @@ snapshots: '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color @@ -7443,12 +7656,12 @@ snapshots: '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color @@ -7456,13 +7669,13 @@ snapshots: '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-class-features-plugin': 7.29.3(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -7471,24 +7684,24 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-create-class-features-plugin': 7.29.3(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-react-constant-elements@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.29.0)': dependencies: @@ -7497,12 +7710,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-module-imports': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) '@babel/types': 7.29.0 transitivePeerDependencies: @@ -7512,29 +7735,29 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-runtime@7.29.0(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.0) babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.0) babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.0) @@ -7545,12 +7768,12 @@ snapshots: '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color @@ -7558,24 +7781,24 @@ snapshots: '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-create-class-features-plugin': 7.29.3(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: @@ -7584,32 +7807,32 @@ snapshots: '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/preset-env@7.29.3(@babel/core@7.29.0)': dependencies: '@babel/compat-data': 7.29.3 '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-option': 7.27.1 '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0) '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) @@ -7684,14 +7907,14 @@ snapshots: '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/types': 7.29.0 esutils: 2.0.3 '@babel/preset-react@7.28.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-option': 7.27.1 '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.29.0) '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) @@ -7703,7 +7926,7 @@ snapshots: '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-option': 7.27.1 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) @@ -8118,7 +8341,7 @@ snapshots: '@docusaurus/logger': 3.10.1 '@docusaurus/utils': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) babel-plugin-dynamic-import-node: 2.3.3 - fs-extra: 11.3.3 + fs-extra: 11.4.0 tslib: 2.8.1 transitivePeerDependencies: - '@swc/core' @@ -8277,7 +8500,7 @@ snapshots: escape-html: 1.0.3 estree-util-value-to-estree: 3.5.0 file-loader: 6.2.0(webpack@5.106.2(@swc/core@1.15.33)) - fs-extra: 11.3.3 + fs-extra: 11.4.0 image-size: 2.0.2 mdast-util-mdx: 3.0.0 mdast-util-to-string: 4.0.0 @@ -8306,7 +8529,7 @@ snapshots: dependencies: '@docusaurus/types': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@types/history': 4.7.11 - '@types/react': 19.2.14 + '@types/react': 19.2.17 '@types/react-router-config': 5.0.11 '@types/react-router-dom': 5.3.3 react: 19.2.5 @@ -8334,7 +8557,7 @@ snapshots: cheerio: 1.0.0-rc.12 combine-promises: 1.2.0 feed: 4.2.2 - fs-extra: 11.3.3 + fs-extra: 11.4.0 lodash: 4.17.23 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) @@ -8375,7 +8598,7 @@ snapshots: '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@types/react-router-config': 5.0.11 combine-promises: 1.2.0 - fs-extra: 11.3.3 + fs-extra: 11.4.0 js-yaml: 4.1.1 lodash: 4.17.23 react: 19.2.5 @@ -8409,7 +8632,7 @@ snapshots: '@docusaurus/types': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@docusaurus/utils': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - fs-extra: 11.3.3 + fs-extra: 11.4.0 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) tslib: 2.8.1 @@ -8464,7 +8687,7 @@ snapshots: '@docusaurus/core': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)))(@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.5))(@rspack/core@1.7.11)(@swc/core@1.15.33)(lightningcss@1.32.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.3) '@docusaurus/types': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@docusaurus/utils': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - fs-extra: 11.3.3 + fs-extra: 11.4.0 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) react-json-view-lite: 2.5.0(react@19.2.5) @@ -8574,7 +8797,7 @@ snapshots: '@docusaurus/utils': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@docusaurus/utils-validation': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - fs-extra: 11.3.3 + fs-extra: 11.4.0 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) sitemap: 7.1.3 @@ -8669,7 +8892,7 @@ snapshots: '@docusaurus/react-loadable@6.0.0(react@19.2.5)': dependencies: - '@types/react': 19.2.14 + '@types/react': 19.2.17 react: 19.2.5 '@docusaurus/theme-classic@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)))(@rspack/core@1.7.11)(@swc/core@1.15.33)(@types/react@19.2.14)(lightningcss@1.32.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.3)': @@ -8728,7 +8951,7 @@ snapshots: '@docusaurus/utils': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@types/history': 4.7.11 - '@types/react': 19.2.14 + '@types/react': 19.2.17 '@types/react-router-config': 5.0.11 clsx: 2.1.1 parse-numeric-range: 1.3.0 @@ -8759,7 +8982,7 @@ snapshots: algoliasearch-helper: 3.28.2(algoliasearch@5.52.0) clsx: 2.1.1 eta: 2.2.0 - fs-extra: 11.3.3 + fs-extra: 11.4.0 lodash: 4.17.23 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) @@ -8788,7 +9011,7 @@ snapshots: '@docusaurus/theme-translations@3.10.1': dependencies: - fs-extra: 11.3.3 + fs-extra: 11.4.0 tslib: 2.8.1 '@docusaurus/tsconfig@3.10.1': {} @@ -8798,7 +9021,7 @@ snapshots: '@mdx-js/mdx': 3.1.1 '@types/history': 4.7.11 '@types/mdast': 4.0.4 - '@types/react': 19.2.14 + '@types/react': 19.2.17 commander: 5.1.0 joi: 17.13.3 react: 19.2.5 @@ -8832,7 +9055,7 @@ snapshots: '@docusaurus/logger': 3.10.1 '@docusaurus/utils': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@docusaurus/utils-common': 3.10.1(@swc/core@1.15.33)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - fs-extra: 11.3.3 + fs-extra: 11.4.0 joi: 17.13.3 js-yaml: 4.1.1 lodash: 4.17.23 @@ -8854,7 +9077,7 @@ snapshots: escape-string-regexp: 4.0.0 execa: 5.1.1 file-loader: 6.2.0(webpack@5.106.2(@swc/core@1.15.33)) - fs-extra: 11.3.3 + fs-extra: 11.4.0 github-slugger: 1.5.0 globby: 11.1.0 gray-matter: 4.0.3 @@ -8989,7 +9212,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/yargs': 17.0.35 chalk: 4.1.2 @@ -9153,6 +9376,10 @@ snapshots: lit: 3.3.2 tslib: 2.8.1 + '@lit/react@1.0.8(@types/react@19.2.17)': + dependencies: + '@types/react': 19.2.17 + '@lit/reactive-element@2.1.2': dependencies: '@lit-labs/ssr-dom-shim': 1.5.1 @@ -9395,6 +9622,8 @@ snapshots: '@polka/url@1.0.0-next.29': {} + '@rolldown/pluginutils@1.0.0-beta.27': {} + '@rollup/pluginutils@5.3.0(rollup@4.59.0)': dependencies: '@types/estree': 1.0.8 @@ -9806,6 +10035,27 @@ snapshots: dependencies: defer-to-connect: 2.0.1 + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/runtime': 7.28.6 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + dependencies: + '@babel/runtime': 7.28.6 + '@testing-library/dom': 10.4.1 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -9813,14 +10063,37 @@ snapshots: '@types/argparse@1.0.38': {} + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.0 + '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/bonjour@3.5.13': dependencies: - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/chai@5.2.3': dependencies: @@ -9835,11 +10108,11 @@ snapshots: '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.19.8 - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/connect@3.4.38': dependencies: - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/debug@4.1.13': dependencies: @@ -9865,7 +10138,7 @@ snapshots: '@types/express-serve-static-core@4.19.8': dependencies: - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/qs': 6.15.0 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -9901,7 +10174,7 @@ snapshots: '@types/http-proxy@1.17.17': dependencies: - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/istanbul-lib-coverage@2.0.6': {} @@ -9935,27 +10208,35 @@ snapshots: '@types/range-parser@1.2.7': {} + '@types/react-dom@19.2.3(@types/react@19.2.17)': + dependencies: + '@types/react': 19.2.17 + '@types/react-router-config@5.0.11': dependencies: '@types/history': 4.7.11 - '@types/react': 19.2.14 + '@types/react': 19.2.17 '@types/react-router': 5.1.20 '@types/react-router-dom@5.3.3': dependencies: '@types/history': 4.7.11 - '@types/react': 19.2.14 + '@types/react': 19.2.17 '@types/react-router': 5.1.20 '@types/react-router@5.1.20': dependencies: '@types/history': 4.7.11 - '@types/react': 19.2.14 + '@types/react': 19.2.17 '@types/react@19.2.14': dependencies: csstype: 3.2.3 + '@types/react@19.2.17': + dependencies: + csstype: 3.2.3 + '@types/retry@0.12.2': {} '@types/sax@1.2.7': @@ -9965,11 +10246,11 @@ snapshots: '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/send@1.2.1': dependencies: - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/serve-index@1.9.4': dependencies: @@ -9978,12 +10259,12 @@ snapshots: '@types/serve-static@1.15.10': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/send': 0.17.6 '@types/sockjs@0.3.36': dependencies: - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/trusted-types@2.0.7': {} @@ -9993,11 +10274,11 @@ snapshots: '@types/ws@6.0.4': dependencies: - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/ws@8.18.1': dependencies: - '@types/node': 10.17.60 + '@types/node': 17.0.45 '@types/yargs-parser@21.0.3': {} @@ -10007,7 +10288,19 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitest/coverage-v8@4.0.18(vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0))': + '@vitejs/plugin-react@4.7.0(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) + transitivePeerDependencies: + - supports-color + + '@vitest/coverage-v8@4.0.18(vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.18 @@ -10019,7 +10312,7 @@ snapshots: obug: 2.1.1 std-env: 3.10.0 tinyrainbow: 3.0.3 - vitest: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0) + vitest: 4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) '@vitest/expect@4.0.18': dependencies: @@ -10030,13 +10323,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.18(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0))': + '@vitest/mocker@4.0.18(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.0.18 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + vite: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) '@vitest/pretty-format@4.0.18': dependencies: @@ -10297,6 +10590,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.3: {} ansis@3.17.0: {} @@ -10314,6 +10609,10 @@ snapshots: argparse@2.0.1: {} + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + array-flatten@1.1.1: {} array-union@2.1.0: {} @@ -11015,6 +11314,8 @@ snapshots: dependencies: '@leichtgewicht/ip-codec': 2.0.5 + dom-accessibility-api@0.5.16: {} + dom-converter@0.2.0: dependencies: utila: 0.4.0 @@ -11390,6 +11691,12 @@ snapshots: jsonfile: 6.2.0 universalify: 2.0.1 + fs-extra@11.4.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + fsevents@2.3.3: optional: true @@ -11904,7 +12211,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 10.17.60 + '@types/node': 17.0.45 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -11918,7 +12225,7 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 10.17.60 + '@types/node': 17.0.45 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -12133,6 +12440,8 @@ snapshots: dependencies: yallist: 4.0.0 + lz-string@1.5.0: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -13419,6 +13728,12 @@ snapshots: lodash: 4.17.23 renderkid: 3.0.0 + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + pretty-time@1.1.0: {} prism-react-renderer@2.4.1(react@19.2.5): @@ -13510,10 +13825,17 @@ snapshots: react: 19.2.5 scheduler: 0.27.0 + react-dom@19.2.8(react@19.2.8): + dependencies: + react: 19.2.8 + scheduler: 0.27.0 + react-fast-compare@3.2.2: {} react-is@16.13.1: {} + react-is@17.0.2: {} + react-json-view-lite@2.5.0(react@19.2.5): dependencies: react: 19.2.5 @@ -13524,6 +13846,8 @@ snapshots: react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.2.5)' webpack: 5.106.2(@swc/core@1.15.33) + react-refresh@0.17.0: {} + react-router-config@5.1.1(react-router@5.3.4(react@19.2.5))(react@19.2.5): dependencies: '@babel/runtime': 7.28.6 @@ -13556,6 +13880,8 @@ snapshots: react@19.2.5: {} + react@19.2.8: {} + readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -14391,7 +14717,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-plugin-dts@4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)): + vite-plugin-dts@4.5.4(rollup@4.59.0)(typescript@5.8.3)(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)): dependencies: '@microsoft/api-extractor': 7.57.4 '@rollup/pluginutils': 5.3.0(rollup@4.59.0) @@ -14404,13 +14730,13 @@ snapshots: magic-string: 0.30.21 typescript: 5.8.3 optionalDependencies: - vite: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + vite: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0): + vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) @@ -14423,11 +14749,12 @@ snapshots: jiti: 1.21.7 lightningcss: 1.32.0 terser: 5.46.0 + yaml: 2.9.0 - vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0): + vitest@4.0.18(jiti@1.21.7)(jsdom@28.1.0)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0): dependencies: '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)) + '@vitest/mocker': 4.0.18(vite@7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.0.18 '@vitest/runner': 4.0.18 '@vitest/snapshot': 4.0.18 @@ -14444,7 +14771,7 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0) + vite: 7.3.1(jiti@1.21.7)(lightningcss@1.32.0)(terser@5.46.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: jsdom: 28.1.0 @@ -14680,6 +15007,9 @@ snapshots: yallist@4.0.0: {} + yaml@2.9.0: + optional: true + yocto-queue@1.2.2: {} zustand@5.0.11(@types/react@19.2.14)(react@19.2.5): diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bbd01da..51ee2b8 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,7 @@ packages: - 'packages/*' - 'apps/*' + - 'examples/*' - 'website' allowBuilds: '@swc/core': true diff --git a/tsconfig.json b/tsconfig.json index 25ecbbc..69b6948 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,9 @@ { "path": "packages/ui" }, + { + "path": "packages/react" + }, { "path": "packages/connector-directline" }, From 61ffff63edf420de05bd2de7e880314003499471 Mon Sep 17 00:00:00 2001 From: Hamza Agar Date: Mon, 27 Jul 2026 20:26:24 +0300 Subject: [PATCH 2/2] chore(release): bump to 0.9.0 to match published @chativa suite @chativa/core, @chativa/genui, and @chativa/ui are already published at 0.9.0; this repo's package.json files still said 0.0.1 (the release workflow bumps versions from the git tag, not from committed files). Needed so pnpm publish resolves this package's workspace:* dependencies to the real published version instead of embedding 0.0.1 into @chativa/react's package.json. Verified via `pnpm pack`: @chativa/core and @chativa/ui both resolve to "0.9.0" in the packed tarball. --- packages/core/package.json | 2 +- packages/genui/package.json | 2 +- packages/react/package.json | 2 +- packages/ui/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 97e1485..7bfa36c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@chativa/core", - "version": "0.0.1", + "version": "0.9.0", "description": "Chativa core — domain interfaces, registries, stores and chat engine (framework-agnostic).", "author": "Hamza Agar", "license": "MIT", diff --git a/packages/genui/package.json b/packages/genui/package.json index 8e58711..f051fe3 100644 --- a/packages/genui/package.json +++ b/packages/genui/package.json @@ -1,6 +1,6 @@ { "name": "@chativa/genui", - "version": "0.0.1", + "version": "0.9.0", "description": "Chativa Generative UI — stream LitElement components inline inside chat messages.", "author": "Hamza Agar", "license": "MIT", diff --git a/packages/react/package.json b/packages/react/package.json index afb8607..2279904 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@chativa/react", - "version": "0.0.1", + "version": "0.9.0", "description": "Chativa React — typed React components (ChatIva, ChatBotButton, ChativaProvider) wrapping the Chativa chat widget for React/Next.js apps.", "author": "Hamza Agar", "license": "MIT", diff --git a/packages/ui/package.json b/packages/ui/package.json index b47133b..ea0f6c7 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@chativa/ui", - "version": "0.0.1", + "version": "0.9.0", "description": "Chativa UI — LitElement web components for the chat widget (chat-iva, chat-bot-button).", "author": "Hamza Agar", "license": "MIT",