@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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Supakit Kitjanabumrungsak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,129 @@
1
- # Temporary Holding Version
1
+ # @datakable/react
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ React bindings for DataKable: the `useDataTable` hook over the
4
+ [`@datakable/core`](https://github.com/Ink01101011/datakable/tree/main/packages/core) table store. Most apps want
5
+ [`datakable`](https://github.com/Ink01101011/datakable/tree/main/packages/datakable), whose `useDataTable` also installs the default feature
6
+ preset; this package installs **no** features unless you pass them.
7
+
8
+ > Version 1.0: the public API is stable and follows semantic versioning from here. Guides,
9
+ > examples and troubleshooting: the [documentation](https://github.com/Ink01101011/datakable/blob/main/docs/README.md).
10
+
11
+ ```bash
12
+ npm install @datakable/react @datakable/core react
13
+ ```
14
+
15
+ React `>=18`. The modules of `<DataTable />` and `useDataTable` carry a `"use client"` directive,
16
+ so the Next.js app router treats them as client code even when a server component imports them
17
+ from here; the rest (core's `createTable`, …) stays usable on the server. Like core,
18
+ it needs a bundler that replaces `process.env.NODE_ENV` (see [core](https://github.com/Ink01101011/datakable/tree/main/packages/core)).
19
+
20
+ ## useDataTable
21
+
22
+ ```tsx
23
+ import { type ColumnDef, pagination, sorting } from '@datakable/core'
24
+ import { useDataTable } from '@datakable/react'
25
+ import type { ReactNode } from 'react'
26
+
27
+ type User = { id: number; name: string; age: number }
28
+
29
+ // Columns are compared by reference: define them outside the component, or memoise them
30
+ // (DK_UNSTABLE_COLUMNS warns in development when a new same-shape array arrives every render).
31
+ const columns: ColumnDef<User, ReactNode>[] = [
32
+ { key: 'name', header: 'Name', cell: ({ value }) => <strong>{value}</strong> },
33
+ { key: 'age', header: 'Age' },
34
+ ]
35
+
36
+ export function Users({ users }: { users: User[] }) {
37
+ // @datakable/react installs no features by default; `datakable` adds the preset.
38
+ const table = useDataTable({
39
+ data: users,
40
+ rowKey: 'id',
41
+ columns,
42
+ features: [sorting(), pagination({ pageSize: 20 })],
43
+ })
44
+ return (
45
+ <ul aria-busy={table.rowModel.status !== 'idle'}>
46
+ {table.rowModel.rows.map((row) => (
47
+ <li key={row.key}>{row.original.name}</li>
48
+ ))}
49
+ </ul>
50
+ )
51
+ }
52
+ ```
53
+
54
+ `useDataTable(options)` takes `createTable`'s options (with `cell` / `invalidCell` returning a
55
+ `ReactNode`) and returns the table — its methods plus the installed features' APIs — with
56
+ `state` and `rowModel` for this render. The returned object is new whenever the table notifies
57
+ and the same object otherwise, so it works as a `useMemo` dependency.
58
+
59
+ - The table is created once per component instance (on the first render) and destroyed on
60
+ unmount. Renders read it through `useSyncExternalStore`.
61
+ - **Read once, at creation:** `features`, `schema`, `invalidRows`, `initialState`,
62
+ `initialData`, `name`, `timeout`, `strict`, `diagnostics`. A new inline `features` array never
63
+ recreates the table. Hoist a `features` array with `as const`: as a plain array type the
64
+ table's type loses the features' methods and state.
65
+ - **Synced** through `table.setOptions` in a layout effect, never during render: `data`,
66
+ `columns`, `rowKey`, `state`, `onStateChange`, `interceptors`, `onDiagnostic`, `fetcher`,
67
+ `rowCount`.
68
+ - `onStateChange` and `onDiagnostic` may be inline functions. `fetcher`, `onStateChange` and
69
+ `onDiagnostic` reach the table as stable wrappers that call the latest prop, so a new reference
70
+ does not refetch — call `refetch()` when a value the fetcher reads changes. Wrap the fetcher
71
+ with `withFetcher()` (`@datakable/core/server`, also exported by `datakable`), and keep the
72
+ function you wrap stable: `withFetcher` returns the same wrapper for the same function, so
73
+ `fetcher={withFetcher(fetchUsers)}` with a module-level `fetchUsers` is fine, but an inline
74
+ arrow function is a new fetcher on every render and reports `DK_UNSTABLE_OPTION` in development
75
+ (hoist it or `useCallback` it).
76
+ - `columns`, `data` and a `rowKey` function are compared by reference. In development,
77
+ `DK_UNSTABLE_COLUMNS` / `DK_UNSTABLE_OPTION` warn when a new same-shape value arrives on every
78
+ render. Structural comparison is not used, because a changed `format` or `accessor` would then
79
+ go stale silently.
80
+ - Controlled slices: pass `state` and `onStateChange` (example in
81
+ [`datakable`](https://github.com/Ink01101011/datakable/tree/main/packages/datakable#controlled-state)).
82
+ - Status-driven UI: render from `table.rowModel.status` and `isInitialLoad` (the
83
+ [status model](https://github.com/Ink01101011/datakable/tree/main/packages/core#status-model)).
84
+
85
+ ## DataTable
86
+
87
+ ```tsx
88
+ import { type ColumnDef, pagination, search, sorting } from '@datakable/core'
89
+ import { DataTable } from '@datakable/react'
90
+ import type { ReactNode } from 'react'
91
+
92
+ type User = { id: number; name: string; age: number }
93
+
94
+ const columns: ColumnDef<User, ReactNode>[] = [
95
+ { key: 'name', header: 'Name' },
96
+ { key: 'age', header: 'Age', sortable: false },
97
+ ]
98
+ // @datakable/react's DataTable renders what the installed features provide (none by default).
99
+ const features = [search(), sorting(), pagination({ pageSize: 20 })]
100
+
101
+ export function Users({ users }: { users: User[] }) {
102
+ return <DataTable data={users} rowKey="id" columns={columns} features={features} />
103
+ }
104
+ ```
105
+
106
+ `<DataTable />` renders sort headers with `aria-sort`, a search input (Enter = `flushSearch`, Esc =
107
+ `clearSearch`), pagination, and Loading / Error / Empty states from `status` + `isInitialLoad`,
108
+ for the features installed (this package installs none by default). Pass `table={useDataTable(…)}`
109
+ to render a table you set up yourself, `components` to replace the search input, pager or states,
110
+ and style it through the `data-*` hooks (`data-status`, `data-initial-load`, `data-sort`,
111
+ `data-invalid`), or import the optional `@datakable/react/styles.css` (zero-specificity rules,
112
+ themed through `--dk-*` custom properties). A `cell` that throws renders `⚠` in that cell
113
+ (`DK_CALLBACK_FAILED`); so does a component it returns that throws while rendering — each such cell
114
+ has its own error boundary, and the other cells keep rendering (`DK_RENDER_FAILED`). A component
115
+ that throws elsewhere in the body shows the Error state with a retry.
116
+
117
+ ## SSR
118
+
119
+ `useDataTable` and `<DataTable />` render on the server: `initialState` applies there (client-mode
120
+ features filter, search and sort the HTML), and no async work starts. The fetcher's first request
121
+ and a `searchFn` for an initial query run after hydration (`status: 'pending'` until then, shown
122
+ as Loading by `<DataTable />`), unless `initialData` holds their result, in which case hydration
123
+ does not fetch again. A table that changed before the hydration commit reports
124
+ `DK_HYDRATION_MISMATCH`. Example:
125
+ [`datakable` SSR](https://github.com/Ink01101011/datakable/tree/main/packages/datakable#ssr).
126
+
127
+ ## License
128
+
129
+ MIT
package/dist/codes.cjs ADDED
@@ -0,0 +1,65 @@
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/codes.ts
21
+ var codes_exports = {};
22
+ __export(codes_exports, {
23
+ reactDiagnostics: () => reactDiagnostics
24
+ });
25
+ module.exports = __toCommonJS(codes_exports);
26
+ var import_core = require("@datakable/core");
27
+ var isFeatureOption = (option) => option.startsWith("features[");
28
+ var reactDiagnostics = process.env.NODE_ENV !== "production" ? [
29
+ (0, import_core.defineDiagnostic)({
30
+ code: "DK_UNSTABLE_COLUMNS",
31
+ level: "warn",
32
+ where: () => ({ kind: "option", path: "columns" }),
33
+ problem: (d) => `useDataTable received a new columns array with the same shape on ${d.renders} renders in a row (columns are compared by reference)`,
34
+ impact: () => "each new array rebuilds the column cache and re-runs the pipeline; in a re-render caused by the table itself, the columns the table already has are kept",
35
+ fix: () => [
36
+ "define the columns outside the component, or memoise them: useMemo(() => [...columns], [the values they read])",
37
+ "a new columns array is how you tell the table the columns changed (accessor / format / cell), so create one only when they do"
38
+ ]
39
+ }),
40
+ (0, import_core.defineDiagnostic)({
41
+ code: "DK_UNSTABLE_OPTION",
42
+ level: "warn",
43
+ where: (d) => ({ kind: "option", path: d.option }),
44
+ problem: (d) => `useDataTable received a new ${d.option} reference on ${d.renders} renders in a row`,
45
+ impact: (d) => d.option === "fetcher" ? "the table always calls the latest fetcher, but a new fetcher does not refetch: values it reads that are not table state do not reload the data" : d.option === "data" ? "each new array is ingested again (schema, data checks, pipeline); in a re-render caused by the table itself an array with equal rows is skipped" : isFeatureOption(d.option) ? `features are read once, when the table is created: the table keeps calling the ${d.option} of the first render (a stale closure)` : "each new rowKey function recomputes every row key",
46
+ fix: (d) => d.option === "fetcher" ? [
47
+ "call table.refetch() when a value the fetcher reads changes (or keep that value in a server-mode feature state, which refetches by itself)",
48
+ "wrap the fetcher in useCallback to silence this warning"
49
+ ] : d.option === "data" ? [
50
+ "memoise derived data: useMemo(() => rows.filter(...), [rows])",
51
+ "or keep the data in state and pass the same array until it changes"
52
+ ] : isFeatureOption(d.option) ? [
53
+ "create the features once: useMemo(() => [search({ searchFn })], []) or outside the component",
54
+ "read changing values inside the function through a ref (ref.current) instead of the render closure"
55
+ ] : [
56
+ "use a key path (rowKey: 'id') or a function defined outside the component",
57
+ "or wrap it in useCallback"
58
+ ]
59
+ })
60
+ ] : [];
61
+ // Annotate the CommonJS export names for ESM import in node:
62
+ 0 && (module.exports = {
63
+ reactDiagnostics
64
+ });
65
+ //# sourceMappingURL=codes.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/codes.ts"],"sourcesContent":["import { defineDiagnostic } from '@datakable/core'\n\ndeclare module '@datakable/core' {\n interface DiagnosticCatalog {\n DK_UNSTABLE_COLUMNS: {\n /** Consecutive renders that passed a new `columns` array with the same shape. */\n renders: number\n }\n DK_UNSTABLE_OPTION: {\n /** `data`, `fetcher`, `rowKey`, or a feature's function option: `features[2].searchFn`. */\n option: string\n /** Consecutive renders that passed a new reference. */\n renders: number\n }\n }\n}\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\nconst isFeatureOption = (option: string) => option.startsWith('features[')\n\n/**\n * Codes owned by `@datakable/react` (§8.3, react, dev only). Like core's dev checks, the\n * definitions exist only in development: the NODE_ENV check is written out here (not an imported\n * flag) so a consumer's bundler folds it while parsing and drops the text from production bundles\n * (§8.2). They are never emitted in production, so `datakable/messages` has no text for them.\n */\nexport const reactDiagnostics =\n process.env.NODE_ENV !== 'production'\n ? [\n defineDiagnostic({\n code: 'DK_UNSTABLE_COLUMNS',\n level: 'warn',\n where: () => ({ kind: 'option', path: 'columns' }),\n problem: (d) =>\n `useDataTable received a new columns array with the same shape on ${d.renders} renders ` +\n 'in a row (columns are compared by reference)',\n impact: () =>\n 'each new array rebuilds the column cache and re-runs the pipeline; in a re-render caused ' +\n 'by the table itself, the columns the table already has are kept',\n fix: () => [\n 'define the columns outside the component, or memoise them: ' +\n 'useMemo(() => [...columns], [the values they read])',\n 'a new columns array is how you tell the table the columns changed (accessor / format / ' +\n 'cell), so create one only when they do',\n ],\n }),\n defineDiagnostic({\n code: 'DK_UNSTABLE_OPTION',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: d.option }),\n problem: (d) =>\n `useDataTable received a new ${d.option} reference on ${d.renders} renders in a row`,\n impact: (d) =>\n d.option === 'fetcher'\n ? 'the table always calls the latest fetcher, but a new fetcher does not refetch: ' +\n 'values it reads that are not table state do not reload the data'\n : d.option === 'data'\n ? 'each new array is ingested again (schema, data checks, pipeline); in a re-render ' +\n 'caused by the table itself an array with equal rows is skipped'\n : isFeatureOption(d.option)\n ? 'features are read once, when the table is created: the table keeps calling the ' +\n `${d.option} of the first render (a stale closure)`\n : 'each new rowKey function recomputes every row key',\n fix: (d) =>\n d.option === 'fetcher'\n ? [\n 'call table.refetch() when a value the fetcher reads changes (or keep that value in ' +\n 'a server-mode feature state, which refetches by itself)',\n 'wrap the fetcher in useCallback to silence this warning',\n ]\n : d.option === 'data'\n ? [\n 'memoise derived data: useMemo(() => rows.filter(...), [rows])',\n 'or keep the data in state and pass the same array until it changes',\n ]\n : isFeatureOption(d.option)\n ? [\n 'create the features once: useMemo(() => [search({ searchFn })], []) or outside ' +\n 'the component',\n 'read changing values inside the function through a ref (ref.current) instead ' +\n 'of the render closure',\n ]\n : [\n \"use a key path (rowKey: 'id') or a function defined outside the component\",\n 'or wrap it in useCallback',\n ],\n }),\n ]\n : []\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiC;AAoBjC,IAAM,kBAAkB,CAAC,WAAmB,OAAO,WAAW,WAAW;AAQlE,IAAM,mBACX,QAAQ,IAAI,aAAa,eACrB;AAAA,MACE,8BAAiB;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,OAAO,EAAE,MAAM,UAAU,MAAM,UAAU;AAAA,IAChD,SAAS,CAAC,MACR,oEAAoE,EAAE,OAAO;AAAA,IAE/E,QAAQ,MACN;AAAA,IAEF,KAAK,MAAM;AAAA,MACT;AAAA,MAEA;AAAA,IAEF;AAAA,EACF,CAAC;AAAA,MACD,8BAAiB;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,OAAO;AAAA,IAChD,SAAS,CAAC,MACR,+BAA+B,EAAE,MAAM,iBAAiB,EAAE,OAAO;AAAA,IACnE,QAAQ,CAAC,MACP,EAAE,WAAW,YACT,mJAEA,EAAE,WAAW,SACX,oJAEA,gBAAgB,EAAE,MAAM,IACtB,kFACG,EAAE,MAAM,2CACX;AAAA,IACV,KAAK,CAAC,MACJ,EAAE,WAAW,YACT;AAAA,MACE;AAAA,MAEA;AAAA,IACF,IACA,EAAE,WAAW,SACX;AAAA,MACE;AAAA,MACA;AAAA,IACF,IACA,gBAAgB,EAAE,MAAM,IACtB;AAAA,MACE;AAAA,MAEA;AAAA,IAEF,IACA;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACZ,CAAC;AACH,IACA,CAAC;","names":[]}
package/dist/codes.js ADDED
@@ -0,0 +1,40 @@
1
+ // src/codes.ts
2
+ import { defineDiagnostic } from "@datakable/core";
3
+ var isFeatureOption = (option) => option.startsWith("features[");
4
+ var reactDiagnostics = process.env.NODE_ENV !== "production" ? [
5
+ defineDiagnostic({
6
+ code: "DK_UNSTABLE_COLUMNS",
7
+ level: "warn",
8
+ where: () => ({ kind: "option", path: "columns" }),
9
+ problem: (d) => `useDataTable received a new columns array with the same shape on ${d.renders} renders in a row (columns are compared by reference)`,
10
+ impact: () => "each new array rebuilds the column cache and re-runs the pipeline; in a re-render caused by the table itself, the columns the table already has are kept",
11
+ fix: () => [
12
+ "define the columns outside the component, or memoise them: useMemo(() => [...columns], [the values they read])",
13
+ "a new columns array is how you tell the table the columns changed (accessor / format / cell), so create one only when they do"
14
+ ]
15
+ }),
16
+ defineDiagnostic({
17
+ code: "DK_UNSTABLE_OPTION",
18
+ level: "warn",
19
+ where: (d) => ({ kind: "option", path: d.option }),
20
+ problem: (d) => `useDataTable received a new ${d.option} reference on ${d.renders} renders in a row`,
21
+ impact: (d) => d.option === "fetcher" ? "the table always calls the latest fetcher, but a new fetcher does not refetch: values it reads that are not table state do not reload the data" : d.option === "data" ? "each new array is ingested again (schema, data checks, pipeline); in a re-render caused by the table itself an array with equal rows is skipped" : isFeatureOption(d.option) ? `features are read once, when the table is created: the table keeps calling the ${d.option} of the first render (a stale closure)` : "each new rowKey function recomputes every row key",
22
+ fix: (d) => d.option === "fetcher" ? [
23
+ "call table.refetch() when a value the fetcher reads changes (or keep that value in a server-mode feature state, which refetches by itself)",
24
+ "wrap the fetcher in useCallback to silence this warning"
25
+ ] : d.option === "data" ? [
26
+ "memoise derived data: useMemo(() => rows.filter(...), [rows])",
27
+ "or keep the data in state and pass the same array until it changes"
28
+ ] : isFeatureOption(d.option) ? [
29
+ "create the features once: useMemo(() => [search({ searchFn })], []) or outside the component",
30
+ "read changing values inside the function through a ref (ref.current) instead of the render closure"
31
+ ] : [
32
+ "use a key path (rowKey: 'id') or a function defined outside the component",
33
+ "or wrap it in useCallback"
34
+ ]
35
+ })
36
+ ] : [];
37
+ export {
38
+ reactDiagnostics
39
+ };
40
+ //# sourceMappingURL=codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/codes.ts"],"sourcesContent":["import { defineDiagnostic } from '@datakable/core'\n\ndeclare module '@datakable/core' {\n interface DiagnosticCatalog {\n DK_UNSTABLE_COLUMNS: {\n /** Consecutive renders that passed a new `columns` array with the same shape. */\n renders: number\n }\n DK_UNSTABLE_OPTION: {\n /** `data`, `fetcher`, `rowKey`, or a feature's function option: `features[2].searchFn`. */\n option: string\n /** Consecutive renders that passed a new reference. */\n renders: number\n }\n }\n}\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\nconst isFeatureOption = (option: string) => option.startsWith('features[')\n\n/**\n * Codes owned by `@datakable/react` (§8.3, react, dev only). Like core's dev checks, the\n * definitions exist only in development: the NODE_ENV check is written out here (not an imported\n * flag) so a consumer's bundler folds it while parsing and drops the text from production bundles\n * (§8.2). They are never emitted in production, so `datakable/messages` has no text for them.\n */\nexport const reactDiagnostics =\n process.env.NODE_ENV !== 'production'\n ? [\n defineDiagnostic({\n code: 'DK_UNSTABLE_COLUMNS',\n level: 'warn',\n where: () => ({ kind: 'option', path: 'columns' }),\n problem: (d) =>\n `useDataTable received a new columns array with the same shape on ${d.renders} renders ` +\n 'in a row (columns are compared by reference)',\n impact: () =>\n 'each new array rebuilds the column cache and re-runs the pipeline; in a re-render caused ' +\n 'by the table itself, the columns the table already has are kept',\n fix: () => [\n 'define the columns outside the component, or memoise them: ' +\n 'useMemo(() => [...columns], [the values they read])',\n 'a new columns array is how you tell the table the columns changed (accessor / format / ' +\n 'cell), so create one only when they do',\n ],\n }),\n defineDiagnostic({\n code: 'DK_UNSTABLE_OPTION',\n level: 'warn',\n where: (d) => ({ kind: 'option', path: d.option }),\n problem: (d) =>\n `useDataTable received a new ${d.option} reference on ${d.renders} renders in a row`,\n impact: (d) =>\n d.option === 'fetcher'\n ? 'the table always calls the latest fetcher, but a new fetcher does not refetch: ' +\n 'values it reads that are not table state do not reload the data'\n : d.option === 'data'\n ? 'each new array is ingested again (schema, data checks, pipeline); in a re-render ' +\n 'caused by the table itself an array with equal rows is skipped'\n : isFeatureOption(d.option)\n ? 'features are read once, when the table is created: the table keeps calling the ' +\n `${d.option} of the first render (a stale closure)`\n : 'each new rowKey function recomputes every row key',\n fix: (d) =>\n d.option === 'fetcher'\n ? [\n 'call table.refetch() when a value the fetcher reads changes (or keep that value in ' +\n 'a server-mode feature state, which refetches by itself)',\n 'wrap the fetcher in useCallback to silence this warning',\n ]\n : d.option === 'data'\n ? [\n 'memoise derived data: useMemo(() => rows.filter(...), [rows])',\n 'or keep the data in state and pass the same array until it changes',\n ]\n : isFeatureOption(d.option)\n ? [\n 'create the features once: useMemo(() => [search({ searchFn })], []) or outside ' +\n 'the component',\n 'read changing values inside the function through a ref (ref.current) instead ' +\n 'of the render closure',\n ]\n : [\n \"use a key path (rowKey: 'id') or a function defined outside the component\",\n 'or wrap it in useCallback',\n ],\n }),\n ]\n : []\n"],"mappings":";AAAA,SAAS,wBAAwB;AAoBjC,IAAM,kBAAkB,CAAC,WAAmB,OAAO,WAAW,WAAW;AAQlE,IAAM,mBACX,QAAQ,IAAI,aAAa,eACrB;AAAA,EACE,iBAAiB;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,OAAO,EAAE,MAAM,UAAU,MAAM,UAAU;AAAA,IAChD,SAAS,CAAC,MACR,oEAAoE,EAAE,OAAO;AAAA,IAE/E,QAAQ,MACN;AAAA,IAEF,KAAK,MAAM;AAAA,MACT;AAAA,MAEA;AAAA,IAEF;AAAA,EACF,CAAC;AAAA,EACD,iBAAiB;AAAA,IACf,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,OAAO;AAAA,IAChD,SAAS,CAAC,MACR,+BAA+B,EAAE,MAAM,iBAAiB,EAAE,OAAO;AAAA,IACnE,QAAQ,CAAC,MACP,EAAE,WAAW,YACT,mJAEA,EAAE,WAAW,SACX,oJAEA,gBAAgB,EAAE,MAAM,IACtB,kFACG,EAAE,MAAM,2CACX;AAAA,IACV,KAAK,CAAC,MACJ,EAAE,WAAW,YACT;AAAA,MACE;AAAA,MAEA;AAAA,IACF,IACA,EAAE,WAAW,SACX;AAAA,MACE;AAAA,MACA;AAAA,IACF,IACA,gBAAgB,EAAE,MAAM,IACtB;AAAA,MACE;AAAA,MAEA;AAAA,IAEF,IACA;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACZ,CAAC;AACH,IACA,CAAC;","names":[]}