@ledgerhq/lumen-ui-rnative-visualization 0.1.13 → 0.1.15
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/dist/module/lib/Components/Axis/Axis.constants.js +21 -0
- package/dist/module/lib/Components/Axis/Axis.constants.js.map +1 -0
- package/dist/module/lib/Components/Axis/index.js +5 -0
- package/dist/module/lib/Components/Axis/index.js.map +1 -0
- package/dist/module/lib/Components/CartesianChart/CartesianChart.js +34 -22
- package/dist/module/lib/Components/CartesianChart/CartesianChart.js.map +1 -1
- package/dist/module/lib/Components/CartesianChart/context/useBuildChartContext.js +5 -4
- package/dist/module/lib/Components/CartesianChart/context/useBuildChartContext.js.map +1 -1
- package/dist/module/lib/Components/CartesianChart/context/useBuildChartContext.test.js +54 -0
- package/dist/module/lib/Components/CartesianChart/context/useBuildChartContext.test.js.map +1 -1
- package/dist/module/lib/Components/CartesianChart/utils.js +18 -8
- package/dist/module/lib/Components/CartesianChart/utils.js.map +1 -1
- package/dist/module/lib/Components/Line/utils.js +6 -1
- package/dist/module/lib/Components/Line/utils.js.map +1 -1
- package/dist/module/lib/Components/Line/utils.test.js +88 -0
- package/dist/module/lib/Components/Line/utils.test.js.map +1 -0
- package/dist/module/lib/Components/LineChart/LineChart.js +19 -31
- package/dist/module/lib/Components/LineChart/LineChart.js.map +1 -1
- package/dist/module/lib/Components/LineChart/LineChart.stories.js +38 -0
- package/dist/module/lib/Components/LineChart/LineChart.stories.js.map +1 -1
- package/dist/module/lib/Components/LineChart/LineChart.test.js +192 -0
- package/dist/module/lib/Components/LineChart/LineChart.test.js.map +1 -1
- package/dist/module/lib/Components/Point/Point.js +8 -2
- package/dist/module/lib/Components/Point/Point.js.map +1 -1
- package/dist/module/lib/Components/Point/constants.js +9 -0
- package/dist/module/lib/Components/Point/constants.js.map +1 -0
- package/dist/module/lib/Components/Point/pointContext/MagneticPointsProvider.js +35 -0
- package/dist/module/lib/Components/Point/pointContext/MagneticPointsProvider.js.map +1 -0
- package/dist/module/lib/Components/Point/pointContext/MagneticPointsProvider.test.js +153 -0
- package/dist/module/lib/Components/Point/pointContext/MagneticPointsProvider.test.js.map +1 -0
- package/dist/module/lib/Components/Point/pointContext/index.js +5 -0
- package/dist/module/lib/Components/Point/pointContext/index.js.map +1 -0
- package/dist/module/lib/Components/Point/pointContext/magneticPointsContext.js +10 -0
- package/dist/module/lib/Components/Point/pointContext/magneticPointsContext.js.map +1 -0
- package/dist/module/lib/Components/Point/utils.js +26 -6
- package/dist/module/lib/Components/Point/utils.js.map +1 -1
- package/dist/module/lib/Components/Point/utils.test.js +84 -2
- package/dist/module/lib/Components/Point/utils.test.js.map +1 -1
- package/dist/module/lib/Components/ReferenceLine/utils.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/ChartTooltipItem.js +52 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/ChartTooltipItem.js.map +1 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/DefaultScrubberTooltip.js +81 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/DefaultScrubberTooltip.js.map +1 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/DefaultScrubberTooltip.test.js +340 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/DefaultScrubberTooltip.test.js.map +1 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/constants.js +12 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/constants.js.map +1 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/utils.js +166 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/utils.js.map +1 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/utils.test.js +253 -0
- package/dist/module/lib/Components/Scrubber/DefaultScrubberTooltip/utils.test.js.map +1 -0
- package/dist/module/lib/Components/Scrubber/Scrubber.js +40 -21
- package/dist/module/lib/Components/Scrubber/Scrubber.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/Scrubber.stories.js +80 -30
- package/dist/module/lib/Components/Scrubber/Scrubber.stories.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/Scrubber.test.js +10 -5
- package/dist/module/lib/Components/Scrubber/Scrubber.test.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/ScrubberProvider.js +81 -29
- package/dist/module/lib/Components/Scrubber/ScrubberProvider.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/utils.js +64 -0
- package/dist/module/lib/Components/Scrubber/utils.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/utils.test.js +128 -1
- package/dist/module/lib/Components/Scrubber/utils.test.js.map +1 -1
- package/dist/module/lib/utils/domain/domain.js.map +1 -1
- package/dist/module/lib/utils/scales/scales.js +13 -4
- package/dist/module/lib/utils/scales/scales.js.map +1 -1
- package/dist/module/lib/utils/scales/scales.test.js +29 -0
- package/dist/module/lib/utils/scales/scales.test.js.map +1 -1
- package/dist/module/lib/utils/ticks/ticks.js +13 -3
- package/dist/module/lib/utils/ticks/ticks.js.map +1 -1
- package/dist/module/lib/utils/ticks/ticks.test.js +34 -0
- package/dist/module/lib/utils/ticks/ticks.test.js.map +1 -1
- package/dist/typescript/src/lib/Components/Axis/Axis.constants.d.ts +5 -0
- package/dist/typescript/src/lib/Components/Axis/Axis.constants.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Axis/Axis.types.d.ts +39 -0
- package/dist/typescript/src/lib/Components/Axis/Axis.types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Axis/index.d.ts +3 -0
- package/dist/typescript/src/lib/Components/Axis/index.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/CartesianChart/CartesianChart.d.ts +1 -1
- package/dist/typescript/src/lib/Components/CartesianChart/CartesianChart.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/CartesianChart/context/useBuildChartContext.d.ts +5 -4
- package/dist/typescript/src/lib/Components/CartesianChart/context/useBuildChartContext.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/CartesianChart/types.d.ts +11 -3
- package/dist/typescript/src/lib/Components/CartesianChart/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/CartesianChart/utils.d.ts +18 -8
- package/dist/typescript/src/lib/Components/CartesianChart/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Line/utils.d.ts +4 -0
- package/dist/typescript/src/lib/Components/Line/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/LineChart/LineChart.d.ts +1 -1
- package/dist/typescript/src/lib/Components/LineChart/LineChart.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/LineChart/types.d.ts +10 -3
- package/dist/typescript/src/lib/Components/LineChart/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Point/Point.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Point/Point.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Point/constants.d.ts +7 -0
- package/dist/typescript/src/lib/Components/Point/constants.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Point/pointContext/MagneticPointsProvider.d.ts +7 -0
- package/dist/typescript/src/lib/Components/Point/pointContext/MagneticPointsProvider.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Point/pointContext/index.d.ts +3 -0
- package/dist/typescript/src/lib/Components/Point/pointContext/index.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Point/pointContext/magneticPointsContext.d.ts +13 -0
- package/dist/typescript/src/lib/Components/Point/pointContext/magneticPointsContext.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Point/types.d.ts +7 -0
- package/dist/typescript/src/lib/Components/Point/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Point/utils.d.ts +8 -6
- package/dist/typescript/src/lib/Components/Point/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/ReferenceLine/utils.d.ts +3 -2
- package/dist/typescript/src/lib/Components/ReferenceLine/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/ChartTooltipItem.d.ts +9 -0
- package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/ChartTooltipItem.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/DefaultScrubberTooltip.d.ts +12 -0
- package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/DefaultScrubberTooltip.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/constants.d.ts +10 -0
- package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/constants.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/utils.d.ts +69 -0
- package/dist/typescript/src/lib/Components/Scrubber/DefaultScrubberTooltip/utils.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Scrubber/Scrubber.d.ts +14 -2
- package/dist/typescript/src/lib/Components/Scrubber/Scrubber.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/ScrubberProvider.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/ScrubberProvider.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/index.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/index.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/types.d.ts +116 -4
- package/dist/typescript/src/lib/Components/Scrubber/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Scrubber/utils.d.ts +33 -3
- package/dist/typescript/src/lib/Components/Scrubber/utils.d.ts.map +1 -1
- package/dist/typescript/src/lib/utils/domain/domain.d.ts +5 -4
- package/dist/typescript/src/lib/utils/domain/domain.d.ts.map +1 -1
- package/dist/typescript/src/lib/utils/index.d.ts +1 -1
- package/dist/typescript/src/lib/utils/index.d.ts.map +1 -1
- package/dist/typescript/src/lib/utils/scales/scales.d.ts +11 -5
- package/dist/typescript/src/lib/utils/scales/scales.d.ts.map +1 -1
- package/dist/typescript/src/lib/utils/ticks/ticks.d.ts +13 -5
- package/dist/typescript/src/lib/utils/ticks/ticks.d.ts.map +1 -1
- package/dist/typescript/src/lib/utils/types.d.ts +3 -28
- package/dist/typescript/src/lib/utils/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/lib/Components/Axis/Axis.constants.ts +23 -0
- package/src/lib/Components/Axis/Axis.types.ts +40 -0
- package/src/lib/Components/Axis/index.ts +2 -0
- package/src/lib/Components/CartesianChart/CartesianChart.tsx +39 -24
- package/src/lib/Components/CartesianChart/context/useBuildChartContext.test.ts +56 -0
- package/src/lib/Components/CartesianChart/context/useBuildChartContext.ts +8 -8
- package/src/lib/Components/CartesianChart/types.ts +11 -3
- package/src/lib/Components/CartesianChart/utils.ts +18 -8
- package/src/lib/Components/Line/utils.test.ts +90 -0
- package/src/lib/Components/Line/utils.ts +6 -1
- package/src/lib/Components/LineChart/LineChart.stories.tsx +36 -0
- package/src/lib/Components/LineChart/LineChart.test.tsx +156 -0
- package/src/lib/Components/LineChart/LineChart.tsx +30 -40
- package/src/lib/Components/LineChart/types.ts +10 -3
- package/src/lib/Components/Point/Point.tsx +9 -3
- package/src/lib/Components/Point/constants.ts +6 -0
- package/src/lib/Components/Point/pointContext/MagneticPointsProvider.test.tsx +162 -0
- package/src/lib/Components/Point/pointContext/MagneticPointsProvider.tsx +45 -0
- package/src/lib/Components/Point/pointContext/index.ts +5 -0
- package/src/lib/Components/Point/pointContext/magneticPointsContext.ts +19 -0
- package/src/lib/Components/Point/types.ts +7 -0
- package/src/lib/Components/Point/utils.test.ts +95 -5
- package/src/lib/Components/Point/utils.ts +35 -7
- package/src/lib/Components/ReferenceLine/utils.ts +4 -7
- package/src/lib/Components/Scrubber/DefaultScrubberTooltip/ChartTooltipItem.tsx +54 -0
- package/src/lib/Components/Scrubber/DefaultScrubberTooltip/DefaultScrubberTooltip.test.tsx +259 -0
- package/src/lib/Components/Scrubber/DefaultScrubberTooltip/DefaultScrubberTooltip.tsx +105 -0
- package/src/lib/Components/Scrubber/DefaultScrubberTooltip/constants.ts +9 -0
- package/src/lib/Components/Scrubber/DefaultScrubberTooltip/utils.test.ts +264 -0
- package/src/lib/Components/Scrubber/DefaultScrubberTooltip/utils.ts +243 -0
- package/src/lib/Components/Scrubber/Scrubber.stories.tsx +104 -42
- package/src/lib/Components/Scrubber/Scrubber.test.tsx +7 -5
- package/src/lib/Components/Scrubber/Scrubber.tsx +47 -24
- package/src/lib/Components/Scrubber/ScrubberProvider.tsx +92 -28
- package/src/lib/Components/Scrubber/index.ts +10 -1
- package/src/lib/Components/Scrubber/types.ts +122 -4
- package/src/lib/Components/Scrubber/utils.test.ts +150 -0
- package/src/lib/Components/Scrubber/utils.ts +93 -3
- package/src/lib/utils/domain/domain.ts +6 -5
- package/src/lib/utils/index.ts +0 -2
- package/src/lib/utils/scales/scales.test.ts +19 -0
- package/src/lib/utils/scales/scales.ts +15 -9
- package/src/lib/utils/ticks/ticks.test.ts +45 -0
- package/src/lib/utils/ticks/ticks.ts +19 -9
- package/src/lib/utils/types.ts +3 -26
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { describe, expect, it } from '@jest/globals';
|
|
1
|
+
import { describe, expect, it, jest } from '@jest/globals';
|
|
2
|
+
import { renderHook } from '@testing-library/react-native';
|
|
2
3
|
|
|
4
|
+
import type { BaseAxisProps } from '../Axis';
|
|
5
|
+
import { ARROW_HEIGHT, ARROW_WIDTH, GAP, LABEL_FONT_SIZE } from './constants';
|
|
3
6
|
import {
|
|
4
|
-
ARROW_HEIGHT,
|
|
5
|
-
ARROW_WIDTH,
|
|
6
7
|
buildArrowPoints,
|
|
7
8
|
computeLabelY,
|
|
8
|
-
GAP,
|
|
9
9
|
isWithinBounds,
|
|
10
|
-
LABEL_FONT_SIZE,
|
|
11
10
|
resolveLabel,
|
|
11
|
+
useMagneticRegistration,
|
|
12
12
|
} from './utils';
|
|
13
13
|
|
|
14
14
|
describe('isWithinBounds', () => {
|
|
@@ -116,3 +116,93 @@ describe('computeLabelY', () => {
|
|
|
116
116
|
expect(result).toBe(pixelY + radius + GAP + GAP + LABEL_FONT_SIZE);
|
|
117
117
|
});
|
|
118
118
|
});
|
|
119
|
+
|
|
120
|
+
const makeContext = () => ({
|
|
121
|
+
register: jest.fn(),
|
|
122
|
+
unregister: jest.fn(),
|
|
123
|
+
version: 0,
|
|
124
|
+
getMagneticPoints: () => new Set<number>(),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const noAxisConfig = (): BaseAxisProps | undefined => undefined;
|
|
128
|
+
|
|
129
|
+
describe('useMagneticRegistration', () => {
|
|
130
|
+
it('registers the data index when magnetic is true', () => {
|
|
131
|
+
const ctx = makeContext();
|
|
132
|
+
renderHook(() => useMagneticRegistration(true, 3, noAxisConfig, ctx));
|
|
133
|
+
|
|
134
|
+
expect(ctx.register).toHaveBeenCalledWith(3);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('does not register when magnetic is false', () => {
|
|
138
|
+
const ctx = makeContext();
|
|
139
|
+
renderHook(() => useMagneticRegistration(false, 3, noAxisConfig, ctx));
|
|
140
|
+
|
|
141
|
+
expect(ctx.register).not.toHaveBeenCalled();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('unregisters on unmount', () => {
|
|
145
|
+
const ctx = makeContext();
|
|
146
|
+
const { unmount } = renderHook(() =>
|
|
147
|
+
useMagneticRegistration(true, 3, noAxisConfig, ctx),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
unmount();
|
|
151
|
+
expect(ctx.unregister).toHaveBeenCalledWith(3);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('resolves dataX through axis config data when provided', () => {
|
|
155
|
+
const ctx = makeContext();
|
|
156
|
+
const getXAxisConfig = (): BaseAxisProps => ({
|
|
157
|
+
scaleType: 'band',
|
|
158
|
+
data: [100, 200, 300],
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
renderHook(() => useMagneticRegistration(true, 200, getXAxisConfig, ctx));
|
|
162
|
+
|
|
163
|
+
expect(ctx.register).toHaveBeenCalledWith(1);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('does not register when axis data exists but does not contain the value', () => {
|
|
167
|
+
const ctx = makeContext();
|
|
168
|
+
const getXAxisConfig = (): BaseAxisProps => ({
|
|
169
|
+
scaleType: 'band',
|
|
170
|
+
data: [100, 200, 300],
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
renderHook(() => useMagneticRegistration(true, 999, getXAxisConfig, ctx));
|
|
174
|
+
|
|
175
|
+
expect(ctx.register).not.toHaveBeenCalled();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('re-registers when dataX changes', () => {
|
|
179
|
+
const ctx = makeContext();
|
|
180
|
+
const { rerender } = renderHook(
|
|
181
|
+
({ dataX }: { dataX: number }) =>
|
|
182
|
+
useMagneticRegistration(true, dataX, noAxisConfig, ctx),
|
|
183
|
+
{ initialProps: { dataX: 2 } },
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
expect(ctx.register).toHaveBeenCalledWith(2);
|
|
187
|
+
|
|
188
|
+
rerender({ dataX: 4 });
|
|
189
|
+
|
|
190
|
+
expect(ctx.unregister).toHaveBeenCalledWith(2);
|
|
191
|
+
expect(ctx.register).toHaveBeenCalledWith(4);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('unregisters and stops when magnetic switches to false', () => {
|
|
195
|
+
const ctx = makeContext();
|
|
196
|
+
const { rerender } = renderHook(
|
|
197
|
+
({ magnetic }: { magnetic: boolean }) =>
|
|
198
|
+
useMagneticRegistration(magnetic, 3, noAxisConfig, ctx),
|
|
199
|
+
{ initialProps: { magnetic: true } },
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
expect(ctx.register).toHaveBeenCalledWith(3);
|
|
203
|
+
|
|
204
|
+
rerender({ magnetic: false });
|
|
205
|
+
|
|
206
|
+
expect(ctx.unregister).toHaveBeenCalledWith(3);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export const ARROW_HEIGHT = 4;
|
|
8
|
-
export const GAP = 4;
|
|
3
|
+
import type { DrawingArea } from '../../utils/types';
|
|
4
|
+
import type { BaseAxisProps } from '../Axis';
|
|
5
|
+
import { LABEL_FONT_SIZE, ARROW_WIDTH, ARROW_HEIGHT, GAP } from './constants';
|
|
6
|
+
import type { MagneticPointsContextValue } from './pointContext/magneticPointsContext';
|
|
9
7
|
|
|
10
8
|
export const isWithinBounds = (
|
|
11
9
|
px: number,
|
|
@@ -53,6 +51,36 @@ export const resolveLabel = (
|
|
|
53
51
|
return resolved === '' ? undefined : resolved;
|
|
54
52
|
};
|
|
55
53
|
|
|
54
|
+
export const resolveDataXToIndex = (
|
|
55
|
+
dataX: number,
|
|
56
|
+
axisConfig: BaseAxisProps | undefined,
|
|
57
|
+
): number | undefined => {
|
|
58
|
+
const axisData = axisConfig?.data;
|
|
59
|
+
if (!axisData || typeof axisData[0] !== 'number') return dataX;
|
|
60
|
+
const index = (axisData as number[]).indexOf(dataX);
|
|
61
|
+
if (index === -1) return undefined;
|
|
62
|
+
return index;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Registers/unregisters a data index as a magnetic snap target
|
|
67
|
+
* when the Point has `magnetic` enabled.
|
|
68
|
+
*/
|
|
69
|
+
export const useMagneticRegistration = (
|
|
70
|
+
magnetic: boolean,
|
|
71
|
+
dataX: number,
|
|
72
|
+
getXAxisConfig: () => BaseAxisProps | undefined,
|
|
73
|
+
{ register, unregister }: MagneticPointsContextValue,
|
|
74
|
+
): void => {
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (!magnetic) return;
|
|
77
|
+
const index = resolveDataXToIndex(dataX, getXAxisConfig());
|
|
78
|
+
if (index === undefined) return;
|
|
79
|
+
register(index);
|
|
80
|
+
return () => unregister(index);
|
|
81
|
+
}, [magnetic, dataX, getXAxisConfig, register, unregister]);
|
|
82
|
+
};
|
|
83
|
+
|
|
56
84
|
/**
|
|
57
85
|
* Computes the vertical position of the label text baseline.
|
|
58
86
|
*/
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { getPointOnScale, isCategoricalScale } from '../../utils/scales/scales';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
ChartScaleFunction,
|
|
5
|
-
DrawingArea,
|
|
6
|
-
} from '../../utils/types';
|
|
2
|
+
import type { ChartScaleFunction, DrawingArea } from '../../utils/types';
|
|
3
|
+
import type { BaseAxisProps } from '../Axis';
|
|
7
4
|
|
|
8
5
|
import type { LabelAlignment, LabelPosition } from './types';
|
|
9
6
|
|
|
@@ -28,7 +25,7 @@ type ResolvePixelParams = {
|
|
|
28
25
|
scale: ChartScaleFunction | undefined;
|
|
29
26
|
axis: 'x' | 'y';
|
|
30
27
|
drawingArea: DrawingArea;
|
|
31
|
-
axisConfig?:
|
|
28
|
+
axisConfig?: BaseAxisProps;
|
|
32
29
|
};
|
|
33
30
|
|
|
34
31
|
type LabelParams = {
|
|
@@ -95,7 +92,7 @@ export const isPixelWithinDrawingArea = (
|
|
|
95
92
|
*/
|
|
96
93
|
const resolveDataValue = (
|
|
97
94
|
index: number,
|
|
98
|
-
axisConfig?:
|
|
95
|
+
axisConfig?: BaseAxisProps,
|
|
99
96
|
): number | undefined => {
|
|
100
97
|
const data = axisConfig?.data;
|
|
101
98
|
if (!data || data.length === 0) return index;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useTheme } from '@ledgerhq/lumen-ui-rnative';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { G, Text as SvgText } from 'react-native-svg';
|
|
4
|
+
|
|
5
|
+
import type { ChartTooltipItemProps } from '../types';
|
|
6
|
+
import { PADDING_X } from './constants';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Memoized so it only re-renders when one of its primitive props actually
|
|
10
|
+
* changes. Combined with the stable per-index ref callbacks built in
|
|
11
|
+
* `DefaultScrubberTooltip`, this keeps the row out of the per-scrub-frame
|
|
12
|
+
* reconciliation path when its label / value / position have not changed.
|
|
13
|
+
*/
|
|
14
|
+
export const ChartTooltipItem = memo(function ChartTooltipItem({
|
|
15
|
+
label,
|
|
16
|
+
value,
|
|
17
|
+
x = 0,
|
|
18
|
+
y = 0,
|
|
19
|
+
width,
|
|
20
|
+
labelRef,
|
|
21
|
+
valueRef,
|
|
22
|
+
}: Readonly<ChartTooltipItemProps>) {
|
|
23
|
+
const { theme } = useTheme();
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<G>
|
|
27
|
+
<SvgText
|
|
28
|
+
ref={labelRef}
|
|
29
|
+
x={x + PADDING_X}
|
|
30
|
+
y={y}
|
|
31
|
+
textAnchor='start'
|
|
32
|
+
alignmentBaseline='central'
|
|
33
|
+
fill={theme.colors.text.muted}
|
|
34
|
+
fontSize={theme.typographies.body4.fontSize}
|
|
35
|
+
fontFamily={theme.fontFamilies.sans}
|
|
36
|
+
>
|
|
37
|
+
{String(label)}
|
|
38
|
+
</SvgText>
|
|
39
|
+
<SvgText
|
|
40
|
+
ref={valueRef}
|
|
41
|
+
x={x + width - PADDING_X}
|
|
42
|
+
y={y}
|
|
43
|
+
textAnchor='end'
|
|
44
|
+
alignmentBaseline='central'
|
|
45
|
+
fill={theme.colors.text.base}
|
|
46
|
+
fontSize={theme.typographies.body4.fontSize}
|
|
47
|
+
fontWeight={theme.typographies.body4.fontWeight}
|
|
48
|
+
fontFamily={theme.fontFamilies.sans}
|
|
49
|
+
>
|
|
50
|
+
{String(value)}
|
|
51
|
+
</SvgText>
|
|
52
|
+
</G>
|
|
53
|
+
);
|
|
54
|
+
});
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { describe, expect, it, jest } from '@jest/globals';
|
|
2
|
+
import { ledgerLiveThemes } from '@ledgerhq/lumen-design-core';
|
|
3
|
+
import { ThemeProvider } from '@ledgerhq/lumen-ui-rnative';
|
|
4
|
+
import { render } from '@testing-library/react-native';
|
|
5
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
6
|
+
|
|
7
|
+
import { CartesianChart } from '../../CartesianChart';
|
|
8
|
+
import { ScrubberContextProvider } from '../context';
|
|
9
|
+
import { Scrubber } from '../Scrubber';
|
|
10
|
+
import type { ScrubberContextValue, ScrubberTooltipContent } from '../types';
|
|
11
|
+
|
|
12
|
+
const sampleSeries = [
|
|
13
|
+
{ id: 's1', stroke: '#7B61FF', data: [10, 20, 30, 40, 50] },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const Wrapper = ({ children }: { children: ReactNode }) => (
|
|
17
|
+
<ThemeProvider themes={ledgerLiveThemes} colorScheme='light'>
|
|
18
|
+
{children}
|
|
19
|
+
</ThemeProvider>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const activeScrubberContext: ScrubberContextValue = {
|
|
23
|
+
enableScrubbing: true,
|
|
24
|
+
scrubberPosition: 2,
|
|
25
|
+
onScrubberPositionChange: () => undefined,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const idleScrubberContext: ScrubberContextValue = {
|
|
29
|
+
enableScrubbing: true,
|
|
30
|
+
scrubberPosition: undefined,
|
|
31
|
+
onScrubberPositionChange: () => undefined,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const renderTooltip = ({
|
|
35
|
+
scrubberProps = { tooltip: () => ({ items: [] }) },
|
|
36
|
+
scrubberContext = activeScrubberContext,
|
|
37
|
+
width = 400,
|
|
38
|
+
height = 200,
|
|
39
|
+
}: {
|
|
40
|
+
scrubberProps?: ComponentProps<typeof Scrubber>;
|
|
41
|
+
scrubberContext?: ScrubberContextValue;
|
|
42
|
+
width?: number;
|
|
43
|
+
height?: number;
|
|
44
|
+
} = {}) =>
|
|
45
|
+
render(
|
|
46
|
+
<Wrapper>
|
|
47
|
+
<CartesianChart series={sampleSeries} width={width} height={height}>
|
|
48
|
+
<ScrubberContextProvider value={scrubberContext}>
|
|
49
|
+
<Scrubber {...scrubberProps} />
|
|
50
|
+
</ScrubberContextProvider>
|
|
51
|
+
</CartesianChart>
|
|
52
|
+
</Wrapper>,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
describe('DefaultScrubberTooltip', () => {
|
|
56
|
+
it('renders nothing when no scrubber position is active', () => {
|
|
57
|
+
const { queryByTestId } = renderTooltip({
|
|
58
|
+
scrubberProps: {
|
|
59
|
+
tooltip: () => ({ items: [{ label: 'Date', value: 'Jan' }] }),
|
|
60
|
+
},
|
|
61
|
+
scrubberContext: idleScrubberContext,
|
|
62
|
+
});
|
|
63
|
+
expect(queryByTestId('chart-tooltip')).toBeNull();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('renders nothing when items callback returns an empty array', () => {
|
|
67
|
+
const { queryByTestId } = renderTooltip({
|
|
68
|
+
scrubberProps: { tooltip: () => ({ items: [] }) },
|
|
69
|
+
});
|
|
70
|
+
expect(queryByTestId('chart-tooltip')).toBeNull();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('renders the tooltip group when scrubber is active and items are provided', () => {
|
|
74
|
+
const { getByTestId } = renderTooltip({
|
|
75
|
+
scrubberProps: {
|
|
76
|
+
tooltip: () => ({ items: [{ label: 'Date', value: 'Jan' }] }),
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
expect(getByTestId('chart-tooltip')).toBeTruthy();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('renders the background rect', () => {
|
|
83
|
+
const { getByTestId } = renderTooltip({
|
|
84
|
+
scrubberProps: {
|
|
85
|
+
tooltip: () => ({ items: [{ label: 'Date', value: 'Jan' }] }),
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
expect(getByTestId('chart-tooltip-rect')).toBeTruthy();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('renders item label and value text', () => {
|
|
92
|
+
const { getByText } = renderTooltip({
|
|
93
|
+
scrubberProps: {
|
|
94
|
+
tooltip: () => ({ items: [{ label: 'Date', value: 'Jan' }] }),
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
expect(getByText('Date')).toBeTruthy();
|
|
98
|
+
expect(getByText('Jan')).toBeTruthy();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('renders multiple items', () => {
|
|
102
|
+
const { getByText } = renderTooltip({
|
|
103
|
+
scrubberProps: {
|
|
104
|
+
tooltip: () => ({
|
|
105
|
+
items: [
|
|
106
|
+
{ label: 'Date', value: 'Jan' },
|
|
107
|
+
{ label: 'Price', value: '$10' },
|
|
108
|
+
],
|
|
109
|
+
}),
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
expect(getByText('Date')).toBeTruthy();
|
|
113
|
+
expect(getByText('Jan')).toBeTruthy();
|
|
114
|
+
expect(getByText('Price')).toBeTruthy();
|
|
115
|
+
expect(getByText('$10')).toBeTruthy();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('passes the active data index to the tooltip callback', () => {
|
|
119
|
+
const tooltip = jest.fn().mockReturnValue({
|
|
120
|
+
items: [{ label: 'i', value: '0' }],
|
|
121
|
+
}) as unknown as (index: number) => ScrubberTooltipContent;
|
|
122
|
+
renderTooltip({ scrubberProps: { tooltip } });
|
|
123
|
+
expect(tooltip).toHaveBeenCalledWith(
|
|
124
|
+
activeScrubberContext.scrubberPosition,
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('suppresses the tooltip when items returns empty for the active index', () => {
|
|
129
|
+
const { queryByTestId } = renderTooltip({
|
|
130
|
+
scrubberProps: { tooltip: () => ({ items: [] }) },
|
|
131
|
+
});
|
|
132
|
+
expect(queryByTestId('chart-tooltip')).toBeNull();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('positioning logic', () => {
|
|
136
|
+
const defaultTooltip = (): ScrubberTooltipContent => ({
|
|
137
|
+
items: [{ label: 'Date', value: 'Jan' }],
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const scrubberAt = (position: number): ScrubberContextValue => ({
|
|
141
|
+
enableScrubbing: true,
|
|
142
|
+
scrubberPosition: position,
|
|
143
|
+
onScrubberPositionChange: () => undefined,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('places tooltip to the right of the scrubber when mid-chart', () => {
|
|
147
|
+
const { getByTestId } = renderTooltip({
|
|
148
|
+
scrubberProps: { tooltip: defaultTooltip },
|
|
149
|
+
scrubberContext: scrubberAt(2),
|
|
150
|
+
});
|
|
151
|
+
expect(getByTestId('chart-tooltip-rect').props.x).toBe(260);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('flips tooltip left when right side would overflow (index 3)', () => {
|
|
155
|
+
const { getByTestId } = renderTooltip({
|
|
156
|
+
scrubberProps: {
|
|
157
|
+
tooltip: () => ({ ...defaultTooltip(), minWidth: 120 }),
|
|
158
|
+
},
|
|
159
|
+
scrubberContext: scrubberAt(3),
|
|
160
|
+
});
|
|
161
|
+
expect(getByTestId('chart-tooltip-rect').props.x).toBe(220);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('flips at the rightmost scrubber position (index 4)', () => {
|
|
165
|
+
const { getByTestId } = renderTooltip({
|
|
166
|
+
scrubberProps: {
|
|
167
|
+
tooltip: () => ({ ...defaultTooltip(), minWidth: 120 }),
|
|
168
|
+
},
|
|
169
|
+
scrubberContext: scrubberAt(4),
|
|
170
|
+
});
|
|
171
|
+
expect(getByTestId('chart-tooltip-rect').props.x).toBe(320);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('custom offset shifts the no-flip tooltip position', () => {
|
|
175
|
+
const { getByTestId } = renderTooltip({
|
|
176
|
+
scrubberProps: {
|
|
177
|
+
tooltip: () => ({ ...defaultTooltip(), offset: 20 }),
|
|
178
|
+
},
|
|
179
|
+
scrubberContext: scrubberAt(2),
|
|
180
|
+
});
|
|
181
|
+
expect(getByTestId('chart-tooltip-rect').props.x).toBe(270);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('wider minWidth can trigger a flip that the default width would not', () => {
|
|
185
|
+
const { getByTestId } = renderTooltip({
|
|
186
|
+
scrubberProps: {
|
|
187
|
+
tooltip: () => ({ ...defaultTooltip(), minWidth: 200 }),
|
|
188
|
+
},
|
|
189
|
+
scrubberContext: scrubberAt(2),
|
|
190
|
+
});
|
|
191
|
+
expect(getByTestId('chart-tooltip-rect').props.x).toBe(50);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe('title in tooltip content', () => {
|
|
196
|
+
it('renders a static string title', () => {
|
|
197
|
+
const { getByTestId, getByText } = renderTooltip({
|
|
198
|
+
scrubberProps: {
|
|
199
|
+
tooltip: () => ({
|
|
200
|
+
title: 'My Title',
|
|
201
|
+
items: [{ label: 'T', value: 'V' }],
|
|
202
|
+
}),
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
expect(getByTestId('chart-tooltip-title')).toBeTruthy();
|
|
206
|
+
expect(getByText('My Title')).toBeTruthy();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('renders the title returned by a callback', () => {
|
|
210
|
+
const { getByTestId } = renderTooltip({
|
|
211
|
+
scrubberProps: {
|
|
212
|
+
tooltip: () => ({
|
|
213
|
+
title: (i: number) => `Index ${i}`,
|
|
214
|
+
items: [{ label: 'T', value: 'V' }],
|
|
215
|
+
}),
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
expect(getByTestId('chart-tooltip-title')).toBeTruthy();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('passes the active data index to the title callback', () => {
|
|
222
|
+
const title = jest.fn().mockReturnValue('Title') as unknown as (
|
|
223
|
+
index: number,
|
|
224
|
+
) => string;
|
|
225
|
+
renderTooltip({
|
|
226
|
+
scrubberProps: {
|
|
227
|
+
tooltip: () => ({
|
|
228
|
+
title,
|
|
229
|
+
items: [{ label: 'T', value: 'V' }],
|
|
230
|
+
}),
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
expect(title).toHaveBeenCalledWith(
|
|
234
|
+
activeScrubberContext.scrubberPosition,
|
|
235
|
+
);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('does not render a title element when title is undefined', () => {
|
|
239
|
+
const { queryByTestId } = renderTooltip({
|
|
240
|
+
scrubberProps: {
|
|
241
|
+
tooltip: () => ({ items: [{ label: 'T', value: 'V' }] }),
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
expect(queryByTestId('chart-tooltip-title')).toBeNull();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('does not render a title element when title callback returns undefined', () => {
|
|
248
|
+
const { queryByTestId } = renderTooltip({
|
|
249
|
+
scrubberProps: {
|
|
250
|
+
tooltip: () => ({
|
|
251
|
+
title: () => undefined,
|
|
252
|
+
items: [{ label: 'T', value: 'V' }],
|
|
253
|
+
}),
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
expect(queryByTestId('chart-tooltip-title')).toBeNull();
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { useTheme } from '@ledgerhq/lumen-ui-rnative';
|
|
2
|
+
import { G, Rect, Text as SvgText } from 'react-native-svg';
|
|
3
|
+
|
|
4
|
+
import type { ScrubberTooltipProps } from '../types';
|
|
5
|
+
import { ChartTooltipItem } from './ChartTooltipItem';
|
|
6
|
+
import {
|
|
7
|
+
BORDER_RADIUS,
|
|
8
|
+
DEFAULT_OFFSET,
|
|
9
|
+
DEFAULT_TOOLTIP_MIN_WIDTH,
|
|
10
|
+
PADDING_X,
|
|
11
|
+
PADDING_Y,
|
|
12
|
+
ROW_GAP,
|
|
13
|
+
ROW_HEIGHT,
|
|
14
|
+
} from './constants';
|
|
15
|
+
import {
|
|
16
|
+
computeItemsBaseY,
|
|
17
|
+
computeTooltipHeight,
|
|
18
|
+
computeTooltipWidth,
|
|
19
|
+
computeTooltipX,
|
|
20
|
+
useBuildRefSetters,
|
|
21
|
+
useTooltipMeasurement,
|
|
22
|
+
} from './utils';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Default structured tooltip anchored to the scrubber line.
|
|
26
|
+
*
|
|
27
|
+
* The tooltip auto-fits its width to the rendered content via `getBBox`,
|
|
28
|
+
* with `minWidth` acting as an optional minimum width override. Use with
|
|
29
|
+
* {@link ScrubberProps.tooltip}; layout options (`offset`, `minWidth`) belong
|
|
30
|
+
* on the object returned from the `tooltip` callback. Return `{ items: [] }`
|
|
31
|
+
* from the callback to hide the tooltip at a given index.
|
|
32
|
+
*/
|
|
33
|
+
export function DefaultScrubberTooltip({
|
|
34
|
+
pixelX,
|
|
35
|
+
drawingArea,
|
|
36
|
+
title,
|
|
37
|
+
items,
|
|
38
|
+
offset = DEFAULT_OFFSET,
|
|
39
|
+
minWidth = DEFAULT_TOOLTIP_MIN_WIDTH,
|
|
40
|
+
}: Readonly<ScrubberTooltipProps>) {
|
|
41
|
+
const { theme } = useTheme();
|
|
42
|
+
|
|
43
|
+
const hasTitle = title !== undefined;
|
|
44
|
+
|
|
45
|
+
const { widths, titleRef, labelRefs, valueRefs } = useTooltipMeasurement(
|
|
46
|
+
items,
|
|
47
|
+
hasTitle,
|
|
48
|
+
title,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const labelRefSetters = useBuildRefSetters(labelRefs, items.length);
|
|
52
|
+
const valueRefSetters = useBuildRefSetters(valueRefs, items.length);
|
|
53
|
+
|
|
54
|
+
if (items.length === 0) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const tooltipWidth = computeTooltipWidth(widths, hasTitle, minWidth);
|
|
59
|
+
const tooltipX = computeTooltipX(pixelX, offset, tooltipWidth, drawingArea);
|
|
60
|
+
const tooltipHeight = computeTooltipHeight(items.length, hasTitle);
|
|
61
|
+
const itemsBaseY = computeItemsBaseY(drawingArea.y, hasTitle);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<G testID='chart-tooltip' opacity={widths === null ? 0 : 1}>
|
|
65
|
+
<Rect
|
|
66
|
+
testID='chart-tooltip-rect'
|
|
67
|
+
x={tooltipX}
|
|
68
|
+
y={drawingArea.y}
|
|
69
|
+
width={tooltipWidth}
|
|
70
|
+
height={tooltipHeight}
|
|
71
|
+
rx={BORDER_RADIUS}
|
|
72
|
+
fill={theme.colors.bg.muted}
|
|
73
|
+
/>
|
|
74
|
+
{hasTitle && (
|
|
75
|
+
<SvgText
|
|
76
|
+
ref={(el) => {
|
|
77
|
+
titleRef.current = el as unknown as (typeof titleRef)['current'];
|
|
78
|
+
}}
|
|
79
|
+
testID='chart-tooltip-title'
|
|
80
|
+
x={tooltipX + PADDING_X}
|
|
81
|
+
y={drawingArea.y + PADDING_Y + ROW_HEIGHT / 2}
|
|
82
|
+
alignmentBaseline='central'
|
|
83
|
+
fill={theme.colors.text.base}
|
|
84
|
+
fontSize={theme.typographies.body4.fontSize}
|
|
85
|
+
fontWeight={theme.typographies.body4.fontWeight}
|
|
86
|
+
fontFamily={theme.fontFamilies.sans}
|
|
87
|
+
>
|
|
88
|
+
{String(title)}
|
|
89
|
+
</SvgText>
|
|
90
|
+
)}
|
|
91
|
+
{items.map((item, i) => (
|
|
92
|
+
<ChartTooltipItem
|
|
93
|
+
key={i}
|
|
94
|
+
label={item.label}
|
|
95
|
+
value={item.value}
|
|
96
|
+
x={tooltipX}
|
|
97
|
+
y={itemsBaseY + i * (ROW_HEIGHT + ROW_GAP) + ROW_HEIGHT / 2}
|
|
98
|
+
width={tooltipWidth}
|
|
99
|
+
labelRef={labelRefSetters[i]}
|
|
100
|
+
valueRef={valueRefSetters[i]}
|
|
101
|
+
/>
|
|
102
|
+
))}
|
|
103
|
+
</G>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const DEFAULT_OFFSET = 10;
|
|
2
|
+
export const DEFAULT_TOOLTIP_MIN_WIDTH = 80;
|
|
3
|
+
export const PADDING_X = 8;
|
|
4
|
+
export const PADDING_Y = 8;
|
|
5
|
+
export const ROW_HEIGHT = 16;
|
|
6
|
+
export const ROW_GAP = 6;
|
|
7
|
+
export const TITLE_GAP = 6;
|
|
8
|
+
export const BORDER_RADIUS = 4;
|
|
9
|
+
export const LABEL_VALUE_GAP = 12;
|