@internetstiftelsen/charts 0.18.1 → 0.18.2
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/tooltip/geometry.js +84 -13
- package/dist/tooltip/types.d.ts +2 -2
- package/dist/tooltip/types.js +2 -2
- package/package.json +1 -1
package/dist/tooltip/geometry.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SPLIT_TOOLTIP_GAP_PX, TOOLTIP_BOX_ARROW_LENGTH_PX, TOOLTIP_CONNECTOR_ALIGNMENT_TOLERANCE_PX, TOOLTIP_CONNECTOR_ELBOW_RATIO, TOOLTIP_CONNECTOR_INSET_PX, TOOLTIP_CONNECTOR_MIN_PATH_LENGTH_PX, TOOLTIP_CONNECTOR_PADDING_PX, TOOLTIP_OFFSET_PX, TOOLTIP_TOTAL_BORDER_WIDTH_PX, TOOLTIP_VIEWPORT_PADDING_PX, } from './types.js';
|
|
2
2
|
const MAX_EXHAUSTIVE_HORIZONTAL_ROW_LAYOUTS = 10;
|
|
3
3
|
const HORIZONTAL_ROW_ORDER_FLIP_PENALTY_PX = 128;
|
|
4
|
+
const AUTO_BAR_TOOLTIP_CONNECTOR_MIN_PATH_LENGTH_PX = 8;
|
|
4
5
|
export function getSplitTooltipViewportBounds() {
|
|
5
6
|
const visualViewport = window.visualViewport;
|
|
6
7
|
const viewportLeft = window.scrollX + (visualViewport?.offsetLeft ?? 0);
|
|
@@ -98,13 +99,16 @@ export function getAnchoredTooltipPosition(anchor, target, tooltipWidth, tooltip
|
|
|
98
99
|
};
|
|
99
100
|
}
|
|
100
101
|
export function resolveTooltipConnectorLayout(arrowEdge, tooltipLeft, tooltipTop, tooltipWidth, tooltipHeight, targetX, targetY, anchor) {
|
|
101
|
-
const
|
|
102
|
-
const
|
|
102
|
+
const boxArrowPosition = resolveTooltipBoxArrowPosition(arrowEdge, tooltipLeft, tooltipTop, tooltipWidth, tooltipHeight, targetX, targetY);
|
|
103
|
+
const arrowTip = resolveTooltipArrowTip(arrowEdge, boxArrowPosition.x, boxArrowPosition.y, TOOLTIP_BOX_ARROW_LENGTH_PX);
|
|
104
|
+
const arrowTipX = tooltipLeft + arrowTip.x;
|
|
105
|
+
const arrowTipY = tooltipTop + arrowTip.y;
|
|
106
|
+
const connectorTarget = resolveTooltipConnectorTarget(arrowEdge, targetX, targetY, arrowTipX, arrowTipY, anchor);
|
|
107
|
+
const localTargetX = connectorTarget.x - tooltipLeft;
|
|
108
|
+
const localTargetY = connectorTarget.y - tooltipTop;
|
|
103
109
|
if (!Number.isFinite(localTargetX) || !Number.isFinite(localTargetY)) {
|
|
104
110
|
return null;
|
|
105
111
|
}
|
|
106
|
-
const boxArrowPosition = resolveTooltipBoxArrowPosition(arrowEdge, tooltipLeft, tooltipTop, tooltipWidth, tooltipHeight, targetX, targetY);
|
|
107
|
-
const arrowTip = resolveTooltipArrowTip(arrowEdge, boxArrowPosition.x, boxArrowPosition.y, TOOLTIP_BOX_ARROW_LENGTH_PX);
|
|
108
112
|
const minX = Math.min(arrowTip.x, localTargetX) - TOOLTIP_CONNECTOR_PADDING_PX;
|
|
109
113
|
const maxX = Math.max(arrowTip.x, localTargetX) + TOOLTIP_CONNECTOR_PADDING_PX;
|
|
110
114
|
const minY = Math.min(arrowTip.y, localTargetY) - TOOLTIP_CONNECTOR_PADDING_PX;
|
|
@@ -117,9 +121,7 @@ export function resolveTooltipConnectorLayout(arrowEdge, tooltipLeft, tooltipTop
|
|
|
117
121
|
const startY = arrowTip.y - minY;
|
|
118
122
|
const endX = localTargetX - minX;
|
|
119
123
|
const endY = localTargetY - minY;
|
|
120
|
-
const
|
|
121
|
-
const arrowTipY = tooltipTop + arrowTip.y;
|
|
122
|
-
const connectorPath = resolveTooltipConnectorPath(arrowEdge, startX, startY, endX, endY, arrowTipX, arrowTipY, anchor);
|
|
124
|
+
const connectorPath = resolveTooltipConnectorPath(arrowEdge, startX, startY, endX, endY, arrowTipX, arrowTipY, anchor, connectorTarget.preferDirectPath);
|
|
123
125
|
if (!hasFiniteNumbers(width, height, boxX, boxY, startX, startY, endX, endY)) {
|
|
124
126
|
return null;
|
|
125
127
|
}
|
|
@@ -134,6 +136,43 @@ export function resolveTooltipConnectorLayout(arrowEdge, tooltipLeft, tooltipTop
|
|
|
134
136
|
arrowY: boxArrowPosition.y,
|
|
135
137
|
};
|
|
136
138
|
}
|
|
139
|
+
function resolveTooltipConnectorTarget(arrowEdge, targetX, targetY, arrowTipX, arrowTipY, anchor) {
|
|
140
|
+
if (isPointTooltipAnchor(anchor)) {
|
|
141
|
+
return { x: targetX, y: targetY, preferDirectPath: false };
|
|
142
|
+
}
|
|
143
|
+
if (arrowEdge === 'left') {
|
|
144
|
+
return {
|
|
145
|
+
x: anchor.right,
|
|
146
|
+
y: clampTooltipCoordinate(arrowTipY, anchor.top, anchor.bottom),
|
|
147
|
+
preferDirectPath: true,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (arrowEdge === 'right') {
|
|
151
|
+
return {
|
|
152
|
+
x: anchor.left,
|
|
153
|
+
y: clampTooltipCoordinate(arrowTipY, anchor.top, anchor.bottom),
|
|
154
|
+
preferDirectPath: true,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (arrowEdge === 'top') {
|
|
158
|
+
return {
|
|
159
|
+
x: clampTooltipCoordinate(arrowTipX, anchor.left, anchor.right),
|
|
160
|
+
y: anchor.bottom,
|
|
161
|
+
preferDirectPath: true,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
x: clampTooltipCoordinate(arrowTipX, anchor.left, anchor.right),
|
|
166
|
+
y: anchor.top,
|
|
167
|
+
preferDirectPath: true,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function isPointTooltipAnchor(anchor) {
|
|
171
|
+
return (Math.abs(anchor.left - anchor.right) <=
|
|
172
|
+
TOOLTIP_CONNECTOR_ALIGNMENT_TOLERANCE_PX &&
|
|
173
|
+
Math.abs(anchor.top - anchor.bottom) <=
|
|
174
|
+
TOOLTIP_CONNECTOR_ALIGNMENT_TOLERANCE_PX);
|
|
175
|
+
}
|
|
137
176
|
export function resolveTooltipArrowPosition(arrowEdge, boxX, boxY, length, halfHeight) {
|
|
138
177
|
switch (arrowEdge) {
|
|
139
178
|
case 'left':
|
|
@@ -210,17 +249,26 @@ function getTooltipConnectorOffset(start, size, target) {
|
|
|
210
249
|
const preferredOffset = target - start;
|
|
211
250
|
return Math.max(minOffset, Math.min(preferredOffset, maxOffset));
|
|
212
251
|
}
|
|
213
|
-
function resolveTooltipConnectorPath(arrowEdge, startX, startY, endX, endY, arrowTipX, arrowTipY, anchor) {
|
|
252
|
+
function resolveTooltipConnectorPath(arrowEdge, startX, startY, endX, endY, arrowTipX, arrowTipY, anchor, preferDirectPath) {
|
|
214
253
|
if (arrowEdge === 'left' || arrowEdge === 'right') {
|
|
215
|
-
|
|
254
|
+
const minPathLength = preferDirectPath
|
|
255
|
+
? AUTO_BAR_TOOLTIP_CONNECTOR_MIN_PATH_LENGTH_PX
|
|
256
|
+
: TOOLTIP_CONNECTOR_MIN_PATH_LENGTH_PX;
|
|
257
|
+
if (isTooltipArrowTipNearVerticalAnchorSpan(arrowTipY, anchor, minPathLength)) {
|
|
216
258
|
return '';
|
|
217
259
|
}
|
|
260
|
+
if (preferDirectPath) {
|
|
261
|
+
return `M ${startX},${startY} L ${endX},${endY}`;
|
|
262
|
+
}
|
|
218
263
|
const elbowX = startX + (endX - startX) * TOOLTIP_CONNECTOR_ELBOW_RATIO;
|
|
219
264
|
return `M ${startX},${startY} L ${elbowX},${startY} L ${endX},${endY}`;
|
|
220
265
|
}
|
|
221
266
|
if (isTooltipArrowTipInsideHorizontalAnchorSpan(arrowTipX, anchor)) {
|
|
222
267
|
return '';
|
|
223
268
|
}
|
|
269
|
+
if (preferDirectPath) {
|
|
270
|
+
return `M ${startX},${startY} L ${endX},${endY}`;
|
|
271
|
+
}
|
|
224
272
|
const elbowY = startY + (endY - startY) * TOOLTIP_CONNECTOR_ELBOW_RATIO;
|
|
225
273
|
return `M ${startX},${startY} L ${startX},${elbowY} L ${endX},${endY}`;
|
|
226
274
|
}
|
|
@@ -232,12 +280,12 @@ function isTooltipArrowTipInsideVerticalAnchorSpan(arrowTipY, anchor) {
|
|
|
232
280
|
return (arrowTipY >= anchor.top - TOOLTIP_CONNECTOR_ALIGNMENT_TOLERANCE_PX &&
|
|
233
281
|
arrowTipY <= anchor.bottom + TOOLTIP_CONNECTOR_ALIGNMENT_TOLERANCE_PX);
|
|
234
282
|
}
|
|
235
|
-
function isTooltipArrowTipNearVerticalAnchorSpan(arrowTipY, anchor) {
|
|
283
|
+
function isTooltipArrowTipNearVerticalAnchorSpan(arrowTipY, anchor, minPathLength = TOOLTIP_CONNECTOR_MIN_PATH_LENGTH_PX) {
|
|
236
284
|
if (isTooltipArrowTipInsideVerticalAnchorSpan(arrowTipY, anchor)) {
|
|
237
285
|
return true;
|
|
238
286
|
}
|
|
239
|
-
return (arrowTipY >= anchor.top -
|
|
240
|
-
arrowTipY <= anchor.bottom +
|
|
287
|
+
return (arrowTipY >= anchor.top - minPathLength &&
|
|
288
|
+
arrowTipY <= anchor.bottom + minPathLength);
|
|
241
289
|
}
|
|
242
290
|
function resolveTooltipArrowTip(arrowEdge, boxX, boxY, length) {
|
|
243
291
|
if (arrowEdge === 'left' || arrowEdge === 'right') {
|
|
@@ -288,6 +336,7 @@ function getCombinedSplitTooltipTarget(layouts) {
|
|
|
288
336
|
function getSideSplitTooltipLayouts(layouts) {
|
|
289
337
|
if (layouts.every((layout) => layout.targetMode === 'auto')) {
|
|
290
338
|
return [...layouts].sort((a, b) => a.anchor.top - b.anchor.top ||
|
|
339
|
+
a.anchor.bottom - b.anchor.bottom ||
|
|
291
340
|
a.anchor.left - b.anchor.left ||
|
|
292
341
|
a.order - b.order);
|
|
293
342
|
}
|
|
@@ -662,6 +711,15 @@ function getSidePlacementCandidates(layout, placedLayouts, allLayouts, bounds) {
|
|
|
662
711
|
];
|
|
663
712
|
if (layout.targetMode === 'auto') {
|
|
664
713
|
const connectorlessRange = getSideConnectorlessTopRange(layout);
|
|
714
|
+
const exactConnectorlessRange = getExactSideConnectorlessTopRange(layout);
|
|
715
|
+
candidates.push({
|
|
716
|
+
top: exactConnectorlessRange.min,
|
|
717
|
+
arrowEdge: layout.arrowEdge,
|
|
718
|
+
});
|
|
719
|
+
candidates.push({
|
|
720
|
+
top: exactConnectorlessRange.max,
|
|
721
|
+
arrowEdge: layout.arrowEdge,
|
|
722
|
+
});
|
|
665
723
|
candidates.push({
|
|
666
724
|
top: connectorlessRange.min,
|
|
667
725
|
arrowEdge: layout.arrowEdge,
|
|
@@ -750,6 +808,17 @@ function getFixedPointSideSpreadPreferredTop(layout, direction) {
|
|
|
750
808
|
return layout.targetY - TOOLTIP_CONNECTOR_INSET_PX;
|
|
751
809
|
}
|
|
752
810
|
function getSideConnectorlessTopRange(layout) {
|
|
811
|
+
const nearPathPadding = layout.targetMode === 'auto'
|
|
812
|
+
? AUTO_BAR_TOOLTIP_CONNECTOR_MIN_PATH_LENGTH_PX
|
|
813
|
+
: 0;
|
|
814
|
+
return {
|
|
815
|
+
min: layout.anchor.top -
|
|
816
|
+
getTooltipConnectorMaxOffset(layout.height) -
|
|
817
|
+
nearPathPadding,
|
|
818
|
+
max: layout.anchor.bottom - TOOLTIP_CONNECTOR_INSET_PX + nearPathPadding,
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
function getExactSideConnectorlessTopRange(layout) {
|
|
753
822
|
return {
|
|
754
823
|
min: layout.anchor.top - getTooltipConnectorMaxOffset(layout.height),
|
|
755
824
|
max: layout.anchor.bottom - TOOLTIP_CONNECTOR_INSET_PX,
|
|
@@ -757,7 +826,9 @@ function getSideConnectorlessTopRange(layout) {
|
|
|
757
826
|
}
|
|
758
827
|
function isSidePlacementConnectorless(candidate, layout) {
|
|
759
828
|
if (layout.targetMode === 'auto') {
|
|
760
|
-
|
|
829
|
+
const connectorlessRange = getSideConnectorlessTopRange(layout);
|
|
830
|
+
return (candidate.top >= connectorlessRange.min &&
|
|
831
|
+
candidate.top <= connectorlessRange.max);
|
|
761
832
|
}
|
|
762
833
|
const arrowTipY = getSidePlacementArrowTipY(candidate.top, layout);
|
|
763
834
|
return (arrowTipY >=
|
package/dist/tooltip/types.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { Scatter } from '../scatter.js';
|
|
|
6
6
|
import type { TooltipTransitionConfig } from '../types.js';
|
|
7
7
|
export declare const TOOLTIP_OFFSET_PX = 12;
|
|
8
8
|
export declare const TOOLTIP_VIEWPORT_PADDING_PX = 10;
|
|
9
|
-
export declare const TOOLTIP_CONNECTOR_INSET_PX =
|
|
9
|
+
export declare const TOOLTIP_CONNECTOR_INSET_PX = 10;
|
|
10
10
|
export declare const TOOLTIP_CONNECTOR_MIN_PATH_LENGTH_PX = 16;
|
|
11
11
|
export declare const TOOLTIP_CONNECTOR_PADDING_PX = 4;
|
|
12
12
|
export declare const TOOLTIP_CONNECTOR_ELBOW_RATIO = 0.45;
|
|
@@ -20,7 +20,7 @@ export declare const TOOLTIP_ARROW_FILL_Z_INDEX = 5;
|
|
|
20
20
|
export declare const TOOLTIP_BODY_Z_INDEX = 6;
|
|
21
21
|
export declare const TOOLTIP_TOTAL_BORDER_WIDTH_PX: number;
|
|
22
22
|
export declare const TOOLTIP_ROOT_Z_INDEX = 30;
|
|
23
|
-
export declare const SPLIT_TOOLTIP_GAP_PX =
|
|
23
|
+
export declare const SPLIT_TOOLTIP_GAP_PX = 4;
|
|
24
24
|
export declare const DEFAULT_TOOLTIP_MAX_WIDTH_PX = 280;
|
|
25
25
|
export declare const DEFAULT_TOOLTIP_TRANSITION: Required<TooltipTransitionConfig>;
|
|
26
26
|
export declare const TOOLTIP_HIDDEN_TRANSFORM = "translateY(2px)";
|
package/dist/tooltip/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const TOOLTIP_OFFSET_PX = 12;
|
|
2
2
|
export const TOOLTIP_VIEWPORT_PADDING_PX = 10;
|
|
3
|
-
export const TOOLTIP_CONNECTOR_INSET_PX =
|
|
3
|
+
export const TOOLTIP_CONNECTOR_INSET_PX = 10;
|
|
4
4
|
export const TOOLTIP_CONNECTOR_MIN_PATH_LENGTH_PX = 16;
|
|
5
5
|
export const TOOLTIP_CONNECTOR_PADDING_PX = 4;
|
|
6
6
|
export const TOOLTIP_CONNECTOR_ELBOW_RATIO = 0.45;
|
|
@@ -14,7 +14,7 @@ export const TOOLTIP_ARROW_FILL_Z_INDEX = 5;
|
|
|
14
14
|
export const TOOLTIP_BODY_Z_INDEX = 6;
|
|
15
15
|
export const TOOLTIP_TOTAL_BORDER_WIDTH_PX = TOOLTIP_BORDER_WIDTH_PX * 2;
|
|
16
16
|
export const TOOLTIP_ROOT_Z_INDEX = 30;
|
|
17
|
-
export const SPLIT_TOOLTIP_GAP_PX =
|
|
17
|
+
export const SPLIT_TOOLTIP_GAP_PX = 4;
|
|
18
18
|
export const DEFAULT_TOOLTIP_MAX_WIDTH_PX = 280;
|
|
19
19
|
export const DEFAULT_TOOLTIP_TRANSITION = {
|
|
20
20
|
show: false,
|
package/package.json
CHANGED