juxscript 1.0.59 → 1.0.60

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.
@@ -1,315 +0,0 @@
1
- import { BaseChart, BaseChartState, ChartDataPoint } from './lib/BaseChart.js';
2
-
3
- export interface AreaChartOptions {
4
- data?: ChartDataPoint[];
5
- title?: string;
6
- subtitle?: string;
7
- xAxisLabel?: string;
8
- yAxisLabel?: string;
9
- showTicksX?: boolean;
10
- showTicksY?: boolean;
11
- showScaleX?: boolean;
12
- showScaleY?: boolean;
13
- scaleXUnit?: string;
14
- scaleYUnit?: string;
15
- showLegend?: boolean;
16
- legendOrientation?: 'horizontal' | 'vertical';
17
- showDataTable?: boolean;
18
- showDataLabels?: boolean;
19
- animate?: boolean;
20
- animationDuration?: number;
21
- width?: number;
22
- height?: number;
23
- colors?: string[];
24
- class?: string;
25
- style?: string;
26
- theme?: 'google' | 'seriesa' | 'hr' | 'figma' | 'notion' | 'chalk' | 'mint';
27
- styleMode?: 'default' | 'gradient' | 'outline' | 'dashed' | 'glow' | 'glass';
28
- borderRadius?: number;
29
- }
30
-
31
- interface AreaChartState extends BaseChartState {
32
- data: ChartDataPoint[];
33
- }
34
-
35
- export class AreaChart extends BaseChart<AreaChartState> {
36
- constructor(id: string, options: AreaChartOptions = {}) {
37
- const defaultColors = ['#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6'];
38
- const randomColor = defaultColors[Math.floor(Math.random() * defaultColors.length)];
39
-
40
- super(id, {
41
- data: options.data ?? [],
42
- title: options.title ?? '',
43
- subtitle: options.subtitle ?? '',
44
- xAxisLabel: options.xAxisLabel ?? '',
45
- yAxisLabel: options.yAxisLabel ?? '',
46
- showTicksX: options.showTicksX ?? true,
47
- showTicksY: options.showTicksY ?? true,
48
- showScaleX: options.showScaleX ?? true,
49
- showScaleY: options.showScaleY ?? true,
50
- scaleXUnit: options.scaleXUnit ?? '',
51
- scaleYUnit: options.scaleYUnit ?? '',
52
- showLegend: options.showLegend ?? false,
53
- legendOrientation: options.legendOrientation ?? 'horizontal',
54
- showDataTable: options.showDataTable ?? false,
55
- showDataLabels: options.showDataLabels ?? true,
56
- animate: options.animate ?? true,
57
- animationDuration: options.animationDuration ?? 800,
58
- width: options.width ?? 600,
59
- height: options.height ?? 400,
60
- colors: options.colors ?? [randomColor],
61
- class: options.class ?? '',
62
- style: options.style ?? '',
63
- theme: options.theme,
64
- styleMode: options.styleMode ?? 'default',
65
- borderRadius: options.borderRadius ?? 4
66
- });
67
- }
68
-
69
- protected _getChartClassName(): string {
70
- return 'jux-areachart';
71
- }
72
-
73
- protected _createSVG(): SVGSVGElement {
74
- const { data, width, height, colors, animate, animationDuration } = this.state;
75
-
76
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
77
- svg.setAttribute('width', width.toString());
78
- svg.setAttribute('height', height.toString());
79
- svg.setAttribute('class', 'jux-areachart-svg');
80
-
81
- if (!data.length) return svg;
82
-
83
- if (animate) this._addAnimationStyles(svg);
84
-
85
- const padding = { top: 40, right: 40, bottom: 60, left: 60 };
86
- const chartWidth = width - padding.left - padding.right;
87
- const chartHeight = height - padding.top - padding.bottom;
88
- const maxValue = Math.max(...data.map(d => d.value));
89
-
90
- this._renderAreaChart(svg, padding, chartWidth, chartHeight, maxValue);
91
-
92
- return svg;
93
- }
94
-
95
- protected _getBaseStyles(): string {
96
- return `
97
- .jux-areachart {
98
- font-family: var(--chart-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
99
- display: inline-block;
100
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
101
- border-radius: 12px;
102
- background: white;
103
- padding: 24px;
104
- }
105
- .jux-areachart-title {
106
- margin: 0 0 0.5rem 0;
107
- font-size: 1.25rem;
108
- font-weight: 600;
109
- }
110
- .jux-areachart-subtitle {
111
- margin: 0 0 1rem 0;
112
- font-size: 0.875rem;
113
- color: #6b7280;
114
- }
115
- .jux-areachart-legend {
116
- display: flex;
117
- flex-wrap: wrap;
118
- gap: 1rem;
119
- margin-top: 1rem;
120
- justify-content: center;
121
- }
122
- .jux-areachart-legend-item {
123
- display: flex;
124
- align-items: center;
125
- gap: 0.5rem;
126
- }
127
- .jux-areachart-legend-swatch {
128
- width: 12px;
129
- height: 12px;
130
- border-radius: 2px;
131
- }
132
- .jux-areachart-legend-label {
133
- font-size: 0.875rem;
134
- color: #374151;
135
- }
136
- .jux-areachart-table {
137
- width: 100%;
138
- margin-top: 1rem;
139
- border-collapse: collapse;
140
- font-size: 0.875rem;
141
- }
142
- .jux-areachart-table thead th {
143
- text-align: center;
144
- padding: 0.5rem;
145
- border-bottom: 2px solid #e5e7eb;
146
- font-weight: 600;
147
- }
148
- .jux-areachart-table tbody td {
149
- padding: 0.5rem;
150
- border-bottom: 1px solid #f3f4f6;
151
- text-align: center;
152
- }
153
- .jux-areachart-svg {
154
- font-family: inherit;
155
- }
156
- `;
157
- }
158
-
159
- private _addAnimationStyles(svg: SVGSVGElement): void {
160
- const { animationDuration } = this.state;
161
- const animationId = `area-grow-${this._id}`;
162
- const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
163
-
164
- style.textContent = `
165
- @keyframes ${animationId} {
166
- from { opacity: 0; transform: scaleY(0); }
167
- to { opacity: 1; transform: scaleY(1); }
168
- }
169
- .jux-area-animated {
170
- transform-origin: bottom;
171
- animation: ${animationId} ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
172
- }
173
- `;
174
- svg.appendChild(style);
175
- }
176
-
177
- private _renderAreaChart(svg: SVGSVGElement, padding: any, chartWidth: number, chartHeight: number, maxValue: number): void {
178
- const { data, width, height, colors, showDataLabels, animate, xAxisLabel, yAxisLabel, showTicksX, showTicksY, showScaleX, showScaleY, scaleYUnit } = this.state;
179
-
180
- const yScale = chartHeight / maxValue;
181
- const xStep = chartWidth / (data.length - 1 || 1);
182
- const color = colors[0];
183
-
184
- // Axes
185
- if (showScaleY) {
186
- this._renderAxis(svg, padding.left, padding.top, padding.left, height - padding.bottom);
187
- if (yAxisLabel && showTicksY) {
188
- this._renderAxisLabel(svg, yAxisLabel, 20, padding.top + chartHeight / 2, -90);
189
- }
190
- if (showTicksY) {
191
- this._renderYTicks(svg, maxValue, yScale, padding, width, height, scaleYUnit, chartHeight);
192
- }
193
- }
194
-
195
- if (showScaleX) {
196
- this._renderAxis(svg, padding.left, height - padding.bottom, width - padding.right, height - padding.bottom);
197
- if (xAxisLabel && showTicksX) {
198
- this._renderAxisLabel(svg, xAxisLabel, padding.left + chartWidth / 2, height - 15, 0);
199
- }
200
- }
201
-
202
- // Build area path
203
- let pathData = `M ${padding.left} ${height - padding.bottom}`;
204
- data.forEach((point, i) => {
205
- const x = padding.left + (i * xStep);
206
- const y = height - padding.bottom - (point.value * yScale);
207
- pathData += ` L ${x} ${y}`;
208
- });
209
- pathData += ` L ${padding.left + ((data.length - 1) * xStep)} ${height - padding.bottom} Z`;
210
-
211
- const areaPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
212
- areaPath.setAttribute('d', pathData);
213
- areaPath.setAttribute('fill', color);
214
- areaPath.setAttribute('fill-opacity', '0.3');
215
- if (animate) areaPath.classList.add('jux-area-animated');
216
- svg.appendChild(areaPath);
217
-
218
- // Line path
219
- let lineData = '';
220
- data.forEach((point, i) => {
221
- const x = padding.left + (i * xStep);
222
- const y = height - padding.bottom - (point.value * yScale);
223
- lineData += (i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`);
224
- });
225
-
226
- const linePath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
227
- linePath.setAttribute('d', lineData);
228
- linePath.setAttribute('stroke', color);
229
- linePath.setAttribute('stroke-width', '3');
230
- linePath.setAttribute('fill', 'none');
231
- svg.appendChild(linePath);
232
-
233
- // Data points
234
- data.forEach((point, i) => {
235
- const x = padding.left + (i * xStep);
236
- const y = height - padding.bottom - (point.value * yScale);
237
-
238
- const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
239
- circle.setAttribute('cx', x.toString());
240
- circle.setAttribute('cy', y.toString());
241
- circle.setAttribute('r', '4');
242
- circle.setAttribute('fill', color);
243
- circle.setAttribute('stroke', 'white');
244
- circle.setAttribute('stroke-width', '2');
245
- svg.appendChild(circle);
246
-
247
- if (showDataLabels) {
248
- const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
249
- label.setAttribute('x', x.toString());
250
- label.setAttribute('y', (y - 10).toString());
251
- label.setAttribute('text-anchor', 'middle');
252
- label.setAttribute('fill', '#374151');
253
- label.setAttribute('font-size', '11');
254
- label.setAttribute('font-weight', '600');
255
- label.textContent = point.value.toString();
256
- svg.appendChild(label);
257
- }
258
- });
259
- }
260
-
261
- private _renderAxis(svg: SVGSVGElement, x1: number, y1: number, x2: number, y2: number): void {
262
- const axis = document.createElementNS('http://www.w3.org/2000/svg', 'line');
263
- axis.setAttribute('x1', x1.toString());
264
- axis.setAttribute('y1', y1.toString());
265
- axis.setAttribute('x2', x2.toString());
266
- axis.setAttribute('y2', y2.toString());
267
- axis.setAttribute('stroke', '#9ca3af');
268
- axis.setAttribute('stroke-width', '2');
269
- svg.appendChild(axis);
270
- }
271
-
272
- private _renderAxisLabel(svg: SVGSVGElement, text: string, x: number, y: number, rotate: number): void {
273
- const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
274
- label.setAttribute('x', x.toString());
275
- label.setAttribute('y', y.toString());
276
- label.setAttribute('text-anchor', 'middle');
277
- if (rotate !== 0) label.setAttribute('transform', `rotate(${rotate}, ${x}, ${y})`);
278
- label.setAttribute('fill', '#6b7280');
279
- label.setAttribute('font-size', '12');
280
- label.setAttribute('font-weight', '500');
281
- label.textContent = text;
282
- svg.appendChild(label);
283
- }
284
-
285
- private _renderYTicks(svg: SVGSVGElement, maxValue: number, yScale: number, padding: any, width: number, height: number, unit: string, chartHeight: number): void {
286
- const numTicks = 5;
287
- for (let i = 0; i <= numTicks; i++) {
288
- const value = (maxValue / numTicks) * i;
289
- const y = height - padding.bottom - (value * yScale);
290
-
291
- const gridLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
292
- gridLine.setAttribute('x1', padding.left.toString());
293
- gridLine.setAttribute('y1', y.toString());
294
- gridLine.setAttribute('x2', (width - padding.right).toString());
295
- gridLine.setAttribute('y2', y.toString());
296
- gridLine.setAttribute('stroke', '#e5e7eb');
297
- gridLine.setAttribute('stroke-width', '1');
298
- gridLine.setAttribute('stroke-dasharray', '4,4');
299
- svg.appendChild(gridLine);
300
-
301
- const tickLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
302
- tickLabel.setAttribute('x', (padding.left - 10).toString());
303
- tickLabel.setAttribute('y', (y + 4).toString());
304
- tickLabel.setAttribute('text-anchor', 'end');
305
- tickLabel.setAttribute('fill', '#6b7280');
306
- tickLabel.setAttribute('font-size', '11');
307
- tickLabel.textContent = Math.round(value).toString() + (unit || '');
308
- svg.appendChild(tickLabel);
309
- }
310
- }
311
- }
312
-
313
- export function areachart(id: string, options: AreaChartOptions = {}): AreaChart {
314
- return new AreaChart(id, options);
315
- }