diff --git a/web/e2e/helpers/overlay-interaction.ts b/web/e2e/helpers/overlay-interaction.ts
new file mode 100644
index 000000000..81a01d841
--- /dev/null
+++ b/web/e2e/helpers/overlay-interaction.ts
@@ -0,0 +1,41 @@
+/**
+ * Overlay interaction helpers for Radix-based UI tests.
+ *
+ * These helpers exist to guard the class of bugs fixed by de-duping
+ * `@radix-ui/react-dismissable-layer` across the tree: body pointer-events
+ * getting stuck, dropdown typeahead breaking, tooltips re-popping after a
+ * dropdown closes, and related nested-overlay regressions.
+ */
+
+import { expect, type Page } from "@playwright/test";
+
+/**
+ * Assert that `
` is interactive (no stuck `pointer-events: none`).
+ *
+ * Call after closing any overlay. This is the fast secondary assertion —
+ * test specs should also assert a user-visible behavior like "a button
+ * responded to a click" so the test fails on meaningful breakage rather
+ * than just a CSS invariant.
+ */
+export async function expectBodyInteractive(page: Page) {
+ const stuck = await page.evaluate(
+ () => document.body.style.pointerEvents === "none",
+ );
+ expect(stuck, "body.style.pointer-events stuck after overlay close").toBe(
+ false,
+ );
+}
+
+/**
+ * Wait until the `` is no longer marked with `pointer-events: none`.
+ *
+ * Useful right after closing an overlay when Radix's cleanup runs in the
+ * next frame. Throws if the style does not clear within `timeoutMs`.
+ */
+export async function waitForBodyInteractive(page: Page, timeoutMs = 2000) {
+ await page.waitForFunction(
+ () => document.body.style.pointerEvents !== "none",
+ null,
+ { timeout: timeoutMs },
+ );
+}
diff --git a/web/e2e/specs/ptz-overlay.spec.ts b/web/e2e/specs/ptz-overlay.spec.ts
new file mode 100644
index 000000000..06beb1788
--- /dev/null
+++ b/web/e2e/specs/ptz-overlay.spec.ts
@@ -0,0 +1,198 @@
+/**
+ * PTZ overlay regression tests -- MEDIUM tier.
+ *
+ * Guards two things on the PTZ preset dropdown:
+ *
+ * 1. After selecting a preset, the "Presets" tooltip must not re-pop
+ * (focus-restore side-effect that originally prompted the
+ * `onCloseAutoFocus preventDefault` workaround).
+ * 2. Keyboard shortcuts fired after the dropdown closes should not
+ * re-open the dropdown via Space/Enter/Arrow on the trigger
+ * (PR #12079 — "Prevent ptz keyboard shortcuts from reopening
+ * presets menu").
+ *
+ * Requires an onvif-configured camera and a mocked /ptz/info endpoint
+ * exposing presets.
+ *
+ * TODO: migrate these tests into live.spec.ts when it comes out of
+ * PENDING_REWRITE in e2e/scripts/lint-specs.mjs. They live in a dedicated
+ * file today so they stay lint-compliant (no waitForTimeout, no
+ * conditional isVisible) while live.spec.ts is still exempt.
+ */
+
+import { test, expect } from "../fixtures/frigate-test";
+import {
+ expectBodyInteractive,
+ waitForBodyInteractive,
+} from "../helpers/overlay-interaction";
+
+const PTZ_CAMERA = "front_door";
+const PRESET_NAMES = ["home", "driveway", "front_porch"];
+
+test.describe("PTZ preset dropdown @medium", () => {
+ test("selecting a preset closes menu cleanly and does not re-open on keyboard", async ({
+ frigateApp,
+ }) => {
+ if (frigateApp.isMobile) {
+ test.skip();
+ return;
+ }
+
+ // 1. Give front_door an onvif host so the PtzControlPanel renders.
+ // 2. Mock the /ptz/info endpoint to expose features + presets.
+ await frigateApp.api.install({
+ config: {
+ cameras: {
+ [PTZ_CAMERA]: {
+ onvif: {
+ host: "10.0.0.50",
+ },
+ },
+ },
+ },
+ });
+
+ await frigateApp.page.route(`**/api/${PTZ_CAMERA}/ptz/info`, (route) =>
+ route.fulfill({
+ json: {
+ name: PTZ_CAMERA,
+ features: ["pt", "zoom"],
+ presets: PRESET_NAMES,
+ profiles: [],
+ },
+ }),
+ );
+
+ // PTZ commands ride the WebSocket, not HTTP. The WsMocker intercepts
+ // the /ws route, so Playwright's page-level `websocket` event never
+ // fires — instead, patch the client WebSocket.prototype.send before
+ // any app code runs and mirror sends into a window-level array the
+ // test can read back.
+ await frigateApp.page.addInitScript(() => {
+ (window as unknown as { __sentWsFrames: string[] }).__sentWsFrames = [];
+ const origSend = WebSocket.prototype.send;
+ WebSocket.prototype.send = function (data) {
+ try {
+ (
+ window as unknown as { __sentWsFrames: string[] }
+ ).__sentWsFrames.push(typeof data === "string" ? data : "(binary)");
+ } catch {
+ // ignore — best-effort tracing
+ }
+ return origSend.call(this, data);
+ };
+ });
+
+ await frigateApp.goto(`/#${PTZ_CAMERA}`);
+
+ // Locate the preset trigger — a button whose accessible name includes
+ // "presets" (set via aria-label={t("ptz.presets")}).
+ const presetTrigger = frigateApp.page.getByRole("button", {
+ name: /presets/i,
+ });
+ await expect(presetTrigger.first()).toBeVisible({ timeout: 5_000 });
+
+ await presetTrigger.first().click();
+
+ const menu = frigateApp.page
+ .locator('[role="menu"], [data-radix-menu-content]')
+ .first();
+ await expect(menu).toBeVisible({ timeout: 3_000 });
+
+ // Pick a preset.
+ const firstPreset = menu
+ .getByRole("menuitem", { name: PRESET_NAMES[0] })
+ .first();
+ await firstPreset.click();
+
+ // Menu closes.
+ await expect(menu).not.toBeVisible({ timeout: 3_000 });
+
+ // Preset command was dispatched over the WS.
+ await expect
+ .poll(
+ async () => {
+ const sentFrames = await frigateApp.page.evaluate(
+ () =>
+ (window as unknown as { __sentWsFrames: string[] })
+ .__sentWsFrames,
+ );
+
+ return sentFrames.some(
+ (frame) =>
+ frame.includes(`"${PTZ_CAMERA}/ptz"`) &&
+ frame.includes(`preset_${PRESET_NAMES[0]}`),
+ );
+ },
+ { timeout: 2_000 },
+ )
+ .toBe(true);
+
+ // Body is interactive.
+ await waitForBodyInteractive(frigateApp.page);
+ await expectBodyInteractive(frigateApp.page);
+
+ // Presets tooltip should NOT be visible.
+ await expect
+ .poll(
+ async () =>
+ frigateApp.page
+ .locator('[role="tooltip"]')
+ .filter({ hasText: /presets/i })
+ .isVisible()
+ .catch(() => false),
+ { timeout: 1_000 },
+ )
+ .toBe(false);
+
+ // Now press keyboard keys — none should reopen the menu.
+ await frigateApp.page.keyboard.press("ArrowUp");
+ await frigateApp.page.keyboard.press("Space");
+ await frigateApp.page.keyboard.press("Enter");
+ await expect
+ .poll(() => menu.isVisible().catch(() => false), { timeout: 1_000 })
+ .toBe(false);
+ });
+});
+
+test.describe("Mobile live camera overlay @medium @mobile", () => {
+ test("mobile single-camera view loads without freezing body", async ({
+ frigateApp,
+ }) => {
+ if (!frigateApp.isMobile) {
+ test.skip();
+ return;
+ }
+
+ // Same config override as the desktop spec so the mobile page exercises
+ // the onvif-enabled code path and its dismissable-layer consumers.
+ await frigateApp.api.install({
+ config: {
+ cameras: {
+ [PTZ_CAMERA]: {
+ onvif: { host: "10.0.0.50" },
+ },
+ },
+ },
+ });
+ await frigateApp.page.route(`**/api/${PTZ_CAMERA}/ptz/info`, (route) =>
+ route.fulfill({
+ json: {
+ name: PTZ_CAMERA,
+ features: ["pt", "zoom"],
+ presets: PRESET_NAMES,
+ profiles: [],
+ },
+ }),
+ );
+
+ await frigateApp.goto(`/#${PTZ_CAMERA}`);
+
+ // Body must be interactive after navigation — this is the mobile-side
+ // smoke test for the dismissable-layer dedupe. A regression that
+ // stuck pointer-events: none on would make the rest of the UI
+ // unclickable.
+ await expectBodyInteractive(frigateApp.page);
+ await expect(frigateApp.page.locator("body")).toBeVisible();
+ });
+});
diff --git a/web/e2e/specs/radix-overlay-regressions.spec.ts b/web/e2e/specs/radix-overlay-regressions.spec.ts
new file mode 100644
index 000000000..aab0be92f
--- /dev/null
+++ b/web/e2e/specs/radix-overlay-regressions.spec.ts
@@ -0,0 +1,301 @@
+/**
+ * Radix overlay regression tests -- MEDIUM tier.
+ *
+ * Guards the bug class fixed by de-duping `@radix-ui/react-dismissable-layer`:
+ *
+ * 1. Body `pointer-events: none` getting stuck after nested overlays close
+ * 2. Dropdown typeahead breaking on the second open
+ * 3. Tooltips popping after a dropdown closes (focus restore side-effect)
+ *
+ * These tests are grouped by UI path rather than by symptom, since a given
+ * flow usually exercises more than one failure mode.
+ *
+ * TODO: migrate these tests into the corresponding page specs
+ * (face-library.spec.ts, system.spec.ts, review.spec.ts) when those files
+ * come out of PENDING_REWRITE in e2e/scripts/lint-specs.mjs. They live in
+ * a dedicated file today so they stay lint-compliant (no waitForTimeout,
+ * no conditional isVisible) while the page specs are still exempt.
+ */
+
+import { type Locator } from "@playwright/test";
+import { test, expect, type FrigateApp } from "../fixtures/frigate-test";
+import {
+ expectBodyInteractive,
+ waitForBodyInteractive,
+} from "../helpers/overlay-interaction";
+
+const GROUPED_FACE_EVENT_ID = "1775487131.3863528-abc123";
+const GROUPED_FACE_TRAINING_IMAGES = [
+ `${GROUPED_FACE_EVENT_ID}-1775487131.3863528-unknown-0.95.webp`,
+ `${GROUPED_FACE_EVENT_ID}-1775487132.3863528-unknown-0.91.webp`,
+];
+
+async function installGroupedFaceAttemptData(app: FrigateApp) {
+ await app.api.install({
+ events: [
+ {
+ id: GROUPED_FACE_EVENT_ID,
+ label: "person",
+ sub_label: null,
+ camera: "front_door",
+ start_time: 1775487131.3863528,
+ end_time: 1775487161.3863528,
+ false_positive: false,
+ zones: ["front_yard"],
+ thumbnail: null,
+ has_clip: true,
+ has_snapshot: true,
+ retain_indefinitely: false,
+ plus_id: null,
+ model_hash: "abc123",
+ detector_type: "cpu",
+ model_type: "ssd",
+ data: {
+ top_score: 0.92,
+ score: 0.92,
+ region: [0.1, 0.1, 0.5, 0.8],
+ box: [0.2, 0.15, 0.45, 0.75],
+ area: 0.18,
+ ratio: 0.6,
+ type: "object",
+ path_data: [],
+ },
+ },
+ ],
+ faces: {
+ train: GROUPED_FACE_TRAINING_IMAGES,
+ alice: ["alice-1.webp"],
+ bob: ["bob-1.webp"],
+ charlie: ["charlie-1.webp"],
+ david: ["david-1.webp"],
+ },
+ });
+}
+
+async function openGroupedFaceAttemptDialog(app: FrigateApp): Promise {
+ await installGroupedFaceAttemptData(app);
+ await app.goto("/faces");
+
+ const groupedCardImage = app.page
+ .locator('img[src*="clips/faces/train/"]')
+ .first();
+ const groupedCard = groupedCardImage.locator("xpath=..");
+ await expect(groupedCardImage).toBeVisible({ timeout: 5_000 });
+ await groupedCard.click();
+
+ const dialog = app.page
+ .getByRole("dialog")
+ .filter({ has: app.page.locator('img[src*="clips/faces/train/"]') })
+ .first();
+ await expect(dialog).toBeVisible({ timeout: 5_000 });
+ await expect(dialog.locator('img[src*="clips/faces/train/"]')).toHaveCount(2);
+
+ return dialog;
+}
+
+function groupedFaceReclassifyTriggers(dialog: Locator) {
+ return dialog.locator('[aria-haspopup="menu"]');
+}
+
+test.describe("FaceSelectionDialog @medium", () => {
+ test("grouped recent-recognition dialog closes menu without re-popping tooltip or locking body", async ({
+ frigateApp,
+ }) => {
+ if (frigateApp.isMobile) {
+ test.skip();
+ return;
+ }
+
+ const dialog = await openGroupedFaceAttemptDialog(frigateApp);
+ const triggers = groupedFaceReclassifyTriggers(dialog);
+ await expect(triggers).toHaveCount(2);
+
+ await triggers.first().click();
+
+ const menu = frigateApp.page
+ .locator('[role="menu"], [data-radix-menu-content]')
+ .first();
+ await expect(menu).toBeVisible({ timeout: 5_000 });
+
+ await menu.getByRole("menuitem", { name: /^bob$/i }).click();
+
+ await expect(menu).not.toBeVisible({ timeout: 3_000 });
+ await expect(dialog).toBeVisible();
+
+ // The grouped recent-recognitions flow wraps the dropdown trigger in a
+ // tooltip inside the detail dialog. Focus should not jump back there.
+ const visibleTooltip = await frigateApp.page
+ .locator('[role="tooltip"]')
+ .filter({ hasText: /train face/i })
+ .isVisible()
+ .catch(() => false);
+ expect(
+ visibleTooltip,
+ "Train Face tooltip popped after dropdown closed in grouped dialog — focus-restore regression",
+ ).toBe(false);
+ });
+
+ test("second grouped-image dropdown open accepts typeahead keyboard input", async ({
+ frigateApp,
+ }) => {
+ if (frigateApp.isMobile) {
+ test.skip();
+ return;
+ }
+
+ const dialog = await openGroupedFaceAttemptDialog(frigateApp);
+ const triggers = groupedFaceReclassifyTriggers(dialog);
+ await expect(triggers).toHaveCount(2);
+
+ await triggers.first().click();
+ let menu = frigateApp.page
+ .locator('[role="menu"], [data-radix-menu-content]')
+ .first();
+ await expect(menu).toBeVisible({ timeout: 5_000 });
+ await menu.getByRole("menuitem", { name: /^bob$/i }).click();
+ await expect(menu).not.toBeVisible({ timeout: 3_000 });
+ await expect(dialog).toBeVisible();
+
+ await triggers.nth(1).click();
+ menu = frigateApp.page
+ .locator('[role="menu"], [data-radix-menu-content]')
+ .first();
+ await expect(menu).toBeVisible({ timeout: 5_000 });
+
+ await frigateApp.page.keyboard.press("c");
+ await expect
+ .poll(
+ async () =>
+ frigateApp.page.evaluate(
+ () =>
+ document.activeElement?.textContent?.trim().toLowerCase() ?? "",
+ ),
+ { timeout: 2_000 },
+ )
+ .toMatch(/^charlie/);
+
+ await frigateApp.page.keyboard.press("Escape");
+ await expect(menu).not.toBeVisible({ timeout: 3_000 });
+ });
+});
+
+test.describe("RestartDialog @medium", () => {
+ test("cancelling restart leaves body interactive", async ({ frigateApp }) => {
+ if (frigateApp.isMobile) {
+ test.skip();
+ return;
+ }
+ await frigateApp.goto("/");
+
+ // "Restart Frigate" lives in the sidebar GeneralSettings dropdown. The
+ // sidebar has several aria-haspopup triggers (System, Account, etc.);
+ // we open each until the Restart item is visible.
+ const sidebarTriggers = frigateApp.page
+ .locator('[role="complementary"] [aria-haspopup="menu"]')
+ .or(frigateApp.page.locator('aside [aria-haspopup="menu"]'));
+ const triggerCount = await sidebarTriggers.count();
+ expect(triggerCount).toBeGreaterThan(0);
+
+ let opened = false;
+ for (let i = 0; i < triggerCount; i++) {
+ const trigger = sidebarTriggers.nth(i);
+ await trigger.click().catch(() => {});
+ const restartItem = frigateApp.page
+ .getByRole("menuitem", { name: /restart/i })
+ .first();
+ const isVisible = await expect(restartItem)
+ .toBeVisible({ timeout: 300 })
+ .then(() => true)
+ .catch(() => false);
+ if (isVisible) {
+ await restartItem.click();
+ opened = true;
+ break;
+ }
+ await frigateApp.page.keyboard.press("Escape").catch(() => {});
+ }
+
+ expect(opened).toBe(true);
+
+ const cancel = frigateApp.page.getByRole("button", { name: /cancel/i });
+ await expect(cancel).toBeVisible({ timeout: 3_000 });
+ await cancel.click();
+
+ await waitForBodyInteractive(frigateApp.page);
+ await expectBodyInteractive(frigateApp.page);
+
+ // Sanity: the surrounding shell is still clickable after the dialog closes.
+ const postCancelTrigger = sidebarTriggers.first();
+ await postCancelTrigger.click();
+ await expect(
+ frigateApp.page
+ .locator('[role="menu"], [data-radix-menu-content]')
+ .first(),
+ ).toBeVisible({ timeout: 3_000 });
+ });
+});
+
+test.describe("Nested overlay invariant @medium", () => {
+ test("closing review filter popover leaves body interactive", async ({
+ frigateApp,
+ }) => {
+ if (frigateApp.isMobile) {
+ test.skip();
+ return;
+ }
+ await frigateApp.goto("/review");
+
+ const camerasBtn = frigateApp.page
+ .getByRole("button", { name: /cameras/i })
+ .first();
+ await expect(camerasBtn).toBeVisible({ timeout: 5_000 });
+
+ await camerasBtn.click();
+
+ const overlay = frigateApp.page
+ .locator(
+ '[role="menu"], [role="dialog"], [data-radix-popper-content-wrapper]',
+ )
+ .first();
+ await expect(overlay).toBeVisible({ timeout: 3_000 });
+
+ await frigateApp.page.keyboard.press("Escape");
+ await expect(overlay).not.toBeVisible({ timeout: 3_000 });
+ await waitForBodyInteractive(frigateApp.page);
+ await expectBodyInteractive(frigateApp.page);
+ });
+});
+
+test.describe("Mobile face library overlay @medium @mobile", () => {
+ test("mobile library selector dropdown closes cleanly", async ({
+ frigateApp,
+ }) => {
+ if (!frigateApp.isMobile) {
+ test.skip();
+ return;
+ }
+
+ // The library collection selector is a Radix DropdownMenu on both
+ // desktop and mobile — a direct consumer of react-dismissable-layer.
+ // This exercises the dedupe'd cleanup path on mobile viewport.
+ await installGroupedFaceAttemptData(frigateApp);
+ await frigateApp.goto("/faces");
+
+ const selector = frigateApp.page
+ .getByRole("button")
+ .filter({ hasText: /\(\d+\)/ })
+ .first();
+ await expect(selector).toBeVisible({ timeout: 5_000 });
+ await selector.click();
+
+ const menu = frigateApp.page
+ .locator('[role="menu"], [data-radix-menu-content]')
+ .first();
+ await expect(menu).toBeVisible({ timeout: 3_000 });
+
+ await frigateApp.page.keyboard.press("Escape");
+ await expect(menu).not.toBeVisible({ timeout: 3_000 });
+ await waitForBodyInteractive(frigateApp.page);
+ await expectBodyInteractive(frigateApp.page);
+ });
+});
diff --git a/web/package-lock.json b/web/package-lock.json
index fc115fc3c..aad435de9 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -12,14 +12,14 @@
"@cycjimmy/jsmpeg-player": "^6.1.2",
"@hookform/resolvers": "^3.10.0",
"@melloware/react-logviewer": "^6.1.2",
- "@radix-ui/react-alert-dialog": "^1.1.6",
+ "@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-aspect-ratio": "^1.1.2",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-collapsible": "^1.1.12",
- "@radix-ui/react-context-menu": "^2.2.6",
+ "@radix-ui/react-context-menu": "^2.2.16",
"@radix-ui/react-dialog": "^1.1.15",
- "@radix-ui/react-dropdown-menu": "^2.1.6",
- "@radix-ui/react-hover-card": "^1.1.6",
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
+ "@radix-ui/react-hover-card": "^1.1.15",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-progress": "^1.1.8",
@@ -1515,17 +1515,17 @@
"license": "MIT"
},
"node_modules/@radix-ui/react-alert-dialog": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.6.tgz",
- "integrity": "sha512-p4XnPqgej8sZAAReCAKgz1REYZEBLR8hU9Pg27wFnCWIMc8g1ccCs0FjBcy05V15VTu8pAePw/VDYeOm/uZ6yQ==",
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz",
+ "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.1",
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-context": "1.1.1",
- "@radix-ui/react-dialog": "1.1.6",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-slot": "1.1.2"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dialog": "1.1.15",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
},
"peerDependencies": {
"@types/react": "*",
@@ -1542,126 +1542,17 @@
}
}
},
- "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-dialog": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz",
- "integrity": "sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.1",
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-context": "1.1.1",
- "@radix-ui/react-dismissable-layer": "1.1.5",
- "@radix-ui/react-focus-guards": "1.1.1",
- "@radix-ui/react-focus-scope": "1.1.2",
- "@radix-ui/react-id": "1.1.0",
- "@radix-ui/react-portal": "1.1.4",
- "@radix-ui/react-presence": "1.1.2",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-slot": "1.1.2",
- "@radix-ui/react-use-controllable-state": "1.1.0",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.6.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
+ "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
},
- "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-dismissable-layer": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz",
- "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.1",
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-callback-ref": "1.1.0",
- "@radix-ui/react-use-escape-keydown": "1.1.0"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-focus-scope": {
+ "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-context": {
"version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz",
- "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
"license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-callback-ref": "1.1.0"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-portal": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz",
- "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-layout-effect": "1.1.0"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-use-escape-keydown": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
- "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-callback-ref": "1.1.0"
- },
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -1672,6 +1563,29 @@
}
}
},
+ "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-arrow": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
@@ -2113,17 +2027,17 @@
}
},
"node_modules/@radix-ui/react-context-menu": {
- "version": "2.2.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.6.tgz",
- "integrity": "sha512-aUP99QZ3VU84NPsHeaFt4cQUNgJqFsLLOt/RbbWXszZ6MP0DpDyjkFZORr4RpAEx3sUBk+Kc8h13yGtC5Qw8dg==",
+ "version": "2.2.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz",
+ "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.1",
- "@radix-ui/react-context": "1.1.1",
- "@radix-ui/react-menu": "2.1.6",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-callback-ref": "1.1.0",
- "@radix-ui/react-use-controllable-state": "1.1.0"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
},
"peerDependencies": {
"@types/react": "*",
@@ -2140,6 +2054,99 @@
}
}
},
+ "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-dialog": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
@@ -2197,21 +2204,6 @@
}
}
},
- "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
- "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
"node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-id": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
@@ -2398,18 +2390,18 @@
}
},
"node_modules/@radix-ui/react-dropdown-menu": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.6.tgz",
- "integrity": "sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA==",
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
+ "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.1",
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-context": "1.1.1",
- "@radix-ui/react-id": "1.1.0",
- "@radix-ui/react-menu": "2.1.6",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-controllable-state": "1.1.0"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
},
"peerDependencies": {
"@types/react": "*",
@@ -2426,10 +2418,106 @@
}
}
},
- "node_modules/@radix-ui/react-focus-guards": {
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-id": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz",
- "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
+ "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -2505,20 +2593,20 @@
}
},
"node_modules/@radix-ui/react-hover-card": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.6.tgz",
- "integrity": "sha512-E4ozl35jq0VRlrdc4dhHrNSV0JqBb4Jy73WAhBEK7JoYnQ83ED5r0Rb/XdVKw89ReAJN38N492BAPBZQ57VmqQ==",
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz",
+ "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.1",
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-context": "1.1.1",
- "@radix-ui/react-dismissable-layer": "1.1.5",
- "@radix-ui/react-popper": "1.2.2",
- "@radix-ui/react-portal": "1.1.4",
- "@radix-ui/react-presence": "1.1.2",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-controllable-state": "1.1.0"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
},
"peerDependencies": {
"@types/react": "*",
@@ -2535,17 +2623,35 @@
}
}
},
- "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-dismissable-layer": {
+ "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-presence": {
"version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz",
- "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.1",
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-callback-ref": "1.1.0",
- "@radix-ui/react-use-escape-keydown": "1.1.0"
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2562,14 +2668,13 @@
}
}
},
- "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-portal": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz",
- "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==",
+ "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-layout-effect": "1.1.0"
+ "@radix-ui/react-slot": "1.2.3"
},
"peerDependencies": {
"@types/react": "*",
@@ -2586,13 +2691,14 @@
}
}
},
- "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-escape-keydown": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
- "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
+ "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-callback-ref": "1.1.0"
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2604,6 +2710,21 @@
}
}
},
+ "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-icons": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz",
@@ -2678,27 +2799,27 @@
}
},
"node_modules/@radix-ui/react-menu": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.6.tgz",
- "integrity": "sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg==",
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
+ "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.1",
- "@radix-ui/react-collection": "1.1.2",
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-context": "1.1.1",
- "@radix-ui/react-direction": "1.1.0",
- "@radix-ui/react-dismissable-layer": "1.1.5",
- "@radix-ui/react-focus-guards": "1.1.1",
- "@radix-ui/react-focus-scope": "1.1.2",
- "@radix-ui/react-id": "1.1.0",
- "@radix-ui/react-popper": "1.2.2",
- "@radix-ui/react-portal": "1.1.4",
- "@radix-ui/react-presence": "1.1.2",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-roving-focus": "1.1.2",
- "@radix-ui/react-slot": "1.1.2",
- "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
"aria-hidden": "^1.2.4",
"react-remove-scroll": "^2.6.3"
},
@@ -2717,17 +2838,22 @@
}
}
},
- "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-dismissable-layer": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz",
- "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==",
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-collection": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.1",
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-callback-ref": "1.1.0",
- "@radix-ui/react-use-escape-keydown": "1.1.0"
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
},
"peerDependencies": {
"@types/react": "*",
@@ -2744,15 +2870,62 @@
}
}
},
- "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-focus-scope": {
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-context": {
"version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz",
- "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-direction": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-id": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.1",
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-callback-ref": "1.1.0"
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-presence": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
@@ -2769,14 +2942,13 @@
}
}
},
- "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-portal": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz",
- "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==",
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.0.2",
- "@radix-ui/react-use-layout-effect": "1.1.0"
+ "@radix-ui/react-slot": "1.2.3"
},
"peerDependencies": {
"@types/react": "*",
@@ -2793,14 +2965,76 @@
}
}
},
- "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-escape-keydown": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
- "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
+ "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-callback-ref": "1.1.0"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
},
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -2869,21 +3103,6 @@
}
}
},
- "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-focus-guards": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
- "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
"node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-id": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
@@ -3717,21 +3936,6 @@
}
}
},
- "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-focus-guards": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
- "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-id": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
diff --git a/web/package.json b/web/package.json
index 0ece2d6fe..02fcb8ca8 100644
--- a/web/package.json
+++ b/web/package.json
@@ -26,14 +26,14 @@
"@cycjimmy/jsmpeg-player": "^6.1.2",
"@hookform/resolvers": "^3.10.0",
"@melloware/react-logviewer": "^6.1.2",
- "@radix-ui/react-alert-dialog": "^1.1.6",
+ "@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-aspect-ratio": "^1.1.2",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-collapsible": "^1.1.12",
- "@radix-ui/react-context-menu": "^2.2.6",
+ "@radix-ui/react-context-menu": "^2.2.16",
"@radix-ui/react-dialog": "^1.1.15",
- "@radix-ui/react-dropdown-menu": "^2.1.6",
- "@radix-ui/react-hover-card": "^1.1.6",
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
+ "@radix-ui/react-hover-card": "^1.1.15",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-progress": "^1.1.8",
diff --git a/web/src/components/card/ExportCard.tsx b/web/src/components/card/ExportCard.tsx
index 966aab4dc..893f251f8 100644
--- a/web/src/components/card/ExportCard.tsx
+++ b/web/src/components/card/ExportCard.tsx
@@ -266,7 +266,7 @@ export function ExportCard({
)}
{!exportedRecording.in_progress && !selectionMode && (
-
+
-
+
{content}
diff --git a/web/src/components/classification/wizard/Step1NameAndDefine.tsx b/web/src/components/classification/wizard/Step1NameAndDefine.tsx
index a4cdc4867..e6fe64bfc 100644
--- a/web/src/components/classification/wizard/Step1NameAndDefine.tsx
+++ b/web/src/components/classification/wizard/Step1NameAndDefine.tsx
@@ -322,7 +322,7 @@ export default function Step1NameAndDefine({
{t("wizard.step1.classificationType")}
-
+
-
+
diff --git a/web/src/components/classification/wizard/Step2StateArea.tsx b/web/src/components/classification/wizard/Step2StateArea.tsx
index 38c2fcad7..efba0d358 100644
--- a/web/src/components/classification/wizard/Step2StateArea.tsx
+++ b/web/src/components/classification/wizard/Step2StateArea.tsx
@@ -238,11 +238,7 @@ export default function Step2StateArea({
{t("wizard.step2.cameras")}
{availableCameras.length > 0 ? (
-
+
-
+
diff --git a/web/src/components/filter/CamerasFilterButton.tsx b/web/src/components/filter/CamerasFilterButton.tsx
index cc89e13cf..c8d311463 100644
--- a/web/src/components/filter/CamerasFilterButton.tsx
+++ b/web/src/components/filter/CamerasFilterButton.tsx
@@ -136,7 +136,6 @@ export function CamerasFilterButton({
return (
{
if (!open) {
diff --git a/web/src/components/menu/AccountSettings.tsx b/web/src/components/menu/AccountSettings.tsx
index be05422b9..4d876a1fc 100644
--- a/web/src/components/menu/AccountSettings.tsx
+++ b/web/src/components/menu/AccountSettings.tsx
@@ -81,7 +81,7 @@ export default function AccountSettings({ className }: AccountSettingsProps) {
};
return (
-
+
diff --git a/web/src/components/menu/GeneralSettings.tsx b/web/src/components/menu/GeneralSettings.tsx
index d5ca1ced6..a84cd0aa2 100644
--- a/web/src/components/menu/GeneralSettings.tsx
+++ b/web/src/components/menu/GeneralSettings.tsx
@@ -205,7 +205,7 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) {
return (
<>
-
+
diff --git a/web/src/components/menu/LiveContextMenu.tsx b/web/src/components/menu/LiveContextMenu.tsx
index 982895200..8ed78e348 100644
--- a/web/src/components/menu/LiveContextMenu.tsx
+++ b/web/src/components/menu/LiveContextMenu.tsx
@@ -272,7 +272,7 @@ export default function LiveContextMenu({
return (
-
+
{children}
diff --git a/web/src/components/menu/SearchResultActions.tsx b/web/src/components/menu/SearchResultActions.tsx
index 2a8cca5a8..aa2562b42 100644
--- a/web/src/components/menu/SearchResultActions.tsx
+++ b/web/src/components/menu/SearchResultActions.tsx
@@ -258,13 +258,13 @@ export default function SearchResultActions({
{isContextMenu ? (
-
+
{children}
{menuItems}
) : (
<>
-
+
diff --git a/web/src/components/overlay/ActionsDropdown.tsx b/web/src/components/overlay/ActionsDropdown.tsx
index 7f841be4f..9f9596d0a 100644
--- a/web/src/components/overlay/ActionsDropdown.tsx
+++ b/web/src/components/overlay/ActionsDropdown.tsx
@@ -22,7 +22,7 @@ export default function ActionsDropdown({
const { t } = useTranslation(["components/dialog", "views/replay", "common"]);
return (
-
+
-
+
-
+
)}
{(ptz?.presets?.length ?? 0) > 0 && (
-
+
diff --git a/web/src/components/overlay/detail/SearchDetailDialog.tsx b/web/src/components/overlay/detail/SearchDetailDialog.tsx
index c23b916a5..729e4fedf 100644
--- a/web/src/components/overlay/detail/SearchDetailDialog.tsx
+++ b/web/src/components/overlay/detail/SearchDetailDialog.tsx
@@ -241,7 +241,7 @@ function AnnotationSettings({
return (
-
+
{
- if (typeof document !== "undefined") {
- document.body.style.pointerEvents = "";
- }
- };
-
useEffect(() => {
setRestartDialogOpen(isOpen);
}, [isOpen]);
@@ -85,16 +79,10 @@ export default function RestartDialog({
if (!open) {
setRestartDialogOpen(false);
onClose();
- clearBodyPointerEvents();
}
}}
>
- {
- event.preventDefault();
- clearBodyPointerEvents();
- }}
- >
+
{t("restart.title")}
diff --git a/web/src/components/player/VideoControls.tsx b/web/src/components/player/VideoControls.tsx
index a92819a31..5a45e83ac 100644
--- a/web/src/components/player/VideoControls.tsx
+++ b/web/src/components/player/VideoControls.tsx
@@ -1,6 +1,6 @@
import { useCallback, useMemo, useRef, useState } from "react";
import { LuFolderX } from "react-icons/lu";
-import { isDesktop, isMobileOnly, isSafari } from "react-device-detect";
+import { isMobileOnly, isSafari } from "react-device-detect";
import { LuPause, LuPlay } from "react-icons/lu";
import {
DropdownMenu,
@@ -246,7 +246,6 @@ export default function VideoControls({
)}
{features.playbackRate && (
{
if (setControlsOpen) {
setControlsOpen(open);
diff --git a/web/src/components/settings/PolygonItem.tsx b/web/src/components/settings/PolygonItem.tsx
index 54a6b41a2..af2e7813a 100644
--- a/web/src/components/settings/PolygonItem.tsx
+++ b/web/src/components/settings/PolygonItem.tsx
@@ -19,7 +19,7 @@ import { LuCopy, LuPencil } from "react-icons/lu";
import { FaDrawPolygon, FaObjectGroup } from "react-icons/fa";
import { BsPersonBoundingBox } from "react-icons/bs";
import { HiOutlineDotsVertical, HiTrash } from "react-icons/hi";
-import { isDesktop, isMobile } from "react-device-detect";
+import { isMobile } from "react-device-detect";
import { toRGBColorString } from "@/utils/canvasUtil";
import { Polygon, PolygonType } from "@/types/canvas";
import { useCallback, useMemo, useState } from "react";
@@ -524,7 +524,7 @@ export default function PolygonItem({
{isMobile && (
<>
-
+
diff --git a/web/src/components/settings/ProfileSectionDropdown.tsx b/web/src/components/settings/ProfileSectionDropdown.tsx
index cab681f46..923a37ebf 100644
--- a/web/src/components/settings/ProfileSectionDropdown.tsx
+++ b/web/src/components/settings/ProfileSectionDropdown.tsx
@@ -41,7 +41,7 @@ export function ProfileSectionDropdown({
: null;
return (
-
+
{iconOnly ? (
diff --git a/web/src/components/settings/wizard/Step1NameCamera.tsx b/web/src/components/settings/wizard/Step1NameCamera.tsx
index 741aa4b05..3e9c69ae1 100644
--- a/web/src/components/settings/wizard/Step1NameCamera.tsx
+++ b/web/src/components/settings/wizard/Step1NameCamera.tsx
@@ -377,7 +377,7 @@ export default function Step1NameCamera({
);
return selectedBrand &&
selectedBrand.value != "other" ? (
-
+
-
+
{t("cameraWizard.step3.roles")}
-
+
@@ -670,7 +667,7 @@ export default function Step3StreamConfig({
{t("cameraWizard.step3.featuresTitle")}
-
+
diff --git a/web/src/components/ws/WsMessageFeed.tsx b/web/src/components/ws/WsMessageFeed.tsx
index 0da86a108..47a3b41ae 100644
--- a/web/src/components/ws/WsMessageFeed.tsx
+++ b/web/src/components/ws/WsMessageFeed.tsx
@@ -351,7 +351,6 @@ function TopicFilterButton({
return (
{
if (!open) setCurrentTopics(selectedTopics);
@@ -517,7 +516,6 @@ function WsCamerasFilterButton({
return (
{
if (!open) setCurrentCameras(selectedCameras);
diff --git a/web/src/pages/FaceLibrary.tsx b/web/src/pages/FaceLibrary.tsx
index ee9213626..20763261c 100644
--- a/web/src/pages/FaceLibrary.tsx
+++ b/web/src/pages/FaceLibrary.tsx
@@ -594,7 +594,7 @@ function LibrarySelector({
forbiddenErrorMessage={t("description.nameCannotContainHash")}
/>
-
+
{pageTitle}
diff --git a/web/src/pages/Settings.tsx b/web/src/pages/Settings.tsx
index c74191957..3c6e4d83f 100644
--- a/web/src/pages/Settings.tsx
+++ b/web/src/pages/Settings.tsx
@@ -2018,7 +2018,6 @@ function CameraSelectButton({
return (
{
if (!open) {
diff --git a/web/src/views/classification/ModelSelectionView.tsx b/web/src/views/classification/ModelSelectionView.tsx
index 4b4ef492d..3cd450bba 100644
--- a/web/src/views/classification/ModelSelectionView.tsx
+++ b/web/src/views/classification/ModelSelectionView.tsx
@@ -342,7 +342,7 @@ function ModelCard({ config, onClick, onUpdate, onDelete }: ModelCardProps) {
{config.name}
-
+
e.stopPropagation()}>
diff --git a/web/src/views/classification/ModelTrainingView.tsx b/web/src/views/classification/ModelTrainingView.tsx
index 23fd6f374..dd4f3c9c0 100644
--- a/web/src/views/classification/ModelTrainingView.tsx
+++ b/web/src/views/classification/ModelTrainingView.tsx
@@ -698,7 +698,7 @@ function LibrarySelector({
regexErrorMessage={t("description.invalidName")}
/>
-
+
{pageTitle}
diff --git a/web/src/views/live/LiveCameraView.tsx b/web/src/views/live/LiveCameraView.tsx
index 629da6e57..49d0e70bf 100644
--- a/web/src/views/live/LiveCameraView.tsx
+++ b/web/src/views/live/LiveCameraView.tsx
@@ -1164,7 +1164,7 @@ function FrigateCameraFeatures({
loading={isSnapshotLoading}
/>
{!fullscreen && (
-
+
-
+
@@ -1641,7 +1641,7 @@ function FrigateCameraFeatures({
<>
{t("stream.audio.unavailable")}
-
+
@@ -1685,7 +1685,7 @@ function FrigateCameraFeatures({
<>
{t("stream.twoWayTalk.unavailable")}
-
+
diff --git a/web/src/views/motion-search/MotionSearchDialog.tsx b/web/src/views/motion-search/MotionSearchDialog.tsx
index ee8652b5e..c5f3274be 100644
--- a/web/src/views/motion-search/MotionSearchDialog.tsx
+++ b/web/src/views/motion-search/MotionSearchDialog.tsx
@@ -598,7 +598,6 @@ function SearchRangeSelector({
setStartOpen(false);
}
}}
- modal={false}
>
-
+
-
+