@bashem/rn-charts 0.0.2

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 (97) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +35 -0
  3. package/lib/module/index.js +14 -0
  4. package/lib/module/index.js.map +1 -0
  5. package/lib/module/package.json +1 -0
  6. package/lib/module/skia/AreaChart/AreaChart.js +122 -0
  7. package/lib/module/skia/AreaChart/AreaChart.js.map +1 -0
  8. package/lib/module/skia/AreaChart/useAreaChart.js +141 -0
  9. package/lib/module/skia/AreaChart/useAreaChart.js.map +1 -0
  10. package/lib/module/skia/BarChart/BarChart.js +127 -0
  11. package/lib/module/skia/BarChart/BarChart.js.map +1 -0
  12. package/lib/module/skia/BarChart/useBarChart.js +172 -0
  13. package/lib/module/skia/BarChart/useBarChart.js.map +1 -0
  14. package/lib/module/skia/Common/VerticalLabel.js +73 -0
  15. package/lib/module/skia/Common/VerticalLabel.js.map +1 -0
  16. package/lib/module/skia/HeatMap/HeatMap.js +76 -0
  17. package/lib/module/skia/HeatMap/HeatMap.js.map +1 -0
  18. package/lib/module/skia/HeatMap/useHeatMap.js +139 -0
  19. package/lib/module/skia/HeatMap/useHeatMap.js.map +1 -0
  20. package/lib/module/skia/PieChart/PieChart.js +96 -0
  21. package/lib/module/skia/PieChart/PieChart.js.map +1 -0
  22. package/lib/module/skia/PieChart/usePieChart.js +103 -0
  23. package/lib/module/skia/PieChart/usePieChart.js.map +1 -0
  24. package/lib/module/skia/Popup.js +58 -0
  25. package/lib/module/skia/Popup.js.map +1 -0
  26. package/lib/module/skia/Progress/LinearProgress.js +69 -0
  27. package/lib/module/skia/Progress/LinearProgress.js.map +1 -0
  28. package/lib/module/skia/Progress/SemiCircleProgress.js +70 -0
  29. package/lib/module/skia/Progress/SemiCircleProgress.js.map +1 -0
  30. package/lib/module/skia/RadarChart/RadarChart.js +98 -0
  31. package/lib/module/skia/RadarChart/RadarChart.js.map +1 -0
  32. package/lib/module/skia/RadarChart/useRadarChart.js +164 -0
  33. package/lib/module/skia/RadarChart/useRadarChart.js.map +1 -0
  34. package/lib/module/skia/common.js +65 -0
  35. package/lib/module/skia/common.js.map +1 -0
  36. package/lib/module/util/colors.js +182 -0
  37. package/lib/module/util/colors.js.map +1 -0
  38. package/lib/module/util/util.js +71 -0
  39. package/lib/module/util/util.js.map +1 -0
  40. package/lib/typescript/index.d.ts +2 -0
  41. package/lib/typescript/index.d.ts.map +1 -0
  42. package/lib/typescript/package.json +1 -0
  43. package/lib/typescript/src/index.d.ts +10 -0
  44. package/lib/typescript/src/index.d.ts.map +1 -0
  45. package/lib/typescript/src/skia/AreaChart/AreaChart.d.ts +25 -0
  46. package/lib/typescript/src/skia/AreaChart/AreaChart.d.ts.map +1 -0
  47. package/lib/typescript/src/skia/AreaChart/useAreaChart.d.ts +47 -0
  48. package/lib/typescript/src/skia/AreaChart/useAreaChart.d.ts.map +1 -0
  49. package/lib/typescript/src/skia/BarChart/BarChart.d.ts +30 -0
  50. package/lib/typescript/src/skia/BarChart/BarChart.d.ts.map +1 -0
  51. package/lib/typescript/src/skia/BarChart/useBarChart.d.ts +41 -0
  52. package/lib/typescript/src/skia/BarChart/useBarChart.d.ts.map +1 -0
  53. package/lib/typescript/src/skia/Common/VerticalLabel.d.ts +17 -0
  54. package/lib/typescript/src/skia/Common/VerticalLabel.d.ts.map +1 -0
  55. package/lib/typescript/src/skia/HeatMap/HeatMap.d.ts +33 -0
  56. package/lib/typescript/src/skia/HeatMap/HeatMap.d.ts.map +1 -0
  57. package/lib/typescript/src/skia/HeatMap/useHeatMap.d.ts +25 -0
  58. package/lib/typescript/src/skia/HeatMap/useHeatMap.d.ts.map +1 -0
  59. package/lib/typescript/src/skia/PieChart/PieChart.d.ts +27 -0
  60. package/lib/typescript/src/skia/PieChart/PieChart.d.ts.map +1 -0
  61. package/lib/typescript/src/skia/PieChart/usePieChart.d.ts +13 -0
  62. package/lib/typescript/src/skia/PieChart/usePieChart.d.ts.map +1 -0
  63. package/lib/typescript/src/skia/Popup.d.ts +26 -0
  64. package/lib/typescript/src/skia/Popup.d.ts.map +1 -0
  65. package/lib/typescript/src/skia/Progress/LinearProgress.d.ts +18 -0
  66. package/lib/typescript/src/skia/Progress/LinearProgress.d.ts.map +1 -0
  67. package/lib/typescript/src/skia/Progress/SemiCircleProgress.d.ts +18 -0
  68. package/lib/typescript/src/skia/Progress/SemiCircleProgress.d.ts.map +1 -0
  69. package/lib/typescript/src/skia/RadarChart/RadarChart.d.ts +27 -0
  70. package/lib/typescript/src/skia/RadarChart/RadarChart.d.ts.map +1 -0
  71. package/lib/typescript/src/skia/RadarChart/useRadarChart.d.ts +41 -0
  72. package/lib/typescript/src/skia/RadarChart/useRadarChart.d.ts.map +1 -0
  73. package/lib/typescript/src/skia/common.d.ts +31 -0
  74. package/lib/typescript/src/skia/common.d.ts.map +1 -0
  75. package/lib/typescript/src/util/colors.d.ts +4 -0
  76. package/lib/typescript/src/util/colors.d.ts.map +1 -0
  77. package/lib/typescript/src/util/util.d.ts +33 -0
  78. package/lib/typescript/src/util/util.d.ts.map +1 -0
  79. package/package.json +172 -0
  80. package/src/index.tsx +12 -0
  81. package/src/skia/AreaChart/AreaChart.tsx +140 -0
  82. package/src/skia/AreaChart/useAreaChart.ts +180 -0
  83. package/src/skia/BarChart/BarChart.tsx +190 -0
  84. package/src/skia/BarChart/useBarChart.ts +210 -0
  85. package/src/skia/Common/VerticalLabel.tsx +91 -0
  86. package/src/skia/HeatMap/HeatMap.tsx +106 -0
  87. package/src/skia/HeatMap/useHeatMap.ts +175 -0
  88. package/src/skia/PieChart/PieChart.tsx +114 -0
  89. package/src/skia/PieChart/usePieChart.ts +156 -0
  90. package/src/skia/Popup.tsx +125 -0
  91. package/src/skia/Progress/LinearProgress.tsx +84 -0
  92. package/src/skia/Progress/SemiCircleProgress.tsx +82 -0
  93. package/src/skia/RadarChart/RadarChart.tsx +159 -0
  94. package/src/skia/RadarChart/useRadarChart.ts +208 -0
  95. package/src/skia/common.ts +82 -0
  96. package/src/util/colors.ts +186 -0
  97. package/src/util/util.ts +89 -0
@@ -0,0 +1,84 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { View, Button, useWindowDimensions } from 'react-native';
3
+ import {
4
+ Canvas,
5
+ LinearGradient,
6
+ Rect,
7
+ RoundedRect,
8
+ } from '@shopify/react-native-skia';
9
+ import type { CommonStyle } from '../common';
10
+
11
+ export interface LinearProgressStyles extends CommonStyle {
12
+ width?: number;
13
+ height?: number;
14
+ radius?: number;
15
+ tintColor?: string;
16
+ backgroundColor?: string;
17
+ tintColors?: string[];
18
+ tineColorsPositions?: number[];
19
+ backgroundColors?: string[];
20
+ backgroundColorsPositions?: number[];
21
+ }
22
+
23
+ export interface LinearProgressProps {
24
+ style: LinearProgressStyles;
25
+ progress: number; // value between 0 and 1
26
+ }
27
+
28
+ export default function LinearProgress({
29
+ progress,
30
+ style,
31
+ }: LinearProgressProps) {
32
+ const width = style.width ?? 300;
33
+ const height = style.height ?? 20;
34
+ const radius = style.radius ?? 0;
35
+ const tintColor = style.tintColor ?? '#4A90E2';
36
+
37
+ // Animate progress
38
+ useEffect(() => {
39
+ // runTiming(progress, 0.7, { duration: 1000 }); // progress to 70%
40
+ }, []);
41
+
42
+ return (
43
+ <View>
44
+ <Canvas style={{ width, height }}>
45
+ {/* Background bar */}
46
+ <RoundedRect
47
+ x={0}
48
+ y={0}
49
+ width={width}
50
+ height={height}
51
+ r={radius}
52
+ color={style.backgroundColor}
53
+ >
54
+ {style.backgroundColors && (
55
+ <LinearGradient
56
+ start={{ x: 0, y: 0 }}
57
+ end={{ x: width, y: 0 }}
58
+ colors={style.backgroundColors}
59
+ positions={style.backgroundColorsPositions}
60
+ />
61
+ )}
62
+ </RoundedRect>
63
+ {/* Foreground progress */}
64
+ <RoundedRect
65
+ x={0}
66
+ y={0}
67
+ width={progress * width} // animate width
68
+ height={height}
69
+ r={radius}
70
+ color={style.tintColor}
71
+ >
72
+ {style.tintColors && (
73
+ <LinearGradient
74
+ start={{ x: 0, y: 0 }}
75
+ end={{ x: width, y: 0 }}
76
+ colors={style.tintColors}
77
+ positions={style.tineColorsPositions}
78
+ />
79
+ )}
80
+ </RoundedRect>
81
+ </Canvas>
82
+ </View>
83
+ );
84
+ }
@@ -0,0 +1,82 @@
1
+ import { View } from 'react-native';
2
+ import {
3
+ Canvas,
4
+ LinearGradient,
5
+ RoundedRect,
6
+ } from '@shopify/react-native-skia';
7
+ import type { CommonStyle } from '../common';
8
+
9
+ export interface SemiCircleProgressStyles extends CommonStyle {
10
+ width?: number;
11
+ height?: number;
12
+ radius?: number;
13
+ tintColor?: string;
14
+ backgroundColor?: string;
15
+ tintColors?: string[];
16
+ tineColorsPositions?: number[];
17
+ backgroundColors?: string[];
18
+ backgroundColorsPositions?: number[];
19
+ }
20
+
21
+ export interface SemiCircleProgressProps {
22
+ style: SemiCircleProgressStyles;
23
+ progress: number;
24
+ }
25
+
26
+ export default function SemiCircleProgress({
27
+ progress,
28
+ style,
29
+ }: SemiCircleProgressProps) {
30
+ const width = style.width ?? 300;
31
+ const height = style.height ?? 20;
32
+ const radius = style.radius ?? 0;
33
+ const tintColor = style.tintColor ?? '#4A90E2';
34
+
35
+ return (
36
+ <View
37
+ onLayout={(event) => {
38
+ const { width, height } = event.nativeEvent.layout;
39
+ console.log('Layout width, height:', width, height);
40
+ }}
41
+ >
42
+ <Canvas style={{ width, height }}>
43
+ {/* Background bar */}
44
+ <RoundedRect
45
+ x={0}
46
+ y={0}
47
+ width={width}
48
+ height={height}
49
+ r={radius}
50
+ color={style.backgroundColor}
51
+ >
52
+ {style.backgroundColors && (
53
+ <LinearGradient
54
+ start={{ x: 0, y: 0 }}
55
+ end={{ x: width, y: 0 }}
56
+ colors={style.backgroundColors}
57
+ positions={style.backgroundColorsPositions}
58
+ />
59
+ )}
60
+ </RoundedRect>
61
+ {/* Foreground progress */}
62
+ <RoundedRect
63
+ x={0}
64
+ y={0}
65
+ width={progress * width} // animate width
66
+ height={height}
67
+ r={radius}
68
+ color={style.tintColor}
69
+ >
70
+ {style.tintColors && (
71
+ <LinearGradient
72
+ start={{ x: 0, y: 0 }}
73
+ end={{ x: width, y: 0 }}
74
+ colors={style.tintColors}
75
+ positions={style.tineColorsPositions}
76
+ />
77
+ )}
78
+ </RoundedRect>
79
+ </Canvas>
80
+ </View>
81
+ );
82
+ }
@@ -0,0 +1,159 @@
1
+ import React, { cloneElement, useMemo, type ReactNode } from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ StyleSheet,
6
+ type ViewStyle,
7
+ type TextStyle,
8
+ } from 'react-native';
9
+ import {
10
+ Canvas,
11
+ Path,
12
+ Group,
13
+ Circle,
14
+ } from '@shopify/react-native-skia';
15
+ import { type CommonStyle } from '../common';
16
+ import useRadarChart from './useRadarChart';
17
+
18
+ export interface RadarDatum {
19
+ values: number[];
20
+ backgroundColor?: string;
21
+ strokeColor?: string;
22
+ strokeWidth?: number;
23
+ }
24
+
25
+ export interface RadarChartStyle extends CommonStyle {
26
+ size?: number;
27
+ strokeWidth?: number;
28
+ strokeColor?: string;
29
+ centerDotRadius?: number;
30
+ centerDotColor?: string;
31
+ }
32
+
33
+ export interface RadarChartProps {
34
+ data: RadarDatum[];
35
+ labels?: string[];
36
+ levels?: number;
37
+ labelViews?: ReactNode[];
38
+ maxValue?: number;
39
+ minValue?: number;
40
+ style?: RadarChartStyle;
41
+ }
42
+
43
+ function RadarChart(props: RadarChartProps) {
44
+ const {
45
+ size,
46
+ cx,
47
+ cy,
48
+ gridPaths,
49
+ axisPaths,
50
+ dataPaths,
51
+ formattedLabels,
52
+ formattedLabelViews,
53
+ strokeWidth,
54
+ strokeColor,
55
+ centerDotRadius,
56
+ centerDotColor,
57
+ } = useRadarChart(props);
58
+
59
+ return (
60
+ <View
61
+ style={[
62
+ {
63
+ width: size,
64
+ height: size,
65
+ backgroundColor: props.style?.backgroundColor,
66
+ },
67
+ ]}
68
+ >
69
+ <Canvas style={{ width: size, height: size }}>
70
+ <Group>
71
+ {/* grid polygons */}
72
+ {gridPaths.map((gridPath, index) => (
73
+ <Path
74
+ key={index}
75
+ path={gridPath}
76
+ style="stroke"
77
+ strokeWidth={strokeWidth}
78
+ color={strokeColor}
79
+ />
80
+ ))}
81
+
82
+ {axisPaths.map((ap, index) => (
83
+ <Path
84
+ key={index}
85
+ path={ap}
86
+ style="stroke"
87
+ strokeWidth={strokeWidth}
88
+ color={strokeColor}
89
+ />
90
+ ))}
91
+
92
+ {dataPaths.map((pathDatum, index) => (
93
+ <Group key={index}>
94
+ <Path
95
+ path={pathDatum.path}
96
+ style="fill"
97
+ color={pathDatum.backgroundColor}
98
+ />
99
+ <Path
100
+ path={pathDatum.path}
101
+ style="stroke"
102
+ strokeWidth={pathDatum.strokeWidth}
103
+ color={pathDatum.strokeColor}
104
+ />
105
+ </Group>
106
+ ))}
107
+
108
+ {/* center dot */}
109
+ <Circle cx={cx} cy={cy} r={centerDotRadius} color={centerDotColor} />
110
+ </Group>
111
+ </Canvas>
112
+
113
+ {/* Labels overlay */}
114
+ <View
115
+ style={[
116
+ StyleSheet.absoluteFill,
117
+ { justifyContent: 'center', alignItems: 'center' },
118
+ ]}
119
+ pointerEvents="none"
120
+ >
121
+ {formattedLabelViews &&
122
+ formattedLabelViews.map((viewDataum, index) => {
123
+ let style: ViewStyle = {
124
+ position: 'absolute',
125
+ bottom: viewDataum.y,
126
+ };
127
+ if (viewDataum.align === 'left') style.left = viewDataum.x;
128
+ if (viewDataum.align === 'right') style.right = viewDataum.x;
129
+
130
+ return (
131
+ <View style={style} key={index}>
132
+ {viewDataum.view}
133
+ </View>
134
+ );
135
+ })}
136
+ {formattedLabels &&
137
+ formattedLabels.map((formatedlabel, index) => {
138
+ let style: TextStyle = {
139
+ position: 'absolute',
140
+ bottom: formatedlabel.y,
141
+ fontSize: 12,
142
+ includeFontPadding: false,
143
+ };
144
+
145
+ if (formatedlabel.align === 'left') style.left = formatedlabel.x;
146
+ if (formatedlabel.align === 'right') style.right = formatedlabel.x;
147
+
148
+ return (
149
+ <Text key={index} style={style}>
150
+ {formatedlabel.label}
151
+ </Text>
152
+ );
153
+ })}
154
+ </View>
155
+ </View>
156
+ );
157
+ }
158
+
159
+ export default RadarChart;
@@ -0,0 +1,208 @@
1
+ import { useMemo } from "react";
2
+ import { Skia, type SkPath } from "@shopify/react-native-skia";
3
+ import { arrayFrom } from "../../util/util";
4
+ import { getPaddings, type CommonStyle } from "../common";
5
+ import type { RadarChartProps } from "./RadarChart";
6
+
7
+ type Point = { x: number; y: number };
8
+
9
+ export interface RadarDatum {
10
+ values: number[];
11
+ backgroundColor?: string;
12
+ strokeColor?: string;
13
+ strokeWidth?: number;
14
+ }
15
+
16
+ interface RadarChartStyle extends CommonStyle {
17
+ size?: number;
18
+ strokeWidth?: number;
19
+ strokeColor?: string;
20
+ centerDotRadius?: number;
21
+ centerDotColor?: string;
22
+ }
23
+
24
+ export default function useRadarChart({
25
+ data,
26
+ labels,
27
+ labelViews,
28
+ levels = 5,
29
+ maxValue,
30
+ minValue = 0,
31
+ style,
32
+ }: RadarChartProps) {
33
+ const size = style?.size ?? 200;
34
+ const { paddingHorizontal, paddingVertical } = getPaddings(style);
35
+
36
+ const radius = size / 2 - Math.max(paddingHorizontal, paddingVertical) / 2;
37
+ const cx = size / 2;
38
+ const cy = size / 2;
39
+
40
+ // Compute max value
41
+ const safeMax = useMemo(() => {
42
+ if (maxValue !== undefined) return maxValue;
43
+ let m = minValue;
44
+ for (let datum of data)
45
+ for (let v of datum.values) m = Math.max(m, v);
46
+ return m;
47
+ }, [data, maxValue]);
48
+
49
+ // Determine number of axes
50
+ const angles = useMemo(() => {
51
+ let len = data[0]?.values.length ?? 0;
52
+ if (len === 0 && labels) len = labels.length;
53
+ if (len === 0 && labelViews) len = labelViews.length;
54
+ if (len === 0) return [];
55
+
56
+ return arrayFrom(len, 1).map(
57
+ (i) => -Math.PI / 2 + (i * 2 * Math.PI) / len
58
+ );
59
+ }, [data[0]?.values.length, labels?.length, labelViews?.length]);
60
+
61
+ const pointFor = (angle: number, r: number): Point => ({
62
+ x: cx + Math.cos(angle) * r,
63
+ y: cy + Math.sin(angle) * r,
64
+ });
65
+
66
+ // ------------------------------
67
+ // Grid paths
68
+ // ------------------------------
69
+ const gridPaths = useMemo(() => {
70
+ const arr: SkPath[] = [];
71
+ for (let lvl = 1; lvl <= levels; lvl++) {
72
+ const r = (radius * lvl) / levels;
73
+ const p = Skia.Path.Make();
74
+ angles.forEach((angle, i) => {
75
+ const pt = pointFor(angle, r);
76
+ if (i === 0) p.moveTo(pt.x, pt.y);
77
+ else p.lineTo(pt.x, pt.y);
78
+ });
79
+ p.close();
80
+ arr.push(p);
81
+ }
82
+ return arr;
83
+ }, [levels, radius, angles]);
84
+
85
+ // ------------------------------
86
+ // Axis paths
87
+ // ------------------------------
88
+ const axisPaths = useMemo(
89
+ () =>
90
+ angles.map((angle) => {
91
+ const p = Skia.Path.Make();
92
+ const outer = pointFor(angle, radius);
93
+ p.moveTo(cx, cy);
94
+ p.lineTo(outer.x, outer.y);
95
+ return p;
96
+ }),
97
+ [angles, radius]
98
+ );
99
+
100
+ // ------------------------------
101
+ // Data polygons
102
+ // ------------------------------
103
+ const dataPaths = useMemo(() => {
104
+ return data.map(({ values, ...rest }) => {
105
+ const path = Skia.Path.Make();
106
+ values.forEach((v, i) => {
107
+ const r = Math.max(0, Math.min(1, v / safeMax)) * radius;
108
+ const pt = pointFor(angles[i]!, r);
109
+ if (i === 0) path.moveTo(pt.x, pt.y);
110
+ else path.lineTo(pt.x, pt.y);
111
+ });
112
+ path.close();
113
+ return { path, ...rest };
114
+ });
115
+ }, [data, radius, safeMax, angles]);
116
+
117
+ // ------------------------------
118
+ // Labels
119
+ // ------------------------------
120
+ const formattedLabels = useMemo(() => {
121
+ if (!labels) return undefined;
122
+
123
+ const arr: {
124
+ x: number;
125
+ y: number;
126
+ label: string;
127
+ align: "left" | "center" | "right";
128
+ }[] = [];
129
+
130
+ const r = radius + 12;
131
+
132
+ angles.forEach((angle, i) => {
133
+ const p = pointFor(angle, r);
134
+ const deg = (angle * 180) / Math.PI;
135
+
136
+ let align: "left" | "center" | "right" = "center";
137
+ if (deg > -90 && deg < 90) align = "left";
138
+ else if (deg < -90 || deg > 90) {
139
+ align = "right";
140
+ p.x = size - p.x;
141
+ }
142
+
143
+ arr.push({
144
+ x: p.x,
145
+ y: size - p.y,
146
+ label: labels[i]!,
147
+ align,
148
+ });
149
+ });
150
+
151
+ return arr;
152
+ }, [labels, angles, radius]);
153
+
154
+ // ------------------------------
155
+ // Label Views
156
+ // ------------------------------
157
+ const formattedLabelViews = useMemo(() => {
158
+ if (!labelViews) return undefined;
159
+
160
+ const arr: {
161
+ x: number;
162
+ y: number;
163
+ view: React.ReactNode;
164
+ align: "left" | "center" | "right";
165
+ }[] = [];
166
+
167
+ const r = radius + 12;
168
+
169
+ angles.forEach((angle, i) => {
170
+ const p = pointFor(angle, r);
171
+ const deg = (angle * 180) / Math.PI;
172
+
173
+ let align: "left" | "center" | "right" = "center";
174
+ if (deg > -90 && deg < 90) align = "left";
175
+ else if (deg < -90 || deg > 90) {
176
+ align = "right";
177
+ p.x = size - p.x;
178
+ }
179
+
180
+ arr.push({
181
+ x: p.x,
182
+ y: size - p.y,
183
+ view: labelViews[i]!,
184
+ align,
185
+ });
186
+ });
187
+
188
+ return arr;
189
+ }, [labelViews, angles, radius]);
190
+
191
+ return {
192
+ size,
193
+ cx,
194
+ cy,
195
+ radius,
196
+ safeMax,
197
+ angles,
198
+ gridPaths,
199
+ axisPaths,
200
+ dataPaths,
201
+ formattedLabels,
202
+ formattedLabelViews,
203
+ strokeWidth: style?.strokeWidth ?? 2,
204
+ strokeColor: style?.strokeColor ?? "gray",
205
+ centerDotRadius: style?.centerDotRadius ?? 2,
206
+ centerDotColor: style?.centerDotColor ?? style?.strokeColor ?? "gray",
207
+ };
208
+ }
@@ -0,0 +1,82 @@
1
+ import { listFontFamilies, matchFont, Skia, TextAlign, type SkFont, type SkParagraph, type SkTextStyle } from "@shopify/react-native-skia";
2
+ import { Platform } from "react-native";
3
+
4
+ export interface CommonStyle {
5
+ padding?: number;
6
+ paddingTop?: number;
7
+ paddingBottom?: number;
8
+ paddingStart?: number;
9
+ paddingEnd?: number;
10
+ paddingLeft?: number;
11
+ paddingRight?: number;
12
+ backgroundColor?: string;
13
+ disableRTL?: boolean;
14
+ font?: SkFont;
15
+ fontSize?: number;
16
+ }
17
+
18
+ export function getCommonStyleFont(style?: CommonStyle) {
19
+ const fontSize = style?.font?.getSize() ?? style?.fontSize ?? 12;
20
+ const font = style?.font ?? getFont(fontSize);
21
+ return { font, fontSize };
22
+ }
23
+
24
+ export function getPaddings(style?: CommonStyle) {
25
+ const paddingTop = style?.paddingTop ?? style?.padding ?? 0;
26
+ const paddingBottom = style?.paddingBottom ?? style?.padding ?? 0;
27
+ const paddingLeft = style?.paddingLeft ?? style?.paddingStart ?? style?.padding ?? 0;
28
+ const paddingRight = style?.paddingRight ?? style?.paddingEnd ?? style?.padding ?? 0;
29
+ const paddingHorizontal = paddingLeft + paddingRight;
30
+ const paddingVertical = paddingTop + paddingBottom;
31
+
32
+ return {
33
+ paddingTop,
34
+ paddingBottom,
35
+ paddingLeft,
36
+ paddingRight,
37
+ paddingHorizontal,
38
+ paddingVertical
39
+ };
40
+ }
41
+
42
+ export function getRandomRGBColor() {
43
+ const r = Math.floor(Math.random() * 256);
44
+ const g = Math.floor(Math.random() * 256);
45
+ const b = Math.floor(Math.random() * 256);
46
+ return `rgb(${r},${g},${b})`;
47
+ };
48
+
49
+ export const systemFontFamilies = Platform.select({
50
+ ios: ["Helvetica", "Arial", "Courier"],
51
+ android: ["roboto-flex", "sans-serif", "Roboto", "serif", "monospace"],
52
+ default: ["sans-serif", "serif"],
53
+ });
54
+
55
+ export function getFont(size: number = 14): SkFont {
56
+ const fontFamily = systemFontFamilies[0];
57
+ // console.log("Available system font families:", listFontFamilies());
58
+ // console.log("Using font family:", fontFamily, systemFontFamilies);
59
+ const font = matchFont({
60
+ fontFamily,
61
+ fontSize: size,
62
+ fontStyle: "normal",
63
+ fontWeight: "normal",
64
+ });
65
+ return font;
66
+ }
67
+
68
+ export const font = getFont();
69
+
70
+ function createParagraph(text: string): SkParagraph {
71
+ const paragraphStyle = {
72
+ textAlign: TextAlign.Center,
73
+ };
74
+
75
+ const fontStyle: SkTextStyle = {
76
+ fontFamilies: systemFontFamilies,
77
+ fontSize: 14,
78
+ };
79
+ const paragraph = Skia.ParagraphBuilder.Make(paragraphStyle).pushStyle(fontStyle).addText(text).pop().build();
80
+
81
+ return paragraph;
82
+ }