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.
- package/README.md +111 -51
- package/package.json +1 -2
- package/src/core/animation/index.ts +0 -113
- package/src/core/animation/index.web.ts +0 -112
- package/src/core/hooks/index.ts +0 -66
- package/src/core/index.ts +0 -26
- package/src/core/layout/index.ts +0 -101
- package/src/core/math/index.ts +0 -72
- package/src/core/package.json +0 -13
- package/src/core/theme/ThemeProvider.tsx +0 -36
- package/src/core/theme/index.ts +0 -5
- package/src/core/theme/themes.ts +0 -132
- package/src/core/types/index.ts +0 -164
- package/src/core/utils/responsive.ts +0 -203
- package/src/core/utils/time.ts +0 -100
- package/src/index.ts +0 -13
- package/src/renderer-svg/adapters/index.ts +0 -84
- package/src/renderer-svg/index.ts +0 -8
- package/src/renderer-svg/package.json +0 -17
- package/src/renderer-svg/paths/arc.ts +0 -93
- package/src/renderer-svg/paths/index.ts +0 -6
- package/src/renderer-svg/paths/line.ts +0 -83
- package/src/renderer-svg/paths/rect.ts +0 -80
- package/src/renderer-svg/primitives/AnimatedCircle.tsx +0 -48
- package/src/renderer-svg/primitives/AnimatedPath.tsx +0 -48
- package/src/renderer-svg/primitives/Text.tsx +0 -73
- package/src/renderer-svg/primitives/index.ts +0 -6
- package/src/widgets/AreaChart/AreaChart.tsx +0 -213
- package/src/widgets/AreaChart/index.ts +0 -2
- package/src/widgets/AreaChart/types.ts +0 -34
- package/src/widgets/BarChart/BarChart.tsx +0 -249
- package/src/widgets/BarChart/index.ts +0 -10
- package/src/widgets/BarChart/types.ts +0 -27
- package/src/widgets/BoxPlot/BoxPlot.tsx +0 -252
- package/src/widgets/BoxPlot/index.ts +0 -2
- package/src/widgets/BoxPlot/types.ts +0 -27
- package/src/widgets/BubbleChart/BubbleChart.tsx +0 -175
- package/src/widgets/BubbleChart/index.ts +0 -2
- package/src/widgets/BubbleChart/types.ts +0 -33
- package/src/widgets/CandlestickChart/CandlestickChart.tsx +0 -204
- package/src/widgets/CandlestickChart/index.ts +0 -2
- package/src/widgets/CandlestickChart/types.ts +0 -29
- package/src/widgets/FunnelChart/FunnelChart.tsx +0 -172
- package/src/widgets/FunnelChart/index.ts +0 -2
- package/src/widgets/FunnelChart/types.ts +0 -22
- package/src/widgets/Gauge/Gauge.tsx +0 -235
- package/src/widgets/Gauge/index.ts +0 -5
- package/src/widgets/Gauge/types.ts +0 -19
- package/src/widgets/GroupedBarChart/GroupedBarChart.tsx +0 -190
- package/src/widgets/GroupedBarChart/index.ts +0 -2
- package/src/widgets/GroupedBarChart/types.ts +0 -30
- package/src/widgets/Heatmap/Heatmap.tsx +0 -216
- package/src/widgets/Heatmap/index.ts +0 -2
- package/src/widgets/Heatmap/types.ts +0 -27
- package/src/widgets/Histogram/Histogram.tsx +0 -173
- package/src/widgets/Histogram/index.ts +0 -2
- package/src/widgets/Histogram/types.ts +0 -18
- package/src/widgets/HorizontalBarChart/HorizontalBarChart.tsx +0 -125
- package/src/widgets/HorizontalBarChart/index.ts +0 -2
- package/src/widgets/HorizontalBarChart/types.ts +0 -23
- package/src/widgets/KPI/KPI.tsx +0 -222
- package/src/widgets/KPI/index.ts +0 -5
- package/src/widgets/KPI/types.ts +0 -19
- package/src/widgets/LineChart/LineChart.tsx +0 -364
- package/src/widgets/LineChart/index.ts +0 -10
- package/src/widgets/LineChart/types.ts +0 -34
- package/src/widgets/MultiLineSparkline/MultiLineSparkline.tsx +0 -234
- package/src/widgets/MultiLineSparkline/index.ts +0 -10
- package/src/widgets/MultiLineSparkline/types.ts +0 -25
- package/src/widgets/PieChart/PieChart.tsx +0 -275
- package/src/widgets/PieChart/index.ts +0 -10
- package/src/widgets/PieChart/types.ts +0 -26
- package/src/widgets/Progress/Progress.tsx +0 -201
- package/src/widgets/Progress/index.ts +0 -5
- package/src/widgets/Progress/types.ts +0 -19
- package/src/widgets/RadarChart/RadarChart.tsx +0 -213
- package/src/widgets/RadarChart/index.ts +0 -2
- package/src/widgets/RadarChart/types.ts +0 -29
- package/src/widgets/SankeyDiagram/SankeyDiagram.tsx +0 -272
- package/src/widgets/SankeyDiagram/index.ts +0 -2
- package/src/widgets/SankeyDiagram/types.ts +0 -29
- package/src/widgets/ScatterPlot/ScatterPlot.tsx +0 -167
- package/src/widgets/ScatterPlot/index.ts +0 -2
- package/src/widgets/ScatterPlot/types.ts +0 -32
- package/src/widgets/Sparkline/Sparkline.tsx +0 -203
- package/src/widgets/Sparkline/index.ts +0 -5
- package/src/widgets/Sparkline/types.ts +0 -18
- package/src/widgets/StackedBarChart/StackedBarChart.tsx +0 -181
- package/src/widgets/StackedBarChart/index.ts +0 -2
- package/src/widgets/StackedBarChart/types.ts +0 -29
- package/src/widgets/SunburstChart/SunburstChart.tsx +0 -176
- package/src/widgets/SunburstChart/index.ts +0 -2
- package/src/widgets/SunburstChart/types.ts +0 -22
- package/src/widgets/Treemap/Treemap.tsx +0 -191
- package/src/widgets/Treemap/index.ts +0 -2
- package/src/widgets/Treemap/types.ts +0 -23
- package/src/widgets/WaterfallChart/WaterfallChart.tsx +0 -226
- package/src/widgets/WaterfallChart/index.ts +0 -2
- package/src/widgets/WaterfallChart/types.ts +0 -26
- package/src/widgets/index.ts +0 -40
- package/src/widgets/package.json +0 -18
package/src/core/utils/time.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Time formatting utilities for chart labels
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export type TimeInterval = 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Format date based on interval
|
|
9
|
-
*/
|
|
10
|
-
export function formatTimeLabel(date: Date, interval: TimeInterval): string {
|
|
11
|
-
switch (interval) {
|
|
12
|
-
case 'minute':
|
|
13
|
-
return date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
|
|
14
|
-
|
|
15
|
-
case 'hour':
|
|
16
|
-
return date.toLocaleTimeString('en-US', { hour: '2-digit' });
|
|
17
|
-
|
|
18
|
-
case 'day':
|
|
19
|
-
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
|
20
|
-
|
|
21
|
-
case 'week':
|
|
22
|
-
return `Week ${getWeekNumber(date)}`;
|
|
23
|
-
|
|
24
|
-
case 'month':
|
|
25
|
-
return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
|
|
26
|
-
|
|
27
|
-
case 'year':
|
|
28
|
-
return date.getFullYear().toString();
|
|
29
|
-
|
|
30
|
-
default:
|
|
31
|
-
return date.toLocaleDateString();
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Get week number of year
|
|
37
|
-
*/
|
|
38
|
-
function getWeekNumber(date: Date): number {
|
|
39
|
-
const firstDayOfYear = new Date(date.getFullYear(), 0, 1);
|
|
40
|
-
const pastDaysOfYear = (date.getTime() - firstDayOfYear.getTime()) / 86400000;
|
|
41
|
-
return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Generate array of dates for a time range
|
|
46
|
-
*/
|
|
47
|
-
export function generateTimeLabels(
|
|
48
|
-
start: Date,
|
|
49
|
-
count: number,
|
|
50
|
-
interval: TimeInterval
|
|
51
|
-
): string[] {
|
|
52
|
-
const labels: string[] = [];
|
|
53
|
-
const current = new Date(start);
|
|
54
|
-
|
|
55
|
-
for (let i = 0; i < count; i++) {
|
|
56
|
-
labels.push(formatTimeLabel(current, interval));
|
|
57
|
-
|
|
58
|
-
// Increment based on interval
|
|
59
|
-
switch (interval) {
|
|
60
|
-
case 'minute':
|
|
61
|
-
current.setMinutes(current.getMinutes() + 1);
|
|
62
|
-
break;
|
|
63
|
-
case 'hour':
|
|
64
|
-
current.setHours(current.getHours() + 1);
|
|
65
|
-
break;
|
|
66
|
-
case 'day':
|
|
67
|
-
current.setDate(current.getDate() + 1);
|
|
68
|
-
break;
|
|
69
|
-
case 'week':
|
|
70
|
-
current.setDate(current.getDate() + 7);
|
|
71
|
-
break;
|
|
72
|
-
case 'month':
|
|
73
|
-
current.setMonth(current.getMonth() + 1);
|
|
74
|
-
break;
|
|
75
|
-
case 'year':
|
|
76
|
-
current.setFullYear(current.getFullYear() + 1);
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return labels;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Reduce labels to fit width (show every Nth label)
|
|
86
|
-
*/
|
|
87
|
-
export function reduceLabels(labels: string[], maxLabels: number): { label: string; index: number }[] {
|
|
88
|
-
if (labels.length <= maxLabels) {
|
|
89
|
-
return labels.map((label, index) => ({ label, index }));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const step = Math.ceil(labels.length / maxLabels);
|
|
93
|
-
const reduced: { label: string; index: number }[] = [];
|
|
94
|
-
|
|
95
|
-
for (let i = 0; i < labels.length; i += step) {
|
|
96
|
-
reduced.push({ label: labels[i], index: i });
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return reduced;
|
|
100
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dashboard Widgets - Main entry point
|
|
3
|
-
* Mobile-first dashboard widget library for React Native
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Core exports
|
|
7
|
-
export * from './core';
|
|
8
|
-
|
|
9
|
-
// Widget exports
|
|
10
|
-
export * from './widgets';
|
|
11
|
-
|
|
12
|
-
// Version
|
|
13
|
-
export const VERSION = '0.1.0';
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Adapters for bridging core utilities with SVG rendering
|
|
3
|
-
*/
|
|
4
|
-
import { Point } from '../../core/layout';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Converts data array to SVG points
|
|
8
|
-
*/
|
|
9
|
-
export function dataToPoints(
|
|
10
|
-
data: number[],
|
|
11
|
-
width: number,
|
|
12
|
-
height: number,
|
|
13
|
-
padding: number = 0
|
|
14
|
-
): Point[] {
|
|
15
|
-
if (data.length === 0) return [];
|
|
16
|
-
|
|
17
|
-
const min = Math.min(...data);
|
|
18
|
-
const max = Math.max(...data);
|
|
19
|
-
const range = max - min || 1;
|
|
20
|
-
|
|
21
|
-
const innerWidth = width - padding * 2;
|
|
22
|
-
const innerHeight = height - padding * 2;
|
|
23
|
-
const stepX = data.length > 1 ? innerWidth / (data.length - 1) : 0;
|
|
24
|
-
|
|
25
|
-
return data.map((value, index) => {
|
|
26
|
-
const normalizedY = (value - min) / range;
|
|
27
|
-
return {
|
|
28
|
-
x: padding + index * stepX,
|
|
29
|
-
y: padding + innerHeight - normalizedY * innerHeight,
|
|
30
|
-
};
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Formats numbers for display
|
|
36
|
-
*/
|
|
37
|
-
export function formatNumber(
|
|
38
|
-
value: number,
|
|
39
|
-
format?: 'number' | 'currency' | 'percent' | 'compact'
|
|
40
|
-
): string {
|
|
41
|
-
switch (format) {
|
|
42
|
-
case 'currency':
|
|
43
|
-
return new Intl.NumberFormat('en-US', {
|
|
44
|
-
style: 'currency',
|
|
45
|
-
currency: 'USD',
|
|
46
|
-
minimumFractionDigits: 0,
|
|
47
|
-
maximumFractionDigits: 0,
|
|
48
|
-
}).format(value);
|
|
49
|
-
|
|
50
|
-
case 'percent':
|
|
51
|
-
return `${value.toFixed(1)}%`;
|
|
52
|
-
|
|
53
|
-
case 'compact':
|
|
54
|
-
if (value >= 1_000_000) {
|
|
55
|
-
return `${(value / 1_000_000).toFixed(1)}M`;
|
|
56
|
-
}
|
|
57
|
-
if (value >= 1_000) {
|
|
58
|
-
return `${(value / 1_000).toFixed(1)}K`;
|
|
59
|
-
}
|
|
60
|
-
return value.toString();
|
|
61
|
-
|
|
62
|
-
case 'number':
|
|
63
|
-
default:
|
|
64
|
-
return new Intl.NumberFormat('en-US').format(value);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Gets color for trend direction
|
|
70
|
-
*/
|
|
71
|
-
export function getTrendColor(
|
|
72
|
-
trend: 'up' | 'down' | 'neutral',
|
|
73
|
-
colors: { positive: string; negative: string; neutral: string }
|
|
74
|
-
): string {
|
|
75
|
-
switch (trend) {
|
|
76
|
-
case 'up':
|
|
77
|
-
return colors.positive;
|
|
78
|
-
case 'down':
|
|
79
|
-
return colors.negative;
|
|
80
|
-
case 'neutral':
|
|
81
|
-
default:
|
|
82
|
-
return colors.neutral;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@dashboard-widgets/renderer-svg",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"description": "SVG renderer for dashboard widgets - primitives, paths, adapters",
|
|
5
|
-
"main": "index.ts",
|
|
6
|
-
"types": "index.ts",
|
|
7
|
-
"private": true,
|
|
8
|
-
"dependencies": {
|
|
9
|
-
"@dashboard-widgets/core": "*"
|
|
10
|
-
},
|
|
11
|
-
"peerDependencies": {
|
|
12
|
-
"react": ">=18.0.0",
|
|
13
|
-
"react-native": ">=0.70.0",
|
|
14
|
-
"react-native-svg": ">=13.0.0",
|
|
15
|
-
"react-native-reanimated": ">=3.0.0"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SVG arc path generator
|
|
3
|
-
* Translates geometry to SVG path strings
|
|
4
|
-
*/
|
|
5
|
-
import { polarToCartesian } from '../../core/math';
|
|
6
|
-
|
|
7
|
-
export interface ArcPathConfig {
|
|
8
|
-
cx: number;
|
|
9
|
-
cy: number;
|
|
10
|
-
radius: number;
|
|
11
|
-
startAngle: number;
|
|
12
|
-
endAngle: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Creates an SVG arc path
|
|
17
|
-
* @param config - Arc configuration
|
|
18
|
-
* @returns SVG path string
|
|
19
|
-
*/
|
|
20
|
-
export function createArcPath(config: ArcPathConfig): string {
|
|
21
|
-
const { cx, cy, radius, startAngle, endAngle } = config;
|
|
22
|
-
|
|
23
|
-
const start = polarToCartesian(cx, cy, radius, endAngle);
|
|
24
|
-
const end = polarToCartesian(cx, cy, radius, startAngle);
|
|
25
|
-
|
|
26
|
-
const largeArcFlag = endAngle - startAngle <= 180 ? '0' : '1';
|
|
27
|
-
|
|
28
|
-
return [
|
|
29
|
-
'M',
|
|
30
|
-
start.x,
|
|
31
|
-
start.y,
|
|
32
|
-
'A',
|
|
33
|
-
radius,
|
|
34
|
-
radius,
|
|
35
|
-
0,
|
|
36
|
-
largeArcFlag,
|
|
37
|
-
0,
|
|
38
|
-
end.x,
|
|
39
|
-
end.y,
|
|
40
|
-
].join(' ');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Creates a filled arc (pie slice) path
|
|
45
|
-
*/
|
|
46
|
-
export function createFilledArcPath(config: ArcPathConfig): string {
|
|
47
|
-
const { cx, cy } = config;
|
|
48
|
-
const arcPath = createArcPath(config);
|
|
49
|
-
|
|
50
|
-
return `${arcPath} L ${cx} ${cy} Z`;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Creates a donut arc path with inner and outer radius
|
|
55
|
-
*/
|
|
56
|
-
export function createDonutArcPath(
|
|
57
|
-
config: ArcPathConfig & { innerRadius: number }
|
|
58
|
-
): string {
|
|
59
|
-
const { cx, cy, radius, innerRadius, startAngle, endAngle } = config;
|
|
60
|
-
|
|
61
|
-
const outerStart = polarToCartesian(cx, cy, radius, endAngle);
|
|
62
|
-
const outerEnd = polarToCartesian(cx, cy, radius, startAngle);
|
|
63
|
-
const innerStart = polarToCartesian(cx, cy, innerRadius, endAngle);
|
|
64
|
-
const innerEnd = polarToCartesian(cx, cy, innerRadius, startAngle);
|
|
65
|
-
|
|
66
|
-
const largeArcFlag = endAngle - startAngle <= 180 ? '0' : '1';
|
|
67
|
-
|
|
68
|
-
return [
|
|
69
|
-
'M',
|
|
70
|
-
outerStart.x,
|
|
71
|
-
outerStart.y,
|
|
72
|
-
'A',
|
|
73
|
-
radius,
|
|
74
|
-
radius,
|
|
75
|
-
0,
|
|
76
|
-
largeArcFlag,
|
|
77
|
-
0,
|
|
78
|
-
outerEnd.x,
|
|
79
|
-
outerEnd.y,
|
|
80
|
-
'L',
|
|
81
|
-
innerEnd.x,
|
|
82
|
-
innerEnd.y,
|
|
83
|
-
'A',
|
|
84
|
-
innerRadius,
|
|
85
|
-
innerRadius,
|
|
86
|
-
0,
|
|
87
|
-
largeArcFlag,
|
|
88
|
-
1,
|
|
89
|
-
innerStart.x,
|
|
90
|
-
innerStart.y,
|
|
91
|
-
'Z',
|
|
92
|
-
].join(' ');
|
|
93
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SVG line path generators
|
|
3
|
-
*/
|
|
4
|
-
import { Point } from '../../core/layout';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Creates a simple line path from points
|
|
8
|
-
*/
|
|
9
|
-
export function createLinePath(points: Point[]): string {
|
|
10
|
-
if (points.length === 0) return '';
|
|
11
|
-
|
|
12
|
-
const pathParts = points.map((point, index) => {
|
|
13
|
-
const command = index === 0 ? 'M' : 'L';
|
|
14
|
-
return `${command} ${point.x} ${point.y}`;
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
return pathParts.join(' ');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Creates a smooth curve path using quadratic bezier curves
|
|
22
|
-
*/
|
|
23
|
-
export function createSmoothLinePath(points: Point[]): string {
|
|
24
|
-
if (points.length === 0) return '';
|
|
25
|
-
if (points.length === 1) return `M ${points[0].x} ${points[0].y}`;
|
|
26
|
-
|
|
27
|
-
const pathParts: string[] = [`M ${points[0].x} ${points[0].y}`];
|
|
28
|
-
|
|
29
|
-
for (let i = 0; i < points.length - 1; i++) {
|
|
30
|
-
const current = points[i];
|
|
31
|
-
const next = points[i + 1];
|
|
32
|
-
|
|
33
|
-
// Calculate control point (midpoint)
|
|
34
|
-
const controlX = (current.x + next.x) / 2;
|
|
35
|
-
const controlY = (current.y + next.y) / 2;
|
|
36
|
-
|
|
37
|
-
if (i === 0) {
|
|
38
|
-
// First segment: use simple control point
|
|
39
|
-
pathParts.push(`Q ${current.x} ${current.y} ${controlX} ${controlY}`);
|
|
40
|
-
} else {
|
|
41
|
-
// Subsequent segments: smooth curve
|
|
42
|
-
pathParts.push(`T ${controlX} ${controlY}`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Final point
|
|
47
|
-
const lastPoint = points[points.length - 1];
|
|
48
|
-
pathParts.push(`T ${lastPoint.x} ${lastPoint.y}`);
|
|
49
|
-
|
|
50
|
-
return pathParts.join(' ');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Creates an area path (filled under line)
|
|
55
|
-
*/
|
|
56
|
-
export function createAreaPath(
|
|
57
|
-
points: Point[],
|
|
58
|
-
baselineY: number
|
|
59
|
-
): string {
|
|
60
|
-
if (points.length === 0) return '';
|
|
61
|
-
|
|
62
|
-
const linePath = createLinePath(points);
|
|
63
|
-
const lastPoint = points[points.length - 1];
|
|
64
|
-
const firstPoint = points[0];
|
|
65
|
-
|
|
66
|
-
return `${linePath} L ${lastPoint.x} ${baselineY} L ${firstPoint.x} ${baselineY} Z`;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Creates a smooth area path
|
|
71
|
-
*/
|
|
72
|
-
export function createSmoothAreaPath(
|
|
73
|
-
points: Point[],
|
|
74
|
-
baselineY: number
|
|
75
|
-
): string {
|
|
76
|
-
if (points.length === 0) return '';
|
|
77
|
-
|
|
78
|
-
const linePath = createSmoothLinePath(points);
|
|
79
|
-
const lastPoint = points[points.length - 1];
|
|
80
|
-
const firstPoint = points[0];
|
|
81
|
-
|
|
82
|
-
return `${linePath} L ${lastPoint.x} ${baselineY} L ${firstPoint.x} ${baselineY} Z`;
|
|
83
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SVG rectangle path generators
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export interface RectConfig {
|
|
6
|
-
x: number;
|
|
7
|
-
y: number;
|
|
8
|
-
width: number;
|
|
9
|
-
height: number;
|
|
10
|
-
radius?: number;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Creates a rounded rectangle path
|
|
15
|
-
*/
|
|
16
|
-
export function createRoundedRectPath(config: RectConfig): string {
|
|
17
|
-
const { x, y, width, height, radius = 0 } = config;
|
|
18
|
-
|
|
19
|
-
if (radius === 0) {
|
|
20
|
-
return `M ${x} ${y} L ${x + width} ${y} L ${x + width} ${y + height} L ${x} ${y + height} Z`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const r = Math.min(radius, width / 2, height / 2);
|
|
24
|
-
|
|
25
|
-
return [
|
|
26
|
-
`M ${x + r} ${y}`,
|
|
27
|
-
`L ${x + width - r} ${y}`,
|
|
28
|
-
`Q ${x + width} ${y} ${x + width} ${y + r}`,
|
|
29
|
-
`L ${x + width} ${y + height - r}`,
|
|
30
|
-
`Q ${x + width} ${y + height} ${x + width - r} ${y + height}`,
|
|
31
|
-
`L ${x + r} ${y + height}`,
|
|
32
|
-
`Q ${x} ${y + height} ${x} ${y + height - r}`,
|
|
33
|
-
`L ${x} ${y + r}`,
|
|
34
|
-
`Q ${x} ${y} ${x + r} ${y}`,
|
|
35
|
-
'Z',
|
|
36
|
-
].join(' ');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Creates a rectangle with only specific corners rounded
|
|
41
|
-
*/
|
|
42
|
-
export function createPartiallyRoundedRectPath(
|
|
43
|
-
config: RectConfig & {
|
|
44
|
-
radiusTopLeft?: number;
|
|
45
|
-
radiusTopRight?: number;
|
|
46
|
-
radiusBottomRight?: number;
|
|
47
|
-
radiusBottomLeft?: number;
|
|
48
|
-
}
|
|
49
|
-
): string {
|
|
50
|
-
const {
|
|
51
|
-
x,
|
|
52
|
-
y,
|
|
53
|
-
width,
|
|
54
|
-
height,
|
|
55
|
-
radiusTopLeft = 0,
|
|
56
|
-
radiusTopRight = 0,
|
|
57
|
-
radiusBottomRight = 0,
|
|
58
|
-
radiusBottomLeft = 0,
|
|
59
|
-
} = config;
|
|
60
|
-
|
|
61
|
-
const rtl = Math.min(radiusTopLeft, width / 2, height / 2);
|
|
62
|
-
const rtr = Math.min(radiusTopRight, width / 2, height / 2);
|
|
63
|
-
const rbr = Math.min(radiusBottomRight, width / 2, height / 2);
|
|
64
|
-
const rbl = Math.min(radiusBottomLeft, width / 2, height / 2);
|
|
65
|
-
|
|
66
|
-
return [
|
|
67
|
-
`M ${x + rtl} ${y}`,
|
|
68
|
-
`L ${x + width - rtr} ${y}`,
|
|
69
|
-
rtr > 0 ? `Q ${x + width} ${y} ${x + width} ${y + rtr}` : '',
|
|
70
|
-
`L ${x + width} ${y + height - rbr}`,
|
|
71
|
-
rbr > 0 ? `Q ${x + width} ${y + height} ${x + width - rbr} ${y + height}` : '',
|
|
72
|
-
`L ${x + rbl} ${y + height}`,
|
|
73
|
-
rbl > 0 ? `Q ${x} ${y + height} ${x} ${y + height - rbl}` : '',
|
|
74
|
-
`L ${x} ${y + rtl}`,
|
|
75
|
-
rtl > 0 ? `Q ${x} ${y} ${x + rtl} ${y}` : '',
|
|
76
|
-
'Z',
|
|
77
|
-
]
|
|
78
|
-
.filter(Boolean)
|
|
79
|
-
.join(' ');
|
|
80
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Animated SVG Circle primitive
|
|
3
|
-
*/
|
|
4
|
-
import React, { memo } from 'react';
|
|
5
|
-
import Animated from 'react-native-reanimated';
|
|
6
|
-
import { Circle } from 'react-native-svg';
|
|
7
|
-
|
|
8
|
-
const AnimatedSVGCircle = Animated.createAnimatedComponent(Circle);
|
|
9
|
-
|
|
10
|
-
export interface AnimatedCircleProps {
|
|
11
|
-
cx: number;
|
|
12
|
-
cy: number;
|
|
13
|
-
r: number;
|
|
14
|
-
fill?: string;
|
|
15
|
-
stroke?: string;
|
|
16
|
-
strokeWidth?: number;
|
|
17
|
-
opacity?: number;
|
|
18
|
-
testID?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Memoized animated circle component
|
|
23
|
-
*/
|
|
24
|
-
export const AnimatedCircle = memo<AnimatedCircleProps>(({
|
|
25
|
-
cx,
|
|
26
|
-
cy,
|
|
27
|
-
r,
|
|
28
|
-
fill = 'transparent',
|
|
29
|
-
stroke = 'transparent',
|
|
30
|
-
strokeWidth = 1,
|
|
31
|
-
opacity = 1,
|
|
32
|
-
testID,
|
|
33
|
-
}) => {
|
|
34
|
-
return (
|
|
35
|
-
<AnimatedSVGCircle
|
|
36
|
-
cx={cx}
|
|
37
|
-
cy={cy}
|
|
38
|
-
r={r}
|
|
39
|
-
fill={fill}
|
|
40
|
-
stroke={stroke}
|
|
41
|
-
strokeWidth={strokeWidth}
|
|
42
|
-
opacity={opacity}
|
|
43
|
-
testID={testID}
|
|
44
|
-
/>
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
AnimatedCircle.displayName = 'AnimatedCircle';
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Animated SVG Path primitive
|
|
3
|
-
*/
|
|
4
|
-
import React, { memo } from 'react';
|
|
5
|
-
import Animated from 'react-native-reanimated';
|
|
6
|
-
import { Path } from 'react-native-svg';
|
|
7
|
-
|
|
8
|
-
const AnimatedSVGPath = Animated.createAnimatedComponent(Path);
|
|
9
|
-
|
|
10
|
-
export interface AnimatedPathProps {
|
|
11
|
-
d: string;
|
|
12
|
-
stroke?: string;
|
|
13
|
-
strokeWidth?: number;
|
|
14
|
-
fill?: string;
|
|
15
|
-
opacity?: number;
|
|
16
|
-
strokeLinecap?: 'butt' | 'round' | 'square';
|
|
17
|
-
strokeLinejoin?: 'miter' | 'round' | 'bevel';
|
|
18
|
-
testID?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Memoized animated path component
|
|
23
|
-
*/
|
|
24
|
-
export const AnimatedPath = memo<AnimatedPathProps>(({
|
|
25
|
-
d,
|
|
26
|
-
stroke = 'transparent',
|
|
27
|
-
strokeWidth = 1,
|
|
28
|
-
fill = 'transparent',
|
|
29
|
-
opacity = 1,
|
|
30
|
-
strokeLinecap = 'round',
|
|
31
|
-
strokeLinejoin = 'round',
|
|
32
|
-
testID,
|
|
33
|
-
}) => {
|
|
34
|
-
return (
|
|
35
|
-
<AnimatedSVGPath
|
|
36
|
-
d={d}
|
|
37
|
-
stroke={stroke}
|
|
38
|
-
strokeWidth={strokeWidth}
|
|
39
|
-
fill={fill}
|
|
40
|
-
opacity={opacity}
|
|
41
|
-
strokeLinecap={strokeLinecap}
|
|
42
|
-
strokeLinejoin={strokeLinejoin}
|
|
43
|
-
testID={testID}
|
|
44
|
-
/>
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
AnimatedPath.displayName = 'AnimatedPath';
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SVG Text primitive with centered text helper
|
|
3
|
-
*/
|
|
4
|
-
import React, { memo } from 'react';
|
|
5
|
-
import { Text as SVGText } from 'react-native-svg';
|
|
6
|
-
|
|
7
|
-
export interface TextProps {
|
|
8
|
-
x: number;
|
|
9
|
-
y: number;
|
|
10
|
-
text: string;
|
|
11
|
-
fontSize?: number;
|
|
12
|
-
fontWeight?: string | number;
|
|
13
|
-
fill?: string;
|
|
14
|
-
textAnchor?: 'start' | 'middle' | 'end';
|
|
15
|
-
alignmentBaseline?: 'baseline' | 'text-bottom' | 'alphabetic' | 'ideographic' | 'middle' | 'central' | 'mathematical' | 'text-top' | 'bottom' | 'center' | 'top' | 'text-before-edge' | 'text-after-edge' | 'before-edge' | 'after-edge' | 'hanging';
|
|
16
|
-
opacity?: number;
|
|
17
|
-
testID?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* SVG Text component with sensible defaults
|
|
22
|
-
*/
|
|
23
|
-
export const Text = memo<TextProps>(({
|
|
24
|
-
x,
|
|
25
|
-
y,
|
|
26
|
-
text,
|
|
27
|
-
fontSize = 14,
|
|
28
|
-
fontWeight = 'normal',
|
|
29
|
-
fill = '#000000',
|
|
30
|
-
textAnchor = 'middle',
|
|
31
|
-
alignmentBaseline = 'middle',
|
|
32
|
-
opacity = 1,
|
|
33
|
-
testID,
|
|
34
|
-
}) => {
|
|
35
|
-
return (
|
|
36
|
-
<SVGText
|
|
37
|
-
x={x}
|
|
38
|
-
y={y}
|
|
39
|
-
fontSize={fontSize}
|
|
40
|
-
fontWeight={fontWeight}
|
|
41
|
-
fill={fill}
|
|
42
|
-
textAnchor={textAnchor}
|
|
43
|
-
alignmentBaseline={alignmentBaseline}
|
|
44
|
-
opacity={opacity}
|
|
45
|
-
testID={testID}
|
|
46
|
-
>
|
|
47
|
-
{text}
|
|
48
|
-
</SVGText>
|
|
49
|
-
);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
Text.displayName = 'Text';
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Helper to create centered text props
|
|
56
|
-
*/
|
|
57
|
-
export function createCenteredTextProps(
|
|
58
|
-
x: number,
|
|
59
|
-
y: number,
|
|
60
|
-
text: string,
|
|
61
|
-
fontSize?: number,
|
|
62
|
-
fill?: string
|
|
63
|
-
): TextProps {
|
|
64
|
-
return {
|
|
65
|
-
x,
|
|
66
|
-
y,
|
|
67
|
-
text,
|
|
68
|
-
fontSize,
|
|
69
|
-
fill,
|
|
70
|
-
textAnchor: 'middle',
|
|
71
|
-
alignmentBaseline: 'middle',
|
|
72
|
-
};
|
|
73
|
-
}
|