@tanstack/alpine-table 9.0.0-beta.0

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.
Files changed (44) hide show
  1. package/README.md +128 -0
  2. package/dist/_virtual/_rolldown/runtime.cjs +29 -0
  3. package/dist/createTable.cjs +65 -0
  4. package/dist/createTable.cjs.map +1 -0
  5. package/dist/createTable.d.cts +18 -0
  6. package/dist/createTable.d.ts +18 -0
  7. package/dist/createTable.js +63 -0
  8. package/dist/createTable.js.map +1 -0
  9. package/dist/createTableHook.cjs +24 -0
  10. package/dist/createTableHook.cjs.map +1 -0
  11. package/dist/createTableHook.d.cts +17 -0
  12. package/dist/createTableHook.d.ts +17 -0
  13. package/dist/createTableHook.js +24 -0
  14. package/dist/createTableHook.js.map +1 -0
  15. package/dist/flex-render.cjs +5 -0
  16. package/dist/flex-render.d.cts +2 -0
  17. package/dist/flex-render.d.ts +2 -0
  18. package/dist/flex-render.js +3 -0
  19. package/dist/flexRender.cjs +40 -0
  20. package/dist/flexRender.cjs.map +1 -0
  21. package/dist/flexRender.d.cts +61 -0
  22. package/dist/flexRender.d.ts +61 -0
  23. package/dist/flexRender.js +38 -0
  24. package/dist/flexRender.js.map +1 -0
  25. package/dist/index.cjs +16 -0
  26. package/dist/index.d.cts +5 -0
  27. package/dist/index.d.ts +5 -0
  28. package/dist/index.js +7 -0
  29. package/dist/reactivity.cjs +34 -0
  30. package/dist/reactivity.cjs.map +1 -0
  31. package/dist/reactivity.js +34 -0
  32. package/dist/reactivity.js.map +1 -0
  33. package/dist/static-functions.cjs +9 -0
  34. package/dist/static-functions.d.cts +1 -0
  35. package/dist/static-functions.d.ts +1 -0
  36. package/dist/static-functions.js +3 -0
  37. package/package.json +68 -0
  38. package/src/createTable.ts +148 -0
  39. package/src/createTableHook.ts +48 -0
  40. package/src/flex-render.ts +1 -0
  41. package/src/flexRender.ts +100 -0
  42. package/src/index.ts +5 -0
  43. package/src/reactivity.ts +41 -0
  44. package/src/static-functions.ts +1 -0
@@ -0,0 +1,61 @@
1
+ import { Cell, CellData, Header, RowData, TableFeatures } from "@tanstack/table-core";
2
+
3
+ //#region src/flexRender.d.ts
4
+ /**
5
+ * Renders an Alpine table value with the provided context props.
6
+ *
7
+ * Use this lower-level helper for custom header, cell, or footer renderers when
8
+ * you already have the render function and context. `FlexRender` is the
9
+ * convenience wrapper for table cell/header/footer objects. Renderers typically
10
+ * return a string of markup that you render into the DOM with `x-html`.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * flexRender(cell.column.columnDef.cell, cell.getContext())
15
+ * ```
16
+ */
17
+ declare function flexRender<TProps extends object>(render: any, props: TProps): any;
18
+ /**
19
+ * Simplified wrapper of `flexRender`. Use this utility function to render headers, cells, or footers with custom markup.
20
+ * Only one prop (`cell`, `header`, or `footer`) may be passed.
21
+ * @example
22
+ * ```html
23
+ * <th x-html="FlexRender({ header })"></th>
24
+ * <td x-html="FlexRender({ cell })"></td>
25
+ * <th x-html="FlexRender({ footer: header })"></th>
26
+ * ```
27
+ *
28
+ * This replaces calling `flexRender` directly like this:
29
+ * ```ts
30
+ * flexRender(cell.column.columnDef.cell, cell.getContext())
31
+ * flexRender(header.column.columnDef.header, header.getContext())
32
+ * flexRender(footer.column.columnDef.footer, footer.getContext())
33
+ * ```
34
+ */
35
+ type FlexRenderProps<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData = CellData> = {
36
+ cell: Cell<TFeatures, TData, TValue>;
37
+ header?: never;
38
+ footer?: never;
39
+ } | {
40
+ header: Header<TFeatures, TData, TValue>;
41
+ cell?: never;
42
+ footer?: never;
43
+ } | {
44
+ footer: Header<TFeatures, TData, TValue>;
45
+ cell?: never;
46
+ header?: never;
47
+ };
48
+ /**
49
+ * Simplified wrapper of `flexRender`. Use this utility function to render headers, cells, or footers with custom markup.
50
+ * Only one prop (`cell`, `header`, or `footer`) may be passed.
51
+ * @example
52
+ * ```html
53
+ * <th x-html="FlexRender({ header })"></th>
54
+ * <td x-html="FlexRender({ cell })"></td>
55
+ * <th x-html="FlexRender({ footer: header })"></th>
56
+ * ```
57
+ */
58
+ declare function FlexRender<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData = CellData>(props: FlexRenderProps<TFeatures, TData, TValue>): any;
59
+ //#endregion
60
+ export { FlexRender, FlexRenderProps, flexRender };
61
+ //# sourceMappingURL=flexRender.d.ts.map
@@ -0,0 +1,38 @@
1
+ //#region src/flexRender.ts
2
+ /**
3
+ * Renders an Alpine table value with the provided context props.
4
+ *
5
+ * Use this lower-level helper for custom header, cell, or footer renderers when
6
+ * you already have the render function and context. `FlexRender` is the
7
+ * convenience wrapper for table cell/header/footer objects. Renderers typically
8
+ * return a string of markup that you render into the DOM with `x-html`.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * flexRender(cell.column.columnDef.cell, cell.getContext())
13
+ * ```
14
+ */
15
+ function flexRender(render, props) {
16
+ if (typeof render === "function") return render(props);
17
+ return render;
18
+ }
19
+ /**
20
+ * Simplified wrapper of `flexRender`. Use this utility function to render headers, cells, or footers with custom markup.
21
+ * Only one prop (`cell`, `header`, or `footer`) may be passed.
22
+ * @example
23
+ * ```html
24
+ * <th x-html="FlexRender({ header })"></th>
25
+ * <td x-html="FlexRender({ cell })"></td>
26
+ * <th x-html="FlexRender({ footer: header })"></th>
27
+ * ```
28
+ */
29
+ function FlexRender(props) {
30
+ if ("cell" in props && props.cell) return flexRender(props.cell.column.columnDef.cell, props.cell.getContext());
31
+ if ("header" in props && props.header) return flexRender(props.header.column.columnDef.header, props.header.getContext());
32
+ if ("footer" in props && props.footer) return flexRender(props.footer.column.columnDef.footer, props.footer.getContext());
33
+ return null;
34
+ }
35
+
36
+ //#endregion
37
+ export { FlexRender, flexRender };
38
+ //# sourceMappingURL=flexRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flexRender.js","names":[],"sources":["../src/flexRender.ts"],"sourcesContent":["import type {\n Cell,\n CellData,\n Header,\n RowData,\n TableFeatures,\n} from '@tanstack/table-core'\n\n/**\n * Renders an Alpine table value with the provided context props.\n *\n * Use this lower-level helper for custom header, cell, or footer renderers when\n * you already have the render function and context. `FlexRender` is the\n * convenience wrapper for table cell/header/footer objects. Renderers typically\n * return a string of markup that you render into the DOM with `x-html`.\n *\n * @example\n * ```ts\n * flexRender(cell.column.columnDef.cell, cell.getContext())\n * ```\n */\nexport function flexRender<TProps extends object>(\n render: any,\n props: TProps,\n): any {\n if (typeof render === 'function') {\n return render(props)\n }\n return render\n}\n\n/**\n * Simplified wrapper of `flexRender`. Use this utility function to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example\n * ```html\n * <th x-html=\"FlexRender({ header })\"></th>\n * <td x-html=\"FlexRender({ cell })\"></td>\n * <th x-html=\"FlexRender({ footer: header })\"></th>\n * ```\n *\n * This replaces calling `flexRender` directly like this:\n * ```ts\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 */\nexport type FlexRenderProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n> =\n | { cell: Cell<TFeatures, TData, TValue>; header?: never; footer?: never }\n | {\n header: Header<TFeatures, TData, TValue>\n cell?: never\n footer?: never\n }\n | {\n footer: Header<TFeatures, TData, TValue>\n cell?: never\n header?: never\n }\n\n/**\n * Simplified wrapper of `flexRender`. Use this utility function to render headers, cells, or footers with custom markup.\n * Only one prop (`cell`, `header`, or `footer`) may be passed.\n * @example\n * ```html\n * <th x-html=\"FlexRender({ header })\"></th>\n * <td x-html=\"FlexRender({ cell })\"></td>\n * <th x-html=\"FlexRender({ footer: header })\"></th>\n * ```\n */\nexport function FlexRender<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TValue extends CellData = CellData,\n>(props: FlexRenderProps<TFeatures, TData, TValue>): any {\n if ('cell' in props && props.cell) {\n return flexRender(props.cell.column.columnDef.cell, props.cell.getContext())\n }\n\n if ('header' in props && props.header) {\n return flexRender(\n props.header.column.columnDef.header,\n props.header.getContext(),\n )\n }\n\n if ('footer' in props && props.footer) {\n return flexRender(\n props.footer.column.columnDef.footer,\n props.footer.getContext(),\n )\n }\n\n return null\n}\n"],"mappings":";;;;;;;;;;;;;;AAqBA,SAAgB,WACd,QACA,OACK;CACL,IAAI,OAAO,WAAW,YACpB,OAAO,OAAO,KAAK;CAErB,OAAO;AACT;;;;;;;;;;;AA8CA,SAAgB,WAId,OAAuD;CACvD,IAAI,UAAU,SAAS,MAAM,MAC3B,OAAO,WAAW,MAAM,KAAK,OAAO,UAAU,MAAM,MAAM,KAAK,WAAW,CAAC;CAG7E,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,WAAW,CAC1B;CAGF,IAAI,YAAY,SAAS,MAAM,QAC7B,OAAO,WACL,MAAM,OAAO,OAAO,UAAU,QAC9B,MAAM,OAAO,WAAW,CAC1B;CAGF,OAAO;AACT"}
package/dist/index.cjs ADDED
@@ -0,0 +1,16 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_flexRender = require('./flexRender.cjs');
3
+ const require_createTable = require('./createTable.cjs');
4
+ const require_createTableHook = require('./createTableHook.cjs');
5
+
6
+ exports.FlexRender = require_flexRender.FlexRender;
7
+ exports.createTable = require_createTable.createTable;
8
+ exports.createTableHook = require_createTableHook.createTableHook;
9
+ exports.flexRender = require_flexRender.flexRender;
10
+ var _tanstack_table_core = require("@tanstack/table-core");
11
+ Object.keys(_tanstack_table_core).forEach(function (k) {
12
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
13
+ enumerable: true,
14
+ get: function () { return _tanstack_table_core[k]; }
15
+ });
16
+ });
@@ -0,0 +1,5 @@
1
+ import { FlexRender, FlexRenderProps, flexRender } from "./flexRender.cjs";
2
+ import { AlpineTable, createTable } from "./createTable.cjs";
3
+ import { AppAlpineTable, AppColumnHelper, CreateTableHookOptions, createTableHook } from "./createTableHook.cjs";
4
+ export * from "@tanstack/table-core";
5
+ export { AlpineTable, AppAlpineTable, AppColumnHelper, CreateTableHookOptions, FlexRender, FlexRenderProps, createTable, createTableHook, flexRender };
@@ -0,0 +1,5 @@
1
+ import { FlexRender, FlexRenderProps, flexRender } from "./flexRender.js";
2
+ import { AlpineTable, createTable } from "./createTable.js";
3
+ import { AppAlpineTable, AppColumnHelper, CreateTableHookOptions, createTableHook } from "./createTableHook.js";
4
+ export * from "@tanstack/table-core";
5
+ export { AlpineTable, AppAlpineTable, AppColumnHelper, CreateTableHookOptions, FlexRender, FlexRenderProps, createTable, createTableHook, flexRender };
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import { FlexRender, flexRender } from "./flexRender.js";
2
+ import { createTable } from "./createTable.js";
3
+ import { createTableHook } from "./createTableHook.js";
4
+
5
+ export * from "@tanstack/table-core"
6
+
7
+ export { FlexRender, createTable, createTableHook, flexRender };
@@ -0,0 +1,34 @@
1
+ let _tanstack_store = require("@tanstack/store");
2
+
3
+ //#region src/reactivity.ts
4
+ /**
5
+ * Creates the table-core reactivity bindings used by the Alpine adapter.
6
+ *
7
+ * Alpine uses TanStack Store atoms directly. Table instance reads
8
+ * are then exposed to Alpine through the proxy wrapper in `createTable`.
9
+ */
10
+ function alpineReactivity() {
11
+ return {
12
+ createOptionsStore: true,
13
+ wrapExternalAtoms: false,
14
+ addSubscription: () => {
15
+ throw new Error("Feature not supported in current reactivity implementation");
16
+ },
17
+ unmount: () => {
18
+ throw new Error("Feature not supported in current reactivity implementation");
19
+ },
20
+ schedule: (fn) => queueMicrotask(() => fn()),
21
+ batch: _tanstack_store.batch,
22
+ untrack: (fn) => fn(),
23
+ createReadonlyAtom: (fn, options) => {
24
+ return (0, _tanstack_store.createAtom)(() => fn(), { compare: options === null || options === void 0 ? void 0 : options.compare });
25
+ },
26
+ createWritableAtom: (value, options) => {
27
+ return (0, _tanstack_store.createAtom)(value, { compare: options === null || options === void 0 ? void 0 : options.compare });
28
+ }
29
+ };
30
+ }
31
+
32
+ //#endregion
33
+ exports.alpineReactivity = alpineReactivity;
34
+ //# sourceMappingURL=reactivity.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactivity.cjs","names":[],"sources":["../src/reactivity.ts"],"sourcesContent":["import { batch, createAtom } from '@tanstack/store'\nimport type {\n TableAtomOptions,\n TableReactivityBindings,\n} from '@tanstack/table-core/reactivity'\n\n/**\n * Creates the table-core reactivity bindings used by the Alpine adapter.\n *\n * Alpine uses TanStack Store atoms directly. Table instance reads\n * are then exposed to Alpine through the proxy wrapper in `createTable`.\n */\nexport function alpineReactivity(): TableReactivityBindings {\n return {\n createOptionsStore: true,\n wrapExternalAtoms: false,\n addSubscription: () => {\n throw new Error(\n 'Feature not supported in current reactivity implementation',\n )\n },\n unmount: () => {\n throw new Error(\n 'Feature not supported in current reactivity implementation',\n )\n },\n schedule: (fn) => queueMicrotask(() => fn()),\n batch,\n untrack: (fn) => fn(),\n createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {\n return createAtom(() => fn(), {\n compare: options?.compare,\n })\n },\n createWritableAtom: <T>(value: T, options?: TableAtomOptions<T>) => {\n return createAtom(value, {\n compare: options?.compare,\n })\n },\n }\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,mBAA4C;CAC1D,OAAO;EACL,oBAAoB;EACpB,mBAAmB;EACnB,uBAAuB;GACrB,MAAM,IAAI,MACR,4DACF;EACF;EACA,eAAe;GACb,MAAM,IAAI,MACR,4DACF;EACF;EACA,WAAW,OAAO,qBAAqB,GAAG,CAAC;EAC3C;EACA,UAAU,OAAO,GAAG;EACpB,qBAAwB,IAAa,YAAkC;GACrE,6CAAwB,GAAG,GAAG,EAC5B,2DAAS,QAAS,QACpB,CAAC;EACH;EACA,qBAAwB,OAAU,YAAkC;GAClE,uCAAkB,OAAO,EACvB,2DAAS,QAAS,QACpB,CAAC;EACH;CACF;AACF"}
@@ -0,0 +1,34 @@
1
+ import { batch, createAtom } from "@tanstack/store";
2
+
3
+ //#region src/reactivity.ts
4
+ /**
5
+ * Creates the table-core reactivity bindings used by the Alpine adapter.
6
+ *
7
+ * Alpine uses TanStack Store atoms directly. Table instance reads
8
+ * are then exposed to Alpine through the proxy wrapper in `createTable`.
9
+ */
10
+ function alpineReactivity() {
11
+ return {
12
+ createOptionsStore: true,
13
+ wrapExternalAtoms: false,
14
+ addSubscription: () => {
15
+ throw new Error("Feature not supported in current reactivity implementation");
16
+ },
17
+ unmount: () => {
18
+ throw new Error("Feature not supported in current reactivity implementation");
19
+ },
20
+ schedule: (fn) => queueMicrotask(() => fn()),
21
+ batch,
22
+ untrack: (fn) => fn(),
23
+ createReadonlyAtom: (fn, options) => {
24
+ return createAtom(() => fn(), { compare: options === null || options === void 0 ? void 0 : options.compare });
25
+ },
26
+ createWritableAtom: (value, options) => {
27
+ return createAtom(value, { compare: options === null || options === void 0 ? void 0 : options.compare });
28
+ }
29
+ };
30
+ }
31
+
32
+ //#endregion
33
+ export { alpineReactivity };
34
+ //# sourceMappingURL=reactivity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactivity.js","names":[],"sources":["../src/reactivity.ts"],"sourcesContent":["import { batch, createAtom } from '@tanstack/store'\nimport type {\n TableAtomOptions,\n TableReactivityBindings,\n} from '@tanstack/table-core/reactivity'\n\n/**\n * Creates the table-core reactivity bindings used by the Alpine adapter.\n *\n * Alpine uses TanStack Store atoms directly. Table instance reads\n * are then exposed to Alpine through the proxy wrapper in `createTable`.\n */\nexport function alpineReactivity(): TableReactivityBindings {\n return {\n createOptionsStore: true,\n wrapExternalAtoms: false,\n addSubscription: () => {\n throw new Error(\n 'Feature not supported in current reactivity implementation',\n )\n },\n unmount: () => {\n throw new Error(\n 'Feature not supported in current reactivity implementation',\n )\n },\n schedule: (fn) => queueMicrotask(() => fn()),\n batch,\n untrack: (fn) => fn(),\n createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {\n return createAtom(() => fn(), {\n compare: options?.compare,\n })\n },\n createWritableAtom: <T>(value: T, options?: TableAtomOptions<T>) => {\n return createAtom(value, {\n compare: options?.compare,\n })\n },\n }\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,mBAA4C;CAC1D,OAAO;EACL,oBAAoB;EACpB,mBAAmB;EACnB,uBAAuB;GACrB,MAAM,IAAI,MACR,4DACF;EACF;EACA,eAAe;GACb,MAAM,IAAI,MACR,4DACF;EACF;EACA,WAAW,OAAO,qBAAqB,GAAG,CAAC;EAC3C;EACA,UAAU,OAAO,GAAG;EACpB,qBAAwB,IAAa,YAAkC;GACrE,OAAO,iBAAiB,GAAG,GAAG,EAC5B,2DAAS,QAAS,QACpB,CAAC;EACH;EACA,qBAAwB,OAAU,YAAkC;GAClE,OAAO,WAAW,OAAO,EACvB,2DAAS,QAAS,QACpB,CAAC;EACH;CACF;AACF"}
@@ -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/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@tanstack/alpine-table",
3
+ "version": "9.0.0-beta.0",
4
+ "description": "Headless UI for building powerful tables & datagrids for Alpine.",
5
+ "author": "Tanner Linsley",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/TanStack/table.git",
10
+ "directory": "packages/alpine-table"
11
+ },
12
+ "homepage": "https://tanstack.com/table",
13
+ "funding": {
14
+ "type": "github",
15
+ "url": "https://github.com/sponsors/tannerlinsley"
16
+ },
17
+ "keywords": [
18
+ "alpine",
19
+ "table",
20
+ "alpine-table",
21
+ "datagrid"
22
+ ],
23
+ "type": "module",
24
+ "types": "./dist/index.d.cts",
25
+ "main": "./dist/index.cjs",
26
+ "module": "./dist/index.js",
27
+ "exports": {
28
+ ".": {
29
+ "import": "./dist/index.js",
30
+ "require": "./dist/index.cjs"
31
+ },
32
+ "./flex-render": {
33
+ "import": "./dist/flex-render.js",
34
+ "require": "./dist/flex-render.cjs"
35
+ },
36
+ "./static-functions": {
37
+ "import": "./dist/static-functions.js",
38
+ "require": "./dist/static-functions.cjs"
39
+ },
40
+ "./package.json": "./package.json"
41
+ },
42
+ "sideEffects": false,
43
+ "engines": {
44
+ "node": ">=16"
45
+ },
46
+ "files": [
47
+ "dist",
48
+ "src"
49
+ ],
50
+ "scripts": {
51
+ "clean": "rimraf ./build && rimraf ./dist",
52
+ "test:eslint": "eslint ./src",
53
+ "test:types": "tsc",
54
+ "test:build": "publint --strict",
55
+ "build": "tsdown"
56
+ },
57
+ "dependencies": {
58
+ "@tanstack/store": "^0.11.0",
59
+ "@tanstack/table-core": "workspace:*"
60
+ },
61
+ "devDependencies": {
62
+ "@types/alpinejs": "^3.13.11",
63
+ "alpinejs": "^3.15.12"
64
+ },
65
+ "peerDependencies": {
66
+ "alpinejs": "^3.15.12"
67
+ }
68
+ }
@@ -0,0 +1,148 @@
1
+ import Alpine from 'alpinejs'
2
+ import { constructTable } from '@tanstack/table-core'
3
+ import { FlexRender, flexRender } from './flexRender'
4
+ import { alpineReactivity } from './reactivity'
5
+ import type {
6
+ RowData,
7
+ Table,
8
+ TableFeatures,
9
+ TableOptions,
10
+ } from '@tanstack/table-core'
11
+
12
+ export type AlpineTable<
13
+ TFeatures extends TableFeatures,
14
+ TData extends RowData,
15
+ > = Table<TFeatures, TData> & {
16
+ /**
17
+ * A lower-level helper to render the content of a cell, header, or footer from a render function and its context.
18
+ */
19
+ flexRender: typeof flexRender
20
+
21
+ /**
22
+ * A convenience helper to render a cell, header, or footer object. Call from `x-html`, e.g. `FlexRender({ header })`.
23
+ */
24
+ FlexRender: typeof FlexRender
25
+ }
26
+
27
+ export function createTable<
28
+ TFeatures extends TableFeatures,
29
+ TData extends RowData,
30
+ >(tableOptions: TableOptions<TFeatures, TData>): AlpineTable<TFeatures, TData> {
31
+ const mergedOptions: TableOptions<TFeatures, TData> = {
32
+ ...tableOptions,
33
+ features: {
34
+ coreReactivityFeature: alpineReactivity(),
35
+ ...tableOptions.features,
36
+ },
37
+ mergeOptions: (
38
+ defaultOptions: TableOptions<TFeatures, TData>,
39
+ newOptions: Partial<TableOptions<TFeatures, TData>>,
40
+ ) => {
41
+ return {
42
+ ...defaultOptions,
43
+ ...newOptions,
44
+ }
45
+ },
46
+ }
47
+
48
+ const table = constructTable(mergedOptions) as unknown as AlpineTable<
49
+ TFeatures,
50
+ TData
51
+ >
52
+
53
+ table.flexRender = flexRender
54
+ table.FlexRender = FlexRender
55
+
56
+ const reactivity = Alpine.reactive({ _ver: 0 })
57
+
58
+ table.store.subscribe(() => {
59
+ reactivity._ver++
60
+ })
61
+
62
+ // Reactively sync options when external Alpine-reactive getters change (e.g.
63
+ // a `get data()` backed by `Alpine.reactive`). Reading the option getters
64
+ // inside the effect registers the dependencies, so the effect re-runs when
65
+ // they change and re-applies the live values via `setOptions`.
66
+ //
67
+ // `setOptions` writes to the options store, not the state store, so a `data`
68
+ // (or other option) change does not emit on `table.store` and would not bump
69
+ // `_ver` on its own. We bump `_ver` here so the template re-pulls derived
70
+ // APIs like `getRowModel()`, which recompute from the new options. The effect
71
+ // never reads `_ver`, so writing it does not re-trigger this effect.
72
+ let initialized = false
73
+ Alpine.effect(() => {
74
+ const state = tableOptions.state as Record<string, unknown> | undefined
75
+ if (state) {
76
+ for (const key in state) {
77
+ void state[key]
78
+ }
79
+ }
80
+ void tableOptions.data
81
+
82
+ table.setOptions((prev) => ({
83
+ ...prev,
84
+ ...tableOptions,
85
+ }))
86
+
87
+ if (initialized) {
88
+ reactivity._ver++
89
+ }
90
+ initialized = true
91
+ })
92
+
93
+ const proxyCache = new WeakMap<object, object>()
94
+
95
+ const toReactiveProxy = <TValue>(value: TValue): TValue => {
96
+ if (typeof value !== 'object' || value === null) {
97
+ return value
98
+ }
99
+
100
+ // Built-in exotic objects (Map, Set, Date, etc.) rely on internal slots and
101
+ // throw "incompatible receiver" when their getters/methods run with a Proxy
102
+ // as the receiver (e.g. `getFacetedUniqueValues().size`). Return them as-is;
103
+ // the read that produced them already tracked `_ver` at the call site.
104
+ if (
105
+ value instanceof Map ||
106
+ value instanceof Set ||
107
+ value instanceof WeakMap ||
108
+ value instanceof WeakSet ||
109
+ value instanceof Date ||
110
+ value instanceof RegExp ||
111
+ value instanceof Promise
112
+ ) {
113
+ return value
114
+ }
115
+
116
+ const cachedProxy = proxyCache.get(value)
117
+ if (cachedProxy) {
118
+ return cachedProxy as TValue
119
+ }
120
+
121
+ const proxy = new Proxy(value, {
122
+ get(target, prop, receiver) {
123
+ if (prop === '__v_skip') {
124
+ return true
125
+ }
126
+
127
+ const resolvedValue = Reflect.get(target, prop, receiver)
128
+
129
+ if (typeof resolvedValue === 'function') {
130
+ return (...args: Array<unknown>) => {
131
+ void reactivity._ver
132
+ return toReactiveProxy(
133
+ (resolvedValue as Function).apply(target, args),
134
+ )
135
+ }
136
+ }
137
+
138
+ void reactivity._ver
139
+ return toReactiveProxy(resolvedValue)
140
+ },
141
+ })
142
+
143
+ proxyCache.set(value, proxy)
144
+ return proxy
145
+ }
146
+
147
+ return toReactiveProxy(table)
148
+ }
@@ -0,0 +1,48 @@
1
+ import { createColumnHelper as coreCreateColumnHelper } from '@tanstack/table-core'
2
+ import { createTable } from './createTable'
3
+ import type { AlpineTable } from './createTable'
4
+ import type { RowData, TableFeatures, TableOptions } from '@tanstack/table-core'
5
+
6
+ export type CreateTableHookOptions<TFeatures extends TableFeatures> = Omit<
7
+ TableOptions<TFeatures, any>,
8
+ 'columns' | 'data' | 'state'
9
+ >
10
+
11
+ export type AppAlpineTable<
12
+ TFeatures extends TableFeatures,
13
+ TData extends RowData,
14
+ > = AlpineTable<TFeatures, TData>
15
+
16
+ export type AppColumnHelper<
17
+ TFeatures extends TableFeatures,
18
+ TData extends RowData,
19
+ > = ReturnType<typeof coreCreateColumnHelper<TFeatures, TData>>
20
+
21
+ export function createTableHook<TFeatures extends TableFeatures>({
22
+ ...defaultTableOptions
23
+ }: CreateTableHookOptions<TFeatures>) {
24
+ function createAppColumnHelper<TData extends RowData>(): AppColumnHelper<
25
+ TFeatures,
26
+ TData
27
+ > {
28
+ return coreCreateColumnHelper<TFeatures, TData>()
29
+ }
30
+
31
+ function createAppTable<TData extends RowData>(
32
+ tableOptions: Omit<TableOptions<TFeatures, TData>, 'features'>,
33
+ ): AppAlpineTable<TFeatures, TData> {
34
+ // Merge default options with provided options (provided takes precedence)
35
+ const mergedOptions = {
36
+ ...defaultTableOptions,
37
+ ...tableOptions,
38
+ } as TableOptions<TFeatures, TData>
39
+
40
+ return createTable<TFeatures, TData>(mergedOptions)
41
+ }
42
+
43
+ return {
44
+ appFeatures: defaultTableOptions.features as TFeatures,
45
+ createAppColumnHelper,
46
+ createAppTable,
47
+ }
48
+ }
@@ -0,0 +1 @@
1
+ export * from './flexRender'
@@ -0,0 +1,100 @@
1
+ import type {
2
+ Cell,
3
+ CellData,
4
+ Header,
5
+ RowData,
6
+ TableFeatures,
7
+ } from '@tanstack/table-core'
8
+
9
+ /**
10
+ * Renders an Alpine table value with the provided context props.
11
+ *
12
+ * Use this lower-level helper for custom header, cell, or footer renderers when
13
+ * you already have the render function and context. `FlexRender` is the
14
+ * convenience wrapper for table cell/header/footer objects. Renderers typically
15
+ * return a string of markup that you render into the DOM with `x-html`.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * flexRender(cell.column.columnDef.cell, cell.getContext())
20
+ * ```
21
+ */
22
+ export function flexRender<TProps extends object>(
23
+ render: any,
24
+ props: TProps,
25
+ ): any {
26
+ if (typeof render === 'function') {
27
+ return render(props)
28
+ }
29
+ return render
30
+ }
31
+
32
+ /**
33
+ * Simplified wrapper of `flexRender`. Use this utility function to render headers, cells, or footers with custom markup.
34
+ * Only one prop (`cell`, `header`, or `footer`) may be passed.
35
+ * @example
36
+ * ```html
37
+ * <th x-html="FlexRender({ header })"></th>
38
+ * <td x-html="FlexRender({ cell })"></td>
39
+ * <th x-html="FlexRender({ footer: header })"></th>
40
+ * ```
41
+ *
42
+ * This replaces calling `flexRender` directly like this:
43
+ * ```ts
44
+ * flexRender(cell.column.columnDef.cell, cell.getContext())
45
+ * flexRender(header.column.columnDef.header, header.getContext())
46
+ * flexRender(footer.column.columnDef.footer, footer.getContext())
47
+ * ```
48
+ */
49
+ export type FlexRenderProps<
50
+ TFeatures extends TableFeatures,
51
+ TData extends RowData,
52
+ TValue extends CellData = CellData,
53
+ > =
54
+ | { cell: Cell<TFeatures, TData, TValue>; header?: never; footer?: never }
55
+ | {
56
+ header: Header<TFeatures, TData, TValue>
57
+ cell?: never
58
+ footer?: never
59
+ }
60
+ | {
61
+ footer: Header<TFeatures, TData, TValue>
62
+ cell?: never
63
+ header?: never
64
+ }
65
+
66
+ /**
67
+ * Simplified wrapper of `flexRender`. Use this utility function to render headers, cells, or footers with custom markup.
68
+ * Only one prop (`cell`, `header`, or `footer`) may be passed.
69
+ * @example
70
+ * ```html
71
+ * <th x-html="FlexRender({ header })"></th>
72
+ * <td x-html="FlexRender({ cell })"></td>
73
+ * <th x-html="FlexRender({ footer: header })"></th>
74
+ * ```
75
+ */
76
+ export function FlexRender<
77
+ TFeatures extends TableFeatures,
78
+ TData extends RowData,
79
+ TValue extends CellData = CellData,
80
+ >(props: FlexRenderProps<TFeatures, TData, TValue>): any {
81
+ if ('cell' in props && props.cell) {
82
+ return flexRender(props.cell.column.columnDef.cell, props.cell.getContext())
83
+ }
84
+
85
+ if ('header' in props && props.header) {
86
+ return flexRender(
87
+ props.header.column.columnDef.header,
88
+ props.header.getContext(),
89
+ )
90
+ }
91
+
92
+ if ('footer' in props && props.footer) {
93
+ return flexRender(
94
+ props.footer.column.columnDef.footer,
95
+ props.footer.getContext(),
96
+ )
97
+ }
98
+
99
+ return null
100
+ }
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from '@tanstack/table-core'
2
+
3
+ export * from './flexRender'
4
+ export * from './createTable'
5
+ export * from './createTableHook'
@@ -0,0 +1,41 @@
1
+ import { batch, createAtom } from '@tanstack/store'
2
+ import type {
3
+ TableAtomOptions,
4
+ TableReactivityBindings,
5
+ } from '@tanstack/table-core/reactivity'
6
+
7
+ /**
8
+ * Creates the table-core reactivity bindings used by the Alpine adapter.
9
+ *
10
+ * Alpine uses TanStack Store atoms directly. Table instance reads
11
+ * are then exposed to Alpine through the proxy wrapper in `createTable`.
12
+ */
13
+ export function alpineReactivity(): TableReactivityBindings {
14
+ return {
15
+ createOptionsStore: true,
16
+ wrapExternalAtoms: false,
17
+ addSubscription: () => {
18
+ throw new Error(
19
+ 'Feature not supported in current reactivity implementation',
20
+ )
21
+ },
22
+ unmount: () => {
23
+ throw new Error(
24
+ 'Feature not supported in current reactivity implementation',
25
+ )
26
+ },
27
+ schedule: (fn) => queueMicrotask(() => fn()),
28
+ batch,
29
+ untrack: (fn) => fn(),
30
+ createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {
31
+ return createAtom(() => fn(), {
32
+ compare: options?.compare,
33
+ })
34
+ },
35
+ createWritableAtom: <T>(value: T, options?: TableAtomOptions<T>) => {
36
+ return createAtom(value, {
37
+ compare: options?.compare,
38
+ })
39
+ },
40
+ }
41
+ }