react-native-metrify 0.1.0-alpha.1 → 0.1.0-alpha.3

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 (101) hide show
  1. package/README.md +111 -51
  2. package/package.json +1 -2
  3. package/src/core/animation/index.ts +0 -113
  4. package/src/core/animation/index.web.ts +0 -112
  5. package/src/core/hooks/index.ts +0 -66
  6. package/src/core/index.ts +0 -26
  7. package/src/core/layout/index.ts +0 -101
  8. package/src/core/math/index.ts +0 -72
  9. package/src/core/package.json +0 -13
  10. package/src/core/theme/ThemeProvider.tsx +0 -36
  11. package/src/core/theme/index.ts +0 -5
  12. package/src/core/theme/themes.ts +0 -132
  13. package/src/core/types/index.ts +0 -164
  14. package/src/core/utils/responsive.ts +0 -203
  15. package/src/core/utils/time.ts +0 -100
  16. package/src/index.ts +0 -13
  17. package/src/renderer-svg/adapters/index.ts +0 -84
  18. package/src/renderer-svg/index.ts +0 -8
  19. package/src/renderer-svg/package.json +0 -17
  20. package/src/renderer-svg/paths/arc.ts +0 -93
  21. package/src/renderer-svg/paths/index.ts +0 -6
  22. package/src/renderer-svg/paths/line.ts +0 -83
  23. package/src/renderer-svg/paths/rect.ts +0 -80
  24. package/src/renderer-svg/primitives/AnimatedCircle.tsx +0 -48
  25. package/src/renderer-svg/primitives/AnimatedPath.tsx +0 -48
  26. package/src/renderer-svg/primitives/Text.tsx +0 -73
  27. package/src/renderer-svg/primitives/index.ts +0 -6
  28. package/src/widgets/AreaChart/AreaChart.tsx +0 -213
  29. package/src/widgets/AreaChart/index.ts +0 -2
  30. package/src/widgets/AreaChart/types.ts +0 -34
  31. package/src/widgets/BarChart/BarChart.tsx +0 -249
  32. package/src/widgets/BarChart/index.ts +0 -10
  33. package/src/widgets/BarChart/types.ts +0 -27
  34. package/src/widgets/BoxPlot/BoxPlot.tsx +0 -252
  35. package/src/widgets/BoxPlot/index.ts +0 -2
  36. package/src/widgets/BoxPlot/types.ts +0 -27
  37. package/src/widgets/BubbleChart/BubbleChart.tsx +0 -175
  38. package/src/widgets/BubbleChart/index.ts +0 -2
  39. package/src/widgets/BubbleChart/types.ts +0 -33
  40. package/src/widgets/CandlestickChart/CandlestickChart.tsx +0 -204
  41. package/src/widgets/CandlestickChart/index.ts +0 -2
  42. package/src/widgets/CandlestickChart/types.ts +0 -29
  43. package/src/widgets/FunnelChart/FunnelChart.tsx +0 -172
  44. package/src/widgets/FunnelChart/index.ts +0 -2
  45. package/src/widgets/FunnelChart/types.ts +0 -22
  46. package/src/widgets/Gauge/Gauge.tsx +0 -235
  47. package/src/widgets/Gauge/index.ts +0 -5
  48. package/src/widgets/Gauge/types.ts +0 -19
  49. package/src/widgets/GroupedBarChart/GroupedBarChart.tsx +0 -190
  50. package/src/widgets/GroupedBarChart/index.ts +0 -2
  51. package/src/widgets/GroupedBarChart/types.ts +0 -30
  52. package/src/widgets/Heatmap/Heatmap.tsx +0 -216
  53. package/src/widgets/Heatmap/index.ts +0 -2
  54. package/src/widgets/Heatmap/types.ts +0 -27
  55. package/src/widgets/Histogram/Histogram.tsx +0 -173
  56. package/src/widgets/Histogram/index.ts +0 -2
  57. package/src/widgets/Histogram/types.ts +0 -18
  58. package/src/widgets/HorizontalBarChart/HorizontalBarChart.tsx +0 -125
  59. package/src/widgets/HorizontalBarChart/index.ts +0 -2
  60. package/src/widgets/HorizontalBarChart/types.ts +0 -23
  61. package/src/widgets/KPI/KPI.tsx +0 -222
  62. package/src/widgets/KPI/index.ts +0 -5
  63. package/src/widgets/KPI/types.ts +0 -19
  64. package/src/widgets/LineChart/LineChart.tsx +0 -364
  65. package/src/widgets/LineChart/index.ts +0 -10
  66. package/src/widgets/LineChart/types.ts +0 -34
  67. package/src/widgets/MultiLineSparkline/MultiLineSparkline.tsx +0 -234
  68. package/src/widgets/MultiLineSparkline/index.ts +0 -10
  69. package/src/widgets/MultiLineSparkline/types.ts +0 -25
  70. package/src/widgets/PieChart/PieChart.tsx +0 -275
  71. package/src/widgets/PieChart/index.ts +0 -10
  72. package/src/widgets/PieChart/types.ts +0 -26
  73. package/src/widgets/Progress/Progress.tsx +0 -201
  74. package/src/widgets/Progress/index.ts +0 -5
  75. package/src/widgets/Progress/types.ts +0 -19
  76. package/src/widgets/RadarChart/RadarChart.tsx +0 -213
  77. package/src/widgets/RadarChart/index.ts +0 -2
  78. package/src/widgets/RadarChart/types.ts +0 -29
  79. package/src/widgets/SankeyDiagram/SankeyDiagram.tsx +0 -272
  80. package/src/widgets/SankeyDiagram/index.ts +0 -2
  81. package/src/widgets/SankeyDiagram/types.ts +0 -29
  82. package/src/widgets/ScatterPlot/ScatterPlot.tsx +0 -167
  83. package/src/widgets/ScatterPlot/index.ts +0 -2
  84. package/src/widgets/ScatterPlot/types.ts +0 -32
  85. package/src/widgets/Sparkline/Sparkline.tsx +0 -203
  86. package/src/widgets/Sparkline/index.ts +0 -5
  87. package/src/widgets/Sparkline/types.ts +0 -18
  88. package/src/widgets/StackedBarChart/StackedBarChart.tsx +0 -181
  89. package/src/widgets/StackedBarChart/index.ts +0 -2
  90. package/src/widgets/StackedBarChart/types.ts +0 -29
  91. package/src/widgets/SunburstChart/SunburstChart.tsx +0 -176
  92. package/src/widgets/SunburstChart/index.ts +0 -2
  93. package/src/widgets/SunburstChart/types.ts +0 -22
  94. package/src/widgets/Treemap/Treemap.tsx +0 -191
  95. package/src/widgets/Treemap/index.ts +0 -2
  96. package/src/widgets/Treemap/types.ts +0 -23
  97. package/src/widgets/WaterfallChart/WaterfallChart.tsx +0 -226
  98. package/src/widgets/WaterfallChart/index.ts +0 -2
  99. package/src/widgets/WaterfallChart/types.ts +0 -26
  100. package/src/widgets/index.ts +0 -40
  101. package/src/widgets/package.json +0 -18
@@ -1,125 +0,0 @@
1
- /**
2
- * HorizontalBarChart Widget - Bars go left to right
3
- */
4
- import React, { memo, useMemo } from 'react';
5
- import { View, Text as RNText, StyleSheet } from 'react-native';
6
- import Svg, { Rect } from 'react-native-svg';
7
- import { useWidgetDimensions, useWidgetTheme, normalize } from '../../core';
8
- import { HorizontalBarChartWidgetProps } from './types';
9
-
10
- export const HorizontalBarChart = memo<HorizontalBarChartWidgetProps>(({
11
- data: widgetData,
12
- width,
13
- height,
14
- loading = false,
15
- theme: themeOverride,
16
- barHeight = 24,
17
- barSpacing = 12,
18
- showValues = true,
19
- showLabels = true,
20
- maxBars = 15,
21
- testID,
22
- }) => {
23
- const theme = useWidgetTheme(themeOverride);
24
- const dimensions = useWidgetDimensions(width, height, 350, 300);
25
-
26
- if (loading) {
27
- return (
28
- <View style={[styles.container, { width: dimensions.width, height: dimensions.height, backgroundColor: theme.colors.surface, borderRadius: theme.radius.md }]} testID={`${testID}-loading`}>
29
- <RNText style={[styles.loadingText, { color: theme.colors.textSecondary }]}>Loading...</RNText>
30
- </View>
31
- );
32
- }
33
-
34
- if (!widgetData || !widgetData.data || widgetData.data.length === 0) {
35
- return (
36
- <View style={[styles.container, { width: dimensions.width, height: dimensions.height, backgroundColor: theme.colors.surface, borderRadius: theme.radius.md }]} testID={`${testID}-empty`}>
37
- <RNText style={[styles.emptyText, { color: theme.colors.textSecondary }]}>No data</RNText>
38
- </View>
39
- );
40
- }
41
-
42
- const { data, title } = widgetData;
43
- const displayData = data.slice(0, maxBars);
44
- const padding = theme.spacing.md;
45
- const titleHeight = title ? theme.fontScale.md + theme.spacing.sm : 0;
46
- const labelWidth = showLabels ? 80 : 0;
47
- const valueWidth = showValues ? 50 : 0;
48
-
49
- const chartWidth = dimensions.width - padding * 2 - labelWidth - valueWidth;
50
- const maxValue = useMemo(() => Math.max(...displayData.map(d => d.value)), [displayData]);
51
-
52
- const bars = useMemo(() => {
53
- return displayData.map((item, index) => {
54
- const normalizedValue = normalize(item.value, 0, maxValue);
55
- const barWidth = normalizedValue * chartWidth;
56
- const barY = index * (barHeight + barSpacing);
57
-
58
- return {
59
- x: 0,
60
- y: barY,
61
- width: barWidth,
62
- height: barHeight,
63
- color: item.color || theme.colors.chartPrimary,
64
- value: item.value,
65
- label: item.label,
66
- };
67
- });
68
- }, [displayData, maxValue, chartWidth, barHeight, barSpacing, theme.colors.chartPrimary]);
69
-
70
- const totalHeight = bars.length * (barHeight + barSpacing);
71
-
72
- return (
73
- <View style={[styles.wrapper, { width: dimensions.width, height: dimensions.height, backgroundColor: theme.colors.surface, borderRadius: theme.radius.md, padding }]} testID={testID}>
74
- {title && (
75
- <RNText style={[styles.title, { color: theme.colors.text, fontSize: theme.fontScale.md, fontWeight: 'bold', marginBottom: theme.spacing.sm }]}>
76
- {title}
77
- </RNText>
78
- )}
79
-
80
- <View style={styles.chartContainer}>
81
- {bars.map((bar, index) => (
82
- <View key={`row-${index}`} style={styles.barRow}>
83
- {showLabels && (
84
- <View style={[styles.labelContainer, { width: labelWidth }]}>
85
- <RNText style={[styles.label, { color: theme.colors.text, fontSize: theme.fontScale.sm }]} numberOfLines={1}>
86
- {bar.label}
87
- </RNText>
88
- </View>
89
- )}
90
-
91
- <View style={{ width: chartWidth, height: barHeight }}>
92
- <Svg width={chartWidth} height={barHeight}>
93
- <Rect x={bar.x} y={0} width={bar.width} height={bar.height} fill={bar.color} rx={theme.radius.sm} ry={theme.radius.sm} />
94
- </Svg>
95
- </View>
96
-
97
- {showValues && (
98
- <View style={[styles.valueContainer, { width: valueWidth }]}>
99
- <RNText style={[styles.value, { color: theme.colors.textSecondary, fontSize: theme.fontScale.sm }]}>
100
- {bar.value}
101
- </RNText>
102
- </View>
103
- )}
104
- </View>
105
- ))}
106
- </View>
107
- </View>
108
- );
109
- });
110
-
111
- HorizontalBarChart.displayName = 'HorizontalBarChart';
112
-
113
- const styles = StyleSheet.create({
114
- wrapper: { justifyContent: 'flex-start', alignItems: 'flex-start' },
115
- container: { justifyContent: 'center', alignItems: 'center' },
116
- loadingText: { fontSize: 16 },
117
- emptyText: { fontSize: 16 },
118
- title: { textAlign: 'center', width: '100%' },
119
- chartContainer: { flex: 1, width: '100%' },
120
- barRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 12 },
121
- labelContainer: { justifyContent: 'center', paddingRight: 8 },
122
- label: { textAlign: 'right' },
123
- valueContainer: { justifyContent: 'center', paddingLeft: 8 },
124
- value: { textAlign: 'left', fontWeight: '600' },
125
- });
@@ -1,2 +0,0 @@
1
- export { HorizontalBarChart } from './HorizontalBarChart';
2
- export type { HorizontalBarChartWidgetProps, HorizontalBarChartData, HorizontalBarDataPoint } from './types';
@@ -1,23 +0,0 @@
1
- /**
2
- * HorizontalBarChart Widget types
3
- */
4
- import { BaseWidgetProps } from '../../core';
5
-
6
- export interface HorizontalBarDataPoint {
7
- value: number;
8
- label: string;
9
- color?: string;
10
- }
11
-
12
- export interface HorizontalBarChartData {
13
- data: HorizontalBarDataPoint[];
14
- title?: string;
15
- }
16
-
17
- export interface HorizontalBarChartWidgetProps extends BaseWidgetProps<HorizontalBarChartData> {
18
- barHeight?: number;
19
- barSpacing?: number;
20
- showValues?: boolean;
21
- showLabels?: boolean;
22
- maxBars?: number;
23
- }
@@ -1,222 +0,0 @@
1
- /**
2
- * KPI Widget - Show one metric + trend
3
- * First widget implementation following the widget contract
4
- */
5
- import React, { memo, useMemo } from 'react';
6
- import { View, Text, StyleSheet } from 'react-native';
7
- import {
8
- useWidgetDimensions,
9
- useWidgetTheme,
10
- createFontSizeCalculator,
11
- } from '../../core';
12
- import { formatNumber, getTrendColor } from '../../renderer-svg/adapters';
13
- import { KPIWidgetProps } from './types';
14
-
15
- /**
16
- * KPI Widget Component
17
- */
18
- export const KPI = memo<KPIWidgetProps>(({
19
- data,
20
- width,
21
- height,
22
- loading = false,
23
- theme: themeOverride,
24
- animated = true,
25
- showTrend = true,
26
- showDelta = true,
27
- fontSize: fontConfig,
28
- testID,
29
- }) => {
30
- const theme = useWidgetTheme(themeOverride);
31
- const dimensions = useWidgetDimensions(width, height, 300, 120);
32
-
33
- // Create responsive font size calculator
34
- const fontSizes = useMemo(
35
- () => createFontSizeCalculator(dimensions.width, dimensions.height, fontConfig),
36
- [dimensions.width, dimensions.height, fontConfig]
37
- );
38
-
39
- // Handle states
40
- if (loading) {
41
- return (
42
- <View
43
- style={[
44
- styles.container,
45
- {
46
- width: dimensions.width,
47
- height: dimensions.height,
48
- backgroundColor: theme.colors.surface,
49
- borderRadius: theme.radius.md,
50
- },
51
- ]}
52
- testID={`${testID}-loading`}
53
- >
54
- <Text style={[styles.loadingText, { color: theme.colors.textSecondary }]}>
55
- Loading...
56
- </Text>
57
- </View>
58
- );
59
- }
60
-
61
- if (!data) {
62
- return (
63
- <View
64
- style={[
65
- styles.container,
66
- {
67
- width: dimensions.width,
68
- height: dimensions.height,
69
- backgroundColor: theme.colors.surface,
70
- borderRadius: theme.radius.md,
71
- },
72
- ]}
73
- testID={`${testID}-empty`}
74
- >
75
- <Text style={[styles.emptyText, { color: theme.colors.textSecondary }]}>
76
- No data
77
- </Text>
78
- </View>
79
- );
80
- }
81
-
82
- const { value, label, delta, trend = 'neutral', format = 'number' } = data;
83
-
84
- // Format the value (no animation for now - Expo Go limitation)
85
- const displayValue = useMemo(
86
- () => formatNumber(value, format),
87
- [value, format]
88
- );
89
-
90
- // Get trend color
91
- const trendColor = useMemo(
92
- () =>
93
- getTrendColor(trend, {
94
- positive: theme.colors.chartPositive,
95
- negative: theme.colors.chartNegative,
96
- neutral: theme.colors.chartNeutral,
97
- }),
98
- [trend, theme.colors]
99
- );
100
-
101
- // Format delta
102
- const formattedDelta = useMemo(() => {
103
- if (delta === undefined) return null;
104
- const sign = delta >= 0 ? '+' : '';
105
- return `${sign}${delta.toFixed(1)}%`;
106
- }, [delta]);
107
-
108
- // Trend icon
109
- const trendIcon = useMemo(() => {
110
- if (trend === 'up') return '↑';
111
- if (trend === 'down') return '↓';
112
- return '→';
113
- }, [trend]);
114
-
115
- return (
116
- <View
117
- style={[
118
- styles.container,
119
- {
120
- width: dimensions.width,
121
- height: dimensions.height,
122
- backgroundColor: theme.colors.surface,
123
- borderRadius: theme.radius.md,
124
- padding: theme.spacing.md,
125
- },
126
- ]}
127
- testID={testID}
128
- >
129
- {/* Label */}
130
- <Text
131
- style={[
132
- styles.label,
133
- {
134
- color: theme.colors.textSecondary,
135
- fontSize: fontSizes.label(theme.fontScale.sm),
136
- marginBottom: theme.spacing.xs,
137
- },
138
- ]}
139
- >
140
- {label}
141
- </Text>
142
-
143
- {/* Value */}
144
- <Text
145
- style={[
146
- styles.value,
147
- {
148
- color: theme.colors.text,
149
- fontSize: fontSizes.value(theme.fontScale.xxl),
150
- fontWeight: 'bold',
151
- },
152
- ]}
153
- >
154
- {displayValue}
155
- </Text>
156
-
157
- {/* Trend and Delta */}
158
- {(showTrend || showDelta) && (delta !== undefined || trend !== 'neutral') && (
159
- <View style={styles.trendContainer}>
160
- {showTrend && (
161
- <Text
162
- style={[
163
- styles.trendIcon,
164
- {
165
- color: trendColor,
166
- fontSize: fontSizes.secondary(theme.fontScale.md),
167
- marginRight: theme.spacing.xs,
168
- },
169
- ]}
170
- >
171
- {trendIcon}
172
- </Text>
173
- )}
174
- {showDelta && formattedDelta && (
175
- <Text
176
- style={[
177
- styles.delta,
178
- {
179
- color: trendColor,
180
- fontSize: fontSizes.secondary(theme.fontScale.md),
181
- fontWeight: '600',
182
- },
183
- ]}
184
- >
185
- {formattedDelta}
186
- </Text>
187
- )}
188
- </View>
189
- )}
190
- </View>
191
- );
192
- });
193
-
194
- KPI.displayName = 'KPI';
195
-
196
- const styles = StyleSheet.create({
197
- container: {
198
- justifyContent: 'center',
199
- alignItems: 'flex-start',
200
- },
201
- loadingText: {
202
- fontSize: 16,
203
- },
204
- emptyText: {
205
- fontSize: 16,
206
- },
207
- label: {
208
- textTransform: 'uppercase',
209
- letterSpacing: 0.5,
210
- },
211
- value: {
212
- marginBottom: 4,
213
- },
214
- trendContainer: {
215
- flexDirection: 'row',
216
- alignItems: 'center',
217
- },
218
- trendIcon: {
219
- fontWeight: 'bold',
220
- },
221
- delta: {},
222
- });
@@ -1,5 +0,0 @@
1
- /**
2
- * KPI Widget exports
3
- */
4
- export { KPI } from './KPI';
5
- export type { KPIWidgetProps, KPIData, KPIFormat } from './types';
@@ -1,19 +0,0 @@
1
- /**
2
- * KPI Widget types
3
- */
4
- import { BaseWidgetProps, TrendDirection } from '../../core/types';
5
-
6
- export type KPIFormat = 'number' | 'currency' | 'percent' | 'compact';
7
-
8
- export interface KPIData {
9
- value: number;
10
- label: string;
11
- delta?: number;
12
- trend?: TrendDirection;
13
- format?: KPIFormat;
14
- }
15
-
16
- export interface KPIWidgetProps extends BaseWidgetProps<KPIData> {
17
- showTrend?: boolean;
18
- showDelta?: boolean;
19
- }