UNPKG

highcharts

Version:
1,410 lines (1,388 loc) 189 kB
// SPDX-License-Identifier: LicenseRef-Highcharts /** * @license Highcharts JS v13.0.1 (2026-08-17) * @module highcharts/modules/navigator * @requires highcharts * * Standalone navigator module * * (c) 2009-2026 Highsoft AS * Author: Mateusz Bernacik * * A commercial license may be required depending on use, * see www.highcharts.com/license */ import * as __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__ from "../highcharts.src.js"; /******/ // The require scope /******/ const __webpack_require__ = {}; /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = (module) => { /******/ const getter = module && module.__esModule ? /******/ () => (module['default']) : /******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter/value functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ if(Array.isArray(definition)) { /******/ var i = 0; /******/ while(i < definition.length) { /******/ var key = definition[i++]; /******/ var binding = definition[i++]; /******/ if(!__webpack_require__.o(exports, key)) { /******/ if(binding === 0) { /******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] }); /******/ } else { /******/ Object.defineProperty(exports, key, { enumerable: true, get: binding }); /******/ } /******/ } else if(binding === 0) { i++; } /******/ } /******/ } else { /******/ 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-2026 Highsoft AS * Author: Torstein Hønsi * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * */ const { isTouchDevice } = (external_highcharts_src_js_default_default()); /* * * * Constants * * */ const composedMembers = []; /* * * * Variables * * */ let NavigatorConstructor; /* * * * Functions * * */ /** @internal */ function compose(ChartClass, NavigatorClass) { if ((0,external_highcharts_src_js_default_namespaceObject.pushUnique)(composedMembers, ChartClass)) { const chartProto = ChartClass.prototype; NavigatorConstructor = NavigatorClass; chartProto.callbacks.push(onChartCallback); (0,external_highcharts_src_js_default_namespaceObject.addEvent)(ChartClass, 'afterAddSeries', onChartAfterAddSeries); (0,external_highcharts_src_js_default_namespaceObject.addEvent)(ChartClass, 'afterSetChartSize', onChartAfterSetChartSize); (0,external_highcharts_src_js_default_namespaceObject.addEvent)(ChartClass, 'afterUpdate', onChartAfterUpdate); (0,external_highcharts_src_js_default_namespaceObject.addEvent)(ChartClass, 'beforeRender', onChartBeforeRender); (0,external_highcharts_src_js_default_namespaceObject.addEvent)(ChartClass, 'beforeShowResetZoom', onChartBeforeShowResetZoom); (0,external_highcharts_src_js_default_namespaceObject.addEvent)(ChartClass, 'update', onChartUpdate); } } /** * Handle adding new series. * @internal */ 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. * @internal */ 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 = (0,external_highcharts_src_js_default_namespaceObject.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 + (0,external_highcharts_src_js_default_namespaceObject.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. * @internal */ function onChartAfterUpdate(event) { if (!this.navigator && !this.scroller && (this.options.navigator.enabled || this.options.scrollbar.enabled)) { this.scroller = this.navigator = new NavigatorConstructor(this); if ((0,external_highcharts_src_js_default_namespaceObject.pick)(event.redraw, true)) { this.redraw(event.animation); // #7067 } } } /** * Initialize navigator for stock charts * @internal */ 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) * @internal */ 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; } } /** @internal */ 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 * @internal */ function onChartUpdate(e) { const navigatorOptions = (e.options.navigator || {}), scrollbarOptions = (e.options.scrollbar || {}); if (!this.navigator && !this.scroller && (navigatorOptions.enabled || scrollbarOptions.enabled)) { (0,external_highcharts_src_js_default_namespaceObject.merge)(true, this.options.navigator, navigatorOptions); (0,external_highcharts_src_js_default_namespaceObject.merge)(true, this.options.scrollbar, scrollbarOptions); delete e.options.navigator; delete e.options.scrollbar; } } /* * * * Default Export * * */ /** @internal */ const ChartNavigatorComposition = { compose }; /** @internal */ /* harmony default export */ const Navigator_ChartNavigatorComposition = (ChartNavigatorComposition); ;// ./code/es-modules/Core/Axis/NavigatorAxisComposition.js /* * * * (c) 2010-2026 Highsoft AS * Author: Torstein Hønsi * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * */ const { isTouchDevice: NavigatorAxisComposition_isTouchDevice } = (external_highcharts_src_js_default_default()); /* * * * Functions * * */ /** @internal */ 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. * @internal */ 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 ((0,external_highcharts_src_js_default_namespaceObject.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 * * */ /** @internal */ class NavigatorAxisAdditions { /* * * * Static Functions * * */ static compose(AxisClass) { if (!AxisClass.keepProps.includes('navigatorAxis')) { AxisClass.keepProps.push('navigatorAxis'); (0,external_highcharts_src_js_default_namespaceObject.addEvent)(AxisClass, 'init', onAxisInit); (0,external_highcharts_src_js_default_namespaceObject.addEvent)(AxisClass, 'setExtremes', onAxisSetExtremes); } } /* * * * Constructors * * */ constructor(axis) { this.axis = axis; } /* * * * Functions * * */ destroy() { this.axis = void 0; } /** * Add logic to normalize the zoomed range in order to preserve the pressed * state of range selector buttons * * @internal * @function Highcharts.Axis#toFixedRange */ toFixedRange(pxMin, pxMax, fixedMin, fixedMax) { const axis = this.axis, halfPointRange = (axis.pointRange || 0) / 2; let newMin = (0,external_highcharts_src_js_default_namespaceObject.pick)(fixedMin, axis.translate(pxMin, true, !axis.horiz)), newMax = (0,external_highcharts_src_js_default_namespaceObject.pick)(fixedMax, axis.translate(pxMax, true, !axis.horiz)); // Add/remove half point range to/from the extremes (#1172) if (!(0,external_highcharts_src_js_default_namespaceObject.defined)(fixedMin)) { newMin = (0,external_highcharts_src_js_default_namespaceObject.correctFloat)(newMin + halfPointRange); } if (!(0,external_highcharts_src_js_default_namespaceObject.defined)(fixedMax)) { newMax = (0,external_highcharts_src_js_default_namespaceObject.correctFloat)(newMax - halfPointRange); } if (!(0,external_highcharts_src_js_default_namespaceObject.isNumber)(newMin) || !(0,external_highcharts_src_js_default_namespaceObject.isNumber)(newMax)) { // #1195, #7411 newMin = newMax = void 0; } return { min: newMin, max: newMax }; } } /* * * * Default Export * * */ /** @internal */ /* harmony default export */ const NavigatorAxisComposition = (NavigatorAxisAdditions); ;// 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-2026 Highsoft AS * Author: Torstein Hønsi * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * */ 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 5.0.0 * @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.ColorType} */ backgroundColor: 'var(--highcharts-neutral-color-5)', /** * The stroke for the handle border and the stripes inside. * * @type {Highcharts.ColorType} */ borderColor: 'var(--highcharts-neutral-color-40)' }, /** * 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.ColorType} */ maskFill: 'color-mix(in srgb, var(--highcharts-highlight-color-60) 30%, transparent)', // eslint-disable-line max-len /** * The color of the line marking the currently zoomed area in the * navigator. * * @sample {highstock} stock/navigator/outline/ * 2px blue outline * * @type {Highcharts.ColorType} */ outlineColor: 'var(--highcharts-neutral-color-40)', /** * 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 color of the navigator series. * * @type {Highcharts.ColorType} * @apioption navigator.series.color */ /** * Sets the fill color of the navigator series. Applies to series * types with a filled area, like the default `areaspline`. * * @type {Highcharts.ColorType} * @apioption navigator.series.fillColor */ /** * 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. * * @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: 'var(--highcharts-neutral-color-10)', id: 'navigator-x-axis', gridLineWidth: 1, tickPixelInterval: 200, labels: { align: 'left', /** * @type {Highcharts.CSSObject} */ style: { /** @ignore */ color: 'var(--highcharts-neutral-color-100)', /** @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 * * */ /** @internal */ /* 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/Extensions/BorderRadius.js /* unused harmony import specifier */ var relativeLength; /* unused harmony import specifier */ var isObject; /* unused harmony import specifier */ var extend; /* unused harmony import specifier */ var addEvent; /* * * * Highcharts Border Radius module * * Author: Torstein Hønsi * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * */ const { defaultOptions } = (external_highcharts_src_js_default_default()); const { noop } = (external_highcharts_src_js_default_default()); /* * * * Constants * * */ const defaultBorderRadiusOptions = { radius: 0, scope: 'stack', where: void 0 }; /* * * * Variables * * */ let oldArc = (/* unused pure expression or super */ null && (noop)); let oldRoundedRect = (/* unused pure expression or super */ null && (noop)); /* * * * Functions * * */ /** @internal */ function applyBorderRadius(path, i, r) { const a = path[i]; let b = path[i + 1]; if (b[0] === 'Z') { b = path[0]; } let line, arc, fromLineToArc; // From straight line to arc if ((a[0] === 'M' || a[0] === 'L') && b[0] === 'A') { line = a; arc = b; fromLineToArc = true; // From arc to straight line } else if (a[0] === 'A' && (b[0] === 'M' || b[0] === 'L')) { line = b; arc = a; } if (line && arc && arc.params) { const bigR = arc[1], // In our use cases, outer pie slice arcs are clockwise and inner // arcs (donut/sunburst etc) are anti-clockwise clockwise = arc[5], params = arc.params, { start, end, cx, cy } = params; // Some geometric constants const relativeR = clockwise ? (bigR - r) : (bigR + r), // The angle, on the big arc, that the border radius arc takes up angleOfBorderRadius = relativeR ? Math.asin(r / relativeR) : 0, angleOffset = clockwise ? angleOfBorderRadius : -angleOfBorderRadius, // The distance along the radius of the big arc to the starting // point of the small border radius arc distanceBigCenterToStartArc = (Math.cos(angleOfBorderRadius) * relativeR); // From line to arc if (fromLineToArc) { // Update the cache params.start = start + angleOffset; // First move to the start position at the radial line. We want to // start one borderRadius closer to the center. line[1] = cx + distanceBigCenterToStartArc * Math.cos(start); line[2] = cy + distanceBigCenterToStartArc * Math.sin(start); // Now draw an arc towards the point where the small circle touches // the great circle. path.splice(i + 1, 0, [ 'A', r, r, 0, // Slanting, 0, // Long arc 1, // Clockwise cx + bigR * Math.cos(params.start), cy + bigR * Math.sin(params.start) ]); // From arc to line } else { // Update the cache params.end = end - angleOffset; // End the big arc a bit earlier arc[6] = cx + bigR * Math.cos(params.end); arc[7] = cy + bigR * Math.sin(params.end); // Draw a small arc towards a point on the end angle, but one // borderRadius closer to the center relative to the perimeter. path.splice(i + 1, 0, [ 'A', r, r, 0, 0, 1, cx + distanceBigCenterToStartArc * Math.cos(end), cy + distanceBigCenterToStartArc * Math.sin(end) ]); } // Long or short arc must be reconsidered because we have modified the // start and end points arc[4] = Math.abs(params.end - params.start) < Math.PI ? 0 : 1; } } /** * Extend arc with borderRadius. * @internal */ function arc(x, y, w, h, options = {}) { const path = oldArc(x, y, w, h, options), { brStart = true, brEnd = true, innerR = 0, r = w, start = 0, end = 0 } = options; if (options.open || !options.borderRadius) { return path; } const alpha = end - start, sinHalfAlpha = Math.sin(alpha / 2), borderRadius = Math.max(Math.min(relativeLength(borderRadiusObject(options.borderRadius).radius, r - innerR), // Cap to half the sector radius (r - innerR) / 2, // For smaller pie slices, cap to the largest small circle that // can be fitted within the sector (r * sinHalfAlpha) / (1 + sinHalfAlpha)), 0), // For the inner radius, we need an extra cap because the inner arc // is shorter than the outer arc innerBorderRadius = Math.min(borderRadius, 2 * (alpha / Math.PI) * innerR); // Apply turn-by-turn border radius. Start at the end since we're // splicing in arc segments. let i = path.length - 1; while (i--) { if ((!brStart && (i === 0 || i === 3)) || (!brEnd && (i === 1 || i === 2))) { continue; } applyBorderRadius(path, i, i > 1 ? innerBorderRadius : borderRadius); } return path; } /** @internal */ function seriesOnAfterColumnTranslate() { if (this.options.borderRadius && !(this.chart.is3d && this.chart.is3d())) { const { options, yAxis } = this, percent = options.stacking === 'percent', seriesDefault = defaultOptions.plotOptions?.[this.type] ?.borderRadius, borderRadius = borderRadiusObject(options.borderRadius, isObject(seriesDefault) ? seriesDefault : {}), reversed = yAxis.options.reversed; for (const point of this.points) { const { shapeArgs } = point; if (point.shapeType === 'roundedRect' && shapeArgs) { const { width = 0, height = 0, y = 0 } = shapeArgs; let brBoxY = y, brBoxHeight = height; // It would be nice to refactor StackItem.getStackBox/ // setOffset so that we could get a reliable box out of // it. Currently it is close if we remove the label // offset, but we still need to run crispCol and also // flip it if inverted, so atm it is simpler to do it // like the below. if (borderRadius.scope === 'stack' && point.stackTotal) { const stackEnd = yAxis.translate(percent ? 100 : point.stackTotal, false, true, false, true), stackThreshold = yAxis.translate(options.threshold || 0, false, true, false, true), box = this.crispCol(0, Math.min(stackEnd, stackThreshold), 0, Math.abs(stackEnd - stackThreshold)); brBoxY = box.y; brBoxHeight = box.height; } const flip = (point.negative ? -1 : 1) * (reversed ? -1 : 1) === -1; // Handle the where option let where = borderRadius.where; // Waterfall, hanging columns should have rounding on // all sides if (!where && this.is('waterfall') && Math.abs((point.yBottom || 0) - (this.translatedThreshold || 0)) > this.borderWidth) { where = 'all'; } if (!where) { where = 'end'; } // Get the radius const r = Math.min(relativeLength(borderRadius.radius, width), width / 2, // Cap to the height, but not if where is `end` where === 'all' ? brBoxHeight / 2 : Infinity) || 0; // If the `where` option is 'end', cut off the // rectangles by making the border-radius box one r // greater, so that the imaginary radius falls outside // the rectangle. if (where === 'end') { if (flip) { brBoxY -= r; brBoxHeight += r; } else { brBoxHeight += r; } } extend(shapeArgs, { brBoxHeight, brBoxY, r }); } } } } /** @internal */ function composeBorderRadius(SeriesClass, SVGElementClass, SVGRendererClass) { const PieSeriesClass = SeriesClass.types.pie; if (!SVGElementClass.symbolCustomAttribs.includes('borderRadius')) { const symbols = SVGRendererClass.prototype.symbols; addEvent(SeriesClass, 'afterColumnTranslate', seriesOnAfterColumnTranslate, { // After columnrange and polar column modifications order: 9 }); addEvent(PieSeriesClass, 'afterTranslate', pieSeriesOnAfterTranslate); SVGElementClass.symbolCustomAttribs.push('borderRadius', 'brBoxHeight', 'brBoxY', 'brEnd', 'brStart'); oldArc = symbols.arc; oldRoundedRect = symbols.roundedRect; symbols.arc = arc; symbols.roundedRect = roundedRect; } } /** * Utility function to get the full border radius options object, from a simple * number or a partial options object. * @internal */ function borderRadiusObject(options, seriesBROptions) { if (!(0,external_highcharts_src_js_default_namespaceObject.isObject)(options)) { options = { radius: options || 0 }; } return (0,external_highcharts_src_js_default_namespaceObject.merge)(defaultBorderRadiusOptions, seriesBROptions, options); } /** @internal */ function pieSeriesOnAfterTranslate() { const borderRadius = borderRadiusObject(this.options.borderRadius); for (const point of this.points) { const shapeArgs = point.shapeArgs; if (shapeArgs) { shapeArgs.borderRadius = relativeLength(borderRadius.radius, (shapeArgs.r || 0) - ((shapeArgs.innerR) || 0)); } } } /** * Extend roundedRect with individual cutting through rOffset. * @internal */ function roundedRect(x, y, width, height, options = {}) { const path = oldRoundedRect(x, y, width, height, options), { r = 0, brBoxHeight = height, brBoxY = y } = options, brOffsetTop = y - brBoxY, brOffsetBtm = (brBoxY + brBoxHeight) - (y + height), // When the distance to the border-radius box is greater than the r // itself, it means no border radius. The -0.1 accounts for float // rounding errors. rTop = (brOffsetTop - r) > -0.1 ? 0 : r, rBtm = (brOffsetBtm - r) > -0.1 ? 0 : r, cutTop = Math.max(rTop && brOffsetTop, 0), cutBtm = Math.max(rBtm && brOffsetBtm, 0); /* The naming of control points: / a -------- b \ / \ h c | | | | | | g d \ / \ f -------- e / */ const a = [x + rTop, y], b = [x + width - rTop, y], c = [x + width, y + rTop], d = [ x + width, y + height - rBtm ], e = [ x + width - rBtm, y + height ], f = [x + rBtm, y + height], g = [x, y + height - rBtm], h = [x, y + rTop]; const applyPythagoras = (r, altitude) => Math.sqrt(Math.pow(r, 2) - Math.pow(altitude, 2)); // Inside stacks, cut off part of the top if (cutTop) { const base = applyPythagoras(rTop, rTop - cutTop); a[0] -= base; b[0] += base; c[1] = h[1] = y + rTop - cutTop; } // Column is lower than the radius. Cut off bottom inside the top // radius. if (height < rTop - cutTop) { const base = applyPythagoras(rTop, rTop - cutTop - height); c[0] = d[0] = x + width - rTop + base; e[0] = Math.min(c[0], e[0]); f[0] = Math.max(d[0], f[0]); g[0] = h[0] = x + rTop - base; c[1] = h[1] = y + height; } // Inside stacks, cut off part of the bottom if (cutBtm) { const base = applyPythagoras(rBtm, rBtm - cutBtm); e[0] += base; f[0] -= base; d[1] = g[1] = y + height - rBtm + cutBtm; } // Cut off top inside the bottom radius if (height < rBtm - cutBtm) { const base = applyPythagoras(rBtm, rBtm - cutBtm - height); c[0] = d[0] = x + width - rBtm + base; b[0] = Math.min(c[0], b[0]); a[0] = Math.max(d[0], a[0]); g[0] = h[0] = x + rBtm - base; d[1] = g[1] = y; } // Preserve the box for data labels path.length = 0; path.push(['M', ...a], // Top side ['L', ...b], // Top right corner ['A', rTop, rTop, 0, 0, 1, ...c], // Right side ['L', ...d], // Bottom right corner ['A', rBtm, rBtm, 0, 0, 1, ...e], // Bottom side ['L', ...f], // Bottom left corner ['A', rBtm, rBtm, 0, 0, 1, ...g], // Left side ['L', ...h], // Top left corner ['A', rTop, rTop, 0, 0, 1, ...a], ['Z']); return path; } /* * * * API Declarations * * */ /** * Detailed options for border radius. * * @sample {highcharts} highcharts/plotoptions/column-borderradius/ * Rounded columns * @sample highcharts/plotoptions/series-border-radius * Column and pie with rounded border * * @interface Highcharts.BorderRadiusOptionsObject */ /** * The border radius. A number signifies pixels. A percentage string, like for * example `50%`, signifies a relative size. For columns this is relative to the * column width, for pies it is relative to the radius and the inner radius. * * @sample {highcharts} highcharts/plotoptions/column-borderradius/ * Rounded columns * @sample highcharts/plotoptions/series-border-radius * Column and pie with rounded border * * @name Highcharts.BorderRadiusOptionsObject#radius * @type {string|number|undefined} */ /** * The scope of the rounding for column charts or plot bands. In a stacked * column chart, the value `point` means each single point will get rounded * corners. The value `stack` means the rounding will apply to the full * stack, so that only points close to the top or bottom will receive * rounding. * * Similarly, for plot bands, the `individual` value means each plot band * will get rounded corners. * * @sample {highcharts} highcharts/plotoptions/column-borderradius/ * Rounded columns * * @name Highcharts.BorderRadiusOptionsObject#scope * @type {"individual"|"point"|"stack"|undefined} */ /** * For column charts, where in the point or stack to apply rounding. The `end` * value means only those corners at the point value will be rounded, leaving * the corners at the base or threshold unrounded. This is the most intuitive * behavior. The `all` value means also the base will be rounded. * * @sample {highcharts} highcharts/plotoptions/column-borderradius-where-all * Rounding on all corners * * @name Highcharts.BorderRadiusOptionsObject#where * @type {"all"|"end"|undefined} * @default end */ (''); // Keeps doclets above in JS file ;// ./code/es-modules/Core/Renderer/SVG/Symbols.js /* * * * (c) 2010-2026 Highsoft AS * Author: Torstein Hønsi * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * */ /* * * * Functions * * */ /* eslint-disable require-jsdoc, valid-jsdoc */ /** * Arc symbol path. * * @param {number} cx * Center X * @param {number} cy * Center Y * @param {number} w * Width * @param {number} h * Height * @param {Highcharts.SymbolOptions} [options] * Options * @return {Highcharts.SVGPathArray} * Path */ function Symbols_arc(cx, cy, w, h, options) { const arc = []; if (options) { let start = options.start || 0, end = options.end || 0; const rx = (0,external_highcharts_src_js_default_namespaceObject.pick)(options.r, w), ry = (0,external_highcharts_src_js_default_namespaceObject.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). See "Arc proximity" // tests at samples/unit-tests/svgrenderer/symbol/demo.js proximity = 0.0001, 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 = (0,external_highcharts_src_js_default_namespaceObject.pick)(options.open, fullCircle), cosStart = fullCircle ? 0 : Math.cos(start), sinStart = fullCircle ? 1 : Math.sin(start), cosEnd = fullCircle ? 0 : Math.cos(end), sinEnd = fullCircle ? 1 : Math.sin(end), // Proximity takes care of rounding errors around PI (#6971) longArc = (0,external_highcharts_src_js_default_namespaceObject.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 (0,external_highcharts_src_js_default_namespaceObject.pick)(options.clockwise, 1), // Clockwise // Use a static pixel offset for full circle (#21701) cx + (fullCircle ? 0.001 : 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 ((0,external_highcharts_src_js_default_namespaceObject.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 (0,external_highcharts_src_js_default_namespaceObject.defined)(options.clockwise) ? 1 - optio