diff --git a/doc/rfc/web-ui.md b/doc/rfc/web-ui.md
index 49b7dead9..93ccedd5e 100644
--- a/doc/rfc/web-ui.md
+++ b/doc/rfc/web-ui.md
@@ -68,7 +68,7 @@ Summary is the default request view, and `?view=history` makes History shareable
**Errors and values.** Gateway failures map from gRPC status: invalid argument and resource exhausted are user errors, not found is a missing resource, unavailable and deadline exceeded are transient, and everything else is internal. A transport with another error shape supplies its own classifier. Raw gateway messages are logged, never rendered, and views keep the last good data on transient failures. Status values stay strings with a display table and an unknown fallback. `int64` values arrive as bigint, number, string, or `Long` and become milliseconds after a safe-range check.
-**Theme.** The `--sq-*` custom properties on `.sq-app` are the theming contract, with light, dark, and system themes built in. React 18 and 19 are both supported.
+**Theme.** Views use BaseUI components with host-supplied `BaseProvider` and Styletron `Provider`. BaseUI owns layout, responsive grids, colors and typography; the stylesheet only enables wrapping long identifiers. There is no independent library theme or styling engine. Hosts choose light, dark, custom, or system-driven themes and own SSR extraction and client hydration. The reference Next.js hosts share a request-scoped Styletron registry that streams new styles and hydrates them in the browser. BaseUI and Styletron React are peers alongside React and React DOM; React 18 and 19 are both supported.
## Observability and identity
diff --git a/web/package.json b/web/package.json
index ccb40fa6b..a18d52aeb 100644
--- a/web/package.json
+++ b/web/package.json
@@ -16,6 +16,9 @@
"typecheck": "pnpm --recursive --if-present run typecheck"
},
"devDependencies": {
+ "baseui": "18.2.0",
+ "styletron-engine-atomic": "1.6.2",
+ "styletron-react": "6.1.1",
"@axe-core/playwright": "4.10.2",
"@bufbuild/buf": "1.73.0",
"@bufbuild/protobuf": "2.15.0",
@@ -26,11 +29,13 @@
"@playwright/test": "1.55.1",
"@submitqueue/api": "workspace:*",
"@types/node": "22.18.6",
+ "@types/react": "^19.1.0",
+ "@types/react-dom": "^19.1.0",
"next": "16.3.8",
"pino": "10.4.0",
"react": "19.3.0",
"react-dom": "19.3.0",
"typescript": "5.9.3",
- "vitest": "4.0.7"
+ "vitest": "4.1.11"
}
}
diff --git a/web/platform/BUILD.bazel b/web/platform/BUILD.bazel
index 4958fc6c3..b7d0439e8 100644
--- a/web/platform/BUILD.bazel
+++ b/web/platform/BUILD.bazel
@@ -1,3 +1,4 @@
+load("@aspect_rules_js//js:defs.bzl", "js_library")
load("@npm//:defs.bzl", "npm_link_all_packages")
load("@npm//web/platform:vitest/package_json.bzl", vitest = "bin")
load("@npm//web/service/submitqueue:eslint/package_json.bzl", eslint = "bin")
@@ -7,6 +8,13 @@ package(default_visibility = ["//web:__subpackages__"])
npm_link_all_packages(name = "node_modules")
+js_library(
+ name = "test_support",
+ testonly = True,
+ types = ["test/rtl.tsx"],
+ deps = [":node_modules"],
+)
+
web_library(
assets = ["styles.css"],
eslint = eslint,
@@ -17,12 +25,15 @@ web_library(
":node_modules/@types/react-dom",
":node_modules/jsdom",
":node_modules/react-dom",
+ ":node_modules/styletron-engine-atomic",
+ ":node_modules/styletron-react",
":node_modules/vitest",
],
vitest = vitest,
deps = [
":node_modules/@types/node",
":node_modules/@types/react",
+ ":node_modules/baseui",
":node_modules/react",
],
)
diff --git a/web/platform/auto-refresh.test.tsx b/web/platform/auto-refresh.test.tsx
index 39dc44d58..c46fe29e0 100644
--- a/web/platform/auto-refresh.test.tsx
+++ b/web/platform/auto-refresh.test.tsx
@@ -1,4 +1,4 @@
-import { act, fireEvent, render, screen } from "@testing-library/react";
+import { act, fireEvent, render, screen } from "./test/rtl.js";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { AutoRefresh } from "./auto-refresh.js";
diff --git a/web/platform/auto-refresh.tsx b/web/platform/auto-refresh.tsx
index 5af366b3d..3818fd28f 100644
--- a/web/platform/auto-refresh.tsx
+++ b/web/platform/auto-refresh.tsx
@@ -1,6 +1,9 @@
"use client";
import { useCallback, useEffect, useRef, useState } from "react";
+import { Block } from "baseui/block/index.js";
+import { Button, SIZE } from "baseui/button/index.js";
+import { LabelXSmall } from "baseui/typography/index.js";
export interface AutoRefreshProps {
terminal?: boolean;
@@ -96,14 +99,14 @@ export function AutoRefresh({
}, [automatic, cycle, intervalMs, jitterMs, maxBackoffMs, paused, random, runRefresh, terminal, transientFailureCount]);
return (
-
- void runRefresh()} type="button">
+
+ void runRefresh()} type="button">
{refreshing ? "Refreshing…" : "Refresh"}
-
-
+
+
{terminal ? "Automatic refresh stopped" : !automatic ? "Manual refresh" : paused ? "Automatic refresh paused" :
transientFailureCount > 0 || localFailures.current > 0 ? "Updates unavailable · retrying" : "Live"}
-
-
+
+
);
}
diff --git a/web/platform/index.ts b/web/platform/index.ts
index d70eb1dd8..4551d37b2 100644
--- a/web/platform/index.ts
+++ b/web/platform/index.ts
@@ -3,3 +3,4 @@
export * from "./navigation.js";
export * from "./auto-refresh.js";
export * from "./timestamp.js";
+export * from "./table.js";
diff --git a/web/platform/package.json b/web/platform/package.json
index e2c4e2a1a..84e43956e 100644
--- a/web/platform/package.json
+++ b/web/platform/package.json
@@ -39,6 +39,9 @@
"typecheck": "tsc --noEmit"
},
"devDependencies": {
+ "baseui": "18.2.0",
+ "styletron-engine-atomic": "1.6.2",
+ "styletron-react": "6.1.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@types/node": "22.18.6",
@@ -51,6 +54,9 @@
"vitest": "4.1.11"
},
"peerDependencies": {
+ "baseui": ">=16 <19",
+ "react-dom": ">=18 <20",
+ "styletron-react": ">=6",
"react": ">=18 <20"
}
}
diff --git a/web/platform/styles.css b/web/platform/styles.css
index f335aff3a..067c40582 100644
--- a/web/platform/styles.css
+++ b/web/platform/styles.css
@@ -1,120 +1 @@
-/* Common native UI styles, scoped to .sq-app; hosts may override --sq-* properties. */
-.sq-app {
- color-scheme: light;
- --sq-surface: #fff;
- --sq-surface-muted: #f5f6f8;
- --sq-text: #202327;
- --sq-muted: #626a74;
- --sq-border: #e3e6e9;
- --sq-accent: #175fc5;
- --sq-accent-soft: #edf3ff;
- --sq-success: #187247;
- --sq-success-soft: #edf8f1;
- --sq-warning: #8b590f;
- --sq-warning-soft: #fff5e7;
- --sq-danger: #b33535;
- --sq-danger-soft: #fff0ef;
- --sq-font: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
- --sq-font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
- font-family: var(--sq-font);
-}
-.sq-app[data-theme="dark"] {
- color-scheme: dark;
- --sq-surface: #16181b;
- --sq-surface-muted: #202328;
- --sq-text: #e8eaed;
- --sq-muted: #a0a7b0;
- --sq-border: #33373d;
- --sq-accent: #6ea8ff;
- --sq-accent-soft: #1c2a40;
- --sq-success: #5cc28a;
- --sq-success-soft: #18301f;
- --sq-warning: #e0a84a;
- --sq-warning-soft: #36290f;
- --sq-danger: #ff7b72;
- --sq-danger-soft: #3a1f1e;
-}
-@media (prefers-color-scheme: dark) {
- .sq-app[data-theme="system"] {
- color-scheme: dark;
- --sq-surface: #16181b;
- --sq-surface-muted: #202328;
- --sq-text: #e8eaed;
- --sq-muted: #a0a7b0;
- --sq-border: #33373d;
- --sq-accent: #6ea8ff;
- --sq-accent-soft: #1c2a40;
- --sq-success: #5cc28a;
- --sq-success-soft: #18301f;
- --sq-warning: #e0a84a;
- --sq-warning-soft: #36290f;
- --sq-danger: #ff7b72;
- --sq-danger-soft: #3a1f1e;
- }
-}
-.sq-app, .sq-app * { box-sizing: border-box; }
-.sq-app { background: var(--sq-surface); color: var(--sq-text); font-size: 14px; line-height: 1.5; }
-.sq-app a { color: var(--sq-accent); text-decoration: none; overflow-wrap: anywhere; }
-.sq-app a:hover { text-decoration: underline; }
-.sq-app a:focus-visible, .sq-app button:focus-visible, .sq-app input:focus-visible, .sq-app select:focus-visible, .sq-app summary:focus-visible {
- outline: 3px solid var(--sq-accent); outline-offset: 3px;
-}
-.sq-app h1 { font-size: 26px; line-height: 1.25; margin: 0 0 10px; letter-spacing: -.5px; }
-.sq-app h2 { font-size: 16px; margin: 0 0 12px; }
-.sq-app p { margin: 8px 0; }
-.sq-app button, .sq-app input, .sq-app select {
- font: inherit; border: 1px solid var(--sq-border); border-radius: 6px;
- color: var(--sq-text); background: var(--sq-surface); padding: 8px 12px;
-}
-.sq-app button, .sq-app summary { cursor: pointer; }
-.sq-app button:disabled { cursor: default; opacity: .65; }
-.sq-app button:hover:not(:disabled) { background: var(--sq-surface-muted); }
-.sq-app input { min-width: 0; }
-.sq-app.site-frame { min-height: 100vh; display: grid; grid-template-rows: auto 1fr auto; }
-.sq-app .site-header, .sq-app .shell, .sq-app .site-footer { width: min(1200px, calc(100% - 48px)); margin-inline: auto; }
-.sq-app .site-header { min-height: 80px; display: flex; align-items: center; justify-content: space-between; gap: 20px; border-bottom: 1px solid var(--sq-border); }
-.sq-app .brand { display: flex; align-items: center; gap: 9px; color: var(--sq-text); font-weight: 600; font-size: 18px; }
-.sq-app .brand-mark { background: var(--sq-text); color: var(--sq-surface); border-radius: 6px; padding: 5px 7px; font-size: 12px; }
-.sq-app .environment-pill, .sq-app .site-footer, .sq-app .sq-secondary { color: var(--sq-muted); font-size: 12px; }
-.sq-app .site-footer { padding: 20px 0; border-top: 1px solid var(--sq-border); }
-.sq-app .shell { padding-block: 28px 48px; }
-.sq-app .centered-state { min-height: 100vh; display: grid; place-items: center; }
-.sq-app .page-heading { display: flex; justify-content: space-between; gap: 24px; align-items: flex-start; flex-wrap: wrap; margin-bottom: 24px; }
-.sq-app .page-heading p { color: var(--sq-muted); font-size: 12px; }
-.sq-app .eyebrow { font-size: 12px; margin: 0 0 10px; color: var(--sq-muted); }
-.sq-app .page-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
-.sq-app .sq-refresh { display: flex; align-items: center; gap: 10px; color: var(--sq-muted); font-size: 12px; }
-.sq-app .sq-error { padding: 16px; border-radius: 6px; background: var(--sq-danger-soft); }
-.sq-app .sq-error p { overflow-wrap: anywhere; }
-.sq-app .button-link { display: inline-block; margin-top: 16px; }
-.sq-app .state-card { max-width: 700px; }
-@media (max-width: 680px) {
-.sq-app .site-header, .sq-app .shell, .sq-app .site-footer { width: calc(100% - 32px); }
-.sq-app .site-header { gap: 12px; flex-wrap: wrap; padding-block: 14px; }
-.sq-app button, .sq-app select, .sq-app input { min-height: 44px; }
-}
-
-
-.sq-app .sq-table-scroll { overflow-x: auto; }
-.sq-app table { width: 100%; border-collapse: collapse; text-align: left; }
-.sq-app th { font-weight: 500; color: var(--sq-muted); font-size: 12px; padding: 10px 12px; border-bottom: 1px solid var(--sq-border); }
-.sq-app td { padding: 18px 12px; border-bottom: 1px solid var(--sq-border); vertical-align: top; }
-.sq-app th:first-child, .sq-app td:first-child { padding-left: 0; }
-.sq-app th:last-child, .sq-app td:last-child { padding-right: 0; }
-.sq-app td time { font-size: 12px; color: var(--sq-muted); }
-.sq-app .sq-table-footer { display: flex; justify-content: space-between; align-items: center; gap: 16px; margin-top: 18px; font-size: 12px; color: var(--sq-muted); }
-.sq-app .sq-status, .sq-app .sq-event { display: inline-block; padding: 2px 7px; border-radius: 4px; font-size: 12px; color: var(--sq-accent); background: var(--sq-accent-soft); white-space: nowrap; }
-.sq-app .sq-status[data-tone="neutral"] { color: var(--sq-muted); background: var(--sq-surface-muted); }
-.sq-app .sq-status[data-tone="success"] { color: var(--sq-success); background: var(--sq-success-soft); }
-.sq-app .sq-status[data-tone="danger"] { color: var(--sq-danger); background: var(--sq-danger-soft); }
-.sq-app .sq-status[data-tone="warning"] { color: var(--sq-warning); background: var(--sq-warning-soft); }
-.sq-app .sq-empty { padding: 35px 0; color: var(--sq-muted); }
-.sq-app .sq-breadcrumb { display: flex; gap: 10px; flex-wrap: wrap; color: var(--sq-muted); font-size: 12px; margin-bottom: 24px; }
-.sq-app .sq-detail-columns { display: grid; grid-template-columns: 1fr 1.15fr; gap: 38px; }
-.sq-app .sq-facts { margin: 0; }
-.sq-app .sq-facts > div { padding: 11px 0; border-bottom: 1px solid var(--sq-border); }
-.sq-app dt { color: var(--sq-muted); font-size: 12px; margin-bottom: 5px; }
-.sq-app dd { margin: 0; overflow-wrap: anywhere; }
-@media (max-width: 680px) {
-.sq-app .sq-detail-columns { grid-template-columns: 1fr; gap: 20px; }
-}
+.sq-app :is(a, code, dd, h1, p, [role="alert"]) { overflow-wrap: anywhere; }
diff --git a/web/platform/table.tsx b/web/platform/table.tsx
new file mode 100644
index 000000000..41e3b1efd
--- /dev/null
+++ b/web/platform/table.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import {
+ StyledRoot,
+ StyledTable,
+ StyledTableBody,
+ StyledTableHead,
+ StyledTableHeadCell,
+ StyledTableHeadRow,
+} from "baseui/table-semantic/index.js";
+import type { ReactNode } from "react";
+
+export function Table({ label, headers, children }: {
+ label: string;
+ headers: string[];
+ children: ReactNode;
+}) {
+ return
+
+
+ {headers.map(header => {header} )}
+
+ {children}
+
+ ;
+}
diff --git a/web/platform/test/rtl.tsx b/web/platform/test/rtl.tsx
new file mode 100644
index 000000000..6ec469aec
--- /dev/null
+++ b/web/platform/test/rtl.tsx
@@ -0,0 +1,16 @@
+import { render as renderRTL, type RenderOptions, type RenderResult } from "@testing-library/react";
+import { BaseProvider, LightTheme } from "baseui";
+import { useId, useState, type ReactElement, type ReactNode } from "react";
+import { Client } from "styletron-engine-atomic";
+import { Provider } from "styletron-react";
+
+export * from "@testing-library/react";
+
+export function render(ui: ReactElement, options?: Omit): RenderResult {
+ function Wrapper({ children }: { children: ReactNode }) {
+ const prefix = useId().replaceAll(":", "");
+ const [engine] = useState(() => new Client({ prefix: `sq-test-${prefix}-` }));
+ return {children} ;
+ }
+ return renderRTL(ui, { wrapper: Wrapper, ...options });
+}
diff --git a/web/platform/vitest.config.ts b/web/platform/vitest.config.ts
index 21c8ec048..177f92ec7 100644
--- a/web/platform/vitest.config.ts
+++ b/web/platform/vitest.config.ts
@@ -5,6 +5,7 @@ export default defineConfig({
jsx: "automatic",
},
test: {
+ maxWorkers: 2,
environment: "jsdom",
globals: true,
setupFiles: ["./test-setup.ts"],
diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml
index cb82776e4..f80f0a84d 100644
--- a/web/pnpm-lock.yaml
+++ b/web/pnpm-lock.yaml
@@ -38,6 +38,15 @@ importers:
'@types/node':
specifier: 22.18.6
version: 22.18.6
+ '@types/react':
+ specifier: ^19.1.0
+ version: 19.3.0
+ '@types/react-dom':
+ specifier: ^19.1.0
+ version: 19.3.0(@types/react@19.3.0)
+ baseui:
+ specifier: 18.2.0
+ version: 18.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(styletron-react@6.1.1(react@19.3.0))
next:
specifier: 16.3.8
version: 16.3.8(@babel/core@7.29.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.55.1)(@types/node@22.18.6)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
@@ -50,12 +59,18 @@ importers:
react-dom:
specifier: 19.3.0
version: 19.3.0(react@19.3.0)
+ styletron-engine-atomic:
+ specifier: 1.6.2
+ version: 1.6.2
+ styletron-react:
+ specifier: 6.1.1
+ version: 6.1.1(react@19.3.0)
typescript:
specifier: 5.9.3
version: 5.9.3
vitest:
- specifier: 4.0.7
- version: 4.0.7(@types/node@22.18.6)(jsdom@27.4.0)
+ specifier: 4.1.11
+ version: 4.1.11(@opentelemetry/api@1.9.0)(@types/node@22.18.6)(jsdom@27.4.0)(vite@7.3.6(@types/node@22.18.6))
api:
dependencies:
@@ -80,6 +95,9 @@ importers:
'@types/react-dom':
specifier: ^19.1.0
version: 19.3.0(@types/react@19.3.0)
+ baseui:
+ specifier: 18.2.0
+ version: 18.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(styletron-react@6.1.1(react@19.3.0))
jsdom:
specifier: ^26.1.0
version: 26.1.0
@@ -89,12 +107,18 @@ importers:
react-dom:
specifier: ^19.1.0
version: 19.3.0(react@19.3.0)
+ styletron-engine-atomic:
+ specifier: 1.6.2
+ version: 1.6.2
+ styletron-react:
+ specifier: 6.1.1
+ version: 6.1.1(react@19.3.0)
typescript:
specifier: ^5.8.3
version: 5.9.3
vitest:
- specifier: 4.0.7
- version: 4.0.7(@types/node@22.18.6)(jsdom@26.1.0)
+ specifier: 4.1.11
+ version: 4.1.11(@opentelemetry/api@1.9.0)(@types/node@22.18.6)(jsdom@26.1.0)(vite@7.3.6(@types/node@22.18.6))
service/shared:
dependencies:
@@ -113,6 +137,9 @@ importers:
'@submitqueue/web-platform':
specifier: 0.0.0
version: link:../../platform
+ baseui:
+ specifier: 18.2.0
+ version: 18.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(styletron-react@6.1.1(react@19.3.0))
next:
specifier: '>=16.3.0 <17'
version: 16.3.8(@babel/core@7.29.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.55.1)(@types/node@22.18.6)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
@@ -128,6 +155,12 @@ importers:
server-only:
specifier: ^0.0.1
version: 0.0.1
+ styletron-engine-atomic:
+ specifier: 1.6.2
+ version: 1.6.2
+ styletron-react:
+ specifier: 6.1.1
+ version: 6.1.1(react@19.3.0)
devDependencies:
'@types/node':
specifier: 22.18.6
@@ -148,8 +181,8 @@ importers:
specifier: 5.9.3
version: 5.9.3
vitest:
- specifier: 4.0.7
- version: 4.0.7(@types/node@22.18.6)(jsdom@27.4.0)
+ specifier: 4.1.11
+ version: 4.1.11(@opentelemetry/api@1.9.0)(@types/node@22.18.6)(jsdom@27.4.0)(vite@7.3.6(@types/node@22.18.6))
service/stovepipe:
dependencies:
@@ -209,8 +242,8 @@ importers:
specifier: 5.9.3
version: 5.9.3
vitest:
- specifier: 4.0.7
- version: 4.0.7(@types/node@22.18.6)(jsdom@27.4.0)
+ specifier: 4.1.11
+ version: 4.1.11(@opentelemetry/api@1.9.0)(@types/node@22.18.6)(jsdom@27.4.0)(vite@7.3.6(@types/node@22.18.6))
service/submitqueue:
dependencies:
@@ -276,8 +309,8 @@ importers:
specifier: 5.9.3
version: 5.9.3
vitest:
- specifier: 4.0.7
- version: 4.0.7(@types/node@22.18.6)(jsdom@27.4.0)
+ specifier: 4.1.11
+ version: 4.1.11(@opentelemetry/api@1.9.0)(@types/node@22.18.6)(jsdom@27.4.0)(vite@7.3.6(@types/node@22.18.6))
stovepipe:
dependencies:
@@ -300,6 +333,9 @@ importers:
'@types/react-dom':
specifier: ^19.1.0
version: 19.3.0(@types/react@19.3.0)
+ baseui:
+ specifier: 18.2.0
+ version: 18.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(styletron-react@6.1.1(react@19.3.0))
jsdom:
specifier: ^26.1.0
version: 26.1.0
@@ -309,12 +345,18 @@ importers:
react-dom:
specifier: ^19.1.0
version: 19.3.0(react@19.3.0)
+ styletron-engine-atomic:
+ specifier: 1.6.2
+ version: 1.6.2
+ styletron-react:
+ specifier: 6.1.1
+ version: 6.1.1(react@19.3.0)
typescript:
specifier: ^5.8.3
version: 5.9.3
vitest:
- specifier: 4.0.7
- version: 4.0.7(@types/node@22.18.6)(jsdom@26.1.0)
+ specifier: 4.1.11
+ version: 4.1.11(@opentelemetry/api@1.9.0)(@types/node@22.18.6)(jsdom@26.1.0)(vite@7.3.6(@types/node@22.18.6))
submitqueue:
dependencies:
@@ -340,6 +382,9 @@ importers:
'@types/react-dom':
specifier: ^19.1.0
version: 19.3.0(@types/react@19.3.0)
+ baseui:
+ specifier: 18.2.0
+ version: 18.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(styletron-react@6.1.1(react@19.3.0))
jsdom:
specifier: ^26.1.0
version: 26.1.0
@@ -349,12 +394,18 @@ importers:
react-dom:
specifier: ^19.1.0
version: 19.3.0(react@19.3.0)
+ styletron-engine-atomic:
+ specifier: 1.6.2
+ version: 1.6.2
+ styletron-react:
+ specifier: 6.1.1
+ version: 6.1.1(react@19.3.0)
typescript:
specifier: ^5.8.3
version: 5.9.3
vitest:
- specifier: 4.0.7
- version: 4.0.7(@types/node@22.18.6)(jsdom@26.1.0)
+ specifier: 4.1.11
+ version: 4.1.11(@opentelemetry/api@1.9.0)(@types/node@22.18.6)(jsdom@26.1.0)(vite@7.3.6(@types/node@22.18.6))
test/e2e/stovepipe:
dependencies:
@@ -394,6 +445,9 @@ importers:
test/package/react18:
dependencies:
+ baseui:
+ specifier: 18.2.0
+ version: 18.2.0(@types/react@19.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styletron-react@6.1.1(react@18.3.1))
jsdom:
specifier: ^26.1.0
version: 26.1.0
@@ -403,6 +457,12 @@ importers:
react-dom:
specifier: 18.3.1
version: 18.3.1(react@18.3.1)
+ styletron-engine-atomic:
+ specifier: 1.6.2
+ version: 1.6.2
+ styletron-react:
+ specifier: 6.1.1
+ version: 6.1.1(react@18.3.1)
packages:
@@ -488,10 +548,6 @@ packages:
resolution: {integrity: sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==}
engines: {node: '>=6.9.0'}
- '@babel/runtime@7.29.7':
- resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==}
- engines: {node: '>=6.9.0'}
-
'@babel/template@7.29.7':
resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
engines: {node: '>=6.9.0'}
@@ -648,6 +704,25 @@ packages:
resolution: {integrity: sha512-OoKoR0f76dCY666JlcbhmVTs2drYj1GUXZTYTcbUgJjh9Nv41aFfZ21bPQTERm5+L5cBDo466NltB2lplS5GBw==}
engines: {node: '>=20.19.0'}
+ '@date-io/core@2.17.0':
+ resolution: {integrity: sha512-+EQE8xZhRM/hsY0CDTVyayMDDY5ihc4MqXCrPxooKw19yAzUIC6uUqsZeaOFNL9YKTNxYKrJP5DFgE8o5xRCOw==}
+
+ '@date-io/date-fns@2.17.0':
+ resolution: {integrity: sha512-L0hWZ/mTpy3Gx/xXJ5tq5CzHo0L7ry6KEO9/w/JWiFWFLZgiNVo3ex92gOl3zmzjHqY/3Ev+5sehAr8UnGLEng==}
+ peerDependencies:
+ date-fns: ^2.0.0
+ peerDependenciesMeta:
+ date-fns:
+ optional: true
+
+ '@date-io/moment@2.17.0':
+ resolution: {integrity: sha512-e4nb4CDZU4k0WRVhz1Wvl7d+hFsedObSauDHKtZwU9kt7gdYEAzKgnrSCTHsEaXrDumdrkCYTeZ0Tmyk7uV4tw==}
+ peerDependencies:
+ moment: ^2.24.0
+ peerDependenciesMeta:
+ moment:
+ optional: true
+
'@emnapi/core@1.10.0':
resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
@@ -924,105 +999,89 @@ packages:
resolution: {integrity: sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-arm@1.3.4':
resolution: {integrity: sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-ppc64@1.3.4':
resolution: {integrity: sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-riscv64@1.3.4':
resolution: {integrity: sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.3.4':
resolution: {integrity: sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-x64@1.3.4':
resolution: {integrity: sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.3.4':
resolution: {integrity: sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.3.4':
resolution: {integrity: sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@img/sharp-linux-arm64@0.35.5':
resolution: {integrity: sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==}
engines: {node: '>=20.9.0'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-arm@0.35.5':
resolution: {integrity: sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==}
engines: {node: '>=20.9.0'}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-ppc64@0.35.5':
resolution: {integrity: sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==}
engines: {node: '>=20.9.0'}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-riscv64@0.35.5':
resolution: {integrity: sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==}
engines: {node: '>=20.9.0'}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-s390x@0.35.5':
resolution: {integrity: sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==}
engines: {node: '>=20.9.0'}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-x64@0.35.5':
resolution: {integrity: sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==}
engines: {node: '>=20.9.0'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.35.5':
resolution: {integrity: sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==}
engines: {node: '>=20.9.0'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@img/sharp-linuxmusl-x64@0.35.5':
resolution: {integrity: sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==}
engines: {node: '>=20.9.0'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@img/sharp-wasm32@0.35.5':
resolution: {integrity: sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==}
@@ -1067,12 +1126,46 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ '@mapbox/geojson-rewind@0.5.2':
+ resolution: {integrity: sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==}
+ hasBin: true
+
+ '@mapbox/geojson-types@1.0.2':
+ resolution: {integrity: sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==}
+
+ '@mapbox/jsonlint-lines-primitives@2.0.3':
+ resolution: {integrity: sha512-0SElaV0uMxEnxzBhhX9WTuPyUeMsAN/SS0i16tjuba4/mio63MG9khjC1a0JAiPGXAwvwm4UfHJURCN7nyudQg==}
+ engines: {node: '>= 22'}
+
+ '@mapbox/mapbox-gl-supported@1.5.0':
+ resolution: {integrity: sha512-/PT1P6DNf7vjEEiPkVIRJkvibbqWtqnyGaBz3nfRdcxclNSnSdaLU5tfAgcD7I8Yt5i+L19s406YLl1koLnLbg==}
+ peerDependencies:
+ mapbox-gl: '>=0.32.1 <2.0.0'
+
+ '@mapbox/point-geometry@0.1.0':
+ resolution: {integrity: sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==}
+
+ '@mapbox/tiny-sdf@1.2.5':
+ resolution: {integrity: sha512-cD8A/zJlm6fdJOk6DqPUV8mcpyJkRz2x2R+/fYcWDYG3oWbG7/L7Yl/WqQ1VZCjnL9OTIMAn6c+BC5Eru4sQEw==}
+
+ '@mapbox/unitbezier@0.0.0':
+ resolution: {integrity: sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==}
+
+ '@mapbox/vector-tile@1.3.1':
+ resolution: {integrity: sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==}
+
+ '@mapbox/whoots-js@3.1.0':
+ resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==}
+ engines: {node: '>=6.0.0'}
+
+ '@math.gl/web-mercator@3.6.3':
+ resolution: {integrity: sha512-UVrkSOs02YLehKaehrxhAejYMurehIHPfFQvPFZmdJHglHOU4V2cCUApTVEwOksvCp161ypEqVp+9H6mGhTTcw==}
+
'@napi-rs/lzma-linux-x64-gnu@1.5.1':
resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==}
engines: {node: ^22.20 || ^24.12 || >=25}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@napi-rs/wasm-runtime@1.2.4':
resolution: {integrity: sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g==}
@@ -1104,28 +1197,24 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@next/swc-linux-arm64-musl@16.3.8':
resolution: {integrity: sha512-dSjKSyWpzxoO1d3DIZZcP4XJcNaKeLmxQMFOiYl5vuBRMmweIqnAhty8tAmRsvTss779cK1FtYnDMj40e4TQlg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@next/swc-linux-x64-gnu@16.3.8':
resolution: {integrity: sha512-lbqOuz3RPRcv+o9msNsJw5x4+Y1ZwPTs6vmL6DCf7i0fZfvng/F59wyeDwqHIvV0mK//RBy/jJkZ+nCKsSMXjQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@next/swc-linux-x64-musl@16.3.8':
resolution: {integrity: sha512-+316WswI8ScVgZeUd+1KGaXkHhaYQzCjvH/05TZSpJ8zBizb1a4G7DtO7F12jcBIqMOtsz9ji1t48fmKtzqsGA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@next/swc-win32-arm64-msvc@16.3.8':
resolution: {integrity: sha512-ji0gd4kMYUxO+1fJBIbiBVRCjzG/lloiyCccnlebvb1ZJ5qXCPZqYg4Jl1DrrixnWNMKylzgpmMWx0yNDYXlzw==}
@@ -1229,79 +1318,66 @@ packages:
resolution: {integrity: sha512-CFmhpvAwzSaWMlN3VN7UtmoTihlZNzoP0juQib5TQRnYUyDV8dXeWOp29sobWAT6gXl/hQgAClLlEiYozQG3OQ==}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.63.5':
resolution: {integrity: sha512-Uc9H8eXCOayV6JLTH5bXKMId6qbhNHa818/BgYjm4jrlq3vZquC9cqyvHBw17xy5Mnj5f+I3gFK5JcEf3hSqrw==}
cpu: [arm]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.63.5':
resolution: {integrity: sha512-VcPr/szv/1BFw112Kt//fxulXt/JPqzzidU84iW68L2DdjnOO8QFUv2zTSYBEPHD6movBD4z+bbr5y60GYM7Jw==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.63.5':
resolution: {integrity: sha512-BnxtJ5/91BrIHYIkGrmjz/lbMhqEHt1dPFqIxIFR+jPn0xVc/oUSCtIT089zfp5ufwGDlYz2UC+Fe1SRBpYFbQ==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-loong64-gnu@4.63.5':
resolution: {integrity: sha512-LrYcHZwF+fAMNKHYTOQ5osWM4AZF7YF6D+XtsjDyEvljtt11twc+zHVXBLNEjxVSUnKYsOhvVz4Z213eW02COQ==}
cpu: [loong64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-loong64-musl@4.63.5':
resolution: {integrity: sha512-nj7QKQePAAUpCpJHtg0pR0W/b92A9NO17JS3BAQmHDn/yhmkir2p8llrKY9TOhleKIaSzy1JhxS3T9FVld6coA==}
cpu: [loong64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-ppc64-gnu@4.63.5':
resolution: {integrity: sha512-5ylkX6dWMeBKge9nTU+Rxfb+ZfaCIJ9lRqIFaK0eAMcWp7OJbYnLveLgXmm0VrvuLKb8qIK+mHyH0qu88RM+iA==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-ppc64-musl@4.63.5':
resolution: {integrity: sha512-oHK4ZHYFDKjZviK34I+NwgfbGxgI7ztrNxj2hPTSSNFgeq1a/lEd7dHV2fdGAuTH4Iym3RHJg+vAbWaWG4B7Zg==}
cpu: [ppc64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-riscv64-gnu@4.63.5':
resolution: {integrity: sha512-UcetmHZ6XOXuUByiKZyQmb55ZPr0LABr3Ec/HB9wKZn6CEAFWZkE+hsJErJ9hbPBC7nI0dKuELx7CoV6IM7TMg==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-riscv64-musl@4.63.5':
resolution: {integrity: sha512-C5CmDPQBtvjVo8cgQsBs+w6WB0JLkiixhgi6hVLV11hERWdn/p0XcPU2OUcZzac9BPOFq7SbaHFa8r3SWEysCQ==}
cpu: [riscv64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-s390x-gnu@4.63.5':
resolution: {integrity: sha512-lHVQHJFKsuuxLMi3MQO9XVL8Tje3JR82CzB+QDKC5NWBcsIWuwsn9uIM5e3lBhI+fF1/s63qnyYqsg65+8rV/w==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.63.5':
resolution: {integrity: sha512-3W9bTFcQNJn71cSJVM9RKIiZOy8DO/XLDii8Uv/Pm6WKqDRj7JV3ZfuXIEfyuy5LXpIzAbB/1M4Ukp9GKNa7nA==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.63.5':
resolution: {integrity: sha512-VDC7rRJlee/scpki96GZ27Omf6yU87s1YXwVTpjE5841faVlDYYT565rgfmoR1U0sqL7z5ivQSDjcsF6VRXyBA==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@rollup/rollup-openbsd-x64@4.63.5':
resolution: {integrity: sha512-z86Ok2p4pTdv5xqCKZsTooO7yBEiaJR/HzU3Wx8RmWsPoLppnMKROhJusQob8B3IE1ghC343kUW9rC2r+Wf3ig==}
@@ -1333,6 +1409,9 @@ packages:
cpu: [x64]
os: [win32]
+ '@rtsao/csstype@2.6.5-forked.0':
+ resolution: {integrity: sha512-0HwnY8uPWcCloTgdbbaJG3MbDUfNf6yKWZfCKxFv9yj2Sbp4mSKaIjC7Cr/5L4hMxvrrk85CU3wlAg7EtBBJ1Q==}
+
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
@@ -1383,6 +1462,9 @@ packages:
'@types/estree@1.0.9':
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+ '@types/hammerjs@2.0.46':
+ resolution: {integrity: sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==}
+
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
@@ -1503,61 +1585,51 @@ packages:
resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-arm64-musl@1.12.2':
resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-linux-loong64-gnu@1.12.2':
resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==}
cpu: [loong64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-loong64-musl@1.12.2':
resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==}
cpu: [loong64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-linux-ppc64-gnu@1.12.2':
resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-gnu@1.12.2':
resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-musl@1.12.2':
resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==}
cpu: [riscv64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-linux-s390x-gnu@1.12.2':
resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-x64-gnu@1.12.2':
resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@unrs/resolver-binding-linux-x64-musl@1.12.2':
resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@unrs/resolver-binding-openharmony-arm64@1.12.2':
resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==}
@@ -1584,34 +1656,34 @@ packages:
cpu: [x64]
os: [win32]
- '@vitest/expect@4.0.7':
- resolution: {integrity: sha512-jGRG6HghnJDjljdjYIoVzX17S6uCVCBRFnsgdLGJ6CaxfPh8kzUKe/2n533y4O/aeZ/sIr7q7GbuEbeGDsWv4Q==}
+ '@vitest/expect@4.1.11':
+ resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==}
- '@vitest/mocker@4.0.7':
- resolution: {integrity: sha512-OsDwLS7WnpuNslOV6bJkXVYVV/6RSc4eeVxV7h9wxQPNxnjRvTTrIikfwCbMyl8XJmW6oOccBj2Q07YwZtQcCw==}
+ '@vitest/mocker@4.1.11':
+ resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==}
peerDependencies:
msw: ^2.4.9
- vite: ^6.0.0 || ^7.0.0-0
+ vite: ^6.0.0 || ^7.0.0 || ^8.0.0
peerDependenciesMeta:
msw:
optional: true
vite:
optional: true
- '@vitest/pretty-format@4.0.7':
- resolution: {integrity: sha512-YY//yxqTmk29+/pK+Wi1UB4DUH3lSVgIm+M10rAJ74pOSMgT7rydMSc+vFuq9LjZLhFvVEXir8EcqMke3SVM6Q==}
+ '@vitest/pretty-format@4.1.11':
+ resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==}
- '@vitest/runner@4.0.7':
- resolution: {integrity: sha512-orU1lsu4PxLEcDWfjVCNGIedOSF/YtZ+XMrd1PZb90E68khWCNzD8y1dtxtgd0hyBIQk8XggteKN/38VQLvzuw==}
+ '@vitest/runner@4.1.11':
+ resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==}
- '@vitest/snapshot@4.0.7':
- resolution: {integrity: sha512-xJL+Nkw0OjaUXXQf13B8iKK5pI9QVtN9uOtzNHYuG/o/B7fIEg0DQ+xOe0/RcqwDEI15rud1k7y5xznBKGUXAA==}
+ '@vitest/snapshot@4.1.11':
+ resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==}
- '@vitest/spy@4.0.7':
- resolution: {integrity: sha512-FW4X8hzIEn4z+HublB4hBF/FhCVaXfIHm8sUfvlznrcy1MQG7VooBgZPMtVCGZtHi0yl3KESaXTqsKh16d8cFg==}
+ '@vitest/spy@4.1.11':
+ resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==}
- '@vitest/utils@4.0.7':
- resolution: {integrity: sha512-HNrg9CM/Z4ZWB6RuExhuC6FPmLipiShKVMnT9JlQvfhwR47JatWLChA6mtZqVHqypE6p/z6ofcjbyWpM7YLxPQ==}
+ '@vitest/utils@4.1.11':
+ resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==}
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
@@ -1699,6 +1771,10 @@ packages:
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
engines: {node: '>=8.0.0'}
+ attr-accept@1.1.3:
+ resolution: {integrity: sha512-iT40nudw8zmCweivz6j58g+RT33I4KbaIvRUhjNmDwO2WmsQUxFEZZYZ5w3vXe5x5MX9D7mfvA/XaLOZYFR9EQ==}
+ engines: {node: '>=4'}
+
available-typed-arrays@1.0.7:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
@@ -1707,8 +1783,8 @@ packages:
resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==}
engines: {node: '>=4'}
- axe-core@4.13.0:
- resolution: {integrity: sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==}
+ axe-core@4.14.0:
+ resolution: {integrity: sha512-9WTZxEjsZ7b13TH8JPmbV2z8CHbl80/2hm3XPEG4JgNdQLK81IBRXmSxHfMAOkSqQeRxT/0dwNDz2GOm3zzpcQ==}
engines: {node: '>=4'}
axobject-query@4.1.0:
@@ -1727,6 +1803,14 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
+ baseui@18.2.0:
+ resolution: {integrity: sha512-jfIiSbKsosPIo+qIkpUbtiWNRae9fYhoGbuL7gEYLI1M5Kz2orMFX05kkuVhD2tSVMHGOEMbCp0MZo6FL9GoxQ==}
+ engines: {node: '>=24.0.0'}
+ peerDependencies:
+ react: '>=18'
+ react-dom: '>=18'
+ styletron-react: '>=6'
+
bidi-js@1.1.0:
resolution: {integrity: sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==}
@@ -1765,6 +1849,9 @@ packages:
caniuse-lite@1.0.30001816:
resolution: {integrity: sha512-+8Yx7BXCoqk6IF8yTicjfUR6D/ldJzdlsodlEOiOSPmhK844WIgk67/zIQaGAOxNkZyyvBlrRFnLvqKIoqbAFw==}
+ card-validator@6.2.0:
+ resolution: {integrity: sha512-1vYv45JaE9NmixZr4dl6ykzbFKv7imI9L7MQDs235b/a7EGbG8rrEsipeHtVvscLSUbl3RX6UP5gyOe0Y2FlHA==}
+
chai@6.2.2:
resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
engines: {node: '>=18'}
@@ -1776,6 +1863,10 @@ packages:
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+ clsx@1.2.1:
+ resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==}
+ engines: {node: '>=6'}
+
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@@ -1783,16 +1874,30 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ commander@7.2.0:
+ resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+ engines: {node: '>= 10'}
+
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ core-js@2.6.12:
+ resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==}
+ deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
+
+ credit-card-type@8.3.0:
+ resolution: {integrity: sha512-czfZUpQ7W9CDxZL4yFLb1kFtM/q2lTOY975hL2aO+DC8+GRNDVSXVCHXhVFZPxiUKmQCZbFP8vIhxx5TBQaThw==}
+
cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
+ css-in-js-utils@2.0.1:
+ resolution: {integrity: sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==}
+
css-tree@3.2.1:
resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==}
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
@@ -1800,6 +1905,9 @@ packages:
css.escape@1.5.1:
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
+ csscolorparser@1.0.3:
+ resolution: {integrity: sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==}
+
cssstyle@4.6.0:
resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==}
engines: {node: '>=18'}
@@ -1808,9 +1916,139 @@ packages:
resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==}
engines: {node: '>=20'}
+ csstype@2.6.11:
+ resolution: {integrity: sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw==}
+
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ d3-array@3.2.4:
+ resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
+ engines: {node: '>=12'}
+
+ d3-axis@3.0.0:
+ resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==}
+ engines: {node: '>=12'}
+
+ d3-brush@3.0.0:
+ resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==}
+ engines: {node: '>=12'}
+
+ d3-chord@3.0.1:
+ resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==}
+ engines: {node: '>=12'}
+
+ d3-color@3.1.0:
+ resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
+ engines: {node: '>=12'}
+
+ d3-contour@4.0.2:
+ resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==}
+ engines: {node: '>=12'}
+
+ d3-delaunay@6.0.4:
+ resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==}
+ engines: {node: '>=12'}
+
+ d3-dispatch@3.0.1:
+ resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
+ engines: {node: '>=12'}
+
+ d3-drag@3.0.0:
+ resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
+ engines: {node: '>=12'}
+
+ d3-dsv@3.0.1:
+ resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ d3-ease@3.0.1:
+ resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
+ engines: {node: '>=12'}
+
+ d3-fetch@3.0.1:
+ resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==}
+ engines: {node: '>=12'}
+
+ d3-force@3.0.0:
+ resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==}
+ engines: {node: '>=12'}
+
+ d3-format@3.1.2:
+ resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==}
+ engines: {node: '>=12'}
+
+ d3-geo@3.1.1:
+ resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==}
+ engines: {node: '>=12'}
+
+ d3-hierarchy@3.1.2:
+ resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==}
+ engines: {node: '>=12'}
+
+ d3-interpolate@3.0.1:
+ resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
+ engines: {node: '>=12'}
+
+ d3-path@3.1.0:
+ resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
+ engines: {node: '>=12'}
+
+ d3-polygon@3.0.1:
+ resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==}
+ engines: {node: '>=12'}
+
+ d3-quadtree@3.0.1:
+ resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==}
+ engines: {node: '>=12'}
+
+ d3-random@3.0.1:
+ resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==}
+ engines: {node: '>=12'}
+
+ d3-scale-chromatic@3.1.0:
+ resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==}
+ engines: {node: '>=12'}
+
+ d3-scale@4.0.2:
+ resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
+ engines: {node: '>=12'}
+
+ d3-selection@3.0.0:
+ resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
+ engines: {node: '>=12'}
+
+ d3-shape@3.2.0:
+ resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
+ engines: {node: '>=12'}
+
+ d3-time-format@4.1.0:
+ resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
+ engines: {node: '>=12'}
+
+ d3-time@3.1.0:
+ resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
+ engines: {node: '>=12'}
+
+ d3-timer@3.0.1:
+ resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
+ engines: {node: '>=12'}
+
+ d3-transition@3.0.1:
+ resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
+ engines: {node: '>=12'}
+ peerDependencies:
+ d3-selection: 2 - 3
+
+ d3-zoom@3.0.0:
+ resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
+ engines: {node: '>=12'}
+
+ d3@7.9.0:
+ resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==}
+ engines: {node: '>=12'}
+
damerau-levenshtein@1.0.8:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
@@ -1834,6 +2072,15 @@ packages:
resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
engines: {node: '>= 0.4'}
+ date-fns-tz@1.3.8:
+ resolution: {integrity: sha512-qwNXUFtMHTTU6CFSFjoJ80W8Fzzp24LntbjFFBgL/faqds4e5mo9mftoRLgr3Vi1trISsg4awSpYVsOQCRnapQ==}
+ peerDependencies:
+ date-fns: '>=2.0.0'
+
+ date-fns@2.30.0:
+ resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
+ engines: {node: '>=0.11'}
+
debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
@@ -1865,6 +2112,9 @@ packages:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
+ delaunator@5.1.0:
+ resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==}
+
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
@@ -1873,6 +2123,9 @@ packages:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
+ detect-node-es@1.1.0:
+ resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
+
doctrine@2.1.0:
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
@@ -1883,10 +2136,16 @@ packages:
dom-accessibility-api@0.6.3:
resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
+ dom-helpers@5.2.1:
+ resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
+
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
+ earcut@2.2.4:
+ resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==}
+
electron-to-chromium@1.5.439:
resolution: {integrity: sha512-qu6QIPXhsb+CRcAiTMNjR4A1y/7tCYKkKjr5CZXRVih6qkDf79peZ2BpEU3qoDBNCRrcy3Mra3X9nG5oruuA7Q==}
@@ -1921,8 +2180,8 @@ packages:
resolution: {integrity: sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==}
engines: {node: '>= 0.4'}
- es-module-lexer@1.7.0:
- resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
+ es-module-lexer@2.3.2:
+ resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==}
es-object-atoms@1.1.2:
resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==}
@@ -2110,6 +2369,10 @@ packages:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
+ file-selector@0.1.19:
+ resolution: {integrity: sha512-kCWw3+Aai8Uox+5tHCNgMFaUdgidxvMnLWO6fM5sZ0hA2wlHP5/DHGF0ECe84BiB95qdJbKNEJhWKVDvMN+JDQ==}
+ engines: {node: '>= 10'}
+
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
@@ -2125,6 +2388,10 @@ packages:
flatted@3.4.4:
resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==}
+ focus-lock@1.3.6:
+ resolution: {integrity: sha512-Ik/6OCk9RQQ0T5Xw+hKNLWrjSMtv51dD4GRmJjbD5a58TIEpI5a5iXagKVl3Z5UuyslMCA8Xwnu76jQob62Yhg==}
+ engines: {node: '>=10'}
+
for-each@0.3.5:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
@@ -2157,6 +2424,9 @@ packages:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
+ geojson-vt@3.2.1:
+ resolution: {integrity: sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==}
+
get-intrinsic@1.3.0:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
@@ -2165,6 +2435,10 @@ packages:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
+ get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+
get-symbol-description@1.1.0:
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
engines: {node: '>= 0.4'}
@@ -2172,6 +2446,9 @@ packages:
get-tsconfig@4.14.3:
resolution: {integrity: sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==}
+ gl-matrix@3.4.4:
+ resolution: {integrity: sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==}
+
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -2196,6 +2473,13 @@ packages:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
+ grid-index@1.1.0:
+ resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==}
+
+ hammerjs@2.0.8:
+ resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==}
+ engines: {node: '>=0.8.0'}
+
has-bigints@1.1.0:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
@@ -2245,10 +2529,16 @@ packages:
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
engines: {node: '>= 14'}
+ hyphenate-style-name@1.1.0:
+ resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==}
+
iconv-lite@0.6.3:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
engines: {node: '>=0.10.0'}
+ ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -2269,10 +2559,20 @@ packages:
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
engines: {node: '>=8'}
+ inline-style-prefixer@5.1.2:
+ resolution: {integrity: sha512-PYUF+94gDfhy+LsQxM0g3d6Hge4l1pAqOSOiZuHWzMvQEGsbRQ/ck2WioLqrY2ZkHyPgVUXxn+hrkF7D6QUGbA==}
+
internal-slot@1.1.0:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
+ internmap@2.0.3:
+ resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
+ engines: {node: '>=12'}
+
+ invariant@2.2.4:
+ resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
+
is-array-buffer@3.0.5:
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
engines: {node: '>= 0.4'}
@@ -2389,6 +2689,10 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ isobject@3.0.1:
+ resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
+ engines: {node: '>=0.10.0'}
+
iterator.prototype@1.1.5:
resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
engines: {node: '>= 0.4'}
@@ -2445,6 +2749,12 @@ packages:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
+ just-extend@4.1.1:
+ resolution: {integrity: sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==}
+
+ kdbush@3.0.0:
+ resolution: {integrity: sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==}
+
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@@ -2487,6 +2797,10 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+ mapbox-gl@1.13.3:
+ resolution: {integrity: sha512-p8lJFEiqmEQlyv+DQxFAOG/XPWN0Wp7j/Psq93Zywz7qt9CcUKFYDBOoOEKzqe6gudHVJY8/Bhqw6VDpX2lSBg==}
+ engines: {node: '>=6.4.0'}
+
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
@@ -2494,6 +2808,9 @@ packages:
mdn-data@2.27.1:
resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==}
+ memoize-one@5.0.0:
+ resolution: {integrity: sha512-7g0+ejkOaI9w5x6LvQwmj68kUj6rxROywPSCqmclG/HBacmFnZqhVscQ8kovkn9FBCNJmOz6SY42+jnvZzDWdw==}
+
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
@@ -2516,9 +2833,22 @@ packages:
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+ mjolnir.js@2.7.3:
+ resolution: {integrity: sha512-Z5z/+FzZqOSO3juSVKV3zcm4R2eAlWwlKMcqHmyFEJAaLILNcDKnIbnb4/kbcGyIuhtdWrzu8WOIR7uM6I34aw==}
+ engines: {node: '>= 4', npm: '>= 3'}
+
+ mockdate@2.0.5:
+ resolution: {integrity: sha512-ST0PnThzWKcgSLyc+ugLVql45PvESt3Ul/wrdV/OPc/6Pr8dbLAIJsN1cIp41FLzbN+srVTNIRn+5Cju0nyV6A==}
+
+ moment@2.31.0:
+ resolution: {integrity: sha512-0acOTfMiWOheYS4eoWb80yYMb/JLvVv9SHbs2PehaDzfUG0Bw855SKyk0IKTnPGa5+U2bmi3W68l1+sGLX/pvw==}
+
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ murmurhash-js@1.0.0:
+ resolution: {integrity: sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==}
+
nanoid@3.3.20:
resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -2596,6 +2926,10 @@ packages:
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
engines: {node: '>= 0.4'}
+ obug@2.2.1:
+ resolution: {integrity: sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==}
+ engines: {node: '>=12.20.0'}
+
on-exit-leak-free@2.1.2:
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
engines: {node: '>=14.0.0'}
@@ -2640,6 +2974,10 @@ packages:
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+ pbf@3.3.0:
+ resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==}
+ hasBin: true
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -2671,6 +3009,14 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ polished@4.3.1:
+ resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==}
+ engines: {node: '>=10'}
+
+ popper.js@1.16.1:
+ resolution: {integrity: sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==}
+ deprecated: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1
+
possible-typed-array-names@1.1.0:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
@@ -2683,6 +3029,9 @@ packages:
resolution: {integrity: sha512-zkd+e9S1AQHhmaBKye9zlFHWjOwVgqXl1q3ECYy8561K7qxR2cREf/STLskulBFd78k6AOFeA+ff1TtEzk9bAA==}
engines: {node: ^10 || ^12 || >=14}
+ potpack@1.0.2:
+ resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==}
+
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@@ -2694,9 +3043,17 @@ packages:
process-warning@5.1.0:
resolution: {integrity: sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==}
+ prop-types-extra@1.1.1:
+ resolution: {integrity: sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==}
+ peerDependencies:
+ react: '>=0.14.0'
+
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ protocol-buffers-schema@3.6.1:
+ resolution: {integrity: sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==}
+
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@@ -2707,6 +3064,14 @@ packages:
quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
+ quickselect@2.0.0:
+ resolution: {integrity: sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==}
+
+ react-clientside-effect@1.2.8:
+ resolution: {integrity: sha512-ma2FePH0z3px2+WOu6h+YycZcEvFmmxIlAb62cF52bG86eMySciO/EQZeQMXd07kPCYB0a1dWDT5J+KE9mCDUw==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+
react-dom@18.3.1:
resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
peerDependencies:
@@ -2717,12 +3082,97 @@ packages:
peerDependencies:
react: ^19.3.0
+ react-dropzone@9.0.0:
+ resolution: {integrity: sha512-wZ2o9B2qkdE3RumWhfyZT9swgJYJPeU5qHEcMU8weYpmLex1eeWX0CC32/Y0VutB+BBi2D+iePV/YZIiB4kZGw==}
+ engines: {node: '>= 6'}
+ peerDependencies:
+ react: '>=0.14.0'
+
+ react-focus-lock@2.13.7:
+ resolution: {integrity: sha512-20lpZHEQrXPb+pp1tzd4ULL6DyO5D2KnR0G69tTDdydrmNhU7pdFmbQUYVyHUgp+xN29IuFR0PVuhOmvaZL9Og==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react-hook-form@7.90.0:
+ resolution: {integrity: sha512-+NdG0FLzCPhFOp2NNxaUYLF9fyZhNjx9FTBBSYWF71/l6BBlmIc/j6xlp3DbaHWLJbIG7Zd8oznA19xJClU97w==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17 || ^18 || ^19
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react-input-mask@2.0.4:
+ resolution: {integrity: sha512-1hwzMr/aO9tXfiroiVCx5EtKohKwLk/NT8QlJXHQ4N+yJJFyUuMT+zfTpLBwX/lK3PkuMlievIffncpMZ3HGRQ==}
+ peerDependencies:
+ react: '>=0.14.0'
+ react-dom: '>=0.14.0'
+
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-lifecycles-compat@3.0.4:
+ resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
+
+ react-map-gl@5.2.13:
+ resolution: {integrity: sha512-yYqpZJADB7o5epiYpkcUED5MWevFnOsVn9mgKfizxjsenLMpVNgNgb/x0e9DS4VZtpOLWW2ZXYBB4BJZJlZmTQ==}
+ engines: {node: '>= 4', npm: '>= 3'}
+ peerDependencies:
+ react: '>=16.3.0'
+
+ react-movable@3.4.1:
+ resolution: {integrity: sha512-VTrBKjRWV4yVUDGj5dIZIhf07fyoFDXzIV6xs3KNNHpgPbkPT7FNu/Vbe11ZjHmT48uOykCmRMpS66DrzRbZZg==}
+ peerDependencies:
+ react: '*'
+ react-dom: '*'
+
+ react-multi-ref@1.0.2:
+ resolution: {integrity: sha512-6oS5yzrZ4UrdMHbF6QAnnaoIe9h8R+Xv4m8uJWVK8/Q4RCc6RTT0XJ/LZ7llVgFcVbnDHeUAcVIhtRgFyzjJpA==}
+
+ react-range@1.10.0:
+ resolution: {integrity: sha512-kDo0LiBUHIQIP8menx0UoxTnHr7UXBYpIYl/DR9jCaO1o29VwvCLpkP/qOTNQz5hkJadPg1uEM07XJcJ1XGoKw==}
+ peerDependencies:
+ react: '*'
+ react-dom: '*'
+
+ react-uid@2.3.0:
+ resolution: {integrity: sha512-tsPZ77GR0pISGYmpCLHAbZTabKXZ7zBniKPVqVMMfnXFyo39zq5g/psIlD5vLTKkjQEhWOO8JhqcHnxkwNu6eA==}
+ engines: {node: '>=8.5.0'}
+ peerDependencies:
+ '@types/react': ^16.8.0
+ react: ^16.8.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react-virtualized-auto-sizer@1.0.2:
+ resolution: {integrity: sha512-MYXhTY1BZpdJFjUovvYHVBmkq79szK/k7V3MO+36gJkWGkrXKtyr4vCPtpphaTLRAdDNoYEYFZWE8LjN+PIHNg==}
+ engines: {node: '>8.0.0'}
+ peerDependencies:
+ react: ^15.3.0 || ^16.0.0-alpha
+ react-dom: ^15.3.0 || ^16.0.0-alpha
+
+ react-virtualized@9.22.6:
+ resolution: {integrity: sha512-U5j7KuUQt3AaMatlMJ0UJddqSiX+Km0YJxSqbAzIiGw5EmNz0khMyqP2hzgu4+QUtm+QPIrxzUX4raJxmVJnHg==}
+ peerDependencies:
+ react: ^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-dom: ^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+ react-window@1.8.5:
+ resolution: {integrity: sha512-HeTwlNa37AFa8MDZFZOKcNEkuF2YflA0hpGPiTT9vR7OawEt+GZbfM6wqkBahD3D3pUjIabQYzsnY/BSJbgq6Q==}
+ engines: {node: '>8.0.0'}
+ peerDependencies:
+ react: ^15.0.0 || ^16.0.0
+ react-dom: ^15.0.0 || ^16.0.0
+
react@18.3.1:
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
engines: {node: '>=0.10.0'}
@@ -2750,6 +3200,9 @@ packages:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
+ resize-observer-polyfill@1.5.1:
+ resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
+
resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
@@ -2757,6 +3210,9 @@ packages:
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+ resolve-protobuf-schema@2.1.0:
+ resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==}
+
resolve@2.0.0-next.7:
resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==}
engines: {node: '>= 0.4'}
@@ -2766,6 +3222,9 @@ packages:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ robust-predicates@3.0.3:
+ resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==}
+
rollup@4.63.5:
resolution: {integrity: sha512-KRWwmNLlPw5M7HcdYfm15oBv9n9LPtjzpzCIxS/phwqvPyxHSoKX6Y2YU3pxSPfy0CLquVgsx/j/hBi6OvH1Nw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -2777,6 +3236,9 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ rw@1.3.3:
+ resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
+
safe-array-concat@1.1.4:
resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==}
engines: {node: '>=0.4'}
@@ -2883,8 +3345,8 @@ packages:
stackback@0.0.2:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
- std-env@3.10.0:
- resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+ std-env@4.3.0:
+ resolution: {integrity: sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==}
stop-iteration-iterator@1.1.0:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
@@ -2938,6 +3400,20 @@ packages:
babel-plugin-macros:
optional: true
+ styletron-engine-atomic@1.6.2:
+ resolution: {integrity: sha512-vWSIxpCkYbVD3xhnxYwnJDJePD8p8pJCu7g1zFxdQIM4z34Eo1zj3LgXJI6yeNMrJ7PkE56SYK6ZOo3hpTOBzA==}
+
+ styletron-react@6.1.1:
+ resolution: {integrity: sha512-K04BwKZTrdRG/wR5BaFG8z0bFu1jkT2HAp0UP5ZeMAKW6Ix8J3yuROWLoLUMZafaRRQ9LjiLpIl65u75L7YZow==}
+ peerDependencies:
+ react: '>=16.8.0'
+
+ styletron-standard@3.1.0:
+ resolution: {integrity: sha512-Cr2q0IFsag6OaIeD/LBNRuCxNTPa/WtTbKP1X3o50mDudN8FGwmD5h1sMJ/Bu5+mO/2NfrNAv9V9zUXn6lXXMA==}
+
+ supercluster@7.1.5:
+ resolution: {integrity: sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==}
+
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -2956,13 +3432,17 @@ packages:
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
- tinyexec@0.3.2:
- resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+ tinyexec@1.3.1:
+ resolution: {integrity: sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==}
+ engines: {node: '>=18'}
tinyglobby@0.2.17:
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
engines: {node: '>=12.0.0'}
+ tinyqueue@2.0.3:
+ resolution: {integrity: sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==}
+
tinyrainbow@3.1.1:
resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==}
engines: {node: '>=14.0.0'}
@@ -3010,6 +3490,9 @@ packages:
tsconfig-paths@3.15.0:
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
+ tslib@1.14.1:
+ resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -3069,6 +3552,30 @@ packages:
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ use-callback-ref@1.3.3:
+ resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ use-sidecar@1.1.3:
+ resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ viewport-mercator-project@7.0.4:
+ resolution: {integrity: sha512-0jzpL6pIMocCKWg1C3mqi/N4UPgZC3FzwghEm1H+XsUo8hNZAyJc3QR7YqC816ibOR8aWT5pCsV+gCu8/BMJgg==}
+ deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
+
vite@7.3.6:
resolution: {integrity: sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -3109,24 +3616,27 @@ packages:
yaml:
optional: true
- vitest@4.0.7:
- resolution: {integrity: sha512-xQroKAadK503CrmbzCISvQUjeuvEZzv6U0wlnlVFOi5i3gnzfH4onyQ29f3lzpe0FresAiTAd3aqK0Bi/jLI8w==}
+ vitest@4.1.11:
+ resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==}
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
- '@types/debug': ^4.1.12
+ '@opentelemetry/api': ^1.9.0
'@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
- '@vitest/browser-playwright': 4.0.7
- '@vitest/browser-preview': 4.0.7
- '@vitest/browser-webdriverio': 4.0.7
- '@vitest/ui': 4.0.7
+ '@vitest/browser-playwright': 4.1.11
+ '@vitest/browser-preview': 4.1.11
+ '@vitest/browser-webdriverio': 4.1.11
+ '@vitest/coverage-istanbul': 4.1.11
+ '@vitest/coverage-v8': 4.1.11
+ '@vitest/ui': 4.1.11
happy-dom: '*'
jsdom: '*'
+ vite: ^6.0.0 || ^7.0.0 || ^8.0.0
peerDependenciesMeta:
'@edge-runtime/vm':
optional: true
- '@types/debug':
+ '@opentelemetry/api':
optional: true
'@types/node':
optional: true
@@ -3136,6 +3646,10 @@ packages:
optional: true
'@vitest/browser-webdriverio':
optional: true
+ '@vitest/coverage-istanbul':
+ optional: true
+ '@vitest/coverage-v8':
+ optional: true
'@vitest/ui':
optional: true
happy-dom:
@@ -3143,10 +3657,16 @@ packages:
jsdom:
optional: true
+ vt-pbf@3.1.3:
+ resolution: {integrity: sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==}
+
w3c-xmlserializer@5.0.0:
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
engines: {node: '>=18'}
+ warning@4.0.3:
+ resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
+
webidl-conversions@7.0.0:
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
engines: {node: '>=12'}
@@ -3361,8 +3881,6 @@ snapshots:
'@babel/runtime@7.29.10': {}
- '@babel/runtime@7.29.7': {}
-
'@babel/template@7.29.7':
dependencies:
'@babel/code-frame': 7.29.7
@@ -3498,6 +4016,20 @@ snapshots:
'@csstools/css-tokenizer@4.0.2':
optional: true
+ '@date-io/core@2.17.0': {}
+
+ '@date-io/date-fns@2.17.0(date-fns@2.30.0)':
+ dependencies:
+ '@date-io/core': 2.17.0
+ optionalDependencies:
+ date-fns: 2.30.0
+
+ '@date-io/moment@2.17.0(moment@2.31.0)':
+ dependencies:
+ '@date-io/core': 2.17.0
+ optionalDependencies:
+ moment: 2.31.0
+
'@emnapi/core@1.10.0':
dependencies:
'@emnapi/wasi-threads': 1.2.1
@@ -3793,6 +4325,36 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.6.0
+ '@mapbox/geojson-rewind@0.5.2':
+ dependencies:
+ get-stream: 6.0.1
+ minimist: 1.2.8
+
+ '@mapbox/geojson-types@1.0.2': {}
+
+ '@mapbox/jsonlint-lines-primitives@2.0.3': {}
+
+ '@mapbox/mapbox-gl-supported@1.5.0(mapbox-gl@1.13.3)':
+ dependencies:
+ mapbox-gl: 1.13.3
+
+ '@mapbox/point-geometry@0.1.0': {}
+
+ '@mapbox/tiny-sdf@1.2.5': {}
+
+ '@mapbox/unitbezier@0.0.0': {}
+
+ '@mapbox/vector-tile@1.3.1':
+ dependencies:
+ '@mapbox/point-geometry': 0.1.0
+
+ '@mapbox/whoots-js@3.1.0': {}
+
+ '@math.gl/web-mercator@3.6.3':
+ dependencies:
+ '@babel/runtime': 7.29.10
+ gl-matrix: 3.4.4
+
'@napi-rs/lzma-linux-x64-gnu@1.5.1':
optional: true
@@ -3960,6 +4522,8 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.63.5':
optional: true
+ '@rtsao/csstype@2.6.5-forked.0': {}
+
'@rtsao/scc@1.1.0': {}
'@standard-schema/spec@1.1.0': {}
@@ -3991,7 +4555,7 @@ snapshots:
'@testing-library/react@16.3.3(@testing-library/dom@10.4.2)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
dependencies:
- '@babel/runtime': 7.29.7
+ '@babel/runtime': 7.29.10
'@testing-library/dom': 10.4.2
react: 19.3.0
react-dom: 19.3.0(react@19.3.0)
@@ -4015,6 +4579,8 @@ snapshots:
'@types/estree@1.0.9': {}
+ '@types/hammerjs@2.0.46': {}
+
'@types/json-schema@7.0.15': {}
'@types/json5@0.0.29': {}
@@ -4199,43 +4765,45 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.12.2':
optional: true
- '@vitest/expect@4.0.7':
+ '@vitest/expect@4.1.11':
dependencies:
'@standard-schema/spec': 1.1.0
'@types/chai': 5.2.3
- '@vitest/spy': 4.0.7
- '@vitest/utils': 4.0.7
+ '@vitest/spy': 4.1.11
+ '@vitest/utils': 4.1.11
chai: 6.2.2
tinyrainbow: 3.1.1
- '@vitest/mocker@4.0.7(vite@7.3.6(@types/node@22.18.6))':
+ '@vitest/mocker@4.1.11(vite@7.3.6(@types/node@22.18.6))':
dependencies:
- '@vitest/spy': 4.0.7
+ '@vitest/spy': 4.1.11
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
vite: 7.3.6(@types/node@22.18.6)
- '@vitest/pretty-format@4.0.7':
+ '@vitest/pretty-format@4.1.11':
dependencies:
tinyrainbow: 3.1.1
- '@vitest/runner@4.0.7':
+ '@vitest/runner@4.1.11':
dependencies:
- '@vitest/utils': 4.0.7
+ '@vitest/utils': 4.1.11
pathe: 2.0.3
- '@vitest/snapshot@4.0.7':
+ '@vitest/snapshot@4.1.11':
dependencies:
- '@vitest/pretty-format': 4.0.7
+ '@vitest/pretty-format': 4.1.11
+ '@vitest/utils': 4.1.11
magic-string: 0.30.21
pathe: 2.0.3
- '@vitest/spy@4.0.7': {}
+ '@vitest/spy@4.1.11': {}
- '@vitest/utils@4.0.7':
+ '@vitest/utils@4.1.11':
dependencies:
- '@vitest/pretty-format': 4.0.7
+ '@vitest/pretty-format': 4.1.11
+ convert-source-map: 2.0.0
tinyrainbow: 3.1.1
acorn-jsx@5.3.2(acorn@8.18.0):
@@ -4344,13 +4912,17 @@ snapshots:
atomic-sleep@1.0.0: {}
+ attr-accept@1.1.3:
+ dependencies:
+ core-js: 2.6.12
+
available-typed-arrays@1.0.7:
dependencies:
possible-typed-array-names: 1.1.0
axe-core@4.10.3: {}
- axe-core@4.13.0: {}
+ axe-core@4.14.0: {}
axobject-query@4.1.0: {}
@@ -4360,11 +4932,87 @@ snapshots:
baseline-browser-mapping@2.11.28: {}
- bidi-js@1.1.0:
- dependencies:
- require-from-string: 2.0.2
- optional: true
-
+ baseui@18.2.0(@types/react@19.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styletron-react@6.1.1(react@18.3.1)):
+ dependencies:
+ '@date-io/date-fns': 2.17.0(date-fns@2.30.0)
+ '@date-io/moment': 2.17.0(moment@2.31.0)
+ axe-core: 4.14.0
+ card-validator: 6.2.0
+ csstype: 2.6.11
+ d3: 7.9.0
+ date-fns: 2.30.0
+ date-fns-tz: 1.3.8(date-fns@2.30.0)
+ just-extend: 4.1.1
+ memoize-one: 5.0.0
+ mockdate: 2.0.5
+ moment: 2.31.0
+ polished: 4.3.1
+ popper.js: 1.16.1
+ prop-types: 15.8.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-dropzone: 9.0.0(react@18.3.1)
+ react-focus-lock: 2.13.7(@types/react@19.3.0)(react@18.3.1)
+ react-hook-form: 7.90.0(@types/react@19.3.0)(react@18.3.1)
+ react-input-mask: 2.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-is: 17.0.2
+ react-map-gl: 5.2.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-movable: 3.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-multi-ref: 1.0.2
+ react-range: 1.10.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-uid: 2.3.0(@types/react@19.3.0)(react@18.3.1)
+ react-virtualized: 9.22.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-virtualized-auto-sizer: 1.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-window: 1.8.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ resize-observer-polyfill: 1.5.1
+ styletron-react: 6.1.1(react@18.3.1)
+ styletron-standard: 3.1.0
+ transitivePeerDependencies:
+ - '@types/react'
+
+ baseui@18.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(styletron-react@6.1.1(react@19.3.0)):
+ dependencies:
+ '@date-io/date-fns': 2.17.0(date-fns@2.30.0)
+ '@date-io/moment': 2.17.0(moment@2.31.0)
+ axe-core: 4.14.0
+ card-validator: 6.2.0
+ csstype: 2.6.11
+ d3: 7.9.0
+ date-fns: 2.30.0
+ date-fns-tz: 1.3.8(date-fns@2.30.0)
+ just-extend: 4.1.1
+ memoize-one: 5.0.0
+ mockdate: 2.0.5
+ moment: 2.31.0
+ polished: 4.3.1
+ popper.js: 1.16.1
+ prop-types: 15.8.1
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ react-dropzone: 9.0.0(react@19.3.0)
+ react-focus-lock: 2.13.7(@types/react@19.3.0)(react@19.3.0)
+ react-hook-form: 7.90.0(@types/react@19.3.0)(react@19.3.0)
+ react-input-mask: 2.0.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react-is: 17.0.2
+ react-map-gl: 5.2.13(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react-movable: 3.4.1(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react-multi-ref: 1.0.2
+ react-range: 1.10.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react-uid: 2.3.0(@types/react@19.3.0)(react@19.3.0)
+ react-virtualized: 9.22.6(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react-virtualized-auto-sizer: 1.0.2(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react-window: 1.8.5(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ resize-observer-polyfill: 1.5.1
+ styletron-react: 6.1.1(react@19.3.0)
+ styletron-standard: 3.1.0
+ transitivePeerDependencies:
+ - '@types/react'
+
+ bidi-js@1.1.0:
+ dependencies:
+ require-from-string: 2.0.2
+ optional: true
+
brace-expansion@1.1.21:
dependencies:
balanced-match: 1.0.2
@@ -4407,6 +5055,10 @@ snapshots:
caniuse-lite@1.0.30001816: {}
+ card-validator@6.2.0:
+ dependencies:
+ credit-card-type: 8.3.0
+
chai@6.2.2: {}
chalk@4.1.2:
@@ -4416,22 +5068,35 @@ snapshots:
client-only@0.0.1: {}
+ clsx@1.2.1: {}
+
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
color-name@1.1.4: {}
+ commander@7.2.0: {}
+
concat-map@0.0.1: {}
convert-source-map@2.0.0: {}
+ core-js@2.6.12: {}
+
+ credit-card-type@8.3.0: {}
+
cross-spawn@7.0.6:
dependencies:
path-key: 3.1.1
shebang-command: 2.0.0
which: 2.0.2
+ css-in-js-utils@2.0.1:
+ dependencies:
+ hyphenate-style-name: 1.1.0
+ isobject: 3.0.1
+
css-tree@3.2.1:
dependencies:
mdn-data: 2.27.1
@@ -4440,6 +5105,8 @@ snapshots:
css.escape@1.5.1: {}
+ csscolorparser@1.0.3: {}
+
cssstyle@4.6.0:
dependencies:
'@asamuzakjp/css-color': 3.2.0
@@ -4453,8 +5120,162 @@ snapshots:
lru-cache: 11.5.3
optional: true
+ csstype@2.6.11: {}
+
csstype@3.2.3: {}
+ d3-array@3.2.4:
+ dependencies:
+ internmap: 2.0.3
+
+ d3-axis@3.0.0: {}
+
+ d3-brush@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+
+ d3-chord@3.0.1:
+ dependencies:
+ d3-path: 3.1.0
+
+ d3-color@3.1.0: {}
+
+ d3-contour@4.0.2:
+ dependencies:
+ d3-array: 3.2.4
+
+ d3-delaunay@6.0.4:
+ dependencies:
+ delaunator: 5.1.0
+
+ d3-dispatch@3.0.1: {}
+
+ d3-drag@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-selection: 3.0.0
+
+ d3-dsv@3.0.1:
+ dependencies:
+ commander: 7.2.0
+ iconv-lite: 0.6.3
+ rw: 1.3.3
+
+ d3-ease@3.0.1: {}
+
+ d3-fetch@3.0.1:
+ dependencies:
+ d3-dsv: 3.0.1
+
+ d3-force@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-quadtree: 3.0.1
+ d3-timer: 3.0.1
+
+ d3-format@3.1.2: {}
+
+ d3-geo@3.1.1:
+ dependencies:
+ d3-array: 3.2.4
+
+ d3-hierarchy@3.1.2: {}
+
+ d3-interpolate@3.0.1:
+ dependencies:
+ d3-color: 3.1.0
+
+ d3-path@3.1.0: {}
+
+ d3-polygon@3.0.1: {}
+
+ d3-quadtree@3.0.1: {}
+
+ d3-random@3.0.1: {}
+
+ d3-scale-chromatic@3.1.0:
+ dependencies:
+ d3-color: 3.1.0
+ d3-interpolate: 3.0.1
+
+ d3-scale@4.0.2:
+ dependencies:
+ d3-array: 3.2.4
+ d3-format: 3.1.2
+ d3-interpolate: 3.0.1
+ d3-time: 3.1.0
+ d3-time-format: 4.1.0
+
+ d3-selection@3.0.0: {}
+
+ d3-shape@3.2.0:
+ dependencies:
+ d3-path: 3.1.0
+
+ d3-time-format@4.1.0:
+ dependencies:
+ d3-time: 3.1.0
+
+ d3-time@3.1.0:
+ dependencies:
+ d3-array: 3.2.4
+
+ d3-timer@3.0.1: {}
+
+ d3-transition@3.0.1(d3-selection@3.0.0):
+ dependencies:
+ d3-color: 3.1.0
+ d3-dispatch: 3.0.1
+ d3-ease: 3.0.1
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-timer: 3.0.1
+
+ d3-zoom@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+
+ d3@7.9.0:
+ dependencies:
+ d3-array: 3.2.4
+ d3-axis: 3.0.0
+ d3-brush: 3.0.0
+ d3-chord: 3.0.1
+ d3-color: 3.1.0
+ d3-contour: 4.0.2
+ d3-delaunay: 6.0.4
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-dsv: 3.0.1
+ d3-ease: 3.0.1
+ d3-fetch: 3.0.1
+ d3-force: 3.0.0
+ d3-format: 3.1.2
+ d3-geo: 3.1.1
+ d3-hierarchy: 3.1.2
+ d3-interpolate: 3.0.1
+ d3-path: 3.1.0
+ d3-polygon: 3.0.1
+ d3-quadtree: 3.0.1
+ d3-random: 3.0.1
+ d3-scale: 4.0.2
+ d3-scale-chromatic: 3.1.0
+ d3-selection: 3.0.0
+ d3-shape: 3.2.0
+ d3-time: 3.1.0
+ d3-time-format: 4.1.0
+ d3-timer: 3.0.1
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+ d3-zoom: 3.0.0
+
damerau-levenshtein@1.0.8: {}
data-urls@5.0.0:
@@ -4486,6 +5307,14 @@ snapshots:
es-errors: 1.3.0
is-data-view: 1.0.2
+ date-fns-tz@1.3.8(date-fns@2.30.0):
+ dependencies:
+ date-fns: 2.30.0
+
+ date-fns@2.30.0:
+ dependencies:
+ '@babel/runtime': 7.29.10
+
debug@3.2.7:
dependencies:
ms: 2.1.3
@@ -4510,11 +5339,17 @@ snapshots:
has-property-descriptors: 1.0.2
object-keys: 1.1.1
+ delaunator@5.1.0:
+ dependencies:
+ robust-predicates: 3.0.3
+
dequal@2.0.3: {}
detect-libc@2.1.2:
optional: true
+ detect-node-es@1.1.0: {}
+
doctrine@2.1.0:
dependencies:
esutils: 2.0.3
@@ -4523,12 +5358,19 @@ snapshots:
dom-accessibility-api@0.6.3: {}
+ dom-helpers@5.2.1:
+ dependencies:
+ '@babel/runtime': 7.29.10
+ csstype: 3.2.3
+
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
es-errors: 1.3.0
gopd: 1.2.0
+ earcut@2.2.4: {}
+
electron-to-chromium@1.5.439: {}
emoji-regex@9.2.2: {}
@@ -4625,7 +5467,7 @@ snapshots:
iterator.prototype: 1.1.5
math-intrinsics: 1.1.0
- es-module-lexer@1.7.0: {}
+ es-module-lexer@2.3.2: {}
es-object-atoms@1.1.2:
dependencies:
@@ -4845,7 +5687,7 @@ snapshots:
array-includes: 3.2.0
array.prototype.flatmap: 1.3.3
ast-types-flow: 0.0.8
- axe-core: 4.13.0
+ axe-core: 4.14.0
axobject-query: 4.1.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
@@ -4991,6 +5833,10 @@ snapshots:
dependencies:
flat-cache: 4.0.1
+ file-selector@0.1.19:
+ dependencies:
+ tslib: 2.8.1
+
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
@@ -5007,6 +5853,10 @@ snapshots:
flatted@3.4.4: {}
+ focus-lock@1.3.6:
+ dependencies:
+ tslib: 2.8.1
+
for-each@0.3.5:
dependencies:
is-callable: 1.2.7
@@ -5037,6 +5887,8 @@ snapshots:
gensync@1.0.0-beta.2: {}
+ geojson-vt@3.2.1: {}
+
get-intrinsic@1.3.0:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -5055,6 +5907,8 @@ snapshots:
dunder-proto: 1.0.1
es-object-atoms: 1.1.2
+ get-stream@6.0.1: {}
+
get-symbol-description@1.1.0:
dependencies:
call-bound: 1.0.4
@@ -5065,6 +5919,8 @@ snapshots:
dependencies:
resolve-pkg-maps: 1.0.0
+ gl-matrix@3.4.4: {}
+
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@@ -5084,6 +5940,10 @@ snapshots:
gopd@1.2.0: {}
+ grid-index@1.1.0: {}
+
+ hammerjs@2.0.8: {}
+
has-bigints@1.1.0: {}
has-flag@4.0.0: {}
@@ -5137,10 +5997,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ hyphenate-style-name@1.1.0: {}
+
iconv-lite@0.6.3:
dependencies:
safer-buffer: 2.1.2
+ ieee754@1.2.1: {}
+
ignore@5.3.2: {}
ignore@7.0.10: {}
@@ -5154,12 +6018,22 @@ snapshots:
indent-string@4.0.0: {}
+ inline-style-prefixer@5.1.2:
+ dependencies:
+ css-in-js-utils: 2.0.1
+
internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
hasown: 2.0.4
side-channel: 1.1.1
+ internmap@2.0.3: {}
+
+ invariant@2.2.4:
+ dependencies:
+ loose-envify: 1.4.0
+
is-array-buffer@3.0.5:
dependencies:
call-bind: 1.0.9
@@ -5282,6 +6156,8 @@ snapshots:
isexe@2.0.0: {}
+ isobject@3.0.1: {}
+
iterator.prototype@1.1.5:
dependencies:
define-data-property: 1.1.4
@@ -5374,6 +6250,10 @@ snapshots:
object.assign: 4.1.7
object.values: 1.2.1
+ just-extend@4.1.1: {}
+
+ kdbush@3.0.0: {}
+
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
@@ -5414,11 +6294,38 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.6.0
+ mapbox-gl@1.13.3:
+ dependencies:
+ '@mapbox/geojson-rewind': 0.5.2
+ '@mapbox/geojson-types': 1.0.2
+ '@mapbox/jsonlint-lines-primitives': 2.0.3
+ '@mapbox/mapbox-gl-supported': 1.5.0(mapbox-gl@1.13.3)
+ '@mapbox/point-geometry': 0.1.0
+ '@mapbox/tiny-sdf': 1.2.5
+ '@mapbox/unitbezier': 0.0.0
+ '@mapbox/vector-tile': 1.3.1
+ '@mapbox/whoots-js': 3.1.0
+ csscolorparser: 1.0.3
+ earcut: 2.2.4
+ geojson-vt: 3.2.1
+ gl-matrix: 3.4.4
+ grid-index: 1.1.0
+ murmurhash-js: 1.0.0
+ pbf: 3.3.0
+ potpack: 1.0.2
+ quickselect: 2.0.0
+ rw: 1.3.3
+ supercluster: 7.1.5
+ tinyqueue: 2.0.3
+ vt-pbf: 3.1.3
+
math-intrinsics@1.1.0: {}
mdn-data@2.27.1:
optional: true
+ memoize-one@5.0.0: {}
+
merge2@1.4.1: {}
micromatch@4.0.8:
@@ -5438,8 +6345,19 @@ snapshots:
minimist@1.2.8: {}
+ mjolnir.js@2.7.3:
+ dependencies:
+ '@types/hammerjs': 2.0.46
+ hammerjs: 2.0.8
+
+ mockdate@2.0.5: {}
+
+ moment@2.31.0: {}
+
ms@2.1.3: {}
+ murmurhash-js@1.0.0: {}
+
nanoid@3.3.20: {}
napi-postinstall@0.3.4: {}
@@ -5526,6 +6444,8 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.1.2
+ obug@2.2.1: {}
+
on-exit-leak-free@2.1.2: {}
optionator@0.9.4:
@@ -5573,6 +6493,11 @@ snapshots:
pathe@2.0.3: {}
+ pbf@3.3.0:
+ dependencies:
+ ieee754: 1.2.1
+ resolve-protobuf-schema: 2.1.0
+
picocolors@1.1.1: {}
picomatch@2.3.2: {}
@@ -5607,6 +6532,12 @@ snapshots:
optionalDependencies:
fsevents: 2.3.2
+ polished@4.3.1:
+ dependencies:
+ '@babel/runtime': 7.29.10
+
+ popper.js@1.16.1: {}
+
possible-typed-array-names@1.1.0: {}
postcss@8.5.23:
@@ -5621,6 +6552,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.2
+ potpack@1.0.2: {}
+
prelude-ls@1.2.1: {}
pretty-format@27.5.1:
@@ -5631,18 +6564,44 @@ snapshots:
process-warning@5.1.0: {}
+ prop-types-extra@1.1.1(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-is: 16.13.1
+ warning: 4.0.3
+
+ prop-types-extra@1.1.1(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ react-is: 16.13.1
+ warning: 4.0.3
+
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
react-is: 16.13.1
+ protocol-buffers-schema@3.6.1: {}
+
punycode@2.3.1: {}
queue-microtask@1.2.3: {}
quick-format-unescaped@4.0.4: {}
+ quickselect@2.0.0: {}
+
+ react-clientside-effect@1.2.8(react@18.3.1):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ react: 18.3.1
+
+ react-clientside-effect@1.2.8(react@19.3.0):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ react: 19.3.0
+
react-dom@18.3.1(react@18.3.1):
dependencies:
loose-envify: 1.4.0
@@ -5654,10 +6613,186 @@ snapshots:
react: 19.3.0
scheduler: 0.28.0
+ react-dropzone@9.0.0(react@18.3.1):
+ dependencies:
+ attr-accept: 1.1.3
+ file-selector: 0.1.19
+ prop-types: 15.8.1
+ prop-types-extra: 1.1.1(react@18.3.1)
+ react: 18.3.1
+
+ react-dropzone@9.0.0(react@19.3.0):
+ dependencies:
+ attr-accept: 1.1.3
+ file-selector: 0.1.19
+ prop-types: 15.8.1
+ prop-types-extra: 1.1.1(react@19.3.0)
+ react: 19.3.0
+
+ react-focus-lock@2.13.7(@types/react@19.3.0)(react@18.3.1):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ focus-lock: 1.3.6
+ prop-types: 15.8.1
+ react: 18.3.1
+ react-clientside-effect: 1.2.8(react@18.3.1)
+ use-callback-ref: 1.3.3(@types/react@19.3.0)(react@18.3.1)
+ use-sidecar: 1.1.3(@types/react@19.3.0)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ react-focus-lock@2.13.7(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ focus-lock: 1.3.6
+ prop-types: 15.8.1
+ react: 19.3.0
+ react-clientside-effect: 1.2.8(react@19.3.0)
+ use-callback-ref: 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ use-sidecar: 1.1.3(@types/react@19.3.0)(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ react-hook-form@7.90.0(@types/react@19.3.0)(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ react-hook-form@7.90.0(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ react-input-mask@2.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ invariant: 2.2.4
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ warning: 4.0.3
+
+ react-input-mask@2.0.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ invariant: 2.2.4
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ warning: 4.0.3
+
react-is@16.13.1: {}
react-is@17.0.2: {}
+ react-lifecycles-compat@3.0.4: {}
+
+ react-map-gl@5.2.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ mapbox-gl: 1.13.3
+ mjolnir.js: 2.7.3
+ prop-types: 15.8.1
+ react: 18.3.1
+ react-virtualized-auto-sizer: 1.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ viewport-mercator-project: 7.0.4
+ transitivePeerDependencies:
+ - react-dom
+
+ react-map-gl@5.2.13(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ mapbox-gl: 1.13.3
+ mjolnir.js: 2.7.3
+ prop-types: 15.8.1
+ react: 19.3.0
+ react-virtualized-auto-sizer: 1.0.2(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ viewport-mercator-project: 7.0.4
+ transitivePeerDependencies:
+ - react-dom
+
+ react-movable@3.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
+ react-movable@3.4.1(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+
+ react-multi-ref@1.0.2:
+ dependencies:
+ '@babel/runtime': 7.29.10
+
+ react-range@1.10.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
+ react-range@1.10.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+
+ react-uid@2.3.0(@types/react@19.3.0)(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ tslib: 1.14.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ react-uid@2.3.0(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ tslib: 1.14.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ react-virtualized-auto-sizer@1.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
+ react-virtualized-auto-sizer@1.0.2(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+
+ react-virtualized@9.22.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ clsx: 1.2.1
+ dom-helpers: 5.2.1
+ loose-envify: 1.4.0
+ prop-types: 15.8.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-lifecycles-compat: 3.0.4
+
+ react-virtualized@9.22.6(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ clsx: 1.2.1
+ dom-helpers: 5.2.1
+ loose-envify: 1.4.0
+ prop-types: 15.8.1
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ react-lifecycles-compat: 3.0.4
+
+ react-window@1.8.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ memoize-one: 5.0.0
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
+ react-window@1.8.5(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ '@babel/runtime': 7.29.10
+ memoize-one: 5.0.0
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+
react@18.3.1:
dependencies:
loose-envify: 1.4.0
@@ -5694,10 +6829,16 @@ snapshots:
require-from-string@2.0.2:
optional: true
+ resize-observer-polyfill@1.5.1: {}
+
resolve-from@4.0.0: {}
resolve-pkg-maps@1.0.0: {}
+ resolve-protobuf-schema@2.1.0:
+ dependencies:
+ protocol-buffers-schema: 3.6.1
+
resolve@2.0.0-next.7:
dependencies:
es-errors: 1.3.0
@@ -5709,6 +6850,8 @@ snapshots:
reusify@1.1.0: {}
+ robust-predicates@3.0.3: {}
+
rollup@4.63.5:
dependencies:
'@types/estree': 1.0.9
@@ -5747,6 +6890,8 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
+ rw@1.3.3: {}
+
safe-array-concat@1.1.4:
dependencies:
call-bind: 1.0.9
@@ -5890,7 +7035,7 @@ snapshots:
stackback@0.0.2: {}
- std-env@3.10.0: {}
+ std-env@4.3.0: {}
stop-iteration-iterator@1.1.0:
dependencies:
@@ -5963,6 +7108,33 @@ snapshots:
optionalDependencies:
'@babel/core': 7.29.7
+ styletron-engine-atomic@1.6.2:
+ dependencies:
+ inline-style-prefixer: 5.1.2
+ styletron-standard: 3.1.0
+
+ styletron-react@6.1.1(react@18.3.1):
+ dependencies:
+ prop-types: 15.8.1
+ react: 18.3.1
+ styletron-standard: 3.1.0
+
+ styletron-react@6.1.1(react@19.3.0):
+ dependencies:
+ prop-types: 15.8.1
+ react: 19.3.0
+ styletron-standard: 3.1.0
+
+ styletron-standard@3.1.0:
+ dependencies:
+ '@rtsao/csstype': 2.6.5-forked.0
+ csstype: 3.2.3
+ inline-style-prefixer: 5.1.2
+
+ supercluster@7.1.5:
+ dependencies:
+ kdbush: 3.0.0
+
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@@ -5977,13 +7149,15 @@ snapshots:
tinybench@2.9.0: {}
- tinyexec@0.3.2: {}
+ tinyexec@1.3.1: {}
tinyglobby@0.2.17:
dependencies:
fdir: 6.5.0(picomatch@4.0.7)
picomatch: 4.0.7
+ tinyqueue@2.0.3: {}
+
tinyrainbow@3.1.1: {}
tldts-core@6.1.86: {}
@@ -6033,6 +7207,8 @@ snapshots:
minimist: 1.2.8
strip-bom: 3.0.0
+ tslib@1.14.1: {}
+
tslib@2.8.1: {}
type-check@0.4.0:
@@ -6132,6 +7308,40 @@ snapshots:
dependencies:
punycode: 2.3.1
+ use-callback-ref@1.3.3(@types/react@19.3.0)(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ use-callback-ref@1.3.3(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ use-sidecar@1.1.3(@types/react@19.3.0)(react@18.3.1):
+ dependencies:
+ detect-node-es: 1.1.0
+ react: 18.3.1
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ use-sidecar@1.1.3(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ detect-node-es: 1.1.0
+ react: 19.3.0
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ viewport-mercator-project@7.0.4:
+ dependencies:
+ '@math.gl/web-mercator': 3.6.3
+
vite@7.3.6(@types/node@22.18.6):
dependencies:
esbuild: 0.28.2
@@ -6144,88 +7354,78 @@ snapshots:
'@types/node': 22.18.6
fsevents: 2.3.3
- vitest@4.0.7(@types/node@22.18.6)(jsdom@26.1.0):
+ vitest@4.1.11(@opentelemetry/api@1.9.0)(@types/node@22.18.6)(jsdom@26.1.0)(vite@7.3.6(@types/node@22.18.6)):
dependencies:
- '@vitest/expect': 4.0.7
- '@vitest/mocker': 4.0.7(vite@7.3.6(@types/node@22.18.6))
- '@vitest/pretty-format': 4.0.7
- '@vitest/runner': 4.0.7
- '@vitest/snapshot': 4.0.7
- '@vitest/spy': 4.0.7
- '@vitest/utils': 4.0.7
- debug: 4.4.3
- es-module-lexer: 1.7.0
+ '@vitest/expect': 4.1.11
+ '@vitest/mocker': 4.1.11(vite@7.3.6(@types/node@22.18.6))
+ '@vitest/pretty-format': 4.1.11
+ '@vitest/runner': 4.1.11
+ '@vitest/snapshot': 4.1.11
+ '@vitest/spy': 4.1.11
+ '@vitest/utils': 4.1.11
+ es-module-lexer: 2.3.2
expect-type: 1.4.0
magic-string: 0.30.21
+ obug: 2.2.1
pathe: 2.0.3
picomatch: 4.0.7
- std-env: 3.10.0
+ std-env: 4.3.0
tinybench: 2.9.0
- tinyexec: 0.3.2
+ tinyexec: 1.3.1
tinyglobby: 0.2.17
tinyrainbow: 3.1.1
vite: 7.3.6(@types/node@22.18.6)
why-is-node-running: 2.3.0
optionalDependencies:
+ '@opentelemetry/api': 1.9.0
'@types/node': 22.18.6
jsdom: 26.1.0
transitivePeerDependencies:
- - jiti
- - less
- - lightningcss
- msw
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - supports-color
- - terser
- - tsx
- - yaml
-
- vitest@4.0.7(@types/node@22.18.6)(jsdom@27.4.0):
- dependencies:
- '@vitest/expect': 4.0.7
- '@vitest/mocker': 4.0.7(vite@7.3.6(@types/node@22.18.6))
- '@vitest/pretty-format': 4.0.7
- '@vitest/runner': 4.0.7
- '@vitest/snapshot': 4.0.7
- '@vitest/spy': 4.0.7
- '@vitest/utils': 4.0.7
- debug: 4.4.3
- es-module-lexer: 1.7.0
+
+ vitest@4.1.11(@opentelemetry/api@1.9.0)(@types/node@22.18.6)(jsdom@27.4.0)(vite@7.3.6(@types/node@22.18.6)):
+ dependencies:
+ '@vitest/expect': 4.1.11
+ '@vitest/mocker': 4.1.11(vite@7.3.6(@types/node@22.18.6))
+ '@vitest/pretty-format': 4.1.11
+ '@vitest/runner': 4.1.11
+ '@vitest/snapshot': 4.1.11
+ '@vitest/spy': 4.1.11
+ '@vitest/utils': 4.1.11
+ es-module-lexer: 2.3.2
expect-type: 1.4.0
magic-string: 0.30.21
+ obug: 2.2.1
pathe: 2.0.3
picomatch: 4.0.7
- std-env: 3.10.0
+ std-env: 4.3.0
tinybench: 2.9.0
- tinyexec: 0.3.2
+ tinyexec: 1.3.1
tinyglobby: 0.2.17
tinyrainbow: 3.1.1
vite: 7.3.6(@types/node@22.18.6)
why-is-node-running: 2.3.0
optionalDependencies:
+ '@opentelemetry/api': 1.9.0
'@types/node': 22.18.6
jsdom: 27.4.0
transitivePeerDependencies:
- - jiti
- - less
- - lightningcss
- msw
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - supports-color
- - terser
- - tsx
- - yaml
+
+ vt-pbf@3.1.3:
+ dependencies:
+ '@mapbox/point-geometry': 0.1.0
+ '@mapbox/vector-tile': 1.3.1
+ pbf: 3.3.0
w3c-xmlserializer@5.0.0:
dependencies:
xml-name-validator: 5.0.0
+ warning@4.0.3:
+ dependencies:
+ loose-envify: 1.4.0
+
webidl-conversions@7.0.0: {}
webidl-conversions@8.0.1:
diff --git a/web/service/shared/BUILD.bazel b/web/service/shared/BUILD.bazel
index d9633e73b..db9da9244 100644
--- a/web/service/shared/BUILD.bazel
+++ b/web/service/shared/BUILD.bazel
@@ -20,9 +20,12 @@ web_library(
":node_modules/@submitqueue/web-platform",
":node_modules/@types/node",
":node_modules/@types/react",
+ ":node_modules/baseui",
":node_modules/next",
":node_modules/pino",
":node_modules/react",
":node_modules/server-only",
+ ":node_modules/styletron-engine-atomic",
+ ":node_modules/styletron-react",
],
)
diff --git a/web/service/shared/package.json b/web/service/shared/package.json
index 4065709a1..4ed45c79d 100644
--- a/web/service/shared/package.json
+++ b/web/service/shared/package.json
@@ -10,6 +10,9 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
+ "baseui": "18.2.0",
+ "styletron-engine-atomic": "1.6.2",
+ "styletron-react": "6.1.1",
"@connectrpc/connect": "^2.1.1",
"@connectrpc/connect-node": "^2.1.1",
"next": ">=16.3.0 <17",
@@ -28,12 +31,16 @@
"eslint": "^9.36.0",
"eslint-config-next": ">=16.3.0 <17",
"typescript": "5.9.3",
- "vitest": "4.0.7"
+ "vitest": "4.1.11"
},
"files": [
"dist"
],
"exports": {
+ "./theme": {
+ "types": "./dist/theme.d.ts",
+ "import": "./dist/theme.js"
+ },
"./navigation": {
"types": "./dist/navigation.d.ts",
"import": "./dist/navigation.js"
diff --git a/web/service/shared/theme.tsx b/web/service/shared/theme.tsx
new file mode 100644
index 000000000..5d0c93523
--- /dev/null
+++ b/web/service/shared/theme.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import { BaseProvider, LightTheme } from "baseui";
+import { useServerInsertedHTML } from "next/navigation";
+import { useState, type ReactNode } from "react";
+import { Client, Server } from "styletron-engine-atomic";
+import { Provider } from "styletron-react";
+
+export function ThemeProvider({ children }: { children: ReactNode }) {
+ const [engine] = useState(() => typeof window === "undefined"
+ ? new Server()
+ : new Client({ hydrate: document.querySelectorAll("style.sq-styletron") }));
+ const [emitted] = useState(() => new Map());
+ useServerInsertedHTML(() => {
+ if (!(engine instanceof Server)) return null;
+ return <>{engine.getStylesheets().map(({ css, attrs }) => {
+ const key = `${attrs["data-hydrate"] ?? "atomic"}:${attrs.media ?? ""}`;
+ const offset = emitted.get(key) ?? 0;
+ emitted.set(key, css.length);
+ // Streaming renders append rules; emit only the new suffix at each flush.
+ return css.length === offset ? null : ;
+ })}>;
+ });
+ return {children} ;
+}
diff --git a/web/service/stovepipe/BUILD.bazel b/web/service/stovepipe/BUILD.bazel
index f77d2b852..4ec6ea06a 100644
--- a/web/service/stovepipe/BUILD.bazel
+++ b/web/service/stovepipe/BUILD.bazel
@@ -86,18 +86,21 @@ vitest.vitest_test(
"vitest.config.ts",
":node_modules",
":node_modules/@submitqueue/web-service-shared",
- ":node_modules/vitest",
":node_modules/@submitqueue/web-stovepipe",
- "//web/stovepipe:lib",
+ ":node_modules/vitest",
"//web:node_modules/@connectrpc/connect",
"//web:node_modules/@connectrpc/connect-node",
"//web:node_modules/@opentelemetry/api",
+ "//web:node_modules/baseui",
"//web:node_modules/next",
"//web:node_modules/pino",
"//web:node_modules/react",
"//web:node_modules/react-dom",
+ "//web:node_modules/styletron-engine-atomic",
+ "//web:node_modules/styletron-react",
"//web/platform:lib",
"//web/service/shared:lib",
+ "//web/stovepipe:lib",
] + glob([
"src/**/*.ts",
"src/**/*.tsx",
@@ -162,10 +165,13 @@ nextjs_standalone_build(
"//web:node_modules/@connectrpc/connect",
"//web:node_modules/@connectrpc/connect-node",
"//web:node_modules/@opentelemetry/api",
+ "//web:node_modules/baseui",
"//web:node_modules/next",
"//web:node_modules/pino",
"//web:node_modules/react",
"//web:node_modules/react-dom",
+ "//web:node_modules/styletron-engine-atomic",
+ "//web:node_modules/styletron-react",
"//web/platform:lib",
"//web/platform:lib_types",
"//web/platform:pkg",
diff --git a/web/service/stovepipe/src/app/layout.tsx b/web/service/stovepipe/src/app/layout.tsx
index 60c6884ca..9b8039395 100644
--- a/web/service/stovepipe/src/app/layout.tsx
+++ b/web/service/stovepipe/src/app/layout.tsx
@@ -1,4 +1,5 @@
import type { ReactNode } from "react";
+import { ThemeProvider } from "@submitqueue/web-service-shared/theme";
import "@submitqueue/web-stovepipe/styles.css";
export const metadata = {
title: "Stovepipe",
@@ -7,7 +8,7 @@ export const metadata = {
export default function Layout({ children }: { children: ReactNode }) {
return (
- {children}
+ {children}
);
}
diff --git a/web/service/submitqueue/BUILD.bazel b/web/service/submitqueue/BUILD.bazel
index 5e6494b31..5e5a9dcd2 100644
--- a/web/service/submitqueue/BUILD.bazel
+++ b/web/service/submitqueue/BUILD.bazel
@@ -22,8 +22,8 @@ ts_project(
"src/**/*.ts",
"src/**/*.tsx",
]) + [
- "next-env.d.ts",
"next.config.ts",
+ "next-env.d.ts",
"vitest.config.ts",
],
declaration = False,
@@ -38,13 +38,13 @@ ts_project(
":node_modules/@opentelemetry/exporter-prometheus",
":node_modules/@opentelemetry/sdk-metrics",
":node_modules/@submitqueue/api",
- ":node_modules/@submitqueue/web-submitqueue",
":node_modules/@submitqueue/web-service-shared",
+ ":node_modules/@submitqueue/web-submitqueue",
":node_modules/@types/node",
- ":node_modules/pino",
":node_modules/@types/react",
":node_modules/@types/react-dom",
":node_modules/next",
+ ":node_modules/pino",
":node_modules/react",
":node_modules/react-dom",
":node_modules/server-only",
@@ -57,19 +57,19 @@ eslint.eslint_test(
args = ["."],
chdir = package_name(),
data = [
- ":node_modules",
- ":node_modules/eslint",
- ":node_modules/eslint-config-next",
- "//web:node_modules/next",
"eslint.config.mjs",
- "next-env.d.ts",
"next.config.ts",
+ "next-env.d.ts",
"package.json",
"tsconfig.json",
"vitest.config.ts",
+ ":node_modules",
":node_modules/@submitqueue/web-service-shared",
- "//web/service/shared:lib",
+ ":node_modules/eslint",
+ ":node_modules/eslint-config-next",
+ "//web:node_modules/next",
"//web/platform:lib",
+ "//web/service/shared:lib",
] + glob([
"src/**/*.ts",
"src/**/*.tsx",
@@ -85,21 +85,24 @@ vitest.vitest_test(
],
chdir = package_name(),
data = [
+ "vitest.config.ts",
":node_modules",
- ":node_modules/vitest",
+ ":node_modules/@submitqueue/web-service-shared",
":node_modules/@submitqueue/web-submitqueue",
- "//web/submitqueue:lib",
+ ":node_modules/vitest",
"//web:node_modules/@connectrpc/connect",
"//web:node_modules/@connectrpc/connect-node",
"//web:node_modules/@opentelemetry/api",
+ "//web:node_modules/baseui",
"//web:node_modules/next",
"//web:node_modules/pino",
"//web:node_modules/react",
"//web:node_modules/react-dom",
- "vitest.config.ts",
- ":node_modules/@submitqueue/web-service-shared",
- "//web/service/shared:lib",
+ "//web:node_modules/styletron-engine-atomic",
+ "//web:node_modules/styletron-react",
"//web/platform:lib",
+ "//web/service/shared:lib",
+ "//web/submitqueue:lib",
] + glob([
"src/**/*.ts",
"src/**/*.tsx",
@@ -112,9 +115,14 @@ next.next_binary(
nextjs_standalone_build(
name = "standalone",
+ srcs = ["next-env.d.ts"] + glob([
+ "src/**",
+ ]),
args = ["--webpack"],
config = "next.config.ts",
data = [
+ "package.json",
+ "tsconfig.json",
":node_modules",
":node_modules/@bufbuild/protobuf",
":node_modules/@connectrpc/connect",
@@ -123,8 +131,8 @@ nextjs_standalone_build(
":node_modules/@opentelemetry/exporter-prometheus",
":node_modules/@opentelemetry/sdk-metrics",
":node_modules/@submitqueue/api",
- ":node_modules/@submitqueue/web-submitqueue",
":node_modules/@submitqueue/web-service-shared",
+ ":node_modules/@submitqueue/web-submitqueue",
":node_modules/next",
":node_modules/react",
":node_modules/react-dom",
@@ -132,25 +140,23 @@ nextjs_standalone_build(
"//web:node_modules/@connectrpc/connect",
"//web:node_modules/@connectrpc/connect-node",
"//web:node_modules/@opentelemetry/api",
+ "//web:node_modules/baseui",
"//web:node_modules/next",
"//web:node_modules/pino",
"//web:node_modules/react",
"//web:node_modules/react-dom",
- "//web/submitqueue:lib",
- "//web/submitqueue:lib_types",
+ "//web:node_modules/styletron-engine-atomic",
+ "//web:node_modules/styletron-react",
"//web/platform:lib",
"//web/platform:lib_types",
"//web/platform:pkg",
"//web/service/shared:lib",
"//web/service/shared:lib_types",
- "package.json",
- "tsconfig.json",
+ "//web/submitqueue:lib",
+ "//web/submitqueue:lib_types",
],
env = {"NEXT_TELEMETRY_DISABLED": "1"},
next_js_binary = ":next",
- srcs = ["next-env.d.ts"] + glob([
- "src/**",
- ]),
)
nextjs_standalone_server(
diff --git a/web/service/submitqueue/src/app/layout.tsx b/web/service/submitqueue/src/app/layout.tsx
index 2692ede64..461122a7c 100644
--- a/web/service/submitqueue/src/app/layout.tsx
+++ b/web/service/submitqueue/src/app/layout.tsx
@@ -1,5 +1,6 @@
import type { Metadata } from "next";
import type { ReactNode } from "react";
+import { ThemeProvider } from "@submitqueue/web-service-shared/theme";
import "@submitqueue/web-submitqueue/styles.css";
@@ -14,7 +15,7 @@ export const metadata: Metadata = {
export default function RootLayout({ children }: { children: ReactNode }) {
return (
- {children}
+ {children}
);
}
diff --git a/web/stovepipe/BUILD.bazel b/web/stovepipe/BUILD.bazel
index 05bd54fdd..e1ce561cd 100644
--- a/web/stovepipe/BUILD.bazel
+++ b/web/stovepipe/BUILD.bazel
@@ -20,13 +20,18 @@ web_library(
":node_modules/@types/react-dom",
":node_modules/jsdom",
":node_modules/react-dom",
+ ":node_modules/styletron-engine-atomic",
+ ":node_modules/styletron-react",
":node_modules/vitest",
+ "//web/platform:test_support",
],
vitest = vitest,
deps = [
":node_modules/@submitqueue/web-platform",
":node_modules/@types/node",
":node_modules/@types/react",
+ ":node_modules/baseui",
":node_modules/react",
+ "//web:node_modules/@types/react",
],
)
diff --git a/web/stovepipe/README.md b/web/stovepipe/README.md
index cbe74e110..1fcf96ecb 100644
--- a/web/stovepipe/README.md
+++ b/web/stovepipe/README.md
@@ -8,7 +8,7 @@ Logging uses a synchronous `onLog` callback passed on each `handle` request. Bin
Instrumentation belongs in the host: wrap `handle` to observe page results and instrument the concrete service client for RPC traces. A `render` result can contain a failed section, so check `requests.ok`, or both `history.ok` and `projectStatus.ok`, before reporting success. The reference host uses native OpenTelemetry spans, a page-load counter and a duration metric; other hosts can use their own telemetry without an adapter. The reusable module has no telemetry dependency or instrumentation API.
-Use the server entry's `createStovepipeWeb` to load a page and render its model with `StovepipeApp`. Mount beneath `WebNavigationProvider` when the host supplies client navigation and refresh. Without it, links and refresh use ordinary document navigation. Import `@submitqueue/web-stovepipe/styles.css`, which includes the common native styles from `@submitqueue/web-platform`.
+Use the server entry's `createStovepipeWeb` to load a page and render its model with `StovepipeApp`. Mount beneath `WebNavigationProvider` when the host supplies client navigation and refresh. Without it, links and refresh use ordinary document navigation. Import `@submitqueue/web-stovepipe/styles.css` for long-identifier wrapping, and supply BaseUI's `BaseProvider` and Styletron's `Provider`. The host owns the theme and styling engine, including SSR stylesheet extraction and hydration; the library creates neither. BaseUI, React, React DOM, and Styletron React are peer dependencies.
## Routes and data
diff --git a/web/stovepipe/package.json b/web/stovepipe/package.json
index bec8d3d5d..e98bfcf1c 100644
--- a/web/stovepipe/package.json
+++ b/web/stovepipe/package.json
@@ -34,9 +34,15 @@
"typecheck": "tsc --noEmit"
},
"peerDependencies": {
+ "baseui": ">=16 <19",
+ "react-dom": ">=18 <20",
+ "styletron-react": ">=6",
"react": ">=18 <20"
},
"devDependencies": {
+ "baseui": "18.2.0",
+ "styletron-engine-atomic": "1.6.2",
+ "styletron-react": "6.1.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@types/node": "22.18.6",
diff --git a/web/stovepipe/view/app.test.tsx b/web/stovepipe/view/app.test.tsx
index d13f616ac..2ba81ff23 100644
--- a/web/stovepipe/view/app.test.tsx
+++ b/web/stovepipe/view/app.test.tsx
@@ -1,4 +1,4 @@
-import { cleanup, render, screen, within } from "@testing-library/react";
+import { cleanup, render, screen, waitFor, within } from "../../platform/test/rtl.js";
import { afterEach, expect, it } from "vitest";
import { StovepipeApp } from "./app.js";
import type { StovepipePageModel } from "../entity/index.js";
@@ -89,7 +89,7 @@ it("links queue entries by request ID even when the change URI is missing", () =
);
expect(screen.getByText("Unknown URI")).toBeVisible();
});
-it("retains the summary and history after a failed refresh", () => {
+it("retains the summary and history after a failed refresh", async () => {
const { rerender } = render( );
rerender(
{
expect(screen.getByText("git://repo/sha")).toBeVisible();
expect(screen.getByText("all_targets_passed")).toBeVisible();
expect(screen.getByText("accepted")).toBeVisible();
- expect(screen.getAllByText("Showing the last successful result.")).toHaveLength(2);
+ await waitFor(() => expect(screen.getAllByText("Showing the last successful result.")).toHaveLength(2));
expect(screen.getByText("green-project")).toBeVisible();
});
it("discards previous results when the request changes", () => {
@@ -124,7 +124,7 @@ it("discards previous results when the request changes", () => {
it("renders recorded project results, completion and shareable pagination", () => {
render( );
const projects = screen.getByRole("region", { name: "Project results" });
- const table = within(projects).getByRole("table", { name: "Project results" });
+ const table = within(projects).getByRole("table", { name: "Recorded project results" });
expect(within(table).getByRole("rowheader", { name: "Repository" })).toBeVisible();
expect(within(projects).getByText("Green (0%)")).toBeVisible();
expect(within(projects).getByText("Breakage (25%)")).toBeVisible();
@@ -160,7 +160,7 @@ it("shows complete empty results without inventing green or a continuation", ()
expect(screen.getByText("Project result recording is complete.")).toBeVisible();
expect(screen.getByText("No project results recorded on this page.")).toBeVisible();
expect(screen.queryByRole("link", { name: /Next projects/ })).toBeNull();
- const table = screen.getByRole("table", { name: "Project results" });
+ const table = screen.getByRole("table", { name: "Recorded project results" });
expect(within(table).getByRole("rowheader", { name: "Repository" })).toBeVisible();
expect(within(table).getByText("No result recorded")).toBeVisible();
});
diff --git a/web/stovepipe/view/app.tsx b/web/stovepipe/view/app.tsx
index 738c29c03..ca57a6a69 100644
--- a/web/stovepipe/view/app.tsx
+++ b/web/stovepipe/view/app.tsx
@@ -1,6 +1,9 @@
"use client";
import { Timestamp } from "@submitqueue/web-platform";
+import { Block } from "baseui/block/index.js";
+import { Tag } from "baseui/tag/index.js";
+import { HeadingLarge, HeadingSmall, LabelMedium, ParagraphSmall } from "baseui/typography/index.js";
import { RefreshControls } from "./refresh.js";
import type { StovepipePageModel } from "../entity/index.js";
import { Link, Section } from "./components.js";
@@ -9,14 +12,16 @@ import { ProjectResults } from "./projects.js";
function Page({ model }: { model: StovepipePageModel }) {
return (
-
-
-
-
+
+
+
+ SP Stovepipe
+
+
+
+
{model.queues.map((queue) => (
))}
-
-
+
+
{model.kind === "request" && (
-
+
← Queue requests
-
+
)}
-
+
{model.kind === "queue"
? model.queue
: `Request ${model.requestId}`}
-
-
+
+
{model.kind === "queue"
? "Requests ordered by acceptance time, newest first."
: model.queue}
-
+
-
+
{model.kind === "queue" && model.showLatestLink && (
-
+
Latest page
-
+
)}
{model.kind === "queue" ? (
) : (
-
+
{({ request, events }) => (
<>
- Request status
+ Request status
>
)}
- Project results
+ Project results
-
+
)}
-
-
-
+
+
);
}
export function StovepipeApp({ model }: { model: StovepipePageModel }) {
diff --git a/web/stovepipe/view/components.tsx b/web/stovepipe/view/components.tsx
index 723dda379..c90b5456d 100644
--- a/web/stovepipe/view/components.tsx
+++ b/web/stovepipe/view/components.tsx
@@ -3,34 +3,15 @@
import { useState, type ReactNode } from "react";
import { useWebNavigation, type WebLinkProps } from "@submitqueue/web-platform";
import type { ReadResult } from "../entity/index.js";
+import { Notification, KIND } from "baseui/notification/index.js";
+import { StyledLink } from "baseui/link/index.js";
+import { ParagraphSmall } from "baseui/typography/index.js";
-export function Link(props: WebLinkProps) {
+export { Table } from "@submitqueue/web-platform";
+
+export function Link({ className = "", ...props }: WebLinkProps) {
const { Link: HostLink } = useWebNavigation();
- return HostLink ? : ;
-}
-export function Table({
- label,
- headers,
- children,
-}: {
- label: string;
- headers: string[];
- children: ReactNode;
-}) {
- return (
-
-
-
-
- {headers.map((header) => (
- {header}
- ))}
-
-
- {children}
-
-
- );
+ return ;
}
export function Section({
result,
@@ -47,10 +28,10 @@ export function Section({
return (
<>
{!result.ok && (
-
+
{result.error}
- {previous !== null && Showing the last successful result.
}
-
+ {previous !== null && Showing the last successful result. }
+
)}
{data !== null ? children(data) : null}
>
diff --git a/web/stovepipe/view/pages.tsx b/web/stovepipe/view/pages.tsx
index 9d3012dc3..7fa5d0486 100644
--- a/web/stovepipe/view/pages.tsx
+++ b/web/stovepipe/view/pages.tsx
@@ -1,6 +1,10 @@
"use client";
import { Timestamp } from "@submitqueue/web-platform";
+import { Block } from "baseui/block/index.js";
+import { StyledTableBodyCell, StyledTableBodyRow } from "baseui/table-semantic/index.js";
+import { Tag } from "baseui/tag/index.js";
+import { LabelXSmall, ParagraphSmall } from "baseui/typography/index.js";
import type {
RequestSummaryModel,
HistoryEventModel,
@@ -22,7 +26,7 @@ export function RequestList({
nextHref: string | null;
}) {
if (!requests.length)
- return No retained requests on this queue.
;
+ return No retained requests on this queue. ;
return (
<>
{requests.map((request) => (
-
-
+
+
{request.id}
-
-
- {request.changeUri || "Unknown URI"}
-
-
-
+
+
+ {request.changeUri || "Unknown URI"}
+
+
+
{request.state || "Unknown"}
-
-
-
+
+
+
-
-
+
+
-
- {request.outcomeReason || "—"}
-
+
+ {request.outcomeReason || "—"}
+
))}
{nextHref && (
-
+
Older requests →
-
+
)}
>
);
@@ -70,42 +74,42 @@ export function RequestList({
export function RequestDetails({ request }: { request: RequestSummaryModel }) {
return (
<>
-
+
-
State
-
-
+ State
+
+
{request.state || "Unknown"}
-
-
+
+
-
Change URI
-
- {request.changeUri || "Unknown URI"}
-
+
Change URI
+
+ {request.changeUri || "Unknown URI"}
+
-
Base URI
-
- {request.baseUri || "No baseline selected"}
-
+
Base URI
+
+ {request.baseUri || "No baseline selected"}
+
-
Accepted
-
+ Accepted
+
-
+
-
Updated
-
+ Updated
+
-
+
-
Outcome
-
{request.outcomeReason || "—"}
+
Outcome
+
{request.outcomeReason || "—"}
>
@@ -118,23 +122,23 @@ export function History({ events }: { events: HistoryEventModel[] }) {
headers={["Time", "Type", "State or event", "Outcome"]}
>
{events.map((event) => (
-
-
+
+
-
-
+
+
{event.kind === "requestState"
? "State"
: event.kind === "event"
? "Event"
: "Unknown"}
-
- {event.label}
- {event.outcomeReason || "—"}
-
+
+ {event.label}
+ {event.outcomeReason || "—"}
+
))}
) : (
- No retained history yet.
+ No retained history yet.
);
}
diff --git a/web/stovepipe/view/projects.tsx b/web/stovepipe/view/projects.tsx
index 2277a6e01..639c9e96f 100644
--- a/web/stovepipe/view/projects.tsx
+++ b/web/stovepipe/view/projects.tsx
@@ -1,53 +1,57 @@
"use client";
import { Timestamp } from "@submitqueue/web-platform";
+import { Block } from "baseui/block/index.js";
+import { StyledTableBodyCell, StyledTableBodyRow } from "baseui/table-semantic/index.js";
+import { Tag } from "baseui/tag/index.js";
+import { ParagraphSmall } from "baseui/typography/index.js";
import type { ProjectStatusModel } from "../entity/index.js";
import { Link, Table } from "./components.js";
function Result({ degree }: { degree: number | null }) {
return (
-
{degree === null ? "No result recorded" : (
<>{degree === 0 ? "Green" : "Breakage"} ({
(degree * 100).toLocaleString("en-US", { maximumSignificantDigits: 6 })
}%)>
)}
-
+
);
}
export function ProjectResults({ model }: { model: ProjectStatusModel }) {
return (
<>
-
+
Breakage ranges from 0% (green) to 100%; missing results are not green.
-
-
-
- Repository
-
-
+
+
+
+ Repository
+
+
{model.projects.map((entry) => (
-
- {entry.project}
-
-
+
+ {entry.project}
+
+
))}
- {!model.projects.length && No project results recorded on this page.
}
- {model.complete
+ {!model.projects.length && No project results recorded on this page. }
+ {model.complete
? "Project result recording is complete."
- : "Project result recording is still in progress; more results may arrive."}
+ : "Project result recording is still in progress; more results may arrive."}
{(model.firstHref || model.nextHref) && (
-
+
{model.firstHref && First projects}
{model.nextHref && Next projects →}
-
+
)}
- Results updated: {model.updatedAtMs === "0"
- ? "Unknown" : }
+ Results updated: {model.updatedAtMs === "0"
+ ? "Unknown" : }
>
);
}
diff --git a/web/stovepipe/view/refresh.test.tsx b/web/stovepipe/view/refresh.test.tsx
index cc13f75ba..f053c4fa2 100644
--- a/web/stovepipe/view/refresh.test.tsx
+++ b/web/stovepipe/view/refresh.test.tsx
@@ -4,7 +4,7 @@ import {
fireEvent,
render,
screen,
-} from "@testing-library/react";
+} from "../../platform/test/rtl.js";
import { afterEach, beforeEach, expect, it, vi } from "vitest";
import { WebNavigationProvider } from "@submitqueue/web-platform";
import { RefreshControls } from "./refresh.js";
diff --git a/web/stovepipe/view/refresh.tsx b/web/stovepipe/view/refresh.tsx
index ca4a3d78d..a23ac0ccc 100644
--- a/web/stovepipe/view/refresh.tsx
+++ b/web/stovepipe/view/refresh.tsx
@@ -2,6 +2,8 @@
import { useCallback, useState } from "react";
import { AutoRefresh, useWebNavigation } from "@submitqueue/web-platform";
+import { Checkbox } from "baseui/checkbox/index.js";
+import { ParagraphXSmall } from "baseui/typography/index.js";
export function RefreshControls() {
const navigation = useWebNavigation();
@@ -30,16 +32,14 @@ export function RefreshControls() {
maxBackoffMs={10_000}
/>
{navigation.refresh && (
-
- setAutomatic(event.currentTarget.checked)}
- />{" "}
+ setAutomatic(event.currentTarget.checked)}
+ >
Auto refresh every 10s
-
+
)}
- {error && {error}
}
+ {error && {error} }
);
}
diff --git a/web/stovepipe/view/styles.css b/web/stovepipe/view/styles.css
index adda74711..063d466f6 100644
--- a/web/stovepipe/view/styles.css
+++ b/web/stovepipe/view/styles.css
@@ -1,14 +1 @@
@import "@submitqueue/web-platform/styles.css";
-
-.sq-app .sq-project-name { overflow-wrap: anywhere; }
-
-/* Stovepipe pages. */
-.sq-app .sq-stacked-sections {
- display: grid;
- gap: 38px;
-}
-@media (max-width: 680px) {
- .sq-app .sq-stacked-sections {
- gap: 20px;
- }
-}
diff --git a/web/stovepipe/vitest.config.ts b/web/stovepipe/vitest.config.ts
index 21c8ec048..177f92ec7 100644
--- a/web/stovepipe/vitest.config.ts
+++ b/web/stovepipe/vitest.config.ts
@@ -5,6 +5,7 @@ export default defineConfig({
jsx: "automatic",
},
test: {
+ maxWorkers: 2,
environment: "jsdom",
globals: true,
setupFiles: ["./test-setup.ts"],
diff --git a/web/submitqueue/BUILD.bazel b/web/submitqueue/BUILD.bazel
index 78761503f..2ea19936a 100644
--- a/web/submitqueue/BUILD.bazel
+++ b/web/submitqueue/BUILD.bazel
@@ -21,13 +21,18 @@ web_library(
":node_modules/@types/react-dom",
":node_modules/jsdom",
":node_modules/react-dom",
+ ":node_modules/styletron-engine-atomic",
+ ":node_modules/styletron-react",
":node_modules/vitest",
+ "//web/platform:test_support",
],
vitest = vitest,
deps = [
":node_modules/@submitqueue/web-platform",
":node_modules/@types/node",
":node_modules/@types/react",
+ ":node_modules/baseui",
":node_modules/react",
+ "//web:node_modules/@types/react",
],
)
diff --git a/web/submitqueue/README.md b/web/submitqueue/README.md
index 230f7bf1e..eb825f70f 100644
--- a/web/submitqueue/README.md
+++ b/web/submitqueue/README.md
@@ -14,7 +14,7 @@ The complete read-only SubmitQueue UI as a mountable module. Folders follow the
Entry points: the root is client-safe (`SubmitQueueApp`, page frames, `WebNavigationProvider`, model types); `./server` has `createSubmitQueueWeb`, the gateway and cursor contracts, and `WebPaths`; `./extension/cursor/hmac` signs cursors; `./extension/gateway/mock` has test fakes; `./styles.css` is the full stylesheet. Controllers and helpers stay internal.
-**Hosting it.** Give `createSubmitQueueWeb` a gateway client (any client matching the structural contract, so the module ships no generated code), a `CursorCodec`, and optionally a mount path, authorization check, error classifier, or cached queue catalog. Route every page path to `handle`, render `SubmitQueueApp` with each page model, and wrap it in a `WebNavigationProvider` for client-side navigation. Hosts must load `./styles.css`, either by importing it or by serving it and linking to it; theme with the `--sq-*` properties.
+**Hosting it.** Give `createSubmitQueueWeb` a gateway client (any client matching the structural contract, so the module ships no generated code), a `CursorCodec`, and optionally a mount path, authorization check, error classifier, or cached queue catalog. Route every page path to `handle`, render `SubmitQueueApp` with each page model, and wrap it in a `WebNavigationProvider` for client-side navigation. Load `./styles.css` for long-identifier wrapping and supply BaseUI's `BaseProvider` and Styletron's `Provider`. The host owns the theme and styling engine, including SSR stylesheet extraction and hydration; BaseUI, React, React DOM, and Styletron React are peers. `WebShell` follows the provider's theme rather than taking a separate theme prop.
Pass `onLog` on each `handle` request to deliver severity, message, and structured metadata to the host's request-scoped logger. Errors retain their original value under `error`, and logs include the correlation `requestId` and page `path`. The callback must be synchronous; omitting it is silent, and callback exceptions do not change page results. The module has no logging-library dependency.
diff --git a/web/submitqueue/package.json b/web/submitqueue/package.json
index d4e6e24ed..9cace1e3f 100644
--- a/web/submitqueue/package.json
+++ b/web/submitqueue/package.json
@@ -44,9 +44,15 @@
"typecheck": "tsc --noEmit"
},
"peerDependencies": {
+ "baseui": ">=16 <19",
+ "react-dom": ">=18 <20",
+ "styletron-react": ">=6",
"react": ">=18 <20"
},
"devDependencies": {
+ "baseui": "18.2.0",
+ "styletron-engine-atomic": "1.6.2",
+ "styletron-react": "6.1.1",
"@connectrpc/connect": "^2.1.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
@@ -57,7 +63,7 @@
"react": "^19.1.0",
"react-dom": "^19.1.0",
"typescript": "^5.8.3",
- "vitest": "4.0.7"
+ "vitest": "4.1.11"
},
"dependencies": {
"@submitqueue/web-platform": "0.0.0"
diff --git a/web/submitqueue/view/components.test.tsx b/web/submitqueue/view/components.test.tsx
index f709719f2..ac076cea9 100644
--- a/web/submitqueue/view/components.test.tsx
+++ b/web/submitqueue/view/components.test.tsx
@@ -1,4 +1,4 @@
-import { fireEvent, render, screen, within } from "@testing-library/react";
+import { act, fireEvent, render, screen, within } from "../../platform/test/rtl.js";
import { describe, expect, it, vi } from "vitest";
import { WebNavigationProvider } from "@submitqueue/web-platform";
import { WebApp } from "./web-app.js";
@@ -30,7 +30,7 @@ describe("request components", () => {
expect(link.getAttribute("href")).toBe(
"/demo-queue/request/demo-queue/1",
);
- expect(screen.getByText("Speculating").getAttribute("data-tone")).toBe("progress");
+ expect(screen.getByText("Speculating").closest("[data-tone]")?.getAttribute("data-tone")).toBe("progress");
expect(screen.getByText("Nov 14, 2023, 10:13:20 PM UTC")).toBeTruthy();
expect(screen.getByRole("link", { name: "Next page" }).getAttribute("href")).toBe(
"/demo-queue?page=opaque-token",
@@ -83,7 +83,8 @@ describe("request components", () => {
expect(within(history).getByText("Building")).toBeTruthy();
fireEvent.click(within(history).getByText("Building"));
expect(within(history).getByText("https://build.example/1")).toBeTruthy();
- fireEvent.change(screen.getByRole("combobox"), { target: { value: "event" } });
+ fireEvent.click(screen.getByRole("combobox"));
+ fireEvent.click(screen.getByRole("option", { name: "Occurrence events" }));
expect(within(history).getAllByRole("listitem")).toHaveLength(1);
});
@@ -140,7 +141,7 @@ describe("request components", () => {
}} />);
expect(screen.getByText("History unavailable")).toBeTruthy();
expect(screen.queryByText("No history has been retained for this request.")).toBeNull();
- fireEvent.click(screen.getByRole("button", { name: "Copy ID" }));
+ await act(async () => fireEvent.click(screen.getByRole("button", { name: "Copy ID" })));
await vi.waitFor(() => expect(writeText).toHaveBeenCalledWith(request.sqid));
});
@@ -171,7 +172,8 @@ describe("request components", () => {
render(
} />
);
- fireEvent.change(screen.getByRole("combobox"), { target: { value: `/logical/${version}` } });
+ fireEvent.click(screen.getByRole("combobox"));
+ fireEvent.click(screen.getByRole("option", { name: version }));
expect(push).toHaveBeenCalledWith(`/logical/${version}`);
expect(screen.getByRole("link", { name: version }).getAttribute("href")).toBe(`/logical/${version}`);
});
@@ -199,6 +201,6 @@ describe("request components", () => {
it("shows unknown statuses safely", () => {
render( );
- expect(screen.getByText("New Pipeline Step").getAttribute("data-tone")).toBe("neutral");
+ expect(screen.getByText("New Pipeline Step").closest("[data-tone]")?.getAttribute("data-tone")).toBe("neutral");
});
});
diff --git a/web/submitqueue/view/components.tsx b/web/submitqueue/view/components.tsx
index 9ea9f99ff..c758f7976 100644
--- a/web/submitqueue/view/components.tsx
+++ b/web/submitqueue/view/components.tsx
@@ -2,7 +2,15 @@
import { ErrorState } from "./error-state.js";
import { useLastSuccessfulData } from "./last-successful-data.js";
-import { Timestamp } from "@submitqueue/web-platform";
+import { Table, Timestamp } from "@submitqueue/web-platform";
+import { Block } from "baseui/block/index.js";
+import { Button, SIZE } from "baseui/button/index.js";
+import { Input } from "baseui/input/index.js";
+import { KIND, Notification } from "baseui/notification/index.js";
+import { Select } from "baseui/select/index.js";
+import { Tag } from "baseui/tag/index.js";
+import { StyledTableBodyCell, StyledTableBodyRow } from "baseui/table-semantic/index.js";
+import { HeadingLarge, HeadingSmall, LabelXSmall, ParagraphSmall, ParagraphXSmall } from "baseui/typography/index.js";
import { useWebApp, WebLink } from "./web-app.js";
import { useState, type ReactNode } from "react";
import type {
@@ -12,31 +20,32 @@ import { WebPaths } from "../core/paths.js";
import { statusDisplay } from "../core/status.js";
function Metadata({ values }: { values: Record }) {
- return {Object.entries(values).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) =>
-
{key} {value}
+ return {Object.entries(values).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) =>
+
)} ;
}
export function RequestStatus({ status }: { status: string }) {
const display = statusDisplay(status);
- return {display.label} ;
+ const kind = ({ neutral: "neutral", success: "positive", danger: "negative", warning: "warning", progress: "accent" } as const)[display.tone];
+ return {display.label} ;
}
function RequestChanges({ request, links = {}, labels = {} }: {
request: RequestSummaryModel; links?: Record; labels?: Record;
}) {
- return {request.changeUris.map(uri =>
- {links[uri] ? {labels[uri] ?? uri} : {labels[uri] ?? uri}}
- )} ;
+ return {request.changeUris.map(uri =>
+ {links[uri] ? {labels[uri] ?? uri} : {labels[uri] ?? uri} }
+ )} ;
}
export function QueueDirectory({ queues, basePath }: { queues: readonly QueueModel[]; basePath?: string }) {
const paths = new WebPaths(basePath === undefined ? {} : { basePath });
return
- Queues Available submit queues
- {queues.length === 0 ? No queues are configured.
:
+ Queues Available submit queues
+ {queues.length === 0 ? No queues are configured. :
{queues.map(queue =>
- {queue.name} {queue.description ? {queue.description}
: null}
+ {queue.name} {queue.description ? {queue.description} : null}
)} }
;
}
@@ -57,24 +66,23 @@ export function RequestList({ model, basePath, empty, changeLinks, changeLabels
.some(value => value.toLowerCase().includes(search.toLowerCase()))
);
return
-
- Find in displayed requests setSearch(event.target.value)} />
- Displayed page · UTC
-
- {model.requests.length === 0 ? {empty ?? "No requests were received in this window."}
:
- requests.length === 0 ? No displayed requests match.
:
-
- Request ID Status Changes Received · UTC
- {requests.map(request =>
- {request.sqid}
- {request.lastError ? {request.lastError}
: null}
-
-
- )}
-
}
- {requests.length} displayed requests · newest received first
+
+ Find in displayed requests setSearch(event.currentTarget.value)} />
+ Displayed page · UTC
+
+ {model.requests.length === 0 ?
{empty ?? "No requests were received in this window."} :
+ requests.length === 0 ?
No displayed requests match. :
+
+ {requests.map(request =>
+ {request.sqid}
+ {request.lastError ? {request.lastError} : null}
+
+
+ )}
+
}
+
{requests.length} displayed requests · newest received first
{model.nextPageToken ? Next page : null}
-
+
;
}
@@ -82,28 +90,31 @@ function HistoryValue({ item }: { item: HistoryEventModel }) {
if (item.type === "status" && item.status !== null) {
return ;
}
- return {item.type === "event" && item.event !== null ? statusDisplay(item.event).label : "Unknown event"} ;
+ return {item.type === "event" && item.event !== null ? statusDisplay(item.event).label : "Unknown event"} ;
}
export function RequestHistory({ events }: { events: HistoryEventModel[] }) {
const [filter, setFilter] = useState("all");
+ const filters = [{ id: "all", label: "All events" }, { id: "status", label: "Lifecycle" }, { id: "event", label: "Occurrence events" }];
const shown = events.filter(event => filter === "all" || event.type === filter);
return
-
Request history Show setFilter(event.target.value)}>
- All events Lifecycle Occurrence events
-
- {events.length === 0 ? No history has been retained for this request.
:
- {shown.map((item, index) =>
-
+ Request history Show option.id === filter)}
+ onChange={({ value }) => setFilter(String(value[0]?.id ?? "all"))} />
+ {events.length === 0 ? No history has been retained for this request. :
+ {shown.map((item, index) =>
+
- {Object.keys(item.metadata).length ? : No additional metadata.
}
+ {Object.keys(item.metadata).length ? : No additional metadata. }
- {item.type === "status" ? "Lifecycle" : item.type === "event" ? "Occurrence" : "Unknown"}
- {item.lastError ? {item.lastError}
: null}
-
- )} }
- {shown.length} displayed events · oldest first · UTC
+ {item.type === "status" ? "Lifecycle" : item.type === "event" ? "Occurrence" : "Unknown"}
+ {item.lastError ? {item.lastError} : null}
+
+ )}}
+ {shown.length} displayed events · oldest first · UTC
;
}
@@ -116,7 +127,7 @@ export function LastSuccessfulData({ result, fallback = null, children }: {
}) {
const data = useLastSuccessfulData(result);
return <>
- {!result.ok ? <> {data !== undefined ? Showing the last successful snapshot; updates are unavailable.
: null}> : null}
+ {!result.ok ? <> {data !== undefined ? Showing the last successful snapshot; updates are unavailable. : null}> : null}
{data !== undefined ? children(data) : fallback}
>;
}
@@ -137,11 +148,11 @@ function CopyControls({ id }: { id: string }) {
setMessage("Copy unavailable. Select the ID or copy the browser address.");
}
};
- return
- void copyValue(id, "ID")}>Copy ID
- void copyValue(window.location.href, "Link")}>Copy link
- {message}
-
;
+ return
+ void copyValue(id, "ID")}>Copy ID
+ void copyValue(window.location.href, "Link")}>Copy link
+ {message}
+ ;
}
export interface RequestDetailProps {
@@ -161,29 +172,33 @@ export function RequestDetail({ model, view = "summary", basePath, backHref, sum
const paths = new WebPaths(basePath === undefined ? {} : { basePath });
const latest = model.history.at(-1);
return
- Queues › {request.queue} › Request
-
- {request.lastError ? {request.lastError}
: null}
-
- Summary
- History{model.historyError ? "" : ` (${model.history.length})`}
-
+ Queues › {request.queue} › Request
+ {request.sqid}
{controls}
+ {request.lastError ? {request.lastError} : null}
+
+
+ Summary
+
+
+ History{model.historyError ? "" : ` (${model.history.length})`}
+
+
{view === "history" ? model.historyError ? : :
-
-
Queue {request.queue}
Request ID {request.sqid}
-
Received · UTC
-
Last recorded event {model.historyError ? "History unavailable" : latest ? <> > : "No retained events"}
-
Last error {request.lastError ?? "None reported"}
-
-
Request metadata {Object.keys(request.metadata).length ? : No additional metadata.
}
+
+
+
+ Last recorded event {model.historyError ? "History unavailable" : latest ? <> > : "No retained events"}
+ Last error {request.lastError ?? "None reported"}
+ Changes
+
Request metadata {Object.keys(request.metadata).length ? : No additional metadata. }
{model.historyError ?
: null}
-
}
+
}
{view === "summary" && model.historyError === null ?
-
+
{model.history.filter(event => event.type === "status" && event.status !== null).map((event, index) =>
{statusDisplay(event.status!).label}
)}
- : null}
+ : null}
;
}
@@ -204,33 +219,32 @@ export function ChangeSubmissions({ model, basePath }: ChangeSubmissionsProps) {
const versions = [...new Map(model.submissions.map(item => [item.versionHref, item.version])).entries()];
const selectedVersion = model.pinnedVersion === null ? model.logicalHref :
model.submissions.find(item => item.version === model.pinnedVersion)?.versionHref;
+ const versionOptions = [{ id: model.logicalHref ?? "", label: "All submitted versions" }, ...versions.map(([href, version]) => ({ id: href, label: version }))];
return
- Queues › {model.queue} › Change
- {model.review} {model.pinnedVersion ? `Submitted version: ${model.pinnedVersion}` : "Submissions across versions"}
- {model.pagination ?
+ Queues › {model.queue} › Change
+ {model.review} {model.pinnedVersion ? `Submitted version: ${model.pinnedVersion}` : "Submissions across versions"}
+ {model.pagination ?
Showing matches from this page of queue requests only.
{model.pagination.nextHref ? " More queue requests remain to be searched." : " The history scan is complete for this receipt window."}
-
: null}
-
Provider {model.provider}
Host {model.host}
Repository {model.repository || "—"}
Queue {model.queue}
- Submission history
+ : null}
+
Repository {model.repository || "—"}
+
Submission history
{model.logicalHref && app && versions.length > 0 ?
- Submitted version void app.navigate(event.target.value)}>
- All submitted versions
- {versions.map(([href, version]) => {version} )}
- :
+ Submitted version option.id === selectedVersion)}
+ onChange={({ value }) => { if (value[0]?.id) void app.navigate(String(value[0].id)); }} /> :
model.pinnedVersion !== null && model.logicalHref ? All submitted versions : null}
-
- {model.window ? Receipt window: — . This is not unlimited retained history.
: Retained submissions for this exact version
}
- {model.submissions.length === 0 ? {model.pagination ? "No submissions were found on this page." : "No submissions were found in this scope."}
:
- Request Submitted version Received · UTC Status
- {model.submissions.map(item => {item.request.sqid}
- {item.version.length > 20 ? `${item.version.slice(0, 8)}…${item.version.slice(-4)}` : item.version}
- {item.request.lastError ? {item.request.lastError}
: null} )}
}
- {model.submissions.length} requests{model.pagination ? " on this page" : ""} · newest received first · repeated submissions remain separate
- {model.pagination ?
+
+ {model.window ? Receipt window: — . This is not unlimited retained history. : Retained submissions for this exact version }
+ {model.submissions.length === 0 ? {model.pagination ? "No submissions were found on this page." : "No submissions were found in this scope."} :
+
+ {model.submissions.map(item => {item.request.sqid}
+ {item.version.length > 20 ? `${item.version.slice(0, 8)}…${item.version.slice(-4)}` : item.version}
+ {item.request.lastError ? {item.request.lastError} : null} )}
}
+ {model.submissions.length} requests{model.pagination ? " on this page" : ""} · newest received first · repeated submissions remain separate
+ {model.pagination ?
{model.pagination.nextHref ? Continue history scan : null}
{model.pagination.latestHref ? Latest history : null}
- : null}
+ : null}
;
}
diff --git a/web/submitqueue/view/error-state.tsx b/web/submitqueue/view/error-state.tsx
index 2791a3698..d42f9bf29 100644
--- a/web/submitqueue/view/error-state.tsx
+++ b/web/submitqueue/view/error-state.tsx
@@ -1,9 +1,14 @@
"use client";
import type { WebError } from "../entity/index.js";
+import { KIND, Notification } from "baseui/notification/index.js";
+import { HeadingSmall, ParagraphSmall } from "baseui/typography/index.js";
export function ErrorState({ error, compact = false }: { error: WebError; compact?: boolean }) {
- return
- {error.title} {error.message}
- ;
+ return
+ {error.title} {error.message}
+ ;
}
diff --git a/web/submitqueue/view/frame.test.tsx b/web/submitqueue/view/frame.test.tsx
index 66ebf0c16..9f7a665e0 100644
--- a/web/submitqueue/view/frame.test.tsx
+++ b/web/submitqueue/view/frame.test.tsx
@@ -1,4 +1,10 @@
-import { render, screen } from "@testing-library/react";
+import { render, screen } from "../../platform/test/rtl.js";
+import { render as renderUnwrapped } from "@testing-library/react";
+import { BaseProvider, DarkTheme, LightTheme } from "baseui";
+import { Button } from "baseui/button/index.js";
+import { renderToString } from "react-dom/server";
+import { Server } from "styletron-engine-atomic";
+import { Provider } from "styletron-react";
import { describe, expect, it } from "vitest";
import { ErrorState } from "./error-state.js";
@@ -27,4 +33,35 @@ describe("WebShell", () => {
expect(screen.getByRole("link").textContent).toBe("Example");
expect(screen.queryByRole("contentinfo")).toBeNull();
});
+
+ it("follows the host theme when it changes", () => {
+ const engine = new Server();
+ function Page({ theme }: { theme: typeof LightTheme }) {
+ return
+ Refresh
+ ;
+ }
+ const { rerender } = renderUnwrapped( );
+ rerender( );
+ expect(engine.getCss()).toContain(DarkTheme.colors.backgroundPrimary);
+ expect(engine.getCss()).toContain(DarkTheme.colors.buttonPrimaryFill);
+ expect(screen.getByRole("link").textContent).toBe("Example");
+ });
+
+ it("extracts custom host theme styles without leaking between server renders", () => {
+ function renderPage(backgroundPrimary: string) {
+ const engine = new Server();
+ const theme = { ...LightTheme, colors: { ...LightTheme.colors, backgroundPrimary } };
+ const html = renderToString(
+ Queue activity
+ );
+ return { html, css: engine.getCss() };
+ }
+ const first = renderPage("#123456");
+ const second = renderPage("#654321");
+ expect(first.html).toContain("Queue activity");
+ expect(first.css).toContain("#123456");
+ expect(second.css).toContain("#654321");
+ expect(second.css).not.toContain("#123456");
+ });
});
diff --git a/web/submitqueue/view/last-successful-data.test.tsx b/web/submitqueue/view/last-successful-data.test.tsx
index 56c1f52eb..7618e7e07 100644
--- a/web/submitqueue/view/last-successful-data.test.tsx
+++ b/web/submitqueue/view/last-successful-data.test.tsx
@@ -1,4 +1,4 @@
-import { renderHook } from "@testing-library/react";
+import { renderHook } from "../../platform/test/rtl.js";
import { describe, expect, it } from "vitest";
import type { LoadResult } from "../entity/index.js";
import { useLastSuccessfulData } from "./last-successful-data.js";
diff --git a/web/submitqueue/view/pages.test.tsx b/web/submitqueue/view/pages.test.tsx
index 164faea8d..4731a0377 100644
--- a/web/submitqueue/view/pages.test.tsx
+++ b/web/submitqueue/view/pages.test.tsx
@@ -1,4 +1,4 @@
-import { fireEvent, render, screen } from "@testing-library/react";
+import { act, fireEvent, render, screen } from "../../platform/test/rtl.js";
import { describe, expect, it, vi } from "vitest";
import { WebNavigationProvider } from "@submitqueue/web-platform";
import { SubmitQueueApp } from "./app.js";
@@ -46,7 +46,7 @@ describe("default reusable application views", () => {
);
expect(screen.getByRole("heading", { name: heading })).toBeTruthy();
- fireEvent.click(screen.getByRole("button", { name: "Refresh" }));
+ await act(async () => fireEvent.click(screen.getByRole("button", { name: "Refresh" })));
expect(refresh).toHaveBeenCalledOnce();
const queueLinks = screen.queryAllByRole("link", { name: "demo-queue" });
queueLinks.forEach(link => expect(link.getAttribute("href")).toBe("/sq/demo-queue"));
@@ -79,7 +79,8 @@ describe("default reusable application views", () => {
}
const navigate = vi.fn();
render( );
- fireEvent.change(screen.getByRole("combobox"), { target: { value: `/sq/demo-queue/change/github/github.com/uber/submitqueue/pull/123/${sha}` } });
+ fireEvent.click(screen.getByRole("combobox"));
+ fireEvent.click(await screen.findByRole("option", { name: sha }));
expect(navigate).toHaveBeenCalledWith(`/sq/demo-queue/change/github/github.com/uber/submitqueue/pull/123/${sha}`);
});
diff --git a/web/submitqueue/view/pages.tsx b/web/submitqueue/view/pages.tsx
index f55b78932..f11da3de3 100644
--- a/web/submitqueue/view/pages.tsx
+++ b/web/submitqueue/view/pages.tsx
@@ -3,6 +3,8 @@
import { WebRefreshControl } from "./refresh-control.js";
import { WebShell, type WebShellProps } from "./shell.js";
import { Timestamp } from "@submitqueue/web-platform";
+import { Block } from "baseui/block/index.js";
+import { HeadingLarge, ParagraphSmall, ParagraphXSmall } from "baseui/typography/index.js";
import { WebLink } from "./web-app.js";
import { ChangeSubmissions, LastSuccessfulData, QueueDirectory, RequestDetailView, RequestListView } from "./components.js";
import type { SubmitQueuePageModel } from "../entity/index.js";
@@ -20,34 +22,30 @@ export interface SubmitQueuePageProps {
/** Renders one page model; refresh and version controls appear only inside a `WebApp` such as `SubmitQueueApp`. */
export function SubmitQueuePage({ model }: SubmitQueuePageProps) {
const refreshControl = ;
- if (model.kind === "queue") {
- return
-
+ return
+ {model.kind === "queue" ? <>
+
-
Queue activity
{model.queue}
-
{model.paged ? "Older requests · snapshot" : "Last 24 hours · updates on refresh"}: —
+
Queue activity {model.queue}
+
{model.paged ? "Older requests · snapshot" : "Last 24 hours · updates on refresh"}: —
- Latest 24 hours {refreshControl}
-
+ Latest 24 hours {refreshControl}
+
- ;
- }
- if (model.kind === "request") {
- return
+ > : model.kind === "request" ?
- ;
- }
- return
- {model.kind === "queues"
- ? {queues => }
- : {change => } }
- {refreshControl}
- ;
+ : <>
+ {model.kind === "queues"
+ ? {queues => }
+ : {change => } }
+ {refreshControl}
+ >}
+ ;
}
export function SubmitQueueStatePage({ kind, homeHref = "/", message }: {
@@ -55,13 +53,13 @@ export function SubmitQueueStatePage({ kind, homeHref = "/", message }: {
}) {
const notFound = kind === "not-found";
return
-
-
- {notFound ? "Request lookup" : "SubmitQueue"}
- {notFound ? "Request not found" : "Authentication required"}
- {message ?? (notFound ? "The queue or request may not exist, or its retained data may have expired." : "Use the credentials configured for this host.")}
- {notFound ? Return to queues : null}
+
+
+ {notFound ? "Request lookup" : "SubmitQueue"}
+ {notFound ? "Request not found" : "Authentication required"}
+ {message ?? (notFound ? "The queue or request may not exist, or its retained data may have expired." : "Use the credentials configured for this host.")}
+ {notFound ? Return to queues : null}
-
+
;
}
diff --git a/web/submitqueue/view/shell.tsx b/web/submitqueue/view/shell.tsx
index ae72dff70..822286d75 100644
--- a/web/submitqueue/view/shell.tsx
+++ b/web/submitqueue/view/shell.tsx
@@ -1,6 +1,10 @@
"use client";
import type { ReactNode } from "react";
+import { Block } from "baseui/block/index.js";
+import { StyledLink } from "baseui/link/index.js";
+import { Tag } from "baseui/tag/index.js";
+import { LabelMedium, LabelXSmall } from "baseui/typography/index.js";
export interface WebShellProps {
children: ReactNode;
@@ -12,22 +16,23 @@ export interface WebShellProps {
brandMark?: string;
environmentLabel?: string;
footer?: ReactNode;
- /** Color scheme: `system` follows the viewer's preference. */
- theme?: "light" | "dark" | "system";
}
export function WebShell({
children, homeHref = "/", homeLabel, brand, brandMark = "", environmentLabel = "Read-only",
- footer = "Read-only · updates automatically", theme = "light",
+ footer = "Read-only · updates automatically",
}: WebShellProps) {
- return
-
+ return
+
+
+ {brandMark ? {brandMark} : null}{brand}
+
+ {environmentLabel ? {environmentLabel} : null}
+
{children}
- {footer ? : null}
- ;
+ {footer ? {footer} : null}
+ ;
}
diff --git a/web/submitqueue/view/styles.css b/web/submitqueue/view/styles.css
index 883cadd6a..063d466f6 100644
--- a/web/submitqueue/view/styles.css
+++ b/web/submitqueue/view/styles.css
@@ -1,41 +1 @@
@import "@submitqueue/web-platform/styles.css";
-
-/* SubmitQueue pages. */
-.sq-app .sq-detail-heading { display: flex; justify-content: space-between; gap: 24px; align-items: flex-start; flex-wrap: wrap; margin-bottom: 24px; }
-.sq-app .sq-detail-actions, .sq-app .sq-copy { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
-.sq-app .sq-detail-actions { align-items: flex-start; }
-.sq-app .sq-detail-actions button { min-height: 40px; font-size: 14px; }
-.sq-app .sq-copy [role="status"] { width: 100%; color: var(--sq-muted); font-size: 12px; }
-.sq-app .sq-copy [role="status"]:empty { display: none; }
-.sq-app .sq-toolbar { display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; align-items: center; margin-bottom: 14px; }
-.sq-app .sq-toolbar label { display: flex; align-items: center; gap: 10px; color: var(--sq-muted); font-size: 12px; flex-wrap: wrap; }
-.sq-app .sq-toolbar input { width: 240px; max-width: 100%; }
-.sq-app .sq-changes { list-style: none; padding: 0; margin: 0; display: grid; gap: 8px; }
-.sq-app .sq-changes code, .sq-app .sq-changes a, .sq-app .sq-version { font: 12px var(--sq-font-mono); overflow-wrap: anywhere; }
-.sq-app .sq-row-error { color: var(--sq-danger); font-size: 12px; max-width: 36ch; overflow-wrap: anywhere; }
-.sq-app .sq-tabs { display: flex; gap: 25px; border-bottom: 1px solid var(--sq-border); margin-bottom: 24px; }
-.sq-app .sq-tabs a { padding: 10px 0 12px; color: var(--sq-muted); }
-.sq-app .sq-tabs [aria-current="page"] { color: var(--sq-text); border-bottom: 2px solid var(--sq-text); }
-.sq-app .sq-soft-panel { padding: 18px; background: var(--sq-surface-muted); border-radius: 8px; margin-bottom: 16px; }
-.sq-app .sq-soft-panel summary { margin-bottom: 10px; }
-.sq-app .sq-stage { list-style: none; display: flex; flex-wrap: wrap; gap: 9px; padding: 0; margin-top: 24px; color: var(--sq-muted); font-size: 12px; }
-.sq-app .sq-stage li + li::before { content: "›"; margin-right: 9px; }
-.sq-app .sq-metadata { margin: 12px 0 0; }
-.sq-app .sq-metadata__entry { display: grid; grid-template-columns: minmax(100px, .35fr) 1fr; gap: 16px; font-size: 12px; padding: 7px 0; }
-.sq-app .sq-history { padding: 0; list-style: none; }
-.sq-app .sq-history__item { display: grid; grid-template-columns: 220px 1fr auto; gap: 16px; padding: 14px 0; border-bottom: 1px solid var(--sq-border); }
-.sq-app .sq-history__item time { font-size: 12px; color: var(--sq-muted); }
-.sq-app .sq-history__item details[open] .sq-metadata { background: var(--sq-surface-muted); padding: 12px; border-radius: 6px; }
-.sq-app .sq-history__item .sq-row-error { grid-column: 2; }
-.sq-app .sq-failure-banner { padding: 16px; border-radius: 6px; color: var(--sq-danger); background: var(--sq-danger-soft); }
-.sq-app .sq-directory ul { list-style: none; padding: 0; margin-top: 24px; }
-.sq-app .sq-directory li { padding: 18px 0; border-bottom: 1px solid var(--sq-border); }
-.sq-app .sq-directory li p { color: var(--sq-muted); }
-.sq-app .sq-change-identity { display: flex; gap: 28px; flex-wrap: wrap; padding: 18px; border-radius: 8px; background: var(--sq-surface-muted); margin: 24px 0; }
-@media (max-width: 680px) {
-.sq-app .sq-history__item { grid-template-columns: 1fr; gap: 8px; }
-.sq-app .sq-history__item .sq-row-error { grid-column: 1; }
-.sq-app .sq-metadata__entry { grid-template-columns: 1fr; gap: 4px; }
-.sq-app .sq-toolbar label { align-items: flex-start; }
-.sq-app .sq-detail-actions button { min-height: 44px; }
-}
diff --git a/web/submitqueue/view/web-app.test.tsx b/web/submitqueue/view/web-app.test.tsx
index 243f7de7d..e9739e223 100644
--- a/web/submitqueue/view/web-app.test.tsx
+++ b/web/submitqueue/view/web-app.test.tsx
@@ -1,4 +1,4 @@
-import { fireEvent, render, screen } from "@testing-library/react";
+import { act, fireEvent, render, screen } from "../../platform/test/rtl.js";
import type { ReactNode } from "react";
import { describe, expect, it, vi } from "vitest";
@@ -25,11 +25,11 @@ function renderApp(model: WebPageModel, navigation: WebNavigation) {
}
describe("WebApp", () => {
- it("refreshes through the host, moving a snapshot page to its refresh target", () => {
+ it("refreshes through the host, moving a snapshot page to its refresh target", async () => {
const refresh = vi.fn(async () => undefined);
renderApp(pageModel("Snapshot", "/latest"), { refresh });
- fireEvent.click(screen.getByRole("button", { name: "Refresh" }));
+ await act(async () => fireEvent.click(screen.getByRole("button", { name: "Refresh" })));
expect(refresh).toHaveBeenCalledWith("/latest");
});
@@ -73,7 +73,7 @@ describe("WebLink", () => {
describe("WebRefreshControl", () => {
it("renders nothing outside a WebApp", () => {
- const { container } = render( );
- expect(container.innerHTML).toBe("");
+ render( );
+ expect(screen.queryByRole("button")).toBeNull();
});
});
diff --git a/web/submitqueue/view/web-app.tsx b/web/submitqueue/view/web-app.tsx
index 8b4dd10dd..65f06bde2 100644
--- a/web/submitqueue/view/web-app.tsx
+++ b/web/submitqueue/view/web-app.tsx
@@ -3,6 +3,7 @@
import { createContext, useContext, useMemo, useRef, type ComponentType } from "react";
import type { WebPageModel } from "../entity/index.js";
import { useWebNavigation, type WebLinkProps } from "@submitqueue/web-platform";
+import { StyledLink } from "baseui/link/index.js";
/** Client-side controls of the enclosing {@link WebApp}. */
export interface WebAppControls {
@@ -57,8 +58,8 @@ export function WebApp({ model, Page }: WebAppProps<
return ;
}
-/** An in-app link: the host's `Link` when supplied, otherwise a plain anchor. */
-export function WebLink(props: WebLinkProps) {
+/** An in-app link styled by BaseUI, using the host's router when supplied. */
+export function WebLink({ className = "", ...props }: WebLinkProps) {
const { Link } = useWebNavigation();
- return Link ? : ;
+ return ;
}
diff --git a/web/submitqueue/vitest.config.ts b/web/submitqueue/vitest.config.ts
index 21c8ec048..177f92ec7 100644
--- a/web/submitqueue/vitest.config.ts
+++ b/web/submitqueue/vitest.config.ts
@@ -5,6 +5,7 @@ export default defineConfig({
jsx: "automatic",
},
test: {
+ maxWorkers: 2,
environment: "jsdom",
globals: true,
setupFiles: ["./test-setup.ts"],
diff --git a/web/test/e2e/stovepipe/stovepipe.spec.ts b/web/test/e2e/stovepipe/stovepipe.spec.ts
index 1b4369505..d1f1d1462 100644
--- a/web/test/e2e/stovepipe/stovepipe.spec.ts
+++ b/web/test/e2e/stovepipe/stovepipe.spec.ts
@@ -10,11 +10,44 @@ const client = createClient(
defaultTimeoutMs: 5_000,
}),
);
+test.describe("server-rendered styling", () => {
+ test.use({ javaScriptEnabled: false });
+ test("styles the queue before hydration", async ({ page }) => {
+ await page.goto("/web%2Fpagination");
+ await expect(page.getByRole("heading", { level: 1 })).toHaveCSS("font-size", "32px");
+ await expect(page.getByRole("button", { name: "Refresh", exact: true })).toHaveCSS("background-color", "rgb(0, 0, 0)");
+ await expect(page.getByRole("table", { name: "Requests", exact: true }).locator("tbody tr")).toHaveCount(50);
+ });
+ test("uses the available width on a wide screen", async ({ page }) => {
+ await page.setViewportSize({ width: 1920, height: 1080 });
+ await page.goto("/web%2Fpagination");
+ const table = await page.getByRole("table", { name: "Requests", exact: true }).boundingBox();
+ expect(table?.width).toBeGreaterThan(1920 * 0.95);
+ });
+});
+test("keeps queue tables inside a narrow viewport", async ({ page }) => {
+ await page.setViewportSize({ width: 390, height: 844 });
+ await page.goto("/web%2Fpagination");
+ await expect(page.getByRole("table", { name: "Requests", exact: true }).locator("tbody tr")).toHaveCount(50);
+ expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true);
+ await page.getByRole("link", { name: "51", exact: true }).click();
+ await expect(page.getByRole("heading", { name: "Request 51", exact: true })).toBeVisible();
+ expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true);
+ const history = page.getByRole("region", { name: "Request history", exact: true });
+ await history.focus();
+ await expect(history).toBeFocused();
+ await page.keyboard.press("ArrowRight");
+ await expect.poll(() => history.evaluate(element => element.scrollLeft)).toBeGreaterThan(0);
+ expect((await new AxeBuilder({ page }).analyze()).violations).toEqual([]);
+});
test("real ingestion, queue selection, cursors, request summaries, history, project results and refresh", async ({
page,
}) => {
const errors: string[] = [];
page.on("pageerror", (error) => errors.push(error.message));
+ page.on("console", (message) => {
+ if (message.type() === "error" && /hydrat|did not match|Minified React error #(?:418|423|425)/iu.test(message.text())) errors.push(message.text());
+ });
const id =
await test.step("Ingest a real request and wait for its projection", async () => {
const { id } = await client.ingest({ queue: "monorepo/main" });
@@ -110,7 +143,7 @@ test("real ingestion, queue selection, cursors, request summaries, history, proj
});
await test.step("Read recorded project results and reload their cursor", async () => {
const section = page.getByRole("region", { name: "Project results", exact: true });
- const projects = section.getByRole("table", { name: "Project results", exact: true });
+ const projects = section.getByRole("table", { name: "Recorded project results", exact: true });
await expect(projects.locator("tbody tr")).toHaveCount(51);
await expect(
projects.getByRole("row").filter({
@@ -148,7 +181,7 @@ test("real ingestion, queue selection, cursors, request summaries, history, proj
await page.goto("/web%2Fpagination/request/49");
const section = page.getByRole("region", { name: "Project results", exact: true });
await expect(section.getByText("No project results recorded on this page.", { exact: true })).toBeVisible();
- const projects = section.getByRole("table", { name: "Project results", exact: true });
+ const projects = section.getByRole("table", { name: "Recorded project results", exact: true });
await expect(projects.locator("tbody tr")).toHaveCount(1);
await expect(projects.getByRole("rowheader", { name: "Repository", exact: true })).toBeVisible();
await expect(projects.getByRole("cell", { name: "No result recorded", exact: true })).toBeVisible();
diff --git a/web/test/e2e/submitqueue/submitqueue.spec.ts b/web/test/e2e/submitqueue/submitqueue.spec.ts
index 4c83fef8f..1b6f612aa 100644
--- a/web/test/e2e/submitqueue/submitqueue.spec.ts
+++ b/web/test/e2e/submitqueue/submitqueue.spec.ts
@@ -100,6 +100,12 @@ test("shows newest requests and an accessible readable detail history", async ({
const listAccessibility = await new AxeBuilder({ page }).analyze();
expect(listAccessibility.violations).toEqual([]);
await page.screenshot({ path: test.info().outputPath("queue.png"), fullPage: true });
+ await page.setViewportSize({ width: 1920, height: 1080 });
+ const table = await page.getByRole("table", { name: `Requests in ${queue}` }).boundingBox();
+ expect(table?.width).toBeGreaterThan(1920 * 0.95);
+ await page.setViewportSize({ width: 390, height: 844 });
+ expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true);
+ await page.setViewportSize({ width: 1280, height: 720 });
await page.getByRole("searchbox").fill("1111111111111111111111111111111111111111");
await expect(requestLinks).toHaveCount(1);
@@ -121,9 +127,15 @@ test("shows newest requests and an accessible readable detail history", async ({
expect(actionBoxes.map(box => box!.y)).toEqual([actionBoxes[0]!.y, actionBoxes[0]!.y, actionBoxes[0]!.y]);
expect(actionBoxes.map(box => box!.height)).toEqual([actionBoxes[0]!.height, actionBoxes[0]!.height, actionBoxes[0]!.height]);
await page.screenshot({ path: test.info().outputPath("request-summary.png"), fullPage: true });
+ await page.setViewportSize({ width: 390, height: 844 });
+ expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true);
await page.getByRole("link", { name: /^History/ }).click();
await expect(page).toHaveURL(url => url.searchParams.get("view") === "history");
await expect(page.getByRole("list", { name: "Request history" })).toBeVisible();
+ expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true);
+ await page.getByRole("list", { name: "Request history" }).locator("summary").first().click();
+ expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true);
+ await page.setViewportSize({ width: 1280, height: 720 });
const history = await page.locator(".sq-history__item").allTextContents();
expectOrderedHistory(history, [
@@ -143,7 +155,8 @@ test("shows newest requests and an accessible readable detail history", async ({
expect(detailAccessibility.violations).toEqual([]);
await page.screenshot({ path: test.info().outputPath("request-history.png"), fullPage: true });
- await page.getByRole("combobox").selectOption("event");
+ await page.getByRole("combobox").click();
+ await page.getByRole("option", { name: "Occurrence events", exact: true }).click();
await expect(page.getByRole("list", { name: "Request history" }).getByText("Accepted")).toHaveCount(0);
await page.getByRole("link", { name: "Summary", exact: true }).click();
await page.getByRole("link", { name: "github://github.com/uber/submitqueue/pull/123/2222222222222222222222222222222222222222", exact: true }).click();
@@ -151,7 +164,8 @@ test("shows newest requests and an accessible readable detail history", async ({
await expect(page.getByRole("table", { name: "Change submissions" }).locator("tbody tr")).toHaveCount(3);
expect(new URL(page.url()).search).toBe("");
await page.screenshot({ path: test.info().outputPath("change-submissions.png"), fullPage: true });
- await page.getByRole("combobox", { name: "Filter submissions by version" }).selectOption({ label: "2222222222222222222222222222222222222222" });
+ await page.getByRole("combobox", { name: /Filter submissions by version/ }).click();
+ await page.getByRole("option", { name: "2222222222222222222222222222222222222222", exact: true }).click();
await expect(page.getByText("Retained submissions for this exact version")).toBeVisible();
await expect(page.getByRole("table", { name: "Change submissions" }).locator("tbody tr")).toHaveCount(2);
expect((await new AxeBuilder({ page }).analyze()).violations).toEqual([]);
@@ -177,9 +191,8 @@ test("shows newest requests and an accessible readable detail history", async ({
const logicalChangeUrl = page.url();
await page.reload();
await expect(page.getByRole("heading", { name: "refs/heads/web-demo", exact: true })).toBeVisible();
- await page.getByRole("combobox", { name: "Filter submissions by version" }).selectOption({
- label: "3333333333333333333333333333333333333333",
- });
+ await page.getByRole("combobox", { name: /Filter submissions by version/ }).click();
+ await page.getByRole("option", { name: "3333333333333333333333333333333333333333", exact: true }).click();
await expect(page.getByRole("heading", { name: "refs/heads/web-demo", exact: true })).toBeVisible();
await expect(page.getByRole("table", { name: "Change submissions" }).locator("tbody tr")).toHaveCount(1);
await page.goto(logicalChangeUrl);
diff --git a/web/test/package/BUILD.bazel b/web/test/package/BUILD.bazel
index de29edbab..1030ccbaf 100644
--- a/web/test/package/BUILD.bazel
+++ b/web/test/package/BUILD.bazel
@@ -83,8 +83,11 @@ js_test(
":node_modules/@submitqueue/web-submitqueue",
"//web:node_modules/@bufbuild/protobuf",
"//web:node_modules/@connectrpc/connect",
+ "//web:node_modules/baseui",
"//web:node_modules/react",
"//web:node_modules/react-dom",
+ "//web:node_modules/styletron-engine-atomic",
+ "//web:node_modules/styletron-react",
"//web/submitqueue:node_modules",
],
entry_point = "consumer-runtime.mjs",
diff --git a/web/test/package/consumer-runtime.mjs b/web/test/package/consumer-runtime.mjs
index ee52b037d..6c1a11366 100644
--- a/web/test/package/consumer-runtime.mjs
+++ b/web/test/package/consumer-runtime.mjs
@@ -2,6 +2,9 @@ import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
+import { BaseProvider, LightTheme } from "baseui";
+import { Server } from "styletron-engine-atomic";
+import { Provider } from "styletron-react";
import { SubmitQueueApp, SubmitQueueShell } from "@submitqueue/web-submitqueue";
import { createSubmitQueueWeb, WebPaths } from "@submitqueue/web-submitqueue/server";
import { newHmacCursorCodec } from "@submitqueue/web-submitqueue/extension/cursor/hmac";
@@ -16,13 +19,16 @@ const result = await web.handle({ path: "/queues/demo-queue", search: {} });
assert.equal(result.kind, "render");
assert.equal(result.model.result.ok, true);
assert.doesNotThrow(() => JSON.stringify(result.model));
-const html = renderToStaticMarkup(createElement(SubmitQueueShell, { homeHref: "/queues" },
- createElement(SubmitQueueApp, { model: result.model })));
+const engine = new Server();
+const html = renderToStaticMarkup(createElement(Provider, { value: engine },
+ createElement(BaseProvider, { theme: LightTheme },
+ createElement(SubmitQueueShell, { homeHref: "/queues" },
+ createElement(SubmitQueueApp, { model: result.model })))));
+assert.ok(engine.getCss().length > 0);
assert.ok(html.includes('href="/queues/demo-queue/request/demo-queue/1"'));
assert.ok(html.includes('aria-label="Queue requests"'));
const stylesheet = await readFile(new URL(import.meta.resolve("@submitqueue/web-submitqueue/styles.css")), "utf8");
assert.ok(stylesheet.includes("@submitqueue/web-platform/styles.css"));
const commonStyles = await readFile(new URL(import.meta.resolve("@submitqueue/web-platform/styles.css")), "utf8");
-assert.ok(commonStyles.includes(".sq-app.site-frame"));
-assert.ok(stylesheet.includes(".sq-app .sq-history"));
+assert.ok(commonStyles.trim().length > 0);
console.log("An ordinary Node/React host loaded and rendered the application with its packaged stylesheet.");
diff --git a/web/test/package/react18/package.json b/web/test/package/react18/package.json
index ead9ec5a1..a3fe8d6fb 100644
--- a/web/test/package/react18/package.json
+++ b/web/test/package/react18/package.json
@@ -4,6 +4,9 @@
"private": true,
"type": "module",
"dependencies": {
+ "baseui": "18.2.0",
+ "styletron-engine-atomic": "1.6.2",
+ "styletron-react": "6.1.1",
"jsdom": "^26.1.0",
"react": "18.3.1",
"react-dom": "18.3.1"
diff --git a/web/test/package/react18/react18-runtime.mjs b/web/test/package/react18/react18-runtime.mjs
index 7e2a6991e..dca3955c2 100644
--- a/web/test/package/react18/react18-runtime.mjs
+++ b/web/test/package/react18/react18-runtime.mjs
@@ -2,6 +2,9 @@ import assert from "node:assert/strict";
import { JSDOM } from "jsdom";
import React, { createElement } from "react";
import { renderToString } from "react-dom/server";
+import { BaseProvider, LightTheme } from "baseui";
+import { Client, Server } from "styletron-engine-atomic";
+import { Provider } from "styletron-react";
import { SubmitQueueApp, SubmitQueueShell } from "@submitqueue/web-submitqueue";
import { createSubmitQueueWeb } from "@submitqueue/web-submitqueue/server";
import { newHmacCursorCodec } from "@submitqueue/web-submitqueue/extension/cursor/hmac";
@@ -23,11 +26,20 @@ const routes = [
{ path: "/demo-queue/request/demo-queue/1", search: { view: "history" } },
];
const pages = [];
+function withProviders(page, engine) {
+ return createElement(Provider, { value: engine }, createElement(BaseProvider, { theme: LightTheme }, page));
+}
+function addPage(route, page) {
+ const engine = new Server();
+ const html = renderToString(withProviders(page, engine));
+ assert.ok(engine.getCss().length > 0);
+ pages.push({ route, page, html, stylesheets: engine.getStylesheets() });
+}
for (const route of routes) {
const result = await web.handle(route);
assert.equal(result.kind, "render", `${JSON.stringify(route)} did not render`);
const page = createElement(SubmitQueueShell, null, createElement(SubmitQueueApp, { model: result.model }));
- pages.push({ route, page, html: renderToString(page) });
+ addPage(route, page);
}
const stovepipe = createStovepipeWeb({ queues: [{ name: "repo/main" }], service: {
@@ -38,7 +50,7 @@ for (const path of ["/repo%2Fmain", "/repo%2Fmain/request/1"]) {
const result = await stovepipe.handle({ path, search: new URLSearchParams() });
assert.equal(result.kind, "render");
const page = createElement(StovepipeApp, { model: result.model });
- pages.push({ route: path, page, html: renderToString(page) });
+ addPage(path, page);
}
const dom = new JSDOM("", { url: "https://submitqueue.test/" });
@@ -47,22 +59,39 @@ for (const name of ["window", "document", "navigator"]) {
}
const errors = [];
const reportError = console.error;
-console.error = (...values) => errors.push(values.map(String).join(" "));
+console.error = (...values) => {
+ const message = values.map(String).join(" ");
+ // BaseUI's Popover still uses defaultProps; React 18 warns but hydrates correctly.
+ if (message.includes("Popover") && message.includes("Support for defaultProps will be removed from function components")) {
+ reportError(...values);
+ } else {
+ errors.push(message);
+ }
+};
const { hydrateRoot } = await import("react-dom/client");
// act flushes hydration before unmounting; unmounting a root that is still
// waiting to hydrate is itself reported as a hydration failure.
const { act } = React;
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
-for (const { route, page, html } of pages) {
+for (const { route, page, html, stylesheets } of pages) {
+ const styles = stylesheets.map(({ css, attrs }) => {
+ const style = document.createElement("style");
+ for (const [name, value] of Object.entries(attrs)) style.setAttribute(name, value);
+ style.textContent = css;
+ document.head.append(style);
+ return style;
+ });
+ const engine = new Client({ hydrate: styles });
const container = document.createElement("div");
container.innerHTML = html;
document.body.append(container);
let root;
await act(async () => {
- root = hydrateRoot(container, page);
+ root = hydrateRoot(container, withProviders(page, engine));
});
await act(async () => root.unmount());
container.remove();
+ for (const style of styles) style.remove();
assert.deepEqual(errors, [], `${JSON.stringify(route)} failed to hydrate on React ${React.version}`);
}
console.error = reportError;
diff --git a/web/tool/library.bzl b/web/tool/library.bzl
index a91bc7621..327e2992e 100644
--- a/web/tool/library.bzl
+++ b/web/tool/library.bzl
@@ -40,9 +40,11 @@ def web_library(package, vitest, eslint, deps, test_deps = [], assets = []):
)
ts_project(
name = "typecheck",
+ testonly = True,
srcs = sources + tests + config,
declaration = True,
no_emit = True,
+ root_dir = "..",
tsconfig = ":tsconfig",
deps = deps + test_deps,
)
@@ -56,14 +58,18 @@ def web_library(package, vitest, eslint, deps, test_deps = [], assets = []):
name = "test",
args = ["run", "--config", "vitest.config.ts"],
chdir = native.package_name(),
- data = sources + tests + config + [
+ data = depset(sources + tests + config + [
":node_modules",
":node_modules/vitest",
"//web:node_modules/react",
"//web:node_modules/react-dom",
# jest-dom resolves its vitest peer from the workspace root.
"//web:node_modules/vitest",
- ] + deps,
+ "//web:node_modules/baseui",
+ "//web:node_modules/styletron-react",
+ "//web:node_modules/@types/react",
+ "//web:node_modules/@types/react-dom",
+ ] + deps + test_deps).to_list(),
)
eslint.eslint_test(
name = "lint",