From ccd8e75ace4eb7c7005f8a93be0e5722191630fb Mon Sep 17 00:00:00 2001 From: ivankirshin Date: Fri, 1 Dec 2023 14:59:15 +0400 Subject: [PATCH 1/8] #2175: Chromatogram: Refactor component for painting chromatogram --- README.md | 2 + lib/index-newcrom.d.ts | 2709 +++++++++++++++++++++++++++ package-lock.json | 4 +- package.json | 11 +- src/components/dragelement/index.js | 4 + src/components/fx/click.js | 2 +- src/components/shapes/draw.js | 22 +- src/lib/index.js | 2 +- src/plot_api/plot_api.js | 10 +- 9 files changed, 2750 insertions(+), 16 deletions(-) create mode 100644 lib/index-newcrom.d.ts diff --git a/README.md b/README.md index 2c0b10cd67d..c573c650883 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**Forked version of plotly.js with some hacks for use in Newcrom's products** + [![npm version](https://badge.fury.io/js/plotly.js.svg)](https://badge.fury.io/js/plotly.js) diff --git a/lib/index-newcrom.d.ts b/lib/index-newcrom.d.ts new file mode 100644 index 00000000000..4902932b9c2 --- /dev/null +++ b/lib/index-newcrom.d.ts @@ -0,0 +1,2709 @@ +interface Navigator { + /*** + * Exists only in Safari + */ + standalone?: boolean; +} + +interface Window { + ENV_APP_VERSION: string; +} + +// Type definitions for plotly.js 2.12 +// Project: https://plot.ly/javascript/, https://github.com/plotly/plotly.js +// Definitions by: Chris Gervang +// Martin Duparc +// Frederik Aalund +// taoqf +// Dadstart +// Jared Szechy +// Sooraj Pudiyadath +// Jon Freedman +// Megan Riel-Mehan +// Josh Miles +// Pramod Mathai +// Michael Adams +// Michael Arnett +// Piotr Błażejewicz +// Brandon Mitchell +// Jessica Blizzard +// Oleg Shilov +// Pablo Gracia +// Jeffrey van Gogh +// John Abdou +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +import { BoxPlotData, BoxPlotMarker } from './lib/traces/box'; +import { CandlestickData } from './lib/traces/candlestick'; +import { OhlcData } from './lib/traces/ohlc'; +import { PieData } from './lib/traces/pie'; +import { SankeyData } from './lib/traces/sankey'; +import { ViolinData } from './lib/traces/violin'; + +export as namespace Plotly; +export { BoxPlotData, CandlestickData, OhlcData, PieData, SankeyData, ViolinData }; + +export type DefaultIcons = + | 'undo' + | 'home' + | 'camera-retro' + | 'zoombox' + | 'pan' + | 'zoom_plus' + | 'zoom_minus' + | 'autoscale' + | 'tooltip_basic' + | 'tooltip_compare' + | 'plotlylogo' + | 'z-axis' + | '3d_rotate' + | 'camera' + | 'movie' + | 'question' + | 'disk' + | 'drawopenpath' + | 'drawclosedpath' + | 'lasso' + | 'selectbox' + | 'drawline' + | 'drawrect' + | 'drawcircle' + | 'eraseshape' + | 'spikeline' + | 'pencil' + | 'newplotlylogo'; + +export const Icons: { [K in DefaultIcons]: Icon }; + +export interface StaticPlots { + resize(root: Root): void; +} + +export const Plots: StaticPlots; + +export interface Point { + x: number; + y: number; + z: number; +} + +export interface PlotScatterDataPoint { + curveNumber: number; + data: PlotData; + pointIndex: number; + pointNumber: number; + x: number; + xaxis: LayoutAxis; + y: number; + yaxis: LayoutAxis; +} + +export interface PlotDatum { + curveNumber: number; + data: PlotData; + customdata: Datum; + pointIndex: number; + pointNumber: number; + x: Datum; + xaxis: LayoutAxis; + y: Datum; + yaxis: LayoutAxis; + text: string; +} + +export interface PlotMouseEvent { + points: PlotDatum[]; + event: MouseEvent; +} + +export interface PlotHoverEvent extends PlotMouseEvent { + xvals: Datum[]; + yvals: Datum[]; +} + +export interface PlotCoordinate { + x: number; + y: number; + pointNumber: number; +} + +export interface SelectionRange { + x: number[]; + y: number[]; +} + +export type PlotSelectedData = Partial; + +export interface PlotSelectionEvent { + points: PlotDatum[]; + range?: SelectionRange | undefined; + lassoPoints?: SelectionRange | undefined; +} + +export interface PlotRestyleEventUpdate { + [key: string]: any; +} + +export type PlotRestyleEvent = [PlotRestyleEventUpdate, number[]]; + +export interface PlotScene { + center: Point; + eye: Point; + up: Point; +} + +export interface PlotRelayoutEvent extends Partial { + 'xaxis.range[0]'?: number | undefined; + 'xaxis.range[1]'?: number | undefined; + 'yaxis.range[0]'?: number | undefined; + 'yaxis.range[1]'?: number | undefined; + 'xaxis.autorange'?: boolean | undefined; + 'yaxis.autorange'?: boolean | undefined; +} + +export interface ClickAnnotationEvent { + index: number; + annotation: Annotations; + fullAnnotation: Annotations; + event: MouseEvent; +} + +export interface FrameAnimationEvent { + name: string; + frame: Frame; + animation: { + frame: { + duration: number; + redraw: boolean; + }; + transition: Transition; + }; +} + +export interface LegendClickEvent { + event: MouseEvent; + node: PlotlyHTMLElement; + curveNumber: number; + expandedIndex: number; + data: Data[]; + layout: Partial; + frames: Frame[]; + config: Partial; + fullData: Data[]; + fullLayout: Partial; +} + +export interface MapboxCenter { + lon: number; + lat: number; +} + +export interface MapboxSymbol { + icon: string; + iconsize: number; + text: string; + placement: 'point' | 'line' | 'line-center'; + textfont: Partial; + textposition: + | 'top left' + | 'top center' + | 'top right' + | 'middle center' + | 'bottom left' + | 'bottom center' + | 'bottom right'; +} +export interface MapboxLayers { + visible: true; + sourcetype: 'geojson' | 'vecotr' | 'raster' | 'image'; + source: number | string; + sourcelayer: string; + sourceattribution: string; + type: 'circle' | 'line' | 'fill' | 'symbol' | 'raster'; + coordinates: number | string; + below: string; + color: Color; + opacity: number; + minzoom: number; + maxzoom: number; + circle: { radius: number }; + line: Partial; + fill: { outlinecolor: Color }; + symbol: Partial; + name: string; + templateitemname: string; +} +export interface Mapbox { + domain: Partial; + accesstoken: string; + style: number | string; + center: Partial; + zoom: number; + bearing: number; + pitch: number; + layers: Array>; + uirevision: number | string; + uid: string; +} + +export interface SliderChangeEvent { + slider: Slider; + step: SliderStep; + interaction: boolean; + previousActive: number; +} + +export interface SliderStartEvent { + slider: Slider; +} + +export interface SliderEndEvent { + slider: Slider; + step: SliderStep; +} + +export interface SunburstClickEvent { + event: MouseEvent; + nextLevel: string; + points: SunburstPlotDatum[]; +} + +export interface SunburstPlotDatum { + color: number; + curveNumber: number; + data: Data; + entry: string; + fullData: Data; + hovertext: string; + id: string; + label: string; + parent: string; + percentEntry: number; + percentParent: number; + percentRoot: number; + pointNumber: number; + root: string; + value: number; +} + +export interface BeforePlotEvent { + data: Data[]; + layout: Partial; + config: Partial; +} + +export interface PlotlyHTMLElement extends HTMLElement { + on(event: 'plotly_click' | 'plotly_unhover', callback: (event: PlotMouseEvent) => void): void; + on(event: 'plotly_hover', callback: (event: PlotHoverEvent) => void): void; + on( + event: 'plotly_selecting' | 'plotly_selected', + callback: (event: PlotSelectionEvent) => void, + ): void; + on(event: 'plotly_restyle', callback: (data: PlotRestyleEvent) => void): void; + on( + event: 'plotly_relayout' | 'plotly_relayouting', + callback: (event: PlotRelayoutEvent) => void, + ): void; + on(event: 'plotly_clickannotation', callback: (event: ClickAnnotationEvent) => void): void; + on(event: 'plotly_animatingframe', callback: (event: FrameAnimationEvent) => void): void; + on( + event: 'plotly_legendclick' | 'plotly_legenddoubleclick', + callback: (event: LegendClickEvent) => boolean, + ): void; + on(event: 'plotly_sliderchange', callback: (event: SliderChangeEvent) => void): void; + on(event: 'plotly_sliderend', callback: (event: SliderEndEvent) => void): void; + on(event: 'plotly_sliderstart', callback: (event: SliderStartEvent) => void): void; + on(event: 'plotly_sunburstclick', callback: (event: SunburstClickEvent) => void): void; + on(event: 'plotly_event', callback: (data: any) => void): void; + on(event: 'plotly_beforeplot', callback: (event: BeforePlotEvent) => boolean): void; + on( + event: + | 'plotly_afterexport' + | 'plotly_afterplot' + | 'plotly_animated' + | 'plotly_animationinterrupted' + | 'plotly_autosize' + | 'plotly_beforeexport' + | 'plotly_deselect' + | 'plotly_doubleclick' + | 'plotly_framework' + | 'plotly_redraw' + | 'plotly_transitioning' + | 'plotly_transitioninterrupted', + callback: () => void, + ): void; + removeAllListeners: (handler: string) => void; + data: Data[]; + layout: Layout; + /** + * !!! Modified: Fixed to use private field + */ + _fullLayout: { + xaxis: { + p2d(point: number): number + }, + yaxis: { + p2d(point: number): number + }, + } +} + +export interface ToImgopts { + format: 'jpeg' | 'png' | 'webp' | 'svg'; + width: number; + height: number; + scale?: number | undefined; +} + +export interface DownloadImgopts { + format: 'jpeg' | 'png' | 'webp' | 'svg'; + width: number; + height: number; + filename: string; +} + +export interface PolarLayout { + domain: Partial; + sector: number[]; + hole: number; + bgcolor: Color; + radialaxis: Partial; + angularaxis: Partial; + gridshape: 'circular' | 'linear'; + uirevision: string | number; + uid: string; +} + +export interface PlotlyDataLayoutConfig { + data: Data[]; + layout?: Partial; + config?: Partial; +} + +export type Root = string | HTMLElement; + +export type RootOrData = Root | PlotlyDataLayoutConfig; + +export function newPlot( + root: Root, + data: Data[], + layout?: Partial, + config?: Partial, +): Promise; +export function relayout(root: Root, layout: Partial): Promise; +export function redraw(root: Root): Promise; +export function purge(root: Root): void; +export function restyle( + root: Root, + aobj: Data, + traces?: number[] | number, +): Promise; +export function update( + root: Root, + traceUpdate: Data, + layoutUpdate: Partial, + traces?: number[] | number, +): Promise; +export function addTraces( + root: Root, + traces: Data | Data[], + newIndices?: number[] | number, +): Promise; +export function deleteTraces(root: Root, indices: number[] | number): Promise; +export function moveTraces( + root: Root, + currentIndices: number[] | number, + newIndices?: number[] | number, +): Promise; +export function extendTraces( + root: Root, + update: Data | Data[], + indices: number | number[], + maxPoints?: number, +): Promise; +export function prependTraces( + root: Root, + update: Data | Data[], + indices: number | number[], +): Promise; +export function toImage(root: RootOrData, opts?: ToImgopts): Promise; +export function downloadImage(root: RootOrData, opts: DownloadImgopts): Promise; +export function react( + root: Root, + data: Data[], + layout?: Partial, + config?: Partial, + isForceUpdate?: boolean +): Promise; +export function addFrames(root: Root, frames: Array>): Promise; +export function deleteFrames(root: Root, frames: number[]): Promise; +export function register(modules: PlotlyModule | PlotlyModule[]): void; + +// Layout +export interface Layout { + colorway: string[]; + title: + | string + | Partial<{ + text: string; + font: Partial; + xref: 'container' | 'paper'; + yref: 'container' | 'paper'; + x: number; + y: number; + xanchor: 'auto' | 'left' | 'center' | 'right'; + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + pad: Partial; + }>; + titlefont: Partial; + autosize: boolean; + showlegend: boolean; + paper_bgcolor: Color; + plot_bgcolor: Color; + separators: string; + hidesources: boolean; + xaxis: Partial; + xaxis2: Partial; + xaxis3: Partial; + xaxis4: Partial; + xaxis5: Partial; + xaxis6: Partial; + xaxis7: Partial; + xaxis8: Partial; + xaxis9: Partial; + yaxis: Partial; + yaxis2: Partial; + yaxis3: Partial; + yaxis4: Partial; + yaxis5: Partial; + yaxis6: Partial; + yaxis7: Partial; + yaxis8: Partial; + yaxis9: Partial; + margin: Partial; + height: number; + width: number; + hovermode: 'closest' | 'x' | 'y' | 'x unified' | 'y unified' | false; + hoverdistance: number; + hoverlabel: Partial; + calendar: Calendar; + 'xaxis.range': [Datum, Datum]; + 'xaxis.range[0]': Datum; + 'xaxis.range[1]': Datum; + 'yaxis.range': [Datum, Datum]; + 'yaxis.range[0]': Datum; + 'yaxis.range[1]': Datum; + 'yaxis.type': AxisType; + 'xaxis.type': AxisType; + 'xaxis.autorange': boolean; + 'yaxis.autorange': boolean; + 'xaxis.title': string; + 'yaxis.title': string; + ternary: {}; // TODO + geo: {}; // TODO + mapbox: Partial; + subplot: string; + radialaxis: Partial; + angularaxis: {}; // TODO + dragmode: 'zoom' | 'pan' | 'select' | 'lasso' | 'orbit' | 'turntable' | false; + orientation: number; + annotations: Array>; + shapes: Array>; + images: Array>; + updatemenus: Array>; + sliders: Array>; + legend: Partial; + font: Partial; + scene: Partial; + barmode: 'stack' | 'group' | 'overlay' | 'relative'; + barnorm: '' | 'fraction' | 'percent'; + bargap: number; + bargroupgap: number; + boxmode: 'group' | 'overlay'; + selectdirection: 'h' | 'v' | 'd' | 'any'; + hiddenlabels: string[]; + grid: Partial<{ + rows: number; + roworder: 'top to bottom' | 'bottom to top'; + columns: number; + subplots: string[]; + xaxes: string[]; + yaxes: string[]; + pattern: 'independent' | 'coupled'; + xgap: number; + ygap: number; + domain: Partial<{ + x: number[]; + y: number[]; + }>; + xside: 'bottom' | 'bottom plot' | 'top plot' | 'top'; + yside: 'left' | 'left plot' | 'right plot' | 'right'; + }>; + polar: Partial; + polar2: Partial; + polar3: Partial; + polar4: Partial; + polar5: Partial; + polar6: Partial; + polar7: Partial; + polar8: Partial; + polar9: Partial; + transition: Transition; + template: Template; + clickmode: 'event' | 'select' | 'event+select' | 'none'; + uirevision: number | string; + uid: string; + datarevision: number | string; + editrevision: number | string; + selectionrevision: number | string; + modebar: Partial; +} + +export interface Legend extends Label { + borderwidth: number; + groupclick: 'toggleitem' | 'togglegroup'; + grouptitlefont: Partial; + itemclick: 'toggle' | 'toggleothers' | false; + itemdoubleclick: 'toggle' | 'toggleothers' | false; + itemsizing: 'trace' | 'constant'; + itemwidth: number; + orientation: 'v' | 'h'; + title: Partial; + tracegroupgap: number; + traceorder: 'grouped' | 'normal' | 'reversed' | 'reversed+grouped'; + uirevision: number | string; + uid: string; + valign: 'top' | 'middle' | 'bottom'; + x: number; + xanchor: 'auto' | 'left' | 'center' | 'right'; + y: number; + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; +} + +export type AxisType = '-' | 'linear' | 'log' | 'date' | 'category' | 'multicategory'; + +export type DTickValue = number | string; + +export interface TickFormatStop { + /** + * Determines whether or not this stop is used. If `false`, + * this stop is ignored even within its `dtickrange`. + */ + enabled: boolean; + /** + * Range [`min`, `max`], where `min`, `max` - dtick values + * which describe some zoom level, it is possible to omit `min` or `max` + * value by passing `null` + */ + dtickrange: [DTickValue | null, DTickValue | null]; + /** + * dtickformat for described zoom level, the same as `tickformat` + */ + value: string; + /** + * When used in a template, named items are created in the output figure + * in addition to any items the figure already has in this array. + * You can modify these items in the output figure by making + * your own item with `templateitemname` matching this `name` + * alongside your modifications (including `visible: false` or `enabled: false` to hide it). + * Has no effect outside of a template. + */ + name: string; + /** + * Used to refer to a named item in this array in the template. + * Named items from the template will be created even without + * a matching item in the input figure, but you can modify one by + * making an item with `templateitemname` matching its `name`, + * alongside your modifications (including `visible: false` or `enabled: false` to hide it). + * If there is no template or no matching item, this item will be hidden + * unless you explicitly show it with `visible: true`. + */ + templateitemname: string; +} + +export interface Axis { + /** + * A single toggle to hide the axis while preserving interaction like dragging. + * Default is true when a cheater plot is present on the axis, otherwise + * false + */ + visible: boolean; + /** + * Sets default for all colors associated with this axis + * all at once: line, font, tick, and grid colors. + * Grid color is lightened by blending this with the plot background + * Individual pieces can override this. + */ + color: Color; + title: string | Partial; + /** + * Former `titlefont` is now the sub-attribute `font` of `title`. + * To customize title font properties, please use `title.font` now. + */ + titlefont: Partial; + type: AxisType; + autorange: true | false | 'reversed'; + /** + * 'If *normal*, the range is computed in relation to the extrema + * of the input data. + * If *tozero*`, the range extends to 0, + * regardless of the input data + * If *nonnegative*, the range is non-negative, + * regardless of the input data. + * Applies only to linear axes. + */ + rangemode: 'normal' | 'tozero' | 'nonnegative'; + range: any[]; + /** + * Determines whether or not this axis is zoom-able. + * If true, then zoom is disabled. + */ + fixedrange: boolean; + + /** + * Ticks + */ + tickmode: 'auto' | 'linear' | 'array'; + nticks: number; + tick0: number | string; + dtick: DTickValue; + tickvals: any[]; + ticktext: string[]; + ticks: 'outside' | 'inside' | ''; + mirror: true | 'ticks' | false | 'all' | 'allticks'; + ticklen: number; + tickwidth: number; + tickcolor: Color; + showticklabels: boolean; + showspikes: boolean; + spikecolor: Color; + spikethickness: number; + /** + * Specifies the ordering logic for the case of categorical variables. + * By default, plotly uses *trace*, which specifies the order that is present in the data supplied. + * Set `categoryorder` to *category ascending* or *category descending* if order should be determined by + * the alphanumerical order of the category names. + * Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category + * is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to + * the *trace* mode. The unspecified categories will follow the categories in `categoryarray`. + * Set `categoryorder` to *total ascending* or *total descending* if order should be determined by the + * numerical order of the values. + * Similarly, the order can be determined by the min, max, sum, mean or median of all the values. + */ + categoryorder: + | 'trace' + | 'category ascending' + | 'category descending' + | 'array' + | 'total ascending' + | 'total descending' + | 'min ascending' + | 'min descending' + | 'max ascending' + | 'max descending' + | 'sum ascending' + | 'sum descending' + | 'mean ascending' + | 'mean descending' + | 'median ascending' + | 'median descending'; + categoryarray: any[]; + tickfont: Partial; + tickangle: 'auto' | number; + tickprefix: string; + /** + * If `all`, all tick labels are displayed with a prefix. + * If `first`, only the first tick is displayed with a prefix. + * If `last`, only the last tick is displayed with a suffix. + * If `none`, tick prefixes are hidden. + */ + showtickprefix: 'all' | 'first' | 'last' | 'none'; + /** + * Sets a tick label suffix. + */ + ticksuffix: string; + /** + * Same as `showtickprefix` but for tick suffixes. + */ + showticksuffix: 'all' | 'first' | 'last' | 'none'; + /** + * If `all`, all exponents are shown besides their significands. + * If `first`, only the exponent of the first tick is shown. + * If `last`, only the exponent of the last tick is shown. + * If `none`, no exponents appear. + */ + showexponent: 'all' | 'first' | 'last' | 'none'; + /** + * Determines a formatting rule for the tick exponents. + * For example, consider the number 1,000,000,000. + * If `none`, it appears as *1,000,000,000*. + * If `e`, *1e+9*. + * If `E`, *1E+9*. + * If `power`, *1x10^9* (with 9 in a super script). + * If `SI`, *1G*. + * If `B`, *1B*. + */ + exponentformat: 'none' | 'e' | 'E' | 'power' | 'SI' | 'B'; + /** + * Hide SI prefix for 10^n if |n| is below this number. This only has an effect when `tickformat` is "SI" or "B". + */ + minexponent: number; + /** + * 'If `true`, even 4-digit integers are separated + */ + separatethousands: boolean; + /** + * Sets the tick label formatting rule using d3 formatting mini-languages + * which are very similar to those in Python. + * For numbers, see: https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3_format + * And for dates see: https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format + * We add one item to d3's date formatter: `%{n}f` for fractional seconds with n digits. + * For example, `"2016-10-13 09:15:23.456"` with tickformat `"%H~%M~%S.%2f"` would display `"09~15~23.46"` + */ + tickformat: string; + /** + * Sets the hover text formatting rule using d3 formatting mini-languages + * which are very similar to those in Python. + * For numbers, see: https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3_format + * And for dates see: https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format + * We add one item to d3's date formatter: `%{n}f` for fractional seconds with n digits. + * For example, `"2016-10-13 09:15:23.456"` with tickformat `"%H~%M~%S.%2f"` would display "09~15~23.46" + */ + hoverformat: string; + calendar: Calendar; + /** + * Array of `Partial` objects. + */ + tickformatstops: Array>; + spikedash: string; + /** + * Determines the drawing mode for the spike line. + * If `toaxis`, the line is drawn from the data point to the axis the + * series is plotted on. + * If `across`, the line is drawn across the entire plot area, and + * supercedes *toaxis*. + * If `marker`, then a marker dot is drawn on the axis the series is + * plotted on + */ + spikemode: + | 'toaxis' + | 'across' + | 'marker' + | 'toaxis+across' + | 'toaxis+across+marker' + | 'across+marker' + | 'toaxis+marker'; + /** + * Determines whether spikelines are stuck to the cursor or to the closest datapoints. + */ + spikesnap: 'data' | 'cursor' | 'hovered data'; + + /** + * Lines and Grids + */ + + /** + * Determines whether or not a line bounding this axis is drawn. + */ + showline: boolean; + /** + * Sets the axis line color + */ + linecolor: Color; + /** + * Sets the width (in px) of the axis line. + */ + linewidth: number; + /** + * Determines whether or not grid lines are drawn. + * If `true`, the grid lines are drawn at every tick mark. + */ + showgrid: boolean; + /** + * Sets the color of the grid lines. + */ + gridcolor: Color; + /** + * Sets the width (in px) of the grid lines. + */ + gridwidth: number; + /** + * Determines whether or not a line is drawn at along the 0 value + * of this axis. + * If `true`, the zero line is drawn on top of the grid lines. + */ + zeroline: boolean; + /** + * Sets the line color of the zero line. + */ + zerolinecolor: Color; + /** + * Sets the width (in px) of the zero line. + */ + zerolinewidth: number; + /** + * Determines whether or not a dividers are drawn + * between the category levels of this axis. + * Only has an effect on *multicategory* axes. + */ + showdividers: boolean; + /** + * Sets the color of the dividers + * Only has an effect on *multicategory* axes. + */ + dividercolor: Color; + /** + * Sets the width (in px) of the dividers + * Only has an effect on *multicategory* axes. + */ + dividerwidth: number; +} + +export type Calendar = + | 'gregorian' + | 'chinese' + | 'coptic' + | 'discworld' + | 'ethiopian' + | 'hebrew' + | 'islamic' + | 'julian' + | 'mayan' + | 'nanakshahi' + | 'nepali' + | 'persian' + | 'jalali' + | 'taiwan' + | 'thai' + | 'ummalqura'; + +export type XAxisName = 'x' | 'x2' | 'x3' | 'x4' | 'x5' | 'x6' | 'x7' | 'x8' | 'x9' | 'x10' | 'x11'; +export type YAxisName = 'y' | 'y2' | 'y3' | 'y4' | 'y5' | 'y6' | 'y7' | 'y8' | 'y9' | 'y10' | 'y11'; +export type AxisName = XAxisName | YAxisName; + +export interface LayoutAxis extends Axis { + fixedrange: boolean; + scaleanchor: AxisName; + scaleratio: number; + constrain: 'range' | 'domain'; + constraintoward: 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom'; + anchor: 'free' | AxisName; + side: 'top' | 'bottom' | 'left' | 'right' | 'clockwise' | 'counterclockwise'; + overlaying: 'free' | AxisName; + layer: 'above traces' | 'below traces'; + domain: number[]; + position: number; + rotation: number; + direction: 'counterclockwise' | 'clockwise'; + rangeslider: Partial; + rangeselector: Partial; + automargin: boolean; + autotick: boolean; + angle: any; + griddash: Dash; + l2p: (v: Datum) => number; +} + +export interface SceneAxis extends Axis { + spikesides: boolean; + showbackground: boolean; + backgroundcolor: Color; + showaxeslabels: boolean; +} + +export interface ShapeLine { + color: string; + width: number; + dash: Dash; +} + +export interface ShapeLabel { + font: Partial; + padding: number; + text: string; + textangle: 'auto' | number; + textposition: + | 'top left' + | 'top center' + | 'top right' + | 'middle left' + | 'middle center' + | 'middle right' + | 'bottom left' + | 'bottom center' + | 'bottom right' + | 'start' + | 'middle' + | 'end'; + texttemplate: string; + xanchor: 'auto' | 'left' | 'center' | 'right'; + yanchor: 'top' | 'middle' | 'bottom'; +} + +export interface Shape { + visible: boolean; + layer: 'below' | 'above'; + type: 'rect' | 'circle' | 'line' | 'path'; + path: string; + xref: 'paper' | XAxisName; + xsizemode: 'scaled' | 'pixel'; + xanchor: number | string; + yref: 'paper' | YAxisName; + ysizemode: 'scaled' | 'pixel'; + yanchor: number | string; + x0: Datum; + y0: Datum; + x1: Datum; + y1: Datum; + fillcolor: string; + name: string; + templateitemname: string; + opacity: number; + line: Partial; + label: Partial; +} + +export interface Margin { + t: number; + b: number; + l: number; + r: number; + pad: number; +} + +export interface ModeBar { + activecolor: Color; + add: ModeBarDefaultButtons | ModeBarDefaultButtons[]; + bgcolor: Color; + color: Color; + orientation: 'v' | 'h'; + remove: ModeBarDefaultButtons | ModeBarDefaultButtons[]; + uirevision: number | string; + uid: string; +} + +export type ModeBarButtonAny = ModeBarDefaultButtons | ModeBarButton; + +export type ModeBarDefaultButtons = + | 'lasso2d' + | 'select2d' + | 'sendDataToCloud' + | 'zoom2d' + | 'pan2d' + | 'zoomIn2d' + | 'zoomOut2d' + | 'autoScale2d' + | 'resetScale2d' + | 'hoverClosestCartesian' + | 'hoverCompareCartesian' + | 'zoom3d' + | 'pan3d' + | 'orbitRotation' + | 'tableRotation' + | 'handleDrag3d' + | 'resetCameraDefault3d' + | 'resetCameraLastSave3d' + | 'hoverClosest3d' + | 'zoomInGeo' + | 'zoomOutGeo' + | 'resetGeo' + | 'hoverClosestGeo' + | 'hoverClosestGl2d' + | 'hoverClosestPie' + | 'toggleHover' + | 'toImage' + | 'resetViews' + | 'toggleSpikelines' + | 'zoomInMapbox' + | 'zoomOutMapbox' + | 'resetViewMapbox' + | 'togglespikelines' + | 'togglehover' + | 'hovercompare' + | 'hoverclosest' + | 'v1hovermode'; + +export type ButtonClickEvent = (gd: PlotlyHTMLElement, ev: MouseEvent) => void; + +export interface Icon { + height?: number | undefined; + width?: number | undefined; + ascent?: number | undefined; + descent?: number | undefined; + name?: string | undefined; + path?: string | undefined; + svg?: string | undefined; + transform?: string | undefined; +} + +export interface ModeBarButton { + /** name / id of the buttons (for tracking) */ + name: string; + + /** + * text that appears while hovering over the button, + * enter null, false or '' for no hover text + */ + title: string; + + /** + * svg icon object associated with the button + * can be linked to Plotly.Icons to use the default plotly icons + */ + icon: string | Icon; + + /** icon positioning */ + gravity?: string | undefined; + + /** + * click handler associated with the button, a function of + * 'gd' (the main graph object) and + * 'ev' (the event object) + */ + click: ButtonClickEvent; + + /** + * attribute associated with button, + * use this with 'val' to keep track of the state + */ + attr?: string | undefined; + + /** initial 'attr' value, can be a function of gd */ + val?: any; + + /** is the button a toggle button? */ + toggle?: boolean | undefined; +} + +export interface GaugeLine { + color: Color; + width: number; +} +export interface Threshold { + line: Partial; + value: number; + thickness: number; +} + +export interface GaugeBar { + color: Color; + line: Partial; + thickness: number; +} +export interface Gauge { + shape: 'angular' | 'bullet'; + bar: Partial; + bgcolor: Color; + bordercolor: Color; + borderwidth: number; + axis: Partial; + steps: Array<{ range: number[]; color: Color }>; + threshold: Partial; +} + +export interface Delta { + reference: number; + position: 'top' | 'bottom' | 'left' | 'right'; + relative: boolean; + valueformat: string; + increasing: { + symbol: string; + color: Color; + }; + decreasing: { + symbol: string; + color: Color; + }; +} + +export interface DataTitle { + text: string; + font: Partial; + standoff: number; + position: + | 'top left' + | 'top center' + | 'top right' + | 'middle center' + | 'bottom left' + | 'bottom center' + | 'bottom right'; +} + +export interface PlotNumber { + valueformat: string; + font: Partial; + prefix: string; + suffix: string; +} + +export interface Template { + data?: { [type in PlotType]?: Array> } | undefined; + layout?: Partial | undefined; +} + +// Data + +export type Datum = string | number | Date | null; +export type TypedArray = + | Int8Array + | Uint8Array + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | Uint8ClampedArray + | Float32Array + | Float64Array; + +export interface ErrorOptions { + visible: boolean; + symmetric: boolean; + color: Color; + thickness: number; + width: number; + opacity: number; +} + +export type ErrorBar = Partial & + ( + | { + type: 'constant' | 'percent'; + value: number; + valueminus?: number | undefined; + } + | { + type: 'data'; + array: Datum[]; + arrayminus?: Datum[] | undefined; + } + ); + +export type Dash = 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot'; +export type PlotType = + | 'bar' + | 'barpolar' + | 'box' + | 'candlestick' + | 'carpet' + | 'choropleth' + | 'choroplethmapbox' + | 'cone' + | 'contour' + | 'contourcarpet' + | 'densitymapbox' + | 'funnel' + | 'funnelarea' + | 'heatmap' + | 'heatmapgl' + | 'histogram' + | 'histogram2d' + | 'histogram2dcontour' + | 'image' + | 'indicator' + | 'isosurface' + | 'mesh3d' + | 'ohlc' + | 'parcats' + | 'parcoords' + | 'pie' + | 'pointcloud' + | 'sankey' + | 'scatter' + | 'scatter3d' + | 'scattercarpet' + | 'scattergeo' + | 'scattergl' + | 'scattermapbox' + | 'scatterpolar' + | 'scatterpolargl' + | 'scatterternary' + | 'splom' + | 'streamtube' + | 'sunburst' + | 'surface' + | 'table' + | 'treemap' + | 'violin' + | 'volume' + | 'waterfall'; + +export type Data = + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial; + +export type Color = + | string + | number + | Array + | Array>; +export type ColorScale = string | string[] | Array<[number, string]>; +export type DataTransform = Partial; +export type ScatterData = PlotData; + +// Bar Scatter +export interface PlotData { + type: PlotType; + x: Datum[] | Datum[][] | TypedArray; + y: Datum[] | Datum[][] | TypedArray; + z: Datum[] | Datum[][] | Datum[][][] | TypedArray; + i: TypedArray; + j: TypedArray; + k: TypedArray; + xy: Float32Array; + error_x: ErrorBar; + error_y: ErrorBar; + xaxis: string; + yaxis: string; + text: string | string[]; + lat: Datum[]; + lon: Datum[]; + line: Partial; + 'line.color': Color; + 'line.width': number; + 'line.dash': Dash; + 'line.shape': 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv'; + 'line.smoothing': number; + 'line.simplify': boolean; + marker: Partial | Partial; + 'marker.symbol': MarkerSymbol | MarkerSymbol[]; + 'marker.color': Color; + 'marker.colorscale': ColorScale | ColorScale[]; + 'marker.opacity': number | number[]; + 'marker.size': number | number[] | number[][]; + 'marker.maxdisplayed': number; + 'marker.sizeref': number; + 'marker.sizemax': number; + 'marker.sizemin': number; + 'marker.sizemode': 'diameter' | 'area'; + 'marker.showscale': boolean; + 'marker.line': Partial; + 'marker.line.color': Color; + 'marker.line.colorscale': ColorScale | ColorScale[]; + 'marker.colorbar': {}; // TODO + 'marker.pad.t': number; + 'marker.pad.b': number; + 'marker.pad.l': number; + 'marker.pad.r': number; + mode: + | 'lines' + | 'markers' + | 'text' + | 'lines+markers' + | 'text+markers' + | 'text+lines' + | 'text+lines+markers' + | 'none' + | 'gauge' + | 'number' + | 'delta' + | 'number+delta' + | 'gauge+number' + | 'gauge+number+delta' + | 'gauge+delta'; + histfunc: 'count' | 'sum' | 'avg' | 'min' | 'max'; + histnorm: '' | 'percent' | 'probability' | 'density' | 'probability density'; + hoveron: 'points' | 'fills'; + hoverinfo: + | 'all' + | 'name' + | 'none' + | 'skip' + | 'text' + | 'x' + | 'x+text' + | 'x+name' + | 'x+y' + | 'x+y+text' + | 'x+y+name' + | 'x+y+z' + | 'x+y+z+text' + | 'x+y+z+name' + | 'y' + | 'y+name' + | 'y+x' + | 'y+text' + | 'y+x+text' + | 'y+x+name' + | 'y+z' + | 'y+z+text' + | 'y+z+name' + | 'y+x+z' + | 'y+x+z+text' + | 'y+x+z+name' + | 'z' + | 'z+x' + | 'z+x+text' + | 'z+x+name' + | 'z+y+x' + | 'z+y+x+text' + | 'z+y+x+name' + | 'z+x+y' + | 'z+x+y+text' + | 'z+x+y+name'; + hoverlabel: Partial; + hovertemplate: string | string[]; + hovertext: string | string[]; + xhoverformat: string; + yhoverformat: string; + zhoverformat: string; + texttemplate: string | string[]; + textinfo: + | 'label' + | 'label+text' + | 'label+value' + | 'label+percent' + | 'label+text+value' + | 'label+text+percent' + | 'label+value+percent' + | 'text' + | 'text+value' + | 'text+percent' + | 'text+value+percent' + | 'value' + | 'value+percent' + | 'percent' + | 'none'; + textposition: + | 'top left' + | 'top center' + | 'top right' + | 'middle left' + | 'middle center' + | 'middle right' + | 'bottom left' + | 'bottom center' + | 'bottom right' + | 'inside' + | 'outside' + | 'auto' + | 'none'; + textfont: Partial; + textangle: 'auto' | number; + insidetextanchor: 'end' | 'middle' | 'start'; + constraintext: 'inside' | 'outside' | 'both' | 'none'; + fill: 'none' | 'tozeroy' | 'tozerox' | 'tonexty' | 'tonextx' | 'toself' | 'tonext'; + fillcolor: string; + fillpattern: Partial; + showlegend: boolean; + legendgroup: string; + legendgrouptitle: { + text: string; + font?: Partial; + }; + legendrank: number; + parents: string[]; + name: string; + stackgroup: string; + groupnorm: '' | 'fraction' | 'percent'; + stackgaps: 'infer zero' | 'interpolate'; + connectgaps: boolean; + visible: boolean | 'legendonly'; + delta: Partial; + gauge: Partial; + number: Partial; + transforms: DataTransform[]; + orientation: 'v' | 'h'; + width: number | number[]; + boxmean: boolean | 'sd'; + boxpoints: 'all' | 'outliers' | 'suspectedoutliers' | false; + jitter: number; + pointpos: number; + opacity: number; + showscale: boolean; + colorscale: ColorScale; + zsmooth: 'fast' | 'best' | false; + zmin: number; + zmax: number; + ygap: number; + xgap: number; + transpose: boolean; + autobinx: boolean; + xbins: { + start: number | string; + end: number | string; + size: number | string; + }; + value: number; + values: Datum[]; + labels: Datum[]; + direction: 'clockwise' | 'counterclockwise'; + hole: number; + rotation: number; + theta: Datum[]; + r: Datum[]; + customdata: Datum[] | Datum[][]; + selectedpoints: Datum[]; + domain: Partial<{ + row: number; + column: number; + x: number[]; + y: number[]; + }>; + title: Partial; + branchvalues: 'total' | 'remainder'; + ids: string[]; + level: string; + cliponaxis: boolean; + automargin: boolean; + locationmode: 'ISO-3' | 'USA-states' | 'country names' | 'geojson-id'; + locations: Datum[]; + reversescale: boolean; + colorbar: Partial; + offset: number; + contours: Partial<{ + coloring: 'fill' | 'heatmap' | 'lines' | 'none'; + end: number; + labelfont: Partial; + labelformat: string; + operation: + | '=' + | '<' + | '>=' + | '>' + | '<=' + | '[]' + | '()' + | '[)' + | '(]' + | '][' + | ')(' + | '](' + | ')['; + showlabels: boolean; + showlines: boolean; + size: number; + start: number; + type: 'levels' | 'constraint'; + value: number | [lowerBound: number, upperBound: number]; + }>; + autocontour: boolean; + ncontours: number; + uirevision: string | number; + uid: string; +} + +/** + * These interfaces are based on attribute descriptions in + * https://github.com/plotly/plotly.js/tree/9d6144304308fc3007f0facf2535d38ea3e9b26c/src/transforms + */ +export interface TransformStyle { + target: number | string | number[] | string[]; + value: Partial; +} + +export interface TransformAggregation { + target: string; + func?: + | 'count' + | 'sum' + | 'avg' + | 'median' + | 'mode' + | 'rms' + | 'stddev' + | 'min' + | 'max' + | 'first' + | 'last' + | undefined; + funcmode?: 'sample' | 'population' | undefined; + enabled?: boolean | undefined; +} + +export interface Transform { + type: 'aggregate' | 'filter' | 'groupby' | 'sort'; + enabled: boolean; + target: number | string | number[] | string[]; + operation: string; + aggregations: TransformAggregation[]; + preservegaps: boolean; + groups: string | number[] | string[]; + nameformat: string; + styles: TransformStyle[]; + value: any; + order: 'ascending' | 'descending'; +} + +export interface ColorBar { + thicknessmode: 'fraction' | 'pixels'; + thickness: number; + lenmode: 'fraction' | 'pixels'; + len: number; + x: number; + xanchor: 'left' | 'center' | 'right'; + xpad: number; + y: number; + yanchor: 'top' | 'middle' | 'bottom'; + ypad: number; + outlinecolor: Color; + outlinewidth: number; + bordercolor: Color; + borderwidth: Color; + bgcolor: Color; + tickmode: 'auto' | 'linear' | 'array'; + nticks: number; + tick0: number | string; + dtick: DTickValue; + tickvals: Datum[] | Datum[][] | Datum[][][] | TypedArray; + ticktext: Datum[] | Datum[][] | Datum[][][] | TypedArray; + ticks: 'outside' | 'inside' | ''; + ticklen: number; + tickwidth: number; + tickcolor: Color; + showticklabels: boolean; + tickfont: Font; + tickangle: 'auto' | number; + tickformat: string; + tickformatstops: Array>; + tickprefix: string; + showtickprefix: 'all' | 'first' | 'last' | 'none'; + ticksuffix: string; + showticksuffix: 'all' | 'first' | 'last' | 'none'; + separatethousands: boolean; + exponentformat: 'none' | 'e' | 'E' | 'power' | 'SI' | 'B'; + showexponent: 'all' | 'first' | 'last' | 'none'; + minexponent: number; + title: string; + titlefont: Font; + titleside: 'right' | 'top' | 'bottom'; + tickvalssrc: any; + ticktextsrc: any; +} + +export type MarkerSymbol = string | number | Array; + +/** + * Any combination of "x", "y", "z", "text", "name" joined with a "+" OR "all" or "none" or "skip". + * examples: "x", "y", "x+y", "x+y+z", "all" + * default: "all" + */ +export interface PlotMarker { + symbol: MarkerSymbol; + color?: Color | Color[] | undefined; + colors?: Color[] | undefined; + colorscale?: ColorScale | undefined; + cauto?: boolean | undefined; + cmax?: number | undefined; + cmin?: number | undefined; + autocolorscale?: boolean | undefined; + reversescale?: boolean | undefined; + opacity: number | number[]; + size: number | number[]; + maxdisplayed?: number | undefined; + sizeref?: number | undefined; + sizemax?: number | undefined; + sizemin?: number | undefined; + sizemode?: 'diameter' | 'area' | undefined; + showscale?: boolean | undefined; + line: Partial; + pad?: Partial | undefined; + width?: number | undefined; + colorbar?: Partial | undefined; + gradient?: + | { + type: 'radial' | 'horizontal' | 'vertical' | 'none'; + color: Color; + typesrc: any; + colorsrc: any; + } + | undefined; + pattern?: Partial; +} + +export type ScatterMarker = PlotMarker; + +export interface ScatterMarkerLine { + width: number | number[]; + color: Color; + cauto?: boolean | undefined; + cmax?: number | undefined; + cmin?: number | undefined; + cmid?: number | undefined; + colorscale?: ColorScale | undefined; + autocolorscale?: boolean | undefined; + reversescale?: boolean | undefined; + coloraxis?: string | undefined; +} + +export interface ScatterLine { + color: Color; + width: number; + dash: Dash; + shape: 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv'; + smoothing: number; + simplify: boolean; +} + +export interface Font { + /** + * HTML font family - the typeface that will be applied by the web browser. + * The web browser will only be able to apply a font if it is available on the system + * which it operates. Provide multiple font families, separated by commas, to indicate + * the preference in which to apply fonts if they aren't available on the system. + * The plotly service (at https://plot.ly or on-premise) generates images on a server, + * where only a select number of fonts are installed and supported. + * These include *Arial*, *Balto*, *Courier New*, *Droid Sans*, *Droid Serif*, + * *Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*, + * *PT Sans Narrow*, *Raleway*, *Times New Roman*. + * @default "Arial, sans-serif" + */ + family: string; + /** + * number greater than or equal to 1 + * @default 13 + */ + size: number; + color: Color; +} + +export interface Edits { + annotationPosition: boolean; + annotationTail: boolean; + annotationText: boolean; + axisTitleText: boolean; + colorbarPosition: boolean; + colorbarTitleText: boolean; + legendPosition: boolean; + legendText: boolean; + shapePosition: boolean; + titleText: boolean; +} + +export interface Config { + /** override the defaults for the toImageButton */ + toImageButtonOptions: Partial<{ + filename: string; + scale: number; + format: 'png' | 'svg' | 'jpeg' | 'webp'; + height: number; + width: number; + }>; + + /** no interactivity, for export or image generation */ + staticPlot: boolean; + + /** + * Determines whether math should be typeset or not, + * when MathJax (either v2 or v3) is present on the page. + */ + typesetMath: boolean; + + /** + * When set it determines base URL for the 'Edit in Chart Studio' `showEditInChartStudio`/`showSendToCloud` mode bar button and the showLink/sendData on-graph link. + * To enable sending your data to Chart Studio Cloud, you need to set both `plotlyServerURL` to 'https://chart-studio.plotly.com' and also set `showSendToCloud` to true. + * @default '' + */ + plotlyServerURL: string; + + /** we can edit titles, move annotations, etc */ + editable: boolean; + edits: Partial; + + /** DO autosize once regardless of layout.autosize (use default width or height values otherwise) */ + autosizable: boolean; + + /** set the length of the undo/redo queue */ + queueLength: number; + + /** if we DO autosize, do we fill the container or the screen? */ + fillFrame: boolean; + + /** if we DO autosize, set the frame margins in percents of plot size */ + frameMargins: number; + + /** mousewheel or two-finger scroll zooms the plot */ + scrollZoom: boolean; + + /** double click interaction (false, 'reset', 'autosize' or 'reset+autosize') */ + doubleClick: 'reset+autosize' | 'reset' | 'autosize' | false; + + /** sets the delay for registering a double-click in ms */ + doubleClickDelay: number; + + /** new users see some hints about interactivity */ + showTips: boolean; + + /** enable axis pan/zoom drag handles */ + showAxisDragHandles: boolean; + + /** enable direct range entry at the pan/zoom drag points (drag handles must be enabled above) */ + showAxisRangeEntryBoxes: boolean; + + /** link to open this plot in plotly */ + showLink: boolean; + + /** if we show a link, does it contain data or just link to a plotly file? */ + sendData: boolean; + + /** text appearing in the sendData link */ + linkText: string; + + /** false or function adding source(s) to linkText */ + showSources: boolean; + + /** display the mode bar (true, false, or 'hover') */ + displayModeBar: 'hover' | boolean; + + /** + * Should we include a ModeBar button, labeled "Edit in Chart Studio", + * that sends this chart to chart-studio.plotly.com (formerly plot.ly) + * or another plotly server as specified by `plotlyServerURL` for editing, export, etc? + * Prior to version 1.43.0 this button was included by default, now it is opt-in using this flag. + * Note that this button can (depending on `plotlyServerURL` being set) send your data to an external server. + * However that server does not persist your data until you arrive at the Chart Studio and explicitly click "Save". + * @default false + */ + showSendToCloud: boolean; + + /** + * Same as `showSendToCloud`, but use a pencil icon instead of a floppy-disk. + * Note that if both `showSendToCloud` and `showEditInChartStudio` are turned, only `showEditInChartStudio` will be honored. + * @default false + */ + showEditInChartStudio: boolean; + + /** remove mode bar button by name (see ./components/modebar/buttons.js for the list of names) */ + modeBarButtonsToRemove: ModeBarDefaultButtons[]; + + /** add mode bar button using config objects (see ./components/modebar/buttons.js for list of arguments) */ + modeBarButtonsToAdd: ModeBarButtonAny[]; + + /** + * fully custom mode bar buttons as nested array, where the outer + * arrays represents button groups, and the inner arrays have + * buttons config objects or names of default buttons + * (see ./components/modebar/buttons.js for more info) + */ + modeBarButtons: ModeBarButtonAny[][] | false; + + /** add the plotly logo on the end of the mode bar */ + displaylogo: boolean; + + /** increase the pixel ratio for Gl plot images */ + plotGlPixelRatio: number; + + /** + * function to add the background color to a different container + * or 'opaque' to ensure there's white behind it + */ + setBackground: ((gd: PlotlyHTMLElement, bgColor: string) => void) | 'opaque' | 'transparent'; + + /** URL to topojson files used in geo charts */ + topojsonURL: string; + + /** + * Mapbox access token (required to plot mapbox trace types) + * If using an Mapbox Atlas server, set this option to '', + * so that plotly.js won't attempt to authenticate to the public Mapbox server. + */ + mapboxAccessToken: string; + + /** + * Turn all console logging on or off (errors will be thrown) + * This should ONLY be set via Plotly.setPlotConfig + */ + logging: boolean | 0 | 1 | 2; + + /** Set global transform to be applied to all traces with no specification needed */ + globalTransforms: any[]; + + /** Which localization should we use? Should be a string like 'en' or 'en-US' */ + locale: string; + + /** + * Localization definitions + * Locales can be provided either here (specific to one chart) or globally + * by registering them as modules. + * Should be an object of objects {locale: {dictionary: {...}, format: {...}}} + * { + * da: { + * dictionary: {'Reset axes': 'Nulstil aksler', ...}, + * format: {months: [...], shortMonths: [...]} + * }, + * ... + * } + * All parts are optional. When looking for translation or format fields, we + * look first for an exact match in a config locale, then in a registered + * module. If those fail, we strip off any regionalization ('en-US' -> 'en') + * and try each (config, registry) again. The final fallback for translation + * is untranslated (which is US English) and for formats is the base English + * (the only consequence being the last fallback date format %x is DD/MM/YYYY + * instead of MM/DD/YYYY). Currently `grouping` and `currency` are ignored + * for our automatic number formatting, but can be used in custom formats. + */ + locales: {}; + + /** Make the chart responsive to window size */ + responsive: boolean; + + /** Watermark the images with the company's logo */ + watermark: boolean; +} + +// Components + +export interface RangeSlider { + visible: boolean; + thickness: number; + range: [Datum, Datum]; + borderwidth: number; + bordercolor: string; + bgcolor: string; +} + +export interface RangeSelectorButton { + step: 'second' | 'minute' | 'hour' | 'day' | 'month' | 'year' | 'all'; + stepmode: 'backward' | 'todate'; + count: number; + label: string; +} + +export interface RangeSelector extends Label { + buttons: Array>; + visible: boolean; + x: number; + xanchor: 'auto' | 'left' | 'center' | 'right'; + y: number; + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + activecolor: string; + borderwidth: number; +} + +export interface Camera { + up: Partial; + center: Partial; + eye: Partial; +} + +export interface Label { + /** Sets the background color of all hover labels on graph. */ + bgcolor: string; + + /** Sets the border color of all hover labels on graph. */ + bordercolor: string; + + /** Sets the default hover label font used by all traces on the graph. */ + font: Partial; +} + +export interface LegendTitle { + font: Partial; + side: 'top' | 'left' | 'top left'; + text: string; +} + +export interface HoverLabel extends Label { + /** + * Sets the horizontal alignment of the text content within hover label box. + * @default "auto" + */ + align: 'left' | 'right' | 'auto'; + + /** + * Sets the default length (in number of characters) of the trace name + * in the hover labels for all traces. + * -1 shows the whole name regardless of length. + * @default 15 + */ + namelength: number; +} + +export interface Annotations extends Label { + /** Determines whether or not this annotation is visible. */ + visible: boolean; + + /** + * Sets the text associated with this annotation. + * Plotly uses a subset of HTML tags to do things like + * newline (
), bold (), italics (), + * hyperlinks (). Tags , , + * are also supported. + */ + text: string; + + /** Sets the angle at which the `text` is drawn with respect to the horizontal. */ + textangle: string; + + /** + * Sets an explicit width for the text box. null (default) lets the + * text set the box width. Wider text will be clipped. + * There is no automatic wrapping; use
to start a new line. + */ + width: number; + + /** + * Sets an explicit height for the text box. null (default) lets the + * text set the box height. Taller text will be clipped. + */ + height: number; + + /** Sets the opacity of the annotation (text + arrow). */ + opacity: number; + + /** + * Sets the horizontal alignment of the `text` within the box. + * Has an effect only if `text` spans more two or more lines + * (i.e. `text` contains one or more
HTML tags) or if an + * explicit width is set to override the text width. + */ + align: 'left' | 'center' | 'right'; + + /** + * Sets the vertical alignment of the `text` within the box. + * Has an effect only if an explicit height is set to override the text height. + */ + valign: 'top' | 'middle' | 'bottom'; + + /** Sets the padding (in px) between the `text` and the enclosing border. */ + borderpad: number; + + /** Sets the width (in px) of the border enclosing the annotation `text`. */ + borderwidth: number; + + /** + * Determines whether or not the annotation is drawn with an arrow. + * If *true*, `text` is placed near the arrow's tail. + * If *false*, `text` lines up with the `x` and `y` provided. + */ + showarrow: boolean; + + /** Sets the color of the annotation arrow. */ + arrowcolor: string; + + /** Sets the end annotation arrow head style. */ + arrowhead: number; + + /** Sets the start annotation arrow head style. */ + startarrowhead: number; + + /** Sets the annotation arrow head position. */ + arrowside: 'end' | 'start'; + + /** + * Sets the size of the end annotation arrow head, relative to `arrowwidth`. + * A value of 1 (default) gives a head about 3x as wide as the line. + */ + arrowsize: number; + + /** + * Sets the size of the start annotation arrow head, relative to `arrowwidth`. + * A value of 1 (default) gives a head about 3x as wide as the line. + */ + startarrowsize: number; + + /** Sets the width (in px) of annotation arrow line. */ + arrowwidth: number; + + /** + * Sets a distance, in pixels, to move the end arrowhead away from the + * position it is pointing at, for example to point at the edge of + * a marker independent of zoom. Note that this shortens the arrow + * from the `ax` / `ay` vector, in contrast to `xshift` / `yshift` + * which moves everything by this amount. + */ + standoff: number; + + /** + * Sets a distance, in pixels, to move the start arrowhead away from the + * position it is pointing at, for example to point at the edge of + * a marker independent of zoom. Note that this shortens the arrow + * from the `ax` / `ay` vector, in contrast to `xshift` / `yshift` + * which moves everything by this amount. + */ + startstandoff: number; + + /** + * Sets the x component of the arrow tail about the arrow head. + * If `axref` is `pixel`, a positive (negative) + * component corresponds to an arrow pointing + * from right to left (left to right). + * If `axref` is an axis, this is an absolute value on that axis, + * like `x`, NOT a relative value. + */ + ax: number; + + /** + * Sets the y component of the arrow tail about the arrow head. + * If `ayref` is `pixel`, a positive (negative) + * component corresponds to an arrow pointing + * from bottom to top (top to bottom). + * If `ayref` is an axis, this is an absolute value on that axis, + * like `y`, NOT a relative value. + */ + ay: number; + + /** + * Indicates in what terms the tail of the annotation (ax,ay) + * is specified. If `pixel`, `ax` is a relative offset in pixels + * from `x`. If set to an x axis id (e.g. *x* or *x2*), `ax` is + * specified in the same terms as that axis. This is useful + * for trendline annotations which should continue to indicate + * the correct trend when zoomed. + */ + axref: 'pixel' | XAxisName; + + /** + * Indicates in what terms the tail of the annotation (ax,ay) + * is specified. If `pixel`, `ay` is a relative offset in pixels + * from `y`. If set to a y axis id (e.g. *y* or *y2*), `ay` is + * specified in the same terms as that axis. This is useful + * for trendline annotations which should continue to indicate + * the correct trend when zoomed. + */ + ayref: 'pixel' | YAxisName; + + /** + * Sets the annotation's x coordinate axis. + * If set to an x axis id (e.g. *x* or *x2*), the `x` position refers to an x coordinate + * If set to *paper*, the `x` position refers to the distance from + * the left side of the plotting area in normalized coordinates + * where 0 (1) corresponds to the left (right) side. + */ + xref: 'paper' | XAxisName; + + /** + * Sets the annotation's x position. + * If the axis `type` is *log*, then you must take the log of your desired range. + * If the axis `type` is *date*, it should be date strings, like date data, + * though Date objects and unix milliseconds will be accepted and converted to strings. + * If the axis `type` is *category*, it should be numbers, using the scale where each + * category is assigned a serial number from zero in the order it appears. + */ + x: number | string; + + /** + * Sets the text box's horizontal position anchor + * This anchor binds the `x` position to the *left*, *center* or *right* of the annotation. + * For example, if `x` is set to 1, `xref` to *paper* and `xanchor` to *right* then the + * right-most portion of the annotation lines up with the right-most edge of the plotting area. + * If *auto*, the anchor is equivalent to *center* for data-referenced annotations or if there + * is an arrow, whereas for paper-referenced with no arrow, the anchor picked corresponds to the closest side. + */ + xanchor: 'auto' | 'left' | 'center' | 'right'; + + /** + * Shifts the position of the whole annotation and arrow to the + * right (positive) or left (negative) by this many pixels. + */ + xshift: number; + + /** + * Sets the annotation's y coordinate axis. + * If set to an y axis id (e.g. *y* or *y2*), the `y` position refers to an y coordinate + * If set to *paper*, the `y` position refers to the distance from + * the bottom of the plotting area in normalized coordinates + * where 0 (1) corresponds to the bottom (top). + */ + yref: 'paper' | YAxisName; + + /** + * Sets the annotation's y position. + * If the axis `type` is *log*, then you must take the log of your desired range. + * If the axis `type` is *date*, it should be date strings, like date data, + * though Date objects and unix milliseconds will be accepted and converted to strings. + * If the axis `type` is *category*, it should be numbers, using the scale where each + * category is assigned a serial number from zero in the order it appears. + */ + y: number | string; + + /** + * Sets the text box's vertical position anchor + * This anchor binds the `y` position to the *top*, *middle* or *bottom* of the annotation. + * For example, if `y` is set to 1, `yref` to *paper* and `yanchor` to *top* then the + * top-most portion of the annotation lines up with the top-most edge of the plotting area. + * If *auto*, the anchor is equivalent to *middle* for data-referenced annotations or if + * there is an arrow, whereas for paper-referenced with no arrow, the anchor picked + * corresponds to the closest side. + */ + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + + /** + * Shifts the position of the whole annotation and arrow up + * (positive) or down (negative) by this many pixels. + */ + yshift: number; + + /** + * Makes this annotation respond to clicks on the plot. + * If you click a data point that exactly matches the `x` and `y` values of this annotation, + * and it is hidden (visible: false), it will appear. In *onoff* mode, you must click the same + * point again to make it disappear, so if you click multiple points, you can show multiple + * annotations. In *onout* mode, a click anywhere else in the plot (on another data point or not) + * will hide this annotation. If you need to show/hide this annotation in response to different + * `x` or `y` values, you can set `xclick` and/or `yclick`. This is useful for example to label + * the side of a bar. To label markers though, `standoff` is preferred over `xclick` and `yclick`. + */ + clicktoshow: false | 'onoff' | 'onout'; + + /** + * Toggle this annotation when clicking a data point whose `x` value + * is `xclick` rather than the annotation's `x` value. + */ + xclick: any; + + /** + * Toggle this annotation when clicking a data point whose `y` value + * is `yclick` rather than the annotation's `y` value. + */ + yclick: any; + + /** + * Sets text to appear when hovering over this annotation. + * If omitted or blank, no hover label will appear. + */ + hovertext: string; + + hoverlabel: Partial; + + /** + * Determines whether the annotation text box captures mouse move and click events, + * or allows those events to pass through to data points in the plot that may be + * behind the annotation. By default `captureevents` is *false* unless `hovertext` + * is provided. If you use the event `plotly_clickannotation` without `hovertext` + * you must explicitly enable `captureevents`. + */ + captureevents: boolean; +} + +export interface Image { + visible: boolean; + source: string; + layer: 'above' | 'below'; + sizex: number; + sizey: number; + sizing: 'fill' | 'contain' | 'stretch'; + opacity: number; + x: number | string; + y: number | string; + xanchor: 'left' | 'center' | 'right'; + yanchor: 'top' | 'middle' | 'bottom'; + xref: 'paper' | XAxisName; + yref: 'paper' | YAxisName; +} + +export interface Scene { + bgcolor: string; + camera: Partial; + domain: Partial; + aspectmode: 'auto' | 'cube' | 'data' | 'manual'; + aspectratio: Partial; + xaxis: Partial; + yaxis: Partial; + zaxis: Partial; + dragmode: 'orbit' | 'turntable' | 'zoom' | 'pan' | false; + hovermode: 'closest' | false; + annotations: Partial | Array>; + captureevents: boolean; +} + +export interface Domain { + x: number[]; + y: number[]; + row: number; + column: number; +} + +export interface Frame { + /** + * An identifier that specifies the group to which the frame belongs, + * used by animate to select a subset of frames. + */ + group: string; + /** + * A label by which to identify the frame + */ + name: string; + /** + * A list of trace indices that identify the respective traces in the + * data attribute + */ + traces: number[]; + /** + * The name of the frame into which this frame's properties are merged + * before applying. This is used to unify properties and avoid needing + * to specify the same values for the same properties in multiple frames. + */ + baseframe: string; + /** + * A list of traces this frame modifies. The format is identical to the + * normal trace definition. + */ + data: Data[]; + /** + * Layout properties which this frame modifies. The format is identical + * to the normal layout definition. + */ + layout: Partial; +} + +export interface Transition { + /** + * Sets the duration of the slider transition + */ + duration: number; + /** + * Sets the easing function of the slider transition + */ + easing: + | 'linear' + | 'quad' + | 'cubic' + | 'sin' + | 'exp' + | 'circle' + | 'elastic' + | 'back' + | 'bounce' + | 'linear-in' + | 'quad-in' + | 'cubic-in' + | 'sin-in' + | 'exp-in' + | 'circle-in' + | 'elastic-in' + | 'back-in' + | 'bounce-in' + | 'linear-out' + | 'quad-out' + | 'cubic-out' + | 'sin-out' + | 'exp-out' + | 'circle-out' + | 'elastic-out' + | 'back-out' + | 'bounce-out' + | 'linear-in-out' + | 'quad-in-out' + | 'cubic-in-out' + | 'sin-in-out' + | 'exp-in-out' + | 'circle-in-out' + | 'elastic-in-out' + | 'back-in-out' + | 'bounce-in-out'; + /** + * Determines whether the figure's layout or traces smoothly transitions during updates that make both traces + * and layout change. Default is "layout first". + */ + ordering?: 'layout first' | 'traces first' | undefined; +} + +export interface SliderStep { + /** + * Determines whether or not this step is included in the slider. + */ + visible: boolean; + /** + * Sets the Plotly method to be called when the slider value is changed. + * If the `skip` method is used, the API slider will function as normal + * but will perform no API calls and will not bind automatically to state + * updates. This may be used to create a component interface and attach to + * slider events manually via JavaScript. + */ + method: 'animate' | 'relayout' | 'restyle' | 'skip' | 'update'; + /** + * Sets the arguments values to be passed to the Plotly + * method set in `method` on slide. + */ + args: any[]; + /** + * Sets the text label to appear on the slider + */ + label: string; + /** + * Sets the value of the slider step, used to refer to the step programatically. + * Defaults to the slider label if not provided. + */ + value: string; + /** + * When true, the API method is executed. When false, all other behaviors are the same + * and command execution is skipped. This may be useful when hooking into, for example, + * the `plotly_sliderchange` method and executing the API command manually without losing + * the benefit of the slider automatically binding to the state of the plot through the + * specification of `method` and `args`. + */ + execute: boolean; +} + +export interface Padding { + /** + * The amount of padding (in px) along the top of the component. + */ + t: number; + /** + * The amount of padding (in px) on the right side of the component. + */ + r: number; + /** + * The amount of padding (in px) along the bottom of the component. + */ + b: number; + /** + * The amount of padding (in px) on the left side of the component. + */ + l: number; + editType: 'arraydraw'; +} + +export interface Slider { + /** + * Determines whether or not the slider is visible. + */ + visible: boolean; + /** + * Determines which button (by index starting from 0) is + * considered active. + */ + active: number; + steps: Array>; + /** + * Determines whether this slider length + * is set in units of plot *fraction* or in *pixels. + * Use `len` to set the value. + */ + lenmode: 'fraction' | 'pixels'; + /** + * Sets the length of the slider + * This measure excludes the padding of both ends. + * That is, the slider's length is this length minus the + * padding on both ends. + */ + len: number; + /** + * Sets the x position (in normalized coordinates) of the slider. + */ + x: number; + /** + * Sets the y position (in normalized coordinates) of the slider. + */ + y: number; + /** + * Set the padding of the slider component along each side. + */ + pad: Partial; + /** + * Sets the slider's horizontal position anchor. + * This anchor binds the `x` position to the *left*, *center* + * or *right* of the range selector. + */ + xanchor: 'auto' | 'left' | 'center' | 'right'; + /** + * Sets the slider's vertical position anchor + * This anchor binds the `y` position to the *top*, *middle* + * or *bottom* of the range selector. + */ + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + transition: Transition; + currentvalue: Partial; + /** + * Sets the font of the slider step labels. + */ + font: Font; + /** + * Sets the background color of the slider grip + * while dragging. + */ + activebgcolor: Color; + /** + * Sets the background color of the slider. + */ + bgcolor: Color; + /** + * Sets the color of the border enclosing the slider. + */ + bordercolor: Color; + /** + * Sets the width (in px) of the border enclosing the slider. + */ + borderwidth: number; + /** + * Sets the length in pixels of step tick marks + */ + ticklen: number; + /** + * Sets the color of the border enclosing the slider. + */ + tickcolor: Color; + /** + * Sets the tick width (in px). + */ + tickwidth: number; + /** + * Sets the length in pixels of minor step tick marks + */ + minorticklen: number; +} + +export interface CurrentValue { + /** + * Shows the currently-selected value above the slider. + */ + visible: boolean; + /** + * The alignment of the value readout relative to the length of the slider. + */ + xanchor: 'left' | 'center' | 'right'; + /** + * The amount of space, in pixels, between the current value label + * and the slider. + */ + offset: number; + /** + * When currentvalue.visible is true, this sets the prefix of the label. + */ + prefix: string; + /** + * When currentvalue.visible is true, this sets the suffix of the label. + */ + suffix: string; + /** + * Sets the font of the current value label text. + */ + font: Partial; +} + +/** + * 'Sets the pattern within the marker. + */ +export interface Pattern { + /** + * Sets the shape of the pattern fill. + * By default, no pattern is used for filling the area. + */ + shape?: '' | '/' | '\\' | 'x' | '-' | '|' | '+' | '.'; + /** + * Determines whether `marker.color` should be used + * as a default to `bgcolor` or a `fgcolor`. + */ + fillmode?: 'replace' | 'overlay'; + /** + * When there is no colorscale sets the color of background pattern fill. + * Defaults to a `marker.color` background when `fillmode` is *overlay*. + * Otherwise, defaults to a transparent background. + */ + bgcolor?: string; + /** + * When there is no colorscale sets the color of foreground pattern fill. + * Defaults to a `marker.color` background when `fillmode` is *replace*. + * Otherwise, defaults to dark grey or white + * to increase contrast with the `bgcolor`. + */ + fgcolor?: string; + /** + * Sets the opacity of the foreground pattern fill. + * Defaults to a 0.5 when `fillmode` is *overlay*. + * Otherwise, defaults to 1. + */ + fgopacity?: string; + /** + * Sets the size of unit squares of the pattern fill in pixels, + * which corresponds to the interval of repetition of the pattern. + */ + size?: number; + /** + * Sets the solidity of the pattern fill. + * Solidity is roughly the fraction of the area filled by the pattern. + * Solidity of 0 shows only the background color without pattern + * and solidty of 1 shows only the foreground color without pattern. + */ + solidity?: number; +} + +export interface UpdateMenuButton { + /** + * Sets the arguments values to be passed to the Plotly method set in `method` on click. + */ + args: any[]; + /** + * Sets a 2nd set of `args`, these arguments values are passed to the Plotly method set in + * method` when clicking this button while in the active state. Use this to create + * toggle buttons. + */ + args2: any[]; + /** + * When true, the API method is executed. When false, all other behaviors are + * the same and command execution is skipped. This may be useful when hooking + * into, for example, the `plotly_buttonclicked` method and executing the API + * command manually without losing the benefit of the updatemenu automatically + * binding to the state of the plot through the specification of `method` + * and `args`. + */ + execute: boolean; + /** + * Sets the text label to appear on the button. + */ + label: string; + /** + * Sets the Plotly method to be called on click. If the `skip` method is + * used, the API updatemenu will function as normal but will perform no + * API calls and will not bind automatically to state updates. This may be + * used to create a component interface and attach to updatemenu events + * manually via JavaScript. + */ + method: 'restyle' | 'relayout' | 'animate' | 'update' | 'skip'; + /** + * When used in a template, named items are created in the output figure in + * addition to any items the figure already has in this array. You can modify + * these items in the output figure by making your own item with + * `templateitemname` matching this `name` alongside your modifications + * (including `visible: false` or `enabled: false` to hide it). Has no effect + * outside of a template. + */ + name: string; + /** + * Used to refer to a named item in this array in the template. Named items + * from the template will be created even without a matching item in the + * input figure, but you can modify one by making an item with + * `templateitemname` matching its `name`, alongside your modifications + * (including `visible: false` or `enabled: false` to hide it). If there is + * no template or no matching item, this item will be hidden unless you + * explicitly show it with `visible: true`. + */ + templateitemname: string; + /** + * Determines whether or not this button is visible. + */ + visible: boolean; +} + +export interface UpdateMenu { + /** + * Determines which button (by index starting from 0) is considered active. + */ + active?: number; + /** + * Sets the background color of the update menu buttons. + */ + bgcolor?: Color; + /** + * Sets the color of the border enclosing the update menu. + */ + bordercolor?: Color; + /** + * Sets the width (in px) of the border enclosing the update menu. + */ + borderwidth: number; + /** + * array of object where each object has one or more of the keys listed below. + */ + buttons: Array>; + /** + * Determines the direction in which the buttons are laid out, whether + * in a dropdown menu or a row/column of buttons. For `left` and `up`, + * the buttons will still appear in left-to-right or top-to-bottom order + * respectively. + */ + direction: 'left' | 'up' | 'right' | 'down'; + /** + * Sets the font of the update menu button text. + */ + font: Partial; + /** + * When used in a template, named items are created in the output + * figure in addition to any items the figure already has in this array. + * You can modify these items in the output figure by making your own item + * with `templateitemname` matching this `name` alongside your modifications + * (including `visible: false` or `enabled: false` to hide it). Has no + * effect outside of a template. + */ + name: string; + /** + * Sets the padding around the buttons or dropdown menu. + */ + pad: Partial; + /** + * Highlights active dropdown item or active button if true. + */ + showactive: boolean; + /** + * Used to refer to a named item in this array in the template. Named + * items from the template will be created even without a matching item + * in the input figure, but you can modify one by making an item with + * `templateitemname` matching its `name`, alongside your modifications + * (including `visible: false` or `enabled: false` to hide it). If there + * is no template or no matching item, this item will be hidden unless + * you explicitly show it with `visible: true`. + */ + templateitemname: string; + /** + * Determines whether the buttons are accessible via a dropdown menu or + * whether the buttons are stacked horizontally or vertically + */ + type: 'dropdown' | 'buttons'; + /** + * Determines whether or not the update menu is visible. + */ + visible: boolean; + /** + * Sets the x position (in normalized coordinates) of the update menu. + */ + x: number; + /** + * Sets the update menu's horizontal position anchor. This anchor binds + * the `x` position to the "left", "center" or "right" of the range selector. + */ + xanchor: 'auto' | 'left' | 'center' | 'right'; + /** + * Sets the y position (in normalized coordinates) of the update menu. + */ + y: number; + /** + * Sets the update menu's vertical position anchor This anchor binds + * the `y` position to the "top", "middle" or "bottom" of the range selector. + */ + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; +} + +interface TraceModule { + moduleType: 'trace'; + name: string; + categories: string[]; + meta: Record; + [key: string]: unknown; +} + +interface LocaleModule { + moduleType: 'locale'; + name: string; + dictionary: Record; + format: Record; +} + +interface TransformModule { + moduleType: 'transform'; + name: string; + transform: any; + calcTransform: any; + attributes: Record; + supplyDefaults: any; +} + +interface ComponentModule { + moduleType: 'component'; + name: string; + [key: string]: unknown; +} + +interface ApiMethodModule { + moduleType: 'apiMethod'; + name: string; + fn: any; +} + +type PlotlyModule = + | TraceModule + | LocaleModule + | TransformModule + | ComponentModule + | ApiMethodModule; + +// Modified +interface LayoutAxis { + uirevision: string; +} diff --git a/package-lock.json b/package-lock.json index 0795b56ee95..182677600d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "plotly.js", + "name": "plotly.js-newcrom", "version": "2.27.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "plotly.js", + "name": "plotly.js-newcrom", "version": "2.27.1", "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 02c19a6d1c5..f6e8bb0adae 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { - "name": "plotly.js", + "name": "plotly.js-newcrom", "version": "2.27.1", "description": "The open source javascript graphing library that powers plotly", "license": "MIT", - "main": "./lib/index.js", - "webpack": "./dist/plotly.js", + "main": "./lib/index-newcrom.js", + "types": "./lib/index-newcrom.d.ts", + "webpack": "./lib/index-newcrom.js", "repository": { "type": "git", "url": "https://github.com/plotly/plotly.js.git" @@ -22,6 +23,7 @@ ], "scripts": { "custom-bundle": "node tasks/custom_bundle.js", + "create-newcrom-bundle": "node tasks/custom_bundle.js --unminified --out newcrom --traces scatter --transforms none", "bundle": "node tasks/bundle.js", "extra-bundles": "node tasks/extra_bundles.js", "locales": "node tasks/locales.js", @@ -62,7 +64,8 @@ "version": "npm run build && npm run no-bad-char && git add -A lib dist build src/version.js", "postversion": "node -e \"console.log('Version bumped and committed. If ok, run: git push && git push --tags')\"", "postpublish": "node tasks/sync_packages.js", - "postshrinkwrap": "chttps ." + "postshrinkwrap": "chttps .", + "prepare": "npm run create-newcrom-bundle" }, "browserify": { "transform": [ diff --git a/src/components/dragelement/index.js b/src/components/dragelement/index.js index 1f7c0e4d8d7..29489b25b69 100644 --- a/src/components/dragelement/index.js +++ b/src/components/dragelement/index.js @@ -89,6 +89,10 @@ dragElement.init = function init(options) { element.style.pointerEvents = 'all'; + if(element.classList.contains('nsewdrag')){ + window.plotlyStartZooming = onStart + } + element.onmousedown = onStart; if(!supportsPassive) { diff --git a/src/components/fx/click.js b/src/components/fx/click.js index 96a47a4dfe8..c7fdb281686 100644 --- a/src/components/fx/click.js +++ b/src/components/fx/click.js @@ -22,6 +22,6 @@ module.exports = function click(gd, evt, subplot) { } else emitClick(); // why do we get a double event without this??? - if(evt.stopImmediatePropagation) evt.stopImmediatePropagation(); + // if(evt.stopImmediatePropagation) evt.stopImmediatePropagation(); } }; diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index 26339816c75..d1c75984c93 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -23,6 +23,7 @@ var constants = require('./constants'); var helpers = require('./helpers'); var getPathString = helpers.getPathString; +var ALWAYS_EDITABLE = true; // Shapes are stored in gd.layout.shapes, an array of objects // index can point to one item in this array, @@ -177,13 +178,24 @@ function drawOne(gd, index) { } else { if(gd._context.edits.shapePosition) { setupDragElement(gd, path, options, index, shapeLayer, editHelpers); - } else if(options.editable === true) { - path.style('pointer-events', - (isOpen || Color.opacity(fillColor) * opacity <= 0.5) ? 'stroke' : 'all' - ); + } else if(ALWAYS_EDITABLE) { + path.style('pointer-events', 'all'); } } - path.node().addEventListener('click', function() { return activateShape(gd, path); }); + + if (options._input.onClick){ + path.node().addEventListener('click', options._input.onClick); + } + if (options._input.onMouseEnter){ + path.node().addEventListener('mouseenter', options._input.onMouseEnter); + } + if (options._input.onMouseLeave){ + path.node().addEventListener('mouseleave', options._input.onMouseLeave); + } + + queueMicrotask(() => { + path.node().addEventListener('mousedown', window.plotlyStartZooming) + }) } } diff --git a/src/lib/index.js b/src/lib/index.js index ebb1822d48c..67ab6bcfe86 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -199,7 +199,7 @@ lib.makeTraceGroups = require('./make_trace_groups'); lib._ = require('./localize'); -lib.notifier = require('./notifier'); +lib.notifier = () => {}; lib.filterUnique = require('./filter_unique'); lib.filterVisible = require('./filter_visible'); diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index a104e88bb11..db40c45619e 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -57,6 +57,9 @@ var numericNameWarningCountLimit = 5; * */ function _doPlot(gd, data, layout, config) { + const isForceRerender = window.isForceRerender + window.isForceRerender = false; + var frames; gd = Lib.getGraphDiv(gd); @@ -158,7 +161,7 @@ function _doPlot(gd, data, layout, config) { // generate calcdata, if we need to // to force redoing calcdata, just delete it before calling _doPlot - var recalc = !gd.calcdata || gd.calcdata.length !== (gd._fullData || []).length; + var recalc = isForceRerender || !gd.calcdata || gd.calcdata.length !== (gd._fullData || []).length; if(recalc) Plots.doCalcdata(gd); // in case it has changed, attach fullData traces to calcdata @@ -2632,7 +2635,7 @@ function applyUIRevisions(data, layout, oldFullData, oldFullLayout) { * object containing `data`, `layout`, `config`, and `frames` members * */ -function react(gd, data, layout, config) { +function react(gd, data, layout, config, isForce) { var frames, plotDone; function addFrames() { return exports.addFrames(gd, frames); } @@ -2739,8 +2742,9 @@ function react(gd, data, layout, config) { seq.push(function() { return Plots.transitionFromReact(gd, restyleFlags, relayoutFlags, oldFullLayout); }); - } else if(restyleFlags.fullReplot || relayoutFlags.layoutReplot || configChanged) { + } else if(isForce || restyleFlags.fullReplot || relayoutFlags.layoutReplot || configChanged) { gd._fullLayout._skipDefaults = true; + window.isForceRerender = true seq.push(exports._doPlot); } else { for(var componentType in relayoutFlags.arrays) { From 9d59c3c1112285b61274a629aca1b457ff0f2f84 Mon Sep 17 00:00:00 2001 From: ivankirshin Date: Wed, 6 Dec 2023 18:05:32 +0400 Subject: [PATCH 2/8] #2254: Front: Fixes for new chromatogram --- src/plots/cartesian/dragbox.js | 39 ++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index 5446277b847..814ce4f2073 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -398,24 +398,27 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { } else { noZoom(); } - } else if(!yActive || dy < Math.min(Math.max(dx * 0.6, MINDRAG), MINZOOM)) { - // look for small drags in one direction or the other, - // and only drag the other axis - - if(dx < MINDRAG || !xActive) { - noZoom(); - } else { - box.t = 0; - box.b = ph; - zoomMode = 'x'; - corners.attr('d', xCorners(box, y0)); - } - } else if(!xActive || dx < Math.min(dy * 0.6, MINZOOM)) { - box.l = 0; - box.r = pw; - zoomMode = 'y'; - corners.attr('d', yCorners(box, x0)); - } else { + } + // !!! To disable single axis scaling + // else if(!yActive || dy < Math.min(Math.max(dx * 0.6, MINDRAG), MINZOOM)) { + // // look for small drags in one direction or the other, + // // and only drag the other axis + // + // if(dx < MINDRAG || !xActive) { + // noZoom(); + // } else { + // box.t = 0; + // box.b = ph; + // zoomMode = 'x'; + // corners.attr('d', xCorners(box, y0)); + // } + // } else if(!xActive || dx < Math.min(dy * 0.6, MINZOOM)) { + // box.l = 0; + // box.r = pw; + // zoomMode = 'y'; + // corners.attr('d', yCorners(box, x0)); + // } + else { zoomMode = 'xy'; corners.attr('d', xyCorners(box)); } From fda4d7d79aa643caf6b8d0901f57d6be7efce20f Mon Sep 17 00:00:00 2001 From: ivankirshin Date: Tue, 19 Dec 2023 19:41:58 +0400 Subject: [PATCH 3/8] #2261: Front: Reset zoom when detection time is applied --- lib/index-newcrom.d.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/index-newcrom.d.ts b/lib/index-newcrom.d.ts index 4902932b9c2..df1a347ad5d 100644 --- a/lib/index-newcrom.d.ts +++ b/lib/index-newcrom.d.ts @@ -340,10 +340,12 @@ export interface PlotlyHTMLElement extends HTMLElement { */ _fullLayout: { xaxis: { - p2d(point: number): number + p2d(point: number): number; + autorange: boolean; }, yaxis: { - p2d(point: number): number + p2d(point: number): number; + autorange: boolean; }, } } From 5d93f7427d4f79c998497f55835c9921f917f31a Mon Sep 17 00:00:00 2001 From: ivankirshin Date: Fri, 5 Jan 2024 14:48:19 +0400 Subject: [PATCH 4/8] #2261: Front: Reset zoom when detection time is applied --- lib/index-newcrom.d.ts | 3 ++- package.json | 2 +- src/plot_api/plot_api.js | 20 ++++++++++++++------ src/plots/cartesian/dragbox.js | 25 +++++++++++++++---------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/lib/index-newcrom.d.ts b/lib/index-newcrom.d.ts index df1a347ad5d..8904873644b 100644 --- a/lib/index-newcrom.d.ts +++ b/lib/index-newcrom.d.ts @@ -435,7 +435,8 @@ export function react( data: Data[], layout?: Partial, config?: Partial, - isForceUpdate?: boolean + isForceUpdate?: boolean, + xAxisRange?: [x0: number, x1: number] | null ): Promise; export function addFrames(root: Root, frames: Array>): Promise; export function deleteFrames(root: Root, frames: number[]): Promise; diff --git a/package.json b/package.json index f6e8bb0adae..713f5be7d2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "plotly.js-newcrom", - "version": "2.27.1", + "version": "2.27.1-1", "description": "The open source javascript graphing library that powers plotly", "license": "MIT", "main": "./lib/index-newcrom.js", diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index db40c45619e..6e6d42a6773 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -57,8 +57,8 @@ var numericNameWarningCountLimit = 5; * */ function _doPlot(gd, data, layout, config) { - const isForceRerender = window.isForceRerender - window.isForceRerender = false; + const isForceRerender = window[`plotly-${gd.dataset.chartId}`].isForceRerender + window[`plotly-${gd.dataset.chartId}`].isForceRerender = false; var frames; @@ -330,9 +330,10 @@ function _doPlot(gd, data, layout, config) { subroutines.doAutoRangeAndConstraints(gd); + // !!! We don't need to save an initial range because we change it if we apply a detection time. // store initial ranges *after* enforcing constraints, otherwise // we will never look like we're at the initial ranges - if(graphWasEmpty) Axes.saveRangeInitial(gd); + // if(graphWasEmpty) Axes.saveRangeInitial(gd); // this one is different from shapes/annotations calcAutorange // the others incorporate those components into ax._extremes, @@ -365,7 +366,8 @@ function _doPlot(gd, data, layout, config) { gd._fullLayout._insideTickLabelsUpdaterange = undefined; return relayout(gd, insideTickLabelsUpdaterange).then(function() { - Axes.saveRangeInitial(gd, true); + // !!! We don't need to save an initial range because we change it if we apply a detection time. + // Axes.saveRangeInitial(gd, true); }); } } @@ -552,6 +554,8 @@ function redraw(gd) { }); } +const generateId = () => Math.random().toString(36).substr(2, 10); + /** * Convenience function to make idempotent plot option obvious to users. * @@ -561,7 +565,9 @@ function redraw(gd) { * @param {Object} config */ function newPlot(gd, data, layout, config) { + gd.dataset.chartId = generateId() gd = Lib.getGraphDiv(gd); + window[`plotly-${gd.dataset.chartId}`] = {} // remove gl contexts Plots.cleanPlot([], {}, gd._fullData || [], gd._fullLayout || {}); @@ -2635,7 +2641,9 @@ function applyUIRevisions(data, layout, oldFullData, oldFullLayout) { * object containing `data`, `layout`, `config`, and `frames` members * */ -function react(gd, data, layout, config, isForce) { +function react(gd, data, layout, config, isForce, xAxisRange) { + window[`plotly-${gd.dataset.chartId}`].xAxisRange = xAxisRange; + var frames, plotDone; function addFrames() { return exports.addFrames(gd, frames); } @@ -2744,7 +2752,7 @@ function react(gd, data, layout, config, isForce) { }); } else if(isForce || restyleFlags.fullReplot || relayoutFlags.layoutReplot || configChanged) { gd._fullLayout._skipDefaults = true; - window.isForceRerender = true + window[`plotly-${gd.dataset.chartId}`].isForceRerender = true seq.push(exports._doPlot); } else { for(var componentType in relayoutFlags.arrays) { diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index 5446277b847..80799d4804c 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -827,17 +827,22 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { if(!ax.fixedrange) { var axName = ax._name; - var autorangeInitial = ax._autorangeInitial; - if(ax._rangeInitial0 === undefined && ax._rangeInitial1 === undefined) { - attrs[axName + '.autorange'] = true; - } else if(ax._rangeInitial0 === undefined) { - attrs[axName + '.autorange'] = autorangeInitial; - attrs[axName + '.range'] = [null, ax._rangeInitial1]; - } else if(ax._rangeInitial1 === undefined) { - attrs[axName + '.range'] = [ax._rangeInitial0, null]; - attrs[axName + '.autorange'] = autorangeInitial; + const xAxisRange = window[`plotly-${gd.dataset.chartId}`].xAxisRange + if (xAxisRange != null && axName === 'xaxis'){ + attrs[axName + '.range'] = [...xAxisRange]; } else { - attrs[axName + '.range'] = [ax._rangeInitial0, ax._rangeInitial1]; + var autorangeInitial = ax._autorangeInitial; + if (ax._rangeInitial0 === undefined && ax._rangeInitial1 === undefined) { + attrs[axName + '.autorange'] = true; + } else if (ax._rangeInitial0 === undefined) { + attrs[axName + '.autorange'] = autorangeInitial; + attrs[axName + '.range'] = [null, ax._rangeInitial1]; + } else if (ax._rangeInitial1 === undefined) { + attrs[axName + '.range'] = [ax._rangeInitial0, null]; + attrs[axName + '.autorange'] = autorangeInitial; + } else { + attrs[axName + '.range'] = [ax._rangeInitial0, ax._rangeInitial1]; + } } } } From 58fa858f1c26e46cc976fb6687b142c31033be58 Mon Sep 17 00:00:00 2001 From: ivankirshin Date: Tue, 30 Jan 2024 14:53:57 +0400 Subject: [PATCH 5/8] #2295: Front: Prepare package for publication --- package.json | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 713f5be7d2d..13d9621c361 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,19 @@ { - "name": "plotly.js-newcrom", - "version": "2.27.1-1", - "description": "The open source javascript graphing library that powers plotly", + "name": "@newcrom/plotly.js", + "version": "0.1.7", + "description": "Forked version of plotly.js with some hacks for use in Newcrom's products. The version is based on plotly.js@2.27.1", "license": "MIT", "main": "./lib/index-newcrom.js", "types": "./lib/index-newcrom.d.ts", "webpack": "./lib/index-newcrom.js", "repository": { "type": "git", - "url": "https://github.com/plotly/plotly.js.git" + "url": "https://github.com/newcrom/plotly.js.git" }, "bugs": { - "url": "https://github.com/plotly/plotly.js/issues" + "url": "https://github.com/newcrom/plotly.js/issues" }, - "author": "Plotly, Inc.", + "author": "Newcrom", "keywords": [ "graphing", "plotting", @@ -63,7 +63,6 @@ "preversion": "check-node-version --node 16 --npm 8 && npm-link-check && npm ls --prod --all", "version": "npm run build && npm run no-bad-char && git add -A lib dist build src/version.js", "postversion": "node -e \"console.log('Version bumped and committed. If ok, run: git push && git push --tags')\"", - "postpublish": "node tasks/sync_packages.js", "postshrinkwrap": "chttps .", "prepare": "npm run create-newcrom-bundle" }, From 262c5779719422b9f246aa646d640087be8b1816 Mon Sep 17 00:00:00 2001 From: ivankirshin Date: Fri, 19 Apr 2024 12:39:51 +0400 Subject: [PATCH 6/8] #2335: Front: Chromatogram changes: new tick position and ID for defining shapes --- package.json | 2 +- src/components/shapes/draw.js | 1 + src/plots/cartesian/axes.js | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 13d9621c361..93112968c92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@newcrom/plotly.js", - "version": "0.1.7", + "version": "0.1.9", "description": "Forked version of plotly.js with some hacks for use in Newcrom's products. The version is based on plotly.js@2.27.1", "license": "MIT", "main": "./lib/index-newcrom.js", diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index d1c75984c93..76dfa60a027 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -113,6 +113,7 @@ function drawOne(gd, index) { var attrs = { 'data-index': index, 'fill-rule': options.fillrule, + 'id': options.name, d: d }; diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index dfdb0e5166d..b46a4ad19d1 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -2524,7 +2524,8 @@ axes.drawOne = function(gd, ax, opts) { var minorTickSigns = axes.getTickSigns(ax, 'minor'); if(ax.ticks || (ax.minor && ax.minor.ticks)) { - var majorTickPath = axes.makeTickPath(ax, mainLinePositionShift, majorTickSigns[2]); + // +4 shift for ticks was added + var majorTickPath = axes.makeTickPath(ax, mainLinePositionShift + 4, majorTickSigns[2]); var minorTickPath = axes.makeTickPath(ax, mainLinePositionShift, minorTickSigns[2], { minor: true }); var mirrorMajorTickPath; From 569a0bbfb9ab28104989902a14f857f3a45966a2 Mon Sep 17 00:00:00 2001 From: ivankirshin Date: Thu, 25 Apr 2024 14:36:38 +0400 Subject: [PATCH 7/8] #2344: Front: Show correct estimated gaussians --- lib/index-newcrom.d.ts | 12 ++++++++++++ package.json | 2 +- src/plot_api/index.js | 1 + src/plot_api/plot_api.js | 10 ++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/index-newcrom.d.ts b/lib/index-newcrom.d.ts index 8904873644b..4c0125eb92e 100644 --- a/lib/index-newcrom.d.ts +++ b/lib/index-newcrom.d.ts @@ -441,6 +441,18 @@ export function react( export function addFrames(root: Root, frames: Array>): Promise; export function deleteFrames(root: Root, frames: number[]): Promise; export function register(modules: PlotlyModule | PlotlyModule[]): void; +export function zoom( + gd: PlotlyHTMLElement, + zoomBounds: ZoomBounds, +): void; + +type ZoomBounds = { + x0: number; + x1: number; + y0: number; + y1: number; +}; + // Layout export interface Layout { diff --git a/package.json b/package.json index 93112968c92..d3a85aff3ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@newcrom/plotly.js", - "version": "0.1.9", + "version": "0.1.10", "description": "Forked version of plotly.js with some hacks for use in Newcrom's products. The version is based on plotly.js@2.27.1", "license": "MIT", "main": "./lib/index-newcrom.js", diff --git a/src/plot_api/index.js b/src/plot_api/index.js index 011ff30ba1c..cbd02769de7 100644 --- a/src/plot_api/index.js +++ b/src/plot_api/index.js @@ -13,6 +13,7 @@ exports._guiRelayout = main._guiRelayout; exports._guiUpdate = main._guiUpdate; exports._storeDirectGUIEdit = main._storeDirectGUIEdit; exports.react = main.react; +exports.zoom = main.zoom; exports.extendTraces = main.extendTraces; exports.prependTraces = main.prependTraces; exports.addTraces = main.addTraces; diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 6e6d42a6773..5bf829fc1ad 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -576,6 +576,15 @@ function newPlot(gd, data, layout, config) { return exports._doPlot(gd, data, layout, config); } +const zoom = (gd, {x0, x1, y0, y1}) => { + Registry.call('_guiRelayout', gd, { + "xaxis.range[0]": x0, + "xaxis.range[1]": x1, + "yaxis.range[0]": y0, + "yaxis.range[1]": y1 + }); +}; + /** * Wrap negative indicies to their positive counterparts. * @@ -3867,6 +3876,7 @@ exports.moveTraces = moveTraces; exports.prependTraces = prependTraces; exports.newPlot = newPlot; +exports.zoom = zoom; exports._doPlot = _doPlot; exports.purge = purge; From df622a5231cf77488eadcbf93379f706f973d92c Mon Sep 17 00:00:00 2001 From: ivankirshin Date: Wed, 4 Sep 2024 23:52:04 +0700 Subject: [PATCH 8/8] #2396: Front: Allow zooming if tapping on peak on mobile --- package.json | 2 +- src/components/shapes/draw.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d3a85aff3ab..5ddb7b3d98a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@newcrom/plotly.js", - "version": "0.1.10", + "version": "0.1.11", "description": "Forked version of plotly.js with some hacks for use in Newcrom's products. The version is based on plotly.js@2.27.1", "license": "MIT", "main": "./lib/index-newcrom.js", diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index 76dfa60a027..d78c3e9f869 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -196,6 +196,7 @@ function drawOne(gd, index) { queueMicrotask(() => { path.node().addEventListener('mousedown', window.plotlyStartZooming) + path.node().addEventListener('touchstart', window.plotlyStartZooming) }) } }