From 51001fd8e27081667c8291e14ab8077a76b6be49 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Fri, 2 Jan 2026 12:56:21 -0700 Subject: [PATCH 01/13] Linting/formatting --- src/components/colorscale/attributes.js | 87 +++-- src/plots/geo/layout_attributes.js | 479 ++++++++++++------------ src/plots/map/constants.js | 46 ++- src/plots/mapbox/constants.js | 131 ++++--- 4 files changed, 379 insertions(+), 364 deletions(-) diff --git a/src/components/colorscale/attributes.js b/src/components/colorscale/attributes.js index 6bfaac6be15..2074e8349f4 100644 --- a/src/components/colorscale/attributes.js +++ b/src/components/colorscale/attributes.js @@ -59,26 +59,24 @@ module.exports = function colorScaleAttrs(context, opts) { opts = opts || {}; var cLetter = opts.cLetter || 'c'; - var onlyIfNumerical = ('onlyIfNumerical' in opts) ? opts.onlyIfNumerical : Boolean(context); - var noScale = ('noScale' in opts) ? opts.noScale : context === 'marker.line'; - var showScaleDflt = ('showScaleDflt' in opts) ? opts.showScaleDflt : cLetter === 'z'; + var onlyIfNumerical = 'onlyIfNumerical' in opts ? opts.onlyIfNumerical : Boolean(context); + var noScale = 'noScale' in opts ? opts.noScale : context === 'marker.line'; + var showScaleDflt = 'showScaleDflt' in opts ? opts.showScaleDflt : cLetter === 'z'; var colorscaleDflt = typeof opts.colorscaleDflt === 'string' ? palettes[opts.colorscaleDflt] : null; var editTypeOverride = opts.editTypeOverride || ''; - var contextHead = context ? (context + '.') : ''; + var contextHead = context ? context + '.' : ''; var colorAttr, colorAttrFull; - if('colorAttr' in opts) { + if ('colorAttr' in opts) { colorAttr = opts.colorAttr; colorAttrFull = opts.colorAttr; } else { - colorAttr = {z: 'z', c: 'color'}[cLetter]; + colorAttr = { z: 'z', c: 'color' }[cLetter]; colorAttrFull = 'in ' + code(contextHead + colorAttr); } - var effectDesc = onlyIfNumerical ? - ' Has an effect only if ' + colorAttrFull + ' is set to a numerical array.' : - ''; + var effectDesc = onlyIfNumerical ? ' Has an effect only if ' + colorAttrFull + ' is set to a numerical array.' : ''; var auto = cLetter + 'auto'; var min = cLetter + 'min'; @@ -95,21 +93,24 @@ module.exports = function colorScaleAttrs(context, opts) { var attrs = {}; - if(colorAttr === 'color') { + if (colorAttr === 'color') { attrs.color = { valType: 'color', arrayOk: true, editType: editTypeOverride || 'style', description: [ - 'Sets the', context, 'color.', + 'Sets the', + context, + 'color.', 'It accepts either a specific color', 'or an array of numbers that are mapped to the colorscale', 'relative to the max and min values of the array or relative to', - minmaxFull, 'if set.' + minmaxFull, + 'if set.' ].join(' ') }; - if(opts.anim) { + if (opts.anim) { attrs.color.anim = true; } } @@ -123,7 +124,9 @@ module.exports = function colorScaleAttrs(context, opts) { 'Determines whether or not the color domain is computed', 'with respect to the input data (here ' + colorAttrFull + ') or the bounds set in', minmaxFull + effectDesc, - 'Defaults to `false` when', minmaxFull, 'are set by the user.' + 'Defaults to `false` when', + minmaxFull, + 'are set by the user.' ].join(' ') }; @@ -134,8 +137,11 @@ module.exports = function colorScaleAttrs(context, opts) { impliedEdits: minmaxImpliedEdits, description: [ 'Sets the lower bound of the color domain.' + effectDesc, - 'Value should have the same units as', colorAttrFull, - 'and if set,', maxFull, 'must be set as well.' + 'Value should have the same units as', + colorAttrFull, + 'and if set,', + maxFull, + 'must be set as well.' ].join(' ') }; @@ -146,8 +152,11 @@ module.exports = function colorScaleAttrs(context, opts) { impliedEdits: minmaxImpliedEdits, description: [ 'Sets the upper bound of the color domain.' + effectDesc, - 'Value should have the same units as', colorAttrFull, - 'and if set,', minFull, 'must be set as well.' + 'Value should have the same units as', + colorAttrFull, + 'and if set,', + minFull, + 'must be set as well.' ].join(' ') }; @@ -157,10 +166,16 @@ module.exports = function colorScaleAttrs(context, opts) { editType: 'calc', impliedEdits: autoImpliedEdits, description: [ - 'Sets the mid-point of the color domain by scaling', minFull, - 'and/or', maxFull, 'to be equidistant to this point.' + effectDesc, - 'Value should have the same units as', colorAttrFull + '.', - 'Has no effect when', autoFull, 'is `false`.' + 'Sets the mid-point of the color domain by scaling', + minFull, + 'and/or', + maxFull, + 'to be equidistant to this point.' + effectDesc, + 'Value should have the same units as', + colorAttrFull + '.', + 'Has no effect when', + autoFull, + 'is `false`.' ].join(' ') }; @@ -168,7 +183,7 @@ module.exports = function colorScaleAttrs(context, opts) { valType: 'colorscale', editType: 'calc', dflt: colorscaleDflt, - impliedEdits: {autocolorscale: false}, + impliedEdits: { autocolorscale: false }, description: [ 'Sets the colorscale.' + effectDesc, 'The colorscale must be an array containing', @@ -176,9 +191,10 @@ module.exports = function colorScaleAttrs(context, opts) { 'rgb, rgba, hex, hsl, hsv, or named color string.', 'At minimum, a mapping for the lowest (0) and highest (1)', 'values are required. For example,', - '`[[0, \'rgb(0,0,255)\'], [1, \'rgb(255,0,0)\']]`.', + "`[[0, 'rgb(0,0,255)'], [1, 'rgb(255,0,0)']]`.", 'To control the bounds of the colorscale in color space,', - 'use', minmaxFull + '.', + 'use', + minmaxFull + '.', 'Alternatively, `colorscale` may be a palette name string', 'of the following list: ' + paletteStr + '.' ].join(' ') @@ -189,10 +205,11 @@ module.exports = function colorScaleAttrs(context, opts) { // gets overrode in 'heatmap' & 'surface' for backwards comp. dflt: opts.autoColorDflt === false ? false : true, editType: 'calc', - impliedEdits: {colorscale: undefined}, + impliedEdits: { colorscale: undefined }, description: [ 'Determines whether the colorscale is a default palette (`autocolorscale: true`)', - 'or the palette determined by', code(contextHead + 'colorscale') + '.' + effectDesc, + 'or the palette determined by', + code(contextHead + 'colorscale') + '.' + effectDesc, 'In case `colorscale` is unspecified or `autocolorscale` is true, the default', 'palette will be chosen according to whether numbers in the `color` array are', 'all positive, all negative or mixed.' @@ -205,25 +222,27 @@ module.exports = function colorScaleAttrs(context, opts) { editType: 'plot', description: [ 'Reverses the color mapping if true.' + effectDesc, - 'If true,', minFull, 'will correspond to the last color', - 'in the array and', maxFull, 'will correspond to the first color.' + 'If true,', + minFull, + 'will correspond to the last color', + 'in the array and', + maxFull, + 'will correspond to the first color.' ].join(' ') }; - if(!noScale) { + if (!noScale) { attrs.showscale = { valType: 'boolean', dflt: showScaleDflt, editType: 'calc', - description: [ - 'Determines whether or not a colorbar is displayed for this trace.' + effectDesc - ].join(' ') + description: ['Determines whether or not a colorbar is displayed for this trace.' + effectDesc].join(' ') }; attrs.colorbar = colorbarAttrs; } - if(!opts.noColorAxis) { + if (!opts.noColorAxis) { attrs.coloraxis = { valType: 'subplotid', regex: counterRegex('coloraxis'), diff --git a/src/plots/geo/layout_attributes.js b/src/plots/geo/layout_attributes.js index b94cca3bec5..a6666178c37 100644 --- a/src/plots/geo/layout_attributes.js +++ b/src/plots/geo/layout_attributes.js @@ -10,14 +10,8 @@ var sortObjectKeys = require('../../lib/sort_object_keys'); var geoAxesAttrs = { range: { valType: 'info_array', - items: [ - {valType: 'number'}, - {valType: 'number'} - ], - description: [ - 'Sets the range of this axis (in degrees),', - 'sets the map\'s clipped coordinates.' - ].join(' ') + items: [{ valType: 'number' }, { valType: 'number' }], + description: ['Sets the range of this axis (in degrees),', "sets the map's clipped coordinates."].join(' ') }, showgrid: { valType: 'boolean', @@ -27,297 +21,290 @@ var geoAxesAttrs = { tick0: { valType: 'number', dflt: 0, - description: [ - 'Sets the graticule\'s starting tick longitude/latitude.' - ].join(' ') + description: ["Sets the graticule's starting tick longitude/latitude."].join(' ') }, dtick: { valType: 'number', - description: [ - 'Sets the graticule\'s longitude/latitude tick step.' - ].join(' ') + description: ["Sets the graticule's longitude/latitude tick step."].join(' ') }, gridcolor: { valType: 'color', dflt: colorAttrs.lightLine, - description: [ - 'Sets the graticule\'s stroke color.' - ].join(' ') + description: ["Sets the graticule's stroke color."].join(' ') }, gridwidth: { valType: 'number', min: 0, dflt: 1, - description: [ - 'Sets the graticule\'s stroke width (in px).' - ].join(' ') + description: ["Sets the graticule's stroke width (in px)."].join(' ') }, griddash: dash }; -var attrs = module.exports = overrideAll({ - domain: domainAttrs({name: 'geo'}, { - description: [ - 'Note that geo subplots are constrained by domain.', - 'In general, when `projection.scale` is set to 1.', - 'a map will fit either its x or y domain, but not both.' - ].join(' ') - }), +var attrs = (module.exports = overrideAll( + { + domain: domainAttrs( + { name: 'geo' }, + { + description: [ + 'Note that geo subplots are constrained by domain.', + 'In general, when `projection.scale` is set to 1.', + 'a map will fit either its x or y domain, but not both.' + ].join(' ') + } + ), - fitbounds: { - valType: 'enumerated', - values: [false, 'locations', 'geojson'], - dflt: false, - editType: 'plot', - description: [ - 'Determines if this subplot\'s view settings are auto-computed to fit trace data.', + fitbounds: { + valType: 'enumerated', + values: [false, 'locations', 'geojson'], + dflt: false, + editType: 'plot', + description: [ + "Determines if this subplot's view settings are auto-computed to fit trace data.", - 'On scoped maps, setting `fitbounds` leads to `center.lon` and `center.lat` getting auto-filled.', + 'On scoped maps, setting `fitbounds` leads to `center.lon` and `center.lat` getting auto-filled.', - 'On maps with a non-clipped projection, setting `fitbounds` leads to `center.lon`, `center.lat`,', - 'and `projection.rotation.lon` getting auto-filled.', + 'On maps with a non-clipped projection, setting `fitbounds` leads to `center.lon`, `center.lat`,', + 'and `projection.rotation.lon` getting auto-filled.', - 'On maps with a clipped projection, setting `fitbounds` leads to `center.lon`, `center.lat`,', - '`projection.rotation.lon`, `projection.rotation.lat`, `lonaxis.range` and `lataxis.range`', - 'getting auto-filled.', + 'On maps with a clipped projection, setting `fitbounds` leads to `center.lon`, `center.lat`,', + '`projection.rotation.lon`, `projection.rotation.lat`, `lonaxis.range` and `lataxis.range`', + 'getting auto-filled.', - // TODO we should auto-fill `projection.parallels` for maps - // with conic projection, but how? + // TODO we should auto-fill `projection.parallels` for maps + // with conic projection, but how? - 'If *locations*, only the trace\'s visible locations are considered in the `fitbounds` computations.', - 'If *geojson*, the entire trace input `geojson` (if provided) is considered in the `fitbounds` computations,', - 'Defaults to *false*.' - ].join(' ') - }, + "If *locations*, only the trace's visible locations are considered in the `fitbounds` computations.", + 'If *geojson*, the entire trace input `geojson` (if provided) is considered in the `fitbounds` computations,', + 'Defaults to *false*.' + ].join(' ') + }, - resolution: { - valType: 'enumerated', - values: [110, 50], - dflt: 110, - coerceNumber: true, - description: [ - 'Sets the resolution of the base layers.', - 'The values have units of km/mm', - 'e.g. 110 corresponds to a scale ratio of 1:110,000,000.' - ].join(' ') - }, - scope: { - valType: 'enumerated', - values: sortObjectKeys(constants.scopeDefaults), - dflt: 'world', - description: 'Set the scope of the map.' - }, - projection: { - type: { + resolution: { + valType: 'enumerated', + values: [110, 50], + dflt: 110, + coerceNumber: true, + description: [ + 'Sets the resolution of the base layers.', + 'The values have units of km/mm', + 'e.g. 110 corresponds to a scale ratio of 1:110,000,000.' + ].join(' ') + }, + scope: { valType: 'enumerated', - values: sortObjectKeys(constants.projNames), - description: 'Sets the projection type.' + values: sortObjectKeys(constants.scopeDefaults), + dflt: 'world', + description: 'Set the scope of the map.' }, - rotation: { - lon: { + projection: { + type: { + valType: 'enumerated', + values: sortObjectKeys(constants.projNames), + description: 'Sets the projection type.' + }, + rotation: { + lon: { + valType: 'number', + description: [ + 'Rotates the map along parallels', + '(in degrees East).', + 'Defaults to the center of the `lonaxis.range` values.' + ].join(' ') + }, + lat: { + valType: 'number', + description: ['Rotates the map along meridians', '(in degrees North).'].join(' ') + }, + roll: { + valType: 'number', + description: [ + 'Roll the map (in degrees)', + 'For example, a roll of *180* makes the map appear upside down.' + ].join(' ') + } + }, + tilt: { valType: 'number', + dflt: 0, description: [ - 'Rotates the map along parallels', - '(in degrees East).', - 'Defaults to the center of the `lonaxis.range` values.' + 'For satellite projection type only.', + 'Sets the tilt angle of perspective projection.' ].join(' ') }, - lat: { + distance: { + valType: 'number', + min: 1.001, + dflt: 2, + description: [ + 'For satellite projection type only.', + 'Sets the distance from the center of the sphere to the point of view', + 'as a proportion of the sphere’s radius.' + ].join(' ') + }, + parallels: { + valType: 'info_array', + items: [{ valType: 'number' }, { valType: 'number' }], + description: [ + 'For conic projection types only.', + 'Sets the parallels (tangent, secant)', + 'where the cone intersects the sphere.' + ].join(' ') + }, + scale: { + valType: 'number', + min: 0, + dflt: 1, + description: [ + 'Zooms in or out on the map view.', + 'A scale of *1* corresponds to the largest zoom level', + "that fits the map's lon and lat ranges. " + ].join(' ') + } + }, + center: { + lon: { valType: 'number', description: [ - 'Rotates the map along meridians', - '(in degrees North).' + "Sets the longitude of the map's center.", + "By default, the map's longitude center lies at the middle of the longitude range", + 'for scoped projection and above `projection.rotation.lon` otherwise.' ].join(' ') }, - roll: { + lat: { valType: 'number', description: [ - 'Roll the map (in degrees)', - 'For example, a roll of *180* makes the map appear upside down.' + "Sets the latitude of the map's center.", + "For all projection types, the map's latitude center lies", + 'at the middle of the latitude range by default.' ].join(' ') } }, - tilt: { + visible: { + valType: 'boolean', + dflt: true, + description: 'Sets the default visibility of the base layers.' + }, + showcoastlines: { + valType: 'boolean', + description: 'Sets whether or not the coastlines are drawn.' + }, + coastlinecolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + description: 'Sets the coastline color.' + }, + coastlinewidth: { valType: 'number', - dflt: 0, - description: [ - 'For satellite projection type only.', - 'Sets the tilt angle of perspective projection.' - ].join(' ') + min: 0, + dflt: 1, + description: 'Sets the coastline stroke width (in px).' + }, + showland: { + valType: 'boolean', + dflt: false, + description: 'Sets whether or not land masses are filled in color.' }, - distance: { + landcolor: { + valType: 'color', + dflt: constants.landColor, + description: 'Sets the land mass color.' + }, + showocean: { + valType: 'boolean', + dflt: false, + description: 'Sets whether or not oceans are filled in color.' + }, + oceancolor: { + valType: 'color', + dflt: constants.waterColor, + description: 'Sets the ocean color' + }, + showlakes: { + valType: 'boolean', + dflt: false, + description: 'Sets whether or not lakes are drawn.' + }, + lakecolor: { + valType: 'color', + dflt: constants.waterColor, + description: 'Sets the color of the lakes.' + }, + showrivers: { + valType: 'boolean', + dflt: false, + description: 'Sets whether or not rivers are drawn.' + }, + rivercolor: { + valType: 'color', + dflt: constants.waterColor, + description: 'Sets color of the rivers.' + }, + riverwidth: { valType: 'number', - min: 1.001, - dflt: 2, - description: [ - 'For satellite projection type only.', - 'Sets the distance from the center of the sphere to the point of view', - 'as a proportion of the sphere’s radius.' - ].join(' ') + min: 0, + dflt: 1, + description: 'Sets the stroke width (in px) of the rivers.' }, - parallels: { - valType: 'info_array', - items: [ - {valType: 'number'}, - {valType: 'number'} - ], - description: [ - 'For conic projection types only.', - 'Sets the parallels (tangent, secant)', - 'where the cone intersects the sphere.' - ].join(' ') + showcountries: { + valType: 'boolean', + description: 'Sets whether or not country boundaries are drawn.' + }, + countrycolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + description: 'Sets line color of the country boundaries.' }, - scale: { + countrywidth: { valType: 'number', min: 0, dflt: 1, + description: 'Sets line width (in px) of the country boundaries.' + }, + showsubunits: { + valType: 'boolean', description: [ - 'Zooms in or out on the map view.', - 'A scale of *1* corresponds to the largest zoom level', - 'that fits the map\'s lon and lat ranges. ' + 'Sets whether or not boundaries of subunits within countries', + '(e.g. states, provinces) are drawn.' ].join(' ') }, - }, - center: { - lon: { + subunitcolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + description: 'Sets the color of the subunits boundaries.' + }, + subunitwidth: { valType: 'number', - description: [ - 'Sets the longitude of the map\'s center.', - 'By default, the map\'s longitude center lies at the middle of the longitude range', - 'for scoped projection and above `projection.rotation.lon` otherwise.' - ].join(' ') + min: 0, + dflt: 1, + description: 'Sets the stroke width (in px) of the subunits boundaries.' + }, + showframe: { + valType: 'boolean', + description: 'Sets whether or not a frame is drawn around the map.' }, - lat: { + framecolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + description: 'Sets the color the frame.' + }, + framewidth: { valType: 'number', - description: [ - 'Sets the latitude of the map\'s center.', - 'For all projection types, the map\'s latitude center lies', - 'at the middle of the latitude range by default.' - ].join(' ') - } - }, - visible: { - valType: 'boolean', - dflt: true, - description: 'Sets the default visibility of the base layers.' - }, - showcoastlines: { - valType: 'boolean', - description: 'Sets whether or not the coastlines are drawn.' - }, - coastlinecolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - description: 'Sets the coastline color.' - }, - coastlinewidth: { - valType: 'number', - min: 0, - dflt: 1, - description: 'Sets the coastline stroke width (in px).' - }, - showland: { - valType: 'boolean', - dflt: false, - description: 'Sets whether or not land masses are filled in color.' - }, - landcolor: { - valType: 'color', - dflt: constants.landColor, - description: 'Sets the land mass color.' - }, - showocean: { - valType: 'boolean', - dflt: false, - description: 'Sets whether or not oceans are filled in color.' - }, - oceancolor: { - valType: 'color', - dflt: constants.waterColor, - description: 'Sets the ocean color' - }, - showlakes: { - valType: 'boolean', - dflt: false, - description: 'Sets whether or not lakes are drawn.' - }, - lakecolor: { - valType: 'color', - dflt: constants.waterColor, - description: 'Sets the color of the lakes.' - }, - showrivers: { - valType: 'boolean', - dflt: false, - description: 'Sets whether or not rivers are drawn.' - }, - rivercolor: { - valType: 'color', - dflt: constants.waterColor, - description: 'Sets color of the rivers.' - }, - riverwidth: { - valType: 'number', - min: 0, - dflt: 1, - description: 'Sets the stroke width (in px) of the rivers.' - }, - showcountries: { - valType: 'boolean', - description: 'Sets whether or not country boundaries are drawn.' - }, - countrycolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - description: 'Sets line color of the country boundaries.' - }, - countrywidth: { - valType: 'number', - min: 0, - dflt: 1, - description: 'Sets line width (in px) of the country boundaries.' - }, - showsubunits: { - valType: 'boolean', - description: [ - 'Sets whether or not boundaries of subunits within countries', - '(e.g. states, provinces) are drawn.' - ].join(' ') - }, - subunitcolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - description: 'Sets the color of the subunits boundaries.' - }, - subunitwidth: { - valType: 'number', - min: 0, - dflt: 1, - description: 'Sets the stroke width (in px) of the subunits boundaries.' - }, - showframe: { - valType: 'boolean', - description: 'Sets whether or not a frame is drawn around the map.' - }, - framecolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - description: 'Sets the color the frame.' - }, - framewidth: { - valType: 'number', - min: 0, - dflt: 1, - description: 'Sets the stroke width (in px) of the frame.' - }, - bgcolor: { - valType: 'color', - dflt: colorAttrs.background, - description: 'Set the background color of the map' + min: 0, + dflt: 1, + description: 'Sets the stroke width (in px) of the frame.' + }, + bgcolor: { + valType: 'color', + dflt: colorAttrs.background, + description: 'Set the background color of the map' + }, + lonaxis: geoAxesAttrs, + lataxis: geoAxesAttrs }, - lonaxis: geoAxesAttrs, - lataxis: geoAxesAttrs -}, 'plot', 'from-root'); + 'plot', + 'from-root' +)); // set uirevision outside of overrideAll so it can be `editType: 'none'` attrs.uirevision = { diff --git a/src/plots/map/constants.js b/src/plots/map/constants.js index 7d48768d8d7..2a867418477 100644 --- a/src/plots/map/constants.js +++ b/src/plots/map/constants.js @@ -4,7 +4,6 @@ var sortObjectKeys = require('../../lib/sort_object_keys'); var arcgisSatHybrid = require('./styles/arcgis-sat-hybrid'); // https://raw.githubusercontent.com/go2garret/maps/v1.0.0/LICENSE var arcgisSat = require('./styles/arcgis-sat'); - var OSM = '© OpenStreetMap contributors'; var cartoPositron = 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json'; @@ -14,7 +13,6 @@ var cartoPositronNoLabels = 'https://basemaps.cartocdn.com/gl/positron-nolabels- var cartoDarkmatterNoLabels = 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json'; var cartoVoyagerNoLabels = 'https://basemaps.cartocdn.com/gl/voyager-nolabels-gl-style/style.json'; - var stylesMap = { basic: cartoVoyager, streets: cartoVoyager, @@ -30,32 +28,34 @@ var stylesMap = { 'plotly-osm-tiles': { type: 'raster', attribution: OSM, - tiles: [ - 'https://tile.openstreetmap.org/{z}/{x}/{y}.png' - ], + tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'], tileSize: 256 } }, - layers: [{ - id: 'plotly-osm-tiles', - type: 'raster', - source: 'plotly-osm-tiles', - minzoom: 0, - maxzoom: 22 - }], + layers: [ + { + id: 'plotly-osm-tiles', + type: 'raster', + source: 'plotly-osm-tiles', + minzoom: 0, + maxzoom: 22 + } + ], glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf' }, 'white-bg': { id: 'white-bg', version: 8, sources: {}, - layers: [{ - id: 'white-bg', - type: 'background', - paint: {'background-color': '#FFFFFF'}, - minzoom: 0, - maxzoom: 22 - }], + layers: [ + { + id: 'white-bg', + type: 'background', + paint: { 'background-color': '#FFFFFF' }, + minzoom: 0, + maxzoom: 22 + } + ], glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf' }, 'carto-positron': cartoPositron, @@ -63,7 +63,7 @@ var stylesMap = { 'carto-voyager': cartoVoyager, 'carto-positron-nolabels': cartoPositronNoLabels, 'carto-darkmatter-nolabels': cartoDarkmatterNoLabels, - 'carto-voyager-nolabels': cartoVoyagerNoLabels, + 'carto-voyager-nolabels': cartoVoyagerNoLabels }; var styleValuesMap = sortObjectKeys(stylesMap); @@ -76,15 +76,11 @@ module.exports = { traceLayerPrefix: 'plotly-trace-layer-', layoutLayerPrefix: 'plotly-layout-layer-', - missingStyleErrorMsg: [ 'No valid maplibre style found, please set `map.style` to one of:', styleValuesMap.join(', '), 'or use a tile service.' ].join('\n'), - - mapOnErrorMsg: 'Map error.', - - + mapOnErrorMsg: 'Map error.' }; diff --git a/src/plots/mapbox/constants.js b/src/plots/mapbox/constants.js index 86e955cb4cd..37f79ddc569 100644 --- a/src/plots/mapbox/constants.js +++ b/src/plots/mapbox/constants.js @@ -5,10 +5,7 @@ var sortObjectKeys = require('../../lib/sort_object_keys'); var requiredVersion = '1.13.4'; var OSM = '© OpenStreetMap contributors'; -var carto = [ - '© Carto', - OSM -].join(' '); +var carto = ['© Carto', OSM].join(' '); var stamenTerrainOrToner = [ 'Map tiles by Stamen Design', @@ -41,26 +38,30 @@ var stylesNonMapbox = { tileSize: 256 } }, - layers: [{ - id: 'plotly-osm-tiles', - type: 'raster', - source: 'plotly-osm-tiles', - minzoom: 0, - maxzoom: 22 - }], + layers: [ + { + id: 'plotly-osm-tiles', + type: 'raster', + source: 'plotly-osm-tiles', + minzoom: 0, + maxzoom: 22 + } + ], glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf' }, 'white-bg': { id: 'white-bg', version: 8, sources: {}, - layers: [{ - id: 'white-bg', - type: 'background', - paint: {'background-color': '#FFFFFF'}, - minzoom: 0, - maxzoom: 22 - }], + layers: [ + { + id: 'white-bg', + type: 'background', + paint: { 'background-color': '#FFFFFF' }, + minzoom: 0, + maxzoom: 22 + } + ], glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf' }, 'carto-positron': { @@ -74,13 +75,15 @@ var stylesNonMapbox = { tileSize: 256 } }, - layers: [{ - id: 'plotly-carto-positron', - type: 'raster', - source: 'plotly-carto-positron', - minzoom: 0, - maxzoom: 22 - }], + layers: [ + { + id: 'plotly-carto-positron', + type: 'raster', + source: 'plotly-carto-positron', + minzoom: 0, + maxzoom: 22 + } + ], glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf' }, 'carto-darkmatter': { @@ -94,13 +97,15 @@ var stylesNonMapbox = { tileSize: 256 } }, - layers: [{ - id: 'plotly-carto-darkmatter', - type: 'raster', - source: 'plotly-carto-darkmatter', - minzoom: 0, - maxzoom: 22 - }], + layers: [ + { + id: 'plotly-carto-darkmatter', + type: 'raster', + source: 'plotly-carto-darkmatter', + minzoom: 0, + maxzoom: 22 + } + ], glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf' }, 'stamen-terrain': { @@ -114,13 +119,15 @@ var stylesNonMapbox = { tileSize: 256 } }, - layers: [{ - id: 'plotly-stamen-terrain', - type: 'raster', - source: 'plotly-stamen-terrain', - minzoom: 0, - maxzoom: 22 - }], + layers: [ + { + id: 'plotly-stamen-terrain', + type: 'raster', + source: 'plotly-stamen-terrain', + minzoom: 0, + maxzoom: 22 + } + ], glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf' }, 'stamen-toner': { @@ -134,13 +141,15 @@ var stylesNonMapbox = { tileSize: 256 } }, - layers: [{ - id: 'plotly-stamen-toner', - type: 'raster', - source: 'plotly-stamen-toner', - minzoom: 0, - maxzoom: 22 - }], + layers: [ + { + id: 'plotly-stamen-toner', + type: 'raster', + source: 'plotly-stamen-toner', + minzoom: 0, + maxzoom: 22 + } + ], glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf' }, 'stamen-watercolor': { @@ -154,13 +163,15 @@ var stylesNonMapbox = { tileSize: 256 } }, - layers: [{ - id: 'plotly-stamen-watercolor', - type: 'raster', - source: 'plotly-stamen-watercolor', - minzoom: 0, - maxzoom: 22 - }], + layers: [ + { + id: 'plotly-stamen-watercolor', + type: 'raster', + source: 'plotly-stamen-watercolor', + minzoom: 0, + maxzoom: 22 + } + ], glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf' } }; @@ -190,7 +201,7 @@ module.exports = { 'Missing Mapbox access token.', 'Mapbox trace type require a Mapbox access token to be registered.', 'For example:', - ' Plotly.newPlot(gd, data, layout, { mapboxAccessToken: \'my-access-token\' });', + " Plotly.newPlot(gd, data, layout, { mapboxAccessToken: 'my-access-token' });", 'More info here: https://www.mapbox.com/help/define-access-token/' ].join('\n'), @@ -202,8 +213,7 @@ module.exports = { multipleTokensErrorMsg: [ 'Set multiple mapbox access token across different mapbox subplot,', - 'using first token found as mapbox-gl does not allow multiple' + - 'access tokens on the same page.' + 'using first token found as mapbox-gl does not allow multiple' + 'access tokens on the same page.' ].join('\n'), mapOnErrorMsg: 'Mapbox error.', @@ -231,8 +241,10 @@ module.exports = { 'ctrl-attrib.mapboxgl-compact .mapboxgl-ctrl-attrib-inner': 'display: none;', 'ctrl-attrib.mapboxgl-compact:hover .mapboxgl-ctrl-attrib-inner': 'display: block; margin-top:2px', 'ctrl-attrib.mapboxgl-compact:hover': 'padding: 2px 24px 2px 4px; visibility: visible; margin-top: 6px;', - 'ctrl-attrib.mapboxgl-compact::after': 'content: ""; cursor: pointer; position: absolute; background-image: url(\'data:image/svg+xml;charset=utf-8,%3Csvg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"%3E %3Cpath fill="%23333333" fill-rule="evenodd" d="M4,10a6,6 0 1,0 12,0a6,6 0 1,0 -12,0 M9,7a1,1 0 1,0 2,0a1,1 0 1,0 -2,0 M9,10a1,1 0 1,1 2,0l0,3a1,1 0 1,1 -2,0"/%3E %3C/svg%3E\'); background-color: rgba(255, 255, 255, 0.5); width: 24px; height: 24px; box-sizing: border-box; border-radius: 12px;', - 'ctrl-attrib.mapboxgl-compact': 'min-height: 20px; padding: 0; margin: 10px; position: relative; background-color: #fff; border-radius: 3px 12px 12px 3px;', + 'ctrl-attrib.mapboxgl-compact::after': + 'content: ""; cursor: pointer; position: absolute; background-image: url(\'data:image/svg+xml;charset=utf-8,%3Csvg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"%3E %3Cpath fill="%23333333" fill-rule="evenodd" d="M4,10a6,6 0 1,0 12,0a6,6 0 1,0 -12,0 M9,7a1,1 0 1,0 2,0a1,1 0 1,0 -2,0 M9,10a1,1 0 1,1 2,0l0,3a1,1 0 1,1 -2,0"/%3E %3C/svg%3E\'); background-color: rgba(255, 255, 255, 0.5); width: 24px; height: 24px; box-sizing: border-box; border-radius: 12px;', + 'ctrl-attrib.mapboxgl-compact': + 'min-height: 20px; padding: 0; margin: 10px; position: relative; background-color: #fff; border-radius: 3px 12px 12px 3px;', 'ctrl-bottom-right > .mapboxgl-ctrl-attrib.mapboxgl-compact::after': 'bottom: 0; right: 0', 'ctrl-bottom-left > .mapboxgl-ctrl-attrib.mapboxgl-compact::after': 'bottom: 0; left: 0', @@ -247,7 +259,8 @@ module.exports = { 'attrib-empty': 'display: none;', // Compact Mapbox logo without text - 'ctrl-logo': 'display:block; width: 21px; height: 21px; background-image: url(\'data:image/svg+xml;charset=utf-8,%3C?xml version="1.0" encoding="utf-8"?%3E %3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 21 21" style="enable-background:new 0 0 21 21;" xml:space="preserve"%3E%3Cg transform="translate(0,0.01)"%3E%3Cpath d="m 10.5,1.24 c -5.11,0 -9.25,4.15 -9.25,9.25 0,5.1 4.15,9.25 9.25,9.25 5.1,0 9.25,-4.15 9.25,-9.25 0,-5.11 -4.14,-9.25 -9.25,-9.25 z m 4.39,11.53 c -1.93,1.93 -4.78,2.31 -6.7,2.31 -0.7,0 -1.41,-0.05 -2.1,-0.16 0,0 -1.02,-5.64 2.14,-8.81 0.83,-0.83 1.95,-1.28 3.13,-1.28 1.27,0 2.49,0.51 3.39,1.42 1.84,1.84 1.89,4.75 0.14,6.52 z" style="opacity:0.9;fill:%23ffffff;enable-background:new" class="st0"/%3E%3Cpath d="M 10.5,-0.01 C 4.7,-0.01 0,4.7 0,10.49 c 0,5.79 4.7,10.5 10.5,10.5 5.8,0 10.5,-4.7 10.5,-10.5 C 20.99,4.7 16.3,-0.01 10.5,-0.01 Z m 0,19.75 c -5.11,0 -9.25,-4.15 -9.25,-9.25 0,-5.1 4.14,-9.26 9.25,-9.26 5.11,0 9.25,4.15 9.25,9.25 0,5.13 -4.14,9.26 -9.25,9.26 z" style="opacity:0.35;enable-background:new" class="st1"/%3E%3Cpath d="M 14.74,6.25 C 12.9,4.41 9.98,4.35 8.23,6.1 5.07,9.27 6.09,14.91 6.09,14.91 c 0,0 5.64,1.02 8.81,-2.14 C 16.64,11 16.59,8.09 14.74,6.25 Z m -2.27,4.09 -0.91,1.87 -0.9,-1.87 -1.86,-0.91 1.86,-0.9 0.9,-1.87 0.91,1.87 1.86,0.9 z" style="opacity:0.35;enable-background:new" class="st1"/%3E%3Cpolygon points="11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 14.33,9.43 12.47,10.34 " style="opacity:0.9;fill:%23ffffff;enable-background:new" class="st0"/%3E%3C/g%3E%3C/svg%3E\')' + 'ctrl-logo': + 'display:block; width: 21px; height: 21px; background-image: url(\'data:image/svg+xml;charset=utf-8,%3C?xml version="1.0" encoding="utf-8"?%3E %3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 21 21" style="enable-background:new 0 0 21 21;" xml:space="preserve"%3E%3Cg transform="translate(0,0.01)"%3E%3Cpath d="m 10.5,1.24 c -5.11,0 -9.25,4.15 -9.25,9.25 0,5.1 4.15,9.25 9.25,9.25 5.1,0 9.25,-4.15 9.25,-9.25 0,-5.11 -4.14,-9.25 -9.25,-9.25 z m 4.39,11.53 c -1.93,1.93 -4.78,2.31 -6.7,2.31 -0.7,0 -1.41,-0.05 -2.1,-0.16 0,0 -1.02,-5.64 2.14,-8.81 0.83,-0.83 1.95,-1.28 3.13,-1.28 1.27,0 2.49,0.51 3.39,1.42 1.84,1.84 1.89,4.75 0.14,6.52 z" style="opacity:0.9;fill:%23ffffff;enable-background:new" class="st0"/%3E%3Cpath d="M 10.5,-0.01 C 4.7,-0.01 0,4.7 0,10.49 c 0,5.79 4.7,10.5 10.5,10.5 5.8,0 10.5,-4.7 10.5,-10.5 C 20.99,4.7 16.3,-0.01 10.5,-0.01 Z m 0,19.75 c -5.11,0 -9.25,-4.15 -9.25,-9.25 0,-5.1 4.14,-9.26 9.25,-9.26 5.11,0 9.25,4.15 9.25,9.25 0,5.13 -4.14,9.26 -9.25,9.26 z" style="opacity:0.35;enable-background:new" class="st1"/%3E%3Cpath d="M 14.74,6.25 C 12.9,4.41 9.98,4.35 8.23,6.1 5.07,9.27 6.09,14.91 6.09,14.91 c 0,0 5.64,1.02 8.81,-2.14 C 16.64,11 16.59,8.09 14.74,6.25 Z m -2.27,4.09 -0.91,1.87 -0.9,-1.87 -1.86,-0.91 1.86,-0.9 0.9,-1.87 0.91,1.87 1.86,0.9 z" style="opacity:0.35;enable-background:new" class="st1"/%3E%3Cpolygon points="11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 14.33,9.43 12.47,10.34 " style="opacity:0.9;fill:%23ffffff;enable-background:new" class="st0"/%3E%3C/g%3E%3C/svg%3E\')' // Mapbox logo WITH text below (commented out for now) // 'ctrl-logo': 'width: 85px; height: 21px; margin: 0 0 -3px -3px; display: block; background-repeat: no-repeat; cursor: pointer; background-image: url(\'data:image/svg+xml;charset=utf-8,%3C?xml version="1.0" encoding="utf-8"?%3E%3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 84.49 21" style="enable-background:new 0 0 84.49 21;" xml:space="preserve"%3E%3Cg%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M83.25,14.26c0,0.12-0.09,0.21-0.21,0.21h-1.61c-0.13,0-0.24-0.06-0.3-0.17l-1.44-2.39l-1.44,2.39 c-0.06,0.11-0.18,0.17-0.3,0.17h-1.61c-0.04,0-0.08-0.01-0.12-0.03c-0.09-0.06-0.13-0.19-0.06-0.28l0,0l2.43-3.68L76.2,6.84 c-0.02-0.03-0.03-0.07-0.03-0.12c0-0.12,0.09-0.21,0.21-0.21h1.61c0.13,0,0.24,0.06,0.3,0.17l1.41,2.36l1.4-2.35 c0.06-0.11,0.18-0.17,0.3-0.17H83c0.04,0,0.08,0.01,0.12,0.03c0.09,0.06,0.13,0.19,0.06,0.28l0,0l-2.37,3.63l2.43,3.67 C83.24,14.18,83.25,14.22,83.25,14.26z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M66.24,9.59c-0.39-1.88-1.96-3.28-3.84-3.28c-1.03,0-2.03,0.42-2.73,1.18V3.51c0-0.13-0.1-0.23-0.23-0.23h-1.4 c-0.13,0-0.23,0.11-0.23,0.23v10.72c0,0.13,0.1,0.23,0.23,0.23h1.4c0.13,0,0.23-0.11,0.23-0.23V13.5c0.71,0.75,1.7,1.18,2.73,1.18 c1.88,0,3.45-1.41,3.84-3.29C66.37,10.79,66.37,10.18,66.24,9.59L66.24,9.59z M62.08,13c-1.32,0-2.39-1.11-2.41-2.48v-0.06 c0.02-1.38,1.09-2.48,2.41-2.48s2.42,1.12,2.42,2.51S63.41,13,62.08,13z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M71.67,6.32c-1.98-0.01-3.72,1.35-4.16,3.29c-0.13,0.59-0.13,1.19,0,1.77c0.44,1.94,2.17,3.32,4.17,3.3 c2.35,0,4.26-1.87,4.26-4.19S74.04,6.32,71.67,6.32z M71.65,13.01c-1.33,0-2.42-1.12-2.42-2.51s1.08-2.52,2.42-2.52 c1.33,0,2.42,1.12,2.42,2.51S72.99,13,71.65,13.01L71.65,13.01z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M62.08,7.98c-1.32,0-2.39,1.11-2.41,2.48v0.06C59.68,11.9,60.75,13,62.08,13s2.42-1.12,2.42-2.51 S63.41,7.98,62.08,7.98z M62.08,11.76c-0.63,0-1.14-0.56-1.17-1.25v-0.04c0.01-0.69,0.54-1.25,1.17-1.25 c0.63,0,1.17,0.57,1.17,1.27C63.24,11.2,62.73,11.76,62.08,11.76z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M71.65,7.98c-1.33,0-2.42,1.12-2.42,2.51S70.32,13,71.65,13s2.42-1.12,2.42-2.51S72.99,7.98,71.65,7.98z M71.65,11.76c-0.64,0-1.17-0.57-1.17-1.27c0-0.7,0.53-1.26,1.17-1.26s1.17,0.57,1.17,1.27C72.82,11.21,72.29,11.76,71.65,11.76z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M45.74,6.53h-1.4c-0.13,0-0.23,0.11-0.23,0.23v0.73c-0.71-0.75-1.7-1.18-2.73-1.18 c-2.17,0-3.94,1.87-3.94,4.19s1.77,4.19,3.94,4.19c1.04,0,2.03-0.43,2.73-1.19v0.73c0,0.13,0.1,0.23,0.23,0.23h1.4 c0.13,0,0.23-0.11,0.23-0.23V6.74c0-0.12-0.09-0.22-0.22-0.22C45.75,6.53,45.75,6.53,45.74,6.53z M44.12,10.53 C44.11,11.9,43.03,13,41.71,13s-2.42-1.12-2.42-2.51s1.08-2.52,2.4-2.52c1.33,0,2.39,1.11,2.41,2.48L44.12,10.53z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M41.71,7.98c-1.33,0-2.42,1.12-2.42,2.51S40.37,13,41.71,13s2.39-1.11,2.41-2.48v-0.06 C44.1,9.09,43.03,7.98,41.71,7.98z M40.55,10.49c0-0.7,0.52-1.27,1.17-1.27c0.64,0,1.14,0.56,1.17,1.25v0.04 c-0.01,0.68-0.53,1.24-1.17,1.24C41.08,11.75,40.55,11.19,40.55,10.49z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M52.41,6.32c-1.03,0-2.03,0.42-2.73,1.18V6.75c0-0.13-0.1-0.23-0.23-0.23h-1.4c-0.13,0-0.23,0.11-0.23,0.23 v10.72c0,0.13,0.1,0.23,0.23,0.23h1.4c0.13,0,0.23-0.1,0.23-0.23V13.5c0.71,0.75,1.7,1.18,2.74,1.18c2.17,0,3.94-1.87,3.94-4.19 S54.58,6.32,52.41,6.32z M52.08,13.01c-1.32,0-2.39-1.11-2.42-2.48v-0.07c0.02-1.38,1.09-2.49,2.4-2.49c1.32,0,2.41,1.12,2.41,2.51 S53.4,13,52.08,13.01L52.08,13.01z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M52.08,7.98c-1.32,0-2.39,1.11-2.42,2.48v0.06c0.03,1.38,1.1,2.48,2.42,2.48s2.41-1.12,2.41-2.51 S53.4,7.98,52.08,7.98z M52.08,11.76c-0.63,0-1.14-0.56-1.17-1.25v-0.04c0.01-0.69,0.54-1.25,1.17-1.25c0.63,0,1.17,0.58,1.17,1.27 S52.72,11.76,52.08,11.76z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M36.08,14.24c0,0.13-0.1,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68c0-0.98-0.74-1.71-1.62-1.71 c-0.8,0-1.46,0.7-1.59,1.62l0.01,4.66c0,0.13-0.11,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68 c0-0.98-0.74-1.71-1.62-1.71c-0.85,0-1.54,0.79-1.6,1.8v4.48c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V6.74 c0.01-0.13,0.1-0.22,0.23-0.22h1.4c0.13,0,0.22,0.11,0.23,0.22V7.4c0.5-0.68,1.3-1.09,2.16-1.1h0.03c1.09,0,2.09,0.6,2.6,1.55 c0.45-0.95,1.4-1.55,2.44-1.56c1.62,0,2.93,1.25,2.9,2.78L36.08,14.24z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M84.34,13.59l-0.07-0.13l-1.96-2.99l1.94-2.95c0.44-0.67,0.26-1.56-0.41-2.02c-0.02,0-0.03,0-0.04-0.01 c-0.23-0.15-0.5-0.22-0.78-0.22h-1.61c-0.56,0-1.08,0.29-1.37,0.78L79.72,6.6l-0.34-0.56C79.09,5.56,78.57,5.27,78,5.27h-1.6 c-0.6,0-1.13,0.37-1.35,0.92c-2.19-1.66-5.28-1.47-7.26,0.45c-0.35,0.34-0.65,0.72-0.89,1.14c-0.9-1.62-2.58-2.72-4.5-2.72 c-0.5,0-1.01,0.07-1.48,0.23V3.51c0-0.82-0.66-1.48-1.47-1.48h-1.4c-0.81,0-1.47,0.66-1.47,1.47v3.75 c-0.95-1.36-2.5-2.18-4.17-2.19c-0.74,0-1.46,0.16-2.12,0.47c-0.24-0.17-0.54-0.26-0.84-0.26h-1.4c-0.45,0-0.87,0.21-1.15,0.56 c-0.02-0.03-0.04-0.05-0.07-0.08c-0.28-0.3-0.68-0.47-1.09-0.47h-1.39c-0.3,0-0.6,0.09-0.84,0.26c-0.67-0.3-1.39-0.46-2.12-0.46 c-1.83,0-3.43,1-4.37,2.5c-0.2-0.46-0.48-0.89-0.83-1.25c-0.8-0.81-1.89-1.25-3.02-1.25h-0.01c-0.89,0.01-1.75,0.33-2.46,0.88 c-0.74-0.57-1.64-0.88-2.57-0.88H28.1c-0.29,0-0.58,0.03-0.86,0.11c-0.28,0.06-0.56,0.16-0.82,0.28c-0.21-0.12-0.45-0.18-0.7-0.18 h-1.4c-0.82,0-1.47,0.66-1.47,1.47v7.5c0,0.82,0.66,1.47,1.47,1.47h1.4c0.82,0,1.48-0.66,1.48-1.48l0,0V9.79 c0.03-0.36,0.23-0.59,0.36-0.59c0.18,0,0.38,0.18,0.38,0.47v4.57c0,0.82,0.66,1.47,1.47,1.47h1.41c0.82,0,1.47-0.66,1.47-1.47 l-0.01-4.57c0.06-0.32,0.25-0.47,0.35-0.47c0.18,0,0.38,0.18,0.38,0.47v4.57c0,0.82,0.66,1.47,1.47,1.47h1.41 c0.82,0,1.47-0.66,1.47-1.47v-0.38c0.96,1.29,2.46,2.06,4.06,2.06c0.74,0,1.46-0.16,2.12-0.47c0.24,0.17,0.54,0.26,0.84,0.26h1.39 c0.3,0,0.6-0.09,0.84-0.26v2.01c0,0.82,0.66,1.47,1.47,1.47h1.4c0.82,0,1.47-0.66,1.47-1.47v-1.77c0.48,0.15,0.99,0.23,1.49,0.22 c1.7,0,3.22-0.87,4.17-2.2v0.52c0,0.82,0.66,1.47,1.47,1.47h1.4c0.3,0,0.6-0.09,0.84-0.26c0.66,0.31,1.39,0.47,2.12,0.47 c1.92,0,3.6-1.1,4.49-2.73c1.54,2.65,4.95,3.53,7.58,1.98c0.18-0.11,0.36-0.22,0.53-0.36c0.22,0.55,0.76,0.91,1.35,0.9H78 c0.56,0,1.08-0.29,1.37-0.78l0.37-0.61l0.37,0.61c0.29,0.48,0.81,0.78,1.38,0.78h1.6c0.81,0,1.46-0.66,1.45-1.46 C84.49,14.02,84.44,13.8,84.34,13.59L84.34,13.59z M35.86,14.47h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68 c0-0.98-0.74-1.71-1.62-1.71c-0.8,0-1.46,0.7-1.59,1.62l0.01,4.66c0,0.13-0.1,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23 V9.68c0-0.98-0.74-1.71-1.62-1.71c-0.85,0-1.54,0.79-1.6,1.8v4.48c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23 V6.74c0.01-0.13,0.11-0.22,0.23-0.22h1.4c0.13,0,0.22,0.11,0.23,0.22V7.4c0.5-0.68,1.3-1.09,2.16-1.1h0.03 c1.09,0,2.09,0.6,2.6,1.55c0.45-0.95,1.4-1.55,2.44-1.56c1.62,0,2.93,1.25,2.9,2.78l0.01,5.16C36.09,14.36,35.98,14.46,35.86,14.47 L35.86,14.47z M45.97,14.24c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V13.5c-0.7,0.76-1.69,1.18-2.72,1.18 c-2.17,0-3.94-1.87-3.94-4.19s1.77-4.19,3.94-4.19c1.03,0,2.02,0.43,2.73,1.18V6.74c0-0.13,0.1-0.23,0.23-0.23h1.4 c0.12-0.01,0.22,0.08,0.23,0.21c0,0.01,0,0.01,0,0.02v7.51h-0.01V14.24z M52.41,14.67c-1.03,0-2.02-0.43-2.73-1.18v3.97 c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.1-0.23-0.23V6.75c0-0.13,0.1-0.22,0.23-0.22h1.4c0.13,0,0.23,0.11,0.23,0.23v0.73 c0.71-0.76,1.7-1.18,2.73-1.18c2.17,0,3.94,1.86,3.94,4.18S54.58,14.67,52.41,14.67z M66.24,11.39c-0.39,1.87-1.96,3.29-3.84,3.29 c-1.03,0-2.02-0.43-2.73-1.18v0.73c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V3.51c0-0.13,0.1-0.23,0.23-0.23 h1.4c0.13,0,0.23,0.11,0.23,0.23v3.97c0.71-0.75,1.7-1.18,2.73-1.17c1.88,0,3.45,1.4,3.84,3.28C66.37,10.19,66.37,10.8,66.24,11.39 L66.24,11.39L66.24,11.39z M71.67,14.68c-2,0.01-3.73-1.35-4.17-3.3c-0.13-0.59-0.13-1.19,0-1.77c0.44-1.94,2.17-3.31,4.17-3.3 c2.36,0,4.26,1.87,4.26,4.19S74.03,14.68,71.67,14.68L71.67,14.68z M83.04,14.47h-1.61c-0.13,0-0.24-0.06-0.3-0.17l-1.44-2.39 l-1.44,2.39c-0.06,0.11-0.18,0.17-0.3,0.17h-1.61c-0.04,0-0.08-0.01-0.12-0.03c-0.09-0.06-0.13-0.19-0.06-0.28l0,0l2.43-3.68 L76.2,6.84c-0.02-0.03-0.03-0.07-0.03-0.12c0-0.12,0.09-0.21,0.21-0.21h1.61c0.13,0,0.24,0.06,0.3,0.17l1.41,2.36l1.41-2.36 c0.06-0.11,0.18-0.17,0.3-0.17h1.61c0.04,0,0.08,0.01,0.12,0.03c0.09,0.06,0.13,0.19,0.06,0.28l0,0l-2.38,3.64l2.43,3.67 c0.02,0.03,0.03,0.07,0.03,0.12C83.25,14.38,83.16,14.47,83.04,14.47L83.04,14.47L83.04,14.47z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M10.5,1.24c-5.11,0-9.25,4.15-9.25,9.25s4.15,9.25,9.25,9.25s9.25-4.15,9.25-9.25 C19.75,5.38,15.61,1.24,10.5,1.24z M14.89,12.77c-1.93,1.93-4.78,2.31-6.7,2.31c-0.7,0-1.41-0.05-2.1-0.16c0,0-1.02-5.64,2.14-8.81 c0.83-0.83,1.95-1.28,3.13-1.28c1.27,0,2.49,0.51,3.39,1.42C16.59,8.09,16.64,11,14.89,12.77z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M10.5-0.01C4.7-0.01,0,4.7,0,10.49s4.7,10.5,10.5,10.5S21,16.29,21,10.49C20.99,4.7,16.3-0.01,10.5-0.01z M10.5,19.74c-5.11,0-9.25-4.15-9.25-9.25s4.14-9.26,9.25-9.26s9.25,4.15,9.25,9.25C19.75,15.61,15.61,19.74,10.5,19.74z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M14.74,6.25C12.9,4.41,9.98,4.35,8.23,6.1c-3.16,3.17-2.14,8.81-2.14,8.81s5.64,1.02,8.81-2.14 C16.64,11,16.59,8.09,14.74,6.25z M12.47,10.34l-0.91,1.87l-0.9-1.87L8.8,9.43l1.86-0.9l0.9-1.87l0.91,1.87l1.86,0.9L12.47,10.34z"/%3E %3Cpolygon class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" points="14.33,9.43 12.47,10.34 11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 "/%3E%3C/g%3E%3C/svg%3E\');' From cef04d2918a75c19cf723121aed414a0980247d3 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Tue, 30 Dec 2025 16:07:35 -0700 Subject: [PATCH 02/13] Initial TS set up --- package-lock.json | 1567 ++++++++++-------------------- package.json | 5 + src/types/README.md | 63 ++ src/types/components/common.d.ts | 41 + src/types/core/config.d.ts | 177 ++++ src/types/core/data.d.ts | 227 +++++ src/types/core/events.d.ts | 136 +++ src/types/core/graph-div.d.ts | 120 +++ src/types/core/layout.d.ts | 230 +++++ src/types/index.d.ts | 20 + src/types/lib/common.d.ts | 108 ++ src/types/plots/common.d.ts | 37 + src/types/traces/common.d.ts | 73 ++ tsconfig.json | 69 ++ 14 files changed, 1806 insertions(+), 1067 deletions(-) create mode 100644 src/types/README.md create mode 100644 src/types/components/common.d.ts create mode 100644 src/types/core/config.d.ts create mode 100644 src/types/core/data.d.ts create mode 100644 src/types/core/events.d.ts create mode 100644 src/types/core/graph-div.d.ts create mode 100644 src/types/core/layout.d.ts create mode 100644 src/types/index.d.ts create mode 100644 src/types/lib/common.d.ts create mode 100644 src/types/plots/common.d.ts create mode 100644 src/types/traces/common.d.ts create mode 100644 tsconfig.json diff --git a/package-lock.json b/package-lock.json index 8c59c40810b..f1f6839a408 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,6 +57,8 @@ "@biomejs/biome": "2.2.0", "@plotly/mathjax-v2": "npm:mathjax@2.7.5", "@plotly/mathjax-v3": "npm:mathjax@^3.2.2", + "@types/d3": "3.5.34", + "@types/node": "^24.10.0", "amdefine": "^1.0.1", "assert": "^2.1.0", "browserify-transform-tools": "^1.7.0", @@ -107,6 +109,7 @@ "through2": "^4.0.2", "transform-loader": "^0.2.4", "true-case-path": "^2.2.1", + "typescript": "^5.9.3", "virtual-webgl": "^1.0.7" }, "engines": { @@ -201,74 +204,6 @@ "@biomejs/cli-win32-x64": "2.2.0" } }, - "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.0.tgz", - "integrity": "sha512-zKbwUUh+9uFmWfS8IFxmVD6XwqFcENjZvEyfOxHs1epjdH3wyyMQG80FGDsmauPwS2r5kXdEM0v/+dTIA9FXAg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-darwin-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.0.tgz", - "integrity": "sha512-+OmT4dsX2eTfhD5crUOPw3RPhaR+SKVspvGVmSdZ9y9O/AgL8pla6T4hOn1q+VAFBHuHhsdxDRJgFCSC7RaMOw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.0.tgz", - "integrity": "sha512-6eoRdF2yW5FnW9Lpeivh7Mayhq0KDdaDMYOJnH9aT02KuSIX5V1HmWJCQQPwIQbhDh68Zrcpl8inRlTEan0SXw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.0.tgz", - "integrity": "sha512-egKpOa+4FL9YO+SMUMLUvf543cprjevNc3CAgDNFLcjknuNMcZ0GLJYa3EGTCR2xIkIUJDVneBV3O9OcIlCEZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, "node_modules/@biomejs/cli-linux-x64": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.0.tgz", @@ -303,40 +238,6 @@ "node": ">=14.21.3" } }, - "node_modules/@biomejs/cli-win32-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.0.tgz", - "integrity": "sha512-n9a1/f2CwIDmNMNkFs+JI0ZjFnMO0jdOyGNtihgUNFnlmd84yIYY2KMTBmMV58ZlVHjgmY5Y6E1hVTnSRieggA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-win32-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.0.tgz", - "integrity": "sha512-Nawu5nHjP/zPKTIryh2AavzTc/KEg4um/MxWdXW0A6P/RZOyIpa7+QSjeXwAwX/utJGaCoXRPWtF3m5U/bB3Ww==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.21.3" - } - }, "node_modules/@choojs/findup": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@choojs/findup/-/findup-0.2.1.tgz", @@ -357,6 +258,30 @@ "node": ">=0.1.90" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@csstools/color-helpers": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", @@ -485,262 +410,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/linux-x64": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", @@ -757,134 +426,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -953,20 +494,33 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "peer": true, "engines": { @@ -974,14 +528,14 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" } }, "node_modules/@jridgewell/sourcemap-codec": { @@ -991,9 +545,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "peer": true, "dependencies": { @@ -1326,6 +880,34 @@ "node": ">=18" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, "node_modules/@turf/area": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@turf/area/-/area-7.1.0.tgz", @@ -1416,36 +998,18 @@ "@types/node": "*" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "node_modules/@types/d3": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.34.tgz", + "integrity": "sha512-2Ub7NdmaSLviC8lwRGt/7use4LBdLQi7iPEkM97yGKrbmCUqepOgOrGJLi1jPdR0/IIwBDpIbtOgdAOJWWXC+Q==", "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } + "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/@types/geojson": { @@ -1462,11 +1026,10 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true }, "node_modules/@types/karma": { "version": "1.7.8", @@ -1494,10 +1057,14 @@ } }, "node_modules/@types/node": { - "version": "14.11.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.2.tgz", - "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==", - "dev": true + "version": "24.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz", + "integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } }, "node_modules/@types/pbf": { "version": "3.0.5", @@ -1554,9 +1121,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1564,12 +1131,12 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.2" + "brace-expansion": "^2.0.1" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -1673,178 +1240,163 @@ "dev": true }, "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, - "license": "Apache-2.0", "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, @@ -1853,7 +1405,6 @@ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, - "license": "BSD-3-Clause", "peer": true }, "node_modules/@xtuc/long": { @@ -1861,7 +1412,6 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true, - "license": "Apache-2.0", "peer": true }, "node_modules/abs-svg-path": { @@ -1913,6 +1463,32 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk/node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/agent-base": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", @@ -1924,11 +1500,10 @@ } }, "node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1940,48 +1515,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "peer": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "dev": true, - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "peer": true - }, "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -2046,6 +1579,13 @@ "integrity": "sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==", "dev": true }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, "node_modules/arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", @@ -2172,24 +1712,10 @@ "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "dev": true, - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.13", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.13.tgz", - "integrity": "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw==", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, "engines": { - "node": ">=6.0.0" + "node": "^4.5.0 || >= 5.9" } }, "node_modules/big.js": { @@ -2327,9 +1853,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", - "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -2360,9 +1886,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "funding": [ { @@ -2378,14 +1904,12 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "peer": true, "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -2531,9 +2055,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001784", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001784.tgz", - "integrity": "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw==", + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", "dev": true, "funding": [ { @@ -2549,7 +2073,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "CC-BY-4.0", "peer": true }, "node_modules/canvas": { @@ -3060,6 +2583,13 @@ "resolved": "https://registry.npmjs.org/country-regex/-/country-regex-1.1.0.tgz", "integrity": "sha1-UcMz3N8Sknt+XuucEKyBEqYSCJY=" }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -3737,6 +3267,16 @@ "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", "dev": true }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -3928,11 +3468,10 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.5.330", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.330.tgz", - "integrity": "sha512-jFNydB5kFtYUobh4IkWUnXeyDbjf/r9gcUEXe1xcrcUxIGfTdzPXA+ld6zBRbwvgIGVzDll/LTIiDztEtckSnA==", + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.6.tgz", + "integrity": "sha512-jwXWsM5RPf6j9dPYzaorcBSUg6AiqocPEyMpkchkvntaH9HGfOOMZwxMJjDY/XEs3T5dM7uyH1VhRMkqUU9qVw==", "dev": true, - "license": "ISC", "peer": true }, "node_modules/elementary-circuits-directed-graph": { @@ -4006,14 +3545,13 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", - "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" + "tapable": "^2.2.0" }, "engines": { "node": ">=10.13.0" @@ -4083,11 +3621,10 @@ "dev": true }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", + "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/es-object-atoms": { @@ -4239,11 +3776,10 @@ } }, "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -4511,23 +4047,6 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "peer": true - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -4651,9 +4170,9 @@ } }, "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", "dev": true }, "node_modules/flatten-vertex-data": { @@ -4665,9 +4184,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", - "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -4675,7 +4194,6 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], - "license": "MIT", "engines": { "node": ">=4.0" }, @@ -4824,20 +4342,6 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -5053,13 +4557,12 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "license": "BSD-2-Clause", "peer": true }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5067,12 +4570,12 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.2" + "brace-expansion": "^2.0.1" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -5708,9 +5211,9 @@ } }, "node_modules/immutable": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.8.tgz", - "integrity": "sha512-d/Ld9aLbKpNwyl0KiM2CT1WYvkitQ1TSvmRtkcV8FKStiDoA7Slzgjmb/1G2yhKM1p0XeNOieaTbFZmU1d3Xuw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", "dev": true }, "node_modules/inflight": { @@ -6703,18 +6206,13 @@ } }, "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" } }, "node_modules/loader-utils": { @@ -6732,9 +6230,9 @@ } }, "node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "node_modules/lodash.merge": { @@ -6965,6 +6463,13 @@ "sourcemap-codec": "^1.4.4" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, "node_modules/map-limit": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz", @@ -7288,9 +6793,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -7414,9 +6919,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -7424,7 +6929,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -7523,11 +7027,10 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/node-source-walk": { @@ -7590,9 +7093,9 @@ } }, "node_modules/npm-link-check/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7619,9 +7122,9 @@ } }, "node_modules/npm-link-check/node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -8094,18 +7597,16 @@ "integrity": "sha1-X3yysfIabh6ISgyHhVqko3NhEHs=" }, "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true }, "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.6" }, @@ -8114,9 +7615,9 @@ } }, "node_modules/pixelmatch": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-7.1.0.tgz", - "integrity": "sha512-1wrVzJ2STrpmONHKBy228LM1b84msXDUoAzVEl0R8Mz4Ce6EPr+IVtxm8+yvrqLYMHswREkjYFaMxnyGnaY3Ng==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-7.2.0.tgz", + "integrity": "sha512-xhcb4yHu9sM/G7foGzoLtXYcC0zHEaOXXjRKhGup0fw78Nf2Tkiapv4EQyMzrbcmQPsllAI7DbFY2UT7PlI9Pg==", "dev": true, "license": "ISC", "dependencies": { @@ -8156,9 +7657,9 @@ "integrity": "sha512-ziHW/02J0XuNuUtmidBc6GXE8YohYydp3DWPWXYsd7O721TjcmN+k6ezjdwkDqep+gnWnFY+yqZHvzElra2oCg==" }, "node_modules/postcss": { - "version": "8.5.12", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.12.tgz", - "integrity": "sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==", + "version": "8.4.41", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "dev": true, "funding": [ { @@ -8174,11 +7675,10 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -8403,9 +7903,9 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/protocol-buffers-schema": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz", - "integrity": "sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.4.0.tgz", + "integrity": "sha512-G/2kcamPF2S49W5yaMGdIpkG6+5wZF0fzBteLKgEHjbNzqjZQ85aAs1iJGto31EJaSTkNvHs5IXuHSaTLWBAiA==" }, "node_modules/pump": { "version": "3.0.2", @@ -8437,9 +7937,9 @@ } }, "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8471,6 +7971,16 @@ "performance-now": "^2.1.0" } }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -8804,16 +8314,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/requirejs": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.7.tgz", @@ -9091,6 +8591,16 @@ "semver": "bin/semver.js" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -9346,44 +8856,18 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", - "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dev": true, - "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.4.1" + "debug": "~4.3.1" }, "engines": { "node": ">=10.0.0" } }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/sort-asc": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", @@ -9426,11 +8910,10 @@ } }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -9845,17 +9328,12 @@ "dev": true }, "node_modules/tapable": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.2.tgz", - "integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" } }, "node_modules/tar-fs": { @@ -9968,16 +9446,17 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", - "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "terser": "^5.31.1" + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" @@ -10002,10 +9481,11 @@ } }, "node_modules/terser-webpack-plugin/node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "license": "MIT", "peer": true, "bin": { "acorn": "bin/acorn" @@ -10014,72 +9494,15 @@ "node": ">=0.4.0" } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "dev": true, - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "peer": true - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.1.tgz", - "integrity": "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==", + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", + "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==", "dev": true, "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -10326,6 +9749,63 @@ "node": ">=18" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", @@ -10414,9 +9894,9 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -10458,6 +9938,13 @@ "node": "*" } }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -10536,9 +10023,9 @@ "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=" }, "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "funding": [ { @@ -10554,11 +10041,10 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "peer": true, "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -10614,6 +10100,13 @@ "node": ">= 0.4.0" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -10681,11 +10174,10 @@ } }, "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -10727,38 +10219,35 @@ } }, "node_modules/webpack": { - "version": "5.105.4", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.4.tgz", - "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.16.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.20.0", - "es-module-lexer": "^2.0.0", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", + "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.17", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.4" + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" }, "bin": { "webpack": "bin/webpack.js" @@ -10777,20 +10266,19 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", - "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=10.13.0" } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "peer": true, @@ -10801,50 +10289,14 @@ "node": ">=0.4.0" } }, - "node_modules/webpack/node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "acorn": "^8.14.0" - } - }, - "node_modules/webpack/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/webpack/node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "dev": true, - "license": "MIT", "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, "peerDependencies": { - "ajv": "^8.8.2" + "acorn": "^8" } }, "node_modules/webpack/node_modules/eslint-scope": { @@ -10861,35 +10313,6 @@ "node": ">=8.0.0" } }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -11224,6 +10647,16 @@ "engines": { "node": ">=10" } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } } } } diff --git a/package.json b/package.json index fb04c203ba6..106d2217cb4 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,8 @@ "cibuild": "npm run empty-dist && npm run preprocess && node tasks/cibundle.mjs", "lint": "npx @biomejs/biome lint", "lint-fix": "npx @biomejs/biome format ./test/image/mocks --write; npx @biomejs/biome lint --write || true", + "typecheck": "tsc --noEmit", + "typecheck:watch": "tsc --noEmit --watch", "pretest": "node tasks/pretest.js", "test-jasmine": "karma start test/jasmine/karma.conf.js", "test-mock": "node tasks/test_mock.mjs", @@ -115,6 +117,8 @@ "@biomejs/biome": "2.2.0", "@plotly/mathjax-v2": "npm:mathjax@2.7.5", "@plotly/mathjax-v3": "npm:mathjax@^3.2.2", + "@types/d3": "3.5.34", + "@types/node": "^24.10.0", "amdefine": "^1.0.1", "assert": "^2.1.0", "browserify-transform-tools": "^1.7.0", @@ -165,6 +169,7 @@ "through2": "^4.0.2", "transform-loader": "^0.2.4", "true-case-path": "^2.2.1", + "typescript": "^5.9.3", "virtual-webgl": "^1.0.7" }, "overrides": { diff --git a/src/types/README.md b/src/types/README.md new file mode 100644 index 00000000000..a4071c340e2 --- /dev/null +++ b/src/types/README.md @@ -0,0 +1,63 @@ +# Types Directory + +Centralized TypeScript type definitions for plotly.js. + +## Quick Import + +```typescript +// Import from main index (recommended) +import type { GraphDiv, Layout, PlotData } from '../types'; + +// Or use path alias +import type { GraphDiv } from '@types'; +``` + +## Directory Structure + +``` +types/ +├── index.d.ts # Main export - import from here +├── core/ # Core Plotly types (GraphDiv, Layout, Data, Config, Events) +├── traces/ # Trace-specific types +├── components/ # Component-specific types +├── plots/ # Plot-specific types +└── lib/ # Utility types +``` + +## Most Common Types + +### GraphDiv +```typescript +import type { GraphDiv } from '../types'; + +function draw(gd: GraphDiv): void { + const layout = gd._fullLayout; + const data = gd._fullData; +} +``` + +### Layout +```typescript +import type { Layout } from '../types'; + +function updateLayout(layout: Partial): void { + layout.title = 'New Title'; +} +``` + +### PlotData (Traces) +```typescript +import type { PlotData, ScatterTrace } from '../types'; + +function processTrace(trace: PlotData): void { + if (trace.type === 'scatter') { + const scatter = trace as ScatterTrace; + } +} +``` + +## Adding New Types + +1. Create file in appropriate subdirectory +2. Export from `index.d.ts` +3. Use in your TypeScript files diff --git a/src/types/components/common.d.ts b/src/types/components/common.d.ts new file mode 100644 index 00000000000..6d5d7aed844 --- /dev/null +++ b/src/types/components/common.d.ts @@ -0,0 +1,41 @@ +/** + * Common component-related types + * + * Types shared across different component modules + */ + +/** + * Component module interface + */ +export interface ComponentModule { + includeBasePlot?: (basePlotModule: string) => void; + layoutAttributes?: any; + name: string; + supplyLayoutDefaults?: (layoutIn: any, layoutOut: any, fullData: any) => void; +} + +/** + * Drawing options (used by many components) + */ +export interface DrawingOptions { + duration?: number; + ease?: string; + redraw?: boolean; +} + +/** + * SVG text utilities return type + */ +export interface TextBBox { + bottom: number; + height: number; + left: number; + right: number; + top: number; + width: number; +} + +/** + * Color with alpha + */ +export type ColorString = string; diff --git a/src/types/core/config.d.ts b/src/types/core/config.d.ts new file mode 100644 index 00000000000..a3a9b5e48ae --- /dev/null +++ b/src/types/core/config.d.ts @@ -0,0 +1,177 @@ +/** + * Config types + * + * Defines the structure of Plotly config options. + */ + +/** + * User-provided configuration for Plotly + */ +export interface Config { + /** + * Whether the plot should resize on window resize + */ + autosizable?: boolean; + + /** + * Display Plotly logo on mode bar + */ + displaylogo?: boolean; + + /** + * Display the mode bar + */ + displayModeBar?: boolean | 'hover'; + + /** + * What happens on double click + */ + doubleClick?: 'reset' | 'autosize' | 'reset+autosize' | false; + + /** + * Allow plot to be edited + */ + editable?: boolean; + + /** + * What can be edited + */ + edits?: Partial; + + /** + * Whether to fill the parent container + */ + fillFrame?: boolean; + + /** + * Margin around the plot when fillFrame is true + */ + frameMargins?: number; + + /** + * Text for the "Edit in Chart Studio" link + */ + linkText?: string; + + /** + * Locale for formatting + */ + locale?: string; + + /** + * Custom locale definitions + */ + locales?: { [locale: string]: any }; + + /** + * Mapbox access token + */ + mapboxAccessToken?: string; + + /** + * Custom mode bar buttons configuration + */ + modeBarButtons?: any; + + /** + * Mode bar buttons to add + */ + modeBarButtonsToAdd?: any[]; + + /** + * Mode bar buttons to remove + */ + modeBarButtonsToRemove?: string[]; + + /** + * Pixel ratio for WebGL plots + */ + plotGlPixelRatio?: number; + + /** + * Base URL for plotly server + */ + plotlyServerURL?: string; + + /** + * Number of operations that can be queued + */ + queueLength?: number; + + /** + * Whether to resize on window resize (alternative) + */ + responsive?: boolean; + + /** + * Enable scroll zoom + */ + scrollZoom?: boolean; + + /** + * Send data to Chart Studio + */ + sendData?: boolean; + + /** + * Background color setting function + */ + setBackground?: string | ((gd: any) => void); + + /** + * Show "Edit in Chart Studio" link + */ + showLink?: boolean; + + /** + * Show tips on first hover + */ + showTips?: boolean; + + /** + * Make the chart static - no interactivity + */ + staticPlot?: boolean; + + /** + * Options for the "Download plot as PNG" button + */ + toImageButtonOptions?: Partial; + + /** + * URL for topojson files + */ + topojsonURL?: string; + + /** + * Add watermark to images + */ + watermark?: boolean; +} + +/** + * Configuration for what can be edited + */ +export interface ConfigEdits { + annotationPosition?: boolean; + annotationTail?: boolean; + annotationText?: boolean; + axisTitleText?: boolean; + colorbarPosition?: boolean; + colorbarTitleText?: boolean; + legendPosition?: boolean; + legendText?: boolean; + shapePosition?: boolean; + titleText?: boolean; +} + +/** + * Options for the "Download plot" button + */ +export interface ToImageButtonOptions { + format?: 'png' | 'svg' | 'jpeg' | 'webp'; + filename?: string; + height?: number; + width?: number; + scale?: number; +} diff --git a/src/types/core/data.d.ts b/src/types/core/data.d.ts new file mode 100644 index 00000000000..9eab5917a16 --- /dev/null +++ b/src/types/core/data.d.ts @@ -0,0 +1,227 @@ +/** + * Data/Trace types + * + * Defines the structure of Plotly data traces. + * This is a union of all possible trace types. + */ + +import type { Dash, ColorScale } from '../lib/common'; + +/** + * All supported plot/trace types in plotly.js + */ +export type PlotType = + | "bar" + | "barpolar" + | "box" + | "candlestick" + | "carpet" + | "choropleth" + | "choroplethmap" + | "choroplethmapbox" + | "cone" + | "contour" + | "contourcarpet" + | "densitymap" + | "densitymapbox" + | "funnel" + | "funnelarea" + | "heatmap" + | "histogram" + | "histogram2d" + | "histogram2dcontour" + | "icicle" + | "image" + | "indicator" + | "isosurface" + | "mesh3d" + | "ohlc" + | "parcats" + | "parcoords" + | "pie" + | "sankey" + | "scatter" + | "scatter3d" + | "scattercarpet" + | "scattergeo" + | "scattergl" + | "scattermap" + | "scattermapbox" + | "scatterpolar" + | "scatterpolargl" + | "scattersmith" + | "scatterternary" + | "splom" + | "streamtube" + | "sunburst" + | "surface" + | "table" + | "treemap" + | "violin" + | "volume" + | "waterfall"; + +/** + * Common properties shared by all trace types + */ +export interface TraceBase { + customdata?: any[]; + hoverinfo?: string; + hoverlabel?: Partial; + hovertemplate?: string | string[]; + ids?: string[]; + legendgroup?: string; + legendgrouptitle?: any; + meta?: any; + name?: string; + opacity?: number; + selectedpoints?: any; + showlegend?: boolean; + type?: PlotType; + uid?: string; + visible?: boolean | 'legendonly'; + xaxis?: string; + yaxis?: string; + [key: string]: any; +} + +/** + * User-provided plot data (trace) + * This will be a union of all specific trace types + */ +export type PlotData = TraceBase & ( + | BarTrace + | LineTrace + | ScatterTrace + // Add more trace types as you convert them + | GenericTrace +); + +/** + * Fully processed plot data with defaults applied (internal use) + */ +export interface FullData extends PlotData { + _expandedIndex?: number; + _fullInput?: any; + _indexToPoints?: { [key: number]: number[] }; + _input?: any; + _length?: number; + _module?: any; + index?: number; +} + +/** + * Generic trace for gradual migration + * Use specific trace types when available + */ +export interface GenericTrace extends TraceBase { + x?: any[]; + y?: any[]; + z?: any[]; + [key: string]: any; +} + +/** + * Scatter trace + */ +export interface ScatterTrace extends TraceBase { + connectgaps?: boolean; + fill?: 'none' | 'tozeroy' | 'tozerox' | 'tonexty' | 'tonextx' | 'toself' | 'tonext'; + fillcolor?: string; + line?: Partial; + marker?: Partial; + mode?: 'lines' | 'markers' | 'lines+markers' | 'none' | 'text' | 'lines+text' | 'markers+text' | 'lines+markers+text'; + text?: string | string[]; + textfont?: any; + textposition?: string | string[]; + type: 'scatter'; + x?: number[] | string[]; + y?: number[] | string[]; +} + +/** + * Bar trace + */ +export interface BarTrace extends TraceBase { + base?: number | number[]; + marker?: Partial; + offset?: number | number[]; + orientation?: 'v' | 'h'; + text?: string | string[]; + textangle?: number; + textposition?: string; + type: 'bar'; + width?: number | number[]; + x?: number[] | string[]; + y?: number[] | string[]; +} + +/** + * Line-only trace (simplified scatter) + */ +export interface LineTrace extends TraceBase { + line?: Partial; + mode: 'lines'; + type: 'scatter'; + x?: number[] | string[]; + y?: number[] | string[]; +} + +/** + * Marker configuration (used by many traces) + */ +export interface Marker { + autocolorscale?: boolean; + cauto?: boolean; + cmax?: number; + cmid?: number; + cmin?: number; + color?: string | string[] | number[]; + coloraxis?: string; + colorbar?: any; + colorscale?: string | any[][]; + line?: Partial; + opacity?: number | number[]; + reversescale?: boolean; + showscale?: boolean; + size?: number | number[]; + symbol?: string | string[]; +} + +/** + * Marker line (outline) + */ +export interface MarkerLine { + autocolorscale?: boolean; + cauto?: boolean; + cmax?: number; + cmid?: number; + cmin?: number; + color?: string | string[]; + colorscale?: string | any[][]; + reversescale?: boolean; + width?: number | number[]; +} + +/** + * Line configuration (used by many traces) + */ +export interface Line { + color?: string; + dash?: Dash; + shape?: 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv'; + simplify?: boolean; + smoothing?: number; + width?: number; +} + +/** + * Hover label configuration + */ +export interface HoverLabel { + align?: 'left' | 'right' | 'auto'; + bgcolor?: string | string[]; + bordercolor?: string | string[]; + font?: any; + namelength?: number | number[]; +} diff --git a/src/types/core/events.d.ts b/src/types/core/events.d.ts new file mode 100644 index 00000000000..a270e91efdd --- /dev/null +++ b/src/types/core/events.d.ts @@ -0,0 +1,136 @@ +/** + * Event types + * + * Defines the structure of Plotly events and event data. + */ + +/** + * Common point data structure returned in events + */ +export interface PlotlyEventPoint { + /** + * Curve number (trace index) + */ + curveNumber: number; + + /** + * Point number within the trace + */ + pointNumber: number; + + /** + * Point index (for calculated data) + */ + pointIndex?: number; + + /** + * X value + */ + x?: any; + + /** + * Y value + */ + y?: any; + + /** + * Z value (for 3D plots) + */ + z?: any; + + /** + * Custom data + */ + customdata?: any; + + /** + * Full data for this trace + */ + data?: any; + + /** + * Full data for all traces + */ + fullData?: any; + + /** + * Additional properties + */ + [key: string]: any; +} + +/** + * Hover event data + */ +export interface PlotlyHoverEvent { + points: PlotlyEventPoint[]; + event: MouseEvent; +} + +/** + * Click event data + */ +export interface PlotlyClickEvent { + points: PlotlyEventPoint[]; + event: MouseEvent; +} + +/** + * Selection event data + */ +export interface PlotlySelectionEvent { + points: PlotlyEventPoint[]; + range?: any; + lassoPoints?: any; +} + +/** + * Relayout event data (when layout changes) + */ +export interface PlotlyRelayoutEvent { + [key: string]: any; +} + +/** + * Restyle event data (when trace style changes) + */ +export interface PlotlyRestyleEvent { + data: any[]; + traces: number[]; +} + +/** + * All Plotly event names + */ +export type PlotlyEventName = + | 'plotly_afterexport' + | 'plotly_afterplot' + | 'plotly_animated' + | 'plotly_animatingframe' + | 'plotly_animationinterrupted' + | 'plotly_autosize' + | 'plotly_beforeexport' + | 'plotly_beforehover' + | 'plotly_buttonclicked' + | 'plotly_click' + | 'plotly_clickannotation' + | 'plotly_deselect' + | 'plotly_doubleclick' + | 'plotly_framework' + | 'plotly_hover' + | 'plotly_legendclick' + | 'plotly_legenddoubleclick' + | 'plotly_redraw' + | 'plotly_relayout' + | 'plotly_restyle' + | 'plotly_selected' + | 'plotly_selecting' + | 'plotly_sliderchange' + | 'plotly_sliderend' + | 'plotly_sliderstart' + | 'plotly_sunburstclick' + | 'plotly_transitioning' + | 'plotly_transitioninterrupted' + | 'plotly_treemapclick' + | 'plotly_unhover' + | 'plotly_webglcontextlost'; diff --git a/src/types/core/graph-div.d.ts b/src/types/core/graph-div.d.ts new file mode 100644 index 00000000000..7bdf1d81f29 --- /dev/null +++ b/src/types/core/graph-div.d.ts @@ -0,0 +1,120 @@ +/** + * Core GraphDiv types + * + * The `gd` parameter appears throughout the codebase and represents + * the graph div element with plotly-specific properties attached. + */ + +import type { Config } from './config'; +import type { FullData, PlotData } from './data'; +import type { FullLayout, Layout } from './layout'; + +/** + * The main graph div element that Plotly operates on. + * This is an HTMLDivElement with additional Plotly-specific properties. + * + * Commonly referred to as `gd` in the codebase. + */ +export interface GraphDiv extends HTMLDivElement { + /** + * Graph dimensions and margins + */ + _context?: GraphContext; + + /** + * Is the plot currently being edited? + */ + _editing?: boolean; + + /** + * Fully processed data traces (internal use) + */ + _fullData?: FullData[]; + + /** + * Fully processed layout (internal use) + */ + _fullLayout?: FullLayout; + + /** + * Has the plot been initialized? + */ + _initialized?: boolean; + + /** + * Plotly framework metadata + */ + _promises?: Promise[]; + + /** + * Current transaction ID for queuing operations + */ + _transitionData?: any; + + /** + * Is the plot transitioning? + */ + _transitioning?: boolean; + + /** + * Calculated data (internal use) + */ + calcdata?: any[]; + + /** + * User-provided configuration options + */ + config?: Partial; + + /** + * User-provided data traces + */ + data?: PlotData[]; + + /** + * Plotly-specific event emitter + */ + emit?: (event: string, ...args: any[]) => void; + + /** + * User-provided layout configuration + */ + layout?: Partial; + + // Add more as you discover them during migration + [key: string]: any; +} + +/** + * Graph context containing environment info + */ +export interface GraphContext { + autosizable?: boolean; + displaylogo?: boolean; + displayModeBar?: boolean | 'hover'; + doubleClick?: string | false; + editable?: boolean; + edits?: any; + fillFrame?: boolean; + frameMargins?: number; + linkText?: string; + locale?: string; + locales?: any; + mapboxAccessToken?: string; + modeBarButtons?: any; + modeBarButtonsToAdd?: any[]; + modeBarButtonsToRemove?: string[]; + plotGlPixelRatio?: number; + plotlyServerURL?: string; + queueLength?: number; + responsive?: boolean; + scrollZoom?: boolean; + sendData?: boolean; + setBackground?: string | Function; + showLink?: boolean; + showTips?: boolean; + staticPlot?: boolean; + toImageButtonOptions?: any; + topojsonURL?: string; + watermark?: boolean; +} diff --git a/src/types/core/layout.d.ts b/src/types/core/layout.d.ts new file mode 100644 index 00000000000..bc8b245e35e --- /dev/null +++ b/src/types/core/layout.d.ts @@ -0,0 +1,230 @@ +/** + * Layout types + * + * Defines the structure of Plotly layout objects. + * Start with common properties and expand as needed. + */ + +import type { Selection } from '@types/d3' +import type { AxisType, Dash } from '../lib/common'; + +/** + * User-provided layout configuration + */ +export interface Layout { + autosize?: boolean; + dragmode?: 'zoom' | 'pan' | 'select' | 'lasso' | 'orbit' | 'turntable' | false; + font?: Partial; + height?: number; + hovermode?: 'closest' | 'x' | 'y' | 'x unified' | 'y unified' | false; + legend?: Partial; + margin?: Partial; + paper_bgcolor?: string; + plot_bgcolor?: string; + showlegend?: boolean; + template?: any; + title?: string | Partial; + width?: number; + xaxis?: Partial; + yaxis?: Partial; + + // Multiple axes support (xaxis2, yaxis3, etc.) + [key: string]: any; +} + +/** + * Fully processed layout with all defaults applied (internal use) + */ +export interface FullLayout extends Layout { + _modules?: any[]; + _basePlotModules?: any[]; + _plots?: { [key: string]: any }; + _subplot?: any[]; + _subplots?: SubplotInfo; + _size?: LayoutSize; + _legends?: string[]; + _infolayer?: Selection; + _zoomlayer?: Selection; + _paperdiv?: Selection; + _glcontainer?: Selection; + _calcInverseTransform?: (gd: any) => void; + _invTransform?: any; + _uid?: string; + _initialAutoSizeIsDone?: boolean; + + // Hover state + _hoverlayer?: any; + _hoverdata?: any[]; + + // Modebar + _modeBar?: any; + + // Grid + grid?: any; + + // Computed properties + _pushmargin?: { [key: string]: any }; + _basePlotModules?: any[]; + + [key: string]: any; +} + +/** + * Layout title configuration + */ +export interface LayoutTitle { + 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; +} + +/** + * Layout margin configuration + */ +export interface LayoutMargin { + l: number; + r: number; + t: number; + b: number; + pad: number; + autoexpand?: boolean; +} + +/** + * Font configuration (used throughout) + */ +export interface Font { + color: string; + family: string; + size: number; + style?: 'normal' | 'italic'; + variant?: string; + weight?: number | string; +} + +/** + * Legend configuration + */ +export interface Legend { + bgcolor?: string; + bordercolor?: string; + borderwidth?: number; + font?: Partial; + itemclick?: 'toggle' | 'toggleothers' | false; + itemdoubleclick?: 'toggle' | 'toggleothers' | false; + itemsizing?: 'trace' | 'constant'; + itemwidth?: number; + orientation?: 'v' | 'h'; + title?: Partial; + tracegroupgap?: number; + traceorder?: string; + valign?: 'top' | 'middle' | 'bottom'; + x?: number; + xanchor?: 'auto' | 'left' | 'center' | 'right'; + y?: number; + yanchor?: 'auto' | 'top' | 'middle' | 'bottom'; +} + +/** + * Legend title configuration + */ +export interface LegendTitle { + font?: Partial; + side?: 'top' | 'left' | 'top left'; + text: string; +} + +/** + * Layout axis configuration + */ +export interface LayoutAxis { + title?: string | Partial; + type?: AxisType; + autorange?: boolean | 'reversed'; + range?: [number | string, number | string]; + fixedrange?: boolean; + showgrid?: boolean; + showline?: boolean; + showticklabels?: boolean; + ticks?: '' | 'outside' | 'inside'; + tickmode?: 'auto' | 'linear' | 'array'; + tickvals?: any[]; + ticktext?: string[]; + tickangle?: number; + tickfont?: Partial; + zeroline?: boolean; + zerolinecolor?: string; + zerolinewidth?: number; + gridcolor?: string; + gridwidth?: number; + linecolor?: string; + linewidth?: number; + mirror?: boolean | 'ticks' | 'all' | 'allticks'; + anchor?: string; + side?: 'top' | 'bottom' | 'left' | 'right'; + overlaying?: string; + domain?: [number, number]; + position?: number; + + // Internal properties + _id?: string; + _name?: string; + _mainAxis?: boolean; + _anchorAxis?: any; + + [key: string]: any; +} + +/** + * Axis title configuration + */ +export interface AxisTitle { + font?: Partial; + standoff?: number; + text: string; +} + +/** + * Padding configuration + */ +export interface Padding { + b: number; + l: number; + r: number; + t: number; +} + +/** + * Layout size information (internal) + */ +export interface LayoutSize { + b: number; + h: number; + l: number; + p: number; + r: number; + t: number; + w: number; +} + +/** + * Subplot information (internal) + */ +export interface SubplotInfo { + [key: string]: string[] | undefined; + cartesian?: string[]; + geo?: string[]; + gl2d?: string[]; + map?: string[]; + mapbox?: string[]; + pie?: string[]; + polar?: string[]; + sankey?: string[]; + ternary?: string[]; +} diff --git a/src/types/index.d.ts b/src/types/index.d.ts new file mode 100644 index 00000000000..74a2d0da521 --- /dev/null +++ b/src/types/index.d.ts @@ -0,0 +1,20 @@ +/** + * Central type definitions for plotly.js + * + * This file exports all shared types from subdirectories. + * Import from here for convenience: + * + * @example + * import type { GraphDiv, Layout, PlotData } from '../types'; + */ + +// Core types +export * from './components/common'; +export * from './core/config'; +export * from './core/data'; +export * from './core/events'; +export * from './core/graph-div'; +export * from './core/layout'; +export * from './lib/common'; +export * from './plots/common'; +export * from './traces/common'; diff --git a/src/types/lib/common.d.ts b/src/types/lib/common.d.ts new file mode 100644 index 00000000000..7d1da324dad --- /dev/null +++ b/src/types/lib/common.d.ts @@ -0,0 +1,108 @@ +/** + * Common library utility types + * + * Types for Lib utilities and helpers + */ + +/** + * Coercion function signature + */ +export type CoerceFn = (attr: string, dflt?: any) => any; + +/** + * Nested property path + */ +export type PropertyPath = string | string[]; + +/** + * Color scale + */ +export type ColorScale = string | string[] | Array<[number, string]>; + +/** + * Date format string + */ +export type DateFormat = string; + +/** + * Single data value + */ +export type Datum = string | number | Date | null; + +/** + * Line dash styles + */ +export type Dash = 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot'; + +/** + * Supported calendar systems + */ +export type Calendar = + | 'chinese' + | 'coptic' + | 'discworld' + | 'ethiopian' + | 'gregorian' + | 'hebrew' + | 'islamic' + | 'jalali' + | 'julian' + | 'mayan' + | 'nanakshahi' + | 'nepali' + | 'persian' + | 'taiwan' + | 'thai' + | 'ummalqura'; + +/** + * Axis type + */ +export type AxisType = '-' | 'category' | 'date' | 'linear' | 'log' | 'multicategory'; + +/** + * Numeric array + */ +export type NumericArray = number[] | Float32Array | Float64Array; + +/** + * Type that can be a single value or an array + */ +export type Arrayable = T | T[]; + +/** + * Rectangle bounds + */ +export interface Rect { + left: number; + right: number; + top: number; + bottom: number; + width?: number; + height?: number; +} + +/** + * Point in 2D space + */ +export interface Point2D { + x: number; + y: number; +} + +/** + * Point in 3D space + */ +export interface Point3D extends Point2D { + z: number; +} + +/** + * RGBA color + */ +export interface RGBAColor { + r: number; + g: number; + b: number; + a: number; +} diff --git a/src/types/plots/common.d.ts b/src/types/plots/common.d.ts new file mode 100644 index 00000000000..2b14e936922 --- /dev/null +++ b/src/types/plots/common.d.ts @@ -0,0 +1,37 @@ +/** + * Common plot-related types + * + * Types shared across different plot modules + */ + +/** + * Plot info structure (internal) + */ +export interface PlotInfo { + id: string; + xaxis: any; + yaxis: any; + domain?: { x: [number, number]; y: [number, number] }; + _module?: any; + [key: string]: any; +} + +/** + * Subplot structure + */ +export interface Subplot { + id: string; + type: string; + domain?: { x: [number, number]; y: [number, number] }; + [key: string]: any; +} + +/** + * Axis range + */ +export type AxisRange = [number, number]; + +/** + * Domain range (normalized 0-1) + */ +export type DomainRange = [number, number]; diff --git a/src/types/traces/common.d.ts b/src/types/traces/common.d.ts new file mode 100644 index 00000000000..f3cec6513c4 --- /dev/null +++ b/src/types/traces/common.d.ts @@ -0,0 +1,73 @@ +/** + * Common trace-related types + * + * Types shared across different trace modules + */ + +/** + * Calculated trace data (internal) + */ +export interface CalcData { + x?: any; + y?: any; + z?: any; + trace?: any; + t?: any; + [key: string]: any; +} + +/** + * Trace module interface + */ +export interface TraceModule { + name: string; + categories: string[]; + animatable?: boolean; + meta?: any; + + // Lifecycle methods + calc?: (gd: any, trace: any) => CalcData[]; + plot?: (gd: any, subplot: any, cdata: any, transitionOpts?: any) => void; + style?: (gd: any, cd?: any) => void; + hoverPoints?: (pointData: any, xval: any, yval: any, hovermode: any) => any; + selectPoints?: (searchInfo: any, selectionTester: any) => any; + eventData?: (out: any, pt: any, trace: any, cd: any, pointNumber: any) => any; + + // Other methods + crossTraceCalc?: (gd: any, plotinfo: any, traces: any[]) => void; + arraysToCalcdata?: (cd: any, trace: any) => void; +} + +/** + * Trace defaults function signature + */ +export type TraceDefaultsFn = ( + traceIn: any, + traceOut: any, + defaultColor: string, + layout: any +) => void; + +/** + * Trace attributes structure + */ +export interface TraceAttributes { + [key: string]: AttributeDefinition; +} + +/** + * Attribute definition + */ +export interface AttributeDefinition { + arrayOk?: boolean; + description?: string; + dflt?: any; + editType?: string; + flags?: string[]; + max?: number; + min?: number; + role?: string; + valType?: string; + values?: any[]; + [key: string]: any; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000000..328648fd1c0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,69 @@ +{ + "compilerOptions": { + // Target and module - optimized for CommonJS codebase + "target": "ES2016", + "module": "CommonJS", + "lib": ["ES2016", "DOM"], + + // Module resolution + "moduleResolution": "node", + "resolveJsonModule": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + + // Paths + "baseUrl": ".", + "paths": { + "stream": ["node_modules/stream-browserify"], + "@types": ["src/types"], + "@types/*": ["src/types/*"] + }, + + // Emit + "declaration": false, + "declarationMap": false, + "sourceMap": true, + "outDir": "./dist", + "noEmit": true, + + // Type checking - start loose, tighten gradually + "strict": false, + "noImplicitAny": false, + "strictNullChecks": false, + "strictFunctionTypes": false, + "strictBindCallApply": false, + "strictPropertyInitialization": false, + "noImplicitThis": false, + "alwaysStrict": false, + + // Linting + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": false, + "noFallthroughCasesInSwitch": true, + + // Advanced options + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "allowJs": true, + "checkJs": false, + "maxNodeModuleJsDepth": 1, + "isolatedModules": true + }, + "include": [ + "src/**/*", + "lib/**/*", + "tasks/**/*" + ], + "exclude": [ + "node_modules", + "dist", + "build", + "test", + "stackgl_modules", + "topojson", + "devtools", + "**/*.spec.js", + "**/*.test.js" + ] +} From 412d4b1629d1197fb84aed298eda02e2258179aa Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Fri, 2 Jan 2026 12:54:54 -0700 Subject: [PATCH 03/13] Convert a few small files to TS --- src/lib/clean_number.js | 22 ---------------------- src/lib/clean_number.ts | 20 ++++++++++++++++++++ src/lib/{mod.js => mod.ts} | 15 ++++----------- src/lib/regex.js | 20 -------------------- src/lib/regex.ts | 21 +++++++++++++++++++++ src/lib/sort_object_keys.js | 5 ----- src/lib/sort_object_keys.ts | 7 +++++++ 7 files changed, 52 insertions(+), 58 deletions(-) delete mode 100644 src/lib/clean_number.js create mode 100644 src/lib/clean_number.ts rename src/lib/{mod.js => mod.ts} (58%) delete mode 100644 src/lib/regex.js create mode 100644 src/lib/regex.ts delete mode 100644 src/lib/sort_object_keys.js create mode 100644 src/lib/sort_object_keys.ts diff --git a/src/lib/clean_number.js b/src/lib/clean_number.js deleted file mode 100644 index 7a265b48df1..00000000000 --- a/src/lib/clean_number.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -var isNumeric = require('fast-isnumeric'); - -var BADNUM = require('../constants/numerical').BADNUM; - -// precompile for speed -var JUNK = /^['"%,$#\s']+|[, ]|['"%,$#\s']+$/g; - -/** - * cleanNumber: remove common leading and trailing cruft - * Always returns either a number or BADNUM. - */ -module.exports = function cleanNumber(v) { - if(typeof v === 'string') { - v = v.replace(JUNK, ''); - } - - if(isNumeric(v)) return Number(v); - - return BADNUM; -}; diff --git a/src/lib/clean_number.ts b/src/lib/clean_number.ts new file mode 100644 index 00000000000..55ca8d8287b --- /dev/null +++ b/src/lib/clean_number.ts @@ -0,0 +1,20 @@ +'use strict'; + +import isNumeric from 'fast-isnumeric'; +import { BADNUM } from '../constants/numerical'; + +// precompile for speed +const JUNK = /^['"%,$#\s']+|[, ]|['"%,$#\s']+$/g; + +/** + * cleanNumber: remove common leading and trailing cruft + * Always returns either a number or BADNUM. + */ +function cleanNumber(v: any): number | undefined { + if (typeof v === 'string') v = v.replace(JUNK, ''); + if (isNumeric(v)) return Number(v); + + return BADNUM; +} + +export default cleanNumber; diff --git a/src/lib/mod.js b/src/lib/mod.ts similarity index 58% rename from src/lib/mod.js rename to src/lib/mod.ts index 04d24056bd3..422ce6dfdf0 100644 --- a/src/lib/mod.js +++ b/src/lib/mod.ts @@ -4,8 +4,8 @@ * sanitized modulus function that always returns in the range [0, d) * rather than (-d, 0] if v is negative */ -function mod(v, d) { - var out = v % d; +export function mod(v: number, d: number) { + const out = v % d; return out < 0 ? out + d : out; } @@ -13,13 +13,6 @@ function mod(v, d) { * sanitized modulus function that always returns in the range [-d/2, d/2] * rather than (-d, 0] if v is negative */ -function modHalf(v, d) { - return Math.abs(v) > (d / 2) ? - v - Math.round(v / d) * d : - v; +export function modHalf(v: number, d: number) { + return Math.abs(v) > d / 2 ? v - Math.round(v / d) * d : v; } - -module.exports = { - mod: mod, - modHalf: modHalf -}; diff --git a/src/lib/regex.js b/src/lib/regex.js deleted file mode 100644 index 15eef630477..00000000000 --- a/src/lib/regex.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -/* - * make a regex for matching counter ids/names ie xaxis, xaxis2, xaxis10... - * - * @param {string} head: the head of the pattern, eg 'x' matches 'x', 'x2', 'x10' etc. - * 'xy' is a special case for cartesian subplots: it matches 'x2y3' etc - * @param {Optional(string)} tail: a fixed piece after the id - * eg counterRegex('scene', '.annotations') for scene2.annotations etc. - * @param {boolean} openEnded: if true, the string may continue past the match. - * @param {boolean} matchBeginning: if false, the string may start before the match. - */ -exports.counter = function(head, tail, openEnded, matchBeginning) { - var fullTail = (tail || '') + (openEnded ? '' : '$'); - var startWithPrefix = matchBeginning === false ? '' : '^'; - if(head === 'xy') { - return new RegExp(startWithPrefix + 'x([2-9]|[1-9][0-9]+)?y([2-9]|[1-9][0-9]+)?' + fullTail); - } - return new RegExp(startWithPrefix + head + '([2-9]|[1-9][0-9]+)?' + fullTail); -}; diff --git a/src/lib/regex.ts b/src/lib/regex.ts new file mode 100644 index 00000000000..f66e0205dce --- /dev/null +++ b/src/lib/regex.ts @@ -0,0 +1,21 @@ +'use strict'; + +const NUMBER_REGEX = '([2-9]|[1-9][0-9]+)?'; + +/** + * make a regex for matching counter ids/names ie xaxis, xaxis2, xaxis10... + * + * @param head: the head of the pattern, eg 'x' matches 'x', 'x2', 'x10' etc. + * 'xy' is a special case for cartesian subplots: it matches 'x2y3' etc + * @param tail: a fixed piece after the id + * eg counterRegex('scene', '.annotations') for scene2.annotations etc. + * @param openEnded: if true, the string may continue past the match. + * @param matchBeginning: if false, the string may start before the match. + */ +export function counter(head: string, tail: string = '', openEnded: boolean, matchBeginning: boolean) { + const fullTail = tail + (openEnded ? '' : '$'); + const startWithPrefix = matchBeginning === false ? '' : '^'; + return head === 'xy' + ? new RegExp(startWithPrefix + 'x' + NUMBER_REGEX + 'y' + NUMBER_REGEX + fullTail) + : new RegExp(startWithPrefix + head + NUMBER_REGEX + fullTail); +} diff --git a/src/lib/sort_object_keys.js b/src/lib/sort_object_keys.js deleted file mode 100644 index f995399cc52..00000000000 --- a/src/lib/sort_object_keys.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -module.exports = function sortObjectKeys(obj) { - return Object.keys(obj).sort(); -}; diff --git a/src/lib/sort_object_keys.ts b/src/lib/sort_object_keys.ts new file mode 100644 index 00000000000..1be0aba0d3c --- /dev/null +++ b/src/lib/sort_object_keys.ts @@ -0,0 +1,7 @@ +'use strict'; + +function sortObjectKeys(obj: Record) { + return Object.keys(obj).sort(); +} + +export default sortObjectKeys; From f7045425cd4344ead5850939de6c4df6d358d4f3 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Fri, 2 Jan 2026 13:05:04 -0700 Subject: [PATCH 04/13] Update requires to handle esbuild ESM/CJS interoperability --- src/components/colorscale/attributes.js | 2 +- src/lib/index.js | 4 ++-- src/plots/geo/layout_attributes.js | 2 +- src/plots/map/constants.js | 2 +- src/plots/mapbox/constants.js | 2 +- src/traces/scatter3d/attributes.js | 2 +- src/traces/scattergl/attributes.js | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/colorscale/attributes.js b/src/components/colorscale/attributes.js index 2074e8349f4..bee2eb008aa 100644 --- a/src/components/colorscale/attributes.js +++ b/src/components/colorscale/attributes.js @@ -2,7 +2,7 @@ var colorbarAttrs = require('../colorbar/attributes'); var counterRegex = require('../../lib/regex').counter; -var sortObjectKeys = require('../../lib/sort_object_keys'); +var sortObjectKeys = require('../../lib/sort_object_keys').default; var palettes = require('./scales.js').scales; var paletteStr = sortObjectKeys(palettes); diff --git a/src/lib/index.js b/src/lib/index.js index d898a526140..8124c9ec9a5 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -105,7 +105,7 @@ lib.roundUp = searchModule.roundUp; lib.sort = searchModule.sort; lib.findIndexOfMin = searchModule.findIndexOfMin; -lib.sortObjectKeys = require('./sort_object_keys'); +lib.sortObjectKeys = require('./sort_object_keys').default; var statsModule = require('./stats'); lib.aggNums = statsModule.aggNums; @@ -206,7 +206,7 @@ lib.pushUnique = require('./push_unique'); lib.increment = require('./increment'); -lib.cleanNumber = require('./clean_number'); +lib.cleanNumber = require('./clean_number').default; lib.ensureNumber = function ensureNumber(v) { if (!isNumeric(v)) return BADNUM; diff --git a/src/plots/geo/layout_attributes.js b/src/plots/geo/layout_attributes.js index a6666178c37..450db363233 100644 --- a/src/plots/geo/layout_attributes.js +++ b/src/plots/geo/layout_attributes.js @@ -5,7 +5,7 @@ var domainAttrs = require('../domain').attributes; var dash = require('../../components/drawing/attributes').dash; var constants = require('./constants'); var overrideAll = require('../../plot_api/edit_types').overrideAll; -var sortObjectKeys = require('../../lib/sort_object_keys'); +var sortObjectKeys = require('../../lib/sort_object_keys').default; var geoAxesAttrs = { range: { diff --git a/src/plots/map/constants.js b/src/plots/map/constants.js index 2a867418477..52117231fae 100644 --- a/src/plots/map/constants.js +++ b/src/plots/map/constants.js @@ -1,6 +1,6 @@ 'use strict'; -var sortObjectKeys = require('../../lib/sort_object_keys'); +var sortObjectKeys = require('../../lib/sort_object_keys').default; var arcgisSatHybrid = require('./styles/arcgis-sat-hybrid'); // https://raw.githubusercontent.com/go2garret/maps/v1.0.0/LICENSE var arcgisSat = require('./styles/arcgis-sat'); diff --git a/src/plots/mapbox/constants.js b/src/plots/mapbox/constants.js index 37f79ddc569..d349438ecd1 100644 --- a/src/plots/mapbox/constants.js +++ b/src/plots/mapbox/constants.js @@ -1,6 +1,6 @@ 'use strict'; -var sortObjectKeys = require('../../lib/sort_object_keys'); +var sortObjectKeys = require('../../lib/sort_object_keys').default; var requiredVersion = '1.13.4'; diff --git a/src/traces/scatter3d/attributes.js b/src/traces/scatter3d/attributes.js index 17023178d28..12998d8cfd2 100644 --- a/src/traces/scatter3d/attributes.js +++ b/src/traces/scatter3d/attributes.js @@ -11,7 +11,7 @@ var DASHES = require('../../constants/gl3d_dashes'); var MARKER_SYMBOLS = require('../../constants/gl3d_markers'); var extendFlat = require('../../lib/extend').extendFlat; var overrideAll = require('../../plot_api/edit_types').overrideAll; -var sortObjectKeys = require('../../lib/sort_object_keys'); +var sortObjectKeys = require('../../lib/sort_object_keys').default; var scatterLineAttrs = scatterAttrs.line; var scatterMarkerAttrs = scatterAttrs.marker; diff --git a/src/traces/scattergl/attributes.js b/src/traces/scattergl/attributes.js index 8f05e9f5cc4..59188554c52 100644 --- a/src/traces/scattergl/attributes.js +++ b/src/traces/scattergl/attributes.js @@ -7,7 +7,7 @@ var scatterAttrs = require('../scatter/attributes'); var axisHoverFormat = require('../../plots/cartesian/axis_format_attributes').axisHoverFormat; var colorScaleAttrs = require('../../components/colorscale/attributes'); -var sortObjectKeys = require('../../lib/sort_object_keys'); +var sortObjectKeys = require('../../lib/sort_object_keys').default; var extendFlat = require('../../lib/extend').extendFlat; var overrideAll = require('../../plot_api/edit_types').overrideAll; var DASHES = require('./constants').DASHES; From 5f72cf8276bdc29b2886a4a772c0de293388fde6 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Fri, 2 Jan 2026 13:28:39 -0700 Subject: [PATCH 05/13] Use ts-node for scripts using TS that run outside of esbuild --- package-lock.json | 15 +++++++++++++++ package.json | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index f1f6839a408..6e816360891 100644 --- a/package-lock.json +++ b/package-lock.json @@ -109,6 +109,7 @@ "through2": "^4.0.2", "transform-loader": "^0.2.4", "true-case-path": "^2.2.1", + "ts-node": "^10.9.2", "typescript": "^5.9.3", "virtual-webgl": "^1.0.7" }, @@ -6470,6 +6471,13 @@ "dev": true, "license": "ISC" }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, "node_modules/map-limit": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz", @@ -10107,6 +10115,13 @@ "dev": true, "license": "MIT" }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", diff --git a/package.json b/package.json index 106d2217cb4..d87dfc646a6 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "schema": "node tasks/schema.mjs", "stats": "node tasks/stats.js", "find-strings": "node tasks/find_locale_strings.js", - "preprocess": "node tasks/preprocess.js", + "preprocess": "ts-node tasks/preprocess.js", "use-draftlogs": "node tasks/use_draftlogs.js", "empty-draftlogs": "node tasks/empty_draftlogs.js", "empty-dist": "node tasks/empty_dist.js", @@ -169,6 +169,7 @@ "through2": "^4.0.2", "transform-loader": "^0.2.4", "true-case-path": "^2.2.1", + "ts-node": "^10.9.2", "typescript": "^5.9.3", "virtual-webgl": "^1.0.7" }, From 5ed7da0614a33094dbc001319609163a8d6f3e5a Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Fri, 2 Jan 2026 16:31:51 -0700 Subject: [PATCH 06/13] Run test script with ts-node --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d87dfc646a6..306a8528631 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "test-mock": "node tasks/test_mock.mjs", "test-image": "node test/image/compare_pixels_test.mjs", "test-export": "node test/image/export_test.js", - "test-syntax": "node tasks/test_syntax.js && npm run find-strings -- --no-output", + "test-syntax": "ts-node tasks/test_syntax.js && npm run find-strings -- --no-output", "test-bundle": "node tasks/test_bundle.js", "test-plain-obj": "node tasks/test_plain_obj.mjs", "test": "npm run test-jasmine -- --nowatch && npm run test-bundle && npm run test-image && npm run test-export && npm run test-syntax && npm run lint", From f2622c5723306d1bb46475e983d19fbcc34eb3c3 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Wed, 6 May 2026 16:00:10 -0600 Subject: [PATCH 07/13] Add additional types and type generation script --- src/types/components/colorbar.d.ts | 115 ++ src/types/components/rangeselector.d.ts | 43 + src/types/components/slider.d.ts | 65 ++ src/types/components/updatemenu.d.ts | 55 + src/types/core/animation.d.ts | 149 +++ src/types/core/api.d.ts | 185 ++++ src/types/core/config.d.ts | 345 ++++-- src/types/core/data.d.ts | 563 +++++++--- src/types/core/events.d.ts | 289 +++-- src/types/core/graph-div.d.ts | 99 +- src/types/core/layout.d.ts | 1088 ++++++++++++++++--- src/types/core/template.d.ts | 47 + src/types/generated/components/modebar.d.ts | 16 + src/types/generated/index.d.ts | 6 + src/types/index.d.ts | 26 +- src/types/lib/attributes.d.ts | 224 ++++ src/types/lib/common.d.ts | 137 ++- src/types/traces/box.d.ts | 42 + src/types/traces/candlestick.d.ts | 51 + src/types/traces/common.d.ts | 7 +- src/types/traces/ohlc.d.ts | 95 ++ src/types/traces/pie.d.ts | 126 +++ src/types/traces/sankey.d.ts | 108 ++ src/types/traces/violin.d.ts | 61 ++ tasks/generate_types.mjs | 307 ++++++ 25 files changed, 3558 insertions(+), 691 deletions(-) create mode 100644 src/types/components/colorbar.d.ts create mode 100644 src/types/components/rangeselector.d.ts create mode 100644 src/types/components/slider.d.ts create mode 100644 src/types/components/updatemenu.d.ts create mode 100644 src/types/core/animation.d.ts create mode 100644 src/types/core/api.d.ts create mode 100644 src/types/core/template.d.ts create mode 100644 src/types/generated/components/modebar.d.ts create mode 100644 src/types/generated/index.d.ts create mode 100644 src/types/lib/attributes.d.ts create mode 100644 src/types/traces/box.d.ts create mode 100644 src/types/traces/candlestick.d.ts create mode 100644 src/types/traces/ohlc.d.ts create mode 100644 src/types/traces/pie.d.ts create mode 100644 src/types/traces/sankey.d.ts create mode 100644 src/types/traces/violin.d.ts create mode 100644 tasks/generate_types.mjs diff --git a/src/types/components/colorbar.d.ts b/src/types/components/colorbar.d.ts new file mode 100644 index 00000000000..504984ba045 --- /dev/null +++ b/src/types/components/colorbar.d.ts @@ -0,0 +1,115 @@ +/** + * ColorBar types + * + * Defines the structure of ColorBar configuration. + */ + +import type { Font } from '../core/layout'; +import type { Color, Datum, DTickValue, XAnchor, XRef, YAnchor, YRef } from '../lib/common'; + +/** + * Exponent format type + */ +export type ExponentFormat = 'none' | 'e' | 'E' | 'power' | 'SI' | 'B'; + +/** + * Show prefix/suffix type + */ +export type ShowTickLabel = 'all' | 'first' | 'last' | 'none'; + +/** + * Tick label position type + */ +export type TickLabelPosition = + | 'outside' + | 'inside' + | 'outside top' + | 'inside top' + | 'outside left' + | 'inside left' + | 'outside right' + | 'inside right' + | 'outside bottom' + | 'inside bottom'; + +/** + * Tick label overflow type + */ +export type TickLabelOverflow = 'allow' | 'hide past div' | 'hide past domain'; + +/** + * Length mode type + */ +export type LengthMode = 'fraction' | 'pixels'; + +/** + * ColorBar title configuration + */ +export interface ColorBarTitle { + text?: string; + font?: Partial; + side?: 'right' | 'top' | 'bottom'; +} + +/** + * Tick format stop configuration + */ +export interface TickFormatStop { + enabled?: boolean; + dtickrange?: [DTickValue | null, DTickValue | null]; + value?: string; + name?: string; + templateitemname?: string; +} + +/** + * ColorBar configuration + */ +export interface ColorBar { + orientation?: 'h' | 'v'; + thicknessmode?: LengthMode; + thickness?: number; + lenmode?: LengthMode; + len?: number; + x?: number; + xref?: XRef; + xanchor?: XAnchor; + xpad?: number; + y?: number; + yref?: YRef; + yanchor?: YAnchor; + ypad?: number; + outlinecolor?: Color; + outlinewidth?: number; + bordercolor?: Color; + borderwidth?: number; + bgcolor?: Color; + tickmode?: 'auto' | 'linear' | 'array'; + nticks?: number; + tick0?: number | string; + dtick?: DTickValue; + tickvals?: Datum[] | Datum[][]; + ticktext?: Datum[] | Datum[][]; + ticks?: 'outside' | 'inside' | ''; + ticklabeloverflow?: TickLabelOverflow; + ticklabelposition?: TickLabelPosition; + ticklen?: number; + tickwidth?: number; + tickcolor?: Color; + ticklabelstep?: number; + showticklabels?: boolean; + labelalias?: DTickValue; + tickfont?: Partial; + tickangle?: 'auto' | number; + tickformat?: string; + tickformatstops?: Array>; + tickprefix?: string; + showtickprefix?: ShowTickLabel; + ticksuffix?: string; + showticksuffix?: ShowTickLabel; + separatethousands?: boolean; + exponentformat?: ExponentFormat; + minexponent?: number; + showexponent?: ShowTickLabel; + title?: Partial; +} diff --git a/src/types/components/rangeselector.d.ts b/src/types/components/rangeselector.d.ts new file mode 100644 index 00000000000..23746053929 --- /dev/null +++ b/src/types/components/rangeselector.d.ts @@ -0,0 +1,43 @@ +/** + * RangeSelector types + * + * Defines the structure of RangeSelector configuration. + */ + +import type { Font } from '../core/layout'; +import type { Color, XAnchor, YAnchor } from '../lib/common'; + +/** + * RangeSelector step type + */ +export type RangeSelectorStep = 'month' | 'year' | 'day' | 'hour' | 'minute' | 'second' | 'all'; + +/** + * RangeSelector button configuration + */ +export interface RangeSelectorButton { + visible?: boolean; + step?: RangeSelectorStep; + stepmode?: 'backward' | 'todate'; + count?: number; + label?: string; + name?: string; + templateitemname?: string; +} + +/** + * RangeSelector configuration + */ +export interface RangeSelector { + buttons?: Array>; + visible?: boolean; + x?: number; + xanchor?: XAnchor; + y?: number; + yanchor?: YAnchor; + activecolor?: Color; + bgcolor?: Color; + bordercolor?: Color; + borderwidth?: number; + font?: Partial; +} diff --git a/src/types/components/slider.d.ts b/src/types/components/slider.d.ts new file mode 100644 index 00000000000..08abed3d76a --- /dev/null +++ b/src/types/components/slider.d.ts @@ -0,0 +1,65 @@ +/** + * Slider types + * + * Defines the structure of Slider configuration. + */ + +import type { Transition } from '../core/animation'; +import type { Font, Padding } from '../core/layout'; +import type { Color, XAnchor, YAnchor } from '../lib/common'; +import type { LengthMode } from './colorbar'; + +/** + * Slider step configuration + */ +export interface SliderStep { + visible?: boolean; + method?: 'restyle' | 'relayout' | 'animate' | 'update' | 'skip'; + args?: any[]; + label?: string; + value?: string; + execute?: boolean; + name?: string; + templateitemname?: string; +} + +/** + * Slider current value configuration + */ +export interface CurrentValue { + visible?: boolean; + xanchor?: XAnchor; + offset?: number; + prefix?: string; + suffix?: string; + font?: Partial; +} + +/** + * Slider configuration + */ +export interface Slider { + visible?: boolean; + active?: number; + steps?: Array>; + lenmode?: LengthMode; + len?: number; + x?: number; + y?: number; + pad?: Partial; + xanchor?: XAnchor; + yanchor?: YAnchor; + transition?: Partial; + currentvalue?: Partial; + font?: Partial; + activebgcolor?: Color; + bgcolor?: Color; + bordercolor?: Color; + borderwidth?: number; + ticklen?: number; + tickcolor?: Color; + tickwidth?: number; + minorticklen?: number; + name?: string; + templateitemname?: string; +} diff --git a/src/types/components/updatemenu.d.ts b/src/types/components/updatemenu.d.ts new file mode 100644 index 00000000000..6ae2a2dd1ab --- /dev/null +++ b/src/types/components/updatemenu.d.ts @@ -0,0 +1,55 @@ +/** + * UpdateMenu types + * + * Defines the structure of UpdateMenu configuration. + */ + +import type { Color, XAnchor, YAnchor } from '../lib/common'; +import type { Font, Padding } from '../core/layout'; + +/** + * UpdateMenu button configuration + */ +export interface UpdateMenuButton { + visible?: boolean; + method?: 'restyle' | 'relayout' | 'animate' | 'update' | 'skip'; + args?: any[]; + args2?: any[]; + label?: string; + execute?: boolean; + name?: string; + templateitemname?: string; +} + +/** + * UpdateMenu direction type + */ +export type UpdateMenuDirection = 'left' | 'up' | 'right' | 'down'; + +/** + * UpdateMenu type + */ +export type UpdateMenuType = 'dropdown' | 'buttons'; + +/** + * UpdateMenu configuration + */ +export interface UpdateMenu { + active?: number; + bgcolor?: Color; + bordercolor?: Color; + borderwidth?: number; + buttons?: Array>; + direction?: UpdateMenuDirection; + font?: Partial; + name?: string; + pad?: Partial; + showactive?: boolean; + templateitemname?: string; + type?: UpdateMenuType; + visible?: boolean; + x?: number; + xanchor?: XAnchor; + y?: number; + yanchor?: YAnchor; +} diff --git a/src/types/core/animation.d.ts b/src/types/core/animation.d.ts new file mode 100644 index 00000000000..2ce98033962 --- /dev/null +++ b/src/types/core/animation.d.ts @@ -0,0 +1,149 @@ +/** + * Animation types + * + * Defines animation and transition types for Plotly. + */ + +import type { PlotData } from './data'; +import type { Layout } from './layout'; + +/** + * Transition easing type + */ +export type TransitionEasing = + | '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'; + +/** + * Transition configuration + */ +export interface Transition { + /** + * Duration of the transition in milliseconds + */ + duration?: number; + + /** + * Easing function for the transition + */ + easing?: TransitionEasing; + + /** + * Ordering of the transition + */ + ordering?: 'layout first' | 'traces first'; +} + +/** + * Animation frame options + */ +export interface AnimationFrameOpts { + /** + * Duration of the frame in milliseconds + */ + duration?: number; + + /** + * Whether to redraw the plot + */ + redraw?: boolean; +} + +/** + * Animation options + */ +export interface AnimationOpts { + /** + * Animation mode + */ + mode?: 'immediate' | 'next' | 'afterall'; + + /** + * Animation direction + */ + direction?: 'forward' | 'reverse'; + + /** + * Start from current state + */ + fromcurrent?: boolean; + + /** + * Transition configuration + */ + transition?: Partial; + + /** + * Frame configuration + */ + frame?: Partial; +} + +/** + * Animation frame + */ +export interface Frame { + /** + * Frame group + */ + group?: string; + + /** + * Frame name + */ + name: string; + + /** + * Trace indices this frame applies to + */ + traces?: number[]; + + /** + * Base frame to inherit from + */ + baseframe?: string; + + /** + * Data updates for this frame + */ + data?: Partial[]; + + /** + * Layout updates for this frame + */ + layout?: Partial; +} diff --git a/src/types/core/api.d.ts b/src/types/core/api.d.ts new file mode 100644 index 00000000000..a0bb44b6f3a --- /dev/null +++ b/src/types/core/api.d.ts @@ -0,0 +1,185 @@ +/** + * Public API function types for Plotly.js + */ + +import type { AnimationOpts, Frame } from './animation'; +import type { Config, DownloadImgopts, ToImgopts } from './config'; +import type { Data } from './data'; +import type { PlotlyHTMLElement } from './events'; +import type { Icon, Layout, Template } from './layout'; + +// --------------------------------------------------------------------------- +// Roots and request shapes +// --------------------------------------------------------------------------- + +export type Root = string | HTMLElement; + +export interface PlotlyDataLayoutConfig { + data: Data[]; + layout?: Partial; + config?: Partial; +} + +export type RootOrData = Root | PlotlyDataLayoutConfig; + +// --------------------------------------------------------------------------- +// Static plots / icons +// --------------------------------------------------------------------------- + +export interface StaticPlots { + resize(root: Root): void; +} + +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 type IconsMap = { [K in DefaultIcons]: Icon }; + +// --------------------------------------------------------------------------- +// Module registration +// --------------------------------------------------------------------------- + +export interface RegisterTraceModule { + moduleType: 'trace'; + name: string; + categories: string[]; + meta: { + description: string; + }; +} + +export interface LocaleModule { + moduleType: 'locale'; + name: string; + dictionary: Record; + format: Record; +} + +export interface RegisterComponentModule { + moduleType: 'component'; + name: string; +} + +export interface ApiMethodModule { + moduleType: 'apiMethod'; + name: string; + fn: any; +} + +export type PlotlyModule = RegisterTraceModule | LocaleModule | RegisterComponentModule | ApiMethodModule; + +// --------------------------------------------------------------------------- +// Validation +// --------------------------------------------------------------------------- + +export interface ValidateResult { + code: string; + container: 'data' | 'layout'; + trace: number | null; + path: string | (string | number)[]; + astr: string; + msg: string; +} + +// --------------------------------------------------------------------------- +// Function declarations +// --------------------------------------------------------------------------- + +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 +): Promise; + +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 animate( + root: Root, + frameOrGroupNameOrFrameList?: string | string[] | Partial | Array>, + opts?: Partial +): Promise; + +export function validate(data: Data[], layout: Partial): ValidateResult[]; +export function setPlotConfig(config: Partial): void; + +export type FigureOrRoot = Root | { data: Data[]; layout: Partial }; +export function makeTemplate(figure: FigureOrRoot): Template; diff --git a/src/types/core/config.d.ts b/src/types/core/config.d.ts index a3a9b5e48ae..62b0b70cbf4 100644 --- a/src/types/core/config.d.ts +++ b/src/types/core/config.d.ts @@ -1,177 +1,294 @@ /** * Config types * - * Defines the structure of Plotly config options. + * Plotly configuration options and edit settings. */ -/** - * User-provided configuration for Plotly - */ -export interface Config { +import type { ModeBarButtonAny, ModeBarDefaultButtons } from './layout'; + +// --------------------------------------------------------------------------- +// Edits +// --------------------------------------------------------------------------- + +export interface Edits { /** - * Whether the plot should resize on window resize + * Determines if the main anchor of the annotation is editable. + * @default false */ - autosizable?: boolean; - + annotationPosition: boolean; /** - * Display Plotly logo on mode bar + * Has only an effect for annotations with arrows. + * @default false */ - displaylogo?: boolean; - + annotationTail: boolean; /** - * Display the mode bar + * Enables editing annotation text. + * @default false */ - displayModeBar?: boolean | 'hover'; - + annotationText: boolean; /** - * What happens on double click + * Enables editing axis title text. + * @default false */ - doubleClick?: 'reset' | 'autosize' | 'reset+autosize' | false; - + axisTitleText: boolean; /** - * Allow plot to be edited + * Enables moving colorbars. + * @default false */ - editable?: boolean; - + colorbarPosition: boolean; /** - * What can be edited + * Enables editing colorbar title text. + * @default false */ - edits?: Partial; - + colorbarTitleText: boolean; /** - * Whether to fill the parent container + * Enables moving the legend. + * @default false */ - fillFrame?: boolean; - + legendPosition: boolean; /** - * Margin around the plot when fillFrame is true + * Enables editing trace name fields from the legend. + * @default false */ - frameMargins?: number; - + legendText: boolean; /** - * Text for the "Edit in Chart Studio" link + * Enables moving shapes. + * @default false */ - linkText?: string; - + shapePosition: boolean; /** - * Locale for formatting + * Enables editing the global layout title. + * @default false */ - locale?: string; + titleText: boolean; +} + +// Backwards-compatible alias +export type ConfigEdits = Edits; + +// --------------------------------------------------------------------------- +// Image export options +// --------------------------------------------------------------------------- + +export interface ToImgopts { + format: 'jpeg' | 'png' | 'webp' | 'svg'; + /** If null, uses current graph width */ + width: number | null; + /** If null, uses current graph height */ + height: number | null; + scale?: number | undefined; +} + +export interface DownloadImgopts { + format: 'jpeg' | 'png' | 'webp' | 'svg'; + width: number | null; + height: number | null; + filename: string; +} + +export interface ToImageButtonOptions { + format?: 'png' | 'svg' | 'jpeg' | 'webp'; + filename?: string; + height?: number; + width?: number; + scale?: number; +} +// --------------------------------------------------------------------------- +// Config +// --------------------------------------------------------------------------- + +export interface Config { /** - * Custom locale definitions + * No interactivity, for export or image generation. + * @default false */ - locales?: { [locale: string]: any }; - + staticPlot: boolean; /** - * Mapbox access token + * Determines whether math should be typeset when MathJax is present. + * @default true */ - mapboxAccessToken?: string; - + typesetMath: boolean; /** - * Custom mode bar buttons configuration + * Base URL for the 'Edit in Chart Studio' button. + * @default '' */ - modeBarButtons?: any; - + plotlyServerURL: string; /** - * Mode bar buttons to add + * Sets all pieces of `edits` unless overridden. + * @default false */ - modeBarButtonsToAdd?: any[]; - + editable: boolean; + edits: Partial; /** - * Mode bar buttons to remove + * Enables moving selections. + * @default true */ - modeBarButtonsToRemove?: string[]; - + editSelection: boolean; /** - * Pixel ratio for WebGL plots + * Plot with respect to layout.autosize:true and infer container size. + * @default false */ - plotGlPixelRatio?: number; - + autosizable: boolean; /** - * Base URL for plotly server + * Change the layout size when window is resized. + * @default false */ - plotlyServerURL?: string; - + responsive: boolean; /** - * Number of operations that can be queued + * Whether the graph fills the container or the screen. + * @default false */ - queueLength?: number; - + fillFrame: boolean; /** - * Whether to resize on window resize (alternative) + * Frame margins in fraction of the graph size. + * @default 0 */ - responsive?: boolean; - + frameMargins: number; /** - * Enable scroll zoom + * Mouse wheel / two-finger scroll zoom. + * @default 'gl3d+geo+map' */ - scrollZoom?: boolean; - + scrollZoom: string | boolean; /** - * Send data to Chart Studio + * Double click interaction mode. + * @default 'reset+autosize' */ - sendData?: boolean; - + doubleClick: 'reset+autosize' | 'reset' | 'autosize' | false; /** - * Background color setting function + * Delay for registering a double-click in ms. + * @default 300 */ - setBackground?: string | ((gd: any) => void); - + doubleClickDelay: number; /** - * Show "Edit in Chart Studio" link + * Show cartesian axis pan/zoom drag handles. + * @default true */ - showLink?: boolean; - + showAxisDragHandles: boolean; /** - * Show tips on first hover + * Show direct range entry at the pan/zoom drag points. + * @default true */ - showTips?: boolean; - + showAxisRangeEntryBoxes: boolean; /** - * Make the chart static - no interactivity + * Show tips while interacting with the resulting graphs. + * @default true */ - staticPlot?: boolean; - + showTips: boolean; /** - * Options for the "Download plot as PNG" button + * Display a link to Chart Studio Cloud at the bottom right. + * @default false */ - toImageButtonOptions?: Partial; - + showLink: boolean; /** - * URL for topojson files + * Sets the text appearing in the `showLink` link. + * @default 'Edit chart' */ - topojsonURL?: string; - + linkText: string; /** - * Add watermark to images + * If `showLink` is true, send data when linking to Chart Studio Cloud. + * @default true */ - watermark?: boolean; -} - -/** - * Configuration for what can be edited - */ -export interface ConfigEdits { - annotationPosition?: boolean; - annotationTail?: boolean; - annotationText?: boolean; - axisTitleText?: boolean; - colorbarPosition?: boolean; - colorbarTitleText?: boolean; - legendPosition?: boolean; - legendText?: boolean; - shapePosition?: boolean; - titleText?: boolean; -} - -/** - * Options for the "Download plot" button - */ -export interface ToImageButtonOptions { - format?: 'png' | 'svg' | 'jpeg' | 'webp'; - filename?: string; - height?: number; - width?: number; - scale?: number; + sendData: boolean; + /** + * Adds a source-displaying function to show sources on the resulting graphs. + * @default false + */ + showSources: false | ((gd: HTMLElement) => void | Promise); + /** + * Mode bar display mode. + * @default 'hover' + */ + displayModeBar: 'hover' | boolean; + /** + * Show "Edit in Chart Studio" mode bar button. + * @default false + */ + showSendToCloud: boolean; + /** + * Same as `showSendToCloud`, but use a pencil icon instead of a floppy-disk. + * @default false + */ + showEditInChartStudio: boolean; + /** + * Remove mode bar buttons by name. + * @default [] + */ + modeBarButtonsToRemove: ModeBarDefaultButtons[]; + /** + * Add mode bar button using config objects or default button strings. + * @default [] + */ + modeBarButtonsToAdd: ModeBarButtonAny[]; + /** + * Define fully custom mode bar buttons as nested array of button groups. + * @default false + */ + modeBarButtons: ModeBarButtonAny[][] | false; + /** + * Statically override options for toImage modebar button. + * @default {} + */ + toImageButtonOptions: Partial<{ + filename: string; + scale: number; + format: 'png' | 'svg' | 'jpeg' | 'webp'; + height: number; + width: number; + }>; + /** + * Display the plotly logo on the mode bar. + * @default true + */ + displaylogo: boolean; + /** + * Watermark images with the company's logo. + * @default false + */ + watermark: boolean; + /** + * Pixel ratio during WebGL image export. + * @default 2 + */ + plotGlPixelRatio: number; + /** + * Set background color function or behavior. + * @default 'transparent' + */ + setBackground: ((gd: HTMLElement, bgColor: string) => void) | 'opaque' | 'transparent'; + /** + * URL to topojson used in geo charts. + * @default 'https://cdn.plot.ly/' + */ + topojsonURL: string; + /** + * Mapbox access token (required for mapbox trace types). + * @default null + */ + mapboxAccessToken: string | null; + /** + * Console logging level (0-2). Set via Plotly.setPlotConfig. + * @default 1 + */ + logging: 0 | 1 | 2; + /** + * On-graph logging (notifier) level (0-2). Set via Plotly.setPlotConfig. + * @default 0 + */ + notifyOnLogging: 0 | 1 | 2; + /** + * Length of the undo/redo queue. + * @default 0 + */ + queueLength: number; + /** + * Localization to use (e.g. 'en' or 'en-US'). + * @default 'en-US' + */ + locale: string; + /** + * Localization definitions. + * @default {} + */ + locales: Record; format?: Record }>; } diff --git a/src/types/core/data.d.ts b/src/types/core/data.d.ts index 9eab5917a16..982961a8542 100644 --- a/src/types/core/data.d.ts +++ b/src/types/core/data.d.ts @@ -1,68 +1,386 @@ /** * Data/Trace types * - * Defines the structure of Plotly data traces. - * This is a union of all possible trace types. + * Comprehensive trace data types covering all plot types, markers, lines, + * and the Data union. */ -import type { Dash, ColorScale } from '../lib/common'; +import type { Color, ColorScale, Dash, Datum, ErrorBar, MarkerSymbol, Pattern, TypedArray } from '../lib/common'; +import type { ColorBar, DataTitle, Delta, Font, Gauge, HoverLabel, Padding, PlotNumber } from './layout'; + +// --------------------------------------------------------------------------- +// PlotType +// --------------------------------------------------------------------------- -/** - * All supported plot/trace types in plotly.js - */ export type PlotType = - | "bar" - | "barpolar" - | "box" - | "candlestick" - | "carpet" - | "choropleth" - | "choroplethmap" - | "choroplethmapbox" - | "cone" - | "contour" - | "contourcarpet" - | "densitymap" - | "densitymapbox" - | "funnel" - | "funnelarea" - | "heatmap" - | "histogram" - | "histogram2d" - | "histogram2dcontour" - | "icicle" - | "image" - | "indicator" - | "isosurface" - | "mesh3d" - | "ohlc" - | "parcats" - | "parcoords" - | "pie" - | "sankey" - | "scatter" - | "scatter3d" - | "scattercarpet" - | "scattergeo" - | "scattergl" - | "scattermap" - | "scattermapbox" - | "scatterpolar" - | "scatterpolargl" - | "scattersmith" - | "scatterternary" - | "splom" - | "streamtube" - | "sunburst" - | "surface" - | "table" - | "treemap" - | "violin" - | "volume" - | "waterfall"; + | 'bar' + | 'barpolar' + | 'box' + | 'candlestick' + | 'carpet' + | 'choropleth' + | 'choroplethmap' + | 'choroplethmapbox' + | 'cone' + | 'contour' + | 'contourcarpet' + | 'densitymap' + | 'densitymapbox' + | 'funnel' + | 'funnelarea' + | 'heatmap' + | 'histogram' + | 'histogram2d' + | 'histogram2dcontour' + | 'icicle' + | 'image' + | 'indicator' + | 'isosurface' + | 'mesh3d' + | 'ohlc' + | 'parcats' + | 'parcoords' + | 'pie' + | 'sankey' + | 'scatter' + | 'scatter3d' + | 'scattercarpet' + | 'scattergeo' + | 'scattergl' + | 'scattermap' + | 'scattermapbox' + | 'scatterpolar' + | 'scatterpolargl' + | 'scattersmith' + | 'scatterternary' + | 'splom' + | 'streamtube' + | 'sunburst' + | 'surface' + | 'table' + | 'treemap' + | 'violin' + | 'volume' + | 'waterfall'; + +// --------------------------------------------------------------------------- +// Marker / Line types +// --------------------------------------------------------------------------- + +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 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 ScatterLine { + color: Color; + width: number; + dash: Dash; + shape: 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv'; + smoothing: number; + simplify: boolean; +} + +// --------------------------------------------------------------------------- +// PlotData +// --------------------------------------------------------------------------- + +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; + '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': {}; + '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[]; + hoverongaps: boolean; + 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; + 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; + zorder: 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 | 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; + maxdepth: number; + uirevision: string | number; + uid: string; +} + +export type ScatterData = PlotData; + +// --------------------------------------------------------------------------- +// Data union — re-exports specialized trace types from traces/ +// Forward declarations so the union compiles without circular imports. +// --------------------------------------------------------------------------- + +export type Data = + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial; + +// --------------------------------------------------------------------------- +// Internal types (not in public API) +// --------------------------------------------------------------------------- /** - * Common properties shared by all trace types + * Common properties shared by all trace types — convenience interface for + * gradual migration of internal code that doesn't need the full PlotData shape. */ export interface TraceBase { customdata?: any[]; @@ -86,21 +404,19 @@ export interface TraceBase { } /** - * User-provided plot data (trace) - * This will be a union of all specific trace types + * Generic trace for gradual migration. Use specific trace types when available. */ -export type PlotData = TraceBase & ( - | BarTrace - | LineTrace - | ScatterTrace - // Add more trace types as you convert them - | GenericTrace -); +export interface GenericTrace extends TraceBase { + x?: any[]; + y?: any[]; + z?: any[]; + [key: string]: any; +} /** * Fully processed plot data with defaults applied (internal use) */ -export interface FullData extends PlotData { +export interface FullData extends Partial { _expandedIndex?: number; _fullInput?: any; _indexToPoints?: { [key: number]: number[] }; @@ -108,120 +424,5 @@ export interface FullData extends PlotData { _length?: number; _module?: any; index?: number; -} - -/** - * Generic trace for gradual migration - * Use specific trace types when available - */ -export interface GenericTrace extends TraceBase { - x?: any[]; - y?: any[]; - z?: any[]; [key: string]: any; } - -/** - * Scatter trace - */ -export interface ScatterTrace extends TraceBase { - connectgaps?: boolean; - fill?: 'none' | 'tozeroy' | 'tozerox' | 'tonexty' | 'tonextx' | 'toself' | 'tonext'; - fillcolor?: string; - line?: Partial; - marker?: Partial; - mode?: 'lines' | 'markers' | 'lines+markers' | 'none' | 'text' | 'lines+text' | 'markers+text' | 'lines+markers+text'; - text?: string | string[]; - textfont?: any; - textposition?: string | string[]; - type: 'scatter'; - x?: number[] | string[]; - y?: number[] | string[]; -} - -/** - * Bar trace - */ -export interface BarTrace extends TraceBase { - base?: number | number[]; - marker?: Partial; - offset?: number | number[]; - orientation?: 'v' | 'h'; - text?: string | string[]; - textangle?: number; - textposition?: string; - type: 'bar'; - width?: number | number[]; - x?: number[] | string[]; - y?: number[] | string[]; -} - -/** - * Line-only trace (simplified scatter) - */ -export interface LineTrace extends TraceBase { - line?: Partial; - mode: 'lines'; - type: 'scatter'; - x?: number[] | string[]; - y?: number[] | string[]; -} - -/** - * Marker configuration (used by many traces) - */ -export interface Marker { - autocolorscale?: boolean; - cauto?: boolean; - cmax?: number; - cmid?: number; - cmin?: number; - color?: string | string[] | number[]; - coloraxis?: string; - colorbar?: any; - colorscale?: string | any[][]; - line?: Partial; - opacity?: number | number[]; - reversescale?: boolean; - showscale?: boolean; - size?: number | number[]; - symbol?: string | string[]; -} - -/** - * Marker line (outline) - */ -export interface MarkerLine { - autocolorscale?: boolean; - cauto?: boolean; - cmax?: number; - cmid?: number; - cmin?: number; - color?: string | string[]; - colorscale?: string | any[][]; - reversescale?: boolean; - width?: number | number[]; -} - -/** - * Line configuration (used by many traces) - */ -export interface Line { - color?: string; - dash?: Dash; - shape?: 'linear' | 'spline' | 'hv' | 'vh' | 'hvh' | 'vhv'; - simplify?: boolean; - smoothing?: number; - width?: number; -} - -/** - * Hover label configuration - */ -export interface HoverLabel { - align?: 'left' | 'right' | 'auto'; - bgcolor?: string | string[]; - bordercolor?: string | string[]; - font?: any; - namelength?: number | number[]; -} diff --git a/src/types/core/events.d.ts b/src/types/core/events.d.ts index a270e91efdd..521cbbed47b 100644 --- a/src/types/core/events.d.ts +++ b/src/types/core/events.d.ts @@ -1,107 +1,234 @@ /** * Event types * - * Defines the structure of Plotly events and event data. + * Plotly event payloads, the typed `on()` overloads on PlotlyHTMLElement, + * and event-related supporting types. */ -/** - * Common point data structure returned in events - */ -export interface PlotlyEventPoint { - /** - * Curve number (trace index) - */ +import type { Slider, SliderStep } from '../components/slider'; +import type { Datum } from '../lib/common'; +import type { AnimationFrameOpts, Frame, Transition } from './animation'; +import type { Config } from './config'; +import type { Data, PlotData } from './data'; +import type { Annotations, Layout, LayoutAxis, Point } from './layout'; + +// --------------------------------------------------------------------------- +// Point / datum types in events +// --------------------------------------------------------------------------- + +export interface PlotScatterDataPoint { curveNumber: number; + data: PlotData; + pointIndex: number; + pointNumber: number; + x: number; + xaxis: LayoutAxis; + y: number; + yaxis: LayoutAxis; +} - /** - * Point number within the trace - */ +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 PlotCoordinate { + x: number; + y: number; + pointNumber: number; +} + +export interface SelectionRange { + x: number[]; + y: number[]; +} + +export type PlotSelectedData = Partial; + +// --------------------------------------------------------------------------- +// Mouse / hover / selection events +// --------------------------------------------------------------------------- - /** - * Point index (for calculated data) - */ - pointIndex?: number; - - /** - * X value - */ - x?: any; - - /** - * Y value - */ - y?: any; - - /** - * Z value (for 3D plots) - */ - z?: any; - - /** - * Custom data - */ - customdata?: any; - - /** - * Full data for this trace - */ - data?: any; - - /** - * Full data for all traces - */ - fullData?: any; - - /** - * Additional properties - */ +export interface PlotMouseEvent { + points: PlotDatum[]; + event: MouseEvent; +} + +export interface PlotHoverEvent extends PlotMouseEvent { + xvals: Datum[]; + yvals: Datum[]; +} + +export interface PlotSelectionEvent { + points: PlotDatum[]; + range?: SelectionRange | undefined; + lassoPoints?: SelectionRange | undefined; +} + +// --------------------------------------------------------------------------- +// Restyle / Relayout events +// --------------------------------------------------------------------------- + +export interface PlotRestyleEventUpdate { [key: string]: any; } -/** - * Hover event data - */ -export interface PlotlyHoverEvent { - points: PlotlyEventPoint[]; +export type PlotRestyleEvent = [PlotRestyleEventUpdate, number[]]; + +export interface PlotRelayoutEvent extends Partial { + 'xaxis.range[0]'?: number; + 'xaxis.range[1]'?: number; + 'yaxis.range[0]'?: number; + 'yaxis.range[1]'?: number; + 'xaxis.autorange'?: boolean; + 'yaxis.autorange'?: boolean; +} + +// --------------------------------------------------------------------------- +// 3D scene / annotation / animation / legend events +// --------------------------------------------------------------------------- + +export interface PlotScene { + center: Point; + eye: Point; + up: Point; +} + +export interface ClickAnnotationEvent { + index: number; + annotation: Annotations; + fullAnnotation: Annotations; event: MouseEvent; } -/** - * Click event data - */ -export interface PlotlyClickEvent { - points: PlotlyEventPoint[]; +export interface FrameAnimationEvent { + name: string; + frame: Frame; + animation: { + frame: AnimationFrameOpts; + 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; } -/** - * Selection event data - */ -export interface PlotlySelectionEvent { - points: PlotlyEventPoint[]; - range?: any; - lassoPoints?: any; +// --------------------------------------------------------------------------- +// Slider events +// --------------------------------------------------------------------------- + +export interface SliderChangeEvent { + slider: Slider; + step: SliderStep; + interaction: boolean; + previousActive: number; } -/** - * Relayout event data (when layout changes) - */ -export interface PlotlyRelayoutEvent { - [key: string]: any; +export interface SliderStartEvent { + slider: Slider; } -/** - * Restyle event data (when trace style changes) - */ -export interface PlotlyRestyleEvent { - data: any[]; - traces: number[]; +export interface SliderEndEvent { + slider: Slider; + step: SliderStep; } -/** - * All Plotly event names - */ +// --------------------------------------------------------------------------- +// Sunburst / before-plot +// --------------------------------------------------------------------------- + +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 SunburstClickEvent { + event: MouseEvent; + nextLevel: string; + points: SunburstPlotDatum[]; +} + +export interface BeforePlotEvent { + data: Data[]; + layout: Partial; + config: Partial; +} + +// --------------------------------------------------------------------------- +// PlotlyHTMLElement +// --------------------------------------------------------------------------- + +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; +} + +// --------------------------------------------------------------------------- +// Event name union (kept for convenience) +// --------------------------------------------------------------------------- + export type PlotlyEventName = | 'plotly_afterexport' | 'plotly_afterplot' @@ -111,6 +238,7 @@ export type PlotlyEventName = | 'plotly_autosize' | 'plotly_beforeexport' | 'plotly_beforehover' + | 'plotly_beforeplot' | 'plotly_buttonclicked' | 'plotly_click' | 'plotly_clickannotation' @@ -122,6 +250,7 @@ export type PlotlyEventName = | 'plotly_legenddoubleclick' | 'plotly_redraw' | 'plotly_relayout' + | 'plotly_relayouting' | 'plotly_restyle' | 'plotly_selected' | 'plotly_selecting' diff --git a/src/types/core/graph-div.d.ts b/src/types/core/graph-div.d.ts index 7bdf1d81f29..2353c62bf10 100644 --- a/src/types/core/graph-div.d.ts +++ b/src/types/core/graph-div.d.ts @@ -3,118 +3,37 @@ * * The `gd` parameter appears throughout the codebase and represents * the graph div element with plotly-specific properties attached. + * Commonly referred to as `gd` in the codebase. */ import type { Config } from './config'; import type { FullData, PlotData } from './data'; import type { FullLayout, Layout } from './layout'; +/** + * Graph context containing environment info (mirrors Config for internal storage) + */ +export interface GraphContext extends Partial { + [key: string]: any; +} + /** * The main graph div element that Plotly operates on. * This is an HTMLDivElement with additional Plotly-specific properties. - * - * Commonly referred to as `gd` in the codebase. */ export interface GraphDiv extends HTMLDivElement { - /** - * Graph dimensions and margins - */ _context?: GraphContext; - - /** - * Is the plot currently being edited? - */ _editing?: boolean; - - /** - * Fully processed data traces (internal use) - */ _fullData?: FullData[]; - - /** - * Fully processed layout (internal use) - */ _fullLayout?: FullLayout; - - /** - * Has the plot been initialized? - */ _initialized?: boolean; - - /** - * Plotly framework metadata - */ _promises?: Promise[]; - - /** - * Current transaction ID for queuing operations - */ _transitionData?: any; - - /** - * Is the plot transitioning? - */ _transitioning?: boolean; - - /** - * Calculated data (internal use) - */ calcdata?: any[]; - - /** - * User-provided configuration options - */ config?: Partial; - - /** - * User-provided data traces - */ - data?: PlotData[]; - - /** - * Plotly-specific event emitter - */ + data?: Array>; emit?: (event: string, ...args: any[]) => void; - - /** - * User-provided layout configuration - */ layout?: Partial; - - // Add more as you discover them during migration [key: string]: any; } - -/** - * Graph context containing environment info - */ -export interface GraphContext { - autosizable?: boolean; - displaylogo?: boolean; - displayModeBar?: boolean | 'hover'; - doubleClick?: string | false; - editable?: boolean; - edits?: any; - fillFrame?: boolean; - frameMargins?: number; - linkText?: string; - locale?: string; - locales?: any; - mapboxAccessToken?: string; - modeBarButtons?: any; - modeBarButtonsToAdd?: any[]; - modeBarButtonsToRemove?: string[]; - plotGlPixelRatio?: number; - plotlyServerURL?: string; - queueLength?: number; - responsive?: boolean; - scrollZoom?: boolean; - sendData?: boolean; - setBackground?: string | Function; - showLink?: boolean; - showTips?: boolean; - staticPlot?: boolean; - toImageButtonOptions?: any; - topojsonURL?: string; - watermark?: boolean; -} diff --git a/src/types/core/layout.d.ts b/src/types/core/layout.d.ts index bc8b245e35e..fbbf14a7f70 100644 --- a/src/types/core/layout.d.ts +++ b/src/types/core/layout.d.ts @@ -1,203 +1,963 @@ /** * Layout types * - * Defines the structure of Plotly layout objects. - * Start with common properties and expand as needed. + * Comprehensive layout, axis, annotation, shape, scene, and supporting types. */ -import type { Selection } from '@types/d3' -import type { AxisType, Dash } from '../lib/common'; +import type { Selection } from '@types/d3'; +import type { TickFormatStop } from '../components/colorbar'; +import type { RangeSelector } from '../components/rangeselector'; +import type { Slider } from '../components/slider'; +import type { UpdateMenu } from '../components/updatemenu'; +import type { AxisType, Calendar, Color, Dash, Datum, DTickValue } from '../lib/common'; +import type { Transition } from './animation'; +import type { PlotType } from './data'; -/** - * User-provided layout configuration - */ -export interface Layout { - autosize?: boolean; - dragmode?: 'zoom' | 'pan' | 'select' | 'lasso' | 'orbit' | 'turntable' | false; - font?: Partial; - height?: number; - hovermode?: 'closest' | 'x' | 'y' | 'x unified' | 'y unified' | false; - legend?: Partial; - margin?: Partial; - paper_bgcolor?: string; - plot_bgcolor?: string; - showlegend?: boolean; - template?: any; - title?: string | Partial; - width?: number; - xaxis?: Partial; - yaxis?: Partial; - - // Multiple axes support (xaxis2, yaxis3, etc.) - [key: string]: any; +// --------------------------------------------------------------------------- +// Font +// --------------------------------------------------------------------------- + +export interface Font { + color: Color; + /** + * HTML font family - the typeface that will be applied by the web browser. + * Provide multiple font families, separated by commas, to indicate preference. + * @default "Arial, sans-serif" + */ + family: string; + /** + * Sets the shape and color of the shadow behind text. + * "auto" places minimal shadow and applies contrast text font color. + * @default "none" + */ + shadow: string; + /** + * @default 13 + */ + size: number; + /** + * Sets the weight (or boldness) of the font. + * @default "normal" + */ + weight: number | 'normal' | 'bold'; + /** + * Sets whether a font should be styled with a normal or italic face from its family. + * @default "normal" + */ + style: 'normal' | 'italic'; + /** + * Sets capitalization of text. + * @default "normal" + */ + textcase: 'normal' | 'word caps' | 'upper' | 'lower'; + /** + * Sets the variant of the font. + * @default "normal" + */ + variant: 'normal' | 'small-caps' | 'all-small-caps' | 'all-petite-caps' | 'petite-caps' | 'unicase'; + /** + * Sets the kind of decoration line(s) with text. + * @default "none" + */ + lineposition: + | 'none' + | 'under' + | 'over' + | 'through' + | 'under+over' + | 'over+under' + | 'over+through' + | 'through+over' + | 'through+under' + | 'under+through' + | 'under+over+through' + | 'under+through+over' + | 'over+under+through' + | 'over+through+under' + | 'through+under+over' + | 'through+over+under'; } -/** - * Fully processed layout with all defaults applied (internal use) - */ -export interface FullLayout extends Layout { - _modules?: any[]; - _basePlotModules?: any[]; - _plots?: { [key: string]: any }; - _subplot?: any[]; - _subplots?: SubplotInfo; - _size?: LayoutSize; - _legends?: string[]; - _infolayer?: Selection; - _zoomlayer?: Selection; - _paperdiv?: Selection; - _glcontainer?: Selection; - _calcInverseTransform?: (gd: any) => void; - _invTransform?: any; - _uid?: string; - _initialAutoSizeIsDone?: boolean; +// --------------------------------------------------------------------------- +// Padding / Margin / Domain +// --------------------------------------------------------------------------- - // Hover state - _hoverlayer?: any; - _hoverdata?: any[]; +export interface Padding { + t: number; + r: number; + b: number; + l: number; + editType: 'arraydraw'; +} - // Modebar - _modeBar?: any; +export interface Margin { + t: number; + b: number; + l: number; + r: number; + pad: number; +} - // Grid - grid?: any; +export interface Domain { + x: number[]; + y: number[]; + row: number; + column: number; +} - // Computed properties - _pushmargin?: { [key: string]: any }; - _basePlotModules?: any[]; +// --------------------------------------------------------------------------- +// Label / HoverLabel / Legend +// --------------------------------------------------------------------------- - [key: string]: any; +export interface Label { + bgcolor: string; + bordercolor: string; + font: Partial; } -/** - * Layout title configuration - */ -export interface LayoutTitle { +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. + * @default 15 + */ + namelength: number; +} + +export interface LegendTitle { + font: Partial; + side: 'top' | 'left' | 'top left' | 'top center' | 'top right'; 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; } -/** - * Layout margin configuration - */ -export interface LayoutMargin { - l: number; - r: number; - t: number; - b: number; - pad: number; - autoexpand?: boolean; +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'; + xref: 'container' | 'paper'; + y: number; + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + yref: 'container' | 'paper'; } -/** - * Font configuration (used throughout) - */ -export interface Font { +// --------------------------------------------------------------------------- +// DataTitle / PlotNumber +// --------------------------------------------------------------------------- + +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; +} + +// --------------------------------------------------------------------------- +// Axis name types +// --------------------------------------------------------------------------- + +type xYAxisNames = `${ + | '' + | `${2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}` + | `${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`}${''}`; + +export type XAxisName = `x${xYAxisNames}`; +export type YAxisName = `y${xYAxisNames}`; +export type AxisName = XAxisName | YAxisName; + +// --------------------------------------------------------------------------- +// Axis support types +// --------------------------------------------------------------------------- + +export interface AutoRangeOptions { + clipmax: DTickValue; + clipmin: DTickValue; + include: DTickValue; + maxallowed: DTickValue; + minallowed: DTickValue; +} + +export interface MinorAxisLayout { + dtick: DTickValue; + gridcolor: Color; + griddash: Dash; + gridwidth: number; + nticks: number; + showgrid: boolean; + tick0: DTickValue; + tickcolor: Color; + ticklen: number; + tickmode: 'auto' | 'linear' | 'array'; + ticks: 'outside' | 'inside' | ''; + tickvals: any[]; + tickwidth: number; +} + +export interface RangeBreak { + bounds: any[]; + dvalue: number; + enabled: boolean; + name: string; + pattern: 'day of week' | 'hour' | ''; + templateitemname: string; + values: any[]; +} + +export interface RangeSlider { + visible: boolean; + thickness: number; + range: [Datum, Datum]; + borderwidth: number; + bordercolor: string; + bgcolor: string; +} + +// --------------------------------------------------------------------------- +// Axis (base) +// --------------------------------------------------------------------------- + +export interface Axis { + visible: boolean; + color: Color; + title: Partial; + type: AxisType; + autorange: true | false | 'reversed' | 'min reversed' | 'max reversed' | 'min' | 'max'; + autorangeoptions: Partial; + rangemode: 'normal' | 'tozero' | 'nonnegative'; + range: any[]; + fixedrange: boolean; + + // Ticks + tickmode: 'auto' | 'linear' | 'array' | 'sync'; + 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; + 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; + showtickprefix: 'all' | 'first' | 'last' | 'none'; + ticksuffix: string; + showticksuffix: 'all' | 'first' | 'last' | 'none'; + showexponent: 'all' | 'first' | 'last' | 'none'; + exponentformat: 'none' | 'e' | 'E' | 'power' | 'SI' | 'B'; + minexponent: number; + separatethousands: boolean; + tickformat: string; + hoverformat: string; + calendar: Calendar; + tickformatstops: Array>; + spikedash: string; + spikemode: + | 'toaxis' + | 'across' + | 'marker' + | 'toaxis+across' + | 'toaxis+across+marker' + | 'across+marker' + | 'toaxis+marker'; + spikesnap: 'data' | 'cursor' | 'hovered data'; + + // Lines and Grids + showline: boolean; + linecolor: Color; + linewidth: number; + showgrid: boolean; + gridcolor: Color; + gridwidth: number; + zeroline: boolean; + zerolinecolor: Color; + zerolinewidth: number; + showdividers: boolean; + dividercolor: Color; + dividerwidth: number; + + autotypenumbers: 'convert types' | 'strict'; + labelalias: DTickValue; + maxallowed: DTickValue; + minallowed: DTickValue; +} + +// --------------------------------------------------------------------------- +// LayoutAxis (extends Axis for cartesian subplots) +// --------------------------------------------------------------------------- + +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; + angle: any; + griddash: Dash; + l2p: (v: Datum) => number; + + autotickangles: number[]; + insiderange: any[]; + matches: AxisName; + minor: Partial; + rangebreaks: Array>; + ticklabelmode: 'instant' | 'period'; + ticklabeloverflow: 'allow' | 'hide past div' | 'hide past domain'; + ticklabelposition: + | 'outside' + | 'inside' + | 'outside top' + | 'inside top' + | 'outside left' + | 'inside left' + | 'outside right' + | 'inside right' + | 'outside bottom' + | 'inside bottom'; + ticklabelstep: number; + tickson: 'labels' | 'boundaries'; + uirevision: DTickValue; +} + +// --------------------------------------------------------------------------- +// SceneAxis (extends Axis for 3D scenes) +// --------------------------------------------------------------------------- + +export interface SceneAxis extends Axis { + spikesides: boolean; + showbackground: boolean; + backgroundcolor: Color; + showaxeslabels: boolean; +} + +// --------------------------------------------------------------------------- +// Camera / Scene +// --------------------------------------------------------------------------- + +export interface Point { + x: number; + y: number; + z: number; +} + +export interface Camera { + up: Partial; + center: Partial; + eye: Partial; +} + +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; +} + +// --------------------------------------------------------------------------- +// Shape / ShapeLine / ShapeLabel +// --------------------------------------------------------------------------- + +export interface ShapeLine { color: string; - family: string; - size: number; - style?: 'normal' | 'italic'; - variant?: string; - weight?: number | string; + width: number; + dash: Dash; } -/** - * Legend configuration - */ -export interface Legend { - bgcolor?: string; - bordercolor?: string; - borderwidth?: number; - font?: Partial; - itemclick?: 'toggle' | 'toggleothers' | false; - itemdoubleclick?: 'toggle' | 'toggleothers' | false; - itemsizing?: 'trace' | 'constant'; - itemwidth?: number; - orientation?: 'v' | 'h'; - title?: Partial; - tracegroupgap?: number; - traceorder?: string; - valign?: 'top' | 'middle' | 'bottom'; - x?: number; - xanchor?: 'auto' | 'left' | 'center' | 'right'; - y?: number; - yanchor?: 'auto' | 'top' | 'middle' | 'bottom'; +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'; } -/** - * Legend title configuration - */ -export interface LegendTitle { - font?: Partial; - side?: 'top' | 'left' | 'top left'; +export interface Shape { + visible: boolean | 'legendonly'; + 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; + showlegend: boolean; + legendgroup: string; + legendgrouptitle: { + text: string; + font?: Partial; + }; + legendrank: number; +} + +// --------------------------------------------------------------------------- +// Annotations +// --------------------------------------------------------------------------- + +export interface Annotations extends Label { + visible: boolean; text: string; + textangle: string; + width: number; + height: number; + opacity: number; + align: 'left' | 'center' | 'right'; + valign: 'top' | 'middle' | 'bottom'; + borderpad: number; + borderwidth: number; + showarrow: boolean; + arrowcolor: string; + arrowhead: number; + startarrowhead: number; + arrowside: 'end' | 'start'; + arrowsize: number; + startarrowsize: number; + arrowwidth: number; + standoff: number; + startstandoff: number; + ax: number; + ay: number; + axref: 'pixel' | XAxisName; + ayref: 'pixel' | YAxisName; + xref: 'paper' | XAxisName; + x: number | string; + xanchor: 'auto' | 'left' | 'center' | 'right'; + xshift: number; + yref: 'paper' | YAxisName; + y: number | string; + yanchor: 'auto' | 'top' | 'middle' | 'bottom'; + yshift: number; + clicktoshow: false | 'onoff' | 'onout'; + xclick: any; + yclick: any; + hovertext: string; + hoverlabel: Partial; + captureevents: boolean; } -/** - * Layout axis configuration - */ -export interface LayoutAxis { - title?: string | Partial; - type?: AxisType; - autorange?: boolean | 'reversed'; - range?: [number | string, number | string]; - fixedrange?: boolean; - showgrid?: boolean; - showline?: boolean; - showticklabels?: boolean; - ticks?: '' | 'outside' | 'inside'; - tickmode?: 'auto' | 'linear' | 'array'; - tickvals?: any[]; - ticktext?: string[]; - tickangle?: number; - tickfont?: Partial; - zeroline?: boolean; - zerolinecolor?: string; - zerolinewidth?: number; - gridcolor?: string; - gridwidth?: number; - linecolor?: string; - linewidth?: number; - mirror?: boolean | 'ticks' | 'all' | 'allticks'; - anchor?: string; - side?: 'top' | 'bottom' | 'left' | 'right'; - overlaying?: string; - domain?: [number, number]; - position?: number; - - // Internal properties - _id?: string; - _name?: string; - _mainAxis?: boolean; - _anchorAxis?: any; +// --------------------------------------------------------------------------- +// Image +// --------------------------------------------------------------------------- - [key: string]: any; +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; } -/** - * Axis title configuration - */ -export interface AxisTitle { - font?: Partial; - standoff?: number; +// --------------------------------------------------------------------------- +// ModeBar / Icon +// --------------------------------------------------------------------------- + +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' + | 'zoomInMap' + | 'zoomInMapbox' + | 'zoomOutMap' + | 'zoomOutMapbox' + | 'resetViewMap' + | 'resetViewMapbox' + | 'togglespikelines' + | 'togglehover' + | 'hovercompare' + | 'hoverclosest' + | 'v1hovermode'; + +export type ButtonClickEvent = (gd: HTMLElement, 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: string; + title: string; + icon: string | Icon; + gravity?: string | undefined; + click: ButtonClickEvent; + attr?: string | undefined; + val?: any; + toggle?: boolean | undefined; +} + +export type ModeBarButtonAny = ModeBarDefaultButtons | ModeBarButton; + +// `ModeBar` is generated from src/components/modebar/attributes.ts. +// See src/types/generated/components/modebar.d.ts. +export type { ModeBar } from '../generated/components/modebar'; + +// --------------------------------------------------------------------------- +// Gauge / Delta / Indicator types +// --------------------------------------------------------------------------- + +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; + }; +} + +// --------------------------------------------------------------------------- +// Mapbox types +// --------------------------------------------------------------------------- + +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: boolean; + sourcetype: 'geojson' | 'vecotr' | 'raster' | 'image'; + source: any; + 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 MapboxBounds { + east: number; + north: number; + south: number; + west: number; +} + +export interface Mapbox { + domain: Partial; + accesstoken: string; + style: number | string; + center: Partial; + zoom: number; + bearing: number; + bounds: MapboxBounds; + pitch: number; + layers: Array>; + uirevision: number | string; + uid: string; +} + +// --------------------------------------------------------------------------- +// PolarLayout +// --------------------------------------------------------------------------- + +export interface PolarLayout { + domain: Partial; + sector: number[]; + hole: number; + bgcolor: Color; + radialaxis: Partial; + angularaxis: Partial; + gridshape: 'circular' | 'linear'; + uirevision: string | number; + uid: string; +} + +// --------------------------------------------------------------------------- +// Template +// --------------------------------------------------------------------------- + +export interface Template { + data?: { [type in PlotType]?: Array> } | undefined; + layout?: Partial | undefined; +} + +// --------------------------------------------------------------------------- +// Layout +// --------------------------------------------------------------------------- + +export interface Layout { + colorway: string[]; + title: 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; + subtitle: + | string + | Partial<{ + text: string; + font: 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; + /** + * Determines expansion of hover effects to other subplots. + * @default "overlaying" + */ + hoversubplots: 'single' | 'overlaying' | 'axis'; + calendar: Calendar; + + // Dotted property paths for Plotly.relayout convenience + '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': Partial; + 'yaxis.title': Partial; + + ternary: {}; + geo: {}; + map: Partial; + mapbox: Partial; + subplot: string; + radialaxis: Partial; + angularaxis: {}; + dragmode: + | 'zoom' + | 'pan' + | 'select' + | 'lasso' + | 'drawclosedpath' + | 'drawopenpath' + | 'drawline' + | 'drawrect' + | 'drawcircle' + | 'orbit' + | 'turntable' + | false; + orientation: number; + annotations: Array>; + shapes: Array>; + images: Array>; + updatemenus: Array>; + sliders: Array>; + legend: Partial; + font: Partial; + scene: Partial; + scene2: Partial; + scene3: Partial; + scene4: Partial; + scene5: Partial; + scene6: Partial; + scene7: Partial; + scene8: Partial; + scene9: 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; +} + +// --------------------------------------------------------------------------- +// Internal types (not in public API types) +// --------------------------------------------------------------------------- + /** - * Padding configuration + * Fully processed layout with all defaults applied (internal use) */ -export interface Padding { - b: number; - l: number; - r: number; - t: number; +export interface FullLayout extends Layout { + _modules?: any[]; + _basePlotModules?: any[]; + _plots?: { [key: string]: any }; + _subplot?: any[]; + _subplots?: SubplotInfo; + _size?: LayoutSize; + _legends?: string[]; + _infolayer?: Selection; + _zoomlayer?: Selection; + _paperdiv?: Selection; + _glcontainer?: Selection; + _calcInverseTransform?: (gd: any) => void; + _invTransform?: any; + _uid?: string; + _initialAutoSizeIsDone?: boolean; + _hoverlayer?: any; + _hoverdata?: any[]; + _modeBar?: any; + _pushmargin?: { [key: string]: any }; + + [key: string]: any; } /** diff --git a/src/types/core/template.d.ts b/src/types/core/template.d.ts new file mode 100644 index 00000000000..a686728c3a3 --- /dev/null +++ b/src/types/core/template.d.ts @@ -0,0 +1,47 @@ +/** + * Template types + * + * Defines the structure of Plotly templates. + */ + +import type { PlotData, PlotType } from './data'; +import type { Layout } from './layout'; + +/** + * Template configuration + */ +export interface Template { + /** + * Default trace configurations by type + */ + data?: { + [K in PlotType]?: Array>; + }; + + /** + * Default layout configuration + */ + layout?: Partial; +} + +/** + * Template figure type + */ +export interface TemplateFigure { + data?: PlotData[]; + layout?: Partial; +} + +/** + * Template validation result + */ +export interface ValidateTemplateResult { + code: string; + index?: number; + traceType?: string; + templateCount?: number; + dataCount?: number; + path?: string; + templateitemname?: string; + msg: string; +} diff --git a/src/types/generated/components/modebar.d.ts b/src/types/generated/components/modebar.d.ts new file mode 100644 index 00000000000..03d75a687c1 --- /dev/null +++ b/src/types/generated/components/modebar.d.ts @@ -0,0 +1,16 @@ +/** + * Generated from src/components/modebar/attributes.ts. + * Do not edit by hand — run `npm run gen:types`. + */ + +import type { Color } from '../../lib/common'; + +export interface ModeBar { + orientation?: 'v' | 'h'; + bgcolor?: Color; + color?: Color; + activecolor?: Color; + uirevision?: any; + add?: string | string[]; + remove?: string | string[]; +} diff --git a/src/types/generated/index.d.ts b/src/types/generated/index.d.ts new file mode 100644 index 00000000000..7ff397dc612 --- /dev/null +++ b/src/types/generated/index.d.ts @@ -0,0 +1,6 @@ +/** + * Generated type aggregator — do not edit by hand. + * Run `npm run gen:types` to regenerate. + */ + +export type { ModeBar } from './components/modebar'; diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 74a2d0da521..e96301ceb0f 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,20 +1,36 @@ /** * Central type definitions for plotly.js * - * This file exports all shared types from subdirectories. - * Import from here for convenience: - * * @example * import type { GraphDiv, Layout, PlotData } from '../types'; */ +// Library utilities +export * from './lib/common'; + // Core types -export * from './components/common'; +export * from './core/animation'; +export * from './core/api'; export * from './core/config'; export * from './core/data'; export * from './core/events'; export * from './core/graph-div'; export * from './core/layout'; -export * from './lib/common'; +export * from './core/template'; + +// Components +export * from './components/colorbar'; +export * from './components/common'; +export * from './components/rangeselector'; +export * from './components/slider'; +export * from './components/updatemenu'; + +// Plot/trace types export * from './plots/common'; +export * from './traces/box'; +export * from './traces/candlestick'; export * from './traces/common'; +export * from './traces/ohlc'; +export * from './traces/pie'; +export * from './traces/sankey'; +export * from './traces/violin'; diff --git a/src/types/lib/attributes.d.ts b/src/types/lib/attributes.d.ts new file mode 100644 index 00000000000..312a8f61ecf --- /dev/null +++ b/src/types/lib/attributes.d.ts @@ -0,0 +1,224 @@ +/** + * Attribute schema → TypeScript type extraction + * + * Plotly's attribute files describe both the runtime metadata (valType, dflt, + * editType, description, ...) AND the public-facing type. This file provides: + * + * - AttrInfo / AttributeMap: structural shape that attribute objects must + * satisfy (compile-time validation of attribute authoring) + * - AttrsToType: a mapped type that walks an attribute object and + * produces the corresponding TypeScript interface + * + * Author attribute files like: + * + * export const attributes = { + * orientation: { + * valType: 'enumerated', + * values: ['v', 'h'] as const, + * dflt: 'h', + * editType: 'modebar', + * }, + * bgcolor: { valType: 'color', editType: 'modebar' }, + * } as const satisfies AttributeMap; + * + * export type ModeBarAttributes = AttrsToType; + */ + +import type { Color, ColorScale, Datum, TypedArray } from './common'; + +// --------------------------------------------------------------------------- +// Attribute info — discriminated union by valType +// --------------------------------------------------------------------------- + +interface BaseAttrInfo { + description?: string; + editType?: string; + role?: 'object' | 'info' | 'style' | 'data'; + arrayOk?: boolean; + anim?: boolean; + dflt?: unknown; + /** Names a reusable item slot in template processing */ + _isLinkedToArray?: string; + /** Marker for axis/subplot id-style attributes */ + _isSubplotObj?: boolean; +} + +export interface DataArrayAttr extends BaseAttrInfo { + valType: 'data_array'; + dflt?: Datum[] | TypedArray; +} + +export interface NumberAttr extends BaseAttrInfo { + valType: 'number'; + dflt?: number; + min?: number; + max?: number; +} + +export interface IntegerAttr extends BaseAttrInfo { + valType: 'integer'; + dflt?: number; + min?: number; + max?: number; +} + +export interface StringAttr extends BaseAttrInfo { + valType: 'string'; + dflt?: string; + /** Allow whitespace-only strings */ + noBlank?: boolean; + strict?: boolean; + values?: readonly string[]; +} + +export interface BooleanAttr extends BaseAttrInfo { + valType: 'boolean'; + dflt?: boolean; +} + +export interface ColorAttr extends BaseAttrInfo { + valType: 'color'; + dflt?: string; +} + +export interface ColorScaleAttr extends BaseAttrInfo { + valType: 'colorscale'; + dflt?: ColorScale; +} + +export interface ColorListAttr extends BaseAttrInfo { + valType: 'colorlist'; + dflt?: string[]; +} + +export interface AngleAttr extends BaseAttrInfo { + valType: 'angle'; + dflt?: number | 'auto'; +} + +export interface SubplotIdAttr extends BaseAttrInfo { + valType: 'subplotid'; + dflt?: string; + regex?: string; +} + +export interface EnumeratedAttr extends BaseAttrInfo { + valType: 'enumerated'; + values: V; + dflt?: V[number]; + coerceNumber?: boolean; +} + +export interface FlagListAttr extends BaseAttrInfo { + valType: 'flaglist'; + flags: F; + extras?: readonly string[]; + dflt?: string; +} + +export interface InfoArrayAttr extends BaseAttrInfo { + valType: 'info_array'; + items?: AttrInfo | readonly AttrInfo[]; + freeLength?: boolean; + dimensions?: 1 | 2 | '1-2'; + dflt?: unknown[]; +} + +export interface AnyAttr extends BaseAttrInfo { + valType: 'any'; +} + +/** + * Union of all leaf attribute shapes (anything with a `valType`). + */ +export type AttrInfo = + | DataArrayAttr + | NumberAttr + | IntegerAttr + | StringAttr + | BooleanAttr + | ColorAttr + | ColorScaleAttr + | ColorListAttr + | AngleAttr + | SubplotIdAttr + | EnumeratedAttr + | FlagListAttr + | InfoArrayAttr + | AnyAttr; + +/** + * A nested map of attribute info. Properties may be leaf attributes + * (with a `valType`) or further-nested maps. A few special meta-keys + * (editType, role, _isLinkedToArray, etc.) live alongside attributes. + */ +export interface AttributeMap { + [key: string]: AttrInfo | AttributeMap | string | boolean | undefined; +} + +// --------------------------------------------------------------------------- +// Type-level conversion +// --------------------------------------------------------------------------- + +/** + * Wrap a type with `T | T[]` if `arrayOk: true` is set on the attribute. + */ +type ApplyArrayOk = A extends { arrayOk: true } ? V | V[] : V; + +/** + * Map a single leaf attribute (object with `valType`) to its TS value type. + */ +export type ValTypeToTS = A extends DataArrayAttr + ? Datum[] | TypedArray + : A extends NumberAttr + ? ApplyArrayOk + : A extends IntegerAttr + ? ApplyArrayOk + : A extends StringAttr + ? ApplyArrayOk + : A extends BooleanAttr + ? ApplyArrayOk + : A extends ColorAttr + ? ApplyArrayOk + : A extends ColorScaleAttr + ? ColorScale + : A extends ColorListAttr + ? Color[] + : A extends AngleAttr + ? ApplyArrayOk + : A extends SubplotIdAttr + ? string + : A extends EnumeratedAttr + ? ApplyArrayOk + : A extends FlagListAttr + ? ApplyArrayOk + : A extends InfoArrayAttr + ? unknown[] + : A extends AnyAttr + ? any + : never; + +/** + * Keys that are metadata about the container itself (not nested attributes). + * They are stripped during type extraction. + */ +type ReservedKey = 'editType' | 'role' | '_isLinkedToArray' | '_isSubplotObj' | '_arrayAttrRegexps' | '_deprecated'; + +/** + * Walk an AttributeMap and produce the corresponding TS interface shape. + * - Leaf entries (with `valType`) → their TS value type + * - Nested entries → recurse + * - Reserved meta-keys → omitted + * + * The `-readonly` modifier strips the readonly that `as const` introduces + * on the source attributes object. The attributes definition is genuinely + * static, but the derived user-facing type represents user-supplied input + * which should be mutable. + */ +export type AttrsToType = { + -readonly [K in keyof T as K extends ReservedKey ? never : K]?: T[K] extends AttrInfo + ? ValTypeToTS + : T[K] extends Record + ? AttrsToType + : never; +}; diff --git a/src/types/lib/common.d.ts b/src/types/lib/common.d.ts index 7d1da324dad..8f19b23a47f 100644 --- a/src/types/lib/common.d.ts +++ b/src/types/lib/common.d.ts @@ -1,78 +1,122 @@ /** * Common library utility types * - * Types for Lib utilities and helpers + * Utility types, scalars, and helpers used throughout plotly.js */ -/** - * Coercion function signature - */ -export type CoerceFn = (attr: string, dflt?: any) => any; +// --------------------------------------------------------------------------- +// Scalar / union types +// --------------------------------------------------------------------------- -/** - * Nested property path - */ -export type PropertyPath = string | string[]; +export type Datum = string | number | Date | null; -/** - * Color scale - */ -export type ColorScale = string | string[] | Array<[number, string]>; +export type TypedArray = + | Int8Array + | Uint8Array + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | Uint8ClampedArray + | Float32Array + | Float64Array; -/** - * Date format string - */ -export type DateFormat = string; +export type Color = + | string + | number + | Array + | Array>; -/** - * Single data value - */ -export type Datum = string | number | Date | null; +export type ColorScale = string | string[] | Array<[number, string]>; -/** - * Line dash styles - */ export type Dash = 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot'; -/** - * Supported calendar systems - */ export type Calendar = + | 'gregorian' | 'chinese' | 'coptic' | 'discworld' | 'ethiopian' - | 'gregorian' | 'hebrew' | 'islamic' - | 'jalali' | 'julian' | 'mayan' | 'nanakshahi' | 'nepali' | 'persian' + | 'jalali' | 'taiwan' | 'thai' | 'ummalqura'; -/** - * Axis type - */ -export type AxisType = '-' | 'category' | 'date' | 'linear' | 'log' | 'multicategory'; +export type AxisType = '-' | 'linear' | 'log' | 'date' | 'category' | 'multicategory'; + +export type DTickValue = number | string; + +export type MarkerSymbol = string | number | Array; + +export type XAnchor = 'auto' | 'left' | 'center' | 'right'; +export type YAnchor = 'auto' | 'top' | 'middle' | 'bottom'; +export type XRef = 'container' | 'paper'; +export type YRef = 'container' | 'paper'; + +// --------------------------------------------------------------------------- +// Error bars +// --------------------------------------------------------------------------- + +export interface ErrorOptions { + visible: boolean; + symmetric: boolean; + color: Color; + thickness: number; + width: number; +} + +export type ErrorBar = Partial & + ( + | { + type: 'constant' | 'percent'; + value: number; + valueminus?: number | undefined; + } + | { + type: 'data'; + array: Datum[]; + arrayminus?: Datum[] | undefined; + } + ); + +// --------------------------------------------------------------------------- +// Pattern +// --------------------------------------------------------------------------- + +export type PatternShape = '' | '/' | '\\' | 'x' | '-' | '|' | '+' | '.'; + +export interface Pattern { + shape?: PatternShape | PatternShape[] | undefined; + path?: string | undefined; + fillmode?: 'replace' | 'overlay' | undefined; + bgcolor?: string | string[] | undefined; + fgcolor?: string | string[] | undefined; + fgopacity?: number | undefined; + size?: number | number[] | undefined; + solidity?: number | number[] | undefined; +} + +// --------------------------------------------------------------------------- +// Internal / lib utility types +// --------------------------------------------------------------------------- + +export type CoerceFn = (attr: string, dflt?: any) => any; + +export type PropertyPath = string | string[]; + +export type DateFormat = string; -/** - * Numeric array - */ export type NumericArray = number[] | Float32Array | Float64Array; -/** - * Type that can be a single value or an array - */ export type Arrayable = T | T[]; -/** - * Rectangle bounds - */ export interface Rect { left: number; right: number; @@ -82,24 +126,15 @@ export interface Rect { height?: number; } -/** - * Point in 2D space - */ export interface Point2D { x: number; y: number; } -/** - * Point in 3D space - */ export interface Point3D extends Point2D { z: number; } -/** - * RGBA color - */ export interface RGBAColor { r: number; g: number; diff --git a/src/types/traces/box.d.ts b/src/types/traces/box.d.ts new file mode 100644 index 00000000000..d11e3e7584f --- /dev/null +++ b/src/types/traces/box.d.ts @@ -0,0 +1,42 @@ +/** + * Box plot trace type + */ + +import type { PlotData } from '../core/data'; +import type { Color, MarkerSymbol } from '../lib/common'; + +export interface BoxPlotMarker { + outliercolor: Color; + symbol: MarkerSymbol; + opacity: number; + size: number; + color: Color; + line: Partial<{ + color: Color; + width: number; + outliercolor: Color; + outlierwidth: number; + }>; +} + +export interface ScatterSelectedMarker { + opacity?: number; + color?: Color; + size?: number; +} + +export interface BoxPlotData extends PlotData { + type: 'box'; + x0: any; + y0: any; + width: number; + quartilemethod: 'linear' | 'exclusive' | 'inclusive'; + boxpoints: 'all' | 'outliers' | 'suspectedoutliers' | false; + jitter: number; + pointpos: number; + marker: Partial; + offsetgroup: string; + alignmentgroup: string; + selected: ScatterSelectedMarker; + unselected: ScatterSelectedMarker; +} diff --git a/src/types/traces/candlestick.d.ts b/src/types/traces/candlestick.d.ts new file mode 100644 index 00000000000..910818417fc --- /dev/null +++ b/src/types/traces/candlestick.d.ts @@ -0,0 +1,51 @@ +/** + * Candlestick trace type + */ + +import type { OhlcData } from './ohlc'; + +export interface CandlestickData { + type: 'candlestick'; + name: OhlcData['name']; + visible: OhlcData['visible']; + showlegend: OhlcData['showlegend']; + opacity: OhlcData['opacity']; + ids: OhlcData['ids']; + xperiod: OhlcData['xperiod']; + xperiod0: OhlcData['xperiod0']; + xperiodalignment: OhlcData['xperiodalignment']; + x: OhlcData['x']; + open: OhlcData['open']; + high: OhlcData['high']; + close: OhlcData['close']; + low: OhlcData['low']; + text: OhlcData['text']; + hovertext: OhlcData['hovertext']; + hoverinfo: OhlcData['hoverinfo']; + meta: OhlcData['meta']; + xaxis: OhlcData['xaxis']; + line: { width?: number | undefined }; + increasing: { + line?: + | { + color?: string | undefined; + width?: number | undefined; + } + | undefined; + }; + decreasing: { + line?: + | { + color?: string | undefined; + width?: number | undefined; + } + | undefined; + }; + hoverlabel: OhlcData['hoverlabel']; + /** + * Number between 0 and 1. + * Selects the width of the whiskers relative to the box's width. + * @default 0 + */ + whiskerwidth: number; +} diff --git a/src/types/traces/common.d.ts b/src/types/traces/common.d.ts index f3cec6513c4..95c1bdc855b 100644 --- a/src/types/traces/common.d.ts +++ b/src/types/traces/common.d.ts @@ -41,12 +41,7 @@ export interface TraceModule { /** * Trace defaults function signature */ -export type TraceDefaultsFn = ( - traceIn: any, - traceOut: any, - defaultColor: string, - layout: any -) => void; +export type TraceDefaultsFn = (traceIn: any, traceOut: any, defaultColor: string, layout: any) => void; /** * Trace attributes structure diff --git a/src/types/traces/ohlc.d.ts b/src/types/traces/ohlc.d.ts new file mode 100644 index 00000000000..6bf4b18e97a --- /dev/null +++ b/src/types/traces/ohlc.d.ts @@ -0,0 +1,95 @@ +/** + * OHLC trace type + */ + +import type { Calendar, Dash } from '../lib/common'; + +export type OhlcHoverInfo = + | 'x' + | 'y' + | 'z' + | 'text' + | 'name' + | 'x+y' + | 'x+z' + | 'x+text' + | 'x+name' + | 'y+z' + | 'y+text' + | 'y+name' + | 'z+text' + | 'z+name' + | 'x+y+z' + | 'x+y+text' + | 'x+y+name' + | 'y+z+text' + | 'y+z+name' + | 'z+text+name' + | 'all' + | 'none' + | 'skip'; + +export interface OhlcData { + type: 'ohlc'; + name: string; + visible: boolean | 'legendonly'; + showlegend: boolean; + legendgroup: string; + opacity: number; + ids: string[]; + x: string[]; + close: number[]; + open: number[]; + high: number[]; + low: number[]; + text: string | string[]; + hovertext: string | string[]; + hoverinfo: OhlcHoverInfo; + meta: any; + customdata: any[]; + xaxis: string; + yaxis: string; + xperiod: any; + xperiodalignment: 'start' | 'middle' | 'end'; + xperiod0: any; + line: { + width: number; + dash: Dash; + }; + selectedpoints: any; + increasing: { + line?: + | { + color?: string | undefined; + width?: number | undefined; + dash?: Dash | undefined; + } + | undefined; + }; + decreasing: { + line?: + | { + color?: string | undefined; + width?: number | undefined; + dash?: Dash | undefined; + } + | undefined; + }; + hoverlabel: { + bgcolor?: string | string[] | undefined; + bordercolor?: string | string[] | undefined; + font?: + | { + family?: string | string[] | undefined; + size?: number | undefined; + color?: string | string[] | undefined; + } + | undefined; + align?: 'left' | 'right' | 'auto' | undefined; + namelength?: number | number[] | undefined; + split?: boolean | undefined; + }; + tickwidth: number; + xcalendar: Calendar; + uirevision: any; +} diff --git a/src/types/traces/pie.d.ts b/src/types/traces/pie.d.ts new file mode 100644 index 00000000000..d49adf954e5 --- /dev/null +++ b/src/types/traces/pie.d.ts @@ -0,0 +1,126 @@ +/** + * Pie chart trace type + */ + +import type { PlotData } from '../core/data'; +import type { DataTitle, HoverLabel } from '../core/layout'; +import type { Datum } from '../lib/common'; + +export type PieColor = string | number; +export type PieColors = Array; + +export interface PieFont { + family: string | string[]; + size: number | number[]; + color: PieColor | PieColors; +} + +export interface PieDataTitle extends Pick { + font: Partial; +} + +export type PieTextPosition = 'inside' | 'outside' | 'auto' | 'none'; + +export type PieHoverInfo = + | 'all' + | 'none' + | 'skip' + | 'label' + | 'text' + | 'value' + | 'percent' + | 'name' + | 'label+text' + | 'label+value' + | 'label+percent' + | 'label+name' + | 'text+value' + | 'text+percent' + | 'text+name' + | 'value+percent' + | 'value+name' + | 'percent+name' + | 'label+text+value' + | 'label+text+percent' + | 'label+text+name' + | 'label+value+percent' + | 'label+value+name' + | 'label+percent+name' + | 'text+value+percent' + | 'text+value+name' + | 'text+percent+name' + | 'value+percent+name' + | 'label+text+value+percent' + | 'label+text+value+name' + | 'label+text+percent+name' + | 'label+value+percent+name' + | 'text+value+percent+name'; + +export interface PieDomain { + x: number[]; + y: number[]; + row: number; + column: number; +} + +export interface PieLine { + color: PieColor | PieColors; + width: number | number[]; +} + +export interface PieMarker { + colors: PieColors; + line: Partial; +} + +export interface PieHoverLabel { + bgcolor: PieColor | PieColors; + bordercolor: PieColor | PieColors; + font: PieFont; + align: HoverLabel['align'] | Array; + namelength: number | number[]; +} + +export type PieInsideTextOrientation = 'horizontal' | 'radial' | 'tangential' | 'auto'; + +export interface PieData + extends Pick< + PlotData, + | 'name' + | 'visible' + | 'showlegend' + | 'legendgroup' + | 'opacity' + | 'ids' + | 'labels' + | 'hovertext' + | 'automargin' + | 'textinfo' + | 'direction' + | 'hole' + | 'rotation' + > { + type: 'pie'; + title: Partial; + values: Array; + dlabel: number; + label0: number; + pull: number | number[]; + text: Datum | Datum[]; + textposition: PieTextPosition | PieTextPosition[]; + texttemplate: string | string[]; + hoverinfo: PieHoverInfo; + hovertemplate: string | string[]; + meta: number | string; + customdata: Datum[]; + domain: Partial; + marker: Partial; + textfont: PieFont; + hoverlabel: Partial; + insidetextfont: PieFont; + insidetextorientation: PieInsideTextOrientation; + outsidetextfont: PieFont; + scalegroup: string; + sort: boolean; + uirevision: number | string; +} diff --git a/src/types/traces/sankey.d.ts b/src/types/traces/sankey.d.ts new file mode 100644 index 00000000000..2972494d9de --- /dev/null +++ b/src/types/traces/sankey.d.ts @@ -0,0 +1,108 @@ +/** + * Sankey trace type + */ + +import type { HoverLabel } from '../core/layout'; +import type { Datum } from '../lib/common'; + +export type SankeyColor = string | number; +export type SankeyColors = Array; + +export interface SankeyFont { + family: string | string[]; + size: number | number[]; + color: SankeyColor | SankeyColors; +} + +export interface SankeyDataTitle { + font: Partial; + title: string; +} + +export type SankeyOrientation = 'v' | 'h'; + +export interface SankeyHoverLabel { + bgcolor: SankeyColor | SankeyColors; + bordercolor: SankeyColor | SankeyColors; + font: SankeyFont; + align: HoverLabel['align'] | Array; + namelength: number | number[]; +} + +export interface SankeyDomain { + row: number; + column: number; + x: number[]; + y: number[]; +} + +export interface SankeyNode { + color: SankeyColor[]; + customdata: Datum[]; + groups: SankeyNode[]; + hoverinfo: 'all' | 'none' | 'skip'; + hoverlabel: Partial; + hovertemplate: string | string[]; + label: Datum[]; + line: Partial<{ + color: SankeyColor; + width: number; + }>; + pad: number; + thickness: number; + x: number[]; + y: number[]; +} + +export interface SankeyColorscale { + cmax: number; + cmin: number; + colorscale: Array<[number, string]>; + label: string; + name: string; + templateitemname: string; +} + +export interface SankeyLink { + arrowlen: number; + color: SankeyColor | SankeyColor[]; + colorscale: Partial; + customdata: Datum[]; + hoverinfo: 'all' | 'none' | 'skip'; + hoverlabel: Partial; + hovertemplate: string | string[]; + hovercolor: SankeyColor | SankeyColor[]; + label: Datum[]; + line: Partial<{ + color: SankeyColor; + width: number; + }>; + source: number[]; + target: number[]; + value: number[]; +} + +export interface SankeyData { + type: 'sankey'; + name: string; + orientation: SankeyOrientation; + visible: boolean | 'legendonly'; + legend: string; + legendrank: number; + legendgrouptitle: Partial; + legendwidth: number; + ids: string[]; + hoverinfo: string; + meta: number | string; + customdata: Datum[]; + domain: Partial; + node: Partial; + link: Partial; + textfont: Partial; + selectpoints: string | number; + arrangement: 'snap' | 'perpendicular' | 'freeform' | 'fixed'; + hoverlabel: Partial; + valueformat: string; + valuesuffix: string; + uirevision: string | number; +} diff --git a/src/types/traces/violin.d.ts b/src/types/traces/violin.d.ts new file mode 100644 index 00000000000..dd2838fff79 --- /dev/null +++ b/src/types/traces/violin.d.ts @@ -0,0 +1,61 @@ +/** + * Violin trace type + */ + +import type { Color } from '../lib/common'; +import type { BoxPlotData } from './box'; + +export interface ViolinData { + type: 'violin'; + + x: BoxPlotData['x']; + y: BoxPlotData['y']; + x0: BoxPlotData['x0']; + y0: BoxPlotData['y0']; + name: BoxPlotData['name']; + + opacity: number; + + orientation: BoxPlotData['orientation']; + bandwidth: number; + scalegroup: string; + scalemode: 'width' | 'count'; + spanmode: 'soft' | 'hard' | 'manual'; + span: any[]; + line: Partial<{ + color: Color; + width: number; + }>; + fillcolor: Color; + points: BoxPlotData['boxpoints']; + jitter: BoxPlotData['jitter']; + pointpos: BoxPlotData['pointpos']; + width: BoxPlotData['width']; + marker: BoxPlotData['marker']; + text: BoxPlotData['text']; + hovertext: BoxPlotData['hovertext']; + hovertemplate: BoxPlotData['hovertemplate']; + box: Partial<{ + visible: boolean; + width: number; + fillcolor: Color; + line: Partial<{ + color: Color; + width: number; + }>; + }>; + meanline: Partial<{ + visible: boolean; + color: Color; + width: number; + }>; + side: 'both' | 'positive' | 'negative'; + + offsetgroup: BoxPlotData['offsetgroup']; + alignmentgroup: BoxPlotData['alignmentgroup']; + + selected: BoxPlotData['selected']; + unselected: BoxPlotData['unselected']; + + hoveron: 'violins' | 'points' | 'kde' | 'all' | string; +} diff --git a/tasks/generate_types.mjs b/tasks/generate_types.mjs new file mode 100644 index 00000000000..31e64346f1b --- /dev/null +++ b/tasks/generate_types.mjs @@ -0,0 +1,307 @@ +#!/usr/bin/env node +/** + * Generate flat .d.ts files from attribute schemas. + * + * Walks src/** /attributes.ts, finds each `export type XAttributes = AttrsToType<...>`, + * resolves the mapped type to its concrete shape via the TypeScript Compiler API, + * and emits flat declaration files into src/types/generated/. + * + * Each attribute file declares the canonical public type name via a JSDoc marker: + * + * @generates ModeBar + * + * That tells the generator to emit `export type ModeBar = { ... }` in the + * generated index, replacing any hand-written definition. + */ + +import * as fs from 'fs'; +import * as path from 'path'; +import * as ts from 'typescript'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const repoRoot = path.resolve(__dirname, '..'); + +const tsconfigPath = path.join(repoRoot, 'tsconfig.json'); +const generatedDir = path.join(repoRoot, 'src/types/generated'); + +// --------------------------------------------------------------------------- +// 1. Discover attribute files +// --------------------------------------------------------------------------- + +function findAttributeFiles(dir, results = []) { + const entries = fs.readdirSync(dir, { withFileTypes: true }); + for (const entry of entries) { + const full = path.join(dir, entry.name); + if (entry.isDirectory()) { + if (entry.name === 'node_modules' || entry.name === 'generated') continue; + findAttributeFiles(full, results); + } else if (entry.isFile() && entry.name === 'attributes.ts') { + results.push(full); + } + } + return results; +} + +const attributeFiles = findAttributeFiles(path.join(repoRoot, 'src')); +console.log(`Found ${attributeFiles.length} attribute file(s):`); +for (const f of attributeFiles) console.log(` ${path.relative(repoRoot, f)}`); + +if (attributeFiles.length === 0) { + console.log('No attribute files to process. Exiting.'); + process.exit(0); +} + +// --------------------------------------------------------------------------- +// 2. Build a TypeScript program over those files +// --------------------------------------------------------------------------- + +const tsconfigJson = ts.readConfigFile(tsconfigPath, ts.sys.readFile); +if (tsconfigJson.error) { + console.error('Failed to read tsconfig:', tsconfigJson.error); + process.exit(1); +} + +const parsed = ts.parseJsonConfigFileContent(tsconfigJson.config, ts.sys, repoRoot); + +const program = ts.createProgram(attributeFiles, { + ...parsed.options, + noEmit: true +}); + +const checker = program.getTypeChecker(); + +// --------------------------------------------------------------------------- +// 3. For each file, find @generates marker + extracted type, emit flat .d.ts +// --------------------------------------------------------------------------- + +/** + * Extract the "@generates X" name from the leading JSDoc of the const + * declaration (or any leading comment in the file). + */ +function findGeneratesMarker(sourceFile) { + const text = sourceFile.getFullText(); + const m = text.match(/@generates\s+([A-Za-z_][A-Za-z0-9_]*)/); + return m ? m[1] : null; +} + +/** + * Find the exported type alias whose name ends in `Attributes`. + * Returns the type alias declaration node. + */ +function findExtractedTypeAlias(sourceFile) { + let result = null; + ts.forEachChild(sourceFile, (node) => { + if ( + ts.isTypeAliasDeclaration(node) && + node.modifiers && + node.modifiers.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) && + node.name.text.endsWith('Attributes') + ) { + result = node; + } + }); + return result; +} + +/** + * Convert a resolved Type to a TypeNode using the checker, then print it + * using the TS printer. This produces real multi-line output and we + * post-process import("...") paths into relative references. + */ +const nodeBuilderFlags = + ts.NodeBuilderFlags.NoTruncation | + ts.NodeBuilderFlags.MultilineObjectLiterals | + ts.NodeBuilderFlags.WriteClassExpressionAsTypeLiteral | + ts.NodeBuilderFlags.UseFullyQualifiedType | + ts.NodeBuilderFlags.InTypeAlias; + +const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, removeComments: false }); + +/** + * Rewrite absolute `import("/abs/path")` references in printed output to + * paths relative to the destination directory. + */ +function rewriteImports(text, outputDir) { + return text.replace(/import\("([^"]+)"\)/g, (_, absPath) => { + let rel = path.relative(outputDir, absPath); + if (!rel.startsWith('.')) rel = './' + rel; + rel = rel.replace(/\.d\.ts$|\.ts$/, ''); + return `import("${rel}")`; + }); +} + +/** + * Replace inline `import("path").Name` references with bare `Name` and + * return the list of `import type` statements needed at the top of the + * generated file. + * + * Inline import types are valid TS but noisier than a hoisted import, + * which is what a human-author would write. + */ +function hoistImportTypes(text, selfName) { + const matches = [...text.matchAll(/import\("([^"]+)"\)\.(\w+)/g)]; + if (matches.length === 0) return { text, importStatements: [] }; + + // Group { path → set of names } + const byPath = new Map(); + for (const [, importPath, name] of matches) { + // Don't import the type we're declaring — it would collide. + if (name === selfName) continue; + if (!byPath.has(importPath)) byPath.set(importPath, new Set()); + byPath.get(importPath).add(name); + } + + // Replace inline references with bare names. + const replaced = text.replace(/import\("([^"]+)"\)\.(\w+)/g, (_, importPath, name) => { + if (name === selfName) return `import("${importPath}").${name}`; + return name; + }); + + // Sort by path, names within each import sorted alphabetically. + const importStatements = [...byPath.entries()] + .sort(([a], [b]) => a.localeCompare(b)) + .map(([importPath, names]) => { + const sorted = [...names].sort(); + return `import type { ${sorted.join(', ')} } from '${importPath}';`; + }); + + return { text: replaced, importStatements }; +} + +const dummyFile = ts.createSourceFile('__d.ts', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS); + +/** + * Convert a resolved Type into a printable declaration. If the type + * resolves to an object literal, emit it as an `interface` (so the + * canonical name appears in error messages and consumers can extend it + * via declaration merging). Otherwise — for unions, intersections, + * tuples, primitives — emit a `type` alias. + * + * Returns `{ kind: 'interface' | 'type', text }`. `text` is the body of + * the interface (without name/braces) or the RHS of the type alias. + */ +function formatDeclaration(type, enclosingDecl, outputDir) { + const typeNode = checker.typeToTypeNode(type, enclosingDecl, nodeBuilderFlags); + if (!typeNode) return { kind: 'type', text: 'unknown' }; + + if (ts.isTypeLiteralNode(typeNode)) { + // Emit each member separately so we can build an interface body. + const memberLines = typeNode.members.map((m) => + rewriteImports(printer.printNode(ts.EmitHint.Unspecified, m, dummyFile), outputDir) + ); + return { kind: 'interface', text: memberLines.join('\n') }; + } + + const text = rewriteImports(printer.printNode(ts.EmitHint.Unspecified, typeNode, dummyFile), outputDir); + return { kind: 'type', text }; +} + +/** + * Convert "ScatterAttributes" → "Scatter" or use the @generates marker. + */ +function deriveCanonicalName(typeName, marker) { + if (marker) return marker; + if (typeName.endsWith('Attributes')) return typeName.slice(0, -'Attributes'.length); + return typeName; +} + +const generated = []; // { canonicalName, typeName, sourceRel, body } + +for (const file of attributeFiles) { + const sourceFile = program.getSourceFile(file); + if (!sourceFile) { + console.warn(`Skipping ${file}: not in program`); + continue; + } + + const alias = findExtractedTypeAlias(sourceFile); + if (!alias) { + console.warn(` ⚠ ${path.relative(repoRoot, file)}: no exported "*Attributes" type alias`); + continue; + } + + const marker = findGeneratesMarker(sourceFile); + const canonical = deriveCanonicalName(alias.name.text, marker); + + const sym = checker.getSymbolAtLocation(alias.name); + if (!sym) { + console.warn(` ⚠ ${path.relative(repoRoot, file)}: could not resolve symbol`); + continue; + } + + // Determine where the .d.ts will land so we can compute relative imports. + const sourceRel = path.relative(repoRoot, file); + const outRel = sourceRel.replace(/^src\//, '').replace(/\/attributes\.ts$/, '.d.ts'); + const outPath = path.join(generatedDir, outRel); + const outputDir = path.dirname(outPath); + + const type = checker.getDeclaredTypeOfSymbol(sym); + const declaration = formatDeclaration(type, alias, outputDir); + + generated.push({ + canonicalName: canonical, + typeName: alias.name.text, + sourceRel, + outPath, + kind: declaration.kind, + body: declaration.text + }); + + console.log(` ✓ ${sourceRel} → ${canonical}`); +} + +// --------------------------------------------------------------------------- +// 4. Emit individual .d.ts files + aggregating index +// --------------------------------------------------------------------------- + +if (!fs.existsSync(generatedDir)) { + fs.mkdirSync(generatedDir, { recursive: true }); +} + +// Per-file generated declarations +for (const g of generated) { + fs.mkdirSync(path.dirname(g.outPath), { recursive: true }); + + const header = `/**\n * Generated from ${g.sourceRel}.\n * Do not edit by hand — run \`npm run gen:types\`.\n */\n\n`; + + const { text: hoistedBody, importStatements } = hoistImportTypes(g.body, g.canonicalName); + const importBlock = importStatements.length ? importStatements.join('\n') + '\n\n' : ''; + + let declaration; + if (g.kind === 'interface') { + const indented = hoistedBody + .split('\n') + .map((line) => (line.length ? ' ' + line : line)) + .join('\n'); + declaration = `export interface ${g.canonicalName} {\n${indented}\n}\n`; + } else { + declaration = `export type ${g.canonicalName} = ${hoistedBody};\n`; + } + + fs.writeFileSync(g.outPath, header + importBlock + declaration); +} + +// Aggregating index that re-exports each canonical type +const indexPath = path.join(generatedDir, 'index.d.ts'); +const indexLines = [ + '/**', + ' * Generated type aggregator — do not edit by hand.', + ' * Run `npm run gen:types` to regenerate.', + ' */', + '' +]; + +for (const g of generated.sort((a, b) => a.canonicalName.localeCompare(b.canonicalName))) { + const rel = g.sourceRel.replace(/^src\//, './').replace(/\/attributes\.ts$/, ''); + // Use `export type` re-export form — works for both interface and type alias, + // and signals to consumers that these are type-only re-exports. + indexLines.push(`export type { ${g.canonicalName} } from '${rel}';`); +} +indexLines.push(''); + +fs.writeFileSync(indexPath, indexLines.join('\n')); + +console.log(`\nWrote ${generated.length} generated type(s) to ${path.relative(repoRoot, generatedDir)}/`); +console.log(`Aggregator: ${path.relative(repoRoot, indexPath)}`); From a131cfe00fcae511aded6a21848f654d4c75efa1 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Wed, 6 May 2026 16:04:21 -0600 Subject: [PATCH 08/13] Convert modebar attributes to TS --- .../modebar/{attributes.js => attributes.ts} | 39 ++++++++++++------- src/components/modebar/defaults.js | 2 +- src/components/modebar/index.js | 2 +- 3 files changed, 26 insertions(+), 17 deletions(-) rename src/components/modebar/{attributes.js => attributes.ts} (75%) diff --git a/src/components/modebar/attributes.js b/src/components/modebar/attributes.ts similarity index 75% rename from src/components/modebar/attributes.js rename to src/components/modebar/attributes.ts index 06435784c42..4b35d183613 100644 --- a/src/components/modebar/attributes.js +++ b/src/components/modebar/attributes.ts @@ -1,31 +1,36 @@ 'use strict'; -var constants = require('./constants'); +import type { AttributeMap, AttrsToType } from '../../types/lib/attributes'; -module.exports = { +const constants = require('./constants'); + +/** + * @generates ModeBar + */ +const attributes = { editType: 'modebar', orientation: { valType: 'enumerated', - values: ['v', 'h'], + values: ['v', 'h'] as const, dflt: 'h', editType: 'modebar', - description: 'Sets the orientation of the modebar.' + description: 'Sets the orientation of the modebar.', }, bgcolor: { valType: 'color', editType: 'modebar', - description: 'Sets the background color of the modebar.' + description: 'Sets the background color of the modebar.', }, color: { valType: 'color', editType: 'modebar', - description: 'Sets the color of the icons in the modebar.' + description: 'Sets the color of the icons in the modebar.', }, activecolor: { valType: 'color', editType: 'modebar', - description: 'Sets the color of the active or hovered on icons in the modebar.' + description: 'Sets the color of the active or hovered on icons in the modebar.', }, uirevision: { valType: 'any', @@ -33,8 +38,8 @@ module.exports = { description: [ 'Controls persistence of user-driven changes related to the modebar,', 'including `hovermode`, `dragmode`, and `showspikes` at both the', - 'root level and inside subplots. Defaults to `layout.uirevision`.' - ].join(' ') + 'root level and inside subplots. Defaults to `layout.uirevision`.', + ].join(' '), }, add: { valType: 'string', @@ -46,8 +51,8 @@ module.exports = { 'Please note that these buttons will only be shown if they are', 'compatible with all trace types used in a graph.', 'Similar to `config.modeBarButtonsToAdd` option.', - 'This may include *' + constants.backButtons.join('*, *') + '*.' - ].join(' ') + 'This may include *' + constants.backButtons.join('*, *') + '*.', + ].join(' '), }, remove: { valType: 'string', @@ -57,7 +62,11 @@ module.exports = { description: [ 'Determines which predefined modebar buttons to remove.', 'Similar to `config.modeBarButtonsToRemove` option.', - 'This may include *' + constants.foreButtons.join('*, *') + '*.' - ].join(' ') - } -}; + 'This may include *' + constants.foreButtons.join('*, *') + '*.', + ].join(' '), + }, +} as const satisfies AttributeMap; + +export type ModeBarAttributes = AttrsToType; + +export default attributes; diff --git a/src/components/modebar/defaults.js b/src/components/modebar/defaults.js index a9930fa3fb6..36a80b73749 100644 --- a/src/components/modebar/defaults.js +++ b/src/components/modebar/defaults.js @@ -3,7 +3,7 @@ var Lib = require('../../lib'); var Color = require('../color'); var Template = require('../../plot_api/plot_template'); -var attributes = require('./attributes'); +var attributes = require('./attributes').default; module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { var containerIn = layoutIn.modebar || {}; diff --git a/src/components/modebar/index.js b/src/components/modebar/index.js index 1bae66bdf3b..d003c57f673 100644 --- a/src/components/modebar/index.js +++ b/src/components/modebar/index.js @@ -4,7 +4,7 @@ module.exports = { moduleType: 'component', name: 'modebar', - layoutAttributes: require('./attributes'), + layoutAttributes: require('./attributes').default, supplyLayoutDefaults: require('./defaults'), manage: require('./manage') From de168cae0ca8aa606d5939a066152fe1b85c4319 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Wed, 6 May 2026 16:06:38 -0600 Subject: [PATCH 09/13] Add type generation npm scripts --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 306a8528631..d961f928bc6 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,8 @@ "lint-fix": "npx @biomejs/biome format ./test/image/mocks --write; npx @biomejs/biome lint --write || true", "typecheck": "tsc --noEmit", "typecheck:watch": "tsc --noEmit --watch", + "gen:types": "node tasks/generate_types.mjs && npx @biomejs/biome format --write src/types/generated", + "gen:types:check": "npm run gen:types && git diff --exit-code src/types/generated/", "pretest": "node tasks/pretest.js", "test-jasmine": "karma start test/jasmine/karma.conf.js", "test-mock": "node tasks/test_mock.mjs", From 5f8654c50a2228f01f2063e3421e99caea9507ad Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Wed, 6 May 2026 16:13:42 -0600 Subject: [PATCH 10/13] Add type check steps to CI --- .github/workflows/ci.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79a69597525..aeedff98cf4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -572,6 +572,26 @@ jobs: - name: Run syntax tests on source files run: .github/scripts/test.sh source-syntax + typecheck: + needs: install-and-cibuild + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: ./.github/actions/setup-workspace + + - name: Type-check TypeScript sources + run: npm run typecheck + + generated-types-drift: + needs: install-and-cibuild + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: ./.github/actions/setup-workspace + + - name: Verify generated types are in sync with attribute sources + run: npm run gen:types:check + # ============================================================ # Standalone jobs (no dependencies on install-and-cibuild) # ============================================================ From eebf71e451488d463e20794c7082421807a01c00 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Wed, 6 May 2026 16:54:57 -0600 Subject: [PATCH 11/13] Update TS docs --- src/types/ARCHITECTURE.md | 194 +++++++++++++++++++ src/types/CONVERTING_ATTRIBUTES.md | 244 ++++++++++++++++++++++++ src/types/GENERATOR.md | 287 +++++++++++++++++++++++++++++ src/types/README.md | 83 +++------ src/types/SETUP.md | 92 +++++++++ 5 files changed, 846 insertions(+), 54 deletions(-) create mode 100644 src/types/ARCHITECTURE.md create mode 100644 src/types/CONVERTING_ATTRIBUTES.md create mode 100644 src/types/GENERATOR.md create mode 100644 src/types/SETUP.md diff --git a/src/types/ARCHITECTURE.md b/src/types/ARCHITECTURE.md new file mode 100644 index 00000000000..1f4d8ec9317 --- /dev/null +++ b/src/types/ARCHITECTURE.md @@ -0,0 +1,194 @@ +# Type System Architecture + +How TypeScript types are organized in plotly.js. + +## Three layers + +``` +┌──────────────────────────────────────────────────────────────┐ +│ Consumer surface (what `npm install plotly.js` exposes) │ +│ lib/index.d.ts — wired via package.json#types │ +│ Curated re-exports of public types + 'export as namespace │ +│ Plotly' for namespace and global usage. │ +└──────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────┐ +│ Internal authoring surface │ +│ src/types/index.d.ts — re-exports everything (internal) │ +└──────────────────────────────────────────────────────────────┘ + │ │ + ▼ ▼ +┌──────────────────────────┐ ┌────────────────────────────────┐ +│ Hand-written types │ │ Generated types │ +│ src/types/core/*.d.ts │ │ src/types/generated/... │ +│ src/types/lib/*.d.ts │ │ │ +│ src/types/components/ │ │ Derived from attributes.ts │ +│ src/types/traces/ │ │ via AttrsToType │ +│ src/types/plots/ │ │ │ +└──────────────────────────┘ └────────────────────────────────┘ +``` + +`lib/index.d.ts` deliberately omits internal types (`FullLayout`, +`GraphDiv`, the `AttributeMap`/`AttrsToType` machinery, `*Internal` shapes, +the `TraceModule` lifecycle interface, etc.) so consumers see a clean +public API. The internal types remain accessible to plotly.js's own code +through the `src/types/` re-exports. + +The split: + +- **Generated types** are the single source of truth for everything in + Plotly's attribute schema. Layout, traces, components — anything you + configure when calling `Plotly.newPlot`. +- **Hand-written types** cover everything the schema doesn't describe: + events, internal runtime state, public API function signatures, + utility types. + +When an `attributes.ts` file is converted, its generated type **replaces** +the corresponding hand-written one. The hand-written file gets a re-export: + +```ts +// src/types/core/layout.d.ts +// `ModeBar` is generated from src/components/modebar/attributes.ts. +export type { ModeBar } from '../generated/components/modebar'; +``` + +Consumers don't notice — externally they still write +`import { type ModeBar } from 'plotly.js'`. Internal callers still +import from the same path inside `src/types/`. + +## Public vs. private (the underscore convention) + +Plotly's runtime stores two kinds of state on graph elements: + +- **Public** — user-supplied, what `Plotly.newPlot(gd, data, layout)` accepts +- **Private** (`_` prefix) — fully-resolved versions Plotly computes after + applying defaults, defined modules, and so on + +This split is reflected in the types: + +| User-facing | Internal | Where defined | +|---|---|---| +| `Layout` | `FullLayout` | `Layout` is generated; `FullLayout extends Layout` is hand-written | +| `PlotData` | `FullData` | Same pattern | +| (n/a) | `GraphDiv` (the `gd` param) | Hand-written — DOM element with `_fullLayout`, `_fullData`, `calcdata`, etc. | + +Internal types use index signatures (`[key: string]: any`) liberally to +allow incremental migration without blocking. As `_` properties get +discovered during JS→TS conversion, add them to `FullLayout`/`FullData`/etc. + +## Directory layout + +``` +src/types/ +├── index.d.ts # main re-export hub +├── core/ # public + internal types for the core API +│ ├── layout.d.ts # Layout, FullLayout, axis/annotation/shape types +│ ├── data.d.ts # PlotData, FullData, marker/line types +│ ├── config.d.ts # Config, Edits, ToImgopts +│ ├── events.d.ts # PlotMouseEvent, PlotlyHTMLElement, etc. +│ ├── api.d.ts # public API function signatures (newPlot, etc.) +│ ├── animation.d.ts # Frame, Transition, AnimationOpts +│ ├── template.d.ts # Template, ValidateTemplateResult +│ └── graph-div.d.ts # GraphDiv (gd parameter), GraphContext +│ +├── components/ # public types for layout components +│ ├── colorbar.d.ts +│ ├── slider.d.ts +│ ├── updatemenu.d.ts +│ ├── rangeselector.d.ts +│ └── common.d.ts +│ +├── traces/ # per-trace public types +│ ├── box.d.ts # BoxPlotData, BoxPlotMarker +│ ├── pie.d.ts # PieData, PieMarker, ... +│ ├── sankey.d.ts +│ ├── violin.d.ts +│ ├── ohlc.d.ts +│ ├── candlestick.d.ts +│ └── common.d.ts # internal TraceModule lifecycle +│ +├── plots/ # internal subplot types (PlotInfo, etc.) +│ └── common.d.ts +│ +├── lib/ # primitives + the schema-extraction machinery +│ ├── common.d.ts # Color, Datum, TypedArray, MarkerSymbol, ... +│ └── attributes.d.ts # AttributeMap, AttrsToType, ValTypeToTS +│ +└── generated/ # output of `npm run gen:types` + ├── index.d.ts # auto-generated re-export aggregator + ├── components/ + │ └── modebar.d.ts # one .d.ts per converted attributes.ts + └── (more as conversion proceeds) +``` + +## How the generation works + +``` +src/components/modebar/attributes.ts + │ + │ const attributes = { ... } as const satisfies AttributeMap; + │ export type ModeBarAttributes = AttrsToType; + │ export default attributes; + │ + ▼ +[ tasks/generate_types.mjs walks attributes.ts files ] + │ + │ Uses TS Compiler API: checker.typeToTypeNode(checker.getDeclaredTypeOfSymbol(...)) + │ Then ts.createPrinter().printNode() flattens the mapped type + │ + ▼ +src/types/generated/components/modebar.d.ts + │ import type { Color } from '../../lib/common'; + │ + │ export interface ModeBar { + │ orientation?: 'v' | 'h'; + │ bgcolor?: Color; + │ ... + │ } + │ + ▼ +src/types/core/layout.d.ts re-exports `ModeBar` from generated/. +src/types/index.d.ts re-exports from layout.d.ts (internal). +lib/index.d.ts re-exports `ModeBar` to consumers (public). +``` + +## What's hand-written and stays that way + +The schema doesn't describe: + +- **Events** — `PlotMouseEvent`, `PlotHoverEvent`, `LegendClickEvent`, + `PlotlyHTMLElement` and its `on()` overloads. These are runtime contracts. +- **Public API function signatures** — `Plotly.newPlot`, `relayout`, + `restyle`, etc. Live in `src/types/core/api.d.ts`. +- **Internal runtime state** — `FullLayout._modules`, `GraphDiv._fullData`, + `_calcInverseTransform`, etc. Live alongside the public types but in + separate `Full*`/`*Internal` interfaces. +- **Utility types the mapped type bottoms out on** — `Color`, `Datum`, + `TypedArray`, `MarkerSymbol`, `Pattern`, `ErrorBar`, etc. Live in + `src/types/lib/common.d.ts`. The generator emits `import("../../lib/common").Color` + references that resolve to these hand-written primitives. + +## Adding internal properties + +When converting a JS file to TS and discovering an internal property like +`fullLayout._someFlag`, add it to the corresponding `Full*` interface: + +```ts +// src/types/core/layout.d.ts +export interface FullLayout extends Layout { + _modules?: any[]; + _someFlag?: boolean; // add new ones here + [key: string]: any; +} +``` + +The `[key: string]: any` index signature is intentional — it absorbs +unknown internal properties so JS code can be migrated piecewise without +type errors. + +## See also + +- [SETUP.md](SETUP.md) — toolchain and npm scripts +- [CONVERTING_ATTRIBUTES.md](CONVERTING_ATTRIBUTES.md) — the conversion recipe +- [GENERATOR.md](GENERATOR.md) — internals of `tasks/generate_types.mjs` diff --git a/src/types/CONVERTING_ATTRIBUTES.md b/src/types/CONVERTING_ATTRIBUTES.md new file mode 100644 index 00000000000..86295e936ed --- /dev/null +++ b/src/types/CONVERTING_ATTRIBUTES.md @@ -0,0 +1,244 @@ +# Converting Attribute Files to TypeScript + +This is the **active workflow** for migrating Plotly's `attributes.js` files +to TypeScript. Each conversion turns one attribute file into the single +source of truth for both the runtime schema and the public TypeScript type. + +## Why + +Today, attribute metadata lives in `src/.../attributes.js` files and the +matching TypeScript types live separately in `src/types/`. They drift. + +After conversion, the `attributes.ts` file IS the schema, and the TypeScript +type is *derived from it* via a mapped type. Both agree by construction. + +## Recipe + +Pick any `attributes.js` file. The recipe is the same for every one. A +small file takes ~10 minutes; a complex trace might take an hour. + +### 1. Rename and stub the imports + +Rename `src//attributes.js` → `src//attributes.ts`. + +At the top of the file, add: + +```ts +'use strict'; + +import type { AttributeMap, AttrsToType } from '../../types/lib/attributes'; +// (adjust the relative path so it points at src/types/lib/attributes) +``` + +### 2. Convert the export + +Replace `module.exports = { ... };` with: + +```ts +/** + * @generates ModeBar + */ +const attributes = { + // ... existing attribute definitions go here +} as const satisfies AttributeMap; + +export type ModeBarAttributes = AttrsToType; + +export default attributes; +``` + +Three things to notice: + +- **`@generates ModeBar`** — declares the canonical public type name. The + `.d.ts` generator uses this to name the output. +- **`as const satisfies AttributeMap`** — `as const` preserves literal types + like `values: ['v', 'h']`; `satisfies AttributeMap` validates structure + without widening. +- **`export default`** — runtime consumers (`require('./attributes').default`) + get the object. Co-existing `export type` exposes the derived TS type. + +### 3. Fix array literals and string literals + +Anywhere an attribute uses a literal-array of options, add `as const`: + +```ts +// Before +values: ['v', 'h'], + +// After +values: ['v', 'h'] as const, +``` + +Without this, TypeScript widens to `string[]` and you lose the union. + +### 4. Update consumers' `require()` calls + +Find every JS file that `require('./attributes')` (relative to the converted +file) and update to `.default`: + +```js +// Before +var attributes = require('./attributes'); + +// After +var attributes = require('./attributes').default; +``` + +ESBuild handles the runtime; this update is just for the JS-level CommonJS +interop pattern the project already uses for converted files. + +### 5. Run the type generator + +```bash +npm run gen:types +``` + +This walks all `attributes.ts` files, resolves their derived types via the +TypeScript Compiler API, writes flattened declaration files into +`src/types/generated/`, and formats the output with biome (so single +quotes, line widths, and other style choices match the rest of the +codebase). + +### 6. Replace the hand-written type in `src/types/` + +Find the corresponding hand-written type (likely in +`src/types/core/layout.d.ts`, `src/types/core/data.d.ts`, or a component +file). Replace its `interface` or `type` definition with a re-export: + +```ts +// Before +export interface ModeBar { + activecolor: Color; + add: ModeBarDefaultButtons | ModeBarDefaultButtons[]; + // ... +} + +// After +// `ModeBar` is generated from src/components/modebar/attributes.ts. +export type { ModeBar } from '../generated/components/modebar'; +``` + +If the hand-written type was richer than the schema (e.g. used a narrowed +union where the schema says `string`), document the gap in a comment or +file an issue. Do not silently lose ergonomics — either improve the schema +(add `values: [...]`) or layer a hand-written refinement on top. + +### 7. Verify + +```bash +npm run typecheck # zero errors +npm run schema # schema regenerates clean +git diff test/plot-schema.json + # the relevant section should be byte-identical + # to before the conversion +``` + +If the schema diff is non-empty, the attribute object's runtime shape +changed somewhere — most often a missed `as const` or a typo. Compare +character-by-character with the original `.js` file. + +### 8. Commit + +```bash +git add src//attributes.ts \ + src//index.js src//defaults.js # (whichever consumers you updated) \ + src/types/core/.d.ts \ + src/types/generated/ +git commit -m "Convert attributes to TypeScript" +``` + +The conversion is a single self-contained commit per file. + +## Worked example: modebar + +See [`src/components/modebar/attributes.ts`](../components/modebar/attributes.ts) +for the canonical example. The full conversion changed: + +- `src/components/modebar/attributes.js` → `src/components/modebar/attributes.ts` + (with `as const satisfies AttributeMap` and `@generates ModeBar`) +- `.default` added to `require('./attributes')` in `index.js` and `defaults.js` +- The hand-written `ModeBar` interface in `src/types/core/layout.d.ts` was + removed and replaced with + `export type { ModeBar } from '../generated/components/modebar';` + +Schema output verified byte-identical (2547 bytes) before and after the +conversion. + +## What stays hand-written + +The schema does not describe these — they remain in `src/types/`: + +- **Events** (`PlotMouseEvent`, `LegendClickEvent`, etc.) +- **Public API function signatures** (`Plotly.newPlot`, `relayout`, ...) +- **Internal types** (`FullLayout._modules`, `GraphDiv._fullData`, ...) +- **Utility types** the mapped type bottoms out on (`Color`, `Datum`, + `TypedArray`, `MarkerSymbol`, ...) + +If you find yourself converting one of these, stop and ask. + +## What if my type doesn't match the hand-written one? + +Almost certainly the hand-written one was wrong, narrowed for ergonomics, or +based on an older schema. Order of operations: + +1. **Compare**. Print both: `npm run gen:types`, then look at the generated + `.d.ts` next to the hand-written one. +2. **If schema is too loose** (e.g. `string` where the hand-written type had + a typed union of valid values), check whether the schema's `values` array + could be expanded. The schema is the authoritative truth — fix it there. +3. **If the hand-written type had additional fields** not in the schema, + they're probably internal/runtime-only and should stay hand-written + (move them to a separate `*Internal.d.ts` file or a parallel interface). +4. **If the schema has fields the hand-written type lacked**, that's a free + coverage win — accept the generated type. + +## Order of conversion (for parallel work) + +Pick from this priority list. Lower-numbered items are smaller / simpler. + +### Tier 1: small components (good first conversions) +- `src/components/modebar/attributes.js` — **DONE** (canonical example) +- `src/components/rangeslider/attributes.js` — small, self-contained +- `src/plots/gl3d/layout/attributes.js` — tiny (one `subplotid`) +- `src/plots/cartesian/attributes.js` — small +- `src/components/fx/attributes.js` — uses helpers (`fontAttrs`, shared sub-objects) + +> Note: `src/components/color/attributes.js` is named like an attribute file +> but actually just exports color constants. It doesn't follow the schema +> pattern and shouldn't be converted with this recipe. + +### Tier 2: small traces +- `src/traces/scatterpolargl/attributes.js` +- `src/traces/histogram2dcontour/attributes.js` +- `src/traces/candlestick/attributes.js` +- `src/traces/funnelarea/attributes.js` +- `src/traces/barpolar/attributes.js` + +### Tier 3: medium components and traces +- Sliders, updatemenus, rangeselector, colorbar attribute files +- `scatter3d`, `scattergl`, `surface`, `mesh3d` + +### Tier 4: large traces +- `scatter` (the big one — many modes and shared subobjects) +- `bar`, `histogram`, `box`, `violin` +- Layout itself + +### Tier 5: shared subobject attributes +- `font_attributes`, `hover_label_attributes`, etc. +- These are imported by many trace files; conversion needs care so the + imported types remain compatible. + +## Working in parallel + +Multiple converters can work on different attribute files in parallel. The +generator is idempotent — every run produces the same output for the same +inputs — so merge conflicts are rare and limited to: + +- `src/types/generated/index.d.ts` (the aggregator) — auto-resolved by + rerunning `npm run gen:types` after merge +- The hand-written type files when removing types — manual conflict if two + converters touch the same file + +Coordinate: claim a file in PR description before starting. Use Tier 1 +files for first-time converters to learn the recipe; reserve Tier 4 for +experienced contributors. diff --git a/src/types/GENERATOR.md b/src/types/GENERATOR.md new file mode 100644 index 00000000000..7e6660168e3 --- /dev/null +++ b/src/types/GENERATOR.md @@ -0,0 +1,287 @@ +# Type Generator Internals + +`tasks/generate_types.mjs` walks `src/**/attributes.ts` files and emits +flat `.d.ts` declarations into `src/types/generated/`. This document +describes how it works for maintainers who want to extend or debug it. + +## Pipeline + +``` +1. Discover find all src/**/attributes.ts files +2. Parse create a TS Program with the project's tsconfig +3. Extract for each file, find `export type *Attributes = ...` +4. Resolve use TypeChecker to compute the concrete type +5. Print use ts.createPrinter to render members +6. Rewrite turn absolute import("...") paths into relative +7. Hoist inline import("...").Name → top-of-file `import type` +8. Decide object-literal type → `interface`, otherwise `type` alias +9. Emit write per-file .d.ts files + an aggregator index +10. Format `biome format --write` (chained from npm script, not the script itself) +``` + +## Key TypeScript Compiler API calls + +The trick to flattening a mapped type like `AttrsToType` +is to convert the resolved `Type` back to a `TypeNode` (an AST node), then +print that node: + +```js +const sym = checker.getSymbolAtLocation(typeAliasDecl.name); +const type = checker.getDeclaredTypeOfSymbol(sym); + +const typeNode = checker.typeToTypeNode(type, typeAliasDecl, nodeBuilderFlags); +const text = printer.printNode(ts.EmitHint.Unspecified, typeNode, dummySourceFile); +``` + +Without `typeToTypeNode`, you'd get `checker.typeToString` output which is +single-line and harder to format. + +## Node builder flags + +```js +ts.NodeBuilderFlags.NoTruncation +| ts.NodeBuilderFlags.MultilineObjectLiterals +| ts.NodeBuilderFlags.WriteClassExpressionAsTypeLiteral +| ts.NodeBuilderFlags.UseFullyQualifiedType +| ts.NodeBuilderFlags.InTypeAlias +``` + +- **NoTruncation** — print full union/intersection without `...` ellipsis +- **MultilineObjectLiterals** — one property per line +- **UseFullyQualifiedType** — emit `import("/abs/path").TypeName` for + external references, which we then rewrite to relative paths +- **InTypeAlias** — render as if writing a type alias body + +## The `@generates` marker + +Each `attributes.ts` declares its canonical public type name via JSDoc: + +```ts +/** + * @generates ModeBar + */ +const attributes = { ... } as const satisfies AttributeMap; +export type ModeBarAttributes = AttrsToType; +``` + +The generator regex-greps each source file for `@generates X` and uses `X` +as the canonical name. This lets the generated type take a different name +from the local `*Attributes` alias, which matters because the public API +type names (`ModeBar`, `Slider`, `Layout`) follow a different convention +than the per-attribute-file naming. + +## Import path rewriting + +`UseFullyQualifiedType` produces output like +`import("/abs/path/src/types/lib/common").Color`. The generator rewrites +these to relative paths from the output file's directory: + +```js +text = text.replace(/import\("([^"]+)"\)/g, (_, absPath) => { + let rel = path.relative(outputDir, absPath); + if (!rel.startsWith('.')) rel = './' + rel; + rel = rel.replace(/\.d\.ts$|\.ts$/, ''); + return `import("${rel}")`; +}); +``` + +Result: `import("../../lib/common").Color` — portable across machines. + +## Import hoisting + +Inline `import("path").Name` references are valid TypeScript but read +poorly. After path rewriting, the generator collects every reference and +emits a single `import type` block at the top of the file: + +```ts +// Before hoisting (TS Compiler default): +export interface ModeBar { + bgcolor?: import("../../lib/common").Color; + color?: import("../../lib/common").Color; +} + +// After hoisting: +import type { Color } from '../../lib/common'; + +export interface ModeBar { + bgcolor?: Color; + color?: Color; +} +``` + +The hoister deduplicates names, groups by path, and sorts alphabetically +within each import statement. A self-reference (where the imported name +matches the type being declared) is left as inline `import("...")` to +avoid colliding with the local declaration. + +## interface vs type alias + +When the resolved type is an object shape (`TypeLiteralNode`), the +generator emits an `interface`: + +```ts +export interface ModeBar { ... } +``` + +For unions, intersections, tuples, or primitives — anything that isn't +an object literal — it falls back to a `type` alias: + +```ts +export type ScatterMode = 'lines' | 'markers' | 'lines+markers'; +``` + +Interfaces give better error messages, support declaration merging, and +match the project's hand-written types. The discrimination happens via +`ts.isTypeLiteralNode(typeNode)` before printing. + +## Why generated types are mutable + +The source attribute objects use `as const` for literal-type preservation, +which makes `typeof attributes` deeply `Readonly<...>`. To prevent that +`readonly` from leaking into the user-facing type, `AttrsToType` uses +the `-readonly` modifier in its mapped type: + +```ts +export type AttrsToType = { + -readonly [K in keyof T as K extends ReservedKey ? never : K]?: ... +}; +``` + +So consumers get plain mutable properties even though the source is +locked-in literal types. This happens at the type level — the generator +itself doesn't manipulate readonly modifiers. + +## Output structure + +``` +src/types/generated/ +├── index.d.ts # aggregator (re-exports each canonical name) +└── components/ + └── modebar.d.ts # one file per converted attribute file +``` + +The output directory mirrors the source: `src/components/modebar/attributes.ts` +becomes `src/types/generated/components/modebar.d.ts`. + +## Aggregator + +The aggregator (`src/types/generated/index.d.ts`) is a one-line-per-type +re-export: + +```ts +export type { ModeBar } from './components/modebar'; +export type { Slider } from './components/sliders'; +// ... one line per canonical name, sorted alphabetically +``` + +It exists so consumers can `import type { ModeBar, Slider } from '../types/generated'` +without knowing the file structure. In practice, the hand-written +`src/types/core/*.d.ts` files re-export from the per-file generated +declarations directly, so the aggregator is mostly for ad-hoc consumers. + +## valType → TypeScript + +The leaf-type mapping lives in `src/types/lib/attributes.d.ts` as the +`ValTypeToTS` mapped type. Summary: + +| valType | TS produced | +|---|---| +| `data_array` | `Datum[] \| TypedArray` | +| `number`, `integer` | `number` (or `number \| number[]` if `arrayOk`) | +| `string` | `string`, narrowed to `values[number]` if `values` provided | +| `boolean` | `boolean` | +| `color` | `Color` | +| `colorscale` | `ColorScale` | +| `colorlist` | `Color[]` | +| `angle` | `number \| 'auto'` | +| `subplotid` | `string` | +| `enumerated` | `values[number]` (literal union) | +| `flaglist` | `string` (combinatorial expansion not yet implemented) | +| `info_array` | `unknown[]` | +| `any` | `any` | + +`arrayOk: true` wraps the result in `T | T[]`. + +Reserved keys stripped from the output: `editType`, `role`, +`_isLinkedToArray`, `_isSubplotObj`, `_arrayAttrRegexps`, `_deprecated`. + +## Extending the generator + +### Adding a new valType + +1. Add an interface to `src/types/lib/attributes.d.ts` (e.g. `interface FooAttr extends BaseAttrInfo { valType: 'foo'; ... }`) +2. Add it to the `AttrInfo` union +3. Add a branch to `ValTypeToTS` mapping it to the desired TS type +4. Run `npm run gen:types` to verify output +5. Run `npm run typecheck` to ensure no regressions + +### Improving flaglist support + +Currently flag lists like `hoverinfo` map to `string`. To produce a +combinatorial union of valid `+`-joined combinations: + +```ts +type Combinations = ... // template literal magic +``` + +This is doable but produces large unions (15+ members for `hoverinfo`). +Consider whether the type-check cost is worth the autocomplete win. + +### Supporting nested attribute objects with metadata + +Some attribute files have shapes like: + +```ts +{ + role: 'object', + editType: 'calc', + foo: { valType: 'number', ... }, + bar: { valType: 'string', ... }, +} +``` + +The mapped type's reserved-key stripping handles `role`/`editType` at the +top level via `ReservedKey`. If a new metadata key gets introduced, +add it to the `ReservedKey` union in `src/types/lib/attributes.d.ts`. + +## Debugging + +If the generator emits `unknown` for a type that should be concrete: + +```bash +node tasks/generate_types.mjs # see the generated output +npm run typecheck # see what tsc thinks the type is +``` + +Inspect with the TS Compiler API directly: + +```js +node -e ' +const ts = require("typescript"); +const program = ts.createProgram(["path/to/attributes.ts"], { /* tsconfig opts */ }); +const checker = program.getTypeChecker(); +// ... probe symbols and types +' +``` + +The `formatDeclaration` function in `tasks/generate_types.mjs` can be +invoked on any `TypeAliasDeclaration` to see what would be emitted. + +## CI integration + +`npm run gen:types:check` runs the generator and then +`git diff --exit-code src/types/generated/`. If the working tree differs, +exit code 1 — meaning a developer changed an attributes.ts file but +didn't commit the regenerated declarations. + +This is wired into `.github/workflows/ci.yml` as the `generated-types-drift` +job, alongside a sibling `typecheck` job. Both gate on the root +`install-and-cibuild` job and run in parallel on every PR. + +A drift failure typically means one of: + +- An `attributes.ts` file was edited without re-running `npm run gen:types` +- Biome's formatter config changed and existing generated files would re-format +- The generator itself changed in a way that affects existing output + +All three are legitimate signals worth investigating. diff --git a/src/types/README.md b/src/types/README.md index a4071c340e2..699aca3cd0c 100644 --- a/src/types/README.md +++ b/src/types/README.md @@ -1,63 +1,38 @@ -# Types Directory +# TypeScript in plotly.js -Centralized TypeScript type definitions for plotly.js. +This directory documents the TypeScript conversion in progress. -## Quick Import +| Doc | Audience | +|---|---| +| [SETUP.md](SETUP.md) | First-time contributor — toolchain overview, npm scripts | +| [ARCHITECTURE.md](ARCHITECTURE.md) | Anyone working with types — directory layout, public/private split | +| [CONVERTING_ATTRIBUTES.md](CONVERTING_ATTRIBUTES.md) | **Contributor doing conversion work** — step-by-step recipe | +| [GENERATOR.md](GENERATOR.md) | Maintainer extending or debugging the type generator | -```typescript -// Import from main index (recommended) -import type { GraphDiv, Layout, PlotData } from '../types'; +## Status -// Or use path alias -import type { GraphDiv } from '@types'; -``` +- TypeScript build infrastructure: ✅ done +- Public type surface in `src/types/`: ✅ done +- `AttributeMap` / `AttrsToType` machinery: ✅ done +- `.d.ts` generator (TS Compiler API + biome format): ✅ done +- Consumer entry point (`lib/index.d.ts`, wired via `package.json#types`): ✅ done +- CI gates (`typecheck` + `generated-types-drift`): ✅ done +- First attribute file converted (modebar): ✅ done +- Conversion of remaining attribute files: 🚧 in progress -## Directory Structure +The published consumer surface lives at [`lib/index.d.ts`](../../lib/index.d.ts). +This `src/types/` directory is the authoring location — internal types live +here, public types are re-exported through `lib/index.d.ts` to consumers. -``` -types/ -├── index.d.ts # Main export - import from here -├── core/ # Core Plotly types (GraphDiv, Layout, Data, Config, Events) -├── traces/ # Trace-specific types -├── components/ # Component-specific types -├── plots/ # Plot-specific types -└── lib/ # Utility types -``` +## How to help -## Most Common Types +If you want to convert an attribute file: -### GraphDiv -```typescript -import type { GraphDiv } from '../types'; +1. Read [CONVERTING_ATTRIBUTES.md](CONVERTING_ATTRIBUTES.md) +2. Pick a file from the priority list at the bottom of that doc +3. Claim it in a PR description +4. Follow the recipe +5. Submit a PR -function draw(gd: GraphDiv): void { - const layout = gd._fullLayout; - const data = gd._fullData; -} -``` - -### Layout -```typescript -import type { Layout } from '../types'; - -function updateLayout(layout: Partial): void { - layout.title = 'New Title'; -} -``` - -### PlotData (Traces) -```typescript -import type { PlotData, ScatterTrace } from '../types'; - -function processTrace(trace: PlotData): void { - if (trace.type === 'scatter') { - const scatter = trace as ScatterTrace; - } -} -``` - -## Adding New Types - -1. Create file in appropriate subdirectory -2. Export from `index.d.ts` -3. Use in your TypeScript files +Each conversion is a single self-contained commit and takes 10-60 minutes +depending on file size. diff --git a/src/types/SETUP.md b/src/types/SETUP.md new file mode 100644 index 00000000000..e2875dc4918 --- /dev/null +++ b/src/types/SETUP.md @@ -0,0 +1,92 @@ +# TypeScript Setup + +Quick reference for the TypeScript toolchain in plotly.js. + +## What's installed + +- **TypeScript** (`typescript ^5.9.3`) — type checker only, never emits JS +- **ts-node** (`^10.9.2`) — runs TS scripts directly (build helpers, generator) +- **@types/node**, **@types/d3** — third-party type definitions +- esbuild handles `.ts` natively for bundling — no plugins needed + +## Two tools, two jobs + +| Tool | Job | +|---|---| +| **esbuild** | Bundle for production. Strips types, transpiles to ES2016, emits `dist/plotly.js`. Fast (~450ms full build). Does **not** check types. | +| **tsc** | Type-check only. Reads `.ts` and `.js` (with `allowJs: true`), reports errors, no output. Slower (~2-5s) but catches bugs. | + +`tsconfig.json` sets `noEmit: true` so tsc never writes files. esbuild is the build system; tsc is the verifier. + +## Configuration + +- [tsconfig.json](../../tsconfig.json) — type checker config +- [esbuild-config.js](../../esbuild-config.js) — bundler config + +Both target ES2016. Strict mode is currently **off** (`strict: false`) for incremental adoption — types tighten over time as files convert. + +## npm scripts + +```bash +npm run typecheck # tsc --noEmit, errors reported, no output +npm run typecheck:watch # incremental rechecking on change + +npm run gen:types # walk attributes.ts files → src/types/generated/, then biome format +npm run gen:types:check # generate then `git diff --exit-code` (CI drift check) + +npm run schema # rebuild test/plot-schema.json from source attributes +npm run bundle # esbuild → dist/plotly.js +npm run build # full production build +``` + +## Workflows + +**Editing during development:** + +```bash +# Terminal 1 +npm run typecheck:watch + +# Terminal 2 — bundle/dev server +npm start +``` + +**Before commit:** + +```bash +npm run typecheck +npm run gen:types # if you converted an attribute file +npm run schema # if attribute files changed +``` + +**CI** runs both checks as separate jobs (see `.github/workflows/ci.yml`): + +```bash +npm run typecheck # validates the type system is internally consistent +npm run gen:types:check # fails if generated types are stale or unformatted +``` + +## How esbuild handles `.ts` + +esbuild has built-in TypeScript support — it strips types and transpiles, no extra config. The catch: when a JS file `require()`s a TS file with a default export, esbuild's CommonJS interop wraps it in `{ default: ... }`. Existing project pattern is to update consumers: + +```js +// Before (JS importing JS) +var attributes = require('./attributes'); + +// After (JS importing TS with `export default`) +var attributes = require('./attributes').default; +``` + +This shows up when converting `attributes.js` → `attributes.ts`. See [CONVERTING_ATTRIBUTES.md](CONVERTING_ATTRIBUTES.md) step 4. + +## Performance + +For a codebase of ~750 source files: + +| Operation | Time | +|---|---| +| `tsc --noEmit` cold | ~2-5s | +| `tsc --noEmit --watch` incremental | ~100ms | +| esbuild full bundle | ~450ms | +| `npm run gen:types` | <1s for current converted set | From c11bca12cd908283e526237cb906a5dd2210e282 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Wed, 6 May 2026 16:55:35 -0600 Subject: [PATCH 12/13] Add entry point to types --- lib/index.d.ts | 284 +++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 285 insertions(+) create mode 100644 lib/index.d.ts diff --git a/lib/index.d.ts b/lib/index.d.ts new file mode 100644 index 00000000000..86d7cbd1d6f --- /dev/null +++ b/lib/index.d.ts @@ -0,0 +1,284 @@ +/** + * TypeScript type definitions for plotly.js. + * + * Public API surface for consumers installing plotly.js as a dependency. + * + * Usage: + * + * import Plotly from 'plotly.js'; + * // or + * import * as Plotly from 'plotly.js'; + * // or + * import { newPlot, Layout, Data } from 'plotly.js'; + * + * const data: Data[] = [{ type: 'scatter', x: [1, 2, 3], y: [4, 5, 6] }]; + * const layout: Partial = { title: { text: 'Demo' } }; + * await Plotly.newPlot(div, data, layout); + * + * Internal types (FullLayout, GraphDiv internals, the AttrsToType machinery, + * etc.) live alongside the source under src/types/ but are intentionally not + * re-exported from this entry point. + */ + +export as namespace Plotly; + +// --------------------------------------------------------------------------- +// Primitives & utility types +// --------------------------------------------------------------------------- + +export type { + AxisType, + Calendar, + Color, + ColorScale, + Dash, + Datum, + DTickValue, + ErrorBar, + ErrorOptions, + MarkerSymbol, + Pattern, + PatternShape, + TypedArray, + XAnchor, + XRef, + YAnchor, + YRef, +} from '../src/types/lib/common'; + +// --------------------------------------------------------------------------- +// Layout, axes, components, and supporting shapes +// --------------------------------------------------------------------------- + +export type { + Annotations, + AutoRangeOptions, + Axis, + AxisName, + ButtonClickEvent, + Camera, + DataTitle, + Delta, + Domain, + Font, + Gauge, + GaugeBar, + GaugeLine, + HoverLabel, + Icon, + Image, + Label, + Layout, + LayoutAxis, + Legend, + LegendTitle, + Mapbox, + MapboxBounds, + MapboxCenter, + MapboxLayers, + MapboxSymbol, + Margin, + MinorAxisLayout, + ModeBar, + ModeBarButton, + ModeBarButtonAny, + ModeBarDefaultButtons, + Padding, + PlotNumber, + Point, + PolarLayout, + RangeBreak, + RangeSlider, + Scene, + SceneAxis, + Shape, + ShapeLabel, + ShapeLine, + Template, + Threshold, + XAxisName, + YAxisName, +} from '../src/types/core/layout'; + +// --------------------------------------------------------------------------- +// Trace data +// --------------------------------------------------------------------------- + +export type { + Data, + PlotData, + PlotMarker, + PlotType, + ScatterData, + ScatterLine, + ScatterMarker, + ScatterMarkerLine, +} from '../src/types/core/data'; + +// --------------------------------------------------------------------------- +// Specialized trace types +// --------------------------------------------------------------------------- + +export type { BoxPlotData, BoxPlotMarker } from '../src/types/traces/box'; +export type { CandlestickData } from '../src/types/traces/candlestick'; +export type { OhlcData } from '../src/types/traces/ohlc'; +export type { + PieData, + PieDataTitle, + PieDomain, + PieFont, + PieHoverInfo, + PieHoverLabel, + PieInsideTextOrientation, + PieLine, + PieMarker, + PieTextPosition, +} from '../src/types/traces/pie'; +export type { + SankeyData, + SankeyColorscale, + SankeyDataTitle, + SankeyDomain, + SankeyFont, + SankeyHoverLabel, + SankeyLink, + SankeyNode, + SankeyOrientation, +} from '../src/types/traces/sankey'; +export type { ViolinData } from '../src/types/traces/violin'; + +// --------------------------------------------------------------------------- +// Components +// --------------------------------------------------------------------------- + +export type { + ColorBar, + ColorBarTitle, + ExponentFormat, + LengthMode, + ShowTickLabel, + TickFormatStop, + TickLabelOverflow, + TickLabelPosition, +} from '../src/types/components/colorbar'; + +export type { CurrentValue, Slider, SliderStep } from '../src/types/components/slider'; + +export type { + UpdateMenu, + UpdateMenuButton, + UpdateMenuDirection, + UpdateMenuType, +} from '../src/types/components/updatemenu'; + +export type { + RangeSelector, + RangeSelectorButton, + RangeSelectorStep, +} from '../src/types/components/rangeselector'; + +// --------------------------------------------------------------------------- +// Animation & template +// --------------------------------------------------------------------------- + +export type { + AnimationFrameOpts, + AnimationOpts, + Frame, + Transition, + TransitionEasing, +} from '../src/types/core/animation'; + +export type { + TemplateFigure, + ValidateTemplateResult, +} from '../src/types/core/template'; + +// --------------------------------------------------------------------------- +// Configuration +// --------------------------------------------------------------------------- + +export type { + Config, + ConfigEdits, + DownloadImgopts, + Edits, + ToImageButtonOptions, + ToImgopts, +} from '../src/types/core/config'; + +// --------------------------------------------------------------------------- +// Events & runtime DOM types +// --------------------------------------------------------------------------- + +export type { + BeforePlotEvent, + ClickAnnotationEvent, + FrameAnimationEvent, + LegendClickEvent, + PlotCoordinate, + PlotDatum, + PlotHoverEvent, + PlotlyEventName, + PlotlyHTMLElement, + PlotMouseEvent, + PlotRelayoutEvent, + PlotRestyleEvent, + PlotRestyleEventUpdate, + PlotScatterDataPoint, + PlotScene, + PlotSelectedData, + PlotSelectionEvent, + SelectionRange, + SliderChangeEvent, + SliderEndEvent, + SliderStartEvent, + SunburstClickEvent, + SunburstPlotDatum, +} from '../src/types/core/events'; + +// --------------------------------------------------------------------------- +// Public API functions +// --------------------------------------------------------------------------- + +export { + addFrames, + addTraces, + animate, + deleteFrames, + deleteTraces, + downloadImage, + extendTraces, + makeTemplate, + moveTraces, + newPlot, + prependTraces, + purge, + react, + redraw, + register, + relayout, + restyle, + setPlotConfig, + toImage, + update, + validate, +} from '../src/types/core/api'; + +export type { + DefaultIcons, + PlotlyDataLayoutConfig, + PlotlyModule, + Root, + RootOrData, + StaticPlots, + ValidateResult, +} from '../src/types/core/api'; + +// --------------------------------------------------------------------------- +// Default export — matches the runtime CommonJS shape +// --------------------------------------------------------------------------- + +import * as PlotlyAPI from '../src/types/core/api'; +declare const Plotly: typeof PlotlyAPI; +export default Plotly; diff --git a/package.json b/package.json index d961f928bc6..a11ed3f616e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "The open source javascript graphing library that powers plotly", "license": "MIT", "main": "./lib/index.js", + "types": "./lib/index.d.ts", "webpack": "./dist/plotly.js", "repository": { "type": "git", From 04261b2266d5fb644ae87151f6c6b0289828b930 Mon Sep 17 00:00:00 2001 From: Cameron DeCoster Date: Wed, 6 May 2026 17:00:37 -0600 Subject: [PATCH 13/13] Update file name case check --- tasks/test_syntax.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tasks/test_syntax.js b/tasks/test_syntax.js index dcb4ff5e538..7abe7db9f58 100644 --- a/tasks/test_syntax.js +++ b/tasks/test_syntax.js @@ -193,12 +193,7 @@ function assertFileNames() { var base = path.basename(file); if( - base === 'README.md' || - base === 'CONTRIBUTING.md' || - base === 'CHANGELOG.md' || - base === 'SECURITY.md' || - base === 'BUILDING.md' || - base === 'CUSTOM_BUNDLE.md' || + base.endsWith('.md') || base === 'CITATION.cff' || file.indexOf('mathjax') !== -1 ) return;