@tailor-platform/app-shell 1.10.1 → 1.12.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.
@@ -21,12 +21,15 @@ import { JSX } from 'react/jsx-runtime';
21
21
  import { Link } from 'react-router';
22
22
  import { LoaderFunctionArgs } from 'react-router';
23
23
  import { Menu as Menu_2 } from '@base-ui/react/menu';
24
+ import { Navigate } from 'react-router';
24
25
  import { parseAbsolute } from '@internationalized/date';
25
26
  import { parseDate } from '@internationalized/date';
26
27
  import { parseDateTime } from '@internationalized/date';
27
28
  import { parseZonedDateTime } from '@internationalized/date';
28
29
  import * as React_2 from 'react';
30
+ import { ReactElement } from 'react';
29
31
  import { ReactNode } from 'react';
32
+ import { Ref } from 'react';
30
33
  import { RefObject } from 'react';
31
34
  import { Select as Select_2 } from '@base-ui/react/select';
32
35
  import { StandardSchemaV1 } from '@standard-schema/spec';
@@ -1817,7 +1820,7 @@ declare namespace Content_3 {
1817
1820
  var displayName: string;
1818
1821
  }
1819
1822
 
1820
- /** The main sheet panel. The `side` is inherited from `Sheet.Root` via context. */
1823
+ /** The main sheet panel. The `side` and modal behavior are inherited from `Sheet.Root` via context. */
1821
1824
  declare function Content_4({ className, children, size, ...props }: SheetContentProps): JSX.Element;
1822
1825
 
1823
1826
  declare namespace Content_4 {
@@ -2210,6 +2213,14 @@ export declare interface DataTableContextValue<TRow extends Record<string, unkno
2210
2213
  clearSelection?: () => void;
2211
2214
  isAllSelected: boolean;
2212
2215
  isIndeterminate: boolean;
2216
+ /** Ids of the currently expanded rows. */
2217
+ expandedIds?: string[];
2218
+ /** Whether `row` is currently expanded. Always `false` for rows without an `id`. */
2219
+ isRowExpanded?: (row: TRow) => boolean;
2220
+ toggleRowExpansion?: (row: TRow) => void;
2221
+ collapseAllRows?: () => void;
2222
+ /** Expansion config. Its presence enables the expand column and detail rows. */
2223
+ rowExpansion?: RowExpansionOptions<TRow>;
2213
2224
  }
2214
2225
 
2215
2226
  /**
@@ -2234,7 +2245,10 @@ declare function DataTableFilters({ className, slot, addIconOnly, }: {
2234
2245
  * different rows (e.g. the trigger in a header row, chips on the row below).
2235
2246
  */
2236
2247
  slot?: "all" | "chips" | "add";
2237
- /** Render the **Add filter** trigger as an icon-only button (label → `aria-label`). */
2248
+ /**
2249
+ * Render the **Add filter** trigger as an icon-only button (label → `aria-label`).
2250
+ * Defaults to `true`; pass `addIconOnly={false}` to show the "Add filter" text label.
2251
+ */
2238
2252
  addIconOnly?: boolean;
2239
2253
  }): JSX.Element | null;
2240
2254
 
@@ -2306,10 +2320,30 @@ declare namespace DataTableToolbar {
2306
2320
  var displayName: string;
2307
2321
  }
2308
2322
 
2309
- declare interface DateBehaviorProps<T extends DateValue> {
2323
+ /** Options for `type: "date"` cells. */
2324
+ declare interface DateCellOptions {
2325
+ /**
2326
+ * Format style. `"short"` → `Apr 9, 2026`; `"long"` → `April 9, 2026`;
2327
+ * `"datetime"` → `Apr 9, 2026, 3:45 PM`. Default: `"short"`.
2328
+ */
2329
+ dateFormat?: "short" | "long" | "datetime";
2330
+ /** BCP 47 locale tag. Defaults to the runtime locale. */
2331
+ locale?: string;
2332
+ }
2333
+
2334
+ /**
2335
+ * Public date controls.
2336
+ *
2337
+ * These are standalone composite widgets built on plain accessible markup and a
2338
+ * proxy input for form value / native validity. Inside `Field.Root`, they also
2339
+ * register with Base UI's label, description, and validation plumbing. All of
2340
+ * that coupling lives in `useDateFieldFieldBridge` (see `./use-date-field-bridge`).
2341
+ */
2342
+ declare interface DateControlProps<T extends DateValue> {
2310
2343
  value?: T | null;
2311
2344
  defaultValue?: T | null;
2312
2345
  onChange?: (value: T | null) => void;
2346
+ onBlur?: () => void;
2313
2347
  granularity?: Granularity;
2314
2348
  minValue?: DateValue;
2315
2349
  maxValue?: DateValue;
@@ -2320,52 +2354,32 @@ declare interface DateBehaviorProps<T extends DateValue> {
2320
2354
  isInvalid?: boolean;
2321
2355
  autoFocus?: boolean;
2322
2356
  hourCycle?: HourCycle;
2323
- hideTimeZone?: boolean;
2324
2357
  placeholderValue?: DateValue;
2325
- /**
2326
- * First day of the week (0 = Sunday … 6 = Saturday); defaults to the locale.
2327
- * Only affects the `w`/`k` (start/end of week) keyboard shortcuts here.
2328
- */
2329
2358
  firstDayOfWeek?: FirstDayOfWeek;
2330
2359
  name?: string;
2331
- /** Accessible name when no visible `label` is provided (e.g. a compact filter input). */
2360
+ className?: string;
2361
+ id?: string;
2362
+ /** Accessible name when there is no visible label. */
2332
2363
  "aria-label"?: string;
2364
+ /** ID of the element(s) that label the control. */
2365
+ "aria-labelledby"?: string;
2366
+ /** ID of the element(s) that describe the control. */
2367
+ "aria-describedby"?: string;
2333
2368
  /** BCP-47 locale override; defaults to the AppShell formatting locale. */
2334
2369
  locale?: string;
2335
2370
  }
2336
2371
 
2337
- /** Options for `type: "date"` cells. */
2338
- declare interface DateCellOptions {
2339
- /**
2340
- * Format style. `"short"` → `Apr 9, 2026`; `"long"` → `April 9, 2026`;
2341
- * `"datetime"` → `Apr 9, 2026, 3:45 PM`. Default: `"short"`.
2342
- */
2343
- dateFormat?: "short" | "long" | "datetime";
2344
- /** BCP 47 locale tag. Defaults to the runtime locale. */
2345
- locale?: string;
2346
- }
2347
-
2348
2372
  /**
2349
2373
  * A segmented date/time input field with no popover.
2350
2374
  *
2351
- * @example
2352
- * ```tsx
2353
- * import { DateField } from "@tailor-platform/app-shell";
2354
- *
2355
- * <DateField label="Invoice date" />
2356
- * <DateField label="Created at" granularity="minute" />
2357
- * ```
2375
+ * Compose with `Field.Root` for label / description / error presentation, or
2376
+ * provide standalone ARIA wiring yourself.
2358
2377
  */
2359
- export declare function DateField<T extends DateValue = DateValue>({ label, description, errorMessage, className, locale: localeProp, value, defaultValue, onChange, granularity, hourCycle, placeholderValue, minValue, maxValue, isDateUnavailable, isDisabled, isReadOnly, isInvalid, isRequired, autoFocus, firstDayOfWeek, name, "aria-label": ariaLabel, }: DateFieldProps<T>): JSX.Element;
2378
+ export declare const DateField: <T extends DateValue = DateValue>(props: DateFieldProps<T> & {
2379
+ ref?: Ref<HTMLInputElement>;
2380
+ }) => ReactElement;
2360
2381
 
2361
- declare interface DateFieldMetaProps {
2362
- label?: LocalizedString;
2363
- description?: LocalizedString;
2364
- errorMessage?: LocalizedString;
2365
- className?: string;
2366
- }
2367
-
2368
- export declare type DateFieldProps<T extends DateValue = DateValue> = DateFieldMetaProps & DateBehaviorProps<T>;
2382
+ export declare type DateFieldProps<T extends DateValue = DateValue> = DateControlProps<T>;
2369
2383
 
2370
2384
  /**
2371
2385
  * Date format options
@@ -2375,21 +2389,92 @@ declare type DateFormat = "short" | "medium" | "long" | "relative";
2375
2389
  /**
2376
2390
  * A date/time input with a popover calendar.
2377
2391
  *
2378
- * Value type is driven by `granularity`:
2379
- * - `"day"` (default) → `CalendarDate`
2380
- * - `"hour" | "minute" | "second"` → `CalendarDateTime` (or `ZonedDateTime` when a `timeZone` is set)
2381
- *
2382
- * @example
2383
- * ```tsx
2384
- * import { DatePicker, today, getLocalTimeZone, type CalendarDate } from "@tailor-platform/app-shell";
2392
+ * Compose with `Field.Root` for label / description / error presentation, or
2393
+ * provide standalone ARIA wiring yourself.
2394
+ */
2395
+ export declare const DatePicker: <T extends DateValue = DateValue>(props: DatePickerProps<T> & {
2396
+ ref?: Ref<HTMLInputElement>;
2397
+ }) => ReactElement;
2398
+
2399
+ export declare type DatePickerProps<T extends DateValue = DateValue> = DateControlProps<T> & {
2400
+ /** IANA timezone; defaults to the AppShell `timeZone`. */
2401
+ timeZone?: string;
2402
+ };
2403
+
2404
+ /**
2405
+ * Range calendar state — the logic react-aria's `useRangeCalendarState` would
2406
+ * otherwise provide, on top of the shared `useCalendarGridState` engine.
2385
2407
  *
2386
- * const [date, setDate] = useState<CalendarDate | null>(null);
2387
- * <DatePicker label="Ship date" value={date} onChange={setDate} />
2388
- * ```
2408
+ * Selection is the react-aria two-click model: the first confirmed day sets an
2409
+ * *anchor*; while the anchor is set the highlighted range live-extends to the
2410
+ * focused day (keyboard nav and pointer hover both move it); the second
2411
+ * confirmed day commits `{ start, end }` in one `onChange`. Picking a day
2412
+ * before the anchor swaps the endpoints, so a committed range is always
2413
+ * ordered — a reversed range can only be produced by typing into the field.
2389
2414
  */
2390
- export declare function DatePicker<T extends DateValue = DateValue>({ label, description, errorMessage, className, locale: localeProp, timeZone: timeZoneProp, value, defaultValue, onChange, granularity, hourCycle, placeholderValue, minValue, maxValue, isDateUnavailable, isDisabled, isReadOnly, isInvalid, isRequired, autoFocus, firstDayOfWeek, name, "aria-label": ariaLabel, }: DatePickerProps<T>): JSX.Element;
2415
+ /** An inclusive date range. `start` and `end` may be the same day. */
2416
+ export declare interface DateRange<T extends DateValue = DateValue> {
2417
+ start: T;
2418
+ end: T;
2419
+ }
2420
+
2421
+ export declare const DateRangePicker: <T extends DateValue = DateValue>(props: DateRangePickerProps<T> & {
2422
+ ref?: Ref<HTMLInputElement>;
2423
+ }) => ReactElement;
2391
2424
 
2392
- export declare type DatePickerProps<T extends DateValue = DateValue> = DateFieldProps<T> & {
2425
+ /**
2426
+ * Public date-range control — the @internationalized/date + Base UI
2427
+ * implementation, mirroring react-aria's `DateRangePicker` interaction spec.
2428
+ *
2429
+ * Like `DateField`/`DatePicker`, it is a standalone composite widget that also
2430
+ * composes inside `Field.Root` (label / description / error / form validation).
2431
+ * A single combined proxy input is registered as the one Field control (its
2432
+ * value is empty until BOTH ends are complete, so `required` blocks a partial
2433
+ * range); two optional plain hidden inputs (`startName` / `endName`) provide
2434
+ * classic form-POST parity. A range typed in reverse is flagged invalid rather
2435
+ * than swapped — only the calendar normalizes endpoint order.
2436
+ */
2437
+ export declare type DateRangePickerProps<T extends DateValue = DateValue> = {
2438
+ value?: DateRange<T> | null;
2439
+ defaultValue?: DateRange<T> | null;
2440
+ /**
2441
+ * Fired with a complete `{ start, end }` range, or `null` when the range is
2442
+ * cleared or becomes incomplete. Never fired for half-typed intermediates.
2443
+ */
2444
+ onChange?: (value: DateRange<T> | null) => void;
2445
+ onBlur?: () => void;
2446
+ granularity?: Granularity;
2447
+ minValue?: DateValue;
2448
+ maxValue?: DateValue;
2449
+ isDateUnavailable?: (date: DateValue) => boolean;
2450
+ isDisabled?: boolean;
2451
+ isReadOnly?: boolean;
2452
+ isRequired?: boolean;
2453
+ isInvalid?: boolean;
2454
+ autoFocus?: boolean;
2455
+ hourCycle?: HourCycle;
2456
+ placeholderValue?: DateValue;
2457
+ firstDayOfWeek?: FirstDayOfWeek;
2458
+ /**
2459
+ * Name for the combined hidden proxy input — a single `name=start/end` field
2460
+ * for native form POST, mirroring `DateField` / `DatePicker`. Inside
2461
+ * `Field.Root`, the Field's `name` takes precedence. For two separate fields,
2462
+ * use `startName` / `endName` instead.
2463
+ */
2464
+ name?: string;
2465
+ /** Names for the two plain hidden start/end inputs (classic form POST). */
2466
+ startName?: string;
2467
+ endName?: string;
2468
+ className?: string;
2469
+ id?: string;
2470
+ /** Accessible name when there is no visible label. */
2471
+ "aria-label"?: string;
2472
+ /** ID of the element(s) that label the control. */
2473
+ "aria-labelledby"?: string;
2474
+ /** ID of the element(s) that describe the control. */
2475
+ "aria-describedby"?: string;
2476
+ /** BCP-47 locale override; defaults to the AppShell formatting locale. */
2477
+ locale?: string;
2393
2478
  /** IANA timezone; defaults to the AppShell `timeZone`. */
2394
2479
  timeZone?: string;
2395
2480
  };
@@ -2740,6 +2825,8 @@ declare namespace Description_4 {
2740
2825
  * Renders structured key-value information with automatic layout.
2741
2826
  * Use { type: "divider" } in the fields array to add dividers between sections.
2742
2827
  *
2828
+ * Pass `render` on a field to draw it yourself when no built-in `type` fits.
2829
+ *
2743
2830
  * @example
2744
2831
  * ```tsx
2745
2832
  * <DescriptionCard
@@ -2750,22 +2837,26 @@ declare namespace Description_4 {
2750
2837
  * { key: "orderNumber", label: "Order #", meta: { copyable: true } },
2751
2838
  * { type: "divider" },
2752
2839
  * { key: "total", label: "Total", type: "money" },
2840
+ * { key: "deliveryBreakdown", label: "Delivery", render: (d) => <PieChart data={d.deliveryBreakdown} /> },
2753
2841
  * ]}
2754
2842
  * />
2755
2843
  * ```
2756
2844
  */
2757
- export declare function DescriptionCard({ data, title, fields, columns, className, style, headerAction, }: DescriptionCardProps): JSX.Element;
2845
+ export declare function DescriptionCard<TData extends object = Record<string, unknown>>({ data, title, fields, columns, className, style, headerAction, }: DescriptionCardProps<TData>): JSX.Element;
2758
2846
 
2759
2847
  /**
2760
2848
  * Props for the DescriptionCard component
2849
+ *
2850
+ * `TData` is inferred from `data`; constrained to `object` rather than
2851
+ * `Record<string, unknown>` so interfaces are accepted.
2761
2852
  */
2762
- export declare interface DescriptionCardProps {
2853
+ export declare interface DescriptionCardProps<TData extends object = Record<string, unknown>> {
2763
2854
  /** Raw backend data object */
2764
- data: Record<string, unknown>;
2855
+ data: TData;
2765
2856
  /** Card title */
2766
2857
  title: string;
2767
2858
  /** Ordered list of field definitions (use { type: "divider" } for dividers) */
2768
- fields: FieldConfig[];
2859
+ fields: FieldConfig<TData>[];
2769
2860
  /** Number of columns on desktop (3 or 4) */
2770
2861
  columns?: Columns;
2771
2862
  /** Additional CSS classes */
@@ -3027,12 +3118,12 @@ export declare const Field: {
3027
3118
  /**
3028
3119
  * A field configuration - either a divider or a field definition
3029
3120
  */
3030
- declare type FieldConfig = FieldDivider | FieldDefinition;
3121
+ declare type FieldConfig<TData extends object = Record<string, unknown>> = FieldDivider | FieldDefinition<TData>;
3031
3122
 
3032
3123
  /**
3033
3124
  * Field definition - renders a key-value pair
3034
3125
  */
3035
- declare interface FieldDefinition {
3126
+ declare interface FieldDefinition<TData extends object = Record<string, unknown>> {
3036
3127
  /** Field type determines rendering (defaults to "text") */
3037
3128
  type?: FieldType_2;
3038
3129
  /** Path to the value in the data object (supports dot notation) */
@@ -3043,6 +3134,12 @@ declare interface FieldDefinition {
3043
3134
  meta?: FieldMeta;
3044
3135
  /** Behavior when value is empty (defaults to "dash") */
3045
3136
  emptyBehavior?: EmptyBehavior;
3137
+ /**
3138
+ * Draws the field from `data` instead of using `type`. Wins over `type` and
3139
+ * replaces the built-in output, so `meta` is not applied. Still runs when the
3140
+ * value at `key` is empty; `emptyBehavior: "hide"` is checked first.
3141
+ */
3142
+ render?: FieldRender<TData>;
3046
3143
  }
3047
3144
 
3048
3145
  /**
@@ -3105,6 +3202,9 @@ export declare interface FieldMetadata {
3105
3202
  };
3106
3203
  }
3107
3204
 
3205
+ /** Renders a field from the whole `data` object, like `render` on DataTable's `Column`. */
3206
+ declare type FieldRender<TData extends object = Record<string, unknown>> = (data: TData) => ReactNode;
3207
+
3108
3208
  declare type FieldRootProps = Pick<React_2.ComponentProps<typeof Field_2.Root>, "name" | "disabled" | "validate" | "validationMode" | "validationDebounceTime" | "className" | "style"> & {
3109
3209
  children: React_2.ReactNode;
3110
3210
  /** Whether the field has been blurred. Maps to Base UI's `touched`. */
@@ -4028,6 +4128,8 @@ declare interface MoneyCellOptions<TRow extends Record<string, unknown>> {
4028
4128
  locale?: string;
4029
4129
  }
4030
4130
 
4131
+ export { Navigate }
4132
+
4031
4133
  /**
4032
4134
  * Extract the node type from a cursor connection result.
4033
4135
  */
@@ -4222,6 +4324,48 @@ declare namespace RadioItemIndicator {
4222
4324
  var displayName: string;
4223
4325
  }
4224
4326
 
4327
+ /**
4328
+ * A standalone inline range calendar. The first click sets one end of the
4329
+ * range, the highlight follows the pointer (or arrow keys), and the second
4330
+ * click completes it — picking a day before the first swaps the endpoints.
4331
+ *
4332
+ * @example
4333
+ * ```tsx
4334
+ * import { RangeCalendar, type DateRange } from "@tailor-platform/app-shell";
4335
+ *
4336
+ * const [range, setRange] = useState<DateRange | null>(null);
4337
+ * <RangeCalendar aria-label="Stay dates" value={range} onChange={setRange} />
4338
+ * ```
4339
+ */
4340
+ export declare function RangeCalendar<T extends DateValue = DateValue>({ value, defaultValue, onChange, minValue, maxValue, isDateUnavailable, isDisabled, isReadOnly, focusedValue, defaultFocusedValue, onFocusChange, firstDayOfWeek, timeZone: timeZoneProp, locale: localeProp, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, }: RangeCalendarProps<T>): JSX.Element;
4341
+
4342
+ /**
4343
+ * Public, closed-API standalone range calendar — the @internationalized/date +
4344
+ * Base UI implementation. Same surface as the react-aria variant; only the
4345
+ * internals differ. Consumers never see Base UI or the calendar engine.
4346
+ */
4347
+ export declare interface RangeCalendarProps<T extends DateValue = DateValue> {
4348
+ value?: DateRange<T> | null;
4349
+ defaultValue?: DateRange<T> | null;
4350
+ /** Fired once per selection, when the second date completes the range. */
4351
+ onChange?: (value: DateRange<T>) => void;
4352
+ minValue?: DateValue;
4353
+ maxValue?: DateValue;
4354
+ isDateUnavailable?: (date: DateValue) => boolean;
4355
+ isDisabled?: boolean;
4356
+ isReadOnly?: boolean;
4357
+ focusedValue?: DateValue;
4358
+ defaultFocusedValue?: DateValue;
4359
+ onFocusChange?: (date: CalendarDate) => void;
4360
+ firstDayOfWeek?: FirstDayOfWeek;
4361
+ "aria-label"?: string;
4362
+ "aria-labelledby"?: string;
4363
+ timeZone?: string;
4364
+ className?: string;
4365
+ /** BCP-47 locale override; defaults to the AppShell formatting locale. */
4366
+ locale?: string;
4367
+ }
4368
+
4225
4369
  /**
4226
4370
  * Redirect to another path.
4227
4371
  *
@@ -4318,7 +4462,7 @@ declare namespace Root {
4318
4462
  * </Sheet.Root>
4319
4463
  * ```
4320
4464
  */
4321
- declare function Root_10({ side, ...props }: SheetRootProps): JSX.Element;
4465
+ declare function Root_10({ side, modal, ...props }: SheetRootProps): JSX.Element;
4322
4466
 
4323
4467
  declare namespace Root_10 {
4324
4468
  var displayName: string;
@@ -4639,6 +4783,54 @@ export declare interface RowAction<TRow extends Record<string, unknown>> {
4639
4783
  onClick: (row: TRow) => void;
4640
4784
  }
4641
4785
 
4786
+ /**
4787
+ * Expandable-row configuration for `useDataTable`.
4788
+ *
4789
+ * The union is what makes an invalid setup unrepresentable: pass `expandedIds`
4790
+ * and you must pass `onChange` with it (controlled), or pass neither and let
4791
+ * the hook own the state. `onChange` alone is still allowed — in uncontrolled
4792
+ * mode it is a notification.
4793
+ */
4794
+ declare type RowExpansionOptions<TRow extends Record<string, unknown>> = {
4795
+ /** Renders the detail panel for an expanded row. */
4796
+ render: (row: TRow) => ReactNode;
4797
+ /**
4798
+ * Decides whether a row can be expanded. Rows returning `false` render an
4799
+ * empty cell in place of the chevron. Defaults to `true` for rows with an
4800
+ * `id`. Gates the panel in both directions: an id in `expandedIds` never
4801
+ * opens a panel for a row this rejects.
4802
+ */
4803
+ canExpand?: (row: TRow) => boolean;
4804
+ /**
4805
+ * The row's record identity — a **bare identifier** such as `"INV-1001"`, not
4806
+ * a sentence. The built-in i18n labels compose it into the accessible names of
4807
+ * the chevron ("Expand row INV-1001") and the panel ("INV-1001 details").
4808
+ * Without it, the generic "Expand row" / "Row details" fallbacks are used.
4809
+ */
4810
+ getLabel?: (row: TRow) => string;
4811
+ } & ({
4812
+ /**
4813
+ * Ids of the expanded rows. Passing this switches expansion to
4814
+ * **controlled** mode: internal state is never written and you update this
4815
+ * array from `onChange`.
4816
+ *
4817
+ * **Batching caveat:** each toggle derives the next array from this
4818
+ * value, so two toggles dispatched before your state commits share a base
4819
+ * and the first is lost. Relevant behind an async store (a debounced URL
4820
+ * sync, `startTransition`) or when looping the toggle over many rows.
4821
+ */
4822
+ expandedIds: string[];
4823
+ /** Called with the full array of expanded ids. Fires once per toggle. */
4824
+ onChange: (ids: string[]) => void;
4825
+ } | {
4826
+ expandedIds?: never;
4827
+ /**
4828
+ * Optional notification in uncontrolled mode, called with the full array
4829
+ * of expanded ids. Fires once per toggle, including under StrictMode.
4830
+ */
4831
+ onChange?: (ids: string[]) => void;
4832
+ });
4833
+
4642
4834
  /**
4643
4835
  * Setter shape compatible with `useSearchParams()`.
4644
4836
  */
@@ -6612,6 +6804,22 @@ export declare type UseDataTableOptions<TRow extends Record<string, unknown>, TF
6612
6804
  * the rows on the **current page**, not all pages.
6613
6805
  */
6614
6806
  onSelectionChange?: (ids: string[]) => void;
6807
+ /**
6808
+ * Expandable detail rows. Providing this enables the whole feature: a chevron
6809
+ * column is added at the left edge (auto-pinned left, after the selection
6810
+ * column) and `render`'s output appears in a full-width row beneath its parent.
6811
+ *
6812
+ * Grouped rather than flat so the parts can't be configured in a broken
6813
+ * combination — a label or predicate without a renderer, or `expandedIds`
6814
+ * without `onChange`, are all compile errors.
6815
+ *
6816
+ * **Requirement:** Each row must have a string or number `id` field.
6817
+ * Expansion is keyed by `id`, so rows without one render no chevron.
6818
+ *
6819
+ * **Note:** Expansion is **not** cleared on page change — ids of rows no
6820
+ * longer on the page simply do not render. Call `collapseAllRows()` to reset.
6821
+ */
6822
+ rowExpansion?: RowExpansionOptions<TRow>;
6615
6823
  /**
6616
6824
  * Sort behaviour configuration.
6617
6825
  *
@@ -6696,6 +6904,16 @@ export declare interface UseDataTableReturn<TRow extends Record<string, unknown>
6696
6904
  clearSelection?: () => void;
6697
6905
  isAllSelected: boolean;
6698
6906
  isIndeterminate: boolean;
6907
+ /** Ids of the currently expanded rows. */
6908
+ expandedIds: string[];
6909
+ /** Whether `row` is currently expanded. Always `false` for rows without an `id`. */
6910
+ isRowExpanded: (row: TRow) => boolean;
6911
+ /** Toggle `row`'s detail panel. Undefined when `rowExpansion` is not provided. */
6912
+ toggleRowExpansion?: (row: TRow) => void;
6913
+ /** Collapse every expanded row. Undefined when `rowExpansion` is not provided. */
6914
+ collapseAllRows?: () => void;
6915
+ /** Expansion config (passthrough for `DataTable.Root`). */
6916
+ rowExpansion?: RowExpansionOptions<TRow>;
6699
6917
  }
6700
6918
 
6701
6919
  /**