@shohojdhara/atomix 0.4.5 → 0.4.7
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/dist/atomix.css +70 -33
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +2 -2
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +93 -109
- package/dist/charts.js +273 -371
- package/dist/charts.js.map +1 -1
- package/dist/core.js +183 -184
- package/dist/core.js.map +1 -1
- package/dist/forms.js +183 -184
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +183 -184
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +7 -51
- package/dist/index.esm.js +281 -470
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +287 -476
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +60 -38
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +6 -35
- package/src/components/AtomixGlass/glass-utils.ts +27 -14
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +19 -21
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +1162 -515
- package/src/components/AtomixGlass/stories/shared-components.tsx +11 -3
- package/src/components/Chart/BubbleChart.tsx +6 -2
- package/src/components/Chart/Chart.stories.tsx +108 -96
- package/src/components/Chart/ChartToolbar.tsx +6 -4
- package/src/components/Chart/ChartTooltip.tsx +5 -4
- package/src/components/Chart/GaugeChart.tsx +20 -12
- package/src/components/Chart/HeatmapChart.tsx +53 -23
- package/src/components/Chart/TreemapChart.tsx +44 -15
- package/src/components/Chart/index.ts +0 -2
- package/src/components/Chart/types.ts +4 -4
- package/src/components/Navigation/Navbar/Navbar.tsx +13 -5
- package/src/components/index.ts +0 -1
- package/src/lib/composables/index.ts +1 -2
- package/src/lib/composables/useAtomixGlass.ts +246 -222
- package/src/lib/composables/useAtomixGlassStyles.ts +46 -23
- package/src/lib/constants/components.ts +3 -1
- package/src/styles/01-settings/_settings.chart.scss +13 -13
- package/src/styles/06-components/_components.atomix-glass.scss +45 -20
- package/src/styles/06-components/_components.chart.scss +23 -5
- package/src/components/Chart/AnimatedChart.tsx +0 -230
- package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +0 -329
- package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +0 -82
- package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +0 -153
- package/src/lib/composables/atomix-glass/useGlassOverLight.ts +0 -198
- package/src/lib/composables/atomix-glass/useGlassState.ts +0 -112
- package/src/lib/composables/atomix-glass/useGlassTransforms.ts +0 -160
- package/src/lib/composables/glass-styles.ts +0 -302
- package/src/lib/composables/useGlassContainer.ts +0 -177
|
@@ -75,16 +75,18 @@ export const BackgroundWrapper: React.FC<BackgroundWrapperProps> = ({
|
|
|
75
75
|
|
|
76
76
|
const bgStyle = {
|
|
77
77
|
backgroundImage: bgImage ? `url(${bgImage})` : undefined,
|
|
78
|
+
backgroundSize: 'cover',
|
|
79
|
+
backgroundPosition: 'center',
|
|
80
|
+
backgroundRepeat: 'no-repeat',
|
|
78
81
|
height,
|
|
79
82
|
width,
|
|
80
83
|
borderRadius,
|
|
81
|
-
padding,
|
|
82
84
|
...style,
|
|
83
85
|
};
|
|
84
86
|
|
|
85
87
|
return (
|
|
86
88
|
<div
|
|
87
|
-
className={`u-relative u-overflow-hidden ${className}`}
|
|
89
|
+
className={`u-relative u-overflow-hidden u-flex u-items-center u-justify-center ${className}`}
|
|
88
90
|
style={bgStyle}
|
|
89
91
|
aria-hidden={ariaHidden}
|
|
90
92
|
>
|
|
@@ -94,10 +96,16 @@ export const BackgroundWrapper: React.FC<BackgroundWrapperProps> = ({
|
|
|
94
96
|
style={{
|
|
95
97
|
backgroundColor: overlayColor,
|
|
96
98
|
opacity: overlayOpacity,
|
|
99
|
+
padding,
|
|
97
100
|
}}
|
|
98
101
|
/>
|
|
99
102
|
)}
|
|
100
|
-
<div
|
|
103
|
+
<div
|
|
104
|
+
className="u-relative u-z-10 u-w-100 u-h-100 u-flex u-items-center u-justify-center"
|
|
105
|
+
style={{ padding }}
|
|
106
|
+
>
|
|
107
|
+
{children}
|
|
108
|
+
</div>
|
|
101
109
|
</div>
|
|
102
110
|
);
|
|
103
111
|
};
|
|
@@ -126,8 +126,12 @@ const BubbleChart = memo(
|
|
|
126
126
|
minBubbleSize + ((bubble.size - minSize) / sizeRange) * (maxBubbleSize - minBubbleSize);
|
|
127
127
|
|
|
128
128
|
// Calculate position
|
|
129
|
-
|
|
130
|
-
const
|
|
129
|
+
// Ensure bubbles don't get cut off by adding padding equal to maxBubbleSize
|
|
130
|
+
const effectiveWidth = scales.innerWidth - maxBubbleSize * 2;
|
|
131
|
+
const effectiveHeight = scales.innerHeight - maxBubbleSize * 2;
|
|
132
|
+
|
|
133
|
+
const x = scales.padding.left + maxBubbleSize + (bubble.x / 100) * effectiveWidth;
|
|
134
|
+
const y = scales.padding.top + maxBubbleSize + effectiveHeight - (bubble.y / 100) * effectiveHeight;
|
|
131
135
|
|
|
132
136
|
// Determine color
|
|
133
137
|
let bubbleColor = bubble.color;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
import { fn } from '@storybook/test';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { useState } from 'react';
|
|
3
|
+
import React, { useMemo, useState } from 'react';
|
|
5
4
|
import { Container, Grid, GridCol } from '../../layouts/Grid';
|
|
6
5
|
import { Badge } from '../Badge';
|
|
7
6
|
import { Button } from '../Button';
|
|
@@ -12,7 +11,6 @@ import { SideMenuItem } from '../Navigation/SideMenu/SideMenuItem';
|
|
|
12
11
|
import { SideMenuList } from '../Navigation/SideMenu/SideMenuList';
|
|
13
12
|
|
|
14
13
|
import {
|
|
15
|
-
AnimatedChart,
|
|
16
14
|
AreaChart,
|
|
17
15
|
BarChart,
|
|
18
16
|
BubbleChart,
|
|
@@ -123,28 +121,13 @@ Charts provide a comprehensive charting library with 20+ chart types including l
|
|
|
123
121
|
defaultValue: { summary: '-' },
|
|
124
122
|
},
|
|
125
123
|
},
|
|
126
|
-
|
|
127
|
-
control: 'text',
|
|
128
|
-
description: 'Width of the chart',
|
|
129
|
-
table: {
|
|
130
|
-
type: { summary: 'string | number' },
|
|
131
|
-
defaultValue: { summary: '100%' },
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
height: {
|
|
135
|
-
control: 'text',
|
|
136
|
-
description: 'Height of the chart',
|
|
137
|
-
table: {
|
|
138
|
-
type: { summary: 'string | number' },
|
|
139
|
-
defaultValue: { summary: '400px' },
|
|
140
|
-
},
|
|
141
|
-
},
|
|
124
|
+
|
|
142
125
|
glass: {
|
|
143
126
|
control: 'boolean',
|
|
144
127
|
description: 'Whether to apply glass effect',
|
|
145
128
|
table: {
|
|
146
129
|
type: { summary: 'boolean' },
|
|
147
|
-
defaultValue: { summary: false },
|
|
130
|
+
defaultValue: { summary: 'false' },
|
|
148
131
|
},
|
|
149
132
|
},
|
|
150
133
|
showToolbar: {
|
|
@@ -152,7 +135,7 @@ Charts provide a comprehensive charting library with 20+ chart types including l
|
|
|
152
135
|
description: 'Whether to show the toolbar',
|
|
153
136
|
table: {
|
|
154
137
|
type: { summary: 'boolean' },
|
|
155
|
-
defaultValue: { summary: false },
|
|
138
|
+
defaultValue: { summary: 'false' },
|
|
156
139
|
},
|
|
157
140
|
},
|
|
158
141
|
config: {
|
|
@@ -163,14 +146,10 @@ Charts provide a comprehensive charting library with 20+ chart types including l
|
|
|
163
146
|
defaultValue: { summary: '{}' },
|
|
164
147
|
},
|
|
165
148
|
},
|
|
166
|
-
|
|
167
|
-
action: 'point clicked',
|
|
149
|
+
onDataPointClick: {
|
|
150
|
+
action: 'data point clicked',
|
|
168
151
|
description: 'Callback when a data point is clicked',
|
|
169
152
|
},
|
|
170
|
-
onPointHover: {
|
|
171
|
-
action: 'point hovered',
|
|
172
|
-
description: 'Callback when hovering over a data point',
|
|
173
|
-
},
|
|
174
153
|
},
|
|
175
154
|
} satisfies Meta<typeof Chart>;
|
|
176
155
|
|
|
@@ -208,10 +187,10 @@ export const GlassVariant: Story = {
|
|
|
208
187
|
>
|
|
209
188
|
<Container>
|
|
210
189
|
<Grid>
|
|
211
|
-
<GridCol
|
|
190
|
+
<GridCol xs={12}>
|
|
212
191
|
<h2 style={{ color: 'white', marginBottom: '2rem' }}>Chart Glass Variant</h2>
|
|
213
192
|
</GridCol>
|
|
214
|
-
<GridCol
|
|
193
|
+
<GridCol xs={12} md={6} className="u-mb-4">
|
|
215
194
|
<LineChart
|
|
216
195
|
{...args}
|
|
217
196
|
title="Sales Performance"
|
|
@@ -225,7 +204,7 @@ export const GlassVariant: Story = {
|
|
|
225
204
|
}}
|
|
226
205
|
/>
|
|
227
206
|
</GridCol>
|
|
228
|
-
<GridCol
|
|
207
|
+
<GridCol xs={12} md={6}>
|
|
229
208
|
<BarChart
|
|
230
209
|
{...args}
|
|
231
210
|
title="Revenue by Month"
|
|
@@ -239,10 +218,10 @@ export const GlassVariant: Story = {
|
|
|
239
218
|
}}
|
|
240
219
|
/>
|
|
241
220
|
</GridCol>
|
|
242
|
-
<GridCol
|
|
221
|
+
<GridCol xs={12} md={6}>
|
|
243
222
|
<PieChart title="Market Share" data={sampleData} glass={true} showToolbar={true} />
|
|
244
223
|
</GridCol>
|
|
245
|
-
<GridCol
|
|
224
|
+
<GridCol xs={12} md={6}>
|
|
246
225
|
<AreaChart
|
|
247
226
|
title="Growth Trend"
|
|
248
227
|
subtitle="Year over year"
|
|
@@ -261,8 +240,7 @@ export const GlassVariant: Story = {
|
|
|
261
240
|
);
|
|
262
241
|
},
|
|
263
242
|
args: {
|
|
264
|
-
|
|
265
|
-
onPointHover: fn(),
|
|
243
|
+
onDataPointClick: fn(),
|
|
266
244
|
},
|
|
267
245
|
parameters: {
|
|
268
246
|
docs: {
|
|
@@ -375,7 +353,7 @@ const generateFunnelData = () => {
|
|
|
375
353
|
|
|
376
354
|
return stages.map(stage => ({
|
|
377
355
|
...stage,
|
|
378
|
-
percentage: ((stage.value / stages[0].value) * 100).toFixed(1),
|
|
356
|
+
percentage: Number(((stage.value / stages[0].value) * 100).toFixed(1)),
|
|
379
357
|
}));
|
|
380
358
|
};
|
|
381
359
|
|
|
@@ -391,7 +369,9 @@ export const ChartGallery: Story = {
|
|
|
391
369
|
const [selectedType, setSelectedType] = useState('line');
|
|
392
370
|
const [animated, setAnimated] = useState(true);
|
|
393
371
|
const [showLegend, setShowLegend] = useState(true);
|
|
372
|
+
const [glassEffect, setGlassEffect] = useState(false);
|
|
394
373
|
const [dataPoints, setDataPoints] = useState(12);
|
|
374
|
+
const [dataSeed, setDataSeed] = useState(0);
|
|
395
375
|
|
|
396
376
|
const chartTypes = [
|
|
397
377
|
{ key: 'line', icon: 'TrendUp', label: 'Line', desc: 'Trends over time' },
|
|
@@ -413,26 +393,55 @@ export const ChartGallery: Story = {
|
|
|
413
393
|
{ key: 'waterfall', icon: 'Drop', label: 'Waterfall', desc: 'Cumulative flow' },
|
|
414
394
|
{ key: 'funnel', icon: 'Funnel', label: 'Funnel', desc: 'Process stages' },
|
|
415
395
|
{ key: 'treemap', icon: 'Tree', label: 'Treemap', desc: 'Hierarchical data' },
|
|
416
|
-
{ key: 'animated', icon: 'Sparkle', label: 'Animated', desc: 'Motion graphics' },
|
|
417
396
|
{ key: 'multiaxis', icon: 'ChartLineUp', label: 'Multi-axis', desc: 'Multiple scales' },
|
|
418
397
|
];
|
|
419
398
|
|
|
420
|
-
// Generate dynamic data based on dataPoints
|
|
421
|
-
const dynamicDatasets =
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
399
|
+
// Generate dynamic data based on dataPoints and dataSeed
|
|
400
|
+
const dynamicDatasets = useMemo(
|
|
401
|
+
() => [
|
|
402
|
+
{ label: 'Sales', data: generateData(dataPoints), color: 'var(--atomix-primary)' },
|
|
403
|
+
{ label: 'Revenue', data: generateData(dataPoints), color: 'var(--atomix-success)' },
|
|
404
|
+
{ label: 'Profit', data: generateData(dataPoints), color: 'var(--atomix-warning)' },
|
|
405
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
406
|
+
],
|
|
407
|
+
[dataPoints, dataSeed]
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
const pieDatasets = useMemo(
|
|
411
|
+
() => [
|
|
412
|
+
{ label: 'Distribution', data: generateData(Math.min(dataPoints, 8)) },
|
|
413
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
414
|
+
],
|
|
415
|
+
[dataPoints, dataSeed]
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
419
|
+
const bubbleData = useMemo(() => generateBubbleData(dataPoints), [dataPoints, dataSeed]);
|
|
420
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
421
|
+
const heatmapData = useMemo(() => generateHeatmapData(), [dataSeed]);
|
|
422
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
423
|
+
const candlestickData = useMemo(
|
|
424
|
+
() => generateCandlestickData(dataPoints),
|
|
425
|
+
[dataPoints, dataSeed]
|
|
426
|
+
);
|
|
427
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
428
|
+
const funnelData = useMemo(() => generateFunnelData(), [dataSeed]);
|
|
429
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
430
|
+
const treemapData = useMemo(
|
|
431
|
+
() => generateTreemapData(Math.min(dataPoints, 20)),
|
|
432
|
+
[dataPoints, dataSeed]
|
|
433
|
+
);
|
|
426
434
|
|
|
427
435
|
const renderChart = () => {
|
|
428
436
|
const commonProps = {
|
|
429
437
|
title: `${chartTypes.find(t => t.key === selectedType)?.label} Chart`,
|
|
430
438
|
config: { showLegend, animate: animated },
|
|
431
439
|
showToolbar: true,
|
|
440
|
+
glass: glassEffect,
|
|
432
441
|
enableFullscreen: true,
|
|
433
442
|
enableExport: true,
|
|
434
443
|
enableRefresh: true,
|
|
435
|
-
onRefresh: () =>
|
|
444
|
+
onRefresh: () => setDataSeed(s => s + 1), // Regenerate on refresh button click
|
|
436
445
|
onExport: (format: string) => console.log('Story: Export clicked', format),
|
|
437
446
|
onFullscreen: (isFullscreen: boolean) =>
|
|
438
447
|
console.log('Story: Fullscreen toggled', isFullscreen),
|
|
@@ -440,39 +449,58 @@ export const ChartGallery: Story = {
|
|
|
440
449
|
|
|
441
450
|
// Custom toolbar with chart controls
|
|
442
451
|
const customToolbar = (
|
|
443
|
-
<div className="u-flex u-gap-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
<div className="u-flex u-items-center u-gap-
|
|
447
|
-
<Icon name="Database" size="sm" />
|
|
452
|
+
<div className="u-flex u-gap-4 u-items-center u-flex-wrap u-mb-5 u-p-3">
|
|
453
|
+
{/* Data Control Group */}
|
|
454
|
+
<div className="u-flex u-items-center u-gap-3">
|
|
455
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
456
|
+
<Icon name="Database" size="sm" className="u-text-muted" />
|
|
448
457
|
<input
|
|
449
458
|
type="range"
|
|
450
459
|
min="4"
|
|
451
460
|
max="20"
|
|
452
461
|
value={dataPoints}
|
|
453
462
|
onChange={e => setDataPoints(Number(e.target.value))}
|
|
454
|
-
className="u-w-
|
|
463
|
+
className="u-w-25"
|
|
455
464
|
title="Adjust data points"
|
|
456
465
|
/>
|
|
457
466
|
<Badge label={dataPoints.toString()} variant="info" size="sm" />
|
|
458
467
|
</div>
|
|
459
468
|
|
|
460
|
-
{/* Legend Toggle */}
|
|
461
469
|
<Button
|
|
462
470
|
size="sm"
|
|
463
|
-
variant=
|
|
471
|
+
variant="secondary"
|
|
472
|
+
onClick={() => setDataSeed(s => s + 1)}
|
|
473
|
+
iconName="ArrowsClockwise"
|
|
474
|
+
label="Regenerate"
|
|
475
|
+
/>
|
|
476
|
+
</div>
|
|
477
|
+
|
|
478
|
+
<div className="u-flex-1" />
|
|
479
|
+
|
|
480
|
+
{/* View Toggles Group */}
|
|
481
|
+
<div className="u-flex u-gap-2">
|
|
482
|
+
<Button
|
|
483
|
+
size="sm"
|
|
484
|
+
variant={showLegend ? 'primary' : 'secondary'}
|
|
464
485
|
onClick={() => setShowLegend(!showLegend)}
|
|
465
|
-
|
|
466
|
-
label=
|
|
486
|
+
iconName="List"
|
|
487
|
+
label="Legend"
|
|
467
488
|
/>
|
|
468
489
|
|
|
469
|
-
{/* Animation Toggle */}
|
|
470
490
|
<Button
|
|
471
491
|
size="sm"
|
|
472
|
-
variant={animated ? '
|
|
492
|
+
variant={animated ? 'primary' : 'secondary'}
|
|
473
493
|
onClick={() => setAnimated(!animated)}
|
|
474
|
-
|
|
475
|
-
label=
|
|
494
|
+
iconName="Sparkle"
|
|
495
|
+
label="Animations"
|
|
496
|
+
/>
|
|
497
|
+
|
|
498
|
+
<Button
|
|
499
|
+
size="sm"
|
|
500
|
+
variant={glassEffect ? 'primary' : 'secondary'}
|
|
501
|
+
onClick={() => setGlassEffect(!glassEffect)}
|
|
502
|
+
iconName="Drop"
|
|
503
|
+
label="Glass"
|
|
476
504
|
/>
|
|
477
505
|
</div>
|
|
478
506
|
</div>
|
|
@@ -481,93 +509,84 @@ export const ChartGallery: Story = {
|
|
|
481
509
|
switch (selectedType) {
|
|
482
510
|
case 'line':
|
|
483
511
|
return (
|
|
484
|
-
<div>
|
|
512
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
485
513
|
{customToolbar}
|
|
486
514
|
<LineChart datasets={dynamicDatasets} {...commonProps} />
|
|
487
515
|
</div>
|
|
488
516
|
);
|
|
489
517
|
case 'area':
|
|
490
518
|
return (
|
|
491
|
-
<div>
|
|
519
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
492
520
|
{customToolbar}
|
|
493
521
|
<AreaChart datasets={dynamicDatasets} {...commonProps} />
|
|
494
522
|
</div>
|
|
495
523
|
);
|
|
496
524
|
case 'bar':
|
|
497
525
|
return (
|
|
498
|
-
<div>
|
|
526
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
499
527
|
{customToolbar}
|
|
500
528
|
<BarChart datasets={dynamicDatasets} {...commonProps} />
|
|
501
529
|
</div>
|
|
502
530
|
);
|
|
503
531
|
case 'pie':
|
|
504
532
|
return (
|
|
505
|
-
<div>
|
|
533
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
506
534
|
{customToolbar}
|
|
507
|
-
<PieChart
|
|
508
|
-
datasets={[{ label: 'Distribution', data: generateData(6) }]}
|
|
509
|
-
{...commonProps}
|
|
510
|
-
/>
|
|
535
|
+
<PieChart datasets={pieDatasets} {...commonProps} />
|
|
511
536
|
</div>
|
|
512
537
|
);
|
|
513
538
|
case 'donut':
|
|
514
539
|
return (
|
|
515
|
-
<div>
|
|
540
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
516
541
|
{customToolbar}
|
|
517
|
-
<DonutChart
|
|
518
|
-
datasets={[{ label: 'Distribution', data: generateData(6) }]}
|
|
519
|
-
{...commonProps}
|
|
520
|
-
/>
|
|
542
|
+
<DonutChart datasets={pieDatasets} {...commonProps} />
|
|
521
543
|
</div>
|
|
522
544
|
);
|
|
523
545
|
case 'scatter':
|
|
524
546
|
return (
|
|
525
|
-
<div>
|
|
547
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
526
548
|
{customToolbar}
|
|
527
549
|
<ScatterChart datasets={dynamicDatasets} {...commonProps} />
|
|
528
550
|
</div>
|
|
529
551
|
);
|
|
530
552
|
case 'radar':
|
|
531
553
|
return (
|
|
532
|
-
<div>
|
|
554
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
533
555
|
{customToolbar}
|
|
534
556
|
<RadarChart datasets={dynamicDatasets} {...commonProps} />
|
|
535
557
|
</div>
|
|
536
558
|
);
|
|
537
559
|
case 'bubble':
|
|
538
560
|
return (
|
|
539
|
-
<div>
|
|
561
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
540
562
|
{customToolbar}
|
|
541
|
-
<BubbleChart bubbleData={
|
|
563
|
+
<BubbleChart bubbleData={bubbleData} {...commonProps} />
|
|
542
564
|
</div>
|
|
543
565
|
);
|
|
544
566
|
case 'gauge':
|
|
545
567
|
return (
|
|
546
|
-
<div>
|
|
568
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
547
569
|
{customToolbar}
|
|
548
570
|
<GaugeChart value={75} max={100} {...commonProps} />
|
|
549
571
|
</div>
|
|
550
572
|
);
|
|
551
573
|
case 'heatmap':
|
|
552
574
|
return (
|
|
553
|
-
<div>
|
|
575
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
554
576
|
{customToolbar}
|
|
555
|
-
<HeatmapChart data={
|
|
577
|
+
<HeatmapChart data={heatmapData} {...commonProps} />
|
|
556
578
|
</div>
|
|
557
579
|
);
|
|
558
580
|
case 'candlestick':
|
|
559
581
|
return (
|
|
560
|
-
<div>
|
|
582
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
561
583
|
{customToolbar}
|
|
562
|
-
<CandlestickChart
|
|
563
|
-
candlestickData={generateCandlestickData(dataPoints)}
|
|
564
|
-
{...commonProps}
|
|
565
|
-
/>
|
|
584
|
+
<CandlestickChart candlestickData={candlestickData} {...commonProps} />
|
|
566
585
|
</div>
|
|
567
586
|
);
|
|
568
587
|
case 'waterfall':
|
|
569
588
|
return (
|
|
570
|
-
<div>
|
|
589
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
571
590
|
{customToolbar}
|
|
572
591
|
<WaterfallChart
|
|
573
592
|
waterfallData={[
|
|
@@ -583,10 +602,10 @@ export const ChartGallery: Story = {
|
|
|
583
602
|
);
|
|
584
603
|
case 'funnel':
|
|
585
604
|
return (
|
|
586
|
-
<div>
|
|
605
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
587
606
|
{customToolbar}
|
|
588
607
|
<FunnelChart
|
|
589
|
-
funnelData={
|
|
608
|
+
funnelData={funnelData}
|
|
590
609
|
funnelOptions={{
|
|
591
610
|
showLabels: true,
|
|
592
611
|
showValues: true,
|
|
@@ -601,10 +620,10 @@ export const ChartGallery: Story = {
|
|
|
601
620
|
);
|
|
602
621
|
case 'treemap':
|
|
603
622
|
return (
|
|
604
|
-
<div>
|
|
623
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
605
624
|
{customToolbar}
|
|
606
625
|
<TreemapChart
|
|
607
|
-
data={
|
|
626
|
+
data={treemapData}
|
|
608
627
|
algorithm="squarified"
|
|
609
628
|
colorConfig={{ scheme: 'category' }}
|
|
610
629
|
labelConfig={{
|
|
@@ -617,16 +636,9 @@ export const ChartGallery: Story = {
|
|
|
617
636
|
/>
|
|
618
637
|
</div>
|
|
619
638
|
);
|
|
620
|
-
case 'animated':
|
|
621
|
-
return (
|
|
622
|
-
<div>
|
|
623
|
-
{customToolbar}
|
|
624
|
-
<AnimatedChart datasets={dynamicDatasets} {...commonProps} />
|
|
625
|
-
</div>
|
|
626
|
-
);
|
|
627
639
|
case 'multiaxis':
|
|
628
640
|
return (
|
|
629
|
-
<div>
|
|
641
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
630
642
|
{customToolbar}
|
|
631
643
|
<MultiAxisChart
|
|
632
644
|
datasets={dynamicDatasets.map((d, i) => ({ ...d, yAxisId: `axis${i}` }))}
|
|
@@ -641,7 +653,7 @@ export const ChartGallery: Story = {
|
|
|
641
653
|
);
|
|
642
654
|
default:
|
|
643
655
|
return (
|
|
644
|
-
<div>
|
|
656
|
+
<div className="u-h-100 u-flex u-flex-column">
|
|
645
657
|
{customToolbar}
|
|
646
658
|
<LineChart datasets={dynamicDatasets} {...commonProps} />
|
|
647
659
|
</div>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { forwardRef, memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
1
|
+
import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { CHART } from '../../lib/constants/components';
|
|
3
3
|
import { Icon } from '../Icon';
|
|
4
4
|
import type { PhosphorIconsType } from '../Icon/Icon';
|
|
5
5
|
import { ChartType } from './types';
|
|
6
|
+
import { Variant } from '../../lib/types/components';
|
|
6
7
|
|
|
7
8
|
export interface ChartToolbarAction {
|
|
8
9
|
id: string;
|
|
@@ -11,7 +12,7 @@ export interface ChartToolbarAction {
|
|
|
11
12
|
onClick: () => void;
|
|
12
13
|
disabled?: boolean;
|
|
13
14
|
active?: boolean;
|
|
14
|
-
variant?:
|
|
15
|
+
variant?: Variant;
|
|
15
16
|
tooltip?: string;
|
|
16
17
|
shortcut?: string;
|
|
17
18
|
}
|
|
@@ -155,7 +156,7 @@ const ChartToolbar = memo(
|
|
|
155
156
|
const settingsButtonRef = useRef<HTMLButtonElement>(null);
|
|
156
157
|
|
|
157
158
|
// Compute effective defaults based on provided groups
|
|
158
|
-
const effectiveDefaults =
|
|
159
|
+
const effectiveDefaults = useMemo(() => (
|
|
159
160
|
groups && groups.length > 0
|
|
160
161
|
? {
|
|
161
162
|
refresh: defaults.refresh ?? true,
|
|
@@ -172,7 +173,8 @@ const ChartToolbar = memo(
|
|
|
172
173
|
tooltips: defaults.tooltips ?? true,
|
|
173
174
|
animations: defaults.animations ?? true,
|
|
174
175
|
}
|
|
175
|
-
: defaults
|
|
176
|
+
: defaults
|
|
177
|
+
), [groups, defaults]);
|
|
176
178
|
|
|
177
179
|
// Close menus when clicking outside
|
|
178
180
|
useEffect(() => {
|
|
@@ -63,15 +63,16 @@ const ChartTooltip = memo<ChartTooltipProps>(
|
|
|
63
63
|
ref={tooltipRef}
|
|
64
64
|
className="c-chart__tooltip"
|
|
65
65
|
style={{
|
|
66
|
-
|
|
67
|
-
top: `${adjustedPosition.y}px`,
|
|
66
|
+
transform: `translate3d(${adjustedPosition.x}px, ${adjustedPosition.y}px, 0)`,
|
|
68
67
|
opacity: visible ? 1 : 0,
|
|
69
68
|
visibility: visible ? 'visible' : 'hidden',
|
|
70
|
-
transition: 'opacity 0.2s ease
|
|
71
|
-
transform: 'translateZ(0)',
|
|
69
|
+
transition: 'opacity 0.2s ease',
|
|
72
70
|
position: 'fixed',
|
|
71
|
+
left: 0,
|
|
72
|
+
top: 0,
|
|
73
73
|
zIndex: 1000,
|
|
74
74
|
pointerEvents: 'none',
|
|
75
|
+
willChange: 'transform',
|
|
75
76
|
}}
|
|
76
77
|
>
|
|
77
78
|
{customRenderer ? (
|
|
@@ -208,11 +208,13 @@ const GaugeChart = memo(
|
|
|
208
208
|
// Create ticks
|
|
209
209
|
const ticks = [];
|
|
210
210
|
if (showTicks) {
|
|
211
|
+
const innerRadius = radius * (1 - thickness);
|
|
212
|
+
|
|
211
213
|
// Major ticks
|
|
212
214
|
for (let i = 0; i <= majorTicks; i++) {
|
|
213
215
|
const tickValue = min + (max - min) * (i / majorTicks);
|
|
214
216
|
const tickAngle = startAngleRad + (i / majorTicks) * angleRange;
|
|
215
|
-
const tickRadius =
|
|
217
|
+
const tickRadius = innerRadius - 2;
|
|
216
218
|
const tickLength = radius * 0.05;
|
|
217
219
|
const x1 = centerX + tickRadius * Math.cos(tickAngle);
|
|
218
220
|
const y1 = centerY + tickRadius * Math.sin(tickAngle);
|
|
@@ -233,8 +235,9 @@ const GaugeChart = memo(
|
|
|
233
235
|
|
|
234
236
|
// Labels for major ticks
|
|
235
237
|
if (showMinMaxLabels) {
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
+
const labelRadius = tickRadius - tickLength - 15;
|
|
239
|
+
const labelX = centerX + labelRadius * Math.cos(tickAngle);
|
|
240
|
+
const labelY = centerY + labelRadius * Math.sin(tickAngle);
|
|
238
241
|
|
|
239
242
|
ticks.push(
|
|
240
243
|
<text
|
|
@@ -242,7 +245,7 @@ const GaugeChart = memo(
|
|
|
242
245
|
x={labelX}
|
|
243
246
|
y={labelY}
|
|
244
247
|
textAnchor="middle"
|
|
245
|
-
dominantBaseline="
|
|
248
|
+
dominantBaseline="central"
|
|
246
249
|
fontSize="12"
|
|
247
250
|
fill="var(--atomix-brand-text-emphasis)"
|
|
248
251
|
>
|
|
@@ -253,9 +256,11 @@ const GaugeChart = memo(
|
|
|
253
256
|
}
|
|
254
257
|
|
|
255
258
|
// Minor ticks
|
|
256
|
-
for (let i = 0; i
|
|
259
|
+
for (let i = 0; i <= majorTicks * minorTicks; i++) {
|
|
260
|
+
if (i % minorTicks === 0) continue;
|
|
261
|
+
|
|
257
262
|
const tickAngle = startAngleRad + (i / (majorTicks * minorTicks)) * angleRange;
|
|
258
|
-
const tickRadius =
|
|
263
|
+
const tickRadius = innerRadius - 2;
|
|
259
264
|
const tickLength = radius * 0.025;
|
|
260
265
|
const x1 = centerX + tickRadius * Math.cos(tickAngle);
|
|
261
266
|
const y1 = centerY + tickRadius * Math.sin(tickAngle);
|
|
@@ -276,19 +281,22 @@ const GaugeChart = memo(
|
|
|
276
281
|
}
|
|
277
282
|
}
|
|
278
283
|
|
|
284
|
+
const innerRadius = radius * (1 - thickness);
|
|
285
|
+
|
|
279
286
|
// Create needle
|
|
280
287
|
const needle = showNeedle ? (
|
|
281
288
|
<g>
|
|
282
289
|
<line
|
|
283
290
|
x1={centerX}
|
|
284
291
|
y1={centerY}
|
|
285
|
-
x2={centerX +
|
|
286
|
-
y2={centerY +
|
|
292
|
+
x2={centerX + (innerRadius - 15) * Math.cos(valueAngle)}
|
|
293
|
+
y2={centerY + (innerRadius - 15) * Math.sin(valueAngle)}
|
|
287
294
|
stroke={needleColor}
|
|
288
|
-
strokeWidth="
|
|
295
|
+
strokeWidth="4"
|
|
289
296
|
strokeLinecap="round"
|
|
290
297
|
/>
|
|
291
298
|
<circle cx={centerX} cy={centerY} r="8" fill={needleColor} />
|
|
299
|
+
<circle cx={centerX} cy={centerY} r="3" fill="var(--atomix-primary-bg, #fff)" />
|
|
292
300
|
</g>
|
|
293
301
|
) : null;
|
|
294
302
|
|
|
@@ -296,9 +304,9 @@ const GaugeChart = memo(
|
|
|
296
304
|
const valueText = showValue ? (
|
|
297
305
|
<text
|
|
298
306
|
x={centerX}
|
|
299
|
-
y={centerY +
|
|
307
|
+
y={centerY + 35}
|
|
300
308
|
textAnchor="middle"
|
|
301
|
-
fontSize="
|
|
309
|
+
fontSize="32"
|
|
302
310
|
fontWeight="bold"
|
|
303
311
|
fill="var(--atomix-primary-text-emphasis)"
|
|
304
312
|
>
|
|
@@ -310,7 +318,7 @@ const GaugeChart = memo(
|
|
|
310
318
|
const labelText = label ? (
|
|
311
319
|
<text
|
|
312
320
|
x={centerX}
|
|
313
|
-
y={labelPosition === 'top' ? centerY - radius * 0.7 : centerY + radius * 0.7}
|
|
321
|
+
y={labelPosition === 'top' ? centerY - radius * 0.7 : centerY + radius * 0.7 + 10}
|
|
314
322
|
textAnchor="middle"
|
|
315
323
|
fontSize="16"
|
|
316
324
|
fill="var(--atomix-brand-text-emphasis)"
|