@milaboratories/miplots4 1.0.171 → 1.0.172
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bubble/ChartRenderer.js +143 -146
- package/dist/bubble/ChartRenderer.js.map +1 -1
- package/dist/dendro/ChartRenderer.js +175 -174
- package/dist/dendro/ChartRenderer.js.map +1 -1
- package/dist/scatterplot/ChartRenderer.js +149 -152
- package/dist/scatterplot/ChartRenderer.js.map +1 -1
- package/dist/scatterplot-umap/ChartRenderer.js +152 -155
- package/dist/scatterplot-umap/ChartRenderer.js.map +1 -1
- package/dist/utils/arrangeLegendParts.js +35 -35
- package/dist/utils/arrangeLegendParts.js.map +1 -1
- package/dist/utils/getContinuousLegendTicks.js +5 -8
- package/dist/utils/getContinuousLegendTicks.js.map +1 -1
- package/dist/utils/getSizeLegendItem.d.ts +3 -0
- package/dist/utils/getSizeLegendItem.js +15 -0
- package/dist/utils/getSizeLegendItem.js.map +1 -0
- package/dist/utils/numberFormat.d.ts +1 -0
- package/dist/utils/numberFormat.js +9 -4
- package/dist/utils/numberFormat.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartRenderer.js","sources":["../../src/scatterplot-umap/ChartRenderer.tsx"],"sourcesContent":["import { chartCartesian } from '@d3fc/d3fc-chart';\nimport type { CartesianChart } from '@d3fc/d3fc-chart/src/cartesian';\nimport type { ScaleLinear } from 'd3-scale';\nimport { scaleLinear, scaleLog, scaleOrdinal, scaleSqrt, scaleSymlog } from 'd3-scale';\nimport { select } from 'd3-selection';\nimport type { D3ZoomEvent, ZoomBehavior, ZoomTransform } from 'd3-zoom';\nimport { zoom, zoomIdentity } from 'd3-zoom';\nimport type { ReactElement } from 'react';\nimport type { Root } from 'react-dom/client';\nimport { createRoot } from 'react-dom/client';\nimport { Error } from '../common/Error';\nimport type { DotAesItem, LegendData, LegendItem } from '../common/types';\nimport {\n BLACK,\n DEFAULT_HEIGHT,\n DEFAULT_WIDTH,\n MAX_LEGEND_GRADIENT_HEIGHT,\n MAX_SHOWN_UNIQUE_VALUES_IN_LABELS,\n MIN_LEGEND_GRADIENT_HEIGHT,\n TITLE_LINE_HEIGHT,\n TITLE_MARGIN\n} from '../constants';\nimport { splitTextByWidth } from '../discrete/utils';\nimport { DEFAULT_DOT_AES, MIN_MARGIN } from '../scatterplot/constants';\nimport { createAesGetter } from '../scatterplot/utils/createAesGetter';\nimport { getTicksAndFormat } from '../scatterplot/utils/getTicksAndFormat';\nimport type { Label } from '../scatterplot/utils/getVisibleLabels';\nimport { createLabelPositioner } from '../scatterplot/utils/getVisibleLabels';\nimport type { ColumnName, ScatterplotEventHandlers } from '../types';\nimport { isContinuousAes } from '../types';\nimport type { ScatterplotUmapLegendInfo } from '../types/scatterplot-umap';\nimport { getContinuousColorScale } from '../utils/getContinuousColorScale';\nimport { getContinuousLegendTicks } from '../utils/getContinuousLegendTicks';\nimport { TextMeasurer } from '../utils/TextMeasurer/TextMeasurer';\nimport { SVGLayer } from './components/SVGLayer';\nimport { LEGEND_OFFSET, PADDINGS, TITLE_LINE } from './constants';\nimport type { CurveLayer, DotsLayer, ScatterplotUmapLayer, ScatterplotUmapSettingsImpl } from './SettingsImpl';\nimport type {\n AesGetters,\n CaptionsSizes,\n ChartScales, ChartSizes,\n Dot,\n DotsExtents,\n LassoControlsState,\n Margins,\n Polygon,\n SVGLayerProps,\n} from './types';\n// @ts-ignore\nimport { seriesSvgMulti, seriesWebglMulti, seriesWebglPoint } from '@d3fc/d3fc-series';\n// @ts-ignore\nimport { webglFillColor } from '@d3fc/d3fc-webgl';\n// @ts-ignore\nimport { pointer } from '@d3fc/d3fc-pointer';\nimport { polygonContains } from 'd3-polygon';\nimport KDBush from 'kdbush';\nimport { DataFrameProvider } from '../common/useDataFrame';\nimport { DataFrame } from '../DataFrame';\nimport { arrangeLegendParts } from '../utils/arrangeLegendParts';\nimport { GET_BLACK, getColorWithFakeOpacity, stringToNumberRgba } from './colors';\n\nfunction convertDotRToSymbolSize(r:number) {\n return (r / 2.35) * (r / 2.35) * 64;\n}\n\nfunction isDotInsidePolygons(x:number, y:number, polygons: Polygon[]) {\n if (polygons.length === 0) {\n return true;\n }\n return polygons.some((p) => p.closed && p.points.length > 2 && polygonContains(p.points, [x, y]));\n}\n\nfunction getGettersFromLayers(\n dataFrame: DataFrame,\n legendInfo: ScatterplotUmapLegendInfo,\n layers: ScatterplotUmapSettingsImpl['layers'],\n): AesGetters {\n const dotLayer = layers.find(l => l.type === 'dots') as DotsLayer | undefined;\n const curveLayer = layers.find(l => l.type === 'curve') as CurveLayer | undefined;\n return {\n dotFill: createAesGetter(dataFrame, legendInfo, dotLayer?.aes.dotFill ?? DEFAULT_DOT_AES.color, 'dotFill'),\n dotSize: createAesGetter(dataFrame, legendInfo, dotLayer?.aes.dotSize ?? DEFAULT_DOT_AES.size, 'dotSize'),\n lineType: createAesGetter(dataFrame, legendInfo, curveLayer?.aes.lineShape ?? 'solid', 'lineShape')\n };\n}\n\nclass ChartRenderer {\n reactRoot: Root | null = null;\n parentNode: HTMLElement | null = null;\n rootNode: HTMLElement | null = null;\n canvasNode: HTMLElement | null = null;\n\n svgLayerElement: SVGElement | null = null;\n svgLayerComponent: ReactElement = (<></>);\n\n aesGetters: AesGetters = {\n dotSize: () => 2,\n dotFill: () => BLACK,\n lineType: () => 'solid'\n };\n\n tools: {\n webglChart: CartesianChart<unknown, unknown>;\n qt?: KDBush;\n fillColor: () => {\n value: (setter: (d: Dot) => [number, number, number, number]) => void;\n data: (setter: () => Dot[]) => void;\n };\n pointSeries: () => unknown;\n zoom: ZoomBehavior<Element, unknown>;\n } | null = null;\n\n margins: Margins = {\n top: MIN_MARGIN,\n bottom: MIN_MARGIN,\n left: MIN_MARGIN,\n right: MIN_MARGIN,\n };\n chartSizes: ChartSizes = {\n chartWidth: DEFAULT_WIDTH, // width of single chart\n chartHeight: DEFAULT_HEIGHT, // height of single chart\n totalWidth: DEFAULT_WIDTH, // width of all charts in charts row, plus left axis, plus legend\n totalHeight: DEFAULT_HEIGHT, // width of all charts in charts height, plus bottom axis, plus top title\n };\n scales: ChartScales = {\n x: scaleLinear().domain([0, 10]).range([0, DEFAULT_WIDTH]),\n y: scaleLinear().domain([0, 10]).range([DEFAULT_HEIGHT, 0]),\n xOriginal: scaleLinear().domain([0, 10]).range([0, DEFAULT_WIDTH]),\n yOriginal: scaleLinear().domain([0, 10]).range([DEFAULT_HEIGHT, 0]),\n };\n\n polygons:Polygon[] = [];\n onPolygonUpdateOutside: ScatterplotEventHandlers['onPolygonUpdate'] = () => undefined;\n onTooltipHintSwitch: ScatterplotEventHandlers['onTooltipHintSwitch'] = () => undefined;\n onLassoControlsStateUpdate: ScatterplotEventHandlers['onLassoControlsStateUpdate'] = () => undefined;\n\n zoomTransform: ZoomTransform | null = null;\n zoomStateKey = '';\n selectedDot: Dot | null = null;\n captionsSizes: CaptionsSizes = {\n xAxisCaptionsWidth: 30,\n yAxisCaptionsWidth: 100,\n };\n mainTitle: string[] = []; // can be multiline\n legend: LegendData = {width: 0, height: 0, items: []};\n\n notCalculatedProps: Partial<SVGLayerProps> = {};\n\n allDots: Dot[] = [];\n visibleLabels: Label[] = [];\n dataFrame: DataFrame = new DataFrame('', {});\n\n clear() {\n if (this.parentNode && this.rootNode && this.canvasNode) {\n this.parentNode?.removeChild(this.rootNode);\n this.parentNode?.removeChild(this.canvasNode);\n this.parentNode = null;\n this.rootNode = null;\n this.canvasNode = null;\n this.svgLayerElement = null;\n this.tools = null;\n }\n // timeout to avoid trying to unmount during rendering\n setTimeout(() => {\n this.reactRoot?.unmount();\n this.reactRoot = null;\n });\n }\n\n init(node: HTMLElement) {\n if (this.parentNode === null) {\n this.parentNode = node;\n this.rootNode = document.createElement('div');\n this.canvasNode = document.createElement('div');\n this.parentNode.appendChild(this.rootNode);\n this.parentNode.appendChild(this.canvasNode);\n this.reactRoot = createRoot(this.rootNode);\n }\n }\n\n updateChartSizes(size: ScatterplotUmapSettingsImpl['chartSettings']['size']) {\n if (size.width !== this.chartSizes.chartWidth || size.height !== this.chartSizes.chartHeight) {\n // NB: now chart sizes always change with one multiplier for width/height so qt stays without changes\n this.chartSizes.chartWidth = size.width;\n this.chartSizes.chartHeight = size.height;\n this.scales.x.range([0, this.chartSizes.chartWidth]);\n this.scales.y.range([this.chartSizes.chartHeight, 0]);\n }\n \n }\n\n updateViewport(\n xAxis: ScatterplotUmapSettingsImpl['chartSettings']['xAxis'],\n yAxis: ScatterplotUmapSettingsImpl['chartSettings']['yAxis'],\n dotsExtents: DotsExtents,\n ) {\n const scaleX = xAxis.scale === 'log' ? scaleLog() : scaleLinear();\n\n let {minX, minY, maxX, maxY} = dotsExtents;\n if (xAxis.lowerValue !== undefined) {\n minX = Math.max(minX, xAxis.lowerValue);\n }\n if (xAxis.upperValue !== undefined) {\n maxX = Math.min(maxX, xAxis.upperValue);\n }\n if (yAxis.lowerValue !== undefined) {\n minY = Math.max(minY, yAxis.lowerValue);\n }\n if (yAxis.upperValue !== undefined) {\n maxY = Math.min(maxY, yAxis.upperValue);\n }\n if (xAxis.symmetricRange !== undefined) {\n const middle = xAxis.symmetricRange;\n if (middle >= minX && middle <= maxX) {\n const halfRange = Math.max(middle - minX, maxX - middle);\n minX = middle - halfRange;\n maxX = middle + halfRange;\n }\n }\n if (typeof yAxis.symmetricRange !== 'undefined') {\n const middle = yAxis.symmetricRange;\n if (middle >= minY && middle <= maxY) {\n const halfRange = Math.max(middle - minY, maxY - middle);\n minY = middle - halfRange;\n maxY = middle + halfRange;\n }\n }\n\n const rangeH = [0, this.chartSizes.chartWidth];\n // supporting scale, it needs to add offsets of fixed size in pixels to general scale Y\n const tempX = scaleX\n .copy()\n .domain([minX, maxX])\n .range([PADDINGS.LEFT, this.chartSizes.chartWidth - PADDINGS.RIGHT]);\n scaleX\n .domain([tempX.invert(0), tempX.invert(this.chartSizes.chartWidth)])\n .range(rangeH)\n .nice();\n // this.scales.x = scaleX;\n // this.scales.xOriginal = scaleX.copy();\n this.scales.x.domain(scaleX.domain());\n this.scales.xOriginal.domain(scaleX.domain());\n\n const scaleY = yAxis.scale === 'log' ? scaleLog() : scaleLinear();\n const rangeV = [this.chartSizes.chartHeight, 0];\n // supporting scale, it needs to add offsets of fixed size in pixels to general scale Y\n const tempY = scaleY\n .copy()\n .domain([minY, maxY])\n .range([this.chartSizes.chartHeight - PADDINGS.BOTTOM, PADDINGS.TOP]);\n scaleY\n .domain([tempY.invert(this.chartSizes.chartHeight), tempY.invert(0)])\n .range(rangeV)\n .nice();\n // this.scales.y = scaleY;\n // this.scales.yOriginal = scaleY.copy();\n this.scales.y.domain(scaleY.domain());\n this.scales.yOriginal.domain(scaleY.domain());\n }\n\n updateCaptionsSize() {\n const textMeasurer = new TextMeasurer('600 14px Arial');\n\n function getMaxTickWidth(ticks: string[]) {\n return Math.max(...ticks.map(key => textMeasurer.getTextWidth(key)));\n }\n\n const {ticks, format} = getTicksAndFormat(this.scales.y, false);\n const maxYTick = getMaxTickWidth(ticks.map(format));\n\n this.captionsSizes = {\n xAxisCaptionsWidth: 20,\n yAxisCaptionsWidth: maxYTick,\n };\n }\n\n createMainTitle(title: ScatterplotUmapSettingsImpl['chartSettings']['title']) {\n this.mainTitle = splitTextByWidth(\n title.name,\n this.chartSizes.totalWidth - this.margins.left - this.margins.right,\n 20\n );\n }\n\n updateMargins(xAxis: ScatterplotUmapSettingsImpl['chartSettings']['xAxis'], yAxis: ScatterplotUmapSettingsImpl['chartSettings']['yAxis']) {\n const titleTextHeight = TITLE_LINE_HEIGHT * this.mainTitle.length;\n const titleHeight = titleTextHeight > 0 ? titleTextHeight + TITLE_MARGIN * 2 : 0;\n this.margins = {\n top: Math.max(titleHeight, MIN_MARGIN),\n bottom: MIN_MARGIN + (xAxis.hiddenLabels ? 0 : this.captionsSizes.xAxisCaptionsWidth) + TITLE_LINE,\n left: MIN_MARGIN + (yAxis.hiddenLabels ? 0 : this.captionsSizes.yAxisCaptionsWidth) + TITLE_LINE,\n right: this.legend.width + MIN_MARGIN,\n };\n this.chartSizes.totalWidth = this.margins.left + this.chartSizes.chartWidth + this.margins.right;\n this.chartSizes.totalHeight =\n this.margins.top + Math.max(this.chartSizes.chartHeight, this.legend.height) + this.margins.bottom;\n\n select(this.canvasNode)\n .style('width', this.chartSizes.chartWidth + 'px')\n .style('height', this.chartSizes.chartHeight + 'px')\n .style('top', this.margins.top + 'px')\n .style('left', this.margins.left + 'px');\n }\n\n updateLegendSize(\n legend: ScatterplotUmapSettingsImpl['chartSettings']['legend'],\n legendLabels: ScatterplotUmapLegendInfo,\n grouping: ColumnName[],\n layers: ScatterplotUmapLayer[]\n ) {\n if (!legend.show) {\n this.legend = {width: 0, height: 0, items: []};\n return;\n }\n\n const legendItems: LegendItem[] = [];\n const emptySizes = {width:0, height:0, left:0, top: 0};\n const continuousHeight = Math.min(\n Math.max(this.chartSizes.chartHeight, MIN_LEGEND_GRADIENT_HEIGHT),\n MAX_LEGEND_GRADIENT_HEIGHT\n );\n const legendHeight = Math.max(this.chartSizes.chartHeight, continuousHeight);\n grouping.forEach(column => {\n const info = legendLabels[column.value];\n if (info.usedAes.length === 0 || !info.aesMap) {\n return;\n }\n if (info.values.length > MAX_SHOWN_UNIQUE_VALUES_IN_LABELS) {\n console.warn(`Too many values for discrete legend (${info.values.length})`);\n return;\n }\n const aesData: Record<string, DotAesItem> = {};\n info.values.forEach(category => {\n if (!aesData[category]) {\n aesData[category] = {...DEFAULT_DOT_AES} as DotAesItem;\n }\n info.usedAes.forEach(key => {\n if (key === 'dotFill') {\n aesData[category].color = (info.aesMap(category, key) ?? BLACK) as string;\n }\n if (key === 'dotSize') {\n aesData[category].size = Number(info.aesMap(category, key) ?? 3);\n }\n });\n });\n\n const title = column.label ?? column.value;\n const scale = scaleOrdinal<DotAesItem>()\n .domain(info.values)\n .range(info.values.map(value => aesData[value]));\n legendItems.push({...emptySizes, id: column.value, type: 'dots', title, scale, values:info.values, labels:info.labels});\n });\n\n layers.forEach(layer => {\n if (layer.type === 'dots' && isContinuousAes(layer.aes.dotFill)) {\n const {domain, range, columnName, type = 'linear'} = layer.aes.dotFill;\n const title = columnName.label ?? columnName.value;\n const colorScale = getContinuousColorScale(range, domain, 'linear') as ScaleLinear<string, string>; // always linear for legend - scale to render gradient, not for dots\n const tickPositionScale = (type === 'log' ? scaleSymlog<string, string>() : scaleLinear<string, string>())\n .domain(domain)\n // @ts-ignore\n .range([continuousHeight, 0]);\n const values = getContinuousLegendTicks(tickPositionScale, domain as [number, number]);\n legendItems.push({...emptySizes, id: 'dotFill', type: 'continuous', title, scale: colorScale, tickPositionScale, values});\n }\n if (layer.type === 'dots' && isContinuousAes(layer.aes.dotSize)) {\n const {columnName, domain, range} = layer.aes.dotSize;\n const title = columnName.label ?? columnName.value;\n const scale = scaleSqrt(domain, range);\n const values = scale.ticks(3);\n const format = scale.tickFormat(3);\n const labels = values.reduce((res: Record<string, string>, v) => {\n res[String(v)] = format(v);\n return res;\n }, {});\n legendItems.push({...emptySizes, id: columnName.value, type: 'size', title, scale, values, labels});\n }\n });\n\n if (!legendItems.length) {\n this.legend = {width: 0, height: 0, items: []};\n return;\n }\n\n const items = arrangeLegendParts(legendItems, legendHeight, continuousHeight);\n const maxRightEdge = items.reduce((max, item) => Math.max(max, item.left + item.width), 0);\n const legendWidth = maxRightEdge + LEGEND_OFFSET;\n\n this.legend = {\n width: legendWidth,\n height: legendHeight,\n items,\n };\n }\n\n initSettings(\n dots: Dot[],\n chartSettings: ScatterplotUmapSettingsImpl['chartSettings'],\n dotExtents: DotsExtents,\n legendInfo: ScatterplotUmapLegendInfo,\n layers: ScatterplotUmapSettingsImpl['layers'],\n grouping: ColumnName[],\n onZoomChange: (v:boolean) => void,\n ) {\n const {xAxis, yAxis, size, title, legend} = chartSettings;\n this.updateChartSizes(size);\n this.updateViewport(xAxis, yAxis, dotExtents);\n this.updateCaptionsSize();\n this.updateLegendSize(legend, legendInfo, grouping, layers);\n this.createMainTitle(title);\n this.updateMargins(xAxis, yAxis);\n\n this.aesGetters = getGettersFromLayers(this.dataFrame, legendInfo, layers);\n\n const fillColor = webglFillColor()\n .data(dots)\n .value((d: Dot) => {\n const rgba = stringToNumberRgba(this.aesGetters.dotFill(d.idx));\n rgba[3] = !d.dimmed && isDotInsidePolygons(d.x, d.y, this.polygons) ? 1 : 0.4;\n return getColorWithFakeOpacity(rgba, rgba);\n });\n\n const pointSeries = seriesWebglPoint()\n .equals((a: Dot[], b: Dot[]) => a === b)\n .size((d: Dot) => convertDotRToSymbolSize(this.aesGetters.dotSize(d.idx)))\n .crossValue((d: Dot) => d.x)\n .mainValue((d: Dot) => d.y)\n .decorate((program: unknown) => fillColor(program));\n\n const z = zoom()\n .scaleExtent([0.1, 1000])\n .filter((e:MouseEvent) => {\n return e.type === 'wheel' || e.metaKey || e.ctrlKey;\n })\n .on('start', () => {\n this.selectedDot = null;\n })\n .on('zoom', (e: D3ZoomEvent<SVGElement, unknown>) => {\n const transform = e.transform;\n const x = transform.rescaleX(this.scales.xOriginal);\n const y = transform.rescaleY(this.scales.yOriginal);\n this.scales.x.domain(x.domain());\n this.scales.y.domain(y.domain());\n\n this.zoomTransform = transform;\n this.zoomStateKey = `${transform.x}_${transform.y}_${transform.k}`; // need it to update axes\n\n this.updateLabelsPosition(this.visibleLabels);\n this.renderSvgLayer();\n this.renderWebglLayer();\n }).on('end', () => {\n this.visibleLabels = this.computeLabels(this.allDots);\n this.renderSvgLayer();\n onZoomChange(true);\n });\n \n // @ts-ignore\n const p = pointer().on('point', ([coord]) => {\n let closestDatum;\n if (coord) {\n closestDatum = this.getClosestDot(coord.x, coord.y);\n }\n \n const needRedraw =\n (this.selectedDot && !closestDatum) ||\n (!this.selectedDot && closestDatum) ||\n this.selectedDot?.idx !== closestDatum?.idx;\n\n this.selectedDot = closestDatum ?? null;\n\n if (needRedraw) {\n this.renderSvgLayer();\n }\n });\n\n const webglChart = chartCartesian({\n xScale: this.scales.x,\n yScale: this.scales.y,\n })\n .xAxisHeight(() => '0') // removing build-in axes from chartCartesian\n .yAxisWidth(() => '0') // removing build-in axes from chartCartesian\n .svgPlotArea(seriesSvgMulti())\n .webglPlotArea(\n // only render the point series on the WebGL layer\n seriesWebglMulti()\n .series([pointSeries])\n .mapping((d: unknown) => d)\n )\n .decorate(selection => {\n const s = selection.enter();\n if (s && !this.svgLayerElement) {\n s.style('grid-template-columns', '0 auto 1fr auto 0'); // removing build-in axes from chartCartesian\n s.style('grid-template-rows', '0 auto 1fr auto 0'); // removing build-in axes from chartCartesian\n this.svgLayerElement = s.select('.svg-plot-area.plot-area svg').node() as SVGElement;\n }\n s.select('.svg-plot-area.plot-area').attr('class', 'svg-plot-area plot-area miplots-scatterplot-plot-area')\n \n // @ts-ignore\n .call(z)\n .call(p);\n });\n\n this.tools = {\n webglChart,\n zoom: z,\n fillColor,\n pointSeries,\n };\n\n select(this.canvasNode)\n .datum(dots)\n .style('position', 'absolute')\n .style('width', this.chartSizes.chartWidth + 'px')\n .style('height', this.chartSizes.chartHeight + 'px')\n .style('top', this.margins.top + 'px')\n .style('left', this.margins.left + 'px');\n this.onPolygonUpdate(this.polygons);\n }\n\n resetZoom(\n xAxis: ScatterplotUmapSettingsImpl['chartSettings']['xAxis'],\n yAxis: ScatterplotUmapSettingsImpl['chartSettings']['yAxis'],\n dotsExtents?: DotsExtents\n ) {\n if (!this.tools?.zoom || !dotsExtents) {\n return;\n }\n this.updateViewport(xAxis, yAxis, dotsExtents);\n select('.miplots-scatterplot-plot-area').call((this.tools.zoom.transform as (selection: unknown, transform: unknown) => void), zoomIdentity);\n }\n\n updateAes(\n legendInfo: ScatterplotUmapLegendInfo,\n layers: ScatterplotUmapSettingsImpl['layers']\n ) {\n if (this.tools === null) {\n return;\n }\n this.aesGetters = getGettersFromLayers(this.dataFrame, legendInfo, layers);\n \n // @ts-ignore\n this.tools.fillColor.value((d: Dot) => {\n const colorGetter = this.aesGetters.dotFill ?? GET_BLACK;\n const rgba = stringToNumberRgba(colorGetter(d.idx));\n rgba[3] = !d.dimmed && isDotInsidePolygons(d.x, d.y, this.polygons) ? 1 : 0.4;\n return getColorWithFakeOpacity(rgba, rgba);\n });\n }\n\n updatePointSize(\n legendInfo: ScatterplotUmapLegendInfo,\n layers: ScatterplotUmapSettingsImpl['layers']\n ) {\n if (this.tools === null) {\n return;\n }\n this.updateAes(legendInfo, layers);\n // TODO: try remove array copy\n select(this.canvasNode).datum([...this.allDots]);\n // @ts-ignore\n this.tools.pointSeries.size((d: Dot) => convertDotRToSymbolSize(this.aesGetters.dotSize(d.idx)));\n }\n\n updateByLasso() {\n if (this.tools === null) {\n return;\n }\n \n // @ts-ignore\n this.tools?.fillColor.value((d: Dot) => {\n const colorGetter = this.aesGetters.dotFill ?? GET_BLACK;\n const rgba = stringToNumberRgba(colorGetter(d.idx));\n rgba[3] = !d.dimmed && isDotInsidePolygons(d.x, d.y, this.polygons) ? 1 : 0.4;\n return getColorWithFakeOpacity(rgba, rgba);\n });\n this.renderWebglLayer();\n }\n\n createQuadtree(dots: Dot[]): KDBush {\n const tree = new KDBush(dots.length, 512);\n\n for (let i = 0; i < dots.length; i++) {\n tree.add(dots[i].x, dots[i].y);\n } \n\n return tree.finish();\n }\n\n getClosestDot(_x: number, _y: number): Dot | null {\n const tree = this.tools?.qt;\n if (!tree) return null;\n const dots = this.allDots;\n const x = this.scales.x.invert(_x);\n const y = this.scales.y.invert(_y);\n const radius = 1 / (this.zoomTransform?.k || 1);\n const minX = x - radius;\n const maxX = x + radius;\n const minY = y - radius;\n const maxY = y + radius;\n\n const indexes = tree.range(minX, minY, maxX, maxY);\n const closest = indexes.reduce((closest, idx: number) => {\n const dot = dots[idx];\n const dX = this.scales.x(dot.x) - _x;\n const dY = this.scales.y(dot.y) - _y;\n const distance = Math.hypot(dX, dY);\n if (closest === null || distance < closest.distance) {\n closest.index = idx;\n closest.distance = distance;\n }\n return closest;\n }, {\n index: -1,\n distance: Infinity\n });\n return indexes.length === 0 || closest.index === -1 ? null : dots[closest.index];\n }\n\n updateDots(dots: Dot[]) {\n if (this.tools === null) {\n return;\n }\n select(this.canvasNode).datum(dots);\n \n // @ts-ignore\n this.tools.fillColor.data(dots);\n this.tools.qt = this.createQuadtree(dots);\n this.allDots = dots;\n }\n\n render(\n dataFrame: DataFrame,\n settingsId: string,\n chartSettings: ScatterplotUmapSettingsImpl['chartSettings'],\n keyColumn: ColumnName | null,\n dots: Dot[],\n dotExtents: DotsExtents,\n dotsByGrouping: Record<string, Dot[]>,\n layers: ScatterplotUmapSettingsImpl['layers'],\n legendInfo: ScatterplotUmapLegendInfo,\n grouping: ColumnName[],\n onPolygonUpdateOutside: ScatterplotEventHandlers['onPolygonUpdate'],\n onTooltipHintSwitch: (v:boolean) => void,\n onLassoControlsStateUpdate: (v:LassoControlsState) => void,\n onZoomChange: (v:boolean) => void,\n ) {\n this.dataFrame = dataFrame;\n const sizesChanged = chartSettings.size.width !== this.chartSizes.chartWidth || chartSettings.size.height !== this.chartSizes.chartHeight; \n if (this.tools === null) {\n this.initSettings(\n dots,\n chartSettings,\n dotExtents,\n legendInfo,\n layers,\n grouping,\n onZoomChange\n ); \n } else {\n const {title, legend, size} = chartSettings;\n this.updateChartSizes(size);\n this.updateLegendSize(legend, legendInfo, grouping, layers);\n this.createMainTitle(title);\n this.updateMargins(chartSettings.xAxis, chartSettings.yAxis);\n this.updateAes(legendInfo, layers);\n }\n\n this.onPolygonUpdateOutside = onPolygonUpdateOutside;\n this.onTooltipHintSwitch = onTooltipHintSwitch;\n this.onLassoControlsStateUpdate = onLassoControlsStateUpdate;\n\n if (this.allDots !== dots) {\n this.updateDots(dots);\n this.visibleLabels = this.computeLabels(dots);\n this.onPolygonUpdate(this.polygons);\n } else if (sizesChanged) {\n this.visibleLabels = this.computeLabels(dots);\n }\n\n this.notCalculatedProps = {\n settingsId,\n chartSettings,\n keyColumn,\n dotsByGrouping,\n layers\n };\n\n this.renderWebglLayer();\n this.renderSvgLayer();\n }\n\n renderWebglLayer() {\n if (this.tools?.webglChart) {\n select(this.canvasNode).call(this.tools?.webglChart);\n }\n }\n\n onPolygonUpdate = (p:Polygon[]) => {\n this.polygons = p;\n this.updateByLasso();\n const filteredDotsIndexes = this.allDots\n .filter(d => isDotInsidePolygons(d.x, d.y, this.polygons))\n .map(d => d.idx);\n this.onPolygonUpdateOutside(filteredDotsIndexes, p);\n };\n\n renderSvgLayer() {\n const props = {\n settingsId: this.notCalculatedProps.settingsId,\n chartSettings: this.notCalculatedProps.chartSettings,\n keyColumn: this.notCalculatedProps.keyColumn,\n dotsByGrouping: this.notCalculatedProps.dotsByGrouping,\n layers: this.notCalculatedProps.layers,\n chartSizes: this.chartSizes,\n scales: this.scales,\n margins: this.margins,\n mainTitle: this.mainTitle,\n captionsSizes: this.captionsSizes,\n container: this.svgLayerElement,\n zoomStateKey: this.zoomStateKey,\n selectedDot: this.selectedDot,\n aesGetters: this.aesGetters,\n legendData: this.legend,\n labels: this.visibleLabels,\n defaultPolygons: this.polygons,\n onPolygonUpdate: this.onPolygonUpdate,\n onTooltipHintSwitch: this.onTooltipHintSwitch,\n onLassoControlsStateUpdate: this.onLassoControlsStateUpdate,\n } as SVGLayerProps;\n this.svgLayerComponent = (\n <DataFrameProvider dataFrame={this.dataFrame}>\n <SVGLayer {...props} />\n </DataFrameProvider>\n );\n this.reactRoot?.render(this.svgLayerComponent);\n }\n\n renderError(message: string) {\n this.reactRoot?.render(<Error message={message} />);\n }\n\n private computeLabels(dots: Dot[]) {\n const textMeasurer = new TextMeasurer('16px Manrope');\n const getPosition = createLabelPositioner(this.chartSizes.chartWidth, this.chartSizes.chartHeight);\n const labels = [];\n\n for (let i = 0; i < dots.length; i++) {\n const dot = dots[i];\n if (dot.label == null) {\n continue;\n }\n const name = String(dot.label);\n const metrics = textMeasurer.getTextMetrics(name);\n const x = this.scales.x(dot.x);\n const y = this.scales.y(dot.y);\n const w = metrics.width;\n const h = (metrics.actualBoundingBoxAscent) + (metrics.actualBoundingBoxDescent);\n const p = 10;\n const position = getPosition(x, y, w, h, p);\n if (!position) {\n continue;\n }\n\n labels.push({\n x,\n y,\n dot,\n name,\n width: w,\n height: h,\n padding: p,\n xPosition: position[0],\n yPosition: position[1],\n } satisfies Label);\n }\n\n return labels;\n }\n\n private updateLabelsPosition(labels: Label[]) {\n for (let i = 0; i < labels.length; i++) {\n const label = labels[i];\n label.x = this.scales.x(label.dot.x as number);\n label.y = this.scales.y(label.dot.y as number);\n }\n }\n}\n\nexport default ChartRenderer;\n"],"names":["convertDotRToSymbolSize","r","isDotInsidePolygons","x","y","polygons","p","polygonContains","getGettersFromLayers","dataFrame","legendInfo","layers","dotLayer","l","curveLayer","createAesGetter","DEFAULT_DOT_AES","ChartRenderer","__publicField","jsx","Fragment","BLACK","MIN_MARGIN","DEFAULT_WIDTH","DEFAULT_HEIGHT","scaleLinear","DataFrame","filteredDotsIndexes","d","_a","_b","node","createRoot","size","xAxis","yAxis","dotsExtents","scaleX","scaleLog","minX","minY","maxX","maxY","middle","halfRange","rangeH","tempX","PADDINGS","scaleY","rangeV","tempY","textMeasurer","TextMeasurer","getMaxTickWidth","ticks","key","format","getTicksAndFormat","maxYTick","title","splitTextByWidth","titleTextHeight","TITLE_LINE_HEIGHT","titleHeight","TITLE_MARGIN","TITLE_LINE","select","legend","legendLabels","grouping","legendItems","emptySizes","continuousHeight","MIN_LEGEND_GRADIENT_HEIGHT","MAX_LEGEND_GRADIENT_HEIGHT","legendHeight","column","info","MAX_SHOWN_UNIQUE_VALUES_IN_LABELS","aesData","category","scale","scaleOrdinal","value","layer","isContinuousAes","domain","range","columnName","type","colorScale","getContinuousColorScale","tickPositionScale","scaleSymlog","values","getContinuousLegendTicks","scaleSqrt","labels","res","v","items","arrangeLegendParts","legendWidth","max","item","LEGEND_OFFSET","dots","chartSettings","dotExtents","onZoomChange","fillColor","webglFillColor","rgba","stringToNumberRgba","getColorWithFakeOpacity","pointSeries","seriesWebglPoint","a","b","program","z","zoom","e","transform","pointer","coord","closestDatum","needRedraw","webglChart","chartCartesian","seriesSvgMulti","seriesWebglMulti","selection","s","zoomIdentity","colorGetter","GET_BLACK","tree","KDBush","_x","_y","radius","indexes","closest","idx","dot","dX","dY","distance","settingsId","keyColumn","dotsByGrouping","onPolygonUpdateOutside","onTooltipHintSwitch","onLassoControlsStateUpdate","sizesChanged","props","DataFrameProvider","SVGLayer","message","Error","getPosition","createLabelPositioner","i","name","metrics","w","h","position","label"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,SAASA,EAAwBC,GAAU;AACvC,SAAQA,IAAI,QAASA,IAAI,QAAQ;AACrC;AAEA,SAASC,EAAoBC,GAAUC,GAAUC,GAAqB;AAClE,SAAIA,EAAS,WAAW,IACb,KAEJA,EAAS,KAAK,CAACC,MAAMA,EAAE,UAAUA,EAAE,OAAO,SAAS,KAAKC,GAAgBD,EAAE,QAAQ,CAACH,GAAGC,CAAC,CAAC,CAAC;AACpG;AAEA,SAASI,EACLC,GACAC,GACAC,GACU;AACV,QAAMC,IAAWD,EAAO,KAAK,CAAAE,MAAKA,EAAE,SAAS,MAAM,GAC7CC,IAAaH,EAAO,KAAK,CAAAE,MAAKA,EAAE,SAAS,OAAO;AACtD,SAAO;AAAA,IACH,SAASE,EAAgBN,GAAWC,IAAYE,KAAA,gBAAAA,EAAU,IAAI,YAAWI,EAAgB,OAAO,SAAS;AAAA,IACzG,SAASD,EAAgBN,GAAWC,IAAYE,KAAA,gBAAAA,EAAU,IAAI,YAAWI,EAAgB,MAAM,SAAS;AAAA,IACxG,UAAUD,EAAgBN,GAAWC,IAAYI,KAAA,gBAAAA,EAAY,IAAI,cAAa,SAAS,WAAW;AAAA,EAAA;AAE1G;AAEA,MAAMG,GAAc;AAAA,EAApB;AACI,IAAAC,EAAA,mBAAyB;AACzB,IAAAA,EAAA,oBAAiC;AACjC,IAAAA,EAAA,kBAA+B;AAC/B,IAAAA,EAAA,oBAAiC;AAEjC,IAAAA,EAAA,yBAAqC;AACrC,IAAAA,EAAA,2BAAmCC,gBAAAA,EAAAA,IAAAC,EAAAA,UAAA,EAAE;AAErC,IAAAF,EAAA,oBAAyB;AAAA,MACrB,SAAS,MAAM;AAAA,MACf,SAAS,MAAMG;AAAA,MACf,UAAU,MAAM;AAAA,IAAA;AAGpB,IAAAH,EAAA,eASW;AAEX,IAAAA,EAAA,iBAAmB;AAAA,MACf,KAAKI;AAAA,MACL,QAAQA;AAAA,MACR,MAAMA;AAAA,MACN,OAAOA;AAAA,IAAA;AAEX,IAAAJ,EAAA,oBAAyB;AAAA,MACrB,YAAYK;AAAA;AAAA,MACZ,aAAaC;AAAA;AAAA,MACb,YAAYD;AAAA;AAAA,MACZ,aAAaC;AAAA;AAAA,IAAA;AAEjB,IAAAN,EAAA,gBAAsB;AAAA,MAClB,GAAGO,EAAA,EAAc,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,GAAGF,CAAa,CAAC;AAAA,MACzD,GAAGE,EAAA,EAAc,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAACD,GAAgB,CAAC,CAAC;AAAA,MAC1D,WAAWC,EAAA,EAAc,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,GAAGF,CAAa,CAAC;AAAA,MACjE,WAAWE,EAAA,EAAc,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAACD,GAAgB,CAAC,CAAC;AAAA,IAAA;AAGtE,IAAAN,EAAA,kBAAqB,CAAA;AACrB,IAAAA,EAAA,gCAAsE,MAAA;AAAA;AACtE,IAAAA,EAAA,6BAAuE,MAAA;AAAA;AACvE,IAAAA,EAAA,oCAAqF,MAAA;AAAA;AAErF,IAAAA,EAAA,uBAAuC;AACvC,IAAAA,EAAA,sBAAe;AACf,IAAAA,EAAA,qBAA0B;AAC1B,IAAAA,EAAA,uBAA+B;AAAA,MAC3B,oBAAoB;AAAA,MACpB,oBAAoB;AAAA,IAAA;AAExB,IAAAA,EAAA,mBAAsB,CAAA;AACtB;AAAA,IAAAA,EAAA,gBAAqB,EAAC,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAC;AAEnD,IAAAA,EAAA,4BAA6C,CAAA;AAE7C,IAAAA,EAAA,iBAAiB,CAAA;AACjB,IAAAA,EAAA,uBAAyB,CAAA;AACzB,IAAAA,EAAA,mBAAuB,IAAIQ,GAAU,IAAI,EAAE;AAmiB3C,IAAAR,EAAA,yBAAkB,CAACZ,MAAgB;AAC/B,WAAK,WAAWA,GAChB,KAAK,cAAA;AACL,YAAMqB,IAAsB,KAAK,QAC5B,OAAO,CAAAC,MAAK1B,EAAoB0B,EAAE,GAAGA,EAAE,GAAG,KAAK,QAAQ,CAAC,EACxD,IAAI,CAAAA,MAAKA,EAAE,GAAG;AACnB,WAAK,uBAAuBD,GAAqBrB,CAAC;AAAA,IACtD;AAAA;AAAA,EAxiBA,QAAQ;;AACJ,IAAI,KAAK,cAAc,KAAK,YAAY,KAAK,gBACzCuB,IAAA,KAAK,eAAL,QAAAA,EAAiB,YAAY,KAAK,YAClCC,IAAA,KAAK,eAAL,QAAAA,EAAiB,YAAY,KAAK,aAClC,KAAK,aAAa,MAClB,KAAK,WAAW,MAChB,KAAK,aAAa,MAClB,KAAK,kBAAkB,MACvB,KAAK,QAAQ,OAGjB,WAAW,MAAM;;AACb,OAAAD,IAAA,KAAK,cAAL,QAAAA,EAAgB,WAChB,KAAK,YAAY;AAAA,IACrB,CAAC;AAAA,EACL;AAAA,EAEA,KAAKE,GAAmB;AACpB,IAAI,KAAK,eAAe,SACpB,KAAK,aAAaA,GAClB,KAAK,WAAW,SAAS,cAAc,KAAK,GAC5C,KAAK,aAAa,SAAS,cAAc,KAAK,GAC9C,KAAK,WAAW,YAAY,KAAK,QAAQ,GACzC,KAAK,WAAW,YAAY,KAAK,UAAU,GAC3C,KAAK,YAAYC,aAAW,KAAK,QAAQ;AAAA,EAEjD;AAAA,EAEA,iBAAiBC,GAA4D;AACzE,KAAIA,EAAK,UAAU,KAAK,WAAW,cAAcA,EAAK,WAAW,KAAK,WAAW,iBAE7E,KAAK,WAAW,aAAaA,EAAK,OAClC,KAAK,WAAW,cAAcA,EAAK,QACnC,KAAK,OAAO,EAAE,MAAM,CAAC,GAAG,KAAK,WAAW,UAAU,CAAC,GACnD,KAAK,OAAO,EAAE,MAAM,CAAC,KAAK,WAAW,aAAa,CAAC,CAAC;AAAA,EAG5D;AAAA,EAEA,eACIC,GACAC,GACAC,GACF;AACE,UAAMC,IAASH,EAAM,UAAU,QAAQI,EAAA,IAAab,EAAA;AAEpD,QAAI,EAAC,MAAAc,GAAM,MAAAC,GAAM,MAAAC,GAAM,MAAAC,MAAQN;AAa/B,QAZIF,EAAM,eAAe,WACrBK,IAAO,KAAK,IAAIA,GAAML,EAAM,UAAU,IAEtCA,EAAM,eAAe,WACrBO,IAAO,KAAK,IAAIA,GAAMP,EAAM,UAAU,IAEtCC,EAAM,eAAe,WACrBK,IAAO,KAAK,IAAIA,GAAML,EAAM,UAAU,IAEtCA,EAAM,eAAe,WACrBO,IAAO,KAAK,IAAIA,GAAMP,EAAM,UAAU,IAEtCD,EAAM,mBAAmB,QAAW;AACpC,YAAMS,IAAST,EAAM;AACrB,UAAIS,KAAUJ,KAAQI,KAAUF,GAAM;AAClC,cAAMG,IAAY,KAAK,IAAID,IAASJ,GAAME,IAAOE,CAAM;AACvD,QAAAJ,IAAOI,IAASC,GAChBH,IAAOE,IAASC;AAAA,MACpB;AAAA,IACJ;AACA,QAAI,OAAOT,EAAM,iBAAmB,KAAa;AAC7C,YAAMQ,IAASR,EAAM;AACrB,UAAIQ,KAAUH,KAAQG,KAAUD,GAAM;AAClC,cAAME,IAAY,KAAK,IAAID,IAASH,GAAME,IAAOC,CAAM;AACvD,QAAAH,IAAOG,IAASC,GAChBF,IAAOC,IAASC;AAAA,MACpB;AAAA,IACJ;AAEA,UAAMC,IAAS,CAAC,GAAG,KAAK,WAAW,UAAU,GAEvCC,IAAQT,EACT,KAAA,EACA,OAAO,CAACE,GAAME,CAAI,CAAC,EACnB,MAAM,CAACM,EAAS,MAAM,KAAK,WAAW,aAAaA,EAAS,KAAK,CAAC;AACvE,IAAAV,EACK,OAAO,CAACS,EAAM,OAAO,CAAC,GAAGA,EAAM,OAAO,KAAK,WAAW,UAAU,CAAC,CAAC,EAClE,MAAMD,CAAM,EACZ,KAAA,GAGL,KAAK,OAAO,EAAE,OAAOR,EAAO,QAAQ,GACpC,KAAK,OAAO,UAAU,OAAOA,EAAO,QAAQ;AAE5C,UAAMW,IAASb,EAAM,UAAU,QAAQG,EAAA,IAAab,EAAA,GAC9CwB,IAAS,CAAC,KAAK,WAAW,aAAa,CAAC,GAExCC,IAAQF,EACT,KAAA,EACA,OAAO,CAACR,GAAME,CAAI,CAAC,EACnB,MAAM,CAAC,KAAK,WAAW,cAAcK,EAAS,QAAQA,EAAS,GAAG,CAAC;AACxE,IAAAC,EACK,OAAO,CAACE,EAAM,OAAO,KAAK,WAAW,WAAW,GAAGA,EAAM,OAAO,CAAC,CAAC,CAAC,EACnE,MAAMD,CAAM,EACZ,KAAA,GAGL,KAAK,OAAO,EAAE,OAAOD,EAAO,QAAQ,GACpC,KAAK,OAAO,UAAU,OAAOA,EAAO,QAAQ;AAAA,EAChD;AAAA,EAEA,qBAAqB;AACjB,UAAMG,IAAe,IAAIC,EAAa,gBAAgB;AAEtD,aAASC,EAAgBC,GAAiB;AACtC,aAAO,KAAK,IAAI,GAAGA,EAAM,IAAI,OAAOH,EAAa,aAAaI,CAAG,CAAC,CAAC;AAAA,IACvE;AAEA,UAAM,EAAC,OAAAD,GAAO,QAAAE,MAAUC,GAAkB,KAAK,OAAO,GAAG,EAAK,GACxDC,IAAWL,EAAgBC,EAAM,IAAIE,CAAM,CAAC;AAElD,SAAK,gBAAgB;AAAA,MACjB,oBAAoB;AAAA,MACpB,oBAAoBE;AAAA,IAAA;AAAA,EAE5B;AAAA,EAEA,gBAAgBC,GAA8D;AAC1E,SAAK,YAAYC;AAAA,MACbD,EAAM;AAAA,MACN,KAAK,WAAW,aAAa,KAAK,QAAQ,OAAO,KAAK,QAAQ;AAAA,MAC9D;AAAA,IAAA;AAAA,EAER;AAAA,EAEA,cAAczB,GAA8DC,GAA8D;AACtI,UAAM0B,IAAkBC,KAAoB,KAAK,UAAU,QACrDC,IAAcF,IAAkB,IAAIA,IAAkBG,KAAe,IAAI;AAC/E,SAAK,UAAU;AAAA,MACX,KAAK,KAAK,IAAID,GAAazC,CAAU;AAAA,MACrC,QAAQA,KAAcY,EAAM,eAAe,IAAI,KAAK,cAAc,sBAAsB+B;AAAA,MACxF,MAAM3C,KAAca,EAAM,eAAe,IAAI,KAAK,cAAc,sBAAsB8B;AAAA,MACtF,OAAO,KAAK,OAAO,QAAQ3C;AAAA,IAAA,GAE/B,KAAK,WAAW,aAAa,KAAK,QAAQ,OAAO,KAAK,WAAW,aAAa,KAAK,QAAQ,OAC3F,KAAK,WAAW,cACZ,KAAK,QAAQ,MAAM,KAAK,IAAI,KAAK,WAAW,aAAa,KAAK,OAAO,MAAM,IAAI,KAAK,QAAQ,QAEhG4C,EAAO,KAAK,UAAU,EACjB,MAAM,SAAS,KAAK,WAAW,aAAa,IAAI,EAChD,MAAM,UAAU,KAAK,WAAW,cAAc,IAAI,EAClD,MAAM,OAAO,KAAK,QAAQ,MAAM,IAAI,EACpC,MAAM,QAAQ,KAAK,QAAQ,OAAO,IAAI;AAAA,EAC/C;AAAA,EAEA,iBACIC,GACAC,GACAC,GACA1D,GACF;AACE,QAAI,CAACwD,EAAO,MAAM;AACd,WAAK,SAAS,EAAC,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAC;AAC5C;AAAA,IACJ;AAEA,UAAMG,IAA4B,CAAA,GAC5BC,IAAa,EAAC,OAAM,GAAG,QAAO,GAAG,MAAK,GAAG,KAAK,EAAA,GAC9CC,IAAmB,KAAK;AAAA,MAC1B,KAAK,IAAI,KAAK,WAAW,aAAaC,EAA0B;AAAA,MAChEC;AAAA,IAAA,GAEEC,IAAe,KAAK,IAAI,KAAK,WAAW,aAAaH,CAAgB;AA0D3E,QAzDAH,EAAS,QAAQ,CAAAO,MAAU;AACvB,YAAMC,IAAOT,EAAaQ,EAAO,KAAK;AACtC,UAAIC,EAAK,QAAQ,WAAW,KAAK,CAACA,EAAK;AACnC;AAEJ,UAAIA,EAAK,OAAO,SAASC,IAAmC;AACxD,gBAAQ,KAAK,wCAAwCD,EAAK,OAAO,MAAM,GAAG;AAC1E;AAAA,MACJ;AACA,YAAME,IAAsC,CAAA;AAC5C,MAAAF,EAAK,OAAO,QAAQ,CAAAG,MAAY;AAC5B,QAAKD,EAAQC,CAAQ,MACjBD,EAAQC,CAAQ,IAAI,EAAC,GAAGhE,EAAA,IAE5B6D,EAAK,QAAQ,QAAQ,CAAAtB,MAAO;AACxB,UAAIA,MAAQ,cACRwB,EAAQC,CAAQ,EAAE,QAASH,EAAK,OAAOG,GAAUzB,CAAG,KAAKlC,IAEzDkC,MAAQ,cACRwB,EAAQC,CAAQ,EAAE,OAAO,OAAOH,EAAK,OAAOG,GAAUzB,CAAG,KAAK,CAAC;AAAA,QAEvE,CAAC;AAAA,MACL,CAAC;AAED,YAAMI,IAAQiB,EAAO,SAASA,EAAO,OAC/BK,IAAQC,GAAA,EACT,OAAOL,EAAK,MAAM,EAClB,MAAMA,EAAK,OAAO,IAAI,CAAAM,MAASJ,EAAQI,CAAK,CAAC,CAAC;AACnD,MAAAb,EAAY,KAAK,EAAC,GAAGC,GAAY,IAAIK,EAAO,OAAO,MAAM,QAAQ,OAAAjB,GAAO,OAAAsB,GAAO,QAAOJ,EAAK,QAAQ,QAAOA,EAAK,QAAO;AAAA,IAC1H,CAAC,GAEDlE,EAAO,QAAQ,CAAAyE,MAAS;AACpB,UAAIA,EAAM,SAAS,UAAUC,EAAgBD,EAAM,IAAI,OAAO,GAAG;AAC7D,cAAM,EAAC,QAAAE,GAAQ,OAAAC,GAAO,YAAAC,GAAY,MAAAC,IAAO,SAAA,IAAYL,EAAM,IAAI,SACzDzB,IAAQ6B,EAAW,SAASA,EAAW,OACvCE,IAAaC,GAAwBJ,GAAOD,GAAQ,QAAQ,GAC5DM,KAAqBH,MAAS,QAAQI,GAAA,IAAgCpE,EAAA,GACvE,OAAO6D,CAAM,EAEb,MAAM,CAACd,GAAkB,CAAC,CAAC,GAC1BsB,IAASC,GAAyBH,GAAmBN,CAA0B;AACrF,QAAAhB,EAAY,KAAK,EAAC,GAAGC,GAAY,IAAI,WAAW,MAAM,cAAc,OAAAZ,GAAO,OAAO+B,GAAY,mBAAAE,GAAmB,QAAAE,GAAO;AAAA,MAC5H;AACA,UAAIV,EAAM,SAAS,UAAUC,EAAgBD,EAAM,IAAI,OAAO,GAAG;AAC7D,cAAM,EAAC,YAAAI,GAAY,QAAAF,GAAQ,OAAAC,EAAA,IAASH,EAAM,IAAI,SACxCzB,IAAQ6B,EAAW,SAASA,EAAW,OACvCP,IAAQe,GAAUV,GAAQC,CAAK,GAC/BO,IAASb,EAAM,MAAM,CAAC,GACtBzB,IAASyB,EAAM,WAAW,CAAC,GAC3BgB,IAASH,EAAO,OAAO,CAACI,GAA6BC,OACvDD,EAAI,OAAOC,CAAC,CAAC,IAAI3C,EAAO2C,CAAC,GAClBD,IACR,CAAA,CAAE;AACL,QAAA5B,EAAY,KAAK,EAAC,GAAGC,GAAY,IAAIiB,EAAW,OAAO,MAAM,QAAQ,OAAA7B,GAAO,OAAAsB,GAAO,QAAAa,GAAQ,QAAAG,GAAO;AAAA,MACtG;AAAA,IACJ,CAAC,GAEG,CAAC3B,EAAY,QAAQ;AACrB,WAAK,SAAS,EAAC,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAC;AAC5C;AAAA,IACJ;AAEA,UAAM8B,IAAQC,GAAmB/B,GAAaK,GAAcH,CAAgB,GAEtE8B,IADeF,EAAM,OAAO,CAACG,GAAKC,MAAS,KAAK,IAAID,GAAKC,EAAK,OAAOA,EAAK,KAAK,GAAG,CAAC,IACtDC;AAEnC,SAAK,SAAS;AAAA,MACV,OAAOH;AAAA,MACP,QAAQ3B;AAAA,MACR,OAAAyB;AAAA,IAAA;AAAA,EAER;AAAA,EAEA,aACIM,GACAC,GACAC,GACAlG,GACAC,GACA0D,GACAwC,GACF;AACE,UAAM,EAAC,OAAA3E,GAAO,OAAAC,GAAO,MAAAF,GAAM,OAAA0B,GAAO,QAAAQ,MAAUwC;AAC5C,SAAK,iBAAiB1E,CAAI,GAC1B,KAAK,eAAeC,GAAOC,GAAOyE,CAAU,GAC5C,KAAK,mBAAA,GACL,KAAK,iBAAiBzC,GAAQzD,GAAY2D,GAAU1D,CAAM,GAC1D,KAAK,gBAAgBgD,CAAK,GAC1B,KAAK,cAAczB,GAAOC,CAAK,GAE/B,KAAK,aAAa3B,EAAqB,KAAK,WAAWE,GAAYC,CAAM;AAEzE,UAAMmG,IAAYC,KACb,KAAKL,CAAI,EACT,MAAM,CAAC9E,MAAW;AACf,YAAMoF,IAAOC,EAAmB,KAAK,WAAW,QAAQrF,EAAE,GAAG,CAAC;AAC9D,aAAAoF,EAAK,CAAC,IAAI,CAACpF,EAAE,UAAU1B,EAAoB0B,EAAE,GAAGA,EAAE,GAAG,KAAK,QAAQ,IAAI,IAAI,KACnEsF,EAAwBF,GAAMA,CAAI;AAAA,IAC7C,CAAC,GAECG,IAAcC,EAAA,EACf,OAAO,CAACC,GAAUC,MAAaD,MAAMC,CAAC,EACtC,KAAK,CAAC1F,MAAW5B,EAAwB,KAAK,WAAW,QAAQ4B,EAAE,GAAG,CAAC,CAAC,EACxE,WAAW,CAACA,MAAWA,EAAE,CAAC,EAC1B,UAAU,CAACA,MAAWA,EAAE,CAAC,EACzB,SAAS,CAAC2F,MAAqBT,EAAUS,CAAO,CAAC,GAEhDC,IAAIC,EAAA,EACL,YAAY,CAAC,KAAK,GAAI,CAAC,EACvB,OAAO,CAACC,MACEA,EAAE,SAAS,WAAWA,EAAE,WAAWA,EAAE,OAC/C,EACA,GAAG,SAAS,MAAM;AACf,WAAK,cAAc;AAAA,IACvB,CAAC,EACA,GAAG,QAAQ,CAACA,MAAwC;AACjD,YAAMC,IAAYD,EAAE,WACdvH,IAAIwH,EAAU,SAAS,KAAK,OAAO,SAAS,GAC5CvH,IAAIuH,EAAU,SAAS,KAAK,OAAO,SAAS;AAClD,WAAK,OAAO,EAAE,OAAOxH,EAAE,QAAQ,GAC/B,KAAK,OAAO,EAAE,OAAOC,EAAE,QAAQ,GAE/B,KAAK,gBAAgBuH,GACrB,KAAK,eAAe,GAAGA,EAAU,CAAC,IAAIA,EAAU,CAAC,IAAIA,EAAU,CAAC,IAEhE,KAAK,qBAAqB,KAAK,aAAa,GAC5C,KAAK,eAAA,GACL,KAAK,iBAAA;AAAA,IACT,CAAC,EAAE,GAAG,OAAO,MAAM;AACf,WAAK,gBAAgB,KAAK,cAAc,KAAK,OAAO,GACpD,KAAK,eAAA,GACLd,EAAa,EAAI;AAAA,IACrB,CAAC,GAGCvG,IAAIsH,KAAU,GAAG,SAAS,CAAC,CAACC,CAAK,MAAM;;AACzC,UAAIC;AACJ,MAAID,MACAC,IAAe,KAAK,cAAcD,EAAM,GAAGA,EAAM,CAAC;AAGtD,YAAME,IACD,KAAK,eAAe,CAACD,KACrB,CAAC,KAAK,eAAeA,OACtBjG,IAAA,KAAK,gBAAL,gBAAAA,EAAkB,UAAQiG,KAAA,gBAAAA,EAAc;AAE5C,WAAK,cAAcA,KAAgB,MAE/BC,KACA,KAAK,eAAA;AAAA,IAEb,CAAC,GAEKC,IAAaC,EAAe;AAAA,MAC9B,QAAQ,KAAK,OAAO;AAAA,MACpB,QAAQ,KAAK,OAAO;AAAA,IAAA,CACvB,EACI,YAAY,MAAM,GAAG,EACrB,WAAW,MAAM,GAAG,EACpB,YAAYC,EAAA,CAAgB,EAC5B;AAAA;AAAA,MAEGC,EAAA,EACK,OAAO,CAAChB,CAAW,CAAC,EACpB,QAAQ,CAACvF,MAAeA,CAAC;AAAA,IAAA,EAEjC,SAAS,CAAAwG,MAAa;AACnB,YAAMC,IAAID,EAAU,MAAA;AACpB,MAAIC,KAAK,CAAC,KAAK,oBACXA,EAAE,MAAM,yBAAyB,mBAAmB,GACpDA,EAAE,MAAM,sBAAsB,mBAAmB,GACjD,KAAK,kBAAkBA,EAAE,OAAO,8BAA8B,EAAE,KAAA,IAEpEA,EAAE,OAAO,0BAA0B,EAAE,KAAK,SAAS,uDAAuD,EAGrG,KAAKb,CAAC,EACN,KAAKlH,CAAC;AAAA,IACf,CAAC;AAEL,SAAK,QAAQ;AAAA,MACT,YAAA0H;AAAA,MACA,MAAMR;AAAA,MACN,WAAAV;AAAA,MACA,aAAAK;AAAA,IAAA,GAGJjD,EAAO,KAAK,UAAU,EACjB,MAAMwC,CAAI,EACV,MAAM,YAAY,UAAU,EAC5B,MAAM,SAAS,KAAK,WAAW,aAAa,IAAI,EAChD,MAAM,UAAU,KAAK,WAAW,cAAc,IAAI,EAClD,MAAM,OAAO,KAAK,QAAQ,MAAM,IAAI,EACpC,MAAM,QAAQ,KAAK,QAAQ,OAAO,IAAI,GAC3C,KAAK,gBAAgB,KAAK,QAAQ;AAAA,EACtC;AAAA,EAEA,UACIxE,GACAC,GACAC,GACF;;AACE,IAAI,GAACP,IAAA,KAAK,UAAL,QAAAA,EAAY,SAAQ,CAACO,MAG1B,KAAK,eAAeF,GAAOC,GAAOC,CAAW,GAC7C8B,EAAO,gCAAgC,EAAE,KAAM,KAAK,MAAM,KAAK,WAAgEoE,CAAY;AAAA,EAC/I;AAAA,EAEA,UACI5H,GACAC,GACF;AACE,IAAI,KAAK,UAAU,SAGnB,KAAK,aAAaH,EAAqB,KAAK,WAAWE,GAAYC,CAAM,GAGzE,KAAK,MAAM,UAAU,MAAM,CAACiB,MAAW;AACnC,YAAM2G,IAAc,KAAK,WAAW,WAAWC,GACzCxB,IAAOC,EAAmBsB,EAAY3G,EAAE,GAAG,CAAC;AAClD,aAAAoF,EAAK,CAAC,IAAI,CAACpF,EAAE,UAAU1B,EAAoB0B,EAAE,GAAGA,EAAE,GAAG,KAAK,QAAQ,IAAI,IAAI,KACnEsF,EAAwBF,GAAMA,CAAI;AAAA,IAC7C,CAAC;AAAA,EACL;AAAA,EAEA,gBACItG,GACAC,GACF;AACE,IAAI,KAAK,UAAU,SAGnB,KAAK,UAAUD,GAAYC,CAAM,GAEjCuD,EAAO,KAAK,UAAU,EAAE,MAAM,CAAC,GAAG,KAAK,OAAO,CAAC,GAE/C,KAAK,MAAM,YAAY,KAAK,CAACtC,MAAW5B,EAAwB,KAAK,WAAW,QAAQ4B,EAAE,GAAG,CAAC,CAAC;AAAA,EACnG;AAAA,EAEA,gBAAgB;;AACZ,IAAI,KAAK,UAAU,UAKnBC,IAAA,KAAK,UAAL,QAAAA,EAAY,UAAU,MAAM,CAACD,MAAW;AACpC,YAAM2G,IAAc,KAAK,WAAW,WAAWC,GACzCxB,IAAOC,EAAmBsB,EAAY3G,EAAE,GAAG,CAAC;AAClD,aAAAoF,EAAK,CAAC,IAAI,CAACpF,EAAE,UAAU1B,EAAoB0B,EAAE,GAAGA,EAAE,GAAG,KAAK,QAAQ,IAAI,IAAI,KACnEsF,EAAwBF,GAAMA,CAAI;AAAA,IAC7C,IACA,KAAK,iBAAA;AAAA,EACT;AAAA,EAEA,eAAeN,GAAqB;AAChC,UAAM+B,IAAO,IAAIC,GAAOhC,EAAK,QAAQ,GAAG;AAExC,aAAS,IAAI,GAAG,IAAIA,EAAK,QAAQ;AAC7B,MAAA+B,EAAK,IAAI/B,EAAK,CAAC,EAAE,GAAGA,EAAK,CAAC,EAAE,CAAC;AAGjC,WAAO+B,EAAK,OAAA;AAAA,EAChB;AAAA,EAEA,cAAcE,GAAYC,GAAwB;;AAC9C,UAAMH,KAAO5G,IAAA,KAAK,UAAL,gBAAAA,EAAY;AACzB,QAAI,CAAC4G,EAAM,QAAO;AAClB,UAAM/B,IAAO,KAAK,SACZvG,IAAI,KAAK,OAAO,EAAE,OAAOwI,CAAE,GAC3BvI,IAAI,KAAK,OAAO,EAAE,OAAOwI,CAAE,GAC3BC,IAAS,OAAK/G,IAAA,KAAK,kBAAL,gBAAAA,EAAoB,MAAK,IACvCS,IAAOpC,IAAI0I,GACXpG,IAAOtC,IAAI0I,GACXrG,IAAOpC,IAAIyI,GACXnG,IAAOtC,IAAIyI,GAEXC,IAAUL,EAAK,MAAMlG,GAAMC,GAAMC,GAAMC,CAAI,GAC3CqG,IAAUD,EAAQ,OAAO,CAACC,GAASC,MAAgB;AACrD,YAAMC,IAAMvC,EAAKsC,CAAG,GACdE,IAAK,KAAK,OAAO,EAAED,EAAI,CAAC,IAAIN,GAC5BQ,IAAK,KAAK,OAAO,EAAEF,EAAI,CAAC,IAAIL,GAC5BQ,IAAW,KAAK,MAAMF,GAAIC,CAAE;AAClC,cAAIJ,MAAY,QAAQK,IAAWL,EAAQ,cACvCA,EAAQ,QAAQC,GAChBD,EAAQ,WAAWK,IAEhBL;AAAAA,IACX,GAAG;AAAA,MACC,OAAO;AAAA,MACP,UAAU;AAAA,IAAA,CACb;AACD,WAAOD,EAAQ,WAAW,KAAKC,EAAQ,UAAU,KAAK,OAAOrC,EAAKqC,EAAQ,KAAK;AAAA,EACnF;AAAA,EAEA,WAAWrC,GAAa;AACpB,IAAI,KAAK,UAAU,SAGnBxC,EAAO,KAAK,UAAU,EAAE,MAAMwC,CAAI,GAGlC,KAAK,MAAM,UAAU,KAAKA,CAAI,GAC9B,KAAK,MAAM,KAAK,KAAK,eAAeA,CAAI,GACxC,KAAK,UAAUA;AAAA,EACnB;AAAA,EAEA,OACIjG,GACA4I,GACA1C,GACA2C,GACA5C,GACAE,GACA2C,GACA5I,GACAD,GACA2D,GACAmF,GACAC,GACAC,GACA7C,GACF;AACE,SAAK,YAAYpG;AACjB,UAAMkJ,IAAehD,EAAc,KAAK,UAAU,KAAK,WAAW,cAAcA,EAAc,KAAK,WAAW,KAAK,WAAW;AAC9H,QAAI,KAAK,UAAU;AACf,WAAK;AAAA,QACDD;AAAA,QACAC;AAAA,QACAC;AAAA,QACAlG;AAAA,QACAC;AAAA,QACA0D;AAAA,QACAwC;AAAA,MAAA;AAAA,SAED;AACH,YAAM,EAAC,OAAAlD,GAAO,QAAAQ,GAAQ,MAAAlC,EAAA,IAAQ0E;AAC9B,WAAK,iBAAiB1E,CAAI,GAC1B,KAAK,iBAAiBkC,GAAQzD,GAAY2D,GAAU1D,CAAM,GAC1D,KAAK,gBAAgBgD,CAAK,GAC1B,KAAK,cAAcgD,EAAc,OAAOA,EAAc,KAAK,GAC3D,KAAK,UAAUjG,GAAYC,CAAM;AAAA,IACrC;AAEA,SAAK,yBAAyB6I,GAC9B,KAAK,sBAAsBC,GAC3B,KAAK,6BAA6BC,GAE9B,KAAK,YAAYhD,KACjB,KAAK,WAAWA,CAAI,GACpB,KAAK,gBAAgB,KAAK,cAAcA,CAAI,GAC5C,KAAK,gBAAgB,KAAK,QAAQ,KAC3BiD,MACP,KAAK,gBAAgB,KAAK,cAAcjD,CAAI,IAGhD,KAAK,qBAAqB;AAAA,MACtB,YAAA2C;AAAA,MACA,eAAA1C;AAAA,MACA,WAAA2C;AAAA,MACA,gBAAAC;AAAA,MACA,QAAA5I;AAAA,IAAA,GAGJ,KAAK,iBAAA,GACL,KAAK,eAAA;AAAA,EACT;AAAA,EAEA,mBAAmB;;AACf,KAAIkB,IAAA,KAAK,UAAL,QAAAA,EAAY,cACZqC,EAAO,KAAK,UAAU,EAAE,MAAKpC,IAAA,KAAK,UAAL,gBAAAA,EAAY,UAAU;AAAA,EAE3D;AAAA,EAWA,iBAAiB;;AACb,UAAM8H,IAAQ;AAAA,MACV,YAAY,KAAK,mBAAmB;AAAA,MACpC,eAAe,KAAK,mBAAmB;AAAA,MACvC,WAAW,KAAK,mBAAmB;AAAA,MACnC,gBAAgB,KAAK,mBAAmB;AAAA,MACxC,QAAQ,KAAK,mBAAmB;AAAA,MAChC,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,eAAe,KAAK;AAAA,MACpB,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,MACb,iBAAiB,KAAK;AAAA,MACtB,iBAAiB,KAAK;AAAA,MACtB,qBAAqB,KAAK;AAAA,MAC1B,4BAA4B,KAAK;AAAA,IAAA;AAErC,SAAK,oBACDzI,gBAAAA,EAAAA,IAAC0I,IAAA,EAAkB,WAAW,KAAK,WAC/B,UAAA1I,gBAAAA,EAAAA,IAAC2I,IAAA,EAAU,GAAGF,EAAA,CAAO,EAAA,CACzB,IAEJ/H,IAAA,KAAK,cAAL,QAAAA,EAAgB,OAAO,KAAK;AAAA,EAChC;AAAA,EAEA,YAAYkI,GAAiB;;AACzB,KAAAlI,IAAA,KAAK,cAAL,QAAAA,EAAgB,OAAOV,gBAAAA,EAAAA,IAAC6I,GAAA,EAAM,SAAAD,GAAkB;AAAA,EACpD;AAAA,EAEQ,cAAcrD,GAAa;AAC/B,UAAMvD,IAAe,IAAIC,EAAa,cAAc,GAC9C6G,IAAcC,GAAsB,KAAK,WAAW,YAAY,KAAK,WAAW,WAAW,GAC3FjE,IAAS,CAAA;AAEf,aAASkE,IAAI,GAAGA,IAAIzD,EAAK,QAAQyD,KAAK;AAClC,YAAMlB,IAAMvC,EAAKyD,CAAC;AAClB,UAAIlB,EAAI,SAAS;AACb;AAEJ,YAAMmB,IAAO,OAAOnB,EAAI,KAAK,GACvBoB,IAAUlH,EAAa,eAAeiH,CAAI,GAC1CjK,IAAI,KAAK,OAAO,EAAE8I,EAAI,CAAC,GACvB7I,IAAI,KAAK,OAAO,EAAE6I,EAAI,CAAC,GACvBqB,IAAID,EAAQ,OACZE,IAAKF,EAAQ,0BAA4BA,EAAQ,0BACjD/J,IAAI,IACJkK,IAAWP,EAAY9J,GAAGC,GAAGkK,GAAGC,GAAGjK,CAAC;AAC1C,MAAKkK,KAILvE,EAAO,KAAK;AAAA,QACR,GAAA9F;AAAA,QACA,GAAAC;AAAA,QACA,KAAA6I;AAAA,QACA,MAAAmB;AAAA,QACA,OAAOE;AAAA,QACP,QAAQC;AAAA,QACR,SAASjK;AAAA,QACT,WAAWkK,EAAS,CAAC;AAAA,QACrB,WAAWA,EAAS,CAAC;AAAA,MAAA,CACR;AAAA,IACrB;AAEA,WAAOvE;AAAA,EACX;AAAA,EAEQ,qBAAqBA,GAAiB;AAC1C,aAASkE,IAAI,GAAGA,IAAIlE,EAAO,QAAQkE,KAAK;AACpC,YAAMM,IAAQxE,EAAOkE,CAAC;AACtB,MAAAM,EAAM,IAAI,KAAK,OAAO,EAAEA,EAAM,IAAI,CAAW,GAC7CA,EAAM,IAAI,KAAK,OAAO,EAAEA,EAAM,IAAI,CAAW;AAAA,IACjD;AAAA,EACJ;AACJ;"}
|
|
1
|
+
{"version":3,"file":"ChartRenderer.js","sources":["../../src/scatterplot-umap/ChartRenderer.tsx"],"sourcesContent":["import { chartCartesian } from '@d3fc/d3fc-chart';\nimport type { CartesianChart } from '@d3fc/d3fc-chart/src/cartesian';\nimport type { ScaleLinear } from 'd3-scale';\nimport { scaleLinear, scaleLog, scaleOrdinal, scaleSymlog } from 'd3-scale';\nimport { select } from 'd3-selection';\nimport type { D3ZoomEvent, ZoomBehavior, ZoomTransform } from 'd3-zoom';\nimport { zoom, zoomIdentity } from 'd3-zoom';\nimport type { ReactElement } from 'react';\nimport type { Root } from 'react-dom/client';\nimport { createRoot } from 'react-dom/client';\nimport { Error } from '../common/Error';\nimport type { DotAesItem, LegendData, LegendItem } from '../common/types';\nimport {\n BLACK,\n DEFAULT_HEIGHT,\n DEFAULT_WIDTH,\n MAX_LEGEND_GRADIENT_HEIGHT,\n MAX_SHOWN_UNIQUE_VALUES_IN_LABELS,\n MIN_LEGEND_GRADIENT_HEIGHT,\n TITLE_LINE_HEIGHT,\n TITLE_MARGIN\n} from '../constants';\nimport { splitTextByWidth } from '../discrete/utils';\nimport { DEFAULT_DOT_AES, MIN_MARGIN } from '../scatterplot/constants';\nimport { createAesGetter } from '../scatterplot/utils/createAesGetter';\nimport { getTicksAndFormat } from '../scatterplot/utils/getTicksAndFormat';\nimport type { Label } from '../scatterplot/utils/getVisibleLabels';\nimport { createLabelPositioner } from '../scatterplot/utils/getVisibleLabels';\nimport type { ColumnName, ScatterplotEventHandlers } from '../types';\nimport { isContinuousAes } from '../types';\nimport type { ScatterplotUmapLegendInfo } from '../types/scatterplot-umap';\nimport { getContinuousColorScale } from '../utils/getContinuousColorScale';\nimport { getContinuousLegendTicks } from '../utils/getContinuousLegendTicks';\nimport { TextMeasurer } from '../utils/TextMeasurer/TextMeasurer';\nimport { SVGLayer } from './components/SVGLayer';\nimport { LEGEND_OFFSET, PADDINGS, TITLE_LINE } from './constants';\nimport type { CurveLayer, DotsLayer, ScatterplotUmapLayer, ScatterplotUmapSettingsImpl } from './SettingsImpl';\nimport type {\n AesGetters,\n CaptionsSizes,\n ChartScales, ChartSizes,\n Dot,\n DotsExtents,\n LassoControlsState,\n Margins,\n Polygon,\n SVGLayerProps,\n} from './types';\n// @ts-ignore\nimport { seriesSvgMulti, seriesWebglMulti, seriesWebglPoint } from '@d3fc/d3fc-series';\n// @ts-ignore\nimport { webglFillColor } from '@d3fc/d3fc-webgl';\n// @ts-ignore\nimport { pointer } from '@d3fc/d3fc-pointer';\nimport { polygonContains } from 'd3-polygon';\nimport KDBush from 'kdbush';\nimport { DataFrameProvider } from '../common/useDataFrame';\nimport { DataFrame } from '../DataFrame';\nimport { arrangeLegendParts } from '../utils/arrangeLegendParts';\nimport { GET_BLACK, getColorWithFakeOpacity, stringToNumberRgba } from './colors';\nimport { getSizeLegendItem } from '../utils/getSizeLegendItem';\n\nfunction convertDotRToSymbolSize(r:number) {\n return (r / 2.35) * (r / 2.35) * 64;\n}\n\nfunction isDotInsidePolygons(x:number, y:number, polygons: Polygon[]) {\n if (polygons.length === 0) {\n return true;\n }\n return polygons.some((p) => p.closed && p.points.length > 2 && polygonContains(p.points, [x, y]));\n}\n\nfunction getGettersFromLayers(\n dataFrame: DataFrame,\n legendInfo: ScatterplotUmapLegendInfo,\n layers: ScatterplotUmapSettingsImpl['layers'],\n): AesGetters {\n const dotLayer = layers.find(l => l.type === 'dots') as DotsLayer | undefined;\n const curveLayer = layers.find(l => l.type === 'curve') as CurveLayer | undefined;\n return {\n dotFill: createAesGetter(dataFrame, legendInfo, dotLayer?.aes.dotFill ?? DEFAULT_DOT_AES.color, 'dotFill'),\n dotSize: createAesGetter(dataFrame, legendInfo, dotLayer?.aes.dotSize ?? DEFAULT_DOT_AES.size, 'dotSize'),\n lineType: createAesGetter(dataFrame, legendInfo, curveLayer?.aes.lineShape ?? 'solid', 'lineShape')\n };\n}\n\nclass ChartRenderer {\n reactRoot: Root | null = null;\n parentNode: HTMLElement | null = null;\n rootNode: HTMLElement | null = null;\n canvasNode: HTMLElement | null = null;\n\n svgLayerElement: SVGElement | null = null;\n svgLayerComponent: ReactElement = (<></>);\n\n aesGetters: AesGetters = {\n dotSize: () => 2,\n dotFill: () => BLACK,\n lineType: () => 'solid'\n };\n\n tools: {\n webglChart: CartesianChart<unknown, unknown>;\n qt?: KDBush;\n fillColor: () => {\n value: (setter: (d: Dot) => [number, number, number, number]) => void;\n data: (setter: () => Dot[]) => void;\n };\n pointSeries: () => unknown;\n zoom: ZoomBehavior<Element, unknown>;\n } | null = null;\n\n margins: Margins = {\n top: MIN_MARGIN,\n bottom: MIN_MARGIN,\n left: MIN_MARGIN,\n right: MIN_MARGIN,\n };\n chartSizes: ChartSizes = {\n chartWidth: DEFAULT_WIDTH, // width of single chart\n chartHeight: DEFAULT_HEIGHT, // height of single chart\n totalWidth: DEFAULT_WIDTH, // width of all charts in charts row, plus left axis, plus legend\n totalHeight: DEFAULT_HEIGHT, // width of all charts in charts height, plus bottom axis, plus top title\n };\n scales: ChartScales = {\n x: scaleLinear().domain([0, 10]).range([0, DEFAULT_WIDTH]),\n y: scaleLinear().domain([0, 10]).range([DEFAULT_HEIGHT, 0]),\n xOriginal: scaleLinear().domain([0, 10]).range([0, DEFAULT_WIDTH]),\n yOriginal: scaleLinear().domain([0, 10]).range([DEFAULT_HEIGHT, 0]),\n };\n\n polygons:Polygon[] = [];\n onPolygonUpdateOutside: ScatterplotEventHandlers['onPolygonUpdate'] = () => undefined;\n onTooltipHintSwitch: ScatterplotEventHandlers['onTooltipHintSwitch'] = () => undefined;\n onLassoControlsStateUpdate: ScatterplotEventHandlers['onLassoControlsStateUpdate'] = () => undefined;\n\n zoomTransform: ZoomTransform | null = null;\n zoomStateKey = '';\n selectedDot: Dot | null = null;\n captionsSizes: CaptionsSizes = {\n xAxisCaptionsWidth: 30,\n yAxisCaptionsWidth: 100,\n };\n mainTitle: string[] = []; // can be multiline\n legend: LegendData = {width: 0, height: 0, items: []};\n\n notCalculatedProps: Partial<SVGLayerProps> = {};\n\n allDots: Dot[] = [];\n visibleLabels: Label[] = [];\n dataFrame: DataFrame = new DataFrame('', {});\n\n clear() {\n if (this.parentNode && this.rootNode && this.canvasNode) {\n this.parentNode?.removeChild(this.rootNode);\n this.parentNode?.removeChild(this.canvasNode);\n this.parentNode = null;\n this.rootNode = null;\n this.canvasNode = null;\n this.svgLayerElement = null;\n this.tools = null;\n }\n // timeout to avoid trying to unmount during rendering\n setTimeout(() => {\n this.reactRoot?.unmount();\n this.reactRoot = null;\n });\n }\n\n init(node: HTMLElement) {\n if (this.parentNode === null) {\n this.parentNode = node;\n this.rootNode = document.createElement('div');\n this.canvasNode = document.createElement('div');\n this.parentNode.appendChild(this.rootNode);\n this.parentNode.appendChild(this.canvasNode);\n this.reactRoot = createRoot(this.rootNode);\n }\n }\n\n updateChartSizes(size: ScatterplotUmapSettingsImpl['chartSettings']['size']) {\n if (size.width !== this.chartSizes.chartWidth || size.height !== this.chartSizes.chartHeight) {\n // NB: now chart sizes always change with one multiplier for width/height so qt stays without changes\n this.chartSizes.chartWidth = size.width;\n this.chartSizes.chartHeight = size.height;\n this.scales.x.range([0, this.chartSizes.chartWidth]);\n this.scales.y.range([this.chartSizes.chartHeight, 0]);\n }\n \n }\n\n updateViewport(\n xAxis: ScatterplotUmapSettingsImpl['chartSettings']['xAxis'],\n yAxis: ScatterplotUmapSettingsImpl['chartSettings']['yAxis'],\n dotsExtents: DotsExtents,\n ) {\n const scaleX = xAxis.scale === 'log' ? scaleLog() : scaleLinear();\n\n let {minX, minY, maxX, maxY} = dotsExtents;\n if (xAxis.lowerValue !== undefined) {\n minX = Math.max(minX, xAxis.lowerValue);\n }\n if (xAxis.upperValue !== undefined) {\n maxX = Math.min(maxX, xAxis.upperValue);\n }\n if (yAxis.lowerValue !== undefined) {\n minY = Math.max(minY, yAxis.lowerValue);\n }\n if (yAxis.upperValue !== undefined) {\n maxY = Math.min(maxY, yAxis.upperValue);\n }\n if (xAxis.symmetricRange !== undefined) {\n const middle = xAxis.symmetricRange;\n if (middle >= minX && middle <= maxX) {\n const halfRange = Math.max(middle - minX, maxX - middle);\n minX = middle - halfRange;\n maxX = middle + halfRange;\n }\n }\n if (typeof yAxis.symmetricRange !== 'undefined') {\n const middle = yAxis.symmetricRange;\n if (middle >= minY && middle <= maxY) {\n const halfRange = Math.max(middle - minY, maxY - middle);\n minY = middle - halfRange;\n maxY = middle + halfRange;\n }\n }\n\n const rangeH = [0, this.chartSizes.chartWidth];\n // supporting scale, it needs to add offsets of fixed size in pixels to general scale Y\n const tempX = scaleX\n .copy()\n .domain([minX, maxX])\n .range([PADDINGS.LEFT, this.chartSizes.chartWidth - PADDINGS.RIGHT]);\n scaleX\n .domain([tempX.invert(0), tempX.invert(this.chartSizes.chartWidth)])\n .range(rangeH)\n .nice();\n // this.scales.x = scaleX;\n // this.scales.xOriginal = scaleX.copy();\n this.scales.x.domain(scaleX.domain());\n this.scales.xOriginal.domain(scaleX.domain());\n\n const scaleY = yAxis.scale === 'log' ? scaleLog() : scaleLinear();\n const rangeV = [this.chartSizes.chartHeight, 0];\n // supporting scale, it needs to add offsets of fixed size in pixels to general scale Y\n const tempY = scaleY\n .copy()\n .domain([minY, maxY])\n .range([this.chartSizes.chartHeight - PADDINGS.BOTTOM, PADDINGS.TOP]);\n scaleY\n .domain([tempY.invert(this.chartSizes.chartHeight), tempY.invert(0)])\n .range(rangeV)\n .nice();\n // this.scales.y = scaleY;\n // this.scales.yOriginal = scaleY.copy();\n this.scales.y.domain(scaleY.domain());\n this.scales.yOriginal.domain(scaleY.domain());\n }\n\n updateCaptionsSize() {\n const textMeasurer = new TextMeasurer('600 14px Arial');\n\n function getMaxTickWidth(ticks: string[]) {\n return Math.max(...ticks.map(key => textMeasurer.getTextWidth(key)));\n }\n\n const {ticks, format} = getTicksAndFormat(this.scales.y, false);\n const maxYTick = getMaxTickWidth(ticks.map(format));\n\n this.captionsSizes = {\n xAxisCaptionsWidth: 20,\n yAxisCaptionsWidth: maxYTick,\n };\n }\n\n createMainTitle(title: ScatterplotUmapSettingsImpl['chartSettings']['title']) {\n this.mainTitle = splitTextByWidth(\n title.name,\n this.chartSizes.totalWidth - this.margins.left - this.margins.right,\n 20\n );\n }\n\n updateMargins(xAxis: ScatterplotUmapSettingsImpl['chartSettings']['xAxis'], yAxis: ScatterplotUmapSettingsImpl['chartSettings']['yAxis']) {\n const titleTextHeight = TITLE_LINE_HEIGHT * this.mainTitle.length;\n const titleHeight = titleTextHeight > 0 ? titleTextHeight + TITLE_MARGIN * 2 : 0;\n this.margins = {\n top: Math.max(titleHeight, MIN_MARGIN),\n bottom: MIN_MARGIN + (xAxis.hiddenLabels ? 0 : this.captionsSizes.xAxisCaptionsWidth) + TITLE_LINE,\n left: MIN_MARGIN + (yAxis.hiddenLabels ? 0 : this.captionsSizes.yAxisCaptionsWidth) + TITLE_LINE,\n right: this.legend.width + MIN_MARGIN,\n };\n this.chartSizes.totalWidth = this.margins.left + this.chartSizes.chartWidth + this.margins.right;\n this.chartSizes.totalHeight =\n this.margins.top + Math.max(this.chartSizes.chartHeight, this.legend.height) + this.margins.bottom;\n\n select(this.canvasNode)\n .style('width', this.chartSizes.chartWidth + 'px')\n .style('height', this.chartSizes.chartHeight + 'px')\n .style('top', this.margins.top + 'px')\n .style('left', this.margins.left + 'px');\n }\n\n updateLegendSize(\n legend: ScatterplotUmapSettingsImpl['chartSettings']['legend'],\n legendLabels: ScatterplotUmapLegendInfo,\n grouping: ColumnName[],\n layers: ScatterplotUmapLayer[]\n ) {\n if (!legend.show) {\n this.legend = {width: 0, height: 0, items: []};\n return;\n }\n\n const legendItems: LegendItem[] = [];\n const emptySizes = {width:0, height:0, left:0, top: 0};\n const continuousHeight = Math.min(\n Math.max(this.chartSizes.chartHeight, MIN_LEGEND_GRADIENT_HEIGHT),\n MAX_LEGEND_GRADIENT_HEIGHT\n );\n const legendHeight = Math.max(this.chartSizes.chartHeight, continuousHeight);\n grouping.forEach(column => {\n const info = legendLabels[column.value];\n if (info.usedAes.length === 0 || !info.aesMap) {\n return;\n }\n if (info.values.length > MAX_SHOWN_UNIQUE_VALUES_IN_LABELS) {\n console.warn(`Too many values for discrete legend (${info.values.length})`);\n return;\n }\n const aesData: Record<string, DotAesItem> = {};\n info.values.forEach(category => {\n if (!aesData[category]) {\n aesData[category] = {...DEFAULT_DOT_AES} as DotAesItem;\n }\n info.usedAes.forEach(key => {\n if (key === 'dotFill') {\n aesData[category].color = (info.aesMap(category, key) ?? BLACK) as string;\n }\n if (key === 'dotSize') {\n aesData[category].size = Number(info.aesMap(category, key) ?? 3);\n }\n });\n });\n\n const title = column.label ?? column.value;\n const scale = scaleOrdinal<DotAesItem>()\n .domain(info.values)\n .range(info.values.map(value => aesData[value]));\n legendItems.push({...emptySizes, id: column.value, type: 'dots', title, scale, values:info.values, labels:info.labels});\n });\n\n layers.forEach(layer => {\n if (layer.type === 'dots' && isContinuousAes(layer.aes.dotFill)) {\n const {domain, range, columnName, type = 'linear'} = layer.aes.dotFill;\n const title = columnName.label ?? columnName.value;\n const colorScale = getContinuousColorScale(range, domain, 'linear') as ScaleLinear<string, string>; // always linear for legend - scale to render gradient, not for dots\n const tickPositionScale = (type === 'log' ? scaleSymlog<string, string>() : scaleLinear<string, string>())\n .domain(domain)\n // @ts-ignore\n .range([continuousHeight, 0]);\n const values = getContinuousLegendTicks(tickPositionScale, domain as [number, number]);\n legendItems.push({...emptySizes, id: 'dotFill', type: 'continuous', title, scale: colorScale, tickPositionScale, values});\n }\n if (layer.type === 'dots' && isContinuousAes(layer.aes.dotSize)) {\n legendItems.push(getSizeLegendItem(layer.aes.dotSize));\n }\n });\n\n if (!legendItems.length) {\n this.legend = {width: 0, height: 0, items: []};\n return;\n }\n\n const items = arrangeLegendParts(legendItems, legendHeight, continuousHeight);\n const maxRightEdge = items.reduce((max, item) => Math.max(max, item.left + item.width), 0);\n const legendWidth = maxRightEdge + LEGEND_OFFSET;\n\n this.legend = {\n width: legendWidth,\n height: legendHeight,\n items,\n };\n }\n\n initSettings(\n dots: Dot[],\n chartSettings: ScatterplotUmapSettingsImpl['chartSettings'],\n dotExtents: DotsExtents,\n legendInfo: ScatterplotUmapLegendInfo,\n layers: ScatterplotUmapSettingsImpl['layers'],\n grouping: ColumnName[],\n onZoomChange: (v:boolean) => void,\n ) {\n const {xAxis, yAxis, size, title, legend} = chartSettings;\n this.updateChartSizes(size);\n this.updateViewport(xAxis, yAxis, dotExtents);\n this.updateCaptionsSize();\n this.updateLegendSize(legend, legendInfo, grouping, layers);\n this.createMainTitle(title);\n this.updateMargins(xAxis, yAxis);\n\n this.aesGetters = getGettersFromLayers(this.dataFrame, legendInfo, layers);\n\n const fillColor = webglFillColor()\n .data(dots)\n .value((d: Dot) => {\n const rgba = stringToNumberRgba(this.aesGetters.dotFill(d.idx));\n rgba[3] = !d.dimmed && isDotInsidePolygons(d.x, d.y, this.polygons) ? 1 : 0.4;\n return getColorWithFakeOpacity(rgba, rgba);\n });\n\n const pointSeries = seriesWebglPoint()\n .equals((a: Dot[], b: Dot[]) => a === b)\n .size((d: Dot) => convertDotRToSymbolSize(this.aesGetters.dotSize(d.idx)))\n .crossValue((d: Dot) => d.x)\n .mainValue((d: Dot) => d.y)\n .decorate((program: unknown) => fillColor(program));\n\n const z = zoom()\n .scaleExtent([0.1, 1000])\n .filter((e:MouseEvent) => {\n return e.type === 'wheel' || e.metaKey || e.ctrlKey;\n })\n .on('start', () => {\n this.selectedDot = null;\n })\n .on('zoom', (e: D3ZoomEvent<SVGElement, unknown>) => {\n const transform = e.transform;\n const x = transform.rescaleX(this.scales.xOriginal);\n const y = transform.rescaleY(this.scales.yOriginal);\n this.scales.x.domain(x.domain());\n this.scales.y.domain(y.domain());\n\n this.zoomTransform = transform;\n this.zoomStateKey = `${transform.x}_${transform.y}_${transform.k}`; // need it to update axes\n\n this.updateLabelsPosition(this.visibleLabels);\n this.renderSvgLayer();\n this.renderWebglLayer();\n }).on('end', () => {\n this.visibleLabels = this.computeLabels(this.allDots);\n this.renderSvgLayer();\n onZoomChange(true);\n });\n \n // @ts-ignore\n const p = pointer().on('point', ([coord]) => {\n let closestDatum;\n if (coord) {\n closestDatum = this.getClosestDot(coord.x, coord.y);\n }\n \n const needRedraw =\n (this.selectedDot && !closestDatum) ||\n (!this.selectedDot && closestDatum) ||\n this.selectedDot?.idx !== closestDatum?.idx;\n\n this.selectedDot = closestDatum ?? null;\n\n if (needRedraw) {\n this.renderSvgLayer();\n }\n });\n\n const webglChart = chartCartesian({\n xScale: this.scales.x,\n yScale: this.scales.y,\n })\n .xAxisHeight(() => '0') // removing build-in axes from chartCartesian\n .yAxisWidth(() => '0') // removing build-in axes from chartCartesian\n .svgPlotArea(seriesSvgMulti())\n .webglPlotArea(\n // only render the point series on the WebGL layer\n seriesWebglMulti()\n .series([pointSeries])\n .mapping((d: unknown) => d)\n )\n .decorate(selection => {\n const s = selection.enter();\n if (s && !this.svgLayerElement) {\n s.style('grid-template-columns', '0 auto 1fr auto 0'); // removing build-in axes from chartCartesian\n s.style('grid-template-rows', '0 auto 1fr auto 0'); // removing build-in axes from chartCartesian\n this.svgLayerElement = s.select('.svg-plot-area.plot-area svg').node() as SVGElement;\n }\n s.select('.svg-plot-area.plot-area').attr('class', 'svg-plot-area plot-area miplots-scatterplot-plot-area')\n \n // @ts-ignore\n .call(z)\n .call(p);\n });\n\n this.tools = {\n webglChart,\n zoom: z,\n fillColor,\n pointSeries,\n };\n\n select(this.canvasNode)\n .datum(dots)\n .style('position', 'absolute')\n .style('width', this.chartSizes.chartWidth + 'px')\n .style('height', this.chartSizes.chartHeight + 'px')\n .style('top', this.margins.top + 'px')\n .style('left', this.margins.left + 'px');\n this.onPolygonUpdate(this.polygons);\n }\n\n resetZoom(\n xAxis: ScatterplotUmapSettingsImpl['chartSettings']['xAxis'],\n yAxis: ScatterplotUmapSettingsImpl['chartSettings']['yAxis'],\n dotsExtents?: DotsExtents\n ) {\n if (!this.tools?.zoom || !dotsExtents) {\n return;\n }\n this.updateViewport(xAxis, yAxis, dotsExtents);\n select('.miplots-scatterplot-plot-area').call((this.tools.zoom.transform as (selection: unknown, transform: unknown) => void), zoomIdentity);\n }\n\n updateAes(\n legendInfo: ScatterplotUmapLegendInfo,\n layers: ScatterplotUmapSettingsImpl['layers']\n ) {\n if (this.tools === null) {\n return;\n }\n this.aesGetters = getGettersFromLayers(this.dataFrame, legendInfo, layers);\n \n // @ts-ignore\n this.tools.fillColor.value((d: Dot) => {\n const colorGetter = this.aesGetters.dotFill ?? GET_BLACK;\n const rgba = stringToNumberRgba(colorGetter(d.idx));\n rgba[3] = !d.dimmed && isDotInsidePolygons(d.x, d.y, this.polygons) ? 1 : 0.4;\n return getColorWithFakeOpacity(rgba, rgba);\n });\n }\n\n updatePointSize(\n legendInfo: ScatterplotUmapLegendInfo,\n layers: ScatterplotUmapSettingsImpl['layers']\n ) {\n if (this.tools === null) {\n return;\n }\n this.updateAes(legendInfo, layers);\n // TODO: try remove array copy\n select(this.canvasNode).datum([...this.allDots]);\n // @ts-ignore\n this.tools.pointSeries.size((d: Dot) => convertDotRToSymbolSize(this.aesGetters.dotSize(d.idx)));\n }\n\n updateByLasso() {\n if (this.tools === null) {\n return;\n }\n \n // @ts-ignore\n this.tools?.fillColor.value((d: Dot) => {\n const colorGetter = this.aesGetters.dotFill ?? GET_BLACK;\n const rgba = stringToNumberRgba(colorGetter(d.idx));\n rgba[3] = !d.dimmed && isDotInsidePolygons(d.x, d.y, this.polygons) ? 1 : 0.4;\n return getColorWithFakeOpacity(rgba, rgba);\n });\n this.renderWebglLayer();\n }\n\n createQuadtree(dots: Dot[]): KDBush {\n const tree = new KDBush(dots.length, 512);\n\n for (let i = 0; i < dots.length; i++) {\n tree.add(dots[i].x, dots[i].y);\n } \n\n return tree.finish();\n }\n\n getClosestDot(_x: number, _y: number): Dot | null {\n const tree = this.tools?.qt;\n if (!tree) return null;\n const dots = this.allDots;\n const x = this.scales.x.invert(_x);\n const y = this.scales.y.invert(_y);\n const radius = 1 / (this.zoomTransform?.k || 1);\n const minX = x - radius;\n const maxX = x + radius;\n const minY = y - radius;\n const maxY = y + radius;\n\n const indexes = tree.range(minX, minY, maxX, maxY);\n const closest = indexes.reduce((closest, idx: number) => {\n const dot = dots[idx];\n const dX = this.scales.x(dot.x) - _x;\n const dY = this.scales.y(dot.y) - _y;\n const distance = Math.hypot(dX, dY);\n if (closest === null || distance < closest.distance) {\n closest.index = idx;\n closest.distance = distance;\n }\n return closest;\n }, {\n index: -1,\n distance: Infinity\n });\n return indexes.length === 0 || closest.index === -1 ? null : dots[closest.index];\n }\n\n updateDots(dots: Dot[]) {\n if (this.tools === null) {\n return;\n }\n select(this.canvasNode).datum(dots);\n \n // @ts-ignore\n this.tools.fillColor.data(dots);\n this.tools.qt = this.createQuadtree(dots);\n this.allDots = dots;\n }\n\n render(\n dataFrame: DataFrame,\n settingsId: string,\n chartSettings: ScatterplotUmapSettingsImpl['chartSettings'],\n keyColumn: ColumnName | null,\n dots: Dot[],\n dotExtents: DotsExtents,\n dotsByGrouping: Record<string, Dot[]>,\n layers: ScatterplotUmapSettingsImpl['layers'],\n legendInfo: ScatterplotUmapLegendInfo,\n grouping: ColumnName[],\n onPolygonUpdateOutside: ScatterplotEventHandlers['onPolygonUpdate'],\n onTooltipHintSwitch: (v:boolean) => void,\n onLassoControlsStateUpdate: (v:LassoControlsState) => void,\n onZoomChange: (v:boolean) => void,\n ) {\n this.dataFrame = dataFrame;\n const sizesChanged = chartSettings.size.width !== this.chartSizes.chartWidth || chartSettings.size.height !== this.chartSizes.chartHeight; \n if (this.tools === null) {\n this.initSettings(\n dots,\n chartSettings,\n dotExtents,\n legendInfo,\n layers,\n grouping,\n onZoomChange\n ); \n } else {\n const {title, legend, size} = chartSettings;\n this.updateChartSizes(size);\n this.updateLegendSize(legend, legendInfo, grouping, layers);\n this.createMainTitle(title);\n this.updateMargins(chartSettings.xAxis, chartSettings.yAxis);\n this.updateAes(legendInfo, layers);\n }\n\n this.onPolygonUpdateOutside = onPolygonUpdateOutside;\n this.onTooltipHintSwitch = onTooltipHintSwitch;\n this.onLassoControlsStateUpdate = onLassoControlsStateUpdate;\n\n if (this.allDots !== dots) {\n this.updateDots(dots);\n this.visibleLabels = this.computeLabels(dots);\n this.onPolygonUpdate(this.polygons);\n } else if (sizesChanged) {\n this.visibleLabels = this.computeLabels(dots);\n }\n\n this.notCalculatedProps = {\n settingsId,\n chartSettings,\n keyColumn,\n dotsByGrouping,\n layers\n };\n\n this.renderWebglLayer();\n this.renderSvgLayer();\n }\n\n renderWebglLayer() {\n if (this.tools?.webglChart) {\n select(this.canvasNode).call(this.tools?.webglChart);\n }\n }\n\n onPolygonUpdate = (p:Polygon[]) => {\n this.polygons = p;\n this.updateByLasso();\n const filteredDotsIndexes = this.allDots\n .filter(d => isDotInsidePolygons(d.x, d.y, this.polygons))\n .map(d => d.idx);\n this.onPolygonUpdateOutside(filteredDotsIndexes, p);\n };\n\n renderSvgLayer() {\n const props = {\n settingsId: this.notCalculatedProps.settingsId,\n chartSettings: this.notCalculatedProps.chartSettings,\n keyColumn: this.notCalculatedProps.keyColumn,\n dotsByGrouping: this.notCalculatedProps.dotsByGrouping,\n layers: this.notCalculatedProps.layers,\n chartSizes: this.chartSizes,\n scales: this.scales,\n margins: this.margins,\n mainTitle: this.mainTitle,\n captionsSizes: this.captionsSizes,\n container: this.svgLayerElement,\n zoomStateKey: this.zoomStateKey,\n selectedDot: this.selectedDot,\n aesGetters: this.aesGetters,\n legendData: this.legend,\n labels: this.visibleLabels,\n defaultPolygons: this.polygons,\n onPolygonUpdate: this.onPolygonUpdate,\n onTooltipHintSwitch: this.onTooltipHintSwitch,\n onLassoControlsStateUpdate: this.onLassoControlsStateUpdate,\n } as SVGLayerProps;\n this.svgLayerComponent = (\n <DataFrameProvider dataFrame={this.dataFrame}>\n <SVGLayer {...props} />\n </DataFrameProvider>\n );\n this.reactRoot?.render(this.svgLayerComponent);\n }\n\n renderError(message: string) {\n this.reactRoot?.render(<Error message={message} />);\n }\n\n private computeLabels(dots: Dot[]) {\n const textMeasurer = new TextMeasurer('16px Manrope');\n const getPosition = createLabelPositioner(this.chartSizes.chartWidth, this.chartSizes.chartHeight);\n const labels = [];\n\n for (let i = 0; i < dots.length; i++) {\n const dot = dots[i];\n if (dot.label == null) {\n continue;\n }\n const name = String(dot.label);\n const metrics = textMeasurer.getTextMetrics(name);\n const x = this.scales.x(dot.x);\n const y = this.scales.y(dot.y);\n const w = metrics.width;\n const h = (metrics.actualBoundingBoxAscent) + (metrics.actualBoundingBoxDescent);\n const p = 10;\n const position = getPosition(x, y, w, h, p);\n if (!position) {\n continue;\n }\n\n labels.push({\n x,\n y,\n dot,\n name,\n width: w,\n height: h,\n padding: p,\n xPosition: position[0],\n yPosition: position[1],\n } satisfies Label);\n }\n\n return labels;\n }\n\n private updateLabelsPosition(labels: Label[]) {\n for (let i = 0; i < labels.length; i++) {\n const label = labels[i];\n label.x = this.scales.x(label.dot.x as number);\n label.y = this.scales.y(label.dot.y as number);\n }\n }\n}\n\nexport default ChartRenderer;\n"],"names":["convertDotRToSymbolSize","r","isDotInsidePolygons","x","y","polygons","p","polygonContains","getGettersFromLayers","dataFrame","legendInfo","layers","dotLayer","l","curveLayer","createAesGetter","DEFAULT_DOT_AES","ChartRenderer","__publicField","jsx","Fragment","BLACK","MIN_MARGIN","DEFAULT_WIDTH","DEFAULT_HEIGHT","scaleLinear","DataFrame","filteredDotsIndexes","d","_a","_b","node","createRoot","size","xAxis","yAxis","dotsExtents","scaleX","scaleLog","minX","minY","maxX","maxY","middle","halfRange","rangeH","tempX","PADDINGS","scaleY","rangeV","tempY","textMeasurer","TextMeasurer","getMaxTickWidth","ticks","key","format","getTicksAndFormat","maxYTick","title","splitTextByWidth","titleTextHeight","TITLE_LINE_HEIGHT","titleHeight","TITLE_MARGIN","TITLE_LINE","select","legend","legendLabels","grouping","legendItems","emptySizes","continuousHeight","MIN_LEGEND_GRADIENT_HEIGHT","MAX_LEGEND_GRADIENT_HEIGHT","legendHeight","column","info","MAX_SHOWN_UNIQUE_VALUES_IN_LABELS","aesData","category","scale","scaleOrdinal","value","layer","isContinuousAes","domain","range","columnName","type","colorScale","getContinuousColorScale","tickPositionScale","scaleSymlog","values","getContinuousLegendTicks","getSizeLegendItem","items","arrangeLegendParts","legendWidth","max","item","LEGEND_OFFSET","dots","chartSettings","dotExtents","onZoomChange","fillColor","webglFillColor","rgba","stringToNumberRgba","getColorWithFakeOpacity","pointSeries","seriesWebglPoint","a","b","program","z","zoom","e","transform","pointer","coord","closestDatum","needRedraw","webglChart","chartCartesian","seriesSvgMulti","seriesWebglMulti","selection","s","zoomIdentity","colorGetter","GET_BLACK","tree","KDBush","_x","_y","radius","indexes","closest","idx","dot","dX","dY","distance","settingsId","keyColumn","dotsByGrouping","onPolygonUpdateOutside","onTooltipHintSwitch","onLassoControlsStateUpdate","sizesChanged","props","DataFrameProvider","SVGLayer","message","Error","getPosition","createLabelPositioner","labels","i","name","metrics","w","h","position","label"],"mappings":"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"}
|
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
import { TextMeasurer as U } from "./TextMeasurer/TextMeasurer.js";
|
|
2
2
|
import { getContinuousLegendWidth as $ } from "./getLegendWidth.js";
|
|
3
|
-
const
|
|
4
|
-
function
|
|
3
|
+
const z = 16, v = 48, A = 20, a = 24;
|
|
4
|
+
function C(h, o, d) {
|
|
5
5
|
return Math.max(
|
|
6
|
-
...
|
|
7
|
-
|
|
6
|
+
...h.map((c) => d.getTextWidth(String(c)) + A),
|
|
7
|
+
d.getTextWidth(o)
|
|
8
8
|
);
|
|
9
9
|
}
|
|
10
|
-
function B(
|
|
11
|
-
const
|
|
12
|
-
let
|
|
13
|
-
return
|
|
14
|
-
|
|
15
|
-
}),
|
|
10
|
+
function B(h, o, d, c) {
|
|
11
|
+
const T = [[]];
|
|
12
|
+
let t = 0, n = o, e = 0;
|
|
13
|
+
return h.forEach((l) => {
|
|
14
|
+
t + c <= n ? (T[e].push(l), t += c) : (T.push([l]), e++, t = c, n = d);
|
|
15
|
+
}), T;
|
|
16
16
|
}
|
|
17
|
-
function X(
|
|
18
|
-
const
|
|
19
|
-
let t = 0,
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
return
|
|
23
|
-
const { type:
|
|
24
|
-
if (
|
|
25
|
-
const
|
|
26
|
-
o -
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
} else if (
|
|
30
|
-
const { labels:
|
|
31
|
-
o -
|
|
32
|
-
const
|
|
33
|
-
|
|
17
|
+
function X(h, o, d) {
|
|
18
|
+
const c = new U("600 14px Manrope"), T = d ?? o;
|
|
19
|
+
let t = 0, n = 0, e = 0;
|
|
20
|
+
h.sort((s, p) => s.type === "continuous" && p.type !== "continuous" ? -1 : p.type === "continuous" && s.type !== "continuous" ? 1 : s.type === "dots" && p.type !== "dots" ? -1 : p.type === "dots" && s.type !== "dots" ? 1 : 0);
|
|
21
|
+
const l = [];
|
|
22
|
+
return h.forEach((s) => {
|
|
23
|
+
const { type: p, values: g, title: y, id: M, scale: S } = s;
|
|
24
|
+
if (p === "continuous") {
|
|
25
|
+
const f = $(g, y), r = T;
|
|
26
|
+
o - n < r && (e += t + a, t = 0, n = 0);
|
|
27
|
+
const i = e, L = n;
|
|
28
|
+
f > t && (t = f), n += r + v, n >= o && (e += t + a, t = 0, n = 0), l.push({ ...s, width: f, height: r, left: i, top: L });
|
|
29
|
+
} else if (p === "size") {
|
|
30
|
+
const { labels: f } = s, r = S(Math.max(...g)) * 2 + 4, u = C(g.map((E) => f[E]), y, c), i = g.length * r;
|
|
31
|
+
o - n < i && (e += t + a, t = 0, n = 0);
|
|
32
|
+
const I = e, R = n;
|
|
33
|
+
u > t && (t = u), n += i + v, n >= o && (e += t + a, t = 0, n = 0), l.push({ ...s, width: u, height: i, left: I, top: R });
|
|
34
34
|
} else {
|
|
35
|
-
const { labels:
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
35
|
+
const { labels: f } = s, r = z;
|
|
36
|
+
let u = o - n;
|
|
37
|
+
u < r && (u = o, e += t + a, t = 0, n = 0);
|
|
38
|
+
const i = B(g, u, o, r), L = C([], y, c), I = t === 0, R = e + L + a;
|
|
39
|
+
i.forEach((E, F) => {
|
|
40
|
+
const W = F === i.length - 1, w = F > 0 ? "" : y, b = F > 0 ? `${M}_${F}` : M, _ = C(E.map((P) => f[P]), I && !W ? "" : w, c), O = E.length * r, G = e, N = n;
|
|
41
|
+
_ > t && (t = _), W ? n += O + v : n = o, n >= o && (e += t + a, I && W && e < R && (e = R), t = 0, n = 0), l.push({ ...s, id: b, title: w, width: _, height: O, left: G, top: N, values: E });
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
-
}),
|
|
44
|
+
}), l;
|
|
45
45
|
}
|
|
46
46
|
export {
|
|
47
47
|
X as arrangeLegendParts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arrangeLegendParts.js","sources":["../../src/utils/arrangeLegendParts.ts"],"sourcesContent":["import type { LegendItem } from '../common/types';\nimport { TextMeasurer } from './TextMeasurer/TextMeasurer';\nimport { getContinuousLegendWidth } from './getLegendWidth';\n\nconst textMeasurer = new TextMeasurer('600 14px Manrope');\nconst LINE_HEIGHT = 16;\nconst GROUP_OFFSET = 48;\nconst TEXT_LEFT_DISCRETE = 20;\nconst COLUMN_OFFSET = 24;\n\nfunction getLegendItemWidth(keys: string[], title: string) {\n return Math.max(\n ...keys.map(text => textMeasurer.getTextWidth(String(text)) + TEXT_LEFT_DISCRETE),\n textMeasurer.getTextWidth(title)\n );\n}\n\nfunction splitLegendPart<T extends string | number>(values: T[], firstPartHeight: number, maxHeight: number, lineHeight: number):T[][] {\n const parts:T[][] = [[]];\n let currentPartHeight = 0;\n let currentAvailableHeight = firstPartHeight;\n let partIdx = 0;\n values.forEach(v => {\n if (currentPartHeight + lineHeight <= currentAvailableHeight) {\n parts[partIdx].push(v);\n currentPartHeight += lineHeight;\n } else {\n parts.push([v]);\n partIdx++;\n currentPartHeight = lineHeight;\n currentAvailableHeight = maxHeight;\n }\n });\n return parts;\n}\n\nexport function arrangeLegendParts(legendItems: LegendItem[], maxHeight:number, continuousHeight?:number):LegendItem[] {\n const continuousItemHeight = continuousHeight ?? maxHeight;\n let currentColumnWidth = 0;\n let currentColumnHeight = 0;\n let currentLeft = 0;\n // continuous bars on the left, then discrete lists, then sizes\n legendItems.sort((item1, item2) => {\n if (item1.type === 'continuous' && item2.type !== 'continuous') {\n return -1;\n }\n if (item2.type === 'continuous' && item1.type !== 'continuous') {\n return 1;\n }\n if (item1.type === 'dots' && item2.type !== 'dots') {\n return -1;\n }\n if (item2.type === 'dots' && item1.type !== 'dots') {\n return 1;\n }\n return 0;\n });\n\n const updatedLegendItems:LegendItem[] = [];\n legendItems.forEach((item) => {\n const {type, values, title, id, scale} = item;\n if (type === 'continuous') {\n const width = getContinuousLegendWidth(values, title);\n const height = continuousItemHeight;\n\n const verticalRest = maxHeight - currentColumnHeight;\n if (verticalRest < height) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n const left = currentLeft;\n const top = currentColumnHeight;\n if (width > currentColumnWidth) {\n currentColumnWidth = width;\n }\n currentColumnHeight += height + GROUP_OFFSET;\n if (currentColumnHeight >= maxHeight) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n \n updatedLegendItems.push({...item, width, height, left, top});\n } else if (type === 'size') {\n const {labels} = item;\n const lineHeight = (scale(Math.max(...values)) * 2 + 4);\n const width = getLegendItemWidth(values.map(v => labels[v]), title);\n const height = values.length * lineHeight;\n\n const verticalRest = maxHeight - currentColumnHeight;\n if (verticalRest < height) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n const left = currentLeft;\n const top = currentColumnHeight;\n if (width > currentColumnWidth) {\n currentColumnWidth = width;\n }\n currentColumnHeight += height + GROUP_OFFSET;\n if (currentColumnHeight >= maxHeight) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n updatedLegendItems.push({...item, width, height, left, top});\n } else {\n const {labels} = item;\n const lineHeight = LINE_HEIGHT;\n\n let verticalRest = maxHeight - currentColumnHeight;\n if (verticalRest < lineHeight) {\n verticalRest = maxHeight;\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n // split values under one title into several columns if too many values\n const groupedValues = splitLegendPart<typeof values[number]>(values, verticalRest, maxHeight, lineHeight);\n\n const titleWidth = getLegendItemWidth([], title);\n\n const startFromTheTop = currentColumnWidth === 0;\n const leftByTitle = currentLeft + titleWidth + COLUMN_OFFSET; // for very wide titles; we don't want include title width to first column width; but if the title is too wide we move it after all column parts;\n groupedValues.forEach((valuesPart, idx) => {\n const last = idx === groupedValues.length - 1;\n const partTitle = idx > 0 ? '' : title;\n const partId = idx > 0 ? `${id}_${idx}` : id;\n const width = getLegendItemWidth(valuesPart.map(v => labels[v]), startFromTheTop && !last ? '' : partTitle);\n const height = valuesPart.length * lineHeight;\n const left = currentLeft;\n const top = currentColumnHeight;\n if (width > currentColumnWidth) {\n currentColumnWidth = width;\n }\n if (last) {\n currentColumnHeight += height + GROUP_OFFSET;\n } else {\n currentColumnHeight = maxHeight;\n }\n if (currentColumnHeight >= maxHeight) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n if (startFromTheTop && last && currentLeft < leftByTitle) {\n currentLeft = leftByTitle;\n }\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n updatedLegendItems.push({...item, id: partId, title: partTitle, width, height, left, top, values: valuesPart} as LegendItem);\n });\n }\n });\n return updatedLegendItems;\n}"],"names":["textMeasurer","TextMeasurer","LINE_HEIGHT","GROUP_OFFSET","TEXT_LEFT_DISCRETE","COLUMN_OFFSET","getLegendItemWidth","keys","title","text","splitLegendPart","values","firstPartHeight","maxHeight","lineHeight","parts","currentPartHeight","currentAvailableHeight","partIdx","v","arrangeLegendParts","legendItems","continuousHeight","continuousItemHeight","currentColumnWidth","currentColumnHeight","currentLeft","item1","item2","updatedLegendItems","item","type","id","scale","width","getContinuousLegendWidth","height","left","top","labels","verticalRest","groupedValues","titleWidth","startFromTheTop","leftByTitle","valuesPart","idx","last","partTitle","partId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"arrangeLegendParts.js","sources":["../../src/utils/arrangeLegendParts.ts"],"sourcesContent":["import type { LegendItem } from '../common/types';\nimport { TextMeasurer } from './TextMeasurer/TextMeasurer';\nimport { getContinuousLegendWidth } from './getLegendWidth';\n\nconst LINE_HEIGHT = 16;\nconst GROUP_OFFSET = 48;\nconst TEXT_LEFT_DISCRETE = 20;\nconst COLUMN_OFFSET = 24;\n\nfunction getLegendItemWidth(keys: string[], title: string, textMeasurer: TextMeasurer) {\n return Math.max(\n ...keys.map(text => textMeasurer.getTextWidth(String(text)) + TEXT_LEFT_DISCRETE),\n textMeasurer.getTextWidth(title)\n );\n}\n\nfunction splitLegendPart<T extends string | number>(values: T[], firstPartHeight: number, maxHeight: number, lineHeight: number):T[][] {\n const parts:T[][] = [[]];\n let currentPartHeight = 0;\n let currentAvailableHeight = firstPartHeight;\n let partIdx = 0;\n values.forEach(v => {\n if (currentPartHeight + lineHeight <= currentAvailableHeight) {\n parts[partIdx].push(v);\n currentPartHeight += lineHeight;\n } else {\n parts.push([v]);\n partIdx++;\n currentPartHeight = lineHeight;\n currentAvailableHeight = maxHeight;\n }\n });\n return parts;\n}\n\nexport function arrangeLegendParts(legendItems: LegendItem[], maxHeight:number, continuousHeight?:number):LegendItem[] {\n const textMeasurer = new TextMeasurer('600 14px Manrope');\n const continuousItemHeight = continuousHeight ?? maxHeight;\n let currentColumnWidth = 0;\n let currentColumnHeight = 0;\n let currentLeft = 0;\n // continuous bars on the left, then discrete lists, then sizes\n legendItems.sort((item1, item2) => {\n if (item1.type === 'continuous' && item2.type !== 'continuous') {\n return -1;\n }\n if (item2.type === 'continuous' && item1.type !== 'continuous') {\n return 1;\n }\n if (item1.type === 'dots' && item2.type !== 'dots') {\n return -1;\n }\n if (item2.type === 'dots' && item1.type !== 'dots') {\n return 1;\n }\n return 0;\n });\n\n const updatedLegendItems:LegendItem[] = [];\n legendItems.forEach((item) => {\n const {type, values, title, id, scale} = item;\n if (type === 'continuous') {\n const width = getContinuousLegendWidth(values, title);\n const height = continuousItemHeight;\n\n const verticalRest = maxHeight - currentColumnHeight;\n if (verticalRest < height) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n const left = currentLeft;\n const top = currentColumnHeight;\n if (width > currentColumnWidth) {\n currentColumnWidth = width;\n }\n currentColumnHeight += height + GROUP_OFFSET;\n if (currentColumnHeight >= maxHeight) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n \n updatedLegendItems.push({...item, width, height, left, top});\n } else if (type === 'size') {\n const {labels} = item;\n const lineHeight = (scale(Math.max(...values)) * 2 + 4);\n const width = getLegendItemWidth(values.map(v => labels[v]), title, textMeasurer);\n const height = values.length * lineHeight;\n\n const verticalRest = maxHeight - currentColumnHeight;\n if (verticalRest < height) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n const left = currentLeft;\n const top = currentColumnHeight;\n if (width > currentColumnWidth) {\n currentColumnWidth = width;\n }\n currentColumnHeight += height + GROUP_OFFSET;\n if (currentColumnHeight >= maxHeight) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n updatedLegendItems.push({...item, width, height, left, top});\n } else {\n const {labels} = item;\n const lineHeight = LINE_HEIGHT;\n\n let verticalRest = maxHeight - currentColumnHeight;\n if (verticalRest < lineHeight) {\n verticalRest = maxHeight;\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n // split values under one title into several columns if too many values\n const groupedValues = splitLegendPart<typeof values[number]>(values, verticalRest, maxHeight, lineHeight);\n\n const titleWidth = getLegendItemWidth([], title, textMeasurer);\n\n const startFromTheTop = currentColumnWidth === 0;\n const leftByTitle = currentLeft + titleWidth + COLUMN_OFFSET; // for very wide titles; we don't want include title width to first column width; but if the title is too wide we move it after all column parts;\n groupedValues.forEach((valuesPart, idx) => {\n const last = idx === groupedValues.length - 1;\n const partTitle = idx > 0 ? '' : title;\n const partId = idx > 0 ? `${id}_${idx}` : id;\n const width = getLegendItemWidth(valuesPart.map(v => labels[v]), startFromTheTop && !last ? '' : partTitle, textMeasurer);\n const height = valuesPart.length * lineHeight;\n const left = currentLeft;\n const top = currentColumnHeight;\n if (width > currentColumnWidth) {\n currentColumnWidth = width;\n }\n if (last) {\n currentColumnHeight += height + GROUP_OFFSET;\n } else {\n currentColumnHeight = maxHeight;\n }\n if (currentColumnHeight >= maxHeight) {\n currentLeft += currentColumnWidth + COLUMN_OFFSET;\n if (startFromTheTop && last && currentLeft < leftByTitle) {\n currentLeft = leftByTitle;\n }\n currentColumnWidth = 0;\n currentColumnHeight = 0;\n }\n updatedLegendItems.push({...item, id: partId, title: partTitle, width, height, left, top, values: valuesPart} as LegendItem);\n });\n }\n });\n return updatedLegendItems;\n}"],"names":["LINE_HEIGHT","GROUP_OFFSET","TEXT_LEFT_DISCRETE","COLUMN_OFFSET","getLegendItemWidth","keys","title","textMeasurer","text","splitLegendPart","values","firstPartHeight","maxHeight","lineHeight","parts","currentPartHeight","currentAvailableHeight","partIdx","v","arrangeLegendParts","legendItems","continuousHeight","TextMeasurer","continuousItemHeight","currentColumnWidth","currentColumnHeight","currentLeft","item1","item2","updatedLegendItems","item","type","id","scale","width","getContinuousLegendWidth","height","left","top","labels","verticalRest","groupedValues","titleWidth","startFromTheTop","leftByTitle","valuesPart","idx","last","partTitle","partId"],"mappings":"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"}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return n + Number(s.toPrecision(2));
|
|
4
|
-
}
|
|
5
|
-
function u(o, n, s = 8) {
|
|
1
|
+
import { roundToSignificantAfterComma as r } from "./numberFormat.js";
|
|
2
|
+
function h(c, n, f = 8) {
|
|
6
3
|
if (n[0] === n[1])
|
|
7
4
|
return [n[0]];
|
|
8
|
-
const t =
|
|
9
|
-
return Math.abs(
|
|
5
|
+
const t = c.ticks(f), o = c.domain(), s = r(o[0]), i = r(o[o.length - 1]), e = Math.abs(t[1] - t[0]) ?? 0;
|
|
6
|
+
return Math.abs(s - t[0]) > e / 4 ? t.unshift(s) : t[0] = s, Math.abs(i - t[t.length - 1]) > e / 4 ? t.push(i) : t[t.length - 1] = i, t;
|
|
10
7
|
}
|
|
11
8
|
export {
|
|
12
|
-
|
|
9
|
+
h as getContinuousLegendTicks
|
|
13
10
|
};
|
|
14
11
|
//# sourceMappingURL=getContinuousLegendTicks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getContinuousLegendTicks.js","sources":["../../src/utils/getContinuousLegendTicks.ts"],"sourcesContent":["import type {ScaleLinear, ScaleSymLog} from 'd3-scale';\
|
|
1
|
+
{"version":3,"file":"getContinuousLegendTicks.js","sources":["../../src/utils/getContinuousLegendTicks.ts"],"sourcesContent":["import type {ScaleLinear, ScaleSymLog} from 'd3-scale';\nimport { roundToSignificantAfterComma } from './numberFormat';\n\nexport function getContinuousLegendTicks(colorScale: ScaleLinear<string, string>|ScaleLinear<string, number>|ScaleSymLog<string, string, never>, valueExtent: [number, number], tickCount = 8) {\n if (valueExtent[0] === valueExtent[1]) {\n return [valueExtent[0]];\n }\n const scaleTicks = colorScale.ticks(tickCount);\n const colorDomain = colorScale.domain();\n const from = roundToSignificantAfterComma(colorDomain[0]);\n const to = roundToSignificantAfterComma(colorDomain[colorDomain.length - 1]);\n const tickStep = Math.abs(scaleTicks[1] - scaleTicks[0]) ?? 0;\n if (Math.abs(from - scaleTicks[0]) > tickStep / 4) {\n scaleTicks.unshift(from);\n } else {\n scaleTicks[0] = from;\n }\n if (Math.abs(to - scaleTicks[scaleTicks.length - 1]) > tickStep / 4) {\n scaleTicks.push(to);\n } else {\n scaleTicks[scaleTicks.length - 1] = to;\n }\n return scaleTicks;\n}"],"names":["getContinuousLegendTicks","colorScale","valueExtent","tickCount","scaleTicks","colorDomain","from","roundToSignificantAfterComma","to","tickStep"],"mappings":";AAGO,SAASA,EAAyBC,GAAwGC,GAA+BC,IAAY,GAAG;AAC3L,MAAID,EAAY,CAAC,MAAMA,EAAY,CAAC;AAChC,WAAO,CAACA,EAAY,CAAC,CAAC;AAE1B,QAAME,IAAaH,EAAW,MAAME,CAAS,GACvCE,IAAcJ,EAAW,OAAA,GACzBK,IAAOC,EAA6BF,EAAY,CAAC,CAAC,GAClDG,IAAKD,EAA6BF,EAAYA,EAAY,SAAS,CAAC,CAAC,GACrEI,IAAW,KAAK,IAAIL,EAAW,CAAC,IAAIA,EAAW,CAAC,CAAC,KAAK;AAC5D,SAAI,KAAK,IAAIE,IAAOF,EAAW,CAAC,CAAC,IAAIK,IAAW,IAC5CL,EAAW,QAAQE,CAAI,IAEvBF,EAAW,CAAC,IAAIE,GAEhB,KAAK,IAAIE,IAAKJ,EAAWA,EAAW,SAAS,CAAC,CAAC,IAAIK,IAAW,IAC9DL,EAAW,KAAKI,CAAE,IAElBJ,EAAWA,EAAW,SAAS,CAAC,IAAII,GAEjCJ;AACX;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { roundToSignificantAfterComma as p } from "./numberFormat.js";
|
|
2
|
+
import { sqrt as d } from "../node_modules/.pnpm/d3-scale@4.0.2/node_modules/d3-scale/src/pow.js";
|
|
3
|
+
function M(l) {
|
|
4
|
+
const { columnName: a, domain: i, range: o } = l, h = a.label ?? a.value, n = Math.min(i[0], i[1]), c = Math.max(i[0], i[1]), f = Math.min(o[0], o[1]), g = Math.max(o[0], o[1]), m = d([n, c], [f, g]).nice(), t = m.ticks(3);
|
|
5
|
+
if (t.length > 1) {
|
|
6
|
+
const e = t[1] - t[0];
|
|
7
|
+
t[0] > n && t.unshift(t[0] - e), t[t.length - 1] < c && t.push(t[t.length - 1] + e);
|
|
8
|
+
}
|
|
9
|
+
const u = m.tickFormat(t.length), s = t.reduce((e, r) => (e[String(r)] = u(r), e), {});
|
|
10
|
+
return t[0] < n && t[0] <= 0 && n > 0 && (t[0] = p(n), s[String(t[0])] = String(t[0])), { width: 0, height: 0, left: 0, top: 0, id: a.value, type: "size", title: h, scale: m, values: t, labels: s };
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
M as getSizeLegendItem
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=getSizeLegendItem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSizeLegendItem.js","sources":["../../src/utils/getSizeLegendItem.ts"],"sourcesContent":["import { scaleSqrt } from 'd3-scale';\nimport type { LegendItemSizes } from '../common/types';\nimport type { ContinuousAesFromColumn } from '../types';\nimport { roundToSignificantAfterComma } from './numberFormat';\n\nexport function getSizeLegendItem(item: ContinuousAesFromColumn<number>): LegendItemSizes {\n const {columnName, domain, range} = item;\n const title = columnName.label ?? columnName.value;\n const minD = Math.min(domain[0], domain[1]);\n const maxD = Math.max(domain[0], domain[1]);\n const minR = Math.min(range[0], range[1]);\n const maxR = Math.max(range[0], range[1]);\n const scale = scaleSqrt([minD, maxD], [minR, maxR]).nice();\n const values = scale.ticks(3);\n if (values.length > 1) {\n const step = values[1] - values[0];\n if (values[0] > minD) {\n values.unshift(values[0] - step);\n }\n if (values[values.length - 1] < maxD) {\n values.push(values[values.length - 1] + step);\n }\n }\n const format = scale.tickFormat(values.length);\n const labels = values.reduce((res: Record<string, string>, v) => {\n res[String(v)] = format(v);\n return res;\n }, {});\n if (values[0] < minD && values[0] <= 0 && minD > 0) { // avoid 0 or negative values in cases when domain in value is positive\n values[0] = roundToSignificantAfterComma(minD);\n labels[String(values[0])] = String(values[0]);\n }\n return {width:0, height:0, left:0, top: 0, id: columnName.value, type: 'size', title, scale, values, labels};\n}"],"names":["getSizeLegendItem","item","columnName","domain","range","title","minD","maxD","minR","maxR","scale","scaleSqrt","values","step","format","labels","res","v","roundToSignificantAfterComma"],"mappings":";;AAKO,SAASA,EAAkBC,GAAwD;AACtF,QAAM,EAAC,YAAAC,GAAY,QAAAC,GAAQ,OAAAC,EAAA,IAASH,GAC9BI,IAAQH,EAAW,SAASA,EAAW,OACvCI,IAAO,KAAK,IAAIH,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC,GACpCI,IAAO,KAAK,IAAIJ,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC,GACpCK,IAAO,KAAK,IAAIJ,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,GAClCK,IAAO,KAAK,IAAIL,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,GAClCM,IAAQC,EAAU,CAACL,GAAMC,CAAI,GAAG,CAACC,GAAMC,CAAI,CAAC,EAAE,KAAA,GAC9CG,IAASF,EAAM,MAAM,CAAC;AAC5B,MAAIE,EAAO,SAAS,GAAG;AACnB,UAAMC,IAAOD,EAAO,CAAC,IAAIA,EAAO,CAAC;AACjC,IAAIA,EAAO,CAAC,IAAIN,KACZM,EAAO,QAAQA,EAAO,CAAC,IAAIC,CAAI,GAE/BD,EAAOA,EAAO,SAAS,CAAC,IAAIL,KAC5BK,EAAO,KAAKA,EAAOA,EAAO,SAAS,CAAC,IAAIC,CAAI;AAAA,EAEpD;AACA,QAAMC,IAASJ,EAAM,WAAWE,EAAO,MAAM,GACvCG,IAASH,EAAO,OAAO,CAACI,GAA6BC,OACvDD,EAAI,OAAOC,CAAC,CAAC,IAAIH,EAAOG,CAAC,GAClBD,IACR,CAAA,CAAE;AACL,SAAIJ,EAAO,CAAC,IAAIN,KAAQM,EAAO,CAAC,KAAK,KAAKN,IAAO,MAC7CM,EAAO,CAAC,IAAIM,EAA6BZ,CAAI,GAC7CS,EAAO,OAAOH,EAAO,CAAC,CAAC,CAAC,IAAI,OAAOA,EAAO,CAAC,CAAC,IAEzC,EAAC,OAAM,GAAG,QAAO,GAAG,MAAK,GAAG,KAAK,GAAG,IAAIV,EAAW,OAAO,MAAM,QAAQ,OAAAG,GAAO,OAAAK,GAAO,QAAAE,GAAQ,QAAAG,EAAA;AACzG;"}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { format as
|
|
2
|
-
function
|
|
3
|
-
return isNaN(
|
|
1
|
+
import { format as o } from "../node_modules/.pnpm/d3-format@3.1.0/node_modules/d3-format/src/defaultLocale.js";
|
|
2
|
+
function m(t) {
|
|
3
|
+
return isNaN(t) ? "?" : t === 0 ? "0" : Math.abs(t) < 0.01 ? o(".1e")(t) : o(".2f")(t);
|
|
4
|
+
}
|
|
5
|
+
function s(t, n = 2) {
|
|
6
|
+
const i = t < 0 ? -1 : 1, r = Math.floor(Math.abs(t)), f = Math.abs(t) - r;
|
|
7
|
+
return i * (r + Number(f.toPrecision(n)));
|
|
4
8
|
}
|
|
5
9
|
export {
|
|
6
|
-
|
|
10
|
+
m as numberFormat,
|
|
11
|
+
s as roundToSignificantAfterComma
|
|
7
12
|
};
|
|
8
13
|
//# sourceMappingURL=numberFormat.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numberFormat.js","sources":["../../src/utils/numberFormat.ts"],"sourcesContent":["import {format as d3format} from 'd3-format';\n\nexport function numberFormat(value: number) {\n if (isNaN(value)) {\n return '?';\n }\n if (value === 0) {\n return '0';\n }\n return Math.abs(value) < 0.01 ? d3format('.1e')(value) : d3format('.2f')(value);\n}\n"],"names":["numberFormat","value","d3format"],"mappings":";AAEO,SAASA,EAAaC,GAAe;AACxC,SAAI,MAAMA,CAAK,IACJ,MAEPA,MAAU,IACH,MAEJ,KAAK,IAAIA,CAAK,IAAI,OAAOC,EAAS,KAAK,EAAED,CAAK,IAAIC,EAAS,KAAK,EAAED,CAAK;AAClF;"}
|
|
1
|
+
{"version":3,"file":"numberFormat.js","sources":["../../src/utils/numberFormat.ts"],"sourcesContent":["import {format as d3format} from 'd3-format';\n\nexport function numberFormat(value: number) {\n if (isNaN(value)) {\n return '?';\n }\n if (value === 0) {\n return '0';\n }\n return Math.abs(value) < 0.01 ? d3format('.1e')(value) : d3format('.2f')(value);\n}\n export function roundToSignificantAfterComma(n: number, precision = 2) {\n const sign = n < 0 ? -1 : 1;\n const whole = Math.floor(Math.abs(n));\n const decimal = Math.abs(n) - whole;\n return sign * (whole + Number(decimal.toPrecision(precision)));\n }\n "],"names":["numberFormat","value","d3format","roundToSignificantAfterComma","n","precision","sign","whole","decimal"],"mappings":";AAEO,SAASA,EAAaC,GAAe;AACxC,SAAI,MAAMA,CAAK,IACJ,MAEPA,MAAU,IACH,MAEJ,KAAK,IAAIA,CAAK,IAAI,OAAOC,EAAS,KAAK,EAAED,CAAK,IAAIC,EAAS,KAAK,EAAED,CAAK;AAClF;AACQ,SAASE,EAA6BC,GAAWC,IAAY,GAAG;AACpE,QAAMC,IAAOF,IAAI,IAAI,KAAK,GACpBG,IAAQ,KAAK,MAAM,KAAK,IAAIH,CAAC,CAAC,GAC9BI,IAAU,KAAK,IAAIJ,CAAC,IAAIG;AAC9B,SAAOD,KAAQC,IAAQ,OAAOC,EAAQ,YAAYH,CAAS,CAAC;AAC/D;"}
|