@ledgerhq/lumen-ui-rnative-visualization 0.1.17 → 0.1.18

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 (166) hide show
  1. package/dist/module/lib/Components/Axis/XAxis/XAxis.js +2 -2
  2. package/dist/module/lib/Components/Axis/XAxis/XAxis.js.map +1 -1
  3. package/dist/module/lib/Components/Axis/YAxis/YAxis.js +2 -2
  4. package/dist/module/lib/Components/Axis/YAxis/YAxis.js.map +1 -1
  5. package/dist/module/lib/Components/CartesianChart/CartesianChart.js +29 -22
  6. package/dist/module/lib/Components/CartesianChart/CartesianChart.js.map +1 -1
  7. package/dist/module/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.js +61 -0
  8. package/dist/module/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.js.map +1 -0
  9. package/dist/module/lib/Components/CartesianChart/ChartEmptyLabel/index.js +4 -0
  10. package/dist/module/lib/Components/CartesianChart/ChartEmptyLabel/index.js.map +1 -0
  11. package/dist/module/lib/Components/CartesianChart/RevealClip/RevealClipDefs.js +3 -4
  12. package/dist/module/lib/Components/CartesianChart/RevealClip/RevealClipDefs.js.map +1 -1
  13. package/dist/module/lib/Components/CartesianChart/hooks/useDataFingerprint.js +13 -0
  14. package/dist/module/lib/Components/CartesianChart/hooks/useDataFingerprint.js.map +1 -0
  15. package/dist/module/lib/Components/CartesianChart/{RevealClip/utils.js → hooks/useRevealClipAnimation.js} +1 -6
  16. package/dist/module/lib/Components/CartesianChart/hooks/useRevealClipAnimation.js.map +1 -0
  17. package/dist/module/lib/Components/CartesianChart/hooks/useShimmerAnimation.js +37 -0
  18. package/dist/module/lib/Components/CartesianChart/hooks/useShimmerAnimation.js.map +1 -0
  19. package/dist/module/lib/Components/Line/Line.js +13 -8
  20. package/dist/module/lib/Components/Line/Line.js.map +1 -1
  21. package/dist/module/lib/Components/Line/constants.js +5 -0
  22. package/dist/module/lib/Components/Line/constants.js.map +1 -0
  23. package/dist/module/lib/Components/Line/types.js +2 -0
  24. package/dist/module/lib/Components/Line/utils.js +24 -7
  25. package/dist/module/lib/Components/Line/utils.js.map +1 -1
  26. package/dist/module/lib/Components/Line/utils.test.js +27 -1
  27. package/dist/module/lib/Components/Line/utils.test.js.map +1 -1
  28. package/dist/module/lib/Components/LineChart/LineChart.js +116 -27
  29. package/dist/module/lib/Components/LineChart/LineChart.js.map +1 -1
  30. package/dist/module/lib/Components/LineChart/LineChart.test.js +78 -0
  31. package/dist/module/lib/Components/LineChart/LineChart.test.js.map +1 -1
  32. package/dist/module/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.js +72 -0
  33. package/dist/module/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.js.map +1 -0
  34. package/dist/module/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.test.js +47 -0
  35. package/dist/module/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.test.js.map +1 -0
  36. package/dist/module/lib/Components/LineChart/LineChartEmptyState/index.js +4 -0
  37. package/dist/module/lib/Components/LineChart/LineChartEmptyState/index.js.map +1 -0
  38. package/dist/module/lib/Components/LineChart/LineChartEmptyState/types.js +4 -0
  39. package/dist/module/lib/Components/LineChart/LineChartEmptyState/types.js.map +1 -0
  40. package/dist/module/lib/Components/LineChart/LineChartEmptyState/utils.js +22 -0
  41. package/dist/module/lib/Components/LineChart/LineChartEmptyState/utils.js.map +1 -0
  42. package/dist/module/lib/Components/LineChart/LineChartEmptyState/utils.test.js +21 -0
  43. package/dist/module/lib/Components/LineChart/LineChartEmptyState/utils.test.js.map +1 -0
  44. package/dist/module/lib/Components/LineChart/utils.js +83 -0
  45. package/dist/module/lib/Components/LineChart/utils.js.map +1 -0
  46. package/dist/module/lib/Components/LineChart/utils.test.js +174 -0
  47. package/dist/module/lib/Components/LineChart/utils.test.js.map +1 -0
  48. package/dist/module/lib/Components/ReferenceLine/ReferenceLine.js +4 -4
  49. package/dist/module/lib/Components/ReferenceLine/ReferenceLine.js.map +1 -1
  50. package/dist/module/lib/Components/ReferenceLine/constants.js +2 -2
  51. package/dist/module/lib/Components/ReferenceLine/constants.js.map +1 -1
  52. package/dist/module/lib/Components/ReferenceLine/utils.js +2 -1
  53. package/dist/module/lib/Components/ReferenceLine/utils.js.map +1 -1
  54. package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/utils.js +2 -1
  55. package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/utils.js.map +1 -1
  56. package/dist/module/lib/Components/Scrubber/Scrubber.js +2 -2
  57. package/dist/module/lib/Components/Scrubber/Scrubber.js.map +1 -1
  58. package/dist/module/lib/Components/Scrubber/ScrubberProvider.js +2 -1
  59. package/dist/module/lib/Components/Scrubber/ScrubberProvider.js.map +1 -1
  60. package/dist/module/lib/Components/Scrubber/utils.js +3 -2
  61. package/dist/module/lib/Components/Scrubber/utils.js.map +1 -1
  62. package/dist/module/lib/utils/numbers.js +16 -0
  63. package/dist/module/lib/utils/numbers.js.map +1 -0
  64. package/dist/module/lib/utils/ticks/ticks.js +0 -16
  65. package/dist/module/lib/utils/ticks/ticks.js.map +1 -1
  66. package/dist/typescript/src/lib/Components/Axis/XAxis/XAxis.d.ts.map +1 -1
  67. package/dist/typescript/src/lib/Components/Axis/YAxis/YAxis.d.ts.map +1 -1
  68. package/dist/typescript/src/lib/Components/CartesianChart/CartesianChart.d.ts +1 -1
  69. package/dist/typescript/src/lib/Components/CartesianChart/CartesianChart.d.ts.map +1 -1
  70. package/dist/typescript/src/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.d.ts +18 -0
  71. package/dist/typescript/src/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.d.ts.map +1 -0
  72. package/dist/typescript/src/lib/Components/CartesianChart/ChartEmptyLabel/index.d.ts +2 -0
  73. package/dist/typescript/src/lib/Components/CartesianChart/ChartEmptyLabel/index.d.ts.map +1 -0
  74. package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/RevealClipDefs.d.ts.map +1 -1
  75. package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/types.d.ts +1 -1
  76. package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/types.d.ts.map +1 -1
  77. package/dist/typescript/src/lib/Components/CartesianChart/hooks/useDataFingerprint.d.ts +9 -0
  78. package/dist/typescript/src/lib/Components/CartesianChart/hooks/useDataFingerprint.d.ts.map +1 -0
  79. package/dist/typescript/src/lib/Components/CartesianChart/{RevealClip/utils.d.ts → hooks/useRevealClipAnimation.d.ts} +2 -5
  80. package/dist/typescript/src/lib/Components/CartesianChart/hooks/useRevealClipAnimation.d.ts.map +1 -0
  81. package/dist/typescript/src/lib/Components/CartesianChart/hooks/useShimmerAnimation.d.ts +13 -0
  82. package/dist/typescript/src/lib/Components/CartesianChart/hooks/useShimmerAnimation.d.ts.map +1 -0
  83. package/dist/typescript/src/lib/Components/CartesianChart/types.d.ts +12 -0
  84. package/dist/typescript/src/lib/Components/CartesianChart/types.d.ts.map +1 -1
  85. package/dist/typescript/src/lib/Components/Line/Line.d.ts +1 -1
  86. package/dist/typescript/src/lib/Components/Line/Line.d.ts.map +1 -1
  87. package/dist/typescript/src/lib/Components/Line/constants.d.ts +3 -0
  88. package/dist/typescript/src/lib/Components/Line/constants.d.ts.map +1 -0
  89. package/dist/typescript/src/lib/Components/Line/index.d.ts +1 -1
  90. package/dist/typescript/src/lib/Components/Line/index.d.ts.map +1 -1
  91. package/dist/typescript/src/lib/Components/Line/types.d.ts +8 -0
  92. package/dist/typescript/src/lib/Components/Line/types.d.ts.map +1 -1
  93. package/dist/typescript/src/lib/Components/Line/utils.d.ts +5 -4
  94. package/dist/typescript/src/lib/Components/Line/utils.d.ts.map +1 -1
  95. package/dist/typescript/src/lib/Components/LineChart/LineChart.d.ts +1 -1
  96. package/dist/typescript/src/lib/Components/LineChart/LineChart.d.ts.map +1 -1
  97. package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.d.ts +9 -0
  98. package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.d.ts.map +1 -0
  99. package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/index.d.ts +3 -0
  100. package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/index.d.ts.map +1 -0
  101. package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/types.d.ts +3 -0
  102. package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/types.d.ts.map +1 -0
  103. package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/utils.d.ts +14 -0
  104. package/dist/typescript/src/lib/Components/LineChart/LineChartEmptyState/utils.d.ts.map +1 -0
  105. package/dist/typescript/src/lib/Components/LineChart/types.d.ts +29 -1
  106. package/dist/typescript/src/lib/Components/LineChart/types.d.ts.map +1 -1
  107. package/dist/typescript/src/lib/Components/LineChart/utils.d.ts +43 -0
  108. package/dist/typescript/src/lib/Components/LineChart/utils.d.ts.map +1 -0
  109. package/dist/typescript/src/lib/Components/ReferenceLine/ReferenceLine.d.ts.map +1 -1
  110. package/dist/typescript/src/lib/Components/ReferenceLine/constants.d.ts +2 -2
  111. package/dist/typescript/src/lib/Components/ReferenceLine/constants.d.ts.map +1 -1
  112. package/dist/typescript/src/lib/Components/ReferenceLine/utils.d.ts.map +1 -1
  113. package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/utils.d.ts.map +1 -1
  114. package/dist/typescript/src/lib/Components/Scrubber/Scrubber.d.ts.map +1 -1
  115. package/dist/typescript/src/lib/Components/Scrubber/ScrubberProvider.d.ts.map +1 -1
  116. package/dist/typescript/src/lib/Components/Scrubber/utils.d.ts.map +1 -1
  117. package/dist/typescript/src/lib/utils/index.d.ts +1 -1
  118. package/dist/typescript/src/lib/utils/index.d.ts.map +1 -1
  119. package/dist/typescript/src/lib/utils/numbers.d.ts +13 -0
  120. package/dist/typescript/src/lib/utils/numbers.d.ts.map +1 -0
  121. package/dist/typescript/src/lib/utils/ticks/ticks.d.ts +1 -11
  122. package/dist/typescript/src/lib/utils/ticks/ticks.d.ts.map +1 -1
  123. package/dist/typescript/src/lib/utils/types.d.ts +20 -2
  124. package/dist/typescript/src/lib/utils/types.d.ts.map +1 -1
  125. package/package.json +3 -3
  126. package/src/lib/Components/Axis/XAxis/XAxis.tsx +13 -18
  127. package/src/lib/Components/Axis/YAxis/YAxis.tsx +13 -18
  128. package/src/lib/Components/CartesianChart/CartesianChart.tsx +29 -23
  129. package/src/lib/Components/CartesianChart/ChartEmptyLabel/ChartEmptyLabel.tsx +68 -0
  130. package/src/lib/Components/CartesianChart/ChartEmptyLabel/index.ts +1 -0
  131. package/src/lib/Components/CartesianChart/RevealClip/RevealClipDefs.tsx +3 -2
  132. package/src/lib/Components/CartesianChart/RevealClip/types.ts +1 -1
  133. package/src/lib/Components/CartesianChart/hooks/useDataFingerprint.ts +16 -0
  134. package/src/lib/Components/CartesianChart/{RevealClip/utils.ts → hooks/useRevealClipAnimation.ts} +1 -9
  135. package/src/lib/Components/CartesianChart/hooks/useShimmerAnimation.ts +52 -0
  136. package/src/lib/Components/CartesianChart/types.ts +12 -0
  137. package/src/lib/Components/Line/Line.tsx +13 -10
  138. package/src/lib/Components/Line/constants.ts +2 -0
  139. package/src/lib/Components/Line/index.ts +1 -1
  140. package/src/lib/Components/Line/types.ts +10 -0
  141. package/src/lib/Components/Line/utils.test.ts +41 -1
  142. package/src/lib/Components/Line/utils.ts +42 -6
  143. package/src/lib/Components/LineChart/LineChart.test.tsx +64 -0
  144. package/src/lib/Components/LineChart/LineChart.tsx +139 -38
  145. package/src/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.test.tsx +39 -0
  146. package/src/lib/Components/LineChart/LineChartEmptyState/LineChartEmptyState.tsx +72 -0
  147. package/src/lib/Components/LineChart/LineChartEmptyState/index.ts +2 -0
  148. package/src/lib/Components/LineChart/LineChartEmptyState/types.ts +3 -0
  149. package/src/lib/Components/LineChart/LineChartEmptyState/utils.test.ts +22 -0
  150. package/src/lib/Components/LineChart/LineChartEmptyState/utils.ts +24 -0
  151. package/src/lib/Components/LineChart/types.ts +35 -1
  152. package/src/lib/Components/LineChart/utils.test.ts +196 -0
  153. package/src/lib/Components/LineChart/utils.ts +107 -0
  154. package/src/lib/Components/ReferenceLine/ReferenceLine.tsx +8 -4
  155. package/src/lib/Components/ReferenceLine/constants.ts +2 -2
  156. package/src/lib/Components/ReferenceLine/utils.ts +2 -1
  157. package/src/lib/Components/Scrubber/DefaultScrubberTooltip/utils.ts +2 -1
  158. package/src/lib/Components/Scrubber/Scrubber.tsx +13 -2
  159. package/src/lib/Components/Scrubber/ScrubberProvider.tsx +2 -1
  160. package/src/lib/Components/Scrubber/utils.ts +3 -5
  161. package/src/lib/utils/index.ts +1 -0
  162. package/src/lib/utils/numbers.ts +15 -0
  163. package/src/lib/utils/ticks/ticks.ts +1 -23
  164. package/src/lib/utils/types.ts +28 -2
  165. package/dist/module/lib/Components/CartesianChart/RevealClip/utils.js.map +0 -1
  166. package/dist/typescript/src/lib/Components/CartesianChart/RevealClip/utils.d.ts.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import type { BaseAxisProps } from '../../Components/Axis';
2
- import type { ChartScaleFunction, DrawingArea } from '../types';
2
+ import type { ChartScaleFunction } from '../types';
3
3
  export declare const APPROXIMATE_TICK_COUNT = 5;
4
4
  export type TickData = {
5
5
  position: number;
@@ -32,14 +32,4 @@ export declare const getTickLabel: (tick: number, axisData: BaseAxisProps["data"
32
32
  * Builds the complete tick data array from a scale and axis configuration.
33
33
  */
34
34
  export declare const buildTicksData: (scale: ChartScaleFunction, axisConfig?: BaseAxisProps, explicitTicks?: number[], formatter?: (value: number | string) => string) => TickData[];
35
- /**
36
- * Excludes the X grid line at the Y-axis origin (left edge)
37
- * to prevent overlap with the Y-axis solid line.
38
- */
39
- export declare const isTickOnXAxisDomainEdge: (tick: TickData, drawingArea: DrawingArea) => boolean;
40
- /**
41
- * Excludes the Y grid line at the X-axis origin (bottom edge)
42
- * to prevent overlap with the X-axis solid line.
43
- */
44
- export declare const isTickOnYAxisDomainEdge: (tick: TickData, drawingArea: DrawingArea) => boolean;
45
35
  //# sourceMappingURL=ticks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ticks.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/utils/ticks/ticks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEhE,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,kBAAkB,EACzB,gBAAgB,MAAM,EAAE,EACxB,WAAW,aAAa,CAAC,MAAM,CAAC,KAC/B,MAAM,EAUR,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,kBAAkB,EACzB,MAAM,MAAM,KACX,MAKF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,MAAM,EACZ,UAAU,aAAa,CAAC,MAAM,CAAC,EAC/B,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,MAAM,KAC7C,MAeF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GACzB,OAAO,kBAAkB,EACzB,aAAa,aAAa,EAC1B,gBAAgB,MAAM,EAAE,EACxB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,MAAM,KAC7C,QAAQ,EASV,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,QAAQ,EACd,aAAa,WAAW,KACvB,OAEF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,QAAQ,EACd,aAAa,WAAW,KACvB,OAEF,CAAC"}
1
+ {"version":3,"file":"ticks.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/utils/ticks/ticks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,kBAAkB,EACzB,gBAAgB,MAAM,EAAE,EACxB,WAAW,aAAa,CAAC,MAAM,CAAC,KAC/B,MAAM,EAUR,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,kBAAkB,EACzB,MAAM,MAAM,KACX,MAKF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,MAAM,EACZ,UAAU,aAAa,CAAC,MAAM,CAAC,EAC/B,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,MAAM,KAC7C,MAeF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GACzB,OAAO,kBAAkB,EACzB,aAAa,aAAa,EAC1B,gBAAgB,MAAM,EAAE,EACxB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,MAAM,KAC7C,QAAQ,EASV,CAAC"}
@@ -15,6 +15,18 @@ export type DrawingArea = {
15
15
  width: number;
16
16
  height: number;
17
17
  };
18
+ /**
19
+ * Interpolation used to draw a line (and its area) between data points.
20
+ * Each value maps to a [d3-shape](https://d3js.org/d3-shape/curve) curve:
21
+ * - `'bump'` — smooth cubic curve with horizontal tangents (`curveBumpX`).
22
+ * - `'natural'` — natural cubic spline through every point (`curveNatural`).
23
+ * - `'monotone'` — smooth curve that preserves monotonicity (`curveMonotoneX`).
24
+ * - `'linear'` — straight segments between points (`curveLinear`).
25
+ * - `'step'` — stepped, piecewise-constant line (`curveStep`).
26
+ * - `'stepAfter'` — stepped line where changes occur after the x-coordinate (`curveStepAfter`).
27
+ * - `'stepBefore'` — stepped line where changes occur before the x-coordinate (`curveStepBefore`).
28
+ */
29
+ export type CurveType = 'bump' | 'natural' | 'monotone' | 'linear' | 'step' | 'stepAfter' | 'stepBefore';
18
30
  export type Series = {
19
31
  /**
20
32
  * Unique identifier for the series.
@@ -29,9 +41,15 @@ export type Series = {
29
41
  */
30
42
  label?: string;
31
43
  /**
32
- * CSS color applied to the series line/mark.
44
+ * Color applied to the series line/mark.
45
+ * @default border-muted
46
+ */
47
+ stroke?: string;
48
+ /**
49
+ * Interpolation used to draw the line between data points.
50
+ * @default 'bump'
33
51
  */
34
- stroke: string;
52
+ curve?: CurveType;
35
53
  };
36
54
  export type NumericScale = ScaleLinear<number, number> | ScaleLogarithmic<number, number>;
37
55
  export type CategoricalScale = ScaleBand<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/lib/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IACzB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErC,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAEjE,MAAM,MAAM,0BAA0B,GAAG;IACvC;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;OAEG;IACH,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;OAEG;IACH,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IAC3D;;OAEG;IACH,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IAC3D;;OAEG;IACH,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC3D;;OAEG;IACH,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC3D;;OAEG;IACH,WAAW,EAAE,WAAW,CAAC;IACzB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/lib/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,SAAS,GACT,UAAU,GACV,QAAQ,GACR,MAAM,GACN,WAAW,GACX,YAAY,CAAC;AAEjB,MAAM,MAAM,MAAM,GAAG;IACnB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IACzB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErC,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAEjE,MAAM,MAAM,0BAA0B,GAAG;IACvC;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;OAEG;IACH,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;OAEG;IACH,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IAC3D;;OAEG;IACH,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IAC3D;;OAEG;IACH,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC3D;;OAEG;IACH,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC3D;;OAEG;IACH,WAAW,EAAE,WAAW,CAAC;IACzB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/lumen-ui-rnative-visualization",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "keywords": [
@@ -44,8 +44,8 @@
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@types/react": "^19.0.0",
47
- "@ledgerhq/lumen-design-core": "0.1.16",
48
- "@ledgerhq/lumen-ui-rnative": "0.1.40",
47
+ "@ledgerhq/lumen-design-core": "0.1.17",
48
+ "@ledgerhq/lumen-ui-rnative": "0.1.41",
49
49
  "react": "^19.0.0",
50
50
  "react-native": "~0.79.7",
51
51
  "react-native-svg": "^15.0.0",
@@ -2,10 +2,7 @@ import { useTheme } from '@ledgerhq/lumen-ui-rnative';
2
2
  import { useMemo } from 'react';
3
3
  import { G, Line as SvgLine, Text as SvgText } from 'react-native-svg';
4
4
 
5
- import {
6
- buildTicksData,
7
- isTickOnXAxisDomainEdge,
8
- } from '../../../utils/ticks/ticks';
5
+ import { buildTicksData } from '../../../utils/ticks/ticks';
9
6
  import { useCartesianChartContext } from '../../CartesianChart/context';
10
7
 
11
8
  import type { XAxisProps } from './types';
@@ -57,20 +54,18 @@ export const XAxis = ({
57
54
  return (
58
55
  <G>
59
56
  {showGrid &&
60
- ticksData
61
- .filter((tick) => isTickOnXAxisDomainEdge(tick, drawingArea))
62
- .map((tick, i) => (
63
- <SvgLine
64
- key={`grid-${tick.value}-${i}`}
65
- x1={tick.position}
66
- y1={drawingArea.y}
67
- x2={tick.position}
68
- y2={drawingArea.y + drawingArea.height}
69
- stroke={gridStroke}
70
- strokeWidth={STROKE_WIDTH}
71
- strokeDasharray={gridLineStyle === 'dashed' ? '3 3' : undefined}
72
- />
73
- ))}
57
+ ticksData.map((tick, i) => (
58
+ <SvgLine
59
+ key={`grid-${tick.value}-${i}`}
60
+ x1={tick.position}
61
+ y1={drawingArea.y}
62
+ x2={tick.position}
63
+ y2={drawingArea.y + drawingArea.height}
64
+ stroke={gridStroke}
65
+ strokeWidth={STROKE_WIDTH}
66
+ strokeDasharray={gridLineStyle === 'dashed' ? '3 3' : undefined}
67
+ />
68
+ ))}
74
69
 
75
70
  {showLine && (
76
71
  <SvgLine
@@ -2,10 +2,7 @@ import { useTheme } from '@ledgerhq/lumen-ui-rnative';
2
2
  import { useMemo } from 'react';
3
3
  import { G, Line as SvgLine, Text as SvgText } from 'react-native-svg';
4
4
 
5
- import {
6
- buildTicksData,
7
- isTickOnYAxisDomainEdge,
8
- } from '../../../utils/ticks/ticks';
5
+ import { buildTicksData } from '../../../utils/ticks/ticks';
9
6
  import { useCartesianChartContext } from '../../CartesianChart/context';
10
7
 
11
8
  import type { YAxisProps } from './types';
@@ -56,20 +53,18 @@ export const YAxis = ({
56
53
  return (
57
54
  <G>
58
55
  {showGrid &&
59
- ticksData
60
- .filter((tick) => isTickOnYAxisDomainEdge(tick, drawingArea))
61
- .map((tick, i) => (
62
- <SvgLine
63
- key={`grid-${tick.value}-${i}`}
64
- x1={drawingArea.x}
65
- y1={tick.position}
66
- x2={drawingArea.x + drawingArea.width}
67
- y2={tick.position}
68
- stroke={gridStroke}
69
- strokeWidth={STROKE_WIDTH}
70
- strokeDasharray={gridLineStyle === 'dashed' ? '3 3' : undefined}
71
- />
72
- ))}
56
+ ticksData.map((tick, i) => (
57
+ <SvgLine
58
+ key={`grid-${tick.value}-${i}`}
59
+ x1={drawingArea.x}
60
+ y1={tick.position}
61
+ x2={drawingArea.x + drawingArea.width}
62
+ y2={tick.position}
63
+ stroke={gridStroke}
64
+ strokeWidth={STROKE_WIDTH}
65
+ strokeDasharray={gridLineStyle === 'dashed' ? '3 3' : undefined}
66
+ />
67
+ ))}
73
68
 
74
69
  {showLine && (
75
70
  <SvgLine
@@ -24,6 +24,8 @@ export function CartesianChart({
24
24
  inset,
25
25
  axisPadding,
26
26
  ariaLabel = 'Chart',
27
+ ariaBusy = false,
28
+ overlay,
27
29
  children,
28
30
  enableScrubbing = false,
29
31
  onScrubberPositionChange,
@@ -75,6 +77,7 @@ export function CartesianChart({
75
77
  onLayout={needsMeasurement ? handleLayout : undefined}
76
78
  accessibilityRole='image'
77
79
  accessibilityLabel={ariaLabel}
80
+ accessibilityState={{ busy: ariaBusy }}
78
81
  style={{
79
82
  width: needsMeasurement ? undefined : resolvedWidth,
80
83
  height,
@@ -82,33 +85,36 @@ export function CartesianChart({
82
85
  }}
83
86
  >
84
87
  {resolvedWidth > 0 && (
85
- <CartesianChartProvider value={contextValue}>
86
- <MagneticPointsProvider>
87
- <ScrubberProvider
88
- width={svgWidth}
89
- height={svgHeight}
90
- enableScrubbing={enableScrubbing}
91
- onScrubberPositionChange={onScrubberPositionChange}
92
- style={OVERFLOW_OFFSET}
93
- magnetRadius={magnetRadius}
94
- >
95
- <Svg
96
- testID='chart-svg'
88
+ <>
89
+ <CartesianChartProvider value={contextValue}>
90
+ <MagneticPointsProvider>
91
+ <ScrubberProvider
97
92
  width={svgWidth}
98
93
  height={svgHeight}
99
- style={{ overflow: 'visible' }}
94
+ enableScrubbing={enableScrubbing}
95
+ onScrubberPositionChange={onScrubberPositionChange}
96
+ style={OVERFLOW_OFFSET}
97
+ magnetRadius={magnetRadius}
100
98
  >
101
- <RevealClipDefs
102
- drawingArea={contextValue.drawingArea}
103
- series={series}
104
- animate={animate}
99
+ <Svg
100
+ testID='chart-svg'
101
+ width={svgWidth}
102
+ height={svgHeight}
103
+ style={{ overflow: 'visible' }}
105
104
  >
106
- {children}
107
- </RevealClipDefs>
108
- </Svg>
109
- </ScrubberProvider>
110
- </MagneticPointsProvider>
111
- </CartesianChartProvider>
105
+ <RevealClipDefs
106
+ drawingArea={contextValue.drawingArea}
107
+ series={series}
108
+ animate={animate}
109
+ >
110
+ {children}
111
+ </RevealClipDefs>
112
+ </Svg>
113
+ </ScrubberProvider>
114
+ </MagneticPointsProvider>
115
+ </CartesianChartProvider>
116
+ {overlay}
117
+ </>
112
118
  )}
113
119
  </View>
114
120
  );
@@ -0,0 +1,68 @@
1
+ import { Text, useStyleSheet } from '@ledgerhq/lumen-ui-rnative';
2
+ import type { ReactNode } from 'react';
3
+ import { View } from 'react-native';
4
+
5
+ type ChartEmptyLabelProps = {
6
+ children: ReactNode;
7
+ };
8
+
9
+ const useStyles = () => {
10
+ return useStyleSheet(
11
+ (t) => ({
12
+ container: {
13
+ position: 'absolute',
14
+ top: 0,
15
+ left: 0,
16
+ right: 0,
17
+ bottom: 0,
18
+ alignItems: 'center',
19
+ justifyContent: 'center',
20
+ },
21
+ pill: {
22
+ backgroundColor: t.colors.bg.muted,
23
+ borderRadius: t.borderRadius.xs,
24
+ paddingHorizontal: t.spacings.s12,
25
+ paddingVertical: t.spacings.s6,
26
+ },
27
+ label: {
28
+ color: t.colors.text.muted,
29
+ ...t.typographies.body3,
30
+ },
31
+ }),
32
+ [],
33
+ );
34
+ };
35
+
36
+ /**
37
+ * Centered overlay label shown when a chart has no data (and is not loading).
38
+ * Rendered through the `overlay` slot of `CartesianChart` so it shares the
39
+ * chart's positioned container and aligns with the chart footprint. Shared
40
+ * across cartesian charts (LineChart, future BarChart).
41
+ *
42
+ * This is the lib's only non-SVG (View/Text) element, so unlike the chart
43
+ * visuals (which read raw theme colors for `react-native-svg`) it is styled with
44
+ * the design system's themed stylesheet, consistent with the components in
45
+ * `ui-rnative`.
46
+ */
47
+ export function ChartEmptyLabel({ children }: Readonly<ChartEmptyLabelProps>) {
48
+ const styles = useStyles();
49
+
50
+ return (
51
+ <View
52
+ pointerEvents='none'
53
+ accessibilityElementsHidden={true}
54
+ importantForAccessibility='no-hide-descendants'
55
+ style={styles.container}
56
+ >
57
+ <View style={styles.pill}>
58
+ <Text
59
+ testID='chart-empty-label'
60
+ style={styles.label}
61
+ accessible={false}
62
+ >
63
+ {children}
64
+ </Text>
65
+ </View>
66
+ </View>
67
+ );
68
+ }
@@ -0,0 +1 @@
1
+ export { ChartEmptyLabel } from './ChartEmptyLabel';
@@ -4,11 +4,12 @@ import { useMemo } from 'react';
4
4
  import Animated from 'react-native-reanimated';
5
5
  import { ClipPath, Defs, Rect } from 'react-native-svg';
6
6
 
7
+ import { useDataFingerprint } from '../hooks/useDataFingerprint';
8
+ import { useRevealClipAnimation } from '../hooks/useRevealClipAnimation';
7
9
  import { OVERFLOW_BUFFER } from '../utils';
8
10
 
9
11
  import { RevealClipContext } from './context';
10
12
  import type { RevealClipDefsProps } from './types';
11
- import { useComputeDataFingerprint, useRevealClipAnimation } from './utils';
12
13
 
13
14
  const DEFAULT_DURATION_IN_SECONDS = 0.8;
14
15
 
@@ -29,7 +30,7 @@ export function RevealClipDefs({
29
30
  const durationMs =
30
31
  (transitions?.enter?.duration ?? DEFAULT_DURATION_IN_SECONDS) * 1000;
31
32
 
32
- const dataFingerprint = useComputeDataFingerprint({ series });
33
+ const dataFingerprint = useDataFingerprint(series);
33
34
  const { clipId, animatedRectProps } = useRevealClipAnimation({
34
35
  durationMs,
35
36
  drawingArea,
@@ -1,6 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
2
 
3
- import type { DrawingArea, Series } from '../../../utils';
3
+ import type { DrawingArea, Series } from '../../../utils/types';
4
4
 
5
5
  export type EnterTransitionConfig = {
6
6
  /**
@@ -0,0 +1,16 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import type { Series } from '../../../utils/types';
4
+
5
+ /**
6
+ * Stable signature of every series' data points, memoized on the `series`
7
+ * reference. Used to key the reveal-clip provider so the reveal animation only
8
+ * replays when the underlying data actually changes — not on unrelated
9
+ * re-renders such as scrubbing or hover.
10
+ */
11
+ export const useDataFingerprint = (series: Series[]): string => {
12
+ return useMemo(
13
+ () => series.map((s) => s.data?.join(',') ?? '').join('|'),
14
+ [series],
15
+ );
16
+ };
@@ -5,7 +5,7 @@ import {
5
5
  withTiming,
6
6
  } from 'react-native-reanimated';
7
7
 
8
- import type { DrawingArea, Series } from '../../../utils/types';
8
+ import type { DrawingArea } from '../../../utils/types';
9
9
  import { OVERFLOW_BUFFER } from '../utils';
10
10
 
11
11
  type RevealClipAnimationConfig = {
@@ -41,11 +41,3 @@ export const useRevealClipAnimation = ({
41
41
 
42
42
  return { clipId, animatedRectProps };
43
43
  };
44
-
45
- export const useComputeDataFingerprint = ({
46
- series,
47
- }: {
48
- series: Series[];
49
- }): string => {
50
- return series.map((s) => s.data?.join(',') ?? '').join('|');
51
- };
@@ -0,0 +1,52 @@
1
+ import { useEffect } from 'react';
2
+ import {
3
+ cancelAnimation,
4
+ Easing,
5
+ useAnimatedProps,
6
+ useReducedMotion,
7
+ useSharedValue,
8
+ withRepeat,
9
+ withTiming,
10
+ } from 'react-native-reanimated';
11
+
12
+ const HALF_PULSE_DURATION_IN_MS = 1000;
13
+ const MIN_OPACITY = 0.5;
14
+
15
+ type ShimmerAnimationResult = {
16
+ animatedProps: ReturnType<typeof useAnimatedProps>;
17
+ };
18
+
19
+ /**
20
+ * Self-contained shimmer (opacity pulse) for SVG content, the RN counterpart of
21
+ * the web's CSS-keyframe shimmer. Shared by the initial loading placeholder and
22
+ * the transition-loading line. Honors the user's reduced-motion preference by
23
+ * keeping the content fully opaque.
24
+ */
25
+ export const useShimmerAnimation = (animate = true): ShimmerAnimationResult => {
26
+ const opacity = useSharedValue(1);
27
+ const reducedMotion = useReducedMotion();
28
+
29
+ useEffect(() => {
30
+ if (animate && !reducedMotion) {
31
+ opacity.value = withRepeat(
32
+ withTiming(MIN_OPACITY, {
33
+ duration: HALF_PULSE_DURATION_IN_MS,
34
+ easing: Easing.inOut(Easing.ease),
35
+ }),
36
+ -1,
37
+ true,
38
+ );
39
+ } else {
40
+ cancelAnimation(opacity);
41
+ opacity.value = 1;
42
+ }
43
+
44
+ return () => {
45
+ cancelAnimation(opacity);
46
+ };
47
+ }, [animate, reducedMotion, opacity]);
48
+
49
+ const animatedProps = useAnimatedProps(() => ({ opacity: opacity.value }));
50
+
51
+ return { animatedProps };
52
+ };
@@ -43,6 +43,18 @@ export type CartesianChartProps = {
43
43
  * @default 'Chart'
44
44
  */
45
45
  ariaLabel?: string;
46
+ /**
47
+ * Marks the chart as busy for assistive technologies (via the container's
48
+ * accessibility state) to signal that its content is loading.
49
+ * @default false
50
+ */
51
+ ariaBusy?: boolean;
52
+ /**
53
+ * Content rendered as an absolutely-positioned overlay above the chart SVG,
54
+ * within the same positioned container (so it aligns with the chart
55
+ * footprint). Used for e.g. an empty-state label.
56
+ */
57
+ overlay?: ReactNode;
46
58
  /**
47
59
  * SVG content rendered inside the chart's context provider.
48
60
  */
@@ -1,3 +1,4 @@
1
+ import { useTheme } from '@ledgerhq/lumen-ui-rnative';
1
2
  import { useId, useMemo } from 'react';
2
3
  import { Defs, G, LinearGradient, Path, Stop } from 'react-native-svg';
3
4
 
@@ -5,17 +6,16 @@ import { isNumericScale } from '../../utils/scales/scales';
5
6
  import { useCartesianChartContext } from '../CartesianChart/context';
6
7
  import { useRevealClip } from '../CartesianChart/RevealClip';
7
8
 
9
+ import { LINE_AREA_GRADIENT_OPACITY, LINE_STROKE_WIDTH } from './constants';
8
10
  import type { LineProps } from './types';
9
11
  import { buildAreaPath, buildLinePath, toScaledPoints } from './utils';
10
12
 
11
- const STROKE_WIDTH = 2;
12
- const AREA_GRADIENT_OPACITY = 0.2;
13
-
14
13
  export const Line = ({
15
14
  seriesId,
16
15
  stroke,
17
16
  showArea = false,
18
17
  areaType: _areaType = 'gradient',
18
+ curve,
19
19
  }: LineProps) => {
20
20
  const { getXScale, getYScale, getXAxisConfig, drawingArea, seriesMap } =
21
21
  useCartesianChartContext();
@@ -25,9 +25,12 @@ export const Line = ({
25
25
  const yScale = getYScale();
26
26
  const xAxisConfig = getXAxisConfig();
27
27
 
28
+ const { theme } = useTheme();
28
29
  const gradientId = useId();
29
30
  const seriesData = seriesMap.get(seriesId);
30
- const resolvedStroke = stroke ?? seriesData?.stroke;
31
+ const resolvedStroke =
32
+ stroke ?? seriesData?.stroke ?? theme.colors.border.muted;
33
+ const resolvedCurve = curve ?? seriesData?.curve;
31
34
 
32
35
  const points = useMemo(
33
36
  () =>
@@ -38,16 +41,16 @@ export const Line = ({
38
41
  );
39
42
 
40
43
  const linePath = useMemo(
41
- () => (points ? buildLinePath(points) : null),
42
- [points],
44
+ () => (points ? buildLinePath(points, resolvedCurve) : null),
45
+ [points, resolvedCurve],
43
46
  );
44
47
 
45
48
  const areaPath = useMemo(
46
49
  () =>
47
50
  showArea && points && drawingArea
48
- ? buildAreaPath(points, drawingArea)
51
+ ? buildAreaPath(points, drawingArea, resolvedCurve)
49
52
  : null,
50
- [showArea, points, drawingArea],
53
+ [showArea, points, drawingArea, resolvedCurve],
51
54
  );
52
55
 
53
56
  if (!linePath) {
@@ -63,7 +66,7 @@ export const Line = ({
63
66
  <Stop
64
67
  offset='0%'
65
68
  stopColor={resolvedStroke}
66
- stopOpacity={AREA_GRADIENT_OPACITY}
69
+ stopOpacity={LINE_AREA_GRADIENT_OPACITY}
67
70
  />
68
71
  <Stop offset='100%' stopColor={resolvedStroke} stopOpacity={0} />
69
72
  </LinearGradient>
@@ -81,7 +84,7 @@ export const Line = ({
81
84
  d={linePath}
82
85
  fill='none'
83
86
  stroke={resolvedStroke}
84
- strokeWidth={STROKE_WIDTH}
87
+ strokeWidth={LINE_STROKE_WIDTH}
85
88
  strokeLinecap='round'
86
89
  strokeLinejoin='round'
87
90
  />
@@ -0,0 +1,2 @@
1
+ export const LINE_STROKE_WIDTH = 2;
2
+ export const LINE_AREA_GRADIENT_OPACITY = 0.25;
@@ -1,2 +1,2 @@
1
1
  export { Line } from './Line';
2
- export type { LineProps } from './types';
2
+ export type { CurveType, LineProps } from './types';
@@ -1,3 +1,7 @@
1
+ import type { CurveType } from '../../utils/types';
2
+
3
+ export type { CurveType };
4
+
1
5
  export type LineProps = {
2
6
  /**
3
7
  * The ID of the series to render.
@@ -20,4 +24,10 @@ export type LineProps = {
20
24
  * @default 'gradient'
21
25
  */
22
26
  areaType?: 'gradient';
27
+ /**
28
+ * Override interpolation used to draw the line between data points.
29
+ * When omitted, falls back to the `curve` defined on the series.
30
+ * @default 'bump'
31
+ */
32
+ curve?: CurveType;
23
33
  };
@@ -5,7 +5,7 @@ import {
5
5
  getNumericScale,
6
6
  } from '../../utils/scales/scales';
7
7
 
8
- import { toScaledPoints } from './utils';
8
+ import { buildLinePath, toScaledPoints } from './utils';
9
9
 
10
10
  const xScale = getNumericScale({
11
11
  scaleType: 'linear',
@@ -88,3 +88,43 @@ describe('toScaledPoints', () => {
88
88
  expect(toScaledPoints(data, xScale, yScale, xData)).toBeNull();
89
89
  });
90
90
  });
91
+
92
+ describe('buildLinePath', () => {
93
+ const points: [number, number][] = [
94
+ [0, 100],
95
+ [50, 20],
96
+ [100, 60],
97
+ ];
98
+
99
+ it('defaults to the bump curve (cubic beziers)', () => {
100
+ const path = buildLinePath(points);
101
+
102
+ expect(path).not.toBeNull();
103
+ expect(path).toContain('C');
104
+ });
105
+
106
+ it('draws straight segments for the linear curve', () => {
107
+ const path = buildLinePath(points, 'linear');
108
+
109
+ expect(path).toBe('M0,100L50,20L100,60');
110
+ });
111
+
112
+ it('uses cubic beziers for smooth curves', () => {
113
+ expect(buildLinePath(points, 'natural')).toContain('C');
114
+ expect(buildLinePath(points, 'monotone')).toContain('C');
115
+ });
116
+
117
+ it('draws orthogonal segments for the step curve', () => {
118
+ const path = buildLinePath(points, 'step');
119
+
120
+ expect(path).not.toBeNull();
121
+ expect(path).not.toContain('C');
122
+ expect(path).toBe('M0,100L25,100L25,20L75,20L75,60L100,60');
123
+ });
124
+
125
+ it('falls back to the default curve for unknown values', () => {
126
+ const path = buildLinePath(points, 'unknown' as never);
127
+
128
+ expect(path).toBe(buildLinePath(points));
129
+ });
130
+ });