cats-charts 0.0.86 → 0.0.88

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/README.md CHANGED
@@ -1,712 +1,712 @@
1
- # CATS4U Charts
2
-
3
- ![npm](https://img.shields.io/npm/v/cats-charts)
4
- ![npm downloads](https://img.shields.io/npm/dm/cats-charts)
5
- ![license](https://img.shields.io/npm/l/cats-charts)
6
- ![angular](https://img.shields.io/badge/angular-20-red)
7
-
8
- **CATS4U Charts** is a reusable Angular chart library built on **Apache ECharts** and **ngx-echarts**.
9
- It provides easy-to-use components for rendering interactive charts such as **Bar, Line, Area, Pie, Doughnut, Sankey, Timeline**, and more.
10
-
11
- ---
12
-
13
- # ✨ Features
14
-
15
- - 📊 Multiple chart types
16
- - ⚡ Powered by Apache ECharts
17
- - 🔌 Angular Standalone Components
18
- - 🎨 Built-in theme support
19
- - 🖱 Click & drill-down events
20
- - 🧩 Easy integration
21
- - 📦 Lightweight and reusable
22
-
23
- ---
24
-
25
- # 📦 Installation
26
-
27
- Install the package along with required dependencies:
28
-
29
- ```bash
30
- npm install cats-charts
31
-
32
- ```
33
-
34
- # 🚀 Usage
35
-
36
- ## Import Library
37
-
38
- ```ts
39
- import { ChartsLib } from 'cats-charts';
40
- ```
41
-
42
- ## TS Syntax
43
-
44
- ```ts
45
- import {
46
- BarChart,
47
- CustomChartComponent,
48
- DoughnutChart,
49
- LinesChart,
50
- PieChart,
51
- SankeyChart
52
- } from 'cats-charts';
53
-
54
- @Component({
55
- ...,
56
- imports: [
57
- BarChart,
58
- CustomChartComponent,
59
- DoughnutChart,
60
- LinesChart,
61
- PieChart,
62
- SankeyChart
63
- ],
64
- })
65
- export class App {}
66
- ```
67
-
68
- ---
69
-
70
- # ⚙️ Inputs
71
-
72
- | Input | Type | Description |
73
- | ------------------ | ------------------------------------------------- | -------------------------------------------------------------- |
74
- | config | | Configuration options to customize chart and pass dynamic data |
75
- | theme | string | default \| dark \| vintage \| essos \| chalk \| roma |
76
- | contextMenuOptions | { label: string; value: string; icon?: string }[] | Context menu options |
77
- | events | string[] | ['click', 'contextmenu', 'dblclick'] |
78
-
79
- ---
80
-
81
- # 📤 Outputs
82
-
83
- | Output | Description |
84
- | ---------------- | ---------------------- |
85
- | contextMenuClick | ( event: any ) => void |
86
- | chartEvent | ( event: any ) => void |
87
-
88
- ## Bar chart config
89
-
90
- ```ts
91
- BarChartConfig {
92
- series: {
93
- name: string;
94
- data: number[];
95
- [key: string]: any;
96
- }[];
97
- xAxisData: string[];
98
- colors?: string[];
99
- backgroundColor?: string;
100
-
101
- // --------------- Title configs ---------------
102
- title?: string;
103
- titlePosition?: string;
104
- showTitle?: boolean;
105
-
106
- // --------------- Tooltip configs ---------------
107
- showTooltip?: boolean;
108
- tooltipFormatter?: (params: any) => void;
109
-
110
- // --------------- Grid configs ---------------
111
- gridLeft?: string | number;
112
- gridRight?: string | number;
113
- gridBottom?: string | number;
114
- gridTop?: string | number;
115
-
116
- // --------------- Zoom Slider configs ---------------
117
- showZoomSlider?: boolean;
118
- zoomStart?: number;
119
- zoomEnd?: number;
120
- zoomControlButtonStyle?: any;
121
-
122
- yAxis?: any;
123
- xAxis?: any;
124
- stacked?: boolean;
125
-
126
- barWidth?: string | number;
127
-
128
- borderRadius?: number;
129
- showLabel?: boolean;
130
- labelPosition?: string;
131
- showXAxisLine?: boolean;
132
- showYAxisLine?: boolean;
133
- // Legend
134
- hideLegend?: boolean;
135
- legendPosition?: 'top' | 'bottom' | 'left' | 'right' | string;
136
- legendAlign?: 'left' | 'center' | 'right' | string;
137
- legendDirection?: 'horizontal' | 'vertical' | string;
138
- legendTextColor?: string;
139
- legendFontSize?: number;
140
- legendContainerWidth?: number; // 0-1
141
- legendIndicatorHeight?: number; // number value is in px
142
- }
143
- ```
144
-
145
- ## Line and Area Chart config
146
-
147
- ```ts
148
- LineChartConfig {
149
- isTrendChart?: boolean;
150
- title?: string;
151
- showTitle?: boolean;
152
- titlePosition?: string;
153
- xAxisData: string[];
154
- tooltipFormatter?: (params: any) => void;
155
- colors?: string[];
156
- series: {
157
- name: string;
158
- data: number[];
159
- areaColor?: string;
160
- smooth?: boolean;
161
- area?: boolean;
162
- [key: string]: any;
163
- }[];
164
- // --------------- Grid configs ---------------
165
- gridLeft?: string | number;
166
- gridRight?: string | number;
167
- gridBottom?: string | number;
168
- gridTop?: string | number;
169
-
170
- borderRadius?: number;
171
- showLabel?: boolean;
172
- labelPosition?: string;
173
-
174
- yAxis?: any;
175
- xAxis?: any;
176
- showXAxisLine?: boolean;
177
- showYAxisLine?: boolean;
178
- showTooltip?: boolean;
179
-
180
- backgroundColor?: string;
181
-
182
- // Legend
183
- hideLegend?: boolean;
184
- legendPosition?: 'top' | 'bottom' | 'left' | 'right' | string;
185
- legendAlign?: 'left' | 'center' | 'right' | string;
186
- legendDirection?: 'horizontal' | 'vertical' | string;
187
- legendTextColor?: string;
188
- legendFontSize?: number;
189
- legendContainerWidth?: number; // 0-1
190
- legendIndicatorHeight?: number; // number value is in px
191
-
192
- customLegend?: ChartLegendConfig<LineChartConfig['series'][number]>;
193
-
194
- }
195
- ```
196
-
197
- ### CustomLegend
198
-
199
- ```ts
200
- type customLegend = {
201
- enabled?: boolean;
202
-
203
- // layout/positioning
204
- layout?: 'horizontal' | 'vertical';
205
- position?: 'top' | 'bottom' | 'left' | 'right';
206
- align?: 'start' | 'center' | 'end';
207
-
208
- // selection behavior
209
- selectionMode?: 'multiple' | 'single' | 'exclusive';
210
-
211
- // scrolling / pagination
212
- scrollable?: boolean;
213
- maxHeight?: string;
214
- maxWidth?: string;
215
- pageSize?: number;
216
- showPagination?: boolean;
217
-
218
- // disabling items
219
- disabled?: boolean;
220
- disabledNames?: string[];
221
-
222
- // accessibility / styling
223
- className?: string;
224
- ariaLabel?: string;
225
- legendTextColor?: string;
226
- legendFontSize?: number;
227
-
228
- // icon rendering
229
- icon?: ChartLegendIcon | ((series: TSeries, index: number) => ChartLegendIcon);
230
-
231
- icons?: Record<string, ChartLegendIcon>;
232
-
233
- // label formatting
234
- formatter?: (name: string, item: ChartLegendItem) => string;
235
- tooltipFormatter?: (item: ChartLegendItem) => string;
236
-
237
- // grouping
238
- groupBy?: (item: ChartLegendItem) => string | undefined;
239
-
240
- // custom Angular template
241
- itemTemplate?: TemplateRef<ChartLegendTemplateContext>;
242
-
243
- // virtualization (advanced)
244
- virtualize?: boolean;
245
- virtualItemHeight?: number;
246
-
247
- // hover behavior linking
248
- hoverLink?: boolean;
249
- };
250
- ```
251
-
252
- ### CustomLegend Example
253
-
254
- ```ts
255
- customLegend?: {
256
- // enable/disable legend UI
257
- enabled?: boolean;
258
-
259
- // layout
260
- layout?: 'horizontal' | 'vertical';
261
- position?: 'top' | 'bottom' | 'left' | 'right';
262
- align?: 'start' | 'center' | 'end';
263
-
264
- // selection behavior
265
- selectionMode?: 'multiple' | 'single' | 'exclusive';
266
-
267
- // scrolling/pagination
268
- scrollable?: boolean;
269
- maxHeight?: string;
270
- maxWidth?: string;
271
- pageSize?: number;
272
- showPagination?: boolean;
273
-
274
- // disabling items
275
- disabled?: boolean;
276
- disabledNames?: string[];
277
-
278
- // styling & accessibility
279
- className?: string;
280
- ariaLabel?: string;
281
- legendTextColor?: string;
282
- legendFontSize?: number;
283
-
284
- // icon configuration
285
- // - either a static icon
286
- // - or a function that returns an icon per series/index
287
- icon?:
288
- | ChartLegendIcon
289
- | ((series: TSeries, index: number) => ChartLegendIcon);
290
-
291
- // mapping of icon names -> icon types
292
- icons?: Record<string, ChartLegendIcon>;
293
-
294
- // text formatting
295
- formatter?: (name: string, item: ChartLegendItem) => string;
296
-
297
- // tooltip formatting
298
- tooltipFormatter?: (item: ChartLegendItem) => string;
299
-
300
- // grouping
301
- groupBy?: (item: ChartLegendItem) => string | undefined;
302
-
303
- // custom Angular template (advanced)
304
- itemTemplate?: TemplateRef<ChartLegendTemplateContext>;
305
-
306
- // virtualization (advanced)
307
- virtualize?: boolean;
308
- virtualItemHeight?: number;
309
-
310
- // hover linking (advanced)
311
- hoverLink?: boolean;
312
- };
313
-
314
- ```
315
-
316
- ## Pie and Donut chart config
317
-
318
- ```ts
319
- DoughnutChartConfig {
320
- title?: string;
321
- showTitle?: boolean;
322
- titlePosition?: 'left' | 'center' | 'right';
323
- top?: any;
324
- bottom?: any;
325
- backgroundColor?: string;
326
- series?: any;
327
- data: {
328
- name: string;
329
- value: number;
330
- [key: string]: any;
331
- }[];
332
-
333
- colors?: string[];
334
-
335
- // Doughnut
336
- innerRadius?: string;
337
- outerRadius?: string;
338
- center?: string[];
339
- // Center Text
340
- showCenterText?: boolean;
341
- centerLabel?: any;
342
- centerValue?: string;
343
- centerValueFromTotal?: boolean;
344
-
345
- // Tooltip
346
- showTooltip?: boolean;
347
- showTooltipPercent?: boolean;
348
- tooltipFormatter?: (params: any, config: DoughnutChartConfig) => void;
349
- valueFormatter?: (value: number) => string;
350
-
351
- // Legend
352
- hideLegend?: boolean;
353
- legendBottom?: number;
354
- legendPosition?: 'top' | 'bottom' | 'left' | 'right' | string;
355
- legendAlign?: 'left' | 'center' | 'right' | string;
356
- legendDirection?: 'horizontal' | 'vertical' | string;
357
- legendTextColor?: string;
358
- legendFontSize?: number;
359
- legendContainerWidth?: number; // 0-1
360
- // Labels
361
- showLabel?: boolean;
362
- labelPosition?: 'inside' | 'outside' | 'center';
363
- showLabelValue?: boolean;
364
- showLabelPercentage?: boolean;
365
-
366
- // Emphasis
367
- emphasisScale?: boolean;
368
-
369
- // Style
370
- borderRadius?: number;
371
- borderColor?: string;
372
- borderWidth?: number;
373
-
374
- enableHoverEffect?: boolean;
375
- }
376
- ```
377
-
378
- ## Custom chart config
379
-
380
- ```ts
381
- CustomChartConfig {
382
- startHour?: string;
383
- endHour?: string;
384
-
385
- shiftColor?: string;
386
- chartMode: 'weekly' | 'daily' | string;
387
-
388
- yAxisData: string[];
389
- categories: string[];
390
- legends: TimeLineLegends;
391
-
392
- barHeight?: number;
393
- shiftHeight?: number;
394
-
395
- data: TimelineData[];
396
- hideLegendCategory?: boolean;
397
- }
398
- ```
399
-
400
- ## Scatter Chart config
401
-
402
- ```ts
403
- ScatterChartConfig {
404
- title?: string;
405
- showTitle?: boolean;
406
- titlePosition?: string;
407
- tooltipFormatter?: (params: any) => void;
408
- colors?: string[];
409
- series: {
410
- name: string;
411
- data: number[];
412
- [key: string]: any;
413
- }[];
414
- // --------------- Grid configs ---------------
415
- gridLeft?: string | number;
416
- gridRight?: string | number;
417
- gridBottom?: string | number;
418
- gridTop?: string | number;
419
-
420
- labelPosition?: string;
421
-
422
- yAxis?: any;
423
- xAxis?: any;
424
- showXAxisLine?: boolean;
425
- showYAxisLine?: boolean;
426
- showTooltip?: boolean;
427
-
428
- backgroundColor?: string;
429
-
430
- // Legend
431
- hideLegend?: boolean;
432
- legendPosition?: 'top' | 'bottom' | 'left' | 'right' | string;
433
- legendAlign?: 'left' | 'center' | 'right' | string;
434
- legendDirection?: 'horizontal' | 'vertical' | string;
435
- legendTextColor?: string;
436
- legendFontSize?: number;
437
- legendContainerWidth?: number; // 0-1
438
- legendIndicatorHeight?: number; // number value is in px
439
- xAxisName?: string;
440
- yAxisName?: string;
441
- }
442
- ```
443
-
444
- ## Sankey Chart config
445
-
446
- ```ts
447
- SankeyChartConfig {
448
- title?: string;
449
- showTitle?: boolean;
450
- backgroundColor?: string;
451
- colors?: string[];
452
- showTooltip?: boolean;
453
- tooltipFormatter?: (params: any) => string;
454
- nodes: SankeyNode[];
455
- links: SankeyLink[];
456
- seriesOption?: SankeySeriesOption;
457
- lineCurveness?: number;
458
- }
459
- ```
460
-
461
- ### For `SankeySeriesOption` refer echarts Sankey series documentation
462
-
463
- https://echarts.apache.org/en/option.html#series-sankey
464
-
465
- # 📊 Supported Charts
466
-
467
- - Bar Chart
468
- - Line Chart
469
- - Area Chart
470
- - Pie Chart
471
- - Doughnut Chart
472
- - Stacked Area Chart
473
- - Sankey Chart
474
- - Heatmap Chart
475
- - Custom Charts
476
-
477
- * Bar Chart
478
- * Line Chart
479
- * Area Chart
480
- * Pie Chart
481
- * Doughnut Chart
482
- * Stacked Area Chart
483
- * Sankey Chart
484
- * Custom Charts
485
-
486
- ---
487
-
488
- # Heatmap Chart
489
-
490
- The heatmap component renders category-based intensity data using Apache ECharts.
491
- Use `[xIndex, yIndex, value]` tuples, where `xIndex` points to `xAxisData` and `yIndex` points to `yAxisData`.
492
-
493
- ## Import
494
-
495
- ```ts
496
- import { Heatmap } from 'cats-charts';
497
-
498
- @Component({
499
- selector: 'app-root',
500
- standalone: true,
501
- imports: [Heatmap],
502
- templateUrl: './app.html',
503
- })
504
- export class App {}
505
- ```
506
-
507
- ## HTML
508
-
509
- ```html
510
- <div style="width: 100%; height: 340px">
511
- <lib-heatmap
512
- [config]="heatmapConfig"
513
- [theme]="selectedTheme"
514
- [events]="['click', 'contextmenu']"
515
- (chartEvent)="handleChartEvent($event)"
516
- ></lib-heatmap>
517
- </div>
518
- ```
519
-
520
- ## TypeScript
521
-
522
- ```ts
523
- heatmapConfig = {
524
- xAxisData: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00'],
525
- yAxisData: ['eth0', 'eth1', 'wlan0', 'vlan10', 'vlan20'],
526
-
527
- data: [
528
- [0, 0, 20],
529
- [1, 0, 60],
530
- [2, 0, 0],
531
- [3, 0, 40],
532
- [4, 0, 80],
533
- [5, 0, 100],
534
-
535
- [0, 1, 40],
536
- [1, 1, 0],
537
- [2, 1, 20],
538
- [3, 1, 60],
539
- [4, 1, 100],
540
- [5, 1, 80],
541
- ] as [number, number, number][],
542
-
543
- min: 0,
544
- max: 100,
545
- showTooltip: true,
546
-
547
- grid: {
548
- left: 58,
549
- right: 18,
550
- top: 20,
551
- bottom: 46,
552
- containLabel: false,
553
- },
554
-
555
- xAxis: {
556
- axisLabel: { color: '#6b7280' },
557
- axisLine: { lineStyle: { color: '#9ca3af' } },
558
- axisTick: { show: true },
559
- },
560
-
561
- yAxis: {
562
- inverse: true,
563
- axisLabel: { color: '#6b7280' },
564
- axisLine: { show: false },
565
- axisTick: { show: true },
566
- },
567
-
568
- visualMap: {
569
- type: 'piecewise',
570
- pieces: [
571
- { min: 0, max: 20, label: '20%', color: '#fde6bd' },
572
- { min: 21, max: 40, label: '40%', color: '#ffd85a' },
573
- { min: 41, max: 60, label: '60%', color: '#ffb247' },
574
- { min: 61, max: 80, label: '80%', color: '#ff0b1f' },
575
- { min: 81, max: 100, label: '100%', color: '#a51d29' },
576
- ],
577
- },
578
-
579
- series: {
580
- itemStyle: {
581
- borderWidth: 0,
582
- },
583
- },
584
- };
585
- ```
586
-
587
- ## Heatmap Config Options
588
-
589
- | Option | Type | Description |
590
- | ---------------- | -------------------------- | ----------------------------------------------------------------------- |
591
- | xAxisData | string[] | Labels for the x-axis |
592
- | yAxisData | string[] | Labels for the y-axis |
593
- | data | [number, number, number][] | Heatmap cells as `[xIndex, yIndex, value]` |
594
- | min | number | Minimum value for color mapping |
595
- | max | number | Maximum value for color mapping |
596
- | colors | string[] | Continuous color range when `visualMap.pieces` is not used |
597
- | visualMap | any | ECharts visual map config. `pieces` also drives the custom legend pills |
598
- | grid | object | ECharts grid config |
599
- | xAxis | any | Extra ECharts x-axis config |
600
- | yAxis | any | Extra ECharts y-axis config |
601
- | showTooltip | boolean | Enables or disables tooltip |
602
- | tooltipFormatter | function | Custom tooltip formatter |
603
- | showLabel | boolean | Shows value labels inside cells |
604
- | labelFormatter | string \| function | Cell label formatter |
605
- | series | any \| any[] | Extra ECharts heatmap series config |
606
-
607
- ---
608
-
609
- # 🎨 Themes
610
-
611
- Available chart themes:
612
-
613
- - default
614
- - dark
615
- - vintage
616
- - essos
617
- - chalk
618
- - roma
619
-
620
- ---
621
-
622
- # 📚 Documentation
623
-
624
- Apache ECharts documentation:
625
-
626
- https://echarts.apache.org/en/api.html#echarts
627
-
628
- ---
629
-
630
- # 🤝 Contributing
631
-
632
- Contributions, issues, and feature requests are welcome.
633
- Feel free to submit a pull request.
634
-
635
- ---
636
-
637
- # 📄 License
638
-
639
- MIT License
640
-
641
- ---
642
-
643
- # Status Timeline
644
-
645
- `StatusTimelineComponent` renders generic categorical intervals in chronological order. Segment
646
- widths are proportional to duration, and dense datasets scroll horizontally without aggregation.
647
-
648
- ## Import and usage
649
-
650
- ```ts
651
- import { StatusTimelineComponent, type StatusTimelineConfig } from 'cats-charts';
652
-
653
- @Component({
654
- standalone: true,
655
- imports: [StatusTimelineComponent],
656
- template: `
657
- <lib-status-timeline
658
- [config]="timelineConfig"
659
- (chartEvent)="onTimelineEvent($event)"
660
- />
661
- `,
662
- })
663
- export class ExampleComponent {
664
- timelineConfig: StatusTimelineConfig = {
665
- startLabel: 'Monday',
666
- endLabel: 'Today',
667
- statuses: [
668
- { value: 'ready', label: 'Ready', color: '#2f8f3a' },
669
- { value: 'deploying', label: 'Deploying', color: '#d0a020' },
670
- { value: 'blocked', label: 'Blocked', color: '#a43b35' },
671
- ],
672
- data: [
673
- { start: '2026-08-24T00:00:00Z', end: '2026-08-25T00:00:00Z', status: 'ready' },
674
- {
675
- start: '2026-08-25T00:00:00Z',
676
- end: '2026-08-25T06:00:00Z',
677
- status: 'deploying',
678
- label: 'Release deployment',
679
- },
680
- { start: '2026-08-25T06:00:00Z', end: '2026-08-26T00:00:00Z', status: 'ready' },
681
- ],
682
- };
683
- }
684
- ```
685
-
686
- ## Configuration
687
-
688
- | Option | Description |
689
- | --- | --- |
690
- | `data` | Dynamic intervals with `start`, `end`, `status`, and optional `label`/`metadata` |
691
- | `statuses` | Text and optional color for each status value |
692
- | `showLegend`, `showTooltip` | Toggle supporting UI (both default to `true`) |
693
- | `legendPosition` | Places the legend at `top`, `bottom`, `left`, or `right` |
694
- | `legendLayout` | Arranges legend items `horizontal` or `vertical` |
695
- | `legendAlign` | Aligns the legend at `start`/`left`, `center`, `end`/`right`, or `space-between` |
696
- | `legendLabelAlign` | Aligns text within vertical legend items to `left`, `center`, or `right` |
697
- | `legendInteractive` | Enables clicking legend labels to dim/restore matching intervals; defaults to `true` |
698
- | `legendDimmedOpacity` | Opacity used for inactive legend items and intervals; defaults to `0.3` |
699
- | `legendScrollable` | Enables bounded legend overflow scrolling; defaults to `true` |
700
- | `legendMaxWidth`, `legendMaxHeight` | Optional scroll viewport limits |
701
- | `legendNote` | Optional explanatory text displayed beside the legend |
702
- | `startLabel`, `endLabel` | Endpoint text; dates are derived when omitted |
703
- | `showEndpointLabels` | Shows or hides the endpoint-label row; defaults to `true` |
704
- | `endpointLabelsAlign` | Aligns endpoint labels at `start`/`left`, `center`, `end`/`right`, or `space-between` |
705
- | `loading`, `loadingLabel`, `emptyLabel`, `error` | Timeline state presentation |
706
- | `minSegmentWidth`, `segmentGap` | Dense-data and spacing controls in pixels |
707
- | `dateFormatter`, `durationFormatter`, `tooltipFormatter` | Display customization hooks |
708
- | `unknownStatus` | Fallback label/color for unconfigured status values |
709
- | `ariaLabel` | Accessible name for the timeline |
710
-
711
- The component emits `chartEvent` with `{ type: 'itemClick', item, index }`. Its appearance can be
712
- themed with the `--status-timeline-*` CSS custom properties defined in the component stylesheet.
1
+ # CATS4U Charts
2
+
3
+ ![npm](https://img.shields.io/npm/v/cats-charts)
4
+ ![npm downloads](https://img.shields.io/npm/dm/cats-charts)
5
+ ![license](https://img.shields.io/npm/l/cats-charts)
6
+ ![angular](https://img.shields.io/badge/angular-20-red)
7
+
8
+ **CATS4U Charts** is a reusable Angular chart library built on **Apache ECharts** and **ngx-echarts**.
9
+ It provides easy-to-use components for rendering interactive charts such as **Bar, Line, Area, Pie, Doughnut, Sankey, Timeline**, and more.
10
+
11
+ ---
12
+
13
+ # ✨ Features
14
+
15
+ - 📊 Multiple chart types
16
+ - ⚡ Powered by Apache ECharts
17
+ - 🔌 Angular Standalone Components
18
+ - 🎨 Built-in theme support
19
+ - 🖱 Click & drill-down events
20
+ - 🧩 Easy integration
21
+ - 📦 Lightweight and reusable
22
+
23
+ ---
24
+
25
+ # 📦 Installation
26
+
27
+ Install the package along with required dependencies:
28
+
29
+ ```bash
30
+ npm install cats-charts
31
+
32
+ ```
33
+
34
+ # 🚀 Usage
35
+
36
+ ## Import Library
37
+
38
+ ```ts
39
+ import { ChartsLib } from 'cats-charts';
40
+ ```
41
+
42
+ ## TS Syntax
43
+
44
+ ```ts
45
+ import {
46
+ BarChart,
47
+ CustomChartComponent,
48
+ DoughnutChart,
49
+ LinesChart,
50
+ PieChart,
51
+ SankeyChart
52
+ } from 'cats-charts';
53
+
54
+ @Component({
55
+ ...,
56
+ imports: [
57
+ BarChart,
58
+ CustomChartComponent,
59
+ DoughnutChart,
60
+ LinesChart,
61
+ PieChart,
62
+ SankeyChart
63
+ ],
64
+ })
65
+ export class App {}
66
+ ```
67
+
68
+ ---
69
+
70
+ # ⚙️ Inputs
71
+
72
+ | Input | Type | Description |
73
+ | ------------------ | ------------------------------------------------- | -------------------------------------------------------------- |
74
+ | config | | Configuration options to customize chart and pass dynamic data |
75
+ | theme | string | default \| dark \| vintage \| essos \| chalk \| roma |
76
+ | contextMenuOptions | { label: string; value: string; icon?: string }[] | Context menu options |
77
+ | events | string[] | ['click', 'contextmenu', 'dblclick'] |
78
+
79
+ ---
80
+
81
+ # 📤 Outputs
82
+
83
+ | Output | Description |
84
+ | ---------------- | ---------------------- |
85
+ | contextMenuClick | ( event: any ) => void |
86
+ | chartEvent | ( event: any ) => void |
87
+
88
+ ## Bar chart config
89
+
90
+ ```ts
91
+ BarChartConfig {
92
+ series: {
93
+ name: string;
94
+ data: number[];
95
+ [key: string]: any;
96
+ }[];
97
+ xAxisData: string[];
98
+ colors?: string[];
99
+ backgroundColor?: string;
100
+
101
+ // --------------- Title configs ---------------
102
+ title?: string;
103
+ titlePosition?: string;
104
+ showTitle?: boolean;
105
+
106
+ // --------------- Tooltip configs ---------------
107
+ showTooltip?: boolean;
108
+ tooltipFormatter?: (params: any) => void;
109
+
110
+ // --------------- Grid configs ---------------
111
+ gridLeft?: string | number;
112
+ gridRight?: string | number;
113
+ gridBottom?: string | number;
114
+ gridTop?: string | number;
115
+
116
+ // --------------- Zoom Slider configs ---------------
117
+ showZoomSlider?: boolean;
118
+ zoomStart?: number;
119
+ zoomEnd?: number;
120
+ zoomControlButtonStyle?: any;
121
+
122
+ yAxis?: any;
123
+ xAxis?: any;
124
+ stacked?: boolean;
125
+
126
+ barWidth?: string | number;
127
+
128
+ borderRadius?: number;
129
+ showLabel?: boolean;
130
+ labelPosition?: string;
131
+ showXAxisLine?: boolean;
132
+ showYAxisLine?: boolean;
133
+ // Legend
134
+ hideLegend?: boolean;
135
+ legendPosition?: 'top' | 'bottom' | 'left' | 'right' | string;
136
+ legendAlign?: 'left' | 'center' | 'right' | string;
137
+ legendDirection?: 'horizontal' | 'vertical' | string;
138
+ legendTextColor?: string;
139
+ legendFontSize?: number;
140
+ legendContainerWidth?: number; // 0-1
141
+ legendIndicatorHeight?: number; // number value is in px
142
+ }
143
+ ```
144
+
145
+ ## Line and Area Chart config
146
+
147
+ ```ts
148
+ LineChartConfig {
149
+ isTrendChart?: boolean;
150
+ title?: string;
151
+ showTitle?: boolean;
152
+ titlePosition?: string;
153
+ xAxisData: string[];
154
+ tooltipFormatter?: (params: any) => void;
155
+ colors?: string[];
156
+ series: {
157
+ name: string;
158
+ data: number[];
159
+ areaColor?: string;
160
+ smooth?: boolean;
161
+ area?: boolean;
162
+ [key: string]: any;
163
+ }[];
164
+ // --------------- Grid configs ---------------
165
+ gridLeft?: string | number;
166
+ gridRight?: string | number;
167
+ gridBottom?: string | number;
168
+ gridTop?: string | number;
169
+
170
+ borderRadius?: number;
171
+ showLabel?: boolean;
172
+ labelPosition?: string;
173
+
174
+ yAxis?: any;
175
+ xAxis?: any;
176
+ showXAxisLine?: boolean;
177
+ showYAxisLine?: boolean;
178
+ showTooltip?: boolean;
179
+
180
+ backgroundColor?: string;
181
+
182
+ // Legend
183
+ hideLegend?: boolean;
184
+ legendPosition?: 'top' | 'bottom' | 'left' | 'right' | string;
185
+ legendAlign?: 'left' | 'center' | 'right' | string;
186
+ legendDirection?: 'horizontal' | 'vertical' | string;
187
+ legendTextColor?: string;
188
+ legendFontSize?: number;
189
+ legendContainerWidth?: number; // 0-1
190
+ legendIndicatorHeight?: number; // number value is in px
191
+
192
+ customLegend?: ChartLegendConfig<LineChartConfig['series'][number]>;
193
+
194
+ }
195
+ ```
196
+
197
+ ### CustomLegend
198
+
199
+ ```ts
200
+ type customLegend = {
201
+ enabled?: boolean;
202
+
203
+ // layout/positioning
204
+ layout?: 'horizontal' | 'vertical';
205
+ position?: 'top' | 'bottom' | 'left' | 'right';
206
+ align?: 'start' | 'center' | 'end';
207
+
208
+ // selection behavior
209
+ selectionMode?: 'multiple' | 'single' | 'exclusive';
210
+
211
+ // scrolling / pagination
212
+ scrollable?: boolean;
213
+ maxHeight?: string;
214
+ maxWidth?: string;
215
+ pageSize?: number;
216
+ showPagination?: boolean;
217
+
218
+ // disabling items
219
+ disabled?: boolean;
220
+ disabledNames?: string[];
221
+
222
+ // accessibility / styling
223
+ className?: string;
224
+ ariaLabel?: string;
225
+ legendTextColor?: string;
226
+ legendFontSize?: number;
227
+
228
+ // icon rendering
229
+ icon?: ChartLegendIcon | ((series: TSeries, index: number) => ChartLegendIcon);
230
+
231
+ icons?: Record<string, ChartLegendIcon>;
232
+
233
+ // label formatting
234
+ formatter?: (name: string, item: ChartLegendItem) => string;
235
+ tooltipFormatter?: (item: ChartLegendItem) => string;
236
+
237
+ // grouping
238
+ groupBy?: (item: ChartLegendItem) => string | undefined;
239
+
240
+ // custom Angular template
241
+ itemTemplate?: TemplateRef<ChartLegendTemplateContext>;
242
+
243
+ // virtualization (advanced)
244
+ virtualize?: boolean;
245
+ virtualItemHeight?: number;
246
+
247
+ // hover behavior linking
248
+ hoverLink?: boolean;
249
+ };
250
+ ```
251
+
252
+ ### CustomLegend Example
253
+
254
+ ```ts
255
+ customLegend?: {
256
+ // enable/disable legend UI
257
+ enabled?: boolean;
258
+
259
+ // layout
260
+ layout?: 'horizontal' | 'vertical';
261
+ position?: 'top' | 'bottom' | 'left' | 'right';
262
+ align?: 'start' | 'center' | 'end';
263
+
264
+ // selection behavior
265
+ selectionMode?: 'multiple' | 'single' | 'exclusive';
266
+
267
+ // scrolling/pagination
268
+ scrollable?: boolean;
269
+ maxHeight?: string;
270
+ maxWidth?: string;
271
+ pageSize?: number;
272
+ showPagination?: boolean;
273
+
274
+ // disabling items
275
+ disabled?: boolean;
276
+ disabledNames?: string[];
277
+
278
+ // styling & accessibility
279
+ className?: string;
280
+ ariaLabel?: string;
281
+ legendTextColor?: string;
282
+ legendFontSize?: number;
283
+
284
+ // icon configuration
285
+ // - either a static icon
286
+ // - or a function that returns an icon per series/index
287
+ icon?:
288
+ | ChartLegendIcon
289
+ | ((series: TSeries, index: number) => ChartLegendIcon);
290
+
291
+ // mapping of icon names -> icon types
292
+ icons?: Record<string, ChartLegendIcon>;
293
+
294
+ // text formatting
295
+ formatter?: (name: string, item: ChartLegendItem) => string;
296
+
297
+ // tooltip formatting
298
+ tooltipFormatter?: (item: ChartLegendItem) => string;
299
+
300
+ // grouping
301
+ groupBy?: (item: ChartLegendItem) => string | undefined;
302
+
303
+ // custom Angular template (advanced)
304
+ itemTemplate?: TemplateRef<ChartLegendTemplateContext>;
305
+
306
+ // virtualization (advanced)
307
+ virtualize?: boolean;
308
+ virtualItemHeight?: number;
309
+
310
+ // hover linking (advanced)
311
+ hoverLink?: boolean;
312
+ };
313
+
314
+ ```
315
+
316
+ ## Pie and Donut chart config
317
+
318
+ ```ts
319
+ DoughnutChartConfig {
320
+ title?: string;
321
+ showTitle?: boolean;
322
+ titlePosition?: 'left' | 'center' | 'right';
323
+ top?: any;
324
+ bottom?: any;
325
+ backgroundColor?: string;
326
+ series?: any;
327
+ data: {
328
+ name: string;
329
+ value: number;
330
+ [key: string]: any;
331
+ }[];
332
+
333
+ colors?: string[];
334
+
335
+ // Doughnut
336
+ innerRadius?: string;
337
+ outerRadius?: string;
338
+ center?: string[];
339
+ // Center Text
340
+ showCenterText?: boolean;
341
+ centerLabel?: any;
342
+ centerValue?: string;
343
+ centerValueFromTotal?: boolean;
344
+
345
+ // Tooltip
346
+ showTooltip?: boolean;
347
+ showTooltipPercent?: boolean;
348
+ tooltipFormatter?: (params: any, config: DoughnutChartConfig) => void;
349
+ valueFormatter?: (value: number) => string;
350
+
351
+ // Legend
352
+ hideLegend?: boolean;
353
+ legendBottom?: number;
354
+ legendPosition?: 'top' | 'bottom' | 'left' | 'right' | string;
355
+ legendAlign?: 'left' | 'center' | 'right' | string;
356
+ legendDirection?: 'horizontal' | 'vertical' | string;
357
+ legendTextColor?: string;
358
+ legendFontSize?: number;
359
+ legendContainerWidth?: number; // 0-1
360
+ // Labels
361
+ showLabel?: boolean;
362
+ labelPosition?: 'inside' | 'outside' | 'center';
363
+ showLabelValue?: boolean;
364
+ showLabelPercentage?: boolean;
365
+
366
+ // Emphasis
367
+ emphasisScale?: boolean;
368
+
369
+ // Style
370
+ borderRadius?: number;
371
+ borderColor?: string;
372
+ borderWidth?: number;
373
+
374
+ enableHoverEffect?: boolean;
375
+ }
376
+ ```
377
+
378
+ ## Custom chart config
379
+
380
+ ```ts
381
+ CustomChartConfig {
382
+ startHour?: string;
383
+ endHour?: string;
384
+
385
+ shiftColor?: string;
386
+ chartMode: 'weekly' | 'daily' | string;
387
+
388
+ yAxisData: string[];
389
+ categories: string[];
390
+ legends: TimeLineLegends;
391
+
392
+ barHeight?: number;
393
+ shiftHeight?: number;
394
+
395
+ data: TimelineData[];
396
+ hideLegendCategory?: boolean;
397
+ }
398
+ ```
399
+
400
+ ## Scatter Chart config
401
+
402
+ ```ts
403
+ ScatterChartConfig {
404
+ title?: string;
405
+ showTitle?: boolean;
406
+ titlePosition?: string;
407
+ tooltipFormatter?: (params: any) => void;
408
+ colors?: string[];
409
+ series: {
410
+ name: string;
411
+ data: number[];
412
+ [key: string]: any;
413
+ }[];
414
+ // --------------- Grid configs ---------------
415
+ gridLeft?: string | number;
416
+ gridRight?: string | number;
417
+ gridBottom?: string | number;
418
+ gridTop?: string | number;
419
+
420
+ labelPosition?: string;
421
+
422
+ yAxis?: any;
423
+ xAxis?: any;
424
+ showXAxisLine?: boolean;
425
+ showYAxisLine?: boolean;
426
+ showTooltip?: boolean;
427
+
428
+ backgroundColor?: string;
429
+
430
+ // Legend
431
+ hideLegend?: boolean;
432
+ legendPosition?: 'top' | 'bottom' | 'left' | 'right' | string;
433
+ legendAlign?: 'left' | 'center' | 'right' | string;
434
+ legendDirection?: 'horizontal' | 'vertical' | string;
435
+ legendTextColor?: string;
436
+ legendFontSize?: number;
437
+ legendContainerWidth?: number; // 0-1
438
+ legendIndicatorHeight?: number; // number value is in px
439
+ xAxisName?: string;
440
+ yAxisName?: string;
441
+ }
442
+ ```
443
+
444
+ ## Sankey Chart config
445
+
446
+ ```ts
447
+ SankeyChartConfig {
448
+ title?: string;
449
+ showTitle?: boolean;
450
+ backgroundColor?: string;
451
+ colors?: string[];
452
+ showTooltip?: boolean;
453
+ tooltipFormatter?: (params: any) => string;
454
+ nodes: SankeyNode[];
455
+ links: SankeyLink[];
456
+ seriesOption?: SankeySeriesOption;
457
+ lineCurveness?: number;
458
+ }
459
+ ```
460
+
461
+ ### For `SankeySeriesOption` refer echarts Sankey series documentation
462
+
463
+ https://echarts.apache.org/en/option.html#series-sankey
464
+
465
+ # 📊 Supported Charts
466
+
467
+ - Bar Chart
468
+ - Line Chart
469
+ - Area Chart
470
+ - Pie Chart
471
+ - Doughnut Chart
472
+ - Stacked Area Chart
473
+ - Sankey Chart
474
+ - Heatmap Chart
475
+ - Custom Charts
476
+
477
+ * Bar Chart
478
+ * Line Chart
479
+ * Area Chart
480
+ * Pie Chart
481
+ * Doughnut Chart
482
+ * Stacked Area Chart
483
+ * Sankey Chart
484
+ * Custom Charts
485
+
486
+ ---
487
+
488
+ # Heatmap Chart
489
+
490
+ The heatmap component renders category-based intensity data using Apache ECharts.
491
+ Use `[xIndex, yIndex, value]` tuples, where `xIndex` points to `xAxisData` and `yIndex` points to `yAxisData`.
492
+
493
+ ## Import
494
+
495
+ ```ts
496
+ import { Heatmap } from 'cats-charts';
497
+
498
+ @Component({
499
+ selector: 'app-root',
500
+ standalone: true,
501
+ imports: [Heatmap],
502
+ templateUrl: './app.html',
503
+ })
504
+ export class App {}
505
+ ```
506
+
507
+ ## HTML
508
+
509
+ ```html
510
+ <div style="width: 100%; height: 340px">
511
+ <lib-heatmap
512
+ [config]="heatmapConfig"
513
+ [theme]="selectedTheme"
514
+ [events]="['click', 'contextmenu']"
515
+ (chartEvent)="handleChartEvent($event)"
516
+ ></lib-heatmap>
517
+ </div>
518
+ ```
519
+
520
+ ## TypeScript
521
+
522
+ ```ts
523
+ heatmapConfig = {
524
+ xAxisData: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00'],
525
+ yAxisData: ['eth0', 'eth1', 'wlan0', 'vlan10', 'vlan20'],
526
+
527
+ data: [
528
+ [0, 0, 20],
529
+ [1, 0, 60],
530
+ [2, 0, 0],
531
+ [3, 0, 40],
532
+ [4, 0, 80],
533
+ [5, 0, 100],
534
+
535
+ [0, 1, 40],
536
+ [1, 1, 0],
537
+ [2, 1, 20],
538
+ [3, 1, 60],
539
+ [4, 1, 100],
540
+ [5, 1, 80],
541
+ ] as [number, number, number][],
542
+
543
+ min: 0,
544
+ max: 100,
545
+ showTooltip: true,
546
+
547
+ grid: {
548
+ left: 58,
549
+ right: 18,
550
+ top: 20,
551
+ bottom: 46,
552
+ containLabel: false,
553
+ },
554
+
555
+ xAxis: {
556
+ axisLabel: { color: '#6b7280' },
557
+ axisLine: { lineStyle: { color: '#9ca3af' } },
558
+ axisTick: { show: true },
559
+ },
560
+
561
+ yAxis: {
562
+ inverse: true,
563
+ axisLabel: { color: '#6b7280' },
564
+ axisLine: { show: false },
565
+ axisTick: { show: true },
566
+ },
567
+
568
+ visualMap: {
569
+ type: 'piecewise',
570
+ pieces: [
571
+ { min: 0, max: 20, label: '20%', color: '#fde6bd' },
572
+ { min: 21, max: 40, label: '40%', color: '#ffd85a' },
573
+ { min: 41, max: 60, label: '60%', color: '#ffb247' },
574
+ { min: 61, max: 80, label: '80%', color: '#ff0b1f' },
575
+ { min: 81, max: 100, label: '100%', color: '#a51d29' },
576
+ ],
577
+ },
578
+
579
+ series: {
580
+ itemStyle: {
581
+ borderWidth: 0,
582
+ },
583
+ },
584
+ };
585
+ ```
586
+
587
+ ## Heatmap Config Options
588
+
589
+ | Option | Type | Description |
590
+ | ---------------- | -------------------------- | ----------------------------------------------------------------------- |
591
+ | xAxisData | string[] | Labels for the x-axis |
592
+ | yAxisData | string[] | Labels for the y-axis |
593
+ | data | [number, number, number][] | Heatmap cells as `[xIndex, yIndex, value]` |
594
+ | min | number | Minimum value for color mapping |
595
+ | max | number | Maximum value for color mapping |
596
+ | colors | string[] | Continuous color range when `visualMap.pieces` is not used |
597
+ | visualMap | any | ECharts visual map config. `pieces` also drives the custom legend pills |
598
+ | grid | object | ECharts grid config |
599
+ | xAxis | any | Extra ECharts x-axis config |
600
+ | yAxis | any | Extra ECharts y-axis config |
601
+ | showTooltip | boolean | Enables or disables tooltip |
602
+ | tooltipFormatter | function | Custom tooltip formatter |
603
+ | showLabel | boolean | Shows value labels inside cells |
604
+ | labelFormatter | string \| function | Cell label formatter |
605
+ | series | any \| any[] | Extra ECharts heatmap series config |
606
+
607
+ ---
608
+
609
+ # 🎨 Themes
610
+
611
+ Available chart themes:
612
+
613
+ - default
614
+ - dark
615
+ - vintage
616
+ - essos
617
+ - chalk
618
+ - roma
619
+
620
+ ---
621
+
622
+ # 📚 Documentation
623
+
624
+ Apache ECharts documentation:
625
+
626
+ https://echarts.apache.org/en/api.html#echarts
627
+
628
+ ---
629
+
630
+ # 🤝 Contributing
631
+
632
+ Contributions, issues, and feature requests are welcome.
633
+ Feel free to submit a pull request.
634
+
635
+ ---
636
+
637
+ # 📄 License
638
+
639
+ MIT License
640
+
641
+ ---
642
+
643
+ # Status Timeline
644
+
645
+ `StatusTimelineComponent` renders generic categorical intervals in chronological order. Segment
646
+ widths are proportional to duration, and dense datasets scroll horizontally without aggregation.
647
+
648
+ ## Import and usage
649
+
650
+ ```ts
651
+ import { StatusTimelineComponent, type StatusTimelineConfig } from 'cats-charts';
652
+
653
+ @Component({
654
+ standalone: true,
655
+ imports: [StatusTimelineComponent],
656
+ template: `
657
+ <lib-status-timeline
658
+ [config]="timelineConfig"
659
+ (chartEvent)="onTimelineEvent($event)"
660
+ />
661
+ `,
662
+ })
663
+ export class ExampleComponent {
664
+ timelineConfig: StatusTimelineConfig = {
665
+ startLabel: 'Monday',
666
+ endLabel: 'Today',
667
+ statuses: [
668
+ { value: 'ready', label: 'Ready', color: '#2f8f3a' },
669
+ { value: 'deploying', label: 'Deploying', color: '#d0a020' },
670
+ { value: 'blocked', label: 'Blocked', color: '#a43b35' },
671
+ ],
672
+ data: [
673
+ { start: '2026-08-24T00:00:00Z', end: '2026-08-25T00:00:00Z', status: 'ready' },
674
+ {
675
+ start: '2026-08-25T00:00:00Z',
676
+ end: '2026-08-25T06:00:00Z',
677
+ status: 'deploying',
678
+ label: 'Release deployment',
679
+ },
680
+ { start: '2026-08-25T06:00:00Z', end: '2026-08-26T00:00:00Z', status: 'ready' },
681
+ ],
682
+ };
683
+ }
684
+ ```
685
+
686
+ ## Configuration
687
+
688
+ | Option | Description |
689
+ | --- | --- |
690
+ | `data` | Dynamic intervals with `start`, `end`, `status`, and optional `label`/`metadata` |
691
+ | `statuses` | Text and optional color for each status value |
692
+ | `showLegend`, `showTooltip` | Toggle supporting UI (both default to `true`) |
693
+ | `legendPosition` | Places the legend at `top`, `bottom`, `left`, or `right` |
694
+ | `legendLayout` | Arranges legend items `horizontal` or `vertical` |
695
+ | `legendAlign` | Aligns the legend at `start`/`left`, `center`, `end`/`right`, or `space-between` |
696
+ | `legendLabelAlign` | Aligns text within vertical legend items to `left`, `center`, or `right` |
697
+ | `legendInteractive` | Enables clicking legend labels to dim/restore matching intervals; defaults to `true` |
698
+ | `legendDimmedOpacity` | Opacity used for inactive legend items and intervals; defaults to `0.3` |
699
+ | `legendScrollable` | Enables bounded legend overflow scrolling; defaults to `true` |
700
+ | `legendMaxWidth`, `legendMaxHeight` | Optional scroll viewport limits |
701
+ | `legendNote` | Optional explanatory text displayed beside the legend |
702
+ | `startLabel`, `endLabel` | Endpoint text; dates are derived when omitted |
703
+ | `showEndpointLabels` | Shows or hides the endpoint-label row; defaults to `true` |
704
+ | `endpointLabelsAlign` | Aligns endpoint labels at `start`/`left`, `center`, `end`/`right`, or `space-between` |
705
+ | `loading`, `loadingLabel`, `emptyLabel`, `error` | Timeline state presentation |
706
+ | `minSegmentWidth`, `segmentGap` | Dense-data and spacing controls in pixels |
707
+ | `dateFormatter`, `durationFormatter`, `tooltipFormatter` | Display customization hooks |
708
+ | `unknownStatus` | Fallback label/color for unconfigured status values |
709
+ | `ariaLabel` | Accessible name for the timeline |
710
+
711
+ The component emits `chartEvent` with `{ type: 'itemClick', item, index }`. Its appearance can be
712
+ themed with the `--status-timeline-*` CSS custom properties defined in the component stylesheet.