@ai-matrx/design-system 0.86.335 → 0.86.337

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.
@@ -38,7 +38,7 @@
38
38
  cursor: default;
39
39
  }
40
40
  .cm-menu[data-density="compact"] .cm-item { min-height: 24px; padding: 2px 6px; }
41
- .cm-item:hover:not([aria-disabled="true"]), .cm-item:focus-visible, .cm-item:focus, .cm-item.cm-open,
41
+ .cm-item:hover:not([aria-disabled="true"]), .cm-item:focus-visible, .cm-item:focus, .cm-item.cm-open, .cm-item[data-state="open"],
42
42
  .cm-item[data-highlighted]:not([aria-disabled="true"]) {
43
43
  background: hsl(var(--accent)); color: hsl(var(--accent-foreground)); outline: none;
44
44
  }
@@ -90,6 +90,24 @@ a.cm-item { text-decoration: none; }
90
90
  z-index: 10001;
91
91
  }
92
92
  .cm-menu[data-menu-look][data-size="large"] { width: 360px; max-height: min(var(--radix-dropdown-menu-content-available-height, 100vh), 40rem); font-size: 15px; }
93
+ /* THE RIGHT-CLICK (MenuLookContext*): the same panel, capped at the room the context menu measured. */
94
+ .cm-menu[data-menu-family="context"] { max-height: min(var(--radix-context-menu-content-available-height, 100vh), 32rem); }
95
+ .cm-menu[data-menu-family="context"][data-size="large"] { max-height: min(var(--radix-context-menu-content-available-height, 100vh), 40rem); }
96
+ /* THE PANEL in a popover (MenuLookPopoverContent): capped at the room the popover measured. */
97
+ /* A plain panel (MenuLookPanel) is held by its host — a CSS-toggled menu whose wrapper is the bounded
98
+ scroller, a sheet that scrolls — so it draws no scroller of its own. As the popover
99
+ (MenuLookPopoverContent, `data-in-popover`) it is capped at the room the popover measured and
100
+ scrolls, and z equals the dialog layer (popover.tsx): a dialog opened from it stacks above it. */
101
+ .cm-menu[data-menu-family="panel"] { max-height: none; overflow: visible; z-index: auto; }
102
+ .cm-menu[data-menu-family="panel"][data-in-popover] {
103
+ max-height: min(var(--radix-popover-content-available-height, 100vh), 40rem);
104
+ overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; z-index: 10000;
105
+ }
106
+ /* A submenu that holds a host's own surface (fit="content", the Alchemy palette): the surface's width,
107
+ no padding, and the popover height it reads mapped to the room this menu measured. */
108
+ .cm-menu[data-menu-look][data-fit="content"] { width: auto; max-width: calc(100vw - 1rem); padding: 0; }
109
+ .cm-menu[data-menu-family="dropdown"][data-fit="content"] { --radix-popover-content-available-height: var(--radix-dropdown-menu-content-available-height); }
110
+ .cm-menu[data-menu-family="context"][data-fit="content"] { --radix-popover-content-available-height: var(--radix-context-menu-content-available-height); }
93
111
  .cm-menu[data-size="large"] .cm-item { min-height: 36px; padding: 4px 12px; gap: 12px; }
94
112
  .cm-menu[data-size="large"] :is(.cm-icon-slot) { width: 18px; }
95
113
  .cm-menu[data-size="large"] :is(.cm-icon, .cm-icon-slot > svg) { width: 18px; height: 18px; }
@@ -103,6 +121,16 @@ a.cm-item { text-decoration: none; }
103
121
  .cm-menu .cm-item[data-current] .cm-label { font-weight: 500; }
104
122
  .cm-current { flex: none; width: 16px; height: 16px; margin-left: auto; color: hsl(var(--primary)); }
105
123
  .cm-trail + .cm-current { margin-left: 0; }
124
+ span.cm-current { display: inline-flex; }
125
+ .cm-current > svg { width: 100%; height: 100%; }
126
+ /* A one-of row's chosen option (MenuLookRadioItem) reads like the current row. */
127
+ .cm-menu .cm-item[role="menuitemradio"][data-state="checked"] .cm-label { font-weight: 500; }
128
+
129
+ /* A SUBMENU ROW'S CHEVRON (MenuLookSubTrigger): at the row's END, 16px, muted — the same column the
130
+ current check uses, so a submenu row's label starts exactly where every other row's does. */
131
+ .cm-chevron { flex: none; width: 16px; height: 16px; margin-left: auto; color: hsl(var(--muted-foreground)); }
132
+ .cm-trail + .cm-chevron { margin-left: 0; }
133
+ .cm-menu[data-size="large"] .cm-chevron { width: 18px; height: 18px; }
106
134
 
107
135
  /* THE MENU'S SEARCH (MenuLookSearch): the menu's own header row, not a capsule inside it — full-bleed
108
136
  with a hairline under it, its text on the rows' left edge (panel 4px + row 8px = 12px), held at
@@ -123,3 +151,70 @@ a.cm-item { text-decoration: none; }
123
151
  .cm-menu .cm-search > input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
124
152
  .cm-menu[data-size="large"] .cm-search { height: 42px; padding: 0 16px; }
125
153
  .cm-menu[data-size="large"] .cm-search > input { font-size: 15px; }
154
+
155
+ /* A ROW'S BADGE AND KEY (MenuLookRowBody `badge` / `shortcut`): after the label, which takes the free
156
+ space, so both sit at the row's end without a margin of their own. */
157
+ .cm-badge {
158
+ flex: none; display: inline-flex; align-items: center; height: 16px; padding: 0 5px;
159
+ border: 1px solid hsl(var(--border)); border-radius: 4px;
160
+ font-size: 10px; font-weight: 500; letter-spacing: 0.04em; text-transform: uppercase; color: hsl(var(--muted-foreground));
161
+ }
162
+ kbd.cm-shortcut { flex: none; }
163
+ .cm-menu .cm-item.cm-danger .cm-icon-slot svg { color: hsl(var(--destructive)); }
164
+
165
+ /* THE SECTION LABEL with a line under it (MenuLookLabel `description`: a menu's header). */
166
+ .cm-section-label[data-has-hint] { flex-direction: column; align-items: flex-start; gap: 1px; }
167
+ .cm-section-label[data-has-hint] .cm-hint { font-weight: 400; letter-spacing: 0; }
168
+
169
+ /* THE PANEL (MenuLookPanel / MenuLookPopoverContent): the same box and rows with no Radix menu under
170
+ them. A panel row is a <button> or a link: the zero-specificity resets above already strip the
171
+ button; a link keeps no underline. */
172
+ .cm-menu[data-menu-family="panel"] :is(button, a).cm-item { cursor: default; }
173
+ .cm-menu .cm-item:disabled { color: hsl(var(--disabled-foreground)); }
174
+ .cm-menu .cm-item:disabled:hover { background: transparent; }
175
+ /* "sheet": no box of its own (a phone's bottom sheet, or a host popover that is already the box), and
176
+ 44px rows under a finger. */
177
+ .cm-menu[data-menu-family="panel"][data-surface="sheet"] {
178
+ width: auto; max-width: none;
179
+ padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none;
180
+ }
181
+ .cm-menu[data-surface="sheet"] .cm-item { min-height: 44px; }
182
+ @media (max-width: 1023px) { .cm-menu[data-menu-family="panel"][data-fill-below="lg"] { width: auto; max-width: none; } }
183
+ .cm-menu[data-surface="sheet"] .cm-header { min-height: 52px; }
184
+
185
+ /* A ROW THAT HOLDS A CONTROL (MenuLookPanelControlRow): no hover fill — the control answers the
186
+ pointer — and the control at the row's end. */
187
+ .cm-menu .cm-item[data-control-row]:hover, .cm-menu .cm-item[data-control-row]:focus-within { background: transparent; color: inherit; }
188
+ .cm-control { flex: none; display: inline-flex; align-items: center; }
189
+
190
+ /* THE PANEL'S HEADER (MenuLookPanelHeader): a 28px mark on the rows' left edge, a title, a muted line. */
191
+ .cm-header {
192
+ display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px;
193
+ padding: 6px 8px; border-radius: 6px; color: inherit; text-decoration: none; cursor: default;
194
+ }
195
+ a.cm-header:hover, a.cm-header:focus-visible { background: hsl(var(--accent)); color: hsl(var(--accent-foreground)); outline: none; }
196
+ .cm-header-mark { flex: none; display: inline-flex; width: 28px; height: 28px; align-items: center; justify-content: center; overflow: hidden; border-radius: 9999px; }
197
+ .cm-header-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
198
+ .cm-header-title { font-size: 14px; font-weight: 500; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
199
+ .cm-header-subtitle { font-size: 11px; color: hsl(var(--muted-foreground)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
200
+
201
+ /* A FOLDED GROUP (MenuLookPanelDisclosure): its chevron turns while open; its rows keep the one left edge. */
202
+ .cm-chevron[data-disclosure-chevron] { transition: transform 150ms ease; }
203
+ .cm-item[aria-expanded="true"] > .cm-chevron[data-disclosure-chevron] { transform: rotate(180deg); }
204
+
205
+ /* A PANEL THAT DECLARES ITS OVERFLOW (MenuLookContent `moreBelowLabel`): the panel is the frame, the
206
+ rows scroll inside it, and the "More actions below" bar is pinned at its bottom edge. */
207
+ .cm-menu[data-overflow="declared"] { overflow: hidden; padding: 0; }
208
+ .cm-menu[data-overflow="declared"] > .cm-viewport { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 4px; }
209
+ .cm-menu .cm-more-below {
210
+ display: flex; flex: none; align-items: center; justify-content: center; gap: 4px; width: 100%;
211
+ padding: 4px 8px; border-top: 1px solid hsl(var(--border)); background: hsl(var(--popover));
212
+ font-size: 11px; font-weight: 500; color: hsl(var(--muted-foreground)); cursor: default;
213
+ }
214
+ .cm-menu .cm-more-below:hover { background: hsl(var(--accent)); color: hsl(var(--accent-foreground)); }
215
+ .cm-menu .cm-more-below > svg { width: 12px; height: 12px; }
216
+
217
+ /* A row with its own button at the end (the organization picker's favorite star, absolutely placed
218
+ over the row): the row keeps that room free so the current check never sits under it. */
219
+ .cm-menu .cm-item[data-end-button] { padding-right: 32px; }
220
+ .cm-menu [data-menu-look-disclosure][data-pending] > .cm-item { background: transparent; color: hsl(var(--muted-foreground)); }
@@ -1,5 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
3
+ import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
4
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
3
5
 
4
6
  /**
5
7
  * The opaque surface option shared by every floating menu surface
@@ -33,9 +35,6 @@ type PopoverSurface = "default" | "solid";
33
35
  * Icons are the package's inlined SVGs (C19) — no icon-library dependency.
34
36
  */
35
37
 
36
- declare const DropdownMenuSubTrigger: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuSubTriggerProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
37
- inset?: boolean;
38
- } & React.RefAttributes<HTMLDivElement>>;
39
38
  /**
40
39
  * A SUBMENU OPENS BESIDE ITS PARENT, NEVER ON TOP OF IT (merged-grid review 2, C1: "nested
41
40
  * submenus overlap the parent menu"). The submenu was drawn INSIDE the parent's surface, and that
@@ -58,18 +57,147 @@ interface DropdownMenuContentProps extends React.ComponentPropsWithoutRef<typeof
58
57
  }
59
58
  declare const DropdownMenuContent: React.ForwardRefExoticComponent<DropdownMenuContentProps & React.RefAttributes<HTMLDivElement>>;
60
59
 
60
+ /**
61
+ * ContextMenu — the right-click menu primitive.
62
+ *
63
+ * THE ROOT RENDERS UNCONDITIONALLY — no hydration mount gate. The gate a
64
+ * matrx-frontend wrapper once carried ("Radix generates dynamic aria-controls
65
+ * ids that differ between SSR and client") was false twice over: a CLOSED
66
+ * `ContextMenuTrigger` renders only `data-state` / `data-disabled` and emits
67
+ * no id at all, so there was never a mismatch to defend against. And the gate
68
+ * was actively harmful: the Trigger wraps ALWAYS-VISIBLE content, so `return
69
+ * null` deleted the wrapped subtree from the server render and the first
70
+ * client render — around a list row, that means the list paints EMPTY and
71
+ * fills in after hydration. Gating the Root would additionally orphan any
72
+ * Trigger rendered beneath it.
73
+ *
74
+ * That history is exactly why this belongs in the package: the same repo had
75
+ * already accumulated two copies of this wrapper, one gated and one not, with
76
+ * the CORRECT one sitting unused beside the defective one.
77
+ *
78
+ * This is the PRIMITIVE only. A host's actual right-click menu SYSTEM — the
79
+ * sections, the copy/export/convert actions, the surface registry — composes
80
+ * these parts and stays host-owned; nothing here knows what an action is.
81
+ *
82
+ * Portalling goes through the package's `usePortalContainer` seam so a menu
83
+ * raised inside a Dialog mounts inside it; an explicit `container` wins.
84
+ */
85
+
86
+ /** Portalled like its parent, so it opens BESIDE it — see `DropdownMenuSubContent` for why. */
87
+ declare const ContextMenuSubContent: React.ForwardRefExoticComponent<Omit<ContextMenuPrimitive.ContextMenuSubContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
88
+ container?: HTMLElement | null;
89
+ } & React.RefAttributes<HTMLDivElement>>;
90
+ interface ContextMenuContentProps extends React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content> {
91
+ /** Explicit portal target; wins over the injected container. */
92
+ container?: HTMLElement | null;
93
+ }
94
+ declare const ContextMenuContent: React.ForwardRefExoticComponent<ContextMenuContentProps & React.RefAttributes<HTMLDivElement>>;
95
+
96
+ /**
97
+ * Popover — ported verbatim from matrx-frontend `components/ui/popover.tsx`.
98
+ *
99
+ * Seam inversion: the host's `useNestedPortalContainer` (dialog/popout aware)
100
+ * becomes the injected `PortalContainerProvider` seam (`portal-container.tsx`);
101
+ * the explicit `container` prop keeps top priority, exactly as before.
102
+ *
103
+ * THE ROOT RENDERS UNCONDITIONALLY — no mount gate. This wrapper used to defer
104
+ * rendering until after hydration ("Radix generates dynamic aria-controls ids
105
+ * that differ between SSR and client"), and that justification was false:
106
+ * Radix ids come from React's SSR-stable `useId` (verified against
107
+ * @radix-ui/react-popover 1.1.17 / react-id 1.1.2). The gate was actively
108
+ * harmful — the Trigger wraps ALWAYS-VISIBLE content, so `return null`
109
+ * deleted it from SSR and the first client paint.
110
+ */
111
+
112
+ interface PopoverContentProps extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {
113
+ /** Explicit portal target; wins over the injected container. */
114
+ container?: HTMLElement | null;
115
+ /**
116
+ * Package-owned open/close motion. Default `true`. Pass `false` for a
117
+ * surface that must appear instantly — a picker re-anchoring while the user
118
+ * types, a measurement pass. It is NOT the reduced-motion switch;
119
+ * `styles.css` already honors `prefers-reduced-motion`.
120
+ */
121
+ animated?: boolean;
122
+ /**
123
+ * HOW WIDE THE POPOVER IS ALLOWED TO BE, and it is the SYSTEM that decides — never a
124
+ * surface pasting its own `w-64` over the default (lane FIX-14, 2026-09-22).
125
+ *
126
+ * `"fixed"` (default) is the historical `w-72`: right for a menu of short, known
127
+ * labels, where a ragged edge would look broken.
128
+ *
129
+ * `"content"` is for a popover whose whole job is to SHOW SOMETHING THE SYSTEM DID
130
+ * NOT CHOOSE — a person's name, a record's title, a row the user is about to
131
+ * create. The relation picker offered
132
+ *
133
+ * Create “Marisol Okonkwo — 418 Calle Pu
134
+ *
135
+ * inside a 16rem box, cut mid-word, on the one control that exists to show the name
136
+ * being created. A fixed width cannot be right for content of unknown length, so
137
+ * this one grows to its content between an honest floor and an honest ceiling:
138
+ *
139
+ * · at least the trigger's own width, and at least 20rem — the width Airtable's and
140
+ * Notion's link-record pickers settle on, and wide enough that an ordinary
141
+ * "name — street, town" fits on one line;
142
+ * · at most 28rem, and never wider than the viewport less a 1rem gutter each side,
143
+ * so it still fits a 375px phone with nothing running off the screen. The floor is
144
+ * clamped by the same gutter, so on a very narrow screen the ceiling still wins.
145
+ *
146
+ * Beyond that ceiling the CONTENT truncates with an ellipsis and carries a `title`.
147
+ * Growing, then ellipsis — never a mid-word cut.
148
+ *
149
+ * BOTH modes keep the phone gutter (2026-09-26): the box is never wider than the
150
+ * viewport less 1rem each side, and Radix keeps it `collisionPadding` (16px) off every
151
+ * screen edge. Measured at 375px before this: `w-72`/`w-80` callers landed flush on
152
+ * the right edge (55→375) because collision padding was 0.
153
+ */
154
+ sizing?: "fixed" | "content";
155
+ /**
156
+ * The surface fill. `"default"` is the theme's popover surface (a host may render it
157
+ * translucent / glass). `"solid"` is the OPAQUE surface — the popover token at full
158
+ * alpha, no backdrop blur — for a menu that must read as paper over a cover image or a
159
+ * busy page (a Notion-style ••• menu). Same option on `DropdownMenuContent`.
160
+ */
161
+ surface?: PopoverSurface;
162
+ /**
163
+ * A NAMED fixed width (0.68.22), for a `sizing="fixed"` popover whose content needs more or
164
+ * less room than the default `md` (18rem) — never a pasted `w-[260px]`. Every width keeps the
165
+ * phone gutter (never wider than the viewport less 1rem each side). Derived from the call
166
+ * sites: `xs` 12rem (a short menu), `sm` 15rem (a ••• menu), `md` 18rem (default),
167
+ * `lg` 20rem (a small form), `xl` 26rem (a picker grid), `2xl` 34rem (a gallery).
168
+ * Ignored when `sizing="content"`.
169
+ */
170
+ width?: PopoverWidth;
171
+ /**
172
+ * The inner padding, named (0.68.22): `none` (the content draws its own — a command list, a
173
+ * picker), `xs` 4px (a menu of rows), `sm` 8px, `md` 12px, `default` 16px.
174
+ */
175
+ padding?: PopoverPadding;
176
+ }
177
+ type PopoverWidth = "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
178
+ type PopoverPadding = "none" | "xs" | "sm" | "md" | "default";
179
+ declare const PopoverContent: React.ForwardRefExoticComponent<PopoverContentProps & React.RefAttributes<HTMLDivElement>>;
180
+
61
181
  /**
62
182
  * `@ai-matrx/design-system/menu-look` — THE ONE MENU LOOK (Arman, 2026-10-23: the header "…", every
63
183
  * crumb dropdown and every Alchemy dropdown are "the IDENTICAL dropdown that I use for Alchemy for size
64
184
  * and style" — the right-click menu).
65
185
  *
66
- * Two halves, one look:
186
+ * Four families, one look:
67
187
  * - `MENU_LOOK_CLASS` / `MenuLookRowBody` / `MenuLookIconSlot`: the class names and the inside of a row,
68
188
  * used by @ai-matrx/context-menu's MenuPanel (its own non-Radix renderer, the right-click menu);
69
- * - `MenuLookContent` / `MenuLookSubContent` / `MenuLookItem` / `MenuLookSubTrigger` /
70
- * `MenuLookCheckboxItem` / `MenuLookLabel` / `MenuLookSeparator` / `MenuLookSearch`: the same panel and rows on the Radix
71
- * dropdown (keyboard, typeahead, focus return, collision padding), used by Alchemy's dropdowns and the
72
- * frame's "…" and crumb menus.
189
+ * - THE DROPDOWN — `MenuLookContent` / `MenuLookSubContent` / `MenuLookItem` / `MenuLookSubTrigger` /
190
+ * `MenuLookCheckboxItem` / `MenuLookRadioGroup` / `MenuLookRadioItem` / `MenuLookLabel` /
191
+ * `MenuLookSeparator` / `MenuLookSearch` (+ `MenuLookSub`): the panel and rows on the Radix dropdown
192
+ * (keyboard, typeahead, focus return, collision padding) — Alchemy's dropdowns, the frame's "…" and
193
+ * crumb menus, a row's "…" (ItemMenu);
194
+ * - THE RIGHT-CLICK — `MenuLookContext*`: the SAME rows on the Radix context menu (a row's right-click,
195
+ * ItemContextMenu without a host menu);
196
+ * - THE PANEL — `MenuLookPanel` / `MenuLookPopoverContent` / `MenuLookPanelItem` /
197
+ * `MenuLookPanelControlRow` / `MenuLookPanelHeader` / `MenuLookPanelDisclosure` /
198
+ * `MenuLookPanelLabel` / `MenuLookPanelSeparator`: the same panel and rows WITHOUT a Radix menu, for a
199
+ * popover or sheet that also holds controls (a theme switch, a Switch, a search list) — the account
200
+ * rail's Settings, Organization and account menus and the frame's admin menu.
73
201
  * Every measurement lives once, in `menu-look.css` (shipped inside `styles.css`): 280px panel, 30px rows,
74
202
  * 13px text on a 1.25 line, 16px icons, 4px/8px row padding, 10px corners. No part takes a `className`.
75
203
  *
@@ -83,9 +211,11 @@ declare const MENU_LOOK: {
83
211
  readonly width: 280;
84
212
  readonly largeWidth: 360;
85
213
  readonly rowHeight: 30;
214
+ readonly sheetRowHeight: 44;
86
215
  readonly fontSize: 13;
87
216
  readonly lineHeight: 1.25;
88
217
  readonly icon: 16;
218
+ readonly headerMark: 28;
89
219
  readonly rowPaddingY: 4;
90
220
  readonly rowPaddingX: 8;
91
221
  readonly radius: 10;
@@ -100,11 +230,19 @@ declare const MENU_LOOK_CLASS: {
100
230
  readonly label: "cm-label";
101
231
  readonly hint: "cm-hint";
102
232
  readonly current: "cm-current";
233
+ readonly chevron: "cm-chevron";
103
234
  readonly search: "cm-search";
104
235
  readonly trail: "cm-trail";
236
+ readonly badge: "cm-badge";
105
237
  readonly shortcut: "cm-shortcut";
238
+ readonly control: "cm-control";
106
239
  readonly divider: "cm-divider";
107
240
  readonly sectionLabel: "cm-section-label";
241
+ readonly header: "cm-header";
242
+ readonly headerMark: "cm-header-mark";
243
+ readonly headerText: "cm-header-text";
244
+ readonly headerTitle: "cm-header-title";
245
+ readonly headerSubtitle: "cm-header-subtitle";
108
246
  readonly danger: "cm-danger";
109
247
  readonly dimmed: "cm-dimmed";
110
248
  };
@@ -118,39 +256,71 @@ interface MenuLookRowBodyProps {
118
256
  /** The glyph (any 16px svg; the slot sizes it). Omitted → no icon column; the text starts the row. */
119
257
  icon?: React.ReactNode | undefined;
120
258
  label: React.ReactNode;
259
+ /** Hover text for the label (a long description stays out of the row: no "novels" in menus). */
260
+ labelTitle?: string | undefined;
121
261
  /** A muted second line under the label. */
122
262
  description?: React.ReactNode | undefined;
123
263
  /** A muted end-of-row hint (a trail, a shortcut word). */
124
264
  trail?: React.ReactNode | undefined;
265
+ /** A small outlined tag at the row's end ("New", "Beta", a count). */
266
+ badge?: React.ReactNode | undefined;
267
+ /** The row's key, at its end ("⌘C", "R"). */
268
+ shortcut?: React.ReactNode | undefined;
125
269
  /** The row the person is on now: medium weight and a check at the row's end (never a left gutter). */
126
270
  current?: boolean | undefined;
127
271
  }
128
- /** The inside of a row: icon (when given), label (with an optional second line), end hint, current check. */
129
- declare function MenuLookRowBody({ icon, label, description, trail, current }: MenuLookRowBodyProps): React.ReactElement;
272
+ /** The inside of a row: icon (when given), label (+ second line), end hint, badge, key, current check. */
273
+ declare function MenuLookRowBody({ icon, label, labelTitle, description, trail, badge, shortcut, current }: MenuLookRowBodyProps): React.ReactElement;
130
274
  /** A row's classes: the look's row, plus its danger / dimmed marks. */
131
275
  declare function menuLookItemClass({ destructive, dimmed }?: {
132
276
  destructive?: boolean | undefined;
133
277
  dimmed?: boolean | undefined;
134
278
  }): string;
135
- type ContentProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuContent>, "className" | "surface">;
136
- interface MenuLookContentProps extends ContentProps {
279
+ type DataAttributes = {
280
+ [dataAttribute: `data-${string}`]: string | undefined;
281
+ };
282
+ interface PanelLookProps {
137
283
  /** "standard" (280px, the right-click menu) or "large" (360px, 36px rows). */
138
284
  size?: MenuLookSize | undefined;
139
285
  density?: MenuLookDensity | undefined;
140
- [dataAttribute: `data-${string}`]: string | undefined;
286
+ }
287
+ /**
288
+ * A submenu panel's fit: `"menu"` (the look's width and padding) or `"content"` — the panel holds a
289
+ * host's own surface (the Alchemy palette): its width, no padding, and the popover height the surface
290
+ * reads mapped to the room this menu measured.
291
+ */
292
+ type MenuLookSubFit = "menu" | "content";
293
+ type ContentProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuContent>, "className" | "surface">;
294
+ interface MenuLookContentProps extends ContentProps, PanelLookProps, DataAttributes {
295
+ /**
296
+ * A LONG MENU SAYS SO, IN WORDS (FIX-Q13, production `/agents/all` at 1024x768: a record's "…" hid
297
+ * its Delete below the fold and read as dead). Given, the panel is a frame that does not scroll, the
298
+ * rows scroll inside it, and a bar with these words ("More actions below") sits at its bottom edge
299
+ * whenever there is more below — a press scrolls to the end. Measured: a menu that fits shows nothing.
300
+ */
301
+ moreBelowLabel?: string | undefined;
141
302
  }
142
303
  /** The menu's panel on the Radix dropdown (portalled, capped at the room Radix measured, scrolls past it). */
143
304
  declare const MenuLookContent: React.ForwardRefExoticComponent<MenuLookContentProps & React.RefAttributes<HTMLDivElement>>;
144
305
  type SubContentProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuSubContent>, "className" | "surface">;
145
- interface MenuLookSubContentProps extends SubContentProps {
146
- size?: MenuLookSize | undefined;
147
- density?: MenuLookDensity | undefined;
148
- [dataAttribute: `data-${string}`]: string | undefined;
306
+ interface MenuLookSubContentProps extends SubContentProps, PanelLookProps, DataAttributes {
307
+ fit?: MenuLookSubFit | undefined;
149
308
  }
150
309
  /** A submenu's panel: the same panel, as wide as the menu it opens from. */
151
310
  declare const MenuLookSubContent: React.ForwardRefExoticComponent<MenuLookSubContentProps & React.RefAttributes<HTMLDivElement>>;
311
+ type ContextContentProps = Omit<React.ComponentPropsWithoutRef<typeof ContextMenuContent>, "className">;
312
+ interface MenuLookContextContentProps extends ContextContentProps, PanelLookProps, DataAttributes {
313
+ }
314
+ /** The right-click menu's panel on the Radix context menu: the dropdown's panel, opened at the pointer. */
315
+ declare const MenuLookContextContent: React.ForwardRefExoticComponent<MenuLookContextContentProps & React.RefAttributes<HTMLDivElement>>;
316
+ type ContextSubContentProps = Omit<React.ComponentPropsWithoutRef<typeof ContextMenuSubContent>, "className">;
317
+ interface MenuLookContextSubContentProps extends ContextSubContentProps, PanelLookProps, DataAttributes {
318
+ fit?: MenuLookSubFit | undefined;
319
+ }
320
+ /** A right-click submenu's panel. */
321
+ declare const MenuLookContextSubContent: React.ForwardRefExoticComponent<MenuLookContextSubContentProps & React.RefAttributes<HTMLDivElement>>;
152
322
  type ItemProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>, "className" | "children" | "asChild">;
153
- interface MenuLookItemProps extends ItemProps, MenuLookRowBodyProps {
323
+ interface MenuLookItemProps extends ItemProps, MenuLookRowBodyProps, DataAttributes {
154
324
  destructive?: boolean | undefined;
155
325
  /** Drawn dimmed (a greyed verb whose reason is the row's tooltip); still focusable. */
156
326
  dimmed?: boolean | undefined;
@@ -159,29 +329,142 @@ interface MenuLookItemProps extends ItemProps, MenuLookRowBodyProps {
159
329
  target?: string | undefined;
160
330
  /** Props for the `<a>` (aria-current, title, onClick). */
161
331
  linkProps?: undefined | Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href" | "target" | "className" | "children">;
162
- [dataAttribute: `data-${string}`]: string | undefined;
163
332
  }
164
- /** One row: icon, label (+ optional second line), optional end hint; a link when given `href`. */
165
- declare const MenuLookItem: React.ForwardRefExoticComponent<MenuLookItemProps & React.RefAttributes<HTMLDivElement>>;
166
- type SubTriggerProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuSubTrigger>, "className" | "children" | "inset">;
167
- interface MenuLookSubTriggerProps extends SubTriggerProps, MenuLookRowBodyProps {
168
- [dataAttribute: `data-${string}`]: string | undefined;
333
+ type SubTriggerProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger>, "className" | "children" | "asChild">;
334
+ interface MenuLookSubTriggerProps extends SubTriggerProps, MenuLookRowBodyProps, DataAttributes {
169
335
  }
170
- /** A row that opens a submenu (the chevron is the dropdown's own). */
171
- declare const MenuLookSubTrigger: React.ForwardRefExoticComponent<MenuLookSubTriggerProps & React.RefAttributes<HTMLDivElement>>;
172
336
  type CheckboxProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>, "className" | "children" | "asChild">;
173
- interface MenuLookCheckboxItemProps extends CheckboxProps, MenuLookRowBodyProps {
174
- [dataAttribute: `data-${string}`]: string | undefined;
337
+ interface MenuLookCheckboxItemProps extends CheckboxProps, MenuLookRowBodyProps, DataAttributes {
338
+ }
339
+ type RadioProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>, "className" | "children" | "asChild">;
340
+ interface MenuLookRadioItemProps extends RadioProps, Omit<MenuLookRowBodyProps, "current">, DataAttributes {
341
+ }
342
+ type LabelPrimitiveProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label>, "className">;
343
+ interface MenuLookLabelProps extends LabelPrimitiveProps {
344
+ /** A muted line under the heading (a menu's header: the record it acts on). */
345
+ description?: React.ReactNode | undefined;
175
346
  }
176
- /** A toggle row: a check in the icon slot while on (the right-click menu's toggle), else its icon — a
177
- * toggle keeps its column either way, so switching it never moves its label. */
347
+ type SeparatorProps = Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>, "className">;
348
+ declare const MenuLookItem: React.ForwardRefExoticComponent<MenuLookItemProps & React.RefAttributes<HTMLDivElement>>;
349
+ /** Holds a submenu: `MenuLookSub` > `MenuLookSubTrigger` + `MenuLookSubContent`. */
350
+ declare const MenuLookSub: React.FC<DropdownMenuPrimitive.DropdownMenuSubProps>;
351
+ declare const MenuLookSubTrigger: React.ForwardRefExoticComponent<MenuLookSubTriggerProps & React.RefAttributes<HTMLDivElement>>;
178
352
  declare const MenuLookCheckboxItem: React.ForwardRefExoticComponent<MenuLookCheckboxItemProps & React.RefAttributes<HTMLDivElement>>;
179
- /** A section heading ("Copy", "Brands", "Pages"). */
180
- declare const MenuLookLabel: React.ForwardRefExoticComponent<Omit<Omit<DropdownMenuPrimitive.DropdownMenuLabelProps & React.RefAttributes<HTMLDivElement>, "ref">, "className"> & React.RefAttributes<HTMLDivElement>>;
181
- /** The line between sections. */
182
- declare const MenuLookSeparator: React.ForwardRefExoticComponent<Omit<Omit<DropdownMenuPrimitive.DropdownMenuSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref">, "className"> & React.RefAttributes<HTMLDivElement>>;
183
- interface MenuLookSearchProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "className" | "style" | "size" | "type"> {
184
- [dataAttribute: `data-${string}`]: string | undefined;
353
+ /** A group of one-of rows (`MenuLookRadioItem`); the host owns `value` / `onValueChange`. */
354
+ declare const MenuLookRadioGroup: React.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuRadioGroupProps & React.RefAttributes<HTMLDivElement>>;
355
+ declare const MenuLookRadioItem: React.ForwardRefExoticComponent<MenuLookRadioItemProps & React.RefAttributes<HTMLDivElement>>;
356
+ declare const MenuLookLabel: React.ForwardRefExoticComponent<MenuLookLabelProps & React.RefAttributes<HTMLDivElement>>;
357
+ declare const MenuLookSeparator: React.ForwardRefExoticComponent<SeparatorProps & React.RefAttributes<HTMLDivElement>>;
358
+ /** The right-click twins of the dropdown rows — identical rows, the Radix context menu underneath. */
359
+ declare const MenuLookContextItem: React.ForwardRefExoticComponent<MenuLookItemProps & React.RefAttributes<HTMLDivElement>>;
360
+ declare const MenuLookContextSub: React.FC<ContextMenuPrimitive.ContextMenuSubProps>;
361
+ declare const MenuLookContextSubTrigger: React.ForwardRefExoticComponent<MenuLookSubTriggerProps & React.RefAttributes<HTMLDivElement>>;
362
+ declare const MenuLookContextCheckboxItem: React.ForwardRefExoticComponent<MenuLookCheckboxItemProps & React.RefAttributes<HTMLDivElement>>;
363
+ declare const MenuLookContextRadioGroup: React.ForwardRefExoticComponent<ContextMenuPrimitive.ContextMenuRadioGroupProps & React.RefAttributes<HTMLDivElement>>;
364
+ declare const MenuLookContextRadioItem: React.ForwardRefExoticComponent<MenuLookRadioItemProps & React.RefAttributes<HTMLDivElement>>;
365
+ declare const MenuLookContextLabel: React.ForwardRefExoticComponent<MenuLookLabelProps & React.RefAttributes<HTMLDivElement>>;
366
+ declare const MenuLookContextSeparator: React.ForwardRefExoticComponent<SeparatorProps & React.RefAttributes<HTMLDivElement>>;
367
+ /**
368
+ * Where a panel sits: `"floating"` draws the menu's own box (border, popover fill, shadow, 280px) — a
369
+ * CSS-toggled menu, or a host whose popover draws nothing; `"sheet"` draws no box (a phone's bottom
370
+ * sheet, or a host popover that is already the box) and gives its rows 44px touch height.
371
+ */
372
+ type MenuLookPanelSurface = "floating" | "sheet";
373
+ interface MenuLookPanelProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "className" | "style">, PanelLookProps, DataAttributes {
374
+ surface?: MenuLookPanelSurface | undefined;
375
+ /**
376
+ * `"lg"`: below the large breakpoint (1024px) the floating panel fills the width its host gives it —
377
+ * a CSS-toggled menu that becomes a bottom-anchored sheet on a phone (AppShell's account menu).
378
+ */
379
+ fillBelow?: "lg" | undefined;
380
+ }
381
+ /** The menu's panel as a plain element: its rows are `MenuLookPanel*` parts. Role `menu` by default. */
382
+ declare const MenuLookPanel: React.ForwardRefExoticComponent<MenuLookPanelProps & React.RefAttributes<HTMLDivElement>>;
383
+ type PopoverProps = Omit<React.ComponentPropsWithoutRef<typeof PopoverContent>, "className" | "surface" | "width" | "padding" | "sizing">;
384
+ interface MenuLookPopoverContentProps extends PopoverProps, PanelLookProps, DataAttributes {
385
+ }
386
+ /**
387
+ * The panel IS the popover: a Radix popover (outside click, Esc, focus return, collision padding)
388
+ * wearing the menu's box — one element, never a popover box around a menu box. Role `menu`.
389
+ */
390
+ declare const MenuLookPopoverContent: React.ForwardRefExoticComponent<MenuLookPopoverContentProps & React.RefAttributes<HTMLDivElement>>;
391
+ type LinkComponent = React.ElementType;
392
+ interface PanelRowMarks {
393
+ destructive?: boolean | undefined;
394
+ /** Drawn dimmed (a greyed verb whose reason is the row's tooltip); still pressable. */
395
+ dimmed?: boolean | undefined;
396
+ }
397
+ interface MenuLookPanelItemProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "className" | "style" | "children" | "type">, MenuLookRowBodyProps, PanelRowMarks, DataAttributes {
398
+ /**
399
+ * A toggle row's state (a tool that is showing): `aria-pressed`, and while on it reads like the
400
+ * current row (medium weight, the check at its end).
401
+ */
402
+ pressed?: boolean | undefined;
403
+ /** A link: the row is an anchor (or `as`, the host's link component — Next's Link, an app link). */
404
+ href?: string | undefined;
405
+ target?: string | undefined;
406
+ rel?: string | undefined;
407
+ /** The link component for `href` (it receives `href`, `className`, `role`, `onClick`, children). */
408
+ as?: LinkComponent | undefined;
409
+ /** Extra props for the link component (`prefetch={false}`, `aria-current`). */
410
+ linkProps?: Record<string, unknown> | undefined;
411
+ }
412
+ /** A panel row: a button, or a link with `href`. Same row as the dropdown's (`cm-item`). */
413
+ declare const MenuLookPanelItem: React.ForwardRefExoticComponent<MenuLookPanelItemProps & React.RefAttributes<HTMLElement>>;
414
+ interface MenuLookPanelControlRowProps extends Omit<React.HTMLAttributes<HTMLElement>, "className" | "style" | "children">, Pick<MenuLookRowBodyProps, "icon" | "label" | "description">, DataAttributes {
415
+ /** The row's own control at its end: a `Switch`, a `SegmentedControl`, a count. */
416
+ control: React.ReactNode;
417
+ /** `"label"` when the whole row should press its control (a Switch); default `"div"`. */
418
+ as?: "div" | "label" | undefined;
419
+ }
420
+ /**
421
+ * A row that holds a control instead of being one (Theme: Light | Dark | Device; Standard view with its
422
+ * Switch): the same icon slot, label and left edge as every row, the control at its END, and no hover
423
+ * fill (the control answers the pointer, not the row).
424
+ */
425
+ declare const MenuLookPanelControlRow: React.ForwardRefExoticComponent<MenuLookPanelControlRowProps & React.RefAttributes<HTMLElement>>;
426
+ interface MenuLookPanelHeaderProps extends DataAttributes {
427
+ /** The 28px mark (an avatar, an organization mark, a colored glyph). */
428
+ mark: React.ReactNode;
429
+ title: React.ReactNode;
430
+ /** One muted line under the title. */
431
+ subtitle?: React.ReactNode | undefined;
432
+ /** The header is a door to its own page. */
433
+ href?: string | undefined;
434
+ as?: LinkComponent | undefined;
435
+ linkProps?: Record<string, unknown> | undefined;
436
+ onClick?: React.MouseEventHandler<HTMLElement> | undefined;
437
+ }
438
+ /**
439
+ * The row a panel opens with (Settings, the organization, the person): a 28px mark on the rows' left
440
+ * edge, a title, an optional muted subtitle. With `href` it is a link to its page.
441
+ */
442
+ declare function MenuLookPanelHeader({ mark, title, subtitle, href, as, linkProps, onClick, ...data }: MenuLookPanelHeaderProps): React.ReactElement;
443
+ interface MenuLookPanelDisclosureProps extends Pick<MenuLookRowBodyProps, "icon" | "label">, DataAttributes {
444
+ /** Omitted with `pending`: the group's rows are still on their way. */
445
+ children?: React.ReactNode;
446
+ /**
447
+ * The group's row while its rows load (a lazy chunk): the same row and chevron, inert and hidden
448
+ * from assistive tech, so nothing below it moves when the group arrives (no layout shift).
449
+ */
450
+ pending?: boolean | undefined;
451
+ defaultOpen?: boolean | undefined;
452
+ open?: boolean | undefined;
453
+ onOpenChange?: ((open: boolean) => void) | undefined;
454
+ }
455
+ /**
456
+ * A folded group of rows ("Quick Access", "Admin"): a row with a down-chevron at its END that opens
457
+ * the group in place. Closed, its rows are ABSENT (hidden: out of the hit-test tree and the tab order),
458
+ * never clipped-but-live. Open, they sit on the same left edge as every row — no indent.
459
+ */
460
+ declare function MenuLookPanelDisclosure({ icon, label, children, pending, defaultOpen, open: openProp, onOpenChange, ...data }: MenuLookPanelDisclosureProps): React.ReactElement;
461
+ /** A panel's section heading. */
462
+ declare function MenuLookPanelLabel({ children, ...data }: {
463
+ children: React.ReactNode;
464
+ } & DataAttributes): React.ReactElement;
465
+ /** The line between a panel's sections. */
466
+ declare function MenuLookPanelSeparator(): React.ReactElement;
467
+ interface MenuLookSearchProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "className" | "style" | "size" | "type">, DataAttributes {
185
468
  }
186
469
  /**
187
470
  * The menu's search: its own header row (full-bleed, a hairline under it, held at the top while the
@@ -190,4 +473,4 @@ interface MenuLookSearchProps extends Omit<React.InputHTMLAttributes<HTMLInputEl
190
473
  */
191
474
  declare const MenuLookSearch: React.ForwardRefExoticComponent<MenuLookSearchProps & React.RefAttributes<HTMLInputElement>>;
192
475
 
193
- export { MENU_LOOK, MENU_LOOK_CLASS, MenuLookCheckboxItem, type MenuLookCheckboxItemProps, MenuLookContent, type MenuLookContentProps, type MenuLookDensity, MenuLookIconSlot, MenuLookItem, type MenuLookItemProps, MenuLookLabel, MenuLookRowBody, type MenuLookRowBodyProps, MenuLookSearch, type MenuLookSearchProps, MenuLookSeparator, type MenuLookSize, MenuLookSubContent, type MenuLookSubContentProps, MenuLookSubTrigger, type MenuLookSubTriggerProps, menuLookItemClass };
476
+ export { MENU_LOOK, MENU_LOOK_CLASS, MenuLookCheckboxItem, type MenuLookCheckboxItemProps, MenuLookContent, type MenuLookContentProps, MenuLookContextCheckboxItem, MenuLookContextContent, type MenuLookContextContentProps, MenuLookContextItem, MenuLookContextLabel, MenuLookContextRadioGroup, MenuLookContextRadioItem, MenuLookContextSeparator, MenuLookContextSub, MenuLookContextSubContent, type MenuLookContextSubContentProps, MenuLookContextSubTrigger, type MenuLookDensity, MenuLookIconSlot, MenuLookItem, type MenuLookItemProps, MenuLookLabel, type MenuLookLabelProps, MenuLookPanel, MenuLookPanelControlRow, type MenuLookPanelControlRowProps, MenuLookPanelDisclosure, type MenuLookPanelDisclosureProps, MenuLookPanelHeader, type MenuLookPanelHeaderProps, MenuLookPanelItem, type MenuLookPanelItemProps, MenuLookPanelLabel, type MenuLookPanelProps, MenuLookPanelSeparator, type MenuLookPanelSurface, MenuLookPopoverContent, type MenuLookPopoverContentProps, MenuLookRadioGroup, MenuLookRadioItem, type MenuLookRadioItemProps, MenuLookRowBody, type MenuLookRowBodyProps, MenuLookSearch, type MenuLookSearchProps, MenuLookSeparator, type MenuLookSize, MenuLookSub, MenuLookSubContent, type MenuLookSubContentProps, type MenuLookSubFit, MenuLookSubTrigger, type MenuLookSubTriggerProps, menuLookItemClass };