@ojiepermana/angular-chart 22.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +249 -0
  2. package/fesm2022/ojiepermana-angular-chart-area.mjs +266 -0
  3. package/fesm2022/ojiepermana-angular-chart-area.mjs.map +1 -0
  4. package/fesm2022/ojiepermana-angular-chart-bar.mjs +674 -0
  5. package/fesm2022/ojiepermana-angular-chart-bar.mjs.map +1 -0
  6. package/fesm2022/ojiepermana-angular-chart-core.mjs +764 -0
  7. package/fesm2022/ojiepermana-angular-chart-core.mjs.map +1 -0
  8. package/fesm2022/ojiepermana-angular-chart-line.mjs +281 -0
  9. package/fesm2022/ojiepermana-angular-chart-line.mjs.map +1 -0
  10. package/fesm2022/ojiepermana-angular-chart-pie.mjs +248 -0
  11. package/fesm2022/ojiepermana-angular-chart-pie.mjs.map +1 -0
  12. package/fesm2022/ojiepermana-angular-chart-primitives.mjs +1186 -0
  13. package/fesm2022/ojiepermana-angular-chart-primitives.mjs.map +1 -0
  14. package/fesm2022/ojiepermana-angular-chart-radar.mjs +329 -0
  15. package/fesm2022/ojiepermana-angular-chart-radar.mjs.map +1 -0
  16. package/fesm2022/ojiepermana-angular-chart-radial.mjs +255 -0
  17. package/fesm2022/ojiepermana-angular-chart-radial.mjs.map +1 -0
  18. package/fesm2022/ojiepermana-angular-chart-scatter.mjs +253 -0
  19. package/fesm2022/ojiepermana-angular-chart-scatter.mjs.map +1 -0
  20. package/fesm2022/ojiepermana-angular-chart.mjs +20 -0
  21. package/fesm2022/ojiepermana-angular-chart.mjs.map +1 -0
  22. package/package.json +76 -0
  23. package/types/ojiepermana-angular-chart-area.d.ts +58 -0
  24. package/types/ojiepermana-angular-chart-bar.d.ts +171 -0
  25. package/types/ojiepermana-angular-chart-core.d.ts +369 -0
  26. package/types/ojiepermana-angular-chart-line.d.ts +57 -0
  27. package/types/ojiepermana-angular-chart-pie.d.ts +93 -0
  28. package/types/ojiepermana-angular-chart-primitives.d.ts +265 -0
  29. package/types/ojiepermana-angular-chart-radar.d.ts +89 -0
  30. package/types/ojiepermana-angular-chart-radial.d.ts +86 -0
  31. package/types/ojiepermana-angular-chart-scatter.d.ts +95 -0
  32. package/types/ojiepermana-angular-chart.d.ts +2 -0
@@ -0,0 +1,255 @@
1
+ import { arc } from 'd3-shape';
2
+ import { max } from 'd3-array';
3
+ import { seriesColorVar, ChartContext } from '@ojiepermana/angular-chart/core';
4
+ import * as i0 from '@angular/core';
5
+ import { inject, input, output, computed, ChangeDetectionStrategy, Component } from '@angular/core';
6
+
7
+ function computeRadialLayout(input) {
8
+ const { data, nameKey, valueKey, innerWidth, innerHeight, seriesKeys, trackPadding, startAngle, endAngle, cornerRadius, } = input;
9
+ const outerRadius = Math.max(0, Math.min(innerWidth, innerHeight) / 2);
10
+ const centerX = innerWidth / 2;
11
+ const centerY = innerHeight / 2;
12
+ if (data.length === 0 || outerRadius === 0) {
13
+ return { centerX, centerY, outerRadius, bars: [], maxValue: 0 };
14
+ }
15
+ const maxValue = input.maxValue ?? max(data, (d) => Number(d[valueKey] ?? 0)) ?? 1;
16
+ const trackCount = data.length;
17
+ const safeTrackPadding = trackCount > 1 ? Math.min(Math.max(trackPadding, 0), outerRadius / (trackCount - 1)) : Math.max(trackPadding, 0);
18
+ const availableRadius = Math.max(0, outerRadius - (trackCount - 1) * safeTrackPadding);
19
+ const trackThickness = availableRadius / trackCount;
20
+ const bars = data.map((d, i) => {
21
+ const inner = i * (trackThickness + safeTrackPadding);
22
+ const outer = inner + trackThickness;
23
+ const value = Number(d[valueKey] ?? 0);
24
+ const pct = maxValue === 0 ? 0 : value / maxValue;
25
+ const sweep = (endAngle - startAngle) * pct;
26
+ const valueEndAngle = startAngle + sweep;
27
+ const key = seriesKeys?.[i] ?? String(d[nameKey] ?? i);
28
+ const arcGen = arc().innerRadius(inner).outerRadius(outer).cornerRadius(cornerRadius);
29
+ return {
30
+ seriesKey: key,
31
+ name: String(d[nameKey] ?? key),
32
+ value,
33
+ datumIndex: i,
34
+ color: seriesColorVar(key),
35
+ arcPath: arcGen.startAngle(startAngle).endAngle(valueEndAngle)(null) ?? '',
36
+ backgroundPath: arcGen.startAngle(startAngle).endAngle(endAngle)(null) ?? '',
37
+ innerRadius: inner,
38
+ outerRadius: outer,
39
+ endAngle: valueEndAngle,
40
+ };
41
+ });
42
+ return { centerX, centerY, outerRadius, bars, maxValue };
43
+ }
44
+
45
+ const DEFAULT_MARGIN = { top: 8, right: 8, bottom: 8, left: 8 };
46
+ const defaultRadialValueFormatter = (value) => `${value}`;
47
+ class RadialChart {
48
+ root = inject(ChartContext);
49
+ data = input.required(/* @ts-ignore */
50
+ ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
51
+ nameKey = input.required(/* @ts-ignore */
52
+ ...(ngDevMode ? [{ debugName: "nameKey" }] : /* istanbul ignore next */ []));
53
+ valueKey = input.required(/* @ts-ignore */
54
+ ...(ngDevMode ? [{ debugName: "valueKey" }] : /* istanbul ignore next */ []));
55
+ seriesKeys = input(undefined, /* @ts-ignore */
56
+ ...(ngDevMode ? [{ debugName: "seriesKeys" }] : /* istanbul ignore next */ []));
57
+ styles = input('base', /* @ts-ignore */
58
+ ...(ngDevMode ? [{ debugName: "styles" }] : /* istanbul ignore next */ []));
59
+ margin = input(DEFAULT_MARGIN, /* @ts-ignore */
60
+ ...(ngDevMode ? [{ debugName: "margin" }] : /* istanbul ignore next */ []));
61
+ trackPadding = input(4, /* @ts-ignore */
62
+ ...(ngDevMode ? [{ debugName: "trackPadding" }] : /* istanbul ignore next */ []));
63
+ cornerRadius = input(8, /* @ts-ignore */
64
+ ...(ngDevMode ? [{ debugName: "cornerRadius" }] : /* istanbul ignore next */ []));
65
+ startAngle = input(-Math.PI / 2, /* @ts-ignore */
66
+ ...(ngDevMode ? [{ debugName: "startAngle" }] : /* istanbul ignore next */ []));
67
+ endAngle = input((3 * Math.PI) / 2, /* @ts-ignore */
68
+ ...(ngDevMode ? [{ debugName: "endAngle" }] : /* istanbul ignore next */ []));
69
+ maxValue = input(undefined, /* @ts-ignore */
70
+ ...(ngDevMode ? [{ debugName: "maxValue" }] : /* istanbul ignore next */ []));
71
+ showTrack = input(true, /* @ts-ignore */
72
+ ...(ngDevMode ? [{ debugName: "showTrack" }] : /* istanbul ignore next */ []));
73
+ showValueLabels = input(false, /* @ts-ignore */
74
+ ...(ngDevMode ? [{ debugName: "showValueLabels" }] : /* istanbul ignore next */ []));
75
+ valueLabelFormat = input(defaultRadialValueFormatter, /* @ts-ignore */
76
+ ...(ngDevMode ? [{ debugName: "valueLabelFormat" }] : /* istanbul ignore next */ []));
77
+ barClick = output();
78
+ innerWidth = computed(() => Math.max(0, this.root.dimensions().width - this.margin().left - this.margin().right), /* @ts-ignore */
79
+ ...(ngDevMode ? [{ debugName: "innerWidth" }] : /* istanbul ignore next */ []));
80
+ innerHeight = computed(() => Math.max(0, this.root.dimensions().height - this.margin().top - this.margin().bottom), /* @ts-ignore */
81
+ ...(ngDevMode ? [{ debugName: "innerHeight" }] : /* istanbul ignore next */ []));
82
+ layout = computed(() => computeRadialLayout({
83
+ data: this.data(),
84
+ nameKey: this.nameKey(),
85
+ valueKey: this.valueKey(),
86
+ seriesKeys: this.seriesKeys(),
87
+ innerWidth: this.innerWidth(),
88
+ innerHeight: this.innerHeight(),
89
+ trackPadding: this.trackPadding(),
90
+ startAngle: this.startAngle(),
91
+ endAngle: this.endAngle(),
92
+ cornerRadius: this.cornerRadius(),
93
+ maxValue: this.maxValue(),
94
+ }), /* @ts-ignore */
95
+ ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
96
+ viewBox = computed(() => {
97
+ const { width, height } = this.root.dimensions();
98
+ return `0 0 ${Math.max(0, width)} ${Math.max(0, height)}`;
99
+ }, /* @ts-ignore */
100
+ ...(ngDevMode ? [{ debugName: "viewBox" }] : /* istanbul ignore next */ []));
101
+ innerTransform = computed(() => `translate(${this.margin().left},${this.margin().top})`, /* @ts-ignore */
102
+ ...(ngDevMode ? [{ debugName: "innerTransform" }] : /* istanbul ignore next */ []));
103
+ ariaSummary = computed(() => `Radial bar chart, ${this.data().length} tracks.`, /* @ts-ignore */
104
+ ...(ngDevMode ? [{ debugName: "ariaSummary" }] : /* istanbul ignore next */ []));
105
+ barAriaLabel(b) {
106
+ return `${b.name}: ${b.value}`;
107
+ }
108
+ formatValueLabel(b) {
109
+ return this.valueLabelFormat()(b.value, b.name);
110
+ }
111
+ barLabelX(b) {
112
+ const radius = (b.innerRadius + b.outerRadius) / 2 + 10;
113
+ return Math.sin(b.endAngle) * radius;
114
+ }
115
+ barLabelY(b) {
116
+ const radius = (b.innerRadius + b.outerRadius) / 2 + 10;
117
+ return -Math.cos(b.endAngle) * radius;
118
+ }
119
+ barLabelAnchor(b) {
120
+ return this.barLabelX(b) >= 0 ? 'start' : 'end';
121
+ }
122
+ emitClick(b) {
123
+ this.barClick.emit({
124
+ seriesKey: b.seriesKey,
125
+ name: b.name,
126
+ value: b.value,
127
+ datumIndex: b.datumIndex,
128
+ datum: this.data()[b.datumIndex],
129
+ });
130
+ }
131
+ setActive(event, b) {
132
+ const clientX = event instanceof PointerEvent ? event.clientX : event.target.getBoundingClientRect().left;
133
+ const clientY = event instanceof PointerEvent ? event.clientY : event.target.getBoundingClientRect().top;
134
+ this.root.activePoint.set({
135
+ index: b.datumIndex,
136
+ datumIndex: b.datumIndex,
137
+ seriesKey: b.seriesKey,
138
+ clientX,
139
+ clientY,
140
+ });
141
+ }
142
+ clearActive() {
143
+ this.root.activePoint.set(null);
144
+ }
145
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RadialChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
146
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: RadialChart, isStandalone: true, selector: "ChartRadial", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, nameKey: { classPropertyName: "nameKey", publicName: "nameKey", isSignal: true, isRequired: true, transformFunction: null }, valueKey: { classPropertyName: "valueKey", publicName: "valueKey", isSignal: true, isRequired: true, transformFunction: null }, seriesKeys: { classPropertyName: "seriesKeys", publicName: "seriesKeys", isSignal: true, isRequired: false, transformFunction: null }, styles: { classPropertyName: "styles", publicName: "styles", isSignal: true, isRequired: false, transformFunction: null }, margin: { classPropertyName: "margin", publicName: "margin", isSignal: true, isRequired: false, transformFunction: null }, trackPadding: { classPropertyName: "trackPadding", publicName: "trackPadding", isSignal: true, isRequired: false, transformFunction: null }, cornerRadius: { classPropertyName: "cornerRadius", publicName: "cornerRadius", isSignal: true, isRequired: false, transformFunction: null }, startAngle: { classPropertyName: "startAngle", publicName: "startAngle", isSignal: true, isRequired: false, transformFunction: null }, endAngle: { classPropertyName: "endAngle", publicName: "endAngle", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, showTrack: { classPropertyName: "showTrack", publicName: "showTrack", isSignal: true, isRequired: false, transformFunction: null }, showValueLabels: { classPropertyName: "showValueLabels", publicName: "showValueLabels", isSignal: true, isRequired: false, transformFunction: null }, valueLabelFormat: { classPropertyName: "valueLabelFormat", publicName: "valueLabelFormat", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { barClick: "barClick" }, host: { properties: { "attr.data-style": "styles()" }, classAttribute: "relative block h-full w-full" }, ngImport: i0, template: `
147
+ <svg:svg
148
+ class="block h-full w-full overflow-visible"
149
+ [attr.viewBox]="viewBox()"
150
+ preserveAspectRatio="xMidYMid meet"
151
+ role="img"
152
+ [attr.aria-label]="ariaSummary()">
153
+ <svg:g [attr.transform]="innerTransform()">
154
+ <svg:g [attr.transform]="'translate(' + layout().centerX + ',' + layout().centerY + ')'">
155
+ @for (b of layout().bars; track b.seriesKey) {
156
+ @if (showTrack()) {
157
+ <svg:path class="chart-radial-track fill-muted" [attr.d]="b.backgroundPath" />
158
+ }
159
+ <svg:path
160
+ class="chart-radial-bar cursor-pointer transition-opacity hover:opacity-80"
161
+ [attr.d]="b.arcPath"
162
+ [attr.fill]="b.color"
163
+ [attr.aria-label]="barAriaLabel(b)"
164
+ tabindex="0"
165
+ (click)="emitClick(b)"
166
+ (keydown.enter)="emitClick(b)"
167
+ (keydown.space)="emitClick(b); $event.preventDefault()"
168
+ (pointerenter)="setActive($event, b)"
169
+ (pointermove)="setActive($event, b)"
170
+ (pointerleave)="clearActive()"
171
+ (focus)="setActive($event, b)"
172
+ (blur)="clearActive()" />
173
+ @if (showValueLabels()) {
174
+ <svg:text
175
+ class="chart-radial-value pointer-events-none fill-muted-foreground text-2xs"
176
+ [attr.x]="barLabelX(b)"
177
+ [attr.y]="barLabelY(b)"
178
+ [attr.text-anchor]="barLabelAnchor(b)"
179
+ dominant-baseline="middle">
180
+ {{ formatValueLabel(b) }}
181
+ </svg:text>
182
+ }
183
+ }
184
+ </svg:g>
185
+ </svg:g>
186
+ </svg:svg>
187
+ <div class="pointer-events-none absolute inset-0 flex items-center justify-center">
188
+ <ng-content select="ChartRadialCenter" />
189
+ </div>
190
+ <ng-content select="ChartTooltip" />
191
+ <ng-content select="ChartLegend" />
192
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
193
+ }
194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RadialChart, decorators: [{
195
+ type: Component,
196
+ args: [{
197
+ selector: 'ChartRadial',
198
+ changeDetection: ChangeDetectionStrategy.OnPush,
199
+ host: { class: 'relative block h-full w-full', '[attr.data-style]': 'styles()' },
200
+ template: `
201
+ <svg:svg
202
+ class="block h-full w-full overflow-visible"
203
+ [attr.viewBox]="viewBox()"
204
+ preserveAspectRatio="xMidYMid meet"
205
+ role="img"
206
+ [attr.aria-label]="ariaSummary()">
207
+ <svg:g [attr.transform]="innerTransform()">
208
+ <svg:g [attr.transform]="'translate(' + layout().centerX + ',' + layout().centerY + ')'">
209
+ @for (b of layout().bars; track b.seriesKey) {
210
+ @if (showTrack()) {
211
+ <svg:path class="chart-radial-track fill-muted" [attr.d]="b.backgroundPath" />
212
+ }
213
+ <svg:path
214
+ class="chart-radial-bar cursor-pointer transition-opacity hover:opacity-80"
215
+ [attr.d]="b.arcPath"
216
+ [attr.fill]="b.color"
217
+ [attr.aria-label]="barAriaLabel(b)"
218
+ tabindex="0"
219
+ (click)="emitClick(b)"
220
+ (keydown.enter)="emitClick(b)"
221
+ (keydown.space)="emitClick(b); $event.preventDefault()"
222
+ (pointerenter)="setActive($event, b)"
223
+ (pointermove)="setActive($event, b)"
224
+ (pointerleave)="clearActive()"
225
+ (focus)="setActive($event, b)"
226
+ (blur)="clearActive()" />
227
+ @if (showValueLabels()) {
228
+ <svg:text
229
+ class="chart-radial-value pointer-events-none fill-muted-foreground text-2xs"
230
+ [attr.x]="barLabelX(b)"
231
+ [attr.y]="barLabelY(b)"
232
+ [attr.text-anchor]="barLabelAnchor(b)"
233
+ dominant-baseline="middle">
234
+ {{ formatValueLabel(b) }}
235
+ </svg:text>
236
+ }
237
+ }
238
+ </svg:g>
239
+ </svg:g>
240
+ </svg:svg>
241
+ <div class="pointer-events-none absolute inset-0 flex items-center justify-center">
242
+ <ng-content select="ChartRadialCenter" />
243
+ </div>
244
+ <ng-content select="ChartTooltip" />
245
+ <ng-content select="ChartLegend" />
246
+ `,
247
+ }]
248
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], nameKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "nameKey", required: true }] }], valueKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueKey", required: true }] }], seriesKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "seriesKeys", required: false }] }], styles: [{ type: i0.Input, args: [{ isSignal: true, alias: "styles", required: false }] }], margin: [{ type: i0.Input, args: [{ isSignal: true, alias: "margin", required: false }] }], trackPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackPadding", required: false }] }], cornerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "cornerRadius", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }], endAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "endAngle", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], showTrack: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTrack", required: false }] }], showValueLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValueLabels", required: false }] }], valueLabelFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueLabelFormat", required: false }] }], barClick: [{ type: i0.Output, args: ["barClick"] }] } });
249
+
250
+ /**
251
+ * Generated bundle index. Do not edit.
252
+ */
253
+
254
+ export { RadialChart, computeRadialLayout };
255
+ //# sourceMappingURL=ojiepermana-angular-chart-radial.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ojiepermana-angular-chart-radial.mjs","sources":["../../../library/chart/radial/radial-layout.ts","../../../library/chart/radial/radial-chart.ts","../../../library/chart/radial/ojiepermana-angular-chart-radial.ts"],"sourcesContent":["import { arc as d3arc } from 'd3-shape';\nimport { max as d3max } from 'd3-array';\nimport type { ChartDatum } from '@ojiepermana/angular-chart/core';\nimport { seriesColorVar } from '@ojiepermana/angular-chart/core';\n\nexport interface RadialLayoutInput {\n readonly data: readonly ChartDatum[];\n readonly nameKey: string;\n readonly valueKey: string;\n readonly innerWidth: number;\n readonly innerHeight: number;\n /** Optional explicit series-key list (same length as data). */\n readonly seriesKeys?: readonly string[];\n /** Gap between concentric tracks (px). */\n readonly trackPadding: number;\n /** Start / end angle (radians). */\n readonly startAngle: number;\n readonly endAngle: number;\n readonly cornerRadius: number;\n readonly maxValue?: number;\n}\n\nexport interface RadialBarRect {\n readonly seriesKey: string;\n readonly name: string;\n readonly value: number;\n readonly datumIndex: number;\n readonly color: string;\n readonly arcPath: string;\n readonly backgroundPath: string;\n readonly innerRadius: number;\n readonly outerRadius: number;\n readonly endAngle: number;\n}\n\nexport interface RadialLayout {\n readonly centerX: number;\n readonly centerY: number;\n readonly outerRadius: number;\n readonly bars: readonly RadialBarRect[];\n readonly maxValue: number;\n}\n\nexport function computeRadialLayout(input: RadialLayoutInput): RadialLayout {\n const {\n data,\n nameKey,\n valueKey,\n innerWidth,\n innerHeight,\n seriesKeys,\n trackPadding,\n startAngle,\n endAngle,\n cornerRadius,\n } = input;\n\n const outerRadius = Math.max(0, Math.min(innerWidth, innerHeight) / 2);\n const centerX = innerWidth / 2;\n const centerY = innerHeight / 2;\n\n if (data.length === 0 || outerRadius === 0) {\n return { centerX, centerY, outerRadius, bars: [], maxValue: 0 };\n }\n\n const maxValue = input.maxValue ?? d3max(data, (d) => Number(d[valueKey] ?? 0)) ?? 1;\n const trackCount = data.length;\n const safeTrackPadding =\n trackCount > 1 ? Math.min(Math.max(trackPadding, 0), outerRadius / (trackCount - 1)) : Math.max(trackPadding, 0);\n const availableRadius = Math.max(0, outerRadius - (trackCount - 1) * safeTrackPadding);\n const trackThickness = availableRadius / trackCount;\n\n const bars: RadialBarRect[] = data.map((d, i) => {\n const inner = i * (trackThickness + safeTrackPadding);\n const outer = inner + trackThickness;\n const value = Number(d[valueKey] ?? 0);\n const pct = maxValue === 0 ? 0 : value / maxValue;\n const sweep = (endAngle - startAngle) * pct;\n const valueEndAngle = startAngle + sweep;\n const key = seriesKeys?.[i] ?? String(d[nameKey] ?? i);\n\n const arcGen = d3arc<unknown>().innerRadius(inner).outerRadius(outer).cornerRadius(cornerRadius);\n\n return {\n seriesKey: key,\n name: String(d[nameKey] ?? key),\n value,\n datumIndex: i,\n color: seriesColorVar(key),\n arcPath: arcGen.startAngle(startAngle).endAngle(valueEndAngle)(null) ?? '',\n backgroundPath: arcGen.startAngle(startAngle).endAngle(endAngle)(null) ?? '',\n innerRadius: inner,\n outerRadius: outer,\n endAngle: valueEndAngle,\n };\n });\n\n return { centerX, centerY, outerRadius, bars, maxValue };\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';\nimport { ChartContext } from '@ojiepermana/angular-chart/core';\nimport type { ChartDatum, ChartMargin, ChartStyleVariant } from '@ojiepermana/angular-chart/core';\nimport { computeRadialLayout, type RadialBarRect } from './radial-layout';\n\nconst DEFAULT_MARGIN: ChartMargin = { top: 8, right: 8, bottom: 8, left: 8 };\nconst defaultRadialValueFormatter = (value: number): string => `${value}`;\n\nexport type RadialValueLabelFormatter = (value: number, name: string) => string;\n\nexport interface RadialBarClickEvent {\n readonly seriesKey: string;\n readonly name: string;\n readonly value: number;\n readonly datumIndex: number;\n readonly datum: ChartDatum;\n}\n\n@Component({\n selector: 'ChartRadial',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'relative block h-full w-full', '[attr.data-style]': 'styles()' },\n template: `\n <svg:svg\n class=\"block h-full w-full overflow-visible\"\n [attr.viewBox]=\"viewBox()\"\n preserveAspectRatio=\"xMidYMid meet\"\n role=\"img\"\n [attr.aria-label]=\"ariaSummary()\">\n <svg:g [attr.transform]=\"innerTransform()\">\n <svg:g [attr.transform]=\"'translate(' + layout().centerX + ',' + layout().centerY + ')'\">\n @for (b of layout().bars; track b.seriesKey) {\n @if (showTrack()) {\n <svg:path class=\"chart-radial-track fill-muted\" [attr.d]=\"b.backgroundPath\" />\n }\n <svg:path\n class=\"chart-radial-bar cursor-pointer transition-opacity hover:opacity-80\"\n [attr.d]=\"b.arcPath\"\n [attr.fill]=\"b.color\"\n [attr.aria-label]=\"barAriaLabel(b)\"\n tabindex=\"0\"\n (click)=\"emitClick(b)\"\n (keydown.enter)=\"emitClick(b)\"\n (keydown.space)=\"emitClick(b); $event.preventDefault()\"\n (pointerenter)=\"setActive($event, b)\"\n (pointermove)=\"setActive($event, b)\"\n (pointerleave)=\"clearActive()\"\n (focus)=\"setActive($event, b)\"\n (blur)=\"clearActive()\" />\n @if (showValueLabels()) {\n <svg:text\n class=\"chart-radial-value pointer-events-none fill-muted-foreground text-2xs\"\n [attr.x]=\"barLabelX(b)\"\n [attr.y]=\"barLabelY(b)\"\n [attr.text-anchor]=\"barLabelAnchor(b)\"\n dominant-baseline=\"middle\">\n {{ formatValueLabel(b) }}\n </svg:text>\n }\n }\n </svg:g>\n </svg:g>\n </svg:svg>\n <div class=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <ng-content select=\"ChartRadialCenter\" />\n </div>\n <ng-content select=\"ChartTooltip\" />\n <ng-content select=\"ChartLegend\" />\n `,\n})\nexport class RadialChart {\n private readonly root = inject(ChartContext);\n\n readonly data = input.required<readonly ChartDatum[]>();\n readonly nameKey = input.required<string>();\n readonly valueKey = input.required<string>();\n readonly seriesKeys = input<readonly string[] | undefined>(undefined);\n readonly styles = input<ChartStyleVariant>('base');\n readonly margin = input<ChartMargin>(DEFAULT_MARGIN);\n readonly trackPadding = input<number>(4);\n readonly cornerRadius = input<number>(8);\n readonly startAngle = input<number>(-Math.PI / 2);\n readonly endAngle = input<number>((3 * Math.PI) / 2);\n readonly maxValue = input<number | undefined>(undefined);\n readonly showTrack = input<boolean>(true);\n readonly showValueLabels = input<boolean>(false);\n readonly valueLabelFormat = input<RadialValueLabelFormatter>(defaultRadialValueFormatter);\n\n readonly barClick = output<RadialBarClickEvent>();\n\n protected readonly innerWidth = computed(() =>\n Math.max(0, this.root.dimensions().width - this.margin().left - this.margin().right),\n );\n protected readonly innerHeight = computed(() =>\n Math.max(0, this.root.dimensions().height - this.margin().top - this.margin().bottom),\n );\n\n protected readonly layout = computed(() =>\n computeRadialLayout({\n data: this.data(),\n nameKey: this.nameKey(),\n valueKey: this.valueKey(),\n seriesKeys: this.seriesKeys(),\n innerWidth: this.innerWidth(),\n innerHeight: this.innerHeight(),\n trackPadding: this.trackPadding(),\n startAngle: this.startAngle(),\n endAngle: this.endAngle(),\n cornerRadius: this.cornerRadius(),\n maxValue: this.maxValue(),\n }),\n );\n\n protected readonly viewBox = computed(() => {\n const { width, height } = this.root.dimensions();\n return `0 0 ${Math.max(0, width)} ${Math.max(0, height)}`;\n });\n\n protected readonly innerTransform = computed(() => `translate(${this.margin().left},${this.margin().top})`);\n protected readonly ariaSummary = computed(() => `Radial bar chart, ${this.data().length} tracks.`);\n\n protected barAriaLabel(b: RadialBarRect): string {\n return `${b.name}: ${b.value}`;\n }\n\n protected formatValueLabel(b: RadialBarRect): string {\n return this.valueLabelFormat()(b.value, b.name);\n }\n\n protected barLabelX(b: RadialBarRect): number {\n const radius = (b.innerRadius + b.outerRadius) / 2 + 10;\n return Math.sin(b.endAngle) * radius;\n }\n\n protected barLabelY(b: RadialBarRect): number {\n const radius = (b.innerRadius + b.outerRadius) / 2 + 10;\n return -Math.cos(b.endAngle) * radius;\n }\n\n protected barLabelAnchor(b: RadialBarRect): 'start' | 'end' {\n return this.barLabelX(b) >= 0 ? 'start' : 'end';\n }\n\n protected emitClick(b: RadialBarRect): void {\n this.barClick.emit({\n seriesKey: b.seriesKey,\n name: b.name,\n value: b.value,\n datumIndex: b.datumIndex,\n datum: this.data()[b.datumIndex],\n });\n }\n\n protected setActive(event: PointerEvent | FocusEvent, b: RadialBarRect): void {\n const clientX =\n event instanceof PointerEvent ? event.clientX : (event.target as Element).getBoundingClientRect().left;\n const clientY =\n event instanceof PointerEvent ? event.clientY : (event.target as Element).getBoundingClientRect().top;\n this.root.activePoint.set({\n index: b.datumIndex,\n datumIndex: b.datumIndex,\n seriesKey: b.seriesKey,\n clientX,\n clientY,\n });\n }\n\n protected clearActive(): void {\n this.root.activePoint.set(null);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["d3max","d3arc"],"mappings":"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"}
@@ -0,0 +1,253 @@
1
+ import { scaleLinear } from 'd3-scale';
2
+ import { extent } from 'd3-array';
3
+ import { seriesColorVar, ChartContext, ScatterViewportContext } from '@ojiepermana/angular-chart/core';
4
+ import * as i0 from '@angular/core';
5
+ import { inject, input, output, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
6
+
7
+ function nice(extent) {
8
+ const [lo, hi] = extent;
9
+ if (lo === undefined || hi === undefined)
10
+ return [0, 1];
11
+ if (lo === hi)
12
+ return [lo - 1, hi + 1];
13
+ return [lo, hi];
14
+ }
15
+ function resolveScatterDomains(input) {
16
+ const xValues = input.data.map((d) => Number(d[input.xKey] ?? 0));
17
+ const yValues = input.data.map((d) => Number(d[input.yKey] ?? 0));
18
+ return {
19
+ xDomain: (input.xDomain ?? nice(extent(xValues))),
20
+ yDomain: (input.yDomain ?? nice(extent(yValues))),
21
+ };
22
+ }
23
+ function computeScatterLayout(input) {
24
+ const { data, xKey, yKey, sizeKey, seriesKey, seriesKeys, innerWidth, innerHeight, minPointRadius, maxPointRadius } = input;
25
+ const xValues = data.map((d) => Number(d[xKey] ?? 0));
26
+ const yValues = data.map((d) => Number(d[yKey] ?? 0));
27
+ const sizeValues = sizeKey ? data.map((d) => Number(d[sizeKey] ?? 0)) : [];
28
+ const { xDomain, yDomain } = resolveScatterDomains(input);
29
+ const xScale = scaleLinear()
30
+ .domain(xDomain)
31
+ .range([0, innerWidth]);
32
+ const yScale = scaleLinear()
33
+ .domain(yDomain)
34
+ .range([innerHeight, 0]);
35
+ let sizeScale = null;
36
+ if (sizeKey && sizeValues.length > 0) {
37
+ const [sLo, sHi] = extent(sizeValues);
38
+ sizeScale = scaleLinear()
39
+ .domain([sLo ?? 0, sHi ?? 1])
40
+ .range([minPointRadius, maxPointRadius]);
41
+ }
42
+ const fallbackKey = seriesKeys[0] ?? 'value';
43
+ const points = data.flatMap((d, i) => {
44
+ const key = seriesKey ? String(d[seriesKey] ?? fallbackKey) : fallbackKey;
45
+ const sz = sizeKey ? Number(d[sizeKey] ?? 0) : 0;
46
+ const rawX = xValues[i];
47
+ const rawY = yValues[i];
48
+ if (rawX < xDomain[0] || rawX > xDomain[1] || rawY < yDomain[0] || rawY > yDomain[1]) {
49
+ return [];
50
+ }
51
+ return [
52
+ {
53
+ seriesKey: key,
54
+ color: seriesColorVar(key),
55
+ x: xScale(rawX),
56
+ y: yScale(rawY),
57
+ radius: sizeScale ? sizeScale(sz) : minPointRadius,
58
+ datumIndex: i,
59
+ rawX,
60
+ rawY,
61
+ rawSize: sz,
62
+ },
63
+ ];
64
+ });
65
+ return { points, xScale, yScale, xDomain, yDomain };
66
+ }
67
+
68
+ const DEFAULT_MARGIN = { top: 8, right: 8, bottom: 24, left: 40 };
69
+ /**
70
+ * Scatter chart — one dot per datum. Both axes are linear; color can
71
+ * come from a fixed series key or per-row via `seriesKey` field. Point
72
+ * radius optionally scales with `sizeKey`.
73
+ */
74
+ class ScatterChart {
75
+ root = inject(ChartContext);
76
+ viewport = inject(ScatterViewportContext);
77
+ data = input.required(/* @ts-ignore */
78
+ ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
79
+ xKey = input.required(/* @ts-ignore */
80
+ ...(ngDevMode ? [{ debugName: "xKey" }] : /* istanbul ignore next */ []));
81
+ yKey = input.required(/* @ts-ignore */
82
+ ...(ngDevMode ? [{ debugName: "yKey" }] : /* istanbul ignore next */ []));
83
+ /** Optional numeric field to drive point radius. */
84
+ sizeKey = input(undefined, /* @ts-ignore */
85
+ ...(ngDevMode ? [{ debugName: "sizeKey" }] : /* istanbul ignore next */ []));
86
+ /** Optional field on each datum used as color key. */
87
+ seriesKey = input(undefined, /* @ts-ignore */
88
+ ...(ngDevMode ? [{ debugName: "seriesKey" }] : /* istanbul ignore next */ []));
89
+ styles = input('base', /* @ts-ignore */
90
+ ...(ngDevMode ? [{ debugName: "styles" }] : /* istanbul ignore next */ []));
91
+ margin = input(DEFAULT_MARGIN, /* @ts-ignore */
92
+ ...(ngDevMode ? [{ debugName: "margin" }] : /* istanbul ignore next */ []));
93
+ minPointRadius = input(3, /* @ts-ignore */
94
+ ...(ngDevMode ? [{ debugName: "minPointRadius" }] : /* istanbul ignore next */ []));
95
+ maxPointRadius = input(12, /* @ts-ignore */
96
+ ...(ngDevMode ? [{ debugName: "maxPointRadius" }] : /* istanbul ignore next */ []));
97
+ xDomain = input(undefined, /* @ts-ignore */
98
+ ...(ngDevMode ? [{ debugName: "xDomain" }] : /* istanbul ignore next */ []));
99
+ yDomain = input(undefined, /* @ts-ignore */
100
+ ...(ngDevMode ? [{ debugName: "yDomain" }] : /* istanbul ignore next */ []));
101
+ pointClick = output();
102
+ innerWidth = computed(() => Math.max(0, this.root.dimensions().width - this.margin().left - this.margin().right), /* @ts-ignore */
103
+ ...(ngDevMode ? [{ debugName: "innerWidth" }] : /* istanbul ignore next */ []));
104
+ innerHeight = computed(() => Math.max(0, this.root.dimensions().height - this.margin().top - this.margin().bottom), /* @ts-ignore */
105
+ ...(ngDevMode ? [{ debugName: "innerHeight" }] : /* istanbul ignore next */ []));
106
+ resolvedDomains = computed(() => resolveScatterDomains({
107
+ data: this.data(),
108
+ xKey: this.xKey(),
109
+ yKey: this.yKey(),
110
+ xDomain: this.xDomain(),
111
+ yDomain: this.yDomain(),
112
+ }), /* @ts-ignore */
113
+ ...(ngDevMode ? [{ debugName: "resolvedDomains" }] : /* istanbul ignore next */ []));
114
+ currentXDomain = computed(() => this.viewport.zoomXDomain() ?? this.resolvedDomains().xDomain, /* @ts-ignore */
115
+ ...(ngDevMode ? [{ debugName: "currentXDomain" }] : /* istanbul ignore next */ []));
116
+ currentYDomain = computed(() => this.viewport.zoomYDomain() ?? this.resolvedDomains().yDomain, /* @ts-ignore */
117
+ ...(ngDevMode ? [{ debugName: "currentYDomain" }] : /* istanbul ignore next */ []));
118
+ layout = computed(() => computeScatterLayout({
119
+ data: this.data(),
120
+ xKey: this.xKey(),
121
+ yKey: this.yKey(),
122
+ sizeKey: this.sizeKey(),
123
+ seriesKey: this.seriesKey(),
124
+ seriesKeys: this.root.visibleSeriesKeys(),
125
+ innerWidth: this.innerWidth(),
126
+ innerHeight: this.innerHeight(),
127
+ minPointRadius: this.minPointRadius(),
128
+ maxPointRadius: this.maxPointRadius(),
129
+ xDomain: this.currentXDomain(),
130
+ yDomain: this.currentYDomain(),
131
+ }), /* @ts-ignore */
132
+ ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
133
+ viewBox = computed(() => {
134
+ const { width, height } = this.root.dimensions();
135
+ return `0 0 ${Math.max(0, width)} ${Math.max(0, height)}`;
136
+ }, /* @ts-ignore */
137
+ ...(ngDevMode ? [{ debugName: "viewBox" }] : /* istanbul ignore next */ []));
138
+ innerTransform = computed(() => `translate(${this.margin().left},${this.margin().top})`, /* @ts-ignore */
139
+ ...(ngDevMode ? [{ debugName: "innerTransform" }] : /* istanbul ignore next */ []));
140
+ clipPathId = computed(() => `${this.root.id()}-scatter-clip`, /* @ts-ignore */
141
+ ...(ngDevMode ? [{ debugName: "clipPathId" }] : /* istanbul ignore next */ []));
142
+ ariaSummary = computed(() => `Scatter chart, ${this.data().length} points.`, /* @ts-ignore */
143
+ ...(ngDevMode ? [{ debugName: "ariaSummary" }] : /* istanbul ignore next */ []));
144
+ constructor() {
145
+ effect(() => {
146
+ const domains = this.resolvedDomains();
147
+ const layout = this.layout();
148
+ this.viewport.innerWidth.set(this.innerWidth());
149
+ this.viewport.innerHeight.set(this.innerHeight());
150
+ this.viewport.fullXDomain.set(domains.xDomain);
151
+ this.viewport.fullYDomain.set(domains.yDomain);
152
+ this.viewport.xScale.set(layout.xScale);
153
+ this.viewport.yScale.set(layout.yScale);
154
+ });
155
+ }
156
+ pointAriaLabel(p) {
157
+ return `${p.seriesKey}: x=${p.rawX}, y=${p.rawY}`;
158
+ }
159
+ emitClick(p) {
160
+ this.pointClick.emit({
161
+ seriesKey: p.seriesKey,
162
+ datumIndex: p.datumIndex,
163
+ x: p.rawX,
164
+ y: p.rawY,
165
+ datum: this.data()[p.datumIndex],
166
+ });
167
+ }
168
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ScatterChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
169
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: ScatterChart, isStandalone: true, selector: "ChartScatter", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, xKey: { classPropertyName: "xKey", publicName: "xKey", isSignal: true, isRequired: true, transformFunction: null }, yKey: { classPropertyName: "yKey", publicName: "yKey", isSignal: true, isRequired: true, transformFunction: null }, sizeKey: { classPropertyName: "sizeKey", publicName: "sizeKey", isSignal: true, isRequired: false, transformFunction: null }, seriesKey: { classPropertyName: "seriesKey", publicName: "seriesKey", isSignal: true, isRequired: false, transformFunction: null }, styles: { classPropertyName: "styles", publicName: "styles", isSignal: true, isRequired: false, transformFunction: null }, margin: { classPropertyName: "margin", publicName: "margin", isSignal: true, isRequired: false, transformFunction: null }, minPointRadius: { classPropertyName: "minPointRadius", publicName: "minPointRadius", isSignal: true, isRequired: false, transformFunction: null }, maxPointRadius: { classPropertyName: "maxPointRadius", publicName: "maxPointRadius", isSignal: true, isRequired: false, transformFunction: null }, xDomain: { classPropertyName: "xDomain", publicName: "xDomain", isSignal: true, isRequired: false, transformFunction: null }, yDomain: { classPropertyName: "yDomain", publicName: "yDomain", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pointClick: "pointClick" }, host: { properties: { "attr.data-style": "styles()" }, classAttribute: "relative block h-full w-full" }, providers: [ScatterViewportContext], ngImport: i0, template: `
170
+ <svg:svg
171
+ class="block h-full w-full overflow-visible"
172
+ [attr.viewBox]="viewBox()"
173
+ preserveAspectRatio="none"
174
+ role="img"
175
+ [attr.aria-label]="ariaSummary()">
176
+ <svg:defs>
177
+ <svg:clipPath [attr.id]="clipPathId()">
178
+ <svg:rect x="0" y="0" [attr.width]="innerWidth()" [attr.height]="innerHeight()" />
179
+ </svg:clipPath>
180
+ </svg:defs>
181
+ <svg:g [attr.transform]="innerTransform()">
182
+ <svg:g class="chart-scatter" [attr.clip-path]="'url(#' + clipPathId() + ')'">
183
+ @for (p of layout().points; track p.datumIndex) {
184
+ <svg:circle
185
+ class="chart-scatter-point cursor-pointer transition-opacity hover:opacity-80"
186
+ [attr.cx]="p.x"
187
+ [attr.cy]="p.y"
188
+ [attr.r]="p.radius"
189
+ [attr.fill]="p.color"
190
+ [attr.aria-label]="pointAriaLabel(p)"
191
+ tabindex="0"
192
+ (click)="emitClick(p)"
193
+ (keydown.enter)="emitClick(p)"
194
+ (keydown.space)="emitClick(p); $event.preventDefault()" />
195
+ }
196
+ </svg:g>
197
+ <ng-content select="svg:g[ChartBrush]" />
198
+ </svg:g>
199
+ </svg:svg>
200
+ <ng-content select="ChartLegend" />
201
+ <ng-content select="ChartZoomControls" />
202
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
203
+ }
204
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ScatterChart, decorators: [{
205
+ type: Component,
206
+ args: [{
207
+ selector: 'ChartScatter',
208
+ changeDetection: ChangeDetectionStrategy.OnPush,
209
+ providers: [ScatterViewportContext],
210
+ host: { class: 'relative block h-full w-full', '[attr.data-style]': 'styles()' },
211
+ template: `
212
+ <svg:svg
213
+ class="block h-full w-full overflow-visible"
214
+ [attr.viewBox]="viewBox()"
215
+ preserveAspectRatio="none"
216
+ role="img"
217
+ [attr.aria-label]="ariaSummary()">
218
+ <svg:defs>
219
+ <svg:clipPath [attr.id]="clipPathId()">
220
+ <svg:rect x="0" y="0" [attr.width]="innerWidth()" [attr.height]="innerHeight()" />
221
+ </svg:clipPath>
222
+ </svg:defs>
223
+ <svg:g [attr.transform]="innerTransform()">
224
+ <svg:g class="chart-scatter" [attr.clip-path]="'url(#' + clipPathId() + ')'">
225
+ @for (p of layout().points; track p.datumIndex) {
226
+ <svg:circle
227
+ class="chart-scatter-point cursor-pointer transition-opacity hover:opacity-80"
228
+ [attr.cx]="p.x"
229
+ [attr.cy]="p.y"
230
+ [attr.r]="p.radius"
231
+ [attr.fill]="p.color"
232
+ [attr.aria-label]="pointAriaLabel(p)"
233
+ tabindex="0"
234
+ (click)="emitClick(p)"
235
+ (keydown.enter)="emitClick(p)"
236
+ (keydown.space)="emitClick(p); $event.preventDefault()" />
237
+ }
238
+ </svg:g>
239
+ <ng-content select="svg:g[ChartBrush]" />
240
+ </svg:g>
241
+ </svg:svg>
242
+ <ng-content select="ChartLegend" />
243
+ <ng-content select="ChartZoomControls" />
244
+ `,
245
+ }]
246
+ }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], xKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "xKey", required: true }] }], yKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "yKey", required: true }] }], sizeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "sizeKey", required: false }] }], seriesKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "seriesKey", required: false }] }], styles: [{ type: i0.Input, args: [{ isSignal: true, alias: "styles", required: false }] }], margin: [{ type: i0.Input, args: [{ isSignal: true, alias: "margin", required: false }] }], minPointRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "minPointRadius", required: false }] }], maxPointRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxPointRadius", required: false }] }], xDomain: [{ type: i0.Input, args: [{ isSignal: true, alias: "xDomain", required: false }] }], yDomain: [{ type: i0.Input, args: [{ isSignal: true, alias: "yDomain", required: false }] }], pointClick: [{ type: i0.Output, args: ["pointClick"] }] } });
247
+
248
+ /**
249
+ * Generated bundle index. Do not edit.
250
+ */
251
+
252
+ export { ScatterChart, computeScatterLayout, resolveScatterDomains };
253
+ //# sourceMappingURL=ojiepermana-angular-chart-scatter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ojiepermana-angular-chart-scatter.mjs","sources":["../../../library/chart/scatter/scatter-layout.ts","../../../library/chart/scatter/scatter-chart.ts","../../../library/chart/scatter/ojiepermana-angular-chart-scatter.ts"],"sourcesContent":["import { scaleLinear, type ScaleLinear } from 'd3-scale';\nimport { extent as d3extent } from 'd3-array';\nimport type { ChartDatum } from '@ojiepermana/angular-chart/core';\nimport { seriesColorVar } from '@ojiepermana/angular-chart/core';\nimport type { NumericDomain } from '@ojiepermana/angular-chart/core';\n\nexport interface ScatterLayoutInput {\n readonly data: readonly ChartDatum[];\n readonly xKey: string;\n readonly yKey: string;\n readonly sizeKey?: string;\n readonly seriesKey?: string;\n readonly seriesKeys: readonly string[];\n readonly innerWidth: number;\n readonly innerHeight: number;\n readonly minPointRadius: number;\n readonly maxPointRadius: number;\n readonly xDomain?: readonly [number, number];\n readonly yDomain?: readonly [number, number];\n}\n\nexport interface ScatterPoint {\n readonly seriesKey: string;\n readonly color: string;\n readonly x: number;\n readonly y: number;\n readonly radius: number;\n readonly datumIndex: number;\n readonly rawX: number;\n readonly rawY: number;\n readonly rawSize: number;\n}\n\nexport interface ScatterLayout {\n readonly points: readonly ScatterPoint[];\n readonly xScale: ScaleLinear<number, number>;\n readonly yScale: ScaleLinear<number, number>;\n readonly xDomain: NumericDomain;\n readonly yDomain: NumericDomain;\n}\n\nfunction nice(extent: [number, number] | [undefined, undefined]): [number, number] {\n const [lo, hi] = extent;\n if (lo === undefined || hi === undefined) return [0, 1];\n if (lo === hi) return [lo - 1, hi + 1];\n return [lo, hi];\n}\n\nexport function resolveScatterDomains(\n input: Pick<ScatterLayoutInput, 'data' | 'xKey' | 'yKey' | 'xDomain' | 'yDomain'>,\n): { xDomain: NumericDomain; yDomain: NumericDomain } {\n const xValues = input.data.map((d) => Number(d[input.xKey] ?? 0));\n const yValues = input.data.map((d) => Number(d[input.yKey] ?? 0));\n return {\n xDomain: (input.xDomain ?? nice(d3extent(xValues) as [number, number])) as NumericDomain,\n yDomain: (input.yDomain ?? nice(d3extent(yValues) as [number, number])) as NumericDomain,\n };\n}\n\nexport function computeScatterLayout(input: ScatterLayoutInput): ScatterLayout {\n const { data, xKey, yKey, sizeKey, seriesKey, seriesKeys, innerWidth, innerHeight, minPointRadius, maxPointRadius } =\n input;\n\n const xValues = data.map((d) => Number(d[xKey] ?? 0));\n const yValues = data.map((d) => Number(d[yKey] ?? 0));\n const sizeValues = sizeKey ? data.map((d) => Number(d[sizeKey] ?? 0)) : [];\n\n const { xDomain, yDomain } = resolveScatterDomains(input);\n\n const xScale = scaleLinear()\n .domain(xDomain as [number, number])\n .range([0, innerWidth]);\n const yScale = scaleLinear()\n .domain(yDomain as [number, number])\n .range([innerHeight, 0]);\n\n let sizeScale: ScaleLinear<number, number> | null = null;\n if (sizeKey && sizeValues.length > 0) {\n const [sLo, sHi] = d3extent(sizeValues) as [number, number];\n sizeScale = scaleLinear()\n .domain([sLo ?? 0, sHi ?? 1])\n .range([minPointRadius, maxPointRadius]);\n }\n\n const fallbackKey = seriesKeys[0] ?? 'value';\n\n const points: ScatterPoint[] = data.flatMap((d, i) => {\n const key = seriesKey ? String(d[seriesKey] ?? fallbackKey) : fallbackKey;\n const sz = sizeKey ? Number(d[sizeKey] ?? 0) : 0;\n const rawX = xValues[i];\n const rawY = yValues[i];\n if (rawX < xDomain[0] || rawX > xDomain[1] || rawY < yDomain[0] || rawY > yDomain[1]) {\n return [];\n }\n return [\n {\n seriesKey: key,\n color: seriesColorVar(key),\n x: xScale(rawX),\n y: yScale(rawY),\n radius: sizeScale ? sizeScale(sz) : minPointRadius,\n datumIndex: i,\n rawX,\n rawY,\n rawSize: sz,\n },\n ];\n });\n\n return { points, xScale, yScale, xDomain, yDomain };\n}\n","import { ChangeDetectionStrategy, Component, computed, effect, inject, input, output } from '@angular/core';\nimport { ChartContext } from '@ojiepermana/angular-chart/core';\nimport type { ChartDatum, ChartMargin, ChartStyleVariant } from '@ojiepermana/angular-chart/core';\nimport { ScatterViewportContext } from '@ojiepermana/angular-chart/core';\nimport { computeScatterLayout, resolveScatterDomains, type ScatterPoint } from './scatter-layout';\n\nconst DEFAULT_MARGIN: ChartMargin = { top: 8, right: 8, bottom: 24, left: 40 };\n\nexport interface ScatterPointClickEvent {\n readonly seriesKey: string;\n readonly datumIndex: number;\n readonly x: number;\n readonly y: number;\n readonly datum: ChartDatum;\n}\n\n/**\n * Scatter chart — one dot per datum. Both axes are linear; color can\n * come from a fixed series key or per-row via `seriesKey` field. Point\n * radius optionally scales with `sizeKey`.\n */\n@Component({\n selector: 'ChartScatter',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [ScatterViewportContext],\n host: { class: 'relative block h-full w-full', '[attr.data-style]': 'styles()' },\n template: `\n <svg:svg\n class=\"block h-full w-full overflow-visible\"\n [attr.viewBox]=\"viewBox()\"\n preserveAspectRatio=\"none\"\n role=\"img\"\n [attr.aria-label]=\"ariaSummary()\">\n <svg:defs>\n <svg:clipPath [attr.id]=\"clipPathId()\">\n <svg:rect x=\"0\" y=\"0\" [attr.width]=\"innerWidth()\" [attr.height]=\"innerHeight()\" />\n </svg:clipPath>\n </svg:defs>\n <svg:g [attr.transform]=\"innerTransform()\">\n <svg:g class=\"chart-scatter\" [attr.clip-path]=\"'url(#' + clipPathId() + ')'\">\n @for (p of layout().points; track p.datumIndex) {\n <svg:circle\n class=\"chart-scatter-point cursor-pointer transition-opacity hover:opacity-80\"\n [attr.cx]=\"p.x\"\n [attr.cy]=\"p.y\"\n [attr.r]=\"p.radius\"\n [attr.fill]=\"p.color\"\n [attr.aria-label]=\"pointAriaLabel(p)\"\n tabindex=\"0\"\n (click)=\"emitClick(p)\"\n (keydown.enter)=\"emitClick(p)\"\n (keydown.space)=\"emitClick(p); $event.preventDefault()\" />\n }\n </svg:g>\n <ng-content select=\"svg:g[ChartBrush]\" />\n </svg:g>\n </svg:svg>\n <ng-content select=\"ChartLegend\" />\n <ng-content select=\"ChartZoomControls\" />\n `,\n})\nexport class ScatterChart {\n private readonly root = inject(ChartContext);\n private readonly viewport = inject(ScatterViewportContext);\n\n readonly data = input.required<readonly ChartDatum[]>();\n readonly xKey = input.required<string>();\n readonly yKey = input.required<string>();\n /** Optional numeric field to drive point radius. */\n readonly sizeKey = input<string | undefined>(undefined);\n /** Optional field on each datum used as color key. */\n readonly seriesKey = input<string | undefined>(undefined);\n readonly styles = input<ChartStyleVariant>('base');\n readonly margin = input<ChartMargin>(DEFAULT_MARGIN);\n readonly minPointRadius = input<number>(3);\n readonly maxPointRadius = input<number>(12);\n readonly xDomain = input<readonly [number, number] | undefined>(undefined);\n readonly yDomain = input<readonly [number, number] | undefined>(undefined);\n\n readonly pointClick = output<ScatterPointClickEvent>();\n\n protected readonly innerWidth = computed(() =>\n Math.max(0, this.root.dimensions().width - this.margin().left - this.margin().right),\n );\n protected readonly innerHeight = computed(() =>\n Math.max(0, this.root.dimensions().height - this.margin().top - this.margin().bottom),\n );\n\n protected readonly resolvedDomains = computed(() =>\n resolveScatterDomains({\n data: this.data(),\n xKey: this.xKey(),\n yKey: this.yKey(),\n xDomain: this.xDomain(),\n yDomain: this.yDomain(),\n }),\n );\n\n protected readonly currentXDomain = computed(() => this.viewport.zoomXDomain() ?? this.resolvedDomains().xDomain);\n\n protected readonly currentYDomain = computed(() => this.viewport.zoomYDomain() ?? this.resolvedDomains().yDomain);\n\n protected readonly layout = computed(() =>\n computeScatterLayout({\n data: this.data(),\n xKey: this.xKey(),\n yKey: this.yKey(),\n sizeKey: this.sizeKey(),\n seriesKey: this.seriesKey(),\n seriesKeys: this.root.visibleSeriesKeys(),\n innerWidth: this.innerWidth(),\n innerHeight: this.innerHeight(),\n minPointRadius: this.minPointRadius(),\n maxPointRadius: this.maxPointRadius(),\n xDomain: this.currentXDomain(),\n yDomain: this.currentYDomain(),\n }),\n );\n\n protected readonly viewBox = computed(() => {\n const { width, height } = this.root.dimensions();\n return `0 0 ${Math.max(0, width)} ${Math.max(0, height)}`;\n });\n\n protected readonly innerTransform = computed(() => `translate(${this.margin().left},${this.margin().top})`);\n\n protected readonly clipPathId = computed(() => `${this.root.id()}-scatter-clip`);\n\n protected readonly ariaSummary = computed(() => `Scatter chart, ${this.data().length} points.`);\n\n constructor() {\n effect(() => {\n const domains = this.resolvedDomains();\n const layout = this.layout();\n this.viewport.innerWidth.set(this.innerWidth());\n this.viewport.innerHeight.set(this.innerHeight());\n this.viewport.fullXDomain.set(domains.xDomain);\n this.viewport.fullYDomain.set(domains.yDomain);\n this.viewport.xScale.set(layout.xScale);\n this.viewport.yScale.set(layout.yScale);\n });\n }\n\n protected pointAriaLabel(p: ScatterPoint): string {\n return `${p.seriesKey}: x=${p.rawX}, y=${p.rawY}`;\n }\n\n protected emitClick(p: ScatterPoint): void {\n this.pointClick.emit({\n seriesKey: p.seriesKey,\n datumIndex: p.datumIndex,\n x: p.rawX,\n y: p.rawY,\n datum: this.data()[p.datumIndex],\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["d3extent"],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ export { CHART_DATA_ATTRIBUTE, CHART_THEMES, CartesianContext, CategoricalViewportContext, ChartContainer, ChartContext, ChartStyle, ScatterViewportContext, bandTicks, buildCartesianScales, buildChartCss, cloneLinear, computeAreaLayout, computeLineLayout, effectiveIndexRange, elementClientCenter, indexRangeSize, linearTicks, nearestCategoryIndex, normalizeIndexRange, normalizeNumericDomain, panIndexRange, panNumericDomain, pointToBandAdapter, provideCartesianFromLineLayout, seriesColorVar, sliceByIndexRange, xScale, yScale, zoomIndexRange, zoomNumericDomain } from '@ojiepermana/angular-chart/core';
2
+ export { ChartAxisX, ChartAxisY, ChartBrush, ChartCrosshair, ChartGrid, ChartLegend, ChartPointerTracker, ChartTooltip, ChartZoomControls, PieCenter, RadialCenter } from '@ojiepermana/angular-chart/primitives';
3
+
4
+ /*
5
+ * Public API Surface of @ojiepermana/angular-chart
6
+ *
7
+ * Hanya core + primitives (kebutuhan bersama semua chart). Famili chart
8
+ * diimpor lewat entry point masing-masing, mis. `@ojiepermana/angular-chart/bar`,
9
+ * supaya aplikasi hanya membundel jenis chart yang dipakai.
10
+ */
11
+ /*
12
+ * Re-export per nama (bukan `export *`): entry point ini menjadi modul shared
13
+ * native federation, dan esbuild tidak bisa meneruskan named export melalui
14
+ * `export *` dari modul external — konsumen akan gagal resolve saat runtime.
15
+ */
16
+
17
+ /**
18
+ * Generated bundle index. Do not edit.
19
+ */
20
+ //# sourceMappingURL=ojiepermana-angular-chart.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ojiepermana-angular-chart.mjs","sources":["../../../library/chart/public-api.ts","../../../library/chart/ojiepermana-angular-chart.ts"],"sourcesContent":["/*\n * Public API Surface of @ojiepermana/angular-chart\n *\n * Hanya core + primitives (kebutuhan bersama semua chart). Famili chart\n * diimpor lewat entry point masing-masing, mis. `@ojiepermana/angular-chart/bar`,\n * supaya aplikasi hanya membundel jenis chart yang dipakai.\n */\n\n/*\n * Re-export per nama (bukan `export *`): entry point ini menjadi modul shared\n * native federation, dan esbuild tidak bisa meneruskan named export melalui\n * `export *` dari modul external — konsumen akan gagal resolve saat runtime.\n */\nexport {\n CHART_DATA_ATTRIBUTE,\n CHART_THEMES,\n CartesianContext,\n CategoricalViewportContext,\n ChartContainer,\n ChartContext,\n ChartStyle,\n ScatterViewportContext,\n bandTicks,\n buildCartesianScales,\n buildChartCss,\n cloneLinear,\n computeAreaLayout,\n computeLineLayout,\n effectiveIndexRange,\n elementClientCenter,\n indexRangeSize,\n linearTicks,\n nearestCategoryIndex,\n normalizeIndexRange,\n normalizeNumericDomain,\n panIndexRange,\n panNumericDomain,\n pointToBandAdapter,\n provideCartesianFromLineLayout,\n seriesColorVar,\n sliceByIndexRange,\n xScale,\n yScale,\n zoomIndexRange,\n zoomNumericDomain,\n} from '@ojiepermana/angular-chart/core';\nexport type {\n AreaLayoutInput,\n AreaLayoutResult,\n CartesianBase,\n CategoryScale,\n ChartActivePoint,\n ChartConfig,\n ChartDatum,\n ChartDimensions,\n ChartIndexRange,\n ChartMargin,\n ChartOrientation,\n ChartSeriesConfig,\n ChartStyleVariant,\n ChartThemeKey,\n ChartTick,\n ClientPoint,\n LineCurve,\n LineLayoutResult,\n LinePoint,\n LineSeriesPath,\n NumericDomain,\n ValueScale,\n} from '@ojiepermana/angular-chart/core';\nexport {\n ChartAxisX,\n ChartAxisY,\n ChartBrush,\n ChartCrosshair,\n ChartGrid,\n ChartLegend,\n ChartPointerTracker,\n ChartTooltip,\n ChartZoomControls,\n PieCenter,\n RadialCenter,\n} from '@ojiepermana/angular-chart/primitives';\nexport type {\n ChartTooltipIndicator,\n ChartTooltipLabelFormatter,\n ChartTooltipPayload,\n ChartTooltipRow,\n ChartTooltipValueFormatter,\n} from '@ojiepermana/angular-chart/primitives';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;AAAA;;;;;;AAMG;AAEH;;;;AAIG;;ACZH;;AAEG"}