cursedbelt 5.15.1 → 5.15.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { type VariantProps } from 'class-variance-authority';
2
- import { type ButtonHTMLAttributes, type MouseEvent, type ReactNode } from 'react';
2
+ import { type ButtonHTMLAttributes, type MouseEvent, type ReactNode, type Ref } from 'react';
3
3
  import { type TooltipMobile, type TooltipPlacement } from './Tooltip.js';
4
4
  /**
5
5
  * The single source of truth for every interactive element that triggers an action.
@@ -69,6 +69,13 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, Va
69
69
  /** How long the post-completion checkmark flash shows (ms). Default 1200. */
70
70
  resetMs?: number;
71
71
  children?: ReactNode;
72
+ /**
73
+ * The rendered `<button>` (or the `asChild` element). React 19 passes `ref` as an ordinary
74
+ * prop and this component already spreads it onto the element — the type is what was
75
+ * missing, so a caller that needed the node (a `useOutsidePress` toggle, a focus return)
76
+ * could not ask for it without a cast.
77
+ */
78
+ ref?: Ref<HTMLButtonElement>;
72
79
  }
73
80
  export declare function Button({ className, variant, size, asChild, loading, leftIcon, tooltip, tooltipSide, tooltipMobile, onAsyncClick, successMessage, errorMessage, resetMs, type, children, disabled, onClick, ...props }: ButtonProps): import("react").JSX.Element;
74
81
  //# sourceMappingURL=Button.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/react/components/Button.tsx"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAoB,KAAK,oBAAoB,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGrG,OAAO,EAAW,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGlF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc;;;8EAkF1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AACxF,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAElF,MAAM,WAAW,WACf,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC,EAC7C,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC;;;8CAG0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;6EACyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;;;eAQW;IACX,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,GAAG,SAAS,CAAC,CAAC;IAC9C,8EAA8E;IAC9E,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B;;;6DAGyD;IACzD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE;yFACqF;IACrF,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAClC;gFAC4E;IAC5E,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAChC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,MAAM,CAAC,EACrB,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAe,EACf,OAAe,EACf,QAAQ,EACR,OAAO,EACP,WAAW,EACX,aAAa,EACb,YAAY,EACZ,cAAsB,EACtB,YAAmB,EACnB,OAAc,EACd,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,GAAG,KAAK,EACT,EAAE,WAAW,+BAyEb"}
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/react/components/Button.tsx"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAoB,MAAM,OAAO,CAAC;AAG/G,OAAO,EAAW,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGlF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc;;;8EAkF1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AACxF,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAElF,MAAM,WAAW,WACf,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC,EAC7C,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC;;;8CAG0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;6EACyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;;;eAQW;IACX,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,GAAG,SAAS,CAAC,CAAC;IAC9C,8EAA8E;IAC9E,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B;;;6DAGyD;IACzD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE;yFACqF;IACrF,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAClC;gFAC4E;IAC5E,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAChC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC;CAC9B;AAED,wBAAgB,MAAM,CAAC,EACrB,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAe,EACf,OAAe,EACf,QAAQ,EACR,OAAO,EACP,WAAW,EACX,aAAa,EACb,YAAY,EACZ,cAAsB,EACtB,YAAmB,EACnB,OAAc,EACd,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,GAAG,KAAK,EACT,EAAE,WAAW,+BAyEb"}
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../src/react/components/Button.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../src/react/components/Button.tsx"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from 'react';
1
+ import { type ReactNode } from 'react';
2
2
  export interface DropdownMenuAction {
3
3
  key: string;
4
4
  label: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../../src/react/components/DropdownMenu.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUvC,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,gEAAgE;AAChE,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,IAAI,CAAC;IACd;qFACiF;IACjF,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,SAAS,CAAC;IACnB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,KAAK,EACL,KAAe,EACf,IAAe,EACf,SAAS,EACT,IAAI,EACJ,YAAY,GACb,EAAE,iBAAiB,+BAqBnB"}
1
+ {"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../../src/react/components/DropdownMenu.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAiC,MAAM,OAAO,CAAC;AAWtE,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,gEAAgE;AAChE,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,IAAI,CAAC;IACd;qFACiF;IACjF,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,SAAS,CAAC;IACnB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,KAAK,EACL,KAAe,EACf,IAAe,EACf,SAAS,EACT,IAAI,EACJ,YAAY,GACb,EAAE,iBAAiB,+BAiDnB"}
@@ -1,6 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as RDrop from '@radix-ui/react-dropdown-menu';
3
3
  import { Check, ChevronRight } from 'lucide-react';
4
+ import { useCallback, useRef, useState } from 'react';
5
+ import { useOutsidePress } from '../hooks/useOutsidePress.js';
4
6
  import { cn } from '../lib/cn.js';
5
7
  import { useFloatingContainer } from '../lib/floatingContainer.js';
6
8
  import { FLOATING_ANIMATION, FLOATING_COLLISION_PADDING, FLOATING_CONTENT_BASE, FLOATING_ITEM_BASE, } from '../lib/floatingStyles.js';
@@ -15,7 +17,29 @@ import { FLOATING_ANIMATION, FLOATING_COLLISION_PADDING, FLOATING_CONTENT_BASE,
15
17
  */
16
18
  export function DropdownMenu({ trigger, items, align = 'start', side = 'bottom', className, open, onOpenChange, }) {
17
19
  const container = useFloatingContainer();
18
- return (_jsxs(RDrop.Root, { open: open, onOpenChange: onOpenChange, children: [_jsx(RDrop.Trigger, { asChild: true, children: trigger }), _jsx(RDrop.Portal, { container: container, children: _jsxs(RDrop.Content, { align: align, side: side, sideOffset: 4, collisionPadding: FLOATING_COLLISION_PADDING, className: cn(FLOATING_CONTENT_BASE, FLOATING_ANIMATION, 'min-w-[8rem] p-1', className), children: [items.map((item) => (_jsx(DropdownItem, { item: item }, item.key))), _jsx(RDrop.Arrow, { className: 'fill-border' })] }) })] }));
20
+ // Always controlled underneath, so the outside-press fallback can close it too.
21
+ const [ownOpen, setOwnOpen] = useState(false);
22
+ const isOpen = open ?? ownOpen;
23
+ const setOpen = useCallback((next) => {
24
+ if (open === undefined)
25
+ setOwnOpen(next);
26
+ onOpenChange?.(next);
27
+ }, [open, onOpenChange]);
28
+ /*
29
+ * Radix's menu listens for the outside `pointerdown` in the BUBBLE phase, so a surface that
30
+ * stops its own pointerdown (a drag handle, a canvas) kept the menu open. The belt's one
31
+ * tap-away listener runs in the capture phase; see `useOutsidePress`. The menu is modal, so
32
+ * it decides on the pointerdown (an inert page sends an iPhone no click).
33
+ */
34
+ const triggerRef = useRef(null);
35
+ const pressInside = useOutsidePress({
36
+ open: isOpen,
37
+ onDismiss: () => setOpen(false),
38
+ inside: [triggerRef],
39
+ escape: false,
40
+ decideOn: 'pointerdown',
41
+ });
42
+ return (_jsxs(RDrop.Root, { open: isOpen, onOpenChange: setOpen, children: [_jsx(RDrop.Trigger, { asChild: true, ref: triggerRef, children: trigger }), _jsx(RDrop.Portal, { container: container, children: _jsxs(RDrop.Content, { align: align, side: side, sideOffset: 4, collisionPadding: FLOATING_COLLISION_PADDING, onClickCapture: pressInside.onClickCapture, onPointerDownCapture: pressInside.onPointerDownCapture, className: cn(FLOATING_CONTENT_BASE, FLOATING_ANIMATION, 'min-w-[8rem] p-1', className), children: [items.map((item) => (_jsx(DropdownItem, { item: item }, item.key))), _jsx(RDrop.Arrow, { className: 'fill-border' })] }) })] }));
19
43
  }
20
44
  function DropdownItem({ item }) {
21
45
  const container = useFloatingContainer();
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.js","sourceRoot":"","sources":["../../../src/react/components/DropdownMenu.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DropdownMenu.js","sourceRoot":"","sources":["../../../src/react/components/DropdownMenu.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../../../src/react/components/Popover.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAA0C,MAAM,OAAO,CAAC;AAU/E;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,uFAAuF;IACvF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAAC;IACvC,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,2FAA2F;IAC3F,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;CACtC;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,YAAY,EACZ,KAAe,EACf,IAAe,EACf,UAAc,EACd,KAAK,EACL,KAAK,EACL,SAAS,EACT,QAAgB,EAChB,KAAa,EACb,MAAa,EACb,SAAgB,EAChB,KAAK,EACL,IAAI,GACL,EAAE,YAAY,+BAuFd;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAEjE"}
1
+ {"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../../../src/react/components/Popover.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAA0C,MAAM,OAAO,CAAC;AAU/E;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,uFAAuF;IACvF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAAC;IACvC,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,2FAA2F;IAC3F,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;CACtC;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,YAAY,EACZ,KAAe,EACf,IAAe,EACf,UAAc,EACd,KAAK,EACL,KAAK,EACL,SAAS,EACT,QAAgB,EAChB,KAAa,EACb,MAAa,EACb,SAAgB,EAChB,KAAK,EACL,IAAI,GACL,EAAE,YAAY,+BA2Fd;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAEjE"}
@@ -60,6 +60,9 @@ export function Popover({ trigger, anchor, children, open, onOpenChange, align =
60
60
  onDismiss: () => setOpen(false),
61
61
  inside: [triggerRef, anchorTrigger],
62
62
  escape: false,
63
+ // Under `modal` the page is inert and an iPhone sends no click for a tap on it — see
64
+ // `decideOn` in useOutsidePress.
65
+ decideOn: modal ? 'pointerdown' : 'click',
63
66
  });
64
67
  const content = (_jsxs(RPopover.Content, { align: align, side: side, sideOffset: sideOffset, collisionPadding: FLOATING_COLLISION_PADDING, style: width != null ? { width } : undefined, "aria-label": label, ...(role ? { role } : {}), onOpenAutoFocus: autoFocus ? undefined : (event) => event.preventDefault(), onInteractOutside: (event) => {
65
68
  // The anchor's own control decides open/shut with its click — see PopoverPoint.
@@ -68,7 +71,7 @@ export function Popover({ trigger, anchor, children, open, onOpenChange, align =
68
71
  },
69
72
  // React-tree capture: a press on a nested layer this panel portalled (a Select's
70
73
  // list, a sub-menu) is INSIDE even though the DOM puts it elsewhere.
71
- onClickCapture: pressInside.onClickCapture, className: cn(unstyled
74
+ onClickCapture: pressInside.onClickCapture, onPointerDownCapture: pressInside.onPointerDownCapture, className: cn(unstyled
72
75
  ? 'z-[var(--z-popover)] outline-none'
73
76
  : cn(FLOATING_CONTENT_BASE, 'p-3'), FLOATING_ANIMATION, className), children: [children, showArrow && _jsx(RPopover.Arrow, { className: 'fill-border' })] }));
74
77
  return (_jsxs(RPopover.Root, { open: isOpen, onOpenChange: setOpen, modal: modal, children: [virtualRef ? _jsx(RPopover.Anchor, { virtualRef: virtualRef }) : null, trigger !== undefined ? (_jsx(RPopover.Trigger, { asChild: true, ref: triggerRef, children: trigger })) : null, portal ? _jsx(RPopover.Portal, { container: container, children: content }) : content] }));
@@ -1 +1 @@
1
- {"version":3,"file":"Popover.js","sourceRoot":"","sources":["../../../src/react/components/Popover.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Popover.js","sourceRoot":"","sources":["../../../src/react/components/Popover.tsx"],"names":[],"mappings":"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"}
@@ -19,6 +19,17 @@ export interface UseOutsidePressOptions {
19
19
  * whose rows play on tap). Default false.
20
20
  */
21
21
  modal?: boolean;
22
+ /**
23
+ * Decide on the `pointerdown` rather than the `click`. Only for a panel that has made the
24
+ * page under it inert (`Popover`'s `modal`, which sets `pointer-events: none` on body).
25
+ *
26
+ * 🔴 Measured 2026-09-27 in Playwright's iPhone 15 WebKit: with the page inert, a tap
27
+ * outside hits `<html>`, which iOS does not consider clickable, so NO `click` is ever
28
+ * sent — the menu stayed open under the owner's finger, exactly as reported. Deciding on
29
+ * the pointerdown closes it; the `click` that same press may still produce is swallowed,
30
+ * or it would land on whatever the closed menu uncovered (the picture, which pauses).
31
+ */
32
+ decideOn?: 'click' | 'pointerdown';
22
33
  }
23
34
  /**
24
35
  * Close a panel when the reader presses anywhere else — the ONE implementation of it in the
@@ -41,8 +52,9 @@ export interface UseOutsidePressOptions {
41
52
  * · **the toggle is inside**, or pressing an open menu's own button shuts it and reopens
42
53
  * it a frame later — the "menu that ignores the second press" desk hit on 2026-09-07.
43
54
  */
44
- export declare function useOutsidePress({ open, onDismiss, inside, escape: closeOnEscape, modal, }: UseOutsidePressOptions): {
55
+ export declare function useOutsidePress({ open, onDismiss, inside, escape: closeOnEscape, modal, decideOn, }: UseOutsidePressOptions): {
45
56
  onClickCapture: () => void;
57
+ onPointerDownCapture: () => void;
46
58
  };
47
59
  export {};
48
60
  //# sourceMappingURL=useOutsidePress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useOutsidePress.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useOutsidePress.ts"],"names":[],"mappings":"AAEA,KAAK,YAAY,GAAG;IAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,sBAAsB;IACrC,+BAA+B;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,+EAA+E;IAC/E,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,4CAA4C;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAUD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,SAAS,EACT,MAAW,EACX,MAAM,EAAE,aAAoB,EAC5B,KAAa,GACd,EAAE,sBAAsB,GAAG;IAAE,cAAc,EAAE,MAAM,IAAI,CAAA;CAAE,CA8DzD"}
1
+ {"version":3,"file":"useOutsidePress.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useOutsidePress.ts"],"names":[],"mappings":"AAEA,KAAK,YAAY,GAAG;IAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,sBAAsB;IACrC,+BAA+B;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,+EAA+E;IAC/E,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,4CAA4C;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;CACpC;AAUD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,SAAS,EACT,MAAW,EACX,MAAM,EAAE,aAAoB,EAC5B,KAAa,EACb,QAAkB,GACnB,EAAE,sBAAsB,GAAG;IAAE,cAAc,EAAE,MAAM,IAAI,CAAC;IAAC,oBAAoB,EAAE,MAAM,IAAI,CAAA;CAAE,CAuF3F"}
@@ -25,7 +25,7 @@ function resolve(target) {
25
25
  * · **the toggle is inside**, or pressing an open menu's own button shuts it and reopens
26
26
  * it a frame later — the "menu that ignores the second press" desk hit on 2026-09-07.
27
27
  */
28
- export function useOutsidePress({ open, onDismiss, inside = [], escape: closeOnEscape = true, modal = false, }) {
28
+ export function useOutsidePress({ open, onDismiss, inside = [], escape: closeOnEscape = true, modal = false, decideOn = 'click', }) {
29
29
  const pressInsideRef = useRef(false);
30
30
  // Latest values without re-subscribing on every render — a listener torn down mid-gesture
31
31
  // would miss the very click it exists for.
@@ -50,15 +50,8 @@ export function useOutsidePress({ open, onDismiss, inside = [], escape: closeOnE
50
50
  return element ? layer.contains(element) : false;
51
51
  });
52
52
  };
53
- const onClick = (event) => {
54
- pressInsideRef.current = false;
55
- const target = event.target instanceof Node ? event.target : null;
56
- if (target && latest.current.modal && !isInside(target) && !onAnotherLayer(target)) {
57
- // Decidable now for a DOM-inside press; a React-tree-inside press would have been
58
- // swallowed too, so a modal panel's portalled layers must live inside `inside`.
59
- event.preventDefault();
60
- event.stopPropagation();
61
- }
53
+ /** Decide once the event has finished dispatching — see the header. */
54
+ const decideLater = (target) => {
62
55
  const timer = setTimeout(() => {
63
56
  timers.delete(timer);
64
57
  if (pressInsideRef.current || !target)
@@ -71,24 +64,57 @@ export function useOutsidePress({ open, onDismiss, inside = [], escape: closeOnE
71
64
  }, 0);
72
65
  timers.add(timer);
73
66
  };
67
+ const outside = (target) => Boolean(target) && !isInside(target) && !onAnotherLayer(target);
68
+ // `pointerdown` mode: the click the same press produces is not a second decision — it is
69
+ // swallowed, until the next press or a second later, whichever comes first.
70
+ let swallowUntil = 0;
71
+ const onPointerDown = (event) => {
72
+ pressInsideRef.current = false;
73
+ swallowUntil = 0;
74
+ const target = event.target instanceof Node ? event.target : null;
75
+ if (outside(target))
76
+ swallowUntil = Date.now() + 1000;
77
+ decideLater(target);
78
+ };
79
+ const onClick = (event) => {
80
+ const target = event.target instanceof Node ? event.target : null;
81
+ if (decideOn === 'pointerdown') {
82
+ if (Date.now() < swallowUntil) {
83
+ swallowUntil = 0;
84
+ event.preventDefault();
85
+ event.stopPropagation();
86
+ }
87
+ return;
88
+ }
89
+ pressInsideRef.current = false;
90
+ if (latest.current.modal && outside(target)) {
91
+ // Decidable now for a DOM-inside press; a React-tree-inside press would have been
92
+ // swallowed too, so a modal panel's portalled layers must live inside `inside`.
93
+ event.preventDefault();
94
+ event.stopPropagation();
95
+ }
96
+ decideLater(target);
97
+ };
74
98
  const onKeyDown = (event) => {
75
99
  if (event.key === 'Escape')
76
100
  latest.current.onDismiss();
77
101
  };
78
102
  document.addEventListener('click', onClick, true);
103
+ if (decideOn === 'pointerdown')
104
+ document.addEventListener('pointerdown', onPointerDown, true);
79
105
  if (closeOnEscape)
80
106
  document.addEventListener('keydown', onKeyDown);
81
107
  return () => {
82
108
  document.removeEventListener('click', onClick, true);
109
+ document.removeEventListener('pointerdown', onPointerDown, true);
83
110
  document.removeEventListener('keydown', onKeyDown);
84
111
  for (const timer of timers)
85
112
  clearTimeout(timer);
86
113
  };
87
- }, [open, closeOnEscape]);
88
- return {
89
- onClickCapture: () => {
90
- pressInsideRef.current = true;
91
- },
114
+ }, [open, closeOnEscape, decideOn]);
115
+ const markInside = () => {
116
+ pressInsideRef.current = true;
92
117
  };
118
+ return { onClickCapture: markInside, onPointerDownCapture: markInside };
93
119
  }
94
120
  //# sourceMappingURL=useOutsidePress.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useOutsidePress.js","sourceRoot":"","sources":["../../../src/react/hooks/useOutsidePress.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useOutsidePress.js","sourceRoot":"","sources":["../../../src/react/hooks/useOutsidePress.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt",
3
- "version": "5.15.1",
3
+ "version": "5.15.3",
4
4
  "license": "ISC",
5
5
  "type": "module",
6
6
  "description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
@@ -86,6 +86,7 @@
86
86
  "e2e:playback-degraded": "playwright test --config e2e/playwright.config.ts playback-degraded.spec.ts",
87
87
  "e2e:resize-grip": "playwright test --config e2e/playwright.config.ts resize-grip-rail.spec.ts",
88
88
  "e2e:touch": "playwright test --config e2e/playwright.config.ts --project=touch",
89
+ "e2e:tap-away": "playwright test --config e2e/playwright.config.ts tap-away.spec.ts",
89
90
  "done:serial": "bun run typecheck && bun run lint && bun run test && bun run build",
90
91
  "paths": "bun run scripts/paths.ts",
91
92
  "surface": "public-surface",
@@ -1,5 +1,6 @@
1
1
  import { afterEach, describe, expect, test } from 'bun:test';
2
2
  import { cleanup, render } from '@testing-library/react';
3
+ import { createRef } from 'react';
3
4
  import { Button } from './Button.js';
4
5
  import { ButtonGroup } from './ButtonGroup.js';
5
6
  import { ButtonLink } from './ButtonLink.js';
@@ -214,3 +215,12 @@ describe('SplitButton', () => {
214
215
  expect(getByRole('group').querySelectorAll('button').length).toBe(2);
215
216
  });
216
217
  });
218
+
219
+ describe('ref', () => {
220
+ test('an IconButton hands its caller the <button> — a useOutsidePress toggle needs the node', () => {
221
+ const ref = createRef<HTMLButtonElement>();
222
+ render(<IconButton ref={ref} label='Folders'>F</IconButton>);
223
+ expect(ref.current?.tagName).toBe('BUTTON');
224
+ expect(ref.current?.getAttribute('aria-label')).toBe('Folders');
225
+ });
226
+ });
@@ -1,7 +1,7 @@
1
1
  import { Slot } from '@radix-ui/react-slot';
2
2
  import { cva, type VariantProps } from 'class-variance-authority';
3
3
  import { Check, Loader2 } from 'lucide-react';
4
- import { useRef, useState, type ButtonHTMLAttributes, type MouseEvent, type ReactNode } from 'react';
4
+ import { type ButtonHTMLAttributes, type MouseEvent, type ReactNode, type Ref, useRef, useState } from 'react';
5
5
  import { toast } from 'sonner';
6
6
  import { cn } from '../lib/cn.js';
7
7
  import { Tooltip, type TooltipMobile, type TooltipPlacement } from './Tooltip.js';
@@ -158,6 +158,13 @@ export interface ButtonProps
158
158
  /** How long the post-completion checkmark flash shows (ms). Default 1200. */
159
159
  resetMs?: number;
160
160
  children?: ReactNode;
161
+ /**
162
+ * The rendered `<button>` (or the `asChild` element). React 19 passes `ref` as an ordinary
163
+ * prop and this component already spreads it onto the element — the type is what was
164
+ * missing, so a caller that needed the node (a `useOutsidePress` toggle, a focus return)
165
+ * could not ask for it without a cast.
166
+ */
167
+ ref?: Ref<HTMLButtonElement>;
161
168
  }
162
169
 
163
170
  export function Button({
@@ -0,0 +1,39 @@
1
+ import { afterEach, describe, expect, test } from 'bun:test';
2
+ import { act, cleanup, fireEvent, render, screen } from '@testing-library/react';
3
+ import type { ButtonHTMLAttributes } from 'react';
4
+ import { DropdownMenu } from './DropdownMenu.js';
5
+
6
+ afterEach(cleanup);
7
+
8
+ function B(props: ButtonHTMLAttributes<HTMLButtonElement>) {
9
+ return (
10
+ <button
11
+ // guardrails-ignore no-raw-action-button: a spec fixture — any trigger element must work.
12
+ type='button'
13
+ {...props}
14
+ />
15
+ );
16
+ }
17
+
18
+ const menu = () => screen.queryByRole('menu', { hidden: true });
19
+
20
+ describe('DropdownMenu closes on a press anywhere else', () => {
21
+ test('even on a surface that stops its own pointerdown — a drag handle, a canvas', async () => {
22
+ render(
23
+ <div>
24
+ <B onPointerDown={(e) => e.stopPropagation()}>drag handle</B>
25
+ <DropdownMenu items={[{ key: 'a', label: 'Rename' }]} trigger={<B>actions</B>} />
26
+ </div>,
27
+ );
28
+ fireEvent.pointerDown(screen.getByText('actions'), { button: 0, ctrlKey: false });
29
+ expect(menu()).toBeTruthy();
30
+ await act(() => new Promise((r) => setTimeout(r, 0)));
31
+ act(() => {
32
+ screen.getByText('drag handle').dispatchEvent(
33
+ new PointerEvent('pointerdown', { bubbles: true, button: 0, pointerType: 'touch' }),
34
+ );
35
+ });
36
+ await act(() => new Promise((r) => setTimeout(r, 5)));
37
+ expect(menu()).toBeNull();
38
+ });
39
+ });
@@ -1,6 +1,7 @@
1
1
  import * as RDrop from '@radix-ui/react-dropdown-menu';
2
2
  import { Check, ChevronRight } from 'lucide-react';
3
- import type { ReactNode } from 'react';
3
+ import { type ReactNode, useCallback, useRef, useState } from 'react';
4
+ import { useOutsidePress } from '../hooks/useOutsidePress.js';
4
5
  import { cn } from '../lib/cn.js';
5
6
  import { useFloatingContainer } from '../lib/floatingContainer.js';
6
7
  import {
@@ -87,15 +88,43 @@ export function DropdownMenu({
87
88
  onOpenChange,
88
89
  }: DropdownMenuProps) {
89
90
  const container = useFloatingContainer();
91
+ // Always controlled underneath, so the outside-press fallback can close it too.
92
+ const [ownOpen, setOwnOpen] = useState(false);
93
+ const isOpen = open ?? ownOpen;
94
+ const setOpen = useCallback(
95
+ (next: boolean) => {
96
+ if (open === undefined) setOwnOpen(next);
97
+ onOpenChange?.(next);
98
+ },
99
+ [open, onOpenChange],
100
+ );
101
+ /*
102
+ * Radix's menu listens for the outside `pointerdown` in the BUBBLE phase, so a surface that
103
+ * stops its own pointerdown (a drag handle, a canvas) kept the menu open. The belt's one
104
+ * tap-away listener runs in the capture phase; see `useOutsidePress`. The menu is modal, so
105
+ * it decides on the pointerdown (an inert page sends an iPhone no click).
106
+ */
107
+ const triggerRef = useRef<HTMLButtonElement | null>(null);
108
+ const pressInside = useOutsidePress({
109
+ open: isOpen,
110
+ onDismiss: () => setOpen(false),
111
+ inside: [triggerRef],
112
+ escape: false,
113
+ decideOn: 'pointerdown',
114
+ });
90
115
  return (
91
- <RDrop.Root open={open} onOpenChange={onOpenChange}>
92
- <RDrop.Trigger asChild>{trigger}</RDrop.Trigger>
116
+ <RDrop.Root open={isOpen} onOpenChange={setOpen}>
117
+ <RDrop.Trigger asChild ref={triggerRef}>
118
+ {trigger}
119
+ </RDrop.Trigger>
93
120
  <RDrop.Portal container={container}>
94
121
  <RDrop.Content
95
122
  align={align}
96
123
  side={side}
97
124
  sideOffset={4}
98
125
  collisionPadding={FLOATING_COLLISION_PADDING}
126
+ onClickCapture={pressInside.onClickCapture}
127
+ onPointerDownCapture={pressInside.onPointerDownCapture}
99
128
  className={cn(FLOATING_CONTENT_BASE, FLOATING_ANIMATION, 'min-w-[8rem] p-1', className)}
100
129
  >
101
130
  {items.map((item) => (
@@ -130,6 +130,44 @@ describe('Popover closes when you press anywhere else', () => {
130
130
  expect(panel()).toBeNull();
131
131
  });
132
132
 
133
+ test('🔴 modal closes on a tap that sends NO click — an iPhone tapping the inert page', async () => {
134
+ // Measured in Playwright's iPhone 15 WebKit, 2026-09-27: under `modal` the tap lands on
135
+ // <html>, iOS sends no click for it, and a click-deciding popover never closed.
136
+ render(<Harness modal />);
137
+ openIt();
138
+ await act(() => new Promise((r) => setTimeout(r, 0)));
139
+ act(() => {
140
+ document.documentElement.dispatchEvent(
141
+ new PointerEvent('pointerdown', { bubbles: true, button: 0, pointerType: 'touch' }),
142
+ );
143
+ });
144
+ await act(() => new Promise((r) => setTimeout(r, 5)));
145
+ expect(panel()).toBeNull();
146
+ });
147
+
148
+ test('modal: the click the closing tap produces does not reach what the menu uncovered', async () => {
149
+ let played = 0;
150
+ function Player() {
151
+ const [open, setOpen] = useState(false);
152
+ return (
153
+ <div>
154
+ <B onClick={() => played++}>picture</B>
155
+ <Popover open={open} onOpenChange={setOpen} modal label='Subtitles' trigger={<B>subtitles</B>}>
156
+ <B>English</B>
157
+ </Popover>
158
+ </div>
159
+ );
160
+ }
161
+ render(<Player />);
162
+ openIt();
163
+ await act(() => new Promise((r) => setTimeout(r, 0)));
164
+ await tapOutside(screen.getByText('picture'), 'touch');
165
+ expect(panel()).toBeNull();
166
+ expect(played).toBe(0);
167
+ await tapOutside(screen.getByText('picture'), 'touch');
168
+ expect(played).toBe(1); // closed, the picture works again
169
+ });
170
+
133
171
  test('modal still closes on an outside press', async () => {
134
172
  render(<Harness modal />);
135
173
  openIt();
@@ -150,6 +150,9 @@ export function Popover({
150
150
  onDismiss: () => setOpen(false),
151
151
  inside: [triggerRef, anchorTrigger],
152
152
  escape: false,
153
+ // Under `modal` the page is inert and an iPhone sends no click for a tap on it — see
154
+ // `decideOn` in useOutsidePress.
155
+ decideOn: modal ? 'pointerdown' : 'click',
153
156
  });
154
157
 
155
158
  const content = (
@@ -171,6 +174,7 @@ export function Popover({
171
174
  // React-tree capture: a press on a nested layer this panel portalled (a Select's
172
175
  // list, a sub-menu) is INSIDE even though the DOM puts it elsewhere.
173
176
  onClickCapture={pressInside.onClickCapture}
177
+ onPointerDownCapture={pressInside.onPointerDownCapture}
174
178
  className={cn(
175
179
  unstyled
176
180
  ? 'z-[var(--z-popover)] outline-none'
@@ -20,6 +20,17 @@ export interface UseOutsidePressOptions {
20
20
  * whose rows play on tap). Default false.
21
21
  */
22
22
  modal?: boolean;
23
+ /**
24
+ * Decide on the `pointerdown` rather than the `click`. Only for a panel that has made the
25
+ * page under it inert (`Popover`'s `modal`, which sets `pointer-events: none` on body).
26
+ *
27
+ * 🔴 Measured 2026-09-27 in Playwright's iPhone 15 WebKit: with the page inert, a tap
28
+ * outside hits `<html>`, which iOS does not consider clickable, so NO `click` is ever
29
+ * sent — the menu stayed open under the owner's finger, exactly as reported. Deciding on
30
+ * the pointerdown closes it; the `click` that same press may still produce is swallowed,
31
+ * or it would land on whatever the closed menu uncovered (the picture, which pauses).
32
+ */
33
+ decideOn?: 'click' | 'pointerdown';
23
34
  }
24
35
 
25
36
  /** A floating layer another component portalled — a press there belongs to that layer. */
@@ -57,7 +68,8 @@ export function useOutsidePress({
57
68
  inside = [],
58
69
  escape: closeOnEscape = true,
59
70
  modal = false,
60
- }: UseOutsidePressOptions): { onClickCapture: () => void } {
71
+ decideOn = 'click',
72
+ }: UseOutsidePressOptions): { onClickCapture: () => void; onPointerDownCapture: () => void } {
61
73
  const pressInsideRef = useRef(false);
62
74
  // Latest values without re-subscribing on every render — a listener torn down mid-gesture
63
75
  // would miss the very click it exists for.
@@ -83,15 +95,8 @@ export function useOutsidePress({
83
95
  });
84
96
  };
85
97
 
86
- const onClick = (event: MouseEvent) => {
87
- pressInsideRef.current = false;
88
- const target = event.target instanceof Node ? event.target : null;
89
- if (target && latest.current.modal && !isInside(target) && !onAnotherLayer(target)) {
90
- // Decidable now for a DOM-inside press; a React-tree-inside press would have been
91
- // swallowed too, so a modal panel's portalled layers must live inside `inside`.
92
- event.preventDefault();
93
- event.stopPropagation();
94
- }
98
+ /** Decide once the event has finished dispatching — see the header. */
99
+ const decideLater = (target: Node | null) => {
95
100
  const timer = setTimeout(() => {
96
101
  timers.delete(timer);
97
102
  if (pressInsideRef.current || !target) return;
@@ -101,22 +106,54 @@ export function useOutsidePress({
101
106
  }, 0);
102
107
  timers.add(timer);
103
108
  };
109
+ const outside = (target: Node | null) => Boolean(target) && !isInside(target as Node) && !onAnotherLayer(target as Node);
110
+
111
+ // `pointerdown` mode: the click the same press produces is not a second decision — it is
112
+ // swallowed, until the next press or a second later, whichever comes first.
113
+ let swallowUntil = 0;
114
+ const onPointerDown = (event: PointerEvent) => {
115
+ pressInsideRef.current = false;
116
+ swallowUntil = 0;
117
+ const target = event.target instanceof Node ? event.target : null;
118
+ if (outside(target)) swallowUntil = Date.now() + 1000;
119
+ decideLater(target);
120
+ };
121
+ const onClick = (event: MouseEvent) => {
122
+ const target = event.target instanceof Node ? event.target : null;
123
+ if (decideOn === 'pointerdown') {
124
+ if (Date.now() < swallowUntil) {
125
+ swallowUntil = 0;
126
+ event.preventDefault();
127
+ event.stopPropagation();
128
+ }
129
+ return;
130
+ }
131
+ pressInsideRef.current = false;
132
+ if (latest.current.modal && outside(target)) {
133
+ // Decidable now for a DOM-inside press; a React-tree-inside press would have been
134
+ // swallowed too, so a modal panel's portalled layers must live inside `inside`.
135
+ event.preventDefault();
136
+ event.stopPropagation();
137
+ }
138
+ decideLater(target);
139
+ };
104
140
  const onKeyDown = (event: KeyboardEvent) => {
105
141
  if (event.key === 'Escape') latest.current.onDismiss();
106
142
  };
107
143
 
108
144
  document.addEventListener('click', onClick, true);
145
+ if (decideOn === 'pointerdown') document.addEventListener('pointerdown', onPointerDown, true);
109
146
  if (closeOnEscape) document.addEventListener('keydown', onKeyDown);
110
147
  return () => {
111
148
  document.removeEventListener('click', onClick, true);
149
+ document.removeEventListener('pointerdown', onPointerDown, true);
112
150
  document.removeEventListener('keydown', onKeyDown);
113
151
  for (const timer of timers) clearTimeout(timer);
114
152
  };
115
- }, [open, closeOnEscape]);
153
+ }, [open, closeOnEscape, decideOn]);
116
154
 
117
- return {
118
- onClickCapture: () => {
119
- pressInsideRef.current = true;
120
- },
155
+ const markInside = () => {
156
+ pressInsideRef.current = true;
121
157
  };
158
+ return { onClickCapture: markInside, onPointerDownCapture: markInside };
122
159
  }