universal-adaptive-bars 0.0.6 → 0.1.0
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/README.md +22 -17
- package/dist/smart-bar-chart.js +2882 -2749
- package/dist/smart-bar-chart.umd.cjs +20 -20
- package/package.json +1 -1
- package/src/lib/SmartBarChart.tsx +155 -63
- package/src/lib/SmartBarChartNative.tsx +152 -53
- package/src/lib/hooks/useChartData.ts +51 -3
- package/src/lib/types.ts +6 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import { parseISO, format, startOfWeek, endOfWeek, startOfMonth, isValid } from 'date-fns';
|
|
2
|
+
import { parseISO, format, startOfWeek, endOfWeek, startOfMonth, isValid, eachDayOfInterval, eachWeekOfInterval, eachMonthOfInterval, eachYearOfInterval } from 'date-fns';
|
|
3
3
|
import type { DataPoint, ChartView, RawDataPoint } from '../types';
|
|
4
4
|
|
|
5
5
|
interface UseChartDataProps {
|
|
@@ -11,12 +11,13 @@ interface UseChartDataProps {
|
|
|
11
11
|
date: string;
|
|
12
12
|
};
|
|
13
13
|
colors?: string[];
|
|
14
|
+
missingDataStrategy?: 'skip' | 'zero';
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
// Default Premium Palette
|
|
17
18
|
const DEFAULT_PALETTE = ['#6366f1', '#8b5cf6', '#ec4899', '#10b981', '#f59e0b', '#3b82f6', '#ef4444'];
|
|
18
19
|
|
|
19
|
-
export const useChartData = ({ data, view, dataKeys, colors = DEFAULT_PALETTE }: UseChartDataProps) => {
|
|
20
|
+
export const useChartData = ({ data, view, dataKeys, colors = DEFAULT_PALETTE, missingDataStrategy = 'skip' }: UseChartDataProps) => {
|
|
20
21
|
const processedData = useMemo(() => {
|
|
21
22
|
if (!data || data.length === 0) return [];
|
|
22
23
|
|
|
@@ -204,9 +205,56 @@ export const useChartData = ({ data, view, dataKeys, colors = DEFAULT_PALETTE }:
|
|
|
204
205
|
aggregated = sorted;
|
|
205
206
|
}
|
|
206
207
|
|
|
208
|
+
// Fill missing data
|
|
209
|
+
if (missingDataStrategy === 'zero' && aggregated.length > 0) {
|
|
210
|
+
const minDate = aggregated[0].date;
|
|
211
|
+
const maxDate = aggregated[aggregated.length - 1].date;
|
|
212
|
+
|
|
213
|
+
// Generate all intervals
|
|
214
|
+
let intervals: Date[] = [];
|
|
215
|
+
if (view === 'day') intervals = eachDayOfInterval({ start: minDate, end: maxDate });
|
|
216
|
+
else if (view === 'week') intervals = eachWeekOfInterval({ start: minDate, end: maxDate });
|
|
217
|
+
else if (view === 'month') intervals = eachMonthOfInterval({ start: minDate, end: maxDate });
|
|
218
|
+
else if (view === 'year') intervals = eachYearOfInterval({ start: minDate, end: maxDate });
|
|
219
|
+
|
|
220
|
+
// Map intervals to data
|
|
221
|
+
const lookup = new Map(aggregated.map(d => [d.id, d]));
|
|
222
|
+
|
|
223
|
+
aggregated = intervals.map((date, _idx) => {
|
|
224
|
+
let keyStr = '';
|
|
225
|
+
if (view === 'day') keyStr = format(date, 'yyyy-MM-dd');
|
|
226
|
+
else if (view === 'week') keyStr = format(startOfWeek(date), 'yyyy-MM-dd');
|
|
227
|
+
else if (view === 'month') keyStr = format(startOfMonth(date), 'yyyy-MM');
|
|
228
|
+
else if (view === 'year') keyStr = format(date, 'yyyy');
|
|
229
|
+
|
|
230
|
+
if (lookup.has(keyStr)) {
|
|
231
|
+
return lookup.get(keyStr)!;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Construct empty data point
|
|
235
|
+
let emptyLabel = '';
|
|
236
|
+
if (view === 'day') emptyLabel = format(date, 'E dd');
|
|
237
|
+
else if (view === 'week') {
|
|
238
|
+
const ws = startOfWeek(date);
|
|
239
|
+
const we = endOfWeek(date);
|
|
240
|
+
emptyLabel = `${format(ws, 'MMM dd')}-${format(we, 'MMM dd')}`;
|
|
241
|
+
}
|
|
242
|
+
else if (view === 'month') emptyLabel = format(date, 'MMM yy');
|
|
243
|
+
else if (view === 'year') emptyLabel = format(date, 'yyyy');
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
id: keyStr,
|
|
247
|
+
label: emptyLabel,
|
|
248
|
+
value: 0,
|
|
249
|
+
date: date,
|
|
250
|
+
color: colors[0]
|
|
251
|
+
};
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
207
255
|
return aggregated;
|
|
208
256
|
|
|
209
|
-
}, [data, view, dataKeys, colors]);
|
|
257
|
+
}, [data, view, dataKeys, colors, missingDataStrategy]);
|
|
210
258
|
|
|
211
259
|
return processedData;
|
|
212
260
|
};
|
package/src/lib/types.ts
CHANGED
|
@@ -42,7 +42,11 @@ export interface ChartTheme {
|
|
|
42
42
|
export interface SmartBarChartProps {
|
|
43
43
|
data: RawDataPoint[];
|
|
44
44
|
view?: ChartView;
|
|
45
|
-
variant?: 'default' | 'stacked';
|
|
45
|
+
variant?: 'default' | 'stacked' | 'grouped';
|
|
46
|
+
layout?: 'vertical' | 'horizontal';
|
|
47
|
+
missingDataStrategy?: 'skip' | 'zero';
|
|
48
|
+
valueFormatter?: (value: number) => string;
|
|
49
|
+
annotations?: { value: number; label?: string; color?: string; strokeDasharray?: string }[];
|
|
46
50
|
colors?: string[];
|
|
47
51
|
theme?: ChartTheme; // New
|
|
48
52
|
axisLabels?: { x?: string; y?: string };
|
|
@@ -58,6 +62,7 @@ export interface SmartBarChartProps {
|
|
|
58
62
|
};
|
|
59
63
|
onPredict?: (currentData: DataPoint[]) => Promise<DataPoint[]>;
|
|
60
64
|
onAnalyze?: (currentData: DataPoint[]) => Promise<string>;
|
|
65
|
+
renderTooltip?: (data: DataPoint) => React.ReactNode;
|
|
61
66
|
height?: number;
|
|
62
67
|
width?: number | string;
|
|
63
68
|
className?: string;
|