twico-ui 1.38.0 → 1.40.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.
package/dist/index.d.cts CHANGED
@@ -138,6 +138,73 @@ interface ImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "al
138
138
 
139
139
  declare const Image: React.ForwardRefExoticComponent<ImageProps & React.RefAttributes<HTMLImageElement>>;
140
140
 
141
+ /** The zoom API passed to a `controls` render function. */
142
+ interface ImageViewerControlsApi {
143
+ /** Current zoom level. */
144
+ zoom: number;
145
+ /** Zoom in one `step`, centered. */
146
+ zoomIn: () => void;
147
+ /** Zoom out one `step`, centered. */
148
+ zoomOut: () => void;
149
+ /** Reset to `minZoom` and re-center. */
150
+ reset: () => void;
151
+ /** Whether zooming in further is possible. */
152
+ canZoomIn: boolean;
153
+ /** Whether zooming out further is possible. */
154
+ canZoomOut: boolean;
155
+ }
156
+
157
+ /**
158
+ * A zoomable / pannable image on a fixed stage: pointer-anchored wheel + pinch zoom, drag-to-pan when zoomed
159
+ * (clamped to the stage), `+` / `-` / `0` keys, and double-click to toggle. Wheel uses a non-passive listener
160
+ * so the page/dialog behind never scrolls. Set the stage size via `style`/`className` on the root.
161
+ *
162
+ * @startingPoint section="Data display" subtitle="Zoomable image viewer" viewport="700x460"
163
+ */
164
+ interface ImageViewerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {
165
+ /** Image source. */
166
+ src?: string;
167
+ /** Accessible description (required). */
168
+ alt: string;
169
+ /** Minimum zoom (also the reset level). @default 1 */
170
+ minZoom?: number;
171
+ /** Maximum zoom. @default 8 */
172
+ maxZoom?: number;
173
+ /** Zoom increment for the wheel / keys / buttons. @default 0.25 */
174
+ step?: number;
175
+ /** Controlled zoom level. Pair with `onZoomChange` and echo it back into this prop — pan/anchor math runs
176
+ * against the rendered zoom, so a controlled value that never updates would drift. */
177
+ zoom?: number;
178
+ /** Initial zoom for the uncontrolled case. @default 1 */
179
+ defaultZoom?: number;
180
+ /** Fired with the new zoom level whenever it changes. */
181
+ onZoomChange?: (zoom: number) => void;
182
+ /** Zoom level a double-click toggles to (from `minZoom`). @default 2 */
183
+ doubleClickZoom?: number;
184
+ /** Built-in zoom in/out/reset controls, or your own. Pass a node, a render function receiving the zoom API,
185
+ * or `false` to hide them. @default the built-in controls */
186
+ controls?: React.ReactNode | ((api: ImageViewerControlsApi) => React.ReactNode) | false;
187
+ /** How the image fills the stage at 1×. #414: `"scale-down"`/`"none"` (like `Image`) avoid upscaling a small
188
+ * image; pan bounds follow the rendered image box. @default "contain" */
189
+ fit?: "contain" | "cover" | "scale-down" | "none";
190
+ /** #414: reactive zoom state — pair with `controls={false}` to drive your own toolbar's disabled states
191
+ * (the imperative `ref` gives the actions). Fires on mount and whenever the state changes. */
192
+ onStateChange?: (state: ImageViewerState) => void;
193
+ /** #414: border-radius token for the stage, e.g. `"md"`, `"lg"`, `"full"`. (Or set the `--twc-iv-radius` /
194
+ * `--twc-iv-bg` custom properties on the root.) @default "lg" */
195
+ radius?: string;
196
+ }
197
+
198
+ /** #414: the reactive state reported by `onStateChange`. */
199
+ interface ImageViewerState {
200
+ zoom: number;
201
+ canZoomIn: boolean;
202
+ canZoomOut: boolean;
203
+ }
204
+
205
+ /** #414: `ref` exposes the zoom API ({@link ImageViewerControlsApi}) so a host toolbar can drive it. */
206
+ declare const ImageViewer: React.ForwardRefExoticComponent<ImageViewerProps & React.RefAttributes<ImageViewerControlsApi>>;
207
+
141
208
  /**
142
209
  * Vertically stacked, expandable disclosure panels with smooth height animation.
143
210
  *
@@ -392,6 +459,17 @@ interface AvatarMenuProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "t
392
459
  showName?: boolean;
393
460
  /** Show a chevron in the trigger (defaults to `showName`). */
394
461
  showChevron?: boolean;
462
+ /** #402: stretch the trigger to full width — the name/subtitle column grows and the chevron pins to the
463
+ * inline-end — for a sidebar footer account row (pair with `Sidebar footerInset={false}`). In fullWidth mode
464
+ * the trigger uses a `radius-md` (not pill) and the menu matches the trigger width. @default false */
465
+ fullWidth?: boolean;
466
+ /** #416: fully replace the built-in menu header (avatar + name + subtitle). */
467
+ header?: React.ReactNode;
468
+ /** #416: extra content appended under the name/subtitle in the built-in menu header (e.g. a presence line or
469
+ * role badge) — menu only, not the trigger. Ignored when `header` is set. */
470
+ headerExtra?: React.ReactNode;
471
+ /** #416: menu popup width in px. @default 240 (or the trigger width when `fullWidth`) */
472
+ menuWidth?: number;
395
473
  /** Menu alignment to the trigger. @default "end" */
396
474
  align?: "start" | "end";
397
475
  }
@@ -466,6 +544,17 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
466
544
  loading?: boolean;
467
545
  /** Stretch to fill the container width. @default false */
468
546
  fullWidth?: boolean;
547
+ /** #398: when `disabled`, stay in the tab order (render `aria-disabled` instead of native `disabled`) so a
548
+ * wrapping `Tooltip` explaining *why* it's disabled is reachable by keyboard. Click and Enter/Space are
549
+ * still blocked and the disabled styling still applies. @default false */
550
+ focusableWhenDisabled?: boolean;
551
+ /** #405: toggle "on" state — sets `aria-pressed` and shows a soft fill + border in the current `tone`
552
+ * (works with any `variant`). Omit for a plain (non-toggle) button. @default undefined */
553
+ pressed?: boolean;
554
+ /** #411: tone of the pressed ("on") fill — the full status `Tone` scale, so a toggle can carry its own
555
+ * selected-state meaning (e.g. success/warning/info/neutral) while `tone` stays `ActionTone` for the
556
+ * unpressed action look. Defaults to `tone`. @default undefined */
557
+ pressedTone?: Tone;
469
558
  /** Render as a different element (e.g. "a"). @default "button" */
470
559
  as?: "button" | "a";
471
560
  /** Link destination — only used with as="a"; scheme-sanitized (javascript:/data:/vbscript: render without href). */
@@ -1924,6 +2013,13 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
1924
2013
  * rearrange only the movable, unpinned columns and leave pinned/actions columns in place.
1925
2014
  * @default false */
1926
2015
  disableColumnReorder?: boolean;
2016
+ /** #403: table-level column defaults, shallow-merged **under** each column definition before
2017
+ * normalisation (built-in defaults < `defaultColumn` < the column). A per-column value always wins.
2018
+ * Set shared flags once instead of repeating them — e.g. a fixed-layout grid:
2019
+ * `defaultColumn={{ sortable: false, filterable: false, hideable: false, pinnable: false, groupable: false,
2020
+ * resizable: false, reorderable: false, wrappable: false, disableColumnMenu: true }}`. Like TanStack Table's
2021
+ * `defaultColumn` / AG Grid's `defaultColDef`. The smart Columns/Filters toolbar buttons follow it too. @default undefined */
2022
+ defaultColumn?: Partial<DatatableColumn<T>>;
1927
2023
  /** Message rendered when there are no rows (filter-aware default: "No rows match your filters" when a filter/quick-search is active, else "No rows"). */
1928
2024
  emptyMessage?: React.ReactNode;
1929
2025
  /** Render a custom empty state inside the table body (e.g. the shipped `<EmptyState/>`). Overrides `emptyMessage`. */
@@ -1980,6 +2076,15 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
1980
2076
  * Shift+Click / Shift+Arrow extend a range from an anchor; selected cells expose `aria-selected` and the
1981
2077
  * grid is `aria-multiselectable` with `aria-activedescendant` on the active cell. @default "none" */
1982
2078
  selectionMode?: "none" | "row" | "cell";
2079
+ /** #392: keyboard cell-navigation model (WAI-ARIA APG grid pattern), independent of `selectionMode`.
2080
+ * - `"cell"` (default): arrow keys move focus to the `<td>`; today's behaviour, unchanged.
2081
+ * - `"widget"`: when a data cell holds exactly **one** interactive control (a toggle button, link, chip,
2082
+ * switch or checkbox), arrow keys focus that control so **Enter/Space** act on it, and the grid body
2083
+ * becomes a **single Tab stop** (every other in-cell control is `tabindex=-1`) instead of one stop per
2084
+ * control. A cell with several controls enters an interaction mode on **Enter/F2** (Tab moves within the
2085
+ * cell, **Escape** returns to the cell). Text inputs/selects (editing) and checkbox-selection / row-expand
2086
+ * controls are unaffected. @default "cell" */
2087
+ cellNavigation?: "cell" | "widget";
1983
2088
  /** Fired when a row is clicked in "row" selection mode: (row, key). */
1984
2089
  onRowClick?: (row: T, key: string | number) => void;
1985
2090
  /** #324: controlled highlighted row key for `selectionMode="row"`. When provided, the grid highlights THIS
@@ -1989,17 +2094,32 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
1989
2094
  activeRowId?: string | number | null;
1990
2095
  /** #324: scroll the controlled active row into view when `activeRowId` changes. @default true */
1991
2096
  scrollActiveRowIntoView?: boolean;
2097
+ /** #395: controlled active cell ({ key, field } | null), independent of `selectionMode`. In "cell" mode it
2098
+ * drives the highlight; in any mode it is the target for `scrollActiveCellIntoView`. Pass `null` to clear.
2099
+ * Lets a host step through specific cells (next changed cell, next validation error, find-in-grid). */
2100
+ activeCell?: { key: string | number; field: string } | null;
2101
+ /** #395: reveal the `activeCell` inside the grid's own scroller (both axes, honouring the sticky header and
2102
+ * pinned columns; never scrolls the page). Re-applied when `rows` change, so a server-mode page switch or a
2103
+ * virtualized mount lands on the cell. Pass an object to center it. @default false */
2104
+ scrollActiveCellIntoView?: boolean | { block?: "nearest" | "center"; inline?: "nearest" | "center" };
1992
2105
  /** Fired when a cell is clicked in "cell" selection mode: (value, row, field). */
1993
2106
  onCellClick?: (value: any, row: T, field: string) => void;
1994
2107
  /** Fired when the active cell changes: ({ key, field } | null). */
1995
2108
  onActiveCellChange?: (cell: { key: string | number; field: string } | null) => void;
2109
+ /** #396: fired at every inline-edit transition so a host can, for example, stand down its own keyboard
2110
+ * shortcuts while a cell is being edited. `reason` is `"start"` (an editor opened), `"commit"` (it closed
2111
+ * saving — fired even when the value was unchanged) or `"cancel"` (it closed discarding). The grid root
2112
+ * also carries a `data-editing` attribute while any editor is open. */
2113
+ onEditingChange?: (cell: { key: string | number; field: string } | null, reason: "start" | "commit" | "cancel") => void;
1996
2114
  /** #317: fired when the rectangular cell selection changes ("cell" mode) — every cell inside the
1997
2115
  * anchor→focus rectangle, in row-major order. Empty array when the selection clears. */
1998
2116
  onCellSelectionChange?: (cells: Array<{ key: string | number; field: string }>) => void;
1999
2117
  /** #318: enable spreadsheet clipboard on cells ("cell" mode): Ctrl/Cmd+C copies the active cell/range as
2000
2118
  * TSV, Ctrl/Cmd+X cuts (copy then clear), Ctrl/Cmd+V pastes onto the target rectangle from the active
2001
- * cell. Paste is format-restricted by column `copyType` (incompatible cells are skipped) and commits
2002
- * through `onRowUpdate`/`onRowsChange` in one batched change; outcomes are announced via `aria-live`.
2119
+ * cell. Paste is format-restricted by column `copyType` (incompatible cells are skipped). It commits
2120
+ * through `onRowsChange` in one change and, per cell, through `onRowUpdate` (once per changed field) —
2121
+ * unless `onCellsCommit` is supplied, which reports the whole paste/cut as a single grouped call instead.
2122
+ * Outcomes are announced via `aria-live`.
2003
2123
  * Copy/cut/paste also show a brief **visible** in-grid confirmation toast + a flash on the affected cells
2004
2124
  * (#320), so sighted users get feedback too. @default false */
2005
2125
  enableClipboard?: boolean;
@@ -2009,6 +2129,11 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
2009
2129
  /** #320: fired after a clipboard paste with the outcome — `written` cells committed, `skipped` cells
2010
2130
  * rejected (read-only or incompatible `copyType`). */
2011
2131
  onCellsPaste?: (result: { written: number; skipped: number }) => void;
2132
+ /** #394: when supplied, a paste or cut reports the whole change as ONE call — the grouped patches per row
2133
+ * (`key`, the updated `row`, and its `patch`) plus `meta.source` — instead of firing `onRowUpdate` once per
2134
+ * cell (which bursts N writes through a rate-limited API). `onRowsChange` is unaffected. The clipboard
2135
+ * counterpart of `onBatchUpdate`. */
2136
+ onCellsCommit?: (changes: Array<{ key: string | number; row: T; patch: Partial<T> }>, meta: { source: "paste" | "cut" }) => void;
2012
2137
  /** Show the **Aggregation** toolbar button and start with the totals row on. From that panel the user
2013
2138
  * toggles totals and picks columns + functions (a column's `aggregation` prop seeds the initial choice);
2014
2139
  * changing the prop re-applies it. When false (the default) the Aggregation button is hidden. @default false */
@@ -2023,10 +2148,19 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
2023
2148
  showGroupBar?: boolean;
2024
2149
  /** #387: custom content for a group header row (the chevron + collapse/expand toggle are kept). Return the
2025
2150
  * node to render in place of the default `"<field>: <value> <count>"` — e.g. a section title + a summary.
2026
- * `rows` is the group's rows; `count` is their number. Return `null` to render an empty label (matching
2027
- * `renderCell`/`renderHeader`). The content sits **inside** the group's toggle button, so keep it
2028
- * non-interactive — a nested button/link would be invalid HTML and its clicks would also toggle the group. */
2029
- renderGroupLabel?: (group: { field: string; value: unknown; count: number; rows: T[] }) => React.ReactNode;
2151
+ * `rows` is the group's rows; `count` is their number; `collapsed` is its current state and `toggle()`
2152
+ * flips it. Return `null` to render an empty label (matching `renderCell`/`renderHeader`). The content sits
2153
+ * **inside** the group's toggle button, so keep it non-interactive — a nested button/link would be invalid
2154
+ * HTML and its clicks would also toggle the group. */
2155
+ renderGroupLabel?: (group: { field: string; value: unknown; count: number; rows: T[]; collapsed: boolean; toggle: () => void }) => React.ReactNode;
2156
+ /** #393: which groups are collapsed, as internal group-path keys (`"/status:open"`, nested
2157
+ * `"/status:open/owner:ann"`). Controlled — pair with `onCollapsedGroupsChange`; omit for uncontrolled. */
2158
+ collapsedGroups?: string[];
2159
+ /** #393: initial collapsed groups for the uncontrolled case (ignored when `collapsedGroups` is set). @default [] */
2160
+ defaultCollapsedGroups?: string[];
2161
+ /** #393: fired when the user collapses/expands a group, with the next array of collapsed group keys. Also
2162
+ * the way to persist collapse state outside `stateKey`. */
2163
+ onCollapsedGroupsChange?: (keys: string[]) => void;
2030
2164
  /** Enable row pinning — adds "Pin to top/bottom" to each row's actions menu; pinned rows stay sticky above/below the scroll body. @default false */
2031
2165
  rowPinning?: boolean;
2032
2166
  /** Enable reorder of rows: the whole row is mouse-draggable, and a focusable drag handle supports
@@ -2180,10 +2314,17 @@ interface DatatableState {
2180
2314
  columnCombine?: Record<string, { fields: string[]; layout?: "inline" | "stack"; separator?: string; labels?: boolean }>;
2181
2315
  /** #341: user-resized width (px) of the batch-editor's column-name field. Absent until the user drags it. */
2182
2316
  batchNameWidth?: number;
2317
+ /** #393: active grouping fields (from the column ⋮ "Group by" items). Absent when nothing is grouped. */
2318
+ grouping?: string[];
2319
+ /** #393: collapsed group keys (internal group-path strings). Absent when every group is expanded. */
2320
+ collapsedGroups?: string[];
2183
2321
  }
2184
2322
 
2185
2323
  interface DatatableColumn<T = any> {
2186
- /** Row object key (also the default sort/filter/search/group/export key). */
2324
+ /** Row object key (also the default sort/filter/search/group/export key). **Must be unique within
2325
+ * `columns`** — it is the column's identity for width, visibility, order, pinning and persisted `stateKey`
2326
+ * state (a duplicate `field` makes two columns share that state and logs a dev warning). To show one row
2327
+ * key in two columns, give the second its own `field` and read the value with `valueGetter`. */
2187
2328
  field: string;
2188
2329
  /** Derive the column's value from the whole row (nested/computed) — drives sort, filter,
2189
2330
  * quick-search, grouping, aggregation, the default cell render, and export. Falls back to
@@ -2229,8 +2370,12 @@ interface DatatableColumn<T = any> {
2229
2370
  minWidth?: number;
2230
2371
  /** Upper bound (px) for the resolved width; `minWidth` wins if they conflict. */
2231
2372
  maxWidth?: number;
2232
- /** Cell alignment; currently affects the actions column's button justification. @default "right" for number/actions columns, else "left" */
2233
- align?: "left" | "right";
2373
+ /** Horizontal alignment of the column's body cells and footer (and the actions column's button
2374
+ * justification), emitted as `data-align` like the `Table` component. Use `"center"` for status icons,
2375
+ * toggles or short counts. @default "right" for number/actions columns, else "left" */
2376
+ align?: "left" | "center" | "right";
2377
+ /** Header-cell alignment, when it should differ from the body `align`. @default the column's `align` */
2378
+ headerAlign?: "left" | "center" | "right";
2234
2379
  /** Allow sorting this column. @default true */
2235
2380
  sortable?: boolean;
2236
2381
  /** Allow filtering this column. @default true */
@@ -2255,8 +2400,11 @@ interface DatatableColumn<T = any> {
2255
2400
  aggregationFormatter?: (value: any) => React.ReactNode;
2256
2401
  /** Map a row to its exported CSV value (defaults to the raw field value). */
2257
2402
  exportValue?: (value: any, row: T) => string | number;
2258
- /** Make this column's cells editable (double-click to edit). Overrides the grid `editMode`. */
2259
- editable?: boolean;
2403
+ /** Make this column's cells editable (double-click to edit). Overrides the grid `editMode`. #424: pass a
2404
+ * predicate `(row, { field }) => boolean` to make it editable only on the rows that satisfy it (like
2405
+ * `cellStyle`/`cellClassName`). A `false` result behaves exactly like `editable: false` for that cell — no
2406
+ * editor on double-click/Enter/F2, and the cell is skipped by paste, cut and the batch editor. */
2407
+ editable?: boolean | ((row: T, ctx: { field: string }) => boolean);
2260
2408
  /** Editor type. "select" (or any column with `valueOptions`) renders a dropdown; else a text/number input by column type. */
2261
2409
  editType?: "text" | "number" | "select";
2262
2410
  /** Full escape hatch for the inline cell editor — render your own control (a searchable / creatable /
@@ -2265,9 +2413,18 @@ interface DatatableColumn<T = any> {
2265
2413
  * built-in select/text editor. Call `commit(nextValue)` to save (fires `onRowUpdate`/`onRowsChange`)
2266
2414
  * or `cancel()` to discard. Twico overlay dropdowns (portaled as `.twc-pop`) are exempt from the
2267
2415
  * cell's outside-click auto-cancel, so a Combobox popover works inside the cell. **Escape cancels**
2268
- * the edit automatically (the wrapper calls `cancel()`), so you needn't wire a keydown — stop
2269
- * propagation on Escape only if your control needs it (e.g. to close its own open dropdown). */
2270
- renderEditCell?: (args: { value: any; row: T; field: string; commit: (nextValue: any) => void; cancel: () => void }) => React.ReactNode;
2416
+ * the edit automatically — but #412: the wrapper IGNORES an Escape a nested control already handled
2417
+ * (`defaultPrevented`), so a twico Select/Combobox/MultiSelect closing its list inside the editor doesn't
2418
+ * cancel the whole edit (a second Escape does). A custom control can still `stopPropagation` to keep Escape.
2419
+ * #390: call `setDraft(next)` as the user types to STAGE a value — click-away then commits the staged
2420
+ * draft spreadsheet-style (like the built-in editor) instead of discarding it; an editor that never stages
2421
+ * keeps the cancel-on-click-away behaviour. #413: pass `{ patch: true }` to stage a multi-key PATCH for
2422
+ * click-away (same no-op rule as `commitPatch`); #423: pass `{ silent: true }` to stage WITHOUT re-rendering
2423
+ * the grid (for an editor that renders from its own draft state — avoids per-keystroke lag on large pages).
2424
+ * Call `commitPatch(patch)` to write several stored keys at once
2425
+ * (a quantity + its unit shown as one column) — it writes `{ ...row, ...patch }` and no-ops only when every
2426
+ * patched key is unchanged. */
2427
+ renderEditCell?: (args: { value: any; row: T; field: string; commit: (nextValue: any) => void; cancel: () => void; setDraft: (next: any, opts?: { patch?: boolean; silent?: boolean }) => void; commitPatch: (patch: Partial<T>) => void }) => React.ReactNode;
2271
2428
  /** Custom control for this column's clause in the **batch** editor (#247) — the counterpart of
2272
2429
  * `renderEditCell` for the "Edit N selected rows" popover. Use it when the value is backed by a large,
2273
2430
  * async, creatable vocabulary that `valueOptions` (a static array) can't express; without it such a
@@ -2328,13 +2485,29 @@ interface DatatableRowAction<T = any> {
2328
2485
  icon?: React.ReactNode;
2329
2486
  /** Accessible label / tooltip / menu text. */
2330
2487
  label: string;
2331
- /** Click handler, receives the row. */
2332
- onClick?: (row: T) => void;
2488
+ /** Click handler, receives the row and the click event. Still runs for a plain left-click when `href` is set
2489
+ * (so client-side routing keeps working); #419: call `e.preventDefault()` there to suppress the native
2490
+ * navigation before you route (otherwise the browser also follows `href` → a full page load). Modifier and
2491
+ * middle clicks fall through to the browser. */
2492
+ onClick?: (row: T, e: React.MouseEvent) => void;
2493
+ /** #399: render this action as a link (`<a>`) — middle-click, open-in-new-tab and copy-address all work.
2494
+ * The URL is scheme-sanitised (`javascript:`/`data:`/`vbscript:` are dropped). A `disabled` action never
2495
+ * emits an href. */
2496
+ href?: string;
2497
+ /** Anchor `target` for the `href` link (e.g. `"_blank"`). */
2498
+ target?: string;
2499
+ /** Anchor `rel` for the `href` link (pair `rel="noopener noreferrer"` with `target="_blank"`). */
2500
+ rel?: string;
2333
2501
  /** Place in the ⋮ overflow menu instead of inline. @default false */
2334
2502
  showInMenu?: boolean;
2335
2503
  /** Render in danger color. */
2336
2504
  danger?: boolean;
2337
2505
  disabled?: boolean;
2506
+ /** #399: shown when `disabled` — as the tooltip for an inline action and as an inline hint in the ⋮ menu.
2507
+ * #419: when set, the inline action renders `aria-disabled` (not native `disabled`) so it stays focusable and
2508
+ * the reason is reachable by hover AND keyboard; click and Enter/Space stay blocked. The menu hint is always
2509
+ * reachable. */
2510
+ disabledReason?: React.ReactNode;
2338
2511
  }
2339
2512
 
2340
2513
  /** Extra context handed to a batch action's `onClick`. */
@@ -3089,9 +3262,21 @@ interface FileUploadProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "on
3089
3262
  /** Called with the files that failed validation: `{ file, reason }` where reason is "type" | "size" | "count". */
3090
3263
  onReject?: (rejections: Array<{ file: File; reason: "type" | "size" | "count" }>) => void;
3091
3264
  onChange?: (files: File[]) => void;
3265
+ /** #406: headless mode — render only this element (a camera badge, an "Attach" IconButton, …) instead of the
3266
+ * dropzone + file list. A click opens the picker and the same accept/maxSize/maxFiles/onReject validation
3267
+ * still runs; track the files yourself via `value`/`onChange`. */
3268
+ trigger?: React.ReactNode;
3269
+ /** #406: also accept dropped files onto the `trigger` (headless mode only). @default false */
3270
+ dropOnTrigger?: boolean;
3271
+ children?: React.ReactNode;
3092
3272
  }
3093
3273
 
3094
- declare function FileUpload(props: FileUploadProps): React.JSX.Element;
3274
+ /** #406: imperative handle exposed via a ref — `open()` opens the native file picker. */
3275
+ interface FileUploadHandle {
3276
+ open(): void;
3277
+ }
3278
+
3279
+ declare const FileUpload: React.ForwardRefExoticComponent<FileUploadProps & React.RefAttributes<FileUploadHandle>>;
3095
3280
 
3096
3281
  /**
3097
3282
  * Square (or circular) button for a single icon. Always provide an aria-label.
@@ -3110,6 +3295,16 @@ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
3110
3295
  size?: "xs" | "sm" | "md" | "lg";
3111
3296
  /** Fully rounded (circular). @default false */
3112
3297
  round?: boolean;
3298
+ /** #398: when `disabled`, stay focusable (render `aria-disabled` instead of native `disabled`) so a wrapping
3299
+ * `Tooltip` explaining *why* it's disabled is reachable by keyboard. Click and Enter/Space stay blocked and
3300
+ * the disabled styling still applies. @default false */
3301
+ focusableWhenDisabled?: boolean;
3302
+ /** #405: toggle "on" state — sets `aria-pressed` and shows a soft fill + border in the current `tone`
3303
+ * (works with any `variant`), e.g. a pin/unpin or bold/italic icon toggle. @default undefined */
3304
+ pressed?: boolean;
3305
+ /** #411: tone of the pressed ("on") fill — the full status `Tone` scale, so a toggle can carry its own
3306
+ * selected-state meaning while `tone` stays `ActionTone` for the unpressed look. Defaults to `tone`. @default undefined */
3307
+ pressedTone?: Tone;
3113
3308
  /** #342: render as a different element — use `"a"` for an icon **link** (GitHub icon, external nav, …) so
3114
3309
  * navigation is a real link, not a button. @default "button" */
3115
3310
  as?: "button" | "a";
@@ -3125,6 +3320,63 @@ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
3125
3320
 
3126
3321
  declare function IconButton(props: IconButtonProps): React.JSX.Element;
3127
3322
 
3323
+ /** One toggle button in a {@link ToggleGroup}. */
3324
+ interface ToggleGroupItem {
3325
+ /** Unique value emitted through `onValueChange` and matched against `value`/`defaultValue`. */
3326
+ value: string;
3327
+ /** Visible label (omit for an icon-only toggle, then set `aria-label`). */
3328
+ label?: React.ReactNode;
3329
+ /** Leading icon node. */
3330
+ icon?: React.ReactNode;
3331
+ /** Disable just this toggle. */
3332
+ disabled?: boolean;
3333
+ /** #411: pressed ("on") tone for THIS item, overriding the group `tone` — so options can carry their own
3334
+ * meaning colour (e.g. Allow=success, Deny=danger, Clear=neutral). */
3335
+ tone?: Tone;
3336
+ /** Accessible label — required when the toggle is icon-only. */
3337
+ "aria-label"?: string;
3338
+ }
3339
+
3340
+ /**
3341
+ * A set of **toggle buttons** (`aria-pressed`) — a tool/mode switch (Allow / Deny / Clear), a formatting bar
3342
+ * (bold / italic), or a segmented control. Per WAI-ARIA it is a *group of toggle buttons*, not a radiogroup:
3343
+ * with `roving`, arrow keys move focus only; Space/Enter/click toggle. Composes `Button` for its look.
3344
+ *
3345
+ * @startingPoint section="Buttons" subtitle="Group of toggle buttons" viewport="700x160"
3346
+ */
3347
+ interface ToggleGroupProps {
3348
+ /** The toggles to render. */
3349
+ items: ToggleGroupItem[];
3350
+ /** `"single"` — one value (`string | null`); clicking the active one deselects. `"multiple"` — a `string[]`.
3351
+ * @default "single" */
3352
+ type?: "single" | "multiple";
3353
+ /** Controlled value: a `string | null` for `"single"`, a `string[]` for `"multiple"`. Pair with `onValueChange`. */
3354
+ value?: string | string[] | null;
3355
+ /** Initial value for the uncontrolled case. */
3356
+ defaultValue?: string | string[] | null;
3357
+ /** Fired with the next value (a `string | null`, or a fresh `string[]`) when a toggle changes. */
3358
+ onValueChange?: (value: string | string[] | null) => void;
3359
+ /** Button size. @default "md" */
3360
+ size?: "xs" | "sm" | "md" | "lg";
3361
+ /** #411: default pressed ("on") fill tone for the group — the full status `Tone` scale (a per-item `tone`
3362
+ * overrides it). The unpressed look stays action-neutral. @default "primary" */
3363
+ tone?: Tone;
3364
+ /** The button variant used for the OFF (unpressed) look. @default "outline" */
3365
+ variant?: "solid" | "soft" | "outline" | "ghost";
3366
+ /** Opt into roving arrow-key focus (WAI-ARIA) — the group is one Tab stop and arrows move focus between
3367
+ * toggles. Off by default (each toggle is in the native tab order). @default false */
3368
+ roving?: boolean;
3369
+ /** Layout + roving axis. @default "horizontal" */
3370
+ orientation?: "horizontal" | "vertical";
3371
+ /** Disable the whole group. @default false */
3372
+ disabled?: boolean;
3373
+ /** Accessible label for the `role="group"` container. */
3374
+ "aria-label"?: string;
3375
+ className?: string;
3376
+ }
3377
+
3378
+ declare function ToggleGroup(props: ToggleGroupProps): React.JSX.Element;
3379
+
3128
3380
  /**
3129
3381
  * Text input with optional label, hint, error state, and inline icons.
3130
3382
  *
@@ -3571,6 +3823,10 @@ interface SidebarProps extends React.HTMLAttributes<HTMLElement> {
3571
3823
  items: SidebarItem[];
3572
3824
  /** Content pinned above the collapse toggle (e.g. a user row). */
3573
3825
  footer?: React.ReactNode;
3826
+ /** #402: remove the built-in padding around `footer` content so an edge-to-edge account row (whose hover
3827
+ * background should reach the rail edges + the top divider) doesn't need consumer negative margins. #417:
3828
+ * when no collapse button follows (`collapsible={false}`), the row also reaches the rail's bottom edge. @default true */
3829
+ footerInset?: boolean;
3574
3830
  /** Controlled collapsed state. */
3575
3831
  collapsed?: boolean;
3576
3832
  /** Uncontrolled initial collapsed state. @default false */
@@ -4539,4 +4795,30 @@ declare function useFocusTrap<T extends HTMLElement = HTMLElement>(
4539
4795
  */
4540
4796
  declare function usePortal(): (node: React.ReactNode) => React.ReactPortal | React.ReactNode | null;
4541
4797
 
4542
- export { Accordion, type AccordionItem, type AccordionProps, type ActionTone, Alert, type AlertProps, Anchor, type AnchorProps, AppShell, type AppShellProps, Avatar, AvatarMenu, type AvatarMenuProps, type AvatarProps, Badge, type BadgeProps, type BarTone, Box, type BoxOwnProps, type BoxProps, Boxplot, type BoxplotDatum, type BoxplotProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, BubbleChart, type BubbleChartProps, Button, type ButtonProps, Candlestick, type CandlestickDatum, type CandlestickProps, Card, CardGrid, type CardGridFilter, type CardGridProps, type CardGridQuery, type CardGridSort, type CardGridSortOption, type CardProps, Carousel, type CarouselProps, Chart, type ChartDatum, type ChartProps, Checkbox, type CheckboxProps, Code, type CodeProps, ColorPicker, type ColorPickerProps, ColorSchemeScript, type ColorSchemeScriptOptions, type ColorSchemeScriptProps, Combobox, type ComboboxGroup, type ComboboxOption, type ComboboxProps, type Command, CommandPalette, type CommandPaletteProps, Container, type ContainerOwnProps, type ContainerProps, Currency, CurrencyField, type CurrencyFieldProps, type CurrencyOption, type CurrencyProps, Datatable, type DatatableBatchAction, type DatatableBatchActionContext, type DatatableColumn, type DatatableFilter, type DatatableFilterOp, type DatatableNumberOp, type DatatableProps, type DatatableQuery, type DatatableRowAction, type DatatableState, type DatatableStringOp, DatePicker, type DatePickerProps, type DateRange, DateRangePicker, type DateRangePickerProps, DateTimePicker, type DateTimePickerProps, Dialog, type DialogProps, type DiffOp, DiffTable, type DiffTableColumn, type DiffTableProps, Divider, type DividerProps, DonutChart, type DonutChartDatum, type DonutChartProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Field, type FieldProps, FileUpload, type FileUploadProps, FilterBar, type FilterBarProps, type FilterClause, type FilterField, type FilterFieldType, type FilterValues, Form, type FormProps, FunnelChart, type FunnelChartProps, type FunnelDatum, Gauge, type GaugeProps, type GaugeSeries, Grid, type GridOwnProps, type GridProps, Heading, type HeadingOwnProps, type HeadingProps, type HeadingSize, Heatmap, type HeatmapDatum, type HeatmapProps, IconButton, type IconButtonProps, Image, type ImageProps, Input, type InputProps, Kanban, type KanbanCard, type KanbanColumn, type KanbanProps, Kbd, type KbdProps, Label, type LabelProps, List, type ListItemData, type ListProps, Menu, type MenuItemDef, type MenuProps, MultiSelect, type MultiSelectGroup, type MultiSelectOption, type MultiSelectProps, Navbar, type NavbarLink, type NavbarProps, type Option, type OptionGroup, Pagination, type PaginationProps, PieChart, type PieChartDatum, type PieChartProps, PolarAreaChart, type PolarAreaChartProps, type PolarAreaDatum, type PolymorphicAs, type PolymorphicComponent, type PolymorphicProps, type PolymorphicPropsWithRef, type PolymorphicRef, Popover, type PopoverProps, Portal, type PortalProps, Pre, type PreProps, Progress, type ProgressProps, RadarChart, type RadarChartProps, type RadarDatum, Radio, RadioGroup, type RadioGroupOption, type RadioGroupProps, type RadioProps, RangeChart, type RangeChartProps, type RangeDatum, Rating, type RatingProps, type ResponsiveColumns, ScatterChart, type ScatterChartProps, type ScatterPoint, type ScatterSeries, Select, type SelectGroup, type SelectOption, type SelectProps, Sidebar, type SidebarItem, type SidebarProps, Skeleton, type SkeletonProps, Slider, type SliderProps, Sparkline, type SparklineDatum, type SparklineProps, Spinner, type SpinnerProps, Stack, type StackOwnProps, type StackProps, Stat, type StatProps, type Step, Stepper, type StepperProps, Switch, type SwitchProps, type Sx, type TabItem, Table, type TableColumn, type TableProps, Tabs, type TabsProps, Tag, type TagProps, Text, type TextOwnProps, type TextProps, type TextTone, Textarea, type TextareaProps, type Theme, ThemeProvider, type ThemeProviderProps, type ThemeTokens, TimePicker, type TimePickerProps, Timeline, type TimelineItem, type TimelineProps, Toast, type ToastApi, type ToastOptions, type ToastProps, ToastProvider, type ToastProviderProps, type ToastTone, ToastViewport, type ToastViewportProps, type Tone, Tooltip, type TooltipProps, type TreeNode, TreeView, type TreeViewProps, Treemap, type TreemapDatum, type TreemapProps, TwicoProvider, type TwicoProviderProps, type UseColorSchemeOptions, type UseFocusTrapOptions, type UseKeyPressOptions, type UseMediaQueryOptions, VisuallyHidden, type VisuallyHiddenProps, type WithSx, createTheme, getColorSchemeScript, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useFocusTrap, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePortal, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
4798
+ /** #406: options for {@link useFilePicker}. */
4799
+ interface UseFilePickerOptions {
4800
+ /** Accepted file types (input accept string, e.g. "image/*,.pdf"). */
4801
+ accept?: string;
4802
+ /** Allow selecting multiple files. @default false */
4803
+ multiple?: boolean;
4804
+ /** Max size per file in bytes; larger files are rejected. */
4805
+ maxSize?: number;
4806
+ /** Max number of files accepted within a SINGLE selection (the hook is stateless — it can't count across
4807
+ * separate picks; track cumulative selection yourself). */
4808
+ maxFiles?: number;
4809
+ /** Called with the files that passed validation. */
4810
+ onFiles?: (files: File[]) => void;
4811
+ /** Called with rejected files: `{ file, reason }` where reason is "type" | "size" | "count". */
4812
+ onReject?: (rejections: Array<{ file: File; reason: "type" | "size" | "count" }>) => void;
4813
+ }
4814
+
4815
+ /**
4816
+ * #406: open a native file picker from your own trigger while reusing FileUpload's validation. Render
4817
+ * `<input {...getInputProps()} />` (hidden) once, then call `open()` from any control.
4818
+ */
4819
+ declare function useFilePicker(options?: UseFilePickerOptions): {
4820
+ open: () => void;
4821
+ getInputProps: () => React.InputHTMLAttributes<HTMLInputElement> & { ref: React.RefObject<HTMLInputElement | null> };
4822
+ };
4823
+
4824
+ export { Accordion, type AccordionItem, type AccordionProps, type ActionTone, Alert, type AlertProps, Anchor, type AnchorProps, AppShell, type AppShellProps, Avatar, AvatarMenu, type AvatarMenuProps, type AvatarProps, Badge, type BadgeProps, type BarTone, Box, type BoxOwnProps, type BoxProps, Boxplot, type BoxplotDatum, type BoxplotProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, BubbleChart, type BubbleChartProps, Button, type ButtonProps, Candlestick, type CandlestickDatum, type CandlestickProps, Card, CardGrid, type CardGridFilter, type CardGridProps, type CardGridQuery, type CardGridSort, type CardGridSortOption, type CardProps, Carousel, type CarouselProps, Chart, type ChartDatum, type ChartProps, Checkbox, type CheckboxProps, Code, type CodeProps, ColorPicker, type ColorPickerProps, ColorSchemeScript, type ColorSchemeScriptOptions, type ColorSchemeScriptProps, Combobox, type ComboboxGroup, type ComboboxOption, type ComboboxProps, type Command, CommandPalette, type CommandPaletteProps, Container, type ContainerOwnProps, type ContainerProps, Currency, CurrencyField, type CurrencyFieldProps, type CurrencyOption, type CurrencyProps, Datatable, type DatatableBatchAction, type DatatableBatchActionContext, type DatatableColumn, type DatatableFilter, type DatatableFilterOp, type DatatableNumberOp, type DatatableProps, type DatatableQuery, type DatatableRowAction, type DatatableState, type DatatableStringOp, DatePicker, type DatePickerProps, type DateRange, DateRangePicker, type DateRangePickerProps, DateTimePicker, type DateTimePickerProps, Dialog, type DialogProps, type DiffOp, DiffTable, type DiffTableColumn, type DiffTableProps, Divider, type DividerProps, DonutChart, type DonutChartDatum, type DonutChartProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Field, type FieldProps, FileUpload, type FileUploadProps, FilterBar, type FilterBarProps, type FilterClause, type FilterField, type FilterFieldType, type FilterValues, Form, type FormProps, FunnelChart, type FunnelChartProps, type FunnelDatum, Gauge, type GaugeProps, type GaugeSeries, Grid, type GridOwnProps, type GridProps, Heading, type HeadingOwnProps, type HeadingProps, type HeadingSize, Heatmap, type HeatmapDatum, type HeatmapProps, IconButton, type IconButtonProps, Image, type ImageProps, ImageViewer, type ImageViewerControlsApi, type ImageViewerProps, type ImageViewerState, Input, type InputProps, Kanban, type KanbanCard, type KanbanColumn, type KanbanProps, Kbd, type KbdProps, Label, type LabelProps, List, type ListItemData, type ListProps, Menu, type MenuItemDef, type MenuProps, MultiSelect, type MultiSelectGroup, type MultiSelectOption, type MultiSelectProps, Navbar, type NavbarLink, type NavbarProps, type Option, type OptionGroup, Pagination, type PaginationProps, PieChart, type PieChartDatum, type PieChartProps, PolarAreaChart, type PolarAreaChartProps, type PolarAreaDatum, type PolymorphicAs, type PolymorphicComponent, type PolymorphicProps, type PolymorphicPropsWithRef, type PolymorphicRef, Popover, type PopoverProps, Portal, type PortalProps, Pre, type PreProps, Progress, type ProgressProps, RadarChart, type RadarChartProps, type RadarDatum, Radio, RadioGroup, type RadioGroupOption, type RadioGroupProps, type RadioProps, RangeChart, type RangeChartProps, type RangeDatum, Rating, type RatingProps, type ResponsiveColumns, ScatterChart, type ScatterChartProps, type ScatterPoint, type ScatterSeries, Select, type SelectGroup, type SelectOption, type SelectProps, Sidebar, type SidebarItem, type SidebarProps, Skeleton, type SkeletonProps, Slider, type SliderProps, Sparkline, type SparklineDatum, type SparklineProps, Spinner, type SpinnerProps, Stack, type StackOwnProps, type StackProps, Stat, type StatProps, type Step, Stepper, type StepperProps, Switch, type SwitchProps, type Sx, type TabItem, Table, type TableColumn, type TableProps, Tabs, type TabsProps, Tag, type TagProps, Text, type TextOwnProps, type TextProps, type TextTone, Textarea, type TextareaProps, type Theme, ThemeProvider, type ThemeProviderProps, type ThemeTokens, TimePicker, type TimePickerProps, Timeline, type TimelineItem, type TimelineProps, Toast, type ToastApi, type ToastOptions, type ToastProps, ToastProvider, type ToastProviderProps, type ToastTone, ToastViewport, type ToastViewportProps, ToggleGroup, type ToggleGroupItem, type ToggleGroupProps, type Tone, Tooltip, type TooltipProps, type TreeNode, TreeView, type TreeViewProps, Treemap, type TreemapDatum, type TreemapProps, TwicoProvider, type TwicoProviderProps, type UseColorSchemeOptions, type UseFilePickerOptions, type UseFocusTrapOptions, type UseKeyPressOptions, type UseMediaQueryOptions, VisuallyHidden, type VisuallyHiddenProps, type WithSx, createTheme, getColorSchemeScript, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useFilePicker, useFocusTrap, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePortal, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };