@tanstack/preact-table 9.0.0-alpha.33 → 9.0.0-alpha.34

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.
@@ -1,33 +1,8 @@
1
1
  let _tanstack_preact_store = require("@tanstack/preact-store");
2
2
 
3
3
  //#region src/Subscribe.ts
4
- /**
5
- * A Preact component that allows you to subscribe to the table state.
6
- *
7
- * This is useful for opting into state re-renders for specific parts of the table state.
8
- *
9
- * @example
10
- * ```tsx
11
- * // As a standalone component
12
- * <Subscribe table={table} selector={(state) => ({ rowSelection: state.rowSelection })}>
13
- * {({ rowSelection }) => (
14
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
15
- * )}
16
- * </Subscribe>
17
- * ```
18
- *
19
- * @example
20
- * ```tsx
21
- * // As table.Subscribe (table instance method)
22
- * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
23
- * {({ rowSelection }) => (
24
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
25
- * )}
26
- * </table.Subscribe>
27
- * ```
28
- */
29
4
  function Subscribe(props) {
30
- const selected = (0, _tanstack_preact_store.useSelector)(props.table.store, props.selector);
5
+ const selected = (0, _tanstack_preact_store.useSelector)("atom" in props ? props.atom : props.table.store, "atom" in props ? props.selector ?? ((x) => x) : props.selector, { compare: _tanstack_preact_store.shallow });
31
6
  return typeof props.children === "function" ? props.children(selected) : props.children;
32
7
  }
33
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"Subscribe.cjs","names":[],"sources":["../src/Subscribe.ts"],"sourcesContent":["import { useSelector } from '@tanstack/preact-store'\nimport type {\n NoInfer,\n RowData,\n Table,\n TableFeatures,\n TableState,\n} from '@tanstack/table-core'\nimport type { ComponentChildren } from 'preact'\n\nexport type SubscribeProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n> = {\n /**\n * The table instance to subscribe to. Required when using as a standalone component.\n * Not needed when using as `table.Subscribe`.\n */\n table: Table<TFeatures, TData>\n /**\n * A selector function that selects the part of the table state to subscribe to.\n * This allows for fine-grained reactivity by only re-rendering when the selected state changes.\n */\n selector: (state: NoInfer<TableState<TFeatures>>) => TSelected\n /**\n * The children to render. Can be a function that receives the selected state, or a Preact node.\n */\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * A Preact component that allows you to subscribe to the table state.\n *\n * This is useful for opting into state re-renders for specific parts of the table state.\n *\n * @example\n * ```tsx\n * // As a standalone component\n * <Subscribe table={table} selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => (\n * <div>Selected rows: {Object.keys(rowSelection).length}</div>\n * )}\n * </Subscribe>\n * ```\n *\n * @example\n * ```tsx\n * // As table.Subscribe (table instance method)\n * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => (\n * <div>Selected rows: {Object.keys(rowSelection).length}</div>\n * )}\n * </table.Subscribe>\n * ```\n */\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n>(props: SubscribeProps<TFeatures, TData, TSelected>): ComponentChildren {\n const selected = useSelector(props.table.store, props.selector)\n\n return typeof props.children === 'function'\n ? props.children(selected)\n : props.children\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,SAAgB,UAId,OAAuE;CACvE,MAAM,mDAAuB,MAAM,MAAM,OAAO,MAAM,SAAS;AAE/D,QAAO,OAAO,MAAM,aAAa,aAC7B,MAAM,SAAS,SAAS,GACxB,MAAM"}
1
+ {"version":3,"file":"Subscribe.cjs","names":["shallow"],"sources":["../src/Subscribe.ts"],"sourcesContent":["import { shallow, useSelector } from '@tanstack/preact-store'\nimport type { Atom, ReadonlyAtom } from '@tanstack/preact-store'\nimport type {\n RowData,\n Table,\n TableFeatures,\n TableState,\n} from '@tanstack/table-core'\nimport type { ComponentChildren } from 'preact'\n\n/**\n * Subscribe to `table.store` (full table state). The selector receives the full\n * {@link TableState}.\n */\nexport type SubscribePropsWithStore<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected,\n> = {\n table: Table<TFeatures, TData>\n /**\n * Select from full table state. Re-renders when the selected value changes\n * (shallow compare).\n *\n * Required in store mode so you never accidentally subscribe to the whole\n * store without an explicit projection.\n */\n selector: (state: TableState<TFeatures>) => TSelected\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to the full value of a slice atom (e.g. `table.atoms.rowSelection`).\n * Omitting `selector` is equivalent to the identity selector — children receive\n * `TAtomValue`.\n */\nexport type SubscribePropsWithAtomIdentity<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n> = {\n table: Table<TFeatures, TData>\n atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>\n selector?: undefined\n children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to a projected value from a slice atom.\n */\nexport type SubscribePropsWithAtomWithSelector<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n TSelected,\n> = {\n table: Table<TFeatures, TData>\n atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>\n selector: (state: TAtomValue) => TSelected\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to a single slice atom (identity or projected).\n */\nexport type SubscribePropsWithAtom<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n TSelected = TAtomValue,\n> =\n | SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>\n | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>\n\nexport type SubscribeProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = unknown,\n TAtomValue = unknown,\n> =\n | SubscribePropsWithStore<TFeatures, TData, TSelected>\n | SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>\n | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>\n\n/**\n * A Preact component that allows you to subscribe to the table state.\n *\n * For `table.Subscribe` from `useTable`, prefer that API it uses overloads so\n * JSX contextual typing works. This standalone component uses a union `props` type.\n */\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n>(\n props: SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>,\n): ComponentChildren\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n TSelected,\n>(\n props: SubscribePropsWithAtomWithSelector<\n TFeatures,\n TData,\n TAtomValue,\n TSelected\n >,\n): ComponentChildren\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected,\n>(\n props: SubscribePropsWithStore<TFeatures, TData, TSelected>,\n): ComponentChildren\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected,\n TAtomValue,\n>(\n props: SubscribeProps<TFeatures, TData, TSelected, TAtomValue>,\n): ComponentChildren {\n const source = 'atom' in props ? props.atom : props.table.store\n const selectFn =\n 'atom' in props ? (props.selector ?? ((x: unknown) => x)) : props.selector\n\n const selected = useSelector(\n source as never,\n selectFn as Parameters<typeof useSelector>[1],\n {\n compare: shallow,\n },\n ) as TSelected\n\n return typeof props.children === 'function'\n ? (props.children as (state: TSelected) => ComponentChildren)(selected)\n : props.children\n}\n"],"mappings":";;;AAqHA,SAAgB,UAMd,OACmB;CAKnB,MAAM,mDAJS,UAAU,QAAQ,MAAM,OAAO,MAAM,MAAM,OAExD,UAAU,QAAS,MAAM,cAAc,MAAe,KAAM,MAAM,UAKlE,EACE,SAASA,gCACV,CACF;AAED,QAAO,OAAO,MAAM,aAAa,aAC5B,MAAM,SAAqD,SAAS,GACrE,MAAM"}
@@ -1,49 +1,58 @@
1
- import { NoInfer, RowData, Table, TableFeatures, TableState } from "@tanstack/table-core";
1
+ import { RowData, Table, TableFeatures, TableState } from "@tanstack/table-core";
2
2
  import { ComponentChildren } from "preact";
3
+ import { Atom, ReadonlyAtom } from "@tanstack/preact-store";
3
4
 
4
5
  //#region src/Subscribe.d.ts
5
- type SubscribeProps<TFeatures extends TableFeatures, TData extends RowData, TSelected = {}> = {
6
- /**
7
- * The table instance to subscribe to. Required when using as a standalone component.
8
- * Not needed when using as `table.Subscribe`.
9
- */
6
+ /**
7
+ * Subscribe to `table.store` (full table state). The selector receives the full
8
+ * {@link TableState}.
9
+ */
10
+ type SubscribePropsWithStore<TFeatures extends TableFeatures, TData extends RowData, TSelected> = {
10
11
  table: Table<TFeatures, TData>;
11
12
  /**
12
- * A selector function that selects the part of the table state to subscribe to.
13
- * This allows for fine-grained reactivity by only re-rendering when the selected state changes.
14
- */
15
- selector: (state: NoInfer<TableState<TFeatures>>) => TSelected;
16
- /**
17
- * The children to render. Can be a function that receives the selected state, or a Preact node.
13
+ * Select from full table state. Re-renders when the selected value changes
14
+ * (shallow compare).
15
+ *
16
+ * Required in store mode so you never accidentally subscribe to the whole
17
+ * store without an explicit projection.
18
18
  */
19
+ selector: (state: TableState<TFeatures>) => TSelected;
19
20
  children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
20
21
  };
22
+ /**
23
+ * Subscribe to the full value of a slice atom (e.g. `table.atoms.rowSelection`).
24
+ * Omitting `selector` is equivalent to the identity selector — children receive
25
+ * `TAtomValue`.
26
+ */
27
+ type SubscribePropsWithAtomIdentity<TFeatures extends TableFeatures, TData extends RowData, TAtomValue> = {
28
+ table: Table<TFeatures, TData>;
29
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>;
30
+ selector?: undefined;
31
+ children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren;
32
+ };
33
+ /**
34
+ * Subscribe to a projected value from a slice atom.
35
+ */
36
+ type SubscribePropsWithAtomWithSelector<TFeatures extends TableFeatures, TData extends RowData, TAtomValue, TSelected> = {
37
+ table: Table<TFeatures, TData>;
38
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>;
39
+ selector: (state: TAtomValue) => TSelected;
40
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
41
+ };
42
+ /**
43
+ * Subscribe to a single slice atom (identity or projected).
44
+ */
45
+ type SubscribePropsWithAtom<TFeatures extends TableFeatures, TData extends RowData, TAtomValue, TSelected = TAtomValue> = SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue> | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>;
46
+ type SubscribeProps<TFeatures extends TableFeatures, TData extends RowData, TSelected = unknown, TAtomValue = unknown> = SubscribePropsWithStore<TFeatures, TData, TSelected> | SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue> | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>;
21
47
  /**
22
48
  * A Preact component that allows you to subscribe to the table state.
23
49
  *
24
- * This is useful for opting into state re-renders for specific parts of the table state.
25
- *
26
- * @example
27
- * ```tsx
28
- * // As a standalone component
29
- * <Subscribe table={table} selector={(state) => ({ rowSelection: state.rowSelection })}>
30
- * {({ rowSelection }) => (
31
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
32
- * )}
33
- * </Subscribe>
34
- * ```
35
- *
36
- * @example
37
- * ```tsx
38
- * // As table.Subscribe (table instance method)
39
- * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
40
- * {({ rowSelection }) => (
41
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
42
- * )}
43
- * </table.Subscribe>
44
- * ```
50
+ * For `table.Subscribe` from `useTable`, prefer that API it uses overloads so
51
+ * JSX contextual typing works. This standalone component uses a union `props` type.
45
52
  */
46
- declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TSelected = {}>(props: SubscribeProps<TFeatures, TData, TSelected>): ComponentChildren;
53
+ declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TAtomValue>(props: SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>): ComponentChildren;
54
+ declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TAtomValue, TSelected>(props: SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>): ComponentChildren;
55
+ declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TSelected>(props: SubscribePropsWithStore<TFeatures, TData, TSelected>): ComponentChildren;
47
56
  //#endregion
48
- export { Subscribe, SubscribeProps };
57
+ export { Subscribe, SubscribeProps, SubscribePropsWithAtom, SubscribePropsWithAtomIdentity, SubscribePropsWithAtomWithSelector, SubscribePropsWithStore };
49
58
  //# sourceMappingURL=Subscribe.d.cts.map
@@ -1,49 +1,58 @@
1
- import { NoInfer, RowData, Table, TableFeatures, TableState } from "@tanstack/table-core";
1
+ import { RowData, Table, TableFeatures, TableState } from "@tanstack/table-core";
2
+ import { Atom, ReadonlyAtom } from "@tanstack/preact-store";
2
3
  import { ComponentChildren } from "preact";
3
4
 
4
5
  //#region src/Subscribe.d.ts
5
- type SubscribeProps<TFeatures extends TableFeatures, TData extends RowData, TSelected = {}> = {
6
- /**
7
- * The table instance to subscribe to. Required when using as a standalone component.
8
- * Not needed when using as `table.Subscribe`.
9
- */
6
+ /**
7
+ * Subscribe to `table.store` (full table state). The selector receives the full
8
+ * {@link TableState}.
9
+ */
10
+ type SubscribePropsWithStore<TFeatures extends TableFeatures, TData extends RowData, TSelected> = {
10
11
  table: Table<TFeatures, TData>;
11
12
  /**
12
- * A selector function that selects the part of the table state to subscribe to.
13
- * This allows for fine-grained reactivity by only re-rendering when the selected state changes.
14
- */
15
- selector: (state: NoInfer<TableState<TFeatures>>) => TSelected;
16
- /**
17
- * The children to render. Can be a function that receives the selected state, or a Preact node.
13
+ * Select from full table state. Re-renders when the selected value changes
14
+ * (shallow compare).
15
+ *
16
+ * Required in store mode so you never accidentally subscribe to the whole
17
+ * store without an explicit projection.
18
18
  */
19
+ selector: (state: TableState<TFeatures>) => TSelected;
19
20
  children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
20
21
  };
22
+ /**
23
+ * Subscribe to the full value of a slice atom (e.g. `table.atoms.rowSelection`).
24
+ * Omitting `selector` is equivalent to the identity selector — children receive
25
+ * `TAtomValue`.
26
+ */
27
+ type SubscribePropsWithAtomIdentity<TFeatures extends TableFeatures, TData extends RowData, TAtomValue> = {
28
+ table: Table<TFeatures, TData>;
29
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>;
30
+ selector?: undefined;
31
+ children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren;
32
+ };
33
+ /**
34
+ * Subscribe to a projected value from a slice atom.
35
+ */
36
+ type SubscribePropsWithAtomWithSelector<TFeatures extends TableFeatures, TData extends RowData, TAtomValue, TSelected> = {
37
+ table: Table<TFeatures, TData>;
38
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>;
39
+ selector: (state: TAtomValue) => TSelected;
40
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
41
+ };
42
+ /**
43
+ * Subscribe to a single slice atom (identity or projected).
44
+ */
45
+ type SubscribePropsWithAtom<TFeatures extends TableFeatures, TData extends RowData, TAtomValue, TSelected = TAtomValue> = SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue> | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>;
46
+ type SubscribeProps<TFeatures extends TableFeatures, TData extends RowData, TSelected = unknown, TAtomValue = unknown> = SubscribePropsWithStore<TFeatures, TData, TSelected> | SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue> | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>;
21
47
  /**
22
48
  * A Preact component that allows you to subscribe to the table state.
23
49
  *
24
- * This is useful for opting into state re-renders for specific parts of the table state.
25
- *
26
- * @example
27
- * ```tsx
28
- * // As a standalone component
29
- * <Subscribe table={table} selector={(state) => ({ rowSelection: state.rowSelection })}>
30
- * {({ rowSelection }) => (
31
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
32
- * )}
33
- * </Subscribe>
34
- * ```
35
- *
36
- * @example
37
- * ```tsx
38
- * // As table.Subscribe (table instance method)
39
- * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
40
- * {({ rowSelection }) => (
41
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
42
- * )}
43
- * </table.Subscribe>
44
- * ```
50
+ * For `table.Subscribe` from `useTable`, prefer that API it uses overloads so
51
+ * JSX contextual typing works. This standalone component uses a union `props` type.
45
52
  */
46
- declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TSelected = {}>(props: SubscribeProps<TFeatures, TData, TSelected>): ComponentChildren;
53
+ declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TAtomValue>(props: SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>): ComponentChildren;
54
+ declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TAtomValue, TSelected>(props: SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>): ComponentChildren;
55
+ declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TSelected>(props: SubscribePropsWithStore<TFeatures, TData, TSelected>): ComponentChildren;
47
56
  //#endregion
48
- export { Subscribe, SubscribeProps };
57
+ export { Subscribe, SubscribeProps, SubscribePropsWithAtom, SubscribePropsWithAtomIdentity, SubscribePropsWithAtomWithSelector, SubscribePropsWithStore };
49
58
  //# sourceMappingURL=Subscribe.d.ts.map
package/dist/Subscribe.js CHANGED
@@ -1,33 +1,8 @@
1
- import { useSelector } from "@tanstack/preact-store";
1
+ import { shallow, useSelector } from "@tanstack/preact-store";
2
2
 
3
3
  //#region src/Subscribe.ts
4
- /**
5
- * A Preact component that allows you to subscribe to the table state.
6
- *
7
- * This is useful for opting into state re-renders for specific parts of the table state.
8
- *
9
- * @example
10
- * ```tsx
11
- * // As a standalone component
12
- * <Subscribe table={table} selector={(state) => ({ rowSelection: state.rowSelection })}>
13
- * {({ rowSelection }) => (
14
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
15
- * )}
16
- * </Subscribe>
17
- * ```
18
- *
19
- * @example
20
- * ```tsx
21
- * // As table.Subscribe (table instance method)
22
- * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
23
- * {({ rowSelection }) => (
24
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
25
- * )}
26
- * </table.Subscribe>
27
- * ```
28
- */
29
4
  function Subscribe(props) {
30
- const selected = useSelector(props.table.store, props.selector);
5
+ const selected = useSelector("atom" in props ? props.atom : props.table.store, "atom" in props ? props.selector ?? ((x) => x) : props.selector, { compare: shallow });
31
6
  return typeof props.children === "function" ? props.children(selected) : props.children;
32
7
  }
33
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"Subscribe.js","names":[],"sources":["../src/Subscribe.ts"],"sourcesContent":["import { useSelector } from '@tanstack/preact-store'\nimport type {\n NoInfer,\n RowData,\n Table,\n TableFeatures,\n TableState,\n} from '@tanstack/table-core'\nimport type { ComponentChildren } from 'preact'\n\nexport type SubscribeProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n> = {\n /**\n * The table instance to subscribe to. Required when using as a standalone component.\n * Not needed when using as `table.Subscribe`.\n */\n table: Table<TFeatures, TData>\n /**\n * A selector function that selects the part of the table state to subscribe to.\n * This allows for fine-grained reactivity by only re-rendering when the selected state changes.\n */\n selector: (state: NoInfer<TableState<TFeatures>>) => TSelected\n /**\n * The children to render. Can be a function that receives the selected state, or a Preact node.\n */\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * A Preact component that allows you to subscribe to the table state.\n *\n * This is useful for opting into state re-renders for specific parts of the table state.\n *\n * @example\n * ```tsx\n * // As a standalone component\n * <Subscribe table={table} selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => (\n * <div>Selected rows: {Object.keys(rowSelection).length}</div>\n * )}\n * </Subscribe>\n * ```\n *\n * @example\n * ```tsx\n * // As table.Subscribe (table instance method)\n * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => (\n * <div>Selected rows: {Object.keys(rowSelection).length}</div>\n * )}\n * </table.Subscribe>\n * ```\n */\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = {},\n>(props: SubscribeProps<TFeatures, TData, TSelected>): ComponentChildren {\n const selected = useSelector(props.table.store, props.selector)\n\n return typeof props.children === 'function'\n ? props.children(selected)\n : props.children\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,SAAgB,UAId,OAAuE;CACvE,MAAM,WAAW,YAAY,MAAM,MAAM,OAAO,MAAM,SAAS;AAE/D,QAAO,OAAO,MAAM,aAAa,aAC7B,MAAM,SAAS,SAAS,GACxB,MAAM"}
1
+ {"version":3,"file":"Subscribe.js","names":[],"sources":["../src/Subscribe.ts"],"sourcesContent":["import { shallow, useSelector } from '@tanstack/preact-store'\nimport type { Atom, ReadonlyAtom } from '@tanstack/preact-store'\nimport type {\n RowData,\n Table,\n TableFeatures,\n TableState,\n} from '@tanstack/table-core'\nimport type { ComponentChildren } from 'preact'\n\n/**\n * Subscribe to `table.store` (full table state). The selector receives the full\n * {@link TableState}.\n */\nexport type SubscribePropsWithStore<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected,\n> = {\n table: Table<TFeatures, TData>\n /**\n * Select from full table state. Re-renders when the selected value changes\n * (shallow compare).\n *\n * Required in store mode so you never accidentally subscribe to the whole\n * store without an explicit projection.\n */\n selector: (state: TableState<TFeatures>) => TSelected\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to the full value of a slice atom (e.g. `table.atoms.rowSelection`).\n * Omitting `selector` is equivalent to the identity selector — children receive\n * `TAtomValue`.\n */\nexport type SubscribePropsWithAtomIdentity<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n> = {\n table: Table<TFeatures, TData>\n atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>\n selector?: undefined\n children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to a projected value from a slice atom.\n */\nexport type SubscribePropsWithAtomWithSelector<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n TSelected,\n> = {\n table: Table<TFeatures, TData>\n atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>\n selector: (state: TAtomValue) => TSelected\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to a single slice atom (identity or projected).\n */\nexport type SubscribePropsWithAtom<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n TSelected = TAtomValue,\n> =\n | SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>\n | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>\n\nexport type SubscribeProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = unknown,\n TAtomValue = unknown,\n> =\n | SubscribePropsWithStore<TFeatures, TData, TSelected>\n | SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>\n | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>\n\n/**\n * A Preact component that allows you to subscribe to the table state.\n *\n * For `table.Subscribe` from `useTable`, prefer that API it uses overloads so\n * JSX contextual typing works. This standalone component uses a union `props` type.\n */\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n>(\n props: SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>,\n): ComponentChildren\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TAtomValue,\n TSelected,\n>(\n props: SubscribePropsWithAtomWithSelector<\n TFeatures,\n TData,\n TAtomValue,\n TSelected\n >,\n): ComponentChildren\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected,\n>(\n props: SubscribePropsWithStore<TFeatures, TData, TSelected>,\n): ComponentChildren\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected,\n TAtomValue,\n>(\n props: SubscribeProps<TFeatures, TData, TSelected, TAtomValue>,\n): ComponentChildren {\n const source = 'atom' in props ? props.atom : props.table.store\n const selectFn =\n 'atom' in props ? (props.selector ?? ((x: unknown) => x)) : props.selector\n\n const selected = useSelector(\n source as never,\n selectFn as Parameters<typeof useSelector>[1],\n {\n compare: shallow,\n },\n ) as TSelected\n\n return typeof props.children === 'function'\n ? (props.children as (state: TSelected) => ComponentChildren)(selected)\n : props.children\n}\n"],"mappings":";;;AAqHA,SAAgB,UAMd,OACmB;CAKnB,MAAM,WAAW,YAJF,UAAU,QAAQ,MAAM,OAAO,MAAM,MAAM,OAExD,UAAU,QAAS,MAAM,cAAc,MAAe,KAAM,MAAM,UAKlE,EACE,SAAS,SACV,CACF;AAED,QAAO,OAAO,MAAM,aAAa,aAC5B,MAAM,SAAqD,SAAS,GACrE,MAAM"}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { FlexRender, FlexRenderProps, Renderable, flexRender } from "./FlexRender.cjs";
2
- import { Subscribe, SubscribeProps } from "./Subscribe.cjs";
2
+ import { Subscribe, SubscribeProps, SubscribePropsWithAtom, SubscribePropsWithAtomIdentity, SubscribePropsWithAtomWithSelector, SubscribePropsWithStore } from "./Subscribe.cjs";
3
3
  import { PreactTable, useTable } from "./useTable.cjs";
4
4
  import { AppCellComponent, AppCellContext, AppCellPropsWithSelector, AppCellPropsWithoutSelector, AppColumnHelper, AppHeaderComponent, AppHeaderContext, AppHeaderPropsWithSelector, AppHeaderPropsWithoutSelector, AppPreactTable, AppTableComponent, AppTablePropsWithSelector, AppTablePropsWithoutSelector, CreateTableHookOptions, createTableHook } from "./createTableHook.cjs";
5
5
  export * from "@tanstack/table-core";
6
- export { AppCellComponent, AppCellContext, AppCellPropsWithSelector, AppCellPropsWithoutSelector, AppColumnHelper, AppHeaderComponent, AppHeaderContext, AppHeaderPropsWithSelector, AppHeaderPropsWithoutSelector, AppPreactTable, AppTableComponent, AppTablePropsWithSelector, AppTablePropsWithoutSelector, CreateTableHookOptions, FlexRender, FlexRenderProps, PreactTable, Renderable, Subscribe, SubscribeProps, createTableHook, flexRender, useTable };
6
+ export { AppCellComponent, AppCellContext, AppCellPropsWithSelector, AppCellPropsWithoutSelector, AppColumnHelper, AppHeaderComponent, AppHeaderContext, AppHeaderPropsWithSelector, AppHeaderPropsWithoutSelector, AppPreactTable, AppTableComponent, AppTablePropsWithSelector, AppTablePropsWithoutSelector, CreateTableHookOptions, FlexRender, FlexRenderProps, PreactTable, Renderable, Subscribe, SubscribeProps, SubscribePropsWithAtom, SubscribePropsWithAtomIdentity, SubscribePropsWithAtomWithSelector, SubscribePropsWithStore, createTableHook, flexRender, useTable };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { FlexRender, FlexRenderProps, Renderable, flexRender } from "./FlexRender.js";
2
- import { Subscribe, SubscribeProps } from "./Subscribe.js";
2
+ import { Subscribe, SubscribeProps, SubscribePropsWithAtom, SubscribePropsWithAtomIdentity, SubscribePropsWithAtomWithSelector, SubscribePropsWithStore } from "./Subscribe.js";
3
3
  import { PreactTable, useTable } from "./useTable.js";
4
4
  import { AppCellComponent, AppCellContext, AppCellPropsWithSelector, AppCellPropsWithoutSelector, AppColumnHelper, AppHeaderComponent, AppHeaderContext, AppHeaderPropsWithSelector, AppHeaderPropsWithoutSelector, AppPreactTable, AppTableComponent, AppTablePropsWithSelector, AppTablePropsWithoutSelector, CreateTableHookOptions, createTableHook } from "./createTableHook.js";
5
5
  export * from "@tanstack/table-core";
6
- export { AppCellComponent, AppCellContext, AppCellPropsWithSelector, AppCellPropsWithoutSelector, AppColumnHelper, AppHeaderComponent, AppHeaderContext, AppHeaderPropsWithSelector, AppHeaderPropsWithoutSelector, AppPreactTable, AppTableComponent, AppTablePropsWithSelector, AppTablePropsWithoutSelector, CreateTableHookOptions, FlexRender, FlexRenderProps, PreactTable, Renderable, Subscribe, SubscribeProps, createTableHook, flexRender, useTable };
6
+ export { AppCellComponent, AppCellContext, AppCellPropsWithSelector, AppCellPropsWithoutSelector, AppColumnHelper, AppHeaderComponent, AppHeaderContext, AppHeaderPropsWithSelector, AppHeaderPropsWithoutSelector, AppPreactTable, AppTableComponent, AppTablePropsWithSelector, AppTablePropsWithoutSelector, CreateTableHookOptions, FlexRender, FlexRenderProps, PreactTable, Renderable, Subscribe, SubscribeProps, SubscribePropsWithAtom, SubscribePropsWithAtomIdentity, SubscribePropsWithAtomWithSelector, SubscribePropsWithStore, createTableHook, flexRender, useTable };
@@ -0,0 +1,9 @@
1
+
2
+
3
+ var _tanstack_table_core_static_functions = require("@tanstack/table-core/static-functions");
4
+ Object.keys(_tanstack_table_core_static_functions).forEach(function (k) {
5
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
6
+ enumerable: true,
7
+ get: function () { return _tanstack_table_core_static_functions[k]; }
8
+ });
9
+ });
@@ -0,0 +1 @@
1
+ export * from "@tanstack/table-core/static-functions";
@@ -0,0 +1 @@
1
+ export * from "@tanstack/table-core/static-functions";
@@ -0,0 +1,3 @@
1
+ export * from "@tanstack/table-core/static-functions"
2
+
3
+ export { };
package/dist/useTable.cjs CHANGED
@@ -8,12 +8,12 @@ let preact_hooks = require("preact/hooks");
8
8
  function useTable(tableOptions, selector = () => ({})) {
9
9
  const [table] = (0, preact_hooks.useState)(() => {
10
10
  const tableInstance = (0, _tanstack_table_core.constructTable)(tableOptions);
11
- tableInstance.Subscribe = function SubscribeBound(props) {
11
+ tableInstance.Subscribe = ((props) => {
12
12
  return require_Subscribe.Subscribe({
13
13
  ...props,
14
14
  table: tableInstance
15
15
  });
16
- };
16
+ });
17
17
  tableInstance.FlexRender = require_FlexRender.FlexRender;
18
18
  return tableInstance;
19
19
  });
@@ -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 NoInfer,\n RowData,\n Table,\n TableFeatures,\n TableOptions,\n TableState,\n} from '@tanstack/table-core'\nimport type { ComponentChildren } from 'preact'\nimport type { FlexRenderProps } from './FlexRender'\nimport type { SubscribeProps } 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 * This is useful for opting into state re-renders for specific parts of the table state.\n *\n * @example\n * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => ( // important to include `{() => {()}}` syntax\n * <tr key={row.id}>\n * // render the row\n * </tr>\n * )}\n * </table.Subscribe>\n */\n Subscribe: <TSelected>(props: {\n selector: (state: NoInfer<TableState<TFeatures>>) => TSelected\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n }) => ComponentChildren\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 * @example\n * ```tsx\n * <table.FlexRender cell={cell} />\n * <table.FlexRender header={header} />\n * <table.FlexRender footer={footer} />\n * ```\n *\n * This replaces calling `flexRender` directly like this:\n * ```tsx\n * flexRender(cell.column.columnDef.cell, cell.getContext())\n * flexRender(header.column.columnDef.header, header.getContext())\n * flexRender(footer.column.columnDef.footer, footer.getContext())\n * ```\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 * @example\n * const table = useTable(options, (state) => ({ globalFilter: state.globalFilter })) // only globalFilter is part of the selected state\n *\n * console.log(table.state.globalFilter)\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 = function SubscribeBound<TSelected>(\n props: Omit<SubscribeProps<TFeatures, TData, TSelected>, 'table'>,\n ) {\n return Subscribe({ ...props, table: tableInstance })\n }\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":";;;;;;;AA4EA,SAAgB,SAKd,cACA,kBACG,EAAE,GACqC;CAC1C,MAAM,CAAC,0CAAwB;EAC7B,MAAM,yDAA+B,aAAa;AAMlD,gBAAc,YAAY,SAAS,eACjC,OACA;AACA,UAAOA,4BAAU;IAAE,GAAG;IAAO,OAAO;IAAe,CAAC;;AAGtD,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 { 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 `atom` to subscribe to a single slice atom 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 atom={table.atoms.rowSelection}>\n * {(rowSelection) => <div>...</div>}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe atom={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>\n * {() => <tr key={row.id}>...</tr>}\n * </table.Subscribe>\n */\n /**\n * Overloads (atom first, then store) so JSX contextual typing works for both modes.\n * Atom without `selector` is separate so children infer `TAtomValue` (identity projection).\n */\n Subscribe: {\n <TAtomValue>(props: {\n atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>\n selector?: undefined\n children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TAtomValue, TSubSelected>(props: {\n atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>\n selector: (state: TAtomValue) => 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":";;;;;;;AAmFA,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,53 +1,57 @@
1
1
  import { FlexRenderProps } from "./FlexRender.cjs";
2
- import { CellData, NoInfer, RowData, Table, TableFeatures, TableOptions, TableState } from "@tanstack/table-core";
2
+ import { SubscribePropsWithStore } from "./Subscribe.cjs";
3
+ import { CellData, RowData, Table, TableFeatures, TableOptions, TableState } from "@tanstack/table-core";
3
4
  import { ComponentChildren } from "preact";
5
+ import { Atom, ReadonlyAtom } from "@tanstack/preact-store";
4
6
 
5
7
  //#region src/useTable.d.ts
6
8
  type PreactTable<TFeatures extends TableFeatures, TData extends RowData, TSelected = {}> = Table<TFeatures, TData> & {
7
9
  /**
8
10
  * A Preact HOC (Higher Order Component) that allows you to subscribe to the table state.
9
11
  *
10
- * This is useful for opting into state re-renders for specific parts of the table state.
12
+ * Pass `atom` to subscribe to a single slice atom instead of the full `table.store`.
11
13
  *
12
14
  * @example
13
15
  * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
14
- * {({ rowSelection }) => ( // important to include `{() => {()}}` syntax
15
- * <tr key={row.id}>
16
- * // render the row
17
- * </tr>
16
+ * {({ rowSelection }) => (
17
+ * <tr key={row.id}>...</tr>
18
18
  * )}
19
19
  * </table.Subscribe>
20
+ *
21
+ * @example
22
+ * <table.Subscribe atom={table.atoms.rowSelection}>
23
+ * {(rowSelection) => <div>...</div>}
24
+ * </table.Subscribe>
25
+ *
26
+ * @example
27
+ * <table.Subscribe atom={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>
28
+ * {() => <tr key={row.id}>...</tr>}
29
+ * </table.Subscribe>
20
30
  */
21
- Subscribe: <TSelected>(props: {
22
- selector: (state: NoInfer<TableState<TFeatures>>) => TSelected;
23
- children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
24
- }) => ComponentChildren;
31
+ /**
32
+ * Overloads (atom first, then store) so JSX contextual typing works for both modes.
33
+ * Atom without `selector` is separate so children infer `TAtomValue` (identity projection).
34
+ */
35
+ Subscribe: {
36
+ <TAtomValue>(props: {
37
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>;
38
+ selector?: undefined;
39
+ children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren;
40
+ }): ComponentChildren;
41
+ <TAtomValue, TSubSelected>(props: {
42
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>;
43
+ selector: (state: TAtomValue) => TSubSelected;
44
+ children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren;
45
+ }): ComponentChildren;
46
+ <TSubSelected>(props: Omit<SubscribePropsWithStore<TFeatures, TData, TSubSelected>, 'table'>): ComponentChildren;
47
+ };
25
48
  /**
26
49
  * A Preact component that renders headers, cells, or footers with custom markup.
27
50
  * Use this utility component instead of manually calling flexRender.
28
- *
29
- * @example
30
- * ```tsx
31
- * <table.FlexRender cell={cell} />
32
- * <table.FlexRender header={header} />
33
- * <table.FlexRender footer={footer} />
34
- * ```
35
- *
36
- * This replaces calling `flexRender` directly like this:
37
- * ```tsx
38
- * flexRender(cell.column.columnDef.cell, cell.getContext())
39
- * flexRender(header.column.columnDef.header, header.getContext())
40
- * flexRender(footer.column.columnDef.footer, footer.getContext())
41
- * ```
42
51
  */
43
52
  FlexRender: <TValue extends CellData = CellData>(props: FlexRenderProps<TFeatures, TData, TValue>) => ComponentChildren;
44
53
  /**
45
54
  * 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`.
46
- *
47
- * @example
48
- * const table = useTable(options, (state) => ({ globalFilter: state.globalFilter })) // only globalFilter is part of the selected state
49
- *
50
- * console.log(table.state.globalFilter)
51
55
  */
52
56
  readonly state: Readonly<TSelected> & {
53
57
  columns: TableOptions<TFeatures, TData>['columns'];
@@ -1,5 +1,7 @@
1
1
  import { FlexRenderProps } from "./FlexRender.js";
2
- import { CellData, NoInfer, RowData, Table, TableFeatures, TableOptions, TableState } from "@tanstack/table-core";
2
+ import { SubscribePropsWithStore } from "./Subscribe.js";
3
+ import { CellData, RowData, Table, TableFeatures, TableOptions, TableState } from "@tanstack/table-core";
4
+ import { Atom, ReadonlyAtom } from "@tanstack/preact-store";
3
5
  import { ComponentChildren } from "preact";
4
6
 
5
7
  //#region src/useTable.d.ts
@@ -7,47 +9,49 @@ type PreactTable<TFeatures extends TableFeatures, TData extends RowData, TSelect
7
9
  /**
8
10
  * A Preact HOC (Higher Order Component) that allows you to subscribe to the table state.
9
11
  *
10
- * This is useful for opting into state re-renders for specific parts of the table state.
12
+ * Pass `atom` to subscribe to a single slice atom instead of the full `table.store`.
11
13
  *
12
14
  * @example
13
15
  * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
14
- * {({ rowSelection }) => ( // important to include `{() => {()}}` syntax
15
- * <tr key={row.id}>
16
- * // render the row
17
- * </tr>
16
+ * {({ rowSelection }) => (
17
+ * <tr key={row.id}>...</tr>
18
18
  * )}
19
19
  * </table.Subscribe>
20
+ *
21
+ * @example
22
+ * <table.Subscribe atom={table.atoms.rowSelection}>
23
+ * {(rowSelection) => <div>...</div>}
24
+ * </table.Subscribe>
25
+ *
26
+ * @example
27
+ * <table.Subscribe atom={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>
28
+ * {() => <tr key={row.id}>...</tr>}
29
+ * </table.Subscribe>
20
30
  */
21
- Subscribe: <TSelected>(props: {
22
- selector: (state: NoInfer<TableState<TFeatures>>) => TSelected;
23
- children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
24
- }) => ComponentChildren;
31
+ /**
32
+ * Overloads (atom first, then store) so JSX contextual typing works for both modes.
33
+ * Atom without `selector` is separate so children infer `TAtomValue` (identity projection).
34
+ */
35
+ Subscribe: {
36
+ <TAtomValue>(props: {
37
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>;
38
+ selector?: undefined;
39
+ children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren;
40
+ }): ComponentChildren;
41
+ <TAtomValue, TSubSelected>(props: {
42
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>;
43
+ selector: (state: TAtomValue) => TSubSelected;
44
+ children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren;
45
+ }): ComponentChildren;
46
+ <TSubSelected>(props: Omit<SubscribePropsWithStore<TFeatures, TData, TSubSelected>, 'table'>): ComponentChildren;
47
+ };
25
48
  /**
26
49
  * A Preact component that renders headers, cells, or footers with custom markup.
27
50
  * Use this utility component instead of manually calling flexRender.
28
- *
29
- * @example
30
- * ```tsx
31
- * <table.FlexRender cell={cell} />
32
- * <table.FlexRender header={header} />
33
- * <table.FlexRender footer={footer} />
34
- * ```
35
- *
36
- * This replaces calling `flexRender` directly like this:
37
- * ```tsx
38
- * flexRender(cell.column.columnDef.cell, cell.getContext())
39
- * flexRender(header.column.columnDef.header, header.getContext())
40
- * flexRender(footer.column.columnDef.footer, footer.getContext())
41
- * ```
42
51
  */
43
52
  FlexRender: <TValue extends CellData = CellData>(props: FlexRenderProps<TFeatures, TData, TValue>) => ComponentChildren;
44
53
  /**
45
54
  * 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`.
46
- *
47
- * @example
48
- * const table = useTable(options, (state) => ({ globalFilter: state.globalFilter })) // only globalFilter is part of the selected state
49
- *
50
- * console.log(table.state.globalFilter)
51
55
  */
52
56
  readonly state: Readonly<TSelected> & {
53
57
  columns: TableOptions<TFeatures, TData>['columns'];
package/dist/useTable.js CHANGED
@@ -8,12 +8,12 @@ import { useMemo, useState } from "preact/hooks";
8
8
  function useTable(tableOptions, selector = () => ({})) {
9
9
  const [table] = useState(() => {
10
10
  const tableInstance = constructTable(tableOptions);
11
- tableInstance.Subscribe = function SubscribeBound(props) {
11
+ tableInstance.Subscribe = ((props) => {
12
12
  return Subscribe({
13
13
  ...props,
14
14
  table: tableInstance
15
15
  });
16
- };
16
+ });
17
17
  tableInstance.FlexRender = FlexRender;
18
18
  return tableInstance;
19
19
  });
@@ -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 NoInfer,\n RowData,\n Table,\n TableFeatures,\n TableOptions,\n TableState,\n} from '@tanstack/table-core'\nimport type { ComponentChildren } from 'preact'\nimport type { FlexRenderProps } from './FlexRender'\nimport type { SubscribeProps } 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 * This is useful for opting into state re-renders for specific parts of the table state.\n *\n * @example\n * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>\n * {({ rowSelection }) => ( // important to include `{() => {()}}` syntax\n * <tr key={row.id}>\n * // render the row\n * </tr>\n * )}\n * </table.Subscribe>\n */\n Subscribe: <TSelected>(props: {\n selector: (state: NoInfer<TableState<TFeatures>>) => TSelected\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n }) => ComponentChildren\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 * @example\n * ```tsx\n * <table.FlexRender cell={cell} />\n * <table.FlexRender header={header} />\n * <table.FlexRender footer={footer} />\n * ```\n *\n * This replaces calling `flexRender` directly like this:\n * ```tsx\n * flexRender(cell.column.columnDef.cell, cell.getContext())\n * flexRender(header.column.columnDef.header, header.getContext())\n * flexRender(footer.column.columnDef.footer, footer.getContext())\n * ```\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 * @example\n * const table = useTable(options, (state) => ({ globalFilter: state.globalFilter })) // only globalFilter is part of the selected state\n *\n * console.log(table.state.globalFilter)\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 = function SubscribeBound<TSelected>(\n props: Omit<SubscribeProps<TFeatures, TData, TSelected>, 'table'>,\n ) {\n return Subscribe({ ...props, table: tableInstance })\n }\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":";;;;;;;AA4EA,SAAgB,SAKd,cACA,kBACG,EAAE,GACqC;CAC1C,MAAM,CAAC,SAAS,eAAe;EAC7B,MAAM,gBAAgB,eAAe,aAAa;AAMlD,gBAAc,YAAY,SAAS,eACjC,OACA;AACA,UAAO,UAAU;IAAE,GAAG;IAAO,OAAO;IAAe,CAAC;;AAGtD,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 { 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 `atom` to subscribe to a single slice atom 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 atom={table.atoms.rowSelection}>\n * {(rowSelection) => <div>...</div>}\n * </table.Subscribe>\n *\n * @example\n * <table.Subscribe atom={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>\n * {() => <tr key={row.id}>...</tr>}\n * </table.Subscribe>\n */\n /**\n * Overloads (atom first, then store) so JSX contextual typing works for both modes.\n * Atom without `selector` is separate so children infer `TAtomValue` (identity projection).\n */\n Subscribe: {\n <TAtomValue>(props: {\n atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>\n selector?: undefined\n children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren\n }): ComponentChildren\n <TAtomValue, TSubSelected>(props: {\n atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>\n selector: (state: TAtomValue) => 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":";;;;;;;AAmFA,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/preact-table",
3
- "version": "9.0.0-alpha.33",
3
+ "version": "9.0.0-alpha.34",
4
4
  "description": "Headless UI for building powerful tables & datagrids for Preact.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -29,6 +29,10 @@
29
29
  "import": "./dist/index.js",
30
30
  "require": "./dist/index.cjs"
31
31
  },
32
+ "./static-functions": {
33
+ "import": "./dist/static-functions.js",
34
+ "require": "./dist/static-functions.cjs"
35
+ },
32
36
  "./package.json": "./package.json"
33
37
  },
34
38
  "sideEffects": false,
@@ -41,7 +45,7 @@
41
45
  ],
42
46
  "dependencies": {
43
47
  "@tanstack/preact-store": "^0.13.0",
44
- "@tanstack/table-core": "9.0.0-alpha.33"
48
+ "@tanstack/table-core": "9.0.0-alpha.34"
45
49
  },
46
50
  "devDependencies": {
47
51
  "@preact/preset-vite": "^2.10.5",
package/src/Subscribe.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { useSelector } from '@tanstack/preact-store'
1
+ import { shallow, useSelector } from '@tanstack/preact-store'
2
+ import type { Atom, ReadonlyAtom } from '@tanstack/preact-store'
2
3
  import type {
3
- NoInfer,
4
4
  RowData,
5
5
  Table,
6
6
  TableFeatures,
@@ -8,60 +8,134 @@ import type {
8
8
  } from '@tanstack/table-core'
9
9
  import type { ComponentChildren } from 'preact'
10
10
 
11
- export type SubscribeProps<
11
+ /**
12
+ * Subscribe to `table.store` (full table state). The selector receives the full
13
+ * {@link TableState}.
14
+ */
15
+ export type SubscribePropsWithStore<
12
16
  TFeatures extends TableFeatures,
13
17
  TData extends RowData,
14
- TSelected = {},
18
+ TSelected,
15
19
  > = {
16
- /**
17
- * The table instance to subscribe to. Required when using as a standalone component.
18
- * Not needed when using as `table.Subscribe`.
19
- */
20
20
  table: Table<TFeatures, TData>
21
21
  /**
22
- * A selector function that selects the part of the table state to subscribe to.
23
- * This allows for fine-grained reactivity by only re-rendering when the selected state changes.
24
- */
25
- selector: (state: NoInfer<TableState<TFeatures>>) => TSelected
26
- /**
27
- * The children to render. Can be a function that receives the selected state, or a Preact node.
22
+ * Select from full table state. Re-renders when the selected value changes
23
+ * (shallow compare).
24
+ *
25
+ * Required in store mode so you never accidentally subscribe to the whole
26
+ * store without an explicit projection.
28
27
  */
28
+ selector: (state: TableState<TFeatures>) => TSelected
29
29
  children: ((state: TSelected) => ComponentChildren) | ComponentChildren
30
30
  }
31
31
 
32
+ /**
33
+ * Subscribe to the full value of a slice atom (e.g. `table.atoms.rowSelection`).
34
+ * Omitting `selector` is equivalent to the identity selector — children receive
35
+ * `TAtomValue`.
36
+ */
37
+ export type SubscribePropsWithAtomIdentity<
38
+ TFeatures extends TableFeatures,
39
+ TData extends RowData,
40
+ TAtomValue,
41
+ > = {
42
+ table: Table<TFeatures, TData>
43
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>
44
+ selector?: undefined
45
+ children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren
46
+ }
47
+
48
+ /**
49
+ * Subscribe to a projected value from a slice atom.
50
+ */
51
+ export type SubscribePropsWithAtomWithSelector<
52
+ TFeatures extends TableFeatures,
53
+ TData extends RowData,
54
+ TAtomValue,
55
+ TSelected,
56
+ > = {
57
+ table: Table<TFeatures, TData>
58
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>
59
+ selector: (state: TAtomValue) => TSelected
60
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren
61
+ }
62
+
63
+ /**
64
+ * Subscribe to a single slice atom (identity or projected).
65
+ */
66
+ export type SubscribePropsWithAtom<
67
+ TFeatures extends TableFeatures,
68
+ TData extends RowData,
69
+ TAtomValue,
70
+ TSelected = TAtomValue,
71
+ > =
72
+ | SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>
73
+ | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>
74
+
75
+ export type SubscribeProps<
76
+ TFeatures extends TableFeatures,
77
+ TData extends RowData,
78
+ TSelected = unknown,
79
+ TAtomValue = unknown,
80
+ > =
81
+ | SubscribePropsWithStore<TFeatures, TData, TSelected>
82
+ | SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>
83
+ | SubscribePropsWithAtomWithSelector<TFeatures, TData, TAtomValue, TSelected>
84
+
32
85
  /**
33
86
  * A Preact component that allows you to subscribe to the table state.
34
87
  *
35
- * This is useful for opting into state re-renders for specific parts of the table state.
36
- *
37
- * @example
38
- * ```tsx
39
- * // As a standalone component
40
- * <Subscribe table={table} selector={(state) => ({ rowSelection: state.rowSelection })}>
41
- * {({ rowSelection }) => (
42
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
43
- * )}
44
- * </Subscribe>
45
- * ```
46
- *
47
- * @example
48
- * ```tsx
49
- * // As table.Subscribe (table instance method)
50
- * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
51
- * {({ rowSelection }) => (
52
- * <div>Selected rows: {Object.keys(rowSelection).length}</div>
53
- * )}
54
- * </table.Subscribe>
55
- * ```
88
+ * For `table.Subscribe` from `useTable`, prefer that API it uses overloads so
89
+ * JSX contextual typing works. This standalone component uses a union `props` type.
56
90
  */
57
91
  export function Subscribe<
58
92
  TFeatures extends TableFeatures,
59
93
  TData extends RowData,
60
- TSelected = {},
61
- >(props: SubscribeProps<TFeatures, TData, TSelected>): ComponentChildren {
62
- const selected = useSelector(props.table.store, props.selector)
94
+ TAtomValue,
95
+ >(
96
+ props: SubscribePropsWithAtomIdentity<TFeatures, TData, TAtomValue>,
97
+ ): ComponentChildren
98
+ export function Subscribe<
99
+ TFeatures extends TableFeatures,
100
+ TData extends RowData,
101
+ TAtomValue,
102
+ TSelected,
103
+ >(
104
+ props: SubscribePropsWithAtomWithSelector<
105
+ TFeatures,
106
+ TData,
107
+ TAtomValue,
108
+ TSelected
109
+ >,
110
+ ): ComponentChildren
111
+ export function Subscribe<
112
+ TFeatures extends TableFeatures,
113
+ TData extends RowData,
114
+ TSelected,
115
+ >(
116
+ props: SubscribePropsWithStore<TFeatures, TData, TSelected>,
117
+ ): ComponentChildren
118
+ export function Subscribe<
119
+ TFeatures extends TableFeatures,
120
+ TData extends RowData,
121
+ TSelected,
122
+ TAtomValue,
123
+ >(
124
+ props: SubscribeProps<TFeatures, TData, TSelected, TAtomValue>,
125
+ ): ComponentChildren {
126
+ const source = 'atom' in props ? props.atom : props.table.store
127
+ const selectFn =
128
+ 'atom' in props ? (props.selector ?? ((x: unknown) => x)) : props.selector
129
+
130
+ const selected = useSelector(
131
+ source as never,
132
+ selectFn as Parameters<typeof useSelector>[1],
133
+ {
134
+ compare: shallow,
135
+ },
136
+ ) as TSelected
63
137
 
64
138
  return typeof props.children === 'function'
65
- ? props.children(selected)
139
+ ? (props.children as (state: TSelected) => ComponentChildren)(selected)
66
140
  : props.children
67
141
  }
@@ -0,0 +1 @@
1
+ export * from '@tanstack/table-core/static-functions'
package/src/useTable.ts CHANGED
@@ -5,16 +5,16 @@ import { FlexRender } from './FlexRender'
5
5
  import { Subscribe } from './Subscribe'
6
6
  import type {
7
7
  CellData,
8
- NoInfer,
9
8
  RowData,
10
9
  Table,
11
10
  TableFeatures,
12
11
  TableOptions,
13
12
  TableState,
14
13
  } from '@tanstack/table-core'
14
+ import type { Atom, ReadonlyAtom } from '@tanstack/preact-store'
15
15
  import type { ComponentChildren } from 'preact'
16
16
  import type { FlexRenderProps } from './FlexRender'
17
- import type { SubscribeProps } from './Subscribe'
17
+ import type { SubscribePropsWithStore } from './Subscribe'
18
18
 
19
19
  export type PreactTable<
20
20
  TFeatures extends TableFeatures,
@@ -24,49 +24,56 @@ export type PreactTable<
24
24
  /**
25
25
  * A Preact HOC (Higher Order Component) that allows you to subscribe to the table state.
26
26
  *
27
- * This is useful for opting into state re-renders for specific parts of the table state.
27
+ * Pass `atom` to subscribe to a single slice atom instead of the full `table.store`.
28
28
  *
29
29
  * @example
30
30
  * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
31
- * {({ rowSelection }) => ( // important to include `{() => {()}}` syntax
32
- * <tr key={row.id}>
33
- * // render the row
34
- * </tr>
31
+ * {({ rowSelection }) => (
32
+ * <tr key={row.id}>...</tr>
35
33
  * )}
36
34
  * </table.Subscribe>
35
+ *
36
+ * @example
37
+ * <table.Subscribe atom={table.atoms.rowSelection}>
38
+ * {(rowSelection) => <div>...</div>}
39
+ * </table.Subscribe>
40
+ *
41
+ * @example
42
+ * <table.Subscribe atom={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>
43
+ * {() => <tr key={row.id}>...</tr>}
44
+ * </table.Subscribe>
37
45
  */
38
- Subscribe: <TSelected>(props: {
39
- selector: (state: NoInfer<TableState<TFeatures>>) => TSelected
40
- children: ((state: TSelected) => ComponentChildren) | ComponentChildren
41
- }) => ComponentChildren
46
+ /**
47
+ * Overloads (atom first, then store) so JSX contextual typing works for both modes.
48
+ * Atom without `selector` is separate so children infer `TAtomValue` (identity projection).
49
+ */
50
+ Subscribe: {
51
+ <TAtomValue>(props: {
52
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>
53
+ selector?: undefined
54
+ children: ((state: TAtomValue) => ComponentChildren) | ComponentChildren
55
+ }): ComponentChildren
56
+ <TAtomValue, TSubSelected>(props: {
57
+ atom: Atom<TAtomValue> | ReadonlyAtom<TAtomValue>
58
+ selector: (state: TAtomValue) => TSubSelected
59
+ children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren
60
+ }): ComponentChildren
61
+ <TSubSelected>(
62
+ props: Omit<
63
+ SubscribePropsWithStore<TFeatures, TData, TSubSelected>,
64
+ 'table'
65
+ >,
66
+ ): ComponentChildren
67
+ }
42
68
  /**
43
69
  * A Preact component that renders headers, cells, or footers with custom markup.
44
70
  * Use this utility component instead of manually calling flexRender.
45
- *
46
- * @example
47
- * ```tsx
48
- * <table.FlexRender cell={cell} />
49
- * <table.FlexRender header={header} />
50
- * <table.FlexRender footer={footer} />
51
- * ```
52
- *
53
- * This replaces calling `flexRender` directly like this:
54
- * ```tsx
55
- * flexRender(cell.column.columnDef.cell, cell.getContext())
56
- * flexRender(header.column.columnDef.header, header.getContext())
57
- * flexRender(footer.column.columnDef.footer, footer.getContext())
58
- * ```
59
71
  */
60
72
  FlexRender: <TValue extends CellData = CellData>(
61
73
  props: FlexRenderProps<TFeatures, TData, TValue>,
62
74
  ) => ComponentChildren
63
75
  /**
64
76
  * 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`.
65
- *
66
- * @example
67
- * const table = useTable(options, (state) => ({ globalFilter: state.globalFilter })) // only globalFilter is part of the selected state
68
- *
69
- * console.log(table.state.globalFilter)
70
77
  */
71
78
  readonly state: Readonly<TSelected> & {
72
79
  columns: TableOptions<TFeatures, TData>['columns']
@@ -90,11 +97,12 @@ export function useTable<
90
97
  TSelected
91
98
  >
92
99
 
93
- tableInstance.Subscribe = function SubscribeBound<TSelected>(
94
- props: Omit<SubscribeProps<TFeatures, TData, TSelected>, 'table'>,
95
- ) {
96
- return Subscribe({ ...props, table: tableInstance })
97
- }
100
+ tableInstance.Subscribe = ((props: any) => {
101
+ return Subscribe({
102
+ ...props,
103
+ table: tableInstance,
104
+ })
105
+ }) as PreactTable<TFeatures, TData, TSelected>['Subscribe']
98
106
 
99
107
  tableInstance.FlexRender = FlexRender
100
108