@unovis/ts 1.6.0-beta.0 → 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.
Files changed (95) hide show
  1. package/components/axis/config.d.ts +1 -1
  2. package/components/axis/config.js.map +1 -1
  3. package/components/axis/index.d.ts +0 -1
  4. package/components/axis/index.js +2 -10
  5. package/components/axis/index.js.map +1 -1
  6. package/components/brush/config.d.ts +1 -1
  7. package/components/brush/config.js.map +1 -1
  8. package/components/crosshair/config.d.ts +5 -0
  9. package/components/crosshair/config.js +1 -1
  10. package/components/crosshair/config.js.map +1 -1
  11. package/components/crosshair/index.d.ts +6 -1
  12. package/components/crosshair/index.js +182 -34
  13. package/components/crosshair/index.js.map +1 -1
  14. package/components/crosshair/sync-bus.d.ts +9 -0
  15. package/components/crosshair/sync-bus.js +27 -0
  16. package/components/crosshair/sync-bus.js.map +1 -0
  17. package/components/graph/config.d.ts +8 -0
  18. package/components/graph/config.js +1 -1
  19. package/components/graph/config.js.map +1 -1
  20. package/components/graph/index.d.ts +1 -0
  21. package/components/graph/index.js +14 -9
  22. package/components/graph/index.js.map +1 -1
  23. package/components/graph/modules/layout.js +33 -31
  24. package/components/graph/modules/layout.js.map +1 -1
  25. package/components/graph/modules/link/index.js +1 -1
  26. package/components/graph/modules/link/index.js.map +1 -1
  27. package/components/graph/types.d.ts +2 -1
  28. package/components/graph/types.js.map +1 -1
  29. package/components/plotband/config.d.ts +59 -0
  30. package/components/plotband/config.js +9 -0
  31. package/components/plotband/config.js.map +1 -0
  32. package/components/plotband/constants.d.ts +5 -0
  33. package/components/plotband/constants.js +413 -0
  34. package/components/plotband/constants.js.map +1 -0
  35. package/components/plotband/index.d.ts +15 -0
  36. package/components/plotband/index.js +92 -0
  37. package/components/plotband/index.js.map +1 -0
  38. package/components/plotband/style.d.ts +4 -0
  39. package/components/plotband/style.js +38 -0
  40. package/components/plotband/style.js.map +1 -0
  41. package/components/plotband/types.d.ts +51 -0
  42. package/components/plotband/types.js +27 -0
  43. package/components/plotband/types.js.map +1 -0
  44. package/components/scatter/index.d.ts +1 -0
  45. package/components/scatter/index.js +11 -1
  46. package/components/scatter/index.js.map +1 -1
  47. package/components/timeline/config.d.ts +65 -14
  48. package/components/timeline/config.js +15 -1
  49. package/components/timeline/config.js.map +1 -1
  50. package/components/timeline/constants.d.ts +3 -0
  51. package/components/timeline/constants.js +6 -0
  52. package/components/timeline/constants.js.map +1 -0
  53. package/components/timeline/index.d.ts +21 -10
  54. package/components/timeline/index.js +379 -93
  55. package/components/timeline/index.js.map +1 -1
  56. package/components/timeline/style.d.ts +7 -0
  57. package/components/timeline/style.js +40 -1
  58. package/components/timeline/style.js.map +1 -1
  59. package/components/timeline/types.d.ts +62 -0
  60. package/components/timeline/types.js +2 -0
  61. package/components/timeline/types.js.map +1 -0
  62. package/components/timeline/utils.d.ts +2 -0
  63. package/components/timeline/utils.js +16 -0
  64. package/components/timeline/utils.js.map +1 -0
  65. package/components/xy-labels/index.js +1 -1
  66. package/components/xy-labels/index.js.map +1 -1
  67. package/components.d.ts +4 -2
  68. package/components.js +1 -0
  69. package/components.js.map +1 -1
  70. package/containers/xy-container/config.d.ts +2 -0
  71. package/containers/xy-container/config.js +1 -1
  72. package/containers/xy-container/config.js.map +1 -1
  73. package/containers/xy-container/index.js +2 -2
  74. package/containers/xy-container/index.js.map +1 -1
  75. package/data-models/graph.js +7 -1
  76. package/data-models/graph.js.map +1 -1
  77. package/index.js +4 -2
  78. package/index.js.map +1 -1
  79. package/package.json +4 -3
  80. package/types/position.d.ts +2 -1
  81. package/types/position.js +1 -0
  82. package/types/position.js.map +1 -1
  83. package/types.d.ts +2 -0
  84. package/types.js +2 -0
  85. package/types.js.map +1 -1
  86. package/utils/data.d.ts +1 -1
  87. package/utils/data.js +2 -2
  88. package/utils/data.js.map +1 -1
  89. package/utils/index.js +2 -2
  90. package/utils/path.d.ts +8 -0
  91. package/utils/path.js +109 -1
  92. package/utils/path.js.map +1 -1
  93. package/utils/text.d.ts +2 -1
  94. package/utils/text.js +10 -2
  95. 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, clamp, getNumber, isFunction, getStackedValues } from '../../utils/data.js';
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.setConfig(config);
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
- const hasConfig = !!(config.x || config.y || config.yStacked);
39
- const x = hasConfig ? config.x : this._accessors.x;
40
- const yAcc = hasConfig ? config.y : this._accessors.y;
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 = hasConfig ? config.yStacked : this._accessors.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
- smartTransition(this.g, duration)
58
- .style('opacity', this.show ? 1 : 0);
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('y1', this._height);
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
- this.x = clamp(Math.round(scaleX(getNumber(this.datum, this.accessors.x, this.datumIndex))), 0, this._width);
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
- const container = tooltip.getContainer() || this.container.node();
142
- const [x, y] = tooltip.isContainerBody() ? [event.clientX, event.clientY] : pointer(event, container);
143
- const content = config.template(this.datum, this.xScale.invert(this.x));
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
- if (config.snapToData && this.datum) {
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(this.datum, this.accessors.baseline, this.datumIndex) || 0;
173
- const stackedValues = getStackedValues(this.datum, this.datumIndex, ...yStackedAccessors)
174
- .map((value, index, arr) => ({
175
- y: this.yScale(value + baselineValue),
176
- opacity: isNumber(getNumber(this.datum, yStackedAccessors[index])) ? 1 : 0,
177
- color: getColor(this.datum, config.color, index),
178
- strokeColor: config.strokeColor ? getColor(this.datum, config.strokeColor, index) : undefined,
179
- strokeWidth: config.strokeWidth ? getNumber(this.datum, config.strokeWidth, index) : undefined,
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(this.datum, a);
280
+ const value = getNumber(datum, a);
281
+ const yPixel = isNumber(value) ? this.yScale(value) : 0;
184
282
  return {
185
- y: this.yScale(value),
283
+ y: yPixel,
186
284
  opacity: isNumber(value) ? 1 : 0,
187
- color: getColor(this.datum, config.color, stackedValues.length + index),
188
- strokeColor: config.strokeColor ? getColor(this.datum, config.strokeColor, index) : undefined,
189
- strokeWidth: config.strokeWidth ? getNumber(this.datum, config.strokeWidth, index) : undefined,
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,