@datakable/react 0.0.0-stage → 1.0.1
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/LICENSE +21 -0
- package/README.md +128 -2
- package/dist/codes.cjs +65 -0
- package/dist/codes.cjs.map +1 -0
- package/dist/codes.js +40 -0
- package/dist/codes.js.map +1 -0
- package/dist/data-table.cjs +428 -0
- package/dist/data-table.cjs.map +1 -0
- package/dist/data-table.js +423 -0
- package/dist/data-table.js.map +1 -0
- package/dist/index.cjs +49 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +242 -0
- package/dist/index.d.ts +242 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/render-codes.cjs +77 -0
- package/dist/render-codes.cjs.map +1 -0
- package/dist/render-codes.js +52 -0
- package/dist/render-codes.js.map +1 -0
- package/dist/styles.css +1 -0
- package/dist/use-data-table.cjs +383 -0
- package/dist/use-data-table.cjs.map +1 -0
- package/dist/use-data-table.js +376 -0
- package/dist/use-data-table.js.map +1 -0
- package/package.json +57 -3
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import * as _datakable_core from '@datakable/core';
|
|
2
|
+
import { TableState, InvalidRowsMode, CreateTableOptions, ColumnDef, SchemaRow, Table, RowModel, AnyFeature, TableSchema, TableStateFor, ApiOf, SearchStatus, RowModelStatus, RowIssue, DiagnosticMessages } from '@datakable/core';
|
|
3
|
+
export * from '@datakable/core';
|
|
4
|
+
import { ReactNode, ComponentType } from 'react';
|
|
5
|
+
|
|
6
|
+
declare module '@datakable/core' {
|
|
7
|
+
interface DiagnosticCatalog {
|
|
8
|
+
DK_UNSTABLE_COLUMNS: {
|
|
9
|
+
/** Consecutive renders that passed a new `columns` array with the same shape. */
|
|
10
|
+
renders: number;
|
|
11
|
+
};
|
|
12
|
+
DK_UNSTABLE_OPTION: {
|
|
13
|
+
/** `data`, `fetcher`, `rowKey`, or a feature's function option: `features[2].searchFn`. */
|
|
14
|
+
option: string;
|
|
15
|
+
/** Consecutive renders that passed a new reference. */
|
|
16
|
+
renders: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Codes owned by `@datakable/react` (§8.3, react, dev only). Like core's dev checks, the
|
|
22
|
+
* definitions exist only in development: the NODE_ENV check is written out here (not an imported
|
|
23
|
+
* flag) so a consumer's bundler folds it while parsing and drops the text from production bundles
|
|
24
|
+
* (§8.2). They are never emitted in production, so `datakable/messages` has no text for them.
|
|
25
|
+
*/
|
|
26
|
+
declare const reactDiagnostics: (_datakable_core.DiagnosticDefinition<"DK_UNSTABLE_COLUMNS"> | _datakable_core.DiagnosticDefinition<"DK_UNSTABLE_OPTION">)[];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* `useDataTable` options: `createTable`'s (§3.2), with `cell` / `invalidCell` returning a
|
|
30
|
+
* `ReactNode` (§10). Read once, at creation: `features`, `schema`, `invalidRows`, `initialState`,
|
|
31
|
+
* `name`, `timeout`, `strict`, `diagnostics`. Every other option follows the latest render.
|
|
32
|
+
*/
|
|
33
|
+
type UseDataTableOptions<T, S extends TableState = TableState, Sch = undefined, M extends InvalidRowsMode = 'drop'> = Omit<CreateTableOptions<T, S, Sch, M>, 'columns'> & {
|
|
34
|
+
/**
|
|
35
|
+
* Compared by reference (§10): a new array tells the table the columns changed. Define them
|
|
36
|
+
* outside the component or memoise them (`DK_UNSTABLE_COLUMNS` in development).
|
|
37
|
+
*/
|
|
38
|
+
columns?: readonly ColumnDef<SchemaRow<T, Sch>, ReactNode>[];
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* What `useDataTable` returns: the table (its methods and the installed features' APIs) with the
|
|
42
|
+
* `state` and `rowModel` of this render. A new object whenever the table notifies, so it can be a
|
|
43
|
+
* dependency of `useMemo` / `memo` children; the same object while nothing changed.
|
|
44
|
+
*/
|
|
45
|
+
type UseDataTableResult<T, S extends TableState = TableState, M extends InvalidRowsMode = 'drop', In = T, Api = unknown> = Table<T, S, M, In> & Api & {
|
|
46
|
+
/** The state snapshot of this render (`getState()`). */
|
|
47
|
+
readonly state: S;
|
|
48
|
+
/** The row model of this render (`getRowModel()`, §6.6): rows, counts, status. */
|
|
49
|
+
readonly rowModel: RowModel<T, M>;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Binds a table to a component (§10): the table is created once per component instance and
|
|
53
|
+
* destroyed on unmount; renders read it through `useSyncExternalStore` (with
|
|
54
|
+
* `getServerSnapshot`), and options are synced with `table.setOptions` in a layout effect, never
|
|
55
|
+
* during render.
|
|
56
|
+
*
|
|
57
|
+
* - `features` (and the other read-once options) are read at creation: a new inline `features`
|
|
58
|
+
* array never recreates the table.
|
|
59
|
+
* - `fetcher`, `onStateChange` and `onDiagnostic` may be inline functions: the table always calls
|
|
60
|
+
* the latest one, and a new reference never refetches (call `refetch()` when a value the fetcher
|
|
61
|
+
* reads changes).
|
|
62
|
+
* - `columns`, `data` and a `rowKey` function are compared by reference: memoise them.
|
|
63
|
+
* - Controlled slices (§3.2): pass `state` and `onStateChange`; changes come back through `state`.
|
|
64
|
+
* - SSR (§7.2): rendering starts no async work. The fetcher's first request and a `searchFn` for an
|
|
65
|
+
* initial query start after the commit (`status: 'pending'` until then; `DK_SSR_ASYNC_DEFERRED`
|
|
66
|
+
* on the server), unless `initialData` already holds their result. `initialState` (e.g. parsed
|
|
67
|
+
* from the URL) applies on the server: client-mode features filter / search / sort the HTML.
|
|
68
|
+
* `getServerSnapshot` is the view at creation; a table that changed before the hydration commit
|
|
69
|
+
* reports `DK_HYDRATION_MISMATCH`.
|
|
70
|
+
*
|
|
71
|
+
* `@datakable/react` installs no features by default; `datakable`'s `useDataTable` installs the
|
|
72
|
+
* default preset.
|
|
73
|
+
*/
|
|
74
|
+
declare function useDataTable<T, S extends TableState = never, const Fs extends readonly AnyFeature[] = [], const Sch extends TableSchema | undefined = undefined, const M extends InvalidRowsMode = 'drop'>(options: UseDataTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {
|
|
75
|
+
features?: Fs;
|
|
76
|
+
}): UseDataTableResult<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M, [
|
|
77
|
+
Sch
|
|
78
|
+
] extends [TableSchema] ? unknown : T, ApiOf<Fs, SchemaRow<T, Sch>>>;
|
|
79
|
+
|
|
80
|
+
/** Props of `components.SearchInput`: the search feature's `input`, bound both ways. */
|
|
81
|
+
interface SearchInputProps {
|
|
82
|
+
/** `state.search.input` (updates as the user types). */
|
|
83
|
+
value: string;
|
|
84
|
+
/** `state.search.status`: `pending` while a debounce waits, `searching` while a request runs. */
|
|
85
|
+
status: SearchStatus;
|
|
86
|
+
/** `setSearch(value)`. */
|
|
87
|
+
onChange(value: string): void;
|
|
88
|
+
/** `flushSearch()` (Enter). */
|
|
89
|
+
onSubmit(): void;
|
|
90
|
+
/** `clearSearch()` (Esc). */
|
|
91
|
+
onClear(): void;
|
|
92
|
+
}
|
|
93
|
+
/** Props of `components.Pagination` (the pagination feature's state and API). */
|
|
94
|
+
interface PaginationProps {
|
|
95
|
+
pageIndex: number;
|
|
96
|
+
pageSize: number;
|
|
97
|
+
pageCount: number;
|
|
98
|
+
canPrev: boolean;
|
|
99
|
+
canNext: boolean;
|
|
100
|
+
prev(): void;
|
|
101
|
+
next(): void;
|
|
102
|
+
setPageIndex(index: number): void;
|
|
103
|
+
setPageSize(size: number): void;
|
|
104
|
+
}
|
|
105
|
+
/** Props of `components.Empty`: shown when the table has loaded and has no rows to show. */
|
|
106
|
+
interface EmptyProps {
|
|
107
|
+
/** `true` when there is data but filters / search removed every row. */
|
|
108
|
+
filtered: boolean;
|
|
109
|
+
}
|
|
110
|
+
/** Props of `components.Loading`: the first load (`isInitialLoad`, nothing to show yet). */
|
|
111
|
+
interface LoadingProps {
|
|
112
|
+
status: RowModelStatus;
|
|
113
|
+
}
|
|
114
|
+
/** Props of `components.Error`: the first load failed, or the body failed to render. */
|
|
115
|
+
interface ErrorProps {
|
|
116
|
+
status: RowModelStatus;
|
|
117
|
+
/**
|
|
118
|
+
* `'load'`: `status === 'error'` on the first load. `'render'`: a component in the body outside
|
|
119
|
+
* the cells threw (a component inside a cell renders `⚠` in that cell only).
|
|
120
|
+
*/
|
|
121
|
+
reason: 'load' | 'render';
|
|
122
|
+
/** `'load'`: `refetch()`. `'render'`: renders the body again. */
|
|
123
|
+
retry(): void;
|
|
124
|
+
}
|
|
125
|
+
/** `<DataTable components={...} />`: replaces the default parts (unstyled, `data-*` hooks only). */
|
|
126
|
+
interface DataTableComponents {
|
|
127
|
+
SearchInput?: ComponentType<SearchInputProps>;
|
|
128
|
+
Pagination?: ComponentType<PaginationProps>;
|
|
129
|
+
Empty?: ComponentType<EmptyProps>;
|
|
130
|
+
Loading?: ComponentType<LoadingProps>;
|
|
131
|
+
Error?: ComponentType<ErrorProps>;
|
|
132
|
+
}
|
|
133
|
+
/** What `<DataTable table={...} />` reads: the value `useDataTable` returns. */
|
|
134
|
+
interface DataTableSource {
|
|
135
|
+
readonly state: TableState;
|
|
136
|
+
readonly rowModel: {
|
|
137
|
+
readonly rows: readonly DataTableRow[];
|
|
138
|
+
readonly filteredCount: number;
|
|
139
|
+
readonly totalCount: number;
|
|
140
|
+
readonly status: RowModelStatus;
|
|
141
|
+
readonly isInitialLoad: boolean;
|
|
142
|
+
};
|
|
143
|
+
getOptions(): {
|
|
144
|
+
readonly columns?: readonly unknown[] | undefined;
|
|
145
|
+
};
|
|
146
|
+
getData(): readonly unknown[];
|
|
147
|
+
refetch(): Promise<unknown>;
|
|
148
|
+
}
|
|
149
|
+
/** The part of a `Row` (§6.6) `<DataTable />` renders from. */
|
|
150
|
+
interface DataTableRow {
|
|
151
|
+
readonly key: string | number;
|
|
152
|
+
readonly index: number;
|
|
153
|
+
readonly original: unknown;
|
|
154
|
+
readonly valid: boolean;
|
|
155
|
+
readonly issues: readonly RowIssue[];
|
|
156
|
+
getValue(id: string): unknown;
|
|
157
|
+
getCellIssues(id: string): readonly RowIssue[];
|
|
158
|
+
}
|
|
159
|
+
/** `<DataTable />`'s own props, next to `table` or the `useDataTable` options. */
|
|
160
|
+
interface DataTableOwnProps {
|
|
161
|
+
components?: DataTableComponents | undefined;
|
|
162
|
+
caption?: ReactNode;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* `<DataTable table={useDataTable(...)} />`, or `<DataTable data={rows} />` with the
|
|
166
|
+
* `useDataTable` options as props (zero-config: columns derived from the data).
|
|
167
|
+
*/
|
|
168
|
+
type DataTableProps<T = unknown, Sch = undefined, M extends InvalidRowsMode = InvalidRowsMode> = DataTableOwnProps & ({
|
|
169
|
+
table: DataTableSource;
|
|
170
|
+
} | (UseDataTableOptions<T, TableState, Sch, M> & {
|
|
171
|
+
features?: readonly AnyFeature[];
|
|
172
|
+
table?: undefined;
|
|
173
|
+
}));
|
|
174
|
+
/**
|
|
175
|
+
* The zero-config table (§10). Renders what the installed features provide: sort buttons with
|
|
176
|
+
* `aria-sort`, a search input bound to `input` (Enter = `flushSearch`, Esc = `clearSearch`),
|
|
177
|
+
* pagination, and the Loading / Error / Empty states from `status` + `isInitialLoad` (§6.6).
|
|
178
|
+
* Unstyled: style it through the `data-*` hooks (`data-status`, `data-initial-load`,
|
|
179
|
+
* `data-invalid`, `data-sort`, …) or replace parts with `components`.
|
|
180
|
+
*
|
|
181
|
+
* `@datakable/react`'s `DataTable` installs no features with `data`; `datakable`'s installs the
|
|
182
|
+
* default preset.
|
|
183
|
+
*/
|
|
184
|
+
declare function DataTable<T, const Sch extends TableSchema | undefined = undefined, const M extends InvalidRowsMode = 'drop'>(props: DataTableProps<T, Sch, M>): ReactNode;
|
|
185
|
+
|
|
186
|
+
declare module '@datakable/core' {
|
|
187
|
+
interface DiagnosticCatalog {
|
|
188
|
+
DK_RENDER_FAILED: {
|
|
189
|
+
/**
|
|
190
|
+
* The render operation: `render:cell` (a cell's boundary: a component returned by `cell` /
|
|
191
|
+
* `invalidCell`) or `render:table` (the body boundary: a component outside the cells).
|
|
192
|
+
*/
|
|
193
|
+
op: 'render:table' | 'render:cell';
|
|
194
|
+
/** `render:cell`: the slot whose component threw, `columns[1].cell`. */
|
|
195
|
+
slot?: string;
|
|
196
|
+
/** `render:cell`: the column id. */
|
|
197
|
+
column?: string;
|
|
198
|
+
/** `render:cell`: the row's index in the data (the first failure; later ones are deduped). */
|
|
199
|
+
row?: number;
|
|
200
|
+
/** `error.name` only; the full error is `context.cause`. */
|
|
201
|
+
errorName?: string;
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/** §3.4: React error boundaries, not interceptor chains (nothing runs interceptors on them). */
|
|
205
|
+
interface Operations {
|
|
206
|
+
'render:table': {
|
|
207
|
+
kind: 'sync';
|
|
208
|
+
input: undefined;
|
|
209
|
+
output: undefined;
|
|
210
|
+
};
|
|
211
|
+
'render:cell': {
|
|
212
|
+
kind: 'sync';
|
|
213
|
+
input: {
|
|
214
|
+
column: string;
|
|
215
|
+
slot: 'cell' | 'invalidCell';
|
|
216
|
+
row: number;
|
|
217
|
+
};
|
|
218
|
+
output: undefined;
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* `columns[i].cell` (§4.1, §10): renders a React node synchronously. A thenable is a contract
|
|
224
|
+
* violation (`DK_CALLBACK_BAD_RETURN`); `<DataTable />` renders `⚠` instead.
|
|
225
|
+
*/
|
|
226
|
+
declare const cellSlot: {
|
|
227
|
+
readonly name: "cell";
|
|
228
|
+
readonly returns: "sync";
|
|
229
|
+
readonly fallback: "those cells rendered ⚠";
|
|
230
|
+
};
|
|
231
|
+
/** `columns[i].invalidCell` (§5.1): renders a flagged cell; same contract as `cell`. */
|
|
232
|
+
declare const invalidCellSlot: {
|
|
233
|
+
readonly name: "invalidCell";
|
|
234
|
+
readonly returns: "sync";
|
|
235
|
+
readonly fallback: "those cells rendered ⚠";
|
|
236
|
+
};
|
|
237
|
+
/** Message text (§8.2): development builds, or production via `datakable/messages`. */
|
|
238
|
+
declare const renderMessages: DiagnosticMessages<'DK_RENDER_FAILED'>;
|
|
239
|
+
/** Codes owned by `<DataTable />` (§8.3, react). Emitted in production too; text behind NODE_ENV. */
|
|
240
|
+
declare const renderDiagnostics: _datakable_core.DiagnosticDefinition<"DK_RENDER_FAILED">[];
|
|
241
|
+
|
|
242
|
+
export { DataTable, type DataTableComponents, type DataTableOwnProps, type DataTableProps, type DataTableSource, type EmptyProps, type ErrorProps, type LoadingProps, type PaginationProps, type SearchInputProps, type UseDataTableOptions, type UseDataTableResult, cellSlot, invalidCellSlot, reactDiagnostics, renderDiagnostics, renderMessages, useDataTable };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import * as _datakable_core from '@datakable/core';
|
|
2
|
+
import { TableState, InvalidRowsMode, CreateTableOptions, ColumnDef, SchemaRow, Table, RowModel, AnyFeature, TableSchema, TableStateFor, ApiOf, SearchStatus, RowModelStatus, RowIssue, DiagnosticMessages } from '@datakable/core';
|
|
3
|
+
export * from '@datakable/core';
|
|
4
|
+
import { ReactNode, ComponentType } from 'react';
|
|
5
|
+
|
|
6
|
+
declare module '@datakable/core' {
|
|
7
|
+
interface DiagnosticCatalog {
|
|
8
|
+
DK_UNSTABLE_COLUMNS: {
|
|
9
|
+
/** Consecutive renders that passed a new `columns` array with the same shape. */
|
|
10
|
+
renders: number;
|
|
11
|
+
};
|
|
12
|
+
DK_UNSTABLE_OPTION: {
|
|
13
|
+
/** `data`, `fetcher`, `rowKey`, or a feature's function option: `features[2].searchFn`. */
|
|
14
|
+
option: string;
|
|
15
|
+
/** Consecutive renders that passed a new reference. */
|
|
16
|
+
renders: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Codes owned by `@datakable/react` (§8.3, react, dev only). Like core's dev checks, the
|
|
22
|
+
* definitions exist only in development: the NODE_ENV check is written out here (not an imported
|
|
23
|
+
* flag) so a consumer's bundler folds it while parsing and drops the text from production bundles
|
|
24
|
+
* (§8.2). They are never emitted in production, so `datakable/messages` has no text for them.
|
|
25
|
+
*/
|
|
26
|
+
declare const reactDiagnostics: (_datakable_core.DiagnosticDefinition<"DK_UNSTABLE_COLUMNS"> | _datakable_core.DiagnosticDefinition<"DK_UNSTABLE_OPTION">)[];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* `useDataTable` options: `createTable`'s (§3.2), with `cell` / `invalidCell` returning a
|
|
30
|
+
* `ReactNode` (§10). Read once, at creation: `features`, `schema`, `invalidRows`, `initialState`,
|
|
31
|
+
* `name`, `timeout`, `strict`, `diagnostics`. Every other option follows the latest render.
|
|
32
|
+
*/
|
|
33
|
+
type UseDataTableOptions<T, S extends TableState = TableState, Sch = undefined, M extends InvalidRowsMode = 'drop'> = Omit<CreateTableOptions<T, S, Sch, M>, 'columns'> & {
|
|
34
|
+
/**
|
|
35
|
+
* Compared by reference (§10): a new array tells the table the columns changed. Define them
|
|
36
|
+
* outside the component or memoise them (`DK_UNSTABLE_COLUMNS` in development).
|
|
37
|
+
*/
|
|
38
|
+
columns?: readonly ColumnDef<SchemaRow<T, Sch>, ReactNode>[];
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* What `useDataTable` returns: the table (its methods and the installed features' APIs) with the
|
|
42
|
+
* `state` and `rowModel` of this render. A new object whenever the table notifies, so it can be a
|
|
43
|
+
* dependency of `useMemo` / `memo` children; the same object while nothing changed.
|
|
44
|
+
*/
|
|
45
|
+
type UseDataTableResult<T, S extends TableState = TableState, M extends InvalidRowsMode = 'drop', In = T, Api = unknown> = Table<T, S, M, In> & Api & {
|
|
46
|
+
/** The state snapshot of this render (`getState()`). */
|
|
47
|
+
readonly state: S;
|
|
48
|
+
/** The row model of this render (`getRowModel()`, §6.6): rows, counts, status. */
|
|
49
|
+
readonly rowModel: RowModel<T, M>;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Binds a table to a component (§10): the table is created once per component instance and
|
|
53
|
+
* destroyed on unmount; renders read it through `useSyncExternalStore` (with
|
|
54
|
+
* `getServerSnapshot`), and options are synced with `table.setOptions` in a layout effect, never
|
|
55
|
+
* during render.
|
|
56
|
+
*
|
|
57
|
+
* - `features` (and the other read-once options) are read at creation: a new inline `features`
|
|
58
|
+
* array never recreates the table.
|
|
59
|
+
* - `fetcher`, `onStateChange` and `onDiagnostic` may be inline functions: the table always calls
|
|
60
|
+
* the latest one, and a new reference never refetches (call `refetch()` when a value the fetcher
|
|
61
|
+
* reads changes).
|
|
62
|
+
* - `columns`, `data` and a `rowKey` function are compared by reference: memoise them.
|
|
63
|
+
* - Controlled slices (§3.2): pass `state` and `onStateChange`; changes come back through `state`.
|
|
64
|
+
* - SSR (§7.2): rendering starts no async work. The fetcher's first request and a `searchFn` for an
|
|
65
|
+
* initial query start after the commit (`status: 'pending'` until then; `DK_SSR_ASYNC_DEFERRED`
|
|
66
|
+
* on the server), unless `initialData` already holds their result. `initialState` (e.g. parsed
|
|
67
|
+
* from the URL) applies on the server: client-mode features filter / search / sort the HTML.
|
|
68
|
+
* `getServerSnapshot` is the view at creation; a table that changed before the hydration commit
|
|
69
|
+
* reports `DK_HYDRATION_MISMATCH`.
|
|
70
|
+
*
|
|
71
|
+
* `@datakable/react` installs no features by default; `datakable`'s `useDataTable` installs the
|
|
72
|
+
* default preset.
|
|
73
|
+
*/
|
|
74
|
+
declare function useDataTable<T, S extends TableState = never, const Fs extends readonly AnyFeature[] = [], const Sch extends TableSchema | undefined = undefined, const M extends InvalidRowsMode = 'drop'>(options: UseDataTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {
|
|
75
|
+
features?: Fs;
|
|
76
|
+
}): UseDataTableResult<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M, [
|
|
77
|
+
Sch
|
|
78
|
+
] extends [TableSchema] ? unknown : T, ApiOf<Fs, SchemaRow<T, Sch>>>;
|
|
79
|
+
|
|
80
|
+
/** Props of `components.SearchInput`: the search feature's `input`, bound both ways. */
|
|
81
|
+
interface SearchInputProps {
|
|
82
|
+
/** `state.search.input` (updates as the user types). */
|
|
83
|
+
value: string;
|
|
84
|
+
/** `state.search.status`: `pending` while a debounce waits, `searching` while a request runs. */
|
|
85
|
+
status: SearchStatus;
|
|
86
|
+
/** `setSearch(value)`. */
|
|
87
|
+
onChange(value: string): void;
|
|
88
|
+
/** `flushSearch()` (Enter). */
|
|
89
|
+
onSubmit(): void;
|
|
90
|
+
/** `clearSearch()` (Esc). */
|
|
91
|
+
onClear(): void;
|
|
92
|
+
}
|
|
93
|
+
/** Props of `components.Pagination` (the pagination feature's state and API). */
|
|
94
|
+
interface PaginationProps {
|
|
95
|
+
pageIndex: number;
|
|
96
|
+
pageSize: number;
|
|
97
|
+
pageCount: number;
|
|
98
|
+
canPrev: boolean;
|
|
99
|
+
canNext: boolean;
|
|
100
|
+
prev(): void;
|
|
101
|
+
next(): void;
|
|
102
|
+
setPageIndex(index: number): void;
|
|
103
|
+
setPageSize(size: number): void;
|
|
104
|
+
}
|
|
105
|
+
/** Props of `components.Empty`: shown when the table has loaded and has no rows to show. */
|
|
106
|
+
interface EmptyProps {
|
|
107
|
+
/** `true` when there is data but filters / search removed every row. */
|
|
108
|
+
filtered: boolean;
|
|
109
|
+
}
|
|
110
|
+
/** Props of `components.Loading`: the first load (`isInitialLoad`, nothing to show yet). */
|
|
111
|
+
interface LoadingProps {
|
|
112
|
+
status: RowModelStatus;
|
|
113
|
+
}
|
|
114
|
+
/** Props of `components.Error`: the first load failed, or the body failed to render. */
|
|
115
|
+
interface ErrorProps {
|
|
116
|
+
status: RowModelStatus;
|
|
117
|
+
/**
|
|
118
|
+
* `'load'`: `status === 'error'` on the first load. `'render'`: a component in the body outside
|
|
119
|
+
* the cells threw (a component inside a cell renders `⚠` in that cell only).
|
|
120
|
+
*/
|
|
121
|
+
reason: 'load' | 'render';
|
|
122
|
+
/** `'load'`: `refetch()`. `'render'`: renders the body again. */
|
|
123
|
+
retry(): void;
|
|
124
|
+
}
|
|
125
|
+
/** `<DataTable components={...} />`: replaces the default parts (unstyled, `data-*` hooks only). */
|
|
126
|
+
interface DataTableComponents {
|
|
127
|
+
SearchInput?: ComponentType<SearchInputProps>;
|
|
128
|
+
Pagination?: ComponentType<PaginationProps>;
|
|
129
|
+
Empty?: ComponentType<EmptyProps>;
|
|
130
|
+
Loading?: ComponentType<LoadingProps>;
|
|
131
|
+
Error?: ComponentType<ErrorProps>;
|
|
132
|
+
}
|
|
133
|
+
/** What `<DataTable table={...} />` reads: the value `useDataTable` returns. */
|
|
134
|
+
interface DataTableSource {
|
|
135
|
+
readonly state: TableState;
|
|
136
|
+
readonly rowModel: {
|
|
137
|
+
readonly rows: readonly DataTableRow[];
|
|
138
|
+
readonly filteredCount: number;
|
|
139
|
+
readonly totalCount: number;
|
|
140
|
+
readonly status: RowModelStatus;
|
|
141
|
+
readonly isInitialLoad: boolean;
|
|
142
|
+
};
|
|
143
|
+
getOptions(): {
|
|
144
|
+
readonly columns?: readonly unknown[] | undefined;
|
|
145
|
+
};
|
|
146
|
+
getData(): readonly unknown[];
|
|
147
|
+
refetch(): Promise<unknown>;
|
|
148
|
+
}
|
|
149
|
+
/** The part of a `Row` (§6.6) `<DataTable />` renders from. */
|
|
150
|
+
interface DataTableRow {
|
|
151
|
+
readonly key: string | number;
|
|
152
|
+
readonly index: number;
|
|
153
|
+
readonly original: unknown;
|
|
154
|
+
readonly valid: boolean;
|
|
155
|
+
readonly issues: readonly RowIssue[];
|
|
156
|
+
getValue(id: string): unknown;
|
|
157
|
+
getCellIssues(id: string): readonly RowIssue[];
|
|
158
|
+
}
|
|
159
|
+
/** `<DataTable />`'s own props, next to `table` or the `useDataTable` options. */
|
|
160
|
+
interface DataTableOwnProps {
|
|
161
|
+
components?: DataTableComponents | undefined;
|
|
162
|
+
caption?: ReactNode;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* `<DataTable table={useDataTable(...)} />`, or `<DataTable data={rows} />` with the
|
|
166
|
+
* `useDataTable` options as props (zero-config: columns derived from the data).
|
|
167
|
+
*/
|
|
168
|
+
type DataTableProps<T = unknown, Sch = undefined, M extends InvalidRowsMode = InvalidRowsMode> = DataTableOwnProps & ({
|
|
169
|
+
table: DataTableSource;
|
|
170
|
+
} | (UseDataTableOptions<T, TableState, Sch, M> & {
|
|
171
|
+
features?: readonly AnyFeature[];
|
|
172
|
+
table?: undefined;
|
|
173
|
+
}));
|
|
174
|
+
/**
|
|
175
|
+
* The zero-config table (§10). Renders what the installed features provide: sort buttons with
|
|
176
|
+
* `aria-sort`, a search input bound to `input` (Enter = `flushSearch`, Esc = `clearSearch`),
|
|
177
|
+
* pagination, and the Loading / Error / Empty states from `status` + `isInitialLoad` (§6.6).
|
|
178
|
+
* Unstyled: style it through the `data-*` hooks (`data-status`, `data-initial-load`,
|
|
179
|
+
* `data-invalid`, `data-sort`, …) or replace parts with `components`.
|
|
180
|
+
*
|
|
181
|
+
* `@datakable/react`'s `DataTable` installs no features with `data`; `datakable`'s installs the
|
|
182
|
+
* default preset.
|
|
183
|
+
*/
|
|
184
|
+
declare function DataTable<T, const Sch extends TableSchema | undefined = undefined, const M extends InvalidRowsMode = 'drop'>(props: DataTableProps<T, Sch, M>): ReactNode;
|
|
185
|
+
|
|
186
|
+
declare module '@datakable/core' {
|
|
187
|
+
interface DiagnosticCatalog {
|
|
188
|
+
DK_RENDER_FAILED: {
|
|
189
|
+
/**
|
|
190
|
+
* The render operation: `render:cell` (a cell's boundary: a component returned by `cell` /
|
|
191
|
+
* `invalidCell`) or `render:table` (the body boundary: a component outside the cells).
|
|
192
|
+
*/
|
|
193
|
+
op: 'render:table' | 'render:cell';
|
|
194
|
+
/** `render:cell`: the slot whose component threw, `columns[1].cell`. */
|
|
195
|
+
slot?: string;
|
|
196
|
+
/** `render:cell`: the column id. */
|
|
197
|
+
column?: string;
|
|
198
|
+
/** `render:cell`: the row's index in the data (the first failure; later ones are deduped). */
|
|
199
|
+
row?: number;
|
|
200
|
+
/** `error.name` only; the full error is `context.cause`. */
|
|
201
|
+
errorName?: string;
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/** §3.4: React error boundaries, not interceptor chains (nothing runs interceptors on them). */
|
|
205
|
+
interface Operations {
|
|
206
|
+
'render:table': {
|
|
207
|
+
kind: 'sync';
|
|
208
|
+
input: undefined;
|
|
209
|
+
output: undefined;
|
|
210
|
+
};
|
|
211
|
+
'render:cell': {
|
|
212
|
+
kind: 'sync';
|
|
213
|
+
input: {
|
|
214
|
+
column: string;
|
|
215
|
+
slot: 'cell' | 'invalidCell';
|
|
216
|
+
row: number;
|
|
217
|
+
};
|
|
218
|
+
output: undefined;
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* `columns[i].cell` (§4.1, §10): renders a React node synchronously. A thenable is a contract
|
|
224
|
+
* violation (`DK_CALLBACK_BAD_RETURN`); `<DataTable />` renders `⚠` instead.
|
|
225
|
+
*/
|
|
226
|
+
declare const cellSlot: {
|
|
227
|
+
readonly name: "cell";
|
|
228
|
+
readonly returns: "sync";
|
|
229
|
+
readonly fallback: "those cells rendered ⚠";
|
|
230
|
+
};
|
|
231
|
+
/** `columns[i].invalidCell` (§5.1): renders a flagged cell; same contract as `cell`. */
|
|
232
|
+
declare const invalidCellSlot: {
|
|
233
|
+
readonly name: "invalidCell";
|
|
234
|
+
readonly returns: "sync";
|
|
235
|
+
readonly fallback: "those cells rendered ⚠";
|
|
236
|
+
};
|
|
237
|
+
/** Message text (§8.2): development builds, or production via `datakable/messages`. */
|
|
238
|
+
declare const renderMessages: DiagnosticMessages<'DK_RENDER_FAILED'>;
|
|
239
|
+
/** Codes owned by `<DataTable />` (§8.3, react). Emitted in production too; text behind NODE_ENV. */
|
|
240
|
+
declare const renderDiagnostics: _datakable_core.DiagnosticDefinition<"DK_RENDER_FAILED">[];
|
|
241
|
+
|
|
242
|
+
export { DataTable, type DataTableComponents, type DataTableOwnProps, type DataTableProps, type DataTableSource, type EmptyProps, type ErrorProps, type LoadingProps, type PaginationProps, type SearchInputProps, type UseDataTableOptions, type UseDataTableResult, cellSlot, invalidCellSlot, reactDiagnostics, renderDiagnostics, renderMessages, useDataTable };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
export * from "@datakable/core";
|
|
3
|
+
import { reactDiagnostics } from "./codes.js";
|
|
4
|
+
import {
|
|
5
|
+
DataTable
|
|
6
|
+
} from "./data-table.js";
|
|
7
|
+
import { cellSlot, invalidCellSlot, renderDiagnostics, renderMessages } from "./render-codes.js";
|
|
8
|
+
import { useDataTable } from "./use-data-table.js";
|
|
9
|
+
export {
|
|
10
|
+
DataTable,
|
|
11
|
+
cellSlot,
|
|
12
|
+
invalidCellSlot,
|
|
13
|
+
reactDiagnostics,
|
|
14
|
+
renderDiagnostics,
|
|
15
|
+
renderMessages,
|
|
16
|
+
useDataTable
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from '@datakable/core'\nexport { reactDiagnostics } from './codes'\nexport {\n DataTable,\n type DataTableComponents,\n type DataTableOwnProps,\n type DataTableProps,\n type DataTableSource,\n type EmptyProps,\n type ErrorProps,\n type LoadingProps,\n type PaginationProps,\n type SearchInputProps,\n} from './data-table'\nexport { cellSlot, invalidCellSlot, renderDiagnostics, renderMessages } from './render-codes'\nexport { type UseDataTableOptions, type UseDataTableResult, useDataTable } from './use-data-table'\n"],"mappings":";AAAA,cAAc;AACd,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,OAUK;AACP,SAAS,UAAU,iBAAiB,mBAAmB,sBAAsB;AAC7E,SAA4D,oBAAoB;","names":[]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/render-codes.ts
|
|
21
|
+
var render_codes_exports = {};
|
|
22
|
+
__export(render_codes_exports, {
|
|
23
|
+
cellSlot: () => cellSlot,
|
|
24
|
+
invalidCellSlot: () => invalidCellSlot,
|
|
25
|
+
registerRenderOperations: () => registerRenderOperations,
|
|
26
|
+
renderDiagnostics: () => renderDiagnostics,
|
|
27
|
+
renderMessages: () => renderMessages
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(render_codes_exports);
|
|
30
|
+
var import_core = require("@datakable/core");
|
|
31
|
+
function registerRenderOperations() {
|
|
32
|
+
(0, import_core.registerOperation)("render:table", { kind: "sync", hot: false });
|
|
33
|
+
(0, import_core.registerOperation)("render:cell", { kind: "sync", hot: false });
|
|
34
|
+
}
|
|
35
|
+
var cellSlot = (0, import_core.defineSlot)({
|
|
36
|
+
name: "cell",
|
|
37
|
+
returns: "sync",
|
|
38
|
+
fallback: "those cells rendered \u26A0"
|
|
39
|
+
});
|
|
40
|
+
var invalidCellSlot = (0, import_core.defineSlot)({
|
|
41
|
+
name: "invalidCell",
|
|
42
|
+
returns: "sync",
|
|
43
|
+
fallback: "those cells rendered \u26A0"
|
|
44
|
+
});
|
|
45
|
+
var renderMessages = {
|
|
46
|
+
DK_RENDER_FAILED: {
|
|
47
|
+
problem: (d) => d.op === "render:cell" ? `a component returned by ${d.slot} (column "${d.column}") threw${d.errorName ? ` ${d.errorName}` : ""} while rendering row #${d.row}` : `a component rendered inside the table body threw${d.errorName ? ` ${d.errorName}` : ""} (outside the cells: a components.Empty / Loading / Error part)`,
|
|
48
|
+
impact: (d) => d.op === "render:cell" ? "that cell renders \u26A0; the other cells and rows, the header, search, pagination and the table API keep working, and the cell renders again when its row's data or the columns change" : "the table body shows the Error state; the header, search and pagination keep working, and the body renders again on the next row model or Retry",
|
|
49
|
+
fix: (d) => d.op === "render:cell" ? [
|
|
50
|
+
`find the throwing component in context.cause (passed to onDiagnostic) and make it total: guard null / undefined / unexpected values of column "${d.column}" instead of throwing`,
|
|
51
|
+
`for your own fallback instead of \u26A0, wrap the component in an error boundary inside ${d.slot}`
|
|
52
|
+
] : [
|
|
53
|
+
"find the throwing component in context.cause (passed to onDiagnostic) and make it total: guard null / undefined / unexpected values instead of throwing",
|
|
54
|
+
"a component returned by a column cell / invalidCell is caught per cell (\u26A0); a throw in the cell function itself is DK_CALLBACK_FAILED"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var renderDiagnostics = [
|
|
59
|
+
(0, import_core.defineDiagnostic)(
|
|
60
|
+
{
|
|
61
|
+
code: "DK_RENDER_FAILED",
|
|
62
|
+
level: "error",
|
|
63
|
+
where: (d) => d.slot ? { kind: "operation", op: d.op, slot: d.slot } : { kind: "operation", op: d.op }
|
|
64
|
+
},
|
|
65
|
+
// Written out (not an imported flag) so a consumer's bundler folds it while parsing (§8.2).
|
|
66
|
+
process.env.NODE_ENV !== "production" && renderMessages.DK_RENDER_FAILED
|
|
67
|
+
)
|
|
68
|
+
];
|
|
69
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
70
|
+
0 && (module.exports = {
|
|
71
|
+
cellSlot,
|
|
72
|
+
invalidCellSlot,
|
|
73
|
+
registerRenderOperations,
|
|
74
|
+
renderDiagnostics,
|
|
75
|
+
renderMessages
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=render-codes.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/render-codes.ts"],"sourcesContent":["import {\n type DiagnosticMessages,\n defineDiagnostic,\n defineSlot,\n registerOperation,\n} from '@datakable/core'\n\ndeclare module '@datakable/core' {\n interface DiagnosticCatalog {\n DK_RENDER_FAILED: {\n /**\n * The render operation: `render:cell` (a cell's boundary: a component returned by `cell` /\n * `invalidCell`) or `render:table` (the body boundary: a component outside the cells).\n */\n op: 'render:table' | 'render:cell'\n /** `render:cell`: the slot whose component threw, `columns[1].cell`. */\n slot?: string\n /** `render:cell`: the column id. */\n column?: string\n /** `render:cell`: the row's index in the data (the first failure; later ones are deduped). */\n row?: number\n /** `error.name` only; the full error is `context.cause`. */\n errorName?: string\n }\n }\n\n /** §3.4: React error boundaries, not interceptor chains (nothing runs interceptors on them). */\n interface Operations {\n 'render:table': { kind: 'sync'; input: undefined; output: undefined }\n 'render:cell': {\n kind: 'sync'\n input: { column: string; slot: 'cell' | 'invalidCell'; row: number }\n output: undefined\n }\n }\n}\n\n/**\n * Registers `render:table` / `render:cell` (§3.4: owned by `@datakable/react`, not core). Neither\n * is hot: no interceptor chain runs per cell, so `on: '*'` interceptors get no hot-op warning for\n * them. Idempotent (an identical re-registration is a no-op).\n */\nexport function registerRenderOperations(): void {\n registerOperation('render:table', { kind: 'sync', hot: false })\n registerOperation('render:cell', { kind: 'sync', hot: false })\n}\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\n/**\n * `columns[i].cell` (§4.1, §10): renders a React node synchronously. A thenable is a contract\n * violation (`DK_CALLBACK_BAD_RETURN`); `<DataTable />` renders `⚠` instead.\n */\nexport const cellSlot = defineSlot({\n name: 'cell',\n returns: 'sync',\n fallback: 'those cells rendered ⚠',\n})\n\n/** `columns[i].invalidCell` (§5.1): renders a flagged cell; same contract as `cell`. */\nexport const invalidCellSlot = defineSlot({\n name: 'invalidCell',\n returns: 'sync',\n fallback: 'those cells rendered ⚠',\n})\n\n/** Message text (§8.2): development builds, or production via `datakable/messages`. */\nexport const renderMessages: DiagnosticMessages<'DK_RENDER_FAILED'> = {\n DK_RENDER_FAILED: {\n problem: (d) =>\n d.op === 'render:cell'\n ? `a component returned by ${d.slot} (column \"${d.column}\") threw` +\n `${d.errorName ? ` ${d.errorName}` : ''} while rendering row #${d.row}`\n : `a component rendered inside the table body threw${d.errorName ? ` ${d.errorName}` : ''} ` +\n '(outside the cells: a components.Empty / Loading / Error part)',\n impact: (d) =>\n d.op === 'render:cell'\n ? 'that cell renders ⚠; the other cells and rows, the header, search, pagination and the ' +\n \"table API keep working, and the cell renders again when its row's data or the columns \" +\n 'change'\n : 'the table body shows the Error state; the header, search and pagination keep working, ' +\n 'and the body renders again on the next row model or Retry',\n fix: (d) =>\n d.op === 'render:cell'\n ? [\n `find the throwing component in context.cause (passed to onDiagnostic) and make it ` +\n `total: guard null / undefined / unexpected values of column \"${d.column}\" ` +\n 'instead of throwing',\n 'for your own fallback instead of ⚠, wrap the component in an error boundary inside ' +\n `${d.slot}`,\n ]\n : [\n 'find the throwing component in context.cause (passed to onDiagnostic) and make it ' +\n 'total: guard null / undefined / unexpected values instead of throwing',\n 'a component returned by a column cell / invalidCell is caught per cell (⚠); a throw in ' +\n 'the cell function itself is DK_CALLBACK_FAILED',\n ],\n },\n}\n\n/** Codes owned by `<DataTable />` (§8.3, react). Emitted in production too; text behind NODE_ENV. */\nexport const renderDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_RENDER_FAILED',\n level: 'error',\n where: (d) =>\n d.slot ? { kind: 'operation', op: d.op, slot: d.slot } : { kind: 'operation', op: d.op },\n },\n // Written out (not an imported flag) so a consumer's bundler folds it while parsing (§8.2).\n process.env.NODE_ENV !== 'production' && renderMessages.DK_RENDER_FAILED,\n ),\n]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAKO;AAqCA,SAAS,2BAAiC;AAC/C,qCAAkB,gBAAgB,EAAE,MAAM,QAAQ,KAAK,MAAM,CAAC;AAC9D,qCAAkB,eAAe,EAAE,MAAM,QAAQ,KAAK,MAAM,CAAC;AAC/D;AASO,IAAM,eAAW,wBAAW;AAAA,EACjC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AACZ,CAAC;AAGM,IAAM,sBAAkB,wBAAW;AAAA,EACxC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AACZ,CAAC;AAGM,IAAM,iBAAyD;AAAA,EACpE,kBAAkB;AAAA,IAChB,SAAS,CAAC,MACR,EAAE,OAAO,gBACL,2BAA2B,EAAE,IAAI,aAAa,EAAE,MAAM,WACnD,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE,yBAAyB,EAAE,GAAG,KACrE,mDAAmD,EAAE,YAAY,IAAI,EAAE,SAAS,KAAK,EAAE;AAAA,IAE7F,QAAQ,CAAC,MACP,EAAE,OAAO,gBACL,4LAGA;AAAA,IAEN,KAAK,CAAC,MACJ,EAAE,OAAO,gBACL;AAAA,MACE,kJACkE,EAAE,MAAM;AAAA,MAE1E,2FACK,EAAE,IAAI;AAAA,IACb,IACA;AAAA,MACE;AAAA,MAEA;AAAA,IAEF;AAAA,EACR;AACF;AAGO,IAAM,oBAAoB;AAAA,MAC/B;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,OAAO,EAAE,MAAM,aAAa,IAAI,EAAE,IAAI,MAAM,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,IAAI,EAAE,GAAG;AAAA,IAC3F;AAAA;AAAA,IAEA,QAAQ,IAAI,aAAa,gBAAgB,eAAe;AAAA,EAC1D;AACF;","names":[]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// src/render-codes.ts
|
|
2
|
+
import {
|
|
3
|
+
defineDiagnostic,
|
|
4
|
+
defineSlot,
|
|
5
|
+
registerOperation
|
|
6
|
+
} from "@datakable/core";
|
|
7
|
+
function registerRenderOperations() {
|
|
8
|
+
registerOperation("render:table", { kind: "sync", hot: false });
|
|
9
|
+
registerOperation("render:cell", { kind: "sync", hot: false });
|
|
10
|
+
}
|
|
11
|
+
var cellSlot = defineSlot({
|
|
12
|
+
name: "cell",
|
|
13
|
+
returns: "sync",
|
|
14
|
+
fallback: "those cells rendered \u26A0"
|
|
15
|
+
});
|
|
16
|
+
var invalidCellSlot = defineSlot({
|
|
17
|
+
name: "invalidCell",
|
|
18
|
+
returns: "sync",
|
|
19
|
+
fallback: "those cells rendered \u26A0"
|
|
20
|
+
});
|
|
21
|
+
var renderMessages = {
|
|
22
|
+
DK_RENDER_FAILED: {
|
|
23
|
+
problem: (d) => d.op === "render:cell" ? `a component returned by ${d.slot} (column "${d.column}") threw${d.errorName ? ` ${d.errorName}` : ""} while rendering row #${d.row}` : `a component rendered inside the table body threw${d.errorName ? ` ${d.errorName}` : ""} (outside the cells: a components.Empty / Loading / Error part)`,
|
|
24
|
+
impact: (d) => d.op === "render:cell" ? "that cell renders \u26A0; the other cells and rows, the header, search, pagination and the table API keep working, and the cell renders again when its row's data or the columns change" : "the table body shows the Error state; the header, search and pagination keep working, and the body renders again on the next row model or Retry",
|
|
25
|
+
fix: (d) => d.op === "render:cell" ? [
|
|
26
|
+
`find the throwing component in context.cause (passed to onDiagnostic) and make it total: guard null / undefined / unexpected values of column "${d.column}" instead of throwing`,
|
|
27
|
+
`for your own fallback instead of \u26A0, wrap the component in an error boundary inside ${d.slot}`
|
|
28
|
+
] : [
|
|
29
|
+
"find the throwing component in context.cause (passed to onDiagnostic) and make it total: guard null / undefined / unexpected values instead of throwing",
|
|
30
|
+
"a component returned by a column cell / invalidCell is caught per cell (\u26A0); a throw in the cell function itself is DK_CALLBACK_FAILED"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var renderDiagnostics = [
|
|
35
|
+
defineDiagnostic(
|
|
36
|
+
{
|
|
37
|
+
code: "DK_RENDER_FAILED",
|
|
38
|
+
level: "error",
|
|
39
|
+
where: (d) => d.slot ? { kind: "operation", op: d.op, slot: d.slot } : { kind: "operation", op: d.op }
|
|
40
|
+
},
|
|
41
|
+
// Written out (not an imported flag) so a consumer's bundler folds it while parsing (§8.2).
|
|
42
|
+
process.env.NODE_ENV !== "production" && renderMessages.DK_RENDER_FAILED
|
|
43
|
+
)
|
|
44
|
+
];
|
|
45
|
+
export {
|
|
46
|
+
cellSlot,
|
|
47
|
+
invalidCellSlot,
|
|
48
|
+
registerRenderOperations,
|
|
49
|
+
renderDiagnostics,
|
|
50
|
+
renderMessages
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=render-codes.js.map
|