mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
fix(desktop): dedupe react-dismissable-layer to stop modal menu → dialog freezes (#1899)
Signed-off-by: Matt Toohey <contact@matttoohey.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,7 @@ export default defineConfig({
|
||||
"**/threadpane-ultrawide.spec.ts",
|
||||
"**/animated-avatar.spec.ts",
|
||||
"**/reminders.spec.ts",
|
||||
"**/reminder-click-repro.spec.ts",
|
||||
"**/virtualization.spec.ts",
|
||||
"**/scroll-history.spec.ts",
|
||||
"**/channel-dense-second-reach.spec.ts",
|
||||
|
||||
@@ -411,11 +411,7 @@ export function ChannelGroupSection({
|
||||
items.length > 0 ? (
|
||||
<SidebarMenu data-testid={listTestId}>
|
||||
{items.map((channel) => (
|
||||
// modal={false}: menu items (e.g. Leave channel) open a modal
|
||||
// AlertDialog. A modal ContextMenu would leave `pointer-events: none`
|
||||
// stuck on <body> when it closes as the dialog mounts, freezing the
|
||||
// whole app. Non-modal avoids installing that body guard entirely.
|
||||
<ContextMenu key={channel.id} modal={false}>
|
||||
<ContextMenu key={channel.id}>
|
||||
<ContextMenuTrigger asChild>
|
||||
<SidebarMenuItem className="content-visibility-auto-row">
|
||||
{draggable ? (
|
||||
@@ -610,10 +606,7 @@ export function CustomChannelSection({
|
||||
)}
|
||||
data-section-actions-open={actionsMenuOpen || undefined}
|
||||
>
|
||||
{/* modal={false}: Rename/Delete section open a modal dialog;
|
||||
a modal ContextMenu would leave `pointer-events: none` stuck on
|
||||
<body> after it closes, freezing the app. */}
|
||||
<ContextMenu modal={false}>
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger asChild>
|
||||
<div className="relative" {...dragHandleProps}>
|
||||
<SidebarGroupLabel asChild>
|
||||
@@ -702,10 +695,7 @@ export function CustomChannelSection({
|
||||
{channels.length > 0 ? (
|
||||
<SidebarMenu>
|
||||
{channels.map((channel) => (
|
||||
// modal={false}: see note on the other channel ContextMenu
|
||||
// above — avoids the pointer-events lockup when Leave
|
||||
// channel's AlertDialog opens.
|
||||
<ContextMenu key={channel.id} modal={false}>
|
||||
<ContextMenu key={channel.id}>
|
||||
<ContextMenuTrigger asChild>
|
||||
<SidebarMenuItem>
|
||||
<DraggableChannelRow channelId={channel.id}>
|
||||
|
||||
144
desktop/tests/e2e/reminder-click-repro.spec.ts
Normal file
144
desktop/tests/e2e/reminder-click-repro.spec.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
import { waitForAnimations } from "../helpers/animations";
|
||||
import { installMockBridge } from "../helpers/bridge";
|
||||
|
||||
/**
|
||||
* Regression suite for the "app freezes after setting a reminder" bug.
|
||||
*
|
||||
* The app used to bundle two copies of @radix-ui/react-dismissable-layer
|
||||
* (react-menu resolved 1.1.11 while react-dialog resolved 1.1.15). Each copy
|
||||
* keeps its own module-level `originalBodyPointerEvents`, so when a *modal*
|
||||
* menu opened a *modal* dialog in the same React commit, the dialog's copy
|
||||
* saved the menu's `pointer-events: none` as the "original" body style and
|
||||
* restored it when the dialog closed — leaving `pointer-events: none` stuck
|
||||
* on <body> and deadening the whole app to the mouse.
|
||||
*
|
||||
* The inbox row context menu hit this: its "Remind me later" item opens
|
||||
* RemindMeLaterDialog synchronously. Fixed by deduplicating the layer via
|
||||
* the pnpm override in pnpm-workspace.yaml — a single copy coordinates
|
||||
* nested modal layers correctly, so the menu keeps its default modal
|
||||
* behavior.
|
||||
*
|
||||
* Each test drives one reminder entry point through a full set-reminder
|
||||
* cycle, then asserts <body> pointer-events is not stuck and that a real
|
||||
* click still lands. The inbox right-click test fails if the dismissable
|
||||
* layer ever duplicates again; the message-menu tests pin the already-safe
|
||||
* paths.
|
||||
*/
|
||||
|
||||
const GENERAL_MESSAGE_ROW = "message-row";
|
||||
// The default mock feed's mention row (from alice, in #general) has a
|
||||
// channel target, so its "Remind me later" context-menu item is enabled.
|
||||
const INBOX_MENTION_ROW = "home-inbox-item-mock-feed-mention";
|
||||
|
||||
/**
|
||||
* Assert the app survived the menu → dialog → close cycle.
|
||||
*
|
||||
* The stuck state is inline `pointer-events: none` left on <body>. The buggy
|
||||
* restore runs when the dialog's dismissable layer unmounts — after its exit
|
||||
* animation — so first wait for the dialog to leave the DOM, then check the
|
||||
* body style, then prove clicks still land by navigating via the sidebar.
|
||||
*/
|
||||
async function expectAppAliveAfterDialogClose(
|
||||
page: import("@playwright/test").Page,
|
||||
) {
|
||||
await expect(page.getByRole("dialog")).toHaveCount(0);
|
||||
await waitForAnimations(page);
|
||||
expect(await page.evaluate(() => document.body.style.pointerEvents)).not.toBe(
|
||||
"none",
|
||||
);
|
||||
await page.getByTestId("channel-random").click();
|
||||
await expect(page.getByTestId("chat-title")).toHaveText("random");
|
||||
}
|
||||
|
||||
/** Open the Remind-me-later dialog from a message row's More-actions menu. */
|
||||
async function openReminderDialogFromMessageMenu(
|
||||
page: import("@playwright/test").Page,
|
||||
) {
|
||||
await page.goto("/");
|
||||
await page.getByTestId("channel-general").click();
|
||||
await expect(page.getByTestId("chat-title")).toHaveText("general");
|
||||
|
||||
const messageRow = page.getByTestId(GENERAL_MESSAGE_ROW).first();
|
||||
await messageRow.hover();
|
||||
await messageRow.getByRole("button", { name: "More actions" }).click();
|
||||
|
||||
const remindItem = page.getByRole("menuitem", { name: "Remind me later" });
|
||||
await expect(remindItem).toBeVisible();
|
||||
await waitForAnimations(page);
|
||||
await remindItem.click();
|
||||
|
||||
const dialog = page.getByRole("dialog");
|
||||
await expect(dialog).toBeVisible();
|
||||
await waitForAnimations(page);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
async function expectReminderSetToast(page: import("@playwright/test").Page) {
|
||||
await expect(
|
||||
page.locator("[data-sonner-toast]").filter({ hasText: "Reminder set" }),
|
||||
).toBeVisible();
|
||||
}
|
||||
|
||||
test.describe("reminder set → app stays clickable", () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await installMockBridge(page);
|
||||
});
|
||||
|
||||
test("01 — message menu → time preset", async ({ page }) => {
|
||||
const dialog = await openReminderDialogFromMessageMenu(page);
|
||||
|
||||
await dialog.getByRole("button", { name: "In 30 minutes" }).click();
|
||||
|
||||
await expectReminderSetToast(page);
|
||||
await expectAppAliveAfterDialogClose(page);
|
||||
});
|
||||
|
||||
test("02 — message menu → custom time via Set reminder footer button", async ({
|
||||
page,
|
||||
}) => {
|
||||
const dialog = await openReminderDialogFromMessageMenu(page);
|
||||
|
||||
// The custom timestamp must be strictly in the future or the Set
|
||||
// reminder button stays disabled — pick tomorrow at 09:00 local time.
|
||||
const tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000);
|
||||
const date = [
|
||||
tomorrow.getFullYear(),
|
||||
String(tomorrow.getMonth() + 1).padStart(2, "0"),
|
||||
String(tomorrow.getDate()).padStart(2, "0"),
|
||||
].join("-");
|
||||
await dialog.getByLabel("Reminder date").fill(date);
|
||||
await dialog.getByLabel("Reminder time").fill("09:00");
|
||||
await dialog.getByRole("button", { name: "Set reminder" }).click();
|
||||
|
||||
await expectReminderSetToast(page);
|
||||
await expectAppAliveAfterDialogClose(page);
|
||||
});
|
||||
|
||||
// The regression path: only the inbox right-click stacks a modal
|
||||
// ContextMenu under the modal dialog. Fails if two copies of the
|
||||
// dismissable layer are ever bundled again — body pointer-events stays
|
||||
// "none" after the dialog closes and the sidebar click below times out.
|
||||
test("03 — inbox row right-click → Remind me later", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await expect(page.getByTestId("home-inbox")).toBeVisible();
|
||||
|
||||
const row = page.getByTestId(INBOX_MENTION_ROW);
|
||||
await expect(row).toBeVisible();
|
||||
await row.click({ button: "right" });
|
||||
|
||||
const remindItem = page.getByRole("menuitem", { name: "Remind me later" });
|
||||
await expect(remindItem).toBeVisible();
|
||||
await waitForAnimations(page);
|
||||
await remindItem.click();
|
||||
|
||||
const dialog = page.getByRole("dialog");
|
||||
await expect(dialog).toBeVisible();
|
||||
await waitForAnimations(page);
|
||||
await dialog.getByRole("button", { name: "In 30 minutes" }).click();
|
||||
|
||||
await expectReminderSetToast(page);
|
||||
await expectAppAliveAfterDialogClose(page);
|
||||
});
|
||||
});
|
||||
@@ -22,10 +22,12 @@ async function storedSidebarWidth(page: Page) {
|
||||
);
|
||||
}
|
||||
|
||||
// Regression guard for the "Leave channel" lockup: opening a modal AlertDialog
|
||||
// from a modal Radix ContextMenu leaves `pointer-events: none` stuck on <body>
|
||||
// after the dialog closes, freezing the whole app. The fix makes the sidebar
|
||||
// context menus non-modal. This asserts the app is still interactive.
|
||||
// Regression guard for the "Leave channel" lockup: with two bundled copies of
|
||||
// @radix-ui/react-dismissable-layer, opening a modal AlertDialog from a modal
|
||||
// Radix ContextMenu left `pointer-events: none` stuck on <body> after the
|
||||
// dialog closed, freezing the whole app. Fixed by the pnpm override in
|
||||
// pnpm-workspace.yaml deduplicating the layer. This asserts the app is still
|
||||
// interactive.
|
||||
async function expectAppClickable(page: Page) {
|
||||
await expect
|
||||
.poll(() =>
|
||||
|
||||
92
pnpm-lock.yaml
generated
92
pnpm-lock.yaml
generated
@@ -4,6 +4,9 @@ settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
overrides:
|
||||
'@radix-ui/react-dismissable-layer': 1.1.15
|
||||
|
||||
patchedDependencies:
|
||||
isomorphic-git: e9b414a60d4cf1d8aa18f7a779483984e821989967c235662566e94ef0238d3f
|
||||
virtua@0.49.3: 367ec28b983b840021685fb5b515df23616a4d9b500614483ada43907c1e14e2
|
||||
@@ -72,7 +75,7 @@ importers:
|
||||
version: 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
'@radix-ui/react-slot':
|
||||
specifier: ^1.2.4
|
||||
version: 1.2.5(@types/react@19.2.17)(react@19.2.7)
|
||||
version: 1.3.0(@types/react@19.2.17)(react@19.2.7)
|
||||
'@radix-ui/react-switch':
|
||||
specifier: ^1.2.6
|
||||
version: 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
@@ -250,7 +253,7 @@ importers:
|
||||
version: 4.6.2
|
||||
'@radix-ui/react-slot':
|
||||
specifier: ^1.2.4
|
||||
version: 1.2.5(@types/react@19.2.17)(react@19.2.7)
|
||||
version: 1.3.0(@types/react@19.2.17)(react@19.2.7)
|
||||
'@radix-ui/react-tooltip':
|
||||
specifier: ^1.2.8
|
||||
version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
@@ -455,21 +458,18 @@ packages:
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@biomejs/cli-linux-x64-musl@2.4.16':
|
||||
resolution: {integrity: sha512-iHDS+MCM65DPqWGu+ECC3uoALyj2H7F4nVUPxIPjz/PIl94EUu+EDfGZDzFP+NY1EOPVt9NQvwFqq7HdMmowdg==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@biomejs/cli-linux-x64@2.4.16':
|
||||
resolution: {integrity: sha512-NbcBbi/nJqn5baae6wqRXdS7Gadf2uRpehSh6vMSYpG8OhkXl/Xg8aorWrJ+9VWqAT5ml90alLvorkpMW0nBwQ==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@biomejs/cli-win32-arm64@2.4.16':
|
||||
resolution: {integrity: sha512-0rgImMsNb5v/chhkIFe3wu7PEFClS6RBAYUijGL9UsYN3PanSaoK24HSSuSJb1pYbYYVjzAyZTl3gtjJ84BM8A==}
|
||||
@@ -523,15 +523,9 @@ packages:
|
||||
emoji-mart: ^5.2
|
||||
react: ^16.8 || ^17 || ^18
|
||||
|
||||
'@floating-ui/core@1.7.5':
|
||||
resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==}
|
||||
|
||||
'@floating-ui/core@1.8.0':
|
||||
resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==}
|
||||
|
||||
'@floating-ui/dom@1.7.6':
|
||||
resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==}
|
||||
|
||||
'@floating-ui/dom@1.8.0':
|
||||
resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==}
|
||||
|
||||
@@ -541,9 +535,6 @@ packages:
|
||||
react: '>=16.8.0'
|
||||
react-dom: '>=16.8.0'
|
||||
|
||||
'@floating-ui/utils@0.2.11':
|
||||
resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
|
||||
|
||||
'@floating-ui/utils@0.2.12':
|
||||
resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
|
||||
|
||||
@@ -792,19 +783,6 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.1.11':
|
||||
resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==}
|
||||
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
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.1.15':
|
||||
resolution: {integrity: sha512-b0XaRlzn2QKuo10XyNgi2DAJDf5XC9d1nD3FJcuvCjbR7+4Ad28zmZsLsqx+hvDEzMnRuZaZxZm9gYObV6RmRA==}
|
||||
peerDependencies:
|
||||
@@ -1221,15 +1199,6 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-escape-keydown@1.1.1':
|
||||
resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-is-hydrated@0.1.1':
|
||||
resolution: {integrity: sha512-qwOiz4Tjo8CNnrOLAYUMXeZwDzXgXpvK4TKQPmWLECM9XoWvA6+0Z2/7Ag3A4ivjS4ovbLJPbskkxioFyBhr8A==}
|
||||
peerDependencies:
|
||||
@@ -1365,21 +1334,18 @@ packages:
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-arm64-musl@1.0.2':
|
||||
resolution: {integrity: sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rolldown/binding-linux-ppc64-gnu@1.0.2':
|
||||
resolution: {integrity: sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-s390x-gnu@1.0.2':
|
||||
resolution: {integrity: sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==}
|
||||
@@ -1393,7 +1359,6 @@ packages:
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-x64-musl@1.0.2':
|
||||
resolution: {integrity: sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==}
|
||||
@@ -1513,21 +1478,18 @@ packages:
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.3.0':
|
||||
resolution: {integrity: sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.3.0':
|
||||
resolution: {integrity: sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.3.0':
|
||||
resolution: {integrity: sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==}
|
||||
@@ -1665,7 +1627,6 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tauri-apps/cli-linux-arm64-musl@2.11.2':
|
||||
resolution: {integrity: sha512-X1rm0BERqAAggtYTESSgXrS3sz4Sb/OiPiz54UqISlXW+GkR3vNIGnsy/lejNmoXGVqri3Q53BCfQiclOIyRPw==}
|
||||
@@ -1693,7 +1654,6 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tauri-apps/cli-win32-arm64-msvc@2.11.2':
|
||||
resolution: {integrity: sha512-HeeZW80jU+gVTOEX4X/hC6NVSAdDVXajwP5fxIZ/3z9WvUC7qrudX2GMTilYq6Dg0e0sk0XgsAJD1hZ5wPBXUA==}
|
||||
@@ -2403,7 +2363,6 @@ packages:
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-arm64-musl@1.32.0:
|
||||
resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
|
||||
@@ -2417,7 +2376,6 @@ packages:
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-x64-musl@1.32.0:
|
||||
resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
|
||||
@@ -3134,7 +3092,7 @@ packages:
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
|
||||
|
||||
yallist@3.1.1:
|
||||
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
||||
@@ -3349,21 +3307,10 @@ snapshots:
|
||||
emoji-mart: 5.6.0
|
||||
react: 19.2.7
|
||||
|
||||
'@floating-ui/core@1.7.5':
|
||||
dependencies:
|
||||
'@floating-ui/utils': 0.2.11
|
||||
optional: true
|
||||
|
||||
'@floating-ui/core@1.8.0':
|
||||
dependencies:
|
||||
'@floating-ui/utils': 0.2.12
|
||||
|
||||
'@floating-ui/dom@1.7.6':
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.7.5
|
||||
'@floating-ui/utils': 0.2.11
|
||||
optional: true
|
||||
|
||||
'@floating-ui/dom@1.8.0':
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.8.0
|
||||
@@ -3375,9 +3322,6 @@ snapshots:
|
||||
react: 19.2.7
|
||||
react-dom: 19.2.7(react@19.2.7)
|
||||
|
||||
'@floating-ui/utils@0.2.11':
|
||||
optional: true
|
||||
|
||||
'@floating-ui/utils@0.2.12': {}
|
||||
|
||||
'@fontsource-variable/inter@5.2.8': {}
|
||||
@@ -3601,19 +3545,6 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.17
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.3
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7)
|
||||
'@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.17)(react@19.2.7)
|
||||
react: 19.2.7
|
||||
react-dom: 19.2.7(react@19.2.7)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.17
|
||||
'@types/react-dom': 19.2.3(@types/react@19.2.17)
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.5
|
||||
@@ -3697,7 +3628,7 @@ snapshots:
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7)
|
||||
'@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7)
|
||||
'@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
'@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
'@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.17)(react@19.2.7)
|
||||
'@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
'@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7)
|
||||
@@ -4037,13 +3968,6 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.17
|
||||
|
||||
'@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.17)(react@19.2.7)':
|
||||
dependencies:
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7)
|
||||
react: 19.2.7
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.17
|
||||
|
||||
'@radix-ui/react-use-is-hydrated@0.1.1(@types/react@19.2.17)(react@19.2.7)':
|
||||
dependencies:
|
||||
react: 19.2.7
|
||||
@@ -4464,7 +4388,7 @@ snapshots:
|
||||
|
||||
'@tiptap/extension-bubble-menu@3.22.5(@tiptap/core@3.22.5(@tiptap/pm@3.22.5))(@tiptap/pm@3.22.5)':
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.7.6
|
||||
'@floating-ui/dom': 1.8.0
|
||||
'@tiptap/core': 3.22.5(@tiptap/pm@3.22.5)
|
||||
'@tiptap/pm': 3.22.5
|
||||
optional: true
|
||||
|
||||
@@ -3,6 +3,14 @@ packages:
|
||||
- "web"
|
||||
allowBuilds:
|
||||
esbuild: true
|
||||
overrides:
|
||||
# Force a single copy of the dismissable-layer. Radix packages otherwise
|
||||
# resolve different versions (react-menu pulled 1.1.11, react-dialog 1.1.15),
|
||||
# and each copy keeps its own module-level saved <body> pointer-events style —
|
||||
# so a modal menu opening a modal dialog left `pointer-events: none` stuck on
|
||||
# <body> when the dialog closed, freezing the app (#1482, reminder dialog).
|
||||
# Removable once every @radix-ui dep converges on one version naturally.
|
||||
"@radix-ui/react-dismissable-layer": 1.1.15
|
||||
patchedDependencies:
|
||||
isomorphic-git: patches/isomorphic-git.patch
|
||||
virtua@0.49.3: patches/virtua@0.49.3.patch
|
||||
|
||||
Reference in New Issue
Block a user