mirror of
https://github.com/zadam/trilium.git
synced 2026-03-13 11:53:38 +01:00
fix(spreadsheet): popups show up and hide
This commit is contained in:
parent
dc7b91433b
commit
aa2d8af15c
@ -43,6 +43,7 @@ function SpreadsheetEditor({ note, noteContext, readOnly }: TypeWidgetProps & {
|
||||
useDarkMode(apiRef);
|
||||
usePersistence(note, noteContext, apiRef, containerRef, readOnly);
|
||||
useSearchIntegration(apiRef);
|
||||
useFixRadixPortals();
|
||||
|
||||
// Focus the spreadsheet when the note is focused.
|
||||
useTriliumEvent("focusOnDetail", () => {
|
||||
@ -55,6 +56,53 @@ function SpreadsheetEditor({ note, noteContext, readOnly }: TypeWidgetProps & {
|
||||
return <div ref={containerRef} className="spreadsheet" />;
|
||||
}
|
||||
|
||||
/**
|
||||
* Univer's design system uses Radix UI primitives whose DismissableLayer detects
|
||||
* "outside" clicks/focus via document-level pointerdown/focusin listeners combined
|
||||
* with a React capture-phase flag. In React, portal events bubble through the
|
||||
* component tree so onPointerDownCapture fires on the DismissableLayer, setting an
|
||||
* internal flag that suppresses the "outside" detection. With preact/compat, portal
|
||||
* events don't bubble through the React tree, so the flag never gets set and Radix
|
||||
* immediately dismisses popups.
|
||||
*
|
||||
* Radix dispatches cancelable custom events ("dismissableLayer.pointerDownOutside"
|
||||
* and "dismissableLayer.focusOutside") on the original event target before calling
|
||||
* onDismiss. The dismiss is skipped if defaultPrevented is true. This hook intercepts
|
||||
* those custom events in the capture phase and prevents default when the target is
|
||||
* inside a Radix portal, restoring the expected behavior.
|
||||
*/
|
||||
function useFixRadixPortals() {
|
||||
useEffect(() => {
|
||||
function isInsideUniverPortal(target: HTMLElement): boolean {
|
||||
// Check for Radix content wrappers (covers most popover/menu portals).
|
||||
if (target.closest("[data-radix-popper-content-wrapper]") || target.closest("[data-radix-menu-content]")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Some Univer portals (e.g. nested color picker) don't use a Radix
|
||||
// wrapper. Fall back to checking if the element has Univer classes.
|
||||
if (target.className?.includes("univer-")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function preventDismiss(e: Event) {
|
||||
if (e.target instanceof HTMLElement && isInsideUniverPortal(e.target)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("dismissableLayer.pointerDownOutside", preventDismiss, true);
|
||||
document.addEventListener("dismissableLayer.focusOutside", preventDismiss, true);
|
||||
return () => {
|
||||
document.removeEventListener("dismissableLayer.pointerDownOutside", preventDismiss, true);
|
||||
document.removeEventListener("dismissableLayer.focusOutside", preventDismiss, true);
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
|
||||
function useInitializeSpreadsheet(containerRef: MutableRef<HTMLDivElement | null>, apiRef: MutableRef<FUniver | undefined>, readOnly: boolean) {
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user