diff --git a/.github/workflows/pull-request-checks.yml b/.github/workflows/pull-request-checks.yml new file mode 100644 index 0000000..70d1706 --- /dev/null +++ b/.github/workflows/pull-request-checks.yml @@ -0,0 +1,35 @@ +name: Pull Request Checks + +on: + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + unit-tests: + name: unit-tests + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up pnpm + uses: pnpm/action-setup@v4 + with: + version: 10.33.2 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run unit tests + run: pnpm test diff --git a/apps/desktop/renderer/package.json b/apps/desktop/renderer/package.json index 8ced03d..efc429f 100644 --- a/apps/desktop/renderer/package.json +++ b/apps/desktop/renderer/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "vite", "build": "vite build", - "preview": "vite preview" + "preview": "vite preview", + "test": "vitest run" }, "dependencies": { "@radix-ui/react-slot": "^1.2.4", @@ -25,7 +26,12 @@ "zustand": "^5.0.12" }, "devDependencies": { + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.6.1", "@vitejs/plugin-react": "^4.3.0", - "vite": "^6.0.0" + "jsdom": "^29.1.1", + "vite": "^6.0.0", + "vitest": "^4.1.6" } } diff --git a/apps/desktop/renderer/src/App.tsx b/apps/desktop/renderer/src/App.tsx index b997ca3..3400a1b 100644 --- a/apps/desktop/renderer/src/App.tsx +++ b/apps/desktop/renderer/src/App.tsx @@ -18,6 +18,8 @@ export default function App() { } /> } /> + } /> + } /> } /> diff --git a/apps/desktop/renderer/src/WorkflowEditor.test.tsx b/apps/desktop/renderer/src/WorkflowEditor.test.tsx new file mode 100644 index 0000000..7031989 --- /dev/null +++ b/apps/desktop/renderer/src/WorkflowEditor.test.tsx @@ -0,0 +1,109 @@ +import { render, screen, waitFor } from "@testing-library/react"; +import { beforeEach, describe, expect, test, vi } from "vitest"; + +const mocks = vi.hoisted(() => ({ + desktopApi: {}, +})); + +vi.mock("./lib/api-client", () => ({ + getAppApi: () => mocks.desktopApi, +})); + +vi.mock("@xyflow/react", async () => { + const React = await import("react"); + return { + Background: () => null, + BaseEdge: () => null, + Controls: () => null, + Handle: () => null, + MarkerType: { ArrowClosed: "arrowclosed" }, + MiniMap: () => null, + Position: { Top: "top", Bottom: "bottom", Left: "left", Right: "right" }, + ReactFlow: ({ children }) =>
{children}
, + useNodesState: (initialNodes) => { + const [nodes, setNodes] = React.useState(initialNodes); + return [nodes, setNodes, vi.fn()]; + }, + }; +}); + +import WorkflowEditor from "./WorkflowEditor"; +import { I18nProvider } from "./components/i18n-provider"; +import { useWorkflowEditorStore } from "./stores/workflowEditorStore"; + +const workflow = { + id: "default-codex", + name: "Default Codex", + visible: true, + version: 1, + runtime: { + engine: "langgraph", + backend: "codex", + model: "", + workspaceAccess: "write", + options: {}, + }, + ui: { + layout: "vertical", + nodePositions: {}, + }, + worktree: { + enabled: false, + files: [], + customFiles: [], + removeOnComplete: false, + }, + steps: [ + { + id: "implement", + type: "agent", + label: "Implement", + prompt: "Implement the requested task.", + next: "", + inputs: [], + outputs: [{ key: "result", kind: "markdown", filename: "result.md" }], + }, + ], +}; + +function setupDesktopApi() { + Object.assign(mocks.desktopApi, { + getWorkflow: vi.fn().mockResolvedValue(workflow), + createWorkflow: vi.fn(), + createWorkflowDraft: vi.fn(), + updateWorkflow: vi.fn(), + updateWorkflowDraft: vi.fn(), + }); +} + +function renderWorkflowEditor(filename = "default-codex.json") { + return render( + + + + ); +} + +describe("WorkflowEditor", () => { + beforeEach(() => { + sessionStorage.clear(); + for (const key of Object.keys(mocks.desktopApi)) { + delete mocks.desktopApi[key]; + } + useWorkflowEditorStore.getState().resetEditor(); + setupDesktopApi(); + }); + + test("renders while an existing workflow is loading and then hydrates the draft", async () => { + renderWorkflowEditor(); + + expect(screen.getByPlaceholderText("Workflow name")).toBeInTheDocument(); + expect(screen.getByTestId("workflow-canvas")).toBeInTheDocument(); + + await waitFor(() => { + expect(mocks.desktopApi.getWorkflow).toHaveBeenCalledWith("default-codex.json"); + expect(useWorkflowEditorStore.getState().currentFilename).toBe("default-codex.json"); + }); + expect(screen.getByDisplayValue("Default Codex")).toBeInTheDocument(); + }); +}); diff --git a/apps/desktop/renderer/src/WorkflowEditor.tsx b/apps/desktop/renderer/src/WorkflowEditor.tsx index 7281f87..c75f759 100644 --- a/apps/desktop/renderer/src/WorkflowEditor.tsx +++ b/apps/desktop/renderer/src/WorkflowEditor.tsx @@ -23,6 +23,7 @@ import { WindowChrome } from "./components/window-chrome"; import { cn } from "./lib/utils"; import { getAppApi } from "./lib/api-client"; import { useConfigStore } from "./stores/configStore"; +import { getWorkflowEditorKey, useWorkflowEditorStore } from "./stores/workflowEditorStore"; import { useWorkflowStore } from "./stores/workflowStore"; const desktopApi = getAppApi(); @@ -557,12 +558,21 @@ function getReasoningLabel(value) { export default function WorkflowEditor({ filename, onClose, onSaved }) { const { t } = useI18n(); - const [workflow, setWorkflow] = useState(() => createDefaultWorkflow({ includeStartStep: !filename })); - const [currentFilename, setCurrentFilename] = useState(filename || null); - const [selectedIdx, setSelectedIdx] = useState(filename ? null : 0); - const [dirty, setDirty] = useState(false); - const [saving, setSaving] = useState(false); - const [error, setError] = useState(""); + const editorKey = useWorkflowEditorStore((s) => s.editorKey); + const storedWorkflow = useWorkflowEditorStore((s) => s.workflow); + const currentFilename = useWorkflowEditorStore((s) => s.currentFilename); + const selectedIdx = useWorkflowEditorStore((s) => s.selectedIdx); + const dirty = useWorkflowEditorStore((s) => s.dirty); + const saving = useWorkflowEditorStore((s) => s.saving); + const error = useWorkflowEditorStore((s) => s.error); + const initializeEditor = useWorkflowEditorStore((s) => s.initializeEditor); + const setWorkflow = useWorkflowEditorStore((s) => s.setWorkflow); + const setCurrentFilename = useWorkflowEditorStore((s) => s.setCurrentFilename); + const setSelectedIdx = useWorkflowEditorStore((s) => s.setSelectedIdx); + const setDirty = useWorkflowEditorStore((s) => s.setDirty); + const setSaving = useWorkflowEditorStore((s) => s.setSaving); + const setError = useWorkflowEditorStore((s) => s.setError); + const resetEditor = useWorkflowEditorStore((s) => s.resetEditor); const [showBackConfirm, setShowBackConfirm] = useState(false); const [confirmRemoveIdx, setConfirmRemoveIdx] = useState(null); const [newCustomWorktreeFile, setNewCustomWorktreeFile] = useState(""); @@ -573,6 +583,8 @@ export default function WorkflowEditor({ filename, onClose, onSaved }) { const loadWorkflowConfig = useConfigStore((s) => s.loadWorkflowConfig); const loadWorkflows = useConfigStore((s) => s.loadWorkflows); const showToast = useWorkflowStore((s) => s.showToast); + const fallbackWorkflow = useMemo(() => createDefaultWorkflow({ includeStartStep: !filename }), [filename]); + const workflow = storedWorkflow || fallbackWorkflow; const isNew = !currentFilename; const selected = selectedIdx !== null ? workflow.steps[selectedIdx] : null; const worktreeFiles = Array.isArray(workflow.worktree?.files) ? workflow.worktree.files : []; @@ -590,9 +602,10 @@ export default function WorkflowEditor({ filename, onClose, onSaved }) { const selectedNodePanelRef = useRef(null); const [flowInstance, setFlowInstance] = useState(null); - useEffect(() => { - setCurrentFilename(filename || null); - }, [filename]); + function closeEditor() { + resetEditor(); + onClose(); + } useEffect(() => { setLiveNodes((currentNodes) => { @@ -634,23 +647,30 @@ export default function WorkflowEditor({ filename, onClose, onSaved }) { }, [flowInstance, selected?.id]); useEffect(() => { + const nextEditorKey = getWorkflowEditorKey(filename); + if (editorKey === nextEditorKey && storedWorkflow) return; + if (!filename) { const next = createDefaultWorkflow(); - setWorkflow(next); - setSelectedIdx(next.steps.length > 0 ? 0 : null); - setDirty(false); + initializeEditor({ + filename: null, + workflow: next, + selectedIdx: next.steps.length > 0 ? 0 : null, + }); return; } desktopApi.getWorkflow(filename) .then((data) => { const next = normalizeWorkflow(data); - setWorkflow(next); - setSelectedIdx(next.steps.length > 0 ? 0 : null); - setDirty(false); + initializeEditor({ + filename, + workflow: next, + selectedIdx: next.steps.length > 0 ? 0 : null, + }); }) .catch(() => setError(t("editor.loadWorkflowFailed"))); - }, [filename]); + }, [filename, editorKey, storedWorkflow, initializeEditor, setError, t]); function updateWorkflow(patch) { setWorkflow((prev) => relinkSteps({ ...prev, ...patch })); @@ -1158,7 +1178,10 @@ export default function WorkflowEditor({ filename, onClose, onSaved }) { showToast(t(draft ? "settings.workflowDraftSaved" : "settings.workflowSaved")); loadWorkflowConfig(); loadWorkflows(); - if (shouldClose) onSaved(savedFilename); + if (shouldClose) { + resetEditor(); + onSaved(savedFilename); + } } catch (err) { setError(err.message || t("editor.saveWorkflowFailed")); } finally { @@ -1170,7 +1193,7 @@ export default function WorkflowEditor({ filename, onClose, onSaved }) {
- dirty ? setShowBackConfirm(true) : onClose()} label={t("editor.back")} className="-ml-2" /> + dirty ? setShowBackConfirm(true) : closeEditor()} label={t("editor.back")} className="-ml-2" /> { @@ -1180,10 +1203,6 @@ export default function WorkflowEditor({ filename, onClose, onSaved }) { placeholder={t("editor.workflowName")} className="no-drag max-w-xs" /> - - - LangGraph DSL - @@ -1906,7 +1925,7 @@ export default function WorkflowEditor({ filename, onClose, onSaved }) {

{t("editor.unsavedChangesConfirm")}

- +
diff --git a/apps/desktop/renderer/src/pages/SettingsPage.tsx b/apps/desktop/renderer/src/pages/SettingsPage.tsx index 1e9340d..91b8059 100644 --- a/apps/desktop/renderer/src/pages/SettingsPage.tsx +++ b/apps/desktop/renderer/src/pages/SettingsPage.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { useLocation, useNavigate, useParams } from "react-router-dom"; import { Eye, EyeOff, Trash2 } from "lucide-react"; import WorkflowEditor from "../WorkflowEditor"; import { BackButton } from "../components/back-button"; @@ -13,9 +14,10 @@ import { useWorkflowStore } from "../stores/workflowStore"; export default function SettingsPage() { const { t } = useI18n(); + const location = useLocation(); + const navigate = useNavigate(); + const { filename } = useParams(); const [activeTab, setActiveTab] = useState("workflows"); - const [editingWorkflow, setEditingWorkflow] = useState(null); - const [showEditor, setShowEditor] = useState(false); const [savingMobileAccess, setSavingMobileAccess] = useState(false); const [savingAiBackend, setSavingAiBackend] = useState(false); const [confirmRemoveWorkflow, setConfirmRemoveWorkflow] = useState(null); @@ -57,14 +59,19 @@ export default function SettingsPage() { loadWorkFolders(); }, []); - if (showEditor) { + const isCreatingWorkflow = location.pathname === "/settings/workflows/new"; + const isEditingWorkflow = Boolean(filename); + + if (isCreatingWorkflow || isEditingWorkflow) { return ( { setShowEditor(false); setEditingWorkflow(null); loadWorkflows(); }} + filename={filename || null} + onClose={() => { + loadWorkflows(); + navigate("/settings"); + }} onSaved={() => { - setShowEditor(false); - setEditingWorkflow(null); + navigate("/settings"); }} /> ); @@ -200,7 +207,7 @@ export default function SettingsPage() {

{t("settings.workflows")}

- +
{workflows.length === 0 ? (
@@ -240,7 +247,7 @@ export default function SettingsPage() { > {visible ? : } - + + ), +})); + +import SettingsPage from "./SettingsPage"; +import { I18nProvider } from "../components/i18n-provider"; +import { useConfigStore } from "../stores/configStore"; +import { useWorkflowEditorStore } from "../stores/workflowEditorStore"; + +function setupDesktopApi() { + Object.assign(mocks.desktopApi, { + getWorkflowConfig: vi.fn().mockResolvedValue({ mobileAccessEnabled: false, aiBackendOverride: "codex" }), + listWorkflows: vi.fn().mockResolvedValue({ + activeWorkflow: "default-codex.json", + workflows: [{ filename: "default-codex.json", name: "Default Codex", phaseCount: 1, visible: true }], + }), + listSkills: vi.fn().mockResolvedValue({ skills: [] }), + listWorkFolders: vi.fn().mockResolvedValue([]), + getWorkflow: vi.fn(), + setMobileAccessEnabled: vi.fn(), + setAiBackendOverride: vi.fn(), + setWorkflowVisible: vi.fn().mockResolvedValue({}), + removeWorkflow: vi.fn(), + pickFolder: vi.fn(), + addWorkFolder: vi.fn(), + removeWorkFolder: vi.fn(), + saveSkill: vi.fn(), + deleteSkill: vi.fn(), + importSkills: vi.fn(), + createWorkflow: vi.fn(), + createWorkflowDraft: vi.fn(), + updateWorkflow: vi.fn(), + updateWorkflowDraft: vi.fn(), + }); +} + +function renderSettings(initialEntry = "/settings") { + return render( + + + + } /> + } /> + } /> + + + + ); +} + +describe("SettingsPage workflow editor routes", () => { + afterEach(() => { + cleanup(); + }); + + beforeEach(() => { + sessionStorage.clear(); + for (const key of Object.keys(mocks.desktopApi)) { + delete mocks.desktopApi[key]; + } + useWorkflowEditorStore.getState().resetEditor(); + useConfigStore.setState({ + workflowConfig: null, + workflows: [], + skills: [], + activeWorkflowFile: "", + workFolders: [], + selectedFolder: "", + }); + setupDesktopApi(); + }); + + test("opens a new workflow editor from the route", () => { + renderSettings("/settings/workflows/new"); + + expect(screen.getByRole("region", { name: "Workflow Editor" })).toBeInTheDocument(); + expect(screen.getByTestId("workflow-editor-filename")).toHaveTextContent("new"); + }); + + test("opens an existing workflow editor from the route", () => { + renderSettings("/settings/workflows/default-codex.json/edit"); + + expect(screen.getByRole("region", { name: "Workflow Editor" })).toBeInTheDocument(); + expect(screen.getByTestId("workflow-editor-filename")).toHaveTextContent("default-codex.json"); + }); + + test("navigates to the workflow editor when Edit is clicked", async () => { + const user = userEvent.setup(); + renderSettings("/settings"); + + await user.click(await screen.findByRole("button", { name: "Edit" })); + + expect(screen.getByRole("region", { name: "Workflow Editor" })).toBeInTheDocument(); + expect(screen.getByTestId("workflow-editor-filename")).toHaveTextContent("default-codex.json"); + }); +}); diff --git a/apps/desktop/renderer/src/stores/workflowEditorStore.test.ts b/apps/desktop/renderer/src/stores/workflowEditorStore.test.ts new file mode 100644 index 0000000..075602b --- /dev/null +++ b/apps/desktop/renderer/src/stores/workflowEditorStore.test.ts @@ -0,0 +1,79 @@ +import { beforeEach, describe, expect, test } from "vitest"; +import { getWorkflowEditorKey, useWorkflowEditorStore } from "./workflowEditorStore"; + +function resetStore() { + sessionStorage.clear(); + useWorkflowEditorStore.getState().resetEditor(); +} + +describe("workflowEditorStore", () => { + beforeEach(() => { + resetStore(); + }); + + test("uses a stable key for new and existing workflows", () => { + expect(getWorkflowEditorKey(null)).toBe("__new__"); + expect(getWorkflowEditorKey("default-codex.json")).toBe("default-codex.json"); + }); + + test("initializes workflow editor draft state", () => { + const workflow = { id: "workflow", name: "Default", steps: [{ id: "implement" }] }; + + useWorkflowEditorStore.getState().initializeEditor({ + filename: "default-codex.json", + workflow, + selectedIdx: 0, + }); + + const state = useWorkflowEditorStore.getState(); + expect(state.editorKey).toBe("default-codex.json"); + expect(state.currentFilename).toBe("default-codex.json"); + expect(state.selectedIdx).toBe(0); + expect(state.dirty).toBe(false); + expect(state.saving).toBe(false); + expect(state.error).toBe(""); + expect(state.workflow).toEqual(workflow); + }); + + test("supports function updates for workflow and selected node", () => { + useWorkflowEditorStore.getState().initializeEditor({ + filename: null, + workflow: { id: "workflow", steps: [] }, + selectedIdx: 0, + }); + + useWorkflowEditorStore.getState().setWorkflow((workflow) => ({ + ...workflow, + steps: [...workflow.steps, { id: "review" }], + })); + useWorkflowEditorStore.getState().setSelectedIdx((selectedIdx) => selectedIdx + 1); + useWorkflowEditorStore.getState().setDirty(true); + + const state = useWorkflowEditorStore.getState(); + expect(state.workflow.steps).toEqual([{ id: "review" }]); + expect(state.selectedIdx).toBe(1); + expect(state.dirty).toBe(true); + }); + + test("resetEditor clears the active draft state", () => { + useWorkflowEditorStore.getState().initializeEditor({ + filename: "default-codex.json", + workflow: { id: "workflow", steps: [] }, + selectedIdx: 0, + }); + useWorkflowEditorStore.getState().setDirty(true); + useWorkflowEditorStore.getState().setSaving(true); + useWorkflowEditorStore.getState().setError("Failed"); + + useWorkflowEditorStore.getState().resetEditor(); + + const state = useWorkflowEditorStore.getState(); + expect(state.editorKey).toBe(""); + expect(state.workflow).toBe(null); + expect(state.currentFilename).toBe(null); + expect(state.selectedIdx).toBe(null); + expect(state.dirty).toBe(false); + expect(state.saving).toBe(false); + expect(state.error).toBe(""); + }); +}); diff --git a/apps/desktop/renderer/src/stores/workflowEditorStore.ts b/apps/desktop/renderer/src/stores/workflowEditorStore.ts new file mode 100644 index 0000000..18d9857 --- /dev/null +++ b/apps/desktop/renderer/src/stores/workflowEditorStore.ts @@ -0,0 +1,78 @@ +import { create } from "zustand"; +import { createJSONStorage, persist } from "zustand/middleware"; + +const NEW_WORKFLOW_EDITOR_KEY = "__new__"; + +export function getWorkflowEditorKey(filename) { + return filename || NEW_WORKFLOW_EDITOR_KEY; +} + +export const useWorkflowEditorStore = create()( + persist( + (set) => ({ + editorKey: "", + workflow: null, + currentFilename: null, + selectedIdx: null, + dirty: false, + saving: false, + error: "", + + initializeEditor({ filename, workflow, selectedIdx }) { + set({ + editorKey: getWorkflowEditorKey(filename), + workflow, + currentFilename: filename || null, + selectedIdx, + dirty: false, + saving: false, + error: "", + }); + }, + setWorkflow(updater) { + set((state) => ({ + workflow: typeof updater === "function" ? updater(state.workflow) : updater, + })); + }, + setCurrentFilename(filename) { + set({ currentFilename: filename || null }); + }, + setSelectedIdx(updater) { + set((state) => ({ + selectedIdx: typeof updater === "function" ? updater(state.selectedIdx) : updater, + })); + }, + setDirty(dirty) { + set({ dirty }); + }, + setSaving(saving) { + set({ saving }); + }, + setError(error) { + set({ error: error || "" }); + }, + resetEditor() { + set({ + editorKey: "", + workflow: null, + currentFilename: null, + selectedIdx: null, + dirty: false, + saving: false, + error: "", + }); + }, + }), + { + name: "workflow-editor-draft", + storage: createJSONStorage(() => sessionStorage), + partialize: (state) => ({ + editorKey: state.editorKey, + workflow: state.workflow, + currentFilename: state.currentFilename, + selectedIdx: state.selectedIdx, + dirty: state.dirty, + }), + } + ) +); diff --git a/apps/desktop/renderer/src/test/setup.ts b/apps/desktop/renderer/src/test/setup.ts new file mode 100644 index 0000000..7dfdf73 --- /dev/null +++ b/apps/desktop/renderer/src/test/setup.ts @@ -0,0 +1,7 @@ +import "@testing-library/jest-dom/vitest"; + +window.ResizeObserver = window.ResizeObserver || class { + observe() {} + unobserve() {} + disconnect() {} +}; diff --git a/apps/desktop/renderer/vite.config.ts b/apps/desktop/renderer/vite.config.ts index d887bd1..4bc376a 100644 --- a/apps/desktop/renderer/vite.config.ts +++ b/apps/desktop/renderer/vite.config.ts @@ -5,6 +5,10 @@ import tailwindcss from "@tailwindcss/vite"; export default defineConfig({ base: "./", plugins: [react(), tailwindcss()], + test: { + environment: "jsdom", + setupFiles: "./src/test/setup.ts", + }, server: { proxy: { "/api": "http://localhost:3000", diff --git a/package.json b/package.json index 95dd37b..9187548 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "make:desktop": "pnpm build:desktop && electron-forge make", "publish:desktop": "pnpm build:desktop && electron-forge publish", "start:desktop": "pnpm run prepare:electron && NODE_OPTIONS='--import tsx' electron .", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "pnpm --dir apps/desktop/renderer test" }, "keywords": [], "author": "", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a43b7e1..de710e2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -142,15 +142,33 @@ importers: specifier: ^5.0.12 version: 5.0.12(@types/react@19.2.14)(react@19.2.5)(use-sync-external-store@1.6.0(react@19.2.5)) devDependencies: + '@testing-library/jest-dom': + specifier: ^6.9.1 + version: 6.9.1 + '@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.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@testing-library/user-event': + specifier: ^14.6.1 + version: 14.6.1(@testing-library/dom@10.4.1) '@vitejs/plugin-react': specifier: ^4.3.0 version: 4.7.0(vite@6.4.2(@types/node@25.7.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.47.1)(tsx@4.21.0)) + jsdom: + specifier: ^29.1.1 + version: 29.1.1 vite: specifier: ^6.0.0 version: 6.4.2(@types/node@25.7.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.47.1)(tsx@4.21.0) + vitest: + specifier: ^4.1.6 + version: 4.1.6(@types/node@25.7.0)(jsdom@29.1.1)(vite@6.4.2(@types/node@25.7.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.47.1)(tsx@4.21.0)) packages: + '@adobe/css-tools@4.4.4': + resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} + '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.2.126': resolution: {integrity: sha512-JFlJBbeAlx7Ic5s4lGUN9SppobryXk/lIqPCvhp6KrJTQIerh3MIBzxsVIJ0MaDut7jVni/oYgsvDni7NIyqHA==} cpu: [arm64] @@ -210,6 +228,21 @@ packages: zod: optional: true + '@asamuzakjp/css-color@5.1.11': + resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/dom-selector@7.1.1': + resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/generational-cache@1.0.1': + resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} @@ -297,9 +330,49 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@bramus/specificity@2.4.2': + resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} + hasBin: true + '@cfworker/json-schema@4.1.1': resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + '@csstools/color-helpers@6.0.2': + resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} + engines: {node: '>=20.19.0'} + + '@csstools/css-calc@3.2.1': + resolution: {integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-color-parser@4.1.0': + resolution: {integrity: sha512-U0KhLYmy2GVj6q4T3WaAe6NPuFYCPQoE3b0dRGxejWDgcPp8TP7S5rVdM5ZrFaqu4N67X8YaPBw14dQSYx3IyQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.4': + resolution: {integrity: sha512-wgsqt92b7C7tQhIdPNxj0n9zuUbQlvAuI1exyzeNrOKOi62SD7ren8zqszmpVREjAOqg8cD2FqYhQfAuKjk4sw==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} + '@electron-forge/cli@7.11.1': resolution: {integrity: sha512-pk8AoLsr7t7LBAt0cFD06XFA6uxtPdvtLx06xeal7O9o7GHGCbj29WGwFoJ8Br/ENM0Ho868S3PrAn1PtBXt5g==} engines: {node: '>= 16.4.0'} @@ -724,6 +797,15 @@ packages: cpu: [x64] os: [win32] + '@exodus/bytes@1.15.0': + resolution: {integrity: sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + '@fastify/ajv-compiler@4.0.5': resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==} @@ -1319,6 +1401,35 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 || ^8 + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@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 + + '@testing-library/user-event@14.6.1': + resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + '@tootallnate/once@2.0.1': resolution: {integrity: sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==} engines: {node: '>= 10'} @@ -1326,6 +1437,9 @@ packages: '@types/appdmg@0.5.5': resolution: {integrity: sha512-G+n6DgZTZFOteITE30LnWj+HRVIGr7wMlAiLWOO02uJFWVEitaPU9JVXm9wJokkgshBawb2O1OykdcsmkkZfgg==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -1344,6 +1458,9 @@ packages: '@types/cacheable-request@6.0.3': resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} @@ -1371,6 +1488,9 @@ packages: '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -1469,6 +1589,35 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitest/expect@4.1.6': + resolution: {integrity: sha512-7EHDquPthALSV0jhhjgEW8FXaviMx7rSqu8W6oqCoAuOhKov814P99QDV1pxMA3QPv21YudvJngIhjrNI4opLg==} + + '@vitest/mocker@4.1.6': + resolution: {integrity: sha512-MCFc63czMjEInOlcY2cpQCvCN+KgbAn+60xu9cMgP4sKaLC5JNAKw7JH8QdAnoAC88hW1IiSNZ+GgVXlN1UcMQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.6': + resolution: {integrity: sha512-h5SxD/IzNhZYnrSZRsUZQIC+vD0GY8cUvq0iwsmkFKixRCKLLWqCXa/FIQ4S1R+sI+PGoojkHsdNrbZiM9Qpgw==} + + '@vitest/runner@4.1.6': + resolution: {integrity: sha512-nOPCmn2+yD0ZNmKdsXGv/UxMMWbMuKeD6GyYncNwdkYDxpQvrPSKYj2rWuDjC2Y4b6w6hjip5dBKFzEUuZe3vA==} + + '@vitest/snapshot@4.1.6': + resolution: {integrity: sha512-YhsdE6xAVfTDmzjxL2ZDUvjj+ZsgyOKe+TdQzqkD72wIOmHka8NuGQ6NpTNZv9D2Z63fbwWKJPeVpEw4EQgYxw==} + + '@vitest/spy@4.1.6': + resolution: {integrity: sha512-JFKxMx6udhwKh/Ldo270e17QX710vgunMkuPAvXjHSvC6oqLWAHhVhjg/I71q0u0CBSErIODV1Kjv0FQNSWjdg==} + + '@vitest/utils@4.1.6': + resolution: {integrity: sha512-FxIY+U81R3LGKCxaHHFRQ5+g6/iRgGLmeHWdp2Amj4ljQRrEIWHmZyDfDYBRZlpyqA7qKxtS9DD1dhk8RnRIVQ==} + '@vscode/sudo-prompt@9.3.2': resolution: {integrity: sha512-gcXoCN00METUNFeQOFJ+C9xUI0DKB+0EGMVg7wbVYRHBw2Eq3fKisDZOkRdOz3kqXRKOENMfShPOmypw1/8nOw==} @@ -1634,9 +1783,20 @@ packages: append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + async@1.5.2: resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} @@ -1681,6 +1841,9 @@ packages: before-after-hook@2.2.3: resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -1766,6 +1929,10 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + chalk@3.0.0: resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} engines: {node: '>=8'} @@ -1942,6 +2109,13 @@ packages: resolution: {integrity: sha512-n63i0lZ0rvQ6FXiGQ+/JFCKAUyPFhLQYJIqKaa+tSJtfKeULF/IDNDAbdnSIxgS4NTuw2b0+lj8LzfITuq+ZxQ==} engines: {node: '>=12.10'} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -1988,6 +2162,10 @@ packages: resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} engines: {node: '>=12'} + data-urls@7.0.0: + resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -2009,6 +2187,9 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} @@ -2063,6 +2244,12 @@ packages: dir-compare@4.2.0: resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + ds-store@0.1.6: resolution: {integrity: sha512-kY21M6Lz+76OS3bnCzjdsJSF7LBpLYGCVfavW8TgQD2XkcqIZ86W0y9qUDZu6fp7SIZzqosMDW2zi7zVFfv4hw==} @@ -2120,6 +2307,10 @@ packages: resolution: {integrity: sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==} engines: {node: '>=10.13.0'} + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -2196,6 +2387,9 @@ packages: estree-util-is-identifier-name@3.0.0: resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} @@ -2222,6 +2416,10 @@ packages: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} engines: {node: '>=6'} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + exponential-backoff@3.1.3: resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} @@ -2505,6 +2703,10 @@ packages: hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + html-url-attributes@3.0.1: resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} @@ -2662,6 +2864,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -2704,6 +2909,15 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + jsdom@29.1.1: + resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -2891,6 +3105,10 @@ packages: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} + lru-cache@11.3.6: + resolution: {integrity: sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -2903,6 +3121,10 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + macos-alias@0.2.12: resolution: {integrity: sha512-yiLHa7cfJcGRFq4FrR4tMlpNHb4Vy4mWnpajlSSIFM5k4Lv8/7BbbDLzCAVogWNl0LlLhizRp1drXv0hK9h0Yw==} os: [darwin] @@ -2950,6 +3172,9 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -3080,6 +3305,10 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} @@ -3230,6 +3459,9 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -3327,6 +3559,9 @@ packages: resolution: {integrity: sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==} engines: {node: '>=0.10.0'} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -3364,6 +3599,9 @@ packages: resolution: {integrity: sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ==} engines: {node: '>=4'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pe-library@1.0.1: resolution: {integrity: sha512-nh39Mo1eGWmZS7y+mK/dQIqg7S1lp38DpRxkyoHf0ZcUs/HDc+yyTjuOtTvSMZHmfSLuSQaX945u05Y2Q6UWZg==} engines: {node: '>=14', npm: '>=7'} @@ -3426,6 +3664,10 @@ packages: engines: {node: '>=14'} hasBin: true + 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} + proc-log@2.0.1: resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -3466,6 +3708,10 @@ packages: pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + qs@6.14.2: resolution: {integrity: sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==} engines: {node: '>=0.6'} @@ -3504,6 +3750,9 @@ packages: peerDependencies: react: ^19.2.5 + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-markdown@10.1.0: resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==} peerDependencies: @@ -3559,6 +3808,10 @@ packages: resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} engines: {node: '>= 10.13.0'} + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} @@ -3667,6 +3920,10 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -3755,6 +4012,9 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -3818,10 +4078,16 @@ packages: resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + stream-buffers@2.2.0: resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==} engines: {node: '>= 0.10.0'} @@ -3863,6 +4129,10 @@ packages: resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} engines: {node: '>=0.10.0'} + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + strip-outer@1.0.1: resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==} engines: {node: '>=0.10.0'} @@ -3889,6 +4159,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tailwind-merge@3.5.0: resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} @@ -3955,10 +4228,28 @@ packages: resolution: {integrity: sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==} engines: {node: '>=20'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.1.2: + resolution: {integrity: sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==} + engines: {node: '>=18'} + tinyglobby@0.2.16: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + + tldts-core@7.0.30: + resolution: {integrity: sha512-uiHN8PIB1VmWyS98eZYja4xzlYqeFZVjb4OuYlJQnZAuJhMw4PbKQOKgHKhBdJR3FE/t5mUQ1Kd80++B+qhD1Q==} + + tldts@7.0.30: + resolution: {integrity: sha512-ELrFxuqsDdHUwoh0XxDbxuLD3Wnz49Z57IFvTtvWy1hJdcMZjXLIuonjilCiWHlT2GbE4Wlv1wKVTzDFnXH1aw==} + hasBin: true + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -3982,9 +4273,17 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + tough-cookie@6.0.1: + resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + engines: {node: '>=16'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -4052,6 +4351,10 @@ packages: undici-types@7.21.0: resolution: {integrity: sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ==} + undici@7.25.0: + resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} + engines: {node: '>=20.18.1'} + unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -4184,6 +4487,51 @@ packages: yaml: optional: true + vitest@4.1.6: + resolution: {integrity: sha512-6lvjbS3p9b4CrdCmguzbh2/4uoXhGE2q71R4OX5sqF9R1bo9Xd6fGrMAfvp5wnCzlBnFVdCOp6onuTQVbo8iUQ==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.6 + '@vitest/browser-preview': 4.1.6 + '@vitest/browser-webdriverio': 4.1.6 + '@vitest/coverage-istanbul': 4.1.6 + '@vitest/coverage-v8': 4.1.6 + '@vitest/ui': 4.1.6 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + wait-on@9.0.5: resolution: {integrity: sha512-qgnbHDfDTRIp73ANEJNRW/7kn8CrDUcvZz18xotJQku/P4saTGkbIzvnMZebPmVvVNUiRq1qWAPyqCH+W4H8KA==} engines: {node: '>=20.0.0'} @@ -4203,6 +4551,10 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + webpack-sources@3.4.1: resolution: {integrity: sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==} engines: {node: '>=10.13.0'} @@ -4217,6 +4569,14 @@ packages: webpack-cli: optional: true + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@16.0.1: + resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -4229,6 +4589,11 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -4256,10 +4621,17 @@ packages: utf-8-validate: optional: true + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + xmlbuilder@15.1.1: resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} engines: {node: '>=8.0'} + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -4339,6 +4711,8 @@ packages: snapshots: + '@adobe/css-tools@4.4.4': {} + '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.2.126': optional: true @@ -4387,6 +4761,26 @@ snapshots: optionalDependencies: zod: 4.4.2 + '@asamuzakjp/css-color@5.1.11': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@asamuzakjp/dom-selector@7.1.1': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + + '@asamuzakjp/generational-cache@1.0.1': {} + + '@asamuzakjp/nwsapi@2.3.9': {} + '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -4501,8 +4895,36 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@bramus/specificity@2.4.2': + dependencies: + css-tree: 3.2.1 + '@cfworker/json-schema@4.1.1': {} + '@csstools/color-helpers@6.0.2': {} + + '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-color-parser@4.1.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/color-helpers': 6.0.2 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.4(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.0': {} + '@electron-forge/cli@7.11.1(encoding@0.1.13)': dependencies: '@electron-forge/core': 7.11.1(encoding@0.1.13) @@ -5040,6 +5462,8 @@ snapshots: '@esbuild/win32-x64@0.27.7': optional: true + '@exodus/bytes@1.15.0': {} + '@fastify/ajv-compiler@4.0.5': dependencies: ajv: 8.20.0 @@ -5624,6 +6048,40 @@ snapshots: tailwindcss: 4.2.4 vite: 6.4.2(@types/node@25.7.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.47.1)(tsx@4.21.0) + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/runtime': 7.29.2 + '@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/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.4.4 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@babel/runtime': 7.29.2 + '@testing-library/dom': 10.4.1 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': + dependencies: + '@testing-library/dom': 10.4.1 + '@tootallnate/once@2.0.1': {} '@types/appdmg@0.5.5': @@ -5631,6 +6089,8 @@ snapshots: '@types/node': 25.7.0 optional: true + '@types/aria-query@5.0.4': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.29.3 @@ -5664,6 +6124,11 @@ snapshots: '@types/node': 25.7.0 '@types/responselike': 1.0.3 + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + '@types/connect@3.4.38': dependencies: '@types/node': 25.7.0 @@ -5697,6 +6162,8 @@ snapshots: dependencies: '@types/ms': 2.1.0 + '@types/deep-eql@4.0.2': {} + '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 @@ -5816,6 +6283,47 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/expect@4.1.6': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.6 + '@vitest/utils': 4.1.6 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.6(vite@6.4.2(@types/node@25.7.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.47.1)(tsx@4.21.0))': + dependencies: + '@vitest/spy': 4.1.6 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 6.4.2(@types/node@25.7.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.47.1)(tsx@4.21.0) + + '@vitest/pretty-format@4.1.6': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.6': + dependencies: + '@vitest/utils': 4.1.6 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.6': + dependencies: + '@vitest/pretty-format': 4.1.6 + '@vitest/utils': 4.1.6 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.6': {} + + '@vitest/utils@4.1.6': + dependencies: + '@vitest/pretty-format': 4.1.6 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + '@vscode/sudo-prompt@9.3.2': {} '@webassemblyjs/ast@1.14.1': @@ -6015,8 +6523,16 @@ snapshots: append-field@1.0.0: {} + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + array-flatten@1.1.1: {} + assertion-error@2.0.1: {} + async@1.5.2: optional: true @@ -6056,6 +6572,10 @@ snapshots: before-after-hook@2.2.3: {} + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -6192,6 +6712,8 @@ snapshots: ccount@2.0.1: {} + chai@6.2.2: {} + chalk@3.0.0: dependencies: ansi-styles: 4.3.0 @@ -6341,6 +6863,13 @@ snapshots: cross-zip@4.0.1: {} + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + css.escape@1.5.1: {} + cssesc@3.0.0: {} csstype@3.2.3: {} @@ -6381,6 +6910,13 @@ snapshots: d3-selection: 3.0.0 d3-transition: 3.0.1(d3-selection@3.0.0) + data-urls@7.0.0: + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + transitivePeerDependencies: + - '@noble/hashes' + debug@2.6.9: dependencies: ms: 2.0.0 @@ -6391,6 +6927,8 @@ snapshots: decamelize@1.2.0: {} + decimal.js@10.6.0: {} + decode-named-character-reference@1.3.0: dependencies: character-entities: 2.0.2 @@ -6443,6 +6981,10 @@ snapshots: minimatch: 3.1.5 p-limit: 3.1.0 + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + ds-store@0.1.6: dependencies: bplist-creator: 0.0.8 @@ -6518,6 +7060,8 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.3 + entities@8.0.0: {} + env-paths@2.2.1: {} err-code@2.0.3: {} @@ -6628,6 +7172,10 @@ snapshots: estree-util-is-identifier-name@3.0.0: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + etag@1.8.1: {} eventemitter3@4.0.7: {} @@ -6652,6 +7200,8 @@ snapshots: signal-exit: 3.0.7 strip-eof: 1.0.0 + expect-type@1.3.0: {} + exponential-backoff@3.1.3: {} express-rate-limit@8.4.1(express@5.2.1): @@ -7094,6 +7644,12 @@ snapshots: hosted-git-info@2.8.9: {} + html-encoding-sniffer@6.0.0: + dependencies: + '@exodus/bytes': 1.15.0 + transitivePeerDependencies: + - '@noble/hashes' + html-url-attributes@3.0.1: {} http-cache-semantics@4.2.0: {} @@ -7231,6 +7787,8 @@ snapshots: is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: {} + is-promise@4.0.0: {} is-property@1.0.2: @@ -7270,6 +7828,32 @@ snapshots: js-tokens@4.0.0: {} + jsdom@29.1.1: + dependencies: + '@asamuzakjp/css-color': 5.1.11 + '@asamuzakjp/dom-selector': 7.1.1 + '@bramus/specificity': 2.4.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.4(css-tree@3.2.1) + '@exodus/bytes': 1.15.0 + css-tree: 3.2.1 + data-urls: 7.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.3.6 + parse5: 8.0.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.1 + undici: 7.25.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -7422,6 +8006,8 @@ snapshots: lowercase-keys@2.0.0: {} + lru-cache@11.3.6: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -7432,6 +8018,8 @@ snapshots: dependencies: react: 19.2.5 + lz-string@1.5.0: {} + macos-alias@0.2.12: dependencies: nan: 2.26.2 @@ -7563,6 +8151,8 @@ snapshots: dependencies: '@types/mdast': 4.0.4 + mdn-data@2.27.1: {} + media-typer@0.3.0: {} media-typer@1.1.0: {} @@ -7741,6 +8331,8 @@ snapshots: mimic-response@3.1.0: {} + min-indent@1.0.1: {} + minimatch@3.1.5: dependencies: brace-expansion: 1.1.14 @@ -7873,6 +8465,8 @@ snapshots: object-keys@1.1.1: optional: true + obug@2.1.1: {} + on-exit-leak-free@2.1.2: {} on-finished@2.4.1: @@ -7974,6 +8568,10 @@ snapshots: dependencies: error-ex: 1.3.4 + parse5@8.0.1: + dependencies: + entities: 8.0.0 + parseurl@1.3.3: {} path-exists@3.0.0: {} @@ -7996,6 +8594,8 @@ snapshots: dependencies: pify: 2.3.0 + pathe@2.0.3: {} + pe-library@1.0.1: {} pend@1.2.0: {} @@ -8055,6 +8655,12 @@ snapshots: prettier@3.8.3: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + proc-log@2.0.1: {} process-warning@4.0.1: {} @@ -8084,6 +8690,8 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 + punycode@2.3.1: {} + qs@6.14.2: dependencies: side-channel: 1.1.0 @@ -8125,6 +8733,8 @@ snapshots: react: 19.2.5 scheduler: 0.27.0 + react-is@17.0.2: {} + react-markdown@10.1.0(@types/react@19.2.14)(react@19.2.5): dependencies: '@types/hast': 3.0.4 @@ -8190,6 +8800,11 @@ snapshots: dependencies: resolve: 1.22.12 + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + remark-parse@11.0.0: dependencies: '@types/mdast': 4.0.4 @@ -8330,6 +8945,10 @@ snapshots: safer-buffer@2.1.2: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.27.0: {} schema-utils@4.3.3: @@ -8453,6 +9072,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -8515,8 +9136,12 @@ snapshots: dependencies: minipass: 3.3.6 + stackback@0.0.2: {} + statuses@2.0.2: {} + std-env@4.1.0: {} + stream-buffers@2.2.0: optional: true @@ -8557,6 +9182,10 @@ snapshots: strip-eof@1.0.0: {} + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + strip-outer@1.0.1: dependencies: escape-string-regexp: 1.0.5 @@ -8585,6 +9214,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + symbol-tree@3.2.4: {} + tailwind-merge@3.5.0: {} tailwindcss@4.2.4: {} @@ -8619,11 +9250,23 @@ snapshots: dependencies: real-require: 0.2.0 + tinybench@2.9.0: {} + + tinyexec@1.1.2: {} + tinyglobby@0.2.16: dependencies: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tinyrainbow@3.1.0: {} + + tldts-core@7.0.30: {} + + tldts@7.0.30: + dependencies: + tldts-core: 7.0.30 + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -8644,8 +9287,16 @@ snapshots: toidentifier@1.0.1: {} + tough-cookie@6.0.1: + dependencies: + tldts: 7.0.30 + tr46@0.0.3: {} + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + tree-kill@1.2.2: {} trim-lines@3.0.1: {} @@ -8697,6 +9348,8 @@ snapshots: undici-types@7.21.0: {} + undici@7.25.0: {} + unified@11.0.5: dependencies: '@types/unist': 3.0.3 @@ -8809,6 +9462,38 @@ snapshots: terser: 5.47.1 tsx: 4.21.0 + vitest@4.1.6(@types/node@25.7.0)(jsdom@29.1.1)(vite@6.4.2(@types/node@25.7.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.47.1)(tsx@4.21.0)): + dependencies: + '@vitest/expect': 4.1.6 + '@vitest/mocker': 4.1.6(vite@6.4.2(@types/node@25.7.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.47.1)(tsx@4.21.0)) + '@vitest/pretty-format': 4.1.6 + '@vitest/runner': 4.1.6 + '@vitest/snapshot': 4.1.6 + '@vitest/spy': 4.1.6 + '@vitest/utils': 4.1.6 + es-module-lexer: 2.1.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.1.2 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: 6.4.2(@types/node@25.7.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.47.1)(tsx@4.21.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.7.0 + jsdom: 29.1.1 + transitivePeerDependencies: + - msw + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + wait-on@9.0.5: dependencies: axios: 1.16.0 @@ -8837,6 +9522,8 @@ snapshots: webidl-conversions@3.0.1: {} + webidl-conversions@8.0.1: {} + webpack-sources@3.4.1: {} webpack@5.106.2: @@ -8879,6 +9566,16 @@ snapshots: - postcss - uglify-js + whatwg-mimetype@5.0.0: {} + + whatwg-url@16.0.1: + dependencies: + '@exodus/bytes': 1.15.0 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -8892,6 +9589,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 @@ -8914,8 +9616,12 @@ snapshots: ws@8.20.0: {} + xml-name-validator@5.0.0: {} + xmlbuilder@15.1.1: {} + xmlchars@2.2.0: {} + xtend@4.0.2: optional: true