@unovis/ts 1.5.2 → 1.6.0-bigip.0
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/axis/index.d.ts +0 -1
- package/components/axis/index.js +2 -10
- package/components/axis/index.js.map +1 -1
- package/components/brush/config.d.ts +1 -1
- package/components/brush/config.js.map +1 -1
- package/components/crosshair/config.d.ts +5 -0
- package/components/crosshair/config.js +1 -1
- package/components/crosshair/config.js.map +1 -1
- package/components/crosshair/index.d.ts +6 -1
- package/components/crosshair/index.js +182 -34
- package/components/crosshair/index.js.map +1 -1
- package/components/crosshair/sync-bus.d.ts +9 -0
- package/components/crosshair/sync-bus.js +27 -0
- package/components/crosshair/sync-bus.js.map +1 -0
- package/components/graph/config.d.ts +8 -0
- package/components/graph/config.js +1 -1
- package/components/graph/config.js.map +1 -1
- package/components/graph/index.d.ts +1 -0
- package/components/graph/index.js +14 -9
- package/components/graph/index.js.map +1 -1
- package/components/graph/modules/layout.js +31 -29
- package/components/graph/modules/layout.js.map +1 -1
- package/components/graph/modules/link/index.js +1 -1
- package/components/graph/modules/link/index.js.map +1 -1
- package/components/graph/types.d.ts +2 -1
- package/components/graph/types.js.map +1 -1
- package/components/plotband/config.d.ts +59 -0
- package/components/plotband/config.js +9 -0
- package/components/plotband/config.js.map +1 -0
- package/components/plotband/constants.d.ts +5 -0
- package/components/plotband/constants.js +413 -0
- package/components/plotband/constants.js.map +1 -0
- package/components/plotband/index.d.ts +15 -0
- package/components/plotband/index.js +92 -0
- package/components/plotband/index.js.map +1 -0
- package/components/plotband/style.d.ts +4 -0
- package/components/plotband/style.js +38 -0
- package/components/plotband/style.js.map +1 -0
- package/components/plotband/types.d.ts +51 -0
- package/components/plotband/types.js +27 -0
- package/components/plotband/types.js.map +1 -0
- package/components/timeline/config.d.ts +65 -14
- package/components/timeline/config.js +15 -1
- package/components/timeline/config.js.map +1 -1
- package/components/timeline/constants.d.ts +3 -0
- package/components/timeline/constants.js +6 -0
- package/components/timeline/constants.js.map +1 -0
- package/components/timeline/index.d.ts +21 -10
- package/components/timeline/index.js +379 -93
- package/components/timeline/index.js.map +1 -1
- package/components/timeline/style.d.ts +7 -0
- package/components/timeline/style.js +40 -1
- package/components/timeline/style.js.map +1 -1
- package/components/timeline/types.d.ts +62 -0
- package/components/timeline/types.js +2 -0
- package/components/timeline/types.js.map +1 -0
- package/components/timeline/utils.d.ts +2 -0
- package/components/timeline/utils.js +16 -0
- package/components/timeline/utils.js.map +1 -0
- package/components.d.ts +4 -2
- package/components.js +1 -0
- package/components.js.map +1 -1
- package/containers/xy-container/config.d.ts +2 -0
- package/containers/xy-container/config.js +1 -1
- package/containers/xy-container/config.js.map +1 -1
- package/containers/xy-container/index.js +2 -2
- package/containers/xy-container/index.js.map +1 -1
- package/data-models/graph.js +7 -1
- package/data-models/graph.js.map +1 -1
- package/index.js +4 -2
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/types/position.d.ts +2 -1
- package/types/position.js +1 -0
- package/types/position.js.map +1 -1
- package/types.d.ts +2 -0
- package/types.js +2 -0
- package/types.js.map +1 -1
- package/utils/data.d.ts +1 -1
- package/utils/data.js +1 -1
- package/utils/data.js.map +1 -1
- package/utils/index.js +2 -2
- package/utils/path.d.ts +8 -0
- package/utils/path.js +109 -1
- package/utils/path.js.map +1 -1
- package/utils/text.d.ts +2 -1
- package/utils/text.js +10 -2
- package/utils/text.js.map +1 -1
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import { pointer } from 'd3-selection';
|
|
2
2
|
import { easeLinear } from 'd3-ease';
|
|
3
3
|
import { XYComponentCore } from '../../core/xy-component/index.js';
|
|
4
|
-
import { isArray, isNumber, getNearest,
|
|
4
|
+
import { isArray, isNumber, getNearest, getNumber, clamp, isFunction, getStackedValues } from '../../utils/data.js';
|
|
5
5
|
import { smartTransition } from '../../utils/d3.js';
|
|
6
6
|
import { getColor } from '../../utils/color.js';
|
|
7
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';
|
|
11
12
|
|
|
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
|
+
}
|
|
12
22
|
class Crosshair extends XYComponentCore {
|
|
13
23
|
constructor(config) {
|
|
14
24
|
super();
|
|
@@ -18,6 +28,9 @@ class Crosshair extends XYComponentCore {
|
|
|
18
28
|
this.x = 0;
|
|
19
29
|
this.show = false;
|
|
20
30
|
this._animFrameId = null;
|
|
31
|
+
this._currentXData = undefined;
|
|
32
|
+
this._syncListener = null;
|
|
33
|
+
this._isSyncActive = false; // true if this chart is the one broadcasting
|
|
21
34
|
/** Accessors passed externally (e.g. from XYContainer) */
|
|
22
35
|
this._accessors = {
|
|
23
36
|
x: undefined,
|
|
@@ -26,7 +39,7 @@ class Crosshair extends XYComponentCore {
|
|
|
26
39
|
baseline: undefined,
|
|
27
40
|
};
|
|
28
41
|
if (config)
|
|
29
|
-
this.
|
|
42
|
+
this.config = Object.assign(Object.assign({}, this.config), config);
|
|
30
43
|
this.g.style('opacity', this.show ? 1 : 0);
|
|
31
44
|
this.line = this.g.append('line')
|
|
32
45
|
.attr('class', line);
|
|
@@ -35,30 +48,41 @@ class Crosshair extends XYComponentCore {
|
|
|
35
48
|
get accessors() {
|
|
36
49
|
var _a;
|
|
37
50
|
const { config } = this;
|
|
38
|
-
|
|
39
|
-
const x =
|
|
40
|
-
const yAcc =
|
|
51
|
+
// If x or y are explicitly set in config, use those; otherwise use container accessors
|
|
52
|
+
const x = config.x || this._accessors.x;
|
|
53
|
+
const yAcc = config.y || this._accessors.y;
|
|
41
54
|
const y = yAcc ? (isArray(yAcc) ? yAcc : [yAcc]) : undefined;
|
|
42
|
-
const yStacked =
|
|
55
|
+
const yStacked = config.yStacked || this._accessors.yStacked;
|
|
43
56
|
const baseline = (_a = config.baseline) !== null && _a !== void 0 ? _a : this._accessors.baseline;
|
|
44
57
|
return { x, y, yStacked, baseline };
|
|
45
58
|
}
|
|
46
59
|
setContainer(containerSvg) {
|
|
47
|
-
// Set up mousemove event for Crosshair
|
|
48
60
|
this.container = containerSvg;
|
|
49
61
|
this.container.on('mousemove.crosshair', this._onMouseMove.bind(this));
|
|
50
62
|
this.container.on('mouseout.crosshair', this._onMouseOut.bind(this));
|
|
63
|
+
this._render();
|
|
64
|
+
// --- SYNC: subscribe if needed ---
|
|
65
|
+
if (this.config.syncId) {
|
|
66
|
+
this._syncListener = (x) => {
|
|
67
|
+
if (!this._isSyncActive) {
|
|
68
|
+
this._updateFromSync(x);
|
|
69
|
+
window.requestAnimationFrame(() => this._render());
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
crosshairSyncBus.subscribe(this.config.syncId, this._syncListener);
|
|
73
|
+
}
|
|
51
74
|
}
|
|
52
75
|
_render(customDuration) {
|
|
53
76
|
const { config } = this;
|
|
54
|
-
if (config.snapToData && !this.datum)
|
|
55
|
-
return;
|
|
56
77
|
const duration = isNumber(customDuration) ? customDuration : config.duration;
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
// --- SYNC: update from sync bus if not active ---
|
|
79
|
+
if (config.syncId && !this._isSyncActive) {
|
|
80
|
+
// _updateFromSync is called by the bus
|
|
81
|
+
}
|
|
82
|
+
smartTransition(this.g, duration).style('opacity', this.show ? 1 : 0);
|
|
59
83
|
this.line
|
|
60
84
|
.attr('y1', 0)
|
|
61
|
-
.attr('
|
|
85
|
+
.attr('y2', this._height);
|
|
62
86
|
smartTransition(this.line, duration, easeLinear)
|
|
63
87
|
.attr('x1', this.x)
|
|
64
88
|
.attr('x2', this.x);
|
|
@@ -88,17 +112,34 @@ class Crosshair extends XYComponentCore {
|
|
|
88
112
|
hide() {
|
|
89
113
|
this._onMouseOut();
|
|
90
114
|
}
|
|
115
|
+
destroy() {
|
|
116
|
+
if (this._animFrameId) {
|
|
117
|
+
window.cancelAnimationFrame(this._animFrameId);
|
|
118
|
+
this._animFrameId = null;
|
|
119
|
+
}
|
|
120
|
+
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
|
+
}
|
|
91
127
|
_onMouseMove(event) {
|
|
92
128
|
var _a, _b;
|
|
93
129
|
const { config, datamodel, element } = this;
|
|
130
|
+
// Set sync active state
|
|
131
|
+
this._isSyncActive = !!config.syncId;
|
|
132
|
+
// Check if we have the necessary accessors
|
|
94
133
|
if (!this.accessors.x && ((_a = datamodel.data) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
95
134
|
console.warn('Unovis | Crosshair: X accessor function has not been configured. Please check if it\'s present in the configuration object');
|
|
135
|
+
return;
|
|
96
136
|
}
|
|
97
137
|
const [x] = pointer(event, element);
|
|
98
138
|
const xRange = this.xScale.range();
|
|
99
139
|
if (config.snapToData) {
|
|
100
140
|
if (!this.accessors.y && !this.accessors.yStacked && ((_b = datamodel.data) === null || _b === void 0 ? void 0 : _b.length)) {
|
|
101
141
|
console.warn('Unovis | Crosshair: Y accessors have not been configured. Please check if they\'re present in the configuration object');
|
|
142
|
+
return;
|
|
102
143
|
}
|
|
103
144
|
const scaleX = this.xScale;
|
|
104
145
|
const valueX = scaleX.invert(x);
|
|
@@ -106,13 +147,26 @@ class Crosshair extends XYComponentCore {
|
|
|
106
147
|
this.datumIndex = datamodel.data.indexOf(this.datum);
|
|
107
148
|
if (!this.datum)
|
|
108
149
|
return;
|
|
109
|
-
|
|
150
|
+
const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex);
|
|
151
|
+
this.x = clamp(Math.round(scaleX(dataX)), 0, this._width);
|
|
152
|
+
this._currentXData = dataX;
|
|
110
153
|
// Show the crosshair only if it's in the chart range and not far from mouse pointer (if configured)
|
|
111
154
|
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
|
+
}
|
|
112
165
|
}
|
|
113
166
|
else {
|
|
114
167
|
const tolerance = 2; // Show the crosshair when it is at least 2 pixels close to the chart area
|
|
115
168
|
this.x = clamp(x, xRange[0], xRange[1]);
|
|
169
|
+
this._currentXData = this.xScale.invert(this.x);
|
|
116
170
|
this.show = (x >= (xRange[0] - tolerance)) && (x <= (xRange[1] + tolerance));
|
|
117
171
|
}
|
|
118
172
|
window.cancelAnimationFrame(this._animFrameId);
|
|
@@ -125,22 +179,51 @@ class Crosshair extends XYComponentCore {
|
|
|
125
179
|
this._hideTooltip();
|
|
126
180
|
}
|
|
127
181
|
_onMouseOut() {
|
|
182
|
+
const { config } = this;
|
|
183
|
+
// If this chart is the sync broadcaster, emit undefined to the sync bus
|
|
184
|
+
if (config.syncId && this._isSyncActive) {
|
|
185
|
+
crosshairSyncBus.emit(config.syncId, undefined);
|
|
186
|
+
}
|
|
187
|
+
this._isSyncActive = false;
|
|
188
|
+
// Hide crosshair and tooltip
|
|
128
189
|
this.show = false;
|
|
190
|
+
this._hideTooltip();
|
|
129
191
|
window.cancelAnimationFrame(this._animFrameId);
|
|
130
192
|
this._animFrameId = window.requestAnimationFrame(() => {
|
|
131
193
|
this._render();
|
|
132
194
|
});
|
|
133
|
-
this._hideTooltip();
|
|
134
195
|
}
|
|
135
196
|
_showTooltip(event) {
|
|
136
197
|
var _a;
|
|
137
198
|
const { config } = this;
|
|
138
199
|
const tooltip = (_a = config.tooltip) !== null && _a !== void 0 ? _a : this.tooltip;
|
|
139
|
-
if (!tooltip)
|
|
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) {
|
|
140
212
|
return;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
213
|
+
}
|
|
214
|
+
let x, y;
|
|
215
|
+
if (event) {
|
|
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));
|
|
144
227
|
// Force set `followCursor` to `true` because we don't want Crosshair's tooltip to be hoverable
|
|
145
228
|
tooltip.config.followCursor = true;
|
|
146
229
|
// Set tooltip placement based on Crosshair's position (left / right)
|
|
@@ -165,34 +248,99 @@ class Crosshair extends XYComponentCore {
|
|
|
165
248
|
var _a, _b;
|
|
166
249
|
const { config, datamodel: { data } } = this;
|
|
167
250
|
if (isFunction(config.getCircles))
|
|
168
|
-
return config.getCircles(this.xScale.invert(this.x), data, this.yScale);
|
|
169
|
-
|
|
251
|
+
return config.getCircles(this._currentXData || this.xScale.invert(this.x), data, this.yScale);
|
|
252
|
+
// Get the datum - either from active mode or from synchronized mode
|
|
253
|
+
let datum = this.datum;
|
|
254
|
+
let datumIndex = this.datumIndex;
|
|
255
|
+
if (!datum && config.syncId && !this._isSyncActive && this._currentXData !== undefined) {
|
|
256
|
+
// Find the datum at the current x position (only for number values)
|
|
257
|
+
if (typeof this._currentXData === 'number') {
|
|
258
|
+
datum = getNearest(this.datamodel.data, this._currentXData, this.accessors.x);
|
|
259
|
+
datumIndex = this.datamodel.data.indexOf(datum);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (config.snapToData && datum) {
|
|
170
263
|
const yAccessors = (_a = this.accessors.y) !== null && _a !== void 0 ? _a : [];
|
|
171
264
|
const yStackedAccessors = (_b = this.accessors.yStacked) !== null && _b !== void 0 ? _b : [];
|
|
172
|
-
const baselineValue = getNumber(
|
|
173
|
-
const stackedValues = getStackedValues(
|
|
174
|
-
.map((value, index
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
265
|
+
const baselineValue = getNumber(datum, this.accessors.baseline, datumIndex) || 0;
|
|
266
|
+
const stackedValues = getStackedValues(datum, datumIndex, ...yStackedAccessors)
|
|
267
|
+
.map((value, index) => {
|
|
268
|
+
const yValue = value + baselineValue;
|
|
269
|
+
const yPixel = this.yScale(yValue);
|
|
270
|
+
return {
|
|
271
|
+
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,
|
|
276
|
+
};
|
|
277
|
+
});
|
|
181
278
|
const regularValues = yAccessors
|
|
182
279
|
.map((a, index) => {
|
|
183
|
-
const value = getNumber(
|
|
280
|
+
const value = getNumber(datum, a);
|
|
281
|
+
const yPixel = isNumber(value) ? this.yScale(value) : 0;
|
|
184
282
|
return {
|
|
185
|
-
y:
|
|
283
|
+
y: yPixel,
|
|
186
284
|
opacity: isNumber(value) ? 1 : 0,
|
|
187
|
-
color: getColor(
|
|
188
|
-
strokeColor: config.strokeColor ? getColor(
|
|
189
|
-
strokeWidth: config.strokeWidth ? getNumber(
|
|
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,
|
|
190
288
|
};
|
|
191
289
|
});
|
|
192
290
|
return stackedValues.concat(regularValues);
|
|
193
291
|
}
|
|
292
|
+
// Return empty array if no data or no datum - crosshair line will still show
|
|
194
293
|
return [];
|
|
195
294
|
}
|
|
295
|
+
_updateFromSync(xData) {
|
|
296
|
+
var _a;
|
|
297
|
+
const { config, datamodel } = this;
|
|
298
|
+
if (!config.syncId || this._isSyncActive) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
// Handle mouse out signal
|
|
302
|
+
if (xData === undefined) {
|
|
303
|
+
this.show = false;
|
|
304
|
+
this._hideTooltip();
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (!this.accessors.x || !((_a = datamodel.data) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
// --- DOMAIN CHECK (on passive chart, use xData directly) ---
|
|
311
|
+
const xDomain = this.xScale.domain();
|
|
312
|
+
if (!isInDomain(xData, xDomain)) {
|
|
313
|
+
this.show = false;
|
|
314
|
+
this._hideTooltip();
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
// --- END DOMAIN CHECK ---
|
|
318
|
+
// Find the datum at this x position
|
|
319
|
+
if (typeof xData === 'number') {
|
|
320
|
+
this.datum = getNearest(datamodel.data, xData, this.accessors.x);
|
|
321
|
+
}
|
|
322
|
+
else if (xData instanceof Date || typeof xData === 'string') {
|
|
323
|
+
const xVal = xData instanceof Date ? xData.getTime() : new Date(xData).getTime();
|
|
324
|
+
this.datum = getNearest(datamodel.data, xVal, this.accessors.x);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
this.datum = undefined;
|
|
328
|
+
}
|
|
329
|
+
this.datumIndex = datamodel.data.indexOf(this.datum);
|
|
330
|
+
// If no datum found, hide the crosshair
|
|
331
|
+
if (!this.datum) {
|
|
332
|
+
this.show = false;
|
|
333
|
+
this._hideTooltip();
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex);
|
|
337
|
+
this.x = clamp(Math.round(this.xScale(dataX)), 0, this._width);
|
|
338
|
+
this._currentXData = dataX;
|
|
339
|
+
// Show the crosshair
|
|
340
|
+
this.show = true;
|
|
341
|
+
// Show tooltip for synchronized chart
|
|
342
|
+
this._showTooltip();
|
|
343
|
+
}
|
|
196
344
|
}
|
|
197
345
|
Crosshair.selectors = style;
|
|
198
346
|
|
|
@@ -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\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\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\n const hasConfig = !!(config.x || config.y || config.yStacked)\n const x = hasConfig ? config.x : this._accessors.x\n const yAcc = hasConfig ? config.y : this._accessors.y\n const y = yAcc ? (isArray(yAcc) ? yAcc : [yAcc]) : undefined\n const yStacked = hasConfig ? 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.setConfig(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 // Set up mousemove event for Crosshair\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 }\n\n _render (customDuration?: number): void {\n const { config } = this\n if (config.snapToData && !this.datum) return\n const duration = isNumber(customDuration) ? customDuration : config.duration\n\n smartTransition(this.g, duration)\n .style('opacity', this.show ? 1 : 0)\n\n this.line\n .attr('y1', 0)\n .attr('y1', 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 _onMouseMove (event: MouseEvent): void {\n const { config, datamodel, element } = this\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 }\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 }\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 this.x = clamp(Math.round(scaleX(getNumber(this.datum, this.accessors.x, this.datumIndex))), 0, this._width)\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.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 _onMouseOut (): void {\n this.show = false\n\n window.cancelAnimationFrame(this._animFrameId)\n this._animFrameId = window.requestAnimationFrame(() => {\n this._render()\n })\n this._hideTooltip()\n }\n\n _showTooltip (event: MouseEvent): void {\n const { config } = this\n const tooltip = config.tooltip ?? this.tooltip\n if (!tooltip) 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 = config.template(this.datum, 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.xScale.invert(this.x), data, this.yScale)\n\n if (config.snapToData && this.datum) {\n const yAccessors = this.accessors.y ?? []\n const yStackedAccessors = this.accessors.yStacked ?? []\n const baselineValue = getNumber(this.datum, this.accessors.baseline, this.datumIndex) || 0\n const stackedValues: CrosshairCircle[] = getStackedValues(this.datum, this.datumIndex, ...yStackedAccessors)\n .map((value, index, arr) => ({\n y: this.yScale(value + baselineValue),\n opacity: isNumber(getNumber(this.datum, yStackedAccessors[index])) ? 1 : 0,\n color: getColor(this.datum, config.color, index),\n strokeColor: config.strokeColor ? getColor(this.datum, config.strokeColor, index) : undefined,\n strokeWidth: config.strokeWidth ? getNumber(this.datum, config.strokeWidth, index) : undefined,\n }))\n\n const regularValues: CrosshairCircle[] = yAccessors\n .map((a, index) => {\n const value = getNumber(this.datum, a)\n return {\n y: this.yScale(value),\n opacity: isNumber(value) ? 1 : 0,\n color: getColor(this.datum, config.color, stackedValues.length + index),\n strokeColor: config.strokeColor ? getColor(this.datum, config.strokeColor, index) : undefined,\n strokeWidth: config.strokeWidth ? getNumber(this.datum, config.strokeWidth, index) : undefined,\n }\n })\n\n return stackedValues.concat(regularValues)\n }\n\n return []\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\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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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare type CrosshairSyncListener = (x: number | Date | undefined) => void;
|
|
2
|
+
declare class CrosshairSyncBus {
|
|
3
|
+
private listeners;
|
|
4
|
+
subscribe(syncId: string, listener: CrosshairSyncListener): void;
|
|
5
|
+
unsubscribe(syncId: string, listener: CrosshairSyncListener): void;
|
|
6
|
+
emit(syncId: string, x: number | Date | undefined): void;
|
|
7
|
+
}
|
|
8
|
+
export declare const crosshairSyncBus: CrosshairSyncBus;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Simple singleton event bus for crosshair sync by syncId
|
|
2
|
+
class CrosshairSyncBus {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.listeners = {};
|
|
5
|
+
}
|
|
6
|
+
subscribe(syncId, listener) {
|
|
7
|
+
if (!this.listeners[syncId]) {
|
|
8
|
+
this.listeners[syncId] = new Set();
|
|
9
|
+
}
|
|
10
|
+
this.listeners[syncId].add(listener);
|
|
11
|
+
}
|
|
12
|
+
unsubscribe(syncId, listener) {
|
|
13
|
+
var _a, _b;
|
|
14
|
+
(_a = this.listeners[syncId]) === null || _a === void 0 ? void 0 : _a.delete(listener);
|
|
15
|
+
if (((_b = this.listeners[syncId]) === null || _b === void 0 ? void 0 : _b.size) === 0) {
|
|
16
|
+
delete this.listeners[syncId];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
emit(syncId, x) {
|
|
20
|
+
var _a;
|
|
21
|
+
(_a = this.listeners[syncId]) === null || _a === void 0 ? void 0 : _a.forEach(listener => listener(x));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const crosshairSyncBus = new CrosshairSyncBus();
|
|
25
|
+
|
|
26
|
+
export { crosshairSyncBus };
|
|
27
|
+
//# sourceMappingURL=sync-bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-bus.js","sources":["../../../src/components/crosshair/sync-bus.ts"],"sourcesContent":["// Simple singleton event bus for crosshair sync by syncId\n\nexport type CrosshairSyncListener = (x: number | Date | undefined) => void\n\nclass CrosshairSyncBus {\n private listeners: Record<string, Set<CrosshairSyncListener>> = {}\n\n subscribe (syncId: string, listener: CrosshairSyncListener): void {\n if (!this.listeners[syncId]) {\n this.listeners[syncId] = new Set()\n }\n this.listeners[syncId].add(listener)\n }\n\n unsubscribe (syncId: string, listener: CrosshairSyncListener): void {\n this.listeners[syncId]?.delete(listener)\n if (this.listeners[syncId]?.size === 0) {\n delete this.listeners[syncId]\n }\n }\n\n emit (syncId: string, x: number | Date | undefined): void {\n this.listeners[syncId]?.forEach(listener => listener(x))\n }\n}\n\nexport const crosshairSyncBus = new CrosshairSyncBus()\n"],"names":[],"mappings":"AAAA;AAIA,MAAM,gBAAgB,CAAA;AAAtB,IAAA,WAAA,GAAA;QACU,IAAS,CAAA,SAAA,GAA+C,EAAE,CAAA;KAmBnE;IAjBC,SAAS,CAAE,MAAc,EAAE,QAA+B,EAAA;AACxD,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;YAC3B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAA;AACnC,SAAA;QACD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;KACrC;IAED,WAAW,CAAE,MAAc,EAAE,QAA+B,EAAA;;QAC1D,CAAA,EAAA,GAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;AACxC,QAAA,IAAI,CAAA,CAAA,EAAA,GAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAI,MAAK,CAAC,EAAE;AACtC,YAAA,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;AAC9B,SAAA;KACF;IAED,IAAI,CAAE,MAAc,EAAE,CAA4B,EAAA;;AAChD,QAAA,CAAA,EAAA,GAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,0CAAE,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;KACzD;AACF,CAAA;AAEY,MAAA,gBAAgB,GAAG,IAAI,gBAAgB;;;;"}
|
|
@@ -62,6 +62,14 @@ export interface GraphConfigInterface<N extends GraphInputNode, L extends GraphI
|
|
|
62
62
|
* Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.
|
|
63
63
|
* Default: `1` */
|
|
64
64
|
layoutParallelSubGroupsPerRow?: number;
|
|
65
|
+
/** Spacing between nodes, dynamic by default.
|
|
66
|
+
* Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.
|
|
67
|
+
* Default: `undefined` */
|
|
68
|
+
layoutParallelNodeSpacing?: number | [number, number];
|
|
69
|
+
/** Spacing between sub-groups.
|
|
70
|
+
* Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.
|
|
71
|
+
* Default: `40` */
|
|
72
|
+
layoutParallelSubGroupSpacing?: number;
|
|
65
73
|
/** Spacing between groups.
|
|
66
74
|
* Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.
|
|
67
75
|
* Default: `undefined` */
|
|
@@ -4,7 +4,7 @@ import { TrimMode } from '../../types/text.js';
|
|
|
4
4
|
import { GraphLayoutType, GraphFitViewAlignment, GraphLinkStyle, GraphNodeShape, GraphNodeSelectionHighlightMode } from './types.js';
|
|
5
5
|
|
|
6
6
|
// Utils
|
|
7
|
-
const GraphDefaultConfig = Object.assign(Object.assign({}, ComponentDefaultConfig), { duration: 1000, zoomScaleExtent: [0.35, 1.25], disableZoom: false, zoomEventFilter: undefined, disableDrag: false, disableBrush: false, zoomThrottledUpdateNodeThreshold: 100, layoutType: GraphLayoutType.Force, layoutAutofit: true, layoutAutofitTolerance: 8.0, layoutNonConnectedAside: false, fitViewPadding: 50, fitViewAlign: GraphFitViewAlignment.Center, layoutGroupOrder: [], layoutParallelSubGroupsPerRow: 1, layoutParallelNodesPerColumn: 6, layoutParallelGroupSpacing: undefined, layoutParallelSortConnectionsByGroup: undefined, layoutNodeGroup: (n) => n.group, layoutParallelNodeSubGroup: (n) => n.subgroup, forceLayoutSettings: {
|
|
7
|
+
const GraphDefaultConfig = Object.assign(Object.assign({}, ComponentDefaultConfig), { duration: 1000, zoomScaleExtent: [0.35, 1.25], disableZoom: false, zoomEventFilter: undefined, disableDrag: false, disableBrush: false, zoomThrottledUpdateNodeThreshold: 100, layoutType: GraphLayoutType.Force, layoutAutofit: true, layoutAutofitTolerance: 8.0, layoutNonConnectedAside: false, fitViewPadding: 50, fitViewAlign: GraphFitViewAlignment.Center, layoutGroupOrder: [], layoutParallelNodeSpacing: undefined, layoutParallelSubGroupsPerRow: 1, layoutParallelNodesPerColumn: 6, layoutParallelGroupSpacing: undefined, layoutParallelSubGroupSpacing: 40, layoutParallelSortConnectionsByGroup: undefined, layoutNodeGroup: (n) => n.group, layoutParallelNodeSubGroup: (n) => n.subgroup, forceLayoutSettings: {
|
|
8
8
|
linkDistance: 60,
|
|
9
9
|
linkStrength: 0.45,
|
|
10
10
|
charge: -500,
|