@tanstack/preact-table 9.0.0-alpha.22 → 9.0.0-alpha.23

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.
Files changed (42) hide show
  1. package/dist/FlexRender.cjs +50 -0
  2. package/dist/FlexRender.cjs.map +1 -0
  3. package/dist/FlexRender.d.cts +51 -0
  4. package/dist/{esm/FlexRender.d.ts → FlexRender.d.ts} +20 -15
  5. package/dist/FlexRender.js +49 -0
  6. package/dist/FlexRender.js.map +1 -0
  7. package/dist/Subscribe.cjs +36 -0
  8. package/dist/Subscribe.cjs.map +1 -0
  9. package/dist/Subscribe.d.cts +49 -0
  10. package/dist/Subscribe.d.ts +49 -0
  11. package/dist/Subscribe.js +36 -0
  12. package/dist/Subscribe.js.map +1 -0
  13. package/dist/createTableHook.cjs +334 -0
  14. package/dist/createTableHook.cjs.map +1 -0
  15. package/dist/createTableHook.d.cts +358 -0
  16. package/dist/createTableHook.d.ts +358 -0
  17. package/dist/createTableHook.js +334 -0
  18. package/dist/createTableHook.js.map +1 -0
  19. package/dist/index.cjs +18 -0
  20. package/dist/index.d.cts +6 -0
  21. package/dist/index.d.ts +6 -0
  22. package/dist/{esm/index.js → index.js} +5 -10
  23. package/dist/useTable.cjs +38 -0
  24. package/dist/useTable.cjs.map +1 -0
  25. package/dist/useTable.d.cts +60 -0
  26. package/dist/useTable.d.ts +60 -0
  27. package/dist/useTable.js +38 -0
  28. package/dist/useTable.js.map +1 -0
  29. package/package.json +11 -13
  30. package/dist/esm/FlexRender.js +0 -41
  31. package/dist/esm/FlexRender.js.map +0 -1
  32. package/dist/esm/Subscribe.d.ts +0 -44
  33. package/dist/esm/Subscribe.js +0 -9
  34. package/dist/esm/Subscribe.js.map +0 -1
  35. package/dist/esm/createTableHook.d.ts +0 -349
  36. package/dist/esm/createTableHook.js +0 -133
  37. package/dist/esm/createTableHook.js.map +0 -1
  38. package/dist/esm/index.d.ts +0 -5
  39. package/dist/esm/index.js.map +0 -1
  40. package/dist/esm/useTable.d.ts +0 -55
  41. package/dist/esm/useTable.js +0 -38
  42. package/dist/esm/useTable.js.map +0 -1
@@ -0,0 +1,358 @@
1
+ import { PreactTable } from "./useTable.js";
2
+ import { AccessorFn, AccessorFnColumnDef, AccessorKeyColumnDef, Cell, CellContext, CellData, Column, ColumnDef, DeepKeys, DeepValue, DisplayColumnDef, GroupColumnDef, Header, IdentifiedColumnDef, NoInfer, Row, RowData, Table, TableFeatures, TableOptions, TableState } from "@tanstack/table-core";
3
+ import { ComponentChildren, ComponentType } from "preact";
4
+
5
+ //#region src/createTableHook.d.ts
6
+ /**
7
+ * Enhanced CellContext with pre-bound cell components.
8
+ * The `cell` property includes the registered cellComponents.
9
+ */
10
+ type AppCellContext<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData, TCellComponents extends Record<string, ComponentType<any>>> = {
11
+ cell: Cell<TFeatures, TData, TValue> & TCellComponents & {
12
+ FlexRender: () => ComponentChildren;
13
+ };
14
+ column: Column<TFeatures, TData, TValue>;
15
+ getValue: CellContext<TFeatures, TData, TValue>['getValue'];
16
+ renderValue: CellContext<TFeatures, TData, TValue>['renderValue'];
17
+ row: Row<TFeatures, TData>;
18
+ table: Table<TFeatures, TData>;
19
+ };
20
+ /**
21
+ * Enhanced HeaderContext with pre-bound header components.
22
+ * The `header` property includes the registered headerComponents.
23
+ */
24
+ type AppHeaderContext<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData, THeaderComponents extends Record<string, ComponentType<any>>> = {
25
+ column: Column<TFeatures, TData, TValue>;
26
+ header: Header<TFeatures, TData, TValue> & THeaderComponents & {
27
+ FlexRender: () => ComponentChildren;
28
+ };
29
+ table: Table<TFeatures, TData>;
30
+ };
31
+ /**
32
+ * Template type for column definitions that can be a string or a function.
33
+ */
34
+ type AppColumnDefTemplate<TProps extends object> = string | ((props: TProps) => any);
35
+ /**
36
+ * Enhanced column definition base with pre-bound components in cell/header/footer contexts.
37
+ */
38
+ type AppColumnDefBase<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData, TCellComponents extends Record<string, ComponentType<any>>, THeaderComponents extends Record<string, ComponentType<any>>> = Omit<IdentifiedColumnDef<TFeatures, TData, TValue>, 'cell' | 'header' | 'footer'> & {
39
+ cell?: AppColumnDefTemplate<AppCellContext<TFeatures, TData, TValue, TCellComponents>>;
40
+ header?: AppColumnDefTemplate<AppHeaderContext<TFeatures, TData, TValue, THeaderComponents>>;
41
+ footer?: AppColumnDefTemplate<AppHeaderContext<TFeatures, TData, TValue, THeaderComponents>>;
42
+ };
43
+ /**
44
+ * Enhanced display column definition with pre-bound components.
45
+ */
46
+ type AppDisplayColumnDef<TFeatures extends TableFeatures, TData extends RowData, TCellComponents extends Record<string, ComponentType<any>>, THeaderComponents extends Record<string, ComponentType<any>>> = Omit<DisplayColumnDef<TFeatures, TData, unknown>, 'cell' | 'header' | 'footer'> & {
47
+ cell?: AppColumnDefTemplate<AppCellContext<TFeatures, TData, unknown, TCellComponents>>;
48
+ header?: AppColumnDefTemplate<AppHeaderContext<TFeatures, TData, unknown, THeaderComponents>>;
49
+ footer?: AppColumnDefTemplate<AppHeaderContext<TFeatures, TData, unknown, THeaderComponents>>;
50
+ };
51
+ /**
52
+ * Enhanced group column definition with pre-bound components.
53
+ */
54
+ type AppGroupColumnDef<TFeatures extends TableFeatures, TData extends RowData, TCellComponents extends Record<string, ComponentType<any>>, THeaderComponents extends Record<string, ComponentType<any>>> = Omit<GroupColumnDef<TFeatures, TData, unknown>, 'cell' | 'header' | 'footer' | 'columns'> & {
55
+ cell?: AppColumnDefTemplate<AppCellContext<TFeatures, TData, unknown, TCellComponents>>;
56
+ header?: AppColumnDefTemplate<AppHeaderContext<TFeatures, TData, unknown, THeaderComponents>>;
57
+ footer?: AppColumnDefTemplate<AppHeaderContext<TFeatures, TData, unknown, THeaderComponents>>;
58
+ columns?: Array<ColumnDef<TFeatures, TData, unknown>>;
59
+ };
60
+ /**
61
+ * Enhanced column helper with pre-bound components in cell/header/footer contexts.
62
+ * This enables TypeScript to know about the registered components when defining columns.
63
+ */
64
+ type AppColumnHelper<TFeatures extends TableFeatures, TData extends RowData, TCellComponents extends Record<string, ComponentType<any>>, THeaderComponents extends Record<string, ComponentType<any>>> = {
65
+ /**
66
+ * Creates a data column definition with an accessor key or function.
67
+ * The cell, header, and footer contexts include pre-bound components.
68
+ */
69
+ accessor: <TAccessor extends AccessorFn<TData> | DeepKeys<TData>, TValue extends (TAccessor extends AccessorFn<TData, infer TReturn> ? TReturn : TAccessor extends DeepKeys<TData> ? DeepValue<TData, TAccessor> : never)>(accessor: TAccessor, column: TAccessor extends AccessorFn<TData> ? AppColumnDefBase<TFeatures, TData, TValue, TCellComponents, THeaderComponents> & {
70
+ id: string;
71
+ } : AppColumnDefBase<TFeatures, TData, TValue, TCellComponents, THeaderComponents>) => TAccessor extends AccessorFn<TData> ? AccessorFnColumnDef<TFeatures, TData, TValue> : AccessorKeyColumnDef<TFeatures, TData, TValue>;
72
+ /**
73
+ * Wraps an array of column definitions to preserve each column's individual TValue type.
74
+ */
75
+ columns: <TColumns extends ReadonlyArray<ColumnDef<TFeatures, TData, any>>>(columns: [...TColumns]) => Array<ColumnDef<TFeatures, TData, any>> & [...TColumns];
76
+ /**
77
+ * Creates a display column definition for non-data columns.
78
+ * The cell, header, and footer contexts include pre-bound components.
79
+ */
80
+ display: (column: AppDisplayColumnDef<TFeatures, TData, TCellComponents, THeaderComponents>) => DisplayColumnDef<TFeatures, TData, unknown>;
81
+ /**
82
+ * Creates a group column definition with nested child columns.
83
+ * The cell, header, and footer contexts include pre-bound components.
84
+ */
85
+ group: (column: AppGroupColumnDef<TFeatures, TData, TCellComponents, THeaderComponents>) => GroupColumnDef<TFeatures, TData, unknown>;
86
+ };
87
+ /**
88
+ * Options for creating a table hook with pre-bound components and default table options.
89
+ * Extends all TableOptions except 'columns' | 'data' | 'store' | 'state' | 'initialState'.
90
+ */
91
+ type CreateTableHookOptions<TFeatures extends TableFeatures, TTableComponents extends Record<string, ComponentType<any>>, TCellComponents extends Record<string, ComponentType<any>>, THeaderComponents extends Record<string, ComponentType<any>>> = Omit<TableOptions<TFeatures, any>, 'columns' | 'data' | 'store' | 'state' | 'initialState'> & {
92
+ /**
93
+ * Table-level components that need access to the table instance.
94
+ * These are available directly on the table object returned by useAppTable.
95
+ * Use `useTableContext()` inside these components.
96
+ * @example { PaginationControls, GlobalFilter, RowCount }
97
+ */
98
+ tableComponents?: TTableComponents;
99
+ /**
100
+ * Cell-level components that need access to the cell instance.
101
+ * These are available on the cell object passed to AppCell's children.
102
+ * Use `useCellContext()` inside these components.
103
+ * @example { TextCell, NumberCell, DateCell, CurrencyCell }
104
+ */
105
+ cellComponents?: TCellComponents;
106
+ /**
107
+ * Header-level components that need access to the header instance.
108
+ * These are available on the header object passed to AppHeader/AppFooter's children.
109
+ * Use `useHeaderContext()` inside these components.
110
+ * @example { SortIndicator, ColumnFilter, ResizeHandle }
111
+ */
112
+ headerComponents?: THeaderComponents;
113
+ };
114
+ /**
115
+ * Props for AppTable component - without selector
116
+ */
117
+ interface AppTablePropsWithoutSelector {
118
+ children: ComponentChildren;
119
+ selector?: never;
120
+ }
121
+ /**
122
+ * Props for AppTable component - with selector
123
+ */
124
+ interface AppTablePropsWithSelector<TFeatures extends TableFeatures, TSelected> {
125
+ children: (state: TSelected) => ComponentChildren;
126
+ selector: (state: TableState<TFeatures>) => TSelected;
127
+ }
128
+ /**
129
+ * Props for AppCell component - without selector
130
+ */
131
+ interface AppCellPropsWithoutSelector<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData, TCellComponents extends Record<string, ComponentType<any>>> {
132
+ cell: Cell<TFeatures, TData, TValue>;
133
+ children: (cell: Cell<TFeatures, TData, TValue> & TCellComponents & {
134
+ FlexRender: () => ComponentChildren;
135
+ }) => ComponentChildren;
136
+ selector?: never;
137
+ }
138
+ /**
139
+ * Props for AppCell component - with selector
140
+ */
141
+ interface AppCellPropsWithSelector<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData, TCellComponents extends Record<string, ComponentType<any>>, TSelected> {
142
+ cell: Cell<TFeatures, TData, TValue>;
143
+ children: (cell: Cell<TFeatures, TData, TValue> & TCellComponents & {
144
+ FlexRender: () => ComponentChildren;
145
+ }, state: TSelected) => ComponentChildren;
146
+ selector: (state: TableState<TFeatures>) => TSelected;
147
+ }
148
+ /**
149
+ * Props for AppHeader/AppFooter component - without selector
150
+ */
151
+ interface AppHeaderPropsWithoutSelector<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData, THeaderComponents extends Record<string, ComponentType<any>>> {
152
+ header: Header<TFeatures, TData, TValue>;
153
+ children: (header: Header<TFeatures, TData, TValue> & THeaderComponents & {
154
+ FlexRender: () => ComponentChildren;
155
+ }) => ComponentChildren;
156
+ selector?: never;
157
+ }
158
+ /**
159
+ * Props for AppHeader/AppFooter component - with selector
160
+ */
161
+ interface AppHeaderPropsWithSelector<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData, THeaderComponents extends Record<string, ComponentType<any>>, TSelected> {
162
+ header: Header<TFeatures, TData, TValue>;
163
+ children: (header: Header<TFeatures, TData, TValue> & THeaderComponents & {
164
+ FlexRender: () => ComponentChildren;
165
+ }, state: TSelected) => ComponentChildren;
166
+ selector: (state: TableState<TFeatures>) => TSelected;
167
+ }
168
+ /**
169
+ * Component type for AppCell - wraps a cell and provides cell context with optional Subscribe
170
+ */
171
+ interface AppCellComponent<TFeatures extends TableFeatures, TData extends RowData, TCellComponents extends Record<string, ComponentType<any>>> {
172
+ <TValue extends CellData = CellData>(props: AppCellPropsWithoutSelector<TFeatures, TData, TValue, TCellComponents>): ComponentChildren;
173
+ <TValue extends CellData = CellData, TSelected = unknown>(props: AppCellPropsWithSelector<TFeatures, TData, TValue, TCellComponents, TSelected>): ComponentChildren;
174
+ }
175
+ /**
176
+ * Component type for AppHeader/AppFooter - wraps a header and provides header context with optional Subscribe
177
+ */
178
+ interface AppHeaderComponent<TFeatures extends TableFeatures, TData extends RowData, THeaderComponents extends Record<string, ComponentType<any>>> {
179
+ <TValue extends CellData = CellData>(props: AppHeaderPropsWithoutSelector<TFeatures, TData, TValue, THeaderComponents>): ComponentChildren;
180
+ <TValue extends CellData = CellData, TSelected = unknown>(props: AppHeaderPropsWithSelector<TFeatures, TData, TValue, THeaderComponents, TSelected>): ComponentChildren;
181
+ }
182
+ /**
183
+ * Component type for AppTable - root wrapper with optional Subscribe
184
+ */
185
+ interface AppTableComponent<TFeatures extends TableFeatures> {
186
+ (props: AppTablePropsWithoutSelector): ComponentChildren;
187
+ <TSelected>(props: AppTablePropsWithSelector<TFeatures, TSelected>): ComponentChildren;
188
+ }
189
+ /**
190
+ * Extended table API returned by useAppTable with all App wrapper components
191
+ */
192
+ type AppPreactTable<TFeatures extends TableFeatures, TData extends RowData, TSelected, TTableComponents extends Record<string, ComponentType<any>>, TCellComponents extends Record<string, ComponentType<any>>, THeaderComponents extends Record<string, ComponentType<any>>> = PreactTable<TFeatures, TData, TSelected> & NoInfer<TTableComponents> & {
193
+ /**
194
+ * Root wrapper component that provides table context with optional Subscribe.
195
+ * @example
196
+ * ```tsx
197
+ * // Without selector - children is ComponentChildren
198
+ * <table.AppTable>
199
+ * <table>...</table>
200
+ * </table.AppTable>
201
+ *
202
+ * // With selector - children receives selected state
203
+ * <table.AppTable selector={(s) => s.pagination}>
204
+ * {(pagination) => <div>Page {pagination.pageIndex}</div>}
205
+ * </table.AppTable>
206
+ * ```
207
+ */
208
+ AppTable: AppTableComponent<TFeatures>;
209
+ /**
210
+ * Wraps a cell and provides cell context with pre-bound cellComponents.
211
+ * Optionally accepts a selector for Subscribe functionality.
212
+ * @example
213
+ * ```tsx
214
+ * // Without selector
215
+ * <table.AppCell cell={cell}>
216
+ * {(c) => <td><c.TextCell /></td>}
217
+ * </table.AppCell>
218
+ *
219
+ * // With selector - children receives cell and selected state
220
+ * <table.AppCell cell={cell} selector={(s) => s.columnFilters}>
221
+ * {(c, filters) => <td>{filters.length}</td>}
222
+ * </table.AppCell>
223
+ * ```
224
+ */
225
+ AppCell: AppCellComponent<TFeatures, TData, NoInfer<TCellComponents>>;
226
+ /**
227
+ * Wraps a header and provides header context with pre-bound headerComponents.
228
+ * Optionally accepts a selector for Subscribe functionality.
229
+ * @example
230
+ * ```tsx
231
+ * // Without selector
232
+ * <table.AppHeader header={header}>
233
+ * {(h) => <th><h.SortIndicator /></th>}
234
+ * </table.AppHeader>
235
+ *
236
+ * // With selector
237
+ * <table.AppHeader header={header} selector={(s) => s.sorting}>
238
+ * {(h, sorting) => <th>{sorting.length} sorted</th>}
239
+ * </table.AppHeader>
240
+ * ```
241
+ */
242
+ AppHeader: AppHeaderComponent<TFeatures, TData, NoInfer<THeaderComponents>>;
243
+ /**
244
+ * Wraps a footer and provides header context with pre-bound headerComponents.
245
+ * Optionally accepts a selector for Subscribe functionality.
246
+ * @example
247
+ * ```tsx
248
+ * <table.AppFooter header={footer}>
249
+ * {(f) => <td><table.FlexRender footer={footer} /></td>}
250
+ * </table.AppFooter>
251
+ * ```
252
+ */
253
+ AppFooter: AppHeaderComponent<TFeatures, TData, NoInfer<THeaderComponents>>;
254
+ };
255
+ /**
256
+ * Creates a custom table hook with pre-bound components for composition.
257
+ *
258
+ * This is the table equivalent of TanStack Form's `createFormHook`. It allows you to:
259
+ * - Define features, row models, and default options once, shared across all tables
260
+ * - Register reusable table, cell, and header components
261
+ * - Access table/cell/header instances via context in those components
262
+ * - Get a `useAppTable` hook that returns an extended table with App wrapper components
263
+ * - Get a `createAppColumnHelper` function pre-bound to your features
264
+ *
265
+ * @example
266
+ * ```tsx
267
+ * // hooks/table.ts
268
+ * export const {
269
+ * useAppTable,
270
+ * createAppColumnHelper,
271
+ * useTableContext,
272
+ * useCellContext,
273
+ * useHeaderContext,
274
+ * } = createTableHook({
275
+ * _features: tableFeatures({
276
+ * rowPaginationFeature,
277
+ * rowSortingFeature,
278
+ * columnFilteringFeature,
279
+ * }),
280
+ * _rowModels: {
281
+ * paginatedRowModel: createPaginatedRowModel(),
282
+ * sortedRowModel: createSortedRowModel(sortFns),
283
+ * filteredRowModel: createFilteredRowModel(filterFns),
284
+ * },
285
+ * tableComponents: { PaginationControls, RowCount },
286
+ * cellComponents: { TextCell, NumberCell },
287
+ * headerComponents: { SortIndicator, ColumnFilter },
288
+ * })
289
+ *
290
+ * // Create column helper with TFeatures already bound
291
+ * const columnHelper = createAppColumnHelper<Person>()
292
+ *
293
+ * // components/table-components.tsx
294
+ * function PaginationControls() {
295
+ * const table = useTableContext() // TFeatures already known!
296
+ * return <table.Subscribe selector={(s) => s.pagination}>...</table.Subscribe>
297
+ * }
298
+ *
299
+ * // features/users.tsx
300
+ * function UsersTable({ data }: { data: Person[] }) {
301
+ * const table = useAppTable({
302
+ * columns,
303
+ * data, // TData inferred from Person[]
304
+ * })
305
+ *
306
+ * return (
307
+ * <table.AppTable>
308
+ * <table>
309
+ * <thead>
310
+ * {table.getHeaderGroups().map(headerGroup => (
311
+ * <tr key={headerGroup.id}>
312
+ * {headerGroup.headers.map(h => (
313
+ * <table.AppHeader header={h} key={h.id}>
314
+ * {(header) => (
315
+ * <th>
316
+ * <table.FlexRender header={h} />
317
+ * <header.SortIndicator />
318
+ * </th>
319
+ * )}
320
+ * </table.AppHeader>
321
+ * ))}
322
+ * </tr>
323
+ * ))}
324
+ * </thead>
325
+ * <tbody>
326
+ * {table.getRowModel().rows.map(row => (
327
+ * <tr key={row.id}>
328
+ * {row.getAllCells().map(c => (
329
+ * <table.AppCell cell={c} key={c.id}>
330
+ * {(cell) => <td><cell.TextCell /></td>}
331
+ * </table.AppCell>
332
+ * ))}
333
+ * </tr>
334
+ * ))}
335
+ * </tbody>
336
+ * </table>
337
+ * <table.PaginationControls />
338
+ * </table.AppTable>
339
+ * )
340
+ * }
341
+ * ```
342
+ */
343
+ declare function createTableHook<TFeatures extends TableFeatures, const TTableComponents extends Record<string, ComponentType<any>>, const TCellComponents extends Record<string, ComponentType<any>>, const THeaderComponents extends Record<string, ComponentType<any>>>({
344
+ tableComponents,
345
+ cellComponents,
346
+ headerComponents,
347
+ ...defaultTableOptions
348
+ }: CreateTableHookOptions<TFeatures, TTableComponents, TCellComponents, THeaderComponents>): {
349
+ appFeatures: TFeatures;
350
+ createAppColumnHelper: <TData extends RowData>() => AppColumnHelper<TFeatures, TData, TCellComponents, THeaderComponents>;
351
+ useAppTable: <TData extends RowData, TSelected = {}>(tableOptions: Omit<TableOptions<TFeatures, TData>, "_features" | "_rowModels">, selector?: (state: TableState<TFeatures>) => TSelected) => AppPreactTable<TFeatures, TData, TSelected, TTableComponents, TCellComponents, THeaderComponents>;
352
+ useTableContext: <TData extends RowData = RowData>() => PreactTable<TFeatures, TData>;
353
+ useCellContext: <TValue extends CellData = unknown>() => Cell<TFeatures, any, TValue>;
354
+ useHeaderContext: <TValue extends CellData = unknown>() => Header<TFeatures, any, TValue>;
355
+ };
356
+ //#endregion
357
+ export { AppCellComponent, AppCellContext, AppCellPropsWithSelector, AppCellPropsWithoutSelector, AppColumnHelper, AppHeaderComponent, AppHeaderContext, AppHeaderPropsWithSelector, AppHeaderPropsWithoutSelector, AppPreactTable, AppTableComponent, AppTablePropsWithSelector, AppTablePropsWithoutSelector, CreateTableHookOptions, createTableHook };
358
+ //# sourceMappingURL=createTableHook.d.ts.map
@@ -0,0 +1,334 @@
1
+ 'use client';
2
+
3
+ import { FlexRender } from "./FlexRender.js";
4
+ import { useTable } from "./useTable.js";
5
+ import { createColumnHelper } from "@tanstack/table-core";
6
+ import { jsx } from "preact/jsx-runtime";
7
+ import { createContext } from "preact";
8
+ import { useContext, useMemo } from "preact/hooks";
9
+
10
+ //#region src/createTableHook.tsx
11
+ /**
12
+ * Creates a custom table hook with pre-bound components for composition.
13
+ *
14
+ * This is the table equivalent of TanStack Form's `createFormHook`. It allows you to:
15
+ * - Define features, row models, and default options once, shared across all tables
16
+ * - Register reusable table, cell, and header components
17
+ * - Access table/cell/header instances via context in those components
18
+ * - Get a `useAppTable` hook that returns an extended table with App wrapper components
19
+ * - Get a `createAppColumnHelper` function pre-bound to your features
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * // hooks/table.ts
24
+ * export const {
25
+ * useAppTable,
26
+ * createAppColumnHelper,
27
+ * useTableContext,
28
+ * useCellContext,
29
+ * useHeaderContext,
30
+ * } = createTableHook({
31
+ * _features: tableFeatures({
32
+ * rowPaginationFeature,
33
+ * rowSortingFeature,
34
+ * columnFilteringFeature,
35
+ * }),
36
+ * _rowModels: {
37
+ * paginatedRowModel: createPaginatedRowModel(),
38
+ * sortedRowModel: createSortedRowModel(sortFns),
39
+ * filteredRowModel: createFilteredRowModel(filterFns),
40
+ * },
41
+ * tableComponents: { PaginationControls, RowCount },
42
+ * cellComponents: { TextCell, NumberCell },
43
+ * headerComponents: { SortIndicator, ColumnFilter },
44
+ * })
45
+ *
46
+ * // Create column helper with TFeatures already bound
47
+ * const columnHelper = createAppColumnHelper<Person>()
48
+ *
49
+ * // components/table-components.tsx
50
+ * function PaginationControls() {
51
+ * const table = useTableContext() // TFeatures already known!
52
+ * return <table.Subscribe selector={(s) => s.pagination}>...</table.Subscribe>
53
+ * }
54
+ *
55
+ * // features/users.tsx
56
+ * function UsersTable({ data }: { data: Person[] }) {
57
+ * const table = useAppTable({
58
+ * columns,
59
+ * data, // TData inferred from Person[]
60
+ * })
61
+ *
62
+ * return (
63
+ * <table.AppTable>
64
+ * <table>
65
+ * <thead>
66
+ * {table.getHeaderGroups().map(headerGroup => (
67
+ * <tr key={headerGroup.id}>
68
+ * {headerGroup.headers.map(h => (
69
+ * <table.AppHeader header={h} key={h.id}>
70
+ * {(header) => (
71
+ * <th>
72
+ * <table.FlexRender header={h} />
73
+ * <header.SortIndicator />
74
+ * </th>
75
+ * )}
76
+ * </table.AppHeader>
77
+ * ))}
78
+ * </tr>
79
+ * ))}
80
+ * </thead>
81
+ * <tbody>
82
+ * {table.getRowModel().rows.map(row => (
83
+ * <tr key={row.id}>
84
+ * {row.getAllCells().map(c => (
85
+ * <table.AppCell cell={c} key={c.id}>
86
+ * {(cell) => <td><cell.TextCell /></td>}
87
+ * </table.AppCell>
88
+ * ))}
89
+ * </tr>
90
+ * ))}
91
+ * </tbody>
92
+ * </table>
93
+ * <table.PaginationControls />
94
+ * </table.AppTable>
95
+ * )
96
+ * }
97
+ * ```
98
+ */
99
+ function createTableHook({ tableComponents, cellComponents, headerComponents, ...defaultTableOptions }) {
100
+ const TableContext = createContext(null);
101
+ const CellContext = createContext(null);
102
+ const HeaderContext = createContext(null);
103
+ /**
104
+ * Create a column helper pre-bound to the features and components configured in this table hook.
105
+ * The cell, header, and footer contexts include pre-bound components (e.g., `cell.TextCell`).
106
+ * @example
107
+ * ```tsx
108
+ * const columnHelper = createAppColumnHelper<Person>()
109
+ *
110
+ * const columns = [
111
+ * columnHelper.accessor('firstName', {
112
+ * header: 'First Name',
113
+ * cell: ({ cell }) => <cell.TextCell />, // cell has pre-bound components!
114
+ * }),
115
+ * columnHelper.accessor('age', {
116
+ * header: 'Age',
117
+ * cell: ({ cell }) => <cell.NumberCell />,
118
+ * }),
119
+ * ]
120
+ * ```
121
+ */
122
+ function createAppColumnHelper() {
123
+ return createColumnHelper();
124
+ }
125
+ /**
126
+ * Access the table instance from within an `AppTable` wrapper.
127
+ * Use this in custom `tableComponents` passed to `createTableHook`.
128
+ * TFeatures is already known from the createTableHook call.
129
+ *
130
+ * @example
131
+ * ```tsx
132
+ * function PaginationControls() {
133
+ * const table = useTableContext()
134
+ * return (
135
+ * <table.Subscribe selector={(s) => s.pagination}>
136
+ * {(pagination) => (
137
+ * <div>
138
+ * <button onClick={() => table.previousPage()}>Prev</button>
139
+ * <span>Page {pagination.pageIndex + 1}</span>
140
+ * <button onClick={() => table.nextPage()}>Next</button>
141
+ * </div>
142
+ * )}
143
+ * </table.Subscribe>
144
+ * )
145
+ * }
146
+ * ```
147
+ */
148
+ function useTableContext() {
149
+ const table = useContext(TableContext);
150
+ if (!table) throw new Error("`useTableContext` must be used within an `AppTable` component. Make sure your component is wrapped with `<table.AppTable>...</table.AppTable>`.");
151
+ return table;
152
+ }
153
+ /**
154
+ * Access the cell instance from within an `AppCell` wrapper.
155
+ * Use this in custom `cellComponents` passed to `createTableHook`.
156
+ * TFeatures is already known from the createTableHook call.
157
+ *
158
+ * @example
159
+ * ```tsx
160
+ * function TextCell() {
161
+ * const cell = useCellContext<string>()
162
+ * return <span>{cell.getValue()}</span>
163
+ * }
164
+ *
165
+ * function NumberCell({ format }: { format?: Intl.NumberFormatOptions }) {
166
+ * const cell = useCellContext<number>()
167
+ * return <span>{cell.getValue().toLocaleString(undefined, format)}</span>
168
+ * }
169
+ * ```
170
+ */
171
+ function useCellContext() {
172
+ const cell = useContext(CellContext);
173
+ if (!cell) throw new Error("`useCellContext` must be used within an `AppCell` component. Make sure your component is wrapped with `<table.AppCell cell={cell}>...</table.AppCell>`.");
174
+ return cell;
175
+ }
176
+ /**
177
+ * Access the header instance from within an `AppHeader` or `AppFooter` wrapper.
178
+ * Use this in custom `headerComponents` passed to `createTableHook`.
179
+ * TFeatures is already known from the createTableHook call.
180
+ *
181
+ * @example
182
+ * ```tsx
183
+ * function SortIndicator() {
184
+ * const header = useHeaderContext()
185
+ * const sorted = header.column.getIsSorted()
186
+ * return sorted === 'asc' ? '🔼' : sorted === 'desc' ? '🔽' : null
187
+ * }
188
+ *
189
+ * function ColumnFilter() {
190
+ * const header = useHeaderContext()
191
+ * if (!header.column.getCanFilter()) return null
192
+ * return (
193
+ * <input
194
+ * value={(header.column.getFilterValue() ?? '') as string}
195
+ * onChange={(e) => header.column.setFilterValue(e.target.value)}
196
+ * placeholder="Filter..."
197
+ * />
198
+ * )
199
+ * }
200
+ * ```
201
+ */
202
+ function useHeaderContext() {
203
+ const header = useContext(HeaderContext);
204
+ if (!header) throw new Error("`useHeaderContext` must be used within an `AppHeader` or `AppFooter` component.");
205
+ return header;
206
+ }
207
+ /**
208
+ * Context-aware FlexRender component for cells.
209
+ * Uses the cell from context, so no need to pass cell prop.
210
+ */
211
+ function CellFlexRender() {
212
+ return /* @__PURE__ */ jsx(FlexRender, { cell: useCellContext() });
213
+ }
214
+ /**
215
+ * Context-aware FlexRender component for headers.
216
+ * Uses the header from context, so no need to pass header prop.
217
+ */
218
+ function HeaderFlexRender() {
219
+ return /* @__PURE__ */ jsx(FlexRender, { header: useHeaderContext() });
220
+ }
221
+ /**
222
+ * Context-aware FlexRender component for footers.
223
+ * Uses the header from context, so no need to pass footer prop.
224
+ */
225
+ function FooterFlexRender() {
226
+ return /* @__PURE__ */ jsx(FlexRender, { footer: useHeaderContext() });
227
+ }
228
+ /**
229
+ * Enhanced useTable hook that returns a table with App wrapper components
230
+ * and pre-bound tableComponents attached directly to the table object.
231
+ *
232
+ * Default options from createTableHook are automatically merged with
233
+ * the options passed here. Options passed here take precedence.
234
+ *
235
+ * TFeatures is already known from the createTableHook call; TData is inferred from the data prop.
236
+ */
237
+ function useAppTable(tableOptions, selector) {
238
+ const table = useTable({
239
+ ...defaultTableOptions,
240
+ ...tableOptions
241
+ }, selector);
242
+ const AppTable = useMemo(() => {
243
+ function AppTableImpl(props) {
244
+ const { children, selector: appTableSelector } = props;
245
+ return /* @__PURE__ */ jsx(TableContext.Provider, {
246
+ value: table,
247
+ children: appTableSelector ? /* @__PURE__ */ jsx(table.Subscribe, {
248
+ selector: appTableSelector,
249
+ children: (state) => children(state)
250
+ }) : children
251
+ });
252
+ }
253
+ return AppTableImpl;
254
+ }, [table]);
255
+ const AppCell = useMemo(() => {
256
+ function AppCellImpl(props) {
257
+ const { cell, children, selector: appCellSelector } = props;
258
+ const extendedCell = Object.assign(cell, {
259
+ FlexRender: CellFlexRender,
260
+ ...cellComponents
261
+ });
262
+ return /* @__PURE__ */ jsx(CellContext.Provider, {
263
+ value: cell,
264
+ children: appCellSelector ? /* @__PURE__ */ jsx(table.Subscribe, {
265
+ selector: appCellSelector,
266
+ children: (state) => children(extendedCell, state)
267
+ }) : children(extendedCell)
268
+ });
269
+ }
270
+ return AppCellImpl;
271
+ }, [table]);
272
+ const AppHeader = useMemo(() => {
273
+ function AppHeaderImpl(props) {
274
+ const { header, children, selector: appHeaderSelector } = props;
275
+ const extendedHeader = Object.assign(header, {
276
+ FlexRender: HeaderFlexRender,
277
+ ...headerComponents
278
+ });
279
+ return /* @__PURE__ */ jsx(HeaderContext.Provider, {
280
+ value: header,
281
+ children: appHeaderSelector ? /* @__PURE__ */ jsx(table.Subscribe, {
282
+ selector: appHeaderSelector,
283
+ children: (state) => children(extendedHeader, state)
284
+ }) : children(extendedHeader)
285
+ });
286
+ }
287
+ return AppHeaderImpl;
288
+ }, [table]);
289
+ const AppFooter = useMemo(() => {
290
+ function AppFooterImpl(props) {
291
+ const { header, children, selector: appFooterSelector } = props;
292
+ const extendedHeader = Object.assign(header, {
293
+ FlexRender: FooterFlexRender,
294
+ ...headerComponents
295
+ });
296
+ return /* @__PURE__ */ jsx(HeaderContext.Provider, {
297
+ value: header,
298
+ children: appFooterSelector ? /* @__PURE__ */ jsx(table.Subscribe, {
299
+ selector: appFooterSelector,
300
+ children: (state) => children(extendedHeader, state)
301
+ }) : children(extendedHeader)
302
+ });
303
+ }
304
+ return AppFooterImpl;
305
+ }, [table]);
306
+ return useMemo(() => {
307
+ return Object.assign(table, {
308
+ AppTable,
309
+ AppCell,
310
+ AppHeader,
311
+ AppFooter,
312
+ ...tableComponents
313
+ });
314
+ }, [
315
+ table,
316
+ AppTable,
317
+ AppCell,
318
+ AppHeader,
319
+ AppFooter
320
+ ]);
321
+ }
322
+ return {
323
+ appFeatures: defaultTableOptions._features,
324
+ createAppColumnHelper,
325
+ useAppTable,
326
+ useTableContext,
327
+ useCellContext,
328
+ useHeaderContext
329
+ };
330
+ }
331
+
332
+ //#endregion
333
+ export { createTableHook };
334
+ //# sourceMappingURL=createTableHook.js.map