juxscript 1.0.19 → 1.0.21

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 (77) hide show
  1. package/bin/cli.js +121 -72
  2. package/lib/components/alert.ts +212 -165
  3. package/lib/components/badge.ts +93 -103
  4. package/lib/components/base/BaseComponent.ts +397 -0
  5. package/lib/components/base/FormInput.ts +322 -0
  6. package/lib/components/button.ts +63 -122
  7. package/lib/components/card.ts +109 -155
  8. package/lib/components/charts/areachart.ts +315 -0
  9. package/lib/components/charts/barchart.ts +421 -0
  10. package/lib/components/charts/doughnutchart.ts +263 -0
  11. package/lib/components/charts/lib/BaseChart.ts +402 -0
  12. package/lib/components/charts/lib/chart-types.ts +159 -0
  13. package/lib/components/charts/lib/chart-utils.ts +160 -0
  14. package/lib/components/charts/lib/chart.ts +707 -0
  15. package/lib/components/checkbox.ts +264 -127
  16. package/lib/components/code.ts +75 -108
  17. package/lib/components/container.ts +113 -130
  18. package/lib/components/data.ts +37 -5
  19. package/lib/components/datepicker.ts +195 -147
  20. package/lib/components/dialog.ts +187 -157
  21. package/lib/components/divider.ts +85 -191
  22. package/lib/components/docs-data.json +544 -2027
  23. package/lib/components/dropdown.ts +178 -136
  24. package/lib/components/element.ts +227 -171
  25. package/lib/components/fileupload.ts +285 -228
  26. package/lib/components/guard.ts +92 -0
  27. package/lib/components/heading.ts +46 -69
  28. package/lib/components/helpers.ts +13 -6
  29. package/lib/components/hero.ts +107 -95
  30. package/lib/components/icon.ts +160 -0
  31. package/lib/components/icons.ts +175 -0
  32. package/lib/components/include.ts +153 -5
  33. package/lib/components/input.ts +174 -374
  34. package/lib/components/kpicard.ts +16 -16
  35. package/lib/components/list.ts +378 -240
  36. package/lib/components/loading.ts +142 -211
  37. package/lib/components/menu.ts +103 -97
  38. package/lib/components/modal.ts +138 -144
  39. package/lib/components/nav.ts +169 -90
  40. package/lib/components/paragraph.ts +49 -150
  41. package/lib/components/progress.ts +118 -200
  42. package/lib/components/radio.ts +297 -149
  43. package/lib/components/script.ts +19 -87
  44. package/lib/components/select.ts +184 -186
  45. package/lib/components/sidebar.ts +152 -140
  46. package/lib/components/style.ts +19 -82
  47. package/lib/components/switch.ts +258 -188
  48. package/lib/components/table.ts +1117 -170
  49. package/lib/components/tabs.ts +162 -145
  50. package/lib/components/theme-toggle.ts +108 -169
  51. package/lib/components/tooltip.ts +86 -157
  52. package/lib/components/write.ts +108 -127
  53. package/lib/jux.ts +86 -41
  54. package/machinery/build.js +466 -0
  55. package/machinery/compiler.js +354 -105
  56. package/machinery/server.js +23 -100
  57. package/machinery/watcher.js +153 -130
  58. package/package.json +1 -2
  59. package/presets/base.css +1166 -0
  60. package/presets/notion.css +2 -1975
  61. package/lib/adapters/base-adapter.js +0 -35
  62. package/lib/adapters/index.js +0 -33
  63. package/lib/adapters/mysql-adapter.js +0 -65
  64. package/lib/adapters/postgres-adapter.js +0 -70
  65. package/lib/adapters/sqlite-adapter.js +0 -56
  66. package/lib/components/areachart.ts +0 -1246
  67. package/lib/components/areachartsmooth.ts +0 -1380
  68. package/lib/components/barchart.ts +0 -1250
  69. package/lib/components/chart.ts +0 -127
  70. package/lib/components/doughnutchart.ts +0 -1191
  71. package/lib/components/footer.ts +0 -165
  72. package/lib/components/header.ts +0 -187
  73. package/lib/components/layout.ts +0 -239
  74. package/lib/components/main.ts +0 -137
  75. package/lib/layouts/default.jux +0 -8
  76. package/lib/layouts/figma.jux +0 -0
  77. /package/lib/{themes → components/charts/lib}/charts.js +0 -0
@@ -1,1246 +0,0 @@
1
- import { getOrCreateContainer } from './helpers.js';
2
- import { State } from '../reactivity/state.js';
3
- import {
4
- googleTheme,
5
- seriesaTheme,
6
- hrTheme,
7
- figmaTheme,
8
- notionTheme,
9
- chalkTheme,
10
- mintTheme
11
- } from '../themes/charts.js';
12
-
13
- /**
14
- * Bar chart data point
15
- */
16
- export interface AreaChartDataPoint {
17
- label: string;
18
- value: number;
19
- color?: string;
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
- }
54
-
55
- /**
56
- * Bar chart state
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
- };
87
-
88
- /**
89
- * Bar chart component - Simple SVG-based bar chart
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');
101
- */
102
- export class AreaChart {
103
- state: AreaChartState;
104
- container: HTMLElement | null = null;
105
- _id: string;
106
- id: string;
107
-
108
- // State bindings
109
- private _boundTheme?: State<string>;
110
- private _boundStyleMode?: State<string>;
111
- private _boundBorderRadius?: State<number>;
112
-
113
- constructor(id: string, options: AreaChartOptions = {}) {
114
- this._id = id;
115
- this.id = id;
116
-
117
- let defaultColors = [
118
- '#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6',
119
- '#ec4899', '#06b6d4', '#f97316', '#84cc16', '#6366f1'
120
- ];
121
- // using defaultColors, select a random color from the list.
122
- const randomColor = defaultColors[Math.floor(Math.random() * defaultColors.length)];
123
- defaultColors = [randomColor];
124
-
125
- this.state = {
126
- data: options.data ?? [],
127
- title: options.title ?? '',
128
- subtitle: options.subtitle ?? '',
129
- xAxisLabel: options.xAxisLabel ?? '',
130
- yAxisLabel: options.yAxisLabel ?? '',
131
- showTicksX: options.showTicksX ?? true,
132
- showTicksY: options.showTicksY ?? true,
133
- showScaleX: options.showScaleX ?? true,
134
- showScaleY: options.showScaleY ?? true,
135
- scaleXUnit: options.scaleXUnit ?? '',
136
- scaleYUnit: options.scaleYUnit ?? '',
137
- showLegend: options.showLegend ?? false,
138
- legendOrientation: options.legendOrientation ?? 'horizontal',
139
- showDataTable: options.showDataTable ?? false,
140
- showDataLabels: options.showDataLabels ?? true,
141
- animate: options.animate ?? true,
142
- animationDuration: options.animationDuration ?? 800,
143
- chartOrientation: options.chartOrientation ?? 'vertical', // NEW
144
- chartDirection: options.chartDirection ?? 'normal', // NEW
145
- width: options.width ?? 600,
146
- height: options.height ?? 400,
147
- colors: options.colors ?? defaultColors,
148
- class: options.class ?? '',
149
- style: options.style ?? '',
150
- theme: options.theme,
151
- styleMode: options.styleMode ?? 'default',
152
- borderRadius: options.borderRadius ?? 4
153
- };
154
- }
155
-
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
- /* -------------------------
200
- * Fluent API
201
- * ------------------------- */
202
-
203
- data(value: AreaChartDataPoint[]): this {
204
- this.state.data = value;
205
- this._updateChart();
206
- return this;
207
- }
208
-
209
- title(value: string): this {
210
- this.state.title = value;
211
- this._updateChart();
212
- return this;
213
- }
214
-
215
- subtitle(value: string): this {
216
- this.state.subtitle = value;
217
- this._updateChart();
218
- return this;
219
- }
220
-
221
- xAxisLabel(value: string): this {
222
- this.state.xAxisLabel = value;
223
- this._updateChart();
224
- return this;
225
- }
226
-
227
- yAxisLabel(value: string): this {
228
- this.state.yAxisLabel = value;
229
- this._updateChart();
230
- return this;
231
- }
232
-
233
- showTicksX(value: boolean): this {
234
- this.state.showTicksX = value;
235
- this._updateChart();
236
- return this;
237
- }
238
-
239
- showTicksY(value: boolean): this {
240
- this.state.showTicksY = value;
241
- this._updateChart();
242
- return this;
243
- }
244
-
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
- showLegend(value: boolean): this {
270
- this.state.showLegend = value;
271
- this._updateChart();
272
- return this;
273
- }
274
-
275
- legendOrientation(value: 'horizontal' | 'vertical'): this {
276
- this.state.legendOrientation = value;
277
- this._updateChart();
278
- return this;
279
- }
280
-
281
- showDataTable(value: boolean): this {
282
- this.state.showDataTable = value;
283
- this._updateChart();
284
- return this;
285
- }
286
-
287
- /**
288
- * Show/hide value labels on bars
289
- */
290
- showDataLabels(value: boolean): this {
291
- this.state.showDataLabels = value;
292
- this._updateChart();
293
- return this;
294
- }
295
-
296
- /**
297
- * Enable/disable bar grow animation
298
- */
299
- animate(value: boolean): this {
300
- this.state.animate = value;
301
- this._updateChart();
302
- return this;
303
- }
304
-
305
- /**
306
- * Set animation duration in milliseconds
307
- */
308
- animationDuration(value: number): this {
309
- this.state.animationDuration = value;
310
- this._updateChart();
311
- return this;
312
- }
313
-
314
- /**
315
- * Set chart orientation (vertical bars or horizontal bars)
316
- */
317
- chartOrientation(value: 'vertical' | 'horizontal'): this {
318
- this.state.chartOrientation = value;
319
- this._updateChart();
320
- return this;
321
- }
322
-
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 {
329
- this.state.chartDirection = value;
330
- this._updateChart();
331
- return this;
332
- }
333
-
334
- width(value: number): this {
335
- this.state.width = value;
336
- this._updateChart();
337
- return this;
338
- }
339
-
340
- height(value: number): this {
341
- this.state.height = value;
342
- this._updateChart();
343
- return this;
344
- }
345
-
346
- colors(value: string[]): this {
347
- this.state.colors = value;
348
- this._updateChart();
349
- return this;
350
- }
351
-
352
- class(value: string): this {
353
- this.state.class = value;
354
- return this;
355
- }
356
-
357
- style(value: string): this {
358
- this.state.style = value;
359
- return this;
360
- }
361
-
362
- /**
363
- * Set chart theme
364
- */
365
- theme(value: 'google' | 'seriesa' | 'hr' | 'figma' | 'notion' | 'chalk' | 'mint'): this {
366
- this.state.theme = value;
367
- this._applyTheme(value);
368
- this._updateChart();
369
- return this;
370
- }
371
-
372
- /**
373
- * Set bar style mode
374
- */
375
- styleMode(value: 'default' | 'gradient' | 'glow' | 'glass'): this {
376
- this.state.styleMode = value;
377
- this._updateChart();
378
- return this;
379
- }
380
-
381
- /**
382
- * Set border radius for bars (0 = sharp corners, higher = rounder)
383
- */
384
- borderRadius(value: number): this {
385
- this.state.borderRadius = value;
386
- this._updateChart();
387
- return this;
388
- }
389
-
390
- /* -------------------------
391
- * Update chart
392
- * ------------------------- */
393
-
394
- private _updateChart(): void {
395
- if (!this.container) return;
396
-
397
- // Find the wrapper div
398
- const wrapper = this.container.querySelector(`#${this._id}`) as HTMLElement;
399
- if (!wrapper) return;
400
-
401
- // Clear and rebuild
402
- wrapper.innerHTML = '';
403
- this._buildChart(wrapper);
404
-
405
- // Reapply theme after rebuild
406
- if (this.state.theme) {
407
- this._applyThemeToWrapper(wrapper);
408
- }
409
- }
410
-
411
- private _buildChart(wrapper: HTMLElement): void {
412
- const { data, title, subtitle, width, height, showLegend, showDataTable } = this.state;
413
-
414
- // Title
415
- if (title) {
416
- const titleEl = document.createElement('h3');
417
- titleEl.className = 'jux-areachart-title';
418
- titleEl.textContent = title;
419
- wrapper.appendChild(titleEl);
420
- }
421
-
422
- // Subtitle
423
- if (subtitle) {
424
- const subtitleEl = document.createElement('p');
425
- subtitleEl.className = 'jux-areachart-subtitle';
426
- subtitleEl.textContent = subtitle;
427
- wrapper.appendChild(subtitleEl);
428
- }
429
-
430
- // SVG Chart
431
- const svg = this._createSVG();
432
- wrapper.appendChild(svg);
433
-
434
- // Legend
435
- if (showLegend) {
436
- const legend = this._createLegend();
437
- wrapper.appendChild(legend);
438
- }
439
-
440
- // Data Table
441
- if (showDataTable) {
442
- const table = this._createDataTable();
443
- wrapper.appendChild(table);
444
- }
445
- }
446
-
447
- private _createSVG(): SVGSVGElement {
448
- const {
449
- data, width, height, colors, xAxisLabel, yAxisLabel,
450
- showTicksX, showTicksY, showScaleX, showScaleY, scaleYUnit,
451
- styleMode, borderRadius, showDataLabels, animate, animationDuration,
452
- chartOrientation, chartDirection
453
- } = this.state;
454
-
455
- if (!data.length) {
456
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
457
- svg.setAttribute('width', width.toString());
458
- svg.setAttribute('height', height.toString());
459
- svg.setAttribute('class', 'jux-areachart-svg');
460
- return svg;
461
- }
462
-
463
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
464
- svg.setAttribute('width', width.toString());
465
- svg.setAttribute('height', height.toString());
466
- svg.setAttribute('class', 'jux-areachart-svg');
467
-
468
- // Add animation styles to SVG
469
- if (animate) {
470
- const animationId = `bar-grow-${this._id}`;
471
- const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
472
-
473
- // Different animation based on orientation and direction
474
- let transformOrigin = 'bottom';
475
- let scaleAxis = 'scaleY';
476
-
477
- if (chartOrientation === 'horizontal') {
478
- if (chartDirection === 'normal') {
479
- transformOrigin = 'left';
480
- scaleAxis = 'scaleX';
481
- } else {
482
- transformOrigin = 'right';
483
- scaleAxis = 'scaleX';
484
- }
485
- } else {
486
- if (chartDirection === 'reverse') {
487
- transformOrigin = 'top';
488
- scaleAxis = 'scaleY';
489
- }
490
- }
491
-
492
- style.textContent = `
493
- @keyframes ${animationId} {
494
- from {
495
- transform: ${scaleAxis}(0);
496
- opacity: 0;
497
- }
498
- to {
499
- transform: ${scaleAxis}(1);
500
- opacity: 1;
501
- }
502
- }
503
- .jux-bar-animated {
504
- transform-origin: ${transformOrigin};
505
- animation: ${animationId} ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
506
- }
507
- .jux-label-animated {
508
- opacity: 0;
509
- animation: fadeIn ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
510
- }
511
- @keyframes fadeIn {
512
- from { opacity: 0; }
513
- to { opacity: 1; }
514
- }
515
- `;
516
- svg.appendChild(style);
517
- }
518
-
519
- // Calculate dimensions
520
- const padding = { top: 40, right: 40, bottom: 60, left: 60 };
521
- const chartWidth = width - padding.left - padding.right;
522
- const chartHeight = height - padding.top - padding.bottom;
523
-
524
- const maxValue = Math.max(...data.map(d => d.value));
525
-
526
- // Determine if we're working with vertical or horizontal layout
527
- const isVertical = chartOrientation === 'vertical';
528
- const isReverse = chartDirection === 'reverse';
529
-
530
- if (isVertical) {
531
- // VERTICAL BARS (original logic with direction support)
532
- this._renderVerticalBars(svg, data, colors, padding, chartWidth, chartHeight, maxValue, isReverse);
533
- } else {
534
- // HORIZONTAL BARS (new logic)
535
- this._renderHorizontalBars(svg, data, colors, padding, chartWidth, chartHeight, maxValue, isReverse);
536
- }
537
-
538
- return svg;
539
- }
540
-
541
- private _renderVerticalBars(
542
- svg: SVGSVGElement,
543
- data: AreaChartDataPoint[],
544
- colors: string[],
545
- padding: { top: number, right: number, bottom: number, left: number },
546
- chartWidth: number,
547
- chartHeight: number,
548
- maxValue: number,
549
- isReverse: boolean
550
- ): void {
551
- const { width, height, xAxisLabel, yAxisLabel, showTicksX, showTicksY, showScaleX, showScaleY, scaleYUnit, styleMode, borderRadius, showDataLabels, animate, animationDuration } = this.state;
552
-
553
- const yScale = chartHeight / maxValue;
554
- const barWidth = chartWidth / data.length;
555
- const barGap = barWidth * 0;
556
- const actualBarWidth = barWidth - barGap;
557
-
558
- // Y-axis
559
- if (showScaleY) {
560
- const yAxis = document.createElementNS('http://www.w3.org/2000/svg', 'line');
561
- yAxis.setAttribute('x1', padding.left.toString());
562
- yAxis.setAttribute('y1', padding.top.toString());
563
- yAxis.setAttribute('x2', padding.left.toString());
564
- yAxis.setAttribute('y2', (height - padding.bottom).toString());
565
- yAxis.setAttribute('stroke', '#9ca3af');
566
- yAxis.setAttribute('stroke-width', '2');
567
- svg.appendChild(yAxis);
568
-
569
- // Y-axis label
570
- if (yAxisLabel && showTicksY) {
571
- const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
572
- label.setAttribute('x', '20');
573
- label.setAttribute('y', (padding.top + chartHeight / 2).toString());
574
- label.setAttribute('text-anchor', 'middle');
575
- label.setAttribute('transform', `rotate(-90, 20, ${padding.top + chartHeight / 2})`);
576
- label.setAttribute('fill', '#6b7280');
577
- label.setAttribute('font-size', '12');
578
- label.setAttribute('font-weight', '500');
579
- label.setAttribute('font-family', 'inherit');
580
- label.textContent = yAxisLabel;
581
- svg.appendChild(label);
582
- }
583
-
584
- // Y-axis ticks
585
- if (showTicksY) {
586
- const numTicks = 5;
587
- for (let i = 0; i <= numTicks; i++) {
588
- const value = (maxValue / numTicks) * i;
589
- const y = isReverse
590
- ? padding.top + (value * yScale)
591
- : height - padding.bottom - (value * yScale);
592
-
593
- // Grid line
594
- const gridLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
595
- gridLine.setAttribute('x1', padding.left.toString());
596
- gridLine.setAttribute('y1', y.toString());
597
- gridLine.setAttribute('x2', (width - padding.right).toString());
598
- gridLine.setAttribute('y2', y.toString());
599
- gridLine.setAttribute('stroke', '#e5e7eb');
600
- gridLine.setAttribute('stroke-width', '1');
601
- gridLine.setAttribute('stroke-dasharray', '4,4');
602
- svg.appendChild(gridLine);
603
-
604
- // Tick label
605
- const tickLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
606
- tickLabel.setAttribute('x', (padding.left - 10).toString());
607
- tickLabel.setAttribute('y', (y + 4).toString());
608
- tickLabel.setAttribute('text-anchor', 'end');
609
- tickLabel.setAttribute('fill', '#6b7280');
610
- tickLabel.setAttribute('font-size', '11');
611
- tickLabel.setAttribute('font-family', 'inherit');
612
- tickLabel.textContent = Math.round(value).toString() + (scaleYUnit || '');
613
- svg.appendChild(tickLabel);
614
- }
615
- }
616
- }
617
-
618
- // X-axis
619
- if (showScaleX) {
620
- const xAxis = document.createElementNS('http://www.w3.org/2000/svg', 'line');
621
- const axisY = isReverse ? padding.top : height - padding.bottom;
622
- xAxis.setAttribute('x1', padding.left.toString());
623
- xAxis.setAttribute('y1', axisY.toString());
624
- xAxis.setAttribute('x2', (width - padding.right).toString());
625
- xAxis.setAttribute('y2', axisY.toString());
626
- xAxis.setAttribute('stroke', '#9ca3af');
627
- xAxis.setAttribute('stroke-width', '2');
628
- svg.appendChild(xAxis);
629
-
630
- // X-axis label
631
- if (xAxisLabel && showTicksX) {
632
- const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
633
- label.setAttribute('x', (padding.left + chartWidth / 2).toString());
634
- label.setAttribute('y', (height - 15).toString());
635
- label.setAttribute('text-anchor', 'middle');
636
- label.setAttribute('fill', '#6b7280');
637
- label.setAttribute('font-size', '12');
638
- label.setAttribute('font-weight', '500');
639
- label.setAttribute('font-family', 'inherit');
640
- label.textContent = xAxisLabel;
641
- svg.appendChild(label);
642
- }
643
- }
644
-
645
- // Bars
646
- data.forEach((point, index) => {
647
- const x = padding.left + (index * barWidth) + (barGap / 2);
648
- const barHeight = point.value * yScale;
649
- const y = isReverse
650
- ? padding.top
651
- : height - padding.bottom - barHeight;
652
- const color = point.color || colors[index % colors.length];
653
-
654
- this._renderBar(svg, x, y, actualBarWidth, barHeight, color, index, point, isReverse ? 'bottom' : 'top');
655
- });
656
- }
657
-
658
- private _renderHorizontalBars(
659
- svg: SVGSVGElement,
660
- data: AreaChartDataPoint[],
661
- colors: string[],
662
- padding: { top: number, right: number, bottom: number, left: number },
663
- chartWidth: number,
664
- chartHeight: number,
665
- maxValue: number,
666
- isReverse: boolean
667
- ): void {
668
- const { width, height, xAxisLabel, yAxisLabel, showTicksX, showTicksY, showScaleX, showScaleY, scaleXUnit, styleMode, borderRadius, showDataLabels, animate, animationDuration } = this.state;
669
-
670
- const xScale = chartWidth / maxValue;
671
- const barHeight = chartHeight / data.length;
672
- const barGap = barHeight * 0.2;
673
- const actualBarHeight = barHeight - barGap;
674
-
675
- // X-axis (now the value axis) - use yAxisLabel since values are horizontal
676
- if (showScaleX) {
677
- const xAxis = document.createElementNS('http://www.w3.org/2000/svg', 'line');
678
- const axisX = isReverse ? width - padding.right : padding.left;
679
- xAxis.setAttribute('x1', axisX.toString());
680
- xAxis.setAttribute('y1', padding.top.toString());
681
- xAxis.setAttribute('x2', axisX.toString());
682
- xAxis.setAttribute('y2', (height - padding.bottom).toString());
683
- xAxis.setAttribute('stroke', '#9ca3af');
684
- xAxis.setAttribute('stroke-width', '2');
685
- svg.appendChild(xAxis);
686
-
687
- // X-axis label (use yAxisLabel for values in horizontal mode)
688
- if (yAxisLabel && showTicksX) {
689
- const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
690
- label.setAttribute('x', (padding.left + chartWidth / 2).toString());
691
- label.setAttribute('y', (height - 15).toString());
692
- label.setAttribute('text-anchor', 'middle');
693
- label.setAttribute('fill', '#6b7280');
694
- label.setAttribute('font-size', '12');
695
- label.setAttribute('font-weight', '500');
696
- label.setAttribute('font-family', 'inherit');
697
- label.textContent = yAxisLabel;
698
- svg.appendChild(label);
699
- }
700
-
701
- // X-axis ticks
702
- if (showTicksX) {
703
- const numTicks = 5;
704
- for (let i = 0; i <= numTicks; i++) {
705
- const value = (maxValue / numTicks) * i;
706
- const x = isReverse
707
- ? width - padding.right - (value * xScale)
708
- : padding.left + (value * xScale);
709
-
710
- // Grid line
711
- const gridLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
712
- gridLine.setAttribute('x1', x.toString());
713
- gridLine.setAttribute('y1', padding.top.toString());
714
- gridLine.setAttribute('x2', x.toString());
715
- gridLine.setAttribute('y2', (height - padding.bottom).toString());
716
- gridLine.setAttribute('stroke', '#e5e7eb');
717
- gridLine.setAttribute('stroke-width', '1');
718
- gridLine.setAttribute('stroke-dasharray', '4,4');
719
- svg.appendChild(gridLine);
720
-
721
- // Tick label (use scaleXUnit since values are on x-axis now)
722
- const tickLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
723
- tickLabel.setAttribute('x', x.toString());
724
- tickLabel.setAttribute('y', (height - padding.bottom + 20).toString());
725
- tickLabel.setAttribute('text-anchor', 'middle');
726
- tickLabel.setAttribute('fill', '#6b7280');
727
- tickLabel.setAttribute('font-size', '11');
728
- tickLabel.setAttribute('font-family', 'inherit');
729
- tickLabel.textContent = Math.round(value).toString() + (scaleXUnit || '');
730
- svg.appendChild(tickLabel);
731
- }
732
- }
733
- }
734
-
735
- // Y-axis (now the category axis) - use xAxisLabel since categories are vertical
736
- if (showScaleY) {
737
- const yAxis = document.createElementNS('http://www.w3.org/2000/svg', 'line');
738
- yAxis.setAttribute('x1', padding.left.toString());
739
- yAxis.setAttribute('y1', padding.top.toString());
740
- yAxis.setAttribute('x2', padding.left.toString());
741
- yAxis.setAttribute('y2', (height - padding.bottom).toString());
742
- yAxis.setAttribute('stroke', '#9ca3af');
743
- yAxis.setAttribute('stroke-width', '2');
744
- svg.appendChild(yAxis);
745
-
746
- // Y-axis label (use xAxisLabel for categories in horizontal mode)
747
- if (xAxisLabel && showTicksY) {
748
- const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
749
- label.setAttribute('x', '20');
750
- label.setAttribute('y', (padding.top + chartHeight / 2).toString());
751
- label.setAttribute('text-anchor', 'middle');
752
- label.setAttribute('transform', `rotate(-90, 20, ${padding.top + chartHeight / 2})`);
753
- label.setAttribute('fill', '#6b7280');
754
- label.setAttribute('font-size', '12');
755
- label.setAttribute('font-weight', '500');
756
- label.setAttribute('font-family', 'inherit');
757
- label.textContent = xAxisLabel;
758
- svg.appendChild(label);
759
- }
760
- }
761
-
762
- // Bars
763
- data.forEach((point, index) => {
764
- const y = padding.top + (index * barHeight) + (barGap / 2);
765
- const barWidth = point.value * xScale;
766
- const x = isReverse
767
- ? width - padding.right - barWidth
768
- : padding.left;
769
- const color = point.color || colors[index % colors.length];
770
-
771
- this._renderBar(svg, x, y, barWidth, actualBarHeight, color, index, point, isReverse ? 'right' : 'left', true);
772
-
773
- // Category label
774
- if (showTicksY && showScaleY) {
775
- const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
776
- label.setAttribute('x', (padding.left - 10).toString());
777
- label.setAttribute('y', (y + actualBarHeight / 2 + 4).toString());
778
- label.setAttribute('text-anchor', 'end');
779
- label.setAttribute('fill', '#6b7280');
780
- label.setAttribute('font-size', '11');
781
- label.setAttribute('font-family', 'inherit');
782
- label.textContent = point.label;
783
-
784
- if (animate) {
785
- label.classList.add('jux-label-animated');
786
- label.style.animationDelay = `${index * 100 + 200}ms`;
787
- }
788
-
789
- svg.appendChild(label);
790
- }
791
- });
792
- }
793
-
794
- private _renderBar(
795
- svg: SVGSVGElement,
796
- x: number,
797
- y: number,
798
- width: number,
799
- height: number,
800
- color: string,
801
- index: number,
802
- point: AreaChartDataPoint,
803
- labelPosition: 'top' | 'bottom' | 'left' | 'right',
804
- isHorizontal: boolean = false
805
- ): void {
806
- const { styleMode, borderRadius, showDataLabels, animate, animationDuration } = this.state;
807
-
808
- const shouldUseGroup = (styleMode === 'glass' || styleMode === 'glow') && animate;
809
- let animationTarget: SVGElement;
810
-
811
- if (shouldUseGroup) {
812
- const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
813
- animationTarget = group;
814
- if (animate) {
815
- group.classList.add('jux-bar-animated');
816
- group.style.animationDelay = `${index * 100}ms`;
817
- }
818
- svg.appendChild(group);
819
- }
820
-
821
- const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
822
- rect.setAttribute('x', x.toString());
823
- rect.setAttribute('y', y.toString());
824
- rect.setAttribute('width', width.toString());
825
- rect.setAttribute('height', height.toString());
826
- // rect.setAttribute('rx', borderRadius.toString());
827
- // rect.setAttribute('ry', borderRadius.toString());
828
-
829
- if (!shouldUseGroup && animate) {
830
- rect.classList.add('jux-bar-animated');
831
- rect.style.animationDelay = `${index * 100}ms`;
832
- }
833
-
834
- // Apply style modes (same as before)
835
- if (styleMode === 'gradient') {
836
- const gradientId = `gradient-${this._id}-${index}`;
837
- const gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');
838
- gradient.setAttribute('id', gradientId);
839
-
840
- if (isHorizontal) {
841
- gradient.setAttribute('x1', '0%');
842
- gradient.setAttribute('y1', '0%');
843
- gradient.setAttribute('x2', '100%');
844
- gradient.setAttribute('y2', '0%');
845
- } else {
846
- gradient.setAttribute('x1', '0%');
847
- gradient.setAttribute('y1', '0%');
848
- gradient.setAttribute('x2', '0%');
849
- gradient.setAttribute('y2', '100%');
850
- }
851
-
852
- const stop1 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
853
- stop1.setAttribute('offset', '0%');
854
- stop1.setAttribute('stop-color', color);
855
- stop1.setAttribute('stop-opacity', '1');
856
-
857
- const stop2 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
858
- stop2.setAttribute('offset', '100%');
859
- stop2.setAttribute('stop-color', this._lightenColor(color, 40));
860
- stop2.setAttribute('stop-opacity', '1');
861
-
862
- gradient.appendChild(stop1);
863
- gradient.appendChild(stop2);
864
- svg.appendChild(gradient);
865
-
866
- rect.setAttribute('fill', `url(#${gradientId})`);
867
- } else if (styleMode === 'glow') {
868
- rect.setAttribute('fill', color);
869
- const filterId = `glow-${this._id}-${index}`;
870
- const defs = svg.querySelector('defs') || document.createElementNS('http://www.w3.org/2000/svg', 'defs');
871
- if (!svg.querySelector('defs')) {
872
- svg.insertBefore(defs, svg.firstChild);
873
- }
874
-
875
- const filter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');
876
- filter.setAttribute('id', filterId);
877
- filter.setAttribute('x', '-50%');
878
- filter.setAttribute('y', '-50%');
879
- filter.setAttribute('width', '200%');
880
- filter.setAttribute('height', '200%');
881
-
882
- const feGaussianBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
883
- feGaussianBlur.setAttribute('in', 'SourceGraphic');
884
- feGaussianBlur.setAttribute('stdDeviation', '4');
885
- feGaussianBlur.setAttribute('result', 'blur');
886
-
887
- const feFlood = document.createElementNS('http://www.w3.org/2000/svg', 'feFlood');
888
- feFlood.setAttribute('flood-color', color);
889
- feFlood.setAttribute('result', 'color');
890
-
891
- const feComposite = document.createElementNS('http://www.w3.org/2000/svg', 'feComposite');
892
- feComposite.setAttribute('in', 'color');
893
- feComposite.setAttribute('in2', 'blur');
894
- feComposite.setAttribute('operator', 'in');
895
- feComposite.setAttribute('result', 'glow');
896
-
897
- const feMerge = document.createElementNS('http://www.w3.org/2000/svg', 'feMerge');
898
- const feMergeNode1 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');
899
- feMergeNode1.setAttribute('in', 'glow');
900
- const feMergeNode2 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');
901
- feMergeNode2.setAttribute('in', 'SourceGraphic');
902
- feMerge.appendChild(feMergeNode1);
903
- feMerge.appendChild(feMergeNode2);
904
-
905
- filter.appendChild(feGaussianBlur);
906
- filter.appendChild(feFlood);
907
- filter.appendChild(feComposite);
908
- filter.appendChild(feMerge);
909
- defs.appendChild(filter);
910
-
911
- rect.setAttribute('filter', `url(#${filterId})`);
912
- } else if (styleMode === 'glass') {
913
- rect.setAttribute('fill', color);
914
- rect.setAttribute('fill-opacity', '0.6');
915
- rect.setAttribute('stroke', color);
916
- rect.setAttribute('stroke-width', '0');
917
- rect.setAttribute('stroke-opacity', '0.8');
918
- } else {
919
- rect.setAttribute('fill', color);
920
- }
921
-
922
- if (shouldUseGroup) {
923
- animationTarget.appendChild(rect);
924
- } else {
925
- svg.appendChild(rect);
926
- }
927
-
928
- // Value labels
929
- if (showDataLabels) {
930
- const valueLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
931
-
932
- if (isHorizontal) {
933
- // For horizontal bars, place label in the middle of the bar
934
- valueLabel.setAttribute('x', (x + width / 2).toString());
935
- valueLabel.setAttribute('y', (y + height / 2 + 4).toString());
936
- valueLabel.setAttribute('text-anchor', 'middle');
937
- valueLabel.setAttribute('fill', '#ffffff');
938
- valueLabel.setAttribute('font-weight', '700');
939
- } else {
940
- valueLabel.setAttribute('x', (x + width / 2).toString());
941
- if (labelPosition === 'top') {
942
- valueLabel.setAttribute('y', (y - 5).toString());
943
- } else {
944
- valueLabel.setAttribute('y', (y + height + 15).toString());
945
- }
946
- valueLabel.setAttribute('text-anchor', 'middle');
947
- valueLabel.setAttribute('fill', '#374151');
948
- valueLabel.setAttribute('font-weight', '600');
949
- }
950
-
951
- valueLabel.setAttribute('font-size', '11');
952
- valueLabel.setAttribute('font-family', 'inherit');
953
- valueLabel.textContent = point.value.toString();
954
-
955
- if (animate) {
956
- valueLabel.classList.add('jux-label-animated');
957
- valueLabel.style.animationDelay = `${index * 100 + animationDuration - 200}ms`;
958
- }
959
-
960
- svg.appendChild(valueLabel);
961
- }
962
- }
963
-
964
- /* -------------------------
965
- * Legend and Data Table
966
- * ------------------------- */
967
-
968
- private _createLegend(): HTMLElement {
969
- const { data, colors, legendOrientation } = this.state;
970
-
971
- const legend = document.createElement('div');
972
- legend.className = 'jux-areachart-legend';
973
-
974
- data.forEach((point, index) => {
975
- const color = point.color || colors[index % colors.length];
976
-
977
- const item = document.createElement('div');
978
- item.className = 'jux-areachart-legend-item';
979
-
980
- const swatch = document.createElement('div');
981
- swatch.className = 'jux-areachart-legend-swatch';
982
- swatch.style.background = color;
983
-
984
- const label = document.createElement('span');
985
- label.className = 'jux-areachart-legend-label';
986
- label.textContent = point.label;
987
-
988
- item.appendChild(swatch);
989
- item.appendChild(label);
990
- legend.appendChild(item);
991
- });
992
-
993
- return legend;
994
- }
995
-
996
- private _createDataTable(): HTMLElement {
997
- const { data, xAxisLabel, yAxisLabel, chartOrientation } = this.state;
998
-
999
- const table = document.createElement('table');
1000
- table.className = 'jux-areachart-table';
1001
-
1002
- const thead = document.createElement('thead');
1003
- const headerRow = document.createElement('tr');
1004
-
1005
- // Swap headers based on orientation
1006
- const columnHeaders = chartOrientation === 'horizontal'
1007
- ? [yAxisLabel || 'Label', xAxisLabel || 'Value']
1008
- : [xAxisLabel || 'Label', yAxisLabel || 'Value'];
1009
-
1010
- columnHeaders.forEach(text => {
1011
- const th = document.createElement('th');
1012
- th.textContent = text;
1013
- headerRow.appendChild(th);
1014
- });
1015
- thead.appendChild(headerRow);
1016
- table.appendChild(thead);
1017
-
1018
- const tbody = document.createElement('tbody');
1019
- data.forEach(point => {
1020
- const row = document.createElement('tr');
1021
-
1022
- const labelCell = document.createElement('td');
1023
- labelCell.textContent = point.label;
1024
-
1025
- const valueCell = document.createElement('td');
1026
- valueCell.textContent = point.value.toString();
1027
-
1028
- row.appendChild(labelCell);
1029
- row.appendChild(valueCell);
1030
- tbody.appendChild(row);
1031
- });
1032
- table.appendChild(tbody);
1033
-
1034
- return table;
1035
- }
1036
-
1037
- private _lightenColor(color: string, percent: number): string {
1038
- const num = parseInt(color.replace('#', ''), 16);
1039
- const r = Math.min(255, Math.floor((num >> 16) + ((255 - (num >> 16)) * percent / 100)));
1040
- const g = Math.min(255, Math.floor(((num >> 8) & 0x00FF) + ((255 - ((num >> 8) & 0x00FF)) * percent / 100)));
1041
- const b = Math.min(255, Math.floor((num & 0x0000FF) + ((255 - (num & 0x0000FF)) * percent / 100)));
1042
- return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
1043
- }
1044
-
1045
- private _applyTheme(themeName: string): void {
1046
- const themes: Record<string, any> = {
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];
1057
- if (!theme) return;
1058
-
1059
- // Apply colors
1060
- // get one color;
1061
- const randomColor = theme.colors[Math.floor(Math.random() * theme.colors.length)];
1062
- this.state.colors = [randomColor];
1063
-
1064
- // Inject base styles (once)
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
- `;
1101
- }
1102
-
1103
- private _applyThemeToWrapper(wrapper: HTMLElement): void {
1104
- if (!this.state.theme) return;
1105
-
1106
- // Remove old theme classes
1107
- wrapper.classList.remove('theme-google', 'theme-seriesa', 'theme-hr', 'theme-figma', 'theme-notion', 'theme-chalk', 'theme-mint');
1108
-
1109
- // Add new theme class
1110
- wrapper.classList.add(`theme-${this.state.theme}`);
1111
- }
1112
-
1113
- private _getBaseStyles(): string {
1114
- return `
1115
- .jux-areachart {
1116
- font-family: var(--chart-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
1117
- display: inline-block;
1118
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
1119
- border-radius: 12px;
1120
- background: white;
1121
- padding: 24px;
1122
- }
1123
-
1124
- .jux-areachart-title {
1125
- margin: 0 0 0.5rem 0;
1126
- font-size: 1.25rem;
1127
- font-weight: 600;
1128
- font-family: inherit;
1129
- }
1130
-
1131
- .jux-areachart-subtitle {
1132
- margin: 0 0 1rem 0;
1133
- font-size: 0.875rem;
1134
- color: #6b7280;
1135
- font-family: inherit;
1136
- }
1137
-
1138
- .jux-areachart-legend {
1139
- display: flex;
1140
- flex-wrap: wrap;
1141
- gap: 1rem;
1142
- margin-top: 1rem;
1143
- justify-content: center;
1144
- }
1145
-
1146
- .jux-areachart-legend-item {
1147
- display: flex;
1148
- align-items: center;
1149
- gap: 0.5rem;
1150
- }
1151
-
1152
- .jux-areachart-legend-swatch {
1153
- width: 12px;
1154
- height: 12px;
1155
- border-radius: 2px;
1156
- }
1157
-
1158
- .jux-areachart-legend-label {
1159
- font-size: 0.875rem;
1160
- color: #374151;
1161
- font-family: inherit;
1162
- }
1163
-
1164
- .jux-areachart-table {
1165
- width: 100%;
1166
- margin-top: 1rem;
1167
- border-collapse: collapse;
1168
- font-size: 0.875rem;
1169
- font-family: inherit;
1170
- }
1171
-
1172
- .jux-areachart-table thead th {
1173
- text-align: left;
1174
- padding: 0.5rem;
1175
- border-bottom: 2px solid #e5e7eb;
1176
- font-weight: 600;
1177
- text-align: center;
1178
- }
1179
-
1180
- .jux-areachart-table tbody td {
1181
- padding: 0.5rem;
1182
- border-bottom: 1px solid #f3f4f6;
1183
- text-align: center;
1184
- }
1185
-
1186
- .jux-areachart-svg {
1187
- font-family: inherit;
1188
- }
1189
- `;
1190
- }
1191
-
1192
- render(targetId?: string | HTMLElement): this {
1193
- // Apply theme first if set
1194
- if (this.state.theme) {
1195
- this._applyTheme(this.state.theme);
1196
- }
1197
-
1198
- let container: HTMLElement;
1199
-
1200
- if (targetId) {
1201
- if (targetId instanceof HTMLElement) {
1202
- container = targetId;
1203
- } else {
1204
- const target = document.querySelector(targetId);
1205
- if (!target || !(target instanceof HTMLElement)) {
1206
- throw new Error(`AreaChart: Target element "${targetId}" not found`);
1207
- }
1208
- container = target;
1209
- }
1210
- } else {
1211
- container = getOrCreateContainer(this._id);
1212
- }
1213
-
1214
- this.container = container;
1215
- const { class: className, style } = this.state;
1216
-
1217
- const wrapper = document.createElement('div');
1218
- wrapper.id = this._id;
1219
- wrapper.className = 'jux-areachart';
1220
-
1221
- // Add theme class
1222
- if (this.state.theme) {
1223
- wrapper.classList.add(`theme-${this.state.theme}`);
1224
- }
1225
-
1226
- // Add custom class
1227
- if (className) {
1228
- wrapper.classList.add(...className.split(' '));
1229
- }
1230
-
1231
- if (style) {
1232
- wrapper.setAttribute('style', style);
1233
- }
1234
-
1235
- container.appendChild(wrapper);
1236
-
1237
- // Build chart content
1238
- this._buildChart(wrapper);
1239
-
1240
- return this;
1241
- }
1242
- }
1243
-
1244
- export function areachart(id: string, options: AreaChartOptions = {}): AreaChart {
1245
- return new AreaChart(id, options);
1246
- }