highcharts
Version:
JavaScript charting framework
1,512 lines (1,476 loc) • 158 kB
JavaScript
/**
* @license Highcharts JS v12.2.0 (2025-04-07)
* @module highcharts/modules/navigator
* @requires highcharts
*
* Standalone navigator module
*
* (c) 2009-2025 Mateusz Bernacik
*
* License: www.highcharts.com/license
*/
import * as __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__ from "../highcharts.src.js";
/******/ // The require scope
/******/ var __webpack_require__ = {};
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/************************************************************************/
;// external ["../highcharts.src.js","default"]
const external_highcharts_src_js_default_namespaceObject = __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__["default"];
var external_highcharts_src_js_default_default = /*#__PURE__*/__webpack_require__.n(external_highcharts_src_js_default_namespaceObject);
;// external ["../highcharts.src.js","default","Chart"]
const external_highcharts_src_js_default_Chart_namespaceObject = __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__["default"].Chart;
var external_highcharts_src_js_default_Chart_default = /*#__PURE__*/__webpack_require__.n(external_highcharts_src_js_default_Chart_namespaceObject);
;// external ["../highcharts.src.js","default","Axis"]
const external_highcharts_src_js_default_Axis_namespaceObject = __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__["default"].Axis;
var external_highcharts_src_js_default_Axis_default = /*#__PURE__*/__webpack_require__.n(external_highcharts_src_js_default_Axis_namespaceObject);
;// ./code/es-modules/Stock/Navigator/ChartNavigatorComposition.js
/* *
*
* (c) 2010-2025 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { isTouchDevice } = (external_highcharts_src_js_default_default());
const { addEvent, merge, pick } = (external_highcharts_src_js_default_default());
/* *
*
* Constants
*
* */
const composedMembers = [];
/* *
*
* Variables
*
* */
let NavigatorConstructor;
/* *
*
* Functions
*
* */
/**
* @private
*/
function compose(ChartClass, NavigatorClass) {
if (external_highcharts_src_js_default_default().pushUnique(composedMembers, ChartClass)) {
const chartProto = ChartClass.prototype;
NavigatorConstructor = NavigatorClass;
chartProto.callbacks.push(onChartCallback);
addEvent(ChartClass, 'afterAddSeries', onChartAfterAddSeries);
addEvent(ChartClass, 'afterSetChartSize', onChartAfterSetChartSize);
addEvent(ChartClass, 'afterUpdate', onChartAfterUpdate);
addEvent(ChartClass, 'beforeRender', onChartBeforeRender);
addEvent(ChartClass, 'beforeShowResetZoom', onChartBeforeShowResetZoom);
addEvent(ChartClass, 'update', onChartUpdate);
}
}
/**
* Handle adding new series.
* @private
*/
function onChartAfterAddSeries() {
if (this.navigator) {
// Recompute which series should be shown in navigator, and add them
this.navigator.setBaseSeries(null, false);
}
}
/**
* For stock charts, extend the Chart.setChartSize method so that we can set the
* final top position of the navigator once the height of the chart, including
* the legend, is determined. #367. We can't use Chart.getMargins, because
* labels offsets are not calculated yet.
* @private
*/
function onChartAfterSetChartSize() {
const legend = this.legend, navigator = this.navigator;
let legendOptions, xAxis, yAxis;
if (navigator) {
legendOptions = legend && legend.options;
xAxis = navigator.xAxis;
yAxis = navigator.yAxis;
const { scrollbarHeight, scrollButtonSize } = navigator;
// Compute the top position
if (this.inverted) {
navigator.left = navigator.opposite ?
this.chartWidth - scrollbarHeight -
navigator.height :
this.spacing[3] + scrollbarHeight;
navigator.top = this.plotTop + scrollButtonSize;
}
else {
navigator.left = pick(xAxis.left, this.plotLeft + scrollButtonSize);
navigator.top = navigator.navigatorOptions.top ||
this.chartHeight -
navigator.height -
scrollbarHeight -
(this.scrollbar?.options.margin || 0) -
this.spacing[2] -
(this.rangeSelector && this.extraBottomMargin ?
this.rangeSelector.getHeight() :
0) -
((legendOptions &&
legendOptions.verticalAlign === 'bottom' &&
legendOptions.layout !== 'proximate' && // #13392
legendOptions.enabled &&
!legendOptions.floating) ?
legend.legendHeight +
pick(legendOptions.margin, 10) :
0) -
(this.titleOffset ? this.titleOffset[2] : 0);
}
if (xAxis && yAxis) { // False if navigator is disabled (#904)
if (this.inverted) {
xAxis.options.left = yAxis.options.left = navigator.left;
}
else {
xAxis.options.top = yAxis.options.top = navigator.top;
}
xAxis.setAxisSize();
yAxis.setAxisSize();
}
}
}
/**
* Initialize navigator, if no scrolling exists yet.
* @private
*/
function onChartAfterUpdate(event) {
if (!this.navigator && !this.scroller &&
(this.options.navigator.enabled ||
this.options.scrollbar.enabled)) {
this.scroller = this.navigator = new NavigatorConstructor(this);
if (pick(event.redraw, true)) {
this.redraw(event.animation); // #7067
}
}
}
/**
* Initialize navigator for stock charts
* @private
*/
function onChartBeforeRender() {
const options = this.options;
if (options.navigator.enabled ||
options.scrollbar.enabled) {
this.scroller = this.navigator = new NavigatorConstructor(this);
}
}
/**
* For Stock charts. For x only zooming, do not to create the zoom button
* because X axis zooming is already allowed by the Navigator and Range
* selector. (#9285)
* @private
*/
function onChartBeforeShowResetZoom() {
const chartOptions = this.options, navigator = chartOptions.navigator, rangeSelector = chartOptions.rangeSelector;
if (((navigator && navigator.enabled) ||
(rangeSelector && rangeSelector.enabled)) &&
((!isTouchDevice &&
this.zooming.type === 'x') ||
(isTouchDevice && this.zooming.pinchType === 'x'))) {
return false;
}
}
/**
* @private
*/
function onChartCallback(chart) {
const navigator = chart.navigator;
// Initialize the navigator
if (navigator && chart.xAxis[0]) {
const extremes = chart.xAxis[0].getExtremes();
navigator.render(extremes.min, extremes.max);
}
}
/**
* Merge options, if no scrolling exists yet
* @private
*/
function onChartUpdate(e) {
const navigatorOptions = (e.options.navigator || {}), scrollbarOptions = (e.options.scrollbar || {});
if (!this.navigator && !this.scroller &&
(navigatorOptions.enabled || scrollbarOptions.enabled)) {
merge(true, this.options.navigator, navigatorOptions);
merge(true, this.options.scrollbar, scrollbarOptions);
delete e.options.navigator;
delete e.options.scrollbar;
}
}
/* *
*
* Default Export
*
* */
const ChartNavigatorComposition = {
compose
};
/* harmony default export */ const Navigator_ChartNavigatorComposition = (ChartNavigatorComposition);
;// ./code/es-modules/Core/Axis/NavigatorAxisComposition.js
/* *
*
* (c) 2010-2025 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { isTouchDevice: NavigatorAxisComposition_isTouchDevice } = (external_highcharts_src_js_default_default());
const { addEvent: NavigatorAxisComposition_addEvent, correctFloat, defined, isNumber, pick: NavigatorAxisComposition_pick } = (external_highcharts_src_js_default_default());
/* *
*
* Functions
*
* */
/**
* @private
*/
function onAxisInit() {
const axis = this;
if (!axis.navigatorAxis) {
axis.navigatorAxis = new NavigatorAxisAdditions(axis);
}
}
/**
* For Stock charts, override selection zooming with some special features
* because X axis zooming is already allowed by the Navigator and Range
* selector.
* @private
*/
function onAxisSetExtremes(e) {
const axis = this, chart = axis.chart, chartOptions = chart.options, navigator = chartOptions.navigator, navigatorAxis = axis.navigatorAxis, pinchType = chart.zooming.pinchType, rangeSelector = chartOptions.rangeSelector, zoomType = chart.zooming.type;
let zoomed;
if (axis.isXAxis &&
(navigator?.enabled || rangeSelector?.enabled)) {
// For y only zooming, ignore the X axis completely
if (zoomType === 'y' && e.trigger === 'zoom') {
zoomed = false;
// For xy zooming, record the state of the zoom before zoom selection,
// then when the reset button is pressed, revert to this state. This
// should apply only if the chart is initialized with a range (#6612),
// otherwise zoom all the way out.
}
else if (((e.trigger === 'zoom' && zoomType === 'xy') ||
(NavigatorAxisComposition_isTouchDevice && pinchType === 'xy')) &&
axis.options.range) {
const previousZoom = navigatorAxis.previousZoom;
// Minimum defined, zooming in
if (defined(e.min)) {
navigatorAxis.previousZoom = [axis.min, axis.max];
// Minimum undefined, resetting zoom
}
else if (previousZoom) {
e.min = previousZoom[0];
e.max = previousZoom[1];
navigatorAxis.previousZoom = void 0;
}
}
}
if (typeof zoomed !== 'undefined') {
e.preventDefault();
}
}
/* *
*
* Class
*
* */
/**
* @private
* @class
*/
class NavigatorAxisAdditions {
/* *
*
* Static Functions
*
* */
/**
* @private
*/
static compose(AxisClass) {
if (!AxisClass.keepProps.includes('navigatorAxis')) {
AxisClass.keepProps.push('navigatorAxis');
NavigatorAxisComposition_addEvent(AxisClass, 'init', onAxisInit);
NavigatorAxisComposition_addEvent(AxisClass, 'setExtremes', onAxisSetExtremes);
}
}
/* *
*
* Constructors
*
* */
constructor(axis) {
this.axis = axis;
}
/* *
*
* Functions
*
* */
/**
* @private
*/
destroy() {
this.axis = void 0;
}
/**
* Add logic to normalize the zoomed range in order to preserve the pressed
* state of range selector buttons
*
* @private
* @function Highcharts.Axis#toFixedRange
*/
toFixedRange(pxMin, pxMax, fixedMin, fixedMax) {
const axis = this.axis, halfPointRange = (axis.pointRange || 0) / 2;
let newMin = NavigatorAxisComposition_pick(fixedMin, axis.translate(pxMin, true, !axis.horiz)), newMax = NavigatorAxisComposition_pick(fixedMax, axis.translate(pxMax, true, !axis.horiz));
// Add/remove half point range to/from the extremes (#1172)
if (!defined(fixedMin)) {
newMin = correctFloat(newMin + halfPointRange);
}
if (!defined(fixedMax)) {
newMax = correctFloat(newMax - halfPointRange);
}
if (!isNumber(newMin) || !isNumber(newMax)) { // #1195, #7411
newMin = newMax = void 0;
}
return {
min: newMin,
max: newMax
};
}
}
/* *
*
* Default Export
*
* */
/* harmony default export */ const NavigatorAxisComposition = (NavigatorAxisAdditions);
;// external ["../highcharts.src.js","default","Color"]
const external_highcharts_src_js_default_Color_namespaceObject = __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__["default"].Color;
var external_highcharts_src_js_default_Color_default = /*#__PURE__*/__webpack_require__.n(external_highcharts_src_js_default_Color_namespaceObject);
;// external ["../highcharts.src.js","default","SeriesRegistry"]
const external_highcharts_src_js_default_SeriesRegistry_namespaceObject = __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__["default"].SeriesRegistry;
var external_highcharts_src_js_default_SeriesRegistry_default = /*#__PURE__*/__webpack_require__.n(external_highcharts_src_js_default_SeriesRegistry_namespaceObject);
;// ./code/es-modules/Stock/Navigator/NavigatorDefaults.js
/* *
*
* (c) 2010-2025 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { parse: color } = (external_highcharts_src_js_default_Color_default());
const { seriesTypes } = (external_highcharts_src_js_default_SeriesRegistry_default());
/* *
*
* Constants
*
* */
/**
* The navigator is a small series below the main series, displaying
* a view of the entire data set. It provides tools to zoom in and
* out on parts of the data as well as panning across the dataset.
*
* @product highstock gantt
* @optionparent navigator
*/
const NavigatorDefaults = {
/**
* Whether the navigator and scrollbar should adapt to updated data
* in the base X axis. When loading data async, as in the demo below,
* this should be `false`. Otherwise new data will trigger navigator
* redraw, which will cause unwanted looping. In the demo below, the
* data in the navigator is set only once. On navigating, only the main
* chart content is updated.
*
* @sample {highstock} stock/demo/lazy-loading/
* Set to false with async data loading
*
* @type {boolean}
* @default true
* @apioption navigator.adaptToUpdatedData
*/
/**
* An integer identifying the index to use for the base series, or a
* string representing the id of the series.
*
* **Note**: As of Highcharts 5.0, this is now a deprecated option.
* Prefer [series.showInNavigator](#plotOptions.series.showInNavigator).
*
* @see [series.showInNavigator](#plotOptions.series.showInNavigator)
*
* @deprecated
* @type {number|string}
* @default 0
* @apioption navigator.baseSeries
*/
/**
* Enable or disable the navigator.
*
* @sample {highstock} stock/navigator/enabled/
* Disable the navigator
*
* @type {boolean}
* @default true
* @apioption navigator.enabled
*/
/**
* When the chart is inverted, whether to draw the navigator on the
* opposite side.
*
* @type {boolean}
* @default false
* @since 5.0.8
* @apioption navigator.opposite
*/
/**
* The height of the navigator.
*
* @sample {highstock} stock/navigator/height/
* A higher navigator
*/
height: 40,
/**
* The distance from the nearest element, the X axis or X axis labels.
*
* @sample {highstock} stock/navigator/margin/
* A margin of 2 draws the navigator closer to the X axis labels
*/
margin: 22,
/**
* Whether the mask should be inside the range marking the zoomed
* range, or outside. In Highcharts Stock 1.x it was always `false`.
*
* @sample {highstock} stock/demo/maskinside-false/
* False, mask outside
*
* @since 2.0
*/
maskInside: true,
/**
* Options for the handles for dragging the zoomed area.
*
* @sample {highstock} stock/navigator/handles/
* Colored handles
*/
handles: {
/**
* Width for handles.
*
* @sample {highstock} stock/navigator/styled-handles/
* Styled handles
*
* @since 6.0.0
*/
width: 7,
/**
* Border radius of the handles.
*
* @sample {highstock} stock/navigator/handles-border-radius/
* Border radius on the navigator handles.
*
* @since 11.4.2
*/
borderRadius: 0,
/**
* Height for handles.
*
* @sample {highstock} stock/navigator/styled-handles/
* Styled handles
*
* @since 6.0.0
*/
height: 15,
/**
* Array to define shapes of handles. 0-index for left, 1-index for
* right.
*
* Additionally, the URL to a graphic can be given on this form:
* `url(graphic.png)`. Note that for the image to be applied to
* exported charts, its URL needs to be accessible by the export
* server.
*
* Custom callbacks for symbol path generation can also be added to
* `Highcharts.SVGRenderer.prototype.symbols`. The callback is then
* used by its method name, as shown in the demo.
*
* @sample {highstock} stock/navigator/styled-handles/
* Styled handles
*
* @type {Array<string>}
* @default ["navigator-handle", "navigator-handle"]
* @since 6.0.0
*/
symbols: ['navigator-handle', 'navigator-handle'],
/**
* Allows to enable/disable handles.
*
* @since 6.0.0
*/
enabled: true,
/**
* The width for the handle border and the stripes inside.
*
* @sample {highstock} stock/navigator/styled-handles/
* Styled handles
*
* @since 6.0.0
* @apioption navigator.handles.lineWidth
*/
lineWidth: 1,
/**
* The fill for the handle.
*
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
*/
backgroundColor: "#f2f2f2" /* Palette.neutralColor5 */,
/**
* The stroke for the handle border and the stripes inside.
*
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
*/
borderColor: "#999999" /* Palette.neutralColor40 */
},
/**
* The color of the mask covering the areas of the navigator series
* that are currently not visible in the main series. The default
* color is bluish with an opacity of 0.3 to see the series below.
*
* @see In styled mode, the mask is styled with the
* `.highcharts-navigator-mask` and
* `.highcharts-navigator-mask-inside` classes.
*
* @sample {highstock} stock/navigator/maskfill/
* Blue, semi transparent mask
*
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
* @default rgba(102,133,194,0.3)
*/
maskFill: color("#667aff" /* Palette.highlightColor60 */).setOpacity(0.3).get(),
/**
* The color of the line marking the currently zoomed area in the
* navigator.
*
* @sample {highstock} stock/navigator/outline/
* 2px blue outline
*
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
* @default #cccccc
*/
outlineColor: "#999999" /* Palette.neutralColor40 */,
/**
* The width of the line marking the currently zoomed area in the
* navigator.
*
* @see In styled mode, the outline stroke width is set with the
* `.highcharts-navigator-outline` class.
*
* @sample {highstock} stock/navigator/outline/
* 2px blue outline
*
* @type {number}
*/
outlineWidth: 1,
/**
* Options for the navigator series. Available options are the same
* as any series, documented at [plotOptions](#plotOptions.series)
* and [series](#series).
*
* Unless data is explicitly defined on navigator.series, the data
* is borrowed from the first series in the chart.
*
* Default series options for the navigator series are:
* ```js
* series: {
* type: 'areaspline',
* fillOpacity: 0.05,
* dataGrouping: {
* smoothed: true
* },
* lineWidth: 1,
* marker: {
* enabled: false
* }
* }
* ```
*
* @see In styled mode, the navigator series is styled with the
* `.highcharts-navigator-series` class.
*
* @sample {highstock} stock/navigator/series-data/
* Using a separate data set for the navigator
* @sample {highstock} stock/navigator/series/
* A green navigator series
*
* @type {*|Array<*>|Highcharts.SeriesOptionsType|Array<Highcharts.SeriesOptionsType>}
*/
series: {
/**
* The type of the navigator series.
*
* Heads up:
* In column-type navigator, zooming is limited to at least one
* point with its `pointRange`.
*
* @sample {highstock} stock/navigator/column/
* Column type navigator
*
* @type {string}
* @default {highstock} `areaspline` if defined, otherwise `line`
* @default {gantt} gantt
*/
type: (typeof seriesTypes.areaspline === 'undefined' ?
'line' :
'areaspline'),
/**
* The fill opacity of the navigator series.
*/
fillOpacity: 0.05,
/**
* The pixel line width of the navigator series.
*/
lineWidth: 1,
/**
* @ignore-option
*/
compare: null,
/**
* @ignore-option
*/
sonification: {
enabled: false
},
/**
* Unless data is explicitly defined, the data is borrowed from the
* first series in the chart.
*
* @type {Array<number|Array<number|string|null>|object|null>}
* @product highstock
* @apioption navigator.series.data
*/
/**
* Data grouping options for the navigator series.
*
* @extends plotOptions.series.dataGrouping
*/
dataGrouping: {
approximation: 'average',
enabled: true,
groupPixelWidth: 2,
// Replace smoothed property by anchors, #12455.
firstAnchor: 'firstPoint',
anchor: 'middle',
lastAnchor: 'lastPoint',
// Day and week differs from plotOptions.series.dataGrouping
units: [
['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]],
['second', [1, 2, 5, 10, 15, 30]],
['minute', [1, 2, 5, 10, 15, 30]],
['hour', [1, 2, 3, 4, 6, 8, 12]],
['day', [1, 2, 3, 4]],
['week', [1, 2, 3]],
['month', [1, 3, 6]],
['year', null]
]
},
/**
* Data label options for the navigator series. Data labels are
* disabled by default on the navigator series.
*
* @extends plotOptions.series.dataLabels
*/
dataLabels: {
enabled: false,
zIndex: 2 // #1839
},
id: 'highcharts-navigator-series',
className: 'highcharts-navigator-series',
/**
* Sets the fill color of the navigator series.
*
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
* @apioption navigator.series.color
*/
/**
* Line color for the navigator series. Allows setting the color
* while disallowing the default candlestick setting.
*
* @type {Highcharts.ColorString|null}
*/
lineColor: null, // #4602
marker: {
enabled: false
},
/**
* Since Highcharts Stock v8, default value is the same as default
* `pointRange` defined for a specific type (e.g. `null` for
* column type).
*
* In Highcharts Stock version < 8, defaults to 0.
*
* @extends plotOptions.series.pointRange
* @type {number|null}
* @apioption navigator.series.pointRange
*/
/**
* The threshold option. Setting it to 0 will make the default
* navigator area series draw its area from the 0 value and up.
*
* @type {number|null}
*/
threshold: null
},
/**
* Enable or disable navigator sticking to right, while adding new
* points. If `undefined`, the navigator sticks to the axis maximum only
* if it was already at the maximum prior to adding points.
*
* @type {boolean}
* @default undefined
* @since 10.2.1
* @sample {highstock} stock/navigator/sticktomax-false/
* stickToMax set to false
* @apioption navigator.stickToMax
*/
/**
* Options for the navigator X axis. Default series options for the
* navigator xAxis are:
* ```js
* xAxis: {
* tickWidth: 0,
* lineWidth: 0,
* gridLineWidth: 1,
* tickPixelInterval: 200,
* labels: {
* align: 'left',
* style: {
* color: '#888'
* },
* x: 3,
* y: -4
* }
* }
* ```
*
* @extends xAxis
* @excluding linkedTo, maxZoom, minRange, opposite, range, scrollbar,
* showEmpty, maxRange
*/
xAxis: {
/**
* Additional range on the right side of the xAxis. Works similar to
* `xAxis.maxPadding`, but the value is set in terms of axis values,
* percentage or pixels.
*
* If it's a number, it is interpreted as axis values, which in a
* datetime axis equals milliseconds.
*
* If it's a percentage string, is interpreted as percentages of the
* axis length. An overscroll of 50% will make a 100px axis 50px longer.
*
* If it's a pixel string, it is interpreted as a fixed pixel value, but
* limited to 90% of the axis length.
*
* If it's undefined, the value is inherited from `xAxis.overscroll`.
*
* Can be set for both, main xAxis and navigator's xAxis.
*
* @type {number | string | undefined}
* @since 6.0.0
* @apioption navigator.xAxis.overscroll
*/
className: 'highcharts-navigator-xaxis',
tickLength: 0,
lineWidth: 0,
gridLineColor: "#e6e6e6" /* Palette.neutralColor10 */,
id: 'navigator-x-axis',
gridLineWidth: 1,
tickPixelInterval: 200,
labels: {
align: 'left',
/**
* @type {Highcharts.CSSObject}
*/
style: {
/** @ignore */
color: "#000000" /* Palette.neutralColor100 */,
/** @ignore */
fontSize: '0.7em',
/** @ignore */
opacity: 0.6,
/** @ignore */
textOutline: '2px contrast'
},
x: 3,
y: -4
},
crosshair: false
},
/**
* Options for the navigator Y axis. Default series options for the
* navigator yAxis are:
* ```js
* yAxis: {
* gridLineWidth: 0,
* startOnTick: false,
* endOnTick: false,
* minPadding: 0.1,
* maxPadding: 0.1,
* labels: {
* enabled: false
* },
* title: {
* text: null
* },
* tickWidth: 0
* }
* ```
*
* @extends yAxis
* @excluding height, linkedTo, maxZoom, minRange, ordinal, range,
* showEmpty, scrollbar, top, units, maxRange, minLength,
* maxLength, resize
*/
yAxis: {
className: 'highcharts-navigator-yaxis',
gridLineWidth: 0,
startOnTick: false,
endOnTick: false,
minPadding: 0.1,
id: 'navigator-y-axis',
maxPadding: 0.1,
labels: {
enabled: false
},
crosshair: false,
title: {
text: void 0
},
tickLength: 0,
tickWidth: 0
}
};
/* *
*
* Default Export
*
* */
/* harmony default export */ const Navigator_NavigatorDefaults = (NavigatorDefaults);
/* *
*
* API Options
*
* */
/**
* Maximum range which can be set using the navigator's handles.
* Opposite of [xAxis.minRange](#xAxis.minRange).
*
* @sample {highstock} stock/navigator/maxrange/
* Defined max and min range
*
* @type {number}
* @since 6.0.0
* @product highstock gantt
* @apioption xAxis.maxRange
*/
(''); // Keeps doclets above in JS file
;// ./code/es-modules/Core/Renderer/SVG/Symbols.js
/* *
*
* (c) 2010-2025 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { defined: Symbols_defined, isNumber: Symbols_isNumber, pick: Symbols_pick } = (external_highcharts_src_js_default_default());
/* *
*
* Functions
*
* */
/* eslint-disable require-jsdoc, valid-jsdoc */
/**
*
*/
function arc(cx, cy, w, h, options) {
const arc = [];
if (options) {
let start = options.start || 0, end = options.end || 0;
const rx = Symbols_pick(options.r, w), ry = Symbols_pick(options.r, h || w),
// Subtract a small number to prevent cos and sin of start and end
// from becoming equal on 360 arcs (#1561). The size of the circle
// affects the constant, therefore the division by `rx`. If the
// proximity is too small, the arc disappears. If it is too great, a
// gap appears. This can be seen in the animation of the official
// bubble demo (#20585).
proximity = 0.0002 / (options.borderRadius ? 1 : Math.max(rx, 1)), fullCircle = (Math.abs(end - start - 2 * Math.PI) <
proximity);
if (fullCircle) {
start = Math.PI / 2;
end = Math.PI * 2.5 - proximity;
}
const innerRadius = options.innerR, open = Symbols_pick(options.open, fullCircle), cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end),
// Proximity takes care of rounding errors around PI (#6971)
longArc = Symbols_pick(options.longArc, end - start - Math.PI < proximity ? 0 : 1);
let arcSegment = [
'A', // ArcTo
rx, // X radius
ry, // Y radius
0, // Slanting
longArc, // Long or short arc
Symbols_pick(options.clockwise, 1), // Clockwise
cx + rx * cosEnd,
cy + ry * sinEnd
];
arcSegment.params = { start, end, cx, cy }; // Memo for border radius
arc.push([
'M',
cx + rx * cosStart,
cy + ry * sinStart
], arcSegment);
if (Symbols_defined(innerRadius)) {
arcSegment = [
'A', // ArcTo
innerRadius, // X radius
innerRadius, // Y radius
0, // Slanting
longArc, // Long or short arc
// Clockwise - opposite to the outer arc clockwise
Symbols_defined(options.clockwise) ? 1 - options.clockwise : 0,
cx + innerRadius * cosStart,
cy + innerRadius * sinStart
];
// Memo for border radius
arcSegment.params = {
start: end,
end: start,
cx,
cy
};
arc.push(open ?
[
'M',
cx + innerRadius * cosEnd,
cy + innerRadius * sinEnd
] : [
'L',
cx + innerRadius * cosEnd,
cy + innerRadius * sinEnd
], arcSegment);
}
if (!open) {
arc.push(['Z']);
}
}
return arc;
}
/**
* Callout shape used for default tooltips.
*/
function callout(x, y, w, h, options) {
const arrowLength = 6, halfDistance = 6, r = Math.min((options?.r) || 0, w, h), safeDistance = r + halfDistance, anchorX = options?.anchorX, anchorY = options?.anchorY || 0;
const path = roundedRect(x, y, w, h, { r });
if (!Symbols_isNumber(anchorX)) {
return path;
}
// Do not render a connector, if anchor starts inside the label
if (anchorX < w && anchorX > 0 && anchorY < h && anchorY > 0) {
return path;
}
// Anchor on right side
if (x + anchorX > w - safeDistance) {
// Chevron
if (anchorY > y + safeDistance &&
anchorY < y + h - safeDistance) {
path.splice(3, 1, ['L', x + w, anchorY - halfDistance], ['L', x + w + arrowLength, anchorY], ['L', x + w, anchorY + halfDistance], ['L', x + w, y + h - r]);
// Simple connector
}
else {
if (anchorX < w) { // Corner connector
const isTopCorner = anchorY < y + safeDistance, cornerY = isTopCorner ? y : y + h, sliceStart = isTopCorner ? 2 : 5;
path.splice(sliceStart, 0, ['L', anchorX, anchorY], ['L', x + w - r, cornerY]);
}
else { // Side connector
path.splice(3, 1, ['L', x + w, h / 2], ['L', anchorX, anchorY], ['L', x + w, h / 2], ['L', x + w, y + h - r]);
}
}
// Anchor on left side
}
else if (x + anchorX < safeDistance) {
// Chevron
if (anchorY > y + safeDistance &&
anchorY < y + h - safeDistance) {
path.splice(7, 1, ['L', x, anchorY + halfDistance], ['L', x - arrowLength, anchorY], ['L', x, anchorY - halfDistance], ['L', x, y + r]);
// Simple connector
}
else {
if (anchorX > 0) { // Corner connector
const isTopCorner = anchorY < y + safeDistance, cornerY = isTopCorner ? y : y + h, sliceStart = isTopCorner ? 1 : 6;
path.splice(sliceStart, 0, ['L', anchorX, anchorY], ['L', x + r, cornerY]);
}
else { // Side connector
path.splice(7, 1, ['L', x, h / 2], ['L', anchorX, anchorY], ['L', x, h / 2], ['L', x, y + r]);
}
}
}
else if ( // Replace bottom
anchorY > h &&
anchorX < w - safeDistance) {
path.splice(5, 1, ['L', anchorX + halfDistance, y + h], ['L', anchorX, y + h + arrowLength], ['L', anchorX - halfDistance, y + h], ['L', x + r, y + h]);
}
else if ( // Replace top
anchorY < 0 &&
anchorX > safeDistance) {
path.splice(1, 1, ['L', anchorX - halfDistance, y], ['L', anchorX, y - arrowLength], ['L', anchorX + halfDistance, y], ['L', w - r, y]);
}
return path;
}
/**
*
*/
function circle(x, y, w, h) {
// Return a full arc
return arc(x + w / 2, y + h / 2, w / 2, h / 2, {
start: Math.PI * 0.5,
end: Math.PI * 2.5,
open: false
});
}
/**
*
*/
function diamond(x, y, w, h) {
return [
['M', x + w / 2, y],
['L', x + w, y + h / 2],
['L', x + w / 2, y + h],
['L', x, y + h / 2],
['Z']
];
}
// #15291
/**
*
*/
function rect(x, y, w, h, options) {
if (options?.r) {
return roundedRect(x, y, w, h, options);
}
return [
['M', x, y],
['L', x + w, y],
['L', x + w, y + h],
['L', x, y + h],
['Z']
];
}
/**
*
*/
function roundedRect(x, y, w, h, options) {
const r = options?.r || 0;
return [
['M', x + r, y],
['L', x + w - r, y], // Top side
['A', r, r, 0, 0, 1, x + w, y + r], // Top-right corner
['L', x + w, y + h - r], // Right side
['A', r, r, 0, 0, 1, x + w - r, y + h], // Bottom-right corner
['L', x + r, y + h], // Bottom side
['A', r, r, 0, 0, 1, x, y + h - r], // Bottom-left corner
['L', x, y + r], // Left side
['A', r, r, 0, 0, 1, x + r, y],
['Z'] // Top-left corner
];
}
/**
*
*/
function triangle(x, y, w, h) {
return [
['M', x + w / 2, y],
['L', x + w, y + h],
['L', x, y + h],
['Z']
];
}
/**
*
*/
function triangleDown(x, y, w, h) {
return [
['M', x, y],
['L', x + w, y],
['L', x + w / 2, y + h],
['Z']
];
}
const Symbols = {
arc,
callout,
circle,
diamond,
rect,
roundedRect,
square: rect,
triangle,
'triangle-down': triangleDown
};
/* *
*
* Default Export
*
* */
/* harmony default export */ const SVG_Symbols = (Symbols);
;// ./code/es-modules/Stock/Navigator/NavigatorSymbols.js
/* *
*
* (c) 2010-2025 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { relativeLength } = (external_highcharts_src_js_default_default());
/* *
*
* Constants
*
* */
/**
* Draw one of the handles on the side of the zoomed range in the navigator.
* @private
*/
function navigatorHandle(_x, _y, width, height, options = {}) {
const halfWidth = options.width ? options.width / 2 : width, markerPosition = 1.5, r = relativeLength(options.borderRadius || 0, Math.min(halfWidth * 2, height));
height = options.height || height;
return [
['M', -markerPosition, height / 2 - 3.5],
['L', -markerPosition, height / 2 + 4.5],
['M', markerPosition - 1, height / 2 - 3.5],
['L', markerPosition - 1, height / 2 + 4.5],
...SVG_Symbols.rect(-halfWidth - 1, 0.5, halfWidth * 2 + 1, height, { r })
];
}
/* *
*
* Default Export
*
* */
const NavigatorSymbols = {
'navigator-handle': navigatorHandle
};
/* harmony default export */ const Navigator_NavigatorSymbols = (NavigatorSymbols);
;// external ["../highcharts.src.js","default","RendererRegistry"]
const external_highcharts_src_js_default_RendererRegistry_namespaceObject = __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__["default"].RendererRegistry;
var external_highcharts_src_js_default_RendererRegistry_default = /*#__PURE__*/__webpack_require__.n(external_highcharts_src_js_default_RendererRegistry_namespaceObject);
;// ./code/es-modules/Stock/Utilities/StockUtilities.js
/* *
*
* (c) 2010-2025 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { defined: StockUtilities_defined } = (external_highcharts_src_js_default_default());
/* *
*
* Functions
*
* */
/**
* Sets the chart.fixedRange to the specified value. If the value is larger
* than actual range, sets it to the maximum possible range. (#20327)
*
* @private
* @function Highcharts.StockChart#setFixedRange
* @param {number|undefined} range
* Range to set in axis units.
*/
function setFixedRange(range) {
const xAxis = this.xAxis[0];
if (StockUtilities_defined(xAxis.dataMax) &&
StockUtilities_defined(xAxis.dataMin) &&
range) {
this.fixedRange = Math.min(range, xAxis.dataMax - xAxis.dataMin);
}
else {
this.fixedRange = range;
}
}
const StockUtilities = {
setFixedRange
};
/* harmony default export */ const Utilities_StockUtilities = (StockUtilities);
;// ./code/es-modules/Stock/Navigator/NavigatorComposition.js
/* *
*
* (c) 2010-2025 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { setOptions } = (external_highcharts_src_js_default_default());
const { composed } = (external_highcharts_src_js_default_default());
const { getRendererType } = (external_highcharts_src_js_default_RendererRegistry_default());
const { setFixedRange: NavigatorComposition_setFixedRange } = Utilities_StockUtilities;
const { addEvent: NavigatorComposition_addEvent, extend, pushUnique } = (external_highcharts_src_js_default_default());
/* *
*
* Variables
*
* */
/* *
*
* Functions
*
* */
/**
* @private
*/
function NavigatorComposition_compose(ChartClass, AxisClass, SeriesClass) {
NavigatorAxisComposition.compose(AxisClass);
if (pushUnique(composed, 'Navigator')) {
ChartClass.prototype.setFixedRange = NavigatorComposition_setFixedRange;
extend(getRendererType().prototype.symbols, Navigator_NavigatorSymbols);
NavigatorComposition_addEvent(SeriesClass, 'afterUpdate', onSeriesAfterUpdate);
setOptions({ navigator: Navigator_NavigatorDefaults });
}
}
/**
* Handle updating series
* @private
*/
function onSeriesAfterUpdate() {
if (this.chart.navigator && !this.options.isInternal) {
this.chart.navigator.setBaseSeries(null, false);
}
}
/* *
*
* Default Export
*
* */
const NavigatorComposition = {
compose: NavigatorComposition_compose
};
/* harmony default export */ const Navigator_NavigatorComposition = (NavigatorComposition);
;// ./code/es-modules/Core/Axis/ScrollbarAxis.js
/* *
*
* (c) 2010-2025 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { composed: ScrollbarAxis_composed } = (external_highcharts_src_js_default_default());
const { addEvent: ScrollbarAxis_addEvent, defined: ScrollbarAxis_defined, pick: ScrollbarAxis_pick, pushUnique: ScrollbarAxis_pushUnique } = (external_highcharts_src_js_default_default());
/* *
*
* Composition
*
* */
var ScrollbarAxis;
(function (ScrollbarAxis) {
/* *
*
* Variables
*
* */
let Scrollbar;
/* *
*
* Functions
*
* */
/**
* Attaches to axis events to create scrollbars if enabled.
*
* @private
*
* @param {Highcharts.Axis} AxisClass
* Axis class to extend.
*
* @param {Highcharts.Scrollbar} ScrollbarClass
* Scrollbar class to use.
*/
function compose(AxisClass, ScrollbarClass) {
if (ScrollbarAxis_pushUnique(ScrollbarAxis_composed, 'Axis.Scrollbar')) {
Scrollbar = ScrollbarClass;
ScrollbarAxis_addEvent(AxisClass, 'afterGetOffset', onAxisAfterGetOffset);
ScrollbarAxis_addEvent(AxisClass, 'afterInit', onAxisAfterInit);
ScrollbarAxis_addEvent(AxisClass, 'afterRender', onAxisAfterRender);
}
}
ScrollbarAxis.compose = compose;
/** @private */
function getExtremes(axis) {
const axisMin = ScrollbarAxis_pick(axis.options?.min, axis.min);
const axisMax = ScrollbarAxis_pick(axis.options?.max, axis.max);
return {
axisMin,
axisMax,
scrollMin: ScrollbarAxis_defined(axis.dataMin) ?
Math.min(axisMin, axis.min, axis.dataMin, ScrollbarAxis_pick(axis.threshold, Infinity)) : axisMin,
scrollMax: ScrollbarAxis_defined(axis.dataMax) ?
Math.max(axisMax, axis.max, axis.dataMax, ScrollbarAxis_pick(axis.threshold, -Infinity)) : axisMax
};
}
/**
* Make space for a scrollbar.
* @private
*/
function onAxisAfterGetOffset() {
const axis = this, scrollbar = axis.scrollbar, opposite = scrollbar && !scrollbar.options.opposite, index = axis.horiz ? 2 : opposite ? 3 : 1;
if (scrollbar) {
// Reset scrollbars offsets
axis.chart.scrollbarsOffsets = [0, 0];
axis.chart.axisOffset[index] +=
scrollbar.size + (scrollbar.options.margin || 0);
}
}
/**
* Wrap axis initialization and create scrollbar if enabled.
* @private
*/
function onAxisAfterInit() {
const axis = this;
if (axis.options?.scrollbar?.enabled) {
// Predefined options:
axis.options.scrollbar.vertical = !axis.horiz;
axis.options.startOnTick = axis.options.endOnTick = false;
axis.scrollbar = new Scrollbar(axis.chart.renderer, axis.options.scrollbar, axis.chart);
ScrollbarAxis_addEvent(axis.scrollbar, 'changed', function (e) {
const { axisMin, axisMax, scrollMin: unitedMin, scrollMax: unitedMax } = getExtremes(axis), range = unitedMax - unitedMin;
let to, from;
// #12834, scroll when show/hide series, wrong extremes
if (!ScrollbarAxis_defined(axisMin) || !ScrollbarAxis_defined(axisMax)) {
return;
}
if ((axis.horiz && !axis.reversed) ||
(!axis.horiz && axis.reversed)) {
to = unitedMin + range * this.to;
from = unitedMin + range * this.from;
}
else {
// Y-values in browser are reversed, but this also
// applies for reversed horizontal axis:
to = unitedMin + range * (1 - this.from);
from = unitedMin + range * (1 - this.to);
}
if (this.shouldUpdateExtremes(e.DOMType)) {
// #17977, set animation to undefined instead of true
const animate = e.DOMType === 'mousemove' ||
e.DOMType === 'touchmove' ? false : void 0;
axis.setExtremes(from, to, true, animate, e);
}
else {
// When live redraw is disabled, don't change extremes
// Only change the position of the scrollbar thumb
this.setRange(this.from, this.to);
}
});
}
}
/**
* Wrap rendering axis, and update scrollbar if one is created.
* @private
*/
function onAxisAfterRender() {
const axis = this, { scrollMin, scrollMax } = getExtremes(axis), scrollbar = axis.scrollbar, offset = (axis.axisTitleMargin + (axis.titleOffset || 0)), scrollbarsOffsets = axis.chart.scrollbarsOffsets, axisMargin = axis.options.margin || 0;
let offsetsIndex, from, to;
if (scrollbar && scrollbarsOffsets) {
if (axis.horiz) {
// Reserve space for labels/title
if (!axis.opposite) {
scrollbarsOffsets[1] += offset;
}
scrollbar.position(axis.left, (axis.top +
axis.height +
2 +
scrollbarsOffsets[1] -
(axis.opposite ? axisMargin : 0)), axis.width, axis.height);
// Next scrollbar should reserve space for margin (if set)
if (!axis.opposite) {
scrollbarsOffsets[1] += axisMargin;
}
offsetsIndex = 1;
}
else {
// Reserve space for labels/title
if (axis.opposite) {
scrollbarsOffsets[0] += offset;
}
let xPosition;
if (!scrollbar.options.opposite) {
xPosition = axis.opposite ? 0 : axisMargin;
}
else {
xPosition = axis.left +
axis.width +
2 +
scrollbarsOffsets[0] -
(axis.opposite ? 0 : axisMargin);
}
scrollbar.position(xPosition, axis.top, axis.width, axis.height);
// Next scrollbar should reserve space for margin (if set)
if (axis.opposite) {
scrollbarsOffsets[0] += axisMargin;
}
offsetsIndex = 0;
}
scrollbarsOffsets[offsetsIndex] += scrollbar.size +
(scrollbar.options.margin || 0);
if (isNaN(scrollMin) ||
isNaN(scrollMax) ||
!ScrollbarAxis_defined(axis.min) ||
!ScrollbarAxis_defined(axis.max) ||
axis.dataMin === axis.dataMax // #10733
) {
// Default action: when data extremes are the same or there is
// not extremes on the axis,