chartgpu-angular 0.0.0-stage → 22.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Naren
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,124 @@
1
- # Temporary Holding Version
1
+ # chartgpu-angular
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ An Angular wrapper for ChartGPU, a chart rendering runtime for building responsive, interactive charts in Angular templates.
4
+
5
+ This is an unofficial wrapper library. It is not affiliated with, endorsed by, or sponsored by ChartGPU or any other upstream vendor unless explicitly stated otherwise.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/chartgpu-angular.svg)](https://www.npmjs.com/package/chartgpu-angular)
8
+ [![npm downloads](https://img.shields.io/npm/dy/chartgpu-angular.svg)](https://www.npmjs.com/package/chartgpu-angular)
9
+ [![GitHub stars](https://img.shields.io/github/stars/kai1992cool/chartgpu-angular.svg)](https://github.com/kai1992cool/chartgpu-angular)
10
+ [![license](https://img.shields.io/npm/l/chartgpu-angular.svg)](https://github.com/kai1992cool/chartgpu-angular/blob/master/LICENSE)
11
+
12
+ ## Features
13
+
14
+ - Uses ChartGPU rendering through Angular components and directives.
15
+ - Configure charts with standard options and theme updates.
16
+ - Define chart content with Angular templates.
17
+ - Bind chart events as Angular outputs.
18
+ - Use shared GPU context handling for dashboards and multiple charts.
19
+
20
+ ## Installation
21
+
22
+ ### 1. Install the package
23
+
24
+ ```bash
25
+ npm install chartgpu-angular
26
+ ```
27
+
28
+ ## Key Implementation Notes:
29
+
30
+ * **This project is an unofficial wrapper library.**
31
+ * **WebGPU is required for rendering.**
32
+ * **The shared GPU context service is intended for dashboard-style reuse.**
33
+
34
+ ## Angular version examples & Documentation
35
+
36
+ StackBlitz examples will be added as each Angular version's rollout is published.
37
+
38
+ > If you click the link for Standalone and NgModule examples are stuck in clone step, please refresh the screen, the stackblitz will initialize
39
+
40
+ | Angular version | Standalone example | NgModule example | Documentation |
41
+ | --------------- | ------------------ | ---------------- | ------------- |
42
+ | Angular 14 | [Modular Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/14/modular) | [Standalone Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/14/standalone) | [Storybook](https://kai1992cool.github.io/chartgpu-angular/demos?version=14) |
43
+ | Angular 15 | [Modular Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/15/modular) | [Standalone Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/15/standalone) | [Storybook](https://kai1992cool.github.io/chartgpu-angular/demos?version=15) |
44
+ | Angular 16 | [Modular Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/16/modular) | [Standalone Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/16/standalone) | [Storybook](https://kai1992cool.github.io/chartgpu-angular/demos?version=16) |
45
+ | Angular 17 | [Modular Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/17/modular) | [Standalone Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/17/standalone) | [Storybook](https://kai1992cool.github.io/chartgpu-angular/demos?version=17) |
46
+ | Angular 18 | [Modular Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/18/modular) | [Standalone Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/18/standalone) | [Storybook](https://kai1992cool.github.io/chartgpu-angular/demos?version=18) |
47
+ | Angular 19 | [Modular Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/19/modular) | [Standalone Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/19/standalone) | [Storybook](https://kai1992cool.github.io/chartgpu-angular/demos?version=19) |
48
+ | Angular 20 | [Modular Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/20/modular) | [Standalone Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/20/standalone) | [Storybook](https://kai1992cool.github.io/chartgpu-angular/demos?version=20) |
49
+ | Angular 21 | [Modular Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/21/modular) | [Standalone Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/21/standalone) | [Storybook](https://kai1992cool.github.io/chartgpu-angular/demos?version=21) |
50
+ | Angular 22 | [Modular Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/22/modular) | [Standalone Demo](https://stackblitz.com/github/kai1992cool/chartgpu-angular/tree/main/demos/22/standalone) | [Storybook](https://kai1992cool.github.io/chartgpu-angular/demos?version=22) |
51
+
52
+ Example usage:
53
+
54
+ ```ts
55
+ import { Component } from '@angular/core';
56
+ import { ChartGPUComponent, provideChartGpuContext } from 'chartgpu-angular';
57
+
58
+ @Component({
59
+ standalone: true,
60
+ imports: [ChartGPUComponent],
61
+ providers: [provideChartGpuContext()],
62
+ template: `<lib-chartgpu-angular />`,
63
+ })
64
+ export class ExampleComponent {}
65
+ ```
66
+
67
+ ## Configuring Styling
68
+
69
+ ### 1. Simplest way
70
+
71
+ The default setup should include the required chart styles for the component, so no separate CSS setup is usually needed.
72
+
73
+ ### 2. Configure chart CSS (when needed)
74
+ If you need additional styles for chart modules or custom visual effects, serve the CSS files as assets in your application configuration.
75
+
76
+ Then pass the asset URL in the appropriate style injection option used by the component.
77
+
78
+ ## Setup
79
+
80
+ Choose the setup that matches your Angular application.
81
+
82
+ ### Standalone application
83
+
84
+ Import `ChartGPUComponent` from `chartgpu-angular` and add it to the `imports` array of each standalone component that uses it. Add `provideChartGpuContext()` to the component or application providers when you want a shared GPU context service:
85
+
86
+ ```ts
87
+ import { Component } from '@angular/core';
88
+ import { ChartGPUComponent, provideChartGpuContext } from 'chartgpu-angular';
89
+
90
+ @Component({
91
+ standalone: true,
92
+ imports: [ChartGPUComponent],
93
+ providers: [provideChartGpuContext()],
94
+ template: `<lib-chartgpu-angular />`,
95
+ })
96
+ export class ExampleComponent {}
97
+ ```
98
+
99
+ ### NgModule application
100
+
101
+ Import `ChartGPUComponent` in the `imports` array of the module that declares the component using it. If you need the shared GPU context service, provide it from the module providers with `provideChartGpuContext()`:
102
+
103
+ ```ts
104
+ import { NgModule } from '@angular/core';
105
+ import { BrowserModule } from '@angular/platform-browser';
106
+ import { AppComponent } from './app.component';
107
+ import { ChartGPUComponent, provideChartGpuContext } from 'chartgpu-angular';
108
+
109
+ @NgModule({
110
+ declarations: [AppComponent],
111
+ imports: [BrowserModule, ChartGPUComponent],
112
+ providers: [provideChartGpuContext()],
113
+ bootstrap: [AppComponent],
114
+ })
115
+ export class AppModule {}
116
+ ```
117
+
118
+ ## Documentation and demos
119
+
120
+ - [ChartGPU documentation](https://chartgpu.io/docs/)
121
+
122
+ ## License
123
+
124
+ MIT
@@ -0,0 +1,682 @@
1
+ import { NgStyle } from "@angular/common";
2
+ import * as i0 from "@angular/core";
3
+ import { ChangeDetectionStrategy, Component, Directive, Injectable, afterNextRender, computed, effect, input, makeEnvironmentProviders, output, signal, untracked, viewChild } from "@angular/core";
4
+ import { ChartGPU, connectCharts, createPipelineCache } from "chartgpu";
5
+ var ChartGpuAngularComponent = class ChartGpuAngularComponent {
6
+ destroyRef;
7
+ options = input.required(...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
8
+ gpuContext = input(null, ...ngDevMode ? [{ debugName: "gpuContext" }] : /* istanbul ignore next */ []);
9
+ theme = input(void 0, ...ngDevMode ? [{ debugName: "theme" }] : /* istanbul ignore next */ []);
10
+ className = input(...ngDevMode ? [void 0, { debugName: "className" }] : /* istanbul ignore next */ []);
11
+ style = input(...ngDevMode ? [void 0, { debugName: "style" }] : /* istanbul ignore next */ []);
12
+ ready = output();
13
+ chartReady = output();
14
+ chartDispose = output();
15
+ resize = output();
16
+ click = output();
17
+ chartClick = output();
18
+ mouseOver = output();
19
+ mouseOut = output();
20
+ crosshairMove = output();
21
+ dataAppend = output();
22
+ zoomChange = output();
23
+ zoomRangeChange = output();
24
+ deviceLost = output();
25
+ chartError = output();
26
+ host = viewChild("host", ...ngDevMode ? [{ debugName: "host" }] : /* istanbul ignore next */ []);
27
+ canvasHost = viewChild("canvasHost", ...ngDevMode ? [{ debugName: "canvasHost" }] : /* istanbul ignore next */ []);
28
+ chartInstance = signal(null, ...ngDevMode ? [{ debugName: "chartInstance" }] : /* istanbul ignore next */ []);
29
+ initializationError = signal(null, ...ngDevMode ? [{ debugName: "initializationError" }] : /* istanbul ignore next */ []);
30
+ chartContainer;
31
+ createdWithOptions;
32
+ resizeTimeout;
33
+ resizeObserver;
34
+ removeChartListeners;
35
+ destroying = false;
36
+ constructor(destroyRef) {
37
+ this.destroyRef = destroyRef;
38
+ this.destroyRef.onDestroy(() => {
39
+ this.resizeObserver?.disconnect();
40
+ if (this.resizeTimeout !== void 0) clearTimeout(this.resizeTimeout);
41
+ this.disposeChart();
42
+ });
43
+ afterNextRender(() => {
44
+ const container = this.host()?.nativeElement;
45
+ if (container) this.observeResize(container);
46
+ });
47
+ effect((onCleanup) => {
48
+ const container = this.canvasHost()?.nativeElement;
49
+ const options = this.options();
50
+ const gpuContext = this.gpuContext();
51
+ const theme = this.theme();
52
+ this.initializationError.set(null);
53
+ if (!container) {
54
+ this.disposeChart();
55
+ return;
56
+ }
57
+ if (typeof navigator === "undefined" || !("gpu" in navigator)) {
58
+ this.reportError(/* @__PURE__ */ new Error("WebGPU not supported in this browser"));
59
+ return;
60
+ }
61
+ if (untracked(() => this.chartInstance()) && this.chartContainer === container) return;
62
+ let cancelled = false;
63
+ let createdInstance;
64
+ const initialOptions = this.getEffectiveOptions(options, theme);
65
+ (gpuContext ? ChartGPU.create(container, initialOptions, gpuContext) : ChartGPU.create(container, initialOptions)).then((instance) => {
66
+ createdInstance = instance;
67
+ if (cancelled) {
68
+ instance.dispose();
69
+ return;
70
+ }
71
+ try {
72
+ const latest = untracked(() => ({
73
+ options: this.options(),
74
+ theme: this.theme()
75
+ }));
76
+ if (latest.options !== options || latest.theme !== theme) instance.setOption(this.getEffectiveOptions(latest.options, latest.theme));
77
+ this.createdWithOptions = latest;
78
+ this.chartContainer = container;
79
+ this.chartInstance.set(instance);
80
+ this.removeChartListeners = this.listenToChart(instance);
81
+ this.ready.emit({ container });
82
+ this.chartReady.emit(instance);
83
+ const range = instance.getZoomRange();
84
+ if (range) this.emitZoomRange(range);
85
+ } catch (cause) {
86
+ instance.dispose();
87
+ throw cause;
88
+ }
89
+ }).catch((cause) => {
90
+ if (cancelled) return;
91
+ if (createdInstance && this.chartInstance() !== createdInstance && !createdInstance.disposed) createdInstance.dispose();
92
+ this.reportError(cause);
93
+ });
94
+ onCleanup(() => {
95
+ cancelled = true;
96
+ if (this.chartContainer === container) this.disposeChart();
97
+ });
98
+ }, { allowSignalWrites: true });
99
+ effect(() => {
100
+ const options = this.options();
101
+ const theme = this.theme();
102
+ const instance = this.chartInstance();
103
+ if (!instance || instance.disposed) return;
104
+ if (this.createdWithOptions?.options === options && this.createdWithOptions.theme === theme) {
105
+ this.createdWithOptions = void 0;
106
+ return;
107
+ }
108
+ try {
109
+ instance.setOption(this.getEffectiveOptions(options, theme));
110
+ } catch (cause) {
111
+ this.reportError(cause);
112
+ }
113
+ }, { allowSignalWrites: true });
114
+ }
115
+ emitClick(event) {
116
+ this.click.emit({
117
+ x: event.offsetX,
118
+ y: event.offsetY
119
+ });
120
+ }
121
+ ngOnDestroy() {
122
+ this.destroying = true;
123
+ }
124
+ getChart() {
125
+ const instance = this.chartInstance();
126
+ return instance && !instance.disposed ? instance : null;
127
+ }
128
+ getContainer() {
129
+ return this.canvasHost()?.nativeElement ?? null;
130
+ }
131
+ appendData(seriesIndex, newPoints, options) {
132
+ this.getChart()?.appendData(seriesIndex, newPoints, options);
133
+ }
134
+ renderFrame() {
135
+ return this.getChart()?.renderFrame() ?? false;
136
+ }
137
+ needsRender() {
138
+ return this.getChart()?.needsRender() ?? false;
139
+ }
140
+ getRenderMode() {
141
+ return this.getChart()?.getRenderMode() ?? "auto";
142
+ }
143
+ setRenderMode(mode) {
144
+ this.getChart()?.setRenderMode(mode);
145
+ }
146
+ setOption(options) {
147
+ this.getChart()?.setOption(options);
148
+ }
149
+ setZoomRange(start, end, source) {
150
+ this.getChart()?.setZoomRange(start, end, source);
151
+ }
152
+ setInteractionX(x, source) {
153
+ this.getChart()?.setInteractionX(x, source);
154
+ }
155
+ getInteractionX() {
156
+ return this.getChart()?.getInteractionX() ?? null;
157
+ }
158
+ hitTest(event) {
159
+ return this.getChart()?.hitTest(event) ?? null;
160
+ }
161
+ getEffectiveOptions(options, theme) {
162
+ return theme !== void 0 ? {
163
+ ...options,
164
+ theme
165
+ } : options;
166
+ }
167
+ listenToChart(instance) {
168
+ const click = (payload) => this.chartClick.emit(payload);
169
+ const mouseOver = (payload) => this.mouseOver.emit(payload);
170
+ const mouseOut = (payload) => this.mouseOut.emit(payload);
171
+ const crosshairMove = (payload) => this.crosshairMove.emit(payload);
172
+ const dataAppend = (payload) => this.dataAppend.emit(payload);
173
+ const zoomChange = (payload) => this.emitZoomRange(payload);
174
+ const deviceLost = (payload) => this.deviceLost.emit(payload);
175
+ instance.on("click", click);
176
+ instance.on("mouseover", mouseOver);
177
+ instance.on("mouseout", mouseOut);
178
+ instance.on("crosshairMove", crosshairMove);
179
+ instance.on("dataAppend", dataAppend);
180
+ instance.on("zoomRangeChange", zoomChange);
181
+ instance.on("deviceLost", deviceLost);
182
+ return () => {
183
+ if (instance.disposed) return;
184
+ instance.off("click", click);
185
+ instance.off("mouseover", mouseOver);
186
+ instance.off("mouseout", mouseOut);
187
+ instance.off("crosshairMove", crosshairMove);
188
+ instance.off("dataAppend", dataAppend);
189
+ instance.off("zoomRangeChange", zoomChange);
190
+ instance.off("deviceLost", deviceLost);
191
+ };
192
+ }
193
+ emitZoomRange(range) {
194
+ this.zoomChange.emit({ range: {
195
+ start: range.start,
196
+ end: range.end
197
+ } });
198
+ this.zoomRangeChange.emit({
199
+ start: range.start,
200
+ end: range.end
201
+ });
202
+ }
203
+ observeResize(container) {
204
+ if (typeof ResizeObserver === "undefined") return;
205
+ this.resizeObserver = new ResizeObserver((entries) => {
206
+ const entry = entries[0];
207
+ if (!entry) return;
208
+ const { width, height } = entry.contentRect;
209
+ this.resize.emit({
210
+ width,
211
+ height,
212
+ container
213
+ });
214
+ if (this.resizeTimeout !== void 0) clearTimeout(this.resizeTimeout);
215
+ this.resizeTimeout = setTimeout(() => {
216
+ this.chartInstance()?.resize();
217
+ this.resizeTimeout = void 0;
218
+ }, 100);
219
+ });
220
+ this.resizeObserver.observe(container);
221
+ }
222
+ reportError(cause) {
223
+ const error = cause instanceof Error ? cause : new Error(String(cause));
224
+ this.initializationError.set(error);
225
+ this.chartError.emit(error);
226
+ }
227
+ disposeChart() {
228
+ const instance = this.chartInstance();
229
+ this.removeChartListeners?.();
230
+ this.removeChartListeners = void 0;
231
+ if (instance && !instance.disposed) {
232
+ instance.dispose();
233
+ if (!this.destroying) this.chartDispose.emit();
234
+ }
235
+ this.chartInstance.set(null);
236
+ this.chartContainer = void 0;
237
+ this.createdWithOptions = void 0;
238
+ }
239
+ static ɵfac = i0.ɵɵngDeclareFactory({
240
+ minVersion: "12.0.0",
241
+ version: "22.2.3",
242
+ ngImport: i0,
243
+ type: ChartGpuAngularComponent,
244
+ deps: [{ token: i0.DestroyRef }],
245
+ target: i0.ɵɵFactoryTarget.Component
246
+ });
247
+ static ɵcmp = i0.ɵɵngDeclareComponent({
248
+ minVersion: "17.0.0",
249
+ version: "22.2.3",
250
+ type: ChartGpuAngularComponent,
251
+ isStandalone: true,
252
+ selector: "lib-chartgpu-angular",
253
+ inputs: {
254
+ options: {
255
+ classPropertyName: "options",
256
+ publicName: "options",
257
+ isSignal: true,
258
+ isRequired: true,
259
+ transformFunction: null
260
+ },
261
+ gpuContext: {
262
+ classPropertyName: "gpuContext",
263
+ publicName: "gpuContext",
264
+ isSignal: true,
265
+ isRequired: false,
266
+ transformFunction: null
267
+ },
268
+ theme: {
269
+ classPropertyName: "theme",
270
+ publicName: "theme",
271
+ isSignal: true,
272
+ isRequired: false,
273
+ transformFunction: null
274
+ },
275
+ className: {
276
+ classPropertyName: "className",
277
+ publicName: "className",
278
+ isSignal: true,
279
+ isRequired: false,
280
+ transformFunction: null
281
+ },
282
+ style: {
283
+ classPropertyName: "style",
284
+ publicName: "style",
285
+ isSignal: true,
286
+ isRequired: false,
287
+ transformFunction: null
288
+ }
289
+ },
290
+ outputs: {
291
+ ready: "ready",
292
+ chartReady: "chartReady",
293
+ chartDispose: "chartDispose",
294
+ resize: "resize",
295
+ click: "click",
296
+ chartClick: "chartClick",
297
+ mouseOver: "mouseOver",
298
+ mouseOut: "mouseOut",
299
+ crosshairMove: "crosshairMove",
300
+ dataAppend: "dataAppend",
301
+ zoomChange: "zoomChange",
302
+ zoomRangeChange: "zoomRangeChange",
303
+ deviceLost: "deviceLost",
304
+ chartError: "chartError"
305
+ },
306
+ host: { classAttribute: "chartgpu-angular" },
307
+ viewQueries: [{
308
+ propertyName: "host",
309
+ first: true,
310
+ predicate: ["host"],
311
+ descendants: true,
312
+ isSignal: true
313
+ }, {
314
+ propertyName: "canvasHost",
315
+ first: true,
316
+ predicate: ["canvasHost"],
317
+ descendants: true,
318
+ isSignal: true
319
+ }],
320
+ ngImport: i0,
321
+ template: `
322
+ <div
323
+ #host
324
+ class="chartgpu-host"
325
+ [class]="className() ?? ''"
326
+ [ngStyle]="style()"
327
+ (click)="emitClick($event)"
328
+ >
329
+ <div #canvasHost class="chartgpu-canvas-host"></div>
330
+ @if (initializationError(); as error) {
331
+ <div class="chartgpu-error" role="alert">{{ error.message }}</div>
332
+ }
333
+ </div>
334
+ `,
335
+ isInline: true,
336
+ styles: [":host{display:block;width:100%;height:100%}.chartgpu-host{position:relative;width:100%;height:100%}.chartgpu-canvas-host{position:absolute;inset:0}.chartgpu-error{position:absolute;inset:0;display:grid;place-items:center;padding:1rem;text-align:center}\n"],
337
+ dependencies: [{
338
+ kind: "directive",
339
+ type: NgStyle,
340
+ selector: "[ngStyle]",
341
+ inputs: ["ngStyle"]
342
+ }],
343
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
344
+ });
345
+ };
346
+ i0.ɵɵngDeclareClassMetadata({
347
+ minVersion: "12.0.0",
348
+ version: "22.2.3",
349
+ ngImport: i0,
350
+ type: ChartGpuAngularComponent,
351
+ decorators: [{
352
+ type: Component,
353
+ args: [{
354
+ selector: "lib-chartgpu-angular",
355
+ standalone: true,
356
+ imports: [NgStyle],
357
+ changeDetection: ChangeDetectionStrategy.OnPush,
358
+ host: { class: "chartgpu-angular" },
359
+ template: `
360
+ <div
361
+ #host
362
+ class="chartgpu-host"
363
+ [class]="className() ?? ''"
364
+ [ngStyle]="style()"
365
+ (click)="emitClick($event)"
366
+ >
367
+ <div #canvasHost class="chartgpu-canvas-host"></div>
368
+ @if (initializationError(); as error) {
369
+ <div class="chartgpu-error" role="alert">{{ error.message }}</div>
370
+ }
371
+ </div>
372
+ `,
373
+ styles: [":host{display:block;width:100%;height:100%}.chartgpu-host{position:relative;width:100%;height:100%}.chartgpu-canvas-host{position:absolute;inset:0}.chartgpu-error{position:absolute;inset:0;display:grid;place-items:center;padding:1rem;text-align:center}\n"]
374
+ }]
375
+ }],
376
+ ctorParameters: () => [{ type: i0.DestroyRef }],
377
+ propDecorators: {
378
+ options: [{
379
+ type: i0.Input,
380
+ args: [{
381
+ isSignal: true,
382
+ alias: "options",
383
+ required: true
384
+ }]
385
+ }],
386
+ gpuContext: [{
387
+ type: i0.Input,
388
+ args: [{
389
+ isSignal: true,
390
+ alias: "gpuContext",
391
+ required: false
392
+ }]
393
+ }],
394
+ theme: [{
395
+ type: i0.Input,
396
+ args: [{
397
+ isSignal: true,
398
+ alias: "theme",
399
+ required: false
400
+ }]
401
+ }],
402
+ className: [{
403
+ type: i0.Input,
404
+ args: [{
405
+ isSignal: true,
406
+ alias: "className",
407
+ required: false
408
+ }]
409
+ }],
410
+ style: [{
411
+ type: i0.Input,
412
+ args: [{
413
+ isSignal: true,
414
+ alias: "style",
415
+ required: false
416
+ }]
417
+ }],
418
+ ready: [{
419
+ type: i0.Output,
420
+ args: ["ready"]
421
+ }],
422
+ chartReady: [{
423
+ type: i0.Output,
424
+ args: ["chartReady"]
425
+ }],
426
+ chartDispose: [{
427
+ type: i0.Output,
428
+ args: ["chartDispose"]
429
+ }],
430
+ resize: [{
431
+ type: i0.Output,
432
+ args: ["resize"]
433
+ }],
434
+ click: [{
435
+ type: i0.Output,
436
+ args: ["click"]
437
+ }],
438
+ chartClick: [{
439
+ type: i0.Output,
440
+ args: ["chartClick"]
441
+ }],
442
+ mouseOver: [{
443
+ type: i0.Output,
444
+ args: ["mouseOver"]
445
+ }],
446
+ mouseOut: [{
447
+ type: i0.Output,
448
+ args: ["mouseOut"]
449
+ }],
450
+ crosshairMove: [{
451
+ type: i0.Output,
452
+ args: ["crosshairMove"]
453
+ }],
454
+ dataAppend: [{
455
+ type: i0.Output,
456
+ args: ["dataAppend"]
457
+ }],
458
+ zoomChange: [{
459
+ type: i0.Output,
460
+ args: ["zoomChange"]
461
+ }],
462
+ zoomRangeChange: [{
463
+ type: i0.Output,
464
+ args: ["zoomRangeChange"]
465
+ }],
466
+ deviceLost: [{
467
+ type: i0.Output,
468
+ args: ["deviceLost"]
469
+ }],
470
+ chartError: [{
471
+ type: i0.Output,
472
+ args: ["chartError"]
473
+ }],
474
+ host: [{
475
+ type: i0.ViewChild,
476
+ args: ["host", { isSignal: true }]
477
+ }],
478
+ canvasHost: [{
479
+ type: i0.ViewChild,
480
+ args: ["canvasHost", { isSignal: true }]
481
+ }]
482
+ }
483
+ });
484
+ var ChartgpuConnectChartsDirective = class ChartgpuConnectChartsDirective {
485
+ charts = input([], {
486
+ ...ngDevMode ? { debugName: "charts" } : /* istanbul ignore next */ {},
487
+ alias: "libChartgpuConnectCharts"
488
+ });
489
+ syncOptions = input(...ngDevMode ? [void 0, { debugName: "syncOptions" }] : /* istanbul ignore next */ []);
490
+ connectionError = output();
491
+ ids = /* @__PURE__ */ new WeakMap();
492
+ nextId = 1;
493
+ signature;
494
+ constructor() {
495
+ effect((onCleanup) => {
496
+ const charts = this.charts();
497
+ const options = this.syncOptions();
498
+ const optionsSignature = options ? `crosshair=${options.syncCrosshair ?? ""},zoom=${options.syncZoom ?? ""}` : "";
499
+ const signature = `${charts.map((chart) => {
500
+ if (!chart) return "null";
501
+ let id = this.ids.get(chart);
502
+ if (id === void 0) {
503
+ id = this.nextId++;
504
+ this.ids.set(chart, id);
505
+ }
506
+ return `${id}:${chart.disposed ? 1 : 0}`;
507
+ }).join("|")}|${optionsSignature}`;
508
+ if (signature === this.signature) return;
509
+ this.signature = signature;
510
+ if (charts.length === 0 || charts.some((chart) => !chart || chart.disposed)) return;
511
+ const resolved = [];
512
+ for (const chart of charts) {
513
+ if (!chart || chart.disposed) return;
514
+ resolved.push(chart);
515
+ }
516
+ try {
517
+ onCleanup(connectCharts(resolved, options));
518
+ } catch (cause) {
519
+ this.connectionError.emit(cause instanceof Error ? cause : new Error(String(cause)));
520
+ }
521
+ });
522
+ }
523
+ static ɵfac = i0.ɵɵngDeclareFactory({
524
+ minVersion: "12.0.0",
525
+ version: "22.2.3",
526
+ ngImport: i0,
527
+ type: ChartgpuConnectChartsDirective,
528
+ deps: [],
529
+ target: i0.ɵɵFactoryTarget.Directive
530
+ });
531
+ static ɵdir = i0.ɵɵngDeclareDirective({
532
+ minVersion: "17.1.0",
533
+ version: "22.2.3",
534
+ type: ChartgpuConnectChartsDirective,
535
+ isStandalone: true,
536
+ selector: "[libChartgpuConnectCharts]",
537
+ inputs: {
538
+ charts: {
539
+ classPropertyName: "charts",
540
+ publicName: "libChartgpuConnectCharts",
541
+ isSignal: true,
542
+ isRequired: false,
543
+ transformFunction: null
544
+ },
545
+ syncOptions: {
546
+ classPropertyName: "syncOptions",
547
+ publicName: "syncOptions",
548
+ isSignal: true,
549
+ isRequired: false,
550
+ transformFunction: null
551
+ }
552
+ },
553
+ outputs: { connectionError: "connectionError" },
554
+ ngImport: i0
555
+ });
556
+ };
557
+ i0.ɵɵngDeclareClassMetadata({
558
+ minVersion: "12.0.0",
559
+ version: "22.2.3",
560
+ ngImport: i0,
561
+ type: ChartgpuConnectChartsDirective,
562
+ decorators: [{
563
+ type: Directive,
564
+ args: [{
565
+ selector: "[libChartgpuConnectCharts]",
566
+ standalone: true
567
+ }]
568
+ }],
569
+ ctorParameters: () => [],
570
+ propDecorators: {
571
+ charts: [{
572
+ type: i0.Input,
573
+ args: [{
574
+ isSignal: true,
575
+ alias: "libChartgpuConnectCharts",
576
+ required: false
577
+ }]
578
+ }],
579
+ syncOptions: [{
580
+ type: i0.Input,
581
+ args: [{
582
+ isSignal: true,
583
+ alias: "syncOptions",
584
+ required: false
585
+ }]
586
+ }],
587
+ connectionError: [{
588
+ type: i0.Output,
589
+ args: ["connectionError"]
590
+ }]
591
+ }
592
+ });
593
+ const INITIAL_STATE = {
594
+ adapter: null,
595
+ device: null,
596
+ pipelineCache: null,
597
+ error: null,
598
+ isReady: false
599
+ };
600
+ var ChartgpuGPUContextService = class ChartgpuGPUContextService {
601
+ state = signal(INITIAL_STATE, ...ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []);
602
+ context = computed(() => {
603
+ const state = this.state();
604
+ if (!state.adapter || !state.device || !state.pipelineCache) return null;
605
+ return {
606
+ adapter: state.adapter,
607
+ device: state.device,
608
+ pipelineCache: state.pipelineCache
609
+ };
610
+ }, ...ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []);
611
+ initialization;
612
+ initialize() {
613
+ if (!this.initialization) this.initialization = this.createContext();
614
+ return this.initialization;
615
+ }
616
+ async createContext() {
617
+ try {
618
+ if (typeof navigator === "undefined" || !("gpu" in navigator)) throw new Error("WebGPU not supported in this browser");
619
+ const gpu = navigator.gpu;
620
+ if (!gpu) throw new Error("WebGPU not supported in this browser");
621
+ const adapter = await gpu.requestAdapter({ powerPreference: "high-performance" });
622
+ if (!adapter) {
623
+ const error = /* @__PURE__ */ new Error("WebGPU is not available. No compatible GPUAdapter was found.");
624
+ const state = {
625
+ ...INITIAL_STATE,
626
+ error
627
+ };
628
+ this.state.set(state);
629
+ return state;
630
+ }
631
+ const device = await adapter.requestDevice();
632
+ const state = {
633
+ adapter,
634
+ device,
635
+ pipelineCache: createPipelineCache(device),
636
+ error: null,
637
+ isReady: true
638
+ };
639
+ this.state.set(state);
640
+ return state;
641
+ } catch (cause) {
642
+ const error = cause instanceof Error ? cause : new Error(String(cause));
643
+ const state = {
644
+ ...INITIAL_STATE,
645
+ error
646
+ };
647
+ this.state.set(state);
648
+ return state;
649
+ }
650
+ }
651
+ static ɵfac = i0.ɵɵngDeclareFactory({
652
+ minVersion: "12.0.0",
653
+ version: "22.2.3",
654
+ ngImport: i0,
655
+ type: ChartgpuGPUContextService,
656
+ deps: [],
657
+ target: i0.ɵɵFactoryTarget.Injectable
658
+ });
659
+ static ɵprov = i0.ɵɵngDeclareInjectable({
660
+ minVersion: "12.0.0",
661
+ version: "22.2.3",
662
+ ngImport: i0,
663
+ type: ChartgpuGPUContextService,
664
+ providedIn: "root"
665
+ });
666
+ };
667
+ i0.ɵɵngDeclareClassMetadata({
668
+ minVersion: "12.0.0",
669
+ version: "22.2.3",
670
+ ngImport: i0,
671
+ type: ChartgpuGPUContextService,
672
+ decorators: [{
673
+ type: Injectable,
674
+ args: [{ providedIn: "root" }]
675
+ }]
676
+ });
677
+ function provideChartGpuContext() {
678
+ return makeEnvironmentProviders([ChartgpuGPUContextService]);
679
+ }
680
+ export { ChartGpuAngularComponent, ChartgpuConnectChartsDirective, ChartgpuGPUContextService, provideChartGpuContext };
681
+
682
+ //# sourceMappingURL=chartgpu-angular.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chartgpu-angular.mjs","names":[],"sources":["../../../projects/chartgpu-angular/src/lib/chartgpu-angular.component.ts","../../../projects/chartgpu-angular/src/lib/connect-charts.directive.ts","../../../projects/chartgpu-angular/src/lib/gpu-context.service.ts","../../../projects/chartgpu-angular/src/lib/gpu-context.provider.ts"],"sourcesContent":["import { NgStyle } from '@angular/common';\r\nimport {\r\n ChangeDetectionStrategy,\r\n Component,\r\n DestroyRef,\r\n ElementRef,\r\n OnDestroy,\r\n afterNextRender,\r\n effect,\r\n input,\r\n output,\r\n signal,\r\n untracked,\r\n viewChild,\r\n} from '@angular/core';\r\nimport {\r\n ChartGPU,\r\n type ChartGPUCrosshairMovePayload,\r\n type ChartGPUDeviceLostPayload,\r\n type ChartGPUEventPayload,\r\n type ChartGPUInstance,\r\n type ChartGPUZoomRangeChangePayload,\r\n type OHLCDataPoint,\r\n} from 'chartgpu';\r\nimport type {\r\n ChartgpuAppendDataOptions,\r\n ChartgpuCartesianSeriesData,\r\n ChartgpuChartHandle,\r\n ChartgpuClickEvent,\r\n ChartgpuDataAppendEvent,\r\n ChartgpuGPUContext,\r\n ChartgpuOptions,\r\n ChartgpuReadyEvent,\r\n ChartgpuResizeEvent,\r\n ChartgpuStyle,\r\n ChartgpuZoomChangeEvent,\r\n ChartgpuZoomRangeChangeEvent,\r\n} from './chartgpu-angular.types';\r\n\r\n@Component({\r\n selector: 'lib-chartgpu-angular',\r\n standalone: true,\r\n imports: [NgStyle],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: { class: 'chartgpu-angular' },\r\n template: `\r\n <div\r\n #host\r\n class=\"chartgpu-host\"\r\n [class]=\"className() ?? ''\"\r\n [ngStyle]=\"style()\"\r\n (click)=\"emitClick($event)\"\r\n >\r\n <div #canvasHost class=\"chartgpu-canvas-host\"></div>\r\n @if (initializationError(); as error) {\r\n <div class=\"chartgpu-error\" role=\"alert\">{{ error.message }}</div>\r\n }\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n display: block;\r\n width: 100%;\r\n height: 100%;\r\n }\r\n\r\n .chartgpu-host {\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\r\n }\r\n\r\n .chartgpu-canvas-host {\r\n position: absolute;\r\n inset: 0;\r\n }\r\n\r\n .chartgpu-error {\r\n position: absolute;\r\n inset: 0;\r\n display: grid;\r\n place-items: center;\r\n padding: 1rem;\r\n text-align: center;\r\n }\r\n `],\r\n})\r\nexport class ChartGpuAngularComponent implements ChartgpuChartHandle, OnDestroy {\r\n readonly options = input.required<ChartgpuOptions>();\r\n readonly gpuContext = input<ChartgpuGPUContext | null>(null);\r\n readonly theme = input<ChartgpuOptions['theme'] | undefined>(undefined);\r\n readonly className = input<string | undefined>();\r\n readonly style = input<ChartgpuStyle | undefined>();\r\n\r\n readonly ready = output<ChartgpuReadyEvent>();\r\n readonly chartReady = output<ChartGPUInstance>();\r\n readonly chartDispose = output<void>();\r\n readonly resize = output<ChartgpuResizeEvent>();\r\n readonly click = output<ChartgpuClickEvent>();\r\n readonly chartClick = output<ChartGPUEventPayload>();\r\n readonly mouseOver = output<ChartGPUEventPayload>();\r\n readonly mouseOut = output<ChartGPUEventPayload>();\r\n readonly crosshairMove = output<ChartGPUCrosshairMovePayload>();\r\n readonly dataAppend = output<ChartgpuDataAppendEvent>();\r\n readonly zoomChange = output<ChartgpuZoomChangeEvent>();\r\n readonly zoomRangeChange = output<ChartgpuZoomRangeChangeEvent>();\r\n readonly deviceLost = output<ChartGPUDeviceLostPayload>();\r\n readonly chartError = output<Error>();\r\n\r\n readonly host = viewChild<ElementRef<HTMLDivElement>>('host');\r\n readonly canvasHost = viewChild<ElementRef<HTMLDivElement>>('canvasHost');\r\n\r\n private readonly chartInstance = signal<ChartGPUInstance | null>(null);\r\n readonly initializationError = signal<Error | null>(null);\r\n private chartContainer?: HTMLDivElement;\r\n private createdWithOptions?: {\r\n options: ChartgpuOptions;\r\n theme: ChartgpuOptions['theme'] | undefined;\r\n };\r\n private resizeTimeout?: ReturnType<typeof setTimeout>;\r\n private resizeObserver?: ResizeObserver;\r\n private removeChartListeners?: () => void;\r\n private destroying = false;\r\n\r\n constructor(private readonly destroyRef: DestroyRef) {\r\n this.destroyRef.onDestroy(() => {\r\n this.resizeObserver?.disconnect();\r\n if (this.resizeTimeout !== undefined) {\r\n clearTimeout(this.resizeTimeout);\r\n }\r\n this.disposeChart();\r\n });\r\n\r\n afterNextRender(() => {\r\n const container = this.host()?.nativeElement;\r\n if (container) {\r\n this.observeResize(container);\r\n }\r\n });\r\n\r\n effect(onCleanup => {\r\n const container = this.canvasHost()?.nativeElement;\r\n const options = this.options();\r\n const gpuContext = this.gpuContext();\r\n const theme = this.theme();\r\n\r\n this.initializationError.set(null);\r\n if (!container) {\r\n this.disposeChart();\r\n return;\r\n }\r\n if (typeof navigator === 'undefined' || !('gpu' in navigator)) {\r\n this.reportError(new Error('WebGPU not supported in this browser'));\r\n return;\r\n }\r\n\r\n if (untracked(() => this.chartInstance()) && this.chartContainer === container) {\r\n return;\r\n }\r\n\r\n let cancelled = false;\r\n let createdInstance: ChartGPUInstance | undefined;\r\n const initialOptions = this.getEffectiveOptions(options, theme);\r\n\r\n void (gpuContext\r\n ? ChartGPU.create(container, initialOptions, gpuContext)\r\n : ChartGPU.create(container, initialOptions)\r\n ).then(instance => {\r\n createdInstance = instance;\r\n if (cancelled) {\r\n instance.dispose();\r\n return;\r\n }\r\n\r\n try {\r\n const latest = untracked(() => ({\r\n options: this.options(),\r\n theme: this.theme(),\r\n }));\r\n if (latest.options !== options || latest.theme !== theme) {\r\n instance.setOption(this.getEffectiveOptions(latest.options, latest.theme));\r\n }\r\n\r\n this.createdWithOptions = latest;\r\n this.chartContainer = container;\r\n this.chartInstance.set(instance);\r\n this.removeChartListeners = this.listenToChart(instance);\r\n this.ready.emit({ container });\r\n this.chartReady.emit(instance);\r\n\r\n const range = instance.getZoomRange();\r\n if (range) {\r\n this.emitZoomRange(range);\r\n }\r\n } catch (cause: unknown) {\r\n instance.dispose();\r\n throw cause;\r\n }\r\n }).catch((cause: unknown) => {\r\n if (cancelled) {\r\n return;\r\n }\r\n if (createdInstance && this.chartInstance() !== createdInstance && !createdInstance.disposed) {\r\n createdInstance.dispose();\r\n }\r\n this.reportError(cause);\r\n });\r\n\r\n onCleanup(() => {\r\n cancelled = true;\r\n if (this.chartContainer === container) {\r\n this.disposeChart();\r\n }\r\n });\r\n }, { allowSignalWrites: true });\r\n\r\n effect(() => {\r\n const options = this.options();\r\n const theme = this.theme();\r\n const instance = this.chartInstance();\r\n if (!instance || instance.disposed) {\r\n return;\r\n }\r\n\r\n if (this.createdWithOptions?.options === options && this.createdWithOptions.theme === theme) {\r\n this.createdWithOptions = undefined;\r\n return;\r\n }\r\n\r\n try {\r\n instance.setOption(this.getEffectiveOptions(options, theme));\r\n } catch (cause: unknown) {\r\n this.reportError(cause);\r\n }\r\n }, { allowSignalWrites: true });\r\n }\r\n\r\n protected emitClick(event: MouseEvent): void {\r\n this.click.emit({ x: event.offsetX, y: event.offsetY });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.destroying = true;\r\n }\r\n\r\n getChart(): ChartGPUInstance | null {\r\n const instance = this.chartInstance();\r\n return instance && !instance.disposed ? instance : null;\r\n }\r\n\r\n getContainer(): HTMLDivElement | null {\r\n return this.canvasHost()?.nativeElement ?? null;\r\n }\r\n\r\n appendData(\r\n seriesIndex: number,\r\n newPoints: ChartgpuCartesianSeriesData | OHLCDataPoint[],\r\n options?: ChartgpuAppendDataOptions,\r\n ): void {\r\n this.getChart()?.appendData(seriesIndex, newPoints, options);\r\n }\r\n\r\n renderFrame(): boolean {\r\n return this.getChart()?.renderFrame() ?? false;\r\n }\r\n\r\n needsRender(): boolean {\r\n return this.getChart()?.needsRender() ?? false;\r\n }\r\n\r\n getRenderMode(): 'auto' | 'external' {\r\n return this.getChart()?.getRenderMode() ?? 'auto';\r\n }\r\n\r\n setRenderMode(mode: 'auto' | 'external'): void {\r\n this.getChart()?.setRenderMode(mode);\r\n }\r\n\r\n setOption(options: ChartgpuOptions): void {\r\n this.getChart()?.setOption(options);\r\n }\r\n\r\n setZoomRange(start: number, end: number, source?: unknown): void {\r\n this.getChart()?.setZoomRange(start, end, source);\r\n }\r\n\r\n setInteractionX(x: number | null, source?: unknown): void {\r\n this.getChart()?.setInteractionX(x, source);\r\n }\r\n\r\n getInteractionX(): number | null {\r\n return this.getChart()?.getInteractionX() ?? null;\r\n }\r\n\r\n hitTest(event: PointerEvent | MouseEvent) {\r\n return this.getChart()?.hitTest(event) ?? null;\r\n }\r\n\r\n private getEffectiveOptions(\r\n options: ChartgpuOptions,\r\n theme: ChartgpuOptions['theme'] | undefined,\r\n ): ChartgpuOptions {\r\n return theme !== undefined ? { ...options, theme } : options;\r\n }\r\n\r\n private listenToChart(instance: ChartGPUInstance): () => void {\r\n const click = (payload: ChartGPUEventPayload) => this.chartClick.emit(payload);\r\n const mouseOver = (payload: ChartGPUEventPayload) => this.mouseOver.emit(payload);\r\n const mouseOut = (payload: ChartGPUEventPayload) => this.mouseOut.emit(payload);\r\n const crosshairMove = (payload: ChartGPUCrosshairMovePayload) => this.crosshairMove.emit(payload);\r\n const dataAppend = (payload: ChartgpuDataAppendEvent) => this.dataAppend.emit(payload);\r\n const zoomChange = (payload: ChartGPUZoomRangeChangePayload) => this.emitZoomRange(payload);\r\n const deviceLost = (payload: ChartGPUDeviceLostPayload) => this.deviceLost.emit(payload);\r\n\r\n instance.on('click', click);\r\n instance.on('mouseover', mouseOver);\r\n instance.on('mouseout', mouseOut);\r\n instance.on('crosshairMove', crosshairMove);\r\n instance.on('dataAppend', dataAppend);\r\n instance.on('zoomRangeChange', zoomChange);\r\n instance.on('deviceLost', deviceLost);\r\n\r\n return () => {\r\n if (instance.disposed) {\r\n return;\r\n }\r\n instance.off('click', click);\r\n instance.off('mouseover', mouseOver);\r\n instance.off('mouseout', mouseOut);\r\n instance.off('crosshairMove', crosshairMove);\r\n instance.off('dataAppend', dataAppend);\r\n instance.off('zoomRangeChange', zoomChange);\r\n instance.off('deviceLost', deviceLost);\r\n };\r\n }\r\n\r\n private emitZoomRange(range: { start: number; end: number }): void {\r\n this.zoomChange.emit({ range: { start: range.start, end: range.end } });\r\n this.zoomRangeChange.emit({ start: range.start, end: range.end });\r\n }\r\n\r\n private observeResize(container: HTMLDivElement): void {\r\n if (typeof ResizeObserver === 'undefined') {\r\n return;\r\n }\r\n\r\n this.resizeObserver = new ResizeObserver(entries => {\r\n const entry = entries[0];\r\n if (!entry) {\r\n return;\r\n }\r\n const { width, height } = entry.contentRect;\r\n this.resize.emit({ width, height, container });\r\n if (this.resizeTimeout !== undefined) {\r\n clearTimeout(this.resizeTimeout);\r\n }\r\n this.resizeTimeout = setTimeout(() => {\r\n this.chartInstance()?.resize();\r\n this.resizeTimeout = undefined;\r\n }, 100);\r\n });\r\n this.resizeObserver.observe(container);\r\n }\r\n\r\n private reportError(cause: unknown): void {\r\n const error = cause instanceof Error ? cause : new Error(String(cause));\r\n this.initializationError.set(error);\r\n this.chartError.emit(error);\r\n }\r\n\r\n private disposeChart(): void {\r\n const instance = this.chartInstance();\r\n this.removeChartListeners?.();\r\n this.removeChartListeners = undefined;\r\n if (instance && !instance.disposed) {\r\n instance.dispose();\r\n if (!this.destroying) {\r\n this.chartDispose.emit();\r\n }\r\n }\r\n this.chartInstance.set(null);\r\n this.chartContainer = undefined;\r\n this.createdWithOptions = undefined;\r\n }\r\n}\r\n","import { Directive, effect, input, output } from '@angular/core';\r\nimport { connectCharts } from 'chartgpu';\r\nimport type { ChartGPUInstance, ChartSyncOptions } from 'chartgpu';\r\n\r\n@Directive({\r\n selector: '[libChartgpuConnectCharts]',\r\n standalone: true,\r\n})\r\nexport class ChartgpuConnectChartsDirective {\r\n readonly charts = input<ReadonlyArray<ChartGPUInstance | null | undefined>>([], {\r\n alias: 'libChartgpuConnectCharts',\r\n });\r\n readonly syncOptions = input<ChartSyncOptions | undefined>();\r\n readonly connectionError = output<Error>();\r\n\r\n private readonly ids = new WeakMap<object, number>();\r\n private nextId = 1;\r\n private signature: string | undefined;\r\n\r\n constructor() {\r\n effect(onCleanup => {\r\n const charts = this.charts();\r\n const options = this.syncOptions();\r\n const optionsSignature = options\r\n ? `crosshair=${options.syncCrosshair ?? ''},zoom=${options.syncZoom ?? ''}`\r\n : '';\r\n const signature = `${charts.map(chart => {\r\n if (!chart) {\r\n return 'null';\r\n }\r\n\r\n let id = this.ids.get(chart);\r\n if (id === undefined) {\r\n id = this.nextId++;\r\n this.ids.set(chart, id);\r\n }\r\n return `${id}:${chart.disposed ? 1 : 0}`;\r\n }).join('|')}|${optionsSignature}`;\r\n\r\n if (signature === this.signature) {\r\n return;\r\n }\r\n this.signature = signature;\r\n\r\n if (charts.length === 0 || charts.some(chart => !chart || chart.disposed)) {\r\n return;\r\n }\r\n\r\n const resolved: ChartGPUInstance[] = [];\r\n for (const chart of charts) {\r\n if (!chart || chart.disposed) {\r\n return;\r\n }\r\n resolved.push(chart);\r\n }\r\n\r\n try {\r\n const disconnect = connectCharts(resolved, options);\r\n onCleanup(disconnect);\r\n } catch (cause: unknown) {\r\n this.connectionError.emit(cause instanceof Error ? cause : new Error(String(cause)));\r\n }\r\n });\r\n }\r\n}\r\n","import { Injectable, computed, signal } from '@angular/core';\nimport { createPipelineCache } from 'chartgpu';\nimport type { ChartGPUCreateContext } from 'chartgpu';\nimport type { ChartgpuGPUContextState } from './chartgpu-angular.types';\n\nconst INITIAL_STATE: ChartgpuGPUContextState = {\n adapter: null,\n device: null,\n pipelineCache: null,\n error: null,\n isReady: false,\n};\n\n/**\n * Creates one shared WebGPU context and pipeline cache for charts in a dashboard.\n * The device is intentionally not destroyed with the service so charts can share it\n * for the lifetime of the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class ChartgpuGPUContextService {\n readonly state = signal<ChartgpuGPUContextState>(INITIAL_STATE);\n readonly context = computed<ChartGPUCreateContext | null>(() => {\n const state = this.state();\n if (!state.adapter || !state.device || !state.pipelineCache) {\n return null;\n }\n\n return {\n adapter: state.adapter,\n device: state.device,\n pipelineCache: state.pipelineCache,\n };\n });\n\n private initialization?: Promise<ChartgpuGPUContextState>;\n\n initialize(): Promise<ChartgpuGPUContextState> {\n if (!this.initialization) {\n this.initialization = this.createContext();\n }\n return this.initialization;\n }\n\n private async createContext(): Promise<ChartgpuGPUContextState> {\n try {\n if (typeof navigator === 'undefined' || !('gpu' in navigator)) {\n throw new Error('WebGPU not supported in this browser');\n }\n\n const gpu = (navigator as Navigator & {\n gpu?: {\n requestAdapter(options: {\n powerPreference: 'high-performance';\n }): Promise<ChartGPUCreateContext['adapter'] | null>;\n };\n }).gpu;\n if (!gpu) {\n throw new Error('WebGPU not supported in this browser');\n }\n\n const adapter = await gpu.requestAdapter({ powerPreference: 'high-performance' });\n if (!adapter) {\n const error = new Error('WebGPU is not available. No compatible GPUAdapter was found.');\n const state: ChartgpuGPUContextState = { ...INITIAL_STATE, error };\n this.state.set(state);\n return state;\n }\n\n const device = await adapter.requestDevice();\n const pipelineCache = createPipelineCache(device);\n const state: ChartgpuGPUContextState = {\n adapter,\n device,\n pipelineCache,\n error: null,\n isReady: true,\n };\n this.state.set(state);\n return state;\n } catch (cause: unknown) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n const state: ChartgpuGPUContextState = { ...INITIAL_STATE, error };\n this.state.set(state);\n return state;\n }\n }\n}\n","import { makeEnvironmentProviders } from '@angular/core';\nimport { ChartgpuGPUContextService } from './gpu-context.service';\n\nexport function provideChartGpuContext() {\n return makeEnvironmentProviders([ChartgpuGPUContextService]);\n}"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,25 @@
1
1
  {
2
2
  "name": "chartgpu-angular",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "22.0.0",
4
+ "peerDependencies": {
5
+ "@angular/common": "^22.0.0",
6
+ "@angular/core": "^22.0.0",
7
+ "chartgpu": "^0.4.0"
8
+ },
9
+ "module": "fesm2022/chartgpu-angular.mjs",
10
+ "typings": "types/chartgpu-angular.d.ts",
11
+ "exports": {
12
+ "./package.json": {
13
+ "default": "./package.json"
14
+ },
15
+ ".": {
16
+ "types": "./types/chartgpu-angular.d.ts",
17
+ "default": "./fesm2022/chartgpu-angular.mjs"
18
+ }
19
+ },
20
+ "sideEffects": false,
21
+ "type": "module",
22
+ "dependencies": {
23
+ "tslib": "^2.3.0"
24
+ }
6
25
  }
@@ -0,0 +1,267 @@
1
+ import * as i0 from "@angular/core";
2
+ import { DestroyRef, ElementRef, OnDestroy } from "@angular/core";
3
+ import { AnimationConfig, AnnotationConfig, AxisConfig, ChartGPUCreateContext, ChartGPUCrosshairMovePayload, ChartGPUDeviceLostPayload, ChartGPUEventPayload, ChartGPUHitTestResult, ChartGPUInstance, ChartGPUInstance as ChartGPUInstance$1, ChartGPUOptions, ChartSyncOptions, DataPoint, DataZoomConfig, OHLCDataPoint, OHLCDataPoint as OHLCDataPoint$1, PipelineCache, RenderMode, SeriesConfig, SeriesType, ThemeConfig, TooltipConfig } from "chartgpu";
4
+ export type ChartgpuOptions = ChartGPUOptions;
5
+ export type ChartgpuSeriesType = SeriesType;
6
+ export type ChartgpuSeriesData = Extract<SeriesConfig, {
7
+ type: 'line';
8
+ }>['data'];
9
+ export type ChartgpuSeriesOptions = SeriesConfig;
10
+ export type ChartgpuAxisOptions = AxisConfig;
11
+ export type ChartgpuZoomOptions = DataZoomConfig;
12
+ export type ChartgpuTooltipOptions = TooltipConfig;
13
+ export type ChartgpuAnimationOptions = AnimationConfig | boolean;
14
+ export type ChartgpuThemeOptions = ThemeConfig | 'light' | 'dark';
15
+ export type ChartgpuAnnotationOptions = AnnotationConfig;
16
+ export type ChartgpuThreeDOptions = Pick<ChartGPUOptions, 'coordinateSystem' | 'camera' | 'interaction3d' | 'axes3d'>;
17
+ export type ChartgpuStreamingOptions = Pick<ChartGPUOptions, 'autoScroll'>;
18
+ export type ChartgpuInteractionOptions = Pick<ChartGPUOptions, 'dataZoom' | 'tooltip'>;
19
+ export type ChartgpuChartInstance = ChartGPUInstance;
20
+ export type ChartgpuGPUContext = ChartGPUCreateContext;
21
+ export type ChartgpuStyle = Record<string, string | number | null | undefined>;
22
+ export type ChartgpuZoomRange = NonNullable<ReturnType<ChartGPUInstance['getZoomRange']>>;
23
+ export type ChartgpuClickParams = ChartGPUEventPayload;
24
+ export type ChartgpuMouseOverParams = ChartGPUEventPayload;
25
+ export type ChartgpuCrosshairMoveParams = ChartGPUCrosshairMovePayload;
26
+ export type ChartgpuHitTestResult = ChartGPUHitTestResult;
27
+ export type ChartgpuRenderMode = RenderMode;
28
+ export type ChartgpuSyncOptions = ChartSyncOptions;
29
+ export type ChartgpuXYArraysData = Readonly<{
30
+ x: ArrayLike<number>;
31
+ y: ArrayLike<number>;
32
+ size?: ArrayLike<number>;
33
+ }>;
34
+ export type ChartgpuInterleavedXYData = ArrayBufferView;
35
+ export type ChartgpuCartesianSeriesData = ReadonlyArray<DataPoint | null> | ChartgpuXYArraysData | ChartgpuInterleavedXYData;
36
+ export type ChartgpuAppendDataOptions = Readonly<{
37
+ maxPoints?: number;
38
+ }>;
39
+ export interface ChartgpuDataAppendEvent {
40
+ seriesIndex: number;
41
+ count: number;
42
+ xExtent: {
43
+ min: number;
44
+ max: number;
45
+ };
46
+ }
47
+ export interface ChartgpuReadyEvent {
48
+ container: HTMLDivElement;
49
+ }
50
+ export interface ChartgpuResizeEvent {
51
+ width: number;
52
+ height: number;
53
+ container: HTMLDivElement;
54
+ }
55
+ export interface ChartgpuClickEvent {
56
+ x: number;
57
+ y: number;
58
+ }
59
+ export interface ChartgpuZoomChangeEvent {
60
+ range: {
61
+ start: number;
62
+ end: number;
63
+ };
64
+ }
65
+ export interface ChartgpuZoomRangeChangeEvent {
66
+ start: number;
67
+ end: number;
68
+ }
69
+ export interface ChartgpuGPUContextState {
70
+ adapter: ChartGPUCreateContext['adapter'] | null;
71
+ device: ChartGPUCreateContext['device'] | null;
72
+ pipelineCache: PipelineCache | null;
73
+ error: Error | null;
74
+ isReady: boolean;
75
+ }
76
+ export interface ChartgpuChartHandle {
77
+ getChart(): ChartGPUInstance | null;
78
+ getContainer(): HTMLDivElement | null;
79
+ appendData(seriesIndex: number, newPoints: ChartgpuCartesianSeriesData | OHLCDataPoint[], options?: ChartgpuAppendDataOptions): void;
80
+ renderFrame(): boolean;
81
+ needsRender(): boolean;
82
+ getRenderMode(): RenderMode;
83
+ setRenderMode(mode: RenderMode): void;
84
+ setOption(options: ChartgpuOptions): void;
85
+ setZoomRange(start: number, end: number, source?: unknown): void;
86
+ setInteractionX(x: number | null, source?: unknown): void;
87
+ getInteractionX(): number | null;
88
+ hitTest(event: PointerEvent | MouseEvent): ChartGPUHitTestResult | null;
89
+ }
90
+ export declare class ChartGpuAngularComponent implements ChartgpuChartHandle, OnDestroy {
91
+ private readonly destroyRef;
92
+ readonly options: import("@angular/core").InputSignal<import("chartgpu").ChartGPUOptions>;
93
+ readonly gpuContext: import("@angular/core").InputSignal<Readonly<{
94
+ readonly device: GPUDevice;
95
+ readonly adapter: GPUAdapter;
96
+ readonly pipelineCache?: import("chartgpu").PipelineCache;
97
+ }> | null>;
98
+ readonly theme: import("@angular/core").InputSignal<import("chartgpu").ThemeConfig | "light" | "dark" | undefined>;
99
+ readonly className: import("@angular/core").InputSignal<string | undefined>;
100
+ readonly style: import("@angular/core").InputSignal<ChartgpuStyle | undefined>;
101
+ readonly ready: import("@angular/core").OutputEmitterRef<ChartgpuReadyEvent>;
102
+ readonly chartReady: import("@angular/core").OutputEmitterRef<ChartGPUInstance$1>;
103
+ readonly chartDispose: import("@angular/core").OutputEmitterRef<void>;
104
+ readonly resize: import("@angular/core").OutputEmitterRef<ChartgpuResizeEvent>;
105
+ readonly click: import("@angular/core").OutputEmitterRef<ChartgpuClickEvent>;
106
+ readonly chartClick: import("@angular/core").OutputEmitterRef<Readonly<{
107
+ readonly seriesIndex: number | null;
108
+ readonly dataIndex: number | null;
109
+ readonly value: readonly [number, number] | null;
110
+ readonly seriesName: string | null;
111
+ readonly event: PointerEvent;
112
+ }>>;
113
+ readonly mouseOver: import("@angular/core").OutputEmitterRef<Readonly<{
114
+ readonly seriesIndex: number | null;
115
+ readonly dataIndex: number | null;
116
+ readonly value: readonly [number, number] | null;
117
+ readonly seriesName: string | null;
118
+ readonly event: PointerEvent;
119
+ }>>;
120
+ readonly mouseOut: import("@angular/core").OutputEmitterRef<Readonly<{
121
+ readonly seriesIndex: number | null;
122
+ readonly dataIndex: number | null;
123
+ readonly value: readonly [number, number] | null;
124
+ readonly seriesName: string | null;
125
+ readonly event: PointerEvent;
126
+ }>>;
127
+ readonly crosshairMove: import("@angular/core").OutputEmitterRef<Readonly<{
128
+ readonly x: number | null;
129
+ readonly source?: unknown;
130
+ }>>;
131
+ readonly dataAppend: import("@angular/core").OutputEmitterRef<ChartgpuDataAppendEvent>;
132
+ readonly zoomChange: import("@angular/core").OutputEmitterRef<ChartgpuZoomChangeEvent>;
133
+ readonly zoomRangeChange: import("@angular/core").OutputEmitterRef<ChartgpuZoomRangeChangeEvent>;
134
+ readonly deviceLost: import("@angular/core").OutputEmitterRef<Readonly<{
135
+ readonly reason: GPUDeviceLostReason;
136
+ readonly message: string;
137
+ }>>;
138
+ readonly chartError: import("@angular/core").OutputEmitterRef<Error>;
139
+ readonly host: import("@angular/core").Signal<ElementRef<HTMLDivElement> | undefined>;
140
+ readonly canvasHost: import("@angular/core").Signal<ElementRef<HTMLDivElement> | undefined>;
141
+ private readonly chartInstance;
142
+ readonly initializationError: import("@angular/core").WritableSignal<Error | null>;
143
+ private chartContainer?;
144
+ private createdWithOptions?;
145
+ private resizeTimeout?;
146
+ private resizeObserver?;
147
+ private removeChartListeners?;
148
+ private destroying;
149
+ constructor(destroyRef: DestroyRef);
150
+ protected emitClick(event: MouseEvent): void;
151
+ ngOnDestroy(): void;
152
+ getChart(): ChartGPUInstance$1 | null;
153
+ getContainer(): HTMLDivElement | null;
154
+ appendData(seriesIndex: number, newPoints: ChartgpuCartesianSeriesData | OHLCDataPoint$1[], options?: ChartgpuAppendDataOptions): void;
155
+ renderFrame(): boolean;
156
+ needsRender(): boolean;
157
+ getRenderMode(): 'auto' | 'external';
158
+ setRenderMode(mode: 'auto' | 'external'): void;
159
+ setOption(options: ChartgpuOptions): void;
160
+ setZoomRange(start: number, end: number, source?: unknown): void;
161
+ setInteractionX(x: number | null, source?: unknown): void;
162
+ getInteractionX(): number | null;
163
+ hitTest(event: PointerEvent | MouseEvent): Readonly<{
164
+ readonly isInGrid: boolean;
165
+ readonly canvasX: number;
166
+ readonly canvasY: number;
167
+ readonly gridX: number;
168
+ readonly gridY: number;
169
+ readonly match: import("chartgpu").ChartGPUHitTestMatch | null;
170
+ }> | null;
171
+ private getEffectiveOptions;
172
+ private listenToChart;
173
+ private emitZoomRange;
174
+ private observeResize;
175
+ private reportError;
176
+ private disposeChart;
177
+ static ɵfac: i0.ɵɵFactoryDeclaration<ChartGpuAngularComponent, never>;
178
+ static ɵcmp: i0.ɵɵComponentDeclaration<ChartGpuAngularComponent, "lib-chartgpu-angular", never, {
179
+ "options": {
180
+ "alias": "options";
181
+ "required": true;
182
+ "isSignal": true;
183
+ };
184
+ "gpuContext": {
185
+ "alias": "gpuContext";
186
+ "required": false;
187
+ "isSignal": true;
188
+ };
189
+ "theme": {
190
+ "alias": "theme";
191
+ "required": false;
192
+ "isSignal": true;
193
+ };
194
+ "className": {
195
+ "alias": "className";
196
+ "required": false;
197
+ "isSignal": true;
198
+ };
199
+ "style": {
200
+ "alias": "style";
201
+ "required": false;
202
+ "isSignal": true;
203
+ };
204
+ }, {
205
+ "ready": "ready";
206
+ "chartReady": "chartReady";
207
+ "chartDispose": "chartDispose";
208
+ "resize": "resize";
209
+ "click": "click";
210
+ "chartClick": "chartClick";
211
+ "mouseOver": "mouseOver";
212
+ "mouseOut": "mouseOut";
213
+ "crosshairMove": "crosshairMove";
214
+ "dataAppend": "dataAppend";
215
+ "zoomChange": "zoomChange";
216
+ "zoomRangeChange": "zoomRangeChange";
217
+ "deviceLost": "deviceLost";
218
+ "chartError": "chartError";
219
+ }, never, never, true, never>;
220
+ }
221
+ export declare class ChartgpuConnectChartsDirective {
222
+ readonly charts: import("@angular/core").InputSignal<readonly (ChartGPUInstance$1 | null | undefined)[]>;
223
+ readonly syncOptions: import("@angular/core").InputSignal<Readonly<{
224
+ readonly syncCrosshair?: boolean;
225
+ readonly syncZoom?: boolean;
226
+ }> | undefined>;
227
+ readonly connectionError: import("@angular/core").OutputEmitterRef<Error>;
228
+ private readonly ids;
229
+ private nextId;
230
+ private signature;
231
+ constructor();
232
+ static ɵfac: i0.ɵɵFactoryDeclaration<ChartgpuConnectChartsDirective, never>;
233
+ static ɵdir: i0.ɵɵDirectiveDeclaration<ChartgpuConnectChartsDirective, "[libChartgpuConnectCharts]", never, {
234
+ "charts": {
235
+ "alias": "libChartgpuConnectCharts";
236
+ "required": false;
237
+ "isSignal": true;
238
+ };
239
+ "syncOptions": {
240
+ "alias": "syncOptions";
241
+ "required": false;
242
+ "isSignal": true;
243
+ };
244
+ }, {
245
+ "connectionError": "connectionError";
246
+ }, never, never, true, never>;
247
+ }
248
+ export declare function provideChartGpuContext(): import("@angular/core").EnvironmentProviders;
249
+ /**
250
+ * Creates one shared WebGPU context and pipeline cache for charts in a dashboard.
251
+ * The device is intentionally not destroyed with the service so charts can share it
252
+ * for the lifetime of the application.
253
+ */
254
+ export declare class ChartgpuGPUContextService {
255
+ readonly state: import("@angular/core").WritableSignal<ChartgpuGPUContextState>;
256
+ readonly context: import("@angular/core").Signal<Readonly<{
257
+ readonly device: GPUDevice;
258
+ readonly adapter: GPUAdapter;
259
+ readonly pipelineCache?: import("chartgpu").PipelineCache;
260
+ }> | null>;
261
+ private initialization?;
262
+ initialize(): Promise<ChartgpuGPUContextState>;
263
+ private createContext;
264
+ static ɵfac: i0.ɵɵFactoryDeclaration<ChartgpuGPUContextService, never>;
265
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
266
+ }
267
+ export type { ChartGPUCreateContext, ChartGPUCrosshairMovePayload, ChartGPUDeviceLostPayload, ChartGPUEventPayload, ChartGPUHitTestResult, ChartGPUInstance, ChartSyncOptions, DataPoint, OHLCDataPoint, PipelineCache, RenderMode };