@ledgerhq/lumen-ui-rnative-visualization 0.1.22 → 0.1.24
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/Line/Line.js +4 -4
- package/dist/module/lib/Components/Line/Line.js.map +1 -1
- package/dist/module/lib/Components/LineChart/LineChart.js +4 -4
- package/dist/module/lib/Components/LineChart/LineChart.js.map +1 -1
- package/dist/module/lib/Components/LineChart/LineChart.performance.test.js +99 -0
- package/dist/module/lib/Components/LineChart/LineChart.performance.test.js.map +1 -0
- package/dist/module/lib/Components/Point/Point.js +81 -50
- package/dist/module/lib/Components/Point/Point.js.map +1 -1
- package/dist/module/lib/Components/Point/Point.test.js +41 -0
- package/dist/module/lib/Components/Point/Point.test.js.map +1 -1
- package/dist/module/lib/Components/Point/constants.js +2 -0
- package/dist/module/lib/Components/Point/constants.js.map +1 -1
- package/dist/module/lib/Components/Point/pointContext/MagneticPointsProvider.js +19 -9
- package/dist/module/lib/Components/Point/pointContext/MagneticPointsProvider.js.map +1 -1
- package/dist/module/lib/Components/Point/pointContext/MagneticPointsProvider.test.js +10 -1
- package/dist/module/lib/Components/Point/pointContext/MagneticPointsProvider.test.js.map +1 -1
- package/dist/module/lib/Components/Point/pointContext/index.js +1 -1
- package/dist/module/lib/Components/Point/pointContext/index.js.map +1 -1
- package/dist/module/lib/Components/Point/pointContext/magneticPointsContext.js +22 -4
- package/dist/module/lib/Components/Point/pointContext/magneticPointsContext.js.map +1 -1
- package/dist/module/lib/Components/Point/usePointGeometry.js +60 -0
- package/dist/module/lib/Components/Point/usePointGeometry.js.map +1 -0
- package/dist/module/lib/Components/Point/usePointGeometry.test.js +86 -0
- package/dist/module/lib/Components/Point/usePointGeometry.test.js.map +1 -0
- package/dist/module/lib/Components/Point/utils.js +58 -15
- package/dist/module/lib/Components/Point/utils.js.map +1 -1
- package/dist/module/lib/Components/Point/utils.test.js +37 -75
- package/dist/module/lib/Components/Point/utils.test.js.map +1 -1
- package/dist/module/lib/Components/Scrubber/ScrubberProvider.js +2 -2
- package/dist/module/lib/Components/Scrubber/ScrubberProvider.js.map +1 -1
- package/dist/module/lib/utils/domain/domain.js +4 -4
- package/dist/module/lib/utils/domain/domain.js.map +1 -1
- package/dist/typescript/src/lib/Components/Line/Line.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Line/Line.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/LineChart/LineChart.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 +2 -0
- package/dist/typescript/src/lib/Components/Point/constants.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Point/pointContext/MagneticPointsProvider.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Point/pointContext/index.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Point/pointContext/index.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Point/pointContext/magneticPointsContext.d.ts +22 -5
- package/dist/typescript/src/lib/Components/Point/pointContext/magneticPointsContext.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Point/types.d.ts +32 -0
- package/dist/typescript/src/lib/Components/Point/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Point/usePointGeometry.d.ts +33 -0
- package/dist/typescript/src/lib/Components/Point/usePointGeometry.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/Point/utils.d.ts +30 -4
- package/dist/typescript/src/lib/Components/Point/utils.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/lib/Components/Line/Line.tsx +4 -4
- package/src/lib/Components/LineChart/LineChart.performance.test.tsx +101 -0
- package/src/lib/Components/LineChart/LineChart.tsx +18 -11
- package/src/lib/Components/Point/Point.test.tsx +46 -0
- package/src/lib/Components/Point/Point.tsx +79 -57
- package/src/lib/Components/Point/constants.ts +2 -0
- package/src/lib/Components/Point/pointContext/MagneticPointsProvider.test.tsx +13 -1
- package/src/lib/Components/Point/pointContext/MagneticPointsProvider.tsx +20 -8
- package/src/lib/Components/Point/pointContext/index.ts +4 -2
- package/src/lib/Components/Point/pointContext/magneticPointsContext.ts +29 -7
- package/src/lib/Components/Point/types.ts +41 -0
- package/src/lib/Components/Point/usePointGeometry.test.ts +95 -0
- package/src/lib/Components/Point/usePointGeometry.ts +77 -0
- package/src/lib/Components/Point/utils.test.ts +34 -80
- package/src/lib/Components/Point/utils.ts +77 -19
- package/src/lib/Components/Scrubber/ScrubberProvider.tsx +2 -2
- package/src/lib/utils/domain/domain.ts +4 -4
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { describe, expect, it
|
|
2
|
-
import { renderHook } from '@testing-library/react-native';
|
|
1
|
+
import { describe, expect, it } from '@jest/globals';
|
|
3
2
|
|
|
4
|
-
import type { BaseAxisProps } from '../Axis';
|
|
5
3
|
import { ARROW_HEIGHT, ARROW_WIDTH, GAP, LABEL_FONT_SIZE } from './constants';
|
|
6
4
|
import {
|
|
7
5
|
buildArrowPoints,
|
|
6
|
+
computeLabelX,
|
|
8
7
|
computeLabelY,
|
|
9
8
|
isWithinBounds,
|
|
10
9
|
resolveLabel,
|
|
11
|
-
useMagneticRegistration,
|
|
12
10
|
} from './utils';
|
|
13
11
|
|
|
14
12
|
describe('isWithinBounds', () => {
|
|
@@ -117,92 +115,48 @@ describe('computeLabelY', () => {
|
|
|
117
115
|
});
|
|
118
116
|
});
|
|
119
117
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
version: 0,
|
|
124
|
-
getMagneticPoints: () => new Set<number>(),
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
const noAxisConfig = (): BaseAxisProps | undefined => undefined;
|
|
118
|
+
describe('computeLabelX', () => {
|
|
119
|
+
const area = { x: 100, y: 0, width: 200, height: 100 };
|
|
120
|
+
const halfArrow = ARROW_WIDTH / 2;
|
|
128
121
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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);
|
|
122
|
+
it('centres the label on the point when clamping is disabled', () => {
|
|
123
|
+
expect(
|
|
124
|
+
computeLabelX(105, 'A very long label', area, 'center', true),
|
|
125
|
+
).toEqual({
|
|
126
|
+
x: 105,
|
|
127
|
+
textAnchor: 'middle',
|
|
128
|
+
});
|
|
152
129
|
});
|
|
153
130
|
|
|
154
|
-
it('
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
data: [100, 200, 300],
|
|
131
|
+
it('centres the label on the point when it fits inside the bounds', () => {
|
|
132
|
+
expect(computeLabelX(200, 'Peak', area, 'auto', true)).toEqual({
|
|
133
|
+
x: 200,
|
|
134
|
+
textAnchor: 'middle',
|
|
159
135
|
});
|
|
160
|
-
|
|
161
|
-
renderHook(() => useMagneticRegistration(true, 200, getXAxisConfig, ctx));
|
|
162
|
-
|
|
163
|
-
expect(ctx.register).toHaveBeenCalledWith(1);
|
|
164
136
|
});
|
|
165
137
|
|
|
166
|
-
it('
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
data: [100, 200, 300],
|
|
138
|
+
it('anchors near the left edge, offset by half the arrow width from the point', () => {
|
|
139
|
+
expect(computeLabelX(105, 'Long label', area, 'auto', true)).toEqual({
|
|
140
|
+
x: 105 - halfArrow,
|
|
141
|
+
textAnchor: 'start',
|
|
171
142
|
});
|
|
172
|
-
|
|
173
|
-
renderHook(() => useMagneticRegistration(true, 999, getXAxisConfig, ctx));
|
|
174
|
-
|
|
175
|
-
expect(ctx.register).not.toHaveBeenCalled();
|
|
176
143
|
});
|
|
177
144
|
|
|
178
|
-
it('
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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);
|
|
145
|
+
it('anchors near the right edge, offset by half the arrow width from the point', () => {
|
|
146
|
+
expect(computeLabelX(295, 'Long label', area, 'auto', true)).toEqual({
|
|
147
|
+
x: 295 + halfArrow,
|
|
148
|
+
textAnchor: 'end',
|
|
149
|
+
});
|
|
192
150
|
});
|
|
193
151
|
|
|
194
|
-
it('
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
rerender({ magnetic: false });
|
|
205
|
-
|
|
206
|
-
expect(ctx.unregister).toHaveBeenCalledWith(3);
|
|
152
|
+
it('omits the arrow offset when no arrow is rendered', () => {
|
|
153
|
+
expect(computeLabelX(105, 'Long label', area, 'auto', false)).toEqual({
|
|
154
|
+
x: 105,
|
|
155
|
+
textAnchor: 'start',
|
|
156
|
+
});
|
|
157
|
+
expect(computeLabelX(295, 'Long label', area, 'auto', false)).toEqual({
|
|
158
|
+
x: 295,
|
|
159
|
+
textAnchor: 'end',
|
|
160
|
+
});
|
|
207
161
|
});
|
|
208
162
|
});
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
|
|
3
1
|
import type { DrawingArea } from '../../utils/types';
|
|
4
2
|
import type { BaseAxisProps } from '../Axis';
|
|
5
|
-
import {
|
|
6
|
-
|
|
3
|
+
import {
|
|
4
|
+
ARROW_HEIGHT,
|
|
5
|
+
ARROW_WIDTH,
|
|
6
|
+
GAP,
|
|
7
|
+
LABEL_CHAR_WIDTH_RATIO,
|
|
8
|
+
LABEL_FONT_SIZE,
|
|
9
|
+
} from './constants';
|
|
10
|
+
import type { LabelAlignment } from './types';
|
|
11
|
+
|
|
12
|
+
export type LabelTextAnchor = 'start' | 'middle' | 'end';
|
|
7
13
|
|
|
8
14
|
export const isWithinBounds = (
|
|
9
15
|
px: number,
|
|
@@ -63,22 +69,33 @@ export const resolveDataXToIndex = (
|
|
|
63
69
|
};
|
|
64
70
|
|
|
65
71
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
72
|
+
* Computes the label's horizontal placement, keeping it inside the drawing area
|
|
73
|
+
* near the left/right edges. Centred on the point when it fits; otherwise
|
|
74
|
+
* anchored to the edge and aligned with the arrow's outer vertex (offset by half
|
|
75
|
+
* the arrow width from the point, when an arrow is rendered).
|
|
68
76
|
*/
|
|
69
|
-
export const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
export const computeLabelX = (
|
|
78
|
+
pixelX: number,
|
|
79
|
+
label: string,
|
|
80
|
+
area: DrawingArea,
|
|
81
|
+
alignment: LabelAlignment,
|
|
82
|
+
hasArrow: boolean,
|
|
83
|
+
): { x: number; textAnchor: LabelTextAnchor } => {
|
|
84
|
+
if (alignment === 'center') {
|
|
85
|
+
return { x: pixelX, textAnchor: 'middle' };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const halfWidth =
|
|
89
|
+
(label.length * LABEL_FONT_SIZE * LABEL_CHAR_WIDTH_RATIO) / 2;
|
|
90
|
+
const arrowOffset = hasArrow ? ARROW_WIDTH / 2 : 0;
|
|
91
|
+
|
|
92
|
+
if (pixelX - halfWidth < area.x) {
|
|
93
|
+
return { x: pixelX - arrowOffset, textAnchor: 'start' };
|
|
94
|
+
}
|
|
95
|
+
if (pixelX + halfWidth > area.x + area.width) {
|
|
96
|
+
return { x: pixelX + arrowOffset, textAnchor: 'end' };
|
|
97
|
+
}
|
|
98
|
+
return { x: pixelX, textAnchor: 'middle' };
|
|
82
99
|
};
|
|
83
100
|
|
|
84
101
|
/**
|
|
@@ -96,3 +113,44 @@ export const computeLabelY = (
|
|
|
96
113
|
? pixelY - radius - arrowOffset - GAP
|
|
97
114
|
: pixelY + radius + arrowOffset + GAP + LABEL_FONT_SIZE;
|
|
98
115
|
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Computes where a point's label and its connector arrow are drawn: the
|
|
119
|
+
* (optionally clamped) horizontal placement, the vertical baseline, and whether
|
|
120
|
+
* the arrow is rendered. Label content is resolved separately via
|
|
121
|
+
* {@link resolveLabel}.
|
|
122
|
+
*/
|
|
123
|
+
export const computeLabelGeometry = ({
|
|
124
|
+
text,
|
|
125
|
+
pixelX,
|
|
126
|
+
pixelY,
|
|
127
|
+
size,
|
|
128
|
+
labelPosition,
|
|
129
|
+
showLabelArrow,
|
|
130
|
+
area,
|
|
131
|
+
alignment,
|
|
132
|
+
}: {
|
|
133
|
+
text: string;
|
|
134
|
+
pixelX: number;
|
|
135
|
+
pixelY: number;
|
|
136
|
+
size: number;
|
|
137
|
+
labelPosition: 'top' | 'bottom';
|
|
138
|
+
showLabelArrow: boolean;
|
|
139
|
+
area: DrawingArea;
|
|
140
|
+
alignment: LabelAlignment;
|
|
141
|
+
}): {
|
|
142
|
+
x: number;
|
|
143
|
+
y: number;
|
|
144
|
+
textAnchor: LabelTextAnchor;
|
|
145
|
+
} => {
|
|
146
|
+
const { x, textAnchor } = computeLabelX(
|
|
147
|
+
pixelX,
|
|
148
|
+
text,
|
|
149
|
+
area,
|
|
150
|
+
alignment,
|
|
151
|
+
showLabelArrow,
|
|
152
|
+
);
|
|
153
|
+
const y = computeLabelY(pixelY, size / 2, labelPosition, showLabelArrow);
|
|
154
|
+
|
|
155
|
+
return { x, y, textAnchor };
|
|
156
|
+
};
|
|
@@ -7,7 +7,7 @@ import { scheduleOnRN } from 'react-native-worklets';
|
|
|
7
7
|
|
|
8
8
|
import { clamp } from '../../utils/numbers';
|
|
9
9
|
import { useCartesianChartContext } from '../CartesianChart/context';
|
|
10
|
-
import {
|
|
10
|
+
import { useMagneticSnapshot } from '../Point/pointContext';
|
|
11
11
|
import { ScrubberContextProvider } from './context';
|
|
12
12
|
import type { ScrubberProviderProps } from './types';
|
|
13
13
|
import {
|
|
@@ -46,7 +46,7 @@ export function ScrubberProvider({
|
|
|
46
46
|
>();
|
|
47
47
|
|
|
48
48
|
const { getXScale, getXAxisConfig, dataLength } = useCartesianChartContext();
|
|
49
|
-
const { getMagneticPoints, version } =
|
|
49
|
+
const { getMagneticPoints, version } = useMagneticSnapshot();
|
|
50
50
|
|
|
51
51
|
// All values touched by the gesture's JS-thread callback live in a single
|
|
52
52
|
// ref. Reading via `latest.current` keeps the callbacks reference-stable
|
|
@@ -55,13 +55,13 @@ export const computeYDomain = (
|
|
|
55
55
|
if (!s.data) continue;
|
|
56
56
|
for (const v of s.data) {
|
|
57
57
|
if (v !== null && v !== undefined) {
|
|
58
|
-
if (
|
|
58
|
+
if (hasValue) {
|
|
59
|
+
if (v < min) min = v;
|
|
60
|
+
if (v > max) max = v;
|
|
61
|
+
} else {
|
|
59
62
|
min = v;
|
|
60
63
|
max = v;
|
|
61
64
|
hasValue = true;
|
|
62
|
-
} else {
|
|
63
|
-
if (v < min) min = v;
|
|
64
|
-
if (v > max) max = v;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
}
|