Skip to content

Commit 46b347b

Browse files
committed
feat: add angular devtools
1 parent bbaeb46 commit 46b347b

16 files changed

Lines changed: 446 additions & 3 deletions

File tree

examples/angular/composable-tables/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
"@angular/platform-browser": "^21.2.11",
1919
"@angular/router": "^21.2.11",
2020
"@faker-js/faker": "^10.4.0",
21+
"@tanstack/angular-devtools": "https://pkg.pr.new/TanStack/devtools/@tanstack/angular-devtools@368",
2122
"@tanstack/angular-table": "^9.0.0-alpha.45",
23+
"@tanstack/angular-table-devtools": "^9.0.0-alpha.43",
2224
"rxjs": "~7.8.2",
2325
"tslib": "^2.8.1"
2426
},
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
1-
import { provideBrowserGlobalErrorListeners } from '@angular/core'
1+
import { isDevMode, provideBrowserGlobalErrorListeners } from '@angular/core'
2+
import { provideTanStackDevtools } from '@tanstack/angular-devtools/provider'
23
import type { ApplicationConfig } from '@angular/core'
34

45
export const appConfig: ApplicationConfig = {
5-
providers: [provideBrowserGlobalErrorListeners()],
6+
providers: [
7+
provideBrowserGlobalErrorListeners(),
8+
isDevMode()
9+
? provideTanStackDevtools(() => ({
10+
plugins: [
11+
{
12+
name: 'TanStack Table',
13+
render: () =>
14+
import('@tanstack/angular-table-devtools').then((m) =>
15+
m.TableDevtoolsPanel(),
16+
),
17+
},
18+
],
19+
}))
20+
: [],
21+
],
622
}

examples/angular/composable-tables/src/app/app.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { ChangeDetectionStrategy, Component } from '@angular/core'
2+
import { tableDevtoolsPlugin } from '@tanstack/angular-table-devtools'
23
import { UsersTable } from './components/users-table/users-table'
34
import { ProductsTable } from './components/products-table/products-table'
5+
import type { TanStackDevtoolsAngularPlugin } from '@tanstack/angular-devtools'
46

57
@Component({
68
selector: 'app-root',
@@ -24,4 +26,11 @@ import { ProductsTable } from './components/products-table/products-table'
2426
`,
2527
changeDetection: ChangeDetectionStrategy.OnPush,
2628
})
27-
export class App {}
29+
export class App {
30+
readonly plugins: Array<TanStackDevtoolsAngularPlugin> = [
31+
tableDevtoolsPlugin(() => ({
32+
theme: 'dark',
33+
devtoolsOpen: true,
34+
})),
35+
]
36+
}

examples/angular/composable-tables/src/app/components/products-table/products-table.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
TanStackTableCell,
77
TanStackTableHeader,
88
} from '@tanstack/angular-table'
9+
import { injectTanStackTableDevtools } from '@tanstack/angular-table-devtools'
910
import { makeProductData } from '../../makeData'
1011
import { createAppColumnHelper, injectAppTable } from '../../table'
1112
import type { Product } from '../../makeData'
@@ -68,4 +69,8 @@ export class ProductsTable {
6869

6970
refreshData = () => this.data.set(makeProductData(1_000))
7071
stressTest = () => this.data.set(makeProductData(200_000))
72+
73+
constructor() {
74+
injectTanStackTableDevtools(() => this.table, 'products-table')
75+
}
7176
}

examples/angular/composable-tables/src/app/components/users-table/users-table.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
TanStackTableHeader,
88
flexRenderComponent,
99
} from '@tanstack/angular-table'
10+
import { injectTanStackTableDevtools } from '@tanstack/angular-table-devtools'
1011
import { makeData } from '../../makeData'
1112
import { createAppColumnHelper, injectAppTable } from '../../table'
1213
import type { Person } from '../../makeData'
@@ -79,4 +80,8 @@ export class UsersTable {
7980

8081
refreshData = () => this.data.set(makeData(1_000))
8182
stressTest = () => this.data.set(makeData(200_000))
83+
84+
constructor() {
85+
injectTanStackTableDevtools(() => this.table, 'users-table')
86+
}
8287
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @ts-check
2+
3+
import rootConfig from '../../eslint.config.js'
4+
5+
/** @type {any} */
6+
const config = [...rootConfig]
7+
8+
export default config
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "@tanstack/angular-table-devtools",
3+
"version": "9.0.0-alpha.43",
4+
"description": "Angular devtools for TanStack Table.",
5+
"license": "MIT",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/TanStack/table.git",
9+
"directory": "packages/angular-table-devtools"
10+
},
11+
"homepage": "https://tanstack.com/table",
12+
"funding": {
13+
"type": "github",
14+
"url": "https://github.com/sponsors/tannerlinsley"
15+
},
16+
"keywords": [
17+
"angular",
18+
"tanstack",
19+
"table",
20+
"devtools"
21+
],
22+
"scripts": {
23+
"clean": "rimraf ./build && rimraf ./dist",
24+
"test:eslint": "eslint ./src",
25+
"test:lib": "vitest --passWithNoTests",
26+
"test:lib:dev": "pnpm test:lib --watch",
27+
"test:types": "tsc",
28+
"test:build": "publint --strict",
29+
"build": "tsdown"
30+
},
31+
"type": "module",
32+
"types": "dist/index.d.ts",
33+
"exports": {
34+
".": "./dist/index.js",
35+
"./production": "./dist/production.js",
36+
"./package.json": "./package.json"
37+
},
38+
"sideEffects": false,
39+
"engines": {
40+
"node": ">=20"
41+
},
42+
"files": [
43+
"dist",
44+
"src"
45+
],
46+
"dependencies": {
47+
"@tanstack/devtools-utils": "https://pkg.pr.new/TanStack/devtools/@tanstack/devtools-utils@368",
48+
"@tanstack/table-core": "workspace:*",
49+
"@tanstack/table-devtools": "workspace:*"
50+
},
51+
"peerDependencies": {
52+
"@angular/core": ">=21.0.0"
53+
}
54+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { TableDevtoolsCore } from '@tanstack/table-devtools'
2+
import { createAngularPanel } from '@tanstack/devtools-utils/angular'
3+
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/angular'
4+
5+
export interface TableDevtoolsAngularInit extends Partial<DevtoolsPanelProps> {}
6+
7+
const [TableDevtoolsPanelBase, TableDevtoolsPanelNoOpBase] =
8+
createAngularPanel(TableDevtoolsCore)
9+
10+
function resolvePanelProps(
11+
props?: TableDevtoolsAngularInit,
12+
): DevtoolsPanelProps {
13+
return {
14+
theme: props?.theme ?? 'dark',
15+
devtoolsOpen: props?.devtoolsOpen ?? false,
16+
}
17+
}
18+
19+
type TableDevtoolsPanelComponent = () => (
20+
inputs: () => TableDevtoolsAngularInit,
21+
hostElement: HTMLElement,
22+
) => () => void
23+
24+
export const TableDevtoolsPanel: TableDevtoolsPanelComponent =
25+
() => (props, host) => {
26+
const panel = TableDevtoolsPanelBase()
27+
return panel(() => resolvePanelProps(props()), host)
28+
}
29+
30+
export const TableDevtoolsPanelNoOp: TableDevtoolsPanelComponent =
31+
() => (props, host) => {
32+
const panel = TableDevtoolsPanelNoOpBase()
33+
return () => panel
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { isDevMode } from '@angular/core'
2+
import * as plugin from './plugin'
3+
import * as Devtools from './TableDevtools'
4+
import * as inject from './injectTanStackTableDevtools'
5+
6+
export const TableDevtoolsPanel = isDevMode()
7+
? Devtools.TableDevtoolsPanel
8+
: Devtools.TableDevtoolsPanelNoOp
9+
10+
export const tableDevtoolsPlugin = isDevMode()
11+
? plugin.tableDevtoolsPlugin
12+
: plugin.tableDevtoolsNoOpPlugin
13+
14+
export type { TableDevtoolsAngularInit } from './TableDevtools'
15+
16+
export type { InjectTanStackTableDevtoolsOptions } from './injectTanStackTableDevtools'
17+
18+
export const injectTanStackTableDevtools = isDevMode()
19+
? inject.injectTanStackTableDevtools
20+
: inject.injectTanStackTableDevtoolsNoOp
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import {
2+
removeTableDevtoolsTarget,
3+
upsertTableDevtoolsTarget,
4+
} from '@tanstack/table-devtools'
5+
import {
6+
APP_ID,
7+
DestroyRef,
8+
Injectable,
9+
Injector,
10+
assertInInjectionContext,
11+
effect,
12+
inject,
13+
} from '@angular/core'
14+
import type { RowData, Table, TableFeatures } from '@tanstack/table-core'
15+
16+
export interface InjectTanStackTableDevtoolsOptions {
17+
enabled?: () => boolean
18+
injector?: Injector
19+
}
20+
21+
function normalizeName(name?: string) {
22+
const trimmedName = name?.trim()
23+
return trimmedName ? trimmedName : undefined
24+
}
25+
26+
let autoId = 0
27+
function generateId(): string {
28+
const appId = inject(APP_ID)
29+
return `tanstacktable-${appId}_${autoId++}${Date.now().toString(36)}`
30+
}
31+
32+
export function injectTanStackTableDevtools<
33+
TFeatures extends TableFeatures = TableFeatures,
34+
TData extends RowData = RowData,
35+
>(
36+
table: () => Table<TFeatures, TData> | undefined,
37+
name?: string,
38+
options?: InjectTanStackTableDevtoolsOptions,
39+
): void {
40+
const registrationId = generateId()
41+
const enabled = () => options?.enabled?.() ?? true
42+
assertInInjectionContext(injectTanStackTableDevtools)
43+
const injector = options?.injector ?? inject(Injector)
44+
const destroyRef = inject(DestroyRef)
45+
46+
effect(
47+
(onCleanup) => {
48+
const enabledValue = enabled()
49+
const tableValue = table()
50+
if (!enabledValue || !tableValue) {
51+
removeTableDevtoolsTarget(registrationId)
52+
}
53+
upsertTableDevtoolsTarget({
54+
id: registrationId,
55+
table: tableValue,
56+
name: normalizeName(name),
57+
})
58+
onCleanup(() => {
59+
removeTableDevtoolsTarget(registrationId)
60+
})
61+
},
62+
{ injector },
63+
)
64+
65+
destroyRef.onDestroy(() => {
66+
removeTableDevtoolsTarget(registrationId)
67+
})
68+
}
69+
70+
export function injectTanStackTableDevtoolsNoOp<
71+
TFeatures extends TableFeatures = TableFeatures,
72+
TData extends RowData = RowData,
73+
>(
74+
_table: Table<TFeatures, TData> | undefined,
75+
_name?: string,
76+
_options?: InjectTanStackTableDevtoolsOptions,
77+
): void {}

0 commit comments

Comments
 (0)