@ngrok/mantle 0.84.3 → 0.85.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/agent.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngrok/mantle",
3
- "version": "0.84.3",
3
+ "version": "0.85.0",
4
4
  "origin": "https://mantle.ngrok.com",
5
5
  "endpoints": {
6
6
  "docs": "https://mantle.ngrok.com/",
@@ -3,21 +3,41 @@ import { i as IconButtonIntent, r as IconButtonAppearance, t as IconButton } fro
3
3
  import { s as SortingMode } from "./direction-BjU0bPST.js";
4
4
  import { t as Table$1 } from "./table-DEI-qvSC.js";
5
5
  import { ComponentProps, ReactNode } from "react";
6
- import { HeaderContext, Row, Table } from "@tanstack/react-table";
6
+ import { CellData, Column, Column_RowSorting, Row, RowData, Row_RowExpanding, StockFeatures, Table, TableFeatures } from "@tanstack/react-table";
7
7
  export * from "@tanstack/react-table";
8
8
  //#region src/components/data-table/types.d.ts
9
9
  declare const sortDirections: readonly ["asc", "desc", "unsorted"];
10
10
  type SortDirection = (typeof sortDirections)[number];
11
11
  //#endregion
12
12
  //#region src/components/data-table/data-table.d.ts
13
- type DataTableProps<TData> = ComponentProps<typeof Table$1.Root> & {
14
- table: Table<TData>;
13
+ /**
14
+ * The table features a sortable column needs. `DataTable.HeaderSortButton`
15
+ * calls the column's sorting API, which exists only when the table registers
16
+ * `rowSortingFeature`.
17
+ */
18
+ type SortableTableFeatures = Pick<StockFeatures, "rowSortingFeature">;
19
+ /**
20
+ * The table features an expandable row needs. `DataTable.RowExpandButton`
21
+ * calls the row's expansion API, which exists only when the table registers
22
+ * `rowExpandingFeature`.
23
+ */
24
+ type ExpandableTableFeatures = Pick<StockFeatures, "rowExpandingFeature">;
25
+ /** A column from a table that registers `rowSortingFeature`. */
26
+ type SortableColumn<TFeatures extends SortableTableFeatures, TData extends RowData, TValue extends CellData> = Column<TFeatures, TData, TValue> & Column_RowSorting<TFeatures, TData>;
27
+ /** A row from a table that registers `rowExpandingFeature`. */
28
+ type ExpandableRow<TFeatures extends ExpandableTableFeatures, TData extends RowData> = Row<TFeatures, TData> & Row_RowExpanding;
29
+ type DataTableProps<TFeatures extends TableFeatures, TData extends RowData> = ComponentProps<typeof Table$1.Root> & {
30
+ /**
31
+ * The TanStack Table instance from `useTable`. Every other `DataTable` part
32
+ * reads it through context.
33
+ */
34
+ table: Table<TFeatures, TData>;
15
35
  };
16
36
  /**
17
37
  * The root container for a data table. Wraps all other `DataTable`
18
38
  * sub-components and provides the table context to its descendants.
19
39
  *
20
- * REQUIRED: Construct a TanStack Table instance via `useReactTable` (from
40
+ * REQUIRED: Construct a TanStack Table instance via `useTable` (from
21
41
  * `@tanstack/react-table`, also re-exported from `@ngrok/mantle/data-table`)
22
42
  * and pass it through the `table` prop. The instance owns columns, data, and
23
43
  * any sorting / filtering / pagination state — the wrapper components read
@@ -30,22 +50,23 @@ type DataTableProps<TData> = ComponentProps<typeof Table$1.Root> & {
30
50
  * import {
31
51
  * DataTable,
32
52
  * createColumnHelper,
33
- * getCoreRowModel,
34
- * useReactTable,
53
+ * tableFeatures,
54
+ * useTable,
35
55
  * } from "@ngrok/mantle/data-table";
36
56
  *
37
57
  * type Row = { id: string; name: string };
38
- * const columnHelper = createColumnHelper<Row>();
39
- * const columns = [
58
+ * const features = tableFeatures({});
59
+ * const columnHelper = createColumnHelper<typeof features, Row>();
60
+ * const columns = columnHelper.columns([
40
61
  * columnHelper.accessor("name", {
41
62
  * id: "name",
42
63
  * header: () => <DataTable.Header>Name</DataTable.Header>,
43
64
  * cell: (props) => <DataTable.Cell>{props.getValue()}</DataTable.Cell>,
44
65
  * }),
45
- * ];
66
+ * ]);
46
67
  *
47
68
  * function MyTable({ data }: { data: Row[] }) {
48
- * const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });
69
+ * const table = useTable({ features, data, columns });
49
70
  * const rows = table.getRowModel().rows;
50
71
  *
51
72
  * return (
@@ -61,8 +82,13 @@ type DataTableProps<TData> = ComponentProps<typeof Table$1.Root> & {
61
82
  * }
62
83
  * ```
63
84
  */
64
- declare function Root<TData>({ children, table, ...props }: DataTableProps<TData>): import("react").JSX.Element;
65
- type DataTableHeaderSortButtonProps<TData, TValue> = Omit<ComponentProps<typeof Button>, "appearance" | "icon" | "intent"> & Pick<HeaderContext<TData, TValue>, "column"> & {
85
+ declare function Root<TFeatures extends TableFeatures, TData extends RowData>({ children, table, ...props }: DataTableProps<TFeatures, TData>): import("react").JSX.Element;
86
+ type DataTableHeaderSortButtonProps<TFeatures extends SortableTableFeatures, TData extends RowData, TValue extends CellData> = Omit<ComponentProps<typeof Button>, "appearance" | "icon" | "intent"> & {
87
+ /**
88
+ * The TanStack Table column this button sorts (`props.column` in `header`).
89
+ * The table must register `rowSortingFeature`.
90
+ */
91
+ column: SortableColumn<TFeatures, TData, TValue>;
66
92
  /**
67
93
  * The visual style of the sort button. Optional — the header sort button's
68
94
  * design is a ghost button, so the wrapper defaults it.
@@ -114,6 +140,11 @@ type DataTableHeaderSortButtonProps<TData, TValue> = Omit<ComponentProps<typeof
114
140
  * - For `"alphanumeric"` sorting: `unsorted → ascending → descending → unsorted`
115
141
  * - For `"time"` sorting: `unsorted → newest-first → oldest-first → unsorted`
116
142
  *
143
+ * The table must register `rowSortingFeature`; the `column` prop's type rejects a
144
+ * column from a table without it. Pair it with `sortedRowModel: createSortedRowModel()`,
145
+ * or the button toggles the icon and never reorders a row. Register a `sortFns` slot
146
+ * too: without one, auto-sort falls back to `sortFn_basic`.
147
+ *
117
148
  * When the column cannot sort (`disableSorting`, or `enableSorting: false` on
118
149
  * the column), the part renders the label as plain text in a `<span>`: no
119
150
  * button, no icon. The other props, `ref` included, land on that span.
@@ -122,10 +153,26 @@ type DataTableHeaderSortButtonProps<TData, TValue> = Omit<ComponentProps<typeof
122
153
  * For right-aligned numeric columns, pass `className="justify-end"` and
123
154
  * `iconPlacement="start"` so the sort icon stays paired with the label.
124
155
  *
156
+ * | Data Attribute | Value | Description |
157
+ * | -------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
158
+ * | `data-sort-direction` | `"asc"`, `"desc"`, or `"unsorted"` | The column's current sort direction. Always `"unsorted"` on the plain-text span. |
159
+ * | `data-table-header-action` | present on the button | Presence-only. `DataTable.Header` drops its horizontal padding when a descendant carries it. Absent on the plain-text span. |
160
+ *
125
161
  * @see https://mantle.ngrok.com/components/data-display/data-table#datatableheadersortbutton
126
162
  *
127
163
  * @example
128
164
  * ```tsx
165
+ * const features = tableFeatures({
166
+ * rowSortingFeature,
167
+ * sortedRowModel: createSortedRowModel(),
168
+ * sortFns: {
169
+ * alphanumeric: sortFn_alphanumeric,
170
+ * datetime: sortFn_datetime,
171
+ * text: sortFn_text,
172
+ * },
173
+ * });
174
+ * const columnHelper = createColumnHelper<typeof features, Row>();
175
+ *
129
176
  * columnHelper.accessor("email", {
130
177
  * id: "email",
131
178
  * header: (props) => (
@@ -139,8 +186,14 @@ type DataTableHeaderSortButtonProps<TData, TValue> = Omit<ComponentProps<typeof
139
186
  * });
140
187
  * ```
141
188
  */
142
- declare function HeaderSortButton<TData, TValue>({ appearance, children, className, column, disableSorting, iconPlacement, intent, sortingMode, sortIcon: propSortIcon, onClick, ...props }: DataTableHeaderSortButtonProps<TData, TValue>): import("react").JSX.Element;
143
- type DataTableHeaderProps<TData, TValue> = ComponentProps<typeof Table$1.Header> & Partial<Pick<HeaderContext<TData, TValue>, "column">>;
189
+ declare function HeaderSortButton<TFeatures extends SortableTableFeatures, TData extends RowData, TValue extends CellData>({ appearance, children, className, column, disableSorting, iconPlacement, intent, sortingMode, sortIcon: propSortIcon, onClick, ...props }: DataTableHeaderSortButtonProps<TFeatures, TData, TValue>): import("react").JSX.Element;
190
+ type DataTableHeaderProps<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData> = ComponentProps<typeof Table$1.Header> & {
191
+ /**
192
+ * The TanStack Table column this cell heads (`props.column` in `header`).
193
+ * When the column is sorted, the cell carries `aria-sort`.
194
+ */
195
+ column?: Column<TFeatures, TData, TValue>;
196
+ };
144
197
  /**
145
198
  * A `<th>` optimized for header actions. Wrap each column's header content in
146
199
  * this; for sortable columns, nest a `DataTable.HeaderSortButton` inside and
@@ -164,7 +217,7 @@ type DataTableHeaderProps<TData, TValue> = ComponentProps<typeof Table$1.Header>
164
217
  * });
165
218
  * ```
166
219
  */
167
- declare function Header<TData, TValue>({ children, className, column, ...props }: DataTableHeaderProps<TData, TValue>): import("react").JSX.Element;
220
+ declare function Header<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData>({ children, className, column, ...props }: DataTableHeaderProps<TFeatures, TData, TValue>): import("react").JSX.Element;
168
221
  /**
169
222
  * The `<tbody>` container for rows of data. Typically wraps a map of
170
223
  * `DataTable.Row`, with a `DataTable.EmptyRow` fallback when there is no data.
@@ -173,7 +226,7 @@ declare function Header<TData, TValue>({ children, className, column, ...props }
173
226
  *
174
227
  * @example
175
228
  * ```tsx
176
- * const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });
229
+ * const table = useTable({ features, data, columns });
177
230
  * const rows = table.getRowModel().rows;
178
231
  *
179
232
  * <DataTable.Root table={table}>
@@ -197,7 +250,7 @@ type DataTableHeadProps = Omit<ComponentProps<typeof Table$1.Head>, "children">;
197
250
  *
198
251
  * @example
199
252
  * ```tsx
200
- * const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });
253
+ * const table = useTable({ features, data, columns });
201
254
  * const rows = table.getRowModel().rows;
202
255
  *
203
256
  * <DataTable.Root table={table}>
@@ -210,21 +263,23 @@ type DataTableHeadProps = Omit<ComponentProps<typeof Table$1.Head>, "children">;
210
263
  * </DataTable.Root>
211
264
  * ```
212
265
  */
213
- declare function Head<TData>(props: DataTableHeadProps): import("react").JSX.Element;
214
- type DataTableRowProps<TData> = Omit<ComponentProps<typeof Table$1.Row>, "children"> & {
215
- row: Row<TData>;
266
+ declare function Head(props: DataTableHeadProps): import("react").JSX.Element;
267
+ type DataTableRowProps<TFeatures extends TableFeatures, TData extends RowData> = Omit<ComponentProps<typeof Table$1.Row>, "children"> & {
268
+ /** The TanStack Table row instance to render. */
269
+ row: Row<TFeatures, TData>;
216
270
  /**
217
271
  * Renders an inline detail panel beneath the row. Called only while the row is
218
272
  * expanded (`row.getIsExpanded()`), so the panel — and any expensive work it
219
273
  * does — stays lazy. Mantle wraps the returned content in a sibling
220
274
  * `DataTable.ExpandedRow` spanning every visible column, so return the
221
- * panel content (not a `<tr>`). Requires the table to be configured for
222
- * expansion (`getExpandedRowModel`, plus `getRowCanExpand` for detail panels);
223
- * pair it with a `DataTable.RowExpandButton` toggle in a leading column. For
224
- * full control over the detail row (custom `colSpan`, multiple panels), omit
225
- * this and render `DataTable.ExpandedRow` yourself.
275
+ * panel content (not a `<tr>`). Requires the table to register
276
+ * `rowExpandingFeature`, plus `getRowCanExpand` for detail panels; pair it
277
+ * with a `DataTable.RowExpandButton` toggle in a leading column. Add
278
+ * `expandedRowModel: createExpandedRowModel()` when rows have sub-rows. For
279
+ * full control over the detail row (custom `colSpan`,
280
+ * multiple panels), omit this and render `DataTable.ExpandedRow` yourself.
226
281
  */
227
- renderExpanded?: (row: Row<TData>) => ReactNode;
282
+ renderExpanded?: (row: Row<TFeatures, TData>) => ReactNode;
228
283
  };
229
284
  /**
230
285
  * A single data table body row rendered from a TanStack Table row instance.
@@ -253,7 +308,7 @@ type DataTableRowProps<TData> = Omit<ComponentProps<typeof Table$1.Row>, "childr
253
308
  * Pass `renderExpanded` to give the row an inline detail panel: when the row is
254
309
  * expanded the row renders its data `<tr>` plus a sibling `DataTable.ExpandedRow`
255
310
  * holding the returned content. Pair it with a `DataTable.RowExpandButton` toggle
256
- * and configure the table for expansion (`getExpandedRowModel`, `getRowCanExpand`).
311
+ * and register `rowExpandingFeature` and `getRowCanExpand` on the table.
257
312
  *
258
313
  * | Data Attribute | Value | Description |
259
314
  * | ---------------- | ----------------------------- | ------------------------------------------------------- |
@@ -297,7 +352,7 @@ type DataTableRowProps<TData> = Omit<ComponentProps<typeof Table$1.Row>, "childr
297
352
  * ))}
298
353
  * ```
299
354
  */
300
- declare function Row$1<TData>({ className, onClick, renderExpanded, row, ...props }: DataTableRowProps<TData>): import("react").JSX.Element;
355
+ declare function Row$1<TFeatures extends TableFeatures, TData extends RowData>({ className, onClick, renderExpanded, row, ...props }: DataTableRowProps<TFeatures, TData>): import("react").JSX.Element;
301
356
  type DataTableEmptyRowProps = ComponentProps<typeof Table$1.Row>;
302
357
  /**
303
358
  * An empty-state row that spans every column. Render this as the `else` branch
@@ -319,9 +374,9 @@ type DataTableEmptyRowProps = ComponentProps<typeof Table$1.Row>;
319
374
  * import { MagnifyingGlassIcon } from "@phosphor-icons/react/MagnifyingGlass";
320
375
  * import { TrayIcon } from "@phosphor-icons/react/Tray";
321
376
  *
322
- * // `table` is your useReactTable instance; derive everything else from it.
377
+ * // `table` is your useTable instance; derive everything else from it.
323
378
  * const rows = table.getRowModel().rows;
324
- * const isFiltered = (table.getState().globalFilter ?? "") !== "";
379
+ * const isFiltered = (table.state.globalFilter ?? "") !== "";
325
380
  *
326
381
  * // EmptyRow already spans every column and Empty.Root centers itself — drop a
327
382
  * // single Empty.Root in as the child; don't hand-roll a <td> or any centering.
@@ -356,7 +411,7 @@ type DataTableEmptyRowProps = ComponentProps<typeof Table$1.Row>;
356
411
  * </DataTable.Body>
357
412
  * ```
358
413
  */
359
- declare function EmptyRow<TData>({ children, ...props }: DataTableEmptyRowProps): import("react").JSX.Element;
414
+ declare function EmptyRow({ children, ...props }: DataTableEmptyRowProps): import("react").JSX.Element;
360
415
  type DataTableActionCellProps = ComponentProps<typeof Table$1.Cell>;
361
416
  /**
362
417
  * A sticky-right `<td>` for per-row action buttons (typically an `IconButton`
@@ -424,7 +479,7 @@ declare function ActionHeader({ children, className, ...props }: DataTableAction
424
479
  * // ...renders id={expandedRowId(row)} — the same value, so they stay associated.
425
480
  * ```
426
481
  */
427
- declare function expandedRowId<TData>(row: Row<TData>): string;
482
+ declare function expandedRowId<TFeatures extends TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>): string;
428
483
  type DataTableExpandHeaderProps = Omit<ComponentProps<typeof Table$1.Header>, "children"> & {
429
484
  /**
430
485
  * Optional header content — e.g. an "expand all" toggle wired to
@@ -455,7 +510,7 @@ type DataTableExpandHeaderProps = Omit<ComponentProps<typeof Table$1.Header>, "c
455
510
  * ```
456
511
  */
457
512
  declare function ExpandHeader({ children, className, ...props }: DataTableExpandHeaderProps): import("react").JSX.Element;
458
- type DataTableRowExpandButtonProps<TData> = Omit<ComponentProps<typeof IconButton>, "appearance" | "aria-controls" | "aria-expanded" | "icon" | "intent" | "label"> & {
513
+ type DataTableRowExpandButtonProps<TFeatures extends ExpandableTableFeatures, TData extends RowData> = Omit<ComponentProps<typeof IconButton>, "appearance" | "aria-controls" | "aria-expanded" | "icon" | "intent" | "label"> & {
459
514
  /**
460
515
  * The visual style of the expand toggle. Optional — the row expand button's
461
516
  * design is a ghost button, so the wrapper defaults it.
@@ -470,11 +525,11 @@ type DataTableRowExpandButtonProps<TData> = Omit<ComponentProps<typeof IconButto
470
525
  */
471
526
  intent?: IconButtonIntent;
472
527
  /**
473
- * The TanStack Table row this button toggles. The table must be configured for
474
- * expansion (`getExpandedRowModel`, plus `getRowCanExpand: () => true` for
475
- * custom detail panels, which have no sub-rows).
528
+ * The TanStack Table row this button toggles. The table must register
529
+ * `rowExpandingFeature`, plus `getRowCanExpand: () => true` for custom detail
530
+ * panels, which have no sub-rows.
476
531
  */
477
- row: Row<TData>;
532
+ row: ExpandableRow<TFeatures, TData>;
478
533
  /**
479
534
  * A human-readable name for the row, woven into the accessible label:
480
535
  * `Show details for {label}` / `Hide details for {label}`.
@@ -504,10 +559,20 @@ type DataTableRowExpandButtonProps<TData> = Omit<ComponentProps<typeof IconButto
504
559
  * pass `onClick` to run side effects before the toggle (call
505
560
  * `event.preventDefault()` to veto it).
506
561
  *
562
+ * The table must register `rowExpandingFeature`; the `row` prop's type rejects a row
563
+ * from a table without it. Add `expandedRowModel: createExpandedRowModel()` when rows
564
+ * have sub-rows; a detail panel expands without it.
565
+ *
507
566
  * @see https://mantle.ngrok.com/components/data-display/data-table#datatablerowexpandbutton
508
567
  *
509
568
  * @example
510
569
  * ```tsx
570
+ * const features = tableFeatures({
571
+ * rowExpandingFeature,
572
+ * expandedRowModel: createExpandedRowModel(),
573
+ * });
574
+ * const columnHelper = createColumnHelper<typeof features, Row>();
575
+ *
511
576
  * columnHelper.display({
512
577
  * id: "expander",
513
578
  * header: () => <DataTable.ExpandHeader />,
@@ -519,10 +584,10 @@ type DataTableRowExpandButtonProps<TData> = Omit<ComponentProps<typeof IconButto
519
584
  * });
520
585
  * ```
521
586
  */
522
- declare function RowExpandButton<TData>({ appearance, className, collapseIcon, expandIcon, intent, label, onClick, row, size, ...props }: DataTableRowExpandButtonProps<TData>): import("react").JSX.Element | null;
523
- type DataTableExpandedRowProps<TData> = Omit<ComponentProps<typeof Table$1.Row>, "children"> & {
587
+ declare function RowExpandButton<TFeatures extends ExpandableTableFeatures, TData extends RowData>({ appearance, className, collapseIcon, expandIcon, intent, label, onClick, row, size, ...props }: DataTableRowExpandButtonProps<TFeatures, TData>): import("react").JSX.Element | null;
588
+ type DataTableExpandedRowProps<TFeatures extends TableFeatures, TData extends RowData> = Omit<ComponentProps<typeof Table$1.Row>, "children"> & {
524
589
  /** The row whose detail panel this displays. */
525
- row: Row<TData>;
590
+ row: Row<TFeatures, TData>;
526
591
  /**
527
592
  * Override the cell's `colSpan`. Defaults to the row's visible-cell count so
528
593
  * the panel spans every visible column (visibility- and pinning-aware).
@@ -576,16 +641,16 @@ type DataTableExpandedRowProps<TData> = Omit<ComponentProps<typeof Table$1.Row>,
576
641
  * ))}
577
642
  * ```
578
643
  */
579
- declare function ExpandedRow<TData>({ children, className, colSpan, row, ...props }: DataTableExpandedRowProps<TData>): import("react").JSX.Element;
644
+ declare function ExpandedRow<TFeatures extends TableFeatures, TData extends RowData>({ children, className, colSpan, row, ...props }: DataTableExpandedRowProps<TFeatures, TData>): import("react").JSX.Element;
580
645
  /**
581
646
  * Use `DataTable` for INTERACTIVE tabular data — sorting, filtering, pagination,
582
647
  * row selection, and server-side or client-side data. Built on TanStack Table;
583
- * the consumer MUST construct a `useReactTable` instance from
648
+ * the consumer MUST construct a `useTable` instance from
584
649
  * `@tanstack/react-table` and pass it to `DataTable.Root` via the `table` prop.
585
- * Every TanStack utility (`createColumnHelper`, `getCoreRowModel`,
586
- * `getSortedRowModel`, `getPaginationRowModel`, `getFilteredRowModel`,
587
- * `useReactTable`, …) is re-exported from `@ngrok/mantle/data-table` so a single
588
- * import covers both the wrapper components and the TanStack helpers.
650
+ * Every TanStack export (`useTable`, `tableFeatures`, `createColumnHelper`, the
651
+ * `*Feature` objects, the `create*RowModel` factories, the `sortFn_*` and `filterFn_*` comparators,
652
+ * …) is re-exported from `@ngrok/mantle/data-table` so a single import covers
653
+ * both the wrapper components and the TanStack helpers.
589
654
  *
590
655
  * For STATIC, layout-driven tables (read-only data dumps, simple key/value
591
656
  * displays, plain markup tables with no interactivity), use `Table` instead.
@@ -617,14 +682,31 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
617
682
  * import {
618
683
  * DataTable,
619
684
  * createColumnHelper,
620
- * getCoreRowModel,
621
- * useReactTable,
685
+ * createSortedRowModel,
686
+ * rowSortingFeature,
687
+ * sortFn_alphanumeric,
688
+ * sortFn_datetime,
689
+ * sortFn_text,
690
+ * tableFeatures,
691
+ * useTable,
622
692
  * } from "@ngrok/mantle/data-table";
623
693
  *
624
694
  * type Row = { id: string; name: string };
625
695
  *
626
- * const columnHelper = createColumnHelper<Row>();
627
- * const columns = [
696
+ * // Register only the features the table uses. Auto-sort resolves the
697
+ * // `alphanumeric`, `text`, and `datetime` comparators by name, so register those three.
698
+ * const features = tableFeatures({
699
+ * rowSortingFeature,
700
+ * sortedRowModel: createSortedRowModel(),
701
+ * sortFns: {
702
+ * alphanumeric: sortFn_alphanumeric,
703
+ * datetime: sortFn_datetime,
704
+ * text: sortFn_text,
705
+ * },
706
+ * });
707
+ *
708
+ * const columnHelper = createColumnHelper<typeof features, Row>();
709
+ * const columns = columnHelper.columns([
628
710
  * columnHelper.accessor("name", {
629
711
  * id: "name",
630
712
  * header: (props) => (
@@ -636,10 +718,10 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
636
718
  * ),
637
719
  * cell: (props) => <DataTable.Cell>{props.getValue()}</DataTable.Cell>,
638
720
  * }),
639
- * ];
721
+ * ]);
640
722
  *
641
723
  * function MyTable({ data }: { data: Row[] }) {
642
- * const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });
724
+ * const table = useTable({ features, data, columns });
643
725
  * const rows = table.getRowModel().rows;
644
726
  *
645
727
  * return (
@@ -663,12 +745,19 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
663
745
  * ```tsx
664
746
  * import {
665
747
  * DataTable,
748
+ * columnFilteringFeature,
666
749
  * createColumnHelper,
667
- * getCoreRowModel,
668
- * getFilteredRowModel,
669
- * getPaginationRowModel,
670
- * getSortedRowModel,
671
- * useReactTable,
750
+ * createFilteredRowModel,
751
+ * createPaginatedRowModel,
752
+ * createSortedRowModel,
753
+ * globalFilteringFeature,
754
+ * rowPaginationFeature,
755
+ * rowSortingFeature,
756
+ * sortFn_alphanumeric,
757
+ * sortFn_datetime,
758
+ * sortFn_text,
759
+ * tableFeatures,
760
+ * useTable,
672
761
  * } from "@ngrok/mantle/data-table";
673
762
  * import { Button } from "@ngrok/mantle/button";
674
763
  * import { CursorPagination } from "@ngrok/mantle/pagination";
@@ -684,8 +773,24 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
684
773
  * // (default 5 | 10 | 20 | 50 | 100).
685
774
  * const DEFAULT_PAGE_SIZE = 10;
686
775
  *
687
- * const columnHelper = createColumnHelper<Payment>();
688
- * const columns = [
776
+ * // `globalFilteringFeature` builds on `columnFilteringFeature`, so register both.
777
+ * const features = tableFeatures({
778
+ * columnFilteringFeature,
779
+ * globalFilteringFeature,
780
+ * rowPaginationFeature,
781
+ * rowSortingFeature,
782
+ * filteredRowModel: createFilteredRowModel(),
783
+ * paginatedRowModel: createPaginatedRowModel(),
784
+ * sortedRowModel: createSortedRowModel(),
785
+ * sortFns: {
786
+ * alphanumeric: sortFn_alphanumeric,
787
+ * datetime: sortFn_datetime,
788
+ * text: sortFn_text,
789
+ * },
790
+ * });
791
+ *
792
+ * const columnHelper = createColumnHelper<typeof features, Payment>();
793
+ * const columns = columnHelper.columns([
689
794
  * columnHelper.accessor("status", {
690
795
  * id: "status",
691
796
  * header: (props) => (
@@ -728,21 +833,18 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
728
833
  * </DataTable.Cell>
729
834
  * ),
730
835
  * }),
731
- * ];
836
+ * ]);
732
837
  *
733
838
  * function PaymentsTable({ data }: { data: Payment[] }) {
734
839
  * const [globalFilter, setGlobalFilter] = useState("");
735
840
  *
736
- * const table = useReactTable({
841
+ * const table = useTable({
842
+ * features,
737
843
  * data,
738
844
  * columns,
739
845
  * state: { globalFilter },
740
846
  * onGlobalFilterChange: setGlobalFilter,
741
- * getCoreRowModel: getCoreRowModel(),
742
- * getSortedRowModel: getSortedRowModel(),
743
- * getFilteredRowModel: getFilteredRowModel(),
744
- * getPaginationRowModel: getPaginationRowModel(),
745
- * initialState: { pagination: { pageSize: DEFAULT_PAGE_SIZE } },
847
+ * initialState: { pagination: { pageIndex: 0, pageSize: DEFAULT_PAGE_SIZE } },
746
848
  * });
747
849
  * const rows = table.getRowModel().rows;
748
850
  * const isFiltered = globalFilter.trim() !== "";
@@ -796,7 +898,7 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
796
898
  * </DataTable.Root>
797
899
  * <CursorPagination.Root
798
900
  * className="flex justify-end"
799
- * pageSize={table.getState().pagination.pageSize}
901
+ * pageSize={table.state.pagination.pageSize}
800
902
  * onChangePageSize={(size) => {
801
903
  * table.setPageSize(size);
802
904
  * table.setPageIndex(0); // reset to the first page when the size changes
@@ -825,9 +927,9 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
825
927
  * import { IconButton } from "@ngrok/mantle/button";
826
928
  * import { DotsThreeVerticalIcon } from "@phosphor-icons/react/DotsThreeVertical";
827
929
  *
828
- * const columnHelper = createColumnHelper<Payment>();
930
+ * const columnHelper = createColumnHelper<typeof features, Payment>();
829
931
  *
830
- * const columns = [
932
+ * const columns = columnHelper.columns([
831
933
  * // …other columns…
832
934
  * columnHelper.display({
833
935
  * id: "actions",
@@ -850,7 +952,7 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
850
952
  * </DataTable.ActionCell>
851
953
  * ),
852
954
  * }),
853
- * ];
955
+ * ]);
854
956
  * ```
855
957
  *
856
958
  * @example
@@ -858,13 +960,13 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
858
960
  * primary cell also renders a `<Link>` as the keyboard and screen-reader path.
859
961
  * `SandboxedOnClick` keeps the link's click from also running the row handler:
860
962
  * ```tsx
861
- * import { DataTable } from "@ngrok/mantle/data-table";
963
+ * import { DataTable, useTable } from "@ngrok/mantle/data-table";
862
964
  * import { SandboxedOnClick } from "@ngrok/mantle/sandboxed-on-click";
863
965
  * import { Link, href, useNavigate } from "react-router";
864
966
  *
865
967
  * function PaymentsTable({ data }: { data: Payment[] }) {
866
968
  * const navigate = useNavigate();
867
- * const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });
969
+ * const table = useTable({ features, data, columns });
868
970
  * const rows = table.getRowModel().rows;
869
971
  *
870
972
  * return (
@@ -902,7 +1004,7 @@ declare function ExpandedRow<TData>({ children, className, colSpan, row, ...prop
902
1004
  declare const DataTable: {
903
1005
  /**
904
1006
  * The root container of the data table component. REQUIRED: pass a
905
- * `useReactTable` instance (from `@tanstack/react-table`, also re-exported
1007
+ * `useTable` instance (from `@tanstack/react-table`, also re-exported
906
1008
  * from `@ngrok/mantle/data-table`) via the `table` prop — every other
907
1009
  * `DataTable.*` part reads from it through context.
908
1010
  *
@@ -910,7 +1012,7 @@ declare const DataTable: {
910
1012
  *
911
1013
  * @example
912
1014
  * ```tsx
913
- * const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });
1015
+ * const table = useTable({ features, data, columns });
914
1016
  * const rows = table.getRowModel().rows;
915
1017
  *
916
1018
  * <DataTable.Root table={table}>
@@ -1083,16 +1185,37 @@ declare const DataTable: {
1083
1185
  * - For `"alphanumeric"` sorting: `unsorted → ascending → descending → unsorted`
1084
1186
  * - For `"time"` sorting: `unsorted → newest-first → oldest-first → unsorted`
1085
1187
  *
1188
+ * The table must register `rowSortingFeature`; the `column` prop's type rejects a
1189
+ * column from a table without it. Pair it with `sortedRowModel: createSortedRowModel()`,
1190
+ * or the button toggles the icon and never reorders a row. Register a `sortFns` slot
1191
+ * too: without one, auto-sort falls back to `sortFn_basic`.
1192
+ *
1086
1193
  * When the column cannot sort (`disableSorting`, or `enableSorting: false` on
1087
1194
  * the column), the part renders the label as plain text: no button, no icon.
1088
1195
  *
1089
1196
  * For right-aligned numeric columns, pass `className="justify-end"` and
1090
1197
  * `iconPlacement="start"` so the sort icon stays paired with the label.
1091
1198
  *
1199
+ * | Data Attribute | Value | Description |
1200
+ * | -------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
1201
+ * | `data-sort-direction` | `"asc"`, `"desc"`, or `"unsorted"` | The column's current sort direction. Always `"unsorted"` on the plain-text span. |
1202
+ * | `data-table-header-action` | present on the button | Presence-only. `DataTable.Header` drops its horizontal padding when a descendant carries it. Absent on the plain-text span. |
1203
+ *
1092
1204
  * @see https://mantle.ngrok.com/components/data-display/data-table#datatableheadersortbutton
1093
1205
  *
1094
1206
  * @example
1095
1207
  * ```tsx
1208
+ * const features = tableFeatures({
1209
+ * rowSortingFeature,
1210
+ * sortedRowModel: createSortedRowModel(),
1211
+ * sortFns: {
1212
+ * alphanumeric: sortFn_alphanumeric,
1213
+ * datetime: sortFn_datetime,
1214
+ * text: sortFn_text,
1215
+ * },
1216
+ * });
1217
+ * const columnHelper = createColumnHelper<typeof features, Row>();
1218
+ *
1096
1219
  * columnHelper.accessor("email", {
1097
1220
  * id: "email",
1098
1221
  * header: (props) => (
@@ -1172,7 +1295,8 @@ declare const DataTable: {
1172
1295
  * column and pair it with `DataTable.ExpandedRow`. Sets `aria-expanded` and
1173
1296
  * (while expanded) `aria-controls`, stops click propagation so it never fires
1174
1297
  * a row-level `onClick`, and renders nothing when `row.getCanExpand()` is
1175
- * false.
1298
+ * false. The table must register `rowExpandingFeature`; the `row` prop's
1299
+ * type rejects a row from a table without it.
1176
1300
  *
1177
1301
  * @see https://mantle.ngrok.com/components/data-display/data-table#datatablerowexpandbutton
1178
1302
  *
@@ -1 +1 @@
1
- import{t as e}from"./cx-0HCjnNv1.js";import{t}from"./button-DGsTE3P2.js";import{t as n}from"./button-CaM-ZAH5.js";import{t as r}from"./icons-B_DDQcVD.js";import{n as i}from"./sandboxed-on-click-UagMFl_U.js";import{t as a}from"./table-EZNW3nFk.js";import{Fragment as o,createContext as s,useContext as c,useMemo as l}from"react";import u from"tiny-invariant";import{Fragment as d,jsx as f,jsxs as p}from"react/jsx-runtime";import{flexRender as m}from"@tanstack/react-table";import{MinusIcon as h}from"@phosphor-icons/react/Minus";import{PlusIcon as g}from"@phosphor-icons/react/Plus";export*from"@tanstack/react-table";const _=[`unsorted`,`asc`,`desc`],v=[`unsorted`,`desc`,`asc`];function y(e,t){return b(t===`alphanumeric`?_:v,e)??`unsorted`}function b(e,t,n){if(e.length===0)return n;let r=e.findIndex(e=>e===t);if(r===-1)return n;let i=(r+1)%e.length;return e.at(i)??n}const x=s(null);function S(){let e=c(x);return u(e,`useDataTableContext should only be used within a DataTable child component`),e}function C({children:e,table:t,...n}){let r=l(()=>({table:t}),[t]);return f(x.Provider,{value:r,children:f(a.Root,{"data-slot":`data-table`,...n,children:f(a.Element,{children:e})})})}function w({appearance:n=`ghost`,children:r,className:i,column:a,disableSorting:o=!1,iconPlacement:s=`end`,intent:c=`neutral`,sortingMode:l,sortIcon:u,onClick:d,...p}){let m=a.getIsSorted(),h=!o&&a.getCanSort(),g=h&&typeof m==`string`?m:`unsorted`;if(!h)return f(`span`,{"data-slot":`data-table-header-sort-button`,"data-sort-direction":`unsorted`,className:e(`flex w-full items-center justify-start`,n===`ghost`&&c===`neutral`&&`text-muted`,i),...p,children:r});let _=u?.(g)??f(H,{mode:l,direction:g});return f(t,{appearance:n,"data-slot":`data-table-header-sort-button`,className:e(`flex justify-start w-full h-full rounded-none not-disabled:active:scale-none`,n===`ghost`&&c===`neutral`&&`text-muted`,i),"data-sort-direction":g,"data-table-header-action":!0,icon:_,iconPlacement:s,onClick:e=>{d?.(e),!e.defaultPrevented&&l!==void 0&&U(a,l)},intent:c,type:`button`,...p,children:r})}function T(e){let t=e?.getIsSorted();if(t===`asc`)return`ascending`;if(t===`desc`)return`descending`}function E({children:t,className:n,column:r,...i}){return f(a.Header,{"aria-sort":T(r),"data-slot":`data-table-header`,className:e(`has-data-table-header-action:px-0`,n),...i,children:t})}const D=e=>f(a.Body,{"data-slot":`data-table-body`,...e});function O(e){let{table:t}=S();return f(a.Head,{"data-slot":`data-table-head`,...e,children:t.getHeaderGroups().map(e=>f(a.Row,{children:e.headers.map(e=>f(o,{children:e.isPlaceholder?f(a.Header,{},e.id):m(e.column.columnDef.header,e.getContext())},e.id))},e.id))})}function k(e){if(e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return!1;let t=e.currentTarget.ownerDocument.getSelection();return t==null||t.isCollapsed?!0:!e.currentTarget.contains(t.anchorNode)}function A({className:t,onClick:n,renderExpanded:r,row:i,...s}){let c=f(a.Row,{"data-slot":`data-table-row`,"data-expanded":i.getIsExpanded()||void 0,"data-clickable":n==null?void 0:``,className:e(n!=null&&`cursor-pointer`,t),onClick:n&&(e=>{k(e)&&n(e)}),...s,children:i.getVisibleCells().map(e=>f(o,{children:m(e.column.columnDef.cell,e.getContext())},e.id))});return r==null?c:p(d,{children:[c,i.getIsExpanded()&&f(B,{row:i,children:r(i)})]})}function j({children:e,...t}){let{table:n}=S(),r=n.getVisibleLeafColumns().length;return f(a.Row,{"data-slot":`data-table-empty-row`,...t,children:f(a.Cell,{colSpan:r,children:e})})}function M(){return f(`span`,{"aria-hidden":!0,className:e(`pointer-events-none absolute -inset-y-px -left-1.5 w-1.5`,`opacity-0 transition-opacity group-data-sticky-active/table:opacity-100`,`shadow-[1px_0_0_0_var(--border-color-card-muted)]`,`bg-linear-to-l to-transparent`,`from-[color-mix(in_oklab,var(--shadow-color)_var(--shadow-second-opacity),transparent)]`)})}function N({children:t,className:n,onClick:r,...o}){let{onClick:s}=i({allowClickEventDefault:!0,onClick:r});return p(a.Cell,{"data-mantle-table-sticky-right":!0,"data-slot":`data-table-action-cell`,className:e(`sticky z-10 right-0 text-end align-middle bg-inherit p-2`,n),onClick:s,...o,children:[f(M,{}),t]})}function P({children:t,className:n,...r}){let{table:i}=S(),o=i.getRowModel().rows.length>0;return p(a.Header,{...o?{"data-mantle-table-sticky-right":!0}:{},"data-slot":`data-table-action-header`,className:e(o&&`sticky z-10 right-0 bg-inherit`,n),...r,children:[t??f(`span`,{className:`sr-only`,children:`Actions`}),o&&f(M,{})]})}function F(e){return`data-table-expanded-row-${encodeURIComponent(e.id)}`}function I({children:t,className:n,...r}){return f(a.Header,{"data-slot":`data-table-expand-header`,className:e(`w-9 px-0 text-center`,n),...r,children:t??f(`span`,{className:`sr-only`,children:`Row details`})})}const L=f(g,{weight:`bold`,className:`size-3.5`}),R=f(h,{weight:`bold`,className:`size-3.5`});function z({appearance:t=`ghost`,className:r,collapseIcon:i=R,expandIcon:a=L,intent:o=`neutral`,label:s,onClick:c,row:l,size:u=`sm`,...d}){if(!l.getCanExpand())return null;let p=l.getIsExpanded(),m=l.getToggleExpandedHandler();return f(n,{type:`button`,"data-slot":`data-table-row-expand-button`,appearance:t,intent:o,size:u,className:e(`rounded`,r),"aria-expanded":p,"aria-controls":p?F(l):void 0,icon:p?i:a,label:`${p?`Hide`:`Show`} details for ${s}`,onClick:e=>{e.stopPropagation(),c?.(e),!e.defaultPrevented&&m()},...d})}function B({children:t,className:n,colSpan:r,row:i,...o}){return f(a.Row,{"data-slot":`data-table-expanded-row`,"data-expanded-content":!0,className:e(`[&>td]:border-t-0`,n),...o,children:f(a.Cell,{id:F(i),colSpan:r??i.getVisibleCells().length,className:`bg-card font-sans text-body`,children:t})})}const V={Root:C,ActionCell:N,ActionHeader:P,Cell:a.Cell,Body:D,EmptyRow:j,Head:O,Header:E,HeaderSortButton:w,Row:A,ExpandHeader:I,RowExpandButton:z,ExpandedRow:B};function H({direction:e,mode:t,...n}){return e===`unsorted`||!t||!e?f(`svg`,{"aria-hidden":!0,...n}):f(r,{mode:t,direction:e,...n})}function U(e,t){if(!e.getCanSort())return;let n=e.getIsSorted();switch(y(typeof n==`string`?n:`unsorted`,t)){case`unsorted`:e.clearSorting();return;case`asc`:e.toggleSorting(!1);return;case`desc`:e.toggleSorting(!0);return;default:return}}export{V as DataTable,F as expandedRowId};
1
+ import{t as e}from"./cx-0HCjnNv1.js";import{t}from"./button-DGsTE3P2.js";import{t as n}from"./button-CaM-ZAH5.js";import{t as r}from"./icons-B_DDQcVD.js";import{n as i}from"./sandboxed-on-click-UagMFl_U.js";import{t as a}from"./table-0jpWGqu6.js";import{Fragment as o,createContext as s,useContext as c,useMemo as l}from"react";import u from"tiny-invariant";import{Fragment as d,jsx as f,jsxs as p}from"react/jsx-runtime";import{callMemoOrStaticFn as m,flexRender as h}from"@tanstack/react-table";import{MinusIcon as g}from"@phosphor-icons/react/Minus";import{PlusIcon as _}from"@phosphor-icons/react/Plus";import{column_getIsSorted as v,row_getIsExpanded as y,row_getVisibleCells as b,table_getVisibleLeafColumns as x}from"@tanstack/react-table/static-functions";export*from"@tanstack/react-table";const S=[`unsorted`,`asc`,`desc`],C=[`unsorted`,`desc`,`asc`];function w(e,t){return T(t===`alphanumeric`?S:C,e)??`unsorted`}function T(e,t,n){if(e.length===0)return n;let r=e.findIndex(e=>e===t);if(r===-1)return n;let i=(r+1)%e.length;return e.at(i)??n}const E=s(null);function D(){let e=c(E);return u(e,`useDataTableContext should only be used within a DataTable child component`),e}function O({children:e,table:t,...n}){let r=l(()=>({table:t}),[t]);return f(E.Provider,{value:r,children:f(a.Root,{"data-slot":`data-table`,...n,children:f(a.Element,{children:e})})})}function k({appearance:n=`ghost`,children:r,className:i,column:a,disableSorting:o=!1,iconPlacement:s=`end`,intent:c=`neutral`,sortingMode:l,sortIcon:u,onClick:d,...p}){let m=a.getIsSorted(),h=!o&&a.getCanSort(),g=h&&typeof m==`string`?m:`unsorted`;if(!h)return f(`span`,{"data-slot":`data-table-header-sort-button`,"data-sort-direction":`unsorted`,className:e(`flex w-full items-center justify-start`,n===`ghost`&&c===`neutral`&&`text-muted`,i),...p,children:r});let _=u?.(g)??f(q,{mode:l,direction:g});return f(t,{appearance:n,"data-slot":`data-table-header-sort-button`,className:e(`flex justify-start w-full h-full rounded-none not-disabled:active:scale-none`,n===`ghost`&&c===`neutral`&&`text-muted`,i),"data-sort-direction":g,"data-table-header-action":!0,icon:_,iconPlacement:s,onClick:e=>{d?.(e),!e.defaultPrevented&&l!==void 0&&J(a,l)},intent:c,type:`button`,...p,children:r})}function A(e){if(e==null)return;let t=m(e,`getIsSorted`,v);if(t===`asc`)return`ascending`;if(t===`desc`)return`descending`}function j({children:t,className:n,column:r,...i}){return f(a.Header,{"aria-sort":A(r),"data-slot":`data-table-header`,className:e(`has-data-table-header-action:px-0`,n),...i,children:t})}const M=e=>f(a.Body,{"data-slot":`data-table-body`,...e});function N(e){let{table:t}=D();return f(a.Head,{"data-slot":`data-table-head`,...e,children:t.getHeaderGroups().map(e=>f(a.Row,{children:e.headers.map(e=>f(o,{children:e.isPlaceholder?f(a.Header,{}):h(e.column.columnDef.header,e.getContext())},e.id))},e.id))})}function P(e){if(e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return!1;let t=e.currentTarget.ownerDocument.getSelection();return t==null||t.isCollapsed?!0:!e.currentTarget.contains(t.anchorNode)}function F({className:t,onClick:n,renderExpanded:r,row:i,...s}){let c=m(i,`getIsExpanded`,y),l=m(i,`getVisibleCells`,b),u=f(a.Row,{"data-slot":`data-table-row`,"data-expanded":c||void 0,"data-clickable":n==null?void 0:``,className:e(n!=null&&`cursor-pointer`,t),onClick:n&&(e=>{P(e)&&n(e)}),...s,children:l.map(e=>f(o,{children:h(e.column.columnDef.cell,e.getContext())},e.id))});return r==null?u:p(d,{children:[u,c&&f(G,{row:i,children:r(i)})]})}function I({children:e,...t}){let{table:n}=D(),r=m(n,`getVisibleLeafColumns`,x).length;return f(a.Row,{"data-slot":`data-table-empty-row`,...t,children:f(a.Cell,{colSpan:r,children:e})})}function L(){return f(`span`,{"aria-hidden":!0,className:e(`pointer-events-none absolute -inset-y-px -left-1.5 w-1.5`,`opacity-0 transition-opacity group-data-sticky-active/table:opacity-100`,`shadow-[1px_0_0_0_var(--border-color-card-muted)]`,`bg-linear-to-l to-transparent`,`from-[color-mix(in_oklab,var(--shadow-color)_var(--shadow-second-opacity),transparent)]`)})}function R({children:t,className:n,onClick:r,...o}){let{onClick:s}=i({allowClickEventDefault:!0,onClick:r});return p(a.Cell,{"data-mantle-table-sticky-right":!0,"data-slot":`data-table-action-cell`,className:e(`sticky z-10 right-0 text-end align-middle bg-inherit p-2`,n),onClick:s,...o,children:[f(L,{}),t]})}function z({children:t,className:n,...r}){let{table:i}=D(),o=i.getRowModel().rows.length>0;return p(a.Header,{...o?{"data-mantle-table-sticky-right":!0}:{},"data-slot":`data-table-action-header`,className:e(o&&`sticky z-10 right-0 bg-inherit`,n),...r,children:[t??f(`span`,{className:`sr-only`,children:`Actions`}),o&&f(L,{})]})}function B(e){return`data-table-expanded-row-${encodeURIComponent(e.id)}`}function V({children:t,className:n,...r}){return f(a.Header,{"data-slot":`data-table-expand-header`,className:e(`w-9 px-0 text-center`,n),...r,children:t??f(`span`,{className:`sr-only`,children:`Row details`})})}const H=f(_,{weight:`bold`,className:`size-3.5`}),U=f(g,{weight:`bold`,className:`size-3.5`});function W({appearance:t=`ghost`,className:r,collapseIcon:i=U,expandIcon:a=H,intent:o=`neutral`,label:s,onClick:c,row:l,size:u=`sm`,...d}){if(!l.getCanExpand())return null;let p=l.getIsExpanded(),m=l.getToggleExpandedHandler();return f(n,{type:`button`,"data-slot":`data-table-row-expand-button`,appearance:t,intent:o,size:u,className:e(`rounded`,r),"aria-expanded":p,"aria-controls":p?B(l):void 0,icon:p?i:a,label:`${p?`Hide`:`Show`} details for ${s}`,onClick:e=>{e.stopPropagation(),c?.(e),!e.defaultPrevented&&m()},...d})}function G({children:t,className:n,colSpan:r,row:i,...o}){let s=r??m(i,`getVisibleCells`,b).length;return f(a.Row,{"data-slot":`data-table-expanded-row`,"data-expanded-content":!0,className:e(`[&>td]:border-t-0`,n),...o,children:f(a.Cell,{id:B(i),colSpan:s,className:`bg-card font-sans text-body`,children:t})})}const K={Root:O,ActionCell:R,ActionHeader:z,Cell:a.Cell,Body:M,EmptyRow:I,Head:N,Header:j,HeaderSortButton:k,Row:F,ExpandHeader:V,RowExpandButton:W,ExpandedRow:G};function q({direction:e,mode:t,...n}){return e===`unsorted`||!t||!e?f(`svg`,{"aria-hidden":!0,...n}):f(r,{mode:t,direction:e,...n})}function J(e,t){if(!e.getCanSort())return;let n=e.getIsSorted();switch(w(typeof n==`string`?n:`unsorted`,t)){case`unsorted`:e.clearSorting();return;case`asc`:e.toggleSorting(!1);return;case`desc`:e.toggleSorting(!0);return;default:return}}export{K as DataTable,B as expandedRowId};
package/dist/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # @ngrok/mantle (0.84.3)
1
+ # @ngrok/mantle (0.85.0)
2
2
 
3
3
  > Offline discovery hint shipped inside the @ngrok/mantle npm package. Authoritative metadata lives at https://mantle.ngrok.com/for-ai-agents.
4
4
 
@@ -0,0 +1 @@
1
+ import{n as e}from"./compose-refs-DdUwopIY.js";import{t}from"./cx-0HCjnNv1.js";import{useLayoutEffect as n,useMemo as r,useRef as i,useState as a}from"react";import{jsx as o}from"react/jsx-runtime";import{flushSync as s}from"react-dom";const c={Body:({children:e,className:n,ref:r,...i})=>o(`tbody`,{"data-slot":`table-body`,className:t(`[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted`,`text-body`,`[&>tr]:bg-card [&>tr]:not-only:hover:bg-card-hover [&>tr]:not-only:has-focus-visible:bg-card-hover`,n),ref:r,...i,children:e}),Caption:({children:e,className:n,ref:r,...i})=>o(`caption`,{"data-slot":`table-caption`,ref:r,className:t(`py-4 text-sm text-gray-500`,`border-t border-card-muted`,n),...i,children:e}),Cell:({children:e,className:n,ref:r,...i})=>o(`td`,{"data-slot":`table-cell`,ref:r,className:t(`p-3 align-middle [&:has([role=checkbox])]:pr-0 font-mono text-mono`,n),...i,children:e}),Element:({children:e,className:n,ref:r,...i})=>o(`table`,{"data-slot":`table-element`,ref:r,className:t(`table-auto border-separate border-spacing-0 caption-bottom w-full min-w-full text-left`,n),...i,children:e}),Foot:({children:e,className:n,ref:r,...i})=>o(`tfoot`,{"data-slot":`table-foot`,ref:r,className:t(`font-medium text-body`,`[&>tr:first-child>*]:border-t [&>tr:first-child>*]:border-card-muted`,`[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted`,`[&>tr]:bg-gray-50/50 [&>tr]:hover:bg-card-hover`,n),...i,children:e}),Head:({children:e,className:n,ref:r,...i})=>o(`thead`,{"data-slot":`table-head`,ref:r,className:t(`[&>tr:last-child>*]:border-b [&>tr:last-child>*]:border-card-muted`,`[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted`,`text-muted bg-base`,`[&>tr]:bg-base`,n),...i,children:e}),Header:({children:e,className:n,ref:r,scope:i=`col`,...a})=>o(`th`,{"data-slot":`table-header`,ref:r,scope:i,className:t(`h-11 px-4 text-left align-middle text-sm font-medium [&:has([role=checkbox])]:pr-0`,n),...a,children:e}),Root:({children:n,className:r,ref:i,...a})=>{let s=l(),c=e(s.ref,i);return o(`div`,{"data-slot":`table`,className:t(`group/table relative w-full overflow-hidden rounded-lg border border-card bg-white dark:bg-gray-100`,r),"data-sticky-active":s.state.hasOverflow&&!s.state.scrolledToEnd||void 0,"data-x-overflow":s.state.hasOverflow,"data-x-scroll-end":s.state.hasOverflow&&s.state.scrolledToEnd,...a,children:o(`div`,{className:t(`scrollbar scroll-fade-x overflow-x-auto overflow-y-clip overscroll-x-none`,`has-data-mantle-table-sticky-right:[--_fade-right:black]`),ref:c,children:n})})},Row:({children:e,ref:t,...n})=>o(`tr`,{"data-slot":`table-row`,ref:t,...n,children:e})};function l(){let e=i(null),[t,o]=a({hasOverflow:!1,scrolledToStart:!0,scrolledToEnd:!1});return n(()=>{let t=e.current;if(!t)return;let n=0,r=()=>{let e=t.scrollWidth>t.clientWidth,n=t.scrollLeft<1,r=Math.abs(t.scrollWidth-t.scrollLeft-t.clientWidth)<1;o(t=>t.hasOverflow!==e||t.scrolledToStart!==n||t.scrolledToEnd!==r?{hasOverflow:e,scrolledToStart:n,scrolledToEnd:r}:t)},i=()=>{n===0&&(n=requestAnimationFrame(()=>{n=0,r()}))},a=new ResizeObserver(()=>{s(r)});a.observe(t);let c=new MutationObserver(i);return c.observe(t,{childList:!0,subtree:!0}),t.addEventListener(`scroll`,i,{passive:!0}),()=>{cancelAnimationFrame(n),a.disconnect(),c.disconnect(),t.removeEventListener(`scroll`,i)}},[]),r(()=>({ref:e,state:t}),[t])}export{c as t};
package/dist/table.js CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./table-EZNW3nFk.js";export{e as Table};
1
+ import{t as e}from"./table-0jpWGqu6.js";export{e as Table};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngrok/mantle",
3
- "version": "0.84.3",
3
+ "version": "0.85.0",
4
4
  "description": "mantle is ngrok's UI library and design system.",
5
5
  "homepage": "https://mantle.ngrok.com",
6
6
  "license": "MIT",
@@ -132,7 +132,7 @@
132
132
  "@radix-ui/react-switch": "1.3.7",
133
133
  "@radix-ui/react-tabs": "1.1.21",
134
134
  "@radix-ui/react-tooltip": "1.2.16",
135
- "@tanstack/react-table": "8.21.3",
135
+ "@tanstack/react-table": "9.2.4",
136
136
  "@tanstack/react-virtual": "3.14.11",
137
137
  "class-variance-authority": "0.7.1",
138
138
  "cmdk": "1.1.1",
@@ -1 +0,0 @@
1
- import{n as e}from"./compose-refs-DdUwopIY.js";import{t}from"./cx-0HCjnNv1.js";import{useLayoutEffect as n,useMemo as r,useRef as i,useState as a}from"react";import{jsx as o}from"react/jsx-runtime";const s={Body:({children:e,className:n,ref:r,...i})=>o(`tbody`,{"data-slot":`table-body`,className:t(`[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted`,`text-body`,`[&>tr]:bg-card [&>tr]:not-only:hover:bg-card-hover [&>tr]:not-only:has-focus-visible:bg-card-hover`,n),ref:r,...i,children:e}),Caption:({children:e,className:n,ref:r,...i})=>o(`caption`,{"data-slot":`table-caption`,ref:r,className:t(`py-4 text-sm text-gray-500`,`border-t border-card-muted`,n),...i,children:e}),Cell:({children:e,className:n,ref:r,...i})=>o(`td`,{"data-slot":`table-cell`,ref:r,className:t(`p-3 align-middle [&:has([role=checkbox])]:pr-0 font-mono text-mono`,n),...i,children:e}),Element:({children:e,className:n,ref:r,...i})=>o(`table`,{"data-slot":`table-element`,ref:r,className:t(`table-auto border-separate border-spacing-0 caption-bottom w-full min-w-full text-left`,n),...i,children:e}),Foot:({children:e,className:n,ref:r,...i})=>o(`tfoot`,{"data-slot":`table-foot`,ref:r,className:t(`font-medium text-body`,`[&>tr:first-child>*]:border-t [&>tr:first-child>*]:border-card-muted`,`[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted`,`[&>tr]:bg-gray-50/50 [&>tr]:hover:bg-card-hover`,n),...i,children:e}),Head:({children:e,className:n,ref:r,...i})=>o(`thead`,{"data-slot":`table-head`,ref:r,className:t(`[&>tr:last-child>*]:border-b [&>tr:last-child>*]:border-card-muted`,`[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted`,`text-muted bg-base`,`[&>tr]:bg-base`,n),...i,children:e}),Header:({children:e,className:n,ref:r,scope:i=`col`,...a})=>o(`th`,{"data-slot":`table-header`,ref:r,scope:i,className:t(`h-11 px-4 text-left align-middle text-sm font-medium [&:has([role=checkbox])]:pr-0`,n),...a,children:e}),Root:({children:n,className:r,ref:i,...a})=>{let s=c(),l=e(s.ref,i);return o(`div`,{"data-slot":`table`,className:t(`group/table relative w-full overflow-hidden rounded-lg border border-card bg-white dark:bg-gray-100`,r),"data-sticky-active":s.state.hasOverflow&&!s.state.scrolledToEnd||void 0,"data-x-overflow":s.state.hasOverflow,"data-x-scroll-end":s.state.hasOverflow&&s.state.scrolledToEnd,...a,children:o(`div`,{className:t(`scrollbar scroll-fade-x overflow-x-auto overflow-y-clip overscroll-x-none`,`has-data-mantle-table-sticky-right:[--_fade-right:black]`),ref:l,children:n})})},Row:({children:e,ref:t,...n})=>o(`tr`,{"data-slot":`table-row`,ref:t,...n,children:e})};function c(){let e=i(null),[t,o]=a({hasOverflow:!1,scrolledToStart:!0,scrolledToEnd:!1});return n(()=>{let t=e.current;if(!t)return;let n=0,r=()=>{let e=t.scrollWidth>t.clientWidth,n=t.scrollLeft<1,r=Math.abs(t.scrollWidth-t.scrollLeft-t.clientWidth)<1;o(t=>t.hasOverflow!==e||t.scrolledToStart!==n||t.scrolledToEnd!==r?{hasOverflow:e,scrolledToStart:n,scrolledToEnd:r}:t)},i=()=>{n===0&&(n=requestAnimationFrame(()=>{n=0,r()}))},a=new ResizeObserver(i);a.observe(t);let s=new MutationObserver(i);return s.observe(t,{childList:!0,subtree:!0}),t.addEventListener(`scroll`,i,{passive:!0}),r(),()=>{cancelAnimationFrame(n),a.disconnect(),s.disconnect(),t.removeEventListener(`scroll`,i)}},[]),r(()=>({ref:e,state:t}),[t])}export{s as t};