@unovis/ts 1.6.0-bigip.1 → 1.6.0-bigip.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/area/index.js +2 -1
- package/components/area/index.js.map +1 -1
- package/components/crosshair/config.d.ts +12 -12
- package/components/crosshair/config.js +1 -1
- package/components/crosshair/config.js.map +1 -1
- package/components/crosshair/index.d.ts +4 -12
- package/components/crosshair/index.js +124 -229
- package/components/crosshair/index.js.map +1 -1
- package/containers/single-container/index.js +3 -1
- package/containers/single-container/index.js.map +1 -1
- package/containers/xy-container/index.js +3 -1
- package/containers/xy-container/index.js.map +1 -1
- package/core/component/index.d.ts +4 -0
- package/core/component/index.js +6 -0
- package/core/component/index.js.map +1 -1
- package/core/xy-component/index.d.ts +1 -0
- package/core/xy-component/index.js +3 -1
- package/core/xy-component/index.js.map +1 -1
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/types/data.d.ts +5 -0
- package/types/data.js +7 -0
- package/types/data.js.map +1 -1
- package/types.js +1 -1
- package/utils/data.d.ts +3 -3
- package/utils/data.js +38 -8
- package/utils/data.js.map +1 -1
package/components/area/index.js
CHANGED
|
@@ -101,7 +101,8 @@ class Area extends XYComponentCore {
|
|
|
101
101
|
getYDataExtent(scaleByVisibleData) {
|
|
102
102
|
const { config, datamodel } = this;
|
|
103
103
|
const yAccessors = (isArray(config.y) ? config.y : [config.y]);
|
|
104
|
-
const
|
|
104
|
+
const xDomain = this.xScale.domain();
|
|
105
|
+
const data = scaleByVisibleData ? filterDataByRange(datamodel.data, xDomain, config.x, true) : datamodel.data;
|
|
105
106
|
return getStackedExtent(data, config.baseline, ...yAccessors);
|
|
106
107
|
}
|
|
107
108
|
_emptyPath() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/area/index.ts"],"sourcesContent":["import { select } from 'd3-selection'\nimport { Transition } from 'd3-transition'\nimport { area, Area as AreaInterface } from 'd3-shape'\nimport { interpolatePath } from 'd3-interpolate-path'\n\n// Core\nimport { XYComponentCore } from 'core/xy-component'\n\n// Utils\nimport { getNumber, getString, isArray, isNumber, getStackedExtent, getStackedData, filterDataByRange } from 'utils/data'\nimport { smartTransition } from 'utils/d3'\nimport { getColor } from 'utils/color'\n\n// Types\nimport { Curve, CurveType } from 'types/curve'\nimport { NumericAccessor } from 'types/accessor'\n\n// Local Types\nimport { AreaDatum } from './types'\n\n// Config\nimport { AreaDefaultConfig, AreaConfigInterface } from './config'\n\n// Styles\nimport * as s from './style'\n\nexport class Area<Datum> extends XYComponentCore<Datum, AreaConfigInterface<Datum>> {\n static selectors = s\n protected _defaultConfig = AreaDefaultConfig as AreaConfigInterface<Datum>\n public config: AreaConfigInterface<Datum> = this._defaultConfig\n public stacked = true\n private _areaGen: AreaInterface<AreaDatum>\n private _prevNegative: boolean[] | undefined // To help guessing the stack direction when an accessor was set to null or 0\n\n events = {\n [Area.selectors.area]: {},\n }\n\n constructor (config?: AreaConfigInterface<Datum>) {\n super()\n if (config) this.setConfig(config)\n\n // Determine if the provided chart should be stacked\n this.stacked = Array.isArray(this.config.y)\n }\n\n _render (customDuration?: number): void {\n super._render(customDuration)\n const { config, datamodel: { data } } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\n\n const curveGen = Curve[config.curveType as CurveType]\n this._areaGen = area<AreaDatum>()\n .x(d => d.x)\n .y0(d => d.y0)\n .y1(d => d.y1)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n .curve(curveGen)\n\n const yAccessors = (isArray(config.y) ? config.y : [config.y]) as NumericAccessor<Datum>[]\n const areaDataX = data.map((d, i) => this.xScale(getNumber(d, config.x, i)))\n\n const stacked = getStackedData(data, config.baseline, yAccessors, this._prevNegative)\n this._prevNegative = stacked.map(s => !!s.isMostlyNegative)\n const minHeightCumulativeArray: number[] = []\n const stackedData: AreaDatum[][] = stacked.map(\n arr => arr.map(\n (d, j) => {\n const x = areaDataX[j]\n const y0 = this.yScale(d[0])\n const y1 = this.yScale(d[1])\n const isNegativeArea = y1 > y0\n\n // Get cumulative adjustment and apply in the correct direction\n const cumulative = minHeightCumulativeArray[j] || 0\n const adjustedY0 = isNegativeArea ? y0 + cumulative : y0 - cumulative\n const adjustedY1 = isNegativeArea ? y1 + cumulative : y1 - cumulative\n\n // Calculate height adjustment if needed\n let heightAdjustment = 0\n if ((config.minHeight || config.minHeight1Px) &&\n Math.abs(adjustedY1 - adjustedY0) < (config.minHeight ?? 1)) {\n heightAdjustment = (config.minHeight ?? 1) - Math.abs(adjustedY1 - adjustedY0)\n minHeightCumulativeArray[j] = cumulative + heightAdjustment\n }\n\n return {\n x,\n y0: adjustedY0,\n y1: isNegativeArea ? adjustedY1 + heightAdjustment : adjustedY1 - heightAdjustment,\n }\n }\n )\n )\n\n // We reverse the data in order to have the first areas to be displayed on top\n // for better visibility when they're close to zero\n const areaMaxIdx = stackedData.length - 1\n const stackedDataReversed = stackedData.reverse()\n const areas = this.g\n .selectAll<SVGPathElement, AreaDatum>(`.${s.area}`)\n .data(stackedDataReversed)\n\n const areasEnter = areas.enter().append('path')\n .attr('class', s.area)\n .attr('d', d => this._areaGen(d) || this._emptyPath())\n .style('opacity', 0)\n .style('fill', (d, i) => getColor(data, config.color, areaMaxIdx - i))\n\n const areasMerged = smartTransition(areasEnter.merge(areas), duration)\n .style('opacity', (d, i) => {\n const isDefined = d.some(p => (p.y0 - p.y1) !== 0)\n return isDefined ? getNumber(data, config.opacity, areaMaxIdx - i) : 0\n })\n .style('fill', (d, i) => getColor(data, config.color, areaMaxIdx - i))\n .style('cursor', (d, i) => getString(data, config.cursor, areaMaxIdx - i))\n\n if (duration) {\n const transition = areasMerged as Transition<SVGPathElement, AreaDatum[], SVGGElement, AreaDatum[]>\n transition.attrTween('d', (d, i, el) => {\n const previous = select(el[i]).attr('d')\n const next = this._areaGen(d) || this._emptyPath()\n return interpolatePath(previous, next)\n })\n } else {\n areasMerged.attr('d', d => this._areaGen(d) || this._emptyPath())\n }\n\n smartTransition(areas.exit(), duration)\n .style('opacity', 0)\n .remove()\n }\n\n getYDataExtent (scaleByVisibleData: boolean): number[] {\n const { config, datamodel } = this\n const yAccessors = (isArray(config.y) ? config.y : [config.y]) as NumericAccessor<Datum>[]\n\n const data = scaleByVisibleData ? filterDataByRange(datamodel.data, this.xScale.domain() as [number, number], config.x) : datamodel.data\n return getStackedExtent(data, config.baseline, ...yAccessors)\n }\n\n _emptyPath (): string {\n const xRange = this.xScale.range()\n const yDomain = this.yScale.domain() as number[]\n\n const y0 = this.yScale((yDomain[0] + yDomain[1]) / 2)\n const y1 = y0\n\n return this._areaGen([\n { y0, y1, x: xRange[0] },\n { y0, y1, x: xRange[1] },\n ])\n }\n}\n"],"names":["s.area","s"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/area/index.ts"],"sourcesContent":["import { select } from 'd3-selection'\nimport { Transition } from 'd3-transition'\nimport { area, Area as AreaInterface } from 'd3-shape'\nimport { interpolatePath } from 'd3-interpolate-path'\n\n// Core\nimport { XYComponentCore } from 'core/xy-component'\n\n// Utils\nimport { getNumber, getString, isArray, isNumber, getStackedExtent, getStackedData, filterDataByRange } from 'utils/data'\nimport { smartTransition } from 'utils/d3'\nimport { getColor } from 'utils/color'\n\n// Types\nimport { Curve, CurveType } from 'types/curve'\nimport { NumericAccessor } from 'types/accessor'\n\n// Local Types\nimport { AreaDatum } from './types'\n\n// Config\nimport { AreaDefaultConfig, AreaConfigInterface } from './config'\n\n// Styles\nimport * as s from './style'\n\nexport class Area<Datum> extends XYComponentCore<Datum, AreaConfigInterface<Datum>> {\n static selectors = s\n protected _defaultConfig = AreaDefaultConfig as AreaConfigInterface<Datum>\n public config: AreaConfigInterface<Datum> = this._defaultConfig\n public stacked = true\n private _areaGen: AreaInterface<AreaDatum>\n private _prevNegative: boolean[] | undefined // To help guessing the stack direction when an accessor was set to null or 0\n\n events = {\n [Area.selectors.area]: {},\n }\n\n constructor (config?: AreaConfigInterface<Datum>) {\n super()\n if (config) this.setConfig(config)\n\n // Determine if the provided chart should be stacked\n this.stacked = Array.isArray(this.config.y)\n }\n\n _render (customDuration?: number): void {\n super._render(customDuration)\n const { config, datamodel: { data } } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\n\n const curveGen = Curve[config.curveType as CurveType]\n this._areaGen = area<AreaDatum>()\n .x(d => d.x)\n .y0(d => d.y0)\n .y1(d => d.y1)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n .curve(curveGen)\n\n const yAccessors = (isArray(config.y) ? config.y : [config.y]) as NumericAccessor<Datum>[]\n const areaDataX = data.map((d, i) => this.xScale(getNumber(d, config.x, i)))\n\n const stacked = getStackedData(data, config.baseline, yAccessors, this._prevNegative)\n this._prevNegative = stacked.map(s => !!s.isMostlyNegative)\n const minHeightCumulativeArray: number[] = []\n const stackedData: AreaDatum[][] = stacked.map(\n arr => arr.map(\n (d, j) => {\n const x = areaDataX[j]\n const y0 = this.yScale(d[0])\n const y1 = this.yScale(d[1])\n const isNegativeArea = y1 > y0\n\n // Get cumulative adjustment and apply in the correct direction\n const cumulative = minHeightCumulativeArray[j] || 0\n const adjustedY0 = isNegativeArea ? y0 + cumulative : y0 - cumulative\n const adjustedY1 = isNegativeArea ? y1 + cumulative : y1 - cumulative\n\n // Calculate height adjustment if needed\n let heightAdjustment = 0\n if ((config.minHeight || config.minHeight1Px) &&\n Math.abs(adjustedY1 - adjustedY0) < (config.minHeight ?? 1)) {\n heightAdjustment = (config.minHeight ?? 1) - Math.abs(adjustedY1 - adjustedY0)\n minHeightCumulativeArray[j] = cumulative + heightAdjustment\n }\n\n return {\n x,\n y0: adjustedY0,\n y1: isNegativeArea ? adjustedY1 + heightAdjustment : adjustedY1 - heightAdjustment,\n }\n }\n )\n )\n\n // We reverse the data in order to have the first areas to be displayed on top\n // for better visibility when they're close to zero\n const areaMaxIdx = stackedData.length - 1\n const stackedDataReversed = stackedData.reverse()\n const areas = this.g\n .selectAll<SVGPathElement, AreaDatum>(`.${s.area}`)\n .data(stackedDataReversed)\n\n const areasEnter = areas.enter().append('path')\n .attr('class', s.area)\n .attr('d', d => this._areaGen(d) || this._emptyPath())\n .style('opacity', 0)\n .style('fill', (d, i) => getColor(data, config.color, areaMaxIdx - i))\n\n const areasMerged = smartTransition(areasEnter.merge(areas), duration)\n .style('opacity', (d, i) => {\n const isDefined = d.some(p => (p.y0 - p.y1) !== 0)\n return isDefined ? getNumber(data, config.opacity, areaMaxIdx - i) : 0\n })\n .style('fill', (d, i) => getColor(data, config.color, areaMaxIdx - i))\n .style('cursor', (d, i) => getString(data, config.cursor, areaMaxIdx - i))\n\n if (duration) {\n const transition = areasMerged as Transition<SVGPathElement, AreaDatum[], SVGGElement, AreaDatum[]>\n transition.attrTween('d', (d, i, el) => {\n const previous = select(el[i]).attr('d')\n const next = this._areaGen(d) || this._emptyPath()\n return interpolatePath(previous, next)\n })\n } else {\n areasMerged.attr('d', d => this._areaGen(d) || this._emptyPath())\n }\n\n smartTransition(areas.exit(), duration)\n .style('opacity', 0)\n .remove()\n }\n\n getYDataExtent (scaleByVisibleData: boolean): number[] {\n const { config, datamodel } = this\n const yAccessors = (isArray(config.y) ? config.y : [config.y]) as NumericAccessor<Datum>[]\n\n const xDomain = this.xScale.domain() as [number, number]\n const data = scaleByVisibleData ? filterDataByRange(datamodel.data, xDomain, config.x, true) : datamodel.data\n return getStackedExtent(data, config.baseline, ...yAccessors)\n }\n\n _emptyPath (): string {\n const xRange = this.xScale.range()\n const yDomain = this.yScale.domain() as number[]\n\n const y0 = this.yScale((yDomain[0] + yDomain[1]) / 2)\n const y1 = y0\n\n return this._areaGen([\n { y0, y1, x: xRange[0] },\n { y0, y1, x: xRange[1] },\n ])\n }\n}\n"],"names":["s.area","s"],"mappings":"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"}
|
|
@@ -21,9 +21,11 @@ export interface CrosshairConfigInterface<Datum> extends WithOptional<XYComponen
|
|
|
21
21
|
baseline?: NumericAccessor<Datum>;
|
|
22
22
|
/** An instance of the Tooltip component to be used with Crosshair. Default: `undefined` */
|
|
23
23
|
tooltip?: Tooltip | undefined;
|
|
24
|
-
/** Tooltip template accessor. The function is supposed to return either a valid HTML string or an HTMLElement.
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
/** Tooltip template accessor. The function is supposed to return either a valid HTML string or an HTMLElement.
|
|
25
|
+
* When snapToData is false, datum will be undefined but nearestDatumIndex and data will be provided.
|
|
26
|
+
* Default: `d => ''` */
|
|
27
|
+
template?: (datum: Datum, x: number | Date, nearestDatumIndex?: number, data?: Datum[]) => string | HTMLElement;
|
|
28
|
+
/** Hide Crosshair when the corresponding datum element is far from mouse pointer. Default: `true` */
|
|
27
29
|
hideWhenFarFromPointer?: boolean;
|
|
28
30
|
/** Distance in pixels to check in the hideWhenFarFromPointer condition. Default: `100` */
|
|
29
31
|
hideWhenFarFromPointerDistance?: number;
|
|
@@ -34,17 +36,15 @@ export interface CrosshairConfigInterface<Datum> extends WithOptional<XYComponen
|
|
|
34
36
|
*/
|
|
35
37
|
snapToData?: boolean;
|
|
36
38
|
/** Custom function for setting up the crosshair circles, usually needed when `snapToData` is set to `false`.
|
|
37
|
-
* The function receives the horizontal position of the crosshair (in the data space, not in pixels), the data array
|
|
38
|
-
*
|
|
39
|
+
* The function receives the horizontal position of the crosshair (in the data space, not in pixels), the data array,
|
|
40
|
+
* the `yScale` instance to help you calculate the correct vertical position of the circles, and the nearest datum index.
|
|
39
41
|
* It has to return an array of the CrosshairCircle objects: `{ y: number; color: string; opacity?: number }[]`.
|
|
40
42
|
* Default: `undefined`
|
|
41
43
|
*/
|
|
42
|
-
getCircles?: (x: number | Date
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
/** Force
|
|
46
|
-
|
|
47
|
-
/** Callback function called when crosshair position changes. Receives x position in data space. Default: `undefined` */
|
|
48
|
-
onCrosshairMove?: (x: number | Date | undefined) => void;
|
|
44
|
+
getCircles?: (x: number | Date, data: Datum[], yScale: ContinuousScale, nearestDatumIndex?: number) => CrosshairCircle[];
|
|
45
|
+
/** Callback function that is called when the crosshair is moved. Default: `undefined` */
|
|
46
|
+
onCrosshairMove?: (x: number | Date, datum: Datum | undefined, datumIndex: number | undefined) => void;
|
|
47
|
+
/** Force the crosshair to show at a specific position. Default: `undefined` */
|
|
48
|
+
forceShowAt?: number | Date;
|
|
49
49
|
}
|
|
50
50
|
export declare const CrosshairDefaultConfig: CrosshairConfigInterface<unknown>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { XYComponentDefaultConfig } from '../../core/xy-component/config.js';
|
|
2
2
|
|
|
3
|
-
const CrosshairDefaultConfig = Object.assign(Object.assign({}, XYComponentDefaultConfig), { yStacked: undefined, baseline: null, duration: 100, tooltip: undefined, template: (d, x) => '', hideWhenFarFromPointer: true, hideWhenFarFromPointerDistance: 100, snapToData: true, getCircles: undefined, color: undefined, strokeColor: undefined, strokeWidth: undefined,
|
|
3
|
+
const CrosshairDefaultConfig = Object.assign(Object.assign({}, XYComponentDefaultConfig), { yStacked: undefined, baseline: null, duration: 100, tooltip: undefined, template: (d, x, nearestDatumIndex, data) => '', hideWhenFarFromPointer: true, hideWhenFarFromPointerDistance: 100, snapToData: true, getCircles: undefined, color: undefined, strokeColor: undefined, strokeWidth: undefined, onCrosshairMove: undefined, forceShowAt: undefined });
|
|
4
4
|
|
|
5
5
|
export { CrosshairDefaultConfig };
|
|
6
6
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sources":["../../../src/components/crosshair/config.ts"],"sourcesContent":["import { XYComponentConfigInterface, XYComponentDefaultConfig } from 'core/xy-component/config'\nimport { Tooltip } from 'components/tooltip'\n\n// Types\nimport { NumericAccessor, ColorAccessor } from 'types/accessor'\nimport { ContinuousScale } from 'types/scale'\nimport { WithOptional } from 'types/misc'\nimport { CrosshairCircle } from './types'\n\n// We extend partial XY config interface because x and y properties are optional for Crosshair\nexport interface CrosshairConfigInterface<Datum> extends WithOptional<XYComponentConfigInterface<Datum>, 'x' | 'y'> {\n /** Optional accessor function for getting the values along the X axis. Default: `undefined` */\n x?: NumericAccessor<Datum>;\n /** Optional single of multiple accessor functions for getting the values along the Y axis. Default: `undefined` */\n y?: NumericAccessor<Datum> | NumericAccessor<Datum>[];\n /** Optional color array or color accessor function for crosshair circles. Default: `d => d.color` */\n color?: ColorAccessor<Datum>;\n /** Optional stroke color accessor function for crosshair circles. Default: `undefined` */\n strokeColor?: ColorAccessor<Datum>;\n /** Optional stroke width for crosshair circles. Default: `undefined` */\n strokeWidth?: NumericAccessor<Datum>;\n /** Separate array of accessors for stacked components (eg StackedBar, Area). Default: `undefined` */\n yStacked?: NumericAccessor<Datum>[];\n /** Baseline accessor function for stacked values, useful with stacked areas. Default: `null` */\n baseline?: NumericAccessor<Datum>;\n /** An instance of the Tooltip component to be used with Crosshair. Default: `undefined` */\n tooltip?: Tooltip | undefined;\n /** Tooltip template accessor. The function is supposed to return either a valid HTML string or an HTMLElement
|
|
1
|
+
{"version":3,"file":"config.js","sources":["../../../src/components/crosshair/config.ts"],"sourcesContent":["import { XYComponentConfigInterface, XYComponentDefaultConfig } from 'core/xy-component/config'\nimport { Tooltip } from 'components/tooltip'\n\n// Types\nimport { NumericAccessor, ColorAccessor } from 'types/accessor'\nimport { ContinuousScale } from 'types/scale'\nimport { WithOptional } from 'types/misc'\nimport { CrosshairCircle } from './types'\n\n// We extend partial XY config interface because x and y properties are optional for Crosshair\nexport interface CrosshairConfigInterface<Datum> extends WithOptional<XYComponentConfigInterface<Datum>, 'x' | 'y'> {\n /** Optional accessor function for getting the values along the X axis. Default: `undefined` */\n x?: NumericAccessor<Datum>;\n /** Optional single of multiple accessor functions for getting the values along the Y axis. Default: `undefined` */\n y?: NumericAccessor<Datum> | NumericAccessor<Datum>[];\n /** Optional color array or color accessor function for crosshair circles. Default: `d => d.color` */\n color?: ColorAccessor<Datum>;\n /** Optional stroke color accessor function for crosshair circles. Default: `undefined` */\n strokeColor?: ColorAccessor<Datum>;\n /** Optional stroke width for crosshair circles. Default: `undefined` */\n strokeWidth?: NumericAccessor<Datum>;\n /** Separate array of accessors for stacked components (eg StackedBar, Area). Default: `undefined` */\n yStacked?: NumericAccessor<Datum>[];\n /** Baseline accessor function for stacked values, useful with stacked areas. Default: `null` */\n baseline?: NumericAccessor<Datum>;\n /** An instance of the Tooltip component to be used with Crosshair. Default: `undefined` */\n tooltip?: Tooltip | undefined;\n /** Tooltip template accessor. The function is supposed to return either a valid HTML string or an HTMLElement.\n * When snapToData is false, datum will be undefined but nearestDatumIndex and data will be provided.\n * Default: `d => ''` */\n template?: (datum: Datum, x: number | Date, nearestDatumIndex?: number, data?: Datum[]) => string | HTMLElement;\n /** Hide Crosshair when the corresponding datum element is far from mouse pointer. Default: `true` */\n hideWhenFarFromPointer?: boolean;\n /** Distance in pixels to check in the hideWhenFarFromPointer condition. Default: `100` */\n hideWhenFarFromPointerDistance?: number;\n /** Snap to the nearest data point.\n * If disabled, the tooltip template will receive only the horizontal position of the crosshair and you'll be responsible\n * for getting the underlying data records and crosshair circles (see the `getCircles` configuration option).\n * Default: `true`\n */\n snapToData?: boolean;\n /** Custom function for setting up the crosshair circles, usually needed when `snapToData` is set to `false`.\n * The function receives the horizontal position of the crosshair (in the data space, not in pixels), the data array,\n * the `yScale` instance to help you calculate the correct vertical position of the circles, and the nearest datum index.\n * It has to return an array of the CrosshairCircle objects: `{ y: number; color: string; opacity?: number }[]`.\n * Default: `undefined`\n */\n getCircles?: (x: number | Date, data: Datum[], yScale: ContinuousScale, nearestDatumIndex?: number) => CrosshairCircle[];\n /** Callback function that is called when the crosshair is moved. Default: `undefined` */\n onCrosshairMove?: (x: number | Date, datum: Datum | undefined, datumIndex: number | undefined) => void;\n /** Force the crosshair to show at a specific position. Default: `undefined` */\n forceShowAt?: number | Date;\n}\n\nexport const CrosshairDefaultConfig: CrosshairConfigInterface<unknown> = {\n ...XYComponentDefaultConfig,\n yStacked: undefined,\n baseline: null,\n duration: 100,\n tooltip: undefined,\n template: <Datum>(d: Datum | undefined, x: number | Date, nearestDatumIndex?: number, data?: Datum[]): string => '',\n hideWhenFarFromPointer: true,\n hideWhenFarFromPointerDistance: 100,\n snapToData: true,\n getCircles: undefined,\n color: undefined,\n strokeColor: undefined,\n strokeWidth: undefined,\n onCrosshairMove: undefined,\n forceShowAt: undefined,\n}\n\n"],"names":[],"mappings":";;AAsDO,MAAM,sBAAsB,GAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAC9B,wBAAwB,CAC3B,EAAA,EAAA,QAAQ,EAAE,SAAS,EACnB,QAAQ,EAAE,IAAI,EACd,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,CAAQ,CAAoB,EAAE,CAAgB,EAAE,iBAA0B,EAAE,IAAc,KAAa,EAAE,EACnH,sBAAsB,EAAE,IAAI,EAC5B,8BAA8B,EAAE,GAAG,EACnC,UAAU,EAAE,IAAI,EAChB,UAAU,EAAE,SAAS,EACrB,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,SAAS,EACtB,WAAW,EAAE,SAAS,EACtB,eAAe,EAAE,SAAS,EAC1B,WAAW,EAAE,SAAS;;;;"}
|
|
@@ -11,13 +11,10 @@ export declare class Crosshair<Datum> extends XYComponentCore<Datum, CrosshairCo
|
|
|
11
11
|
config: CrosshairConfigInterface<Datum>;
|
|
12
12
|
container: Selection<SVGSVGElement, any, SVGSVGElement, any>;
|
|
13
13
|
line: Selection<SVGLineElement, any, SVGElement, any>;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
show: boolean;
|
|
14
|
+
private _xPx;
|
|
15
|
+
private _yPx;
|
|
16
|
+
private _mouseEvent;
|
|
18
17
|
private _animFrameId;
|
|
19
|
-
private _dataX;
|
|
20
|
-
private _isMouseOver;
|
|
21
18
|
/** Tooltip component to be used by Crosshair if not provided by the config.
|
|
22
19
|
* This property is supposed to be set externally by a container component like XYContainer. */
|
|
23
20
|
tooltip: Tooltip;
|
|
@@ -27,17 +24,12 @@ export declare class Crosshair<Datum> extends XYComponentCore<Datum, CrosshairCo
|
|
|
27
24
|
get accessors(): CrosshairAccessors<Datum>;
|
|
28
25
|
constructor(config?: CrosshairConfigInterface<Datum>);
|
|
29
26
|
setContainer(containerSvg: Selection<SVGSVGElement, unknown, SVGSVGElement, unknown>): void;
|
|
30
|
-
setConfig(config: CrosshairConfigInterface<Datum>): void;
|
|
31
27
|
_render(customDuration?: number): void;
|
|
32
28
|
hide(): void;
|
|
33
|
-
destroy(): void;
|
|
34
29
|
_onMouseMove(event: MouseEvent): void;
|
|
35
|
-
private _processMouseMove;
|
|
36
30
|
_onMouseOut(): void;
|
|
37
|
-
_showTooltip(
|
|
31
|
+
_showTooltip(datum: Datum, xValue: number, pos: [number, number], nearestDatumIndex?: number): void;
|
|
38
32
|
_hideTooltip(): void;
|
|
39
33
|
getYDataExtent(): number[];
|
|
40
34
|
private getCircleData;
|
|
41
|
-
_updateFromSync(xData: number | Date | undefined): void;
|
|
42
|
-
private _getSyncState;
|
|
43
35
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
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, clamp, getNumber, 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
|
+
import { FindNearestDirection } from '../../types/data.js';
|
|
8
9
|
import { CrosshairDefaultConfig } from './config.js';
|
|
9
10
|
import * as style from './style.js';
|
|
10
11
|
import { line, circle } from './style.js';
|
|
@@ -15,11 +16,10 @@ class Crosshair extends XYComponentCore {
|
|
|
15
16
|
this.clippable = true; // Don't apply clipping path to this component. See XYContainer
|
|
16
17
|
this._defaultConfig = CrosshairDefaultConfig;
|
|
17
18
|
this.config = this._defaultConfig;
|
|
18
|
-
this.
|
|
19
|
-
this.
|
|
19
|
+
this._xPx = undefined;
|
|
20
|
+
this._yPx = undefined;
|
|
21
|
+
this._mouseEvent = undefined;
|
|
20
22
|
this._animFrameId = null;
|
|
21
|
-
this._dataX = undefined;
|
|
22
|
-
this._isMouseOver = false;
|
|
23
23
|
/** Accessors passed externally (e.g. from XYContainer) */
|
|
24
24
|
this._accessors = {
|
|
25
25
|
x: undefined,
|
|
@@ -28,8 +28,8 @@ class Crosshair extends XYComponentCore {
|
|
|
28
28
|
baseline: undefined,
|
|
29
29
|
};
|
|
30
30
|
if (config)
|
|
31
|
-
this.
|
|
32
|
-
this.g.style('opacity',
|
|
31
|
+
this.setConfig(config);
|
|
32
|
+
this.g.style('opacity', 0);
|
|
33
33
|
this.line = this.g.append('line')
|
|
34
34
|
.attr('class', line);
|
|
35
35
|
}
|
|
@@ -37,44 +37,100 @@ class Crosshair extends XYComponentCore {
|
|
|
37
37
|
get accessors() {
|
|
38
38
|
var _a;
|
|
39
39
|
const { config } = this;
|
|
40
|
-
|
|
41
|
-
const x = config.x
|
|
42
|
-
const yAcc = config.y
|
|
40
|
+
const hasConfig = !!(config.x || config.y || config.yStacked);
|
|
41
|
+
const x = hasConfig ? config.x : this._accessors.x;
|
|
42
|
+
const yAcc = hasConfig ? config.y : this._accessors.y;
|
|
43
43
|
const y = yAcc ? (isArray(yAcc) ? yAcc : [yAcc]) : undefined;
|
|
44
|
-
const yStacked = config.yStacked
|
|
44
|
+
const yStacked = hasConfig ? config.yStacked : this._accessors.yStacked;
|
|
45
45
|
const baseline = (_a = config.baseline) !== null && _a !== void 0 ? _a : this._accessors.baseline;
|
|
46
46
|
return { x, y, yStacked, baseline };
|
|
47
47
|
}
|
|
48
48
|
setContainer(containerSvg) {
|
|
49
|
+
// Set up mousemove event for Crosshair
|
|
49
50
|
this.container = containerSvg;
|
|
50
51
|
this.container.on('mousemove.crosshair', this._onMouseMove.bind(this));
|
|
51
52
|
this.container.on('mouseout.crosshair', this._onMouseOut.bind(this));
|
|
52
|
-
this._render();
|
|
53
|
-
}
|
|
54
|
-
setConfig(config) {
|
|
55
|
-
super.setConfig(config);
|
|
56
|
-
// For synchronized charts, update from sync when config changes
|
|
57
|
-
const { isActive, enableSync } = this._getSyncState();
|
|
58
|
-
if (enableSync && !isActive && (isNumber(config.xPosition) || config.xPosition instanceof Date)) {
|
|
59
|
-
this._updateFromSync(config.xPosition);
|
|
60
|
-
}
|
|
61
53
|
}
|
|
62
54
|
_render(customDuration) {
|
|
63
|
-
|
|
55
|
+
var _a, _b, _c, _d;
|
|
56
|
+
const { config, datamodel } = this;
|
|
64
57
|
const duration = isNumber(customDuration) ? customDuration : config.duration;
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
58
|
+
const isForceShowAtDefined = config.forceShowAt !== undefined;
|
|
59
|
+
const xPx = isForceShowAtDefined ? this.xScale(config.forceShowAt) : this._xPx;
|
|
60
|
+
const xValue = this.xScale.invert(xPx);
|
|
61
|
+
let datum;
|
|
62
|
+
let datumIndex;
|
|
63
|
+
let nearestDatumIndex;
|
|
64
|
+
// Always calculate the nearest datum index for template and getCircles functions
|
|
65
|
+
if (((_a = datamodel.data) === null || _a === void 0 ? void 0 : _a.length) && this.accessors.x) {
|
|
66
|
+
const nearestDatum = getNearest(datamodel.data, xValue, this.accessors.x, FindNearestDirection.Left);
|
|
67
|
+
nearestDatumIndex = datamodel.data.indexOf(nearestDatum);
|
|
68
|
+
}
|
|
69
|
+
if (config.snapToData) {
|
|
70
|
+
if (!this.accessors.y && !this.accessors.yStacked && ((_b = datamodel.data) === null || _b === void 0 ? void 0 : _b.length)) {
|
|
71
|
+
console.warn('Unovis | Crosshair: Y accessors have not been configured. Please check if they\'re present in the configuration object');
|
|
72
|
+
}
|
|
73
|
+
datum = getNearest(datamodel.data, xValue, this.accessors.x);
|
|
74
|
+
datumIndex = datamodel.data.indexOf(datum);
|
|
75
|
+
if (!datum)
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const xRange = this.xScale.range();
|
|
79
|
+
const yRange = this.yScale.range();
|
|
80
|
+
const xClamped = config.snapToData
|
|
81
|
+
? clamp(Math.round(this.xScale(getNumber(datum, this.accessors.x, datumIndex))), 0, this._width)
|
|
82
|
+
: clamp(xPx, xRange[0], xRange[1]);
|
|
83
|
+
const isCrosshairWithinXRange = (xPx >= xRange[0]) && (xPx <= xRange[1]);
|
|
84
|
+
const isCrosshairWithinYRange = (this._yPx >= yRange[1]) && (this._yPx <= yRange[0]);
|
|
85
|
+
let shouldShow = this._xPx ? isCrosshairWithinXRange && isCrosshairWithinYRange : isCrosshairWithinXRange;
|
|
86
|
+
// If the crosshair is far from the mouse pointer (usually when `snapToData` is `true` and data resolution is low), hide it
|
|
87
|
+
if (config.hideWhenFarFromPointer && ((Math.abs(xClamped - (+xPx)) >= config.hideWhenFarFromPointerDistance))) {
|
|
88
|
+
shouldShow = false;
|
|
89
|
+
}
|
|
90
|
+
const tooltip = (_c = config.tooltip) !== null && _c !== void 0 ? _c : this.tooltip;
|
|
91
|
+
if (shouldShow && tooltip) {
|
|
92
|
+
const container = tooltip.getContainer() || this.container.node();
|
|
93
|
+
const isContainerBody = tooltip.isContainerBody();
|
|
94
|
+
if (isForceShowAtDefined) {
|
|
95
|
+
// Convert SVG coordinates to screen coordinates
|
|
96
|
+
const containerRect = this.container.node().getBoundingClientRect();
|
|
97
|
+
// Use the actual left margin from the container
|
|
98
|
+
const screenX = (isContainerBody ? xPx + containerRect.left : xPx) + this._containerMargin.left;
|
|
99
|
+
const screenY = this._height / 2 + (isContainerBody ? containerRect.top : 0);
|
|
100
|
+
const pos = [screenX, screenY];
|
|
101
|
+
this._showTooltip(datum, xValue, pos, nearestDatumIndex);
|
|
102
|
+
}
|
|
103
|
+
else if (this._mouseEvent) {
|
|
104
|
+
const pos = (isContainerBody ? [this._mouseEvent.clientX, this._mouseEvent.clientY] : pointer(this._mouseEvent, container));
|
|
105
|
+
this._showTooltip(datum, xValue, pos, nearestDatumIndex);
|
|
106
|
+
}
|
|
69
107
|
}
|
|
70
|
-
|
|
108
|
+
else
|
|
109
|
+
this._hideTooltip();
|
|
110
|
+
// Trigger `onCrosshairMove` if the render was triggered by a mouse move event
|
|
111
|
+
if (this._mouseEvent) {
|
|
112
|
+
(_d = config.onCrosshairMove) === null || _d === void 0 ? void 0 : _d.call(config, shouldShow ? this.xScale.invert(this._xPx) : undefined, datum, datumIndex);
|
|
113
|
+
this._mouseEvent = undefined;
|
|
114
|
+
}
|
|
115
|
+
// When `config.forceShowAt` becomes undefined, the component will "jump" to `this._xPx` which is set to the last mouse position.
|
|
116
|
+
// This looks off, so we set `this._xPx` to `xPx` to make it look like the crosshair is rendered at the forced position
|
|
117
|
+
if (isForceShowAtDefined) {
|
|
118
|
+
this._xPx = undefined;
|
|
119
|
+
}
|
|
120
|
+
smartTransition(this.g, duration)
|
|
121
|
+
.style('opacity', shouldShow ? 1 : 0);
|
|
71
122
|
this.line
|
|
72
123
|
.attr('y1', 0)
|
|
73
|
-
.attr('
|
|
124
|
+
.attr('y1', this._height);
|
|
125
|
+
// Don't render the crosshair if the xPx is not finite
|
|
126
|
+
if (!isFinite(xClamped))
|
|
127
|
+
return;
|
|
74
128
|
smartTransition(this.line, duration, easeLinear)
|
|
75
|
-
.attr('x1',
|
|
76
|
-
.attr('x2',
|
|
77
|
-
const circleData =
|
|
129
|
+
.attr('x1', xClamped)
|
|
130
|
+
.attr('x2', xClamped);
|
|
131
|
+
const circleData = isFunction(config.getCircles)
|
|
132
|
+
? config.getCircles(xValue, datamodel.data, this.yScale, nearestDatumIndex)
|
|
133
|
+
: this.getCircleData(datum, datumIndex);
|
|
78
134
|
const circles = this.g
|
|
79
135
|
.selectAll('circle')
|
|
80
136
|
.data(circleData, (d, i) => { var _a; return (_a = d.id) !== null && _a !== void 0 ? _a : i; });
|
|
@@ -82,13 +138,13 @@ class Crosshair extends XYComponentCore {
|
|
|
82
138
|
.append('circle')
|
|
83
139
|
.attr('class', circle)
|
|
84
140
|
.attr('r', 0)
|
|
85
|
-
.attr('cx',
|
|
141
|
+
.attr('cx', xClamped)
|
|
86
142
|
.attr('cy', d => d.y)
|
|
87
143
|
.style('fill', d => d.color)
|
|
88
144
|
.style('stroke', d => d.strokeColor)
|
|
89
145
|
.style('stroke-width', d => d.strokeWidth);
|
|
90
146
|
smartTransition(circlesEnter.merge(circles), duration, easeLinear)
|
|
91
|
-
.attr('cx',
|
|
147
|
+
.attr('cx', xClamped)
|
|
92
148
|
.attr('cy', d => d.y)
|
|
93
149
|
.attr('r', 4)
|
|
94
150
|
.style('opacity', d => d.opacity)
|
|
@@ -100,108 +156,36 @@ class Crosshair extends XYComponentCore {
|
|
|
100
156
|
hide() {
|
|
101
157
|
this._onMouseOut();
|
|
102
158
|
}
|
|
103
|
-
destroy() {
|
|
104
|
-
if (this._animFrameId) {
|
|
105
|
-
window.cancelAnimationFrame(this._animFrameId);
|
|
106
|
-
this._animFrameId = null;
|
|
107
|
-
}
|
|
108
|
-
this._hideTooltip();
|
|
109
|
-
}
|
|
110
159
|
_onMouseMove(event) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return;
|
|
114
|
-
this._animFrameId = window.requestAnimationFrame(() => {
|
|
115
|
-
this._processMouseMove(event);
|
|
116
|
-
this._animFrameId = null;
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
_processMouseMove(event) {
|
|
120
|
-
var _a, _b;
|
|
121
|
-
this._isMouseOver = true;
|
|
122
|
-
const { config, datamodel, element } = this;
|
|
123
|
-
const { isActive, enableSync } = this._getSyncState();
|
|
124
|
-
// Early return for synchronized non-active charts, but allow tooltip display
|
|
125
|
-
if (enableSync && !isActive) {
|
|
126
|
-
if (this.show && this.datum) {
|
|
127
|
-
this._showTooltip(event);
|
|
128
|
-
}
|
|
129
|
-
else if (this.show && this._dataX !== undefined && isNumber(this._dataX)) {
|
|
130
|
-
// For synchronized charts, find the datum if it doesn't exist
|
|
131
|
-
this.datum = getNearest(this.datamodel.data, this._dataX, this.accessors.x);
|
|
132
|
-
if (this.datum) {
|
|
133
|
-
this._showTooltip(event);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
// Check if we have the necessary accessors
|
|
160
|
+
var _a;
|
|
161
|
+
const { datamodel, element } = this;
|
|
139
162
|
if (!this.accessors.x && ((_a = datamodel.data) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
140
163
|
console.warn('Unovis | Crosshair: X accessor function has not been configured. Please check if it\'s present in the configuration object');
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
const [x] = pointer(event, element);
|
|
144
|
-
const xRange = this.xScale.range();
|
|
145
|
-
if (config.snapToData) {
|
|
146
|
-
if (!this.accessors.y && !this.accessors.yStacked && ((_b = datamodel.data) === null || _b === void 0 ? void 0 : _b.length)) {
|
|
147
|
-
console.warn('Unovis | Crosshair: Y accessors have not been configured. Please check if they\'re present in the configuration object');
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
const scaleX = this.xScale;
|
|
151
|
-
const valueX = scaleX.invert(x);
|
|
152
|
-
this.datum = getNearest(datamodel.data, valueX, this.accessors.x);
|
|
153
|
-
this.datumIndex = datamodel.data.indexOf(this.datum);
|
|
154
|
-
if (!this.datum)
|
|
155
|
-
return;
|
|
156
|
-
const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex);
|
|
157
|
-
this.x = clamp(Math.round(scaleX(dataX)), 0, this._width);
|
|
158
|
-
this._dataX = dataX;
|
|
159
|
-
// Show the crosshair only if it's in the chart range and not far from mouse pointer (if configured)
|
|
160
|
-
this.show = (this.x >= 0) && (this.x <= this._width) && (!config.hideWhenFarFromPointer || (Math.abs(this.x - x) < config.hideWhenFarFromPointerDistance));
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
const tolerance = 2; // Show the crosshair when it is at least 2 pixels close to the chart area
|
|
164
|
-
this.x = clamp(x, xRange[0], xRange[1]);
|
|
165
|
-
this._dataX = this.xScale.invert(this.x);
|
|
166
|
-
this.show = (x >= (xRange[0] - tolerance)) && (x <= (xRange[1] + tolerance));
|
|
167
|
-
}
|
|
168
|
-
// Call onCrosshairMove callback if provided
|
|
169
|
-
if (this.show && config.onCrosshairMove && this._dataX !== undefined) {
|
|
170
|
-
config.onCrosshairMove(this._dataX);
|
|
171
164
|
}
|
|
172
|
-
|
|
173
|
-
this.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
165
|
+
const [x, y] = pointer(event, element);
|
|
166
|
+
this._xPx = x;
|
|
167
|
+
this._yPx = y;
|
|
168
|
+
this._mouseEvent = event;
|
|
169
|
+
window.cancelAnimationFrame(this._animFrameId);
|
|
170
|
+
this._animFrameId = window.requestAnimationFrame(() => {
|
|
171
|
+
this._render();
|
|
172
|
+
});
|
|
178
173
|
}
|
|
179
174
|
_onMouseOut() {
|
|
180
|
-
this.
|
|
181
|
-
const { config } = this;
|
|
182
|
-
// Always hide on mouse out
|
|
183
|
-
this.show = false;
|
|
184
|
-
this._hideTooltip();
|
|
185
|
-
// Throttle rendering using requestAnimationFrame
|
|
186
|
-
if (this._animFrameId)
|
|
187
|
-
return;
|
|
175
|
+
window.cancelAnimationFrame(this._animFrameId);
|
|
188
176
|
this._animFrameId = window.requestAnimationFrame(() => {
|
|
189
177
|
this._render();
|
|
190
|
-
this._animFrameId = null;
|
|
191
178
|
});
|
|
192
|
-
// If this is the active chart, notify parent to clear sync state
|
|
193
|
-
if (config.onCrosshairMove) {
|
|
194
|
-
config.onCrosshairMove(undefined);
|
|
195
|
-
}
|
|
196
179
|
}
|
|
197
|
-
_showTooltip(
|
|
180
|
+
_showTooltip(datum, xValue, pos, nearestDatumIndex) {
|
|
198
181
|
var _a;
|
|
199
|
-
const
|
|
200
|
-
|
|
182
|
+
const { config, datamodel } = this;
|
|
183
|
+
const tooltip = (_a = config.tooltip) !== null && _a !== void 0 ? _a : this.tooltip;
|
|
184
|
+
if (!tooltip || !pos)
|
|
201
185
|
return;
|
|
202
|
-
const
|
|
203
|
-
const
|
|
204
|
-
|
|
186
|
+
const [x, y] = pos;
|
|
187
|
+
const content = config.template(datum, xValue, nearestDatumIndex, datamodel.data);
|
|
188
|
+
// Force set `followCursor` to `true` because we don't want Crosshair's tooltip to be hoverable
|
|
205
189
|
tooltip.config.followCursor = true;
|
|
206
190
|
// Set tooltip placement based on Crosshair's position (left / right)
|
|
207
191
|
if (!tooltip.config.horizontalPlacement || tooltip.config.horizontalPlacement === Position.Auto) {
|
|
@@ -213,133 +197,44 @@ class Crosshair extends XYComponentCore {
|
|
|
213
197
|
}
|
|
214
198
|
_hideTooltip() {
|
|
215
199
|
var _a;
|
|
216
|
-
const
|
|
200
|
+
const { config } = this;
|
|
201
|
+
const tooltip = (_a = config.tooltip) !== null && _a !== void 0 ? _a : this.tooltip;
|
|
217
202
|
tooltip === null || tooltip === void 0 ? void 0 : tooltip.hide();
|
|
218
203
|
}
|
|
219
|
-
// We don't want Crosshair to be taken
|
|
204
|
+
// We don't want Crosshair to be be taken in to account in domain calculations
|
|
220
205
|
getYDataExtent() {
|
|
221
206
|
return [undefined, undefined];
|
|
222
207
|
}
|
|
223
|
-
getCircleData() {
|
|
208
|
+
getCircleData(datum, datumIndex) {
|
|
224
209
|
var _a, _b;
|
|
225
|
-
const {
|
|
226
|
-
|
|
227
|
-
if (isFunction(this.config.getCircles)) {
|
|
228
|
-
return this.config.getCircles(this._dataX || this.xScale.invert(this.x), data, this.yScale);
|
|
229
|
-
}
|
|
230
|
-
// Get the datum - either from active mode or from synchronized mode
|
|
231
|
-
let datum = this.datum;
|
|
232
|
-
let datumIndex = this.datumIndex;
|
|
233
|
-
if (!datum && enableSync && !isActive && this._dataX !== undefined) {
|
|
234
|
-
if (isNumber(this._dataX)) {
|
|
235
|
-
datum = getNearest(this.datamodel.data, this._dataX, this.accessors.x);
|
|
236
|
-
datumIndex = this.datamodel.data.indexOf(datum);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
if (this.config.snapToData && datum) {
|
|
210
|
+
const { config } = this;
|
|
211
|
+
if (config.snapToData && datum) {
|
|
240
212
|
const yAccessors = (_a = this.accessors.y) !== null && _a !== void 0 ? _a : [];
|
|
241
213
|
const yStackedAccessors = (_b = this.accessors.yStacked) !== null && _b !== void 0 ? _b : [];
|
|
242
214
|
const baselineValue = getNumber(datum, this.accessors.baseline, datumIndex) || 0;
|
|
243
215
|
const stackedValues = getStackedValues(datum, datumIndex, ...yStackedAccessors)
|
|
244
|
-
.map((value, index) => {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
strokeColor: this.config.strokeColor ? getColor(datum, this.config.strokeColor, index) : undefined,
|
|
252
|
-
strokeWidth: this.config.strokeWidth ? getNumber(datum, this.config.strokeWidth, index) : undefined,
|
|
253
|
-
};
|
|
254
|
-
});
|
|
216
|
+
.map((value, index) => ({
|
|
217
|
+
y: this.yScale(value + baselineValue),
|
|
218
|
+
opacity: isNumber(getNumber(datum, yStackedAccessors[index], index)) ? 1 : 0,
|
|
219
|
+
color: getColor(datum, config.color, index),
|
|
220
|
+
strokeColor: config.strokeColor ? getColor(datum, config.strokeColor, index) : undefined,
|
|
221
|
+
strokeWidth: config.strokeWidth ? getNumber(datum, config.strokeWidth, index) : undefined,
|
|
222
|
+
}));
|
|
255
223
|
const regularValues = yAccessors
|
|
256
224
|
.map((a, index) => {
|
|
257
|
-
const value = getNumber(datum, a);
|
|
258
|
-
const yPixel = isNumber(value) ? this.yScale(value) : 0;
|
|
225
|
+
const value = getNumber(datum, a, datumIndex);
|
|
259
226
|
return {
|
|
260
|
-
y:
|
|
227
|
+
y: this.yScale(value),
|
|
261
228
|
opacity: isNumber(value) ? 1 : 0,
|
|
262
|
-
color: getColor(datum,
|
|
263
|
-
strokeColor:
|
|
264
|
-
strokeWidth:
|
|
229
|
+
color: getColor(datum, config.color, stackedValues.length + index),
|
|
230
|
+
strokeColor: config.strokeColor ? getColor(datum, config.strokeColor, index) : undefined,
|
|
231
|
+
strokeWidth: config.strokeWidth ? getNumber(datum, config.strokeWidth, index) : undefined,
|
|
265
232
|
};
|
|
266
233
|
});
|
|
267
234
|
return stackedValues.concat(regularValues);
|
|
268
235
|
}
|
|
269
|
-
// Return empty array if no data or no datum - crosshair line will still show
|
|
270
236
|
return [];
|
|
271
237
|
}
|
|
272
|
-
_updateFromSync(xData) {
|
|
273
|
-
var _a;
|
|
274
|
-
const { isActive, enableSync } = this._getSyncState();
|
|
275
|
-
if (!enableSync || isActive)
|
|
276
|
-
return;
|
|
277
|
-
// Handle mouse out signal
|
|
278
|
-
if (xData === undefined) {
|
|
279
|
-
this.show = false;
|
|
280
|
-
this._hideTooltip();
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
if (!this.accessors.x || !((_a = this.datamodel.data) === null || _a === void 0 ? void 0 : _a.length))
|
|
284
|
-
return;
|
|
285
|
-
// Check if xPosition is within the chart's x domain
|
|
286
|
-
const xDomain = this.xScale.domain();
|
|
287
|
-
let xValue;
|
|
288
|
-
if (typeof xData === 'number') {
|
|
289
|
-
xValue = xData;
|
|
290
|
-
}
|
|
291
|
-
else if (xData instanceof Date) {
|
|
292
|
-
xValue = xData.getTime();
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
this.show = false;
|
|
296
|
-
this._hideTooltip();
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
// If xPosition is outside the chart's domain, hide the crosshair
|
|
300
|
-
const domainMin = typeof xDomain[0] === 'number' ? xDomain[0] : (xDomain[0] instanceof Date ? xDomain[0].getTime() : 0);
|
|
301
|
-
const domainMax = typeof xDomain[1] === 'number' ? xDomain[1] : (xDomain[1] instanceof Date ? xDomain[1].getTime() : 0);
|
|
302
|
-
if (xValue < domainMin || xValue > domainMax) {
|
|
303
|
-
this.show = false;
|
|
304
|
-
this._hideTooltip();
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
// Find the datum at this x position
|
|
308
|
-
if (typeof xData === 'number') {
|
|
309
|
-
this.datum = getNearest(this.datamodel.data, xData, this.accessors.x);
|
|
310
|
-
}
|
|
311
|
-
else if (xData instanceof Date) {
|
|
312
|
-
this.datum = getNearest(this.datamodel.data, xData.getTime(), this.accessors.x);
|
|
313
|
-
}
|
|
314
|
-
else {
|
|
315
|
-
this.datum = undefined;
|
|
316
|
-
}
|
|
317
|
-
this.datumIndex = this.datamodel.data.indexOf(this.datum);
|
|
318
|
-
// If no datum found, hide the crosshair
|
|
319
|
-
if (!this.datum) {
|
|
320
|
-
this.show = false;
|
|
321
|
-
this._hideTooltip();
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
const dataX = getNumber(this.datum, this.accessors.x, this.datumIndex);
|
|
325
|
-
this.x = clamp(Math.round(this.xScale(dataX)), 0, this._width);
|
|
326
|
-
this._dataX = dataX;
|
|
327
|
-
// Show the crosshair
|
|
328
|
-
this.show = true;
|
|
329
|
-
// Show tooltip for synchronized chart using the same logic as active charts
|
|
330
|
-
const syntheticEvent = {
|
|
331
|
-
clientX: this.container.node().getBoundingClientRect().left + this.x,
|
|
332
|
-
clientY: this.container.node().getBoundingClientRect().top + this._height / 2,
|
|
333
|
-
};
|
|
334
|
-
this._showTooltip(syntheticEvent);
|
|
335
|
-
}
|
|
336
|
-
_getSyncState() {
|
|
337
|
-
// A chart is active if it's being hovered and doesn't have external sync props
|
|
338
|
-
const isActive = this._isMouseOver && !isNumber(this.config.xPosition) && !this.config.forceShow;
|
|
339
|
-
// A chart is in sync mode if it has external sync props (regardless of mouse state)
|
|
340
|
-
const enableSync = isNumber(this.config.xPosition) || !!this.config.forceShow;
|
|
341
|
-
return { isActive, enableSync };
|
|
342
|
-
}
|
|
343
238
|
}
|
|
344
239
|
Crosshair.selectors = style;
|
|
345
240
|
|