@estiva-app/ui 0.3.0 → 0.5.0

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 +1 @@
1
- {"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../src/AppShell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;IAC9B,uEAAuE;IACvE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,gEAAgE;IAChE,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,qEAAqE;IACrE,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,qFAAqF;IACrF,GAAG,EAAE,SAAS,CAAA;IACd,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,QAAQ,CAAC,EAAE,OAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,aAAa,+BAmCjH"}
1
+ {"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../src/AppShell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;IAC9B,uEAAuE;IACvE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,gEAAgE;IAChE,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,qEAAqE;IACrE,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,qFAAqF;IACrF,GAAG,EAAE,SAAS,CAAA;IACd,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,QAAQ,CAAC,EAAE,OAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,aAAa,+BA0CjH"}
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../src/Avatar.tsx"],"names":[],"mappings":"AA2BA,eAAO,MAAM,MAAM,GAAI,KAAK,MAAM,WAIjC,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,WAIvC,CAAA;AAED,MAAM,WAAW,WAAW;IAC1B,wGAAwG;IACxG,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uGAAuG;IACvG,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAQ,EAAE,IAAS,EAAE,SAAS,EAAE,EAAE,WAAW,+BA0BhF"}
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../src/Avatar.tsx"],"names":[],"mappings":"AA2BA,eAAO,MAAM,MAAM,GAAI,KAAK,MAAM,WAIjC,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,WAIvC,CAAA;AAED,MAAM,WAAW,WAAW;IAC1B,wGAAwG;IACxG,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uGAAuG;IACvG,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAQ,EAAE,IAAS,EAAE,SAAS,EAAE,EAAE,WAAW,+BAuChF"}
@@ -6,10 +6,13 @@
6
6
  * wrapper resolves pictures itself; a consumer without such a wrapper could
7
7
  * never have shown one.
8
8
  *
9
- * The ring sits on the Avatar itself: the old extra wrapper was a 24px
10
- * window minus a 2px border with a fixed 24px Avatar inside, so
11
- * overflow-hidden clipped 4px of face and the right edge of the initials
12
- * with it, which is how "CO" rendered as "C(". One box, whole letters.
9
+ * The ring is drawn OUTSIDE the face, as a shadow (2026-09-03). It was a
10
+ * `border` before, which box-sizing takes out of the inside: a 24px avatar
11
+ * showed 20px of face, and at 18px only 14px — noticeably smaller than the
12
+ * number asked for. A shadow costs the face nothing, so `size` means the
13
+ * size. It replaced an even older wrapper whose `overflow-hidden` clipped
14
+ * 4px of face and the right edge of the initials with it ("CO" as "C(") —
15
+ * hence the rule this file keeps: nothing that clips ever wraps the face.
13
16
  */
14
17
  export interface AvatarGroupMember {
15
18
  name: string;
@@ -18,6 +21,12 @@ export interface AvatarGroupMember {
18
21
  }
19
22
  export interface AvatarGroupProps {
20
23
  members: AvatarGroupMember[];
24
+ /**
25
+ * Face size in pixels; the overlap follows it. 24 is the members pill,
26
+ * 18 the replies row (Katerina, 2026-09-03) — that row drew its own stack
27
+ * for two months for want of this one number, and drifted while it did.
28
+ */
29
+ size?: number;
21
30
  }
22
- export declare function AvatarGroup({ members }: AvatarGroupProps): import("react").JSX.Element;
31
+ export declare function AvatarGroup({ members, size }: AvatarGroupProps): import("react").JSX.Element;
23
32
  //# sourceMappingURL=AvatarGroup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarGroup.d.ts","sourceRoot":"","sources":["../src/AvatarGroup.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAC7B;AAED,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,gBAAgB,+BAgBxD"}
1
+ {"version":3,"file":"AvatarGroup.d.ts","sourceRoot":"","sources":["../src/AvatarGroup.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,IAAS,EAAE,EAAE,gBAAgB,+BA8BnE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ChipInput.d.ts","sourceRoot":"","sources":["../src/ChipInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6E,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAMjH;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,mDAAmD;IACnD,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,cAAc,+BAiChF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe;IACzE,KAAK,EAAE,CAAC,EAAE,CAAA;IACV,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,IAAI,CAAA;IAC7B,4CAA4C;IAC5C,OAAO,EAAE,CAAC,EAAE,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,qDAAqD;IACrD,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,SAAS,CAAA;IACtC,6CAA6C;IAC7C,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,SAAS,CAAA;CACtC;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,EAAE,EACrE,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAuB,EACvB,SAAS,EACT,UAAe,EACf,WAAW,EACX,UAAU,GACX,EAAE,cAAc,CAAC,CAAC,CAAC,+BA4InB"}
1
+ {"version":3,"file":"ChipInput.d.ts","sourceRoot":"","sources":["../src/ChipInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6E,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAOjH;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,mDAAmD;IACnD,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,cAAc,+BAiChF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe;IACzE,KAAK,EAAE,CAAC,EAAE,CAAA;IACV,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,IAAI,CAAA;IAC7B,4CAA4C;IAC5C,OAAO,EAAE,CAAC,EAAE,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,qDAAqD;IACrD,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,SAAS,CAAA;IACtC,6CAA6C;IAC7C,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,SAAS,CAAA;CACtC;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,EAAE,EACrE,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAuB,EACvB,SAAS,EACT,UAAe,EACf,WAAW,EACX,UAAU,GACX,EAAE,cAAc,CAAC,CAAC,CAAC,+BAuJnB"}
package/dist/Field.d.ts CHANGED
@@ -1,13 +1,40 @@
1
- import type { ReactNode } from 'react';
1
+ import { type ReactNode } from 'react';
2
2
  /**
3
- * Peek's Field (2026-08-28), verbatim: a label over a control, 8px apart,
4
- * with a red asterisk when required. The label is the `input-label` type
5
- * token as a plain class, never merged.
3
+ * The id a surrounding `Field` wants this control to have, falling back to the
4
+ * caller's own outside one.
5
+ *
6
+ * **Inside a Field, the Field wins**, which is the opposite of what I wrote
7
+ * first and the test caught within the minute. Letting a control's own `id`
8
+ * take precedence leaves the label's `htmlFor` pointing at the id the Field
9
+ * generated and the control answering to a different one — which is this
10
+ * ticket's defect exactly, reproduced by the fix for it, and it fails with the
11
+ * same message: *"Found a label with the text of: Title, however no form
12
+ * control was found associated to that label."*
13
+ *
14
+ * A caller who needs to choose the id names it on the Field (`htmlFor`), which
15
+ * is the one place that can set both halves. Outside a Field there is nothing
16
+ * to disagree with, so the caller's id is used.
17
+ */
18
+ export declare function useFieldControlId(ownId?: string): string | undefined;
19
+ /**
20
+ * Peek's Field (2026-08-28): a label over a control, 8px apart, with a red
21
+ * asterisk when required. The label is the `input-label` type token as a plain
22
+ * class, never merged.
23
+ *
24
+ * The label names its control (SHA-17). It did not, and the control was a
25
+ * *sibling* of the label with no `htmlFor`, so there was neither an explicit
26
+ * nor an implicit association: a screen reader announced an unlabelled edit
27
+ * box and clicking the label focused nothing.
6
28
  */
7
29
  export interface FieldProps {
8
30
  label: string;
9
31
  required?: boolean;
32
+ /**
33
+ * Override the generated id. Only needed when something outside has to name
34
+ * the control — an `aria-describedby` elsewhere, or a form library.
35
+ */
36
+ htmlFor?: string;
10
37
  children: ReactNode;
11
38
  }
12
- export declare function Field({ label, required, children }: FieldProps): import("react").JSX.Element;
39
+ export declare function Field({ label, required, htmlFor, children }: FieldProps): import("react").JSX.Element;
13
40
  //# sourceMappingURL=Field.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../src/Field.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,QAAgB,EAAE,QAAQ,EAAE,EAAE,UAAU,+BAUtE"}
1
+ {"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../src/Field.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAoBxE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGpE;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,QAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,UAAU,+BAe/E"}
@@ -47,12 +47,17 @@ export interface IdentityMenuProps {
47
47
  }
48
48
  export interface IdentityPanelProps extends Omit<IdentityMenuProps, 'compact' | 'className'> {
49
49
  onClose: () => void;
50
+ /** The trigger to hang from — the panel portals to the body and fits the
51
+ * viewport, so no header, sidebar or scroll container can cover it (the
52
+ * z-10 floating top bar trapped the old in-flow panel under a z-20 panel
53
+ * header, 2026-09-03). Absent, the panel stands in flow — the stories. */
54
+ anchor?: HTMLElement | null;
50
55
  /** On the Menu surface — the stories pass `static` to stand it in flow. */
51
56
  className?: string;
52
57
  }
53
58
  /** The menu alone — what `IdentityMenu` opens. Exported so the stories show
54
59
  * the designed artifact rather than a closed trigger, and for any surface
55
60
  * that wants the panel without the trigger. */
56
- export declare function IdentityPanel({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, className, children }: IdentityPanelProps): import("react").JSX.Element;
61
+ export declare function IdentityPanel({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, anchor, className, children }: IdentityPanelProps): import("react").JSX.Element;
57
62
  export declare function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact, className, children }: IdentityMenuProps): import("react").JSX.Element;
58
63
  //# sourceMappingURL=IdentityMenu.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IdentityMenu.d.ts","sourceRoot":"","sources":["../src/IdentityMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAOhD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,QAAQ;IACvB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,QAAQ,CAAA;IACZ,qEAAqE;IACrE,QAAQ,EAAE,OAAO,CAAA;IACjB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC,CAAA;CAC1D;AAED,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,WAAW,CAAC;IAC1F,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;gDAEgD;AAChD,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,kBAAkB,+BAmDvI;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,iBAAiB,+BAqC7I"}
1
+ {"version":3,"file":"IdentityMenu.d.ts","sourceRoot":"","sources":["../src/IdentityMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAOxD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,QAAQ;IACvB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,QAAQ,CAAA;IACZ,qEAAqE;IACrE,QAAQ,EAAE,OAAO,CAAA;IACjB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC,CAAA;CAC1D;AAED,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,WAAW,CAAC;IAC1F,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB;;;+EAG2E;IAC3E,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;gDAEgD;AAChD,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,kBAAkB,+BAmD/I;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,iBAAiB,+BA0C7I"}
package/dist/Menu.d.ts CHANGED
@@ -16,14 +16,39 @@ import { type ComponentPropsWithRef, type ReactNode } from 'react';
16
16
  * row; and the two exits every menu has — Escape and a click outside —
17
17
  * owned by the menu, never copied into a caller.
18
18
  *
19
- * Two anchorings: `position` portals it to the body at fixed viewport
20
- * coordinates (for menus opened inside scrolling containers that clip);
21
- * without it the menu hangs below its trigger, right-aligned, and the
22
- * caller's wrapper is `relative`.
19
+ * Where it goes is owned here too (2026-09-03), because the two ways a menu
20
+ * goes wrong are both placement: it opens inside a stacking context or a
21
+ * scroll container and something covers or clips it, or it opens near an
22
+ * edge and runs off the screen. Both shipped — the identity menu vanished
23
+ * under a z-indexed panel header, a submenu was cut by the right edge — so
24
+ * the shell now portals to the body (nothing in an app can cover the body's
25
+ * last child at z-50) and fits itself to the viewport (fit.ts, the same
26
+ * measured geometry Select uses). A caller hands over a trigger, not
27
+ * coordinates.
28
+ *
29
+ * Three anchorings, in order of preference:
30
+ * - `anchor` (an element, usually the trigger): portalled, measured, and
31
+ * placed by `fitMenu` — under the anchor, flipped above when the room
32
+ * below is worse, clamped inside the viewport, height-capped with its own
33
+ * scrollbar. `align="right"` hangs the menu's right edge from the
34
+ * anchor's. Closes on resize and on any page scroll, because both move
35
+ * the anchor out from under it.
36
+ * - `position` (viewport coordinates the caller computed): portalled and
37
+ * clamped (`clampBox`) — the caller's corner survives, but can no longer
38
+ * land off screen.
39
+ * - neither: in-flow under a `relative` wrapper, right-aligned. For stories
40
+ * and static surfaces only — inside an app this mode inherits every
41
+ * ancestor's stacking context and clip, which is how the identity menu
42
+ * got covered.
23
43
  */
24
44
  export interface MenuProps {
25
45
  onClose: () => void;
26
- /** Viewport coordinates; the menu is portalled, hung from `top`, and aligned to whichever edge is given. */
46
+ /** The trigger an element, or the rect a click handler already measured.
47
+ * The menu portals to the body and places itself against it. */
48
+ anchor?: HTMLElement | DOMRect | null;
49
+ /** With `anchor`: which of the menu's edges hangs from the anchor's. Default left. */
50
+ align?: 'left' | 'right';
51
+ /** Viewport coordinates; the menu is portalled, hung from `top`, aligned to whichever edge is given, and clamped on screen. */
27
52
  position?: {
28
53
  top: number;
29
54
  right: number;
@@ -31,10 +56,38 @@ export interface MenuProps {
31
56
  top: number;
32
57
  left: number;
33
58
  };
59
+ /** Close 150ms after the pointer leaves the menu — the hover-flow menus
60
+ * (quick-menu cards) dismiss this way. The grace period is shared with any
61
+ * open MenuSub panel, so crossing into a portalled submenu never counts as
62
+ * leaving. */
63
+ closeOnLeave?: boolean;
64
+ children: ReactNode;
65
+ className?: string;
66
+ }
67
+ export declare function Menu({ onClose, anchor, align, position, closeOnLeave, children, className }: MenuProps): import("react").JSX.Element;
68
+ /**
69
+ * A row that opens another menu beside it — the submenu two Peek menus
70
+ * hand-rolled before this, one of which dropped the ref its edge-flip
71
+ * measured and shipped a submenu cut off by the screen (2026-09-03).
72
+ *
73
+ * Hover-timed like those were: opens at once, closes 150ms after the
74
+ * pointer leaves row and panel both, so the diagonal from row to panel
75
+ * survives. The panel portals to the body and is placed by `fitSubmenu` —
76
+ * right of the row when it fits, left when it does not, never past an edge
77
+ * — so it also escapes whatever container its menu happens to be in.
78
+ */
79
+ export interface MenuSubProps {
80
+ /** The trigger row's label. */
81
+ label: string;
82
+ leading?: ReactNode;
83
+ /** Mark the trigger row as holding a current value. */
84
+ selected?: boolean;
85
+ /** The submenu's rows. */
34
86
  children: ReactNode;
87
+ /** On the submenu panel. */
35
88
  className?: string;
36
89
  }
37
- export declare function Menu({ onClose, position, children, className }: MenuProps): import("react").JSX.Element;
90
+ export declare function MenuSub({ label, leading, selected, children, className }: MenuSubProps): import("react").JSX.Element;
38
91
  export interface MenuItemProps extends Omit<ComponentPropsWithRef<'button'>, 'children'> {
39
92
  label?: string;
40
93
  /** Replaces the label/description block — for rows whose middle is richer
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../src/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,qBAAqB,EAAsB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAMzG;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,4GAA4G;IAC5G,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACzE,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,SAAS,+BAoCzE;AAED,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;8EAC0E;IAC1E,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB;;wCAEoC;IACpC,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzB,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mGAAmG;IACnG,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,yFAAyF;IACzF,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAgB,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,+BAyC3K;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAe,EAAE,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,+BAOhE;AAED;;mCAEmC;AACnC,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,uFAAuF;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAS7M;AAED,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAE3F"}
1
+ {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../src/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwF,KAAK,qBAAqB,EAAsB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAO5K;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB;qEACiE;IACjE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,IAAI,CAAA;IACrC,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,+HAA+H;IAC/H,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACzE;;;mBAGe;IACf,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAOD,wBAAgB,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAc,EAAE,QAAQ,EAAE,YAAoB,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,SAAS,+BAqGvH;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0BAA0B;IAC1B,QAAQ,EAAE,SAAS,CAAA;IACnB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,YAAY,+BAwDtF;AAED,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;8EAC0E;IAC1E,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB;;wCAEoC;IACpC,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzB,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mGAAmG;IACnG,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,yFAAyF;IACzF,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAgB,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,+BAyC3K;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAe,EAAE,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,+BAOhE;AAED;;mCAEmC;AACnC,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,uFAAuF;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAS7M;AAED,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAE3F"}
package/dist/Select.d.ts CHANGED
@@ -32,36 +32,7 @@ export interface SelectProps {
32
32
  disabled?: boolean;
33
33
  className?: string;
34
34
  }
35
- /**
36
- * Where a menu of this size goes, given its anchor and the viewport — pure,
37
- * so the geometry is testable without a browser.
38
- *
39
- * Left is clamped inside the viewport with an 8px margin. Height is capped
40
- * at 288px (the old `max-h-72`) but never taller than the space it opens
41
- * into; when the room below the anchor is smaller than both the content and
42
- * the room above, the menu opens UPWARD (anchored to the trigger's top via
43
- * `bottom`). The 120px floor keeps a menu usable even in a cramped corner —
44
- * scrollable beats invisible.
45
- */
46
- export declare function fitMenu({ anchor, menu, viewport, }: {
47
- anchor: {
48
- left: number;
49
- top: number;
50
- bottom: number;
51
- };
52
- menu: {
53
- width: number;
54
- contentHeight: number;
55
- };
56
- viewport: {
57
- width: number;
58
- height: number;
59
- };
60
- }): {
61
- left: number;
62
- top?: number;
63
- bottom?: number;
64
- maxHeight: number;
65
- };
35
+ import { fitMenu } from './fit';
36
+ export { fitMenu };
66
37
  export declare function Select({ value, onChange, options, size, ariaLabel, placeholder, disabled, className }: SelectProps): import("react").JSX.Element;
67
38
  //# sourceMappingURL=Select.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../src/Select.tsx"],"names":[],"mappings":"AACA,OAAO,EAAiG,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIrI;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,EACtB,MAAM,EACN,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACrD,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9C,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAYrE;AAED,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAgB,EAAE,SAAS,EAAE,WAAuB,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,WAAW,+BAqO1I"}
1
+ {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../src/Select.tsx"],"names":[],"mappings":"AACA,OAAO,EAAiG,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIrI;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAKD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,CAAA;AAElB,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAgB,EAAE,SAAS,EAAE,WAAuB,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,WAAW,+BAwO1I"}
@@ -1 +1 @@
1
- {"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../src/TextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAG5D;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAA;AAElE,eAAO,MAAM,SAAS,6GAgBpB,CAAA"}
1
+ {"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../src/TextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAI5D;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAA;AAElE,eAAO,MAAM,SAAS,6GAmBpB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../src/Textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,sBAAsB,EAAE,MAAM,OAAO,CAAA;AAG/D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAA;AAEvE,eAAO,MAAM,QAAQ,+GAenB,CAAA"}
1
+ {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../src/Textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,sBAAsB,EAAE,MAAM,OAAO,CAAA;AAI/D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAA;AAEvE,eAAO,MAAM,QAAQ,+GAkBnB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../src/Tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAI1G;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,YAAY,+BAMzD;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAA;IAC5B,6GAA6G;IAC7G,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAKD,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,SAAiB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,gBAAgB,+BAkCrG"}
1
+ {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../src/Tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAI1G;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,YAAY,+BAMzD;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAA;IAC5B,6GAA6G;IAC7G,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAKD,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,SAAiB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,gBAAgB,+BAwCrG"}
package/dist/fit.d.ts ADDED
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Viewport geometry for everything that floats — pure, so the decisions are
3
+ * testable without a browser.
4
+ *
5
+ * One module, because the failure it prevents keeps recurring one surface at
6
+ * a time: the files-panel picker was cut off at the right edge (fixed in
7
+ * Select, 2026-09-01), then a reply menu's highlight submenu was cut off the
8
+ * same way and the identity menu vanished under a z-indexed header
9
+ * (2026-09-03). A menu that hand-rolls its own geometry is a menu waiting to
10
+ * be the next screenshot; the shell calls these instead.
11
+ */
12
+ /**
13
+ * Where a menu of this size goes, given its anchor and the viewport.
14
+ *
15
+ * Left is clamped inside the viewport with an 8px margin. Height is capped
16
+ * at `cap` — Select's option list keeps the old `max-h-72` (288), a menu
17
+ * panel passes none and uses all the room it opens into, so it scrolls only
18
+ * when the screen truly has no space (the identity panel got Select's cap
19
+ * by accident and grew a scrollbar at full height, 2026-09-03) — but never
20
+ * taller than that room; when the room below the anchor is smaller than
21
+ * both the content and the room above, the menu opens UPWARD (anchored to
22
+ * the trigger's top via `bottom`). The 120px floor keeps a menu usable even
23
+ * in a cramped corner — scrollable beats invisible.
24
+ */
25
+ export declare function fitMenu({ anchor, menu, viewport, cap, }: {
26
+ anchor: {
27
+ left: number;
28
+ top: number;
29
+ bottom: number;
30
+ };
31
+ menu: {
32
+ width: number;
33
+ contentHeight: number;
34
+ };
35
+ viewport: {
36
+ width: number;
37
+ height: number;
38
+ };
39
+ /** Tallest the menu may stand even with room to spare. Absent: the room is the only limit. */
40
+ cap?: number;
41
+ }): {
42
+ left: number;
43
+ top?: number;
44
+ bottom?: number;
45
+ maxHeight: number;
46
+ };
47
+ /**
48
+ * Keep a box a caller has already placed fully on screen.
49
+ *
50
+ * For the menus whose caller measured a rect and chose the corner itself
51
+ * (`position`): the caller's math stays authoritative, but its result can no
52
+ * longer land off screen — it is slid inside the viewport, never flipped,
53
+ * and capped to the viewport's height with the same 120px floor as fitMenu.
54
+ */
55
+ export declare function clampBox({ box, viewport, }: {
56
+ box: {
57
+ left: number;
58
+ top: number;
59
+ width: number;
60
+ height: number;
61
+ };
62
+ viewport: {
63
+ width: number;
64
+ height: number;
65
+ };
66
+ }): {
67
+ left: number;
68
+ top: number;
69
+ maxHeight: number;
70
+ };
71
+ /**
72
+ * Where a submenu goes, given its trigger row and the viewport.
73
+ *
74
+ * To the RIGHT of the row when it fits, flipped to the LEFT when it does not
75
+ * — the measured flip two menus hand-rolled and one of them broke (the copy
76
+ * dropped the ref its measurement read, so it measured nothing and always
77
+ * opened rightward, off the screen). Top-aligned with the row, slid up when
78
+ * the tail would run past the bottom edge.
79
+ */
80
+ export declare function fitSubmenu({ row, panel, viewport, }: {
81
+ row: {
82
+ left: number;
83
+ right: number;
84
+ top: number;
85
+ };
86
+ panel: {
87
+ width: number;
88
+ height: number;
89
+ };
90
+ viewport: {
91
+ width: number;
92
+ height: number;
93
+ };
94
+ }): {
95
+ left: number;
96
+ top: number;
97
+ };
98
+ //# sourceMappingURL=fit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fit.d.ts","sourceRoot":"","sources":["../src/fit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,EACtB,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,GAA8B,GAC/B,EAAE;IACD,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACrD,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9C,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3C,8FAA8F;IAC9F,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CASrE;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,EACvB,GAAG,EACH,QAAQ,GACT,EAAE;IACD,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACjE,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAKnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,KAAK,EACL,QAAQ,GACT,EAAE;IACD,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IACjD,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACxC,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAKhC"}
package/dist/index.d.ts CHANGED
@@ -20,7 +20,7 @@ export { ChipInput, InputChip, type ChipInputOption, type ChipInputProps, type I
20
20
  export { IconButton, type IconButtonProps, type IconButtonVariant } from './IconButton';
21
21
  export { IdentityMenu, IdentityPanel, type Identity, type IdentityMenuProps, type IdentityPanelProps } from './IdentityMenu';
22
22
  export { Tooltip, WithTooltip, type TooltipProps, type WithTooltipProps } from './Tooltip';
23
- export { Field, type FieldProps } from './Field';
23
+ export { Field, useFieldControlId, type FieldProps } from './Field';
24
24
  export { Select, type SelectOption, type SelectProps } from './Select';
25
25
  export { TextInput, type TextInputProps } from './TextInput';
26
26
  export { Textarea, type TextareaProps } from './Textarea';
@@ -31,7 +31,8 @@ export { EditableText, type EditableTextProps } from './EditableText';
31
31
  export { EmptyState, type EmptyStateProps } from './EmptyState';
32
32
  export { SkeletonBar, SkeletonList, SkeletonRow } from './Skeleton';
33
33
  export { Breadcrumb, type BreadcrumbProps, type Crumb } from './Breadcrumb';
34
- export { EnterHint, Menu, MenuItem, MenuRow, MenuSection, type MenuItemProps, type MenuProps } from './Menu';
34
+ export { EnterHint, Menu, MenuItem, MenuRow, MenuSection, MenuSub, type MenuItemProps, type MenuProps, type MenuSubProps } from './Menu';
35
+ export { clampBox, fitMenu, fitSubmenu } from './fit';
35
36
  export { NavItem, type NavItemProps } from './NavItem';
36
37
  export { Person, type PersonProps } from './Person';
37
38
  export { Rail, type RailProps } from './Rail';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}