cursedbelt 5.103.1 → 5.104.1

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.
@@ -16,6 +16,10 @@ export interface ChoiceOption<T extends string = string> {
16
16
  image?: ReactNode;
17
17
  /** Accessible name for a picture tile whose `label` is not a plain string. */
18
18
  'aria-label'?: string;
19
+ /** `layout='list'` only: a quiet right-aligned fact about the row — a count, "you are here". */
20
+ trailing?: ReactNode;
21
+ /** `layout='list'` only: depth in levels of 1rem, so a flattened tree keeps its shape. */
22
+ indent?: number;
19
23
  }
20
24
  export interface ChoiceGroupProps<T extends string = string> {
21
25
  options: readonly ChoiceOption<T>[];
@@ -37,11 +41,19 @@ export interface ChoiceGroupProps<T extends string = string> {
37
41
  * `text` (default): a wrapping row of worded options. `picture`: one strip of
38
42
  * square thumbnail tiles, checked by an accent ring — a cover picker, an avatar
39
43
  * picker. The strip does not wrap; put the group in a `ScrollArea axis='x'` when
40
- * it can be longer than its container.
44
+ * it can be longer than its container. `list`: full-width stacked rows, each with
45
+ * a `trailing` slot and an `indent` — a list of moments, a folder tree. Give the
46
+ * group a height through `className` when it can outgrow its container.
41
47
  */
42
- layout?: 'text' | 'picture';
48
+ layout?: 'text' | 'picture' | 'list';
43
49
  /** `layout='picture'` tile edge in px. Default 64. */
44
50
  tileSize?: number;
51
+ /**
52
+ * `layout='list'` only: a double-click or Enter on a row takes it straight to the
53
+ * action the choice was for, without reaching for the dialog's button. `onChange`
54
+ * has already reported that row by then.
55
+ */
56
+ onConfirm?: (value: T) => void;
45
57
  className?: string;
46
58
  }
47
59
  /**
@@ -54,6 +66,7 @@ export interface ChoiceGroupProps<T extends string = string> {
54
66
  * - a long or data-driven list → `SelectField` / `ChoiceMenu`
55
67
  * - a color → `SwatchPicker`
56
68
  * - one picture out of several (a cover, an avatar) → THIS, `layout='picture'`
69
+ * - rows that each carry two lines and a fact, or a tree → THIS, `layout='list'`
57
70
  * - a handful of answers that each need words → THIS
58
71
  *
59
72
  * ── 🔴 Why this exists: the hidden-radio trap (family, 2026-09-26) ──────────
@@ -74,5 +87,5 @@ export interface ChoiceGroupProps<T extends string = string> {
74
87
  * `relative` on the root contains the non-focusable form-bubble input Radix adds
75
88
  * inside a `<form>`, so even that is positioned against this group.
76
89
  */
77
- export declare function ChoiceGroup<T extends string = string>({ options, value, onChange, label, 'aria-label': ariaLabel, description, disabled, disabledReason, name, layout, tileSize, className, ...rest }: ChoiceGroupProps<T>): import("react").JSX.Element;
90
+ export declare function ChoiceGroup<T extends string = string>({ options, value, onChange, label, 'aria-label': ariaLabel, description, disabled, disabledReason, name, layout, tileSize, onConfirm, className, ...rest }: ChoiceGroupProps<T>): import("react").JSX.Element;
78
91
  //# sourceMappingURL=ChoiceGroup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChoiceGroup.d.ts","sourceRoot":"","sources":["../../../src/react/components/ChoiceGroup.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAS,MAAM,OAAO,CAAC;AAK9C,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,2CAA2C;IAC3C,KAAK,EAAE,CAAC,CAAC;IACT,+EAA+E;IAC/E,KAAK,EAAE,SAAS,CAAC;IACjB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACzD,OAAO,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IACpC,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC7B,yEAAyE;IACzE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;6FACyF;IACzF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EACrD,OAAO,EACP,KAAK,EACL,QAAQ,EACR,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,WAAW,EACX,QAAgB,EAChB,cAAc,EACd,IAAI,EACJ,MAAe,EACf,QAAa,EACb,SAAS,EACT,GAAG,IAAI,EACR,EAAE,gBAAgB,CAAC,CAAC,CAAC,+BA+DrB"}
1
+ {"version":3,"file":"ChoiceGroup.d.ts","sourceRoot":"","sources":["../../../src/react/components/ChoiceGroup.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAS,MAAM,OAAO,CAAC;AAK9C,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,2CAA2C;IAC3C,KAAK,EAAE,CAAC,CAAC;IACT,+EAA+E;IAC/E,KAAK,EAAE,SAAS,CAAC;IACjB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gGAAgG;IAChG,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACzD,OAAO,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IACpC,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC7B,yEAAyE;IACzE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;6FACyF;IACzF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACrC,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EACrD,OAAO,EACP,KAAK,EACL,QAAQ,EACR,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,WAAW,EACX,QAAgB,EAChB,cAAc,EACd,IAAI,EACJ,MAAe,EACf,QAAa,EACb,SAAS,EACT,SAAS,EACT,GAAG,IAAI,EACR,EAAE,gBAAgB,CAAC,CAAC,CAAC,+BA4DrB"}
@@ -1,9 +1,12 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import * as RadioGroup from '@radix-ui/react-radio-group';
3
3
  import { useId } from 'react';
4
- import { cn } from '../lib/cn.js';
4
+ import { cn, RAW_BUTTON } from '../lib/cn.js';
5
5
  import { TAP_TARGET } from '../lib/tapTarget.js';
6
6
  import { Tooltip } from './Tooltip.js';
7
+ const ROOT_LAYOUT = { text: 'flex-wrap gap-1.5', picture: 'gap-2', list: 'flex-col gap-0.5' };
8
+ /** Focus, checked and disabled, the same on a chip and on a row. */
9
+ const OPTION_STATES = 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[state=checked]:border-accent data-[state=checked]:bg-accent/10 data-[state=checked]:font-medium disabled:cursor-not-allowed disabled:opacity-50';
7
10
  /**
8
11
  * Pick ONE of a few options whose labels are sentences — "No — just their own
9
12
  * page" / "Yes — they can edit anyone, like you". The options are all visible at
@@ -14,6 +17,7 @@ import { Tooltip } from './Tooltip.js';
14
17
  * - a long or data-driven list → `SelectField` / `ChoiceMenu`
15
18
  * - a color → `SwatchPicker`
16
19
  * - one picture out of several (a cover, an avatar) → THIS, `layout='picture'`
20
+ * - rows that each carry two lines and a fact, or a tree → THIS, `layout='list'`
17
21
  * - a handful of answers that each need words → THIS
18
22
  *
19
23
  * ── 🔴 Why this exists: the hidden-radio trap (family, 2026-09-26) ──────────
@@ -34,13 +38,31 @@ import { Tooltip } from './Tooltip.js';
34
38
  * `relative` on the root contains the non-focusable form-bubble input Radix adds
35
39
  * inside a `<form>`, so even that is positioned against this group.
36
40
  */
37
- export function ChoiceGroup({ options, value, onChange, label, 'aria-label': ariaLabel, description, disabled = false, disabledReason, name, layout = 'text', tileSize = 64, className, ...rest }) {
41
+ export function ChoiceGroup({ options, value, onChange, label, 'aria-label': ariaLabel, description, disabled = false, disabledReason, name, layout = 'text', tileSize = 64, onConfirm, className, ...rest }) {
38
42
  const id = useId();
39
43
  const labelId = label != null ? `${id}-label` : undefined;
40
44
  const descriptionId = description != null ? `${id}-desc` : undefined;
41
45
  const reasonId = disabled && disabledReason != null ? `${id}-reason` : undefined;
42
46
  const describedBy = [descriptionId, reasonId].filter(Boolean).join(' ') || undefined;
43
- return (_jsxs("div", { ...rest, className: cn('flex min-w-0 flex-col gap-1.5', className), "data-cb-choice-group": '', children: [label != null ? (_jsx("span", { id: labelId, className: cn('text-sm font-medium text-foreground', disabled && 'opacity-60'), children: label })) : null, _jsx(RadioGroup.Root, { "aria-labelledby": labelId, "aria-label": labelId ? undefined : ariaLabel, "aria-describedby": describedBy, value: value ?? '', onValueChange: (next) => onChange(next), disabled: disabled, name: name, className: cn('relative flex min-w-0', layout === 'picture' ? 'gap-2' : 'flex-wrap gap-1.5'), children: options.map((option) => layout === 'picture' ? (_jsx(PictureTile, { option: option, size: tileSize }, option.value)) : (_jsxs(RadioGroup.Item, { value: option.value, disabled: option.disabled, className: cn('flex min-w-0 max-w-full flex-col items-start rounded-md border border-border bg-transparent px-2.5 py-1.5 text-left text-sm text-foreground transition-colors', 'hover:border-accent', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', 'data-[state=checked]:border-accent data-[state=checked]:bg-accent/10 data-[state=checked]:font-medium', 'disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-border', TAP_TARGET), children: [_jsx("span", { className: 'min-w-0 break-words', children: option.label }), option.description != null ? (_jsx("span", { className: 'min-w-0 break-words text-xs font-normal text-muted-foreground', children: option.description })) : null] }, option.value))) }), reasonId ? (_jsx("p", { id: reasonId, className: 'text-xs text-muted-foreground', children: disabledReason })) : null, descriptionId ? (_jsx("p", { id: descriptionId, className: 'text-xs text-muted-foreground', children: description })) : null] }));
47
+ return (_jsxs("div", { ...rest, className: cn('flex min-w-0 flex-col gap-1.5', className), "data-cb-choice-group": '', children: [label != null ? (_jsx("span", { id: labelId, className: cn('text-sm font-medium text-foreground', disabled && 'opacity-60'), children: label })) : null, _jsx(RadioGroup.Root, { "aria-labelledby": labelId, "aria-label": labelId ? undefined : ariaLabel, "aria-describedby": describedBy, value: value ?? '', onValueChange: (next) => onChange(next), disabled: disabled, name: name, className: cn('relative flex min-w-0', ROOT_LAYOUT[layout]), children: options.map((option) => layout === 'picture' ? (_jsx(PictureTile, { option: option, size: tileSize }, option.value)) : layout === 'list' ? (_jsx(ListRow, { option: option, onConfirm: onConfirm }, option.value)) : (_jsx(RadioGroup.Item, { value: option.value, disabled: option.disabled, className: cn(RAW_BUTTON, 'flex min-w-0 max-w-full flex-col items-start rounded-md border border-border bg-transparent px-2.5 py-1.5 text-left text-sm text-foreground transition-colors', 'hover:border-accent', OPTION_STATES, 'disabled:hover:border-border', TAP_TARGET), children: _jsx(OptionWords, { option: option }) }, option.value))) }), reasonId ? (_jsx("p", { id: reasonId, className: 'text-xs text-muted-foreground', children: disabledReason })) : null, descriptionId ? (_jsx("p", { id: descriptionId, className: 'text-xs text-muted-foreground', children: description })) : null] }));
48
+ }
49
+ /** What keeps `label` and `description` two lines, in a chip and in a row alike. */
50
+ function OptionWords({ option }) {
51
+ return (_jsxs(_Fragment, { children: [_jsx("span", { className: 'min-w-0 max-w-full break-words', children: option.label }), option.description != null ? (_jsx("span", { className: 'min-w-0 max-w-full break-words text-xs font-normal text-muted-foreground', children: option.description })) : null] }));
52
+ }
53
+ /**
54
+ * One full-width row of a `layout='list'` group: the words on the left, `trailing` on the
55
+ * right. The indent is padding, not a margin, so a nested row's highlight still spans the list.
56
+ */
57
+ function ListRow({ option, onConfirm }) {
58
+ return (_jsxs(RadioGroup.Item, { value: option.value, disabled: option.disabled,
59
+ // 0.625rem is the row's own `px-2.5`, which a `padding-inline-start` would otherwise replace.
60
+ style: option.indent ? { paddingInlineStart: `calc(0.625rem + ${option.indent}rem)` } : undefined, onDoubleClick: onConfirm ? () => onConfirm(option.value) : undefined, onKeyDown: onConfirm
61
+ ? (event) => {
62
+ if (event.key === 'Enter')
63
+ onConfirm(option.value);
64
+ }
65
+ : undefined, className: cn(RAW_BUTTON, 'flex w-full min-w-0 items-center gap-3 rounded-md border border-transparent px-2.5 py-1.5 text-left text-sm text-foreground transition-colors', 'hover:bg-muted', OPTION_STATES, 'disabled:hover:bg-transparent', TAP_TARGET), children: [_jsx("span", { className: 'flex min-w-0 flex-1 flex-col items-start', children: _jsx(OptionWords, { option: option }) }), option.trailing != null ? (_jsx("span", { className: 'shrink-0 text-xs font-normal text-muted-foreground', children: option.trailing })) : null] }));
44
66
  }
45
67
  /**
46
68
  * One square tile of a `layout='picture'` group. Still a Radix radio item — roving
@@ -50,7 +72,7 @@ export function ChoiceGroup({ options, value, onChange, label, 'aria-label': ari
50
72
  */
51
73
  function PictureTile({ option, size }) {
52
74
  const name = option['aria-label'] ?? (typeof option.label === 'string' ? option.label : undefined);
53
- const item = (_jsx(RadioGroup.Item, { value: option.value, disabled: option.disabled, "aria-label": option.image != null ? name : undefined, style: { width: size, height: size }, className: cn('flex shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-card text-center text-caption leading-tight text-foreground transition-colors', 'hover:border-accent', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', 'data-[state=checked]:border-accent data-[state=checked]:ring-2 data-[state=checked]:ring-accent', option.image == null && 'px-1 data-[state=checked]:bg-accent/10', 'disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-border'), children: option.image ?? option.label }));
75
+ const item = (_jsx(RadioGroup.Item, { value: option.value, disabled: option.disabled, "aria-label": option.image != null ? name : undefined, style: { width: size, height: size }, className: cn(RAW_BUTTON, 'flex shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-card text-center text-caption leading-tight text-foreground transition-colors', 'hover:border-accent', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', 'data-[state=checked]:border-accent data-[state=checked]:ring-2 data-[state=checked]:ring-accent', option.image == null && 'px-1 data-[state=checked]:bg-accent/10', 'disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-border'), children: option.image ?? option.label }));
54
76
  return option.image != null ? _jsx(Tooltip, { content: option.label, children: item }) : item;
55
77
  }
56
78
  //# sourceMappingURL=ChoiceGroup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChoiceGroup.js","sourceRoot":"","sources":["../../../src/react/components/ChoiceGroup.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChoiceGroup.js","sourceRoot":"","sources":["../../../src/react/components/ChoiceGroup.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,UAAU,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAkB,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AA6DvC,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAW,CAAC;AAEvG,oEAAoE;AACpE,MAAM,aAAa,GACjB,+NAA+N,CAAC;AAElO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,WAAW,CAA4B,EACrD,OAAO,EACP,KAAK,EACL,QAAQ,EACR,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,WAAW,EACX,QAAQ,GAAG,KAAK,EAChB,cAAc,EACd,IAAI,EACJ,MAAM,GAAG,MAAM,EACf,QAAQ,GAAG,EAAE,EACb,SAAS,EACT,SAAS,EACT,GAAG,IAAI,EACa;IACpB,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,MAAM,aAAa,GAAG,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,MAAM,QAAQ,GAAG,QAAQ,IAAI,cAAc,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,MAAM,WAAW,GAAG,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;IAErF,OAAO,CACL,kBAAS,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,+BAA+B,EAAE,SAAS,CAAC,0BAAuB,EAAE,aAC9F,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CACf,eAAM,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,qCAAqC,EAAE,QAAQ,IAAI,YAAY,CAAC,YAC9F,KAAK,GACD,CACR,CAAC,CAAC,CAAC,IAAI,EACR,KAAC,UAAU,CAAC,IAAI,uBACG,OAAO,gBACZ,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,sBACzB,WAAW,EAC7B,KAAK,EAAE,KAAK,IAAI,EAAE,EAClB,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAS,CAAC,EAC5C,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,YAE1D,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACtB,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CACrB,KAAC,WAAW,IAAoB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,IAA5C,MAAM,CAAC,KAAK,CAAoC,CACnE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,CACtB,KAAC,OAAO,IAAoB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,IAAlD,MAAM,CAAC,KAAK,CAA0C,CACrE,CAAC,CAAC,CAAC,CACF,KAAC,UAAU,CAAC,IAAI,IAEd,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,SAAS,EAAE,EAAE,CACX,UAAU,EACV,+JAA+J,EAC/J,qBAAqB,EACrB,aAAa,EACb,8BAA8B,EAC9B,UAAU,CACX,YAED,KAAC,WAAW,IAAC,MAAM,EAAE,MAAM,GAAI,IAZ1B,MAAM,CAAC,KAAK,CAaD,CACnB,CACF,GACe,EACjB,QAAQ,CAAC,CAAC,CAAC,CACV,YAAG,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAC,+BAA+B,YACvD,cAAc,GACb,CACL,CAAC,CAAC,CAAC,IAAI,EACP,aAAa,CAAC,CAAC,CAAC,CACf,YAAG,EAAE,EAAE,aAAa,EAAE,SAAS,EAAC,+BAA+B,YAC5D,WAAW,GACV,CACL,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,SAAS,WAAW,CAAmB,EAAE,MAAM,EAA+B;IAC5E,OAAO,CACL,8BACE,eAAM,SAAS,EAAC,gCAAgC,YAAE,MAAM,CAAC,KAAK,GAAQ,EACrE,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAC5B,eAAM,SAAS,EAAC,0EAA0E,YACvF,MAAM,CAAC,WAAW,GACd,CACR,CAAC,CAAC,CAAC,IAAI,IACP,CACJ,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CAAmB,EAAE,MAAM,EAAE,SAAS,EAA+D;IACnH,OAAO,CACL,MAAC,UAAU,CAAC,IAAI,IACd,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,8FAA8F;QAC9F,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,mBAAmB,MAAM,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,EACjG,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EACpE,SAAS,EACP,SAAS;YACP,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO;oBAAE,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACrD,CAAC;YACH,CAAC,CAAC,SAAS,EAEf,SAAS,EAAE,EAAE,CACX,UAAU,EACV,+IAA+I,EAC/I,gBAAgB,EAChB,aAAa,EACb,+BAA+B,EAC/B,UAAU,CACX,aAED,eAAM,SAAS,EAAC,0CAA0C,YACxD,KAAC,WAAW,IAAC,MAAM,EAAE,MAAM,GAAI,GAC1B,EACN,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,CACzB,eAAM,SAAS,EAAC,oDAAoD,YAAE,MAAM,CAAC,QAAQ,GAAQ,CAC9F,CAAC,CAAC,CAAC,IAAI,IACQ,CACnB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAmB,EAAE,MAAM,EAAE,IAAI,EAA6C;IAChG,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACnG,MAAM,IAAI,GAAG,CACX,KAAC,UAAU,CAAC,IAAI,IACd,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ,gBACb,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EACnD,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EACpC,SAAS,EAAE,EAAE,CACX,UAAU,EACV,4KAA4K,EAC5K,qBAAqB,EACrB,yEAAyE,EACzE,iGAAiG,EACjG,MAAM,CAAC,KAAK,IAAI,IAAI,IAAI,wCAAwC,EAChE,8EAA8E,CAC/E,YAEA,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,GACb,CACnB,CAAC;IACF,OAAO,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,KAAC,OAAO,IAAC,OAAO,EAAE,MAAM,CAAC,KAAK,YAAG,IAAI,GAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACxF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"RowActions.d.ts","sourceRoot":"","sources":["../../../../src/react/components/DataTable/RowActions.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQrD,+DAA+D;AAC/D,eAAO,MAAM,cAAc,qBAAmB,CAAC;AAE/C,MAAM,WAAW,eAAe,CAAC,IAAI;IACnC,GAAG,EAAE,IAAI,CAAC;IACV,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B;yFACqF;IACrF,IAAI,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC1B;iFAC6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,yFAAyF;IACzF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,EAC/B,GAAG,EACH,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,SAAyB,EACzB,MAAM,EACN,QAAQ,EACR,gBAAgB,EAChB,GAAG,IAAI,EACR,EAAE,eAAe,CAAC,IAAI,CAAC,+BAqFvB"}
1
+ {"version":3,"file":"RowActions.d.ts","sourceRoot":"","sources":["../../../../src/react/components/DataTable/RowActions.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQrD,+DAA+D;AAC/D,eAAO,MAAM,cAAc,qBAAmB,CAAC;AAE/C,MAAM,WAAW,eAAe,CAAC,IAAI;IACnC,GAAG,EAAE,IAAI,CAAC;IACV,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B;yFACqF;IACrF,IAAI,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC1B;iFAC6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,yFAAyF;IACzF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,EAC/B,GAAG,EACH,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,SAAyB,EACzB,MAAM,EACN,QAAQ,EACR,gBAAgB,EAChB,GAAG,IAAI,EACR,EAAE,eAAe,CAAC,IAAI,CAAC,+BA+FvB"}
@@ -1,8 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { EllipsisVertical, Pencil, Trash2 } from 'lucide-react';
3
+ import { useState } from 'react';
3
4
  import { Button } from '../Button.js';
4
5
  import { IconButton } from '../IconButton.js';
5
- import { lazyPart } from './lazyPart.js';
6
+ import { lazyPart, standInPress } from './lazyPart.js';
6
7
  // The kebab's menu is Radix's Menu, and most tables never draw a kebab — so it loads
7
8
  // with the first row that has one, not with the table (forge task 2309). Edit and
8
9
  // Delete are plain buttons and stay synchronous.
@@ -17,7 +18,11 @@ export const preloadRowMenu = MenuPart.preload;
17
18
  * surfaces the intent.
18
19
  */
19
20
  export function RowActions({ row, onEdit, onDelete, menu, menuLabel = 'Row actions', action, menuOpen, onMenuOpenChange, ...rest }) {
20
- const kebab = (_jsx(IconButton, { label: menuLabel, className: 'size-8 pointer-coarse:min-w-11 [&_svg]:size-4', children: _jsx(EllipsisVertical, {}) }));
21
+ // 🔴 Always controlled, so a press before the menu's chunk lands is not lost (forge task 4172).
22
+ const [ownOpen, setOwnOpen] = useState(false);
23
+ const open = onMenuOpenChange ? (menuOpen ?? false) : ownOpen;
24
+ const setOpen = onMenuOpenChange ?? setOwnOpen;
25
+ const kebab = (standIn) => (_jsx(IconButton, { ...standIn, label: menuLabel, className: 'size-8 pointer-coarse:min-w-11 [&_svg]:size-4', children: _jsx(EllipsisVertical, {}) }));
21
26
  return (_jsxs("div", { ...rest, className: 'flex items-center justify-end gap-0.5',
22
27
  // The kebab's Radix trigger opens on pointerdown — stop the bubble here so opening
23
28
  // the menu never doubles as a row click.
@@ -33,6 +38,10 @@ export function RowActions({ row, onEdit, onDelete, menu, menuLabel = 'Row actio
33
38
  }, children: _jsx(Pencil, {}) })) : null, onDelete ? (_jsx(IconButton, { label: 'Delete row', className: 'size-8 text-muted-foreground hover:text-destructive [&_svg]:size-4', onClick: (e) => {
34
39
  e.stopPropagation();
35
40
  onDelete(row);
36
- }, children: _jsx(Trash2, {}) })) : null, menu && menu.length > 0 ? (_jsx(MenuPart, { align: 'end', trigger: kebab, items: menu, fallback: kebab, ...(onMenuOpenChange ? { open: menuOpen ?? false, onOpenChange: onMenuOpenChange } : {}) })) : null] }));
41
+ }, children: _jsx(Trash2, {}) })) : null, menu && menu.length > 0 ? (_jsx(MenuPart, { align: 'end', trigger: kebab(), items: menu, fallback: kebab({
42
+ 'aria-haspopup': 'menu',
43
+ loading: open,
44
+ ...standInPress(() => setOpen(true)),
45
+ }), open: open, onOpenChange: setOpen })) : null] }));
37
46
  }
38
47
  //# sourceMappingURL=RowActions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RowActions.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/RowActions.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RowActions.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/RowActions.tsx"],"names":[],"mappings":"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"}
@@ -15,7 +15,7 @@
15
15
  * the moment the chunk lands, and React would REMOUNT the part — a half-typed search,
16
16
  * an open menu, gone.
17
17
  */
18
- import { type ComponentType, type ReactNode } from 'react';
18
+ import { type ComponentType, type PointerEvent, type ReactNode } from 'react';
19
19
  export interface LazyPart<P> {
20
20
  (props: P & {
21
21
  fallback?: ReactNode;
@@ -23,5 +23,19 @@ export interface LazyPart<P> {
23
23
  /** Fetch the part now. Resolves when a new mount would draw it synchronously. */
24
24
  preload: () => Promise<void>;
25
25
  }
26
+ export interface StandInPress {
27
+ onPointerDown: (event: PointerEvent) => void;
28
+ onClick: () => void;
29
+ }
30
+ /**
31
+ * 🔴 What a lazy trigger's stand-in (the `fallback` drawn as the trigger) listens to, so a press
32
+ * before the chunk lands is not lost (forge task 4172). `press` records it in the state the part
33
+ * is controlled by, and the part mounts already open.
34
+ *
35
+ * Radix's rule for a press, because the landing replaces the button: one that lands between the
36
+ * pointerdown and the release leaves the browser's `click` with neither button. The `click` is
37
+ * still heard, for the keyboard.
38
+ */
39
+ export declare function standInPress(press: () => void): StandInPress;
26
40
  export declare function lazyPart<P extends object>(load: () => Promise<ComponentType<P>>): LazyPart<P>;
27
41
  //# sourceMappingURL=lazyPart.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazyPart.d.ts","sourceRoot":"","sources":["../../../../src/react/components/DataTable/lazyPart.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAmB,KAAK,aAAa,EAAE,KAAK,SAAS,EAAsB,MAAM,OAAO,CAAC;AAGhG,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,CAAC,KAAK,EAAE,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,GAAG,SAAS,CAAC;IACjD,iFAAiF;IACjF,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CA+B7F"}
1
+ {"version":3,"file":"lazyPart.d.ts","sourceRoot":"","sources":["../../../../src/react/components/DataTable/lazyPart.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AAGf,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,CAAC,KAAK,EAAE,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,GAAG,SAAS,CAAC;IACjD,iFAAiF;IACjF,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC7C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,YAAY,CAO5D;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CA+B7F"}
@@ -16,8 +16,26 @@ import { jsx as _jsx } from "react/jsx-runtime";
16
16
  * the moment the chunk lands, and React would REMOUNT the part — a half-typed search,
17
17
  * an open menu, gone.
18
18
  */
19
- import { Suspense, useState } from 'react';
19
+ import { Suspense, useState, } from 'react';
20
20
  import { lazyWithReload } from '../../lazy/staleChunk.js';
21
+ /**
22
+ * 🔴 What a lazy trigger's stand-in (the `fallback` drawn as the trigger) listens to, so a press
23
+ * before the chunk lands is not lost (forge task 4172). `press` records it in the state the part
24
+ * is controlled by, and the part mounts already open.
25
+ *
26
+ * Radix's rule for a press, because the landing replaces the button: one that lands between the
27
+ * pointerdown and the release leaves the browser's `click` with neither button. The `click` is
28
+ * still heard, for the keyboard.
29
+ */
30
+ export function standInPress(press) {
31
+ return {
32
+ onPointerDown: (event) => {
33
+ if (event.button === 0 && !event.ctrlKey)
34
+ press();
35
+ },
36
+ onClick: press,
37
+ };
38
+ }
21
39
  export function lazyPart(load) {
22
40
  let loaded = null;
23
41
  let pending = null;
@@ -1 +1 @@
1
- {"version":3,"file":"lazyPart.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/lazyPart.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAuD,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAQ1D,MAAM,UAAU,QAAQ,CAAmB,IAAqC;IAC9E,IAAI,MAAM,GAA4B,IAAI,CAAC;IAC3C,IAAI,OAAO,GAAqC,IAAI,CAAC;IACrD,MAAM,QAAQ,GAAG,GAA8B,EAAE;QAC/C,OAAO,KAAK,IAAI,EAAE,CAAC,IAAI,CACrB,CAAC,SAAS,EAAE,EAAE;YACZ,MAAM,GAAG,SAAS,CAAC;YACnB,OAAO,SAAS,CAAC;QACnB,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;YACjB,OAAO,GAAG,IAAI,CAAC,CAAC,4DAA4D;YAC5E,MAAM,KAAK,CAAC;QACd,CAAC,CACF,CAAC;QACF,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;IAE5F,SAAS,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,KAAK,EAAgC;QACvE,MAAM,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,MAAM;YAAE,OAAO,KAAC,MAAM,OAAM,KAAW,GAAI,CAAC;QAChD,OAAO,CACL,KAAC,QAAQ,IAAC,QAAQ,EAAE,QAAQ,YAC1B,KAAC,IAAI,OAAM,KAAwB,GAAI,GAC9B,CACZ,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE;QACxB,MAAM,QAAQ,EAAE,CAAC;IACnB,CAAC,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"lazyPart.js","sourceRoot":"","sources":["../../../../src/react/components/DataTable/lazyPart.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAKL,QAAQ,EACR,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAa1D;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,OAAO;QACL,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE;YACvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO;gBAAE,KAAK,EAAE,CAAC;QACpD,CAAC;QACD,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAmB,IAAqC;IAC9E,IAAI,MAAM,GAA4B,IAAI,CAAC;IAC3C,IAAI,OAAO,GAAqC,IAAI,CAAC;IACrD,MAAM,QAAQ,GAAG,GAA8B,EAAE;QAC/C,OAAO,KAAK,IAAI,EAAE,CAAC,IAAI,CACrB,CAAC,SAAS,EAAE,EAAE;YACZ,MAAM,GAAG,SAAS,CAAC;YACnB,OAAO,SAAS,CAAC;QACnB,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;YACjB,OAAO,GAAG,IAAI,CAAC,CAAC,4DAA4D;YAC5E,MAAM,KAAK,CAAC;QACd,CAAC,CACF,CAAC;QACF,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;IAE5F,SAAS,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,KAAK,EAAgC;QACvE,MAAM,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,MAAM;YAAE,OAAO,KAAC,MAAM,OAAM,KAAW,GAAI,CAAC;QAChD,OAAO,CACL,KAAC,QAAQ,IAAC,QAAQ,EAAE,QAAQ,YAC1B,KAAC,IAAI,OAAM,KAAwB,GAAI,GAC9B,CACZ,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE;QACxB,MAAM,QAAQ,EAAE,CAAC;IACnB,CAAC,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"PlayerStrip.d.ts","sourceRoot":"","sources":["../../../src/react/media/PlayerStrip.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PlayerStrip.d.ts","sourceRoot":"","sources":["../../../src/react/media/PlayerStrip.tsx"],"names":[],"mappings":"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"}
@@ -39,7 +39,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
39
39
  import { useEffect, useId, useState } from "react";
40
40
  import { Info, MoreHorizontal, Pause, Play, Repeat, Repeat1, Shuffle, SkipBack, SkipForward, Volume1, Volume2, VolumeX, } from "lucide-react";
41
41
  import { IconButton } from "../components/IconButton.js";
42
- import { lazyPart } from "../components/DataTable/lazyPart.js";
42
+ import { lazyPart, standInPress } from "../components/DataTable/lazyPart.js";
43
43
  import { Tooltip } from "../components/Tooltip.js";
44
44
  import { cn } from "../lib/cn.js";
45
45
  import { splitActions } from "./splitActions.js";
@@ -121,8 +121,8 @@ function OverflowMenu({ actions }) {
121
121
  if (actions.length === 0)
122
122
  return null;
123
123
  const explained = actions.filter((action) => action.hint);
124
- const trigger = (onClick) => (_jsx(IconButton, { className: "cbps__icon", label: "More actions for this track", onClick: onClick, size: "lg", children: _jsx(MoreHorizontal, {}) }));
125
- return (_jsxs(_Fragment, { children: [_jsx(LazyMenu, { align: "end", fallback: trigger(() => setOpen(true)), onOpenChange: setOpen, open: open, items: [
124
+ const trigger = (press) => (_jsx(IconButton, { ...press, className: "cbps__icon", label: "More actions for this track", size: "lg", children: _jsx(MoreHorizontal, {}) }));
125
+ return (_jsxs(_Fragment, { children: [_jsx(LazyMenu, { align: "end", fallback: trigger(standInPress(() => setOpen(true))), onOpenChange: setOpen, open: open, items: [
126
126
  ...actions.map((action) => ({
127
127
  key: action.key,
128
128
  label: action.label,
@@ -137,10 +137,10 @@ function OverflowMenu({ actions }) {
137
137
  : []),
138
138
  ], side: "top", trigger: trigger() }), help ? (_jsx(LazyActionsHelp, { listLabel: "Track actions explained", onClose: () => setHelp(false), open: true, rows: explained.map((action) => ({ key: action.key, icon: action.icon, label: action.label, hint: action.hint })) })) : null] }));
139
139
  }
140
- function ActionButton({ action, onClick }) {
140
+ function ActionButton({ action, ...press }) {
141
141
  return (_jsx(IconButton
142
142
  // A popover trigger is not a toggle: its state is the panel's, which Radix announces.
143
- , { "aria-pressed": action.active === undefined || action.popover ? undefined : action.active, className: cn("cbps__icon", action.active ? "is-active" : "", action.danger ? "is-danger" : ""), disabled: action.disabled ?? false, label: action.label, onClick: onClick ?? action.onClick, size: "lg", tooltip: action.hint ?? action.label, children: action.icon }));
143
+ , { "aria-pressed": action.active === undefined || action.popover ? undefined : action.active, className: cn("cbps__icon", action.active ? "is-active" : "", action.danger ? "is-danger" : ""), disabled: action.disabled ?? false, label: action.label, onClick: press.onClick ?? action.onClick, onPointerDown: press.onPointerDown, size: "lg", tooltip: action.hint ?? action.label, children: action.icon }));
144
144
  }
145
145
  /**
146
146
  * 🔴 Controlled, so a press that lands BEFORE the panel's chunk does is not lost: the fallback
@@ -148,7 +148,7 @@ function ActionButton({ action, onClick }) {
148
148
  */
149
149
  function PopoverAction({ action }) {
150
150
  const [open, setOpen] = useState(false);
151
- return (_jsx(LazyPopover, { align: "center", fallback: _jsx(ActionButton, { action: action, onClick: () => setOpen(true) }), onOpenChange: setOpen, open: open, side: "top", trigger: _jsx(ActionButton, { action: action }), children: action.popover }));
151
+ return (_jsx(LazyPopover, { align: "center", fallback: _jsx(ActionButton, { action: action, ...standInPress(() => setOpen(true)) }), onOpenChange: setOpen, open: open, side: "top", trigger: _jsx(ActionButton, { action: action }), children: action.popover }));
152
152
  }
153
153
  export function PlayerStrip({ art, title, subtitle, onReveal, revealLabel = "Show this track in the list", revealBusy = false, playing, positionMs, durationMs, onToggle, onSeek, onNext, onPrevious, shuffle, onShuffleChange, repeat, onRepeatChange, volume = 1, muted = false, onVolumeChange, onMutedChange, trackActions = [], inlineActions, utilityActions = [], seekLine = true, empty, error = null, errorTone = "danger", formatTime = defaultFormatTime, className, rootRef, ...rest }) {
154
154
  const scrubberId = useId();
@@ -1 +1 @@
1
- {"version":3,"file":"PlayerStrip.js","sourceRoot":"","sources":["../../../src/react/media/PlayerStrip.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PlayerStrip.js","sourceRoot":"","sources":["../../../src/react/media/PlayerStrip.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt",
3
- "version": "5.103.1",
3
+ "version": "5.104.1",
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.",
@@ -965,7 +965,7 @@
965
965
  "@types/react-dom": "^19.2.3",
966
966
  "@vidstack/react": "1.15.6",
967
967
  "@vitejs/plugin-react": "^5.2.0",
968
- "cursedbelt-server": "^4.58.0",
968
+ "cursedbelt-server": "^4.59.0",
969
969
  "cursedops": "^0.23.0",
970
970
  "diff": "^9.0.0",
971
971
  "emoji-mart": "^5.6.0",
@@ -76,6 +76,67 @@ describe('ChoiceGroup', () => {
76
76
  expect(queryByText('Only curators.')).toBeNull();
77
77
  });
78
78
 
79
+ describe("layout='list'", () => {
80
+ const ROWS: ChoiceOption[] = [
81
+ { value: 'root', label: 'Holidays', description: 'Holidays', trailing: 'You are here' },
82
+ { value: 'nested', label: '2019', description: 'Holidays/2019', indent: 2 },
83
+ ];
84
+
85
+ test('each row is a radio holding its two lines and its trailing fact', () => {
86
+ const { getAllByRole, getByText } = render(
87
+ <ChoiceGroup layout='list' aria-label='Destination' options={ROWS} value='root' onChange={() => {}} />,
88
+ );
89
+ expect(getAllByRole('radio').map((radio) => radio.textContent)).toEqual(['HolidaysHolidaysYou are here', '2019Holidays/2019']);
90
+ // The trailing fact is a sibling of the words, so it holds the right edge however long they run.
91
+ expect(getByText('You are here').parentElement?.getAttribute('role')).toBe('radio');
92
+ });
93
+
94
+ test('an indent pads inside the row, on top of its own padding', () => {
95
+ const { getAllByRole } = render(
96
+ <ChoiceGroup layout='list' aria-label='Destination' options={ROWS} value='root' onChange={() => {}} />,
97
+ );
98
+ const [root, nested] = getAllByRole('radio') as [HTMLElement, HTMLElement];
99
+ expect(root.style.paddingInlineStart).toBe('');
100
+ expect(nested.style.paddingInlineStart).toBe('calc(0.625rem + 2rem)');
101
+ });
102
+
103
+ test('a double-click or Enter confirms that row, and an arrow key only chooses', () => {
104
+ const confirmed: string[] = [];
105
+ const { getAllByRole } = render(
106
+ <ChoiceGroup
107
+ layout='list'
108
+ aria-label='Destination'
109
+ options={ROWS}
110
+ value='root'
111
+ onChange={() => {}}
112
+ onConfirm={(next) => confirmed.push(next)}
113
+ />,
114
+ );
115
+ const [root, nested] = getAllByRole('radio') as [HTMLElement, HTMLElement];
116
+ fireEvent.doubleClick(nested);
117
+ fireEvent.keyDown(root, { key: 'Enter' });
118
+ fireEvent.keyDown(root, { key: 'ArrowDown' });
119
+ expect(confirmed).toEqual(['nested', 'root']);
120
+ });
121
+
122
+ test('with no onConfirm, a double-click is two clicks and nothing throws', () => {
123
+ const { getAllByRole } = render(
124
+ <ChoiceGroup layout='list' aria-label='Destination' options={ROWS} value='root' onChange={() => {}} />,
125
+ );
126
+ fireEvent.doubleClick(getAllByRole('radio')[1] as HTMLElement);
127
+ fireEvent.keyDown(getAllByRole('radio')[1] as HTMLElement, { key: 'Enter' });
128
+ });
129
+ });
130
+
131
+ // RadioGroup.Item IS a `<button>`, so `raw-button-resets-face` cannot see it: a host without
132
+ // Tailwind's preflight (desk) draws system-ui 13.33px on any option that does not reset itself.
133
+ test.each(['text', 'picture', 'list'] as const)("layout='%s' resets the browser's button face", (layout) => {
134
+ const { getAllByRole } = render(
135
+ <ChoiceGroup layout={layout} aria-label='Which' options={OPTIONS} value='member' onChange={() => {}} />,
136
+ );
137
+ for (const radio of getAllByRole('radio')) expect(radio.className).toContain('font-[inherit]');
138
+ });
139
+
79
140
  describe("layout='picture'", () => {
80
141
  const PICTURES: ChoiceOption[] = [
81
142
  { value: 'first', label: 'Whichever is first' },
@@ -1,6 +1,6 @@
1
1
  import * as RadioGroup from '@radix-ui/react-radio-group';
2
2
  import { type ReactNode, useId } from 'react';
3
- import { cn } from '../lib/cn.js';
3
+ import { cn, RAW_BUTTON } from '../lib/cn.js';
4
4
  import { TAP_TARGET } from '../lib/tapTarget.js';
5
5
  import { Tooltip } from './Tooltip.js';
6
6
 
@@ -21,6 +21,10 @@ export interface ChoiceOption<T extends string = string> {
21
21
  image?: ReactNode;
22
22
  /** Accessible name for a picture tile whose `label` is not a plain string. */
23
23
  'aria-label'?: string;
24
+ /** `layout='list'` only: a quiet right-aligned fact about the row — a count, "you are here". */
25
+ trailing?: ReactNode;
26
+ /** `layout='list'` only: depth in levels of 1rem, so a flattened tree keeps its shape. */
27
+ indent?: number;
24
28
  }
25
29
 
26
30
  export interface ChoiceGroupProps<T extends string = string> {
@@ -43,14 +47,28 @@ export interface ChoiceGroupProps<T extends string = string> {
43
47
  * `text` (default): a wrapping row of worded options. `picture`: one strip of
44
48
  * square thumbnail tiles, checked by an accent ring — a cover picker, an avatar
45
49
  * picker. The strip does not wrap; put the group in a `ScrollArea axis='x'` when
46
- * it can be longer than its container.
50
+ * it can be longer than its container. `list`: full-width stacked rows, each with
51
+ * a `trailing` slot and an `indent` — a list of moments, a folder tree. Give the
52
+ * group a height through `className` when it can outgrow its container.
47
53
  */
48
- layout?: 'text' | 'picture';
54
+ layout?: 'text' | 'picture' | 'list';
49
55
  /** `layout='picture'` tile edge in px. Default 64. */
50
56
  tileSize?: number;
57
+ /**
58
+ * `layout='list'` only: a double-click or Enter on a row takes it straight to the
59
+ * action the choice was for, without reaching for the dialog's button. `onChange`
60
+ * has already reported that row by then.
61
+ */
62
+ onConfirm?: (value: T) => void;
51
63
  className?: string;
52
64
  }
53
65
 
66
+ const ROOT_LAYOUT = { text: 'flex-wrap gap-1.5', picture: 'gap-2', list: 'flex-col gap-0.5' } as const;
67
+
68
+ /** Focus, checked and disabled, the same on a chip and on a row. */
69
+ const OPTION_STATES =
70
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[state=checked]:border-accent data-[state=checked]:bg-accent/10 data-[state=checked]:font-medium disabled:cursor-not-allowed disabled:opacity-50';
71
+
54
72
  /**
55
73
  * Pick ONE of a few options whose labels are sentences — "No — just their own
56
74
  * page" / "Yes — they can edit anyone, like you". The options are all visible at
@@ -61,6 +79,7 @@ export interface ChoiceGroupProps<T extends string = string> {
61
79
  * - a long or data-driven list → `SelectField` / `ChoiceMenu`
62
80
  * - a color → `SwatchPicker`
63
81
  * - one picture out of several (a cover, an avatar) → THIS, `layout='picture'`
82
+ * - rows that each carry two lines and a fact, or a tree → THIS, `layout='list'`
64
83
  * - a handful of answers that each need words → THIS
65
84
  *
66
85
  * ── 🔴 Why this exists: the hidden-radio trap (family, 2026-09-26) ──────────
@@ -93,6 +112,7 @@ export function ChoiceGroup<T extends string = string>({
93
112
  name,
94
113
  layout = 'text',
95
114
  tileSize = 64,
115
+ onConfirm,
96
116
  className,
97
117
  ...rest
98
118
  }: ChoiceGroupProps<T>) {
@@ -117,31 +137,28 @@ export function ChoiceGroup<T extends string = string>({
117
137
  onValueChange={(next) => onChange(next as T)}
118
138
  disabled={disabled}
119
139
  name={name}
120
- className={cn('relative flex min-w-0', layout === 'picture' ? 'gap-2' : 'flex-wrap gap-1.5')}
140
+ className={cn('relative flex min-w-0', ROOT_LAYOUT[layout])}
121
141
  >
122
142
  {options.map((option) =>
123
143
  layout === 'picture' ? (
124
144
  <PictureTile key={option.value} option={option} size={tileSize} />
145
+ ) : layout === 'list' ? (
146
+ <ListRow key={option.value} option={option} onConfirm={onConfirm} />
125
147
  ) : (
126
148
  <RadioGroup.Item
127
149
  key={option.value}
128
150
  value={option.value}
129
151
  disabled={option.disabled}
130
152
  className={cn(
153
+ RAW_BUTTON,
131
154
  'flex min-w-0 max-w-full flex-col items-start rounded-md border border-border bg-transparent px-2.5 py-1.5 text-left text-sm text-foreground transition-colors',
132
155
  'hover:border-accent',
133
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
134
- 'data-[state=checked]:border-accent data-[state=checked]:bg-accent/10 data-[state=checked]:font-medium',
135
- 'disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-border',
156
+ OPTION_STATES,
157
+ 'disabled:hover:border-border',
136
158
  TAP_TARGET,
137
159
  )}
138
160
  >
139
- <span className='min-w-0 break-words'>{option.label}</span>
140
- {option.description != null ? (
141
- <span className='min-w-0 break-words text-xs font-normal text-muted-foreground'>
142
- {option.description}
143
- </span>
144
- ) : null}
161
+ <OptionWords option={option} />
145
162
  </RadioGroup.Item>
146
163
  ),
147
164
  )}
@@ -160,6 +177,58 @@ export function ChoiceGroup<T extends string = string>({
160
177
  );
161
178
  }
162
179
 
180
+ /** What keeps `label` and `description` two lines, in a chip and in a row alike. */
181
+ function OptionWords<T extends string>({ option }: { option: ChoiceOption<T> }) {
182
+ return (
183
+ <>
184
+ <span className='min-w-0 max-w-full break-words'>{option.label}</span>
185
+ {option.description != null ? (
186
+ <span className='min-w-0 max-w-full break-words text-xs font-normal text-muted-foreground'>
187
+ {option.description}
188
+ </span>
189
+ ) : null}
190
+ </>
191
+ );
192
+ }
193
+
194
+ /**
195
+ * One full-width row of a `layout='list'` group: the words on the left, `trailing` on the
196
+ * right. The indent is padding, not a margin, so a nested row's highlight still spans the list.
197
+ */
198
+ function ListRow<T extends string>({ option, onConfirm }: { option: ChoiceOption<T>; onConfirm?: (value: T) => void }) {
199
+ return (
200
+ <RadioGroup.Item
201
+ value={option.value}
202
+ disabled={option.disabled}
203
+ // 0.625rem is the row's own `px-2.5`, which a `padding-inline-start` would otherwise replace.
204
+ style={option.indent ? { paddingInlineStart: `calc(0.625rem + ${option.indent}rem)` } : undefined}
205
+ onDoubleClick={onConfirm ? () => onConfirm(option.value) : undefined}
206
+ onKeyDown={
207
+ onConfirm
208
+ ? (event) => {
209
+ if (event.key === 'Enter') onConfirm(option.value);
210
+ }
211
+ : undefined
212
+ }
213
+ className={cn(
214
+ RAW_BUTTON,
215
+ 'flex w-full min-w-0 items-center gap-3 rounded-md border border-transparent px-2.5 py-1.5 text-left text-sm text-foreground transition-colors',
216
+ 'hover:bg-muted',
217
+ OPTION_STATES,
218
+ 'disabled:hover:bg-transparent',
219
+ TAP_TARGET,
220
+ )}
221
+ >
222
+ <span className='flex min-w-0 flex-1 flex-col items-start'>
223
+ <OptionWords option={option} />
224
+ </span>
225
+ {option.trailing != null ? (
226
+ <span className='shrink-0 text-xs font-normal text-muted-foreground'>{option.trailing}</span>
227
+ ) : null}
228
+ </RadioGroup.Item>
229
+ );
230
+ }
231
+
163
232
  /**
164
233
  * One square tile of a `layout='picture'` group. Still a Radix radio item — roving
165
234
  * tabindex, arrow keys and `aria-checked` come from the group, exactly as for a text
@@ -175,6 +244,7 @@ function PictureTile<T extends string>({ option, size }: { option: ChoiceOption<
175
244
  aria-label={option.image != null ? name : undefined}
176
245
  style={{ width: size, height: size }}
177
246
  className={cn(
247
+ RAW_BUTTON,
178
248
  'flex shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-card text-center text-caption leading-tight text-foreground transition-colors',
179
249
  'hover:border-accent',
180
250
  'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
@@ -0,0 +1,108 @@
1
+ import { afterEach, describe, expect, test } from 'bun:test';
2
+ import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
3
+ import { useState } from 'react';
4
+ import type * as RowActionsModule from './RowActions.js';
5
+
6
+ afterEach(cleanup);
7
+
8
+ /**
9
+ * A copy of `RowActions.tsx` with its OWN `MenuPart` — nothing has loaded its chunk, and nothing can
10
+ * until a test yields, because a dynamic import never settles inside the synchronous run after
11
+ * `render`. So what a test does before its first `await` happens BEFORE the chunk lands, every time.
12
+ */
13
+ async function coldRowActions(): Promise<typeof RowActionsModule> {
14
+ return (await import(`./RowActions.tsx?cold=${Math.random()}`)) as typeof RowActionsModule;
15
+ }
16
+
17
+ const LABEL = 'More for Alien';
18
+ const MENU = [{ key: 'retry', label: 'Retry' }];
19
+ const kebab = () => screen.getByRole('button', { name: LABEL });
20
+
21
+ describe('RowActions — a press on the ⋯ before its menu chunk lands (forge task 4172)', () => {
22
+ test('🔴 a click is remembered: the menu opens when the chunk lands', async () => {
23
+ const { RowActions } = await coldRowActions();
24
+ render(<RowActions row={{}} menu={MENU} menuLabel={LABEL} />);
25
+ fireEvent.click(kebab());
26
+ expect(screen.queryByRole('menuitem')).toBeNull();
27
+ expect(await screen.findByRole('menuitem', { name: 'Retry' })).toBeTruthy();
28
+ });
29
+
30
+ test('🔴 a press still held as the chunk lands is not lost — its click goes to neither button', async () => {
31
+ const { RowActions } = await coldRowActions();
32
+ render(<RowActions row={{}} menu={MENU} menuLabel={LABEL} />);
33
+ fireEvent.pointerDown(kebab(), { button: 0 });
34
+ expect(await screen.findByRole('menuitem', { name: 'Retry' })).toBeTruthy();
35
+ });
36
+
37
+ test('the kebab spins while the press waits, the only answer a slow link can give', async () => {
38
+ const { RowActions } = await coldRowActions();
39
+ render(<RowActions row={{}} menu={MENU} menuLabel={LABEL} />);
40
+ expect(kebab().getAttribute('aria-haspopup')).toBe('menu');
41
+ expect(kebab().hasAttribute('aria-busy')).toBe(false);
42
+ fireEvent.click(kebab());
43
+ expect(kebab().getAttribute('aria-busy')).toBe('true');
44
+ });
45
+
46
+ test('a second press, by someone who thinks the first was lost, does not cancel it', async () => {
47
+ const { RowActions } = await coldRowActions();
48
+ render(<RowActions row={{}} menu={MENU} menuLabel={LABEL} />);
49
+ fireEvent.click(kebab());
50
+ fireEvent.click(kebab());
51
+ expect(await screen.findByRole('menuitem', { name: 'Retry' })).toBeTruthy();
52
+ });
53
+
54
+ test('a right button or a ctrl press is not a press on the menu', async () => {
55
+ const { RowActions, preloadRowMenu } = await coldRowActions();
56
+ render(<RowActions row={{}} menu={MENU} menuLabel={LABEL} />);
57
+ fireEvent.pointerDown(kebab(), { button: 2 });
58
+ fireEvent.pointerDown(kebab(), { button: 0, ctrlKey: true });
59
+ await act(preloadRowMenu);
60
+ await waitFor(() => expect(kebab().getAttribute('aria-expanded')).toBe('false'));
61
+ expect(screen.queryByRole('menuitem')).toBeNull();
62
+ });
63
+
64
+ test('a table that controls the menu hears the press, and its answer opens it', async () => {
65
+ const { RowActions } = await coldRowActions();
66
+ const heard: boolean[] = [];
67
+ function Controlled() {
68
+ const [open, setOpen] = useState(false);
69
+ return (
70
+ <RowActions
71
+ row={{}}
72
+ menu={MENU}
73
+ menuLabel={LABEL}
74
+ menuOpen={open}
75
+ onMenuOpenChange={(next) => {
76
+ heard.push(next);
77
+ setOpen(next);
78
+ }}
79
+ />
80
+ );
81
+ }
82
+ render(<Controlled />);
83
+ fireEvent.click(kebab());
84
+ expect(await screen.findByRole('menuitem', { name: 'Retry' })).toBeTruthy();
85
+ expect(heard).toEqual([true]);
86
+ });
87
+
88
+ test('the menu that mounted open still closes: a pick runs and takes it away', async () => {
89
+ const { RowActions } = await coldRowActions();
90
+ const picked: string[] = [];
91
+ render(
92
+ <RowActions row={{}} menu={[{ key: 'retry', label: 'Retry', onClick: () => picked.push('retry') }]} menuLabel={LABEL} />,
93
+ );
94
+ fireEvent.click(kebab());
95
+ fireEvent.click(await screen.findByRole('menuitem', { name: 'Retry' }));
96
+ expect(picked).toEqual(['retry']);
97
+ await waitFor(() => expect(screen.queryByRole('menuitem')).toBeNull());
98
+ });
99
+
100
+ test('after the chunk, the ⋯ is Radix\'s own: closed until it is pressed, open on the press', async () => {
101
+ const { RowActions, preloadRowMenu } = await coldRowActions();
102
+ await preloadRowMenu();
103
+ render(<RowActions row={{}} menu={MENU} menuLabel={LABEL} />);
104
+ expect(kebab().getAttribute('aria-expanded')).toBe('false');
105
+ fireEvent.pointerDown(kebab(), { button: 0 });
106
+ expect(await screen.findByRole('menuitem', { name: 'Retry' })).toBeTruthy();
107
+ });
108
+ });
@@ -1,9 +1,10 @@
1
1
  import { EllipsisVertical, Pencil, Trash2 } from 'lucide-react';
2
+ import { useState } from 'react';
2
3
  import { Button } from '../Button.js';
3
4
  import type { DropdownMenuItem } from '../DropdownMenu.js';
4
- import { IconButton } from '../IconButton.js';
5
+ import { IconButton, type IconButtonProps } from '../IconButton.js';
5
6
  import type { DataTableRowAction } from './types.js';
6
- import { lazyPart } from './lazyPart.js';
7
+ import { lazyPart, standInPress } from './lazyPart.js';
7
8
 
8
9
  // The kebab's menu is Radix's Menu, and most tables never draw a kebab — so it loads
9
10
  // with the first row that has one, not with the table (forge task 2309). Edit and
@@ -48,8 +49,12 @@ export function RowActions<TRow>({
48
49
  onMenuOpenChange,
49
50
  ...rest
50
51
  }: RowActionsProps<TRow>) {
51
- const kebab = (
52
- <IconButton label={menuLabel} className='size-8 pointer-coarse:min-w-11 [&_svg]:size-4'>
52
+ // 🔴 Always controlled, so a press before the menu's chunk lands is not lost (forge task 4172).
53
+ const [ownOpen, setOwnOpen] = useState(false);
54
+ const open = onMenuOpenChange ? (menuOpen ?? false) : ownOpen;
55
+ const setOpen = onMenuOpenChange ?? setOwnOpen;
56
+ const kebab = (standIn?: Partial<IconButtonProps>) => (
57
+ <IconButton {...standIn} label={menuLabel} className='size-8 pointer-coarse:min-w-11 [&_svg]:size-4'>
53
58
  <EllipsisVertical />
54
59
  </IconButton>
55
60
  );
@@ -121,13 +126,19 @@ export function RowActions<TRow>({
121
126
  ) : null}
122
127
  {menu && menu.length > 0 ? (
123
128
  // Until the menu arrives the kebab is already there, the same button in the same
124
- // place — so nothing shifts and nothing flashes; a click in those milliseconds opens nothing.
129
+ // place — so nothing shifts and nothing flashes. A press in those moments spins the kebab,
130
+ // which on a slow link is the only answer it has, and the menu mounts open.
125
131
  <MenuPart
126
132
  align='end'
127
- trigger={kebab}
133
+ trigger={kebab()}
128
134
  items={menu}
129
- fallback={kebab}
130
- {...(onMenuOpenChange ? { open: menuOpen ?? false, onOpenChange: onMenuOpenChange } : {})}
135
+ fallback={kebab({
136
+ 'aria-haspopup': 'menu',
137
+ loading: open,
138
+ ...standInPress(() => setOpen(true)),
139
+ })}
140
+ open={open}
141
+ onOpenChange={setOpen}
131
142
  />
132
143
  ) : null}
133
144
  </div>
@@ -15,7 +15,14 @@
15
15
  * the moment the chunk lands, and React would REMOUNT the part — a half-typed search,
16
16
  * an open menu, gone.
17
17
  */
18
- import { type Attributes, type ComponentType, type ReactNode, Suspense, useState } from 'react';
18
+ import {
19
+ type Attributes,
20
+ type ComponentType,
21
+ type PointerEvent,
22
+ type ReactNode,
23
+ Suspense,
24
+ useState,
25
+ } from 'react';
19
26
  import { lazyWithReload } from '../../lazy/staleChunk.js';
20
27
 
21
28
  export interface LazyPart<P> {
@@ -24,6 +31,29 @@ export interface LazyPart<P> {
24
31
  preload: () => Promise<void>;
25
32
  }
26
33
 
34
+ export interface StandInPress {
35
+ onPointerDown: (event: PointerEvent) => void;
36
+ onClick: () => void;
37
+ }
38
+
39
+ /**
40
+ * 🔴 What a lazy trigger's stand-in (the `fallback` drawn as the trigger) listens to, so a press
41
+ * before the chunk lands is not lost (forge task 4172). `press` records it in the state the part
42
+ * is controlled by, and the part mounts already open.
43
+ *
44
+ * Radix's rule for a press, because the landing replaces the button: one that lands between the
45
+ * pointerdown and the release leaves the browser's `click` with neither button. The `click` is
46
+ * still heard, for the keyboard.
47
+ */
48
+ export function standInPress(press: () => void): StandInPress {
49
+ return {
50
+ onPointerDown: (event) => {
51
+ if (event.button === 0 && !event.ctrlKey) press();
52
+ },
53
+ onClick: press,
54
+ };
55
+ }
56
+
27
57
  export function lazyPart<P extends object>(load: () => Promise<ComponentType<P>>): LazyPart<P> {
28
58
  let loaded: ComponentType<P> | null = null;
29
59
  let pending: Promise<ComponentType<P>> | null = null;
@@ -53,7 +53,7 @@ import {
53
53
  import type { ActionsHelpProps } from "../components/ActionsHelp.js";
54
54
  import type { DropdownMenuProps } from "../components/DropdownMenu.js";
55
55
  import { IconButton } from "../components/IconButton.js";
56
- import { lazyPart } from "../components/DataTable/lazyPart.js";
56
+ import { lazyPart, type StandInPress, standInPress } from "../components/DataTable/lazyPart.js";
57
57
  import type { PopoverProps } from "../components/Popover.js";
58
58
  import { Tooltip } from "../components/Tooltip.js";
59
59
  import { cn } from "../lib/cn.js";
@@ -268,8 +268,8 @@ function OverflowMenu({ actions }: { actions: PlayerStripAction[] }): React.Reac
268
268
  const [help, setHelp] = useState(false);
269
269
  if (actions.length === 0) return null;
270
270
  const explained = actions.filter((action) => action.hint);
271
- const trigger = (onClick?: () => void) => (
272
- <IconButton className="cbps__icon" label="More actions for this track" onClick={onClick} size="lg">
271
+ const trigger = (press?: StandInPress) => (
272
+ <IconButton {...press} className="cbps__icon" label="More actions for this track" size="lg">
273
273
  <MoreHorizontal />
274
274
  </IconButton>
275
275
  );
@@ -277,7 +277,7 @@ function OverflowMenu({ actions }: { actions: PlayerStripAction[] }): React.Reac
277
277
  <>
278
278
  <LazyMenu
279
279
  align="end"
280
- fallback={trigger(() => setOpen(true))}
280
+ fallback={trigger(standInPress(() => setOpen(true)))}
281
281
  onOpenChange={setOpen}
282
282
  open={open}
283
283
  items={[
@@ -309,7 +309,7 @@ function OverflowMenu({ actions }: { actions: PlayerStripAction[] }): React.Reac
309
309
  );
310
310
  }
311
311
 
312
- function ActionButton({ action, onClick }: { action: PlayerStripAction; onClick?: () => void }): React.ReactNode {
312
+ function ActionButton({ action, ...press }: { action: PlayerStripAction } & Partial<StandInPress>): React.ReactNode {
313
313
  return (
314
314
  <IconButton
315
315
  // A popover trigger is not a toggle: its state is the panel's, which Radix announces.
@@ -317,7 +317,8 @@ function ActionButton({ action, onClick }: { action: PlayerStripAction; onClick?
317
317
  className={cn("cbps__icon", action.active ? "is-active" : "", action.danger ? "is-danger" : "")}
318
318
  disabled={action.disabled ?? false}
319
319
  label={action.label}
320
- onClick={onClick ?? action.onClick}
320
+ onClick={press.onClick ?? action.onClick}
321
+ onPointerDown={press.onPointerDown}
321
322
  size="lg"
322
323
  tooltip={action.hint ?? action.label}
323
324
  >
@@ -335,7 +336,7 @@ function PopoverAction({ action }: { action: PlayerStripAction }): React.ReactNo
335
336
  return (
336
337
  <LazyPopover
337
338
  align="center"
338
- fallback={<ActionButton action={action} onClick={() => setOpen(true)} />}
339
+ fallback={<ActionButton action={action} {...standInPress(() => setOpen(true))} />}
339
340
  onOpenChange={setOpen}
340
341
  open={open}
341
342
  side="top"
@@ -358,6 +358,32 @@ describe("playerStrip.css — the layout the owner specified", () => {
358
358
  });
359
359
  });
360
360
 
361
+ describe("a press still held as a lazy chunk lands (forge task 4172)", () => {
362
+ /** A copy with its own lazy parts: nothing can land before the test's first `await` after `render`. */
363
+ const coldStrip = async () => ((await import(`./PlayerStrip.tsx?cold=${Math.random()}`)) as { PlayerStrip: typeof PlayerStrip }).PlayerStrip;
364
+
365
+ test("🔴 the ⋯ opens — the landing replaces the button, so no click ever comes", async () => {
366
+ const Cold = await coldStrip();
367
+ const three = ["share", "keep", "tag"].map((key) => ({ key, label: key, icon: null }));
368
+ render(<Cold {...base} inlineActions={1} trackActions={three} />);
369
+ fireEvent.pointerDown(screen.getByRole("button", { name: "More actions for this track" }), { button: 0 });
370
+ const menu = await screen.findByRole("menu", { hidden: true });
371
+ expect(await within(menu).findByText("keep")).toBeDefined();
372
+ });
373
+
374
+ test("🔴 a panel opens the same way", async () => {
375
+ const Cold = await coldStrip();
376
+ render(
377
+ <Cold
378
+ {...base}
379
+ trackActions={[{ key: "rate", label: "Rate this track", icon: <span>★</span>, popover: <p>five stars here</p> }]}
380
+ />,
381
+ );
382
+ fireEvent.pointerDown(screen.getByRole("button", { name: "Rate this track" }), { button: 0 });
383
+ expect(await screen.findByText("five stars here")).not.toBeNull();
384
+ });
385
+ });
386
+
361
387
  describe("a track action that opens a panel", () => {
362
388
  test("🔴 a press opens the popover's content instead of acting, and it is reachable from the strip", async () => {
363
389
  render(