react-native-livechart 4.20.0 → 4.21.1

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 (111) hide show
  1. package/dist/components/AxisLabelOverlay.d.ts +5 -1
  2. package/dist/components/AxisLabelOverlay.d.ts.map +1 -1
  3. package/dist/components/CrosshairOverlay.d.ts +4 -2
  4. package/dist/components/CrosshairOverlay.d.ts.map +1 -1
  5. package/dist/components/CustomMarkerOverlay.d.ts.map +1 -1
  6. package/dist/components/CustomThresholdBadgeOverlay.d.ts +18 -0
  7. package/dist/components/CustomThresholdBadgeOverlay.d.ts.map +1 -0
  8. package/dist/components/CustomTooltipOverlay.d.ts +4 -2
  9. package/dist/components/CustomTooltipOverlay.d.ts.map +1 -1
  10. package/dist/components/DegenParticlesOverlay.d.ts.map +1 -1
  11. package/dist/components/ExtremaConnectorOverlay.d.ts +5 -1
  12. package/dist/components/ExtremaConnectorOverlay.d.ts.map +1 -1
  13. package/dist/components/LiveChart.d.ts.map +1 -1
  14. package/dist/components/LiveChartSeries.d.ts.map +1 -1
  15. package/dist/components/MarkerOverlay.d.ts +4 -2
  16. package/dist/components/MarkerOverlay.d.ts.map +1 -1
  17. package/dist/components/ReferenceLineOverlay.d.ts +10 -5
  18. package/dist/components/ReferenceLineOverlay.d.ts.map +1 -1
  19. package/dist/components/ReferenceLineSeriesOverlay.d.ts +19 -0
  20. package/dist/components/ReferenceLineSeriesOverlay.d.ts.map +1 -0
  21. package/dist/core/chartDataPresence.d.ts +8 -0
  22. package/dist/core/chartDataPresence.d.ts.map +1 -0
  23. package/dist/core/liveChartEngineTick.d.ts +6 -1
  24. package/dist/core/liveChartEngineTick.d.ts.map +1 -1
  25. package/dist/core/resolveConfig.d.ts +32 -1
  26. package/dist/core/resolveConfig.d.ts.map +1 -1
  27. package/dist/core/useLiveChartEngine.d.ts +9 -1
  28. package/dist/core/useLiveChartEngine.d.ts.map +1 -1
  29. package/dist/core/useLiveChartSeriesEngine.d.ts.map +1 -1
  30. package/dist/draw/candle.d.ts +3 -1
  31. package/dist/draw/candle.d.ts.map +1 -1
  32. package/dist/draw/candleGap.d.ts +14 -0
  33. package/dist/draw/candleGap.d.ts.map +1 -0
  34. package/dist/draw/lineGap.d.ts +25 -0
  35. package/dist/draw/lineGap.d.ts.map +1 -0
  36. package/dist/draw/markerAtlas.d.ts +3 -2
  37. package/dist/draw/markerAtlas.d.ts.map +1 -1
  38. package/dist/hooks/crosshairShared.d.ts +7 -3
  39. package/dist/hooks/crosshairShared.d.ts.map +1 -1
  40. package/dist/hooks/useCandleGapPaths.d.ts +12 -0
  41. package/dist/hooks/useCandleGapPaths.d.ts.map +1 -0
  42. package/dist/hooks/useChartPaths.d.ts +4 -1
  43. package/dist/hooks/useChartPaths.d.ts.map +1 -1
  44. package/dist/hooks/useChartReveal.d.ts +1 -1
  45. package/dist/hooks/useChartReveal.d.ts.map +1 -1
  46. package/dist/hooks/useCrosshair.d.ts +9 -5
  47. package/dist/hooks/useCrosshair.d.ts.map +1 -1
  48. package/dist/hooks/useDegen.d.ts.map +1 -1
  49. package/dist/hooks/useLineGapPaths.d.ts +10 -0
  50. package/dist/hooks/useLineGapPaths.d.ts.map +1 -0
  51. package/dist/hooks/useLiveChartHasData.d.ts +2 -2
  52. package/dist/hooks/useLiveChartHasData.d.ts.map +1 -1
  53. package/dist/hooks/useReferenceLine.d.ts +4 -3
  54. package/dist/hooks/useReferenceLine.d.ts.map +1 -1
  55. package/dist/hooks/useReferenceLineSeries.d.ts +23 -0
  56. package/dist/hooks/useReferenceLineSeries.d.ts.map +1 -0
  57. package/dist/hooks/useReverseMorphEngineInputs.d.ts.map +1 -1
  58. package/dist/hooks/useThreshold.d.ts +13 -13
  59. package/dist/hooks/useThreshold.d.ts.map +1 -1
  60. package/dist/index.d.ts +1 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/math/candleGaps.d.ts +18 -0
  63. package/dist/math/candleGaps.d.ts.map +1 -0
  64. package/dist/math/referenceLineSeries.d.ts +12 -0
  65. package/dist/math/referenceLineSeries.d.ts.map +1 -0
  66. package/dist/math/referenceLines.d.ts +5 -5
  67. package/dist/math/referenceLines.d.ts.map +1 -1
  68. package/dist/math/spline.d.ts +5 -1
  69. package/dist/math/spline.d.ts.map +1 -1
  70. package/dist/types.d.ts +191 -17
  71. package/dist/types.d.ts.map +1 -1
  72. package/package.json +1 -1
  73. package/src/components/AxisLabelOverlay.tsx +162 -81
  74. package/src/components/CrosshairOverlay.tsx +394 -147
  75. package/src/components/CustomMarkerOverlay.tsx +9 -6
  76. package/src/components/CustomThresholdBadgeOverlay.tsx +74 -0
  77. package/src/components/CustomTooltipOverlay.tsx +7 -3
  78. package/src/components/DegenParticlesOverlay.tsx +34 -23
  79. package/src/components/ExtremaConnectorOverlay.tsx +43 -3
  80. package/src/components/LiveChart.tsx +1918 -974
  81. package/src/components/LiveChartSeries.tsx +445 -296
  82. package/src/components/MarkerOverlay.tsx +215 -156
  83. package/src/components/ReferenceLineOverlay.tsx +113 -55
  84. package/src/components/ReferenceLineSeriesOverlay.tsx +141 -0
  85. package/src/core/chartDataPresence.ts +24 -0
  86. package/src/core/liveChartEngineTick.ts +34 -1
  87. package/src/core/resolveConfig.ts +186 -0
  88. package/src/core/useLiveChartEngine.ts +36 -1
  89. package/src/core/useLiveChartSeriesEngine.ts +2 -0
  90. package/src/draw/candle.ts +1 -1
  91. package/src/draw/candleGap.ts +132 -0
  92. package/src/draw/lineGap.ts +180 -0
  93. package/src/draw/markerAtlas.ts +8 -3
  94. package/src/hooks/crosshairShared.ts +92 -11
  95. package/src/hooks/useCandleGapPaths.ts +88 -0
  96. package/src/hooks/useChartPaths.ts +81 -22
  97. package/src/hooks/useChartReveal.ts +1 -1
  98. package/src/hooks/useCrosshair.ts +178 -69
  99. package/src/hooks/useDegen.ts +82 -53
  100. package/src/hooks/useLineGapPaths.ts +76 -0
  101. package/src/hooks/useLiveChartHasData.ts +8 -4
  102. package/src/hooks/useReferenceLine.ts +6 -5
  103. package/src/hooks/useReferenceLineSeries.ts +101 -0
  104. package/src/hooks/useReverseMorphEngineInputs.ts +11 -20
  105. package/src/hooks/useThreshold.ts +31 -22
  106. package/src/index.ts +15 -0
  107. package/src/math/candleGaps.ts +120 -0
  108. package/src/math/referenceLineSeries.ts +83 -0
  109. package/src/math/referenceLines.ts +34 -6
  110. package/src/math/spline.ts +15 -5
  111. package/src/types.ts +202 -17
@@ -10,7 +10,7 @@ import type { ChartEngineLayout } from "../core/useLiveChartEngine";
10
10
  import type { ChartPadding } from "../draw/line";
11
11
  import type { TooltipLayout } from "../hooks/crosshairShared";
12
12
  import { resolveCrosshairVisibleOpacity } from "../hooks/useCrosshairVisibleOpacity";
13
- import type { CandlePoint, TooltipRenderProps } from "../types";
13
+ import type { CandleGap, CandlePoint, TooltipRenderProps } from "../types";
14
14
 
15
15
  // Mirror the Skia tooltip's offsets (see crosshairShared.ts) so a custom pill
16
16
  // lines up with where the built-in one would sit. The vertical edge gap is
@@ -42,6 +42,7 @@ export function CustomTooltipOverlay({
42
42
  scrubTime,
43
43
  scrubActive,
44
44
  scrubCandle,
45
+ scrubGap,
45
46
  tooltipLayout,
46
47
  engine,
47
48
  padding,
@@ -59,6 +60,8 @@ export function CustomTooltipOverlay({
59
60
  scrubActive: SharedValue<boolean>;
60
61
  /** OHLC candle under the crosshair (candle mode); omitted/`null` in line mode. */
61
62
  scrubCandle?: SharedValue<CandlePoint | null>;
63
+ /** Explicit line or candle gap under the crosshair; omitted/`null` outside one. */
64
+ scrubGap?: SharedValue<CandleGap | null>;
62
65
  tooltipLayout: SharedValue<TooltipLayout>;
63
66
  engine: ChartEngineLayout;
64
67
  padding: ChartPadding;
@@ -82,9 +85,9 @@ export function CustomTooltipOverlay({
82
85
  // a worklet-safe formatter for the value/time.
83
86
  const valueStr = useDerivedValue(() => tooltipLayout.get().valueStr);
84
87
  const timeStr = useDerivedValue(() => tooltipLayout.get().timeStr);
85
- // A stable `null` candle SharedValue for line mode so `ctx.candle` is always
86
- // present (a SharedValue), regardless of mode.
88
+ // Stable null SharedValues keep both fields present regardless of mode.
87
89
  const nullCandle = useSharedValue<CandlePoint | null>(null);
90
+ const nullGap = useSharedValue<CandleGap | null>(null);
88
91
 
89
92
  const ctx: TooltipRenderProps = {
90
93
  value: scrubValue,
@@ -93,6 +96,7 @@ export function CustomTooltipOverlay({
93
96
  timeStr,
94
97
  active: scrubActive,
95
98
  candle: scrubCandle ?? nullCandle,
99
+ gap: scrubGap ?? nullGap,
96
100
  };
97
101
  const element = renderTooltip(ctx);
98
102
 
@@ -17,6 +17,36 @@ import type { ChartEngineLayout } from "../core/useLiveChartEngine";
17
17
 
18
18
  type DegenPack = SharedValue<Float64Array<ArrayBuffer>>;
19
19
 
20
+ type ParticlePool = {
21
+ a: { transforms: SkRSXform[]; sprites: SkRect[]; colors: SkColor[] };
22
+ b: { transforms: SkRSXform[]; sprites: SkRect[]; colors: SkColor[] };
23
+ tick: boolean;
24
+ instances: ReturnType<typeof buildParticleInstances>;
25
+ instancePool: ReturnType<typeof buildParticleInstances>;
26
+ spriteRect: SkRect;
27
+ };
28
+
29
+ function makeParticlePool(
30
+ particleSlotCount: number,
31
+ spriteSize: number,
32
+ ): ParticlePool {
33
+ const instancePool = Array.from({ length: particleSlotCount }, () => ({
34
+ x: 0,
35
+ y: 0,
36
+ scale: 0,
37
+ alpha: 0,
38
+ colorIndex: 0,
39
+ }));
40
+ return {
41
+ a: { transforms: [], sprites: [], colors: [] },
42
+ b: { transforms: [], sprites: [], colors: [] },
43
+ tick: false,
44
+ instances: [],
45
+ instancePool,
46
+ spriteRect: Skia.XYWHRect(0, 0, spriteSize, spriteSize),
47
+ };
48
+ }
49
+
20
50
  /**
21
51
  * Renders the degen particle burst with a single `drawAtlas` call.
22
52
  *
@@ -64,30 +94,11 @@ export function DegenParticlesOverlay({
64
94
  // memoizes this on `colorList`.
65
95
  const colorRgb = colorList.map((c) => parseColorRgb(c));
66
96
 
67
- const poolRef = useRef<{
68
- a: { transforms: SkRSXform[]; sprites: SkRect[]; colors: SkColor[] };
69
- b: { transforms: SkRSXform[]; sprites: SkRect[]; colors: SkColor[] };
70
- tick: boolean;
71
- instances: ReturnType<typeof buildParticleInstances>;
72
- instancePool: ReturnType<typeof buildParticleInstances>;
73
- spriteRect: SkRect;
74
- } | null>(null);
97
+ const poolRef = useRef<ParticlePool | null>(null);
75
98
  if (poolRef.current === null) {
76
- const instancePool = Array.from({ length: particleSlotCount }, () => ({
77
- x: 0,
78
- y: 0,
79
- scale: 0,
80
- alpha: 0,
81
- colorIndex: 0,
82
- }));
83
- poolRef.current = {
84
- a: { transforms: [], sprites: [], colors: [] },
85
- b: { transforms: [], sprites: [], colors: [] },
86
- tick: false,
87
- instances: [],
88
- instancePool,
89
- spriteRect: Skia.XYWHRect(0, 0, sprite.size, sprite.size),
90
- };
99
+ // React permits this predictable lazy-ref initialization: https://react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents
100
+ // react-doctor-disable-next-line react-doctor/no-ref-current-in-render -- false positive for React's documented lazy-ref exception
101
+ poolRef.current = makeParticlePool(particleSlotCount, sprite.size);
91
102
  }
92
103
 
93
104
  // Single per-frame worklet. Reads `packRevision` so it re-runs each frame
@@ -11,7 +11,11 @@ import type {
11
11
  } from "../core/useLiveChartEngine";
12
12
  import type { ChartPadding } from "../draw/line";
13
13
  import { usePathBuilder } from "../hooks/usePathBuilder";
14
- import { EXTREMA_EDGE_INSET, EXTREMA_LABEL_FONT_SIZE } from "./AxisLabelOverlay";
14
+ import {
15
+ EXTREMA_EDGE_INSET,
16
+ EXTREMA_LABEL_FONT_SIZE,
17
+ extremaPointsCoincide,
18
+ } from "./AxisLabelOverlay";
15
19
 
16
20
  /** How far off-plot (px) the extremum may sit before the connector is dropped. */
17
21
  const CONNECTOR_CULL = 24;
@@ -55,6 +59,7 @@ function ConnectorLine({
55
59
  engine,
56
60
  padding,
57
61
  config,
62
+ suppressWhen,
58
63
  }: {
59
64
  side: "top" | "bottom";
60
65
  timeSV: SharedValue<number>;
@@ -63,6 +68,10 @@ function ConnectorLine({
63
68
  engine: ChartEngineLayout;
64
69
  padding: ChartPadding;
65
70
  config: ResolvedConnector;
71
+ suppressWhen?: {
72
+ timeSV: SharedValue<number>;
73
+ valueSV: SharedValue<number>;
74
+ };
66
75
  }) {
67
76
  const builder = usePathBuilder();
68
77
  const { line, fontSize } = config;
@@ -88,6 +97,13 @@ function ConnectorLine({
88
97
 
89
98
  if (
90
99
  !Number.isFinite(value) ||
100
+ (suppressWhen != null &&
101
+ extremaPointsCoincide(
102
+ time,
103
+ value,
104
+ suppressWhen.timeSV.get(),
105
+ suppressWhen.valueSV.get(),
106
+ )) ||
91
107
  cw === 0 ||
92
108
  ch === 0 ||
93
109
  chartW <= 0 ||
@@ -153,15 +169,29 @@ export function ExtremaConnectorOverlay({
153
169
  extremaTimeOffset = 0,
154
170
  top,
155
171
  bottom,
172
+ hideExtrema = false,
173
+ suppressBottomWhenCoincident = false,
156
174
  }: {
157
175
  engine: ChartEngineLayout & Partial<ChartEngineExtrema>;
158
176
  padding: ChartPadding;
159
177
  extremaTimeOffset?: number;
160
178
  top: ResolvedConnector | null;
161
179
  bottom: ResolvedConnector | null;
180
+ /** Hide extrema connectors while the chart is showing its loading shell. */
181
+ hideExtrema?: boolean;
182
+ /** Drop the lower connector when both configured labels share one point. */
183
+ suppressBottomWhenCoincident?: boolean;
162
184
  }) {
163
- const hasTop = top != null && engine.extremaMaxTime != null;
164
- const hasBottom = bottom != null && engine.extremaMinTime != null;
185
+ const hasTop =
186
+ !hideExtrema &&
187
+ top != null &&
188
+ engine.extremaMaxTime != null &&
189
+ engine.extremaMaxValue != null;
190
+ const hasBottom =
191
+ !hideExtrema &&
192
+ bottom != null &&
193
+ engine.extremaMinTime != null &&
194
+ engine.extremaMinValue != null;
165
195
  if (!hasTop && !hasBottom) return null;
166
196
 
167
197
  return (
@@ -186,6 +216,16 @@ export function ExtremaConnectorOverlay({
186
216
  engine={engine}
187
217
  padding={padding}
188
218
  config={bottom!}
219
+ suppressWhen={
220
+ suppressBottomWhenCoincident &&
221
+ engine.extremaMaxTime != null &&
222
+ engine.extremaMaxValue != null
223
+ ? {
224
+ timeSV: engine.extremaMaxTime!,
225
+ valueSV: engine.extremaMaxValue!,
226
+ }
227
+ : undefined
228
+ }
189
229
  />
190
230
  )}
191
231
  </>