juxscript 1.0.19 → 1.0.20
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/lib/components/alert.ts +124 -128
- package/lib/components/areachart.ts +169 -287
- package/lib/components/areachartsmooth.ts +2 -2
- package/lib/components/badge.ts +63 -72
- package/lib/components/barchart.ts +120 -48
- package/lib/components/button.ts +92 -60
- package/lib/components/card.ts +97 -121
- package/lib/components/chart-types.ts +159 -0
- package/lib/components/chart-utils.ts +160 -0
- package/lib/components/chart.ts +628 -48
- package/lib/components/checkbox.ts +137 -51
- package/lib/components/code.ts +89 -75
- package/lib/components/container.ts +1 -1
- package/lib/components/datepicker.ts +93 -78
- package/lib/components/dialog.ts +163 -130
- package/lib/components/divider.ts +111 -193
- package/lib/components/docs-data.json +697 -274
- package/lib/components/doughnutchart.ts +125 -57
- package/lib/components/dropdown.ts +172 -85
- package/lib/components/element.ts +66 -61
- package/lib/components/fileupload.ts +142 -171
- package/lib/components/heading.ts +64 -21
- package/lib/components/hero.ts +109 -34
- package/lib/components/icon.ts +247 -0
- package/lib/components/icons.ts +174 -0
- package/lib/components/include.ts +77 -2
- package/lib/components/input.ts +105 -53
- package/lib/components/list.ts +120 -79
- package/lib/components/menu.ts +97 -2
- package/lib/components/modal.ts +144 -63
- package/lib/components/nav.ts +153 -52
- package/lib/components/paragraph.ts +54 -91
- package/lib/components/progress.ts +83 -107
- package/lib/components/radio.ts +151 -52
- package/lib/components/select.ts +110 -102
- package/lib/components/sidebar.ts +148 -105
- package/lib/components/switch.ts +124 -125
- package/lib/components/table.ts +214 -137
- package/lib/components/tabs.ts +194 -113
- package/lib/components/theme-toggle.ts +38 -7
- package/lib/components/tooltip.ts +207 -47
- package/lib/jux.ts +24 -5
- package/package.json +1 -2
|
@@ -1,116 +1,39 @@
|
|
|
1
1
|
import { getOrCreateContainer } from './helpers.js';
|
|
2
2
|
import { State } from '../reactivity/state.js';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Bar chart options
|
|
24
|
-
*/
|
|
25
|
-
export interface AreaChartOptions {
|
|
26
|
-
data?: AreaChartDataPoint[];
|
|
27
|
-
title?: string;
|
|
28
|
-
subtitle?: string;
|
|
29
|
-
xAxisLabel?: string;
|
|
30
|
-
yAxisLabel?: string;
|
|
31
|
-
showTicksX?: boolean;
|
|
32
|
-
showTicksY?: boolean;
|
|
33
|
-
showScaleX?: boolean;
|
|
34
|
-
showScaleY?: boolean;
|
|
35
|
-
scaleXUnit?: string;
|
|
36
|
-
scaleYUnit?: string;
|
|
37
|
-
showLegend?: boolean;
|
|
38
|
-
legendOrientation?: 'horizontal' | 'vertical';
|
|
39
|
-
showDataTable?: boolean;
|
|
40
|
-
showDataLabels?: boolean;
|
|
41
|
-
animate?: boolean;
|
|
42
|
-
animationDuration?: number;
|
|
43
|
-
chartOrientation?: 'vertical' | 'horizontal'; // NEW
|
|
44
|
-
chartDirection?: 'normal' | 'reverse'; // NEW: normal = bottom-to-top or left-to-right, reverse = opposite
|
|
45
|
-
width?: number;
|
|
46
|
-
height?: number;
|
|
47
|
-
colors?: string[];
|
|
48
|
-
class?: string;
|
|
49
|
-
style?: string;
|
|
50
|
-
theme?: 'google' | 'seriesa' | 'hr' | 'figma' | 'notion' | 'chalk' | 'mint';
|
|
51
|
-
styleMode?: 'default' | 'gradient' | 'glow' | 'glass';
|
|
52
|
-
borderRadius?: number;
|
|
53
|
-
}
|
|
4
|
+
ChartDataPoint,
|
|
5
|
+
BarAreaChartOptions,
|
|
6
|
+
BarAreaChartState,
|
|
7
|
+
ChartTheme,
|
|
8
|
+
ChartStyleMode,
|
|
9
|
+
ChartOrientation,
|
|
10
|
+
ChartDirection,
|
|
11
|
+
LegendOrientation,
|
|
12
|
+
ChartPropertyMapping,
|
|
13
|
+
ChartStateObject
|
|
14
|
+
} from './chart-types.js';
|
|
15
|
+
import {
|
|
16
|
+
lightenColor,
|
|
17
|
+
getThemeConfig,
|
|
18
|
+
createLegend,
|
|
19
|
+
createDataTable,
|
|
20
|
+
applyThemeStyles
|
|
21
|
+
} from './chart-utils.js';
|
|
54
22
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
type AreaChartState = {
|
|
59
|
-
data: AreaChartDataPoint[];
|
|
60
|
-
title: string;
|
|
61
|
-
subtitle: string;
|
|
62
|
-
xAxisLabel: string;
|
|
63
|
-
yAxisLabel: string;
|
|
64
|
-
showTicksX: boolean;
|
|
65
|
-
showTicksY: boolean;
|
|
66
|
-
showScaleX: boolean;
|
|
67
|
-
showScaleY: boolean;
|
|
68
|
-
scaleXUnit: string;
|
|
69
|
-
scaleYUnit: string;
|
|
70
|
-
showLegend: boolean;
|
|
71
|
-
legendOrientation: 'horizontal' | 'vertical';
|
|
72
|
-
showDataTable: boolean;
|
|
73
|
-
showDataLabels: boolean;
|
|
74
|
-
animate: boolean;
|
|
75
|
-
animationDuration: number;
|
|
76
|
-
chartOrientation: 'vertical' | 'horizontal'; // NEW
|
|
77
|
-
chartDirection: 'normal' | 'reverse'; // NEW
|
|
78
|
-
width: number;
|
|
79
|
-
height: number;
|
|
80
|
-
colors: string[];
|
|
81
|
-
class: string;
|
|
82
|
-
style: string;
|
|
83
|
-
theme?: 'google' | 'seriesa' | 'hr' | 'figma' | 'notion' | 'chalk' | 'mint';
|
|
84
|
-
styleMode: 'default' | 'gradient' | 'glow' | 'glass';
|
|
85
|
-
borderRadius: number;
|
|
86
|
-
};
|
|
23
|
+
// Re-export for convenience
|
|
24
|
+
export type { ChartDataPoint as AreaChartDataPoint };
|
|
25
|
+
export type { BarAreaChartOptions as AreaChartOptions };
|
|
87
26
|
|
|
88
27
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* Usage:
|
|
92
|
-
* jux.areachart('sales-chart')
|
|
93
|
-
* .data([
|
|
94
|
-
* { label: 'Jan', value: 100 },
|
|
95
|
-
* { label: 'Feb', value: 150 },
|
|
96
|
-
* { label: 'Mar', value: 200 }
|
|
97
|
-
* ])
|
|
98
|
-
* .title('Monthly Sales')
|
|
99
|
-
* .showLegend(true)
|
|
100
|
-
* .render('#app');
|
|
28
|
+
* Area chart component - Simple SVG-based area chart
|
|
101
29
|
*/
|
|
102
30
|
export class AreaChart {
|
|
103
|
-
state:
|
|
31
|
+
state: BarAreaChartState;
|
|
104
32
|
container: HTMLElement | null = null;
|
|
105
33
|
_id: string;
|
|
106
34
|
id: string;
|
|
107
35
|
|
|
108
|
-
|
|
109
|
-
private _boundTheme?: State<string>;
|
|
110
|
-
private _boundStyleMode?: State<string>;
|
|
111
|
-
private _boundBorderRadius?: State<number>;
|
|
112
|
-
|
|
113
|
-
constructor(id: string, options: AreaChartOptions = {}) {
|
|
36
|
+
constructor(id: string, options: BarAreaChartOptions = {}) {
|
|
114
37
|
this._id = id;
|
|
115
38
|
this.id = id;
|
|
116
39
|
|
|
@@ -118,7 +41,6 @@ export class AreaChart {
|
|
|
118
41
|
'#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6',
|
|
119
42
|
'#ec4899', '#06b6d4', '#f97316', '#84cc16', '#6366f1'
|
|
120
43
|
];
|
|
121
|
-
// using defaultColors, select a random color from the list.
|
|
122
44
|
const randomColor = defaultColors[Math.floor(Math.random() * defaultColors.length)];
|
|
123
45
|
defaultColors = [randomColor];
|
|
124
46
|
|
|
@@ -140,8 +62,8 @@ export class AreaChart {
|
|
|
140
62
|
showDataLabels: options.showDataLabels ?? true,
|
|
141
63
|
animate: options.animate ?? true,
|
|
142
64
|
animationDuration: options.animationDuration ?? 800,
|
|
143
|
-
chartOrientation: options.chartOrientation ?? 'vertical',
|
|
144
|
-
chartDirection: options.chartDirection ?? 'normal',
|
|
65
|
+
chartOrientation: options.chartOrientation ?? 'vertical',
|
|
66
|
+
chartDirection: options.chartDirection ?? 'normal',
|
|
145
67
|
width: options.width ?? 600,
|
|
146
68
|
height: options.height ?? 400,
|
|
147
69
|
colors: options.colors ?? defaultColors,
|
|
@@ -153,54 +75,11 @@ export class AreaChart {
|
|
|
153
75
|
};
|
|
154
76
|
}
|
|
155
77
|
|
|
156
|
-
/* -------------------------
|
|
157
|
-
* State Binding Methods
|
|
158
|
-
* ------------------------- */
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Bind theme to reactive state
|
|
162
|
-
*/
|
|
163
|
-
bindTheme(stateObj: State<string>): this {
|
|
164
|
-
this._boundTheme = stateObj;
|
|
165
|
-
|
|
166
|
-
stateObj.subscribe((val) => {
|
|
167
|
-
this.theme(val as any);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
return this;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Bind styleMode to reactive state
|
|
175
|
-
*/
|
|
176
|
-
bindStyleMode(stateObj: State<string>): this {
|
|
177
|
-
this._boundStyleMode = stateObj;
|
|
178
|
-
|
|
179
|
-
stateObj.subscribe((val) => {
|
|
180
|
-
this.styleMode(val as any);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
return this;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Bind borderRadius to reactive state
|
|
188
|
-
*/
|
|
189
|
-
bindBorderRadius(stateObj: State<number>): this {
|
|
190
|
-
this._boundBorderRadius = stateObj;
|
|
191
|
-
|
|
192
|
-
stateObj.subscribe((val) => {
|
|
193
|
-
this.borderRadius(val);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
return this;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
78
|
/* -------------------------
|
|
200
79
|
* Fluent API
|
|
201
80
|
* ------------------------- */
|
|
202
81
|
|
|
203
|
-
data(value:
|
|
82
|
+
data(value: ChartDataPoint[]): this {
|
|
204
83
|
this.state.data = value;
|
|
205
84
|
this._updateChart();
|
|
206
85
|
return this;
|
|
@@ -242,37 +121,13 @@ export class AreaChart {
|
|
|
242
121
|
return this;
|
|
243
122
|
}
|
|
244
123
|
|
|
245
|
-
showScaleX(value: boolean): this {
|
|
246
|
-
this.state.showScaleX = value;
|
|
247
|
-
this._updateChart();
|
|
248
|
-
return this;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
showScaleY(value: boolean): this {
|
|
252
|
-
this.state.showScaleY = value;
|
|
253
|
-
this._updateChart();
|
|
254
|
-
return this;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
scaleXUnit(value: string): this {
|
|
258
|
-
this.state.scaleXUnit = value;
|
|
259
|
-
this._updateChart();
|
|
260
|
-
return this;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
scaleYUnit(value: string): this {
|
|
264
|
-
this.state.scaleYUnit = value;
|
|
265
|
-
this._updateChart();
|
|
266
|
-
return this;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
124
|
showLegend(value: boolean): this {
|
|
270
125
|
this.state.showLegend = value;
|
|
271
126
|
this._updateChart();
|
|
272
127
|
return this;
|
|
273
128
|
}
|
|
274
129
|
|
|
275
|
-
legendOrientation(value:
|
|
130
|
+
legendOrientation(value: LegendOrientation): this {
|
|
276
131
|
this.state.legendOrientation = value;
|
|
277
132
|
this._updateChart();
|
|
278
133
|
return this;
|
|
@@ -284,48 +139,31 @@ export class AreaChart {
|
|
|
284
139
|
return this;
|
|
285
140
|
}
|
|
286
141
|
|
|
287
|
-
/**
|
|
288
|
-
* Show/hide value labels on bars
|
|
289
|
-
*/
|
|
290
142
|
showDataLabels(value: boolean): this {
|
|
291
143
|
this.state.showDataLabels = value;
|
|
292
144
|
this._updateChart();
|
|
293
145
|
return this;
|
|
294
146
|
}
|
|
295
147
|
|
|
296
|
-
/**
|
|
297
|
-
* Enable/disable bar grow animation
|
|
298
|
-
*/
|
|
299
148
|
animate(value: boolean): this {
|
|
300
149
|
this.state.animate = value;
|
|
301
150
|
this._updateChart();
|
|
302
151
|
return this;
|
|
303
152
|
}
|
|
304
153
|
|
|
305
|
-
/**
|
|
306
|
-
* Set animation duration in milliseconds
|
|
307
|
-
*/
|
|
308
154
|
animationDuration(value: number): this {
|
|
309
155
|
this.state.animationDuration = value;
|
|
310
156
|
this._updateChart();
|
|
311
157
|
return this;
|
|
312
158
|
}
|
|
313
159
|
|
|
314
|
-
|
|
315
|
-
* Set chart orientation (vertical bars or horizontal bars)
|
|
316
|
-
*/
|
|
317
|
-
chartOrientation(value: 'vertical' | 'horizontal'): this {
|
|
160
|
+
chartOrientation(value: ChartOrientation): this {
|
|
318
161
|
this.state.chartOrientation = value;
|
|
319
162
|
this._updateChart();
|
|
320
163
|
return this;
|
|
321
164
|
}
|
|
322
165
|
|
|
323
|
-
|
|
324
|
-
* Set chart direction (normal or reverse)
|
|
325
|
-
* For vertical: normal = bottom-to-top, reverse = top-to-bottom
|
|
326
|
-
* For horizontal: normal = left-to-right, reverse = right-to-left
|
|
327
|
-
*/
|
|
328
|
-
chartDirection(value: 'normal' | 'reverse'): this {
|
|
166
|
+
chartDirection(value: ChartDirection): this {
|
|
329
167
|
this.state.chartDirection = value;
|
|
330
168
|
this._updateChart();
|
|
331
169
|
return this;
|
|
@@ -343,75 +181,169 @@ export class AreaChart {
|
|
|
343
181
|
return this;
|
|
344
182
|
}
|
|
345
183
|
|
|
346
|
-
|
|
347
|
-
this.state.
|
|
184
|
+
theme(value: ChartTheme): this {
|
|
185
|
+
this.state.theme = value;
|
|
186
|
+
this._applyTheme(value);
|
|
348
187
|
this._updateChart();
|
|
349
188
|
return this;
|
|
350
189
|
}
|
|
351
190
|
|
|
352
|
-
|
|
353
|
-
this.state.
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
style(value: string): this {
|
|
358
|
-
this.state.style = value;
|
|
191
|
+
styleMode(value: ChartStyleMode): this {
|
|
192
|
+
this.state.styleMode = value;
|
|
193
|
+
this._updateChart();
|
|
359
194
|
return this;
|
|
360
195
|
}
|
|
361
196
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
*/
|
|
365
|
-
theme(value: 'google' | 'seriesa' | 'hr' | 'figma' | 'notion' | 'chalk' | 'mint'): this {
|
|
366
|
-
this.state.theme = value;
|
|
367
|
-
this._applyTheme(value);
|
|
197
|
+
borderRadius(value: number): this {
|
|
198
|
+
this.state.borderRadius = value;
|
|
368
199
|
this._updateChart();
|
|
369
200
|
return this;
|
|
370
201
|
}
|
|
371
202
|
|
|
203
|
+
/* -------------------------
|
|
204
|
+
* Reactivity Support
|
|
205
|
+
* ------------------------- */
|
|
206
|
+
|
|
372
207
|
/**
|
|
373
|
-
*
|
|
208
|
+
* Sync a single property to a state object
|
|
374
209
|
*/
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
210
|
+
sync(property: string, stateObj: State<any>, toState?: Function, toComponent?: Function): this {
|
|
211
|
+
const transform = toComponent || ((v: any) => v);
|
|
212
|
+
|
|
213
|
+
stateObj.subscribe((val: any) => {
|
|
214
|
+
const transformed = transform(val);
|
|
215
|
+
|
|
216
|
+
// Map property to correct method
|
|
217
|
+
switch (property) {
|
|
218
|
+
case 'data': this.data(transformed); break;
|
|
219
|
+
case 'title': this.title(transformed); break;
|
|
220
|
+
case 'subtitle': this.subtitle(transformed); break;
|
|
221
|
+
case 'width': this.width(transformed); break;
|
|
222
|
+
case 'height': this.height(transformed); break;
|
|
223
|
+
case 'theme': this.theme(transformed); break;
|
|
224
|
+
case 'styleMode': this.styleMode(transformed); break;
|
|
225
|
+
case 'borderRadius': this.borderRadius(transformed); break;
|
|
226
|
+
case 'showTicksX': this.showTicksX(transformed); break;
|
|
227
|
+
case 'showTicksY': this.showTicksY(transformed); break;
|
|
228
|
+
case 'showLegend': this.showLegend(transformed); break;
|
|
229
|
+
case 'showDataLabels': this.showDataLabels(transformed); break;
|
|
230
|
+
case 'showDataTable': this.showDataTable(transformed); break;
|
|
231
|
+
case 'animate': this.animate(transformed); break;
|
|
232
|
+
case 'animationDuration': this.animationDuration(transformed); break;
|
|
233
|
+
case 'legendOrientation': this.legendOrientation(transformed); break;
|
|
234
|
+
case 'chartOrientation': this.chartOrientation(transformed); break;
|
|
235
|
+
case 'chartDirection': this.chartDirection(transformed); break;
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
378
239
|
return this;
|
|
379
240
|
}
|
|
380
241
|
|
|
381
242
|
/**
|
|
382
|
-
*
|
|
243
|
+
* Sync multiple properties from a state object
|
|
244
|
+
*
|
|
245
|
+
* @param stateObject - Object containing State instances for each property
|
|
246
|
+
* @param mapping - Optional mapping of state keys to component method names
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* // Auto-mapping (state keys match method names)
|
|
250
|
+
* chart.syncState(chartStates);
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* // Custom mapping
|
|
254
|
+
* chart.syncState(chartStates, {
|
|
255
|
+
* chartTheme: 'theme',
|
|
256
|
+
* chartTitle: 'title',
|
|
257
|
+
* chartWidth: 'width'
|
|
258
|
+
* });
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* // Function mapping for transforms
|
|
262
|
+
* chart.syncState(chartStates, {
|
|
263
|
+
* chartWidth: (value) => chart.width(Number(value))
|
|
264
|
+
* });
|
|
383
265
|
*/
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
266
|
+
syncState(stateObject: ChartStateObject, mapping?: ChartPropertyMapping): this {
|
|
267
|
+
// Default mapping: camelCase state names to method names
|
|
268
|
+
const defaultMapping: ChartPropertyMapping = {
|
|
269
|
+
chartType: 'type', // Not used in area chart, ignored
|
|
270
|
+
chartTheme: 'theme',
|
|
271
|
+
chartStyleMode: 'styleMode',
|
|
272
|
+
borderRadius: 'borderRadius',
|
|
273
|
+
chartTitle: 'title',
|
|
274
|
+
chartWidth: 'width',
|
|
275
|
+
chartHeight: 'height',
|
|
276
|
+
showTicksX: 'showTicksX',
|
|
277
|
+
showTicksY: 'showTicksY',
|
|
278
|
+
showLegend: 'showLegend',
|
|
279
|
+
showDataTable: 'showDataTable',
|
|
280
|
+
showDataLabels: 'showDataLabels',
|
|
281
|
+
animate: 'animate',
|
|
282
|
+
animationDuration: 'animationDuration',
|
|
283
|
+
legendOrientation: 'legendOrientation',
|
|
284
|
+
chartOrientation: 'chartOrientation',
|
|
285
|
+
chartDirection: 'chartDirection'
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const finalMapping = { ...defaultMapping, ...mapping };
|
|
289
|
+
|
|
290
|
+
// Iterate through state object and bind each property
|
|
291
|
+
Object.entries(stateObject).forEach(([key, stateObj]) => {
|
|
292
|
+
if (!stateObj || typeof stateObj.subscribe !== 'function') {
|
|
293
|
+
console.warn(`AreaChart.syncState: "${key}" is not a valid State object`);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const methodOrFunction = finalMapping[key];
|
|
298
|
+
|
|
299
|
+
if (!methodOrFunction) {
|
|
300
|
+
console.warn(`AreaChart.syncState: No mapping found for "${key}"`);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (typeof methodOrFunction === 'function') {
|
|
305
|
+
// Custom function mapping
|
|
306
|
+
stateObj.subscribe(methodOrFunction);
|
|
307
|
+
} else {
|
|
308
|
+
// String mapping to method name
|
|
309
|
+
const methodName = methodOrFunction as keyof this;
|
|
310
|
+
const method = this[methodName];
|
|
311
|
+
|
|
312
|
+
if (typeof method !== 'function') {
|
|
313
|
+
console.warn(`AreaChart.syncState: Method "${String(methodName)}" not found`);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
stateObj.subscribe((val: any) => {
|
|
318
|
+
(method as Function).call(this, val);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
387
323
|
return this;
|
|
388
324
|
}
|
|
389
325
|
|
|
390
326
|
/* -------------------------
|
|
391
|
-
*
|
|
327
|
+
* Internal Methods
|
|
392
328
|
* ------------------------- */
|
|
393
329
|
|
|
394
330
|
private _updateChart(): void {
|
|
395
331
|
if (!this.container) return;
|
|
396
332
|
|
|
397
|
-
// Find the wrapper div
|
|
398
333
|
const wrapper = this.container.querySelector(`#${this._id}`) as HTMLElement;
|
|
399
334
|
if (!wrapper) return;
|
|
400
335
|
|
|
401
|
-
// Clear and rebuild
|
|
402
336
|
wrapper.innerHTML = '';
|
|
403
337
|
this._buildChart(wrapper);
|
|
404
338
|
|
|
405
|
-
// Reapply theme after rebuild
|
|
406
339
|
if (this.state.theme) {
|
|
407
340
|
this._applyThemeToWrapper(wrapper);
|
|
408
341
|
}
|
|
409
342
|
}
|
|
410
343
|
|
|
411
344
|
private _buildChart(wrapper: HTMLElement): void {
|
|
412
|
-
const {
|
|
345
|
+
const { title, subtitle, showLegend, showDataTable } = this.state;
|
|
413
346
|
|
|
414
|
-
// Title
|
|
415
347
|
if (title) {
|
|
416
348
|
const titleEl = document.createElement('h3');
|
|
417
349
|
titleEl.className = 'jux-areachart-title';
|
|
@@ -419,7 +351,6 @@ export class AreaChart {
|
|
|
419
351
|
wrapper.appendChild(titleEl);
|
|
420
352
|
}
|
|
421
353
|
|
|
422
|
-
// Subtitle
|
|
423
354
|
if (subtitle) {
|
|
424
355
|
const subtitleEl = document.createElement('p');
|
|
425
356
|
subtitleEl.className = 'jux-areachart-subtitle';
|
|
@@ -427,19 +358,21 @@ export class AreaChart {
|
|
|
427
358
|
wrapper.appendChild(subtitleEl);
|
|
428
359
|
}
|
|
429
360
|
|
|
430
|
-
// SVG Chart
|
|
431
361
|
const svg = this._createSVG();
|
|
432
362
|
wrapper.appendChild(svg);
|
|
433
363
|
|
|
434
|
-
// Legend
|
|
435
364
|
if (showLegend) {
|
|
436
|
-
const legend = this.
|
|
365
|
+
const legend = createLegend(this.state.data, this.state.colors, 'jux-areachart');
|
|
437
366
|
wrapper.appendChild(legend);
|
|
438
367
|
}
|
|
439
368
|
|
|
440
|
-
// Data Table
|
|
441
369
|
if (showDataTable) {
|
|
442
|
-
const table =
|
|
370
|
+
const table = createDataTable(
|
|
371
|
+
this.state.data,
|
|
372
|
+
this.state.xAxisLabel,
|
|
373
|
+
this.state.yAxisLabel,
|
|
374
|
+
'jux-areachart'
|
|
375
|
+
);
|
|
443
376
|
wrapper.appendChild(table);
|
|
444
377
|
}
|
|
445
378
|
}
|
|
@@ -540,7 +473,7 @@ export class AreaChart {
|
|
|
540
473
|
|
|
541
474
|
private _renderVerticalBars(
|
|
542
475
|
svg: SVGSVGElement,
|
|
543
|
-
data:
|
|
476
|
+
data: ChartDataPoint[],
|
|
544
477
|
colors: string[],
|
|
545
478
|
padding: { top: number, right: number, bottom: number, left: number },
|
|
546
479
|
chartWidth: number,
|
|
@@ -657,7 +590,7 @@ export class AreaChart {
|
|
|
657
590
|
|
|
658
591
|
private _renderHorizontalBars(
|
|
659
592
|
svg: SVGSVGElement,
|
|
660
|
-
data:
|
|
593
|
+
data: ChartDataPoint[],
|
|
661
594
|
colors: string[],
|
|
662
595
|
padding: { top: number, right: number, bottom: number, left: number },
|
|
663
596
|
chartWidth: number,
|
|
@@ -799,7 +732,7 @@ export class AreaChart {
|
|
|
799
732
|
height: number,
|
|
800
733
|
color: string,
|
|
801
734
|
index: number,
|
|
802
|
-
point:
|
|
735
|
+
point: ChartDataPoint,
|
|
803
736
|
labelPosition: 'top' | 'bottom' | 'left' | 'right',
|
|
804
737
|
isHorizontal: boolean = false
|
|
805
738
|
): void {
|
|
@@ -823,8 +756,8 @@ export class AreaChart {
|
|
|
823
756
|
rect.setAttribute('y', y.toString());
|
|
824
757
|
rect.setAttribute('width', width.toString());
|
|
825
758
|
rect.setAttribute('height', height.toString());
|
|
826
|
-
|
|
827
|
-
|
|
759
|
+
// rect.setAttribute('rx', borderRadius.toString());
|
|
760
|
+
// rect.setAttribute('ry', borderRadius.toString());
|
|
828
761
|
|
|
829
762
|
if (!shouldUseGroup && animate) {
|
|
830
763
|
rect.classList.add('jux-bar-animated');
|
|
@@ -1042,71 +975,20 @@ export class AreaChart {
|
|
|
1042
975
|
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
|
|
1043
976
|
}
|
|
1044
977
|
|
|
1045
|
-
private _applyTheme(themeName:
|
|
1046
|
-
const
|
|
1047
|
-
google: googleTheme,
|
|
1048
|
-
seriesa: seriesaTheme,
|
|
1049
|
-
hr: hrTheme,
|
|
1050
|
-
figma: figmaTheme,
|
|
1051
|
-
notion: notionTheme,
|
|
1052
|
-
chalk: chalkTheme,
|
|
1053
|
-
mint: mintTheme
|
|
1054
|
-
};
|
|
1055
|
-
|
|
1056
|
-
const theme = themes[themeName];
|
|
978
|
+
private _applyTheme(themeName: ChartTheme): void {
|
|
979
|
+
const theme = getThemeConfig(themeName);
|
|
1057
980
|
if (!theme) return;
|
|
1058
981
|
|
|
1059
|
-
// Apply colors
|
|
1060
|
-
// get one color;
|
|
1061
982
|
const randomColor = theme.colors[Math.floor(Math.random() * theme.colors.length)];
|
|
1062
983
|
this.state.colors = [randomColor];
|
|
1063
984
|
|
|
1064
|
-
|
|
1065
|
-
const baseStyleId = 'jux-areachart-base-styles';
|
|
1066
|
-
if (!document.getElementById(baseStyleId)) {
|
|
1067
|
-
const style = document.createElement('style');
|
|
1068
|
-
style.id = baseStyleId;
|
|
1069
|
-
style.textContent = this._getBaseStyles();
|
|
1070
|
-
document.head.appendChild(style);
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
// Inject font (once per theme)
|
|
1074
|
-
if (theme.font && !document.querySelector(`link[href="${theme.font}"]`)) {
|
|
1075
|
-
const link = document.createElement('link');
|
|
1076
|
-
link.rel = 'stylesheet';
|
|
1077
|
-
link.href = theme.font;
|
|
1078
|
-
document.head.appendChild(link);
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
// Apply theme-specific styles
|
|
1082
|
-
const styleId = `jux-areachart-theme-${themeName}`;
|
|
1083
|
-
let styleElement = document.getElementById(styleId) as HTMLStyleElement;
|
|
1084
|
-
|
|
1085
|
-
if (!styleElement) {
|
|
1086
|
-
styleElement = document.createElement('style');
|
|
1087
|
-
styleElement.id = styleId;
|
|
1088
|
-
document.head.appendChild(styleElement);
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
// Generate CSS with theme variables
|
|
1092
|
-
const variablesCSS = Object.entries(theme.variables)
|
|
1093
|
-
.map(([key, value]) => ` ${key}: ${value};`)
|
|
1094
|
-
.join('\n');
|
|
1095
|
-
|
|
1096
|
-
styleElement.textContent = `
|
|
1097
|
-
.jux-areachart.theme-${themeName} {
|
|
1098
|
-
${variablesCSS}
|
|
1099
|
-
}
|
|
1100
|
-
`;
|
|
985
|
+
applyThemeStyles(themeName, 'jux-areachart', this._getBaseStyles());
|
|
1101
986
|
}
|
|
1102
987
|
|
|
1103
988
|
private _applyThemeToWrapper(wrapper: HTMLElement): void {
|
|
1104
989
|
if (!this.state.theme) return;
|
|
1105
990
|
|
|
1106
|
-
// Remove old theme classes
|
|
1107
991
|
wrapper.classList.remove('theme-google', 'theme-seriesa', 'theme-hr', 'theme-figma', 'theme-notion', 'theme-chalk', 'theme-mint');
|
|
1108
|
-
|
|
1109
|
-
// Add new theme class
|
|
1110
992
|
wrapper.classList.add(`theme-${this.state.theme}`);
|
|
1111
993
|
}
|
|
1112
994
|
|
|
@@ -1241,6 +1123,6 @@ ${variablesCSS}
|
|
|
1241
1123
|
}
|
|
1242
1124
|
}
|
|
1243
1125
|
|
|
1244
|
-
export function areachart(id: string, options:
|
|
1126
|
+
export function areachart(id: string, options: BarAreaChartOptions = {}): AreaChart {
|
|
1245
1127
|
return new AreaChart(id, options);
|
|
1246
1128
|
}
|
|
@@ -921,7 +921,7 @@ export class AreaChartSmooth {
|
|
|
921
921
|
|
|
922
922
|
// Calculate control points for smooth curve
|
|
923
923
|
const tension = 0.3;
|
|
924
|
-
|
|
924
|
+
|
|
925
925
|
if (isHorizontal) {
|
|
926
926
|
const cp1x = current.x + (next.x - prev.x) * tension;
|
|
927
927
|
const cp1y = current.y;
|
|
@@ -1006,7 +1006,7 @@ export class AreaChartSmooth {
|
|
|
1006
1006
|
} else if (styleMode === 'glow') {
|
|
1007
1007
|
area.setAttribute('fill', color);
|
|
1008
1008
|
area.setAttribute('fill-opacity', '0.3');
|
|
1009
|
-
|
|
1009
|
+
|
|
1010
1010
|
const filterId = `glow-area-${this._id}`;
|
|
1011
1011
|
const defs = svg.querySelector('defs') || document.createElementNS('http://www.w3.org/2000/svg', 'defs');
|
|
1012
1012
|
if (!svg.querySelector('defs')) {
|