diff --git a/src/components/expanded-state/chart/ChartExpandedStateHeader.js b/src/components/expanded-state/chart/ChartExpandedStateHeader.js
index 0afd18adfd8..96f58ed9df5 100644
--- a/src/components/expanded-state/chart/ChartExpandedStateHeader.js
+++ b/src/components/expanded-state/chart/ChartExpandedStateHeader.js
@@ -1,19 +1,19 @@
import lang from 'i18n-js';
import React, { useMemo } from 'react';
+import { View } from 'react-native';
import Animated, { FadeIn, useAnimatedStyle, withTiming } from 'react-native-reanimated';
-import { ColumnWithMargins, Row } from '../../layout';
-import ChartContextButton from './ChartContextButton';
-import { ChartDateLabel, ChartPercentChangeLabel, ChartPriceLabel } from './chart-data-labels';
-import { useChartData } from '@/react-native-animated-charts/src';
+import { TIMING_CONFIGS } from '@/components/animations/animationConfigs';
+import RainbowCoinIcon from '@/components/coin-icon/RainbowCoinIcon';
import { Column, Columns, Text } from '@/design-system';
import ChartTypes from '@/helpers/chartTypes';
import { convertAmountToNativeDisplay } from '@/helpers/utilities';
import { useAccountSettings } from '@/hooks';
+import { useChartData } from '@/react-native-animated-charts/src';
import styled from '@/styled-thing';
import { padding } from '@/styles';
-import RainbowCoinIcon from '@/components/coin-icon/RainbowCoinIcon';
-import { View } from 'react-native';
-import { TIMING_CONFIGS } from '@/components/animations/animationConfigs';
+import { ColumnWithMargins, Row } from '../../layout';
+import ChartContextButton from './ChartContextButton';
+import { ChartDateLabel, ChartPercentChangeLabel, ChartPriceLabel } from './chart-data-labels';
const noPriceData = lang.t('expanded_state.chart.no_price_data');
@@ -26,7 +26,6 @@ const Container = styled(ColumnWithMargins).attrs({
export default function ChartExpandedStateHeader({
asset,
color: givenColors,
- dateRef,
isPool,
latestChange,
latestPrice = noPriceData,
@@ -84,7 +83,7 @@ export default function ChartExpandedStateHeader({
const firstValue = data?.points?.[0]?.y;
const lastValue = data?.points?.[data.points.length - 1]?.y;
- return firstValue === Number(firstValue) ? lastValue / firstValue : 1;
+ return firstValue === Number(firstValue) ? lastValue / firstValue : undefined;
}, [data]);
const showPriceChangeStyle = useAnimatedStyle(() => {
@@ -135,7 +134,7 @@ export default function ChartExpandedStateHeader({
-
+
diff --git a/src/components/expanded-state/chart/chart-data-labels/ChartDateLabel.js b/src/components/expanded-state/chart/chart-data-labels/ChartDateLabel.tsx
similarity index 69%
rename from src/components/expanded-state/chart/chart-data-labels/ChartDateLabel.js
rename to src/components/expanded-state/chart/chart-data-labels/ChartDateLabel.tsx
index 344067f6eec..6308b7a450d 100644
--- a/src/components/expanded-state/chart/chart-data-labels/ChartDateLabel.js
+++ b/src/components/expanded-state/chart/chart-data-labels/ChartDateLabel.tsx
@@ -1,8 +1,9 @@
import lang from 'i18n-js';
-import React from 'react';
-import { useAnimatedStyle } from 'react-native-reanimated';
+import React, { useCallback } from 'react';
+import Animated, { AnimatedStyle, FadeIn, useAnimatedStyle } from 'react-native-reanimated';
import { useRatio } from './useRatio';
import { ChartXLabel, useChartData } from '@/react-native-animated-charts/src';
+import { useTheme } from '@/theme';
const MONTHS = [
lang.t('expanded_state.chart.date.months.month_00'),
@@ -19,7 +20,7 @@ const MONTHS = [
lang.t('expanded_state.chart.date.months.month_11'),
];
-function formatDatetime(value, chartTimeDefaultValue) {
+function formatDatetime(value: string, chartTimeDefaultValue: string) {
'worklet';
// we have to do it manually due to limitations of reanimated
if (value === '') {
@@ -70,25 +71,37 @@ function formatDatetime(value, chartTimeDefaultValue) {
return res;
}
-export default function ChartDateLabel({ chartTimeDefaultValue, ratio }) {
+export default function ChartDateLabel({
+ chartTimeDefaultValue,
+ ratio,
+ showPriceChangeStyle,
+}: {
+ chartTimeDefaultValue: string;
+ ratio: number | undefined;
+ showPriceChangeStyle: AnimatedStyle;
+}) {
const { isActive } = useChartData();
- const sharedRatio = useRatio('ChartDataLabel');
+ const sharedRatio = useRatio();
const { colors } = useTheme();
const textStyle = useAnimatedStyle(() => {
const realRatio = isActive.value ? sharedRatio.value : ratio;
return {
- color: realRatio === 1 ? colors.blueGreyDark : realRatio < 1 ? colors.red : colors.green,
+ color: realRatio !== undefined ? (realRatio === 1 ? colors.blueGreyDark : realRatio < 1 ? colors.red : colors.green) : 'transparent',
};
- }, [ratio]);
+ });
const formatWorklet = useCallback(
- value => {
+ (value: string) => {
'worklet';
return formatDatetime(value, chartTimeDefaultValue);
},
[chartTimeDefaultValue]
);
- return ;
+ return (
+
+
+
+ );
}
diff --git a/src/components/expanded-state/chart/chart-data-labels/ChartPercentChangeLabel.js b/src/components/expanded-state/chart/chart-data-labels/ChartPercentChangeLabel.tsx
similarity index 57%
rename from src/components/expanded-state/chart/chart-data-labels/ChartPercentChangeLabel.js
rename to src/components/expanded-state/chart/chart-data-labels/ChartPercentChangeLabel.tsx
index 8e14ee25ed3..2dca8a3670b 100644
--- a/src/components/expanded-state/chart/chart-data-labels/ChartPercentChangeLabel.js
+++ b/src/components/expanded-state/chart/chart-data-labels/ChartPercentChangeLabel.tsx
@@ -1,11 +1,13 @@
import React, { memo } from 'react';
-import { useAnimatedStyle, useDerivedValue } from 'react-native-reanimated';
+import { DerivedValue, SharedValue, useAnimatedStyle, useDerivedValue } from 'react-native-reanimated';
import { AnimatedText } from '@/design-system';
import { IS_ANDROID } from '@/env';
import { useChartData } from '@/react-native-animated-charts/src';
+import { useTheme } from '@/theme';
import { useRatio } from './useRatio';
+import { DataType } from '@/react-native-animated-charts/src/helpers/ChartContext';
-function formatNumber(num) {
+function formatNumber(num: string) {
'worklet';
const first = num.split('.');
const digits = first[0].split('').reverse();
@@ -19,25 +21,29 @@ function formatNumber(num) {
return newDigits.reverse().join('') + '.' + first[1];
}
-const formatWorklet = (originalY, data, latestChange) => {
+const formatWorklet = (originalY: SharedValue, data: DataType, latestChange: number | undefined) => {
'worklet';
const firstValue = data?.points?.[0]?.y;
const lastValue = data?.points?.[data.points.length - 1]?.y;
return firstValue === Number(firstValue) && firstValue
? (() => {
+ const originalYNumber = Number(originalY?.value);
const value =
- originalY?.value === lastValue || !originalY?.value
- ? parseFloat(latestChange ?? 0)
- : ((originalY.value || lastValue) / firstValue) * 100 - 100;
- const numValue = parseFloat(value);
+ originalYNumber === lastValue || !originalYNumber ? latestChange ?? 0 : ((originalYNumber || lastValue) / firstValue) * 100 - 100;
- return (IS_ANDROID ? '' : numValue > 0 ? '↑' : numValue < 0 ? '↓' : '') + ' ' + formatNumber(Math.abs(numValue).toFixed(2)) + '%';
+ return (IS_ANDROID ? '' : value > 0 ? '↑' : value < 0 ? '↓' : '') + ' ' + formatNumber(Math.abs(value).toFixed(2)) + '%';
})()
: '';
};
-export default memo(function ChartPercentChangeLabel({ ratio, latestChange }) {
+export default memo(function ChartPercentChangeLabel({
+ latestChange,
+ ratio,
+}: {
+ latestChange: DerivedValue;
+ ratio: number | undefined;
+}) {
const { originalY, data, isActive } = useChartData();
const { colors } = useTheme();
@@ -47,9 +53,9 @@ export default memo(function ChartPercentChangeLabel({ ratio, latestChange }) {
const textStyle = useAnimatedStyle(() => {
const realRatio = isActive.value ? sharedRatio.value : ratio;
return {
- color: realRatio === 1 ? colors.blueGreyDark : realRatio < 1 ? colors.red : colors.green,
+ color: realRatio !== undefined ? (realRatio === 1 ? colors.blueGreyDark : realRatio < 1 ? colors.red : colors.green) : 'transparent',
};
- }, [ratio]);
+ });
return (
({
const Container = styled(Column)({
paddingBottom: 30,
- paddingTop: ios ? 0 : 20,
+ paddingTop: IS_IOS ? 0 : 4,
width: '100%',
});
diff --git a/src/components/value-chart/ExtremeLabels.js b/src/components/value-chart/ExtremeLabels.tsx
similarity index 58%
rename from src/components/value-chart/ExtremeLabels.js
rename to src/components/value-chart/ExtremeLabels.tsx
index 47b3bc07a78..c4a689039ed 100644
--- a/src/components/value-chart/ExtremeLabels.js
+++ b/src/components/value-chart/ExtremeLabels.tsx
@@ -1,23 +1,39 @@
import React, { useCallback, useMemo, useState } from 'react';
-import { View } from 'react-native';
+import { LayoutChangeEvent, StyleProp, View, ViewStyle } from 'react-native';
import { formatNative } from '../expanded-state/chart/chart-data-labels/ChartPriceLabel';
import { useChartData } from '@/react-native-animated-charts/src';
import { Text } from '@/design-system';
import { useAccountSettings } from '@/hooks';
import { supportedNativeCurrencies } from '@/references';
+import { useTheme } from '@/theme';
+import { TextSize } from '@/design-system/typography/typeHierarchy';
-function trim(val) {
+function trim(val: number) {
return Math.min(Math.max(val, 0.05), 0.95);
}
-const CenteredLabel = ({ position, fontSize = '14px / 19px (Deprecated)', style, width, ...props }) => {
+const CenteredLabel = ({
+ children,
+ color,
+ position,
+ size = '14px / 19px (Deprecated)',
+ style,
+ width,
+}: {
+ children: React.ReactNode;
+ color: string;
+ position: number;
+ size?: TextSize;
+ style: StyleProp;
+ width: number;
+}) => {
const [componentWidth, setWidth] = useState(0);
const onLayout = useCallback(
({
nativeEvent: {
layout: { width: newWidth },
},
- }) => {
+ }: LayoutChangeEvent) => {
setWidth(newWidth);
},
[setWidth]
@@ -30,29 +46,30 @@ const CenteredLabel = ({ position, fontSize = '14px / 19px (Deprecated)', style,
return (
-
- {props.children}
+
+ {children}
);
};
-const Labels = ({ color, width, isCard }) => {
+const Labels = ({ color, width, isCard }: { color: string; width: number; isCard: boolean }) => {
const { nativeCurrency } = useAccountSettings();
const nativeSelected = supportedNativeCurrencies?.[nativeCurrency];
const { greatestX, greatestY, smallestX, smallestY } = useChartData();
const { colors } = useTheme();
- if (!greatestX) {
- return null;
- }
+ if (!greatestX || !greatestY || !smallestX || !smallestY) return null;
+
const positionMin = trim((smallestY.x - smallestX.x) / (greatestX.x - smallestX.x));
const positionMax = trim((greatestY.x - smallestX.x) / (greatestX.x - smallestX.x));
@@ -62,27 +79,22 @@ const Labels = ({ color, width, isCard }) => {
- {formatNative(smallestY.y, null, nativeSelected)}
+ {formatNative(smallestY.y.toString(), null, nativeSelected)}
) : null}
{positionMax ? (
- {formatNative(greatestY.y, null, nativeSelected)}
+ {formatNative(greatestY.y.toString(), null, nativeSelected)}
) : null}
>
diff --git a/src/hooks/charts/useChartDataLabels.ts b/src/hooks/charts/useChartDataLabels.ts
index 53d023ae749..2e6979739c3 100644
--- a/src/hooks/charts/useChartDataLabels.ts
+++ b/src/hooks/charts/useChartDataLabels.ts
@@ -1,15 +1,32 @@
import { useCallback } from 'react';
-import ChartTypes, { ChartType } from '@/helpers/chartTypes';
-import { ChartData } from './useChartInfo';
import { useDerivedValue } from 'react-native-reanimated';
+import ChartTypes, { ChartType } from '@/helpers/chartTypes';
import { toFixedWorklet } from '@/safe-math/SafeMath';
+import { AssetApiResponse, AssetMetadata } from '@/__swaps__/types/assets';
+import { ChartData } from './useChartInfo';
const formatPercentChange = (change = 0) => {
'worklet';
return toFixedWorklet(change, 2);
};
-export default function useChartDataLabels({ asset, chartType, points }: { asset: any; chartType: ChartType; points: ChartData[] }) {
+type AssetWithPrice = (AssetApiResponse | AssetMetadata) & {
+ price?: {
+ relative_change_24h?: number;
+ relativeChange24h?: number;
+ value: number;
+ };
+};
+
+export default function useChartDataLabels({
+ asset,
+ chartType,
+ points,
+}: {
+ asset: AssetWithPrice;
+ chartType: ChartType;
+ points: ChartData[];
+}) {
const latestPrice = asset?.price?.value;
const getPercentChangeForPrice = useCallback(
@@ -23,11 +40,14 @@ export default function useChartDataLabels({ asset, chartType, points }: { asset
[points]
);
- const latestChange = useDerivedValue(() =>
- !points || chartType === ChartTypes.day
- ? formatPercentChange(asset?.price?.relative_change_24h || asset?.price?.relativeChange24h)
- : getPercentChangeForPrice(points[0]?.y ?? 0)
- );
+ const latestChange = useDerivedValue(() => {
+ if (!points || chartType === ChartTypes.day) {
+ // Handle both AssetApiResponse and AssetMetadata price change fields
+ const change = asset?.price?.relative_change_24h ?? asset?.price?.relativeChange24h ?? 0;
+ return formatPercentChange(change);
+ }
+ return getPercentChangeForPrice(points[0]?.y ?? 0);
+ });
return {
latestChange,
diff --git a/src/react-native-animated-charts/src/charts/linear/ChartPathProvider.tsx b/src/react-native-animated-charts/src/charts/linear/ChartPathProvider.tsx
index bc4659cba17..80d797dcb5a 100644
--- a/src/react-native-animated-charts/src/charts/linear/ChartPathProvider.tsx
+++ b/src/react-native-animated-charts/src/charts/linear/ChartPathProvider.tsx
@@ -19,7 +19,7 @@ interface ChartPathProviderProps {
children: React.ReactNode;
}
-function getCurveType(curveType: keyof typeof CurveType) {
+function getCurveType(curveType: keyof typeof CurveType | undefined) {
switch (curveType) {
case CurveType.basis:
return shape.curveBasis;
@@ -97,7 +97,7 @@ function createPath({ data, width, height, yRange }: CallbackType): PathData {
.line()
.x(item => scaleX(item.x))
.y(item => scaleY(item.y))
- .curve(getCurveType(data.curve!))(data.points);
+ .curve(getCurveType(data.curve))(data.points);
if (path === null) {
return {
@@ -161,7 +161,7 @@ export const ChartPathProvider = React.memo(({ children,
// because we do have initial data in the paths
// we wait until we receive new stuff in deps
if (initialized.current) {
- setPaths(([_, curr]) => [curr, data.points.length ? createPath({ data, height, width, yRange }) : null]);
+ setPaths(([, curr]) => [curr, data.points.length ? createPath({ data, height, width, yRange }) : null]);
} else {
// componentDidMount hack
initialized.current = true;
diff --git a/src/react-native-animated-charts/src/helpers/ChartContext.ts b/src/react-native-animated-charts/src/helpers/ChartContext.ts
index 118c8d60feb..cb30230808a 100644
--- a/src/react-native-animated-charts/src/helpers/ChartContext.ts
+++ b/src/react-native-animated-charts/src/helpers/ChartContext.ts
@@ -46,7 +46,9 @@ export interface PathScales {
scaleY: (value: number) => number;
}
-export interface ChartData {
+type WithPathData = Pick;
+
+export type ChartData = {
data: DataType;
width: number;
height: number;
@@ -61,6 +63,6 @@ export interface ChartData {
positionY: SharedValue;
previousPath: PathData | null;
currentPath: PathData | null;
-}
+} & WithPathData;
export const ChartContext = React.createContext(null);