Skip to content

Commit ad26f61

Browse files
riccardoperraAlemTuzlakautofix-ci[bot]
authored
feat(angular): angular adapter and utils (#368)
* feat(angular-devtools): create angular adapter package Add the @tanstack/angular-devtools package with: - TanStackDevtoolsComponent: standalone Angular component that wraps TanStackDevtoolsCore - Plugin system supporting Angular components rendered into devtools containers - Type definitions for Angular-specific plugin and init configuration - Build config using @analogjs/vite-plugin-angular for AOT compilation * fix(angular-devtools): add reactivity for input changes, remove unused RenderArray * feat(devtools-utils): add angular support * fix: resolve angular build issues - Remove @analogjs/vite-plugin-angular from build (produces empty chunks for library builds). Use plain esbuild via Vite instead - Angular AOT compilation happens at consumer's build time. - Upgrade Angular dev deps from ^19 to ^20 for TypeScript 5.9 compat. - Remove @angular/build dep (only needed by analogjs plugin). - Add @tanstack/angular-devtools workspace override to root. * ci: apply automated fixes * fix: resolve lint, knip, and sherif issues - Fix array-type ESLint rule in angular-devtools - Fix import/consistent-type-specifier-style in devtools-utils angular - Sort peerDependencies alphabetically (sherif) - Remove unused devDependencies flagged by knip - Remove angularCompilerOptions from tsconfig (not using ngc) * feat: add Angular support with setup, adapter, and custom plugin documentation * feat(angular): angular adapter add utils and some examples, fix build * ci: apply automated fixes * feat: Add angular adapter and devtools-utils/angular * remove afterNextRender in devtools-utils Since angular-devtools already run the code within afterNextRender in browser env, we don't like to wrap the panel returned from utils * fix examples * fix angular devtools wrong pnpm link * feat(angular-devtools): add with-devtools provider * docs(angular-devtools): update docs * ci: apply automated fixes * chore(angular-devtools): fix examples dependencies and knip issues * feat(angular-devtools): rename withDevtools to provideTanStackDevtools * Add a11y plugin for angular * chore(deps): update @tanstack/devtools and related packages * ci: apply automated fixes --------- Co-authored-by: Alem Tuzlak <t.zlak@hotmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent f1844a2 commit ad26f61

124 files changed

Lines changed: 6965 additions & 273 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/config.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@
4545
{ "label": "Basic Setup", "to": "framework/vue/basic-setup" },
4646
{ "label": "Vue Adapter", "to": "framework/vue/adapter" }
4747
]
48+
},
49+
{
50+
"label": "angular",
51+
"children": [
52+
{ "label": "Basic Setup", "to": "framework/angular/basic-setup" },
53+
{ "label": "Angular Adapter", "to": "framework/angular/adapter" }
54+
]
4855
}
4956
]
5057
},
@@ -89,6 +96,12 @@
8996
"children": [
9097
{ "label": "Custom Plugins", "to": "framework/vue/guides/custom-plugins" }
9198
]
99+
},
100+
{
101+
"label": "angular",
102+
"children": [
103+
{ "label": "Custom Plugins", "to": "framework/angular/guides/custom-plugins" }
104+
]
92105
}
93106
]
94107
},
@@ -121,6 +134,12 @@
121134
"children": [
122135
{ "label": "Vue Reference", "to": "framework/vue/reference/index" }
123136
]
137+
},
138+
{
139+
"label": "angular",
140+
"children": [
141+
{ "label": "Angular Reference", "to": "framework/angular/reference/index" }
142+
]
124143
}
125144
]
126145
},

docs/devtools-utils.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/preact'
3737

3838
// Vue
3939
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/vue'
40+
41+
// Angular
42+
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/angular'
4043
```
4144

4245
## React
@@ -252,6 +255,49 @@ const [MyPanel, NoOpPanel] = createVuePanel(MyDevtoolsCore)
252255

253256
The panel component accepts `theme` and `devtoolsProps` as props. It mounts the core instance into a `div` element on `onMounted` and calls `unmount()` on `onUnmounted`.
254257

258+
## Angular
259+
260+
### createAngularPlugin
261+
262+
The Angular factory takes a `name` string and an Angular component class as separate arguments, similar to the Vue API.
263+
264+
**Signature:**
265+
266+
```ts
267+
function createAngularPlugin(
268+
name: string,
269+
component: Type<any>,
270+
): readonly [Plugin, NoOpPlugin]
271+
```
272+
273+
**Usage:**
274+
275+
```ts
276+
import { createAngularPlugin } from '@tanstack/devtools-utils/angular'
277+
import { MyStorePanelComponent } from './my-store-panel.component'
278+
279+
const [MyPlugin, NoOpPlugin] = createAngularPlugin('My Store', MyStorePanelComponent)
280+
```
281+
282+
The returned functions:
283+
284+
- **`Plugin(inputs?)`** -- returns `{ name, component, inputs }` where `component` is your Angular component class.
285+
- **`NoOpPlugin(inputs?)`** -- returns `{ name, component: NoOpComponent, inputs }` where the component is an empty standalone component (renders nothing visible).
286+
287+
Both accept an optional `inputs` object that gets forwarded to the component via `setInput()`.
288+
289+
### createAngularPanel
290+
291+
For class-based devtools cores, Angular provides `createAngularPanel`. It creates a standalone Angular component that handles mounting and unmounting the core class:
292+
293+
```ts
294+
import { createAngularPanel } from '@tanstack/devtools-utils/angular'
295+
296+
const [MyPanel, NoOpPanel] = createAngularPanel(MyDevtoolsCore)
297+
```
298+
299+
The panel component accepts `theme` and `devtoolsProps` as signal inputs. It mounts the core instance into a `div` element using `afterNextRender` and calls `unmount()` via `DestroyRef.onDestroy`.
300+
255301
## When to Use Factories vs Manual Plugin Objects
256302

257303
**Use the factories** when you are building a reusable library plugin that will be published as a package. The factories ensure:

docs/framework/angular/adapter.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
title: TanStack Devtools Angular Adapter
3+
id: adapter
4+
---
5+
6+
The Angular adapter wraps `TanStackDevtoolsCore` in an Angular standalone component, using Angular's `createComponent` and `ApplicationRef.attachView` to dynamically render plugins into the correct DOM containers managed by the devtools shell.
7+
8+
## Installation
9+
10+
```sh
11+
npm install @tanstack/angular-devtools
12+
```
13+
14+
## Component Inputs
15+
16+
The `TanStackDevtools` (selector: `tanstack-devtools`) accepts the following signal-based inputs, defined by the `TanStackDevtoolsAngularInit` interface:
17+
18+
| Input | Type | Description |
19+
| --- | --- | --- |
20+
| `plugins` | `TanStackDevtoolsAngularPlugin[]` | Array of plugins to render inside the devtools panel. |
21+
| `config` | `Partial<TanStackDevtoolsConfig>` | Configuration for the devtools shell. Sets the initial state on first load; afterwards settings are persisted in local storage. |
22+
| `eventBusConfig` | `ClientEventBusConfig` | Configuration for the TanStack Devtools client event bus. |
23+
24+
## Plugin Type
25+
26+
Each plugin in the `plugins` array must conform to the `TanStackDevtoolsAngularPlugin` type:
27+
28+
```ts
29+
type TanStackDevtoolsAngularPlugin = {
30+
id?: string
31+
render: TanStackDevtoolsAngularPluginRender
32+
name: string | Type<any>
33+
inputs?: Record<string, any>
34+
defaultOpen?: boolean
35+
}
36+
```
37+
38+
| Field | Type | Description |
39+
|---------------| --- | --- |
40+
| `id` | `string` (optional) | Unique identifier for the plugin. |
41+
| `render` | `Type<any>` | The Angular component class to render as the plugin panel content. |
42+
| `name` | `string \| Type<any>` | Display name for the tab title. Can be a plain string or an Angular component class for custom rendering. |
43+
| `inputs` | `Record<string, any>` (optional) | Additional inputs passed to the plugin component via `setInput()`. |
44+
| `defaultOpen` | `boolean` (optional) | Whether this plugin tab should be open by default. |
45+
46+
## Key Differences from Other Frameworks
47+
48+
The Angular adapter uses `component` (an Angular component class reference) instead of `render` (a JSX element) in plugin definitions. Inputs are provided through the `inputs` field and bound to the component with `setInput()`, rather than being embedded directly in a JSX expression or passed via `v-bind`.
49+
50+
```typescript
51+
import { Component } from '@angular/core'
52+
import { TanStackDevtools } from '@tanstack/angular-devtools'
53+
import { AngularQueryDevtoolsPanel } from '@tanstack/angular-query-devtools'
54+
55+
@Component({
56+
selector: 'app-root',
57+
standalone: true,
58+
imports: [TanStackDevtools],
59+
template: `
60+
<tanstack-devtools [plugins]="plugins" />
61+
`,
62+
})
63+
export class App {
64+
plugins = [
65+
{
66+
name: 'Angular Query',
67+
render: AngularQueryDevtoolsPanel,
68+
inputs: { style: 'height: 100%' },
69+
},
70+
]
71+
}
72+
```
73+
74+
## Exports
75+
76+
The `@tanstack/angular-devtools` package exports:
77+
78+
- **`TanStackDevtools`** -- The main Angular standalone component that renders the devtools panel.
79+
- **`TanStackDevtoolsAngularPlugin`** (type) -- The type for plugin definitions.
80+
- **`TanStackDevtoolsAngularInit`** (type) -- The inputs interface for the `TanStackDevtoolsComponent`.
81+
82+
The package depends on `@tanstack/devtools` (the core package), which provides `TanStackDevtoolsCore`, `TanStackDevtoolsConfig`, `ClientEventBusConfig`, and other core utilities.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
title: Basic setup
3+
id: basic-setup
4+
---
5+
6+
TanStack Devtools provides you with an easy-to-use and modular client that allows you to compose multiple devtools into one easy-to-use panel.
7+
8+
## Setup
9+
10+
Install the [TanStack Devtools](https://www.npmjs.com/package/@tanstack/angular-devtools) library. This will install the devtools core as well as provide you with the Angular-specific adapter.
11+
12+
```bash
13+
npm i @tanstack/angular-devtools
14+
```
15+
16+
Next, in the root of your application, import the `TanStackDevtoolsComponent` from `@tanstack/angular-devtools` and add it to your template.
17+
18+
```typescript
19+
import { Component } from '@angular/core'
20+
import { TanStackDevtoolsComponent } from '@tanstack/angular-devtools'
21+
22+
@Component({
23+
selector: 'app-root',
24+
standalone: true,
25+
imports: [TanStackDevtools],
26+
template: `
27+
<app-content />
28+
<tanstack-devtools />
29+
`,
30+
})
31+
export class App {}
32+
```
33+
34+
Import the desired devtools and provide them to the `TanStackDevtools` via the `[plugins]` input along with a label for the menu.
35+
36+
```typescript
37+
import { Component } from '@angular/core'
38+
import { TanStackDevtools } from '@tanstack/angular-devtools'
39+
import type { TanStackDevtoolsAngularPlugin } from '@tanstack/angular-devtools'
40+
import { AngularQueryDevtoolsPanel } from '@tanstack/angular-query-devtools'
41+
42+
@Component({
43+
selector: 'app-root',
44+
standalone: true,
45+
imports: [TanStackDevtools],
46+
template: `
47+
<app-content />
48+
<tanstack-devtools [plugins]="plugins" />
49+
`,
50+
})
51+
export class AppComponent {
52+
plugins: Array<TanStackDevtoolsAngularPlugin> = [
53+
{
54+
name: 'Angular Query',
55+
render: AngularQueryDevtoolsPanel,
56+
},
57+
]
58+
}
59+
```
60+
61+
Finally, add any additional configuration you desire to the `TanStackDevtools`. More information can be found under the [TanStack Devtools Configuration](../../configuration) section.

0 commit comments

Comments
 (0)