@unovis/ts 1.6.0-bigip.0 → 1.6.0-bigip.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/crosshair/config.d.ts +6 -5
- package/components/crosshair/config.js +1 -1
- package/components/crosshair/config.js.map +1 -1
- package/components/crosshair/index.d.ts +6 -4
- package/components/crosshair/index.js +117 -118
- package/components/crosshair/index.js.map +1 -1
- package/components/timeline/index.js +3 -4
- package/components/timeline/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/index.js +1 -0
- package/styles/index.js.map +1 -1
- package/types/text.d.ts +1 -1
- package/types/text.js.map +1 -1
- package/utils/text.d.ts +1 -1
- package/utils/text.js +11 -7
- package/utils/text.js.map +1 -1
- package/components/crosshair/sync-bus.d.ts +0 -9
- package/components/crosshair/sync-bus.js +0 -27
- package/components/crosshair/sync-bus.js.map +0 -1
|
@@ -40,10 +40,11 @@ export interface CrosshairConfigInterface<Datum> extends WithOptional<XYComponen
|
|
|
40
40
|
* Default: `undefined`
|
|
41
41
|
*/
|
|
42
42
|
getCircles?: (x: number | Date | Date, data: Datum[], yScale: ContinuousScale) => CrosshairCircle[];
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
/** X position in data space (not pixels) for synchronized crosshair. Default: `undefined` */
|
|
44
|
+
xPosition?: number | Date;
|
|
45
|
+
/** Force show the crosshair even when mouse is not over the chart. Default: `false` */
|
|
46
|
+
forceShow?: boolean;
|
|
47
|
+
/** Callback function called when crosshair position changes. Receives x position in data space. Default: `undefined` */
|
|
48
|
+
onCrosshairMove?: (x: number | Date | undefined) => void;
|
|
48
49
|
}
|
|
49
50
|
export declare const CrosshairDefaultConfig: CrosshairConfigInterface<unknown>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { XYComponentDefaultConfig } from '../../core/xy-component/config.js';
|
|
2
2
|
|
|
3
|
-
const CrosshairDefaultConfig = Object.assign(Object.assign({}, XYComponentDefaultConfig), { yStacked: undefined, baseline: null, duration: 100, tooltip: undefined, template: (d, x) => '', hideWhenFarFromPointer: true, hideWhenFarFromPointerDistance: 100, snapToData: true, getCircles: undefined, color: undefined, strokeColor: undefined, strokeWidth: undefined,
|
|
3
|
+
const CrosshairDefaultConfig = Object.assign(Object.assign({}, XYComponentDefaultConfig), { yStacked: undefined, baseline: null, duration: 100, tooltip: undefined, template: (d, x) => '', hideWhenFarFromPointer: true, hideWhenFarFromPointerDistance: 100, snapToData: true, getCircles: undefined, color: undefined, strokeColor: undefined, strokeWidth: undefined, xPosition: undefined, forceShow: false, onCrosshairMove: undefined });
|
|
4
4
|
|
|
5
5
|
export { CrosshairDefaultConfig };
|
|
6
6
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sources":["../../../src/components/crosshair/config.ts"],"sourcesContent":["import { XYComponentConfigInterface, XYComponentDefaultConfig } from 'core/xy-component/config'\nimport { Tooltip } from 'components/tooltip'\n\n// Types\nimport { NumericAccessor, ColorAccessor } from 'types/accessor'\nimport { ContinuousScale } from 'types/scale'\nimport { WithOptional } from 'types/misc'\nimport { CrosshairCircle } from './types'\n\n// We extend partial XY config interface because x and y properties are optional for Crosshair\nexport interface CrosshairConfigInterface<Datum> extends WithOptional<XYComponentConfigInterface<Datum>, 'x' | 'y'> {\n /** Optional accessor function for getting the values along the X axis. Default: `undefined` */\n x?: NumericAccessor<Datum>;\n /** Optional single of multiple accessor functions for getting the values along the Y axis. Default: `undefined` */\n y?: NumericAccessor<Datum> | NumericAccessor<Datum>[];\n /** Optional color array or color accessor function for crosshair circles. Default: `d => d.color` */\n color?: ColorAccessor<Datum>;\n /** Optional stroke color accessor function for crosshair circles. Default: `undefined` */\n strokeColor?: ColorAccessor<Datum>;\n /** Optional stroke width for crosshair circles. Default: `undefined` */\n strokeWidth?: NumericAccessor<Datum>;\n /** Separate array of accessors for stacked components (eg StackedBar, Area). Default: `undefined` */\n yStacked?: NumericAccessor<Datum>[];\n /** Baseline accessor function for stacked values, useful with stacked areas. Default: `null` */\n baseline?: NumericAccessor<Datum>;\n /** An instance of the Tooltip component to be used with Crosshair. Default: `undefined` */\n tooltip?: Tooltip | undefined;\n /** Tooltip template accessor. The function is supposed to return either a valid HTML string or an HTMLElement. Default: `d => ''` */\n template?: (data: Datum, x: number | Date) => string | HTMLElement;\n /** Hide Crosshair when the corresponding element is far from mouse pointer. Default: `true` */\n hideWhenFarFromPointer?: boolean;\n /** Distance in pixels to check in the hideWhenFarFromPointer condition. Default: `100` */\n hideWhenFarFromPointerDistance?: number;\n /** Snap to the nearest data point.\n * If disabled, the tooltip template will receive only the horizontal position of the crosshair and you'll be responsible\n * for getting the underlying data records and crosshair circles (see the `getCircles` configuration option).\n * Default: `true`\n */\n snapToData?: boolean;\n /** Custom function for setting up the crosshair circles, usually needed when `snapToData` is set to `false`.\n * The function receives the horizontal position of the crosshair (in the data space, not in pixels), the data array\n * and the `yScale` instance to help you calculate the correct vertical position of the circles.\n * It has to return an array of the CrosshairCircle objects: `{ y: number; color: string; opacity?: number }[]`.\n * Default: `undefined`\n */\n getCircles?: (x: number | Date | Date, data: Datum[], yScale: ContinuousScale) => CrosshairCircle[];\n
|
|
1
|
+
{"version":3,"file":"config.js","sources":["../../../src/components/crosshair/config.ts"],"sourcesContent":["import { XYComponentConfigInterface, XYComponentDefaultConfig } from 'core/xy-component/config'\nimport { Tooltip } from 'components/tooltip'\n\n// Types\nimport { NumericAccessor, ColorAccessor } from 'types/accessor'\nimport { ContinuousScale } from 'types/scale'\nimport { WithOptional } from 'types/misc'\nimport { CrosshairCircle } from './types'\n\n// We extend partial XY config interface because x and y properties are optional for Crosshair\nexport interface CrosshairConfigInterface<Datum> extends WithOptional<XYComponentConfigInterface<Datum>, 'x' | 'y'> {\n /** Optional accessor function for getting the values along the X axis. Default: `undefined` */\n x?: NumericAccessor<Datum>;\n /** Optional single of multiple accessor functions for getting the values along the Y axis. Default: `undefined` */\n y?: NumericAccessor<Datum> | NumericAccessor<Datum>[];\n /** Optional color array or color accessor function for crosshair circles. Default: `d => d.color` */\n color?: ColorAccessor<Datum>;\n /** Optional stroke color accessor function for crosshair circles. Default: `undefined` */\n strokeColor?: ColorAccessor<Datum>;\n /** Optional stroke width for crosshair circles. Default: `undefined` */\n strokeWidth?: NumericAccessor<Datum>;\n /** Separate array of accessors for stacked components (eg StackedBar, Area). Default: `undefined` */\n yStacked?: NumericAccessor<Datum>[];\n /** Baseline accessor function for stacked values, useful with stacked areas. Default: `null` */\n baseline?: NumericAccessor<Datum>;\n /** An instance of the Tooltip component to be used with Crosshair. Default: `undefined` */\n tooltip?: Tooltip | undefined;\n /** Tooltip template accessor. The function is supposed to return either a valid HTML string or an HTMLElement. Default: `d => ''` */\n template?: (data: Datum, x: number | Date) => string | HTMLElement;\n /** Hide Crosshair when the corresponding element is far from mouse pointer. Default: `true` */\n hideWhenFarFromPointer?: boolean;\n /** Distance in pixels to check in the hideWhenFarFromPointer condition. Default: `100` */\n hideWhenFarFromPointerDistance?: number;\n /** Snap to the nearest data point.\n * If disabled, the tooltip template will receive only the horizontal position of the crosshair and you'll be responsible\n * for getting the underlying data records and crosshair circles (see the `getCircles` configuration option).\n * Default: `true`\n */\n snapToData?: boolean;\n /** Custom function for setting up the crosshair circles, usually needed when `snapToData` is set to `false`.\n * The function receives the horizontal position of the crosshair (in the data space, not in pixels), the data array\n * and the `yScale` instance to help you calculate the correct vertical position of the circles.\n * It has to return an array of the CrosshairCircle objects: `{ y: number; color: string; opacity?: number }[]`.\n * Default: `undefined`\n */\n getCircles?: (x: number | Date | Date, data: Datum[], yScale: ContinuousScale) => CrosshairCircle[];\n /** X position in data space (not pixels) for synchronized crosshair. Default: `undefined` */\n xPosition?: number | Date;\n /** Force show the crosshair even when mouse is not over the chart. Default: `false` */\n forceShow?: boolean;\n /** Callback function called when crosshair position changes. Receives x position in data space. Default: `undefined` */\n onCrosshairMove?: (x: number | Date | undefined) => void;\n}\n\nexport const CrosshairDefaultConfig: CrosshairConfigInterface<unknown> = {\n ...XYComponentDefaultConfig,\n yStacked: undefined,\n baseline: null,\n duration: 100,\n tooltip: undefined,\n template: <Datum>(d: Datum, x: number | Date): string => '',\n hideWhenFarFromPointer: true,\n hideWhenFarFromPointerDistance: 100,\n snapToData: true,\n getCircles: undefined,\n color: undefined,\n strokeColor: undefined,\n strokeWidth: undefined,\n xPosition: undefined,\n forceShow: false,\n onCrosshairMove: undefined,\n}\n\n"],"names":[],"mappings":";;AAsDO,MAAM,sBAAsB,GAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAC9B,wBAAwB,CAC3B,EAAA,EAAA,QAAQ,EAAE,SAAS,EACnB,QAAQ,EAAE,IAAI,EACd,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,CAAQ,CAAQ,EAAE,CAAgB,KAAa,EAAE,EAC3D,sBAAsB,EAAE,IAAI,EAC5B,8BAA8B,EAAE,GAAG,EACnC,UAAU,EAAE,IAAI,EAChB,UAAU,EAAE,SAAS,EACrB,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,SAAS,EACtB,WAAW,EAAE,SAAS,EACtB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,KAAK,EAChB,eAAe,EAAE,SAAS;;;;"}
|
|
@@ -16,9 +16,8 @@ export declare class Crosshair<Datum> extends XYComponentCore<Datum, CrosshairCo
|
|
|
16
16
|
datumIndex: number;
|
|
17
17
|
show: boolean;
|
|
18
18
|
private _animFrameId;
|
|
19
|
-
private
|
|
20
|
-
private
|
|
21
|
-
private _isSyncActive;
|
|
19
|
+
private _dataX;
|
|
20
|
+
private _isMouseOver;
|
|
22
21
|
/** Tooltip component to be used by Crosshair if not provided by the config.
|
|
23
22
|
* This property is supposed to be set externally by a container component like XYContainer. */
|
|
24
23
|
tooltip: Tooltip;
|
|
@@ -28,14 +27,17 @@ export declare class Crosshair<Datum> extends XYComponentCore<Datum, CrosshairCo
|
|
|
28
27
|
get accessors(): CrosshairAccessors<Datum>;
|
|
29
28
|
constructor(config?: CrosshairConfigInterface<Datum>);
|
|
30
29
|
setContainer(containerSvg: Selection<SVGSVGElement, unknown, SVGSVGElement, unknown>): void;
|
|
30
|
+
setConfig(config: CrosshairConfigInterface<Datum>): void;
|
|
31
31
|
_render(customDuration?: number): void;
|
|
32
32
|
hide(): void;
|
|
33
33
|
destroy(): void;
|
|
34
34
|
_onMouseMove(event: MouseEvent): void;
|
|
35
|
+
private _processMouseMove;
|
|
35
36
|
_onMouseOut(): void;
|
|
36
|
-
_showTooltip(event
|
|
37
|
+
_showTooltip(event: MouseEvent): void;
|
|
37
38
|
_hideTooltip(): void;
|
|
38
39
|
getYDataExtent(): number[];
|
|
39
40
|
private getCircleData;
|
|
40
41
|
_updateFromSync(xData: number | Date | undefined): void;
|
|
42
|
+
private _getSyncState;
|
|
41
43
|
}
|
|
@@ -8,17 +8,7 @@ import { Position } from '../../types/position.js';
|
|
|
8
8
|
import { CrosshairDefaultConfig } from './config.js';
|
|
9
9
|
import * as style from './style.js';
|
|
10
10
|
import { line, circle } from './style.js';
|
|
11
|
-
import { crosshairSyncBus } from './sync-bus.js';
|
|
12
11
|
|
|
13
|
-
function isInDomain(x, xDomain) {
|
|
14
|
-
if (!Array.isArray(xDomain) || xDomain.length < 2)
|
|
15
|
-
return false;
|
|
16
|
-
// Convert everything to numbers for comparison
|
|
17
|
-
const xVal = typeof x === 'number' ? x : (x instanceof Date ? x.getTime() : new Date(x).getTime());
|
|
18
|
-
const d0 = +xDomain[0];
|
|
19
|
-
const d1 = +xDomain[xDomain.length - 1];
|
|
20
|
-
return xVal >= d0 && xVal <= d1;
|
|
21
|
-
}
|
|
22
12
|
class Crosshair extends XYComponentCore {
|
|
23
13
|
constructor(config) {
|
|
24
14
|
super();
|
|
@@ -28,9 +18,8 @@ class Crosshair extends XYComponentCore {
|
|
|
28
18
|
this.x = 0;
|
|
29
19
|
this.show = false;
|
|
30
20
|
this._animFrameId = null;
|
|
31
|
-
this.
|
|
32
|
-
this.
|
|
33
|
-
this._isSyncActive = false; // true if this chart is the one broadcasting
|
|
21
|
+
this._dataX = undefined;
|
|
22
|
+
this._isMouseOver = false;
|
|
34
23
|
/** Accessors passed externally (e.g. from XYContainer) */
|
|
35
24
|
this._accessors = {
|
|
36
25
|
x: undefined,
|
|
@@ -61,23 +50,22 @@ class Crosshair extends XYComponentCore {
|
|
|
61
50
|
this.container.on('mousemove.crosshair', this._onMouseMove.bind(this));
|
|
62
51
|
this.container.on('mouseout.crosshair', this._onMouseOut.bind(this));
|
|
63
52
|
this._render();
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
};
|
|
72
|
-
crosshairSyncBus.subscribe(this.config.syncId, this._syncListener);
|
|
53
|
+
}
|
|
54
|
+
setConfig(config) {
|
|
55
|
+
super.setConfig(config);
|
|
56
|
+
// For synchronized charts, update from sync when config changes
|
|
57
|
+
const { isActive, enableSync } = this._getSyncState();
|
|
58
|
+
if (enableSync && !isActive && (isNumber(config.xPosition) || config.xPosition instanceof Date)) {
|
|
59
|
+
this._updateFromSync(config.xPosition);
|
|
73
60
|
}
|
|
74
61
|
}
|
|
75
62
|
_render(customDuration) {
|
|
76
63
|
const { config } = this;
|
|
77
64
|
const duration = isNumber(customDuration) ? customDuration : config.duration;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
65
|
+
const { isActive, enableSync } = this._getSyncState();
|
|
66
|
+
// Handle synchronized charts with xPosition prop
|
|
67
|
+
if (enableSync && !isActive && (isNumber(config.xPosition) || config.xPosition instanceof Date)) {
|
|
68
|
+
this._updateFromSync(config.xPosition);
|
|
81
69
|
}
|
|
82
70
|
smartTransition(this.g, duration).style('opacity', this.show ? 1 : 0);
|
|
83
71
|
this.line
|
|
@@ -118,17 +106,35 @@ class Crosshair extends XYComponentCore {
|
|
|
118
106
|
this._animFrameId = null;
|
|
119
107
|
}
|
|
120
108
|
this._hideTooltip();
|
|
121
|
-
// --- SYNC: unsubscribe if needed ---
|
|
122
|
-
if (this.config.syncId && this._syncListener) {
|
|
123
|
-
crosshairSyncBus.unsubscribe(this.config.syncId, this._syncListener);
|
|
124
|
-
this._syncListener = null;
|
|
125
|
-
}
|
|
126
109
|
}
|
|
127
110
|
_onMouseMove(event) {
|
|
111
|
+
// Throttle the entire mouse move processing
|
|
112
|
+
if (this._animFrameId)
|
|
113
|
+
return;
|
|
114
|
+
this._animFrameId = window.requestAnimationFrame(() => {
|
|
115
|
+
this._processMouseMove(event);
|
|
116
|
+
this._animFrameId = null;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
_processMouseMove(event) {
|
|
128
120
|
var _a, _b;
|
|
121
|
+
this._isMouseOver = true;
|
|
129
122
|
const { config, datamodel, element } = this;
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
const { isActive, enableSync } = this._getSyncState();
|
|
124
|
+
// Early return for synchronized non-active charts, but allow tooltip display
|
|
125
|
+
if (enableSync && !isActive) {
|
|
126
|
+
if (this.show && this.datum) {
|
|
127
|
+
this._showTooltip(event);
|
|
128
|
+
}
|
|
129
|
+
else if (this.show && this._dataX !== undefined && isNumber(this._dataX)) {
|
|
130
|
+
// For synchronized charts, find the datum if it doesn't exist
|
|
131
|
+
this.datum = getNearest(this.datamodel.data, this._dataX, this.accessors.x);
|
|
132
|
+
if (this.datum) {
|
|
133
|
+
this._showTooltip(event);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
132
138
|
// Check if we have the necessary accessors
|
|
133
139
|
if (!this.accessors.x && ((_a = datamodel.data) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
134
140
|
console.warn('Unovis | Crosshair: X accessor function has not been configured. Please check if it\'s present in the configuration object');
|
|
@@ -149,82 +155,53 @@ class Crosshair extends XYComponentCore {
|
|
|
149
155
|
return;
|
|
150
156
|
const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex);
|
|
151
157
|
this.x = clamp(Math.round(scaleX(dataX)), 0, this._width);
|
|
152
|
-
this.
|
|
158
|
+
this._dataX = dataX;
|
|
153
159
|
// Show the crosshair only if it's in the chart range and not far from mouse pointer (if configured)
|
|
154
160
|
this.show = (this.x >= 0) && (this.x <= this._width) && (!config.hideWhenFarFromPointer || (Math.abs(this.x - x) < config.hideWhenFarFromPointerDistance));
|
|
155
|
-
// Emit to sync bus if configured
|
|
156
|
-
if (config.syncId) {
|
|
157
|
-
const xDomain = this.xScale.domain();
|
|
158
|
-
if (isInDomain(dataX, xDomain)) {
|
|
159
|
-
crosshairSyncBus.emit(config.syncId, dataX);
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
crosshairSyncBus.emit(config.syncId, undefined);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
161
|
}
|
|
166
162
|
else {
|
|
167
163
|
const tolerance = 2; // Show the crosshair when it is at least 2 pixels close to the chart area
|
|
168
164
|
this.x = clamp(x, xRange[0], xRange[1]);
|
|
169
|
-
this.
|
|
165
|
+
this._dataX = this.xScale.invert(this.x);
|
|
170
166
|
this.show = (x >= (xRange[0] - tolerance)) && (x <= (xRange[1] + tolerance));
|
|
171
167
|
}
|
|
172
|
-
|
|
173
|
-
this.
|
|
174
|
-
this.
|
|
175
|
-
}
|
|
168
|
+
// Call onCrosshairMove callback if provided
|
|
169
|
+
if (this.show && config.onCrosshairMove && this._dataX !== undefined) {
|
|
170
|
+
config.onCrosshairMove(this._dataX);
|
|
171
|
+
}
|
|
172
|
+
// Render immediately since we're already in a throttled context
|
|
173
|
+
this._render();
|
|
176
174
|
if (this.show)
|
|
177
175
|
this._showTooltip(event);
|
|
178
176
|
else
|
|
179
177
|
this._hideTooltip();
|
|
180
178
|
}
|
|
181
179
|
_onMouseOut() {
|
|
180
|
+
this._isMouseOver = false;
|
|
182
181
|
const { config } = this;
|
|
183
|
-
//
|
|
184
|
-
if (config.syncId && this._isSyncActive) {
|
|
185
|
-
crosshairSyncBus.emit(config.syncId, undefined);
|
|
186
|
-
}
|
|
187
|
-
this._isSyncActive = false;
|
|
188
|
-
// Hide crosshair and tooltip
|
|
182
|
+
// Always hide on mouse out
|
|
189
183
|
this.show = false;
|
|
190
184
|
this._hideTooltip();
|
|
191
|
-
|
|
185
|
+
// Throttle rendering using requestAnimationFrame
|
|
186
|
+
if (this._animFrameId)
|
|
187
|
+
return;
|
|
192
188
|
this._animFrameId = window.requestAnimationFrame(() => {
|
|
193
189
|
this._render();
|
|
190
|
+
this._animFrameId = null;
|
|
194
191
|
});
|
|
192
|
+
// If this is the active chart, notify parent to clear sync state
|
|
193
|
+
if (config.onCrosshairMove) {
|
|
194
|
+
config.onCrosshairMove(undefined);
|
|
195
|
+
}
|
|
195
196
|
}
|
|
196
197
|
_showTooltip(event) {
|
|
197
198
|
var _a;
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
if (!tooltip) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
// For synchronized charts, we need to find the datum if it doesn't exist
|
|
204
|
-
let datum = this.datum;
|
|
205
|
-
if (!datum && config.syncId && !this._isSyncActive && this._currentXData !== undefined) {
|
|
206
|
-
// Find the datum at the current x position (only for number values)
|
|
207
|
-
if (typeof this._currentXData === 'number') {
|
|
208
|
-
datum = getNearest(this.datamodel.data, this._currentXData, this.accessors.x);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
if (!datum) {
|
|
199
|
+
const tooltip = (_a = this.config.tooltip) !== null && _a !== void 0 ? _a : this.tooltip;
|
|
200
|
+
if (!tooltip || !this.datum)
|
|
212
201
|
return;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// Use actual mouse event
|
|
217
|
-
const container = tooltip.getContainer() || this.container.node();
|
|
218
|
-
[x, y] = tooltip.isContainerBody() ? [event.clientX, event.clientY] : pointer(event, container);
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
// Use synthetic event for sync
|
|
222
|
-
const containerRect = this.container.node().getBoundingClientRect();
|
|
223
|
-
x = tooltip.isContainerBody() ? containerRect.left + this.x : this.x;
|
|
224
|
-
y = tooltip.isContainerBody() ? containerRect.top + this._height / 2 : this._height / 2;
|
|
225
|
-
}
|
|
226
|
-
const content = config.template(datum, this._currentXData || this.xScale.invert(this.x));
|
|
227
|
-
// Force set `followCursor` to `true` because we don't want Crosshair's tooltip to be hoverable
|
|
202
|
+
const container = tooltip.getContainer() || this.container.node();
|
|
203
|
+
const [x, y] = tooltip.isContainerBody() ? [event.clientX, event.clientY] : pointer(event, container);
|
|
204
|
+
const content = this.config.template(this.datum, this._dataX || this.xScale.invert(this.x));
|
|
228
205
|
tooltip.config.followCursor = true;
|
|
229
206
|
// Set tooltip placement based on Crosshair's position (left / right)
|
|
230
207
|
if (!tooltip.config.horizontalPlacement || tooltip.config.horizontalPlacement === Position.Auto) {
|
|
@@ -236,30 +213,30 @@ class Crosshair extends XYComponentCore {
|
|
|
236
213
|
}
|
|
237
214
|
_hideTooltip() {
|
|
238
215
|
var _a;
|
|
239
|
-
const
|
|
240
|
-
const tooltip = (_a = config.tooltip) !== null && _a !== void 0 ? _a : this.tooltip;
|
|
216
|
+
const tooltip = (_a = this.config.tooltip) !== null && _a !== void 0 ? _a : this.tooltip;
|
|
241
217
|
tooltip === null || tooltip === void 0 ? void 0 : tooltip.hide();
|
|
242
218
|
}
|
|
243
|
-
// We don't want Crosshair to be
|
|
219
|
+
// We don't want Crosshair to be taken into account in domain calculations
|
|
244
220
|
getYDataExtent() {
|
|
245
221
|
return [undefined, undefined];
|
|
246
222
|
}
|
|
247
223
|
getCircleData() {
|
|
248
224
|
var _a, _b;
|
|
249
|
-
const {
|
|
250
|
-
|
|
251
|
-
|
|
225
|
+
const { datamodel: { data } } = this;
|
|
226
|
+
const { isActive, enableSync } = this._getSyncState();
|
|
227
|
+
if (isFunction(this.config.getCircles)) {
|
|
228
|
+
return this.config.getCircles(this._dataX || this.xScale.invert(this.x), data, this.yScale);
|
|
229
|
+
}
|
|
252
230
|
// Get the datum - either from active mode or from synchronized mode
|
|
253
231
|
let datum = this.datum;
|
|
254
232
|
let datumIndex = this.datumIndex;
|
|
255
|
-
if (!datum &&
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
datum = getNearest(this.datamodel.data, this._currentXData, this.accessors.x);
|
|
233
|
+
if (!datum && enableSync && !isActive && this._dataX !== undefined) {
|
|
234
|
+
if (isNumber(this._dataX)) {
|
|
235
|
+
datum = getNearest(this.datamodel.data, this._dataX, this.accessors.x);
|
|
259
236
|
datumIndex = this.datamodel.data.indexOf(datum);
|
|
260
237
|
}
|
|
261
238
|
}
|
|
262
|
-
if (config.snapToData && datum) {
|
|
239
|
+
if (this.config.snapToData && datum) {
|
|
263
240
|
const yAccessors = (_a = this.accessors.y) !== null && _a !== void 0 ? _a : [];
|
|
264
241
|
const yStackedAccessors = (_b = this.accessors.yStacked) !== null && _b !== void 0 ? _b : [];
|
|
265
242
|
const baselineValue = getNumber(datum, this.accessors.baseline, datumIndex) || 0;
|
|
@@ -269,10 +246,10 @@ class Crosshair extends XYComponentCore {
|
|
|
269
246
|
const yPixel = this.yScale(yValue);
|
|
270
247
|
return {
|
|
271
248
|
y: yPixel,
|
|
272
|
-
opacity: 1,
|
|
273
|
-
color: getColor(datum, config.color, index),
|
|
274
|
-
strokeColor: config.strokeColor ? getColor(datum, config.strokeColor, index) : undefined,
|
|
275
|
-
strokeWidth: config.strokeWidth ? getNumber(datum, config.strokeWidth, index) : undefined,
|
|
249
|
+
opacity: isNumber(getNumber(datum, yStackedAccessors[index])) ? 1 : 1,
|
|
250
|
+
color: getColor(datum, this.config.color, index),
|
|
251
|
+
strokeColor: this.config.strokeColor ? getColor(datum, this.config.strokeColor, index) : undefined,
|
|
252
|
+
strokeWidth: this.config.strokeWidth ? getNumber(datum, this.config.strokeWidth, index) : undefined,
|
|
276
253
|
};
|
|
277
254
|
});
|
|
278
255
|
const regularValues = yAccessors
|
|
@@ -282,9 +259,9 @@ class Crosshair extends XYComponentCore {
|
|
|
282
259
|
return {
|
|
283
260
|
y: yPixel,
|
|
284
261
|
opacity: isNumber(value) ? 1 : 0,
|
|
285
|
-
color: getColor(datum, config.color, stackedValues.length + index),
|
|
286
|
-
strokeColor: config.strokeColor ? getColor(datum, config.strokeColor, index) : undefined,
|
|
287
|
-
strokeWidth: config.strokeWidth ? getNumber(datum, config.strokeWidth, index) : undefined,
|
|
262
|
+
color: getColor(datum, this.config.color, stackedValues.length + index),
|
|
263
|
+
strokeColor: this.config.strokeColor ? getColor(datum, this.config.strokeColor, index) : undefined,
|
|
264
|
+
strokeWidth: this.config.strokeWidth ? getNumber(datum, this.config.strokeWidth, index) : undefined,
|
|
288
265
|
};
|
|
289
266
|
});
|
|
290
267
|
return stackedValues.concat(regularValues);
|
|
@@ -294,39 +271,50 @@ class Crosshair extends XYComponentCore {
|
|
|
294
271
|
}
|
|
295
272
|
_updateFromSync(xData) {
|
|
296
273
|
var _a;
|
|
297
|
-
const {
|
|
298
|
-
if (!
|
|
274
|
+
const { isActive, enableSync } = this._getSyncState();
|
|
275
|
+
if (!enableSync || isActive)
|
|
299
276
|
return;
|
|
300
|
-
}
|
|
301
277
|
// Handle mouse out signal
|
|
302
278
|
if (xData === undefined) {
|
|
303
279
|
this.show = false;
|
|
304
280
|
this._hideTooltip();
|
|
305
281
|
return;
|
|
306
282
|
}
|
|
307
|
-
if (!this.accessors.x || !((_a = datamodel.data) === null || _a === void 0 ? void 0 : _a.length))
|
|
283
|
+
if (!this.accessors.x || !((_a = this.datamodel.data) === null || _a === void 0 ? void 0 : _a.length))
|
|
308
284
|
return;
|
|
309
|
-
|
|
310
|
-
// --- DOMAIN CHECK (on passive chart, use xData directly) ---
|
|
285
|
+
// Check if xPosition is within the chart's x domain
|
|
311
286
|
const xDomain = this.xScale.domain();
|
|
312
|
-
|
|
287
|
+
let xValue;
|
|
288
|
+
if (typeof xData === 'number') {
|
|
289
|
+
xValue = xData;
|
|
290
|
+
}
|
|
291
|
+
else if (xData instanceof Date) {
|
|
292
|
+
xValue = xData.getTime();
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
this.show = false;
|
|
296
|
+
this._hideTooltip();
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
// If xPosition is outside the chart's domain, hide the crosshair
|
|
300
|
+
const domainMin = typeof xDomain[0] === 'number' ? xDomain[0] : (xDomain[0] instanceof Date ? xDomain[0].getTime() : 0);
|
|
301
|
+
const domainMax = typeof xDomain[1] === 'number' ? xDomain[1] : (xDomain[1] instanceof Date ? xDomain[1].getTime() : 0);
|
|
302
|
+
if (xValue < domainMin || xValue > domainMax) {
|
|
313
303
|
this.show = false;
|
|
314
304
|
this._hideTooltip();
|
|
315
305
|
return;
|
|
316
306
|
}
|
|
317
|
-
// --- END DOMAIN CHECK ---
|
|
318
307
|
// Find the datum at this x position
|
|
319
308
|
if (typeof xData === 'number') {
|
|
320
|
-
this.datum = getNearest(datamodel.data, xData, this.accessors.x);
|
|
309
|
+
this.datum = getNearest(this.datamodel.data, xData, this.accessors.x);
|
|
321
310
|
}
|
|
322
|
-
else if (xData instanceof Date
|
|
323
|
-
|
|
324
|
-
this.datum = getNearest(datamodel.data, xVal, this.accessors.x);
|
|
311
|
+
else if (xData instanceof Date) {
|
|
312
|
+
this.datum = getNearest(this.datamodel.data, xData.getTime(), this.accessors.x);
|
|
325
313
|
}
|
|
326
314
|
else {
|
|
327
315
|
this.datum = undefined;
|
|
328
316
|
}
|
|
329
|
-
this.datumIndex = datamodel.data.indexOf(this.datum);
|
|
317
|
+
this.datumIndex = this.datamodel.data.indexOf(this.datum);
|
|
330
318
|
// If no datum found, hide the crosshair
|
|
331
319
|
if (!this.datum) {
|
|
332
320
|
this.show = false;
|
|
@@ -335,11 +323,22 @@ class Crosshair extends XYComponentCore {
|
|
|
335
323
|
}
|
|
336
324
|
const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex);
|
|
337
325
|
this.x = clamp(Math.round(this.xScale(dataX)), 0, this._width);
|
|
338
|
-
this.
|
|
326
|
+
this._dataX = dataX;
|
|
339
327
|
// Show the crosshair
|
|
340
328
|
this.show = true;
|
|
341
|
-
// Show tooltip for synchronized chart
|
|
342
|
-
|
|
329
|
+
// Show tooltip for synchronized chart using the same logic as active charts
|
|
330
|
+
const syntheticEvent = {
|
|
331
|
+
clientX: this.container.node().getBoundingClientRect().left + this.x,
|
|
332
|
+
clientY: this.container.node().getBoundingClientRect().top + this._height / 2,
|
|
333
|
+
};
|
|
334
|
+
this._showTooltip(syntheticEvent);
|
|
335
|
+
}
|
|
336
|
+
_getSyncState() {
|
|
337
|
+
// A chart is active if it's being hovered and doesn't have external sync props
|
|
338
|
+
const isActive = this._isMouseOver && !isNumber(this.config.xPosition) && !this.config.forceShow;
|
|
339
|
+
// A chart is in sync mode if it has external sync props (regardless of mouse state)
|
|
340
|
+
const enableSync = isNumber(this.config.xPosition) || !!this.config.forceShow;
|
|
341
|
+
return { isActive, enableSync };
|
|
343
342
|
}
|
|
344
343
|
}
|
|
345
344
|
Crosshair.selectors = style;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/crosshair/index.ts"],"sourcesContent":["import { Selection, pointer } from 'd3-selection'\nimport { easeLinear } from 'd3-ease'\n\n// Core\nimport { XYComponentCore } from 'core/xy-component'\nimport { Tooltip } from 'components/tooltip'\n\n// Utils\nimport { isNumber, isArray, getNumber, clamp, getStackedValues, getNearest, isFunction } from 'utils/data'\nimport { smartTransition } from 'utils/d3'\nimport { getColor } from 'utils/color'\n\n// Types\nimport { Position } from 'types/position'\n\n// Local Types\nimport { CrosshairAccessors, CrosshairCircle } from './types'\n\n// Config\nimport { CrosshairDefaultConfig, CrosshairConfigInterface } from './config'\n\n// Styles\nimport * as s from './style'\n\nimport { crosshairSyncBus, CrosshairSyncListener } from './sync-bus'\n\nfunction isInDomain (x: number | Date | string, xDomain: (number | Date)[]): boolean {\n if (!Array.isArray(xDomain) || xDomain.length < 2) return false\n\n // Convert everything to numbers for comparison\n const xVal = typeof x === 'number' ? x : (x instanceof Date ? x.getTime() : new Date(x).getTime())\n const d0 = +xDomain[0]\n const d1 = +xDomain[xDomain.length - 1]\n\n return xVal >= d0 && xVal <= d1\n}\n\nexport class Crosshair<Datum> extends XYComponentCore<Datum, CrosshairConfigInterface<Datum>> {\n static selectors = s\n clippable = true // Don't apply clipping path to this component. See XYContainer\n protected _defaultConfig = CrosshairDefaultConfig as CrosshairConfigInterface<Datum>\n public config: CrosshairConfigInterface<Datum> = this._defaultConfig\n container: Selection<SVGSVGElement, any, SVGSVGElement, any>\n line: Selection<SVGLineElement, any, SVGElement, any>\n x = 0\n datum: Datum\n datumIndex: number\n show = false\n private _animFrameId: number = null\n private _currentXData: number | Date | undefined = undefined\n\n private _syncListener: CrosshairSyncListener | null = null\n private _isSyncActive = false // true if this chart is the one broadcasting\n\n /** Tooltip component to be used by Crosshair if not provided by the config.\n * This property is supposed to be set externally by a container component like XYContainer. */\n public tooltip: Tooltip\n\n /** Accessors passed externally (e.g. from XYContainer) */\n private _accessors: CrosshairAccessors<Datum> = {\n x: undefined,\n y: undefined,\n yStacked: undefined,\n baseline: undefined,\n }\n\n public set accessors (accessors: CrosshairAccessors<Datum>) { this._accessors = accessors }\n public get accessors (): CrosshairAccessors<Datum> {\n const { config } = this\n // If x or y are explicitly set in config, use those; otherwise use container accessors\n const x = config.x || this._accessors.x\n const yAcc = config.y || this._accessors.y\n const y = yAcc ? (isArray(yAcc) ? yAcc : [yAcc]) : undefined\n const yStacked = config.yStacked || this._accessors.yStacked\n const baseline = config.baseline ?? this._accessors.baseline\n\n return { x, y, yStacked, baseline }\n }\n\n constructor (config?: CrosshairConfigInterface<Datum>) {\n super()\n if (config) this.config = { ...this.config, ...config }\n\n this.g.style('opacity', this.show ? 1 : 0)\n this.line = this.g.append('line')\n .attr('class', s.line)\n }\n\n setContainer (containerSvg: Selection<SVGSVGElement, unknown, SVGSVGElement, unknown>): void {\n this.container = containerSvg\n this.container.on('mousemove.crosshair', this._onMouseMove.bind(this))\n this.container.on('mouseout.crosshair', this._onMouseOut.bind(this))\n this._render()\n\n // --- SYNC: subscribe if needed ---\n if (this.config.syncId) {\n this._syncListener = (x) => {\n if (!this._isSyncActive) {\n this._updateFromSync(x)\n window.requestAnimationFrame(() => this._render())\n }\n }\n crosshairSyncBus.subscribe(this.config.syncId, this._syncListener)\n }\n }\n\n _render (customDuration?: number): void {\n const { config } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\n\n // --- SYNC: update from sync bus if not active ---\n if (config.syncId && !this._isSyncActive) {\n // _updateFromSync is called by the bus\n }\n\n smartTransition(this.g, duration).style('opacity', this.show ? 1 : 0)\n this.line\n .attr('y1', 0)\n .attr('y2', this._height)\n smartTransition(this.line, duration, easeLinear)\n .attr('x1', this.x)\n .attr('x2', this.x)\n const circleData = this.getCircleData()\n const circles = this.g\n .selectAll<SVGCircleElement, CrosshairCircle>('circle')\n .data(circleData, (d, i) => d.id ?? i)\n const circlesEnter = circles.enter()\n .append('circle')\n .attr('class', s.circle)\n .attr('r', 0)\n .attr('cx', this.x)\n .attr('cy', d => d.y)\n .style('fill', d => d.color)\n .style('stroke', d => d.strokeColor)\n .style('stroke-width', d => d.strokeWidth)\n smartTransition(circlesEnter.merge(circles), duration, easeLinear)\n .attr('cx', this.x)\n .attr('cy', d => d.y)\n .attr('r', 4)\n .style('opacity', d => d.opacity)\n .style('fill', d => d.color)\n .style('stroke', d => d.strokeColor)\n .style('stroke-width', d => d.strokeWidth)\n circles.exit().remove()\n }\n\n hide (): void {\n this._onMouseOut()\n }\n\n destroy (): void {\n if (this._animFrameId) {\n window.cancelAnimationFrame(this._animFrameId)\n this._animFrameId = null\n }\n this._hideTooltip()\n // --- SYNC: unsubscribe if needed ---\n if (this.config.syncId && this._syncListener) {\n crosshairSyncBus.unsubscribe(this.config.syncId, this._syncListener)\n this._syncListener = null\n }\n }\n\n _onMouseMove (event: MouseEvent): void {\n const { config, datamodel, element } = this\n\n // Set sync active state\n this._isSyncActive = !!config.syncId\n\n // Check if we have the necessary accessors\n if (!this.accessors.x && datamodel.data?.length) {\n console.warn('Unovis | Crosshair: X accessor function has not been configured. Please check if it\\'s present in the configuration object')\n return\n }\n\n const [x] = pointer(event, element)\n const xRange = this.xScale.range()\n\n if (config.snapToData) {\n if (!this.accessors.y && !this.accessors.yStacked && datamodel.data?.length) {\n console.warn('Unovis | Crosshair: Y accessors have not been configured. Please check if they\\'re present in the configuration object')\n return\n }\n const scaleX = this.xScale\n const valueX = scaleX.invert(x) as number\n\n this.datum = getNearest(datamodel.data, valueX, this.accessors.x)\n this.datumIndex = datamodel.data.indexOf(this.datum)\n if (!this.datum) return\n\n const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex)\n this.x = clamp(Math.round(scaleX(dataX)), 0, this._width)\n this._currentXData = dataX\n\n // Show the crosshair only if it's in the chart range and not far from mouse pointer (if configured)\n this.show = (this.x >= 0) && (this.x <= this._width) && (!config.hideWhenFarFromPointer || (Math.abs(this.x - x) < config.hideWhenFarFromPointerDistance))\n\n // Emit to sync bus if configured\n if (config.syncId) {\n const xDomain = this.xScale.domain()\n if (isInDomain(dataX, xDomain)) {\n crosshairSyncBus.emit(config.syncId, dataX)\n } else {\n crosshairSyncBus.emit(config.syncId, undefined)\n }\n }\n } else {\n const tolerance = 2 // Show the crosshair when it is at least 2 pixels close to the chart area\n this.x = clamp(x, xRange[0], xRange[1])\n this._currentXData = this.xScale.invert(this.x)\n this.show = (x >= (xRange[0] - tolerance)) && (x <= (xRange[1] + tolerance))\n }\n\n window.cancelAnimationFrame(this._animFrameId)\n this._animFrameId = window.requestAnimationFrame(() => {\n this._render()\n })\n\n if (this.show) this._showTooltip(event)\n else this._hideTooltip()\n }\n\n\n _onMouseOut (): void {\n const { config } = this\n\n // If this chart is the sync broadcaster, emit undefined to the sync bus\n if (config.syncId && this._isSyncActive) {\n crosshairSyncBus.emit(config.syncId, undefined)\n }\n this._isSyncActive = false\n\n // Hide crosshair and tooltip\n this.show = false\n this._hideTooltip()\n\n window.cancelAnimationFrame(this._animFrameId)\n this._animFrameId = window.requestAnimationFrame(() => {\n this._render()\n })\n }\n\n _showTooltip (event?: MouseEvent): void {\n const { config } = this\n const tooltip = config.tooltip ?? this.tooltip\n\n if (!tooltip) {\n return\n }\n\n // For synchronized charts, we need to find the datum if it doesn't exist\n let datum = this.datum\n if (!datum && config.syncId && !this._isSyncActive && this._currentXData !== undefined) {\n // Find the datum at the current x position (only for number values)\n if (typeof this._currentXData === 'number') {\n datum = getNearest(this.datamodel.data, this._currentXData, this.accessors.x)\n }\n }\n\n if (!datum) {\n return\n }\n\n let x: number, y: number\n if (event) {\n // Use actual mouse event\n const container = tooltip.getContainer() || this.container.node()\n ;[x, y] = tooltip.isContainerBody() ? [event.clientX, event.clientY] : pointer(event, container)\n } else {\n // Use synthetic event for sync\n const containerRect = this.container.node().getBoundingClientRect()\n x = tooltip.isContainerBody() ? containerRect.left + this.x : this.x\n y = tooltip.isContainerBody() ? containerRect.top + this._height / 2 : this._height / 2\n }\n\n const content = config.template(datum, this._currentXData || this.xScale.invert(this.x))\n // Force set `followCursor` to `true` because we don't want Crosshair's tooltip to be hoverable\n tooltip.config.followCursor = true\n\n // Set tooltip placement based on Crosshair's position (left / right)\n if (!tooltip.config.horizontalPlacement || tooltip.config.horizontalPlacement === Position.Auto) {\n const xRelative = tooltip.isContainerBody() ? x - this.container.node().getBoundingClientRect().left : x\n tooltip.overrideHorizontalPlacement(xRelative > this._containerWidth / 2 ? Position.Left : Position.Right)\n }\n\n if (content) tooltip.show(content, { x, y })\n }\n\n _hideTooltip (): void {\n const { config } = this\n const tooltip = config.tooltip ?? this.tooltip\n tooltip?.hide()\n }\n\n // We don't want Crosshair to be be taken in to account in domain calculations\n getYDataExtent (): number[] {\n return [undefined, undefined]\n }\n\n private getCircleData (): CrosshairCircle[] {\n const { config, datamodel: { data } } = this\n\n if (isFunction(config.getCircles)) return config.getCircles(this._currentXData || this.xScale.invert(this.x), data, this.yScale)\n\n // Get the datum - either from active mode or from synchronized mode\n let datum = this.datum\n let datumIndex = this.datumIndex\n\n if (!datum && config.syncId && !this._isSyncActive && this._currentXData !== undefined) {\n // Find the datum at the current x position (only for number values)\n if (typeof this._currentXData === 'number') {\n datum = getNearest(this.datamodel.data, this._currentXData, this.accessors.x)\n datumIndex = this.datamodel.data.indexOf(datum)\n }\n }\n\n if (config.snapToData && datum) {\n const yAccessors = this.accessors.y ?? []\n const yStackedAccessors = this.accessors.yStacked ?? []\n const baselineValue = getNumber(datum, this.accessors.baseline, datumIndex) || 0\n\n const stackedValues: CrosshairCircle[] = getStackedValues(datum, datumIndex, ...yStackedAccessors)\n .map((value, index) => {\n const yValue = value + baselineValue\n const yPixel = this.yScale(yValue)\n return {\n y: yPixel,\n opacity: 1,\n color: getColor(datum, config.color, index),\n strokeColor: config.strokeColor ? getColor(datum, config.strokeColor, index) : undefined,\n strokeWidth: config.strokeWidth ? getNumber(datum, config.strokeWidth, index) : undefined,\n }\n })\n\n const regularValues: CrosshairCircle[] = yAccessors\n .map((a, index) => {\n const value = getNumber(datum, a)\n const yPixel = isNumber(value) ? this.yScale(value) : 0\n return {\n y: yPixel,\n opacity: isNumber(value) ? 1 : 0, // Hide circles with invalid values\n color: getColor(datum, config.color, stackedValues.length + index),\n strokeColor: config.strokeColor ? getColor(datum, config.strokeColor, index) : undefined,\n strokeWidth: config.strokeWidth ? getNumber(datum, config.strokeWidth, index) : undefined,\n }\n })\n\n return stackedValues.concat(regularValues)\n }\n\n // Return empty array if no data or no datum - crosshair line will still show\n return []\n }\n\n _updateFromSync (xData: number | Date | undefined): void {\n const { config, datamodel } = this\n\n if (!config.syncId || this._isSyncActive) {\n return\n }\n\n // Handle mouse out signal\n if (xData === undefined) {\n this.show = false\n this._hideTooltip()\n return\n }\n\n if (!this.accessors.x || !datamodel.data?.length) {\n return\n }\n\n // --- DOMAIN CHECK (on passive chart, use xData directly) ---\n const xDomain = this.xScale.domain()\n if (!isInDomain(xData, xDomain)) {\n this.show = false\n this._hideTooltip()\n return\n }\n // --- END DOMAIN CHECK ---\n\n // Find the datum at this x position\n if (typeof xData === 'number') {\n this.datum = getNearest(datamodel.data, xData, this.accessors.x)\n } else if (xData instanceof Date || typeof xData === 'string') {\n const xVal = xData instanceof Date ? xData.getTime() : new Date(xData).getTime()\n this.datum = getNearest(datamodel.data, xVal, this.accessors.x)\n } else {\n this.datum = undefined\n }\n this.datumIndex = datamodel.data.indexOf(this.datum)\n\n // If no datum found, hide the crosshair\n if (!this.datum) {\n this.show = false\n this._hideTooltip()\n return\n }\n\n const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex)\n this.x = clamp(Math.round(this.xScale(dataX)), 0, this._width)\n this._currentXData = dataX\n\n // Show the crosshair\n this.show = true\n\n // Show tooltip for synchronized chart\n this._showTooltip()\n }\n}\n"],"names":["s.line","s.circle","s"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/crosshair/index.ts"],"sourcesContent":["import { Selection, pointer } from 'd3-selection'\nimport { easeLinear } from 'd3-ease'\n\n// Core\nimport { XYComponentCore } from 'core/xy-component'\nimport { Tooltip } from 'components/tooltip'\n\n// Utils\nimport { isNumber, isArray, getNumber, clamp, getStackedValues, getNearest, isFunction } from 'utils/data'\nimport { smartTransition } from 'utils/d3'\nimport { getColor } from 'utils/color'\n\n// Types\nimport { Position } from 'types/position'\n\n// Local Types\nimport { CrosshairAccessors, CrosshairCircle } from './types'\n\n// Config\nimport { CrosshairDefaultConfig, CrosshairConfigInterface } from './config'\n\n// Styles\nimport * as s from './style'\n\nexport class Crosshair<Datum> extends XYComponentCore<Datum, CrosshairConfigInterface<Datum>> {\n static selectors = s\n clippable = true // Don't apply clipping path to this component. See XYContainer\n protected _defaultConfig = CrosshairDefaultConfig as CrosshairConfigInterface<Datum>\n public config: CrosshairConfigInterface<Datum> = this._defaultConfig\n container: Selection<SVGSVGElement, any, SVGSVGElement, any>\n line: Selection<SVGLineElement, any, SVGElement, any>\n x = 0\n datum: Datum\n datumIndex: number\n show = false\n private _animFrameId: number = null\n private _dataX: number | Date | undefined = undefined\n private _isMouseOver = false\n\n /** Tooltip component to be used by Crosshair if not provided by the config.\n * This property is supposed to be set externally by a container component like XYContainer. */\n public tooltip: Tooltip\n\n /** Accessors passed externally (e.g. from XYContainer) */\n private _accessors: CrosshairAccessors<Datum> = {\n x: undefined,\n y: undefined,\n yStacked: undefined,\n baseline: undefined,\n }\n\n public set accessors (accessors: CrosshairAccessors<Datum>) { this._accessors = accessors }\n public get accessors (): CrosshairAccessors<Datum> {\n const { config } = this\n // If x or y are explicitly set in config, use those; otherwise use container accessors\n const x = config.x || this._accessors.x\n const yAcc = config.y || this._accessors.y\n const y = yAcc ? (isArray(yAcc) ? yAcc : [yAcc]) : undefined\n const yStacked = config.yStacked || this._accessors.yStacked\n const baseline = config.baseline ?? this._accessors.baseline\n\n return { x, y, yStacked, baseline }\n }\n\n constructor (config?: CrosshairConfigInterface<Datum>) {\n super()\n if (config) this.config = { ...this.config, ...config }\n\n this.g.style('opacity', this.show ? 1 : 0)\n this.line = this.g.append('line')\n .attr('class', s.line)\n }\n\n setContainer (containerSvg: Selection<SVGSVGElement, unknown, SVGSVGElement, unknown>): void {\n this.container = containerSvg\n this.container.on('mousemove.crosshair', this._onMouseMove.bind(this))\n this.container.on('mouseout.crosshair', this._onMouseOut.bind(this))\n this._render()\n }\n\n setConfig (config: CrosshairConfigInterface<Datum>): void {\n super.setConfig(config)\n // For synchronized charts, update from sync when config changes\n const { isActive, enableSync } = this._getSyncState()\n if (enableSync && !isActive && (isNumber(config.xPosition) || config.xPosition instanceof Date)) {\n this._updateFromSync(config.xPosition)\n }\n }\n\n _render (customDuration?: number): void {\n const { config } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\n const { isActive, enableSync } = this._getSyncState()\n // Handle synchronized charts with xPosition prop\n if (enableSync && !isActive && (isNumber(config.xPosition) || config.xPosition instanceof Date)) {\n this._updateFromSync(config.xPosition)\n }\n\n smartTransition(this.g, duration).style('opacity', this.show ? 1 : 0)\n\n this.line\n .attr('y1', 0)\n .attr('y2', this._height)\n\n smartTransition(this.line, duration, easeLinear)\n .attr('x1', this.x)\n .attr('x2', this.x)\n\n const circleData = this.getCircleData()\n const circles = this.g\n .selectAll<SVGCircleElement, CrosshairCircle>('circle')\n .data(circleData, (d, i) => d.id ?? i)\n\n const circlesEnter = circles.enter()\n .append('circle')\n .attr('class', s.circle)\n .attr('r', 0)\n .attr('cx', this.x)\n .attr('cy', d => d.y)\n .style('fill', d => d.color)\n .style('stroke', d => d.strokeColor)\n .style('stroke-width', d => d.strokeWidth)\n\n smartTransition(circlesEnter.merge(circles), duration, easeLinear)\n .attr('cx', this.x)\n .attr('cy', d => d.y)\n .attr('r', 4)\n .style('opacity', d => d.opacity)\n .style('fill', d => d.color)\n .style('stroke', d => d.strokeColor)\n .style('stroke-width', d => d.strokeWidth)\n\n circles.exit().remove()\n }\n\n hide (): void {\n this._onMouseOut()\n }\n\n destroy (): void {\n if (this._animFrameId) {\n window.cancelAnimationFrame(this._animFrameId)\n this._animFrameId = null\n }\n this._hideTooltip()\n }\n\n _onMouseMove (event: MouseEvent): void {\n // Throttle the entire mouse move processing\n if (this._animFrameId) return\n this._animFrameId = window.requestAnimationFrame(() => {\n this._processMouseMove(event)\n this._animFrameId = null\n })\n }\n\n private _processMouseMove (event: MouseEvent): void {\n this._isMouseOver = true\n const { config, datamodel, element } = this\n const { isActive, enableSync } = this._getSyncState()\n\n // Early return for synchronized non-active charts, but allow tooltip display\n if (enableSync && !isActive) {\n if (this.show && this.datum) {\n this._showTooltip(event)\n } else if (this.show && this._dataX !== undefined && isNumber(this._dataX)) {\n // For synchronized charts, find the datum if it doesn't exist\n this.datum = getNearest(this.datamodel.data, this._dataX, this.accessors.x)\n if (this.datum) {\n this._showTooltip(event)\n }\n }\n return\n }\n\n // Check if we have the necessary accessors\n if (!this.accessors.x && datamodel.data?.length) {\n console.warn('Unovis | Crosshair: X accessor function has not been configured. Please check if it\\'s present in the configuration object')\n return\n }\n\n const [x] = pointer(event, element)\n const xRange = this.xScale.range()\n\n if (config.snapToData) {\n if (!this.accessors.y && !this.accessors.yStacked && datamodel.data?.length) {\n console.warn('Unovis | Crosshair: Y accessors have not been configured. Please check if they\\'re present in the configuration object')\n return\n }\n const scaleX = this.xScale\n const valueX = scaleX.invert(x) as number\n\n this.datum = getNearest(datamodel.data, valueX, this.accessors.x)\n this.datumIndex = datamodel.data.indexOf(this.datum)\n if (!this.datum) return\n\n const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex)\n this.x = clamp(Math.round(scaleX(dataX)), 0, this._width)\n this._dataX = dataX\n\n // Show the crosshair only if it's in the chart range and not far from mouse pointer (if configured)\n this.show = (this.x >= 0) && (this.x <= this._width) && (!config.hideWhenFarFromPointer || (Math.abs(this.x - x) < config.hideWhenFarFromPointerDistance))\n } else {\n const tolerance = 2 // Show the crosshair when it is at least 2 pixels close to the chart area\n this.x = clamp(x, xRange[0], xRange[1])\n this._dataX = this.xScale.invert(this.x)\n this.show = (x >= (xRange[0] - tolerance)) && (x <= (xRange[1] + tolerance))\n }\n\n // Call onCrosshairMove callback if provided\n if (this.show && config.onCrosshairMove && this._dataX !== undefined) {\n config.onCrosshairMove(this._dataX)\n }\n\n // Render immediately since we're already in a throttled context\n this._render()\n\n if (this.show) this._showTooltip(event)\n else this._hideTooltip()\n }\n\n _onMouseOut (): void {\n this._isMouseOver = false\n const { config } = this\n\n // Always hide on mouse out\n this.show = false\n this._hideTooltip()\n\n // Throttle rendering using requestAnimationFrame\n if (this._animFrameId) return\n this._animFrameId = window.requestAnimationFrame(() => {\n this._render()\n this._animFrameId = null\n })\n\n // If this is the active chart, notify parent to clear sync state\n if (config.onCrosshairMove) {\n config.onCrosshairMove(undefined)\n }\n }\n\n _showTooltip (event: MouseEvent): void {\n const tooltip = this.config.tooltip ?? this.tooltip\n\n if (!tooltip || !this.datum) return\n\n const container = tooltip.getContainer() || this.container.node()\n const [x, y] = tooltip.isContainerBody() ? [event.clientX, event.clientY] : pointer(event, container)\n const content = this.config.template(this.datum, this._dataX || this.xScale.invert(this.x))\n\n tooltip.config.followCursor = true\n\n // Set tooltip placement based on Crosshair's position (left / right)\n if (!tooltip.config.horizontalPlacement || tooltip.config.horizontalPlacement === Position.Auto) {\n const xRelative = tooltip.isContainerBody() ? x - this.container.node().getBoundingClientRect().left : x\n tooltip.overrideHorizontalPlacement(xRelative > this._containerWidth / 2 ? Position.Left : Position.Right)\n }\n\n if (content) tooltip.show(content, { x, y })\n }\n\n _hideTooltip (): void {\n const tooltip = this.config.tooltip ?? this.tooltip\n tooltip?.hide()\n }\n\n // We don't want Crosshair to be taken into account in domain calculations\n getYDataExtent (): number[] {\n return [undefined, undefined]\n }\n\n private getCircleData (): CrosshairCircle[] {\n const { datamodel: { data } } = this\n const { isActive, enableSync } = this._getSyncState()\n if (isFunction(this.config.getCircles)) {\n return this.config.getCircles(this._dataX || this.xScale.invert(this.x), data, this.yScale)\n }\n // Get the datum - either from active mode or from synchronized mode\n let datum = this.datum\n let datumIndex = this.datumIndex\n if (!datum && enableSync && !isActive && this._dataX !== undefined) {\n if (isNumber(this._dataX)) {\n datum = getNearest(this.datamodel.data, this._dataX, this.accessors.x)\n datumIndex = this.datamodel.data.indexOf(datum)\n }\n }\n\n if (this.config.snapToData && datum) {\n const yAccessors = this.accessors.y ?? []\n const yStackedAccessors = this.accessors.yStacked ?? []\n const baselineValue = getNumber(datum, this.accessors.baseline, datumIndex) || 0\n\n const stackedValues: CrosshairCircle[] = getStackedValues(datum, datumIndex, ...yStackedAccessors)\n .map((value, index) => {\n const yValue = value + baselineValue\n const yPixel = this.yScale(yValue)\n return {\n y: yPixel,\n opacity: isNumber(getNumber(datum, yStackedAccessors[index])) ? 1 : 1,\n color: getColor(datum, this.config.color, index),\n strokeColor: this.config.strokeColor ? getColor(datum, this.config.strokeColor, index) : undefined,\n strokeWidth: this.config.strokeWidth ? getNumber(datum, this.config.strokeWidth, index) : undefined,\n }\n })\n\n const regularValues: CrosshairCircle[] = yAccessors\n .map((a, index) => {\n const value = getNumber(datum, a)\n const yPixel = isNumber(value) ? this.yScale(value) : 0\n return {\n y: yPixel,\n opacity: isNumber(value) ? 1 : 0, // Hide circles with invalid values\n color: getColor(datum, this.config.color, stackedValues.length + index),\n strokeColor: this.config.strokeColor ? getColor(datum, this.config.strokeColor, index) : undefined,\n strokeWidth: this.config.strokeWidth ? getNumber(datum, this.config.strokeWidth, index) : undefined,\n }\n })\n\n return stackedValues.concat(regularValues)\n }\n\n // Return empty array if no data or no datum - crosshair line will still show\n return []\n }\n\n _updateFromSync (xData: number | Date | undefined): void {\n const { isActive, enableSync } = this._getSyncState()\n if (!enableSync || isActive) return\n\n // Handle mouse out signal\n if (xData === undefined) {\n this.show = false\n this._hideTooltip()\n return\n }\n\n if (!this.accessors.x || !this.datamodel.data?.length) return\n\n // Check if xPosition is within the chart's x domain\n const xDomain = this.xScale.domain()\n let xValue: number\n if (typeof xData === 'number') {\n xValue = xData\n } else if (xData instanceof Date) {\n xValue = xData.getTime()\n } else {\n this.show = false\n this._hideTooltip()\n return\n }\n\n // If xPosition is outside the chart's domain, hide the crosshair\n const domainMin = typeof xDomain[0] === 'number' ? xDomain[0] : (xDomain[0] instanceof Date ? xDomain[0].getTime() : 0)\n const domainMax = typeof xDomain[1] === 'number' ? xDomain[1] : (xDomain[1] instanceof Date ? xDomain[1].getTime() : 0)\n if (xValue < domainMin || xValue > domainMax) {\n this.show = false\n this._hideTooltip()\n return\n }\n\n // Find the datum at this x position\n if (typeof xData === 'number') {\n this.datum = getNearest(this.datamodel.data, xData, this.accessors.x)\n } else if (xData instanceof Date) {\n this.datum = getNearest(this.datamodel.data, xData.getTime(), this.accessors.x)\n } else {\n this.datum = undefined\n }\n this.datumIndex = this.datamodel.data.indexOf(this.datum)\n\n // If no datum found, hide the crosshair\n if (!this.datum) {\n this.show = false\n this._hideTooltip()\n return\n }\n\n const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex)\n this.x = clamp(Math.round(this.xScale(dataX)), 0, this._width)\n this._dataX = dataX\n\n // Show the crosshair\n this.show = true\n\n // Show tooltip for synchronized chart using the same logic as active charts\n const syntheticEvent = {\n clientX: this.container.node().getBoundingClientRect().left + this.x,\n clientY: this.container.node().getBoundingClientRect().top + this._height / 2,\n } as MouseEvent\n this._showTooltip(syntheticEvent)\n }\n\n private _getSyncState (): { isActive: boolean; enableSync: boolean } {\n // A chart is active if it's being hovered and doesn't have external sync props\n const isActive = this._isMouseOver && !isNumber(this.config.xPosition) && !this.config.forceShow\n // A chart is in sync mode if it has external sync props (regardless of mouse state)\n const enableSync = isNumber(this.config.xPosition) || !!this.config.forceShow\n return { isActive, enableSync }\n }\n}\n"],"names":["s.line","s.circle","s"],"mappings":"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"}
|
|
@@ -87,7 +87,7 @@ class Timeline extends XYComponentCore {
|
|
|
87
87
|
var _a, _b, _c, _d;
|
|
88
88
|
const { config, datamodel: { data } } = this;
|
|
89
89
|
const rowLabels = this._getRowLabels(data);
|
|
90
|
-
const rowHeight = config.rowHeight || (this._height / rowLabels.length);
|
|
90
|
+
const rowHeight = config.rowHeight || (this._height / (rowLabels.length || 1));
|
|
91
91
|
const hasIcons = rowLabels.some(l => l.iconHref);
|
|
92
92
|
const maxIconSize = max(rowLabels.map(l => l.iconSize || 0));
|
|
93
93
|
// We calculate the longest label width to set the bleed values accordingly
|
|
@@ -160,7 +160,7 @@ class Timeline extends XYComponentCore {
|
|
|
160
160
|
const yHeight = Math.abs(yRange[1] - yRange[0]);
|
|
161
161
|
const rowLabels = this._getRowLabels(data);
|
|
162
162
|
const numRowLabels = rowLabels.length;
|
|
163
|
-
const rowHeight = config.rowHeight || (yHeight / numRowLabels);
|
|
163
|
+
const rowHeight = config.rowHeight || (yHeight / (numRowLabels || 1));
|
|
164
164
|
const yOrdinalScale = scaleOrdinal()
|
|
165
165
|
.range(arrayOfIndices(numRowLabels))
|
|
166
166
|
.domain(rowLabels.map(l => l.label));
|
|
@@ -340,8 +340,7 @@ class Timeline extends XYComponentCore {
|
|
|
340
340
|
.style('opacity', 0)
|
|
341
341
|
.remove();
|
|
342
342
|
// Scroll Bar
|
|
343
|
-
const
|
|
344
|
-
const absoluteContentHeight = contentBBox.height;
|
|
343
|
+
const absoluteContentHeight = recordTypes.length * rowHeight;
|
|
345
344
|
this._scrollbarHeight = yHeight * yHeight / absoluteContentHeight || 0;
|
|
346
345
|
this._maxScroll = Math.max(absoluteContentHeight - yHeight, 0);
|
|
347
346
|
this._scrollBarGroup
|