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

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)("source" in props ? props.source : props.table.store, "source" 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 source (e.g. `table.atoms.rowSelection` or\n * `table.optionsStore`). Omitting `selector` is equivalent to the identity\n * selector children receive `TSourceValue`.\n */\nexport type SubscribePropsWithSourceIdentity<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSourceValue,\n> = {\n table: Table<TFeatures, TData>\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector?: undefined\n children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to a projected value from a source (atom or store).\n */\nexport type SubscribePropsWithSourceWithSelector<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSourceValue,\n TSelected,\n> = {\n table: Table<TFeatures, TData>\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector: (state: TSourceValue) => TSelected\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to a single source atom or store (identity or projected).\n */\nexport type SubscribePropsWithSource<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSourceValue,\n TSelected = TSourceValue,\n> =\n | SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>\n | SubscribePropsWithSourceWithSelector<\n TFeatures,\n TData,\n TSourceValue,\n TSelected\n >\n\nexport type SubscribeProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = unknown,\n TSourceValue = unknown,\n> =\n | SubscribePropsWithStore<TFeatures, TData, TSelected>\n | SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>\n | SubscribePropsWithSourceWithSelector<\n TFeatures,\n TData,\n TSourceValue,\n TSelected\n >\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 TSourceValue,\n>(\n props: SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>,\n): ComponentChildren\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSourceValue,\n TSelected,\n>(\n props: SubscribePropsWithSourceWithSelector<\n TFeatures,\n TData,\n TSourceValue,\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 TSourceValue,\n>(\n props: SubscribeProps<TFeatures, TData, TSelected, TSourceValue>,\n): ComponentChildren {\n const source = 'source' in props ? props.source : props.table.store\n const selectFn =\n 'source' 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":";;;AA+HA,SAAgB,UAMd,OACmB;CAKnB,MAAM,mDAJS,YAAY,QAAQ,MAAM,SAAS,MAAM,MAAM,OAE5D,YAAY,QAAS,MAAM,cAAc,MAAe,KAAM,MAAM,UAKpE,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 source (e.g. `table.atoms.rowSelection` or
24
+ * `table.optionsStore`). Omitting `selector` is equivalent to the identity
25
+ * selector — children receive `TSourceValue`.
26
+ */
27
+ type SubscribePropsWithSourceIdentity<TFeatures extends TableFeatures, TData extends RowData, TSourceValue> = {
28
+ table: Table<TFeatures, TData>;
29
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>;
30
+ selector?: undefined;
31
+ children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren;
32
+ };
33
+ /**
34
+ * Subscribe to a projected value from a source (atom or store).
35
+ */
36
+ type SubscribePropsWithSourceWithSelector<TFeatures extends TableFeatures, TData extends RowData, TSourceValue, TSelected> = {
37
+ table: Table<TFeatures, TData>;
38
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>;
39
+ selector: (state: TSourceValue) => TSelected;
40
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
41
+ };
42
+ /**
43
+ * Subscribe to a single source — atom or store (identity or projected).
44
+ */
45
+ type SubscribePropsWithSource<TFeatures extends TableFeatures, TData extends RowData, TSourceValue, TSelected = TSourceValue> = SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue> | SubscribePropsWithSourceWithSelector<TFeatures, TData, TSourceValue, TSelected>;
46
+ type SubscribeProps<TFeatures extends TableFeatures, TData extends RowData, TSelected = unknown, TSourceValue = unknown> = SubscribePropsWithStore<TFeatures, TData, TSelected> | SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue> | SubscribePropsWithSourceWithSelector<TFeatures, TData, TSourceValue, 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, TSourceValue>(props: SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>): ComponentChildren;
54
+ declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TSourceValue, TSelected>(props: SubscribePropsWithSourceWithSelector<TFeatures, TData, TSourceValue, 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, SubscribePropsWithSource, SubscribePropsWithSourceIdentity, SubscribePropsWithSourceWithSelector, 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 source (e.g. `table.atoms.rowSelection` or
24
+ * `table.optionsStore`). Omitting `selector` is equivalent to the identity
25
+ * selector — children receive `TSourceValue`.
26
+ */
27
+ type SubscribePropsWithSourceIdentity<TFeatures extends TableFeatures, TData extends RowData, TSourceValue> = {
28
+ table: Table<TFeatures, TData>;
29
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>;
30
+ selector?: undefined;
31
+ children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren;
32
+ };
33
+ /**
34
+ * Subscribe to a projected value from a source (atom or store).
35
+ */
36
+ type SubscribePropsWithSourceWithSelector<TFeatures extends TableFeatures, TData extends RowData, TSourceValue, TSelected> = {
37
+ table: Table<TFeatures, TData>;
38
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>;
39
+ selector: (state: TSourceValue) => TSelected;
40
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
41
+ };
42
+ /**
43
+ * Subscribe to a single source — atom or store (identity or projected).
44
+ */
45
+ type SubscribePropsWithSource<TFeatures extends TableFeatures, TData extends RowData, TSourceValue, TSelected = TSourceValue> = SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue> | SubscribePropsWithSourceWithSelector<TFeatures, TData, TSourceValue, TSelected>;
46
+ type SubscribeProps<TFeatures extends TableFeatures, TData extends RowData, TSelected = unknown, TSourceValue = unknown> = SubscribePropsWithStore<TFeatures, TData, TSelected> | SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue> | SubscribePropsWithSourceWithSelector<TFeatures, TData, TSourceValue, 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, TSourceValue>(props: SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>): ComponentChildren;
54
+ declare function Subscribe<TFeatures extends TableFeatures, TData extends RowData, TSourceValue, TSelected>(props: SubscribePropsWithSourceWithSelector<TFeatures, TData, TSourceValue, 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, SubscribePropsWithSource, SubscribePropsWithSourceIdentity, SubscribePropsWithSourceWithSelector, 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("source" in props ? props.source : props.table.store, "source" 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 source (e.g. `table.atoms.rowSelection` or\n * `table.optionsStore`). Omitting `selector` is equivalent to the identity\n * selector children receive `TSourceValue`.\n */\nexport type SubscribePropsWithSourceIdentity<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSourceValue,\n> = {\n table: Table<TFeatures, TData>\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector?: undefined\n children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to a projected value from a source (atom or store).\n */\nexport type SubscribePropsWithSourceWithSelector<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSourceValue,\n TSelected,\n> = {\n table: Table<TFeatures, TData>\n source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>\n selector: (state: TSourceValue) => TSelected\n children: ((state: TSelected) => ComponentChildren) | ComponentChildren\n}\n\n/**\n * Subscribe to a single source atom or store (identity or projected).\n */\nexport type SubscribePropsWithSource<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSourceValue,\n TSelected = TSourceValue,\n> =\n | SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>\n | SubscribePropsWithSourceWithSelector<\n TFeatures,\n TData,\n TSourceValue,\n TSelected\n >\n\nexport type SubscribeProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = unknown,\n TSourceValue = unknown,\n> =\n | SubscribePropsWithStore<TFeatures, TData, TSelected>\n | SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>\n | SubscribePropsWithSourceWithSelector<\n TFeatures,\n TData,\n TSourceValue,\n TSelected\n >\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 TSourceValue,\n>(\n props: SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>,\n): ComponentChildren\nexport function Subscribe<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSourceValue,\n TSelected,\n>(\n props: SubscribePropsWithSourceWithSelector<\n TFeatures,\n TData,\n TSourceValue,\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 TSourceValue,\n>(\n props: SubscribeProps<TFeatures, TData, TSelected, TSourceValue>,\n): ComponentChildren {\n const source = 'source' in props ? props.source : props.table.store\n const selectFn =\n 'source' 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":";;;AA+HA,SAAgB,UAMd,OACmB;CAKnB,MAAM,WAAW,YAJF,YAAY,QAAQ,MAAM,SAAS,MAAM,MAAM,OAE5D,YAAY,QAAS,MAAM,cAAc,MAAe,KAAM,MAAM,UAKpE,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, SubscribePropsWithSource, SubscribePropsWithSourceIdentity, SubscribePropsWithSourceWithSelector, 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, SubscribePropsWithSource, SubscribePropsWithSourceIdentity, SubscribePropsWithSourceWithSelector, 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, SubscribePropsWithSource, SubscribePropsWithSourceIdentity, SubscribePropsWithSourceWithSelector, 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, SubscribePropsWithSource, SubscribePropsWithSourceIdentity, SubscribePropsWithSourceWithSelector, 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 `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,53 +1,58 @@
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 `source` to subscribe to a single atom or store (e.g. `table.atoms.rowSelection`
13
+ * or `table.optionsStore`) instead of the full `table.store`.
11
14
  *
12
15
  * @example
13
16
  * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
14
- * {({ rowSelection }) => ( // important to include `{() => {()}}` syntax
15
- * <tr key={row.id}>
16
- * // render the row
17
- * </tr>
17
+ * {({ rowSelection }) => (
18
+ * <tr key={row.id}>...</tr>
18
19
  * )}
19
20
  * </table.Subscribe>
21
+ *
22
+ * @example
23
+ * <table.Subscribe source={table.atoms.rowSelection}>
24
+ * {(rowSelection) => <div>...</div>}
25
+ * </table.Subscribe>
26
+ *
27
+ * @example
28
+ * <table.Subscribe source={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>
29
+ * {() => <tr key={row.id}>...</tr>}
30
+ * </table.Subscribe>
20
31
  */
21
- Subscribe: <TSelected>(props: {
22
- selector: (state: NoInfer<TableState<TFeatures>>) => TSelected;
23
- children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
24
- }) => ComponentChildren;
32
+ /**
33
+ * Overloads (source first, then store) so JSX contextual typing works for both modes.
34
+ * Source without `selector` is separate so children infer `TSourceValue` (identity projection).
35
+ */
36
+ Subscribe: {
37
+ <TSourceValue>(props: {
38
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>;
39
+ selector?: undefined;
40
+ children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren;
41
+ }): ComponentChildren;
42
+ <TSourceValue, TSubSelected>(props: {
43
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>;
44
+ selector: (state: TSourceValue) => TSubSelected;
45
+ children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren;
46
+ }): ComponentChildren;
47
+ <TSubSelected>(props: Omit<SubscribePropsWithStore<TFeatures, TData, TSubSelected>, 'table'>): ComponentChildren;
48
+ };
25
49
  /**
26
50
  * A Preact component that renders headers, cells, or footers with custom markup.
27
51
  * 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
52
  */
43
53
  FlexRender: <TValue extends CellData = CellData>(props: FlexRenderProps<TFeatures, TData, TValue>) => ComponentChildren;
44
54
  /**
45
55
  * 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
56
  */
52
57
  readonly state: Readonly<TSelected> & {
53
58
  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,50 @@ 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 `source` to subscribe to a single atom or store (e.g. `table.atoms.rowSelection`
13
+ * or `table.optionsStore`) instead of the full `table.store`.
11
14
  *
12
15
  * @example
13
16
  * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
14
- * {({ rowSelection }) => ( // important to include `{() => {()}}` syntax
15
- * <tr key={row.id}>
16
- * // render the row
17
- * </tr>
17
+ * {({ rowSelection }) => (
18
+ * <tr key={row.id}>...</tr>
18
19
  * )}
19
20
  * </table.Subscribe>
21
+ *
22
+ * @example
23
+ * <table.Subscribe source={table.atoms.rowSelection}>
24
+ * {(rowSelection) => <div>...</div>}
25
+ * </table.Subscribe>
26
+ *
27
+ * @example
28
+ * <table.Subscribe source={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>
29
+ * {() => <tr key={row.id}>...</tr>}
30
+ * </table.Subscribe>
20
31
  */
21
- Subscribe: <TSelected>(props: {
22
- selector: (state: NoInfer<TableState<TFeatures>>) => TSelected;
23
- children: ((state: TSelected) => ComponentChildren) | ComponentChildren;
24
- }) => ComponentChildren;
32
+ /**
33
+ * Overloads (source first, then store) so JSX contextual typing works for both modes.
34
+ * Source without `selector` is separate so children infer `TSourceValue` (identity projection).
35
+ */
36
+ Subscribe: {
37
+ <TSourceValue>(props: {
38
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>;
39
+ selector?: undefined;
40
+ children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren;
41
+ }): ComponentChildren;
42
+ <TSourceValue, TSubSelected>(props: {
43
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>;
44
+ selector: (state: TSourceValue) => TSubSelected;
45
+ children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren;
46
+ }): ComponentChildren;
47
+ <TSubSelected>(props: Omit<SubscribePropsWithStore<TFeatures, TData, TSubSelected>, 'table'>): ComponentChildren;
48
+ };
25
49
  /**
26
50
  * A Preact component that renders headers, cells, or footers with custom markup.
27
51
  * 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
52
  */
43
53
  FlexRender: <TValue extends CellData = CellData>(props: FlexRenderProps<TFeatures, TData, TValue>) => ComponentChildren;
44
54
  /**
45
55
  * 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
56
  */
52
57
  readonly state: Readonly<TSelected> & {
53
58
  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 `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"}
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.35",
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,144 @@ 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 source (e.g. `table.atoms.rowSelection` or
34
+ * `table.optionsStore`). Omitting `selector` is equivalent to the identity
35
+ * selector — children receive `TSourceValue`.
36
+ */
37
+ export type SubscribePropsWithSourceIdentity<
38
+ TFeatures extends TableFeatures,
39
+ TData extends RowData,
40
+ TSourceValue,
41
+ > = {
42
+ table: Table<TFeatures, TData>
43
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>
44
+ selector?: undefined
45
+ children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren
46
+ }
47
+
48
+ /**
49
+ * Subscribe to a projected value from a source (atom or store).
50
+ */
51
+ export type SubscribePropsWithSourceWithSelector<
52
+ TFeatures extends TableFeatures,
53
+ TData extends RowData,
54
+ TSourceValue,
55
+ TSelected,
56
+ > = {
57
+ table: Table<TFeatures, TData>
58
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>
59
+ selector: (state: TSourceValue) => TSelected
60
+ children: ((state: TSelected) => ComponentChildren) | ComponentChildren
61
+ }
62
+
63
+ /**
64
+ * Subscribe to a single source — atom or store (identity or projected).
65
+ */
66
+ export type SubscribePropsWithSource<
67
+ TFeatures extends TableFeatures,
68
+ TData extends RowData,
69
+ TSourceValue,
70
+ TSelected = TSourceValue,
71
+ > =
72
+ | SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>
73
+ | SubscribePropsWithSourceWithSelector<
74
+ TFeatures,
75
+ TData,
76
+ TSourceValue,
77
+ TSelected
78
+ >
79
+
80
+ export type SubscribeProps<
81
+ TFeatures extends TableFeatures,
82
+ TData extends RowData,
83
+ TSelected = unknown,
84
+ TSourceValue = unknown,
85
+ > =
86
+ | SubscribePropsWithStore<TFeatures, TData, TSelected>
87
+ | SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>
88
+ | SubscribePropsWithSourceWithSelector<
89
+ TFeatures,
90
+ TData,
91
+ TSourceValue,
92
+ TSelected
93
+ >
94
+
32
95
  /**
33
96
  * A Preact component that allows you to subscribe to the table state.
34
97
  *
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
- * ```
98
+ * For `table.Subscribe` from `useTable`, prefer that API it uses overloads so
99
+ * JSX contextual typing works. This standalone component uses a union `props` type.
56
100
  */
57
101
  export function Subscribe<
58
102
  TFeatures extends TableFeatures,
59
103
  TData extends RowData,
60
- TSelected = {},
61
- >(props: SubscribeProps<TFeatures, TData, TSelected>): ComponentChildren {
62
- const selected = useSelector(props.table.store, props.selector)
104
+ TSourceValue,
105
+ >(
106
+ props: SubscribePropsWithSourceIdentity<TFeatures, TData, TSourceValue>,
107
+ ): ComponentChildren
108
+ export function Subscribe<
109
+ TFeatures extends TableFeatures,
110
+ TData extends RowData,
111
+ TSourceValue,
112
+ TSelected,
113
+ >(
114
+ props: SubscribePropsWithSourceWithSelector<
115
+ TFeatures,
116
+ TData,
117
+ TSourceValue,
118
+ TSelected
119
+ >,
120
+ ): ComponentChildren
121
+ export function Subscribe<
122
+ TFeatures extends TableFeatures,
123
+ TData extends RowData,
124
+ TSelected,
125
+ >(
126
+ props: SubscribePropsWithStore<TFeatures, TData, TSelected>,
127
+ ): ComponentChildren
128
+ export function Subscribe<
129
+ TFeatures extends TableFeatures,
130
+ TData extends RowData,
131
+ TSelected,
132
+ TSourceValue,
133
+ >(
134
+ props: SubscribeProps<TFeatures, TData, TSelected, TSourceValue>,
135
+ ): ComponentChildren {
136
+ const source = 'source' in props ? props.source : props.table.store
137
+ const selectFn =
138
+ 'source' in props ? (props.selector ?? ((x: unknown) => x)) : props.selector
139
+
140
+ const selected = useSelector(
141
+ source as never,
142
+ selectFn as Parameters<typeof useSelector>[1],
143
+ {
144
+ compare: shallow,
145
+ },
146
+ ) as TSelected
63
147
 
64
148
  return typeof props.children === 'function'
65
- ? props.children(selected)
149
+ ? (props.children as (state: TSelected) => ComponentChildren)(selected)
66
150
  : props.children
67
151
  }
@@ -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,57 @@ 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 `source` to subscribe to a single atom or store (e.g. `table.atoms.rowSelection`
28
+ * or `table.optionsStore`) instead of the full `table.store`.
28
29
  *
29
30
  * @example
30
31
  * <table.Subscribe selector={(state) => ({ rowSelection: state.rowSelection })}>
31
- * {({ rowSelection }) => ( // important to include `{() => {()}}` syntax
32
- * <tr key={row.id}>
33
- * // render the row
34
- * </tr>
32
+ * {({ rowSelection }) => (
33
+ * <tr key={row.id}>...</tr>
35
34
  * )}
36
35
  * </table.Subscribe>
36
+ *
37
+ * @example
38
+ * <table.Subscribe source={table.atoms.rowSelection}>
39
+ * {(rowSelection) => <div>...</div>}
40
+ * </table.Subscribe>
41
+ *
42
+ * @example
43
+ * <table.Subscribe source={table.atoms.rowSelection} selector={(s) => s?.[row.id]}>
44
+ * {() => <tr key={row.id}>...</tr>}
45
+ * </table.Subscribe>
37
46
  */
38
- Subscribe: <TSelected>(props: {
39
- selector: (state: NoInfer<TableState<TFeatures>>) => TSelected
40
- children: ((state: TSelected) => ComponentChildren) | ComponentChildren
41
- }) => ComponentChildren
47
+ /**
48
+ * Overloads (source first, then store) so JSX contextual typing works for both modes.
49
+ * Source without `selector` is separate so children infer `TSourceValue` (identity projection).
50
+ */
51
+ Subscribe: {
52
+ <TSourceValue>(props: {
53
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>
54
+ selector?: undefined
55
+ children: ((state: TSourceValue) => ComponentChildren) | ComponentChildren
56
+ }): ComponentChildren
57
+ <TSourceValue, TSubSelected>(props: {
58
+ source: Atom<TSourceValue> | ReadonlyAtom<TSourceValue>
59
+ selector: (state: TSourceValue) => TSubSelected
60
+ children: ((state: TSubSelected) => ComponentChildren) | ComponentChildren
61
+ }): ComponentChildren
62
+ <TSubSelected>(
63
+ props: Omit<
64
+ SubscribePropsWithStore<TFeatures, TData, TSubSelected>,
65
+ 'table'
66
+ >,
67
+ ): ComponentChildren
68
+ }
42
69
  /**
43
70
  * A Preact component that renders headers, cells, or footers with custom markup.
44
71
  * 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
72
  */
60
73
  FlexRender: <TValue extends CellData = CellData>(
61
74
  props: FlexRenderProps<TFeatures, TData, TValue>,
62
75
  ) => ComponentChildren
63
76
  /**
64
77
  * 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
78
  */
71
79
  readonly state: Readonly<TSelected> & {
72
80
  columns: TableOptions<TFeatures, TData>['columns']
@@ -90,11 +98,12 @@ export function useTable<
90
98
  TSelected
91
99
  >
92
100
 
93
- tableInstance.Subscribe = function SubscribeBound<TSelected>(
94
- props: Omit<SubscribeProps<TFeatures, TData, TSelected>, 'table'>,
95
- ) {
96
- return Subscribe({ ...props, table: tableInstance })
97
- }
101
+ tableInstance.Subscribe = ((props: any) => {
102
+ return Subscribe({
103
+ ...props,
104
+ table: tableInstance,
105
+ })
106
+ }) as PreactTable<TFeatures, TData, TSelected>['Subscribe']
98
107
 
99
108
  tableInstance.FlexRender = FlexRender
100
109