react-native-financial-charts 1.0.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/LICENSE +20 -0
- package/README.md +309 -0
- package/lib/module/ChartContext.js +269 -0
- package/lib/module/ChartContext.js.map +1 -0
- package/lib/module/components/AnimatedTextInput.js +24 -0
- package/lib/module/components/AnimatedTextInput.js.map +1 -0
- package/lib/module/components/ChartArea.js +31 -0
- package/lib/module/components/ChartArea.js.map +1 -0
- package/lib/module/components/ChartBaseline.js +121 -0
- package/lib/module/components/ChartBaseline.js.map +1 -0
- package/lib/module/components/ChartCanvas.js +36 -0
- package/lib/module/components/ChartCanvas.js.map +1 -0
- package/lib/module/components/ChartCursor.js +75 -0
- package/lib/module/components/ChartCursor.js.map +1 -0
- package/lib/module/components/ChartLine.js +37 -0
- package/lib/module/components/ChartLine.js.map +1 -0
- package/lib/module/components/ChartTooltipDate.js +100 -0
- package/lib/module/components/ChartTooltipDate.js.map +1 -0
- package/lib/module/components/ChartTooltipValue.js +102 -0
- package/lib/module/components/ChartTooltipValue.js.map +1 -0
- package/lib/module/index.js +24 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/interfaces.js +4 -0
- package/lib/module/interfaces.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/utils.js +30 -0
- package/lib/module/utils.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/ChartContext.d.ts +16 -0
- package/lib/typescript/src/ChartContext.d.ts.map +1 -0
- package/lib/typescript/src/components/AnimatedTextInput.d.ts +8 -0
- package/lib/typescript/src/components/AnimatedTextInput.d.ts.map +1 -0
- package/lib/typescript/src/components/ChartArea.d.ts +9 -0
- package/lib/typescript/src/components/ChartArea.d.ts.map +1 -0
- package/lib/typescript/src/components/ChartBaseline.d.ts +10 -0
- package/lib/typescript/src/components/ChartBaseline.d.ts.map +1 -0
- package/lib/typescript/src/components/ChartCanvas.d.ts +7 -0
- package/lib/typescript/src/components/ChartCanvas.d.ts.map +1 -0
- package/lib/typescript/src/components/ChartCursor.d.ts +10 -0
- package/lib/typescript/src/components/ChartCursor.d.ts.map +1 -0
- package/lib/typescript/src/components/ChartLine.d.ts +10 -0
- package/lib/typescript/src/components/ChartLine.d.ts.map +1 -0
- package/lib/typescript/src/components/ChartTooltipDate.d.ts +9 -0
- package/lib/typescript/src/components/ChartTooltipDate.d.ts.map +1 -0
- package/lib/typescript/src/components/ChartTooltipValue.d.ts +9 -0
- package/lib/typescript/src/components/ChartTooltipValue.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +16 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/interfaces.d.ts +30 -0
- package/lib/typescript/src/interfaces.d.ts.map +1 -0
- package/lib/typescript/src/utils.d.ts +15 -0
- package/lib/typescript/src/utils.d.ts.map +1 -0
- package/package.json +171 -0
- package/src/ChartContext.tsx +311 -0
- package/src/components/AnimatedTextInput.tsx +27 -0
- package/src/components/ChartArea.tsx +28 -0
- package/src/components/ChartBaseline.tsx +137 -0
- package/src/components/ChartCanvas.tsx +28 -0
- package/src/components/ChartCursor.tsx +84 -0
- package/src/components/ChartLine.tsx +34 -0
- package/src/components/ChartTooltipDate.tsx +110 -0
- package/src/components/ChartTooltipValue.tsx +109 -0
- package/src/index.tsx +23 -0
- package/src/interfaces.ts +51 -0
- package/src/utils.ts +33 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Tony-Starkus
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# 📈 React Native Finance Kit
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="./docs/assets/0.gif" alt="Interactive Line" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
A **high-performance** financial charting library for React Native, built on the power of **Skia** and **Reanimated**.
|
|
8
|
+
|
|
9
|
+
Designed to render animations at **60/120 FPS** on the UI thread, with absolute touch precision (pixel-perfect) and support for complex gesture interactions.
|
|
10
|
+
|
|
11
|
+
## ✨ Highlights
|
|
12
|
+
|
|
13
|
+
- 🚀 **Native Performance:** GPU rendering via Skia.
|
|
14
|
+
- 👆 **Smooth Interaction:** Gestures run entirely on the UI Thread (Worklets).
|
|
15
|
+
- 🎯 **Pixel-Perfect Precision:** Hybrid algorithm using _Lookup Table_ + _Catmull-Rom_ ensures the cursor never drifts off the line.
|
|
16
|
+
- 🎨 **Customizable:** Colors, gradients, tooltips, and dimensions are fully adjustable.
|
|
17
|
+
|
|
18
|
+
## 📦 Installation
|
|
19
|
+
|
|
20
|
+
Since this library relies on powerful native modules, you must install the **Peer Dependencies**:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
yarn add react-native-finance-kit
|
|
24
|
+
|
|
25
|
+
# Install required dependencies
|
|
26
|
+
yarn add @shopify/react-native-skia react-native-reanimated react-native-gesture-handler d3
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
> **Note for Expo:**
|
|
30
|
+
> If you are using Expo Go, ensure that the Skia and Reanimated versions are compatible with your SDK.
|
|
31
|
+
> It's recommended using **Development Builds** (`npx expo run:android`) for the best performance.
|
|
32
|
+
|
|
33
|
+
## ⚡ Basic Usage
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import React from 'react';
|
|
37
|
+
import { View } from 'react-native';
|
|
38
|
+
import { Chart } from 'react-native-finance-kit';
|
|
39
|
+
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
40
|
+
|
|
41
|
+
const data = [
|
|
42
|
+
{ timestamp: 1625945400000, value: 33575.25 },
|
|
43
|
+
{ timestamp: 1625946300000, value: 33545.25 },
|
|
44
|
+
{ timestamp: 1625947200000, value: 33510.25 },
|
|
45
|
+
{ timestamp: 1625948100000, value: 33215.25 },
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
export default function App() {
|
|
49
|
+
return (
|
|
50
|
+
<View
|
|
51
|
+
style={{ flex: 1, justifyContent: 'center', backgroundColor: '#000' }}
|
|
52
|
+
>
|
|
53
|
+
<GestureHandlerRootView style={{ flex: 1, marginTop: 200 }}>
|
|
54
|
+
<Chart.Root data={data} height={250}>
|
|
55
|
+
<Chart.Canvas>
|
|
56
|
+
<Chart.Area />
|
|
57
|
+
<Chart.Line />
|
|
58
|
+
<Chart.Cursor />
|
|
59
|
+
</Chart.Canvas>
|
|
60
|
+
|
|
61
|
+
<Chart.Tooltip.Value />
|
|
62
|
+
<Chart.Tooltip.Date />
|
|
63
|
+
</Chart.Root>
|
|
64
|
+
</GestureHandlerRootView>
|
|
65
|
+
</View>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 💡 Examples
|
|
71
|
+
|
|
72
|
+
Here are some common patterns to customize the chart to your needs.
|
|
73
|
+
|
|
74
|
+
### 1. Custom Colors (The "Bitcoin" Look)
|
|
75
|
+
|
|
76
|
+
Customize the line color and the area gradient to match specific assets (e.g., Orange for BTC, Blue for ETH).
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
<Chart.Root data={data}>
|
|
80
|
+
<Chart.Canvas>
|
|
81
|
+
<Chart.Area
|
|
82
|
+
// Gradient from transparent Orange to transparent
|
|
83
|
+
gradientColors={['#F7931A50', '#F7931A00']}
|
|
84
|
+
/>
|
|
85
|
+
<Chart.Line
|
|
86
|
+
colors={['#F7931A']} // Solid Orange
|
|
87
|
+
strokeWidth={4}
|
|
88
|
+
/>
|
|
89
|
+
<Chart.Cursor crosshairColor="#F7931A" />
|
|
90
|
+
</Chart.Canvas>
|
|
91
|
+
</Chart.Root>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+

|
|
95
|
+
|
|
96
|
+
### 2. Minimal Sparkline
|
|
97
|
+
|
|
98
|
+
A small, simplified chart without tooltips or padding, perfect for lists or crypto tickers.
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
<Chart.Root
|
|
102
|
+
data={data}
|
|
103
|
+
height={60}
|
|
104
|
+
width={120}
|
|
105
|
+
padding={0} // Remove padding to touch edges
|
|
106
|
+
>
|
|
107
|
+
<Chart.Canvas>
|
|
108
|
+
<Chart.Line
|
|
109
|
+
strokeWidth={2}
|
|
110
|
+
colors={['#10B981', '#10B981', '#10B981', '#10B981']}
|
|
111
|
+
/>
|
|
112
|
+
</Chart.Canvas>
|
|
113
|
+
{/* No Tooltips, no Cursor */}
|
|
114
|
+
</Chart.Root>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+

|
|
118
|
+
|
|
119
|
+
### 3. Custom Currency Formatting (USD/EUR)
|
|
120
|
+
|
|
121
|
+
Use a Worklet to format values dynamically on the UI thread.
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
const formatUSD = (value: number) => {
|
|
125
|
+
'worklet';
|
|
126
|
+
return `$ ${value.toFixed(2)}`;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const formatEUR = (value: number) => {
|
|
130
|
+
'worklet';
|
|
131
|
+
return `€ ${value.toFixed(2).replace('.', ',')}`;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Usage
|
|
135
|
+
<Chart.Root data={data}>
|
|
136
|
+
<Chart.Canvas>
|
|
137
|
+
<Chart.Area />
|
|
138
|
+
<Chart.Line />
|
|
139
|
+
<Chart.Cursor />
|
|
140
|
+
</Chart.Canvas>
|
|
141
|
+
<Chart.ToolTip.Value format={formatUSD} />
|
|
142
|
+
</Chart.Root>;
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+

|
|
146
|
+
|
|
147
|
+
### 4. Customizing the Tooltip Style
|
|
148
|
+
|
|
149
|
+
Change the background color and border radius of the floating tooltip.
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
<Chart.Root data={data}>
|
|
153
|
+
<Chart.Canvas>
|
|
154
|
+
<Chart.Area />
|
|
155
|
+
<Chart.Line />
|
|
156
|
+
<Chart.Cursor />
|
|
157
|
+
</Chart.Canvas>
|
|
158
|
+
<Chart.Tooltip.Value
|
|
159
|
+
containerStyle={{
|
|
160
|
+
backgroundColor: 'white',
|
|
161
|
+
borderRadius: 4,
|
|
162
|
+
borderWidth: 1,
|
|
163
|
+
borderColor: '#E5E7EB',
|
|
164
|
+
}}
|
|
165
|
+
style={{
|
|
166
|
+
color: 'black',
|
|
167
|
+
fontSize: 14,
|
|
168
|
+
}}
|
|
169
|
+
/>
|
|
170
|
+
</Chart.Root>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+

|
|
174
|
+
|
|
175
|
+
## 🛠️ API Reference
|
|
176
|
+
|
|
177
|
+
### `<Chart.Root />`
|
|
178
|
+
|
|
179
|
+
The parent component that manages state and calculations.
|
|
180
|
+
|
|
181
|
+
| Prop | Type | Default | Description |
|
|
182
|
+
| ---------------- | ------------- | -------------- | ---------------------------------------- |
|
|
183
|
+
| `data` | `DataPoint[]` | **Required** | `{ timestamp: number, value: number }[]` |
|
|
184
|
+
| `height` | `number` | `250` | Total height of the chart |
|
|
185
|
+
| `width` | `number` | `Screen Width` | Total width of the chart |
|
|
186
|
+
| `padding` | `number` | `20` | Internal horizontal padding |
|
|
187
|
+
| `containerStyle` | `ViewStyle` | `{}` | Styles for the main container |
|
|
188
|
+
|
|
189
|
+
### `<Chart.Canvas />`
|
|
190
|
+
|
|
191
|
+
The wrapper for all Skia elements.
|
|
192
|
+
|
|
193
|
+
| Prop | Type | Default | Description |
|
|
194
|
+
| ---------- | ----------------- | ------- | --------------------------------------- |
|
|
195
|
+
| `children` | `React.ReactNode` | - - - | Children element. Must be Skia elements |
|
|
196
|
+
|
|
197
|
+
### `<Chart.Line />`
|
|
198
|
+
|
|
199
|
+
Draws the main chart line.
|
|
200
|
+
|
|
201
|
+
| Prop | Type | Default | Description |
|
|
202
|
+
| ------------- | ---------- | ---------------------------------------------- | ------------------------------ |
|
|
203
|
+
| `strokeWidth` | `number` | `3` | Line thickness |
|
|
204
|
+
| `colors` | `string[]` | `['#00E396', '#00E396', '#EA3943', '#EA3943']` | Gradient colors (Top → Bottom) |
|
|
205
|
+
|
|
206
|
+
### `<Chart.Baseline />`
|
|
207
|
+
|
|
208
|
+
Draws a dashed horizontal line at the starting value (baseline). Useful for visualizing profit/loss.
|
|
209
|
+
|
|
210
|
+
| Prop | Type | Default | Description |
|
|
211
|
+
| ----------- | --------- | --------- | -------------------------------------------------------- |
|
|
212
|
+
| `color` | `string` | `#858CA2` | Color of the dashed line and starting dot. |
|
|
213
|
+
| `showLabel` | `boolean` | `true` | Whether to show the label chip with the formatted value. |
|
|
214
|
+
|
|
215
|
+
### `<Chart.Area />`
|
|
216
|
+
|
|
217
|
+
Draws the gradient fill below the line.
|
|
218
|
+
|
|
219
|
+
| Prop | Type | Default | Description |
|
|
220
|
+
| ---------------- | ---------- | ---------------------------------- | -------------------------------------------------------------------------------- |
|
|
221
|
+
| `gradientColors` | `string[]` | `['#000', '#000', '#000', '#000']` | Array of 4 colors for the area gradient (Top -> Baseline -> Baseline -> Bottom). |
|
|
222
|
+
|
|
223
|
+
### `<Chart.Cursor />`
|
|
224
|
+
|
|
225
|
+
The interactive cursor that follows the finger.
|
|
226
|
+
|
|
227
|
+
| Prop | Type | Default | Description |
|
|
228
|
+
| ---------------- | -------- | --------- | ------------------------------------ |
|
|
229
|
+
| `crosshairColor` | `string` | `'white'` | Color of the vertical line |
|
|
230
|
+
| `circleColor` | `string` | `'white'` | Border color of the indicator circle |
|
|
231
|
+
|
|
232
|
+
### `<Chart.Tooltip.Value />`
|
|
233
|
+
|
|
234
|
+
Displays the current interpolated value (price, score, etc).
|
|
235
|
+
|
|
236
|
+
| Prop | Type | Default | Description |
|
|
237
|
+
| ---------------- | --------------------------- | -------- | ----------------------- |
|
|
238
|
+
| `format` | `(value: number) => string` | `$ 0.00` | Format function |
|
|
239
|
+
| `style` | `TextStyle` | `{}` | Inner text style |
|
|
240
|
+
| `containerStyle` | `ViewStyle` | `{}` | Tooltip container style |
|
|
241
|
+
|
|
242
|
+
### `<Chart.Tooltip.Date />`
|
|
243
|
+
|
|
244
|
+
Displays the current date/time.
|
|
245
|
+
|
|
246
|
+
| Prop | Type | Default | Description |
|
|
247
|
+
| ---------------- | --------------------------- | ------------ | ----------------------- |
|
|
248
|
+
| `style` | `TextStyle` | `{}` | Inner text style |
|
|
249
|
+
| `containerStyle` | `ViewStyle` | `{}` | Tooltip container style |
|
|
250
|
+
| `format` | `(value: number) => string` | `DD/MM/YYYY` | Timestamp formatter |
|
|
251
|
+
|
|
252
|
+
## 🎨 Advanced Customization
|
|
253
|
+
|
|
254
|
+
### Formatting Currency (USD)
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
const formatUSD = (value: number) => {
|
|
258
|
+
'worklet';
|
|
259
|
+
return `$ ${value.toFixed(2)}`;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
<Chart.Tooltip.Value format={formatUSD} />;
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Styling the Container
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
<Chart.Root
|
|
269
|
+
data={data}
|
|
270
|
+
containerStyle={{
|
|
271
|
+
backgroundColor: '#1E1E2D',
|
|
272
|
+
borderRadius: 20,
|
|
273
|
+
borderWidth: 1,
|
|
274
|
+
borderColor: '#333',
|
|
275
|
+
}}
|
|
276
|
+
>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## 🐛 Troubleshooting
|
|
280
|
+
|
|
281
|
+
**Error: `missing libsvg.a` or `skia` crash**
|
|
282
|
+
|
|
283
|
+
1. `cd android && ./gradlew clean`
|
|
284
|
+
2. `cd .. && rm -rf node_modules && yarn install`
|
|
285
|
+
3. Ensure `@shopify/react-native-skia` is compatible with your RN version.
|
|
286
|
+
|
|
287
|
+
**Error: `Reanimated failed to create a worklet`**
|
|
288
|
+
|
|
289
|
+
Add to `babel.config.js`:
|
|
290
|
+
|
|
291
|
+
```js
|
|
292
|
+
plugins: ['react-native-reanimated/plugin'],
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## 🤝 Contributing
|
|
296
|
+
|
|
297
|
+
1. Fork the project
|
|
298
|
+
2. Create your Feature Branch (`git checkout -b feature/NewFeature`)
|
|
299
|
+
3. Commit your changes (`git commit -m 'Add some NewFeature'`)
|
|
300
|
+
4. Push to the Branch (`git push origin feature/NewFeature`)
|
|
301
|
+
5. Open a Pull Request
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
This library was inspired by the awesome [react-native-wagmi-charts](https://github.com/coinjar/react-native-wagmi-charts). Ideally, I aimed to create a performant Skia-based alternative with a similar easy-to-use API.
|
|
306
|
+
|
|
307
|
+
## 📄 License
|
|
308
|
+
|
|
309
|
+
Distributed under the MIT License. See `LICENSE` for more information.
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useContext, useMemo } from 'react';
|
|
4
|
+
import { Dimensions, StyleSheet, View } from 'react-native';
|
|
5
|
+
import * as d3 from 'd3';
|
|
6
|
+
import { Skia } from '@shopify/react-native-skia';
|
|
7
|
+
import { useSharedValue } from 'react-native-reanimated';
|
|
8
|
+
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
9
|
+
import { solveCatmullRom } from "./utils.js";
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
const MOCK_SHARED_VAL_NUM = {
|
|
12
|
+
value: 0
|
|
13
|
+
};
|
|
14
|
+
const MOCK_SHARED_VAL_BOOL = {
|
|
15
|
+
value: false
|
|
16
|
+
};
|
|
17
|
+
const EMPTY_PATH = Skia.Path.Make();
|
|
18
|
+
const WINDOW_WIDTH = Dimensions.get('window').width;
|
|
19
|
+
const INITIAL_CONTEXT = {
|
|
20
|
+
originalData: [],
|
|
21
|
+
width: WINDOW_WIDTH,
|
|
22
|
+
height: 250,
|
|
23
|
+
padding: 20,
|
|
24
|
+
domainX: [0, 1],
|
|
25
|
+
domainY: [0, 1],
|
|
26
|
+
yRange: [0, 1],
|
|
27
|
+
xScale: d3.scaleTime(),
|
|
28
|
+
yScale: d3.scaleLinear(),
|
|
29
|
+
path: EMPTY_PATH,
|
|
30
|
+
areaPath: EMPTY_PATH,
|
|
31
|
+
baselineY: 0,
|
|
32
|
+
gradientColors: ['#000', '#000', '#000', '#000'],
|
|
33
|
+
gradientPositions: [0, 0.5, 0.5, 1],
|
|
34
|
+
currentX: MOCK_SHARED_VAL_NUM,
|
|
35
|
+
currentY: MOCK_SHARED_VAL_NUM,
|
|
36
|
+
isActive: MOCK_SHARED_VAL_BOOL,
|
|
37
|
+
currentValue: MOCK_SHARED_VAL_NUM,
|
|
38
|
+
currentTimestamp: MOCK_SHARED_VAL_NUM,
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
yMap: new Float32Array(0),
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
valueMap: new Float32Array(0)
|
|
43
|
+
};
|
|
44
|
+
export const ChartContext = /*#__PURE__*/createContext(INITIAL_CONTEXT);
|
|
45
|
+
const ChartProvider = ({
|
|
46
|
+
data,
|
|
47
|
+
width = Dimensions.get('window').width,
|
|
48
|
+
height = 250,
|
|
49
|
+
padding = 20,
|
|
50
|
+
containerStyle,
|
|
51
|
+
children
|
|
52
|
+
}) => {
|
|
53
|
+
// Initialize Reanimated shared values
|
|
54
|
+
const currentX = useSharedValue(0);
|
|
55
|
+
const currentY = useSharedValue(0);
|
|
56
|
+
const isActive = useSharedValue(false);
|
|
57
|
+
const currentValue = useSharedValue(0);
|
|
58
|
+
const currentTimestamp = useSharedValue(0);
|
|
59
|
+
|
|
60
|
+
// useMemo: "Only execute this heavy logic if data or screen size changes"
|
|
61
|
+
const processedContext = useMemo(() => {
|
|
62
|
+
// 1. Safety validations (prevent crashes with empty array)
|
|
63
|
+
if (!data || data.length < 2 || width === 0) {
|
|
64
|
+
return {
|
|
65
|
+
...INITIAL_CONTEXT,
|
|
66
|
+
originalData: data || [],
|
|
67
|
+
width: width || WINDOW_WIDTH,
|
|
68
|
+
height,
|
|
69
|
+
padding,
|
|
70
|
+
currentX,
|
|
71
|
+
currentY,
|
|
72
|
+
isActive,
|
|
73
|
+
currentValue,
|
|
74
|
+
currentTimestamp
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 2. Extract Data Limits (Min/Max)
|
|
79
|
+
const timestamps = data.map(d => d.timestamp);
|
|
80
|
+
const values = data.map(d => d.value);
|
|
81
|
+
const minTime = Math.min(...timestamps);
|
|
82
|
+
const maxTime = Math.max(...timestamps);
|
|
83
|
+
const minValue = Math.min(...values);
|
|
84
|
+
const maxValue = Math.max(...values);
|
|
85
|
+
|
|
86
|
+
// 3. Define Drawing Area (with vertical "breathing room")
|
|
87
|
+
const verticalSquish = height * 0.15; // Leave 15% margin
|
|
88
|
+
const minRangeY = height - padding - verticalSquish;
|
|
89
|
+
const maxRangeY = padding + verticalSquish;
|
|
90
|
+
const safeMinRangeY = Math.max(minRangeY, maxRangeY + 1);
|
|
91
|
+
const domainYMin = minValue;
|
|
92
|
+
const domainYMax = maxValue;
|
|
93
|
+
|
|
94
|
+
// 4. Create D3 Scales (Unit Converters)
|
|
95
|
+
const xScale = d3.scaleTime().domain([minTime, maxTime]).range([padding, width - padding]);
|
|
96
|
+
const yScale = d3.scaleLinear().domain([domainYMin, domainYMax]).range([safeMinRangeY, maxRangeY]);
|
|
97
|
+
const firstValue = data[0]?.value || 0;
|
|
98
|
+
const baselineY = yScale(firstValue);
|
|
99
|
+
|
|
100
|
+
// --- THE BIG MAGIC: MANUAL PATH AND MAP GENERATION ---
|
|
101
|
+
// Instead of asking D3 to draw the line and then trying to guess where it is,
|
|
102
|
+
// we calculate PIXEL BY PIXEL where the line should pass.
|
|
103
|
+
// We save this in two places:
|
|
104
|
+
// 1. skiaPath: To draw on the screen.
|
|
105
|
+
// 2. yMap / valueMap: Giant arrays for the finger to query instantly.
|
|
106
|
+
|
|
107
|
+
const skiaPath = Skia.Path.Make();
|
|
108
|
+
if (data.length > 0) {
|
|
109
|
+
skiaPath.moveTo(xScale(data[0]?.timestamp || 0), yScale(data[0]?.value || 0));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Create typed arrays (Float32) the exact size of the screen width.
|
|
113
|
+
// This is extremely efficient for memory and reading.
|
|
114
|
+
const mapSize = Math.ceil(width);
|
|
115
|
+
const yMap = new Float32Array(mapSize).fill(-1);
|
|
116
|
+
const valueMap = new Float32Array(mapSize).fill(-1);
|
|
117
|
+
const totalPoints = data.length - 1;
|
|
118
|
+
const xPixelStart = padding;
|
|
119
|
+
const xPixelEnd = width - padding;
|
|
120
|
+
const xTotalRange = xPixelEnd - xPixelStart;
|
|
121
|
+
|
|
122
|
+
// === THE MAIN LOOP ===
|
|
123
|
+
// We iterate through every X coordinate on the screen (0, 1, 2... 400).
|
|
124
|
+
for (let x = 0; x < width; x++) {
|
|
125
|
+
// If we are outside the chart's useful area (margins), skip.
|
|
126
|
+
if (x < xPixelStart || x > xPixelEnd) continue;
|
|
127
|
+
|
|
128
|
+
// STEP A: Discover where we are on the timeline.
|
|
129
|
+
// progress = 0.5 means we are exactly in the middle of the chart.
|
|
130
|
+
const progress = (x - xPixelStart) / xTotalRange;
|
|
131
|
+
|
|
132
|
+
// STEP B: Find which data points surround us.
|
|
133
|
+
const floatIndex = progress * totalPoints;
|
|
134
|
+
const index = Math.floor(floatIndex); // Index of the point to the left
|
|
135
|
+
const safeIndex = Math.min(index, totalPoints - 1);
|
|
136
|
+
|
|
137
|
+
// STEP C: Local progress (t) between current and next point.
|
|
138
|
+
const t = floatIndex - safeIndex;
|
|
139
|
+
|
|
140
|
+
// STEP D: Select the 4 control points for Catmull-Rom.
|
|
141
|
+
// p1 and p2 are the points we are passing between.
|
|
142
|
+
const p1 = data[safeIndex]?.value || 0;
|
|
143
|
+
const p2 = data[safeIndex + 1]?.value ?? p1;
|
|
144
|
+
|
|
145
|
+
// p0 and p3 are the "distant neighbors" needed to calculate the curve.
|
|
146
|
+
// If they don't exist (at edges), we duplicate the neighbor (standard D3 strategy).
|
|
147
|
+
const p0 = safeIndex > 0 ? data[safeIndex - 1]?.value || 0 : p1;
|
|
148
|
+
const p3 = safeIndex < totalPoints - 1 ? data[safeIndex + 2]?.value || 0 : p2;
|
|
149
|
+
|
|
150
|
+
// STEP E: Calculate Exact Interpolated Value
|
|
151
|
+
const interpolatedValue = solveCatmullRom(p0, p1, p2, p3, t);
|
|
152
|
+
const interpolatedY = yScale(interpolatedValue);
|
|
153
|
+
|
|
154
|
+
// STEP F: Save to maps and drawing
|
|
155
|
+
yMap[x] = interpolatedY; // Height Map
|
|
156
|
+
valueMap[x] = interpolatedValue; // Value Map
|
|
157
|
+
|
|
158
|
+
// Add line to visual drawing. Since we do this pixel by pixel, the curve is perfect.
|
|
159
|
+
skiaPath.lineTo(x, interpolatedY);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Close the area (to create the gradient effect below the line)
|
|
163
|
+
const areaPath = skiaPath.copy();
|
|
164
|
+
areaPath.lineTo(width - padding, baselineY); // Down to base
|
|
165
|
+
areaPath.lineTo(padding, baselineY); // Back to start
|
|
166
|
+
areaPath.close();
|
|
167
|
+
|
|
168
|
+
// Gradient calculation (Green on top, Red on bottom)
|
|
169
|
+
const safeHeight = height || 1;
|
|
170
|
+
const splitRatio = Math.max(0, Math.min(1, baselineY / safeHeight));
|
|
171
|
+
return {
|
|
172
|
+
originalData: data,
|
|
173
|
+
width,
|
|
174
|
+
height,
|
|
175
|
+
padding,
|
|
176
|
+
domainX: [minTime, maxTime],
|
|
177
|
+
domainY: [domainYMin, domainYMax],
|
|
178
|
+
yRange: [safeMinRangeY, maxRangeY],
|
|
179
|
+
xScale,
|
|
180
|
+
yScale,
|
|
181
|
+
path: skiaPath,
|
|
182
|
+
areaPath: areaPath,
|
|
183
|
+
baselineY: baselineY || 0,
|
|
184
|
+
gradientColors: ['#00E396E6', '#00E39600', '#EA394300', '#EA394326'],
|
|
185
|
+
gradientPositions: [0, splitRatio, splitRatio, 1],
|
|
186
|
+
currentX,
|
|
187
|
+
currentY,
|
|
188
|
+
isActive,
|
|
189
|
+
currentValue,
|
|
190
|
+
currentTimestamp,
|
|
191
|
+
yMap,
|
|
192
|
+
valueMap
|
|
193
|
+
};
|
|
194
|
+
}, [data, width, height, padding, currentX, currentY, isActive, currentValue, currentTimestamp]);
|
|
195
|
+
|
|
196
|
+
// --- GESTURE HANDLER (USER INTERACTION) ---
|
|
197
|
+
// This function runs on the UI Thread (Worklet). It is critical for performance.
|
|
198
|
+
// It DOES NOT RECALCULATE math. It simply reads the map we created above.
|
|
199
|
+
const onGestureEvent = touchX => {
|
|
200
|
+
'worklet';
|
|
201
|
+
|
|
202
|
+
// Directive for Reanimated to compile this separately.
|
|
203
|
+
if (!processedContext.yMap || processedContext.yMap.length === 0) return;
|
|
204
|
+
|
|
205
|
+
// 1. Limit touch to chart boundaries (Clamp)
|
|
206
|
+
const x = Math.max(padding, Math.min(touchX, width - padding));
|
|
207
|
+
currentX.value = x;
|
|
208
|
+
|
|
209
|
+
// 2. DIRECT LOOKUP (O(1) Complexity - Instant)
|
|
210
|
+
// Since we created a map where index = pixel X, we just round the touch X
|
|
211
|
+
// and grab the value from the array. No complex math here!
|
|
212
|
+
const xIndex = Math.round(x);
|
|
213
|
+
|
|
214
|
+
// @ts-ignore - Direct access to TypedArray on UI thread
|
|
215
|
+
const preCalculatedY = processedContext.yMap[xIndex];
|
|
216
|
+
// @ts-ignore
|
|
217
|
+
const preCalculatedValue = processedContext.valueMap[xIndex];
|
|
218
|
+
|
|
219
|
+
// If we found a valid value in the map, update reactive variables.
|
|
220
|
+
if (preCalculatedY !== undefined && preCalculatedY !== -1 && preCalculatedValue) {
|
|
221
|
+
currentY.value = preCalculatedY;
|
|
222
|
+
currentValue.value = preCalculatedValue;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// 3. Timestamp (Time is linear, so we can mathematically calculate without issues)
|
|
226
|
+
const xRangeStart = padding;
|
|
227
|
+
const xRangeEnd = width - padding;
|
|
228
|
+
const progress = (x - xRangeStart) / (xRangeEnd - xRangeStart);
|
|
229
|
+
const [minTime, maxTime] = processedContext.domainX;
|
|
230
|
+
currentTimestamp.value = minTime + progress * (maxTime - minTime);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Gesture Configuration
|
|
234
|
+
const gesture = Gesture.Pan().onBegin(e => {
|
|
235
|
+
isActive.value = true;
|
|
236
|
+
onGestureEvent(e.x);
|
|
237
|
+
}).onChange(e => {
|
|
238
|
+
onGestureEvent(e.x);
|
|
239
|
+
}).onFinalize(() => {
|
|
240
|
+
isActive.value = false;
|
|
241
|
+
});
|
|
242
|
+
return /*#__PURE__*/_jsx(ChartContext.Provider, {
|
|
243
|
+
value: processedContext,
|
|
244
|
+
children: /*#__PURE__*/_jsx(GestureDetector, {
|
|
245
|
+
gesture: gesture,
|
|
246
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
247
|
+
style: [styles.container, containerStyle],
|
|
248
|
+
children: children
|
|
249
|
+
})
|
|
250
|
+
})
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
export const useChart = () => {
|
|
254
|
+
const context = useContext(ChartContext);
|
|
255
|
+
if (!context) {
|
|
256
|
+
throw new Error('[ChartContext]: the useChart hook must be used inside ChartContext provider');
|
|
257
|
+
}
|
|
258
|
+
return context;
|
|
259
|
+
};
|
|
260
|
+
const styles = StyleSheet.create({
|
|
261
|
+
container: {
|
|
262
|
+
backgroundColor: '#17171A',
|
|
263
|
+
borderRadius: 16,
|
|
264
|
+
position: 'relative',
|
|
265
|
+
overflow: 'hidden'
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
export default ChartProvider;
|
|
269
|
+
//# sourceMappingURL=ChartContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","createContext","useContext","useMemo","Dimensions","StyleSheet","View","d3","Skia","useSharedValue","Gesture","GestureDetector","solveCatmullRom","jsx","_jsx","MOCK_SHARED_VAL_NUM","value","MOCK_SHARED_VAL_BOOL","EMPTY_PATH","Path","Make","WINDOW_WIDTH","get","width","INITIAL_CONTEXT","originalData","height","padding","domainX","domainY","yRange","xScale","scaleTime","yScale","scaleLinear","path","areaPath","baselineY","gradientColors","gradientPositions","currentX","currentY","isActive","currentValue","currentTimestamp","yMap","Float32Array","valueMap","ChartContext","ChartProvider","data","containerStyle","children","processedContext","length","timestamps","map","d","timestamp","values","minTime","Math","min","maxTime","max","minValue","maxValue","verticalSquish","minRangeY","maxRangeY","safeMinRangeY","domainYMin","domainYMax","domain","range","firstValue","skiaPath","moveTo","mapSize","ceil","fill","totalPoints","xPixelStart","xPixelEnd","xTotalRange","x","progress","floatIndex","index","floor","safeIndex","t","p1","p2","p0","p3","interpolatedValue","interpolatedY","lineTo","copy","close","safeHeight","splitRatio","onGestureEvent","touchX","xIndex","round","preCalculatedY","preCalculatedValue","undefined","xRangeStart","xRangeEnd","gesture","Pan","onBegin","e","onChange","onFinalize","Provider","style","styles","container","useChart","context","Error","create","backgroundColor","borderRadius","position","overflow"],"sourceRoot":"../../src","sources":["ChartContext.tsx"],"mappings":";;AACA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,UAAU,EAAEC,OAAO,QAAQ,OAAO;AACjE,SAASC,UAAU,EAAEC,UAAU,EAAEC,IAAI,QAAQ,cAAc;AAE3D,OAAO,KAAKC,EAAE,MAAM,IAAI;AAGxB,SAASC,IAAI,QAAQ,4BAA4B;AACjD,SAASC,cAAc,QAAQ,yBAAyB;AAExD,SAASC,OAAO,EAAEC,eAAe,QAAQ,8BAA8B;AACvE,SAASC,eAAe,QAAQ,YAAS;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAE1C,MAAMC,mBAAmB,GAAG;EAAEC,KAAK,EAAE;AAAE,CAAwB;AAC/D,MAAMC,oBAAoB,GAAG;EAAED,KAAK,EAAE;AAAM,CAAyB;AACrE,MAAME,UAAU,GAAGV,IAAI,CAACW,IAAI,CAACC,IAAI,CAAC,CAAC;AACnC,MAAMC,YAAY,GAAGjB,UAAU,CAACkB,GAAG,CAAC,QAAQ,CAAC,CAACC,KAAK;AAEnD,MAAMC,eAAkC,GAAG;EACzCC,YAAY,EAAE,EAAE;EAChBF,KAAK,EAAEF,YAAY;EACnBK,MAAM,EAAE,GAAG;EACXC,OAAO,EAAE,EAAE;EACXC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;EACfC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;EACfC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;EACdC,MAAM,EAAExB,EAAE,CAACyB,SAAS,CAAC,CAAC;EACtBC,MAAM,EAAE1B,EAAE,CAAC2B,WAAW,CAAC,CAAC;EACxBC,IAAI,EAAEjB,UAAU;EAChBkB,QAAQ,EAAElB,UAAU;EACpBmB,SAAS,EAAE,CAAC;EACZC,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;EAChDC,iBAAiB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;EACnCC,QAAQ,EAAEzB,mBAAmB;EAC7B0B,QAAQ,EAAE1B,mBAAmB;EAC7B2B,QAAQ,EAAEzB,oBAAoB;EAC9B0B,YAAY,EAAE5B,mBAAmB;EACjC6B,gBAAgB,EAAE7B,mBAAmB;EACrC;EACA8B,IAAI,EAAE,IAAIC,YAAY,CAAC,CAAC,CAAC;EACzB;EACAC,QAAQ,EAAE,IAAID,YAAY,CAAC,CAAC;AAC9B,CAAC;AAED,OAAO,MAAME,YAAY,gBAAG/C,aAAa,CAAoBuB,eAAe,CAAC;AAU7E,MAAMyB,aAAgD,GAAGA,CAAC;EACxDC,IAAI;EACJ3B,KAAK,GAAGnB,UAAU,CAACkB,GAAG,CAAC,QAAQ,CAAC,CAACC,KAAK;EACtCG,MAAM,GAAG,GAAG;EACZC,OAAO,GAAG,EAAE;EACZwB,cAAc;EACdC;AACF,CAAC,KAAK;EACJ;EACA,MAAMZ,QAAQ,GAAG/B,cAAc,CAAC,CAAC,CAAC;EAClC,MAAMgC,QAAQ,GAAGhC,cAAc,CAAC,CAAC,CAAC;EAClC,MAAMiC,QAAQ,GAAGjC,cAAc,CAAC,KAAK,CAAC;EACtC,MAAMkC,YAAY,GAAGlC,cAAc,CAAC,CAAC,CAAC;EACtC,MAAMmC,gBAAgB,GAAGnC,cAAc,CAAC,CAAC,CAAC;;EAE1C;EACA,MAAM4C,gBAAgB,GAAGlD,OAAO,CAAC,MAAM;IACrC;IACA,IAAI,CAAC+C,IAAI,IAAIA,IAAI,CAACI,MAAM,GAAG,CAAC,IAAI/B,KAAK,KAAK,CAAC,EAAE;MAC3C,OAAO;QACL,GAAGC,eAAe;QAClBC,YAAY,EAAEyB,IAAI,IAAI,EAAE;QACxB3B,KAAK,EAAEA,KAAK,IAAIF,YAAY;QAC5BK,MAAM;QACNC,OAAO;QACPa,QAAQ;QACRC,QAAQ;QACRC,QAAQ;QACRC,YAAY;QACZC;MACF,CAAC;IACH;;IAEA;IACA,MAAMW,UAAU,GAAGL,IAAI,CAACM,GAAG,CAAEC,CAAC,IAAKA,CAAC,CAACC,SAAS,CAAC;IAC/C,MAAMC,MAAM,GAAGT,IAAI,CAACM,GAAG,CAAEC,CAAC,IAAKA,CAAC,CAACzC,KAAK,CAAC;IAEvC,MAAM4C,OAAO,GAAGC,IAAI,CAACC,GAAG,CAAC,GAAGP,UAAU,CAAC;IACvC,MAAMQ,OAAO,GAAGF,IAAI,CAACG,GAAG,CAAC,GAAGT,UAAU,CAAC;IACvC,MAAMU,QAAQ,GAAGJ,IAAI,CAACC,GAAG,CAAC,GAAGH,MAAM,CAAC;IACpC,MAAMO,QAAQ,GAAGL,IAAI,CAACG,GAAG,CAAC,GAAGL,MAAM,CAAC;;IAEpC;IACA,MAAMQ,cAAc,GAAGzC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtC,MAAM0C,SAAS,GAAG1C,MAAM,GAAGC,OAAO,GAAGwC,cAAc;IACnD,MAAME,SAAS,GAAG1C,OAAO,GAAGwC,cAAc;IAC1C,MAAMG,aAAa,GAAGT,IAAI,CAACG,GAAG,CAACI,SAAS,EAAEC,SAAS,GAAG,CAAC,CAAC;IACxD,MAAME,UAAU,GAAGN,QAAQ;IAC3B,MAAMO,UAAU,GAAGN,QAAQ;;IAE3B;IACA,MAAMnC,MAAM,GAAGxB,EAAE,CACdyB,SAAS,CAAC,CAAC,CACXyC,MAAM,CAAC,CAACb,OAAO,EAAEG,OAAO,CAAC,CAAC,CAC1BW,KAAK,CAAC,CAAC/C,OAAO,EAAEJ,KAAK,GAAGI,OAAO,CAAC,CAAC;IACpC,MAAMM,MAAM,GAAG1B,EAAE,CACd2B,WAAW,CAAC,CAAC,CACbuC,MAAM,CAAC,CAACF,UAAU,EAAEC,UAAU,CAAC,CAAC,CAChCE,KAAK,CAAC,CAACJ,aAAa,EAAED,SAAS,CAAC,CAAC;IAEpC,MAAMM,UAAU,GAAGzB,IAAI,CAAC,CAAC,CAAC,EAAElC,KAAK,IAAI,CAAC;IACtC,MAAMqB,SAAS,GAAGJ,MAAM,CAAC0C,UAAU,CAAC;;IAEpC;IACA;IACA;IACA;IACA;IACA;;IAEA,MAAMC,QAAQ,GAAGpE,IAAI,CAACW,IAAI,CAACC,IAAI,CAAC,CAAC;IACjC,IAAI8B,IAAI,CAACI,MAAM,GAAG,CAAC,EAAE;MACnBsB,QAAQ,CAACC,MAAM,CACb9C,MAAM,CAACmB,IAAI,CAAC,CAAC,CAAC,EAAEQ,SAAS,IAAI,CAAC,CAAC,EAC/BzB,MAAM,CAACiB,IAAI,CAAC,CAAC,CAAC,EAAElC,KAAK,IAAI,CAAC,CAC5B,CAAC;IACH;;IAEA;IACA;IACA,MAAM8D,OAAO,GAAGjB,IAAI,CAACkB,IAAI,CAACxD,KAAK,CAAC;IAChC,MAAMsB,IAAI,GAAG,IAAIC,YAAY,CAACgC,OAAO,CAAC,CAACE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAMjC,QAAQ,GAAG,IAAID,YAAY,CAACgC,OAAO,CAAC,CAACE,IAAI,CAAC,CAAC,CAAC,CAAC;IAEnD,MAAMC,WAAW,GAAG/B,IAAI,CAACI,MAAM,GAAG,CAAC;IACnC,MAAM4B,WAAW,GAAGvD,OAAO;IAC3B,MAAMwD,SAAS,GAAG5D,KAAK,GAAGI,OAAO;IACjC,MAAMyD,WAAW,GAAGD,SAAS,GAAGD,WAAW;;IAE3C;IACA;IACA,KAAK,IAAIG,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAG9D,KAAK,EAAE8D,CAAC,EAAE,EAAE;MAC9B;MACA,IAAIA,CAAC,GAAGH,WAAW,IAAIG,CAAC,GAAGF,SAAS,EAAE;;MAEtC;MACA;MACA,MAAMG,QAAQ,GAAG,CAACD,CAAC,GAAGH,WAAW,IAAIE,WAAW;;MAEhD;MACA,MAAMG,UAAU,GAAGD,QAAQ,GAAGL,WAAW;MACzC,MAAMO,KAAK,GAAG3B,IAAI,CAAC4B,KAAK,CAACF,UAAU,CAAC,CAAC,CAAC;MACtC,MAAMG,SAAS,GAAG7B,IAAI,CAACC,GAAG,CAAC0B,KAAK,EAAEP,WAAW,GAAG,CAAC,CAAC;;MAElD;MACA,MAAMU,CAAC,GAAGJ,UAAU,GAAGG,SAAS;;MAEhC;MACA;MACA,MAAME,EAAE,GAAG1C,IAAI,CAACwC,SAAS,CAAC,EAAE1E,KAAK,IAAI,CAAC;MACtC,MAAM6E,EAAE,GAAG3C,IAAI,CAACwC,SAAS,GAAG,CAAC,CAAC,EAAE1E,KAAK,IAAI4E,EAAE;;MAE3C;MACA;MACA,MAAME,EAAE,GAAGJ,SAAS,GAAG,CAAC,GAAGxC,IAAI,CAACwC,SAAS,GAAG,CAAC,CAAC,EAAE1E,KAAK,IAAI,CAAC,GAAG4E,EAAE;MAC/D,MAAMG,EAAE,GACNL,SAAS,GAAGT,WAAW,GAAG,CAAC,GAAG/B,IAAI,CAACwC,SAAS,GAAG,CAAC,CAAC,EAAE1E,KAAK,IAAI,CAAC,GAAG6E,EAAE;;MAEpE;MACA,MAAMG,iBAAiB,GAAGpF,eAAe,CAACkF,EAAE,EAAEF,EAAE,EAAEC,EAAE,EAAEE,EAAE,EAAEJ,CAAC,CAAC;MAC5D,MAAMM,aAAa,GAAGhE,MAAM,CAAC+D,iBAAiB,CAAC;;MAE/C;MACAnD,IAAI,CAACwC,CAAC,CAAC,GAAGY,aAAa,CAAC,CAAC;MACzBlD,QAAQ,CAACsC,CAAC,CAAC,GAAGW,iBAAiB,CAAC,CAAC;;MAEjC;MACApB,QAAQ,CAACsB,MAAM,CAACb,CAAC,EAAEY,aAAa,CAAC;IACnC;;IAEA;IACA,MAAM7D,QAAQ,GAAGwC,QAAQ,CAACuB,IAAI,CAAC,CAAC;IAChC/D,QAAQ,CAAC8D,MAAM,CAAC3E,KAAK,GAAGI,OAAO,EAAEU,SAAS,CAAC,CAAC,CAAC;IAC7CD,QAAQ,CAAC8D,MAAM,CAACvE,OAAO,EAAEU,SAAS,CAAC,CAAC,CAAC;IACrCD,QAAQ,CAACgE,KAAK,CAAC,CAAC;;IAEhB;IACA,MAAMC,UAAU,GAAG3E,MAAM,IAAI,CAAC;IAC9B,MAAM4E,UAAU,GAAGzC,IAAI,CAACG,GAAG,CAAC,CAAC,EAAEH,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEzB,SAAS,GAAGgE,UAAU,CAAC,CAAC;IAEnE,OAAO;MACL5E,YAAY,EAAEyB,IAAI;MAClB3B,KAAK;MACLG,MAAM;MACNC,OAAO;MACPC,OAAO,EAAE,CAACgC,OAAO,EAAEG,OAAO,CAAqB;MAC/ClC,OAAO,EAAE,CAAC0C,UAAU,EAAEC,UAAU,CAAqB;MACrD1C,MAAM,EAAE,CAACwC,aAAa,EAAED,SAAS,CAAqB;MACtDtC,MAAM;MACNE,MAAM;MACNE,IAAI,EAAEyC,QAAQ;MACdxC,QAAQ,EAAEA,QAAQ;MAClBC,SAAS,EAAEA,SAAS,IAAI,CAAC;MACzBC,cAAc,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC;MACpEC,iBAAiB,EAAE,CAAC,CAAC,EAAE+D,UAAU,EAAEA,UAAU,EAAE,CAAC,CAAC;MACjD9D,QAAQ;MACRC,QAAQ;MACRC,QAAQ;MACRC,YAAY;MACZC,gBAAgB;MAChBC,IAAI;MACJE;IACF,CAAC;EACH,CAAC,EAAE,CACDG,IAAI,EACJ3B,KAAK,EACLG,MAAM,EACNC,OAAO,EACPa,QAAQ,EACRC,QAAQ,EACRC,QAAQ,EACRC,YAAY,EACZC,gBAAgB,CACjB,CAAC;;EAEF;EACA;EACA;EACA,MAAM2D,cAAc,GAAIC,MAAc,IAAK;IACzC,SAAS;;IAAE;IAEX,IAAI,CAACnD,gBAAgB,CAACR,IAAI,IAAIQ,gBAAgB,CAACR,IAAI,CAACS,MAAM,KAAK,CAAC,EAAE;;IAElE;IACA,MAAM+B,CAAC,GAAGxB,IAAI,CAACG,GAAG,CAACrC,OAAO,EAAEkC,IAAI,CAACC,GAAG,CAAC0C,MAAM,EAAEjF,KAAK,GAAGI,OAAO,CAAC,CAAC;IAC9Da,QAAQ,CAACxB,KAAK,GAAGqE,CAAC;;IAElB;IACA;IACA;IACA,MAAMoB,MAAM,GAAG5C,IAAI,CAAC6C,KAAK,CAACrB,CAAC,CAAC;;IAE5B;IACA,MAAMsB,cAAc,GAAGtD,gBAAgB,CAACR,IAAI,CAAC4D,MAAM,CAAC;IACpD;IACA,MAAMG,kBAAkB,GAAGvD,gBAAgB,CAACN,QAAQ,CAAC0D,MAAM,CAAC;;IAE5D;IACA,IACEE,cAAc,KAAKE,SAAS,IAC5BF,cAAc,KAAK,CAAC,CAAC,IACrBC,kBAAkB,EAClB;MACAnE,QAAQ,CAACzB,KAAK,GAAG2F,cAAc;MAC/BhE,YAAY,CAAC3B,KAAK,GAAG4F,kBAAkB;IACzC;;IAEA;IACA,MAAME,WAAW,GAAGnF,OAAO;IAC3B,MAAMoF,SAAS,GAAGxF,KAAK,GAAGI,OAAO;IACjC,MAAM2D,QAAQ,GAAG,CAACD,CAAC,GAAGyB,WAAW,KAAKC,SAAS,GAAGD,WAAW,CAAC;IAC9D,MAAM,CAAClD,OAAO,EAAEG,OAAO,CAAC,GAAGV,gBAAgB,CAACzB,OAAO;IACnDgB,gBAAgB,CAAC5B,KAAK,GAAG4C,OAAO,GAAG0B,QAAQ,IAAIvB,OAAO,GAAGH,OAAO,CAAC;EACnE,CAAC;;EAED;EACA,MAAMoD,OAAO,GAAGtG,OAAO,CAACuG,GAAG,CAAC,CAAC,CAC1BC,OAAO,CAAEC,CAAC,IAAK;IACdzE,QAAQ,CAAC1B,KAAK,GAAG,IAAI;IACrBuF,cAAc,CAACY,CAAC,CAAC9B,CAAC,CAAC;EACrB,CAAC,CAAC,CACD+B,QAAQ,CAAED,CAAC,IAAK;IACfZ,cAAc,CAACY,CAAC,CAAC9B,CAAC,CAAC;EACrB,CAAC,CAAC,CACDgC,UAAU,CAAC,MAAM;IAChB3E,QAAQ,CAAC1B,KAAK,GAAG,KAAK;EACxB,CAAC,CAAC;EAEJ,oBACEF,IAAA,CAACkC,YAAY,CAACsE,QAAQ;IAACtG,KAAK,EAAEqC,gBAAiB;IAAAD,QAAA,eAC7CtC,IAAA,CAACH,eAAe;MAACqG,OAAO,EAAEA,OAAQ;MAAA5D,QAAA,eAChCtC,IAAA,CAACR,IAAI;QAACiH,KAAK,EAAE,CAACC,MAAM,CAACC,SAAS,EAAEtE,cAAc,CAAE;QAAAC,QAAA,EAAEA;MAAQ,CAAO;IAAC,CACnD;EAAC,CACG,CAAC;AAE5B,CAAC;AAED,OAAO,MAAMsE,QAAQ,GAAGA,CAAA,KAAM;EAC5B,MAAMC,OAAO,GAAGzH,UAAU,CAAC8C,YAAY,CAAC;EACxC,IAAI,CAAC2E,OAAO,EAAE;IACZ,MAAM,IAAIC,KAAK,CACb,6EACF,CAAC;EACH;EACA,OAAOD,OAAO;AAChB,CAAC;AAED,MAAMH,MAAM,GAAGnH,UAAU,CAACwH,MAAM,CAAC;EAC/BJ,SAAS,EAAE;IACTK,eAAe,EAAE,SAAS;IAC1BC,YAAY,EAAE,EAAE;IAChBC,QAAQ,EAAE,UAAU;IACpBC,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC;AAEF,eAAehF,aAAa","ignoreList":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { TextInput } from 'react-native';
|
|
4
|
+
import Animated from 'react-native-reanimated';
|
|
5
|
+
|
|
6
|
+
// This trick allows animate the 'text' property of a TextInput directly from Reanimated
|
|
7
|
+
// Because React Native <Text> nodes cannot have their text updated 60 times a second without performance issues.
|
|
8
|
+
// <TextInput editable={false} /> acts as a hgh-performance Label.
|
|
9
|
+
|
|
10
|
+
// 1. Whitelist the native 'text' prop so Reanimated can modify it directly
|
|
11
|
+
Animated.addWhitelistedNativeProps({
|
|
12
|
+
text: true
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// 2. Extends the standard props to include 'text'
|
|
16
|
+
|
|
17
|
+
// 3. Create the component
|
|
18
|
+
const AnimatedTextInputComponent = Animated.createAnimatedComponent(TextInput);
|
|
19
|
+
|
|
20
|
+
// 4. Export with strict typing casting
|
|
21
|
+
// We cast it as a Component that accepts AnimatedTextInputProps
|
|
22
|
+
const AnimatedTextInput = AnimatedTextInputComponent;
|
|
23
|
+
export default AnimatedTextInput;
|
|
24
|
+
//# sourceMappingURL=AnimatedTextInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TextInput","Animated","addWhitelistedNativeProps","text","AnimatedTextInputComponent","createAnimatedComponent","AnimatedTextInput"],"sourceRoot":"../../../src","sources":["components/AnimatedTextInput.tsx"],"mappings":";;AAAA,SAASA,SAAS,QAAQ,cAAc;AAExC,OAAOC,QAAQ,MAA8B,yBAAyB;;AAEtE;AACA;AACA;;AAEA;AACAA,QAAQ,CAACC,yBAAyB,CAAC;EAAEC,IAAI,EAAE;AAAK,CAAC,CAAC;;AAElD;;AAKA;AACA,MAAMC,0BAA0B,GAAGH,QAAQ,CAACI,uBAAuB,CAACL,SAAS,CAAC;;AAE9E;AACA;AACA,MAAMM,iBAAiB,GACrBF,0BAEC;AAEH,eAAeE,iBAAiB","ignoreList":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { LinearGradient, Path, vec } from '@shopify/react-native-skia';
|
|
4
|
+
import { useChart } from "../ChartContext.js";
|
|
5
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
+
/**
|
|
7
|
+
* Draws the background gradient fill.
|
|
8
|
+
*/
|
|
9
|
+
const ChartArea = ({
|
|
10
|
+
gradientColors: _gradientColors
|
|
11
|
+
}) => {
|
|
12
|
+
const {
|
|
13
|
+
areaPath,
|
|
14
|
+
height,
|
|
15
|
+
gradientColors,
|
|
16
|
+
gradientPositions
|
|
17
|
+
} = useChart();
|
|
18
|
+
_gradientColors = _gradientColors || gradientColors;
|
|
19
|
+
return /*#__PURE__*/_jsx(Path, {
|
|
20
|
+
path: areaPath,
|
|
21
|
+
style: "fill",
|
|
22
|
+
children: /*#__PURE__*/_jsx(LinearGradient, {
|
|
23
|
+
start: vec(0, 0),
|
|
24
|
+
end: vec(0, height),
|
|
25
|
+
colors: _gradientColors,
|
|
26
|
+
positions: gradientPositions
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
export default ChartArea;
|
|
31
|
+
//# sourceMappingURL=ChartArea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["LinearGradient","Path","vec","useChart","jsx","_jsx","ChartArea","gradientColors","_gradientColors","areaPath","height","gradientPositions","path","style","children","start","end","colors","positions"],"sourceRoot":"../../../src","sources":["components/ChartArea.tsx"],"mappings":";;AAAA,SAASA,cAAc,EAAEC,IAAI,EAAEC,GAAG,QAAQ,4BAA4B;AACtE,SAASC,QAAQ,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAM3C;AACA;AACA;AACA,MAAMC,SAA2B,GAAGA,CAAC;EAAEC,cAAc,EAAEC;AAAgB,CAAC,KAAK;EAC3E,MAAM;IAAEC,QAAQ;IAAEC,MAAM;IAAEH,cAAc;IAAEI;EAAkB,CAAC,GAAGR,QAAQ,CAAC,CAAC;EAE1EK,eAAe,GAAGA,eAAe,IAAID,cAAc;EAEnD,oBACEF,IAAA,CAACJ,IAAI;IAACW,IAAI,EAAEH,QAAS;IAACI,KAAK,EAAC,MAAM;IAAAC,QAAA,eAChCT,IAAA,CAACL,cAAc;MACbe,KAAK,EAAEb,GAAG,CAAC,CAAC,EAAE,CAAC,CAAE;MACjBc,GAAG,EAAEd,GAAG,CAAC,CAAC,EAAEQ,MAAM,CAAE;MACpBO,MAAM,EAAET,eAAgB;MACxBU,SAAS,EAAEP;IAAkB,CAC9B;EAAC,CACE,CAAC;AAEX,CAAC;AAED,eAAeL,SAAS","ignoreList":[]}
|