@milaboratories/miplots4 1.0.163 → 1.0.165

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Lasso.js","sources":["../../../src/scatterplot-umap/components/Lasso.tsx"],"sourcesContent":["import {SCATTERPLOT_LASSO_EVENTS} from '../constants';\nimport type {LassoControlsState, LassoMode} from '../types';\nimport type {Polygon} from '../types';\nimport type {Selection} from 'd3-selection';\nimport {select} from 'd3-selection';\nimport {BLACK} from '../../constants';\nimport type {ChartScales, ChartSizes, Point} from '../types';\nimport type {MouseEvent} from 'react';\nimport React, {useCallback, useEffect, useRef, useState} from 'react';\nimport {drag} from 'd3-drag';\n\nconst SELECTION_COLOR = '#845CFF';\nconst START_GREY = '#CFD1DB';\nconst CLOSING_DISTANCE = 20;\nconst R = 3;\nconst R_START = 6;\nconst MAX_HISTORY_LENGTH = 10;\n\ntype CircleData = { // moving point for editing\n idx: number;\n p: Point;\n};\ntype CirclesSelection = Selection<SVGCircleElement, CircleData, SVGGElement | null, CircleData>;\n\ntype HistoryFrame = {\n newPolygonPoints: Point[],\n closedPolygons: Polygon[]\n}\n\n// Mode = 'selection': creating new polygons, pan with button\n// Mode = 'pen': selecting polygon to edit or delete, any zooming actions\nexport function Lasso({\n scales,\n chartSizes,\n zoomStateKey,\n defaultPolygons,\n onPolygonsApply,\n onLassoControlsStateUpdate,\n}: {\n scales: ChartScales;\n chartSizes: ChartSizes;\n zoomStateKey: string;\n defaultPolygons: Polygon[];\n onPolygonsApply: (data: Polygon[]) => void;\n onLassoControlsStateUpdate: (v: LassoControlsState) => void;\n}) {\n useEffect(() => {\n // Events from outer controls\n function onPolygonDelete() {\n if (newPolygonPointsRef.current.length > 0) {\n clearNotFinishedPolygon();\n } else if (selectedPolygonRef.current === null) {\n updatePolygons([]);\n onPolygonsApply([]);\n } else {\n updatePolygons([...closedPolygonsRef.current.filter((_p, idx) => idx !== selectedPolygonRef.current)]);\n updateSelectedPolygon(null);\n onPolygonsApply(closedPolygonsRef.current);\n }\n }\n\n function onModeSelect(e: CustomEvent<LassoMode>) {\n updateMode(e.detail);\n }\n function onClickBack() {\n loadHistoryItem(historyIndexRef.current - 1);\n }\n function onClickForward() {\n loadHistoryItem(historyIndexRef.current + 1);\n }\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.delete, onPolygonDelete);\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.selectMode, onModeSelect as EventListener);\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.back, onClickBack);\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.forward, onClickForward);\n return () => {\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.delete, onPolygonDelete);\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.selectMode, onModeSelect as EventListener);\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.back, onClickBack);\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.forward, onClickForward);\n };\n }, []);\n\n // inner state\n const [lassoMode, setLassoMode] = useState<LassoMode>('pen');\n\n const [closedPolygons, setClosedPolygons] = useState<Polygon[]>(defaultPolygons);\n const closedPolygonsRef = useRef<Polygon[]>(defaultPolygons);\n\n const [hoveredPolygon, setHoveredPolygon] = useState<number | null>(null);\n\n const [selectedPolygon, setSelectedPolygon] = useState<number | null>(null);\n const selectedPolygonRef = useRef<number | null>(null);\n\n const [newPolygonPoints, setNewPolygonPoints] = useState<Point[]>([]);\n const newPolygonPointsRef = useRef(newPolygonPoints);\n\n const [history, setHistory] = useState<HistoryFrame[]>([{newPolygonPoints, closedPolygons}]);\n const [historyIndex, setHistoryIndex] = useState(0);\n const historyRef = useRef(history);\n const historyIndexRef = useRef(historyIndex);\n\n const [movingPoint, setMovingPoint] = useState<null | Point>(null);\n const movingPointRef = useRef<null | Point>(null);\n\n const [closeToStartPoint, setCloseToStartPoint] = useState(false);\n\n const selectedCirclesContainerRef = useRef<SVGGElement | null>(null);\n const selectedCirclesSelectionRef = useRef<CirclesSelection | null>(null);\n\n const saveCurrentStateToHistory = useCallback(function () {\n const newHistoryItem = {\n newPolygonPoints: [...newPolygonPointsRef.current],\n closedPolygons: [...closedPolygonsRef.current]\n };\n const newHistory = historyRef.current.slice(0, historyIndexRef.current + 1);\n newHistory.push(newHistoryItem);\n if (newHistory.length > MAX_HISTORY_LENGTH) {\n newHistory.shift();\n }\n setHistory(newHistory);\n setHistoryIndex(newHistory.length - 1);\n historyRef.current = newHistory;\n historyIndexRef.current = newHistory.length - 1;\n }, []);\n\n const loadHistoryItem = useCallback(function (index:number) {\n if (index > historyRef.current.length - 1 || index < 0) {\n return;\n }\n updateMode('selection');\n const historyState = historyRef.current[index];\n updatePolygons(historyState.closedPolygons, false);\n updateNewPolygon(historyState.newPolygonPoints, false);\n setHistoryIndex(index);\n historyIndexRef.current = index;\n }, []);\n function updatePolygons(p: Polygon[], saveToHistory = true) {\n setClosedPolygons(p);\n closedPolygonsRef.current = p;\n if (saveToHistory) {\n saveCurrentStateToHistory();\n }\n }\n\n function updateNewPolygon(points:Point[], saveToHistory = true) {\n newPolygonPointsRef.current = points;\n setNewPolygonPoints(points);\n if (saveToHistory) {\n saveCurrentStateToHistory();\n }\n }\n\n function updateSelectedPolygon(idx: number | null) {\n setSelectedPolygon(idx);\n selectedPolygonRef.current = idx;\n }\n\n function updateMode(v: LassoMode) {\n setLassoMode(v);\n if (v === 'selection') {\n updateSelectedPolygon(null);\n selectedCirclesSelectionRef.current = null;\n selectedCirclesContainerRef.current = null;\n }\n if (v === 'pen') {\n if (newPolygonPointsRef.current.length > 2) {\n const polygon:Polygon = {points: newPolygonPointsRef.current, closed: true};\n updatePolygons([...closedPolygonsRef.current, polygon]);\n onPolygonsApply([...closedPolygonsRef.current, polygon]);\n }\n clearNotFinishedPolygon();\n }\n }\n function clearNotFinishedPolygon(saveToHistory = true) {\n movingPointRef.current = null;\n updateNewPolygon([], saveToHistory);\n }\n\n function onKeyDown(e: KeyboardEvent) {\n const escape = e.key === 'Escape';\n if (!escape) {\n return;\n }\n clearNotFinishedPolygon();\n }\n\n useEffect(() => {\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, []);\n\n useEffect(() => {\n selectedCirclesSelectionRef.current?.attr('cx', d => scales.x(d.p[0])).attr('cy', d => scales.y(d.p[1]));\n }, [zoomStateKey, chartSizes.chartWidth, chartSizes.chartHeight]);\n\n const onNewPointAddByClick = useCallback(function () {\n setCloseToStartPoint(false);\n if (!movingPointRef.current || lassoMode === 'pen') {\n return;\n }\n const currentCoords = [...movingPointRef.current] as Point;\n const x = scales.x.invert(currentCoords[0]);\n const y = scales.y.invert(currentCoords[1]);\n\n if (!newPolygonPointsRef.current.length) {\n updateNewPolygon([[x, y]]);\n return;\n }\n\n const points = newPolygonPointsRef.current;\n const tooFar = !closeToStartPoint;\n if (tooFar || points.length < 3) {\n updateNewPolygon([...points, [x, y]]);\n } else {\n const polygon:Polygon = {points: [...points], closed: true};\n clearNotFinishedPolygon(false);\n updatePolygons([...closedPolygons, polygon]);\n // to avoid freezing of ui updating in case of big amount of points to apply polygons and change opacity\n setTimeout(() => onPolygonsApply([...closedPolygons, polygon]), 0);\n }\n }, [lassoMode, closeToStartPoint]);\n\n const onMouseMove = useCallback(function(e: MouseEvent<SVGRectElement>) {\n const p: Point = [e.nativeEvent.offsetX, e.nativeEvent.offsetY];\n const points = newPolygonPointsRef.current;\n const startPoint = newPolygonPointsRef.current[0];\n if (startPoint) {\n const startX = scales.x(startPoint[0]);\n const startY = scales.y(startPoint[1]);\n const distance = points.length > 1\n ? Math.sqrt((p[0] - startX) ** 2 + (p[1] - startY) ** 2)\n : Infinity;\n setCloseToStartPoint(distance < CLOSING_DISTANCE);\n } else {\n setCloseToStartPoint(false);\n }\n\n setMovingPoint(p);\n movingPointRef.current = p;\n }, []);\n\n function clearSelectedCircles() {\n if (selectedCirclesContainerRef.current) {\n select(selectedCirclesContainerRef.current).data([]).exit().remove();\n }\n }\n\n function updateSelectedCircles(el: SVGGElement | null) {\n if (el !== selectedCirclesContainerRef.current && el) {\n clearSelectedCircles();\n selectedCirclesContainerRef.current = el;\n onPolygonSelect(selectedPolygon);\n }\n }\n\n const onPolygonSelect = useCallback(function (idx: number | null) {\n if (lassoMode === 'selection') {\n return;\n }\n if (idx !== null) {\n const d = drag<SVGCircleElement, CircleData, SVGGElement | null>()\n .on('drag', function (e) {\n const el = select<SVGCircleElement, CircleData>(this);\n const d = el.data()[0] as number[] & CircleData;\n d[0] = e.x;\n d[1] = e.y;\n d.p = [scales.x.invert(d[0]), scales.y.invert(d[1])];\n el.attr('cx', d[0]).attr('cy', d[1]);\n const editedPolygons = closedPolygonsRef.current.map((polygon, polygonIdx) => {\n return idx !== polygonIdx ? polygon : {\n ...polygon,\n points: polygon.points.map((el, pointIdx) =>\n pointIdx === d.idx ? ([scales.x.invert(d[0]), scales.y.invert(d[1])] as Point) : el\n ),\n };\n });\n updatePolygons(editedPolygons, false);\n })\n .on('end', function () {\n saveCurrentStateToHistory();\n onPolygonsApply(closedPolygonsRef.current);\n });\n const draggablePointsData = closedPolygonsRef.current[idx].points.map((p, idx) => ({idx, p}));\n const selectedCircles = select(selectedCirclesContainerRef.current)\n .selectAll<SVGCircleElement, CircleData>('circle')\n .data(draggablePointsData, (d) => d.idx)\n .join('circle');\n selectedCirclesSelectionRef.current = selectedCircles;\n\n selectedCircles\n .attr('cx', d => scales.x(d.p[0]))\n .attr('cy', d => scales.y(d.p[1]))\n .attr('r', R)\n .attr('fill', 'white')\n .attr('stroke', SELECTION_COLOR);\n selectedCircles.call(d);\n }\n }, []);\n\n useEffect(() => {\n onLassoControlsStateUpdate({\n mode: lassoMode,\n backEnabled: historyIndex > 0,\n forwardEnabled: historyIndex < history.length - 1,\n deleteEnabled: selectedPolygon !== null || closedPolygons.length > 0 || newPolygonPoints.length > 0,\n });\n }, [lassoMode, selectedPolygon, closedPolygons, newPolygonPoints, historyIndex, history]);\n\n return (\n <>\n <g>\n <defs>\n <pattern\n id=\"diagonalStripes\"\n width=\"5\"\n height=\"5\"\n patternTransform=\"rotate(45 0 0)\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"10\" stroke={SELECTION_COLOR} strokeWidth=\"1\" />\n </pattern>\n </defs>\n <rect\n fill=\"transparent\"\n width={chartSizes.chartWidth}\n height={chartSizes.chartHeight}\n onMouseMove={onMouseMove}\n onClick={onNewPointAddByClick}\n />\n {closedPolygons.map((p, idx) => {\n const isHovered = idx === hoveredPolygon;\n const isSelected = idx === selectedPolygon;\n const points = p.points.map(p => [scales.x(p[0]), scales.y(p[1])]);\n const pathD =\n points\n .map((p, idx) => {\n return (idx === 0 ? 'M' : 'L') + p[0] + ',' + p[1];\n })\n .join('') + 'z';\n return (\n <g key={idx}>\n <path\n d={pathD}\n fill={isHovered && !isSelected ? 'url(#diagonalStripes)' : 'transparent'}\n stroke={isSelected || isHovered ? SELECTION_COLOR : BLACK}\n onMouseOver={() => setHoveredPolygon(idx)}\n onMouseLeave={() => setHoveredPolygon(null)}\n onClick={() => updateSelectedPolygon(idx)}\n style={{pointerEvents: lassoMode === 'selection' || isSelected ? 'none' : 'auto'}}\n />\n {isSelected && <g ref={el => updateSelectedCircles(el)} />}\n </g>\n );\n })}\n <polyline\n points={newPolygonPoints.map((p) => `${scales.x(p[0])},${scales.y(p[1])}`).join(' ')}\n stroke={BLACK}\n fill=\"none\"\n style={{pointerEvents: 'none'}}\n />\n {newPolygonPoints.length > 1 && movingPoint && (\n <g style={{pointerEvents: 'none'}}>\n <circle\n cx={scales.x(newPolygonPoints[0][0])}\n cy={scales.y(newPolygonPoints[0][1])}\n r={R_START}\n fill=\"none\"\n stroke={START_GREY}\n strokeDasharray=\"3 3\"\n />\n <line\n x1={movingPoint[0]}\n y1={movingPoint[1]}\n x2={scales.x(newPolygonPoints[0][0])}\n y2={scales.y(newPolygonPoints[0][1])}\n stroke={START_GREY}\n strokeDasharray=\"3 3\"\n />\n </g>\n )}\n {newPolygonPoints.length > 0 && movingPoint && (\n <g style={{pointerEvents: 'none'}}>\n <line\n x1={scales.x(newPolygonPoints[newPolygonPoints.length - 1][0])}\n y1={scales.y(newPolygonPoints[newPolygonPoints.length - 1][1])}\n x2={movingPoint[0]}\n y2={movingPoint[1]}\n stroke={SELECTION_COLOR}\n />\n {newPolygonPoints.map((p, idx) => (\n <circle\n key={idx}\n cx={scales.x(p[0])}\n cy={scales.y(p[1])}\n r={R}\n fill=\"white\"\n stroke={idx > 0 ? SELECTION_COLOR : BLACK}\n />\n ))}\n <circle\n cx={movingPoint[0]}\n cy={movingPoint[1]}\n r={R}\n fill=\"white\"\n stroke={SELECTION_COLOR}\n />\n </g>\n )}\n {closeToStartPoint && movingPoint && (\n <circle\n cx={movingPoint[0] + 5}\n cy={movingPoint[1] - 5}\n r={2}\n fill=\"none\"\n stroke={SELECTION_COLOR}\n strokeWidth={0.5}\n />\n )}\n </g>\n </>\n );\n}\n"],"names":["SELECTION_COLOR","START_GREY","CLOSING_DISTANCE","R","R_START","MAX_HISTORY_LENGTH","Lasso","scales","chartSizes","zoomStateKey","defaultPolygons","onPolygonsApply","onLassoControlsStateUpdate","useEffect","onPolygonDelete","newPolygonPointsRef","clearNotFinishedPolygon","selectedPolygonRef","updatePolygons","closedPolygonsRef","_p","idx","updateSelectedPolygon","onModeSelect","e","updateMode","onClickBack","loadHistoryItem","historyIndexRef","onClickForward","SCATTERPLOT_LASSO_EVENTS","lassoMode","setLassoMode","useState","closedPolygons","setClosedPolygons","useRef","hoveredPolygon","setHoveredPolygon","selectedPolygon","setSelectedPolygon","newPolygonPoints","setNewPolygonPoints","history","setHistory","historyIndex","setHistoryIndex","historyRef","movingPoint","setMovingPoint","movingPointRef","closeToStartPoint","setCloseToStartPoint","selectedCirclesContainerRef","selectedCirclesSelectionRef","saveCurrentStateToHistory","useCallback","newHistoryItem","newHistory","index","historyState","updateNewPolygon","p","saveToHistory","points","v","polygon","onKeyDown","_a","d","onNewPointAddByClick","currentCoords","x","y","onMouseMove","startPoint","startX","startY","distance","clearSelectedCircles","select","updateSelectedCircles","el","onPolygonSelect","drag","editedPolygons","polygonIdx","pointIdx","draggablePointsData","selectedCircles","jsx","Fragment","isHovered","isSelected","pathD","BLACK","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Lasso.js","sources":["../../../src/scatterplot-umap/components/Lasso.tsx"],"sourcesContent":["import {SCATTERPLOT_CONTROLS_EVENTS} from '../constants';\nimport type {LassoControlsState, LassoMode} from '../types';\nimport type {Polygon} from '../types';\nimport type {Selection} from 'd3-selection';\nimport {select} from 'd3-selection';\nimport {BLACK} from '../../constants';\nimport type {ChartScales, ChartSizes, Point} from '../types';\nimport type {MouseEvent} from 'react';\nimport React, {useCallback, useEffect, useRef, useState} from 'react';\nimport {drag} from 'd3-drag';\n\nconst SELECTION_COLOR = '#845CFF';\nconst START_GREY = '#CFD1DB';\nconst CLOSING_DISTANCE = 20;\nconst R = 3;\nconst R_START = 6;\nconst MAX_HISTORY_LENGTH = 10;\n\ntype CircleData = { // moving point for editing\n idx: number;\n p: Point;\n};\ntype CirclesSelection = Selection<SVGCircleElement, CircleData, SVGGElement | null, CircleData>;\n\ntype HistoryFrame = {\n newPolygonPoints: Point[],\n closedPolygons: Polygon[]\n}\n\n// Mode = 'selection': creating new polygons, pan with button\n// Mode = 'pen': selecting polygon to edit or delete, any zooming actions\nexport function Lasso({\n scales,\n chartSizes,\n zoomStateKey,\n defaultPolygons,\n onPolygonsApply,\n onLassoControlsStateUpdate,\n}: {\n scales: ChartScales;\n chartSizes: ChartSizes;\n zoomStateKey: string;\n defaultPolygons: Polygon[];\n onPolygonsApply: (data: Polygon[]) => void;\n onLassoControlsStateUpdate: (v: LassoControlsState) => void;\n}) {\n useEffect(() => {\n // Events from outer controls\n function onPolygonDelete() {\n if (newPolygonPointsRef.current.length > 0) {\n clearNotFinishedPolygon();\n } else if (selectedPolygonRef.current === null) {\n updatePolygons([]);\n onPolygonsApply([]);\n } else {\n updatePolygons([...closedPolygonsRef.current.filter((_p, idx) => idx !== selectedPolygonRef.current)]);\n updateSelectedPolygon(null);\n onPolygonsApply(closedPolygonsRef.current);\n }\n }\n\n function onModeSelect(e: CustomEvent<LassoMode>) {\n updateMode(e.detail);\n }\n function onClickBack() {\n loadHistoryItem(historyIndexRef.current - 1);\n }\n function onClickForward() {\n loadHistoryItem(historyIndexRef.current + 1);\n }\n document.addEventListener(SCATTERPLOT_CONTROLS_EVENTS.lassoDelete, onPolygonDelete);\n document.addEventListener(SCATTERPLOT_CONTROLS_EVENTS.lassoSelectMode, onModeSelect as EventListener);\n document.addEventListener(SCATTERPLOT_CONTROLS_EVENTS.lassoBack, onClickBack);\n document.addEventListener(SCATTERPLOT_CONTROLS_EVENTS.lassoForward, onClickForward);\n return () => {\n document.removeEventListener(SCATTERPLOT_CONTROLS_EVENTS.lassoDelete, onPolygonDelete);\n document.removeEventListener(SCATTERPLOT_CONTROLS_EVENTS.lassoSelectMode, onModeSelect as EventListener);\n document.removeEventListener(SCATTERPLOT_CONTROLS_EVENTS.lassoBack, onClickBack);\n document.removeEventListener(SCATTERPLOT_CONTROLS_EVENTS.lassoForward, onClickForward);\n };\n }, []);\n\n // inner state\n const [lassoMode, setLassoMode] = useState<LassoMode>('pen');\n\n const [closedPolygons, setClosedPolygons] = useState<Polygon[]>(defaultPolygons);\n const closedPolygonsRef = useRef<Polygon[]>(defaultPolygons);\n\n const [hoveredPolygon, setHoveredPolygon] = useState<number | null>(null);\n\n const [selectedPolygon, setSelectedPolygon] = useState<number | null>(null);\n const selectedPolygonRef = useRef<number | null>(null);\n\n const [newPolygonPoints, setNewPolygonPoints] = useState<Point[]>([]);\n const newPolygonPointsRef = useRef(newPolygonPoints);\n\n const [history, setHistory] = useState<HistoryFrame[]>([{newPolygonPoints, closedPolygons}]);\n const [historyIndex, setHistoryIndex] = useState(0);\n const historyRef = useRef(history);\n const historyIndexRef = useRef(historyIndex);\n\n const [movingPoint, setMovingPoint] = useState<null | Point>(null);\n const movingPointRef = useRef<null | Point>(null);\n\n const [closeToStartPoint, setCloseToStartPoint] = useState(false);\n\n const selectedCirclesContainerRef = useRef<SVGGElement | null>(null);\n const selectedCirclesSelectionRef = useRef<CirclesSelection | null>(null);\n\n const saveCurrentStateToHistory = useCallback(function () {\n const newHistoryItem = {\n newPolygonPoints: [...newPolygonPointsRef.current],\n closedPolygons: [...closedPolygonsRef.current]\n };\n const newHistory = historyRef.current.slice(0, historyIndexRef.current + 1);\n newHistory.push(newHistoryItem);\n if (newHistory.length > MAX_HISTORY_LENGTH) {\n newHistory.shift();\n }\n setHistory(newHistory);\n setHistoryIndex(newHistory.length - 1);\n historyRef.current = newHistory;\n historyIndexRef.current = newHistory.length - 1;\n }, []);\n\n const loadHistoryItem = useCallback(function (index:number) {\n if (index > historyRef.current.length - 1 || index < 0) {\n return;\n }\n updateMode('selection');\n const historyState = historyRef.current[index];\n updatePolygons(historyState.closedPolygons, false);\n updateNewPolygon(historyState.newPolygonPoints, false);\n setHistoryIndex(index);\n historyIndexRef.current = index;\n }, []);\n function updatePolygons(p: Polygon[], saveToHistory = true) {\n setClosedPolygons(p);\n closedPolygonsRef.current = p;\n if (saveToHistory) {\n saveCurrentStateToHistory();\n }\n }\n\n function updateNewPolygon(points:Point[], saveToHistory = true) {\n newPolygonPointsRef.current = points;\n setNewPolygonPoints(points);\n if (saveToHistory) {\n saveCurrentStateToHistory();\n }\n }\n\n function updateSelectedPolygon(idx: number | null) {\n setSelectedPolygon(idx);\n selectedPolygonRef.current = idx;\n }\n\n function updateMode(v: LassoMode) {\n setLassoMode(v);\n if (v === 'selection') {\n updateSelectedPolygon(null);\n selectedCirclesSelectionRef.current = null;\n selectedCirclesContainerRef.current = null;\n }\n if (v === 'pen') {\n if (newPolygonPointsRef.current.length > 2) {\n const polygon:Polygon = {points: newPolygonPointsRef.current, closed: true};\n updatePolygons([...closedPolygonsRef.current, polygon]);\n onPolygonsApply([...closedPolygonsRef.current, polygon]);\n }\n clearNotFinishedPolygon();\n }\n }\n function clearNotFinishedPolygon(saveToHistory = true) {\n movingPointRef.current = null;\n updateNewPolygon([], saveToHistory);\n }\n\n function onKeyDown(e: KeyboardEvent) {\n const escape = e.key === 'Escape';\n if (!escape) {\n return;\n }\n clearNotFinishedPolygon();\n }\n\n useEffect(() => {\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, []);\n\n useEffect(() => {\n selectedCirclesSelectionRef.current?.attr('cx', d => scales.x(d.p[0])).attr('cy', d => scales.y(d.p[1]));\n }, [zoomStateKey, chartSizes.chartWidth, chartSizes.chartHeight]);\n\n const onNewPointAddByClick = useCallback(function () {\n setCloseToStartPoint(false);\n if (!movingPointRef.current || lassoMode === 'pen') {\n return;\n }\n const currentCoords = [...movingPointRef.current] as Point;\n const x = scales.x.invert(currentCoords[0]);\n const y = scales.y.invert(currentCoords[1]);\n\n if (!newPolygonPointsRef.current.length) {\n updateNewPolygon([[x, y]]);\n return;\n }\n\n const points = newPolygonPointsRef.current;\n const tooFar = !closeToStartPoint;\n if (tooFar || points.length < 3) {\n updateNewPolygon([...points, [x, y]]);\n } else {\n const polygon:Polygon = {points: [...points], closed: true};\n clearNotFinishedPolygon(false);\n updatePolygons([...closedPolygons, polygon]);\n // to avoid freezing of ui updating in case of big amount of points to apply polygons and change opacity\n setTimeout(() => onPolygonsApply([...closedPolygons, polygon]), 0);\n }\n }, [lassoMode, closeToStartPoint]);\n\n const onMouseMove = useCallback(function(e: MouseEvent<SVGRectElement>) {\n const p: Point = [e.nativeEvent.offsetX, e.nativeEvent.offsetY];\n const points = newPolygonPointsRef.current;\n const startPoint = newPolygonPointsRef.current[0];\n if (startPoint) {\n const startX = scales.x(startPoint[0]);\n const startY = scales.y(startPoint[1]);\n const distance = points.length > 1\n ? Math.sqrt((p[0] - startX) ** 2 + (p[1] - startY) ** 2)\n : Infinity;\n setCloseToStartPoint(distance < CLOSING_DISTANCE);\n } else {\n setCloseToStartPoint(false);\n }\n\n setMovingPoint(p);\n movingPointRef.current = p;\n }, []);\n\n function clearSelectedCircles() {\n if (selectedCirclesContainerRef.current) {\n select(selectedCirclesContainerRef.current).data([]).exit().remove();\n }\n }\n\n function updateSelectedCircles(el: SVGGElement | null) {\n if (el !== selectedCirclesContainerRef.current && el) {\n clearSelectedCircles();\n selectedCirclesContainerRef.current = el;\n onPolygonSelect(selectedPolygon);\n }\n }\n\n const onPolygonSelect = useCallback(function (idx: number | null) {\n if (lassoMode === 'selection') {\n return;\n }\n if (idx !== null) {\n const d = drag<SVGCircleElement, CircleData, SVGGElement | null>()\n .on('drag', function (e) {\n const el = select<SVGCircleElement, CircleData>(this);\n const d = el.data()[0] as number[] & CircleData;\n d[0] = e.x;\n d[1] = e.y;\n d.p = [scales.x.invert(d[0]), scales.y.invert(d[1])];\n el.attr('cx', d[0]).attr('cy', d[1]);\n const editedPolygons = closedPolygonsRef.current.map((polygon, polygonIdx) => {\n return idx !== polygonIdx ? polygon : {\n ...polygon,\n points: polygon.points.map((el, pointIdx) =>\n pointIdx === d.idx ? ([scales.x.invert(d[0]), scales.y.invert(d[1])] as Point) : el\n ),\n };\n });\n updatePolygons(editedPolygons, false);\n })\n .on('end', function () {\n saveCurrentStateToHistory();\n onPolygonsApply(closedPolygonsRef.current);\n });\n const draggablePointsData = closedPolygonsRef.current[idx].points.map((p, idx) => ({idx, p}));\n const selectedCircles = select(selectedCirclesContainerRef.current)\n .selectAll<SVGCircleElement, CircleData>('circle')\n .data(draggablePointsData, (d) => d.idx)\n .join('circle');\n selectedCirclesSelectionRef.current = selectedCircles;\n\n selectedCircles\n .attr('cx', d => scales.x(d.p[0]))\n .attr('cy', d => scales.y(d.p[1]))\n .attr('r', R)\n .attr('fill', 'white')\n .attr('stroke', SELECTION_COLOR);\n selectedCircles.call(d);\n }\n }, []);\n\n useEffect(() => {\n onLassoControlsStateUpdate({\n mode: lassoMode,\n backEnabled: historyIndex > 0,\n forwardEnabled: historyIndex < history.length - 1,\n deleteEnabled: selectedPolygon !== null || closedPolygons.length > 0 || newPolygonPoints.length > 0,\n });\n }, [lassoMode, selectedPolygon, closedPolygons, newPolygonPoints, historyIndex, history]);\n\n return (\n <>\n <g>\n <defs>\n <pattern\n id=\"diagonalStripes\"\n width=\"5\"\n height=\"5\"\n patternTransform=\"rotate(45 0 0)\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"10\" stroke={SELECTION_COLOR} strokeWidth=\"1\" />\n </pattern>\n </defs>\n <rect\n fill=\"transparent\"\n width={chartSizes.chartWidth}\n height={chartSizes.chartHeight}\n onMouseMove={onMouseMove}\n onClick={onNewPointAddByClick}\n />\n {closedPolygons.map((p, idx) => {\n const isHovered = idx === hoveredPolygon;\n const isSelected = idx === selectedPolygon;\n const points = p.points.map(p => [scales.x(p[0]), scales.y(p[1])]);\n const pathD =\n points\n .map((p, idx) => {\n return (idx === 0 ? 'M' : 'L') + p[0] + ',' + p[1];\n })\n .join('') + 'z';\n return (\n <g key={idx}>\n <path\n d={pathD}\n fill={isHovered && !isSelected ? 'url(#diagonalStripes)' : 'transparent'}\n stroke={isSelected || isHovered ? SELECTION_COLOR : BLACK}\n onMouseOver={() => setHoveredPolygon(idx)}\n onMouseLeave={() => setHoveredPolygon(null)}\n onClick={() => updateSelectedPolygon(idx)}\n style={{pointerEvents: lassoMode === 'selection' || isSelected ? 'none' : 'auto'}}\n />\n {isSelected && <g ref={el => updateSelectedCircles(el)} />}\n </g>\n );\n })}\n <polyline\n points={newPolygonPoints.map((p) => `${scales.x(p[0])},${scales.y(p[1])}`).join(' ')}\n stroke={BLACK}\n fill=\"none\"\n style={{pointerEvents: 'none'}}\n />\n {newPolygonPoints.length > 1 && movingPoint && (\n <g style={{pointerEvents: 'none'}}>\n <circle\n cx={scales.x(newPolygonPoints[0][0])}\n cy={scales.y(newPolygonPoints[0][1])}\n r={R_START}\n fill=\"none\"\n stroke={START_GREY}\n strokeDasharray=\"3 3\"\n />\n <line\n x1={movingPoint[0]}\n y1={movingPoint[1]}\n x2={scales.x(newPolygonPoints[0][0])}\n y2={scales.y(newPolygonPoints[0][1])}\n stroke={START_GREY}\n strokeDasharray=\"3 3\"\n />\n </g>\n )}\n {newPolygonPoints.length > 0 && movingPoint && (\n <g style={{pointerEvents: 'none'}}>\n <line\n x1={scales.x(newPolygonPoints[newPolygonPoints.length - 1][0])}\n y1={scales.y(newPolygonPoints[newPolygonPoints.length - 1][1])}\n x2={movingPoint[0]}\n y2={movingPoint[1]}\n stroke={SELECTION_COLOR}\n />\n {newPolygonPoints.map((p, idx) => (\n <circle\n key={idx}\n cx={scales.x(p[0])}\n cy={scales.y(p[1])}\n r={R}\n fill=\"white\"\n stroke={idx > 0 ? SELECTION_COLOR : BLACK}\n />\n ))}\n <circle\n cx={movingPoint[0]}\n cy={movingPoint[1]}\n r={R}\n fill=\"white\"\n stroke={SELECTION_COLOR}\n />\n </g>\n )}\n {closeToStartPoint && movingPoint && (\n <circle\n cx={movingPoint[0] + 5}\n cy={movingPoint[1] - 5}\n r={2}\n fill=\"none\"\n stroke={SELECTION_COLOR}\n strokeWidth={0.5}\n />\n )}\n </g>\n </>\n );\n}\n"],"names":["SELECTION_COLOR","START_GREY","CLOSING_DISTANCE","R","R_START","MAX_HISTORY_LENGTH","Lasso","scales","chartSizes","zoomStateKey","defaultPolygons","onPolygonsApply","onLassoControlsStateUpdate","useEffect","onPolygonDelete","newPolygonPointsRef","clearNotFinishedPolygon","selectedPolygonRef","updatePolygons","closedPolygonsRef","_p","idx","updateSelectedPolygon","onModeSelect","e","updateMode","onClickBack","loadHistoryItem","historyIndexRef","onClickForward","SCATTERPLOT_CONTROLS_EVENTS","lassoMode","setLassoMode","useState","closedPolygons","setClosedPolygons","useRef","hoveredPolygon","setHoveredPolygon","selectedPolygon","setSelectedPolygon","newPolygonPoints","setNewPolygonPoints","history","setHistory","historyIndex","setHistoryIndex","historyRef","movingPoint","setMovingPoint","movingPointRef","closeToStartPoint","setCloseToStartPoint","selectedCirclesContainerRef","selectedCirclesSelectionRef","saveCurrentStateToHistory","useCallback","newHistoryItem","newHistory","index","historyState","updateNewPolygon","p","saveToHistory","points","v","polygon","onKeyDown","_a","d","onNewPointAddByClick","currentCoords","x","y","onMouseMove","startPoint","startX","startY","distance","clearSelectedCircles","select","updateSelectedCircles","el","onPolygonSelect","drag","editedPolygons","polygonIdx","pointIdx","draggablePointsData","selectedCircles","jsx","Fragment","isHovered","isSelected","pathD","BLACK","jsxs"],"mappings":"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"}
@@ -9,9 +9,10 @@ export declare const DEFAULT_TICKS_SIZE = 4;
9
9
  export declare const TICK_OFFSET = 6;
10
10
  export declare const MIN_PADDING = 12;
11
11
  export declare const LEGEND_OFFSET = 24;
12
- export declare const SCATTERPLOT_LASSO_EVENTS: {
13
- delete: string;
14
- selectMode: string;
15
- back: string;
16
- forward: string;
12
+ export declare const SCATTERPLOT_CONTROLS_EVENTS: {
13
+ lassoDelete: string;
14
+ lassoSelectMode: string;
15
+ lassoBack: string;
16
+ lassoForward: string;
17
+ resetViewport: string;
17
18
  };
@@ -1,19 +1,20 @@
1
- const E = {
1
+ const T = {
2
2
  TOP: 30,
3
3
  BOTTOM: 30,
4
4
  LEFT: 30,
5
5
  RIGHT: 30
6
- }, S = 20, T = 4, L = 24, O = {
7
- delete: "LASSO_DELETE",
8
- selectMode: "LASSO_SELECT_MODE",
9
- back: "LASSO_BACK",
10
- forward: "LASSO_FORWARD"
6
+ }, E = 20, S = 4, O = 24, s = {
7
+ lassoDelete: "LASSO_DELETE",
8
+ lassoSelectMode: "LASSO_SELECT_MODE",
9
+ lassoBack: "LASSO_BACK",
10
+ lassoForward: "LASSO_FORWARD",
11
+ resetViewport: "SCATTERPLOT_RESET_VIEWPORT"
11
12
  };
12
13
  export {
13
- T as DEFAULT_TICKS_SIZE,
14
- L as LEGEND_OFFSET,
15
- E as PADDINGS,
16
- O as SCATTERPLOT_LASSO_EVENTS,
17
- S as TITLE_LINE
14
+ S as DEFAULT_TICKS_SIZE,
15
+ O as LEGEND_OFFSET,
16
+ T as PADDINGS,
17
+ s as SCATTERPLOT_CONTROLS_EVENTS,
18
+ E as TITLE_LINE
18
19
  };
19
20
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../src/scatterplot-umap/constants.ts"],"sourcesContent":["// inner paddings in chart area\nexport const PADDINGS = {\n TOP: 30,\n BOTTOM: 30,\n LEFT: 30,\n RIGHT: 30\n};\n\nexport const TITLE_LINE = 20;\nexport const DEFAULT_TICKS_SIZE = 4;\nexport const TICK_OFFSET = 6;\nexport const MIN_PADDING = 12;\n\nexport const LEGEND_OFFSET = 24;\n\nexport const SCATTERPLOT_LASSO_EVENTS = {\n delete: 'LASSO_DELETE',\n selectMode: 'LASSO_SELECT_MODE',\n back: 'LASSO_BACK',\n forward: 'LASSO_FORWARD'\n};\n"],"names":["PADDINGS","TITLE_LINE","DEFAULT_TICKS_SIZE","LEGEND_OFFSET","SCATTERPLOT_LASSO_EVENTS"],"mappings":"AACO,MAAMA,IAAW;AAAA,EACpB,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AACX,GAEaC,IAAa,IACbC,IAAqB,GAIrBC,IAAgB,IAEhBC,IAA2B;AAAA,EACpC,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,SAAS;AACb;"}
1
+ {"version":3,"file":"constants.js","sources":["../../src/scatterplot-umap/constants.ts"],"sourcesContent":["// inner paddings in chart area\nexport const PADDINGS = {\n TOP: 30,\n BOTTOM: 30,\n LEFT: 30,\n RIGHT: 30\n};\n\nexport const TITLE_LINE = 20;\nexport const DEFAULT_TICKS_SIZE = 4;\nexport const TICK_OFFSET = 6;\nexport const MIN_PADDING = 12;\n\nexport const LEGEND_OFFSET = 24;\n\nexport const SCATTERPLOT_CONTROLS_EVENTS = {\n lassoDelete: 'LASSO_DELETE',\n lassoSelectMode: 'LASSO_SELECT_MODE',\n lassoBack: 'LASSO_BACK',\n lassoForward: 'LASSO_FORWARD',\n resetViewport: 'SCATTERPLOT_RESET_VIEWPORT'\n};\n"],"names":["PADDINGS","TITLE_LINE","DEFAULT_TICKS_SIZE","LEGEND_OFFSET","SCATTERPLOT_CONTROLS_EVENTS"],"mappings":"AACO,MAAMA,IAAW;AAAA,EACpB,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AACX,GAEaC,IAAa,IACbC,IAAqB,GAIrBC,IAAgB,IAEhBC,IAA8B;AAAA,EACvC,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,eAAe;AACnB;"}
@@ -11,6 +11,7 @@ export declare class ChartScatterplotUmap extends AbstractChart {
11
11
  onPolygonUpdate: (data: number[], polygons: Polygon[]) => void;
12
12
  onTooltipHintSwitch: (v: boolean) => void;
13
13
  onLassoControlsStateUpdate: (v: LassoControlsState) => void;
14
+ onZoomChange: (isZoomChanged: boolean) => void;
14
15
  calculatedData: {
15
16
  dots: Dot[];
16
17
  groupingKeys: string[];
@@ -1,32 +1,34 @@
1
- var U = Object.defineProperty;
2
- var L = (d, p, t) => p in d ? U(d, p, { enumerable: !0, configurable: !0, writable: !0, value: t }) : d[p] = t;
3
- var g = (d, p, t) => L(d, typeof p != "symbol" ? p + "" : p, t);
4
- import { AbstractChart as A } from "../AbstractChart.js";
5
- import { createLegendInfo as R, addPalettesToAesMapping as I } from "../scatterplot/utils/createLegendInfo.js";
6
- import { formatColumnValue as T } from "../scatterplot/utils/formatColumnValue.js";
7
- import { sortDotsByGrouping as P } from "../scatterplot/utils/sortDotsByGrouping.js";
8
- import { arraysAreDifferent as v } from "../utils/arraysAreDifferent.js";
9
- import B from "./ChartRenderer.js";
10
- import { SCATTERPLOT_LASSO_EVENTS as f } from "./constants.js";
11
- import { ScatterplotUmapSettingsImpl as D } from "./SettingsImpl.js";
1
+ var R = Object.defineProperty;
2
+ var A = (c, p, t) => p in c ? R(c, p, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[p] = t;
3
+ var f = (c, p, t) => A(c, typeof p != "symbol" ? p + "" : p, t);
4
+ import { AbstractChart as T } from "../AbstractChart.js";
5
+ import { createLegendInfo as X, addPalettesToAesMapping as Y } from "../scatterplot/utils/createLegendInfo.js";
6
+ import { formatColumnValue as B } from "../scatterplot/utils/formatColumnValue.js";
7
+ import { sortDotsByGrouping as I } from "../scatterplot/utils/sortDotsByGrouping.js";
8
+ import { arraysAreDifferent as b } from "../utils/arraysAreDifferent.js";
9
+ import P from "./ChartRenderer.js";
10
+ import { SCATTERPLOT_CONTROLS_EVENTS as m } from "./constants.js";
11
+ import { ScatterplotUmapSettingsImpl as w } from "./SettingsImpl.js";
12
12
  import { format as V } from "../node_modules/.pnpm/d3-format@3.1.0/node_modules/d3-format/src/defaultLocale.js";
13
- function X(d) {
14
- return typeof d == "object" && "type" in d && d.type === "grouping";
13
+ function Z(c) {
14
+ return typeof c == "object" && "type" in c && c.type === "grouping";
15
15
  }
16
- class N extends A {
16
+ class H extends T {
17
17
  constructor(t, a, e) {
18
18
  super(t, a);
19
- g(this, "settings");
20
- g(this, "chartRenderer");
21
- g(this, "onPolygonUpdate", () => {
19
+ f(this, "settings");
20
+ f(this, "chartRenderer");
21
+ f(this, "onPolygonUpdate", () => {
22
22
  });
23
23
  // dots indexes from input data
24
- g(this, "onTooltipHintSwitch", () => {
24
+ f(this, "onTooltipHintSwitch", () => {
25
25
  });
26
- g(this, "onLassoControlsStateUpdate", () => {
26
+ f(this, "onLassoControlsStateUpdate", () => {
27
27
  });
28
- g(this, "calculatedData", null);
29
- this.settings = new D(a), this.chartRenderer = new B(), e && (this.onPolygonUpdate = e.onPolygonUpdate, this.onTooltipHintSwitch = e.onTooltipHintSwitch, this.onLassoControlsStateUpdate = e.onLassoControlsStateUpdate);
28
+ f(this, "onZoomChange", () => {
29
+ });
30
+ f(this, "calculatedData", null);
31
+ this.settings = new w(a), this.chartRenderer = new P(), e && (this.onPolygonUpdate = e.onPolygonUpdate, this.onTooltipHintSwitch = e.onTooltipHintSwitch, this.onLassoControlsStateUpdate = e.onLassoControlsStateUpdate, this.onZoomChange = e.onZoomChange);
30
32
  }
31
33
  mount(t) {
32
34
  try {
@@ -40,88 +42,95 @@ class N extends A {
40
42
  }
41
43
  updateSettingsAndData(t, a) {
42
44
  try {
43
- const e = this.settings, n = this.data;
44
- this.settings = new D(a), this.data = t, this._needUpdateCalculatedDataBySettings(e, this.settings) || this._needUpdateCalculatedDataByData(n, this.data) ? this._updateData() : this._updateAesInData();
45
- const s = e.layers.find((o) => o.type === "dots"), r = this.settings.layers.find((o) => o.type === "dots");
46
- s && r && s.aes.dotSize !== r.aes.dotSize && typeof s.aes.dotSize == "number" && typeof r.aes.dotSize == "number" && this.chartRenderer.updatePointSize(), this._updateChart(), this.hasError = !1;
45
+ const e = this.settings, s = this.data;
46
+ this.settings = new w(a), this.data = t, this._needUpdateCalculatedDataBySettings(e, this.settings) || this._needUpdateCalculatedDataByData(s, this.data) ? this._updateData() : this._updateAesInData();
47
+ const n = e.layers.find((o) => o.type === "dots"), i = this.settings.layers.find((o) => o.type === "dots");
48
+ n && i && n.aes.dotSize !== i.aes.dotSize && typeof n.aes.dotSize == "number" && typeof i.aes.dotSize == "number" && this.chartRenderer.updatePointSize(), this._updateChart(), this.hasError = !1;
47
49
  } catch (e) {
48
50
  this.hasError = !0, e instanceof Error && (this.chartRenderer.renderError(e.message), console.error(e));
49
51
  }
50
52
  }
51
53
  updateChartState(t, a) {
52
- if (t === "polygon" && (this.chartRenderer.polygons = a, this._updateChart()), t === f.delete && document) {
53
- const e = new CustomEvent(f.delete);
54
- document.dispatchEvent(e);
54
+ var e;
55
+ if (t === "polygon" && (this.chartRenderer.polygons = a, this._updateChart()), t === m.lassoDelete && document) {
56
+ const s = new CustomEvent(m.lassoDelete);
57
+ document.dispatchEvent(s);
55
58
  }
56
- if (t === f.selectMode && document) {
57
- const e = new CustomEvent(f.selectMode, { detail: a });
58
- document.dispatchEvent(e);
59
+ if (t === m.lassoSelectMode && document) {
60
+ const s = new CustomEvent(m.lassoSelectMode, { detail: a });
61
+ document.dispatchEvent(s);
59
62
  }
60
- if (t === f.forward && document) {
61
- const e = new CustomEvent(f.forward);
62
- document.dispatchEvent(e);
63
+ if (t === m.lassoForward && document) {
64
+ const s = new CustomEvent(m.lassoForward);
65
+ document.dispatchEvent(s);
63
66
  }
64
- if (t === f.back && document) {
65
- const e = new CustomEvent(f.back);
66
- document.dispatchEvent(e);
67
+ if (t === m.lassoBack && document) {
68
+ const s = new CustomEvent(m.lassoBack);
69
+ document.dispatchEvent(s);
67
70
  }
71
+ t === m.resetViewport && (this.chartRenderer.resetZoom(this.settings.chartSettings.xAxis, this.settings.chartSettings.yAxis, (e = this.calculatedData) == null ? void 0 : e.dotsExtents), this.onZoomChange(!1));
68
72
  }
69
73
  export() {
70
74
  return console.warn("export not implemented"), "";
71
75
  }
72
76
  _needUpdateCalculatedDataBySettings(t, a) {
73
- var e, n, s, r;
74
- return v(
77
+ var e, s, n, i;
78
+ return b(
75
79
  t.grouping.map((o) => o.columnName.value),
76
80
  a.grouping.map((o) => o.columnName.value)
77
- ) || t.grouping.some((o, l) => {
78
- var m;
79
- return v(o.order, (m = a.grouping) == null ? void 0 : m[l].order);
80
- }) || t.layers.length !== a.layers.length || t.layers.some((o, l) => o.type !== a.layers[l].type) || (((e = t.label) == null ? void 0 : e.value) || ((n = a.label) == null ? void 0 : n.value)) && ((s = t.label) == null ? void 0 : s.value) !== ((r = a.label) == null ? void 0 : r.value);
81
+ ) || t.grouping.some((o, u) => {
82
+ var g;
83
+ return b(o.order, (g = a.grouping) == null ? void 0 : g[u].order);
84
+ }) || t.layers.length !== a.layers.length || t.layers.some((o, u) => o.type !== a.layers[u].type) || (((e = t.label) == null ? void 0 : e.value) || ((s = a.label) == null ? void 0 : s.value)) && ((n = t.label) == null ? void 0 : n.value) !== ((i = a.label) == null ? void 0 : i.value);
81
85
  }
82
86
  _needUpdateCalculatedDataByData(t, a) {
83
- const e = Object.keys(t.data), n = Object.keys(a.data);
84
- return t.id !== a.id || e.length !== n.length || e.some((s) => {
85
- var r;
86
- return t.data[s].length !== ((r = a.data[s]) == null ? void 0 : r.length);
87
+ const e = Object.keys(t.data), s = Object.keys(a.data);
88
+ return t.id !== a.id || e.length !== s.length || e.some((n) => {
89
+ var i;
90
+ return t.data[n].length !== ((i = a.data[n]) == null ? void 0 : i.length);
87
91
  });
88
92
  }
89
93
  _updateData() {
90
- const { x: t, y: a, label: e, highlight: n, grouping: s, layers: r } = this.settings, o = {
94
+ var D;
95
+ const { x: t, y: a, label: e, highlight: s, grouping: n, layers: i } = this.settings, o = {
91
96
  minX: 1 / 0,
92
97
  maxX: -1 / 0,
93
98
  minY: 1 / 0,
94
99
  maxY: -1 / 0
95
- }, l = r.some((i) => i.type === "curve"), m = /* @__PURE__ */ new Set(), c = {}, C = [], b = e != null && e.format ? V(e.format) : void 0;
96
- for (let i = 0; i < this.data.rowsCount; i++) {
97
- const u = this.data.getColumnValue(t.value, i), h = this.data.getColumnValue(a.value, i);
98
- if (typeof u != "number" || typeof h != "number" || !isFinite(u) || !isFinite(h))
100
+ }, u = i.some((r) => r.type === "curve"), g = /* @__PURE__ */ new Set(), h = {}, C = [], _ = e != null && e.format ? V(e.format) : void 0;
101
+ for (let r = 0; r < this.data.rowsCount; r++) {
102
+ const d = this.data.getColumnValue(t.value, r), l = this.data.getColumnValue(a.value, r);
103
+ if (typeof d != "number" || typeof l != "number" || !isFinite(d) || !isFinite(l))
99
104
  continue;
100
- u < o.minX && (o.minX = u), u > o.maxX && (o.maxX = u), h < o.minY && (o.minY = h), h > o.maxY && (o.maxY = h);
101
- const w = n ? !this.data.getColumnValue(n.value, i) : !1, S = {
102
- x: u,
103
- y: h,
104
- idx: i,
105
- label: T(this.data, i, e, b),
106
- dimmed: w
105
+ d < o.minX && (o.minX = d), d > o.maxX && (o.maxX = d), l < o.minY && (o.minY = l), l > o.maxY && (o.maxY = l);
106
+ const x = s ? !this.data.getColumnValue(s.value, r) : !1, v = {
107
+ x: d,
108
+ y: l,
109
+ idx: r,
110
+ label: B(this.data, r, e, _),
111
+ dimmed: x
107
112
  };
108
- if (l) {
109
- const y = s.map(({ columnName: _ }) => this.data.getColumnValue(_.value, i)).join("_");
110
- m.add(y), c[y] || (c[y] = []), c[y].push(S);
113
+ if (u) {
114
+ const y = n.map(({ columnName: L }) => this.data.getColumnValue(L.value, r)).join("_");
115
+ g.add(y), h[y] || (h[y] = []), h[y].push(v);
111
116
  }
112
- C.push(S);
117
+ C.push(v);
118
+ }
119
+ const E = [...g];
120
+ u && E.forEach((r) => {
121
+ h[r].sort((d, l) => d.x - l.x);
122
+ }), I(this.data, C, n, s);
123
+ const U = X(this.data, n, i), S = ((D = this.calculatedData) == null ? void 0 : D.dotsExtents) ?? null;
124
+ if (S) {
125
+ const { minX: r, maxX: d, minY: l, maxY: x } = S;
126
+ (r !== o.minX || d !== o.maxX || l !== o.minY || x !== o.maxY) && this.onZoomChange(!0);
113
127
  }
114
- const E = [...m];
115
- l && E.forEach((i) => {
116
- c[i].sort((u, h) => u.x - h.x);
117
- }), P(this.data, C, s, n);
118
- const x = R(this.data, s, r);
119
128
  this.calculatedData = {
120
129
  dots: C,
121
- dotsByGrouping: c,
130
+ dotsByGrouping: h,
122
131
  groupingKeys: E,
123
132
  dotsExtents: o,
124
- legendLabels: x
133
+ legendLabels: U
125
134
  };
126
135
  }
127
136
  _updateAesInData() {
@@ -129,19 +138,19 @@ class N extends A {
129
138
  if (!t)
130
139
  return;
131
140
  const { layers: a, grouping: e } = this.settings;
132
- e.forEach(({ columnName: n, inheritedAes: s }) => {
133
- const r = /* @__PURE__ */ new Set(), o = {};
134
- a.forEach((l) => {
135
- l.aes && Object.entries(l.aes).forEach(([m, c]) => {
136
- X(c) && c.value === n.value && (r.add(m), c.palette && (o[m] = c.palette));
141
+ e.forEach(({ columnName: s, inheritedAes: n }) => {
142
+ const i = /* @__PURE__ */ new Set(), o = {};
143
+ a.forEach((u) => {
144
+ u.aes && Object.entries(u.aes).forEach(([g, h]) => {
145
+ Z(h) && h.value === s.value && (i.add(g), h.palette && (o[g] = h.palette));
137
146
  });
138
- }), t.legendLabels[n.value].usedAes = [...r], t.legendLabels[n.value].aesMap = I(n, o, s);
147
+ }), t.legendLabels[s.value].usedAes = [...i], t.legendLabels[s.value].aesMap = Y(s, o, n);
139
148
  });
140
149
  }
141
150
  _updateChart() {
142
151
  if (!this.calculatedData)
143
152
  return;
144
- const { id: t, chartSettings: a, keyColumn: e, layers: n, grouping: s } = this.settings;
153
+ const { id: t, chartSettings: a, keyColumn: e, layers: s, grouping: n } = this.settings;
145
154
  this.chartRenderer.render(
146
155
  this.data,
147
156
  t,
@@ -150,16 +159,17 @@ class N extends A {
150
159
  this.calculatedData.dots,
151
160
  this.calculatedData.dotsExtents,
152
161
  this.calculatedData.dotsByGrouping,
153
- n,
162
+ s,
154
163
  this.calculatedData.legendLabels,
155
- s.map((r) => r.columnName),
164
+ n.map((i) => i.columnName),
156
165
  this.onPolygonUpdate,
157
166
  this.onTooltipHintSwitch,
158
- this.onLassoControlsStateUpdate
167
+ this.onLassoControlsStateUpdate,
168
+ this.onZoomChange
159
169
  );
160
170
  }
161
171
  }
162
172
  export {
163
- N as ChartScatterplotUmap
173
+ H as ChartScatterplotUmap
164
174
  };
165
175
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/scatterplot-umap/index.ts"],"sourcesContent":["import {format} from 'd3-format';\nimport { AbstractChart } from '../AbstractChart';\nimport type { DataFrame } from '../DataFrame';\nimport { addPalettesToAesMapping, createLegendInfo } from '../scatterplot/utils/createLegendInfo';\nimport {formatColumnValue} from '../scatterplot/utils/formatColumnValue';\nimport {sortDotsByGrouping} from '../scatterplot/utils/sortDotsByGrouping';\nimport type { AesItem, ContinuousAesFromColumn, InheritAesScatterplot, ScatterplotEventHandlers } from '../types';\nimport type { ScatterplotUmapLegendInfo, ScatterplotUmapSettings } from '../types/scatterplot-umap';\nimport {arraysAreDifferent} from '../utils/arraysAreDifferent';\nimport ChartRenderer from './ChartRenderer';\nimport { SCATTERPLOT_LASSO_EVENTS } from './constants';\nimport type { DotsLayer } from './SettingsImpl';\nimport { ScatterplotUmapSettingsImpl } from './SettingsImpl';\nimport type { Dot, DotsExtents, LassoControlsState, LassoMode, Polygon } from './types';\n\nfunction isInheritMapping<T extends (string | number)>(value:T | InheritAesScatterplot | ContinuousAesFromColumn<T>):value is InheritAesScatterplot {\n return typeof value === 'object' && 'type' in value && value.type === 'grouping';\n}\n\nexport class ChartScatterplotUmap extends AbstractChart {\n settings: ScatterplotUmapSettingsImpl;\n chartRenderer: ChartRenderer;\n\n onPolygonUpdate: (data: number[], polygons: Polygon[]) => void = () => undefined; // dots indexes from input data\n onTooltipHintSwitch: (v:boolean) => void = () => undefined;\n onLassoControlsStateUpdate: (v: LassoControlsState) => void = () => undefined;\n\n calculatedData: {\n dots: Dot[],\n groupingKeys: string[],\n dotsByGrouping: Record<string, Dot[]>,\n dotsExtents: DotsExtents,\n legendLabels: ScatterplotUmapLegendInfo\n } | null = null;\n\n constructor(data: DataFrame, settings: ScatterplotUmapSettings, eventHandlers?: ScatterplotEventHandlers) {\n super(data, settings);\n\n this.settings = new ScatterplotUmapSettingsImpl(settings);\n this.chartRenderer = new ChartRenderer();\n\n if (eventHandlers) {\n this.onPolygonUpdate = eventHandlers.onPolygonUpdate;\n this.onTooltipHintSwitch = eventHandlers.onTooltipHintSwitch;\n this.onLassoControlsStateUpdate = eventHandlers.onLassoControlsStateUpdate;\n }\n }\n\n mount(node: HTMLElement) {\n try {\n this.chartRenderer.init(node);\n this._updateData();\n this._updateChart();\n this.hasError = false;\n } catch (err) {\n this.hasError = true;\n console.error(err);\n if (err instanceof Error) {\n this.chartRenderer.renderError(err.message as string);\n console.error(err);\n }\n }\n }\n\n unmount() {\n this.chartRenderer.clear();\n }\n\n updateSettingsAndData(data: DataFrame, settings: ScatterplotUmapSettings) {\n try {\n const previousSettings = this.settings;\n const previousData = this.data;\n this.settings = new ScatterplotUmapSettingsImpl(settings);\n this.data = data;\n if (\n this._needUpdateCalculatedDataBySettings(previousSettings, this.settings) ||\n this._needUpdateCalculatedDataByData(previousData, this.data)\n ) {\n this._updateData();\n } else {\n this._updateAesInData();\n }\n\n // for some reason it's not enough for size updating to do like with fillColor\n const prevLayer = previousSettings.layers.find(l => l.type === 'dots') as DotsLayer;\n const currentLayer = this.settings.layers.find(l => l.type === 'dots') as DotsLayer;\n if (prevLayer && currentLayer && prevLayer.aes.dotSize !== currentLayer.aes.dotSize\n && typeof prevLayer.aes.dotSize === 'number' && typeof currentLayer.aes.dotSize === 'number') {\n this.chartRenderer.updatePointSize();\n }\n this._updateChart();\n this.hasError = false;\n } catch (err) {\n this.hasError = true;\n if (err instanceof Error) {\n this.chartRenderer.renderError(err.message as string);\n console.error(err);\n }\n }\n }\n\n updateChartState(field: string, value: unknown) {\n if (field === 'polygon') {\n this.chartRenderer.polygons = value as Polygon[];\n this._updateChart();\n }\n if (field === SCATTERPLOT_LASSO_EVENTS.delete) {\n if (document) {\n const event = new CustomEvent(SCATTERPLOT_LASSO_EVENTS.delete);\n document.dispatchEvent(event);\n }}\n if (field === SCATTERPLOT_LASSO_EVENTS.selectMode) {\n if (document) {\n const event = new CustomEvent(SCATTERPLOT_LASSO_EVENTS.selectMode, {detail: value as LassoMode});\n document.dispatchEvent(event);\n }\n }\n if (field === SCATTERPLOT_LASSO_EVENTS.forward) {\n if (document) {\n const event = new CustomEvent(SCATTERPLOT_LASSO_EVENTS.forward);\n document.dispatchEvent(event);\n }\n }\n if (field === SCATTERPLOT_LASSO_EVENTS.back) {\n if (document) {\n const event = new CustomEvent(SCATTERPLOT_LASSO_EVENTS.back);\n document.dispatchEvent(event);\n }\n }\n }\n\n export(): string {\n console.warn('export not implemented');\n return '';\n // this._updateChart();\n // return renderToString(this.chartRenderer.component);\n }\n\n _needUpdateCalculatedDataBySettings(prevSettings: ScatterplotUmapSettingsImpl, settings: ScatterplotUmapSettingsImpl) {\n return (\n arraysAreDifferent(\n prevSettings.grouping.map(v => v.columnName.value),\n settings.grouping.map(v => v.columnName.value),\n ) ||\n prevSettings.grouping.some((v, idx) => arraysAreDifferent(v.order, settings.grouping?.[idx].order)) ||\n prevSettings.layers.length !== settings.layers.length ||\n prevSettings.layers.some((l, idx) => l.type !== settings.layers[idx].type) ||\n (prevSettings.label?.value || settings.label?.value) && prevSettings.label?.value !== settings.label?.value\n );\n }\n\n _needUpdateCalculatedDataByData(prevData: DataFrame, data: DataFrame) {\n const prevKeys = Object.keys(prevData.data);\n const keys = Object.keys(data.data);\n return (\n prevData.id !== data.id ||\n prevKeys.length !== keys.length ||\n prevKeys.some(key => prevData.data[key].length !== data.data[key]?.length)\n );\n }\n\n _updateData() {\n const {x, y, label, highlight, grouping, layers} = this.settings;\n\n const dotsExtents = {\n minX: Infinity,\n maxX: -Infinity,\n minY: Infinity,\n maxY: -Infinity,\n };\n\n const hasCurve = layers.some(layer => layer.type === 'curve');\n const groupingKeysSet = new Set<string>();\n const dotsByGrouping:Record<string, Dot[]> = {};\n\n const dots: Dot[] = [];\n const labelFormatter = label?.format ? format(label.format) : undefined;\n\n for (let idx = 0; idx < this.data.rowsCount; idx++) {\n const xv = this.data.getColumnValue(x.value, idx);\n const yv = this.data.getColumnValue(y.value, idx);\n\n if (typeof xv !== 'number' || typeof yv !== 'number') {\n continue;\n }\n if (!isFinite(xv) || !isFinite(yv)) {\n continue;\n }\n\n if (xv < dotsExtents.minX) {\n dotsExtents.minX = xv;\n }\n if (xv > dotsExtents.maxX) {\n dotsExtents.maxX = xv;\n }\n if (yv < dotsExtents.minY) {\n dotsExtents.minY = yv;\n }\n if (yv > dotsExtents.maxY) {\n dotsExtents.maxY = yv;\n }\n\n const dimmed = highlight ? !this.data.getColumnValue(highlight.value, idx) : false;\n const dot: Dot = {\n x: xv,\n y: yv,\n idx,\n label: formatColumnValue(this.data, idx, label, labelFormatter),\n dimmed\n };\n if (hasCurve) {\n const groupingKey = grouping.map(({columnName}) => this.data.getColumnValue(columnName.value, idx)).join('_');\n groupingKeysSet.add(groupingKey);\n if (!dotsByGrouping[groupingKey]) {\n dotsByGrouping[groupingKey] = [];\n }\n dotsByGrouping[groupingKey].push(dot);\n }\n dots.push(dot);\n }\n\n const groupingKeys = [...groupingKeysSet];\n if (hasCurve) {\n groupingKeys.forEach(key => {\n dotsByGrouping[key].sort((a, b) => a.x - b.x);\n });\n }\n sortDotsByGrouping(this.data, dots, grouping, highlight);\n const legendLabels = createLegendInfo(this.data, grouping, layers);\n\n this.calculatedData = {\n dots,\n dotsByGrouping,\n groupingKeys,\n dotsExtents,\n legendLabels,\n };\n }\n\n _updateAesInData() {\n const calculated = this.calculatedData;\n if (!calculated) {\n return;\n }\n const {layers, grouping} = this.settings;\n grouping.forEach(({columnName, inheritedAes}) => {\n const usedAes = new Set<keyof AesItem>();\n const usedAesFromPalettes:Partial<Record<keyof AesItem, string[]>> = {}; // if there is palette in mapping then\n layers.forEach(layer => {\n if (!layer.aes) return;\n \n Object.entries(layer.aes).forEach(([key, value]) => {\n if (!(isInheritMapping(value) && value.value === columnName.value)) return;\n usedAes.add(key as keyof AesItem);\n if (value.palette) {\n usedAesFromPalettes[key as keyof AesItem] = value.palette;\n }\n });\n });\n\n calculated.legendLabels[columnName.value].usedAes = [...usedAes];\n calculated.legendLabels[columnName.value].aesMap = addPalettesToAesMapping(columnName, usedAesFromPalettes, inheritedAes);\n });\n }\n\n _updateChart() {\n if (!this.calculatedData) {\n return;\n }\n const {id, chartSettings, keyColumn, layers, grouping} = this.settings;\n this.chartRenderer.render(\n this.data,\n id,\n chartSettings,\n keyColumn,\n this.calculatedData.dots,\n this.calculatedData.dotsExtents,\n this.calculatedData.dotsByGrouping,\n layers,\n this.calculatedData.legendLabels,\n grouping.map(v => v.columnName),\n this.onPolygonUpdate,\n this.onTooltipHintSwitch,\n this.onLassoControlsStateUpdate\n );\n }\n}\n"],"names":["isInheritMapping","value","ChartScatterplotUmap","AbstractChart","data","settings","eventHandlers","__publicField","ScatterplotUmapSettingsImpl","ChartRenderer","node","err","previousSettings","previousData","prevLayer","l","currentLayer","field","SCATTERPLOT_LASSO_EVENTS","event","prevSettings","arraysAreDifferent","v","idx","_a","_b","_c","_d","prevData","prevKeys","keys","key","x","y","label","highlight","grouping","layers","dotsExtents","hasCurve","layer","groupingKeysSet","dotsByGrouping","dots","labelFormatter","format","xv","yv","dimmed","dot","formatColumnValue","groupingKey","columnName","groupingKeys","a","b","sortDotsByGrouping","legendLabels","createLegendInfo","calculated","inheritedAes","usedAes","usedAesFromPalettes","addPalettesToAesMapping","id","chartSettings","keyColumn"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/scatterplot-umap/index.ts"],"sourcesContent":["import {format} from 'd3-format';\nimport { AbstractChart } from '../AbstractChart';\nimport type { DataFrame } from '../DataFrame';\nimport { addPalettesToAesMapping, createLegendInfo } from '../scatterplot/utils/createLegendInfo';\nimport {formatColumnValue} from '../scatterplot/utils/formatColumnValue';\nimport {sortDotsByGrouping} from '../scatterplot/utils/sortDotsByGrouping';\nimport type { AesItem, ContinuousAesFromColumn, InheritAesScatterplot, ScatterplotEventHandlers } from '../types';\nimport type { ScatterplotUmapLegendInfo, ScatterplotUmapSettings } from '../types/scatterplot-umap';\nimport {arraysAreDifferent} from '../utils/arraysAreDifferent';\nimport ChartRenderer from './ChartRenderer';\nimport { SCATTERPLOT_CONTROLS_EVENTS } from './constants';\nimport type { DotsLayer } from './SettingsImpl';\nimport { ScatterplotUmapSettingsImpl } from './SettingsImpl';\nimport type { Dot, DotsExtents, LassoControlsState, LassoMode, Polygon } from './types';\n\nfunction isInheritMapping<T extends (string | number)>(value:T | InheritAesScatterplot | ContinuousAesFromColumn<T>):value is InheritAesScatterplot {\n return typeof value === 'object' && 'type' in value && value.type === 'grouping';\n}\n\nexport class ChartScatterplotUmap extends AbstractChart {\n settings: ScatterplotUmapSettingsImpl;\n chartRenderer: ChartRenderer;\n\n onPolygonUpdate: (data: number[], polygons: Polygon[]) => void = () => undefined; // dots indexes from input data\n onTooltipHintSwitch: (v:boolean) => void = () => undefined;\n onLassoControlsStateUpdate: (v: LassoControlsState) => void = () => undefined;\n onZoomChange: (isZoomChanged: boolean) => void = () => undefined;\n\n calculatedData: {\n dots: Dot[],\n groupingKeys: string[],\n dotsByGrouping: Record<string, Dot[]>,\n dotsExtents: DotsExtents,\n legendLabels: ScatterplotUmapLegendInfo,\n } | null = null;\n\n constructor(data: DataFrame, settings: ScatterplotUmapSettings, eventHandlers?: ScatterplotEventHandlers) {\n super(data, settings);\n\n this.settings = new ScatterplotUmapSettingsImpl(settings);\n this.chartRenderer = new ChartRenderer();\n\n if (eventHandlers) {\n this.onPolygonUpdate = eventHandlers.onPolygonUpdate;\n this.onTooltipHintSwitch = eventHandlers.onTooltipHintSwitch;\n this.onLassoControlsStateUpdate = eventHandlers.onLassoControlsStateUpdate;\n this.onZoomChange = eventHandlers.onZoomChange;\n }\n }\n\n mount(node: HTMLElement) {\n try {\n this.chartRenderer.init(node);\n this._updateData();\n this._updateChart();\n this.hasError = false;\n } catch (err) {\n this.hasError = true;\n console.error(err);\n if (err instanceof Error) {\n this.chartRenderer.renderError(err.message as string);\n console.error(err);\n }\n }\n }\n\n unmount() {\n this.chartRenderer.clear();\n }\n\n updateSettingsAndData(data: DataFrame, settings: ScatterplotUmapSettings) {\n try {\n const previousSettings = this.settings;\n const previousData = this.data;\n this.settings = new ScatterplotUmapSettingsImpl(settings);\n this.data = data;\n if (\n this._needUpdateCalculatedDataBySettings(previousSettings, this.settings) ||\n this._needUpdateCalculatedDataByData(previousData, this.data)\n ) {\n this._updateData();\n } else {\n this._updateAesInData();\n }\n\n // for some reason it's not enough for size updating to do like with fillColor\n const prevLayer = previousSettings.layers.find(l => l.type === 'dots') as DotsLayer;\n const currentLayer = this.settings.layers.find(l => l.type === 'dots') as DotsLayer;\n if (prevLayer && currentLayer && prevLayer.aes.dotSize !== currentLayer.aes.dotSize\n && typeof prevLayer.aes.dotSize === 'number' && typeof currentLayer.aes.dotSize === 'number') {\n this.chartRenderer.updatePointSize();\n }\n this._updateChart();\n this.hasError = false;\n } catch (err) {\n this.hasError = true;\n if (err instanceof Error) {\n this.chartRenderer.renderError(err.message as string);\n console.error(err);\n }\n }\n }\n\n updateChartState(field: string, value: unknown) {\n if (field === 'polygon') {\n this.chartRenderer.polygons = value as Polygon[];\n this._updateChart();\n }\n if (field === SCATTERPLOT_CONTROLS_EVENTS.lassoDelete) {\n if (document) {\n const event = new CustomEvent(SCATTERPLOT_CONTROLS_EVENTS.lassoDelete);\n document.dispatchEvent(event);\n }}\n if (field === SCATTERPLOT_CONTROLS_EVENTS.lassoSelectMode) {\n if (document) {\n const event = new CustomEvent(SCATTERPLOT_CONTROLS_EVENTS.lassoSelectMode, {detail: value as LassoMode});\n document.dispatchEvent(event);\n }\n }\n if (field === SCATTERPLOT_CONTROLS_EVENTS.lassoForward) {\n if (document) {\n const event = new CustomEvent(SCATTERPLOT_CONTROLS_EVENTS.lassoForward);\n document.dispatchEvent(event);\n }\n }\n if (field === SCATTERPLOT_CONTROLS_EVENTS.lassoBack) {\n if (document) {\n const event = new CustomEvent(SCATTERPLOT_CONTROLS_EVENTS.lassoBack);\n document.dispatchEvent(event);\n }\n }\n if (field === SCATTERPLOT_CONTROLS_EVENTS.resetViewport) {\n this.chartRenderer.resetZoom(this.settings.chartSettings.xAxis, this.settings.chartSettings.yAxis, this.calculatedData?.dotsExtents);\n this.onZoomChange(false);\n }\n }\n\n export(): string {\n console.warn('export not implemented');\n return '';\n // this._updateChart();\n // return renderToString(this.chartRenderer.component);\n }\n\n _needUpdateCalculatedDataBySettings(prevSettings: ScatterplotUmapSettingsImpl, settings: ScatterplotUmapSettingsImpl) {\n return (\n arraysAreDifferent(\n prevSettings.grouping.map(v => v.columnName.value),\n settings.grouping.map(v => v.columnName.value),\n ) ||\n prevSettings.grouping.some((v, idx) => arraysAreDifferent(v.order, settings.grouping?.[idx].order)) ||\n prevSettings.layers.length !== settings.layers.length ||\n prevSettings.layers.some((l, idx) => l.type !== settings.layers[idx].type) ||\n (prevSettings.label?.value || settings.label?.value) && prevSettings.label?.value !== settings.label?.value\n );\n }\n\n _needUpdateCalculatedDataByData(prevData: DataFrame, data: DataFrame) {\n const prevKeys = Object.keys(prevData.data);\n const keys = Object.keys(data.data);\n return (\n prevData.id !== data.id ||\n prevKeys.length !== keys.length ||\n prevKeys.some(key => prevData.data[key].length !== data.data[key]?.length)\n );\n }\n\n _updateData() {\n const {x, y, label, highlight, grouping, layers} = this.settings;\n\n const dotsExtents = {\n minX: Infinity,\n maxX: -Infinity,\n minY: Infinity,\n maxY: -Infinity,\n };\n\n const hasCurve = layers.some(layer => layer.type === 'curve');\n const groupingKeysSet = new Set<string>();\n const dotsByGrouping:Record<string, Dot[]> = {};\n\n const dots: Dot[] = [];\n const labelFormatter = label?.format ? format(label.format) : undefined;\n\n for (let idx = 0; idx < this.data.rowsCount; idx++) {\n const xv = this.data.getColumnValue(x.value, idx);\n const yv = this.data.getColumnValue(y.value, idx);\n\n if (typeof xv !== 'number' || typeof yv !== 'number') {\n continue;\n }\n if (!isFinite(xv) || !isFinite(yv)) {\n continue;\n }\n\n if (xv < dotsExtents.minX) {\n dotsExtents.minX = xv;\n }\n if (xv > dotsExtents.maxX) {\n dotsExtents.maxX = xv;\n }\n if (yv < dotsExtents.minY) {\n dotsExtents.minY = yv;\n }\n if (yv > dotsExtents.maxY) {\n dotsExtents.maxY = yv;\n }\n\n const dimmed = highlight ? !this.data.getColumnValue(highlight.value, idx) : false;\n const dot: Dot = {\n x: xv,\n y: yv,\n idx,\n label: formatColumnValue(this.data, idx, label, labelFormatter),\n dimmed\n };\n if (hasCurve) {\n const groupingKey = grouping.map(({columnName}) => this.data.getColumnValue(columnName.value, idx)).join('_');\n groupingKeysSet.add(groupingKey);\n if (!dotsByGrouping[groupingKey]) {\n dotsByGrouping[groupingKey] = [];\n }\n dotsByGrouping[groupingKey].push(dot);\n }\n dots.push(dot);\n }\n\n const groupingKeys = [...groupingKeysSet];\n if (hasCurve) {\n groupingKeys.forEach(key => {\n dotsByGrouping[key].sort((a, b) => a.x - b.x);\n });\n }\n sortDotsByGrouping(this.data, dots, grouping, highlight);\n const legendLabels = createLegendInfo(this.data, grouping, layers);\n\n const prevDotExtents = this.calculatedData?.dotsExtents ?? null;\n if (prevDotExtents) {\n const {minX, maxX, minY, maxY} = prevDotExtents;\n if (minX !== dotsExtents.minX || maxX !== dotsExtents.maxX \n || minY !== dotsExtents.minY || maxY !== dotsExtents.maxY) {\n this.onZoomChange(true); // dots viewport is changed but it will not be changed automatically; this call is to undisable reset button\n }\n }\n this.calculatedData = {\n dots,\n dotsByGrouping,\n groupingKeys,\n dotsExtents,\n legendLabels,\n };\n }\n\n _updateAesInData() {\n const calculated = this.calculatedData;\n if (!calculated) {\n return;\n }\n const {layers, grouping} = this.settings;\n grouping.forEach(({columnName, inheritedAes}) => {\n const usedAes = new Set<keyof AesItem>();\n const usedAesFromPalettes:Partial<Record<keyof AesItem, string[]>> = {}; // if there is palette in mapping then\n layers.forEach(layer => {\n if (!layer.aes) return;\n \n Object.entries(layer.aes).forEach(([key, value]) => {\n if (!(isInheritMapping(value) && value.value === columnName.value)) return;\n usedAes.add(key as keyof AesItem);\n if (value.palette) {\n usedAesFromPalettes[key as keyof AesItem] = value.palette;\n }\n });\n });\n\n calculated.legendLabels[columnName.value].usedAes = [...usedAes];\n calculated.legendLabels[columnName.value].aesMap = addPalettesToAesMapping(columnName, usedAesFromPalettes, inheritedAes);\n });\n }\n\n _updateChart() {\n if (!this.calculatedData) {\n return;\n }\n const {id, chartSettings, keyColumn, layers, grouping} = this.settings;\n this.chartRenderer.render(\n this.data,\n id,\n chartSettings,\n keyColumn,\n this.calculatedData.dots,\n this.calculatedData.dotsExtents,\n this.calculatedData.dotsByGrouping,\n layers,\n this.calculatedData.legendLabels,\n grouping.map(v => v.columnName),\n this.onPolygonUpdate,\n this.onTooltipHintSwitch,\n this.onLassoControlsStateUpdate,\n this.onZoomChange\n );\n }\n}\n"],"names":["isInheritMapping","value","ChartScatterplotUmap","AbstractChart","data","settings","eventHandlers","__publicField","ScatterplotUmapSettingsImpl","ChartRenderer","node","err","previousSettings","previousData","prevLayer","l","currentLayer","field","SCATTERPLOT_CONTROLS_EVENTS","event","_a","prevSettings","arraysAreDifferent","v","idx","_b","_c","_d","prevData","prevKeys","keys","key","x","y","label","highlight","grouping","layers","dotsExtents","hasCurve","layer","groupingKeysSet","dotsByGrouping","dots","labelFormatter","format","xv","yv","dimmed","dot","formatColumnValue","groupingKey","columnName","groupingKeys","a","b","sortDotsByGrouping","legendLabels","createLegendInfo","prevDotExtents","minX","maxX","minY","maxY","calculated","inheritedAes","usedAes","usedAesFromPalettes","addPalettesToAesMapping","id","chartSettings","keyColumn"],"mappings":"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"}
@@ -458,6 +458,7 @@ export type ScatterplotEventHandlers = ChartEventHandlers<{
458
458
  onTooltipHintSwitch: (d: boolean) => void;
459
459
  onLassoStateChange: () => void;
460
460
  onLassoControlsStateUpdate: (v: LassoControlsState) => void;
461
+ onZoomChange: (isZoomChanged: boolean) => void;
461
462
  }>;
462
463
  export type HeatmapEventHandlers = ChartEventHandlers<{
463
464
  onTooltipHintSwitch: (d: boolean) => void;