@tanstack/preact-table 9.0.0-alpha.40 → 9.0.0-alpha.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/useTable.cjs CHANGED
@@ -3,11 +3,18 @@ const require_Subscribe = require('./Subscribe.cjs');
3
3
  let _tanstack_table_core = require("@tanstack/table-core");
4
4
  let _tanstack_preact_store = require("@tanstack/preact-store");
5
5
  let preact_hooks = require("preact/hooks");
6
+ let _tanstack_table_core_reactivity = require("@tanstack/table-core/reactivity");
6
7
 
7
8
  //#region src/useTable.ts
8
9
  function useTable(tableOptions, selector = () => ({})) {
9
10
  const [table] = (0, preact_hooks.useState)(() => {
10
- const tableInstance = (0, _tanstack_table_core.constructTable)(tableOptions);
11
+ const tableInstance = (0, _tanstack_table_core.constructTable)({
12
+ ...tableOptions,
13
+ _features: {
14
+ coreReativityFeature: (0, _tanstack_table_core_reactivity.constructReactivityBindings)(),
15
+ ...tableOptions._features
16
+ }
17
+ });
11
18
  tableInstance.Subscribe = ((props) => {
12
19
  return require_Subscribe.Subscribe({
13
20
  ...props,
@@ -17,20 +24,23 @@ function useTable(tableOptions, selector = () => ({})) {
17
24
  tableInstance.FlexRender = require_FlexRender.FlexRender;
18
25
  return tableInstance;
19
26
  });
20
- table.setOptions((prev) => ({
21
- ...prev,
22
- ...tableOptions
23
- }));
24
- const selectorWithDataAndColumns = (state) => ({
25
- columns: tableOptions.columns,
26
- data: tableOptions.data,
27
- ...selector(state)
28
- });
29
- const state = (0, _tanstack_preact_store.useSelector)(table.store, selectorWithDataAndColumns, { compare: _tanstack_preact_store.shallow });
27
+ (0, preact_hooks.useEffect)(() => {
28
+ table.setOptions((prev) => ({
29
+ ...prev,
30
+ ...tableOptions
31
+ }));
32
+ }, [table, tableOptions]);
33
+ const state = (0, _tanstack_preact_store.useSelector)(table.store, selector, { compare: _tanstack_preact_store.shallow });
34
+ const options = (0, _tanstack_preact_store.useSelector)(table.optionsStore, (options) => options, { compare: _tanstack_preact_store.shallow });
30
35
  return (0, preact_hooks.useMemo)(() => ({
31
36
  ...table,
37
+ options,
38
+ state
39
+ }), [
40
+ table,
41
+ options,
32
42
  state
33
- }), [state, table]);
43
+ ]);
34
44
  }
35
45
 
36
46
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"useTable.cjs","names":["Subscribe","FlexRender","shallow"],"sources":["../src/useTable.ts"],"sourcesContent":["import { useMemo, useState } from 'preact/hooks'\nimport { constructTable } from '@tanstack/table-core'\nimport { shallow, useSelector } from '@tanstack/preact-store'\nimport { FlexRender } from './FlexRender'\nimport { Subscribe } from './Subscribe'\nimport type {\n CellData,\n RowData,\n Table,\n TableFeatures,\n TableOptions,\n TableState,\n} from '@tanstack/table-core'\nimport type { Atom, ReadonlyAtom } from '@tanstack/preact-store'\nimport type { ComponentChildren } from 'preact'\nimport type { FlexRenderProps } from './FlexRender'\nimport type { SubscribePropsWithStore } from './Subscribe'\n\nexport type PreactTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n> = Table<TFeatures, TData> & {\n /**\n * A Preact HOC (Higher Order Component) that allows you to subscribe to the table state.\n *\n * Pass `source` to subscribe to a single atom or store (e.g. `table.atoms.rowSelection`\n * or `table.optionsStore`) instead of the full `table.store`.\n *\n * @example\n * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => (\n * <tr key={row.id}>...</tr>\n * )}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe source={table.atoms.rowSelection}>\n * {(rowSelection) => <div>...</div>}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe source={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>\n * {() => <tr key={row.id}>...</tr>}\n * </table.Subscribe>\n */\n /**\n * Overloads (source first, then store) so JSX contextual typing works for both modes.\n * Source without `selector` is separate so children infer `TSourceValue` (identity projection).\n */\n Subscribe: {\n <TSourceValue>(props: {\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector?: undefined\n children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TSourceValue, TSubSelected>(props: {\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector: (state: TSourceValue) => TSubSelected\n children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TSubSelected>(\n props: Omit<\n SubscribePropsWithStore<TFeatures, TData, TSubSelected>,\n 'table'\n >,\n ): ComponentChildren\n }\n /**\n * A Preact component that renders headers, cells, or footers with custom markup.\n * Use this utility component instead of manually calling flexRender.\n */\n FlexRender: <TValue extends CellData = CellData>(\n props: FlexRenderProps<TFeatures, TData, TValue>,\n ) => ComponentChildren\n /**\n * The selected state of the table. This state may not match the structure of `table.store.state` because it is selected by the `selector` function that you pass as the 2nd argument to `useTable`.\n */\n readonly state: Readonly<TSelected> & {\n columns: TableOptions<TFeatures, TData>['columns']\n data: TableOptions<TFeatures, TData>['data']\n }\n}\n\nexport function useTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n>(\n tableOptions: TableOptions<TFeatures, TData>,\n selector: (state: TableState<TFeatures>) => TSelected = () =>\n ({}) as TSelected,\n): PreactTable<TFeatures, TData, TSelected> {\n const [table] = useState(() => {\n const tableInstance = constructTable(tableOptions) as PreactTable<\n TFeatures,\n TData,\n TSelected\n >\n\n tableInstance.Subscribe = ((props: any) => {\n return Subscribe({\n ...props,\n table: tableInstance,\n })\n }) as PreactTable<TFeatures, TData, TSelected>['Subscribe']\n\n tableInstance.FlexRender = FlexRender\n\n return tableInstance\n })\n\n // sync table options on every render\n table.setOptions((prev) => ({\n ...prev,\n ...tableOptions,\n }))\n\n const selectorWithDataAndColumns = (state: TableState<TFeatures>) => ({\n columns: tableOptions.columns,\n data: tableOptions.data,\n ...selector(state),\n })\n\n const state = useSelector(table.store, selectorWithDataAndColumns, {\n compare: shallow,\n })\n\n return useMemo(\n () => ({\n ...table,\n state,\n }),\n [state, table],\n ) as PreactTable<TFeatures, TData, TSelected>\n}\n"],"mappings":";;;;;;;AAoFA,SAAgB,SAKd,cACA,kBACG,EAAE,GACqC;CAC1C,MAAM,CAAC,0CAAwB;EAC7B,MAAM,yDAA+B,aAAa;AAMlD,gBAAc,cAAc,UAAe;AACzC,UAAOA,4BAAU;IACf,GAAG;IACH,OAAO;IACR,CAAC;;AAGJ,gBAAc,aAAaC;AAE3B,SAAO;GACP;AAGF,OAAM,YAAY,UAAU;EAC1B,GAAG;EACH,GAAG;EACJ,EAAE;CAEH,MAAM,8BAA8B,WAAkC;EACpE,SAAS,aAAa;EACtB,MAAM,aAAa;EACnB,GAAG,SAAS,MAAM;EACnB;CAED,MAAM,gDAAoB,MAAM,OAAO,4BAA4B,EACjE,SAASC,gCACV,CAAC;AAEF,yCACS;EACL,GAAG;EACH;EACD,GACD,CAAC,OAAO,MAAM,CACf"}
1
+ {"version":3,"file":"useTable.cjs","names":["Subscribe","FlexRender","shallow"],"sources":["../src/useTable.ts"],"sourcesContent":["import { useEffect, useMemo, useState } from 'preact/hooks'\nimport { constructTable } from '@tanstack/table-core'\nimport { shallow, useSelector } from '@tanstack/preact-store'\nimport { constructReactivityBindings } from '@tanstack/table-core/reactivity'\nimport { FlexRender } from './FlexRender'\nimport { Subscribe } from './Subscribe'\n// import { preactReactivity } from './reactivity'\nimport type {\n CellData,\n RowData,\n Table,\n TableFeatures,\n TableOptions,\n TableState,\n} from '@tanstack/table-core'\nimport type { Atom, ReadonlyAtom } from '@tanstack/preact-store'\nimport type { ComponentChildren } from 'preact'\nimport type { FlexRenderProps } from './FlexRender'\nimport type { SubscribePropsWithStore } from './Subscribe'\n\nexport type PreactTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n> = Table<TFeatures, TData> & {\n /**\n * A Preact HOC (Higher Order Component) that allows you to subscribe to the table state.\n *\n * Pass `source` to subscribe to a single atom or store (e.g. `table.atoms.rowSelection`\n * or `table.optionsStore`) instead of the full `table.store`.\n *\n * @example\n * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => (\n * <tr key={row.id}>...</tr>\n * )}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe source={table.atoms.rowSelection}>\n * {(rowSelection) => <div>...</div>}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe source={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>\n * {() => <tr key={row.id}>...</tr>}\n * </table.Subscribe>\n */\n /**\n * Overloads (source first, then store) so JSX contextual typing works for both modes.\n * Source without `selector` is separate so children infer `TSourceValue` (identity projection).\n */\n Subscribe: {\n <TSourceValue>(props: {\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector?: undefined\n children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TSourceValue, TSubSelected>(props: {\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector: (state: TSourceValue) => TSubSelected\n children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TSubSelected>(\n props: Omit<\n SubscribePropsWithStore<TFeatures, TData, TSubSelected>,\n 'table'\n >,\n ): ComponentChildren\n }\n /**\n * A Preact component that renders headers, cells, or footers with custom markup.\n * Use this utility component instead of manually calling flexRender.\n */\n FlexRender: <TValue extends CellData = CellData>(\n props: FlexRenderProps<TFeatures, TData, TValue>,\n ) => ComponentChildren\n /**\n * The selected state of the table. This state may not match the structure of `table.store.state` because it is selected by the `selector` function that you pass as the 2nd argument to `useTable`.\n */\n readonly state: Readonly<TSelected> & {\n columns: TableOptions<TFeatures, TData>['columns']\n data: TableOptions<TFeatures, TData>['data']\n }\n}\n\nexport function useTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n>(\n tableOptions: TableOptions<TFeatures, TData>,\n selector: (state: TableState<TFeatures>) => TSelected = () =>\n ({}) as TSelected,\n): PreactTable<TFeatures, TData, TSelected> {\n const [table] = useState(() => {\n const tableInstance = constructTable({\n ...tableOptions,\n _features: {\n coreReativityFeature: constructReactivityBindings(), // preactReactivity() currently causes infinite re-renders\n ...tableOptions._features,\n },\n }) as PreactTable<TFeatures, TData, TSelected>\n\n tableInstance.Subscribe = ((props: any) => {\n return Subscribe({\n ...props,\n table: tableInstance,\n })\n }) as PreactTable<TFeatures, TData, TSelected>['Subscribe']\n\n tableInstance.FlexRender = FlexRender\n\n return tableInstance\n })\n\n useEffect(() => {\n table.setOptions((prev) => ({\n ...prev,\n ...tableOptions,\n }))\n }, [table, tableOptions])\n\n const state = useSelector(table.store, selector, { compare: shallow })\n const options = useSelector(table.optionsStore, (options) => options, {\n compare: shallow,\n })\n\n return useMemo(\n () => ({\n ...table,\n options,\n state,\n }),\n [table, options, state],\n ) as PreactTable<TFeatures, TData, TSelected>\n}\n"],"mappings":";;;;;;;;AAsFA,SAAgB,SAKd,cACA,kBACG,EAAE,GACqC;CAC1C,MAAM,CAAC,0CAAwB;EAC7B,MAAM,yDAA+B;GACnC,GAAG;GACH,WAAW;IACT,wFAAmD;IACnD,GAAG,aAAa;IACjB;GACF,CAAC;AAEF,gBAAc,cAAc,UAAe;AACzC,UAAOA,4BAAU;IACf,GAAG;IACH,OAAO;IACR,CAAC;;AAGJ,gBAAc,aAAaC;AAE3B,SAAO;GACP;AAEF,mCAAgB;AACd,QAAM,YAAY,UAAU;GAC1B,GAAG;GACH,GAAG;GACJ,EAAE;IACF,CAAC,OAAO,aAAa,CAAC;CAEzB,MAAM,gDAAoB,MAAM,OAAO,UAAU,EAAE,SAASC,gCAAS,CAAC;CACtE,MAAM,kDAAsB,MAAM,eAAe,YAAY,SAAS,EACpE,SAASA,gCACV,CAAC;AAEF,yCACS;EACL,GAAG;EACH;EACA;EACD,GACD;EAAC;EAAO;EAAS;EAAM,CACxB"}
package/dist/useTable.js CHANGED
@@ -2,12 +2,19 @@ import { FlexRender } from "./FlexRender.js";
2
2
  import { Subscribe } from "./Subscribe.js";
3
3
  import { constructTable } from "@tanstack/table-core";
4
4
  import { shallow, useSelector } from "@tanstack/preact-store";
5
- import { useMemo, useState } from "preact/hooks";
5
+ import { useEffect, useMemo, useState } from "preact/hooks";
6
+ import { constructReactivityBindings } from "@tanstack/table-core/reactivity";
6
7
 
7
8
  //#region src/useTable.ts
8
9
  function useTable(tableOptions, selector = () => ({})) {
9
10
  const [table] = useState(() => {
10
- const tableInstance = constructTable(tableOptions);
11
+ const tableInstance = constructTable({
12
+ ...tableOptions,
13
+ _features: {
14
+ coreReativityFeature: constructReactivityBindings(),
15
+ ...tableOptions._features
16
+ }
17
+ });
11
18
  tableInstance.Subscribe = ((props) => {
12
19
  return Subscribe({
13
20
  ...props,
@@ -17,20 +24,23 @@ function useTable(tableOptions, selector = () => ({})) {
17
24
  tableInstance.FlexRender = FlexRender;
18
25
  return tableInstance;
19
26
  });
20
- table.setOptions((prev) => ({
21
- ...prev,
22
- ...tableOptions
23
- }));
24
- const selectorWithDataAndColumns = (state) => ({
25
- columns: tableOptions.columns,
26
- data: tableOptions.data,
27
- ...selector(state)
28
- });
29
- const state = useSelector(table.store, selectorWithDataAndColumns, { compare: shallow });
27
+ useEffect(() => {
28
+ table.setOptions((prev) => ({
29
+ ...prev,
30
+ ...tableOptions
31
+ }));
32
+ }, [table, tableOptions]);
33
+ const state = useSelector(table.store, selector, { compare: shallow });
34
+ const options = useSelector(table.optionsStore, (options) => options, { compare: shallow });
30
35
  return useMemo(() => ({
31
36
  ...table,
37
+ options,
38
+ state
39
+ }), [
40
+ table,
41
+ options,
32
42
  state
33
- }), [state, table]);
43
+ ]);
34
44
  }
35
45
 
36
46
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"useTable.js","names":[],"sources":["../src/useTable.ts"],"sourcesContent":["import { useMemo, useState } from 'preact/hooks'\nimport { constructTable } from '@tanstack/table-core'\nimport { shallow, useSelector } from '@tanstack/preact-store'\nimport { FlexRender } from './FlexRender'\nimport { Subscribe } from './Subscribe'\nimport type {\n CellData,\n RowData,\n Table,\n TableFeatures,\n TableOptions,\n TableState,\n} from '@tanstack/table-core'\nimport type { Atom, ReadonlyAtom } from '@tanstack/preact-store'\nimport type { ComponentChildren } from 'preact'\nimport type { FlexRenderProps } from './FlexRender'\nimport type { SubscribePropsWithStore } from './Subscribe'\n\nexport type PreactTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n> = Table<TFeatures, TData> & {\n /**\n * A Preact HOC (Higher Order Component) that allows you to subscribe to the table state.\n *\n * Pass `source` to subscribe to a single atom or store (e.g. `table.atoms.rowSelection`\n * or `table.optionsStore`) instead of the full `table.store`.\n *\n * @example\n * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => (\n * <tr key={row.id}>...</tr>\n * )}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe source={table.atoms.rowSelection}>\n * {(rowSelection) => <div>...</div>}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe source={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>\n * {() => <tr key={row.id}>...</tr>}\n * </table.Subscribe>\n */\n /**\n * Overloads (source first, then store) so JSX contextual typing works for both modes.\n * Source without `selector` is separate so children infer `TSourceValue` (identity projection).\n */\n Subscribe: {\n <TSourceValue>(props: {\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector?: undefined\n children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TSourceValue, TSubSelected>(props: {\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector: (state: TSourceValue) => TSubSelected\n children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TSubSelected>(\n props: Omit<\n SubscribePropsWithStore<TFeatures, TData, TSubSelected>,\n 'table'\n >,\n ): ComponentChildren\n }\n /**\n * A Preact component that renders headers, cells, or footers with custom markup.\n * Use this utility component instead of manually calling flexRender.\n */\n FlexRender: <TValue extends CellData = CellData>(\n props: FlexRenderProps<TFeatures, TData, TValue>,\n ) => ComponentChildren\n /**\n * The selected state of the table. This state may not match the structure of `table.store.state` because it is selected by the `selector` function that you pass as the 2nd argument to `useTable`.\n */\n readonly state: Readonly<TSelected> & {\n columns: TableOptions<TFeatures, TData>['columns']\n data: TableOptions<TFeatures, TData>['data']\n }\n}\n\nexport function useTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n>(\n tableOptions: TableOptions<TFeatures, TData>,\n selector: (state: TableState<TFeatures>) => TSelected = () =>\n ({}) as TSelected,\n): PreactTable<TFeatures, TData, TSelected> {\n const [table] = useState(() => {\n const tableInstance = constructTable(tableOptions) as PreactTable<\n TFeatures,\n TData,\n TSelected\n >\n\n tableInstance.Subscribe = ((props: any) => {\n return Subscribe({\n ...props,\n table: tableInstance,\n })\n }) as PreactTable<TFeatures, TData, TSelected>['Subscribe']\n\n tableInstance.FlexRender = FlexRender\n\n return tableInstance\n })\n\n // sync table options on every render\n table.setOptions((prev) => ({\n ...prev,\n ...tableOptions,\n }))\n\n const selectorWithDataAndColumns = (state: TableState<TFeatures>) => ({\n columns: tableOptions.columns,\n data: tableOptions.data,\n ...selector(state),\n })\n\n const state = useSelector(table.store, selectorWithDataAndColumns, {\n compare: shallow,\n })\n\n return useMemo(\n () => ({\n ...table,\n state,\n }),\n [state, table],\n ) as PreactTable<TFeatures, TData, TSelected>\n}\n"],"mappings":";;;;;;;AAoFA,SAAgB,SAKd,cACA,kBACG,EAAE,GACqC;CAC1C,MAAM,CAAC,SAAS,eAAe;EAC7B,MAAM,gBAAgB,eAAe,aAAa;AAMlD,gBAAc,cAAc,UAAe;AACzC,UAAO,UAAU;IACf,GAAG;IACH,OAAO;IACR,CAAC;;AAGJ,gBAAc,aAAa;AAE3B,SAAO;GACP;AAGF,OAAM,YAAY,UAAU;EAC1B,GAAG;EACH,GAAG;EACJ,EAAE;CAEH,MAAM,8BAA8B,WAAkC;EACpE,SAAS,aAAa;EACtB,MAAM,aAAa;EACnB,GAAG,SAAS,MAAM;EACnB;CAED,MAAM,QAAQ,YAAY,MAAM,OAAO,4BAA4B,EACjE,SAAS,SACV,CAAC;AAEF,QAAO,eACE;EACL,GAAG;EACH;EACD,GACD,CAAC,OAAO,MAAM,CACf"}
1
+ {"version":3,"file":"useTable.js","names":[],"sources":["../src/useTable.ts"],"sourcesContent":["import { useEffect, useMemo, useState } from 'preact/hooks'\nimport { constructTable } from '@tanstack/table-core'\nimport { shallow, useSelector } from '@tanstack/preact-store'\nimport { constructReactivityBindings } from '@tanstack/table-core/reactivity'\nimport { FlexRender } from './FlexRender'\nimport { Subscribe } from './Subscribe'\n// import { preactReactivity } from './reactivity'\nimport type {\n CellData,\n RowData,\n Table,\n TableFeatures,\n TableOptions,\n TableState,\n} from '@tanstack/table-core'\nimport type { Atom, ReadonlyAtom } from '@tanstack/preact-store'\nimport type { ComponentChildren } from 'preact'\nimport type { FlexRenderProps } from './FlexRender'\nimport type { SubscribePropsWithStore } from './Subscribe'\n\nexport type PreactTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n> = Table<TFeatures, TData> & {\n /**\n * A Preact HOC (Higher Order Component) that allows you to subscribe to the table state.\n *\n * Pass `source` to subscribe to a single atom or store (e.g. `table.atoms.rowSelection`\n * or `table.optionsStore`) instead of the full `table.store`.\n *\n * @example\n * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => (\n * <tr key={row.id}>...</tr>\n * )}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe source={table.atoms.rowSelection}>\n * {(rowSelection) => <div>...</div>}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe source={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>\n * {() => <tr key={row.id}>...</tr>}\n * </table.Subscribe>\n */\n /**\n * Overloads (source first, then store) so JSX contextual typing works for both modes.\n * Source without `selector` is separate so children infer `TSourceValue` (identity projection).\n */\n Subscribe: {\n <TSourceValue>(props: {\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector?: undefined\n children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TSourceValue, TSubSelected>(props: {\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector: (state: TSourceValue) => TSubSelected\n children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TSubSelected>(\n props: Omit<\n SubscribePropsWithStore<TFeatures, TData, TSubSelected>,\n 'table'\n >,\n ): ComponentChildren\n }\n /**\n * A Preact component that renders headers, cells, or footers with custom markup.\n * Use this utility component instead of manually calling flexRender.\n */\n FlexRender: <TValue extends CellData = CellData>(\n props: FlexRenderProps<TFeatures, TData, TValue>,\n ) => ComponentChildren\n /**\n * The selected state of the table. This state may not match the structure of `table.store.state` because it is selected by the `selector` function that you pass as the 2nd argument to `useTable`.\n */\n readonly state: Readonly<TSelected> & {\n columns: TableOptions<TFeatures, TData>['columns']\n data: TableOptions<TFeatures, TData>['data']\n }\n}\n\nexport function useTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n>(\n tableOptions: TableOptions<TFeatures, TData>,\n selector: (state: TableState<TFeatures>) => TSelected = () =>\n ({}) as TSelected,\n): PreactTable<TFeatures, TData, TSelected> {\n const [table] = useState(() => {\n const tableInstance = constructTable({\n ...tableOptions,\n _features: {\n coreReativityFeature: constructReactivityBindings(), // preactReactivity() currently causes infinite re-renders\n ...tableOptions._features,\n },\n }) as PreactTable<TFeatures, TData, TSelected>\n\n tableInstance.Subscribe = ((props: any) => {\n return Subscribe({\n ...props,\n table: tableInstance,\n })\n }) as PreactTable<TFeatures, TData, TSelected>['Subscribe']\n\n tableInstance.FlexRender = FlexRender\n\n return tableInstance\n })\n\n useEffect(() => {\n table.setOptions((prev) => ({\n ...prev,\n ...tableOptions,\n }))\n }, [table, tableOptions])\n\n const state = useSelector(table.store, selector, { compare: shallow })\n const options = useSelector(table.optionsStore, (options) => options, {\n compare: shallow,\n })\n\n return useMemo(\n () => ({\n ...table,\n options,\n state,\n }),\n [table, options, state],\n ) as PreactTable<TFeatures, TData, TSelected>\n}\n"],"mappings":";;;;;;;;AAsFA,SAAgB,SAKd,cACA,kBACG,EAAE,GACqC;CAC1C,MAAM,CAAC,SAAS,eAAe;EAC7B,MAAM,gBAAgB,eAAe;GACnC,GAAG;GACH,WAAW;IACT,sBAAsB,6BAA6B;IACnD,GAAG,aAAa;IACjB;GACF,CAAC;AAEF,gBAAc,cAAc,UAAe;AACzC,UAAO,UAAU;IACf,GAAG;IACH,OAAO;IACR,CAAC;;AAGJ,gBAAc,aAAa;AAE3B,SAAO;GACP;AAEF,iBAAgB;AACd,QAAM,YAAY,UAAU;GAC1B,GAAG;GACH,GAAG;GACJ,EAAE;IACF,CAAC,OAAO,aAAa,CAAC;CAEzB,MAAM,QAAQ,YAAY,MAAM,OAAO,UAAU,EAAE,SAAS,SAAS,CAAC;CACtE,MAAM,UAAU,YAAY,MAAM,eAAe,YAAY,SAAS,EACpE,SAAS,SACV,CAAC;AAEF,QAAO,eACE;EACL,GAAG;EACH;EACA;EACD,GACD;EAAC;EAAO;EAAS;EAAM,CACxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/preact-table",
3
- "version": "9.0.0-alpha.40",
3
+ "version": "9.0.0-alpha.42",
4
4
  "description": "Headless UI for building powerful tables & datagrids for Preact.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -48,8 +48,9 @@
48
48
  "src"
49
49
  ],
50
50
  "dependencies": {
51
+ "@preact/signals": "^2.9.0",
51
52
  "@tanstack/preact-store": "^0.13.0",
52
- "@tanstack/table-core": "9.0.0-alpha.39"
53
+ "@tanstack/table-core": "9.0.0-alpha.42"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@preact/preset-vite": "^2.10.5",
@@ -0,0 +1,63 @@
1
+ // TOTO - re-explore preact signals for reactivity
2
+ import { batch, computed, signal, untracked } from '@preact/signals'
3
+ import type {
4
+ TableAtomOptions,
5
+ TableReactivityBindings,
6
+ } from '@tanstack/table-core/reactivity'
7
+ import type { Atom, Observer, ReadonlyAtom } from '@tanstack/preact-store'
8
+
9
+ function observerToCallback<T>(
10
+ observerOrNext: Observer<T> | ((value: T) => void),
11
+ ): (value: T) => void {
12
+ return typeof observerOrNext === 'function'
13
+ ? observerOrNext
14
+ : (value) => observerOrNext.next?.(value)
15
+ }
16
+
17
+ function signalToReadonlyAtom<T>(source: {
18
+ value: T
19
+ subscribe: (observer: (value: T) => void) => () => void
20
+ }): ReadonlyAtom<T> {
21
+ return Object.assign(source, {
22
+ get: () => source.value,
23
+ subscribe: ((observerOrNext: Observer<T> | ((value: T) => void)) => {
24
+ const unsubscribe = source.subscribe(observerToCallback(observerOrNext))
25
+ return { unsubscribe }
26
+ }) as ReadonlyAtom<T>['subscribe'],
27
+ })
28
+ }
29
+
30
+ function signalToWritableAtom<T>(source: {
31
+ value: T
32
+ subscribe: (observer: (value: T) => void) => () => void
33
+ }): Atom<T> {
34
+ return Object.assign(source, {
35
+ set: (updater: T | ((prevVal: T) => T)) => {
36
+ source.value =
37
+ typeof updater === 'function'
38
+ ? (updater as (prevVal: T) => T)(source.value)
39
+ : updater
40
+ },
41
+ get: () => source.value,
42
+ subscribe: ((observerOrNext: Observer<T> | ((value: T) => void)) => {
43
+ const unsubscribe = source.subscribe(observerToCallback(observerOrNext))
44
+ return { unsubscribe }
45
+ }) as Atom<T>['subscribe'],
46
+ })
47
+ }
48
+
49
+ export function preactReactivity(): TableReactivityBindings {
50
+ return {
51
+ createReadonlyAtom: <T>(fn: () => T, _options?: TableAtomOptions<T>) => {
52
+ return signalToReadonlyAtom(computed(fn))
53
+ },
54
+ createWritableAtom: <T>(
55
+ value: T,
56
+ _options?: TableAtomOptions<T>,
57
+ ): Atom<T> => {
58
+ return signalToWritableAtom(signal(value))
59
+ },
60
+ untrack: untracked,
61
+ batch: batch,
62
+ }
63
+ }
package/src/useTable.ts CHANGED
@@ -1,8 +1,10 @@
1
- import { useMemo, useState } from 'preact/hooks'
1
+ import { useEffect, useMemo, useState } from 'preact/hooks'
2
2
  import { constructTable } from '@tanstack/table-core'
3
3
  import { shallow, useSelector } from '@tanstack/preact-store'
4
+ import { constructReactivityBindings } from '@tanstack/table-core/reactivity'
4
5
  import { FlexRender } from './FlexRender'
5
6
  import { Subscribe } from './Subscribe'
7
+ // import { preactReactivity } from './reactivity'
6
8
  import type {
7
9
  CellData,
8
10
  RowData,
@@ -92,11 +94,13 @@ export function useTable<
92
94
  ({}) as TSelected,
93
95
  ): PreactTable<TFeatures, TData, TSelected> {
94
96
  const [table] = useState(() => {
95
- const tableInstance = constructTable(tableOptions) as PreactTable<
96
- TFeatures,
97
- TData,
98
- TSelected
99
- >
97
+ const tableInstance = constructTable({
98
+ ...tableOptions,
99
+ _features: {
100
+ coreReativityFeature: constructReactivityBindings(), // preactReactivity() currently causes infinite re-renders
101
+ ...tableOptions._features,
102
+ },
103
+ }) as PreactTable<TFeatures, TData, TSelected>
100
104
 
101
105
  tableInstance.Subscribe = ((props: any) => {
102
106
  return Subscribe({
@@ -110,27 +114,24 @@ export function useTable<
110
114
  return tableInstance
111
115
  })
112
116
 
113
- // sync table options on every render
114
- table.setOptions((prev) => ({
115
- ...prev,
116
- ...tableOptions,
117
- }))
117
+ useEffect(() => {
118
+ table.setOptions((prev) => ({
119
+ ...prev,
120
+ ...tableOptions,
121
+ }))
122
+ }, [table, tableOptions])
118
123
 
119
- const selectorWithDataAndColumns = (state: TableState<TFeatures>) => ({
120
- columns: tableOptions.columns,
121
- data: tableOptions.data,
122
- ...selector(state),
123
- })
124
-
125
- const state = useSelector(table.store, selectorWithDataAndColumns, {
124
+ const state = useSelector(table.store, selector, { compare: shallow })
125
+ const options = useSelector(table.optionsStore, (options) => options, {
126
126
  compare: shallow,
127
127
  })
128
128
 
129
129
  return useMemo(
130
130
  () => ({
131
131
  ...table,
132
+ options,
132
133
  state,
133
134
  }),
134
- [state, table],
135
+ [table, options, state],
135
136
  ) as PreactTable<TFeatures, TData, TSelected>
136
137
  }