Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xDomain option for Candlestick chart #196

Open
fprt77 opened this issue Feb 6, 2025 · 0 comments
Open

xDomain option for Candlestick chart #196

fprt77 opened this issue Feb 6, 2025 · 0 comments

Comments

@fprt77
Copy link

fprt77 commented Feb 6, 2025

There is no option to set "xDomain" for candlestick charts. Even for line chart this functionality break when interacting with chart itself (touch index is calculated as if chart is always stretched from start to end, thus ignoring xDomain interval).

For those who might be interested I have made patch that fixes both issues and allows both line and candlestick chart to be drawn inside xDomain interval.

Examples:

Image

Image

Patch content - react-native-wagmi-charts+2.6.0.patch
diff --git a/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Candle.d.ts b/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Candle.d.ts
index 6a7d5fa..ef31042 100644
--- a/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Candle.d.ts
+++ b/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Candle.d.ts
@@ -32,5 +32,8 @@ export type CandlestickChartCandleProps = {
         useAnimations: boolean;
     }) => React.ReactNode;
 };
-export declare const CandlestickChartCandle: ({ candle, maxHeight, domain, margin, positiveColor, negativeColor, rectProps: overrideRectProps, lineProps: overrideLineProps, index, width, useAnimations, renderLine, renderRect, }: CandlestickChartCandleProps) => React.JSX.Element;
+export type CandlestickChartCandleExtraProps = {
+    domainOffset: number;
+};
+export declare const CandlestickChartCandle: ({ candle, maxHeight, domain, margin, positiveColor, negativeColor, rectProps: overrideRectProps, lineProps: overrideLineProps, index, width, useAnimations, renderLine, renderRect, domainOffset, }: CandlestickChartCandleProps & CandlestickChartCandleExtraProps) => JSX.Element;
 //# sourceMappingURL=Candle.d.ts.map
\ No newline at end of file
diff --git a/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Candle.d.ts.map b/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Candle.d.ts.map
index 68724a4..8c33af7 100644
--- a/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Candle.d.ts.map
+++ b/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Candle.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"Candle.d.ts","sourceRoot":"","sources":["../../../../../src/charts/candle/Candle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAK1C,OAAO,EAAQ,SAAS,EAAE,UAAU,EAAQ,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAMhD,MAAM,MAAM,2BAA2B,GAAG;IACxC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,EACZ,CAAC,EACD,CAAC,EACD,KAAK,EACL,MAAM,EACN,IAAI,GACL,EAAE;QACD,CAAC,EAAE,UAAU,CAAC;QACd,CAAC,EAAE,UAAU,CAAC;QACd,KAAK,EAAE,UAAU,CAAC;QAClB,MAAM,EAAE,UAAU,CAAC;QACnB,IAAI,EAAE,UAAU,CAAC;QACjB,aAAa,EAAE,OAAO,CAAC;KACxB,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB,UAAU,CAAC,EAAE,CAAC,EACZ,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,MAAM,EACN,WAAW,GACZ,EAAE;QACD,EAAE,EAAE,UAAU,CAAC;QACf,EAAE,EAAE,UAAU,CAAC;QACf,EAAE,EAAE,UAAU,CAAC;QACf,EAAE,EAAE,UAAU,CAAC;QACf,MAAM,EAAE,UAAU,CAAC;QACnB,WAAW,EAAE,UAAU,CAAC;QACxB,aAAa,EAAE,OAAO,CAAC;KACxB,KAAK,KAAK,CAAC,SAAS,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,sBAAsB,0LAgBhC,2BAA2B,sBAiF7B,CAAC"}
\ No newline at end of file
+{"version":3,"file":"Candle.d.ts","sourceRoot":"","sources":["../Candle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAK1C,OAAO,EAAQ,SAAS,EAAE,UAAU,EAAQ,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAMhD,MAAM,MAAM,2BAA2B,GAAG;IACxC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,EACZ,CAAC,EACD,CAAC,EACD,KAAK,EACL,MAAM,EACN,IAAI,GACL,EAAE;QACD,CAAC,EAAE,UAAU,CAAC;QACd,CAAC,EAAE,UAAU,CAAC;QACd,KAAK,EAAE,UAAU,CAAC;QAClB,MAAM,EAAE,UAAU,CAAC;QACnB,IAAI,EAAE,UAAU,CAAC;QACjB,aAAa,EAAE,OAAO,CAAC;KACxB,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB,UAAU,CAAC,EAAE,CAAC,EACZ,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,MAAM,EACN,WAAW,GACZ,EAAE;QACD,EAAE,EAAE,UAAU,CAAC;QACf,EAAE,EAAE,UAAU,CAAC;QACf,EAAE,EAAE,UAAU,CAAC;QACf,EAAE,EAAE,UAAU,CAAC;QACf,MAAM,EAAE,UAAU,CAAC;QACnB,WAAW,EAAE,UAAU,CAAC;QACxB,aAAa,EAAE,OAAO,CAAC;KACxB,KAAK,KAAK,CAAC,SAAS,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,YAAY,EAAE,MAAM,CAAC;CACtB,CAAA;AAED,eAAO,MAAM,sBAAsB,wMAiBhC,2BAA2B,GAAG,gCAAgC,gBAiFhE,CAAC"}
\ No newline at end of file
diff --git a/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Context.d.ts b/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Context.d.ts
index b26acf5..ee6a974 100644
--- a/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Context.d.ts
+++ b/node_modules/react-native-wagmi-charts/lib/typescript/src/charts/candle/Context.d.ts
@@ -7,6 +7,9 @@ type CandlestickChartProviderProps = {
     width?: number;
     height?: number;
 };
-export declare function CandlestickChartProvider({ children, data, }: CandlestickChartProviderProps): React.JSX.Element;
+type CandlestickChartProviderExtraProps = {
+    xDomain?: [number, number];
+};
+export declare function CandlestickChartProvider({ children, data, xDomain }: CandlestickChartProviderProps & CandlestickChartProviderExtraProps): React.JSX.Element;
 export {};
 //# sourceMappingURL=Context.d.ts.map
\ No newline at end of file
diff --git a/node_modules/react-native-wagmi-charts/src/charts/candle/Candle.tsx b/node_modules/react-native-wagmi-charts/src/charts/candle/Candle.tsx
index a63f8e1..aad0018 100644
--- a/node_modules/react-native-wagmi-charts/src/charts/candle/Candle.tsx
+++ b/node_modules/react-native-wagmi-charts/src/charts/candle/Candle.tsx
@@ -56,6 +56,10 @@ export type CandlestickChartCandleProps = {
   }) => React.ReactNode;
 };
 
+export type CandlestickChartCandleExtraProps = {
+  domainOffset: number;
+}
+
 export const CandlestickChartCandle = ({
   candle,
   maxHeight,
@@ -72,11 +76,12 @@ export const CandlestickChartCandle = ({
     props.useAnimations ? <AnimatedLine {...props} /> : <Line {...props} />,
   renderRect = (props) =>
     props.useAnimations ? <AnimatedRect {...props} /> : <Rect {...props} />,
-}: CandlestickChartCandleProps) => {
+  domainOffset,
+}: CandlestickChartCandleProps & CandlestickChartCandleExtraProps) => {
   const { close, open, high, low } = candle;
   const isPositive = close > open;
   const fill = isPositive ? positiveColor : negativeColor;
-  const x = index * width;
+  const x = domainOffset + index * width;
   const max = Math.max(open, close);
   const min = Math.min(open, close);
 
diff --git a/node_modules/react-native-wagmi-charts/src/charts/candle/Candles.tsx b/node_modules/react-native-wagmi-charts/src/charts/candle/Candles.tsx
index 077d008..4aa88ee 100644
--- a/node_modules/react-native-wagmi-charts/src/charts/candle/Candles.tsx
+++ b/node_modules/react-native-wagmi-charts/src/charts/candle/Candles.tsx
@@ -32,7 +32,7 @@ export function CandlestickChartCandles({
   ...props
 }: CandlestickChartCandlesProps) {
   const { width, height } = React.useContext(CandlestickChartDimensionsContext);
-  const { data, domain, step } = useCandlestickChart();
+  const { data, domain, step, domainOffset } = useCandlestickChart();
 
   ////////////////////////////////////////////////
 
@@ -55,6 +55,7 @@ export function CandlestickChartCandles({
             useAnimations={useAnimations}
             candle={candle}
             index={index}
+            domainOffset={domainOffset}
             {...candleProps}
           />
         ))}
diff --git a/node_modules/react-native-wagmi-charts/src/charts/candle/Context.tsx b/node_modules/react-native-wagmi-charts/src/charts/candle/Context.tsx
index 14545d0..6ecb128 100644
--- a/node_modules/react-native-wagmi-charts/src/charts/candle/Context.tsx
+++ b/node_modules/react-native-wagmi-charts/src/charts/candle/Context.tsx
@@ -14,32 +14,52 @@ export const CandlestickChartContext = React.createContext<TContext>({
   step: 0,
   setWidth: () => undefined,
   setHeight: () => undefined,
+  xDomain: undefined,
+  domainOffset: 0,
 });
 
-type CandlestickChartProviderProps = {
+export type CandlestickChartProviderProps = {
   children: React.ReactNode;
   data: TData;
   width?: number;
   height?: number;
+  xDomain?: [number, number];
+};
+
+export type CandlestickChartProviderExtraProps = {
+  xDomain?: [number, number];
 };
 
 export function CandlestickChartProvider({
   children,
   data = [],
-}: CandlestickChartProviderProps) {
+  xDomain,
+}: CandlestickChartProviderProps & CandlestickChartProviderExtraProps) {
   const [width, setWidth] = React.useState(0);
   const [height, setHeight] = React.useState(0);
   const [step, setStep] = React.useState(0);
+  const [domainOffset, setDomainOffset] = React.useState(0);
   const currentX = useSharedValue(-1);
   const currentY = useSharedValue(-1);
   const domain = React.useMemo(() => getDomain(data), [data]);
 
   React.useEffect(() => {
     if (data.length) {
-      const newStep = width / data.length;
+      var newStep: number;
+      var newDomainOffset: number;
+      if (xDomain) {
+        const startPosition = (data[0].timestamp - xDomain[0]) / (xDomain[1] - xDomain[0]);
+        const endPosition = (data[data.length - 1].timestamp - xDomain[0]) / (xDomain[1] - xDomain[0]);
+        newStep = width * (endPosition - startPosition) / data.length;
+        newDomainOffset = width * startPosition;
+      } else {
+        newStep = width / data.length;
+        newDomainOffset = 0;
+      }
       setStep(newStep);
+      setDomainOffset(newDomainOffset);
     }
-  }, [data.length, width]);
+  }, [data.length, width, xDomain]);
 
   const contextValue = React.useMemo(
     () => ({
@@ -53,8 +73,10 @@ export function CandlestickChartProvider({
       setWidth,
       setHeight,
       setStep,
+      xDomain,
+      domainOffset,
     }),
-    [currentX, currentY, data, domain, height, step, width]
+    [currentX, currentY, data, domain, height, step, width, xDomain, domainOffset]
   );
 
   return (
diff --git a/node_modules/react-native-wagmi-charts/src/charts/candle/Crosshair.tsx b/node_modules/react-native-wagmi-charts/src/charts/candle/Crosshair.tsx
index ca1fa14..0fc7aaf 100644
--- a/node_modules/react-native-wagmi-charts/src/charts/candle/Crosshair.tsx
+++ b/node_modules/react-native-wagmi-charts/src/charts/candle/Crosshair.tsx
@@ -39,7 +39,7 @@ export function CandlestickChartCrosshair({
   ...props
 }: CandlestickChartCrosshairProps) {
   const { width, height } = React.useContext(CandlestickChartDimensionsContext);
-  const { currentX, currentY, step } = useCandlestickChart();
+  const { currentX, currentY, step, domainOffset } = useCandlestickChart();
 
   const tooltipPosition = useSharedValue<'left' | 'right'>('left');
 
@@ -56,7 +56,7 @@ export function CandlestickChartCrosshair({
       }
       opacity.value = 1;
       currentY.value = clamp(y, 0, height);
-      currentX.value = boundedX - (boundedX % step) + step / 2;
+      currentX.value = (boundedX - domainOffset) - ((boundedX - domainOffset) % step) + step / 2;
     },
     onEnd: () => {
       opacity.value = 0;
@@ -74,9 +74,9 @@ export function CandlestickChartCrosshair({
   const vertical = useAnimatedStyle(
     () => ({
       opacity: opacity.value,
-      transform: [{ translateX: currentX.value }],
+      transform: [{ translateX: domainOffset + currentX.value }],
     }),
-    [opacity, currentX]
+    [opacity, currentX, domainOffset]
   );
 
   useAnimatedReaction(
diff --git a/node_modules/react-native-wagmi-charts/src/charts/candle/types.ts b/node_modules/react-native-wagmi-charts/src/charts/candle/types.ts
index a6c8a59..1877842 100644
--- a/node_modules/react-native-wagmi-charts/src/charts/candle/types.ts
+++ b/node_modules/react-native-wagmi-charts/src/charts/candle/types.ts
@@ -20,6 +20,8 @@ export type TContext = {
   step: number;
   setWidth: React.Dispatch<React.SetStateAction<number>>;
   setHeight: React.Dispatch<React.SetStateAction<number>>;
+  xDomain?: [number, number] | undefined;
+  domainOffset: number;
 };
 export type TPriceType = 'crosshair' | 'open' | 'close' | 'low' | 'high';
 export type TFormatterFn<T> = ({
diff --git a/node_modules/react-native-wagmi-charts/src/charts/candle/useCandleData.ts b/node_modules/react-native-wagmi-charts/src/charts/candle/useCandleData.ts
index 5321ec4..7cee72b 100644
--- a/node_modules/react-native-wagmi-charts/src/charts/candle/useCandleData.ts
+++ b/node_modules/react-native-wagmi-charts/src/charts/candle/useCandleData.ts
@@ -10,7 +10,11 @@ export function useCandleData(): Readonly<SharedValue<TCandle>> {
     if (currentX.value === -1) {
       return { timestamp: -1, low: -1, open: -1, high: -1, close: -1 };
     }
-    return data[Math.floor(currentX.value / step)] as TCandle;
+    const index = Math.floor(currentX.value / step)
+    if (index < 0 || index >= data.length) {
+      return { timestamp: -1, low: -1, open: -1, high: -1, close: -1 };
+    }
+    return data[index] as TCandle;
   }, [currentX, data, step]);
 
   return candle;
diff --git a/node_modules/react-native-wagmi-charts/src/charts/candle/usePrice.ts b/node_modules/react-native-wagmi-charts/src/charts/candle/usePrice.ts
index 85095ee..634d084 100644
--- a/node_modules/react-native-wagmi-charts/src/charts/candle/usePrice.ts
+++ b/node_modules/react-native-wagmi-charts/src/charts/candle/usePrice.ts
@@ -31,7 +31,7 @@ export function useCandlestickChartPrice({
         maxHeight: height,
       });
     } else {
-      price = candle.value[type];
+      price = candle.value ? candle.value[type] : -1;
     }
     if (price === -1) return '';
     return price.toFixed(precision).toString();
diff --git a/node_modules/react-native-wagmi-charts/src/charts/line/Cursor.tsx b/node_modules/react-native-wagmi-charts/src/charts/line/Cursor.tsx
index 310330b..faa5219 100644
--- a/node_modules/react-native-wagmi-charts/src/charts/line/Cursor.tsx
+++ b/node_modules/react-native-wagmi-charts/src/charts/line/Cursor.tsx
@@ -99,10 +99,22 @@ export function LineChartCursor({
         // so we clamp the index at 0 to fix it
         // https://github.com/coinjar/react-native-wagmi-charts/issues/24
         const minIndex = 0;
-        const boundedIndex = Math.max(
+        var boundedIndex = Math.max(
           minIndex,
           Math.round(xPosition / width / (1 / (data ? data.length - 1 : 1)))
         );
+        if (xDomain && data) {
+          const xPositionFraction = xPosition / width
+          const startPosition = (data[0].timestamp - xDomain[0]) / (xDomain[1] - xDomain[0])
+          const endPosition = (data[data.length - 1].timestamp - xDomain[0]) / (xDomain[1] - xDomain[0])
+          if (xPositionFraction <= startPosition) {
+            boundedIndex = -1
+          } if (xPositionFraction > endPosition) {
+            boundedIndex = -1
+          } else {
+            boundedIndex = Math.round((data.length - 1) * (xPositionFraction - startPosition) / (endPosition - startPosition))
+          }
+        }
 
         if (snapToPoint) {
           // We have to run this on the JS thread unfortunately as the scaleLinear functions won't work on UI thread
diff --git a/node_modules/react-native-wagmi-charts/src/charts/line/Tooltip.tsx b/node_modules/react-native-wagmi-charts/src/charts/line/Tooltip.tsx
index 5a81e57..34c8d00 100644
--- a/node_modules/react-native-wagmi-charts/src/charts/line/Tooltip.tsx
+++ b/node_modules/react-native-wagmi-charts/src/charts/line/Tooltip.tsx
@@ -144,14 +144,14 @@ export function LineChartTooltip({
     };
   }, [
     atXPosition,
-    atYPosition.value,
-    currentX.value,
-    currentY.value,
+    atYPosition,
+    currentX,
+    currentY,
     cursorGutter,
-    elementHeight.value,
-    elementWidth.value,
+    elementHeight,
+    elementWidth,
     height,
-    isActive.value,
+    isActive,
     position,
     type,
     width,
diff --git a/node_modules/react-native-wagmi-charts/src/components/AnimatedText.tsx b/node_modules/react-native-wagmi-charts/src/components/AnimatedText.tsx
index 6c4c175..8ca741c 100644
--- a/node_modules/react-native-wagmi-charts/src/components/AnimatedText.tsx
+++ b/node_modules/react-native-wagmi-charts/src/components/AnimatedText.tsx
@@ -51,7 +51,7 @@ export const AnimatedText = ({ text, style }: AnimatedTextProps) => {
       underlineColorAndroid="transparent"
       editable={false}
       ref={Platform.select({ web: inputRef })}
-      value={text.value}
+      value={text}
       style={[styles.text, style]}
       animatedProps={animatedProps}
     />

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant